[๐Ÿฅˆ Silver 2] ์‹œ๋ฆฌ์–ผ ๊ฒ€์ฆ ๋ฃจํ”„๋ฅผ ๊ฑฐ๊พธ๋กœ ๋Œ๋ฆฌ๊ธฐ โ€” DreamHack babycmp ํ’€์ด

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

[๐Ÿฅˆ Silver 2] ์‹œ๋ฆฌ์–ผ ๊ฒ€์ฆ ๋ฃจํ”„๋ฅผ ๊ฑฐ๊พธ๋กœ ๋Œ๋ฆฌ๊ธฐ โ€” DreamHack babycmp ํ’€์ด

SERIAL ํ•œ ์ค„๋งŒ ๋ฐ›๋Š” MFC ๋‹ค์ด์–ผ๋กœ๊ทธ ์•ฑ. ์ž…๋ ฅ 24๊ธ€์ž๋ฅผ int32 ๋ฐฐ์—ด๋กœ ๋ถ€ํ’€๋ฆฐ ๋’ค .data ์— ๋ฐ•์•„ ๋‘” ๊ฐ’ 24๊ฐœ์™€ ํ†ต์งธ๋กœ ๋น„๊ตํ•œ๋‹ค. ๋ณ€ํ™˜์ด ror32 โ†’ XOR โ†’ ADD โ†’ +30000 ๋„‰ ์ค„๋ฟ์ด๋ผ ์ž๋ฆฌ๋งˆ๋‹ค ํ›„๋ณด๊ฐ€ ํ•˜๋‚˜๋กœ ๋–จ์–ด์ง€๊ณ , ํ‚ค๋Š” .rdata ๊ฐ€ ์•„๋‹ˆ๋ผ ์ฝ”๋“œ ์ฆ‰์น˜๊ฐ’์œผ๋กœ ์ˆจ์–ด ์žˆ๋‹ค. ์—ญ์‚ฐ๋ณธ์€ ๋ฐ”์ด๋„ˆ๋ฆฌ์˜ ๋ฃจํ”„ ๊ธฐ๊ณ„์–ด๋ฅผ Unicorn ์œผ๋กœ ๊ทธ๋Œ€๋กœ ๋Œ๋ ค ๊ต์ฐจ๊ฒ€์ฆํ–ˆ๋‹ค.

๋ฌธ์ œ: DreamHack โ€” babycmp ๋ถ„๋ฅ˜: reversing ๋‚œ์ด๋„: ๐Ÿฅˆ Silver 2 FLAG: DH{y0u_4r3_cmp__ma5t3r!}

๋ฌธ์ œ ์„ค๋ช…์€ ํ•œ ์ค„์ด ์ „๋ถ€๋‹ค.

ํ”Œ๋ž˜๊ทธ๋ฅผ ์ฐพ์„ ์ˆ˜ ์žˆ๊ฒ ๋‚˜์š”?

๋ฐ›์€ ํŒŒ์ผ๋„ ํ•˜๋‚˜๋ฟ์ด๋‹ค. babycmp.exe, 102,912๋ฐ”์ดํŠธ. ์†Œ์Šค๋„ Dockerfile ๋„ ์—†๊ณ  ์„œ๋ฒ„๋„ ์—†๋‹ค. ์ „๋ถ€ ์ด ์•ˆ์— ๋“ค์–ด ์žˆ๋‹ค๋Š” ๋œป์ด๋‹ค.

file extracted/babycmp.exe && objdump -h extracted/babycmp.exe

objdump -h ๋กœ ํ™•์ธํ•œ babycmp.exe ์˜ ์„น์…˜ ํ‘œ. PE32+ GUI ์‹คํ–‰ํŒŒ์ผ์ด๊ณ  .text ๋Š” 0x2d5c ๋กœ ์ž‘์€๋ฐ ๋ฆฌ์†Œ์Šค ์„น์…˜ .rsrc ๊ฐ€ 0x115b0 ์œผ๋กœ ๊ฐ€์žฅ ํฌ๋‹ค
objdump -h ๋กœ ํ™•์ธํ•œ babycmp.exe ์˜ ์„น์…˜ ํ‘œ. PE32+ GUI ์‹คํ–‰ํŒŒ์ผ์ด๊ณ  .text ๋Š” 0x2d5c ๋กœ ์ž‘์€๋ฐ ๋ฆฌ์†Œ์Šค ์„น์…˜ .rsrc ๊ฐ€ 0x115b0 ์œผ๋กœ ๊ฐ€์žฅ ํฌ๋‹ค

PE32+, GUI ์„œ๋ธŒ์‹œ์Šคํ…œ, 6์„น์…˜. ๋ˆˆ์— ๋„๋Š” ๊ฑด ํฌ๊ธฐ ๋ฐฐ๋ถ„์ด๋‹ค. ์ฝ”๋“œ(.text)๋Š” 0x2d5c(11,612๋ฐ”์ดํŠธ) ๋ฐ–์— ์•ˆ ๋˜๋Š”๋ฐ ๋ฆฌ์†Œ์Šค(.rsrc)๊ฐ€ 0x115b0(70,576๋ฐ”์ดํŠธ)์œผ๋กœ ์—ฌ์„ฏ ๋ฐฐ๊ฐ€ ๋„˜๋Š”๋‹ค.

๋กœ์ง์ด ์ ๊ณ  ํ™”๋ฉด์ด ๋งŽ์€ ํ”„๋กœ๊ทธ๋žจ, ์ฆ‰ ๋‹ค์ด์–ผ๋กœ๊ทธ ํ•˜๋‚˜์งœ๋ฆฌ GUI ์•ฑ์ด๋‹ค. .data ๋„ 0x400 ์œผ๋กœ ์ž‘์•„์„œ, ๋ญ”๊ฐ€ ํ•˜๋“œ์ฝ”๋”ฉ๋œ ๊ฐ’์ด ์žˆ๋‹ค๋ฉด ๊ฑฐ๊ธฐ ๋‹ค ๋“ค์–ด๊ฐ„๋‹ค.


๋ฌธ์ œ ๊ฐœ์š”

ํ•ญ๋ชฉ๋‚ด์šฉ
๋ฌธ์ œ๋ช…babycmp
๋‚œ์ด๋„๐Ÿฅˆ Silver 2
๋ถ„๋ฅ˜reversing
์ œ๊ณต ํŒŒ์ผbabycmp.exe (PE32+ x86-64, GUI, 102,912๋ฐ”์ดํŠธ)
์ŠคํƒMSVC 2022 ยท MFC(mfc140u.dll) ๋‹ค์ด์–ผ๋กœ๊ทธ
ํ•ต์‹ฌ ์ทจ์•ฝ์  / ๊ธฐ๋ฒ•์ž…๋ ฅ์„ ์ƒ์ˆ˜์—ด๊ณผ ํ†ต์งธ๋กœ ๋น„๊ตํ•˜๋Š” ์‹œ๋ฆฌ์–ผ ๊ฒ€์ฆ์˜ ์—ญ์‚ฐ

ํ๋ฆ„์€ ์ด๋ ‡๋‹ค. ๋‹ค์ด์–ผ๋กœ๊ทธ์— SERIAL ์„ ๋„ฃ๊ณ  Check ๋ฅผ ๋ˆ„๋ฅด๋ฉด, ๊ธธ์ดยท์ ‘๋‘์‚ฌยท๋ ๊ธ€์ž๋ฅผ ๋จผ์ € ๋ณด๊ณ  ํ†ต๊ณผํ•œ ์ž…๋ ฅ์„ ํ•œ ๊ธ€์ž์”ฉ int32 ๋กœ ๋ถ€ํ’€๋ฆฐ๋‹ค. ๊ทธ 24๊ฐœ ๊ฐ’์„ .data ์— ๋ฐ•์•„ ๋‘” 24๊ฐœ์™€ ํ†ต์งธ๋กœ ๋น„๊ตํ•œ๋‹ค. ๋ณ€ํ™˜์ด ๋„‰ ์ค„๋ฟ์ด๋ผ ์ž๋ฆฌ๋งˆ๋‹ค ํ›„๋ณด๊ฐ€ ํ•˜๋‚˜๋กœ ๋–จ์–ด์ง„๋‹ค.



๐Ÿงฉ ๋ฐฐ๊ฒฝ โ€” MFC ๋‹ค์ด์–ผ๋กœ๊ทธ ์•ฑ์ด ๋‚จ๊ธฐ๋Š” ๊ฒƒ

MFC(Microsoft Foundation Classes)๋Š” Win32 API ๋ฅผ C++ ํด๋ž˜์Šค๋กœ ๊ฐ์‹ผ ์˜ค๋ž˜๋œ GUI ํ”„๋ ˆ์ž„์›Œํฌ๋‹ค. CDialog ๋ฅผ ์ƒ์†ํ•œ ํด๋ž˜์Šค ํ•˜๋‚˜์— ๋ฒ„ํŠผ ํ•ธ๋“ค๋Ÿฌ๋ฅผ ๋ถ™์ด๋ฉด ์ฐฝ ํ•˜๋‚˜์งœ๋ฆฌ ํ”„๋กœ๊ทธ๋žจ์ด ๋ฐ”๋กœ ๋‚˜์˜จ๋‹ค.

๋ฆฌ๋ฒ„์‹ฑ ์ชฝ์—์„œ MFC ๋ฐ”์ด๋„ˆ๋ฆฌ๊ฐ€ ํŽธํ•œ ์ด์œ ๊ฐ€ ๋‘˜ ์žˆ๋‹ค.

ํ•˜๋‚˜๋Š” ํ™”๋ฉด ๋ฌธ์ž์—ด์ด ๋ฆฌ์†Œ์Šค๋กœ ๋”ฐ๋กœ ๋น ์ง„๋‹ค๋Š” ๊ฒƒ. ๋‹ค์ด์–ผ๋กœ๊ทธ ํ…œํ”Œ๋ฆฟยท๋ผ๋ฒจยท๋ฉ”์‹œ์ง€๊ฐ€ .rsrc ์— UTF-16 ์œผ๋กœ ๋ชจ์—ฌ ์žˆ์–ด์„œ, ์ฝ”๋“œ๋ฅผ ์ฝ๊ธฐ ์ „์— ํ”„๋กœ๊ทธ๋žจ์ด ๋ฌด์Šจ ๋ง์„ ํ•˜๋Š”์ง€๋ถ€ํ„ฐ ์•Œ ์ˆ˜ ์žˆ๋‹ค.

๋‹ค๋ฅธ ํ•˜๋‚˜๋Š” ํ”„๋ ˆ์ž„์›Œํฌ ์ฝ”๋“œ๊ฐ€ DLL ๋กœ ๋น ์ง„๋‹ค๋Š” ๊ฒƒ. mfc140u.dll ์„ ์ž„ํฌํŠธ๋กœ ์“ฐ๊ธฐ ๋•Œ๋ฌธ์— .text ์— ๋‚จ๋Š” ๊ฑด ๋Œ€๋ถ€๋ถ„ ์ถœ์ œ์ž๊ฐ€ ์ง์ ‘ ์“ด ์ฝ”๋“œ๋‹ค. ์ •์  ๋งํฌ๋œ CRT ํ•จ์ˆ˜ ์ˆ˜์ฒœ ๊ฐœ ์‚ฌ์ด์—์„œ main ์„ ์ฐพ๋Š” ์ˆ˜๊ณ ๊ฐ€ ์—†๋‹ค.

๊ทธ๋ž˜์„œ ์ˆœ์„œ๋Š” ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ "๋ฌธ์ž์—ด โ†’ ์ž„ํฌํŠธ โ†’ ๊ทธ ์‚ฌ์ด์— ๋‚€ ์งง์€ ์ฝ”๋“œ"๊ฐ€ ๋œ๋‹ค.


๐Ÿ”ฌ ์ •์ฐฐ โ€” ํ”„๋กœ๊ทธ๋žจ์ด ํ•˜๋Š” ๋ง๋ถ€ํ„ฐ ์ฝ๋Š”๋‹ค

๋ฆฌ์†Œ์Šค ๋ฌธ์ž์—ด์€ UTF-16 ์ด๋ผ strings ์— -el ์„ ์ค˜์•ผ ๋‚˜์˜จ๋‹ค.

strings -n 4 -el extracted/babycmp.exe | grep -nE 'SERIAL|Check|GOT IT|Congra|failed|opps'

strings -el ์ถœ๋ ฅ์—์„œ GOT IT, Congraturations, failed, opps try again, SERIAL, Check ์—ฌ์„ฏ ์ค„์ด ๋ฆฌ์†Œ์Šค ์ˆœ์„œ๋Œ€๋กœ ์žกํžŒ ํ™”๋ฉด
strings -el ์ถœ๋ ฅ์—์„œ GOT IT, Congraturations, failed, opps try again, SERIAL, Check ์—ฌ์„ฏ ์ค„์ด ๋ฆฌ์†Œ์Šค ์ˆœ์„œ๋Œ€๋กœ ์žกํžŒ ํ™”๋ฉด

์—ฌ์„ฏ ์ค„๋กœ ํ”„๋กœ๊ทธ๋žจ์˜ ์ „๋ถ€๊ฐ€ ๋“œ๋Ÿฌ๋‚œ๋‹ค. SERIAL: ๋ผ๋ฒจ๊ณผ Check ๋ฒ„ํŠผ์ด ์žˆ๊ณ , ๊ฒฐ๊ณผ๋Š” Congraturations! ์•„๋‹ˆ๋ฉด opps! try again! ์ด๋‹ค. ์˜คํƒˆ์ž๊นŒ์ง€ ๊ทธ๋Œ€๋กœ๋‹ค.

์„ฑ๊ณต/์‹คํŒจ ๋ฌธ์ž์—ด์ด ๋ฆฌ์†Œ์Šค ์ธ๋ฑ์Šค 8~11 ์— ๋‚˜๋ž€ํžˆ ๋ถ™์–ด ์žˆ๋Š” ๊ฒƒ๋„ ํžŒํŠธ๋‹ค. ๋ถ„๊ธฐ๊ฐ€ ํ•˜๋‚˜๋ฟ์ด๋ผ๋Š” ๋œป์ด๋ผ, ๊ฒ€์‚ฌ ํ•จ์ˆ˜ ํ•˜๋‚˜๋งŒ ์ฐพ์œผ๋ฉด ๋œ๋‹ค.

๋‹ค์Œ์€ ์ž„ํฌํŠธ์™€ ๋นŒ๋“œ ํ”์ ์ด๋‹ค.

objdump -x extracted/babycmp.exe | grep 'DLL Name'; strings -n 8 extracted/babycmp.exe | grep -E 'neko_hat|[.]pdb'

objdump -x ์ž„ํฌํŠธ ๋ชฉ๋ก์— mfc140u.dll ์ด ๋งจ ์œ„๋กœ ์žกํžˆ๊ณ , ์•„๋ž˜ strings ๊ฒฐ๊ณผ์— neko_hat ๊ณผ PDB ๊ฒฝ๋กœ babycmp.pdb ๊ฐ€ ํ•จ๊ป˜ ๋‚˜์˜จ ํ™”๋ฉด
objdump -x ์ž„ํฌํŠธ ๋ชฉ๋ก์— mfc140u.dll ์ด ๋งจ ์œ„๋กœ ์žกํžˆ๊ณ , ์•„๋ž˜ strings ๊ฒฐ๊ณผ์— neko_hat ๊ณผ PDB ๊ฒฝ๋กœ babycmp.pdb ๊ฐ€ ํ•จ๊ป˜ ๋‚˜์˜จ ํ™”๋ฉด

mfc140u.dll ์ด ๋งจ ์•ž์ด๋‹ค. ์˜ˆ์ƒ๋Œ€๋กœ MFC ์•ฑ์ด๊ณ , ๋‚˜๋จธ์ง€๋Š” CRT ์™€ USER32ยทCOMCTL32 ๋ฟ์ด๋‹ค. PDB ๊ฒฝ๋กœ์— C:\Users\user\OneDrive\Desktop\babycmp\x64\Release\babycmp.pdb ๊ฐ€ ๋‚จ์•„ ์žˆ์–ด Release ๋นŒ๋“œ๋ผ๋Š” ๊ฒƒ๋„ ํ™•์ธ๋œ๋‹ค.

๊ทธ๋ฆฌ๊ณ  neko_hat. ๋ฌธ์ œ ์ถœ์ œ์ž ๋‹‰๋„ค์ž„๊ณผ ๊ฐ™์€ ๋ฌธ์ž์—ด์ด ๋ฐ”์ด๋„ˆ๋ฆฌ ์•ˆ์— ๋ฐ•ํ˜€ ์žˆ๋‹ค.

์—ฌ๊ธฐ์„œ ํ•œ ๊ฐ€์ง€ ์ฃผ์˜ํ•  ๊ฒŒ ์žˆ๋‹ค. ์ถœ๋ ฅ์ด neko_hat ์ด ์•„๋‹ˆ๋ผ neko_hatH ๋‹ค. ๋’ค์— ๋ถ™์€ H ๋Š” ๋ฌธ์ž์—ด์˜ ์ผ๋ถ€๊ฐ€ ์•„๋‹ˆ๋ผ ๋‹ค์Œ ๋ช…๋ น์˜ ์ฒซ ๋ฐ”์ดํŠธ(0x48)๋‹ค. .rdata ์— ๋„๋กœ ๋๋‚˜๋Š” ๋ฌธ์ž์—ด ์ƒ์ˆ˜๊ฐ€ ์•„๋‹ˆ๋ผ ์ฝ”๋“œ ํ•œ๊ฐ€์šด๋ฐ ๋ฐ•ํžŒ ์ฆ‰์น˜๊ฐ’์ด๋ผ๋Š” ์‹ ํ˜ธ๋‹ค.

์ด์ œ ์‹ค์ œ๋กœ ๋ญ๋ผ๋„ ๋„ฃ์–ด ๋ณธ๋‹ค. ๋ฆฌ๋ˆ…์Šค์—์„œ PE ๋ฅผ ๋Œ๋ฆฌ๋ ค๋ฉด wine ์ด ํ•„์š”ํ•˜๊ณ , MFC ์•ฑ์ด๋ผ mfc140u.dll ์ด ์žˆ๋Š” ํ”„๋ฆฌํ”ฝ์Šค๋ฅผ ๋”ฐ๋กœ ๋งŒ๋“ค์–ด์•ผ ํ•œ๋‹ค.

export WINEPREFIX="$HOME/.wine_babycmp" WINEDEBUG=-all
wineboot -i
winetricks -q -f vcrun2022

์ฐฝ์„ ๋„์šฐ๊ณ  ์ขŒํ‘œ๋ฅผ ์ฐ์–ด ์ž…๋ ฅํ•˜๋Š” ๋ถ€๋ถ„์€ ์Šคํฌ๋ฆฝํŠธ๋กœ ๋ฌถ์–ด ๋’€๋‹ค.

#!/usr/bin/env python3
"""babycmp.exe ๋ฅผ Xvfb ์œ„ wine ์œผ๋กœ ๋„์šฐ๊ณ  ์‹œ๋ฆฌ์–ผ์„ ์‹ค์ œ๋กœ ์ž…๋ ฅํ•ด ํ™”๋ฉด์„ ์ฐ๋Š”๋‹ค.
 
ํ•ฉ์„ฑ์ด ์•„๋‹ˆ๋ผ ์ง„์งœ ์•ฑ ํ™”๋ฉด์ด๋‹ค. xdotool ๋กœ ์ž…๋ ฅ์ฐฝ์„ ํด๋ฆญ โ†’ ์‹œ๋ฆฌ์–ผ ํƒ€์ดํ•‘ โ†’
Check ๋ฒ„ํŠผ ํด๋ฆญ๊นŒ์ง€ ์‹ค์ œ ๋งˆ์šฐ์Šค/ํ‚ค๋ณด๋“œ ์ด๋ฒคํŠธ๋ฅผ ๋„ฃ๋Š”๋‹ค.
 
    python3 gui_capture.py <์‹œ๋ฆฌ์–ผ> <์ถœ๋ ฅPNG> [--wrong]
 
WM ์ด ์—†์–ด ์ฐฝ์— ์ œ๋ชฉํ‘œ์‹œ์ค„์ด ์—†๋‹ค. ์ขŒํ‘œ๋Š” 1280x1040 ํ™”๋ฉด์— ๋‹ค์ด์–ผ๋กœ๊ทธ๊ฐ€
๊ฐ€์šด๋ฐ ๋œจ๋Š” ๊ฒƒ์„ ๊ธฐ์ค€์œผ๋กœ ์žก์•˜๊ณ , ์ฐ์€ ๋’ค ๊ฒ€์€ ๋ฐฐ๊ฒฝ์„ trim ํ•ด์„œ ์ž˜๋ผ๋‚ธ๋‹ค.
"""
import os
import shutil
import signal
import subprocess
import sys
import time
from pathlib import Path
 
HERE = Path(__file__).resolve().parent
EXE = HERE / "extracted" / "babycmp.exe"
PREFIX = Path.home() / ".wine_babycmp"
 
SCREEN = "1280x1040x24"
EDIT_XY = (630, 543)     # SERIAL ์ž…๋ ฅ์ฐฝ
CHECK_XY = (852, 543)    # Check ๋ฒ„ํŠผ
 
 
def free_display(start=141, end=180):
    for n in range(start, end):
        if not Path(f"/tmp/.X11-unix/X{n}").exists():
            return n
    raise RuntimeError("๋นˆ ๋””์Šคํ”Œ๋ ˆ์ด ์—†์Œ")
 
 
def sh(cmd, env, **kw):
    return subprocess.run(cmd, env=env, capture_output=True, text=True, **kw)
 
 
def main():
    if len(sys.argv) < 3:
        print(__doc__)
        return 2
    serial, out = sys.argv[1], Path(sys.argv[2])
    out.parent.mkdir(parents=True, exist_ok=True)
 
    disp = f":{free_display()}"
    env = dict(os.environ, DISPLAY=disp, WINEPREFIX=str(PREFIX), WINEDEBUG="-all")
 
    xvfb = subprocess.Popen(
        ["Xvfb", disp, "-screen", "0", SCREEN, "-nolisten", "tcp"],
        stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
    app = None
    try:
        time.sleep(3)
        app = subprocess.Popen(["wine", str(EXE)], env=env,
                               stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL,
                               preexec_fn=os.setsid)
        time.sleep(18)  # mfc140u.dll ๋กœ๋”ฉ์ด ๋А๋ฆฌ๋‹ค
 
        sh(["xdotool", "mousemove", *map(str, EDIT_XY), "click", "1"], env)
        time.sleep(0.6)
        sh(["xdotool", "type", "--delay", "40", serial], env)
        time.sleep(1.0)
 
        sh(["xdotool", "mousemove", *map(str, CHECK_XY), "click", "1"], env)
        time.sleep(2.5)
 
        raw = out.with_suffix(".raw.png")
        sh(["import", "-window", "root", str(raw)], env)
        subprocess.run(["convert", str(raw), "-bordercolor", "black", "-fuzz", "2%",
                        "-trim", "+repage", "-bordercolor", "#0d1117",
                        "-border", "28", str(out)], check=True)
        raw.unlink(missing_ok=True)
        print(f"SAVED: {out}")
    finally:
        if app is not None:
            try:
                os.killpg(os.getpgid(app.pid), signal.SIGKILL)
            except ProcessLookupError:
                pass
        # ์ด ํ”„๋ฆฌํ”ฝ์Šค ์ „์šฉ wineserver ๋งŒ ๋‚ด๋ฆฐ๋‹ค (๋‹ค๋ฅธ wine ์ž‘์—… ๋ณดํ˜ธ)
        if shutil.which("wineserver"):
            sh(["wineserver", "-k"], env)
        xvfb.terminate()
        xvfb.wait(timeout=10)
    return 0
 
 
if __name__ == "__main__":
    sys.exit(main())
python3 gui_capture.py 'DH{aaaaaaaaaaaaaaaaaaaa}' /home/jinho/homepage/public/images/blog/dreamhack-babycmp-writeup/04_gui_wrong.png

wine ์œผ๋กœ ๋„์šด babycmp ๋‹ค์ด์–ผ๋กœ๊ทธ. SERIAL ์นธ์— ์•„๋ฌด ๊ฐ’์ด๋‚˜ ๋„ฃ๊ณ  Check ๋ฅผ ๋ˆ„๋ฅด์ž opps try again ์ด ์ฃผํ™ฉ์ƒ‰์œผ๋กœ ๋œฌ ํ™”๋ฉด
wine ์œผ๋กœ ๋„์šด babycmp ๋‹ค์ด์–ผ๋กœ๊ทธ. SERIAL ์นธ์— ์•„๋ฌด ๊ฐ’์ด๋‚˜ ๋„ฃ๊ณ  Check ๋ฅผ ๋ˆ„๋ฅด์ž opps try again ์ด ์ฃผํ™ฉ์ƒ‰์œผ๋กœ ๋œฌ ํ™”๋ฉด

ํ™”๋ฉด์€ ์ •์งํ•˜๋‹ค. ๋ผ๋ฒจ ํ•˜๋‚˜, ์ž…๋ ฅ์นธ ํ•˜๋‚˜, ๋ฒ„ํŠผ ํ•˜๋‚˜. ํ‹€๋ฆฌ๋ฉด opps! try again!. ์ •๋‹ต ํ•˜๋‚˜๋ฅผ ๋งžํžˆ๋Š” ๊ฒƒ ๋ง๊ณ  ๋‹ค๋ฅธ ๊ธธ์€ ์—†๋‹ค๋Š” ๊ฒŒ ๋ˆˆ์œผ๋กœ ํ™•์ธ๋œ๋‹ค.



๐Ÿšง ๊ด€๋ฌธ โ€” ๊ฒ€์‚ฌ ํ•จ์ˆ˜๊ฐ€ ๋จผ์ € ๋ณด๋Š” ์„ธ ๊ฐ€์ง€

.text ๊ฐ€ 11KB ๋ฟ์ด๋ผ ๋””์Šค์–ด์…ˆ๋ธ”๋ฆฌ๋ฅผ ํ†ต์งธ๋กœ ํ›‘์–ด๋„ ๋ถ€๋‹ด์ด ์—†๋‹ค. 0x140001c30 ๋ถ€ํ„ฐ ์‹œ์ž‘ํ•˜๋Š” ํ•จ์ˆ˜ ํ•˜๋‚˜๊ฐ€ ๋ฌธ์ž์—ด ๊ฐ์ฒด๋ฅผ ๋ฐ›์•„ bool ์„ ๋Œ๋ ค์ฃผ๋Š” ๋ชจ์–‘์ธ๋ฐ, ๊ทธ ์•ˆ์ด ๊ณง ๊ฒ€์‚ฌ ๋ฃจํ‹ด์ด๋‹ค.

์ฃผ์„์€ sed ๊ทœ์น™ ํŒŒ์ผ๋กœ ์–น์—ˆ๋‹ค. --cmd ์•ˆ์— ์ธ๋ผ์ธ์œผ๋กœ sed 's|โ€ฆ|โ€ฆ|' ๋ฅผ ์“ฐ๋ฉด ๋”ฐ์˜ดํ‘œ๊ฐ€ ์…ธ์„ ์ง€๋‚˜๋ฉฐ ๊นจ์ ธ์„œ, ์น˜ํ™˜ ๊ทœ์น™์€ ํŒŒ์ผ์— ๋”ฐ๋กœ ๋‘”๋‹ค.

s|^   140001c9d:.*|&   <-- rcx+0x10 = std::string ์˜ size()|
s|^   140001ca1:.*|&   <-- ๊ธธ์ด๊ฐ€ 0x18(=24)์ด ์•„๋‹ˆ๋ฉด ๋ฐ”๋กœ ํƒˆ๋ฝ|
s|^   140001cd3:.*|&   <-- rbp+0xf ์— ๋งŒ๋“ค์–ด ๋‘” 3๊ธ€์ž ๋ฌธ์ž์—ด|
s|^   140001cdb:.*|&   <-- ์ ‘๋‘์‚ฌ๋ฅผ ํ•œ ๊ธ€์ž์”ฉ ๋Œ€์กฐ|
s|^   140001ced:.*|&   <-- r11 = 3, ์„ธ ๊ธ€์ž๋งŒ ๋ณธ๋‹ค|
s|^   140001d02:.*|&   <-- 24๋ฒˆ์งธ(0x17) ๊ธ€์ž๋Š” 0x7d = '}'|
objdump -d -M intel --start-address=0x140001c9d --stop-address=0x140001d08 extracted/babycmp.exe | sed -f gate.sed | tail -n +5

objdump ๋กœ ๋œฌ ๊ฒ€์‚ฌ ํ•จ์ˆ˜ ์•ž๋ถ€๋ถ„์— sed ์ฃผ์„์ด ๋ถ™์€ ํ™”๋ฉด. ๊ธธ์ด 0x18 ๋น„๊ต, ์ ‘๋‘์‚ฌ 3๊ธ€์ž ๋ฃจํ”„, ๋งˆ์ง€๋ง‰ ๊ธ€์ž 0x7d ๋น„๊ต๊ฐ€ ์ฐจ๋ก€๋กœ ๋ณด์ธ๋‹ค
objdump ๋กœ ๋œฌ ๊ฒ€์‚ฌ ํ•จ์ˆ˜ ์•ž๋ถ€๋ถ„์— sed ์ฃผ์„์ด ๋ถ™์€ ํ™”๋ฉด. ๊ธธ์ด 0x18 ๋น„๊ต, ์ ‘๋‘์‚ฌ 3๊ธ€์ž ๋ฃจํ”„, ๋งˆ์ง€๋ง‰ ๊ธ€์ž 0x7d ๋น„๊ต๊ฐ€ ์ฐจ๋ก€๋กœ ๋ณด์ธ๋‹ค

๊ด€๋ฌธ์ด ์…‹์ด๋‹ค.

๊ธธ์ด๋Š” ์ •ํ™•ํžˆ 24๋ฐ”์ดํŠธ. mov r15, [rcx+0x10] ๋กœ std::string::size() ๋ฅผ ์ฝ๊ณ  cmp r15, 0x18 ๋กœ ๋น„๊ตํ•œ๋‹ค. jne ๊ฐ€ ์•„๋‹ˆ๋ผ je ๋กœ ํ†ต๊ณผ ๊ฒฝ๋กœ๋ฅผ ์žก์•„ ๋†จ์„ ๋ฟ ์˜๋ฏธ๋Š” ๊ฐ™๋‹ค.

์•ž ์„ธ ๊ธ€์ž๋Š” ๊ณ ์ • ๋ฌธ์ž์—ด. rbp+0xf ์— ์„ธ ๊ธ€์ž์งœ๋ฆฌ ์ž„์‹œ ๋ฌธ์ž์—ด์„ ๋งŒ๋“ค์–ด ๋‘๊ณ  (r13=0xf ๊ฐ€ capacity, r11=3 ์ด size) ํ•œ ๊ธ€์ž์”ฉ cmp ํ•œ๋‹ค. ๊ทธ ์„ธ ๊ธ€์ž๋Š” .rdata 0x140004f50 ์—์„œ WORD ํ•˜๋‚˜ + BYTE ํ•˜๋‚˜๋กœ ๋ณต์‚ฌํ•ด ์˜ค๋Š”๋ฐ,

xxd -s 0x4150 -l 8 extracted/babycmp.exe

์ฝ์–ด ๋ณด๋ฉด 44 48 7b, ์ฆ‰ DH{ ๋‹ค. ํ”Œ๋ž˜๊ทธ ํ˜•์‹์ด ๊ณง ์‹œ๋ฆฌ์–ผ ํ˜•์‹์ด๋‹ค.

๋งˆ์ง€๋ง‰ ๊ธ€์ž๋Š” ๋‹ซ๋Š” ์ค‘๊ด„ํ˜ธ. cmp BYTE PTR [rax+0x17], 0x7d. 0x17 ์€ 23์ด๊ณ , 24๊ธ€์ž ๋ฌธ์ž์—ด์˜ ๋งˆ์ง€๋ง‰ ์ธ๋ฑ์Šค๋‹ค.

์—ฌ๊ธฐ๊นŒ์ง€๋กœ ํ˜•ํƒœ๊ฐ€ ์ •ํ•ด์ง„๋‹ค. DH{ + 20๊ธ€์ž + }. ๋‚จ์€ ๊ฑด ๊ฐ€์šด๋ฐ 20๊ธ€์ž๋‹ค.


๐Ÿ’ฃ ํ•ต์‹ฌ โ€” ํ•œ ๊ธ€์ž๋ฅผ int32 ๋กœ ๋ถ€ํ’€๋ฆฌ๋Š” ๋„‰ ์ค„

๊ด€๋ฌธ์„ ํ†ต๊ณผํ•˜๋ฉด 0x140001a10 ์ด ํ˜ธ์ถœ๋œ๋‹ค. ์ธ์ž๋Š” ์ž…๋ ฅ ๋ฌธ์ž์—ด, ๋ฐ˜ํ™˜์€ std::vector<int>. ๊ธ€์ž ์ˆ˜๋งŒํผ int32 ๋ฅผ ๋‹ด๋Š” ๋ฒกํ„ฐ๋ฅผ ๋งŒ๋“ค์–ด ๋Œ๋ ค์ฃผ๋Š” ํ•จ์ˆ˜๋‹ค.

s|^   140001af5:.*|&   <-- ํ‚ค "neko_hat" ์„ ์ฝ”๋“œ ์ฆ‰์น˜๊ฐ’์œผ๋กœ ์Šคํƒ์—|
s|^   140001b0b:.*|&   <-- i < size() ์ธ ๋™์•ˆ ๋ฐ˜๋ณต|
s|^   140001b34:.*|&   <-- v = (int8)serial[i]  ๋ถ€ํ˜ธํ™•์žฅ ์ฃผ์˜|
s|^   140001b44:.*|&   <-- v = ror32(v, 4)|
s|^   140001b52:.*|&   <-- eax = i % 8|
s|^   140001b67:.*|&   <-- v ^= key[i % 8]|
s|^   140001b73:.*|&   <-- eax = i % 4|
s|^   140001b89:.*|&   <-- v += key[i % 4]|
s|^   140001b8f:.*|&   <-- v += 0x7530 = 30000|
objdump -d -M intel --start-address=0x140001af5 --stop-address=0x140001ba9 extracted/babycmp.exe | sed -f loop.sed | tail -n +5

objdump ๋กœ ๋œฌ ๋ณ€ํ™˜ ๋ฃจํ”„ ์ „์ฒด์— sed ์ฃผ์„์ด ๋ถ™์€ ํ™”๋ฉด. movabs ๋กœ ํ‚ค๋ฅผ ์Šคํƒ์— ์˜ฌ๋ฆฌ๊ณ  ror, xor, add ๋‘ ๋ฒˆ์ด ์ˆœ์„œ๋Œ€๋กœ ์ด์–ด์ง„๋‹ค
objdump ๋กœ ๋œฌ ๋ณ€ํ™˜ ๋ฃจํ”„ ์ „์ฒด์— sed ์ฃผ์„์ด ๋ถ™์€ ํ™”๋ฉด. movabs ๋กœ ํ‚ค๋ฅผ ์Šคํƒ์— ์˜ฌ๋ฆฌ๊ณ  ror, xor, add ๋‘ ๋ฒˆ์ด ์ˆœ์„œ๋Œ€๋กœ ์ด์–ด์ง„๋‹ค

๋ฃจํ”„์— ๋“ค์–ด๊ฐ€๊ธฐ ์ „ ๋‘ ์ค„์ด ๋จผ์ € ๋ˆˆ์— ๋“ค์–ด์˜จ๋‹ค.

movabs rax, 0x7461685f6f6b656e   ; "neko_hat" ์„ ๋ฆฌํ‹€์—”๋””์–ธ 8๋ฐ”์ดํŠธ๋กœ
mov    QWORD PTR [rsp+0x38], rax
mov    BYTE PTR [rsp+0x40], 0    ; ๋„ ์ข…๋ฃŒ

ํ‚ค๋Š” .rdata ์— ์—†๋‹ค. movabs ์˜ ์ฆ‰์น˜๊ฐ’์œผ๋กœ ์ฝ”๋“œ์— ๋ฐ•ํ˜€ ์žˆ๋‹ค๊ฐ€ ์Šคํƒ์— ๋ณต์‚ฌ๋œ๋‹ค. ์•„๊นŒ strings ๊ฐ€ neko_hatH ๋กœ ๋ณด์—ฌ ์ค€ ์ด์œ ๊ฐ€ ์ด๊ฒƒ์ด๋‹ค. .rdata ๋งŒ ๋’ค์ง€๊ฑฐ๋‚˜, strings ๊ฒฐ๊ณผ๋ฅผ ๋ฌธ์ž์—ด ์ƒ์ˆ˜ ๋ชฉ๋ก์œผ๋กœ๋งŒ ์ฝ์œผ๋ฉด ์—ฌ๊ธฐ์„œ ํ•œ ๋ฒˆ ๋ง‰ํžŒ๋‹ค.

๋ฃจํ”„ ๋ณธ์ฒด๋Š” ๋„‰ ์ค„๋กœ ์š”์•ฝ๋œ๋‹ค.

for (int i = 0; i < s.size(); i++) {
    int v = (signed char)s[i];   // movsx โ€” ๋ถ€ํ˜ธํ™•์žฅ
    v = _rotr(v, 4);             // ror eax, 4
    v ^= key[i % 8];             // xor
    v += key[i % 4];             // add
    v += 30000;                  // add 0x7530
    out[i] = v;
}

i % 8 ๊ณผ i % 4 ๋Š” ์†Œ์Šค์— ๋‚˜๋จธ์ง€ ์—ฐ์‚ฐ์œผ๋กœ ์“ฐ์—ฌ ์žˆ์—ˆ์„ ํ…๋ฐ, ์ปดํŒŒ์ผ๋Ÿฌ๊ฐ€ and eax, 0x80000007 + ์Œ์ˆ˜ ๋ณด์ •(dec / or / inc)์œผ๋กœ ํŽผ์ณ ๋†จ๋‹ค. ์ž…๋ ฅ ์ธ๋ฑ์Šค๋Š” ํ•ญ์ƒ 0 ์ด์ƒ์ด๋ผ ๋ณด์ • ๊ฒฝ๋กœ๋Š” ์‹ค์ œ๋กœ ์•ˆ ํƒ„๋‹ค. ๊ทธ๋ƒฅ i % 8 ๋กœ ์ฝ์œผ๋ฉด ๋œ๋‹ค.

ํ•ต์‹ฌ์€ ror ๋‹ค. ์˜ค๋ฅธ์ชฝ์œผ๋กœ 4๋น„ํŠธ ๋Œ๋ฆฌ๋ฉด ์›๋ž˜ ๊ฐ’์˜ ํ•˜์œ„ ๋‹ˆ๋ธ”์ด ์ตœ์ƒ์œ„๋กœ ์˜ฌ๋ผ๊ฐ„๋‹ค. ๊ธ€์ž ํ•˜๋‚˜๊ฐ€ 0x00~0x7f ๋ฒ”์œ„๋ผ, ๊ฒฐ๊ณผ๋Š” ์ƒ์œ„ 4๋น„ํŠธ์— ๊ธ€์ž์˜ ํ•˜์œ„ ๋‹ˆ๋ธ”์ด ๋ฐ•ํžˆ๊ณ  ๋‚˜๋จธ์ง€๋Š” 30000 ๊ทผ์ฒ˜์˜ ์ž‘์€ ์ˆ˜๊ฐ€ ๋˜๋Š” ๋ชจ์–‘์ด ๋œ๋‹ค.

์‹œ๋ฆฌ์–ผ ์ฒซ ๊ธ€์ž D ๊ฐ€ movsx, ror, xor, add, add ๋ฅผ ๊ฑฐ์ณ .data ๊ธฐ๋Œ€๊ฐ’ 0x40007608 ์ด ๋˜๊ธฐ๊นŒ์ง€๋ฅผ ์ƒ์ž๋กœ ์ด์€ ํ๋ฆ„๋„
์‹œ๋ฆฌ์–ผ ์ฒซ ๊ธ€์ž D ๊ฐ€ movsx, ror, xor, add, add ๋ฅผ ๊ฑฐ์ณ .data ๊ธฐ๋Œ€๊ฐ’ 0x40007608 ์ด ๋˜๊ธฐ๊นŒ์ง€๋ฅผ ์ƒ์ž๋กœ ์ด์€ ํ๋ฆ„๋„

์ฒซ ๊ธ€์ž D(0x44)๋กœ ์†๊ณ„์‚ฐํ•ด ๋ณด๋ฉด 0x44 โ†’ 0x40000004 โ†’ 0x4000006a โ†’ 0x400000d8 โ†’ 0x40007608. ๋’ค์—์„œ ํ™•์ธํ•˜๊ฒ ์ง€๋งŒ ์ด ๊ฐ’์ด .data ์˜ 0๋ฒˆ์งธ ๊ธฐ๋Œ€๊ฐ’๊ณผ ์ •ํ™•ํžˆ ๊ฐ™๋‹ค.

์ด ๊ตฌ์กฐ ๋•Œ๋ฌธ์— ์ž๋ฆฌ๋งˆ๋‹ค ํ›„๋ณด๊ฐ€ ํ•˜๋‚˜๋กœ ๋–จ์–ด์ง„๋‹ค. ๊ฐ ์ž๋ฆฌ์˜ ๊ณ„์‚ฐ์ด ์•ž๋’ค ๊ธ€์ž์™€ ์ „ํ˜€ ์–ฝํžˆ์ง€ ์•Š์•„์„œ(๋ธ”๋ก ์ฒด์ด๋‹๋„, ๋ˆ„์  ์ƒํƒœ๋„ ์—†๋‹ค) ์ธ์‡„ ๊ฐ€๋Šฅํ•œ 95๊ธ€์ž๋ฅผ ํ•œ ๋ฒˆ์”ฉ ๋„ฃ์–ด ๋ณด๋ฉด ๋์ด๋‹ค.



๐Ÿงฎ ๊ธฐ๋Œ€๊ฐ’ 24๊ฐœ๋Š” .data ์— ๊ทธ๋Œ€๋กœ

๋ณ€ํ™˜์ด ๋๋‚˜๋ฉด ๊ฒฐ๊ณผ ๋ฒกํ„ฐ๋ฅผ ์ƒ์ˆ˜ ๋ฐฐ์—ด๊ณผ ๋น„๊ตํ•œ๋‹ค.

objdump -d -M intel --start-address=0x140001dc7 --stop-address=0x140001df6 extracted/babycmp.exe | tail -n +8; xxd -s 0x7050 -l 96 extracted/babycmp.exe

objdump ๋กœ ๋œฌ 8๋ฐ”์ดํŠธ ๋‹จ์œ„ ๋น„๊ต ๋ฃจํ”„์™€ xxd ๋กœ ๋ฝ‘์€ .data 0x7050 ๋ถ€ํ„ฐ 96๋ฐ”์ดํŠธ. ๊ฐ’๋งˆ๋‹ค ๋’ค์ชฝ์— 75 00 ๋˜๋Š” 76 00 ์ด ๋ฐ˜๋ณต๋œ๋‹ค
objdump ๋กœ ๋œฌ 8๋ฐ”์ดํŠธ ๋‹จ์œ„ ๋น„๊ต ๋ฃจํ”„์™€ xxd ๋กœ ๋ฝ‘์€ .data 0x7050 ๋ถ€ํ„ฐ 96๋ฐ”์ดํŠธ. ๊ฐ’๋งˆ๋‹ค ๋’ค์ชฝ์— 75 00 ๋˜๋Š” 76 00 ์ด ๋ฐ˜๋ณต๋œ๋‹ค

๋น„๊ต ๋ฃจํ”„๊ฐ€ ์žฌ๋ฏธ์žˆ๋‹ค. int ๋‹จ์œ„๊ฐ€ ์•„๋‹ˆ๋ผ QWORD ๋‹จ์œ„๋กœ 8๋ฐ”์ดํŠธ์”ฉ ํ›‘๋Š”๋‹ค.

lea rcx, [rip+0x6282]      ; 0x140008050  โ€” ๊ธฐ๋Œ€๊ฐ’ ๋ฐฐ์—ด ์‹œ์ž‘
mov r8,  [rbp-0x39]        ; ๋ฐฉ๊ธˆ ๋งŒ๋“  ๋ฒกํ„ฐ์˜ ๋ฐ์ดํ„ฐ ํฌ์ธํ„ฐ
mov rdx, r8
sub rdx, rcx               ; ๋‘ ๋ฐฐ์—ด์˜ ๊ฑฐ๋ฆฌ
lea r9,  [rip+0x62d1]      ; 0x1400080b0  โ€” ๊ธฐ๋Œ€๊ฐ’ ๋ฐฐ์—ด ๋
...
mov rax, [rcx]
cmp [rdx+rcx*1], rax       ; 8๋ฐ”์ดํŠธ์”ฉ ๋น„๊ต
jne <์‹คํŒจ>
add rcx, 8
cmp rcx, r9
jl  <๊ณ„์†>

0x1400080b0 - 0x140008050 = 0x60, 96๋ฐ”์ดํŠธ๋‹ค. int32 24๊ฐœ. ๊ธธ์ด ๊ฒ€์‚ฌ๊ฐ€ 24์˜€๋˜ ๊ฒƒ๊ณผ ์ •ํ™•ํžˆ ๋งž๋Š”๋‹ค.

xxd ๋กœ ๋ฝ‘์€ ๋ฐ”์ดํŠธ๋ฅผ ๋ณด๋ฉด ๊ทœ์น™์ด ๋ˆˆ์— ๋ˆ๋‹ค. 4๋ฐ”์ดํŠธ๋งˆ๋‹ค ์„ธ ๋ฒˆ์งธ ๋ฐ”์ดํŠธ๊ฐ€ 75 ๋˜๋Š” 76 ์ด๋‹ค. ๋ฆฌํ‹€์—”๋””์–ธ์ด๋‹ˆ ์ด๊ฒŒ 0x7530(30000) ๊ทผ์ฒ˜๋ผ๋Š” ๋œป์ด๊ณ , ๋งˆ์ง€๋ง‰ add ๊ฐ€ ๋‚จ๊ธด ์ž๊ตญ์ด๋‹ค. ์ƒ์œ„ ๋ฐ”์ดํŠธ๋Š” 40, 80, b0, 90, 00, 50โ€ฆ ์œผ๋กœ ํฉ์–ด์ง€๋Š”๋ฐ ์ด๊ฒŒ ror ์ด ์˜ฌ๋ ค ๋ณด๋‚ธ ๋‹ˆ๋ธ”์ด๋‹ค.

ํŒŒ์ผ ์˜คํ”„์…‹์€ .data ์˜ VMA 0x140008000 ์ด ํŒŒ์ผ 0x7000 ์— ๋†“์ด๋ฏ€๋กœ 0x7000 + 0x50 = 0x7050. ์œ„ ๋ช…๋ น์˜ -s 0x7050 ์ด ๊ทธ๋ ‡๊ฒŒ ๋‚˜์˜จ ๊ฐ’์ด๋‹ค.


๐ŸŽฏ ์—ญ์‚ฐ โ€” ์ž๋ฆฌ๋งˆ๋‹ค 95๊ธ€์ž๋ฅผ ๋„ฃ์–ด ๋ณธ๋‹ค

๋˜๋Œ๋ฆฌ๋Š” ํ•จ์ˆ˜๋ฅผ ๋”ฐ๋กœ ์œ ๋„ํ•  ํ•„์š”๊ฐ€ ์—†๋‹ค. ์ž๋ฆฌ ํ•˜๋‚˜์— ํ›„๋ณด๊ฐ€ 95๊ฐœ๋ฟ์ด๋‹ˆ ์ •๋ฐฉํ–ฅ์œผ๋กœ ๊ณ„์‚ฐํ•ด์„œ ๋งž๋Š” ๊ฒƒ์„ ๊ณ ๋ฅด๋ฉด ๋œ๋‹ค. ํ›„๋ณด๊ฐ€ ์ •ํ™•ํžˆ ํ•˜๋‚˜์”ฉ ๋‚˜์˜ค๋Š”์ง€๋„ ๊ฐ™์ด ํ™•์ธํ•œ๋‹ค.

์ฃผ์†Œยทํ‚คยท๊ธฐ๋Œ€๊ฐ’์€ ์ „๋ถ€ ๋ฐ”์ด๋„ˆ๋ฆฌ์—์„œ ์ง์ ‘ ์ฝ๋Š”๋‹ค. ํ•˜๋“œ์ฝ”๋”ฉํ•œ ์ƒ์ˆ˜๋ฅผ ๋‘๋ฉด "์ด ๊ฐ’์ด ์–ด๋””์„œ ์™”๋‚˜"๊ฐ€ ๊ธ€ ๋ฐ–์œผ๋กœ ์ƒˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

#!/usr/bin/env python3
"""babycmp (DreamHack, Silver 2, reversing) โ€” solver
 
babycmp.exe ์˜ ๊ฒ€์ฆ ๋ฃจํ‹ด์„ ๊ทธ๋Œ€๋กœ ๋‹ค์‹œ ๊ตฌํ˜„ํ•˜๊ณ , ๋ฐ”์ด๋„ˆ๋ฆฌ์—์„œ ๋ฝ‘์€
๊ธฐ๋Œ€๊ฐ’ ๋ฐฐ์—ด๊ณผ ๋งž๋Š” ๋ฌธ์ž๋ฅผ ์ž๋ฆฌ๋งˆ๋‹ค ์ฐพ์•„ ์‹œ๋ฆฌ์–ผ(=ํ”Œ๋ž˜๊ทธ)์„ ๋ณต์›ํ•œ๋‹ค.
 
๊ฒ€์ฆ ๋ฃจํ‹ด (0x140001a10, 0x140001c30):
    if (len(s) != 0x18) return false
    if (s[0:3] != "DH{") return false
    if (s[0x17] != '}')   return false
    for i in range(len(s)):
        v  = (int32)(int8)s[i]
        v  = ror32(v, 4)
        v ^= key[i % 8]          # key = "neko_hat"
        v += key[i % 4]
        v += 30000               # 0x7530
        if v != expected[i]: return false
 
๊ธฐ๋Œ€๊ฐ’ 24๊ฐœ๋Š” .data 0x140008050 ์—, ์ ‘๋‘์‚ฌ "DH{" ๋Š” .rdata 0x140004f50 ์— ์žˆ๋‹ค.
๋ฐ”์ด๋„ˆ๋ฆฌ์—์„œ ์ง์ ‘ ์ฝ์œผ๋ฏ€๋กœ ํ•˜๋“œ์ฝ”๋”ฉํ•œ ๊ฐ’์ด ์—†๋‹ค.
"""
import struct
import sys
from pathlib import Path
 
EXE = Path(__file__).with_name("extracted") / "babycmp.exe"
 
# objdump -h babycmp.exe ๋กœ ์–ป์€ (์„น์…˜, VMA, ํŒŒ์ผ์˜คํ”„์…‹, ํฌ๊ธฐ)
SECTIONS = [
    (".text", 0x140001000, 0x00400, 0x2D5C),
    (".rdata", 0x140004000, 0x03200, 0x3D84),
    (".data", 0x140008000, 0x07000, 0x0400),
]
 
KEY = b"neko_hat"          # movabs rax, 0x7461685f6f6b656e @ 0x140001af5
EXPECTED_RVA = 0x140008050  # lea rcx,[rip+0x6282]
EXPECTED_END = 0x1400080B0  # lea r9,[rip+0x62d1]
PREFIX_RVA = 0x140004F50    # movzx eax,WORD PTR [rip+0x32c5]
SERIAL_LEN = 0x18           # cmp r15,0x18
 
 
def rva_to_offset(rva: int) -> int:
    for _name, vma, off, size in SECTIONS:
        if vma <= rva < vma + size:
            return off + (rva - vma)
    raise ValueError(f"RVA {rva:#x} ๊ฐ€ ์–ด๋А ์„น์…˜์—๋„ ์—†๋‹ค")
 
 
def ror32(value: int, count: int) -> int:
    value &= 0xFFFFFFFF
    count &= 31
    return ((value >> count) | (value << (32 - count))) & 0xFFFFFFFF
 
 
def transform(ch: int, i: int) -> int:
    """๊ฒ€์ฆ ๋ฃจํ‹ด ํ•œ ๋ฌธ์ž๋ถ„. ์ž…๋ ฅ์€ movsx ๋กœ ๋ถ€ํ˜ธํ™•์žฅ๋œ int32 ๋กœ ๋‹ค๋ค„์ง„๋‹ค."""
    v = ch - 0x100 if ch >= 0x80 else ch      # movsx eax, byte
    v = ror32(v, 4)
    v ^= KEY[i % 8]
    v = (v + KEY[i % 4]) & 0xFFFFFFFF
    v = (v + 30000) & 0xFFFFFFFF
    return v
 
 
def main() -> int:
    blob = EXE.read_bytes()
 
    off = rva_to_offset(PREFIX_RVA)
    prefix = blob[off:off + 3]
 
    off = rva_to_offset(EXPECTED_RVA)
    count = (EXPECTED_END - EXPECTED_RVA) // 4
    expected = struct.unpack(f"<{count}I", blob[off:off + count * 4])
 
    print(f"[*] ์ ‘๋‘์‚ฌ      : {prefix.decode()}")
    print(f"[*] ์‹œ๋ฆฌ์–ผ ๊ธธ์ด : {SERIAL_LEN}")
    print(f"[*] ๊ธฐ๋Œ€๊ฐ’ ๊ฐœ์ˆ˜ : {count}")
 
    serial = bytearray()
    for i, target in enumerate(expected):
        hits = [c for c in range(0x20, 0x7F) if transform(c, i) == target]
        if len(hits) != 1:
            print(f"[!] index {i}: ํ›„๋ณด {len(hits)}๊ฐœ {hits} โ€” ์ค‘๋‹จ")
            return 1
        serial.append(hits[0])
 
    flag = serial.decode()
    print(f"[*] ๋ณต์›๋œ ์‹œ๋ฆฌ์–ผ: {flag}")
 
    ok = (
        len(serial) == SERIAL_LEN
        and serial[:3] == prefix
        and serial[SERIAL_LEN - 1] == ord("}")
        and all(transform(c, i) == expected[i] for i, c in enumerate(serial))
    )
    print(f"[*] ์ž์ฒด ๊ฒ€์ฆ    : {'PASS' if ok else 'FAIL'}")
    print()
    print(f"FLAG: {flag}")
    return 0 if ok else 1
 
 
if __name__ == "__main__":
    sys.exit(main())
python3 solve.py

solve.py ์‹คํ–‰ ๊ฒฐ๊ณผ. ์ ‘๋‘์‚ฌ DH ์ค‘๊ด„ํ˜ธ์™€ ๊ธธ์ด 24, ๊ธฐ๋Œ€๊ฐ’ 24๊ฐœ๋ฅผ ์ฝ์€ ๋’ค ๋ณต์›๋œ ์‹œ๋ฆฌ์–ผ๊ณผ ์ž์ฒด ๊ฒ€์ฆ PASS, ๋งˆ์ง€๋ง‰ ์ค„์— ํ”Œ๋ž˜๊ทธ๊ฐ€ ์ฐํ˜”๋‹ค
solve.py ์‹คํ–‰ ๊ฒฐ๊ณผ. ์ ‘๋‘์‚ฌ DH ์ค‘๊ด„ํ˜ธ์™€ ๊ธธ์ด 24, ๊ธฐ๋Œ€๊ฐ’ 24๊ฐœ๋ฅผ ์ฝ์€ ๋’ค ๋ณต์›๋œ ์‹œ๋ฆฌ์–ผ๊ณผ ์ž์ฒด ๊ฒ€์ฆ PASS, ๋งˆ์ง€๋ง‰ ์ค„์— ํ”Œ๋ž˜๊ทธ๊ฐ€ ์ฐํ˜”๋‹ค

24์ž๋ฆฌ ๋ชจ๋‘ ํ›„๋ณด๊ฐ€ ์ •ํ™•ํžˆ ํ•˜๋‚˜์”ฉ ๋‚˜์™”๋‹ค. len(hits) != 1 ์—์„œ ํ•œ ๋ฒˆ๋„ ์•ˆ ๊ฑธ๋ ธ๋‹ค๋Š” ๋œป์ด๋ผ ํ”Œ๋ž˜๊ทธ๊ฐ€ ์œ ์ผํ•ด๋ผ๋Š” ๊ฒƒ๋„ ๊ฐ™์ด ์ฆ๋ช…๋œ๋‹ค.



๐Ÿ” ๊ฒ€์ฆ โ€” ๋ฐ”์ด๋„ˆ๋ฆฌ์˜ ๊ธฐ๊ณ„์–ด๋ฅผ ๊ทธ๋Œ€๋กœ ๋Œ๋ ค ๋ณธ๋‹ค

์—ฌ๊ธฐ์„œ ๋ฉˆ์ถ”๋ฉด ์ฐœ์ฐœํ•˜๋‹ค. ์œ„ ํŒŒ์ด์ฌ์€ ์–ด๋””๊นŒ์ง€๋‚˜ ๋‚ด๊ฐ€ ์–ด์…ˆ๋ธ”๋ฆฌ๋ฅผ ์ฝ๊ณ  ์†์œผ๋กœ ์˜ฎ๊ธด ๊ฒƒ์ด๋‹ค. ror ์„ rol ๋กœ ์ฝ์—ˆ๊ฑฐ๋‚˜, movsx ๋ฅผ movzx ๋กœ ๋ดค๊ฑฐ๋‚˜, XOR ๊ณผ ADD ์˜ ์ˆœ์„œ๋ฅผ ๋ฐ”๊ฟจ๋‹ค๋ฉด ๊ฐ’์ด ์•ˆ ๋งž์•„์„œ ๋ฐ”๋กœ ํ‹ฐ๊ฐ€ ๋‚˜๊ฒ ์ง€๋งŒ, ๋ฐ˜๋Œ€๋กœ ์šฐ์—ฐํžˆ ๋งž์•„๋–จ์–ด์ง€๋Š” ์‹ค์ˆ˜๋„ ์žˆ์„ ์ˆ˜ ์žˆ๋‹ค.

๊ทธ๋ž˜์„œ ๋ฐ”์ด๋„ˆ๋ฆฌ์—์„œ .text ๋ฅผ ๋– ๋‹ค๊ฐ€ ๊ทธ ๋ฃจํ”„๋ฅผ Unicorn ์œผ๋กœ ๊ทธ๋Œ€๋กœ ์‹คํ–‰ํ–ˆ๋‹ค. ์ง์ ‘ ์ง  ์ฝ”๋“œ๊ฐ€ ์•„๋‹ˆ๋ผ ์ถœ์ œ์ž๊ฐ€ ์ปดํŒŒ์ผํ•œ ๊ธฐ๊ณ„์–ด๊ฐ€ ๋„๋Š” ๊ฒƒ์ด๋ผ, ์ฝ๊ธฐ ์‹ค์ˆ˜๊ฐ€ ์žˆ์œผ๋ฉด ์—ฌ๊ธฐ์„œ ๊ฐˆ๋ฆฐ๋‹ค.

๋ฃจํ”„๊ฐ€ ์ฐธ์กฐํ•˜๋Š” ๊ฑด ์…‹๋ฟ์ด๋‹ค. rdi ์˜ std::string, rsi ์˜ std::vector, ๊ทธ๋ฆฌ๊ณ  rsp+0x38 ์˜ ํ‚ค. ์ด ์…‹๋งŒ ๋ฉ”๋ชจ๋ฆฌ์— ๋งŒ๋“ค์–ด ์ฃผ๋ฉด 0x140001b09 ๋ถ€ํ„ฐ 0x140001ba9 ๊นŒ์ง€ ๊ทธ๋Œ€๋กœ ๋Œ๋ฆด ์ˆ˜ ์žˆ๋‹ค.

โ–ถ๐Ÿ› ์‚ฝ์งˆ โ€” std::string ์„ SSO ๋กœ ์žก์•˜๋‹ค๊ฐ€ 16๊ธ€์ž๊นŒ์ง€๋งŒ ๋งž์•˜๋‹ค

์ฒซ ํŒ์€ capacity ๋ฅผ 0x0f ๋กœ ์คฌ๋‹ค. MSVC ์˜ std::string ์€ ์งง์€ ๋ฌธ์ž์—ด์„ ํž™ ๋Œ€์‹  ๊ฐ์ฒด ์•ˆ์— ๊ทธ๋Œ€๋กœ ๋‹ด๋Š”๋ฐ(SSO), ๋ฃจํ”„๋„ cmp QWORD PTR [rdi+0x18], 0x10 ๋กœ ๊ทธ ๋ถ„๊ธฐ๋ฅผ ํƒ„๋‹ค. 0x10 ๋ฏธ๋งŒ์ด๋ฉด r8 = rdi, ์ฆ‰ ๊ฐ์ฒด ์ž์‹ ์ด ๋ฌธ์ž ๋ฒ„ํผ๋‹ค.

๋ฌธ์ œ๋Š” ๊ฐ™์€ ๊ฐ์ฒด์˜ +0x10 ์— size ๋ฅผ ์จ ๋„ฃ์–ด์•ผ ํ•œ๋‹ค๋Š” ๊ฒƒ์ด๋‹ค. ๋ฌธ์ž ๋ฒ„ํผ๊ฐ€ ๊ฐ์ฒด ์‹œ์ž‘๋ถ€ํ„ฐ ๊น”๋ฆฌ๋‹ˆ 17๋ฒˆ์งธ ๊ธ€์ž(์ธ๋ฑ์Šค 16)๊ฐ€ size ํ•„๋“œ์— ๊ทธ๋Œ€๋กœ ๋ฎ์ธ๋‹ค.

    # โ˜… ์—ฌ๊ธฐ๊ฐ€ ํ‹€๋ ธ๋‹ค โ€” capacity 0x0f ๋Š” SSO ๊ฒฝ๋กœ๋ผ rdi ๊ฐ€ ๊ณง ๋ฌธ์ž ๋ฒ„ํผ๋‹ค.
    #    ๋ฐ”๋กœ ์•„๋ž˜ size ๋ฅผ rdi+0x10 ์— ์“ฐ๋Š” ์ˆœ๊ฐ„ 17๋ฒˆ์งธ ๊ธ€์ž๊ฐ€ ๋‚ ์•„๊ฐ„๋‹ค.
    uc.mem_write(STR_OBJ, serial)
    uc.mem_write(STR_OBJ + 0x10, struct.pack("<Q", len(serial)))
    uc.mem_write(STR_OBJ + 0x18, struct.pack("<Q", 0x0F))
python3 emulate_sso.py 'DH{y0u_4r3_cmp__ma5t3r!}'

emulate_sso.py ์‹คํ–‰ ๊ฒฐ๊ณผ. ์ธ๋ฑ์Šค 0๋ถ€ํ„ฐ 15๊นŒ์ง€๋Š” ์ผ์น˜ ํ‘œ์‹œ O ๊ฐ€ ๋ถ™์ง€๋งŒ 16๋ฒˆ๋ถ€ํ„ฐ X ๋กœ ๋ฐ”๋€Œ๊ณ  ๋งˆ์ง€๋ง‰์— MISMATCH ๊ฐ€ ์ฐํ˜”๋‹ค
emulate_sso.py ์‹คํ–‰ ๊ฒฐ๊ณผ. ์ธ๋ฑ์Šค 0๋ถ€ํ„ฐ 15๊นŒ์ง€๋Š” ์ผ์น˜ ํ‘œ์‹œ O ๊ฐ€ ๋ถ™์ง€๋งŒ 16๋ฒˆ๋ถ€ํ„ฐ X ๋กœ ๋ฐ”๋€Œ๊ณ  ๋งˆ์ง€๋ง‰์— MISMATCH ๊ฐ€ ์ฐํ˜”๋‹ค

์ฆ์ƒ์ด ์•„์ฃผ ์–Œ์ „ํ•ด์„œ ์˜คํžˆ๋ ค ํ—ท๊ฐˆ๋ ธ๋‹ค. ์•ž 16๊ฐœ๊ฐ€ ๋”ฑ ๋งž์œผ๋‹ˆ ๋ณ€ํ™˜์‹์€ ๋งž์€ ๊ฒƒ ๊ฐ™์€๋ฐ ๋’ค๋งŒ ํ‹€๋ฆฌ๋‹ˆ, ์ฒ˜์Œ์—” i % 8 ์ฃผ๊ธฐ๋‚˜ ๋ถ€ํ˜ธํ™•์žฅ ์ชฝ์„ ์˜์‹ฌํ–ˆ๋‹ค.

์‹ค์ œ๋กœ๋Š” ๋ณ€ํ™˜์‹์ด ์•„๋‹ˆ๋ผ ๋‚ด๊ฐ€ ๋งŒ๋“  ๊ฐ€์งœ ๊ฐ์ฒด์˜ ๋ ˆ์ด์•„์›ƒ์ด ํ‹€๋ฆฐ ๊ฒƒ์ด์—ˆ๋‹ค. ์ธ๋ฑ์Šค 16์˜ ๊ฒฐ๊ณผ๋ฅผ ์—ญ์œผ๋กœ ํ’€๋ฉด ๊ธ€์ž๊ฐ€ 0x18(=24), ์ฆ‰ size ๊ฐ’์ด๊ณ  17๋ฒˆ๋ถ€ํ„ฐ๋Š” ์ „๋ถ€ 0x00 ์ด์—ˆ๋‹ค. ๊ฐ’์ด "์ด์ƒํ•œ ๊ฐ’"์ด ์•„๋‹ˆ๋ผ "๋‚ด๊ฐ€ ๋ฐฉ๊ธˆ ์จ ๋„ฃ์€ ๊ฐ’"์ด๋ฉด ์ฝ๊ธฐ๊ฐ€ ํ‹€๋ฆฐ ๊ฒŒ ์•„๋‹ˆ๋ผ ์„ธํŒ…์ด ํ‹€๋ฆฐ ๊ฒƒ์ด๋‹ค.

24๊ธ€์ž๋Š” ์‹ค์ œ๋กœ๋„ ํž™์— ์žกํžˆ๋ฏ€๋กœ capacity ๋ฅผ 0x1f ๋กœ ์˜ฌ๋ฆฌ๊ณ  ๋ฐ์ดํ„ฐ ํฌ์ธํ„ฐ๋ฅผ ๋”ฐ๋กœ ๋‘๋‹ˆ ๊ทธ๋Œ€๋กœ ๋งž์•˜๋‹ค. ๋งˆ์ง€๋ง‰ ํ”„๋กฌํ”„ํŠธ์˜ ๋ถ‰์€ ํ‘œ์‹œ๋Š” ์Šคํฌ๋ฆฝํŠธ๊ฐ€ ๋ถˆ์ผ์น˜์ผ ๋•Œ 1๋กœ ๋๋‚˜๊ฒŒ ํ•ด ๋‘” ๊ฒƒ์ด๋ผ ์ •์ƒ์ด๋‹ค.

๊ณ ์นœ ํŒ์€ ์ด๋ ‡๋‹ค.

#!/usr/bin/env python3
"""babycmp.exe ์˜ ๋ณ€ํ™˜ ๋ฃจํ”„๋ฅผ Unicorn ์œผ๋กœ '๊ทธ๋Œ€๋กœ' ๋Œ๋ ค ๋ณธ๋‹ค.
 
์†์œผ๋กœ ์˜ฎ๊ฒจ ์ ์€ ํŒŒ์ด์ฌ ์žฌ๊ตฌํ˜„(solve.py)์ด ๋งž๋Š”์ง€ ํ™•์ธํ•˜๋Š” ์šฉ๋„๋‹ค.
์ง์ ‘ ์ง  ์ฝ”๋“œ๊ฐ€ ์•„๋‹ˆ๋ผ ๋ฐ”์ด๋„ˆ๋ฆฌ์—์„œ ๋– ๋‚ธ .text ๋ฐ”์ดํŠธ๋ฅผ ๊ทธ๋Œ€๋กœ ์‹คํ–‰ํ•˜๋ฏ€๋กœ,
ror/xor/add ์ˆœ์„œ๋‚˜ ๋ถ€ํ˜ธํ™•์žฅ์„ ์ž˜๋ชป ์ฝ์—ˆ์œผ๋ฉด ์—ฌ๊ธฐ์„œ ๊ฐ’์ด ์–ด๊ธ‹๋‚œ๋‹ค.
 
    python3 emulate.py 'DH{y0u_4r3_cmp__ma5t3r!}'
 
๋ฃจํ”„ ๊ตฌ๊ฐ„์€ 0x140001b09(์ดˆ๊ธฐ ๊ฒฝ๊ณ„๊ฒ€์‚ฌ) ~ 0x140001ba9(๋ฃจํ”„ ํƒˆ์ถœ ์งํ›„).
๋ฃจํ”„๊ฐ€ ์ฐธ์กฐํ•˜๋Š” ๊ฒƒ์€ ์…‹๋ฟ์ด๋ผ ๊ทธ ์…‹๋งŒ ๋งŒ๋“ค์–ด ์ฃผ๋ฉด ๋œ๋‹ค.
  rdi : std::string  โ€” [rdi+0x10]=size, [rdi+0x18]=capacity, [rdi]=ํž™ ๋ฐ์ดํ„ฐ ํฌ์ธํ„ฐ
  rsi : std::vector  โ€” [rsi]=int32 ๋ฐฐ์—ด ์‹œ์ž‘ ํฌ์ธํ„ฐ
  rsp+0x38 : ํ‚ค 8๋ฐ”์ดํŠธ "neko_hat"
 
capacity ๋ฅผ 0x10 ๋ฏธ๋งŒ์œผ๋กœ ์ฃผ๋ฉด MSVC ์˜ SSO ๊ทœ์•ฝ๋Œ€๋กœ rdi ์ž์ฒด๋ฅผ ๋ฌธ์ž ๋ฒ„ํผ๋กœ ์ฝ๋Š”๋ฐ,
๊ทธ๋Ÿฌ๋ฉด ์˜คํ”„์…‹ 0x10 ์˜ size ํ•„๋“œ๊ฐ€ 17๋ฒˆ์งธ ๋ฌธ์ž์™€ ๊ฒน์ณ 16๋ฐ”์ดํŠธ๊นŒ์ง€๋งŒ ๋งž๋Š”๋‹ค.
24๊ธ€์ž ์‹œ๋ฆฌ์–ผ์€ ์‹ค์ œ๋กœ๋„ ํž™์— ์žกํžˆ๋ฏ€๋กœ capacity ๋ฅผ 0x1f ๋กœ ๋‘”๋‹ค.
"""
import struct
import sys
from pathlib import Path
 
from unicorn import Uc, UC_ARCH_X86, UC_MODE_64
from unicorn.x86_const import (UC_X86_REG_RSP, UC_X86_REG_RBP, UC_X86_REG_RSI,
                               UC_X86_REG_RDI)
 
HERE = Path(__file__).resolve().parent
EXE = HERE / "extracted" / "babycmp.exe"
 
IMAGE_BASE = 0x140000000
SECTIONS = [(".text", 0x140001000, 0x00400, 0x2D5C),
            (".rdata", 0x140004000, 0x03200, 0x3D84),
            (".data", 0x140008000, 0x07000, 0x0400)]
 
LOOP_START = 0x140001B09
LOOP_END = 0x140001BA9
KEY_RVA = 0x140001AF5      # movabs rax, <key> โ€” ์ฆ‰์น˜๊ฐ’์—์„œ ํ‚ค๋ฅผ ์ง์ ‘ ๋ฝ‘๋Š”๋‹ค
EXPECTED_RVA = 0x140008050
EXPECTED_END = 0x1400080B0
 
STACK = 0x00200000
HEAP = 0x00300000
STR_OBJ = HEAP + 0x000     # std::string
STR_DAT = HEAP + 0x080     # ๊ทธ ๋ฌธ์ž์—ด์ด ๊ฐ€๋ฆฌํ‚ค๋Š” ํž™ ๋ฒ„ํผ
VEC_OBJ = HEAP + 0x100     # std::vector
OUT_BUF = HEAP + 0x200     # int32 ๊ฒฐ๊ณผ ๋ฐฐ์—ด
 
 
def main() -> int:
    serial = (sys.argv[1] if len(sys.argv) > 1 else "DH{y0u_4r3_cmp__ma5t3r!}").encode()
    blob = EXE.read_bytes()
 
    uc = Uc(UC_ARCH_X86, UC_MODE_64)
    uc.mem_map(IMAGE_BASE, 0x20000)
    uc.mem_map(STACK, 0x10000)
    uc.mem_map(HEAP, 0x10000)
    for _name, vma, off, size in SECTIONS:
        uc.mem_write(vma, blob[off:off + size])
 
    # ํ‚ค๋Š” ์ฝ”๋“œ ์•ˆ movabs ์ฆ‰์น˜๊ฐ’(0x48 0xB8 + imm64)์—์„œ ์ฝ๋Š”๋‹ค
    key = uc.mem_read(KEY_RVA + 2, 8)
    print(f"[*] ์ฝ”๋“œ์—์„œ ๋ฝ‘์€ ํ‚ค : {bytes(key).decode()}  (movabs @ {KEY_RVA:#x})")
 
    # std::string โ€” capacity >= 0x10 ์ด๋ผ ๋ฃจํ”„๊ฐ€ [rdi] ์˜ ํž™ ํฌ์ธํ„ฐ๋ฅผ ๋”ฐ๋ผ๊ฐ„๋‹ค
    uc.mem_write(STR_DAT, serial)
    uc.mem_write(STR_OBJ, struct.pack("<Q", STR_DAT))
    uc.mem_write(STR_OBJ + 0x10, struct.pack("<Q", len(serial)))
    uc.mem_write(STR_OBJ + 0x18, struct.pack("<Q", 0x1F))
    # std::vector โ€” ๋ฐ์ดํ„ฐ ํฌ์ธํ„ฐ๋งŒ ์žˆ์œผ๋ฉด ๋œ๋‹ค
    uc.mem_write(VEC_OBJ, struct.pack("<Q", OUT_BUF))
 
    rsp = STACK + 0x8000
    uc.reg_write(UC_X86_REG_RSP, rsp)
    uc.mem_write(rsp + 0x38, bytes(key))
    uc.reg_write(UC_X86_REG_RBP, 0)          # edx=0, r9=0 ์„ ๋งŒ๋“œ๋Š” ์†Œ์Šค ๋ ˆ์ง€์Šคํ„ฐ
    uc.reg_write(UC_X86_REG_RSI, VEC_OBJ)
    uc.reg_write(UC_X86_REG_RDI, STR_OBJ)
 
    print(f"[*] ์ž…๋ ฅ ์‹œ๋ฆฌ์–ผ     : {serial.decode()}  ({len(serial)}๋ฐ”์ดํŠธ)")
    print(f"[*] ์—๋ฎฌ๋ ˆ์ด์…˜ ๊ตฌ๊ฐ„ : {LOOP_START:#x} โ†’ {LOOP_END:#x}")
    uc.emu_start(LOOP_START, LOOP_END)
 
    got = struct.unpack(f"<{len(serial)}i",
                        uc.mem_read(OUT_BUF, len(serial) * 4))
    n = (EXPECTED_END - EXPECTED_RVA) // 4
    want = struct.unpack(f"<{n}i", uc.mem_read(EXPECTED_RVA, n * 4))
 
    print()
    print(" idx  ch   ์—๋ฎฌ๋ ˆ์ด์…˜ ๊ฒฐ๊ณผ      .data ๊ธฐ๋Œ€๊ฐ’        ์ผ์น˜")
    for i, (g, w) in enumerate(zip(got, want)):
        print(f" {i:3d}  {chr(serial[i])!r:>4}  {g:12d}  {w:12d}   "
              f"{'O' if g == w else 'X'}")
 
    ok = list(got) == list(want)
    print()
    print(f"RESULT: {'MATCH โ€” ์žฌ๊ตฌํ˜„์ด ๋ฐ”์ด๋„ˆ๋ฆฌ์™€ ๋™์ผํ•˜๋‹ค' if ok else 'MISMATCH'}")
    return 0 if ok else 1
 
 
if __name__ == "__main__":
    sys.exit(main())
python3 emulate.py 'DH{y0u_4r3_cmp__ma5t3r!}'

emulate.py ์‹คํ–‰ ๊ฒฐ๊ณผ. ์ฝ”๋“œ์—์„œ ๋ฝ‘์€ ํ‚ค๊ฐ€ neko_hat ์œผ๋กœ ์ฐํžˆ๊ณ  24์ž๋ฆฌ ๋ชจ๋‘ ์—๋ฎฌ๋ ˆ์ด์…˜ ๊ฒฐ๊ณผ์™€ .data ๊ธฐ๋Œ€๊ฐ’์ด ์ผ์น˜ํ•ด MATCH ๊ฐ€ ๋‚˜์™”๋‹ค
emulate.py ์‹คํ–‰ ๊ฒฐ๊ณผ. ์ฝ”๋“œ์—์„œ ๋ฝ‘์€ ํ‚ค๊ฐ€ neko_hat ์œผ๋กœ ์ฐํžˆ๊ณ  24์ž๋ฆฌ ๋ชจ๋‘ ์—๋ฎฌ๋ ˆ์ด์…˜ ๊ฒฐ๊ณผ์™€ .data ๊ธฐ๋Œ€๊ฐ’์ด ์ผ์น˜ํ•ด MATCH ๊ฐ€ ๋‚˜์™”๋‹ค

24๊ฐœ ์ „๋ถ€ ์ผ์น˜. ํ‚ค๋„ .rdata ๋ฅผ ๋’ค์ง„ ๊ฒŒ ์•„๋‹ˆ๋ผ movabs ์ฆ‰์น˜๊ฐ’์—์„œ ์ฝ์€ ๊ฒƒ์ด๋ผ "์ฝ”๋“œ ์•ˆ์— ๋ฐ•ํ˜€ ์žˆ๋‹ค"๋Š” ์ฃผ์žฅ๊นŒ์ง€ ๊ฐ™์ด ํ™•์ธ๋œ๋‹ค.


๐Ÿš€ ์‹ค์ œ ์•ฑ์— ๋„ฃ์–ด ๋ณธ๋‹ค

๋งˆ์ง€๋ง‰์€ ์›๋ณธ ํ”„๋กœ๊ทธ๋žจ์ด๋‹ค. ์•„๊นŒ ์•„๋ฌด ๊ฐ’์ด๋‚˜ ๋„ฃ์–ด opps! try again! ์„ ๋ฐ›์•˜๋˜ ๊ทธ ํ™”๋ฉด์— ๋ณต์›ํ•œ ์‹œ๋ฆฌ์–ผ์„ ๋„ฃ๋Š”๋‹ค. ์Šคํฌ๋ฆฝํŠธ๋Š” ์ •์ฐฐ ๋•Œ ์“ด ๊ฒƒ๊ณผ ๊ฐ™๊ณ  ์ธ์ž๋งŒ ๋ฐ”๋€๋‹ค.

python3 gui_capture.py 'DH{y0u_4r3_cmp__ma5t3r!}' /home/jinho/homepage/public/images/blog/dreamhack-babycmp-writeup/11_gui_success.png

wine ์œผ๋กœ ๋„์šด babycmp ๋‹ค์ด์–ผ๋กœ๊ทธ์— ๋ณต์›ํ•œ ์‹œ๋ฆฌ์–ผ์„ ๋„ฃ๊ณ  Check ๋ฅผ ๋ˆ„๋ฅด์ž ์ฃผํ™ฉ์ƒ‰ Congraturations ๊ฐ€ ๋œฌ ํ™”๋ฉด
wine ์œผ๋กœ ๋„์šด babycmp ๋‹ค์ด์–ผ๋กœ๊ทธ์— ๋ณต์›ํ•œ ์‹œ๋ฆฌ์–ผ์„ ๋„ฃ๊ณ  Check ๋ฅผ ๋ˆ„๋ฅด์ž ์ฃผํ™ฉ์ƒ‰ Congraturations ๊ฐ€ ๋œฌ ํ™”๋ฉด

Congraturations!. ์ž…๋ ฅ์นธ์ด ์ข์•„ ์‹œ๋ฆฌ์–ผ ๋’ท๋ถ€๋ถ„์ด ์ž˜๋ ค ๋ณด์ด์ง€๋งŒ, ์•ž์˜ solve.py ์ถœ๋ ฅ๊ณผ ๊ฐ™์€ ๊ฐ’์„ ๊ทธ๋Œ€๋กœ ํƒ€์ดํ•‘ํ•œ ๊ฒƒ์ด๋‹ค.


๐Ÿงฐ ์žฌํ˜„

๋นŒ๋“œํ•  ๊ฒŒ ์—†์–ด์„œ ์ค€๋น„๋ฌผ์€ ํŒŒ์ด์ฌ ํ•˜๋‚˜๋ฟ์ด๋‹ค. ๊ต์ฐจ๊ฒ€์ฆ๊นŒ์ง€ ํ•˜๋ ค๋ฉด Unicorn ์ด ํ•„์š”ํ•˜๋‹ค.

ํ•ญ๋ชฉ๊ฐ’
OSUbuntu (Linux 6.17, x86-64)
๋””์Šค์–ด์…ˆ๋ธ”๋ŸฌGNU objdump (binutils)
์—๋ฎฌ๋ ˆ์ดํ„ฐunicorn 2.1.2 (pip install unicorn)
GUI ์‹คํ–‰wine 10.0 + winetricks vcrun2022 (mfc140u.dll)
ํ™”๋ฉด ์บก์ณXvfb ยท xdotool ยท ImageMagick
๋Œ€์ƒbabycmp.exe md5 845e7763ffb4246b3f294b418b0d9b9c

reproduce.sh ํ•˜๋‚˜๋กœ ๋ณต์›๊ณผ ๊ต์ฐจ๊ฒ€์ฆ์ด ๊ฐ™์ด ๋ˆ๋‹ค.

#!/usr/bin/env bash
# babycmp (DreamHack Silver 2, reversing) โ€” ํ•œ ๋ฐฉ ์žฌํ˜„.
# solve.py ๊ฐ€ babycmp.exe ์—์„œ ์ง์ ‘ ๊ธฐ๋Œ€๊ฐ’ยทํ‚คยท์ ‘๋‘์‚ฌ๋ฅผ ์ฝ์–ด ์‹œ๋ฆฌ์–ผ์„ ๋ณต์›ํ•˜๊ณ ,
# emulate.py ๊ฐ€ ๋ฐ”์ด๋„ˆ๋ฆฌ์˜ ๋ณ€ํ™˜ ๋ฃจํ”„๋ฅผ Unicorn ์œผ๋กœ ๊ทธ๋Œ€๋กœ ๋Œ๋ ค ๊ต์ฐจ๊ฒ€์ฆํ•œ๋‹ค.
#
# ํ•„์š”: python3, (๊ต์ฐจ๊ฒ€์ฆ๊นŒ์ง€ ํ•˜๋ ค๋ฉด) pip install unicorn
set -eu
cd "$(dirname "$(readlink -f "$0")")"
 
EXPECT=$(python3 -c "import json;print(json.load(open('๋ฌธ์ œ.json'))['flag'])" 2>/dev/null || echo '')
 
OUT=$(timeout 300 python3 solve.py 2>&1) || true
echo "$OUT" | tail -8
FLAG=$(printf '%s' "$OUT" | grep -aoE 'DH\{[^}]+\}' | head -1)
 
# ๊ต์ฐจ๊ฒ€์ฆ: ๋ฐ”์ด๋„ˆ๋ฆฌ ๊ธฐ๊ณ„์–ด๋ฅผ ์‹ค์ œ๋กœ ์‹คํ–‰ํ•ด ๊ฐ™์€ ๊ฐ’์ด ๋‚˜์˜ค๋Š”์ง€ (unicorn ์—†์œผ๋ฉด ๊ฑด๋„ˆ๋œ€)
if [ -n "$FLAG" ] && python3 -c "import unicorn" 2>/dev/null; then
  echo
  if timeout 300 python3 emulate.py "$FLAG" 2>&1 | tail -1 | grep -q MATCH; then
    echo "โœ” emulate.py: ๋ฐ”์ด๋„ˆ๋ฆฌ ๋ณ€ํ™˜ ๋ฃจํ”„์™€ ์ผ์น˜"
  else
    echo "โœ˜ emulate.py: ๋ถˆ์ผ์น˜ โ€” ์žฌ๊ตฌํ˜„์ด ํ‹€๋ ธ๋‹ค"; exit 1
  fi
else
  echo; echo "(unicorn ๋ฏธ์„ค์น˜ โ€” ์—๋ฎฌ๋ ˆ์ด์…˜ ๊ต์ฐจ๊ฒ€์ฆ ์ƒ๋žต)"
fi
 
if [ -n "$FLAG" ] && { [ -z "$EXPECT" ] || [ "$FLAG" = "$EXPECT" ]; }; then
  echo; echo "โœ… PASS  $FLAG"; exit 0
fi
echo; echo "โŒ FAIL (์–ป์€ ๊ฐ’: '${FLAG:-์—†์Œ}' / ๊ธฐ๋Œ€: '$EXPECT')"; exit 1

์ถœ๋ ฅ ๋์€ ์ด๋ ‡๋‹ค.

FLAG: DH{y0u_4r3_cmp__ma5t3r!}
 
โœ” emulate.py: ๋ฐ”์ด๋„ˆ๋ฆฌ ๋ณ€ํ™˜ ๋ฃจํ”„์™€ ์ผ์น˜
 
โœ… PASS  DH{y0u_4r3_cmp__ma5t3r!}


๐Ÿ“ ๊ฒฐ๋ก 

์ •๋‹ต์„ ๋“ค๊ณ  ์žˆ๋Š” ํ”„๋กœ๊ทธ๋žจ์€ ์ •๋‹ต์„ ๋‚ด์ค„ ์ˆ˜๋ฐ–์— ์—†๋‹ค.

์ด ๋ฌธ์ œ์˜ ๊ฒ€์ฆ์€ "์ž…๋ ฅ์„ ๋ณ€ํ™˜ํ•ด์„œ ์ €์žฅ๋œ ๊ฐ’๊ณผ ๊ฐ™์€์ง€ ๋ณธ๋‹ค"๋Š” ๊ตฌ์กฐ๋‹ค. ์ €์žฅ๋œ ๊ฐ’์ด ๋ฐ”์ด๋„ˆ๋ฆฌ ์•ˆ์— ์žˆ๊ณ  ๋ณ€ํ™˜์ด ๊ฐ€์—ญ์ด๋ฉด, ๊ทธ ๋‘˜๋กœ ์ •๋‹ต์„ ๊ณ„์‚ฐํ•  ์ˆ˜ ์žˆ๋‹ค. ์„œ๋ฒ„์— ๋ฌผ์–ด๋ณด๋Š” ๊ตฌ์กฐ์˜€๋‹ค๋ฉด 24๊ธ€์ž๋ฅผ ๋‹ค ๋งžํžˆ๊ธฐ ์ „์—” ์•„๋ฌด๊ฒƒ๋„ ๋ชป ์–ป์—ˆ์„ ํ…๋ฐ, ํด๋ผ์ด์–ธํŠธ ์•ˆ์—์„œ ๋๋‚˜๋‹ˆ ๋น„๊ต ๋Œ€์ƒ์ด ๊ณง ๋‹ต์ด ๋œ๋‹ค.

๋ผ์ด์„ ์Šค ํ‚ค๋‚˜ ์˜คํ”„๋ผ์ธ ์ธ์ฆ์„ ์ด๋ ‡๊ฒŒ ์งœ๋ฉด ์•ˆ ๋˜๋Š” ์ด์œ ๊ฐ€ ์—ฌ๊ธฐ ์žˆ๋‹ค. ๊ฒ€์ฆ ๋กœ์ง๊ณผ ๊ธฐ๋Œ“๊ฐ’์ด ๊ฐ™์€ ์‹คํ–‰ํŒŒ์ผ์— ๋“ค์–ด ์žˆ์œผ๋ฉด ๋‚œ๋…ํ™”๋ฅผ ์–ผ๋งˆ๋‚˜ ์–น๋“  ์‹œ๊ฐ„ ๋ฌธ์ œ๋‹ค. ์„œ๋ช… ๊ฒ€์ฆ์ฒ˜๋Ÿผ ์ •๋‹ต์„ ๋ชฐ๋ผ๋„ ํ™•์ธ๋งŒ ๋˜๋Š” ๊ตฌ์กฐ๋กœ ๊ฐ€์•ผ ํ•œ๋‹ค.

์ž๋ฆฌ๋ผ๋ฆฌ ์–ฝํžˆ์ง€ ์•Š์œผ๋ฉด ๋ธŒ๋ฃจํŠธํฌ์Šค๊ฐ€ 24๋ฒˆ์œผ๋กœ ๋๋‚œ๋‹ค.

๊ฐ€์šด๋ฐ 20๊ธ€์ž๋ฅผ ํ†ต์งธ๋กœ ๋งžํžˆ๋ ค๋ฉด ๊ฒฝ์šฐ์˜ ์ˆ˜๊ฐ€ 95์˜ 20์ œ๊ณฑ์ด์ง€๋งŒ, ์‹ค์ œ๋กœ๋Š” ์ž๋ฆฌ๋งˆ๋‹ค 95๋ฒˆ์”ฉ ์Šค๋ฌผ๋„ค ๋ฒˆ ๋Œ๋ฆฌ๋ฉด ๋œ๋‹ค. ๊ฐ ์ž๋ฆฌ์˜ ๊ณ„์‚ฐ์— ์•ž ๊ธ€์ž๊ฐ€ ์•ˆ ์„ž์ด๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

์•”ํ˜ธ์—์„œ CBC ๊ฐ™์€ ์ฒด์ด๋‹์„ ์“ฐ๋Š” ์ด์œ ๊ฐ€ ์ด๊ฒƒ์ด๋‹ค. ํ•œ ์ž๋ฆฌ์˜ ๊ฒฐ๊ณผ๊ฐ€ ๋‹ค๋ฅธ ์ž๋ฆฌ์— ๋ฒˆ์ง€์ง€ ์•Š์œผ๋ฉด ์ „์ˆ˜ ํƒ์ƒ‰์˜ ๋น„์šฉ์ด ๊ณฑ์…ˆ์—์„œ ๋ง์…ˆ์œผ๋กœ ๋‚ด๋ ค์•‰๋Š”๋‹ค.

์†์œผ๋กœ ์˜ฎ๊ธด ์žฌ๊ตฌํ˜„์€ ๊ธฐ๊ณ„๋กœ ํ•œ ๋ฒˆ ๋” ์žฌ ๋ด์•ผ ํ•œ๋‹ค.

์–ด์…ˆ๋ธ”๋ฆฌ๋ฅผ ์ฝ์–ด ํŒŒ์ด์ฌ์œผ๋กœ ์˜ฎ๊ธฐ๋Š” ์ˆœ๊ฐ„ "๋‚ด๊ฐ€ ์ œ๋Œ€๋กœ ์ฝ์—ˆ๋‚˜"๋ผ๋Š” ๋ถˆํ™•์‹ค์„ฑ์ด ์ƒ๊ธด๋‹ค. ๊ฐ’์ด ๋งž์œผ๋ฉด ๋Œ€๊ฐœ ๋งž์€ ๊ฒƒ์ด์ง€๋งŒ, ์ด๋ฒˆ์ฒ˜๋Ÿผ ํ‹€๋ฆฐ ๊ฒŒ ๋ณ€ํ™˜์‹์ด ์•„๋‹ˆ๋ผ ๋‚ด๊ฐ€ ๋งŒ๋“  ๊ฐ€์งœ ๊ฐ์ฒด ๋ ˆ์ด์•„์›ƒ์ธ ๊ฒฝ์šฐ๋„ ์žˆ๋‹ค. ์•ž 16๊ฐœ๊ฐ€ ๋งž์•„๋–จ์–ด์ ธ์„œ ํ•œ์ฐธ ์—‰๋šฑํ•œ ๋ฐ๋ฅผ ๋ดค๋‹ค.

Unicorn ์œผ๋กœ ๋ฌธ์ œ ๋ฐ”์ด๋„ˆ๋ฆฌ์˜ ๋ช…๋ น์„ ๊ทธ๋Œ€๋กœ ๋Œ๋ฆฌ๋Š” ๋ฐ ๋“  ๊ฑด ์Šคํฌ๋ฆฝํŠธ 90์ค„ ์ •๋„๋‹ค. ๊ทธ ์ •๋„๋ฉด "์ฝ์€ ๋Œ€๋กœ ์˜ฎ๊ฒผ๋‹ค"๋ฅผ ์ฆ๊ฑฐ๋กœ ๋ฐ”๊พธ๊ธฐ์— ์‹ผ ํŽธ์ด๋‹ค.

์ถœ์ œ์ž์˜ ํ”์ ์€ ์ƒ๊ฐ๋ณด๋‹ค ๋งŽ์ด ๋‚จ๋Š”๋‹ค.

PDB ๊ฒฝ๋กœ์—์„œ ๋นŒ๋“œ ๋””๋ ‰ํ† ๋ฆฌ์™€ ๊ณ„์ • ์ด๋ฆ„์ด, ์ฆ‰์น˜๊ฐ’์—์„œ ์ถœ์ œ์ž ๋‹‰๋„ค์ž„์ด ๊ทธ๋Œ€๋กœ ๋‚˜์™”๋‹ค. ํ‚ค๊ฐ€ neko_hat ์ธ ๊ฑธ ๋ฏธ๋ฆฌ ์•Œ์•˜๋‹ค๊ณ  ๋ฌธ์ œ๊ฐ€ ์‰ฌ์›Œ์ง€์ง„ ์•Š์ง€๋งŒ, Release ๋นŒ๋“œ๊ฐ€ ์–ด๋””๊นŒ์ง€ ์ง€์›Œ ์ฃผ๋Š”์ง€์— ๋Œ€ํ•œ ๊ฐ์€ ํ™•์‹คํžˆ ์ƒ๊ธด๋‹ค.

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

Comments

๋Œ“๊ธ€

0๊ฐœ

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

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

Related

๊ด€๋ จ ๊ธ€

3๊ฐœ
[๐Ÿฅˆ Silver 4] ํ”„๋กœ๊ทธ๋žจ์ด ์ •๋ง๋กœ ์ž๊ธฐ ์ด๋ฆ„์—๊ฒŒ ๋ฌผ์—ˆ๋‹ค โ€” DreamHack What is your name? ํ’€์ด
blog

[๐Ÿฅˆ Silver 4] ํ”„๋กœ๊ทธ๋žจ์ด ์ •๋ง๋กœ ์ž๊ธฐ ์ด๋ฆ„์—๊ฒŒ ๋ฌผ์—ˆ๋‹ค โ€” DreamHack What is your name? ํ’€์ด

zip ์•ˆ์— exe๊ฐ€ 11๊ฐœ, ์ „๋ถ€ ํŒŒ์ผ๋ช…์ด ๋ฌด์ž‘์œ„ 3๊ธ€์ž๋กœ ๋’ค์„ž์—ฌ ์žˆ๋‹ค. ์‹คํ–‰ํ•ด๋„ ์ฝ˜์†”์— ์•„๋ฌด๊ฒƒ๋„ ์•ˆ ๋œจ๊ณ , sha256๋„ ์ „๋ถ€ ๋‹ค๋ฅด๋‹ค. cmp -l๋กœ ๋‘ ํŒŒ์ผ์„ ๊ฒน์ณ๋ณด๋‹ˆ 123392๋ฐ”์ดํŠธ ์ค‘ ๋”ฑ 2๋ฐ”์ดํŠธ๋งŒ ๋‹ค๋ฅด๋‹ค๋Š” ๊ฑธ ๋ฐœ๊ฒฌํ•˜๋ฉด์„œ ์‹ค๋งˆ๋ฆฌ๊ฐ€ ํ’€๋ ธ๋‹ค. ๊ฐ exe๋Š” GetModuleFileNameA๋กœ ์ž๊ธฐ ์ž์‹ ์˜ ํŒŒ์ผ๋ช…์„ ์ฝ์–ด ํ•œ ๊ธ€์ž์”ฉ ๋ฐ€์–ด์„œ ์ถœ๋ ฅํ•  ๋ฟ์ด์—ˆ๊ณ , ๊ทธ ๊ฒฐ๊ณผ๋ฅผ ์ˆœ์„œ๋Œ€๋กœ ์ด์–ด๋ถ™์ด๋ฉด ๊ทธ๋Œ€๋กœ flag๊ฐ€ ๋œ๋‹ค โ€” "What is your name?"์ด ์€์œ ๊ฐ€ ์•„๋‹ˆ๋ผ, ํ”„๋กœ๊ทธ๋žจ์ด ์ง„์งœ๋กœ ์ž๊ธฐ ์ž์‹ ์˜ ์ด๋ฆ„์„ ๋ฌป๋Š” ์งˆ๋ฌธ์ด์—ˆ๋‹ค.
#dreamhack#ctf#reversing+4
2026-07-21#dreamhack +6
[๐Ÿฅ‰ Bronze 2] ์•”ํ˜ธ๋„ ํ”Œ๋ž˜๊ทธ๋„ .data ์— ๋ˆ„์›Œ ์žˆ๋‹ค โ€” DreamHack Gyul Brix Calculator ํ’€์ด
blog

[๐Ÿฅ‰ Bronze 2] ์•”ํ˜ธ๋„ ํ”Œ๋ž˜๊ทธ๋„ .data ์— ๋ˆ„์›Œ ์žˆ๋‹ค โ€” DreamHack Gyul Brix Calculator ํ’€์ด

๋‹น๋„๋ฅผ ์ž…๋ ฅ๋ฐ›๋Š” ์ฒ™ํ•˜๋Š” 32๋น„ํŠธ PE ์•ˆ์—, ๊ด€๋ฆฌ์ž ์•”ํ˜ธ์™€ ํ”Œ๋ž˜๊ทธ๊ฐ€ ๊ฐ๊ฐ ๋‹จ์ผ๋ฐ”์ดํŠธ XOR ํ•œ ๊ฒน๋งŒ ์“ด ์ฑ„ .data ์— ๋‚˜๋ž€ํžˆ ๋ˆ„์›Œ ์žˆ๋‹ค. ํ‚ค๊ฐ€ ์ฝ”๋“œ ์•ˆ ์ฆ‰์น˜๊ฐ’์ด๋ผ strings ๋กœ๋Š” ์•„๋ฌด๊ฒƒ๋„ ์•ˆ ์žกํžˆ๊ณ , ๋‘ ๋ธ”๋กญ์„ ํ‚คยท์•”ํ˜ธ๋ฌธ ์Œ์œผ๋กœ ๋„˜๊ฒจ์งš์œผ๋ฉด ๋” ํ—ค๋งจ๋‹ค. ๋””์Šค์–ด์…ˆ๋ธ”๋ฆฌ์—์„œ 0x55 ์™€ 0x77 ์„ ์ฝ์–ด๋‚ด๋ฉด ๋๋‚œ๋‹ค.
#dreamhack#ctf#reversing+6
2026-08-17#dreamhack +6
[๐Ÿฅˆ Silver 1] ์ƒ์‡„๋˜๋Š” ์—ฐ์‚ฐ 14๊ฐœ์™€ ๋ฏธ๋ผ ํ‚ค 2๊ฐœ โ€” DreamHack Ransom ํ’€์ด
blog

[๐Ÿฅˆ Silver 1] ์ƒ์‡„๋˜๋Š” ์—ฐ์‚ฐ 14๊ฐœ์™€ ๋ฏธ๋ผ ํ‚ค 2๊ฐœ โ€” DreamHack Ransom ํ’€์ด

UPX ๋กœ ํฌ์žฅ๋œ 32๋น„ํŠธ PE ๊ฐ€ flag.txt ๋ฅผ ๋‘ ๋ฒˆ ์•”ํ˜ธํ™”ํ•œ๋‹ค. ์ง„์งœ main ์€ ์•”ํ˜ธํ™” ํ•จ์ˆ˜๋ฅผ ๋‘˜ ๋ถ€๋ฅด๋Š”๋ฐ, ํ•˜๋‚˜๋งŒ ๋ณด๊ณ  ๋’ค์ง‘์œผ๋ฉด ์•„๋ฌด๊ฒƒ๋„ ์•ˆ ๋‚˜์˜จ๋‹ค. 2๋‹จ๊ณ„๋Š” ๊ณ ์ • ์ธ๋ฑ์Šค ์—ฐ์‚ฐ์ด 15๊ฐœ๋‚˜ ๋ถ™์–ด ์žˆ์ง€๋งŒ 14๊ฐœ๊ฐ€ ์—ญ์—ฐ์‚ฐ ์ง์ด๋ผ ์ƒ์‡„๋˜๊ณ  ์‹ค์งˆ์€ ํ•˜๋‚˜๋ฟ์ด๊ณ , .rdata ์˜ ํ‚ค์ฒ˜๋Ÿผ ์ƒ๊ธด ๋ฌธ์ž์—ด ์…‹ ์ค‘ ๋‘˜์€ ์Šคํƒ์— ๋ณต์‚ฌ๋งŒ ๋˜๊ณ  ์ฝํžˆ์ง€ ์•Š๋Š” ๋ฏธ๋ผ๋‹ค. ํ‚ค๊ฐ€ ํŒŒ์ผ๋ณด๋‹ค ํ•œ ๋ฐ”์ดํŠธ ์งง์•„ ๋งˆ์ง€๋ง‰ ๋ฐ”์ดํŠธ๋Š” ์ดˆ๊ธฐํ™” ์•ˆ ๋œ ์Šคํƒ์„ ์ฝ๋Š”๋‹ค.
#dreamhack#ctf#reversing+7
2026-07-28#dreamhack +5