输入表在PE中的结构及加载过程

转载 2012年03月31日 08:39:04

http://hi.baidu.com/mymillet/blog/item/0c09123debead3c19f3d6249.html

输入表结构我们知道,程序调用外部的dll函数通常都是下面这种形式:
    call my_label
    ...
my_label: jmp dword ptr [xxxxxxxx]
    对一个dll中的函数的调用总是通过一个地址间接的调用的.这些地址就放在输入表里(所以如果你改动了输入表, 可能也需要改my_label: jmp dword ptr [xxxxxxxx]).
    
    输入表(Import Table),简而言之,就是描述该pe文件从哪几个动态连接库导入了什么函数的一组结构数组.在这里我希望能用最简洁的语言让你明白什么是输入表.输入表的组成并不复杂,只用到三个结构.它们是:IMAGE_IMPORT_DESCRIPTOR,IMAGE_THUNK_DATA,IMAGE_IMPORT_BY_NAME.
    我们先看一下框图.

                           IMAGE_IMPORT_DESCRIPTOR
                          |---------------------------|
|---------------------| OriginalFirstThunk  |
|                         |---------------------------|
|                         | TimeDateStamp      |
|                         |---------------------------|
|                         | ForwarderChain     |
|                         |---------------------------|
|                         |       Name                |----> "USER32.DLL"
|                         |---------------------------|
|                         |     FirstThunk          |---------------------------------------------------------------------|
|                         |---------------------------|(装入内存后FirstThunk指向的结构数组会被修改)      |
|                                                                                                                                                |
|     Hint-name table                  IMAGE_IMPORT_BY_NAME   import address table(IAT)      |
|     |--------------------------------|     |--------------------------------|     |--------------------------------|      |
|-> | IMAGE_THUNK_DATA |-->| 44 | "GetMessage"        |<--| IMAGE_THUNK_DATA|<---|
      |--------------------------------|     |-----|--------------------------|     |--------------------------------|
      | IMAGE_THUNK_DATA |-->| 72 | "LoadIcon"             |<--| IMAGE_THUNK_DATA |
      |--------------------------------|     |-----|--------------------------|     |--------------------------------|
      |     ......                           |-->| ..    |    ......                     |<--|     ......                            |
      |--------------------------------|    |------|--------------------------|    |---------------------------------|
      |       NULL                      |     |       NULL                       |
      |--------------------------------|    |----------------------------------|

    当然,这是描述从一个dll中引入函数的情形.从几个dll中引入函数,那么就有几个这样的结构.同时,这也是磁盘文件上的结构.装入内存后FirstThunk指向的结构数组会被修改.可以看下面的图.
    我们先来熟悉一下这三个结构的定义:

typedef struct _IMAGE_IMPORT_DESCRIPTOR {
    union {
         DWORD Characteristics;       // 0 for terminating null import descriptor
         DWORD OriginalFirstThunk; // RVA to original unbound IAT (PIMAGE_THUNK_DATA)
    };
    DWORD TimeDateStamp;          // 0 if not bound,
                                                        // -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;
    DWORD FirstThunk;                  // RVA to IAT (if bound this IAT has actual addresses)
} IMAGE_IMPORT_DESCRIPTOR;

typedef struct _IMAGE_THUNK_DATA32 {
    union {
         PBYTE   ForwarderString;
         PDWORD Function;
         DWORD Ordinal;
         PIMAGE_IMPORT_BY_NAME   AddressOfData;
    } u1;
} IMAGE_THUNK_DATA32;

 

typedef struct _IMAGE_IMPORT_BY_NAME {
    WORD    Hint;                 //指出函数在所在的dll的输出表中的序号
    BYTE    Name[1];            //指出要输入的函数的函数名
} IMAGE_IMPORT_BY_NAME, *PIMAGE_IMPORT_BY_NAME;

 

IMAGE_IMPORT_DESCRIPTOR结构的各个域的含义:
1)union {
         DWORD Characteristics;
         DWORD OriginalFirstThunk;
   };
    这个联合指向一个 IMAGE_THUNK_DATA 类型的结构数组.这个联合不是很重要,可以为0.
 
2)TimeDateStamp
    该dll的时间日期戳,一般为0.
 
3)ForwarderChain
    正向连接索引.一般为0.
 
4)Name
    dll名字的RVA.
 
5)FirstThunk
    这个域也是一个RVA,指向一个DWORD数组,数组以NULL结束.数组中的每个DWORD实际上是一个IMAGE_THUNK_DATA结构的联合体。IMAGE_THUNK_DATA联合体通常被解释为一个指向IMAGE_IMPORT_BY_NAME结构的RVA.

    从上图我们可以看出有两个并行的指针数组都指向IMAGE_IMPORT_BY_NAME结构.事实上,OriginalFirstThunk指向的IMAGE_THUNK_DATA结构数组从来不被修改,该数组有时也叫提示名表(Hint-name table),提示名表总是指向IMAGE_IMPORT_BY_NAME结构数组.而FirstThunk指向的IMAGE_THUNK_DATA结构数组在该pe文件被加载时,加载程序会修改该数组的内容.加载程序迭代搜索数组的每一个指针,找到每一个IMAGE_IMPORT_BY_NAME结构所对应的输入函数的地址,然后加载程序用找到的地址修改相应的IMAGE_THUNK_DATA结构.(这是理解加载过程的关键).
    如前面提到的
          call my_label
          ...
my_label: jmp dword ptr [xxxxxxxx]
    其中的xxxxxxxx就是FirstThunk指向的IMAGE_THUNK_DATA数组中的一个的值.因为FirstThunk所指向的数组在加载后是所有输入函数的地址,因此它被称为输入地址表(Import Address Table,IAT).
    pe文件加载后输入表的情形如下:
                           IMAGE_IMPORT_DESCRIPTOR
                           |--------------------------|
|---------------------| OriginalFirstThunk |
|                         |---------------------------|
|                         | TimeDateStamp     |
|                         |---------------------------|
|                         | ForwarderChain     |
|                         |---------------------------|
|                         |       Name                |----> "USER32.DLL"
|                         |---------------------------|
|                         |     FirstThunk          |-----------------------------------------------------------|
|                         |---------------------------|                                                                       |
|                                                                                                                                   |
|     Hint-name table           IMAGE_IMPORT_BY_NAME  import address table(IAT)  |
|    |--------------------------------|     |-----------------------------| |------------------------------|      |
|->| IMAGE_THUNK_DATA |-->| 44 | "GetMessage"    | |ptr of GetMessage      |<----|
    |---------------------------------|     |----|------------------------| |------------------------------|
    | IMAGE_THUNK_DATA |--> | 72 | "LoadIcon"          | | ptr of LoadIcon           |
    |---------------------------------|     |----|------------------------| |------------------------------|
    |     ......                             |-->| .. |    ......                    | |     ......                         |
    |---------------------------------|     |----|------------------------| |------------------------------|
    |       NULL                       |   
 
 

 

windows PE文件结构及其加载机制

1. 概述PE文件的全称是Portable Executable,意为可移植的可执行的文件,常见的EXE、DLL、OCX、SYS、COM都是PE文件,PE文件是微软Windows操作系统上的程序文件(...
  • liuyez123
  • liuyez123
  • 2016年04月29日 15:00
  • 6261

Dll注入--修改PE文件头

DLL注入,除了常见的远线程注入,挂钩和修改注册表以外还可以通过修改PE文件头来达到注入目的,废话少说先上菜。1. 思路PE文件经常会调用外部DLL文件,而需要调用的DLL文件都会在PE文件说明,通过...
  • qq_20977145
  • qq_20977145
  • 2016年06月25日 14:12
  • 4374

PE文件结构(三) 输入表

PE文件结构(三) 参考 书:《加密与解密》 视频:小甲鱼 解密系列 视频 输入表 输入函数,表示被程序调用但是它的代码不在程序代码中的,而在dll中的函数。对于这些函数,磁盘上的可...
  • billvsme
  • billvsme
  • 2014年10月03日 11:52
  • 2329

PE文件结构及其加载机制(四)

下面我们开始学习节表。 不知道还记不记得在前面哪个结构体中出现过节的数量?   嘿嘿,忘记了吧,我们翻开以前的记录,看看。 原来是 typedef struct IMAGE_NT_HEADE...
  • thebulesky
  • thebulesky
  • 2017年10月31日 11:00
  • 89

PE文件结构及其加载机制(二)

以及对应的结构体 typedef struct _IMAGE_OPTIONAL_HEADER { WORD Magic; BYTE ...
  • thebulesky
  • thebulesky
  • 2017年10月30日 19:20
  • 95

windows PE文件结构及其加载机制

1. 概述 PE文件的全称是Portable Executable,意为可移植的可执行的文件,常见的EXE、DLL、OCX、SYS、COM都是PE文件,PE文件是微软Windows操作系统上的程...
  • FlowShell
  • FlowShell
  • 2017年11月01日 19:33
  • 96

PE文件结构及其加载机制

PE文件结构及其加载机制(一) 一、PE文件结构 PE即Portable Executable,是win32环境自身所带的执行体文件格式,其部分特性继承自Unix的COFF(Common ...
  • vbsourcecode
  • vbsourcecode
  • 2013年11月01日 22:20
  • 1237

PE文件结构及其加载机制(二)

在学习之前,我们来看看上次的进度 以及对应的结构体 typedef struct _IMAGE_OPTIONAL_HEADER { WORD ...
  • andylau00j
  • andylau00j
  • 2014年04月21日 20:29
  • 466

PE学习(十)第十章: 加载配置信息表

第十章:加载配置信息 加载配置信息表最初是用来存放附加信息,后来用来存放SEH各种导演句柄变成“异常处理表” 异常与中断类似,中断有点外部(键盘)发出,异常由软件,异常发生时跑到异常处理函数,这个...
  • pomelozero
  • pomelozero
  • 2015年04月10日 09:58
  • 286

Windows PE 第八章 延迟加载导入表

延迟加载导入表     延迟加载导入表是PE中引入的专门用来描述与动态链接库延迟加载相关的数据,因为这些数据所引起的作用和结构与导入表数据基本一致,所以称为延迟加载导入表。     延迟加载导入表...
  • u013761036
  • u013761036
  • 2017年02月09日 23:46
  • 305
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:输入表在PE中的结构及加载过程
举报原因:
原因补充:

(最多只允许输入30个字)