本文主要是通过分析VMProtect 1.81 Demo版加密后的程序,讲述VMP的基本结构,并尝试分析虚拟代码的功能以及虚拟代码还原。
虚拟机保护技术是将程序的可执行代码转化为自定义的中间操作码(一字节或多字节),用以保护源程序不被逆向和篡改,这些中间操作码通过虚拟机解释执行,实现程序原来的功能。在这种情况下,如果要逆向程序,就需要对整个虚拟机结构进行逆向,理解程序功能,还需要结合操作码进行分析,整个程序逆向工程将会十分繁琐。以下是一个一般虚拟机结构:

虚拟机解释执行流程如下:
与虚拟机相关的数据结构如下:
本案例的样本来自于如何分析虚拟机系列(1):新手篇VMProtect 1.81 Demo - 吾爱破解 - 52pojie.cn。样本的汇编代码如下,就是一个简单的加减同一个常量。
经过VMP保护后,变成如下所示
这里有个典型的VMP入口特征:push call。push压入栈的数据是虚拟指令操作码表(VM Opcode Table)所在地址,然后通过call sub_40472C进入VM Entry。byte_404781 如下
首先一个很典型的特征就是VMP在创建虚拟机环境时,会将真实环境中寄存器的值入栈保存。
以上两条指令把要被操作的数据压入栈,这是基于栈的虚拟机的一个特点:数据的操作需要在栈上进行。那么可以确定这里应该是虚拟栈了。
初始化esi,通过画堆栈图分析,可知 esi 的值为 byte_404781,也就是虚拟指令操作码表(VM Opcode Table)的基址。
初始化 ebp 的值为 esp,指向虚拟栈的栈顶,然后创建一个新的栈帧,用于当作虚拟寄存器使用,edi指向虚拟寄存器的基址。
之后是获取虚拟栈栈顶数据,即虚拟指令操作码的偏移地址,然后加上虚拟操作码表的基址,此时 esi 指向第一个将要被执行的虚拟指令操作码。
根据虚拟指令操作码跳转到对应的VM Handler来执行相应功能。jpt_404757 是一个函数地址表,存放的是VM Handlers的偏移。

虚拟栈栈顶的两个单字节数相加,结果存入后者所在位置,标志寄存器入真实栈,然后将真实栈顶元素(标志寄存器的值)存入到虚拟栈顶处。
参与加法运算的是[源ebp+2] 、[源ebp]的两个字节相加,而不是[源ebp+1] 、[源ebp]的两个字节相加,可能的原因是虚拟栈按两字节对齐。
虚拟栈栈顶两个双字节数相加。此时虚拟栈提升两字节。虚拟栈顶的前四字节为运算产生的标志位,后两字节为运算产生的值。
虚拟栈栈顶两个四字节数相加。此时虚拟栈顶的位置不变。
从虚拟栈栈顶取出两个单字节数据,进行逻辑右移运算。将结果零扩展至双字节(右移结果存储在al中,但入栈的却是ax)。此时虚拟栈提升两字节。
从虚拟栈中依次取出双字节数据、单字节数据(作为位移值),进行逻辑右移运算。此时虚拟栈提升两字节。
从虚拟栈栈顶依次取四字节数据、一字节数据(作为位移值),进行逻辑右移运算。此时虚拟栈提升两字节。
从虚拟栈栈顶依次取两个四字节数据、一个一字节数据,进行双精度右移,这里仅将高位eax放入栈中。此时虚拟栈缩小两字节。
从虚拟栈中依次取出两个单字节数据,进行逻辑左移运算。将结果零扩展为双字节(结果存储在al,但入栈的却是ax)。此时虚拟栈提升两字节。
从虚拟栈的栈顶中依次取出双字节数据、单字节数据(位移值),进行逻辑左移。此时虚拟栈提升两字节。
从虚拟栈的栈顶中依次取出四字节数据、单字节数据(位移值),进行逻辑左移。此时虚拟栈提升两字节。
从虚拟栈栈顶依次取两个四字节数据、一个一字节数据,进行双精度左移。此时虚拟栈缩小两字节。
从虚拟栈中依次取出两个双字节数据,实际上是低位一字节先进行非运算,然后再进行与运算。此时虚拟栈提升两字节。
对虚拟栈栈顶的四字节取反,然后分成两个双字节数进行与运算。此时虚拟栈提升两字节。
从虚拟栈栈顶依次取两个四字节数据,先进行非运算,然后与运算。此时虚拟栈顶位置不变。
取虚拟指令中的操作数(单字节),零扩展至单字,然后入栈。此时虚拟栈提升两字节。
取虚拟指令中操作数(两字节),将其入栈。此时虚拟栈提升两字节。
取虚拟指令中操作数(四字节),将其入栈。此时虚拟栈提升四字节。
取虚拟指令中操作数(单字节),符号扩展成双字,然后入栈。此时虚拟栈提升四字节。
取虚拟指令中的操作数(两字节),符号扩展至双字,然后入栈。此时虚拟栈提升四字节。
从虚拟指令中取出操作数(单字节),作为虚拟寄存器的索引值,然后取出对应的虚拟寄存器中的值(单字节),将其入栈。此时虚拟栈提升两字节。
sub esi, 0FFFFFFFFh等价于 add esi, 1
从虚拟指令中取出操作数(单字节),作为虚拟寄存器的索引值,取出对应虚拟寄存器的数据(双字节),将其入栈。此时虚拟栈提升两字节。
虚拟指令的操作码(单字节)与常量0x3C进行与运算,作为虚拟寄存器的索引值,取出对应虚拟寄存器中的值(四字节),将其入栈。此时虚拟栈提升四字节。
从虚拟指令中取出一字节操作数作为虚拟寄存器索引,取虚拟栈栈顶的两字节数据,将其存储到对应虚拟寄存器中,实际存储低位(一字节)。此时虚拟栈缩小两字节。
从虚拟指令中取出一字节操作数作为虚拟寄存器索引,然后取虚拟栈栈顶的两字节数据,将其存入对应虚拟寄存器中。此时虚拟栈缩小两字节。
虚拟指令的操作码(一字节)与0x3C进行与运算,取出虚拟栈栈顶的四字节数据,将其存放到指定的虚拟寄存器中。此时虚拟栈缩小四字节。
虚拟栈的栈顶指针入栈(低位两字节)。此时虚拟栈提升两字节。
虚拟栈的栈顶指针入栈(四字节)。此时虚拟栈提升四字节。
虚拟栈栈顶的两字节数据加载到虚拟栈指针寄存器中。此时虚拟栈顶变化未知。
虚拟栈栈顶的四字节数据加载到虚拟栈指针寄存器中。此时虚拟栈顶变化未知。
从虚拟栈中依次取四字节数据(内存地址)、一字节数据(待存储的值),将一字节数据存储到四字节数据所指向的内存中。此时虚拟栈缩小六字节。
另一种使用堆栈段寄存器 ss 的情况:
从虚拟栈中依次取四字节数据(内存地址)、两字节数据(待存储的值),将两字节数据存储到四字节数据所指向的内存中。此时虚拟栈缩小六字节。
另一种使用堆栈段寄存器 ss 的情况:
从虚拟栈栈顶依次取两个四字节数据,前者作为内存地址,后者作为待存储的值,然后将值存储到对应内存中。此时虚拟栈缩小八字节。
另一种使用堆栈段寄存器 ss 的情况:
从虚拟栈顶中取出四字节数据作为内存地址,从对应地址中取出单字节数据,零扩展至单字后将其入栈。此时虚拟栈缩小两字节。
另一种使用堆栈段寄存器 ss 的情况:
从虚拟栈中依次取四字节数据作为内存地址,取出对应内存的两字节数据,将其压入栈。此时虚拟栈缩小两字节。
另一种使用堆栈段寄存器 ss 的情况:
取虚拟栈栈顶的四字节数据作为内存地址,然后取对应内存地址的四字节数据,将其压入栈。此时虚拟栈顶位置不变。
另一种使用堆栈段寄存器 ss 的情况:
按照vm_entry入栈顺序进行逆序出栈,还原本机环境。
先检查栈空间是否充足,如果充足的话,跳转到vm_dispatcher,否则进行栈空间调整然后再跳转到vm_dispatcher。
这里借助OllyDBG的Trace功能,跟踪程序执行的代码流,使用方法如下:
通过VM Handler的分析,已经知晓了这些指令类型,通过地址与一级虚拟指令的映射关系,可以初步根据代码流将虚拟代码还原成一级虚拟指令代码流,但是这些一级虚拟指令在不同环境下,操作数是不同的,因此还需要根据OD Trace到的寄存器和内存再做进一步优化。我这里偷点懒,使用的方法仅针对该样本,并不是一个通用的方法:找到一级虚拟指令地址后,选取该Handler中合适的指令,从记录到的上下文环境中提取操作数,手动执行运算得到结果。
具体代码如下:
最终得到一级虚拟指令如下:
一级虚拟指令还原成二级虚拟指令的方法是利用虚拟堆栈平衡,即二级虚拟指令执行后,虚拟栈保持平衡。具体步骤如下:
需注意:
对于刚才还原出的一级虚拟指令样本,先从最后面分析,往上连续的PushReg指令一般都是虚拟寄存器入栈,用于后续恢复真实环境。那么,切割出一级虚拟指令片段如下:
那么根据这个,就需要往前寻找相同数量且连续的PopReg指令,对应一级虚拟指令片段如下:
这里根据VM Entry处的代码进行了虚拟寄存器与真实寄存器之间的映射。
找到了虚拟栈到虚拟寄存器的映射后,就可以从这里开始往下利用虚拟栈平衡划分一级虚拟指令片段了,这里挑出几个片段进行分析。
以上片段可还原成二级虚拟指令
以上片段可还原成二级虚拟指令
以上片段可还原成二级虚拟指令
对于有符号整数x,根据补码规则可得−x=∼x+1,进一步有∼x=−(x+1),通过这个化简上述二级虚拟指令,可得
这部分代码进行了复杂的标志位计算,然而其产生的结果在后续代码中并没有用到,因此是一段混淆代码。对于标志位的计算,一般与条件跳转指令有关,即先通过逻辑运算提取某一标志位是否为1(例如ZF),然后根据这个结果计算目标跳转指令,接着就是执行条件跳转指令。
至于最上面那个一级虚拟指令片段,通过分析发现其虚拟栈并没有平衡,原因在于,VM Entry处在保存真实环境时,额外入栈了两个数据,加上这两个push指令就平衡了。
不过后续并没有用到该ADDDW虚拟指令产生的结果和标志位,因此认定为这个片段为混淆指令片段。
最终去除混淆代码以及虚拟寄存器与真实寄存器映射(Pop和Push指令,这个主要是在多个虚拟机中跟踪真实寄存器),还原出的二级虚拟指令如下:
此时的二级虚拟指令可以说是与源指令一模一样了,所实现的功能并无差异。
对于虚拟代码还原,首要是识别处虚拟机的相关数据结构,例如虚拟栈指针、虚拟字节码指针、虚拟字节码表等等,然后人工分析处VM Handler的功能,当然,对于VM Handler的分析,可以借助AI来完成,需要告知虚拟机的相关数据结构,使AI的回答能够更精确。分析完虚拟机的结构以及相关数据结构后,可以尝试提取虚拟机结构的特征,比如VM Dispatcher存在VM Handler Table的使用,然后可以尝试编写代码自动化虚拟机结构的识别。之后借助模拟执行来获取整个代码流的执行情况,根据这个还原出虚拟代码流的一级虚拟指令。
对于一级虚拟指令还原成二级虚拟指令,需要利用到虚拟栈平衡这一特征来划分一级虚拟指令片段,这些片段对应一条或多条二级虚拟指令(复杂的逻辑运算可以尝试简化)。这里我总结了一点规律,如有不对的地方,恳请斧正:
因为基于栈的虚拟机,对于一个完整的二级虚拟指令,首先是将操作数据入栈,然后在栈中进行运算,然后将运算产生的标志位或运算结果出栈,因此对于push操作,可以认定是二级虚拟指令开始的标志,对于pop操作,可以认定是二级虚拟指令结束标志。但仍需要注意的是,运算指令后跟随的第一个出栈指令,是将运算产生的标志位出栈,如果后续没有第二个出栈指令,即运算结果仍然保留在虚拟栈中,则有可能该运算结果仍参与后续的指令的执行,因此还需往后进行虚拟栈平衡分析(test、cmp除外,它们只在意运算产生的标志位)
对于模拟执行得到的本机指令以及还原出的一级虚拟指令中,可能存在无用代码,可以借助**变量存活分析(Live-variable analysis)**识别出无用代码并删除,达到简化代码目的。
参考:
如何分析虚拟机系列(1):新手篇VMProtect 1.81 Demo - 吾爱破解 - 52pojie.cn
ac5K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6T1L8r3!0Y4i4K6u0W2j5X3q4U0K9#2)9J5k6h3g2F1k6$3W2F1k6h3g2J5K9h3&6Y4i4K6u0r3x3e0N6Q4x3V1j5H3y4g2)9J5c8U0t1H3x3U0p5`.
.text:00401000 sub_401000 proc near ; CODE XREF: start↓p
.text:00401000 mov eax, dword_403000; 值为 0deadbeefh
.text:00401005 add eax, 12345678h
.text:0040100A sub eax, 12345678h
.text:0040100F mov dword_403000, eax
.text:00401014 retn
.text:00401014 sub_401000 endp
.text:00401000 sub_401000 proc near ; CODE XREF: start↓p
.text:00401000 mov eax, dword_403000; 值为 0deadbeefh
.text:00401005 add eax, 12345678h
.text:0040100A sub eax, 12345678h
.text:0040100F mov dword_403000, eax
.text:00401014 retn
.text:00401014 sub_401000 endp
.text:00401000 ; void sub_401000()
.text:00401000 sub_401000 proc near ; CODE XREF: start↓p
.text:00401000 push offset byte_404781
.text:00401005 call sub_40472C
.text:0040100A
.text:0040100A loc_40100A: ; CODE XREF: sub_40472C+2B↓j
.text:0040100A ; DATA XREF: .vmp0:jpt_404757↓o
.text:0040100A mov esi, [ebp+0] ; jumptable 00404757 cases 126,128,146,149,246,255
.text:0040100D add ebp, 4
.text:00401010 jmp loc_40474E
.text:00401010 sub_401000 end
.text:00401000 ; void sub_401000()
.text:00401000 sub_401000 proc near ; CODE XREF: start↓p
.text:00401000 push offset byte_404781
.text:00401005 call sub_40472C
.text:0040100A
.text:0040100A loc_40100A: ; CODE XREF: sub_40472C+2B↓j
.text:0040100A ; DATA XREF: .vmp0:jpt_404757↓o
.text:0040100A mov esi, [ebp+0] ; jumptable 00404757 cases 126,128,146,149,246,255
.text:0040100D add ebp, 4
.text:00401010 jmp loc_40474E
.text:00401010 sub_401000 end
.vmp0:00404781 byte_404781 db 0Eh, 0E8h, 81h ; DATA XREF: sub_401000↑o
.vmp0:00404784 dd 5C765DA9h, 3E0A1A1Eh, 3A36262Eh, 602122Ah, 3000E822h
.vmp0:00404798 dd 16790040h, 34567869h, 1E7A1412h, 5678E836h, 97341234h
.vmp0:004047AC dd 5C066B4Dh, 1121973Eh, 4C3C0622h, 0EB161121h, 1E11F7EAh
.vmp0:004047C0 dd 326B2020h, 78081577h, 36325C32h, 30006904h, 0ED0040h
.vmp0:004047D4 dd 4382010h, 8342C24h, 0E1001Ch, 8 dup(0)
.vmp0:00404800 dd 200h dup(?)
.vmp0:00404781 byte_404781 db 0Eh, 0E8h, 81h ; DATA XREF: sub_401000↑o
.vmp0:00404784 dd 5C765DA9h, 3E0A1A1Eh, 3A36262Eh, 602122Ah, 3000E822h
.vmp0:00404798 dd 16790040h, 34567869h, 1E7A1412h, 5678E836h, 97341234h
.vmp0:004047AC dd 5C066B4Dh, 1121973Eh, 4C3C0622h, 0EB161121h, 1E11F7EAh
.vmp0:004047C0 dd 326B2020h, 78081577h, 36325C32h, 30006904h, 0ED0040h
.vmp0:004047D4 dd 4382010h, 8342C24h, 0E1001Ch, 8 dup(0)
.vmp0:00404800 dd 200h dup(?)
.vmp0:0040472C push esi
.vmp0:0040472D push edi
.vmp0:0040472E push esp
.vmp0:0040472F push ebx
.vmp0:00404730 push eax
.vmp0:00404731 push edx
.vmp0:00404732 push ebp
.vmp0:00404733 pushf
.vmp0:00404734 push ecx
.vmp0:0040472C push esi
.vmp0:0040472D push edi
.vmp0:0040472E push esp
.vmp0:0040472F push ebx
.vmp0:00404730 push eax
.vmp0:00404731 push edx
.vmp0:00404732 push ebp
.vmp0:00404733 pushf
.vmp0:00404734 push ecx
.vmp0:00404735 push ds:dword_404649
.vmp0:0040473B push 0
.vmp0:00404735 push ds:dword_404649
.vmp0:0040473B push 0
.vmp0:00404740 mov esi, [esp+2Ch+arg_0] ;arg_0 = dword ptr 4
.vmp0:00404740 mov esi, [esp+2Ch+arg_0] ;arg_0 = dword ptr 4
.vmp0:00404744 mov ebp, esp
.vmp0:00404746 sub esp, 0C0h
.vmp0:0040474C mov edi, esp
.vmp0:00404744 mov ebp, esp
.vmp0:00404746 sub esp, 0C0h
.vmp0:0040474C mov edi, esp
.vmp0:0040474E loc_40474E:
.vmp0:0040474E add esi, [ebp+0] ;index of vm opcode
.vmp0:0040474E loc_40474E:
.vmp0:0040474E add esi, [ebp+0] ;index of vm opcode
mov al, [esi] ;get vm opcode
movzx eax, al
inc esi ;index + 1
jmp ds:jpt_404757[eax*4] ; jmp to vm handler
mov al, [esi] ;get vm opcode
movzx eax, al
inc esi ;index + 1
jmp ds:jpt_404757[eax*4] ; jmp to vm handler
loc_40476F:
mov al, [ebp+0]
sub ebp, 2
add [ebp+4], al
pushf
pop dword ptr [ebp+0]
jmp loc_40400F
loc_40476F:
mov al, [ebp+0]
sub ebp, 2
add [ebp+4], al
pushf
pop dword ptr [ebp+0]
jmp loc_40400F
loc_4045FC:
mov ax, [ebp+0]
sub ebp, 2
add [ebp+4], ax
pushf
pop dword ptr [ebp+0]
jmp loc_40400F
loc_4045FC:
mov ax, [ebp+0]
sub ebp, 2
add [ebp+4], ax
pushf
pop dword ptr [ebp+0]
jmp loc_40400F
loc_404000:
mov eax, [ebp+0]
add [ebp+4], eax
pushf
pop dword ptr [ebp+0]
jmp loc_404751
loc_404000:
mov eax, [ebp+0]
add [ebp+4], eax
pushf
pop dword ptr [ebp+0]
jmp loc_404751
loc_404680:
mov al, [ebp+0]
mov cl, [ebp+2]
sub ebp, 2
shr al, cl
mov [ebp+4], ax
pushf
pop dword ptr [ebp+0]
jmp loc_40400F
loc_404680:
mov al, [ebp+0]
mov cl, [ebp+2]
sub ebp, 2
shr al, cl
mov [ebp+4], ax
pushf
pop dword ptr [ebp+0]
jmp loc_40400F
loc_40454E:
mov ax, [ebp+0]
mov cl, [ebp+2]
sub ebp, 2
shr ax, cl
mov [ebp+4], ax
pushf
pop dword ptr [ebp+0]
jmp loc_40400F
loc_40454E:
mov ax, [ebp+0]
mov cl, [ebp+2]
sub ebp, 2
shr ax, cl
mov [ebp+4], ax
pushf
pop dword ptr [ebp+0]
jmp loc_40400F
loc_404077:
mov eax, [ebp+0]
mov cl, [ebp+4]
sub ebp, 2
shr eax, cl
mov [ebp+4], eax
pushf
pop dword ptr [ebp+0]
jmp loc_40400F
loc_404077:
mov eax, [ebp+0]
mov cl, [ebp+4]
sub ebp, 2
shr eax, cl
mov [ebp+4], eax
pushf
pop dword ptr [ebp+0]
jmp loc_40400F
loc_404610:
mov eax, [ebp+0]
mov edx, [ebp+4]
mov cl, [ebp+8]
add ebp, 2
shrd eax, edx, cl
mov [ebp+4], eax
pushf
pop dword ptr [ebp+0]
jmp loc_404751
loc_404610:
mov eax, [ebp+0]
mov edx, [ebp+4]
mov cl, [ebp+8]
add ebp, 2
shrd eax, edx, cl
mov [ebp+4], eax
pushf
pop dword ptr [ebp+0]
jmp loc_404751
loc_4045C0:
mov al, [ebp+0]
mov cl, [ebp+2]
sub ebp, 2
shl al, cl
mov [ebp+4], ax
pushf
pop dword ptr [ebp+0]
jmp loc_40400F
loc_4045C0:
mov al, [ebp+0]
mov cl, [ebp+2]
sub ebp, 2
shl al, cl
mov [ebp+4], ax
pushf
pop dword ptr [ebp+0]
jmp loc_40400F
loc_404698:
mov ax, [ebp+0]
mov cl, [ebp+2]
sub ebp, 2
shl ax, cl
mov [ebp+4], ax
pushf
pop dword ptr [ebp+0]
jmp loc_40400F
loc_404698:
mov ax, [ebp+0]
mov cl, [ebp+2]
sub ebp, 2
shl ax, cl
mov [ebp+4], ax
pushf
pop dword ptr [ebp+0]
jmp loc_40400F
loc_4046EF:
mov eax, [ebp+0]
mov cl, [ebp+4]
sub ebp, 2
shl eax, cl
mov [ebp+4], eax
pushf
pop dword ptr [ebp+0]
jmp loc_40400F
loc_4046EF:
mov eax, [ebp+0]
mov cl, [ebp+4]
sub ebp, 2
shl eax, cl
mov [ebp+4], eax
pushf
pop dword ptr [ebp+0]
jmp loc_40400F
loc_4046BF:
mov eax, [ebp+0]
mov edx, [ebp+4]
mov cl, [ebp+8]
add ebp, 2
shld eax, edx, cl
mov [ebp+4], eax
pushf
pop dword ptr [ebp+0]
jmp loc_404751
loc_4046BF:
mov eax, [ebp+0]
mov edx, [ebp+4]
mov cl, [ebp+8]
add ebp, 2
shld eax, edx, cl
mov [ebp+4], eax
pushf
pop dword ptr [ebp+0]
jmp loc_404751
loc_404591:
mov ax, [ebp+0]
mov dx, [ebp+2]
not al
not dl
sub ebp, 2
and al, dl
mov [ebp+4], ax
pushf
pop dword ptr [ebp+0]
jmp loc_40400F
loc_404591:
mov ax, [ebp+0]
mov dx, [ebp+2]
not al
not dl
sub ebp, 2
and al, dl
mov [ebp+4], ax
pushf
pop dword ptr [ebp+0]
jmp loc_40400F
loc_404041:
not dword ptr [ebp+0]
mov ax, [ebp+0]
sub ebp, 2
and [ebp+4], ax
pushf
pop dword ptr [ebp+0]
jmp loc_40400F
loc_404041:
not dword ptr [ebp+0]
mov ax, [ebp+0]
sub ebp, 2
and [ebp+4], ax
pushf
pop dword ptr [ebp+0]
jmp loc_40400F
loc_40451A:
mov eax, [ebp+0]
mov edx, [ebp+4]
not eax
not edx
and eax, edx
mov [ebp+4], eax
pushf
pop dword ptr [ebp+0]
jmp loc_404751
loc_40451A:
mov eax, [ebp+0]
mov edx, [ebp+4]
not eax
not edx
and eax, edx
mov [ebp+4], eax
pushf
pop dword ptr [ebp+0]
jmp loc_404751
loc_4044E4:
movzx eax, byte ptr [esi]
sub ebp, 2
mov [ebp+0], ax
add esi, 1
jmp loc_40400F
loc_4044E4:
movzx eax, byte ptr [esi]
sub ebp, 2
mov [ebp+0], ax
add esi, 1
jmp loc_40400F
loc_40464D:
mov ax, [esi]
lea esi, [esi+2]
sub ebp, 2
mov [ebp+0], ax
jmp loc_40400F
loc_40464D:
mov ax, [esi]
lea esi, [esi+2]
sub ebp, 2
mov [ebp+0], ax
jmp loc_40400F
loc_40462B:
mov eax, [esi]
sub ebp, 4
lea esi, [esi+4]
mov [ebp+0], eax
jmp loc_40400F
loc_40462B:
mov eax, [esi]
sub ebp, 4
lea esi, [esi+4]
mov [ebp+0], eax
jmp loc_40400F
loc_40453B:
mov al, [esi]
cbw
cwde
sub ebp, 4
lea esi, [esi+1]
mov [ebp+0], eax
jmp loc_40400F
loc_40453B:
mov al, [esi]
cbw
cwde
sub ebp, 4
lea esi, [esi+1]
mov [ebp+0], eax
jmp loc_40400F
loc_4044BE:
mov ax, [esi]
cwde
add esi, 2
sub ebp, 4
mov [ebp+0], eax
jmp loc_40400F
loc_4044BE:
mov ax, [esi]
cwde
add esi, 2
sub ebp, 4
mov [ebp+0], eax
jmp loc_40400F
loc_4044D0:
mov al, [esi]
mov al, [edi+eax]
sub ebp, 2
sub esi, 0FFFFFFFFh
mov [ebp+0], ax
jmp loc_40400F
loc_4044D0:
mov al, [esi]
mov al, [edi+eax]
sub ebp, 2
sub esi, 0FFFFFFFFh
mov [ebp+0], ax
jmp loc_40400F
loc_4045E9:
mov al, [esi]
inc esi
mov ax, [edi+eax]
sub ebp, 2
mov [ebp+0], ax
jmp loc_40400F
loc_4045E9:
mov al, [esi]
inc esi
mov ax, [edi+eax]
sub ebp, 2
mov [ebp+0], ax
jmp loc_40400F
loc_4045AF:
and al, 3Ch
mov edx, [edi+eax]
sub ebp, 4
mov [ebp+0], edx
jmp loc_40400F
loc_4045AF:
and al, 3Ch
mov edx, [edi+eax]
sub ebp, 4
mov [ebp+0], edx
jmp loc_40400F
loc_404568:
mov al, [esi]
mov dx, [ebp+0]
sub esi, 0FFFFFFFFh
add ebp, 2
mov [edi+eax], dl
jmp loc_404751
loc_404568:
mov al, [esi]
mov dx, [ebp+0]
sub esi, 0FFFFFFFFh
add ebp, 2
mov [edi+eax], dl
jmp loc_404751
loc_4046DA:
mov al, [esi]
add esi, 1
mov dx, [ebp+0]
add ebp, 2
mov [edi+eax], dx
jmp loc_404751
loc_4046DA:
mov al, [esi]
add esi, 1
mov dx, [ebp+0]
add ebp, 2
mov [edi+eax], dx
jmp loc_404751
loc_404058:
and al, 3Ch
mov edx, [ebp+0]
add ebp, 4
mov [edi+eax], edx
jmp loc_404751
loc_404058:
and al, 3Ch
mov edx, [ebp+0]
add ebp, 4
mov [edi+eax], edx
jmp loc_404751
loc_40463B:
mov eax, ebp
sub ebp, 2
mov [ebp+0], ax
jmp loc_40400F
loc_40463B:
mov eax, ebp
sub ebp, 2
mov [ebp+0], ax
jmp loc_40400F
loc_4046B2:
mov eax, ebp
sub ebp, 4
mov [ebp+0], eax
jmp loc_40400F
loc_4046B2:
mov eax, ebp
sub ebp, 4
mov [ebp+0], eax
jmp loc_40400F
loc_404532:
mov bp, [ebp+0]
jmp loc_40400F
loc_404532:
mov bp, [ebp+0]
jmp loc_40400F
loc_40457C:
mov ebp, [ebp+0]
jmp loc_40400F
loc_40457C:
mov ebp, [ebp+0]
jmp loc_40400F
loc_4044AE:
mov eax, [ebp+0]
mov dl, [ebp+4]
add ebp, 6
mov [eax], dl
jmp loc_404751
loc_4044AE:
mov eax, [ebp+0]
mov dl, [ebp+4]
add ebp, 6
mov [eax], dl
jmp loc_404751
loc_40475E:
mov eax, [ebp+0]
mov dl, [ebp+4]
add ebp, 6
mov ss:[eax], dl
jmp loc_404751
loc_40475E:
mov eax, [ebp+0]
mov dl, [ebp+4]
add ebp, 6
mov ss:[eax], dl
jmp loc_404751
loc_4044F6:
mov eax, [ebp+0]
mov dx, [ebp+4]
add ebp, 6
mov [eax], dx
jmp loc_404751
loc_4044F6:
mov eax, [ebp+0]
mov dx, [ebp+4]
add ebp, 6
mov [eax], dx
jmp loc_404751
loc_404706:
mov eax, [ebp+0]
mov dx, [ebp+4]
add ebp, 6
mov ss:[eax], dx
jmp loc_404751
loc_404706:
mov eax, [ebp+0]
mov dx, [ebp+4]
add ebp, 6
mov ss:[eax], dx
jmp loc_404751
loc_404670:
mov eax, [ebp+0]
mov edx, [ebp+4]
add ebp, 8
mov [eax], edx
jmp loc_404751
loc_404670:
mov eax, [ebp+0]
mov edx, [ebp+4]
add ebp, 8
mov [eax], edx
jmp loc_404751
loc_4045D8:
mov eax, [ebp+0]
mov edx, [ebp+4]
add ebp, 8
mov ss:[eax], edx
jmp loc_404751
loc_4045D8:
mov eax, [ebp+0]
mov edx, [ebp+4]
add ebp, 8
mov ss:[eax], edx
jmp loc_404751
loc_40465F:
mov edx, [ebp+0]
add ebp, 2
mov al, [edx]
mov [ebp+0], ax
jmp loc_404751
loc_40465F:
mov edx, [ebp+0]
add ebp, 2
mov al, [edx]
mov [ebp+0], ax
jmp loc_404751
loc_40449C:
mov edx, [ebp+0]
add ebp, 2
mov al, ss:[edx]
mov [ebp+0], ax
jmp loc_404751
loc_40449C:
mov edx, [ebp+0]
add ebp, 2
mov al, ss:[edx]
mov [ebp+0], ax
jmp loc_404751
loc_404508:
mov eax, [ebp+0]
add ebp, 2
mov ax, [eax]
mov [ebp+0], ax
jmp loc_404751
loc_404508:
mov eax, [ebp+0]
add ebp, 2
mov ax, [eax]
mov [ebp+0], ax
jmp loc_404751
loc_404719:
mov eax, [ebp+0]
add ebp, 2
mov ax, ss:[eax]
mov [ebp+0], ax
jmp loc_404751
loc_404719:
mov eax, [ebp+0]
add ebp, 2
mov ax, ss:[eax]
mov [ebp+0], ax
jmp loc_404751
loc_404584:
mov eax, [ebp+0]
mov eax, [eax]
mov [ebp+0], eax
jmp loc_404751
loc_404584:
mov eax, [ebp+0]
mov eax, [eax]
mov [ebp+0], eax
jmp loc_404751
loc_404069:
mov eax, [ebp+0]
mov eax, ss:[eax]
mov [ebp+0], eax
jmp loc_404751
loc_404069:
mov eax, [ebp+0]
传播安全知识、拓宽行业人脉——看雪讲师团队等你加入!