2026 18th CODEGATE CTF 문제 풀이

0. 개요

  • 문제 이름 : Ghost
  • 문제 유형 : Crypto
  • 환경 :
    • 해시 구조 : Davies-Meyer
    • 블록 암호: 커스텀 Feistel (64-bit)
    • oracle 제공: round core 출력
  • 목표 :
    • 서로 다른 두 입력 m₁, m₂에 대해 동일한 해시 값을 만드는 충돌 생성

1. 전체 구조 분석

1-1. 해시 구조

해시는 Davies-Meyer 구조를 사용한다.

DM(iv, m) = E(iv, m) ⊕ iv

따라서 충돌 조건은 다음과 같이 단순화된다.

DM(iv, m1) = DM(iv, m2)
→ E(iv, m1) = E(iv, m2)

결국 블록 암호 출력 충돌 문제


1-2. 문제 정의

문제는 다음가 같이 정리된다. 같은 입력(iv)에 대해 동일한 암호 출력이 나오도록 두 메시지를 찾는 문제


2. 암호 구조 분석

2-1. 전체 구조

블록 암호는 다음과 같은 Feistel 구조를 가진다.

  • 블록 : 64-bit (32bit x 2)
  • 라운드 : 32
  • 키 : 8 x 32bit

2-2. 라운드 키 스케줄

1
2
3
4
k0 k1 k2 k3 k4 k5 k6 k7
k0 k1 k2 k3 k4 k5 k6 k7
k0 k1 k2 k3 k4 k5 k6 k7
k7 k6 k5 k4 k3 k2 k1 k0

반복 및 마지막 역순 구조


2-3. 라운드 함수

F(r, k) = ROTL( SBOX(r + k), 11 )

구성:

  • 32-bit 덧셈
  • SBOX (4-bit x 8개)
  • rotate

3. 취약점 분석

3-1. oracle 제공

서버는 다음 oracle을 제공한다.

query(right, subkey) -> round output


3-2. 의미

이 oracle 을 이용하면:

  • 특정 입력에 대한 SBOX 결과 관찰 가능
  • rotation 제거 가능

SBOX를 직접 복구할 수 있다.


4. SBOX 복구

4-1. 구조

  • SBOX : 4-bit -> 4-bit
  • 개수 : 8개

총 경우의 수는 8 x 16 = 128 이다.


4-2. 복구 방법

1
2
3
4
5
6
for i in range(8):
for n in range(16):
y = query(0, n << (4*i))
z = rotr(y, 11)
sboxes[i][n] = (z >> (4*i)) & 0xF

4-3. 결과

전체 SBOW 완전 복원


5. 문제 핵심

5-1. 중요한 관찰

SBOX를 알게되면

  • F 함수 완전히 재현 가능
  • F 역함수 구성 가능

5-2. 의미

암호를 black-box가 아니라 white-box로 변환


5-3. 아이디어

암호를 깨는 것이 아니라 출력을 원하는 값으로 맞춘다.


6. 공격 시나리오

6-1. 목표

E(iv, m1) = E(iv, m2)


6-2. 출력 구조 설계

다음과 같은 구조를 정의한다.

(A, 0, 0, 0, 0, 0, A, 0)

  • Feistel 대칭성 이용

6-3. 라운드 역산

각 라운드에 대해 F(r, k) = target 를 만족하도록 k를 계산


6-4. 역함수 적용

k = inv_sbox( ROTR(target, 11) ) - r

  • 각 라운드 키를 직접 구성 가능

6-5. parameterization

출력 값을 변수 t로 둔다.
A = t, 하나의 t -> 하나의 key 생성


6-6. 충돌 탐색

1
2
3
for t in range(2^16):
key = build_key(t)
enc = encrypt(iv, key)

if enc in seen:
collision

  • Birthday principle 적용

7. 결과.

충돌 발견:

t1 = 1, t2 = 5


7-1. 메시지

m1 = 159eaf6a89d3f60e154eaf6a89d3f60e154eaf6a89d3f60e159eaf6a89d3f60f
m2 = 15deaf6a89d3f60a154eaf6a89d3f60a154eaf6a89d3f60a15deaf6a89d3f60f


8. 전체 공격 흐름 정리

전체 과정은 다음과 같다.

  1. oracle을 이용해 SBOX 복구
  2. 라운드 함수 F 완전 재현
  3. 역함수 구성
  4. 원하는 출력 구조 설계
  5. 각 라운드 key 역산
  6. parameter t 기반 key 생성
  7. birthday 탐색으로 충돌 발견
  8. m1, m2 생성 → 조건 만족

9. 포인트

이 문제의 포인트는 다음과 같다.

  • oracle -> 내부 구조 완전 복구
  • SBOX -> 암호 전체를 풀어버린다.
  • Feistel 대칭성 -> 출력 설계 가능
  • brute-force가 아니라 구조적 공격

10. 정리

oracle을 이용해 SBOX를 복구하고, 라운드 함수를 역으로 구성하여
동일한 출력이 나오도록 메시지를 설계해 Davies-Meyer 해시 충돌을 만드는 문제

11. 최종 플래그

1
codegate2026{9a907c6a23bea7b6233ef362173739ef98b656049ce5c58361660b10cce4475d31a6779b31b2d