资源枚举

写一个例子,枚举一个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;
}

Windows PE资源表编程(枚举资源树)的更多相关文章

  1. WindowsPE 第七章 资源表

    资源表 在程序设计中,总会设计一些数据.这些数据可能是源代码内部需要用到的常量,菜单选项.界面描述等:也可能是源代码外部的,比如程序的图标文件.北京音乐文件.配置文件等,以上这些数据统称为资源.按照程 ...

  2. PE格式第九讲,资源表解析

    PE格式第九讲,资源表解析 一丶熟悉Windows管理文件的方法 首先,为什么标题是这个,主要是为了下边讲解资源方便,因为资源结构体很乱.如果直接拿出来讲解,那么就会很晕. 1.windows管理文件 ...

  3. [PE结构分析] 11.资源表结构

    资源表是一个树形结构,可以设置成2的31次方的层数,Windows 使用了3级: 类型->名称->语言 其中涉及到四个结构: Data Description Resource Direc ...

  4. Window黑客编程之资源释放技术

    前言 今天说一下写病毒木马会广泛使用的一种技术--资源释放技术.为什么我们在写木马时会使用到资源释放技术呢?这是因为它可以使我们写的程序变得简洁.如果程序需要额外加载一些DLL文件或者文本文件,我们可 ...

  5. iteye上总结的编程精华资源

    原文:http://www.iteye.com/magazines/130 博客是记录学习历程.分享经验的最佳平台,多年以来,各路技术大牛在ITeye网站上产生了大量优质的技术文章,并将系列文章集结成 ...

  6. 背水一战 Windows 10 (9) - 资源: 资源限定符概述, 资源限定符示例

    [源码下载] 背水一战 Windows 10 (9) - 资源: 资源限定符概述, 资源限定符示例 作者:webabcd 介绍背水一战 Windows 10 之 资源 资源限定符概述 资源限定符示例 ...

  7. bundle绑定资源表

    1.注册绑定资源表 在application_Start函数中: (注意不要加拓展名,否则压缩时出问题) BundleTable.Bundles.Add(new ScriptBundle(" ...

  8. Windows Store App 全球化:引用分离资源文件中的资源

    大部分应用程序仅需要单个默认资源文件,例如Strings/zh-CN/Resources.resw,但是在某些应用程序中,最好将资源分离到多个资源文件中,以便更好地组织资源内容,这样就需要考虑如何引用 ...

  9. 第三百七十四节,Django+Xadmin打造上线标准的在线教育平台—创建课程app,在models.py文件生成4张表,课程表、课程章节表、课程视频表、课程资源表

    第三百七十四节,Django+Xadmin打造上线标准的在线教育平台—创建课程app,在models.py文件生成4张表,课程表.课程章节表.课程视频表.课程资源表 创建名称为app_courses的 ...

随机推荐

  1. PTA甲级—常用技巧与算法

    散列 1078 Hashing (25 分) Quadratic probing (with positive increments only) is used to solve the collis ...

  2. SHELL编程概念&变量剖析

    一.shell软件概念和应用场景 1) 学习Linux技术,不是为了学习系统安装.命令操作.用户权限.配置IP.网络管理,学习Linux技术重点:基于Linux系统部署和维护各种应用软件.程序(Apa ...

  3. Java 运行时数据区和内存模型

    运行时数据区是指对 JVM 运行过程中涉及到的内存根据功能.目的进行的划分,而内存模型可以理解为对内存进行存取操作的过程定义.总是有人望文生义的将前者描述为 "Java 内存模型" ...

  4. 2019 GDUT Rating Contest III : Problem D. Lemonade Line

    题面: D. Lemonade Line Input file: standard input Output file: standard output Time limit: 1 second Memo ...

  5. 前端-CS-04

    一:DOM(文档对象模型) document 简写DOM 1.DOM中定义变量用 var  如下截图中:定义demo变量 2.取一个input输入框中的值的方法: 1)先如1中,在dom中顶一个一个变 ...

  6. WM_CLOSE WM_QUIT WM_DESTROY 三者的区别

    一 个窗口或者应用程序应该被关闭时发出WM_CLOSE消息,当接收到WM_CLOSE消息时,如果你愿意,向用户提出是否真的退出.你知道让用户作确认或 有错误出现或有什么应该注意的事情发生的时候,往往弹 ...

  7. java中ReentrantLock核心源码详解

    ReentrantLock简介 ReentrantLock是一个可重入且独占式的锁,它具有与使用synchronized监视器锁相同的基本行为和语义,但与synchronized关键字相比,它更灵活. ...

  8. pycharm在debug时总是报UnicodeDecodeError

    1,原文链接 解决pycharm run 正常 debug 报 UnicodeDecodeError 错误的问题 2,解决方法 首先尝试 如果上面还不行

  9. 【转载】C# get 与set的一些说明

    转载 在面向对象编程(OOP)中,是不允许外界直接对类的成员变量直接访问的,既然不能访问,那定义这些成员变量还有什么意义呢?所以C#中就要用set和get方法来访问私有成员变量,它们相当于外界访问对象 ...

  10. BUAA_2020_OO_UNIT2_REVIEW

    OO第二单元总结 1. 设计策略 总的来说,三次作业没有大的重构,都是使用了多线程进行电梯调度,输入线程和运行线程分离,主要的不同在于三次电梯调度器线程的数量有所不同,第一次为一个,第二次为n个,第三 ...