PE(Portable Executable)可移植的执行体,Win32平台下的可执行文件格式。常见的exe、dll、sys、scr都是PE文件。
- 分析PE文件格式,直接修改
此种方式需要对PE文件的格式比较了解,才能进行修改,否则很可能将文件损坏。
本文主要描述第二种方式:
- 通过Windows API进行修改
- BeginUpdateResource
1 HANDLE WINAPI BeginUpdateResource( 2 _In_ LPCTSTR pFileName, 3 _In_ BOOL bDeleteExistingResources 4 );
参数pFileName为需要修改资源的文件名,bDeleteExistingResources是否删除pFileName参数指定的现有资源,成功则返回提供给UpdateResource和EndUpdateResource函数使用的句柄。
- UpdateResource
1 BOOL WINAPI UpdateResource( 2 _In_ HANDLE hUpdate, 3 _In_ LPCTSTR lpType, 4 _In_ LPCTSTR lpName, 5 _In_ WORD wLanguage, 6 _In_opt_ LPVOID lpData, 7 _In_ DWORD cbData 8 );
hUpdate:指定更新文件句柄,此句柄由BeginUpdateResource函数返回。
lpType:指向说明将被更新的资源类型的字符串,可以是以下预定义资源类型,也可以是自定义资源,如"png"。
RT_ACCELERATOR 加速器表RT_ANICURSOR 动态光标RT_ANIICON 动态图标RT_BITMAP 位图资源RT_CURSOR 由硬件支持的光标资源RT_DIALOG 对话框RT_FONT 字体资源RT_FONTDIR 字体目录资源RT_GROUP_CURSOR 与硬件无关的光标资源RT_GROUP_ICON 与硬件无关的目标资源RT_HTML HTML文档RT_ICON 由硬件支持的图标资源RT_MENU 菜单资源RT_MESSAGETABLE 消息表的入口RT_PLUGPLAY 即插即用资源RT_RCDATA 应用程序定义资源(原始数据或自定义资源)RT_STRING 字符表入口RT_VERSION 版本资源RT_VXD VXDlpName:指向说明待被更新的资源名称的字符串,可以通过宏MAKEINTRESOURCE(ID)获取,ID为资源ID。
wLanguage:指定将被更新资源的语言标识,可参见宏MAKELANGID。
lpData:指向被插入可支持文件的资源数据的指针,如果lpData为NULL,所指定的资源将从可执行文件中被删除。
cbData:指定lpData中的资源数据数据大小,以字节计数。
- EndUpdateResource
1 BOOL WINAPI EndUpdateResource( 2 _In_ HANDLE hUpdate, 3 _In_ BOOL fDiscard 4 );
hUpdate用于资源更新的句柄,此句柄通过BeginUpdateResource函数返回。fDiscard用来说明是否向可执行文件中写入资源更新内容。如果此参数为TRUE,则在可执行文件中无变化;如果此参数为FALSE,则在可执行文件中写入变化。 - EnumResourceTypes
1 BOOL WINAPI EnumResourceTypes( 2 _In_opt_ HMODULE hModule, 3 _In_ ENUMRESTYPEPROC lpEnumFunc, 4 _In_ LONG_PTR lParam 5 );
为资源搜寻模块并且将它找到的每个资源类型传递给用户定义的回调函数。
- EnumResourceNames
1 BOOL WINAPI EnumResourceNames( 2 _In_opt_ HMODULE hModule, 3 _In_ LPCTSTR lpszType, 4 _In_ ENUMRESNAMEPROC lpEnumFunc, 5 _In_ LONG_PTR lParam 6 );
为每个指定类型的资源搜寻模块,并将每个查找到的资源名称传递给回调函数。
lpszType:被列举出的资源类型,可以通过IS_INTRESOURCE进行判断,如果为TRUE,表明是一个资源ID,则将指针强制转换为资源ID,并从资源中加载字符串;如果为FALSE,则认为是一个字符串指针。
#define IS_INTRESOURCE(_r) ((((ULONG_PTR)(_r)) >> 16) == 0)