0.前言
首先应该知道虚拟机的一些基本知识,参考1 然后使用动态调试。
1.脱壳
1.1 od附加调试
这个程序无法直接将程序拖入od调试,因为作者在题目中说了加了壳,而且直接拖入之后,会弹窗不允许反调试,附加进程进行调试可以有效的避免AntiDebuggers检测。具体方法:
1.双击运行程序。
2.file——>attach——>找到运行的程序进程
1.2 脱壳
1.使用strong od
2.plugins——>OllyDump——>脱壳再当前调试的进程——>脱壳
2.调试
2.1 查看dump的程序
使用ida查看,从整体架构来看,如图
与虚拟机的整体架构几乎一样,上面的圈出来的部分,即为虚拟机的VMDispatcher,下面的是各个handler,跳转执行;上面是字节码的输入+初始化。典型的虚拟机。点进去VMDispatcher,可以看一眼,是一个跳转表. 下面是Dispatcher
.text:00421224 loc_421224: ; CODE XREF: sub_420CE0+53F↑j
.text:00421224 jmp off_42271B[eax*4]
//根据eax(opcode)的取值,判断跳转到哪一个handler
下面是跳转表
.text:0042271B off_42271B dd offset loc_42196F ; DATA XREF: sub_420CE0:loc_421224↑r
.text:0042271F dd offset loc_421582
.text:00422723 dd offset loc_4219EE
.text:00422727 dd offset loc_4218D9
.text:0042272B dd offset loc_4216FB
.text:0042272F dd offset loc_421F12
.text:00422733 dd offset loc_4218FF
.text:00422737 dd offset loc_421A83
.text:0042273B dd offset loc_4226D8
.text:0042273F dd offset loc_4213E1
.text:00422743 dd offset loc_421E66
.text:00422747 dd offset loc_421FF8
.text:0042274B dd offset loc_4214A4
.text:0042274F dd offset loc_4215B9
.text:00422753 dd offset loc_421815
.text:00422757 dd offset loc_42140B
.text:0042275B dd offset loc_421EAC
.text:0042275F dd offset loc_421B83
.text:00422763 dd offset loc_421F4E
.text:00422767 dd offset loc_422041
.text:0042276B dd offset sub_421765
.text:0042276F dd offset sub_421BDC
.text:00422773 dd offset sub_4215A0
.text:00422777 dd offset sub_421C02
.text:0042277B dd offset sub_4219D0
.text:0042277F dd offset sub_421C3B
.text:00422783 dd offset sub_42195F
.text:00422787 dd offset sub_421928
.text:0042278B dd offset sub_4218B7
.text:0042278F dd offset sub_421B62
.text:00422793 align 4
.text:00422794 dd 55004216h, 61004216h, 6700421Fh, 40004215h, 0B2004214h
.text:00422794 dd 5A004219h, 0DD004220h, 0F9004214h, 0B1004213h, 0E800421Ah
.text:00422794 dd 0FFFF48DCh, 6558CE9h
.text:004227C4 db 0
2.2 run trace 分析虚拟机指令
因为oddump出来的程序在与ida的入口地址一致,ida中的VMDispatcher的地址,在od中也是相同的。在od中0x00421224处下断点,运行查看eax为0x0000001B,然后使用run trace,对单个的handler进行追踪,方法如下:
调试——>打开或清楚RUN追踪——>单步步入
结果如下:
地址 线程 命令 寄存器和注释
清除收集的信息
00421224 主 jmp dword ptr ds:[eax*4+0x42271B]
00421928 主 and eax,0xED825741 FL=0, EAX=00000001
0042192E 主 mov ax,word ptr ds:[edi+0x8] EAX=00000000
00421936 主 jmp short CrackMe_.0042193B
0042193B 主 sbb eax,0xED82D59D FL=CPA, EAX=127D2A63
00421941 主 jmp CrackMe_.00421D12
00421D12 主 add eax,dword ptr ds:[esi+0x2] FL=P, EAX=12982A63
00421D19 主 jmp CrackMe_.004219F6
004219F6 主 mov eax,dword ptr ds:[esi] EAX=00000001
004219F8 主 jmp short CrackMe_.004219FE
004219FE 主 add esi,0x4 ESI=0043E56A
00421A01 主 jmp short CrackMe_.00421A05
00421A05 主 sub ebp,0x4 FL=A, EBP=0019FBBC
00421A08 主 jmp short CrackMe_.00421A0B
00421A0B 主 mov dword ptr ss:[ebp],eax
00421A0E 主 jmp CrackMe_.00421810
00421810 主 jmp CrackMe_.0042126B
0042126B 主 jmp short CrackMe_.00421270
00421270 主 jmp short CrackMe_.00421274
00421274 主 movsx eax,bl EAX=00000000
00421277 主 mov eax,0xED636BF0 EAX=ED636BF0
0042127C 主 jmp CrackMe_.00421281
00421281 主 movsx eax,byte ptr ss:[esp+0x9] EAX=00000029
00421289 主 jmp short CrackMe_.0042128E
0042128E 主 movsx eax,byte ptr ss:[esp+0x5] EAX=00000037
00421296 主 jmp short CrackMe_.00421298
00421298 主 movsx eax,byte ptr ss:[esp+0x4] EAX=FFFFFFE3
004212A0 主 jmp CrackMe_.00421173
00421173 主 pushfd ESP=0019FA54
00421174 主 clc
00421175 主 jmp short CrackMe_.00421178
00421178 主 adc ax,0x5725 FL=C, EAX=FFFF5708
0042117D 主 jmp short CrackMe_.00421182
00421182 主 inc al FL=CP, EAX=FFFF5709
00421184 主 jmp CrackMe_.004210BD
004210BD 主 xor ax,0xBF77 FL=PS, EAX=FFFFE87E
004210C2 主 jmp short CrackMe_.004210C6
004210C6 主 lea eax,dword ptr ds:[edi+0x40] EAX=0019FAD8
004210C9 主 jmp short CrackMe_.004210CC
004210CC 主 cmp ebp,eax FL=P
004210CE 主 jmp short CrackMe_.004210D1
004210D1 主 ja CrackMe_.00421208
00421208 主 movzx eax,byte ptr ds:[esi] EAX=0000001B
0042120B 主 jmp CrackMe_.0042123A
0042123A 主 lea esi,dword ptr ds:[esi+0x1] ESI=0043E56B
0042123D 主 jmp CrackMe_.0042121E
0042121E 主 popfd FL=A, ESP=0019FA58
0042121F 主 jmp short CrackMe_.00421224
信息收集完成, 开始动态记录
在这一段程序的执行中,可以使其简化分析,主要的handler代码是0x00421224——0x0042126B,0x0042126B之后的代码,是所有handler的公共的部分,不用考虑。而且在汇编代码中加入了一些混淆,经过分析之后的关键代码如下:
00421224 主 jmp dword ptr ds:[eax*4+0x42271B]
004219F6 主 mov eax,dword ptr ds:[esi] EAX=00000001
00421A05 主 sub ebp,0x4 FL=A, EBP=0019FBBC
00421A0B 主 mov dword ptr ss:[ebp],eax
ebp是与栈相关,这段代码,将esi指向的内容放到ebp,然后栈减0x4,把eax的值放入栈中,所以opcode为1B的整体的功能应该是把一个立即数压入栈中。 再接下来是26,去混淆后的关键代码如下
地址 线程 命令 寄存器和注释
清除收集的信息
00421224 主 jmp dword ptr ds:[eax*4+0x42271B]
004216AB 主 mov eax,dword ptr ss:[ebp+0x4] EAX=00000001
00421713 主 mov edx,dword ptr ss:[ebp] EDX=00000000
00421716 主 imul edx EAX=00000000
0042171D 主 mov dword ptr ss:[ebp+0x4],eax
00421720 主 mov dword ptr ss:[ebp],edx
信息收集完成, 开始动态记录
看到有一条关键的 imul指令,分析得出,这是将eax*edx,乘完之后放入栈中。
3.求解sn
程序将一个字符串WoJiuShiZheMe与输入的sn异或,然后判断结果是否为1B0602081C1F0D3E352C000A00,所以可以将判定结果与字符串异或,得到的sn如下: