-
-
[原创]Sandboxie隐形屏障:解密COM隔离机制
-
发表于: 2025-5-25 20:16 813
-
时镜过迁,转眼即逝,基于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;
}
#include <Windows.h>
#include <comdef.h>
#include <taskschd.h>
#include <iostream>
#include <rpc.h>
#pragma comment(lib, "ole32.lib")
#pragma comment(lib, "rpcrt4.lib")
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
"fd7K9s2c8@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);
}
#include <Windows.h>
#include <comdef.h>
#include <taskschd.h>
#include <iostream>
#include <rpc.h>
#pragma comment(lib, "ole32.lib")
#pragma comment(lib, "rpcrt4.lib")
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
"fd7K9s2c8@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)(
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课
赞赏
- [原创]Sandboxie隐形屏障:解密COM隔离机制 814
- [原创]eBPF初学者编码实践 4587
- Windows驱动编程之NDIS(VPN) 18996
- [讨论] 有关Windows 13484
- [分享]Windows驱动开发初学者注意事项 16452