最近写Sandboxieplus劫持com请求方法的例子,RpcSs和DcomLaunch都是服务类型,需要详细了解SandboxiePlus如何实现服务隔离的。即本文剖析一个问题:SandboxiePlus如何管理一个服务的。
Windows服务对应的文件有两种类型:
一个Windows服务必须存在存在两个处理逻辑:ServiceMain函数和ServiceCtrlHandler函数。如果该服务是由svchost.exe进行托管的话,这个dll必须导出ServiceMain函数,函数名不可以改变。ServiceMain函数是服务的主要逻辑代码,ServiceCtrlHandler函数主要响应来自SCM(服务控制管理器)各种控制命令,比如:STOP和SHUTDOWN。下面将使用如下代码生成服务ServiceTest.exe文件研究SandboxiePlus如何实现服务的隔离。
执行sc create ServiceTest binPath= "D:\test\service_test_exe.exe" DisplayName= "Service Test" start= auto 命令来创建服务,注册表方面的修改如下:


主要逻辑:首先查看是否是沙盒化服务,如果是调用SbieDll_StartBoxedService,向SbieSvc进程发送MSGID_SERVICE_RUN请求;否则调用SbieDll_CallServer函数,向SbieSvc进程发送MSGID_SERVICE_START请求,启动服务。
SbieDll_StartBoxedService对应的源码如下:
Scm_StartBoxedService2函数对应的源码如下:
调用StartService之后,对应服务的注册表内容如下:

使用DebugView可以看到服务输出的内容,如下图:

启动的服务进程会被再次注入SbieDll,其对StartServiceCtrlDispatcher hook的代码如下:
对RegisterServiceCtrlHandler函数hook的源码主要设置Scm_Handler或Scm_HandlerEx,如下:
该函数可产生暂停、停止和恢复服务等效果,主要逻辑:设置服务的注册表SBIE_ControlCode键实现。上文中的Scm_StartServiceCtrlDispatcherX函数设置了hEvent来监听是否设置了SBIE_ControlCode,如果设置了就调用Scm_Handler或Scm_HandlerEx,通过这种方式实现了模拟SCM发送各种控制码给ServiceCtrlHandler函数的过程。
这些函数主要查询注册表中的信息,一些函数如下:
SubscribeServiceChangeNotifications和NotifyServiceStatusChange,这两个函数都是用于监控服务或SCM的状态改变。具体用法可以见微软的MSDN文档。这里举出两个使用情况:
对于SubscribeServiceChangeNotifications来说,SandboxiePlus对应的hook函数并没有实质的内容,目前是一个空函数,对应的代码如下:
对于NotifyServiceStatusChange来说,SandboxiePlus对应的hook函数主要逻辑:
对应的源码如下:
Scm_Notify_ThreadProc函数的源码如下:
#include <windows.h>
#include <tchar.h>
#include <strsafe.h>
SERVICE_STATUS g_ServiceStatus = { 0 };
SERVICE_STATUS_HANDLE g_StatusHandle = NULL;
HANDLE g_hStopEvent = NULL;
VOID WINAPI ServiceMain(DWORD argc, LPTSTR* argv);
VOID WINAPI ServiceCtrlHandler(DWORD);
DWORD WINAPI ServiceWorkerThread(LPVOID lpParam);
#define SERVICE_NAME _T("SampleService")
int main(int argc, char* argv[])
{
SERVICE_TABLE_ENTRY DispatchTable[] =
{
{ (LPWSTR)SERVICE_NAME, (LPSERVICE_MAIN_FUNCTION)ServiceMain },
{ NULL, NULL }
};
if (!StartServiceCtrlDispatcher(DispatchTable))
{
return GetLastError();
}
return 0;
}
VOID WINAPI ServiceMain(DWORD argc, LPTSTR* argv)
{
DWORD Status = E_FAIL;
HANDLE hThread = INVALID_HANDLE_VALUE;
g_StatusHandle = RegisterServiceCtrlHandler(SERVICE_NAME, ServiceCtrlHandler);
if (g_StatusHandle == NULL)
{
goto EXIT;
}
ZeroMemory(&g_ServiceStatus, sizeof(g_ServiceStatus));
g_ServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
g_ServiceStatus.dwControlsAccepted = 0;
g_ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
g_ServiceStatus.dwWin32ExitCode = 0;
g_ServiceStatus.dwServiceSpecificExitCode = 0;
g_ServiceStatus.dwCheckPoint = 0;
if (!SetServiceStatus(g_StatusHandle, &g_ServiceStatus))
{
OutputDebugString(_T("MySampleService: ServiceMain: SetServiceStatus returned error"));
}
g_hStopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (g_hStopEvent == NULL)
{
g_ServiceStatus.dwControlsAccepted = 0;
g_ServiceStatus.dwCurrentState = SERVICE_STOPPED;
g_ServiceStatus.dwWin32ExitCode = GetLastError();
g_ServiceStatus.dwCheckPoint = 1;
if (!SetServiceStatus(g_StatusHandle, &g_ServiceStatus))
{
OutputDebugString(_T("MySampleService: ServiceMain: SetServiceStatus returned error"));
}
goto EXIT;
}
g_ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN;
g_ServiceStatus.dwCurrentState = SERVICE_RUNNING;
g_ServiceStatus.dwWin32ExitCode = 0;
g_ServiceStatus.dwCheckPoint = 0;
if (!SetServiceStatus(g_StatusHandle, &g_ServiceStatus))
{
OutputDebugString(_T("MySampleService: ServiceMain: SetServiceStatus returned error"));
}
hThread = CreateThread(NULL, 0, ServiceWorkerThread, NULL, 0, NULL);
if (hThread == NULL)
{
g_ServiceStatus.dwControlsAccepted = 0;
g_ServiceStatus.dwCurrentState = SERVICE_STOPPED;
g_ServiceStatus.dwWin32ExitCode = GetLastError();
g_ServiceStatus.dwCheckPoint = 1;
if (!SetServiceStatus(g_StatusHandle, &g_ServiceStatus))
{
OutputDebugString(_T("MySampleService: ServiceMain: SetServiceStatus returned error"));
}
goto EXIT;
}
WaitForSingleObject(hThread, INFINITE);
CloseHandle(hThread);
CloseHandle(g_hStopEvent);
g_ServiceStatus.dwControlsAccepted = 0;
g_ServiceStatus.dwCurrentState = SERVICE_STOPPED;
g_ServiceStatus.dwWin32ExitCode = 0;
g_ServiceStatus.dwCheckPoint = 3;
if (!SetServiceStatus(g_StatusHandle, &g_ServiceStatus))
{
OutputDebugString(_T("MySampleService: ServiceMain: SetServiceStatus returned error"));
}
EXIT:
return;
}
VOID WINAPI ServiceCtrlHandler(DWORD Ctrl)
{
switch (Ctrl)
{
case SERVICE_CONTROL_STOP:
case SERVICE_CONTROL_SHUTDOWN:
if (g_ServiceStatus.dwCurrentState != SERVICE_RUNNING)
break;
g_ServiceStatus.dwControlsAccepted = 0;
g_ServiceStatus.dwCurrentState = SERVICE_STOP_PENDING;
g_ServiceStatus.dwWin32ExitCode = 0;
g_ServiceStatus.dwCheckPoint = 4;
if (!SetServiceStatus(g_StatusHandle, &g_ServiceStatus))
{
OutputDebugString(_T("MySampleService: ServiceCtrlHandler: SetServiceStatus returned error"));
}
SetEvent(g_hStopEvent);
break;
default:
break;
}
}
DWORD WINAPI ServiceWorkerThread(LPVOID lpParam)
{
while (WaitForSingleObject(g_hStopEvent, 10000) != WAIT_OBJECT_0)
{
OutputDebugString(_T("MySampleService: Doing stuff..."));
}
return ERROR_SUCCESS;
}
#include <windows.h>
#include <tchar.h>
#include <strsafe.h>
SERVICE_STATUS g_ServiceStatus = { 0 };
SERVICE_STATUS_HANDLE g_StatusHandle = NULL;
HANDLE g_hStopEvent = NULL;
VOID WINAPI ServiceMain(DWORD argc, LPTSTR* argv);
VOID WINAPI ServiceCtrlHandler(DWORD);
DWORD WINAPI ServiceWorkerThread(LPVOID lpParam);
#define SERVICE_NAME _T("SampleService")
int main(int argc, char* argv[])
{
SERVICE_TABLE_ENTRY DispatchTable[] =
{
{ (LPWSTR)SERVICE_NAME, (LPSERVICE_MAIN_FUNCTION)ServiceMain },
{ NULL, NULL }
};
if (!StartServiceCtrlDispatcher(DispatchTable))
{
return GetLastError();
}
return 0;
}
VOID WINAPI ServiceMain(DWORD argc, LPTSTR* argv)
{
DWORD Status = E_FAIL;
HANDLE hThread = INVALID_HANDLE_VALUE;
g_StatusHandle = RegisterServiceCtrlHandler(SERVICE_NAME, ServiceCtrlHandler);
if (g_StatusHandle == NULL)
{
goto EXIT;
}
ZeroMemory(&g_ServiceStatus, sizeof(g_ServiceStatus));
g_ServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
g_ServiceStatus.dwControlsAccepted = 0;
g_ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
g_ServiceStatus.dwWin32ExitCode = 0;
g_ServiceStatus.dwServiceSpecificExitCode = 0;
g_ServiceStatus.dwCheckPoint = 0;
if (!SetServiceStatus(g_StatusHandle, &g_ServiceStatus))
{
OutputDebugString(_T("MySampleService: ServiceMain: SetServiceStatus returned error"));
}
g_hStopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (g_hStopEvent == NULL)
{
g_ServiceStatus.dwControlsAccepted = 0;
g_ServiceStatus.dwCurrentState = SERVICE_STOPPED;
g_ServiceStatus.dwWin32ExitCode = GetLastError();
g_ServiceStatus.dwCheckPoint = 1;
if (!SetServiceStatus(g_StatusHandle, &g_ServiceStatus))
{
OutputDebugString(_T("MySampleService: ServiceMain: SetServiceStatus returned error"));
}
goto EXIT;
}
g_ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN;
g_ServiceStatus.dwCurrentState = SERVICE_RUNNING;
g_ServiceStatus.dwWin32ExitCode = 0;
g_ServiceStatus.dwCheckPoint = 0;
if (!SetServiceStatus(g_StatusHandle, &g_ServiceStatus))
{
OutputDebugString(_T("MySampleService: ServiceMain: SetServiceStatus returned error"));
}
hThread = CreateThread(NULL, 0, ServiceWorkerThread, NULL, 0, NULL);
if (hThread == NULL)
{
g_ServiceStatus.dwControlsAccepted = 0;
g_ServiceStatus.dwCurrentState = SERVICE_STOPPED;
g_ServiceStatus.dwWin32ExitCode = GetLastError();
g_ServiceStatus.dwCheckPoint = 1;
if (!SetServiceStatus(g_StatusHandle, &g_ServiceStatus))
{
OutputDebugString(_T("MySampleService: ServiceMain: SetServiceStatus returned error"));
}
goto EXIT;
}
WaitForSingleObject(hThread, INFINITE);
CloseHandle(hThread);
CloseHandle(g_hStopEvent);
g_ServiceStatus.dwControlsAccepted = 0;
g_ServiceStatus.dwCurrentState = SERVICE_STOPPED;
g_ServiceStatus.dwWin32ExitCode = 0;
g_ServiceStatus.dwCheckPoint = 3;
if (!SetServiceStatus(g_StatusHandle, &g_ServiceStatus))
{
OutputDebugString(_T("MySampleService: ServiceMain: SetServiceStatus returned error"));
}
EXIT:
return;
}
VOID WINAPI ServiceCtrlHandler(DWORD Ctrl)
{
switch (Ctrl)
{
case SERVICE_CONTROL_STOP:
case SERVICE_CONTROL_SHUTDOWN:
if (g_ServiceStatus.dwCurrentState != SERVICE_RUNNING)
break;
g_ServiceStatus.dwControlsAccepted = 0;
g_ServiceStatus.dwCurrentState = SERVICE_STOP_PENDING;
g_ServiceStatus.dwWin32ExitCode = 0;
g_ServiceStatus.dwCheckPoint = 4;
if (!SetServiceStatus(g_StatusHandle, &g_ServiceStatus))
{
OutputDebugString(_T("MySampleService: ServiceCtrlHandler: SetServiceStatus returned error"));
}
SetEvent(g_hStopEvent);
break;
default:
break;
}
}
DWORD WINAPI ServiceWorkerThread(LPVOID lpParam)
{
while (WaitForSingleObject(g_hStopEvent, 10000) != WAIT_OBJECT_0)
{
OutputDebugString(_T("MySampleService: Doing stuff..."));
}
return ERROR_SUCCESS;
}
_FX SC_HANDLE Scm_CreateServiceW(
SC_HANDLE hSCManager,
WCHAR *lpServiceName, WCHAR *lpDisplayName, ULONG dwDesiredAccess,
ULONG dwServiceType, ULONG dwStartType, ULONG dwErrorControl,
WCHAR *lpBinaryPathName, WCHAR *lpLoadOrderGroup, WCHAR *lpdwTagId,
WCHAR *lpDependencies, WCHAR *lpServiceStartName, WCHAR *lpPassword)
{
NTSTATUS status;
SC_HANDLE hService;
HANDLE hkey;
UNICODE_STRING uni;
WCHAR *name;
hService = Scm_OpenServiceWImpl(
hSCManager, lpServiceName, SERVICE_QUERY_STATUS);
if (hService) {
Scm_CloseServiceHandleImpl(hService);
SetLastError(ERROR_SERVICE_EXISTS);
return NULL;
}
if (GetLastError() != ERROR_SERVICE_DOES_NOT_EXIST)
return NULL;
hkey = Scm_OpenKeyForService(lpServiceName, TRUE);
if (! hkey) {
return NULL;
}
RtlInitUnicodeString(&uni, L"Type");
status = NtSetValueKey(
hkey, &uni, 0, REG_DWORD, &dwServiceType, sizeof(ULONG));
if (! NT_SUCCESS(status))
goto abort;
RtlInitUnicodeString(&uni, L"Start");
status = NtSetValueKey(
hkey, &uni, 0, REG_DWORD, &dwStartType, sizeof(ULONG));
if (! NT_SUCCESS(status))
goto abort;
RtlInitUnicodeString(&uni, L"ErrorControl");
status = NtSetValueKey(
hkey, &uni, 0, REG_DWORD, &dwErrorControl, sizeof(ULONG));
if (! NT_SUCCESS(status))
goto abort;
if (lpDisplayName) {
RtlInitUnicodeString(&uni, L"DisplayName");
status = NtSetValueKey(
hkey, &uni, 0, REG_SZ, lpDisplayName,
(wcslen(lpDisplayName) + 1) * sizeof(WCHAR));
if (! NT_SUCCESS(status))
goto abort;
}
if (lpBinaryPathName) {
RtlInitUnicodeString(&uni, L"ImagePath");
status = NtSetValueKey(
hkey, &uni, 0, REG_SZ, lpBinaryPathName,
(wcslen(lpBinaryPathName) + 1) * sizeof(WCHAR));
if (! NT_SUCCESS(status))
goto abort;
}
if (lpServiceStartName) {
RtlInitUnicodeString(&uni, L"ObjectName");
status = NtSetValueKey(
hkey, &uni, 0, REG_SZ, lpServiceStartName,
(wcslen(lpServiceStartName) + 1) * sizeof(WCHAR));
if (! NT_SUCCESS(status))
goto abort;
}
status = Scm_AddBoxedService(lpServiceName);
if (! NT_SUCCESS(status))
goto abort;
NtClose(hkey);
name = Dll_Alloc(
sizeof(ULONG) + (wcslen(lpServiceName) + 1) * sizeof(WCHAR));
*(ULONG *)name = tzuk;
wcscpy((WCHAR *)(((ULONG *)name) + 1), lpServiceName);
_wcslwr(name);
SetLastError(0);
return (SC_HANDLE)name;
abort:
NtDeleteKey(hkey);
NtClose(hkey);
SetLastError(ERROR_INVALID_PARAMETER);
return NULL;
}
_FX SC_HANDLE Scm_CreateServiceW(
SC_HANDLE hSCManager,
WCHAR *lpServiceName, WCHAR *lpDisplayName, ULONG dwDesiredAccess,
ULONG dwServiceType, ULONG dwStartType, ULONG dwErrorControl,
WCHAR *lpBinaryPathName, WCHAR *lpLoadOrderGroup, WCHAR *lpdwTagId,
WCHAR *lpDependencies, WCHAR *lpServiceStartName, WCHAR *lpPassword)
{
NTSTATUS status;
SC_HANDLE hService;
HANDLE hkey;
UNICODE_STRING uni;
WCHAR *name;
hService = Scm_OpenServiceWImpl(
hSCManager, lpServiceName, SERVICE_QUERY_STATUS);
if (hService) {
Scm_CloseServiceHandleImpl(hService);
SetLastError(ERROR_SERVICE_EXISTS);
return NULL;
}
if (GetLastError() != ERROR_SERVICE_DOES_NOT_EXIST)
return NULL;
hkey = Scm_OpenKeyForService(lpServiceName, TRUE);
if (! hkey) {
return NULL;
}
RtlInitUnicodeString(&uni, L"Type");
status = NtSetValueKey(
hkey, &uni, 0, REG_DWORD, &dwServiceType, sizeof(ULONG));
if (! NT_SUCCESS(status))
goto abort;
RtlInitUnicodeString(&uni, L"Start");
status = NtSetValueKey(
hkey, &uni, 0, REG_DWORD, &dwStartType, sizeof(ULONG));
if (! NT_SUCCESS(status))
goto abort;
RtlInitUnicodeString(&uni, L"ErrorControl");
status = NtSetValueKey(
hkey, &uni, 0, REG_DWORD, &dwErrorControl, sizeof(ULONG));
if (! NT_SUCCESS(status))
goto abort;
if (lpDisplayName) {
RtlInitUnicodeString(&uni, L"DisplayName");
status = NtSetValueKey(
hkey, &uni, 0, REG_SZ, lpDisplayName,
(wcslen(lpDisplayName) + 1) * sizeof(WCHAR));
if (! NT_SUCCESS(status))
goto abort;
}
if (lpBinaryPathName) {
RtlInitUnicodeString(&uni, L"ImagePath");
status = NtSetValueKey(
hkey, &uni, 0, REG_SZ, lpBinaryPathName,
(wcslen(lpBinaryPathName) + 1) * sizeof(WCHAR));
if (! NT_SUCCESS(status))
goto abort;
}
if (lpServiceStartName) {
RtlInitUnicodeString(&uni, L"ObjectName");
status = NtSetValueKey(
hkey, &uni, 0, REG_SZ, lpServiceStartName,
(wcslen(lpServiceStartName) + 1) * sizeof(WCHAR));
if (! NT_SUCCESS(status))
goto abort;
}
status = Scm_AddBoxedService(lpServiceName);
if (! NT_SUCCESS(status))
goto abort;
NtClose(hkey);
name = Dll_Alloc(
sizeof(ULONG) + (wcslen(lpServiceName) + 1) * sizeof(WCHAR));
*(ULONG *)name = tzuk;
wcscpy((WCHAR *)(((ULONG *)name) + 1), lpServiceName);
_wcslwr(name);
SetLastError(0);
return (SC_HANDLE)name;
abort:
NtDeleteKey(hkey);
NtClose(hkey);
SetLastError(ERROR_INVALID_PARAMETER);
return NULL;
}
_FX SC_HANDLE Scm_OpenServiceWImpl(
SC_HANDLE hSCManager,
const WCHAR *lpServiceName,
DWORD dwDesiredAccess)
{
WCHAR *name;
BOOLEAN ok = FALSE;
if (hSCManager != HANDLE_SERVICE_MANAGER) {
SetLastError(ERROR_INVALID_HANDLE);
return (SC_HANDLE)0;
}
if ((! lpServiceName) || (! *lpServiceName)) {
SetLastError(ERROR_INVALID_PARAMETER);
return (SC_HANDLE)0;
}
Scm_DiscardKeyCache(lpServiceName);
if (Scm_IsBoxedService(lpServiceName)) {
HANDLE hkey = Scm_OpenKeyForService(lpServiceName, FALSE);
if (hkey) {
NtClose(hkey);
ok = TRUE;
}
} else {
SERVICE_QUERY_RPL *rpl = (SERVICE_QUERY_RPL *)
Scm_QueryServiceByName(lpServiceName, FALSE, FALSE);
if (rpl) {
Dll_Free(rpl);
ok = TRUE;
}
}
if (! ok) {
return (SC_HANDLE)0;
}
name = Dll_Alloc(
sizeof(ULONG) + (wcslen(lpServiceName) + 1) * sizeof(WCHAR));
*(ULONG *)name = tzuk;
wcscpy((WCHAR *)(((ULONG *)name) + 1), lpServiceName);
_wcslwr(name);
SetLastError(0);
return (SC_HANDLE)name;
}
_FX SC_HANDLE Scm_OpenServiceWImpl(
SC_HANDLE hSCManager,
const WCHAR *lpServiceName,
DWORD dwDesiredAccess)
{
WCHAR *name;
BOOLEAN ok = FALSE;
if (hSCManager != HANDLE_SERVICE_MANAGER) {
SetLastError(ERROR_INVALID_HANDLE);
return (SC_HANDLE)0;
}
if ((! lpServiceName) || (! *lpServiceName)) {
SetLastError(ERROR_INVALID_PARAMETER);
return (SC_HANDLE)0;
}
Scm_DiscardKeyCache(lpServiceName);
if (Scm_IsBoxedService(lpServiceName)) {
HANDLE hkey = Scm_OpenKeyForService(lpServiceName, FALSE);
if (hkey) {
NtClose(hkey);
ok = TRUE;
}
} else {
SERVICE_QUERY_RPL *rpl = (SERVICE_QUERY_RPL *)
Scm_QueryServiceByName(lpServiceName, FALSE, FALSE);
if (rpl) {
Dll_Free(rpl);
ok = TRUE;
}
}
if (! ok) {
return (SC_HANDLE)0;
}
name = Dll_Alloc(
sizeof(ULONG) + (wcslen(lpServiceName) + 1) * sizeof(WCHAR));
*(ULONG *)name = tzuk;
wcscpy((WCHAR *)(((ULONG *)name) + 1), lpServiceName);
_wcslwr(name);
SetLastError(0);
return (SC_HANDLE)name;
}
_FX BOOL Scm_CloseServiceHandleImpl(SC_HANDLE hSCObject)
{
BOOL ok = FALSE;
if (hSCObject == HANDLE_SERVICE_MANAGER)
ok = TRUE;
else if (Scm_GetHandleName(hSCObject)) {
Scm_Notify_CloseHandle(hSCObject);
Dll_Free(hSCObject);
ok = TRUE;
}
if (ok)
SetLastError(0);
else
SetLastError(ERROR_INVALID_HANDLE);
return ok;
}
_FX BOOL Scm_CloseServiceHandleImpl(SC_HANDLE hSCObject)
{
BOOL ok = FALSE;
if (hSCObject == HANDLE_SERVICE_MANAGER)
ok = TRUE;
else if (Scm_GetHandleName(hSCObject)) {
Scm_Notify_CloseHandle(hSCObject);
Dll_Free(hSCObject);
ok = TRUE;
}
if (ok)
SetLastError(0);
else
SetLastError(ERROR_INVALID_HANDLE);
return ok;
}
_FX BOOL SbieDll_StartBoxedService(const WCHAR *ServiceName, BOOLEAN WithAdd)
{
HANDLE hkey;
SERVICE_STATUS ss;
SERVICE_QUERY_RPL *rpl;
ULONG retries, error;
WCHAR text[130];
Sbie_snwprintf(text, 130, L"StartBoxedService; name: '%s'", ServiceName);
SbieApi_MonitorPutMsg(MONITOR_SCM, text);
if (WithAdd)
Scm_AddBoxedService(ServiceName);
rpl = Scm_QueryBoxedServiceByName(ServiceName, TRUE, -1);
if (! rpl)
return FALSE;
if (rpl->service_status.dwCurrentState != SERVICE_STOPPED &&
rpl->service_status.dwCurrentState != SERVICE_START_PENDING) {
Dll_Free(rpl);
SetLastError(ERROR_SERVICE_ALREADY_RUNNING);
return FALSE;
}
if (rpl->service_status.dwServiceType & SERVICE_DRIVER) {
SbieApi_Log(2103, L"%S [%S] (StartService)", ServiceName, Dll_BoxName);
Dll_Free(rpl);
SetLastError(ERROR_ACCESS_DENIED);
return FALSE;
}
if (! (rpl->service_status.dwServiceType & SERVICE_WIN32)) {
Dll_Free(rpl);
SetLastError(ERROR_SERVICE_LOGON_FAILED);
return FALSE;
}
hkey = Scm_OpenKeyForService(ServiceName, TRUE);
if (! hkey) {
error = GetLastError();
Dll_Free(rpl);
SetLastError(error);
return FALSE;
}
memzero(&ss, sizeof(SERVICE_STATUS));
ss.dwCurrentState = SERVICE_START_PENDING;
ss.dwControlsAccepted = SERVICE_ACCEPT_STOP;
ss.dwWaitHint = 5000;
Scm_SetServiceStatus_Internal(
hkey, HANDLE_SERVICE_STATUS, &ss, FALSE);
CloseHandle(hkey);
error = Scm_StartBoxedService2(ServiceName, rpl);
Dll_Free(rpl);
if (! error) {
error = ERROR_SERVICE_LOGON_FAILED;
for (retries = 0; retries < 40; ++retries) {
Sleep(500);
rpl = Scm_QueryBoxedServiceByName(ServiceName, TRUE, 0);
if (! rpl)
return FALSE;
if (rpl->service_status.dwCurrentState == SERVICE_RUNNING) {
error = 0;
break;
}
Dll_Free(rpl);
}
}
......
SetLastError(0);
return TRUE;
}
_FX BOOL SbieDll_StartBoxedService(const WCHAR *ServiceName, BOOLEAN WithAdd)
{
HANDLE hkey;
SERVICE_STATUS ss;
SERVICE_QUERY_RPL *rpl;
ULONG retries, error;
WCHAR text[130];
Sbie_snwprintf(text, 130, L"StartBoxedService; name: '%s'", ServiceName);
SbieApi_MonitorPutMsg(MONITOR_SCM, text);
if (WithAdd)
Scm_AddBoxedService(ServiceName);
rpl = Scm_QueryBoxedServiceByName(ServiceName, TRUE, -1);
if (! rpl)
return FALSE;
if (rpl->service_status.dwCurrentState != SERVICE_STOPPED &&
rpl->service_status.dwCurrentState != SERVICE_START_PENDING) {
Dll_Free(rpl);
SetLastError(ERROR_SERVICE_ALREADY_RUNNING);
return FALSE;
}
if (rpl->service_status.dwServiceType & SERVICE_DRIVER) {
SbieApi_Log(2103, L"%S [%S] (StartService)", ServiceName, Dll_BoxName);
Dll_Free(rpl);
SetLastError(ERROR_ACCESS_DENIED);
return FALSE;
}
if (! (rpl->service_status.dwServiceType & SERVICE_WIN32)) {
Dll_Free(rpl);
SetLastError(ERROR_SERVICE_LOGON_FAILED);
return FALSE;
}
hkey = Scm_OpenKeyForService(ServiceName, TRUE);
if (! hkey) {
error = GetLastError();
Dll_Free(rpl);
SetLastError(error);
return FALSE;
}
memzero(&ss, sizeof(SERVICE_STATUS));
ss.dwCurrentState = SERVICE_START_PENDING;
ss.dwControlsAccepted = SERVICE_ACCEPT_STOP;
ss.dwWaitHint = 5000;
Scm_SetServiceStatus_Internal(
hkey, HANDLE_SERVICE_STATUS, &ss, FALSE);
CloseHandle(hkey);
error = Scm_StartBoxedService2(ServiceName, rpl);
Dll_Free(rpl);
if (! error) {
error = ERROR_SERVICE_LOGON_FAILED;
for (retries = 0; retries < 40; ++retries) {
Sleep(500);
rpl = Scm_QueryBoxedServiceByName(ServiceName, TRUE, 0);
if (! rpl)
return FALSE;
if (rpl->service_status.dwCurrentState == SERVICE_RUNNING) {
error = 0;
break;
}
Dll_Free(rpl);
}
}
......
SetLastError(0);
return TRUE;
}
_FX ULONG Scm_StartBoxedService2(const WCHAR *name, SERVICE_QUERY_RPL *qrpl)
{
SERVICE_RUN_REQ *req;
MSG_HEADER *rpl;
ULONG error, path_len, req_len;
WCHAR *path;
BOOL free_path;
free_path = FALSE;
if (_wcsicmp(name, _bits) == 0 ||
_wcsicmp(name, _wuauserv) == 0 ||
_wcsicmp(name, Scm_CryptSvc) == 0) {
STARTUPINFO si;
const WCHAR *ProcessName;
if (_wcsicmp(name, _bits) == 0) {
ProcessName = SandboxieBITS;
Scm_DeletePermissions(L"69AD4AEE-51BE-439B-A92C-86AE490E8B30");
} else if (_wcsicmp(name, _wuauserv) == 0) {
ProcessName = SandboxieWUAU;
Scm_DeletePermissions(L"653C5148-4DCE-4905-9CFD-1B23662D3D9E");
}
else if (_wcsicmp(name, Scm_CryptSvc) == 0) {
ProcessName = SandboxieCrypto;
} else
ProcessName = NULL;
si.lpReserved = NULL;
if (SbieDll_RunFromHome(ProcessName, NULL, &si, NULL)) {
path = (WCHAR *)si.lpReserved;
if (path)
free_path = TRUE;
}
}
if (! free_path) {
path = Scm_GetServiceConfigString(qrpl, 'P');
}
path_len = (wcslen(path) + 1) * sizeof(WCHAR);
req_len = sizeof(SERVICE_RUN_REQ) + path_len;
req = Dll_Alloc(req_len);
req->h.length = req_len;
req->h.msgid = MSGID_SERVICE_RUN;
req->type = qrpl->service_status.dwServiceType;
if (_wcsicmp(name, L"McAfee SiteAdvisor Service") == 0) {
req->type = SERVICE_WIN32_OWN_PROCESS;
}
wcsncpy(req->name, name, 64);
req->name[63] = L'\0';
req->devmap[0] = L'\0';
File_GetSetDeviceMap(req->devmap);
req->path_len = path_len;
memcpy(req->path, path, path_len);
rpl = (MSG_HEADER *)SbieDll_CallServer(&req->h);
if (! rpl)
error = ERROR_NOT_ENOUGH_MEMORY;
else {
error = rpl->status;
Dll_Free(rpl);
}
if (free_path)
HeapFree(GetProcessHeap(), HEAP_GENERATE_EXCEPTIONS, path);
return error;
}
_FX ULONG Scm_StartBoxedService2(const WCHAR *name, SERVICE_QUERY_RPL *qrpl)
{
SERVICE_RUN_REQ *req;
MSG_HEADER *rpl;
ULONG error, path_len, req_len;
WCHAR *path;
BOOL free_path;
free_path = FALSE;
if (_wcsicmp(name, _bits) == 0 ||
_wcsicmp(name, _wuauserv) == 0 ||
_wcsicmp(name, Scm_CryptSvc) == 0) {
STARTUPINFO si;
const WCHAR *ProcessName;
if (_wcsicmp(name, _bits) == 0) {
ProcessName = SandboxieBITS;
Scm_DeletePermissions(L"69AD4AEE-51BE-439B-A92C-86AE490E8B30");
} else if (_wcsicmp(name, _wuauserv) == 0) {
ProcessName = SandboxieWUAU;
Scm_DeletePermissions(L"653C5148-4DCE-4905-9CFD-1B23662D3D9E");
}
else if (_wcsicmp(name, Scm_CryptSvc) == 0) {
ProcessName = SandboxieCrypto;
} else
[培训]Windows内核深度攻防:从Hook技术到Rootkit实战!
最后于 2025-6-6 18:00
被baolongshou编辑
,原因: