其实我也是个菜鸟,只是看大家那么对人问VM,发表下自己的看法,大牛别笑
VM的还原,我个人呢,总结了集中方法
第一种方法:对比
比如说现在的过图第一个点97F660
0097F65E CC int3
0097F65F CC int3
0097F660 E9 61D2A501 jmp 023DC8C6
0097F665 68 48F76C01 push 0x16CF748
0097F66A 64:A1 00000000 mov eax,dword ptr fs:[0]
0097F670 50 push eax
一看就知道是一个CALL的头部,VM HOOK了5个字节,下一句是push 0x16CF748
这个好办多了,其实有好多CALL,头部都PUSH了一个像这样的一个数,看看上面是什么,就知道怎么还原了
在最近找个CALL看看,就可以还原.比如
004A89A0 55 push ebp
004A89A1 8BEC mov ebp,esp
004A89A3 6A FF push -0x1
004A89A5 68 10746801 push 0x1687410
004A89AA 64:A1 00000000 mov eax,dword ptr fs:[0]
一对比看就知道上面被HOOK的地方为
push ebp
mov ebp,esp
push -1
刚刚好5个字节,于是呢,还原就是
0097F660 = 55 8B EC 6A FF
但是呢,这种方法适用范围小
第二种方法,查找
现在过图CALL的第3个点是9F644D
009F644D /E9 9C5C9E01 jmp 023DC0EE
009F6452 |90 nop
009F6453 |90 nop
009F6454 |59 pop ecx
009F6455 |5F pop edi
009F6456 |5E pop esi
009F6457 |5B pop ebx
009F6458 |8BE5 mov esp,ebp
009F645A |5D pop ebp
009F645B |C3 retn
大家看一下,009F644D处HOOK了5个字节,然后NOP填充了2个字节,意思就是一共HOOK了7个字节
那么他HOOK后跳回的地址就是00976454
然后我们CTRL+S查找命令 JMP 00976454
就找到一个点
02F4FF63 64:890D 0000000>mov dword ptr fs:[0],ecx
02F4FF6A 9C pushfd
02F4FF6B 66:892424 mov word ptr ss:[esp],sp
02F4FF6F 9C pushfd
02F4FF70 9C pushfd
02F4FF71 8D6424 4C lea esp,dword ptr ss:[esp+0x4C]
02F4FF75 ^ E9 DA64AAFD jmp 009F6454
然后大家往上走,就看到一句
02F4FF63 64:890D 0000000>mov dword ptr fs:[0],ecx
刚刚好7个字节,
于是还原了就是
009F644D = 64 89 0D 00 00 00 00
如果实在不放心,大家可以测试下崩溃不,或者找最几个相同的地方去看看
第三种,跟踪返回点
现在过图的第二个点97F91D
0097F91D E8 B7CFA501 call 023DC8D9
0097F922 85C0 test eax,eax
0097F924 0F84 93000000 je 0097F9BD
0097F92A 8B4D CC mov ecx,dword ptr ss:[ebp-0x34]
0097F92D 8B81 24060000 mov eax,dword ptr ds:[ecx+0x624]
0097F933 50 push eax
这种VM不是JMP跳转的,他是CALL一个地址
CALL呢有一个返回地址,返回地址其实就是RETN时ESP的值
知道这个就好办了
我们看他是HOOK了5个字节,那么他的返回点就是0097F922
我们在0097F91D处下断,断下后,CTRL+T(设置条件断点)
我们在 条件为真 的前面打勾 在后面输入
[ESP]==0097F922
然后确定,CTRL+F7(自动步入)
他就会自动一直往下跑,一直跑到ESP的值是0097F922的时候才会暂停
大家等一会就会断下了,最后呢断在
02F50B52 C74424 24 22F99>mov dword ptr ss:[esp+0x24],0x97F922
02F50B5A 883424 mov byte ptr ss:[esp],dh
02F50B5D 894424 14 mov dword ptr ss:[esp+0x14],eax
02F50B61 60 pushad
02F50B62 53 push ebx
02F50B63 FF7424 48 push dword ptr ss:[esp+0x48]
02F50B67 C2 4C00 retn 0x4C
跳回去后,执行的第一条指令是 test eax,eax,那被HOOK的地方一定跟EAX有关,我们往上看
找不到我们要的数据,那怎么办呢,我们继续网上找
查找所有常量 02F50B52
我们就会找到一句
02F53B5E ^\E9 EFCFFFFF jmp 02F50B52
我们条过去看看
02F53B34 66:0FBEC1 movsx ax,cl
02F53B38 66:0FB6D2 movzx dx,dl
02F53B3C 66:0FC9 bswap cx
02F53B3F FD std
02F53B40 9D popfd
02F53B41 2F das
02F53B42 61 popad
02F53B43 9C pushfd
02F53B44 F8 clc
02F53B45 881C24 mov byte ptr ss:[esp],bl
02F53B48 9C pushfd
02F53B49 83C4 0C add esp,0xC
02F53B4C 60 pushad
02F53B4D 54 push esp
02F53B4E C60424 E0 mov byte ptr ss:[esp],0xE0
02F53B52 8D6424 24 lea esp,dword ptr ss:[esp+0x24]
02F53B56 E8 754763FD call 005882D0
02F53B5B 57 push edi
02F53B5C 9C pushfd
02F53B5D 60 pushad
02F53B5E ^ E9 EFCFFFFF jmp 02F50B52
大家注意到没.红色这条就是我们要的指令了
复制下来,跳回到0097F91D,把他改为 call 005882D0
然后我们二进制复制下来就OK了
那么还原了就是
0097F91D = E8 AE 89 C0 FF
到这呢,我的方法也就结束了,本人仅仅发表个人观点,大家交流下,大牛勿喷!!
VM的还原,我个人呢,总结了集中方法
第一种方法:对比
比如说现在的过图第一个点97F660
0097F65E CC int3
0097F65F CC int3
0097F660 E9 61D2A501 jmp 023DC8C6
0097F665 68 48F76C01 push 0x16CF748
0097F66A 64:A1 00000000 mov eax,dword ptr fs:[0]
0097F670 50 push eax
一看就知道是一个CALL的头部,VM HOOK了5个字节,下一句是push 0x16CF748
这个好办多了,其实有好多CALL,头部都PUSH了一个像这样的一个数,看看上面是什么,就知道怎么还原了
在最近找个CALL看看,就可以还原.比如
004A89A0 55 push ebp
004A89A1 8BEC mov ebp,esp
004A89A3 6A FF push -0x1
004A89A5 68 10746801 push 0x1687410
004A89AA 64:A1 00000000 mov eax,dword ptr fs:[0]
一对比看就知道上面被HOOK的地方为
push ebp
mov ebp,esp
push -1
刚刚好5个字节,于是呢,还原就是
0097F660 = 55 8B EC 6A FF
但是呢,这种方法适用范围小
第二种方法,查找
现在过图CALL的第3个点是9F644D
009F644D /E9 9C5C9E01 jmp 023DC0EE
009F6452 |90 nop
009F6453 |90 nop
009F6454 |59 pop ecx
009F6455 |5F pop edi
009F6456 |5E pop esi
009F6457 |5B pop ebx
009F6458 |8BE5 mov esp,ebp
009F645A |5D pop ebp
009F645B |C3 retn
大家看一下,009F644D处HOOK了5个字节,然后NOP填充了2个字节,意思就是一共HOOK了7个字节
那么他HOOK后跳回的地址就是00976454
然后我们CTRL+S查找命令 JMP 00976454
就找到一个点
02F4FF63 64:890D 0000000>mov dword ptr fs:[0],ecx
02F4FF6A 9C pushfd
02F4FF6B 66:892424 mov word ptr ss:[esp],sp
02F4FF6F 9C pushfd
02F4FF70 9C pushfd
02F4FF71 8D6424 4C lea esp,dword ptr ss:[esp+0x4C]
02F4FF75 ^ E9 DA64AAFD jmp 009F6454
然后大家往上走,就看到一句
02F4FF63 64:890D 0000000>mov dword ptr fs:[0],ecx
刚刚好7个字节,
于是还原了就是
009F644D = 64 89 0D 00 00 00 00
如果实在不放心,大家可以测试下崩溃不,或者找最几个相同的地方去看看
第三种,跟踪返回点
现在过图的第二个点97F91D
0097F91D E8 B7CFA501 call 023DC8D9
0097F922 85C0 test eax,eax
0097F924 0F84 93000000 je 0097F9BD
0097F92A 8B4D CC mov ecx,dword ptr ss:[ebp-0x34]
0097F92D 8B81 24060000 mov eax,dword ptr ds:[ecx+0x624]
0097F933 50 push eax
这种VM不是JMP跳转的,他是CALL一个地址
CALL呢有一个返回地址,返回地址其实就是RETN时ESP的值
知道这个就好办了
我们看他是HOOK了5个字节,那么他的返回点就是0097F922
我们在0097F91D处下断,断下后,CTRL+T(设置条件断点)
我们在 条件为真 的前面打勾 在后面输入
[ESP]==0097F922
然后确定,CTRL+F7(自动步入)
他就会自动一直往下跑,一直跑到ESP的值是0097F922的时候才会暂停
大家等一会就会断下了,最后呢断在
02F50B52 C74424 24 22F99>mov dword ptr ss:[esp+0x24],0x97F922
02F50B5A 883424 mov byte ptr ss:[esp],dh
02F50B5D 894424 14 mov dword ptr ss:[esp+0x14],eax
02F50B61 60 pushad
02F50B62 53 push ebx
02F50B63 FF7424 48 push dword ptr ss:[esp+0x48]
02F50B67 C2 4C00 retn 0x4C
跳回去后,执行的第一条指令是 test eax,eax,那被HOOK的地方一定跟EAX有关,我们往上看
找不到我们要的数据,那怎么办呢,我们继续网上找
查找所有常量 02F50B52
我们就会找到一句
02F53B5E ^\E9 EFCFFFFF jmp 02F50B52
我们条过去看看
02F53B34 66:0FBEC1 movsx ax,cl
02F53B38 66:0FB6D2 movzx dx,dl
02F53B3C 66:0FC9 bswap cx
02F53B3F FD std
02F53B40 9D popfd
02F53B41 2F das
02F53B42 61 popad
02F53B43 9C pushfd
02F53B44 F8 clc
02F53B45 881C24 mov byte ptr ss:[esp],bl
02F53B48 9C pushfd
02F53B49 83C4 0C add esp,0xC
02F53B4C 60 pushad
02F53B4D 54 push esp
02F53B4E C60424 E0 mov byte ptr ss:[esp],0xE0
02F53B52 8D6424 24 lea esp,dword ptr ss:[esp+0x24]
02F53B56 E8 754763FD call 005882D0
02F53B5B 57 push edi
02F53B5C 9C pushfd
02F53B5D 60 pushad
02F53B5E ^ E9 EFCFFFFF jmp 02F50B52
大家注意到没.红色这条就是我们要的指令了
复制下来,跳回到0097F91D,把他改为 call 005882D0
然后我们二进制复制下来就OK了
那么还原了就是
0097F91D = E8 AE 89 C0 FF
到这呢,我的方法也就结束了,本人仅仅发表个人观点,大家交流下,大牛勿喷!!