win7讲述人修复_Safengine Shielden v2.40 IAT修复及脚本编写(x64dbg)

作者受L4nce文章启发研究脱加密壳写脚本,先从简单程序入手,后遇SE的IAT加密问题。通过分析找到获取API地址的方法,修改脚本流程,还介绍了判断IAT调用类型的方法。此外,分享了写x64dbg脚本时遇到的问题及解决办法,建议在win7环境脱壳。
e2db7fa1fc643f941005fee42aa17b0c.png

前言

首先感谢L4nce前辈写的“ 浅谈Safengine系列脱壳 ”,给了我很大帮助,让我开始入门脱加密壳。

L4nce的这篇文章已经算是“巨人的肩膀”了,但我觉得仍有一些东西可以细写。由于是自己第一次研究脱壳写脚本,没有人指点,错误纰漏处还请指正包涵。

e2db7fa1fc643f941005fee42aa17b0c.png

我的奇妙之旅

到这里,我就假设大家已经看完L4nce的文章了。接下来我想谈一些他文章中没有写到或者写全的东西,以及一些我的“奇妙旅途”。

关于研究脱壳写脚本,我是先从简单程序(只有几个API调用的汇编程序)入手,分析调用iat的代码有什么特征和功能,然后写个简易脚本,测试脱壳成功了。再用相对复杂程序(易语言静态编译程序)测试脚本并完善修改。

这个方法在我看来或许比较耗时,但可以逐步解决难关,避免在莫名其妙的问题上“卡关”。

再来谈谈SE的IAT加密。。。刚开始按照L4nce的思路写脚本,最后测试脱壳什么的都成功了。。。直到我√上了“使用散列API函数名称”再测试脱壳,就失效了。

分析看了一下,不再走获得API地址的add edi,eax这条路了。这样就只能另辟蹊径获得API地址

这逼的我重新分析两种情况下call sedata_section的流程,以图寻找共同点和突破点。

一般来说,为了程序的速度,壳对原程序的iat调用的加密不会多厉害,最多是在第一次跑的时候跑的久一点,之后调用都是马上取得目标地址,调用API或者对寄存器赋值API地址。这一点,我认为不仅适用于se,也适用于其他加密壳,照着这个想法找下去,总能找到希望。

最终我找到了一个点:push xxxxxx 

 6be86084eb40b3ffebe18ca158057cc6.png

se在虚拟机中获取到目标(API)地址后会将其修改成push 目标地址

由此我修改了脚本流程:

1.找 call sedata_section

2.步进跟踪找push xxxxxx和cmp dword ptr ss:[esp+0x4],0

3.对push的立即数下硬件写入断点,以此来获得目标(API)地址

4.判断调用IAT的类型,做出修复

在第4点上,L4nce说了大部分情况,但有些特殊情况没有细说了。我在此把相关情况列一下:

常见: 

1.call dword ptr [iat]

2.jmp dword ptr [iat]

3.mov reg,dword ptr [iat]

   call reg

少见:

4.call @ jmp dword ptr [iat]

   jmp dword ptr [iat]

第4种情况的call,在加壳的时候有时候会加密,有时候不会(但其调用的 jmp dword ptr [iat] 是一定会加密的)。既然这样,就一律按加密的情况来考虑。

e2db7fa1fc643f941005fee42aa17b0c.png

判断调用IAT的类型

在L4nce方法的基础上,我做了一些较大的变动。方法如下:

1.分别对 call sedata_section+5和 call sedata_section+6这两处可能的返回地址下单字节断点(int3)

2.判断获取到的目标(API)地址所处地址是否大于壳区段,以此判断是否是Mov_Reg类型或者其他IAT调用类型

96f644ff4e80cfea9c1acc17db40bb8b.png

cb95a04b4b37f6b41539fae490ab50fc.png

其他IAT调用类型

00fa5bd000aa5d77dc07d7a3ba93c3f2.png(shadow已破)

3.1如果是 Mov_Reg类型,直接run,停在返回地址后,依次判断哪个寄存器参与了调用。

3.2如果是其他IAT调用的类型,先对其API地址下硬件执行断点再run,此时EIP停在API领空,判断[esp]是否与 call sedata_section+5或者 call sedata_section+6相等,或者都不相等。

4.1 如果与 call sedata_section+6相等,则是 call dword ptr [iat]

4.2 如果与 call sedata_section+5相等,则是

       call @ jmp dword ptr [iat]

       jmp dword ptr [iat]中的call

4.3 如果都不相等,则是 jmp dword ptr [iat]

至此,IAT的调用类型就判断完了,然后按照各自情况修复就可以了,可以直接参考脚本。

(特殊API如CreateThread不会填充push xxxxxx,手动修复即可)

e2db7fa1fc643f941005fee42aa17b0c.png

写脚本的奇妙旅途

写x64dbg脚本,还真是发生了不少“奇妙事件”。有些解决了,有些只能回避掉。

1. 单步步入(sti)无效:

在把EIP设置到call上后,第一次sti有一定几率停在原地不动

2. 跑脚本时奇奇怪怪的异常崩溃:

也是把EIP设置到call上后,步进追踪可能崩溃,可能出现异常访问(偏偏手动单步执行脚本就不会出现,换个系统也有可能不会再出现)。遇到这种情况,只能把地址加入ignore表,到时候手动修复。所幸这都是少数,一般就3个左右

3. 跑脚本跑得x64dbg崩溃:

这个还好,跑脚本前把GUI更新关闭,堆栈更新关闭,日志更新关闭即可。出现特殊情况了,再解开GUI更新,分析情况。

4. call压入错误返回地址

这个是最奇妙的。把EIP设置到call上后,第一次步进,,有几率出现压入错误的返回地址的现象!只能重新把EIP设置在call上,把之前的返回地址清0,再步进跟踪一次,就不会再出现了。

e2db7fa1fc643f941005fee42aa17b0c.png

尾声

L4nce在他的文中写到还有“被抽取的代码”,不过我脱壳时都没遇见到,不知道什么情况。

脱壳时建议选择win7环境(xp貌似用不了x64dbg),win10下脱出来的易语言静态编译程序 (其他语言程序没问题) ,在其他平台运行不了。只有win7脱下来的正常运行在其他平台(暂时只测试了xp,win7,win10)

脚本我写了比较多的注释,放上来供大家参考。至于特殊情况的判断和修复,相信对有心学习的人来说不是难事,对伸手党倒是难事。

637d884bfbf0a535a321dbc15210d535.gif

- End -

22c2b2fa18b8f512d97c391451bd1250.png

看雪ID:Lixinist      

https://bbs.pediy.com/thread-251066.htm

本文由看雪论坛 Lixinist   原创

转载请注明来自看雪社区

热门图书推荐

145a45573ec399c6b34d0dd1b4a184d3.png 立即购买!

热门文章阅读

1、GandCrab V2.0 详细分析

2、SSDT-HOOK

3、C++写壳详解之基础篇

59a3c599ee7dcbe39eedf1082eac3171.png

公众号ID:ikanxue

官方微博:看雪安全

商务合作:wsc@kanxue.com

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值