环境配置#
远程调试的大体架构如下图
由于在 mac 上不能运行 windows 的调试器,所以可以通过远程调试来实现通过 mac 进行调试。
首先将加壳的文件和远程调试服务文件复制到TARGET(win10)
机器中,远程调试服务文件位与 dbgsrv 目录。
TARGET(win10)
最终结构如下
加壳程序是通过 upx 进行加壳,32 位程序。
远程调试#
在远程调试之前,将加壳程序PACKED_PRACTICA_1.EXE
在 mac(ida7.0)上进行局部分析,勾选 MANUAL LOAD 手动加载,加载文件所有区段。
在运行调试之前,IDA 加载器会转到已加壳程序的入口。
程序入口
注意:不能重命名数据库文件 IDB
在TARGET(win10)
中运行 win32_remote.exe 远程调试服务器,-i 指定 ip 地址。
调试器选择Remote Windows debugger
。
在 Process options 中,在 Hostname 中输入TARGET(win10)
的 ip 地址和端口,在 Application 和 Input file 中写入位与TARGET(win10)
中的加壳程序的绝对路径,Directory 中写入目录路径即可,配置完成后,点击 ok。
打开调试器菜单选择 Start process,调试开始之后会在程序入口处暂停(修改:需要在 0x638ec 处设置断点才会在此处暂停)。
可执行文件进行了随机化处理,因而每次执行的地址都会变化,所以必须在同一次运行中完成转存和重建 IAT 的工作,中途不能关闭程序。
打开 segments 选项卡,观察 header 文件头之后的第一个代码区段,该区段的起始地址是 631000,终点地址是 238000。
寻找 OEP#
第一种方式可以尝试文本搜索功能搜索 popad 或者 popa 指令,在此程序中可以搜索到一处 popa 指令
从图中可以看出这个地址 0x63146e 处就是 OEP。
第二种方式通过之前学习的覆盖第一个区段的执行断点来寻找 OEP。
双击段视图中的第一个区段,跳转到 0x631000,查看区段数据,地址是随机化的,基址并不是 0x401000,但内存占用都是 0x7000,upx0 区段从 0x631000 到 0x638000,差值是 0x7000 字节。
按 F2 键在 upx0 区段的起点设置断点,这里是 0x601000,断点大小是 0x7000
删除其它断点,只留下这个断点,按 F9 键开始调试。
程序在此处暂停,确定和之前的 OEP 位置一直,然后删除这个断点,去掉红色背景。
点击界面左下角的 Reanalyze program,重新分析程序。
OEP 之后的内容被 IDA 识别位 STUB 的一部分,所以并没有加上sub_
而是标记为loc_
。
转存及 IAT 重建#
找到 OEP 后,开始转存及重建 IAT,先查看文件基址和最高地址。
在这里文件基址是 0x630000,最高地址是 0x63B000,拿出转存的脚本文件,修改文件中的地址,然后加载运行脚本。
脚本如下:
import idaapi
import idc
import struct
start_ea = 0x630000
end_ea = 0x63b000
step = 4 # 每个地址处的数据占用4个字节
file_path = "dump.bin"
with open(file_path, "wb") as f:
for ea in range(start_ea, end_ea, step):
# 读取指定地址处的4个字节数据并进行小端字节序转换
bin_data = struct.pack("<L", idaapi.get_32bit(ea))
f.write(bin_data)
运行完成后,生成转存文件(脚本文件在 mac 上运行,所以转存文件也生成在 mac 上。)。
将 dump.bin 文件复制到 windows 上,通过 peeditor 打开,
在每个区段上右键单击选择 dumpfixer,操作完成后,然后将.bin 改成.exe 文件,效果如下:
将 dump.exe 文件通过 scylla 打开,加载加壳程序进程。
输入 OEP 地址,此处为 0x63146e,然后点击 IAT Autosearch 和 Get Imports,发现一处未能识别的 API 函数。
将 API 地址加上基址,0x630000+0x20d4=0x6320d4,转到 16 进制视图,并不像 IAT 的一部分。
转向反汇编视图查看该处的引用,内容如下:
按 x 键显示了 2 处引用。
而0x6320d4
指向的地址只返回 RET 指令,如下:
0x6320d4
指向的是程序内的一个固定地址,而且只是一个 RET 指令,并不是引用的 API 函数,所以可以删除,在 Syclla 中,右键单击 API 函数报错处 CUT THUNK 从 IAT 中删除。
删除后如下:
最后点击 Fix Dump 对 dump.exe 重建 IAT,最后生成 dump_SCY.exe 可执行程序。
如果此时运行 dump_SCY.exe,还是黑屏一闪而过。
取消随机基址#
因为出了 IAT 之外在运行时生成的地址没有被重定向因为它们总是在变,所以需要消除这个随机性,打开 ida,加载 dump_SCY.exe 文件,使用 Manual Load 加载 pe 头区段,然后转到这一区段。
在 header 头中找到如下内容 Dll characteristics,需要将其值改为 0。
打开菜单 Edit-patch program-change word 将这个值改为 0。
点击 ok,然后使用 apply patches to input file 将改动保存回可执行文件。
此刻,再次运行dump_SCY.exe
可成功运行,说明脱壳后的文件执行成功。