【PE文件】导出表
导出表位置
IMAGE_NT_HEADERS.IMAGE_OPTIONAL_HEADER32.IMAGE_DATA_DIRECTORY_ARRAY[0].VirtualAddress
导出表结构
导出表以一个 IMAGE_EXPORT_DIRECTORY(IED)结构体开始,它使不同的应用程序都可以调用库文件(DLL/SYS)中提供的导出函数。通过导出地址表(EAT),应用程序就能准确的从相应的库文件中获取导出函数地址。需要注意的是:PE文件中只有一个用于描述导出函数的 IED 结构体。
1 struct _IMAGE_EXPORT_DIRECTORY 2 { 3 0x00 DWORD Characteristics; 4 0x04 DWORD TimeDateStamp; 5 0x08 WORD MajorVersion; 6 0x0a WORD MinorVersion; 7 0x0c DWORD Name; //DLL名称 8 0x10 DWORD Base; //序号基数 9 0x14 DWORD NumberOfFunctions; //导出函数地址个数 10 0x18 DWORD NumberOfNames; //导出函数名称个数 11 0x1c DWORD AddressOfFunctions; //地址表数组Rva 元素=4字节 12 0x20 DWORD AddressOfNames; //名称表数组Rva 元素=4字节 13 0x24 DWORD AddressOfNameOrdinals; //序号表数组Rva 元素=2字节 14 };
可以使用如下 API 函数从库文件中获取导出函数,该API函数内部就是通过解析EAT表来获取指定API函数地址的。
示例:通过导出表获取MessageBox函数地址
2.1 名称导出
1 "MessageBox" = AddressOfNames[i]; //获取函数名称在名称表中下标 2 nIndex = AddressOfNameOrdinals[i]; //通过名称下标获取序号索引 3 pMessageBox = AddressOfFunctions[nIndex]; //通过索引获取函数地址Rva,当使用ImageBase+Rva = 函数调用地址
2.2 序号导出
1 如果函数以序号导出: 2 获取导出函数地址时直接用序号减去Base得到nIndex //通过序号-Base获取序号索引 3 函数地址 = AddressOfFunctions[nIndex] //通过索引获取函数地址Rva,当使用ImageBase+Rva = 函数调用地址