外部地址
在保护应用程序时,VMProtect 会利用编译期间空闲的空间来满足自己的需要,包括存储各种数据(虚拟化或变异代码、VM 解释器等)。因此,当从程序的其他部分进行 “内部” 跳转时,可能会发生某些情况。执行这种跳转的地址称为外部地址。当使用代码标记并在标记内执行从程序的非受保护部分的跳转时,可能会发生上述情况:
VMProtectBegin(nil); for I:=0 to 10 do begin Inc(J); VMProtectEnd; end;
在汇编代码中,这个循环看起来像:
----------------- marker begin ---------------- 0044D12C mov eax, 0000000B 0044D131 inc ebx ----------------- marker end ----------------- 0044D132 dec eax 0044D133 jnz 0044D131
显然,当 0044D12C 和 0044D131 地址的命令被虚拟化,并且在 0044D133 执行非虚拟化的条件跳转时,会发生错误,因为 0044D131 的地址包含各种数据或者只是垃圾而不是原始代码。在这个例子中,0044D131 是一个外部地址。
当启用 “调试模式” 选项时,INT 03 命令将替换原始代码。这是一个简单的断点,也是一个调试器命令。当受保护的应用程序在调试器下执行并将控制权传递给 0044D131 地址时,将激活断点,并且调试器窗口会显示启动给定跳转的地址。
当检测到此类跳转时,我们建议检查所有代码标记,是否设置正确。如果未标记受保护代码,或者无法更改程序逻辑以避免在受保护代码内部传递控制权,则应在 GUI 中将此类地址标记为 外部地址 。