终于修改了EXE的图标罗
这些天研究怎样修改EXE文件里面的图标,看了antghazi<<如何修改可执行文件的图标>>一文,一开始连代码该怎么打也不知道,后来代码拼出来了,有些地方还是不明白,耽搁了两三天.
关键就在
pFirstIcon = firstIconData->OffsetToData - rsrc_SectionHeader->VirtualAddress + (char*)dirRoot;
为什么要减去 VirtualAddress 呢?
最后看了张正秋的<<Windows应用程序捆绑核心编程 >>网上试读的文章,才明白了些.
OffsetToData是一个内存中的RVA,用这个值减去"资源节的开始RVA"(对应的Section Header的VirtualAddress),就可以得到相对于资源节开始的偏移。
得到的是相于于资源节,也就是相对于.rsrc节的偏移地址.加上它!就是第一个图标的图像数据了.
至少是为什么要这样减,我还没弄清楚,暂时死记下来算了。
感觉资源树好麻烦,还是不明白里面是怎么分布的.
理解PE的文件格式和资源树对理解那些代码至关重要!!!
PE文件的格式示意图(完全按我个人理解,勿以为是标准)
Dos Header | Dos Stub | PE Header | Section Header 1 | Section Header …… | Section Header n | Section 1 | Section …… | Section n |
PE文件的资源树,个人觉得不好理解,就讲本例子中一个图标图像数据获取的过程吧。
先确定一个事实,图标放在盒子里面,盒子放在抽屉里面,抽屉嵌在柜子上。
1.找到资源段的Section Header。
2.根据Section Header找到资源段。
3.在资源段里面找到图标的"柜子",有不少柜子,找到专放图标的。
4.在图标的"柜子"里面找到放第一个图标的"抽屉"。里面不止一个抽屉,
有些抽屉放着图标,有些没有放。我们找到第一个就算了。
5.在放图标的"抽屉"里面找到放图标的"盒子"。
6.盒子打开后,里面没有图标???不过有张纸,写着图标在哪。然后我们去找就是了。
不知道有没有人没听懂。。。。。。
贴出来的代码是完整的,但不能直接运行,你先在程序运行的当前目录下放两个EXE,一个叫Test1.exe,一个叫Test2.exe。图标要不一样的(不然怎么试)。然后运行程序后,Test2.exe的图标会变成Test1.exe的图标。
主要写了两个函数
1.GetIconData 得到EXE的第一个图标的图像数据。
2.WriteIconData 把图像数据写入(替换)EXE中第一个图标。
要注意的是,写入图标数据时不考虑是否与之前图标大小一致的问题,因为本人也不知道如果不一致又怎么办。。。
源代码的前部分写注释比较多,后面部分,我自己都有点晕,所以注释不大好写。
哇,三点多了,我死。不写了。欢迎有人来指点我啊。
#include "stdafx.h"
#include "stdlib.h"
#include "windows.h"
void GetIconData(char *pfile,char **pdata,DWORD *size)
{
HANDLE hSrcFile;
DWORD dwFileSize;
char *pSrcFile;
DWORD dwReaded;
IMAGE_DOS_HEADER *dosHeader;
IMAGE_NT_HEADERS *ntHeader;
IMAGE_SECTION_HEADER *sectionHeader;
IMAGE_SECTION_HEADER *rsrc_SectionHeader;
IMAGE_RESOURCE_DIRECTORY *dirRoot;
IMAGE_RESOURCE_DIRECTORY_ENTRY *entry;
IMAGE_RESOURCE_DIRECTORY_ENTRY *iconEntry;
IMAGE_RESOURCE_DIRECTORY *tempDir;
IMAGE_RESOURCE_DIRECTORY_ENTRY *tempEntry;
IMAGE_RESOURCE_DIRECTORY *firstIconDir;
IMAGE_RESOURCE_DIRECTORY_ENTRY *firstIconEntry;
IMAGE_RESOURCE_DATA_ENTRY *firstIconData;
char *pFirstIcon;
/*将目标EXE文件读入内存(不同于操作系统的调用)*/
hSrcFile = CreateFile(pfile,GENERIC_READ | GENERIC_WRITE,FILE_SHARE_READ | FILE_SHARE_WRITE,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
if(hSrcFile == INVALID_HANDLE_VALUE)
{
printf("Can't open the %s file./n",pfile);return;
}
dwFileSize = GetFileSize(hSrcFile,NULL);
pSrcFile = (char *)malloc(dwFileSize);
ReadFile(hSrcFile,pSrcFile,dwFileSize,&dwReaded,NULL);
//至此pSrcFile已是目标EXE文件在内存的首地址了.
/*下一步就是找出Dos Header.*/
dosHeader = (IMAGE_DOS_HEADER*)pSrcFile;
/*根据dosHeader里面的一个成员找到PE Header.*/
ntHeader = (IMAGE_NT_HEADERS*)(pSrcFile + dosHeader->e_lfanew);
/*找出第一个Sesion Header.*/
sectionHeader = (IMAGE_SECTION_HEADER*)((char*)ntHeader + sizeof(IMAGE_NT_HEADERS));
/*找出.rsrc的Section Header.*/
printf("There are the Section Header follow./n");
for(int i=0;i<ntHeader->FileHeader.NumberOfSections;i++,sectionHeader++)
{
printf("Section Header #%d: %s/n",i+1,sectionHeader->Name);
if(strcmp((char*)sectionHeader->Name,".rsrc") == 0)
rsrc_SectionHeader = sectionHeader;///找到.rsrc的Section Header了!!!
}
/*找出.rsrc Section.*/
dirRoot = (IMAGE_RESOURCE_DIRECTORY*)(pSrcFile + rsrc_SectionHeader->PointerToRawData);
/*找出第一个资源目录*/
entry = (IMAGE_RESOURCE_DIRECTORY_ENTRY*)((char*)dirRoot +sizeof(IMAGE_RESOURCE_DIRECTORY_ENTRY));
/*找出.rsrc 中 Icon 的资源目录*/
printf("There are the directory of the .rsrc Section./n");
for(int j=0;j<dirRoot->NumberOfIdEntries+dirRoot->NumberOfNamedEntries;j++,entry++)
{
printf("Resource Directory #%d: %d/n",j+1,entry->Name);
if(entry->Name == 3)
iconEntry = (IMAGE_RESOURCE_DIRECTORY_ENTRY*)((char*)dirRoot+entry->OffsetToDirectory);//找到 Icon 的资源目录了!!!
}
tempDir = (IMAGE_RESOURCE_DIRECTORY*)iconEntry;
tempEntry = (IMAGE_RESOURCE_DIRECTORY_ENTRY*)((char*)tempDir+sizeof(IMAGE_RESOURCE_DIRECTORY));
printf("There are the /"IconItems/" of the icon directory./n");
for(int k=0;k<tempDir->NumberOfIdEntries+tempDir->NumberOfNamedEntries;k++,tempEntry++)
{
printf("IconItem %d Is %d/n",k+1,tempEntry->DataIsDirectory);
if(tempEntry->DataIsDirectory > 0 && k ==0 )
{
//拿到第一个图标的"Item"
firstIconDir = (IMAGE_RESOURCE_DIRECTORY*)((char *)dirRoot+tempEntry->OffsetToDirectory);
firstIconEntry = (IMAGE_RESOURCE_DIRECTORY_ENTRY*)((char*)firstIconDir+sizeof(IMAGE_RESOURCE_DIRECTORY));
firstIconData = (IMAGE_RESOURCE_DATA_ENTRY*)((char*)dirRoot+firstIconEntry->OffsetToData);
}
}
//得到第一个图标Item的图像数据的物理地址
pFirstIcon = firstIconData->OffsetToData - rsrc_SectionHeader->VirtualAddress + (char*)dirRoot;
//返回
*size = firstIconData->Size;
*pdata = (char*)malloc(firstIconData->Size);
memcpy(*pdata,pFirstIcon,*size);
/*释放资源.*/
CloseHandle(hSrcFile);
free(pSrcFile);
}
void WriteIconData(char *pfile,const char *pdata,DWORD size)
{
HANDLE hSrcFile;
DWORD dwFileSize;
char *pSrcFile;
DWORD dwReaded;
IMAGE_DOS_HEADER *dosHeader;
IMAGE_NT_HEADERS *ntHeader;
IMAGE_SECTION_HEADER *sectionHeader;
IMAGE_SECTION_HEADER *rsrc_SectionHeader;
IMAGE_RESOURCE_DIRECTORY *dirRoot;
IMAGE_RESOURCE_DIRECTORY_ENTRY *entry;
IMAGE_RESOURCE_DIRECTORY_ENTRY *iconEntry;
IMAGE_RESOURCE_DIRECTORY *tempDir;
IMAGE_RESOURCE_DIRECTORY_ENTRY *tempEntry;
IMAGE_RESOURCE_DIRECTORY *firstIconDir;
IMAGE_RESOURCE_DIRECTORY_ENTRY *firstIconEntry;
IMAGE_RESOURCE_DATA_ENTRY *firstIconData;
char *pFirstIcon;
/*将目标EXE文件读入内存(不同于操作系统的调用)*/
hSrcFile = CreateFile(pfile,GENERIC_READ | GENERIC_WRITE,FILE_SHARE_READ | FILE_SHARE_WRITE,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
if(hSrcFile == INVALID_HANDLE_VALUE)
{
printf("Can't open the %s file./n",pfile);return;
}
dwFileSize = GetFileSize(hSrcFile,NULL);
pSrcFile = (char *)malloc(dwFileSize);
ReadFile(hSrcFile,pSrcFile,dwFileSize,&dwReaded,NULL);
//至此pSrcFile已是目标EXE文件在内存的首地址了.
/*下一步就是找出Dos Header.*/
dosHeader = (IMAGE_DOS_HEADER*)pSrcFile;
/*根据dosHeader里面的一个成员找到PE Header.*/
ntHeader = (IMAGE_NT_HEADERS*)(pSrcFile + dosHeader->e_lfanew);
/*找出第一个Sesion Header.*/
sectionHeader = (IMAGE_SECTION_HEADER*)((char*)ntHeader + sizeof(IMAGE_NT_HEADERS));
/*找出.rsrc的Section Header.*/
printf("There are the Section Header follow./n");
for(int i=0;i<ntHeader->FileHeader.NumberOfSections;i++,sectionHeader++)
{
printf("Section Header #%d: %s/n",i+1,sectionHeader->Name);
if(strcmp((char*)sectionHeader->Name,".rsrc") == 0)
rsrc_SectionHeader = sectionHeader;///找到.rsrc的Section Header了!!!
}
/*找出.rsrc Section.*/
dirRoot = (IMAGE_RESOURCE_DIRECTORY*)(pSrcFile + rsrc_SectionHeader->PointerToRawData);
/*找出第一个资源目录*/
entry = (IMAGE_RESOURCE_DIRECTORY_ENTRY*)((char*)dirRoot +sizeof(IMAGE_RESOURCE_DIRECTORY_ENTRY));
/*找出.rsrc 中 Icon 的资源目录*/
printf("There are the directory of the .rsrc Section./n");
for(int j=0;j<dirRoot->NumberOfIdEntries+dirRoot->NumberOfNamedEntries;j++,entry++)
{
printf("Resource Directory #%d: %d/n",j+1,entry->Name);
if(entry->Name == 3)
iconEntry = (IMAGE_RESOURCE_DIRECTORY_ENTRY*)((char*)dirRoot+entry->OffsetToDirectory);//找到 Icon 的资源目录了!!!
}
tempDir = (IMAGE_RESOURCE_DIRECTORY*)iconEntry;
tempEntry = (IMAGE_RESOURCE_DIRECTORY_ENTRY*)((char*)tempDir+sizeof(IMAGE_RESOURCE_DIRECTORY));
printf("There are the /"IconItems/" of the icon directory./n");
for(int k=0;k<tempDir->NumberOfIdEntries+tempDir->NumberOfNamedEntries;k++,tempEntry++)
{
printf("IconItem %d Is %d/n",k+1,tempEntry->DataIsDirectory);
if(tempEntry->DataIsDirectory > 0 && k==0)
{
//拿到第一个图标的"Item"
firstIconDir = (IMAGE_RESOURCE_DIRECTORY*)((char *)dirRoot+tempEntry->OffsetToDirectory);
firstIconEntry = (IMAGE_RESOURCE_DIRECTORY_ENTRY*)((char*)firstIconDir+sizeof(IMAGE_RESOURCE_DIRECTORY));
firstIconData = (IMAGE_RESOURCE_DATA_ENTRY*)((char*)dirRoot+firstIconEntry->OffsetToData);
}
}
//得到第一个图标Item的图像数据的物理地址
pFirstIcon = firstIconData->OffsetToData - rsrc_SectionHeader->VirtualAddress + (char*)dirRoot;
//返回
memcpy(pFirstIcon,pdata,size);
//写入文件
SetFilePointer(hSrcFile,0,0,FILE_BEGIN);
WriteFile(hSrcFile,pSrcFile,dwFileSize,&dwReaded,NULL);
/*释放资源.*/
CloseHandle(hSrcFile);
free(pSrcFile);
}
int main(int argc, char* argv[])
{
char *pIconData ;
DWORD dwIconSize;
GetIconData("Test1.exe",&pIconData,&dwIconSize);
WriteIconData("Test2.exe",pIconData,dwIconSize);
printf("Hello World!/n");
return 0;
}
终于修改了EXE的图标罗相关推荐
- 使用Python修改可执行文件-EXE的图标
文章目录 1. 前置知识 2. 方法1 不靠谱,但很方便的资源替换法 3. 方法2 使用PeFile库修改图标 4. 优化体验 接受jpg.png.bmp等格式的图片作为icon 参考链接 Pytho ...
- 如何给生成的exe加图标
一.简述 今天就简单介绍一下如何给exe加图标,其实很简单,但是主要是为了讲述另一个问题,这也是之前遇到的一个容易忽略的问题. 首先我们了解一下一共有多少个图标可以设置. 看到下面这张图,我们首先会了 ...
- qt 修改.exe文件图标_如何在没有错误的情况下更改压缩的.EXE文件上的图标
qt 修改.exe文件图标 We've previously shown you how to modify the icon on an .EXE file, but if you've tried ...
- VC++编程实现修改EXE文件图标
VC++编程实现修改EXE文件图标 刚才发现论坛上面有网友问:如何通过编程实现修改EXE文件的图标,类似于 熊猫烧香 的效果!自己也对这个比较感兴趣网上找了找,找到了两种方法,可以满足大家都要求了,这 ...
- 用UpdateResource修改EXE文件图标的多源码(已修正) 注:转帖请包函作者信息.(作者:菜新)
微软官网UpdateResource 其它参考信息: https://msdn.microsoft.com/zh-cn/library/ms648008.aspx#_win32_Updating_Re ...
- C#怎么修改生成的EXE文件图标
C#怎么修改生成的EXE文件图标 工具/原料 1.VS,Visual Studio 2013或其他版本 2-ico的图标文件一个 方法/步骤 1.打开你的项目文件,如下图,选择release选项 2. ...
- C#上位机开发—— 修改窗口图标和exe文件图标
一.准备应用程序图标 首先寻找一个好看的应用程序图标图片,然后使用在线工具转换为 .ico格式: 二.修改窗口图标 在窗口的属性中找到Icon项,选择要设置的图标即可: 运行后即可看到窗口图标被修改: ...
- Qt修改exe文件图标
修改Qt生成exe的图标 1. 直接添加.ico 首先要注意的一点是,你的.ico文件不可以是直接用过jpg等图片格式直接修改后缀名形成的,必须是用转换工具来通过jpg转换成ico的格式,不然就会出现 ...
- 改变exe文件图标的方法
说句实话,要想用普通的方法来替换图标,不是完全不可行,当然也不是完全可行.这个看似简单的问题并不是想象中那么容易解决,为什么有人修改exe的图标总是失败,其实他忽视了exe和图标的复杂性,用简单的方法 ...
最新文章
- 使用容器和数据库克隆进行数据库迁移
- 微信支付 - 构建商户端支付成功的回调接口
- 射击的乐趣:WIN32诠释打飞机游戏
- C++可重载运算符和不可重载运算符
- Android 带着用户名的SharedPreferences
- 在QEMU硬件环境中启动 kernel 2.6 + busybox as rootfs
- C++之初始化列表的一个笔记
- win10搭建Linux子系统,win10中搭建Linux子系统
- 使用MIB来监控你的应用(tuxedo mib)
- 经典论文解析——Unet和Vnet——图像分割
- win7网络适配器_win7网络重置
- 《Git与Github使用笔记》第12章 Pull Request的使用
- 如何彻底禁用谷歌Chrome更新
- 原神换服报错(二级地址解析失败),换服失败,无反应
- 池化方法总结(Pooling) 和卷积 。 第三部分讲的很好
- 辽宁计算机考研学校二本,二本院校逆袭985到底有多难?
- android 屏蔽实体按键,Android中屏蔽返回键,home键以及其他实体按键
- pmap gdb 分析堆外内存泄露情况
- 服务器显示内存错误怎么办,服务器怎么查看内存故障
- 个人赛 A 题 传球游戏(ball)
热门文章
- meta20 无法安装 google play_不ROOT不刷机,小米手机如何安装谷歌 GMS 三件套
- 关于我对网赚的思路,赚钱的方法透露
- composer镜像源切换
- CentOS无人值守安装
- 华东师范大学张凯教授课题组招收图神经网络方向博士生
- PAT-B 1036. 跟奥巴马一起编程(15)(15 分) 画方型字符
- 回归常态啦 2020.12.08日记
- matlab中f分布,在matlab中用哪个函数求F分布的分位点(分子分母的自由度和概率均已知)...
- Structure Boundary Preserving Segmentation for Medical Image with Ambiguous Boundary
- 奇异值分解实验:图像压缩与推荐系统