9. 资源表
找到资源并使用:
HRSRC hSrc = FindResource(NULL, TEXT("RollName"), TEXT("Exe"));//遍历结构直到获得数据而非目录
DWORD dwSize = SizeofResource(NULL, hSrc);
HGLOBAL hResLoaded = LoadResource(NULL, hSrc);//数据起始地址
LPVOID pExe = LockResource(hResLoaded); //数据起始地址
IMAGE_DIRECTORY_ENTRY_RESOURCE;
IMAGE_RESOURCE_DIRECTORY;
IMAGE_RESOURCE_DIRECTORY_ENTRY;
RT_ICON;
IMAGE_RESOURCE_DATA_ENTRY;
//可能是这种结构
typedef struct _IMAGE_RESOURCE_DIRECTORY {
DWORD Characteristics; //可忽略
DWORD TimeDateStamp; //可忽略
WORD MajorVersion; //可忽略
WORD MinorVersion; //可忽略
WORD NumberOfNamedEntries; //有命名字项的个数
WORD NumberOfIdEntries; //Id项的个数
// IMAGE_RESOURCE_DIRECTORY_ENTRY DirectoryEntries[];
} IMAGE_RESOURCE_DIRECTORY, *PIMAGE_RESOURCE_DIRECTORY;
//也可能是这种结构
typedef struct _IMAGE_RESOURCE_DATA_ENTRY {
DWORD OffsetToData; //数据的RVA
DWORD Size; //数据的size
DWORD CodePage; //可忽略
DWORD Reserved; //可忽略
} IMAGE_RESOURCE_DATA_ENTRY, *PIMAGE_RESOURCE_DATA_ENTRY;
typedef struct _IMAGE_RESOURCE_DIRECTORY_ENTRY {
union {
struct {
DWORD NameOffset:31; //相对于与资源节的偏移量
DWORD NameIsString:1; //是否为字符串
} DUMMYSTRUCTNAME;
DWORD Name;
WORD Id; //不为字符串则为资源Id
} DUMMYUNIONNAME;
union {
DWORD OffsetToData; //不为目录则为数据
struct {
DWORD OffsetToDirectory:31; //相对于与资源节的偏移量
DWORD DataIsDirectory:1; //是否为目录
} DUMMYSTRUCTNAME2;
} DUMMYUNIONNAME2;
} IMAGE_RESOURCE_DIRECTORY_ENTRY, *PIMAGE_RESOURCE_DIRECTORY_ENTRY;
举例:
9600h是资源表的地址,这一行代表是IMAGE_RESOURCE_DIRECTORY,有价值的是最后两个WORD,NumberOfNamedEntries和NumberOfIdEntries。
9610h处的8字节表示IMAGE_RESOURCE_DIRECTORY_ENTRY,前4字节最高位为1,说明NameIsString,低31bit的5C4h是相对于9600h的偏移,于是转去9BC4h查看。
9BC4h处是IMAGE_RESOURCE_DIRECTORY_STRING结构,3代表Length,后面是Unicode字符串。
回到9614h,最高位是1,说明DataIsDirectory,低31bit的50h是相对于9600h的偏移,于是转去9650h查看。
同样,9650h是资源表的地址,这一行代表是IMAGE_RESOURCE_DIRECTORY,有价值的是最后两个WORD,NumberOfNamedEntries和NumberOfIdEntries。继续按以上方式解析,得到9BCCh处的IMAGE_RESOURCE_DIRECTORY_STRING,以及97A0h处的IMAGE_RESOURCE_DIRECTORY。
97B0处是IMAGE_RESOURCE_DIRECTORY_ENTRY,第一个4字节的最高位为0,低16bit表示语言ID,第二个4字节的最高位也为0,低16bit表示OffsetToData,相当于9600h,所以定位到9A10h。
9A10h处代表IMAGE_RESOURCE_DATA_ENTRY,前4字节352B0h是RVA,接着4字节1600h是size,于是可以提取出二进制文件。352B0h在文件偏移208B0h处,提取1600h字节后是一个PE文件。