본문 바로가기

Reversing/Malware Analysis

[LockBit 3.0] RaaS 랜섬웨어 분석 (LockBit Black)

목차
 

1. 개요
   1.1) 배경
   1.2) 랜섬웨어 빌더 유출
   1.3) 감염 시 증상

2. 상세 분석
   2.1) 분석 파일 정보
   2.2) 페이로드 실행 환경 구성
   2.3) 페이로드 복호화 과정
   2.4) API Resolve
   2.5) 암호화된 랜섬웨어 행위 코드 복호화
   2.6) 자식 프로세스 생성 후 프로세스 할로잉 수행
   2.7) 랜섬웨어 행위 코드 분석
      2.7.1) Fake IAT
      2.7.2) 랜섬웨어 행위 코드 API Resolve
      2.7.3) API 호출 전 실행되는 트램폴린
      2.7.4) 사용되는 문자열 복호화
      2.7.5) 해시 기반으로 Image Name 비교
      2.7.6) 난독화 코드 복원 작업
      2.7.7) 안티 디버깅
      2.7.8) OS 버전 확인
      2.7.9) LCG 난독화 생성 및 XOR 복호화
      2.7.10) aPlib로 압축된 config 데이터
      2.7.11) 노출되는 랜섬 노트 문자열
      2.7.12) 관리자 권한 확인
      2.7.13) UAC Bypass 및 관리자 권한으로 재실행
      2.7.14) 프로세스 권한 활성

   2.8) config 옵션 기능 분석
      2.8.1) 커맨드라인 인자 확인
      2.8.2) 특정 국가 환경 체크 - language_check
      2.8.3) 암호화 파일 확장자 생성 - set_icons
      2.8.4) 뮤텍스 생성 / 중복 실행 방지  - running_one
      2.8.5) 보안 서비스 및 프로세스 종료  - kill_defender
      2.8.6) 휴지통 관련 디렉터리 제거
      2.8.7) Shadow Copy 복사본 제거
      2.8.8) 서비스 중지 및 삭제 - kill_services
      2.8.9) 프로세스  강제 종료 - kill_process
      2.8.10) 프로세스 및 스레드 우선 순위 변경
      2.8.11) 멀티 스레드 환경 구성
      2.8.12) Key Matrix 생성 - local_disks
      2.8.13) 볼륨 강제 마운트 - local_disks
      2.8.14) Microsoft Exchange Server 대상 암호화 - local_disks
      2.8.15) 파일 속성 변경
      2.8.16) 공유 위반 프로세스 강제 종료
      2.8.17) 파일 암호화
      2.8.18) 네트워크 공유 폴더 암호화 - network_shares
      2.8.19) 이벤트 로그 무력화  - delete_eventlogs
      2.8.20) 배경화면 변경  - set_wallpaper

   2.9) 자가 삭제 - shutdown_system , wipe_freespace , self_destruct
      2.9.1) 도메인 컨트롤러 확인
      2.9.2) self_delete 구조
      2.9.3) self_delete 루틴 분석


3. 결론

4. 참고 문헌

 

 

1. 개요

1.1) 배경

LockBit은 대표적인 RaaS(Ransomware as a Service) 기반 랜섬웨어로, 2019년 ‘ABCD’ 랜섬웨어로 처음 등장하였다. 이후 2019년 LockBit 1.0을 시작으로, 2021년 LockBit 2.0, 2022년 LockBit 3.0까지 지속적으로 발전해 왔다. LockBit 운영 조직은 RaaS 모델을 활용한 제휴 프로그램을 통해 다수의 공격자를 모집하고, 이를 기반으로 대규모 공격을 수행할 수 있는 구조를 갖추고 있다. 특히 가장 활발히 활동하던 2020년경, 연구자들은 LockBit이 약 75,000달러 이상의 수익을 올린 것으로 추정하고 있다.

 

그림1) 탈취한 데이터를 전용 유출 사이트에 공개

 

LockBit은 중소기업부터 대기업, 정부 기관에 이르기까지 폭넓은 대상을 공격하며, 특히 미국과 유럽 지역에서 운영되는 IT 기업을 주요 타겟으로 삼아 왔다. 랜섬웨어 운영자들은 파일 암호화 이전에 데이터를 탈취한 뒤 이를 공개하겠다고 협박하는 ‘이중 갈취  전략을 사용한다. 피해자가 몸값 지불을 거부할 경우, 탈취한 데이터를 전용 유출 사이트에 공개하거나 최신 공격 정보를 게시함으로써 압박을 가하는 방식이다.

 

LockBit은 Black, Green 등 다양한 변종으로 유포되고 있으며, DarkSide 랜섬웨어와 BlackMatter 랜섬웨어와도 높은 코드 유사성을 보인다. 이러한 정황을 바탕으로 보안 연구자들은 이들 랜섬웨어가 동일하거나 연관된 공격 조직에 의해 개발·운영되고 있을 가능성이 높다고 분석하고 있다.

 

 

 

1.2) 랜섬웨어 빌더 유출

2022년경 LockBit 3.0(Black) 버전의 랜섬웨어 빌더가 유출되면서, 그 악명 높던 LockBit은 큰 위기에 직면하게 된다. 해당 사건은 보안 업계의 주요 관심사로 떠올랐으며, LockBit 운영 조직은 이에 대해 내부 불만을 품은 개발자가 빌더를 외부로 유출한 것이라는 공식 입장을 밝혔다.

 

빌더 유출로 인해 누구나 비교적 손쉽게 랜섬웨어를 생성·유포할 수 있는 환경이 조성되었으며, 특히 기술적 지식이 부족한 사용자들까지 랜섬웨어 공격에 가담할 수 있게 되었다. 이로 인해 다양한 변종이 무분별하게 등장할 가능성이 커졌고, 악용 소지가 충분하다는 점에서 해당 사건은 공식적인 보안 위협으로 간주되고 있다. 실제로 빌더 유출 이후 LockBit 계열로 추정되는 신규 샘플과 변종이 지속적으로 관측되고 있다.

 

그림2) 유출된 LockBit 3.0(Black) Builder

 

유출된 LockBit 3.0 빌더는 설정 파일(config.json), 키 생성기(keygen.exe), 그리고 랜섬웨어 빌더(builder.exe)로 구성되어 있다. 빌드 과정에서는 각 샘플을 식별하기 위한 고유 ID와 공개키(pub.key), 개인키(priv.key)가 생성되며, 암호화된 파일을 복구하기 위한 복호화 도구와 DLL 로더, EXE 로더가 빌드된다. 

 

1.3) 감염 시 증상

그림3) LockBit3.0 랜섬웨어 감염 시 배경 화면
그림4) LockBit3.0 랜섬웨어 감염 시 암호화된 파일 및 랜섬 노트

 

감염될 경우 파일은 암호화되며, 동시에 특정 아이콘으로 변경된다. 또한 피해자가 공격자에게 몸값을 지불하도록 유도하기 위해, 암호화가 수행된 각 디렉터리마다 랜섬 노트가 자동으로 생성된다.

2. 상세 분석

2.1) 분석 파일 정보

그림5) 이력서를 위장한 exe 실행 파일

File name #이력서_221116(경력사항도 같이 기재하였습니다 잘 부탁드립니다).exe
MD5 b303ffe0bbddca1570940557cabdd966
SHA-256 5e79854b8a92b169212e0ea3ad0252e4a86fc7e186fc162f143bb7754a73ec63
File type Win32 EXE
File size 855.66 KB (876192 bytes)
Creation Time 2021-09-25 21:57:46 UTC

 

LockBit 3.0은 정상적인 이력서 문서 파일로 위장하여 HWP 아이콘을 사용한 형태로 배포된다. 이를 통해 사용자가 해당 파일을 정상적인 문서로 오인해 악성코드를 실행하도록 유도한다.

 

그림6) 파일 내부에 포함된 nsis 스크립트 및 페이로드

 

파일을 분해해보면 내부에 페이로드와 NSIS 스크립트가 함께 포함되어 있으며, NSIS는 스크립트 기반으로 동작하는 Windows용 설치 시스템이다. 또한 정상 DLL 파일인 system.dll이 포함되어 있으며, 해당 파일은 NSIS 스크립트를 구동하는 과정에서 활용된다. 분해된 파일 목록과 각 파일의 해시는 아래 표와 같다.

파일 이름 설명 sha256
$PLUGINDIR\System.dll nsi 스크립트를 구동 시키기는데 사용되는 dll 8DC562CDA7217A3A52DB898243DE3E2ED68B80E62DDCB8619545ED0B4E7F65A8
514095725 Lockbit Payload 4E5537355AD834E172615399775DF50EA4A1FDCD9895A96FCA9FBDF98BC4EB6F
NSIS.nsi Payload를 실행하기 위해 사용되는 nsi 스크립트 4571E4025D3A579FF70075EBE77ABB4453F5441C9A75D52C218669C10179C841

 

2.2) 페이로드 실행 환경 구성

그림7) 페이로드 실행을 위한 초기 환경 설정

 

페이로드 실행을 위한 TEMP 경로 하위에 랜덤 한 문자열과 .tmp 확장자를 조합한 형식의 디렉터리를 생성한다.

그림8) TEMP 경로에 폴더 생성
그림9) 생성한 경로에 복사된 System.dll

 

생성된 .tmp 디렉터리 경로에 NSIS 스크립트를 구동하기 위한 system.dll 파일이 복사된다.

 

그림10) TEMP 경로에 LockBit 페이로드 파일 복사
그림11) TEMP 경로에 복사된 LockBit 페이로드

 

TEMP 경로에 이후 메모리에 적재되어 실행될 페이로드 파일이 생성된다.

 

그림12) 페이로드 메모리 적재 및 실행 과정

 

ZwCreateSection()을 호출하여 새로운 섹션 객체를 생성한 뒤, NtMapViewOfSection()을 통해 해당 섹션을 프로세스 주소 공간에 매핑하여 실행에 필요한 메모리 공간을 할당한다. 이후 "514095725" 파일을 읽어 해당 메모리 영역에 페이로드를 적재하고, 이를 호출하여 실행한다.

 

 

2.3) 페이로드 복호화 과정

그림13) 일부 영역을 제외하고 NULL 데이터로 채워져 있는 LockBit 페이로드

 

"514095725" 파일을 확인해 보면 다수의 0x00 NULL 데이터로 채워져 있으며, 하단으로 스크롤을 내려야 실제 페이로드 존재 여부를 확인할 수 있다. 해당 페이로드는 파일 오프셋 기준으로 0x6840035 부터 0x6867E46 영역에 기록되어 있다. 이는 분석 과정에서 혼란을 유발하고 페이로드 식별을 어렵게 하기 위한 목적의 기법으로 판단된다.

 

그림14) 암호화된 페이로드를 다중 XOR 연산을 통해 복호화

 

실행되는 페이로드는 다중 XOR 연산으로 암호화되어 있으며, 실행을 위해 총 네 차례의 XOR 복호화 과정을 거친다.

 

그림15) 복호화에 사용되는 키 배열 구조

 

암호화 해제 과정에서 페이로드 내부에서 0xDEADBEEF 값을 기준으로 특정 위치를 탐색한다. 이후 해당 영역에 대해 Size 값만큼 복호화 범위를 지정하며, Key1과 Key2를 XOR 연산한 값을 실제 복호화 키로 사용한다. 암호화 해제에 사용되는 키 정보는 아래 표와 같다.

xor key size
Round 1 0x62873AB1 0x2C03
Round 2 0x641A9DFF 0x2759
Round 3 0xAFEAE710 0x22AF
Round 4 0xAF618355 0x1E05

 

2.4) API Resolve 

그림16) API Resolve 과정

 

동작에 필요한 API를 동적으로 획득한다. PEB(Process Environment Block)에 접근한 뒤 LDR 구조체를 참조하고, InLoadOrderModuleList를 순회하여 로드된 모듈 kernel32.dll의 ImageBase 주소를 식별한다.

 

이후 kernel32.dll의 EAT(Export Address Table)에 접근하여 LoadLibraryA와 GetProcAddress 함수의 주소를 획득하고, 실행에 필요한 API를 동적으로 로딩한다.

 

LockBit 페이로드에서 동적으로 로딩하는 API 목록은 아래와 같다.

CreateProcessW GetThreadContext SetThreadContext
VirtualAlloc VirtualAllocEx WriteProcessMemory
ResumeThread TerminateProcess ExitProcess
ReadProcessMemory GetModuleFileNameW GetCommandLineW
NtUnmapViewOfSection CloseHandle IsWow64Process
CreateFileW ReadFile GetFileSize
VirtualFree LoadLibraryA LoadLibraryW
CryptAcquireContextW CryptCreateHash CryptHashData
CryptDeriveKey CryptDestroyHash CryptDecrypt
CryptDestroyKey CryptReleaseContext GetModuleHandleW
GetProcAddress WaitForSingleObject CreateThread

 

2.5) 암호화 된 랜섬웨어 행위 코드 복호화

그림17) AES 256 암호화 세션 키 생성
그림18) 내부에 저장된 랜섬웨어 행위 페이로드 복호화
그림19) 복호화 전,후 랜섬웨어 행위 페이로드

 

 

LockBit은 자식 프로세스를 생성한 뒤, 해당 프로세스에 코드를 주입하여 실행하는 프로세스 할로잉(Process Hollowing) 기법을 주로 사용한다. 자식 프로세스에 주입하기 위해 페이로드 내부에 포함된 암호화된 PE를 복호화하는 과정이 수행되며, CryptDecrypt() 함수를 호출하여 복호화를 진행한다.

 

호출되는 CryptDeriveKey() 함수의 ALG_ID 값을 확인한 결과, 해당 주입 코드가 AES-256 방식으로 암호화되어 있는 것으로 확인된다.

 

2.6) 자식 프로세스 생성 후 프로세스 할로잉 수행

그림20) 프로세스 할로잉을 수행하기 위해 프로세스 생성

 

프로세스 할로잉을 수행하기 위해 CreateProcessW()를 호출하여 자식 프로세스를 CREATE_NO_WINDOW | CREATE_SUSPENDED 상태로 생성한다.

그림21) 스레드 컨텍스트 획득

 

GetThreadContext()를 호출하여 생성된 자식 프로세스의 메인 스레드 컨텍스트를 획득한다.

그림22) 프로세스 할로잉 작업을 Direct System Call로 수행

 

보안 솔루션의 탐지를 회피하기 위해 API 래퍼 함수 사용을 최소화하고, 직접적인 시스템 콜(Syscall)을 통해 프로세스 할로잉을 수행한다. 각 운영체제 버전에 맞는 SSN(System Service Number)을 동적으로 추출한 뒤, Return Address Manipulation 기법을 활용하여 Syscall을 호출한다.

 

실행되는 retfar(0xCB) 명령은 FAR RETURN 명령으로, 코드 세그먼트(CS)와 명령 포인터(IP/EIP)를 함께 복원하여 제어 흐름을 변경하는 방식이다. 그러나 이러한 제어 흐름 전환 방식은 일반적인 사용자 모드 환경에서 거의 사용되지 않기 때문에, x64dbg와 같은 사용자 모드 디버거에서는 해당 명령을 정상적인 실행 흐름으로 처리하지 못하고 예외를 발생시킨다.

 

그림23) (0x2A) NtUnmapViewOfSection

NtUnmapViewOfSection()을 호출하여 생성된 자식 프로세스의 기존 이미지 매핑을 해제하고, 원래 로드되어 있던 실행 이미지를 제거한다.

 

그림24) (0x4A) NtCreateSection

 

NtCreateSection()을 호출하여 주입할 PE 이미지를 로드하기 위한 새로운 섹션 객체를 생성하고, 필요한 메모리 공간을 할당한다.

 

그림25) (0x28)  NtMapViewOfSection

 

NtMapViewOfSection()을 호출하여 생성한 섹션을 자식 프로세스의 주소 공간에 매핑하고, 복호화된 PE 이미지를 해당 메모리 영역에 로드한다.

 

그림26) (0x3A) ZwWriteVirtualMemory

 

ZwWriteVirtualMemory()를 호출하여 매핑된 메모리 영역에 PE 헤더 및 각 섹션 데이터를 기록한다. 이후 PEB에 저장된 ImageBaseAddress 값을 새로 주입된 PE의 기준 주소로 수정하여, 자식 프로세스가 정상적인 실행 이미지로 인식하도록 조작한다.

그림27) 스레드 컨텍스트 수정

 

SetThreadContext()를 호출하여 자식 프로세스의 메인 스레드 컨텍스트를 수정하여 명령 포인터(EIP/RIP)를 새로 주입된 PE의 진입점으로 변경한다.

 

그림28) (0x70052) NtResumeThread

 

NtResumeThread() 호출을 통해 수정된 컨텍스트를 기반으로 자식 프로세스의 실행이 재개된다.

 

 

2.7) 랜섬웨어 행위 코드 분석

그림29) 랜섬웨어 행위 start 루틴

 

최종적으로 자식 프로세스에서 실행되는 페이로드에는 각 초기화 과정을 거쳐 파일 암호화 동작을 수행하는 코드가 포함되어 있다.

 

2.7.1) Fake IAT

그림30) Fake IAT

 

랜섬웨어 행위를 감추기 위해 임의로 함수 테이블이 구성되어있다. 바이너리의 실제 IAT 대신 공격자가 의도한 함수 정보만을 노출함으로써, 실행 흐름을 은폐하기 위한 기법으로 판단된다.

 

 

2.7.2) 랜섬웨어 행위 코드 API Resolve

그림31) API를 동적으로 획득
그림32) hash 기반으로 비교하여 API 주소를 수집

 

랜섬웨어 행위에 필요한 API들을 동적으로 획득한다. DLL에 포함된 API 이름을 해싱한 뒤, 이를 랜섬웨어 동작에 필요한 API 해시 목록과 비교하여 일치하는 항목의 API 주소를 수집하는 방식으로 API 로딩을 수행한다.

 

동적으로 획득되는 API 목록 중, 주요 행위에 사용되는 API를 정리하면 아래 표와 같다.

NtOpenProcess NtOpenProcessToken ZwDuplicateToken
ZwDuplicateObject NtQueryInformationToken NtSetInformationToken
ZwPrivilegeCheck RtlAdjustPrivilege CheckTokenMembership
NtTerminateProcess ZwTerminateThread ZwShutdownSystem
NtAllocateVirtualMemory NtFreeVirtualMemory ZwWriteVirtualMemory
ZwReadVirtualMemory ZwProtectVirtualMemory CreateRemoteThread
CreateThread FindFirstFileExW FindNextFileW
GetFileAttributesW GetLogicalDriveStringsW GetDriveTypeW
GetDiskFreeSpaceExW CreateFileW ReadFile
WriteFile FlushFileBuffers SetFilePointerEx
DeleteFileW MoveFileExW CopyFileW
SetFileAttributesW MD4Init MD4Update
MD4Final MD5Init MD5Update
MD5Final cryptbase.SystemFunction040 cryptbase.SystemFunction041
RegCreateKeyExW RegSetValueExW RegDeleteKeyW
RegEnumKeyW OpenSCManagerW CreateServiceW
StartServiceW ControlService DeleteService
NetShareEnum NetUserEnum NetUserGetInfo
NetUserSetInfo DsGetDcNameW DsGetDcOpen

 

2.7.3) API 호출 전 실행되는 트램폴린

그림33) API 호출 되기 전 실행되는 트램폴린 구현

 

LockBit은 리졸빙된 API를 직접 호출하는 대신, 연산 코드가 포함된 힙 영역으로 제어 흐름을 전달하는 트램폴린 포인터를 구현한다. 해당 트램폴린은 연산을 통해 실제 API 주소를 계산한 뒤, 그 주소로 점프한다. 이때 힙에 배치되는 코드는 사전에 정의된 코드 세트 중에서 무작위로 선택된다.

 

아래는 API 호출을 위해 제어 흐름을 이동시키는 트램폴린 동작 2 가지 예시이다.

그림34) rol 연산 후 계산되는 API 주소로 JMP

 

그림35) xor 연산 후 계산되는 API 주소로 JMP

 

2.7.4) 사용되는 문자열 복호화

그림36) 사용되는 문자열 배열 복호화

 

사용되는 특정 문자열 배열들은 XOR 연산을 통해 암호화되어 있으며, 이를 동적으로 복호화하여 사용한다. 특정 문자열 배열 복호화에 사용되는 XOR 키 값은 0x19039FF6이다.

 

2.7.5) 해시 기반으로 Image Name 비교

그림37) 해시 기반으로 Image Name 식별

 

LockBit 3.0에는 실행 중인 프로세스와 서비스를 식별한 뒤 이를 강제로 종료하는 기능이 포함되어 있다. 이 과정에서 프로세스의 PID를 획득하거나 로드된 서비스를 식별할 때, 해시화된 ImageName을 기준으로 분기를 처리한다.

 

이러한 구조로 인해 원본 문자열을 직접 확인하기 어렵기 때문에, 유출된 빌더에 포함된 설정 파일(config)을 참조하거나 알려진 프로세스 및 서비스 이름을 기반으로 브루트포싱을 수행해 이를 유추해야 한다.

 

 

2.7.6) 난독화 코드 복원 작업

그림38) 난독화 된 디컴파일러 코드 복구 작업

 

API 호출 시 트램폴린을 경유해 최종적으로 API를 호출하는 방식을 사용함에 따라, IDA의 정적 디컴파일 환경에서는 함수 간 호출 관계를 파악하는 데 제약이 발생한다.

 

따라서 정적 분석만으로는 한계가 있어, 동적 트레이스(Trace) 분석을 병행해 실제로 호출되는 API를 확인하였다. 본 분석에서는 분석 효율을 높이기 위해 확인된 API 호출 지점을 기준으로 각 함수를 재정의하고 라벨링하여 전체 코드 흐름을 정리하였다.

 

 

2.7.7) 안티 디버깅

LockBit 3.0에는 분석을 방해하기 위한 다양한 안티디버깅 기법이 포함되어 있으며, 총 네 가지의 안티디버깅 기법이 확인되었다.

그림39) ZwSetInformationThread(ThreadHideFromDebugger) 안티 디버깅

__kernel_entry NTSYSCALLAPI NTSTATUS NtSetInformationThread(
  [in] HANDLE          ThreadHandle,
  [in] THREADINFOCLASS ThreadInformationClass,
  [in] PVOID           ThreadInformation,
  [in] ULONG           ThreadInformationLength
);


typedef enum _THREAD_INFORMATION_CLASS {
    ThreadBasicInformation,
    ThreadTimes,
    ThreadPriority,
    ThreadBasePriority,
    ThreadAffinityMask,
    ThreadImpersonationToken,
    ThreadDescriptorTableEntry,
    ThreadEnableAlignmentFaultFixup,
    ThreadEventPair,
    ThreadQuerySetWin32StartAddress,
    ThreadZeroTlsCell,
    ThreadPerformanceCount,
    ThreadAmILastThread,
    ThreadIdealProcessor,
    ThreadPriorityBoost,
    ThreadSetTlsArrayAddress,
    ThreadIsIoPending,
    ThreadHideFromDebugger <<
} THREAD_INFORMATION_CLASS, *PTHREAD_INFORMATION_CLASS;

 

ZwSetInformationThread()를 호출하면서 ThreadInformationClass 인자로 ThreadHideFromDebugger를 전달함으로써, 디버거가 연결된 상태에서 실행될 경우 해당 스레드를 디버거로부터 은닉한다. 이로 인해 디버거는 해당 스레드에 대한 이벤트를 수신하지 못하게 되므로 디버깅에 실패한다.

 

그림40) 힙 플래그 HEAP_VALIDATE_PARAMETERS_ENABLED 검사를 통한 안티 디버깅

 

NtCurrentPeb()를 통해 PEB의 ProcessHeap을 획득한 뒤, 힙 플래그 HEAP_VALIDATE_PARAMETERS_ENABLED 값의 설정 여부를 검사한다. 해당 플래그는 디버거 환경에서 활성화되기 때문에, 이를 통해 디버깅 여부를 판단한다.

 

디버깅이 탐지되면, 정상적인 힙 핸들을 사용하지 않고 ROR 연산으로 의도적으로 힙 핸들을 변조하여 크래시를 유도한다.

그림41) 힙 메모리 패턴 값 검사를 통한 안티 디버깅

 

디버깅 환경에서는 힙 영역 중 미사용 공간이 특정 패턴 값(예: 0xABABABAB, 0xFEEEFEEE)으로 채워지는 특징이 있다. LockBit은 이러한 힙 메모리 초기화 특성을 이용하여 RtlHeapAllocate() 수행 이후, 할당된 힙 블록의 끝부분에 해당 패턴 값이 존재하는지를 검사하고, 이를 기반으로 디버깅 여부를 판별한다.

 

그림42) 디버거에서 Attach 시 호출되는 DbgUiRemoteBreakin() 암호화

 

RtlEncryptMemory()를 통해 DbgUiRemoteBreakin() 함수 일부를 암호화한다.

 

DbgUiRemoteBreakin()은 디버거가 프로세스에 연결될 때 실행되는 함수며, 이를 변조함으로써 디버거 Attach 시 예외를 유발하여 디버깅을 방해한다.

 

 

2.7.8) OS 버전 확인

그림43) OS 환경 검사

 

PEB 구조체에 접근하여 OSMajorVersion과 OSMinorVersion 값을 확인하여 현재 운영체제 버전을 식별한다.

 

2.7.9) LCG 난독화 생성 및 XOR 복호화

그림44) LCG 난독화 생성 및 XOR 복호화

 

RSA 공개 키, 실행 흐름 제어 플래그, 랜섬 노트 데이터 등 주요 설정 정보는 내부에 암호화된 형태로 저장되어 있다. 해당 데이터는 XOR 연산과 LCG 기반 의사 난수 생성기로 생성된 키를 조합하여 복호화되며, 이때 사용되는 시드 값은 0xC9F719BC0x5ECE4542 로 확인된다.

 

2.7.10) aPlib로 압축된 config 데이터

그림45) 압축된 config 데이터 aPlib 압축 해제

 

그림46) 복호화 전,후 config 데이터

 

복호화 이후 aPLib 라이브러리 형식의 압축 데이터를 확인할 수 있다. 이를 압축 해제하면 RSA 공개 키와 실행 제어용 플래그 정보를 확인할 수 있다. 코드 영역에 aPLib 압축을 식별할 수 있는 대표적인 시그니처 값인 0x7D00가 확인된다.

 

2.7.11) 노출되는 랜섬 노트 문자열

그림47) 복호화 후 노출되는 랜섬 노트 문자열

 

랜섬 노트 문자열은 암호화된 상태로 Base64 인코딩 되어 내부에 저장되어 있으며, 실행 시점에 이를 동적으로 복호화하여 생성한다. LCG 기반 의사 난수 생성기와 XOR 연산을 이용한 문자열 복호화가 진행된다.

 

 

2.7.12) 관리자 권한 확인

그림48) 관리자 권한 체크

 

LockBit 3.0은 파일 암호화 행위를 수행하기 위해 필요한 권한이 확보되었는지 검사한다. 만약 사용자 권한으로 실행된 경우, UAC 우회 기법을 통해 관리자 권한으로 재실행될 수 있도록 한다.

 

그림49) Administrators 그룹인지 조회

 

CheckTokenMembership() 함수를 호출하고, SID 값 S-1-5-32-544를 인자로 전달하여 현재 프로세스의 보안 토큰이 Administrators 그룹에 포함되어 있는지를 확인한다.

 

이후, 프로세스의 토큰을 획득한 뒤, 토큰에 포함된 그룹 SID 목록을 조회하여 해당 목록을 순회하고 Administrators 그룹의 존재 여부를 확인한다.

 

 

2.7.13) UAC Bypass 및 관리자 권한으로 재실행

그림50) UAC Bypass -> dllhost.exe 관리자 권한을 상속 받아 재실행

 

사용자 권한으로 실행될 경우, 관리자 권한으로 재실행하기 위해 CMSTPLUA COM 객체가 호출된다. 이때 ICMLuaUtil 인터페이스의 ObjectStublessClient9 메서드가 실행되며, 그 결과 dllhost.exe 프로세스가 생성된다. 이후 dllhost.exe를 부모 프로세스로 하여 LockBit이 COM 서버 프로세스의 관리자 권한을 상속받아 자식 프로세스로 실행된다.

 

특정 COM 객체(CLSID)를 악용하여 UAC 상승을 수행하는 기법

(https://learn.microsoft.com/en-us/windows/win32/com/the-com-elevation-moniker)

 

2.7.14) 프로세스 권한 활성

그림51) 랜섬웨어 행위에 필요한 프로세스 권한 활성화

 

랜섬웨어 행위를 원활히 수행하기 위해 RtlAdjustPrivilege() 함수를 호출하여 필요한 프로세스 권한을 활성화한다.

활성화되는 권한은 아래와 같다.

Privilege 설명 설명
0x03 SeAssignPrimaryTokenPrivilege 다른 사용자 토큰을 프로세스에 할당
0x05 SeIncreaseQuotaPrivilege 프로세스 메모리/리소스 할당량 증가
0x08 SeSystemEnvironmentPrivilege UEFI/시스템 펌웨어 레벨의 환경 변수 수정
0x09 SeSystemProfilePrivilege 시스템 성능 프로파일링
0x0B SeSystemtimePrivilege 시스템 시간 변경
0x0D SeBackupPrivilege 파일 ACL 무시하고 읽기 가능
0x0E SeLoadDriverPrivilege 커널 드라이버 로드
0x11 SeShutdownPrivilege 로컬 시스템 종료/재부팅
0x12 SeRemoteShutdownPrivilege 원격 시스템 종료
0x13 SeProfileSingleProcessPrivilege 특정 프로세스 성능 분석
0x14 SeDebugPrivilege 모든 프로세스 접근
0x1C SeRestorePrivilege 파일 ACL 무시하고 쓰기 가능
0x1D SeTakeOwnershipPrivilege 파일/레지스트리 소유권 획득
0x21 SeSecurityPrivilege 보안 로그/정책 변경
0x24 SeManageVolumePrivilege 볼륨 관리 (raw disk 접근)

 

 

 

2.8) config 옵션 기능 분석

그림52) config 옵션에 따라 동작되는 LockBit 3.0 , 유출된 빌더 config 정보

 

복호화된 config 정보를 로드한 뒤, 각 기능의 활성화 여부에 따라 전체 동작 흐름이 분기된다. 유출된 빌더를 통해 해당 설정값에 대한 세부 기능을 확인할 수 있으며, 이를 기반으로 LockBit 3.0이 제공하는 전체 기능 목록과 분석 대상 샘플에서 실제로 활성화된 기능 여부를 비교·분석할 수 있다.

key 설명
encrypt_mode 암호화 모드 지정 (“fast” or “auto”)
encrypt_filename 파일명 암호화
impersonation "impers_accounts"에 저장된 자격증명을 이용해 로그인
skip_hidden_folders 숨김 폴더를 암호화에서 제외
language_check 감염 시스템이 CIS(독립국가연합)인지 확인
local_disks 로컬 드라이브 암호화
network_shares 네트워크 드라이브 및 공유 폴더 암호화
kill_processes “kill_processes”에 저장된 프로세스 종료
kill_services "kill_services"에 저장된 서비스 종료
running_one 중복실행 방지
print_note 연결된 프린터를 통해 랜섬노트 출력
set_wallpaper 바탕화면 변경
set_icons 암호화된 파일 아이콘 변경
send_report 감염 시스템 정보 수집
self_destruct 악성행위 완료 후 자가 삭제
kill_defender 윈도우 디펜더 및 Anti-Virus 종료
wipe_freespace 자가 삭제 시, Free space 완전 삭제
psexec_netspread PsExec를 통한 네트워크 전파
gpo_netspread 그룹정책(GPO) 통한 네트워크 전파
gpo_ps_update PowerShell로 모든 도메인 GPO 업데이트
shutdown_system 시스템 재부팅
delete_eventlogs 이벤트 로그 삭제
delete_gpo_delay 생성한 그룹정책(GPO) 삭제

 

활성화 되있는 flag 비활성화 되있는 flag
shutdown_system encrypt_mode
wipe_freespace encrypt_filename
self_destruct impersonation
set_wallpaper skip_hidden_folders
delete_eventlogs gpo_ps_update
network_shares delete_gpo_delay
local_disks gpo_netspread 
kill_process psexec_netspread
kill_services send_report
kill_defender print_note
set_icons language_check
running_one  

 

 

2.8.1) 커맨드라인 인자 확인

그림53) 커맨드라인 인자를 확인하여 암호화 방식 진행

 

실행 시 전달되는 커맨드라인 인자를 확인하여 암호화 방식 및 전체 동작 흐름을 결정한다. 총 9개의 실행 인자를 지원하며, 별도의 인자가 전달되지 않은 경우에도 기본 암호화 동작이 수행된다. 입력된 인자 값은 문자열 그대로 비교되지 않고 해시 값으로 변환된 뒤, 내부에 미리 저장된 해시 값과 비교하여 분기 처리가 이루어진다.

옵션 Hash 설명
-path [value] 0x45471D17 지정된 특정 경로만 선택적으로 암호화
-pass [value] 0x459F1CD7 LockBit 내부에 포함된 실행 코드 복호화 패스워드
-safe 0x452F4997 Windows Safe Mode 환경에서 암호화 수행
wall 0x45678B17 바탕화면 배경 변경, 랜섬노트 출력, 프린터로 랜섬노트 인쇄
-gspd 0x69268C17 Group Policy 그룹 정책 수정
-psex 0x69C71957 횡적 이동 전파
-gdel 0xCB62E940 그룹 정책 업데이트 제거
-del 0x4B668957 실행 완료 후 자가 삭제
default X 기본 암호화 동작

 

 

2.8.2) 특정 국가 환경 체크 - language_check

그림54) 특정 국가 환경에서는 종료

 

language_check 옵션이 활성화된 경우, 운영체제의 설치 언어와 사용자 기본 UI 언어를 확인한 뒤 특정 국가·언어 환경에서는 동작을 수행하지 않고 즉시 종료하도록 설계되어 있다.

 

본 분석 대상 샘플에서는 해당 기능이 비활성화되어 있었으나, 설정상 차단 대상 국가는 구소련(CIS) 및 친러시아 국가로 구성되어 있는 것이 확인된다. 이러한 언어·지역 기반 차단 패턴을 통해, 해당 랜섬웨어가 러시아권을 배경으로 유포되었을 가능성을 추정할 수 있다.

LANGID 언어
0x0419 Russia (러시아)
0x0422 Ukrainian (우크라이나)
0x0423 Belarusian (벨라루스)
0x0428 Tajik(타지크)
0x042B Armenian (아르메니아)
0x042C Azeri (아제르바이잔)
0x0437 Georgian (조지아)
0x043F Kazakh (카자흐스탄)
0x0440 Kyrgyz (키르기스스탄)
0x0442 Turkmen (투르크메니스탄)
0x0443 Uzbek (우즈베키스탄)
0x0444 Tatar (러시아 내 소수민족)

 

 

2.8.3) 암호화 파일 확장자 생성 - set_icons

그림55) 파일 확장자 생성

 

RSA 공개 키의 MD5 해시를 생성한 뒤 이를 UUID 형식으로 변환하여 고유 식별자를 생성한다. 이후 생성된 UUID 값에 대해 다시 한번 MD5 해시를 계산하고, 결과를 Base64로 인코딩하여 파일 확장자 이름을 생성한다.

 

또한 파일 암호화 과정에서 확장자 변경 시 충돌이나 오류를 방지하기 위해, 확장자에 +,/,= 문자가 포함되어 있으면 x, i, z 등의 문자로 치환하는 처리가 함께 수행된다.

그림56) 생성한 파일 확장자 아이콘 파일 생성
그림57) 아이콘을 표시하기 위해 레지스트리에 등록

 

앞서 생성된 아이콘 파일(yYQ85HpV1.ico)은 ProgramData 경로에 생성된다. 이후 해당 아이콘을 표시하기 위해 레지스트리에 아이콘 경로를 등록한다. 등록되는 경로는 HKEY_CLASSES_ROOT\<암호화 확장자>\DefaultIcon이며, 레지스트리 값에는 아이콘 파일이 위치한 경로가 기록되어 있다.

 

 

2.8.4) 뮤텍스 생성 / 중복 실행 방지  - running_one

그림58) 뮤텍스를 열거하여 중복 실행 방지

 

뮤텍스를 생성하여 중복 실행을 방지한다. running_one 옵션이 활성화된 경우에 동작하며, 뮤텍스 이름은 다음 과정을 통해 결정된다.

  1. RSA 공개 키의 MD5 해시를 생성한다.
  2. 생성된 해시를 UUID 형식으로 변환한다.
  3. UUID 값에 추가 연산을 수행한 뒤 MD4 해시를 계산하여 최종 뮤텍스 이름으로 사용한다.

동일한 뮤텍스를 가진 프로세스가 이미 실행 중일 경우, 새 프로세스는 실행되지 않고 종료되어 중복 실행을 방지한다.

 

2.8.5) 보안 서비스 및 프로세스 종료  - kill_defender

그림59) kill_defender 옵션
그림60) Windows Defender 관련 서비스 및 보안 프로세스 종료

 

현재 실행 중인 Windows Defender 관련 서비스와 보안 프로세스를 식별한 뒤, 이를 강제로 종료하거나 제거한다. kill_defender 옵션이 활성화돼있을 경우 동작하며, 보안 서비스 제어에 필요한 권한을 확보하기 위해 TrustedInstaller 서비스를 실행한 후 해당 프로세스의 토큰을 탈취한다. 이후 탈취한 토큰을 이용해 Defender 및 기타 보안 서비스에 대한 중지·삭제 작업을 수행한다. 아래는 해당 함수가 실행될 때 종료되는 프로세스 및 서비스에 대한 로그이다.

Process & Service Log
Process terminated: sppsvc.exe (7524); exit status 0x0
Service deleted: WdFilter (Microsoft Defender Antivirus Mini-Filter Driver)
Service deleted: Sense (Windows Defender Advanced Threat Protection Service)
Service deleted: WdNisDrv (Microsoft Defender Antivirus Network Inspection System Driver)
Service deleted: WinDefend (Microsoft Defender Antivirus Service)
Service deleted: WdBoot (Microsoft Defender Antivirus Boot Driver)
Service deleted: WdNisSvc (Microsoft Defender Antivirus Network Inspection Service)
Service stopped: sppsvc (Software Protection)
Process terminated: MsMpEng.exe (3200); exit status 0x0
Process terminated: svchost.exe (5352); exit status 0x0
Service deleted: wscsvc (Security Center)
Process terminated: backgroundTaskHost.exe (4548); exit status 0x1
Process terminated: WindowsPackageManagerServer.exe (1160); exit status 0x0

 

2.8.6) 휴지통 관련 디렉터리 제거

그림61) 휴지통 관련 디렉터리 제거

 

시스템에 연결된 모든 드라이브 경로를 획득하고 하드 디스크, 이동식 드라이브인 경우 해당 드라이브의 휴지통 관련 서브 디렉터리를 제거한다. 해당 루틴은 휴지통을 포함한 불필요한 흔적을 제거하고, 백그라운드에서 안정적으로 동작할 수 있는 환경을 준비하는 역할을 한다.

 

2.8.7) Shadow Copy 복사본 제거

그림62) Shadow Copy 복사본 삭제

 

시스템 복원 지점 및 백업을 제거하여 파일 복구를 불가능하게 만들기 위해 WMI를 이용해 시스템에 존재하는 모든 볼륨 섀도 복사본(Shadow Copy)을 삭제한다. ROOT\\CIMV2 네임스페이스에 연결한 후, WQL 쿼리(SELECT * FROM Win32_ShadowCopy)를 실행하여 시스템에 존재하는 모든 Shadow Copy 객체를 열거한다. 각 Shadow Copy 인스턴스의 ID 값을 획득한 뒤, DeleteInstance() 메서드를 호출하여 복사본을 삭제한다.

 

2.8.8) 서비스 중지 및 삭제 - kill_services

그림63) kill_service 옵션

 

EnumServiceStatusEx() 함수를 사용해 현재 시스템에 등록된 서비스 목록을 열거한 뒤, config에 미리 정의된 서비스 목록과 비교하여 일치하는 서비스가 발견되면 ControlService()를 호출해 강제로 중지시키고, DeleteService()를 통해 서비스를 삭제한다.

 

해당 동작은 kill_service 옵션이 활성화된 경우에만 수행된다. 유출된 빌더 기준으로 확인된 종료 대상 서비스 목록은 아래와 같으며, 실제 적용되는 서비스 목록은 설정된 플래그에 따라 추가되거나 변경될 수 있다.

Service
vss sql svc memtas
msexchange sophos veeam backup
GxVss GxBlr GxFWD GxCVD
GxCIMgr      

 

 

 

2.8.9) 프로세스  강제 종료 - kill_process

그림64) kill_process 옵션

 

NtQuerySystemInformation()을 호출하여 현재 실행 중인 프로세스 목록을 열거한 뒤, config에 사전에 정의된 프로세스 목록과 비교한다. 일치하는 프로세스가 발견되면 NtTerminateProcess()를 사용해 해당 프로세스를 강제로 종료한다.

 

해당 동작은 kill_process 옵션이 활성화된 경우에만 수행된다. 유출된 빌더 기준으로 확인된 종료 대상 프로세스 목록은 아래와 같으며, 실제 적용되는 목록은 설정된 플래그 설정에 따라 추가되거나 변경될 수 있다.

Process
sql oracle ocssd dbsnmp
synctime agntsvc isqlplussvc xfssvccon
mydesktopservice ocautoupds encsvc firefox
tbirdconfig mydesktopqos ocomm dbeng50
sqbcoreservic excel infopath msaccess
mspub onenote outlook powerpnt
steam thebat thunderbird visio
winword wordpad notepad calc
wuauclt onedrive    

 

 

 

2.8.10) 프로세스 및 스레드 우선순위 변경

그림65) 프로세스 I/O 우선순위, CPU 스케줄링 우선순위 조정

 

현재 프로세스의 I/O 우선순위, CPU 스케줄링 우선순위, Hard Error 처리 방식을 조정한다.

특히 디스크 I/O 중심의 암호화 작업을 효율적으로 수행하기 위해 I/O 우선순위를 변경하며, 함수 호출 후에는 I/O Priority가 Normal → High로 상승한 것을 확인할 수 있다.

그림66) 스레드 CPU 스케줄링 우선 순위 조정

 

SetThreadPriority()를 THREAD_PRIORITY_HIGHEST 인자로 호출하여, 해당 스레드가 CPU 스케줄링에서 다른 스레드보다 우선적으로 실행되도록 조정한다.

 

2.8.11) 멀티 스레드 환경 구성

그림67) 비동기 I/O, 멀티 스레드 구조로 동작하는 파일 암호화 로직

 

파일 암호화 작업은 성능 극대화를 위해 IO Completion Port(IOCP) 기반의 비동기 I/O + 멀티스레드 구조로 설계되어 있다. 각 워커 스레드는 IOCP에 연결되어 파일 암호화, 쓰기 등의 작업을 병렬로 처리한다.

 

CreateIoCompletionPort()를 통해 새로운 IOCP를 생성한 뒤, 각 워커 스레드는 EncryptionWorkerThread를 실행하며 해당 IOCP에 종속된다. 생성된 스레드는 ThreadHideFromDebugger()를 통해 디버거에서 은닉되어, 동적 분석 및 디버깅을 어렵게 만든다.

 

2.8.12) Key Matrix 생성 - local_disks

그림68) 파일 암호화에 필요한 Key Matrix 생성

 

CPUID, RDRAND 등 어셈블리 명령을 활용해 0x80 바이트 크기의 난수를 생성하여, 이를 파일 암호화에 사용할 Key Matrix로 활용한다. 생성된 Key Matrix는 RtlEncryptMemory()로 암호화하여 저장하고, 필요 시 RtlDecryptMemory()로 복호화하여 사용된다. 이후 복호화된 Key Matrix를 RSA 공개키로 암호화하여 저장하고, Key Matrix의 체크섬을 생성하여 무결성 검증에 사용한다.

그림69) Key Matrix 배열 구조

 

최종적으로 구현된 Key Matrix 구조는 다음과 같이 저장된다.

내용 설명
Checksum
4 바이트
Key Matrix 무결성을 검증하기 위한 체크섬 값.
RSA 암호화된 Salsa20 Key Matrix
128 바이트 (0x80)
실제 파일 암호화에 사용될 Salsa20 Key Matrix를 RSA 공개키로 암호화한 데이터.
Salsa20 Key Matrix
128 바이트 (0x80)
RtlEncryptMemory()로 암호화된 Salsa20 Key Matrix

 

 

2.8.13) 볼륨 강제 마운트 - local_disks

그림70) 마운트되지 않은 볼륨 탐색 후 강제로 마운트

 

시스템에 존재하지만 마운트 되지 않은 로컬 및 이동식 볼륨을 탐색하여 강제로 마운트 하는 기능을 수행한다.

모든 볼륨을 열거한 뒤, GetVolumePathNamesForVolumeNameW()로 마운트 포인트 존재 여부를 확인한다. 마운트 되지 않은 볼륨 중 로컬 디스크 또는 이동식 디스크만을 대상으로 삼는다.

 

Windows 7,8,9,10,11 환경에서는 DeviceIoControl(IOCTL_DISK_GET_PARTITION_INFO_EX)를 인자로 호출해 시스템 예약 파티션이나 특정 OEM 볼륨은 제외한다. 조건을 만족하는 볼륨은 SetVolumeMountPoint()를 통해 강제로 마운트 된다.

 

2.8.14) Microsoft Exchange Server 대상 암호화 - local_disks

그림71) Mailbox 관련 데이터를 암호화

 

ExchangeInstallPath 환경 변수를 조회하여 시스템에 Microsoft Exchange Server가 설치되어 있는지 여부를 확인한다. 해당 환경 변수가 존재할 경우 Exchange 서버가 설치된 것으로 판단하며, \\?\Mailbox 경로를 생성해 Mailbox 관련 데이터를 암호화 대상에 포함시킨다.

 

2.8.15) 파일 속성 변경

그림72) 원활한 파일 암호화 진행을 위해 파일 소유자 및 권한 변경

 

시스템의 보호된 파일에 접근하기 위해 파일 소유자와 권한을 조정한 뒤, SetFileAttributesW()를 호출하여 파일 속성을 변경한다. 이때 인자값으로 0x80 (FILE_ATTRIBUTE_NORMAL)을 전달해 읽기 전용·시스템·숨김 등의 속성이 설정된 파일을 일반 파일 속성으로 강제로 변경한다.

 

2.8.16) 공유 위반 프로세스 강제 종료

그림73) 공유 위반 프로세스 강제 종료

 

공유 위반으로 파일이 점유된 경우 암호화 작업이 차질 없이 진행되도록 하기 위해, RMGetList()를 호출하여 파일을 점유 중인 프로세스 목록을 조회한다. 조회된 프로세스 중 중요 시스템 프로세스나 Explorer는 제외하며, 점유 프로세스가 서비스일 경우에는 ControlService()와 DeleteService()를 통해 강제로 중지·제거한다. 나머지 점유 프로세스는 NtTerminateProcess() 등을 통해 강제 종료하여 암호화가 정상적으로 수행되도록 한다.

 

2.8.17) 파일 암호화

그림74) 파일 암호화 과정

 

이전 Key Matrix 구조체를 활용하여 파일 암호화를 수행한다. 먼저 RtlDecryptMemory()로 Key Matrix를 메모리에서 복호화해, 암호화에 필요한 Salsa20 키를 준비한다. 이후 Custom Salsa20 알고리즘으로 파일 데이터를 암호화하고, 작업이 끝나면 Key Matrix를 RtlEncryptMemory()로 다시 암호화하여 메모리에서 안전하게 보호한다. 마지막으로 파일 footer에 추후 복호화에 필요한 정보를 추가한다. 아래는 파일 암호화 전후의 Hex 데이터 내용이다.

 

 

2.8.18) 네트워크 공유 폴더 암호화 - network_shares

그림75) 네트워크 공유 폴더 내용 암호화

 

NetShareEnum() 함수를 이용해 네트워크 공유 자원을 열거한다. 발견된 공유 폴더가 있을 경우, 해당 경로의 파일도 암호화 대상에 포함한다. 이 기능은 network_shares 옵션이 활성화되어 있을 때만 수행된다.

 

 

2.8.19) 이벤트 로그 무력화  - delete_eventlogs

그림76) 행위 추적을 방지하기 위한 이벤트 로그 무력화 및 제거

 

파일 암호화가 완료된 이후, 행위 추적을 방지하기 위해 시스템 이벤트 로그를 무력화하는 동작을 수행한다.

SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\WINEVT\\Channels
SYSTEM\\CurrentControlSet\\Services\\EventLog

 

레지스트리에 접근하여, 모든 이벤트 로그 채널을 순회한다. 각 채널의 Enabled 또는 ChannelAccess 값을 덮어써 로그 기록을 비활성화한 뒤, OpenEventLogW()와 ClearEventLogW()를 호출해 기존 이벤트 로그를 삭제한다.

 

이후 ControlService()를 호출해 EventLog 서비스를 강제로 중지하고, DeleteService()를 통해 서비스를 삭제하여, 이후 발생하는 행위가 로그로 남지 않도록 한다.

 

2.8.20) 배경화면 변경  - set_wallpaper

그림77) 감염 사실을 사용자에 알리기 위한 wallpaper 생성 및 변경
그림78) ProgramData 경로에 생성되는 배경화면 파일

 

파일 암호화가 완료된 이후, 감염 사실을 사용자에게 인지시키기 위해 readme 파일을 확인하도록 안내하는 문자열을 포함한 비트맵(Bitmap) 이미지를 생성한다. 해당 이미지는 ProgramData 경로에 저장되며, 파일명은 앞서 아이콘 확장자 생성 시 사용된 이름과 동일하게 사용된다.

 

이후 HKEY_CURRENT_USER\Control Panel\Desktop 레지스트리에 접근하여 바탕화면 설정을 변경한다.
WallpaperStyle 값을 10으로 설정하고, 새로 생성한 비트맵 이미지의 경로를 WallPaper 값으로 지정한 뒤 SystemParametersInfoW()를 호출하여 바탕화면을 강제로 변경한다.

 

 

2.9) 자가 삭제 - shutdown_system , wipe_freespace , self_destruct

LockBit 3.0에서는 모든 악성 행위를 수행한 이후, 자신의 흔적을 제거하기 위해 마지막 단계에서 자가 삭제를 수행한다.

자가 삭제 코드를 실행하기 위한 임시 바이너리(.tmp)를 생성한 뒤, 이를 자식 프로세스로 생성하고 메모리 주입을 통해 자가 삭제 페이로드를 실행하여 원본 랜섬웨어 바이너리 및 관련 파일을 삭제하도록 동작한다. 이후 cmd 배치 명령을 실행함으로써 임시 바이너리(.tmp 파일)까지 제거한다.

 

해당 기능은 shutdown_system, wipe_freespace, self_destruct 옵션 중 하나라도 활성화되어 있을 경우에 동작하며, 각 옵션의 활성화 여부는 자가 삭제 루틴 호출 시 인자로 전달된다.

 

2.9.1) 도메인 컨트롤러 확인

그림79) Domain Controller 환경인지 조회

 

자가 삭제 루틴을 수행하기 전에 도메인 컨트롤러(DC) 환경에서의 삭제 행위를 방지하기 위해, 먼저 시스템이 도메인에 조인되어 있는지 여부를 확인한다. 이후 DsGetDcOpenW() / DsGetDcNextW()를 사용해 도메인 내 모든 DC의 이름을 순회하며 열거된 DC 이름과 현재 시스템의 컴퓨터 이름을 비교한다. 이 과정에서 이름이 일치할 경우 해당 시스템을 Domain Controller로 판단하고, 이를 나타내는 값으로 1을 반환한다.

 

2.9.2) self_delete 구조

그림80) 자가 삭제 루틴

 

self_delete 루틴에서 전달되는 인자 내용은 다음과 같다.

self_delete(
  IsDC,                    // 도메인 컨트롤러 여부
  config_shutdown_system,  // 시스템 종료
  config_wipe_freespace,   // 디스크 여유공간 와이프
  config_self_destruct     // 자가 삭제
);

 

2.9.3) self_delete 루틴 분석

그림81) ProgramData 경로에 생성되는 임시 .tmp 파일
그림82) 임시.tmp파일을 자식 프로세스로 생성

 

ProgramData 경로에 랜덤한 숫자 기반의 임시 .tmp 파일을 생성한 뒤, 부모 프로세스와 자식 프로세스 간 통신을 위한 Named Pipe(lpName)를 생성한다. 이후 aPLib 포맷으로 압축된 바이너리를 메모리 상에서 압축 해제하여 해당 .tmp 파일에 작성한다.

 

파일 생성이 완료되면 CreateProcessW()를 호출하여 해당 .tmp 바이너리를 CREATE_SUSPENDED 상태로 실행함으로써, 이후 메모리 주입 및 초기화 작업을 수행할 수 있도록 준비한다.

 

그림83) 생성한 자식 프로세스에 메모리 주입 후 실행

 

Suspend 상태로 생성된 자식 프로세스(.tmp)를 대상으로, 내부에 포함된 파일 삭제용 바이너리 페이로드를 복호화한 뒤 메모리 주입 방식으로 실행한다. ZwWriteVirtualMemory()를 사용해 복호화된 페이로드를 주입한다. 이후 ResumeThread()를 호출하여 중단되어 있던 자식 프로세스를 재개함으로써 주입된 코드가 실행된다.

 

과정에서 Named Pipe 기반 IPC 채널을 생성하여 부모 프로세스와 자식 프로세스 간에 실행 제어 정보를 전달한다. 전달되는 파라미터는 다음과 같다.

 

  • IsDC : 도메인 컨트롤러 여부
  • config_shutdown_system : 시스템 종료 여부
  • config_wipe_freespace : 디스크 여유 공간 와이프 여부
  • config_self_destruct : 자가 삭제 수행 여부

그림84) 이름 및 데이터가 변조된 랜섬웨어 파일

 

실행된 .tmp 파일은 랜섬웨어 본래 바이너리의 내용을 덮어쓴 후, 파일 이름을 여러 차례 변경한다. AAAA, BBBB, ZZZZ 등으로 순차적으로 이름을 변경하고, 최종적으로 파일을 삭제한다.

 

이와 같은 덮어쓰기 → 반복적인 파일명 변경 → 삭제 절차는 포렌식 도구를 통한 복구를 어렵게 만들기 위한 전형적인 흔적 제거 기법으로, 랜섬웨어 실행 파일과 관련된 파일을 최대한 제거하여 감염 이후의 추적과 분석을 방해하려는 목적을 가진다.

 

그림85) 생성한 tmp 파일도 함께 제거

 

삭제 루틴의 마지막 단계에서는 cmd.exe를 이용한 배치 명령을 실행하여 자기 자신(.tmp 파일)까지 제거한다.

실행되는 명령은 다음과 같다.

"C:\Windows\System32\cmd.exe" /C DEL /F /Q C:\PROGRA~3\9FF9.tmp >> NUL

 

 

3. 결론

LockBit 3.0은 단순히 파일을 암호화하는 수준을 넘어, 침투부터 암호화, 추적 회피, 자가 삭제까지 전 과정을 체계적으로 설계한 고도화된 랜섬웨어임을 분석을 통해 확인할 수 있었다.

 

초기 단계에서 권한을 확보하고 실행 환경을 면밀히 점검한 뒤, 난수 기반으로 생성된 Key Matrix를 중심으로 Salsa20과 RSA를 결합한 암호화 구조를 사용한다. 암호화 과정에서는 I/O 우선순위 조정과 IOCP 기반 멀티스레드 구조를 활용해 대규모 파일을 빠르게 처리하며, 네트워크 공유와 Exchange Mailbox 등 기업 환경을 정밀하게 노린다.

 

암호화 이후에는 이벤트 로그 비활성화 및 삭제, 보안 서비스 종료, 프로세스 강제 종료 등 다양한 포렌식 방해 기법을 수행하고, 최종적으로는 파일 덮어쓰기·이름 변경을 이용한 자가 삭제 루틴으로 흔적을 최소화한다.

 

4. 참고 문헌

[1] https://www.somansa.com/wp-content/uploads/2023/01/lockbit30_202212.pdf

(Somansa LockBit 3.0 랜섬웨어 분석)

 

[2] https://www.cyberone.kr/news-trends-detail?id=94796&page=1

(Cyberone LockBit 3.0 Builder 분석)

 

[3] https://industrialcyber.co/ransomware/trend-micro-details-lockbit-3-0-ransomware-that-imitates-blackmatter-capabilities/

(Trend Micro details LockBit 3.0 ransomware that imitates BlackMatter capabilities)

 

[4] https://medium.com/s2wblog/evolution-of-lockbit-to-3-0-e21386188b65

(S2W Evolution of LockBit to 3.0)

 

[5] https://socprime.com/ko/blog/lockbit-ransomware-detection/

(LockBit Ransomware Detection)