zoukankan      html  css  js  c++  java
  • PE知识复习之PE的绑定导入表

                        PE知识复习之PE的绑定导入表

    一丶简介

      根据前几讲,我们已经熟悉了导入表结构.但是如果大家尝试过打印导入表的结构. INT IAT的时候. 会出现问题.

    PE在加载前 INT IAT表都指向一个名称表. 这样说是没错的. 但是如果你打印过导入表.会发现一个问题. 有的EXE程序.在打印IAT表的时候.发现里面是地址.

    原因:

      我们的PE程序在加载的时候.我们知道. PE中导入表的子表. IAT表.会填写函数地址. 但是这就造成了一个问题.PE程序启动慢.每次启动都要给IAT表填写函数地址.

      我们可不可以在文件中就给填写好. 这样是可以的.

    优点:

      PE程序启动变快.

    缺点:

      如果DLL的ImageBase变了.那么就需要进行重定位.因为在文件中你填写的地址是固定的地址.

    导入表结构:

    typedef struct _IMAGE_IMPORT_DESCRIPTOR {
        union {
            DWORD   Characteristics;            // 0 for terminating null import descriptor
            DWORD   OriginalFirstThunk;         // INT 表
        } DUMMYUNIONNAME;
        DWORD   TimeDateStamp;                  // 时间戳.
                                                // -1 if bound, and real date	ime stamp
                                                //     in IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT (new BIND)
                                                // O.W. date/time stamp of DLL bound to (Old BIND)
    
        DWORD   ForwarderChain;                 // -1 if no forwarders
        DWORD   Name;                //指向DLL名字的 RVA
        DWORD   FirstThunk;                     // IAT 表
    } IMAGE_IMPORT_DESCRIPTOR;
    typedef IMAGE_IMPORT_DESCRIPTOR UNALIGNED *PIMAGE_IMPORT_DESCRIPTOR;

    但是我们怎么知道.在文件中IAT表是否填写地址.还是不填写地址. 重要的地方 就是 TimeDateStamp (时间戳)成员, 如果为0 则是这个DLL没有绑定. 如果为 -1 则是这个DLL进行了绑定.

    那么什么是绑定.

      绑定的意思就是IAT的函数地址 是否是文件一开始就写入. 如果是绑定就是一开始就填写的.否则反之.

    二丶绑定导入表

      怎么判断导入表中的 IAT表函数地址是否绑定. 根据 TimeDataStamp进行判断. 0未绑定, -1 绑定. 而真正的绑定时间存放在绑定导入表中.

    数据目录的第12项

      绑定导入表结构

    typedef struct _IMAGE_BOUND_IMPORT_DESCRIPTOR {
        DWORD   TimeDateStamp;                //真正的时间戳,
        WORD    OffsetModuleName;              //DLL的名字. PE的文件名
        WORD    NumberOfModuleForwarderRefs;        //依赖的另外的DLL有几个
    // Array of zero or more IMAGE_BOUND_FORWARDER_REF follows
    } IMAGE_BOUND_IMPORT_DESCRIPTOR,  *PIMAGE_BOUND_IMPORT_DESCRIPTOR;

    我们的一个DLL可能依赖其他的DLL. 所以导入表的最后一个成员是依赖的DLL有几个.如果有两个.那么紧跟着下面就是依赖的DLL的绑定导入表结构.

    依赖DLL的结构

    typedef struct _IMAGE_BOUND_FORWARDER_REF {
        DWORD   TimeDateStamp;
        WORD    OffsetModuleName;
        WORD    Reserved;
    } IMAGE_BOUND_FORWARDER_REF, *PIMAGE_BOUND_FORWARDER_REF;

    跟绑定导入表是一样的. REF 引用的意思.就是说.我的绑定导入表中依赖的DLL有两个.那么绑定导入表下面.还有两个就是 xxx_REF结构(跟绑定导入表一样)

    注意REF结构中第三个成员.,他是用来占位置的.保留的.

    OffsetModuleName 成员.这个成员不是RVA 也不是FOA 而是第一个绑定导入表地址 +
    OffsetModuleName 这个成员的值.才是一个指针. 这个指针才是真正的文件名所在的位置.
    PS: 不管你打印到第几个 永远都是 第一个绑定导入表的值 + OffsetModuleName的值

    如何判断这个DLL是否基址改变是否更新. 就是绑定导入表的时间戳 跟 文件头中的时间戳进行对比.如果不一样.就要用重新计算地址.进行填写.

  • 相关阅读:
    【20211112】学习,为自己,也为别人
    【20211109】计划会使人拥有魔力
    【20211110】责任是不确性的克星
    【20211113】因材施教
    【20211119】责任能使人变得难以置信
    【20211115】连岳摘抄
    【20211106】连岳摘抄
    c#中用正则过滤所有标点符号
    带农历的JavaScript日期时间
    JQuery常用方法一览
  • 原文地址:https://www.cnblogs.com/iBinary/p/9745417.html
Copyright © 2011-2022 走看看