很久之前做过的一道VM,当时觉得还不错,但一直没来得及写一篇文章,现在回来再复现一下

main函数结构很清晰,vm的痕迹也很明显,符号表没删十分友好,

直接dump下来opcode:

Untitled

再处理一下:

data = b'\\xf0\\x00\\x00\\x00\\xf1\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02\\x00\\x00\\x00\\xf1\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x02\\x00\\x00\\x00\\xf1\\x00\\x00\\x00\\x03\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xf1\\x00\\x00\\x00\\x02\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xf2\\x00\\x00\\x00\\x03\\x00\\x00\\x00\\xb9y7\\x9e\\x00\\x00\\x00\\x00\\xf1\\x00\\x00\\x00\\x04\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\xf5\\x00\\x00\\x00\\x04\\x00\\x00\\x00\\x05\\x00\\x00\\x00\\xf2\\x00\\x00\\x00\\x04\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x02\\x00\\x00\\x00\\xf1\\x00\\x00\\x00\\x05\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\xf3\\x00\\x00\\x00\\x05\\x00\\x00\\x00\\x05\\x00\\x00\\x00\\xf2\\x00\\x00\\x00\\x05\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02\\x00\\x00\\x00\\xf4\\x00\\x00\\x00\\x04\\x00\\x00\\x00\\x05\\x00\\x00\\x00\\xf1\\x00\\x00\\x00\\x05\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\xf2\\x00\\x00\\x00\\x05\\x00\\x00\\x00\\x03\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\xf4\\x00\\x00\\x00\\x04\\x00\\x00\\x00\\x05\\x00\\x00\\x00\\xf2\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x04\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\xf1\\x00\\x00\\x00\\x04\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\xf5\\x00\\x00\\x00\\x04\\x00\\x00\\x00\\x05\\x00\\x00\\x00\\xf2\\x00\\x00\\x00\\x04\\x00\\x00\\x00\\x03\\x00\\x00\\x00\\x02\\x00\\x00\\x00\\xf1\\x00\\x00\\x00\\x05\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\xf3\\x00\\x00\\x00\\x05\\x00\\x00\\x00\\x05\\x00\\x00\\x00\\xf2\\x00\\x00\\x00\\x05\\x00\\x00\\x00\\x02\\x00\\x00\\x00\\x02\\x00\\x00\\x00\\xf4\\x00\\x00\\x00\\x04\\x00\\x00\\x00\\x05\\x00\\x00\\x00\\xf1\\x00\\x00\\x00\\x05\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\xf2\\x00\\x00\\x00\\x05\\x00\\x00\\x00\\x03\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\xf4\\x00\\x00\\x00\\x04\\x00\\x00\\x00\\x05\\x00\\x00\\x00\\xf2\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x04\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\xf2\\x00\\x00\\x00\\x02\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xf6\\x00\\x00\\x00\\xff\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'

for i in range(0, len(data), 4):
    group = data[i:i+4]
    group = group[::-1]
    data1 = ''.join(format(byte, '02x') for byte in group)
    print("0x" + data1 + ",")

得到opcode:

opcode = [
0xf0,
0xf1, 0x00, 0x00, 0x02,
0xf1, 0x01, 0x01, 0x02,
0xf1, 0x03, 0x00, 0x00,
0xf1, 0x02, 0x00, 0x00,
0xf2, 0x03, 0x9e3779b9, 0x00,
0xf1, 0x04, 0x01, 0x01,
0xf5, 0x04, 0x05,
0xf2, 0x04, 0x01, 0x02,
0xf1, 0x05, 0x01, 0x01,
0xf3, 0x05, 0x05,
0xf2, 0x05, 0x00, 0x02,
0xf4, 0x04, 0x05,
0xf1, 0x05, 0x01, 0x01,
0xf2, 0x05, 0x03, 0x01,
0xf4, 0x04, 0x05,
0xf2, 0x00, 0x04, 0x01,
0xf1, 0x04, 0x00, 0x01,
0xf5, 0x04, 0x05,
0xf2, 0x04, 0x03, 0x02,
0xf1, 0x05, 0x00, 0x01,
0xf3, 0x05, 0x05,
0xf2, 0x05, 0x02, 0x02,
0xf4, 0x04, 0x05,
0xf1, 0x05, 0x00, 0x01,
0xf2, 0x05, 0x03, 0x01,
0xf4, 0x04, 0x05,
0xf2, 0x01, 0x04, 0x01,
0xf2, 0x02, 0x01, 0x00,
0xf6,
0xff
]

将里面的指令对应的函数扒下来跑一遍:

opcode = [
0xf0,
0xf1, 0x00, 0x00, 0x02,
0xf1, 0x01, 0x01, 0x02,
0xf1, 0x03, 0x00, 0x00,
0xf1, 0x02, 0x00, 0x00,
0xf2, 0x03, 0x9e3779b9, 0x00,
0xf1, 0x04, 0x01, 0x01,
0xf5, 0x04, 0x05,
0xf2, 0x04, 0x01, 0x02,
0xf1, 0x05, 0x01, 0x01,
0xf3, 0x05, 0x05,
0xf2, 0x05, 0x00, 0x02,
0xf4, 0x04, 0x05,
0xf1, 0x05, 0x01, 0x01,
0xf2, 0x05, 0x03, 0x01,
0xf4, 0x04, 0x05,
0xf2, 0x00, 0x04, 0x01,
0xf1, 0x04, 0x00, 0x01,
0xf5, 0x04, 0x05,
0xf2, 0x04, 0x03, 0x02,
0xf1, 0x05, 0x00, 0x01,
0xf3, 0x05, 0x05,
0xf2, 0x05, 0x02, 0x02,
0xf4, 0x04, 0x05,
0xf1, 0x05, 0x00, 0x01,
0xf2, 0x05, 0x03, 0x01,
0xf4, 0x04, 0x05,
0xf2, 0x01, 0x04, 0x01,
0xf2, 0x02, 0x01, 0x00,
0xf6,
0xff
]

def F1(a1, a2, a3):
    if a3:
        if a3 == 1:
            print(f'reg[{a1}] = reg[{a2}]')
        elif a3 == 2:
            print(f'reg[{a1}] = flag[{a2}]')
    else:
        print(f'reg[{a1}] = {a2}')
def F2(a1, a2, a3):
    if a3:
        if a3 == 1:
            print(f'reg[{a1}] += reg[{a2}]')
        elif a3 == 2:
            print(f'reg[{a1}] += flag[{a2}]')
    else:
        print(f'reg[{a1}] += {a2}')
def F3(a1, a2):
    print(f'reg[{a1}] <<= {a2}')
def F4(a1, a2):
    print(f'reg[{a1}] ^= reg[{a2}]')
def F5(a1, a2):
    print(f'reg[{a1}] >>= {a2}')

enc = [
  0x1A, 0x62, 0xB9, 0x76, 0xDE, 0xAD, 0xE4, 0xCC, 0xC8, 0xBF, 0xC8, 0x25, 0x72, 0xD4, 0xC2, 0x16, 0x3A, 0xD5, 0x17, 0xF3, 0xA1, 0x11, 0xA1, 0xF2, 0xE6, 0xF0, 0x89, 0xDF, 0x23, 0xA6, 0xCD, 0xDC, 0x09, 0xF4, 0xC2, 0x21, 0x63, 0x8D, 0xD8, 0xDB]

reg = [0] * 5
flag = ''
i = 0

while opcode[i] != 0xFF:
    if opcode[i] == 0xF0:       # F0是初始化函数
        i += 1
    elif opcode[i] == 0xF1:     # F1指令占4字节
        F1(opcode[i+1], opcode[i+2], opcode[i+3])
        i += 4
    elif opcode[i] == 0xF2:     # F2指令占4字节
        F2(opcode[i+1], opcode[i+2], opcode[i+3])
        i += 4
    elif opcode[i] == 0xF3:     # F3指令占3字节
        F3(opcode[i+1], opcode[i+2])
        i += 3
    elif opcode[i] == 0xF4:     # F4指令占3字节
        F4(opcode[i+1], opcode[i+2])
        i += 3
    elif opcode[i] == 0xF5:     # F5指令占3字节
        F5(opcode[i+1], opcode[i+2])
        i += 3

# reg[0] = flag[0]
# reg[1] = flag[1]
# reg[3] = 0
# reg[2] = 0
# reg[3] += 2654435769
# reg[4] = reg[1]
# reg[4] >>= 5
# reg[4] += flag[1]
# reg[5] = reg[1]
# reg[5] <<= 5
# reg[5] += flag[0]
# reg[4] ^= reg[5]
# reg[5] = reg[1]
# reg[5] += reg[3]
# reg[4] ^= reg[5]
# reg[0] += reg[4]
# reg[4] = reg[0]
# reg[4] >>= 5
# reg[4] += flag[3]
# reg[5] = reg[0]
# reg[5] <<= 5
# reg[5] += flag[2]
# reg[4] ^= reg[5]
# reg[5] = reg[0]
# reg[5] += reg[3]
# reg[4] ^= reg[5]
# reg[1] += reg[4]
# reg[2] += 1

还有一个F6,看来是控制的执行轮次:

Untitled

再根据题目,大概能看出来是TEA加密,轮次是40,还更改了位移数