很久之前做过的一道VM,当时觉得还不错,但一直没来得及写一篇文章,现在回来再复现一下
main函数结构很清晰,vm的痕迹也很明显,符号表没删十分友好,
直接dump下来opcode:
再处理一下:
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,看来是控制的执行轮次:
再根据题目,大概能看出来是TEA加密,轮次是40,还更改了位移数