茫茫記憶體,我該如何用 windbg 找到你 ?

一線碼農發表於2021-04-13

一:背景

1. 講故事

前天wx上有個朋友丟給我一個dump,讓我幫忙鑑定一下某些敏感資訊在記憶體中是否也是加密的,現在資料安全很重要,不僅資料庫中的資訊要加密,灌到記憶體後資料同樣也需密文儲存,隨用隨解密,爭取安全最大化?,此為背景,接下來就是我艹,這咋讓我鑑定呀????

二:如何鑑定

1. 思考

我艹幾秒後,冷靜下來想想還是有一定解決辦法的,我先把問題化簡一下。

  • 判斷記憶體中是否有字串為 張三 or 李四 or 王五 的明文字元。

  • 判斷記憶體中是否存在各自明文的 md5。

上面兩點檢索一下,基本就能確定那些敏感資訊是否加密了。

像 C# 這種託管語言有一個好處,就是所有的託管物件都是存放在 託管堆 上,言外之意就是字串也在 託管堆 上,所以接下來的問題是如何在堆上檢索 string=張三 的字串。

問題來了,很多時候 託管堆 上的 string 是海量的,我見過最高有幾千萬個,string茫茫,何時才能找到我最靚的崽呀 ??? ,理論時間結束,接下來開始打怪。

2. 案例演示

為了能夠繼續聊下去,我用一個簡單的例子演示一下如何通過人肉搜尋 string=張三, 先看程式碼。


    class Program
    {
        static List<string> strList = new List<string>();
        static void Main(string[] args)
        {
            strList.Add("fake");
            strList.Add("張三");

            Console.ReadLine();
        }
    }

接下來祭出 windbg。

  • !dumpheap -type System.String -min 8 -max 15 找到所有 10-15byte 範圍的字串。

0:000> !dumpheap  -type System.String -min 8 -max 15
 Address       MT     Size
026f1228 652224e4       14     
026f164c 652224e4       16     
026f230c 65222d74       12     
...

Statistics:
      MT    Count    TotalSize Class Name
65225468        1           12 System.Collections.Generic.GenericEqualityComparer`1[[System.String, mscorlib]]
65222d74       10          156 System.String[]
652224e4       65         1168 System.String
Total 76 objects

從輸出中可以看出,當前size範圍內有 1168 個 string,還發現這個 size 不是特別準,先不管了,string 雖然有點多,但還是可以人肉的,用 !do xxx 逐個檢視。


0:000> !do 026f2354
Name:        System.String
MethodTable: 652224e4
EEClass:     65327690
Size:        18(0x12) bytes
File:        C:\Windows\Microsoft.Net\assembly\GAC_32\mscorlib\v4.0_4.0.0.0__b77a5c561934e089\mscorlib.dll
String:      張三
Fields:
      MT    Field   Offset                 Type VT     Attr    Value Name
652242a8  4000283        4         System.Int32  1 instance        2 m_stringLength
65222c9c  4000284        8          System.Char  1 instance     5f20 m_firstChar
652224e4  4000288       70        System.String  0   shared   static Empty
    >> Domain:Value  00a22530:NotInit  <<

看到沒有,上面的 String: 張三 就是我要的結果,明文儲存 實錘。

文章到此是不是可以結束啦 ???, 那就太沒有實戰經驗了,剛才說了,很多時候篩選後的 string 也可能高達幾萬幾十萬,再用人肉那是不可能的。。。

那有沒有代替人肉的指令碼呢????, 嘿嘿,還真有。。。

三:使用自動化指令碼

現在的 windbg preview 支援 javacript 作為指令碼擴充套件,接下來我準備把剛才的 人肉步驟 寫入指令碼,貌似專業名字叫 playbook,蹩腳指令碼如下:


"use strict";

function RunCommands() {

    var ctl = host.namespace.Debugger.Utility.Control;
    var str_address_list = ctl.ExecuteCommand("!dumpheap  -type System.String -min 8 -max 15 -short");

    for (var str_address of str_address_list) {

        var str_dump = ctl.ExecuteCommand("!do -nofields " + str_address);

        var str = str_dump.Last();

        var isContains = str.indexOf("張三") > 0;

        if(isContains) host.diagnostics.debugLog(str+"  "+str_address +"\n");
    }
}

指令碼的邏輯還是非常簡單的,就是模擬剛才的人肉,最後在輸出內容中判斷是否有 張三 的字串,如果有,連同 address 地址一起列印出來,指令碼儲存好之後,用 dx 命令來執行 RunCommands() 函式。


0:000> dx Debugger.State.Scripts.RunCommands.Contents.RunCommands()
String:      張三  026f2354
Debugger.State.Scripts.RunCommands.Contents.RunCommands()

看到沒有, 明文 張三 顯示出來了,不信的話,我截一張圖,證明我沒有騙你 ???。

四:總結

在這個案例中最後使用了 js 指令碼輕鬆搞定,可以看出,指令碼給了 windbg 無限的挖掘可能, 真的是太強大了,有興趣的話可參考 MSDN: https://docs.microsoft.com/en-us/windows-hardware/drivers/debugger/javascript-debugger-scripting

更多高質量乾貨:參見我的 GitHub: dotnetfly

圖片名稱

相關文章