๋ฌธ์ : DreamHack โ secret message ๋ถ๋ฅ: Reversing ๋์ด๋: ๐ฅ Bronze 1 FLAG:
DH{93589e6c1db065fa95075ab5e3790bc1}
๋ฌธ์ ๊ฐ์
| ํญ๋ชฉ | ๋ด์ฉ |
|---|---|
| ๋ฌธ์ ๋ช | secret message |
| ๋์ด๋ | ๐ฅ Bronze 1 (614๋ช ํด๊ฒฐ) |
| ๋ถ๋ฅ | Reversing |
| ์ ๊ณต ํ์ผ | prob(ELF64 PIE, stripped), secretMessage.enc(1332B), imageviewer.py |
| ํต์ฌ ๊ธฐ๋ฒ | ์คํธ๋ฆฝ ๋ฐ์ด๋๋ฆฌ ์ ์ ๋ถ์(objdump) + ์ปค์คํ RLE ์๊ณ ๋ฆฌ์ฆ ์ญ์ฐ + gdb ๋ฐํ์ ๋ผ์ด๋ํธ๋ฆฝ ๊ฒ์ฆ |
๋ฌธ์ ์ค๋ช ์ ์งง๋ค.
๋๋ฆผ์ด๋ ๋น๋ฐ์ค๋ฐ ์ด๋ฏธ์ง ํ์ผ์ ์์ ์ด ๊ณต๋ถํ ์๊ณ ๋ฆฌ์ฆ์ ํตํด ์ธ์ฝ๋ฉ ํ์์ด์. ์ธ์ฝ๋ฉ ํ๋ก๊ทธ๋จ์ ๋ถ์ํ์ฌ ์๋ณธ ์ด๋ฏธ์ง๋ฅผ ์์๋ด์ฃผ์ธ์. ์๋ณธ ํ์ผ์ ๊ตฌํ ๊ฒฝ์ฐ imageviewer.py๋ฅผ ํตํด ์ด๋ฏธ์ง๋ฅผ ๋ณผ ์ ์์ต๋๋ค.
์ฆ prob๋ ์๋ณธ ์ด๋ฏธ์ง(secretMessage.raw)๋ฅผ ์ด๋ค ์๊ณ ๋ฆฌ์ฆ์ผ๋ก ์์ถํด secretMessage.enc๋ฅผ ๋ง๋ ์ธ์ฝ๋๋ค. ์๋ณธ ํ์ผ ์์ฒด๋ ์ฃผ์ด์ง์ง ์๊ณ , ์ธ์ฝ๋ ๋ฐ์ด๋๋ฆฌ์ ๊ฒฐ๊ณผ๋ฌผ๋ง ์๋ค. prob๋ฅผ ๋ฆฌ๋ฒ์ฑํด์ ์ธ์ฝ๋ฉ ๊ท์น์ ์์๋ด๊ณ , ๊ทธ๊ฑธ ๊ฑฐ๊พธ๋ก ๋๋ ค ์๋ณธ ๋นํธ๋งต์ ๋ณต์ํด์ผ ํ๋ค.
๐งฉ ๋ฐฐ๊ฒฝ โ imageviewer.py๊ฐ ๊ธฐ๋ํ๋ ํฌ๋งท
imageviewer.py๋ ๋ฑ 3์ค์ด๋ค.
from PIL import Image
with open(sys.argv[1], "rb") as f:
output = f.read()
Image.frombytes("1", (500, 50), output).show()PIL์ frombytes์ ๋ชจ๋ "1"์ ์ฃผ๋ฉด 1๋นํธ ํ๋ฐฑ ์ด๋ฏธ์ง๋ก ํด์ํ๋ค. ํฝ์
ํ๋๊ฐ 1๋นํธ๋ผ 8๊ฐ์ฉ ๋ฌถ์ฌ 1๋ฐ์ดํธ๊ฐ ๋๋๋ฐ, PIL์ raw ๋์ฝ๋๋ ํ๋ง๋ค ๋ฐ์ดํธ ๊ฒฝ๊ณ๋ก ํจ๋ฉํ๋ค. ํญ 500ํฝ์
์ 500๋นํธ = 62.5๋ฐ์ดํธ๋ผ ๊ฐ ํ์ด 63๋ฐ์ดํธ๋ก ์ฌ๋ฆผ๋๊ณ , ๋์ด 50์ ๊ณฑํ๋ฉด ์๋ณธ ํ์ผ์ ์ ํํ 63 ร 50 = 3150๋ฐ์ดํธ์ฌ์ผ ํ๋ค.
๋์ค์ ์ด 3150์ด๋ผ๋ ์ซ์๊ฐ ๋ฐ๋ชฉ์ ์ก๋๋ฐ, ๋ค์ ์ฝ์ง ํ ๊ธ์์ ๊ทธ๋๋ก ๋จ๊ฒจ๋๋ค.
๐ฌ ์ฝ๋ ์ ์ฐฐ
์คํธ๋ฆฝ ์ฌ๋ถ์ ๊ธฐ๋ณธ ์ ๋ณด
file prob secretMessage.enc imageviewer.py && wc -c secretMessage.enc
prob๋ ์คํธ๋ฆฝ๋ PIE ์คํ ํ์ผ์ด๋ค. ์ฌ๋ณผ ํ
์ด๋ธ์ด ์์ผ๋ ํจ์ ์ด๋ฆ์ ์ ๋ถ ์คํ์
์ผ๋ก ๋ด์ผ ํ๋ค. secretMessage.enc๋ 1332๋ฐ์ดํธ โ ๋ฐฐ๊ฒฝ์์ ๊ณ์ฐํ ์๋ณธ 3150๋ฐ์ดํธ๋ณด๋ค ํจ์ฌ ์๋ค. ๋ญ๊ฐ ์์ถ์ด ๋ค์ด๊ฐ๋ค๋ ๋ป์ด๋ค.
.rodata์์ ํ์ผ ์ ์ถ๋ ฅ ํ๋ฆ ์ก๊ธฐ
๋์ ์ฌ๋ณผ(fopen@plt, fgetc@plt, fputc@plt, remove@plt)์ด ๋จ์์์ด์ ์ด ๋ฐ์ด๋๋ฆฌ๊ฐ ํ์ค C ์คํธ๋ฆผ ํจ์๋ก ํ์ผ์ ์ํํ๋ค๋ ๊ฑด ๋ฐ๋ก ๋ณด์ธ๋ค. ์ด๋ค ํ์ผ์ ์ฌ๋์ง๋ .rodata๋ฅผ ๋ณด๋ฉด ๋์จ๋ค.
objdump -s -j .rodata prob
"secretMessage.raw"๋ฅผ "rb"๋ก ์ด๊ณ "secretMessage.enc"๋ฅผ "wb"๋ก ์ฐ๋ค. ์ฆ prob๋ raw๋ฅผ ์ฝ์ด์ enc๋ฅผ ์ฐ๋ ์ธ์ฝ๋๋ค. ๋์ remove()๋ก ์๋ณธ raw๋ฅผ ์ง์ฐ๊ณ "done!"์ ์ถ๋ ฅํ๋ ํ๋ฆ๊น์ง ๋ฌธ์์ด๋ง์ผ๋ก ์ง์์ด ๊ฐ๋ค โ ๋ค์์ main() ๋์ค์ด์
๋ธ๋ฆฌ๋ก ๊ทธ๋๋ก ํ์ธ๋๋ค.
โถ๐ ์ฝ์ง โ 3125๋ฐ์ดํธ๋ผ๊ณ ๋ฏฟ๊ณ ์์ํ๋ค
RLE๋ฅผ ๋ค ์ญ์ฐํ๊ณ ์ฒ์ ๋๋ ธ์ ๋ ์ถ๋ ฅ์ด 3150๋ฐ์ดํธ์๋ค. 500 ร 50 รท 8 = 3125๋ก ๊ณ์ฐํด๋๋ ๋๋ 25๋ฐ์ดํธ๊ฐ ๋จ๋ ๊ฑธ ๋ณด๊ณ ๋์ฝ๋ ๋ก์ง์ด ์ด๋๊ฐ ํ๋ ธ๋ค๊ณ ํ์ ํ๋ค. ์นด์ดํธ ๋ฐ์ดํธ ์ฒ๋ฆฌ, ์ค๋ฒํ๋ก ๋ฆฌ์
์กฐ๊ฑด, ํ์ด ํ์ ์์๊น์ง ํ์ฐธ์ ๋ค์ ๋ค์ก๋ค.
python3 -c "print(500*50/8)" && python3 decode.py extracted/secretMessage.enc secretMessage.raw
์์ธ์ ๋์ฝ๋๊ฐ ์๋๋ผ ๋ด ๊ณ์ฐ์ด์๋ค. PIL์ raw ๋ชจ๋ "1"์ ๋ฐฐ๊ฒฝ ์น์
์์ ์ ์ด๋ ๋๋ก ํ๋ง๋ค ๋ฐ์ดํธ ์ ๋ ฌ ํจ๋ฉ์ ํ๋ค. ํญ 500๋นํธ๋ 62.5๋ฐ์ดํธ๋ผ 63๋ฐ์ดํธ๋ก ์ฌ๋ฆผ๋๊ณ , 63 ร 50 = 3150์ด ๋ง๋ ๊ฐ์ด๋ค. Image.frombytes ๋ฌธ์๋ฅผ ๋ค์ ์ฝ๊ณ ์์ผ ํฝ์
์๋ฅผ 8๋ก ๋๋๊ธฐ๋ง ํ๋ฉด ์ ๋๋ค๋ ๊ฑธ ์์๋ค.
๐ฃ ํต์ฌ โ encode()์ ์ํ๋จธ์
์ ์ ๋ถ์: main()๊ณผ encode() ํธ์ถ ๊ด๊ณ
objdump -d -M intel --start-address=0x911 --stop-address=0x991 prob | sed -rE -f annotate_main.sed
main()์ secretMessage.raw๋ฅผ "rb"๋ก, secretMessage.enc๋ฅผ "wb"๋ก ์ฐ ๋ค์ 0x7fa ์คํ์
์ ํจ์๋ฅผ encode(FILE *in, FILE *out) ํํ๋ก ํธ์ถํ๋ค. ๊ทธ๋ค์ ์๋ณธ raw๋ฅผ ์ง์ฐ๊ณ "done!"์ ์ฐ๋๋ค โ ์ ๋ฌธ์ ์ ์๋ณธ ์ด๋ฏธ์ง๊ฐ ์๋์ง, ์ด ํ ์ค์ด ์ค๋ช
ํด์ค๋ค.
encode()์ ํต์ฌ ๋ถ๊ธฐ
0x7fa์ ํจ์๋ฅผ ์ญ ๋ฐ๋ผ๊ฐ๋ฉด, ๋งค ๋ฐ์ดํธ๋ฅผ ๋ ๊ฐ์ ์ํ(prev, cnt)๋ก ๋ค๋ฃจ๋ ๋ฐ๋ณต๋ฌธ์ด ๋์จ๋ค. ํต์ฌ ๋ถ๊ธฐ๋ง ์๋ผ์ ๋ณด๋ฉด ์ด๋ ๋ค.
objdump -d -M intel --start-address=0x83d --stop-address=0x864 prob | sed -rE -f annotate_core.sed
์๋ก ์ฝ์ ๋ฐ์ดํธ c๋ ์ผ๋จ ๋ฌด์กฐ๊ฑด fputc(c, out)์ผ๋ก ๊ทธ๋๋ก echo๋๋ค. ๊ทธ ์งํ c == prev๋ฅผ ๋น๊ตํ๋๋ฐ, ์ด ๋น๊ต๊ฐ outer ๋ฃจํ(0x851)์ inner ๋ฃจํ(0x85f) ๋ ๊ณณ์์ ๋ฐ๋ณตํด์ ๋ฑ์ฅํ๋ค. ๋๋จธ์ง ๋ก์ง๊น์ง ์ ๋ถ ์ถ์ ํ๋ฉด ๋ค์๊ณผ ๊ฐ์ ๊ท์น์ผ๋ก ์ ๋ฆฌ๋๋ค.
๊ฐ์ ๊ฐ์ด ์ฐ์์ผ๋ก ๋ช ๋ฒ(L) ๋์ค๋๋์ ๋ฐ๋ผ ์ถ๋ ฅ ์ธ๊ทธ๋จผํธ๊ฐ ๊ฐ๋ฆฐ๋ค.

L == 1: ๊ฐ์ ๋ฑ ํ ๋ฒ๋ง echo. ์นด์ดํธ ๋ฐ์ดํธ ์์.L == 2..257: ์ฒ์ ๋ ๊ฐ๋ ๊ทธ๋๋ก echo(v, v)ํ๊ณ , ์ดํ ๋ฐ๋ณต์ ์ธ๊ธฐ๋ง ํ๋ค๊ฐ(echo ์ ํจ) ๊ฐ์ด ๋ฐ๋๋ฉด ๊ทธ ๋ฐ๋ณต ํ์cnt = L - 2๋ฅผ ํ๋ ๋ emit.cnt๋0x00 ~ 0xfe๋ฒ์.cnt๊ฐ0xff(255)์ ๋๋ฌํ๋ฉด ๊ทธ ์์ ์ ๊ฐ์ ๋ก[v, v, 0xff](์ ํํ 257๊ฐ)๋ฅผ emitํ๊ณprev๋ฅผ ๋ฆฌ์ ํ๋ค. ๋ฐ์ด ๊ทธ๋ณด๋ค ๋ ๊ธธ๋ฉด ๋ค์ ์ธ๊ทธ๋จผํธ๋ถํฐ ๋ค์ ์ฒ์ ๊ท์น(์ฒซ 2๊ฐ echo)์ด ์ ์ฉ๋๋ค โ ์นด์ดํธ ๋ฐ์ดํธ ํ๋๊ฐ 8๋นํธ๋ผ 255๊ฐ ํํ ํ๊ณ์ด๊ธฐ ๋๋ฌธ์ ์๊ธฐ๋ ๋ถํ ์ด๋ค.
๋์ฝ๋ฉ์ ์ด ๊ท์น์ ๊ทธ๋๋ก ๋ค์ง์ผ๋ฉด ๋๋ค. v๋ฅผ ํ๋ ์ฝ์ด ์ถ๋ ฅํ๊ณ , ๋ฐ๋ก ๋ค์ ๋ฐ์ดํธ๋ v์ ๊ฐ์ผ๋ฉด ๊ทธ ํ์ด๋ฅผ ์ธ๊ทธ๋จผํธ๋ก ์๋นํด์ cnt๋ฅผ ๋ง์ ์ฝ๊ณ (1+cnt)๊ฐ๋ฅผ ์ถ๊ฐ๋ก ์ถ๋ ฅํ๋ค. ๋ค๋ฅด๋ฉด v๋ ๋จ๋
์ด์์ผ๋ ๊ทธ ๋ฐ์ดํธ๊ฐ ๊ณง ๋ค์ ์ธ๊ทธ๋จผํธ์ ์์์ด๋ค.
๋ฐํ์ ๊ฒ์ฆ โ ์คํ์ ์ด ์ค์ ๋ก ๋ง๋์ง, ๊ทธ๋ฆฌ๊ณ ๋ผ์ด๋ํธ๋ฆฝ
์ ์ ๋ถ์๋ง์ผ๋ก ๋๋ด์ง ์๊ณ 0x7fa๊ฐ ์ค์ ์คํ ์ค์๋ ๋ง๋ ์ฃผ์์ธ์ง, ๊ทธ๋ฆฌ๊ณ ๋ฌด์๋ณด๋ค ์ญ์ฐํ ๋์ฝ๋๊ฐ ์ง์ง๋ก ๋ง๋์ง๋ฅผ ํ์ธํ๊ณ ์ถ์๋ค. ๋ฐฉ๋ฒ์ ๊ฐ๋จํ๋ค โ ๋ณต์ํ raw ํ์ผ์ ์๋ณธ prob ๋ฐ์ด๋๋ฆฌ์ ๋ค์ ๋จน์ฌ์, ์๋ก ๋์จ enc๊ฐ ์ฒ์ ๋ฐ์ secretMessage.enc์ ๋ฐ์ดํธ ๋จ์๋ก ๊ฐ์์ง ๋ณด๋ฉด ๋๋ค.
break *0x7fa
run
info registers rdi rsi
continuePIE๋ผ ๋งํฌ ํ์ ์ฃผ์ 0x7fa์ ๊ทธ๋ฅ ๋ธ๋ ์ดํฌํฌ์ธํธ๋ฅผ ๊ฑธ๋ฉด ์คํจํ๋ค(Cannot access memory). starti๋ก ํ ๋ฒ ๋ฉ์ถฐ info proc mappings๋ก ์ค์ ๋ก๋ ๋ฒ ์ด์ค(0x555555400000)๋ฅผ ๊ตฌํ ๋ค์, base + 0x7fa์ ๋ธ๋ ์ดํฌํฌ์ธํธ๋ฅผ ๊ฑธ์๋ค.
gdb -q -batch -x cmds.gdb --args ./prob && cmp secretMessage.enc ../extracted/secretMessage.enc && echo ROUND-TRIP-OK
๋ธ๋ ์ดํฌํฌ์ธํธ๊ฐ ์ ํํ encode(FILE *in=0x555555602310, FILE *out=0x5555556024f0) ์ง์
์์ ์ ๊ฑธ๋ ธ๊ณ , rdi/rsi๊ฐ main()์์ ๋๊ธด ๋ FILE*๋ผ๋ ๊ฒ๋ ํ์ธ๋๋ค. ๊ทธ๋ฆฌ๊ณ ์ด ํ๋ก์ธ์ค๊ฐ ๋ค ๋๊ณ ๋์ ๋ง๋ secretMessage.enc๊ฐ ๋ฌธ์ ์์ ๋ฐ์ ์๋ณธ๊ณผ cmp๋ก ์์ ํ ๋์ผํ๋ค โ ์ ์ ๋ถ์์ผ๋ก ์ฌ๊ตฌ์ฑํ ์ํ๋จธ์ ์ด ์ธ์ฝ๋์ ๋์๊ณผ ์ ํํ ์ผ์นํ๋ค๋ ๋ป์ด๋ค.
๐ Full Exploit
๋์ฝ๋๋ ์์์ ์ ๋ฆฌํ ๊ท์น์ ๊ทธ๋๋ก ์ฝ๋๋ก ์ฎ๊ธด ๊ฒ๋ฟ์ด๋ค.
def decode(enc: bytes) -> bytes:
out = bytearray()
i, n = 0, len(enc)
while i < n:
v = enc[i]
i += 1
out.append(v)
if i < n and enc[i] == v:
i += 1 # ํ์ด์ ๋๋ฒ์งธ v ์๋น
cnt = enc[i]
i += 1
out.extend([v] * (1 + cnt))
return bytes(out)$ python3 decode.py extracted/secretMessage.enc secretMessage.raw
enc=1332B -> raw=3150B (expect 500*50/8=3125B for 1bpp 500x50)secretMessage.raw๊ฐ ๋์ค๋ฉด imageviewer.py๊ฐ ๊ธฐ๋ํ๋ ๊ทธ๋๋ก Image.frombytes("1", (500, 50), data)์ ๋ฃ์ด PNG๋ก ์ ์ฅํ๋ค.
from PIL import Image
with open("secretMessage.raw", "rb") as f:
data = f.read()
Image.frombytes("1", (500, 50), data).save("secretMessage.png")
DH{93589e6c1db065fa95075ab5e3790bc1}. ๋๋ฆผํต์ ์ ์ถํด ์ ๋ต ์ฒ๋ฆฌ๋๋ค.
๐ ๊ฒฐ๋ก
์คํธ๋ฆฝ๋ผ๋ ํ์ค ๋ผ์ด๋ธ๋ฌ๋ฆฌ ํธ์ถ์ ๋จ๋๋ค.
fopen/fgetc/fputc/remove PLT ์ฌ๋ณผ๋ง์ผ๋ก๋ ์ด ๋ฐ์ด๋๋ฆฌ๊ฐ ํ์ผ์ ์ด์ด ๋ฐ์ดํธ ๋จ์๋ก ์ํํ๋ฉฐ ๋ค๋ฅธ ํ์ผ์ ์ด๋ค๋ ํฐ ๊ทธ๋ฆผ์ ์ฌ๋ณผ ์ด๋ฆ ์์ด๋ ๊ทธ๋ฆด ์ ์์๋ค. ์ปค์คํ
์๊ณ ๋ฆฌ์ฆ์ด๋ผ๋ ๊ฒฐ๊ตญ ํ์ค I/O ์์ ์นํ ์์ผ๋ฉด ๊ทธ ํธ์ถ ์ง์ ์ด ์ข์ ์ด์ ํ๊ฐ ๋๋ค.
์์ถ ์๊ณ ๋ฆฌ์ฆ ์ญ์ฐ์ ์ํ(๋ ์ง์คํฐยท์คํ ๋ณ์) ๋ ๊ฐ๋ง ์ถ๋ ค๋ ์ถฉ๋ถํ ๋๊ฐ ๋ง๋ค.
์ด ์ธ์ฝ๋๋ prev์ cnt ๋ฑ ๋ ๊ฐ์ ๋ก์ปฌ ๋ณ์๋ก ์ ์ฒด RLE๋ฅผ ๊ตด๋ ธ๋ค. ๋์ค์ด์
๋ธ๋ฆฌ๊ฐ ๊ธธ์ด ๋ณด์ฌ๋ ์ด๋ค ์คํ ์ฌ๋กฏ์ด ๋ฐ๋ณตํด์ ๋น๊ตยท๊ฐฑ์ ๋๋์ง๋ง ์ถ๋ฆฌ๋ฉด ์ํ๋จธ์ ์ ์๊ฐ๋ณด๋ค ๋นจ๋ฆฌ ๋๋ฌ๋๋ค.
์ญ์ฐ ๊ฒฐ๊ณผ๋ ์๋ณธ ๋๊ตฌ๋ก ๋ค์ ๊ฒ์ฆํ ์ ์์ผ๋ฉด ์ ์ผ ํ์คํ๋ค.
๋์ฝ๋๋ฅผ ์์ผ๋ก ์ง๊ณ "์ด๊ฒ ๋ง๋ค"๊ณ ๋ฏฟ๋ ๊ฒ๊ณผ, ๊ทธ ์ถ๋ ฅ์ ์๋ ์ธ์ฝ๋์ ๋ค์ ๋ฃ์ด ๋ฐ์ดํธ ๋จ์๋ก ์๋ณธ๊ณผ ์ผ์น์ํค๋ ๊ฒ์ ์ ๋ขฐ๋๊ฐ ๋ค๋ฅด๋ค. ์ด๋ฒ์ฒ๋ผ ์ธ์ฝ๋ ๋ฐ์ด๋๋ฆฌ๊ฐ ์ฃผ์ด์ง๋ ๋ฌธ์ ๋ผ๋ฉด ๋ผ์ด๋ํธ๋ฆฝ ๊ฒ์ฆ์ ๊ผญ ๋ถ์ด๋ ํธ์ด ์์ ํ๋ค.
Comments
๋๊ธ
๋๊ธ์ ๋จ๊ธฐ๋ ค๋ฉด ๋ก๊ทธ์ธ์ด ํ์ํด์. (๋ค์ด๋ฒ ยท ๊ตฌ๊ธ ๊ณ์ )
๋๊ธ ๋ถ๋ฌ์ค๋ ์คโฆ