用带 VM 的壳 + 混淆就没意思了啊…
应该是用 VMP (旧版) 或类似的壳套上,然后将这部分给虚拟化了。
去掉外层的花指令倒是不难:
import re
rJunkCode = re.compile(rb'\xE8\x00\x00\x00\x00([\s\S])+?\x8F\x44\x24\xFC')
with open('CM2.exe', 'rb') as f:
cm2 = f.read()
def replacer(group: re.Match):
return b'\x90' * len(group.group(0))
# .VIP5:0046A000 ; Section 5. (virtual address 0006A000)
# .VIP5:0046A000 ; Virtual size : 00003B4F ( 15183.)
# .VIP5:0046A000 ; Section size in file : 00003C00 ( 15360.)
# .VIP5:0046A000 ; Offset to raw data for section: 00058000
# .VIP5:0046A000 ; Flags E0000000: Executable Readable Writable
# .VIP5:0046A000 ; Alignment : default
sec5 = cm2[0x00058000:0x00058000+0x00003C00]
sec5 = rJunkCode.sub(replacer, sec5)
cm2_dejunk = bytearray(cm2)
cm2_dejunk[0x00058000:0x00058000+0x00003C00] = sec5
with open('CM2.dejunk.exe', 'wb') as f:
f.write(cm2_dejunk)
然后就是虚拟化处理后的部分,粗略看了下至少有 32 个 Handler 要分析:
;.VIP4:00466000 off_466000 dd offset loc_463000 ; DATA XREF: sub_4030DE+6A371↓o
; ...
;.VIP4:0046607C dd offset loc_463353
; (0x0046607C + 4 - 0x00466000) / 4 = 32 个 Handler 块
第一个 Handler 处理块,凭感觉应该是拷贝 12 字节,然后继续跳到虚拟机其它地方执行:
; 463000: handler 0
push ebp
mov ebp, esp
sub esp, 3Ch
mov dword ptr [ebp-4], 0
push 0x466404
push eax
push ecx
push edx
push ebx
push ebp
push esi
push edi
pushf
push 0
mov esi, [esp+24h] ; vm_inst
mov ebx, [esp]
add esi, ebx
mov ebp, esp
sub esp, 200h
mov eax, esp
add eax, 0F0h
cmp ebp, eax
jge loc_46D3F2
mov eax, esp
mov esp, ebp
sub esp, 0F0h
; memcpy(esp, eax, 0x0C)
push esi
push edi
push ecx
mov esi, eax
mov edi, esp
add edi, 0Ch
rep movsb
pop ecx
pop edi
pop esi
loc_46D3F2:
movzx eax, byte ptr [esi] ; eax = dword[0x466000 + byte[esi] * 4 + ebx] + ebx
shl eax, 2
lea esi, [esi+1] ; inc esi
add eax, offset off_466000 ; 跳到下一个 vm handler?
add eax, ebx
mov eax, [eax]
add eax, ebx
jmp eax
如果真要分析的话,估计得全部看一遍,分析虚拟机字节码对应的指令,然后再破解了。
因为我没对抗过 VM 虚拟机的壳,就不继续看了。
记录 VM 访问:
地址=0046D45A
模块/标签/异常=cm2.exe
状态=已禁用
反汇编=mov eax,dword ptr ds:[eax]
命中=0
摘要=暂停条件(0), 日志("eax: {eax}")
分析日志/对比,dword[466064]
(即 004632B8
) 在按下按钮的时候会执行(这个 Handler 应该是加载字符串)。可能刚好在判断之前,也可能已经判断完了 :)