首页
社区
课程
招聘
[分享]PE结构体中导出表/导入表解析——初阶
发表于: 2018-1-24 12:59 11488

[分享]PE结构体中导出表/导入表解析——初阶

2018-1-24 12:59
11488

一、导出表解析



输出表位置,落在了.rdata段,



16000【5200】

17D70【6F70】
  从而,可以知道17D70,输出表在磁盘中的偏移是6F70


在010里,Ctrl + G,输入6F70

这里,先看下导出表的数据结构,40B,

typedef struct _IMAGE_EXPORT_DIRECTORY {
    DWORD   Characteristics;
    DWORD   TimeDateStamp;
    WORD    MajorVersion;
    WORD    MinorVersion;
    DWORD   Name; // DLL的名称地址
    DWORD   Base; // 索引基数
    DWORD   NumberOfFunctions; // 函数地址表大小
    DWORD   NumberOfNames; // 函数名表大小 == 函数序号表大小
    DWORD   AddressOfFunctions;     // 函数地址表——首地址
    DWORD   AddressOfNames;         // 函数名表——首地址
    DWORD   AddressOfNameOrdinals;  // 函数序号表——首地址
} IMAGE_EXPORT_DIRECTORY, *PIMAGE_EXPORT_DIRECTORY;


那就从6F70的位置,开始,找40B,如下:


00 00 00 00

71 DB 67 5A 【时间戳】

00 00 【主版本】

00 00 【次版本】

C0 7D 01 00【DLL名称地址】

01 00 00 00 【索引基数】

04 00 00 00 【函数地址表大小】

04 00 00 00 【函数名表大小 == 函数序号表大小】

98 7D 01 00【函数地址表——首地址】

A8 7D 01 00 【函数名表——首地址】

B8 7D 01 00【函数序号表——首地址】


1、看DLL的名称是啥:地址17DC0【6FC0】,找到了我们自己的库dll_00.dll



2、再看下函数地址表中的元素,首地址17D98【6F98】,共有4个,地址,4B/个



如下所示:



3、再来看函数名表中的元素,首地址17DA8【6FA8】,共有4个,地址4B/个


这些都是地址值,要找到真正的函数名:

17DD0【6FD0】


17DD5【6FD5】


17DDA【6FDA】


17DCB【6FCB】



特别注意:函数名表,其实存放的也是地址值,RVA,这个只是我们自己找到的名称,方便起见,直接写的名字



4、接下来,看下函数序号表,首地址17DB8【6FB8】,4个,序号,2B/个



5、接下来,就分析分析:从这里,也可以看到,序号表里的值,并没有加上索引基数


最终,会得到如下结果:



6、验证下,我们的结果:成功了;




至于,索引基数,还没看到效果呢,————注意看下刚刚的LoadPe里的Ordinal那一列




部分代码:

 

#pragma once

#define WIN32DLL_EXPORTS

#ifdef __cplusplus
extern "C" {
#endif

#ifdef WIN32DLL_EXPORTS
#define WIN32DLL_API __declspec(dllexport)
#else
#define WIN32DLL_API __declspec(dllimport)
#endif

	WIN32DLL_API void Fun1();
	WIN32DLL_API void Fun2();
	WIN32DLL_API void Fun3();

#ifdef __cplusplus
}
#endif

def文件

 

LIBRARY;
EXPORTS;
	Fun4;


二、导入表解析

写一个测试程序,查看导入表RVA



输入表位置,落在了.idata段



1A000【7400】

1A1E8【75E8】


共20B

typedef struct _IMAGE_IMPORT_DESCRIPTOR {
    union {
        DWORD   Characteristics;            // 0 for terminating null import descriptor
        DWORD   OriginalFirstThunk;         // RVA to original unbound IAT (PIMAGE_THUNK_DATA)
    } DUMMYUNIONNAME;
    DWORD   TimeDateStamp;                  // 0 if not 
    DWORD   ForwarderChain;              
    DWORD   Name;
    DWORD   FirstThunk;                     // RVA to IAT
} IMAGE_IMPORT_DESCRIPTOR;



2C A3 01 00 【OriginalFirstThunk:INT(Import Name Table)导入名称表地址RVA】

00 00 00 00 

00 00 00 00 

54 A4 01 00【DLL名称(地址值)】

E0 A0 01 00【IAT(Import Address Table)导入地址表地址RVA】


1、首先看下DLL的名字,1A454【7854】



2、看下INT(OriginalFirstThunk):1A32C【772C】,全0结尾



函数名数组:

44 A4 01 00 ————1A444【7844】——————最高位为0,说明是名称导入的,不是序号导入的;

3C A4 01 00 ————1A43C【783C】——————

4C A4 01 00 ————1A44C【784C】——————

34 A4 01 00 ————1A434【7834】——————


注意:IAT和INT都指向下面的数据结构,4B

typedef struct _IMAGE_THUNK_DATA32 {
    union {
        DWORD ForwarderString;      // PBYTE 
        DWORD Function;             // PDWORD,导入函数的地址,在加载到内存后,这里才起作用
        DWORD Ordinal;              // 假如是序号导入的,会用到这里
        DWORD AddressOfData;        // PIMAGE_IMPORT_BY_NAME,假如是函数名导入的,用到这里,它指向另外一个结构体:PIMGE_IMPORT_BY_NAME
    } u1;
} IMAGE_THUNK_DATA32;

// 如果是函数名导入的,AddressOfData会指向下面这个结构体
typedef struct _IMAGE_IMPORT_BY_NAME {
    WORD    Hint;
    CHAR   Name[1];
} IMAGE_IMPORT_BY_NAME, *PIMAGE_IMPORT_BY_NAME;

由上可知,函数名导入的,因此,上面的地址值,就会指向一个PIMAGE_IMPORT_BY_NAME的结构体:

【7844】Fun3


【783C】Fun2


【784C】Fun4


【7834】Fun1



3、看下IAT,1A0E0【74E0】全0结束,IAT和INT一样,都指向IMAGE_THUNK_DATA32结构体,4B



可见,最高位都是0,所以,也是名称导入的,另外,还可以发现,这个位置的值,和INT的值是一样的,因此,不再赘述了;

44 A4 01 00 

3C A4 01 00 

4C A4 01 00 

34 A4 01 00



 

#include <stdio.h>

extern "C" __declspec(dllimport) void Fun1();
extern "C" __declspec(dllimport) void Fun2();
extern "C" __declspec(dllimport) void Fun3();

// 如果是在def中导出的,需要如下声明
void Fun4();

#pragma comment(lib, "../Debug/dll_00.lib")

int main(int argc, char** argv) {
	Fun1();
	Fun2();
	Fun3();
	Fun4();

	getchar();

	return 0;
}

三、如果,修改def为

LIBRARY;
EXPORTS;
	Fun4 @1;

看下导入表里的INT/IAT:




可见,这里的一项,最高位为1,序号导入,这个序号,就是dll export的那个序号


至此,PE结构中,导入/导出表的介绍结束;


PS:I Dare to do sth I feared,作为一枚奋斗青年,也是一枚小白,最近在学习PE结构相关的知识,这篇帖子也算是自己的一个总结;希望能对需要的人以帮助;也期待大神们的更多指导;


15PB


[课程]FART 脱壳王!加量不加价!FART作者讲授!

收藏
免费 1
支持
分享
最新回复 (14)
雪    币: 32
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
2018-1-24 13:31
0
雪    币: 49
活跃值: (118)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
加油啊老宋
2018-1-24 13:31
0
雪    币: 310
活跃值: (2227)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
mark
2018-1-24 14:14
0
雪    币: 68
活跃值: (101)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
mark  另外能介绍下所用的工具是什么吗?
2018-1-24 14:19
0
雪    币: 47
活跃值: (36)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
6
010  Editor  &&  LoadPe
2018-1-24 14:49
0
雪    币: 224
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
2018-1-24 19:59
0
雪    币: 175
活跃值: (2331)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
写的很好,收藏了。
2018-1-24 21:14
0
雪    币: 1515
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
顶!
2018-1-24 21:37
0
雪    币: 6818
活跃值: (153)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
2018-1-24 22:54
0
雪    币: 11
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
2018-1-25 15:12
0
雪    币: 13
活跃值: (30)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12
6666666
2018-1-25 21:32
0
雪    币: 22
活跃值: (139)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
13
2018-1-26 10:11
0
雪    币: 8084
活跃值: (1515)
能力值: ( LV2,RANK:15 )
在线值:
发帖
回帖
粉丝
14
pe结构有些复杂呵
2018-1-27 16:40
0
雪    币: 688
活跃值: (15)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
15
Mark
2018-2-20 10:45
0
游客
登录 | 注册 方可回帖
返回
//