
Python 기반의 오픈소스 게임 개발 도구인 RenPy를 악용해 HijackLoader를 유포하는 사례가 발견됐다. RenPy로 제작된 게임은 실행에 필요한 Python 코드와 리소스가 ZIP 파일 형태로 배포되며 공격자는 게임 실행 흐름의 진입점에 해당하는 Script.rpy 파일에 RenEngine Loader라는 악성 스크립트를 삽입했다. 해당 스크립트는 먼저 샌드박스 환경 여부를 점검하고 동일한 ZIP 파일 내에 함께 포함된 HijackLoader를 실행하는 역할을 수행한다. HijackLoader는 모듈형 구조의 악성코드로 최종 페이로드 실행에 필요한 모듈을 복호화 및 로드하는 방식으로 동작한다. 또한 DLL Stomping과 Heaven's Gate 등 다양한 탐지 및 분석 방지 기법이 적용됐다.
RenEngine Loader
RenPy 기반 게임의 ZIP 아카이브를 압축 해제하면 Instaler.exe라는 실행 파일이 존재하며 해당 파일은 게임 실행 진입점인 Script.rpy를 추출 및 실행하는 역할을 한다. RenEngine Loader는 Script.rpy 내에 삽입된 악성 스크립트로 시작되며 먼저 PowerShell 명령어를 이용해 샌드박스 환경을 검사한 후 같은 폴더 내 .key 파일을 Base64 디코딩해 다음 단계에서 사용할 파일명 및 암호 등의 문자열을 획득한다.

디코딩한 문자열 중에서 filename이 가리키는 Zt5qwYUCFL.txt 파일을 password인 “eAX7G6bTT”로 XOR 복호화 후 압축을 해제한다. 압축 해제된 파일은 [표 1]의 정상 EXE 파일, 악성 DLL 파일 및 암호화된 셸코드 파일을 포함하며 그중 정상 EXE 파일 W8CPbGQI.exe를 실행해 d3dx9_43.dll(HijackLoader)을 로드한다.


HijackLoader
d3dx9_43.dll은 CPU가 SSE2 명령어를 지원하는지 런타임에서 확인하고 초기화하는 함수 __sse2_available_init()를 수정해 사용하며 해당 함수 내에서 다음 페이로드인 VSDebugScriptAgent170.dll 파일을 로드한 후 로드된 DLL의 0x7076 주소를 호출한다.
- SSE2(Streaming SIMD Extensions 2): IA-32 SIMD(Single Instruction, Multiple Data) 명령어 집합의 일종.

DLL Stomping
호출된 VSDebugScriptAgent170.dll의 0x7076 주소의 코드는 정상 evr.dll을 대상으로 DLL Stomping을 수행한다. DLL Stomping은 DLL 인젝션 방식 중 하나로 삽입할 셸코드를 로드된 DLL의 코드 영역에 덮어쓰는 기법이다. 셸코드는 같은 폴더 내 Tiag.gr 파일 오프셋 0x1A92에 암호화된 상태로 저장돼 있으며 4바이트의 키(0xE3D56B78)와 더하면서 복호화한다. 이후 evr.dll의 BaseOfCode가 가리키는 주소에 복호화된 셸코드를 복사한 후 0xED0 주소를 호출해 실행한다.


모듈 로드
호출된 셸코드는 Froodjurain.wkk 파일에서 ti 모듈을 추출 및 로드한다. Froodjurain.wkk는 HijackLoader가 사용하는 모듈 데이터를 IDAT 문자열(49 44 41 54)을 기준으로 나누어 저장한 파일이다. 셸코드는 파일 내의 모든 IDAT 문자열을 검색한 후 각 문자열 바로 다음 바이트부터 0x2000 크기만큼 데이터를 읽어 하나의 블록으로 결합한다. 이렇게 만들어진 블록에서 오프셋 0x4의 4바이트 값(0xC67BCDDB)을 키로 사용해 오프셋 0x10부터 XOR 복호화를 수행하며 이때 오프셋 0x8의 4바이트 값(0x2074DA)이 복호화할 데이터의 크기를 나타낸다.

복호화된 데이터는 LZNT1 알고리즘으로 압축된 데이터이며 RtlDecompressBuffer 함수를 이용해 압축 해제한 후 아래 과정에 따라 ti 모듈을 검색한다. 원하는 모듈의 위치 및 크기 정보가 확인되면 셸코드 형태의 모듈 데이터를 정상 rasapi32.dll을 대상으로 [그림 5]의 DLL Stomping 방식으로 인젝션해 로드한다.
① 복호화된 데이터(Data)에서 모듈 정보를 담고 있는 테이블(Table)의 위치를 계산한다.
- Table Offset = *(Data + 0x8) + *(Data + 0x160) + 0x3DD + 0x10DE
② 테이블의 각 항목은 0x8A의 크기를 가지며 가장 앞에 모듈의 이름을 저장하고 있다.
③ 테이블에서 원하는 이름을 검색하고 해당 항목(Table[N])에 저장된 모듈의 위치와 크기 정보를 확인한다.
- 모듈 위치: Table Offset – 0x10DE + 0xEE4 + *(Table[N] + 0x82) / 모듈 크기: *(Table[N] + 0x86)


Heaven’s Gate
HijackLoader의 ti 모듈은 프로세스 할로잉을 이용해 최종 페이로드를 로드하는 역할을 수행하며 그 과정에서 32비트 프로세스에서 64비트 API를 직접 호출하는 Heaven’s Gate 기법을 사용한다. Heaven’s Gate는 32비트 ntdll.dll의 Windows Native API의 코드에서 System Call Number를 추출하고 64비트 환경으로 모드 스위칭 후 syscall을 직접 호출하는 방식으로 구현된다. 이와 같은 방식은 디버거로 추적이 불가능하지만 하드코딩된 CRC32 해시로 프로세스 할로잉과 관련된 API의 목록을 확인할 수 있다.

System Call Number 추출
Windows Native API 중 NtCreateFile을 예시로 32비트와 64비트에서 해당 함수의 구현 코드를 확인해보면 eax 레지스터에 동일하게 0x55 값을 저장한 후 시스템 호출을 수행하는 것을 알 수 있다. 이를 바탕으로 ti 모듈은 로드된 32비트 ntdll.dll에서 필요한 API의 System Call Number를 추출한 후 64비트 환경에서 System Call 과정을 직접 구현해 호출하도록 설계됐다.

모드 스위칭
런타임 중 32비트와 64비트 간의 모드 스위칭은 jmp far, call far, ret far 명령어를 사용해 CS 레지스터의 값을 변경함으로써 발생하며 ti 모듈에서는 스택에 0x33을 push한 후 ret far 명령어로 CS 레지스터 값을 변경하고 64비트 환경으로 전환한다. 이후 syscall을 호출해 원하는 Windows Native API를 실행하고 0x23 값과 ret far를 이용해 32비트로 돌아온다.
- CS 레지스터 값에 따른 모드 스위칭: 0x1B(32 native), 0x23(32 WOW64), 0x33(64 native)


오픈소스 게임 개발 도구인 RenPy에 삽입된 악성코드는 실제 게임 구동과 함께 백그라운드에서 악성 동작을 수행하기 때문에 감염 여부를 식별하기 어렵고 Heaven’s Gate와 같은 기법으로 탐지 및 분석을 방해하기 때문에 주의가 필요하다. 따라서, 공식 사이트가 아닌 사설 공유 플랫폼에서 게임 또는 소프트웨어의 다운로드를 지양하고 보안 프로그램과 OS를 항상 최신 버전으로 유지할 것을 권고한다.
상기 악성코드는 잉카인터넷 안티바이러스 제품 TACHYON Internet Security 6.0에서 진단 및 치료가 가능하다.


'분석 정보 > 악성코드 분석 정보' 카테고리의 다른 글
| PyPI mistralai 패키지 공급망 침해 분석 (0) | 2026.05.19 |
|---|---|
| CPU-Z 공급망 공격 분석 (1) | 2026.05.12 |
| 해커조직 TeamPCP, LiteLLM PyPI에 악성코드 삽입 (0) | 2026.04.21 |
| ILSpy 홈페이지로 위장한 멀웨어 유포 주의 (0) | 2026.04.15 |
| DeepLoad, 확장 프로그램으로 위장해 암호화폐 탈취 (0) | 2026.04.14 |