當前位置:
首頁 > 新聞 > 從PowerShell內存轉儲中提取執行的腳本內容

從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


喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 FreeBuf 的精彩文章:

挖洞經驗 | 用跨站搜索在谷歌問題跟蹤平台實現敏感信息獲取
安全建設之平台搭建

TAG:FreeBuf |