랜섬웨어 분석 보고서

DragonForce 랜섬웨어 분석 보고서

geonwoo9643 2026. 2. 3. 18:18

1. 개요 (Overview)


1.1 분석 배경

DragonForce 랜섬웨어는 2025년 초부터 활발히 유포되고 있는 악성코드로, ChaCha8 스트림 암호화와 RSA 공개키 암호화를 결합한 하이브리드 암호화 방식을 채택하고 있습니다. 특히 멀티스레드 기반의 고속 암호화 엔진을 탑재하여 대량의 파일을 신속하게 암호화하며, 파일 크기와 타입에 따라 차별화된 암호화 전략을 적용합니다. 본 보고서는 DragonForce의 암호학적 구조를 정밀 분석하고, API 후킹을 통한 실시간 키 추출 기법과 복호화 전략을 제시합니다.


1.2 핵심 요약

  • 고성능 멀티스레드 아키텍처 : CreateThread API를 반복 호출하여 다수의 워커 스레드를 생성하고, 병렬 처리를 통해 암호화 속도를 극대화합니다.
  • ChaCha8 스트림 암호화 : 4번의 더블 라운드를 수행하는 경량화된 ChaCha8 알고리즘을 사용하여, 성능과 보안성의 균형을 추구합니다. 각 파일마다 고유한 32바이트 키와 8바이트 nonce를 생성합니다.
  • 차별화된 암호화 전략 : 파일 크기와 타입에 따라 전체 파일 암호화, 선택적 청크 암호화, 헤더만 암호화 등 세 가지 방식을 선택적으로 적용합니다.
  • 완벽한 복호화 가능성 : CryptGenRandom API 호출 시점에 생성되는 평문 키를 API 후킹으로 실시간 캡처할 경우, RSA 개인키 없이도 완벽한 복호화가 가능합니다. 본 분석에서 개발한 복호화 스크립트를 통해 실증적으로 검증되었습니다.

 

2. 식별 정보 (Identification)


  • Malware Family: DragonForce
  • Filetype: PE32 (Windows Executable)
  • Hash (SHA256): c844d02c91d5e6dc293de80085ad2f69b5c44bc46ec9fdaa4e3efbda062c871c
  • Extension: .dragonforce_encrypted
  • Target: Windows 기반 시스템

 

3. 분석 환경 및 도구 (Tools)


구분 도구명 (Tool) 용도 (Purpose)
정적 분석 IDA Pro ChaCha8 구현 루틴 및 암호화 로직 분석
동적 분석 CryptGenRandom API Hooking (x86) 실시간 키 및 nonce 추출
행위 분석 Process Monitor 파일 I/O 및 멀티스레드 행위 추적
검증 도구 Python ChaCha8 복호화 스크립트 개발 및 PoC

 

4. 암호화 기술 분석 (Technical Analysis)


4.1 전체 암호화 워크플로우

DragonForce는 고성능 멀티스레딩 모델을 기반으로 다음과 같은 5단계 프로세스를 거칩니다.

  1. 멀티스레드 생성 : WinMain에서 CreateThread API를 반복 호출하여 다수의 워커 스레드(StartAddress) 생성
  2. 키 및 Nonce 생성 : CryptGenRandom API를 통해 파일별로 고유한 32바이트 ChaCha 키와 8바이트 nonce를 생성
  3. ChaCha State 초기화 : 생성된 키와 nonce로 ChaCha state를 초기화하고 카운터를 0으로 설정
  4. 차별화된 파일 암호화 : 파일 크기 및 타입에 따라 전체/부분/헤더 암호화 전략을 선택적으로 적용
  5. 메타데이터 저장 : ChaCha 키, nonce, 파일명 정보를 RSA 공개키로 암호화하여 파일 footer에 추가

4.2 키 생성 및 관리 (Key Generation)

4.2.1 CryptGenRandom을 통한 난수 생성

DragonForce는 Windows CryptoAPI의 CryptGenRandom 함수를 사용하여 암호학적으로 안전한 난수를 생성합니다.

// 각 파일마다 고유한 키와 nonce 생성
CryptGenRandom(hProv, 32, chacha_key);    // 32바이트 ChaCha Key
CryptGenRandom(hProv, 8, chacha_nonce);   // 8바이트 ChaCha Nonce

 

4.2.2 ChaCha State 초기화

생성된 키와 nonce를 사용하여 ChaCha state를 초기화합니다.

  • Constant: "expand 32-byte k" (ChaCha 표준 상수)
  • Key: CryptGenRandom으로 생성한 32바이트 난수
  • Counter: 0으로 초기화 (블록마다 1씩 증가)
  • Nonce: CryptGenRandom으로 생성한 8바이트 난수

ChaCha State 구조 (64바이트):

Constant (16B) Key (32B) Counter (8B) Nonce (8B)

 

4.2.3 메타데이터 생성 및 RSA 암호화

파일 복호화에 필요한 정보를 메타데이터로 구성하여 RSA 공개키로 암호화합니다.

 

메타데이터 구조 (→ RSA 공개키로 암호화 → 파일 footer에 추가) :

ChaCha Key (32B) ChaCha Nonce (8B) 파일명 길이 (4B) 파일명 (Variable)

 

공격자는 RSA 개인키를 통해 이 메타데이터를 복호화하여 각 파일의 ChaCha 키를 복구할 수 있습니다.


4.3 파일 처리 및 I/O 아키텍처

4.3.1 CreateThread 기반 멀티스레드 암호화

[WinMain]
    ├─> CreateThread (Worker Thread 1) → StartAddress
    ├─> CreateThread (Worker Thread 2) → StartAddress
    ├─> CreateThread (Worker Thread 3) → StartAddress
    └─> CreateThread (Worker Thread N) → StartAddress

[StartAddress]
    └─> 파일 시스템 순회
        └─> 대상 파일 발견
            └─> 파일 암호화 수행

 

4.3.2 파일 암호화 메인 로직

다음의 순서로 파일 암호화를 수행합니다:

  1. 키 및 Nonce 생성: CryptGenRandom 호출
  2. ChaCha State 초기화: 키, nonce, 카운터 설정
  3. 파일 크기/타입 판별: 암호화 전략 선택
  4. ChaCha8 블록 암호화: 실제 암호화 수행
  5. 메타데이터 기록: RSA로 암호화된 메타데이터를 footer에 추가

 

4.3.3 파일 크기 및 타입에 따른 차별화된 암호화 전략

DragonForce는 효율성을 위해 파일 크기와 타입에 따라 세 가지 암호화 방식을 선택적으로 적용합니다.

암호화 방식 대상 파일
전체 파일 암호화 작은 파일 (< 1MB)
선택적 청크 암호화 큰 파일 (≥ 1MB, 성능 최적화)
헤더만 암호화 특정 파일 타입 (미디어 파일 등)

 

암호화 프로세스 :

SetFilePointerEx (파일 포인터 이동)
    ↓
ReadFile (데이터 읽기)
    ↓
Encryption (ChaCha8 블록 암호화)
    ↓
WriteFile (암호화된 데이터 쓰기)
    ↓
파일명 변경 (원본.확장자 → 원본.확장자.dragonforce_encrypted)

4.4 정적 분석

  • 멀티스레드 암호화 (CreateThread)

 

  • 작업자 스레드 함수 (암호화)

 

  • pbData (RSA1 시그니처)

 

  • 파일 암호화 실행 함수

스레드 시작
    ↓
Crypto API 초기화
    ↓
RSA 공개키 임포트 (CryptImportKey)
- pbData : 4096바이트 RSA 공개키
- "RSA1" 시그니처 확인됨
    ↓
5MB 암호화 버퍼 할당 (VirtualAlloc)
    ↓
무한 루프 시작
    ↓
┌──────────────────────────────┐
│ 크리티컬 섹션 진입            │
│ (EnterCriticalSection)        │
└──────────────────────────────┘
    ↓
작업 큐에서 파일 항목 가져오기
    ↓ 
큐가 비어있음? ──Yes─→ 5초 대기 후 재시도
    ↓ No
큐에서 항목 제거 (연결 리스트 업데이트)
    ↓
┌──────────────────────────────┐
│ 크리티컬 섹션 탈출            │
│ (LeaveCriticalSection)        │
└──────────────────────────────┘
    ↓
종료 플래그 확인? ──Yes─→ 스레드 종료
    ↓ No
파일 경로 처리
    ↓
파일 암호화 실행 함수 호출
- RSA 공개키로 ChaCha 키/Nonce 암호화
- select_encryption_strategy 호출
- 파일 크기별 암호화 전략 실행
    ↓
작업 항목 메모리 해제 (free)
    ↓
무한 루프 계속

 

  • 랜덤 키/Nonce 생성 (CryptGenRandom)

 

  • ChaCha State 초기화

 

ChaCha8 블록 암호화

1. ChaCha8 키스트림 생성

ChaCha8은 일반적인 ChaCha20의 10번 더블 라운드 대신, 4번의 더블 라운드를 수행하여 성능을 최적화한 변형입니다.

ChaCha8 라운드 구조:
┌─────────────────────────────────┐
│    Initial State (64 bytes)     │
│  [Constant | Key | Ctr | Nonce] │
└─────────────────────────────────┘
            ↓
    ┌───────────────┐
    │ Double Round  │  ← 4번 반복 (ChaCha8)
    │ (QR 함수 8회) │
    └───────────────┘
            ↓
┌─────────────────────────────────┐
│      Keystream (64 bytes)       │
└─────────────────────────────────┘

 

2. ChaCha 라운드 연산 (Quarter Round)

Quarter Round (a, b, c, d):
    a += b; d ^= a; d <<<= 16;
	    c += d; b ^= c; b <<<= 12;
    a += b; d ^= a; d <<<= 8;
    c += d; b ^= c; b <<<= 7;

 

3. XOR 암호화 및 카운터 증가

*// 생성된 키스트림과 평문을 XOR*

for (i = 0; i < block_size; i++) {
    ciphertext[i] = plaintext[i] ^ keystream[i];
}

*// 블록마다 카운터 증가*

counter++;

 

메타데이터 생성 및 RSA 암호화

  • 메타데이터 구조체 생성

 

  • RSA 공개키로 메타데이터 암호화

 

  • 암호화된 메타데이터를 파일 footer에 기록

 

파일 처리 전체 흐름

  • 파일 열기 및 크기 확인

 

  • 암호화 전략 선택

 

  • 전체 암호화 (작은 파일)

 

    • 헤더만 암호화 (중간 크기 파일)

 

  • 청크 단위 선택 암호화 (큰 파일)

 

  • 암호화된 데이터 파일에 쓰기

 

  • 파일명 변경 (.dragonforce_encrypted 추가)

[파일 처리 과정]
1. 파일 열기 및 크기 확인
   ↓
2. CryptGenRandom 호출
   - 32바이트 ChaCha 키 생성
   - 8바이트 nonce 생성
   ↓
3. ChaCha State 초기화
   - Constant: "expand 32-byte k"
   - Key: 생성된 32바이트
   - Counter: 0
   - Nonce: 생성된 8바이트
   ↓
4. 파일 크기/타입에 따라 암호화 전략 선택
   - 작은 파일: 전체 암호화
   - 큰 파일: 선택적 청크 암호화
   - 특정 타입: 헤더만 암호화
   ↓
5. ChaCha8 블록 암호화
   - 4번의 더블 라운드
   - 키스트림 생성
   - XOR 연산
   ↓
6. 메타데이터 생성 및 암호화
   - [Key | Nonce | 파일명 길이 | 파일명]
   - RSA 공개키로 암호화
   - 파일 footer에 추가
   ↓
7. 파일명 변경
   원본.확장자 → 원본.확장자.dragonforce_encrypted

 

함수 호출 관계도 (Call Graph)

 

5. 복호화 기술 분석 (Decryption Strategy)


5.1 복호화 가능성 분석

DragonForce 랜섬웨어는 다음과 같은 특성으로 인해 완벽한 복호화가 가능합니다:

  1. 키 생성 시점 취약점 : CryptGenRandom API 호출 시 생성되는 평문 키를 API 후킹으로 실시간 캡처 가능
  2. 메모리 덤프 가능성 : 암호화 진행 중 프로세스 메모리에 평문 키가 존재
  3. 파일별 독립 암호화 : 각 파일마다 별도의 키를 사용하므로, 해당 키만 있으면 개별 파일 복호화 가능
  4. RSA 개인키 불필요 : API 후킹으로 평문 키를 직접 확보하므로, 공격자의 RSA 개인키 없이도 복호화 가능

5.2 ChaCha8 키 복구 메커니즘

DragonForce의 암호학적 약점은 CryptGenRandom API 호출 시점에 생성되는 32바이트 키와 8바이트 nonce가 평문으로 메모리에 존재한다는 점입니다.

# API 후킹 로그에서 키 추출
def extract_keys_from_log(log_file):
    keys = []
    with open(log_file, 'r') as f:
        for line in f:
            if "Length: 32 bytes" in line:
                # 다음 줄에서 키 추출
                key_line = next(f)
                key = extract_hex(key_line)  # "Data: ..." 파싱
                
                # 이어서 nonce 추출 (다음 32바이트 로그 항목)
                nonce_line1 = next(f)
                nonce_line2 = next(f)
                nonce = extract_hex(nonce_line2)
                
                keys.append((key, nonce))
    return keys

5.3 ChaCha8 복호화 스크립트 개발

캡처한 키 정보를 활용하여 Python 기반 ChaCha8 복호화 스크립트를 개발했습니다.

 

스크립트 주요 기능:

  1. API 후킹 로그 파일 파싱 (키/nonce 추출)
  2. 암호화 파일의 footer에서 메타데이터 추출 (선택적)
  3. ChaCha8 state 초기화 및 키스트림 생성
  4. XOR 연산을 통한 복호화 수행
  5. 원본 파일 복원 및 저장
def chacha8_decrypt(ciphertext, key, nonce):
    """
    ChaCha8 복호화 (ChaCha20의 8라운드 변형)
    """
    # 1. ChaCha State 초기화
    state = initialize_chacha_state(key, nonce, counter=0)
    
    # 2. 블록 단위 복호화
    plaintext = bytearray()
    block_size = 64  # ChaCha는 64바이트 블록
    
    for block_idx in range(0, len(ciphertext), block_size):
        # 키스트림 생성 (4번의 더블 라운드)
        keystream = chacha8_block(state, counter=block_idx // block_size)
        
        # XOR 복호화
        block = ciphertext[block_idx:block_idx + block_size]
        for i in range(len(block)):
            plaintext.append(block[i] ^ keystream[i])
    
    return bytes(plaintext)

def chacha8_block(initial_state, counter):
    """
    ChaCha8 키스트림 블록 생성 (4번의 더블 라운드)
    """
    state = initial_state.copy()
    state[12] = counter  # 카운터 설정
    
    working_state = state.copy()
    
    # 4번의 더블 라운드 (총 8번의 라운드)
    for _ in range(4):
        # Column round
        quarter_round(working_state, 0, 4, 8, 12)
        quarter_round(working_state, 1, 5, 9, 13)
        quarter_round(working_state, 2, 6, 10, 14)
        quarter_round(working_state, 3, 7, 11, 15)
        
        # Diagonal round
        quarter_round(working_state, 0, 5, 10, 15)
        quarter_round(working_state, 1, 6, 11, 12)
        quarter_round(working_state, 2, 7, 8, 13)
        quarter_round(working_state, 3, 4, 9, 14)
    
    # Add initial state
    for i in range(16):
        working_state[i] = (working_state[i] + state[i]) & 0xFFFFFFFF
    
    # Convert to bytes (keystream)
    return state_to_bytes(working_state)

5.4 무결성 검증

복구된 파일의 유효성을 판단하기 위해 파일 헤더 시그니처(매직 넘버)를 검증합니다.

파일 유형 매직 넘버 (Hex) 설명
JPG FF D8 FF JPEG 이미지 파일
PNG 89 50 4E 47 0D 0A 1A 0A PNG 이미지 파일
GIF 47 49 46 38 GIF 이미지 파일
PDF 25 50 44 46 PDF 문서 파일
EXE/DLL 4D 5A (MZ) Windows 실행 파일
ZIP/DOCX 50 4B 03 04 압축 파일 및 MS Office
DOC (Old) D0 CF 11 E0 MS Office 구버전
TXT 가독 문자 비중 70% 이상 텍스트 파일 판별 로직
def verify_decryption(decrypted_data, expected_filetype):
    """
    복호화된 데이터의 매직 넘버 검증
    """
    magic_numbers = {
        'jpg': bytes([0xFF, 0xD8, 0xFF]),
        'png': bytes([0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A]),
        'pdf': bytes([0x25, 0x50, 0x44, 0x46]),
        'exe': bytes([0x4D, 0x5A]),
        'zip': bytes([0x50, 0x4B, 0x03, 0x04]),
        # ... 추가 파일 타입
    }
    
    if expected_filetype in magic_numbers:
        expected_magic = magic_numbers[expected_filetype]
        return decrypted_data.startswith(expected_magic)
    
    return True  # 알 수 없는 타입은 검증 생략

 

6. 요약 및 결론 (Conclusion)


6.1 최종 평가

DragonForce 랜섬웨어는 ChaCha8 스트림 암호화와 RSA 하이브리드 방식, 멀티스레드 기반 고속 처리를 특징으로 하는 정교한 악성코드입니다. 그러나 키 생성 과정에서 CryptGenRandom API를 직접 호출하는 구조적 취약점으로 인해, API 후킹을 통한 실시간 키 캡처가 가능하며, 이를 활용한 완벽한 복호화가 실증되었습니다.

[취약점 요약]
CryptGenRandom API 호출
         ↓
   평문 키 생성 (32B)
         ↓
  ★ API 후킹 지점 ★  ← 키 캡처 가능!
         ↓
  ChaCha State 초기화
         ↓
   파일 암호화 수행

6.2 대응 가이드

6.2.1 예방적 조치

  1. API 모니터링 강화
    • CryptGenRandom, BCryptGenRandom 등 암호화 API 호출을 실시간 모니터링하는 EDR 솔루션 배치
    • 의심스러운 대량의 난수 생성 패턴 탐지
  2. 행위 기반 탐지
    • 멀티스레드 기반의 대량 파일 접근 패턴 탐지
    • .dragonforce_encrypted 확장자 추가 행위 차단
    • 파일 footer에 메타데이터 기록 행위 모니터링
  3. 파일 시스템 보호
    • 실시간 백업 시스템 구축 (VSS, 증분 백업)
    • 중요 디렉터리에 대한 접근 제어 강화

6.2.2 사후 대응

  1. 초동 조치
    • 감염 발견 즉시 시스템 격리 (네트워크 차단)
    • 시스템을 종료하지 말고 메모리 덤프(Full Memory Dump) 수행
    • 프로세스 메모리에서 CryptGenRandom 생성 키 추출 시도
  2. 키 복구 시도
    • API 후킹 도구(Frida, Detours 등)를 사용하여 CryptGenRandom 호출 로그 확보
    • 메모리 포렌식을 통한 평문 키 탐색
    • 로그 파일 또는 메모리 덤프에서 32바이트 키 패턴 추출
  3. 복호화 수행
    • 본 보고서에서 제공하는 ChaCha8 복호화 스크립트 활용
    • 추출한 키/nonce로 암호화된 파일 복원
    • 매직 넘버 검증을 통한 복호화 성공 여부 확인

6.3 기술적 특징 요약

항목 세부 내용
암호화 알고리즘 ChaCha8 (4번의 더블 라운드) + RSA (메타데이터)
키 관리 파일별 독립 32바이트 키 + 8바이트 nonce
암호화 전략 파일 크기/타입에 따라 전체/부분/헤더 암호화 선택
멀티스레딩 CreateThread 기반 워커 스레드 병렬 처리
메타데이터 RSA로 암호화된 키 정보를 파일 footer에 저장
확장자 .dragonforce_encrypted
복호화 가능성 API 후킹 또는 메모리 덤프로 키 확보 시 100% 복구 가능

6.4 결론

DragonForce 랜섬웨어는 ChaCha8과 RSA를 결합한 하이브리드 암호화 방식과 멀티스레드 기반 고속 암호화를 특징으로 하는 위협적인 악성코드입니다. 그러나 키 생성 과정의 구조적 취약점으로 인해, 적절한 대응 절차(API 후킹, 메모리 포렌식)를 통해 평문 키를 확보할 경우 RSA 개인키 없이도 완벽한 복호화가 가능합니다. 분석을 통해 개발된 ChaCha8 복호화 도구는 DragonForce 감염 피해 복구에 직접 활용될 수 있으며, 유사한 ChaCha 기반 랜섬웨어 대응에도 응용 가능합니다. 향후 랜섬웨어 대응을 위해서는 암호화 API 모니터링 강화실시간 메모리 포렌식 체계 구축이 필수적입니다.