2017WHCTF REVERSE babyRE

这个题其实比较简单,考察点是GDB调试与逆向分析


拖入OD分析,main无法F5,于是查看汇编代码以及汇编流程图

2017WHCTF REVERSE babyRE_第1张图片2017WHCTF REVERSE babyRE_第2张图片

查看逻辑,很明显字符串的长度为0x0E(14个字符),然后调用了judge函数,判断字符串合法性

2017WHCTF REVERSE babyRE_第3张图片

然后发现,IDA解析不了judge函数,肯定是有某些绕过静态反汇编的手段,于是开始GDB

直接在scanf的地方下断,开始进入judge的判断单步

2017WHCTF REVERSE babyRE_第4张图片

注意这里0x400686的call rdx,就是judge函数的入口,需要单步进入(即s命令进去)

进来之后,发现了一段初始化

2017WHCTF REVERSE babyRE_第5张图片

所以查看rbp之后,可以保存下来这些初始数据(不需要一个一个去打印)

2017WHCTF REVERSE babyRE_第6张图片

运行到0x600B40时,初始化完成,查看内存,把这些值复制下来

接下来,我们需要判断的是,这些初始数据和我们输入的字符串是发生了什么样的验证过程和匹配关系


2017WHCTF REVERSE babyRE_第7张图片

edx是我们输入,0x600b6b是把异或的结果保存起来(所以可以在这里下断点,去查看每一次的运算结果是什么)

结果发现,第一个是a,第二个是c(输入是abcdefghijklmn),马上可以猜测异或的是0-13这按id的标号的数字


2017WHCTF REVERSE babyRE_第8张图片

当然,也可以选择在运算循环结束之后去下断,地址在0x600b77,运行到这内存已经有了运算后的结果字符串

所以程序逻辑很简单:把输入字符串和自己对应下标的整数值异或,然后和栈中初始化的值进行比较,相同即正确。

把栈中的初始化值异或一下就可以。

inp = 'abcdefghijklmn'
out = 'acagacaoacagac'
for i in range(0,len(inp)):
	print ord(inp[i]) ^ ord(out[i]),
print

s = [0x66,0x6d,0x63,0x64,0x7f,0x6b,0x37,0x64,0x3b,0x56,0x60,0x3b,0x6e,0x70]
st = ''
for i in range(0,len(s)):
	st += chr(s[i] ^ i)
print st

最后的flag是:

flag{n1c3_j0b}

你可能感兴趣的:(CTF之旅,Linux,reverse)