日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

22. PE结构-PE详解之输入表(导入表)、屠龙刀W32Dasm(静态)、LordPE(动态)工具入门(查找dll、调用函数)

發布時間:2025/3/15 编程问答 21 豆豆
生活随笔 收集整理的這篇文章主要介紹了 22. PE结构-PE详解之输入表(导入表)、屠龙刀W32Dasm(静态)、LordPE(动态)工具入门(查找dll、调用函数) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

我們知道PE 文件中的數據被載入內存后根據不同頁面屬性被劃分成很多區塊(節),并有區塊表(節表)的數據來描述這些區塊。這里我們需要注意的問題是:一個區塊中的數據僅僅只是由于屬性相同而放在一起,并不一定是同一種用途的內容。例如接著要講的輸入表、輸出表等就有可能和只讀常量一起被放在同一個區塊中,因為他們的屬性都是可讀不可寫的。

其次,由于不同用途的數據有可能被放入同一個區塊中,因此僅僅依靠區塊表是無法確定和定位的。那要怎么辦?對了,PE 文件頭中 IMAGE_OPTIONAL_DEADER32 結構的數據目錄表來指出他們的位置,我們可以由數據目錄表來定位的數據包括輸入表、輸出表、資源、重定位表和TLS等15 種數據。(數據目錄表,不要以為他在前邊出現就不重要哦~)

這節課我們談的是輸入表,為什么需要輸入表呢?因為我們從數據目錄表得到的僅僅是一些指定數據的RVA 和數據塊的尺寸,很明顯,不同的數據塊中的數據組織方式(結構)是顯然不同的,例如輸入表和資源數據塊中的數據就完全是牛馬不相及的兩個東西。因此,我們想要深入了解PE 文件就必須了解這些數據的組織方式,以及了解系統是如何處理調用它們的。

輸入函數

在代碼分析或編程中經常遇到“輸入函數(Import Functions,也稱導入函數)”的概念。這里我們就來解釋下,輸入函數就是被程序調用但其執行代碼又不在程序中的函數,這些函數的代碼位于相關的DLL 文件中,在調用者程序中只保留相關的函數信息(如函數名、DLL 文件名等)就可以。對于磁盤上的PE 文件來說,它無法得知這些輸入函數在內存中的地址,只有當PE 文件被裝入內存后,Windows 加載器才將相關DLL 裝入,并將調用輸入函數的指令和函數實際所處的地址聯系起來。這就是“動態鏈接”的概念。動態鏈接是通過PE 文件中定義的“輸入表”來完成的,輸入表中保存的正是函數名和其駐留的DLL 名等。


實例預演(視頻中將演示,這里只能截圖)

以上是咱這次實驗的小青蛙哈~灰常簡單的一個小程序,如圖雙擊程序只顯示一個對話窗口,然后就結束~試驗用小程序,我們盡量的將內部的結構刪減,調試起來才方便些。我們這次體驗的目的就是想靠所學的知識,試圖來找到MessageBox 在內存中的地址。
注:MessageBox 是來自于USER32.DLL 動態鏈接庫里的一個函數,我們通過對PE 文件的靜態反編譯分析來觀察hello.exe 這個試驗品是如何定位和調用MessageBox 這個在“異鄉”的函數哈。
(MessageBox 有兩個版本,一個是MessageBoxA 還有一個是MessageBoxW 分別帶便ASCII碼形式和UNICODE)

體驗開始:
1. 我們用曾經號稱為屠龍刀的W32DAM 對hello.exe進行反編譯,如圖:

我們可以看到這個程序只有兩個導入模塊(Import Module),分別導入來自兩個動態鏈接庫(USER32.DLL和KERNEL32.DLL)的若干函數,我們還清晰可見,咱要跟蹤的MessageBoxA 就在USER32.DLL 中,這里程序還自動給我們定位了它的虛擬地址:2A2DC,但我們不要用這個,因為我們說過這回我們是來探險的,凡事講究人工……

我們通過W32DASM 的查找功能找出MessageBox 這個函數代碼的位置,并試圖查看他的匯編跳轉~

push xxxx?? push xxxx?? push xxxx?? push xxxx 之后再來一個Call xxxx ……
沒錯,這就是調用函數的一個標準形式。每個push 其實就是將所要調用的函數需要的參數入棧,為啥要入棧呢?這又要從地球的起源說起了……我這里就簡單的說下吧:棧的發明,使得函數和子程序的出現成為可能!對于局部變量和參數,棧的特性最適合不過~不明白不急哈,這個是匯編語言和編譯原理的范疇了,以后咱學習深入自然會碰到,到時候再來詳細解決就可以。

int MessageBox( HWND?hWnd,?LPCTSTR?lpText,?LPCTSTR?lpCaption,?UINT?uType?// style of message box?);
由定義可見MessageBox 函數共有四個參數,因此我們四次push xxxx 分別將參數按照STDCALL 的方式入棧之后,就可以CALL MessageBox 這個函數了。好,既然是CALL 我們的目標函數了,通過反匯編我們就可以觀察到它的地址是:[0042A2AC],難道就這么簡單?42A2AC 就是目標函數的地址?

那我們就直接把程序往下拉,試圖找找這個 42A2AC 的地址吧~
可是…… ……

我們悲劇的發覺,程序壓根還沒到?42A2AC?這地方,到了421FF8 就結束了!!什么情況呢?
或許……或許……或許……在沒詳細講輸入表時我們還不能直接給大家答案……

好吧,這里提問一下,這是一個什么地址呢?偏移地址 or 虛擬地址?

恩,沒錯,這是一個VA 哈,那這個VA 上節課我們說過可以換算成存放在實際物理內存上的方法。具體就是將這個VA 與該程序的各個區塊的VA 地址逐一對比,由于PE 頭文件有記載每個區塊的VA 地址也同時記載著它的實際物理地址,因此我們可以通過判斷該VA 位于哪個區塊內并求出與區塊VA 的差值進而求出該VA 的實際物理地址。那既然前邊直直的路子走不通,我們就試下把他轉換為物理地址試試吧?!

我們看到,咱的42A2AC 地址加載咱的2A000 和 2B000 之間(改程序VC編寫,映像基地址為400000打頭哦~),因此我們可以將該地址定位到改程序位于.idata 區塊內。該區塊的VA 起始地址為42A000,因此42A2AC - 42A000 = 2AC,raw data offs 跟我們說該區塊的物理地址是28000,因此42A2AC 這個VA 所對應的物理偏移地址就是 28000 + 2AC = 282AC。

咱用UE 打開看下282AC 這偏移地址上有啥東西……

282AC 這個地址上存放著 DCA20200 這個數據,翻譯成ASCII 碼也是莫名其妙的說~
但我們把DCA20200 當成一個DWORD 類型的數據來讀的話我們得到數據 0002A2DC(還記得大端與小端吧)
慢著,是不是很熟悉,又是2A****開頭,跟咱之前的地址是不是差不多?那好,我們又按照剛才的方法轉化為偏移地址試試,轉化后得到的偏移地址是:282DC,咱再看看282DC 里邊有啥神秘的東西吧?

哈哈,看到奇跡了嗎?從282DC 地址讀起,ASCII 碼對應的值是MessageBoxA.USER32.dll?

?

輸入表結構

回顧一下,在 PE文件頭的 IMAGE_OPTIONAL_HEADER 結構中的 DataDirectory(數據目錄表) 的第二個成員就是指向輸入表的。而輸入表是以一個 IMAGE_IMPORT_DESCRIPTOR(簡稱IID) 的數組開始。每個被 PE文件鏈接進來的 DLL文件都分別對應一個 IID數組結構。在這個 IID數組中,并沒有指出有多少個項(就是沒有明確指明有多少個鏈接文件),但它最后是以一個全為NULL(0) 的 IID 作為結束的標志。
IMAGE_IMPORT_DESCRIPTOR 結構定義如下:

IMAGE_IMPORT_DESCRIPTOR STRUCT?

? ? union?

? ? ? ? Characteristics????????????? DWORD ? ??
? ? ? ? OriginalFirstThunk??????? DWORD ? ??

? ? ends?
? ? TimeDateStamp???????????????????? DWORD ? ??
? ? ForwarderChain???????????????? ? ? DWORD ? ??
? ? Name????????????????????????????? ? ? ? DWORD ? ??
? ? FirstThunk??????????? ? ? ? ? ? ? ? ? DWORD ? ?

IMAGE_IMPORT_DESCRIPTOR ENDS?

成員介紹:

OriginalFirstThunk
它指向first thunk,IMAGE_THUNK_DATA,該 thunk 擁有 Hint 和 Function name 的地址。

TimeDateStamp
該字段可以忽略。如果那里有綁定的話它包含時間/數據戳(time/data stamp)。如果它是0,就沒有綁定在被導入的DLL中發生。在最近,它被設置為0xFFFFFFFF以表示綁定發生。

ForwarderChain
一般情況下我們也可以忽略該字段。在老版的綁定中,它引用API的第一個forwarder chain(傳遞器鏈表)。它可被設置為0xFFFFFFFF以代表沒有forwarder。

Name
它表示DLL 名稱的相對虛地址(譯注:相對一個用null作為結束符的ASCII字符串的一個RVA,該字符串是該導入DLL文件的名稱,如:KERNEL32.DLL)。

FirstThunk
它包含由IMAGE_THUNK_DATA定義的 first thunk數組的虛地址,通過loader用函數虛地址初始化thunk。在Orignal First Thunk缺席下,它指向first thunk:Hints和The Function names的thunks。

這個OriginalFirstThunk 和?FirstThunk明顯是親家,兩家伙首先名字就差不多。那他們有什么不可告人的秘密呢?來,我們看下面一張圖(畫的很辛苦,大家仔細看哈):

我們看到:OriginalFirstThunk 和?FirstThunk 他們都是兩個類型為IMAGE_THUNK_DATA 的數組,它是一個指針大小的聯合(union)類型。每一個IMAGE_THUNK_DATA 結構定義一個導入函數信息(即指向結構為IMAGE_IMPORT_BY_NAME 的家伙,這家伙稍后再議),然后數組最后以一個內容為0 的 IMAGE_THUNK_DATA 結構作為結束標志。

我們得到?IMAGE_THUNK_DATA 結構的定義如下:
IMAGE_THUNK_DATA STRUC

union u1

? ? ?ForwarderString?????? DWORD? ?? ? ? ? ? ?; 指向一個轉向者字符串的RVA
? ? ?Function????????????????????? DWORD? ???????? ; 被輸入的函數的內存地址
? ? ?Ordinal?????????????????????? DWORD? ?? ? ? ? ?; 被輸入的API 的序數值
? ? ?AddressOfData???????? DWORD? ?? ? ? ? ? ?; 指向 IMAGE_IMPORT_BY_NAME

ends

IMAGE_THUNK_DATA ENDS

我們可以看出由于是union結構,所以IMAGE_THUNK_DATA 事實上是一個雙字大小。該結構在不同時候賦予不同的意義。

那我們怎么來區分何時是何意義呢?
規定如下:
當 IMAGE_THUNK_DATA 值的最高位為 1時,表示函數以序號方式輸入,這時候低 31位被看作一個函數序號。
當?IMAGE_THUNK_DATA 值的最高位為 0時,表示函數以字符串類型的函數名方式輸入,這時雙字的值是一個 RVA,指向一個 IMAGE_IMPORT_BY_NAME 結構。

好,那接著我們討論下指向的這個?IMAGE_IMPORT_BY_NAME 結構。IMAGE_IMPORT_BY_NAME 結構僅僅只有一個字型數據的大小,存有一個輸入函數的相關信息結構。其結構如下:

IMAGE_IMPORT_BY_NAME STRUCT

Hint??????? WORD??? ??
Name ? ?? BYTE????? ?

IMAGE_IMPORT_BY_NAME ENDS

結構中的 Hint 字段也表示函數的序號,不過這個字段是可選的,有些編譯器總是將它設置為 0,Name 字段定義了導入函數的名稱字符串,這是一個以 0 為結尾的字符串。

輸入地址表(IAT)

為什么由兩個并行的指針數組同時指向 IMAGE_IMPORT_BY_NAME 結構呢?第一個數組(由 OriginalFirstThunk 所指向)是單獨的一項,而且不能被改寫,我們前邊稱為 INT。第二個數組(由 FirstThunk 所指向)事實上是由 PE 裝載器重寫的。

好了,那么 PE 裝載器的核心操作時如何的呢?這里就給大家揭秘啦~
PE 裝載器首先搜索 OriginalFirstThunk ,找到之后加載程序迭代搜索數組中的每個指針,找到每個 IMAGE_IMPORT_BY_NAME 結構所指向的輸入函數的地址,然后加載器用函數真正入口地址來替代由 FirstThunk 數組中的一個入口,因此我們稱為輸入地址表(IAT)。所以,當我們的 PE 文件裝載內存后準備執行時,剛剛的圖就會轉化為下圖:

此時,輸入表中其他部分就不重要了,程序依靠 IAT 提供的函數地址就可正常運行。

?

實踐

靜態

OriginalFirstThunk? ? INT

輸入表地址為2A000

2A000為虛擬地址,28000為物理地址

?下圖就是導入表的地址。

2A15C-2A000+28000=2815C

2A2DC-2A000+28000=282DC,找到MessageBox函數

FirstThunk? IAT

2A2AC-2A000+28000=282AC

FirstThunk? IAT

?

動態

OriginalFirstThunk? ? INT

用LordPE jump full出動態的exe

win7 64位和win10上lordPE不好使,建議虛擬機XP上運行。

剩下的與靜態分析一樣方法。

注意一點:動態的虛擬地址與物理地址是一樣的。

總結

以上是生活随笔為你收集整理的22. PE结构-PE详解之输入表(导入表)、屠龙刀W32Dasm(静态)、LordPE(动态)工具入门(查找dll、调用函数)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 日本不卡一区在线 | 亚洲av成人无码一区二区三区在线观看 | 欧美高清视频一区二区 | 校园春色中文字幕 | 国产真实夫妇交换视频 | 自拍偷拍电影 | 久久b | 蜜臀在线视频 | 6680新视觉电影免费观看 | 亚洲一区成人 | 精品视频一区二区三区四区五区 | 在线观看色网 | 夜夜激情| 精品嫩模一区二区三区 | 大肉大捧一进一出好爽视频 | 一级肉体全黄裸片 | 欧美日韩精品电影 | 黄色一级带| 原来神马电影免费高清完整版动漫 | 欧美激情精品久久久久久免费 | 午夜免费观看 | 日韩精品一区二区三区无码专区 | 萌白酱一区二区 | 色姑娘久 | 久草免费看 | 日本黄色中文字幕 | 欧美性猛交xxxx乱大交俱乐部 | 中文字幕69| 激情综合五月网 | www..com黄色 | 男女无遮挡做爰猛烈视频 | 黑巨茎大战欧美白妞 | 香蕉视频成人在线 | 免费福利视频网站 | 国产一区二区三区四区hd | 香蕉视频性 | 国内自拍99 | 久草在现| 日本人添下边视频免费 | 国产一区二区在线观看免费 | 欧美一区二区人人喊爽 | 99国产精品久久久久久久 | 超碰人人擦 | 91免费小视频 | www.com色 | 成人在线播放网站 | 国产偷人妻精品一区 | 黄色成人小视频 | 打屁股疼的撕心裂肺的视频 | 在线免费观看日韩 | www.四虎. | 伊人久久一区二区 | 已满18岁免费观看电视连续剧 | 男性裸体全身精光gay | 欧美bbbbb | 看片一区二区 | 欧美精品在欧美一区二区少妇 | 精品人妻一区二区三区四区五区 | 中出亚洲 | 久久成人久久爱 | 免费毛片看 | 国产在线青青草 | 精品亚洲国产成av人片传媒 | 男人看的网站 | 亚洲图片另类小说 | 亚洲精品av中文字幕在线在线 | 欧美乱大交xxxxx潮喷 | 91蝌蚪91九色 | 处破痛哭a√18成年片免费 | www精品视频 | 亚洲天堂中文字幕 | 丰满少妇一级 | 欧美伊人久久 | 欧美日韩国产一级 | 动漫美女被到爽流 | 日韩av一级片 | 国产在线精品成人欧美 | 国产免费黄色网址 | www.男人的天堂 | 长篇乱肉合集乱500小说日本 | 18欧美性xxxx极品hd | 国产女主播在线观看 | 自拍偷拍p | 中文字幕视频在线播放 | 久久精品国产久精国产 | 国产精品视频在线观看免费 | 91精品国产电影 | 69xxx中国| 操碰av| 亚洲第一成人网站 | 午夜偷拍福利 | 中文在线永久免费观看 | 377p粉嫩大胆色噜噜噜 | 影音先锋亚洲天堂 | 人人妻人人澡人人爽人人精品 | 91大神一区二区 | 性色av一区二区三区红粉影视 | 日韩精品系列 | 91蜜桃传媒精品久久久一区二区 |