拿到一个程序之后首先用PEID查看一下有什么有用的信息。
只能发现链接器版本是VC6.0。根据经验可以推论出此程序的OEP特征。
平衡堆栈的汇编代码:SUB esp,0x58
第一个调用的函数是:GetVersion()
类似的程序特征如下图。
程序入口有标准的pushad/pushfd,使用ESP定律下硬件执行断点。
运行之后依次找到pushfd pushad之后,单步几下就会到达oep位置。
到达程序入口点,ctrl+A进行分析之后发现,第一个函数没有显示Getversion()。推测可能被加密了。
壳当中生成加密IAT的步骤是:
获取原始IAT的函数地址,并保存到一定位置。
申请空间,构造新的IAT函数。
原始函数地址填充代码段,构造新IAT函数代码进行加密。
将新构造的函数地址填充到IAT表。
跟进去这个地址查看一下,发现返回值弹出真正的函数地址。
设置硬件断点,重新运行程序。
断到壳代码中填充IAT表的地方。
写入IAT的地方是一个循环,包括获取原始函数地址,函数地址被拷贝到新的代码段中,然后将新的代码段地址写入IAT。
首先在填充IAT处,下断点,ctrl+F11,进行run跟踪。
获取到原始函数地址。
继续往上查看EAX来自于哪。
将原始函数地址写入到代码段。
我们要做的任务就是把获取原始函数的地址填写到IAT中。
通过写脚本来运行。
//定义变量
VAR dwGetAPIAddr
VAR dwSetIATAddr
VAR dwOEP
VAR dwTep
MOV dwGetIATAddr,001D0474 // 获取 API 地址的地方
MOV dwSetIATAddr,001D0897 // 填充 IAT 的地方
MOV dwOEP, 0047148B // OEP
//去除断点
BC
BPHWC
BPMC
// 设置断点
BPHWS dwOEP, "x"
BPHWS dwGetIATAddr,"x"
BPHWS dwSetIATAddr ,"x"
//构造循环
LOOP1:
RUN //运行程序
//判断是否是获取API的地方
cmp eip, dwGetAPIAddr
JNZ SIGN1
mov dwTep,eax //将原始函数地址用一个临时变量保存
jmp LOOP1
//判断是否是填充API的地方
SIGN1:
cmp eip, dwSetIATAddr
JNZ SIGN2
mov [edx],dwTep //将原始函数地址写入IAT表
jmp LOOP1
//判断是否为OEP
SIGN2:
cmp eip, dwOEP //到达OEP处退出
JZ EXIT
jmp LOOP1
//结束
EXIT:
MSG "IAT解密完成"
脚本运行成功界面:
最后需要dump文件,修改输入表。
运行成功界面。
- End -
![640?wx_fmt=png](https://i-blog.csdnimg.cn/blog_migrate/ded141431f01bf17721def302f48dd83.jpeg)
看雪ID:Jabez
https://bbs.pediy.com/user-825190.htm
本文由 Jabez 原创
转载请注明来自看雪社区
![640?](https://i-blog.csdnimg.cn/blog_migrate/740edcc3db184e4e52c0c677aa63014b.gif)
热门图书推荐:
戳![640?](https://i-blog.csdnimg.cn/blog_migrate/d3bc08de195c10c9e4cbb1b4d7f8cbf5.png)
看雪学院官方QQ群
QQ:953174865
欢迎入群交流!
热门技术文章:
看雪CTF.TSRC 2018 团队赛 第十二题『移动迷宫』 解题思路
C/C++代码虚拟化保护 在移动端的应用
看雪CTF.TSRC 2018 团队赛 第十一题『伊甸园』 解题思路
从补丁到Root——CVE-2014-4323分析
公众号ID:ikanxue
官方微博:看雪安全
商务合作:wsc@kanxue.com