[re]硬猜flag:2020网鼎杯青龙组re_joker_wp
[re]硬猜flag:2020网鼎杯青龙组re_joker_wp
2020网鼎杯青龙组的一道逆向题joker,这道题其实并不是很难,但难在考心态和脑洞,获取flag的最后一步居然是硬猜,我吐了啊,而且没法**,因为这道题你拿到flag了,在程序中输入也不会告诉你flag正确。
题目分析
题目是一个32位windows程序:
逆向分析一下,main函数直接f5是不行的,堆栈不平衡。
但这里无需去纠正他,因为main函数的逻辑还算简单:
直接可以看出flag字符串长度是0x18也就是24
然后对输入的flag进行了下面两个操作,这两个函数都可以f5:
分别是wrong:
和omg:
首先对输入的flag的每个字节根据并1后是否为真进行了-下标或者亦或下标的操作,然后得到的结果跟一个全局变量比较,逻辑比较简单就可以还原:
result="fkcd\x7fagd;Vka{&;Pc_MZq\x0c7f"
i=0
flag=""
for j in result:
if(i&1):
flag+=chr(ord(j)+i)
else:
flag+=chr(ord(j)^i)
i+=1
print flag
然而flag是假的(看flag的字符串也能看出来,而且程序还没结束)。
然后继续分析:
这里可以看到对一个函数进行了一些操作,很明显可以看出右边的操作是循环对这个函数进行解密,解密之后直接调用。直接点进这个函数也是一堆乱码:
好办,直接上od,在这个函数调用前的位置0x401833 下断点,然后执行到这:
可以看到函数已经解密了:
然后olldump直接脱壳,啥也不用选:
然后IDA打开,可以f5这个函数:
逻辑是,对输入的内容和hahahaha_do_you_find_me?这个字符串进行异或,然后和一个全局变量进行比较,注意只异或了19个字节,然后写出脚本还原一下:
result2="\x0e\x0d\x09\x06\x13\x05\x58\x56\x3e\x06\x0c\x3c\x1f\x57\x14\x6b\x57\x59\x0d"
flag=""
haha="hahahaha_do_you_find_me?"
for i in range(19):
flag+=chr(ord(haha[i])^ord(result2[i]))
print flag
只有19个字节,还缺后5个字节,这个就体现这道题的恶心之处了。
IDA中看程序的逻辑发现调用flag校验函数之后还有一个finally函数,这个函数正常执行是执行不到的,当然执行到了也不是校验flag或者计算输出flag,这是个“逗你玩”的函数:
这个函数同样是加密的,从刚刚从OD中脱出来的程序中可以看到这个函数的明文:
5个字符:“%tp&:”,但后面的判断简直是在搞笑,每次都是随机的?这里显然不是,虽然说脑洞不是很大,但这样子加大难度真的很烦。
因为flag最后一个字节一定是‘}’,那么用‘:’^‘}’=0x47,然后使用“%tp&:”分别异或0x47得到最后5个字节。**没用,因为这个flag你就算是得到了,在程序中输入也会告诉你是错误的,只有在比赛页面提交才会正确,也就是说没有任何一个队伍在提交这道题的flag前是确定自己做对了的…
完整exp:
result="fkcd\x7fagd;Vka{&;Pc_MZq\x0c7f"
i=0
flag=""
for j in result:
if(i&1):
flag+=chr(ord(j)+i)
else:
flag+=chr(ord(j)^i)
i+=1
print flag
result2="\x0e\x0d\x09\x06\x13\x05\x58\x56\x3e\x06\x0c\x3c\x1f\x57\x14\x6b\x57\x59\x0d\x47\x47\x47\x47\x47"
flag=""
haha="hahahaha_do_you_fin%tp&:"
for i in range(24):
flag+=chr(ord(haha[i])^ord(result2[i]))
print flag
得到真的flag:
上一篇: 无线网络连接上但上不了网的解决方法
下一篇: 一次性纸碗的优缺点都是哪些