有没有办法为另一个进程设置令牌?

时间:2011-02-28 12:31:19

标签: c++ windows multithreading winapi token

有SetThreadToken()函数,但没有“SetProcessToken()”这样的函数。

有没有办法为另一个进程设置令牌?如何写“SetProcessToken()”?

3 个答案:

答案 0 :(得分:7)

是的,您可以使用未记录的NtSetInformationProcess函数,但是一旦进程开始运行,进程令牌就会被锁定,无法再进行修改。因此,您必须使用CREATE_SUSPENDED创建标志启动流程,设置流程令牌,然后使用ResumeThread()恢复流程。为了设置进程令牌,调用者必须拥有并启用SeAssignPrimaryTokenPrivilege权限。

以下代码应该足够了:

// A few required typedefs

typedef enum _PROCESS_INFORMATION_CLASS
{
    ProcessBasicInformation,
    ProcessQuotaLimits,
    ProcessIoCounters,
    ProcessVmCounters,
    ProcessTimes,
    ProcessBasePriority,
    ProcessRaisePriority,
    ProcessDebugPort,
    ProcessExceptionPort,
    ProcessAccessToken,
    ProcessLdtInformation,
    ProcessLdtSize,
    ProcessDefaultHardErrorMode,
    ProcessIoPortHandlers,
    ProcessPooledUsageAndLimits,
    ProcessWorkingSetWatch,
    ProcessUserModeIOPL,
    ProcessEnableAlignmentFaultFixup,
    ProcessPriorityClass,
    ProcessWx86Information,
    ProcessHandleCount,
    ProcessAffinityMask,
    ProcessPriorityBoost,
    MaxProcessInfoClass
} PROCESS_INFORMATION_CLASS, *PPROCESS_INFORMATION_CLASS;

typedef struct _PROCESS_ACCESS_TOKEN
{
    HANDLE Token;
    HANDLE Thread;
} PROCESS_ACCESS_TOKEN, *PPROCESS_ACCESS_TOKEN;

typedef NTSTATUS (NTAPI * NtSetInformationProcess) (HANDLE processHandle, PROCESS_INFORMATION_CLASS infoClass, PVOID info, ULONG infoLength);


// Assume we have a handle to an existing process: targetProcessHandle, started in a suspended state, and a new token: newToken to assign to this process.

// First we must enable SeAssignPrimaryTokenPrivilege.
// Note: The user under which this runs must already hold the privilege, this only enables it (it is initially disabled by default).
LUID luid;
LookupPrivilegeValue(0, SE_ASSIGNPRIMARYTOKEN_NAME, &luid);
TOKEN_PRIVILEGES privs;
privs.PrivilegeCount = 1;
privs.Privileges[0].Luid = luid;
privs.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;

HANDLE myToken;
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &myToken))
{
    wprintf("Unable to open own process token to enable permissions\n");
    return FALSE;
}
if (!AdjustTokenPrivileges(myToken, FALSE, &privs, sizeof(TOKEN_PRIVILEGES), 0, 0))
{
    wprintf("Error setting token privileges: 0x%08x\n", GetLastError());
    CloseHandle(myToken);
    return FALSE;
}
// Even if AdjustTokenPrivileges returns TRUE, it may not have succeeded, check last error top confirm
if (GetLastError() == ERROR_NOT_ALL_ASSIGNED)
{
    wprintf("Unable to enable a required privilege\n");
    CloseHandle(myToken);
    return FALSE;
}
CloseHandle(myToken);

PROCESS_ACCESS_TOKEN tokenInfo;
tokenInfo.Token = newToken;
tokenInfo.Thread = 0;

// Get a handle to ntdll
HMODULE ntdll = LoadLibrary(L"ntdll.dll");

// And a pointer to the NtSetInformationProcess function
NtSetInformationProcess setInfo = (NtSetInformationProcess)GetProcAddress(ntdll,"NtSetInformationProcess");
NTSTATUS setInfoResult = setInfo(targetProcessHandle, ProcessAccessToken, &tokenInfo, sizeof(PROCESS_ACCESS_TOKEN));
if (setInfoResult < 0)
{
    wprintf(L"Error setting token: 0x%08x\n", setInfoResult);
    return FALSE;
}

FreeLibrary(ntdll);

// You can now resume the target process' main thread here using ResumeThread().

return TRUE;

答案 1 :(得分:3)

是。通过OpenProcessToken()获取一个令牌,使用DuplicateTokenEx()复制令牌,使用SetTokenInformation()设置重复令牌,然后使用此令牌创建一个新进程CreateProcessAsUser() < / p>

您需要SeTcbPrivilegeSeAssignPrimaryTokenPrivilegeSeIncreaseQuotaPrivilege

答案 2 :(得分:1)

进程只有一个安全令牌,即主要安全令牌,它是用户安全令牌的副本。

线程有第二个安全令牌,即模拟令牌。进程没有这些,只有线程。您无法使进程模拟其他用户的安全令牌。