站在巨人的肩膀上学习ctf vm

本文介绍了CTF中虚拟机(VM)的相关知识,包括简单结构、伪虚拟机分析、栈虚拟机的逆向方法,并通过实例解析了VM的保护机制。通过学习,可以对VM有一个初步的认识和理解。
摘要由CSDN通过智能技术生成

0x00 前言

本文提到的vm是ctf里的vm,最近vm还是很热门的,最近的虎符,de1ctf,再到网鼎杯都有vm的身影,但是vm的知识在网上挺散的(我只找到了绿盟那篇比较系统),vm的wp也相对比较简单,所以身为小白的我就在这里归纳一下网上大佬们的文章,和我的思考和学习总结,希望可以给各位看官一些帮助。

参考文章:

虚拟机保护逆向入门

虚拟机保护技术浅谈

《加密与解密》第四版 P592 ~P593

0x01 简单结构

《加密与解密》“中说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}  嘿嘿嘿,很简单吧,我们来进入下一个阶段。

0x02 网鼎_2020

具体的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);
        }
        ++v8;
        v10 += 2;
        break;
      case 8:
        flag[v6] = v5;
        ++v10;
        ++v6;
        break;
   
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值