本章会向你介绍使用 IDA Pro 进行恶意代码分析的完整的过程。如果你要在 IDA Pro 上研究得更深入,Chris Eagle 的 The ID. A Pro Book: The Unofficial Guide to the World’s Most Popular Disassembler, 2 nd Edition(No Starch 出版社, 2011) 值得推荐,对 IDA Pro 和逆向工程来说,它都是一份极好的桌面参考资料。
1 . DLLMain 的地址是什么?
Ctrl + F 搜索 DLLMain

方法一:打开图形前缀
options —> General —> Line prefixes (graph)


方法二: 使用空格切换视图

2. 使用 Imports 窗口并浏览到 gethostbyname, 导入函数定位到什么地址?

3. 有多少函数调用了 gethostbyname?
对函数按下 x 键,即可调出交叉引用

点击 type 进行排序可见分为 p 和 r。p 代表函数,r 代表读取属性。
除去重复的地址,可见 gethostbyname 被调用了五次。

4. 将精力集中在位于 0x10001757 处的对 gethostbyname 的调用, 你能找出哪个 DNS 请求将被触发吗?
G 键调出跳转地址

使用 call 调用函数,push 压栈传参,因此判断 off_10019040 即为查询的域名

跟随 off_10019040,即可见 ida 解析出来的字符串 pics.praticalmalwareanalysis.com

5. IDA Pro 识别了在 ex 10001656 处的子过程中的多少个局部变量?
正数是参数,带 负号 的即为局部变量,可见有 23 个

6. IDA Pro 识别了在 ex 1001656 处的子过程中的多少个参数?
直接看 ida 分析出的传参 DWORD __stdcall sub_10001656(LPVOID lpThreadParameter),或看正数的数量,只有 lpThreadParameter 一个正数,即只有一个参数。
7. 使用 Strings 窗口, 来在反汇编中定位字符串 \cmd.exe /c。它位于哪?
Shift + F12 调出 Strings 窗口,搜索 \cmd.exe /c。
跟随 sub_1000FF58+278↑o

8. 在引用 \cmd.exe /c 的代码所在的区域发生了什么?
字符串中可见其作用应为远控类。
后续还有使用 memcmp 判断输入的命令是什么

9. 在同样的区域, 在 0x100101C8 处, 看起来好像 dword_1008E5C4 是一个全局变量, 它帮助决定走哪条路径。那恶意代码是如何设置 dword_1008E5C4 的呢? (提示:使用 dword_1008E5C4 的交叉引用。)
查看 dword_1008E5C4 的交叉引用,我们可以发现 type 分为了 r 读和 w 写。
追踪写操作 sub_10001656+22,可见 dword_1008E5C4 的值为函数 sub_10003695 的返回值。
eax通常为函数返回值。
继续追踪 sub_10003695,发现其主要逻辑为调用 GetVersionExA 函数返回系统版本,判断系统版本执行后续操作
tab 转成伪代码

从微软的官方文档 中我们可知
Versionlnformation.dwPlatformld的值默认为 2 VER_PLATFORM_WIN32_NT 2: The operating system is Windows 7, Windows Server 2008, Windows Vista, Windows Server 2003, Windows XP, or Windows 2000.
Versionlnformation.dwPlatformld == 2Result:=OSVl.dwPlatformld;{ 返回值: 为0表示为win3x系统; 为1表示为win9x系统; 为2表示为WinNT; 为3表示为win2000系统;}由判断结果我们可见其主要功能为判断操作系统版本,若为 windows 2000 之前则使用 command.exe,之后则使用 cmd.exe

10. 在位于 0x1000FF58 处的子过程中的几百行指令中, 一系列使用 memcmp 来比较字符串的比较。如果对 robotwork 的字符串比较是成功的 (当 memcmp 返回 o) , 会发生什么?
跳转至 0x1000FF58 后 option + T 搜索 robotwork,发现若 Buf1 的前 9 个字节等于 Robotwork,则调用 sub_100052A2
memcmp判断s1与s2的前n个字节是否相同,相同则置ZF = 1
跟踪 sub_100052A2 ,发现其主要功能为进到 SOFTWARE\Microsoft\Windows\CurrentVersion 查询 WorkTime 的键值
后续调用的的 loc_10005379 函数,逻辑类似,查询 WorkTimes 的键值
查询完成后调用 sub_100038EE, 继续跟踪该函数。可见该函数作用为将查询到的 WorkTime 和 WorkTimes 值通过先前建立好的 socket 会话发出。

看一下伪代码

11. PSLIST 导出函数做了什么?
可见首先调用 sub_100036C3 函数
sub_100036C3 函数用作判断系统版本
sub_1000664C 通过 CreateToolhelp32Snapshot 创建系统进程快照,通过快照句柄 pe 遍历所有进程,枚举所有进程的模块,将所有信息通过 sub_100038BB 函数发送出去。

12. 使用图模式来绘制出对 sub_10004E79 的交叉引用图。当进入这个函数时, 哪个 API 函数可能被调用?仅仅基于这些 API 函数, 你会如何重命名这个函数?
右键 sub_10004E79 —> Xrefs graph from...
SendSystemDefaultLangID

13. DLLMain 直接调用了多少个 Windows API?多少个在深度为 2 时被调用?
…
14. 在 0x10001358 处, 有一个对 sleep (一个使用一个包含要睡眠的毫秒数的参数的 API 函数) 的调用。顺着代码向后看, 如果这段代码执行, 这个程序会睡眠多久?
0Dh即13,将指针指向eax的第 13 位atoi(eax) = 30(读取寄存器的值,直到非数字)- 将
eax与3E8h即 1000 相乘,即 30000 - sleep 30000 毫秒

15. 在 0x10001701 处是一个对 socket 的调用。它的 3 个参数是什么?
可直接看ida 直接给出注释
或是微软的官方文档 socket function (winsock2.h)
SOCKET WSAAPI socket( [in] int af, [in] int type, [in] int protocol);| 参数 | 值 | 含义 |
|---|---|---|
| af (address family) | 2 | AF_INET → IPv4 地址族 |
| type | 1 | SOCK_STREAM → 面向连接的 TCP 套接字 |
| protocol | 6 | IPPROTO_TCP → TCP 协议 |
16. 使用 MSDN 页面的 socket 和 IDA Pro 中的命名符号常量, 你能使参数更加有意义吗?在你应用了修改以后, 参数是什么?
右键函数名 —> Symbolic constant —> use standard symbolic constant

17. 搜索 in 指令 (opcode exED) 的使用。这个指令和一个魔术字符串 VMXh 用来进行 VMware 检测。这在这个恶意代码中被使用了吗?使用对执行 in 指令函数的交叉引用, 能发现进一步检测 VMware 的证据吗?
Alt+T直接搜索in;- 或者
Alt+B搜索ED
在 sub_10006196 中可见 .text:100061C7 处的字符串 VMXh (原为 16 进制字符,需按 r 转换)
查看 sub_10006196 函数的交叉引用,后续还可见判断环境是否位虚拟机的操作

18. 将你的光标跳转到 0x1001D988 处, 你发现了什么?
一堆乱码

19. 如果你安装了 IDA Python 插件 (包括 IDA Pro 的商业版本的插件) , 运行 Lab 05-01. py, 一个本书中随恶意代码提供的 IDA Pro Python 脚本, (确定光标是在 0x1001D988处。) 在你运行这个脚本后发生了什么?
选中上题数据,shift + E 进行导出
将数据与 0x55 进行异或,并转成 ASCII 输出

20. 将光标放在同一位置, 你如何将这个数据转成一个单一的 ASCII 字符串?
对地址按下 A 键即可转成 ASCII 格式

21. 使用一个文本编辑器打开这个脚本。它是如何工作的?
循环从 0x00 到 0x4F 共 80 次,将每个字符与 0x55 进行异或,并解码
sea = ScreenEA()
for i in range(0x00,0x50): b = Byte(sea+i) decoded_byte = b ^ 0x55 PatchByte(sea+i,decoded_byte)部分信息可能已经过时