时镜过迁,转眼即逝,基于Sandboxie意图快速构建解决方案,除了看源码,还可以借助AI学习,对于"技术老炮"游刃有余,每当有年轻朋友来寻找答案,总会多提一句,调试,实践,分享会有更多收获。 本篇是关于COM隔离方案见解,COM和DCOM不是一回事,是包含关系,COM是标准,容易混淆概念,Sandboxie COM隔离也是非常复杂。 DCOM是基于微软Component Object Model(COM)协议扩展,最早是用来跨网络对象通信,是一种跨主机的通信解决方案,经典应用包括打印机共享,WMI等。DCOM和RPC有关联?DCOM是基于RPC协议扩展,来传递对象引用,需要对Object Remote Procedure Call一起处理,这里表述两者因果关系。 题外记,琐碎时间空隙,很多年前还在甲方实习,听到乙方大佬谈论RPC/COM逃逸提权,天方夜谭,无从下手,坚持,挣扎,放弃。
编译部署或Github/官方下载安装程序,线上版安装到本地,把自己编译好的程序替换,附加调试。 注意!基于Sandboxie-Plus版本调试驱动会有签名检测,替换SbieSvc启动会失败。
驱动中有签名认证,SbieSvc初始化设置端口,签名检验失败,驱动返回STATUS_INVALID_SIGNATURE错误,SbieSvc服务会退出。
编码测试单元,能够在沙箱触发COM操作
代码通过COM口打开IE对象并访问百度网站,RPC连接,沙箱中效果如下,Unit.exe COM操作被Sandbox重定向到沙箱内的DcomLaunch.exe,进程树清晰,SboxDcomLaunch和SandboxieRpcSs是父子进程关系,SboxDcomLaunch负责执行IE相关的操作。
如何附加调试呢?先修改测试用例,main函数的地方添加暂停,程序被加载后先不调用COM口函数。
SbieSvc,SbieDrv先要通过KmdUtil停止卸载,自编译程序SbieDrv.sys,SbieSvc.exe,SbieDll.dll,SandboxieDcomLaunch.exe和SandboxieRpcSs.exe替换至Sandbox目录,重新启动沙箱,加载编译后的组件。
SbieDll工程附加到Unit.exe上,RPC和DCOM附加SandboxieRpcSs.exe 和SandboxieDcomLaunch.exe,这时候程序回车运行,开始动态调试。 沙箱内进程通过LDR注入成功后,进程加载系统DLL会被SbieDLL感染,Unit.exe调用CoCreateInstance方法会被挂钩至SbieDLL!Com_CoCreateInstance,下断后Unit.exe中回车,如下图所示:
Sandboxie RPC,COM处理分为两个步骤,重定向和隔离。沙箱通过SbieDll Hook进程RPC,COM相关API,将沙箱内进程请求重定向至SandboxieRpcSs进程,SandboxieRpcSs实现隔离,部分重定向操作等同于隔离,需要具体区分。
SandboxieRpcSs是一个被遗忘的进程,以往的见解中,包括各类QQ群"老炮"给出的解决方案,对SandboxieRpcSs绝口不提,对于RPC特别喜欢把重定向和隔离的概念混淆,另外绕过重定向和绕过隔离也是两个概念,不能混为一谈。 代码还没有运行,发现RpcSs和DcomLaunch进程已经启动,虽然SbieDll也有触发时机,并不是启动RPC最早的时机。
沙箱内RPC进程通过SbieSvc.exe启动,SboxSvc中有处理COMProxy的模块。
RpcSs启动失败会抛出2337的错误,Plus这个地方做了重试,会不停的启动RpcSs服务。 epmapper是RPC架构服务之一,负责RPC动态端口分配的服务,可以列出公开接口。客户端请求RPC,这时候就会找epmapper来询问相关信息,epmapper返回给客户端正确的端口和数据。 DCOM请求先要构造出来RPC服务,才能处理DCOM请求。SandboxieRpcSs是基础组件,沙箱内任何进程请求epmapper都应该先拉起SandboxieRpcSs进程,否则沙箱内肯定是处理不了RPC请求。 SandboxieRpcSs进程启动以后,关键逻辑如下:
WinSxs全称叫Side by Side,负责管理组件版本,系统位置C:\Windows\WinSxS,Sxs是微软提出"并行组件存储"解决方案。简单理解WinSxs下可以同时保存多个副本VC++运行库,每个程序都用自己的DLL版本。复杂的COM应用中,为不同组件分配独立的激活上下文,避免全局DLL版本冲突。 Sandbox启动RPCSS服务的时候,Sxs_Thread线程非常关键,目的是为了Sandbox沙箱提供隔离的组件版本管理,非常有意思的隔离方案。 sxs.dll和ole32.dll动态库加载SxsGenerateActivationContext,CreateStreamOnHGlobal,基于SxsGenerateActivationContext确保插件依赖的正确版本DLL被加载,使用CreateStreamOnHGlobal将插件配置或资源数据封装为流,供COM组件安全使用。
创建队列,接收沙盘请求SbieDll_QueueCreate,Sxs_Request处理,Sxs_Generate解析请求数据,比如清单/配置文件,语言,架构等等,用来生成上下文句柄,并通过pCreateStreamOnHGlobal创建ManifestStream,ConfigStream,创建IStream对象.
Sxs_GenerateHelper版本差异化处理,根据Windows版本将ISteam对象填充SXS_GENERATE_ACTIVATION_CONTEXT_VISTA_ARGS结构,通过pSxsGenerateActivationContext生成hSection.
沙盒进程通过hSection映射私有组件数据,LPC将数据回包给RPCSS_SXS
除了上述Sxs处理,还做了网络隔离,服务隔离,注册表权限模拟,StartRpcEptMapper和Service_Start_ServiceMain,分别创建了RpcEptMapper和RPCSS服务。 RPCSS服务COM/DCOM的核心服务,处理对象激活请求、解析分布式组件分布式通信的基石,Win7以上系统,需要额外启动RpcEptMapper服务,用于管理RPC端点映射数据库,确保RPC接口标识符的正确解析,注册会被SCM Hook拦截进入到my_StartServiceCtrlDispatcherW启动。
ServiceMain调用会触发RpcRt_RpcBindingFromStringBindingW和AlpcConnect,最终会通过Ipc_Start沙箱内部启动RpcSs服务。
ncalrpc:[lsasspirpc]是LSASS(Local Security Authority Subsystem Service)进程关联,负责系统安全策略、用户认证(如 NTLM/Kerberos)、凭证管理等敏感操作。 ncalrpc:[lsapolicylookup]用于LSA(Local Security Authority)策略查询,例如检查用户权限、安全组策略、域信任关系等。 actkernel是启动SandboxieDcomLaunch定义的服务事件,并非RPC标准的功能。 题外话,Mimikatz通过ncalrpc:[lsasspirpc]连接到 LSASS,调用 Lsapirpc 接口读取进程内存,提取明文密码或票据。
Rpcss服务的依赖关系
DCOM Server Process Launcher负责启动和监控DCOM服务进程,按需激活DCOM对象,管理DCOM的进程周期,另外要与RPCSS服务协同工作,确保分布式跨进程/机器的通信。DCOM服务依赖于RPCSS的UUID解析,测试用例中调用了CoCreateInstance,就是激活了DCOM对象。 See DoLingerLeader和linger.c文件,提供了一种LingerProcess机制来检测沙箱内服务,Add_LL_Entry将SandboxieDcomLaunch添加成LingerProcess,包括Crypto,BITS,WUAU等组件。
ProcessStartMonitor线程监听SESSION_PROCESS事件,通过SbieApi_EnumProcessEx枚举沙盒内进程,有新进程调用AddPid注册进程句柄监控。
RpcSs进程Hook_Service_Control_Manager对SCM服务进行了Hook,重定向到沙盒内部。
沙箱内对CreateFileMappingW函数做了处理,创建共享内存区域ComPlusCOMRegTable,模拟DCOM注册表的全局状态。
SandboxieRpcSs初始化成功以后,会向SbieSvc发送MSGID_SBIE_INI_RUN_SBIE_CTRL的消息事件。
SandboxieDcomLaunch启动以后,对SCM,Token进行了HOOK,注册了DCOMLAUNCH的服务,模拟Dcom服务加载对应的请求,DcomLauncher本身没太多技术细节,不做详细分析。
沙箱内进程COM请求重定向到RpcSs进程服务中,有很多种解决方案可以用,sandboxie这块做的也比较细化,有黑白名单的概念。
CoCreateInstance/CoCreateInstanceEx:拦截对象创建,检查CLSID是否在允许列表,也可以阻止特定类实例化,如ClosedClsid直接返回失败。 Com_IClassFactory_New使用自定义工厂实例化对象,转发请求到沙箱内进程。CoGetClassObject也需要做同样的处理,创建和获取都不会绕过沙箱对CLSID处理。
沙箱没设置CLSID授权列表,测试用例创建和获取COM对象,不会执行Com_IClassFactory_New,直接调用系统函数__sys_CoCreateInstance,如何将请求重定向沙箱SandboxRpcSs进程呢? See Ipc_NtAlpcConnectPort,Unit进程请求了InternetExplorer.Application的实例,实例被转换成了CLSID,会触发\RPC Control\epmapper,如果是沙箱内进程epmapper请求,检测DocmLaunch注册表和DcomLaunch Event.
AlpcConnectPort将PortName修改成沙箱内的SboxName,\Sandbox\zy.chen\DefaultBox\Session_3\RPC Control\epmapper
还有个概念,比如新的进程iexplore.exe进程会向RPCSS服务注册一个唯一的RPC端点,也会被重定向沙箱内,Ipc_NtAlpcCreatePort也会重定向到沙箱内路径。
CoCreateInstance原理感兴趣朋友,可以基于combase.dll组件对CoCreateInstance流程IDA逆向下,也可以基于DeepSeek来分析下,坑肯定有的,把符号表和汇编输入,输出的结果如下:
DeepSeek仅做参考,另一种快捷的梳理方式,基于vs2019可以直接栈回溯,这里在SbieDll!Alpc模块下断,Ipc_NtAlpcConnectPortEx栈回溯
除了上面的Alpc Name重定向之外,上文提到SandboxieRpcSs Sxe_Thread线程会处理来自于沙箱内的Rpc_Sxs消息,处理Sandboxie Sxs请求。消息事件的生产者是进程调用Sxs_CreateActCtxW产生的Sxs数据,调用SbieDll!Sxs_CallService将进程Sxs请求转发至RpcSs中处理,端口是RPCS_SXS.
RpcSs中Sxs_CreateActCtxW处理打印如下,Sxs隔离方案是非常重要的环节,也是对抗水位较高的地方。
SbieDLL!Ipc_StartServer函数中对死锁和策略绕过有细节处理,CreateProcess启动流程复杂,内部会加载LoadLibrary,线程B已持有加载器锁,并等待SandboxieRpcSs启动完成,就会造成死锁。
DLL初始化阶段,调用CreateProcess启动RPC进程可能会出现这种情况,Sandboxie通过SbieSvc ProcessServer来启动。 SbieSvc服务发消息MSGID_PROCESS_RUN_SANDBOXED,通过SbieDll_RunSandboxed函数负责发送,Svc收到消息后处理,关于SRP和AppLocker策略绕过方案,也可以直接抄作业。
还有两个关于COM API基本处理,CoMarshalInterface和CoUnmarshalInterface,msdn对两个函数介绍,通俗来讲是序列化和反序列化。
接口封送:Com_CoMarshalInterface将COM接口指针序列化时,若目标上下文为跨沙箱,则生成指向沙箱代理的OBJREF,确保反序列化时在沙箱内重建,另外对ISearchNotifyInlineSite对象做了特殊处理。
比如类型dwDestContext等于MSHCTX_DIFFERENTMACHINE,这是由宿主环境的epmapper生成,代理OBJERF数据构建,通过SbieDll_CallServer封送。
接口解封:Com_CoUnmarshalInterface检测到外部封送数据时,通过COM_UNMARSHAL_INTERFACE_REQ请求SbieSvc在沙箱内解封,返回本地代理对象。
Com_CoUnmarshalInterface Hook函数用来解决什么问题呢?是解决SbieSvc OXID解析冲突,Sandboxie对epmapper做了隔离,处理不了沙箱外的SbieSvc epmapper注册的OXID,如果解析失败返回OR_INVALID_OXID,回滚流的位置,调用Com_CoUnmarshalInterface_Common自定义处理。 Com_CoUnmarshalInterface_Common自定义处理,构造COM_UNMARSHAL_INTERFACE_REQ请求,通过Com_CreateProxy发送SBieSvc来处理,将SbieSvc解析的数据,在接收objidx和封送数据,SbieSvc返回激活上下文数据映射到当前进程。
Sandboxie还有很多细节处理,Rpc,Com Hook囊括了多数关键接口,篇幅长短,不一一完整列举,本篇基础加以代码动态调试,也许可以给大家带来更多见解和思路,文中难免有纰漏,多多包涵。
KmdUtil.exe install SbieSvc D:\Sandboxie-Plus\SbieSvc.exe type=own start=auto display="Sandboxie Service" group=UIGroup
KmdUtil.exe install SbieSvc D:\Sandboxie-Plus\SbieSvc.exe type=own start=auto display="Sandboxie Service" group=UIGroup
本地计算机 上的 Sandboxie Service 服务启动后停止。某些服务在未由其他服务或程序使用时将自动停止。
本地计算机 上的 Sandboxie Service 服务启动后停止。某些服务在未由其他服务或程序使用时将自动停止。
SbieSvc!API_SET_SERVICE_PORT
SbieApi_Call(API_SET_SERVICE_PORT, 1, (ULONG_PTR)m_instance->m_PortHandle);
SbieDrv!MyIsCallerSigned
NTSTATUS KphVerifyCurrentProcess();
_FX BOOLEAN MyIsCallerSigned(void)
{
return TRUE; // 直接返回成功
NTSTATUS status;
// in test signing mode don't verify the signature
if (Driver_OsTestSigning)
return TRUE;
status = KphVerifyCurrentProcess();
//DbgPrint("Image Signature Verification result: 0x%08x\r\n", status);
if (!NT_SUCCESS(status)) {
//Log_Status(MSG_1330, 0, status);
return FALSE;
}
return TRUE;
}
SbieSvc!API_SET_SERVICE_PORT
SbieApi_Call(API_SET_SERVICE_PORT, 1, (ULONG_PTR)m_instance->m_PortHandle);
SbieDrv!MyIsCallerSigned
NTSTATUS KphVerifyCurrentProcess();
_FX BOOLEAN MyIsCallerSigned(void)
{
return TRUE; // 直接返回成功
NTSTATUS status;
// in test signing mode don't verify the signature
if (Driver_OsTestSigning)
return TRUE;
status = KphVerifyCurrentProcess();
//DbgPrint("Image Signature Verification result: 0x%08x\r\n", status);
if (!NT_SUCCESS(status)) {
//Log_Status(MSG_1330, 0, status);
return FALSE;
}
return TRUE;
}
const RPC_WSTR RPC_INTERFACE_UUID = (RPC_WSTR)L"6d9c4bcf-7e20-46c0-8d3a-8cfeb5a59010";
void TriggerDCOMOperation() {
HRESULT hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
if (FAILED(hr)) {
return;
}
IWebBrowser2* pBrowser = nullptr;
CLSID clsidIE;
do {
hr = CLSIDFromProgID(L"InternetExplorer.Application", &clsidIE);
if (FAILED(hr)) {
break;
}
hr = CoCreateInstance(
clsidIE,
nullptr,
CLSCTX_LOCAL_SERVER,
IID_IWebBrowser2,
(void**)&pBrowser
);
if (FAILED(hr) || !pBrowser) {
break;
}
hr = pBrowser->put_Visible(VARIANT_TRUE);
if (FAILED(hr)) {
break;
}
VARIANT url, flags, targetFrame, postData, headers;
VariantInit(&url);
VariantInit(&flags);
VariantInit(&targetFrame);
VariantInit(&postData);
VariantInit(&headers);
url.vt = VT_BSTR;
url.bstrVal = SysAllocString(L"0adK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6%4N6%4N6Q4x3X3g2T1j5h3W2V1N6g2)9J5k6h3y4G2L8b7`.`. ");
flags.vt = VT_I4;
flags.lVal = navNoHistory;
hr = pBrowser->Navigate2(
&url, // URL
&flags, // Flags
&targetFrame, // Target frame
&postData, // Post data
&headers // Headers
);
// clear
VariantClear(&url);
VariantClear(&flags);
VariantClear(&targetFrame);
VariantClear(&postData);
VariantClear(&headers);
if (FAILED(hr)) {
break;
}
system("pause");
} while (false);
if (pBrowser) {
pBrowser->Release();
pBrowser = nullptr;
}
CoUninitialize();
}
void TriggerRPCOperation() {
RPC_STATUS status;
RPC_WSTR szStringBinding = nullptr;
status = RpcStringBindingCompose(
RPC_INTERFACE_UUID,
(RPC_WSTR)L"ncalrpc",
nullptr,
(RPC_WSTR)L"RpcTestPort",
nullptr,
&szStringBinding
);
if (status != RPC_S_OK) {
std::cerr << "[-] rpc bind error " << status << std::endl;
return;
}
RPC_BINDING_HANDLE hBinding = nullptr;
status = RpcBindingFromStringBinding(szStringBinding, &hBinding);
if (status == RPC_S_OK) {
std::cout << "[+] rpc connect success. " << std::endl;
RpcBindingFree(&hBinding);
}
else {
std::cerr << "[-] rpc connect error: " << status << std::endl;
}
RpcStringFree(&szStringBinding);
}
int main() {
std::cout << "[+] unit test create dcom object.\n" << std::endl;
TriggerDCOMOperation();
std::cout << "[+] unit test connect rpc.\n" << std::endl;
TriggerRPCOperation();
system("pause");
return 0;
}
void* __RPC_USER midl_user_allocate(size_t size) {
return malloc(size);
}
void __RPC_USER midl_user_free(void* p) {
free(p);
}
const RPC_WSTR RPC_INTERFACE_UUID = (RPC_WSTR)L"6d9c4bcf-7e20-46c0-8d3a-8cfeb5a59010";
void TriggerDCOMOperation() {
HRESULT hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
if (FAILED(hr)) {
return;
}
IWebBrowser2* pBrowser = nullptr;
CLSID clsidIE;
do {
hr = CLSIDFromProgID(L"InternetExplorer.Application", &clsidIE);
if (FAILED(hr)) {
break;
}
hr = CoCreateInstance(
clsidIE,
nullptr,
CLSCTX_LOCAL_SERVER,
IID_IWebBrowser2,
(void**)&pBrowser
);
if (FAILED(hr) || !pBrowser) {
break;
}
hr = pBrowser->put_Visible(VARIANT_TRUE);
if (FAILED(hr)) {
break;
}
VARIANT url, flags, targetFrame, postData, headers;
VariantInit(&url);
VariantInit(&flags);
VariantInit(&targetFrame);
VariantInit(&postData);
VariantInit(&headers);
url.vt = VT_BSTR;
url.bstrVal = SysAllocString(L"fdaK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6%4N6%4N6Q4x3X3g2T1j5h3W2V1N6g2)9J5k6h3y4G2L8b7`.`. ");
flags.vt = VT_I4;
flags.lVal = navNoHistory;
hr = pBrowser->Navigate2(
&url, // URL
&flags, // Flags
&targetFrame, // Target frame
&postData, // Post data
&headers // Headers
);
// clear
VariantClear(&url);
VariantClear(&flags);
VariantClear(&targetFrame);
VariantClear(&postData);
VariantClear(&headers);
if (FAILED(hr)) {
break;
}
system("pause");
} while (false);
if (pBrowser) {
pBrowser->Release();
pBrowser = nullptr;
}
CoUninitialize();
}
void TriggerRPCOperation() {
RPC_STATUS status;
RPC_WSTR szStringBinding = nullptr;
status = RpcStringBindingCompose(
RPC_INTERFACE_UUID,
(RPC_WSTR)L"ncalrpc",
nullptr,
(RPC_WSTR)L"RpcTestPort",
nullptr,
&szStringBinding
);
if (status != RPC_S_OK) {
std::cerr << "[-] rpc bind error " << status << std::endl;
return;
}
RPC_BINDING_HANDLE hBinding = nullptr;
status = RpcBindingFromStringBinding(szStringBinding, &hBinding);
if (status == RPC_S_OK) {
std::cout << "[+] rpc connect success. " << std::endl;
RpcBindingFree(&hBinding);
}
else {
std::cerr << "[-] rpc connect error: " << status << std::endl;
}
RpcStringFree(&szStringBinding);
}
int main() {
std::cout << "[+] unit test create dcom object.\n" << std::endl;
TriggerDCOMOperation();
std::cout << "[+] unit test connect rpc.\n" << std::endl;
TriggerRPCOperation();
system("pause");
return 0;
}
void* __RPC_USER midl_user_allocate(size_t size) {
return malloc(size);
}
void __RPC_USER midl_user_free(void* p) {
free(p);
}
int main() {
std::cout << "[+] unit test create dcom object.\n" << std::endl;
// 调试缓冲,不要直接运行代码
system("pause");
TriggerDCOMOperation();
std::cout << "[+] unit test connect rpc.\n" << std::endl;
TriggerRPCOperation();
system("pause");
return 0;
}
int main() {
std::cout << "[+] unit test create dcom object.\n" << std::endl;
// 调试缓冲,不要直接运行代码
system("pause");
TriggerDCOMOperation();
std::cout << "[+] unit test connect rpc.\n" << std::endl;
TriggerRPCOperation();
system("pause");
return 0;
}
KmdUtil stop SbieSvc
KmdUtil stop SbieDrv
KmdUtil delete SbieSvc
KmdUtil delete SbieDrv
sc query SbieSvc & sc query SbieDrv
KmdUtil stop SbieSvc
KmdUtil stop SbieDrv
KmdUtil delete SbieSvc
KmdUtil delete SbieDrv
sc query SbieSvc & sc query SbieDrv
SbieDll!Dll_InitExeEntry --> SbieDll!SbieDll_StartCOM --> SbieDll!Ipc_StartServer
SbieDll!Dll_InitExeEntry --> SbieDll!SbieDll_StartCOM --> SbieDll!Ipc_StartServer
// Start Inject
"D:\Sandboxie-Plus\Start.exe" /env:00000000_SBIE_CURRENT_DIRECTORY="D:\Sandboxie-Plus" /env:=Refresh E:\Sandboxie_Hook\x64\Release\Unit.exe
// Start Rpc
"D:\Sandboxie-Plus\SandboxieRpcSs.exe" 00000000_SBIE_ALL_USERS=\Device\HarddiskVolume3\ProgramData
// Start Inject
"D:\Sandboxie-Plus\Start.exe" /env:00000000_SBIE_CURRENT_DIRECTORY="D:\Sandboxie-Plus" /env:=Refresh E:\Sandboxie_Hook\x64\Release\Unit.exe
// Start Rpc
"D:\Sandboxie-Plus\SandboxieRpcSs.exe" 00000000_SBIE_ALL_USERS=\Device\HarddiskVolume3\ProgramData
SbieSvc.exe!RunSandboxedStartProcess
// check if we are starting rpcss or dcomlaunch
else if ((service = wcscmp(cmd, L"*RPCSS*") == 0 ? L"RpcSs" : NULL, service)
/*|| (service = wcscmp(cmd, L"*DCOM*") == 0 ? L"DcomLaunch" : NULL, service)*/) {
WCHAR program[64];
wcscpy(program, SANDBOXIE);
wcscat(program, service);
wcscat(program, L".exe");
WCHAR homedir[MAX_PATH];
SbieApi_GetHomePath(NULL, 0, homedir, MAX_PATH);
cmd = (WCHAR *)HeapAlloc(GetProcessHeap(), 0, 512 * sizeof(WCHAR));
if (! cmd) {
SetLastError(ERROR_ACCESS_DENIED);
return FALSE;
}
_snwprintf(cmd, 512, L"\"%s\\%s\"", homedir, program);
dir = NULL;
CmdAltered = true;
}
bool bSession0 = (BoxNameOrModelPid > 0) && ((si->dwFlags & 0x80000000) != 0);
if (bSession0) {
OpenProcessToken(GetCurrentProcess(), TOKEN_IMPERSONATE | TOKEN_QUERY | TOKEN_DUPLICATE | STANDARD_RIGHTS_READ, &PrimaryTokenHandle);
}
// impersonate caller in case they have a different device map
// with different drive mappings
ok = DuplicateToken(PrimaryTokenHandle,
SecurityImpersonation,
&ImpersonationTokenHandle);
if (bSession0) {
CloseHandle(PrimaryTokenHandle);
PrimaryTokenHandle = NULL;
}
if (ok)
ok = SetThreadToken(NULL, ImpersonationTokenHandle);
if (ok) {
// create new process
ok = CreateProcessAsUser(
PrimaryTokenHandle, NULL, cmd, NULL, NULL, FALSE,
crflags2, env, dir, si, pi);
LastError = GetLastError();
}
SbieSvc.exe!RunSandboxedStartProcess
// check if we are starting rpcss or dcomlaunch
else if ((service = wcscmp(cmd, L"*RPCSS*") == 0 ? L"RpcSs" : NULL, service)
/*|| (service = wcscmp(cmd, L"*DCOM*") == 0 ? L"DcomLaunch" : NULL, service)*/) {
WCHAR program[64];
wcscpy(program, SANDBOXIE);
wcscat(program, service);
wcscat(program, L".exe");
WCHAR homedir[MAX_PATH];
SbieApi_GetHomePath(NULL, 0, homedir, MAX_PATH);
cmd = (WCHAR *)HeapAlloc(GetProcessHeap(), 0, 512 * sizeof(WCHAR));
if (! cmd) {
SetLastError(ERROR_ACCESS_DENIED);
return FALSE;
}
_snwprintf(cmd, 512, L"\"%s\\%s\"", homedir, program);
dir = NULL;
CmdAltered = true;
}
bool bSession0 = (BoxNameOrModelPid > 0) && ((si->dwFlags & 0x80000000) != 0);
if (bSession0) {
OpenProcessToken(GetCurrentProcess(), TOKEN_IMPERSONATE | TOKEN_QUERY | TOKEN_DUPLICATE | STANDARD_RIGHTS_READ, &PrimaryTokenHandle);
}
// impersonate caller in case they have a different device map
// with different drive mappings
ok = DuplicateToken(PrimaryTokenHandle,
SecurityImpersonation,
&ImpersonationTokenHandle);
if (bSession0) {
CloseHandle(PrimaryTokenHandle);
PrimaryTokenHandle = NULL;
}
if (ok)
ok = SetThreadToken(NULL, ImpersonationTokenHandle);
if (ok) {
// create new process
ok = CreateProcessAsUser(
PrimaryTokenHandle, NULL, cmd, NULL, NULL, FALSE,
crflags2, env, dir, si, pi);
LastError = GetLastError();
}
Sxs_Thread
SbieDll_IsOpenCOM
--> Hook_Service_Control_Manager
--> Hook CreateFileMappingW
--> Hook_Privilege
--> Start_WinSock
--> StartRpcEptMapper
--> Service_Start_ServiceMain
Dde_Thread
--> CreateWindows - RegisterClass - Sandboxie_DDE_ProxyClass1
Sxs_Thread
SbieDll_IsOpenCOM
--> Hook_Service_Control_Manager
--> Hook CreateFileMappingW
--> Hook_Privilege
--> Start_WinSock
--> StartRpcEptMapper
--> Service_Start_ServiceMain
Dde_Thread
--> CreateWindows - RegisterClass - Sandboxie_DDE_ProxyClass1
while (!mod && (retry++ < 20)) {
mod = LoadLibrary(L"sxs.dll");
if (!mod) {
NtYieldExecution();
}
}
if (mod) {
pSxsGenerateActivationContext = (P_SxsGenerateActivationContext)
GetProcAddress(mod, "SxsGenerateActivationContext");
}
else {
Sxs_Error(0x77, status);
return FALSE;
}
mod = 0;
retry = 0;
while (!mod && (retry++ < 20)) {
mod = LoadLibrary(L"ole32.dll");
if (!mod) {
NtYieldExecution();
}
}
if (mod) {
pCreateStreamOnHGlobal = (P_CreateStreamOnHGlobal)
GetProcAddress(mod, "CreateStreamOnHGlobal");
}
else {
Sxs_Error(0x88, status);
return FALSE;
}
while (!mod && (retry++ < 20)) {
mod = LoadLibrary(L"sxs.dll");
if (!mod) {
NtYieldExecution();
}
}
if (mod) {
pSxsGenerateActivationContext = (P_SxsGenerateActivationContext)
GetProcAddress(mod, "SxsGenerateActivationContext");
}
else {
Sxs_Error(0x77, status);
return FALSE;
}
mod = 0;
retry = 0;
while (!mod && (retry++ < 20)) {
mod = LoadLibrary(L"ole32.dll");
if (!mod) {
NtYieldExecution();
}
}
if (mod) {
pCreateStreamOnHGlobal = (P_CreateStreamOnHGlobal)
GetProcAddress(mod, "CreateStreamOnHGlobal");
}
else {
Sxs_Error(0x88, status);
return FALSE;
}
if (*lpManifestText) {
args.ManifestStream = Sxs_CreateStreamFromBuffer(lpManifestText);
if (! args.ManifestStream)
ok = FALSE;
} else
ok = FALSE;
if (ok && *lpConfigPath && *lpConfigText) {
args.ConfigPath = lpConfigPath;
args.ConfigStream = Sxs_CreateStreamFromBuffer(lpConfigText);
if (! args.ConfigStream)
ok = FALSE;
}
if (*lpManifestText) {
args.ManifestStream = Sxs_CreateStreamFromBuffer(lpManifestText);
if (! args.ManifestStream)
ok = FALSE;
} else
ok = FALSE;
if (ok && *lpConfigPath && *lpConfigText) {
args.ConfigPath = lpConfigPath;
args.ConfigStream = Sxs_CreateStreamFromBuffer(lpConfigText);
if (! args.ConfigStream)
ok = FALSE;
}
if (Sxs_WindowsVista || Sxs_Windows7 || Sxs_Windows8 || Sxs_Windows10) {
WCHAR *ptr = LangNames;
while (*ptr) {
if (*ptr == L'_')
*ptr = L'\0';
++ptr;
}
memzero(&vista_args, sizeof(vista_args));
vista_args.ArchId = args->ArchId;
vista_args.LangNames = LangNames;
vista_args.StoreDir = args->StoreDir;
vista_args.ManifestStream = args->ManifestStream;
vista_args.SourcePath = args->SourcePath;
vista_args.Two = args->Two;
vista_args.ConfigStream = args->ConfigStream;
vista_args.ConfigPath = args->ConfigPath;
if (pSxsGenerateActivationContext((void *)&vista_args)) {
if (Sxs_WindowsVista)
args->hSection = vista_args.hSectionVista;
else if (Sxs_Windows7)
args->hSection = vista_args.hSectionWin7;
else if (Sxs_Windows8 || Sxs_Windows10)
args->hSection = vista_args.hSectionWin8;
else
args->hSection = NULL;
if (! args->hSection) {
// in the esoteric case where pSxsGenerateActivationContext
// returns success but zero section, we want to signal to
// Sxs_CallService in core/dll/sxs.c to try alternate call
args->hSection = (HANDLE)(ULONG_PTR)-1;
}
} else
args->hSection = NULL;
} else {
if (! pSxsGenerateActivationContext(args))
args->hSection = NULL;
}
if (Sxs_WindowsVista || Sxs_Windows7 || Sxs_Windows8 || Sxs_Windows10) {
WCHAR *ptr = LangNames;
while (*ptr) {
if (*ptr == L'_')
*ptr = L'\0';
++ptr;
}
memzero(&vista_args, sizeof(vista_args));
vista_args.ArchId = args->ArchId;
vista_args.LangNames = LangNames;
vista_args.StoreDir = args->StoreDir;
vista_args.ManifestStream = args->ManifestStream;
vista_args.SourcePath = args->SourcePath;
vista_args.Two = args->Two;
vista_args.ConfigStream = args->ConfigStream;
vista_args.ConfigPath = args->ConfigPath;
if (pSxsGenerateActivationContext((void *)&vista_args)) {
if (Sxs_WindowsVista)
args->hSection = vista_args.hSectionVista;
else if (Sxs_Windows7)
args->hSection = vista_args.hSectionWin7;
else if (Sxs_Windows8 || Sxs_Windows10)
args->hSection = vista_args.hSectionWin8;
else
args->hSection = NULL;
if (! args->hSection) {
// in the esoteric case where pSxsGenerateActivationContext
// returns success but zero section, we want to signal to
// Sxs_CallService in core/dll/sxs.c to try alternate call
args->hSection = (HANDLE)(ULONG_PTR)-1;
}
} else
args->hSection = NULL;
} else {
if (! pSxsGenerateActivationContext(args))
args->hSection = NULL;
}
status = NtMapViewOfSection(
hSection, NtCurrentProcess(), &MappedBase,
0, 0, &ZeroOffset, &ViewSize, xViewShare,
MEM_PHYSICAL, PAGE_READONLY);
if (NT_SUCCESS(status)) {
UCHAR *data = HeapAlloc(GetProcessHeap(), 0, ViewSize);
if (data) {
memcpy(data, MappedBase, ViewSize);
*rsp_len = (ULONG)ViewSize;
*rsp_data = data;
}
NtUnmapViewOfSection(NtCurrentProcess(), (void *)MappedBase);
}
CloseHandle(hSection);
status = NtMapViewOfSection(
hSection, NtCurrentProcess(), &MappedBase,
0, 0, &ZeroOffset, &ViewSize, xViewShare,
MEM_PHYSICAL, PAGE_READONLY);
if (NT_SUCCESS(status)) {
UCHAR *data = HeapAlloc(GetProcessHeap(), 0, ViewSize);
if (data) {
memcpy(data, MappedBase, ViewSize);
*rsp_len = (ULONG)ViewSize;
*rsp_data = data;
}
NtUnmapViewOfSection(NtCurrentProcess(), (void *)MappedBase);
}
CloseHandle(hSection);
// win7
StartRpcEptMapper() {
wcscpy(ServiceName2, L"RpcEptMapper");
swprintf(EventName, SBIE_BOXED_ L"ServiceInitComplete_%s", ServiceName2);
hEvent = CreateEvent(NULL, TRUE, FALSE, EventName);
if (! hEvent)
return FALSE;
ok = Service_Start_ServiceMain(
ServiceName2, L"rpcepmap.dll", "ServiceMain", TRUE);
}
wcscpy(ServiceName, L"RPCSS");
ok = Service_Start_ServiceMain(
ServiceName, L"rpcss.dll", "ServiceMain", TRUE);
// win7
StartRpcEptMapper() {
wcscpy(ServiceName2, L"RpcEptMapper");
swprintf(EventName, SBIE_BOXED_ L"ServiceInitComplete_%s", ServiceName2);
hEvent = CreateEvent(NULL, TRUE, FALSE, EventName);
if (! hEvent)
return FALSE;
ok = Service_Start_ServiceMain(
ServiceName2, L"rpcepmap.dll", "ServiceMain", TRUE);
}
wcscpy(ServiceName, L"RPCSS");
ok = Service_Start_ServiceMain(
ServiceName, L"rpcss.dll", "ServiceMain", TRUE);
BOOL my_StartServiceCtrlDispatcherW(
const LPSERVICE_TABLE_ENTRY lpServiceTable)
{
LPTSTR parms[1];
LPSERVICE_MAIN_FUNCTION ServiceMain;
SERVICE_TABLE_ENTRY *entry = lpServiceTable;
while (entry->lpServiceName) {
ServiceMain = entry->lpServiceProc;
parms[0] = entry->lpServiceName;
ServiceMain(1, parms);
++entry;
}
return 1;
}
BOOL my_StartServiceCtrlDispatcherW(
const LPSERVICE_TABLE_ENTRY lpServiceTable)
{
LPTSTR parms[1];
LPSERVICE_MAIN_FUNCTION ServiceMain;
SERVICE_TABLE_ENTRY *entry = lpServiceTable;
while (entry->lpServiceName) {
ServiceMain = entry->lpServiceProc;
parms[0] = entry->lpServiceName;
ServiceMain(1, parms);
++entry;
}
return 1;
}
NtAlpcConnectPortEx --> Ipc_StartServer
ncalrpc:[lsasspirpc] -- \RPC Control\lsasspirpc -- \Sandbox\DefaultBox\Session_3\RPC Control\lsasspirpc
ncalrpc:[lsapolicylookup] -- \RPC Control\lsapolicylookup -- \Sandbox\DefaultBox\Session_3\RPC Control\lsapolicylookup
ncalrpc:[lsapolicylookup] -- \RPC Control\actkernel -- \Sandbox\DefaultBox\Session_3\RPC Control\actkernel
NtAlpcConnectPortEx --> Ipc_StartServer
ncalrpc:[lsasspirpc] -- \RPC Control\lsasspirpc -- \Sandbox\DefaultBox\Session_3\RPC Control\lsasspirpc
ncalrpc:[lsapolicylookup] -- \RPC Control\lsapolicylookup -- \Sandbox\DefaultBox\Session_3\RPC Control\lsapolicylookup
ncalrpc:[lsapolicylookup] -- \RPC Control\actkernel -- \Sandbox\DefaultBox\Session_3\RPC Control\actkernel
SERVICE_NAME: Rpcss
TYPE : 20 WIN32_SHARE_PROCESS
START_TYPE : 2 AUTO_START
ERROR_CONTROL : 1 NORMAL
BINARY_PATH_NAME : C:\Windows\system32\svchost.exe -k rpcss -p
LOAD_ORDER_GROUP : COM Infrastructure
TAG : 0
DISPLAY_NAME : Remote Procedure Call (RPC)
DEPENDENCIES : RpcEptMapper
: DcomLaunch
SERVICE_START_NAME : NT AUTHORITY\NetworkService
SERVICE_NAME: Rpcss
TYPE : 20 WIN32_SHARE_PROCESS
START_TYPE : 2 AUTO_START
ERROR_CONTROL : 1 NORMAL
BINARY_PATH_NAME : C:\Windows\system32\svchost.exe -k rpcss -p
LOAD_ORDER_GROUP : COM Infrastructure
TAG : 0
DISPLAY_NAME : Remote Procedure Call (RPC)
DEPENDENCIES : RpcEptMapper
: DcomLaunch
SERVICE_START_NAME : NT AUTHORITY\NetworkService
Add_LL_Entry(lingers, &linger_count, _SandboxieDcomLaunch);
Add_LL_Entry(lingers, &linger_count, _SandboxieCrypto);
Add_LL_Entry(lingers, &linger_count, _SandboxieBITS);
Add_LL_Entry(lingers, &linger_count, _SandboxieWUAU);
Add_LL_Entry(lingers, &linger_count, _wuauclt);
Add_LL_Entry(lingers, &linger_count, _TrustedInstaller);
Add_LL_Entry(lingers, &linger_count, _tiworker);
Add_LL_Entry(lingers, &linger_count, _SandboxieDcomLaunch);
Add_LL_Entry(lingers, &linger_count, _SandboxieCrypto);
Add_LL_Entry(lingers, &linger_count, _SandboxieBITS);
Add_LL_Entry(lingers, &linger_count, _SandboxieWUAU);
Add_LL_Entry(lingers, &linger_count, _wuauclt);
Add_LL_Entry(lingers, &linger_count, _TrustedInstaller);
Add_LL_Entry(lingers, &linger_count, _tiworker);
heventRpcSs = CreateEvent(0, FALSE, FALSE, NULL);
HANDLE ThreadHandle = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ProcessStartMonitor, NULL, 0, NULL);
if (ThreadHandle)
CloseHandle(ThreadHandle);
heventRpcSs = CreateEvent(0, FALSE, FALSE, NULL);
HANDLE ThreadHandle = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ProcessStartMonitor, NULL, 0, NULL);
if (ThreadHandle)
CloseHandle(ThreadHandle);
for (i = 0; ; ++i) {
rc = SbieApi_QueryConfAsIs(
NULL, L"StartService", i, image, sizeof(WCHAR) * 120);
if (rc != 0)
break;
SbieDll_StartBoxedService(image, TRUE);
}
for (i = 0; ; ++i) {
rc = SbieApi_QueryConfAsIs(
NULL, L"StartService", i, image, sizeof(WCHAR) * 120);
if (rc != 0)
break;
SbieDll_StartBoxedService(image, TRUE);
}
HOOK_WIN32(CreateFileMappingW) --> my_CreateFileMappingW()
Name: Global\ComPlusCOMRegTable
ComPlusCOMRegTable = CreateFileMapping(
INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE | SEC_COMMIT,
0, (PAGE_SIZE * 2), ComPlusCOMRegTable_Name);
_FX HANDLE my_CreateFileMappingW(
HANDLE hFile,
LPSECURITY_ATTRIBUTES lpAttributes,
DWORD flProtect,
DWORD dwMaximumSizeHigh,
DWORD dwMaximumSizeLow,
LPCWSTR lpName)
{
typedef HANDLE (__stdcall *P_CreateFileMappingW)(
HANDLE hFile,
LPSECURITY_ATTRIBUTES lpAttributes,
DWORD flProtect,
DWORD dwMaximumSizeHigh,
DWORD dwMaximumSizeLow,
LPCWSTR lpName);
HANDLE handle = 0;
if (lpName && _wcsicmp(lpName, ComPlusCOMRegTable_Name) == 0)
handle = ComPlusCOMRegTable;
if (! handle) {
handle = ((P_CreateFileMappingW)__sys_CreateFileMappingW)(
hFile, lpAttributes, flProtect,
dwMaximumSizeHigh, dwMaximumSizeLow, lpName);
}
return handle;
}
HOOK_WIN32(CreateFileMappingW) --> my_CreateFileMappingW()
Name: Global\ComPlusCOMRegTable
ComPlusCOMRegTable = CreateFileMapping(
INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE | SEC_COMMIT,
0, (PAGE_SIZE * 2), ComPlusCOMRegTable_Name);
_FX HANDLE my_CreateFileMappingW(
HANDLE hFile,
LPSECURITY_ATTRIBUTES lpAttributes,
DWORD flProtect,
DWORD dwMaximumSizeHigh,
DWORD dwMaximumSizeLow,
LPCWSTR lpName)
{
typedef HANDLE (__stdcall *P_CreateFileMappingW)(
传播安全知识、拓宽行业人脉——看雪讲师团队等你加入!
最后于 2025-5-27 09:05
被一半人生编辑
,原因: