序
好多年前的一些恶作剧程序就是将windows上其他的程序图标全部换成一个;
或者将一个用户常用的一个应用(比如QQ)图标替换到一个其他程序上,然后将该应用替换伪装成这个常用的应用。
当用户点击的时候,运行的可能是意想不到的程序。
抛开恶作剧的想法,我们单从技术角度去看这个问题,如何去实现呢?
都是资源
程序图标都是资源图片,在打包的时候,由打包程序拷贝到exe的程序文件里面去了。
因为exe文件是有对应的格式的,不同的数据存储在对应位置,而且格式比较复杂。
有兴趣的小伙伴可以百度搜索相关的exe文件格式介绍,并且还有一个PEView的文件查看器。
抛开繁杂的exe文件格式,我们如何去进行操作呢?
WIN32 API
微软提供了繁多的API,供我们来使用。
其中 LoadLibraryEx 函数可以加载dll或者exe,返回模块句柄;
再通过 EnumResourceNames 函数枚举出对应的资源(比如图标),通过传入的回调函数进行操作;
在回调函数中通过 UpdateResource 函数操作资源,这样就可以实现对exe文件中资源的更换。
需要注意的是在替换之前,需要将需要替换的exe文件里面的资源删除;再将另一个exe文件的资源(比如图标)更新到该exe里面,这样我们就实现了程序图标的替换,以假乱真。
具体实现
代码很短,且有详细的注释,请看:
删除图标回调函数BOOL CALLBACK DelIcons(HMODULE hModule, LPCWSTR lpszType, LPWSTR lpszName, LONG_PTR lParam) { HANDLE hUpdate = (HANDLE)lParam; void* pData = 0; // 数据为空,即为删除 int nSizeOfIconRes = 0; UpdateResource(hUpdate,lpszType,lpszName,MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),pData,nSizeOfIconRes); return TRUE;}替换图标回调函数BOOL CALLBACK UpdateIcons(HMODULE hModule, LPCWSTR lpszType, LPWSTR lpszName, LONG_PTR lParam) { HANDLE hUpdate = (HANDLE)lParam; HRSRC hRes = FindResource(hModule,lpszName,lpszType); // 查找数据源 HGLOBAL hResLoaded = LoadResource(hModule, hRes); // 加载数据源 void* pData = LockResource(hResLoaded); // 加锁 int nSizeOfIconRes = SizeofResource(hModule,hRes); // 获取资源大小 UpdateResource(hUpdate,lpszType,lpszName,MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),pData,nSizeOfIconRes); UnlockResource(hResLoaded); // 解锁 FreeResource(hResLoaded); // 释放资源 return TRUE;}// brief changeIcon 改变程序图标( eg: changeIcon("xxx.exe", "QQ.exe");/// 将 QQ.exe 的企鹅图标 换到 xxx.exe;)/// param dstApp 要改图标的程序名称/// param srcApp 图标来源图标///void changeIcon(const char*dstApp, const char*srcApp) { HANDLE hUpdate = BeginUpdateResourceA(dstApp, false); // 加载目的文件,并删除图标 HMODULE hdst = LoadLibraryExA(dstApp, 0, LOAD_LIBRARY_AS_DATAFILE); EnumResourceNames(hdst,RT_ICON,DelIcons,(long)hUpdate); EnumResourceNames(hdst,RT_GROUP_ICON,DelIcons,(long)hUpdate); FreeLibrary(hdst); // 加载源文件,并更新图标 HMODULE hsrc = LoadLibraryExA(srcApp, 0, LOAD_LIBRARY_AS_DATAFILE); EnumResourceNames(hsrc,RT_ICON,UpdateIcons,(long)hUpdate); EnumResourceNames(hsrc,RT_GROUP_ICON,UpdateIcons,(long)hUpdate); FreeLibrary(hsrc); EndUpdateResource(hUpdate,FALSE);}
使用的时候,只需要简单的传入两个对应的exe路径即可:
int main(int argc, char* argv[]){ changeIcon("X:/xxx/xxx.exe", "X:/xxx/QQ.exe"); return 0;}
总结
希望大家看后能够对exe文件有所理解,其实它也只是一个有着对应格式的二进制文件而已,只是windows赋予它可执行权限而已。
此文仅作为技术讨论,请勿乱用,否则后果自负,与本人无关!
如果觉得我写的还不错的话,求赞,求关注哦!(^▽^)