PE文件格式--------------導入表和IAT


pe文件導入表

1)提取導入表:在數據目錄的中,索引為1的位置;

導入表起始RVA地址:IMAGE_NT_HEADER.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress

導入表大小:IMAGE_NT_HEADER.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualSize

2)導入表結構:一個導入庫對應下面的一個結構,pe文件引用了幾個導入庫文件就有幾個這樣的結構,最后以全0值結構結束。當pe在磁盤中時,結構中的兩個域OriginalFirstThunk和FirstThunk都指向IMAGE_THUNK_DATA,當pe加載准備運行時,前者仍然指向IMAGE_THUNK_DATA,后者則有裝載器修改為指向導入函數實際地址。

IMAGE_IMPORT_DESCRIPTOR struc

+00h OriginalFirstThunk:                       dd                ;存放RVA,該RVA指向一個IMAGE_THUNK_DATA結構數組,該數組占4字節,以全0值結尾

+04h DateTimeStamp:                          dd                

+08h ForwarderChain:                         dd

+0ch Name1:                                        dd              ;存放RVA,該RVA指向dll名字,該名字已0結尾

+10h FirstThunk:                                 dd                ;存放RVA,該RVA指向一個IMAGE_THUNK_DATA結構數組,該數組占4字節,以全0值結尾

IMAGE_IMPORT_DESCRIPTOR ends

 IMAGE_THUNK_DATA struc

     union

     {

         ForwarderString:       dd

         Function:                  dd

         Ordinal:                    dd                ;序號

         AddressOfData:         dd                ;指向IMAGE_IMPORT_BY_NAME

      }

IMAGE_THUNK_DATA ends

IMAGE_IMPORT_BY_NAME struc

    Hint:                           dw                ;函數序號,但有的編譯器不用此域

    Name1:                       db                ;函數名稱,以0結尾

IMAGE_IMPORT_BY_NAME ends

 3)IAT導入地址表

pe裝載后,導入表的第0項的FirstThunk指向的RVA,即為導入地址表的起始位置。

另一種更便捷的導入表提取方法是:數據目錄的IMAGE_DIRECTORY_ENTRY_IAT

4)導入表圖解

 pe文件加載前

 

 
pe文件加載后
 
4)主要代碼:
 

RvaToOffset.asm

;======================
;將RVA轉化為pe文件偏移
;by 紫陌
;======================
_RvaToOffset proc _lpImageBase, _lpRva
 local @offsetFile
 
 pushad
 
 xor eax, eax
 mov @offsetFile, eax
 ;*******************
 ;判斷是否為pe文件
 ;*******************
 mov edi, _lpImageBase
 assume edi:ptr IMAGE_DOS_HEADER
 .if [edi].e_magic != IMAGE_DOS_SIGNATURE
  xor eax, eax
  jmp _overpos
 .endif
 add edi, [edi].e_lfanew
 assume edi:ptr IMAGE_NT_HEADERS
 .if [edi].Signature != IMAGE_NT_SIGNATURE
  xor eax, eax
  jmp _overpos
 .endif
 ;*********************
 ;edi指向節表
 ;*********************
 movzx ecx, [edi].FileHeader.NumberOfSections
 movzx ebx, [edi].FileHeader.SizeOfOptionalHeader
 add edi, 4
 add edi, sizeof IMAGE_FILE_HEADER
 add edi, ebx
 assume edi:ptr IMAGE_SECTION_HEADER
 mov ebx, _lpRva
 .while ecx
  mov edx, [edi].VirtualAddress
  add edx, [edi].Misc.VirtualSize
  .if ebx >= [edi].VirtualAddress && ebx <= edx
   sub ebx, [edi].VirtualAddress
   mov eax, [edi].PointerToRawData
   add eax, ebx
   mov @offsetFile, eax
   jmp _overpos
  .endif
  add edi, sizeof IMAGE_SECTION_HEADER
  dec ecx
 .endw
_overpos:
 assume edi:nothing
 popad
 mov eax, @offsetFile
 ret
_RvaToOffset endp

 

processpefile_import.asm

;=====================
;處理pe文件導入表
;by 紫陌
;=====================
;=====================
;數據段
;=====================
.const
szTitleImportTable   db 'Import Descriptor (%08X)', 0dh, 0ah, 0
szImportDescriptor   db 0dh, 0ah, '*****************ImportDescriptor************************', 0dh ,0ah
         db 'OriginalFirstThunk (%08X):%08X', 0dh, 0ah
         db 'TimeDateStamp (%08X):%08X', 0dh, 0ah
         db 'ForwarderChain (%08X):%08X', 0dh, 0ah
         db 'Name1 (%08X):%08X->%s', 0dh, 0ah
         db 'FirstThunk (%08X):%08X', 0dh, 0ah, 0
szTitleOrignialFirstThunk db '-----------------OriginalFirstThunk-------------------------', 0dh ,0ah, 0
szThunkData      db 'Addresss or Order (%08X):%08X', 0dh, 0ah, 0
szImportByName     db '                                 -->ImportByName (%08X):%04X %s', 0dh ,0ah, 0
szTitleFirstThunk    db '-------------------FirstThunk-------------------------', 0dh ,0ah, 0

;=====================
;代碼段
;=====================
.code
_ProcessPeFile_Import proc _lpImageBase
 local @szBuf[512]:BYTE
 local @szDllName:DWORD
 local @ThunkFlag:BYTE
 
 pushad
 ;**********************
 ;edi指向導入表
 ;**********************
 mov edi, _lpImageBase
 assume edi:ptr IMAGE_DOS_HEADER
 add edi, [edi].e_lfanew
 assume edi:ptr IMAGE_NT_HEADERS
 mov eax, [edi].OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT * sizeof IMAGE_DATA_DIRECTORY].VirtualAddress
 invoke _RvaToOffset, _lpImageBase, eax
 mov edi, eax
 add edi, _lpImageBase
 assume edi:ptr IMAGE_IMPORT_DESCRIPTOR
 invoke RtlZeroMemory, addr szShowMsg, sizeof szShowMsg
 ;***********************
 ;輸出導入表首地址
 ;***********************
 invoke wsprintf, addr @szBuf, addr szTitleImportTable, edi
 invoke lstrcpy, addr szShowMsg, addr @szBuf
 ;***********************
 ;循環輸出IMAGE_IMPORT_DESCRIPTOR
 ;***********************
 .while !(([edi].OriginalFirstThunk == 0) && ([edi].TimeDateStamp == 0) && ([edi].ForwarderChain == 0) && ([edi].Name1 == 0) && ([edi].FirstThunk == 0))
  invoke _RvaToOffset, _lpImageBase, [edi].Name1
  add eax, _lpImageBase
  mov @szDllName, eax
  invoke wsprintf, addr @szBuf, addr szImportDescriptor, \
   addr [edi].OriginalFirstThunk, [edi].OriginalFirstThunk, \
   addr [edi].TimeDateStamp, [edi].TimeDateStamp, \
   addr [edi].ForwarderChain, [edi].ForwarderChain, \
   addr [edi].Name1, [edi].Name1, @szDllName, \
   addr [edi].FirstThunk, [edi].FirstThunk
  invoke lstrcat, addr szShowMsg, addr @szBuf
  invoke SetWindowText, hRichEdit, addr szShowMsg
  ;***************************
  ;根據OriginalFirstThunk循環輸出IMAGE_THUNK_DATA和IMAGE_IMPORT_BY_NAME
  ;***************************
  invoke lstrcat, addr szShowMsg, addr szTitleOrignialFirstThunk
  mov @ThunkFlag, 0
  invoke _RvaToOffset, _lpImageBase, [edi].OriginalFirstThunk
  add eax, _lpImageBase
  mov esi, eax
_OriginalFirstThunk:
   .while (DWORD ptr [esi]) != 0
   invoke wsprintf, addr @szBuf, addr szThunkData, \
    esi, \
    DWORD ptr [esi]
   invoke lstrcat, addr szShowMsg, addr @szBuf
   mov eax, [esi]
   test eax, 80000000h
   jnz @F
   invoke _RvaToOffset, _lpImageBase, eax
   add eax, _lpImageBase
   mov ebx, eax
   add ebx, 2
   movzx ecx, WORD ptr [eax]
   invoke wsprintf, addr @szBuf, addr szImportByName, \
    eax, \
    ecx, \
    ebx
   invoke lstrcat, addr szShowMsg, addr @szBuf
   @@:
   add esi, 4
   invoke SetWindowText, hRichEdit, addr szShowMsg
  .endw
  .if @ThunkFlag == 1
   jmp _continuewhile
  .endif
  ;***************************
  ;根據FirstThunk循環輸出IMAGE_THUNK_DATA和IMAGE_IMPORT_BY_NAME
  ;***************************
  invoke lstrcat, addr szShowMsg, addr szTitleFirstThunk
  mov @ThunkFlag, 1
  invoke _RvaToOffset, _lpImageBase, [edi].FirstThunk
  add eax, _lpImageBase
  mov esi, eax
  jmp _OriginalFirstThunk
_continuewhile:
  add edi, sizeof IMAGE_IMPORT_DESCRIPTOR
 .endw
 assume edi:nothing
 popad
 
 ret
_ProcessPeFile_Import endp

_ProcessPeFile_IAT proc _lpImageBase
 local @szBuf[512]:BYTE
 local @NumOfIAT
 
 pushad
 ;********************
 ;edi指向IAT表
 ;********************
 mov edi, _lpImageBase
 assume edi:ptr IMAGE_DOS_HEADER
 add edi, [edi].e_lfanew
 assume edi:ptr IMAGE_NT_HEADERS
 mov eax, [edi].OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT * sizeof IMAGE_DATA_DIRECTORY].VirtualAddress
 invoke _RvaToOffset, _lpImageBase, eax
 add eax, _lpImageBase
 mov ecx, [edi].OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT * sizeof IMAGE_DATA_DIRECTORY].isize
 shr ecx, 2
 mov @NumOfIAT, ecx
 mov edi, eax
 assume edi:ptr IMAGE_THUNK_DATA
 invoke lstrcat, addr szShowMsg, addr szTitleIAT
 mov ecx, @NumOfIAT
 .while ecx
  mov @NumOfIAT, ecx
  invoke wsprintf, addr @szBuf, addr szIAT, \
   edi, \
   [edi].u1.AddressOfData
  invoke lstrcat, addr szShowMsg, addr @szBuf
  mov ecx, @NumOfIAT
  add edi, 4
  dec ecx
 .endw
 invoke SetWindowText, hRichEdit, addr szShowMsg
 
 assume edi:nothing
 popad
 ret
_ProcessPeFile_IAT endp

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM