๋ ๋ํ ยท AI ์๋ํ ยท ์์คํ
์์ง๋์ด๋ง
์ง์ ๋ง๋ค๊ณ , ์คํํ๊ณ , ๊ธฐ๋กํ๋ค
ยฉ 2026 ZINO LAB
[๐ฑ ์์น] ๋ฐ์ดํธ ๋จ์ ROT128 ๋ณตํธ โ DreamHack ROT128 ํ์ด โ ZINO
2026-06-08 ยท 1๋ถ ์ฝ๊ธฐ ยท
flag.png๋ฅผ ์ํธํํด encfile๋ก ๋จ๊ธด rot128.py๋ฅผ ๋ถ์ํ๋ค. ๊ฐ ๋ฐ์ดํธ์ +128 mod 256์ ์ ์ฉํ๊ณ 2์๋ฆฌ 16์ง์ ํ
์คํธ๋ก ์ด์ด๋ถ์ธ ๋จ์ ์นํ์ด๋ฉฐ, 128์ ๋ ๋ฒ ๋ํ๋ฉด ์๋๋๋ก ๋์์ค๋ ์๊ธฐ์ญ์์ด๋ค. ๊ฐ์ ์ฐ์ฐ์ ํ ๋ฒ ๋ ๋๋ ค PNG๋ฅผ ๋ณต์ํ๊ณ ํ๋๊ทธ๋ฅผ ์ฝ๋๋ค.
๋ฌธ์ : DreamHack โ ROT128
๋ถ๋ฅ : Crypto
๋์ด๋ : ๐ฑ ์์น
FLAG : DH{y0u_So1ved_basic_cryp7o_How_wa5_1t?}
์ํธํ ์์ค rot128.py ์ ๊ฒฐ๊ณผ๋ฌผ encfile ๋ง ์ฃผ์ด์ง๋ค. ์ ์ ํ๋ฌธ์ธ flag.png ๋ ์๋ค. ์์ค๋ฅผ ์ฝ๊ณ ์ฐ์ฐ์ ๊ฑฐ๊พธ๋ก ๋๋ ค PNG๋ฅผ ๋ณต์ํ ๋ค, ์ด๋ฏธ์ง ์์ ์ ํ ํ๋๊ทธ๋ฅผ ๋์ผ๋ก ์ฝ๋ ๋ฌธ์ ๋ค.
๋ฌธ์ ๊ฐ์
ํญ๋ชฉ ๋ด์ฉ ๋ฌธ์ ๋ช
ROT128 ๋์ด๋ ๐ฑ ์์น ๋ถ๋ฅ Crypto ์ ๊ณต ํ์ผ rot128.py (์ํธํ ์์ค), encfile (์ํธ๋ฌธ)๋ชฉํ encfile ๋ณตํธ โ flag.png ๋ณต์ โ ํ๋๊ทธ ํ๋ํต์ฌ ๊ธฐ๋ฒ ๋ฐ์ดํธ +128 mod 256 ์นํ + 16์ง์ ํ
์คํธ ์ธ์ฝ๋ฉ, ์๊ธฐ์ญ์
์ด๋ฆ์ด ROT128์ด๋ผ ์ ๋ฐ์ ๋ต์ ์๋ ค์ฃผ๊ณ ์์ํ๋ค. ์ํ๋ฒณ์ 13์นธ ๋๋ฆฌ๋ ROT13์ ๋ฐ์ดํธ ๋ฒ์ ์ธ๋ฐ, ํ์ ๋์ด 128์ด๋ผ๋ ์ ์ด ํฌ์ธํธ๋ค. 256์ ์ ๋ฐ์ด๋ผ ๋ ๋ฒ ๋๋ฆฌ๋ฉด ์ ์๋ฆฌ๋ก ์จ๋ค.
๐ฌ ์ ์ฐฐ โ ๋ฌด์์ ๋ฐ์๋
์์ถ์ ํ๋ฉด ํ์ผ์ ๋๋ฟ์ด๋ค. ๋จผ์ ๋ก ์ฑ๊ฒฉ๋ถํฐ ๋ณธ๋ค.
์ด ๊ธ์ด ๋์์ด ๋๋์?
๐ฅ ํต์ฌ ๐ก ์ธ์ฌ์ดํธ ๐ ์ข์์ ๐คฏ ์ถฉ๊ฒฉ โก ๋น ๋ฆ
file
์ ๊ณต ํ์ผ ํ์ธ โ encfile์ ๋ฐ์ด๋๋ฆฌ๊ฐ ์๋๋ผ ASCII ํ
์คํธ
encfile ์ด ๋ฐ์ด๋๋ฆฌ๊ฐ ์๋๋ผ ASCII ํ
์คํธ , ๊ทธ๊ฒ๋ ์ค๋ฐ๊ฟ ์๋ ์์ฃผ ๊ธด ํ ์ค์ด๋ผ๋ ๊ฒ ์ฒซ ๋จ์๋ค. PNG๋ฅผ ์ํธํํ๋ค๋๋ฐ ๊ฒฐ๊ณผ๊ฐ ํ
์คํธ๋ผ๋ฉด, ๋ฐ์ดํธ๋ฅผ ๊ทธ๋๋ก ์ ์ฅํ ๊ฒ ์๋๋ผ ์ด๋ค ์์ผ๋ก๋ ๋ฌธ์๋ก ์ธ์ฝ๋ฉํ๋ค๋ ๋ป์ด๋ค.
์์ค๋ฅผ ์ด์ด ๋ณด๋ฉด ํ๋ฆ์ด ๊ทธ๋๋ก ๋๋ฌ๋๋ค.
#!/usr/bin/env python3
hex_list = [( hex (i)[ 2 :]. zfill ( 2 ). upper ()) for i in range ( 256 )]
with open ( 'flag.png' , 'rb' ) as f:
plain_s = f. read ()
plain_list = [ hex (i)[ 2 :]. zfill ( 2 ). upper () for i in plain_s]
enc_list = list ( range ( len (plain_list)))
for i in range ( len (plain_list)):
hex_b = plain_list[i]
index = hex_list. index (hex_b)
enc_list[i] = hex_list[(index + 128 ) % len (hex_list)]
enc_list = '' . join (enc_list)
with open ( 'encfile' , 'w' , encoding = 'utf-8' ) as f:
f. write (enc_list)
hex_list ๋ '00', '01', ..., 'FF' โ 0๋ถํฐ 255๊น์ง๋ฅผ 2์๋ฆฌ ๋๋ฌธ์ 16์ง์ ๋ฌธ์์ด๋ก ๋ง๋ 256์นธ ํ๋ค. ์ธ๋ฑ์ค i ์ ๊ฐ์ด ๊ณง hex(i) ์ด๋ฏ๋ก hex_list.index('XX') == 0xXX , ์ฆ ์ด ํ์์ ์ด๋ค 16์ง์ ๋ฌธ์์ด์ ์ธ๋ฑ์ค๋ ๊ทธ ๋ฐ์ดํธ ๊ฐ ์์ฒด๋ค.
plain_list ๋ flag.png ์ ๊ฐ ๋ฐ์ดํธ๋ฅผ ๊ฐ์ ํ์์ 16์ง์ ๋ฌธ์์ด๋ก ๋ฐ๊พผ ๊ฒ.
ํต์ฌ ๋ฃจํ: ๋ฐ์ดํธ ํ๋๋ฅผ ๊ณจ๋ผ index (= ๊ทธ ๋ฐ์ดํธ ๊ฐ)๋ฅผ ๊ตฌํ๊ณ , (index + 128) % 256 ์์น์ 16์ง์ ๋ฌธ์์ด๋ก ๋ฐ๊ฟ ๋ด๋๋ค.
๋ง์ง๋ง์ ๊ตฌ๋ถ์ ์์ด ์ ๋ถ ์ด์ด๋ถ์ฌ ํ
์คํธ๋ก ์ ์ฅ.
์ ๋ฆฌํ๋ฉด ์ํธํ๋ ๋ฑ ํ ์ค๋ก ์์ถ๋๋ค. ๊ฐ ๋ฐ์ดํธ b ๋ฅผ (b + 128) % 256 ์ผ๋ก ๋ฐ๊พผ ๋ค 2์๋ฆฌ ๋๋ฌธ์ 16์ง์๋ก ์ ์ด ์ด์ด๋ถ์ธ๋ค. index ๊ณ์ฐ์ด๋ hex_list ๋ ๊ทธ ํ ์ค์ ๋น ๋๋ฌ ํํํ ๊ฒ์ผ ๋ฟ์ด๋ค.
๐ง ์ํธ ๋ถ์ โ ROT128์ ์ ์ฒด encfile ์ ์ง์ ํ ๋ฒ ๋ค์ฌ๋ค๋ณด๋ฉด ๋ถ์์ด ๋ง๋์ง ๋ฐ๋ก ํ์ธ๋๋ค.
#!/usr/bin/env python3
# encfile ๊ตฌ์กฐ ์ ์ฐฐ โ ๋ฌด์์ด ๋ค์ด ์๋์ง ๋จผ์ ํ์ธ
enc = open ( 'encfile' ). read ()
print ( f "length : { len (enc) } " )
print ( f "length % 2 : { len (enc) % 2} " )
print ( f "charset : { '' . join ( sorted ( set (enc))) } " )
print ( f "head (40) : { enc[: 40 ] } " )
print ( f "tail (40) : { enc[ - 40 :] } " )
vals = [ int (enc[i:i + 2 ], 16 ) for i in range ( 0 , len (enc), 2 )]
print ( f "pairs : { len (vals) } " )
print ( f "min / max : { min (vals) } / { max (vals) } " ) encfile ์ ์ฐฐ โ 0~F 16์ง์๋ง, ๊ธธ์ด ์ง์, 74405 ํ์ด
๋ฌธ์ ์ข
๋ฅ๋ 0123456789ABCDEF ๋ฟ์ด๊ณ ๊ธธ์ด๋ ์ง์(148,810)๋ค. 2๊ธ์๊ฐ ํ ๋ฐ์ดํธ์ด๋ ํ๋ฌธ์ 148810 / 2 = 74,405 ๋ฐ์ดํธ. ๊ฐ์ ๋ฒ์๋ 0~255 ์ ์ฒด์ ๊ฑธ์ณ ์์ด, ์์๋๋ก ์ผ๋ฐ์ ์ธ ๋ฐ์ด๋๋ฆฌ(PNG)๋ฅผ ๋ฐ์ดํธ ๋จ์๋ก ์ธ์ฝ๋ฉํ ๋ชจ์ต์ด๋ค.
์ด์ ๋ณตํธ๋ค. ํ์ ๋์ด 128์ด๋ผ๋ ๊ฒ ์ด ๋ฌธ์ ์ ์ ๋ถ๋ค.
(b + 128) + 128 = b + 256 โก b (mod 256) 128์ ๋ ๋ฒ ๋ํ๋ฉด 256์ด ๋๊ณ , 256์ ๋ชจ๋๋ฌ 256์์ 0์ด๋ค. ์ฆ ์ํธํ ํจ์๊ฐ ๊ณง ๋ณตํธํ ํจ์ ๋ค. ํค๋ ์ญ์ฐ์ฐ๋ ๋ฐ๋ก ํ์ ์์ด, ์ํธ๋ฌธ ๋ฐ์ดํธ์ ๋ค์ +128 mod 256 ์ ์ ์ฉํ๋ฉด ํ๋ฌธ์ผ๋ก ๋์์จ๋ค. ์ด๋ฐ ์ฑ์ง์ ์๊ธฐ์ญ์(involution)์ด๋ผ ๋ถ๋ฅธ๋ค โ ROT13์ ๋ ๋ฒ ์ ์ฉํ๋ฉด ์๋ฌธ์ด ๋๋ ๊ฒ๊ณผ ๊ฐ์ ์ด์น๋ค.
๊ฐ์ฅ ๊น๋ํ ๊ฒ์ฆ์ PNG ์๊ทธ๋์ฒ๋ค. PNG๋ ํญ์ 89 50 4E 47 ๋ก ์์ํ๋ค. ๊ทธ๋ ๋ค๋ฉด encfile ์ ๋งจ ์ ๋ฐ์ดํธ๋ 0x89 ์ 128์ ๋ํ ๊ฐ์ด์ด์ผ ํ๋ค.
๋ฐ์ดํธ ํ ๊ฐ์ ์๋ณต โ 0x89 โ 0x09, encfile ์ฒซ ํ์ด๊ฐ 09
0x89 (137) + 128 = 265, 256์ ๋นผ๋ฉด 9 = 0x09 . ๊ทธ๋ฆฌ๊ณ ์ ์ฐฐ ์ถ๋ ฅ์ head ๋ฅผ ๋ณด๋ฉด encfile ์ ์ ํํ 09D0... ๋ก ์์ํ๋ค. ์ฒซ ํ์ด๊ฐ 09 ๋ผ๋ ์ฌ์ค ํ๋๋ก "์ด ํ์ผ์ PNG๋ฅผ ROT128ํ ๊ฒ"์ด๋ผ๋ ๊ฐ์ค์ด ๋ง์๋จ์ด์ง๋ค.
๐ฏ ๋ณตํธ โ ๊ฐ์ ์ฐ์ฐ์ ํ ๋ฒ ๋ ๋ถ์ํ ๊ทธ๋๋ก ์ฎ๊ธฐ๋ฉด ๋ณตํธ ์คํฌ๋ฆฝํธ๋ ์งง๋ค. 2๊ธ์์ฉ ๋์ด ์ ์๋ก ๋ง๋ค๊ณ , +128 mod 256 ์ ๋๋ ค ๋ฐ์ดํธ๋ก ์ด๋ค.
#!/usr/bin/env python3
# ROT128 ๋ณตํธ: ์ํธํ๋ ๊ฐ ๋ฐ์ดํธ b -> (b+128)%256 ์ 2์๋ฆฌ ๋๋ฌธ์ hex๋ก ์ด์ด๋ถ์.
# 128์ ๋ ๋ฒ ๋ํ๋ฉด 256โก0 ์ด๋ฏ๋ก, ๋ณตํธ๋ ๋๊ฐ์ด +128 ํ๋ฉด ์๋ณธ์ด ๋ณต์๋๋ค(์๊ธฐ์ญ์).
enc = open ( 'encfile' ). read (). strip ()
# encfile์ 16์ง์ ๋ฌธ์๋ง ๊ธธ์ด ์ง์ -> 2๊ธ์์ฉ ํ ๋ฐ์ดํธ
enc_bytes = [ int (enc[i:i + 2 ], 16 ) for i in range ( 0 , len (enc), 2 )]
dec_bytes = bytes ((b + 128 ) % 256 for b in enc_bytes)
open ( 'flag.png' , 'wb' ). write (dec_bytes)
print ( f "enc text length : { len (enc) } " )
print ( f "decoded bytes : { len (dec_bytes) } " )
print ( f "first 8 bytes : { dec_bytes[: 8 ]. hex () } " )
print ( f "is PNG signature: { dec_bytes[: 8 ] == bytes . fromhex ( '89504e470d0a1a0a' ) } " ) ๋ณตํธ ์คํ โ 74405๋ฐ์ดํธ ๋ณต์, PNG ์๊ทธ๋์ฒ ์ผ์น
๋ณต์ํ 8๋ฐ์ดํธ๊ฐ 89504e470d0a1a0a โ PNG์ ํ์ค ์๊ทธ๋์ฒ(\x89PNG\r\n\x1a\n )์ ์ ํํ ์ผ์นํ๋ค. ํ์ผ ๋ช
๋ น์ผ๋ก๋ ๋ค์ ํ์ธํ๋ค.
file flag.png โ ์ ์ PNG๋ก ์ธ์, 1792ร848
๊นจ์ง ์กฐ๊ฐ์ด ์๋๋ผ ํค๋๋ถํฐ IEND๊น์ง ์จ์ ํ 1792ร848 RGB PNG๋ค. ๋ณตํธ๊ฐ ํ ๋ฐ์ดํธ๋ ์ด๊ธ๋์ง ์์๋ค๋ ๋ป์ด๋ค.
๐ฉ ํ๋๊ทธ ๋ณต์ํ flag.png ๋ฅผ ์ด๋ฉด ํ๋๊ทธ๊ฐ ๊ทธ๋๋ก ์ ํ ์๋ค.
๋ณต์๋ flag.png โ ํ๋๊ทธ๊ฐ ์ด๋ฏธ์ง์ ์ ํ ์๋ค
DH{y0u_So1ved_basic_cryp7o_How_wa5_1t?}
๐ ๊ฒฐ๋ก ์ด๋ฆ์ด ํ์ด์ ์ ๋ฐ์ด์๋ค.
ROT128์ ํ์ ๋ 128์ด 256์ ์ ๋ฐ์ด๋ผ ๋ ๋ฒ ์ ์ฉํ๋ฉด ์ ์๋ฆฌ๋ก ๋์์จ๋ค. ๊ทธ๋์ ํค๋ ์ญ์ฐ์ฐ๋ ๋ฐ๋ก ํ์ ์์ด, ์ํธํ์ ์ด ์ฝ๋๋ฅผ ๊ทธ๋๋ก ํ ๋ฒ ๋ ๋๋ฆฌ๋ฉด ๋ณตํธ๊ฐ ๋๋ค.
์ํธ๋ฌธ์ด ํ
์คํธ๋ผ๋ ๋จ์๋ฅผ ๋จผ์ ์ฝ๋ ๊ฒ ์ค์ํ๋ค.
file ๋ก ๋ณธ "ASCII text"์ ์ ์ฐฐ์ 0-9A-F charset์ด "๋ฐ์ดํธ๋ฅผ 16์ง์ ๋ฌธ์์ด๋ก ์ธ์ฝ๋ฉํ๋ค"๋ ๊ตฌ์กฐ๋ฅผ ์๋ ค์คฌ๋ค. ๊ฑฐ๊พธ๋ก 2๊ธ์๋ฅผ ํ ๋ฐ์ดํธ๋ก ๋ฌถ๋ ๋์ฝ๋ฉ ๋จ๊ณ๋ฅผ ๋นผ๋จน์ผ๋ฉด ๋ณตํธ๊ฐ ์ด๊ธ๋๋ค. PNG ์๊ทธ๋์ฒ(89 50 4E 47 )๋ ์ด๋ฐ ๋ณต์์ด ๋ง๋์ง ํ์ธํ๋ ๊ฐ์ฅ ๋น ๋ฅธ ๊ธฐ์ค์ ์ด๋ค.
๋ฐฉ์ด ๊ด์ . ์ด ๋ฌธ์ ์ ํต์ฌ์ ํค ์๋ ๊ณ ์ ์นํ์ด๋ผ๋ ๋ฐ ์๋ค. ํค๊ฐ ์์ผ๋ ๋๊ตฌ๋ ๋์ผํ ์ญ์ฐ์ฐ์ผ๋ก ์๋ฌธ์ ๋๋๋ฆด ์ ์๊ณ , +128 ๊ฐ์ ๋จ์ ์ํํธ๋ ์๊ธฐ์ญ์์ด๋ผ ๋ถ์ ๊ฐ์น๋ ์๋ค. ์ค์ ๊ธฐ๋ฐ์ ๋ค๋ฃฌ๋ค๋ฉด ๊ฒ์ฆ๋ ๋์นญํค ์ํธ(AES-GCM ๋ฑ)์ ์ถฉ๋ถํ ๊ธธ์ด์ ๋น๋ฐ ํค๋ฅผ ์จ์ผ ํ๋ฉฐ, ROT ๊ณ์ดยทXOR ๋จ์ผ ๋ฐ์ดํธยท๋จ์ ์ํํธ๋ ๋๋
ํ์ผ ๋ฟ ์ํธ๊ฐ ์๋๋ผ๋ ์ ์ ๊ธฐ์ตํ๋ฉด ๋๋ค.
+3
Comments
๋๊ธ
๋๊ธ์ ๋จ๊ธฐ๋ ค๋ฉด ๋ก๊ทธ์ธ์ด ํ์ํด์. (๋ค์ด๋ฒ ยท ๊ตฌ๊ธ ๊ณ์ )
๋๊ธ ๋ถ๋ฌ์ค๋ ์คโฆ