Level 1 | Double DES
https://dreamhack.io/wargame/challenges/1118
Double DES
4바이트 전수 조사 쯤이야 간단하죠! Exploit Tech: Meet in the middle attack에서 함께 실습하는 문제입니다.
dreamhack.io
prob.py
#!/usr/bin/env python3
from Crypto.Cipher import DES
import signal
import os
if __name__ == "__main__":
signal.alarm(15)
with open("flag", "rb") as f:
flag = f.read()
key = b'Dream_' + os.urandom(4) + b'Hacker'
key1 = key[:8]
key2 = key[8:]
print("4-byte Brute-forcing is easy. But can you do it in 15 seconds?")
cipher1 = DES.new(key1, DES.MODE_ECB)
cipher2 = DES.new(key2, DES.MODE_ECB)
encrypt = lambda x: cipher2.encrypt(cipher1.encrypt(x))
decrypt = lambda x: cipher1.decrypt(cipher2.decrypt(x))
print(f"Hint for you :> {encrypt(b'DreamHack_blocks').hex()}")
msg = bytes.fromhex(input("Send your encrypted message(hex) > "))
if decrypt(msg) == b'give_me_the_flag':
print(flag)
else:
print("Nope!")
🔎 코드 분석
#!/usr/bin/env python3
from Crypto.Cipher import DES
import signal
import os
if __name__ == "__main__":
signal.alarm(15) #제한 시간 15초
with open("flag", "rb") as f:
flag = f.read()
key = b'Dream_' + os.urandom(4) + b'Hacker' #Dream_ + 임의의 4바이트 + Hacker 총 16바이트
key1 = key[:8] #key의 앞 8바이트, 미지의 2바이트
key2 = key[8:] #key의 뒤 8바이트, 미지의 2바이트
print("4-byte Brute-forcing is easy. But can you do it in 15 seconds?")
cipher1 = DES.new(key1, DES.MODE_ECB)
cipher2 = DES.new(key2, DES.MODE_ECB)
encrypt = lambda x: cipher2.encrypt(cipher1.encrypt(x)) #암호화 > cipher1 사용 암호화
decrypt = lambda x: cipher1.decrypt(cipher2.decrypt(x)) #복호화 > cipher2 사용 복호화 (=cipher2 암호화 후 cipher1 복호화)
print(f"Hint for you :> {encrypt(b'DreamHack_blocks').hex()}") #암호화 결과값 출력
msg = bytes.fromhex(input("Send your encrypted message(hex) > "))
if decrypt(msg) == b'give_me_the_flag':
print(flag)
else:
print("Nope!")
- siganl 함수 관련
[Python] Python 일정 시간 후 timeout 에러 내는 방법
서버 사이드에서 어떤 작업을 하고 클라이언트 사이드로 응답을 하는 로직을 만드는 중 이었습니다. 사용하고 있는 서버 인프라가 특정 시간만큼만 작동하고 그 이상으로 작동할 시 timeout error
growd.tistory.com
- 난수 생성 관련
https://docs.python.org/ko/3.10/library/random.html
random — 의사 난수 생성 — Python 3.10.13 문서
random — 의사 난수 생성 소스 코드: Lib/random.py 이 모듈은 다양한 분포에 대한 의사 난수 생성기를 구현합니다. 정수에 대해서는, 범위에서 균일한 선택이 있습니다. 시퀀스에 대해서는, 무작위
docs.python.org
➕ os.urandom
CSPRNG(Cryptographically Secure PseudoRandom Number Generator)
/dev/urandom 이 만드는 난수 ▶ 값 예측 어려움
✔️ DES.new 함수
https://howudong.tistory.com/90
[네트워크 보안] DES 개념 및 암/복호화 구현(Python)
DES의 개념 - 64bit 평문을 64bit 암호문으로 암호화하는 대표적인 비밀키 방식의 대칭 암호 알고리즘 - 암호화/복호화할 때 쓰는 비밀키가 동일함 DES 암호화 방식 평문을 64비트로 나눠 56비트의 키
howudong.tistory.com
DES 대칭키 암호
▶ 키를 알면 암복호화 모두 가능 / 키 모르면 둘 다 불가능
전체 암호화 과정
1) cipher1 암호화
2) cipher2 복호화 ▶ 암호화 기능의 역연산 (= cipher2 로 암호화 > cipher1 로 복호화)
🔎 익스플로잇 설계
📖 전수 조사 (Exhaustive search) 📖
모든 가능한 값을 대입해서 올바른 입력값을 찾는 방식
키 미지 바이트 ▶ 4바이트 (=32비트)
총 232 가지 키 존재
전수 조사 코드
from pwn import *
from Crypto.Cipher import DES
from tqdm import trange #시간 확인
io = process(["python3", "prob.py"])
io.recvuntil(b":> ")
hint = bytes.fromhex(io.recvline().decode())
for i in trange(2**32):
key = b'Dream_' + i.to_bytes(4, "big") + b'Hacker'
key1 = key[:8]
key2 = key[8:]
cipher1 = DES.new(key1, DES.MODE_ECB)
cipher2 = DES.new(key2, DES.MODE_ECB)
if cipher2.encrypt(cipher1.encrypt(b'DreamHack_blocks')) == hint:
print("Success")
break
tqdm 사용법 - python 진행률 프로세스바
파이썬으로 어떤 작업을 수행중인데, 프로그램이 내가 의도한 데로 돌아가고 있는 중인가, 진행상황이 궁금할 때가 있다. 시간이 걸리는 작업의 경우에 더 이런 상태 확인이 필요하다. 파이썬
skillmemory.tistory.com

📌 Meet-in-the-Middle Attack
A : b'DreamHack_blocks'
B : A가 암호화된 결과
cipher2.encrypt(cipher1.encrypt(A)) = B
key1, key2 가능 후보는 미지의 2바이트에 따라 각각 216=65536 가지 가능성
▶ cipher1.encrypt(A), cipher2.decrpyt(B) 가능한 가짓수 모두 65536가지
올바른 키일 경우, cipher2.encrypt(cipher1.encrypt(A)) = B 성립
양변에 cipher2.decrypt ▶ cipher1.encrypt(A) = cipher2.decrypt(B)
ciperh1.encrypt(A) 후보 65536개와 cipher2.decrypy(B) 후보 65536 공통 값이 있으면,
해당 경우에 사용된 key1, key2가 올바른 키
▶가운데에서 만난다는 의미의 Meet-in-the-middle attack
Python dict 자료형 사용 익스플로잇
key1 후보 dict에 저장
for i in range(2**16):
b = i.to_bytes(2, "big") #미지의 2바이트
cipher = DES.new(b"Dream_" + b, DES.MODE_ECB) #Dream_ + 임의 2바이트로 cipher1 암호키 생성
enc = cipher.encrypt(b"DreamHack_blocks") #생성된 암호키로 암호화
conflict[enc] = b"Dream_" + b #confilct 자료형에 {암호문:암호키} 형태로 저장
key2 후보 값 생성 후 탐색
for i in range(2**16):
b = i.to_bytes(2, "big") #미지 2바이트 생성
cipher = DES.new(b + b"Hacker", DES.MODE_ECB) #임의 2바이트 + Hacker로 cipher2 암호키 생성
dec = cipher.decrypt(hint) #생성된 암호키로 hint 복호화
# cipher2로 복호화한 값이 cipher1으로 암호화한 hint 값과 동일해야 함
if dec in conflict: #딕셔너리 자료형을 통해 동일 값 탐색
key1 = conflict[dec] #key1은 conflict value 값
key2 = b + b"Hacker" #key2는 미지 2바이트 + Hacker 값
break
힌트 cipher1 암호화 값과 힌트 cipher2 복호화 값 비교를 통해 key 찾기
- to_bytes 함수
https://thebook.io/006950/0223/
컴퓨터 사이언스 부트캠프 with 파이썬: 1 메모리 저장 방식
더북(TheBook): (주)도서출판 길벗에서 제공하는 IT 도서 열람 서비스입니다.
thebook.io
int형을 byte로 전환할 때, 파라미터를 통해 빅 엔디언 방식과 리틀 엔디언 방식을 설정해줄 수 있음

'WorkOut > Dreamhack' 카테고리의 다른 글
Cryptography | 현대 암호 (대칭키 & 비대칭키 암호, 기밀성/무결성/인증/부인방지) (0) | 2024.07.15 |
---|---|
Cryptography | 고전 암호 (치환 & 전치) (0) | 2024.07.07 |
Cryptography | 배타적 논리합과 합동식 (0) | 2024.07.07 |
Cryptography | 분명히 시작은 암호학 공부였는데.. (1) | 2024.07.07 |