ROP学习
Nullcon HackIM的第一道re题,虽然做出来了但是原理没太明白,flag里面显示用了ROP,所以学习一下。
main程序
反汇编的结果如下图所示:
程序存在溢出漏洞,使用蒸米大佬的脚本判断溢出长度。
脚本:
|
|
首先生成长度为150的字符串:
|
|
用gdb打开main文件,输入生成的长度为150的字符串:
|
|
64位程序使用的内存地址不能大于0x00007fffffffffff,否则会抛出异常。但是,虽然PC不能跳转到那个地址,我们依然可以通过栈来计算出溢出点。因为ret相当于“pop rip”指令,所以我们只要看一下栈顶的数值就能知道PC跳转的地址了。
|
|
得出溢出点存在于0x4130634139624138处。再次使用蒸米大佬的脚本:
|
|
故溢出长度为56,一般: payload = “a” * 56 + ret_addr
给出的blob文件如下:
可以看到给出的字符串a长度就是56,后面0x4011A2是返回地址,0x4040A0是存储flag字符串dest的地址。这个blob文件相当于一个大型gadgets,可以进行一系列操作随后将值写入EAX并返回。
可以使用如下命令在gdb中尝试调试:
|
|
如下图是我进行调试的一个片段
解题
从上面的解析可以看出,最后的返回值就是把flag进行一系列线性变换得到的,所以需要首先得到具体的线性变换,然后使用z3求解器进行求解。
下面的脚本用于求线性变换, 其中flag文件中填入的字符串为: hackim20{00000000000000000000000}
|
|
最后打印的dic中是flag中哪些字符串能够影响第i个输出的returncode.
下面的脚本用于使用z3的求解, 其中flag文件中填入的字符串依然是: hackim20{00000000000000000000000}
|
|
hackim20{B4byR0pDo0dOod00duDoo}
官方解法
blob是一个大型的ROP文件,所以本质是一个虚拟机,对输入的字符串进行一系列操作后,根据return输出。
|
|
翻译出来的字节码如下:
x86-64的寄存器作用如图所示:
rdi寄存器中是exit函数的参数,所以最后的返回值就是rdi中的值。
根据以上操作使用z3解题
|
|
参考链接
蒸米大佬的一步步学ROP系列
一步一步学ROP 之 Linux_x86篇
一步一步学ROP之linux_x64篇
一步一步学ROP之gadgets和2free篇