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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

PE文件结构详解(六)重定位

發布時間:2024/4/11 编程问答 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 PE文件结构详解(六)重定位 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

前面兩篇?PE文件結構詳解(四)PE導入表?和?PE文件結構詳解(五)延遲導入表?介紹了PE文件中比較常用的兩種導入方式,不知道大家有沒有注意到,在調用導入函數時系統生成的代碼是像下面這樣的:


在這里,IE的iexplorer.exe導入了Kernel32.dll的GetCommandLineA函數,可以看到這是個間接call,00401004這個地址的內存里保存了目的地址,根據圖中顯示的符號信息可知,00401004這個地址是存在于iexplorer.exe模塊中的,實際上也就是一項IAT的地址。這個是IE6的exe中的例子,當然在dll中如果導入其他dll中的函數,結果也是一樣的。這樣就有一個問題,代碼里call的地址是一個模塊內的地址,而且是一個VA,那么如果模塊基地址發生了變化,這個地址豈不是就無效了?這個問題如何解決?

答案是:Windows使用重定位機制保證以上代碼無論模塊加載到哪個基址都能正確被調用。聽起來很神奇,是怎么做到的呢?其實原理并不很復雜,這個過程分三步:

1.編譯的時候由編譯器識別出哪些項使用了模塊內的直接VA,比如push一個全局變量、函數地址,這些指令的操作數在模塊加載的時候就需要被重定位。

2.鏈接器生成PE文件的時候將編譯器識別的重定位的項紀錄在一張表里,這張表就是重定位表,保存在DataDirectory中,序號是?IMAGE_DIRECTORY_ENTRY_BASERELOC。

3.PE文件加載時,PE 加載器分析重定位表,將其中每一項按照現在的模塊基址進行重定位。

以上三步,前兩部涉及到了編譯和鏈接的知識,跟本文的關系不大,我們直接看第三步,這一步符合本系列的特征。

在查看重定位表的定義前,我們先了解一下他的存儲方式,有助于后面的理解。按照常規思路,每個重定位項應該是一個DWORD,里面保存需要重定位的RVA,這樣只需要簡單操作便能找到需要重定位的項。然而,Windows并沒有這樣設計,原因是這樣存放太占用空間了,試想一下,加入一個文件有n個重定位項,那么就需要占用4*n個字節。所以Windows采用了分組的方式,按照重定位項所在的頁面分組,每組保存一個頁面其實地址的RVA,頁內的每項重定位項使用一個WORD保存重定位項在頁內的偏移,這樣就大大縮小了重定位表的大小。

有了上面的概念,我們現在可以來看一下基址重定位表的定義了:

[cpp]?view plain?copy
  • typedef?struct?_IMAGE_BASE_RELOCATION?{??
  • ????DWORD???VirtualAddress;??
  • ????DWORD???SizeOfBlock;??
  • //??WORD????TypeOffset[1];??
  • }?IMAGE_BASE_RELOCATION;??
  • typedef?IMAGE_BASE_RELOCATION?UNALIGNED?*?PIMAGE_BASE_RELOCATION;??
  • VirtualAddress:頁起始地址RVA。

    SizeOfBlock:表示該分組保存了幾項重定位項。

    TypeOffset:這個域有兩個含義,大家都知道,頁內偏移用12位就可以表示,剩下的高4位用來表示重定位的類型。而事實上,Windows只用了一種類型IMAGE_REL_BASED_HIGHLOW ?數值是 3。

    好了,有了以上知識,相信大家可以很容易的寫出自己修正重定位表的代碼,不如自己做個練習驗證一下吧。

    本文?by evil.eagle 轉載的時候請注明出處。http://blog.csdn.net/evileagle/article/details/12886949

    最后,還是總結一下,哪些項目需要被重定位呢?

    1.代碼中使用全局變量的指令,因為全局變量一定是模塊內的地址,而且使用全局變量的語句在編譯后會產生一條引用全局變量基地址的指令。

    2.將模塊函數指針賦值給變量或作為參數傳遞,因為賦值或傳遞參數是會產生mov和push指令,這些指令需要直接地址。

    3.C++中的構造函數和析構函數賦值虛函數表指針,虛函數表中的每一項本身就是重定位項,為什么呢?大家自己考慮一下吧,不難哦~

    總結

    以上是生活随笔為你收集整理的PE文件结构详解(六)重定位的全部內容,希望文章能夠幫你解決所遇到的問題。

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