[Crypto] EZ-Des - Dreamhack

2025. 10. 21. 02:50·

Đề bài


Mô tả

Đề bài này cũng khá ngắn gọn khi nó cho mình 1 file keys.txt, 1 file flag.txt và 1 file des.py và một trang web để mình tải ciphertext.txt về

  • Dịch vụ Flask cho tải ciphertext.txt và keys.txt. Mỗi block 8 byte (DES) — tổng cộng 50 block (400 bytes)
  • Mã hóa mỗi block bằng “Triple‑DES EDE” nhưng 3 lần dùng cùng một key → thực chất chỉ còn Single DES (ECB) cho từng block
  • Thứ tự key/khối bị xáo bằng random.shuffle(idxs) với seed = int(time.time()), và seed bị lộ qua header X-Used-Seed (và mtime của file)
  • Vì thế ta có hai hướng giải:
    • Cách A (chuẩn): lấy seed ⇒ tái tạo thứ tự trộn ⇒ giải DES từng block với key tương ứng
    • Cách B (không cần seed): brute‑force 50 key/khối, chọn decrypt nào ra ASCII có nghĩa (unique) ⇒ ráp lại toàn văn/flag

Phân tích source

# triple_des_ede(block, key)
c1 = DES.new(key, DES.MODE_ECB).encrypt(block)
c2 = DES.new(key, DES.MODE_ECB).decrypt(c1)
c3 = DES.new(key, DES.MODE_ECB).encrypt(c2)
return c3
  • Dùng cùng key cho E, D, E ⇒ D(E(m, K), K) = m ⇒ cả chuỗi EDE(m, K, K, K) = E(m, K)
  • random.seed(seed); random.shuffle(idxs) ⇒ deterministic nếu biết seed (header/mtime)

Tấn công

Cách A – Có seed

  1. Tải keys.txt và ciphertext.txt, đọc header X-Used-Seed (hoặc lấy mtime).
  2. random.seed(seed); random.shuffle(idxs) → có thứ tự key.
  3. Chia ciphertext thành 50 block 8B, giải DES‑ECB lần lượt với keys[idxs[i]].
  4. Nối plaintext ⇒ cắt padding ‘A’ nếu có ⇒ lấy flag.

Cách B – Không cần seed (đã dùng trong phiên này)

  1. Chia ciphertext thành 50 block 8B.
  2. Với mỗi block i, thử giải bằng 50 key trong keys.txt.
  3. Chọn kết quả nào in được/ASCII, có nghĩa (mỗi block của đề này là duy nhất, không trùng key).
  4. Sắp xếp theo vị trí hiện tại (vì ciphertext giữ thứ tự block, chỉ key bị xáo) ⇒ ráp toàn văn/flag.

Lưu ý: Bộ đề này được soạn để mỗi block plaintext là cụm từ tiếng Anh hoàn chỉnh/không nhiễu nên tiêu chí “printable ASCII” đủ phân biệt 1–1.


Script

from Crypto.Cipher import DES
import binascii
import string

def is_printable(bs: bytes) -> bool:
    try:
        s = bs.decode('latin-1')
    except UnicodeDecodeError:
        return False
    allowed = set(string.printable)
    return all(ch in allowed for ch in s)

def des_decrypt_block(block: bytes, key: bytes) -> bytes:
    return DES.new(key, DES.MODE_ECB).decrypt(block)

def parse_hex_to_bytes(hex_with_spaces: str) -> bytes:
    hx = ''.join(hex_with_spaces.split())
    return binascii.unhexlify(hx)

def main(keys_path='keys.txt', cipher_hex_path='cipher_hex.txt'):
    keys = [bytes.fromhex(line.strip()) for line in open(keys_path) if line.strip()]
    assert len(keys) == 50 and all(len(k)==8 for k in keys)

    hex_str = open(cipher_hex_path, 'r', encoding='utf-8').read()
    c = parse_hex_to_bytes(hex_str)
    assert len(c) == 400 and len(c) % 8 == 0
    blocks = [c[i:i+8] for i in range(0, len(c), 8)]

    chosen = [None]*len(blocks)
    for i, cb in enumerate(blocks):
        hit = None
        for k in keys:
            pt = des_decrypt_block(cb, k)
            if is_printable(pt):
                hit = pt
                break
        if not hit:
            raise RuntimeError(f'No printable candidate for block {i}')
        chosen[i] = hit

    plaintext = b''.join(chosen)
    print(plaintext.decode('latin-1', 'replace'))

if __name__ == '__main__':
    main()

Trước khi run script thì mình sẽ cần lưu bản text của ciphertext thành dạng hex và đặt là cipher_hex.txt


Flag

Flag: DH{Mistress_Sarah_Darling_inadvertently_bestowed_a_ring_of_considerable_value_upon_the_coin_cup_of_a_homeless_gentleman_known_as_Billy_Ray_Harris_However_Billy_displaying_admirable_integrity_sought_out_Sarah_to_return_the_precious_item_In_gratitude_Sarah_initiated_a_fundraising_campaign_which_has_since_enabled_Billy_to_acquire_both_a_residence_and_gainful_employment_UwUwUwUwUwUwUwUwUwUwUwUwUwUwU_}

'WriteUp > Crypto' 카테고리의 다른 글

Augury - BuckeyeCTF 2025  (0) 2025.11.09
[Crypto] Guess Me! - m0leCon Teaser 2026  (0) 2025.10.25
'WriteUp/Crypto' Other posts in category
  • Augury - BuckeyeCTF 2025
  • [Crypto] Guess Me! - m0leCon Teaser 2026
longhd
longhd
Longhd's Blog
  • longhd
    Ha Duy Long - InfosecPTIT
    longhd
  • Total
    Today
    Yesterday
  • About me

    • Hello I'm Duy Long 👋🏻
    • View all categories (117) N
      • Certificates (4)
      • CTF (3)
      • WriteUp (94) N
        • Forensics (44) N
        • Steganography (5)
        • RE (9) N
        • OSINT (8)
        • Web (17)
        • MISC (6)
        • Crypto (3)
        • Pwn (2)
      • Love Story (0)
      • Labs (15)
        • Information Gathering (10)
        • Vulnerability Scanning (2)
        • Introduction to Web Applica.. (1)
        • Common Web Application Atta.. (1)
        • SQL Injection Attacks (1)
  • Blog Menu

    • Home
    • Tag
    • GuestBook
  • Popular Posts

  • Tags

    Web
    BuckeyeCTF2025
    EnigmaXplore3.0
    THM
    Re
    CHH
    V1tCTF2025
    POCCTF2025
    CSCV2025
    picoCTF
    Forensics
    OSINT
    misc
    Dreamhack
    writeup
    SunshineCTF2025
    CTF
    Steganography
    htb
    PTITCTF2025
  • Recent Comments

  • Recent Posts

  • hELLO· Designed ByLong.v4.10.4
longhd
[Crypto] EZ-Des - Dreamhack
Go to Top

티스토리툴바