题目地址:b0verfl0w
1.基本信息收集
1.文件信息
2.查看保护
3.IDA查看反汇编代码
2.漏洞定位及利用思路
Stack pivot
可以看到vul()函数存在栈溢出漏洞,但是很明显我们可以利用的空间并不大,由上图注释,s到bp距离为20字节,而bp占4字节,所以能溢出的栈空间只有50-0x20-4=14字节。所以我们再进行ROP技术就变的困难许多。
不过我们可以用Stack pivot(劫持栈指针)的方法,下面简单介绍一下,内容摘自ctf-wiki。
是什么?
劫持栈指针(Stack pivot)就是改写rsp(esp),使其指向其他位置。这样栈也就被劫持到攻击者控制的内存上去,然后在该位置做ROP。
为什么?
1.可以控制的栈溢出的字节比较少,难以构造较长的ROP链,无法直接利用溢出字节进行ROP
2.开启了PIE保护,栈地址未知,并且无法泄露,但是利用某些技术(如ret2dl-resolve)时,必须知道栈地址,可以通过stack pivot将栈劫持到相应的区域
3.其它漏洞难以利用,stack pivot 能够将一些非栈溢出的漏洞,变成栈溢出的漏洞,例如,将程序劫持到堆空间中。
利用条件:
如果在尝试了直接Rop发现比较难实现,并且程序中有可以利用进行读写的函数,就可以考虑stack pivot
1.可以控制程序执行流
2.存在地址已知,内容可控的Buffer
(1) BSS,由于进程按页分配内存,分配给bss段的内存大小至少一个页(4k,0x1000)大小。然而一般bss段的内容用不了这么多的空间,并且bss段分配的内存页拥有读写权限
(2) 堆,但是需要我们能够泄露堆地址
3.可以控制sp指针,一般来说,控制栈指针会使用 ROP,常见的控制栈指针的 gadgets 一般是 pop rsp/esp
再回到题目:
由于可以控制的栈溢出的字节比较少,难以构造较长的ROP链,无法直接利用溢出字节进行ROP,但是满足Stack pivot的利用条件,所以本题可以用Stack pivot。
注意到存在一个hint函数,反汇编查看一下;
这是一个很重要的提示,我们稍后会用到。
接下来按照正常栈溢出的题目的套路来:
3.利用步骤
1.找填充值
1 | gdb-peda$ pattern create 100 /tmp/input |
填充值为36。所以我们需要填充36字节的垃圾值然后跟上要返回的地址(4字节)
我们的payload可以构造如下:
0x08048504为jmp esp 的gadgets(看前面提到的hint),覆盖了返回地址,当程序执行到ret时,将该地址pop给eip,并且esp会加4指向asm(sub esp,0x28;jmp esp),然后eip执行地址0x08048504上的代码jmp esp,eip又会执行esp指向的sub esp,0x28;jmp esp,完成esp的劫持。正常情况下eip指向的是.text段中的代码,所以需要将sub esp,0x28;jmp esp转化为机器码,这里是十六进制机器码。
至于为什么是sub 0x28,36byte+4byte=40byte=0x28byte。
2.编写exp
1 | from pwn import * |