x64dbg-手脱UPX
9unk Lv5

目标程序

程序下载:CRACKME UPX

解压密码:9unk

任务目标:手脱 UPX,手动定位修复 IAT(输入函数地址表)

手脱 UPX

首先第一步是定位 OEP,我们先用 x64dbg 加载 Crackme UPX

1.jpg

我们这里使用 ESP 定律来定位 OEP,现在我们停在了入口点处,单击 F8 键执行 PUSHAD

2.jpg

在 ESP 寄存器值上面单击鼠标右键选择 –> 在内存窗口中转到

3.jpg

然后对刚刚定位的4个字节的数据,设置硬件访问断点(4个字节)

4.jpg

F9 运行程序,看一看到程序停在了跳转 OEP 位置附近

5.jpg

F8 运行程序到 OEP 处

6.jpg

这里使用 scylla 插件(快捷键:Ctrl+I),我们选择好相应的进程,并点击 dump,就能将程序 dump 出来

7.jpg

8.jpg

9.jpg

可以看到上面程序已经 dump 成功,但是还没修复 IAT,程序还无法正常运行

我们知道 API 函数的调用通常是通过间接跳转或间接 call 来实现的(即 JMP [xxxxxxxx] 或 call [xxxxxxx])

我们这里随便找一个间接调用,并跳转到相应的反汇编地址

10.jpg

11.jpg

跳转到内存窗口,定位到相应数据窗口

12.jpg

我们知道 IAT 的每个元素都保存了以个 API 函数的入口地址,比如这里的 E0 82 59 76 (小段存储)

13.jpg

我们把数据窗口稍微往上拉一下,就可以看到整个 IAT 了。

14.jpg

属于同一个动态库的 API 函数地址都是连续存放的,不同的动态库函数地址列表是用零隔开的

有一些壳将这部分全部填零,使得我们重建 IAT 变得异常困难,这里由于原程序还需要调用这些 API 函数,所以该壳没有阿静这部分填零,下面看看最后一个动态库的 IAT 项,如下:

15.jpg

可以看到这里显示了该 DLL 中的三个 API 函数,入口地址是 76 7xxxxx

我们使用 Alt+M 看看 76 7 开头的地址属于哪个 DLL 的。

16.jpg

可以看到这是属于 comdlg32.dll 中的 API 函数

我们再看看最上面 API(76 5xxxxx)是属于哪个 DLL 的

17.jpg

可以看到这是属于 user32.dll 的 API函数

现在我们定位一下整个 IAT 的起始位置和结束位置

18.jpg

可以看到 IAT 的其实地址是:403184,结束地址是:40328C。

有些强壳可能会将 IAT 前后都填充上垃圾数据,让我们定位 IAT 的起始位置和结束位置更加困难。但是我们知道 IAT 中的数值都是属于某个动态代码段范围内的,如果我们发现数值不属于任何一个动态库的代码段的话,就说明该数值是垃圾数据

重建 IAT 需要三项指标:

  • IAT 的起始虚拟地址:403184

  • IAT 的大小:40328c(IAT结束地址)- 403184(IAT起始地址)=108(十六进制)

  • OEP 的虚拟地址:401000

打开 scylla 插件,输入相应的值,点击 Get Imports(获取 IAT) 如下图所示

19.jpg

最后点击 Fix Dump 将 IAT 导入到之前 dump 的程序中。

20.jpg

导入完成的程序如下

21.jpg

reference

参考自:从零开始 OlllyDBG-三十四章 [Ricardo Narvaja]

  • 本文标题:x64dbg-手脱UPX
  • 本文作者:9unk
  • 创建时间:2021-03-10 18:26:28
  • 本文链接:https://9unkk.github.io/2021/03/10/x64dbg-shou-tuo-upx/
  • 版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!