[GWCTF 2019]babyvm

最后更新于 2024-07-20 1743 字 预计阅读时间: 8 分钟


从题目可知这是一道模拟虚拟机通过操作码对数据进行操作的题目,PE64无壳,放入ida,对函数进行分析

在vm_init中创建结构体得到

其中reg0-3是4个寄存器,g_action是操作码的集合,vm_main是vm根据对应操作码对reg和输入数据的操作,xor,input,add_ip,swpa,add_mul都是对寄存器的操作

在vm_start函数中,当读到操作码不为F4时进入函数

for ( i = 0; *a1->g != *(&a1->opcode1 + 16 * i); ++i ) 在遍历g_action是否有操作码满足上述init函数中的操作码,如果有则调用对应操作码的函数,我们就可以写脚本来查看所有操作

opcode=[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]

for x in range(len(opcode)):
    code=opcode[x]
   #print(hex(opcode[x]))
    if opcode[x]==0xF4:
        print("\n")
    if opcode[x]==0xF5:
        print("input:__________________________21")
    if opcode[x]==0xF2:
        print("r0=r0 ^ r1")
    if opcode[x]==0xF7:
        print("r0=r0 * r4")
    if opcode[x]==0xF8:
        print("swap(r0,r4)")
    if opcode[x]==0xF6:
        print("r0=2 * r1 + r2 + 3 * r0")
    if opcode[x]==0xF1:
        fun_op=opcode[x+1]
        num=opcode[x+2]
        if fun_op == 0xE1:
            r0 = num
            print(f"r0=input[{num}]")
        if fun_op == 0xE2:
            r1 = num
            print(f"r1=input[{num}]")
        if fun_op == 0xE3:
            r2 = num
            print(f"r2=input[{num}]")
        if fun_op == 0xE4:
            print(f"input[{num}]=r0")
        if fun_op == 0xE5:
            r3 = num
            print(f"r4=input[{num}]")
        if fun_op == 0xE7:
            print(f"input[{num}]=r1")
#输出
input:__________________________21
r0=input[0]
r0=r0 ^ r1
input[32]=r0
r0=input[1]
r0=r0 ^ r1
input[33]=r0
r0=input[2]
r0=r0 ^ r1
input[34]=r0
r0=input[3]
r0=r0 ^ r1
input[35]=r0
r0=input[4]
r0=r0 ^ r1
input[36]=r0
r0=input[5]
r0=r0 ^ r1
input[37]=r0
r0=input[6]
r0=r0 ^ r1
input[38]=r0
r0=input[7]
r0=r0 ^ r1
input[39]=r0
r0=input[8]
r0=r0 ^ r1
input[40]=r0
r0=input[9]
r0=r0 ^ r1
input[41]=r0
r0=input[10]
r0=r0 ^ r1
input[42]=r0
r0=input[11]
r0=r0 ^ r1
input[43]=r0
r0=input[12]
r0=r0 ^ r1
input[44]=r0
r0=input[13]
r0=r0 ^ r1
input[45]=r0
r0=input[14]
r0=r0 ^ r1
input[46]=r0
r0=input[15]
r0=r0 ^ r1
input[47]=r0
r0=input[16]
r0=r0 ^ r1
input[48]=r0
r0=input[17]
r0=r0 ^ r1
input[49]=r0
r0=input[18]
r0=r0 ^ r1
input[50]=r0
r0=input[19]
r0=r0 ^ r1
input[51]=r0


input:__________________________21
r0=input[0]
r1=input[1]
r0=r0 ^ r1
input[0]=r0
r0=input[1]
r1=input[2]
r0=r0 ^ r1
input[1]=r0
r0=input[2]
r1=input[3]
r0=r0 ^ r1
input[2]=r0
r0=input[3]
r1=input[4]
r0=r0 ^ r1
input[3]=r0
r0=input[4]
r1=input[5]
r0=r0 ^ r1
input[4]=r0
r0=input[5]
r1=input[6]
r0=r0 ^ r1
input[5]=r0
r0=input[6]
r1=input[7]
r2=input[8]
r4=input[12]
r0=2 * r1 + r2 + 3 * r0
r0=r0 * r4
input[6]=r0
r0=input[7]
r1=input[8]
r2=input[9]
r4=input[12]
r0=2 * r1 + r2 + 3 * r0
r0=r0 * r4
input[7]=r0
r0=input[8]
r1=input[9]
r2=input[10]
r4=input[12]
r0=2 * r1 + r2 + 3 * r0
r0=r0 * r4
input[8]=r0
r0=input[13]
r1=input[19]
swap(r0,r4)
input[13]=r0
input[19]=r1
r0=input[14]
r1=input[18]
swap(r0,r4)
input[14]=r0
input[18]=r1
r0=input[15]
r1=input[17]
swap(r0,r4)
input[15]=r0
input[17]=r1

该操作分为两部分,但第一部分为假的flag故flag应在第二段,写z3脚本爆破得到

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

r=[BitVec(f"r{i}",8) for i in range(20)]
s=Solver()
s.add(r[9]==flag[9])
s.add(r[10]==flag[10])
s.add(r[11]==flag[11])
s.add(r[12]==flag[12])
s.add(r[13]==flag[13])
s.add(r[14]==flag[14])
s.add(r[15]==flag[15])
s.add(r[16]==flag[16])
s.add(r[17]==flag[17])
s.add(r[18]==flag[18])
s.add(r[19]==flag[19])
s.add(r[0]^r[1]==(flag[0]))
s.add(r[0]^r[1]==(flag[0]))
s.add(r[1]^r[2]==(flag[1]))
s.add(r[2]^r[3]==(flag[2]))
s.add(r[3]^r[4]==(flag[3]))
s.add(r[4]^r[5]==(flag[4]))
s.add(r[5]^r[6]==(flag[5]))
s.add(((flag[10]) +2 * (flag[9]) + 3 * r[8])*(flag[12])==(flag[8]))
s.add(((flag[9]) +2 * r[8] + 3 * r[7])*(flag[12])==(flag[7]))
s.add((r[8]  +2 * r[7] + 3 * r[6])*(flag[12])==(flag[6]))




if s.check()==sat:
    ans=s.model()
    print(ans)
    for x  in r:
        print(chr(ans[x].as_long()),end="")

此作者没有提供个人介绍。
最后更新于 2024-07-20