<div> 

前言

近來正在學習《漏洞戰爭》,也是頭一回分析二進制漏洞,花了好大一番功夫才搞明白,便想記錄下過程。 初次分析,若有不正之處,還請多多指教。

分析環境

 Windos XP & Ollydbg & Immunity debugger & IDA Pro & Adobe Reader 9.3.4

分析過程

1.定位漏洞點

根據書中給出的信息,漏洞存在於CoolType.dll中,使用IDA Pro反編譯CoolType.dll,找到字符串 “SING” ,使用交叉引用功能定位到漏洞代碼附近 但造成漏洞的主要原因是strcat,Adobe Reader在調用strcat時,未對uniqueName字段的字符串長度進行檢測,導致可以將任意長度的字符串複製到固定大小的棧空間中,最終導致棧溢出。(摘抄自《漏洞戰爭》)

2.如何控制EIP

知道從哪可以複製數據到棧中導致棧溢出後,下一步就該考慮該複製多少數據進去才能控制eip。 使用ollydbg附加adobe reader,在0x803DDAB處,也就是call strcat的位置下斷點。 使用msf生成樣本文件,隨後用adobe reader打開,同時觸發斷點。 執行F8,數據被複制到棧中,目的地址爲0x12E4D8 使用immunity debugger的mona插件生成溢出字符串,並複製該字符串到0x12E4D8的位置。 至於爲什麼是溢出字符串的長度爲什麼是572字節,其實這裏我是抄樣本里的數據長度。嘗試過用500字節會覆蓋函數的返回地址,但並非當前函數,使用600、1000、1200都會觸發STACK_BUFFER_OVERRUN異常。主要是想搞明白書中的內容,所以這裏也用572字節。 執行F9,觸發異常,但此處並未能覆蓋EIP 異常信息顯示,無法訪問[6B413187],爲了消除影響,通過計算偏移找到6B413187的位置,然後使用一個可讀寫的內存地址去替換它。 但如果直接拿6B413187去計算偏移的話是算不出來的,原因在於6B413187並不在我們生成的溢出字符串中。而EAX來源於[ECX+1C],應該拿ECX中的值去計算偏移纔對。 找到偏移0×130的位置,將6B41316B替換成一個讀寫的內存地址,比如0x4A8A08E2,這是書中給出的地址,也可替換成其他的。(0×130也就是十六進制的304) 重新調試,將修改後的溢出字符串再次複製到緩衝區。(緩衝區的起始地址是0x12E4D8,被修改的位置在0x12E608,也就是0x12E4D8+0×130) 執行F9,再次觸發異常,且成功覆蓋EIP 再次使用immunity debugger的mona插件去計算偏移 重啓調試進程,執行完0x803DDAB的call strcat後,在0x12E4D8+0x1F8的位置設置內存斷點(0x1F8也就是504的十六進制) F9繼續執行,執行到第三次斷點,找到能覆蓋EIP的指令。

3.分析ShellCode

知道如何控制EIP後,繼續來分析樣本中的ShellCode。 重啓調試進程,執行完0x803DDAB的call strcat後,在0x12E6D0的位置設置內存斷點 多次F9執行到0x808B308,也就是call dword ptr ds:[eax] F7單步執行call dword ptr ds:[eax],跟入0x4A80CB38 此時的ESP的值爲0x12DD24,而溢出字符串的位置在0x12E4D8。shellcode中通過ADD EBP,794; LEAVE;回到原來的棧空間中去。

F7繼續執行

而用來繞過DEP的ROP指令和shellcode都存放在堆中,使用POP ESP修改ESP的值爲0x0C0C0C0C F7繼續執行到ESP=0x0C0C0C1C,EIP=4A801F90的位置,前面那幾條ROP指令暫不清楚作用是什麼,嘗試過替換掉成其他無意義的指令和去除這幾條指令,shellcode依舊能正常運行。 而0x4A801F90正是關鍵的ROP指令之一,除此之外還有0x4A80B692 EAX中的值指向icucnv36.dll的IAT表,通過提前構造好棧中的參數,再利用POP EAX; JMP DWORD PTR DS:[EAX] 實現函數調用。後面幾個函數的調用都是使用這種思路。 第一次調用了Kernel32.CreateFileA函數,其參數爲 但後面調用的函數需要用到前一個函數的返回值,shellcode通過以下三條ROP指令將上一個函數的返回值放到下一個函數的參數列表中。 ROP1: XCHG EAX,EDI,此時EAX中存放的正是上一個函數的返回值。 ROP2: POP EBX,EBX中的值將參下一條ROP指令的計算。 ROP3: AND DWORD PTR SS:[EBX*2+ESP],EDI,這裏纔是將返回值放到參數列表的指令。 第二個調用的函數爲Kernel32.CreateFileMappingA,參數列表如下 運用同樣的手法調用第三個函數Kernel32.MapViewOfFile,參數列表如下 第四個函數爲MSVCR80.memcpy,參數列表如下。位於ESP中的值(0x4F70000)爲函數返回地址,也就是Shellcode的位置。 至此,整個shellcode的佈局思路也分析得七七八八了。

小結

接下來,討論下分析過程中的幾個問題。 1.爲什麼ROP指令的地址都在icucnv36.dll的地址空間 這點書中也提到,因爲在Adobe Reader的各個版本上這個dll的地址都是不變的。通過對比win7和xp中的icucnv36.dll(同一adobe reader版本),發現只有icucnv36.dll沒有開啓REBASE,DEP,ASLR,且存在可讀可執行的.text段和可讀可寫的.data段。 2.既然使用500個字節的溢出字符串也能覆蓋EIP,那要怎麼做才能成功執行shellcode呢? 直接使用POP ESP的地址覆蓋返回地址,將ESP設爲0x0C0C0C0C即可,後面的都一樣了。(測試時並沒有發現GS的影子) 3.ROP3中的AND DWORD PTR SS:[EBX*2+ESP],EDI能換成諸如mov、xor嗎? 可以,但找不到,嘗試過在icucnv36.dll中查找mov、xor、or等指令來替換and,但都找不到。但也許還有其他辦法實現該功能。

參考資料

 《漏洞戰爭》
 《灰帽黑客》第四版 第12章
*本文作者:wnltc0,轉載請註明來自FreeBuf.COM
相關文章