成為頂級黑客--彙編與反彙編(五)--重點內存轉文件偏移的原理

再解釋下內存轉文件偏移的原理。(因為RVA是病毒感染的關鍵字段)

  • 計算RVA 公式: x - ImageBase == RVA
  • 計算差值偏移. RVA - 節.VirtualAddress == 差值偏移.
  • 計算FOA 差值偏移 + 節.PointerToRawData == FOA

PE 中涉及的地址有四類,它們分別是:

  • 虛擬內存地址(VA)
  • 相對虛擬內存地址(RVA)
  • 文件偏移地址(FOA)
  • 特殊地址

原因

成為頂級黑客--彙編與反彙編(五)--重點內存轉文件偏移的原理

當一個PE文件被加載到內存中以後,我們稱之為“映象”(image),一般來說,PE文件在硬盤上和在內存裡是不完全一樣的,被加載到內存以後其佔用的虛擬地址空間要比在硬盤上佔用的空間大一些,這是因為各個節在硬盤上是連續的,而在內存中是按頁對齊的,所以加載到內存以後節之間會出現一些“空洞”。

因為存在這種對齊,所以在PE結構內部,表示某個位置的地址採用了兩種方式,針對在硬盤上存儲文件中的地址,稱為原始存儲地址或物理地址表示距離文件頭的偏移;另外一種是針對加載到內存以後映象中的地址,稱為相對虛擬地址(RVA),表示相對內存映象頭的偏移。

然而CPU的某些指令是需要使用絕對地址的,比如取全局變量的地址,傳遞函數的地址編譯以後的彙編指令中肯定需要用到絕對地址而不是相對映象頭的偏移,因此PE文件會建議操作系統將其加載到某個內存地址(這個叫基地址),編譯器便根據這個地址求出代碼中一些全局變量和函數的地址,並將這些地址用到對應的指令中。這種表示方式叫做虛擬地址(VA)。

區塊

在區塊表 後面的就是一個一個區塊,每個區塊佔用對齊值的整數倍,一般的文件都有代碼塊 跟 數據塊( 它們的名字一般為.text 跟 .data 但這是可以修改的)。每個區塊的數據具有相同的屬性。編譯器先在obj中生成不同的區塊, 鏈接器再按照一定的規則合併不同obj跟庫中的快。例如每個obj中肯定有.text 塊, 連接器就會把它們合併成一個單一的.text 塊;再如,如果兩個區塊具有相同的的屬性就有可能被合併成一個塊。(參考section表來理解)

PE文件頭裡的幾個重要信息

我在010 Editor裡操作的。

入口點地址:

展開struct IMAGE_NT_HEADERS NtHeader,再展開struct IMAGE_OPTIONAL_HEADER32 OptionalHeader,DWORD AddressOfEntryPoint即為所得。這個對應的就是PE文件頭地址。我這個插圖後面就不插圖了,主要是怎麼找到這個字段。

成為頂級黑客--彙編與反彙編(五)--重點內存轉文件偏移的原理

入口點地址

基地址(這個要計算VA RVA+基地址=VA):

點擊展開struct IMAGE_NT_HEADERS NtHeader,再點擊展開struct IMAGE_OPTIONAL_HEADER32 OptionalHeader,DWORD ImageBase即為所得。

.text節的VA(節內VA)

點擊展開struct IMAGE_SECTION_HEADER SectionHeaders[4],點擊展開struct IMAGE_SECTION_HEADER SectionHeaders[0],DWORD VirtualAddress即為所得。

.text節的文件偏移(這個每個節也不同,與每個節的VA相關)

點擊展開struct IMAGE_SECTION_HEADER SectionHeaders[4],點擊展開struct IMAGE_SECTION_HEADER SectionHeaders[0],DWORD PointerToRawData即為所得。

VA RVA FOA實例計算

寫這麼詳細還看不懂,可以選擇別的方向了,因為改PE文件理解在哪個地址添加內容這個是基礎。我就用舉例子就用常用的kernel32.dll,它的版本可以從它的字段time_t TimeDateStamp03/21/2009 14:06:57(49C4F481h) ,時間戳是從01/01/1970 12:00 AM開始計數的。

  • 首先你先要找出你想查看的字段的RVA,比如我現在想看struct IMAGE_EXPORT_DIRECTORY ExportDir中的DWORD Name字段,我們在16進製表示看出他是00004B98h這就是它的RVA。
成為頂級黑客--彙編與反彙編(五)--重點內存轉文件偏移的原理

RVA的表示

  • 我們再找出基地址,這個在上面介紹過了,然後找出來為7C800000h,所以我們可以計算出這個Name字段的VA為 : VA = RVA + ImageBase 即 7C804B98h = 00004B98h + 7C800000h;
成為頂級黑客--彙編與反彙編(五)--重點內存轉文件偏移的原理

ImageBase

  • 我們再計算FOA,首先它是一個.text字段,所以我們需要找到.text的片內上面介紹的兩個信息。我們可以發現DWORD VirtualAddress為00001000h,DWORD PointerToRawData為00000400h.帶入公式 RVA -.section. VirtualAddress+section.PointerToRawData =FOA 、

即 00004B98h - 00001000h + 00000400h = 00003F98h

成為頂級黑客--彙編與反彙編(五)--重點內存轉文件偏移的原理

section.VirtualAddress和section.PointerToRawData

  • 找出FOA了,我們再去尋找它指代的信息。找到00003F98,我們發現十六制內容為4B 45 52 4E 45 4C 33 32 2E 64 6C 6C,查看後面的翻譯.為KERNEL32.dll
成為頂級黑客--彙編與反彙編(五)--重點內存轉文件偏移的原理

我們需要的內容,KERNEL32.dll

FOA的話,其實用LORDPE的文件地址計算器和0101 EDITOR都能直接看出來,但是自己會求解了,就會加深理解。


分享到:


相關文章: