在把壳子开源之前,我会先对VMProtect1.70.4这个版本做一个简单的分析。在这几天分析过程中,我感受到了VMProtect的威力,并得出一个结论:分析VMProtect非常耗时间,如果没有做好与之长期斗争的准备,很难有实用的成果。另外,由于我第一次分析VMProtect,有分析不对的地方或者术语用得不恰当的地方,希望老萌萌们能指出来,我立即修改,不能误人子弟。分析的样本有三份,我放到了附件里面。 壳子我是去年写的,当时刚刚看了<<加密与解密>>第四版的第21章,我估摸了一下,自己可以写出来,然后就写出来了。在写之前,我记得当时还在bilibili观看了哈工大姜守旭教授教授的编译原理这门课程的视频,了解了大概就开干,看视频这个操作,对我写指令壳起了一种壮胆的效果。现在要开源,我又熟悉了下整个项目的流程。代码写得有点乱,我会画一张加壳时的流程图做一个直观的说明,和其他一些要点说明,以减少读代码时遇到的困惑。如果遇到调试或者编译问题,可以留言,我看到会及时回复。指令壳源码我会上传到附件。
写一个简单程序来测试:(ps:这个程序在vmp样本一文件夹)
在OD中打开,函数在0x401080这个位置。 打开vmp,开始加壳: 下拉列表选择最快速度,其他不选择。 程序加好壳子后,用OD打开,开始分析: 0x401080这儿已经变为jmp了,跳到.vmp0这节里面:
以上操作是把寄存器压到栈里,执行完后如下图:
寄存器压栈完成后,会先计算出调度表的地址。 [esp+48]这个值就是入口push 4A781400 这个值,经过计算后得到调度表的地址。调度表地址存放在esi寄存器里。
如下,内存5里显示的就是经过加密的调度表:
然后按F7,到下面那个位置,箭头指向的三步,ebp指向的是真实堆栈,edi就是虚拟机的上下文环境(VMContext)。edi指向的堆栈空间,最大的作用就是存放寄存器。
在接下来的步骤中,通过在esi指向的调度表中取值,然后把ebp所指向的寄存器的值,挨个放到edi的虚拟环境中。 至此,虚拟机的环境构建完成,准备工作已经做好。
接下来进入正题,程序会通过edi寄存器取ebx的值,取两次,第一次的值压入[ebp],第二次压入[ebp+4],然后进入一个handler块进行运算。 这就是那个handler块:
可以把上面的handler块命名为Handler_NOT_AND
那么,可以把以上的运算过程可以表示成这样:not(ebx) and not(ebx)
执行xor eax,ebx这条指令的时候,虚拟机会多次调用Handler_NOT_AND 块,整个流程可以记录为如下形式:
T = not(not(ebx) and not(ebx)) and not(not(eax) and not(eax));即为:T = ebx and eax; S= not(eax) and not(ebx); 最终结果:ret= not(T) and not(S)。 通过写程序来验证,与虚拟机算出来的0x690035一致,说明流程记录没有问题。那么,xor eax,ebx可以用这个表达式来表示:eax = not(ebx and eax) and not(not(eax) and not(ebx))。 执行完xor eax,ebx之后,eax寄存器的位置在edi中的会变:
下一个xor eax,ebx 和上面的操作是一样的,这个操作完了,eax=0x004A3035。 eax寄存器的位置在edi中又变了:
按F7单步跟,(...省略不重要的部分),接着,程序把edi中所保存的寄存器,再吐出来给ebp所指向的堆栈空间,然后ebp赋值给esp,最后再pop到真实寄存器,退出虚拟机。 退出虚拟机:
测试程序和上面一样。(ps:这个程序在vmp样本二文件夹) 下拉列表选择最快速度,再把调试器勾选上,其他不选择。
加壳完成后,打开CFF来查看,程序会新增一节.vmp1,程序入口也在这节里面。
此外,还构建了一个TLS表:(但在这儿作用似乎不大)
程序执行到入口后,按F7单步跟,步骤和上面“01速度最快"分析时相差无几,会先构建虚拟机环境。 虚拟环境构建完成后,接着按F7单步跟,我的想法是,很快就能找到一些反调试的线索,但是跟了几个小时,发现不对劲了,和上面“01 速度最快"分析时用手工跟踪,完全不在一个数量级的。天气又大,整个人木在那里。后来,想到在退出虚拟机那个地方下断,方法就是搜索vmp1这节的ret或者ret xx,最终找到两个地方,一个是调度器ret xx,这个不管,另一个就是下图所给出的,在ret 0x40处下断。按F9程序跑起来后,会断在这里,能看到右边寄存器窗口的字符串。这个位置,可以作为过掉检测调试器的突破口。 当然,最好的办法应该是在一些能检测出调试器的API函数下断。 vmp1.70.4这个版本,开启调试器检测后,程序会依次调用以下的API来检测是否有调试器存在:
注意:API下断时,不要在头部下断,虚拟机会对有些API函数的头部进行0xCC检测,比如在这个程序中,虚拟机执行到GetThreadContext函数之前,会对GetThreadContext函数的头部进行0xCC检测。建议:没有特殊状况,对API下断时要避开在头部下断。
此外,在调用CloseHandle之前,虚拟机会手工构造一个SEH异常处理例程,如果调用成功,没出现异常,那么虚拟机会移除这个SEH。假如调用CloseHandle触发异常,那么将万劫不复,程序进入0x4A99AE后,你会寸步难行,我这儿遇到的是非法写入的异常,程序一直卡在那里。
想过掉CloseHandle检测,可以在CloseHandle头部直接返回(eax=0),然后恢复选区即可。
测试程序:(ps:这个程序在vmp样本三文件夹)
用OD打开,找到test_vmp函数的位置:0x4010E0。
打开vmp,开始加壳:
选择最大保护。
把加壳后的程序,拖入OD,程序断在了入口处:
找到0x4010E0,下一个硬件断点,然后按F9让程序跑起来:
程序断在了这里,按F7单步跟踪:
程序会先构建虚拟机环境,上面已经分析了,这里省略。
开始进入正题,因为程序在加壳的时候勾选了隐藏常量和内存保护,对我这种初等选手,所以刚开始的时候就遇到了困难。 在第一条指令(mov eax,[esp+4])中,虚拟机会先对[esp+4]解码,又因为4是常量,所以虚拟机刚开始的时候,会对这个常量解密操作。 大概步骤:程序会在esi指向的调度表读取四个字节,并且在解密过程,还会读取多次,来对常量解密。esp寄存器也是加密了的,解码操作和解码常量差不多。
mov eax,[esp+4] 模型是:mov 寄存器,内存 这种模式的指令会走如下的handler块:
关于xor eax, ebx 指令,上面有分析过,除了垃圾指令,其他没变:
在mov g_num,eax这条指令中,虚拟机对g_num内存地址也是加密了的,解密时候,程序会对esi指向的调度表读取四个字节,并且会读取多次,经过计算最终得到g_num的内存地址。 mov g_num,eax 模型是:mov 内存地址,寄存器 这种模式的指令会走如下handler块:
关于隐藏常量和内存保护的解密过程,只是跟了几遍,了解了大概流程,没有具体分析,退出虚拟机时,加密寄存器,这个解密模式和隐藏常量和内存保护的解密过程似乎差不多。总的来说,这次分析过程是失败的,因为隐藏常量、内存保护以及离开虚拟机时加密寄存器的解密过程没有分析出来,只是把汇编指令在虚拟机中的handler块找出来了。我觉得,这些解密操作,正是vmprotect虚拟机最精华的部分之一,在跟踪这些解密操作的时候,我脑袋都大了,暂时先搁在这儿,做一些更有意义的事情(^_^ )。这节可以省略不看。如果有像我一样的初等选手,跟起来又有点费劲,又想了解这个解密过程的,可以在看雪搜搜,有很多大神都应该分析过。
项目名称:指令壳框架 功能:可以对32位可执行程序加壳(*.exe) 编译器:vs2019(编译模式采用的是Debug模式,也就是调试模式) 开发语言:C、C++、内联汇编 解决方案:一个解决方案,两个项目(VMProtect、Stub,VMProtect是现实核心功能,Stub是外壳部分)
Common文件夹里封装了一些类: CString类即是字符串操作的类,支持字符串和整型混合相加(字符串+(DWORD)16进制/10进),生成一个字符串。(注意:加16进制时,前面要加DWORD表示这是16进制。) PE类封装了处理PE文件格式一些函数,比如文件拉伸、修复重定位表、添加新节等等。 FileOpenration类是文件操作类,封装了打开文件、删除文件、保存文件、创建子进程等等一些函数。
在加壳过程中,要频繁用到内存申请、内存释放的操作,为了防止内存泄漏,我封装了一个类(AllocMemory)用来申请内存, 这个类的作用就是只管申请内存,不用管释放,这个类会自动释放内存:
程序外观:
实验:对test_vmp函数加壳
拖入OD,在0x401010这个位置:
打开vmp_1.0,开始加壳:
回到项目,点击编译:
用OD打开,经过加了花指令的从IAT表拷贝过来的API的跳转地址,每次执行时,样式都不一样。 第一次打开:
用OD第二次打开:
此外,对加了该指令壳的函数,每次进入该函数后,指令也会变,这些操作都是在外壳中完成的,具体请参考Stub项目。
指令分析器的作用:把要保护的指令,翻译为中间表示。我用的是BeaEngine引擎,所以在解析指令的时候,需要遵循BeaEngine反汇编引擎的规则。 指令分析器的主框架如下:
上面这个解析器,对一条指令是从右往左解析的,比如这条指令:mov eax,eax 翻译为中间表示就是:
handler操作和数据是分别保存的,仍然以上面那条指令为例:
内存操作处理起来比较麻烦,至少对我来说是如此,MemoryMiddle()函数用来专门处理内存操作。 例如这条指令 mov dword ptr[eax+ecx*4+0x401000],eax,可以译成如下的中间表示:
此外,局部变量的操作,比如这条指令:mov dword ptr[ebp-0x8],eax,仍然可以用MemoryMiddle函数来翻译:
下面举个完整的例子:
上面这个函数,翻译为中间表示如下:
垃圾指令构造器的设计很简单,对我来说,难点在于垃圾指令的选择,有些指令是不能作为垃圾指令,改变普通寄存器的指令我没有用,比如AAA指令,会改变eax寄存器的值。 下面是垃圾指令的构造器核心函数:
ProduceRubbishOpecode函数,每被调用一次就可以构造一条垃圾指令。
把要用到的handler全部放到一个表格中归类整理,如下图: 先来举一个例子,比如指令:xor eax,eax
上面每一个中间表示的handler都有对应一个函数:
vmtest.h和vmtest.cpp分别存放了所有handler块的声明和具体实现。请参考VMProtect项目。
IAT解密模块、反调试模块以及花指令构造器,都在Stub项目中,Stub.dll动态库是整个程序的外壳部分。 IAT加密过程: 第一步把IAT表转存到一个临时数据结构中,然后清除IAT和INT表,最后把临时数据结构中的函数名称加密。这步是在VMProtect项目中完成的。 第二步在Stub中解密这个临时数据结构,解密之后,再加密,并且加上花指令。 花指令构造器具体实现在JunkCode.cpp文件中。以下列出花指令构造器的核心函数:
测试的时候,我只是对常用的指令添加了handler块,还有很多指令是没有处理的,那么,程序在加壳过程中,如果有jmp或者jxx跳转到未知指令(未知指令是指没有添加handler的指令,找不到匹配),就会出错,此时,则应该先检查是否有未知指令,并添加相应的handler块。 添加方式:以inc指令为例子 第一步: 在vmtest.h中添加声明CString vINC(char VR0, char VR1);
第二步:在vmtest.cpp中实现其函数功能。
第三步: 在VMLoader2.cpp,把55改成56,在g_FunName数组里添加{vINC,"inc ","vINC "},注意"inc "和"vINC ",后面有一个空格, 不然程序在匹配inc指令的时候匹配不上,就会把inc当成不可模拟指令来处理。
这个加壳程序,设计上有先天缺陷,这可以归咎于我正向开发的基础不扎实,还有就是只掌握了编译原理的一些皮毛知识,好些地方都有点乱,像是硬怼的,很多地方现在还能看到打斗的痕迹。整个程序,由于在设计上的缺陷,使得虚拟机不能对寄存器进行轮转操作。另外,汇编指令是直接换成handler块的,中间没有先对汇编指令进行任何变形。所以,这只是一个模拟vmprotect的最最简单的指令壳子。
编译时,请采用Debug和x86模式:
编译时,可能会遇到的编码错误:
Stub项目运行库选择多线程(/MT)
void __declspec(naked) test_vmp(
int
a,
int
b)
{
/
*
__asm {
mov eax,dword ptr[esp
+
4
]
mov ecx,dword ptr[esp
+
8
]
add eax,ecx
ret
}
*
/
__asm {
xor eax,ebx
xor eax, ebx
ret
}
}
int
main()
{
test_vmp(
1
,
2
);
printf(
"%d\n"
, x);
system(
"pause"
);
return
0
;
}
void __declspec(naked) test_vmp(
int
a,
int
b)
{
/
*
__asm {
mov eax,dword ptr[esp
+
4
]
mov ecx,dword ptr[esp
+
8
]
add eax,ecx
ret
}
*
/
__asm {
xor eax,ebx
xor eax, ebx
ret
}
}
int
main()
{
test_vmp(
1
,
2
);
printf(
"%d\n"
, x);
system(
"pause"
);
return
0
;
}
/
/
入口
00401080
| jmp debug_test2.vmp.
4A77D2
| Debug_test2.cpp:
5
004A77D2
| push
4A781400
|
004A77D7
| call debug_test2.vmp.
4A6B9F
|
004A6B9F
| jmp debug_test2.vmp.
4A703A
|
004A703A
| push esi | esi:_mainCRTStartup
004A703B
| jmp debug_test2.vmp.
4A52E8
|
004A52E8
| pushfd |
004A52E9
| push D3AC6D6A |
004A52EE
| mov byte ptr ss:[esp
+
4
],
8F
|
004A52F3
| pushfd |
004A52F4
| pop dword ptr ss:[esp
+
4
] | [esp
+
4
]:___use_sse2_mathfcns
+
4A78
004A52F8
| jmp debug_test2.vmp.
4A64C1
|
004A64C1
| call debug_test2.vmp.
4A5FE9
|
004A5FE9
| pushad |
004A5FEA
| mov dword ptr ss:[esp
+
24
],ebp | [esp
+
24
]:_mainCRTStartup
004A5FEE
| push esp |
004A5FEF
| pushfd |
004A5FF0
| push
72B57CE7
|
004A5FF5
| pushfd |
004A5FF6
| mov dword ptr ss:[esp
+
30
],eax | eax:___use_sse2_mathfcns
+
2D1
004A5FFA
| mov byte ptr ss:[esp],cl |
004A5FFD
| call debug_test2.vmp.
4A701F
|
004A701F
| call debug_test2.vmp.
4A5A25
|
004A5A25
| jmp debug_test2.vmp.
4A6BC5
|
004A6BC5
| mov dword ptr ss:[esp
+
34
],edx | [esp
+
34
]:___use_sse2_mathfcns
+
2D1
004A6BC9
| call debug_test2.vmp.
4A5C3D
|
004A5C3D
| call debug_test2.vmp.
4A6681
|
004A6681
| mov dword ptr ss:[esp
+
38
],edx | [esp
+
38
]:___use_sse2_mathfcns
+
2D1
004A6685
| push dword ptr ss:[esp
+
8
] | [esp
+
8
]:___use_sse2_mathfcns
+
42C0
004A6689
| mov dword ptr ss:[esp
+
38
],ecx | [esp
+
38
]:___use_sse2_mathfcns
+
2D1
, ecx:___use_sse2_mathfcns
+
2D1
004A668D
| push E7FE4EC3 |
004A6692
| mov byte ptr ss:[esp],dh |
004A6695
| lea esp,dword ptr ss:[esp
+
3C
] |
004A6699
| jmp debug_test2.vmp.
4A632E
|
004A632E
| btr si,
6
|
004A6333
| push edi |
004A6334
| push
20AD5139
|
004A6339
| xchg esi,ecx | esi:_mainCRTStartup, ecx:___use_sse2_mathfcns
+
2D1
004A633B
| call debug_test2.vmp.
4A6129
|
004A6129
| mov dword ptr ss:[esp
+
4
],ebx |
004A612D
| movsx esi,cl | esi:___use_sse2_mathfcns
+
2D1
004A6130
| pop ecx | ecx:
"U嬱Q梓\x0E"
004A6131
| btc di,cx |
004A6135
| pushad |
004A6136
| mov dword ptr ss:[esp
+
1C
],
0
|
004A613E
| stc |
004A613F
| jmp debug_test2.vmp.
4A70CF
/
/
入口
00401080
| jmp debug_test2.vmp.
4A77D2
| Debug_test2.cpp:
5
004A77D2
| push
4A781400
|
004A77D7
| call debug_test2.vmp.
4A6B9F
|
004A6B9F
| jmp debug_test2.vmp.
4A703A
|
004A703A
| push esi | esi:_mainCRTStartup
004A703B
| jmp debug_test2.vmp.
4A52E8
|
004A52E8
| pushfd |
004A52E9
| push D3AC6D6A |
004A52EE
| mov byte ptr ss:[esp
+
4
],
8F
|
004A52F3
| pushfd |
004A52F4
| pop dword ptr ss:[esp
+
4
] | [esp
+
4
]:___use_sse2_mathfcns
+
4A78
004A52F8
| jmp debug_test2.vmp.
4A64C1
|
004A64C1
| call debug_test2.vmp.
4A5FE9
|
004A5FE9
| pushad |
004A5FEA
| mov dword ptr ss:[esp
+
24
],ebp | [esp
+
24
]:_mainCRTStartup
004A5FEE
| push esp |
004A5FEF
| pushfd |
004A5FF0
| push
72B57CE7
|
004A5FF5
| pushfd |
004A5FF6
| mov dword ptr ss:[esp
+
30
],eax | eax:___use_sse2_mathfcns
+
2D1
004A5FFA
| mov byte ptr ss:[esp],cl |
004A5FFD
| call debug_test2.vmp.
4A701F
|
004A701F
| call debug_test2.vmp.
4A5A25
|
004A5A25
| jmp debug_test2.vmp.
4A6BC5
|
004A6BC5
| mov dword ptr ss:[esp
+
34
],edx | [esp
+
34
]:___use_sse2_mathfcns
+
2D1
004A6BC9
| call debug_test2.vmp.
4A5C3D
|
004A5C3D
| call debug_test2.vmp.
4A6681
|
004A6681
| mov dword ptr ss:[esp
+
38
],edx | [esp
+
38
]:___use_sse2_mathfcns
+
2D1
004A6685
| push dword ptr ss:[esp
+
8
] | [esp
+
8
]:___use_sse2_mathfcns
+
42C0
004A6689
| mov dword ptr ss:[esp
+
38
],ecx | [esp
+
38
]:___use_sse2_mathfcns
+
2D1
, ecx:___use_sse2_mathfcns
+
2D1
004A668D
| push E7FE4EC3 |
004A6692
| mov byte ptr ss:[esp],dh |
004A6695
| lea esp,dword ptr ss:[esp
+
3C
] |
004A6699
| jmp debug_test2.vmp.
4A632E
|
004A632E
| btr si,
6
|
004A6333
| push edi |
004A6334
| push
20AD5139
|
004A6339
| xchg esi,ecx | esi:_mainCRTStartup, ecx:___use_sse2_mathfcns
+
2D1
004A633B
| call debug_test2.vmp.
4A6129
|
004A6129
| mov dword ptr ss:[esp
+
4
],ebx |
004A612D
| movsx esi,cl | esi:___use_sse2_mathfcns
+
2D1
004A6130
| pop ecx | ecx:
"U嬱Q梓\x0E"
004A6131
| btc di,cx |
004A6135
| pushad |
004A6136
| mov dword ptr ss:[esp
+
1C
],
0
|
004A613E
| stc |
004A613F
| jmp debug_test2.vmp.
4A70CF
004A70CF
| mov esi,dword ptr ss:[esp
+
48
] |
004A70D3
| btr bp,sp |
004A70D7
| jmp debug_test2.vmp.
4A53AF
|
004A53AF
| movzx bp,bl |
004A53B3
| btc bp,si |
004A53B7
| rol esi,
18
|
004A53BA
| push
124E6496
|
004A53BF
| inc esi |
004A53C0
| jmp debug_test2.vmp.
4A6C85
|
004A70CF
| mov esi,dword ptr ss:[esp
+
48
] |
004A70D3
| btr bp,sp |
004A70D7
| jmp debug_test2.vmp.
4A53AF
|
004A53AF
| movzx bp,bl |
004A53B3
| btc bp,si |
004A53B7
| rol esi,
18
|
004A53BA
| push
124E6496
|
004A53BF
| inc esi |
004A53C0
| jmp debug_test2.vmp.
4A6C85
|
004A53F7
| rol ah,
6
|
004A53FA
| sbb edx,esp |
004A53FC
| mov eax,dword ptr ss:[ebp] |
004A53FF
| jmp debug_test2.vmp.
4A5BC4
004A5BC4
| cmc |
004A5BC5
| mov edx,dword ptr ss:[ebp
+
4
] |
004A5BC8
| push
25584F9E
|
004A5BCD
| pushad |
004A5BCE
| clc |
004A5BCF
| bt cx,C |
004A5BD4
|
not
eax |
004A5BD6
| pushad |
004A5BD7
| bt cx,bx |
004A5BDB
| call debug_test2.vmp.
4A5D63
|
004A5D63
| cmc |
004A5D64
|
not
edx |
004A5D66
|
cmp
edi,F7A6A772 |
004A5D6C
| stc |
004A5D6D
| stc |
004A5D6E
| stc |
004A5D6F
|
and
eax,edx |
004A5D71
| jmp debug_test2.vmp.
4A5A3F
|
004A5A3F
| jmp debug_test2.vmp.
4A6E72
|
004A6E73
| pushfd |
004A6E74
| mov dword ptr ss:[ebp
+
4
],eax |
004A6E77
| jmp debug_test2.vmp.
4A564D
|
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
/
/
化简之后
004A53FC
| mov eax,dword ptr ss:[ebp] |
004A5BC5
| mov edx,dword ptr ss:[ebp
+
4
] |
004A5BD4
|
not
eax |
004A5D64
|
not
edx |
004A5D6F
|
and
eax,edx |
004A6E74
| mov dword ptr ss:[ebp
+
4
],eax |
004A6E77
| jmp debug_test2.vmp.
4A564D
|
004A53F7
| rol ah,
6
|
004A53FA
| sbb edx,esp |
004A53FC
| mov eax,dword ptr ss:[ebp] |
004A53FF
| jmp debug_test2.vmp.
4A5BC4
004A5BC4
| cmc |
004A5BC5
| mov edx,dword ptr ss:[ebp
+
4
] |
004A5BC8
| push
25584F9E
|
004A5BCD
| pushad |
004A5BCE
| clc |
004A5BCF
| bt cx,C |
004A5BD4
|
not
eax |
004A5BD6
| pushad |
004A5BD7
| bt cx,bx |
004A5BDB
| call debug_test2.vmp.
4A5D63
|
004A5D63
| cmc |
004A5D64
|
not
edx |
004A5D66
|
cmp
edi,F7A6A772 |
004A5D6C
| stc |
004A5D6D
| stc |
004A5D6E
| stc |
004A5D6F
|
and
eax,edx |
004A5D71
| jmp debug_test2.vmp.
4A5A3F
|
004A5A3F
| jmp debug_test2.vmp.
4A6E72
|
004A6E73
| pushfd |
004A6E74
| mov dword ptr ss:[ebp
+
4
],eax |
004A6E77
| jmp debug_test2.vmp.
4A564D
|
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
/
/
化简之后
004A53FC
| mov eax,dword ptr ss:[ebp] |
004A5BC5
| mov edx,dword ptr ss:[ebp
+
4
] |
004A5BD4
|
not
eax |
004A5D64
|
not
edx |
004A5D6F
|
and
eax,edx |
004A6E74
| mov dword ptr ss:[ebp
+
4
],eax |
004A6E77
| jmp debug_test2.vmp.
4A564D
|
IsDebuggerPresent
CheckRemoteDebuggerPresent
GetThreadContext
CloseHandle
NtQueryInformationProcess
NtSetInformationThread
/
/
关于这些函数介绍,看雪里有很多大神发了反调试相关的帖子,搜一下就能找到。
IsDebuggerPresent
CheckRemoteDebuggerPresent
GetThreadContext
CloseHandle
NtQueryInformationProcess
NtSetInformationThread
/
/
关于这些函数介绍,看雪里有很多大神发了反调试相关的帖子,搜一下就能找到。
int
g_num
=
0
;
void __declspec(naked) test_vmp(
int
a,
int
b)
{
__asm {
mov eax,[esp
+
4
]
/
/
[esp
+
4
]
=
=
a
mov ebx,[esp
+
8
]
/
/
[esp
+
8
]
=
=
b
xor eax, ebx
mov g_num,eax
ret
}
}
void test2()
{
test_vmp(
0x10
,
0x21
);
printf(
"%X\n"
, g_num);
}
int
main()
{
test2();
system(
"pause"
);
return
0
;
}
int
g_num
=
0
;
void __declspec(naked) test_vmp(
int
a,
int
b)
{
__asm {
mov eax,[esp
+
4
]
/
/
[esp
+
4
]
=
=
a
mov ebx,[esp
+
8
]
/
/
[esp
+
8
]
=
=
b
xor eax, ebx
mov g_num,eax
ret
}
}
void test2()
{
test_vmp(
0x10
,
0x21
);
printf(
"%X\n"
, g_num);
}
int
main()
{
test2();
system(
"pause"
);
return
0
;
}
004A6AFF
|
66
:
0FB6C3
| movzx ax,bl |
004A6B03
| F6D0 |
not
al |
004A6B05
|
66
:
0FB6C3
| movzx ax,bl |
004A6B09
|
66
:
0FBEC2
| movsx ax,dl |
004A6B0D
|
8B45
00
| mov eax,dword ptr ss:[ebp] |
004A6B10
|
60
| pushad |
004A6B11
| E9
41140000
| jmp debug_test2.vmp.
4A7F57
|
004A6A55
|
36
:
8B00
| mov eax,dword ptr ss:[eax] |
004A6A58
|
55
| push ebp |
004A6A59
| E9
8A000000
| jmp debug_test2.vmp.
4A6AE8
|
004A6AE8
|
882C24
| mov byte ptr ss:[esp],ch |
004A6AEB
| FF3424 | push dword ptr ss:[esp] |
004A6AEE
|
8945
00
| mov dword ptr ss:[ebp],eax |
004A6AF1
| FF3424 | push dword ptr ss:[esp] |
004A6AF4
|
9C
| pushfd |
004A6AF5
|
9C
| pushfd |
004A6AF6
|
8D6424
38
| lea esp,dword ptr ss:[esp
+
38
] |
004A6AFA
| E9
83150000
| jmp debug_test2.vmp.
4A8082
|
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
可以化简为:
004A6B0D
|
8B45
00
| mov eax,dword ptr ss:[ebp] |
004A6A55
|
36
:
8B00
| mov eax,dword ptr ss:[eax] |
004A6AEE
|
8945
00
| mov dword ptr ss:[ebp],eax |
可以把上面的handler块命名为Handler_Reg_Mem
004A6AFF
|
66
:
0FB6C3
| movzx ax,bl |
004A6B03
| F6D0 |
not
al |
004A6B05
|
66
:
0FB6C3
| movzx ax,bl |
004A6B09
|
66
:
0FBEC2
| movsx ax,dl |
004A6B0D
|
8B45
00
| mov eax,dword ptr ss:[ebp] |
004A6B10
|
60
| pushad |
004A6B11
| E9
41140000
| jmp debug_test2.vmp.
4A7F57
|
004A6A55
|
36
:
8B00
| mov eax,dword ptr ss:[eax] |
004A6A58
|
55
| push ebp |
004A6A59
| E9
8A000000
| jmp debug_test2.vmp.
4A6AE8
|
004A6AE8
|
882C24
| mov byte ptr ss:[esp],ch |
004A6AEB
| FF3424 | push dword ptr ss:[esp] |
004A6AEE
|
8945
00
| mov dword ptr ss:[ebp],eax |
004A6AF1
| FF3424 | push dword ptr ss:[esp] |
004A6AF4
|
9C
| pushfd |
004A6AF5
|
9C
| pushfd |
004A6AF6
|
8D6424
38
| lea esp,dword ptr ss:[esp
+
38
] |
004A6AFA
| E9
83150000
| jmp debug_test2.vmp.
4A8082
|
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
可以化简为:
004A6B0D
|
8B45
00
| mov eax,dword ptr ss:[ebp] |
004A6A55
|
36
:
8B00
| mov eax,dword ptr ss:[eax] |
004A6AEE
|
8945
00
| mov dword ptr ss:[ebp],eax |
可以把上面的handler块命名为Handler_Reg_Mem
004A6113
| push ebp |
004A6114
| lahf |
004A6115
| pushad |
004A6116
| mov eax,dword ptr ss:[ebp] |
004A6119
| rcr dh,
6
|
004A611C
| bts dx,
7
|
004A6121
| bts dx,
1
|
004A6126
| mov edx,dword ptr ss:[ebp
+
4
] |
004A6129
| stc |
004A612A
|
not
eax |
004A612C
| pushfd |
004A612D
| push dword ptr ss:[esp] |
004A6130
|
not
edx |
004A6132
| jmp debug_test2.vmp.
4A66E3
|
004A6137
|
not
esi |
004A6139
| mov byte ptr ss:[esp],dh |
004A613C
| pushfd |
004A613D
| push C19B900A |
004A6142
| pushfd |
004A6143
| lea esp,dword ptr ss:[esp
+
4C
] |
004A6147
| jmp debug_test2.vmp.
4A60CA
|
004A66E3
| clc |
004A66E4
|
and
eax,edx |
004A66E6
| push edi |
004A66E7
| push esi |
004A66E8
| jmp debug_test2.vmp.
4A61EF
|
004A61EF
| mov dword ptr ss:[ebp
+
4
],eax |
004A61F2
| mov byte ptr ss:[esp
+
C],
31
|
31
:
'1'
004A61F7
| mov byte ptr ss:[esp
+
C],
65
|
65
:
'e'
004A61FC
| push A8B985C4 |
004A6201
| mov word ptr ss:[esp
+
C],sp |
004A6206
| pushfd |
004A6207
| pop dword ptr ss:[esp
+
34
] |
004A620B
| mov byte ptr ss:[esp
+
8
],ah |
004A620F
| call debug_test2.vmp.
4A78E2
|
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
/
/
可以化简为:
004A6116
| mov eax,dword ptr ss:[ebp] |
004A6126
| mov edx,dword ptr ss:[ebp
+
4
] |
004A612A
|
not
eax |
004A6130
|
not
edx |
004A66E4
|
and
eax,edx |
004A61EF
| mov dword ptr ss:[ebp
+
4
],eax |
004A6113
| push ebp |
004A6114
| lahf |
004A6115
| pushad |
004A6116
| mov eax,dword ptr ss:[ebp] |
004A6119
| rcr dh,
6
|
004A611C
| bts dx,
7
|
004A6121
| bts dx,
1
|
004A6126
| mov edx,dword ptr ss:[ebp
+
4
] |
004A6129
| stc |
004A612A
|
not
eax |
004A612C
| pushfd |
004A612D
| push dword ptr ss:[esp] |
004A6130
|
not
edx |
004A6132
| jmp debug_test2.vmp.
4A66E3
|
004A6137
|
not
esi |
004A6139
| mov byte ptr ss:[esp],dh |
004A613C
| pushfd |
004A613D
| push C19B900A |
004A6142
| pushfd |
004A6143
| lea esp,dword ptr ss:[esp
+
4C
] |
004A6147
| jmp debug_test2.vmp.
4A60CA
|
004A66E3
| clc |
004A66E4
|
and
eax,edx |
004A66E6
| push edi |
004A66E7
| push esi |
004A66E8
| jmp debug_test2.vmp.
4A61EF
|
004A61EF
| mov dword ptr ss:[ebp
+
4
],eax |
004A61F2
| mov byte ptr ss:[esp
+
C],
31
|
31
:
'1'
004A61F7
| mov byte ptr ss:[esp
+
C],
65
|
65
:
'e'
004A61FC
| push A8B985C4 |
004A6201
| mov word ptr ss:[esp
+
C],sp |
004A6206
| pushfd |
004A6207
| pop dword ptr ss:[esp
+
34
] |
004A620B
| mov byte ptr ss:[esp
+
8
],ah |
004A620F
| call debug_test2.vmp.
4A78E2
|
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
/
/
可以化简为:
004A6116
| mov eax,dword ptr ss:[ebp] |
004A6126
| mov edx,dword ptr ss:[ebp
+
4
] |
004A612A
|
not
eax |
004A6130
|
not
edx |
004A66E4
|
and
eax,edx |
004A61EF
| mov dword ptr ss:[ebp
+
4
],eax |
004A69C7
|
04
08
| add al,
8
|
004A69C9
|
60
| pushad |
004A69CA
|
66
:
05
7B36
| add ax,
367B
|
004A69CE
|
8B45
00
| mov eax,dword ptr ss:[ebp] |
004A69D1
|
20D6
|
and
dh,dl |
004A69D3
|
66
:F7D2 |
not
dx |
004A69D6
|
08C2
|
or
dl,al |
004A69D8
|
8B55
04
| mov edx,dword ptr ss:[ebp
+
4
] |
004A69DB
|
68
37EDD2A5
| push A5D2ED37 |
004A69E0
|
66
:
81FF
7052
|
cmp
di,
5270
|
004A69E5
|
84CB
| test bl,cl |
004A69E7
| F8 | clc |
004A69E8
|
83C5
08
| add ebp,
8
|
004A69EB
| FF7424
04
| push dword ptr ss:[esp
+
4
] |
004A69EF
|
66
:
896424
14
| mov word ptr ss:[esp
+
14
],sp |
004A69F4
| E9
94F4FFFF
| jmp debug_test2.vmp.
4A5E8D
|
004A5E8D
|
8910
| mov dword ptr ds:[eax],edx |
004A5E8F
|
9C
| pushfd |
004A5E90
|
66
:
895424
04
| mov word ptr ss:[esp
+
4
],dx |
004A5E95
|
8D6424
2C
| lea esp,dword ptr ss:[esp
+
2C
] |
004A5E99
| E9 E4210000 | jmp debug_test2.vmp.
4A8082
|
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
可以化简为:
004A69CE
|
8B45
00
| mov eax,dword ptr ss:[ebp] |
004A69D8
|
8B55
04
| mov edx,dword ptr ss:[ebp
+
4
] |
004A69E8
|
83C5
08
| add ebp,
8
|
004A5E8D
|
8910
| mov dword ptr ds:[eax],edx |
可以把上面的handler块命名为Handler_Mem_Reg
004A69C7
|
04
08
| add al,
8
|
004A69C9
|
60
| pushad |
004A69CA
|
66
:
05
7B36
| add ax,
367B
|
004A69CE
|
8B45
00
| mov eax,dword ptr ss:[ebp] |
004A69D1
|
20D6
|
and
dh,dl |
004A69D3
|
66
:F7D2 |
not
dx |
004A69D6
|
08C2
|
or
dl,al |
004A69D8
|
8B55
04
| mov edx,dword ptr ss:[ebp
+
4
] |
004A69DB
|
68
37EDD2A5
| push A5D2ED37 |
004A69E0
|
66
:
81FF
7052
|
cmp
di,
5270
|
004A69E5
|
84CB
| test bl,cl |
004A69E7
| F8 | clc |
004A69E8
|
83C5
08
| add ebp,
8
|
004A69EB
| FF7424
04
| push dword ptr ss:[esp
+
4
] |
004A69EF
|
66
:
896424
14
| mov word ptr ss:[esp
+
14
],sp |
004A69F4
| E9
94F4FFFF
| jmp debug_test2.vmp.
4A5E8D
|
004A5E8D
|
8910
| mov dword ptr ds:[eax],edx |
004A5E8F
|
9C
| pushfd |
004A5E90
|
66
:
895424
04
| mov word ptr ss:[esp
+
4
],dx |
004A5E95
|
8D6424
2C
| lea esp,dword ptr ss:[esp
+
2C
] |
004A5E99
| E9 E4210000 | jmp debug_test2.vmp.
4A8082
|
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
可以化简为:
004A69CE
|
8B45
00
| mov eax,dword ptr ss:[ebp] |
004A69D8
|
8B55
04
| mov edx,dword ptr ss:[ebp
+
4
] |
004A69E8
|
83C5
08
| add ebp,
8
|
004A5E8D
|
8910
| mov dword ptr ds:[eax],edx |
可以把上面的handler块命名为Handler_Mem_Reg
using namespace std;
class
AllocMemory
{
vector<char
*
>p;
public:
virtual ~AllocMemory()
{
for
(
int
i
=
0
; i < p.size(); i
+
+
)
{
if
(p[i]
=
=
0
)
{
continue
;
}
free(p[i]);
p[i]
=
0
;
}
p.clear();
}
public:
template<typename T>
T auto_malloc( ULONG_PTR MAXSIZE)
{
T tmp
=
(T)malloc(MAXSIZE);
memset((char
*
)tmp,
0
, MAXSIZE);
p.push_back((char
*
)tmp);
return
tmp;
}
};
using namespace std;
class
AllocMemory
{
vector<char
*
>p;
public:
virtual ~AllocMemory()
{
for
(
int
i
=
0
; i < p.size(); i
+
+
)
{
if
(p[i]
=
=
0
)
{
continue
;
}
free(p[i]);
p[i]
=
0
;
}
p.clear();
}
public:
template<typename T>
T auto_malloc( ULONG_PTR MAXSIZE)
{
T tmp
=
(T)malloc(MAXSIZE);
memset((char
*
)tmp,
0
, MAXSIZE);
p.push_back((char
*
)tmp);
return
tmp;
}
};
void __declspec(naked) test_vmp(
int
a,
int
b)
{
__asm {
mov eax, [esp
+
4
]
mov eax, [esp
+
4
]
mov eax, [esp
+
4
]
mov eax,[esp
+
4
]
/
/
[esp
+
4
]
=
=
a
mov ebx,[esp
+
8
]
/
/
[esp
+
8
]
=
=
b
xor eax, ebx
mov g_num,eax
ret
}
}
int
main()
{
test_vmp(
1
,
2
);
system(
"pause"
);
return
;
}
void __declspec(naked) test_vmp(
int
a,
int
b)
{
__asm {
mov eax, [esp
+
4
]
mov eax, [esp
+
4
]
mov eax, [esp
+
4
]
mov eax,[esp
+
4
]
/
/
[esp
+
4
]
=
=
a
mov ebx,[esp
+
8
]
/
/
[esp
+
8
]
=
=
b
xor eax, ebx
mov g_num,eax
ret
}
}
int
main()
{
test_vmp(
1
,
2
);
system(
"pause"
);
return
;
}
/
/
解析要保护的指令,翻译为中间表示
void MiddleRepresent(DISASM disAsm)
{
/
*
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
*
/
/
*
1
、是否有操作
3
*
/
/
*
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
*
/
if
(NO_ARGUMENT !
=
disAsm.Argument3.ArgType)
{
switch (disAsm.Argument3.ArgType &
0xF0000000
)
{
case REGISTER_TYPE:
/
/
寄存器
break
;
case MEMORY_TYPE:
/
/
内存
break
;
case CONSTANT_TYPE:
/
/
常数
break
;
default:
break
;
}
}
/
*
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
*
/
/
*
2
、是否有操作
2
*
/
/
*
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
*
/
if
(NO_ARGUMENT !
=
disAsm.Argument2.ArgType)
{
switch (disAsm.Argument2.ArgType &
0xF0000000
)
{
case REGISTER_TYPE:
/
/
寄存器
break
;
case MEMORY_TYPE:
/
/
内存
break
;
case CONSTANT_TYPE:
/
/
常数
break
;
default:
break
;
}
}
/
*
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
*
/
/
*
3
、是否有操作
1
*
/
/
*
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
*
/
if
(NO_ARGUMENT !
=
disAsm.Argument1.ArgType)
{
switch (disAsm.Argument1.ArgType &
0xF0000000
)
{
case REGISTER_TYPE:
/
/
寄存器
break
;
case MEMORY_TYPE:
/
/
内存
break
;
case CONSTANT_TYPE:
/
/
常数
break
;
default:
break
;
}
}
/
*
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
*
/
/
*
4
、处理普通handler
*
/
/
*
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
*
/
/
/
省略...
/
*
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
*
/
/
*
5
、判断是否有辅助handler
*
/
/
*
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
*
/
if
(
0x10000000
!
=
disAsm.Argument1.ArgType ||
0x10000000
!
=
disAsm.Argument2.ArgType ||
0x10000000
!
=
disAsm.Argument3.ArgType
)
{
if
(NO_ARGUMENT !
=
disAsm.Argument1.ArgType)
{
switch (disAsm.Argument1.ArgType &
0xF0000000
)
{
case REGISTER_TYPE:
/
/
寄存器
break
;
case MEMORY_TYPE:
/
/
内存
break
;
case CONSTANT_TYPE:
/
/
常数
break
;
default:
break
;
}
}
}
}
/
/
解析要保护的指令,翻译为中间表示
void MiddleRepresent(DISASM disAsm)
{
/
*
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
*
/
/
*
1
、是否有操作
3
*
/
/
*
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
*
/
if
(NO_ARGUMENT !
=
disAsm.Argument3.ArgType)
{
switch (disAsm.Argument3.ArgType &
0xF0000000
)
{
case REGISTER_TYPE:
/
/
寄存器
break
;
case MEMORY_TYPE:
/
/
内存
break
;
case CONSTANT_TYPE:
/
/
常数
break
;
default:
break
;
}
}
/
*
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
*
/
/
*
2
、是否有操作
2
*
/
/
*
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
*
/
if
(NO_ARGUMENT !
=
disAsm.Argument2.ArgType)
{
switch (disAsm.Argument2.ArgType &
0xF0000000
)
{
case REGISTER_TYPE:
/
/
寄存器
break
;
case MEMORY_TYPE:
/
/
内存
break
;
case CONSTANT_TYPE:
/
/
常数
break
;
default:
break
;
}
}
/
*
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
*
/
/
*
3
、是否有操作
1
*
/
/
*
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
*
/
if
(NO_ARGUMENT !
=
disAsm.Argument1.ArgType)
{
switch (disAsm.Argument1.ArgType &
0xF0000000
)
{
case REGISTER_TYPE:
/
/
寄存器
break
;
case MEMORY_TYPE:
/
/
内存
break
;
case CONSTANT_TYPE:
/
/
常数
break
;
default:
break
;
}
}
/
*
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
*
/
/
*
4
、处理普通handler
*
/
/
*
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
*
/
/
/
省略...
/
*
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
*
/
/
*
5
、判断是否有辅助handler
*
/
/
*
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
*
/
if
(
0x10000000
!
=
disAsm.Argument1.ArgType ||
0x10000000
!
=
disAsm.Argument2.ArgType ||
0x10000000
!
=
disAsm.Argument3.ArgType
)
{
if
(NO_ARGUMENT !
=
disAsm.Argument1.ArgType)
{
switch (disAsm.Argument1.ArgType &
0xF0000000
)
{
case REGISTER_TYPE:
/
/
寄存器
break
;
case MEMORY_TYPE:
/
/
内存
break
;
case CONSTANT_TYPE:
/
/
常数
break
;
default:
break
;
}
}
}
}
vPushReg VR_ecx
/
/
操作
2
vPushReg VR_eax
/
/
操作
1
vMOV
/
/
普通handler
vPopReg VR_eax
/
/
辅助handler
vPushReg VR_ecx
/
/
操作
2
vPushReg VR_eax
/
/
操作
1
vMOV
/
/
普通handler
vPopReg VR_eax
/
/
辅助handler
vPushReg VR_ecx
/
/
操作
2
vPushReg VR_eax
/
/
操作
1
vMOV
/
/
普通handler
vPopReg VR_eax
/
/
辅助handler
把VR_ecx、VR_eax、VR_eax分离出来保存在一个数据表的结构体中。
翻译就可以这样表示了:
vPushReg
vPushReg
vMOV
vPopReg
vPushReg VR_ecx
/
/
操作
2
vPushReg VR_eax
/
/
操作
1
vMOV
/
/
普通handler
vPopReg VR_eax
/
/
辅助handler
把VR_ecx、VR_eax、VR_eax分离出来保存在一个数据表的结构体中。
翻译就可以这样表示了:
vPushReg
vPushReg
vMOV
vPopReg
vPushReg
/
/
eax
vPushImm4
/
/
4
vPushReg4
/
/
ecx
vMUL_MEM
/
/
*
vPushReg4
/
/
eax
vAdd4
/
/
+
vPushImm4
/
/
0x401000
vAdd
/
/
+
vWriteMemDs4
vPushReg
/
/
eax
vPushImm4
/
/
4
vPushReg4
/
/
ecx
vMUL_MEM
/
/
*
vPushReg4
/
/
eax
vAdd4
/
/
+
vPushImm4
/
/
0x401000
vAdd
/
/
+
vWriteMemDs4
vPushImm4
/
/
0xFFFFFFF8
vPushReg4
/
/
ebp
vAdd4
负
8
会被BeaEngine引擎解析为
0xFFFFFFF8
,ebp
-
0x8
与
0xFFFFFFF8
+
ebp是等价的
vPushImm4
/
/
0xFFFFFFF8
vPushReg4
/
/
ebp
vAdd4
负
8
会被BeaEngine引擎解析为
0xFFFFFFF8
,ebp
-
0x8
与
0xFFFFFFF8
+
ebp是等价的
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)
最后于 2021-5-7 18:28
被舒默哦编辑
,原因: 更正错误
上传的附件: