灯火互联
管理员
管理员
  • 注册日期2011-07-27
  • 发帖数41778
  • QQ
  • 火币41290枚
  • 粉丝1086
  • 关注100
  • 终身成就奖
  • 最爱沙发
  • 忠实会员
  • 灌水天才奖
  • 贴图大师奖
  • 原创先锋奖
  • 特殊贡献奖
  • 宣传大使奖
  • 优秀斑竹奖
  • 社区明星
阅读:1647回复:0

菜鸟也学输入表

楼主#
更多 发布于:2012-08-24 20:01

关于导入表:

      可执行文件使用来自于其他dll的代码或数据时,称为输入。当PE文件装入时,

Windows加载器的工作之一就是定位所有被输入的函数和数据,并且让正在被装入的

PE文件可以使用那些地址。这个过程是通过PE文件的输入表(Import Tab 也称之为

导入表)完成的,输入表中保存的是函数名和其驻留的dll名等,动态连接所需输信息,

输入表在软件外壳技术上的地位十分重要,因此在研究外壳的技术时一定要掌握这部分

知识。




学习输入表要先从整个PE文件说起,
-------------*-------------------------------------------------*
                 | DOS Header(IMAGE_DOS_HEADER) | -->64 Byte
DOS头部  --------------------------------------------------
                 | DOS Stub                                            | -->112 Byte
-------------*-------------------------------------------------*
                 | "PE"00 (Signature)                              | -->4 Byte
                  -------------------------------------------------
                 | IMAGE_FILE_HEADER                        | -->20 Byte
PE文件头--------------------------------------------------
                 | IMAGE_OPTIONAL_HEADER32          | -->96 Byte
                 ---------------------------------------------------
                 | 数据目录表                                           | -->128 Byte
-------------*--------------------------------------------------*
                 | IMAGE_SECTION_HEADER                 | -->40 Byte
                 ---------------------------------------------------
   块表       | IMAGE_SECTION_HEADER                 | -->40 Byte
                  --------------------------------------------------
                 | IMAGE_SECTION_HEADER                 | -->40 Byte
-------------*--------------------------------------------------*
                 |.text                                                       | -->512 Byte
                 ---------------------------------------------------
    块          |.rdata                                                   | -->512 Byte
                 ---------------------------------------------------
                 |.data                                                     | -->512 Byte
-------------*-------------------------------------------------*
                 | COFF行号                                            | -->NULL
                 ---------------------------------------------------
调试信息| COFF符号表                                         | -->NULL
                 ---------------------------------------------------
                 | Code View 调试信息                             | -->NULL
-------------*--------------------------------------------------*
--------->>>摘自互联网(方舟子把我们搞的人心惶惶的,我等菜鸟写点东西都心惊胆战)上面就是一个简单的PE结构图(附件里我会附带一个比较详细的PE结构图供菜菜们娱乐),
我们来找出和输入表有关的区段和数据结构以及他们在PE文件中的位置。

1.IMAGE_NT_HEADER->IMAGE_OPTIONAL_HEADER32->第104个字节(也就是数据目录表的IMAGE_DIRECTORY_ENTRY_IMPORT) :struct _IMAGE_DATA_DIRECTORY{Dword VirtualAdress;    Dword  Size;};
该结构第一个成员是指向.idata区段首地址。


2.节表    .idata
typedef struct _IMAGE_SECTION_HEADER {
       BYTE Name[IMAGE_SIZEOF_SHORT_NAME];
    union {
           Dword PhysicalAddress;
           Dword VirtualSize;
    }     Misc;
     Dword VirtualAddress;
     Dword SizeOfRawData;
     Dword PointerToRawData;
     Dword PointerToRelocations;
     Dword PointerToLinenumbers;
     word NumberOfRelocations;
     word NumberOfLinenumbers;
     Dword Characteristics;
};
第五个成员表示该区段在文件中的起始地址。


3.   .idata区段中
参考附件中的图片。

   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 datetime 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 IMAGE_IMPORT_DESCRIPTOR UNALIGNED *PIMAGE_IMPORT_DESCRIPTOR;
//传说中的IID结构。
这个结构很重要,我们一个一个成员来分析


1)指向输入名称表(简称INT)的RVA,INT是一个IMAGE_THUNK_DATA结构数组,数组中的每一个IMAGE_THUNK_DATA结构指向IMAGE_IMPORT_BY_NAME结构,数组最后一个内容是内容为0的IMAGE_THUNK_DATA。

typedef struct _IMAGE_IMPORT_BY_NAME {
                      word    Hint;
                     BYTE    Name[1];
          } IMAGE_IMPORT_BY_NAME, *PIMAGE_IMPORT_BY_NAME;

成员1:
          word    Hint;指示本函数在其所驻留dll的输入表中的序号。该域被PE装载器
用来在DLL的输出表里快速查询函数。该值不是必须的,一些链接器将此值设为0.

成员2:
         BYTE    Name[1];含有输入函数的函数名,函数名是一个ASCII码字符串


2)32位时间标志。

3)这个是第一个被转向的API的索引,一般为0。

4)DLL的名字的指针,是一个以00结尾的ASCII字符的RVA地址,例如”kernel32.dll”


5)包含指向输入地址表(IAT)的RVA。IAT是一个IMAGE_THUNK_DATA数组。


成员1同成员5非常相似,他们指向两个本质上相同的数组IMAGE_THUNK_DATA。



以上便是PE中和输入表相关的数据结构














喜欢0 评分0
游客

返回顶部