안랩, CryptXXX 암호화 비밀과 복구 툴 공개
크립트엑스엑스엑스(CryptXXX) 랜섬웨어는 정상 파일을 암호화한 후 '.crypt' 확장자로 변경하여 사용자에게 비트코인을 요구하는 랜섬웨어다. 이 랜섬웨어는 현재까지 버전 1.x, 2.x, 3.x 세 가지 형태가 알려져 있다. 안랩은 현재 크립트엑스엑스엑스 2.x 버전에 의해 암호화된 파일에 대한 복구 툴을 제공하고 있다. 특히, 국내 사용자들이 많이 사용하고 있으나 기존 복구 툴이 지원하지 않는 한글 파일(HWP)의 복구도 가능하다는 점이 주목할만하다.
이 글에서는 크립트엑스엑스엑스 2.x 버전의 암호화 방식과 안랩이 제공하는 복구 툴에 대해 소개한다.
▶관련 콘텐츠: CryptXXX 랜섬웨어 분석 완료∙∙∙복구 툴 제공
1. 암호화 방식
[그림1]은 크립트엑스엑스엑스에 의해 암호화된 'Photo.jpg' 파일을 나타낸다. 암호화는 고정 크기(0x1FFF)의 블록 단위로 순차적으로 이뤄지며, 암호화 최대 크기는 0xD012FE(대략 13M)로 이후의 데이터는 원본과 동일하다.
암호화된 파일은 원본 파일과 비교하여 260(=0x104)바이트가 증가한 형태이며, 이는 파일 끝부분에 삽입된 키 테이블(Key Table) 정보로 인한 것이다([그림 1]에서 붉은색 블록 참고). 이 키 테이블 정보는 블록 단위의 암호를 복호화하는 데 핵심이 되는 데이터로, 공개키를 통해 암호화되어 저장된다. 즉, 구조적으로는 해당 공개키에 매칭되는 개인키 정보 없이는 해당 키 테이블 정보를 복호화할 수 없고, 파일 복구가 불가능하다. 하지만, 해당 키 테이블 정보는 개인키 없이도 원본 파일 시작 부분의 일부 데이터(예를 들면 파일 포맷별 Magic 정보)를 통해 파일의 형태를 확인할 수 있으며, 그것을 토대로 유추할 수 있는 키 값으로 복구가 가능하다.
2. Key Table 생성 방식과 취약성
[그림 2]는 파일 끝에 삽입된 0x104바이트 크기의 키 테이블이 생성되는 과정을 나타낸다. 이 그림에서 노란색 부분이 공개키로 암호화된 KeyTable_A[0x40]이며, CryptEncrypt() API를 통해 공개키로 암호화 시 원본 0x40바이트 크기의 데이터가 최종 0x80바이트 크기로 증가된다.
[그림2]에서 언급된 암호화에 사용되는 핵심 정보 3가지는 ‘4바이트 SEED 값’, ‘KeyTable_A[0x40]’, 'KeyTable_B[0x100]'이며, 최초 4바이트 크기의 SEED 값으로부터 이후 정보들이 순차적으로 만들어지는 구조를 갖는다. 키 생성 과정의 최상위에 위치하는 SEED 값은 감염 시점의 시스템 시간(SystemTime) 정보 중에서 시(wHour), 분(wMinute), 초(Second), 밀리초(Millisecond)를 이용하여 얻어지며, 이 SEED 값으로부터 0x40바이트 크기의 KeyTable_A[0x40] 데이터가 생성된다. 바로 이 부분에서 제작자가 의도하지 않은 취약성이 존재하며, SEED 값이 동일하면 매번 동일한 KeyTable_A[0x40]가 생성되는 구조를 갖는다. 최종 블록 단위의 암호화에 사용되는 KeyTable_B[0x100]의 데이터와 원본 파일로부터 읽은 블록과의 XOR(배타적 논리합)을 통해 암호화가 수행된다.
즉, SEED 값이 동일하면 매번 생성되는 최종 키 테이블 정보가 동일한 점과 암호화 방식이 XOR이라는 2가지 포인트를 바탕으로 복구 대상 파일의 Magic 정보가 존재한다면, 역으로 키를 유추할 수 있는 구조다. [그림 3]은 SEED 값이 0x02978CAC일 때, 생성되는 키 테이블 A, B의 예를 나타낸다.
KeyTable_A[0x40] 데이터가 생성되는 방식은 다음의 2가지 기본 테이블 중, 델파이 랜덤(Delphi Random) 함수를 통해 얻은 랜덤값을 바탕으로 하나의 값이 선택되어 구성되는 구조를 갖는다.
(1) "QWERTYUIOPASDFGHJKLZXCVBNM<>:\?!@$%^&*()_+~|
(2) "qwertyuiop[]asdfghjkl;zxcvbnm,./`1234567890-="
크립트엑스엑스엑스는 총 2번의 델파이 랜덤 함수를 사용하여 아래의 Index(A)와 Index(B)를 얻게 된다. 이때 Index(A)는 위 기본 테이블 중 하나를 선택하기 위한 목적으로, Index(B)는 선택된 테이블의 데이터 중 하나를 선택하기 위한 목적으로 사용된다.
Index(A): DelphiRandom(3) - 0 ~ 2 범위의 랜덤 값 생성(0, 2인 경우 -> (1)번, 1인 경우 -> (2))
Index(B): DelphiRandom(44) - 0 ~ 43 범위의 랜덤 값 생성
예를 들어 Index(A) == 0이고, Index(B) == 3이면, ‘R’ 문자열이 선택된다.
3. 키 테이블 생성 함수
크립트엑스엑스엑스 랜섬웨어에서 파일 암호화 시 사용되는 핵심 정보 3가지의 생성 함수는 다음과 같다.
(1) SEED 값 생성
[그림4]는 SystemTime 정보를 통해 4바이트 크기의 SEED 값을 생성하는 함수를 나타낸다.
(2) 키 테이블(A) 생성
[그림5]는 SEED 값을 바탕으로 0x40바이트 크기의 키 테이블을 생성하는 함수이며, do-while 문을 통해 생성되는 0x40바이트 크기의 데이터가 SEED 값이 동일하면 동일한 형태로 생성되는 취약성이 존재하는 부분이다.
(3) 키 테이블(B) 생성
[그림 6]은 키 테이블(A)로부터 0x100바이트 크기의 최종 키 테이블(B)가 생성되는 함수를 나타낸다. 이 키 테이블 정보는 1바이트 단위의 블록 단위의 암호화 시 XOR 키 값으로 사용된다.
4. 복구 방식
시, 분, 초, 밀리초 정보를 통해 계산되는 SEED 값의 범위는 다음과 같다.
- 최소값: 00:00:00:0000 -> 0, 최대값: 23:59:59:999 -> 0x5265bff
사용자마다 그리고 암호화된 파일마다 서로 다른 SEED 값을 유추하기 위해 0 ~ 0x5265bff 범위의 SEED를 순차적으로 선택하며, 이를 바탕으로 암호화에 사용된 키 테이블을 생성하거나 복호화를 시도한다. 첫 번째 블록에 대한 복호화를 통해 파일의 고유한 식별 정보(Magic)가 확인되면, 유효한 SEED 값으로 판단하고 전체 파일에 대한 블록 단위의 복구를 시도한다. 우선 첫 번째 파일이 복구에 성공하면, 두 번째 파일부터는 SEED의 범위를 제한하여 좀 더 빠른 복구가 가능하도록 했다. 이러한 설정은 복구 대상 파일들이 동일 시간대에 감염된 형태가 대부분일 것으로 가정하여 이루어진 것으로, 복구 대상 파일들이 서로 다른 시스템에서 다른 시간대에 수집된 형태의 경우, 복구 시간이 더 오래 걸리는 특징을 갖는다.
[그림7]은 크립트엑스엑스엑스 복구 툴에서 파일 복구를 위해 이루어지는 과정을 나타낸 것이다. 구조상 첫 번째 파일을 복구하는 데 오랜 시간이 소요되며, 이후 파일부터는 빠르게 복구가 가능하다.
5. 복구 대상 리스트
복구 툴을 통해 복구 가능한 크립트엑스엑스엑스 버전은 2.x로 제한적이며, 우선 다음의 확장자들에 대한 복구가 가능하도록 제작되었다. 특히, 국내 사용자들이 많이 사용하고 있으나 기존 복구 툴이 지원하지 않는 한글 파일(HWP)의 복구가 가능하다. 이 외에도 원본 파일의 고유한 식별 정보만 알 수 있다면, 복구가 가능한 구조이기 때문에 추후 복구 대상으로 추가될 수 있다.
CHM, AI, HWP, PDB, PDF, RTF, HTM, HTML, PHP, XML, DWG, PS, WSF, KEY, CSR, CRT, WAV, MP3, OGG, WMA, WMV, AVI, ASF, MP4, MOV, MID, MPG, FLV, PNG, GIF, BMP, TIF, JPG, JPEG, ZIP, RAR, BZ2, 7Z, GZ, JAR, APK, TGZ, ODS, DOC, DOT, PPT, POT, PPS, XLS, XLT, DOCX, DOCM, DOTX, DOTM, PPTX, PPTM, POTM, POTX, PPSM, XLSX, XLSB, XLSM, XLTM, XLTX, EPS, ISO, SQLITE3, MDB, MSI, APP, FDB, ACCDB, SLN, CLASS, VCXPROJ
6. 복구 툴 경로
안랩은 크립트엑스엑스엑스 랜섬웨어 2.x 버전에 대한 복구 툴을 랜섬웨어 보안센터를 통해 무료로 제공하고 있다.
- AhnLabASEC 분석팀