简介
在渗透测试当中经常会使用到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对象:
cpp
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
的路径, 然后添加到引用中去: