一个图标可最多包含65536个图标
ICON_DIR 图标头
ICON_DIR_ENTRY 图标项,被包含在ICON_DIR中
ICON_DIR_ENTRY 描述每个图标大小,文件位置,字节大小等
假如现在1个图标里包含了3个图标资源,对应的结构:
ICON_DIR 内含有3个 :ICON_DIR_ENTRY ICON_DIR_ENTRY ICON_DIR_ENTRY
文件中 : 图标头(ICON_DIR)后直接跟图标数据
PE: 图标头跟图标数据分开放, 图标头被放在图标组(对应索引14), 图标数据放在图标资源(索引3)
查找过程:
1.找到图标组(一个图标组对应着一个图标文件)
2.通过图标组找到每个图标头
3.解析图标头的ID再去匹配图标资源中的ID ( 图标头的ID 实际为ICON_DIR_ENTRY.imageOffset)
* pe结构和文件结构中 ICON_DIR_ENTRY.imageOffset 是不一样的
*pe中占2个字节, 图标文件中占4字节
图标结构:
//图标头
struct ICON_DIR
{
WORD reserved;
WORD idtype; //资源类别 . ico为1
WORD idcount; //图标数量
ICON_DIR_ENTRY dir_entry[1]; // 数量1占位, 具体为idcount;
};
//一个图标项 -> 对应一个图标资源
struct ICON_DIR_ENTRY
{
unsigned char width;
unsigned char height;
unsigned char colorcount;
unsigned char reserved;
WORD planes;
WORD bitcount;
DWORD bytesInRes; // 此图标字节数
DWORD imageOffset; //图标所在文件位置
};
pe中的图标结构: ICON_DIR_ENTRY最后一个字段imageOffset 被修改成2个字节,为图标资源的ID值, 下面代码中使用的:
//图标项
struct ICON_DIR_ENTRY_IN_PE
{
unsigned char width;
unsigned char height;
unsigned char colorcount;
unsigned char reserved;
WORD planes;
WORD bitcount;
DWORD bytesInRes;
WORD idIndex; // 跟文件中的结构相比,只有此字段变成2字节的ID值,ID对应图标资源的ID
};
//图标头
struct ICON_DIR_IN_PE
{
WORD reserved;
WORD idtype;
WORD idcount;
ICON_DIR_ENTRY_IN_PE dir_entry[1];
};
下面代码里,很多错误处理都简单处理或省略了
#define _CRT_SECURE_NO_WARNINGS
#include "stdafx.h"
#include <Windows.h>
#include <stdio.h>
#include <iostream>
#include <time.h>
using std::endl;
using std::cout;
#define RES_IS_DIR 0x80000000
#define RES_AND_DIR 0x7fffffff
#define RES_IS_NAME 0x80000000
#define RES_AND_NAME 0x7fffffff
#define FILENAME_LENGTH 256
#define RES_ICON_INDEX 0x3
#define RES_ICON_GROUP_INDEX 0xe
char sectioninfo[] = "\nname\t实际大小\tRVA\t\t原始大小\t文件位置\t属性\n";
char szSection[] = "%s\t%08x\t%08x\t%08x\t%08x\t%08x";
char szMsgRes[] = "\n\n资源所处的节:%s , rva:%08X , foa:%08X,资源首地址:%08X\n";
char szMsgResErr[] = "没有资源\n";
wchar_t szLevel1ByID[] = L"资源类型(自定义) %d";
wchar_t szLevel1[] = L"\n资源类型:%s\n";
wchar_t szLevel2ByName[] = L" Name:%s\n";
wchar_t szLevel2ByID[] = L" ID:%d\n";
wchar_t szResData[] = L" 文件偏移:%08X, RVA::%08X 代码页=%04X, 长度%d字节\n";
const wchar_t * szMsgResType[] =
{
L"光标",
L"位图",
L"图标",\
L"菜单",\
L"对话框",\
L"字符串",\
L"字体目录",\
L"字体",\
L"加速键",\
L"未格式化资源",\
L"消息表",\
L"光标组",\
L"未知类型",\
L"图标组",\
L"未知类型",\
L"版本信息" };
#pragma pack( push, 1 )
//文件中 图标项结构
struct ICON_DIR_ENTRY
{
unsigned char width;
unsigned char height;
unsigned char colorcount;
unsigned char reserved;
WORD planes;
WORD bitcount;
DWORD bytesInRes; //字节大小
DWORD imageOffset; // 文件中的位置
};
//pe中图标项结构,与文件中只有最后一个字段有区别
struct ICON_DIR_ENTRY_IN_PE
{
unsigned char width;
unsigned char height;
unsigned char colorcount;
unsigned char reserved;
WORD planes;
WORD bitcount;
DWORD bytesInRes;
WORD idIndex; // 图标id, 对应资源图标目录中的id
};
//文件中icon头结构
struct ICON_DIR
{
WORD reserved;
WORD idtype;
WORD idcount;
ICON_DIR_ENTRY dir_entry[1];
};
// pe中的图标头结构
stru