setcontext+mprotect+orw
摆烂多日的第一次提笔,这篇博客其实想写好久了,但是由于各种原因拖到现在,不说废话了,直接开写。
先细致的讲解一下setcontext和orw
setcontext
一个大概函数一样的东西,主要作用就是把通过它把程序跳转到我门已经设置好的rop上面,使用这个手法的条件有两个,一个是你能跳到这个函数上面(拿到程序流),二是控制了rip,下面是setcontext的汇编代码
1 | 0x00007fc35bf5f1b5 <+53>: mov rsp,QWORD PTR [rdi+0xa0] |
不是跳到setcontext的开头,而是跳到53这个位置,当执行下面的代码后,就可以通过rip给很多寄存器赋值,包括rsp,还能通过rcx控制栈顶信息,操作手法就是先通过rdi+0xa0把rsp指向我们伪造的rop的地址,然后再通过rdi+0xa8让rcx储存ret的地址,然后把ret的地址push到栈上,最后的执行顺序就是这样
1 | 0x7fe87be4e1ff <setcontext+127> ret //自己的ret |
然后还可以通过rop再把程序流跳到别的地方,很好玩。
orw
当有些程序被沙箱保护后就不能直接调用system(“/bin/sh”)来拿到权限了,比如这个程序
1 | rootzhang@ubuntu:~/get-shell/tcache/HITCON 2019 one_punch_man$ seccomp-tools dump ./pwn |
只允许程序调用read,write,open和mprotect这几个我认识的函数,那就只能orw了,不过现在在我看来orw有两种类型,一种是构造rop来完成打印flag,一种是直接构造代码,让他执行orw代码(不过这种需要mprotect协助),调用orw需要通过系统调用来完成,即syscall,每个函数都对应一个调用号,比如open的调用号是2,read的调用号是0,write的调用号是1,调用时对rax赋值就行。
完成前置知识,下面具体题目具体分析
HITCON 2019 one_punch_man
算是复现的最艰难的一道题,除了一些不知道的glibc的特性以外,还因为按照wiki上的思路复现的代码就跑不通,最后自己想出来一个这个笨办法。
源码太长就不看了,主要有四个功能,漏洞是ufa,然后一般情况下只能使用calloc,calloc不能使用tcache上面的堆,其次堆的大小设置为大于0x80,意味着也不能使用fastbin上面的堆,在glibc高版本的情况下使用出fast和tcache的堆拿到程序流很难,好在程序给了后门函数
1 | __int64 __fastcall sub_15BB(__int64 a1, __int64 a2) |
只要让这个地址的数大于6就行,当一个地址的数变大首先想到了unsortedattackbin,但libc.2.27.so已经对unsortedbin上面的堆严加管控,当一个堆脱离时,会严格检查fd和bk,通过wiki得知smallbin配合tcache也可以完成类似的行为,比如先让tcache上面的0x200的bin上六个堆,让smallbin的0x200上面上2个堆,然后申请0x200,首先会分配smallbin上面的一个堆给你,让后把另一个堆脱链放入tcache上面,只要更改后面的bk,让其脱链的时候就可以向bk->fd写入一个地址了,这个地址肯定很大,和unsortedbin的思路很像。
1 | pwndbg> bins |
注意修改bk的时候也得让fd有意义,不然fd->bk=bk就会不成立
修改完后就可以使用malloc了,哦对当smallbin上的堆进入tcache上面时tcache就会出问题,不能进只能出,所以0x217得先准备好才行。
脚本
网上搜了一圈,没有像我做的这复杂的,我是用mprotect做的
1 | from pwn import * |