๋ฌธ์ : DreamHack โ ByteCaesar ๋ถ๋ฅ: Crypto ๋์ด๋: ๐ฑ ์์น FLAG:
DH{37bdfc823523deca663c737a6c6e24fc561da4dd515f097cf8a48d417a3fb4ca}
prob.py, secret, output.txt ์ธ ํ์ผ์ด ์ฃผ์ด์ง๋ค. prob.py๋ ์ด๋ค ๋ฌธ์ฅ์ ๋ฐ์ดํธ ๋จ์ Caesar ์ํธ๋ก ๋ฐ์ด output.txt์ hex๋ก ์ถ๋ ฅํ๋ค. ํค๋ ์คํํ ๋๋ง๋ค ๋๋ค์ผ๋ก ๋ฝํ์ง๋ง, 1~255 ์ฌ์ด์ ํ ๋ฐ์ดํธ๋ผ ๊ฒฝ์ฐ์ ์๊ฐ ๊ณ ์ 255๊ฐ๋ค. ์ ์์กฐ์ฌ๋ก ๊ธ๋ฐฉ ๋ซ๋ฆฐ๋ค.

๋ฌธ์ ๊ฐ์
| ํญ๋ชฉ | ๋ด์ฉ |
|---|---|
| ๋ฌธ์ ๋ช | ByteCaesar |
| ๋์ด๋ | ๐ฑ ์์น |
| ๋ถ๋ฅ | Crypto |
| ์ ๊ณต ํ์ผ | prob.py, secret(๊ฐ์ง), output.txt(์ํธ๋ฌธ) |
| ๋ชฉํ | ๋ฐ์ดํธ Caesar ์ํธ๋ฌธ ๋ณตํธ |
| ํต์ฌ ๊ธฐ๋ฒ | ํค ๊ณต๊ฐ(255๊ฐ) ์ ์์กฐ์ฌ |
ํค๊ฐ ๋๋ค์ด๋ผ๋ ํ ๋ฐ์ดํธ๋ฟ์ด๋ผ ๋ธ๋ฃจํธํฌ์ค๊ฐ ์ฆ์ ํตํ๋ค.
๋ฐฐ๊ฒฝ โ ๋ฐ์ดํธ ๋จ์ Caesar cipher
Caesar cipher๋ ๊ธ์๋ฅผ ์ผ์ ์นธ์๋งํผ ๋ฏธ๋ ์นํ ์ํธ๋ค. ๋ณดํต์ ์ํ๋ฒณ 26์ ์์์ ๋ฐ์ง๋ง, ์ด ๋ฌธ์ ๋ ๋ฐ์ดํธ ์ ์ฒด(0~255) ๋ฅผ ๋์์ผ๋ก ๋ฏผ๋ค.
- ์ํธํ:
enc[i] = (secret[i] + key) % 256 - ๋ณตํธํ:
dec[i] = (enc[i] - key) % 256
์ฌ๊ธฐ์ ํต์ฌ์ ํค๊ฐ ํ ๋ฐ์ดํธ๋ผ๋ ์ ์ด๋ค. ์ํ๋ฒณ Caesar๊ฐ ํค 25๊ฐ์ง๋ฟ์ด๋ผ ์ฝ๊ฒ ๋ซ๋ฆฌ๋ฏ, ๋ฐ์ดํธ Caesar๋ ํค๊ฐ 255๊ฐ์ง(1~255)๋ฟ์ด๋ผ ์ ๋ถ ๋์ ํด ๋ณด๋ฉด ๋๋ค. ๋๋ค์ผ๋ก ๋ฝ์๋ค๋ ์ฌ์ค์ ์๋ฌด ๋ฐฉ์ด๊ฐ ๋์ง ์๋๋ค โ ์ด์ฐจํผ ๋ค ์ธ์ด ๋ณผ ์ ์์ผ๋๊น.
์ ์์กฐ์ฌ์์ "๋ง๋ ํค"๋ฅผ ์ด๋ป๊ฒ ์์๋ณผ๊น? ์๋ฌธ์ด ์ฝ์ ์ ์๋ ๋ฌธ์ฅ(ASCII)์ด๋ผ๋ ๊ฑธ ์ด์ฉํ๋ค. ์๋ชป๋ ํค๋ก ๋ณตํธํ๋ฉด ์ ์ด๋ฌธ์ยท๊นจ์ง ๋ฐ์ดํธ๊ฐ ์์ฌ ๋์ค๊ณ , ๋ง๋ ํค๋ก๋ง ์ ๋ถ ์ธ์ ๊ฐ๋ฅํ ASCII๊ฐ ๋์จ๋ค. ์ฌ๊ธฐ์ "ํ๋๊ทธ ํ์ DH{๊ฐ ํฌํจ๋๋๊ฐ"๊น์ง ์กฐ๊ฑด์ผ๋ก ๊ฑธ๋ฉด ์ ๋ต ํค๊ฐ ์ ์ผํ๊ฒ ๊ฑธ๋ฆฐ๋ค.
๐ฌ ์ ์ฐฐ โ ์์ค์ ๊ฐ์ง secret
prob.py๋ ์งง๋ค. ๋๋ค ํค๋ก secret ํ์ผ์ ๋ฐ์ดํธ Caesar ์ํธํํด hex๋ก ์ถ๋ ฅํ๋ค.
class Caesar:
def __init__(self, key):
assert isinstance(key, int) and 1 <= key <= 255
self._key = key
def encrypt(self, msg):
return bytes([(b + self._key) % 256 for b in msg])
key = random.randint(1, 255) # ํค๋ 1~255 ๋๋ค ํ ๋ฐ์ดํธ
secret_enc = Caesar(key).encrypt(open("secret","rb").read())
print(f"my encrypted sentence > {secret_enc.hex()}")
์ฃผ์ํ ํจ์ ์ด ํ๋ ์๋ค. ํจ๊ป ์ฃผ์ด์ง secret ํ์ผ์ ์ด์ด ๋ณด๋ฉด ์ง์ง ํ๋๊ทธ๊ฐ ์๋๋ผ ๊ฐ์ง๋ค.

secret ํ์ผ ๋ด์ฉ์ "This is not real flag, DH{FAKE_FLAG} :>" โ ๋๋๊ณ ๊ฐ์ง๋ค. ์ง์ง ์ํธ๋ฌธ์ output.txt์ hex๋ฟ์ด๋, ๊ทธ๊ฑธ ๋ณตํธํด์ผ ํ๋ค.
๐ฃ ํต์ฌ โ 255๊ฐ ํค๋ฅผ ์ ๋ถ ๋์
output.txt์ ์ํธ๋ฌธ์ 1๋ถํฐ 255๊น์ง ๋ชจ๋ ํค๋ก ๋ณตํธํ๋ฉด์, ๊ฒฐ๊ณผ๊ฐ ์ ๋ถ ์ธ์ ๊ฐ๋ฅํ๊ณ DH{๋ฅผ ํฌํจํ๋ ํค๋ฅผ ์ฐพ๋๋ค.

ํค๊ฐ ํ๋๋ง ์ด๊ธ๋๋ ๊ฒฐ๊ณผ๊ฐ ํ ๋ฌ๋ผ์ง๋ค. key=177์ด๋ฉด "Uif tvoโฆ"์ฒ๋ผ ํ ์นธ์ฉ ๋ฐ๋ฆฐ ๊ธ์๊ฐ ๋์ค๊ณ , key=178์์ ๋น๋ก์ "The sun slowly sets over the calmโฆ"์ด๋ผ๋ ์จ์ ํ ์์ด ๋ฌธ์ฅ์ด ๋์จ๋ค. ์ ๋ต ํค๋ 178์ด๋ค.
๐ Full Exploit
์ ์์กฐ์ฌ๋ก ํค๋ฅผ ์ฐพ์ ๋ณตํธํ๊ณ , ๋ฌธ์ฅ ์์์ ํ๋๊ทธ๋ฅผ ์ ๊ท์์ผ๋ก ๋ฝ๋๋ค.
import re
line = [l for l in open("output.txt") if "encrypted sentence >" in l][0]
enc = bytes.fromhex(line.split("> ")[1].strip())
for key in range(1, 256):
dec = bytes((b - key) % 256 for b in enc)
if b"DH{" in dec and all(32 <= c < 127 for c in dec):
print("key =", key)
print(re.search(rb"DH\{[^}]+\}", dec).group(0).decode())
break
key=178๋ก ๋ณตํธํ๋ฉด ๋
ธ์ ์ง๋ ๋ฐ๋ค๋ฅผ ๋ฌ์ฌํ ๊ธด ๋ฌธ๋จ์ด ๋์ค๊ณ , ๊ทธ ๋ง์ง๋ง ๋ฌธ์ฅ "โฆsleeping with the flag, DH{โฆ}"์ ํ๋๊ทธ๊ฐ ๋ฐํ ์๋ค.
key = 178
DH{37bdfc823523deca663c737a6c6e24fc561da4dd515f097cf8a48d417a3fb4ca}๐ ๊ฒฐ๋ก
ํค ๊ณต๊ฐ์ด ์์ผ๋ฉด ๋๋ค๋ ์์ฉ์๋ค.
์ด ๋ฌธ์ ์ ํค๋ ๋งค๋ฒ ๋๋ค์ผ๋ก ๋ฝํ์ง๋ง 1~255 ์ค ํ๋๋ผ, 255๋ฒ๋ง ์๋ํ๋ฉด ๋ฐ๋์ ๊ฑธ๋ฆฐ๋ค. ์ํธ์ ์์ ์ฑ์ ์๊ณ ๋ฆฌ์ฆ์ ๋ณต์กํจ์ด ์๋๋ผ ํค ๊ณต๊ฐ์ ํฌ๊ธฐ์์ ๋์จ๋ค. ์๋ฌด๋ฆฌ ๊ทธ๋ด๋ฏํ ์ํธ๋ผ๋ ํค๊ฐ ๋ช๋ฐฑ ๊ฐ์ง๋ฟ์ด๋ฉด ์ ์์กฐ์ฌ ์์ ๋ฌด๋์ง๋ค. ์ค์ ์์ ํคยทPINยทํ ํฐ์ ๋ค๋ฃฐ ๋ "๊ฒฝ์ฐ์ ์๊ฐ ๋ช ๊ฐ์ธ๊ฐ"๋ฅผ ๋จผ์ ๋ฐ์ง๋ ์ต๊ด์ด ์ค์ํ๋ค.
๋ณตํธ์ ์ ๋ต์ ํ๋ฌธ์ ํํ๋ก ํ๋ณํ๋ค.
์ ์์กฐ์ฌ์์ ๋ง๋ ํค๋ฅผ ์๋์ผ๋ก ๊ณจ๋ผ๋ธ ๊ธฐ์ค์ "๊ฒฐ๊ณผ๊ฐ ์ฝ์ ์ ์๋ ASCII์ด๊ณ ํ๋๊ทธ ํ์์ ํฌํจํ๋๊ฐ"์๋ค. ์๋ฌธ์ด ์ด๋ค ํํ(์์ด ๋ฌธ์ฅยทํน์ ๋งค์ง๋ฐ์ดํธยทํ๋๊ทธ ์ ๋์ฌ)์ธ์ง ์๋ฉด, ์๋ฐฑ~์๋ง ๊ฐ ํ๋ณด ์ค์์ ์ ๋ต์ ๊ธฐ๊ณ์ ์ผ๋ก ๊ฑธ๋ฌ๋ผ ์ ์๋ค. ๋ธ๋ฃจํธํฌ์ค๋ "๋ค ํด๋ณด๊ธฐ"๊ฐ ์๋๋ผ "๋ค ํด๋ณด๋ ์ ๋ต์ ์์๋ณด๋ ๊ธฐ์ค์ ์ธ์ฐ๊ธฐ"๊ฐ ํต์ฌ์ด๋ค.
Comments
๋๊ธ
๋๊ธ์ ๋จ๊ธฐ๋ ค๋ฉด ๋ก๊ทธ์ธ์ด ํ์ํด์. (๋ค์ด๋ฒ ยท ๊ตฌ๊ธ ๊ณ์ )
๋๊ธ ๋ถ๋ฌ์ค๋ ์คโฆ