实验 1 缓冲区溢出和恶意代码分析
1.1 实验名称
《缓冲区溢出和恶意代码分析》
1 、熟练使用恶意代码分析工具 OD 和 IDA
2 、通过实例分析,掌握缓冲区溢出的详细机理
3 、通过实例,熟悉恶意样本分析过程
第一阶段:利用 IDA 和 OD 分析 bufferoverflow 攻击实例(见实验 1 代码和样
本文件 bufferoverflow.exe)
1 、分析 bufferoverflow 实例中的关键汇编代码
2 、分析程序执行过程中寄存器和栈地址及其数据的变化(包含程序开始执行前、开始执行
时、溢出前、溢出后几个阶段)
3、解释为什么该实例中在 XP 环境下需要输入 17 个任意字符就可以绕过密码比较的判断功
能
第二阶段:分析恶意样本实例(见实验 1 代码和样本文件 example.exe)
1 、分析 example 恶意代码关键汇编代码
2 、结合汇编代码说明该恶意软件样本的主要功能
第三阶段:分析真实勒索软件样本(可选,见实验 1 代码和样本文件 radman.rar)
1 、搭建服务器,成功执行该恶意代码
2 、分析 radmant 勒索软件恶意代码关键汇编代码
3 、结合汇编代码说明该恶意软件样本的主要功能
1.4. 1 bufferoverflow 分析
首先打开 IDA_Pro ,根据函数名找到 main()函数的代码起始地址是 0x004123B0。
需要注意的是,由于 IDA_Pro 是静态编译工具,在存在重定位的情况下(比如 Windows11 操作系统的真实机)与 OllyDBG 所加载的动态内存里的地址并不一致,这时需要在打开 IDA_Pro 的时候手动更改 Image Base ,才能与 OD 中的地址保持一致。
由于在 XP 操作系统中不存在重定位,所以 IDA_Pro 中显示的地址与 OD 中一致,因此 直接打开 OD ,将断点设置在 0x004123B0 作为程序的入口。
可以看到 main()函数是由 0x004116FE 跳转来的。
在 IDA_Pro 中使用 ctrl+x 对 main()函数不断交叉编译,可以看到调用 main()的的函数 _main_0 的调用者地址为 00412BBC ,这也正是程序的真正入口地址。设置断点。
首先执行到该断点处,然后进入call 语句。可以看到现在将要执行的地址内容是 main() 函数内容,并且 0x0012FF7C 处保存的是 main()函数的返回地址,EBP 指向地址的内容是 call 语句所在函数的 EBP 地址。之后执行到 push ebx 上方,表明系统为局部变量分配了 0xDC (220 字节)大小的内存空间(选择显示 ASCII 数据,可以看到其中是有数据的)。
执行到 MOV DWORD 上方,是系统对分配的内存空间进行了初始化,全部置为 CC 表 示 int 断点,这样如果有位置程序跳到这片区域就不会出现崩溃情况而是直接被中断下来。 可以看到初始化后复函数的返回地址和 EBP 依旧存在。
继续向下执行,在地址 0x004123DE 处是调用命令行输入的一个 CALL 语句(往里多步 入几层可以发现实际上是调用了 kernel32GetMessage.dll 中一个函数,用于获取命令行输入 并存放在内存的合适位置,这里的存放位置是 0x0012FF60 处) 。接着执行到 0x004123EF 位置的 CALL 语句上方,发现两句 PUSH 语句是将数据段的“ 12345 ”和内存中的输入压栈 (同时也可以看出我们输入的内容被存放在了 SS:[EBP- 18] ,即 0x0012FF60 处)。
继续执行来到 0x004123EF 位置的 CALL 语句,作用是比较栈顶两个元素的值是否相等, 如果相等则置 EAX 为 0(也就是输入正确字符串“ 12345 ”时),不等就置为 0xFFFFFFFF, 并且再接下来会把两个栈顶元素弹栈。然后,程序根据 EAX 的值是否为零决定输出的内容, 具体方式是通过对 SS:[EBP-8]赋值为 0 或 1 判断跳转位置。
可以看到,SS:EBP-8 的值决定程序的输出,这个位置距离我们输入内容的存放位置 SS:EBP- 18 只有 0x10 也就是 16 。因此当我们输入长度超过 17 个字节的内容、并保证第 17 个字节的十六进制最低位是 1 时(比如 17*“ 1 ”),就能够成功覆盖 SS:[EBP-8] ,让程序 输出“Welcome ”。此外,输入更长的内容还能覆盖到 pre EBP 和返回地址,从而进行提权 等攻击。
1.4.2 example 分析
我们开始使用静态分析基础技术,研究 PE 文件结构和字符串列表。我们看到这个恶意 代码导入了一些联网功能函数、服务操作函数和注册表操作函数。在下面的列表中,我们关 注到一些有趣的字符串。
我们看到域名、注册表位置(如字符串 SOFTWARE\Microsoft(XPS;像 DOWNLOAD、UPLOAD 这样的命令字符串,以及 HTTP/1.8 字符串等。这些表明恶意代码可能是一个 HTTP 后门程序。字符串-cc 、-re 、-in 应该是一些命令行参数(例如-in 可能是 install 的缩写)。
我们尝试运行一下 example,但它看起来似乎立即删除了自身,除此以外没有别的发现。
接下来,我们使用 procmon 工具,设置一个 example.exe 进程名称上的过滤器。依然没 有任何有趣的如 writeFile 、RegSetValue 之类的事件。
但是通过深入挖掘后,我们发现了一个 Process Create 的条目。双击该条目将看到如下 图所示的对话框,可以发现,恶意代码是通过使用"C:\WINDOWS\system32\cmd.exe ”/c del Z:\Lab03-84.exe >>NUL 来从系统中删去自身的。
静态分析到此就没有太多值得分析的了,接下来尝试动态分析 example。
首先,我们使用OllyDbg 调试恶意代码。我们使用F8 键step-over,直至到达地址0x403945, 此处 是对 main 函数的调用(最简单找出 main 函数位于地址 0x402AF0 的方法,是使用 IDA Pro)。接下来,使用 F7 键 step-into 到 main 函数调用。我们使用 F7 键和 F8 键继续向前单步, 同时注意样本的行为。
首先,恶意代码在地址 0x402AFD 查看命令行参数的数量是否等于 1 。我们没有指定任 何参数,所以检查成功,并且在地址 0x401000 处恢复运行。接下来,它试图打开注册表项 HKLM\SOFTWARE\Microsoft XPS ,然而由于注册表项不存在,函数返回 0 ,所以调用进入 0x402410 处的函数。
从 0x40240C 处 F7 进去可以看到,程序似乎在某个时刻将一个网址
"http://www.practicalmalwareanalysis.com"压入了寄存器,推测 example 是具有网络能力的恶 意代码。
0x402410 处的函数使用 GetModuleFilenameA 获取当前可执行文件的路径,并构造出一 个 ASCII 字符串:/c del path-to-executable>>NUL 。图 9- 1L 展示了在 OllyDbg 的寄存器面板 窗口中的这个字符串实例。注意,EDX 寄存器值是 0x12E248 ,但是 OllyDbg 正确地解释它 为 ASCII 字符串指针。
恶意代码通过在 ShellExecuteA 调用中结合构造的字符串和 cmd.exe 来尝试着从硬盘上 删除自己。
综合以上信息,我推测恶意代码创建一个注册表项 HKLM\SOFTWARE\Microsoft\XPS。 Microsoft 之后的空格使得它成为一个独特的主机感染标识。它在地址 0x4011BE 处,用 EDX 寄存器指向的缓冲区内容,来填充注册表下名为 Configuration 的键值。为了找出缓冲区的 内容,我们在地址 0x4011BE 处设置断点,并且运行恶意代码。在寄存器面板窗口中,右键 单击 EDX 寄存器的内容,选择 Follow in Dump 。十六进制的转储视图显示了 4 个以 NULL 结束的字符串,随后是多个 0 ,字符串包含值 ups 、http://www.practicalmalwareanalysis.com、 80 和 68。
综合以上信息,加上查阅资料,发现恶意代码构造一个 HTTP/1.0 GET 请求,并且连 接一个远程系统。这种连接不太可能被防火墙拦截,因为它是一个向外的合法 HTTP 请求。 由于我的恶意代码分析虚拟机禁用了网络,向外的连接永远不会成功,运行恶意代码就会失 败。然后,仔细跟踪反汇编列表,会看到恶意代码事实上是尝试着连接注册表键值配置中记 录的域名和端口。进一步分析反汇编代码显示,恶意代码在服务器返回的文档中搜索特殊的 字符串(反引号、单引号、反引号、单引号、反引号) ,并且用它们来表示命令控制协议。
(1)在 WINXP 中,栈是怎么分布的?栈中可以存放代码吗?
栈的结构如下。可以
(2)为什么该实例中在 XP 环境下需要输入 17 个任意字符就可以绕过密码比较的判断功
能?
17 个字符能够覆盖返回结果的判断条件。