1. 개요 (Overview)
1.1 분석 배경
WannaCry는 2017년 전 세계적으로 대규모 피해를 입힌 랜섬웨어로, SMB 취약점(EternalBlue)을 통한 자가 전파 기능과 AES + RSA 혼합 암호 구조를 사용한다. 특히 Windows CryptoAPI 호출 시 생성된 대칭키가 메모리에 평문으로 남는 구조적 결함을 이용하면 복구가 가능하다.
1.2 핵심 요약
- 동적 모듈 로딩 : 리소스 내부에 암호화된 상태로 존재하는 DLL을 실행 시점에 메모리에서 복구하여 실제 암호화 로직을 구동한다.
- 하이브리드 암호화 : 파일별로 생성된 AES-128 키를 사용자용 RSA-2048 공개키로 보호하는 다층 구조를 채택하고 있다.
- 추출 데이터 기반 복구 : 키 생성 API 호출 시점을 가로채어 획득한 16바이트 대칭키 정보를 활용하면 공격자의 개인키 없이도 원본 데이터 복구가 가능하다.
2. 식별 정보 (Identification)
- Malware Family: WannaCry (WanaCrypt0r 2.0)
- Filetype: PE32 (Windows Executable)
- Hash (SHA256): ed01ebfbc9eb5bbea545af4d01bf5f1071661840480439c6e5babe8e080e41aa
- Extension: .WNCRY
- Ransom Note: @Please_Read_Me@.txt
- Encryption: AES-128-CBC + RSA-2048
3. 분석 환경 및 도구 (Tools)
| 구분 | 도구명 (Tool) | 용도 (Purpose) |
| 정적 분석 | IDA Pro | 바이너리 디스어셈블리 및 주요 암호화 서브루틴 분석 |
| 동적 분석 | x64dbg | 런타임 디버깅 및 메모리 내 키 데이터 추출 |
| 행위 분석 | Process Monitor | 파일 권한 변경 및 자가 복제 행위 추적 |
| 검증 도구 | Python | 후킹 데이터 기반 복호화 로직 구현 및 시그니처 검증 |
4. 암호화 기술 분석 (Technical Analysis)
4.1 초기화 및 설치
WannaCry는 실행 인자에 따라 동작 모드를 달리한다.
- 설치 모드 (i) : CopyFileA를 통해 자기 자신을 복제하고 시스템 서비스로 등록을 시도한다.
- 암호화 모드 (인자 없음) :
- 작업 디렉토리 설정(SetCurrentDirectoryA)
- 시스템 내 암호화 대상 파일 목록 수집
- 파일 권한을 변경하여 모든 사용자가 수정 가능하도록 조작(icacls)
4.2 암호화 DLL 로더
WannaCry의 실제 암호화 로직은 실행 파일 내부가 아닌, 리소스에 포함된 t.wnry 파일(암호화된 DLL 컨테이너)에 존재한다.
- 헤더 검증 : "WANACRY!" 매직 넘버 확인.
- 키 복구 : 내부 저장된 RSA 개인키로 AES 키를 복호화하여 t.wnry 내부의 DLL을 메모리 상에서 복구한다.
- 실행 : 복구된 DLL 내의 암호화 함수 포인터를 획득하여 호출한다.
4.3 키 생성 및 관리
WannaCry는 다층 구조의 키 관리 체계를 가진다.
- 사용자 RSA 키쌍 생성 : CryptGenKey를 통해 RSA-2048 키쌍(VPU/VPR)을 생성한다.
- 00000000.pky : 사용자 공개키 (Plaintext 저장)
- 00000000.eky : 사용자 개인키 (공격자의 마스터 공개키로 암호화되어 저장)
- 파일별 AES 키 생성 : 각 파일을 암호화할 때마다 CryptGenRandom(16)을 호출하여 고유한 AES-128 키를 생성한다.
4.4 파일 암호화 매커니즘
파일 암호화 시 다음과 같은 구조로 데이터를 재구성한다.
- 알고리즘 : AES-128-CBC (IV = 16바이트 Zero)
- 파일 구조:
- 0x00 : 매직 넘버 ("WANACRY!")
- 0x08 : RSA로 암호화된 AES 키 크기 (256바이트)
- 0x0C : RSA(VPU)로 암호화된 AES 세션 키
- 0x110 : 원본 파일 크기 (8바이트)
- 0x118 : AES-CBC로 암호화된 데이터
4.5 정적 분석
- 실행 파일 경로 획득 / 고유한 랜덤 서비스명 생성 (컴퓨터별)

- 인자 여부에 따른 실행 모드 분기
- “-i” 인자가 있을 때 : 설치/서비스 모드


- 설치 디렉터리 생성

- 디렉토리에 Hidden + System 속성 설정

- tasksche.exe를 Windows 서비스로 등록하고 시작



조건 1: 인자 개수가 2개인가? (WannaCry.exe /i)
↓
조건 2: 두 번째 인자가 "/i"인가?
↓
조건 3: 설치 디렉토리 생성 성공?
- 우선순위 1: C:\ProgramData\[랜덤이름]
- 우선순위 2: C:\Intel\[랜덤이름]
- 우선순위 3: %TEMP%\[랜덤이름]
- 디렉토리에 Hidden + System 속성 설정
↓
조건 4: 현재 실행 파일을 tasksche.exe로 복사
↓
조건 5: tasksche.exe 파일이 정상적으로 생성되었는지 확인
↓
조건 6: tasksche.exe를 Windows 서비스로 등록하고 시작
- 기존 서비스가 있으면 시작
- 없으면 새로 생성하고 시작
- 60초 동안 뮤텍스 생성 대기
모든 조건을 만족하면 → 설치 완료, 프로그램 종료
하나라도 실패하면 → 일반 실행 모드로 진행
- “-i” 인자가 없을 때 : 일반 실행 모드

- 레지스트리에 경로 저장 (지속성 확보)

- 랜섬웨어 리소스 추출

- 비트코인 주소 설정

- 파일 숨김 및 권한 설정



- 시스템 호환성 확인

- 메인 페이로드 복호화 및 실행
- 암호화 DLL : t.wnry 파일에서 암호화된 DLL 추출 및 복호화
- 파일 검증 : "WANACRY!" 시그니처 확인
- RSA 복호화 : RSA 개인 키로 256바이트 암호화된 데이터 복호화 → AES 키 추출
- AES 복호화 : 추출한 AES-128 키로 페이로드 데이터 복호화 (AES-128-CBC)
- 메모리 반환 : 복호화된 페이로드가 담긴 메모리 주소 반환


- AES-128-CBC 복호화

- 페이로드 진입점 탐색 (TaskStart 함수)

- 리소스 정리

1. 작업 디렉토리 설정
↓ strrchr로 파일 경로에서 마지막 '\' 찾기
↓ '\' 이후를 NULL로 변경 (디렉토리 경로만 추출)
↓ SetCurrentDirectoryA로 실행 파일의 디렉토리로 이동
2. 레지스트리에 경로 저장 (지속성 확보)
↓ registry_save_or_load_path(1) 호출
↓ HKLM\Software\WanaCrypt0r 또는 HKCU\Software\WanaCrypt0r에 현재 디렉토리 저장
3. 랜섬웨어 리소스 추출
↓ extract_zip_resources: 리소스 ID 0x80A (ZIP 파일) 추출
↓ 압축 해제하여 다음 파일들 생성:
- @WanaDecryptor@.exe (랜섬노트 UI 프로그램)
- 언어별 메시지 파일 (msg/m_*.wnry)
- 기타 리소스 파일
4. 비트코인 주소 설정
↓ setup_bitcoin_address 호출
↓ 3개 비트코인 주소 중 랜덤으로 1개 선택:
- 13AM4VW2dhxYgXeQepoHkHSQuy6NgaEb94
- 12t9YDPgwueZ9NyMgw519p7AA8isjr6SMw
- 115p7UMMngoj1pMvkpHijcRdfJNXj6LrLn
↓ __bitcoin_txt 파일에 선택한 주소 저장
5. 파일 숨김 및 권한 설정
↓ create_process_hidden("attrib +h .") - 현재 디렉토리 숨김 속성 설정
↓ create_process_hidden("icacls . /grant Everyone:F /T /C /Q")
- 모든 사용자에게 전체 권한 부여
- /T: 하위 디렉토리 포함
- /C: 오류 무시하고 계속
- /Q: 조용히 실행
6. 시스템 호환성 확인
↓ check_system_and_load_apis 호출
↓ Windows 버전 확인 (Vista 이상)
↓ 파일 작업 API 동적 로드:
- CreateFileW, WriteFile, ReadFile
- MoveFileW, MoveFileExW, DeleteFileW
- CloseHandle
7. 메인 페이로드 복호화 및 실행
↓ init_resource_manager - 리소스 관리자 초기화
↓ prepare_resource_buffers - 리소스 버퍼 준비
↓ extract_and_decrypt_resource("t.wnry") - t.wnry 파일 복호화:
│ ├ 파일 시그니처 확인: "WANACRY!"
│ ├ RSA로 암호화된 AES 키 256바이트 읽기
│ ├ RSA 개인키로 AES 키 복호화
│ └ AES-128로 페이로드 복호화
↓ decompress_payload - 복호화된 페이로드 압축 해제
↓ get_payload_entry_point("TaskStart") - 페이로드에서 "TaskStart" 함수 찾기
↓ 페이로드 진입점 실행 → **메인 랜섬웨어 활동 시작**
│ ├ 파일 암호화 시작
│ ├ 랜섬노트 표시
│ ├ 네트워크 공격 (SMB 취약점 악용)
│ └ 시스템 복구 방지 (섀도우 복사본 삭제 등)
↓ cleanup_resource_manager - 리소스 정리
8. 프로그램 종료
5. 복호화 기술 분석 (Decryption Strategy)
5.1 동적 API 후킹을 통한 키 데이터 캡처
WannaCry는 탐지를 피하기 위해 암호화 API를 동적으로 로드한다. 이 호출 시점을 가로채어 복구에 필요한 핵심 인자들을 JSON 형태로 확보한다.
- 대칭키 원천 데이터 확보 : 암호화 모듈이 CryptGenRandom을 호출하여 생성하는 16바이트 난수를 캡처한다.
- 비대칭키 구조 재구성 : CryptExportKey 호출 시 노출되는 PRIVATEKEYBLOB을 가로채어 RSA 개인키의 구성 요소(modulus, prime1, prime2, exponent 등)를 복원한다.
5.2 암호화 컨테이너 및 헤더 분석
복호화를 위해 .WNCRY 파일의 구조를 정밀하게 파싱하여 암호화된 본문과 메타데이터를 분리한다.
- 헤더 식별 및 검증 : 파일 선두 8바이트의 매직 넘버(WANACRY!)를 통해 대상 파일 여부를 확인한다.
- 메타데이터 추출 :
- 키 블록 파싱 : RSA로 암호화된 AES 키의 크기(필드 0x08)를 읽어 데이터 오프셋을 계산한다.
- 원본 크기 복원 : 파일 종단에 추가된 패딩을 제거하기 위해 8바이트의 원본 크기(Original Size) 정보를 확보한다.
5.3 복호화 알고리즘 구현
캡처된 키 후보군을 순차적으로 대입하여 CBC 모드 복호화를 수행하는 핵심 로직이다.
def execute_aes_decryption(cipher_payload, key_candidate, original_size):
"""
AES-128-CBC 알고리즘을 이용한 데이터 복구 로직
"""
# IV(초기화 벡터)는 16바이트 Zero로 고정됨
initial_vector = b'\x00' * 16
# 1. 블록 크기(16바이트) 정렬을 위한 패딩 처리
if len(cipher_payload) % 16 != 0:
cipher_payload += b'\x00' * (16 - (len(cipher_payload) % 16))
# 2. CBC 모드 복호화 엔진 초기화 및 실행
cipher_engine = AES.new(key_candidate, AES.MODE_CBC, initial_vector)
decrypted_raw = cipher_engine.decrypt(cipher_payload)
# 3. 메타데이터에 기록된 원본 크기만큼 데이터 절삭 (패딩 제거)
return decrypted_raw[:original_size]
5.4 다중 키 전수조사 및 무결성 검증
후킹된 JSON 로그에 여러 개의 키가 존재할 경우, 각 키로 복호화된 결과물의 상위 바이트(Magic Number)를 대조하여 최종 복구 성공 여부를 판별한다.
def verify_restored_content(data, ext):
"""
복호화된 데이터의 파일 포맷 시그니처 검증
"""
# 1. 파일 크기 임계값 검사
if len(data) < 4: return False, "Invalid Length"
# 2. 확장자별 매직 넘버 대조 (Whitelisting 방식)
magic = data[:4]
if ext in ['.JPG', '.JPEG'] and magic[:3] == b'\xFF\xD8\xFF':
return True, "✅ JPEG 이미지 확인"
elif ext == '.PNG' and magic == b'\x89PNG':
return True, "✅ PNG 이미지 확인"
elif ext == '.PDF' and magic[:4] == b'%PDF':
return True, "✅ PDF 문서 확인"
elif ext in ['.DOCX', '.XLSX'] and magic[:2] == b'PK':
return True, "✅ MS Office (OpenXML) 확인"
return False, "잘못된 복호화 시도"
6. 요약 및 결론 (Conclusion)
6.1 설계 의도 및 암호학적 한계
WannaCry는 설계 당시 공격자의 마스터 개인키(Master Private Key) 없이는 원본 데이터 복구가 불가능하도록 의도된 고강도 암호화 아키텍처를 보유하고 있다. 그러나 실제 구현 과정에서 파일 암호화에 직접적으로 관여하는 대칭키(AES-128) 생성 시점에 Windows CryptoAPI를 호출하며, 이 과정에서 키 데이터가 메모리 상에 평문(Plaintext)으로 노출되는 치명적인 설계 결함이 확인되었다.
6.2 데이터 복구 가능성 입증
본 분석을 통해 실시간 API 후킹으로 확보된 CryptGenRandom의 페이로드를 활용한 복구 메커니즘을 검증하였다. 이를 통해 공격자와의 타협이나 비용 지불 없이도 감염된 시스템 내부의 원본 파일을 안정적으로 복원할 수 있음을 입증하였으며, 이는 랜섬웨어 대응 전략에 있어 매우 중요한 기술적 근거가 된다.
7. 대응 및 예방 가이드 (Mitigation & Recovery)
7.1 초동 조치 및 데이터 보존 전략
- 프로세스 유지 및 메모리 보호 : 감염 식별 시 랜섬웨어 프로세스를 즉시 종료하거나 시스템을 재부팅하는 행위는 메모리에 상주하는 키 데이터를 소멸시키므로 지양해야 한다.
- 동적 데이터 추출 : 프로세스가 실행 중인 상태에서 메모리 덤프를 획득하거나 API 후킹 로그를 확보하여, 파일 복호화의 핵심인 CryptGenRandom 생성 키와 PRIVATEKEYBLOB 데이터를 선제적으로 추출해야 한다.
- 네트워크 격리 : 자가 전파를 차단하기 위해 즉시 네트워크를 차단하되, 시스템 전원은 유지하여 휘발성 증거(Volatile Evidence)를 보존하는 것이 복구의 핵심이다.
7.2 기술적 복구 프로세스
- 추출 키 기반 전수조사 : 확보된 AES 키 리스트를 복호화 엔진에 입력하여 .WNCRY 파일의 헤더 파싱 결과와 대조한다.
- 자동화 복구 수행 : 검증된 대칭키를 활용하여 decrypted 폴더 내에 원본 데이터를 재생성하며, 파일 시그니처 대조를 통해 복구 데이터의 무결성을 최종 확인한다.
부록: 침해 지표 (IOC)
| 구분 | Type | Value |
| Hash | SHA256 | ed01ebfbc9eb5bbea545af4d01bf5f1071661840480439c6e5babe8e080e41aa |
| File | Resource | t.wnry (Encrypted DLL Container) |
| Magic | String | WANACRY! |
| Extension | Suffix | .WNCRY |
'랜섬웨어 분석 보고서' 카테고리의 다른 글
| Lynx 랜섬웨어 분석 보고서 (0) | 2026.01.01 |
|---|---|
| Mamona 랜섬웨어 분석 보고서 (0) | 2026.01.01 |
| Nitrogen 랜섬웨어 분석 보고서 (0) | 2025.12.31 |
| Donut 랜섬웨어 분석 보고서 (0) | 2025.12.29 |
| Babuk 랜섬웨어 분석 보고서 (0) | 2025.12.26 |