一区二区三区日韩精品-日韩经典一区二区三区-五月激情综合丁香婷婷-欧美精品中文字幕专区

分享

深度探索win32可執(zhí)行文件格式

 ShaneWu 2010-01-13

深度探索win32可執(zhí)行文件格式

Matt Pietrek    翻譯:姜慶東

 

 

 

 摘要: 對可執(zhí)行文件的深入認識將帶你深入到系統(tǒng)深處。如果你知道你的exe/dll 里是些什么東東,你就是一個更有知識的程序員。作為系列文章的第一章,將關(guān)注這幾年來PE格式的變化,同時也簡單介紹一下PE格式。經(jīng)過這次更新,作者加 入了PE格式是如何與.NET協(xié)作的及PE文件表格(PE FILE SECTIONS),RVA,The DataDirectory,函數(shù)的輸入等內(nèi)容。

 

                                

很久以前,我給Microsoft Systems Journal(現(xiàn)在的MSDN寫了一篇名為“Peering Inside the PE: A Tour of the Win32 Portable Executable File Format, “的文章,后來比我期望的還流行,到現(xiàn)在我還聽說有人在用它(它還在MSDN里)。不幸的是,那篇文章的問題依舊存在,WIN32的世界靜悄悄地變了好多,那篇文章已顯得過期了。從這個月開始我將用這兩篇文章來彌補。

你可能會問為什么我應(yīng)當(dāng)了解PE格式,答案依舊:操作系統(tǒng)的可執(zhí)行文件格式和數(shù)據(jù)結(jié)構(gòu)暴露出系統(tǒng)的底層細節(jié)。通過了解這些,你的程序?qū)⒕幍母錾?/span>

當(dāng)然,你可以閱讀微軟的文檔來了解我將要告訴你的。但是,像很多文檔一樣,‘寧可晦澀,但為瓦全‘。

我把焦點放在提供一些不適合放在正式文檔里的內(nèi)容。另外,這篇文章里的一些知識不見得能在官方文檔里找到。

1.       裂縫的撕開。

讓我給你一些從1994年我寫那篇文章來PE格式變化的例子。WIN16已經(jīng)成為歷史,也就沒有必要作什么比較和說明了。另外一個可憎的東西就是用在WINDOWS 3.1 中的WIN32S,在它上面運行程序是那么的不穩(wěn)定。

那時候,WINDOWS 95 (也叫Chicago)還沒有發(fā)行。NT還是3.5版。微軟的連接器還沒開始大規(guī)模的優(yōu)化,盡管如此,there were MIPS and DEC Alpha implementations of Windows NT that added to the story.

那么究竟,這么些年來,有些什么新的東西出來呢?64位的WINDOWS有了它自己的PE變種,WINDOWS CE 支持各種CPU了,各種優(yōu)化如DLL的延遲載入,節(jié)表的合并,動態(tài)捆綁等也已出臺。

有很多類似的東西發(fā)生了。

       讓我們最好忘了。NET。它是如何與系統(tǒng)切入的呢?對于操作系統(tǒng),.NET的可執(zhí)行文件格式是與舊的PE格式兼容的。雖然這么說,在運行時期,.NET還是按元數(shù)據(jù)和中間語言來組織數(shù)據(jù)的,這畢竟是它的核心。這篇文章當(dāng)中,我將打開.NET元數(shù)據(jù)這扇門,但不做深入討論。

如果WIN32的這些變化都不足以讓我重寫這篇文章,就是原來的那些錯誤也讓我汗顏。比如我對TLS的描述只是一帶而過,我對時間戳的描述只有你生活在美國西部才行等等。還有,一些東西已是今是作非了,我曾說過.RDATA幾乎沒排上用場,今天也是,我還說過.IDATA節(jié)是可讀可寫的,但是一些搞API攔截的人發(fā)現(xiàn)好像是錯的。

在更新這篇文章的過程當(dāng)中,我也檢查了PEDUMP這個用來傾印PE文件的程序.這個程序能夠在0X86IA-64平臺下編譯和運行。

2.       PE 格式概覽

微軟的可執(zhí)行文件格式,也就是大家熟悉的PE 格式,是官方文檔的一部分。但是,它是從VAX/VMS上的COFF派生出來的,就WINDOWS NT小組的大部分是從DEC轉(zhuǎn)過來的看來,這是可以理解的。很自然,這些人在NT的開發(fā)上會用他們以往的代碼。

采用術(shù)語’PORTABLE EXECUTABLE’是因為微軟希望有一個通用在所有WINDOWS平臺上和所有CPU上的文件格式。從大的方面講,這個目標(biāo)已經(jīng)實現(xiàn)。它適用于NT及其后代,95及其后代,和CE.

微軟產(chǎn)生的OBJ文件是用COFF格式的。當(dāng)你看到它的很多域都是用八進制的編碼的,你會發(fā)現(xiàn)她是多么古老了。COFF OBJ文件用到了很多和PE一樣的數(shù)據(jù)結(jié)構(gòu)和枚舉,我馬上會提到一些。

64位的WINDOWS只對PE格式作了一點點改變。這個新的格式叫做PE32+.沒有增加一個字段,且只刪了一個字段。其他的改變就是把以前的32位字段擴展成64位。對于C++代碼,通過宏定義WINDOWS的頭文件已經(jīng)屏蔽了這些差別。

EXE與DLL的差別完全是語義上的。它們用的都是同樣一種文件格式-PE。唯一的區(qū)別就是其中有一個字段標(biāo)識出是EXE還是DLL.還有很多DLL的擴展比如OCX,CPL等都是DLL.它們有一樣的實體。

你首先要知道的關(guān)于PE 的知識就是磁盤中的數(shù)據(jù)結(jié)構(gòu)布局和內(nèi)存中的數(shù)據(jù)結(jié)構(gòu)布局是一樣的。載入可執(zhí)行文件(比如LOADLIBARY)的首要任務(wù)就是把磁盤中的文件映射到進程的 地址空間.因此像IMAGE_NT_HEADER(下面解釋)在磁盤和內(nèi)存中是一樣的。關(guān)鍵的是你要懂得你怎樣在磁盤中獲得PE文件某些信息的,當(dāng)它載入 內(nèi)存時你可以一樣獲得,基本上是沒什么不同的(即內(nèi)存映射文件)。但是知道與映射普通的內(nèi)存映射文件不同是很重要的。WINDOWS載入器察看PE文件才 決定映射到哪里,然后從文件的開始處往更高的地址映射,但是有的東西在文件中的偏移和在內(nèi)存中的偏移會不一樣。盡管如此,你也有了足夠的信息把文件偏移轉(zhuǎn) 化成內(nèi)存偏移。見圖1

Figure 1 offsets
Figure 1 Offsets

 

  當(dāng) windows載入器把PE載入內(nèi)存,在內(nèi)存中它稱作模塊(MODULE),文件從HMODULE這個地址開始映射。記住這點:給你個HMODULE,從 那你可以知道一個數(shù)據(jù)結(jié)構(gòu)(IMAGE_DOS_HEADER),然后你還可以知道所有得數(shù)據(jù)結(jié)構(gòu)。這個強大的功能對于API攔截特別有意義。(準(zhǔn)確地 說:對于WINDOWS CE,這是不成立的,不過這是后話)。

  內(nèi) 存中的模塊代表著進程從這個可執(zhí)行文件中所需要的所有代碼,數(shù)據(jù),資源。其他部分可以被讀入,但是可能不映射(如,重定位節(jié))。還有一些部分根本就不映 射,比如當(dāng)調(diào)試信息放到文件的尾部的時候。有一個字段告訴系統(tǒng)把文件映射到內(nèi)存需要多少內(nèi)存。不需要的數(shù)據(jù)放在文件的尾部,而在過去,所有部分都映射。

  在WINNT.H描述了PE 格式。在這個文件中,幾乎有所有的關(guān)于PE的數(shù)據(jù)結(jié)構(gòu),枚舉,#DEFINE。當(dāng)然,其它地方也有相關(guān)文檔,但是還是WINNT.H說了算。

  有 很多檢測PE文件的工具,有VISUAL STUDIO的DUMPBIN,SDK中的DEPENDS,我比較喜歡DEPENDS,因為它以一種簡潔的方式檢測出文件的引入引出。一個免費的PE察看 器,PEBrowse,來自smidgenosoft。我的pedump也是很有用的,它和dumpbin有一樣的功能。

  從api的立場看,imagehlp.dll提供了讀寫pe文件的機制。

  在開始討論pe文件前,回顧一下pe文件的一些基本概念是有意義的。在下面幾節(jié),我將討論:pe 節(jié),相對虛擬地址(rva),數(shù)據(jù)目錄,函數(shù)的引入。

 

3.       PE節(jié)

PE節(jié)以某鐘順序表示代碼或數(shù)據(jù),代碼就是代碼了,但是卻有多種類型的數(shù)據(jù),可讀寫的程序數(shù)據(jù)(如全局變量),其它的節(jié)包含API的引入引出表,資源,重定位。每個節(jié)有自己的屬性,包括是否是代碼節(jié),是否只讀還是可讀可寫,節(jié)的數(shù)據(jù)是否全局共享。

通常,節(jié)中的數(shù)據(jù)邏輯上是關(guān)聯(lián)的。PE文件一般至少要有兩個節(jié),一個是代碼,另一個為數(shù)據(jù),一般還有一個其它類型的數(shù)據(jù)的節(jié)。后面我將描述各種類型的節(jié)。

每個節(jié)都有一個獨特的名字。這個名字是用來傳達這個節(jié)的用途的。比如,.RDATA表示一個只讀節(jié),節(jié)的名字對于操作系統(tǒng)毫無意義,只是為了人們便于理解。把一個節(jié)命名為FOOBAR和.TEXT是一樣有用的。微軟給他們的節(jié)命名了個有特色的名字,但是這不是必需的。Borland的連接器用的是code和data。

一般編譯器將產(chǎn)生一系列標(biāo)準(zhǔn)的節(jié),但這沒有什么不可思議的。你可以建立和命名自己的節(jié),連接器會自動在程序文件中包含它們。在visual c++中,你能用#pragma指令讓編譯器插入數(shù)據(jù)到一個節(jié)中。像下面這樣:

#pragma data_seg( "MY_DATA" )
。。。有必要初始化
#pragma data_seg()

你也可以對.data做同樣的事。大部分的程序都只用編譯器產(chǎn)生的節(jié),但是有時候你卻需要這樣。比如建立一個全局共享節(jié)。

   節(jié) 并不是全部由連接器確定的,他們可以在編譯階段由編譯器放入obj文件。連接器的工作就是合并所有obj和庫中需要的節(jié)成一個最終的合適的節(jié)。比如,你的 工程中的所有obj可能都有一個包含代碼的.text節(jié),連接器把這些節(jié)合并成一個.text節(jié)。同樣對于.data等;這些主題超出了這篇文章的范圍 了。還有更多的規(guī)則關(guān)于連接器的。在obj文件中是專門給linker用的,并不放入到pe文件中,這種節(jié)是用來給連接器傳遞信息的。

   節(jié) 有兩個關(guān)于對齊的字段,一個對應(yīng)磁盤文件,另一個對應(yīng)內(nèi)存中的文件。Pe文件頭指出了這兩個值,他們可以不一樣。每個節(jié)的偏移從對齊值的倍數(shù)開始,比如, 典型的對齊值時0x200,那么每個節(jié)的的偏移必須是0x200的倍數(shù)。一旦載入內(nèi)存,節(jié)的起始地址總是以頁對齊。X86cpu的頁大小為4k,al- 64為8k

下面是pedump傾印出的Windows XP KERNEL32.DLL..text .data節(jié)的信息:

Section Table
  01 .text     VirtSize: 00074658  VirtAddr:  00001000
    raw data offs:   00000400  raw data size: 00074800
•••
  02 .data     VirtSize: 000028CA  VirtAddr:  00076000
    raw data offs:   00074C00  raw data size: 00002400

建立一個節(jié)在文件中的偏移和它相對于載入地址的偏移相同的pe文件是可能的。在98/me中,這會加速大

文件的載入。Visual studio 6.0 的默認選項 /opt:win98j就是這樣產(chǎn)生文件的。在Visual studio.net中是否用/opt:nowin98取決于文件是否夠小。

  一個有趣的連接器特征是合并節(jié)的能力。如果兩個節(jié)有相似兼容的屬性,連接的時候就可以合并為一個節(jié)。這取決于是否用/merger開關(guān)。像下面就把.rdata和.text合并為一個節(jié).text

  /MERGE:.rdata=.text

合并節(jié)的優(yōu)點就是對于磁盤和內(nèi)存節(jié)省空間。每個節(jié)至少占用一頁內(nèi)存,如果你可以把可執(zhí)行文件的節(jié)數(shù)從4減到3,很可能就可以少用一頁內(nèi)存。當(dāng)然,這取決于兩個節(jié)的空余空間加起來是否達到一頁。

   當(dāng)你合并節(jié)事情會變得有意思,因為這沒有什么硬性和容易的規(guī)則。比如你可以合并.rdata到.text,

但是你不可以把.rsrc.reloc.pdata合并到別的節(jié)。先前Visual Studio .NET允許把.idata合并,后來又不允許了。但是當(dāng)發(fā)行的時候,連接器還是可以把.idata合并到別的節(jié)。

   因為引入節(jié)的一部分在載入器載入事將被寫入,你可能驚奇它是如何被放入一個只讀節(jié)的。是這樣的,在載入的時候系統(tǒng)會臨時改變那些包含引入節(jié)的頁為可讀可寫,初始化完成后,又恢復(fù)原來屬性。

 

4.       相對虛擬地址

在可執(zhí)行文件中,有很多地方需要指定內(nèi)存地址,比如,引用全局變量時,需要指定它的地址。Pe文件盡管有一個首選的載入地址,但是他們可以載入到進程空間的任何地方,所以你不能依賴于pe的載入點。由于這點,必須有一個方法來指定地址而不依賴于pe載入點的地址。為了避免把內(nèi)存地址硬編碼進pe文件,  提出了RVA。RVA是一個簡單的相對于PE載入點的內(nèi)存偏移。比如,PE載入點為0X400000,那么代碼節(jié)中的地址0X401000RVA

(target address) 0x401000 - (load address)0x400000  = (RVA)0x1000.

RVA加上PE的載入點的實際地址就可以把RVA轉(zhuǎn)化實際地址。順便說一下,按PE的說法,內(nèi)存中的實際地址稱為VA(VIRTUAL ADDRESS).不要忘了早點我說的PE的載入點就是HMODULE

想對探索內(nèi)存中的任意DLL?G      etModuleHanle(LPCTSTR)取得載入點,用你的PE知識來干活吧

 

5.       數(shù)據(jù)目錄

PE文件中有很多數(shù)據(jù)結(jié)構(gòu)需要快速定位,顯然的例子有,引入函數(shù),引出函數(shù),資源,重定位。這些東西是以一致的方式來定位的,這就是數(shù)據(jù)目錄。

  數(shù)據(jù)目錄是一個結(jié)構(gòu)數(shù)組,包含16個結(jié)構(gòu)。每個元素有一個定義好的標(biāo)識,如下:

// Export Directory

#define IMAGE_DIRECTORY_ENTRY_EXPORT         0

// Import Directory

#define IMAGE_DIRECTORY_ENTRY_IMPORT         1

// Resource Directory

#define IMAGE_DIRECTORY_ENTRY_RESOURCE       2

// Exception Directory

#define IMAGE_DIRECTORY_ENTRY_EXCEPTION      3

// Security Directory

#define IMAGE_DIRECTORY_ENTRY_SECURITY       4

// Base Relocation Table

#define IMAGE_DIRECTORY_ENTRY_BASERELOC      5

// Debug Directory

#define IMAGE_DIRECTORY_ENTRY_DEBUG          6

// Description String

#define IMAGE_DIRECTORY_ENTRY_COPYRIGHT      7

// Machine Value (MIPS GP)

#define IMAGE_DIRECTORY_ENTRY_GLOBALPTR      8

// TLS Directory

#define IMAGE_DIRECTORY_ENTRY_TLS            9

// Load Configuration Directory

#define IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG    10

typedef struct _IMAGE_DATA_DIRECTORY {

    ULONG   VirtualAddress;

    ULONG   Size;

} IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY;

6.       引入函數(shù)

當(dāng)你使用別的DLL中的代碼或數(shù)據(jù),稱為引入。當(dāng)PE載入時,載入器的工作之一就是定位所有引入函數(shù)及數(shù)據(jù),使那些地址對于載入的PE可見。具體細節(jié)在后面討論,在這里只是大概講一下。

  當(dāng)你用到了一個DLL中的代碼或數(shù)據(jù),你就暗中連接到這個DLL。但是你不必為把這些地址變得對你的代碼有效做任何事情,載入器為你做這些。方法之一就是顯式連接,這樣你就要確定DLL已被載入,及函數(shù)的地址。調(diào)用LOADLIBARYGETPROCADDRESS就可以了。

  當(dāng)你暗式連接DLL,LOADLIBARYGETPROCADDRESS同樣還是執(zhí)行了的。只不過載入器為你做了這些。載入器還保證PE文件所需得任何附加的DLL都已被載入。比如,當(dāng)你連接了KERNEL32.DLL,而它又引入了NTDLL.DLL的函數(shù),又比如當(dāng)你連接了GDI32.DLL,而它又依賴于USER32, ADVAPI32, NTDLL, KERNEL32 DLLs的函數(shù),載入器會保證這些DLL被載入及函數(shù)的決議。

   暗式連接時,決議過程在PE文件在載入時就發(fā)生了。如果這時有什么問題(比如這個DLL文件找不到),進程終止。

  VISUAL C++ 6.0 加入了DLL的延遲載入的特征。它是暗式連接和顯式連接的混合。當(dāng)你延遲載入DLL,連接器做出一些和引入標(biāo)準(zhǔn)規(guī)則DLL類似的東西,但是操作系統(tǒng)卻不管這些東西,而是在第一次調(diào)用這個DLL中的函數(shù)的時候載入(如果還沒載入),然后調(diào)用GetProcAddress取得函數(shù)的地址。

  對于pe文件要引入的dll都有一個對應(yīng)的結(jié)構(gòu)數(shù)組,每個結(jié)構(gòu)指出這個dll的名字及指向一個函數(shù)指針數(shù)組的指針,這個函數(shù)指針數(shù)組就是所謂的IATIMORT ADDRESS TABLE.每個輸入函數(shù),在IAT中都有一個保留槽,載入器將在那里寫入真正的函數(shù)地址。最后特別重要一點的是:模塊一旦載入,IAT中包含所要調(diào)用的引入函數(shù)的地址。

  把所有輸入函數(shù)放在IAT一個地方是很有意義的,這樣無論代碼中多少次調(diào)用一個引入函數(shù),都是通過IAT中的一個函數(shù)指針。

   讓我們看看是怎樣調(diào)用一個引入函數(shù)的。有兩種情況需要考慮:有效率的和效率差的。最好的情況

   像下面這樣:

     CALL DWORD PTR [0x00405030]

直接調(diào)用[0x405030]中的函數(shù),0x405030位于IAT部分。效率差的方式如下:

CALL 0x0040100C

•••

0x0040100C:

JMP       DWORD PTR [0x00405030]

 這種情況,CALL把控制權(quán)轉(zhuǎn)到一個子程序,子程序中的JMP指令跳轉(zhuǎn)到位于IAT中的0x00405030,簡單說,它多用了5字節(jié)和JMP多花的時間。

 你可能驚訝引入函數(shù)就采用了這種方式,有個很好的解釋,編譯器無法區(qū)別引入函數(shù)的調(diào)用和普通函數(shù)調(diào)用,對于每個函數(shù)調(diào)用,編譯器只產(chǎn)生如下指令:

  CALL XXXXXXXX

XXXXXXXX是一個由連接器填入的RVA,注意,這條指令不是通過函數(shù)指針來的,而是代碼中的實際地址。

為了因果的平衡,連接器必須產(chǎn)生一塊代碼來代替去代XXXXXXXX,簡單的方法就是象上面所示調(diào)用一個JMP STUB.

 那么JMP STUB 從那里來呢?令人驚異的是,它取自輸入函數(shù)的引入庫。如果你去察看一個引入庫,在輸入函數(shù)名字的關(guān)聯(lián)處,你會發(fā)現(xiàn)與上面JMP STUB相似的指令。

  接著,另一個問題就是如何優(yōu)化這種形式,答案是你給編譯器的修飾符,__declspec(import) 修飾符告訴編譯器,這個函數(shù)來自另一個dll,這樣編譯器就會產(chǎn)生第一種指令。

  另外,編譯器將給函數(shù)加上__imp_前綴然后送給連接器決議,這樣可以直接把__imp_xxx送到iat,就不需要jmp stub了。

  對于我們這有什么意義呢,如果你在寫一個引出函數(shù)的東西并提供一個頭文件的話,別忘了在函數(shù)前加上修飾符__declspec(import)

  __declspec(dllimport) void Foo(void);

winnt.h等系統(tǒng)頭文件中就是這樣做的。

 

7.       PE 文件結(jié)構(gòu)

  現(xiàn)在讓我們開始研究PE文件格式,我將從文件的頭部開始,描述每個PE文件中都有的各種數(shù)據(jù)結(jié)構(gòu),然后,我將討論更多的專門的數(shù)據(jù)結(jié)構(gòu)比如引入表和資源,除非特殊說明,這些結(jié)構(gòu)都定義在WINNT.H中。

  一般地,這些結(jié)構(gòu)都有32和64位之分,如IMAGE_NT_HEADERS32 ,IMAGE_NT_HEADER64等,他們基本上是一樣的,除了64位的擴展了某些字段。通過#DEFINE  WINNT.H都屏蔽了這些區(qū)別,選擇那個數(shù)據(jù)結(jié)構(gòu)取決于你要如何編譯了(如,是否定義_WIN64)

The MS-DOS Header

每個PE文件是以一個DOS程序開始的,這讓人想起WINDOWS在沒有如此可觀的使用者的早期年代。當(dāng)可執(zhí)行文件在非WINDOWS平臺上運行的時候至少可以顯示出一條信息表示它需要WINDOWS。

PE文件的開頭是一個IMAGE_DOS_HEADER結(jié)構(gòu),結(jié)構(gòu)中只有兩個重要的字段e_magic and e_lfanew;e_lfanew指出pe file header 的偏移,e_magic需要設(shè)定位0x5a4d,被#define 成IMAGE_DOS_SIGNATURE  它的ascii’MZ’, Mark Zbikowski   首字母,DOS 的原始構(gòu)建者之一。

 

The IMAGE_NT_HEADERS Header

          這個結(jié)構(gòu)是PE文件的主要定位信息的所在。它的偏移由IMAGE_DOS_HEADERe_lfanew給出

確實有64和32位之分,但我在討論中將不作考慮,他們幾乎沒有區(qū)別。

    typedef struct _IMAGE_NT_HEADERS {

    DWORD Signature;

    IMAGE_FILE_HEADER FileHeader;

IMAGE_OPTIONAL_HEADER32 OptionalHeader;

} IMAGE_NT_HEADERS32, *PIMAGE_NT_HEADERS32;

 

一個有效的pe文件里,Signture被設(shè)為0x00004500,ascii 為’PE00’,#define IMAGE_NT_SIGNTURE  0X00004500; 第二個字段是一個IMAGE_FILE_HEADER結(jié)構(gòu),它包含文件的基本信息,特別重要的是它指出了IMAGE_OPTIONAL_HEADER的大 ?。ㄖ匾獑??);在PE文件中,IMAGE_OPTIONAL_HEADER是非常重要的,但是仍稱作IMAGE_OPTIONAL_HEADER。

IMAGE_OPTIONAL_HEADER結(jié)構(gòu)的末尾就是用來定位pe文件中重要信息的地址簿-數(shù)據(jù)目錄,它的定義如下:

typedef struct _IMAGE_DATA_DIRECTORY {

    DWORD   VirtualAddress;     // RVA of the data

    DWORD   Size;               // Size of the data

};

 

The Section Table

 

   緊接著IMAGE_NT_HEADERS后的就是節(jié)表,節(jié)表就是IMAGE_SECTION_HEADER的數(shù)組。IMAGE_SECTION_HEADER包含了它所關(guān)聯(lián)的節(jié)的信息,如位置,長度,特征;該數(shù)組的數(shù)目由IMAGE_NT_HEADERS.FileHeader.NumberOfSections指出。具體見下圖

 

PE中的節(jié)的大小的總和最后是要對齊的,Visual Studio 6.0中的默認值是4k,除非你使用/OPT:NOWIN98 /ALIGN開關(guān);在.NET中,依然用了默認的/OPT:WIN98,但是如果文件小于一特定大小時,就會采用0X200為對齊值。

  .NET文檔中有關(guān)于對齊的另一件有趣的事。.NET文件的內(nèi)存對齊值為8K而不是普通X86平臺上的4K,這樣就保證了在X86平臺編譯的程序可以在IA-64平臺上運行。如果內(nèi)存對齊值為4K,那么IA-64的載入器就不能載入這個程序,因為它的頁為8K.

 

 

                                 

 

這部分將討論:引出節(jié),引出推進,綁定,延遲載入,調(diào)試信息,線程局部存儲,資源節(jié)。

考慮到這部分對某些東西的討論不夠深入,譯者將參考別的資料作一些補充。

The Exports Section

   待續(xù) 

對不起大家,工作很忙,這是以前學(xué)PE的時候翻譯的一篇文章,我現(xiàn)在都覺得不堪入目,難為大家了。下一篇可能要等很久了,建議大家直接看E文。為了感謝大家的厚愛,我貼一篇關(guān)于PE的vir的C代碼,網(wǎng)上大多是ASM的吧  

http://www.csdn.net/Develop/read_article.asp?id=17437

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多

    狠狠做深爱婷婷久久综合| 日韩不卡一区二区三区色图| 午夜福利精品视频视频 | 久久福利视频在线观看| 丰满少妇被猛烈撞击在线视频 | 国产欧美日韩不卡在线视频| 丝袜av一区二区三区四区五区| 好吊妞视频免费在线观看| 日本一本不卡免费视频| 国产专区亚洲专区久久| 日韩人妻欧美一区二区久久| 日韩精品一级一区二区| 久久国产亚洲精品成人| 日韩一区中文免费视频| 欧洲一区二区三区自拍天堂| 国产精品福利精品福利| 高中女厕偷拍一区二区三区| 国产精品欧美一级免费| 久久精品视频就在久久| 99国产成人免费一区二区| 久久夜色精品国产高清不卡| 亚洲男人的天堂就去爱| 深夜日本福利在线观看| 欧美三级不卡在线观线看| 丰满人妻一二三区av| 九九热在线视频精品免费| 日本精品中文字幕人妻| 97人妻精品一区二区三区男同| 激情五月综五月综合网| 日本国产欧美精品视频| 爱在午夜降临前在线观看| 久久99午夜福利视频| 韩国日本欧美国产三级| 福利视频一区二区在线| 在线中文字幕亚洲欧美一区| 手机在线不卡国产视频| 欧美激情一区二区亚洲专区| 亚洲欧美国产精品一区二区| 色欧美一区二区三区在线| 亚洲一区二区三区日韩91| 99日韩在线视频精品免费|