一、概述
想要获取一个可执行文件(PE文件)里包含的资源文件,首先要解析可执行文件,得到资源存储的地址及大小,可参考 https://blog.youkuaiyun.com/zhyulo/article/details/85717711 。然后,根据资源存储方式,得到各资源的数据内容及其大小,可参考 https://blog.youkuaiyun.com/zhyulo/article/details/85930045 。
PE文件的资源中,对话框的资源类型ID=5。对话框不仅可以通过ID区别,也可以通过对话框名区别,也就是说对话框在资源树的第二层可能是数字,也可能是字符串,这点需要注意。
对话框可以说是资源中最重要、最复杂的一种。它在结构上分为2种:基本对话框和扩展对话框。而由于对于一些属性,既可能是字符串ID,又可能直接就是字符串,所以在这里又把它们的存储设计了一种新的方式。而由于对话框上有不同控件,不同控件所需的参数又不尽相同,所以解析对话框在资源中的数据流一直是一个难点。在博主的不断的努力下,才揭开了它的神秘面纱。
在RC文件中,基本对话框和扩展对话框的定义如下所示:
IDD_ABOUTBOX DIALOG DISCARDABLE 0, 0, 235, 55
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "关于 test"
FONT 9, "宋体"
BEGIN
ICON IDR_MAINFRAME,IDC_STATIC,11,17,20,20
LTEXT "test 1.0 版",IDC_STATIC,40,10,119,8,
SS_NOPREFIX
LTEXT "版权所有 (C) 2019",IDC_STATIC,40,25,119,8
DEFPUSHBUTTON "确定",IDOK,178,7, 50,14,WS_GROUP
END
IDD_TEST_DIALOG DIALOGEX 0, 0, 320, 200
STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
EXSTYLE WS_EX_APPWINDOW
CAPTION "test"
FONT 9, "宋体"
BEGIN
DEFPUSHBUTTON "确定",IDOK,260,7,50,14
PUSHBUTTON "取消",IDCANCEL,260,23,50,14
LTEXT "TODO: 在这里设置对话控制。",IDC_STATIC,50,90,200,8
END
二、ID与字符串组合结构
由于对于一些属性,既可能是字符串ID,又可能直接就是字符串,所以在这里又把它们的存储设计了一种新的方式。注意,这里的字符串都是Unicode字符串。如果该结构的第一个字是0xFFFF,说明该结构是一个ID,ID值为第二个字。否则,该结构是一个字符串,以'\0'结束。我们这里把这个结构定义为IDStr。
三、基本对话框的资源结构
基本对话框包括对话框头和子控件2部分组成。对话框头与每一个子控件4字节对齐。
1.对话框头
对话框头的结构如下所示:
struct DialogBoxHeader
{
DWORD Style;//标准窗口样式
DWORD ExStyle;//扩展窗口样式
WORD DlgItems;//控件数量
WORD x;//起点坐标
WORD y;
WORD cx;//宽
WORD cy;//高
IDStr menuName;//菜单名
IDStr ClassName;//类名
IDStr szCaption;//对话框标题
};
如果Style的DS_SETFONT位为1,那么在DialogBoxHeader的结构后还有字体结构,字体结构如下:
struct DialogFont
{
WORD wPointSize;//字体大小
WCHAR FontName[1];
};
2.子控件
基本对话框的子控件结构如下:
str