PE文件解析-资源中的快捷键结构

一、概述

    想要获取一个可执行文件(PE文件)里包含的资源文件,首先要解析可执行文件,得到资源存储的地址及大小,可参考 https://blog.csdn.net/zhyulo/article/details/85717711 。然后,根据资源存储方式,得到各资源的数据内容及其大小,可参考 https://blog.csdn.net/zhyulo/article/details/85930045 。

    PE文件的资源中,快捷键的资源类型ID=9。在RC文件中,快捷键的定义方式如下:

IDR_ACCELERATOR ACCELERATORS DISCARDABLE 
BEGIN
    "O",            ID_FILE_OPEN,           VIRTKEY, CONTROL, NOINVERT
    "S",            ID_FILE_SAVE,           VIRTKEY, CONTROL, NOINVERT
END

二、快捷键的资源结构

    快捷键在资源中,以AccelTableEntry快捷键结构数组方式存储,该结构体定义如下:

struct AccelTableEntry
{
	WORD fFlags;//功能键
	WORD wAnsi;//虚拟键值
	WORD wId;//快捷键id
	WORD padding;
};

fFlags: 功能键,比如Shift、Ctrl、Alt等按键值,该成员每一位都代表一个涵义,可通过或运算组合使用。如果第8位(0x80)值为1,代表该数组成员为最后一个元素。常见功能键值有:

#define FALT		16
#define FCONTROL	8
#define FNOINVERT	2
#define FSHIFT		4
#define FVIRTKEY	1

wAnsi: 按键值,比如F1~F24按键,字母按键,数字按键等等。按键值定义位于winuser.h文件中,以VK_开头定义。

wId: 快捷键响应的ID值。

padding: 4字节对齐用,没有实际意义。

三、示例程序

    以下程序展示了如何从PE文件的快捷键资源流中读取并输出成RC文件形式的代码。

void GetAccel(void *buf, WORD id)
{
	struct AccelTableEntry
	{
		WORD fFlags;//功能键
		WORD wAnsi;//虚拟键值
		WORD wId;//快捷键id
		WORD padding;
	} *Entry = (AccelTableEntry*)buf;
	PutIDName(id, "IDR_ACCELERATOR");
	Puts(" ACCELERATORS PRELOAD MOVEABLE PURE\nBEGIN\n");
	for(int i=0; ; i++)
	{
		Puts("\t");
		if(Entry[i].wAnsi >= 'A' && Entry[i].wAnsi <= 'Z')
			Print("\"%c\",", Entry[i].wAnsi);
		else if(Entry[i].wAnsi >= '0' && Entry[i].wAnsi <= '9')
			Print("\"%c\",", Entry[i].wAnsi);
		else if(Entry[i].wAnsi >= VK_F1 && Entry[i].wAnsi <= VK_F24)
			Print("VK_F%d,", Entry[i].wAnsi - VK_F1 + 1);
		else if(Entry[i].wAnsi >= VK_NUMPAD0 && Entry[i].wAnsi <= VK_NUMPAD9)
			Print("VK_NUMPAD%d,", Entry[i].wAnsi - VK_NUMPAD0);
		else Print("%d,", Entry[i].wAnsi);
		Puts("\t");

		PutIDName(Entry[i].wId, "ID_ACCEL");
		if(Entry[i].fFlags & FVIRTKEY) Puts(", VIRTKEY");
		else Puts(", ASCII");
		if(Entry[i].fFlags & FNOINVERT) Puts(", NOINVERT");
		if(Entry[i].fFlags & FSHIFT) Puts(", SHIFT");
		if(Entry[i].fFlags & FCONTROL) Puts(", CONTROL");
		if(Entry[i].fFlags & FALT) Puts(", ALT");
		Puts("\n");
		if(Entry[i].fFlags & 0x80) break;
	}
	Puts("END\n");
}

 

©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页