Tokyo Westerns CTF 2018 - Neighbor C
๋ชฉ์ฐจ
0x00. Introduction
Environment
์ ๊ณต๋ libc๊ฐ ์์ ๋ฒ์ ์ด๋ผ ์ต์ loader๋ก ๋ก๋๊ฐ ์๋๋ค. ๊ทธ๋ ๋ค๊ณ ๋ก์ปฌ libc๋ฅผ ์ด์ฉํ๋ฉด ํ์ด๊ฐ ์ด๋ ค์์ง๊ธฐ ๋๋ฌธ์ docker๋ก ์๋ฒ๋ฅผ ๊ตฌ์ฑํด์ ํ๊ฒฝ์ ๊ตฌ์ถํ๊ธฐ๋ก ํ๋ค.
์ด๋ ๊ฒ ์๋ฒ๋ฅผ ๊ตฌ์ฑํ๋ฉด 9999 ํฌํธ๋ฅผ ๋ฆฌ์ค๋ํ๋ค๊ฐ ์ฐ๊ฒฐ์ด ๋๋ฉด EXEC:/home/user/neighbor๋ฅผ ํตํด neighbor ํ๋ก์ธ์ค๋ฅผ ์คํํ๋ค.
๊ทธ๋์ ๊ธฐ์กด์ exploit.py ํฌ๋งท์ผ๋ก๋ ์ฐ๊ฒฐ์ด ๋ถ๊ฐ๋ฅํ๊ณ , ๋ค์๊ณผ ๊ฐ์ด ์์ ํด์ค์ผ ์ ๋๋ก ๋๋ฒ๊น
์ ํ ์ ์๋ค.
=
=
=
=
=
๊ทธ๋ฆฌ๊ณ ๋๋ฒ๊ฑฐ๊ฐ libc๋ฅผ ์ ๋๋ก ์ฝ์ด์ ์ฌ๋ณผ์ ๋ก๋ํ๊ธฐ ์ํด์ sysroot ์ธ์๋ฅผ ์คฌ๋๋ฐ, ๊ทธ๋ฌ๋ฉด ํ์ฌ ์์น๋ฅผ root ๋๋ ํ ๋ฆฌ๋ก ์ธ์ํ๊ณ libc ํ์ผ์ ์ฐพ๊ฒ ๋๋ค. ๋ฐ๋ผ์ vmmap์ ํตํด libc ๊ฒฝ๋ก๋ฅผ ํ์ธํ๊ณ ๊ทธ์ ๋ง์ถฐ์ ๋๋ ํ ๋ฆฌ๋ฅผ ์์ฑํ ํ libc ํ์ผ์ ๋ณต์ฌํด์ฃผ๋ฉด ๋๋ค.
0x01. Vulnerability
void __fastcall __noreturn
void __noreturn
void __fastcall __noreturn
๋ฐ์ด๋๋ฆฌ๋ฅผ ๋ณด๋ฉด sub_8D0()์์ fprintf์ format์ ์ง์ ์
๋ ฅํ ์ ์์ด FSB๊ฐ ๋ฐ์ํ๋ค.
์ ๋ฒ ๋ฌธ์ ์์๋ ๊ฒฝํํ์ง๋งโฆ ์ทจ์ฝ์ ์ด ๊ฐ๋จํ๋ฉด exploit์ด ๋ณต์กํด์ง๋๋ฐ ์ด ๋ฌธ์ ๋ ๊ทธ๋ฐ ๊ฒ ๊ฐ๋ค.
0x02. Exploit
Stack Control
์ทจ์ฝ์ ์ ํ์ฉํ๊ธฐ์ ์์ ๋ฌธ์ ๋ format์ด ์ ์ญ๋ณ์์ด๊ธฐ ๋๋ฌธ์ stack์ ๊ฐ์ ์
๋ ฅํ ์๊ฐ ์๋ค. ๊ทธ๋ฌ๋ฉด stack์ ํฌ์ธํฐ๋ฅผ ๋ง๋ค ์ ์์ด์ FSB์ ํต์ฌ์ธ %n์ ํตํด ํฌ์ธํฐ๊ฐ ๊ฐ๋ฆฌํค๋ ๊ณณ์ ๊ฐ์ ์ฐ๋ ๊ฒ์ด ๋ถ๊ฐ๋ฅํ๋ค. ๋ฐ๋ผ์ stack์ ์๋ ๊ฐ์ผ๋ก ์ ์ ํ๊ฒ ์ํ๋ ๊ณณ์ ๊ฐ์ ์ธ ์ ์๋ primitive๋ฅผ ํ๋ํด์ผ ํ๋ค.
๊ทธ๋์ fprintf()๋ฅผ ํ ๋์ stack์ ์ถ๋ ฅํด๋ณด์๋๋ฐ, push rbp๋ฅผ ํ๋ค๊ฐ ์๊ธด stack ์์ญ์ ์ฃผ์๊ฐ ๋ ๊ฐ ์์๋ค. ์ฌ๊ธฐ์์ ์ ๊ตณ์ด main() -> sub_937() -> sub_8D0()์ผ๋ก ํจ์๋ฅผ ํธ์ถํ ๊น์ ๋ํ ์๋ฌธ์ด ํ๋ ธ๋๋ฐ, Double Staged FSB๊ฐ ๊ฐ๋ฅํ๊ฒ ํ๊ธฐ ์ํจ์ด์๋ค.
0x7fffffffebd0($rsp+0x20)์ด 0x7fffffffebe0($rsp+0x30)์ ๊ฐ๋ฆฌํค๊ณ ์์ด์ FSB๋ฅผ ์ด์ฉํ๋ฉด 0x7fffffffebe0์ ์ํ๋ ์ฃผ์๋ฅผ ๊ตฌ์ฑํ ์ ์๋ค.
0x7fffffffebd0์ด 9๋ฒ์งธ format string์ด๊ธฐ ๋๋ฌธ์, ๋ค์๊ณผ ๊ฐ์ด payload๋ฅผ ์์ฑํ๋ฉด 0x7fffffffebe0์ ๋ด๊ฒจ์๋ ๊ฐ์ ์ปจํธ๋กคํ ์ ์๋ค.
%1c%9$hhn: 0x00007fffffffebf0 -> 0x00007fffffffeb01%258c%9$hn: 0x00007fffffffebf0 -> 0x00007fffffff0102%16909060c%9$n: 0x00007fffffffebf0 -> 0x00007fff01020304
๋๋ฒ๊น
ํ๊ฒฝ์์๋ ํธ์๋ฅผ ์ํด ASLR์ ๊บผ๋์๊ธฐ ๋๋ฌธ์ $rsp์ ์ฒซ ๋ฐ์ดํธ๊ฐ 0xb0๋ก ๊ณ ์ ๋์ด์์ง๋ง, ์ค์ ์๋ฒ ํ๊ฒฝ์์๋ ASLR์ด ์ผ์ ธ์์ ๊ฒ์ด๋ฏ๋ก ์ด ๋ 1/16 ํ๋ฅ ๋ก exploit ์ฑ๊ณต๋ฅ ์ด ๋จ์ด์ง๊ฒ ๋๋ค.
์๋ฌดํผ ๋ก์ปฌ ํ๊ฒฝ์์๋ ์๋ฌ ๋ฉ์ธ์ง๋ ๋ณผ ์ ์๊ธฐ ๋๋ฌธ์ fprintf(stderr, format) ๊ฒฐ๊ณผ๋ฅผ ๋ณผ ์ ์์๋๋ฐ, ์๋ฒ ํ๊ฒฝ์์๋ ์๋ฌ ๋ฉ์ธ์ง๋ฅผ ๋ณผ ์๊ฐ ์๋ค. ๋ฐ๋ผ์ ์ stack control์ ํตํด ๋จผ์ ํด์ผํ ๊ฒ์ stderr๋ฅผ stdout์ผ๋ก ๋ง๋ค์ด์ ๋ค์ ๋จ๊ณ๋ก ๋์ด๊ฐ๋ ๊ฒ์ด๋ผ๊ณ ํ๋จํ๋ค.
Libc Leak
# fprintf(stderr, format);
fprintf์ stderr๋ libc์ Data์์ญ์ ์๋ stderr๊ฐ ์๋, sub_8D0()๋ฅผ ํธ์ถํ ๋ ์ธ์๋ก ์ ๋ฌํ stack์ ์๋ stderr์ด๋ค. ๊ทธ๋ฆฌ๊ณ ์ด stderr๋ $rbp-0x8์ผ๋ก ์ ๊ทผํ ์ ์๋๋ฐ, ์ด ์ฃผ์๋ 0x7fffffffebc8($rsp+0x18)์ด๋ค.
๋คํํ ์ปจํธ๋กคํ ์ ์๋ 0x7fffffffebe0์ ์ด๋ฏธ stack ์์ญ์ ์ฃผ์๊ฐ ๋ด๊ฒจ์์ผ๋ฏ๋ก, ์ฒซ ๋ฐ์ดํธ๋ง 0xc8์ผ๋ก ๋ฎ์ผ๋ฉด 0x7fffffffebe0์ด 0x7fffffffebc8์ ๊ฐ๋ฆฌํค๊ฒ ๋๋ค. ๊ทธ๋ฌ๋ฉด 0x7fffffffebe0์ด 11๋ฒ์งธ format string์ด๊ธฐ ๋๋ฌธ์ stderr๋ฅผ stdout์ผ๋ก ๋ฐ๊ฟ ์ ์๋ค.
ํ์ง๋ง ์ฌ๊ธฐ์์๋ stderr์ stdout์ ๋ ๋ฒ์งธ ๋ฐ์ดํธ๊ฐ ๋ค๋ฅด๊ธฐ ๋๋ฌธ์, 0x7fffffffebc8์ ์ฒซ ๋ ๋ฐ์ดํธ๋ฅผ 0x2620์ผ๋ก ๋ฎ์ด์ฐ๊ฒ ๋๋ฉด ASLR์ ์ํด ๋๋ค์ exploit ํ๋ฅ ์ด 1/16์ด ๋๋ค.
์ต์ข ์ ์ผ๋ก๋ 1/256 ํ๋ฅ ๋ก exploit์ด ๊ฐ๋ฅํ๋ค.
์ด๋ ๊ฒ ์ป์ด์ง stdout์ผ๋ก format string์ ์ถ๋ ฅํด๋ณธ ๊ฒ๊ณผ ์ค์ stack์ ๋ด์ฉ์ ๋น๊ตํ๋ฉด ์์ ๊ฐ๋ค.
์์ธํ ๋ณด๋ฉด 5๋ฒ์งธ format string๋ถํฐ stack์ ๋ด์ฉ๊ณผ ์ผ์นํ๋ ๊ฒ์ ํ์ธํ ์ ์๋๋ฐ, stack ์์ format string์ ๋ค์ calling convention์ ๋ฐ๋ผ ๋ ์ง์คํฐ์ ๊ฐ๋ค์ ์ถ๋ ฅํด์ค๋ค๊ณ ํ๋ค.
rsi,rdx,rcx,r8,r9
ํ์ง๋ง ์ ๊ฒฝ์ฐ๋ rdx๋ถํฐ ์ถ๋ ฅ๋๋ ๊ฒ์ ๋ณผ ์ ์๋๋ฐ, fprintf์ ๋ ๋ฒ์งธ ์ธ์๊ฐ ๋ค์ด๊ฐ์ ๊ทธ๋ฐ๊ฒ ์๋๊น ์๊ฐํ๋ค.
์๋ฌดํผ ๋ค์ ๋์์์ stack์ 10๋ฒ์งธ ๊ฐ์ libc์ ์ฃผ์๊ฐ ๋ค์ด๊ฐ์์ผ๋ฏ๋ก offset์ ๊ณ์ฐํด์ ๋นผ์ฃผ๋ฉด libc์ base ์ฃผ์๋ฅผ ํ๋ํ ์ ์๋ค.
Triggering malloc
์ด์ ๊ฐ์ฅ ์ค์ํ ์ด๋์ ๋ฌด์์ ์ธ ๊ฒ์ธ์ง์ ๋ํ ๋ถ๋ถ์ธ๋ฐ, ์์ libc๋ผ์ malloc_hook์ ์ฌ์ฉํ ์ ์๋ค. ๋ฐ๋ผ์ ์ด๋์๋ ๊ฒฐ์ ๋์๊ณ , one shot ๊ฐ์ ฏ์ ํ์ธํด๋ณด์๋ค.
)
|| }
)
|| }
)
|| }
๋คํํ ์กฐ๊ฑด์ด ๋นก์ธ์ง ์์์ ํ์ธํด๋ดค๋๋ฐ, 0xf1247์ ์์นํ ๊ฐ์ ฏ์ด ํ์ฉํ ์ ์์ด ๋ณด์๋ค. ๋ฐ๋ผ์ ๋ฌด์์๋ ์์ฐ์ค๋ฝ๊ฒ ํด๊ฒฐ๋์๋๋ฐ, ๋ง์ ์๊ฐํด๋ณด๋ malloc์ ์ด๋์ ๊ฐ ํธ์ถํด์ผ malloc_hook์ด ํธ์ถ๋ ๊ฒ์ธ๋ฐโฆ
while๋ฌธ ํ๋ฆ์ ํธ์ถ๋๋ ํจ์๋ fgets์ fprintf๋ฐ์ ์๋ค.
ํน์ ํจ์ ๋ด๋ถ์ ์ผ๋ก malloc์ด ํธ์ถ๋๋์ง ํ์ธํด๋ณด๋ ค๊ณ ํ๋๋ฐ, fgets๋ ๊ฐ๋จํด์ malloc์ด ์๋ค๋ ๊ฒ์ ํ์ธํ ์ ์์๋ค. ๋ฐ๋ฉด fprintf๋ vfprintf์ ํธ์ถํ๋๋ฐ ์ด ์์ ๋๋ฌด ๋ง์ ์ฝ๋๊ฐ ์์ด์ ํ์ธ์ด ์ด๋ ค์ ๋ค.
๊ทธ๋์ ๊ตฌ๊ธ๋ง์ ํด๋ณด๋ ์ ๋ณด๊ฐ ์กฐ๊ธ ์์๋ค.
- https://stackoverflow.com/questions/6743034/does-fprintf-use-malloc-under-the-hood
- https://github.com/Naetw/CTF-pwn-tips?tab=readme-ov-file
ํ์ธํด๋ณด๋ format string์ ํตํด ๋ง๋ค์ด์ง output string์ด ์ฌ์ด์ฆ๊ฐ 0x10001 ์ด์์ด๋ฉด malloc์ ํธ๋ฆฌ๊ฑฐํ ์ ์๋ ๊ฒ ๊ฐ๋ค.
๊ทธ๋์ ๊ฑฐ๊พธ๋ก malloc์ ํธ์ถํ๋ ํจ์, j_malloc์ ํธ์ถํ๋ ํจ์๋ฅผ xrefํด๋ดค๋๋ฐ vfprintf๊ฐ ์๋ ๊ฒ ๊น์ง๋ ํ์ธํ๋ค.
Arbitrary Write
์, ๋ค์ stack์ ๋ณด๋ฉด 0x7fffffffebc0($rsp+0x10)์ด NULL๋ก ๋น์ด์๋ค.
์ด ๋น์ด์๋ ๊ณต๊ฐ(free_space)์ Double Staged FSB๋ฅผ ์ด์ฉํด 1์ฐจ์ ์ผ๋ก ์ฐ๋ฆฌ๊ฐ ์ํ๋ ์ฃผ์(addr)์ ๋ง๋ค์ด์ฃผ๊ณ , ๋ง๋ค์ด์ง ์ฃผ์๋ฅผ ํฌ์ธํฐ๋ก ์ฌ์ฉํด ๋ค์ Double Staged FSB๋ฅผ ์ด์ฉํ์ฌ ์ํ๋ ๊ฐ(value)์ ์ธ ๊ฒ์ด๋ค.
๋น์ฐํ addr์ malloc_hook์ด ๋ ๊ฒ์ด๊ณ , value๋ ๋ก๋ฉ๋ ์์น์ one shot ๊ฐ์ ฏ์ด ๋ ๊ฒ์ด๋ค. ์ด ๊ณผ์ ์ python์ผ๋ก ๋ง๋ค๋ฉด ๋ค์๊ณผ ๊ฐ์ด ๋ง๋ค ์ ์๋ค.
= + 0x10
= f
+= b
= f
+= b
= f
+= b
์ฌ์ค ๋ถํ์ํ payload๊ฐ ๋ง์ด ๋ณด๋ด์ ธ์ ํจ์จ์ ์ด์ง ์์ง๋ง, ํ๋ค๋ณด๋ ์์ฌ์ด ๋์ ๋ผ์ธ ํ๋๋ก arbitrary write๋ฅผ ํ ์ ์๊ฒ ๋ง๋ค์๋ค.
0x03. Payload
= True
=
=
= 0x0000555555400000
= 0xb0
= 0x3c4b10
= 0xf1247
=
= f
=
= + 0x10
= f
+= b
return
= f
+= b
= f
+= b
=
=
=
=
=
# overwrite stderr in stack to stdout
# leak libc base
= b
= - 0x20840
= +
= +
# write one_gadget address to malloc_hook
# trigger malloc -> malloc_hook