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\time 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是否基址改变是否更新. 就是绑定导入表的时间戳 跟 文件头中的时间戳进行对比.如果不一样.就要用重新计算地址.进行填写.

PE知识复习之PE的绑定导入表的更多相关文章

  1. PE知识复习之PE的导入表

    PE知识复习之PE的导入表 一丶简介 上一讲讲解了导出表. 也就是一个PE文件给别人使用的时候.导出的函数  函数的地址 函数名称 序号 等等. 一个进程是一组PE文件构成的.  PE文件需要依赖那些 ...

  2. PE知识复习之PE的导出表

    PE知识复习之PE的导出表 一丶简介 在说明PE导出表之前.我们要理解.一个PE可执行程序.是由一个文件组成的吗. 答案: 不是.是由很多PE文件组成.DLL也是PE文件.如果我们PE文件运行.那么就 ...

  3. PE知识复习之PE的各种头属性解析

    PE知识复习之PE的各种头属性解析 一丶DOS头结构体 typedef struct _IMAGE_DOS_HEADER { // DOS .EXE header WORD e_magic; // M ...

  4. PE知识复习之PE的重定位表

    PE知识复习之PE的重定位表 一丶何为重定位 重定位的意思就是修正偏移的意思.  如一个地址位 0x401234 ,Imagebase = 0x400000 . 那么RVA就是 1234.  如果Im ...

  5. PE知识复习之PE合并节

    PE知识复习之PE合并节 一丶简介 根据上一讲.我们为PE新增了一个节. 并且属性了各个成员中的相互配合. 例如文件头记录节个数.我们新增节就要修改这个个数. 那么现在我们要合并一个节.以上一讲我们例 ...

  6. PE知识复习之PE新增节

    PE知识复习之PE新增节 一丶为什么新增节.以及新增节的步骤 例如前几讲.我们的PE文件在空白区可以添加代码.但是这样是由一个弊端的.因为你的空白区节属性可能是只读的不能执行.如果你修改了属性.那么程 ...

  7. PE知识复习之PE扩大节

    PE知识复习之PE扩大节 一丶为什么扩大节 上面我们讲了,空白区添加我们的代码.但是有的时候.我们的空白区不够了怎么办.所以需要进行扩大节. 扩大节其实很简单.修改节数据对齐后的大小即可. 并且在PE ...

  8. PE知识复习之PE文件空白区添加代码

    PE知识复习之PE文件空白区添加代码 一丶简介 根据上面所讲PE知识.我们已经可以实现我们的一点手段了.比如PE的入口点位置.改为我们的入口位置.并且填写我们的代码.这个就是空白区添加代码. 我们也可 ...

  9. PE知识复习之PE的RVA与FOA的转换

    PE知识复习之PE的RVA与FOA的转换 一丶简介PE的两种状态 首先我们知道PE有两种状态.一种是内存展开.一种是在文件中的状态.那么此时我们有一个需求. 我们想改变一个全局变量的初始值.此时应该怎 ...

随机推荐

  1. SpringBoot整合使用JdbcTemplate

    JdbcTemplate是Spring框架自带的对JDBC操作的封装,目的是提供统一的模板方法使对数据库的操作更加方便.友好,效率也不错. 整合使用JdbcTemplate实现对图书的添加功能小案例 ...

  2. Android 性能优化之使用Lint

    代码静态检查推荐: (1)Android自定义Lint实践 (2)美团外卖Android Lint代码检查实践 (3)Android自定义Lint实践2——改进原生Detector Lint 是 An ...

  3. json格式的数据及遍历:

    代码: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8 ...

  4. Hive与Hbase整合

    Hive与Hbase整合 1.文档 Hive HBase Integration 2.拷贝jar文件 2.1.把Hbase的lib目录下面的jar文件全部拷贝到Hive的lib目录下面 cd /hom ...

  5. 【原创】C# API 未能创建 SSL/TLS 安全通道 问题解决

    在调用执行API之前添加以下代码就行了 System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;

  6. ChartControl设置坐标轴范围

    需求:有一条坐标轴是用来表示百分比的,所以刻度范围只能是从0 - 100: 解决方法:运行chatcontrol设计器,选中需要设置的轴,如下图: 设置Whole range 的最大最小值: 默认情况 ...

  7. C# WPF 使用委托修改UI控件

    近段时间在自学WPF,是一个完全不懂WPF的菜鸟,对于在线程中修改UI控件使用委托做一个记录,给自已以后查询也给需要的参考: 界面只放一个RichTextBox,在窗体启动时开起两个线程,调用两个函数 ...

  8. ndk编译libx264生成库

    编译脚本如下: TOOLCHAIN=$NDK/toolchains/arm-linux-androideabi-4.6/prebuilt/linux-x86_64 function build_x26 ...

  9. Redis两种方式实现限流

    案例-实现访问频率限制: 实现访问者 $ip 在一定的时间 $time 内只能访问 $limit 次. 非脚本实现 private boolean accessLimit(String ip, int ...

  10. numpy.random 常用函数详解之简单随机数篇(Simple random data)

    1.numpy.random.rand(d0,d1,d2,...,dn) 参数:d0,d1,d2,...,dn 须是正整数,用来描述生成随机数组的维度.如(3,2)代表生成3行2列的随机数组. 返回值 ...