Windows安全之PE結構(六)之導出表(IDT)結構分析

在這裡來說 要清一下DLL檔(dynamic link library)的基礎認識, 每一個windows擁有4GB的虛擬內存空間,
可是我們發現 有好多好多的函數 如MessageBox等 在一個win系統下 有無限個程序會調用到這個方法 但如果每一個程序也需要在內存中加載一次 不就重覆了嗎?
有一百個程序需要調用MessageBox, 在內存也只需要加載一次User.dll 所有程序在內存中找到他, 然後複製需要的函數到我們的程序裡. 省了很多內存.我們的微軟前輩們都很強大 lol..

大部份的DLL文件也包含了導出表! (可不是指所有的DLL)


導出表(EXPORT TABLE) 中的主要成分是一個表格,內含函數名稱,輸出序數等,序數是指定DLL某個函數的16位數字,在指向的DLL中是獨一無二的,在此我們不提倡只用序數來索引函數的方法,這樣會給DLL文件帶來維護的問題,例如當DLL文件一旦升級或修改可能導致調用改DLL的程序無法加載到需要的函數

又是DataDirectory(數據目錄表)的第一個成員指向導出表
IMAGE_EXPORT_DIRECTORY STRUCT
Characteristics DWORD ? ;未使用,總是定義為0
TimeDateStamp DWORD ?   ;文件生成時間
MajorVersion WORD ?   ;未使用,總是定義為0
MinorVersion WORD ?   ;未使用,總是定義為0
Name         DWORD ?   ;模塊的真實名稱
Base         DWORD ?   ;基數,加上序數就是函數地址數組的索引值
NumberOfFunction DWORD ? ; 導出函數的總數量
NumberOfName     DWORD ? ; 以名稱方式導出的函數的總數
AddressOfFunction DWORD ? ; 指向輸出函數地址的RVA
AddressOfNames    DWORD ? ; 指向輸出函數名稱的RVA
AddressOfNameOrdinals DWORD ?; 指向輸出函數序號的RVA
IMAGE_EXPORT_DIRECTORY ENDS

以下是count.dll 的解析 我只導出了一個函數 嘗試查找它的地址

用LordPE把它打開, 定位EAT位置 在我電腦中是22620H , 而所在段是.rdata
得出以下結果 才可以開始靜態分析....
EAT : RVA 22620
RVA = 22620 - 1F000 = 3620 + d800 = 10E20
10e20 = IMAGE_EXPORT_DIRECTORY的在硬盤中地址

Characteristics = 0
TimeDateStamp = 54C0FD44
MajorVersion = 0
MinorVersion = 0
Name = 00022652
Base = 0x00000001
NumberOfFunction = 0x00000001
NumberOfName = 0x00000001
AddressOfFunction = 0x00022648 (22648-1F000) = 3648 + D800 = 10E48
AddressOfNames = 0x0002264C (2264C-1F000)=364C = 364C + D800 = 10E4C
AddressOfNameOrdinals = 0x00022650 (22650-1F000)= 3650 + D800 = 10E50


AddressOfNames 10E4C存放的是另一個RVA他是一個
10E5C = 0
0+1 就是1啦 , 這是說明在第一項

那第一個序號的相應第一個函數名稱的就是1序號了

最後就用0x00022648這個地址尋找了
AddressOfFunction 指向了 0x00022648 它裡面
(22648-1F000) = 3648 + D800 = 10E48
10E48中存放的是000116C2 這個就是第一個導出函數的地址了

如下圖的流程大致如下

三個主要數組是並排 以項為尋找單位




這裡詳解一下
1. 首先定位導出表的位址 計算出物理地址
如下圖:





2. 首先透過AddressOfNames,取得存放函數名稱的字符串的地址
如下圖:





3. 計算出字符串的物理地址, 尋找目標的函數是數組的第幾項
如下圖:




4. 再透過AddressOfNameOrdinals 尋找目標函數是數組中的序號 +上base (base可以不是1)
如下圖:





5. 最後AddressOfFunction尋找第某項中的地址是多少
如下圖:






6.最後打開DASM32 證明一下, 用尋找功能尋找函數名稱,看到了地址跟我們在ultraedit靜態分析出來的一樣 證明沒錯了
如下圖:



首先用addressOfNames找出目標函數是第幾項元素,然後用AddressOfNameOrdinals遍歷一次 查項他在第幾項元素中的序號是多少,然後用addressOffunction 查看該序號的項數的地址

在靜態分析中, 熟練虛擬地址 與 物理地址的轉換是十分重要的。不然就會搞亂了
我們在ultraedit中的是PE文件在硬盤中的物理地址, 而用的虛擬地址 是加載內存後的。所以我們要熟悉轉換方法

Comments

Popular posts from this blog

Android Kernel Development - Kernel compilation and Hello World

How does Nested-Virtualization works?

Understanding ACPI and Device Tree