[GWCTF 2019]babyvm 详解 (vm逆向 IDA结构体)

前言

这是笔者做的第一道vm题,虽然相较于同类题题面很简单,但是在过程中收获了很多。

wp

64位无壳,拖入IDA看看先

长这个样,三个函数挨个点进去看看 

 如果比较有经验的话,可以直接认出来这是比较明显的vm。先不细看,点开下一个。

 认真分析一下,可以发现是一个循环执行段,执行(*(16 * (i + 1LL) + a1 + 16))(a1)这一地址的函数,直到**(a1 + 16) == 0xF4为止。。。。

 第三个函数是一个判断。现在再看第一个函数

这样看其实比较麻烦对不对,但是没关系,可以通过结构体来简化这一段代码

对vm有了解的话,可以看出这里代码的前四行相当于设置了寄存器,unk_202060相当于是操作码(指令流),而下面一个数字一个函数的相当于汇编指令。明白了这些,为了看到更明白,我们打开结构体窗口操作一下:

 

在下面空白右键,新建结构体

这里我命名为cpu,随便怎么都可以,你开心就好

创建好后按d新建成员,由于上面是4位,所以创建好后多点几次d,把类型改成对应的dd

一共有四个寄存器,按照顺序命名

 

是这个效果,不要直接命名为eax等真实的,记的加个_啥的,不然会报错。

给操作码也起个名方便看,它占8位所以要设置成dq,不要忘记按顺序设置结构体的元素。

下面就到函数部分了。每一个函数对应一个编码,为此我们可以设置一个另外的结构体来存放函数。注意大小是8不要搞错。

做好后,再到刚刚大的结构体里添加一个新的元素,按y键设置类型为我们刚刚设置好的结构体

上面一共有七个函数,我们点击刚设置好的结构体成员,按*将其设置为大小为8的数组,再把名字改改方便看。

好的,设置完成。我们回到第一个函数。点击类型,按y将其改为我们结构体的名字

点第一个

美观!如法炮制把每个函数都设置一遍,这样就方便看了很多

然后点进函数分析

第一个很明显是mov,对寄存器移来移去的

第二个明显xor

第三个判断flag长度

 

第四个啥事不干 明显是nop

第五个mul,没啥说的

第六个是明显的交换XCHG

第七个是eax = ecx+2*ebx+3*eax

函数都比较简单,下面只需要编写代码还原一下代码就行了

code=[0xF5, 0xF1, 0xE1, 0x00, 0x00, 0x00, 0x00, 0xF2, 0xF1, 0xE4,
  0x20, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x01, 0x00, 0x00, 0x00,
  0xF2, 0xF1, 0xE4, 0x21, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x02,
  0x00, 0x00, 0x00, 0xF2, 0xF1, 0xE4, 0x22, 0x00, 0x00, 0x00,
  0xF1, 0xE1, 0x03, 0x00, 0x00, 0x00, 0xF2, 0xF1, 0xE4, 0x23,
  0x00, 0x00, 0x00, 0xF1, 0xE1, 0x04, 0x00, 0x00, 0x00, 0xF2,
  0xF1, 0xE4, 0x24, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x05, 0x00,
  0x00, 0x00, 0xF2, 0xF1, 0xE4, 0x25, 0x00, 0x00, 0x00, 0xF1,
  0xE1, 0x06, 0x00, 0x00, 0x00, 0xF2, 0xF1, 0xE4, 0x26, 0x00,
  0x00, 0x00, 0xF1, 0xE1, 0x07, 0x00, 0x00, 0x00, 0xF2, 0xF1,
  0xE4, 0x27, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x08, 0x00, 0x00,
  0x00, 0xF2, 0xF1, 0xE4, 0x28, 0x00, 0x00, 0x00, 0xF1, 0xE1,
  0x09, 0x00, 0x00, 0x00, 0xF2, 0xF1, 0xE4, 0x29, 0x00, 0x00,
  0x00, 0xF1, 0xE1, 0x0A, 0x00, 0x00, 0x00, 0xF2, 0xF1, 0xE4,
  0x2A, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x0B, 0x00, 0x00, 0x00,
  0xF2, 0xF1, 0xE4, 0x2B, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x0C,
  0x00, 0x00, 0x00, 0xF2, 0xF1, 0xE4, 0x2C, 0x00, 0x00, 0x00,
  0xF1, 0xE1, 0x0D, 0x00, 0x00, 0x00, 0xF2, 0xF1, 0xE4, 0x2D,
  0x00, 0x00, 0x00, 0xF1, 0xE1, 0x0E, 0x00, 0x00, 0x00, 0xF2,
  0xF1, 0xE4, 0x2E, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x0F, 0x00,
  0x00, 0x00, 0xF2, 0xF1, 0xE4, 0x2F, 0x00, 0x00, 0x00, 0xF1,
  0xE1, 0x10, 0x00, 0x00, 0x00, 0xF2, 0xF1, 0xE4, 0x30, 0x00,
  0x00, 0x00, 0xF1, 0xE1, 0x11, 0x00, 0x00, 0x00, 0xF2, 0xF1,
  0xE4, 0x31, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x12, 0x00, 0x00,
  0x00, 0xF2, 0xF1, 0xE4, 0x32, 0x00, 0x00, 0x00, 0xF1, 0xE1,
  0x13, 0x00, 0x00, 0x00, 0xF2, 0xF1, 0xE4, 0x33, 0x00, 0x00,
  0x00, 0xF4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF5, 0xF1,
  0xE1, 0x00, 0x00, 0x00, 0x00, 0xF1, 0xE2, 0x01, 0x00, 0x00,
  0x00, 0xF2, 0xF1, 0xE4, 0x00, 0x00, 0x00, 0x00, 0xF1, 0xE1,
  0x01, 0x00, 0x00, 0x00, 0xF1, 0xE2, 0x02, 0x00, 0x00, 0x00,
  0xF2, 0xF1, 0xE4, 0x01, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x02,
  0x00, 0x00, 0x00, 0xF1, 0xE2, 0x03, 0x00, 0x00, 0x00, 0xF2,
  0xF1, 0xE4, 0x02, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x03, 0x00,
  0x00, 0x00, 0xF1, 0xE2, 0x04, 0x00, 0x00, 0x00, 0xF2, 0xF1,
  0xE4, 0x03, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x04, 0x00, 0x00,
  0x00, 0xF1, 0xE2, 0x05, 0x00, 0x00, 0x00, 0xF2, 0xF1, 0xE4,
  0x04, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x05, 0x00, 0x00, 0x00,
  0xF1, 0xE2, 0x06, 0x00, 0x00, 0x00, 0xF2, 0xF1, 0xE4, 0x05,
  0x00, 0x00, 0x00, 0xF1, 0xE1, 0x06, 0x00, 0x00, 0x00, 0xF1,
  0xE2, 0x07, 0x00, 0x00, 0x00, 0xF1, 0xE3, 0x08, 0x00, 0x00,
  0x00, 0xF1, 0xE5, 0x0C, 0x00, 0x00, 0x00, 0xF6, 0xF7, 0xF1,
  0xE4, 0x06, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x07, 0x00, 0x00,
  0x00, 0xF1, 0xE2, 0x08, 0x00, 0x00, 0x00, 0xF1, 0xE3, 0x09,
  0x00, 0x00, 0x00, 0xF1, 0xE5, 0x0C, 0x00, 0x00, 0x00, 0xF6,
  0xF7, 0xF1, 0xE4, 0x07, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x08,
  0x00, 0x00, 0x00, 0xF1, 0xE2, 0x09, 0x00, 0x00, 0x00, 0xF1,
  0xE3, 0x0A, 0x00, 0x00, 0x00, 0xF1, 0xE5, 0x0C, 0x00, 0x00,
  0x00, 0xF6, 0xF7, 0xF1, 0xE4, 0x08, 0x00, 0x00, 0x00, 0xF1,
  0xE1, 0x0D, 0x00, 0x00, 0x00, 0xF1, 0xE2, 0x13, 0x00, 0x00,
  0x00, 0xF8, 0xF1, 0xE4, 0x0D, 0x00, 0x00, 0x00, 0xF1, 0xE7,
  0x13, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x0E, 0x00, 0x00, 0x00,
  0xF1, 0xE2, 0x12, 0x00, 0x00, 0x00, 0xF8, 0xF1, 0xE4, 0x0E,
  0x00, 0x00, 0x00, 0xF1, 0xE7, 0x12, 0x00, 0x00, 0x00, 0xF1,
  0xE1, 0x0F, 0x00, 0x00, 0x00, 0xF1, 0xE2, 0x11, 0x00, 0x00,
  0x00, 0xF8, 0xF1, 0xE4, 0x0F, 0x00, 0x00, 0x00, 0xF1, 0xE7,
  0x11, 0x00, 0x00, 0x00, 0xF4,-1,-1,0,0,0,0,0,0,]
i=0
jd=0
while 1:
    if code[i]==241:
      if code[i+1]==225:
        print("mov eax,flag[",code[i+2],"]")
      elif code[i+1]==226:
        print("mov ebx,flag[",code[i+2],"]")
      elif code[i+1]==227:
        print("mov ecx,flag[",code[i+2],"]")
      elif code[i+1]==228:
        print("mov flag[",code[i + 2],"]" ,"eax" )
      elif code[i+1]==229:
        print("mov edx,flag[",code[i+2],"]")
      elif code[i+1]==231:
        print("mov flag[",code[i + 2],"]" ,"ebx" )
      i+=6
    elif code[i]==242:
      print("xor eax,ebx")
      i+=1
    elif code[i]==245:
      print("judge len")
      i+=1
    elif code[i]==244:
      print("nop")
      i+=1
    elif code[i]==247:
      print("mul eax,edx")
      i+=1
    elif code[i]==248:
      print("XCHG eax,ebx")
      i+=1
    elif code[i]==246:
      print("eax = ecx+2*ebx+3*eax")
      i+=1
    elif code[i]==0:
      i+=1
    elif code[i]==-1:
      break

这是结果

judge len
mov eax,flag[ 0 ]
xor eax,ebx
mov flag[ 32 ] eax
mov eax,flag[ 1 ]
xor eax,ebx
mov flag[ 33 ] eax
mov eax,flag[ 2 ]
xor eax,ebx
mov flag[ 34 ] eax
mov eax,flag[ 3 ]
xor eax,ebx
mov flag[ 35 ] eax
mov eax,flag[ 4 ]
xor eax,ebx
mov flag[ 36 ] eax
mov eax,flag[ 5 ]
xor eax,ebx
mov flag[ 37 ] eax
mov eax,flag[ 6 ]
xor eax,ebx
mov flag[ 38 ] eax
mov eax,flag[ 7 ]
xor eax,ebx
mov flag[ 39 ] eax
mov eax,flag[ 8 ]
xor eax,ebx
mov flag[ 40 ] eax
mov eax,flag[ 9 ]
xor eax,ebx
mov flag[ 41 ] eax
mov eax,flag[ 10 ]
xor eax,ebx
mov flag[ 42 ] eax
mov eax,flag[ 11 ]
xor eax,ebx
mov flag[ 43 ] eax
mov eax,flag[ 12 ]
xor eax,ebx
mov flag[ 44 ] eax
mov eax,flag[ 13 ]
xor eax,ebx
mov flag[ 45 ] eax
mov eax,flag[ 14 ]
xor eax,ebx
mov flag[ 46 ] eax
mov eax,flag[ 15 ]
xor eax,ebx
mov flag[ 47 ] eax
mov eax,flag[ 16 ]
xor eax,ebx
mov flag[ 48 ] eax
mov eax,flag[ 17 ]
xor eax,ebx
mov flag[ 49 ] eax
mov eax,flag[ 18 ]
xor eax,ebx
mov flag[ 50 ] eax
mov eax,flag[ 19 ]
xor eax,ebx
mov flag[ 51 ] eax
nop
judge len

mov eax,flag[ 0 ]
mov ebx,flag[ 1 ]
xor eax,ebx
mov flag[ 0 ] eax
mov eax,flag[ 1 ]
mov ebx,flag[ 2 ]
xor eax,ebx
mov flag[ 1 ] eax
mov eax,flag[ 2 ]
mov ebx,flag[ 3 ]
xor eax,ebx
mov flag[ 2 ] eax
mov eax,flag[ 3 ]
mov ebx,flag[ 4 ]
xor eax,ebx
mov flag[ 3 ] eax
mov eax,flag[ 4 ]
mov ebx,flag[ 5 ]
xor eax,ebx
mov flag[ 4 ] eax
mov eax,flag[ 5 ]
mov ebx,flag[ 6 ]
xor eax,ebx
mov flag[ 5 ] eax


mov eax,flag[ 6 ]
mov ebx,flag[ 7 ]
mov ecx,flag[ 8 ]
mov edx,flag[ 12 ]
eax = ecx+2*ebx+3*eax
mul eax,edx
mov flag[ 6 ] eax

mov eax,flag[ 7 ]
mov ebx,flag[ 8 ]
mov ecx,flag[ 9 ]
mov edx,flag[ 12 ]
eax = ecx+2*ebx+3*eax
mul eax,edx
mov flag[ 7 ] eax

mov eax,flag[ 8 ]
mov ebx,flag[ 9 ]
mov ecx,flag[ 10 ]
mov edx,flag[ 12 ]
eax = ecx+2*ebx+3*eax
mul eax,edx
mov flag[ 8 ] eax



mov eax,flag[ 13 ]
mov ebx,flag[ 19 ]
XCHG eax,ebx
mov flag[ 13 ] eax
mov flag[ 19 ] ebx
mov eax,flag[ 14 ]
mov ebx,flag[ 18 ]
XCHG eax,ebx
mov flag[ 14 ] eax
mov flag[ 18 ] ebx
mov eax,flag[ 15 ]
mov ebx,flag[ 17 ]
XCHG eax,ebx
mov flag[ 15 ] eax
mov flag[ 17 ] ebx
nop

前面一段是假的代码,只看后面即可,逻辑比较简单。

还有一处坑

第三个函数是假的judge函数,真正的数据需要交叉引用看到

真正的检查函数

编写脚本得到flag

from z3 import*
def swap(a, b):
  a,b=b,a
  return a, b
bb=[105,  69,  42,  55,   9,  23, 197,  11,  92, 114,
   51, 118,  51,  33, 116,  49,  95,  51, 115, 114]
bb[15],bb[17]=swap(bb[15],bb[17])
bb[14],bb[18]=swap(bb[14],bb[18])
bb[19],bb[13]=swap(bb[19],bb[13])

s = Solver()
f = [BitVec(f"f{[i]}", 8) for i in range(11)]


s.add((f[6]*3+f[7]*2+f[8])*bb[12]==bb[6])
s.add(bb[12]*(f[7]*3+f[8]*2+f[9])==bb[7])
s.add(bb[12]*(f[8]*3+f[9]*2+f[10])==bb[8])
s.add(bb[0] == f[0] ^ f[1])
s.add(bb[1] == f[1] ^ f[2])
s.add(bb[2] == f[2] ^ f[3])
s.add(bb[3] == f[3] ^ f[4])
s.add(bb[4] == f[4] ^ f[5])
s.add(bb[5] == f[5] ^ f[6])
s.add(f[9]==bb[9])
s.add(f[10]==bb[10])

if s.check() == sat:
    t = s.model()
    for i in f:
        print(chr(t[i].as_long()), end='')
for i in range(0,9):
    print(chr(bb[11+i]),end="")

flag{Y0u_hav3_r3v3rs3_1t!}

  • 13
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值