Codegate CTF 2019 - 7amebox-tiny_adventure
๋ชฉ์ฐจ
0x00. Introduction
๊ธฐ๋ณธ์ ์ธ ๊ตฌ์กฐ๋ 7amebox-name๊ณผ ๋์ผํ๋ค.
Global variables
int dog_count_0x1000;
int *dog_avatar_0x1003;
int *map_0x1303;
int sell_count_0x1306;
int hp_0x1309;
int power_0x130c;
int x_0x130f;
int y_0x1312;
Concept
)
)
)
)
)
>1
) =
# (\x23) = wall
) =
)
##############################################################
#@ #
# a f #
# #
# v z #
# i p #
##############################################################
stage.map ํ์ผ์ ์ฝ์ด ๋ฉ๋ชจ๋ฆฌ์ ๋ก๋ํ ํ w, a, s, d๋ฅผ ํตํด ์์ง์ด๋ค๊ฐ monster๋ฅผ ์ก์ผ๋ฉด ์์ฑ๋๋ *์ ํ๋ํด์ power up์ ํ๋ค. ์ด ์ธ์๋ ์ทจ์ฝ์ ํธ๋ฆฌ๊ฑฐ๋ฅผ ์ํ buy_dug, sell_dog ๋ฉ๋ด๊ฐ ์๋ค.
Goal
void
stage.map์ ์๋ z๋ฅผ ๋ง๋ ๊ฒฝ์ฐ boss ์คํ
์ด์ง๊ฐ ์ด๋ฆฌ๊ณ , hp๋ ์ฌ์ค์ ๊ด๊ณ ์์ด power๋ง 0x2bc๋ณด๋ค ํฌ๊ฑฐ๋ ๊ฐ์ผ๋ฉด flag๋ฅผ ์ถ๋ ฅํด์ค๋ค.
ํ์ง๋ง map์ ์๋ ๋ชจ๋ monster๋ฅผ ์ก์๋ power ๊ฐ์ 0x2bc๋ณด๋ค ํฌ๊ฒ ๋ง๋ค ์ ์๊ธฐ ๋๋ฌธ์ exploit ๋ฐฉํฅ์ map์ ์ ๋ณด๋ฅผ ์กฐ์ํ๋ ๊ฒ์ผ๋ก ์ก์๋ค.
0x01. Vulnerability
Firmware ์คํ ํ ์ฒ์ ์คํ๋๋ load_map_0x103() ํจ์์์ ๋ค์๊ณผ ๊ฐ์ ์ ์ญ๋ณ์ ์ด๊ธฐํ๊ฐ ์ด๋ฃจ์ด์ง๋ค.
int
์ด ์ค dog_avatar_0x1003์ ๋ค์๊ณผ ๊ฐ์ด ํ์ฉ๋๋ค.
void
syscall์ ํตํด์ ๋ฉ๋ชจ๋ฆฌ ํ ๋น์ด ์ฑ๊ณตํ๋ฉด dog_count_0x1000์ด ์ฆ๊ฐํ๊ณ ํด๋น index์ ํ ๋น๋ ๋ฉ๋ชจ๋ฆฌ ์์ญ ์ฃผ์๋ฅผ ์ด๋ค.
๊ทธ๋ฐ๋ฐ dog_count_0x1000์ boundary check๋ฅผ ํ์ง ์๊ธฐ ๋๋ฌธ์ ๊ฐ์ด 0x101์ด ๋ ๊ฒฝ์ฐ dog_avatar_0x1003 ๋ฐฐ์ด ๋ค์ ์๋ map_0x1303์ ๊ฐ์ ์ธ ์ ์๊ฒ ๋๋ค. map_0x1303์๋ stage.map์ ๋ด์ฉ์ ์ฝ์ด ์ ์ฅํ ๋ฉ๋ชจ๋ฆฌ ์ฃผ์๊ฐ ๋ด๊ฒจ์๊ธฐ ๋๋ฌธ์ ์ด๋ฅผ ์กฐ์ํ ๊ฒฝ์ฐ map ์ ๋ณด๋ฅผ ์กฐ์ํ ์ ์๋ค. ๊ฒ๋ค๊ฐ avatar๋ฅผ ๊ทธ๋ฆฐ๋ค๋ ๋ช
๋ชฉ์ผ๋ก ํ ๋น๋ฐ์ ๋ฉ๋ชจ๋ฆฌ์ ๊ฐ์ 0x1000๋งํผ ์ธ ์ ์์ด์ map์ ๋ด์ฉ๋ ๋ง์๋๋ก ์กฐ์ํ ์ ์๋ค.
do )
>n
do )
>n
๋ฌธ์ ๋ 0xfb๋ฒ๋ง ํ ๋น์ด ๋๊ณ ์คํจํ๋๋ฐ ์ด์ ๋ฅผ ํ์ธํด๋ณด๋,
์ด๋ฏธ ํ ๋น๋์ด์๋ page๊ฐ ์๊ณ emulator์์ 0x0 ~ 0xff000์์ญ๋ง ํ ๋น ๊ฐ๋ฅํ ์์ญ์ผ๋ก ์ ์ฅํ๊ธฐ ๋๋ฌธ์ด์๋ค.
=
=
= 0
...
...
= # 0x100000
...
๋ฐ๋ผ์ index ์ญํ ์ ํ๋ dog_count_0x1000 ๊ฐ์ 0xfb์์ 0x101๊น์ง ๋ค๋ฅธ ์ทจ์ฝ์ ์ ์ด์ฉํด์ ์ฆ๊ฐ์์ผ์ผํ๋๋ฐ, sell_count_0x1306 ๊ฐ์ด ๋ฑ ๊ทธ ์ฐจ์ด์ธ 0x6์ด๋ฏ๋ก sell_dog_0x304()๋ฅผ ํ์ฉํด์ผ ํ๋ค๋ ํฉ๋ฆฌ์ ์ธ ์ถ๋ก ์ ํด๋ณผ ์ ์๋ค.
void
ํ์ง๋ง sell_dog_0x304()์ ์ฝ๋๋ฅผ ๋ณด๋ฉด unmappingํ ์ฃผ์๊ฐ 0x100000๋ณด๋ค ์์ผ๋ฉด syscall์ ํธ์ถํ ์ ์๋ค. ๊ทธ๋ฐ๋ฐ ๋์ ๋ถ์์ ํ ๋ AAAA๋ฅผ ์
๋ ฅํ๋๋ unmapping์ด ์ฑ๊ณตํ ๊ธฐ์ต์ด ์์ด emulator ์ฝ๋๋ฅผ ํ์ธํด๋ณด์๋ค.
...
# munmap
= & 0b111111111000000000000
...
...
= & 0b1111
...
Emulator์์ sys_s6()์ด ํธ์ถ๋๋ฉด Memory ๊ฐ์ฒด์ set_perm() ํจ์๋ฅผ ํตํด page์ ๊ถํ์ 0b0000์ผ๋ก ๋ง๋ค์ด๋ฒ๋ฆฐ๋ค. ๊ทธ๋ฐ๋ฐ ์ด ๊ณผ์ ์์ ํด๋น page๊ฐ ์กด์ฌํ๋์ง ํ์ธํ์ง ์๊ณ ๊ถํ์ ์
๋ ฅํ๋๋ฐ, python์ dictionary์์ ์กด์ฌํ์ง ์๋ key์ ๊ฐ์ ์
๋ ฅํ๋ฉด key-value ์์ ์์ฑํด์ ์ ์ฅํ๋ค.
๋ฐ๋ผ์ ์กด์ฌํ์ง ์๋ ์์ญ์ธ AAAA ์์ญ๋ unmapping์ด ๊ฐ๋ฅํ๊ณ , ์ด ์์ญ์ด pages dictionary์ ์ ์ฅ๋๋ฏ๋ก ํ ๋น๋ ๊ฐ๋ฅํ๋ค. ๋ฌผ๋ก ํ ๋น ์ดํ ๊ฐ์ ์ฐ๊ฑฐ๋ ์ฝ์ผ๋ ค๊ณ ํ๋ฉด memory size๋ฅผ ๋์ด๊ฐ๋ฏ๋ก ์๋ฌ๊ฐ ๋๋ค. ํ์ง๋ง dog_count_0x1000๋ฅผ ์ฆ๊ฐ์ํค๋ ๊ฒ์ด ๋ชฉ์ ์ด๋ฏ๋ก munmap -> map์ 6๋ฒ ์ํํ๊ณ write๊ฐ ๊ฐ๋ฅํ ์์ญ์ map ์ ๋ณด๋ฅผ ์ฐ๋ฉด ๋๋ค.
0x02. Exploit
Emulator๊ฐ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ํ ๋นํด์ฃผ๋ ๊ณผ์ ์ ๋ค์๊ณผ ๊ฐ๋ค.
return
return -1
return
return -1
์ด๋ ๊ฒ addr์ด ์ ํด์ง์ง ์์์ ๋, pages dictionary๋ฅผ ์ํํ๋ฉฐ PERM_MAPPED ๊ถํ์ด ์๋ page๋ฅผ returnํด์ค๋ค.
python 2.7์์๋ dictionary๋ฅผ ์ํํ ๋ ๋๋คํ ์์๋ก ์ํํ๋๋ฐ๋ค, ๊ฐ์ ์ดํ์ ์ถ๊ฐํ๋ค๊ณ ํ๋๋ผ๋ ์์๊ฐ ๋งจ ๋ค์ ์ค๋ ๊ฒ์ด ์๋๋ผ ์ค๊ฐ์ ๋ ์๋ ์๋ค.
# Python 2.7.18
>>> =
>>>
... print ,
...
>>> = 5
>>>
... print ,
...
๋ฐ๋ผ์ Memory ๊ฐ์ฒด์ pages dictionary์ key-value ๊ฐ์ ์ถ๊ฐํ๋ค๋ฉด ๋์ ํ๋ฅ ๋ก ์ค๊ฐ์ key๊ฐ ์ฝ์
๋ ๊ฒ์ด๋ค. ์ค์ ๋ก emulator๊ฐ pages dictionary๋ฅผ ์์ฑํ๊ณ unmapping์ ํ๋ ๊ณผ์ ์ ๋ฐ๋ผํด๋ณด๋ฉด ๋ค์๊ณผ ๊ฐ์ ๊ฒฐ๊ณผ๋ฅผ ์ป์ ์ ์๋ค.
>>> =
>>> # Memory.__init__()
... = 0
...
>>> = 0 # Memory.set_perm()
>>> # Memory.allocate()
...
... print %
...
0x100000 is 98-
>>> print %
0x78000 is 256-
๋ฐ๋ผ์ ๋ง์ง๋ง page์ธ 0x78000 ์์ญ์ ๋จ๊ฒจ๋๊ณ ๋ชจ๋ ์์ญ์ ํ ๋นํ๊ธฐ ์ํด ๋ค์๊ณผ ๊ฐ์ด payload๋ฅผ ๊ตฌ์ฑํ๋ค.
์ด๋ฌ๋ฉด dog_count_0x1000๋ 0xfa๊น์ง ์ฆ๊ฐํ์ ๊ฒ์ด๊ณ , sell_dog_0x304()๋ฅผ ์ด์ฉํ์ฌ 0x6๋งํผ ๋ ์ฆ๊ฐ์ํค๋ ๋ฐฉ์์ ๋ค์๊ณผ ๊ฐ๋ค.
๋ง์ง๋ง์ผ๋ก ๋จ์ 0x78000 ๋ฉ๋ชจ๋ฆฌ๋ฅผ ํ ๋น๋ฐ์ผ๋ฉด ๋ง์นจ๋ด dog_count_0x1000๋ 0x101์ด ๋๋ฉด์ map_0x1303์ด 0x78000์ผ๋ก ๋ฎ์ด๊ฒ ๋๋ค.
์ด์ avatar๋ฅผ ๊ทธ๋ฆฌ๊ธฐ ์ํด ์
๋ ฅํ๋ ๊ฐ์ด ๊ทธ๋๋ก map ์ ๋ณด๊ฐ ๋๋ฏ๋ก, ๋์ ์์น์ boss๋ฅผ ์ ์ธํ map์ ๋ชจ๋ power up์ ์๋ฏธํ๋ *์ผ๋ก ์ฑ์๋ฃ๊ธฐ ์ํ payload๋ ๋ค์๊ณผ ๊ฐ๋ค.
= b
+= b * 3598
+= b
์ด์ ๋จ์ ๊ฒ์ ์ถฉ๋ถํ power๋ฅผ ๋๋ ค์ boss์ ์ธ์ฐ๋ ๊ฒ์ธ๋ฐ, boss๋ฅผ ์ด๊ธฐ๊ธฐ ์ํ ์กฐ๊ฑด์ power๊ฐ 0x2bc๋ณด๋ค ํฌ๊ฑฐ๋ ๊ฐ์ ๊ฒ์ด๊ณ power up์ ํ๋ฉด power๊ฐ 0x5๋งํผ ์ฆ๊ฐํ๋ฏ๋ก, ์ต์ 121๋ฒ์ power up์ด ํ์ํ๋ค ํ์ฌ map์ ๋ชจ๋ ์๋ฆฌ๊ฐ *์ผ๋ก ์ฑ์์ ธ์์ผ๋ฏ๋ก ์ด๋๋ก๋ 121๋ฒ ์ ์ ์ด๋ํ ์ ์ด ์๋ ๊ณณ์ผ๋ก ์ด๋ํ๋ฉด ๋๋ค.
0x03. Payload
=
=
=
return
return
return
return
=
=
= b
+= b * 3598
+= b
0x04. Decompile
char *str_0x6e2 = "====================================================\
| PWN ADVENTURE V8.6 |\
====================================================\
| __ |\
| _|^ |________ |\
| (____| |___ |\
| |________| |\
| | | | | |\
| |\
----------------------------------------------------";
char *str_0xc66 = "====================================================\
| YOU WERE DEAD! |\
====================================================\
| HP : 0 |\
| |\
| |\
| ... |\
| ___ |\
| |___| |\
----------------------------------------------------";
char *str_0x6a5 = " direction\
________________________________\
| W : north |\
| A : west D : east |\
| S : south |\
|________________________________|";
char *str_0x9c5 = "-------------------------------------------------\
* (\x2a) = power up\
# (\x23) = wall\
@ (\x40) = you\
a ~ y = monster\
z = boss monster (flag)\
-------------------------------------------------";
int dog_count_0x1000;
int *dog_avatar_0x1003;
int *map_0x1303;
int sell_count_0x1306;
int hp_0x1309;
int power_0x130c;
int x_0x130f;
int y_0x1312;
int
void
int
int
void
void
void
void
void
void