[๐Ÿฅ‡ Gold 4] ์ฝ”๋“œ๋ณด๋‹ค ๋ฐ์ดํ„ฐ๊ฐ€ ์—ด ๋ฐฐ ํฐ ์ด์œ  โ€” DreamHack Snaky ํ’€์ด

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

[๐Ÿฅ‡ Gold 4] ์ฝ”๋“œ๋ณด๋‹ค ๋ฐ์ดํ„ฐ๊ฐ€ ์—ด ๋ฐฐ ํฐ ์ด์œ  โ€” DreamHack Snaky ํ’€์ด

.text ๋Š” 1.5KB ์ธ๋ฐ .data ๊ฐ€ 15KB ๋‹ค. ๊ทธ ๋ฐ์ดํ„ฐ๊ฐ€ 25ร—25ร—25 ๊ฒฉ์ž์˜€๊ณ , ์ž…๋ ฅ ๋ฌธ์ž ์—ฌ์„ฏ ๊ฐœ๋Š” ยฑx ยฑy ยฑz ์—ฌ์„ฏ ๋ฐฉํ–ฅ์ด์—ˆ๋‹ค. ์ง€๋‚˜์˜จ ์นธ์ด ๋ฒฝ์œผ๋กœ ๋ฐ”๋€Œ์–ด ์ž๊ธฐ ๋ชธ์„ ๋ฐŸ์„ ์ˆ˜ ์—†๋Š” 3D ๋ฑ€ ๋ฏธ๋กœ โ€” ํ†ต๋กœ 107์นธ์ด ํ†ต์งธ๋กœ ์™ธ๊ธธ์ด๋ผ ๋‹ต์€ ํ•˜๋‚˜๋ฟ์ด๋‹ค.

๋ฌธ์ œ: DreamHack โ€” Snaky ๋ถ„๋ฅ˜: reversing ๋‚œ์ด๋„: ๐Ÿฅ‡ Gold 4 FLAG: DH{zzzzzz222222277779999zzzzzzzssssssss999777777777222222222222zzzzz999zzz999777ssss99999999999777777sssssssz}

๋ฌธ์ œ ์„ค๋ช…์€ ํ”ํ•œ ํ˜•ํƒœ๋‹ค.

x64 ๋ฆฌ๋ˆ…์Šค ํ™˜๊ฒฝ์—์„œ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๋Š” ELF ํŒŒ์ผ์ด ์ฒจ๋ถ€ํŒŒ์ผ๋กœ ์ฃผ์–ด์ง‘๋‹ˆ๋‹ค. ํ•ด๋‹น ELF ํŒŒ์ผ์€ ์ด์šฉ์ž๋กœ๋ถ€ํ„ฐ ๋ฌธ์ž์—ด์„ ์ž…๋ ฅ๋ฐ›์•„ ๊ฒ€์ฆ์„ ์ˆ˜ํ–‰ํ•œ ํ›„ ์ •๋‹ต์ด๋ฉด good :)์„, ํ‹€๋ฆฌ๋ฉด wrong :(์„ ์ถœ๋ ฅํ•˜๋Š” ํ”„๋กœ๊ทธ๋žจ์ž…๋‹ˆ๋‹ค. ์ •๋‹ต์ด ๋˜๋Š” ๋ฌธ์ž์—ด์ด ํ”Œ๋ž˜๊ทธ์ด๋ฉฐ, ํ”Œ๋ž˜๊ทธ ํ˜•์‹์€ DH{...} ์ž…๋‹ˆ๋‹ค.

๋ฌธ์ œ ํŽ˜์ด์ง€์— ์—…๋ฐ์ดํŠธ ๊ธฐ๋ก์ด ํ•˜๋‚˜ ๋ถ™์–ด ์žˆ๋‹ค.

2025.03.05: good :)์„ ์ถœ๋ ฅํ•˜๋Š” ์ž…๋ ฅ ๊ฐ’์ด ์—ฌ๋Ÿฌ ๊ฐœ์˜€๋˜ ๋ฌธ์ œ๋ฅผ ์ˆ˜์ •ํ•˜์˜€์Šต๋‹ˆ๋‹ค.

์ด ํ•œ ์ค„์ด ๋‚˜์ค‘์— ํ’€์ด๊ฐ€ ๋งž์•˜๋‹ค๋Š” ํ™•์ธ์ด ๋œ๋‹ค. ๋‹ต์ด ์ •ํ™•ํžˆ ํ•˜๋‚˜์—ฌ์•ผ ํ•œ๋‹ค๋Š” ๋œป์ด๋‹ˆ๊นŒ.


๋ฌธ์ œ ๊ฐœ์š”

ํ•ญ๋ชฉ๋‚ด์šฉ
๋ฌธ์ œ๋ช…Snaky (id 1774)
๋‚œ์ด๋„๐Ÿฅ‡ Gold 4
๋ถ„๋ฅ˜reversing
์ œ๊ณต ํŒŒ์ผchall (ELF 64-bit, non-PIE, stripped, 30,184๋ฐ”์ดํŠธ)
์ž„ํฌํŠธ__isoc99_scanf ยท puts ยท setvbuf โ€” ๊ทธ๊ฒŒ ์ „๋ถ€๋‹ค
ํ•ต์‹ฌ.data ์— ์ˆจ์€ 25ร—25ร—25 3D ๋ฏธ๋กœ + ์ž๊ธฐ ๋ชธ์„ ๋ฐŸ์„ ์ˆ˜ ์—†๋Š” ์ œ์•ฝ
๋‹ต106๊ฑธ์Œ, ๋‹จ์ˆœ๊ฒฝ๋กœ ์ •ํ™•ํžˆ 1๊ฐœ

ํ’€์ด๋Š” ์„น์…˜ ํฌ๊ธฐ๋ฅผ ๋ณธ ์ˆœ๊ฐ„ ๋ฐฉํ–ฅ์ด ์žกํ˜”๋‹ค. ๋กœ์ง์€ 1.5KB ์ธ๋ฐ ๋ฐ์ดํ„ฐ๊ฐ€ 15KB ๋‹ค. ๋‹ต์ด ์ฝ”๋“œ๊ฐ€ ์•„๋‹ˆ๋ผ ๋ฐ์ดํ„ฐ์— ์žˆ๋‹ค๋Š” ๋œป์ด๋‹ค.

๊ทธ๋‹ค์Œ์€ ๊ทธ ๋ฐ์ดํ„ฐ๊ฐ€ ์–ด๋–ค ๋ชจ์–‘์ธ์ง€ ์•Œ์•„๋‚ด๋Š” ์ผ์ด์—ˆ๊ณ , ์ธ๋ฑ์Šค ๊ณ„์‚ฐ์‹ ํ•˜๋‚˜๊ฐ€ ๊ทธ๊ฑธ ๋‹ค ๋งํ•ด ์คฌ๋‹ค.



๐Ÿ”ฌ ์ •์ฐฐ โ€” ์„น์…˜ ํฌ๊ธฐ๊ฐ€ ๋จผ์ € ๋งํ•œ๋‹ค

file extracted/chall; readelf -SW extracted/chall | grep -E "\.text|\.rodata|\.data|\.bss"
file ๊ณผ readelf ๋กœ ๋ณธ chall โ€” non-PIE stripped x86-64 ์ด๊ณ  text ๋Š” 0x60c ๋ฐ”์ดํŠธ์ธ๋ฐ data ๊ฐ€ 0x3d29 ๋ฐ”์ดํŠธ๋ผ ์ฝ”๋“œ๋ณด๋‹ค ๋ฐ์ดํ„ฐ๊ฐ€ ์—ด ๋ฐฐ ํฌ๋‹ค
file ๊ณผ readelf ๋กœ ๋ณธ chall โ€” non-PIE stripped x86-64 ์ด๊ณ  text ๋Š” 0x60c ๋ฐ”์ดํŠธ์ธ๋ฐ data ๊ฐ€ 0x3d29 ๋ฐ”์ดํŠธ๋ผ ์ฝ”๋“œ๋ณด๋‹ค ๋ฐ์ดํ„ฐ๊ฐ€ ์—ด ๋ฐฐ ํฌ๋‹ค

.text ๊ฐ€ 0x60c = 1,548๋ฐ”์ดํŠธ. .data ๊ฐ€ 0x3d29 = 15,657๋ฐ”์ดํŠธ.

๋ฆฌ๋ฒ„์‹ฑ ๋ฌธ์ œ์—์„œ ์ด ๋น„์œจ์€ ๊ฐ•ํ•œ ์‹ ํ˜ธ๋‹ค. ๊ฒ€์ฆ ๋กœ์ง์ด 1.5KB ์•ˆ์— ๋“ค์–ด๊ฐ„๋‹ค๋ฉด ๋ณต์žกํ•œ ์•”ํ˜ธ ๋ฃจํ‹ด์€ ์•„๋‹ˆ๊ณ , ๋Œ€์‹  15KB์งœ๋ฆฌ ํ‘œ๋ฅผ ์ฐธ์กฐํ•œ๋‹ค๋Š” ๋œป์ด๋‹ค.

non-PIE ๋ผ๋Š” ๊ฒƒ๋„ ๋ฐ˜๊ฐ‘๋‹ค. ์ฃผ์†Œ๊ฐ€ ์‹คํ–‰๋งˆ๋‹ค ๊ณ ์ •์ด๋ผ ๋‚˜์ค‘์— gdb ๋กœ ํ™•์ธํ•  ๋•Œ 0x404060 ๊ฐ™์€ ๊ฐ’์„ ๊ทธ๋Œ€๋กœ ์“ธ ์ˆ˜ ์žˆ๋‹ค.

์ž„ํฌํŠธ๊ฐ€ ์„ธ ๊ฐœ๋ฟ์ด๋‹ค

nm -D extracted/chall; strings -a extracted/chall | grep -E "%255s|good|wrong"
nm ์œผ๋กœ ๋ณธ ์ž„ํฌํŠธ์™€ ์ฃผ์š” ๋ฌธ์ž์—ด โ€” scanf puts setvbuf ์„ธ ๊ฐœ๋ฟ์ด๊ณ  ํฌ๋งท ๋ฌธ์ž์—ด์€ %255s ์ด๋ฉฐ ์ถœ๋ ฅ์€ good ๊ณผ wrong ๋‘ ๊ฐ€์ง€๋‹ค
nm ์œผ๋กœ ๋ณธ ์ž„ํฌํŠธ์™€ ์ฃผ์š” ๋ฌธ์ž์—ด โ€” scanf puts setvbuf ์„ธ ๊ฐœ๋ฟ์ด๊ณ  ํฌ๋งท ๋ฌธ์ž์—ด์€ %255s ์ด๋ฉฐ ์ถœ๋ ฅ์€ good ๊ณผ wrong ๋‘ ๊ฐ€์ง€๋‹ค

scanf("%255s", buf) ๋กœ ํ•œ ์ค„ ๋ฐ›๊ณ , puts ๋กœ ๋‘˜ ์ค‘ ํ•˜๋‚˜๋ฅผ ์ฐ๋Š”๋‹ค. ์•”ํ˜ธ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋„ ํŒŒ์ผ ์ž…์ถœ๋ ฅ๋„ ์—†๋‹ค.

๊ทธ๋Ÿฌ๋‹ˆ๊นŒ ์ด ํ”„๋กœ๊ทธ๋žจ์€ ์ž…๋ ฅ ๋ฌธ์ž์—ด ํ•˜๋‚˜๋ฅผ ํ‘œ์™€ ๋Œ€์กฐํ•˜๋Š” ๊ฒƒ์ด ์ „๋ถ€๋‹ค.


๐Ÿงฉ ๋ฐฐ๊ฒฝ โ€” stripped ๋ฐ”์ด๋„ˆ๋ฆฌ๋ฅผ ์ฝ๋Š” ์ˆœ์„œ

์‹ฌ๋ณผ์ด ์—†์œผ๋‹ˆ ํ•จ์ˆ˜ ์ด๋ฆ„์ด ํ•˜๋‚˜๋„ ์—†๋‹ค. ๊ทธ๋ž˜๋„ ์ˆœ์„œ๋ฅผ ์ •ํ•ด ๋‘๋ฉด ํ—ค๋งฌ ์ผ์ด ์ ๋‹ค.

์—”ํŠธ๋ฆฌ์—์„œ main ์„ ์ฐพ๋Š”๋‹ค. _start ๊ฐ€ __libc_start_main ์— ๋„˜๊ธฐ๋Š” ์ฒซ ์ธ์ž๊ฐ€ main ์ด๋‹ค. ์—ฌ๊ธฐ์„œ๋Š” mov rdi,0x4016a3 ์ด๋ผ main ์€ 0x4016a3.

ํ˜ธ์ถœ ๊ทธ๋ž˜ํ”„๋ฅผ ์œ„์—์„œ ์•„๋ž˜๋กœ ํ›‘๋Š”๋‹ค. main โ†’ 0x401482(์ง„์งœ ๋กœ์ง) โ†’ 0x401348(๊ฒ€์ฆ) โ†’ ๊ทธ ์•„๋ž˜๋กœ 0x40127a, 0x4011eb, 0x401196.

๋ฆฌํ”„ ํ•จ์ˆ˜๋ถ€ํ„ฐ ์ด๋ฆ„์„ ๋ถ™์ธ๋‹ค. ๊ฐ€์žฅ ์ž‘์€ ํ•จ์ˆ˜๊ฐ€ ๋Œ€๊ฐœ ๊ฐ€์žฅ ๋‹จ์ˆœํ•˜๊ณ , ๊ฑฐ๊ธฐ์„œ ์ž๋ฃŒ๊ตฌ์กฐ๊ฐ€ ๋“œ๋Ÿฌ๋‚œ๋‹ค. ์ด ๋ฌธ์ œ์—์„œ๋Š” 0x401196 ๊ณผ 0x4011eb ์ด ๊ทธ ์ž๋ฆฌ์˜€๋‹ค.

์•„๋ž˜์—์„œ๋Š” ์ฝ์–ด๋‚ธ ์ด๋ฆ„์œผ๋กœ ๋ถ€๋ฅด๊ฒ ๋‹ค. ์‹ค์ œ ๋ฐ”์ด๋„ˆ๋ฆฌ์—๋Š” ์ฃผ์†Œ๋ฐ–์— ์—†๋‹ค.

์ฃผ์†Œ๋ถ™์ธ ์ด๋ฆ„ํ•˜๋Š” ์ผ
0x401196mark(x,y,z)๊ฒฉ์ž์˜ ๊ทธ ์นธ์„ 1 ๋กœ ๋งŒ๋“ ๋‹ค
0x4011ebcan_move(x,y,z)๋ฒ”์œ„ ์•ˆ์ด๊ณ  ๊ฐ’์ด 1 ์ด ์•„๋‹ˆ๋ฉด 1 ์„ ๋Œ๋ ค์ค€๋‹ค
0x40127acheck_chars(s)์ž…๋ ฅ์ด ํ—ˆ์šฉ๋œ ๊ธ€์ž๋กœ๋งŒ ๋˜์–ด ์žˆ๋Š”์ง€ ๋ณธ๋‹ค
0x401348check(s)์‹ค์ œ ๊ฒ€์ฆ โ€” ์•„๋ž˜์—์„œ ์ž์„ธํžˆ



๐Ÿ’ฃ ํ•ต์‹ฌ โ€” ๊ฒฉ์ž, ์—ฌ์„ฏ ๋ฐฉํ–ฅ, ๊ทธ๋ฆฌ๊ณ  ๋ฑ€

์ž…๋ ฅ์— ์“ธ ์ˆ˜ ์žˆ๋Š” ๊ธ€์ž๋Š” ์—ฌ์„ฏ ๊ฐœ๋‹ค

check_chars ๋Š” ๋ฌธ์ž ํ•˜๋‚˜๋ฅผ ์—ฌ์„ฏ ๊ฐ’๊ณผ ์ฐจ๋ก€๋กœ ๋น„๊ตํ•œ๋‹ค. ๊ฐ™์€ ํŒจํ„ด์ด ์—ฌ์„ฏ ๋ฒˆ ๋ฐ˜๋ณต๋˜๋‹ˆ ํŒ์ • ์ค„๋งŒ ๋ฝ‘์•„ ๋ณธ๋‹ค.

# annot_charset.sed
s|cmp    al,0x4b|&               <-- 'K'|
s|cmp    al,0x39|&               <-- '9'|
s|cmp    al,0x7a|&               <-- 'z'|
s|cmp    al,0x37|&               <-- '7'|
s|cmp    al,0x32|&               <-- '2'|
s|cmp    al,0x73|&               <-- 's'  ์—ฌ์„ฏ ๊ธ€์ž๋งŒ ํ—ˆ์šฉํ•œ๋‹ค|
s|test   al,al|&                <-- NUL ์ด๋ฉด ๊ฒ€์‚ฌ ๋|
s|cmp    DWORD PTR \[rbp-0x4\],0xff|&    <-- ์ตœ๋Œ€ 256๊ธ€์ž|
objdump -d -M intel --no-show-raw-insn --start-address=0x40127a --stop-address=0x401348 extracted/chall | sed -f annot_charset.sed | grep -E "cmp|test|jle"
objdump ๋กœ ๋ฝ‘์€ ๋ฌธ์ž ๊ฒ€์‚ฌ ๋ถ€๋ถ„์˜ ํŒ์ • ์ค„ โ€” 0x4b 0x39 0x7a 0x37 0x32 0x73 ์—ฌ์„ฏ ๊ฐ’๊ณผ๋งŒ ๋น„๊ตํ•˜๊ณ  NUL ์„ ๋งŒ๋‚˜๋ฉด ํ†ต๊ณผ, ์ตœ๋Œ€ 256๊ธ€์ž๊นŒ์ง€ ๋ณธ๋‹ค
objdump ๋กœ ๋ฝ‘์€ ๋ฌธ์ž ๊ฒ€์‚ฌ ๋ถ€๋ถ„์˜ ํŒ์ • ์ค„ โ€” 0x4b 0x39 0x7a 0x37 0x32 0x73 ์—ฌ์„ฏ ๊ฐ’๊ณผ๋งŒ ๋น„๊ตํ•˜๊ณ  NUL ์„ ๋งŒ๋‚˜๋ฉด ํ†ต๊ณผ, ์ตœ๋Œ€ 256๊ธ€์ž๊นŒ์ง€ ๋ณธ๋‹ค

0x4b 0x39 0x7a 0x37 0x32 0x73 โ†’ K 9 z 7 2 s. ์—ฌ์„ฏ ๊ฐœ๋‹ค.

ํ”Œ๋ž˜๊ทธ ์•ŒํŒŒ๋ฒณ์ด ์—ฌ์„ฏ ๊ธ€์ž๋กœ ์ œํ•œ๋œ๋‹ค๋Š” ๊ฑด ๊ทธ ์ž์ฒด๋กœ ์˜๋ฏธ๊ฐ€ ์žˆ๋‹ค. ์ž„์˜์˜ ๋ฌธ์ž์—ด์„ ๋งžํžˆ๋Š” ๊ฒŒ ์•„๋‹ˆ๋ผ ์—ฌ์„ฏ ๊ฐ€์ง€ ์ค‘ ํ•˜๋‚˜๋ฅผ ๊ณ ๋ฅด๋Š” ์„ ํƒ์„ ๋ฐ˜๋ณตํ•˜๋Š” ๋ฌธ์ œ๋ผ๋Š” ๋œป์ด๋‹ค.

์ธ๋ฑ์Šค ๊ณ„์‚ฐ์‹์ด ์ž๋ฃŒ๊ตฌ์กฐ๋ฅผ ๋“œ๋Ÿฌ๋‚ธ๋‹ค

can_move ๋ฅผ ๋ณด๋ฉด ๋ฒ”์œ„ ๊ฒ€์‚ฌ์™€ ์ฃผ์†Œ ๊ณ„์‚ฐ์ด ํ•œ์ž๋ฆฌ์— ์žˆ๋‹ค.

# annot_index.sed โ€” ์ฃผ์†Œ๋กœ ์ค„์„ ์ง€์ •ํ•ด์•ผ ๊ฐ™์€ ๋ช…๋ น์ด ์—ฌ๋Ÿฌ ๋ฒˆ ๋‚˜์˜ฌ ๋•Œ ์•ˆ ํ—ท๊ฐˆ๋ฆฐ๋‹ค
s|^  401202:.*|&    <-- x <= 24|
s|^  40120e:.*|&    <-- y <= 24|
s|^  40121a:.*|&    <-- z <= 24|
s|^  401238:.*|&           <-- rsi = z * 625|
s|^  401242:.*|&                 <-- rax = 4y|
s|^  401246:.*|&                 <-- rax = 5y|
s|^  401249:.*|&            <-- rdx = 20y|
s|^  401251:.*|&                 <-- rax = 25y|
s|^  401254:.*|&                 <-- rax = 25y + 625z|
s|^  401257:.*|&            <-- rdx = x + 25y + 625z|
s|^  40125b:.*|&   <-- ๊ฒฉ์ž ์‹œ์ž‘ 0x404060|
s|^  401262:.*|&                 <-- rax = ๊ฒฉ์ž + ์˜คํ”„์…‹|
s|^  401268:.*|&                 <-- ๊ฐ’์ด 1 ์ด๋ฉด ๋ชป ๊ฐ„๋‹ค|
objdump -d -M intel --no-show-raw-insn --start-address=0x4011eb --stop-address=0x40127a extracted/chall | sed -f annot_index.sed
objdump ๋กœ ๋ฝ‘์€ can_move ํ•จ์ˆ˜ โ€” ์„ธ ์ขŒํ‘œ๋ฅผ ๋ชจ๋‘ 0 ์ด์ƒ 24 ์ดํ•˜๋กœ ๊ฒ€์‚ฌํ•œ ๋’ค x + 25y + 625z ๋กœ ์˜คํ”„์…‹์„ ๋งŒ๋“ค์–ด 0x404060 ์—์„œ ์ฝ๊ณ  ๊ฐ’์ด 1 ์ด๋ฉด ์‹คํŒจ๋ฅผ ๋Œ๋ ค์ค€๋‹ค
objdump ๋กœ ๋ฝ‘์€ can_move ํ•จ์ˆ˜ โ€” ์„ธ ์ขŒํ‘œ๋ฅผ ๋ชจ๋‘ 0 ์ด์ƒ 24 ์ดํ•˜๋กœ ๊ฒ€์‚ฌํ•œ ๋’ค x + 25y + 625z ๋กœ ์˜คํ”„์…‹์„ ๋งŒ๋“ค์–ด 0x404060 ์—์„œ ์ฝ๊ณ  ๊ฐ’์ด 1 ์ด๋ฉด ์‹คํŒจ๋ฅผ ๋Œ๋ ค์ค€๋‹ค

์ปดํŒŒ์ผ๋Ÿฌ๊ฐ€ ๊ณฑ์…ˆ์„ ์‹œํ”„ํŠธ์™€ ๋ง์…ˆ์œผ๋กœ ์ชผ๊ฐœ ๋†”์„œ ์ฒ˜์Œ์—” ๋ˆˆ์— ์•ˆ ๋“ค์–ด์˜จ๋‹ค. ์ˆœ์„œ๋Œ€๋กœ ๋”ฐ๋ผ๊ฐ€๋ฉด ์ด๋ ‡๋‹ค.

rsi = z * 0x271        ; 0x271 = 625
rax = y
rax = y << 2           ; 4y
rax = 4y + y           ; 5y
rdx = rax * 4          ; 20y
rax = 5y + 20y         ; 25y
rax = 25y + 625z
rdx = rax + x          ; x + 25y + 625z
rax = 0x404060 + rdx

25 = 5ยฒ, 625 = 25ยฒ. ๊ทธ๋ฆฌ๊ณ  ๋ฒ”์œ„ ๊ฒ€์‚ฌ๊ฐ€ ์„ธ ์ขŒํ‘œ ๋ชจ๋‘ 0..24.

25ร—25ร—25 = 15,625๋ฐ”์ดํŠธ 3์ฐจ์› ๋ฐฐ์—ด์ด๋‹ค. .data ํฌ๊ธฐ 15,657 ์—์„œ ์•ž์˜ 32๋ฐ”์ดํŠธ๋ฅผ ๋นผ๋ฉด ์ •ํ™•ํžˆ 15,625๋‹ค. ๋”ฑ ๋งž๋Š”๋‹ค.

๊ฐ’์ด 1 ์ด๋ฉด ๋ชป ๊ฐ€๋Š” ์นธ. 0 ์ด๋ฉด ํ†ต๋กœ.

์—ฌ์„ฏ ๊ธ€์ž๊ฐ€ ์—ฌ์„ฏ ๋ฐฉํ–ฅ์ด๋‹ค

check ์˜ ์ด๋™ ์ฒ˜๋ฆฌ ๋ถ€๋ถ„์„ ๋ณธ๋‹ค.

# annot_walk.sed
s|^  401372:.*|&    <-- ์‹œ์ž‘ x = 24|
s|^  401379:.*|&    <-- ์‹œ์ž‘ y = 12|
s|^  401380:.*|&    <-- ์‹œ์ž‘ z = 12|
s|^  401394:.*|&      <-- mark(24,12,12)|
s|^  4013e4:.*|&        <-- 'K' : x + 1|
s|^  4013ea:.*|&        <-- '9' : x - 1|
s|^  4013f0:.*|&        <-- 'z' : y + 1|
s|^  4013f6:.*|&        <-- '7' : y - 1|
s|^  4013fc:.*|&        <-- '2' : z + 1|
s|^  401402:.*|&        <-- 's' : z - 1|
s|^  40140f:.*|&    <-- ๋ชฉํ‘œ ํŒ์ •์ด ๋จผ์ €๋‹ค : x == 0|
s|^  401415:.*|&    <-- y == 12|
s|^  40141b:.*|&    <-- z == 12  โ†’ good :)|
s|^  401435:.*|&      <-- ๊ทธ ๋‹ค์Œ์— ์ด๋™ ๊ฐ€๋Šฅ ํŒ์ •|
s|^  401452:.*|&      <-- ๋งˆ์ง€๋ง‰์— ์ด ์นธ์„ ์น ํ•œ๋‹ค (๋ฑ€ ๋ชธํ†ต)|
objdump -d -M intel --no-show-raw-insn --start-address=0x401372 --stop-address=0x40140f extracted/chall | sed -f annot_walk.sed
objdump ๋กœ ๋ฝ‘์€ ์ด๋™ ๋ถ„๊ธฐ โ€” ์‹œ์ž‘ ์ขŒํ‘œ๋ฅผ 24,12,12 ๋กœ ๋‘๊ณ  K 9 z 7 2 s ์—ฌ์„ฏ ๊ธ€์ž๋ฅผ ๊ฐ๊ฐ x y z ์˜ ์ฆ๊ฐ์œผ๋กœ ์—ฐ๊ฒฐํ•˜๋Š” ์ ํ”„ ํ…Œ์ด๋ธ” ํ˜•ํƒœ์˜ ๋น„๊ต ์‚ฌ์Šฌ์ด ๋ณด์ธ๋‹ค
objdump ๋กœ ๋ฝ‘์€ ์ด๋™ ๋ถ„๊ธฐ โ€” ์‹œ์ž‘ ์ขŒํ‘œ๋ฅผ 24,12,12 ๋กœ ๋‘๊ณ  K 9 z 7 2 s ์—ฌ์„ฏ ๊ธ€์ž๋ฅผ ๊ฐ๊ฐ x y z ์˜ ์ฆ๊ฐ์œผ๋กœ ์—ฐ๊ฒฐํ•˜๋Š” ์ ํ”„ ํ…Œ์ด๋ธ” ํ˜•ํƒœ์˜ ๋น„๊ต ์‚ฌ์Šฌ์ด ๋ณด์ธ๋‹ค
๊ธ€์ž์ด๋™
Kx + 1
9x โˆ’ 1
zy + 1
7y โˆ’ 1
2z + 1
sz โˆ’ 1

์‹œ์ž‘์€ (24, 12, 12), ์ฆ‰ ํ๋ธŒ์˜ ํ•œ์ชฝ ๋ฉด ํ•œ๊ฐ€์šด๋ฐ๋‹ค.

์ˆœ์„œ๊ฐ€ ์ค‘์š”ํ•˜๋‹ค โ€” ๋ชฉํ‘œ ํŒ์ •์ด ์ด๋™ ๊ฐ€๋Šฅ ํŒ์ •๋ณด๋‹ค ๋จผ์ €

ํ•œ ๊ฑธ์Œ๋งˆ๋‹ค ํ•˜๋Š” ์ผ์˜ ์ˆœ์„œ๊ฐ€ ์ด ๋ฌธ์ œ์˜ ๋งˆ์ง€๋ง‰ ์กฐ๊ฐ์ด๋‹ค.

objdump -d -M intel --no-show-raw-insn --start-address=0x40140f --stop-address=0x401460 extracted/chall | sed -f annot_walk.sed
objdump ๋กœ ๋ฝ‘์€ ํ•œ ๊ฑธ์Œ ์ฒ˜๋ฆฌ ์ˆœ์„œ โ€” ์ขŒํ‘œ๋ฅผ ์˜ฎ๊ธด ๋’ค ๋จผ์ € 0,12,12 ๋„๋‹ฌ์„ ํ™•์ธํ•˜๊ณ  ๊ทธ๋‹ค์Œ์— ์ด๋™ ๊ฐ€๋Šฅ ์—ฌ๋ถ€๋ฅผ ๋ณด๋ฉฐ ๋งˆ์ง€๋ง‰์— ๊ทธ ์นธ์„ 1 ๋กœ ์น ํ•œ๋‹ค
objdump ๋กœ ๋ฝ‘์€ ํ•œ ๊ฑธ์Œ ์ฒ˜๋ฆฌ ์ˆœ์„œ โ€” ์ขŒํ‘œ๋ฅผ ์˜ฎ๊ธด ๋’ค ๋จผ์ € 0,12,12 ๋„๋‹ฌ์„ ํ™•์ธํ•˜๊ณ  ๊ทธ๋‹ค์Œ์— ์ด๋™ ๊ฐ€๋Šฅ ์—ฌ๋ถ€๋ฅผ ๋ณด๋ฉฐ ๋งˆ์ง€๋ง‰์— ๊ทธ ์นธ์„ 1 ๋กœ ์น ํ•œ๋‹ค

C ๋กœ ์˜ฎ๊ธฐ๋ฉด ์ด๋ ‡๋‹ค.

int check(char *s)
{
    if (!check_chars(s)) return 0;          // K 9 z 7 2 s ๋งŒ ํ—ˆ์šฉ
 
    int x = 24, y = 12, z = 12;
    mark(x, y, z);                          // ์‹œ์ž‘ ์นธ๋„ ๋ชธํ†ต์ด๋‹ค
 
    for (char *p = s; *p && p < s + 0x100; p++) {
        switch (*p) {
            case 'K': x++; break;  case '9': x--; break;
            case 'z': y++; break;  case '7': y--; break;
            case '2': z++; break;  case 's': z--; break;
            default: return 0;
        }
        if (x == 0 && y == 12 && z == 12) return 1;   // โ‘  ๋„์ฐฉ์ด๋ฉด ๊ทธ ์ž๋ฆฌ์—์„œ ์„ฑ๊ณต
        if (!can_move(x, y, z))            return 0;   // โ‘ก ๋ฒฝ์ด๊ฑฐ๋‚˜ ์ด๋ฏธ ๋ฐŸ์€ ์นธ์ด๋ฉด ์‹คํŒจ
        mark(x, y, z);                                 // โ‘ข ์ง€๋‚˜์˜จ ์นธ์„ ๋ฒฝ์œผ๋กœ ๋งŒ๋“ ๋‹ค
    }
    return 0;
}

์„ธ ์ค„์˜ ์ˆœ์„œ๊ฐ€ ๊ฐ๊ฐ ๋œป์ด ์žˆ๋‹ค.

โ‘ ์ด โ‘ก๋ณด๋‹ค ๋จผ์ €๋ผ์„œ ๋ชฉํ‘œ ์นธ์€ ๋ฒฝ์ด์–ด๋„ ์ƒ๊ด€์—†๋‹ค. ๋„์ฐฉ ํŒ์ •์ด ์ด๋™ ๊ฐ€๋Šฅ ํŒ์ •์„ ์•ž์ง€๋ฅธ๋‹ค.

โ‘ข ๋•Œ๋ฌธ์— ์ง€๋‚˜์˜จ ์นธ์ด ๋ฒฝ์ด ๋œ๋‹ค. ๋˜๋Œ์•„๊ฐˆ ์ˆ˜๋„, ์ž๊ธฐ ๊ฒฝ๋กœ์™€ ๊ต์ฐจํ•  ์ˆ˜๋„ ์—†๋‹ค. ๋ฑ€์ด ์ž๊ธฐ ๋ชธ์„ ๋จน์œผ๋ฉด ์ฃฝ๋Š” ๊ฒƒ๊ณผ ๊ฐ™๋‹ค. ๋ฌธ์ œ ์ด๋ฆ„์ด ์—ฌ๊ธฐ์„œ ๋‚˜์™”๋‹ค.

๊ทธ๋Ÿฌ๋‹ˆ ๋‹ต์€ ๋‹จ์ˆœ๊ฒฝ๋กœ์—ฌ์•ผ ํ•œ๋‹ค. ๊ฐ™์€ ์นธ์„ ๋‘ ๋ฒˆ ๋ฐŸ๋Š” ์ˆœ๊ฐ„ ์‹คํŒจ๋‹ค.



๐Ÿ› ์‚ฝ์งˆ

โ–ถ๐Ÿ•ณ๏ธ ์‚ฝ์งˆ 1 โ€” 15,657 ๊ณผ 15,625 ์˜ 32๋ฐ”์ดํŠธ ์ฐจ์ด

์ธ๋ฑ์Šค ๊ณ„์‚ฐ์‹์—์„œ 25ร—25ร—25 = 15,625 ๋ฅผ ์ฝ๊ณ  ๋‚˜์„œ .data ํฌ๊ธฐ์™€ ๋งž์ถฐ ๋ดค๋Š”๋ฐ 15,657 ์ด์—ˆ๋‹ค. 32๋ฐ”์ดํŠธ๊ฐ€ ๋‚จ๋Š”๋‹ค.

๊ณ„์‚ฐ์‹์„ ์ž˜๋ชป ์ฝ์—ˆ๋‚˜ ์‹ถ์–ด ์‹œํ”„ํŠธ ์ˆœ์„œ๋ฅผ ๋‘ ๋ฒˆ ๋‹ค์‹œ ๋”ฐ๋ผ๊ฐ”๋‹ค. ๋‹ต์€ ๋” ๋‹จ์ˆœํ–ˆ๋‹ค โ€” ๊ฒฉ์ž๊ฐ€ .data ์˜ ์‹œ์ž‘์ด ์•„๋‹ˆ์—ˆ๋‹ค.

readelf -SW extracted/chall | grep '\.data'

.data ๋Š” ๊ฐ€์ƒ์ฃผ์†Œ 0x404040 ์—์„œ ์‹œ์ž‘ํ•˜๋Š”๋ฐ, ๋””์Šค์–ด์…ˆ๋ธ”์ด ๊ฐ€๋ฆฌํ‚ค๋Š” ๊ฒฉ์ž๋Š” 0x404060 ์ด๋‹ค. ์ฐจ์ด๊ฐ€ ์ •ํ™•ํžˆ 0x20 = 32๋ฐ”์ดํŠธ. ์•ž์˜ 32๋ฐ”์ดํŠธ๋Š” ๋‹ค๋ฅธ ์ „์—ญ ๋ณ€์ˆ˜ ์ž๋ฆฌ๋‹ค.

๊ทธ๋ž˜์„œ ํŒŒ์ผ์—์„œ ๊ฒฉ์ž๋ฅผ ๋œฐ ๋•Œ ์˜คํ”„์…‹์„ ์ด๋ ‡๊ฒŒ ์žก์•„์•ผ ํ•œ๋‹ค.

GRID_VA, DATA_VA, DATA_OFF = 0x404060, 0x404040, 0x3040
off = DATA_OFF + (GRID_VA - DATA_VA)     # 0x3060

์„น์…˜ ํฌ๊ธฐ๊ฐ€ ๋”ฑ ๋งž์ง€ ์•Š๋Š”๋‹ค๊ณ  ํ•ด์„์ด ํ‹€๋ฆฐ ๊ฒŒ ์•„๋‹ˆ๋‹ค. ์„น์…˜์€ ์—ฌ๋Ÿฌ ๋ณ€์ˆ˜๋ฅผ ๋‹ด๋Š” ๊ทธ๋ฆ‡์ด๊ณ , ์šฐ๋ฆฌ๊ฐ€ ์ฐพ๋Š” ๋ฐฐ์—ด์€ ๊ทธ ์•ˆ์˜ ํ•œ ์กฐ๊ฐ์ผ ๋ฟ์ด๋‹ค. ์ฐจ์ด๊ฐ€ 32์ฒ˜๋Ÿผ ์ž‘๊ณ  ๊น”๋”ํ•œ ๊ฐ’์ด๋ฉด ์˜คํžˆ๋ ค "๋‹ค๋ฅธ ์ „์—ญ์ด ์•ž์— ์žˆ๋‹ค"๋Š” ์‹ ํ˜ธ๋กœ ์ฝ๋Š” ๊ฒŒ ๋งž๋‹ค.

โ–ถ๐Ÿ•ณ๏ธ ์‚ฝ์งˆ 2 โ€” sed ์ฃผ์„์ด ์—‰๋šฑํ•œ ์ค„์— ๋ถ™์—ˆ๋‹ค

๋””์Šค์–ด์…ˆ๋ธ”์— <-- ์ฃผ์„์„ ์–น์œผ๋ ค๊ณ  sed ์Šคํฌ๋ฆฝํŠธ๋ฅผ ์ผ๋Š”๋ฐ, ์ฒ˜์Œ ๊ฒƒ์€ ์„ธ ์ค„์ด ์•„์˜ˆ ์•ˆ ๋ถ™๊ณ  ํ•œ ์ค„์€ ์ž˜๋ชป๋œ ๊ณณ์— ์„ธ ๋ฒˆ ๋ถ™์—ˆ๋‹ค.

์›์ธ์ด ๋‘˜์ด์—ˆ๋‹ค.

์ฒซ์งธ, BRE ์—์„œ \+ ๋Š” ๋ฆฌํ„ฐ๋Ÿด ํ”Œ๋Ÿฌ์Šค๊ฐ€ ์•„๋‹ˆ๋‹ค. GNU sed ์˜ ๊ธฐ๋ณธ ์ •๊ทœ์‹์—์„œ \+ ๋Š” "ํ•˜๋‚˜ ์ด์ƒ"์ด๋ผ๋Š” ์ˆ˜๋Ÿ‰์ž๋‹ค. ๊ทธ๋ž˜์„œ ์ด๋Ÿฐ ํŒจํ„ด์ด ์•„๋ฌด๊ฒƒ๋„ ๋ชป ์žก์•˜๋‹ค.

s|lea    rdx,\[rax\*4\+0x0\]|&   <-- rdx = 20y|

[+] ์ฒ˜๋Ÿผ ๋ฌธ์ž ํด๋ž˜์Šค๋กœ ๊ฐ์‹ธ๋ฉด ๋ฆฌํ„ฐ๋Ÿด์ด ๋œ๋‹ค.

๋‘˜์งธ, ๊ฐ™์€ ๋ช…๋ น์ด ์—ฌ๋Ÿฌ ๋ฒˆ ๋‚˜์˜จ๋‹ค. add rax,rdx ๊ฐ€ ํ•œ ํ•จ์ˆ˜ ์•ˆ์— ์„ธ ๋ฒˆ ์žˆ๋Š”๋ฐ(5y ๋งŒ๋“ค ๋•Œ, 25y ๋งŒ๋“ค ๋•Œ, ๊ฒฉ์ž ์ฃผ์†Œ ๋”ํ•  ๋•Œ) ๋ช…๋ น๋งŒ์œผ๋กœ ํŒจํ„ด์„ ์“ฐ๋ฉด ์…‹ ๋‹ค ๊ฐ™์€ ์ฃผ์„์„ ๋‹ฌ์•„ ๋ฒ„๋ฆฐ๋‹ค. ์‹ค์ œ๋กœ "rax = 5y" ๊ฐ€ ์„ธ ๊ตฐ๋ฐ์— ์ฐํ˜”๋‹ค.

์ฃผ์†Œ๋กœ ์ค„์„ ์ง€์ •ํ•˜๋‹ˆ ๋‘˜ ๋‹ค ํ•ด๊ฒฐ๋๋‹ค.

s|^  401246:.*|&   <-- rax = 5y|
s|^  401251:.*|&   <-- rax = 25y|
s|^  401262:.*|&   <-- rax = ๊ฒฉ์ž + ์˜คํ”„์…‹|

์ฃผ์„์„ ๋‹จ ๋’ค์—๋Š” grep '<--' ๋กœ ๋ช‡ ์ค„์— ๋ถ™์—ˆ๋Š”์ง€ ์„ธ์–ด ๋ณธ๋‹ค. ์˜๋„ํ•œ ๊ฐœ์ˆ˜์™€ ๋‹ค๋ฅด๋ฉด ํŒจํ„ด์ด ํ‹€๋ฆฐ ๊ฒƒ์ด๋‹ค. ์ฃผ์„์ด ํ‹€๋ฆฐ ์ž๋ฆฌ์— ๋ถ™์€ ์บก์ณ๋Š” ๊ธ€์„ ์ฝ๋Š” ์‚ฌ๋žŒ์„ ์ž˜๋ชป๋œ ๋ฐฉํ–ฅ์œผ๋กœ ๋Œ๊ณ  ๊ฐ„๋‹ค.


๐Ÿงช ๋Ÿฐํƒ€์ž„์œผ๋กœ ํ™•์ธ

์ •์  ๋ถ„์„์€ ์—ฌ๊ธฐ๊นŒ์ง€๊ณ , ์ฝ์€ ๊ฒŒ ๋งž๋Š”์ง€ ์‹คํ–‰ ์ค‘์— ํ™•์ธํ•œ๋‹ค. non-PIE ๋ผ ์ฃผ์†Œ๋ฅผ ๊ทธ๋Œ€๋กœ ์“ธ ์ˆ˜ ์žˆ์–ด ๋ฐฐ์น˜ ์Šคํฌ๋ฆฝํŠธ ํ•˜๋‚˜๋ฉด ๋œ๋‹ค.

# runtime_check.gdb
set pagination off
set confirm off
 
# 0x401394 = check() ์•ˆ์˜ ์ฒซ mark(x,y,z) ํ˜ธ์ถœ ์ง์ „
break *0x401394
# 0x401452 = ๊ฑธ์Œ๋งˆ๋‹ค ๋„๋Š” mark(x,y,z) ํ˜ธ์ถœ ์ง์ „
break *0x401452
 
run
 
printf "\n[1] ์‹œ์ž‘ ์ขŒํ‘œ (mark ์ธ์ž: rdi=x, rsi=y, rdx=z)\n"
printf "    x=%d  y=%d  z=%d\n", $edi, $esi, $edx
printf "    ๊ฒฉ์ž ์ฃผ์†Œ 0x404060, ์ธ๋ฑ์Šค x+25*y+625*z\n"
printf "    ์‹œ์ž‘ ์นธ ๊ฐ’ = %d   (0 ์ด๋ฉด ํ†ต๋กœ)\n", *(unsigned char *)(0x404060 + $edi + 25*$esi + 625*$edx)
 
continue
 
printf "\n[2] ์ฒซ ๊ฑธ์Œ ๋’ค โ€” ์ž…๋ ฅ ์ฒซ ๊ธ€์ž๋Š” 'z' ์ด๋ฏ€๋กœ y ๊ฐ€ 1 ๋Š˜์–ด์•ผ ํ•œ๋‹ค\n"
printf "    x=%d  y=%d  z=%d\n", $edi, $esi, $edx
printf "    ์ด ์นธ์˜ ๊ฐ’ = %d   (์•„์ง 0 ์ด๋ผ ํ†ต๊ณผ)\n", *(unsigned char *)(0x404060 + $edi + 25*$esi + 625*$edx)
 
# ๋‹ค์Œ ๊ฑธ์Œ์˜ mark ํ˜ธ์ถœ๊นŒ์ง€ ์ง„ํ–‰ โ€” ๊ทธ ์‚ฌ์ด์— ์•ž ์นธ์ด ์น ํ•ด์กŒ์–ด์•ผ ํ•œ๋‹ค
continue
printf "\n[3] ํ•œ ๊ฑธ์Œ ๋” ๊ฐ„ ๋’ค โ€” ๋ฐฉ๊ธˆ ์ง€๋‚˜์˜จ ์นธ์„ ํ™•์ธํ•œ๋‹ค\n"
printf "    (24,13,12) ๊ฐ’ = %d   (1 ์ด๋ฉด ๋‹ค์‹œ ๋ชป ๋ฐŸ๋Š”๋‹ค)\n", *(unsigned char *)(0x404060 + 24 + 25*13 + 625*12)
 
printf "\n[4] ํ†ต๋กœ ์นธ ์ˆ˜๋ฅผ ์‹คํ–‰ ์ค‘ ๋ฉ”๋ชจ๋ฆฌ์—์„œ ์ง์ ‘ ์„ผ๋‹ค\n"
set $n = 0
set $i = 0
while $i < 15625
  if *(unsigned char *)(0x404060 + $i) == 0
    set $n = $n + 1
  end
  set $i = $i + 1
end
printf "    ๊ฐ’์ด 0 ์ธ ์นธ = %d ๊ฐœ  (์›๋ž˜ 107 ์นธ, ์ง€๋‚˜์˜จ 2์นธ์ด ์ด๋ฏธ ์น ํ•ด์กŒ๋‹ค)\n", $n
 
quit
printf 'zzzzzz222222277779999zzzzzzzssssssss999777777777222222222222zzzzz999zzz999777ssss99999999999777777sssssssz\n' | gdb -q -batch -x runtime_check.gdb extracted/chall
gdb ๋ฐฐ์น˜ ์‹คํ–‰ ๊ฒฐ๊ณผ โ€” ์‹œ์ž‘ ์ขŒํ‘œ๊ฐ€ 24,12,12 ๋กœ ํ™•์ธ๋˜๊ณ  ์ฒซ ๊ธ€์ž z ์— ๋”ฐ๋ผ y ๊ฐ€ 13 ์œผ๋กœ ๋Š˜๋ฉฐ, ์ง€๋‚˜์˜จ ์นธ์˜ ๊ฐ’์ด 1 ๋กœ ๋ฐ”๋€Œ๊ณ  ์‹คํ–‰ ์ค‘ ๋ฉ”๋ชจ๋ฆฌ์—์„œ ํ†ต๋กœ ์นธ์ด 105๊ฐœ๋กœ ์„ธ์–ด์ง„๋‹ค
gdb ๋ฐฐ์น˜ ์‹คํ–‰ ๊ฒฐ๊ณผ โ€” ์‹œ์ž‘ ์ขŒํ‘œ๊ฐ€ 24,12,12 ๋กœ ํ™•์ธ๋˜๊ณ  ์ฒซ ๊ธ€์ž z ์— ๋”ฐ๋ผ y ๊ฐ€ 13 ์œผ๋กœ ๋Š˜๋ฉฐ, ์ง€๋‚˜์˜จ ์นธ์˜ ๊ฐ’์ด 1 ๋กœ ๋ฐ”๋€Œ๊ณ  ์‹คํ–‰ ์ค‘ ๋ฉ”๋ชจ๋ฆฌ์—์„œ ํ†ต๋กœ ์นธ์ด 105๊ฐœ๋กœ ์„ธ์–ด์ง„๋‹ค

[1] ์‹œ์ž‘ ์ขŒํ‘œ๊ฐ€ (24,12,12) ๋กœ ํ™•์ธ๋œ๋‹ค. [2] ์ฒซ ๊ธ€์ž z ์— y ๊ฐ€ 12 โ†’ 13 ์œผ๋กœ ๋Š˜์—ˆ๋‹ค. [3] ๋ฐฉ๊ธˆ ์ง€๋‚˜์˜จ ์นธ์˜ ๊ฐ’์ด 1 ๋กœ ๋ฐ”๋€Œ์–ด ์žˆ๋‹ค. ๋ชธํ†ต์ด ๋‚จ๋Š”๋‹ค๋Š” ๊ฒŒ ์‹คํ–‰ ์ค‘์—๋„ ๊ทธ๋Œ€๋กœ๋‹ค.

[4] ๋Š” ๊ฒฉ์ž๋ฅผ ๋ฉ”๋ชจ๋ฆฌ์—์„œ ์ง์ ‘ ํ›‘์€ ๊ฒƒ์ด๋‹ค. ๊ฐ’์ด 0 ์ธ ์นธ์ด 105๊ฐœ. ์ด๋•Œ ์ด๋ฏธ ๋‘ ์นธ(์‹œ์ž‘๊ณผ ์ฒซ ๊ฑธ์Œ)์„ ์น ํ–ˆ์œผ๋‹ˆ ์›๋ž˜๋Š” 107์นธ์ด๋‹ค.

15,625์นธ ์ค‘ ํ†ต๋กœ๊ฐ€ 107์นธ๋ฟ์ด๋ผ๋Š” ๊ฒŒ ์—ฌ๊ธฐ์„œ ์ฒ˜์Œ ๋“œ๋Ÿฌ๋‚œ๋‹ค.


๐ŸŽฏ ๊ฒฉ์ž๋ฅผ ๊บผ๋‚ด ๋ณด๋‹ˆ ์™ธ๊ธธ์ด์—ˆ๋‹ค

ํŒŒ์ผ์—์„œ ๊ฒฉ์ž๋ฅผ ๊ทธ๋Œ€๋กœ ๋–  ์™€ ๊ตฌ์กฐ๋ฅผ ๋ณธ๋‹ค. .data ๋Š” ํŒŒ์ผ ์˜คํ”„์…‹ 0x3040, ๊ฐ€์ƒ์ฃผ์†Œ 0x404040 ์ด๋ฏ€๋กœ ๊ฒฉ์ž(0x404060)๋Š” ํŒŒ์ผ์—์„œ 0x3060 ์ด๋‹ค.

ํ†ต๋กœ ์นธ๋งˆ๋‹ค ์ด์›ƒํ•œ ํ†ต๋กœ๊ฐ€ ๋ช‡ ๊ฐœ์ธ์ง€ ์„ธ๋ฉด ๋ฏธ๋กœ์˜ ์„ฑ์งˆ์ด ํ•œ ๋ฒˆ์— ๋‚˜์˜จ๋‹ค. 1์ด๋ฉด ๋์ , 2๋ฉด ์™ธ๊ธธ ์ค‘๊ฐ„, 3 ์ด์ƒ์ด๋ฉด ๊ฐˆ๋ฆผ๊ธธ์ด๋‹ค.

#!/usr/bin/env python3
"""๊ฒฉ์ž๊ฐ€ ์™œ ๋‹ต์„ ํ•˜๋‚˜๋งŒ ๊ฐ–๋Š”์ง€ ๊ตฌ์กฐ๋กœ ํ™•์ธํ•œ๋‹ค."""
import collections
 
from solve import MOVES, START, GOAL, load_grid, bfs
 
g = load_grid("extracted/chall")
 
opens = {(x, y, z)
         for z in range(25) for y in range(25) for x in range(25)
         if g[x + 25 * y + 625 * z] == 0}
 
deg = collections.Counter(
    sum(1 for d in MOVES.values() if (x + d[0], y + d[1], z + d[2]) in opens)
    for (x, y, z) in opens
)
 
print(f"ํ†ต๋กœ ์นธ        : {len(opens)} / 15625")
print(f"์ด์›ƒ ํ†ต๋กœ ์ˆ˜ ๋ถ„ํฌ : {dict(sorted(deg.items()))}")
print(f"  ๋์ (1๊ฐœ)     : {deg[1]}")
print(f"  ์™ธ๊ธธ(2๊ฐœ)     : {deg[2]}")
print(f"  ๊ฐˆ๋ฆผ๊ธธ(3๊ฐœ+)  : {sum(v for k, v in deg.items() if k >= 3)}")
print()
 
ends = sorted(p for p in opens
              if sum(1 for d in MOVES.values() if (p[0] + d[0], p[1] + d[1], p[2] + d[2]) in opens) == 1)
print(f"๋์  ์ขŒํ‘œ      : {ends}")
print(f"์‹œ์ž‘ {START} / ๋ชฉํ‘œ {GOAL} ์™€ ์ผ์น˜? {set(ends) == {START, GOAL}}")
print()
 
path = bfs(g)
pts, cur = [START], START
for ch in path:
    d = MOVES[ch]
    cur = (cur[0] + d[0], cur[1] + d[1], cur[2] + d[2])
    pts.append(cur)
 
print(f"BFS ๊ฒฝ๋กœ ๊ฑธ์Œ   : {len(path)}")
print(f"๊ฒฝ๋กœ๊ฐ€ ๋ฐŸ๋Š” ์นธ  : {len(set(pts))}")
print(f"ํ†ต๋กœ ์ „์ฒด์™€ ๊ฐ™๋‚˜ : {set(pts) == opens}   โ† ๊ฐ™์œผ๋ฉด ๊ณ๊ฐ€์ง€๊ฐ€ ํ•˜๋‚˜๋„ ์—†๋‹ค๋Š” ๋œป")
python3 analyze_grid.py
๊ฒฉ์ž ๊ตฌ์กฐ ๋ถ„์„ ์ถœ๋ ฅ โ€” ํ†ต๋กœ 107์นธ ์ค‘ ์ด์›ƒ์ด 1๊ฐœ์ธ ๋์ ์ด 2๊ฐœ, ์ด์›ƒ์ด 2๊ฐœ์ธ ์™ธ๊ธธ์ด 105๊ฐœ์ด๊ณ  ๊ฐˆ๋ฆผ๊ธธ์€ 0๊ฐœ์ด๋ฉฐ ๋์  ๋‘ ๊ณณ์ด ์‹œ์ž‘๊ณผ ๋ชฉํ‘œ์™€ ์ •ํ™•ํžˆ ์ผ์น˜ํ•œ๋‹ค
๊ฒฉ์ž ๊ตฌ์กฐ ๋ถ„์„ ์ถœ๋ ฅ โ€” ํ†ต๋กœ 107์นธ ์ค‘ ์ด์›ƒ์ด 1๊ฐœ์ธ ๋์ ์ด 2๊ฐœ, ์ด์›ƒ์ด 2๊ฐœ์ธ ์™ธ๊ธธ์ด 105๊ฐœ์ด๊ณ  ๊ฐˆ๋ฆผ๊ธธ์€ 0๊ฐœ์ด๋ฉฐ ๋์  ๋‘ ๊ณณ์ด ์‹œ์ž‘๊ณผ ๋ชฉํ‘œ์™€ ์ •ํ™•ํžˆ ์ผ์น˜ํ•œ๋‹ค

์ฝ์„ ๊ฒƒ์ด ์„ธ ๊ฐ€์ง€๋‹ค.

๊ฐˆ๋ฆผ๊ธธ์ด 0๊ฐœ๋‹ค. ํ†ต๋กœ 107์นธ์ด ์ „๋ถ€ ์ด์›ƒ 2๊ฐœ(๋์ ๋งŒ 1๊ฐœ)๋ผ ๋ถ„๊ธฐ๊ฐ€ ์—†๋‹ค. ํ•˜๋‚˜๋กœ ์ด์–ด์ง„ ๊ด€์ด๋‹ค.

๋์  ๋‘ ๊ณณ์ด ์‹œ์ž‘๊ณผ ๋ชฉํ‘œ์™€ ์ •ํ™•ํžˆ ์ผ์น˜ํ•œ๋‹ค. ์ฆ‰ ์ด ๊ด€์˜ ์–‘ ๋์ด ๋ฌธ์ œ์˜ ์ถœ๋ฐœ์ ๊ณผ ๋„์ฐฉ์ ์ด๋‹ค.

BFS ๊ฒฝ๋กœ๊ฐ€ ํ†ต๋กœ ์ „์ฒด์™€ ๊ฐ™๋‹ค. 106๊ฑธ์Œ์ด ๋ฐŸ๋Š” 107์นธ์ด ์—ด๋ฆฐ ์นธ ์ „๋ถ€๋‹ค. ๊ณ๊ฐ€์ง€๋„, ๋ง‰๋‹ค๋ฅธ ๊ธธ๋„ ์—†๋‹ค.

๊ทธ๋ž˜์„œ ๋‹ต์ด ํ•˜๋‚˜๋ฟ์ด๋‹ค. ๋ฌธ์ œ ํŽ˜์ด์ง€์˜ "์ •๋‹ต์ด ์—ฌ๋Ÿฌ ๊ฐœ์˜€๋˜ ๊ฒƒ์„ ์ˆ˜์ •ํ–ˆ๋‹ค"๋Š” ๊ธฐ๋ก๊ณผ ๋งž์•„๋–จ์–ด์ง„๋‹ค.

๋ˆˆ์œผ๋กœ๋„ ํ™•์ธํ•ด ๋‘๋ ค๊ณ  ๊ฒฉ์ž๋ฅผ z ํŒ๋ณ„๋กœ ํŽผ์ณ ๊ทธ๋ ธ๋‹ค. ์†์œผ๋กœ ๊ทธ๋ฆฐ ๋„์‹์ด ์•„๋‹ˆ๋ผ ์ถ”์ถœํ•œ ๋ฐ์ดํ„ฐ๋ฅผ ๊ทธ๋Œ€๋กœ ๋ Œ๋”ํ•œ ๊ฒƒ์ด๋‹ค.

๊ฒฉ์ž๋ฅผ z ํŒ๋ณ„๋กœ ํŽผ์นœ ๊ทธ๋ฆผ โ€” ํ†ต๋กœ 107์นธ์ด z 11 ๋ถ€ํ„ฐ 23 ๊นŒ์ง€ ํฉ์–ด์ ธ ์žˆ๊ณ  ์ „๋ถ€ ์ •๋‹ต ๊ฒฝ๋กœ ์ƒ‰์œผ๋กœ ์น ํ•ด์ ธ ์žˆ์–ด ๊ฒฝ๋กœ ๋ฐ– ํ†ต๋กœ๊ฐ€ ํ•˜๋‚˜๋„ ์—†๋‹ค๋Š” ๊ฒŒ ๋ˆˆ์œผ๋กœ ๋ณด์ธ๋‹ค
๊ฒฉ์ž๋ฅผ z ํŒ๋ณ„๋กœ ํŽผ์นœ ๊ทธ๋ฆผ โ€” ํ†ต๋กœ 107์นธ์ด z 11 ๋ถ€ํ„ฐ 23 ๊นŒ์ง€ ํฉ์–ด์ ธ ์žˆ๊ณ  ์ „๋ถ€ ์ •๋‹ต ๊ฒฝ๋กœ ์ƒ‰์œผ๋กœ ์น ํ•ด์ ธ ์žˆ์–ด ๊ฒฝ๋กœ ๋ฐ– ํ†ต๋กœ๊ฐ€ ํ•˜๋‚˜๋„ ์—†๋‹ค๋Š” ๊ฒŒ ๋ˆˆ์œผ๋กœ ๋ณด์ธ๋‹ค

z ํŒ์„ ์˜ค๊ฐ€๋ฉฐ ์ด์–ด์ง€๋Š” ๊ฒŒ ๋ณด์ธ๋‹ค. ํŒ ํ•˜๋‚˜์— ์  ํ•˜๋‚˜๋งŒ ์ฐํžŒ z ๋“ค(1318, 2022)์€ ๊ฒฝ๋กœ๊ฐ€ ๊ทธ ์ธต์„ ๊ด€ํ†ตํ•ด ์ง€๋‚˜๊ฐ€๊ธฐ๋งŒ ํ•˜๋Š” ๊ตฌ๊ฐ„์ด๋‹ค.



๐Ÿš€ Full Exploit

BFS ๋กœ ์ตœ๋‹จ๊ฒฝ๋กœ๋ฅผ ์ฐพ๋Š”๋‹ค. ๋ฑ€ ์ œ์•ฝ("๊ฐ™์€ ์นธ์„ ๋‘ ๋ฒˆ ๋ฐŸ์œผ๋ฉด ์‹คํŒจ")์€ ๋”ฐ๋กœ ์ฒ˜๋ฆฌํ•  ํ•„์š”๊ฐ€ ์—†๋‹ค โ€” BFS ๊ฐ€ ์ฐพ๋Š” ์ตœ๋‹จ๊ฒฝ๋กœ๋Š” ์• ์ดˆ์— ๊ฐ™์€ ์นธ์„ ๋‘ ๋ฒˆ ์ง€๋‚˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

๋ชฉํ‘œ ํŒ์ •์ด ์ด๋™ ๊ฐ€๋Šฅ ํŒ์ •๋ณด๋‹ค ๋จผ์ €๋ผ๋Š” ์ ๋งŒ ์ฝ”๋“œ์— ๋ฐ˜์˜ํ•˜๋ฉด ๋œ๋‹ค.

#!/usr/bin/env python3
"""Snaky (DreamHack, Gold 4 / reversing) โ€” solver
 
๋ฐ”์ด๋„ˆ๋ฆฌ๊ฐ€ ํ•˜๋Š” ์ผ:
  .data 0x404060 ์— 25x25x25 ๋ฐ”์ดํŠธ ๋ฐฐ์—ด์ด ์žˆ๋‹ค. ์ธ๋ฑ์Šค๋Š” x + 25*y + 625*z.
  ๊ฐ’ 1 = ๋ง‰ํžŒ ์นธ. ์‹œ์ž‘ (24,12,12) ์—์„œ ์ถœ๋ฐœํ•ด ์ž…๋ ฅ ๋ฌธ์ž์—ด์„ ํ•œ ๊ธ€์ž์”ฉ ๋ฐฉํ–ฅ์œผ๋กœ ์ฝ๋Š”๋‹ค.
 
      K: x+1    9: x-1    z: y+1    7: y-1    2: z+1    s: z-1
 
  ๊ฐ ๊ฑธ์Œ๋งˆ๋‹ค
    โ‘  (0,12,12) ์— ๋„๋‹ฌํ–ˆ์œผ๋ฉด ๊ทธ ์ž๋ฆฌ์—์„œ ์„ฑ๊ณต(good :)
    โ‘ก 0..24 ๋ฒ”์œ„๋ฅผ ๋ฒ—์–ด๋‚˜๊ฑฐ๋‚˜ ๊ฐ’์ด 1 ์ธ ์นธ์ด๋ฉด ์‹คํŒจ
    โ‘ข ์•„๋‹ˆ๋ฉด ๊ทธ ์นธ์„ 1 ๋กœ ์น ํ•˜๊ณ  ๊ณ„์†    โ† ์ง€๋‚˜์˜จ ์นธ์„ ๋ฒฝ์œผ๋กœ ๋งŒ๋“ ๋‹ค(๋ฑ€)
 
  โ‘ข ๋•Œ๋ฌธ์— ๊ฒฝ๋กœ๋Š” ์ž๊ธฐ ์ž์‹ ๊ณผ ๋งŒ๋‚  ์ˆ˜ ์—†๋‹ค. ๊ทธ๋ž˜์„œ ๋‹จ์ˆœ๊ฒฝ๋กœ๋งŒ ๋‹ต์ด ๋œ๋‹ค.
  BFS ์ตœ๋‹จ๊ฒฝ๋กœ๋Š” ์• ์ดˆ์— ๊ฐ™์€ ์นธ์„ ๋‘ ๋ฒˆ ๋ฐŸ์ง€ ์•Š์œผ๋ฏ€๋กœ ์ด ์ œ์•ฝ์„ ์ž๋™์œผ๋กœ ๋งŒ์กฑํ•œ๋‹ค.
 
  flag = DH{<์ฐพ์€ ๊ฒฝ๋กœ ๋ฌธ์ž์—ด>}
"""
import argparse
import collections
import sys
 
N = 25
START = (24, 12, 12)
GOAL = (0, 12, 12)
 
# ๋ฌธ์ž โ†’ (dx, dy, dz).  ๋””์Šค์–ด์…ˆ๋ธ” 0x4013a6~0x401406 ๊ทธ๋Œ€๋กœ.
MOVES = {
    "K": (1, 0, 0),
    "9": (-1, 0, 0),
    "z": (0, 1, 0),
    "7": (0, -1, 0),
    "2": (0, 0, 1),
    "s": (0, 0, -1),
}
 
GRID_VA, DATA_VA, DATA_OFF = 0x404060, 0x404040, 0x3040
 
 
def load_grid(path: str) -> bytes:
    """ELF ์—์„œ 25^3 ๊ฒฉ์ž๋ฅผ ๊ทธ๋Œ€๋กœ ๋–  ์˜จ๋‹ค (์„น์…˜ ํ—ค๋” ์—†์ด ๊ณ ์ • ์˜คํ”„์…‹)."""
    blob = open(path, "rb").read()
    off = DATA_OFF + (GRID_VA - DATA_VA)
    g = blob[off:off + N * N * N]
    if len(g) != N * N * N:
        sys.exit(f"๊ฒฉ์ž๋ฅผ ๋ชป ์ฝ์—ˆ๋‹ค: {len(g)} ๋ฐ”์ดํŠธ")
    return g
 
 
def blocked(g: bytes, x: int, y: int, z: int) -> bool:
    """can_move() ์™€ ๊ฐ™์€ ํŒ์ • โ€” ๋ฒ”์œ„ ๋ฐ–์ด๊ฑฐ๋‚˜ ๊ฐ’์ด 1 ์ด๋ฉด ๋ชป ๊ฐ„๋‹ค."""
    if not (0 <= x <= 24 and 0 <= y <= 24 and 0 <= z <= 24):
        return True
    return g[x + 25 * y + 625 * z] == 1
 
 
def bfs(g: bytes) -> str | None:
    """START โ†’ GOAL ์ตœ๋‹จ ๊ฒฝ๋กœ๋ฅผ ์ด๋™ ๋ฌธ์ž์—ด๋กœ ๋Œ๋ ค์ค€๋‹ค."""
    prev: dict = {START: None}
    q = collections.deque([START])
    while q:
        cur = q.popleft()
        for ch, (dx, dy, dz) in MOVES.items():
            nxt = (cur[0] + dx, cur[1] + dy, cur[2] + dz)
            if nxt == GOAL:                      # ๋ชฉํ‘œ ํŒ์ •์ด ์ด๋™ ๊ฐ€๋Šฅ ํŒ์ •๋ณด๋‹ค ๋จผ์ €๋‹ค
                path, node = [ch], cur
                while prev[node] is not None:
                    pch, pnode = prev[node]
                    path.append(pch)
                    node = pnode
                return "".join(reversed(path))
            if nxt in prev or blocked(g, *nxt):
                continue
            prev[nxt] = (ch, cur)
            q.append(nxt)
    return None
 
 
def count_simple_paths(g: bytes, limit: int = 5) -> int:
    """๋‹จ์ˆœ๊ฒฝ๋กœ๊ฐ€ ์ •๋ง ํ•˜๋‚˜๋ฟ์ธ์ง€ ์„ผ๋‹ค (์—ด๋ฆฐ ์นธ์ด 107๊ฐœ๋ผ ์™„์ „ํƒ์ƒ‰์ด ๋œ๋‹ค)."""
    found = 0
    seen = {START}
 
    def dfs(cur):
        nonlocal found
        if found >= limit:
            return
        for ch, (dx, dy, dz) in MOVES.items():
            nxt = (cur[0] + dx, cur[1] + dy, cur[2] + dz)
            if nxt == GOAL:
                found += 1
                if found >= limit:
                    return
                continue
            if nxt in seen or blocked(g, *nxt):
                continue
            seen.add(nxt)
            dfs(nxt)
            seen.discard(nxt)
 
    dfs(START)
    return found
 
 
def simulate(g: bytes, s: str) -> bool:
    """๋ฐ”์ด๋„ˆ๋ฆฌ์˜ check() ๋ฅผ ๊ทธ๋Œ€๋กœ ํ‰๋‚ด๋‚ด ๊ฒ€์ฆํ•œ๋‹ค."""
    if any(c not in MOVES for c in s):
        return False
    grid = bytearray(g)
    x, y, z = START
    grid[x + 25 * y + 625 * z] = 1
    for c in s:
        dx, dy, dz = MOVES[c]
        x, y, z = x + dx, y + dy, z + dz
        if (x, y, z) == GOAL:
            return True
        if not (0 <= x <= 24 and 0 <= y <= 24 and 0 <= z <= 24):
            return False
        if grid[x + 25 * y + 625 * z] == 1:
            return False
        grid[x + 25 * y + 625 * z] = 1
    return False
 
 
def main() -> int:
    ap = argparse.ArgumentParser()
    ap.add_argument("binary", nargs="?", default="extracted/chall")
    ap.add_argument("--count-paths", action="store_true", help="๋‹จ์ˆœ๊ฒฝ๋กœ ๊ฐœ์ˆ˜๋„ ์„ผ๋‹ค")
    a = ap.parse_args()
 
    g = load_grid(a.binary)
    opens = sum(1 for b in g if b == 0)
    print(f"[*] ๊ฒฉ์ž 25x25x25 = {len(g)} ์นธ,  ํ†ต๋กœ {opens} ์นธ / ๋ฒฝ {len(g) - opens} ์นธ")
    print(f"[*] ์‹œ์ž‘ {START} โ†’ ๋ชฉํ‘œ {GOAL}")
 
    path = bfs(g)
    if path is None:
        print("[-] ๊ฒฝ๋กœ ์—†์Œ")
        return 1
 
    print(f"[+] ๊ฒฝ๋กœ ๊ธธ์ด {len(path)}")
    print(f"[+] ๊ฒฝ๋กœ     {path}")
    print(f"[+] ์ž์ฒด ๊ฒ€์ฆ(check ์žฌํ˜„) : {'ํ†ต๊ณผ' if simulate(g, path) else '์‹คํŒจ'}")
 
    if a.count_paths:
        n = count_simple_paths(g)
        print(f"[*] ๋‹จ์ˆœ๊ฒฝ๋กœ ๊ฐœ์ˆ˜ : {'5๊ฐœ ์ด์ƒ' if n >= 5 else n}๊ฐœ")
 
    print(f"[+] FLAG: DH{{{path}}}")
    return 0
 
 
if __name__ == "__main__":
    sys.exit(main())
python3 solve.py --count-paths
solve.py ์‹คํ–‰ ๊ฒฐ๊ณผ โ€” ํ†ต๋กœ 107์นธ์„ ํ™•์ธํ•˜๊ณ  106๊ฑธ์Œ ๊ฒฝ๋กœ๋ฅผ ์ฐพ์€ ๋’ค ์ž์ฒด ๊ฒ€์ฆ์„ ํ†ต๊ณผํ•˜๋ฉฐ ๋‹จ์ˆœ๊ฒฝ๋กœ ์™„์ „ํƒ์ƒ‰ ๊ฒฐ๊ณผ๊ฐ€ 1๊ฐœ๋กœ ๋‚˜์™€ ํ”Œ๋ž˜๊ทธ๊ฐ€ ์ถœ๋ ฅ๋œ๋‹ค
solve.py ์‹คํ–‰ ๊ฒฐ๊ณผ โ€” ํ†ต๋กœ 107์นธ์„ ํ™•์ธํ•˜๊ณ  106๊ฑธ์Œ ๊ฒฝ๋กœ๋ฅผ ์ฐพ์€ ๋’ค ์ž์ฒด ๊ฒ€์ฆ์„ ํ†ต๊ณผํ•˜๋ฉฐ ๋‹จ์ˆœ๊ฒฝ๋กœ ์™„์ „ํƒ์ƒ‰ ๊ฒฐ๊ณผ๊ฐ€ 1๊ฐœ๋กœ ๋‚˜์™€ ํ”Œ๋ž˜๊ทธ๊ฐ€ ์ถœ๋ ฅ๋œ๋‹ค

--count-paths ๋Š” DFS ๋กœ ๋‹จ์ˆœ๊ฒฝ๋กœ๋ฅผ ์ „๋ถ€ ์„ธ๋Š” ์˜ต์…˜์ด๋‹ค. ํ†ต๋กœ๊ฐ€ 107์นธ๋ฟ์ด๋ผ ์™„์ „ํƒ์ƒ‰์ด ์ˆœ์‹๊ฐ„์— ๋๋‚œ๋‹ค. ๊ฒฐ๊ณผ๋Š” 1๊ฐœ โ€” ๊ตฌ์กฐ ๋ถ„์„๊ณผ ์ผ์น˜ํ•œ๋‹ค.

์‹ค์ œ ๋ฐ”์ด๋„ˆ๋ฆฌ๋กœ ํ™•์ธ

๊ณ„์‚ฐ์ด ๋งž์•„๋„ ํ”„๋กœ๊ทธ๋žจ์ด good :) ์„ ๋ฑ‰๋Š”์ง€๋Š” ๋ณ„๊ฐœ๋‹ค. ๋Œ€์กฐ๊ตฐ์„ ๊ฐ™์ด ๋„ฃ์–ด ๋Œ๋ฆฐ๋‹ค.

#!/usr/bin/env python3
"""์ฐพ์€ ๊ฒฝ๋กœ๋ฅผ ์‹ค์ œ ๋ฐ”์ด๋„ˆ๋ฆฌ์— ๋จน์—ฌ good :) ์ด ๋‚˜์˜ค๋Š”์ง€ ํ™•์ธํ•œ๋‹ค."""
import subprocess
 
BIN = "./extracted/chall"
ANSWER = ("zzzzzz222222277779999zzzzzzzssssssss999777777777222222222222"
          "zzzzz999zzz999777ssss99999999999777777sssssssz")
 
 
def run(s: str) -> str:
    p = subprocess.run([BIN], input=s + "\n", capture_output=True, text=True, timeout=20)
    return p.stdout.strip()
 
 
cases = [
    ("์ •๋‹ต ๊ฒฝ๋กœ", ANSWER),
    ("๋งˆ์ง€๋ง‰ ๊ธ€์ž๋งŒ ๋ฐ”๊ฟˆ", ANSWER[:-1] + "7"),
    ("ํ•œ ๊ฑธ์Œ ์งง๊ฒŒ", ANSWER[:-1]),
    ("์—ญ์ˆœ", ANSWER[::-1]),
]
 
for label, s in cases:
    out = run(s)
    print(f"{label:20s} len={len(s):3d}  โ†’  {out}")
 
print()
print(f"FLAG: DH{{{ANSWER}}}")
python3 verify.py
verify.py ์‹คํ–‰ ๊ฒฐ๊ณผ โ€” ์ •๋‹ต ๊ฒฝ๋กœ๋งŒ good ์ด ๋‚˜์˜ค๊ณ  ๋งˆ์ง€๋ง‰ ๊ธ€์ž๋ฅผ ๋ฐ”๊พธ๊ฑฐ๋‚˜ ํ•œ ๊ฑธ์Œ ์งง๊ฒŒ ํ•˜๊ฑฐ๋‚˜ ์—ญ์ˆœ์œผ๋กœ ๋„ฃ์€ ์„ธ ๋Œ€์กฐ๊ตฐ์€ ๋ชจ๋‘ wrong ์ด ๋‚˜์˜จ๋‹ค
verify.py ์‹คํ–‰ ๊ฒฐ๊ณผ โ€” ์ •๋‹ต ๊ฒฝ๋กœ๋งŒ good ์ด ๋‚˜์˜ค๊ณ  ๋งˆ์ง€๋ง‰ ๊ธ€์ž๋ฅผ ๋ฐ”๊พธ๊ฑฐ๋‚˜ ํ•œ ๊ฑธ์Œ ์งง๊ฒŒ ํ•˜๊ฑฐ๋‚˜ ์—ญ์ˆœ์œผ๋กœ ๋„ฃ์€ ์„ธ ๋Œ€์กฐ๊ตฐ์€ ๋ชจ๋‘ wrong ์ด ๋‚˜์˜จ๋‹ค

์ •๋‹ต๋งŒ good :), ๋‚˜๋จธ์ง€ ์…‹์€ ์ „๋ถ€ wrong :(.

์—ญ์ˆœ์ด ์‹คํŒจํ•˜๋Š” ๊ฒŒ ์žฌ๋ฐŒ๋‹ค. ํ†ต๋กœ๋Š” ๋Œ€์นญ์ธ๋ฐ ์‹œ์ž‘๊ณผ ๋ชฉํ‘œ๊ฐ€ ์ •ํ•ด์ ธ ์žˆ์œผ๋‹ˆ ๋ฐฉํ–ฅ์„ ๋’ค์ง‘์œผ๋ฉด ์ฒซ ๊ฑธ์Œ๋ถ€ํ„ฐ ๋ฒฝ์ด๋‹ค.

DH{zzzzzz222222277779999zzzzzzzssssssss999777777777222222222222zzzzz999zzz999777ssss99999999999777777sssssssz}



๐Ÿงช ์žฌํ˜„

reproduce.sh ํ•˜๋‚˜๋กœ ๊ฒฉ์ž ์ถ”์ถœ๋ถ€ํ„ฐ ์‹ค์ œ ๋ฐ”์ด๋„ˆ๋ฆฌ ํ™•์ธ๊นŒ์ง€ ๋ˆ๋‹ค. ์™ธ๋ถ€ ์„œ๋ฒ„๊ฐ€ ํ•„์š” ์—†๋Š” ์˜คํ”„๋ผ์ธ ๋ฌธ์ œ๋ผ ์ธ์ž๋„ ์—†๋‹ค.

./reproduce.sh

ํ•„์š”ํ•œ ๊ฑด python3, objdump, ๊ทธ๋ฆฌ๊ณ  x86-64 ๋ฆฌ๋ˆ…์Šค๋ฟ์ด๋‹ค. ๋ฐ”์ด๋„ˆ๋ฆฌ๊ฐ€ ๋™์  ๋งํฌ๋ผ glibc ๊ฐ€ ์žˆ์œผ๋ฉด ๊ทธ๋Œ€๋กœ ๋ˆ๋‹ค.

ํŒ์ •์€ ์ด๋ ‡๊ฒŒ ์ฝ๋Š”๋‹ค.

ํ™”๋ฉด๋œป๋Œ€์ฒ˜
๊ฒฉ์ž๋ฅผ ๋ชป ์ฝ์—ˆ๋‹คํŒŒ์ผ ์˜คํ”„์…‹์ด ์•ˆ ๋งž์Œreadelf -SW ๋กœ .data ์˜คํ”„์…‹์„ ๋‹ค์‹œ ํ™•์ธ
ํ†ต๋กœ 107 ์นธ ์ด ์•„๋‹˜๋‹ค๋ฅธ ๋ฒ„์ „์˜ ๋ฐฐํฌ๋ณธ2025.03.05 ์ดํ›„ ๋ฐฐํฌ๋ณธ์ธ์ง€ ํ™•์ธ
๋‹จ์ˆœ๊ฒฝ๋กœ ๊ฐœ์ˆ˜ : 5๊ฐœ ์ด์ƒ๋ฏธ๋กœ์— ๊ฐˆ๋ฆผ๊ธธ์ด ์ƒ๊น€์œ„์™€ ๊ฐ™์Œ โ€” ์˜› ๋ฐฐํฌ๋ณธ์ผ ๊ฐ€๋Šฅ์„ฑ
์ž์ฒด ๊ฒ€์ฆ : ์‹คํŒจ์ด๋™ํ‘œ๋‚˜ ์ˆœ์„œ ํ•ด์„์ด ํ‹€๋ฆผsimulate() ๋ฅผ ๋””์Šค์–ด์…ˆ๋ธ”๊ณผ ๋‹ค์‹œ ๋Œ€์กฐ
wrong :(๋ฐ”์ด๋„ˆ๋ฆฌ์— ์‹คํ–‰ ๊ถŒํ•œ์ด ์—†๊ฑฐ๋‚˜ ๋‹ค๋ฅธ ํŒŒ์ผchmod +x extracted/chall

๋งˆ์ง€๋ง‰ ์ค„์€ ์‹ค์ œ๋กœ ๋ฐŸ์•˜๋‹ค. ๋ฐฐํฌ zip ์ด ์‹คํ–‰ ๋น„ํŠธ๋ฅผ ๋ณด์กดํ•˜์ง€ ์•Š์•„์„œ chmod ์—†์ด๋Š” ์•„์˜ˆ ์‹คํ–‰์ด ์•ˆ ๋œ๋‹ค.



๐Ÿ“ ๊ฒฐ๋ก 

์„น์…˜ ํฌ๊ธฐ๋Š” ๊ณต์งœ๋กœ ์–ป๋Š” ๋‹จ์„œ๋‹ค.

readelf -S ํ•œ ๋ฒˆ์ด๋ฉด ๋กœ์งํ˜•์ธ์ง€ ๋ฐ์ดํ„ฐํ˜•์ธ์ง€ ๊ฐˆ๋ฆฐ๋‹ค. .text ๊ฐ€ ์ž‘๊ณ  .data ๊ฐ€ ํฌ๋ฉด ๋‹ต์€ ํ‘œ ์•ˆ์— ์žˆ๊ณ , ํ•  ์ผ์€ ๊ทธ ํ‘œ์˜ ๋ชจ์–‘์„ ์•Œ์•„๋‚ด๋Š” ๊ฒƒ์ด๋‹ค. ์ด ๋ฌธ์ œ๋Š” ๊ทธ ํŒ๋‹จ๋งŒ์œผ๋กœ ๋ฐฉํ–ฅ์ด ์žกํ˜”๋‹ค.

๊ณฑ์…ˆ ์ƒ์ˆ˜๊ฐ€ ์ž๋ฃŒ๊ตฌ์กฐ๋ฅผ ๋งํ•œ๋‹ค.

imul rsi,rax,0x271 ์—์„œ 625 ๋ฅผ, ๊ทธ ์œ„์—์„œ 25 ๋ฅผ ์ฝ๋Š” ์ˆœ๊ฐ„ 3์ฐจ์› ๋ฐฐ์—ด์ด ํ™•์ •๋œ๋‹ค. ์ปดํŒŒ์ผ๋Ÿฌ๊ฐ€ ๊ณฑ์…ˆ์„ ์‹œํ”„ํŠธ์™€ ๋ง์…ˆ์œผ๋กœ ์ชผ๊ฐœ ๋†”์„œ ํ•œ๋ˆˆ์— ์•ˆ ๋ณด์ผ ๋ฟ์ด๋‹ค. ์ƒ์ˆ˜๋ฅผ ์ธ์ˆ˜๋ถ„ํ•ดํ•ด ๋ณด๋Š” ์Šต๊ด€์ด ์—ฌ๊ธฐ์„œ ๊ฐ’์„ ํ•œ๋‹ค.

์—ฐ์‚ฐ ์ˆœ์„œ๊นŒ์ง€ ์ฝ์–ด์•ผ ์ •ํ™•ํ•œ ๋ชจ๋ธ์ด ๋œ๋‹ค.

๋ชฉํ‘œ ํŒ์ •์ด ์ด๋™ ๊ฐ€๋Šฅ ํŒ์ •๋ณด๋‹ค ๋จผ์ € ์˜ค๋Š” ๊ฒƒ, ๊ทธ๋ฆฌ๊ณ  ์น ํ•˜๊ธฐ๊ฐ€ ๋งจ ๋งˆ์ง€๋ง‰์ธ ๊ฒƒ โ€” ๋‘˜ ์ค‘ ํ•˜๋‚˜๋งŒ ์ž˜๋ชป ์˜ฎ๊ฒจ๋„ ์‹œ๋ฎฌ๋ ˆ์ดํ„ฐ๊ฐ€ ์›๋ณธ๊ณผ ์–ด๊ธ‹๋‚œ๋‹ค. ๋””์Šค์–ด์…ˆ๋ธ”์—์„œ ๋ถ„๊ธฐ์˜ ์œ„์น˜๋Š” ์กฐ๊ฑด ์ž์ฒด๋งŒํผ ์ค‘์š”ํ•˜๋‹ค.

ํ‘ผ ๋’ค์— ๊ตฌ์กฐ๋ฅผ ํ•œ ๋ฒˆ ๋” ํ™•์ธํ•˜๋ฉด ๋‹ต์ด ๋งž์•˜๋‹ค๋Š” ๊ฑธ ์Šค์Šค๋กœ ์•Œ ์ˆ˜ ์žˆ๋‹ค.

๊ฒฝ๋กœ๋ฅผ ์ฐพ๊ณ  ๋๋‚ผ ์ˆ˜๋„ ์žˆ์—ˆ์ง€๋งŒ, ํ†ต๋กœ์˜ ์ฐจ์ˆ˜ ๋ถ„ํฌ๋ฅผ ์„ธ ๋ณด๋‹ˆ ๊ฐˆ๋ฆผ๊ธธ์ด 0๊ฐœ์˜€๋‹ค. ๊ทธ๋ž˜์„œ ๋‹ต์ด ํ•˜๋‚˜๋ฟ์ด๋ผ๋Š” ๊ฒŒ ํƒ์ƒ‰ ๊ฒฐ๊ณผ๊ฐ€ ์•„๋‹ˆ๋ผ ๊ตฌ์กฐ๋กœ ์„ค๋ช…๋œ๋‹ค. ๋ฌธ์ œ ํŽ˜์ด์ง€์˜ ์ˆ˜์ • ๊ธฐ๋ก๊ณผ๋„ ๋งž๋ฌผ๋ฆฐ๋‹ค. ์ด๋Ÿฐ ํ™•์ธ์€ ๋ช‡ ์ค„์ด๋ฉด ๋˜๊ณ , ํ‹€๋ฆฐ ๋‹ต์„ ๋ถ™๋“ค๊ณ  ์žˆ๋Š” ์‹œ๊ฐ„์„ ์ค„์—ฌ ์ค€๋‹ค.

๋ฐฉ์–ด ์ชฝ์—์„œ ๋ณด๋ฉด, ๊ฒ€์ฆ ๋กœ์ง์„ ๋ฐ์ดํ„ฐ ํ‘œ๋กœ ์˜ฎ๊ธฐ๋Š” ๊ฑด ๋‚œ๋…ํ™”๊ฐ€ ์•„๋‹ˆ๋‹ค. ํ‘œ๊ฐ€ ํฌ๋ฉด ์˜คํžˆ๋ ค ๋ˆˆ์— ๋„๊ณ , ์ธ๋ฑ์Šค ๊ณ„์‚ฐ์‹ ํ•œ ์ค„์ด ๊ตฌ์กฐ๋ฅผ ํ†ต์งธ๋กœ ์•Œ๋ ค ์ค€๋‹ค. ๊ฐ’์„ ์ง€ํ‚ค๊ณ  ์‹ถ์œผ๋ฉด ํ‘œ๋ฅผ ์ˆจ๊ธธ ๊ฒŒ ์•„๋‹ˆ๋ผ ์• ์ดˆ์— ํด๋ผ์ด์–ธํŠธ์— ๋‘์ง€ ์•Š์•„์•ผ ํ•œ๋‹ค.

์ด ๊ธ€์ด ๋„์›€์ด ๋๋‚˜์š”?

Comments

๋Œ“๊ธ€

0๊ฐœ

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

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

Related

๊ด€๋ จ ๊ธ€

3๊ฐœ
[๐Ÿฅ‰ Bronze 2] ๋ถ„๊ธฐ ๋ฏธ๋กœ ๋’ค์— ์ˆจ์€ ์ƒ์ˆ˜ ํ•œ ์ค„ โ€” DreamHack Labyrinth ํ’€์ด
blog

[๐Ÿฅ‰ Bronze 2] ๋ถ„๊ธฐ ๋ฏธ๋กœ ๋’ค์— ์ˆจ์€ ์ƒ์ˆ˜ ํ•œ ์ค„ โ€” DreamHack Labyrinth ํ’€์ด

14KB ์งœ๋ฆฌ stripped PIE ํ•˜๋‚˜๊ฐ€ ์ „๋ถ€์ธ ๋ฆฌ๋ฒ„์‹ฑ ๋ฌธ์ œ. ptrace ์•ˆํ‹ฐ๋””๋ฒ„๊น…๊ณผ ์‹œ๋“œ %7 ๋กœ ๊ฐˆ๋ผ์ง€๋Š” ๋ถ„๊ธฐ ๋ฏธ๋กœ๊ฐ€ ๊ฒน๊ฒน์ด ๊น”๋ ค ์žˆ์ง€๋งŒ, ์ •๋‹ต ์ž…๋ ฅ์€ .rodata ์˜ 32๋ฐ”์ดํŠธ๋ฅผ 0x30 ์œผ๋กœ XOR ํ•œ ๊ฒƒ์ด ์ „๋ถ€์˜€๋‹ค. flag ์ƒ์„ฑ๊ธฐ๊นŒ์ง€ ํŒŒ์ด์ฌ์œผ๋กœ ์žฌ๊ตฌํ˜„ํ•ด ๋ฐ”์ด๋„ˆ๋ฆฌ ์ถœ๋ ฅ๊ณผ ๋ฐ”์ดํŠธ ๋‹จ์œ„๋กœ ๋Œ€์กฐํ–ˆ๋‹ค.
#dreamhack#ctf#reversing+6
2026-08-20#dreamhack +5
[๐Ÿฅˆ Bronze 2] ๋ฏธ๋ผ์ธ ์ค„ ์•Œ์•˜๋˜ ๋””์ฝ”๋“œ๊ฐ€ ์‚ฌ์‹ค ์ •๋‹ต์ด์—ˆ๋‹ค โ€” DreamHack ์•„ ๋ฌธ์ œ ์ด๋ฆ„ ๋ญ˜๋กœํ•˜์ง€ ํ’€์ด
blog

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

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

[๐Ÿฅˆ Bronze 2] ๋‚œ๋…ํ™”๋œ ์ „์—ญ ๋ณ€์ˆ˜๋ฅผ GDB๋กœ ๊ทธ๋Œ€๋กœ ์ฝ์–ด๋‚ด๊ธฐ โ€” DreamHack Stop before stops! ํ’€์ด

C++ ๋ฐ”์ด๋„ˆ๋ฆฌ์ธ๋ฐ ํ•จ์ˆ˜ยท์ „์—ญ๋ณ€์ˆ˜ ์ด๋ฆ„์ด ์ „๋ถ€ ๋ฌด์ž‘์œ„ ๋ฌธ์ž์—ด๋กœ ๋ฐ”๋€Œ์–ด ์žˆ๋‹ค. ์ •์  ๋ถ„์„์œผ๋กœ ๋กœ์ง์€ ๋‹ค ์ฝํžˆ๋Š”๋ฐ(24์ž ๋น„๋ฐ€๋ฒˆํ˜ธ๋ฅผ ๋น„๊ตํ•ด ๋งž์œผ๋ฉด flag๋ฅผ ์ถœ๋ ฅ), ์‹ค์ œ ๋น„๊ต ๋Œ€์ƒ ๋ฌธ์ž์—ด์€ ์‹คํ–‰ ์‹œ์ ์— ์กฐ์šฉํžˆ ์ฑ„์›Œ์ง€๋Š” ์ „์—ญ std::string์ด๋ผ ์ •์  ๋””์Šค์–ด์…ˆ๋ธ”๋ฆฌ๋งŒ์œผ๋ก  ๊ฐ’์„ ์•Œ ์ˆ˜ ์—†๋‹ค. GDB๋กœ static initializer๊ฐ€ ๋๋‚œ ์งํ›„ raw ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์ฝ์–ด ๊ฐ’์„ ๊ทธ๋Œ€๋กœ ๊บผ๋ƒˆ๋‹ค.
#dreamhack#ctf#reversing+5
2026-07-19#dreamhack +5