有点累 随便写写
在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; }
这个可能在编码上有点问题,应该难不道诸位的,最后感谢提供例子的朋友。
累了睡了