恶意代码分析实战——利用IDA PRO分析Lab05-01.dll
1.实验目的
利用IDA Pro分析Lab05-01.dll中发现的恶意代码,回答以下问题:
- DLLMain的地址是什么?
- 使用Imports窗口并浏览到gethostbyname,导入函数定位到什么地址?
- 有多少函数调用了gethostbyname?
- 将精力集中在位于0x10001757处的对gethostbyname的调用,你能找出哪个DNS请求将被触发吗?
- IDA Pro 识别了在0x10001656处的子过程中的多少个局部变量?
- IDA Pro识别了在0x10001656处的子过程中的多少个参数?
- 使用Strings窗口,来在反汇编中定位字符串 \cmd.exe /c, 它位于哪儿?
- 在引用 \cmd.exe /c的代码所在区域发生了什么?
- 在同样的区域,在0x100101C8处,看起来dword_1008E5C4好像是一个全局变量,它帮助决定走哪条路径。那恶意代码是如何设置dword_1008E5C4的呢?(提示:使用交叉引用)
- 在位于0x1000FF58处的子过程中的几百行指令中,一系列使用memcmp来比较字符串的比较。如果对robotwork的字符串比较是成功的(当memcmp返回0),会发生什么?
- PSLIST导出函数做了什么?
- 使用图模式来绘制出对sub_10004E79的交叉引用图。当进入这个函数时,哪个API函数可能被调用?仅仅基于这些API函数,你会如何重命名这个函数?
- DllMain直接调用了多少个Windows API?多少个在深度为2时被调用?
- 在0x10001358处,有一个对Sleep(一个使用一个包含要睡眠的毫秒数的参数的API函数)的调用。顺着代码向后看,如果这段代码执行,这个程序会睡眠多久?
- 在0x10001701处是一个对socket的调用,它的3个参数是什么?
- 使用MSDN页面的socket和IDA Pro中的命名符号常量,你能使参数更有意义吗?修改后,参数是什么?
- 搜索in指令(opcode 0xED)的使用。这个指令和一个魔术字符串VMXh用来进行Vmware检测。在这个恶意代码中被使用了吗?使用对执行in指令函数的交叉引用,能发现进一步检测Vmware的证据吗?
- 将你的光标跳转到0x1001D988处,你发现了什么?
- 如果你安装了IDA Python插件(包括IDA Pro的商业版本插件),运行Lab05-01.py,一个IDA Pro Python脚本(确定光标是在0x1001D988处),在运行该脚本后发生了什么?
- 将光标放于同一位置,你如何将这个数据转成一个单一的ASCII字符串?
- 使用一个文本编辑器打开这个脚本。它是如何工作的?
2.实验环境(硬件、软件)
Winxp虚拟机:
硬件:处理器Intel® Core™ i5-10210U CPU @ 1.60GHz 2.11 GHz
软件:32位操作系统
3.实验步骤
(1)DLLMain的地址是什么?
从中可以看到DLLMain的地址为1000D02E
(2)使用Imports窗口并浏览到gethostbyname,导入函数定位到什么地址?
从中可以看到gethostbyname定位到的地址为100163CC
(3)有多少函数调用了gethostbyname?
可以看到有5个函数调用了gethostbyname函数9次
(4)将精力集中在位于0x10001757处的对gethostbyname的调用,你能找出哪个DNS请求将被触发吗?
先跳转到10001757处,在这个汇编代码先将10019040中的内容存放到中寄存器eax中,我们双击off_10019040进入10019040查看
发现存在pics.praticalmalwareanalys的字样,然后双击aThisIsRdoPics_,发现了praticalmalwareanalysis.com的域名信息。
用hex窗口打开aThisIsRdoPics_
发现前13个字节就是 [This is RDO],也就是说,后来令eax加上0Dh,就是将eax指向了praticalmalwareanalysis.com,然后再将eax压入栈作为gethostbyname的参数。所以位于0x10001757处的对gethostbyname的调用访问了praticalmalwareanalysis.com
(5)IDA Pro 识别了在0x10001656处的子过程中的多少个局部变量?
所以共有23个局部变量
(6)IDA Pro识别了在0x10001656处的子过程中的多少个参数?
共有一个参数
(7)使用Strings窗口,来在反汇编中定位字符串 \cmd.exe /c, 它位于哪儿?
所以它位于0x10095B34
(8)在引用 \cmd.exe /c的代码所在区域发生了什么?
来到0x10095B34处,双击 sub_1000FF58查看这个字符串的交叉引用
看到再100101D0处该字符串被压入栈
往上翻发现在该字符串被引用之前还有一个字符串
双击aHiMasterDDDDDD
图中字符串表示为远程shell会话解密一段数字,即开启一段远程session会话。
(9)在同样的区域,在0x100101C8处,看起来dword_1008E5C4好像是一个全局变量,它帮助决定走哪条路径。那恶意代码是如何设置dword_1008E5C4的呢?(提示:使用交叉引用)
双击dword_1008E5C4
选中1008E5C4,ctrl+x查看交叉引用,发现进行写操作的只有第一条
双击10001656+22,发现它将eax的值赋给了dword_1008E5C4,而EAX是前一条指令函数调用的返回值。因此双击前面的函数调用sub_10003695查看eax的返回值
可以看到该函数包括了一个GetversionExA的调用,用于获取当前操作系统版本的信息,之后再将VersionInformation.dwPlatformId与2比较来决定寄存器al的值即eax的值。
其中2代表WIN32_NT系统,也就是说,该处的函数会检查一下是不是win32系统来决定eax的值,之后再存放入dword_1008E5C4中,而dword_1008E5C4的值也就是0或1
(10)在位于0x1000FF58处的子过程中的几百行指令中,一系列使用memcmp来比较字符串的比较。如果对robotwork的字符串比较是成功的(当memcmp返回0),会发生什么?
跳转到0x1000FF58处向下翻,找到rootwork
jnz指令是比较不成功时跳转,所以跳过jnz指令向下执行,双击查看sub_100052A2函数,我们看到了关于注册表的信息
往下翻发现调用了sub_100038EE函数
双击进入sub_100038EE函数查看,发现其调用了了malloc函数创建了内存空间,然后又调用了send函数,最后调用了free函数释放内存空间,所以猜测可能是对注册表SOFTWARE\Microsoft\Windows\CurrentVersion进行了修改或查询操作,然后再将结构发送出去。
为了更直观详细的查看sub_100052A2函数到底做了什么,我们返回sub_100052A2函数内,按下F5查看伪c代码
发现首先用RegOpenKeyExA函数打开了注册表HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion,然后查询了aWorktime和aWorktimes键也就是worktime和worktimes键的值,然后调用了sub_100038EE函数,将这些信息发了出去。
(11)PSLIST导出函数做了什么?
进入导出列表窗口
双击PSLIST函数,看到它的汇编代码,首先调用sub_100036C3函数,如果返回值为1则往下执行函数sub_10006518和sub_1000654C。
首先进入到sub_100036C3函数中查看,并按F5查看伪c代码,可以看到sub_100036C3函数做出了一个判断,判断系统是否是win32且版本大于win2000,如果是则返回1
我们进入到sub_10006518和sub_1000654两个函数中查看
发现它们都调用了CreateToolhelp32Snapshot函数和sub_1000620C函数,CreateToolhelp32Snapshot函数就是获取主机的进程信息,而sub_1000620C,我们点进去观察伪C代码发现它就是将查询到的进程信息写入到一个文件中。
所以PSLIST导出函数的作用就是搜寻主机内的进程并把它写入到一个文件中形成一个进程列表。
(12)使用图模式来绘制出对sub_10004E79的交叉引用图。当进入这个函数时,哪个API函数可能被调用?仅仅基于这些API函数,你会如何重命名这个函数?
跳转到该函数处,选中sub_10004E79,然后点击User xrefs chart生成交叉引用图
当进入这个函数时GetSystemDefaultLangID、sprintf、strlen这三个API被调用。
该函数又调用了sub_100038EE函数,而sub_100038EE函数又调用了send,malloc,free,__imp_strlen函数。
由于该函数调用了GetSystemDefaultLangID函数,又间接调用了send函数,所以猜测该函数会获取系统默认语言ID后,通过send函数发送远程连接的对方,所以该函数可以取名GetSystemLanguageID。
(13)DllMain直接调用了多少个Windows API?多少个在深度为2时被调用?
跳转到DLLMain函数处,选中DLLMain函数,点击view→Subviews→Function Calls查看函数调用窗口
可以看到直接调用了strlen、strnicmp、CreateThread、strncpy这4个Windows API。
打开User xrefs chart,勾选掉Cross,references to,并且将深度设为2
放大后查看,大约有31个API在深度为2时被调用
(14)在0x10001358处,有一个对Sleep(一个使用一个包含要睡眠的毫秒数的参数的API函数)的调用。顺着代码向后看,如果这段代码执行,这个程序会睡眠多久?
跳转到0x10001358处,放下在调用Sleep前先将eax压入了栈作为Sleep函数的参数,也就是睡眠时间,所以往前看找到eax的值,即为睡眠时间。
从中可以看出,在这段汇编代码中,先将off_10019020存放到了eax中,我们双击进入off_10019020,查看其内容
发现了[This is CTI]30的字样,双击进入aThisIsCti30,发现它定义的值为[This is CTI]30
在Sleep那段汇编代码中又将eax加了0DH,也就是13字节,即对应信息为[This is CTI],也就是eax指向了30紧接着将eax压入栈,调用了atoi函数将eax的值化成了整数,也就是说eax的值为30,然后imul指令又将eax乘以3E8h,也就是30*1000=30000ms=30s,所以sleep函数会使程序睡眠30s
(15)在0x10001701处是一个对socket的调用,它的3个参数是什么?
跳转到0x10001701处,发现在调用socket函数前先将6,1,2这三个数压入了栈,故它的三个参数为6,1,2
(16)使用MSDN页面的socket和IDA Pro中的命名符号常量,你能使参数更有意义吗?修改后,参数是什么?
右键单机这三个参数,选择 use standard symbolic constant,会列举出IDA Pro 为这个特定值找到的所有对应量
而对于socket函数,三个参数分别为domain(协议域,或协议族family)、type(socket类型)、protocol(协议)。在这个socket函数中,domain=2对应AF_INET,即决定了要用IPv4地址(32位)与端口号(16位)的组合;type=1对应的是SOCK_STREAM,即流式套接字;protocol=6对应的是IPPROTO_TCP,即TCP协议。应用了修改后参数如下:
(17)搜索in指令(opcode 0xED)的使用。这个指令和一个魔术字符串VMXh用来进行Vmware检测。在这个恶意代码中被使用了吗?使用对执行in指令函数的交叉引用,能发现进一步检测Vmware的证据吗?
搜索in指令
双击sub_10006196跳转到in指令地址处,发现了一些类似于字符串的十六进制数
选中这些十六进制数,按R键将其转化为字符串,发现它们正是VMXh,所以这个恶意代码使用了Vmware检测技术。
单机该in指令所在的函数名,按ctrl+x查看交叉引用,发现一共有三个函数调用了该函数
分别查看这三个函数,发现均存在Found Virtual Machine,Install Cancel的字样,这些便是对VMware进一步检测的证据。
(18)将你的光标跳转到0x1001D988处,你发现了什么?
发现了一串没有含义的随机数据
(19)如果你安装了IDA Python插件(包括IDA Pro的商业版本插件),运行Lab05-01.py,一个IDA Pro Python脚本(确定光标是在0x1001D988处),在运行该脚本后发生了什么?
运行脚本后变成了明文字符串
(20)将光标放于同一位置,你如何将这个数据转成一个单一的ASCII字符串?
按下a键后
该字符串是xdoor is this backdoor, string decoded for Practical Malware Analysis Lab :)1234
(21)使用一个文本编辑器打开这个脚本。它是如何工作的?
ScreenEA()函数获取IDA调试窗口中光标所指向代码的地址,for循环范围为连续50个字节,Byte函数读取每个字节的值,然后再将该值于0x55进行异或运算,最后将结果输出返回到IDA对应的地址中。
4.实验结论
- DLLMain的地址是什么?
0x1000D02E - 使用Imports窗口并浏览到gethostbyname,导入函数定位到什么地址?
0x100163CC - 有多少函数调用了gethostbyname?
被5个不同的函数调用调用了9次 - 将精力集中在位于0x10001757处的对gethostbyname的调用,你能找出哪个DNS请求将被触发吗?
如果在0x10001757处调用gethostbyname,恶意代码会发起对praticalmalwareanalysis.com的DNS请求 - IDA Pro 识别了在0x10001656处的子过程中的多少个局部变量?
识别出了23个局部变量 - IDA Pro识别了在0x10001656处的子过程中的多少个参数?
识别出了一个参数 - 使用Strings窗口,来在反汇编中定位字符串 \cmd.exe /c, 它位于哪儿?
位于0x10095B34处 - 在引用 \cmd.exe /c的代码所在区域发生了什么?
为攻击者开启一段远程shell会话 - 在同样的区域,在0x100101C8处,看起来dword_1008E5C4好像是一个全局变量,它帮助决定走哪条路径。那恶意代码是如何设置dword_1008E5C4的呢?(提示:使用交叉引用)
sub_10003695函数先检查主机是否为win32_NT系统,再将判断结果(0或1)存放入eax寄存器中,再放入dword_1008E5C4中 - 在位于0x1000FF58处的子过程中的几百行指令中,一系列使用memcmp来比较字符串的比较。如果对robotwork的字符串比较是成功的(当memcmp返回0),会发生什么?
注册表HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\WorkTime和Worktimes的值会被查询,然后通过远程shell连接发送给攻击者。 - PSLIST导出函数做了什么?
PSLIST导出函数会查询所有进程,并将该进程列表通过网络发送出去,或者寻找某个特定进程并获取其信息 - 使用图模式来绘制出对sub_10004E79的交叉引用图。当进入这个函数时,哪个API函数可能被调用?仅仅基于这些API函数,你会如何重命名这个函数?
调用了GetSystemDefaultLangID、sprintf、strlen三个API,可以重命名为GetSystemLanguageId - DllMain直接调用了多少个Windows API?多少个在深度为2时被调用?
直接调用了strncpy、strnicmp、CreateThread和strlen这四个API,大约有31个API再深度为2时被调用 - 在0x10001358处,有一个对Sleep(一个使用一个包含要睡眠的毫秒数的参数的API函数)的调用。顺着代码向后看,如果这段代码执行,这个程序会睡眠多久?
恶意代码会使程序休眠30秒 - 在0x10001701处是一个对socket的调用,它的3个参数是什么?
这三个参数为6,1,2 - 使用MSDN页面的socket和IDA Pro中的命名符号常量,你能使参数更有意义吗?修改后,参数是什么?
domain=2对应AF_INET;type=1对应的是SOCK_STREAM;protocol=6对应的是IPPROTO_TCP - 搜索in指令(opcode 0xED)的使用。这个指令和一个魔术字符串VMXh用来进行Vmware检测。在这个恶意代码中被使用了吗?使用对执行in指令函数的交叉引用,能发现进一步检测Vmware的证据吗?
在这个代码中存在in指令和VMXh的使用,还存在Found Virtual Machine,Install Cancel的字符串,证明该恶意代码做出了进一步的Vmware检测 - 将你的光标跳转到0x1001D988处,你发现了什么?
发现了一串随机数据 - 如果你安装了IDA Python插件(包括IDA Pro的商业版本插件),运行Lab05-01.py,一个IDA Pro Python脚本(确定光标是在0x1001D988处),在运行该脚本后发生了什么?
那些随机数据变成了一串字符串明文 - 将光标放于同一位置,你如何将这个数据转成一个单一的ASCII字符串?
按下a键,这些单一字符转换为一个单一的ASCII字符串 - 使用一个文本编辑器打开这个脚本。它是如何工作的?
ScreenEA()函数获取IDA调试窗口中光标所指向代码的地址,for循环范围为连续50个字节,Byte函数读取每个字节的值,然后再将该值于0x55进行异或运算,最后将结果输出返回到IDA对应的地址中。