소스코드당
#!/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!")
Double DES는 두 개의 Data Encryption Standard (DES) 암호화를 연속적으로 적용하여 보안성을 향상하려는 암호화 방식입니다. DES 자체의 보안이 약화되면서 이를 강화하기 위해 제안된 기법 중 하나입니다. 하지만 Double DES에는 취약점이 있어 실질적으로 많이 사용되지는 않습니다.
동작 방식
- 암호화:
- 평문 PP에 대해 두 개의 서로 다른 키 K1K_1와 K2K_2를 사용하여 두 번 암호화를 수행합니다.
- EK1(P)E_{K_1}(P): 첫 번째 DES 암호화.
- EK2E_{K_2}: 두 번째 DES 암호화.
- CC: 최종 암호문.
- 복호화:
- 암호문 CC에 대해 같은 두 키를 역순으로 사용하여 복호화합니다.
- DK2(C)D_{K_2}(C): 두 번째 DES 복호화.
- DK1D_{K_1}: 첫 번째 DES 복호화.
보안 목표
- 단일 DES의 56비트 키 길이를 두 번 적용함으로써 키 길이를 112비트로 늘려 보안성을 강화하려는 것이 목표였습니다.
취약점: Meet-in-the-Middle 공격
Double DES는 Meet-in-the-Middle (MITM) 공격으로 인해 예상보다 약한 보안성을 가집니다.
- MITM 공격:
- 공격자가 암호문 CC와 평문 PP 한 쌍을 알고 있다고 가정.
- EK1(P)E_{K_1}(P)와 DK2(C)D_{K_2}(C)의 중간 값을 계산하여 키를 복구.
- 단계:
- 첫 번째 키 K1K_1 후보를 모두 시도하여 EK1(P)E_{K_1}(P) 값을 저장.
- 두 번째 키 K2K_2 후보를 모두 시도하여 DK2(C)D_{K_2}(C) 값을 계산.
- EK1(P)E_{K_1}(P)와 DK2(C)D_{K_2}(C)의 일치 여부를 확인하여 올바른 K1K_1과 K2K_2를 찾음.
- 결과:
- Double DES의 보안 수준은 이론적으로 21122^{112}번의 연산을 요구하지만, MITM 공격으로 인해 2572^{57}번의 연산으로 키를 복구 가능.
- 이는 단일 DES의 2562^{56}에 비해 큰 보안 향상이 아님.
Triple DES와의 비교
Double DES의 취약점을 극복하기 위해 Triple DES가 제안되었습니다. 이는 DES를 세 번 연속 적용하는 방식으로, 보안성이 크게 향상되었습니다:
C=EK1(DK2(EK1(P)))C = E_{K_1}(D_{K_2}(E_{K_1}(P)))
- Triple DES는 효과적인 키 길이가 112비트에서 168비트에 이르며, 여전히 많은 금융 시스템에서 사용됩니다.
요약
- Double DES는 두 번의 DES 암호화를 사용하여 보안을 강화하려 했으나, MITM 공격으로 인해 예상보다 약한 보안을 제공합니다.
- Triple DES가 더 강력한 대안으로 사용됩니다.
- 현재는 AES(Advanced Encryption Standard)와 같은 더 안전하고 효율적인 암호화 방식이 널리 사용됩니다.
이 프로그램은 두 개의 DES 키를 사용하여 데이터를 암호화하고 복호화합니다. 주요 목표는 4바이트의 랜덤 값을 brute-force하여 프로그램이 15초 내에 암호화된 메시지를 올바르게 복호화하도록 만드는 것입니다. 프로그램의 흐름을 분석하고 공격 방법을 설명하겠습니다.
코드 분석
- 키 생성:
- key는 16바이트로 구성되며, b'Dream_' + 4바이트 랜덤 값 + b'Hacker 형태입니다.
- key1와 key2는 각각 8바이트로 나뉘어 DES 키로 사용됩니다.
- key = b'Dream_' + os.urandom(4) + b'Hacker' key1 = key[:8] key2 = key[8:]
- 암호화와 복호화:
- encrypt: 두 번의 DES 암호화를 적용 (Cipher1 → Cipher2).
- decrypt: 두 번의 DES 복호화를 적용 (Cipher2 → Cipher1).
- 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))
- 힌트:
- 프로그램은 b'DreamHack_blocks'를 암호화한 값을 힌트로 제공합니다.
- print(f"Hint for you :> {encrypt(b'DreamHack_blocks').hex()}")
- 입력 확인:
- 프로그램은 사용자가 입력한 메시지를 복호화한 결과가 b'give_me_the_flag'인지 확인합니다.
- msg = bytes.fromhex(input("Send your encrypted message(hex) > ")) if decrypt(msg) == b'give_me_the_flag': print(flag) else: print("Nope!")
공격 전략
- 키 공간:
- os.urandom(4)는 4바이트의 랜덤 값을 생성합니다.
- 4바이트는 2322^{32} (약 42억)개의 가능한 값이 있습니다.
- Brute-Force:
- 힌트 메시지와 입력한 메시지의 암호화 및 복호화 과정을 역추적하여 가능한 키를 brute-force 합니다.
- 먼저 key1와 key2를 추정하여 메시지를 복호화합니다.
- 공격 단계:
- 힌트 값과 평문(b'DreamHack_blocks')을 사용하여 모든 가능한 key1와 key2를 brute-force 합니다.
- 올바른 키를 찾으면 사용자가 입력한 암호화된 메시지를 복호화하여 플래그를 가져옵니다.
https://whitehacking.tistory.com/38
여기 문제 풀이가 너무 완벽해서 줏어왔다..역시 암호학은 복호화 과정 100% 이해해야 풀이가능 ㅋㅋㅋ
직접 손으로 타이핑하거나, 종이에 쓰는게 이해가 빠르다
DreamHack_block를 암호화 해서 16진수로 나타낸 값이 저거
DreamHack_block를 A, 전체 암호화 결과를 B라고하면
cipher2.encrypt(cipher1.encrypt(A))=B
여기에 cipher2.decryp를 양식에 둘다 넣어주면
cipher1.encrypt(A) = cipher2.dercrypt(B)
이 식을 만족하는 공통된 key1, key2가 올바른 키
2^16 =2^17
이 코드는 DreamHack 문제에서 Double DES 암호화를 브루트포싱을 통해 풀기 위한 스크립트입니다. 코드의 주요 목적은 key1과 key2를 찾아 특정 메시지를 복호화하거나 암호화된 데이터를 다시 보낼 수 있도록 하는 것입니다. 아래는 코드의 주요 부분에 대한 설명입니다.
1. Key와 Message 정의
key = b'Dream_' + bytearray(4) + b'Hacker'
- key는 DES 키의 형식을 나타냅니다.
- 앞부분은 b'Dream_' (6바이트).
- 중간은 4바이트로 브루트포싱할 영역 (bytearray(4)는 빈 값으로 초기화).
- 뒷부분은 b'Hacker' (6바이트).
- key1과 key2는 각각 이 키에서 중간의 브루트포싱 값에 의해 결정됩니다.
2. Key1 브루트포싱 (Precomputation)
m = {}
for i in range(0, 256 * 256):
key1 = key[:6] + int.to_bytes(i, 2, 'big')
cipher1 = DES.new(key1, DES.MODE_ECB)
cipher_text = cipher1.encrypt(b'DreamHack_blocks')
m[cipher_text] = int.to_bytes(i, 2, 'big')
- key1의 중간 값 (int.to_bytes(i, 2, 'big'))을 모든 가능한 값으로 설정하며 브루트포싱합니다.
- i는 2바이트 값이므로 총 256 * 256 = 65,536개의 경우의 수를 시도합니다.
- 각 key1로 b'DreamHack_blocks' 문자열을 암호화하여 암호문을 생성하고, 결과를 딕셔너리 m에 저장합니다:
- Key: cipher_text (암호화된 텍스트).
- Value: key1에서 사용된 중간 값 (2바이트).
3. 서버 연결
r = remote('host3.dreamhack.games', 18638)
data = r.recvline()
data = r.recvline()[16: -1]
print(data)
- remote를 사용하여 DreamHack 문제의 서버에 연결합니다.
- 서버로부터 제공되는 힌트를 읽어옵니다. 이 힌트는 Double DES 암호화된 텍스트로, 이를 브루트포싱하여 키를 복구합니다.
4. Key2 브루트포싱
cipher_text3 = int.to_bytes(int(data, 16), 16, 'big')
ans = 0
for i in range(0, 256 * 256):
key2 = int.to_bytes(i, 2, 'big') + key[10:]
cipher2 = DES.new(key2, DES.MODE_ECB)
cipher_text2 = cipher2.decrypt(cipher_text3)
if cipher_text2 in m:
ans = m.get(cipher_text2) + int.to_bytes(i, 2, 'big')
- 힌트를 바탕으로 key2를 브루트포싱합니다.
- cipher_text3는 서버에서 받은 힌트(암호화된 메시지)를 바이트로 변환한 값.
- key2는 브루트포싱 값과 b'Hacker'의 조합.
- 각 key2로 복호화를 시도하며, 복호화된 값이 m 딕셔너리의 키(cipher_text)에 존재하는지 확인합니다.
- 키를 찾으면 ans에 key1과 key2의 중간 값들을 조합해 저장합니다.
5. 암호화 메시지 생성
cipher1 = DES.new(key[:6] + ans[:2], DES.MODE_ECB)
cipher2 = DES.new(ans[2:] + key[10:], DES.MODE_ECB)
send_msg = cipher2.encrypt(cipher1.encrypt(b'give_me_the_flag'))
- 찾은 key1과 key2를 사용하여 Double DES 암호화를 수행합니다.
- 메시지 b'give_me_the_flag'를 암호화하여 서버로 보낼 메시지를 생성합니다.
6. 서버로 암호화 메시지 전송
print(send_msg.hex())
r.sendline(send_msg.hex().encode('ascii'))
r.interactive()
- 생성한 암호화 메시지를 서버에 전송합니다.
- r.interactive()를 사용하여 서버와의 상호작용을 유지합니다.
코드 흐름 요약
- Precomputation (Key1): key1의 모든 가능한 값을 브루트포싱하여 암호화된 텍스트를 딕셔너리로 저장.
- 서버로부터 힌트 수신: 서버에서 제공된 Double DES 암호문을 수신.
- Key2 브루트포싱: 받은 힌트를 이용해 key2를 브루트포싱하며 key1과 일치하는 값을 찾음.
- Double DES 암호화 메시지 생성: 찾은 key1과 key2로 b'give_me_the_flag'를 암호화.
- 서버로 메시지 전송: 암호화된 메시지를 서버로 보내 플래그를 획득.
중요한 점
- Precomputation: key1을 미리 브루트포싱하고 저장하여 검색 속도를 빠르게 함.
- 효율적인 키 탐색: Double DES의 중간 값을 활용한 Meet-in-the-Middle 공격 기법 사용.
- 2단계 브루트포싱: key1과 key2를 분리하여 효율적으로 브루트포싱.
이 코드는 Double DES의 보안 약점을 효과적으로 이용하여 키를 찾는 방식입니다.
https://whitehacking.tistory.com/38
'Dreamhack > Dreamhack Wargame (Challenge)' 카테고리의 다른 글
[119] IT 비전공자 [dreamhack][CodeEngn] Malware L08문제 풀기 (0) | 2025.01.07 |
---|---|
[118] IT 비전공자 [dreamhack]Batch Checker문제 풀기 (0) | 2025.01.06 |
[116] IT 비전공자 [dreamhack]iofile_vtable 문제 풀기 (0) | 2025.01.05 |
[115] IT 비전공자 [dreamhack]Collect Me 문제 풀기 (0) | 2025.01.03 |
[114] IT 비전공자 [dreamhack]likeb64문제 풀기 (0) | 2025.01.02 |