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(數據目錄表)的第一個成員指向導出表
以下是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文件在硬盤中的物理地址, 而用的虛擬地址 是加載內存後的。所以我們要熟悉轉換方法
可是我們發現 有好多好多的函數 如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
Post a Comment