赞
踩
本文提到的vm是ctf里的vm,最近vm还是很热门的,最近的虎符,de1ctf,再到网鼎杯都有vm的身影,但是vm的知识在网上挺散的(我只找到了绿盟那篇比较系统),vm的wp也相对比较简单,所以身为小白的我就在这里归纳一下网上大佬们的文章,和我的思考和学习总结,希望可以给各位看官一些帮助。
参考文章:
《加密与解密》第四版 P592 ~P593
《加密与解密》“中说ctf_vm不是VMware,,它类似于 P-CODE ,将一系列指令解释成bytecode 后放到一个解释引擎中执行,从而对软件进行保护。”简单来说,就是先设立一个一个不重复的标志(一个字节就是一个标志),然后每个标志通过分发器(dispatcher),寻找到对应的解释(handler),之后把这些标志通过不同的排列组合,并把组合后的标志存到一个固定的地方(这个大数组就是opcode),而组合后的逻辑与将保护程序逻辑相同,实现替换,从而进行保护。
一下是图解:
说明:在ctf_vm中 分发器(dispatcher) 与解释器 (handler)通常是用switch和case实现的,通常有如下结构
- switch(opcode)
- {
- case 1: // handler1
- ......
- break;
-
- case 2: // handler2
- ......
- break;
-
- case 3: // handler3
- ......
- break;
- }
为了更好的理解,我们来看一道类似vm思想的题(伪虚拟机)南邮的一道ctf
本文着重看vm保护,其他本文不再赘述。进入vm_protect。
一般分为两个部分,在分发器之前(红框),会先对一些辅助的值进行赋值(这个下文具体讲解),第二部分(紫框)就是具体的分发,和每一个handler,
在这道伪虚拟机里
1)handler的含义非常好理解,所以也没有什么必要去理解红框里辅助的值,
2)本道题所保护的flag算法只是最简单的+ - * /,所以没必要通过opcode的顺序自己来还原(15000个也不可能自己还原)
小结:本题并没有逆向虚拟机最重要的东西(翻译handler含义,翻译所保护代码的含义),放在这是为了初步认识ctf_vm的结构。
放上师傅写的脚本(拿idapython跑一下):
- adr1 = 0x6010C0
- adr2 = 0x601060
- flag =[]
-
- for i in range(0,24*4,4):
- print "%x"%Dword(adr2+i)
- flag.append(Dword(adr2+i))
-
- for i in range(14997,-1,-3):
- a = Byte(adr1+i)
- b = Byte(adr1+i+1)
- c = Byte(adr1+i+2)
- if(a == 1):
- flag[b] -= c
- flag[b] = flag[b]&0xff
- if(a == 2):
- flag[b] += c
- flag[b] = flag[b] & 0xff
- if(a == 3):
- flag[b] ^= c
- flag[b] = flag[b] & 0xff
- if(a == 4):
- flag[b] /= c
- flag[b] = flag[b] & 0xff
- if(a == 5):
- flag[b] ^= flag[c]
- flag[b] = flag[b] & 0xff
- print(''.join(map(chr,flag)))
flag: nctf{Embr4ce_Vm_j0in_R3} 嘿嘿嘿,很简单吧,我们来进入下一个阶段。
具体的wp可以看这位师傅写的:网鼎杯2020 伪虚拟机逆向 wp
咱们直接看vm_protect的部分:
- v10 = 0;
- v9 = 0;
- v8 = 0;
- v7 = 0;
- v6 = 0;
- while ( 1 )
- {
- result = v10;
- if ( v10 >= size )
- return result;
- switch ( opcode[v10] )
- {
- case 1:
- v4[v7] = v5;
- ++v10;
- ++v7;
- ++v9;
- break;
- case 2:
- v5 = opcode[v10 + 1] + flag[v9];
- v10 += 2;
- break;
- case 3:
- v5 = flag[v9] - LOBYTE(opcode[v10 + 1]);
- v10 += 2;
- break;
- case 4:
- v5 = opcode[v10 + 1] ^ flag[v9];
- v10 += 2;
- break;
- case 5:
- v5 = opcode[v10 + 1] * flag[v9];
- v10 += 2;
- break;
- case 6:
- ++v10;
- break;
- case 7:
- if ( v4[v8] != opcode[v10 + 1] )
- {
- printf("what a shame...");
- exit(0)
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。