Chromium-sandbox-ThreadProcess-analysis
本篇是sandbox源码剖析的第十五篇,主要分析了子系统ThreadProcess的三大组件。
Target进程执行9个进程线程相关API时,应用于此的三大组件进行了一些处理。该子系统和Filesystem类似,但9个API却分成了3个类别,具体内容请参考本文的详细解读。
阅读本篇前,请先阅读前面所有章节。
想要流程的阅读本系列你需要以下几个条件: 1. 较高水平的C++编码能力(至少通读C++ Primer 5th,刷过课后题,有一定编码量)。 2. 熟悉Windows API编程,尤其是安全相关的内容。 3. 对二进制安全有一定了解,熟悉各类型安全漏洞成因、漏洞缓解措施及bypass手法。
chromium-sandbox-ThreadProcess-analysis
上一篇分析了Filesystem子系统,通过对filesystem子系统三大组件的分析,我们已经理清了完整的脉络。本篇我们采用相同的方式,长驱直入,分析ThreadProcess子系统。
初始化设置
在分析三大组件前,先看看初始化时都置办了哪些物件。
TopLevelDispatcher::TopLevelDispatcher
TopLevelDispatcher
的构造器是在PolicyBase
的构造器中调用的,构造器内部我们已经非常熟悉了,它会将ipc_targets_
指针数组的每一个成员指向正确的dispatcher对象。而对于ThreadProcess子系统来说,这个dispatcher对象是一个ThreadProcessDispatcher
对象:
1 |
|
可以看到该子系统相关的IPC请求tag有6种,分别是NtOpenThread, NtOpenProcess, CreateProcess, NtOpenProcessToken, NtOpenProcessTokenEx, CreateThread。
PolicyBase::AddTarget
PolicyBase
的Rules是预先由操纵者设计好的,当在BrokerServices::SpawnTarget
中调用PolicyBase::AddTarget
时,会进行一大堆关键操作,此前我们已经分析过数个了。
1 |
|
LowLevelPolicy::Done
操作没什么好说的,我们感兴趣的是SetupAllInterceptions
:
1 |
|
上一篇分析的FilesystemDispatcher
在此处对5个系统调用进行了Interceptions的安装。类比一下,其他的子系统应该也差不多。我们先看看ThreadProcessDispatcher::SetupService
:
1 |
|
再看看此后的关键call——SetupBasicInterceptions
:
1 |
|
9个函数中有3个是不需要IPC请求的,其余6个仅有CreateProcess在dispatcher的SetupService
中进行了设置,其他都是由SetupBasicInterceptions
部署的。除了没有IPC请求的3个以及需要判定is_csrss_connected
的CreateThread,其他的几个为什么不放入Dispatcher中的SetupService
处理,我也不是很懂,字面的意思是因为它们无需实际的policy,但另一方面,dispatcher和policy并没有直接关联。
或许继续分析会找到答案也说不定。
policy
和filesystem子系统大同小异,policy也提供了一个最为重要的接口GenerateRules
以及6个在dispatcher中调用的action。
1 |
|
GenerateRules
也是一个德行:
1 |
|
实际上在GenerateRules
中就可以发现,对于ThreadProcess子系统来说,所有的规则都只能限制CreateProcess。回想SetupService
,它内部也仅对CreateProcess进行了拦截器的部署,其他的5个IPC请求的tag,由于没有实际的policy参数条件约束,所以设计上并未在此处进行拦截器部署。另外5个拦截器的部署是在一个全局的SetupBasicInterceptions
中处理的。
所以,从设计者的角度来讲,dispatcher的SetupService
和policy的GenerateRules
有一定程度的耦合。
6个action函数先不关心,继续看dispatcher。
dispatcher
1 |
|
构造器实际上也颇为重要,实际上他是在PolicyBase::AddTarget
首次GetTarget
时调用到的(还记得各子系统static局部dispatcher对象吗):
1 |
|
Server端IPC的处理机制本篇就不再说了,我们直接来看看这些请求处理的callback函数是如何处理的:
1 |
|
另外两个kernel32.dll的函数则不太一致:
1 |
|
再次回到policy组件,最为关心的当属进行了Rule审判的CreateProcessWAction
:
1 |
|
这个helper函数实际上就是一层封装:
1 |
|
其他的5个action,就仅仅是封装罢了:
1 |
|
IPC请求处理的后半段相关部分已经分析过了,剩下的就是回去看看target client端是如何发起请求的了。
interceptions
target在调用以上9个WIN
API或系统调用时,实际上调用到的是broker或target自己为target部署的拦截器函数。其中系统调用的拦截器由broker为target部署,而除了ntdll的其他dll(这里仅有kernel32.dll)中函数的导入表(Eat)拦截器是target自己部署的(broker会在AddToPatchFunction
和AddUnloadModule
后把它们传给target,sidestep和smart_sidestep虽有组件但目前尚未用到)。
对于ThreadProcess子系统的拦截器来说,一共有3种:
- broker部署的4个系统调用拦截器
- target自身部署的2个kernel32.dll的导入表拦截器
- 无需IPC请求的3个系统调用拦截器
其中前两种都在process_thread_interceptions.cc中定义,后一种则独立开来,在policy_target.cc中定义。policy_target.cc中不仅包含这3个interceptions,还包含一个我们上一篇分析过的函数QueryBroker
。
我们先看第一种,以TargetNtOpenThread
为例:
1 |
|
第二类有两个,TargetCreateProcess
和TargetCreateThread
,前者有ASCII和Unicode两个版本,且它是有Rule可match的,后者一无所有:
1 |
|
中规中矩的TargetCreateThread
:
1 |
|
第三种就有点意思了,我们都展开看看:
1 |
|
另外两个是和thread token相关:
1 |
|
到此,我们就缕清了ThreadProcess子系统的相关内容,尽管和filesystem子系统有一定的不同,但整体的架构是一致的,只是具体的应用因场景而有所差异。