前言
這里不得不用簡(jiǎn)單的篇幅介紹一下mona.py。這是由corelan team整合的一個(gè)可以自動(dòng)構(gòu)造Rop Chain而且集成了metasploit計(jì)算偏移量功能的強(qiáng)大挖洞輔助插件,詳情可以參照他們的官方網(wǎng)站。
當(dāng)我在準(zhǔn)備Derbycon的高級(jí)開(kāi)發(fā)課程之前,還一直在玩IE的原始堆分配。其中有些問(wèn)題給我?guī)?lái)了挫折(至少說(shuō),讓我的整個(gè)研究進(jìn)度都慢了許多)。反觀,這也提高了我快速識(shí)別對(duì)象的能力,也是一個(gè)不錯(cuò)的機(jī)遇。畢竟,我是在嘗試找一個(gè)包含任意數(shù)據(jù)的對(duì)象,或者指針,這做起來(lái)并不那么容易!
我決定給mona.py插件增加一些新的特性,以便讓大家可以更快的尋找到感興趣的對(duì)象。這些新特性僅僅在WinDBG下有效。
dumpobj (do)
這第一個(gè)新特性就是dumpobj。這條mona.py命令會(huì)轉(zhuǎn)儲(chǔ)對(duì)象中的內(nèi)容,并提供內(nèi)容中的有用信息。該命令有以下幾個(gè)參數(shù):
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)
正如你看到的幫助信息,我們至少需要提供兩個(gè)參數(shù)。
-a <address> : 開(kāi)始的位置(對(duì)象的地址。當(dāng)然,這個(gè)你可以自己隨意定義)
-s <number> :對(duì)象的大小,如果你指定-s參數(shù),mona會(huì)嘗試自己定義一個(gè)大小。如果定義失敗,那么mona會(huì)對(duì)這個(gè)對(duì)象轉(zhuǎn)儲(chǔ)0×28字節(jié)。
此外,你也可以告訴mona轉(zhuǎn)儲(chǔ)一些鏈接對(duì)象。-l參數(shù)后跟上一個(gè)數(shù)字,這個(gè)數(shù)字代表了遞歸轉(zhuǎn)儲(chǔ)的等級(jí)。由于性能的原因,會(huì)限制輸出的大小,鏈接對(duì)象中只有第一個(gè)0×28字節(jié)的內(nèi)容會(huì)輸出給用戶。當(dāng)然,你也可以使用-m參數(shù),看到更多內(nèi)容。
在WinDBG中轉(zhuǎn)儲(chǔ)對(duì)象中的內(nèi)容很繁瑣。在某些情況下,dds/dc命令力度還是不夠的,還需要做一些額外的工作才能夠進(jìn)一步分析這個(gè)對(duì)象和可選對(duì)象。
讓我們來(lái)看看下面這個(gè)例子,假設(shè)我們?cè)?x023a1bc0有一個(gè)0×78字節(jié)的對(duì)象。我們可以使用WinDBG命令轉(zhuǎn)儲(chǔ)這個(gè)對(duì)象中的內(nèi)容。
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,以及一些垃圾數(shù)據(jù)。
使用mona,我們可以轉(zhuǎn)儲(chǔ)相同的對(duì)象,mona會(huì)嘗試在對(duì)象中收集更多有關(guān)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
很顯然,對(duì)象中的某些值指向了字符串(ASCII and Unicode),其他的似乎指向了另外一個(gè)對(duì)象(ADVAPI32!g_CodeLevelObjTable+0×4)。這個(gè)看起來(lái)是不是要比使用dds/dc命令更方便呢?其實(shí),我們還可以做得更好,我們還可以通知mona自動(dòng)打印鏈接對(duì)象。接下來(lái),我們?cè)俅问褂胢ona命令并帶上-L參數(shù)看看效果吧。
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確定源對(duì)象中包含了對(duì)2個(gè)鏈接對(duì)象的引用,并且轉(zhuǎn)儲(chǔ)了鏈接對(duì)象。最重要的是要知道m(xù)ona不會(huì)把字符串 (ASCII or Unicode) 當(dāng)作對(duì)象處理,因?yàn)閙ona已經(jīng)顯示了字符串,dumpobj命令的輸出,最終會(huì)寫入一個(gè)名為“dumpobj.txt”的文本文件中。
dumplog (dl)
顯然,dumpobj命令能夠十分輕松的獲得一個(gè)對(duì)象的重要信息。如果你已經(jīng)知道起始對(duì)象,這對(duì)你來(lái)說(shuō)就更加方便了。
為了讓世界清凈下來(lái),我決定使用dumplog去解析日志文件(基于某一語(yǔ)法),并在已經(jīng)分配好的對(duì)象中執(zhí)行dumpobj命令。在當(dāng)前這個(gè)版本,dumplog并不能夠轉(zhuǎn)儲(chǔ)鏈接對(duì)象,但是我準(zhǔn)備給他加上這一特性。
Dumplog在使用前,需要進(jìn)行一些設(shè)置。我們需要告訴WinDBG創(chuàng)建一個(gè)遵循特定協(xié)議的日志文件,當(dāng)然了,我們需要在同一個(gè)調(diào)試會(huì)話中運(yùn)行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
這個(gè)想法是為了記錄所有的堆分配以及自由操作。在WinDBG中可以通過(guò)以下步驟實(shí)現(xiàn):
.logclose
.logopen c:\\allocs.txt
接下來(lái),記錄2個(gè)斷點(diǎn)
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).
當(dāng)RtlAllocateHeap 和RtlFreeHeap被調(diào)用時(shí),這兩個(gè)斷點(diǎn)就會(huì)向WinDBG發(fā)送一個(gè)消息。
當(dāng)你準(zhǔn)備分析漏洞時(shí),不要關(guān)閉WinDBG,關(guān)閉日志文件時(shí)使用.logclose命令。我們現(xiàn)在就可以使用mona解析日志文件了。
!py mona dl -fc:\allocs.txt
輸出將被寫入dump_alloc_free.txt文件
文章來(lái)源:FreeBuf黑客與極客(FreeBuf.COM)]