溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

從PowerShell內(nèi)存轉(zhuǎn)儲(chǔ)中提取執(zhí)行的腳本內(nèi)容

發(fā)布時(shí)間:2021-11-25 15:23:29 來(lái)源:億速云 閱讀:176 作者:柒染 欄目:編程語(yǔ)言

從PowerShell內(nèi)存轉(zhuǎn)儲(chǔ)中提取執(zhí)行的腳本內(nèi)容,針對(duì)這個(gè)問(wèn)題,這篇文章詳細(xì)介紹了相對(duì)應(yīng)的分析和解答,希望可以幫助更多想解決這個(gè)問(wèn)題的小伙伴找到更簡(jiǎn)單易行的方法。

上次發(fā)布從PowerShell流程轉(zhuǎn)儲(chǔ)中提取活動(dòng)歷史記錄之后,我又想到了一個(gè)有趣的問(wèn)題:“是否可以提取已執(zhí)行的腳本(來(lái)自磁盤(pán))的內(nèi)容,即使這些文件未被捕獲?",我得到答案是“是”,但是它也很復(fù)雜。這將需要大量的WinDbg自動(dòng)化工作,因此第一步,安裝WinDbg模塊。

我們先創(chuàng)建一個(gè)簡(jiǎn)單的腳本。

從PowerShell內(nèi)存轉(zhuǎn)儲(chǔ)中提取執(zhí)行的腳本內(nèi)容

打開(kāi)PowerShell會(huì)話,運(yùn)行腳本,然后創(chuàng)建轉(zhuǎn)儲(chǔ)文件。

從PowerShell內(nèi)存轉(zhuǎn)儲(chǔ)中提取執(zhí)行的腳本內(nèi)容

現(xiàn)在,使用WinDbg模塊連接到轉(zhuǎn)儲(chǔ)文件:

Connect-DbgSession -ArgumentList '-z "C:\Users\lee\AppData\Local\Temp\powershell.DMP"'

開(kāi)始

我們想要提取表示在該會(huì)話中運(yùn)行的腳本的對(duì)象(如果存在)。但我們?nèi)绾握业竭@些呢?

首先,讓我們使用SOS的“轉(zhuǎn)儲(chǔ)對(duì)象”命令來(lái)轉(zhuǎn)儲(chǔ)它知道的關(guān)于進(jìn)程中每個(gè)對(duì)象的所有內(nèi)容。因此,我們將從!DumpHeap命令開(kāi)始查找所有對(duì)象實(shí)例(即:我們甚至不使用-Type過(guò)濾器)。但還有其他方法可以做到這一點(diǎn),但這一步和下一步將需要很長(zhǎng)時(shí)間。

$allReferences = dbg !dumpheap -short

一旦我們擁有所有對(duì)象引用,讓我們使用!do(轉(zhuǎn)儲(chǔ)對(duì)象命令)讓SOS將它們?nèi)靠梢暬?。轉(zhuǎn)儲(chǔ)對(duì)象的輸出不包括被轉(zhuǎn)儲(chǔ)對(duì)象的地址,因此我們也將使用Add-Member來(lái)跟蹤它。

$ allObjects = $ allReferences | Foreach-Object {$ object = dbg“!do $ ”; Add-Member -InputObject $ object Address $  -PassThru -Force}

SOS在此流程實(shí)例中知道大約有一百萬(wàn)個(gè)對(duì)象。但是他們中的任何一個(gè)GUID都會(huì)被SOS可視化嗎?

從PowerShell內(nèi)存轉(zhuǎn)儲(chǔ)中提取執(zhí)行的腳本內(nèi)容

看起來(lái)我們很幸運(yùn)!在這些百萬(wàn)個(gè)對(duì)象中,我們?cè)O(shè)法將其縮小到PowerShell內(nèi)存中的7個(gè)System.String對(duì)象,這些對(duì)象以某種方式引用了GUID。如果我們認(rèn)為信息可能一直在System.String中,我們可以使用“$allReferences = dbg !dumpheap –type System.String –short”使我們的初始“$ allObjects”查詢更快。但是我們?nèi)绾闻宄@些GUID的是什么?

為了找到答案,我們將使用SOS的!gcroot命令。這通常用于診斷托管內(nèi)存泄漏 ,!gcroot命令會(huì)告訴您引用它的對(duì)象以及引用該對(duì)象的對(duì)象 - 一直到達(dá)對(duì)象的根目錄。讓我們探討一下這些根源。

從PowerShell內(nèi)存轉(zhuǎn)儲(chǔ)中提取執(zhí)行的腳本內(nèi)容

第5項(xiàng)根植于對(duì)象數(shù)組(System.Object[]),其中一個(gè)元素是ConcurrentDictionary,它包含一個(gè)ScriptBlock,它又包含CompiledScriptBlockData,其中包含PowerShell AST中的節(jié)點(diǎn),在引用這個(gè)GUID的命令A(yù)ST中觸底。

這是我實(shí)例中的第4項(xiàng):

從PowerShell內(nèi)存轉(zhuǎn)儲(chǔ)中提取執(zhí)行的腳本內(nèi)容

這是有趣的!這個(gè)開(kāi)頭是相同的根對(duì)象數(shù)組(0000026e101e9a40),相同的ConcurrentDictionary(0000026e003bc440),但這次最后是一個(gè)包含我們的字符串和另一個(gè)字符串的元組(兩個(gè)項(xiàng)目的簡(jiǎn)單配對(duì))。讓我們深入了解那個(gè)元組及其包含的字符串。

從PowerShell內(nèi)存轉(zhuǎn)儲(chǔ)中提取執(zhí)行的腳本內(nèi)容

所以這個(gè)元組有兩個(gè)元素。第一個(gè)元素看起來(lái)是執(zhí)行腳本的路徑,第二個(gè)元素看起來(lái)是該腳本中的內(nèi)容。讓我們看看PowerShell Source對(duì)這些數(shù)據(jù)結(jié)構(gòu)。我將搜索ConcurrentDictionary以查看我能找到的內(nèi)容。在第三頁(yè),我們可以看到我們正在查看的內(nèi)容:

從PowerShell內(nèi)存轉(zhuǎn)儲(chǔ)中提取執(zhí)行的腳本內(nèi)容

有一個(gè)名為CompiledScriptBlock的類。它包含一個(gè)名為“s_cachedScripts”的靜態(tài)(進(jìn)程范圍)緩存。這是一個(gè)將一對(duì)字符串映射到ScriptBlock實(shí)例的字典。如果您閱讀了源代碼,您可以確切地看到Tuple的內(nèi)容 - 腳本路徑到ScriptBlock緩存時(shí)包含的內(nèi)容的映射:

從PowerShell內(nèi)存轉(zhuǎn)儲(chǔ)中提取執(zhí)行的腳本內(nèi)容

這個(gè)數(shù)據(jù)結(jié)構(gòu)是我們最終討論的內(nèi)容。出于性能原因,PowerShell維護(hù)一個(gè)內(nèi)部腳本塊緩存,這樣每次看到腳本時(shí)都不需要重新編譯腳本塊。該緩存是路徑和腳本內(nèi)容的關(guān)鍵。存儲(chǔ)在緩存中的東西是ScriptBlock類的一個(gè)實(shí)例,它包含(除此之外)編譯的腳本的AST。

所以現(xiàn)在我們知道這個(gè)東西存在了,我們可以在自動(dòng)化中更智能,并提取這些東西!現(xiàn)在我們需要一個(gè)真正的腳本,這就是我們要做的:

1. 使用!dumpheap查找此Tuple類的實(shí)例。dumpheap命令執(zhí)行子字符串搜索,因此我們將使用正則表達(dá)式進(jìn)行一些后處理。

2. 這給了我們實(shí)際想要研究的元組類的MT。

3. 使用該MT作為過(guò)濾器再次運(yùn)行!dumpheap

從PowerShell內(nèi)存轉(zhuǎn)儲(chǔ)中提取執(zhí)行的腳本內(nèi)容

現(xiàn)在我們可以探索其中一個(gè)節(jié)點(diǎn)。它有一個(gè)m_key,我們可以深入研究。

從PowerShell內(nèi)存轉(zhuǎn)儲(chǔ)中提取執(zhí)行的腳本內(nèi)容

差不多了!讓我們從那些結(jié)果鍵中提取出兩個(gè)項(xiàng)目,然后生成一個(gè)漂亮的PowerShell對(duì)象:

從PowerShell內(nèi)存轉(zhuǎn)儲(chǔ)中提取執(zhí)行的腳本內(nèi)容

這是一個(gè)將所有這些打包成函數(shù)的腳本.

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 }              
    }              
}

 

關(guān)于從PowerShell內(nèi)存轉(zhuǎn)儲(chǔ)中提取執(zhí)行的腳本內(nèi)容問(wèn)題的解答就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,如果你還有很多疑惑沒(méi)有解開(kāi),可以關(guān)注億速云行業(yè)資訊頻道了解更多相關(guān)知識(shí)。

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI