简介
在渗透测试当中经常会使用到PowerShell
来执行脚本, 但是直接使用PowerShell.exe
是一个非常敏感的行为, EDR等产品对PowerShell.exe
进程的创建监控的很密切, 并且随着PowerShell
的渗透测试工具的普及, 越来越多的EDR会利用微软提供的AMSI
接口对PS脚本进行扫描, 但是对于低版本的PowerShell
并没有引入AMSI
;
如果我们可以自己实现一个PowerShell
, 而不是去调用系统的PowerShell.exe
来执行PS脚本, 就会使得我们的行为更加的隐蔽, 甚至我们可以将自实现的PowerShell
模块注入到一个第三方进程中去(例如svchost.exe
), 可能会使行为更加隐蔽;
通过C#实现PS调用
Powershell
实际上是属于C#的子集(System.Management.Automation
), 所以实际上我们在C#中调用Powershell就是调用 System.Management.Automation对象:
using System;
using System.Reflection;
using System.Text;
using System.Management.Automation;
using System.Collections.ObjectModel;
using System.Management.Automation.Runspaces;namespace Test
{class Program{public static void Main(string[] args){InvokePS("PS> ");}public static int InvokePS(string ps){Runspace runspace = RunspaceFactory.CreateRunspace();runspace.Open();while (true){try{Console.Write(ps);string cmd = Console.ReadLine();if (cmd.Contains("exit")){break;}Pipeline pipeline = runspace.CreatePipeline();pipeline.Commands.AddScript(cmd);pipeline.Commands.Add("Out-String");Collection<PSObject> results = pipeline.Invoke();StringBuilder stringBuilder = new StringBuilder();foreach (PSObject obj in results){foreach (string line in obj.ToString().Split(new[] { "\r\n", "\r", "\n" }, StringSplitOptions.None)){stringBuilder.AppendLine(line.TrimEnd());}}Console.Write(stringBuilder.ToString());}catch (Exception e){string errorText = e.Message + "\n";Console.Write(errorText);}}return 0;}}
}
需要注意的是在引用System.Management.Automation
时, 需要手动找System.Management.Automation.dll
的路径, 然后添加到引用中去: