Delivery
The report begins with the documented delivery of the browser-wallet drainer.
Capture file origin, signing state and browser context.
Supported by review evidenceMalware Analysis / Artefact: web3-provider.js · SHA-256 b8dae0cab6e9…
An obfuscated provider, resolved string table, recipient addresses and telemetry. What the code establishes — and why this copy does not contain a complete backend.
No complete deployment or backend; no dynamic testing
The raw code tells us more than the project name. We separate the visible interface, provider call and potential effect so suspicious code does not become a premature verdict.
b8dae0cab6e95db8de1d3bb1baef189d9e4956c3ad5f83680c5b0597e255f2f4The analysis path for this report. Every node shows what is supported, where detection can start and where the claim stops.
The report begins with the documented delivery of the browser-wallet drainer.
Capture file origin, signing state and browser context.
Supported by review evidenceStatic configuration connects the interface, destination roles and runtime options.
Correlate configuration markers rather than isolated strings.
Supported by review evidenceThe logic seeks the browser context relevant to wallet interactions.
Combine process tree, extensions and profile access.
Supported by review evidenceDeceptive presentation and the technical wallet request remain separate evidence layers.
Compare UI text, provider call and transaction content.
Bounded or unresolvedA configured recipient role proves neither ownership nor a successful transfer.
Use confirmed chain events only with time and transaction context.
Bounded or unresolvedReview pivots derived from the report — not a live configuration or universal family indicator.
Source, validation and limits accompany every rule.
rules:
- id: value-ranked-wallet-transfer-review
languages: [javascript, typescript]
severity: WARNING
message: Review value-ranked assets passed to a wallet transfer operation
patterns:
- pattern-inside: |
$A.sort(($X, $Y) => $Y.amount_usd - $X.amount_usd);
...
- pattern-either:
- pattern: $W.sendTransaction(...)
- pattern: |
$W.request({method: "eth_sendTransaction", ...})
We reviewed a pinned JavaScript snapshot of the GitLab project cryptodrainexe/cryptowalletdrainer. The source dates to 23 February 2025 and the manual audit to 12 October 2026. For this account, existing files were compared statically on 13 October.
The question is what this specific copy shows about wallet behaviour, data transmission and system completeness. No Windows executable was examined, no sample executed and no endpoint contacted.
Reference: ARTIFACT-MANIFEST.md, commit 233cd4e62536170ef67ac12e3ac8f218f1d10517; behaviour assessment in AUDIT-DE.md. The hash ledger below distinguishes the original from derived artifacts.
b8dae0cab6e95db8de1d3bb1baef189d9e4956c3ad5f83680c5b0597e255f2f4Original sample
02818c11a03deb783b45f89bfbc44409ae39ad7db7bbdc16edb251e30d27f42eAnalysis output / tool
d3fa51775c324cbb750dbc3e27cb3e834a44dcd2cd23a2b64e5775a65699d230Analysis output / tool
89abae5ced4c67258d7ef4d14f53c05efa44e09ccd0a7889a183b5e917c0bcf1Analysis output / tool
The first view shows selected references in the preserved HTML package. The second separates raw file, our tool, existing derived artifacts and report. Lines represent documented file relationships, not an executed wallet or C2 chain.
File references and processing history are different relationships.
A file reference does not establish runtime behaviour. Recorded processing is not a new execution.
Selected HTML references, preserved files and missing dependencies.
Original HTML with script references.
index.html, line87: static src reference; no browser execution.
index.html, line88: static src reference; no browser execution.
index.html, line94: static src reference; no browser execution.
index.html, line97: static src reference; no browser execution.
index.html, line86: static src reference; no browser execution.
index.html, line93: static src reference; no browser execution.
Local file present; HTML references it at line87.
index.html, line87: static src reference; no browser execution.
Local file present; HTML references it at line88.
index.html, line88: static src reference; no browser execution.
Local file present; HTML references it at line94.
index.html, line94: static src reference; no browser execution.
Pinned raw code, HTML reference at line97.
index.html, line97: static src reference; no browser execution.
HTML line86 references a file outside the preserved package.
index.html, line86: static src reference; no browser execution.
HTML line93 references a file missing from the package.
index.html, line93: static src reference; no browser execution.
Historically documented processing; hashes checked read-only now.
Original bytes preserved separately.
Tool line12 reads a text file; the historical run is only documented.
Local text parser, read only in this review.
Tool line12 reads a text file; the historical run is only documented.
ARTIFACT-MANIFEST.md, Derived artifacts: decoder calls statically replaced.
Manifest lists string-table-map.json with its own hash; mapping data not published.
Existing derived artifact; contents not published.
Manifest lists string-table-map.json with its own hash; mapping data not published.
Existing artifact after static replacement.
ARTIFACT-MANIFEST.md, Derived artifacts: decoder calls statically replaced.
Manifest: Terser5.44.0 folding and formatting.
SHA-256 recalculated locally and compared with manifest.
Existing Terser processing; separate hash.
Manifest: Terser5.44.0 folding and formatting.
AUDIT-DE.md cites lines in normalized output.
SHA-256 recalculated locally and compared with manifest.
Historical counts and hashes, no rerun.
SHA-256 recalculated locally and compared with manifest.
SHA-256 recalculated locally and compared with manifest.
Interpretation and limits, separate from source code.
AUDIT-DE.md cites lines in normalized output.
Limit: Script src is an HTML reference, not proof of successful runtime initialisation. The complete original backend is unavailable. The historical transformation was not rerun.
The HTML snapshot places the project name in its title element. The browser file therefore labels itself a drainer; the name alone still does not establish behaviour. Only metadata is shown, not executable script setup.
SHA-256 fcf7097d63a47ea9b6bf14b613a34cf1199225792d75da4f647c1dd03f1b2e4c<html lang="en"><head></head><body>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>CryptoDrainEXE Multi-chain Crypto Wallet Drainer</title>
Original source-file lines. Choose a note to highlight its range.
The historical manifest records 3,295 string entries, 403 table rotations, 107 decoder aliases and 7,922 statically replaced calls. Subsequently, 1,722 string concatenations were folded and the normalized output syntax-checked with Terser 5.44.0. This work was not rerun here.
The original, decoder-replaced and normalized artifacts have different hashes. Some opaque variable names remain. The output is readable, not an executed program or verified deployment.
The short original excerpt is displayed as text only. It was located exactly in the raw file and existing normalized output. The page title supplies the name in wallet-connection metadata. This demonstrates the transformation, not the malicious functionality of the whole sample.
Source artifact · hash of the full file, not the excerpt
'name':document[_0x24d3e8(0x483)]name: document.title,Text view · no execution · original remains unchanged
The hexadecimal call conceals a property or string name here. This short excerpt stays tied to its original file and location.
The earlier decoder replacement and normalization produce document.title. The location in the derived analysis artifact is recorded separately.
The page title becomes the name in wallet-connection metadata. It is neither a recipient address nor a C2 destination.
Limit: Not a complete decoder; no claim about runtime or payment.
Normalized output shows the DOM identifiers actually used: style, div, web3-overlay and web3-modal. The comparison above establishes one string resolution; the longer genuine excerpt below shows its immediate UI context.
This is an excerpt from existing analysis output, not a rebuilt model UI. SHA-256: 02818c11a03deb783b45f89bfbc44409ae39ad7db7bbdc16edb251e30d27f42e.
Source artifact · hash of the full file, not the excerpt
'FxZSQ':_0x844b4c(0x579)FxZSQ: "style",Text view · no execution · original remains unchanged
The hexadecimal call conceals a property or string name here. This short excerpt stays tied to its original file and location.
The earlier decoder replacement and normalization produce "style". The location in the derived analysis artifact is recorded separately.
style names a DOM element. The adjacent web3-overlay and web3-modal names place the string in the interface code.
Limit: Not a complete decoder; no claim about runtime or payment.
SHA-256 02818c11a03deb783b45f89bfbc44409ae39ad7db7bbdc16edb251e30d27f42e FxZSQ: "style",
OujMT: "web3-style",
iviYd: "div",
kKYbd: "web3-overlay",
wqNjF: "none",
XEQTG: ".web3-overlay",
uoEut: "click",
luxzn: "web3-modal"
Original source-file lines. Choose a note to highlight its range.
This excerpt comes from our analysis tool, not the drainer. It validates individual escape sequences, returns a character and advances the read position. No eval, browser or network request.
It is not a complete JavaScript parser. It documents one helper step, not execution of the sample.
function decodeEscape(text, index) {
const ch = text[index];
const simple = { n: "\n", r: "\r", t: "\t", b: "\b", f: "\f", v: "\v", "0": "\0" };
if (Object.hasOwn(simple, ch)) return [simple[ch], index + 1];
if (ch === "x") {
const hex = text.slice(index + 1, index + 3);
if (!/^[0-9a-f]{2}$/i.test(hex)) throw new Error(`invalid hex escape at ${index}`);
return [String.fromCharCode(Number.parseInt(hex, 16)), index + 3];
}
if (ch === "u") {
const hex = text.slice(index + 1, index + 5);
if (!/^[0-9a-f]{4}$/i.test(hex)) throw new Error(`invalid unicode escape at ${index}`);
return [String.fromCharCode(Number.parseInt(hex, 16)), index + 5];
}
if (ch === "\n") return ["", index + 1];
if (ch === "\r" && text[index + 1] === "\n") return ["", index + 2];
return [ch, index + 1];
}
Line numbers refer to this excerpt. Choose a note to highlight its range.
This genuine tool excerpt reads characters between known quotation marks. Escapes are delegated to the separate helper. It evaluates no JavaScript; table markers and sample-specific decoder mappings are excluded.
SHA-256 89abae5ced4c67258d7ef4d14f53c05efa44e09ccd0a7889a183b5e917c0bcf1 const quote = text[i];
if (quote !== "\"" && quote !== "'") throw new Error(`unexpected token in string table at ${i}`);
i += 1;
let value = "";
while (i < text.length && text[i] !== quote) {
if (text[i] === "\\") {
const decoded = decodeEscape(text, i + 1);
value += decoded[0];
i = decoded[1];
} else {
value += text[i];
i += 1;
}
}
if (text[i] !== quote) throw new Error("unterminated string table item");
Original source-file lines. Choose a note to highlight its range.
This second tool excerpt joins recognised JSON string literals. The loop stops when no replacement occurs. It is the actual local processing step, not a rebuilt drainer model. The historical run and counts are recorded in the manifest; it was not rerun for this addition.
SHA-256 89abae5ced4c67258d7ef4d14f53c05efa44e09ccd0a7889a183b5e917c0bcf1const jsonString = '"(?:\\\\.|[^"\\\\])*"';
const concatPattern = new RegExp(`(${jsonString})\\s*\\+\\s*(${jsonString})`, "g");
let foldedConcats = 0;
while (true) {
let round = 0;
output = output.replace(concatPattern, (_full, left, right) => {
round += 1;
foldedConcats += 1;
return JSON.stringify(JSON.parse(left) + JSON.parse(right));
});
if (round === 0) break;
}
Original source-file lines. Choose a note to highlight its range.
Static analysis documents value sorting by amount_usd (line 4445) and wallet/device telemetry including IP/location data and asset inventory (1938–2258). The code therefore prioritises assets by value and transmits information about the wallet and its environment.
Manual finding CR-01 describes the harmful mismatch: the page frames the action as verification or a claim while code requests broad permissions or direct asset transfers. The wallet branches are documented at 4678–5875; permission-related findings at 3525–3832 and 4529–4677. “Verification Error” appears as UI text at line 4816. The assessment relies on paths and context, not that word alone.
Telegram is a telemetry sink here, not evidence of a complete executing C2 server.
The two configured target addresses below are separate from protocol addresses and services. Address and Receiver name the same value; chain configuration additionally specifies an execution-contract target. The manual audit statically traces the recipient/spender role into value-bearing paths.
Other wallet deep links, chain explorers, price and metadata services are referenced in the sample. They are not standalone malicious indicators. Public-IP lookup references api[.]ipify[.]org in normalized output, line 1950; the table presents representative services rather than every domain.
The two configured target addresses below are separate from protocol addresses and services. Address and Receiver name the same value; chain configuration additionally specifies an execution-contract target. The manual audit statically traces the recipient/spender role into value-bearing paths. Other wallet deep links, chain explorers, price and metadata services are referenced in the sample. They are not standalone malicious indicators. Public-IP lookup references api[.]ipify[.]org in normalized output, line 1950; the table presents representative services rather than every domain.
0x3362B269946B8B244FF50cF07cc73f133279A21E0x55775D0D339D5B4146699a04fF49feEf8bc1Cff2api[.]telegram[.]orgavatars[.]githubusercontent[.]comipapi[.]corpc[.]ankr[.]comtoys2025[.]netlify[.]app0x000000000022d473030f116ddee9f6b43ac78ba3No indicators in this category.
In this copy, send_request is a local dispatcher (lines 1795–1858), not a complete HTTP C2 client. Forwarding certain signature data to an executing server is therefore incomplete. The original server source is missing.
Telegram is documented as a telemetry service; bot tokens and chat/user identifiers remain redacted. RPC endpoints and the declared metadata domain do not establish a complete operator backend.
String tables and opaque names are ordinary obfuscation. More informative is the combination of wallet-oriented behaviour, value sorting and telemetry with incomplete dependencies and missing server source.
This explains why a readable code copy and a fully observed system are not the same. It supports no claim about market position or actual victim losses.
The Evidence Anchor at the start identifies the binary, file or revision actually used. These links provide context and reported observations; they do not substitute for local sample analysis.
The pinned code supports classification as a browser-wallet drainer. Original/analysis pairs make selected transformations checkable. Recipient roles and telemetry are statically documented; payments, account types and current operation were not verified. Missing dependencies and the local dispatcher constrain reconstruction of the whole system.
Start a conversation