资源枚举

写一个例子,枚举一个PE文件的资源表。首先说下资源相关的作为铺垫。

1.资源类型也是PE可选头中数据目录的一种。位于第三个类型。

2.资源目录分为三层。第四层是描述文件相关的。这些结构是按照二叉排序树的结构存的。每一个节点都可以看成是一段连续的数据块(1个资源目录头+n个资源目录项)。

3.整体基本结构:

OK,基础知识就简单说这些。如果还是不清楚,看下这里http://blog.csdn.net/u013761036/article/details/54562473这里我单独针对资源表写的一个博客。

说下写这个枚举资源表结构的程序思路:

理解了PE里面怎么存资源的剩下的就很简单了。

1.把PE加载到内存里。拿出来PE头,找到扩展头里面的第三个数据项。找到资源表RVA和大小。

2.根据RVA用函数换算出FOA的地址,这个地址指向的就是第一层目录的目录头结构,根据这个目录头开始,紧跟在后面的就是n个以名称命名的和m个以id命名的资源目录项。

3.上面2可以把目录头看成节点,把目录项看成连接到下一条节点的边,这样DFS或者BFS跑三层。依次枚举经过的信息。在第三层的时候直接把文件相关的也都输出来就可以了。

[注:DFS-深度优先搜索,就是平时说的递归 BFS-广度优先搜索,用队列模拟的一个扩散感觉的遍历]。

刚刚写了个例子,简单跑了一遍没发现啥问题:代码如下:

注意两个地方(这个我被坑了好一会):

(1)

结构里面涉及的下一个目录项和指向资源块的地址都是相对于资源表的起始位置而不是文件起始位置。

(2)

指针加法问题

XXXX * y;

DWORD z;

Y地址后偏移z长度得到x地址

XXXX * x = (XXXX *)((DWORD) y + DWORD(z))

// GET_RES.cpp : 定义控制台应用程序的入口点。
// #include "stdafx.h"
#include <windows.h>
#include <winbase.h>
#include <stdio.h>
#include <tchar.h>
#include <imagehlp.h>
#include <vector>
#include <string>
#include <iostream>
#include <string> using namespace std; //CP_ACP
string ws2s(const wstring& wide, UINT CodePage){ int wide_length = static_cast<int>(wide.length());
if (wide_length == 0)
return string(); int charcount = WideCharToMultiByte(CodePage, 0, wide.data(), wide_length,
NULL, 0, NULL, NULL);
if (charcount == 0)
return string(); string mb;
mb.resize(charcount);
WideCharToMultiByte(CodePage, 0, wide.data(), wide_length,
&mb[0], charcount, NULL, NULL); return mb;
} VOID ShowRes_DFS(DWORD dwDeep ,IMAGE_RESOURCE_DIRECTORY* pNowResourceDesc ,IMAGE_RESOURCE_DIRECTORY* pBaseResourceDesc){
/*
一级子目录按照资源类型分类。
二级子目录按照资源ID分类。
三级子目录按照资源代码页分类。
三级子目录后即为节点,也就是所说的文件。这里的文件其实就是包含了资源数据的指针和大小等信息的一个数据结构而已。
对于所有资源数据块的访问均可以从这里开始。
*/
dwDeep ++;
IMAGE_RESOURCE_DIRECTORY_ENTRY *pResourceBaseAddress = (IMAGE_RESOURCE_DIRECTORY_ENTRY *)((PBYTE)
pNowResourceDesc + sizeof(IMAGE_RESOURCE_DIRECTORY));
for(int i = 0 ;i < pNowResourceDesc->NumberOfIdEntries + pNowResourceDesc->NumberOfNamedEntries ;i ++){
IMAGE_RESOURCE_DIRECTORY_ENTRY *pNowResourceAddress = (IMAGE_RESOURCE_DIRECTORY_ENTRY *)((DWORD)pResourceBaseAddress + i * sizeof(IMAGE_RESOURCE_DIRECTORY_ENTRY)); for(int j = 1 ;j < (dwDeep-1) * 3 ;j ++){
cout<<" ";
}
cout<<"Value: ";
if(pNowResourceAddress->NameIsString){
IMAGE_RESOURCE_DIR_STRING_U *wsName = (IMAGE_RESOURCE_DIR_STRING_U*)
((DWORD)pNowResourceAddress->NameOffset + (DWORD)pBaseResourceDesc);
wstring wsV = wstring(wsName->NameString ,wsName->Length);
cout<<ws2s(wsV ,CP_ACP);
}else{
cout<<pNowResourceAddress->Id;
}
cout<<endl;
if(pNowResourceAddress->DataIsDirectory){
ShowRes_DFS(dwDeep ,(IMAGE_RESOURCE_DIRECTORY*)((DWORD)pNowResourceAddress->OffsetToDirectory + (DWORD)pBaseResourceDesc),pBaseResourceDesc);
}else{
for(int j = 1 ;j < (dwDeep) * 3 ;j ++){
cout<<" ";
}
IMAGE_RESOURCE_DATA_ENTRY * pFileRes = (IMAGE_RESOURCE_DATA_ENTRY*)((DWORD)pNowResourceAddress->OffsetToDirectory + (DWORD)pBaseResourceDesc);
cout<<"File: RVA-"<<pFileRes->OffsetToData;
cout<<",Size-"<<pFileRes->Size;
cout<<",Page-"<<pFileRes->CodePage;
cout<<endl;
}
}
return ;
} typedef PVOID (CALLBACK* PFNEXPORTFUNC)(PIMAGE_NT_HEADERS,PVOID,ULONG,PIMAGE_SECTION_HEADER*); BOOL FindReso(const wstring &wsPeFilePath){
HANDLE hFileHandle,hFileMapHandle;
DWORD dwFileAttrib=0;
void * pBaseAddress;
hFileHandle=CreateFile(wsPeFilePath.c_str(),GENERIC_READ,0,0,OPEN_EXISTING,dwFileAttrib,0);
if(hFileHandle == INVALID_HANDLE_VALUE){
return FALSE;
}
hFileMapHandle=CreateFileMapping(hFileHandle,0,PAGE_READONLY,0,0,0);
if(hFileMapHandle==NULL){
CloseHandle(hFileHandle);
return FALSE;
}
pBaseAddress=MapViewOfFile(hFileMapHandle,FILE_MAP_READ,0,0,0);
if (pBaseAddress==NULL) {
CloseHandle(hFileMapHandle);
CloseHandle(hFileHandle);
return FALSE;
} HMODULE hModule = ::LoadLibrary(L"DbgHelp.dll");
if(!hModule){
return FALSE;
}
PFNEXPORTFUNC ImageRvaToVax=(PFNEXPORTFUNC)GetProcAddress(hModule,"ImageRvaToVa");
if(!ImageRvaToVax){
FreeLibrary(hModule);
return FALSE;
} IMAGE_DOS_HEADER * pDosHeader = (IMAGE_DOS_HEADER*)pBaseAddress;
IMAGE_NT_HEADERS * pNtHeader = (IMAGE_NT_HEADERS *)((BYTE*)pBaseAddress+ pDosHeader->e_lfanew);
IMAGE_OPTIONAL_HEADER * pOptHeader = (IMAGE_OPTIONAL_HEADER *)((BYTE*)pBaseAddress + pDosHeader->e_lfanew + 24);
IMAGE_RESOURCE_DIRECTORY* pResourceDesc = (IMAGE_RESOURCE_DIRECTORY*)ImageRvaToVax(pNtHeader,pBaseAddress,pOptHeader->DataDirectory[2].VirtualAddress,0); if(pResourceDesc->NumberOfIdEntries + pResourceDesc->NumberOfNamedEntries == 0){
return TRUE;
}
ShowRes_DFS(0 ,pResourceDesc ,pResourceDesc);
FreeLibrary(hModule);
CloseHandle(hFileMapHandle);
CloseHandle(hFileHandle);
return TRUE;
}
int _tmain(int argc, _TCHAR* argv[])
{
WCHAR wcLocalFilePath[MAX_PATH] = {0};
GetModuleFileName(0 ,wcLocalFilePath ,MAX_PATH);
FindReso(wcLocalFilePath);
return 0;
}

最新文章

  1. Android Weekly Notes Issue #229
  2. 获取访问者的IP
  3. 命令安装VS
  4. 使用ShareSDK一键分享
  5. pdf转word
  6. github for windows 桌面版使用方法
  7. 搭建SpringMVC+MyBatis开发框架六
  8. 深入学习Struts2
  9. CLR和.Net对象
  10. topshelf和quartz
  11. linux_常用命令_(ls, lsof,nslookup)_查看文件按照时间排序
  12. 项目中BigDecimal与Double使用场景
  13. 关于map的初级应用
  14. vim之快速查找功能
  15. kafka全部数据清空与某一topic数据清空
  16. EasyUI datagrid 的多条件查询
  17. 客户化软件时代的前夜 ZT
  18. Bootstrap(3) 表格与按钮
  19. ui设计学习路线图分享送给初学者
  20. Java调用HTTPS接口的证书配置

热门文章

  1. Typora学习
  2. .zip爆破
  3. restful设计风格
  4. .NET Core 环境变量详解
  5. BST(二叉搜索树)的基本操作
  6. istio服务条目(ServiceEntry)介绍
  7. Linux中Sshd服务配置文件优化版本(/etc/ssh/sshd_config)
  8. 显示目录下的内容--ls
  9. Linux 用户和用户组管理(useradd userdel groupadd groupdel)
  10. JavaWeb 补充(JSP&EL&JSTL)