[PE构造拆解分析] 9.导出表 IMAGE_EXPORT_DIRECTOPAJEROY

by admin on 2019年12月15日
typedef struct _IMAGE_EXPORT_DIRECTORY {
    DWORD   Characteristics;    // 未使用,总为0 

    DWORD   TimeDateStamp;      // 文件创建时间戳
    WORD    MajorVersion;       // 未使用,总为0 

    WORD    MinorVersion;       // 未使用,总为0
    DWORD   Name;               // 指向一个代表此 DLL名字的 ASCII字符串的 RVA
    DWORD   Base;               // 函数的起始序号
    DWORD   NumberOfFunctions;  // 导出函数的总数

    DWORD   NumberOfNames;      // 以名称方式导出的函数的总数

    DWORD   AddressOfFunctions;     // 指向输出函数地址的RVA
    DWORD   AddressOfNames;         // 指向输出函数名字的RVA
    DWORD   AddressOfNameOrdinals;  // 指向输出函数序号的RVA

} IMAGE_EXPORT_DIRECTORY, *PIMAGE_EXPORT_DIRECTORY;

导出表:

财富表是一个树形构造,能够设置成2的三拾七遍方的层数,Windows 使用了3级:

AddressOfFunctions 所指向内容是以 4
字节为二个单位的数组成分,各类元素代表函数入口

  • 上篇文章,大家学习了各样头,Dos,NT,节表头,大家清楚,OptionalHeader指向的DataDirectory[]数组意气风发共有十五个:

类型->名称->语言

AddressOfNames 所指向内容是以 4
字节为叁个单位的数组成分,每一种成分代表三个照准字符串的 奥迪Q3VA

图片 1

图片 2

AddressOfNamesOrdinals 所指向内容是以 2
字节为一个单位的数组成分,每种成分代表对应名字在 AddressOfFunctions
中的序号数。

  • 我们接下去要学习的有:

 

AddressOfNames 和 AddressOfNamesOrdinals
的数码显著是同样的,不是生机勃勃律那么就出错了。

  1. IMAGE_DIRECTORY_ENTRY_IMPORT 导入表
  2. IMAGE_DIRECTORY_ENTRY_BASERELOC 基址重定位表
  3. IMAGE_DIRECTORY_ENTRY_EXPORT 导出表
  4. IMAGE_DIRECTORY_ENTRY_RESOURCE 资源表

在那之中提到到五个布局:

第大器晚成要明白三种检索函数入口地址的法门:

  • 前几天大家学习导出表:

 

A. 从序号查找函数入口地址

  1. 定位到PE 文件头
  2. 从PE 文件头中的 IMAGE_OPTIONAL_HEADEOdyssey32
    构造中抽取数据目录表,并从第三个数据目录中获得导出表的大切诺基VA
  3. 从导出表的 Base 字段得到开头序号
    4.
    将需求搜索的导出序号减去最初序号Base,获得函数在进口地址表中的索引,检查测试索引值是或不是超越导出表的
    NumberOfFunctions 字段的值,要是过量后面一个的话,表明输入的序号是无效的
  4. 用这些索引值在 AddressOfFunctions
    字段指向的导出函数入口地址表中抽出相应的花色,那就是函数入口地址的迈凯伦570VA
    值,当函数棉被服装入内部存款和储蓄器的时候,这一个ENCOREVA
    值加上模块实际装入的集散地址,就拿走了函数真正的进口地址
  1. 我们清楚dll文件,是动态链接库,里面有超多函数给别人调用,不过外人怎么知道此中有哪些函数呢?就须求导出表清单给人家看,就好似你去餐厅点餐,却不驾驭餐厅有怎么样菜,那时候服务员会拿出美食指南来,这几个菜单就犹如导出表。
  2. 享有PE文件都得以有导出表,只是大多数景观下,exe不提供导出表而已。

Data

Description

Resource Directory Tables (and Resource Directory Entries)

A series of tables, one for each group of nodes in the tree. All top-level (Type) nodes are listed in the first table. Entries in this table point to second-level tables. Each second-level tree has the same Type ID but different Name IDs. Third-level trees have the same Type and Name IDs but different Language IDs.

Each individual table is immediately followed by directory entries, in which each entry has a name or numeric identifier and a pointer to a data description or a table at the next lower level.

Resource Directory Strings

Two-byte-aligned Unicode strings, which serve as string data that is pointed to by directory entries.

Resource Data Description

An array of records, pointed to by tables, that describe the actual size and location of the resource data. These records are the leaves in the resource-description tree.

Resource Data

Raw data of the resource section. The size and location information in the Resource Data Descriptions field delimit the individual regions of resource data.

B. 从函数名称查找入口地址

自个儿想通的地点,记录下来:用函数名来查究的话,Base
的值现在未有其他意义

  1. 第一获得导出表的地点
  2. 从导出表的 NumberOfNames
    字段获得已命名函数的总额,并以那些数字作为循环的次数来布局二个巡回,从
    AddressOfNames
    字段指向得到的函数名称地址表的率先项起初,在循环军长每意气风发项定义的函数名与要物色的函数名相相比,若无其余二个函数名是切合的,表示文件中尚无点名名称的函数。
    3.
    借使某生龙活虎项定义的函数名与要物色的函数名适合,那么记下那几个函数名在字符串地址表中的索引值,然后在AddressOfNamesOrdinals
    指向的数组中以同等的索引值抽出数组项的值,大家这里假若那么些值是 x
  3. 终极,以 x 的值作为索引值在 AddressOfFunctions 
    字段指向的函数入口地址表中拿走 纳瓦拉VA 。此 景逸SUVVA 正是函数的入口地址。

沾满图片:

图片 3

  • 咱俩精通OptionalHeader指向的DataDirectory[]数组豆蔻梢头共有拾四个,每一个都以如出生龙活虎辙的社团:

 

  1. VirtualAddress  设想偏移地址
  2. size  大小

 

  • NtHeader.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT
    ],这一个数据目录表VirtualAddress指向的是导出表之处:

 

 

typedef struct _IMAGE_EXPORT_DIRECTORY 
 {
 DWORD Characteristics;//未使用,总是定义为0 
 DWORD TimeDateStamp;//文件生成时间 
 WORD MajorVersion;//未使用,总是定义为0 
 WORD MinorVersion;//未使用,总是定义为0 
 DWORD Name; //模块的真实名称的RVA 
 DWORD Base; //基数,加上序数就是函数地址数组的索引值 
 DWORD NumberOfFunctions;//导出函数的总数 
 DWORD NumberOfNames; //以名称方式导出的函数的总数 
 DWORD AddressOfFunctions; // RVA from base of image指向输出函数地址的RVA 
 DWORD AddressOfNames; // RVA from base of image指向输出函数名字的RVA 
 DWORD AddressOfNameOrdinals; // RVA from base of image向输出函数序号的RVA 

 } IMAGE_EXPORT_DIRECTORY, *PIMAGE_EXPORT_DIRECTORY

Resource Directory Table

Each resource directory
table has the following format. This data structure should be considered
the heading of a table because the table actually consists of directory
entries (described in section 6.9.2, “Resource Directory Entries”) and
this structure:

Offset Size Field Description
0 4 Characteristics Resource flags. This field is reserved for future use. It is currently set to zero.
4 4 Time/Date Stamp The time that the resource data was created by the resource compiler.
8 2 Major Version The major version number, set by the user.
10 2 Minor Version The minor version number, set by the user.
12 2 Number of Name Entries The number of directory entries immediately following the table that use strings to identify Type, Name, or Language entries (depending on the level of the table).
14 2 Number of ID Entries The number of directory entries immediately following the Name entries that use numeric IDs for Type, Name, or Language entries.

 

  1. Characteristics:今后尚未利用,经常为0。
  2. TimeDateStamp:导出表生成的时间戳,由一而再器生成。
  3. MajorVersion,MinorVersion:看名字是本子,实际貌似未有用,都以0。
  4. Name:模块的名字,便是dll的称呼。
  5. Base:序号的基数,按序号导出函数的序号值从Base开首依次增加。
  6. NumberOfFunctions:全体导出函数的数额。
  7. NumberOfNames:按名字导出函数的数据。
  8. AddressOfFunctions:一个奥迪Q3VA,指向七个DWO奥迪Q5D数组,数组中的每风流浪漫项是二个导出函数的揽胜VA,顺序与导出序号雷同。
  9. AddressOfNames:一个CRUISERVA,依旧指向一个DWOGL450D数组,数组中的每大器晚成项仍是叁个TucsonVA,指向贰个意味着函数名字。
  10. AddressOfNameOrdinals:五个HavalVA,依旧指向三个WO安德拉D数组,数组中的每意气风发项与AddressOfNames中的每生龙活虎项对应,表示该名字的函数在AddressOfFunctions中的序号。

Resource Directory Entries

The directory entries
make up the rows of a table. Each resource directory entry has the
following format. Whether the entry is a Name or ID entry is indicated
by the resource directory table, which indicates how many Name and ID
entries follow it (remember that all the Name entries precede all the ID
entries for the table). All entries for the table are sorted in
ascending order: the Name entries by case-sensitive string and the ID
entries by numeric value.  Offsets are relative to the address in the
IMAGE_DIRECTORY_ENTRY_RESOURCE DataDirectory.

Offset

Size

Field

Description

0

4

Name Offset

The offset of a string that gives the Type, Name, or Language ID entry, depending on level of table.

0

4

Integer ID

A 32-bit integer that identifies the Type, Name, or Language ID entry.

4

4

Data Entry Offset

High bit 0. Address of a Resource Data entry (a leaf).

4

4

Subdirectory Offset

High bit 1. The lower 31 bits are the address of another resource directory table (the next level down).

 

typedef struct _IMAGE_IMPORT_BY_NAME 
{
 WORD Hint;
 CHAR Name[1];
} IMAGE_IMPORT_BY_NAME, *PIMAGE_IMPORT_BY_NAME;

Resource Directory String

The resource directory
string area consists of Unicode strings, which are word-aligned. These
strings are stored together after the last Resource Directory entry and
before the first Resource Data entry. This minimizes the impact of these
variable-length strings on the alignment of the fixed-size directory
entries. Each resource directory string has the following format:

Offset

Size

Field

Description

0

2

Length

The size of the string, not including length field itself.

2

variable

Unicode String

The variable-length Unicode string data, word-aligned.

图片 4

 

图片 5

Resource Data Entry

Each Resource Data
entry describes an actual unit of raw data in the Resource Data area. A
Resource Data entry has the following format:

Offset

Size

Field

Description

  0

4

Data RVA

The address of a unit
of resource data in the Resource Data area.

  4

4

Size

The size, in bytes, of
the resource data that is pointed to by the Data RVA field.

  8

4

Codepage

The code page that is
used to decode code point values within the resource data. Typically,
the code page would be the Unicode code page.

12

4

Reserved, must be
0.

  • AddressOfFunctions 指向装有函数之处。
  • AddressOfNames 指向名字的地址。
  • AddressOfNameOrdinals 指向二个序号。

  • 寻觅导出表代码(c/c++):

    int main(int argc, char *argv[])
    {
    PIMAGE_DOS_HEADER Pdos = (PIMAGE_DOS_HEADER)GetModuleHandle(L”user32.dll”);

 PIMAGE_NT_HEADERS Pnt = (PIMAGE_NT_HEADERS)((int)Pdos->e_lfanew + (int)Pdos);

 IMAGE_OPTIONAL_HEADER32 Popt = Pnt->OptionalHeader;

 IMAGE_EXPORT_DIRECTORY * Export;
 Export = (IMAGE_EXPORT_DIRECTORY*)(Popt.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress + (ULONG_PTR)Pdos);

 DWORD * AllAddress;
 DWORD * AllName;
 USHORT * AllOrg;

 AllAddress = (DWORD*)((int)Export->AddressOfFunctions + (int)Pdos);//函数地址数组
 AllName = (DWORD*)((int)Export->AddressOfNames + (int)Pdos);//函数名称数组
 AllOrg = (USHORT *)((int)Export->AddressOfNameOrdinals + (int)Pdos);//序号数组


 int OneAddress;
 char * OneName;
 USHORT OneOrg;
 char * Buf = new char[500];
 int ListId = NULL;

 for (int i = 0; i < (int)Export->NumberOfNames; i++)
 {

 OneName = (char*)((BYTE*)Pdos + AllName[i]);
 OneOrg = (USHORT)AllOrg[i];
 OneAddress = (int)((int)Pdos + AllAddress[OneOrg]);

 printf("Name: %s, Org :%d,Address :%x\n", OneName, OneOrg, OneAddress);
 }

 return 0;
}

图片 6

 

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图