EtherHiding: Fake Google Drive Offline Extension Configured On-Chain
macOS
TTP Hunt low Contagious InterviewEtherHidingClickFix
A Chrome extension named Google Drive Offline, added silently by a Node.js backdoor after a fake macOS update lure and configured from an Ethereum contract; the chain AllSecure links to UNC5342, as reported by Cyber Security News.
What this hunt looks for
In July 2026 Cyber Security News reported AllSecure research into a campaign that reaches macOS users through malvertising rather than a job lure. A fake frozen-Mac or system-update page has the victim paste into Terminal a command already on the clipboard, which installs Node.js and starts a remote-access tool that reads its command-and-control details from an Ethereum smart contract.
The tool checks in about every five minutes, runs operator JavaScript, and persists through a launch agent, a line appended to .zshrc and hidden files in cache directories. AllSecure links the methods to UNC5342 and Contagious Interview while noting that the delivery departs from that cluster's usual lures.
The chain then deploys an infostealer and silently adds a Chrome Manifest V3 extension disguised as Google Drive Offline, requesting debugging, cookie, native-messaging and all-URL access. A later write-up says it is patched into Chrome's Secure Preferences. No extension identifier is published, so the queries use the name, permissions, hashes, host signs, domains and contracts.
- Technique
- User execution through a pasted command (MITRE ATT&CK T1204.004) installing a Node.js backdoor that resolves its configuration from an Ethereum contract (T1102.001) and persists as a launch agent and a shell-profile line (T1543.001, T1546.004), followed by a malicious browser extension (T1176.001) and browser credential theft (T1555.003).
- Data sources
- Browser extension inventory, EDR process telemetry, EDR network telemetry, File-write telemetry, osquery
- Last updated
- 2026-10-04
Indicators
The atomic values this hunt matches on, listed separately from the queries so they can be lifted into tooling that speaks none of the query languages below. Every value here is reported by one of the sources cited at the foot of this page.
| Type | Value | Note |
|---|---|---|
| Extension name | Google Drive Offline |
Display name of the malicious Chrome MV3 extension (Cyber Security News, reporting AllSecure). |
| SHA256 | 370a5ae7f91291559ce514f44c50430dd2c35ed866bedcf6ac5f4f896259fbed |
Malicious Chrome MV3 extension (Cyber Security News). |
| SHA256 | 529815d365a8ec8da165f3993ada3ad452381b56c736cd25cdf328968b4ab795 |
Node.js remote-access tool, version 1.0.3 (Cyber Security News). |
| SHA256 | 7eca7aef8dcc46f15349509ac3dff8c0a71295c233787872c3842e058f9d7c50 |
Infostealer module (Cyber Security News). |
| Smart contract address | 0x85a6d913aac80286f01fa082ef0b96c188673043 |
Ethereum contract holding the extension's configuration (Cyber Security News). Lower-cased here; the report prints the checksummed form. |
| Smart contract address | 0x2aca749b59529f5cbcd6fbd34b35b1a546713df6 |
Ethereum contract holding the backdoor's configuration (Cyber Security News). |
| Function selector | 0x3bc5de30 |
Getter the malware calls on the contracts (Cyber Security News). |
| Domain | real-tumble.pro |
Stage 0 delivery domain (Cyber Security News). |
| URL | https://th-updates.sbs/analytics |
Extension C2 (Cyber Security News). |
| URL | https://rg-telemetry.sbs/api |
Backdoor C2 (Cyber Security News). |
| URL | https://eth-mainnet.rpcfast.com/?apikey=xbhWBI1Wkguk8SNMu1bvvLurPGLXmgwYeC4S6g2H7WdwFigZSmPWVZRxrskEQwIf |
Operator's hard-coded RPC endpoint and API key (Cyber Security News). The host is a legitimate RPC service; the key is the indicator. |
| XOR key | 9f10d0899beff7952f586a49305f8b14, 2752df77aeb348657f5fb59a22d65f4a |
C2 traffic keys (Cyber Security News). |
| Wallet address | 0x277765fb63601ce5a9814daf68aa2a57f54ea968, 0x89c5151236de544d077fc69813a4db89224ee8a1 |
Attacker funder wallets (Cyber Security News). |
| Wallet address | 0xdf16a4d0a234a2bbc4d21645d4c7a19d2db8f192, 0x75ac1ebf164c6f2ac24e73bb4c9518b8d93559e2 |
Attacker treasury hubs (Cyber Security News). |
| File path (macOS) | ~/Library/LaunchAgents/, ~/Library/Caches/, ~/.zshrc |
Locations of the persistence artefacts: a launch agent named com.<random>.plist, a random directory under Library/Caches, a /tmp lock file and a line appended to .zshrc (Cyber Security News). The report names no file, so the queries match writes to these locations by node or a shell. |
| Behaviour | NODE_TLS_REJECT_UNAUTHORIZED=0; Node.js running from Library/Caches |
Behavioural detection indicators listed in the report (Cyber Security News). |
Logic
Every query below implements these steps, so the same hunt returns the same result in each product.
- Collect: process, file and network events on macOS endpoints, plus Chrome extension and launchd state through osquery
- Match: node runs from Library/Caches or with NODE_TLS_REJECT_UNAUTHORIZED=0, or an extension is named Google Drive Offline (osquery)
- Match: or real-tumble.pro, th-updates.sbs or rg-telemetry.sbs is reached, or a reported contract, wallet or key is in a URL or command
- Match: or, lower fidelity: node or a shell writes a launch agent or .zshrc, a reported hash is seen, or the RPC host is reached
- Match: or, lower fidelity: a process other than Chrome writes Chrome's Secure Preferences file (extension sideload)
- Report: Macs with the signal kinds hit, most kinds first
Queries
Defender / Sentinel KQL
Written for this site, from indicators reported by Cyber Security News (AllSecure)Node running from a cache directory or the campaign hosts and identifiers are the strong signals, and persistence or hash hits alone need the process behind them read.
union
// optional: lower fidelity, only a secondary report states that the extension is patched into Secure Preferences and Chrome helper process names vary; delete this line and the branch below it
(DeviceFileEvents
| where Timestamp > ago(30d) and ActionType in ("FileCreated", "FileModified", "FileRenamed")
| where FileName =~ "Secure Preferences" and not(InitiatingProcessFileName startswith "Google Chrome")
| project Timestamp, DeviceId, DeviceName, Signal = "extension sideload", Detail = strcat(FolderPath, "/", FileName, " by ", InitiatingProcessFileName)),
// optional: lower fidelity, the report names no file for the launch agent or the .zshrc line, so legitimate installers and developer tools also match; delete this line and the branch below it
(DeviceFileEvents
| where Timestamp > ago(30d) and ActionType in ("FileCreated", "FileModified", "FileRenamed")
| where InitiatingProcessFileName in~ ("node", "sh", "bash", "zsh", "curl")
| where FolderPath contains "/Library/LaunchAgents" or FileName =~ ".zshrc"
| project Timestamp, DeviceId, DeviceName, Signal = "persistence", Detail = strcat(FolderPath, "/", FileName, " by ", InitiatingProcessFileName)),
// optional: lower fidelity, the three hashes are single builds and a rebuild changes them; delete this line and the branch below it
(DeviceFileEvents
| where Timestamp > ago(90d) and SHA256 in ("370a5ae7f91291559ce514f44c50430dd2c35ed866bedcf6ac5f4f896259fbed", "529815d365a8ec8da165f3993ada3ad452381b56c736cd25cdf328968b4ab795", "7eca7aef8dcc46f15349509ac3dff8c0a71295c233787872c3842e058f9d7c50")
| project Timestamp, DeviceId, DeviceName, Signal = "reported hash", Detail = strcat(FolderPath, "/", FileName)),
(DeviceNetworkEvents
| where Timestamp > ago(90d)
| where RemoteUrl has_any ("real-tumble.pro", "th-updates.sbs", "rg-telemetry.sbs") or RemoteUrl has_any ("0x85a6d913aac80286f01fa082ef0b96c188673043", "0x2aca749b59529f5cbcd6fbd34b35b1a546713df6", "0x3bc5de30", "0x277765fb63601ce5a9814daf68aa2a57f54ea968", "0x89c5151236de544d077fc69813a4db89224ee8a1", "0xdf16a4d0a234a2bbc4d21645d4c7a19d2db8f192", "0x75ac1ebf164c6f2ac24e73bb4c9518b8d93559e2", "xbhWBI1Wkguk8SNMu1bvvLurPGLXmgwYeC4S6g2H7WdwFigZSmPWVZRxrskEQwIf")
// optional: lower fidelity, eth-mainnet.rpcfast.com is a legitimate RPC service and only the API key is the indicator; delete this line and the next
or RemoteUrl has "eth-mainnet.rpcfast.com"
| project Timestamp, DeviceId, DeviceName, Signal = "network", Detail = strcat(InitiatingProcessFileName, " -> ", RemoteUrl)),
(DeviceProcessEvents
| where Timestamp > ago(30d)
| where (FileName =~ "node" and (FolderPath contains "/Library/Caches/" or ProcessCommandLine contains "/Library/Caches/"))
or ProcessCommandLine contains "NODE_TLS_REJECT_UNAUTHORIZED=0"
or ProcessCommandLine has_any ("0x85a6d913aac80286f01fa082ef0b96c188673043", "0x2aca749b59529f5cbcd6fbd34b35b1a546713df6", "0x3bc5de30", "0x277765fb63601ce5a9814daf68aa2a57f54ea968", "0x89c5151236de544d077fc69813a4db89224ee8a1", "0xdf16a4d0a234a2bbc4d21645d4c7a19d2db8f192", "0x75ac1ebf164c6f2ac24e73bb4c9518b8d93559e2", "xbhWBI1Wkguk8SNMu1bvvLurPGLXmgwYeC4S6g2H7WdwFigZSmPWVZRxrskEQwIf")
| project Timestamp, DeviceId, DeviceName, Signal = "process", Detail = ProcessCommandLine)
| summarize Hits = count(), Signals = make_set(Signal), FirstSeen = min(Timestamp), LastSeen = max(Timestamp), Details = make_set(Detail, 5) by DeviceId, DeviceName
| order by array_length(Signals) desc, LastSeen desc
Lower-fidelity parts (4)
- the launch agent and .zshrc write match — the report names no file for either, so legitimate installers and developer tools also match. Remove: delete the // optional: comment line and the (DeviceFileEvents ...) branch beneath it
- the three reported SHA256 hashes — each is a single build and a rebuild changes it. Remove: delete the // optional: comment line and the (DeviceFileEvents ...) branch beneath it
- the eth-mainnet.rpcfast.com host match — it is a legitimate RPC service and only the API key is the indicator. Remove: delete the // optional: comment line and the line beneath it
- the Chrome Secure Preferences write by a non-Chrome process — only a secondary report states it, and Chrome helper process names vary. Remove: delete the // optional: comment line and the (DeviceFileEvents ...) branch beneath it
Splunk SPL
Written for this site, from indicators reported by Cyber Security News (AllSecure)The same process, persistence, hash and network signals over the Endpoint data model and proxy logs.
```Placeholders: the Endpoint data model carries macOS process and file events; index=proxy is the proxy log.```
| tstats count max(_time) AS _time FROM datamodel=Endpoint.Processes WHERE earliest=-30d
((Processes.process_name="node" AND Processes.process="*/Library/Caches/*") OR Processes.process="*NODE_TLS_REJECT_UNAUTHORIZED=0*" OR Processes.process="*0x85a6d913aac80286f01fa082ef0b96c188673043*" OR Processes.process="*0x2aca749b59529f5cbcd6fbd34b35b1a546713df6*" OR Processes.process="*0x3bc5de30*" OR Processes.process="*0x277765fb63601ce5a9814daf68aa2a57f54ea968*" OR Processes.process="*0x89c5151236de544d077fc69813a4db89224ee8a1*" OR Processes.process="*0xdf16a4d0a234a2bbc4d21645d4c7a19d2db8f192*" OR Processes.process="*0x75ac1ebf164c6f2ac24e73bb4c9518b8d93559e2*" OR Processes.process="*xbhWBI1Wkguk8SNMu1bvvLurPGLXmgwYeC4S6g2H7WdwFigZSmPWVZRxrskEQwIf*")
BY Processes.dest, Processes.process
| rename Processes.dest AS host, Processes.process AS detail
| eval signal="process"
```optional: lower fidelity, the report names no file for the launch agent or the .zshrc line, so legitimate installers and developer tools also match; delete this line and the append block below it```
| append
[| tstats count max(_time) AS _time FROM datamodel=Endpoint.Filesystem WHERE earliest=-30d (Filesystem.file_path="*/Library/LaunchAgents/*" OR Filesystem.file_name=".zshrc") Filesystem.process_name IN ("node","sh","bash","zsh","curl") BY Filesystem.dest, Filesystem.file_path
| rename Filesystem.dest AS host, Filesystem.file_path AS detail
| eval signal="persistence"]
```optional: lower fidelity, only a secondary report states that the extension is patched into Secure Preferences and Chrome helper process names vary; delete this line and the append block below it```
| append
[| tstats count max(_time) AS _time FROM datamodel=Endpoint.Filesystem WHERE earliest=-30d Filesystem.file_name="Secure Preferences" NOT Filesystem.process_name="Google Chrome*" BY Filesystem.dest, Filesystem.process_name
| rename Filesystem.dest AS host, Filesystem.process_name AS detail
| eval signal="extension sideload"]
```optional: lower fidelity, the three hashes are single builds and a rebuild changes them; delete this line and the append block below it```
| append
[search index=endpoint earliest=-90d file_hash IN ("370a5ae7f91291559ce514f44c50430dd2c35ed866bedcf6ac5f4f896259fbed", "529815d365a8ec8da165f3993ada3ad452381b56c736cd25cdf328968b4ab795", "7eca7aef8dcc46f15349509ac3dff8c0a71295c233787872c3842e058f9d7c50")
| stats count max(_time) AS _time values(file_path) AS details BY host
| eval signal="reported hash"]
| append
[search index=proxy earliest=-90d (url="*real-tumble.pro*" OR url="*th-updates.sbs*" OR url="*rg-telemetry.sbs*" OR url="*0x85a6d913aac80286f01fa082ef0b96c188673043*" OR url="*0x2aca749b59529f5cbcd6fbd34b35b1a546713df6*" OR url="*0x3bc5de30*" OR url="*0x277765fb63601ce5a9814daf68aa2a57f54ea968*" OR url="*0x89c5151236de544d077fc69813a4db89224ee8a1*" OR url="*0xdf16a4d0a234a2bbc4d21645d4c7a19d2db8f192*" OR url="*0x75ac1ebf164c6f2ac24e73bb4c9518b8d93559e2*" OR url="*xbhWBI1Wkguk8SNMu1bvvLurPGLXmgwYeC4S6g2H7WdwFigZSmPWVZRxrskEQwIf*"
```optional: lower fidelity, eth-mainnet.rpcfast.com is a legitimate RPC service and only the API key is the indicator; delete this line and the next```
OR url="*eth-mainnet.rpcfast.com*"
)
| stats count max(_time) AS _time values(url) AS details BY src
| eval host=src, signal="network"]
| stats sum(count) AS hits min(_time) AS first_seen max(_time) AS last_seen values(signal) AS signals values(detail) AS details BY host
| eval signal_count=mvcount(signals)
| convert ctime(first_seen) ctime(last_seen)
| sort - signal_count, - last_seen
Lower-fidelity parts (4)
- the launch agent and .zshrc write match — the report names no file for either, so legitimate installers and developer tools also match. Remove: delete the optional comment line and the append block beneath it
- the three reported SHA256 hashes — each is a single build and a rebuild changes it. Remove: delete the optional comment line and the append block beneath it
- the eth-mainnet.rpcfast.com host match — it is a legitimate RPC service and only the API key is the indicator. Remove: delete the optional comment line and the line beneath it
- the Chrome Secure Preferences write by a non-Chrome process — only a secondary report states it, and Chrome helper process names vary. Remove: delete the optional comment line and the append block beneath it
Sigma
Written for this site, from indicators reported by Cyber Security News (AllSecure)Three rules that apply to macOS process, file and DNS telemetry.
title: Node.js Backdoor Host Signs from the Fake Google Drive Offline Campaign
id: c0cb412a-0787-4f1b-a518-3744c0349f82
status: experimental
description: >
Detects the node binary executing from a Library/Caches directory, a
command line that disables Node.js certificate checking, or one of the
contract, wallet or API-key identifiers AllSecure lists for the Node.js
backdoor that reads its configuration from an Ethereum contract.
references:
- https://cybersecuritynews.com/north-korean-etherhiding-campaign/
logsource:
category: process_creation
detection:
sel_node:
Image|endswith: '/node'
sel_cache:
Image|contains: '/Library/Caches/'
selection_tls:
CommandLine|contains: 'NODE_TLS_REJECT_UNAUTHORIZED=0'
selection_ids:
CommandLine|contains:
- '0x85a6d913aac80286f01fa082ef0b96c188673043'
- '0x2aca749b59529f5cbcd6fbd34b35b1a546713df6'
- '0x3bc5de30'
- '0x277765fb63601ce5a9814daf68aa2a57f54ea968'
- '0x89c5151236de544d077fc69813a4db89224ee8a1'
- '0xdf16a4d0a234a2bbc4d21645d4c7a19d2db8f192'
- '0x75ac1ebf164c6f2ac24e73bb4c9518b8d93559e2'
- 'xbhWBI1Wkguk8SNMu1bvvLurPGLXmgwYeC4S6g2H7WdwFigZSmPWVZRxrskEQwIf'
# optional: lower fidelity, the three hashes are single builds and a rebuild changes them; delete this line and the selection below it
selection_hash:
Hashes|contains:
- 'SHA256=370a5ae7f91291559ce514f44c50430dd2c35ed866bedcf6ac5f4f896259fbed'
- 'SHA256=529815d365a8ec8da165f3993ada3ad452381b56c736cd25cdf328968b4ab795'
- 'SHA256=7eca7aef8dcc46f15349509ac3dff8c0a71295c233787872c3842e058f9d7c50'
condition: (sel_node and sel_cache) or 1 of selection_*
falsepositives:
- Developer tooling that caches its own Node.js runtime under Library/Caches, and developers who disable certificate checking for a local test
level: high
---
title: Node.js or Shell Writing a Launch Agent or Shell Profile on macOS
id: c0cb412a-0787-4f1b-a518-3744c0349f83
status: experimental
description: >
Detects node, a shell or curl writing a launch agent or .zshrc, the
persistence AllSecure describes for the Node.js backdoor.
references:
- https://cybersecuritynews.com/north-korean-etherhiding-campaign/
logsource:
category: file_event
detection:
sel_writer:
Image|endswith:
- '/node'
- '/sh'
- '/bash'
- '/zsh'
- '/curl'
sel_target:
TargetFilename|contains: '/Library/LaunchAgents/'
sel_profile:
TargetFilename|endswith: '/.zshrc'
condition: sel_writer and (sel_target or sel_profile)
falsepositives:
- Legitimate installers and developer tools that write launch agents or edit .zshrc from a shell
level: low
---
title: Lookup of the Fake Google Drive Offline Campaign Infrastructure
id: cab30928-411d-4f1f-9d4c-06c3e17952a2
status: experimental
description: >
Detects lookups and web requests for the delivery domain and the two
command-and-control hosts Cyber Security News lists for the EtherHiding
campaign that installs a malicious Chrome extension named Google Drive
Offline.
references:
- https://cybersecuritynews.com/north-korean-etherhiding-campaign/
logsource:
category: dns_query
detection:
selection_exact:
QueryName:
- 'real-tumble.pro'
- 'th-updates.sbs'
- 'rg-telemetry.sbs'
selection_sub:
QueryName|endswith:
- '.real-tumble.pro'
- '.th-updates.sbs'
- '.rg-telemetry.sbs'
condition: 1 of selection_*
level: high
---
# optional: lower fidelity, only a secondary report states that the extension is patched into Secure Preferences and Chrome helper process names vary; delete this line and every document below it
title: Chrome Secure Preferences Written by a Non-Chrome Process
id: c0cb412a-0787-4f1b-a518-3744c0349f84
status: experimental
description: >
Detects a process other than Chrome writing Chrome's Secure Preferences
file, the way the sideloaded Google Drive Offline extension is reported to
be planted.
references:
- https://aviatrix.ai/threat-research-center/dprk-linked-macos-malvertising-uses-fake-updates-to-deliver-crypto-stealing-malware/
logsource:
category: file_event
detection:
selection:
TargetFilename|endswith: '/Secure Preferences'
filter_chrome:
Image|contains: 'Google Chrome'
condition: selection and not filter_chrome
falsepositives:
- Browser management tools that edit Chrome profile preferences
level: medium
Lower-fidelity parts (3)
- the three reported SHA256 hashes — each is a single build and a rebuild changes it. Remove: delete the # optional: comment line and the selection_hash block beneath it
- the launch agent and .zshrc write match — the report names no file for either, so legitimate installers and developer tools also match. Remove: delete the whole second document, the one titled Node.js or Shell Writing a Launch Agent or Shell Profile on macOS, with its --- separator
- the Chrome Secure Preferences write by a non-Chrome process — only a secondary report states it, and Chrome helper process names vary. Remove: delete the # optional: comment line and the document beneath it
CrowdStrike LogScale
Written for this site, from indicators reported by Cyber Security News (AllSecure)The process, identifier, DNS and hash signals over Falcon events on macOS; Falcon file-write events are not used, so persistence is left to the osquery query.
event_platform=Mac
| (#event_simpleName=/^(ProcessRollup2|SyntheticProcessRollup2)$/ ((FileName=node ImageFileName=/\/Library\/Caches\//) or CommandLine=/(NODE_TLS_REJECT_UNAUTHORIZED=0|0x85a6d913aac80286f01fa082ef0b96c188673043|0x2aca749b59529f5cbcd6fbd34b35b1a546713df6|0x3bc5de30|0x277765fb63601ce5a9814daf68aa2a57f54ea968|0x89c5151236de544d077fc69813a4db89224ee8a1|0xdf16a4d0a234a2bbc4d21645d4c7a19d2db8f192|0x75ac1ebf164c6f2ac24e73bb4c9518b8d93559e2|xbhWBI1Wkguk8SNMu1bvvLurPGLXmgwYeC4S6g2H7WdwFigZSmPWVZRxrskEQwIf)/i))
or (#event_simpleName=DnsRequest DomainName=/(^|\.)(real-tumble\.pro|th-updates\.sbs|rg-telemetry\.sbs)$/i)
// optional: lower fidelity, the three hashes are single builds and a rebuild changes them; delete this line and the next
or (#event_simpleName=/^(ProcessRollup2|SyntheticProcessRollup2)$/ in(SHA256HashData, values=["370a5ae7f91291559ce514f44c50430dd2c35ed866bedcf6ac5f4f896259fbed", "529815d365a8ec8da165f3993ada3ad452381b56c736cd25cdf328968b4ab795", "7eca7aef8dcc46f15349509ac3dff8c0a71295c233787872c3842e058f9d7c50"]))
| groupBy([aid, ComputerName], function=[count(as=Hits), count(#event_simpleName, distinct=true, as=SignalKinds), collect([#event_simpleName]), min(@timestamp, as=FirstSeen), max(@timestamp, as=LastSeen)])
| sort(SignalKinds, order=desc)
Lower-fidelity parts (1)
- the three reported SHA256 hashes — each is a single build and a rebuild changes it. Remove: delete the // optional: comment line and the line beneath it
Elastic
Written for this site, from indicators reported by Cyber Security News (AllSecure)The same process, DNS, persistence, hash and RPC-host signals over Elastic Defend events from macOS hosts.
FROM logs-endpoint.events.*
| WHERE host.os.type == "macos"
| EVAL cmd = TO_LOWER(process.command_line), exe = TO_LOWER(process.executable), path = TO_LOWER(file.path), name = TO_LOWER(COALESCE(dns.question.name, destination.domain))
| WHERE (TO_LOWER(process.name) == "node" AND exe RLIKE ".*/library/caches/.*")
OR cmd RLIKE ".*(node_tls_reject_unauthorized=0|0x85a6d913aac80286f01fa082ef0b96c188673043|0x2aca749b59529f5cbcd6fbd34b35b1a546713df6|0x3bc5de30|0x277765fb63601ce5a9814daf68aa2a57f54ea968|0x89c5151236de544d077fc69813a4db89224ee8a1|0xdf16a4d0a234a2bbc4d21645d4c7a19d2db8f192|0x75ac1ebf164c6f2ac24e73bb4c9518b8d93559e2|xbhWBI1Wkguk8SNMu1bvvLurPGLXmgwYeC4S6g2H7WdwFigZSmPWVZRxrskEQwIf).*"
OR name RLIKE "(.*\\.)?(real-tumble\\.pro|th-updates\\.sbs|rg-telemetry\\.sbs)"
OR (TO_LOWER(process.name) IN ("node", "sh", "bash", "zsh", "curl") AND (path RLIKE ".*/library/launchagents/.*" OR TO_LOWER(file.name) == ".zshrc"))
OR (path RLIKE ".*/secure preferences" AND NOT TO_LOWER(process.name) RLIKE "google chrome.*")
OR file.hash.sha256 IN ("370a5ae7f91291559ce514f44c50430dd2c35ed866bedcf6ac5f4f896259fbed", "529815d365a8ec8da165f3993ada3ad452381b56c736cd25cdf328968b4ab795", "7eca7aef8dcc46f15349509ac3dff8c0a71295c233787872c3842e058f9d7c50")
OR process.hash.sha256 IN ("370a5ae7f91291559ce514f44c50430dd2c35ed866bedcf6ac5f4f896259fbed", "529815d365a8ec8da165f3993ada3ad452381b56c736cd25cdf328968b4ab795", "7eca7aef8dcc46f15349509ac3dff8c0a71295c233787872c3842e058f9d7c50")
OR name == "eth-mainnet.rpcfast.com"
| EVAL signal = CASE(file.path IS NOT NULL, "file", process.command_line IS NOT NULL, "process", "network")
| STATS hits = COUNT(*), signal_kinds = COUNT_DISTINCT(signal), signals = VALUES(signal), last_seen = MAX(@timestamp) BY host.name
| SORT signal_kinds DESC, last_seen DESC
Lower-fidelity parts (4)
- the launch agent and .zshrc write match — the report names no file for either, so legitimate installers and developer tools also match. Remove: delete the OR line beginning (TO_LOWER(process.name) IN ("node", "sh"
- the three reported SHA256 hashes — each is a single build and a rebuild changes it. Remove: delete the two OR lines ending in file.hash.sha256 IN and process.hash.sha256 IN
- the eth-mainnet.rpcfast.com host match — it is a legitimate RPC service and only the API key is the indicator. Remove: delete the final OR line, name == "eth-mainnet.rpcfast.com"
- the Chrome Secure Preferences write by a non-Chrome process — only a secondary report states it, and Chrome helper process names vary. Remove: delete the OR line beginning (path RLIKE ".*/secure preferences"
Cortex XQL
Written for this site, from indicators reported by Cyber Security News (AllSecure)The same process, network, persistence and hash signals over Cortex events from macOS agents.
dataset = xdr_data
| filter agent_os_type = ENUM.AGENT_OS_MAC
| alter host = lowercase(coalesce(dns_query_name, action_external_hostname, ""))
| filter (event_type = ENUM.PROCESS and ((lowercase(action_process_image_name) = "node" and lowercase(action_process_image_path) ~= "/library/caches/") or lowercase(action_process_image_command_line) ~= "node_tls_reject_unauthorized=0|(0x85a6d913aac80286f01fa082ef0b96c188673043|0x2aca749b59529f5cbcd6fbd34b35b1a546713df6|0x3bc5de30|0x277765fb63601ce5a9814daf68aa2a57f54ea968|0x89c5151236de544d077fc69813a4db89224ee8a1|0xdf16a4d0a234a2bbc4d21645d4c7a19d2db8f192|0x75ac1ebf164c6f2ac24e73bb4c9518b8d93559e2|xbhWBI1Wkguk8SNMu1bvvLurPGLXmgwYeC4S6g2H7WdwFigZSmPWVZRxrskEQwIf)"))
or (event_type = ENUM.NETWORK and host ~= "(^|[.])(real-tumble[.]pro|th-updates[.]sbs|rg-telemetry[.]sbs)$")
// optional: lower fidelity, eth-mainnet.rpcfast.com is a legitimate RPC service and only the API key is the indicator; delete this line and the next
or (event_type = ENUM.NETWORK and host = "eth-mainnet.rpcfast.com")
// optional: lower fidelity, the report names no file for the launch agent or the .zshrc line, so legitimate installers and developer tools also match; delete this line and the next
or (event_type = ENUM.FILE and lowercase(actor_process_image_name) in ("node", "sh", "bash", "zsh", "curl") and (lowercase(action_file_path) ~= "/library/launchagents/" or lowercase(action_file_name) = ".zshrc"))
// optional: lower fidelity, only a secondary report states that the extension is patched into Secure Preferences and Chrome helper process names vary; delete this line and the next
or (event_type = ENUM.FILE and lowercase(action_file_name) = "secure preferences" and lowercase(actor_process_image_name) !~= "google chrome")
// optional: lower fidelity, the three hashes are single builds and a rebuild changes them; delete this line and the next
or action_file_sha256 in ("370a5ae7f91291559ce514f44c50430dd2c35ed866bedcf6ac5f4f896259fbed", "529815d365a8ec8da165f3993ada3ad452381b56c736cd25cdf328968b4ab795", "7eca7aef8dcc46f15349509ac3dff8c0a71295c233787872c3842e058f9d7c50") or action_process_image_sha256 in ("370a5ae7f91291559ce514f44c50430dd2c35ed866bedcf6ac5f4f896259fbed", "529815d365a8ec8da165f3993ada3ad452381b56c736cd25cdf328968b4ab795", "7eca7aef8dcc46f15349509ac3dff8c0a71295c233787872c3842e058f9d7c50")
| comp count() as hits, count_distinct(event_type) as signal_kinds, max(_time) as last_seen by agent_hostname
| sort desc signal_kinds, desc last_seen
Lower-fidelity parts (4)
- the eth-mainnet.rpcfast.com host match — it is a legitimate RPC service and only the API key is the indicator. Remove: delete the // optional: comment line and the line beneath it
- the launch agent and .zshrc write match — the report names no file for either, so legitimate installers and developer tools also match. Remove: delete the // optional: comment line and the line beneath it
- the Chrome Secure Preferences write by a non-Chrome process — only a secondary report states it, and Chrome helper process names vary. Remove: delete the // optional: comment line and the line beneath it
- the three reported SHA256 hashes — each is a single build and a rebuild changes it. Remove: delete the // optional: comment line and the line beneath it
osquery
Written for this site, from indicators reported by Cyber Security News (AllSecure)A point-in-time check of the extension, running node, its environment and launch agents on the Mac in hand.
SELECT 'extension' AS signal, ce.name AS item, ce.identifier || ' ' || ce.path AS detail
FROM users u CROSS JOIN chrome_extensions ce USING (uid)
WHERE ce.name LIKE '%Drive Offline%'
-- optional: lower fidelity, legitimate developer and automation extensions also request these permissions; delete this line and the three below it
OR (ce.permissions LIKE '%debugger%'
AND ce.permissions LIKE '%nativeMessaging%'
AND ce.permissions LIKE '%cookies%')
UNION ALL
SELECT 'node from cache', name, path || ' ' || cmdline
FROM processes
WHERE name = 'node' AND (path LIKE '%/Library/Caches/%' OR cwd LIKE '%/Library/Caches/%' OR cmdline LIKE '%/Library/Caches/%')
UNION ALL
SELECT 'certificate checking disabled', p.name, p.cmdline
FROM processes p JOIN process_envs e USING (pid)
WHERE p.name = 'node' AND e.key = 'NODE_TLS_REJECT_UNAUTHORIZED' AND e.value = '0'
UNION ALL
SELECT 'launch agent', path, COALESCE(program, '') || ' ' || COALESCE(program_arguments, '')
FROM launchd
WHERE path LIKE '%/Library/LaunchAgents/%' AND (program LIKE '%/Library/Caches/%' OR program_arguments LIKE '%/Library/Caches/%');
Lower-fidelity parts (1)
- the debugger, nativeMessaging and cookies permission combination — legitimate developer and automation extensions also request these permissions. Remove: delete the -- optional: comment line and the three lines beneath it, keeping the WHERE name match
YARA
Written for this site, from indicators reported by Cyber Security News (AllSecure)Content rules for the malicious Manifest V3 extension and for configuration strings the report lists.
rule EtherHiding_Fake_Google_Drive_Offline_Manifest
{
meta:
description = "Chrome MV3 manifest named Google Drive Offline requesting debugger, native messaging, cookie and all-URL access"
reference = "https://cybersecuritynews.com/north-korean-etherhiding-campaign/"
strings:
$name = "Google Drive Offline"
$mv3 = /"manifest_version"\s*:\s*3/
$p_debugger = "\"debugger\""
$p_native = "\"nativeMessaging\""
$p_cookies = "\"cookies\""
$p_all = "<all_urls>"
$msg = "__MSG_appName__"
condition:
filesize < 64KB and $mv3 and
(
($name and 3 of ($p_*)) or
($msg and all of ($p_*))
)
}
// optional: lower fidelity, the report does not say these strings appear as literals in the file; delete this line and the rule below it
rule EtherHiding_Fake_Google_Drive_Offline_Config_Strings
{
meta:
description = "Configuration strings reported for the Node.js backdoor and extension that read their configuration from an Ethereum contract"
reference = "https://cybersecuritynews.com/north-korean-etherhiding-campaign/"
strings:
$contract1 = "0x85a6d913aac80286f01fa082ef0b96c188673043" nocase
$contract2 = "0x2aca749b59529f5cbcd6fbd34b35b1a546713df6" nocase
$xor1 = "9f10d0899beff7952f586a49305f8b14"
$xor2 = "2752df77aeb348657f5fb59a22d65f4a"
$c2_ext = "th-updates.sbs/analytics"
$c2_bd = "rg-telemetry.sbs/api"
$rpckey = "xbhWBI1Wkguk8SNMu1bvvLurPGLXmgwYeC4S6g2H7WdwFigZSmPWVZRxrskEQwIf"
condition:
filesize < 5MB and any of ($contract*, $xor*, $c2_*, $rpckey)
}
Lower-fidelity parts (1)
- the configuration-strings rule — the report does not say the contracts, XOR keys, URLs and API key appear as literals in the file. Remove: delete the // optional: comment line and the EtherHiding_Fake_Google_Drive_Offline_Config_Strings rule beneath it
False positives and tuning
All of this page rests on one secondary report relaying AllSecure's research, with no primary publication, so the attribution is relayed and confidence is low; no contract or wallet has been read on-chain here.
The display name is the weakest match, since an extension can be renamed, and the permission branch of the osquery query also returns legitimate developer and automation extensions; read each identifier and install path.
Developer tools may keep Node.js under Library/Caches or start node with certificate checking disabled; the host signs are strongest together, or alongside a new launch agent and a changed .zshrc.
The persistence query will also match legitimate installers writing launch agents from a shell.
Sources
- North Korean EtherHiding Campaign Targets Crypto Wallets and Developer Credentials — Cyber Security News, 2026-07-31
- DPRK-Linked macOS Malvertising Uses Fake Updates to Deliver Crypto-Stealing Malware — Aviatrix Threat Research Center, 2026