您的位置:首页 > 其它

windows服务程序中创建用户进程

2015-11-30 17:11 393 查看
最近碰到个问题, 需要在服务中检测用户桌面的情况。但是服务程序都是SYSTEM账户下运行, 属于Session0, 不能检测到用户桌面的情况。所以就需要另启一个用户进程来获取这些信息, 然后发送给服务。所以就用到了 CreateProcessAsUser来创建用户进程。

#include <Windows.h>
#include <iostream>
#include <fstream>
#include <Wtsapi32.h>
#include <TlHelp32.h>
#pragma comment(lib, "wtsapi32.lib")
#include <Userenv.h>
#pragma comment(lib,"userenv.lib")
using namespace std;

typedef struct _TOKEN_LINKED_TOKEN {
HANDLE LinkedToken;
} TOKEN_LINKED_TOKEN, *PTOKEN_LINKED_TOKEN;
SERVICE_STATUS_HANDLE hServiceStatus;
SERVICE_STATUS ServiceStatus;

DWORD GetActiveSessionID()
{

DWORD dwSessionId = 0;
PWTS_SESSION_INFO pSessionInfo = NULL;
DWORD dwCount = 0;

WTSEnumerateSessions(WTS_CURRENT_SERVER_HANDLE, 0, 1, &pSessionInfo, &dwCount);

for(DWORD i = 0; i < dwCount; i++)
{
WTS_SESSION_INFO si = pSessionInfo[i];
if(WTSActive == si.State)
{
dwSessionId = si.SessionId;
break;
}
}

WTSFreeMemory(pSessionInfo);
return dwSessionId;

}

BOOL ServiceExecute(std::wstring wstrCmdLine, INT32& n32ExitResult)
{
ofstream ofile("C:\\logEvent.txt");
ofile<<"start excute"<<std::endl;
DWORD dwProcesses = 0;
BOOL bResult = FALSE;

DWORD dwSid = GetActiveSessionID();

DWORD dwRet = 0;
PROCESS_INFORMATION pi;
STARTUPINFO si;
HANDLE hProcess = NULL, hPToken = NULL, hUserTokenDup = NULL;
if (!WTSQueryUserToken(dwSid, &hPToken))
{
ofile<<"get token error 1"<<std::endl;
PROCESSENTRY32 procEntry;
DWORD dwPid = 0;
HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hSnap == INVALID_HANDLE_VALUE)
{
return FALSE;
}

procEntry.dwSize = sizeof(PROCESSENTRY32);
if (Process32First(hSnap, &procEntry))
{
do
{
if (_tcsicmp(procEntry.szExeFile, _T("explorer.exe")) == 0)
{
DWORD exeSessionId = 0;
if (ProcessIdToSessionId(procEntry.th32ProcessID, &exeSessionId) && exeSessionId == dwSid)
{
dwPid = procEntry.th32ProcessID;
break;
}
}

} while (Process32Next(hSnap, &procEntry));
}
CloseHandle(hSnap);

// explorer进程不存在
if (dwPid == 0)
{
return FALSE;
}

hProcess = ::OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, dwPid);
if (hProcess == NULL)
{
return FALSE;
}

if(!::OpenProcessToken(hProcess, TOKEN_ALL_ACCESS_P,&hPToken))
{
CloseHandle(hProcess);
return FALSE;
}
}

if (hPToken == NULL)
return FALSE;

TOKEN_LINKED_TOKEN admin;
bResult = GetTokenInformation(hPToken, (TOKEN_INFORMATION_CLASS)19, &admin, sizeof(TOKEN_LINKED_TOKEN), &dwRet);

if (!bResult) // vista 以前版本不支持TokenLinkedToken
{
ofile<<"Get token info error" <<std::endl;
TOKEN_PRIVILEGES tp;
LUID luid;
if (LookupPrivilegeValue(NULL,SE_DEBUG_NAME,&luid))
{
tp.PrivilegeCount =1;
tp.Privileges[0].Luid =luid;
tp.Privileges[0].Attributes =SE_PRIVILEGE_ENABLED;
}
DuplicateTokenEx(hPToken,MAXIMUM_ALLOWED,NULL,SecurityIdentification,TokenPrimary,&hUserTokenDup);
}
else
{
hUserTokenDup = admin.LinkedToken;
ofile<<"token: "<<hUserTokenDup<<std::endl;
}

LPVOID pEnv =NULL;
DWORD dwCreationFlags = CREATE_PRESERVE_CODE_AUTHZ_LEVEL;

if(CreateEnvironmentBlock(&pEnv,hUserTokenDup,TRUE))
{
dwCreationFlags|=CREATE_UNICODE_ENVIRONMENT;
}
else
{
pEnv = NULL;
}

ZeroMemory( &si, sizeof(si) );
si.cb = sizeof(si);
si.dwFlags = STARTF_USESHOWWINDOW;
si.wShowWindow = SW_SHOWNORMAL;
ZeroMemory( &pi, sizeof(pi) );

bResult = CreateProcessAsUser(
hUserTokenDup, // client's access token
NULL, // file to execute
(LPTSTR) wstrCmdLine.c_str(), // command line
NULL, // pointer to process SECURITY_ATTRIBUTES
NULL, // pointer to thread SECURITY_ATTRIBUTES
FALSE, // handles are not inheritable
dwCreationFlags, // creation flags
pEnv, // pointer to new environment block
NULL, // name of current directory
&si, // pointer to STARTUPINFO structure
&pi // receives information about new process
);

if(pi.hProcess)
{
if(WAIT_OBJECT_0 == WaitForSingleObject(pi.hProcess, 180000))
{
DWORD dwResult = 0;
if(GetExitCodeProcess(pi.hProcess, &dwResult))
{
n32ExitResult = dwResult;
}
else
{
n32ExitResult = -1;
}

CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
}
else
{
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
n32ExitResult = -1;
}
}

if (hUserTokenDup != NULL)
CloseHandle(hUserTokenDup);
if (hProcess != NULL)
CloseHandle(hProcess);
if (hPToken != NULL)
CloseHandle(hPToken);
if (pEnv != NULL)
DestroyEnvironmentBlock(pEnv);

return TRUE;

}

void CreateProcess2()
{
HANDLE hTokenThis = NULL;
HANDLE hTokenDup = NULL;
HANDLE hThisProcess = GetCurrentProcess();
BOOL bResult = FALSE;
bResult = OpenProcessToken(hThisProcess, TOKEN_ALL_ACCESS, &hTokenThis);
if(!bResult)
{
printf("OpenProcessToken Failed! Error = 0x%08lx\n", GetLastError());
return;
}

bResult = DuplicateTokenEx(hTokenThis, MAXIMUM_ALLOWED, NULL, SecurityIdentification, TokenPrimary, &hTokenDup);
if(!bResult)
{
printf("DuplicateTokenEx Failed! Error = 0x%08lx\n", GetLastError());
return;
}

DWORD dwSessionId = WTSGetActiveConsoleSessionId();
bResult = SetTokenInformation(hTokenDup, TokenSessionId, &dwSessionId, sizeof(DWORD));
if(!bResult)
{
printf("SetTokenInformation Failed! Error = 0x%08lx\n", GetLastError());
return;
}

STARTUPINFO si;
PROCESS_INFORMATION pi;
ZeroMemory(&si, sizeof(STARTUPINFO));
ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));
si.cb = sizeof(STARTUPINFO);
//si.lpDesktop = "WinSta0\\Default";

si.dwFlags = STARTF_USESHOWWINDOW;
si.wShowWindow = SW_SHOWNORMAL;

LPVOID pEnv = NULL;
DWORD dwCreationFlag = NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE | CREATE_UNICODE_ENVIRONMENT;

bResult = CreateEnvironmentBlock(&pEnv, hTokenDup, FALSE);
if(!bResult)
{
printf("CreateEnvironmentBlock Failed! Error = 0x%08lx\n", GetLastError());
return;
}

TCHAR szApp[MAX_PATH] = _T("notepad.exe");
bResult = CreateProcessAsUser(hTokenDup, NULL, szApp, NULL, NULL, FALSE, dwCreationFlag, pEnv, NULL, &si, &pi);
if(!bResult)
{
return;
}
}

void WINAPI ServiceMain(DWORD argc, char**argv)
{
ServiceStatus.dwCurrentState=SERVICE_START_PENDING;
ServiceStatus.dwControlsAccepted=SERVICE_ACCEPT_STOP;

//注册服务控制函数
//hServiceStatus=RegisterServiceCtrlHandler(L"ATestService",ServiceStrl);
//if(!hServiceStatus)
//{
// MessageBox(NULL,"注册控制服务失败!","",MB_OK);
// return;
//}

//设置服务状态
SetServiceStatus(hServiceStatus,&ServiceStatus);

ServiceStatus.dwWin32ExitCode=S_OK;
ServiceStatus.dwCheckPoint=0;
ServiceStatus.dwWaitHint=0;
ServiceStatus.dwCurrentState=SERVICE_RUNNING;
SetServiceStatus(hServiceStatus,&ServiceStatus);

//服务任务部分
ofstream ofile("C:\\logEvent.txt");
ofile<<"Service Start"<<std::endl;

while(1)
{
ofile<<"run...open process as user"<<std::endl;
ofile.close();
wchar_t buf[MAX_PATH] = L"notepad.exe";
int ret = 0;
//ServiceExecute(L"notepad.exe", ret);
CreateProcess2();
break;
}

//退出服务
ServiceStatus.dwCurrentState=SERVICE_STOPPED;
SetServiceStatus(hServiceStatus,&ServiceStatus);
}
int _tmain(int argc, _TCHAR* argv[])
{
DWORD nRet = 0;

SECURITY_ATTRIBUTES SecAttr;
SECURITY_DESCRIPTOR SecDesc;
SecAttr.nLength = sizeof(SecAttr);
SecAttr.bInheritHandle = FALSE;
SecAttr.lpSecurityDescriptor = &SecDesc;
InitializeSecurityDescriptor(&SecDesc, SECURITY_DESCRIPTOR_REVISION);
SetSecurityDescriptorDacl(&SecDesc, TRUE, 0, FALSE);
HANDLE hTest = CreateEvent(&SecAttr,TRUE,FALSE,L"Global\\Service_Test_Handle");

HANDLE hClientTest = CreateEvent(NULL,TRUE,FALSE,L"Global\\User_Test_Handle");

DWORD dwLastError = GetLastError();
if (hClientTest && ERROR_ALREADY_EXISTS == dwLastError)
{
ofstream ofile("C:\\logHandle.txt");
ofile<<"open user handle ok"<<std::endl;
ofile.close();
}
ofstream ofile("C:\\logHandle.txt");
ofile<<"GetLastError: "<<dwLastError<<std::endl;
ofile.close();

SERVICE_TABLE_ENTRY dispatchTable[] =
{
{ L"ATestService", (LPSERVICE_MAIN_FUNCTION)ServiceMain},
{NULL, NULL}
};

// Call the service control dispatcher with our entry table
if (!StartServiceCtrlDispatcher(dispatchTable))
{
return GetLastError();
}
return 0;
}

ServiceExecute比CreateProcess2的实现更加完善, 实际运行中用ServiceExecute更好。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: