CSAW CTF2017年的总决赛的一道逆向题目“Rabbithole”
这个题目久只有一个64位的ELF文件。
我写这个题目的主要目的是:1.提升自己IDApython能力。3.加强对IDA流程图的利用。4.对算法的过程的理解。
首先拿到文件然后用IDA Pro 7.7 打开
找到主要的位置,进行一个简单的分析:
这里主要的是check_value这个函数
哇靠,这个函数IDA F5分析有错误。首先我们来看一下吧:
通过F5来看,它就是直接的return a2+8。
感觉久很“答辩”
这里我们再来看看roots:
它是一个充满了指针的一个数组。
我们随便看一个node_吧
可以看到一个node里面有好多的0,然后其他的就不是0。感觉这些数据就很符合while ( !*(_BYTE *)a2 ) 的构造。
但是这里F5出来有一点点的小问题:它就循环一下然后就退出去了。
我们这里看看汇编代码:
这里汇编看到的是:循环调用自身,而不是简单的一个while循环。感觉也大差不差的。
大致看了check的代码,我们回到main
大概就是传入的flag值,进入check函数里面去比较。值需要相同,这里用爆破的思想来爆破出flag的值。
我们循环遍历可见字符,然后去模拟这个check函数。
这里一个59次的循环:
可以看到这里的cmp rdx,3Bh【控制循环】
每一次循环的时候 有:rsi, [r8 + rdx*8] 和 inc rdx
也就是每一次循环出来后roots +8
简单的模拟一下:
1 | for i in range(59): |
看汇编代码更加的清晰。
现就就是需要来模拟check_value函数:
1 | def check_value(c,node): |
这里你可能会想为什么会有if get_byte(node+8) == 1:
最后总结一下这2个代码:
1 | def check_value(c, node): |
原本的程序是:flag字符串一个一个的进入check函数,然后返回的是ax 但是在返回之前有一个mov al,[rsi + 8]。然后进行and操作。and ecx , eax
在程序开始的时候有mov cl,1。在将flag中的字符串遍历完了后有一个test cl,cl的操作【test 也就是按位与】
我们这里不能让他跳转。也就是jz【zf标志位=1就跳转】
cl =1的情况下【zf = 0】所以这里需要cl == 1
也就是说: r = get_byte(node + 8) & 0x1
if r == 1:
这个就是说 r = 返回出来的[node + 8] & cl【0x1】 ==1
上面有一个and ecx ,eax。ecx :也就是定义好的0x1,eax 是node+8。需要操作后的cl还是==1
这里用python 写出来就是 r = get_byte[node+8] & 0x1 ==1,则就是正确的。
【这里有点点说不清楚…】
因为程序中是最后的一次出来cl == 1,所以需要每一个flag 在进行check 后的cl ==1
所以可以利用这一点去进行爆破。
循环遍历每一个可见字符,让他每一次通过一次check函数,当 cl == 1 则能得出该可见字符是正确的。