• session0穿透-server降权打开程序


    有点累 随便写写

    在win7以后,win服务虽然是system的高权 但因为不在同一session的缘故,无法再可以控制桌面,包括显示ui,获取句柄,截图,弹窗等等。。

    这样我在做进程守护的时候就遇到了些问题,守护的程序出现执行却无反馈的情况,查了很多例子,需要CreateProcessAsUser来调动程序就可以解决,需要注意这个CreateProcessAsUser需要system权限,仅admin是不行的,虽然网上有例子说可以手动提升admin权限,但我在本地安全策略里添加了相关权限依旧不行。

    CreateProcessAsUser,打开程序之前需要一个令牌降权,有两种方法一个是获取用户的令牌

    dwSessionID = ::WTSGetActiveConsoleSessionId();//获取用户id
            if (FALSE == ::WTSQueryUserToken(dwSessionID,&hToken)//hToken获取到令牌
    {
        int i = GetLastError();//获取错误编码
    }

    另一种方法是通过获取其他程序的令牌,当然这种很有可能出现意外

    LPWSTR lpa = ConvertCharToLPWSTR(_T("EXPLORER.EXE"))
    GetTokenByName(hToken,lpa)
    BOOL   GetTokenByName(HANDLE   &hToken, LPWSTR   lpName)
    {
        if (!lpName)
        {
            return   FALSE;
        }
        HANDLE  hProcessSnap = NULL;
        BOOL  bRet = FALSE;
        PROCESSENTRY32   pe32 = { 0 };
        hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
        if (hProcessSnap == INVALID_HANDLE_VALUE)
            return   (FALSE);
    
        pe32.dwSize = sizeof(PROCESSENTRY32);
    
        if (Process32First(hProcessSnap, &pe32))
        {
            do
            {
                CString exefile = pe32.szExeFile;
                CString paraname = lpName;
                LPCSTR cname = wtoc(lpName).c_str;
                if (!exefile.CompareNoCase(cname))
                {
                    HANDLE   hProcess =
                        OpenProcess(PROCESS_QUERY_INFORMATION,
                            FALSE, pe32.th32ProcessID);
                    bRet = OpenProcessToken(hProcess, TOKEN_ALL_ACCESS, &hToken);
                    CloseHandle(hProcessSnap);
                    return   (bRet);
                }
            } while (Process32Next(hProcessSnap, &pe32));
            bRet = TRUE;
        }
        else
            bRet = FALSE;
    
        CloseHandle(hProcessSnap);
        return   (bRet);
    }

    我使用的是第一种方案,这里只写出降权call程序的代码,server的太多就不写了

    #include "pch.h"
    #include <UserEnv.h>
    #include <WtsApi32.h>
    //#include <afx.h>
    #include <tchar.h>
    #pragma comment(lib, "UserEnv.lib")
    #pragma comment(lib, "WtsApi32.lib")
    
    // 突破SESSION 0隔离创建用户进程  传入程序路径
    
    #define _AFXDLL
    
    BOOL CreateUserProcess(char *lpszFileName)
    {
        BOOL bRet = TRUE;
        DWORD dwSessionID = 0;
        HANDLE hToken = NULL;
        HANDLE hDuplicatedToken = NULL;
        LPVOID lpEnvironment = NULL;
        STARTUPINFO si = { 0 };
        PROCESS_INFORMATION pi = { 0 };
        si.cb = sizeof(si);
    
        do
        {
            // 获得当前Session ID
            dwSessionID = ::WTSGetActiveConsoleSessionId();
            LPCWSTR err = _T("ERROR");
            
    
    
            // 获得当前Session的用户令牌
            if (FALSE == ::WTSQueryUserToken(dwSessionID, &hToken))
            {    
                int i = GetLastError();
                //ShowMessage("WTSQueryUserToken", "ERROR");
                MessageBox(GetForegroundWindow(), err, _T("WTSQueryUserToken"), 1);
                bRet = FALSE;
                break;
            }
    
            // 复制令牌
            if (FALSE == ::DuplicateTokenEx(hToken, MAXIMUM_ALLOWED, NULL,
                SecurityIdentification, TokenPrimary, &hDuplicatedToken))
            {
                //ShowMessage("DuplicateTokenEx", "ERROR");
                MessageBox(GetForegroundWindow(), err, _T("DuplicateTokenEx"), 1);
                bRet = FALSE;
                break;
            }
    
            // 创建用户Session环境
            if (FALSE == ::CreateEnvironmentBlock(&lpEnvironment,
                hDuplicatedToken, FALSE))
            {
                //ShowMessage("CreateEnvironmentBlock", "ERROR");
                MessageBox(GetForegroundWindow(), err, _T("CreateEnvironmentBlock"), 1);
                bRet = FALSE;
                break;
            }
    
            
    
            // 在复制的用户Session下执行应用程序,创建进程
            if (FALSE == ::CreateProcessAsUser(hDuplicatedToken,
                lpszFileName, NULL, NULL, NULL, FALSE,
                NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE | CREATE_UNICODE_ENVIRONMENT,
                lpEnvironment, NULL, &si, &pi))
            {
                //ShowMessage("CreateProcessAsUser", "ERROR");
                MessageBox(GetForegroundWindow(), err, _T("CreateProcessAsUser"), 1);
                bRet = FALSE;
                break;
            }
    
        } while (FALSE);
        // 关闭句柄, 释放资源
        if (lpEnvironment)
        {
            ::DestroyEnvironmentBlock(lpEnvironment);
        }
        if (hDuplicatedToken)
        {
            ::CloseHandle(hDuplicatedToken);
        }
        if (hToken)
        {
            ::CloseHandle(hToken);
        }
        return bRet;
    }
    
    int main(int argc, char* argv[])
    
    {
        char a[] = "calc.exe";
        CreateUserProcess(a);
            return 0;
    }

    这个可能在编码上有点问题,应该难不道诸位的,最后感谢提供例子的朋友。

    累了睡了

    -----------------------------

    CreateUserProcess做成服务刚开机时,用户还未登陆系统,这时会索取不到令牌,会出错,原本跳过本次循环就可以了,但有MessageBox

    所以使用时一定要去除所有MessageBox 不然报错会弹窗 可弹窗又不显示,整个服务就卡住了。

    ----------------------------------------------

      1 #include <stdio.h>
      2 #include <Windows.h>
      3 #include <UserEnv.h>
      4 #include <WtsApi32.h>
      5 #pragma comment(lib, "UserEnv.lib")
      6 #pragma comment(lib, "WtsApi32.lib")
      7 
      8 #define SLEEP_TIME 5000 //间隔时间
      9 
     10 #define FILE_PATH "C:\log.txt" //信息输出文件
     11 
     12 bool brun = false;
     13 
     14 SERVICE_STATUS servicestatus;
     15 
     16 SERVICE_STATUS_HANDLE hstatus;
     17 
     18 //int WriteToLog(const char* str);
     19 
     20 void WINAPI ServiceMain(int argc, char** argv);
     21 
     22 void WINAPI CtrlHandler(DWORD request);
     23 
     24 static HANDLE hProcess = NULL;
     25 
     26 
     27 
     28 // 突破SESSION 0隔离创建用户进程  传入程序路径
     29 
     30 int WriteToLog(const char* str)
     31 
     32 {
     33 
     34     FILE* pfile;
     35 
     36     fopen_s(&pfile, FILE_PATH, "a+");
     37 
     38     if (pfile == NULL)
     39 
     40     {
     41 
     42         return -1;
     43 
     44     }
     45 
     46     fprintf_s(pfile, "%s
    ", str);
     47 
     48     fclose(pfile);
     49 
     50     return 0;
     51 
     52 }
     53 
     54 const char* itoa1(int val)
     55 {
     56     static char result[sizeof(int) << 3 + 2];
     57     unsigned int tempval = val;
     58     if (val < 0) tempval = -val;
     59     int i = sizeof(int) << 3 + 1;
     60     do {
     61         result[i] = "0123456789"[tempval % 10];
     62         tempval /= 10; --i;
     63     } while (tempval);
     64     if (val < 0) result[i--] = '-';
     65     return &result[i + 1];
     66 }
     67 
     68 HANDLE CreateUserProcess(char *lpszFileName)
     69 {
     70     BOOL bRet = TRUE;
     71     DWORD dwSessionID = 0;
     72     HANDLE hToken = NULL;
     73     HANDLE hDuplicatedToken = NULL;
     74     LPVOID lpEnvironment = NULL;
     75     STARTUPINFO si = { 0 };
     76     PROCESS_INFORMATION pi = { 0 };
     77     si.cb = sizeof(si);
     78 
     79     do
     80     {
     81         // 获得当前Session ID
     82         dwSessionID = ::WTSGetActiveConsoleSessionId();
     83         //LPCSTR err = _T("ERROR");
     84 
     85 
     86 
     87         WriteToLog("sessionS");
     88 
     89         // 获得当前Session的用户令牌
     90         if (FALSE == ::WTSQueryUserToken(dwSessionID, &hToken))
     91         {
     92             int i = GetLastError();
     93 
     94             WriteToLog("WTSQueryUserToken");
     95             WriteToLog(itoa1(i));
     96             bRet = FALSE;
     97             return NULL;
     98         }
     99 
    100         // 复制令牌
    101         if (FALSE == ::DuplicateTokenEx(hToken, MAXIMUM_ALLOWED, NULL,
    102             SecurityIdentification, TokenPrimary, &hDuplicatedToken))
    103         {
    104             int i = GetLastError();
    105 
    106             WriteToLog("DuplicateTokenEx");
    107             WriteToLog(itoa1(i));
    108             bRet = FALSE;
    109             return NULL;
    110         }
    111 
    112         // 创建用户Session环境
    113         if (FALSE == ::CreateEnvironmentBlock(&lpEnvironment,
    114             hDuplicatedToken, FALSE))
    115         {
    116             int i = GetLastError();
    117 
    118             WriteToLog("CreateEnvironmentBlock");
    119             WriteToLog(itoa1(i));
    120 
    121             bRet = FALSE;
    122             return NULL;
    123         }
    124 
    125     
    126         //L"calc.exe"
    127         // 在复制的用户Session下执行应用程序,创建进程
    128         if (FALSE == ::CreateProcessAsUser(hDuplicatedToken,
    129             lpszFileName, NULL, NULL, NULL, FALSE,
    130             NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE | CREATE_UNICODE_ENVIRONMENT,
    131             lpEnvironment, NULL, &si, &pi))
    132         {
    133             int i = GetLastError();
    134 
    135             WriteToLog("CreateProcessAsUser");
    136             WriteToLog(itoa1(i));
    137             
    138             bRet = FALSE;
    139             return NULL;
    140         }
    141         WriteToLog("sessionC");
    142 
    143     } while (FALSE);
    144     // 关闭句柄, 释放资源
    145     if (lpEnvironment)
    146     {
    147         ::DestroyEnvironmentBlock(lpEnvironment);
    148     }
    149     if (hDuplicatedToken)
    150     {
    151         ::CloseHandle(hDuplicatedToken);
    152     }
    153     if (hToken)
    154     {
    155         ::CloseHandle(hToken);
    156     }
    157     return pi.hProcess;
    158 }
    159 
    160 
    161 
    162 void WINAPI ServiceMain(int argc, char** argv)
    163 {
    164     WriteToLog("smain");
    165 
    166     servicestatus.dwServiceType = SERVICE_WIN32;
    167 
    168     servicestatus.dwCurrentState = SERVICE_START_PENDING;
    169 
    170     servicestatus.dwControlsAccepted = SERVICE_ACCEPT_SHUTDOWN | SERVICE_ACCEPT_STOP ;
    171 
    172     servicestatus.dwWin32ExitCode = 0;
    173 
    174     servicestatus.dwServiceSpecificExitCode = 0;
    175 
    176     servicestatus.dwCheckPoint = 0;
    177 
    178     servicestatus.dwWaitHint = 0;
    179 
    180     hstatus = ::RegisterServiceCtrlHandler("boot", CtrlHandler);
    181 
    182     if (hstatus == 0)
    183     {
    184         int i = GetLastError();
    185         WriteToLog(itoa1(i));
    186         WriteToLog("RegisterServiceCtrlHandler failed");
    187 
    188         return;
    189 
    190     }
    191 
    192     WriteToLog("RegisterServiceCtrlHandler success");
    193 
    194     //向SCM 报告运行状态
    195 
    196     servicestatus.dwCurrentState = SERVICE_RUNNING;
    197 
    198     if (!SetServiceStatus(hstatus, &servicestatus))
    199     {
    200         int i = GetLastError();
    201         WriteToLog(itoa1(i));
    202         WriteToLog("SetServiceStatus failed");
    203 
    204         return;
    205 
    206     }
    207 
    208     //在此处添加你自己希望服务做的工作,在这里我做的工作是获得当前可用的物理和虚拟内存信息
    209 
    210     brun = true;
    211 
    212     
    213 
    214     while (brun)
    215     {
    216         WriteToLog("while1");
    217 
    218 
    219         //循环开启
    220         
    221         
    222         char a[] = "C:\Windows\1.exe";
    223         hProcess = CreateUserProcess(a);
    224         
    225 
    226         WaitForSingleObject(hProcess, INFINITE);
    227         CloseHandle(hProcess);
    228         hProcess = NULL;
    229 
    230 
    231         Sleep(SLEEP_TIME);
    232 
    233 
    234     }
    235 
    236     WriteToLog("service stopped");
    237 
    238 }
    239 
    240 void WINAPI CtrlHandler(DWORD request)
    241 {
    242     // 停止服务
    243     switch (request)
    244     {
    245     case SERVICE_CONTROL_STOP:
    246 
    247         brun = false;
    248 
    249         servicestatus.dwCurrentState = SERVICE_STOPPED;
    250 
    251         break;
    252 
    253     case SERVICE_CONTROL_SHUTDOWN:
    254 
    255         brun = false;
    256 
    257         servicestatus.dwCurrentState = SERVICE_STOPPED;
    258 
    259         break;
    260 
    261     default:
    262 
    263         break;
    264 
    265     }
    266 
    267     SetServiceStatus(hstatus, &servicestatus);
    268 }
    269 
    270 int main()
    271 {
    272 
    273 
    274     SERVICE_TABLE_ENTRY entrytable[2];
    275 
    276     const char* constc = "boot";
    277 
    278     char* c = nullptr;
    279 
    280     c = const_cast<char*>(constc);
    281 
    282 
    283     entrytable[0].lpServiceName = c;
    284 
    285     entrytable[0].lpServiceProc = (LPSERVICE_MAIN_FUNCTION)ServiceMain;
    286 
    287     entrytable[1].lpServiceName = NULL;
    288 
    289     entrytable[1].lpServiceProc = NULL;
    290 
    291     StartServiceCtrlDispatcher(entrytable);
    292     return 0;
    293 
    294 }
  • 相关阅读:
    iOS,Layer
    iOS 手势冲突
    ECharts
    手动安装Package Control
    webstorm配置svn详解
    js 对象 类型转换
    google 跨域解决办法
    关于内层DIV设置margin-top不起作用的解决方案
    图片与文字在div里实现垂直水平都居中
    css3之3D翻牌效果
  • 原文地址:https://www.cnblogs.com/moshuixiong/p/12169281.html
Copyright © 2020-2023  润新知