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 
#include 
//#include 
#include 
#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 
  2 #include 
  3 #include 
  4 #include 
  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\n", 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 }

你可能感兴趣的:(session0穿透-server降权打开程序)