zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    css background详解
    Javascript DOM 编程艺术:ENHANCING CONTENT
    Javascript DOM 编程艺术:创建一个简单的gallery
    js prototype
    Javascript DOM 编程艺术:优雅降级
    php solutions:创建画廊
    Javascript DOM 编程艺术: popUp
    Javascript DOM 编程艺术:Creating Markup on the Fly
    转:Node和Element的区别
    javascript语言精粹:函数
  • 原文地址:https://www.cnblogs.com/guanlaiy/p/2474504.html
Copyright © 2011-2022 走看看