英文原文:Analysis of the FBI Tor Malware
一、背景
Tor(The Oninon Router)提供一个匿名交流网络平台,它使得用户在浏览网页或访问其它网络服务时不会被跟踪。作为该网络的一部分即所谓的“暗网”(darknet),是指只能通过 Tor 网络访问的服务器群组,这些服务器提供包括社区论坛、电子邮件等多种服务。虽然提供这些服务都是无恶意的,初衷是用来关注侵犯人权问题,但是由于匿名的原因吸引了很多有犯罪意图的人,比如传播儿童色情。事后执法部门也不能追踪到犯罪者的源 IP 地址。
2013 年,在“暗网”服务器上发现了一款恶意软件,它利用特定 Web 浏览器上的安全漏洞在用户电脑上执行一段代码。该代码收集一些用户信息,发往弗吉尼亚州的服务器,之后自毁。就恶意软件的特征来讲,它没有明显的恶意意图。初步推断是 FBI 植入,他们在弗吉尼亚州有办事处,曾经也派专人开发过恶意程序,可能是他们创建了它—现在看来是真的。
二、对 Shellcode 的逆向分析
1、漏洞利用
漏洞利用代码用 javascript 编写,利用一个出名的 firefox 浏览器的特定版本(Tor 网络预装的 firefox)的漏洞。该漏洞利用代码经过了模糊处理,但通过快速扫描可以看到一长串十六进制字符,这些字符是 shellcode 的前几个标志性字节,即 call 操作码(shellcode 经常以一个 jump 或 call 开始,因此知道了这些操作码使得识别 shellcode 变得容易起来)。
我不会在这里分析这个漏洞,但是要看一下这个 shellcode。
首先,让我们用一些基本的 shellcode 原则设定一个场景。
2、位置无关代码
Shellcode 的成功执行经过了独一无二的挑战,因为它是直接注入到一个进程而不是由 Windows 加载器加载。因此,我们不知道 shellcode 位于内存中的什么地方,更关键的是,不知道标准的 windowsAPI 函数位于什么地方(而通常情况下,Windows 加载器会告诉一个程序这些信息)。
因此,我们必须使用一系列技巧去获得这个信息。FBI 恶意程序用了一个常用的技巧去找出它的内存地址:
call start
start:
pop ebp
call 函数将执行程序移动到 start 标签处,同时将程序当前执行的位置压入堆栈中(这样我们稍后可以从 call 函数返回)。
在此,我们将要用这个值,从栈里窃取位置,堆栈弹出的值保存到 ebp 寄存器。我们现在知道了下一条指令的地址,那么就可以用它来访问跟我们的 shellcode 相关的数据。
三、定位 Windows API
因为正常情况下 Windows 加载器会加载 Windows API 的位置到我们的程序,所以我们不奢望运行一个 shellcode 时能够知道程序的位置信息。找出 API 函数惯用的方法是查看 FS 段寄存器所指的线程信息块(thread information block)。我们能够通过这个结构体去定位被我们 shellcode 宿主程序加载的 DLLs,然后利用这些 DLL 的输出直到找到目标函数为止。当然这个过程是很乏味的,所以,FBI 这个 shellcode 使用了一个库,包含在 MetasploitFramwork 内,这是由 Stephen Fewer 写的一个函数解析器。它的工作原理如下:
push arguments
. . .
push FUNCTIONHASH
call<Stephen’sResolver>
这个函数的哈希值是由一个简单的 hash 算法生成,以我们调用函数的名称命名。这样做的目的不是为了混淆代码(尽管它达到这个目的),但只允许我们用一个 32 位的 DWORD 来调用此函数,而不是一个长型字符串(shellcode 空间往往是有限的)。
值得庆幸的是,我们自己可以计算出 hash 值,或者用别人生成的查找表。
四、开始
如果我们对 shellcode 的开始进行反汇编,如下图:
我们一旦计算出指向 API 解析器的 ebp 寄存器值,我们就可以在 windows 的 API 进行哈希调用前获取其十六进制数。如此,如果在查找表里查找到那个值,在那个值附近查找调用的函数,并且添加一些注释,如下图:
这段代码执行完整性检查,通过用 GET 开始的 HTTP 请求头部信息以确保 shellcode 安全运行。然后调用 Windows API 函数 LoadLibrary()载入两个动态链接库:ws2_32.dll(用于互联网通信的 Windows 套接字库)和 iphlpapi.dll(WindowsIP 辅助库)。
五、连接到 HTTP 服务器
在必要的库文件都加载完之后,shellcode 将执行下图中的操作:
再一次,用相同的步骤,用哈希值查找一个 Windows API 函数:connect ()函数。我们可以看见,在[ebp +0x2e1]位置的数据作为一个参数传递给 connect ()函数—从手册我们知道,那个参数是一个 sockaddr 结构体(sockaddr structure)。我们知道 ebp 寄存器指向我们在内存中的地址,使用那个地址,再加上偏移量,我们就能定位出那些数据在内存 0x2E8 处(ebp=0×7)。
因此,我们在分析 sockaddr 之前,先给这些代码添加一些注释,命名一些内存偏移地址,如下图:
这个 eax 寄存器保存着调用 connect ()函数的返回值,如果这个值为0(来自微软用户手册)表示 connect ()调用成功。但是我们成功连接到哪儿?如果我们现在添加一些注释到我们之前的反汇编文件,基于我们在微软用户手册中能查到的关于 sockaddr 结构体的信息,我们可以这样添加注释,如下图:
通过对 IP 地址进行 whois 快速查询,只得到很少信息。如下图:
六、收集用户信息
接下来,这个恶意软件尝试获得 windows 主机名—通常情况下这是 windows 机器的名字。这可能有助于确认嫌疑犯和确认他们没有逮捕错人。
其次,它枚举了活跃主机的 hostname 和 IP 地址。
使用 SendARP ()函数来发现网络中所有电脑的 MAC 地址。有一些“恰当”的方式做到这样,但是 shellocode 只能获得有限的空间去完成这些事。MAC 地址将用户与一张特定的网卡绑定,于是可以通过这些网卡的供应链来追踪用户。
最后,它要构建 HTTP 头部信息,将 MAC 地址放进 Cookie 字段,用户的主机名放进 Host 字段,并且要以 GET 请求方式发送到 http://65.222.202.54/05cea4de-951d-4037-bf8f-f69055b279bb。这些十六进制数字的意义不清楚,它们可能是任意选择或链接一个用户到特定的接入服务器。
七、最后阶段
这个 shellcode 最后阶段的唯一目的就是在该 shellcode 结束时运行更多的 shell 代码—它这样做的方式稍微有点迂回,我也不知道为什么这样,也许是一次粗略的尝试。
那么,最后一歩要怎么做。首先,它利用一些字符串长度操作找出一些被嵌入在其他所有数据区的代码。那些代码计算出我们的 HTTP 请求字符串结束的位置,跳过在 shellcode 结尾处的所有的无效的空操作指令,然后跳到那里。那里是哪里?谁知道!我被告知有更多的 shellcode(这不重要),但是我已经没有时间来调试这个漏洞并获得它。
构建头部,然后跳转到头部结尾处。
查找 http 头部结尾处的无效指令并且跳过它们。
八、运行代码
到目前为止,我以完全静态的方式分析了这些代码—主要是为了完整性。通过运行这些代码能够更快速的分析它们,同时可以验证我们的分析是否正确。既然这段恶意代码没有任何破坏系统的行为,因此我们可以安全的在真机上运行它。于是运行它并观察它发送给 FBI 的确切数据。因为 shellcode 不是一个 exe 可执行文件,我需要一个 shellcode 加载器去运行它—-它们快速的分配需要的内存,加载 shellcode 并跳转到该处。这是加载 shellcode 需要做的—-在调用真正的 shellcode 之前会自动断开。
然后我们启动调试器跨步执行到调用 cnnect()函数。我们不得不把这个 shellcode 的目标指向另一台我们自己的机器,便于观察运行结果。因此,我将让他指向 ip 地址为 192.168.0.254 的 77 端口,然后在这个机器上运行 netcat 程序抓取数据。在下图代码暂停的箭头所指处,就是早期通过 patch 方式来修改 sockaddr 结构体。
然后我们继续跨步执行到调用 send()函数,执行它,之后我们能看见在 netcat 终端的输出,它将输出它收到的所有数据—显示的那些数据原本是发给 FBI。你可以看到,cookie 里面的 ID 包含了我的 MAC 地址,Host 头部包含了我的 desktop 名。
最后,我们跨步执行到最后阶段—最后的空操作可能是用来注入更多的已经提取的 shellcode。在那个十六进制查看器窗口可以看见,我们构造的那个 HTTP 请求已经发出。
九、结论
这个恶意软件从用户浏览器发送确认信息给攻击机,然后使用户 firefox 浏览器崩溃。就复杂性而言,它没有很明显的特别之处,也没有使用一些大家不知道的新技术。
如果这个恶意软件作者是 FBI,那么他们需要去回答一些很严肃的问题。这些恶意程序被植入到非美国的服务器上,并攻击利用全球用户的浏览器(他们当中很多人是无辜的)他们这样做甚至可能会得到法律授权?我不这么认为。当有人告发时 FBI 是否需要出示他们曾经得到过法律授权的证据?未必。我希望他们会依据用户的电脑内发现的证据和在收到起诉时取得的证据—-尽管最初的搜索授权可能很不靠谱。不管怎么说,我毕竟不是一个律师。