Files
wufuc/src/wufuc/hlpsvc.c

207 lines
6.8 KiB
C

#include "stdafx.h"
#include "hlpmisc.h"
#include "hlpsvc.h"
LPQUERY_SERVICE_CONFIGW QueryServiceConfigByNameAlloc(
SC_HANDLE hSCM,
const wchar_t *pServiceName,
LPDWORD pcbBufSize)
{
SC_HANDLE hService;
LPQUERY_SERVICE_CONFIGW result = NULL;
hService = OpenServiceW(hSCM, pServiceName, SERVICE_QUERY_CONFIG);
if ( !hService ) return result;
result = QueryServiceConfigAlloc(hSCM, hService, pcbBufSize);
CloseServiceHandle(hService);
return result;
}
LPQUERY_SERVICE_CONFIGW QueryServiceConfigAlloc(
SC_HANDLE hSCM,
SC_HANDLE hService,
LPDWORD pcbBufSize)
{
DWORD cbBytesNeeded;
LPQUERY_SERVICE_CONFIGW result = NULL;
if ( !QueryServiceConfigW(hService, NULL, 0, &cbBytesNeeded)
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER ) {
result = malloc(cbBytesNeeded);
if ( result ) {
if ( QueryServiceConfigW(hService, result, cbBytesNeeded, &cbBytesNeeded) ) {
if ( pcbBufSize )
*pcbBufSize = cbBytesNeeded;
} else {
free(result);
result = NULL;
}
}
}
return result;
}
bool QueryServiceStatusProcessInfoByName(
SC_HANDLE hSCM,
const wchar_t *pServiceName,
LPSERVICE_STATUS_PROCESS pServiceStatus)
{
bool result = false;
SC_HANDLE hService;
DWORD cbBytesNeeded;
hService = OpenServiceW(hSCM, pServiceName, SERVICE_QUERY_STATUS);
if ( !hService )
return result;
result = !!QueryServiceStatusEx(hService,
SC_STATUS_PROCESS_INFO,
(LPBYTE)pServiceStatus,
sizeof *pServiceStatus,
&cbBytesNeeded);
CloseServiceHandle(hService);
return result;
}
bool QueryServiceGroupName(const LPQUERY_SERVICE_CONFIGW pServiceConfig, LPWSTR *pGroupName, HLOCAL *hMem)
{
bool result = false;
int NumArgs;
LPWSTR *argv;
argv = CommandLineToArgvW(pServiceConfig->lpBinaryPathName, &NumArgs);
if ( argv ) {
if ( !_wcsicmp(PathFindFileNameW(argv[0]), L"svchost.exe") ) {
for ( int i = 1; (i + 1) < NumArgs; i++ ) {
if ( !_wcsicmp(argv[i], L"-k") ) {
*pGroupName = argv[++i];
*hMem = (HLOCAL)argv;
return true;
}
}
}
LocalFree((HLOCAL)argv);
}
return false;
}
DWORD QueryServiceProcessId(SC_HANDLE hSCM, SC_HANDLE hService)
{
DWORD result = 0;
SERVICE_STATUS_PROCESS ServiceStatus;
DWORD cbBytesNeeded;
if ( QueryServiceStatusEx(hService,
SC_STATUS_PROCESS_INFO,
(LPBYTE)&ServiceStatus,
sizeof ServiceStatus,
&cbBytesNeeded) ) {
result = ServiceStatus.dwProcessId;
}
return result;
}
DWORD QueryServiceProcessIdByName(SC_HANDLE hSCM, const wchar_t *pServiceName)
{
SERVICE_STATUS_PROCESS ServiceStatusProcess;
if ( QueryServiceStatusProcessInfoByName(hSCM, pServiceName, &ServiceStatusProcess) )
return ServiceStatusProcess.dwProcessId;
return 0;
}
DWORD HeuristicServiceGroupProcessId(SC_HANDLE hSCM, const wchar_t *pGroupNameSearch)
{
wchar_t *pData;
DWORD result = 0;
DWORD dwProcessId;
DWORD cbBufSize;
LPQUERY_SERVICE_CONFIGW pServiceConfig;
bool success = false;
LPWSTR pGroupName;
HLOCAL hMem;
pData = RegGetValueAlloc(HKEY_LOCAL_MACHINE,
L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Svchost",
pGroupNameSearch,
RRF_RT_REG_MULTI_SZ,
NULL,
NULL);
if ( !pData ) return result;
for ( wchar_t *pName = pData; *pName; pName += wcslen(pName) + 1 ) {
dwProcessId = QueryServiceProcessIdByName(hSCM, pName);
if ( !dwProcessId ) continue;
pServiceConfig = QueryServiceConfigByNameAlloc(hSCM, pName, &cbBufSize);
if ( !pServiceConfig ) continue;
if ( pServiceConfig->dwServiceType == SERVICE_WIN32_SHARE_PROCESS
&& QueryServiceGroupName(pServiceConfig, &pGroupName, &hMem) ) {
success = !_wcsicmp(pGroupNameSearch, pGroupName);
LocalFree(hMem);
}
free(pServiceConfig);
if ( success ) {
result = dwProcessId;
break;
}
}
free(pData);
return result;
}
DWORD HeuristicServiceProcessId(SC_HANDLE hSCM, SC_HANDLE hService)
{
DWORD result = 0;
LPQUERY_SERVICE_CONFIGW pServiceConfig;
LPWSTR pGroupName;
HLOCAL hMem;
result = QueryServiceProcessId(hSCM, hService);
if ( result )
return result;
pServiceConfig = QueryServiceConfigAlloc(hSCM, hService, NULL);
if ( pServiceConfig ) {
switch ( pServiceConfig->dwServiceType ) {
case SERVICE_WIN32_OWN_PROCESS:
// if the service isn't already running there's no
// way to accurately guess the PID when it is set to
// run in its own process. returns 0
break;
case SERVICE_WIN32_SHARE_PROCESS:
// when the service is configured to run in a shared
// process, it is possible to "guess" which svchost.exe
// it will eventually be loaded into by finding other
// services in the same group that are already running.
if ( QueryServiceGroupName(pServiceConfig, &pGroupName, &hMem) ) {
result = HeuristicServiceGroupProcessId(hSCM, pGroupName);
LocalFree(hMem);
}
break;
}
free(pServiceConfig);
}
return result;
}
DWORD HeuristicServiceProcessIdByName(SC_HANDLE hSCM, const wchar_t *pServiceName)
{
DWORD result = 0;
SC_HANDLE hService;
hService = OpenServiceW(hSCM, pServiceName, SERVICE_QUERY_STATUS | SERVICE_QUERY_CONFIG);
result = HeuristicServiceProcessId(hSCM, hService);
CloseServiceHandle(hService);
return result;
}