랜섬웨어 분석 보고서

Lynx 랜섬웨어 분석 보고서

geonwoo9643 2026. 1. 1. 23:24

1. 개요 (Overview)


1.1 분석 배경

Lynx 랜섬웨어는 2024년 중반부터 활동이 두드러진 악성코드로, INC Ransom → LYNX → Sinobi로 이어지는 리브랜딩 계보의 핵심 변종입니다. 특히 Sinobi와 암호화 엔진을 공유하며, 단순 대칭키 암호화를 넘어 ECDH(Curve25519) 기반의 정교한 키 교환 메커니즘을 채택하고 있습니다. 본 보고서는 Lynx의 암호학적 아키텍처를 정밀 분석하고, 세션 키 생성 과정의 취약점을 이용한 데이터 복구 전략을 제안합니다.


1.2 핵심 요약

  • 고도화된 키 교환 아키텍처 : RSA 기반의 단순 구조를 탈피하여, Curve25519 타원 곡선 암호와 SHA-512 KDF(Key Derivation Function)를 결합한 세션 키 생성 모델을 운용합니다.
  • 고성능 암호화 엔진 : AES-128 CTR(Counter) 모드를 사용하여 병렬 처리를 지원하며, 파일 끝에 116바이트의 독자적인 메타데이터 마커를 삽입합니다.
  • 조건부 복구 가능성 : 공격자의 RSA 개인키가 없더라도, 난수 생성 API(CryptGenRandom) 호출 시점에 생성된 32바이트 클라이언트 시드를 메모리 포렌식으로 확보할 경우 완벽한 복구가 가능합니다.

 

2. 식별 정보 (Identification)


  • Malware Family: Lynx (INC Ransom / Sinobi 계보)
  • Filetype: PE32 (Windows Executable)
  • Hash (SHA256): 0315dbb793f855f154aa8d227151f1098bd9b580a4f85064648b85bac1321663
  • Extension: .LYNX
  • Ransom Note: README.txt
  • Target: Windows Enterprise Environment

 

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


구분 도구명 (Tool) 용도 (Purpose)
정적 분석 IDA Pro Curve25519 Montgomery Ladder 및 SHA-512 구현 루틴 분석
동적 분석 x64dbg CryptGenRandom 호출 시점의 32바이트 난수(시드) 추출
행위 분석 Process Monitor 파일 I/O 완료 포트(IOCP) 및 워커 스레드 행위 추적
검증 도구 Python cryptography 라이브러리를 이용한 ECDH 키 파생 및 복구 PoC

 

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


4.1 전체 암호화 워크플로우

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

  1. 시드 생성 : Windows CryptoAPI의 CryptGenRandom을 통해 32바이트 클라이언트 시드를 생성합니다.
  2. ECDH 키 교환 : 생성된 시드를 Curve25519 표준에 맞게 Clamping한 후, 하드코딩된 서버 공개키와 연산하여 공유 비밀(Shared Secret)을 도출합니다.
  3. 키 파생(KDF) : 공유 비밀을 SHA-512로 해싱하여 AES-128 키(16B)와 초기 카운터(16B)를 추출합니다.
  4. 병렬 암호화 : AES-128 CTR 모드로 데이터를 암호화하며, I/O 완료 포트(IOCP)를 통해 워커 스레드가 1MB 청크 단위로 처리합니다.

4.2 키 생성 및 관리 (Key Generation)

4.2.1 Curve25519 스칼라 포맷팅 (Clamping)

Lynx는 생성된 32바이트 난수를 그대로 사용하지 않고, RFC 7748 표준에 따른 비트 조작 과정을 거쳐 타원 곡선 연산의 안전성을 확보합니다.

// IDA Pro 정적 분석 데이터 기반 재구성
client_private[0] &= 0xF8;      // 하위 3비트 클리어 (Small Subgroup 공격 방지)
client_private[31] &= 0x7F;     // 최상위 비트 클리어
client_private[31] |= 0x40;     // 비트 6 설정 (표준 X25519 형식)

 

4.2.2 SHA-512 기반 키 추출 결함

생성된 공유 비밀은 SHA-512 해시 함수를 통해 확장됩니다. 이 과정에서 AES 키와 CTR 카운터가 인접하게 배치됩니다.

  • AES-128 Key : hash_output[0:16]
  • CTR Counter : hash_output[16:32] (Big-endian)

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

Lynx는 대규모 엔터프라이즈 환경을 타겟팅하므로, 효율적인 파일 처리를 위해 OVERLAPPED I/O워커 스레드 모델을 사용합니다.

  • 작은 파일 (Case 2) : 직접 메타데이터를 삽입하고 즉시 처리.
  • 큰 파일 (Case 3) : 매직 바이트 체크 후 IO 완료 포트에 큐잉하여 백그라운드에서 병렬 암호화.
  • 메타데이터 삽입 : 암호화가 완료된 파일 끝에 클라이언트 공개키와 식별 문자열("LYNX")을 포함한 116바이트를 추가 기록합니다.

4.4 정적 분석

  • 랜덤 키 생성 (32바이트)

 

  • Curve25519 키 클램핑

 

  • ECDH 키 교환 (공유 비밀 생성)

 

  • 공격자 공개키 하드코딩

 

  • SHA-512 Hash 함수 (키 파생)

 

  • SHA-512 업데이트 함수

 

  • SHA-512 압축 함수

 

  • 패딩 추가 및 해시 출력 (64바이트)

 

  • AES 키 확장 (10라운드)

 

  • AES 암호화 (AES-128-CTR)

 

  • 파일 암호화

1. ECDH: shared_secret = curve25519(private_key, attacker_public_key)
2. KDF: hash = SHA512(shared_secret)  # 64바이트
3. 키 추출:
   - aes_key = hash[0:16]      # AES-128 마스터 키
   - counter = hash[16:32]     # CTR 초기 카운터
4. 키 확장: expanded_key = aes128_key_expansion(aes_key)  # 176바이트
5. 암호화: ciphertext = AES-128-CTR(plaintext, expanded_key, counter)
   - 1MB 청크 단위 처리
   - 마지막 116바이트는 암호화하지 않음
6. 메타데이터: 파일 끝에 116바이트 추가 (공개키, 해시, "LYNX")
7. 파일명 변경: 원본.확장자 → 원본.확장자.LYNX

 

  • 파일 처리

[파일 처리 과정]
1. 파일 열기 및 크기 확인
   ↓
2. ECDH 키 교환
   - 랜덤 개인키 생성
   - 공유 비밀 계산
   - SHA-512로 키 파생
   ↓
3. AES 키 준비
   - 마스터 키: hash[0:16]
   - CTR 카운터: hash[16:32]
   - 확장 키: 176바이트
   ↓
4. OVERLAPPED 구조체 구성
   - 파일 정보
   - 암호화 키/카운터
   - 메타데이터 (116바이트)
   ↓
5. IO 완료 포트에 큐잉
   - 작은 파일: 케이스 2 (직접 메타데이터)
   - 큰 파일: 케이스 3 (매직 바이트 체크)
   ↓
6. 워커 스레드가 처리
   (encryption_worker_thread)
   
[출력]
원본파일명.LYNX (암호화된 파일)

 

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


5.1 세션 키 복구 메커니즘

Lynx의 유일한 암호학적 약점은 세션 키의 원천이 되는 32바이트 난수가 생성 직후 메모리에 평문으로 남거나, API 모니터링을 통해 탈취 가능하다는 점입니다.

def derive_lynx_keys(captured_seed):
    # 1. Clamping 수행 (X25519 표준)
    private_key = bytearray(captured_seed)
    private_key[0] &= 248
    private_key[31] = (private_key[31] & 127) | 64
    
    # 2. 공유 비밀 도출
    server_pub = x25519.X25519PublicKey.from_public_bytes(ATTACKER_PUB_KEY)
    shared_secret = x25519.X25519PrivateKey.from_private_bytes(private_key).exchange(server_pub)
    
    # 3. SHA-512 해시에서 키셋 분리
    kdf_output = hashlib.sha512(shared_secret).digest()
    return kdf_output[:16], kdf_output[16:32] # AES_KEY, COUNTER

5.2 무결성 검증

복구된 키의 유효성을 판단하기 위해 파일 헤더 시그니처를 대조합니다.

파일 유형 매직 넘버 (Hex) 설명
EXE/DLL 4D 5A 윈도우 실행 파일
ZIP/DOCX 50 4B 03 04 압축 파일 및 MS 오피스
PNG 89 50 4E 47 이미지 파일 시그니처

 

6. 요약 및 결론 (Conclusion)


6.1 최종 평가

Lynx 랜섬웨어는 Curve25519와 SHA-512를 결합하여 암호학적으로 매우 견고하게 설계되었습니다. 하지만 세션 키 생성의 기점이 되는 32바이트 시드 값이 메모리상에 노출될 수 있다는 점이 복구의 핵심 실마리입니다.


6.2 대응 가이드

  1. 초동 조치 : 감염 발생 즉시 시스템을 종료하지 말고, 메모리 덤프(Full Memory Dump)를 수행하여 CryptGenRandom에 의해 생성된 난수 시퀀스를 확보해야 합니다.
  2. 모니터링 강화 : Curve25519, SHA-512, AES-CTR 관련 암호 라이브러리를 빈번하게 호출하거나 파일 끝에 116바이트의 고정 데이터를 쓰는 프로세스를 탐지하도록 EDR 정책을 최적화하십시오.