根據函數名稱導出函數

根據函數名稱導出函數

  • 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[]
  • 根據名稱導出函數的步驟

    1. 獲取模塊首地址,首地址也是DOS頭首地址
    2. 根據DOS頭中的e_lfanew(RVA,因爲PE頭映射到內存中後和exe文件中是一樣的,所以這個地址也是File Address,即lfa這個前綴)定位到NT頭
    3. 根據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;
    4. 這時需要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;
    5. 這時需要後面3個RVA來找到函數地址,先來解釋一下這三個RVA

      • AddressOfFunctions,函數的地址表,指向一個DWORD數組,數組元素是函數地址的RVA
      • AddressOfNames,函數的名稱表,指向一個DWORD數組,數組元素是函數名稱的RVA
      • AddressOfNameOrdinals,有名稱的函數的索引表,指向一個WORD數組,數組元素是和AddressOfFunctions對應的索引值
    6. 使用AddressOfNames定位到名稱表,設置循環找到需要導出的函數名
    7. AddressOfNames和AddressOfNameOrdinals是相互對應的,也就是說搜索的函數名在AddressOfNames中的位置是第 i 個,那麼該名稱對應的AddressOfNameOrdinals中的位置也是第 i 個,即兩個數組下標是對應相同的。
    8. 記下名稱匹配時Name下標,例如是第5個
    9. 根據記下的下標,找該函數的索引值。也就是尋址到AddressOfNameOrdinals的第5個元素,然後將該元素(WORD型)的值記下。
    10. 將記下的值作爲AddressOfFunctions數組的下標,找出該函數的RVA
    11. 通過RVA計算出VA就行了
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章