首页
社区
课程
招聘
[旧帖] [原创]VMProtect加密程序解析 0.00雪花
发表于: 2010-9-9 17:39 15447

[旧帖] [原创]VMProtect加密程序解析 0.00雪花

2010-9-9 17:39
15447
收藏
免费 8
支持
分享
最新回复 (62)
雪    币: 32
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
26
感谢分享,看的不是很明白,基础不好啊
2010-9-16 20:24
0
雪    币: 1844
活跃值: (35)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
27
H 命名是给自己看的

看看你的分析能否抢闸在 看雪精华 10 里出现,不然就落在一年后了
2010-9-16 23:23
0
雪    币: 251
活跃值: (77)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
28
这个回调函数要悲剧了。。今天是不可能放出来了。。明天也不可能放出来了。何年何月出来要看了。。
我原来没有细看。。VMP的TLS回调函数里面装的东西,居然他妈的是一个完整的VM。和程序执行的那个用的是相同的初始化和Dispatch。。
在程序里面不能设置int3和硬件断点。。因为TLS里面已经执行过一个VM了。。它做了多少事情呀。。我们跟着进去的其实VMP已经做了很多事情了。
本来想着看看不能设置int3和硬件断点。。进去TLS看看。。还想着TLS里。。VM没有启动的话。。是不是能爽到直接看普通指令。。想不到。。原来TLS里面还有一个完整的VM。。
慢慢来吧。。也没有想着。一下子就搞定VMP。。
至少VMt里面是有着代码检测指令的。。刚好看看VMP是怎么检测的。。看VMP花几百条指令完成一个not(a)。。总比不过看点VMP的代码检测。。
2010-9-16 23:57
0
雪    币: 1556
活跃值: (310)
能力值: ( LV4,RANK:40 )
在线值:
发帖
回帖
粉丝
29
第一次见有精华的临时用户,膜拜一下

BTW,能否把加好的bin一起放上来?
2010-9-17 09:15
0
雪    币: 1708
活跃值: (586)
能力值: ( LV15,RANK:670 )
在线值:
发帖
回帖
粉丝
30
希望能整理一下。帖子内容太分散了。
2010-9-17 10:38
0
雪    币: 251
活跃值: (77)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
31
VM_POPdw_EDISTACK
VM_PUSHdw_BYTECODEdw
VM_ADDdw_EBPSTACK
VM_POPdw_EDISTACK
VM_POPdw_EDISTACK
VM_POPdw_EDISTACK
VM_POPdw_EDISTACK
VM_POPdw_EDISTACK
VM_POPdw_EDISTACK
VM_POPdw_EDISTACK
VM_POPdw_EDISTACK
VM_POPdw_EDISTACK
VM_POPdw_EDISTACK
VM_POPdw_EDISTACK
VM_POPdw_EDISTACK
VM_POPdw_EDISTACK

VM_PUSHw_BYTECODEb

VM_PUSHdw_BYTECODEdw
VM_MOVb_EBPSTACK_[MEMADDR] MEMADDR=[EBP]
;两条指令实现一个功能:从BYTECODE计算地址。读取该地址的数据
VM_PUSHdw_EBP
VM_COPYw_EBPSTACK
;两条指令实现一个功能:复制操作数,一个变两个
VM_NANDb
;操作数是NAND(a,a),5条指令实现一个逻辑运算:not(a)
VM_POPdw_EDISTACK         ;扫尾工作

VM_ADDb_EBPSTACK          ;a=a+b
VM_POPdw_EDISTACK

VM_PUSHdw_EBP
VM_COPYw_EBPSTACK
;两条指令实现了一个功能:复制操作数,一个变两个
VM_NAND
;操作数是NAND(a,a),5条指令实现一个逻辑运算:not(a)
;两个not,中间有一个加法是什么意思呢?
;运算:a=8 b=4
;not(a)=7
;a=a+b=7+4=11
;not(a)=4
;实现运算a=a-b
;用二进制更容易看:8=1000  4=100  
VM_POPdw_EDISTACK         ;扫尾工作
VM_MOVw_EDISTACK_EBPSTACK ;还读取1Byte的bytecode,用于修改参与Dispatch运算的bl,这个也记一下

VM_MOVdw_EBPSTACK_EDISTACK
VM_MOVdw_EBPSTACK_EDISTACK
VM_NANDdw                 ;操作数相同,nand(b,b)=not(b) b
VM_POPdw_EDISTACK         ;扫尾工作
VM_PUSHdw_BYTECODEw                                      a
VM_NANDdw                 ;操作数不同,nand(a,nand(b,b))        
;这里我的注释只是我跟的那一圈时候的参考,到底是同数NAND还是异数NAND,要看具体的了。反正VM_HANDdw只是负责读取EBPSTACK栈顶的2个dword去操作,而上面说道的nand是多了一个复制操作数的指令。所以肯定nand(a,a),而这里是没有复制的这一步操作,所以要看具体情况
VM_POPdw_EDISTACK         ;扫尾工作
VM_POPdw_EDISTACK         ;保存结果 00000286

VM_MOVdw_EBPSTACK_EDISTACK
VM_MOVdw_EBPSTACK_EDISTACK
VM_NANDdw                 ;操作数相同 nand(b1,b1)   eflags   b1
VM_POPdw_EDISTACK         ;扫尾工作
VM_PUSHdw_BYTECODEw                                          a1
VM_NANDdw                 ;操作说不同 nand(a1,nand(b1,b1)
VM_POPdw_EDISTACK
VM_ADDdw_EBPSTACK         ;nand(a,nand(b,b)) + nand(a1,nand(b1,b1)
VM_POPdw_EDISTACK
VM_POPdw_EDISTACK         ;保存结果,两个保存数据都在EDISTACK栈顶 00000246

VM_PUSHdw_BYTECODEdw
VM_PUSHdw_BYTECODEdw
VM_PUSHdw_EBP
VM_PUSHw_BYTECODEb
VM_MOVdw_EBPSTACK_EDISTACK  ;放入的是上一个计算结果
VM_PUSHdw_EBP               
;一口气放了一堆数据进去。来自各种各样的地方,有两个操作数堆栈地址,VM一定要绕着,数据就在堆栈里,也要先去取出操作数地址,然后再从里面读出来。贴个当前堆栈图,倒着就可以找到各个PUSH的数据
CPU Stack
Locked    Value      ASCII Comments
0013F998   F99E
0013F99C   02460013  .F
0013F9A0   00040000  ...
0013F9A4   0013F9A8  .
0013F9A8   4DBE49D5  IM
0013F9AC   4DBE4AD8  JM

VM_COPYdw_EBPSTACK         ;复制操作数,完了后ebpstack就变这样
CPU Stack
Locked    Value      ASCII Comments
0013F998   0246
0013F99C   02460000  ..F
               0000  ...
VM_NANDdw                  ;继续计算,00000246是上面nand(a,nand(b,b)) + nand(a1,nand(b1,b1)得到,现在再加一个nand,就变成nand[nand(a,nand(b,b)) + nand(a1,nand(b1,b1),nand(a,nand(b,b)) + nand(a1,nand(b1,b1)],虽然VM猥琐了一下,隔开了再运算。我们要不受影响
VM_POPdw_EDISTACK          ;VM的nand运算后堆栈顶还有一个原来操作数的位置,调用这条指令扫尾
VM_PUSHdw_BYTECODEb
VM_NANDdw
VM_POPdw_EDISTACK
VM_SHRdw_EBPSTACK          ;几个NAND的计算结果右移
VM_POPdw_EDISTACK          ;扫尾

VM_ADDdw_EBPSTACK          ;我们需要好好的停下来,说明一下。因为这里已经实现了一次条件判断,等有时间再来加上它条件判断的解析,发点堆栈空间。一个是前面的。后一个是判断完了的。。
CPU Stack
Locked    Value      ASCII Comments
0013F998   F99E
0013F99C   02460013  .F
0013F9A0   00040000  ...
0013F9A4   0013F9A8  .
0013F9A8   4DBE49D5  IM
0013F9AC   4DBE4AD8  JM
CPU Stack
Locked    Value      ASCII Comments
0013F9A0   00000004  ...
0013F9A4   0013F9AC  .
0013F9A8   4DBE49D5  IM
0013F9AC   4DBE4AD8  JM

VM_COPYdw_EBPSTACK
CPU Stack
Locked    Value      ASCII Comments
0013F9A4   4DBE4AD8  JM
0013F9A8   4DBE49D5  IM
0013F9AC   4DBE4AD8  JM
VM_POPdw_EDISTACK                    ;这个不是扫尾,把计算结果保存到EDISTACK
VM_POPdw_EDISTACK
VM_POPdw_EDISTACK                    ;这两个么才是清除EBPSTACK垃圾数据
VM_MOVdw_EBPSTACK_EDISTACK           ;这里呢重新取出来,因为刚才的是加密数据而且只实现了条件判断。还要继续操作
(感谢发邀请码给我)
VM_PUSHdw_EBP                        
VM_COPYdw_EBPSTACK                   ;两个指令完成的是复制栈顶数据操作            
VM_POPdw_EDISTACK                    ;复制然后保存了一份到EDISTACK    tag1                  
VM_PUSHdw_EBP
VM_COPYdw_EBPSTACK
VM_NANDdw                            ;取反数据not(a)
CPU Stack
Locked    Value      ASCII Comments
0013F9A8   4DBE4AD8  JM
0013F9AC   4DBE4AD8  JM
VM_POPdw_EDISTACK                    ;扫尾
VM_PUSHdw_BYTECODEdw                 ;重新获取一个操作数b
VM_NANDdw                            ;NAND(not(a),b)
VM_POPdw_EDISTACK                    ;扫尾
VM_MOVdw_EBPSTACK_EDISTACK           ;取得就是前面复制的a,还没有进行操作的   tag1指令
VM_PUSHdw_BYTECODEdw                 ;获得操作数b1
VM_NANDdw                            ;NAND(a,b1)
VM_POPdw_EDISTACK                    ;扫尾
VM_NANDdw                            ;现在2个操作数合并NAND[NAND(NOT(A),B),NAND(A,B1)]
VM_POPdw_EDISTACK                    ;扫尾,看一下EBPSTACK堆栈
CPU Stack
Locked    Value      ASCII Comments
0013F9AC   0043651A  eC.            ;计算结果是这个
VM_POPdw_EDISTACK                    ;这个保存很重要,等下肯定还要读取,跟进handler里面去,记一下位置:0013F8C0  tag1
VM_POPdw_EDISTACK                    ;已经保存了数据,清除EBPSTACK,扫尾

VM_MOVdw_EBPSTACK_EDISTACK           ;存进去,马上继续操作,读出来了   tag1指令
VM_MOVdw_EBPSTACK_EDISTACK           
VM_MOVdw_EBPSTACK_EDISTACK
VM_MOVdw_EBPSTACK_EDISTACK
VM_MOVdw_EBPSTACK_EDISTACK
VM_MOVdw_EBPSTACK_EDISTACK
VM_MOVdw_EBPSTACK_EDISTACK
VM_MOVdw_EBPSTACK_EDISTACK
VM_MOVdw_EBPSTACK_EDISTACK
VM_MOVdw_EBPSTACK_EDISTACK
VM_MOVdw_EBPSTACK_EDISTACK
VM_MOVdw_EBPSTACK_EDISTACK
;这么多数据被从EDISTACK移动到了EBPSTACK。这是原来初始化保存的context数据,第一个是计算出来的数据的
;看一眼堆栈
CPU Stack
Locked    Value      ASCII Comments
0013F980   8021D2F0  !     ; UNICODE "tractTitle"
0013F984   0013F9C0  .
0013F988   00000246  F..
0013F98C   00000020   ...
0013F990   000359F4  Y.
0013F994   0013F9CC  .
0013F998   00400000  ..@.  ;
0013F99C   00000000  ....
0013F9A0   004253CD  SB.   ; RETURN from NOTEPAD.004255DB to NOTEPAD.004253CD
0013F9A4   000359F4  Y.
0013F9A8   00400000  ..@.  ;
0013F9AC   0043651A  eC.
VM_PUSHdw_BYTECODEdw                ;还在继续放数据进EBPSTACK,但是从BYTECODE中获得
VM_ADDdw_EBPSTACK                   ;看一下堆栈,它的操作数是:
CPU Stack
Locked    Value      ASCII Comments
0013F97C   7FDE2D10  -
0013F980   8021D2F0  !     ; UNICODE "tractTitle"  ;运算结果是00000000
VM_POPdw_EDISTACK                      ;扫尾
VM_MOVdw_EBPSTACK_EDISTACK             ;继续放数据
VM_MOVdw_EBPSTACK_EDISTACK        ;把计算好的跳转地址再压入一次。现在0043651A就在EBPSTACK的栈顶
VM_JMP                            ;把0043651A放到ESI,ESI是VM的BYTECODE指针,这久相当于跳转
;我们来看一下,VM_JMP结束后,并不是像其他伪指令一样,跳到Disptch,而是在它的上面一点,多执行几条指令:
0043E6A9    89F3            MOV EBX,ESI                              ; *
0043E6B8    0375 00         ADD ESI,DWORD PTR SS:[EBP]               ; *
;EBX是参与到BYTECODE的数据解码的,既然ESI指向的BYTECODE地址不同了,EBX也要重新填充
;[EBP]中是00000000,这是VM初始化进入时,放入的0,它应该是一个偏移量,每次进入新的BYTECODE地址时,地址都要加上这个偏移量,在VMP中一个已经计算好的数据,可能VMP原来可以ESI到这里都是指向另一个位置,通过这个偏移量修正ESI指向BYTECODE地址。
;我们来回忆一下,VM到现在为止,只是进行了一次条件判断,然后跳转到相应的位置(这就是几千条指令做的事,⊙﹏⊙b汗)
;VM条件判断的操作数都是从BYTECODE流中获得,不是动态的去获取了什么信息,或许,这是VMP内部的一个标志判断,看有没有设置XX标志,要不要跳转到YY代码去执行一下,按照这样的思路来看的话,我们的程序已经跳转,我们要过去看看到底这个YY代码是做什么的,还有XX标志如果是VMP内部的标志的话,是什么标志呢?我们知道由于在原程序里无法设int3和硬件断点后保存,否则下次重新打开就会出问题,所以我们才进TLS来的,至少这个TLS是包含了代码检测的,猜测一下,这个XX标志难道是VMP用来判断是否进行代码检测的标志?如果那样,如果我们爆破了那个条件判断结果,不去YY代码执行,是不是能够跳过代码检测?一切都是未知的,以上内容纯属猜测,我们还是继续跟着进YY代码去看看吧,如果YY代码真的是负责代码检测的,我们再回来考虑爆破问题。。(以上猜测完全错误。。⊙﹏⊙b汗)

进入新的ESI指向的BYTECODE
VM_POPdw_EDISTACK                         ;0013F8F0=00000000 原程序用的偏移量的0
VM_PUSHdw_BYTECODEdw              ;8021D2F0这个数字出现过几次了
VM_ADDdw_EBPSTACK                        ;加上原程序初始化时的另外一个00000000
VM_POPdw_EDISTACK                        ;扫尾
VM_POPdw_EDISTACK                        ;0013F8D4=8021D2F0
VM_POPdw_EDISTACK                        ;0013F8D0=0013F9C0 这个比较记得,是原程序的EBP指针
VM_POPdw_EDISTACK                        ;0013F8C8=00000246 这个是EFL
VM_POPdw_EDISTACK                        ;0013F8EC=00000020
;换了ESI指针,重新保存初始化的几个数据,
;在EDISTACK与EBPSTACK的移动指令里下个断,以后移动数据的位置都记录下来
VM_PUSHdw_EBP                       
VM_COPYdw_EBPSTACK                ;复制000359F4,看来要搞这个数,记录有点不清,忘记这个数是怎么来的了
VM_POPdw_EDISTACK                        ;0013F8D8=000359F4,存个备份到EDISTACK
VM_PUSHdw_EBP                                ;
VM_COPYdw_EBPSTACK                         ;在复制000359F4
VM_NANDdw                                ;NAND(A,A)=NOT(A)=FFFCA60B
VM_POPdw_EDISTACK                        ;扫尾
VM_PUSHdw_BYTECODEdw                        ;从BYTECODE流中获得一个参数
VM_NANDdw                         ;NAND(NAND(A),B)
VM_POPdw_EDISTACK                        ;扫尾

VM_PUSHdw_BYTECODEdw                        ;取个参数:4DFD2FC2
VM_MOVdw_EBPSTACK_EDISTACK                 ;移动00359F4过来,就是刚才原始的A
VM_NANDdw                                ;NAND(A,B1)
VM_POPdw_EDISTACK                        ;扫尾
VM_NANDdw                                ;NAND[NAND(A),B),NAND(A,B1)]
VM_POPdw_EDISTACK                        ;扫尾
VM_NANDdw                                ;上面的两个操作数,再次NAND
;前面跳转的地方就有这段了。这次再次出来,就在这里解析一下,这个操作是实现xor(a,b)。B和B1是有联系的,她们互为相反数,是你等于虚拟机直接传了一个相反数过来,相当于隐藏了一次NAND(B,B)操作。来看一个实例演算,演算过程放在下一楼
VM_POPdw_EDISTACK                        ;0013F8C4=4DFE7636 xor(000359F4,4DFD2FC2)
VM_POPdw_EDISTACK                        ;0013F8C0=0013F9CC 继续保存原来程序的context结构数据
VM_POPdw_EDISTACK                        ;0013F8E0=00400000
VM_POPdw_EDISTACK                        ;0013F8E8=00000000
VM_POPdw_EDISTACK                        ;0013F8F8=004253CD
VM_POPdw_EDISTACK                        ;0013F8CC=000359F4
VM_POPdw_EDISTACK                        ;0013F8DC=00400000
VM_POPdw_EDISTACK                        ;0013F8E4=0043651A
;所有的原程序cotext等数据保存完毕,提取context等数据,改动了其中之一。保存回去
2010-9-17 19:06
0
雪    币: 251
活跃值: (77)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
32
当进行双操作数运算时(通常都是),运算完后,结果占据了原操作数的一个位置,还有一个位置,另一个操作数在运算中会读取当前的EFL寄存器覆盖;为了保证通用性(不一定都是双操作数)VM并没有在VM_NAND这样的指令中清除另一个操作数的堆栈空间,而是在结束后还需要调用VM_POPdw_EDISTACK的指令(不一定是dw,但是那个只是一点点变化),把EBPSTACK的栈顶数据清除到EDISTACK;这条指令并不是只作为清除,它也可以当做一条MOV指令来用,把数据从EBPSTACK移动到EDISTACK

VM_PUSHdw_EBP                        
VM_COPYdw_EBPSTACK                   ;两个指令完成的是复制栈顶数据操作
VM_POPdw_EDISTACK                    ;扫尾

XOR指令实际是VM运用NAND操作中有NOT操作。它保存了一个NOT操作,这样就相当于隐藏了一次NAND(B,B)的操作

贴不了了。说说理论吧。关于int3指令的检测。非常正规,和常规方法没有任何区别。从PE文件进去,获得程序文件开头地址。读取代码进行测试,没什么特色。

在数据的堆栈移动中。比如:
存储到[EDI+EAX]的位置,EDI是固定的,而EAX是临时运算的。
我们通过看EAX的计算过程可以看到,EAX的最大偏移位置是0--3C,一共可以有16个存储位置。同时为了按照4的边界对齐,选择了3C这个来构造

VM的虚拟环境检测,没有特色。都是一些老东西。。很平常的VMware检测
2010-9-18 12:49
0
雪    币: 251
活跃值: (77)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
33
这个帖子拖这么长 代码估计是不发了 来更新上一些理论知识
我的帖子怎么沉这么深了 给我起来!!^_^
加点东西
跳过了N多的指令 一下的所有记录都将是跳跃式的 一切初始化、计算、移动等无聊部分都被略过 当然如果关键操作 而我也没有看到的也将被跳过 将就着看吧VM_MOVdw_[EBP]_EBP+4这是一条跨堆栈的指令,他可以把数据随意的存到其他地方,VM就是用这条指令把下面的DLL的名字存入到EBPSTACK下面的堆栈中,下面的堆栈空间被当做是一个字符串存储的数据空间
CPU Stack
Locked    Value      ASCII Comments
0013F790   7C80B741  A|    ; kernel32.GetModuleHandleA
0013F794   0013FF8C  .    ; ASCII "SbieDll.dll"
VM_APIJMP_EBPSTACK
;这个指令首先给ECX放入API参数的个数,循环读取参数,最后跳转进系统空间
;第一个APIJMP检测的是 沙盘(sandboxie) 我没有用沙盘
;跳转地址:004363EA

;解码出第二个要检测的函数kernel32.IsDebuggerPresent
;还有一个地址0013F6C8   004393BC  C.    ; Entry point of procedure
CPU Stack
Locked    Value      ASCII  Comments
0013F698   7C813133  31|    ; kernel32.IsDebuggerPresent
;下一个要检测的是IsDebuggerPresent函数,但是在进入之前,先来一个CC码检测,看看有没有下断
CPU Stack
Locked    Value      ASCII  Comments
0013F790   3133
0013F794   00CC7C81  |.
VM_EBPSTACKw_MEMb
0013F794   00CC0064  d..
;接下来就是一系列的检查和比较跳转 这里不再复述
;我肯定是没有下断点洒 最后计算好、解密完的地址是0043C2D4
VM_JMP                                        ;走起
0013F698   7C813133  31|    ; kernel32.IsDebuggerPresent
VM_APIJMP_EBPSTACK
;这里就直接该返回值了,返回值肯定是1洒,毫不犹豫的改为0
;接着就是检测返回值了 毫无疑问 VM检测不出来^_^
;最后的比较跳转地址:0043929C
VM_JMP                                        ;走起

0013F794   7C85AAF2  |      ; kernel32.CheckRemoteDebuggerPresent
;我们的第三位登场的角色就是它了
VM_JMP                                        ;走起
;CC码检测是必须的
VM_EBPSTACKw_MEMb
0013F794   00CC008B  ..
;最后的比较+跳转时刻的堆栈图:
0013F780   FFBF
0013F784   FD6CFFFF  l
0013F788   0004FFFF  .
0013F78C   0013F790  .
0013F790   7681CB89  藖v
0013F794   768003D3  v
;我肯定是没有下断点洒 最后计算好、解密完的地址是0043A82B
VM_JMP                                        ;走起
0013F78C   7C85AAF2  |     ; kernel32.CheckRemoteDebuggerPresent
0013F790   FFFFFFFF
0013F794   0013FF98  .
VM_APIJMP_EBPSTACK                        ;执行去了
;返回值修改为0
;接着还是一系列的比较,ZF位检测,最后的跳转地址:00428F50
;我们如果不修改,被查到你开了调试器,跑去了另外一路的结局就是:
0013F794   00423E60  `>B.   ; ASCII "A debugger has been found running in your system.
Please, unload it from memory and restart your program."
VM_APIJMP_EBPSTACK
0013F788   7C80B56F  o|     ; kernel32.GetModuleFileNameA
0013F78C   00400000  ..@.   ; OFFSET NOTEPAD
;最后的结局就是消息框里“嘣”的弹出上面的话给你
VM_JMP                                        ;走起

0013F794   7C809BE7  鐩€|     ; kernel32.CloseHandle
;下一个是这位
0013F784   7C809BE7  鐩€|     ; kernel32.CloseHandle
0013F788   DEADC0DE                                        ;这叫什么东西!
0013F78C   0013FFE0  .     ; Pointer to next SEH record
0013F790   00427A04  zB.   ; SE handler
0013F794   0013FF98  .
VM_APIJMP_EBPSTACK                                        ;执行
;返回为0 也不用去异常 这是一个关闭无效句柄的检测 DEADCODE本身就不是什么东西
;跳转地址:0042357C
VM_JMP                                        ;走起
;这次去的地方并不是新的函数,而是释放掉在CloseHandle函数那里构建的SEH

0013F794   7C863FCA  ?|     ; kernel32.UnhandledExceptionFilter
;首先依然是检测CC码,跳转地址:00422E3E
VM_JMP                                        ;走起
0013F794   7C809BE7  鐩€|     ; kernel32.CloseHandle
;这个也一起出现,跳转地址:004262DC
VM_JMP                                        ;走起
0013F76C   0013FF8C  .     ; ASCII "sice.sys"
;这个也出现,跳转地址:00422D4C
VM_JMP                                        ;走起
0013F794   0013FF8C  .     ; ASCII "siwvid.sys"
;字符串进一步解码为这个
0013F790   00425E64  d^B.
0013F794   0013FF8C  .     ; ASCII "siwvid.sys"
VM_APIJMP_EBPSTACK
;命名的有点问题,这个handler并不只是可以跳去API,它是有一个分支的,这里它就跳去了一个VM的call里
;SoftIce都停止开发了,我也没有用洒,不怕它检测
0013F634   7C92D92E  .賿|    ; ntdll.NtQuerySystemInformation
;呼呼 好绕呀,最后进入的是这个函数
;跳转地址:0042357C
VM_JMP                                        ;走起
;跳转地址:00426071 我晕 我想不起我装了SoftIce的,让我们重新来过,这里过去就灭了
VM_JMP                                        ;走起
2010-9-18 14:23
0
雪    币: 251
活跃值: (77)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
34
留位留位留位留位留位留位
2010-9-18 14:23
0
雪    币: 251
活跃值: (77)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
35
留位留位留位留位留位留位留位留位
2010-9-18 14:24
0
雪    币: 251
活跃值: (77)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
36
留位留位留位留位留位留位留位留位留位
2010-9-18 14:24
0
雪    币: 1312
活跃值: (5164)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
37
强...............
2010-9-19 02:32
0
雪    币: 1312
活跃值: (5164)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
38
我也留位...............
2010-9-19 02:32
0
雪    币: 8
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
39
这么长的文章一定是好文章,只是看不懂,帮顶。
2010-9-19 12:46
0
雪    币: 9
活跃值: (25)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
40
此人用的IDA静态分析VMProtect的程序,
但是怎么找到的对应的一些关键点呢?

凭眼力吗?
2010-9-19 19:53
0
雪    币: 252
活跃值: (37)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
41
都快成大牛了。
2010-9-19 22:07
0
雪    币: 20
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
42
啊。。。太牛了,快点解VMP吧!
2010-9-20 11:51
0
雪    币: 251
活跃值: (77)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
43
还不起来 更待何时!
2010-9-29 11:58
0
雪    币: 375
活跃值: (12)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
44
写得不错。
楼主出工具没?
2010-9-29 12:31
0
雪    币: 251
活跃值: (77)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
45
不出,只是学习

此贴结贴 不再更新了
2010-9-29 12:41
0
雪    币: 189
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
46
支持,写得蛮不错的。
2010-10-4 13:09
0
雪    币: 105
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
47
楼主写得很好哦,保存下来了
2010-10-4 15:14
0
雪    币: 35
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
48
这篇文章好长哦!汇编书上并没有这些东西啊。
2010-10-5 15:00
0
雪    币: 88
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
49
好贴,mark下。
2010-11-15 18:03
0
雪    币: 75
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
50
谢谢老师分享,辛苦了!!!
2010-11-16 11:12
0
游客
登录 | 注册 方可回帖
返回
//