360春秋杯 smallest
分析

程序就简单的几句汇编,这里就是调用read函数,64位的read系统调用号为0,这里xor将rax设为了0,实际上这几行汇编代码就是调用了read(0, $rsp, 0x400),向栈顶写入0x400个字节数据,这题可以用SROP去做。
EXP
exp参考了yichen的博客https://www.yuque.com/hxfqg9/bin/erh0l7#cS7rH
首先是泄露栈的地址,写入/bin/sh,但是如何调用write函数呢,这里很巧妙,首先向栈中写入3个start_addr,就是read的地址,因为是写在栈顶的,其实就是返回地址。
1 | |
那么第一个read返回之后,又调用一次read,我们发送一字节\xb3,将第二个0x4000B0最后一位改了,改成0x4000B3,也就跳过了xor rax, rax,防止rax置零,而且因为我们调用了read并发送了一字节数据,read会返回读取的字节数到rax,那么rax此时变成了1,这样我们就可以调用write函数了。然后我们接收后8个字节的数据,因为前8个是0x4000B0,后面8字节才是栈地址。
write之后 
然后我们可以通过SROP去构造了,将read的栈迁移到上面我们接收到的栈地址,这样就不用计算偏移了,并通过发送15个字节将rax改成15调用Sigreturn,来恢复我们构造好的read。
1 | |
然后构造好execve的frame,我们可以打印出execve的frame有多长,发现是0x108的长度,那么将/bin/sh写入stack_addr+0x108的位置,然后同样向read输入15个字节调用Sigreturn恢复frame从而调用execve
1 | |
完整的EXP:
1 | |