参考博客CTF逆向-[MRCTF2020]VirtualTree-恒成立的jz花指令去除及smc变换原执行流程在二叉树上的应用,通过逆向思维编写脚本以解决_serfend的博客-CSDN博客
main函数逻辑比较清晰,开头的sub_401510是去掉花指令(此题最关键的操作之一)后的函数,中间经过sub_6F1610函数和sub_6F16F0函数的变换,最后和byte_7108EC数组做对比
先看sub_401680函数,a1、a1+4、a1+8可以联想到二叉树
右键a1,创建新的结构体
改成这样继续看,先判断左子树,然后异或,再判断右子树,是中序遍历
对401680交叉引用,发现还有其他的函数引用,跟进
先将所有的401510函数替换成off_4208B0为起点的内容(off_4208B0也是有花指令的,需要去除),再将所有的中序遍历改为后序遍历
这里的14个操作分别对应了off_4208B0为起点的14个函数,需要一一替换
其实只有三种函数
ps:这些函数的去花需要先D,然后对下面有意义的语句一行行C,最后对0EBh nop,就能去花了
int __cdecl sub_401470(int a1, int a2)
{
int result; // eax
result = *(&input + a2);
*(&input + a1) ^= result;
return result;
}
//input[a1] ^= input[a2]
int __cdecl sub_4014A0(int a1, int a2)
{
__int64 v2; // rax
int result; // eax
v2 = *(&input + a1) - *(&input + a2);
result = (HIDWORD(v2) ^ v2) - HIDWORD(v2);
*(&input + a1) = result;
return result;
}
//input[a1] = abs(input[a1] - input[a2])
int __cdecl sub_4014E0(int a1, char a2)
{
int result; // eax
result = a1;
*(&input + a1) += a2;
return result;
}
//input[a1] += input[a2]
对这个数组交叉引用,可以找到函数sub_401120,里面找到二叉树的顺序以及这个数组的值
用同样的方法改成结构体
画出二叉树,后序遍历的顺序如下
dword_421310数组的值就是从65递增
捋一捋顺序,先对输入异或操作(异或对象就是dword_421310数组),再进行14项操作,最后与已知数组对比。逆向一下,脚本如下
flag = '17637703522E4A28521B17123A0A6C6200000000'
flag = [x for x in bytearray.fromhex(flag)]
def f_add_a2(a1: int, a2: int):
flag[a1] -= a2
def f_xor_ginputIndexOfa2(a1: int, a2: int):
flag[a1] ^= flag[a2]
def f_abs_inputA1_minus_inputA2(a1: int, a2: int):
if flag[a1] < flag[a2]:
flag[a1] = -flag[a1]
flag[a1] += flag[a2]
commands = '''
f_add_a2(0, 10)
f_xor_ginputIndexOfa2(1, 2)
f_add_a2(2, 7)
f_abs_inputA1_minus_inputA2(3, 7)
f_xor_ginputIndexOfa2(4, 5)
f_abs_inputA1_minus_inputA2(6, 1)
f_add_a2(7, 3)
f_xor_ginputIndexOfa2(8, 7)
f_abs_inputA1_minus_inputA2(9, 8)
f_abs_inputA1_minus_inputA2(10, 7)
f_xor_ginputIndexOfa2(11, 12)
f_abs_inputA1_minus_inputA2(12, 2)
f_xor_ginputIndexOfa2(14, 15)
f_add_a2(15, 2)
'''.split('\n')
commands = commands[::-1]
for command in commands:
if len(command) < 5:
continue
eval(command)
order = [13, 12, 7, 16, 15, 11, 6, 3, 10, 5, 14, 9, 8, 4, 2, 1]
order = [x-1 for x in order]
for index, i in enumerate(order):
flag[index] ^= (65+i)
flag = [chr(x) for x in flag]
flag = ''.join(flag)
print(flag)
# @_7r3e_f0r_fuNN!