在McAfee Labs,我们最近观察到了Dorkbot僵尸网络的一个新变体。Dorkbot是一个臭名昭著的僵尸网络,与2011年4月首次被发现,使用的攻击手段包括后门植入,密码窃取和其他恶意行为。Dorkbot的传播途径也非常广泛,包括了USB设备、IM客户端、社交网络、电子邮件,还有隐蔽式下载。Dorkbot的主要攻击目标就是盗取用户凭证,以及各种能够识别个人身份的信息。它同时还能够在你的PC上,通过控制服务器安装更多的恶意程序。
不过最近,McAfee又发现了Dorkbot的新变种。恶意软件会从api[.]wipmania[.]net下载文件,api[.]wipmania[.]net是一个提供地理定位服务的站点。以下屏幕显示下载程序文件的网络流量。
下载的文件是使用Microsoft Visual C / C ++(2008版)编译的包装器。在我们的分析过程中,我们研究了包装文件并从恶意软件中提取了核心运行文件。
核心运行文件分析
核心运行文件也符合Microsoft Visual C ++编译规则,文件大小为48KB,具有虚拟机名称,注册表项,加密URL等相关的字符串,如下所示:
检测是否有虚拟运行环境
在执行任何恶意活动之前,恶意软件会执行检查虚拟环境的代码。它使用SetupDiGetDeviceRegistryPropertyA()API,这有助于检索指定的通用即插即用设备属性。检测代码段如下:
我们可以从上图中看到,Dorkbot所使用的第三个参数为0xC(SPDRP_FRIENDLYNAME),0xC可以检索设备是否为杀软设备,然后,使用与虚拟机相关的字符串检查运行设备名称,例如vbox,qemu,vmware和virtual hd。如果Dorkbot发现这些字符串中的任何一个,都表示恶意软件是在虚拟环境运行,则Dorkbot会立即终止恶意运行。
在检测完虚拟环境后,Dorkbot接下来会对当前运行目录进行检查,它会将文件运行路径与来自%appdata%的所需路径与GUID格式的文件夹名称(例如,%appdata%/ {GUID})进行比较。以下汇编代码就是检查文件路径的恶意代码段:
如果文件从不同的路径执行,Dorkbot会将该事件视为其第一次执行。在第一次执行时,Dorkbot会设置其运行环境,比如文件删除,注册表项等。Dorkbot会在%appdata%中创建一个目录并进行复制。Dorkbot会使用自定义函数和StringFromGUID2()API来获取GUID格式的文件夹名称。删除的文件和路径如下所示:
Dorkbot还创建了一个运行注册表项和任务,以便在系统上持续存在,使用上述删除文件设置执行文件路径。Dorkbot创建的注册表项如下所示:
Dorkbot还会创建一个任务,当用户登录时执行Dorkbot的恶意文件。
在成功安装注册表和计划任务后,Dorkbot使用process hollowing把其代码作为svchost.exe加入杀软的应用程序级白名单。
在将恶意代码注入到svchost.exe中后,Dorkbot会调用ZwQueueApcThread(),这是一个未记录的API,用于在当前远程线程上对异步过程调用(APC)进程(恶意软件的远程代码)进行排队,APC是在特定线程的上下文中异步执行的函数。ZwQueueApcThread允许调用者指定三个(包括线程例程)将传递给线程的参数,之后Dorkbot会发送与核心运行文件攻击地址不同的运行地址,从而与控制服务器进行连接(被查费以前的Dorkbot的组成包括命令服务器和控制服务器)。
注入的代码首先会运行重定位代码,这样注入的代码就会与新设备的基地址兼容。重定位代码后,为确保Dorkbot在系统中保持活动状态 ,即使在手动终止之后 ,Dorkbot还是会通过在已运行的进程中注入watchdog代码。
不过,研究人员却观察到的一个奇怪的现象,在注入watchdog代码之前,Dorkbot会检查进程名称TeamViewer和tv_w32.exe。如果恶意软件找到它们之一,它不会将其代码注入该进程。
Dorkbot会列举正在运行的进程,并尝试使用远程内存功能进行创建,读取和写入与内存相关的0x10047A标志及打开这些标志的权限。标志的定义如下:
watchdog代码具有一部分API调用的功能,不过Dorkbot需要对watchdog代码进行更新,使其与远程进程兼容。 Dorkbot还会更新代码中与API地址和恶意软件进程ID相关的占位符。除了watchdog代码以外,Dorkbot还会注入其文件路径,由代码引用,这样watchdog便可以重新启动进程。下图显示修改前后的watchdog代码:
注入的代码使用WaitForSingleObject()API来等待恶意软件进程的发生。它会把恶意软件的进程ID作为第一个参数,把等待时间作为第二个参数。如果恶意软件进程被终止,Dorkbot就会向WaitForSingleObject()发送信号,让注入的代码继续进行,具体过程是这样的:获取信号后,注入的代码执行CreateProcessW()API并再次创建恶意软件进程。
正如前面提到的, Dorkbot还会将恶意运行的文件路径注入到远程进程,以便在手动终止时重新启动恶意程序。但是,正如我们在前面看到的,我们找不到任何引用恶意软件文件路径的地址,这是因为恶意软件已将文件路径的地址作为参数传递给了CreateRemoteThread()API,并在EBP寄存器([EBP + 8])的帮助下引用代码。
网络连接
对于网络连接的运行,Dorkbot会包含加密URL的列表。Dorkbot会解密此列表并生成格式为 %s%u.%s的URL列表,该列表也存在于Dorkbot本身中。这里第一个“%s”表示字符串“con”,“%u”表示整数1和2,最后的“%s”表示已经解密的URL。因此,Dorkbot会在每个解密的URL前添加前缀con1.和con2.。
解密网址: abcxyz.com
生成的网址:con1. abcxyz.com, con2. abcxyz.com
如上图所示,解密的URL的前4个字节是在Dorkbot中被硬编码过的固定双字值。这4个字节也会用于检查从服务器接收的数据,数据的第五个字节表示操作系统主版本和次版本,第六个字节会检查操作系统是32位还是64位。该字节的值为0x20或0x40,分别用32进制和64进制表示。
接下来那一部分是十六进制数据,用字符进行定义,例如,0x41代表“A”,表示为4和1.这部分数据是计算机名称,以及用#分开的哈希值。Dorkbot使用格式说明符“%s#%s”,其中第一部分是计算机名称,后者是哈希值。再往后的数据是字值(在上图表示为0x444E),它表示文件中的特定偏移量。数据的最后部分是网络连接,所发生的时间和GetTickCount()API的输出数据。
在将数据发送到服务器之后,Dorkbot就已经准备好接收数据了。由于这些网址目前尚未启用,因此我们在分析期间没有收到来自服务器的任何资料。但是,从汇编代码中,我们可以看到恶意软件将会以以特定格式来接受自服务器的数据。以下汇编代码段显示Dorkbot对接收到的数据所进行的检查。
可以看出,WS2_32.recv()API是从连接的套接字接收数据,并返回接收的字节数。Dorkbot会检查API的返回值,如上图所示,服务器接收的字节长度为205,也就是说,Dorkbot已经计算出来自控制服务器的数据长度为205字节。在检查字节数后,Dorkbot会计算数据的前6个字节,它将前4个字节与在发送数据时使用的固定双字值(上图中为18273645)进行比较。Dorkbot便会计算出第五和第六个字节分别为1和0。由于这些网址目前尚未启用,所以研究人员的分析也就到此为止了,请大家关注我们后续的跟踪分析。