NSA的第七种武器|双脉冲星(DoublePulsar) 后门详细分析

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. 参考文献

  1. Rootkits: Subverting the Windows Kernel.(pp94-95)
  2. https://zerosum0x0.blogspot.com.au/2017/04/doublepulsar-initial-smb-backdoor-ring.html
  3. http://blog.checkpoint.com/2017/05/25/brokers-shadows-analyzing-vulnerabilities-attacks-spawned-leaked-nsa-hacking-tools/

原文发布于微信公众号 - FreeBuf(freebuf)

原文发表时间:2017-07-05

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏美团技术团队

高性能队列——Disruptor

背景 Disruptor是英国外汇交易公司LMAX开发的一个高性能队列,研发的初衷是解决内存队列的延迟问题(在性能测试中发现竟然与I/O操作处于同样的数量级)。...

613110
来自专栏菩提树下的杨过

ZooKeeper 笔记(6) 分布式锁

  目前分布式锁,比较成熟、主流的方案有基于redis及基于zookeeper的二种方案。   大体来讲,基于redis的分布式锁核心指令为SETNX,即如果目...

25480
来自专栏有趣的django

面试题目及答案

1 Python的函数参数传递 看两个例子: a = 1 def fun(a): a = 2 fun(a) print a # 1 a = [] de...

1.2K90
来自专栏不会写文章的程序员不是好厨师

为Hibiscus写文之定时器篇——HashedWheelTimer

去年一年在简书大约写了25篇,在公司内网写了5篇博客。今年定个小目标吧,在简书产出高质量的博客50篇,加油!

20320
来自专栏积累沉淀

Java批处理

批处理 JDBC对批处理的操作,首先简单说一下JDBC操作sql语句的简单机制。 JDBC执行数据库操作语句,首先需要将sql语句打包成为网络字...

49850
来自专栏蜉蝣禅修之道

EJBCA使用之注册用户及创建证书

30040
来自专栏kevindroid

android7.0下retrofit框架不断GC的问题

18520
来自专栏分布式系统进阶

Influxdb的Meta data分析

Influxdb定义了一个Service:Precreator Serivec(services/precreator/service.go),实现比较简单,周...

14320
来自专栏阿杜的世界

《七周七并发模型》阅读笔记(一)一、线程与锁——第一天二、线程与锁——第二天三、线程与锁——第三天

线程与锁模型其实是对底层硬件运行过程的形式化,这种形式化既是该模型最大的优点,也是它最大的缺点。我们借助Java语言来学习线程与锁模型,不过内容也适用于其他语言...

13920
来自专栏Android机器圈

Java设计模式总汇二(小白也要飞)

PS:上一篇我介绍了适配器设计模式、单例设计模式、静态代理设计模式、简单工厂设计模式,如果没有看过第一篇的小火鸡可以点这个看看http://www.cnblog...

35290

扫码关注云+社区

领取腾讯云代金券