前言
這里不得不用簡單的篇幅介紹一下mona.py。這是由corelan team整合的一個可以自動構造Rop Chain而且集成了metasploit計算偏移量功能的強大挖洞輔助插件,詳情可以參照他們的官方網站。
當我在準備Derbycon的高級開發課程之前,還一直在玩IE的原始堆分配。其中有些問題給我帶來了挫折(至少說,讓我的整個研究進度都慢了許多)。反觀,這也提高了我快速識別對象的能力,也是一個不錯的機遇。畢竟,我是在嘗試找一個包含任意數據的對象,或者指針,這做起來并不那么容易!
我決定給mona.py插件增加一些新的特性,以便讓大家可以更快的尋找到感興趣的對象。這些新特性僅僅在WinDBG下有效。
dumpobj (do)
這第一個新特性就是dumpobj。這條mona.py命令會轉儲對象中的內容,并提供內容中的有用信息。該命令有以下幾個參數:
Usage of command ‘dumpobj’ :
—————————–
Dump the contents of an object.
Arguments:
-a <address>????? : Address of object
-s <number>?????? : Size of object (default value: 0x28 or size of chunk)
Optional arguments:
-l <number>?????? : Recursively dump objects
-m<number>?????? : Size forrecursive objects (default value: 0x28)
正如你看到的幫助信息,我們至少需要提供兩個參數。
-a <address> : 開始的位置(對象的地址。當然,這個你可以自己隨意定義)
-s <number> :對象的大小,如果你指定-s參數,mona會嘗試自己定義一個大小。如果定義失敗,那么mona會對這個對象轉儲0×28字節。
此外,你也可以告訴mona轉儲一些鏈接對象。-l參數后跟上一個數字,這個數字代表了遞歸轉儲的等級。由于性能的原因,會限制輸出的大小,鏈接對象中只有第一個0×28字節的內容會輸出給用戶。當然,你也可以使用-m參數,看到更多內容。
在WinDBG中轉儲對象中的內容很繁瑣。在某些情況下,dds/dc命令力度還是不夠的,還需要做一些額外的工作才能夠進一步分析這個對象和可選對象。
讓我們來看看下面這個例子,假設我們在0x023a1bc0有一個0×78字節的對象。我們可以使用WinDBG命令轉儲這個對象中的內容。
0:001> dds 0x023a1bc0 L 0x78/4
023a1bc0? 023a1d30
023a1bc4? 023a1818
023a1bc8? 00000000
023a1bcc? 023a1d3c
023a1bd0? 023a1824
023a1bd4? baadf00d
023a1bd8? 00020000
023a1bdc? 00000001
023a1be0? 00160014
023a1be4? 023a1a38
023a1be8? 013a0138
023a1bec? 023a1a68
023a1bf0? 00000000
023a1bf4? 00000001
023a1bf8? 023a18a8
023a1bfc? 00000000
023a1c00? 00000000
023a1c04? 00000007
023a1c08? 00000007
023a1c0c? 023a18d0
023a1c10? 00000000
023a1c14? 00000000
023a1c18? 00000000
023a1c1c? 00000000
023a1c20? 00000000
023a1c24? 00000000
023a1c28? 00000000
023a1c2c? 00000000
023a1c30? 00000000
023a1c34? 00000000
0:001> dc 0x023a1bc0 L 0x78/4
023a1bc0? 023a1d30 023a1818 00000000 023a1d3c? 0.:…:…..<.:.
023a1bd0? 023a1824 baadf00d 00020000 00000001? $.:………….
023a1be0? 00160014 023a1a38 013a0138 023a1a68? ….8.:.8.:.h.:.
023a1bf0? 00000000 00000001 023a18a8 00000000? ……….:…..
023a1c00? 00000000 00000007 00000007 023a18d0? …………..:.
023a1c10? 00000000 00000000 00000000 00000000? …………….
023a1c20? 00000000 00000000 00000000 00000000? …………….
023a1c30? 00000000 00000000??????????????????? ……..
Nice!我們可以看到很多東西—似乎是指針的值,nulls,以及一些垃圾數據。
使用mona,我們可以轉儲相同的對象,mona會嘗試在對象中收集更多有關dword的信息。
0:001> !py mona do -a 0x023a1bc0
Hold on…
[+] No size specified, checking if address is part of known heap chunk
Address found in chunk 0x023a1bb8, heap 0x00240000, (user)size 0x78
—————————————————-
[+] Dumping object at 0x023a1bc0, 0x78 bytes
[+] Preparing output file ‘dumpobj.txt’
– (Re)setting logfile c:\logs\HeapAlloc2\dumpobj.txt
[+] Generating module info table, hang on…
– Processing modules
– Done. Let’s rock ‘n roll.
>> Object at 0x023a1bc0 (0x78 bytes):
Offset? Address????? Contents??? Info
——? ——-????? ——–??? —–
+00???? 0x023a1bc0 | 0x023a1d30? (Heap) ptr to ASCII ‘0::’
+04???? 0x023a1bc4 | 0x023a1818? (Heap) ptr to ASCII ‘:’
+08???? 0x023a1bc8 | 0x00000000
+0c???? 0x023a1bcc | 0x023a1d3c? (Heap) ptr to 0x77e46464 : ADVAPI32!g_CodeLevelObjTable+0x4
+10???? 0x023a1bd0 | 0x023a1824? (Heap) ptr to ASCII ‘:’
+14???? 0x023a1bd4 | 0xbaadf00d
+18???? 0x023a1bd8 | 0x00020000? = UNICODE ‘ ‘
+1c???? 0x023a1bdc | 0x00000001
+20???? 0x023a1be0 | 0x00160014? = UNICODE ”
+24???? 0x023a1be4 | 0x023a1a38? (Heap) ptr to UNICODE ‘Basic User’
+28???? 0x023a1be8 | 0x013a0138? (Heap) ptr to ASCII ‘AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA…’
+2c???? 0x023a1bec | 0x023a1a68? (Heap) ptr to UNICODE ‘Allows programs to execute as a user that does not have Administrator or Power User access rights, but can still access resouces accessible by normal users.’
+30???? 0x023a1bf0 | 0x00000000
+34???? 0x023a1bf4 | 0x00000001
+38???? 0x023a1bf8 | 0x023a18a8
+3c???? 0x023a1bfc | 0x00000000
+40???? 0x023a1c00 | 0x00000000
+44???? 0x023a1c04 | 0x00000007
+48???? 0x023a1c08 | 0x00000007
+4c???? 0x023a1c0c | 0x023a18d0? (Heap) ptr to ASCII ‘ :H:p:’
+50???? 0x023a1c10 | 0x00000000
+54???? 0x023a1c14 | 0x00000000
+58???? 0x023a1c18 | 0x00000000
+5c???? 0x023a1c1c | 0x00000000
+60???? 0x023a1c20 | 0x00000000
+64???? 0x023a1c24 | 0x00000000
+68???? 0x023a1c28 | 0x00000000
+6c???? 0x023a1c2c | 0x00000000
+70???? 0x023a1c30 | 0x00000000
+74???? 0x023a1c34 | 0x00000000
[+] This mona.py actiontook 0:00:00.579000
很顯然,對象中的某些值指向了字符串(ASCII and Unicode),其他的似乎指向了另外一個對象(ADVAPI32!g_CodeLevelObjTable+0×4)。這個看起來是不是要比使用dds/dc命令更方便呢?其實,我們還可以做得更好,我們還可以通知mona自動打印鏈接對象。接下來,我們再次使用mona命令并帶上-L參數看看效果吧。
0:001> !py mona do -a 0x023a1bc0 -l 1
Hold on…
[+] No size specified, checking if address is part of known heap chunk
Address found in chunk 0x023a1bb8, heap 0x00240000, (user)size 0x78
—————————————————-
[+] Dumping object at 0x023a1bc0, 0x78 bytes
[+] Also dumping up to 1 levels deep, max size of nested objects: 0x28 bytes
[+] Preparing output file ‘dumpobj.txt’
– (Re)setting logfile c:\logs\HeapAlloc2\dumpobj.txt
[+] Generating module info table, hang on…
– Processing modules
– Done. Let’s rock ‘n roll.
>> Object at 0x023a1bc0 (0x78 bytes):
Offset? Address????? Contents??? Info
——? ——-????? ——–??? —–
+00???? 0x023a1bc0 | 0x023a1d30? (Heap) ptr to ASCII ‘0::’
+04???? 0x023a1bc4 | 0x023a1818? (Heap) ptr to ASCII ‘:’
+08???? 0x023a1bc8 | 0x00000000
+0c???? 0x023a1bcc | 0x023a1d3c? (Heap) ptr to 0x77e46464 : ADVAPI32!g_CodeLevelObjTable+0x4
+10???? 0x023a1bd0 | 0x023a1824? (Heap) ptr to ASCII ‘:’
+14???? 0x023a1bd4 | 0xbaadf00d
+18???? 0x023a1bd8 | 0x00020000? = UNICODE ‘ ‘
+1c???? 0x023a1bdc | 0x00000001
+20???? 0x023a1be0 | 0x00160014? = UNICODE ”
+24???? 0x023a1be4 | 0x023a1a38? (Heap) ptr to UNICODE ‘Basic User’
+28???? 0x023a1be8 | 0x013a0138? (Heap) ptr to ASCII ‘AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA…’
+2c???? 0x023a1bec | 0x023a1a68? (Heap) ptr to UNICODE ‘Allows programs to execute as a user that does not have Administrator or Power User access rights, but can still access resouces accessible by normal users.’
+30???? 0x023a1bf0 | 0x00000000
+34???? 0x023a1bf4 | 0x00000001
+38???? 0x023a1bf8 | 0x023a18a8? (Heap) ptr to 0x00000101 :
+3c???? 0x023a1bfc | 0x00000000
+40???? 0x023a1c00 | 0x00000000
+44???? 0x023a1c04 | 0x00000007
+48???? 0x023a1c08 | 0x00000007
+4c???? 0x023a1c0c | 0x023a18d0? (Heap) ptr to ASCII ‘ :H:p:’
+50???? 0x023a1c10 | 0x00000000
+54???? 0x023a1c14 | 0x00000000
+58???? 0x023a1c18 | 0x00000000
+5c???? 0x023a1c1c | 0x00000000
+60???? 0x023a1c20 | 0x00000000
+64???? 0x023a1c24 | 0x00000000
+68???? 0x023a1c28 | 0x00000000
+6c???? 0x023a1c2c | 0x00000000
+70???? 0x023a1c30 | 0x00000000
+74???? 0x023a1c34 | 0x00000000
>> Object at 0x023a1d3c (0x28 bytes):
Offset? Address????? Contents??? Info
——? ——-????? ——–??? —–
+00???? 0x023a1d3c | 0x77e46464? ADVAPI32!g_CodeLevelObjTable+0x4
+04???? 0x023a1d40 | 0x023a1bcc? (Heap) ptr to ASCII ‘<:$:’
+08???? 0x023a1d44 | 0xbaadf00d
+0c???? 0x023a1d48 | 0x00040000? = UNICODE ‘ ‘
+10???? 0x023a1d4c | 0x00000101
+14???? 0x023a1d50 | 0x001a0018? = UNICODE ”
+18???? 0x023a1d54 | 0x023a1c50? (Heap) ptr to UNICODE ‘Unrestricted’
+1c???? 0x023a1d58 | 0x0090008e? (Heap) ptr to ASCII ‘AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA…’
+20???? 0x023a1d5c | 0x023a1c88? (Heap) ptr to UNICODE ‘Software access rights are determined by the access rights of the user.’
+24???? 0x023a1d60 | 0x00000000
>> Object at 0x023a18a8 (0x28 bytes):
Offset? Address????? Contents??? Info
——? ——-????? ——–??? —–
+00???? 0x023a18a8 | 0x00000101
+04???? 0x023a18ac | 0x05000000
+08???? 0x023a18b0 | 0x0000000a
+0c???? 0x023a18b4 | 0xabababab
+10???? 0x023a18b8 | 0xabababab
+14???? 0x023a18bc | 0xfeeefeee
+18???? 0x023a18c0 | 0x00000000
+1c???? 0x023a18c4 | 0x00000000
+20???? 0x023a18c8 | 0x0005000a? = UNICODE ”
+24???? 0x023a18cc | 0x051807c2
[+] This mona.py actiontook 0:00:00.640000
在上面的輸出我們可以看到,mona確定源對象中包含了對2個鏈接對象的引用,并且轉儲了鏈接對象。最重要的是要知道mona不會把字符串 (ASCII or Unicode) 當作對象處理,因為mona已經顯示了字符串,dumpobj命令的輸出,最終會寫入一個名為“dumpobj.txt”的文本文件中。
dumplog (dl)
顯然,dumpobj命令能夠十分輕松的獲得一個對象的重要信息。如果你已經知道起始對象,這對你來說就更加方便了。
為了讓世界清凈下來,我決定使用dumplog去解析日志文件(基于某一語法),并在已經分配好的對象中執行dumpobj命令。在當前這個版本,dumplog并不能夠轉儲鏈接對象,但是我準備給他加上這一特性。
Dumplog在使用前,需要進行一些設置。我們需要告訴WinDBG創建一個遵循特定協議的日志文件,當然了,我們需要在同一個調試會話中運行mona。
Dumplog的幫助信息如下:
Usage of command ‘dl’ :
————————
Dump all objects recorded in an alloc/free log
Note: dumplog will only dump objects that have not been freed in the samelogfile.
Expected syntax for log entries:
Alloc : ‘alloc(size in hex) =address’
Free? : ‘free(address)’
Additional text after the alloc & free info is fine.
Just make sure the syntax matches exactly with the examples above.
Arguments:
-f <path/to/logfile>: Full path to the logfile
這個想法是為了記錄所有的堆分配以及自由操作。在WinDBG中可以通過以下步驟實現:
.logclose
.logopen c:\\allocs.txt
接下來,記錄2個斷點
bp !ntdll + 0002e12c “.printf \”alloc(0x%x) = 0x%p\”,poi(esp+c), eax; .echo; g”
bp ntdll!RtlFreeHeap “j (poi(esp+c)!=0)’.printf \”free(0x%p)\”, poi(esp+c); .echo; g'; ‘g';”
(基于kernel32.dll最新版本, Windows7 SP1).
當RtlAllocateHeap 和RtlFreeHeap被調用時,這兩個斷點就會向WinDBG發送一個消息。
當你準備分析漏洞時,不要關閉WinDBG,關閉日志文件時使用.logclose命令。我們現在就可以使用mona解析日志文件了。
!py mona dl -fc:\allocs.txt
輸出將被寫入dump_alloc_free.txt文件
文章來源:FreeBuf黑客與極客(FreeBuf.COM)]