從PowerShell內存轉儲中提取執行的腳本內容
上次發布從PowerShell流程轉儲中提取活動歷史記錄之後,我又想到了一個有趣的問題:「是否可以提取已執行的腳本(來自磁碟)的內容,即使這些文件未被捕獲?」,我得到答案是「是」,但是它也很複雜。這將需要大量的WinDbg自動化工作,因此第一步,安裝WinDbg模塊。
我們先創建一個簡單的腳本。
打開PowerShell會話,運行腳本,然後創建轉儲文件。
現在,使用WinDbg模塊連接到轉儲文件:
Connect-DbgSession -ArgumentList "-z "C:UsersleeAppDataLocalTemppowershell.DMP""
開始
我們想要提取表示在該會話中運行的腳本的對象(如果存在)。但我們如何找到這些呢?
首先,讓我們使用SOS的「轉儲對象」命令來轉儲它知道的關於進程中每個對象的所有內容。因此,我們將從!DumpHeap
命令開始查找所有對象實例(即:我們甚至不使用-Type過濾器)。但還有其他方法可以做到這一點,但這一步和下一步將需要很長時間。
$allReferences = dbg !dumpheap -short
一旦我們擁有所有對象引用,讓我們使用!do
(轉儲對象命令)讓SOS將它們全部可視化。轉儲對象的輸出不包括被轉儲對象的地址,因此我們也將使用Add-Member來跟蹤它。
$ allObjects = $ allReferences | Foreach-Object {$ object = dbg「!do $ 」; Add-Member -InputObject $ object Address $ -PassThru -Force}
SOS在此流程實例中知道大約有一百萬個對象。但是他們中的任何一個GUID都會被SOS可視化嗎?
看起來我們很幸運!在這些百萬個對象中,我們設法將其縮小到PowerShell內存中的7個System.String對象,這些對象以某種方式引用了GUID。如果我們認為信息可能一直在System.String中,我們可以使用「$allReferences = dbg !dumpheap –type System.String –short」
使我們的初始「$ allObjects」
查詢更快。但是我們如何弄清楚這些GUID的是什麼?
為了找到
答案
,我們將使用SOS的!gcroot
命令。這通常用於診斷託管內存泄漏 ,!gcroot
命令會告訴您引用它的對象以及引用該對象的對象 - 一直到達對象的根目錄。讓我們探討一下這些根源。第5項根植於對象數組(System.Object[]),其中一個元素是ConcurrentDictionary
,它包含一個ScriptBlock
,它又包含CompiledScriptBlockData
,其中包含PowerShell AST中的節點,在引用這個GUID的命令AST中觸底。
這是我實例中的第4項:
這是有趣的!這個開頭是相同的根對象數組(0000026e101e9a40),相同的ConcurrentDictionary(0000026e003bc440),但這次最後是一個包含我們的字元串和另一個字元串的元組(兩個項目的簡單配對)。讓我們深入了解那個元組及其包含的字元串。
所以這個元組有兩個元素。第一個元素看起來是執行腳本的路徑,第二個元素看起來是該腳本中的內容。讓我們看看PowerShell Source對這些數據結構。我將搜索ConcurrentDictionary以查看我能找到的內容。在第三頁,我們可以看到我們正在查看的內容:
有一個名為CompiledScriptBlock
的類。它包含一個名為「s_cachedScripts」
的靜態(進程範圍)緩存。這是一個將一對字元串映射到ScriptBlock實例的字典。如果您閱讀了源代碼,您可以確切地看到Tuple的內容 - 腳本路徑到ScriptBlock緩存時包含的內容的映射:
這個數據結構是我們最終討論的內容。出於性能原因,PowerShell維護一個內部腳本塊緩存,這樣每次看到腳本時都不需要重新編譯腳本塊。該緩存是路徑和腳本內容的關鍵。存儲在緩存中的東西是ScriptBlock類的一個實例,它包含(除此之外)編譯的腳本的AST。
所以現在我們知道這個東西存在了,我們可以在自動化中更智能,並提取這些東西!現在我們需要一個真正的腳本,這就是我們要做的:
1. 使用
!dumpheap
查找此Tuple類的實例。dumpheap命令執行子字元串搜索,因此我們將使用正則表達式進行一些後處理。2. 這給了我們實際想要研究的元組類的MT。
3. 使用該MT作為過濾器再次運行!dumpheap
現在我們可以探索其中一個節點。它有一個m_key
,我們可以深入研究。
差不多了!讓我們從那些結果鍵中提取出兩個項目,然後生成一個漂亮的PowerShell對象:
這是一個將所有這些打包成函數的腳本.
function Get-ScriptBlockCache{ $nodeType = dbg !dumpheap -type ConcurrentDictionary | Select-String "ConcurrentDictionary.Node.Tuple.String.String.]]$" $nodeMT = $nodeType | ConvertFrom-String | Foreach-Object P1 $nodeAddresses = dbg !dumpheap -mt $nodeMT -short $keys = $nodeAddresses | % { dbg !do $_ } | Select-String m_key $keyAddresses = $keys | ConvertFrom-String | Foreach-Object P7 foreach($keyAddress in $keyAddresses) { $keyObject = dbg !do $keyAddress $item1 = $keyObject | Select-String m_Item1 | ConvertFrom-String | % P7 $string1 = dbg !do $item1 | Select-String "String:s+(.)" | % { $_.Matches.Groups[1].Value } $item2 = $keyObject | Select-String mItem2 | ConvertFrom-String | % P7 $string2 = dbg !do $item2 | Select-String "String:s+(.*)" | % { $.Matches.Groups[1].Value } [PSCustomObject] @{ Path = $string1; Content = $string2 } } }
*參考來源:*leeholmes,周大濤編譯,轉載請註明來自FreeBuf.COM
※挖洞經驗 | 用跨站搜索在谷歌問題跟蹤平台實現敏感信息獲取
※安全建設之平台搭建
TAG:FreeBuf |