吾爱破解 - LCG - LSG |安卓破解|病毒分析|www.52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

搜索
查看: 3619|回复: 38
上一主题 下一主题
收起左侧

[原创] 浅谈VMProtect 2.13.8 IAT修复

  [复制链接]
跳转到指定楼层
楼主
ICEY 发表于 2021-2-3 18:22 回帖奖励
本帖最后由 ICEY 于 2021-2-5 15:13 编辑

前言:
这篇文章是《浅谈壳IAT修复》系列的最终章了,这段时间应该都不会再出这个系列了。所以我尽量写的清晰一点,详细一点。至于为什么是最终章,因为我最近真的太累了,放假这么久还没放松过,而且,我也没有再出下去的动力了。主要是没人看。唉。
往期回顾:

那我们开始吧。
加密方式以及版本:
环境:XP SP3
正片:



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


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

二、 api调用的分析

1.首先大家应该都知道,程序调用IAT的代码一般是:
[Asm] 纯文本查看 复制代码
CALL [IAT]    JMP [IAT]    mov e?? , [iat]
这三种
以下简称FF15,FF25,MOV型

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


加壳后:

JMP [IAT]:
加壳前:

加壳后:

mov e??,[IAT]
加壳前:

加壳后:



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

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

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

首先我们先要知道,被重定向的API,进入了 VMP0 区段,再经过一系列的运算,得到真实的API的地址,放入堆栈,然后通过 RET 的方法进入真实的API。看图:

这是重定向CALL ,一直F7就可以到这一步。

这里我们用OD的跟踪步入功能,将条件设置为:

两个地址自己在区段表查看,每一次加壳后的 地址都不一样,不是固定的。

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


设置好后,我们随便找一个 重定向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前的堆栈:(各个类型都一样这样设置)

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


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


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


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


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


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



通过区别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:补码在后
否则补码在前

例如:我们再用到上面的图。
加壳前:

加壳后:

我们是因为有未加壳的原程序,才知道他的原型是FF 15,且补码在前。
那么我们假设,我们并不知道它的原型,
那我们来跑一遍刚刚的脚本来判断他的类型。
(判断脚本我会提供,当然了我说了原理,所以你们也可以自己写)
在这个CALL右键点击此处为新EIP,然后运行我写的判断类型脚本。就可以知道他的原型和RET出来之后的地址了。

以上61B71D就是出RET后的第一句(EIP会停在出RET的第一句,这看来是一个二次重定向啊),然后看信息框,原型是FF15,且补码在前(qian)。
至于为什么用拼音不用中文,因为记事本的编码问题,用中文会乱码。你们自己改判断脚本吧。

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

1.从代码段头开始搜索 符合条件的CALL (也就是CALL VMP0区段 的)
2.判断这个CALL的原始类型(上面讲了判断的方法)
3.修复这个IAT调用(通过上面的判断来选择修复方法。改写代码段,使其恢复原本的调用类型)
4.搜索下一个符合条件的CALL(若不存在,跳转到结束)
5.返回 步骤2
(可以去下载脚本看是如何进行代码段的修复)
为了大家方便理解我还把脚本写的特别简单,没有什么复杂语句。并且还有一些中文注释便于理解。

以下是一些细节:
1.
修复的方式:
修复前:

修复后:

他会将原本的API填入IAT表。顺序是搜索符合条件的顺序。

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

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

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

关于这个脚本,并不是直接可以用的,要根据你的程序,特定的数据进行修改。
例如:

还有一个特征码(用于寻找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 (小端序程序,以字节为个体从后往前看)
我们就可以得到 特征码:
  ,, ,  , ,,
合并一下同类项:
E8????2?00
E8????1?00
E8????0F00
E8????0E00
E8????0D00
E8????0C00
E8????0B00


至于为什么不合并E8????0?00,是因为符合这个特征的不仅有CALL VMP0段。更多的是CALL TEXT段。干扰太多,脚本就跑的极慢。
这就是要填入脚本的特征码了,有多少个特征码,就至少要运行多少次脚本。
修改的方法举个例子:
假设你用E8????1?00当特征码修复了若干个函数弹出脚本运行完成。那么改法如下:

这个IAT改成下一个要填充的地址,然后再把红框中的特征码改掉。
然后再运行一次脚本。结束后这两个数据又要改。直到你将所有的特征码都试完。
(不过上文我有说,OD跑脚本插件有BUG,可能有一些第一次没被搜索到,所以你可以试着多跑几次脚本。但记得改上图中IAT那个数据。)
(就算是脚本,也要修复挺久的,更别说手动修复了。)

四、    手动修复

上面跑完所有特征码后,就可以将绝大部分的重定向API都修复好,这时打开C盘,看看有没有用脚本修复失败的API,手动修复。
确实有一个:476FB8

其实这个我试了很多次,是至少必有一个函数是修复失败的。我们利用我上面提供的判断类型的脚本。可以先知道它的类型。

FF15型,补码在前,RET出来后停在77FE0000。
其实这个呢,就是一个被偷掉开头的函数,从77FE0000,到77FE0003,就是VMP偷走的函数头,下一个JMP就是跳回那个函数的对应行。我们将这个头以二进制形式复制下来,然后跟入下面那个CALL,将头补回去,你就可以知道这个函数是什么了。

我们直接手动在 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,会修复错误。)
很好找的, 看看数据和其他对比一下大小就知道了。(一般有两个二次重定向)

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

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

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

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

ps:如果你在其他论坛也看到此篇文章,看ID,你就知道还是我。
如果你觉得我这篇文章还行,请给我一个免费的热心值,求求了,这对我真的很重要!


免费评分

参与人数 64威望 +2 吾爱币 +167 热心值 +61 收起 理由
hlfadzchlfhf + 1 + 1 用心讨论,共获提升!
ezaizeli + 1 热心回复!
tandekun + 1 + 1 写的很多
临时户口 + 1 谢谢@Thanks!
风入白袍 + 1 用心讨论,共获提升!
yywyf0001 + 1 + 1 热心回复!
hjm666 + 2 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
gaosld + 1 + 1 用心讨论,共获提升!
2333o + 1 + 1 谢谢@Thanks!
Mandrake + 1 + 1 谢谢@Thanks!
clide2000 + 1 + 1 我很赞同!
xukefei + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
lynlon + 1 + 1 热心回复!
吾爱破解1111 + 1 + 1 谢谢@Thanks!
kkkwz + 1 + 1 技术含量很高,很经典
sumingzhe + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
该起来努力了 + 1 谢谢@Thanks!
tingnixingxing + 1 我很赞同!
mmp211 + 1 鼓励转贴优秀软件安全工具和文档!
浮萍漂泊本无根 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
石碎大胸口 + 1 + 1 用心讨论,共获提升!
该吃饭了。。 + 1 + 1 热心回复!
mai1zhi2 + 1 我很赞同!
Neko + 1 + 1 我很赞同!
xingc119 + 1 + 1 我很赞同!
lookerJ + 1 + 1 热心回复!
s54713085 + 1 用心讨论,共获提升!
c_ailu001 + 1 + 1 我很赞同!
evea + 1 + 1 谢谢@Thanks!
魔道书生 + 2 + 1 我很赞同!
whc2001 + 2 + 1 看不大懂,牛逼就完事了
winddyj + 1 + 1 希望能继续写下去
uyspace + 1 + 1 我很赞同!
齐恩 + 1 + 1 444不太吉利 再来一分
aywl47 + 1 + 1 我很赞同!
Sound + 2 + 100 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
610100 + 3 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
材鸟 + 2 + 1 精华
solly + 3 + 1 用心讨论,共获提升!
gxwtk + 1 + 1 用心讨论,共获提升!
奈落堇梦 + 2 + 1 用心讨论,共获提升!
抱书人人 + 1 + 1 谢谢@Thanks!
穿透骨頭撫摸妳 + 1 + 1 膜拜大佬
adime2018 + 1 + 1 我很赞同!
fangchang819 + 1 + 1 热心回复!
qzhsjz + 1 + 1 必须资瓷
不爱everyone + 1 + 1 用心讨论,共获提升!
xinzdf110 + 1 + 1 热心回复!
朱朱你堕落了 + 3 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
vison.v + 1 + 1 我很赞同!
kelvar + 1 + 1 谢谢@Thanks!
allan147 + 1 + 1 就算理解不太好,也要给大佬加分
ycwq110 + 1 + 1 谢谢@Thanks!
笙若 + 1 + 1 谢谢@Thanks!
perror + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
宅の士 + 1 用心讨论,共获提升!
正己 + 2 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
夜泉 + 1 鼓励转贴优秀软件安全工具和文档!
ipc2008 + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
绿雪羚羊 + 1 + 1 谢谢@Thanks!
q510 + 2 + 1 我很赞同!
初吻给奶嘴耶 + 1 + 1 我很赞同!
peter_king + 1 谢谢@Thanks!
R-R, + 1 + 1 谢谢@Thanks!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

推荐
 楼主| ICEY 发表于 2021-2-3 18:53 |楼主
初吻给奶嘴耶 发表于 2021-2-3 18:48
emm  有个疑问
vmp3.x 没有遇到 mov reg, [function] 这种被vm  不知道是不是vmp2才有 还是我某个选项没有 ...

不好意思。没有研究过。我水平太低了。
推荐
初吻给奶嘴耶 发表于 2021-2-3 18:48
emm  有个疑问
vmp3.x 没有遇到 mov reg, [function] 这种被vm  不知道是不是vmp2才有 还是我某个选项没有勾选?   
沙发
R-R, 发表于 2021-2-3 18:29
5#
q510 发表于 2021-2-3 18:58
真是太难了,
6#
初吻给奶嘴耶 发表于 2021-2-3 18:58
ICEY 发表于 2021-2-3 18:53
不好意思。没有研究过。我水平太低了。

感谢分享  那我去康康
7#
zwtstc 发表于 2021-2-3 20:21
本帖最后由 zwtstc 于 2021-2-3 20:23 编辑

谢谢分享
8#
宅の士 发表于 2021-2-3 20:45
VMP脱壳有些难,我都是基本能不脱壳完成破解或运行时资源替换尽量不脱
9#
普罗米修斯、 发表于 2021-2-3 21:14
感谢分享
10#
Airey 发表于 2021-2-3 21:16
感谢分享!!!!
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则 警告:本版块禁止灌水或回复与主题无关内容,违者重罚!

快速回复 收藏帖子 返回列表 搜索

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2021-2-25 05:33

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

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