
리버스 엔지니어링 노트, 난독화 해제된 소스, IOC, 그리고 Tourmaline ClickFix Python RAT의 YARA 규칙으로, DNS 터널과 블록체인 데드드롭 C2를 다룹니다.
저는 최근에 스스로를 "Torumaline"이라고 부르는 교묘하게 설계된 악성코드를 우연히 발견했습니다.
이 README는 이 저장소가 처음 만들어질 당시 제가 시험 준비로 매우 바빴기 때문에 Claude가 아주 친절하게 작성해 주었습니다.
이 악성코드를 분석하고 복호화하는 데 수학 준비 시간의 상당 부분을 쏟아부었습니다!
블로그 글을 읽어보세요!
교육 및 연구 목적으로만 사용
모든 샘플은 악성코드 분석 및 방어 연구를 위해 제공됩니다. 샌드박스화된 에어갭 환경 외부에서 실행하지 마십시오.
Tourmaline(Tourmaline.exe)은 ClickFix 캠페인을 통해 유포되는 정교한 다단계 Windows 정보 탈취기/백도어입니다. ClickFix는 가짜 Cloudflare "사람인지 확인하세요" 브라우저 팝업으로, 사용자가 악성 명령이나 설치 프로그램을 직접 실행하도록 속입니다.
이 바이너리는 완전한 Python 3.11 런타임과 두 단계의 난독화된 Python 페이로드를 번들로 포함하는 맞춤 제작된 Inno Setup 6.7.0 (Revision 2, 64비트 오프셋) 설치 프로그램입니다. 다음과 같은 지속적 백도어를 구축합니다:
microsoft.com 쿼리로 위장)tourmaline/
├── README.md # 이 파일
├── LICENSE # 연구용 라이선스
├── .gitignore
│
├── src/ # 추출 및 디오브푸스케이트된 소스 코드
│ ├── stage1_loader.py # Stage 1: 원본 난독화된 XOR 타임락 로더 (main.py)
│ ├── stage2_backdoor.py # Stage 2: 디오브푸스케이트된 핵심 백도어 (QGBdu.dxf에서 추출)
│ └── decrypt_payload.py # 유틸리티: O(1) 페이로드 키 복구 및 복호화
│
├── iocs/ # 침해 지표
│ ├── indicators.json # 구조화된 IOC 데이터 (IP, 해시, 도메인, 레지스트리)
│ ├── indicators.csv # SIEM 가져오기용 플랫 CSV
│ └── rules.yar # YARA 탐지 규칙
│
└── samples/ # 악성코드 샘플 (비밀번호 보호됨)
├── README.md # 샘플 아카이브 지침
├── Tourmaline_sample.zip # 비밀번호: infected - Tourmaline.exe 포함
└── QGBdu.dxf # 원시 암호화된 Stage 2 페이로드 블롭
이 악성코드는 ClickFix를 통해 유포됩니다. ClickFix는 침해되었거나 공격자가 제어하는 웹사이트가 가짜 Cloudflare CAPTCHA 또는 브라우저 확인 페이지를 오버레이하는 사회공학 기법입니다. 오버레이는 피해자에게 다음을 지시합니다:
Win+R 누르기붙여넣은 명령은 Tourmaline.exe를 다운로드하고 조용히 실행합니다. 설치 프로그램은 /VERYSILENT /SUPPRESSMSGBOXES /NORESTART로 실행됩니다.
참고: 기본
innoextract 1.9는 이 바이너리를 추출할 수 없습니다 — Revision 1만 지원합니다. Revision 2는 64비트 오프셋을 사용하며 사용자 정의 파싱이 필요합니다 (src/decrypt_payload.py참조).
Tourmaline.exe
│
├─ Inno Setup 설치 프로그램이 조용히 실행됨
│ ├─ Python 3.11 런타임을 %APPDATA%\Tourmaline\에 추출
│ ├─ main.py 추출 (Stage 1 로더)
│ ├─ QGBdu.dxf 추출 (암호화된 Stage 2 블롭)
│ ├─ 기존 pythonw.exe 인스턴스 종료
│ └─ 지속성 등록 (작업 스케줄러 / 레지스트리)
│ └─ 이름: "TourmalineUpdate" / "Hardware monitoring service"
│
├─ Stage 1: main.py (XOR 타임락 로더)
│ ├─ _n을 99,999,999 → 0으로 카운트 (느린 VM에서 수 시간의 안티 샌드박스 지연)
│ ├─ 각 _n에서 33바이트 XOR 키 생성: struct.pack('>I', _n) + 하드코딩된 접미사
│ ├─ QGBdu.dxf의 알려진 평문 헤더에 대해 키 테스트
│ └─ 일치 시: QGBdu.dxf를 완전히 복호화하고 결과를 exec()
│ └─ O(1) 우회: 처음 4바이트에 대한 기지 평문 공격 (아래 참조)
│
└─ Stage 2: QGBdu.dxf → Python 백도어
├─ HKLM\SOFTWARE\Microsoft\Cryptography에서 MachineGuid 읽기
├─ 뮤텍스 Global\Tourmaline_<hash> 파생
├─ 이더리움 데드드롭(Sepolia 테스트넷)을 통해 C2 IP 확인
├─ C2에 DNS 터널 설정
└─ 폴링-실행 루프: 작업 가져오기, Python exec(), 출력 반환
로더(main.py)는 XOR 복호화 키를 찾기 위해 99,999,999부터의 카운트다운을 사용합니다. 실제 머신에서는 몇 초 만에 완료됩니다 (_n이 높게 시작하고 실제 값이 14,511,188 근처에 있기 때문). 짧은 시간 제한이 있는 샌드박스에서는 루프가 완료되지 않습니다.
키 구조:
full_key = struct.pack('>I', _n) + bytes.fromhex('2b0cffe07b06ac25793b3f00cfaa2dd5881c2d6378165247539dbbdaeb')
평문의 처음 16바이트(g1 = lambda l6, )를 알고 있으므로 기지 평문 XOR 공격을 통해 _n을 즉시 복구할 수 있습니다:
key_prefix = bytes(ciphertext[i] ^ known_plaintext[i] for i in range(4))
# 결과: key_prefix = 00dd6c54 → _n = 14,511,188
이를 재현하려면 src/decrypt_payload.py를 사용하십시오.
이 악성코드는 Sepolia 테스트넷의 이더리움 스마트 컨트랙트를 호출하여 활성 C2 IP 주소를 검색합니다. 이는 공격자가 컨트랙트를 업데이트하여 언제든지 C2 IP를 변경할 수 있음을 의미합니다 — 전통적인 IP 블록리스트 기반 C2 차단은 효과가 없습니다.
Contract : 0x2d7a04cca0c34005f58393f30ac725e25f19e5f5
Selector : 0xeb9fd6fe
Network : Ethereum Sepolia (chainId 11155111)
RPC : https://ethereum-sepolia-rpc.publicnode.com
Result : 현재 C2 IP를 포함하는 ChaCha20 암호화 블롭
반환된 데이터는 하드코딩된 ChaCha20 키로 복호화되어 실제 C2 주소를 드러냅니다. 분석 시점에 이는 **158.94.211.185**로 확인되었습니다 (라이브 RPC 호출로 검증됨).
모든 C2 트래픽은 원시 UDP DNS 쿼리로 C2 IP의 포트 53에 직접 전송됩니다. 쿼리는 <encoded_data>.microsoft.com 형식으로 구성되어 DNS 기반 필터링을 우회하고 정상적인 Windows 텔레메트리로 보입니다.
socket.getaddrinfo나 DNS 라이브러리를 사용하지 않음백도어는 임의의 Python exec() 엔진을 구현합니다. 작업은:
exec()됨지원되는 작업 유형: Python exec, 파일 업로드/다운로드, 셸 명령, 자체 업데이트.
| 파일 | SHA256 |
|---|---|
Tourmaline.exe | c9b390b3b7148f549df86503858d52e030b2b5e78fed0bc525ded5927f9265d6 |
Tourmaline.exe (MD5) | b74ac808dea2de31caf024310694ef0c |
다음을 포함하는 탐지 규칙은 iocs/rules.yar를 참조하십시오:
이 악성코드가 머신에서 실행된 경우:
taskkill /F /IM pythonw.exe%APPDATA%\Tourmaline\ 또는 %COMMONAPPDATA%\Tourmaline\TourmalineUpdate 삭제HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Run에서 Tourmaline 또는 SystemService 확인158.94.211.185:53/UDP; 모든 예상치 못한 아웃바운드 UDP/53 차단ethereum-sepolia-rpc.publicnode.compip install pyOpenSSL cryptography
# 저장소 루트에서:
python3 src/decrypt_payload.py samples/QGBdu.dxf decrypted_stage2.py
7z x -pinfected samples/Tourmaline_sample.zip
LICENSE를 참조하십시오. 이 저장소는 교육 및 방어 연구 목적으로만 사용됩니다.
| 속성 | 값 |
|---|
| 파일 이름 | Tourmaline.exe |
| 크기 | 11,341,339 바이트 (~10.8 MB) |
| MD5 | b74ac808dea2de31caf024310694ef0c |
| SHA256 | c9b390b3b7148f549df86503858d52e030b2b5e78fed0bc525ded5927f9265d6 |
| 형식 | Inno Setup 6.7.0 Unicode (Revision 2, 64비트 오프셋) |
| PE 유형 | 32비트 PE, 11개 섹션 |
| 오버레이 크기 | 10,447,387 바이트 |
| Inno 매직 오프셋 | 0xD9864 (890,148 바이트) |
| 앱 이름 | Tourmaline |
| 앱 버전 | 2.63.519 |
| 앱 GUID | {2C25872D-85FC-44C7-9B16-844E39E50A44} |
| 설치 경로 | {commonappdata}\Tourmaline |
| 번들 런타임 | Python 3.11 (전체 임베드) |
| 페이로드 파일 | 솔리드 LZMA2 스트림 내 36개 파일 |
| 매개변수 | 값 |
|---|
| C2 IP | 158.94.211.185 |
| C2 포트 | 53 (UDP) |
| 프로토콜 | 사용자 정의 DNS-over-UDP 터널 |
| 스푸핑된 도메인 | microsoft.com |
| ChaCha20 키 | 36f555c87f71581f57d83576c88193fdc00a0173f741a3e198e2d7abdc9cda59 |
| 블록체인 컨트랙트 | 0x2d7a04cca0c34005f58393f30ac725e25f19e5f5 (Sepolia) |
| ECDSA 공개키 | MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEt17l3rGHHR9sYdHEvV8S+JRRCUHQQveSadlGk04xM/8WClDf/67Tyritt2+T18SY8n0xv1TKKl0AgnNFuboEEQ== |
| 서비스 이름 | SystemService / TourmalineUpdate |
| 뮤텍스 | Global\Tourmaline_<MachineGuid-hash> |
| 유형 | 값 |
|---|
| C2 IP | 158.94.211.185 |
| C2 포트 | 53/UDP |
| 스푸핑된 도메인 | *.microsoft.com (사용자 정의 UDP, 실제 DNS 아님) |
| 이더리움 RPC | https://ethereum-sepolia-rpc.publicnode.com |
| 스마트 컨트랙트 | 0x2d7a04cca0c34005f58393f30ac725e25f19e5f5 |
| 키 | 값 |
|---|
HKLM\SOFTWARE\Microsoft\Cryptography\MachineGuid | 피해자 핑거프린팅을 위해 읽힘 |
%APPDATA%\Tourmaline\ | 설치 디렉터리 |
| 작업 스케줄러 | TourmalineUpdate |
| 서비스 표시 이름 | Hardware monitoring service |
| 뮤텍스 | Global\Tourmaline_<hash> |
| 필드 | 값 |
|---|
| 발견 날짜 | 2026년 9월 |
| 연구자 | Vihaan Pundir (v-pun215) |
| 유포 경로 | ClickFix 가짜 Cloudflare CAPTCHA |
| 분류 | 백도어 / DNS 터널 C2 / 블록체인 데드드롭 |
| 플랫폼 | Windows (64비트) |