首页
社区
课程
招聘
[原创]看雪 2016 CTF 第十八题 D-ASM-VM
发表于: 2016-12-8 12:32 6730

[原创]看雪 2016 CTF 第十八题 D-ASM-VM

HHHso 活跃值
22
2016-12-8 12:32
6730

主要的技术点有:
a.以ret跳转的方式截断函数体,阻碍IDA流程图对局部变量的识别。
b.以SEH异常处理链的方式实现正确分支的间接跳转。
c.以模拟展平化汇编的vm隐藏普通对比和方程组等用于校验的h后半部分算法。

注册码校验分两部分进行 key = xsmKey + vmKey ,
其中前半部分xsmKey由a截断的函数体实现校验,成功后通过b实现跳转进入c的asm-vm校验后半部分vmKey。
vm相对简短,反编译出来即可得到校验条件,详细参考后续反编译代码解释和ASM-VM反编译代码。

1.入口
1.1 消息响应函数入口
_WinMain@16 中有注册对话框的初始化调用,Hi_DialogFunc_sub_401050为对话框消息响应函数,如下。

.text:0040101A push    0               ; dwInitParam
.text:0040101C push    offset Hi_DialogFunc_sub_401050 ; lpDialogFunc
.text:00401021 push    0               ; hWndParent
.text:00401023 push    65h             ; lpTemplateName
.text:00401025 mov     eax, hInstance
.text:0040102A push    eax             ; hInstance
.text:0040102B call    ds:DialogBoxParamA

1.2 校验入口
在1.1的消息函数 Hi_DialogFunc_sub_401050 中,
获取注册码key后进入核心校验函数Hi_XorSubIterMul_and_ASMvm_check_sub_401120
.text:004010AE call    ds:GetDlgItemTextA
.text:004010B4 cmp     esi, esp
.text:004010B6 call    __chkesp
.text:004010BB lea     ecx, [ebp+StringKey]
.text:004010BE push    ecx
.text:004010BF mov     edx, [ebp+hDlg]
.text:004010C2 push    edx
.text:004010C3 call    Hi_XorSubIterMul_and_ASMvm_check_sub_401120

2.前半部分注册码xsmKey校验与逆向求解
在Hi_XorSubIterMul_and_ASMvm_check_sub_401120中,函数被插入的ret跳转截断;
阻碍IDA对整个函数体局部变量的识别,ret的跳转是直接顺序连接的,直接nop掉即可。
nop掉后,快捷键"U"在函数首地址 401120 处去掉函数原有定义,
再快捷键"C"重建为代码,并重建函数,这时候流程图就比较清晰。
直接nop掉的代码片段:

.text:004011AC loc_4011AC:
.text:004011AC lea     eax, loc_4011AC
.text:004011B2 add     eax, 10h
.text:004011B5 push    eax
.text:004011B6 retn

2.1 在函数Hi_XorSubIterMul_and_ASMvm_check_sub_401120中,逐步检测要求
a. key[0x0D]及其后面的字符都为数字
b. xsmKey = key[0~8], xkey='3!"!5|ben'
xsmKey_xs[i] = xsmKey[i] ^ xkey[i] - 0x41,其中i=0,..,8
要求 xsmKey_xs[0]>1,且xsmKey_xs为递增数列
c. xsmKey_xsm=1; xsmKey_xsm *= xsmKey_xs[i],其中i=0,..,8
要求累积xsmKey_xsm 等于 0x0D4C2086

d. 所以xsmKey就可以通过上述的逆操作得到
~c. python 尝试累积xsmKey_xsm=0xD4C2086的因式分解
    >>> 0xD4C2086/2
    111546435
    >>> 0xD4C2086/2/5
    22309287
    >>> 0xD4C2086/2/5/7.0
    3187041.0
    >>> 0xD4C2086/2/5/7.0/9 //-----------9不正确
    354115.6666666667
    >>> 0xD4C2086/2/5/7.0/11
    289731.0
    >>> 0xD4C2086/2/5/7.0/11/13
    22287.0
    >>> 0xD4C2086/2/5/7.0/11/13/17
    1311.0
    >>> 0xD4C2086/2/5/7.0/11/13/17/19
    69.0
    >>> 0xD4C2086/2/5/7.0/11/13/17/19/23
    3.0
    刚刚好不多不少,且要求是递增数列,所以有数列
    xsmKey_xs = [2,3,5,7,11,13,17,19,23]
~b. 一步到位就可以得到前半部分注册码
    >>> xkey='3!"!5|ben'
    >>> xsmKey_xs = [2,3,5,7,11,13,17,19,23]
    >>> b"".join([chr((0x41+xsmKey_xs[i])^ord(xkey[i])) for i in xrange(0,9)])
    'pediy2016'

2.2 异常跳转实现
2.2.1在 Hi_XorSubIterMul_and_ASMvm_check_sub_401120 的入口SEH初始化时,
跟进异常处理跳转表
.text:00401125 push    offset Hi_SEH_ScopeTable_stru_4080C0
.text:0040112A push    offset __except_handler3

Hi_SEH_ScopeTable_stru_4080C0 _SCOPETABLE_ENTRY <0FFFFFFFFh, offset loc_401334, offset loc_401338>

2.2.2 下述代码实现异常跳转表的修改,以实现产生异常时跳转到目标地址
a.分配新的跳转表条目lpMem_newScopeTableEntry
b.复制上面Hi_SEH_ScopeTable_stru_4080C0的前两个字段
c.新跳转表的第三字段为TryLevel=0保护的代码区异常处理回调,其修改为
  上述的loc_401338+6,即为 0040133E,进入后半部分的ASM-vm校验。
    .text:0040133E mov     esp, [ebp+ms_exc.old_esp]
    .text:00401341 mov     edx, [ebp+P2_key]
    .text:00401344 push    edx             ; P2_key
    .text:00401345 mov     eax, [ebp+hWnd]
    .text:00401348 push    eax             ; hWnd
    .text:00401349 call    Hi_ASMvm_check_sub_4013B0

//----------------------------------------------------------
.text:0040115B push    0Ch             ; size_t
.text:0040115D call    _malloc
.text:00401162 add     esp, 4
00401165 mov     [ebp+lpMem_newScopeTableEntry], eax
...//省略无关代码
.text:004011C3 mov     [ebp+ms_exc.registration.TryLevel], 0
.text:004011CA mov     eax, [ebp+ms_exc.registration.ScopeTable]
.text:004011CD mov     [ebp+var_1C_ScopeTable], eax
.text:004011D0 mov     eax, [ebp+var_1C_ScopeTable]
.text:004011D3 mov     [ebp+var_20_cpyScopeTable], eax
.text:004011D6 mov     ecx, [ebp+lpMem_newScopeTableEntry]
.text:004011D9 mov     edx, [ebp+var_20_cpyScopeTable]
.text:004011DC mov     eax, [edx]
.text:004011DE mov     [ecx], eax
.text:004011E0 mov     ecx, [ebp+lpMem_newScopeTableEntry]
.text:004011E3 mov     edx, [ebp+var_20_cpyScopeTable]
.text:004011E6 mov     eax, [edx+4]
.text:004011E9 mov     [ecx+4], eax
.text:004011EC mov     ecx, [ebp+var_20_cpyScopeTable]
.text:004011EF mov     edx, [ecx+8]
.text:004011F2 add     edx, 6
.text:004011F5 mov     eax, [ebp+lpMem_newScopeTableEntry]
.text:004011F8 mov     [eax+8], edx
.text:004011FB mov     eax, [ebp+lpMem_newScopeTableEntry]
.text:004011FE mov     [ebp+ms_exc.registration.ScopeTable
//----------------------------------------------------------
d.如果累积xsmKey_xsm匹配,则会产生除零异常,转如后半部分校验
.text:00401318 loc_401318:
.text:00401318 mov     ecx, 0D4C2086h
.text:0040131D sub     ecx, dword ptr [ebp+var_58_xsmKey_xsm]
.text:00401320 mov     eax, 64h
.text:00401325 cdq
.text:00401326 idiv    ecx

3.模拟展平化汇编的vm
经过前半部分的校验正确后会进入 Hi_ASMvm_check_sub_4013B0 进行后部分校验
这种VM的模型类似于我们平时的汇编编程习惯,
编译器都会有汇编的MapList文件产生开关选项,其相当于把MapList的内容放在局部栈空间中。
而vm操作码也基本模仿我们的汇编指令也基本。

后续b中vm代码初始化和从中vm的指令handler表初始化指令都比较有规律,我们可以编写脚本提取出来做后续加工分析
后续的加工分析主要是vm指令反编译,即可反编译出vm代码的逻辑功能,参考后续分析。

a.下面是其VM寄存器缓存空间的分配,寄存器都是单字节的
其中
R7为标识flag寄存器,用于存储减和比较结果,
R6随后会初始化为0xFF,属于vm的栈寄存器vm-sp
R4_R5为16位寄存器相当于vm-eip,设为pc
Rxs=[R0,R1,R2,R3,pc:R4_R5,R6,R7]
.text:00401AE3 6A 08                         push    8               ; size_t
.text:00401AE5 E8 81 28 00 00                call    _malloc
.text:00401AEA 83 C4 04                      add     esp, 4
.text:00401AED 89 45 FC                      mov     [ebp+lpMem_Rxs]

b. vm代码初始化
.text:004013DC C6 85 64 FD FE FF 01          mov     [ebp+var_1029C], 1
.text:004013E3 C6 85 65 FD FE FF 00          mov     [ebp+var_1029B], 0
.text:004013EA C6 85 66 FD FE FF 02          mov     [ebp+var_1029A], 2
.text:004013F1 C6 85 67 FD FE FF 00          mov     [ebp+var_10299], 0
.text:004013F8 C6 85 68 FD FE FF 03          mov     [ebp+var_10298], 3
...//省略代码
.text:00401ACE C6 85 62 FE FE FF 00          mov     [ebp+var_1019E], 0
.text:00401AD5 C6 85 63 FE FE FF 99          mov     [ebp+var_1019D], 99h
.text:00401ADC C6 85 64 FE FE FF 00          mov     [ebp+var_1019C], 0

c. vm的指令handler表初始化
.text:00401AF0 8D 05 01 21 40 00             lea     eax, loc_402101
.text:00401AF6 89 85 70 FE FE FF             mov     [ebp+var_10190], eax
.text:00401AFC 8D 05 2D 21 40 00             lea     eax, loc_40212D
...//省略代码
.text:004020E4 8D 05 44 41 40 00             lea     eax, loc_404144
.text:004020EA 89 85 CC 00 FF FF             mov     [ebp+var_FF34], eax
.text:004020F0 8D 05 A3 41 40 00             lea     eax, loc_4041A3
.text:004020F6 89 85 D0 00 FF FF             mov     [ebp+var_FF30]

3.1 vm代码chip提取和vm的指令handler表提取

a. vm的指令handler表提取
执行后续的#-------之间代码,即可得到vm指令的handler表,
后续即可根据需求之间定位到vm指令地址进行填表操作
格式 vm操作码:["vm操作指令名称","vmhandler地址"]
  0x00:["vm_","4022CE"],#
  0x01:["vm_","402101"],#
  0x02:["vm_","40212D"],#
  ..//省略
  0x98:["vm_","404144"],#
  0x99:["vm_","4041A3"],#

#------- ------- -------
def pickOpTbl(InitTbl_s=0x401AED,InitTbl_e=0x4020FC):
  InitTbl_ea = InitTbl_s
  OpTbl = {}
  while InitTbl_ea < InitTbl_e:
    InitTbl_ea = FindCode(InitTbl_ea,SEARCH_NEXT|SEARCH_DOWN)
    eaasm = GetDisasm(InitTbl_ea)
    if "lea     eax" in eaasm:
      opAddr = int(eaasm.replace("lea     eax, loc_",""),0x10)
      InitTbl_ea = FindCode(InitTbl_ea,SEARCH_NEXT|SEARCH_DOWN)
      eaasm = GetDisasm(InitTbl_ea)
      locoff = int(eaasm[eaasm.index("_")+1:eaasm.index("]")],0x10)
      OpTbl[locoff] = opAddr
  return OpTbl

OpTbl = pickOpTbl()
OffRef = 0x10194
OpOffs = OpTbl.keys()
OpOffs.sort()
OpOffs.reverse()
OpvTbl = {}
for OpOff in OpOffs:
  OpvTbl[(OffRef-OpOff)/4] = OpTbl[OpOff]

for op,opf in OpvTbl.viewitems():
  print '  0x{:02X}:["vm_","{:X}"],#'.format(op,opf)
  #print "{:02X} var:{:X} {:X}".format(op,OffRef-op*4,opf)
#------- ------- -------

b. vm代码chip片段的提取
执行后续的#-------之间代码即可得到vm的代码片段Opcodes
#------- ------- -------
def pickOps(InitOp_s=0x4013DC,InitOp_e=0x401AE3):
  Ops = {}
  opoff = c_long(0)
  for opa in xrange(InitOp_s,InitOp_e,7):
    opoff.value = Dword(opa+2)
    Ops[-opoff.value] = Byte(opa+6)
  return Ops

Ops = pickOps()
OffRef = 0x1029C
OpOffs = Ops.keys()
OpOffs.sort()
OpOffs.reverse()
Opvs = {}
for OpOff in OpOffs:
  Opvs[(OffRef-OpOff)] = Ops[OpOff]

Opcodes = []
for op,opf in Opvs.viewitems():
  print "{:02X} var:{:X} {:X}".format(op,OffRef-op,opf)
  Opcodes.append(opf)
#------- ------- -------
3.2 填完3.1的a中handler表,有了3.1的b在vm代码,就可以直接反编译了
以下是一种反编译框架,带仿真模拟功能,
这里并没有逆向所有vm指令,基本一边反编译一边添加,废话少说,
将后面的#-------直接代码直接复制到IDAPython里编译
Ccs=Opcodes
vm_run(Ccs,0)  #反编译整个vm代码Ccs
#vm_run(Ccs,0,True) #仿真模拟执行
执行vm_run(Ccs,0)不带模拟直接反编译结果如下
pc为Ccs=Opcodes虚拟代码指令chip片段的指令指针,从偏移pc=0开始,0x100结束
op为指令操作码,后紧跟指令对应的handler地址,截至是指令的反编译
指令操作数格式与IA格式相仿。

pc:00 op:01 402101 vm_b_mov_R0_imm8 00 (0)  //mov R0,imm8 后面为"无符号hex值 (有符号hex值)"
pc:02 op:02 40212D vm_b_mov_R1_imm8 00 (0)
pc:04 op:03 40215A vm_b_mov_R2_imm8 00 (0)
---------------------------{其中 var_E004 = 注册码key 执行前在.text 004041D8 call _strcpy处初始化
pc:06 op:96 40408B vm_b_R7_test_sub_RefVarBufR2_R1 R7=(var_E004[R2]-R1)? 1:0
pc:09 op:21 4027A5 vm_jz 13 else 0C
pc:0C op:29 402877 vm_b_add_R0_imm8 01 (01)
pc:0E op:2B 4028DB vm_b_add_R2_imm8 01 (01)
pc:10 op:27 402758 vm_jmp 06
---------------------------} 此断vm循环计算var_E004.key的字符长度,长度结果放于 R0
pc:13 op:81 403ABD vm_b_sub_R0_imm8 14 (14)  
pc:15 op:21 4027A5 vm_jz 19 else 18       //key长度与0x14比较,如果不等则vm_reg_dtor_leave推出
pc:18 op:01 402101 vm_reg_dtor_leave
pc:19 op:01 402101 vm_b_mov_R0_imm8 2E (2E) //var_8004为后半部注册码逐步校验结果缓存区
pc:1B op:12 402401 vm_b_mov_VarX_R0 VarX:8000 var_8004[0]=R0 //当满足条件是会将相应位字节置为0x2E,以便最后检测
pc:1E op:01 402101 vm_b_mov_R0_imm8 63 (63)
pc:20 op:02 40212D vm_b_mov_R1_imm8 09 (9)
pc:22 op:8B 403CE8 vm_b_R7_test_sub_R0_RefVarBufR1 R7=(R0 - var_E004[R1])? 1:0
pc:25 op:21 4027A5 vm_jz 29 else 28    //-------key[0x09] == (R0 = 0x63 = 'c')
pc:28 op:01 402101 vm_reg_dtor_leave
pc:29 op:01 402101 vm_b_mov_R0_imm8 6F (6F)
pc:2B op:2A 4028A8 vm_b_add_R1_imm8 01 (01)
pc:2D op:8B 403CE8 vm_b_R7_test_sub_R0_RefVarBufR1 R7=(R0 - var_E004[R1])? 1:0
pc:30 op:21 4027A5 vm_jz 34 else 33   //-------key[0x0A] == (R0 = 0x6F = 'o')
pc:33 op:01 402101 vm_reg_dtor_leave
pc:34 op:2A 4028A8 vm_b_add_R1_imm8 01 (01)
pc:36 op:8B 403CE8 vm_b_R7_test_sub_R0_RefVarBufR1 R7=(R0 - var_E004[R1])? 1:0
pc:39 op:21 4027A5 vm_jz 3D else 3C  //-------key[0x0B] == (R0 = 0x6F = 'o')
pc:3C op:01 402101 vm_reg_dtor_leave
pc:3D op:01 402101 vm_b_mov_R0_imm8 6C (6C)
pc:3F op:2A 4028A8 vm_b_add_R1_imm8 01 (01)
pc:41 op:8B 403CE8 vm_b_R7_test_sub_R0_RefVarBufR1 R7=(R0 - var_E004[R1])? 1:0
pc:44 op:21 4027A5 vm_jz 48 else 47  //-------key[0x0C] == (R0 = 0x6C = 'l')
pc:47 op:01 402101 vm_reg_dtor_leave
pc:48 op:01 402101 vm_b_mov_R0_imm8 2E (2E)
pc:4A op:03 40215A vm_b_mov_R2_imm8 01 (1)  //比对结果var_8004[1]=0x2E,前面是var_8004[0]=0x2E
pc:4C op:14 402496 vm_b_mov_RefVarBufR2_R0 VarBufAddr:8000 var_8004[R2]=R0
pc:4F op:01 402101 vm_b_mov_R0_imm8 31 (31)
pc:51 op:2A 4028A8 vm_b_add_R1_imm8 01 (01)
pc:53 op:8B 403CE8 vm_b_R7_test_sub_R0_RefVarBufR1 R7=(R0 - var_E004[R1])? 1:0
pc:56 op:21 4027A5 vm_jz 5A else 59  //-------key[0x0D] == (R0 = 0x31 = '1')
pc:59 op:01 402101 vm_reg_dtor_leave
pc:5A op:0B 40222E vm_b_mov_R0_RefVarBufR1 VarBufAddr:2000 R0=var_E004[R1]
pc:5D op:29 402877 vm_b_add_R0_imm8 D0 (-30)
pc:5F op:08 4021C8 vm_b_mov_R2_R0 R2=R0
pc:60 op:45 402F39 vm_b_imul_R0_R2 R0*=R2
pc:61 op:45 402F39 vm_b_imul_R0_R2 R0*=R2
pc:62 op:1B 402665 vm_b_push_R0    //-------R0 = dn3 = pown(key[0x0D]-0x30),立方,压栈
pc:63 op:2A 4028A8 vm_b_add_R1_imm8 01 (01)
pc:65 op:0B 40222E vm_b_mov_R0_RefVarBufR1 VarBufAddr:2000 R0=var_E004[R1]
pc:68 op:29 402877 vm_b_add_R0_imm8 D0 (-30)
pc:6A op:08 4021C8 vm_b_mov_R2_R0 R2=R0
pc:6B op:45 402F39 vm_b_imul_R0_R2 R0*=R2
pc:6C op:45 402F39 vm_b_imul_R0_R2 R0*=R2
pc:6D op:1B 402665 vm_b_push_R0   //-------R0 = en3 = pown(key[0x0E]-0x30),立方,压栈
pc:6E op:2A 4028A8 vm_b_add_R1_imm8 01 (01)
pc:70 op:0B 40222E vm_b_mov_R0_RefVarBufR1 VarBufAddr:2000 R0=var_E004[R1]
pc:73 op:29 402877 vm_b_add_R0_imm8 D0 (-30)
pc:75 op:08 4021C8 vm_b_mov_R2_R0 R2=R0
pc:76 op:45 402F39 vm_b_imul_R0_R2 R0*=R2
pc:77 op:45 402F39 vm_b_imul_R0_R2 R0*=R2  //-------R0 = fn3 = pown(key[0x0F]-0x30),立方
pc:78 op:1D 4026DE vm_b_pop_R2             // R2 = en3
pc:79 op:2D 402923 vm_b_add_R0_R2          // R0 = R0 + R2 = fn3 + en3
pc:7A op:1D 4026DE vm_b_pop_R2             // R2 = dn
pc:7B op:2D 402923 vm_b_add_R0_R2          // R0 = R0 + R2 = fn3 + en3 + dn3
pc:7C op:1B 402665 vm_b_push_R0            //压栈 def3 = fn3 + en3 + dn3
pc:7D op:02 40212D vm_b_mov_R1_imm8 0D (D)
pc:7F op:0B 40222E vm_b_mov_R0_RefVarBufR1 VarBufAddr:2000 R0=var_E004[R1]
pc:82 op:29 402877 vm_b_add_R0_imm8 D0 (-30)
pc:84 op:41 402E89 vm_b_imul_R0_imm8 64 (64)
pc:86 op:2A 4028A8 vm_b_add_R1_imm8 01 (01)
pc:88 op:11 4023B0 vm_b_mov_R2_RefVarBufR1 VarBufAddr:2000 R2=var_E004[R1]
pc:8B op:2B 4028DB vm_b_add_R2_imm8 D0 (-30)
pc:8D op:43 402EEF vm_b_imul_R2_imm8 0A (0A)
pc:8F op:2D 402923 vm_b_add_R0_R2
pc:90 op:2A 4028A8 vm_b_add_R1_imm8 01 (01)
pc:92 op:11 4023B0 vm_b_mov_R2_RefVarBufR1 VarBufAddr:2000 R2=var_E004[R1]
pc:95 op:2B 4028DB vm_b_add_R2_imm8 D0 (-30)//相当于三位数字符转为十进制数值
pc:97 op:2D 402923 vm_b_add_R0_R2           // R0 = int(key[0x0D~0x0F],0x0A)
pc:98 op:1D 4026DE vm_b_pop_R2              //出栈R2 = def3 = fn3 + en3 + dn3
pc:99 op:85 403BE6 vm_b_R7_test_sub_R0_R2 //即要求 key[0x0D~0x0F] 三位十进制的值等于各位数的立方和,
pc:9A op:21 4027A5 vm_jz 9E else 9D       //其整个三位数的高位key[0x0D]="1"
pc:9D op:01 402101 vm_reg_dtor_leave
pc:9E op:01 402101 vm_b_mov_R0_imm8 2E (2E)
pc:A0 op:03 40215A vm_b_mov_R2_imm8 02 (2)  //比对结果var_8004[2]=0x2E
pc:A2 op:14 402496 vm_b_mov_RefVarBufR2_R0 VarBufAddr:8000 var_8004[R2]=R0
pc:A5 op:2A 4028A8 vm_b_add_R1_imm8 01 (01)
pc:A7 op:0B 40222E vm_b_mov_R0_RefVarBufR1 VarBufAddr:2000 R0=var_E004[R1]
pc:AA op:29 402877 vm_b_add_R0_imm8 D0 (-30)
pc:AC op:41 402E89 vm_b_imul_R0_imm8 0A (0A)
pc:AE op:2A 4028A8 vm_b_add_R1_imm8 01 (01)
pc:B0 op:11 4023B0 vm_b_mov_R2_RefVarBufR1 VarBufAddr:2000 R2=var_E004[R1]
pc:B3 op:2B 4028DB vm_b_add_R2_imm8 D0 (-30)
pc:B5 op:2D 402923 vm_b_add_R0_R2         
pc:B6 op:1B 402665 vm_b_push_R0         //压栈 x = int(key[0x10:0x11],0x0A)
pc:B7 op:2A 4028A8 vm_b_add_R1_imm8 01 (01)
pc:B9 op:11 4023B0 vm_b_mov_R2_RefVarBufR1 VarBufAddr:2000 R2=var_E004[R1]
pc:BC op:2B 4028DB vm_b_add_R2_imm8 D0 (-30)
pc:BE op:43 402EEF vm_b_imul_R2_imm8 0A (0A)
pc:C0 op:2A 4028A8 vm_b_add_R1_imm8 01 (01)
pc:C2 op:0B 40222E vm_b_mov_R0_RefVarBufR1 VarBufAddr:2000 R0=var_E004[R1]
pc:C5 op:29 402877 vm_b_add_R0_imm8 D0 (-30)
pc:C7 op:30 402965 vm_b_add_R2_R0       //R2 = y = int(key[0x12:0x13],0x0A)
pc:C8 op:1E 4026B5 vm_b_pop_R1          //出栈 R1 = x
pc:C9 op:04 402187 vm_b_mov_R0_R1
pc:CA op:2D 402923 vm_b_add_R0_R2       //R0 = x + y
pc:CB op:42 402EBA vm_b_imul_R1_imm8 04 (04)  //R1 = R1 * 4 = x * 4
pc:CD op:43 402EEF vm_b_imul_R2_imm8 02 (02)  //R2 = R2 * 2 = y * 2
pc:CF op:2F 40294E vm_b_add_R1_R2             //R1 = R1 + R2 = 4x+2y
pc:D0 op:81 403ABD vm_b_sub_R0_imm8 23 (23)
pc:D2 op:26 40280E vm_jnz E4 else D5   //R0 - 0x23 = 0 >>得到  x+y=0x23
pc:D5 op:82 403B14 vm_b_cmp_R1_imm8 5E (5E)
pc:D7 op:26 40280E vm_jnz E4 else DA   //R1 - 0x5E = 0 >>得到 4x+2y=0x5E
pc:DA op:01 402101 vm_b_mov_R0_imm8 2E (2E)
pc:DC op:03 40215A vm_b_mov_R2_imm8 03 (3) //比对结果var_8004[3]=0x2E
pc:DE op:14 402496 vm_b_mov_RefVarBufR2_R0 VarBufAddr:8000 var_8004[R2]=R0
pc:E1 op:27 402758 vm_jmp E5
pc:E4 op:01 402101 vm_reg_dtor_leave
pc:E5 op:02 40212D vm_b_mov_R1_imm8 00 (0)
pc:E7 op:01 402101 vm_b_mov_R0_imm8 00 (0)
pc:E9 op:03 40215A vm_b_mov_R2_imm8 2E (2E)
---------------------------{var_8004[0,1,2,3]是否都等于0x2E,
pc:EB op:98 404144 vm_b_R7_test_sub_RefVarBufR1_R2 R7=(var_8004[R1]-R2)? 1:0
pc:EE op:26 40280E vm_jnz F3 else F1
pc:F1 op:29 402877 vm_b_add_R0_imm8 01 (01)
pc:F3 op:2A 4028A8 vm_b_add_R1_imm8 01 (01)
pc:F5 op:82 403B14 vm_b_cmp_R1_imm8 04 (04)
pc:F7 op:26 40280E vm_jnz EB else FA
---------------------------}如果都等则显示成功 vm_MsgBox_Success,否则退出
pc:FA op:81 403ABD vm_b_sub_R0_imm8 04 (04)
pc:FC op:26 40280E vm_jnz 100 else FF
pc:FF op:99 4041A3 vm_MsgBox_Success
pc:100 op:01 402101 vm_reg_dtor_leave

综上vm代码的解释我们可以得到注册码后半部分的边界条件

a. key[0x09~0x0C] = "cool"
key[0x09] == (R0 = 0x63 = 'c')
key[0x0A] == (R0 = 0x6F = 'o')
key[0x0B] == (R0 = 0x6F = 'o')
key[0x0C] == (R0 = 0x6C = 'l')

b. key[0x0D~0x0F] = "153"
dn = key[0x0D] = '1'
en = key[0x0E]
fn = key[0x0F]
根据三位十进制的值等于各位数的立方和,通过下面的python代码我们可以枚举到
满足条件的三位数 000,001,153,370,371,407
由于最高位为"1",所以只能是"153"
nstr = "0123456789"
for dn in nstr:
  for en in nstr:
    for fn in nstr:
      defn = int(dn+en+fn,0x0A)
      def3 = pow(int(dn,0x0A),3)
      def3 += pow(int(en,0x0A),3)
      def3 += pow(int(fn,0x0A),3)
      if defn == def3:
        print dn+en+fn

c. key[0x10~0x13] = "1223"
x = key[0x10~0x11]
y = key[0x12~0x13]
vm代码确定的方程组为
    x+y=0x23
    4x+2y=0x5E
解方程组得到
  x=12,y=23

即我们可以得到注册码的后半部分为vmKey="cool1531223"
结合前半部分 xsmKey = "pediy2016"
则注册码为 key = xsmKey + vmKey = "pediy2016cool1531223"

3.3 ASM-VM反编译代码
#------- ------- ------- ------- ------- ------- -------
#Rxs,lvc只在仿真模拟时才使用,这里提供的是正确的注册码
#可以考虑提供非正确的注册码,仿真类似于Trace指令
Rxs = [0,0,0,0,0,0,0xFF,0,]
lvc = { #LocalVarCache
0xE004:ord("p"),
0xE003:ord("e"),
0xE002:ord("d"),
0xE001:ord("i"),
0xE000:ord("y"),
0xDFFF:ord("2"),
0xDFFE:ord("0"),
0xDFFD:ord("1"),
0xDFFC:ord("6"),
0xDFFB:ord("c"),
0xDFFA:ord("o"),
0xDFF9:ord("o"),
0xDFF8:ord("l"),
0xDFF7:ord("1"),
0xDFF6:ord("5"),
0xDFF5:ord("3"),
0xDFF4:ord("1"),
0xDFF3:ord("2"),
0xDFF2:ord("2"),
0xDFF1:ord("3"),
0xDFF0:ord("\0")
}

VMHandler = {
  0x00:["vm_reg_dtor_leave","4022CE"],#
  0x01:["vm_b_mov_R0_imm8","402101"],#
  0x02:["vm_b_mov_R1_imm8","40212D"],#
  0x03:["vm_b_mov_R2_imm8","40215A"],#
  0x04:["vm_b_mov_R0_R1","402187"],#
  0x05:["vm_b_mov_R0_R2","402197"],#
  0x06:["vm_b_mov_R1_R0","4021A7"],#
  0x07:["vm_b_mov_R1_R2","4021B7"],#
  0x08:["vm_b_mov_R2_R0","4021C8"],#
  0x09:["vm_b_mov_R2_R1","4021D8"],#
  0x0A:["vm_","4021E9"],#
  0x0B:["vm_b_mov_R0_RefVarBufR1","40222E"],#
  0x0C:["vm_","40227E"],#
  0x0E:["vm_","4022D3"],#
  0x0F:["vm_","402319"],#
  0x10:["vm_","40236A"],#
  0x11:["vm_b_mov_R2_RefVarBufR1","4023B0"],#
  0x12:["vm_b_mov_VarX_R0","402401"],#
  0x13:["vm_","402446"],#
  0x14:["vm_b_mov_RefVarBufR2_R0","402496"],#
  0x15:["vm_","4024E6"],#
  0x16:["vm_","40252C"],#
  0x17:["vm_","40257D"],#
  0x18:["vm_","4025C3"],#
  0x19:["vm_","402614"],#
  0x1A:["vm_","40263D"],#
  0x1B:["vm_b_push_R0","402665"],#vm_b_mov_RefVarBufR6_R0
  0x1C:["vm_b_pop_R0","40268D"],#vm_b_mov_R0_RefVarBufR6
  0x1D:["vm_b_pop_R2","4026DE"],#vm_b_mov_R2_RefVarBufR6
  0x1E:["vm_b_pop_R1","4026B5"],#vm_b_mov_R1_RefVarBufR6
  0x1F:["vm_","402706"],#
  0x20:["vm_","40272F"],#
  0x21:["vm_jz","4027A5"],#
  0x26:["vm_jnz","40280E"],#
  0x27:["vm_jmp","402758"],#
  0x28:["vm_","4027A0"],#
  0x29:["vm_b_add_R0_imm8","402877"],#
  0x2A:["vm_b_add_R1_imm8","4028A8"],#
  0x2B:["vm_b_add_R2_imm8","4028DB"],#
  0x2C:["vm_b_add_R0_R1","40290E"],#
  0x2D:["vm_b_add_R0_R2","402923"],#
  0x2E:["vm_b_add_R1_R0","402938"],#
  0x2F:["vm_b_add_R1_R2","40294E"],#
  0x30:["vm_b_add_R2_R0","402965"],#
  0x31:["vm_b_add_R2_R1","40297B"],#
  0x32:["vm_","402992"],#
  0x33:["vm_","4029DC"],#
  0x34:["vm_","402A31"],#
  0x35:["vm_","402A86"],#
  0x36:["vm_","402AD2"],#
  0x37:["vm_","402B29"],#
  0x38:["vm_","402B75"],#
  0x39:["vm_","402BCC"],#
  0x3A:["vm_","402C23"],#
  0x3B:["vm_","402C90"],#
  0x3C:["vm_","402CFD"],#
  0x3D:["vm_","402D55"],#
  0x3E:["vm_","402DC3"],#
  0x3F:["vm_","402E1B"],#
  0x41:["vm_b_imul_R0_imm8","402E89"],#
  0x42:["vm_b_imul_R1_imm8","402EBA"],#
  0x43:["vm_b_imul_R2_imm8","402EEF"],#
  0x44:["vm_","402F24"],#
  0x45:["vm_b_imul_R0_R2","402F39"],#
  0x46:["vm_","402F4E"],#
  0x47:["vm_","402F64"],#
  0x48:["vm_","402F7B"],#
  0x49:["vm_","402F91"],#
  0x4A:["vm_","402FA8"],#
  0x4B:["vm_","402FF2"],#
  0x4C:["vm_","403049"],#
  0x4E:["vm_","4030A0"],#
  0x4F:["vm_","4030EE"],#
  0x50:["vm_","403147"],#
  0x51:["vm_","403195"],#
  0x52:["vm_","4031EE"],#
  0x53:["vm_","403245"],#
  0x54:["vm_","4032B2"],#
  0x55:["vm_","40331F"],#
  0x56:["vm_","403377"],#
  0x57:["vm_","4033E5"],#
  0x58:["vm_","40343D"],#
  0x61:["vm_","4034AB"],#
  0x62:["vm_","4034DC"],#
  0x63:["vm_","40350F"],#
  0x64:["vm_","403542"],#
  0x65:["vm_","403557"],#
  0x66:["vm_","40356C"],#
  0x67:["vm_","403582"],#
  0x68:["vm_","403599"],#
  0x69:["vm_","4035AF"],#
  0x6A:["vm_","4035C6"],#
  0x6B:["vm_","403610"],#
  0x6C:["vm_","403665"],#
  0x6E:["vm_","4036BA"],#
  0x6F:["vm_","403706"],#
  0x70:["vm_","40375D"],#
  0x71:["vm_","4037A9"],#
  0x72:["vm_","403800"],#
  0x73:["vm_","403857"],#
  0x74:["vm_","4038C4"],#
  0x75:["vm_","403931"],#
  0x76:["vm_","403989"],#
  0x77:["vm_","4039F7"],#
  0x78:["vm_","403A4F"],#
  0x81:["vm_b_sub_R0_imm8","403ABD"],#
  0x82:["vm_b_cmp_R1_imm8","403B14"],#
  0x83:["vm_b_sub_R2_imm8","403B6C"],#
  0x84:["vm_","403BC4"],#
  0x85:["vm_b_R7_test_sub_R0_R2","403BE6"],#
  0x86:["vm_","403C08"],#
  0x87:["vm_","403C2A"],#
  0x88:["vm_","403C4D"],#
  0x89:["vm_","403C6F"],#
  0x8A:["vm_","403C92"],#
  0x8B:["vm_b_R7_test_sub_R0_RefVarBufR1","403CE8"],#
  0x8C:["vm_","403D49"],#
  0x8E:["vm_","403DAA"],#
  0x8F:["vm_","403E01"],#
  0x90:["vm_","403E63"],#
  0x91:["vm_","403EBA"],#
  0x92:["vm_","403F1C"],#
  0x93:["vm_","403F72"],#
  0x94:["vm_","403FD3"],#
  0x95:["vm_","404034"],#
  0x96:["vm_b_R7_test_sub_RefVarBufR2_R1","40408B"],#
  0x97:["vm_","4040ED"],#
  0x98:["vm_b_R7_test_sub_RefVarBufR1_R2","404144"],#
  0x99:["vm_MsgBox_Success","4041A3"],#
}

def vm_run(code_chip = [],pc = 0,bSimTrace=False):
  globals()['bSimTrace'] = bSimTrace
  Rxs[6]=0xFF
  pc_end = code_chip.__len__()
  while pc < pc_end:
    pc = vm_dispatch(pc,bSimTrace)
    if not pc:
      break

def vm_dispatch(pc=0,bSimTrace=False):
  op = Ccs[pc]
  if op in VMHandler:
    try:
      pc = globals()[VMHandler[op][0]](pc+1,bSimTrace)
      return pc
    except KeyError as er:
      print """def {}(pc): #{}
  npc = pc+1
  Rx = Ccs[pc]
  trace_tips(0x{:02X},pc,npc,"".format())
  return npc

""".format(VMHandler[op][0],VMHandler[op][1],op)
      return None
  else:
    print "op:{:02X} of pc:{:02X} is not vm code".format(op,pc)
    return None

def trace_tips(op,pc,npc,tips):
  bSimTrace = globals()["bSimTrace"]
  if bSimTrace:
    print "pc:{:02X} npc:{:02X} op:{:02X} {} {}".format(pc-1,npc,op,VMHandler[op][1],tips)
  else:
    print "pc:{:02X} op:{:02X} {} {}".format(pc-1,op,VMHandler[op][1],tips)

def vm_get_imm16_u(pc):
  return c_ushort((Ccs[pc+1] << 8)|Ccs[pc]).value

def vm_get_imm16_s(pc):
  return c_short((Ccs[pc+1] << 8)|Ccs[pc]).value

def vm_set_R7_flag(ResultVal):
  if ResultVal:
    Rxs[7] = 1
  else:
    Rxs[7] = 0

def vm_get_lvc(VarAddr):
  if VarAddr <= 0xFF:
    pass
  else:
    VarAddr = 0x10004-VarAddr
  if VarAddr in lvc:
    return lvc[VarAddr]
  else:
    #raise Exception("VarAddr {:X} not in lvc".format(VarAddr))
    print ("VarAddr {:X} is not given in lvc, default 0x00".format(VarAddr))
    return 0

def vm_set_lvc(VarAddr,Val):
  if VarAddr <= 0xFF:
    pass
  else:
    VarAddr = 0x10004-VarAddr
  lvc[VarAddr]=Val
  print "lvc[{:X}] = {:X}".format(VarAddr,Val)

def vm_reg_dtor_leave(pc = 0,bSimTrace = False): #402101
  npc = pc
  trace_tips(0x01,pc,npc,"vm_reg_dtor_leave")
  #raise Exception("-------Chip End-------")
  return npc

def vm_b_mov_R0_imm8(pc = 0,bSimTrace = False): #402101
  npc = pc+1
  Rx = Ccs[pc]
  if bSimTrace:
    Rxs[0]=Rx
  trace_tips(0x01,pc,npc,"vm_b_mov_R0_imm8 {:02X} ({:X})".format(Rx,c_byte(Rx).value))
  return npc

def vm_b_mov_R1_imm8(pc = 0,bSimTrace = False): #40212D
  npc = pc+1
  Rx = Ccs[pc]
  if bSimTrace:
    Rxs[1]=Rx
  trace_tips(0x02,pc,npc,"vm_b_mov_R1_imm8 {:02X} ({:X})".format(Rx,c_byte(Rx).value))
  return npc

def vm_b_mov_R2_imm8(pc = 0,bSimTrace = False): #40215A
  npc = pc+1
  Rx = Ccs[pc]
  if bSimTrace:
    Rxs[2]=Rx
  trace_tips(0x03,pc,npc,"vm_b_mov_R2_imm8 {:02X} ({:X})".format(Rx,c_byte(Rx).value))
  return npc

def vm_b_mov_R0_R1(pc = 0,bSimTrace = False): #402187
  npc = pc
  if bSimTrace:
    Rxs[0] = Rxs[1]
  trace_tips(0x04,pc,npc,"vm_b_mov_R0_R1".format())
  return npc

def vm_b_mov_R0_R2(pc = 0,bSimTrace = False): #402197
  npc = pc
  if bSimTrace:
    Rxs[0] = Rxs[2]
  trace_tips(0x05,pc,npc,"vm_b_mov_R0_R2".format())
  return npc

def vm_b_mov_R1_R0(pc = 0,bSimTrace = False): #4021A7
  npc = pc
  if bSimTrace:
    Rxs[1] = Rxs[0]
  trace_tips(0x06,pc,npc,"vm_b_mov_R1_R0".format())
  return npc

def vm_b_mov_R1_R2(pc = 0,bSimTrace = False): #4021B7
  npc = pc
  if bSimTrace:
    Rxs[1] = Rxs[2]
  trace_tips(0x07,pc,npc,"vm_b_mov_R1_R2".format())
  return npc

def vm_b_mov_R2_R0(pc = 0,bSimTrace = False): #4021C8
  npc = pc
  if bSimTrace:
    Rxs[2] = Rxs[0]
  trace_tips(0x08,pc,npc,"vm_b_mov_R2_R0".format())
  return npc

def vm_b_mov_R2_R1(pc = 0,bSimTrace = False): #4021D8
  npc = pc
  if bSimTrace:
    Rxs[2] = Rxs[1]
  trace_tips(0x09,pc,npc,"vm_b_mov_R2_R1".format())
  return npc

def vm_b_R7_test_sub_RefVarBufR2_R1(pc = 0,bSimTrace = False): #40408B
  npc = pc+2
  RefVarOff = vm_get_imm16_u(pc)
  if bSimTrace:
    vm_set_R7_flag(vm_get_lvc(RefVarOff+Rxs[2])-Rxs[1])
  trace_tips(0x96,pc,npc,"vm_b_R7_test_sub_RefVarBufR2_R1 R7=(var_{:X}[R2]-R1)? 1:0 ".format(0x10004-RefVarOff))
  return npc

def vm_b_R7_test_sub_RefVarBufR1_R2(pc = 0,bSimTrace = False): #404144
  npc = pc+2
  RefVarOff = vm_get_imm16_u(pc)
  if bSimTrace:
    vm_set_R7_flag(vm_get_lvc(RefVarOff+Rxs[1])-Rxs[2])
  trace_tips(0x98,pc,npc,"vm_b_R7_test_sub_RefVarBufR1_R2 R7=(var_{:X}[R1]-R2)? 1:0 ".format(0x10004-RefVarOff))
  return npc

from ctypes import *
def vm_MsgBox_Success(pc = 0,bSimTrace = False): #4041A3
  npc = pc
  if bSimTrace:
    windll.user32.MessageBoxA(0,"Sucess!","Sucess!",0)
  trace_tips(0x99,pc,npc,"vm_MsgBox_Success".format())
  return npc

def vm_jz(pc = 0,bSimTrace = False): #4027A5
  npc = pc
  #
  skip_jmp_npc = pc+2
  #
  off = vm_get_imm16_s(pc)
  jmp_npc = pc-1
  jmp_npc += off
  #
  if bSimTrace:
    if Rxs[7]:#NZ skip jmp
      npc = skip_jmp_npc
    else: #Z jmp
      npc = jmp_npc
  else:
    npc = skip_jmp_npc
  trace_tips(0x21,pc,npc,"vm_jz {:02X} else {:02X}".format(jmp_npc,skip_jmp_npc))
  return npc

def vm_jnz(pc = 0,bSimTrace = False): #40280E
  npc = pc
  #
  skip_jmp_npc = pc+2
  #
  off = vm_get_imm16_s(pc)
  jmp_npc = pc-1
  jmp_npc += off
  #
  if bSimTrace:
    if not Rxs[7]:#Z skip jmp
      npc = skip_jmp_npc
    else: #NZ jmp
      npc = jmp_npc
  else:
    npc = skip_jmp_npc
  trace_tips(0x26,pc,npc,"vm_jnz {:02X} else {:02X}".format(jmp_npc,skip_jmp_npc))
  return npc
  #return skip_jmp_npc
  #return npc ******* ******* *******

def vm_b_add_R0_imm8(pc = 0,bSimTrace = False): #402877
  npc = pc+1
  imm8 = Ccs[pc]
  if bSimTrace:
    Rxs[0]+=c_byte(imm8).value
  trace_tips(0x29,pc,npc,"vm_b_add_R0_imm8 {:02X} ({:02X})".format(imm8,c_byte(imm8).value))
  return npc

def vm_b_add_R1_imm8(pc = 0,bSimTrace = False): #4028A8
  npc = pc+1
  imm8 = Ccs[pc]
  if bSimTrace:
    Rxs[1]+=c_byte(imm8).value
  trace_tips(0x2A,pc,npc,"vm_b_add_R1_imm8 {:02X} ({:02X})".format(imm8,c_byte(imm8).value))
  return npc

def vm_b_add_R2_imm8(pc = 0,bSimTrace = False): #4028DB
  npc = pc+1
  imm8 = Ccs[pc]
  if bSimTrace:
    Rxs[2]+=c_byte(imm8).value
  trace_tips(0x2B,pc,npc,"vm_b_add_R2_imm8 {:02X} ({:02X})".format(imm8,c_byte(imm8).value))
  return npc

def vm_jmp(pc = 0,bSimTrace = False): #402758
  off = vm_get_imm16_s(pc)
  jmp_npc = pc-1
  jmp_npc += off
  if bSimTrace:
    npc = jmp_npc
  else:
    skip_jmp_npc = pc+2
    npc = skip_jmp_npc
  trace_tips(0x27,pc,npc,"vm_jmp {:02X}".format(jmp_npc))
  return npc

def vm_b_sub_R0_imm8(pc = 0,bSimTrace = False): #403ABD
  npc = pc+1
  imm8 = Ccs[pc]
  if bSimTrace:
    #print "R0={:02X}".format(Rxs[0])
    Rxs[0]-=imm8
    vm_set_R7_flag(Rxs[0])
  trace_tips(0x81,pc,npc,"vm_b_sub_R0_imm8 {:02X} ({:02X})".format(imm8,c_byte(imm8).value))
  return npc

def vm_b_cmp_R1_imm8(pc = 0,bSimTrace = False): #403B14
  npc = pc+1
  imm8 = Ccs[pc]
  if bSimTrace:
    #Rxs[1]-=imm8 not given back to Rxs[1]
    vm_set_R7_flag(Rxs[1]-imm8)
  trace_tips(0x82,pc,npc,"vm_b_cmp_R1_imm8 {:02X} ({:02X})".format(imm8,c_byte(imm8).value))
  return npc

def vm_b_sub_R2_imm8(pc = 0,bSimTrace = False): #403B6C
  npc = pc+1
  imm8 = Ccs[pc]
  if bSimTrace:
    Rxs[2]-=imm8
    vm_set_R7_flag(Rxs[2])
  trace_tips(0x83,pc,npc,"vm_b_sub_R2_imm8 {:02X} ({:02X})".format(imm8,c_byte(imm8).value))
  return npc

def vm_b_mov_VarX_R0(pc = 0,bSimTrace = False): #402401
  npc = pc+2
  VarAddr = vm_get_imm16_u(pc)
  if bSimTrace:
    vm_set_lvc(VarAddr,Rxs[0])
  trace_tips(0x12,pc,npc,"vm_b_mov_VarX_R0 VarX:{:X} var_{:X}[0]=R0".format(VarAddr,0x10004-VarAddr))
  return npc

def vm_b_R7_test_sub_R0_RefVarBufR1(pc = 0,bSimTrace = False): #403CE8
  npc = pc+2
  VarAddr = vm_get_imm16_u(pc)
  if bSimTrace:
    Rxs[0] -= vm_get_lvc(VarAddr)
    vm_set_R7_flag(Rxs[0])
  trace_tips(0x8B,pc,npc,"vm_b_R7_test_sub_R0_RefVarBufR1 R7=(R0 - var_{:X}[R1])? 1:0 ".format(0x10004-VarAddr))
  return npc

def vm_b_mov_RefVarBufR2_R0(pc = 0,bSimTrace = False): #402496
  npc = pc+2
  VarBufAddr = vm_get_imm16_u(pc)
  if bSimTrace:
    VarBufXAddr = VarBufAddr + Rxs[2]
    vm_set_lvc(VarBufXAddr,Rxs[0])
  trace_tips(0x14,pc,npc,"vm_b_mov_RefVarBufR2_R0 VarBufAddr:{:X} var_{:X}[R2]=R0".format(VarBufAddr,0x10004-VarBufAddr))
  return npc

def vm_b_mov_R0_RefVarBufR1(pc = 0,bSimTrace = False): #40222E
  npc = pc+2
  VarBufAddr = vm_get_imm16_u(pc)
  if bSimTrace:
    VarBufXAddr = VarBufAddr + Rxs[1]
    Rxs[0] = vm_get_lvc(VarBufXAddr)
  trace_tips(0x0B,pc,npc,"vm_b_mov_R0_RefVarBufR1 VarBufAddr:{:X} R0=var_{:X}[R1]".format(VarBufAddr,0x10004-VarBufAddr))
  return npc

def vm_b_mov_R2_R0(pc = 0,bSimTrace = False): #4021C8
  npc = pc
  if bSimTrace:
    Rxs[2] = Rxs[0]
  trace_tips(0x08,pc,npc,"vm_b_mov_R2_R0 R2=R0".format())
  return npc

def vm_b_imul_R0_R2(pc = 0,bSimTrace = False): #402F39
  npc = pc
  if bSimTrace:
    Rxs[0] = c_ubyte(Rxs[0] * Rxs[2]).value
  trace_tips(0x45,pc,npc,"vm_b_imul_R0_R2 R0*=R2".format())
  return npc

def vm_b_push_R0(pc = 0,bSimTrace = False): #402665
  npc = pc
  if bSimTrace:
    vm_set_lvc(Rxs[6],Rxs[0])
    VarBufXAddr = Rxs[6]
    Rxs[6] -= 1
    trace_tips(0x1B,pc,npc,"vm_b_push_R0 VarXAddr:{:X} var_{:X}=R0".format(VarBufXAddr,0xFF04-c_ubyte(VarBufXAddr).value))
  else:
    trace_tips(0x1B,pc,npc,"vm_b_push_R0".format())
  return npc

def vm_b_pop_R0(pc = 0,bSimTrace = False): #40268D
  npc = pc
  if bSimTrace:
    Rxs[6] += 1
    VarBufXAddr = Rxs[6]
    Rxs[0] = vm_get_lvc(VarBufXAddr)
    trace_tips(0x1C,pc,npc,"vm_b_pop_R0 VarXAddr:{:X} R2=var_{:X}".format(VarBufXAddr,0xFF04-c_ubyte(VarBufXAddr).value))
  else:
    trace_tips(0x1C,pc,npc,"vm_b_pop_R0".format())
  return npc

def vm_b_pop_R2(pc = 0,bSimTrace = False): #4026DE
  npc = pc
  if bSimTrace:
    Rxs[6] += 1
    VarBufXAddr = Rxs[6]
    Rxs[2] = vm_get_lvc(VarBufXAddr)
    trace_tips(0x1D,pc,npc,"vm_b_pop_R2 VarXAddr:{:X} R2=var_{:X}".format(VarBufXAddr,0xFF04-c_ubyte(VarBufXAddr).value))
  else:
    trace_tips(0x1D,pc,npc,"vm_b_pop_R2".format())
  return npc

def vm_b_pop_R1(pc = 0,bSimTrace = False): #4026B5
  npc = pc
  if bSimTrace:
    Rxs[6] += 1
    VarBufXAddr = Rxs[6]
    Rxs[1] = vm_get_lvc(VarBufXAddr)
    trace_tips(0x1E,pc,npc,"vm_b_pop_R1 VarXAddr:{:X} R2=var_{:X}".format(VarBufXAddr,0xFF04-c_ubyte(VarBufXAddr).value))
  else:
    trace_tips(0x1E,pc,npc,"vm_b_pop_R1".format())
  return npc

def vm_b_add_R0_R1(pc = 0,bSimTrace = False): #40290E
  npc = pc
  if bSimTrace:
    Rxs[0]+=Rxs[1]
  trace_tips(0x2C,pc,npc,"vm_b_add_R0_R1".format())
  return npc

def vm_b_add_R0_R2(pc = 0,bSimTrace = False): #402923
  npc = pc
  if bSimTrace:
    Rxs[0]+=Rxs[2]
  trace_tips(0x2D,pc,npc,"vm_b_add_R0_R2".format())
  return npc

def vm_b_add_R1_R0(pc = 0,bSimTrace = False): #402938
  npc = pc
  if bSimTrace:
    Rxs[1]+=Rxs[0]
  trace_tips(0x2E,pc,npc,"vm_b_add_R1_R0".format())
  return npc

def vm_b_add_R1_R2(pc = 0,bSimTrace = False): #40294E
  npc = pc
  if bSimTrace:
    Rxs[1]+=Rxs[2]
  trace_tips(0x2F,pc,npc,"vm_b_add_R1_R2".format())
  return npc

def vm_b_add_R2_R0(pc = 0,bSimTrace = False): #402965
  npc = pc
  if bSimTrace:
    #print "R2={:02X},R0={:02X}".format(Rxs[2],Rxs[0])
    Rxs[2]+=Rxs[0]
  trace_tips(0x30,pc,npc,"vm_b_add_R2_R0".format())
  return npc

def vm_b_add_R2_R1(pc = 0,bSimTrace = False): #40297B
  npc = pc
  if bSimTrace:
    Rxs[2]+=Rxs[1]
  trace_tips(0x31,pc,npc,"vm_b_add_R2_R1".format())
  return npc

def vm_b_imul_R0_imm8(pc = 0,bSimTrace = False): #402E89
  npc = pc + 1
  imm8 = Ccs[pc]
  if bSimTrace:
    Rxs[0]*=imm8
  trace_tips(0x41,pc,npc,"vm_b_imul_R0_imm8 {:02X} ({:02X})".format(imm8,c_byte(imm8).value))
  return npc

def vm_b_imul_R1_imm8(pc = 0,bSimTrace = False): #402EBA
  npc = pc + 1
  imm8 = Ccs[pc]
  if bSimTrace:
    Rxs[1]*=imm8
  trace_tips(0x42,pc,npc,"vm_b_imul_R1_imm8 {:02X} ({:02X})".format(imm8,c_byte(imm8).value))
  return npc

def vm_b_imul_R2_imm8(pc = 0,bSimTrace = False): #402EEF
  npc = pc + 1
  imm8 = Ccs[pc]
  if bSimTrace:
    Rxs[2]*=imm8
  trace_tips(0x43,pc,npc,"vm_b_imul_R2_imm8 {:02X} ({:02X})".format(imm8,c_byte(imm8).value))
  return npc

def vm_b_mov_R2_RefVarBufR1(pc = 0,bSimTrace = False): #4023B0
  npc = pc+2
  VarBufAddr = vm_get_imm16_u(pc)
  VarBufXAddr = VarBufAddr + Rxs[1]
  if bSimTrace:
    Rxs[2] = vm_get_lvc(VarBufXAddr)
  trace_tips(0x11,pc,npc,"vm_b_mov_R2_RefVarBufR1 VarBufAddr:{:X} R2=var_{:X}[R1]".format(VarBufAddr,0x10004-VarBufAddr))
  return npc

def vm_b_R7_test_sub_R0_R2(pc = 0,bSimTrace = False): #403BE6
  npc = pc
  if bSimTrace:
    Rxs[0] -= Rxs[2]
    vm_set_R7_flag(Rxs[0])
  trace_tips(0x85,pc,npc,"vm_b_R7_test_sub_R0_R2".format())
  return npc
#------- ------- ------- ------- ------- ------- -------
3.4
ASM-VM最初的分析模型的所有handlerh列表
sti = StepInfo{ //=malloc(8)
  .00h.Buf
  .04hw.pc
  .06h.spc
}
00 var:10194 4022CE exit
01 var:10190 402101 sti.Buf[0] = var_10004[sti.pc++]
02 var:1018C 40212D sti.Buf[1] = var_10004[sti.pc++]
03 var:10188 40215A sti.Buf[2] = var_10004[sti.pc++]
04 var:10184 402187 sti.Buf[0] = sti.Buf[1]
05 var:10180 402197 sti.Buf[0] = sti.Buf[2]
06 var:1017C 4021A7 sti.Buf[1] = sti.Buf[0]
07 var:10178 4021B7 sti.Buf[1] = sti.Buf[2]
08 var:10174 4021C8 sti.Buf[2] = sti.Buf[0]
09 var:10170 4021D8 sti.Buf[2] = sti.Buf[1]
0A var:1016C 4021E9 w = var_10004[sti.pc++2];sti.Buf[0] = var_10004[w]
0B var:10168 40222E w = var_10004[sti.pc++2];b=sti.Buf[1];sti.Buf[0] = var_10004[w+b]
0C var:10164 40227E w = var_10004[sti.pc++2];b=sti.Buf[2];sti.Buf[0] = var_10004[w+b]
0E var:1015C 4022D3 w = var_10004[sti.pc++2];sti.Buf[1] = var_10004[w]
0F var:10158 402319 w = var_10004[sti.pc++2];b=sti.Buf[2];sti.Buf[1] = var_10004[w+b]
10 var:10154 40236A w = var_10004[sti.pc++2];sti.Buf[2] = var_10004[w]
11 var:10150 4023B0 w = var_10004[sti.pc++2];b=sti.Buf[1];sti.Buf[2] = var_10004[w+b]
12 var:1014C 402401 w = var_10004[sti.pc++2];var_10004[w]=sti.Buf[0]
13 var:10148 402446 w = var_10004[sti.pc++2];b=sti.Buf[1];var_10004[w+b] = sti.Buf[0]
14 var:10144 402496 w = var_10004[sti.pc++2];b=sti.Buf[2];var_10004[w+b] = sti.Buf[0]
15 var:10140 4024E6 w = var_10004[sti.pc++2];var_10004[w] = sti.Buf[1]
16 var:1013C 40252C w = var_10004[sti.pc++2];b=sti.Buf[2];sti.var_10004[w+b] = Buf[1]
17 var:10138 40257D w = var_10004[sti.pc++2];var_10004[w] = sti.Buf[2]
18 var:10134 4025C3 w = var_10004[sti.pc++2];b=sti.Buf[1];var_10004[w+b] = sti.Buf[2]
19 var:10130 402614 var_FF04[sti.spc--] = sti.Buf[1]
1A var:1012C 40263D var_FF04[sti.spc--] = sti.Buf[2]
1B var:10128 402665 var_FF04[sti.spc--] = sti.Buf[0]
1C var:10124 40268D sti.Buf[0] = var_FF04[++sti.spc]
1D var:10120 4026DE sti.Buf[2] = var_FF04[++sti.spc]
1E var:1011C 4026B5 sti.Buf[1] = var_FF04[++sti.spc]
1F var:10118 402706 var_FF04[sti.spc--] = sti.Buf[7]
20 var:10114 40272F sti.Buf[7] = var_FF04[++sti.spc]
21 var:10110 4027A5 sti.Buf[7].al? sti.pc++2:(w1=var_10004[sti.pc--];sti.pc+=w1)
26 var:100FC 40280E sti.Buf[7].al? (w1=var_10004[sti.pc--];sti.pc+=w1):sti.pc++2
27 var:100F8 402758 w1 = var_10004[sti.pc--];sti.pc+=w1
28 var:100F4 4027A0 jmp
29 var:100F0 402877 sti.Buf[0].al+=var_10004[sti.pc++]
2A var:100EC 4028A8 sti.Buf[1].al+=var_10004[sti.pc++]
2B var:100E8 4028DB sti.Buf[2].al+=var_10004[sti.pc++]
2C var:100E4 40290E sti.Buf[0] += sti.Buf[1]
2D var:100E0 402923 sti.Buf[0] += sti.Buf[2]
2E var:100DC 402938 sti.Buf[1] += sti.Buf[0]
2F var:100D8 40294E sti.Buf[1] += sti.Buf[2]
30 var:100D4 402965 sti.Buf[2] += sti.Buf[0]
31 var:100D0 40297B sti.Buf[2] += sti.Buf[1]
32 var:100CC 402992 w = var_10004[sti.pc++2];sti.Buf[0].al+=var_10004[w]
33 var:100C8 4029DC w = var_10004[sti.pc++2];b = sti.Buf[1];sti.Buf[0].al+=var_10004[w+b]
34 var:100C4 402A31 w = var_10004[sti.pc++2];b = sti.Buf[2];sti.Buf[0].al+=var_10004[w+b]
35 var:100C0 402A86 w = var_10004[sti.pc++2];sti.Buf[1].al+=var_10004[w]
36 var:100BC 402AD2 w = var_10004[sti.pc++2];b = sti.Buf[2];sti.Buf[1].al+=var_10004[w+b]
37 var:100B8 402B29 w = var_10004[sti.pc++2];sti.Buf[2].al+=var_10004[w]
38 var:100B4 402B75 w = var_10004[sti.pc++2];b = sti.Buf[1];sti.Buf[2].al+=var_10004[w+b]
39 var:100B0 402BCC w = var_10004[sti.pc++2];var_10004[w]+=sti.Buf[0]
3A var:100AC 402C23 w = var_10004[sti.pc++2];b = sti.Buf[1];var_10004[w+b]+=sti.Buf[0]
3B var:100A8 402C90 w = var_10004[sti.pc++2];b = sti.Buf[2];var_10004[w+b]+=sti.Buf[0]
3C var:100A4 402CFD w = var_10004[sti.pc++2];var_10004[w]+=sti.Buf[1]
3D var:100A0 402D55 w = var_10004[sti.pc++2];b = sti.Buf[2];var_10004[w+b]+=sti.Buf[1]
3E var:1009C 402DC3 w = var_10004[sti.pc++2];var_10004[w]+=sti.Buf[2]
3F var:10098 402E1B w = var_10004[sti.pc++2];b = sti.Buf[1];var_10004[w+b]+=sti.Buf[2]
41 var:10090 402E89 w = var_10004[sti.pc++];sti.Buf[0]*=var_10004[w]
42 var:1008C 402EBA w = var_10004[sti.pc++];sti.Buf[1]*=var_10004[w]
43 var:10088 402EEF w = var_10004[sti.pc++];sti.Buf[2]*=var_10004[w]
44 var:10084 402F24 sti.Buf[0]*=sti.Buf[1]
45 var:10080 402F39 sti.Buf[0]*=sti.Buf[2]
46 var:1007C 402F4E sti.Buf[1]*=sti.Buf[0]
47 var:10078 402F64 sti.Buf[1]*=sti.Buf[2]
48 var:10074 402F7B sti.Buf[2]*=sti.Buf[0]
49 var:10070 402F91 sti.Buf[2]*=sti.Buf[1]
4A var:1006C 402FA8 w = var_10004[sti.pc++2];sti.Buf[0]*=var_10004[w]
4B var:10068 402FF2 w = var_10004[sti.pc++2];b = sti.Buf[1];sti.Buf[0]*=var_10004[w+b]
4C var:10064 403049 w = var_10004[sti.pc++2];b = sti.Buf[2];sti.Buf[0]*=var_10004[w+b]
4E var:1005C 4030A0 w = var_10004[sti.pc++2];sti.Buf[1]*=var_10004[w]
4F var:10058 4030EE w = var_10004[sti.pc++2];b = sti.Buf[2];sti.Buf[1]*=var_10004[w+b]
50 var:10054 403147 w = var_10004[sti.pc++2];sti.Buf[2]*=var_10004[w]
51 var:10050 403195 w = var_10004[sti.pc++2];b = sti.Buf[1];sti.Buf[2]*=var_10004[w+b]
52 var:1004C 4031EE w = var_10004[sti.pc++2];var_10004[w]*=sti.Buf[0]
53 var:10048 403245 w = var_10004[sti.pc++2];b = sti.Buf[1];var_10004[w+b]*=sti.Buf[0]
54 var:10044 4032B2 w = var_10004[sti.pc++2];b = sti.Buf[2];var_10004[w+b]*=sti.Buf[0]
55 var:10040 40331F w = var_10004[sti.pc++2];var_10004[w]*=sti.Buf[1]
56 var:1003C 403377 w = var_10004[sti.pc++2];b = sti.Buf[2];var_10004[w+b]*=sti.Buf[1]
57 var:10038 4033E5 w = var_10004[sti.pc++2];var_10004[w]*=sti.Buf[2]
58 var:10034 40343D w = var_10004[sti.pc++2];b = sti.Buf[1];var_10004[w+b]*=sti.Buf[2]
61 var:10010 4034AB w = var_10004[sti.pc++];sti.Buf[0]^=var_10004[w]
62 var:1000C 4034DC w = var_10004[sti.pc++];sti.Buf[1]^=var_10004[w]
63 var:10008 40350F w = var_10004[sti.pc++];sti.Buf[2]^=var_10004[w]
64 var:10004 403542 sti.Buf[0]^=sti.Buf[1]
65 var:10000 403557 sti.Buf[0]^=sti.Buf[2]
66 var:FFFC 40356C sti.Buf[1]^=sti.Buf[0]
67 var:FFF8 403582 sti.Buf[1]^=sti.Buf[2]
68 var:FFF4 403599 sti.Buf[2]^=sti.Buf[0]
69 var:FFF0 4035AF sti.Buf[2]^=sti.Buf[1]
6A var:FFEC 4035C6 w = var_10004[sti.pc++2];sti.Buf[0]^=var_10004[w]
6B var:FFE8 403610 w = var_10004[sti.pc++2];b = sti.Buf[1];sti.Buf[0]^=var_10004[w+b]
6C var:FFE4 403665 w = var_10004[sti.pc++2];b = sti.Buf[2];sti.Buf[0]^=var_10004[w+b]
6E var:FFDC 4036BA w = var_10004[sti.pc++2];sti.Buf[1]^=var_10004[w]
6F var:FFD8 403706 w = var_10004[sti.pc++2];b = sti.Buf[2];sti.Buf[1]^=var_10004[w+b]
70 var:FFD4 40375D w = var_10004[sti.pc++2];sti.Buf[2]^=var_10004[w]
71 var:FFD0 4037A9 w = var_10004[sti.pc++2];b = sti.Buf[1];sti.Buf[2]^=var_10004[w+b]
72 var:FFCC 403800 w = var_10004[sti.pc++2];var_10004[w]^=sti.Buf[0]
73 var:FFC8 403857 w = var_10004[sti.pc++2];b = sti.Buf[1];var_10004[w+b]^=sti.Buf[0]
74 var:FFC4 4038C4 w = var_10004[sti.pc++2];b = sti.Buf[2];var_10004[w+b]^=sti.Buf[0]
75 var:FFC0 403931 w = var_10004[sti.pc++2];var_10004[w]^=sti.Buf[1]
76 var:FFBC 403989 w = var_10004[sti.pc++2];b = sti.Buf[2];var_10004[w+b]^=sti.Buf[1]
77 var:FFB8 4039F7 w = var_10004[sti.pc++2];var_10004[w]^=sti.Buf[2]
78 var:FFB4 403A4F w = var_10004[sti.pc++2];b = sti.Buf[1];var_10004[w+b]^=sti.Buf[2]
81 var:FF90 403ABD w = var_10004[sti.pc++];sti.Buf[7]=(sti.Buf[0]-=var_10004[w])? 1:0
82 var:FF8C 403B14 w = var_10004[sti.pc++];sti.Buf[7]=(sti.Buf[1]-=var_10004[w])? 1:0
83 var:FF88 403B6C w = var_10004[sti.pc++];sti.Buf[7]=(sti.Buf[2]-=var_10004[w])? 1:0
84 var:FF84 403BC4 sti.Buf[7] = (sti.Buf[0]-sti.Buf[1])? 1:0
85 var:FF80 403BE6 sti.Buf[7] = (sti.Buf[0]-sti.Buf[2])? 1:0
86 var:FF7C 403C08 sti.Buf[7] = (sti.Buf[1]-sti.Buf[0])? 1:0
87 var:FF78 403C2A sti.Buf[7] = (sti.Buf[1]-sti.Buf[2])? 1:0
88 var:FF74 403C4D sti.Buf[7] = (sti.Buf[2]-sti.Buf[0])? 1:0
89 var:FF70 403C6F sti.Buf[7] = (sti.Buf[2]-sti.Buf[1])? 1:0
8A var:FF6C 403C92 w = var_10004[sti.pc++2];sti.Buf[7] = (sti.Buf[0]-var_10004[w])? 1:0
8B var:FF68 403CE8 w = var_10004[sti.pc++2];b = sti.Buf[1];sti.Buf[7] = (sti.Buf[0]-var_10004[w+b])? 1:0
8C var:FF64 403D49 w = var_10004[sti.pc++2];b = sti.Buf[2];sti.Buf[7] = (sti.Buf[0]-var_10004[w+b])? 1:0
8E var:FF5C 403DAA w = var_10004[sti.pc++2];sti.Buf[7] = (sti.Buf[1]-var_10004[w])? 1:0
8F var:FF58 403E01 w = var_10004[sti.pc++2];b = sti.Buf[2];sti.Buf[7] = (sti.Buf[1]-var_10004[w+b])? 1:0
90 var:FF54 403E63 w = var_10004[sti.pc++2];sti.Buf[7] = (sti.Buf[2]-var_10004[w])? 1:0
91 var:FF50 403EBA w = var_10004[sti.pc++2];b = sti.Buf[1];sti.Buf[7] = (sti.Buf[2]-var_10004[w+b])? 1:0
92 var:FF4C 403F1C w = var_10004[sti.pc++2];sti.Buf[7] = (var_10004[w]-sti.Buf[0])? 1:0
93 var:FF48 403F72 w = var_10004[sti.pc++2];b = sti.Buf[1];sti.Buf[7] = (var_10004[w+b]-sti.Buf[0])? 1:0
94 var:FF44 403FD3 w = var_10004[sti.pc++2];b = sti.Buf[2];sti.Buf[7] = (var_10004[w+b]-sti.Buf[0])? 1:0
95 var:FF40 404034 w = var_10004[sti.pc++2];sti.Buf[7] = (var_10004[w]-sti.Buf[1])? 1:0
96 var:FF3C 40408B w = var_10004[sti.pc++2];b = sti.Buf[2];sti.Buf[7] = (var_10004[w+b]-sti.Buf[1])? 1:0
97 var:FF38 4040ED w = var_10004[sti.pc++2];sti.Buf[7] = (var_10004[w]-sti.Buf[2])? 1:0
98 var:FF34 404144 w = var_10004[sti.pc++2];b = sti.Buf[1];sti.Buf[7] = (var_10004[w+b]-sti.Buf[2])? 1:0
99 var:FF30 4041A3 MessageBoxA(hWnd,"Success!","Success!",0)


[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

收藏
免费 1
支持
分享
最新回复 (2)
雪    币: 13713
活跃值: (2851)
能力值: ( LV15,RANK:2663 )
在线值:
发帖
回帖
粉丝
2
再次拜服。很难相信,这么短时间,能完成这么多的工作量。
2016-12-8 17:04
0
雪    币: 0
活跃值: (226)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
除了膜拜我还能说什么呢
2018-6-22 01:19
0
游客
登录 | 注册 方可回帖
返回
//