一、
服务程序,要同桌面程序交换,程序属性必须设置:SERVICE_INTERACTIVE_PROCESS
SC_HANDLE hService = ::CreateService( hSCM, szServiceName, szServiceName, SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS|SERVICE_INTERACTIVE_PROCESS,// SERVICE_AUTO_START, SERVICE_ERROR_NORMAL,//SERVICE_DEMAND_START szFilePath, NULL, NULL, _T(""), NULL, NULL);
设置钩子:
hHook = ::SetWindowsHookEx(WH_GETMESSAGE,HookGetMsgProc,hInst,dwThreadID);
dwThreadID为0 设置全局钩子。
这种情况下是没有任何权限问题的,但是一旦你想注入指定的进程设置线程钩子,这个时候就会出现拒绝访问 的权限问题了,以我的程序为例:服务程序调用CreateProcess启动一个控制台程序,再由控制台程序来挂钩:
if(!::CreateProcess(NULL,cFilePath, NULL, NULL, FALSE, 0, NULL, NULL, &sInfo, &pInfo))
因为服务程序是执行的SYSTEM权限,由SYSTEM调用CreateProcess启动的控制台程序权限也是继承的服务程序的权限,所以也是SYSTEM权限
而桌面的程序都是用的Administrator权限,所以对桌面程序挂钩会访问失败(至于为什么全局钩子可以,这个没有去了解,待研究),所以,我就用了
explorer.exe进程的权限去启动控制台程序 CreateProcessAsUser:
//枚举进程 DWORD Process(BOOL bExit) { DWORD lpidprocesses[1024],cbneeded,cprocesses; HANDLE hprocess,hExplorer = NULL; HMODULE hmodule; TCHAR normalname[MAX_PATH]=_T("UnknownProcess"); BOOL bMonitor = FALSE; if(!EnumProcesses(lpidprocesses,sizeof(lpidprocesses),&cbneeded)) { OutputDebugString(_T("EnumProcesses Error\n")); return -1; } cprocesses=cbneeded/sizeof(DWORD); // for(UINT i=0;i<cprocesses;i++) { hprocess=OpenProcess(PROCESS_ALL_ACCESS,FALSE,lpidprocesses[i]); if(hprocess) { if(EnumProcessModules(hprocess,&hmodule,sizeof(hmodule),&cbneeded)) { GetModuleBaseName(hprocess,hmodule,normalname,sizeof(normalname)); if(_tcsicmp(normalname,szProcessname[0]) == 0) { bMonitor = TRUE; dwMonitorProcessId = lpidprocesses[i]; } else if (_tcsicmp(normalname,szProcessname[1]) == 0) { hExplorer = hprocess; } } } } //启动ABMonitor if (bMonitor == FALSE) { dwMonitorProcessId = 0; TCHAR szFilePath[MAX_PATH] = {0}; TCHAR cFilePath[MAX_PATH] = {0}; GetAppPath(szFilePath); _tcscpy(cFilePath,_T("\"")); _tcscat(cFilePath,szFilePath); _tcscat(cFilePath,_T("ABMonitor.exe\"")); //清空结构 STARTUPINFO sInfo; PROCESS_INFORMATION pInfo; ZeroMemory(&sInfo,sizeof(sInfo)); sInfo.cb=sizeof(sInfo); sInfo.dwFlags=STARTF_USESHOWWINDOW; sInfo.wShowWindow=SW_SHOWNORMAL; ZeroMemory(&pInfo,sizeof(pInfo)); ////////////////////////////////////////////////////////////////////////// //用桌面账户启动ABMonitor,以Administrator身份,否则SYSTEM权限无法挂钩线程钩子 //只能设置全局钩子 if (hExplorer != NULL) { HANDLE hToken = NULL,hNewToken = NULL; if (OpenProcessToken(hExplorer,MAXIMUM_ALLOWED, &hToken)) { if (DuplicateTokenEx(hToken, MAXIMUM_ALLOWED, NULL,SecurityImpersonation, TokenPrimary, &hNewToken)) { BOOL bRet = CreateProcessAsUser(hNewToken, NULL,cFilePath, NULL, NULL, FALSE,0, NULL, NULL, &sInfo, &pInfo); if(!bRet) { return -1; } CloseHandle(hNewToken); } CloseHandle(hToken); } } } CloseHandle(hprocess); return 0; }
这样就可以控制台程序执行的就是Administrator权限了,SetWindowsHookEx 也可以正常执行了……