CISCN 初赛复盘 RE baby_tree
这道题,逆向下来会发现还是挺有规律的,多注意观察decl与extension即可
这里只写了一些关键点
一、ast树

经过搜索了解到这是swift语言的ast结构,编译原理的知识
二、利用Nopated++转化为js风格的代码
这样可以提高代码的可读性

三、ast树的特点
我在逆向的时候,发现ast树有个很大的特点,他总是先声明出运算符号,如==、-、+、&、arr等等,然后再在后面的argument_list(参数列表中) 列出运算所用到的参数,但很多时候,参数会再次嵌套运算符,形成如下的结构:

我们逆向的时候,会有种层层嵌套,最后递归回来的豁然感觉
四、注意关键词extension和decl
这两个关键词每次出现都会带来运算符、参数、函数调用之类的,如下图



(取下标)

(b数组)
甚至有的时候,decl会表示函数的含义,如下图,count代表len()函数

五、参数的赋值
=的运算是有点神奇的,ast没有把 '='列入运算符号中

是通过两行并列的式子完成的 subscript_expr 在等号左边, binary_expr在等号右边
六、最后逆向出的代码如下
bool check(string encoded,string keyValue){ uint8[] b= arr[utf8(encoded)] //参数类型逆向的有问题 //39行之前/// uint8[] k= arr[utf8(keyValue)] UInt8 r0,r1,r2,r3; for i in range(len(b)-4): r0=b[i],r1=b[i+1],r2=b[i+2],r3=b[i+3]; //207行之前// b[i+0] = r2^(0xff&(k[0] + (r0>>4))); //287行之前// b[i+1] = r3^(0xff&(k[1] + (r1>>2))); //269行之前// b[i+2] = r0^(k[1]); //410行之前// b[i+3] = r1^k[3]; //451行之前 k[0],k[1],k[2],k[3] = k[1],k[2],k[3],k[0] return b == [88,35,88,225,7,201,57,94,77,56,75,168,72,218,64,91,16,101,32,207,73,130,74,128,76,201,16,248,41,205,103,84,91,99,79,202,22,131,63,255,20,16] } //571行之前 if len(CommandLine) >= 2: data = CommandLine.arguments[1];//612行之前 string key = "345y"; //621行之前 bool result = check(data,key) //644行之前 print(......) //最后的print没逆明白
七、写出解密脚本
b = [88,35,88,225,7,201,57,94,77,56,75,168,72,218,64,91,16,101,32,207,73,130,74,128,76,201,16,248,41,205,103,84,91,99,79,202,22,131,63,255,20,16] k = list('345y') #pytohn中字符串不能修改,我们需要先把他转化为列表... k[0], k[1], k[2], k[3] = k[2], k[3], k[0], k[1] #循环38次后的k值 for i in range(len(b)-4,-1,-1): r1 = b[i+3] ^ ord(k[3]) r0 = b[i+2] ^ ord(k[2]) r3 = b[i+1] ^ (0xff&(ord(k[1])+(r1>>2))) r2 = b[i+0] ^ (0xff&(ord(k[0])+(r0>>4))) b[i] = r0 ; b[i+1] = r1;b[i+2] = r2;b[i+3] = r3 k[0], k[1], k[2], k[3] = k[3], k[0], k[1], k[2] #倒置 for i in b: print(chr(i),end="") #flag{30831242-56db-45b4-96fd-1f47e60da99d}
八、一些小疑点
1、print的逆向没看懂
2、这两个 '->' 相当于返回类型的变化(从右往左看),暗示了函数嵌套调用...

这道题的所有点就这么多,写的有点粗糙,可能只有我自己能看懂(:
这道题给我的感觉是,只要下决心去逆向,很快就能找到规律,不错的一道题