吾爱汇编

 找回密码
 立即注册

QQ登录

绑定QQ避免忘记帐号

查看: 6989|回复: 92

[原创逆向图文] 浅谈VMProtect 2.13.8 IAT修复

  [复制链接]
ICEY 发表于 2021-2-3 18:21 | 显示全部楼层 |阅读模式

本帖最后由 ICEY 于 2021-2-3 23:12 编辑

调试环境:吾爱汇编XP虚拟机
加密方式:默认




一、 壳到OEP的大致流程(只列出关键)
壳到OEP的大致流程.png
首先,载入OD后,先停在的VMP1区段。
    接触过VMP的人应该都知道 VirtualProtect 这个函数吧,找OEP用的。说通俗一点这其实就是一个改写 区段访问权限 的函数,VMP壳就是利用这个函数来清除我们在代码段 和 IAT 设置的内存访问断点。只要过了这个函数就可以在代码段设置访问断点了。


另外提一点,我们设置的 硬件访问 和 硬件写入 断点并不会被壳检测到,但是硬件执行断点会被检测到。 知道了 大致流程 和 哪些断点不被检测,我们就可以很轻易地找OEP了。这里给大家提供我找OEP的方法
(仅针对VMP 2.13.8):
先把程序运行起来,然后数据窗口定位到 代码段 的头部,往下拉,找到最后一个有效值(最后一个不是00的值),下一个硬件访问断点,重载程序,F9按两次(一次断在写入时,一次断在干扰时),再在代码段设置内存访问断点。就可以直接断在OEP了。

二、 api调用的分析

1.首先大家应该都知道,程序调用IAT的代码一般是:
CALL [IAT]    JMP [IAT]    mov e?? , [iat]
这三种(好像还有一种不太常见的,VC程序没有这种调用,所以这里不讲)
以下简称FF15,FF25,MOV型

2.然后,我们要知道,VMP壳对原先的IAT调用改成什么样子了。这里展示三个例子:CALL [IAT]:
加壳前:
加壳前ff15.png

加壳后:
加壳后ff15.png
JMP [IAT]:
加壳前:
加壳前FF25.png
加壳后:
加壳后FF25.png
mov e??,[IAT]
加壳前:
加壳前MOV.png
加壳后:
加壳后MOV.png


可以发现,FF 15 型的调用是 6 字节的,但重定向后的E8 是 5 字节的。
这里我们又要补充一个关于VMP对IAT重定向的知识:
VMP在加壳时会直接对代码段进行改写,将 大部分 的IAT调用均重定向到 VMP0 区段进行解密(这里和大部分加密壳不一样,大部分加密壳是对IAT表进行改写)。
又因为重定向的代码为E8,是 5 字节的,因此壳会随机填充一个字节。
填充的位置在 E8 call 的上面或者下面都有可能。
以下是VMP 重定向 和 原来的API调用 对比:
各种函数调用的类型.png
(此处没有 esp )

可以发现,关于寄存器EAX的iat调用,和VMP的重定向调用 一样,都是5字节的,也就意味着,对于mov eax,[IAT]这种类型,VMP在加壳时 是没有进行 补码 的。

那我们怎么知道一个被重定向的API,原先是什么,是以哪种方式进行调用的呢?这里我给大家提供一个我原创的方法。

首先我们先要知道,被重定向的API,进入了 VMP0 区段,再经过一系列的运算,得到真实的API的地址,放入堆栈,然后通过 RET 的方法进入真实的API。看图:
如何进入真实API.png
这是重定向CALL ,一直F7就可以到这一步。

这里我们用OD的跟踪步入功能,将条件设置为:
跟踪步入设置条件.png
两个地址自己在区段表查看,每一次加壳后的 地址都不一样,不是固定的。

这个一定要全程开着。脱壳脚本也要依赖这个。


设置好后,我们随便找一个 重定向CALL,设置为新EIP,然后手动 F7步入,然后点跟踪步入,之后OD就直接停在 出RET的第一句。

区别1:(这里我直接贴结论,你自己去程序试)
先把除了ESP,EBP以外的寄存器全部置0。不改ESP,EBP是防止程序崩溃。
对加壳前FF 15,FF 25 类型的调用,加壳后,通过上面操作,RET出来的第一句就是原API地址。
对加壳前MOV类型的调用,加壳后,通过上面操作,RET出来的第一句是在代码段。API放入寄存器的相应位置。

依照上面的区别,我们可以写出一个初步判断脚本,可以判断出原型是否为MOV型。

区别2:(这里我直接贴结论,你自己去程序试)
我们先将 [ESP]置1,[ESP+4]置2,[ESP+8]置3。(有助于判断)

进CALL前的堆栈:(各个类型都一样这样设置)
全部CALL进CALL前.png
原FF 15,且补码在前:RET到真实API后,堆栈:
FF15 前.png

原FF 15,且补码在后:RET到真实API后,堆栈:
FF 15 后.png

原FF 25,且补码在前:RET到真实API后,堆栈:
FF 25 前.png

原FF 25,且补码在后:RET到真实API后,堆栈:
FF 25后.png

原MOV,且补码在前:RET回代码段后,堆栈:
MOV 前.png

原MOV,且补码在后:RET回代码段后,堆栈:
MOV 后.png


通过区别1和区别2,我们就可以很清楚地知道,这个被重定向的API,原来是什么,是怎么被调用。然后修复是应该从哪个地址开始修改代码。
(若补码在前,则在重定向CALL的地址 -1 处开始修改,若补码在后,则直接从重定向CALL的地址开始修改)

我利用这两个区别,就能写一个完整的判断脚本,判断这个CALL的原型,并且补码在前还是在后。(记得把跟踪步入的条件设置好哦)
结论:
先经过区别1将MOV型和FF15、FF25型分开

若已知不是MOV型:
RET到API,且[ESP]=1:FF25型,补码在后
RET到API,且[ESP+4]=2:FF15型,补码在前
RET到API,且[ESP+4]=1:FF15型,且补码在后
RET到API,且[ESP+4]=3:FF25型,且补码在前

若已知是MOV型:
RET回代码段,且[ESP]=1:补码在后
否则补码在前

例如:我们再用到上面的图。
看上面展示的FF15型的图,重复发不了。

我们是因为有未加壳的原程序,才知道他的原型是FF 15,且补码在前。
那么我们假设,我们并不知道它的原型,
那我们来跑一遍刚刚的脚本来判断他的类型。
(判断脚本我会提供,当然了我说了原理,所以你们也可以自己写)
在这个CALL右键点击此处为新EIP,然后运行我写的判断类型脚本。就可以知道他的原型和RET出来之后的地址了。
试用判断.png
以上61B71D就是出RET后的第一句(EIP会停在出RET的第一句,这看来是一个二次重定向啊),然后看信息框,原型是FF15,且补码在前(qian)。
至于为什么用拼音不用中文,因为记事本的编码问题,用中文会乱码。你们自己改判断脚本吧。

三、    修复脚本的逻辑解释
注意上面有说,脚本要依赖 OD 的跟踪步入,记得设置好条件
脚本的大致步骤:

1.从代码段头开始搜索 符合条件的CALL (也就是CALL VMP0区段 的)
2.判断这个CALL的原始类型(上面讲了判断的方法)
3.修复这个IAT调用(通过上面的判断来选择修复方法。改写代码段,使其恢复原本的调用类型)
4.搜索下一个符合条件的CALL(若不存在,跳转到结束)
5.返回 步骤2

以下是一些细节:
1.
修复的方式:
修复前:
示例修复前.png
修复后:
修复示例.png
他会将原本的API填入IAT表。顺序是搜索符合条件的顺序。

2.每获得一个API,脚本就会遍历已修复了的API,看看是否有重复的,若无重复,则填入iat下一个地址,若有重复,就不填入IAT,再修改代码段对应代码 指向 重复的地址。
不填入重复的API可以保证填入的API个数不会超过 原定IAT中API的个数,也就是不会溢出,覆盖其他有效数据。

3.对于修复不了重定位,会在C盘输出一个TXT,里面的地址就是需要你手动进行修复的地址。

4.因为OD脚本插件的一些BUG,所以有一些明明符合特征的CALL,有时却没有搜索得到,此时要右键分析代码,再跑一次脚本(又要改一个数据)。

关于这个脚本,并不是直接可以用的,要根据你的程序,特定的数据进行修改。
例如:
条件.png
还有一个特征码(用于寻找CALL VMP0段 的地址),这个根据VMP0区段的地址范围来找。首先你要知道一个 e8调用时后面跟的是函数地址相对于当前地址的偏移量。


举个找特征码的例子:
Vmp0 区段的地址是 从 53C000 ~ 615000
那么,你去代码段的头,输入 CALL 615000(VMP0段尾)   得到:
00401000      E8 FB3F2100   call 未加壳_v.00615000
    再到代码段的尾(不用真的到尾,接近就行了),输入 CALL 53C000(VMP0段首)得到:
    004801E3      E8 18BE0B00   call 未加壳_v.0053C000
    这样,你就可以得到两个极限值,也就是说所有的CALL VMP0段的CALL,E8后面的数值肯定  大于 18BE0B00 ,小于 FB3F2100 (小端序程序,以字节为个体从后往前看)
我们就可以得到 特征码:
特征码1.png ,, 特征码2.png ,  , 特征码3.png ,,
合并一下同类项:
E8????2?00
E8????1?00
E8????0F00
E8????0E00
E8????0D00
E8????0C00
E8????0B00


这就是要填入脚本的特征码了,有多少个特征码,就至少要运行多少次脚本。
修改的方法举个例子:
假设你用E8????1?00当特征码修复了若干个函数弹出脚本运行完成。那么改法如下:
脚本用法.png
这个IAT改成下一个要填充的地址,然后再把红框中的特征码改掉。
然后再运行一次脚本。结束后这两个数据又要改。直到你将所有的特征码都试完。
(不过上文我有说,OD跑脚本插件有BUG,可能有一些第一次没被搜索到,所以你可以试着多跑几次脚本。但记得改上图中IAT那个数据。)
(就算是脚本,也要修复挺久的,更别说手动修复了。)

四、    手动修复

上面跑完所有特征码后,就可以将绝大部分的重定向API都修复好,这时打开C盘,看看有没有用脚本修复失败的API,手动修复。
确实有一个:476FB8
修复示例0.png
其实这个我试了很多次,是至少必有一个函数是修复失败的。我们利用我上面提供的判断类型的脚本。可以先知道它的类型。
例外0.png
FF15型,补码在前,RET出来后停在77FE0000。
其实这个呢,就是一个被偷掉开头的函数,从77FE0000,到77FE0003,就是VMP偷走的函数头,下一个JMP就是跳回那个函数的对应行。我们将这个头以二进制形式复制下来,然后跟入下面那个CALL,将头补回去,你就可以知道这个函数是什么了。
得到真实API.png
我们直接手动在 476FB8-1 这个地址修改就行了。记得将API记录下来,手动填到IAT中。

其实干完这一步,我们就已经修复完所有的API了。可以用OD自带的插件DUMP出来一份(保留以下现场),这是可以运行的但是跨平台不能运行。但此时你用REC也修复不了,因为我们修复出来的IAT是乱序的,并不是以一个一个DLL的顺序排列好。

所以我们要先用UIF进行修复(也就是帮我们排序)。不得不说UIF是真的强大。
但是用UIF前,我们先要先进行其他的操作。

用ODdump出来的那一份程序进行修改:
1.将dump出来那一份脱壳版拖进 StudyPE+ x86 ,给它加一个区段,用于存放我们UIF修复的API。(在原有的IAT进行修复可能会出错)

2.再将添加了区段的脱壳版 拖进OD,在我们修复的IAT中找到二次重定位的API,将它更改,直接填入真实的API。(因为UIF识别不了重定向的api,会修复错误。)
二次重定向.png
很好找的, 看看数据和其他对比一下大小就知道了。(一般有两个二次重定向)

3.打开UIF,填入PID,代码段的头,代码段的尾,和我们添加的区段的头部地址。勾选修复输入表。然后点击修复。
UIF修复后.png
修复后,排好了顺序

3.用UIF修复完后,我们就可以直接用REC进行跨平台修复了。选择我们加了区段的脱壳版,填好OEP偏移,和UIF修复后的地址(也就是我们新加的区段头地址)。点获取。
REC填入.png
然后修复转存到 你加了区段的脱壳版 上就可以完美修复了。

XP系统下脱壳修复,WIN10上运行:
win10.png

加壳工具,例子(未加壳版,加壳版,脱壳修复版),脚本(判断类型、修复)打包下载地址:
打包下载.zip (234 Bytes, 下载次数: 54)

ps:如果你在其他论坛也看到此篇文章,看ID,你就知道还是我。
加密选项.png

评分

参与人数 44威望 +1 HB +152 THX +19 收起 理由
xiaoxixpj + 1 [吾爱汇编论坛52HB.COM]-感谢楼主热心分享,小小评分不成敬意!
854335132 + 1 [吾爱汇编论坛52HB.COM]-软件反汇编逆向分析,软件安全必不可少!
NOP + 1
longge188 + 1 [吾爱汇编论坛52HB.COM]-吃水不忘打井人,给个评分懂感恩!
虚心学习 + 1 [吾爱汇编论坛52HB.COM]-感谢楼主热心分享,小小评分不成敬意!
459121520 + 1
消逝的过去 + 1
纯英文 + 1
冷亦飞 + 1
飞刀梦想 + 1
MoeRay + 1
逝水流年 + 1
我是好人 + 1 [吾爱汇编论坛52HB.COM]-软件反汇编逆向分析,软件安全必不可少!
XiaoWeiSec + 1
ldljlzw + 1
playboy + 2
boot + 2
davidhee + 1 + 1 [吾爱汇编论坛52HB.COM]-感谢楼主热心分享,小小评分不成敬意!
hotD + 2 + 1
kalove + 1
kll545012 + 1 [吾爱汇编论坛52HB.COM]-软件反汇编逆向分析,软件安全必不可少!
上帝的恩赐 + 1 [吾爱汇编论坛52HB.COM]-感谢楼主热心分享,小小评分不成敬意!
temp + 1 + 1
成丰羽 + 1 [吾爱汇编论坛52HB.COM]-感谢楼主热心分享,小小评分不成敬意!
ams + 1
53956250 + 1
bnjzzheng + 1 [吾爱汇编论坛52HB.COM]-吃水不忘打井人,给个评分懂感恩!
1587665267 + 1
Marriner + 1 + 1 图文并茂的好文。
a810680485 + 1 + 1
eurchin + 1 + 1 [快捷评语]--吃水不忘打井人,给个评分懂感恩!
fubodadi + 1
zwj00544 + 1 + 1
king51999 + 1 [快捷评语]--积极评分,从我做起。感谢分享!
kaoliu35 + 1
firstcmm + 1 [快捷评语]--你将受到所有人的崇拜!
lies + 1
爱解码 + 1
jjpp001 + 1 + 1 论坛的秩序需要大家共同监督与维护,感谢!
HlccFu + 5 + 1 [快捷评语]--你将受到所有人的崇拜!
Shark恒 + 1 + 100 + 1 [快捷评语]--你将受到所有人的崇拜!
洋葱、 + 2 + 1 [快捷评语]--吃水不忘打井人,给个评分懂感恩!
我是墨白!! + 3 + 1
莣孒嬡沵芣蓜 + 6 + 1 [快捷评语]--你将受到所有人的崇拜!

查看全部评分

吾爱汇编论坛-学破解,防破解!知进攻,懂防守!逆向分析,软件安全!52HB.COM
HlccFu 发表于 2021-2-4 15:48 | 显示全部楼层
吾爱汇编论坛-学破解,防破解!知进攻,懂防守!逆向分析,软件安全!52HB.COM
666888tzq 发表于 2021-2-6 13:32 | 显示全部楼层

厉害了,帮顶。
吾爱汇编论坛-学破解,防破解!知进攻,懂防守!逆向分析,软件安全!52HB.COM
yimilee 发表于 2021-4-23 16:23 | 显示全部楼层
吾爱汇编论坛-学破解,防破解!知进攻,懂防守!逆向分析,软件安全!52HB.COM
mirvc 发表于 2021-4-24 22:45 | 显示全部楼层

感谢楼主分享
吾爱汇编论坛-学破解,防破解!知进攻,懂防守!逆向分析,软件安全!52HB.COM
保安 发表于 2021-12-9 16:11 | 显示全部楼层
吾爱汇编论坛-学破解,防破解!知进攻,懂防守!逆向分析,软件安全!52HB.COM
头像被屏蔽
kisny 发表于 2021-12-25 17:05 | 显示全部楼层

可以回复看一波
吾爱汇编论坛-学破解,防破解!知进攻,懂防守!逆向分析,软件安全!52HB.COM
king51999 发表于 2021-12-28 22:36 | 显示全部楼层


感谢楼主分享
吾爱汇编论坛-学破解,防破解!知进攻,懂防守!逆向分析,软件安全!52HB.COM
乌云 发表于 2021-12-29 00:50 | 显示全部楼层


感谢楼主分享
吾爱汇编论坛-学破解,防破解!知进攻,懂防守!逆向分析,软件安全!52HB.COM
bnjzzheng 发表于 2021-12-29 08:43 | 显示全部楼层

大佬贴,膜拜大佬
吾爱汇编论坛-学破解,防破解!知进攻,懂防守!逆向分析,软件安全!52HB.COM
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

警告:本站严惩灌水回复,尊重自己从尊重他人开始!

1层
2层
3层
4层
5层
6层
7层
8层
9层
10层

免责声明

吾爱汇编(www.52hb.com)所讨论的技术及相关工具仅限用于研究学习,皆在提高软件产品的安全性,严禁用于不良动机。任何个人、团体、组织不得将其用于非法目的,否则,一切后果自行承担。吾爱汇编不承担任何因为技术滥用所产生的连带责任。吾爱汇编内容源于网络,版权争议与本站无关。您必须在下载后的24个小时之内,从您的电脑中彻底删除。如有侵权请邮件或微信与我们联系处理。

站长邮箱:SharkHeng@sina.com
站长QQ:1140549900


QQ|RSS|手机版|小黑屋|帮助|吾爱汇编 ( 京公网安备11011502005403号 , 京ICP备20003498号-6 )|网站地图

Powered by Discuz!

吾爱汇编 www.52hb.com

快速回复 返回顶部 返回列表