[DH] Exploit Tech: Return Oriented Programming

Return Oriented Programming

리턴 가젯 사용하여 실행 흐름 구현
RTL, Return to dl-resolve, GOT overwrite 등..

ROP 페이로드는 리턴 가젯으로 구성 Ret 단위로 여러 코드 연쇄적 실행 -> ROP chain이라고 한다.

// 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");
  write(1, "Buf: ", 5);
  read(0, buf, 0x100);
  printf("Buf: %s\n", buf);

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

  return 0;
}

위 코드 다시 보자. buf를 0x100 만큼 읽고 프린트하면 당연히 canary leak이 된다. 그리고 여기서 ROP 페이로드를 짜는 부분이 중요한데 그건 후술하자.

system 호출이 없기 때문에 우리가 가젯을 찾아서 가지고 와야 한다.

익스플로잇 설계

  1. 카나리 릭

  2. sytem 함수의 주소 계산
    이 함수는 libc.so.6에 정의되어 있다. read도 이 라이브러리에 있는데, 코드에 있다는 건 어느 주소이든 간에 libc.so.6이 통째로 매핑되어 있다는 뜻이다.

직접 호출하지는 않아서 GOT 등록은 아니지만, 이 GOT 값을 읽고 오프셋을 빼면 Libc.so.6 매핑 시작 주소를 알 수 있다. 여기서 system 오프셋을 더하면 함수 호출이 가능하다.

libc 파일이 있으면 readelf 명령어로 오프셋 구하기가 가능하다.

  1. “/bin/sh”
    pwndbg에서 일단 search로 찾아본다.