Skip to content
KitploitKITPLOIT
도구익스플로잇블로그
Log in
제출
도구익스플로잇블로그
제출

해킹, 침투 테스트 및 사이버 보안 도구를 당신의 보안 무기고에!

Kitploit은 해킹, 사이버 보안 및 침투 테스트 도구 디렉토리입니다. 최신 프로젝트 업데이트를 발견하여 취약점을 찾고, 시스템을 분석하고, 테스트를 자동화하고, 보안을 강화하세요.

피드문의개인정보© 2026 Kitploit

도구 디렉토리

카테고리

모든 카테고리 보기
Loading categories
도구/GitHubGitHub/v-pun215/tourmaline
Indicator of Compromise (IOC) ManagementReverse EngineeringMalware AnalysisDigital ForensicsCryptographyCommand and ControlThreat IntelligenceLearning & EducationIncident ResponseDNS Analysis
GitHubv-pun215/tourmaline
109321일 전아직 검토되지 않음

인기

모두 보기 →

커뮤니티에서 가장 많이 사용되는 도구를 찾아보세요.

모든 도구 탐색

도구 컬렉션을 둘러보세요

모든 도구 보기 →
공유

Tourmaline

Reverse engineering notes, deobfuscated source, IOCs, and YARA rules for the Tourmaline ClickFix Python RAT, covering its DNS tunnel and blockchain dead-drop C2.

저장소 보기
요청한 언어로 콘텐츠를 사용할 수 없습니다. 영어 버전을 표시합니다.

Tourmaline

I recently stumbled upon a piece of cleverly designed malware that calls itself "Tourmaline".

This README is very kindly written by Claude as I was super busy with exams at the time of this repository's inception.

Exploiting and decrypting this malware took a huge chunk of my time from math prep!

Read the blogpost!

FOR EDUCATIONAL AND RESEARCH PURPOSES ONLY
All samples are provided for malware analysis and defensive research. Do not execute outside a sandboxed, air-gapped environment.


Overview

Tourmaline (Tourmaline.exe) is a sophisticated, multi-stage Windows infostealer/backdoor distributed via a ClickFix campaign - a fake Cloudflare "Verify you are human" browser popup that tricks users into manually running a malicious command or installer.

The binary is a custom-built Inno Setup 6.7.0 (Revision 2, 64-bit offsets) installer that bundles a full Python 3.11 runtime and two stages of obfuscated Python payload. It establishes a persistent backdoor with:

  • DNS tunneling C2 over UDP port 53 (masquerading as microsoft.com queries)
  • Ethereum blockchain dead-drop for C2 IP distribution (Sepolia testnet)
  • ChaCha20-encrypted task execution channel
  • ECDSA-signed commands to prevent sinkholing
  • Anti-sandbox time-lock (100M iteration countdown, bypassable in O(1))

Repository Structure

tourmaline/
├── README.md                  # This file
├── LICENSE                    # Research use license
├── .gitignore
│
├── src/                       # Extracted & deobfuscated source code
│   ├── stage1_loader.py       # Stage 1: Original obfuscated XOR time-lock loader (main.py)
│   ├── stage2_backdoor.py     # Stage 2: Deobfuscated core backdoor (from QGBdu.dxf)
│   └── decrypt_payload.py     # Utility: O(1) payload key recovery & decryption
│
├── iocs/                      # Indicators of Compromise
│   ├── indicators.json        # Structured IOC data (IPs, hashes, domains, registry)
│   ├── indicators.csv         # Flat CSV for SIEM import
│   └── rules.yar              # YARA detection rules
│
└── samples/                   # Malware samples (password-protected)
    ├── README.md              # Sample archive instructions
    ├── Tourmaline_sample.zip  # Password: infected - contains Tourmaline.exe
    └── QGBdu.dxf             # Raw encrypted Stage 2 payload blob

Infection Vector

The malware is distributed via ClickFix - a social engineering technique where a compromised or attacker-controlled website overlays a fake Cloudflare CAPTCHA or browser verification page. The overlay instructs the victim to:

  1. Press Win+R
  2. Paste a command (copied to clipboard by the page's JavaScript)
  3. Press Enter

The pasted command downloads and silently executes Tourmaline.exe. The installer runs /VERYSILENT /SUPPRESSMSGBOXES /NORESTART.


Binary Format

PropertyValue
File nameTourmaline.exe
Size11,341,339 bytes (~10.8 MB)
MD5b74ac808dea2de31caf024310694ef0c
SHA256c9b390b3b7148f549df86503858d52e030b2b5e78fed0bc525ded5927f9265d6
FormatInno Setup 6.7.0 Unicode (Revision 2, 64-bit offsets)
PE type32-bit PE, 11 sections
Overlay size10,447,387 bytes
Inno magic offset0xD9864 (890,148 bytes)
App nameTourmaline
App version2.63.519
App GUID{2C25872D-85FC-44C7-9B16-844E39E50A44}
Install path{commonappdata}\Tourmaline
Bundled runtimePython 3.11 (full embed)
Payload files36 files in solid LZMA2 stream

Note: Stock innoextract 1.9 cannot extract this binary — it only supports Revision 1. Revision 2 uses 64-bit offsets and requires custom parsing (see src/decrypt_payload.py).


Execution Flow

Tourmaline.exe
│
├─ Inno Setup installer runs silently
│   ├─ Extracts Python 3.11 runtime to %APPDATA%\Tourmaline\
│   ├─ Extracts main.py (Stage 1 loader)
│   ├─ Extracts QGBdu.dxf (encrypted Stage 2 blob)
│   ├─ Kills any existing pythonw.exe instances
│   └─ Registers persistence (Task Scheduler / registry)
│       └─ Name: "TourmalineUpdate" / "Hardware monitoring service"
│
├─ Stage 1: main.py (XOR Time-Lock Loader)
│   ├─ Counts _n from 99,999,999 → 0 (anti-sandbox delay ~hours on slow VMs)
│   ├─ At each _n, constructs 33-byte XOR key: struct.pack('>I', _n) + hardcoded_suffix
│   ├─ Tests key against known plaintext header of QGBdu.dxf
│   └─ On match: decrypts QGBdu.dxf entirely and exec()s the result
│       └─ O(1) bypass: known-plaintext attack on first 4 bytes (see below)
│
└─ Stage 2: QGBdu.dxf → Python backdoor
    ├─ Reads MachineGuid from HKLM\SOFTWARE\Microsoft\Cryptography
    ├─ Derives mutex Global\Tourmaline_<hash>
    ├─ Resolves C2 IP via Ethereum dead-drop (Sepolia testnet)
    ├─ Establishes DNS tunnel to C2
    └─ Poll-execute loop: fetches tasks, exec()s Python, returns output

Stage 1 — Anti-Sandbox Time-Lock (O(1) Bypass)

The loader (main.py) uses a countdown from 99,999,999 to find the XOR decryption key. On a real machine this completes in seconds (because _n starts high and the true value is near 14,511,188). In a sandbox with a short time limit, the loop never completes.

Key structure:

full_key = struct.pack('>I', _n) + bytes.fromhex('2b0cffe07b06ac25793b3f00cfaa2dd5881c2d6378165247539dbbdaeb')

Since we know the first 16 bytes of the plaintext (g1 = lambda l6, ), we can recover _n instantly via known-plaintext XOR attack:

key_prefix = bytes(ciphertext[i] ^ known_plaintext[i] for i in range(4))
# Result: key_prefix = 00dd6c54 → _n = 14,511,188

Use src/decrypt_payload.py to reproduce this.


Stage 2 — Core Backdoor Architecture

Configuration (Hardcoded)

ParameterValue
C2 IP158.94.211.185
C2 Port53 (UDP)
ProtocolCustom DNS-over-UDP tunnel
Spoofed domainmicrosoft.com
ChaCha20 key36f555c87f71581f57d83576c88193fdc00a0173f741a3e198e2d7abdc9cda59
Blockchain contract0x2d7a04cca0c34005f58393f30ac725e25f19e5f5 (Sepolia)
ECDSA pubkeyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEt17l3rGHHR9sYdHEvV8S+JRRCUHQQveSadlGk04xM/8WClDf/67Tyritt2+T18SY8n0xv1TKKl0AgnNFuboEEQ==
Service nameSystemService / TourmalineUpdate
MutexGlobal\Tourmaline_<MachineGuid-hash>

Blockchain Dead-Drop (C2 Resilience)

The malware calls an Ethereum smart contract on the Sepolia testnet to retrieve the active C2 IP address. This means the attacker can change the C2 IP at any time by updating the contract — traditional IP blocklist-based C2 disruption is ineffective.

Contract : 0x2d7a04cca0c34005f58393f30ac725e25f19e5f5
Selector : 0xeb9fd6fe
Network  : Ethereum Sepolia (chainId 11155111)
RPC      : https://ethereum-sepolia-rpc.publicnode.com
Result   : ChaCha20-encrypted blob containing current C2 IP

The returned data is decrypted with the hardcoded ChaCha20 key to reveal the live C2 address. At time of analysis, this resolved to 158.94.211.185 (verified via live RPC call).

DNS Tunnel (C2 Communication)

All C2 traffic is sent as raw UDP DNS queries directly to the C2 IP on port 53. Queries are structured as <encoded_data>.microsoft.com, bypassing DNS-based filtering and appearing as legitimate Windows telemetry.

  • Custom implementation: Does not use Python's socket.getaddrinfo or any DNS library
  • Opcode obfuscation: Each packet has a random XOR byte applied to the DNS opcode field
  • Encoding: Task data is base-encoded into DNS label format

Task Execution Engine

도구 다운로드