《Windows PE》7.4 资源表应用

本节我们将通过两个示例程序,演示对PE文件内图标资源的置换与提取。

本节必须掌握的知识点:

        更改图标

        提取图标资源

7.4.1 更改图标

让我们来做一个实验,替换PE文件中现有的图标。如果手工替换,一定是先找到资源表,然后分别替换图标资源和图标组资源就可以了。当然这个过程稍微有点繁复,可能会涉及到其他资源的重定位。还好,Windows操作系统为开发者提供了一组更新PE文件中资源的API函数:BeginUpdateResource、UpdateResource、EndUpdateResource。用来枚举 PE 文件中资源的函数有:EnumResourceTypes、EnumResourceNames、EnumResourceLanguages。具体的使用方法可以参见MSDN,下面我们将使用这些函数实现图标资源的替换。

实验五十:更改图标

●模块1:resource.h(略)

●模块2:peinfo.rc(略)

●模块3:info.h

#pragma once
#ifndef INFO_H_
#define INFO_H_

#include <windows.h>
#include <richedit.h>	//CHARFORMAT富文本结构定义
#include <commctrl.h>	//通用控件
#pragma comment(lib,"comctl32.lib")
#include <strsafe.h>	//StringCchCopy
#include <stdlib.h>

// 文件中的ICO头部
typedef struct
{
	byte bWidth;				//宽度
	byte bHeight;				//高度
	byte bColorCount;			//颜色数
	byte bReserved;			//保留字,必须为0
	WORD wPlanes;			//调色板
	WORD wBitCount;			//每个像素的位数
	DWORD dwBytesInRes;		//资源长度
	DWORD dwImageOffset;	//资源在文件偏移
}ICON_DIR_ENTRY;

typedef struct
{
	WORD idReserved;			//保留字,必须为0
	WORD idType;				//资源类别,如果是1表示为ICO文件
	WORD idCount;				//图标数量
	//ICON_DIR_ENTRY idEntries;	//图标项,一个图标一项
}ICON_DIR;

//PE中ICO头部
typedef struct
{
	byte bWidth;			//宽度
	byte bHeight;			//高度
	byte bColorCount;		//颜色数
	byte bReserved;		//保留字,必须为0
	WORD wPlanes;		//调色板
	WORD wBitCount;		//每个像素的位数
	DWORD dwBytesInRes;	//资源长度
	WORD nID;			//资源在文件序号
}PE_ICON_DIR_ENTRY;
typedef struct
{
	WORD idReserved;	//保留字,必须为0
	WORD idType;		//资源类别,如果是1表示为ICO文件
	WORD idCount;		//图标数量
	PE_ICON_DIR_ENTRY idEntries;	//图标项,一个图标一项
}PE_ICON_DIR;

//函数声明
BOOL CALLBACK DlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
void Exception(void);
void init(); //初始化
void  _OpenFile();//打开PE文件并处理
int  CALLBACK _Handler(EXCEPTION_POINTERS * lpExceptionPoint);
void ShowErrMsg();
void _AppendInfo(const TCHAR * _lpsz);//往文本框中追加文本
//将boy.ico图标替换指定PE程序的图标
BOOL _doUpdate(TCHAR* lpszFile, TCHAR* lpszExeFile);

#endif

●模块4:PEUpdateIcon.c

/*------------------------------------------------------------------------
 FileName: PEUpdateIcon.c
 实验50:更改程序图标实例(支持32位和64位PE文件)
 (c) bcdaren, 2024
-----------------------------------------------------------------------*/
#include <strsafe.h>	//StringCchCopy
#include "resource.h"
#include "info.h"

HANDLE hInstance;
HWND hWinMain, hWinEdit;
HMODULE hRichEdit;
TCHAR szFileName[MAX_PATH];
HANDLE hFileDump;
HANDLE hFile;

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int nCmdShow)
{
	TCHAR	szDllEdit[] = TEXT("RichEd20.dll");
	TCHAR	szClassEdit[] = TEXT("RichEdit20W");//peinfo.rc中定义
	hRichEdit = LoadLibrary((LPCWSTR)&szDllEdit);
	hInstance = GetModuleHandle(NULL);
	DialogBoxParam(hInstance, MAKEINTRESOURCE(DLG_MAIN), NULL, 
(DLGPROC)DlgProc, (LPARAM)0);
	FreeLibrary(hRichEdit);
	return 0;
}

//初始化窗口函数
void init()
{
	CHARFORMAT stCf;
	TCHAR	szClassEdit[] = TEXT("RichEdit20A");
	TCHAR	szFont[] = TEXT("宋体");
	HINSTANCE hInstance;

	hWinEdit = GetDlgItem(hWinMain, IDC_INFO);
	//为窗口程序设置图标
	hInstance = GetModuleHandle(NULL);
	HICON hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(ICO_MAIN));
	//HICON hIcon = LoadIcon(hInstance, TEXT("#111"));
	SendMessage(hWinMain, WM_SETICON, ICON_BIG, (LPARAM)hIcon);

	//设置编辑控件
	SendMessage(hWinEdit, EM_SETTEXTMODE, TM_PLAINTEXT, 0);
	RtlZeroMemory(&stCf, sizeof(stCf));
	stCf.cbSize = sizeof(stCf);
	stCf.yHeight = 9 * 20;
	stCf.dwMask = CFM_FACE | CFM_SIZE | CFM_BOLD;
	StringCchCopy((LPTSTR)&stCf.szFaceName, lstrlen(szFont) + 1, (LPCTSTR)&szFont);
	SendMessage(hWinEdit, EM_SETCHARFORMAT, 0, (LPARAM)&stCf);
	SendMessage(hWinEdit, EM_EXLIMITTEXT, 0, -1);//设为-1表示无限制
}

//富文本窗口回调函数
BOOL CALLBACK DlgProc(HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam)
{
	const TCHAR szErr[] = TEXT("文件格式错误!");
	const TCHAR szErrFormat[] = TEXT("这个文件不是PE格式的文件!");
	switch (wMsg)
	{
	case WM_CLOSE:
		EndDialog(hWnd, 0);
		return TRUE;

	case WM_INITDIALOG:
		hWinMain = hWnd;
		init();	//初始化
		return TRUE;

	case WM_COMMAND:
		switch (wParam)
		{
		case IDM_EXIT:
			EndDialog(hWnd, 0);
			return TRUE;

		case IDM_OPEN:
			_OpenFile();
			return TRUE;
		case IDM_1:
			MessageBox(NULL, szErrFormat, szErr, MB_ICONWARNING);
			return TRUE;
		case IDM_2:
			MessageBox(NULL, szErrFormat, szErr, MB_ICONWARNING);
			return TRUE;
		case IDM_3:
			MessageBox(NULL, szErrFormat, szErr, MB_ICONWARNING);
			return TRUE;
		}
	}
	return FALSE;
}

//执行比对PE文件
void _OpenFile()
{
	OPENFILENAME stOF;
	HANDLE hFile = NULL;
	HANDLE hMapFile = NULL;
	PBYTE lpMemory = NULL;	//PE文件内存映射文件地址
	int dwFileSize;
	const TCHAR szDefaultExt[] = TEXT("exe");
	const TCHAR szFilter[] = TEXT("PE Files (*.exe)\0*.exe\0")\
		TEXT("DLL Files(*.dll)\0*.dll\0")\
		TEXT("SCR Files(*.scr)\0*.scr\0")\
		TEXT("FON Files(*.fon)\0*.fon\0")\
		TEXT("DRV Files(*.drv)\0*.drv\0")\
		TEXT("All Files(*.*)\0*.*\0\0");
	const TCHAR szErr[] = TEXT("文件格式错误!");
	const TCHAR szErrFormat[] = TEXT("操作文件时出现错误!");
	const TCHAR szOut1[] = TEXT("----------------------------------------------------------------\r\n")
		TEXT("待处理的PE文件:%s\r\n");
	static TCHAR lpszBoyIcon[] = 
TEXT("D:\\code\\winpe\\ch07\\PEUpdateIcon\\boy.ico");
	const TCHAR szFailure[] = TEXT("执行图标修改失败。");
	const TCHAR szSuccess[] = TEXT("恭喜你,图标修改成功成功的。");

	IMAGE_DOS_HEADER *lpstDOS;	//DOS块地址
	IMAGE_NT_HEADERS *lpstNT;	//PE文件头地址

	//显示打开文件对话框
	RtlZeroMemory(&st
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值