我最近对虚拟化非常着迷,并从随机生成的字节码中检索原始代码,例如 VMProtect/等保护程序。但我无法理解它实际上是如何完成的。
尽管我已经阅读了一些有助于更好地理解虚拟化的文章,即使是专门针对我试图去虚拟化的保护程序编写的文章,我也无法将他们的文章与我自己的示例相关联。两者之间存在差异,这让我感到困惑。
我制作了一个小程序,它接受一个字符串输入并输出它,然后将虚拟化添加到该函数中。我注意到的第一件事是该函数现在调用了另一个函数,看起来它在调用后添加了随机的垃圾指令。我还注意到它将 4 个字节压入堆栈。
.vmp0:00440C0F 68 28 02 8E 51 push 518E0228h
.vmp0:00440C14 E8 68 BB FC FF call sub_40C781
在里面sub_40C781
我看到它正在推送堆栈上的所有寄存器以及pushf
推送标志的指令。在这些推送和主要指令之间,我不禁注意到它们之间毫无意义的指令,这有点奇怪,因为我只在保护中指定了虚拟化。无论如何,我设法从名为 go as 的函数中清除的主要有效指令
push ebp
push ebx
push ecx
push esi
push edi
pushf
push edx
push eax
mov eax, 0
push eax
mov esi, [esp+24h+arg_0]
lea esi, [esi+eax]
lea esp, [esp-0C0h]
但是从那里开始,我不确定如何进行。最后的其余指令lea
作为
.vmp0:0040E187 loc_40E187: ; CODE XREF: .vmp0:00416516↓j
.vmp0:0040E187 ; .vmp0:loc_42E5EB↓j ...
.vmp0:0040E187 8B DE mov ebx, esi
.vmp0:0040E189 B8 00 00 00 00 mov eax, 0
.vmp0:0040E18E 0F BA F7 E7 btr edi, 0E7h ; 'ç'
.vmp0:0040E192 66 23 F8 and di, ax
.vmp0:0040E195 2B D8 sub ebx, eax
.vmp0:0040E197
.vmp0:0040E197 loc_40E197: ; DATA XREF: sub_40C781:loc_40E197↓o
.vmp0:0040E197 8D 3D 97 E1 40 00 lea edi, loc_40E197
.vmp0:0040E19D 66 0F A4 D0 09 shld ax, dx, 9
.vmp0:0040E1A2 C1 C8 49 ror eax, 49h
.vmp0:0040E1A5 81 EE 04 00 00 00 sub esi, 4
.vmp0:0040E1AB 0F A3 F8 bt eax, edi
.vmp0:0040E1AE 33 C6 xor eax, esi
.vmp0:0040E1B0 C6 C4 27 mov ah, 27h ; '''
.vmp0:0040E1B3 8B 06 mov eax, [esi]
.vmp0:0040E1B5 F9 stc
.vmp0:0040E1B6 F8 clc
.vmp0:0040E1B7 E9 79 12 05 00 jmp loc_45F435
但是我看不出这将如何解释代码并将其转换为 x86 表示。根据我的理解,esi
可能是VM的指令ptr。loc_40E197
由于缺乏更好的词,似乎是指令“调度员”。但我无法掌握内部工作原理,esi
似乎每个循环减少 4,我认为应该是 1。
任何有关如何进行的见解将不胜感激。