导入表的作用是什么? 没有它exe能运行吗?
导出表的作用是什么? 没有它exe能运行吗?
导出模块名,函数(序号),变量,类 通常导出表用于dll,没有导出表程序也可以运行
已知一个dll名,和一个dll导出函数的名字,如何得到这个函数名的地址?
导出表中查找 ENT(导出名称表) EOT(导出序号表) EAT(导出地址表)
怎么才能知道一个exe都使用了哪些API?
通过遍历导入表(INT,IAT)
如何判断导入函数是以序号导入或是以名称导入?
IMAGE_THUNK_DATA.DWORD 最高位1,说明序号导入
IMAGE_THUNK_DATA.DWORD 最高位0,说明名称导入
怎么才知道导出函数是仅以序号导出还是以名称导出?
遍历导出地址表,再遍历导出序号表,序号表中的值与导出地址表下标对应,
说明这个函数是名称导出, 如果序号表中的值没有与地址表下标对应,那么它是序号导出(序号+BASE)
资源表
概述
windows的资源有菜单、图标、快捷键、版本信息以及其它未格式化的二进制资源比如菜单、图标、快捷键、 版本信息以及其它未格式化的二进制资源。。。
资源由三层一样的结构体组成
第一层:资源的类型是什么(图标,位图,菜单....)
第二次:资源的叫什么名字 (1.png, 2.png)
第三层:资源的语言,资源的信息(大小,文件中位置)
资源表结构
资源表位于数据目标表,下标为2
资源目录结构体
typedef struct _IMAGE_RESOURCE_DIRECTORY {
DWORD Characteristics; // (1) 资源属性标识
DWORD TimeDateStamp; // (2) 资源建立的时间
WORD MajorVersion; // (3) 资源主版本
WORD MinorVersion; // (4) 资源子版本
WORD NumberOfNamedEntries; // (5) 资源名称条目个数
WORD NumberOfIdEntries; // (6) 资源ID条目个数
} IMAGE_RESOURCE_DIRECTORY, *PIMAGE_RESOURCE_DIRECTORY;
typedef struct _IMAGE_RESOURCE_DIRECTORY_ENTRY {
union {
struct {
DWORD NameOffset :31; // (1) 资源名偏移
DWORD NameIsString:1; // (2) 资源名为字符串
};
DWORD Name; // (3) 资源/语言类型
WORD Id; // (4) 资源数字ID
};
union {
DWORD OffsetToData; // (5) 数据偏移地址
struct {
DWORD OffsetToDirectory:31;// (6) 子目录偏移地址
DWORD DataIsDirectory :1;// (7) 数据为目录
};
};
}IMAGE_RESOURCE_DIRECTORY_ENTRY,*PIMAGE_RESOURCE_DIRECTORY_ENTRY;
当资源的名字为字符时,它指向这样一个结构体
typedef struct _IMAGE_RESOURCE_DIR_STRING_U {
WORD Length; // (1) 字符串长度
WCHAR NameString[ 1 ]; // (2) 字符串数组
} IMAGE_RESOURCE_DIR_STRING_U,*PIMAGE_RESOURCE_DIR_STRING_U;
最后一层指向真正数据的信息
typedef struct _IMAGE_RESOURCE_DATA_ENTRY {
DWORD OffsetToData; // (1) 资源数据的RVA
DWORD Size; // (2) 资源数据的长度
DWORD CodePage; // (3) 代码页
DWORD Reserved; // (4) 保留字段
} IMAGE_RESOURCE_DATA_ENTRY, *PIMAGE_RESOURCE_DATA_ENTRY;
解析资源表
//获取资源表 PIMAGE_RESOURCE_DIRECTORY PE::GetResourceDirectory() { //资源表位于数据目录表, 下标为2 DWORD dwResourceRva = GetNtHeader()->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress; DWORD dwResourceFoa = RvaToFoa(dwResourceRva) + (DWORD)m_pBuff; return (PIMAGE_RESOURCE_DIRECTORY)(dwResourceFoa); } //自定义 const WCHAR* RES[20] = { L"光标", L"位图", L"图标", L"菜单", L"对话框", L"字符串列表", L"字体目录", L"字体", L"快捷键", L"非格式化资源", L"消息列表", L"鼠标指针数组", L"NULL", L"图标组", L"NULL", L"版本信息", }; //显示资源表 void PE::ShowResourceInfo() { //1. 获取资源目录表 PIMAGE_RESOURCE_DIRECTORY pResourceOne = GetResourceDirectory(); //获取资源数组项 PIMAGE_RESOURCE_DIRECTORY_ENTRY pResouceOneEntry = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(pResourceOne + 1); //1.2 遍历所有资源类型 //资源总个数 DWORD dwResourceNumber = pResourceOne->NumberOfIdEntries + pResourceOne>NumberOfNamedEntries; for (int i = 0; i < dwResourceNumber; i++) { //1.3 判断资源类型,是数字还是字符串 if (pResouceOneEntry[i].NameIsString) { //资源ID是字符串 //那么NameOffset 有效(基于资源表的偏移) PIMAGE_RESOURCE_DIR_STRING_U szName = (PIMAGE_RESOURCE_DIR_STRING_U)(pResouceOneEntry[i].NameOffset + (DWORD)pResourceOne); TCHAR szBuff[100]; wcsncpy_s(szBuff, szName->NameString, szName->Length); printf("%S ", szBuff); } else { //资源ID是数字 // 系统定义的 0 - 16 if (pResouceOneEntry[i].Id < 16) { wprintf(L"%s ", RES[pResouceOneEntry[i].Id]); } // 自定义的 else { printf("%02d ", pResouceOneEntry[i].Id); } } //2 解析第二层数据 //2.1 是否有第二层数据 if (pResouceOneEntry[i].DataIsDirectory) { //2.2 获取第二层资源表 PIMAGE_RESOURCE_DIRECTORY pResourceTwo = (PIMAGE_RESOURCE_DIRECTORY)(pResouceOneEntry[i].OffsetToDirectory + (DWORD)pResourceOne); //获取资源数组项 PIMAGE_RESOURCE_DIRECTORY_ENTRY pResouceTwoEntry = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(pResourceTwo + 1); //这种资源有多少个 DWORD dwNumber2 = pResourceTwo->NumberOfIdEntries + pResourceTwo>NumberOfNamedEntries; //2.3 遍历资源 for (int i = 0; i < dwNumber2; i++) { //资源名字是 数字,还是字符串 if (pResouceTwoEntry[i].NameIsString) { PIMAGE_RESOURCE_DIR_STRING_U szName = (PIMAGE_RESOURCE_DIR_STRING_U)(pResouceTwoEntry[i].NameOffset + (DWORD)pResourceOne); TCHAR szBuff[100]; wcsncpy_s(szBuff, szName->NameString, szName->Length); printf(" %S ", szBuff); } else { printf(" %02d ", pResouceTwoEntry[i].Id); } //3. 解析第3层 //3.1 是否有第三层数据 if (pResouceTwoEntry[i].DataIsDirectory) { //3.2 获取第三层资源表 PIMAGE_RESOURCE_DIRECTORY pResourceThree = (PIMAGE_RESOURCE_DIRECTORY)(pResouceTwoEntry[i].OffsetToDirectory + (DWORD)pResourceOne); PIMAGE_RESOURCE_DIRECTORY_ENTRY pResourceThreadEntry = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(pResourceThree + 1); //第三层 执行真正数据 PIMAGE_RESOURCE_DATA_ENTRY pResourceData = (PIMAGE_RESOURCE_DATA_ENTRY)(pResourceThreadEntry->OffsetToData + (DWORD)pResourceOne); printf(" 资源位置 %08X,资源大小 %02d ", pResourceData>OffsetToData, pResourceData->Size); } } } } }