1. 引言
NSA的一系列SMB 漏洞利用的背后,最后都会使用到双脉冲星(DoublePulsar)后门。双脉冲星后门是一个无文件内核级的SMB后门。
2. 双脉冲星后门的安装过程
双脉冲星后门是通过内核级的shellcode来安装的(在x86 系统上,shellcode一般从地址0xffdff1f1开始)。我们来围观一下这段shellcode.
Shellcode的开始就是很有意思的一段代码:
这段代码咋看有些多余, jz的跳转是永远不会被执行的。事实上,这段代码是用来测试系统是否为64 位系统。
在64 位系统上,上述字节则反汇编为
这样一来, jz 总是会跳转。
这段代码测试CPU是32位还是64位,根据测试结果跳到不同的shellcode代码。
本文以32位系统为例进行分析。
紧接着,进入如下代码:
这段代码又是个什么鬼呢?这段代码的作用是hook SYSENTER, 具体可参见 [1]。下次执行SYSENTER指令的时候,控制会转到ebx 17 的代码,即地址 FFDFF221。
跟进FFDFF221 代码,
这段代码过河拆桥,将上面SYSENTER的Hook摘掉。随后执行
FFDFF39A这个函数正是试图安装双脉冲星后门的函数。这个函数篇幅略长,但目的非常清晰,替换 srv.sys!SrvTracation2DispatchTable 表中 0xe项函数指针 (即表偏移0x38)。替换后的代码即为SMB的后门函数。
在ffdff51e处下断点,就可以非常清楚的观察到:
这里ebx就是srv!SrvTransaction2DispatchTable的地址, ebx 0x38就是0xe项的函数指针。eax为替换后的后门函数地址。
3. 双脉冲星后门功能分析
根据上面的分析,双脉冲星后门被成功的安装到了srv!SrvTransaction2DispatchTable 的0xe项。那么这个后门如何利用呢? 攻击者只需要构造SMB_COM_TRANSACTION2 请求(0x32),并指定Subcommand 为SESSION_SETUP(0xe)这个无效的值,这时,SrvTransaction2DispatchTable的0xe项派遣函数,也就是被替换的后门函数将被调用。SMB 请求报文如下图所示
下面分析一下后门函数的功能。
这个函数可谓整个双脉冲星后门的精华所在,里面使用了一系列令人眼花缭乱的技巧。
函数开始调用了3个不同的函数:
sub_FFDFF930
sub_FFDFF89F
sub_FFDF8E0
下面对这三个函数逐一进行分析
先看第一个函数sub_FFDFF930。
这个函数虽然代码非常简单,但要深入理解却也着实不易,主要是一些用到的数据结构并没有公开,只能靠大量的逆向工作来进行猜测。该函数的参数是传给SrvTransaction2DispatchTable 中Dispatch函数的参数,参数类型没有公开,权且称其为CONTEXT。在经过大量的逆向分析后,结论如下:
CONTEXT的 某个偏移的地方存放着一个指针Ptr (进一步的深入分析发现,这个指针其实是个指向IRP的指针,应该就是SMB请求的IRP),这个指针的值正好是CONTEXT的起始地址 Size。所以只需从CONTEXT的起始地址开始步长为4字节递增搜索,就可以找到这个指针。
如下图所示。
找到这个地址后,就可以在此基础上推算出 SMB响应报文的地址以及SMB请求报文中Parameter存放的地址。
这么看似费了一番周折,但主要目的是为了避免对于不同平台需要对SMB响应和SMB请求报文的Parameter在结构中的偏移进行硬编码。
SMB相应 报文的起始地址存放在ebp 44处,而SMB请求报文的Parameter则存放在ebp 38处。
接下来看第二个函数 sub_FFDFF89F:
这个函数更加简单,用来初始化会话用的密钥运算操作。
最后,看第三个函数,这个函数对SMB 后门请求报文做一些简单的合法性检查,其中又使用了一些技巧来找到内核态的指针,来验证指针的有效性。其次,它对 ParameterCount 和TotalParameterCount值进行检测,二者都必须是0xc。这个函数的存在,体现了这段shellcode在稳定性方面做了一些周全的考虑。
三个函数执行完后,调用了FFDFF88B 这个函数,根据函数的计算结果,会跳到不同的分支。
这个函数伪代码如下:
这个函数就是将dword的四个字节加起来, 结果转化成一个字节。
那么它的输入是什么呢,经调试分析,输入就是SMB请求的 Timeout 字段。
也就是说,后门函数将SMB的Timeout请求字段解码,把解码的结果跟0x23,0x77,0xc8比较作为后门的命令。
当结果为0x23时,后门函数用来检查后门是否已经安装,即PING命令。
当结果为0x77时,后门函数用来进一步执行传入的shellcode。
当结果为0xc8时,后门函数用来卸载后门。
下面看一个具体的例子:
这个请求中Timeout的值为 93 89 07 00: 0x93 0x89 0x07 00= 0x123,取最后一个字节,结果为0x23,根据上面的分析,这是PING命令。
在处理PING 命令时,我们看到,把计算出来的密钥放在了SMB响应报文的Signature中,已备后面发送shellcode时加密使用。
最后一段PING 命令处理代码:
这里会根据不同的状态将响应报文的MID(Multiplex ID) 加上一个值(正常情况下,响应的MID必须和请求中的MID值一致)。MID增量值具体含义见下表:
下图是一个PING命令成功的例子,
请求,
可见,请求中的MID为66(0x0042)
响应:
响应中的MID值为82(0x0052)。两者MID差值为0x0052-0x0042 = 0x10.
在做完这一切后,将控制跳转到原来的派遣函数,以便回复SMB请求。
4. 结束语
本文详细分析了作为NSA第七种武器的双脉冲星后门的代码。该代码构思相当巧妙,隐蔽性很强。作者对Windows 代码, 尤其是SMB部分的代码可谓相当熟悉。整个Shellcode考虑到了通用性,稳定性,犹如做工精良的武器一般。而这样的内核级后门,对入侵者无疑是敞开了一扇大门,几乎可以为所欲为。
5. 参考文献
- Rootkits: Subverting the Windows Kernel.(pp94-95)
- https://zerosum0x0.blogspot.com.au/2017/04/doublepulsar-initial-smb-backdoor-ring.html
- http://blog.checkpoint.com/2017/05/25/brokers-shadows-analyzing-vulnerabilities-attacks-spawned-leaked-nsa-hacking-tools/