病毒分析教程第三话--静态逆向分析(上)

静态逆向分析(上)


教程参考自《恶意代码分析实战》
程序来自:http://www.nostarch.com/malware.htm


使用上两话静态特征分析和动态行为分析的方法只能从宏观的角度分析样本,但由于无法得到源代码,所以我们无法确凿地判定这些样本就是恶意的。本着格物致知的宗旨,我们现在学习使用静态逆向分析的方法,从反汇编的角度来分析一个样本。


PS:由于静态逆向分析过程冗杂,所以本话使用问答的方式进行讲解。

Lab 5-1

本节实验使用样本Lab05-01.dll。
Lab05-01.dll

使用Exeinfo查壳,很幸运,没有加壳,是用VC6写的。
Exeinfo

DllMain的地址是什么?
直接点击左侧DllMain地址,便可在右侧窗口看到其地址,为0x1000D02E。这里顺带提一句,我们分析样本从DllMain开始分析就好了,因为所有DllEntryPoint到DllMain之间执行的代码一般是由编译器生成的,我们不必去分析。
DllMain

使用Imports窗口并浏览到gethostbyname,导入函数定位到什么位置?
点击上方的Imports标签,便可看到导入表,然后按Ctrl+F搜索gethostbyname,位置在.idata节的0x100163CC处。
Imports

有多少函数调用了gethostbyname?
在gethostbyname上按下Ctrl+X便可查看它的交叉引用情况,窗口最底下的“Line 1 of 18”这行文字,告诉我们存在对gethostbyname的9处交叉引用。一些版本的IDA Pro会计算两次交叉引用:类型p是被调用的引用,类型r是被“读取”的引用(因为是对一个导入项call dword ptr […],所以CPU必须先读取这个导入项,再调用它)。仔细查看交叉引用表,会发现实际上在5个不同的函数中调用了gethostbyname。
Xref

将精力集中在位于0x10001757处的对gethostbyname的调用,你能找出哪个DNS请求将被触发吗?
gethostbyname只有一个参数,就是要查询的域名,在下图红框中,可以看到参数存储在eax中,而eax的值是由off_10019040处复制过来的(当然还在off_10019040的基础上加了0x0D)。
DNS

双击off_100190404进去后可以发现得到的域名字符串是“[This is RDO]pics.practicalmalwareanalysis.com”。经过上面的add eax,0xDh,eax就变成了“pics.practicalmalwareanalysis.com”,所以DNS请求的域名就是pics.practicalmalwareanalysis.com
DNS

IDA Pro识别了在0x10001656处的子过程中的多少个局部变量?
有23个,下图红框中负偏移的都是局部变量。最下面一个正偏移的是传入的参数。
Var

IDA Pro识别了在0x10001656处的子过程中的多少个参数?
上个图中已经看到了,1个。当然也可以按下F5进行反编译,更直观地看到参数。
Args

使用Strings窗口,来在反汇编中定位字符串\cmd.exe /c。它位于哪?
按下Shift+F12唤出字符串窗口,定位到字符串\cmd.exe /c,在xdoors_d节中的0x10095B处。
Strings

在引用\cmd.exe /c的代码所在的区域发生了什么?
点击该字符串,然后转换成图形模式,以便更好地观察。
Cmd

这个函数的结构不会复杂,我们现在来看看这个函数在干嘛。将目光移到函数开头,发现有个可疑的字符串,看了下,从语句中可以猜测这是一个反弹shell连接成功的提示语。然后接着看下面红框里的call。
Tips

点进去后,发现有send和free函数,这是与socket相关的函数。
Send

返回继续看原来的函数,下拉可以看到一个recv函数,看来这是一个socket连接确凿无疑了。
Recv

再往下看,发现该函数调用了很多次memcmp,一直在做字符串的比较,如:“quit”、“minstall”、“inject”等。
Memcmp

Memcmp

经过上面几个特征,我们大致搞清楚了这个函数的功能,就是建立一个反弹shell,然后根据接收的命令(quit、minstall、inject等)进行恶意操作。

在同样的区域,在0x100101C8处,看起来好像dword_1008E5C4是一个全局变量,它帮助决定走哪条路径。那恶意代码是如何设置dword_1008E5C4的呢?(提示:使用dword_1008E5C4的交叉引用。)
选中dword_1008E5C4,然后按下Ctrl+X查看交叉引用。
E5C4

有3处交叉引用,但是真正修改了这个值的是第一个语句(类型为w),其它的两处都仅是读操作。
Xref

点过去看,dword_1008E5C4的值来自eax,而eax是函数sub_10003695返回的,继续看函数sub_10003695。
Sub

sub_10003695函数很短,主要就调用了一个GetVersionExA,用来获取当前的操作系统版本,其中将dwPlatformId与数字2进行比较,来确定如何设置AL寄存器。如果PlatformId为VER_PLATFORM_WIN32_NT,AL会被置位。这里只是简单地判断当前操作系统是否Windows 2000或更高版本,我们可以得出结论,该全局变量通常会被置为1。也就是说高于Windows 2000的版本则调用cmd.exe,否则调用command.exe。
GetVersion

在位于0x1000FF58处的子过程中的几百行指令中,一系列使用memcmp来比较字 符串的比较。如果对robotwork的字符串比较是成功的(当memcmp返回0),会发生什么?
若比较成功,红框中的jnz就不会跳转,函数sub_100052A2会被调用,参数是[ebp+s](socket)。
Robot

双击进入sub_100052A2,开头就是一个RegOpenKeyExA打开键HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion。
Key

然后查询了WorkTime和WorkTimes键的值。(aWorkTime是字符串WorkTime,aWorkTimes是字符串WorkTimes),然后直接调用sub_100038EE(就是上面那个调用了send和free的函数)将这些信息发送出去。
Val

未完待续。。。。。