• EAT表


    0X0 EAT表

    在windows系统中,“库”是为了方便其他程序调用而集中包含相关的函数的文件(dll,sys).win32 API是最具有代表性的库。
    EAT是一种核心机制,它使不同的应用程序可以调用库文件中提供的函数。也就是说,只有通过EAT表才能准确的求得从相应的库中导出函数的起始地址。
    PE文件内的结构体(IMAGE_EXPORT_DIRECTORY)保存着导出信息,且PE文件中仅有一个用来说明库EAT的IMAGE_EXPORT_DIRECTORY结构体

    0X01 IMAGE_EXPORT_DIRECTORY结构体

    我们可以在PE文件头 IMAGE_EXPORT_DIRECTORY的位置,IMAGE_OPTIONAL_HEADER32.DataDirectory[0].VirtualAddress就是该结构体数组的起始地址。

    IMAGE_EXPORT_DIRECTORY 结构体代码如下

    typedef struct _IMAGE_EXPORT_DIRECTORY {
    	DWORD Characteristics;			//保留 总是定义为0
    	DWORD TimeDateStamp;			//文件生成时间
    	WORD  MajorVersion;				//主版本号 一般不赋值
    	WORD  MinorVersion;				//次版本号 一般不赋值
    	DWORD Name;						//模块的真实名称
    	DWORD Base;						//索引基数 加上序数就是函数地址数组的索引值
    	DWORD NumberOfFunctions;		//地址表中个数
    	DWORD NumberOfNames;			//名称表的个数
    	DWORD AddressOfFunctions;		//输出函数地址的RVA
    	DWORD AddressOfNames;			//输出函数名字的RVA
    	DWORD AddressOfNameOrdinals;	//输出函数序号的RVA
    } IMAGE_EXPORT_DIRECTORYM, *pIMAGE_EXPORT_DIRECTORY;
    

    IMAGE_EXPORT_DIRECTORY 结构体的重要成员

    项目 含义
    NumberOfFunctions 实际Export函数的个数
    NumberOfNames Export函数中具名函数的个数
    AddressOfFunctions Export函数地址数组(数组元素个数=NumberOfFunctions)
    AddressOfNames 函数名称地址数组(数组元素个数=NumberOfNames)
    AddressOfNameOrdinals Ordinal地址数组(数组元素个数=NumberOfNames)

    下图是描述kernel32.dll文件的IMAGE_EXPORT_DIRECTORY 结构体与整个EAT结构

    0x02 获取库函数的操作原理

    从库中获取函数的API为GetProAddress()函数。该API引用EAT来获取指定API的地址,下面说明GetProAddress()函数的流程。

    GetProAddress()操作原理

    (1) 首先我们有一个要查找的函数名字fun_name
    (2) 通过IMAGE_EXPORT_DIRECTORYM 获得AddressOfNames成员获取函数名称数组。通过比较(strcmp)字符串,查找出指定的函数名称,获取数组的索引值
    (3) 通过IMAGE_EXPORT_DIRECTORYM 获得AddressOfNameOrdinals成员获取函数名称数组,将获取的数组索引值作为AddressOfNameOrdinals数组的下标获取相应的值ordinal
    (4) 通过IMAGE_EXPORT_DIRECTORYM 获得AddressOfFunctions成员获取函数名称数组。并把ordinal作为AddressOfFunctions数组的下标,获取指定函数的地址

    提示

    对于没有函数名称的导出函数,可以通过Ordinal查找它们地址。从Ordinal值减去IMAGE_EXPORT_DIRECTORY.Base成员最后一个值,使用该值作为"函数地址数组"(AddressOfFunctions)的索引,即可查找到相应的函数地址。

    0x03 使用user32.dll练习

    1 查找EAT表的地址
    通过PEview查看user32.dll RVA 3900 => RAW 2D00

    2 查出来EAT表的RAW为 2D00

    EAT结构体中的含义

    名称 数据(RVA) RAW
    Characteristics 0 0
    TimeDateStamp 48025D7A 0
    MajorVersion 0000 0
    MinorVersion 0000 0
    Name 000055C0 49C0
    Base 00000001 0
    NumberOfFunctions 000002DC 0
    NumberOfNames 000002DC 0
    AddressOfFunctions 00003928 2D28
    AddressOfNames 00004498 3898
    AddressOfNameOrdinals 00005008 4408

    3 查看函数名称组

    AddressOfNames是一个 4个字节RVA组成的数组,AddressOfNameOrdinals是一个2个字节组成的数组,AddressOfFunctions 是由4个字节 函数地址组成的数组
    我们查找第一个函数名的地址来演示整个流程 首先找到AddressOfNames 在文件中的首地址RAW 3898

    RVA 55CB => RAW 49CB 转换成文件偏移

    这个为一个函数,序号为0,下一步需要查找AddressOfNameOrdinals中索引为0中的数据

    从数组中取出数据为零,则在AddressOfFunctions 数组查找下标为0的数组

    RVA 00018673
    用OllDbg查看user32.dll 看到 ImageBase=77D10000
    所以该ActivateKeyboardLayout函数的实际地址为 77D10000+18673=77D28673

    0x04 寻找函数地址示意图

  • 相关阅读:
    第二面某知科技的
    面试的提问和大致经过
    抓取菜鸟教程中python内置函数的关键字和链接
    记录下之前写的udp,tcp。很浅显
    python连接mongodb数据库操作
    生成随机字母或数字
    python连接mysql基本操作
    post登录请求
    文件的读写
    request,正则爬虫
  • 原文地址:https://www.cnblogs.com/mhpcuit/p/13121520.html
Copyright © 2020-2023  润新知