[๐Ÿฅ‰ Bronze 1] ์ŠคํŠธ๋ฆฝ๋œ PIE ๋ฐ”์ด๋„ˆ๋ฆฌ์˜ ์ปค์Šคํ…€ RLE ์—ญ์‚ฐ โ€” DreamHack secret message ํ’€์ด

2026-07-19ยท1๋ถ„ ์ฝ๊ธฐยท

[๐Ÿฅ‰ Bronze 1] ์ŠคํŠธ๋ฆฝ๋œ PIE ๋ฐ”์ด๋„ˆ๋ฆฌ์˜ ์ปค์Šคํ…€ RLE ์—ญ์‚ฐ โ€” DreamHack secret message ํ’€์ด

๋“œ๋ฆผ์ด๊ฐ€ ์ด๋ฏธ์ง€๋ฅผ ์ž๊ธฐ๊ฐ€ ๋งŒ๋“  ์ธ์ฝ”๋”ฉ์œผ๋กœ ์••์ถ•ํ•ด๋’€๋‹ค. ์ŠคํŠธ๋ฆฝ๋œ PIE ELF๋ฅผ objdump๋กœ ๋œฏ์–ด fopen/fgetc/fputc ํ˜ธ์ถœ๋งŒ์œผ๋กœ ์ปค์Šคํ…€ RLE ์ƒํƒœ๋จธ์‹ ์„ ๋ณต์›ํ•˜๊ณ , gdb ๋Ÿฐํƒ€์ž„ ๊ฒ€์ฆ๊นŒ์ง€ ๊ฑฐ์ณ ์›๋ณธ ๋น„ํŠธ๋งต์„ ๋˜์‚ด๋ฆฐ ํ’€์ด.

๋ฌธ์ œ: 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

file/wc๋กœ ํ™•์ธํ•œ ๋ฐ”์ด๋„ˆ๋ฆฌ ๊ธฐ๋ณธ ์ •๋ณด โ€” stripped PIE ELF, enc ํŒŒ์ผ 1332๋ฐ”์ดํŠธ
file/wc๋กœ ํ™•์ธํ•œ ๋ฐ”์ด๋„ˆ๋ฆฌ ๊ธฐ๋ณธ ์ •๋ณด โ€” stripped PIE ELF, enc ํŒŒ์ผ 1332๋ฐ”์ดํŠธ

prob๋Š” ์ŠคํŠธ๋ฆฝ๋œ PIE ์‹คํ–‰ ํŒŒ์ผ์ด๋‹ค. ์‹ฌ๋ณผ ํ…Œ์ด๋ธ”์ด ์—†์œผ๋‹ˆ ํ•จ์ˆ˜ ์ด๋ฆ„์€ ์ „๋ถ€ ์˜คํ”„์…‹์œผ๋กœ ๋ด์•ผ ํ•œ๋‹ค. secretMessage.enc๋Š” 1332๋ฐ”์ดํŠธ โ€” ๋ฐฐ๊ฒฝ์—์„œ ๊ณ„์‚ฐํ•œ ์›๋ณธ 3150๋ฐ”์ดํŠธ๋ณด๋‹ค ํ›จ์”ฌ ์ž‘๋‹ค. ๋ญ”๊ฐ€ ์••์ถ•์ด ๋“ค์–ด๊ฐ”๋‹ค๋Š” ๋œป์ด๋‹ค.

.rodata์—์„œ ํŒŒ์ผ ์ž…์ถœ๋ ฅ ํ๋ฆ„ ์žก๊ธฐ

๋™์  ์‹ฌ๋ณผ(fopen@plt, fgetc@plt, fputc@plt, remove@plt)์ด ๋‚จ์•„์žˆ์–ด์„œ ์ด ๋ฐ”์ด๋„ˆ๋ฆฌ๊ฐ€ ํ‘œ์ค€ C ์ŠคํŠธ๋ฆผ ํ•จ์ˆ˜๋กœ ํŒŒ์ผ์„ ์ˆœํšŒํ•œ๋‹ค๋Š” ๊ฑด ๋ฐ”๋กœ ๋ณด์ธ๋‹ค. ์–ด๋–ค ํŒŒ์ผ์„ ์—ฌ๋Š”์ง€๋Š” .rodata๋ฅผ ๋ณด๋ฉด ๋‚˜์˜จ๋‹ค.

objdump -s -j .rodata prob

objdump๋กœ .rodata ์„น์…˜์„ ๋คํ”„ํ•ด ํ™•์ธํ•œ ํŒŒ์ผ๋ช…ยท๋ชจ๋“œ ๋ฌธ์ž์—ด
objdump๋กœ .rodata ์„น์…˜์„ ๋คํ”„ํ•ด ํ™•์ธํ•œ ํŒŒ์ผ๋ช…ยท๋ชจ๋“œ ๋ฌธ์ž์—ด

"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

decode.py ์‹คํ–‰ โ€” 3125๊ฐ€ ์•„๋‹ˆ๋ผ 3150๋ฐ”์ดํŠธ๊ฐ€ ๋‚˜์˜จ ์ˆœ๊ฐ„
decode.py ์‹คํ–‰ โ€” 3125๊ฐ€ ์•„๋‹ˆ๋ผ 3150๋ฐ”์ดํŠธ๊ฐ€ ๋‚˜์˜จ ์ˆœ๊ฐ„

์›์ธ์€ ๋””์ฝ”๋”๊ฐ€ ์•„๋‹ˆ๋ผ ๋‚ด ๊ณ„์‚ฐ์ด์—ˆ๋‹ค. 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

objdump๋กœ ํ™•์ธํ•œ main() โ€” fopen ๋‘ ๋ฒˆ, encode(in,out) ํ˜ธ์ถœ, remove๋กœ ์›๋ณธ ์‚ญ์ œ
objdump๋กœ ํ™•์ธํ•œ main() โ€” fopen ๋‘ ๋ฒˆ, encode(in,out) ํ˜ธ์ถœ, remove๋กœ ์›๋ณธ ์‚ญ์ œ

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

objdump๋กœ ํ™•์ธํ•œ encode() ํ•ต์‹ฌ ๋ฃจํ”„ โ€” fputc๋กœ ์ฆ‰์‹œ echo, c์™€ prev ๋น„๊ต๊ฐ€ ๋‘ ๋ฒˆ ๋“ฑ์žฅ
objdump๋กœ ํ™•์ธํ•œ encode() ํ•ต์‹ฌ ๋ฃจํ”„ โ€” fputc๋กœ ์ฆ‰์‹œ echo, c์™€ prev ๋น„๊ต๊ฐ€ ๋‘ ๋ฒˆ ๋“ฑ์žฅ

์ƒˆ๋กœ ์ฝ์€ ๋ฐ”์ดํŠธ c๋Š” ์ผ๋‹จ ๋ฌด์กฐ๊ฑด fputc(c, out)์œผ๋กœ ๊ทธ๋Œ€๋กœ echo๋œ๋‹ค. ๊ทธ ์งํ›„ c == prev๋ฅผ ๋น„๊ตํ•˜๋Š”๋ฐ, ์ด ๋น„๊ต๊ฐ€ outer ๋ฃจํ”„(0x851)์™€ inner ๋ฃจํ”„(0x85f) ๋‘ ๊ณณ์—์„œ ๋ฐ˜๋ณตํ•ด์„œ ๋“ฑ์žฅํ•œ๋‹ค. ๋‚˜๋จธ์ง€ ๋กœ์ง๊นŒ์ง€ ์ „๋ถ€ ์ถ”์ ํ•˜๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ทœ์น™์œผ๋กœ ์ •๋ฆฌ๋œ๋‹ค.

๊ฐ™์€ ๊ฐ’์ด ์—ฐ์†์œผ๋กœ ๋ช‡ ๋ฒˆ(L) ๋‚˜์˜ค๋А๋ƒ์— ๋”ฐ๋ผ ์ถœ๋ ฅ ์„ธ๊ทธ๋จผํŠธ๊ฐ€ ๊ฐˆ๋ฆฐ๋‹ค.

RLE ์„ธ๊ทธ๋จผํŠธ ํฌ๋งท ๋‹ค์ด์–ด๊ทธ๋žจ โ€” L=1 ๋‹จ๋…, L=2..257 ๋Ÿฐ, L=257 ์˜ค๋ฒ„ํ”Œ๋กœ
RLE ์„ธ๊ทธ๋จผํŠธ ํฌ๋งท ๋‹ค์ด์–ด๊ทธ๋žจ โ€” L=1 ๋‹จ๋…, L=2..257 ๋Ÿฐ, L=257 ์˜ค๋ฒ„ํ”Œ๋กœ

  • 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
continue

PIE๋ผ ๋งํฌ ํƒ€์ž„ ์ฃผ์†Œ 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

gdb ๋Ÿฐํƒ€์ž„ ํ™•์ธ โ€” 0x7fa์—์„œ ๋ธŒ๋ ˆ์ดํฌ, encode(FILEin, FILEout) ์ธ์ž ํ™•์ธ, ์žฌ์ธ์ฝ”๋”ฉ ๊ฒฐ๊ณผ๊ฐ€ ์›๋ณธ๊ณผ ๋ฐ”์ดํŠธ ๋‹จ์œ„๋กœ ์ผ์น˜
gdb ๋Ÿฐํƒ€์ž„ ํ™•์ธ โ€” 0x7fa์—์„œ ๋ธŒ๋ ˆ์ดํฌ, encode(FILEin, FILEout) ์ธ์ž ํ™•์ธ, ์žฌ์ธ์ฝ”๋”ฉ ๊ฒฐ๊ณผ๊ฐ€ ์›๋ณธ๊ณผ ๋ฐ”์ดํŠธ ๋‹จ์œ„๋กœ ์ผ์น˜

๋ธŒ๋ ˆ์ดํฌํฌ์ธํŠธ๊ฐ€ ์ •ํ™•ํžˆ 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

๋Œ“๊ธ€

0๊ฐœ

๋Œ“๊ธ€์„ ๋‚จ๊ธฐ๋ ค๋ฉด ๋กœ๊ทธ์ธ์ด ํ•„์š”ํ•ด์š”. (๋„ค์ด๋ฒ„ ยท ๊ตฌ๊ธ€ ๊ณ„์ •)

๋Œ“๊ธ€ ๋ถˆ๋Ÿฌ์˜ค๋Š” ์ค‘โ€ฆ

Related

๊ด€๋ จ ๊ธ€

3๊ฐœ
[๐Ÿฅˆ Bronze 2] ๋ฏธ๋ผ์ธ ์ค„ ์•Œ์•˜๋˜ ๋””์ฝ”๋“œ๊ฐ€ ์‚ฌ์‹ค ์ •๋‹ต์ด์—ˆ๋‹ค โ€” DreamHack ์•„ ๋ฌธ์ œ ์ด๋ฆ„ ๋ญ˜๋กœํ•˜์ง€ ํ’€์ด
blog

[๐Ÿฅˆ Bronze 2] ๋ฏธ๋ผ์ธ ์ค„ ์•Œ์•˜๋˜ ๋””์ฝ”๋“œ๊ฐ€ ์‚ฌ์‹ค ์ •๋‹ต์ด์—ˆ๋‹ค โ€” DreamHack ์•„ ๋ฌธ์ œ ์ด๋ฆ„ ๋ญ˜๋กœํ•˜์ง€ ํ’€์ด

39๋ฐ”์ดํŠธ ์•”ํ˜ธ๋ฌธ์„ XOR 0xAA๋กœ ํ’€๋ฉด ๊ทธ๋Ÿด๋“ฏํ•œ DH{} ๋ฌธ์ž์—ด์ด ๋ฐ”๋กœ ๋‚˜์˜จ๋‹ค. ๋„ˆ๋ฌด ์‰ฌ์›Œ์„œ ๋ฏธ๋ผ๋ผ๊ณ  ํŒ๋‹จํ•˜๊ณ , ์‚ฌ์šฉ์ž ์ž…๋ ฅ์„ ๋ณ€ํ˜•ํ•˜๋Š” ๋ณต์žกํ•œ ์ปค์Šคํ…€ ์ธ์ฝ”๋”ฉ ํ•จ์ˆ˜๋ฅผ ํ†ต์งธ๋กœ ์—ญ์‚ฐํ–ˆ๋‹ค. GDB๋กœ ๋Œ€์กฐํ•˜๋‹ค 32๋น„ํŠธ ์‹œํ”„ํŠธ ์นด์šดํŠธ ๋งˆ์Šคํ‚น ๋•Œ๋ฌธ์— ํŠน์ • ์ž๋ฆฌ๊ฐ€ ํ•ญ์ƒ 0์ด ๋˜๋Š” ๋ฒ„๊ทธ๋ฅผ ๋ฐœ๊ฒฌํ–ˆ๊ณ , ๊ทธ ๋ฒ„๊ทธ๋ฅผ ์ซ“์•„๊ฐ€๋‹ค ๊ฒฐ๊ตญ ์ฒ˜์Œ ๋ดค๋˜ ๊ทธ ๋””์ฝ”๋“œ ๋ฌธ์ž์—ด์ด ์ง„์งœ ์ •๋‹ต์ด์—ˆ๋‹ค๋Š” ๊ฑธ ์•Œ๊ฒŒ ๋๋‹ค.
#dreamhack#ctf#reversing+4
2026-07-19#dreamhack +4
[๐Ÿฅ‰ Bronze 3] stripped Rust ๋ฐ”์ด๋„ˆ๋ฆฌ์—์„œ ์Šคํƒ key ๋ฅผ ๋ฝ‘์•„ XOR ์—ญ์‚ฐ โ€” DreamHack Rusty Gyul ํ’€์ด
blog

[๐Ÿฅ‰ Bronze 3] stripped Rust ๋ฐ”์ด๋„ˆ๋ฆฌ์—์„œ ์Šคํƒ key ๋ฅผ ๋ฝ‘์•„ XOR ์—ญ์‚ฐ โ€” DreamHack Rusty Gyul ํ’€์ด

์‹ฌ๋ณผ์„ ๋ชจ๋‘ ๊ฑท์–ด๋‚ธ Rust ELF ํ•˜๋‚˜๊ฐ€ "ํ”Œ๋ž˜๊ทธ๋ฅผ ๋งž์ถฐ๋ด"๋ผ๊ณ  ํ•œ๋‹ค. ltrace ์—๋Š” strcmp ํ•˜๋‚˜ ์•ˆ ์žกํžˆ๊ณ  main ์€ ๊ป๋ฐ๊ธฐ๋ฟ์ด๋‹ค. ์ง„์งœ ๊ฒ€์‚ฌ ๋ฃจํ‹ด์„ ์–ด์…ˆ๋ธ”๋ฆฌ์—์„œ ์ฐพ์•„ ๋“ค์–ด๊ฐ€ ๋ณด๋ฉด, ์ž…๋ ฅ์„ trim ํ•œ ๋’ค ์Šคํƒ์— ์‹ค์–ด๋‘” 32๋ฐ”์ดํŠธ key ์™€ ํ•œ ๋ฐ”์ดํŠธ์”ฉ XOR ํ•ด์„œ ์ „๋ถ€ 0x55 ์ธ์ง€๋งŒ ๋ณธ๋‹ค. key ๋ฅผ ๊ทธ๋Œ€๋กœ ๋ฝ‘์•„ 0x55 ๋กœ ๋˜XOR ํ•˜๋ฉด ํ”Œ๋ž˜๊ทธ๊ฐ€ ๋‚˜์˜จ๋‹ค.
#dreamhack#ctf#reversing+5
2026-07-16#dreamhack +3
[๐Ÿฅ‰ Bronze 2] dreamhack.exe์— ์‹ฌ๊ฒจ์•ผ ์—ด๋ฆฌ๋Š” DLL โ€” DreamHack Inject ME!!! ํ’€์ด
blog

[๐Ÿฅ‰ Bronze 2] dreamhack.exe์— ์‹ฌ๊ฒจ์•ผ ์—ด๋ฆฌ๋Š” DLL โ€” DreamHack Inject ME!!! ํ’€์ด

์ต์ŠคํฌํŠธ๋„ ์—†๋Š” DLL์ด DllMain์—์„œ ํ˜ธ์ŠคํŠธ ํ”„๋กœ์„ธ์Šค๋ช…์„ ๊ฒ€์‚ฌํ•œ๋‹ค. ์ด๋ฆ„์ด dreamhack.exe์—ฌ์•ผ flag๋ฅผ ๊ณ„์‚ฐํ•˜๋Š”๋ฐ, ๊ทธ ๊ฐ’์€ ํ”„๋กœ์„ธ์Šค๋ช… ์ฒซ 4๋ฐ”์ดํŠธ๋ฅผ WELL512 PRNG ์‹œ๋“œ๋กœ ์‚ผ์•„ ๋งŒ๋“ ๋‹ค. ํ”„๋กœ์„ธ์Šค๋ช…์ด ๊ณ ์ •์ด๋ผ flag๋Š” ์‹คํ–‰ ์—†์ด ์ •์ ์œผ๋กœ ๋ณต์›๋œ๋‹ค.
#dreamhack#ctf#reversing+5
2026-07-13#dreamhack +3