有关Windows Token的一些坑

Ⅰ:前言

​ 当我们需要从运行在Session 0的服务进程创建一个具有管理员权限,且运行在登录用户Session的进程时,一般的流程代码应该如:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
std::tuple<HANDLE, uint32_t> CreateSessionProcess(uint32_t sessionID, const std::wstring& cmd)
{
    // 获取特定session的用户token
    HANDLE userToken = nullptr;
	if (!WTSQueryUserToken(sessionID, &userToken))
	{
		return {};
	}

    // 获取linked token
    TOKEN_LINKED_TOKEN adminTokenInfo = { 0 };
	DWORD infoLen = sizeof(adminTokenInfo);
	if (!GetTokenInformation(userToken, TokenLinkedToken, &adminTokenInfo, sizeof(TOKEN_LINKED_TOKEN), &infoLen))
	{
		CloseHandle(userToken);
		return {};
	}
    
    //
    // ...做一些其他操作
    //
    
    // 使用Token创建进程
    CreateProcessAsUser(...)
}

​ 这流程看起来很普通,但是暗藏几个细节坑,下面将详细解释

Ⅱ:驱动保护与WTSQueryUserToken

Ⅲ:系统UAC与GetTokenInformation

Ⅳ:后话