๋ฌธ์ : DreamHack โ photographer ๋ถ๋ฅ: reversing ๋์ด๋: ๐ฅ Silver 3 FLAG:
DH{d85a130283f58035eb327b56e37d2dd087156ba629687a5d52bd4af3c5bfa4f4}
๋ฌธ์ ์ค๋ช ์ ํ ์ค์ด๋ค. "I lost my big-secret photo..."
๋ฐ์ ๊ฑด ์์ด๋ฒ๋ ธ๋ค๋ ์ฌ์ง์ ์ํด ํ๋์, ๊ทธ ์ฌ์ง์ ๊ทธ ๊ผด๋ก ๋ง๋ ํ๋ก๊ทธ๋จ ํ๋๋ค.
๋ฌธ์ ๊ฐ์
| ํญ๋ชฉ | ๋ด์ฉ |
|---|---|
| ๋ฌธ์ ๋ช | photographer |
| ๋์ด๋ | ๐ฅ Silver 3 |
| ๋ถ๋ฅ | reversing |
| ์ ๊ณต ํ์ผ | prob (26,848B, stripped PIE C++), flag.bmp.enc (6,220,854B) |
| ์๋ฒ | ์์ โ ํ์ผ๋ง ์ค๋ค |
| ํต์ฌ ๊ธฐ๋ฒ | ๊ณ ์ ์๋ srand(0xBEEF) + ๋ฐ์ดํธ๋ณ ๊ฐ์ญ ๋ณํ์ ์ญ์ฐ |
prob์ flag.bmp๋ฅผ ์ฝ์ด flag.bmp.enc๋ฅผ ๋ฑ๋ ํ ๋ฐฉํฅ ๋ณํ๊ธฐ๋ค. ์ฐ๋ฆฌ๊ฐ ๊ฐ์ง ๊ฑด ๊ฒฐ๊ณผ๋ฌผ๋ฟ์ด๋, ๊ทธ ๋ณํ์ ์ฝ์ด์ ๊ฑฐ๊พธ๋ก ๋๋ฆฌ๋ฉด ๋๋ค.
๋๋๋ฆฐ BMP๋ฅผ ์ด๋ฉด ํ๋๊ทธ๊ฐ ๊ทธ๋ฆผ์ผ๋ก ๊ทธ๋ ค์ ธ ์๋ค.
๐ฌ ์ ์ฐฐ โ ๋ฐ์ ๊ฒ ๋ ๊ฐ
๋จผ์ ๋ญ ๋ฐ์๋์ง๋ถํฐ ๋ณธ๋ค.
ls -l extracted && file extracted/* && xxd -l 64 extracted/flag.bmp.enc
flag.bmp.enc๋ file์ด data๋ผ๊ณ ๋ง ํ๋ค. BMP๋ผ๋ฉด BM์ผ๋ก ์์ํด์ผ ํ๋๋ฐ ์ฒซ ๋ ๋ฐ์ดํธ๊ฐ 72 35๋ค. ํค๋๊น์ง ๊ฑด๋๋ ธ๋ค๋ ๋ป์ด๋ค.
๊ทธ๋ฐ๋ฐ ํฅ์ค๋ฅผ ๋ณด๋ฉด ๊ท์น์ด ํ๋ ๋์ ๋๋ค. 00๊ณผ ff๊ฐ ์ธ ๋ฐ์ดํธ ์ฃผ๊ธฐ๋ก ๊ณ์ ๋์จ๋ค. ์ฒซ ์ค 7235 ed32 e597 b400 9fea d841 9900 dc4b์์ 00์ ์คํ์
7๊ณผ 13์ ์๋ค. ๋ ๋ค 3์ผ๋ก ๋๋ ๋๋จธ์ง๊ฐ 1์ด๋ค. ๊ทธ ์๋ ์ค๋ค์ ff๋ ๋ง์ฐฌ๊ฐ์ง๋ค.
24๋นํธ BMP๋ ํฝ์ ํ๋๊ฐ B, G, R ์ธ ๋ฐ์ดํธ๋ค. ๊ทธ๋ฌ๋ "์ธ ๋ฐ์ดํธ ์ฃผ๊ธฐ"๋ฅผ ๋ณด๋ฉด ํฝ์ ๊ตฌ์กฐ๊ฐ ์ด์ ์๋ค๊ณ โ ๊ฐ์ ๊ทธ๋๋ก๊ณ ์๋ฆฌ๋ง ์์๋ค๊ณ โ ์๊ฐํ๊ธฐ ์ฝ๋ค. ์ฌ๊ธฐ์ ํ ๋ฒ ํ์ง์๋ค.
๋ค์์ ๋ฐ์ด๋๋ฆฌ๊ฐ ๋ญ ๋งํฌํ๋์ง๋ค. stripped๋ผ๋ PLT๋ ๋จ๋๋ค.
objdump -d -M intel extracted/prob | grep -E "@plt>:" | grep -iE "rand|time|memmove|alarm|clock"
rand@plt์ srand@plt๊ฐ ์๋ค. ๋์๋ฅผ ์ด๋ค.
๊ทธ๋ฐ๋ฐ time@plt๋ clock@plt๋ ์๋ค. ์๋๋ฅผ ์คํ ์๊ฐ์์ ๋ฝ์ง ์๋๋ค๋ ๋ป์ด๋ค. ์๋๊ฐ ์์๋ฉด ๋์์ด์ด ๋งค ์คํ ๋๊ฐ๊ณ , ๊ทธ๋ฌ๋ฉด ๋๋๋ฆด ์ ์๋ค. ์ด ํ ์ค์ด ๋ฌธ์ ๋ฅผ ํ ์ ์๊ฒ ๋ง๋ ๋ค.
๐ ์ฝ์ง โ ์๋ฆฌ๋ฅผ ์์๋ค๊ณ ๋ฏฟ์๋ค
โถ๐ ์ฝ์ง โ 'ํฝ์ ์ ํ'์ด๋ผ๋ ์๋ชป๋ ์ฒซ ๊ฐ์ค
ํฅ์ค์ ์ธ ๋ฐ์ดํธ ์ฃผ๊ธฐ + rand() ์ฌ์ฉ. ์ด ๋์ ๋ถ์ด๋ ์์ฐ์ค๋ฝ๊ฒ ํ๋์ ๊ทธ๋ฆผ์ด ๋ ์ฌ๋๋ค.
ํฝ์ (๋๋ ๋ฐ์ดํธ)์ ์๋ฆฌ๋ฅผ ๋์๋ก ์์ ๊ฒ์ด๋ค. ๊ฐ์ ๊ทธ๋๋ก๋๊น
00ยทff๊ฐ์ ์ฑ๋๊ฐ์ด ์ด์ ์๊ณ ,std::shuffle์ด๋ FisherโYates๋ฅผ ๋๋ ธ์ ๊ฒ์ด๋ค.
๊ทธ๋์ ์ฒ์์ memmove@plt๊ฐ ์๋ ๊ฒ๋ "๋ธ๋ก์ ์ฎ๊ธด๋ค"๋ ์ฆ๊ฑฐ๋ก ์ฝ์๋ค. ์
ํ์ด๋ฉด ์ญ์
ํ๋ง ๋ง๋ค๋ฉด ๋๋ main์ ๋์ถฉ ํ๊ณ rand() % n ํจํด๋ง ์ฐพ์ผ๋ ค ํ๋ค.
ํ๋ ธ๋ค. main์๋ ๋ ์์๋ฅผ ๋ง๋ฐ๊พธ๋ ์ฝ๋๊ฐ ์๋ค. mov BYTE PTR [rax], bl โ ์ฝ์ ์๋ฆฌ์ ๊ทธ๋๋ก ๋์ด๋ค. ์๋ฆฌ๋ ํ ๋ฒ๋ ์ ๋ฐ๋๋ค.
์ธ ๋ฐ์ดํธ ์ฃผ๊ธฐ์ ์ ์ฒด๋ ์
ํ์ด ์๋์๋ค. ์๋์์ ๋ณด๊ฒ ์ง๋ง ๋ณํ์ i % 3์ผ๋ก ์ธ ๊ฐ๋๋ก ๊ฐ๋ฆฌ๊ณ , ๊ทธ์ค i%3==1 ๊ฐ๋๊ฐ ํ์ ๋ง ํ๋ค. ๊ทธ๋ฐ๋ฐ 00000000๊ณผ 11111111์ ๋ช ์นธ์ ๋๋ ค๋ ์๊ธฐ ์์ ์ด๋ค. ์๋ณธ BMP๋ ํฐ ๋ฐฐ๊ฒฝ(ff ff ff)๊ณผ ๊ฒ์ ๊ธ์(00 00 00)๊ฐ ๋๋ถ๋ถ์ด๋, ๊ทธ ์๋ฆฌ์ 00ยทff๋ ๋ณํ์ ํต๊ณผํด๋ ๊ทธ๋๋ก ๋จ๋๋ค.
์ค์ ๋ก ์ 4KB์์ ff 1353๊ฐ ์ค 1347๊ฐ๊ฐ i%3==1 ์๋ฆฌ์ ์๋ค. ํฝ์
๊ตฌ์กฐ๊ฐ ์ด์๋จ์ ๊ฒ ์๋๋ผ, ์ธ ๊ฐ๋ ์ค ํ๋๊ฐ ๊ทน๋จ๊ฐ์ ๋ณด์กดํ ๊ฒ๋ฟ์ด๋ค.
๊ฐ์ค์ด ๊ด์ธก์ ์ค๋ช
ํ๋ ๊ฒ์ฒ๋ผ ๋ณด์ธ๋ค๊ณ ๋ง๋ ๊ฑด ์๋๋ค. memmove@plt๋ ์
ํ์ ์ฆ๊ฑฐ๊ฐ ์๋๋ผ ๊ทธ๋ฅ std::vector๊ฐ ์ปค์ง ๋ ์ฐ๋ ๊ฒ์ด์๋ค.
๐ main ์ ์ฝ๋๋ค
main์ ์ฌ๋ณผ์ด ์๋ค. ์ํธ๋ฆฌ(_start)๊ฐ __libc_start_main์ ๋๊ธฐ๋ ์ฒซ ์ธ์๋ฅผ ๋ณด๋ฉด 0x24fb๋ค.
objdump -d -M intel --start-address=0x24fb --stop-address=0x2540 extracted/prob | sed -f annot_seed.sed
์ฒซ ์ค๋ถํฐ ๋ต์ด ๋์จ๋ค.
251a: bf ef be 00 00 mov edi,0xbeef ; ์๋
251f: e8 6c fd ff ff call 2290 <srand@plt> ; srand(0xbeef)srand(0xBEEF). ํ๋ก๊ทธ๋จ์ด ๋ญ ํ๋ ๋์์ด์ ํญ์ ๊ฐ๋ค.
์ด์ด์ lea๋ก ์ง๋ ๋ ์ฃผ์ 0x4004, 0x400d๊ฐ ๊ฐ๊ฐ ifstream๊ณผ ofstream ์์ฑ์๋ก ๋ค์ด๊ฐ๋ค. ๊ทธ ์๋ฆฌ์ ๋ญ๊ฐ ์๋์ง๋ .rodata๋ฅผ ๊ทธ๋๋ก ๋คํํ๋ฉด ๋ณด์ธ๋ค.
objdump -s -j .rodata extracted/prob
flag.bmp๋ฅผ ์ฝ์ด flag.bmp.enc๋ก ์ด๋ค. ํ์ผ ์ ์ฒด๋ฅผ std::vector<char>์ ๋ด๊ณ , ์ธ๋ฑ์ค๋ฅผ 0๋ถํฐ ๋๊น์ง ํ๋ ๋ฃจํ๊ฐ ์ด์ด์ง๋ค.
๋ฃจํ ๋ณธ์ฒด ์ฒซ๋จธ๋ฆฌ๋ ์ด๋ ๊ฒ ์๊ฒผ๋ค.
objdump -d -M intel --start-address=0x2649 --stop-address=0x2699 extracted/prob | sed -f annot_dispatch.sed
0xaaaaaaaaaaaaaaab๋ ์ปดํ์ผ๋ฌ๊ฐ 3์ผ๋ก ๋๋๋ ๋๋์
์ ๊ณฑ์
์ผ๋ก ๋ฐ๊ฟ ๋ ์ฐ๋ ์์๋ค. ๊ทธ๊ฑธ๋ก i / 3์ ๊ตฌํ๊ณ , i - 3*(i/3)์ผ๋ก i % 3์ ๋ง๋ ๋ค์ 0ยท1ยท2 ์ธ ๊ฐ๋๋ก ๋ด๋ค.
์ฆ ๋ฐ์ดํธ๋ง๋ค ์ธ๋ฑ์ค์ ๋ฐ๋ผ ๋ค๋ฅธ ๋ณํ์ด ๊ฑธ๋ฆฐ๋ค. ์๊น ํฅ์ค์์ ๋ณธ ์ธ ๋ฐ์ดํธ ์ฃผ๊ธฐ์ ์ ์ฒด๊ฐ ์ด๊ฑฐ๋ค.
๐ฃ ์ธ ๊ฐ๋ ๋ณํ
์ธ ๋ถ๊ธฐ๋ฅผ ์ฐจ๋ก๋ก ์ฝ๋๋ค.
i % 3 == 0
objdump -d -M intel --start-address=0x2699 --stop-address=0x26fe extracted/prob | sed -f annot_cases.sed![ํด๋ฆญํ์ฌ ํ๋ objdump ๋ก ๋ณธ i%3==0 ๋ถ๊ธฐ โ ror8(b,7) ์ ๋ถ๋ฅธ ๋ค rand() ๋ฅผ ๋ํ๊ณ movzx ๋ก ํ์ 1๋ฐ์ดํธ๋ง ๋จ๊ธด ๋ค์ rol8(x,4) ๋ฅผ ๊ฑธ์ด v[i] ์ ๋์ด๋ค](/_next/image?url=%2Fimages%2Fblog%2Fdreamhack-photographer-writeup%2F05_case0.png&w=3840&q=75)
ror8(v[i], 7) โ + rand() โ ํ์ ๋ฐ์ดํธ๋ง ๋จ๊น โ rol8(..., 4). ํ์ ๋ ๋ฒ์ ๋ง์
ํ ๋ฒ์ด๋ค.
i % 3 == 1
objdump -d -M intel --start-address=0x26fe --stop-address=0x2757 extracted/prob | sed -f annot_cases.sed
์ฌ๊ธฐ์ ๋์๊ฐ ๊ฐ์ด ์๋๋ผ ํ์ ๋์ผ๋ก ๋ค์ด๊ฐ๋ค. cdq; shr edx,0x1d; add; and 0x7; sub๋ ๋ถํธ ์๋ % 8์ ์ธ๋ผ์ธํ ๊ฒ์ธ๋ฐ, rand()๋ ํญ์ 0 ์ด์์ด๋ผ ์ค์ง์ ์ผ๋ก rand() & 7์ด๋ค.
i % 3 == 2
objdump -d -M intel --start-address=0x2757 --stop-address=0x279b extracted/prob | sed -f annot_cases.sed![ํด๋ฆญํ์ฌ ํ๋ objdump ๋ก ๋ณธ i%3==2 ๋ถ๊ธฐ โ xor eax,ebx ๋ก ๋ฐ์ดํธ์ rand() ๋ฅผ XOR ํ ๋ค lea ebx,[rax-0x18] ๋ก 0x18 ์ ๋นผ๊ณ ๊ทธ ํ์ ๋ฐ์ดํธ๋ฅผ v[i] ์ ๋์ด๋ค](/_next/image?url=%2Fimages%2Fblog%2Fdreamhack-photographer-writeup%2F07_case2.png&w=3840&q=75)
XOR ํ 0x18์ ๋บ๋ค. 32๋นํธ๋ก ๊ณ์ฐํ์ง๋ง ์ ์ฅ์ mov BYTE PTR [rax], bl โ ํ์ 1๋ฐ์ดํธ๋ง ๋จ๋๋ค. ๋บ์
์ mod 256์์ ํ์ ๋ฐ์ดํธ๋ง ๋ณด๋ฉด ๋๋ ์์ ๋นํธ๋ ์ ๊ฒฝ ์ธ ํ์๊ฐ ์๋ค.
์ธ ๊ฐ๋๋ฅผ ํ ์ฅ์ผ๋ก ์ ๋ฆฌํ๋ฉด ์ด๋ ๋ค.
![ํด๋ฆญํ์ฌ ํ๋ ์ธ ๊ฐ๋ ๋ณํ ํ์ดํ๋ผ์ธ ๋์ โ srand(0xbeef) ์ดํ flag.bmp ์ ๋ฐ์ดํธ v[0], v[1], v[2] ์ ๋์ r0, r1, r2 ๊ฐ ์ธ๋ฑ์ค ์์๋ก ์ง์ง์ด์ง๊ณ i%3 ๊ฐ์ ๋ฐ๋ผ rol8/ror8/XOR ์ธ ์ ์ค ํ๋๊ฐ ์ ์ฉ๋๋ค](/_next/image?url=%2Fimages%2Fblog%2Fdreamhack-photographer-writeup%2F00_pipeline.png&w=3840&q=75)
์ฌ๊ธฐ์ ์ค์ํ ๊ฒ ๋ ๊ฐ์ง๋ค.
์ฒซ์งธ, ์ธ ๊ฐ๋ ๋ชจ๋ rand()๋ฅผ ์ ํํ ํ ๋ฒ์ฉ ๋ถ๋ฅธ๋ค. ๋ถ๊ธฐ๋ง๋ค ๊ฐ์๊ฐ ๋ฌ๋๋ค๋ฉด ๋์ ์๋น ์์น๋ฅผ ๋ฐ๋ก ์ถ์ ํด์ผ ํ์ ํ
๋ฐ, ๊ทธ๋ด ํ์๊ฐ ์๋ค. i๋ฒ์งธ ๋ฐ์ดํธ๋ i๋ฒ์งธ ๋์๋ฅผ ์ด๋ค.
๋์งธ, ์๋ฆฌ๋ฅผ ๋ฐ๊พธ๋ ์ฝ๋๊ฐ ์๋ค. ํ์ ยท๋ง์ ยทXORยท๋บ์ ๋ฟ์ด๊ณ ์ ๋ถ 8๋นํธ ์์์ ๊ฐ์ญ์ด๋ค. ์ญํจ์๋ฅผ ๊ฐ์ ์์๋ก ๊ฑธ๋ฉด ๊ทธ๋๋ก ๋์์จ๋ค.
๐ ํ์ ํฌํผ ๋ ๊ฐ
0x2489์ 0x24c2๊ฐ ๋ญ์ง ํ์ธํ๋ค. ๋ ๋ค ์ธ์๋ฅผ ๋ ๊ฐ ๋ฐ๋ ์งง์ ํจ์๋ค.
objdump -d -M intel --start-address=0x2489 --stop-address=0x24c2 extracted/prob | sed -f annot_rot.sed
(b >> n) | (b << (8 - n)) โ ์ค๋ฅธ์ชฝ ํ์ ์ด๋ค.
objdump -d -M intel --start-address=0x24c2 --stop-address=0x24fb extracted/prob | sed -f annot_rot.sed
์ด์ชฝ์ ์ํํธ ์์๊ฐ ๋ฐ๋๋ผ ์ผ์ชฝ ํ์ ์ด๋ค.
๋ ํจ์ ๋ชจ๋ and DWORD PTR [rbp-0x8], 0x7๋ก ํ์ ๋์ 0~7๋ก ์๋ฅธ๋ค. n์ด 0์ด๋ฉด 8 - n = 8์ด ๋์ด ์ํํธ๊ฐ ๋ฐ์ดํธ ๋ฐ์ผ๋ก ๋ฐ๋ ค๋๋๋ฐ, ์ ์ฅํ ๋ ํ์ 1๋ฐ์ดํธ๋ง ์ฐ๋ฏ๋ก ๊ฒฐ๊ณผ๋ ์๋ ๊ฐ ๊ทธ๋๋ก๋ค. ํญ๋ฑ์ด ๋๋ ๋ฐ๋ก ์์ธ ์ฒ๋ฆฌํ ํ์๋ ์๋ค.
sar์ด ์ฐ์ธ ๊ฒ ๋์ ๊ฑธ๋ฆด ์ ์๋๋ฐ, ๋ฐ๋ก ์์ movzx edx, BYTE PTR [rbp-0x4]๋ก ์ ํ์ฅ์ ํด ๋๋ค. ๊ฐ์ด ํญ์ 0~255๋ผ ์ฐ์ ์ํํธ๋ ๋
ผ๋ฆฌ ์ํํธ๋ ๊ฒฐ๊ณผ๊ฐ ๊ฐ๋ค. ์ด๊ฑธ ๋์น๊ณ ๋ถํธ ์๋ ํ์
์ผ๋ก ์ฎ๊ธฐ๋ฉด ์กฐ์ฉํ ์ด๊ธ๋๋ค โ ์๋ ์ฝ์ง 2์์ ์ค์ ๋ก ๋๋ ค๋ดค๋ค.
๐งช ๋ฐํ์ ํ์ธ โ ์๋์ ๋์์ด
์ฌ๊ธฐ๊น์ง๋ ์ ๋ถ ์ ์ ๋ถ์์ด๋ค. ์ค์ ๋ก ๊ทธ๋ ๊ฒ ๋๋์ง ๋ถ์ด์ ๋ณธ๋ค.
set pagination off
set confirm off
# 1) srand() ์ ์ค์ ๋ก ์ด๋ค ์๋๊ฐ ๋ค์ด๊ฐ๋์ง โ ์ ์ ์ผ๋ก ์ฝ์ 0xbeef ๋ฅผ ๋ฐํ์์ผ๋ก ํ์ธ
break srand
run
printf "\n[gdb] srand(0x%x) <- main+0x1f ์ mov edi,0xbeef ๊ฐ ๊ทธ๋๋ก ๋ค์ด์๋ค\n\n", $edi
# 2) ๊ทธ ์๋์์ ๋์ค๋ rand() ์ ์ธ ๊ฐ โ solve.py ์ ctypes ํธ์ถ๊ณผ ๊ฐ์์ผ ํ๋ค
delete 1
break rand
continue
finish
continue
finish
continue
finish
quitgdb -q -batch -x ../verify.gdb ./prob 2>&1 | grep -vE "Missing separate|^Downloading|^Reading|Using host libthread"
์ธ ๊ฐ์ง๊ฐ ํ ํ๋ฉด์์ ํ์ธ๋๋ค.
__srandom (x=48879) โ 48879๋ 0xBEEF๋ค. ์ ์ ์ผ๋ก ์ฝ์ ๊ฐ์ด ๋ฐํ์์๋ ๊ทธ๋๋ก ๋ค์ด๊ฐ๋ค.
rand() ๋ฐํ๊ฐ์ ์์๋๋ก 479531427, 447733150, 1307573299.
๊ทธ๋ฆฌ๊ณ ๋ณต๊ท ์ฃผ์๊ฐ ...66cb, ...6703, ...677a๋ค. PIE ๋ฒ ์ด์ค๋ฅผ ๋นผ๋ฉด 0x26cb, 0x2703, 0x277a โ ๊ฐ๊ฐ i%3==0, 1, 2 ๋ถ๊ธฐ ์์ call rand@plt ๋ฐ๋ก ๋ค์์ด๋ค. ์ธ ๋ถ๊ธฐ๊ฐ ์ธ๋ฑ์ค ์์๋๋ก ๋์๋ฅผ ํ๋์ฉ ๊ฐ์ ธ๊ฐ๋ค๋ ๊ฒ ์คํ์ผ๋ก ํ์ธ๋๋ค.
PIE ๋ฒ ์ด์ค๋ฅผ ๊ด๋ก๋ก ๊ฐ์ ํ์ง ์๊ณ ํ๋ฉด์ ์ฐํ ๋ณต๊ท ์ฃผ์์์ ์ญ์ฐํ๋ค. ๋ฒ ์ด์ค๋ ํ๊ฒฝ์ ๋ฐ๋ผ ๋ฌ๋ผ์ง๋ค.
๐ solve.py
์ญํจ์๋ ๊ทธ๋๋ก ๋ค์ง์ผ๋ฉด ๋๋ค.
i % 3 | ์ํธํ | ๋ณตํธํ |
|---|---|---|
| 0 | rol8((ror8(b,7) + r) & 0xff, 4) | rol8((ror8(c,4) - r) & 0xff, 7) |
| 1 | ror8(b, r & 7) | rol8(c, r & 7) |
| 2 | (b ^ r) - 0x18 | ((c + 0x18) & 0xff) ^ (r & 0xff) |
rand()๋ ๋ค์ ๊ตฌํํ์ง ์์๋ค. glibc์ rand()๋ TYPE_3 ๊ฐ์ฐ ๋๋จน์ ์์ฑ๊ธฐ๋ผ ์์ผ๋ก ์ฎ๊ธฐ๋ฉด ์ด๊ธฐํ 34๋จ๊ณ์ ์๋ฐ์
๊น์ง ์ ํํ ๋ง์ถฐ์ผ ํ๋ค. ํ ๊ตฐ๋ฐ๋ง ํ๋ ค๋ 6๋ฐฑ๋ง ๋ฐ์ดํธ๊ฐ ์ ๋ถ ์ด๊ธ๋๊ณ , ๊ทธ๊ฑธ ๋๋ฒ๊น
ํ ์ด์ ๊ฐ ์๋ค. ctypes๋ก ์์คํ
libc์ ๊ฒ์ ๊ทธ๋๋ก ๋ถ๋ฅธ๋ค.
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
DreamHack photographer (#1998, Silver 3, reversing) โ flag.bmp.enc ๋ณตํธ
prob ๋ flag.bmp ๋ฅผ ํต์งธ๋ก ์ฝ์ด ํ ๋ฐ์ดํธ์ฉ ๋ณํํ ๋ค flag.bmp.enc ๋ก ์ด๋ค.
main(0x24fb) ์ ๊ทธ๋๋ก ์ฎ๊ธฐ๋ฉด ์ด๋ ๋ค.
srand(0xbeef);
for (i = 0; i < v.size(); i++)
switch (i % 3) {
case 0: v[i] = rol8((ror8(v[i], 7) + rand()) & 0xff, 4); break;
case 1: v[i] = ror8(v[i], rand() & 7); break;
case 2: v[i] = (v[i] ^ rand()) - 0x18; break;
}
ror8/rol8 ์ ๊ฐ๊ฐ 0x2489 / 0x24c2 ์ ์๋ ์ธ๋ผ์ธ ์๋ ํฌํผ๋ค.
0x2489: sar edx, cl(n&7) ; shl edx, 8-(n&7) ; or โ ROR8
0x24c2: shl edx, cl(n&7) ; sar edx, 8-(n&7) ; or โ ROL8
์ธ ๋ถ๊ธฐ ๋ชจ๋ ๋ฐ์ดํธ๋น rand() ๋ฅผ ์ ํํ ํ ๋ฒ ๋ถ๋ฅด๋ฏ๋ก ๋์ ์๋น ์์๊ฐ ์ธ๋ฑ์ค ์์์ ๊ฐ๋ค.
์๋๊ฐ 0xbeef ์์๋ผ srand/rand ์์ด์ ์์ ํ ๊ฒฐ์ ์ ์ด๋ค โ time(NULL) ์ด ์๋ค๋ ๊ฒ
`objdump -d` ์ PLT ๋ชฉ๋ก์์ ์ด๋ฏธ ๋ณด์ธ๋ค.
์ญ๋ณํ:
i%3==0: b = rol8((ror8(c, 4) - rand()) & 0xff, 7)
i%3==1: b = rol8(c, rand() & 7)
i%3==2: b = ((c + 0x18) & 0xff) ^ (rand() & 0xff)
rand() ๋ ์ฌ๊ตฌํํ์ง ์๊ณ ctypes ๋ก **libc ์ ๊ฒ์ ๊ทธ๋๋ก** ๋ถ๋ฅธ๋ค. glibc ์ TYPE_3
๊ฐ์ฐ ๋๋จน์ ์์ฑ๊ธฐ๋ฅผ ์์ผ๋ก ์ฎ๊ธฐ๋ค ํ๋ฆฌ๋ฉด ์ ์๊ฐ ์ด๊ธ๋๋๋ฐ, ๊ทธ๊ฑธ ๋๋ฒ๊น
ํ ์ด์ ๊ฐ ์๋ค.
์คํ:
python3 solve.py # extracted/flag.bmp.enc โ flag.bmp
"""
import ctypes
import ctypes.util
from pathlib import Path
HERE = Path(__file__).resolve().parent
ENC = HERE / "extracted" / "flag.bmp.enc"
OUT = HERE / "flag.bmp"
SEED = 0xBEEF
def ror8(b: int, n: int) -> int:
n &= 7
return ((b >> n) | (b << (8 - n))) & 0xFF
def rol8(b: int, n: int) -> int:
n &= 7
return ((b << n) | (b >> (8 - n))) & 0xFF
def main():
libc = ctypes.CDLL(ctypes.util.find_library("c"))
libc.srand(ctypes.c_uint(SEED))
enc = bytearray(ENC.read_bytes())
out = bytearray(len(enc))
for i, c in enumerate(enc):
r = libc.rand()
m = i % 3
if m == 0:
out[i] = rol8((ror8(c, 4) - r) & 0xFF, 7)
elif m == 1:
out[i] = rol8(c, r & 7)
else:
out[i] = ((c + 0x18) & 0xFF) ^ (r & 0xFF)
OUT.write_bytes(bytes(out))
print(f"[*] {ENC.name} {len(enc)} bytes -> {OUT.name}")
print(f"[*] magic : {bytes(out[:2])!r}")
print(f"[*] BITMAPINFO: size={int.from_bytes(out[2:6],'little')} "
f"offset={int.from_bytes(out[10:14],'little')} "
f"w={int.from_bytes(out[18:22],'little')} "
f"h={int.from_bytes(out[22:26],'little')} "
f"bpp={int.from_bytes(out[28:30],'little')}")
if __name__ == "__main__":
main()python3 solve.py && file flag.bmp
BM์ด ๋์์๋ค. ํค๋๊ฐ ์ค์ค๋ก 1920ร1080 24bpp๋ผ๊ณ ๋งํ๊ณ , ์ ์ธํ ํฌ๊ธฐ 6,220,854๊ฐ ์ค์ ํ์ผ ํฌ๊ธฐ์ ์ ํํ ๋ง๋๋ค. ํค๋ ํ๋๋ก ์ด๋ฏธ ๋ณต์์ด ๋ง์๋ค๋ ๊ฑธ ์ ์ ์๋ค.
๐ผ๏ธ ๋์ฐพ์ ์ฌ์ง
python3 render.py
ํ๋๊ทธ๋ ํ์ผ ์ด๋์๋ ๋ฌธ์์ด๋ก ๋ค์ด ์์ง ์๋ค. ์ฌ์ง์ ๊ทธ๋ ค์ ธ ์์ด์ strings๋ก๋ ์ ๋ ์ ๋์จ๋ค. ๊ทธ๋ฆผ์ ๋ณต์ํ๋ ๊ฒ ์์ฒด๊ฐ ๋ฌธ์ ์๋ค.
DH{d85a130283f58035eb327b56e37d2dd087156ba629687a5d52bd4af3c5bfa4f4}โ ๊ฒ์ฆ โ ๋ฌธ์ ๋ฐ์ด๋๋ฆฌ๋ก ๋๋๋ ค ๋ณธ๋ค
๊ทธ๋ฆผ์ด ๋ฉ์ฉกํด ๋ณด์ธ๋ค๊ณ ๋ณตํธ๊ฐ ์ ํํ ๊ฑด ์๋๋ค. 1๋นํธ๋ง ์ด๊ธ๋๋ ๋์ผ๋ก๋ ๊ตฌ๋ถ์ด ์ ๋๋ค.
ํ์คํ ๊ฒ์ฆ์ ๋ฌธ์ ๊ฐ ์ค prob์ ์ค๋ผํด๋ก ์ฐ๋ ๊ฒ์ด๋ค. ๋ณต์ํ flag.bmp๋ฅผ ์๋ ์๋ฆฌ์ ๋๊ณ prob์ ๋๋ ค์, ๋์จ flag.bmp.enc๊ฐ ๋ฐฐํฌ๋ณธ๊ณผ ๋ฐ์ดํธ ๋จ์๋ก ๊ฐ์์ง ๋ณธ๋ค. ๊ฐ๋ค๋ฉด ์ฐ๋ฆฌ ์ญํจ์๊ฐ ์ ํํ ์ญํจ์๋ผ๋ ๋ป์ด๋ค.
cp ../flag.bmp . && ./prob && sha256sum flag.bmp.enc ../extracted/flag.bmp.enc && cmp flag.bmp.enc ../extracted/flag.bmp.enc && echo ROUNDTRIP_OK
ํด์๊ฐ ๊ฐ๋ค. 6,220,854๋ฐ์ดํธ ์ค ํ ๋ฐ์ดํธ๋ ๋ค๋ฅด์ง ์๋ค.
๐ ์ฝ์ง 2 โ sar ์ ๋ถํธ ์๋ ์ํํธ๋ก ์ฎ๊ธฐ๋ฉด
โถ๐ ์ฝ์ง 2 โ ํ์ ํฌํผ๋ฅผ int8_t ๋ก ์ฌ๊ตฌํํ์ ๋
0x2489/0x24c2๋ ํ์ ์ sar(์ฐ์ ์ฐ์ํํธ)๋ก ํ๋ค. ์ด์
๋ธ๋ฆฌ๋ง ํ๊ณ "์ฐ์ ์ด๋๊น ๋ถํธ ํ์ฅ์ด๊ฒ ๊ตฌ๋" ํ๊ณ int8_t๋ก ์ฎ๊ธฐ๋ฉด 0x80 ์ด์ ๋ฐ์ดํธ์์ ๊ฒฐ๊ณผ๊ฐ ์ด๊ธ๋๋ค.
์ค์ ๋ก๋ ๋ฐ๋ก ์์ movzx edx, BYTE PTR [rbp-0x4]๊ฐ ์์ด ์ ํ์ฅ์ ํด ๋๋ค. ๊ทธ๋์ sar์ด๋ shr์ด๋ ๊ฐ๋ค.
ํ๋ฆฐ ๊ฐ์ ๋ง ๋ฃ์ ๋ฒ์ ์ ๋ง๋ค์ด ๋๋ ค ๋ดค๋ค.
def ror8_signed(b: int, n: int) -> int:
n &= 7
s = b - 256 if b & 0x80 else b # โ ์ฌ๊ธฐ๊ฐ ํ๋ฆฐ ๊ฐ์ : ๋ถํธ ์๋ char ๋ก ๋ณธ๋ค
return ((s >> n) | (s << (8 - n))) & 0xFF
def rol8_signed(b: int, n: int) -> int:
n &= 7
s = b - 256 if b & 0x80 else b
return ((s << n) | (s >> (8 - n))) & 0xFFpython3 toy_signed.py && file flag_signed.bmp
ํค๋๊ฐ \xc2M์ด๋ค. file์ ์ฌ์ ํ data๋ผ๊ณ ํ๋ค.
๊ทธ๋ฐ๋ฐ ํฝ์ ์์ญ๋ง ๊ฐ์ ๋ก ๋ ๋ํด ๋ณด๋ฉด ๊ฒฐ๊ณผ๊ฐ ๋ ๊ณ ์ฝํ๋ค.

๊ทธ๋ฆผ์ ๊ฑฐ์ ๋ฉ์ฉกํด ๋ณด์ธ๋ค. ์์ด ์ข ๋ฌผ๋ค๊ณ ์ก์์ด ๋ ์ ๋๋ผ, ํ๋๊ทธ๋ ๊ทธ๋๋ก ์ฝํ๋ค. ์ด ๋ฌธ์ ์์๋ ์ด์ฐจํผ ๋ต์ ์ป๋๋ค.
๋ฌธ์ ๋ "๋์ผ๋ก ๋ดค์ ๋ ๊ทธ๋ด๋ฏํ๋ฉด ๋ง๋ค"๊ณ ๋์ด๊ฐ๋ ์ต๊ด์ด๋ค. ์๋ณธ BMP๊ฐ ๋๋ถ๋ถ 00๊ณผ ff๋ผ์ ๋ถํธ ํ์ฅ์ ์ํฅ์ ๋ ๋ฐ์์ ๋ฟ, ์ฌ์ง์ด ์กฐ๊ธ๋ง ๋ณต์กํ์ผ๋ฉด ์์๋ณด๊ธฐ ์ด๋ ค์ ์ ๊ฒ์ด๋ค. ํค๋๊ฐ BM์ธ์ง, ์๋ณต ํด์๊ฐ ๋ง๋์ง โ ๊ธฐ๊ณ๊ฐ ํ์ ํ ์ ์๋ ๊ธฐ์ค์ ํ๋๋ ๋๋ ๊ฒ ๋ง๋ค.
๐งฐ ์ฌํ ํ๊ฒฝ
| ํญ๋ชฉ | ๊ฐ |
|---|---|
| OS | Ubuntu 25.10 (x86-64) |
| glibc | 2.42 โ ctypes๋ก ๋ถ๋ฅด๋ rand()๊ฐ ์ด๊ฒ์ด๋ค |
| Python | 3.13.7 (ํ์ค ctypes๋ง ์ฌ์ฉ, ์ด๋ฏธ์ง ๋ ๋๋ง์๋ง Pillow 10.4.0) |
| binutils | objdump 2.45 |
| gdb | 16.3 (-batch ๋ชจ๋) |
| ๋ฐฐํฌ๋ฌผ sha256 | flag.bmp.enc โ 83266dde8aea8e67db2e97af066a843f263604b2cde6be0c16317d53d78a02f3 |
์์
ํด๋ ๊ตฌ์ฑ์ ์ด๋ ๋ค. ๋์ค์ด์
๋ธ ์บก์ณ์ ๋ถ์ธ ์ฃผ์์ sed ๊ท์น ํ์ผ๋ก ๋จ๊ฒจ ๋๋ค.
photographer/
โโโ extracted/ # ๋ฐฐํฌ๋ฌผ (prob, flag.bmp.enc)
โโโ solve.py # ๋ณตํธ โ flag.bmp ์์ฑ
โโโ toy_signed.py # ์ฝ์ง 2 ์ฌํ (๋ถํธ ํ์ฅ ๋ฒ์ )
โโโ render.py # flag.bmp โ ๋ธ๋ก๊ทธ์ฉ PNG
โโโ verify.gdb # gdb ๋ฐํ์ ํ์ธ ์คํฌ๋ฆฝํธ
โโโ annot_*.sed # objdump ์ถ๋ ฅ ์ฃผ์ ๊ท์น
โโโ roundtrip/ # prob ์ ์ค๋ผํด๋ก ์ฐ๋ ์๋ณต ๊ฒ์ฆctypes๋ก libc rand()๋ฅผ ๋ถ๋ฅด๋ ๋ฐฉ์์ glibc ๊ณ์ด์ด๋ฉด ์ด๋์๋ ๊ฐ์ ์์ด์ด ๋์จ๋ค. musl(Alpine)์ rand() ๊ตฌํ์ด ๋ฌ๋ผ ๊ฐ์ด ์ด๊ธ๋๋, ์ปจํ
์ด๋๋ก ๋๋ฆฐ๋ค๋ฉด ๋ฐ๋น์ยท์ฐ๋ถํฌ ๊ณ์ด ์ด๋ฏธ์ง๋ฅผ ์ฐ๋ ๊ฒ ๋ง๋ค.
๐ ๊ฒฐ๋ก
์๋๊ฐ ์์๋ฉด ๋์๋ ๋์๊ฐ ์๋๋ค.
rand()๊ฐ ๋ณด์ธ๋ค๊ณ ๊ฒ๋จน์ ๊ฒ ์๋๋ผ srand()์ ๋ญ๊ฐ ๋ค์ด๊ฐ๋์ง๋ถํฐ ๋ณธ๋ค. time(NULL)์ด๋ฉด ์๊ฐ์ ๋ธ๋ฃจํธํฌ์คํด์ผ ํ์ง๋ง, ์์๋ฉด ๊ทธ๋ฅ ๊ฐ์ ์์ด์ ๋ค์ ๋ฝ์ผ๋ฉด ๋์ด๋ค. ์ด ๋ฌธ์ ๋ time@plt๊ฐ ์๋ค๋ ๊ฒ๋ง์ผ๋ก PLT ๋ชฉ๋ก ๋จ๊ณ์์ ์ด๋ฏธ ๋ต์ ์ ๋ฐ์ด ๋์๋ค.
๋์ ์๋น ํ์๊ฐ ๋ถ๊ธฐ๋ง๋ค ๊ฐ์์ง ํ์ธํ๋ค.
์ธ ๊ฐ๋ ์ค ํ๋๋ผ๋ rand()๋ฅผ ๋ ๋ฒ ๋ถ๋ฅด๊ฑฐ๋ ๊ฑด๋๋ฐ์๋ค๋ฉด ์ธ๋ฑ์ค์ ๋์์ ๋์์ด ๊นจ์ ธ์, ์๋น ์์๋ฅผ ๋ฐ๋ก ์๋ฎฌ๋ ์ด์
ํด์ผ ํ๋ค. ๋ถ๊ธฐ๋ง๋ค ์ ํํ ํ ๋ฒ์ฉ์ด๋ผ for ํ ์ค๋ก ๋๋ฌ๋ค. ์ญ์ฐ ์คํฌ๋ฆฝํธ๋ฅผ ์ง๊ธฐ ์ ์ ์ด๊ฑธ ๋จผ์ ์ธ์ด ๋ณด๋ ๊ฒ ์์๋ค.
์ด์ ๋ธ๋ฆฌ๋ฅผ ๊ณ ๊ธ ์ธ์ด๋ก ์ฎ๊ธธ ๋๋ ํญ๊ณผ ๋ถํธ๋ฅผ ๊ฐ์ด ์ฎ๊ธด๋ค.
sar๋ง ๋ณด๊ณ ๋ถํธ ํ์ฅ์ ๋ฃ์ผ๋ฉด ์ด๊ธ๋๊ณ , ์์ movzx๊น์ง ๋ด์ผ ์ ํ์ฅ์ธ ๊ฑธ ์๋ค. ์ ์ฅ์ด mov BYTE PTR์ด๋ฉด ์์ ๋นํธ๋ ๋ฒ๋ ค์ง๋ค๋ ๊ฒ๋ ๋ง์ฐฌ๊ฐ์ง๋ค. ์ํํธยท์ฐ์ ์ ์ฎ๊ธธ ๋ ์ ์ผ ์์ฃผ ์๋ ๊ณณ์ด๋ค.
๋ณต์๋ฌผ์ ๋์ด ์๋๋ผ ๊ธฐ๊ณ๋ก ํ์ ํ๋ค.
๋ถํธ ํ์ฅ ๋ฒ์ ๋ ํ๋๊ทธ๋ ์ฝํ๋ค. ๋์ผ๋ก ํต๊ณผ์์ผฐ์ผ๋ฉด ํ๋ฆฐ ์ฝ๋๋ฅผ ๋ง๋ค๊ณ ๋ฏฟ์ ์ฑ ๋์ด๊ฐ์ ๊ฒ์ด๋ค. ์ฌ๊ธฐ์ ๋ฌธ์ ๋ฐ์ด๋๋ฆฌ ์์ฒด๊ฐ ์ค๋ผํด์ด ๋์ด ์ค๋ค โ ๋ณต์๋ณธ์ ๋ค์ ๋ฃ์ด ๋ฐฐํฌ๋ณธ๊ณผ ํด์๊ฐ ๊ฐ์์ง ๋ณด๋ฉด ๋ ผ์์ ์ฌ์ง๊ฐ ์๋ค. ์ผ๋ฐฉํฅ ๋ณํ๊ธฐ๋ฅผ ์ฃผ๋ ๋ฆฌ๋ฒ์ฑ ๋ฌธ์ ๋ผ๋ฉด ๋์ฒด๋ก ์ธ ์ ์๋ ๋ฐฉ๋ฒ์ด๋ค.
๋ฐฉ์ด ๊ด์ ์์๋ ์ด ๊ตฌ์กฐ ์ ์ฒด๊ฐ ์ํธ๊ฐ ์๋๋ค.
ํค๊ฐ ๋ฐ์ด๋๋ฆฌ ์์ ์์๋ก ๋ฐํ ์๊ณ , ๋ณํ์ด ๋ฐ์ดํธ ๋จ์๋ก ๊ฐ์ญ์ด๋ฉฐ, ๋ณํ๊ธฐ ์์ฒด๋ฅผ ํจ๊ป ๋ฐฐํฌํ๋ค. ์ ์ค ํ๋๋ง ์์ด๋ ๊ธฐ๋ฐ์ฑ์ ์๋ค. ํ์ผ์ ์ค์ ๋ก ๋ณดํธํ ์๊ฐ์ด๋ผ๋ฉด ๊ฒ์ฆ๋ AEAD(AES-GCM, ChaCha20-Poly1305)์ ์ธ๋ถ์์ ์ฃผ์ ํ ํค๋ฅผ ์ฐ๋ ๊ฒ ๋ง๊ณ ๋ค๋ฅธ ๋ต์ ์๋ค. ์ง์ ๋ง๋ ๋ฐ์ดํธ ๋ณํ์ ๋๋ ํ์ง ์ํธ๊ฐ ์๋๋ค.
Comments
๋๊ธ
๋๊ธ์ ๋จ๊ธฐ๋ ค๋ฉด ๋ก๊ทธ์ธ์ด ํ์ํด์. (๋ค์ด๋ฒ ยท ๊ตฌ๊ธ ๊ณ์ )
๋๊ธ ๋ถ๋ฌ์ค๋ ์คโฆ