-
-
[原创]通过x64dbg脚本功能修复IAT表
-
发表于:
2022-8-2 01:34
28542
-
[PEDIY.华章 Crackme 竞赛 2009] [第十回] –ninejs
感兴趣可自行去下载,看到下面评论也不少在说会dump但不会修复IAT表,故开此贴简单介绍一下刚学的方法
通过栈平衡应该可以很快定位到OEP位置,这种基础操作不再赘述
确定入口点在0x0047148B
,此处下硬件执行断点,方便下次快速定位
直接先 dump 一手,有问题再慢慢修
x64dbg 下方控制台可输入scylla
指令,调出 scylla 工具,直接点上方图标也可以
确认 OEP 地址是否正确,然后点击 dump,成功后可以看到源文件目录下多了一个后缀为 xxx_dump
的文件,双击运行
不出意外的话是无法正常运行的,这时候不要慌,将此文件拖入 x64dbg,咱们一步步看问题出在哪了
这个 x64dbg 的脚本语法和汇编还挺像,里面可以用变量,可以用条件跳,可以添加段声明,这里简单说一下老王的思路
他首先确定了 IAT 表的范围,然后直接对 IAT 表进行遍历,把 EIP 依次设为表中的地址开始跑,每跑完一次就把获取到的地址写回,跑完即可把 IAT 表修复
但他这个判定方法很奇葩,还记得我们上面说的call [0x475080]
,这个函数是通过ret
下方的四个字节作为跳板跳到系统 API,他这就是吃定了每个函数都用这种方法跳转
但现实可能真的这么简单吗?然后课堂上就被打脸了,有的地方用的是jmp xxx
,有的地方是call reg
,这种跳转的,脚本根本无法正常获取到地址,最后老王只能灰溜溜的手动修复了剩下的部分
欸嘿,是时候到我表演真正的技术了!经过我花了数小时仔仔细细,认认真真把 x64dbg 手册翻了个遍,终于我悟了,老王他不行,我行!开玩笑哈,我就是吹水比他强
首先咱们还是基于老王这个思想进行架构,遍历没问题,修改EIP
没问题,但置单步和这个判定逻辑咱们得改,自己置单步实在是太慢了,我们可以用 x64dbg 的 api,让他帮我们跑,这样效率会更高,比如说像“跟踪”菜单里的“步进直到条件满足”,直接在这里写暂停条件肯定比我们自己置单步判断条件来的快,我这里主要用到了一个重要 API:RunToParty
,这个函数的功能是运行到指定模块,参数0为用户模块,参数1为系统模块,我的想法很简单,我管你是用什么方式跳转的,反正你肯定要跳转到系统模块,只要在这个时候断下,我们就能拿到系统函数的首地址,我本来这里用的是模块地址范围做逻辑判断的,正好看到有这么一个函数,倒省了我一番心思,ok,上代码
我的这种写法 x64dbg 也是支持的,是不是十分的简洁明了,运行完脚本之后,可以看到 IAT 表已经被完美修复
这时候我们再打开scylla
工具,确定好 OEP,直接点击 IAT AutoSearch,然后点击 Get Imports,此时表已经能被加载出来,点击右侧的 Fix Dump,选择我们之前 dump 出来无法正常运行的文件,大功告成,新生成的xxx_dump_SCY
已经能够完美运行,拖进 IDA 也可以清楚的看到调用的函数,收工!
/
/
运行到OEP
bph
0x47148b
/
/
设定硬件执行断点
g
/
/
导入表范围
/
/
表范围可以通过内存页跳转至
0x475080
直接看出来
impStart
=
0x00475000
impEnd
=
0x00475120
WHILEBEGIN:
/
/
取出一项
mov itaItem, dword:[impStart]
/
/
跳过
0
cmp
itaItem,
0
jz WHILECONTINUE
/
/
设为新的EIP
mov eip, itaItem
/
/
单步,直到遇到ret
SETBEGIN:
sti
/
/
置单步
/
/
判断是否到达ret
mov code, byte:[eip]
/
/
ret的机器码为
0xC3
cmp
code,
0xC3
jnz SETBEGIN
/
/
从栈顶取出API地址,存入IAT对应项
mov apiAddr, dword:[esp]
mov dword:[impStart],apiAddr
WHILECONTINUE:
add impStart,
4
cmp
impStart, impEnd
jb WHILEBEGIN
ret
/
/
运行到OEP
bph
0x47148b
/
/
设定硬件执行断点
g
/
/
导入表范围
/
/
表范围可以通过内存页跳转至
0x475080
直接看出来
impStart
=
0x00475000
impEnd
=
0x00475120
WHILEBEGIN:
/
/
取出一项
mov itaItem, dword:[impStart]
/
/
跳过
0
cmp
itaItem,
0
jz WHILECONTINUE
/
/
设为新的EIP
mov eip, itaItem
/
/
单步,直到遇到ret
SETBEGIN:
sti
/
/
置单步
/
/
判断是否到达ret
mov code, byte:[eip]
/
/
ret的机器码为
0xC3
cmp
code,
0xC3
jnz SETBEGIN
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!