악성코드 분석 (Malware Analysis)/기타 (etc)

[악성코드 분석] 게임핵을 받으면 악성코드까지 같이? Gh0st RAT

xenen 2025. 2. 17. 23:32

1. 개요

게임 핵이 실행되면 %temp% 디렉터리에 dll 파일이 생성되고 rundll32에 의해 실행됩니다. 생성된 파일의 분석 의뢰를 받았습니다. 

1.1. 분석 환경

운영 체제 Windows 10 64bit
분석 도구 x64dbg,
IDA Pro,
Process Explorer

 

1.2. 파일 정보

구분 내용
파일 명 Top_dump_2.dll
파일 크기 148,480 바이트
해쉬(MD5) EBDE50177EED2CE16ABCA1C861AF9951
진단명 Remote Access Trojans, RAT
악성 동작 l  C2 서버 연결
l  드라이브 정보 수집
l  화면 정보 수집
l  캠 정보 수집
l  오디오 정보 수집
l  프로세스 정보 수집
l  명령어 수행 및 결과 값 정보 수집
l  시스템 종료 권한 설정
l  파일 드랍
l  이벤트 로그 삭제
l  특정 URL 주소 접속
l  서비스 HOST ID 값 설정
연결 대상 211.110.139.167(대한민국)

 

 

 

2. 분석 내용

2.1. 악성 행위 전체 흐름도

게임핵에 생성된 파일의 이름은 ‘Top_dump_2.dll’ 입니다. 해당 파일은 최종적으로 C2 서버에서 명령어를 받아서 아래와 같은 악성 행위를 수행하고 결과 값을 다시 C2에 전송합니다.

[그림 1] 악성코드 흐름도

 

 

 

 

2.2. 상세 분석

2.2.1. C2 서버 연결

DLL 파일이 실행되면 ‘CreateThread’ 함수를 통하여 쓰레드를 생성합니다. 생성된 쓰레드에서 실행되는 함수는 ‘user32.dll’, ‘advapi32.dll’, ‘shell32.dll’, ‘gdi32.dll’, ‘ws2_32.dll’ 모듈을 로드하고 ‘sub_180010850’ 함수를 실행합니다.

[그림 2] 모듈 로드

 

모듈을 로드한 이후 ‘sub_180001C50’ 함수에서 ‘connect’ 함수를 실행하여 C2 서버로 연결을 수행합니다.

[그림 3] Connect 함수를 통해 C2 접속

 

실제 디버깅을 수행해보면  ‘211.110.139.167’ IP 주소에 ‘21354’ 포트로 연결을 수행하는 것을 확인할 수 있습니다.

[그림 4] Connect 함수 디버깅 화면

 

C2 서버 연결 이후에는 ‘CreateEventA’, ‘beginthreadex’, ‘WaitForSingleObject’ 함수를 사용하여 쓰레드를 생성합니다.

 

‘CreateEventA’ 함수를 통하여 논시그널(Non-signal) 상태의 이벤트를 생성하고 beginthreadex 함수를 통하여 쓰레드를 생성하여 ‘sub_18000DCE0’ 함수를 실행합니다.

 

이후 ‘WaitForSingleObject’ 함수를 통해 생성된 이벤트가 시그널(Signal) 상태로 변경될때까지 대기합니다.

[그림 5] 쓰레드 생성 방법

 

‘sub_18000DCE0’ 함수는 이벤트 상태를 시그널 상태로 변경하고 인자 값으로 전달 받은 함수를 실행합니다.

[그림 6] 이벤트 처리 및 함수 실행

 

 

recv 함수를 통해 C2 서버에서 전달받은 바이트의 첫 5바이트에 ‘Gh0st’ 문자열이 있는지를 확인하고 해당 문자열이 없을 경우 예외가 발생됩니다.

 

정상적으로 ‘Gh0st’ 문자열이 있을 경우 zlib을 통해 압축된 데이터를 해제를 수행합니다. 압축 해제된 데이터를 인자 값으로 동적으로 함수를 호출합니다.

[그림 7] 동적 함수 실행

 

동적으로 함수를 호출하는 부분은 메인 쓰레드에서는 ‘CKernelManager vftable’ 값으로 설정합니다. ‘CKernelManager’의 행위는 C2 서버에서 명령어를 전달받으면 악성행위를 수행합니다.

[그림 8] 동적 함수 설정

 

동적 함수을 설정한 이후, “HKLM\HARDWARE\DESCRIPTION\System\CentralProcessor\0” 키에서 “~MHz”의 데이터에서 프로세서의 속도의 정보와, ‘capGetDriverDescriptionA’ API 함수를 사용하여 PC에 연결되어있는 카메라 정보를 획득하여 C2 서버로 전송합니다.

[그림 9] 프로세서 속도 정보

 

2.2.2. 드라이브 정보 수집

이후, C2 서버로부터 zlib으로 인코딩된 0x1 바이트가 전달되면 드라이브에 대한 정보를 수집합니다.

 

‘GetlogicaldrivestringsA’ 함수를 사용하여 논리적 드라이브의 정보를 획득하고 ‘GetVolumeInformationA’, ‘GetDiskFreeSpaceExA’ 함수를 통하여 획득한 논리적 드라이브의 루트 디렉터리와 연결된 파일 시스템 및 볼륨에 대한 정보를 검색 및 볼륨에서 사용 가능한 공간의 양에 대한 정보를 수집합니다.

 

[그림 10] 드라이브 정보 수집

 

최종적으로 수집한 정보를 zlib을 통하여 압축하고 ‘Gh0st’ 문자열, 패킷 전체 길이, 압축 전 데이터 길이, 압축 데이터(수집된 정보)로 패킷 구조를 생성합니다.

[그림 11] 전송 데이터 구조

 

최종적으로 수집한 정보를 C2 서버에게 압축(‘Gh0st’ 문자열, 패킷 전체 길이, 압축 전 데이터 길이, 압축 데이터)하여 정보를 전송합니다.

[그림 12] 정보 전송

 

2.2.3. 화면 정보 수집

C2 서버로부터 zlib으로 인코딩된 0x10 바이트가 전달되면 화면 정보를 수집합니다.

‘BitBlt’ 함수는 한 장치(Device)에서 다른 장치로 그래픽 데이터를 복사하여 스크린샷을 정보를 수집합니다.

[그림 13] 화면 정보 수집

 

최종적으로 수집한 정보를 C2 서버에게 압축하여 정보를 전송합니다.

[그림 14] 정보 전송

 

2.2.4. 캠 정보 수집

C2 서버로부터 zlib으로 인코딩된 0x1A 바이트가 전달되면 컴퓨터에 연결된 캠(카메라)에 대한 정보를 수집합니다.

감염 PC에 캠이 연결되어 있을 경우 ‘capCreateCaptureWindowA’ 함수를 통해 캡쳐 윈도우를 생성하여 캠에서 실시간 정보를 수집합니다.

[그림 15] 캠 정보 수집

 

최종적으로 수집한 정보를 C2 서버에 압축하여 정보를 전송합니다.

[그림 16] 정보 전송

 

2.2.5. 오디오 정보 수집

C2 서버로부터 zlib으로 인코딩된 0x22 바이트가 전달되면 오디오에 대한 정보를 수집합니다.

‘waveInGetNumDevs’ 함수를 통하여 윈도우에 연결된 입력 장치(마이크)을 조사합니다.

만약, 입력 장치가 있을 경우, 해당 입력 장치의 핸들을 획득하고 녹음 정보를 수집합니다. (waveInOpen, waveInPrepareHeader, waveInaddBuffer)

[그림 17] 오디오 정보 수집

 

최종적으로 수집한 정보를 압축해 C2 서버에 전송합니다.

[그림 18] 정보 전송

 

2.2.6. 프로세스 정보 수집

C2 서버로부터 zlib으로 인코딩된 0x23 바이트가 전달되면 프로세스에 대한 정보를 수집합니다.

 

모든 프로세스의 핸들을 획득하기 위해 실행 중인 악성 프로세스에 ‘SeDebugPrivilege’ 권한을 부여합니다.

[그림 19] 프로세스 권한 할당

 

‘CreateToolhelp32Snapshot’, ‘Process32First’ 함수를 통하여 모든 프로세스의 목록을 가져옵니다. 이 후 프로세스의 핸들을 획득하고 각 프로세스의 이름, PID 등의 정보를 수집합니다.

[그림 20] 프로세스 정보 수집

 

 

최종적으로 수집한 정보를 압축해 C2 서버에 전송합니다.

[그림 21] 정보 전송

 

2.2.7. 명령어 수행 및 결과 값 정보 수집

C2 서버로부터 zlib으로 인코딩된 0x28 바이트가 전달되면 명령어를 수행하고 결과 값을 C2 서버에 전송합니다.

‘CreatePipe’ 함수를 통하여 프로세스 실행 결과 값을 전달받을 수 있게 설정하고 ‘CreateProcessA’ 함수를 통해 ‘cmd.exe’(명령 프롬프트)를 생성합니다. 생성된 ‘cmd.exe’ 프로세스에서 공격자의 명령어를 수행합니다.

[그림 22] 명령 프롬프트 생성

 

‘cmd.exe’ 프로세스에서 실행된 결과 값을 ‘NamedPipe’에서 읽고 압축된 정보를 C2 서버로 전송합니다.

[그림 23] 명령어 결과 값 전송

 

2.2.8. 시스템 종료 권한 설정

C2 서버로부터 zlib으로 인코딩된 0x29 바이트가 전달되면 현재 프로세스에 ‘SeShutdownPrivilege’(시스템 종료 권한)을 할당합니다.

[그림 24] SeShutdownPrivilege 권한 할당

 

2.7. 프로세스 종료

C2 서버로부터 zlib으로 인코딩된 0x2A 바이트가 전달되면 프로세스를 종료합니다.

[그림 25] 프로세스 종료

 

2.2.9. 파일 드랍

C2 서버로부터 zlib으로 인코딩된 0x2B 바이트가 전달되면 C2 서버로부터 전달된 URL 주소에 접속하여 해당 바이트를 읽고 파일로 저장한다.

[그림 26] 파일 생성

 

2.2.10. 이벤트 로그 삭제

C2 서버로부터 zlib으로 인코딩된 0x2D 바이트가 전달되면 감염 PC의 ‘Application’, ‘Security’, ‘System’ 이벤트 로그를 모두 지운다.

[그림 27] 이벤트 로그 제거

 

2.2.11. 특정 URL 주소 접속

C2 서버로부터 zlib으로 인코딩된 0x2e, 0x2f 바이트가 전달되면 인터넷 익스플로러을 통해 C2 서버에서 전달되는 URL 주소로 접속한다.

‘HKEY_CLASSES_ROOT\\Applications\\iexplore.exe\\shell\\open\\command’ 서브키에서 ‘iexplorer.exe’ 파일의 경로를 반환 받아 C2서버로부터 전달받은 URL 주소를 실행한다.

0x2f값일 경우에는 lpdesktop을 설정하여 포그라운드에서 실행한다.

[그림 28] 인터넷 익스플로러를 통해 URL 접속

 

2.2.12. 서비스 HOST ID 값 설정

C2 서버로부터 zlib으로 인코딩된 0x30바이트가 전달되면 ‘HKLM \SYSTEM\CurrentControlSet\services’ 키에 ‘Host’ 값을 생성한다.

[그림 29] HOST ID 설정

 

3. 결론

게임핵에서 생성하는 해당 파일은 Remote Access Trojans, RAT 기능을 수행하는 악성코드로 C2 서버로부터 zlib으로 압축된 명령어를 전달받아 정보 수집 및 유출 등의 행위를 수행합니다.

 

악성 DLL이 C2 서버와 통신하는 방법은 약속된 구조체를 사용합니다. 통신에 사용되는 구조체는 아래 그림과 같습니다. 시그니처(5Byte), 패킷 총 길이(4Byte), 압축이 해제된 데이터 길이(4Byte), 압축 데이터(x byte)로 구성되어 있습니다. 이때, 데이터는 압축 방법은 zlib 방식을 사용합니다.

[그림 30] 악성 DLL 통신 방법