Stack Pivot



原理

Stack pivot 劫持栈指针,是一种比较重要的栈溢出利用技术

目的是将栈劫持到一个攻击者能够控制的内存上去,在该位置再做Rop

它的原理十分简单,如下图:

我们控制了橙色部分区域,但是中间有一段不可控制的内存,这时,我们需要控制rsp跳转到橙色部分,继续执行我们的Rop指令,这就是stack pivot,当然上图中的情况是最简单的一种,劫持rsp有多中不同的姿势

利用

什么情况下需要利用stack pivot?
1.栈溢出的字节比较少,无法直接利用溢出字节进行Rop
2.栈地址未知并且无法泄露,但是利用某些利用技术时必须要知道栈地址,就可以通过stack pivot将栈劫持到相应的区域
3.stack pivot能够使得一些非栈溢出的漏洞变成为栈溢出漏洞从而进行攻击,典型:可以将程序劫持到heap空间中

如果在尝试了直接Rop发现比较难实现,并且程序中有可以利用进行读写的函数,就可以考虑stack pivot
stack pivot有什么利用条件?
1.存在内容可控的内存,位置已知,拥有读写的权限,有几个典型的位置可供选择

一个是bss段末有较大的空间,因为进程内存按页分配,分配给bss段的内存大小至少一个页(4k,0x1000)大小,一般bss段的内容是用不了这么大的空间的,并且bss段分配的内存页拥有读写权限,是stack pivot的好目标
另一个是heap空间,这个不用赘述了,但是需要注意泄露堆地址

2.控制rsp(esp),需要相应的Godgets,其中有一个最典型,在x64的libc_csu_init通过Godgets中,做一个适当偏移能够得到这样一个Godgets

可见是一个pop rsp ret,如果将ret的地址改成leave ,ret,那么我们正常通过pop rbp;pop r12;pop r13;pop r14执行到返回时,将rbp中的值相应设置好也可以劫持rsp
或者其他诸如add rsp,0x100等能够劫持rsp寄存器值的Godget
其他的还是需要依据题目的意图来寻找
3.控制流可以劫持

例题

EkoPartyCTF 2016 fuckzing-exploit-200

首先,题目之前需要输入一段team_name,这是比赛时一段逆向题目需要解出来的结果,具体过程不在赘述,请参考文章:

漏洞是一个简单的栈溢出,触发位置在reverse成功后输出flag的位置:

memcpy不安全拷贝将输入的team_name字后的字节拷贝到rbp-x020处造成栈溢出
由于题目中不能够进行ret2vuln,需要一次Rop完成leak libc 和 getshell,所以考虑应该进行stack pivot劫持栈指针到一个可控位置后,利用read和write函数进行读写,并在该位置上做Rop
找到劫持位置

可见,如上述所说,bss段后面的空间0x00606000 – 0x00607000拥有相关权限,可以用来作为栈指针空间
找到劫持栈指针的Godgets

并且在做rop时,我们利用libc_csu_init中的通用Godgets

首先,向劫持地址中read()并做stack pivot,将rsp劫持到pivot_addr,之后在该位置上做leak libc与最后的Ret2libc即可
注意,pop rsp 时应该为addr-0x18,因为之后还要pop r13 ; pop r14 ; pop r15 rsp会加0x18
exp:

Nullcon-hackim-2015/exploit-5

Atum推荐的另外一道Stack pivot的题目,应该是heap overflow ,触发漏洞stack pivot到heap的空间上,然后在heap上瞎搞
但是实际做下来,包括参考一些战队的wp发现,这道题目做stack pivot是比较困难的,因为没有合适的stack pivot的godgets,造成难以劫持栈到相应空间
然而,题目中拥有的任意地址读与任意地址写的权限,我们充分利用,能够比较轻松地做出题目
首先,逆向分析数据结构,发现题目中建立了这样一个结构体节点:
struct note{
char name[16]; //用户名
int length; //内容的长度
char *content;
note *bk;
node *fd;
}

第一个note名称为“HEAD”,其他note与HEAD note一起链接成一个doubled circle link,双向循环链表
其中store是增加note,get是打印note中的content,并且将相应的note在链表中删除,edit是重新编辑note中的content
漏洞是一个很明显的栈溢出,在Edit时,没有限制edit的大小,造成heap overflow

如果我们创建了两个note,通过重新edit note1溢出到第二个note的管理结构中,修改content指针,再通过get函数中的打印content内容,就能够造成任意地址读

同样,我们修改了content指针之后,在对受害的chunk note进行edit,能够造成任意地址写

于是思路很直接,首先leak libc
(由于本地测试,就用的本地的libc,如果是远程,就多泄露几个libc的函数,通过libc_base查找下载相应的libc)
之后,修改strncmp的got表为system,然后输入“/bin/sh”就能够起shell

但是在任意地址读的时候,发现由于get函数中

write后会直接free掉相应的地址,不进行控制free无效地址,于是,首先第一步先利用任意地址写将free的got表改成ret,日掉free的功能后按照上述思路能够成功利用

最后,正如题目名称mix,混杂的,这道题目的利用方法很多,有通过heap overlfow转成格式化字符串的,同样也有stack piovt的等等,参考如下:
HackIM CTF – Mixme
HACKIM CTF 2015 – Exploitation 5
[Write Up] Hackim CTF – mixme – PWN5

参考资料

Emerging ‘Stack Pivoting’ Exploits Bypass Common Security
ROP and DEP

发表评论