cu629944 发表于 2013-1-20 18:13

VMP逆向分析笔记(连载ing~)

本帖最后由 cu629944 于 2013-1-20 19:11 编辑

       好久没来52了。这篇文作为我即将告别破解一段时间的纪念吧,等高考结束再重新接触破解吧,我年纪小,才17~接触计算机技术时间也不长,所以文章里面难免有错误。请大家提出来,然后我好知道我下一个学习的目标是啥,正所谓,脸就是用来丢的,我就把我分析的文贴出来,这个文我是边调试边写的,故肯定有考虑不周,有错误的地方,请大家谅解,小菜玩高科技,打肿脸充胖子嘛。这篇文没有完结,下一面是NAND门分析和跳转的方式。更新ING~
    VMP 逆向分析笔记 ——作者:Kinney山有木兮木有枝心悦君兮君不知只愿君心似我心鸿雁在云鱼在水天气还是一成不变的炎热,空气中的灰尘与水滴无一例外的都被蒸发掉。尽管不知道是不是暂时的。只是感觉阵阵热浪席卷而来,日子还是一样过。我庆幸,在你最美丽的时刻被我遇见。我庆幸,我遇见你在你最美丽的时刻。狒狒~加油...! BY_Kinney
一、VMP入口(新老对比) 将Test.exe分别用VMP1.8和VMP2.05的流程,来V+M一下(即虚拟+变异)。将Test.VMP1.X.exe载入OD,可以看到程序在00401000断下来:
   
  00401000 > 68 2765A8D0 push 0xD0A86527
  00401005 E8 97510000 call Test_vmp.004061A1
由一个PUSH DWORD来作为VMP的VM入口,这个Dword在这个程序里是 0xD0A86527,VMP将 0xD0A86527压入堆栈来作为源程序的入口,这个 0xD0A86527有什么用呢?它是用来计算函数VM开始执行的地址,可以利用68 ?? ?? ?? ?? E8(这个特征码是NOOBY牛公开的)来暴力猜测入口。我们再来看看VMP新版本的入口,将Test.VMP2.X.exe载入OD后,也是中断在00401000处,很明显,VMP将入口改成了一个JMP跳转。我们F7单步跟踪下看看。
      00401000 > $-E9 586F0000 JMP Test_vmp.00407F5D #入口改成了JMP指令
  00407F5D > 60 PUSHAD
  00407F5E . E9 20000000 JMP Test_vmp.00407F83
  00407F83 > 9C PUSHFD
  00407F63 $ C74424 24 4B032AF2 MOV DWORD PTR SS:,F22A034B #这个才是真正的KEY
  00407F6B . 9C PUSHFD
  00407F6C . C74424 24 80C91693 MOV DWORD PTR SS:,9316C980 #模拟旧版CALL的返回,无用 00407F74 . 55 PUSH EBP
  00407F75 . 9C PUSHFD
  00407F76 . C60424 EB MOV BYTE PTR SS:,0EB
  00407F7A . 8D6424 2C LEA ESP,DWORD PTR SS:
  00407F7E .^E9 92E5FFFF JMP Test_vmp.00406515从这里可以看出来了,高版本的VMP将PUSH KEY改成了JMP指令,并且把68 ?? ?? ?? ?? E8这样的特征码给擦除了。继续单步跟踪,紧接着就是VM的虚拟机的入口:  00406515 > E8 49060000 CALL Test_vmp.00406B63
  00406B63 $ 891C24 MOV DWORD PTR SS:,EBX
  00406B66 . 60 PUSHAD
  00406B67 . 57 PUSH EDI
00405617 $ 894424 24 MOV DWORD PTR SS:,EAX
  0040561B . 880424 MOV BYTE PTR SS:,AL
  30040561F . 897424 40 MOV DWORD PTR SS:,ESI
  00405623 . FF3424 PUSH DWORD PTR SS:
  00405626 . 68 EEBA723B PUSH 3B72BAEE
  0040562B . 54 PUSH ESP
  0040562C . C64424 08 1E MOV BYTE PTR SS:,1E
  00405631 . 8D6424 4C LEA ESP,DWORD PTR SS:
  00405635 . E9 580F0000 JMP Test_vmp.00406592
  00406592 > F6D7 NOT BH
  00406E6E $ 60 PUSHAD
  004055DE $ 897424 24 MOV DWORD PTR SS:,ESI
  004055E2 . 0F90C0 SETO AL
  004055E5 . 9C PUSHFD
  004055E6 . 8F4424 20 POP DWORD PTR SS:
  004055EA . 66:0FBAFE 0F BTC SI,0F
  004055EF . 66:87F3 XCHG BX,SI
  004055F2 . 66:0FCE BSWAP SI
  004055F5 . 66:D3E6 SHL SI,CL
  004055F8 . 877C24 1C XCHG DWORD PTR SS:,EDI
  004055FC . 66:F7D7 NOT DI
  004055FF . 894C24 18 MOV DWORD PTR SS:,ECX
  00405603 . 66:FFC6 INC SI
  00405606 . 00CB ADD BL,CL
  00405608 . 66:0FB6F1 MOVZX SI,CL
  0040560C . 895424 14 MOV DWORD PTR SS:,EDX
  00405610 . 39D4 CMP ESP,EDX
各种保存寄存器啊!保存完收工~ESP不用保存~VMP在任何时候都可以获取现在的ESP,现在堆栈等于进行了pushad,pushfd但ESP位置随即用一个通用寄存器替代了。  004052FF . FF35 186D4000 PUSH DWORD PTR DS: #这个数据很重要,用来在虚拟 机中随即算法解密时用
  00405305 . 8F4424 0C POP DWORD PTR SS:
  00405309 . 66:87D6 XCHG SI,DX
  开始解密虚拟机的EIP:
  0040530C . C74424 08 00000000 MOV DWORD PTR SS:,0 #这个是常量,是虚拟机堆栈的 顶端数据,作用是初始EIP的 一个偏移和控制虚拟代码的解 密偏移。
  00405314 . 30D3 XOR BL,DL
  00405316 . 66:87FE XCHG SI,DI
  00405319 . F9 STC
  0040531A . 66:F7DE NEG SI
  0040531D . 8B7424 38 MOV ESI,DWORD PTR SS: #这里就是call之前压入堆栈 的KEY
  00405321 . A9 FB87394E TEST EAX,4E3987FB
  00405326 . F5 CMC
  00405327 . 66:81E5 D910 AND BP,10D9
  0040532C . F7D6 NOT ESI
  0040532E . 66:C1ED 0C SHR BP,0C
  00405332 . 81EE 996B5878 SUB ESI,78586B99
  00405338 . 38D5 CMP CH,DL
  0040533A . 66:FFCB DEC BX
  0040533D . 81F6 0F163D95 XOR ESI,953D160F
    ESI就是VM的起始地址,就是VMP虚拟机的EIP  00405343 . 87D7 XCHG EDI,EDX
  00405345 . 66:F7D7 NOT DI
  00405348 . 4D DEC EBP
  00405349 . 66:0FBAF7 0B BTR DI,0B
  0040534E . 8D6C24 08 LEA EBP,DWORD PTR SS: #EBP == 0012FF90 建立虚拟堆 栈
  00405352 . 85C1 TEST ECX,EAX
  00405354 . 60 PUSHAD
  00405355 . 81EC 98000000 SUB ESP,98
  0040535B . 66:D3D7 RCL DI,CL
  0040535E . D0F8 SAR AL,1
  00405360 . 89E7 MOV EDI,ESP #EDI == 0012FED0,建立的堆栈大 小为C0
  00405362 > D2EF SHR BH,CL
  00405364 . C0E8 03 SHR AL,3
  00405367 . D2FB SAR BL,CL
  00405369 . D0F3 SAL BL,1
这个版本里前面0x40是作为通用寄存器时用的,其他作为缓存堆栈,其算法会在下面看到。缓存中保存的是真正的寄存器0x24,和一个返回地址,一个KEY,一个全局控制变量。  0040536B . 89F3 MOV EBX,ESI
  0040536D . 0FBAFA 09 BTC EDX,9
  00405371 . F6D2 NOT DL
  00405373 . 66:0FBED3 MOVSX DX,BL
  00405377 . 0375 00 ADD ESI,DWORD PTR SS:
  0040537A > 66:0FB3EA BTR DX,BP
这一段代码就是VMP_JMP指令的后半段,主要是初始化校验寄存器和设置起始地址,这里只是下半部分,因此没有偏移量,VMP在入口出用一个0来模拟偏移量。入口到这里就完成了。二、VMP的基本构架
    ESI 相当于常规的EIP,即VM.EIPEDI 指向虚拟机通用寄存器的地址,是虚拟机在操作内存,且EDI指向虚拟机的堆栈的上限, 用向下发展EBP 指向虚拟机堆栈的栈顶,且EBP指向堆栈下限并向上发展EAX 计算将要执行的指令序列号和选择虚拟机通用寄存器,指令执行时用作中间变量.其它时候用作花指令EDX 执行时通常用作中间变量,其它大部分时间用来做花指令EBX BL用作校验码.ECX SHLD,SHRD时用作中间变量,其他大部分时间用来做花指令ESP 指向垃圾,这个寄存器就是用来迷惑追踪者的,一般对ESP的操作都是花指令,大部分可以忽略在VM运行的时候,通常一切操作都是在VM堆栈内完成的。在一些虚拟与常规(比如说调用系统函数)交接的地方,系统并不知道VM的堆栈的存在,这就需要把数据(比如系统函数的调用参数)移动到常规的ESP栈顶,然后继续执行的。
      0040537E . 8A46 FF MOV AL,BYTE PTR DS: #这里的1是可变的,每次都不 一样
  00405381 . 0FA3E0 BT EAX,ESP
  00405384 . 28D8 SUB AL,BL
  00405386 . 66:0FB6D2 MOVZX DX,DL
  0040538A . 80D2 3E ADC DL,3E
  0040538D . 34 EE XOR AL,0EE
   0040538F . 0F80 AA150000 JO Test_vmp.0040693F #迷惑你的假跳转
  00405395 . 66:0FCA BSWAP DX
  00405398 . D0C0 ROL AL,1
  0040539A . 66:0FB6D2 MOVZX DX,DL
  0040539E . 66:0FBDD3 BSR DX,BX
  004053A2 . 66:0FA4DA 0A SHLD DX,BX,0A
  004053A7 . 04 1A ADD AL,1A
  004053A9 . 66:81E2 F5C2 AND DX,0C2F5
  004053AE . 8D9424 ADF56060 LEA EDX,DWORD PTR SS:
  004053B5 . C1F2 11 SAL EDX,11
  004053B8 . 66:19CA SBB DX,CX
  004053BB . 28C3 SUB BL,AL
  004053BD . 53 PUSH EBX
  004053BE . 83C6 FF ADD ESI,-1 #相当于SUB ESI,1,这种就是 升序,ESI是往上走的,也就是 说,会有LEA等形式
指令表和索引(Dispatch) 我们回到VMP,虚拟机是在一个大的循环里面执行的,现在我们就在这个大循环的起点,这个循环将解释所有的指令和参数,直到执行退出指令,在VMP里面,执行退出指令并不是代表退出虚拟机,现在我们继续进行调试,首先看一下循环开始的指令
   
   看看寄存器
   
   此时ESI和EBX都是指向OPCODE的第一个地址  0040537E . 8A46 FF MOV AL,BYTE PTR DS:
  00405381 . 0FA3E0 BT EAX,ESP
  00405384 . 28D8 SUB AL,BL #减去校验值    这个是虚拟机中常见的手段,就是通过当前的校验码来影响下一条指令的解码,通过解码后的指令来计算新的校验码,如果这个校验码不正确的话,那么下面的指令就会出错,不过不一定是立即出错。这个技术主要是防止通过强行修改EIP来改变程序执行的流畅,要进行爆破的话,除了要获得目标EIP的值以外,还要获得校验寄存器当时的状态,然后同时修改EIP和校验寄存器,才可以实施爆破。
      0040538D . 34 EE XOR AL,0EE
  0040538F . 0F80 AA150000 JO Test_vmp.0040693F
  00405395 . 66:0FCA BSWAP DX
  00405398 . D0C0 ROL AL,1
  0040539A . 66:0FB6D2 MOVZX DX,DL
  0040539E . 66:0FBDD3 BSR DX,BX
  004053A2 . 66:0FA4DA 0A SHLD DX,BX,0A
  004053A7 . 04 1A ADD AL,1A
  004053A9 . 66:81E2 F5C2 AND DX,0C2F5
  004053AE . 8D9424 ADF56060 LEA EDX,DWORD PTR SS:
  004053B5 . C1F2 11 SAL EDX,11
  004053B8 . 66:19CA SBB DX,CX
  004053BB . 28C3 SUB BL,AL #修正校验值
  004053BD . 53 PUSH EBX
  004053BE . 83C6 FF ADD ESI,-1
  004053C1 . E9 56130000 JMP Test_vmp.0040671C
  0040671C > 0FB6C0 MOVZX EAX,AL #到这里EAX解码完成
EAX用来作为一个索引,在指令表里查找指令,这里有效的部分就是AL,所以最多会有FF个指令  00406727 . 8B1485 62594000 MOV EDX,DWORD PTR DS: #405962就是指令表
  0040672E . 66:0FA3CA BT DX,CX
  00406732 . F8 CLC
  00406733 . 38DB CMP BL,BL
405692是硬编码,所以很容易看出来,而EAX的作用和Handle很像,因此很多人都叫这个为Handle,指令表是防御中的重中之重,是重点保护对象撒~接下来看解码指令执行地址  0040672E . 66:0FA3CA BT DX,CX
  00406732 . F8 CLC
  00406733 . 38DB CMP BL,BL
  00406735 . 81C2 F899DAC8 ADD EDX,C8DA99F8
  0040673B . FF3424 PUSH DWORD PTR SS:
  0040673E . F8 CLC
  0040673F . 81C2 00000000 ADD EDX,0
  00406745 .^E9 20EBFFFF JMP Test_vmp.0040526A
0040526A > 895424 04 MOV DWORD PTR SS:,EDX
  0040526E . 9C PUSHFD
  0040526F . 883424 MOV BYTE PTR SS:,DH
  00405272 . FF7424 08 PUSH DWORD PTR SS:
  00405276 . C2 0C00 RETN 0C #跳到Handle执行的地址
接下来这个是第一条Handle:  0040641E . 60 PUSHAD
  0040641F . FEC2 INC DL
  00406421 . 66:0FBED3 MOVSX DX,BL
  00406425 . 9C PUSHFD
  00406426 . FEC8 DEC AL
  00406428 . 60 PUSHAD
  00406429 . 9C PUSHFD
  0040642A . 8A7424 04 MOV DH,BYTE PTR SS:
  0040642E . C0CA 07 ROR DL,7
  00406431 . C0C0 02 ROL AL,2
  00406434 . 66:0FA3C5 BT BP,AX
  00406438 . 9C PUSHFD
  00406439 . F9 STC
  0040643A . 2C 7A SUB AL,7A
  0040643C . F5 CMC
  0040643D . 66:F7C5 C905 TEST BP,5C9
  00406442 . 66:FFC2 INC DX
  00406445 . F6DA NEG DL
  00406447 . 24 3C AND AL,3C
  00406449 . 66:0FBBEA BTC DX,BP
  0040644D . 8B55 00 MOV EDX,DWORD PTR SS: #这句可以看出,前面关于EDX 寄存器的操作都是花指令
  00406450 . 84C7 TEST BH,AL
  00406452 . 80FD 6A CMP CH,6A
  00406455 . C60424 85 MOV BYTE PTR SS:,85
  00406459 . 9C PUSHFD
  0040645A . 83C5 04 ADD EBP,4
  0040645D . E9 DD080000 JMP Test_vmp.00406D3F
  0040626D $ 891438 MOV DWORD PTR DS:,EDX
  00406270 . 881424 MOV BYTE PTR SS:,DL
  00406273 . 66:891C24 MOV WORD PTR SS:,BX
  00406277 . 880424 MOV BYTE PTR SS:,AL
  0040627A . 8D6424 54 LEA ESP,DWORD PTR SS:
  0040627E .^E9 F7F0FFFF JMP Test_vmp.0040537A
很容易看出来,这段代码相当于一个汇编指令 mov reg,const,我将这段Handle称为SetR32 。(也叫原子指令,我自己是这么理解的)至于const是什么东西,就不知道了,这要看前面的指令把什么压入堆栈了,有可能是常量,也有可能是地址(当前面的指令模拟lea的时候)。重新回到DISPATCH,然后寻找他的解密指令:  0040672E . 66:0FA3CA BT DX,CX
  00406732 . F8 CLC
  00406733 . 38DB CMP BL,BL
  00406735 . 81C2 F899DAC8 ADD EDX,C8DA99F8 #这一句是解密DISPATCHTABLE的代 码
  0040673B . FF3424 PUSH DWORD PTR SS:
  0040673E . F8 CLC
  0040673F . 81C2 00000000 ADD EDX,0
  00406745 .^E9 20EBFFFF JMP Test_vmp.0040526A
0040526A > 895424 04 MOV DWORD PTR SS:,EDX
  0040526E . 9C PUSHFD
  0040526F . 883424 MOV BYTE PTR SS:,DH
  00405272 . FF7424 08 PUSH DWORD PTR SS:
00405276 . C2 0C00 RETN 0C
接下来我们来解密DISPATCHTABLE,找空代码区域,自己写PATCH代码进行恢复:  00409396 0000 ADD BYTE PTR DS:,AL
我们就在这里写PATCH代码吧:
  00409396 60 PUSHAD
  00409397 BE 62594000 MOV ESI,Test_vmp.00405962
  0040939C BF 00954000 MOV EDI,Test_vmp.00403010
  004093A1 B9 00010000 MOV ECX,100
  004093A6 33DB XOR EBX,EBX
  004093A8 8B0433 MOV EAX,DWORD PTR DS:
  004093AB 81C2 F899DAC8 ADD EDX,C8DA99F8
  004093B1 89043B MOV DWORD PTR DS:,EAX
  004093B4 83C3 04 ADD EBX,4
  004093B7 49 DEC ECX
  004093B8 ^75 EE JNZ SHORT Test_vmp.004093A8
  004093BA 61 POPAD
  004093BB ^\E9 AABEFFFF jmp Test_vmp.0040526A
   
二进制代码为:
    60 BE 62 59 40 00 BF 10 30 40 00 B9 00 01 00 00 33 DB 8B 04 33 81 C2 F8 99 DA C8 89 04 3B 83 C3
04 49 75 EE 61 E9 AA BE FF FF
将垃圾代码、重复的handle去掉,就可以分析Handle了。第一条handle是SetR32,已经在上面分析完毕了,就不再重复了。直接从第二条Handle开始了。
   
GetI32
代码:
00406E39 66:31D0 xor ax,dx #各种花指令....
00406E3C F6D0 not al
00406E3E 08CC or ah,cl
00406E40 8B46 FC mov eax,dword ptr ds: #这个才是重点啊....
0040681B 0FC8 bswap eax
00406EAA 66:F7C7 C665 test di,0x65C6
00406EAF 29D8 sub eax,ebx
004065F2 40 inc eax
004065F3 52 push edx
004065F4 9C pushfd
004065F5 F7D0 not eax
004065F7 9C pushfd
004065F8 56 push esi
00405513 48 dec eax
0040512D 9C pushfd
0040512E F9 stc
0040512F 29C3 sub ebx,eax
00405131 F9 stc
00405132 FF7424 04 push dword ptr ss:
00405136 9C pushfd
00405137 F5 cmc
00405138 83ED 04 sub ebp,0x4
004068D0 886C24 04 mov byte ptr ss:,ch
004068D4 66:897C24 04 mov word ptr ss:,di
004068D9 8945 00 mov dword ptr ss:,eax
004068DC 68 015E8A55 push 0x558A5E01
004068E1 66:897424 08 mov word ptr ss:,si
004068E6 8D76 FC lea esi,dword ptr ds:
004068E9 68 A9C40EBC push 0xBC0EC4A9
004068EE 8D6424 34 lea esp,dword ptr ss:
00405F43 66:0FA5C0 shld ax,ax,cl
00405F47 0FBAE1 07 bt ecx,0x7
00405F4B D2C0 rol al,cl
00405F4D 8D47 50 lea eax,dword ptr ds:
00405F50 F9 stc
00406B72 F8 clc
00406B73 39C5 cmp ebp,eax
00406B75 9C pushfd
00405DB4 ^\0F87 C0F5FFFF ja Test_vmp.0040537A
作用:
从指令表中读取dword字节的立即数保存到EBP堆栈栈顶,并检测堆栈大小。
Add32:
代码:
004054A9 F9 stc
004054AA 2F das
004054AB 8B45 00 mov eax,dword ptr ss:
004054AE 66:0FBAE1 0E bt cx,0xE
004054B3 F9 stc
004056D9 8D6424 04 lea esp,dword ptr ss:
004056DD 0F87 430F0000 ja Test_vmp.00406626
004056E3 0145 04 add dword ptr ss:,eax
004056E6 9C pushfd
004056E6 9C pushfd
00406DFC 9C pushfd
00406DFD 8F0424 pop dword ptr ss:
00406E00 9C pushfd
00406E01 FF7424 04 push dword ptr ss:
00406E05 8F45 00 pop dword ptr ss:
00406E08 68 B6979826 push 0x269897B6
00406E0D 8D6424 0C lea esp,dword ptr ss:
作用:
将栈顶数据以Dword与相加,标志位保存在栈顶,计算结果保存在
例子:
GetR32:
代码:
004060AE 50 push eax
004060AF FEC8 dec al
004060B1 D2D2 rcl dl,cl
004060B3 66:0FBED1 movsx dx,cl
004060B7 0F94C6 sete dh
004060BA C0C0 02 rol al,0x2
004060BD 60 pushad
004060BE 80DA E4 sbb dl,0xE4
004060C1 66:0FBCD3 bsf dx,bx
004060C5 2C 7A sub al,0x7A
004060C7 30CE xor dh,cl
004060C9 66:FFC2 inc dx
004060CC FEC6 inc dh
004060CE 24 3C and al,0x3C
004060D0 D2DA rcr dl,cl
004060D2 66:C1C2 05 rol dx,0x5
004060D6 C0D6 07 rcl dh,0x7
004060D9 8B1438 mov edx,dword ptr ds:
004060DC 66:0FBAE3 01 bt bx,0x1
004060E1 F5 cmc
004060E2 83ED 04 sub ebp,0x4
004060E5 51 push ecx
004060E6 8955 00 mov dword ptr ss:,edx
004060E9 54 push esp
004060EA 68 2BA533D4 push 0xD433A52B
004060EF 66:896424 08 mov word ptr ss:,sp
004060F4 8D6424 30 lea esp,dword ptr ss:
00405F43 66:0FA5C0 shld ax,ax,cl
00405F47 0FBAE1 07 bt ecx,0x7
00405F4B D2C0 rol al,cl
00405F4D 8D47 50 lea eax,dword ptr ds:
00405F50 F9 stc
00406B72 F8 clc
00406B73 39C5 cmp ebp,eax
00406B75 9C pushfd
00405DB0 8D6424 08 lea esp,dword ptr ss:
00405DB4 ^ 0F87 C0F5FFFF ja Test_vmp.0040537A
作用:
将EDI堆栈数据以解密出来的EAX为偏移,以Dword保存到栈顶,并检查堆栈是否碰撞。
GetESP:
代码:
004058EF D2F0 sal al,cl
004058F1 20D4 and ah,dl
004058F3 D0CC ror ah,1
004058F5 F6D8 neg al
004058F7 89E8 mov eax,ebp
004058F9 F6C2 E8 test dl,0xE8
004058FC 83ED 04 sub ebp,0x4
00406700 8945 00 mov dword ptr ss:,eax
00406703 50 push eax
00406704 8D6424 04 lea esp,dword ptr ss:
00405F43 66:0FA5C0 shld ax,ax,cl
00405F47 0FBAE1 07 bt ecx,0x7
00405F4B D2C0 rol al,cl
00405F4D 8D47 50 lea eax,dword ptr ds:
00405F50 F9 stc
00406B73 39C5 cmp ebp,eax
00405DB0 8D6424 08 lea esp,dword ptr ss:
00405DB4 ^ 0F87 C0F5FFFF ja Test_vmp.0040537A
作用:
以EBP栈顶地址为数据保存在EBP栈顶,并检查堆栈是否碰撞。
GetI8To16
代码:
00405E14 52 push edx ;
00405E15 51 push ecx
00405E16 34 48 xor al,0x48
00405E18 8A46 FF mov al,byte ptr ds:
00405E1B C64424 04 F8 mov byte ptr ss:,0xF8
00405E20 66:897424 04 mov word ptr ss:,si
00405E25 28D8 sub al,bl
00405E27 FF7424 04 push dword ptr ss:
00405E2B 60 pushad
00405E2C FEC8 dec al
00405E2E 0FA3FD bt ebp,edi
00405E31 F6D0 not al
00405E33 68 4E13BE6A push 0x6ABE134E
00405E38 66:81FB E930 cmp bx,0x30E9
00405EF3 04 0C add al,0xC
00405EF5 66:0FBAE6 03 bt si,0x3
00405EFA 28C3 sub bl,al
00405EFC FF7424 04 push dword ptr ss:
00405F00 66:0FBAE3 06 bt bx,0x6
00405F05 F8 clc
00405F06 83ED 02 sub ebp,0x2
00405F09 9C pushfd
00405F0A 66:8945 00 mov word ptr ss:,ax
00405F0E 68 ED219CFC push 0xFC9C21ED
0040563F 8D76 FF lea esi,dword ptr ds:
00405642 9C pushfd
00405643 880C24 mov byte ptr ss:,cl
00405646 9C pushfd
00405647 8D6424 44 lea esp,dword ptr ss:
00405F43 66:0FA5C0 shld ax,ax,cl
00405F47 0FBAE1 07 bt ecx,0x7
00405F4B D2C0 rol al,cl
00405F4D 8D47 50 lea eax,dword ptr ds:
00405F50 F9 stc
00406B72 F8 clc
00406B73 39C5 cmp ebp,eax
00406B75 9C pushfd
作用:
从指令表获取一个Byte立即数,扩展到word字节保存到EBP栈顶并检查堆栈是否碰撞。
SetR16:
代码:
00405424 66:0FBAEA 09 bts dx,0x9 ;
00405429 60 pushad
0040542A 66:0FBDD2 bsr dx,dx
0040542E 66:0FCA bswap dx
00405431 8A46 FF mov al,byte ptr ds:
00405434 80CA EA or dl,0xEA
00405437 28D8 sub al,bl
00405439 F6D6 not dh
0040543B 66:0FB6D1 movzx dx,cl
0040518B 4E dec esi ; Test_vmp.004086E7
0040518C FEC2 inc dl
0040518E 9C pushfd
0040518F 54 push esp
00405190 FEC0 inc al
00406A89 28CE sub dh,cl
00406A8B F9 stc
00406A8C 34 BD xor al,0xBD
00406A8E C0FA 04 sar dl,0x4
00406A91 F6D6 not dh
00406A93 D0DA rcr dl,1
00406A95 04 93 add al,0x93
00406A97 D0CA ror dl,1
00406A99 FEC6 inc dh
00406A9B 80C2 70 add dl,0x70
00406A9E 9C pushfd
00406A9F 28C3 sub bl,al
00406AA1 00EA add dl,ch
00406AA3 80F2 6A xor dl,0x6A
00406AA6 0F9AC2 setpe dl
00406AA9 38DF cmp bh,bl
00406AAB 66:8B55 00 mov dx,word ptr ss:
00406AAF 66:F7C6 80D4 test si,0xD480
00406AB4 C60424 F9 mov byte ptr ss:,0xF9
00406AB8 83C5 02 add ebp,0x2
00406ABB 68 FA91AC0D push 0xDAC91FA
00406AC0 66:891438 mov word ptr ds:,dx
00406AC4 55 push ebp
00406AC5 68 2A1F493D push 0x3D491F2A
00406ACA 881424 mov byte ptr ss:,dl
00406ACD 8D6424 40 lea esp,dword ptr ss:
作用:
从EBP堆栈栈顶读取Word长度数据保存到堆栈。
RmDs32
代码:
00405706 F6D0 not al
00405708 8B45 00 mov eax,dword ptr ss:
00406BCB 9C pushfd
00406BCC 9C pushfd
00406BCD FF7424 04 push dword ptr ss:
00406BD1 8B00 mov eax,dword ptr ds:
00406BD3 68 503CC298 push 0x98C23C50
00406BD8 68 8717E2A4 push 0xA4E21787
00406BDD 8945 00 mov dword ptr ss:,eax
00406BE0 C60424 00 mov byte ptr ss:,0x0
00406BE4 9C pushfd
00406BE5 FF3424 push dword ptr ss:
00406BE8 C74424 08 BCE71>mov dword ptr ss:,0x361FE7BC
00406BF0 8D6424 1C lea esp,dword ptr ss:
作用:
以EBP堆栈栈顶数据为地址,取出Dwrod长度数据保存到EBP栈顶。
GetR16
代码:
00405808 28D8 sub al,bl ;
0040580A 18F8 sbb al,bh
0040580C D0C8 ror al,1
0040580E 8A46 FF mov al,byte ptr ds:
00406005 3C 3C cmp al,0x3C
00406007 28D8 sub al,bl
00406009 9C pushfd
0040600A 68 FBA19387 push 0x8793A1FB
0040600F FEC0 inc al
00406011 60 pushad
00406012 66:85E2 test dx,sp
00406015 C60424 72 mov byte ptr ss:,0x72
00406019 34 BD xor al,0xBD
0040601B F5 cmc
0040601C 04 93 add al,0x93
0040601E 9C pushfd
0040601F 66:C74424 04 CB>mov word ptr ss:,0xA4CB
00406026 66:0FA3EE bt si,bp
0040602A 28C3 sub bl,al
0040602C 9C pushfd
0040602D 66:8B0438 mov ax,word ptr ds:
00406031 66:0FA3DC bt sp,bx
00406035 83C6 FF add esi,-0x1
00406038 66:0FBAE2 09 bt dx,0x9
0040603D 83ED 02 sub ebp,0x2
00406040 9C pushfd
00406041 66:8945 00 mov word ptr ss:,ax
00406045 884C24 08 mov byte ptr ss:,cl
00406049 68 E954CEDF push 0xDFCE54E9
0040604E 68 2141065F push 0x5F064121
00406053 9C pushfd
00405F43 66:0FA5C0 shld ax,ax,cl
00405F47 0FBAE1 07 bt ecx,0x7
00405F4B D2C0 rol al,cl
00405F4D 8D47 50 lea eax,dword ptr ds:
00405F50 F9 stc
00406B72 F8 clc
00406B73 39C5 cmp ebp,eax
00406B75 9C pushfd
00405DB0 8D6424 08 lea esp,dword ptr ss:
00405DB4 ^ 0F87 C0F5FFFF ja Test_vmp.0040537A
作用:
从EDI堆栈以EAX为偏移量取出数据保存到EBP栈顶,并检查堆栈是否碰撞。

RmSs32
代码:
00406A35 66:F7D0 not ax ;
00406A38 8B45 00 mov eax,dword ptr ss:
00406A3B 53 push ebx
00406A3C 57 push edi
00406A3D 9C pushfd
00406A3E FF3424 push dword ptr ss:
00406A41 36:8B00 mov eax,dword ptr ss:
00406A44 60 pushad
00406A45 53 push ebx
00406A46 66:895424 04 mov word ptr ss:,dx
00406A4B 8945 00 mov dword ptr ss:,eax
00406A4E 9C pushfd
00406A4F 884424 0C mov byte ptr ss:,al
00406A53 9C pushfd
00406A54 8D6424 3C lea esp,dword ptr ss:
作用:
从EPB堆栈栈顶读取Dword长度数据为地址保存到EBP堆栈栈顶。
GetI8To32
代码:
00406C47 C0C8 07 ror al,0x7 ;
00406C4A 8A46 FF mov al,byte ptr ds:
00406B26 66:0FBAE6 05 bt si,0x5
00406B2B 66:0FBAE2 03 bt dx,0x3
00406B30 F5 cmc
00406B31 28D8 sub al,bl
00406A74 9C pushfd
004063C2 FEC8 dec al
004063C4 51 push ecx
00405D71 66:C70424 C3CB mov word ptr ss:,0xCBC3
00405D77 4E dec esi
00405D78 FF7424 04 push dword ptr ss:
00405D7C F6D0 not al
00405D7E 9C pushfd
00405D7F 881424 mov byte ptr ss:,dl
00405D82 9C pushfd
00405D83 04 0C add al,0xC
00405D85 882C24 mov byte ptr ss:,ch
00405D88 28C3 sub bl,al
00405D8A 883424 mov byte ptr ss:,dh
00401005 F9 stc
00401006 F9 stc
00401007 66:98 cbw
00401009 80FA C2 cmp dl,0xC2
00405ED4 84F1 test cl,dh
00406315 98 cwde
00406316 9C pushfd
00406317 F9 stc
00406318 83ED 04 sub ebp,0x4
0040631B 9C pushfd
0040540C 8945 00 mov dword ptr ss:,eax
0040540F C64424 10 8F mov byte ptr ss:,0x8F
00405414 55 push ebp
00405415 66:C70424 890C mov word ptr ss:,0xC89
0040541B 8D6424 38 lea esp,dword ptr ss:
00405F43 66:0FA5C0 shld ax,ax,cl
00405F47 0FBAE1 07 bt ecx,0x7
00405F4B D2C0 rol al,cl
00405F4D 8D47 50 lea eax,dword ptr ds:
00405F50 F9 stc
00406B72 F8 clc
00406B73 39C5 cmp ebp,eax
00406B75 9C pushfd
00405DB0 8D6424 08 lea esp,dword ptr ss:
00405DB4 ^ 0F87 C0F5FFFF ja Test_vmp.0040537A
作用:
从指令表里取出BYTE长度立即数,扩展为32位保存到EBP堆栈栈顶,并检查堆栈大小
WmSs32
代码:
00406D56 66:F7C7 C521 test di,0x21C5 ;
00406D5B 66:0FBAE7 06 bt di,0x6
00406D60 F7DA neg edx
00406D62 8B45 00 mov eax,dword ptr ss:
00406D65 8D97 A6EA741E lea edx,dword ptr ds:
00406D6B F7D2 not edx
00406D6D 8B55 04 mov edx,dword ptr ss:
00406D70 F9 stc
00406D71 F9 stc
00405F1D 51 push ecx
00405F1E 83C5 08 add ebp,0x8
00405F21 50 push eax
00405DF5 68 2AACF49B push 0x9BF4AC2A
00405DFA 36:8910 mov dword ptr ss:,edx
00405DFD 68 C47FBCD1 push 0xD1BC7FC4
00405E02 60 pushad
00405E03 884424 04 mov byte ptr ss:,al
00405E07 886424 08 mov byte ptr ss:,ah
00405E0B 8D6424 34 lea esp,dword ptr ss:
作用:
从EBP栈顶读出Dword长度数据作为数据,并将保存到该地址中。
nor32
代码:
0040589D 66:92 xchg ax,dx ;
0040589F 20DE and dh,bl
004058A1 8B45 00 mov eax,dword ptr ss:
004058A4 0F92C6 setb dh
004058A7 8B55 04 mov edx,dword ptr ss:
004058AA F7C2 7A44722B test edx,0x2B72447A
004058B0 F7D0 not eax
004058B2 68 946AEF00 push 0xEF6A94
004058B7 F9 stc
004058B8 60 pushad
004058B9 F9 stc
004058BA F7D2 not edx
004058BC 66:0FA3F5 bt bp,si
004058C0 66:0FBAE0 0F bt ax,0xF
004058C5 66:0FA3F0 bt ax,si
004058C9 60 pushad
004058CA 21D0 and eax,edx
004058CC 57 push edi
004058CD 8945 04 mov dword ptr ss:,eax
00405E70 9C pushfd
00405E71 8F4424 48 pop dword ptr ss:
00405E75 68 9FFA557B push 0x7B55FA9F
00405E7A C64424 1C D0 mov byte ptr ss:,0xD0
00405E7F 66:895424 04 mov word ptr ss:,dx
00405E84 FF7424 4C push dword ptr ss:
00405E88 8F45 00 pop dword ptr ss:
00405E8B C60424 F7 mov byte ptr ss:,0xF7
00405E8F C60424 F5 mov byte ptr ss:,0xF5
00405E93 880C24 mov byte ptr ss:,cl
00405E96 8D6424 50 lea esp,dword ptr ss:
作用:
Dword版Nand门。从EBP堆栈栈顶和读取出两个数据作为操作数,运算结果保存到,标志位保存到EBP栈顶。
例子:
   
add8
代码:
00406D9E F6D8 neg al ;
00406DA0 8A45 00 mov al,byte ptr ss:
00406DA3 F5 cmc
00406DA4 68 AD4C75F8 push 0xF8754CAD
00406DA9 F9 stc
00406DAA F9 stc
00406DAB 83ED 02 sub ebp,0x2
00405100 C60424 9C mov byte ptr ss:,0x9C
00405104 0045 04 add byte ptr ss:,al
00405107 60 pushad
00405108 9C pushfd
00405109 C64424 10 8A mov byte ptr ss:,0x8A
0040510E 9C pushfd
0040510F 9C pushfd
00405110 8F4424 28 pop dword ptr ss:
00405114 9C pushfd
00405115 FF7424 2C push dword ptr ss:
00405119 8F45 00 pop dword ptr ss:
0040511C 885C24 04 mov byte ptr ss:,bl
00405120 C60424 F8 mov byte ptr ss:,0xF8
00405124 8D6424 30 lea esp,dword ptr ss:
00405F43 66:0FA5C0 shld ax,ax,cl
00405F47 0FBAE1 07 bt ecx,0x7
00405F4B D2C0 rol al,cl
00405F4D 8D47 50 lea eax,dword ptr ds:
00405F50 F9 stc
00406B72 F8 clc
00406B73 39C5 cmp ebp,eax
00406B75 9C pushfd
作用:
从EBP堆栈读取BYTE长度数据与相加,计算结果保存到,标志位保存到栈顶,并校验堆栈是否碰撞。
SetR8By16
代码:
00405716 FEC8 dec al ;
00405718 88C0 mov al,al
0040571A F8 clc
0040571B 0FB646 FF movzx eax,byte ptr ds:
00405168 FECE dec dh
0040516A 66:0FB6D0 movzx dx,al
0040516E 66:0FCA bswap dx
00405171 28D8 sub al,bl
00405173 66:0FABEA bts dx,bp
00405177 C0C8 06 ror al,0x6
0040517A 60 pushad
0040517B 66:0FB6D1 movzx dx,cl
0040517F FEC2 inc dl
0040567A FEC8 dec al
0040567C F6D6 not dh
0040567E F5 cmc
0040567F 66:D3C2 rol dx,cl
00405682 C0DA 07 rcr dl,0x7
00405685 F6D0 not al
00405687 F6DE neg dh
00405689 C0EA 03 shr dl,0x3
0040568C D2C6 rol dh,cl
0040568E 83C6 FF add esi,-0x1
00405691 F8 clc
00405692 28C3 sub bl,al
00405694 60 pushad
00405695 0F90C6 seto dh
00405698 66:8B55 00 mov dx,word ptr ss:
0040569C 9C pushfd
0040569D 83EC B8 sub esp,-0x48
0040646C 83C5 02 add ebp,0x2
0040646F 9C pushfd
00406470 881438 mov byte ptr ds:,dl
00406473 FF3424 push dword ptr ss:
00406476 60 pushad
00406477 9C pushfd
00406478 8D6424 30 lea esp,dword ptr ss:
作用:
将EBP栈顶数据读取WORD长度数据,取BYTE长度保存到EDI堆栈。
SetEIP
代码:
00406CF4 F5 cmc ;
00406CF5 F7D6 not esi
00406CF7 66:C1E6 02 shl si,0x2
00406CFB 8B75 00 mov esi,dword ptr ss:
00406CFE F5 cmc
00406CFF 66:81F9 B522 cmp cx,0x22B5
00406D04 83C5 04 add ebp,0x4
00406D07 60 pushad
00406D08 9C pushfd
00406D09 60 pushad
00406D0A 8D6424 44 lea esp,dword ptr ss:
作用:
这里出示的是前半部分,从EBP栈顶读取数据给ESI,该指令是VMP里面的唯一一个跳转指令。
Retn
指令:
0040616E 80C2 E7 add dl,0xE7
00406171 89EC mov esp,ebp
00406173 66:19DD sbb bp,bx
00406176 FD std
00406177 D2D9 rcr cl,cl
00406179 59 pop ecx
0040617A F9 stc
0040617B 66:29FE sub si,di
0040617E 59 pop ecx
0040617F 66:81FF 8AAC cmp di,0xAC8A
00406184 98 cwde
00406185 5D pop ebp
00406186 80EE 8E sub dh,0x8E
00406189 66:89C7 mov di,ax
0040618C 5A pop edx
0040618D 88ED mov ch,ch
0040618F C0E9 02 shr cl,0x2
00406192 66:0FBCF3 bsf si,bx
00406196 59 pop ecx
00406197 F5 cmc
00406198 5F pop edi
00406199 66:0FBAF6 0F btr si,0xF
0040619E 66:29F6 sub si,si
004061A1 9D popfd
00406E23 8D9E E98ED341 lea ebx,dword ptr ds:
00406E29 8B7424 04 mov esi,dword ptr ss:
00406633 8B4424 0C mov eax,dword ptr ss:
00406637 98 cwde
00406638 8D83 CF4CE596 lea eax,dword ptr ds:
0040663E 8B4424 10 mov eax,dword ptr ss:
00406642 9C pushfd
00406643 8B5C24 18 mov ebx,dword ptr ss:
00406647 C64424 0C F2 mov byte ptr ss:,0xF2
0040664C FF7424 1C push dword ptr ss:
00406650 C2 2000 retn 0x20
作用:
恢复堆栈原环境,并退出虚拟机。
至此,我调试本程序的从运行到弹出对话框的原子指令分析完毕。

pxhb 发表于 2013-1-20 18:15

期待已久,终于发出来了

djy597060921 发表于 2013-1-20 18:19

谢谢分享!

LShang 发表于 2013-1-20 18:20

膜拜下
基本看不懂
这样的连载牛文,加个精华吧

yuan71058 发表于 2013-1-20 18:24

前排占 了 .............

小雨细无声 发表于 2013-1-20 18:27

额滴神.....膜拜折服

a070458 发表于 2013-1-20 18:37

期待楼主高考成功回来继续发表好文章
文章太大机子卡飞了。。。。。
有木有PDF{:1_906:}

jaffer 发表于 2013-1-20 18:37

膜拜一下。

Rookietp 发表于 2013-1-20 18:44

笨笨师傅,排版太差啦,看起来好费力.

gxwtk 发表于 2013-1-20 19:00

整理成doc或pdf文件就更好了。。。。。
要不看着费劲
页: [1] 2 3 4 5 6 7 8
查看完整版本: VMP逆向分析笔记(连载ing~)