参考上节的跟踪记录vm_tls.txt,可以看到第117行和第290行的VmCALL将代码分成3块,标记为Chunk1 - Chunk3,我们先看下VmCALL的实现,再分别分析这3块代码。
shrd rsi,rbx,cl
mov esi,dword ptr ss:[rbp]
Esi = 栈顶DWORD
clc
stc
add rbp,8
jmp vmp_userdebugger.7FF69E7403F7
bsf ax,di
sar r12d,cl
inc r12d
shl ch,5
lea r12,qword ptr ds:[7FF69E74065C]
R12 固定取7FF69E74065C
rcl al,7
not bh
mov rax,100000000
rcr rbx,10
add rsi,rax
Rsi += 100000000
xchg al,bh
bsr bx,dx
shld bx,sp,cl
rcr ebx,cl
mov rbx,rsi
Rbx = Rsi
movsx cx,cl
add rsi,qword ptr ss:[rbp]
Rsi += 栈顶QWORD, 注意此处未调整RBP栈指针
可以看到,VmCALL取栈中DWORD作为基数计算RBX和RSI,我们第一篇分析过,RSI指向字节码缓冲区,RBX为解密Seed,也就是说每个Chunk都有自己的RSI和RBX。
在继续分析Chunk之前,可先参考下节Nor Gate说明,其对用到的运算的Nor变换做了详细说明,下面的分析不在赘述。
[Anakin] VmPOP V_98 ;V_98 = $HandlerBase
[Anakin] VmPUSH FFFFFFFF9F5A5C32
[Anakin] VmADD
[Anakin] VmPOP V_40
[Anakin] VmPOP V_B8
[Anakin] VmPOP V_28
[Anakin] VmPOP V_18
[Anakin] VmPOP V_00
[Anakin] VmPOP V_78
[Anakin] VmPOP V_A0
[Anakin] VmPOP V_90
[Anakin] VmPOP V_40
[Anakin] VmPOP V_20
[Anakin] VmPOP V_68
[Anakin] VmPOP V_50
[Anakin] VmPOP V_58
[Anakin] VmPOP V_30
[Anakin] VmPOP V_B0
[Anakin] VmPOP V_38
[Anakin] VmPOP V_48
[Anakin] VmPOP V_70
[Anakin] VmPOP V_88
[Anakin] VmPOP V_10
[Anakin] VmPOP V_A8
[Anakin] VmPUSH 0000000064765E24 ;压栈分支1标识
[Anakin] VmPUSHB8 00
[Anakin] VmPUSH 000000014018B3E7
[Anakin] VmPUSH V_98
[Anakin] VmADD
[Anakin] VmPOP V_08
[Anakin] VmREADB ;b = BYTE:[000000014018B3E7 + $HandlerBase]
[Anakin] VmSBP
[Anakin] VmREADB
[Anakin] VmNOTANDB ;b = ~b
[Anakin] VmPOP V_60
[Anakin] VmADDB ;b = 00 + b
[Anakin] VmPOP V_10 ;V_10 = eflags
[Anakin] VmSBP
[Anakin] VmREADB
[Anakin] VmNOTANDB ;b = ~b
[Anakin] VmPOP V_80 ;V_80 = eflags
[Anakin] VmPOPW8 V_60 ;V_60 = b
[Anakin] VmPUSH V_10
[Anakin] VmPUSH V_10
[Anakin] VmNOTAND ;d1 = NOTAND(V_10, V_10) => d1 = ~V_10
[Anakin] VmPOP V_60
[Anakin] VmPUSH FFFFFFFFFFFFF7EA
[Anakin] VmNOTAND ;d1 = NOTAND(d1, FFFFF7EA) => d1 = Nor(~V_10, ~00000815) = V_10 & 00000815
[Anakin] VmPOP V_08
[Anakin] VmPUSH V_80
[Anakin] VmPUSH V_80
[Anakin] VmNOTAND ;d2 = NOTAND(V_80, V_80) => d2 = ~V_80
[Anakin] VmPOP V_60
[Anakin] VmPUSH 0000000000000815
[Anakin] VmNOTAND ;d2 = NOTAND(d2, 00000815) => d2 = Nor(~V_80, ~FFFFF7EA) = V_80 & FFFFF7EA
[Anakin] VmPOP V_08
[Anakin] VmADD
[Anakin] VmPOP V_08
[Anakin] VmPOP V_70 ;V_70 = d1 + d2 => V_70 = EFLAGS(BYTE:[000000014018B3E7 + $HandlerBase] - 0)
[Anakin] VmPUSH 0000000064766651 ;压栈分支2标识
[Anakin] VmSBP ;压栈栈顶指针,用于后文选择分支
[Anakin] VmPUSHB8 03
[Anakin] VmPUSHD 000000BF
[Anakin] VmPUSH V_70
[Anakin] VmNOTAND ;q = CDQ(NOTAND(V_70, 000000BF)) => ZF == 0 ? 0b1000000 : 0
[Anakin] VmPOP V_68
[Anakin] VmSHR ;q = SHR(q, 3) => ZF == 0 ? 8 : 0
[Anakin] VmPOP V_08
[Anakin] VmADD ;q += SavedRBP (上文压栈的栈顶指针,选择分支)
[Anakin] VmPOP V_08
[Anakin] VmREADQ
[Anakin] VmPOP V_A8 ;V_A8 = QWORD:[q](取分支标识)
[Anakin] VmPOP V_68
[Anakin] VmPOP V_08
[Anakin] VmPUSH V_A8
[Anakin] VmPOPD V_A8 ;V_A8 = CQD(V_A8)
[Anakin] VmPUSHD V_A8
[Anakin] VmSBP
[Anakin] VmREADD
[Anakin] VmNOTANDD ;d1 = NOTAND(V_A8, V_A8)
[Anakin] VmPOP V_08
[Anakin] VmPUSHD DB91AA8C
[Anakin] VmNOTANDD ;d1 = NOTAND(d1, DB91AA8C) => d1 = Nor(~V_A8, ~246E5573)
[Anakin] VmPOP V_68
[Anakin] VmPUSHD 246E5573
[Anakin] VmPUSHD V_A8
[Anakin] VmNOTANDD ;d2 = NOTAND(V_A8, 246E5573) => d2 = Nor(V_A8, 246E5573)
[Anakin] VmPOP V_60
[Anakin] VmNOTANDD
[Anakin] VmPOP V_60
[Anakin] VmPOP V_08 ;V_08 = NOTAND(d2, d1) => V_08 = Nor(d1, d2) = V_A8 ^ 246E5573 (分支标识解密)
[Anakin] VmPUSH V_18
[Anakin] VmPUSH V_98
[Anakin] VmPUSH V_60
[Anakin] VmPUSH V_00
[Anakin] VmPUSH V_88
[Anakin] VmPUSH V_50
[Anakin] VmPUSH V_30
[Anakin] VmPUSH V_B0
[Anakin] VmPUSH V_20
[Anakin] VmPUSH V_28
[Anakin] VmPUSH V_38
[Anakin] VmPUSH V_78
[Anakin] VmPUSH V_A0
[Anakin] VmPUSH V_90
[Anakin] VmPUSH V_58
[Anakin] VmPUSH V_48
[Anakin] VmPUSH V_40
[Anakin] VmPUSH V_18
[Anakin] VmPUSH V_70
[Anakin] VmPUSH V_B8
[Anakin] VmPUSH 0000000060A5A3CE
[Anakin] VmADD
[Anakin] VmPOP V_60
[Anakin] VmPUSH V_98
[Anakin] VmPUSH V_08 ;压栈解码后的分支标识
[Anakin] VmCALL ;调用选择分支
等价逻辑:
If (*(BYTE*)(000000014018B3E7 + $HandlerBase) != 0)
{
//未执行
VmCALL 40180B57
}
Else
{
//即Chunk2
VmCALL 40183322
}
[Anakin] VmPOP V_90 ;V_90 = $HandlerBase
[Anakin] VmPUSH FFFFFFFF9F5A5C32
[Anakin] VmADD
[Anakin] VmPOP V_20
[Anakin] VmPOP V_00
[Anakin] VmPOP V_70
[Anakin] VmPOP V_80
[Anakin] VmPOP V_60
[Anakin] VmPOP V_98
[Anakin] VmPOP V_38
[Anakin] VmPOP V_48
[Anakin] VmPOP V_28
[Anakin] VmPOP V_18
[Anakin] VmPOP V_30
[Anakin] VmPOP V_10
[Anakin] VmPOP V_88
[Anakin] VmPOP V_08
[Anakin] VmPOP V_A8
[Anakin] VmPOP V_40
[Anakin] VmPOP V_20
[Anakin] VmPOP V_68
[Anakin] VmPOPD V_78 ;V_78 = eflags
[Anakin] VmPUSHD V_78
[Anakin] VmPUSHD V_78
[Anakin] VmNOTANDD
[Anakin] VmPOP V_B0
[Anakin] VmPUSHD DB91AA8C
[Anakin] VmNOTANDD
[Anakin] VmPOP V_B8
[Anakin] VmPUSHD 246E5573
[Anakin] VmPUSHD V_78
[Anakin] VmNOTANDD
[Anakin] VmPOP V_50
[Anakin] VmNOTANDD
[Anakin] VmPOP V_B0
[Anakin] VmPOP V_A0 ;V_A0 = V_78 ^ 246E5573
[Anakin] VmPOP V_58
[Anakin] VmPOP V_B8
[Anakin] VmPUSH V_70
[Anakin] VmPUSH V_88
[Anakin] VmPUSH V_08
[Anakin] VmPUSH V_48
[Anakin] VmPUSH V_98
[Anakin] VmPUSH V_80
[Anakin] VmPUSH V_A8
[Anakin] VmPUSH 000000000CABFA9E ;PUSH Branch1
[Anakin] VmPUSH 000000014018B3E7
[Anakin] VmPUSH V_90
[Anakin] VmADD
[Anakin] VmPOP V_50 ;PUSH (V_90 + 000000014018B3E7)
[Anakin] VmPUSH 0000000140000000
[Anakin] VmPUSH V_90
[Anakin] VmADD
[Anakin] VmPOP V_58
[Anakin] VmPOP V_50 ;V_50 = V_90 + 0000000140000000 => V_50 = PIMAGE_DOS_HEADER
[Anakin] VmPUSH V_50
[Anakin] VmPUSHD 0000003C
[Anakin] VmADD
[Anakin] VmPOP V_58 ;PUSH (V_50 + 0000003C)
[Anakin] VmREADD
[Anakin] VmPOPD V_88 ;V_88 = DWORD:[BP] => V_88 = PIMAGE_DOS_HEADER->e_lfanew
[Anakin] VmPUSH 0000000000000000
[Anakin] VmPOPD V_8C
[Anakin] VmPUSH V_88
[Anakin] VmPUSH V_50
[Anakin] VmADD
[Anakin] VmPOP V_A8 ;PUSH (V_50 + V_88) => PUSH PIMAGE_NT_HEADERS64
[Anakin] VmSBP
[Anakin] VmREADQ
[Anakin] VmPOP V_B0
[Anakin] VmPUSHD 00000028
[Anakin] VmADD
[Anakin] VmPOP V_A8 ;PUSH (PIMAGE_NT_HEADERS64 + 00000028) => PUSH PIMAGE_NT_HEADERS64->AddressOfEntryPoint
[Anakin] VmREADD
[Anakin] VmPOPD V_B0 ;V_B0 = AddressOfEntryPoint
[Anakin] VmPUSH 0000000000000000
[Anakin] VmPOPD V_B4 ;V_B4 = 0
[Anakin] VmPUSH V_50
[Anakin] VmPUSH V_B0
[Anakin] VmADD
[Anakin] VmPOP V_A8
[Anakin] VmPOP V_A8 ;V_A8 = V_B0 + V_50
[Anakin] VmPUSHB8 cc
[Anakin] VmPUSH V_A8
[Anakin] VmREADB ;b = BYTE:[V_A8], 判断程序入口点地址第一个字节是不是‘0xCC’
[Anakin] VmSBP ;判断逻辑参考Chunk1及Nor Gate
[Anakin] VmREADB
[Anakin] VmNOTANDB
[Anakin] VmPOP V_58
[Anakin] VmADDB
[Anakin] VmPOP V_58
[Anakin] VmSBP
[Anakin] VmREADB
[Anakin] VmNOTANDB
[Anakin] VmPOP V_B8
[Anakin] VmPOPW8 V_70
[Anakin] VmPUSH V_58
[Anakin] VmSBP
[Anakin] VmREADQ
[Anakin] VmNOTAND
[Anakin] VmPOP V_88
[Anakin] VmPUSH FFFFFFFFFFFFF7EA
[Anakin] VmNOTAND
[Anakin] VmPOP V_B0
[Anakin] VmPUSH V_B8
[Anakin] VmPUSH V_B8
[Anakin] VmNOTAND
[Anakin] VmPOP V_70
[Anakin] VmPUSH 0000000000000815
[Anakin] VmNOTAND
[Anakin] VmPOP V_88
[Anakin] VmADD
[Anakin] VmPOP V_88
[Anakin] VmPOP V_70
[Anakin] VmPOP V_88
[Anakin] VmPUSH 000000000CABFDC1 ;PUSH Branch2
[Anakin] VmSBP
[Anakin] VmPUSHB8 03
[Anakin] VmPUSHD 000000BF
[Anakin] VmPUSH V_70
[Anakin] VmNOTAND
[Anakin] VmPOP V_A0
[Anakin] VmSHR
[Anakin] VmPOP V_B0
[Anakin] VmADD
[Anakin] VmPOP V_B0
[Anakin] VmREADQ
[Anakin] VmPOP V_58
[Anakin] VmPOP V_B0
[Anakin] VmPOP V_08
[Anakin] VmPUSH V_58
[Anakin] VmPOPD V_58
[Anakin] VmPUSHD V_58
[Anakin] VmSBP
[Anakin] VmREADD
[Anakin] VmNOTANDD
[Anakin] VmPOP V_A0
[Anakin] VmPUSHD B34CBE36
[Anakin] VmNOTANDD
[Anakin] VmPOP V_78
[Anakin] VmPUSHD 4CB341C9
[Anakin] VmPUSHD V_58
[Anakin] VmNOTANDD
[Anakin] VmPOP V_B0
[Anakin] VmNOTANDD
[Anakin] VmPOP V_B0
[Anakin] VmPOP V_08 ;V_08 = $Branch ^ 4CB341C9
[Anakin] VmPUSH V_50
[Anakin] VmPUSH V_08
[Anakin] VmPUSH V_80
[Anakin] VmPUSH V_B0
[Anakin] VmPUSH V_40
[Anakin] VmPUSH V_88
[Anakin] VmPUSH V_38
[Anakin] VmPUSH V_98
[Anakin] VmPUSH V_18
[Anakin] VmPUSH V_68
[Anakin] VmPUSH V_28
[Anakin] VmPUSH V_30
[Anakin] VmPUSH V_48
[Anakin] VmPUSH V_60
[Anakin] VmPUSH V_10
[Anakin] VmPUSH V_A8
[Anakin] VmPUSH V_20
[Anakin] VmPUSH V_50
[Anakin] VmPUSH V_70
[Anakin] VmPUSH V_00
[Anakin] VmPUSH 0000000060A5A3CE
[Anakin] VmADD
[Anakin] VmPOP V_B0
[Anakin] VmPUSH V_90
[Anakin] VmPUSH V_08 ;压栈选择的分支
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)