avatar

目录
E盾VMP前与VMP后的逆向

因为加了VMP之后,很多东西都看不到,所以先通过源码来找出不会被vm的特征码,方便下一步逆向。

E盾有源码,先看下源码分析,有个检测od的子程序,也就是禁止调试。那么也就是第一步要先处理这个检测od

E盾分析流程

检测OD -> 登录 -> 合法 -> JS运算 -> 时间

下文中的12

检测OD

托进od,字符串搜索127.0.0.1,因为根据源码可知,这里上面的子程序就是检测od

点进去,会发现上面有几个call,那么如何确定那个是检测OD的了,在每个call下断然后F8运行,当运行到一个CALL时候,弹出弹框说检测到非法调试,那就是了。通过这个蠢方法我找到了,也标上注释了。

在这里断下,运行到这里,F7跟进去,发现非法工具就说明进去到了检测ODCALL内了,那么也有两个call

1那个call是什么了,看下面的字段。这里和源码这里就很像,如果a!=0,就弹出发现非法工具,跳转也实现了,说明要这个call 返回0就可以了

Code
1
2
mov [local.1],eax //将eax赋值给local.1
cmp [local.1],0x0 //将local.1和0比较

F7跟进这个CALL

Code
1
2
3
0041BDD1   $  55            push ebp
0041BDD2 . 8BEC mov ebp,esp
0041BDD4 . 81EC 04000000 sub esp,0x4

Code
1
2
3
4
5
0041BDD1      B8 00000000   mov eax,0x0
0041BDD6 C9 leave
0041BDD7 C3 retn
0041BDD8 90 nop
0041BDD9 90 nop

现在目的达到了。可以正常运行不禁止调试。那么2那个call有什么用了。刚进这个call时候都可以发现,有vmp的代码,就是这句,要找一处可以做特征码的地方,那么即使碰到Vmp时候也可以定位到,因为有时候是不能像刚才那样子通过搜索字符串跟过来的

Code
1
0041FF8F  |.  56 4D 50 72 6>ascii "VMProtect begin",0

所以跟进2那个call

Code
1
2
3
4
5
0040106F   $  5E            pop esi
00401070 > 6A 00 push 0x0
00401072 . 4B dec ebx
00401073 .^ 75 FB jnz short 网络验证.00401070
00401075 . FFE6 jmp esi

另一种情况

如果是直接通过特征码定位过来的话,jmp esi也会跳到这里,处理方法一样

Code
1
2
3
mov eax,0
leave
ret

检测OD特征码:

Code
1
5E 6A 00 4B 75 FB FF E6

登录

正常运行以后,有按钮,所以在OD下按钮事件断点

Code
1
FF 55 FC 5F 5E

F7跟进去

根据源码来分析

往下拉,有个登录中字符串,那么登录中下面两个call其中一个可能就是处理事件了,为什么这么猜测,因为跟进那俩个call。他是跳到易语言核心支持库那块的。

一路F8跟下去先分析代码,来到一个关键跳转,注释里写明白了代码分析

为什么说是关键跳转了,往下拉一点,就可以看到这些字符串,看代码那块就可以知道,这里是验证是否登录成功,如果登录成功就写配置项了。

在给eax赋值那个call下断跟进去,分析代码

Code
1
2
3
4
004015D1   .  E8 BBAC0200   call 网络验证.0042C291
004015D6 . 83C4 10 add esp,0x10
004015D9 . 8945 E8 mov dword ptr ss:[ebp-0x18],eax
004015DC . 837D E8 01 cmp dword ptr ss:[ebp-0x18],0x1

Code
1
2
3
4
5
6
004015D6      B8 01000000   mov eax,0x1
004015DB C9 leave
004015DC C3 retn
004015DD 90 nop
004015DE 90 nop
004015DF 90 nop

在这个retn出去以后,就会发现那个跳转没有实现,一路F8走下去看源码就知道,三个写配置项后,就是合法检测


合法


跟到这里,有三个call,按照刚才的蠢方法,分析那个call会崩溃

在这个callF7跟进去

Code
1
2
3
00415930  |.  E8 7A690100   call 网络验证.0042C2AF                       ;  核心支持库
00415935 |. 83C4 10 add esp,0x10
00415938 |. 68 01000000 push 0x1

这里,有两处相似的代码段,把上面的那段注释为2,底下那段注释为1

从登陆开始,就会发现,很多处代码都一直在调用到这里,所以我觉得这里一定有很大用处,所以在12的头部都分别下断。

现在跟进来后,断在了2处,一路F8运行出去

Code
1
2
3
4
00415930  |.  E8 7A690100   call 网络验证.0042C2AF                       ;  核心支持库
00415935 C9 leave
00415936 C3 retn
00415937 90 nop

然后点击运行,就会发现,又回到了刚才的核心支持库中,在F8运行出来,会跳到进去之前的下个call,这个call原本是运行不到的,因为当运行到上个call时,就会崩溃,那么来到这里,碰运气,也将他

Code
1
2
leave 
ret

接着在点运行, 发现又回到了核心支持库,又跟出来,按照刚才的处理方法。

然后运行

直接就弹出窗口了,显示登陆成功,连后面的运算,补时间都不用,但是明显这样是不行的, 因为后面如果有暗桩,这样子处理的话会闪退。


所以重新运行程序,通过刚才的处理也知道,很多处调用了核心支持库,所以这次直接从核心支持库下手。而且最重要的就是,核心支持库,不担心他被VMP,即使被VMP了,也可以照着样子直接还原。

在核心支持库12的尾部下断,也就是retn的位置

输入了帐号密码后,第一次断下,按照经验这个可能是处理事件,因为刚才分析时候也发现处理事件也会调用到这里,所以再次点运行

看右下角堆栈窗口,有明文12123就是帐号,这时候F7跟出去

Code
1
2
3
4
0040159C   .  E8 F0AC0200   call    0042C291
004015A1 83C4 10 add esp, 0x10
004015A4 8945 F4 mov dword ptr [ebp-0xC], eax
004015A7 837D F4 01 cmp dword ptr [ebp-0xC], 0x1

Code
1
2
3
4
5
6
004015A1      B8 01000000   mov     eax, 0x1
004015A6 C9 leave
004015A7 C3 retn
004015A8 90 nop
004015A9 90 nop
004015AA 90 nop

接下来就是合法了,仔细想,刚才处理合法时,他调用核心支持库时,多是调用2的那处,所以这时候运行一下,但是会发现一直都是断在1处,那么把1的断点,先取消,在次运行,就发现,断在了2处,F7跟出去

这个注释很眼熟把,就是刚才处理合法时候下的。

Code
1
2
3
00415935      C9            leave                                    ;  出来来到了这里,直接leave出去
00415936 C3 retn
00415937 90 nop

为什么我可以肯定这里就是合法了,因为我用前辈经验总结出来的一个特征码定位过,是同一处地方。

通过特征码搜索

Code
1
8B 44 24 0C 56 8B 30 56

然后有得程序会搜出三个,但是在这里只能搜出两个,不论搜出几个,在倒数第二个的头部下断,然后F8一路跟进去

走到retn以后,会发现,又走到了2这里。继续走出去

看。同一处地方。


JS运算

合法处理完后,就该到JS的运算了,为什么要处理,因为如果不处理,直接运行,会一直断在1处,然后就会是一堆机器码啊,不知道什么时间戳还有一堆乱七八糟的东西运算,所以把这里leave retn了防止干扰分析

这时候把核心支持库的俩个断点取消,把按钮事件的断点打开

F7跟进

往下看

到了这一块代码了

在易语言函数拼接那个CALL里下断,跟进去,这里我复制了一下二进制码,在vmp时候,好像也存在,所以比较适合做特征码。

Code
1
2
3
4
头部特征码:
55 8B EC 8B C1 40 C1 E0 02 2B E0 8D 3C 24
尾部特征码:
C6 07 00 58 8B E5 5D C3

直接运行到retn这里,看右下角堆栈窗口,就有源码处那四个字符串拼接

这时候启用12的断点,会断在2处,可能就是这个验证_调用远程JS玩意,直接把他跳过。

为什么会在核心支持库处可以看到,因为看源码什么到数值到文本都是易语言独有的,而哪些运算就是验证_调用远程JS这个里面的。现在目的就是把他给跳过,直接进入下一步运算中。

Code
1
0041A391   .  83C4 10       add     esp, 0x10                        ;  字符串拼接后F8出来会断在这里

一直往下拉,就会看见这个算法JS也就是刚才说的那个函数调用没错了。直接在出来的位置把他跳过。

Code
1
2
3
0041A391      C9            leave                                    ;  字符串拼接后F8出来会断在这里
0041A392 C3 retn
0041A393 90 nop


运算

接下来到这一处了,看源码就知道,如果本地结果AAAAAA /252 不等于 服务器运算结果,那就进行死循环。

那么现在,服务器肯定是连接失败了。因为是爆破进去的,所以为0,那么本地结果了,也将他置0就好了,0除以任何数都为0嘛。所以这俩肯定是相等的。

怎么做了,回到核心支持库,因为刚才跳过了算法JS,所以只要在此点击运行,那就会断在1处,而这个时候开始数,当到11次时候(官方的,就是未经修改的算法),将EAX置0就可以了。

当运转了11次后,这时候有个特征,就是EAX的值,和堆栈窗口中+8的值很相似。

将其置0.


时间

运算也处理完了,这时候就剩下时间了。也是投机取巧发现的方法,这时候只要将1的断点取消,只启用2的断点,很快就会在堆栈窗口中看见-1的字符串

这时对第一个-1右键,数据窗口中跟随,英文的话就是Follow in Dump

然后在数据窗口中,选中-1的值,快捷键 Ctrl+E,或者右键->二进制编辑,将其改为99999


按照刚才搞官方的写下流程:

1.处理检测OD

Code
1
2
3
4
5
6
7
特征码:
5E 6A 00 4B 75 FB FF E6
jmp esi 下断
F7 跟过去
mov eax,0
leave
ret

2.登录

Code
1
2
3
4
5
6
7
FF 25
找核心支持库 1 和 2
在 1 和 2 retn 处下断
输入帐号密码后,第一次出现帐号时候,F8跟出去
mov eax,1
leave
ret

3.合法

Code
1
2
3
4
5
6
7
8
9
10
11
12
两种办法:
FF 25 核心支持库,在1 处理了登录后
取消1的断点,只保留2的断点
然后F8运行出去
leave
ret

2.特征码:
5E 6A 00 4B 75 FB FF E6
处理完登录后,在倒数第二个下断个函数头下断,F8跟出去
leave
ret

4.js运算防止干扰

Code
1
2
3
4
5
6
7
8
9
俩个特征码取其一
头部特征码:
55 8B EC 8B C1 40 C1 E0 02 2B E0 8D 3C 24
尾部特征码:
C6 07 00 58 8B E5 5D C3

在retn 下断,运行到retn,看见字符串拼接,取消断点,启用 核心支持库 中 2的断点,F8跟出去
leave
ret

5.运算

Code
1
2
3
4
处理了js运算后
启用 核心支持库 1 的断点,官方的话,没有进行修改情况下是运行11次
然后观察eax和 堆栈窗口处 +8 的值是否类似
将eax 置0

6.补时间

Code
1
2
3
4
5
6
处理了运算后
取消核心支持库 1 的断点
启用核心支持库 2 的断点
运行几次,观察堆栈窗口,出现字符串 -1时
将其数据窗口中跟随
选中,二进制编辑或快捷键 Ctrl + E 将其 修改为 99999

7.退出

Code
1
2
3
看见网上的方法 
push 60
函数头改ret。不过我测试中没用到过。

VMP实战

查壳,VMP的

1.处理检测OD

通过特征码定位到jmp esi

其实不定位也行,因为就在下面,F2下断,运行,我试过。这里会断两次。

这是第一次。按照刚才的处理,将这里返回0

Code
1
00413910    68 04000080     push    0x80000004                       ; 第一次断下

Code
1
2
3
00413910    B8 00000000     mov     eax, 0x0                         ; 第一次断下
00413915 C9 leave
00413916 C3 retn

按照正常的话,这个时候,运行,就可以了。但是这里不行,运行的话就会崩

所以从第二次断下开始下手

Code
1
2
3
00440E46    68 05000080     push    0x80000005                       ; 第二次断下
00440E4B 6A 00 push 0x0
00440E4D 68 A0D74F00 push 004FD7A0

Code
1
2
3
00440E46    B8 00000000     mov     eax, 0x0                         ; 第二次断下
00440E4B C9 leave
00440E4C C3 retn

启动完成。


2.登录

Ctrl+ B 搜索 FF 25 查找到核心支持库,然后在 12中下断。

输入帐号密码,点击登录,断下,第一次正常是处理事件,第二次跟出去,这里是被VM后,变成了PUSH。不管他直接修改

Code
1
00B04C1F    68 BE99BECF     push    0xCFBE99BE                       ; denglu

Code
1
2
3
4
5
6
00B04C1F    B8 01000000     mov     eax, 0x1                         ; denglu
00B04C24 C9 leave
00B04C25 C3 retn
00B04C26 90 nop
00B04C27 90 nop
00B04C28 90 nop


3.合法

点击运行,回到1那里,然后取消断点,保留2的断点。

2断下后,F8跟出来。

Code
1
006E2237    68 2AB2D07F     push    0x7FD0B22A                       ; 合法

Code
1
2
3
4
5
006E2237    C9              leave                                    ; 合法
006E2238 C3 retn
006E2239 90 nop
006E223A 90 nop
006E223B 90 nop


4.防止干扰

通过特征码定位

Code
1
2
尾部特征码:
C6 07 00 58 8B E5 5D C3

出现字符串拼接,取消断点,启用2的断点,运行跟过去

但是这里,不清楚为什么,一运行到2后,堆栈窗口中就出现-1的字符串,也就是时间,这里就顺势修改了。

接着运行两次,就出现这个窗口了。


启动游戏测试效果

这里不管怎么呼出。都没效果,不知道是还有二次验证还是怎么样。


疑问

为什么会直接跳过了运算,是我漏了什么还是原作者修改后,还是VMP的效果。

为什么处理了时间后没有效果,请问是有二次验证,还是还有什么暗桩。

文章作者: KeyboArd
文章链接: https://www.wrpzkb.cn/pojie7/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 KeyboArd's Blog
打赏
  • 微信
    微信
  • 支付寶
    支付寶

评论