根據函數名稱導出函數
- RVA(相對虛擬地址)和VA(虛擬地址)的關係
- VA = RVA + DOS頭地址(模塊基地址)
- 相關的RVA
- IMAGE_DOS_HEADER結構體中的e_lfanew(LONG),指向NT頭
- NT頭中IMAGE_OPTIONAL_HEADER中的IMAGE_DATA_DIRECTORY結構體數組中的RVA
- ExportTable中的三個RVA,AddressOfFunctions,AddressOfNames和AddressOfOrfinals
- 另外,AddressOfFunction這個RVA所指向的內容還是RVA表。每個RVA都指向一個函數
- AddressOfNames所指的還是RVA數組,這些數組中每個數都是一個字符串的首地址RVA
- 需要注意的是,AddressOfOrdinals指向的是 WORD 寬度的數組
- 各種RVA數據寬度
- LONG e_lfanes
- DWORD DATA_DIRECTORY中的VirtualAddress
- DWORD AddressOfFunctions
- DWORD AddressOfNames
- DWORD AddressOfOrfinals
- DWORD AddressOfFunctions[]
- DWORD AddressOfNames[]
- WORD AddressOfOrfinals[]
根據名稱導出函數的步驟
- 獲取模塊首地址,首地址也是DOS頭首地址
- 根據DOS頭中的e_lfanew(RVA,因爲PE頭映射到內存中後和exe文件中是一樣的,所以這個地址也是File Address,即lfa這個前綴)定位到NT頭
根據NT頭中是一個特徵碼兩個結構體
typedef struct _IMAGE_NT_HEADERS { DWORD Signature; //The bytes are "PE\0\0". IMAGE_FILE_HEADER FileHeader; IMAGE_OPTIONAL_HEADER32 OptionalHeader; } IMAGE_NT_HEADERS32, *PIMAGE_NT_HEADERS32;
這時需要OptionalHeader中的內容。OptionalHeader的最後一個數據成員是有16個成員的結構體數組。每一個結構體都存了一個RVA,每個RVA又會指向一個結構體。就好像這個數組是一級目錄,每個一級目錄又指向一個二級目錄,二級目錄又會指向正式內容。
這裏,只需要該結構體數組的第一個元素,即Export Table,導出表。
導出表結構體如下:typedef struct _IMAGE_EXPORT_DIRECTORY { DWORD Characteristics; DWORD TimeDateStamp; WORD MajorVersion; WORD MinorVersion; DWORD Name; DWORD Base; DWORD NumberOfFunctions; DWORD NumberOfNames; DWORD AddressOfFunctions; // RVA from base of image DWORD AddressOfNames; // RVA from base of image DWORD AddressOfNameOrdinals; // RVA from base of image } IMAGE_EXPORT_DIRECTORY, *PIMAGE_EXPORT_DIRECTORY;
這時需要後面3個RVA來找到函數地址,先來解釋一下這三個RVA
- AddressOfFunctions,函數的地址表,指向一個DWORD數組,數組元素是函數地址的RVA
- AddressOfNames,函數的名稱表,指向一個DWORD數組,數組元素是函數名稱的RVA
- AddressOfNameOrdinals,有名稱的函數的索引表,指向一個WORD數組,數組元素是和AddressOfFunctions對應的索引值
- 使用AddressOfNames定位到名稱表,設置循環找到需要導出的函數名
- AddressOfNames和AddressOfNameOrdinals是相互對應的,也就是說搜索的函數名在AddressOfNames中的位置是第 i 個,那麼該名稱對應的AddressOfNameOrdinals中的位置也是第 i 個,即兩個數組下標是對應相同的。
- 記下名稱匹配時Name下標,例如是第5個
- 根據記下的下標,找該函數的索引值。也就是尋址到AddressOfNameOrdinals的第5個元素,然後將該元素(WORD型)的值記下。
- 將記下的值作爲AddressOfFunctions數組的下標,找出該函數的RVA
- 通過RVA計算出VA就行了