资源枚举

写一个例子,枚举一个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. ubuntu18.04+gunicorn+nginx+supervisor+mysql+redis安装django项目

    Ubuntu18.04 install Django project 项目准备: ECS 实例 (云服务器) 此安装部署方案适合本地ubuntu18.04系统安装和虚拟机中ubuntu18.04系统安 ...

  2. 测试工程师Docker基础

    一.docker概述 1.docker为什么会出现 本质:所有技术的出现都是因为出现了一些问题,我们需要去解决,才去研究和学习: 问题: ​ 开发环境.测试环境.仿真环境.正式环境等诸多环境都需要进行 ...

  3. axios之增删查改操作

    一.get方法获取数据 axios.get('url') .then(function (res) { console.log(res); }).catch(function (error) { co ...

  4. C#无边框窗体拖动代码

    1.重写 protected override void WndProc(ref Message m) { if (m.Msg == 163 && this.ClientRectang ...

  5. 半监督学习方法(Semi-supervised Learning)的分类

    根据模型的训练策略划分: 直推式学习(Transductive Semi-supervised Learning) 无标记数据就是最终要用来测试的数据,学习的目的就是在这些数据上取得最佳泛化能力. 归 ...

  6. Python爬虫系列之爬取美团美食板块商家数据(二)

    今天为大家重写一个美团美食板块小爬虫,说不定哪天做旅游攻略的时候也可以用下呢.废话不多说,让我们愉快地开始吧~ 开发工具 Python版本:3.6.4 相关模块: requests模块: argpar ...

  7. 走进docker-swarm 带大家快速掌握docker自带编排工具

    什么是Docker Swarm? 对比Docker 前面我们介绍过Docker可以理解成是一个我们的服务的独立运行的容器,那么在实际工作中,我们的系统可能是一个微服务应用,系统中根据业务拆分成多个模块 ...

  8. [Fundamental of Power Electronics]-PART I-2.稳态变换器原理分析-2.1 引言

    2.1 引言 在上一章中,介绍了降压变换器作为降低直流电压的一种方法,其仅使用非耗散开关,电感器和电容器.开关状态变换产生一个矩形波形\(v_{s}(t)\),如图2.1所示.当开关位于位置1时,该电 ...

  9. Unity2D项目-平台、解谜、战斗! 1.3移动组件

    各位看官老爷们,这里是RuaiRuai工作室,一个做单机游戏的兴趣作坊. 在这一篇中,我们将会自顶向下地讨论本2D游戏中主角不可或缺的一个功能--移动控制. 首先我们简单分析一下2D游戏中主角与移动相 ...

  10. Polly-故障处理和弹性应对很有一手

    前言 对于运行中的系统,可以说百分百的小伙伴会经常遇见以下问题: 网络不通,突然又好了: 服务器宕机了: 调用服务接口超时了: 调用接口报错啦: 通讯信息发送失败需要重发: 以上只是列举了一些常遇到的 ...