流水账笔记:PE文件格式(导出表)
来源:互联网 发布:监听2121端口 编辑:程序博客网 时间:2024/05/16 09:02
数据目录下记录了导出表的地址,其结构体如下:
Characteristics
属性,不重要
TimeDataStamp
导出表的生成时间,可以修改,系统不关心
MajorVersion & MinorVersion
版本号,不重要
Name
导出 dll 的名称
AddressOfFunctions
表示加载到内存后相对该模块的偏移地址(RVA)
在分析下面字段时,我们用 DEPENDS.exe 借助理解,将 dll 用 DEPENDS 打开,我们看到如下信息:
- Ordinal字段的值通过 AddressOfNameOrdinals 这张表里中的各个值和 Base 值相加得出
- Function 字段代表的是 AddresssOfNames 表里的内容
- Entry Point 字段代表的是 AddressOfFunctions 的内容
- Hint 字段是通过 AddresssOfNames 的排列顺序得出
将 dll 分为不同的导出方式,来观察这张表的变化。
情况一
此时,用 DEPENDS 打开,发现 fun1 和 fun2 之间插了许多填充的数据
再观察 dll 中的导出表字段,发现 Base 字段为 1。各张表信息如下表所示:
AddressOfFunctions 项 内容 第 1 项 0x00001000 第 2 项 0 … … 第 999 项 0 第 1000 项 0x00001020 第 1001 项 0x00001040————————————————-——-——————)))图表割线)
AddresssOfNames 项 内容 第 1 项 字符串指针(fun1) 第 2 项 字符串指针(fun2) 第 3 项 字符串指针(fun3)————————————————-——-——————)))图表割线)
AddressOfNameOrdinals 项 内容 第 1 项 0 第 2 项 0x03e7 (999) 第 3 项 0x03e8 (1000)情况二
此时,用 DEPENDS 打开:
再观察 dll 中的导出表字段,发现 Base 字段的值为 999。各张表信息如下表所示:
AddressOfFunctions 项 内容 第 1 项 0x00001000 第 2项 0x00001020 第 3项 0x00001040————————————————-——-——————)))图表割线)
AddresssOfNames 项 内容 第 1 项 字符串指针(fun1) 第 2 项 字符串指针(fun2) 第 3 项 字符串指针(fun3)————————————————-——-——————)))图表割线)
AddressOfNameOrdinals 项 内容 第 1 项 0x0000 第 2 项 0x0001 第 3 项 0x0002情况三
如果我们将一项函数不导出名称
此时,用 DEPENDS 打开:
再观察 dll 中的导出表字段,发现 Base 字段的值为 999。各张表信息如下表所示:
AddressOfFunctions 项 内容 第 1 项 0x00001000 第 2 项 0x00001020 第 3 项 0x00001040————————————————-——-——————)))图表割线)
AddresssOfNames 项 内容 第 1 项 字符串指针(fun1) 第 2 项 字符串指针(fun2)————————————————-——-——————)))图表割线)
AddressOfNameOrdinals 项 内容 第 1 项 0x0000 第 2 项 0x0001情况四
如果导出的序号按如图排列
此时,用 DEPENDS 打开:
再观察 dll 中的导出表字段,发现 Base 字段的值为 1。各张表信息如下表所示:
AddressOfFunctions 项 内容 第 1 项 0x00001020 第 2 项 0x00001000 第 3 项 0x00001040————————————————-——-——————)))图表割线)
AddresssOfNames 项 内容 第 1 项 字符串指针(fun1) 第 2 项 字符串指针(fun2) 第 3 项 字符串指针(fun3)————————————————-——-——————)))图表割线)
AddressOfNameOrdinals 项 内容 第 1 项 0x0001 第 2 项 0x0000 第 3 项 0x0002我们可知,AddresssOfNames 中字符串的排列顺序是按照.def 文件中字符串排列顺序排列的;而 AddressOfNameOrdinals 中的序号排列顺序是按照.def 文件中序号的顺序。
系统在调用 GetProcAddress,流程如图:(先画一半…好累) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~(流程图请忽视…)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~(流程图请忽视…)
模拟 GetProcAddress 代码
#include "stdafx.h"#include <windows.h>typedef void (*PFN_fun)();int MyGetProc(HMODULE hModule, LPCSTR lpProcName);int _tmain(int argc, _TCHAR* argv[]){ HMODULE hModule = LoadLibraryA("mydll.dll"); if (hModule == NULL) { MessageBox(NULL, _T("Dll加载失败!"), NULL, MB_OK); return -1; } int nItem = 3; //PFN_fun pfn = (PFN_fun)GetProcAddress(hModule, "Fun1"); PFN_fun pfn = (PFN_fun)MyGetProc(hModule, "fun2"); if (pfn == NULL) { return -1; } pfn(); return 0;}int MyGetProc(HMODULE hModule, LPCSTR lpProcName){ //得到 Dos 结构体 PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)hModule; //定位到 OptionalHeader 的地址 DWORD dwOpAddr = pDosHeader->e_lfanew + (DWORD)hModule + sizeof(IMAGE_FILE_HEADER) + sizeof(DWORD); PIMAGE_OPTIONAL_HEADER32 pOpHeader = (PIMAGE_OPTIONAL_HEADER32)dwOpAddr; //得到导出表结构体 DWORD dwExportAddr = pOpHeader->DataDirectory->VirtualAddress + (DWORD)hModule; PIMAGE_EXPORT_DIRECTORY pExportDir = (PIMAGE_EXPORT_DIRECTORY)dwExportAddr; //如果高四位为 0,则为序号导入 if (((DWORD)(lpProcName) & 0xffff0000) == 0) { /* 序号导入 */ int nNumOfFun = pExportDir->NumberOfFunctions; int nGetFunAddr = pExportDir->AddressOfFunctions + (DWORD)hModule; //1. 由 序号 - Base 得出在 AddressOfFunctions 表的第几项 int nItem = (DWORD)(lpProcName) - pExportDir->Base; if (nItem >= nNumOfFun) { return NULL; } //2. 遍历 AddressOfFunctions 表,定位到某一项 while (-- nNumOfFun) { nGetFunAddr += sizeof(DWORD); } return *((int *)nGetFunAddr) + (DWORD)hModule; } else { /* 字符串导入 */ int nItem = pExportDir->NumberOfNames; char* pNameTableAddr = (char *)(pExportDir->AddressOfNames + (DWORD)hModule); int nOrdinalCount = 0; SHORT nOrdinal = 0; //1. 遍历 AddressOfNames 表 while (nItem --) { char *pString = (char *)(*(DWORD *)(pNameTableAddr) + (DWORD)hModule); if (strcmp(pString, lpProcName) == 0) { //2. 遍历 AddressOfNameOrdinal 表 char *pOrdinalTable = (char *)(pExportDir->AddressOfNameOrdinals) + (DWORD)hModule; while (nOrdinalCount --) { pOrdinalTable += sizeof(SHORT); } nOrdinal = (SHORT&)(*pOrdinalTable); //3. 遍历 AddressOfFunctions 表 int nGetFunAddr = pExportDir->AddressOfFunctions + (DWORD)hModule; while (nOrdinal --) { nGetFunAddr += sizeof(DWORD); } return *((int *)nGetFunAddr) + (DWORD)hModule; } pNameTableAddr += sizeof(LPCSTR); nOrdinalCount++; } return NULL; } return NULL;}
- 流水账笔记:PE文件格式(导出表)
- 流水账笔记:PE文件格式(资源表)
- 流水账笔记:PE文件格式(导入表注入---手动)
- 流水账笔记:PE文件格式(重定位表)
- 流水账笔记:PE文件格式(Dos Header)
- 流水账笔记:PE文件格式(FileHeader)
- 流水账笔记:PE文件格式(OptionalHeader 上)
- 流水账笔记:PE文件格式(IAT)
- 流水账笔记:PE文件格式(OptionalHeader 下)
- 流水账笔记:PE文件格式(SectionHeaders)
- 流水账笔记:PE文件格式(RVA & FOA)
- 流水账笔记:PE文件格式(关于dump)
- 流水账笔记:PE文件格式(TLS)
- 流水账笔记:PE文件格式(手工增加节)
- 流水账笔记:PE文件格式(TLS手动注入)
- PE导出表笔记
- PE文件格式笔记
- PE文件格式学习笔记
- sublime最好用部分功能
- 字符串的查找:朴素查找算法和KMP算法
- Python3pandas库Series用法(基础整理)
- poi设置excel行高
- PAT甲级 1111. Online Map (30)
- 流水账笔记:PE文件格式(导出表)
- 特征提取与特征选择
- Android头像选择
- docker镜像操作
- PAT 甲级 1112. Stucked Keyboard (20)
- eclipse导入maven项目时报Could not calculate build plan: Plugin org.apache.maven.plugins:maven-resources
- Cannot link libpng
- 151. Reverse Words in a String
- 分段多项式及样条估计