这些天研究怎样修改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的图标罗相关推荐

  1. 使用Python修改可执行文件-EXE的图标

    文章目录 1. 前置知识 2. 方法1 不靠谱,但很方便的资源替换法 3. 方法2 使用PeFile库修改图标 4. 优化体验 接受jpg.png.bmp等格式的图片作为icon 参考链接 Pytho ...

  2. 如何给生成的exe加图标

    一.简述 今天就简单介绍一下如何给exe加图标,其实很简单,但是主要是为了讲述另一个问题,这也是之前遇到的一个容易忽略的问题. 首先我们了解一下一共有多少个图标可以设置. 看到下面这张图,我们首先会了 ...

  3. qt 修改.exe文件图标_如何在没有错误的情况下更改压缩的.EXE文件上的图标

    qt 修改.exe文件图标 We've previously shown you how to modify the icon on an .EXE file, but if you've tried ...

  4. VC++编程实现修改EXE文件图标

    VC++编程实现修改EXE文件图标 刚才发现论坛上面有网友问:如何通过编程实现修改EXE文件的图标,类似于 熊猫烧香 的效果!自己也对这个比较感兴趣网上找了找,找到了两种方法,可以满足大家都要求了,这 ...

  5. 用UpdateResource修改EXE文件图标的多源码(已修正) 注:转帖请包函作者信息.(作者:菜新)

    微软官网UpdateResource 其它参考信息: https://msdn.microsoft.com/zh-cn/library/ms648008.aspx#_win32_Updating_Re ...

  6. C#怎么修改生成的EXE文件图标

    C#怎么修改生成的EXE文件图标 工具/原料 1.VS,Visual Studio 2013或其他版本 2-ico的图标文件一个 方法/步骤 1.打开你的项目文件,如下图,选择release选项 2. ...

  7. C#上位机开发—— 修改窗口图标和exe文件图标

    一.准备应用程序图标 首先寻找一个好看的应用程序图标图片,然后使用在线工具转换为 .ico格式: 二.修改窗口图标 在窗口的属性中找到Icon项,选择要设置的图标即可: 运行后即可看到窗口图标被修改: ...

  8. Qt修改exe文件图标

    修改Qt生成exe的图标 1. 直接添加.ico 首先要注意的一点是,你的.ico文件不可以是直接用过jpg等图片格式直接修改后缀名形成的,必须是用转换工具来通过jpg转换成ico的格式,不然就会出现 ...

  9. 改变exe文件图标的方法

    说句实话,要想用普通的方法来替换图标,不是完全不可行,当然也不是完全可行.这个看似简单的问题并不是想象中那么容易解决,为什么有人修改exe的图标总是失败,其实他忽视了exe和图标的复杂性,用简单的方法 ...

最新文章

  1. 使用容器和数据库克隆进行数据库迁移
  2. 微信支付 - 构建商户端支付成功的回调接口
  3. 射击的乐趣:WIN32诠释打飞机游戏
  4. C++可重载运算符和不可重载运算符
  5. Android 带着用户名的SharedPreferences
  6. 在QEMU硬件环境中启动 kernel 2.6 + busybox as rootfs
  7. C++之初始化列表的一个笔记
  8. win10搭建Linux子系统,win10中搭建Linux子系统
  9. 使用MIB来监控你的应用(tuxedo mib)
  10. 经典论文解析——Unet和Vnet——图像分割
  11. win7网络适配器_win7网络重置
  12. 《Git与Github使用笔记》第12章 Pull Request的使用
  13. 如何彻底禁用谷歌Chrome更新
  14. 原神换服报错(二级地址解析失败),换服失败,无反应
  15. 池化方法总结(Pooling) 和卷积 。 第三部分讲的很好
  16. 辽宁计算机考研学校二本,二本院校逆袭985到底有多难?
  17. android 屏蔽实体按键,Android中屏蔽返回键,home键以及其他实体按键
  18. pmap gdb 分析堆外内存泄露情况
  19. 服务器显示内存错误怎么办,服务器怎么查看内存故障
  20. 个人赛 A 题 传球游戏(ball)

热门文章

  1. meta20 无法安装 google play_不ROOT不刷机,小米手机如何安装谷歌 GMS 三件套
  2. 关于我对网赚的思路,赚钱的方法透露
  3. composer镜像源切换
  4. CentOS无人值守安装
  5. 华东师范大学张凯教授课题组招收图神经网络方向博士生
  6. PAT-B 1036. 跟奥巴马一起编程(15)(15 分) 画方型字符
  7. 回归常态啦 2020.12.08日记
  8. matlab中f分布,在matlab中用哪个函数求F分布的分位点(分子分母的自由度和概率均已知)...
  9. Structure Boundary Preserving Segmentation for Medical Image with Ambiguous Boundary
  10. 奇异值分解实验:图像压缩与推荐系统