首页
社区
课程
招聘
[原创] SandboxiePlus Service隔离代码分析
发表于: 2025-6-6 17:57 408

[原创] SandboxiePlus Service隔离代码分析

2025-6-6 17:57
408

最近写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 命令来创建服务,注册表方面的修改如下:
scm_createservice
scm_createservice

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

Scm_StartBoxedService2函数对应的源码如下:

调用StartService之后,对应服务的注册表内容如下:
scm_startservice

使用DebugView可以看到服务输出的内容,如下图:
scm_startservice
启动的服务进程会被再次注入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;
    // Register our service control handler with the SCM
    g_StatusHandle = RegisterServiceCtrlHandler(SERVICE_NAME, ServiceCtrlHandler);
    if (g_StatusHandle == NULL)
    {
        goto EXIT;
    }
 
    // Tell the service controller we are starting
    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"));
    }
 
    // Create stop event to wait on later
    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;
    }
 
    // Tell the service controller we are started
    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"));
    }
 
    // Start the thread that will perform the main task of the service
    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;
    }
 
    // Wait until our worker thread exits effectively signaling that the service needs to stop
    WaitForSingleObject(hThread, INFINITE);
 
    // Cleanup
    CloseHandle(hThread);
    CloseHandle(g_hStopEvent);
 
    // Tell the service controller we are stopped
    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"));
        }
 
        // This will signal the worker thread to start shutting down
        SetEvent(g_hStopEvent);
 
        break;
 
    default:
        break;
    }
}
 
DWORD WINAPI ServiceWorkerThread(LPVOID lpParam)
{
    // 主服务逻辑在此实现
    // 这是一个示例,每10秒检查一次停止事件
    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;
    // Register our service control handler with the SCM
    g_StatusHandle = RegisterServiceCtrlHandler(SERVICE_NAME, ServiceCtrlHandler);
    if (g_StatusHandle == NULL)
    {
        goto EXIT;
    }
 
    // Tell the service controller we are starting
    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"));
    }
 
    // Create stop event to wait on later
    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;
    }
 
    // Tell the service controller we are started
    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"));
    }
 
    // Start the thread that will perform the main task of the service
    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;
    }
 
    // Wait until our worker thread exits effectively signaling that the service needs to stop
    WaitForSingleObject(hThread, INFINITE);
 
    // Cleanup
    CloseHandle(hThread);
    CloseHandle(g_hStopEvent);
 
    // Tell the service controller we are stopped
    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"));
        }
 
        // This will signal the worker thread to start shutting down
        SetEvent(g_hStopEvent);
 
        break;
 
    default:
        break;
    }
}
 
DWORD WINAPI ServiceWorkerThread(LPVOID lpParam)
{
    // 主服务逻辑在此实现
    // 这是一个示例,每10秒检查一次停止事件
    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;
 
    //
    // verify the service does not exist (also verifies hSCManager,
    // and that the service name is not NULL)
    //
     
    // 检查服务是否已经存在,沙盒中的hSCManager必须是HANDLE_SERVICE_MANAGER
    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;
 
    //
    // create a key for the new service                    
    //
    // 设置服务注册表内容,注册表位置HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\lpServiceName
    hkey = Scm_OpenKeyForService(lpServiceName, TRUE);
    if (! hkey) {
        // SetLastError already called
        return NULL;
    }
     
    // Type => SERVICE_WIN32_OWN_PROCESS
    RtlInitUnicodeString(&uni, L"Type");                       
    status = NtSetValueKey(
        hkey, &uni, 0, REG_DWORD, &dwServiceType, sizeof(ULONG));
    if (! NT_SUCCESS(status))
        goto abort;
     
    // Start => auto
    RtlInitUnicodeString(&uni, L"Start");
    status = NtSetValueKey(
        hkey, &uni, 0, REG_DWORD, &dwStartType, sizeof(ULONG));
    if (! NT_SUCCESS(status))
        goto abort;
 
    // ErrorControl => 1,
    RtlInitUnicodeString(&uni, L"ErrorControl");
    status = NtSetValueKey(
        hkey, &uni, 0, REG_DWORD, &dwErrorControl, sizeof(ULONG));
    if (! NT_SUCCESS(status))
        goto abort;
 
    if (lpDisplayName) {
 
        // Service Test
        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) {
 
        // 可执行文件的路径 => D:\test\service_test_exe.exe
        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;
    }
 
    //
    // add the service to SbieSvc list of sandboxed services
    //
    // 标记服务是一个沙盒化服务,将lpServiceName添加到HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\SbieSvc的SandboxedServices中
    status = Scm_AddBoxedService(lpServiceName);
 
    if (! NT_SUCCESS(status))
        goto abort;
 
    NtClose(hkey);
 
    //
    // allocate a 'handle' that points to the service name
    //
 
    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;
 
    //
    // failure:  delete the key for the new service
    //
 
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;
 
    //
    // verify the service does not exist (also verifies hSCManager,
    // and that the service name is not NULL)
    //
     
    // 检查服务是否已经存在,沙盒中的hSCManager必须是HANDLE_SERVICE_MANAGER
    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;
 
    //
    // create a key for the new service                    
    //
    // 设置服务注册表内容,注册表位置HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\lpServiceName
    hkey = Scm_OpenKeyForService(lpServiceName, TRUE);
    if (! hkey) {
        // SetLastError already called
        return NULL;
    }
     
    // Type => SERVICE_WIN32_OWN_PROCESS
    RtlInitUnicodeString(&uni, L"Type");                       
    status = NtSetValueKey(
        hkey, &uni, 0, REG_DWORD, &dwServiceType, sizeof(ULONG));
    if (! NT_SUCCESS(status))
        goto abort;
     
    // Start => auto
    RtlInitUnicodeString(&uni, L"Start");
    status = NtSetValueKey(
        hkey, &uni, 0, REG_DWORD, &dwStartType, sizeof(ULONG));
    if (! NT_SUCCESS(status))
        goto abort;
 
    // ErrorControl => 1,
    RtlInitUnicodeString(&uni, L"ErrorControl");
    status = NtSetValueKey(
        hkey, &uni, 0, REG_DWORD, &dwErrorControl, sizeof(ULONG));
    if (! NT_SUCCESS(status))
        goto abort;
 
    if (lpDisplayName) {
 
        // Service Test
        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) {
 
        // 可执行文件的路径 => D:\test\service_test_exe.exe
        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;
    }
 
    //
    // add the service to SbieSvc list of sandboxed services
    //
    // 标记服务是一个沙盒化服务,将lpServiceName添加到HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\SbieSvc的SandboxedServices中
    status = Scm_AddBoxedService(lpServiceName);
 
    if (! NT_SUCCESS(status))
        goto abort;
 
    NtClose(hkey);
 
    //
    // allocate a 'handle' that points to the service name
    //
 
    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;
 
    //
    // failure:  delete the key for the new service
    //
 
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;
    }
 
    //
    // open the service if we know its name, first check in the sandbox,
    // and if not found, outside the sandbox
    //
 
    Scm_DiscardKeyCache(lpServiceName);
 
    if (Scm_IsBoxedService(lpServiceName)) {
         
        // 调用NtCreateKey 或 NtOpenKey打开对应的服务
        HANDLE hkey = Scm_OpenKeyForService(lpServiceName, FALSE);
        if (hkey) {
            NtClose(hkey);
            ok = TRUE;
        }
 
    } else {
        // 调用SbieDll_CallServer向SbieSvc服务发送MSGID_SERVICE_QUERY类型请求
        SERVICE_QUERY_RPL *rpl = (SERVICE_QUERY_RPL *)
            Scm_QueryServiceByName(lpServiceName, FALSE, FALSE);
        if (rpl) {
            Dll_Free(rpl);
            ok = TRUE;
        }
    }
 
    if (! ok) {
        // either Scm_OpenKeyForService or Scm_QueryServiceByName
        // has already called SetLastError
        return (SC_HANDLE)0;
    }
 
    //
    // allocate a 'handle' that points to the service name
    //
 
    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;
    }
 
    //
    // open the service if we know its name, first check in the sandbox,
    // and if not found, outside the sandbox
    //
 
    Scm_DiscardKeyCache(lpServiceName);
 
    if (Scm_IsBoxedService(lpServiceName)) {
         
        // 调用NtCreateKey 或 NtOpenKey打开对应的服务
        HANDLE hkey = Scm_OpenKeyForService(lpServiceName, FALSE);
        if (hkey) {
            NtClose(hkey);
            ok = TRUE;
        }
 
    } else {
        // 调用SbieDll_CallServer向SbieSvc服务发送MSGID_SERVICE_QUERY类型请求
        SERVICE_QUERY_RPL *rpl = (SERVICE_QUERY_RPL *)
            Scm_QueryServiceByName(lpServiceName, FALSE, FALSE);
        if (rpl) {
            Dll_Free(rpl);
            ok = TRUE;
        }
    }
 
    if (! ok) {
        // either Scm_OpenKeyForService or Scm_QueryServiceByName
        // has already called SetLastError
        return (SC_HANDLE)0;
    }
 
    //
    // allocate a 'handle' that points to the service name
    //
 
    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;
     
    // 关闭Scm_OpenSCManagerW返回的结果HANDLE_SERVICE_MANAGER
    if (hSCObject == HANDLE_SERVICE_MANAGER)
        ok = TRUE;
    else if (Scm_GetHandleName(hSCObject)) {
        // 删除Scm_Notify_Global中和hSCObject相关的element,和NotifyServiceStatusChange函数相关
        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;
     
    // 关闭Scm_OpenSCManagerW返回的结果HANDLE_SERVICE_MANAGER
    if (hSCObject == HANDLE_SERVICE_MANAGER)
        ok = TRUE;
    else if (Scm_GetHandleName(hSCObject)) {
        // 删除Scm_Notify_Global中和hSCObject相关的element,和NotifyServiceStatusChange函数相关
        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)   // WithAdd = False
{
    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);
 
    //
    // when invoked from SandboxieRpcSs to handle StartProcess,
    // specify WithAdd to add the service to the sandbox
    //
 
    if (WithAdd)
        Scm_AddBoxedService(ServiceName);
 
    //
    // get service parameters and check that the service can be started
    //
 
    rpl = Scm_QueryBoxedServiceByName(ServiceName, TRUE, -1);
    if (! rpl)
        return FALSE;
 
    // 服务处于RUNNING状态,无需启动
    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;
    }
 
    // 如果启动的服务不是一个exe或dll,暂时不支持,报错。
    if (! (rpl->service_status.dwServiceType & SERVICE_WIN32)) {
 
        Dll_Free(rpl);
        SetLastError(ERROR_SERVICE_LOGON_FAILED);
        return FALSE;
    }
 
    //
    // set service status - start pending
    //
 
    hkey = Scm_OpenKeyForService(ServiceName, TRUE);
    if (! hkey) {
        error = GetLastError();
        Dll_Free(rpl);
        SetLastError(error);
        return FALSE;
    }
 
    //
    // indicate the service is initializing
    //
 
    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);
 
    //
    // launch the service
    //
 
    error = Scm_StartBoxedService2(ServiceName, rpl);
 
    Dll_Free(rpl);
 
    //
    // wait for the service to indicate it has started
    //
 
    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)   // WithAdd = False
{
    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);
 
    //
    // when invoked from SandboxieRpcSs to handle StartProcess,
    // specify WithAdd to add the service to the sandbox
    //
 
    if (WithAdd)
        Scm_AddBoxedService(ServiceName);
 
    //
    // get service parameters and check that the service can be started
    //
 
    rpl = Scm_QueryBoxedServiceByName(ServiceName, TRUE, -1);
    if (! rpl)
        return FALSE;
 
    // 服务处于RUNNING状态,无需启动
    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;
    }
 
    // 如果启动的服务不是一个exe或dll,暂时不支持,报错。
    if (! (rpl->service_status.dwServiceType & SERVICE_WIN32)) {
 
        Dll_Free(rpl);
        SetLastError(ERROR_SERVICE_LOGON_FAILED);
        return FALSE;
    }
 
    //
    // set service status - start pending
    //
 
    hkey = Scm_OpenKeyForService(ServiceName, TRUE);
    if (! hkey) {
        error = GetLastError();
        Dll_Free(rpl);
        SetLastError(error);
        return FALSE;
    }
 
    //
    // indicate the service is initializing
    //
 
    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);
 
    //
    // launch the service
    //
 
    error = Scm_StartBoxedService2(ServiceName, rpl);
 
    Dll_Free(rpl);
 
    //
    // wait for the service to indicate it has started
    //
 
    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;
 
    //
    // special handling for Sandboxie services:
    // either run directly (for SandboxieCrypto)
    // or build a path to the Sandboxie executable
    //
 
    free_path = FALSE;
    // _bits -> 后台智能传输服务,_wuauserv -> Windows更新服务,Scm_CryptSvc -> 加密服务
    // 这三个特殊服务特殊处理
    if (_wcsicmp(name, _bits) == 0           ||    
        _wcsicmp(name, _wuauserv) == 0       ||
        _wcsicmp(name, Scm_CryptSvc) == 0) {
 
        //PROCESS_INFORMATION pi;
        STARTUPINFO si;
 
        const WCHAR *ProcessName;
        //BOOLEAN use_sbiesvc = TRUE;
 
        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;
            //use_sbiesvc = FALSE;
        } 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');
    }
 
    //
    // otherwise start service through SbieSvc
    //
 
    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) {
 
        //
        // the McAfee SiteAdvisor Service is a WIN32_SHARE_PROCESS service
        // when it is part of the Total Protection suite, so we need to
        // make sure it will always be treated as SERVICE_WIN32_OWN_PROCESS
        //
 
        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);
     
    // 向SbieSvc发送MSGID_SERVICE_RUN请求,创建进程
    rpl = (MSG_HEADER *)SbieDll_CallServer(&req->h);
    if (! rpl)
        error = ERROR_NOT_ENOUGH_MEMORY;
    else {
        error = rpl->status;
        Dll_Free(rpl);
    }
 
    //
    // finish
    //
 
    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;
 
    //
    // special handling for Sandboxie services:
    // either run directly (for SandboxieCrypto)
    // or build a path to the Sandboxie executable
    //
 
    free_path = FALSE;
    // _bits -> 后台智能传输服务,_wuauserv -> Windows更新服务,Scm_CryptSvc -> 加密服务
    // 这三个特殊服务特殊处理
    if (_wcsicmp(name, _bits) == 0           ||    
        _wcsicmp(name, _wuauserv) == 0       ||
        _wcsicmp(name, Scm_CryptSvc) == 0) {
 
        //PROCESS_INFORMATION pi;
        STARTUPINFO si;
 
        const WCHAR *ProcessName;
        //BOOLEAN use_sbiesvc = TRUE;
 
        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;
            //use_sbiesvc = FALSE;
        } else

[培训]科锐逆向工程师培训第53期2025年7月8日开班!

最后于 2025-6-6 18:00 被baolongshou编辑 ,原因:
收藏
免费 1
支持
分享
最新回复 (1)
雪    币: 5564
活跃值: (4573)
能力值: ( LV13,RANK:300 )
在线值:
发帖
回帖
粉丝
2
SandboxiePlus COM请求劫持原理 => 084K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6E0M7q4)9J5k6i4N6W2K9i4S2A6L8W2)9J5k6i4q4I4i4K6u0W2j5$3!0E0i4K6u0r3M7#2)9J5c8X3S2s2P5q4N6W2x3#2b7^5P5o6g2g2b7$3I4n7P5X3W2a6x3@1y4x3d9#2q4Q4c8f1k6Q4b7V1y4Q4z5p5y4Q4c8e0k6Q4z5o6c8Q4z5f1k6Q4c8e0g2Q4z5o6g2Q4b7U0c8Q4c8e0S2Q4b7U0k6Q4b7e0y4Q4c8e0N6Q4z5f1q4Q4z5o6c8Q4c8e0g2Q4b7U0m8Q4z5p5k6Q4c8e0c8Q4b7V1y4Q4z5e0W2Q4c8e0c8Q4b7V1y4Q4b7U0c8Q4c8e0g2Q4z5p5k6Q4b7f1k6Q4c8e0c8Q4b7V1u0Q4b7e0g2Q4c8e0N6Q4z5f1y4Q4z5p5u0Q4c8e0N6Q4z5f1y4Q4z5p5u0Q4c8e0S2Q4b7V1k6Q4z5e0W2Q4c8e0N6Q4b7f1k6Q4z5o6N6Q4c8e0g2Q4z5o6k6Q4z5o6g2Q4c8e0g2Q4b7f1g2Q4b7U0W2Q4c8e0y4Q4z5o6m8Q4z5o6u0Q4c8e0S2Q4b7e0k6Q4z5o6q4Q4c8e0k6Q4z5e0S2Q4b7f1k6Q4c8e0S2Q4z5o6y4Q4b7V1c8Q4c8e0g2Q4z5o6g2Q4b7U0y4Q4c8e0k6Q4b7U0y4Q4b7e0S2Q4c8e0c8Q4b7U0S2Q4z5o6m8Q4c8e0c8Q4b7U0S2Q4z5p5u0Q4c8e0g2Q4z5o6g2Q4b7f1y4Q4c8e0c8Q4b7V1y4Q4z5e0N6Q4c8e0g2Q4z5p5k6Q4b7U0N6Q4c8f1k6Q4b7V1y4Q4z5p5y4Q4c8e0W2Q4z5o6u0Q4b7e0y4Q4c8e0g2Q4b7U0m8Q4b7U0q4Q4c8e0k6Q4z5f1u0Q4b7U0c8Q4c8e0g2Q4b7e0g2Q4b7V1c8Q4c8e0c8Q4b7V1q4Q4z5o6k6Q4c8f1k6Q4b7V1y4Q4z5p5y4Q4c8e0k6Q4z5o6c8Q4z5f1k6Q4c8e0S2Q4b7U0m8Q4b7e0u0Q4c8e0y4Q4z5o6m8Q4z5o6t1`.
2025-6-6 17:59
0
游客
登录 | 注册 方可回帖
返回