Windows PE资源表编程(枚举资源树)
资源枚举
写一个例子,枚举一个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资源表编程(枚举资源树)的更多相关文章
- WindowsPE 第七章 资源表
资源表 在程序设计中,总会设计一些数据.这些数据可能是源代码内部需要用到的常量,菜单选项.界面描述等:也可能是源代码外部的,比如程序的图标文件.北京音乐文件.配置文件等,以上这些数据统称为资源.按照程 ...
- PE格式第九讲,资源表解析
PE格式第九讲,资源表解析 一丶熟悉Windows管理文件的方法 首先,为什么标题是这个,主要是为了下边讲解资源方便,因为资源结构体很乱.如果直接拿出来讲解,那么就会很晕. 1.windows管理文件 ...
- [PE结构分析] 11.资源表结构
资源表是一个树形结构,可以设置成2的31次方的层数,Windows 使用了3级: 类型->名称->语言 其中涉及到四个结构: Data Description Resource Direc ...
- Window黑客编程之资源释放技术
前言 今天说一下写病毒木马会广泛使用的一种技术--资源释放技术.为什么我们在写木马时会使用到资源释放技术呢?这是因为它可以使我们写的程序变得简洁.如果程序需要额外加载一些DLL文件或者文本文件,我们可 ...
- iteye上总结的编程精华资源
原文:http://www.iteye.com/magazines/130 博客是记录学习历程.分享经验的最佳平台,多年以来,各路技术大牛在ITeye网站上产生了大量优质的技术文章,并将系列文章集结成 ...
- 背水一战 Windows 10 (9) - 资源: 资源限定符概述, 资源限定符示例
[源码下载] 背水一战 Windows 10 (9) - 资源: 资源限定符概述, 资源限定符示例 作者:webabcd 介绍背水一战 Windows 10 之 资源 资源限定符概述 资源限定符示例 ...
- bundle绑定资源表
1.注册绑定资源表 在application_Start函数中: (注意不要加拓展名,否则压缩时出问题) BundleTable.Bundles.Add(new ScriptBundle(" ...
- Windows Store App 全球化:引用分离资源文件中的资源
大部分应用程序仅需要单个默认资源文件,例如Strings/zh-CN/Resources.resw,但是在某些应用程序中,最好将资源分离到多个资源文件中,以便更好地组织资源内容,这样就需要考虑如何引用 ...
- 第三百七十四节,Django+Xadmin打造上线标准的在线教育平台—创建课程app,在models.py文件生成4张表,课程表、课程章节表、课程视频表、课程资源表
第三百七十四节,Django+Xadmin打造上线标准的在线教育平台—创建课程app,在models.py文件生成4张表,课程表.课程章节表.课程视频表.课程资源表 创建名称为app_courses的 ...
随机推荐
- 优秀的vue服务端渲染框架
目前国内优秀的基于vue的ssr框架有minissr,可以在服务端生成html代码,有利于搜索引擎爬取. https://www.wechatmini.com/vue/minissr 使用方法可以参考 ...
- Python爬虫学习二------爬虫基本原理
爬虫是什么?爬虫其实就是获取网页的内容经过解析来获得有用数据并将数据存储到数据库中的程序. 基本步骤: 1.获取网页的内容,通过构造请求给服务器端,让服务器端认为是真正的浏览器在请求,于是返回响应.p ...
- 【Azure 微服务】PowerShell中,用Connect-ServiceFabricCluster命令无法连接到sf-test.chinaeast2.cloudapp.chinacloudapi.cn:19000 问题分析
问题描述 Azure Service Fabric提供了PowerShell的指令来进行创建,管理资源,如Get-ServiceFabricClusterHealth 获取当前集群的健康状态,但这些命 ...
- C语言II博客作业02
这个作业属于那个课程 https://edu.cnblogs.com/campus/zswxy/SE2020-4 这个作业要求在哪里 https://edu.cnblogs.com/campus/zs ...
- 攻防世界 reverse elrond32
tinyctf-2014 elrond32 1 int __cdecl main(int a1, char **arg_input) 2 { 3 if ( a1 > 1 && c ...
- springboot的yml中的bruid没有提示
解决方案: springboot的yml中的bruid没有提示只要在maven加上:druid-spring-boot-starter(注意版本的统一,否则可能会冲突) 效果图:
- 每天自学两小时Python,整理了最详细的学习路线和规
上次这篇文章每天自学两小时Python,三个月学通月入20K主要是给大家整理了学习资料视频和PDF书籍,很多需要的都关注私信领取了. 很多朋友领取之后都问我教程有了那么应该从哪去开始学习呢,私信太多我 ...
- 用DeBug的方式,带你掌握HBase文件在Snapshot的各种变化
摘要:掌握Snapshot可以帮助我们很好的完成HBase数据备份和数据迁移的工作. 简介 HBase的Snapshot功能可以在不复制数据的情况下,快速克隆一张表,完成一次数据备份.通过Snapsh ...
- java面试一日一题:java线程池
问题:请讲下java中的线程池 分析:在面试中经常问到线程池的问题,要掌握其基本概念,使用方法,注意事项等,引申下tomcat中默认的线程数是多少 回答要点: 主要从以下几点去考虑, 1.为什么要使用 ...
- [Fundamental of Power Electronics]-PART II-8. 变换器传递函数-8.1 Bode图回顾
8.0 序 工程设计过程主要包括以下几个过程: 1.定义规格与其他设计目标 2.提出一个电路.这是一个创造性的过程,需要利用工程师的实际见识和经验. 3.对电路进行建模.变换器的功率级建模方法已经在第 ...