zoukankan      html  css  js  c++  java
  • PE文件---导入表,导出表

    IAT

    • Import Address Table,导入地址表

    DLL中隐式链接的调用过程

    • 以调用CreateFileW()为例该函数位于kernel32.dll中

    • call dword ptr ds:[01001104] 实现函数的调用

    • 调用CreateFileW()函数时并非直接调用,而是通过获取01001104地址处的值来实现(所有API调用均采用这种方式)。

    • 地址01001 104是notepad.exe中.text节区的内存区域(更确切地说是IAT内存区域)。

    • 01001104地址处的值为7C8107F0

    • 指令与call 7C8107F0 为一个效果

    IMAGE_IMPORT_DESCRIPTOR

    • IMAGE_ IMPORT_ DESCRIPTOR结构体中记录着PE文件要导入哪些库文件。
    typedef struct _IMAGE_IMPORT_DESCRIPTOR {
    	union {
    		DWORD Characteristics;
    		DWORD OriginalFirstThunk;			//INT的地址
    	};
    	DWORD TimeDateStamp;
    	DWORD ForwarderChain;
    	DWORD Name;								//库名称字符串地址
    	DWORD FirstThunk;						//IAT的地址
    } IMAGE_IMPORT_DESCRIPTOR;
     
    typedef struct _IMAGE_IMPORT_BY_NAME {
    	WORD Hint;								//ordinal
    	BYTE Name[1];							//function name string
    } IMAGE_IMPORT_BY_NAME, *PIMAGE_IMPORT_BY_NAME;
    
    • INT : Import_Name_Table

    • 它不在PE头而在PE体中,但查找其位置的信息在PE头中,IMAGE_ OPTIONAL_ HEADER32.
      DataDirectory[ 1].VirtualAddress的值即是IMAGE_ IMPORT_ DESCRIPTOR结构体数组的起始地址( RVA值)。IMAGE IMPORT_ DESCRIPTOR结构体数组也被称为IMPORT Directory Table (只有了解上述全部称谓,与他人交流时才能没有障碍)。
    typedef struct _IMAGE_DATA_DIRECTORY {
        DWORD VirtualAddress;
        DWORD Size;
    } IMAGE_DATA_DIRECTORY,*PIMAGE_DATA_DIRECTORY;
    

    EAT

    • 通过EAT才能准确求得从相应库中导出函数的起始地址。与前面讲解的IAT一样,PE文件内的特定结构体( IMAGE_ EXPORT_ DIRECTORY )保存着导出信息,且PE文件中仅有一个用来说明库EAT的IMAGE_ EXPORT DIRECTORY结构体。

    用来说明IAT的IMAGE_ IMPORT_ DESCRIPTOR 结构体以数组形式存在,且拥有多个成员。这样是因为PE文件可以同时导入多个库。

    • 可以在PE文件的PE头中查找到IMAGE_EXPORT_DIRECTORY结构体的位置。IMAGE_OPTIONAL_ HEADER32.DataDirectory[0]. VirtualAddress值即是IMAGE_ EXPORT_ DIRECTORY结构体数组的起始地址(也是RVA的值)。

    IMAGE_EXPORT_DIRECTORY

    typedef struct _IMAGE_EXPORT_DIRECTORY {
        DWORD   Characteristics;
        DWORD   TimeDateStamp;
        WORD    MajorVersion;
        WORD    MinorVersion; 
        DWORD   Name;                   //导出文件名的字符串的地址
        DWORD   Base;					
        DWORD   NumberOfFunctions;		//实际Export函数的个数
        DWORD   NumberOfNames;			//Export函数中有名字的函数的个数
        DWORD   AddressOfFunctions;		//Export函数数组地址
        DWORD   AddressOfNames;			//函数名称数组地址
        DWORD   AddressOfNameOrdinals;	//Ordinal数组地址( 数组元素个数=NumberOfNames )
    
    } IMAGE_EXPORT_DIRECTORY, *PIMAGE_EXPORT_DIRECTORY;
    

    • Ordinal:数组中的每一项与AddressOfNames中的每一项对应,表示该名字的函数在AddressOfFunctions中的序号

    从库中获得函数地址的API为GetProcAddress()函数。该API引用EAT来获取指定API的地址。通过GetProcAddress() 获取的函数地址的函数拥有函数名称.

    对于没有函数名称的导出函数,可以通过Ordinal 查找到它们的地址。从Ordinal值中减去IMAGE EXPORT_ DIRECTORY.Base 成员后得到一个值,使用该值作为“函数地址数组”的索引,即可查找到相应函数的地址。

    GetProcAddress()原理:

    (1)利用AddressOfNames成员转到“函数名称数组”。
    (2)“函数名称数组”中存储着字符串地址。通过比较( strcmp)字符串,查找指
    定的函数名称(此时数组的索引称为name_index)。
    (3)利用AddressOfNameOrdinals成员,转到orinal数组。
    (4)在ordinal 数组中通过name_ index 查找相应ordinal 值。
    (5)利用AddressOfFunctions成员转到“ 函数地址数组”( EAT )。
    (6)在“函数地址数组”中将刚刚求得的ordinal用作数组索引,获得指定函数的起
    始地址。

  • 相关阅读:
    Ubuntu 14.04 配置FTP
    python 命名规范
    Windows 多用户远程访问 Ubuntu 14.04桌面
    ubuntu 安装Matlab 解决显示中文乱码
    形式参数、实际参数和值传递、引用传递
    关于Hibernate中的临时态, 持久态, 游离态
    HTTP错误
    SpringMVC注解
    java变量的命名使用规则
    字节流与字符流的区别详解
  • 原文地址:https://www.cnblogs.com/l0nmar/p/12851516.html
Copyright © 2011-2022 走看看