无论我设置什么权限,我都会从 CreateProcessAsUserW 收到错误 1314,根据 MSDN,我应该添加SE_INCREASE_QUOTA_NAME和SE_ASSIGNPRIMARYTOKEN_NAME。
只是为了确保,我在组策略控制台中验证了权限确实被添加了。
LSA_OBJECT_ATTRIBUTES ObjectAttributes;
WCHAR* SystemName = &strSessionUserName[0];
USHORT SystemNameLength;
LSA_UNICODE_STRING lusSystemName;
NTSTATUS ntsResult;
LSA_HANDLE lsahPolicyHandle;
// Object attributes are reserved, so initialize to zeros.
ZeroMemory(&ObjectAttributes, sizeof(ObjectAttributes));
//Initialize an LSA_UNICODE_STRING to the server name.
SystemNameLength = (USHORT)wcslen(SystemName);
lusSystemName.Buffer = SystemName;
lusSystemName.Length = SystemNameLength * sizeof(WCHAR);
lusSystemName.MaximumLength = (SystemNameLength + 1) * sizeof(WCHAR);
// Get a handle to the Policy object.
ntsResult = LsaOpenPolicy(
nullptr, //Name of the target system.
&ObjectAttributes, //Object attributes.
0x000f0fff, //Desired access permissions.
&lsahPolicyHandle //Receives the policy handle.
);
PSID pSid;
if (false == ConvertStringSidToSid(strSid.data(), &pSid))
return false;
WCHAR* pQuotaName = L"SeIncreaseQuotaPrivilege";
LSA_UNICODE_STRING Privilege[1];
size_t stQuotaLength = wcslen(pQuotaName);
Privilege[0].Buffer = pQuotaName;
Privilege[0].Length = (USHORT)(stQuotaLength*sizeof(WCHAR));
Privilege[0].MaximumLength = (USHORT)(stQuotaLength + 1)*sizeof(WCHAR);
ntsResult = LsaAddAccountRights(lsahPolicyHandle, pSid, Privilege, 1);
if (!LookupPrivilegeValue(
NULL, // lookup privilege on local system
L"SeIncreaseQuotaPrivilege", // privilege to lookup
&luid)) // receives LUID of privilege
{
printf("LookupPrivilegeValue error: %u\n", GetLastError());
return FALSE;
}
tp.PrivilegeCount = 1;
tp.Privileges[0].Luid = luid;
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
if (!AdjustTokenPrivileges(
hToken,
FALSE,
&tp,
sizeof(TOKEN_PRIVILEGES),
(PTOKEN_PRIVILEGES)NULL,
(PDWORD)NULL))
{
printf("AdjustTokenPrivileges error: %u\n", GetLastError());
return FALSE;
}
WCHAR* pAssignToken = L"SeAssignPrimaryTokenPrivilege";
size_t stAssignToken = wcslen(pAssignToken);
Privilege[0].Buffer = pAssignToken;
Privilege[0].Length = (USHORT)(stAssignToken*sizeof(WCHAR));
Privilege[0].MaximumLength = (USHORT)(stAssignToken + 1)*sizeof(WCHAR);
ntsResult = LsaAddAccountRights(lsahPolicyHandle, pSid, Privilege, 1);
if (!LookupPrivilegeValue(
NULL, // lookup privilege on local system
L"SeAssignPrimaryTokenPrivilege", // privilege to lookup
&luid)) // receives LUID of privilege
{
printf("LookupPrivilegeValue error: %u\n", GetLastError());
return FALSE;
}
tp.PrivilegeCount = 1;
tp.Privileges[0].Luid = luid;
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
if (!AdjustTokenPrivileges(
hToken,
FALSE,
&tp,
sizeof(TOKEN_PRIVILEGES),
(PTOKEN_PRIVILEGES)NULL,
(PDWORD)NULL))
{
printf("AdjustTokenPrivileges error: %u\n", GetLastError());
return FALSE;
}
WCHAR* pTcbName = L"SeTcbPrivilege";
size_t stTcbName = wcslen(pTcbName);
Privilege[0].Buffer = pTcbName;
Privilege[0].Length = (USHORT)(stTcbName*sizeof(WCHAR));
Privilege[0].MaximumLength = (USHORT)(stTcbName + 1)*sizeof(WCHAR);
ntsResult = LsaAddAccountRights(lsahPolicyHandle, pSid, Privilege, 1);
if (!LookupPrivilegeValue(
NULL, // lookup privilege on local system
L"SeTcbPrivilege", // privilege to lookup
&luid)) // receives LUID of privilege
{
printf("LookupPrivilegeValue error: %u\n", GetLastError());
return FALSE;
}
tp.PrivilegeCount = 1;
tp.Privileges[0].Luid = luid;
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
if (!AdjustTokenPrivileges(
hToken,
FALSE,
&tp,
sizeof(TOKEN_PRIVILEGES),
(PTOKEN_PRIVILEGES)NULL,
(PDWORD)NULL))
{
printf("AdjustTokenPrivileges error: %u\n", GetLastError());
return FALSE;
}
si.cb = sizeof(STARTUPINFO);
if (FALSE == CreateProcessAsUserW(hToken, nullptr, L"notepad.exe", nullptr, nullptr, false, CREATE_SUSPENDED | CREATE_BREAKAWAY_FROM_JOB, nullptr, nullptr, &si, &pi))
{
return false;
}
我使用以下标志从目标用户检索令牌:
TOKEN_QUERY | TOKEN_DUPLICATE | TOKEN_IMPERSONATE | TOKEN_ASSIGN_PRIMARY
使用CreateProcessWithToken / CreateProcessWithLogon是有问题的,因为 CreateProcessWithToken 会启动一个新作业,这会扰乱目标进程的初始化,并且 CreateProcessWithLogon 需要密码,在运行时是未知的。