BearParser
Portable Executable parsing library (from PE-bear)
Loading...
Searching...
No Matches
ResourceDirWrapper.cpp
Go to the documentation of this file.
2#include "pe/PEFile.h"
3
4#define MAX_ENTRIES 50
5#define MAX_DEPTH 5
6
7/*
8typedef struct _IMAGE_RESOURCE_DIRECTORY {
9 DWORD Characteristics;
10 DWORD TimeDateStamp;
11 WORD MajorVersion;
12 WORD MinorVersion;
13 WORD NumberOfNamedEntries;
14 WORD NumberOfIdEntries;
15 // IMAGE_RESOURCE_DIRECTORY_ENTRY DirectoryEntries[];
16} IMAGE_RESOURCE_DIRECTORY, *PIMAGE_RESOURCE_DIRECTORY;
17
18
19 // Each directory contains the 32-bit Name of the entry and an offset,
20 // relative to the beginning of the resource directory of the data associated
21 // with this directory entry. If the name of the entry is an actual text
22 // string instead of an integer Id, then the high order bit of the name field
23 // is set to one and the low order 31-bits are an offset, relative to the
24 // beginning of the resource directory of the string, which is of type
25 // IMAGE_RESOURCE_DIRECTORY_STRING. Otherwise the high bit is clear and the
26 // low-order 16-bits are the integer Id that identify this resource directory
27 // entry. If the directory entry is yet another resource directory (i.e. a
28 // subdirectory), then the high order bit of the offset field will be
29 // set to indicate this. Otherwise the high bit is clear and the offset
30 // field points to a resource data entry.
31
32#define RESOURCE_NAME_IS_STRING 0x80000000
33#define RESOURCE_DATA_IS_DIRECTORY 0x80000000
34
35
36typedef struct _IMAGE_RESOURCE_DIRECTORY_ENTRY {
37 union {
38 struct {
39 DWORD NameOffset:31;
40 DWORD NameIsString:1;
41 } name;
42 DWORD Name;
43 WORD Id;
44 };
45 union {
46 DWORD OffsetToData;
47 struct {
48 DWORD OffsetToDirectory:31;
49 DWORD DataIsDirectory:1;
50 } dir;
51 };
52} IMAGE_RESOURCE_DIRECTORY_ENTRY, *PIMAGE_RESOURCE_DIRECTORY_ENTRY;
53
54*/
55//-------------
56
57IMAGE_RESOURCE_DIRECTORY* ResourceDirWrapper::mainResourceDir()
58{
60
61 BYTE *ptr = m_Exe->getContentAt(rva, Executable::RVA, sizeof(IMAGE_RESOURCE_DIRECTORY));
62 return (IMAGE_RESOURCE_DIRECTORY*) ptr;
63}
64
65IMAGE_RESOURCE_DIRECTORY* ResourceDirWrapper::resourceDir()
66{
67 if (this->rawOff == 0) return mainResourceDir();
68
69 BYTE *ptr = m_Exe->getContentAt(this->rawOff, Executable::RAW, sizeof(IMAGE_RESOURCE_DIRECTORY));
70 return (IMAGE_RESOURCE_DIRECTORY*) ptr;
71}
72
74{
75 clear();
76 if (this->topEntryID == TOP_ENTRY_ROOT && this->album != NULL) {
77 this->album->clear();
78 }
79 IMAGE_RESOURCE_DIRECTORY* dir = resourceDir();
80 if (dir == NULL) return false;
81 size_t namesNum = dir->NumberOfNamedEntries;
82 size_t idsNum = dir->NumberOfIdEntries;
83
84 size_t totalEntries = namesNum + idsNum;
85 for (size_t i = 0; i < totalEntries && i < MAX_ENTRIES; i++ ) {
86
87 long topDirId = (this->topEntryID != TOP_ENTRY_ROOT) ? this->topEntryID : long(i) ;
88
89 //ResourceEntryWrapper(PEFile *pe, ResourceDirWrapper *parentDir, size_t entryNumber, long topEntryId, ResourcesAlbum *resAlbum)
90 ResourceEntryWrapper* entry = new ResourceEntryWrapper(this->m_PE, this, i, topDirId, this->album);
91
92 if (entry->getPtr() == NULL) {
93 delete entry;
94 break;
95 }
96 if (this->topEntryID == TOP_ENTRY_ROOT && this->album != NULL) {
97 pe::resource_type typeId = static_cast<pe::resource_type>(entry->getID());
98 this->album->mapIdToLeafType(i, typeId);
99 }
100 //this->parsedSize += val;
101 this->entries.push_back(entry);
102 }
103 //printf("Entries: %d\n", getEntriesCount());
104 return true;
105}
106
107
109{
110 if (getPtr() == NULL) return 0;
111 bufsize_t size = sizeof(IMAGE_RESOURCE_DIRECTORY);
112 size += getEntriesAreaSize();
113 return size;
114}
115
116void* ResourceDirWrapper::getFieldPtr(size_t fId, size_t subField)
117{
118 IMAGE_RESOURCE_DIRECTORY* d = resourceDir();
119 if (d == NULL) return NULL;
120
121 switch (fId) {
122 case CHARACTERISTIC: return &d->Characteristics;
123 case TIMESTAMP: return &d->TimeDateStamp;
124 case MAJOR_VER: return &d->MajorVersion;
125 case MINOR_VER: return &d->MinorVersion;
126 case NAMED_ENTRIES_NUM : return &d->NumberOfNamedEntries;
127 case ID_ENTRIES_NUM : return &d->NumberOfIdEntries;
128 }
129 return this->getPtr();
130}
131
132bufsize_t ResourceDirWrapper::getFieldSize(size_t fId, size_t subField)
133{
134 IMAGE_RESOURCE_DIRECTORY* d = resourceDir();
135 if (d == NULL) return 0;
136
137 // calculate size of the last field separately:
138 if (fId == ID_ENTRIES_NUM) {
139 void *nextPtr = (&d->NumberOfIdEntries) + 1;
140 void *argPtr = &d->NumberOfIdEntries;
141 return (BYTE*) nextPtr - (BYTE*)argPtr;
142 }
143 return DataDirEntryWrapper::getFieldSize(fId, subField);
144}
145
146QString ResourceDirWrapper::getFieldName(size_t fieldId)
147{
148 switch (fieldId) {
149 case CHARACTERISTIC: return "Characteristics";
150 case TIMESTAMP: return "TimeDateStamp";
151 case MAJOR_VER: return "MajorVersion";
152 case MINOR_VER: return "MinorVersion";
153 case NAMED_ENTRIES_NUM : return "NumberOfNamedEntries";
154 case ID_ENTRIES_NUM : return "NumberOfIdEntries";
155 }
156 return getName();
157}
158
159//-----------------------------------------------------------------
160
162{
163 delete childDir;
164 this->childDir = NULL;
165 //---
166 delete childLeaf;
167 this->childLeaf = NULL;
168}
169
171{
172 clear();
173 //---
174 offset_t childRaw = getChildAddress();
175 if (childRaw == 0 || childRaw == INVALID_ADDR) return false;
176
177 if (this->isDir()) {
178 long depth = this->parentDir->getDepth() + 1;
179 if (depth >= MAX_DEPTH) return false;
180 this->childDir = new ResourceDirWrapper(this->m_PE, this->album, childRaw, depth, topEntryID);
181 } else {
182 this->childLeaf = new ResourceLeafWrapper(m_Exe, childRaw, topEntryID);
183 if (this->album != NULL) {
184 album->putLeaf(childLeaf, topEntryID);
185 }
186 }
187 return true;
188}
189
190
191IMAGE_RESOURCE_DIRECTORY_ENTRY* ResourceEntryWrapper::getEntryPtr()
192{
193 if (this->parentDir == NULL) return NULL;
194 uint64_t offset = parentDir->getFieldOffset(ResourceDirWrapper::ID_ENTRIES_NUM);
195 if (offset == INVALID_ADDR) return NULL;
196
197 size_t lastSize = parentDir->getFieldSize(ResourceDirWrapper::ID_ENTRIES_NUM, FIELD_NONE);
198 offset += lastSize;
199 offset += (this->entryNum * sizeof(IMAGE_RESOURCE_DIRECTORY_ENTRY));
200
201 void *ptr = m_Exe->getContentAt(offset, Executable::RAW, sizeof(IMAGE_RESOURCE_DIRECTORY_ENTRY));
202 return (IMAGE_RESOURCE_DIRECTORY_ENTRY*) ptr;
203}
204
205//IMAGE_RESOURCE_DIRECTORY_ENTRY
206void* ResourceEntryWrapper::getFieldPtr(size_t fieldId, size_t subField)
207{
208 IMAGE_RESOURCE_DIRECTORY_ENTRY* entry = getEntryPtr();
209 if (entry == NULL) return NULL;
210
211 switch (fieldId) {
212 case NAME_ID_ADDR:
213 return &entry->Name;
214 case OFFSET_TO_DATA:
215 return &entry->OffsetToData;
216 }
217 return getPtr();
218}
219
221{
222 switch (fieldId) {
223 case NAME_ID_ADDR:
224 return(isByName()) ? "Name": "ID";
225 case OFFSET_TO_DATA:
226 return "Offset To Data";
227 }
228 return getName();
229}
230
232{
233 IMAGE_RESOURCE_DIRECTORY_ENTRY* entry = getEntryPtr();
234 if (entry == NULL) return false;
235 if (entry->NameIsString == 1) return true;
236 return false;
237}
238
240{
241 IMAGE_RESOURCE_DIRECTORY_ENTRY* entry = getEntryPtr();
242 if (entry == NULL) return false;
243 if (entry->DataIsDirectory == 1) return true;
244 return false;
245}
246
248{
249 IMAGE_RESOURCE_DIRECTORY_ENTRY* entry = getEntryPtr();
250 if (entry == NULL) return INVALID_ADDR;
251
252 if (this->parentDir == NULL) return INVALID_ADDR;
253 offset_t fOff = this->parentDir->getOffset(this->parentDir->getPtr());
254 if (fOff == INVALID_ADDR) return INVALID_ADDR;
255
256 if (entry->NameIsString != 1) return INVALID_ADDR;
257 return fOff + entry->NameOffset;
258}
259
260IMAGE_RESOURCE_DIRECTORY_STRING* ResourceEntryWrapper::getNameStr()
261{
262 offset_t nameOff = getNameOffset();
263 if (nameOff == INVALID_ADDR) return NULL;
264
265 const size_t BASIC_SIZE = sizeof(IMAGE_RESOURCE_DIRECTORY_STRING);
266 IMAGE_RESOURCE_DIRECTORY_STRING *ptr = (IMAGE_RESOURCE_DIRECTORY_STRING*) this->m_Exe->getContentAt(nameOff, Executable::RAW, BASIC_SIZE);
267 return ptr;
268}
269
271{
272 switch (id) {
273 case pe::RESTYPE_CURSOR : return "Cursor";
274 case pe::RESTYPE_FONT :return "Font";
275 case pe::RESTYPE_BITMAP : return "Bitmap";
276 case pe::RESTYPE_ICON : return "Icon";
277 case pe::RESTYPE_MENU : return "Menu";
278 case pe::RESTYPE_DIALOG : return "Dialog";
279 case pe::RESTYPE_STRING : return "String";
280 case pe::RESTYPE_FONTDIR : return "Font Dir";
281 case pe::RESTYPE_ACCELERATOR : return "Accelerator";
282 case pe::RESTYPE_RCDATA : return "RC Data";
283 case pe::RESTYPE_MESSAGETABLE : return "Message Table";
284
285 case pe::RESTYPE_GROUP_CURSOR : return "Cursors Group";
286 case pe::RESTYPE_GROUP_ICON : return "Icons Group";
287 case pe::RESTYPE_VERSION : return "Version";
288 case pe::RESTYPE_DLGINCLUDE : return "Dlg Include";
289 case pe::RESTYPE_PLUGPLAY : return "Plug & Play";
290 case pe::RESTYPE_VXD : return "VXD";
291 case pe::RESTYPE_ANICURSOR : return "Animated Cursor";
292 case pe::RESTYPE_ANIICON : return "Animated Icon";
293 case pe::RESTYPE_HTML : return "HTML";
294 case pe::RESTYPE_MANIFEST : return "Manifest";
295 }
296 return "";
297}
298
300{
301 IMAGE_RESOURCE_DIRECTORY_ENTRY* entry = getEntryPtr();
302 if (entry == NULL) return 0;
303 if (this->isByName()) return 0;
304
305 return entry->Id;
306}
307
309{
310 const IMAGE_RESOURCE_DIRECTORY_ENTRY* entry = getEntryPtr();
311 if (!entry) {
312 return INVALID_ADDR;
313 }
314 if (entry->DataIsDirectory) {
315 return entry->OffsetToDirectory;
316 }
317 return entry->OffsetToData;
318}
319
321{
322 if (!this->parentDir) return INVALID_ADDR;
323
324 const offset_t fOff = this->parentDir->getOffset(this->parentDir->mainResourceDir());
325 if (fOff == INVALID_ADDR) return INVALID_ADDR;
326
327 const offset_t childOff = getChildOffsetToDirectory();
328 if (childOff == INVALID_ADDR) return INVALID_ADDR;
329
330 return fOff + childOff;
331}
332
333//-------------------------------------------------------------------------
334
335IMAGE_RESOURCE_DATA_ENTRY* ResourceLeafWrapper::leafEntryPtr()
336{
337 if (this->offset == 0 || this->offset == INVALID_ADDR) return NULL;
338
339 IMAGE_RESOURCE_DATA_ENTRY* leaf = (IMAGE_RESOURCE_DATA_ENTRY*) this->m_Exe->getContentAt(this->offset, Executable::RAW, sizeof(IMAGE_RESOURCE_DATA_ENTRY));
340 return leaf;
341}
342
343void* ResourceLeafWrapper::getFieldPtr(size_t fieldId, size_t subField)
344{
345 IMAGE_RESOURCE_DATA_ENTRY* leaf = leafEntryPtr();
346 if (!leaf) return NULL;
347
348 switch (fieldId) {
349 case OFFSET_TO_DATA: return &leaf->OffsetToData;
350 case DATA_SIZE: return &leaf->Size;
351 case CODE_PAGE: return &leaf->CodePage;
352 case RESERVED: return &leaf->Reserved;
353 }
354 return NULL;
355}
356
358{
359 switch (fieldId) {
360 case OFFSET_TO_DATA: return "OffsetToData";
361 case DATA_SIZE: return "DataSize";
362 case CODE_PAGE: return "CodePage";
363 case RESERVED: return "Reserved";
364 }
365 return "";
366}
367
368
uint32_t bufsize_t
const offset_t INVALID_ADDR
uint64_t offset_t
#define FIELD_NONE
#define MAX_DEPTH
#define MAX_ENTRIES
#define TOP_ENTRY_ROOT
Definition: ResourcesAlbum.h:3
offset_t getDirEntryAddress()
virtual bufsize_t getFieldSize(size_t fieldId, size_t subField=FIELD_NONE)
virtual offset_t getFieldOffset(size_t fieldId, size_t subField=FIELD_NONE)
virtual offset_t getOffset()
std::vector< ExeNodeWrapper * > entries
virtual void clear()
BYTE * getContentAt(offset_t offset, bufsize_t size, bool allowExceptions=false)
Definition: Executable.h:57
PEFile * m_PE
Definition: PENodeWrapper.h:36
virtual bufsize_t getSize()
virtual QString getFieldName(size_t fieldId)
virtual void * getFieldPtr(size_t fieldId, size_t subField)
virtual void * getPtr()
IMAGE_RESOURCE_DIRECTORY * mainResourceDir()
virtual bufsize_t getFieldSize(size_t fieldId, size_t subField)
virtual QString getName()
bufsize_t getEntriesAreaSize()
WORD getID()
virtual QString getFieldName(size_t fieldId)
offset_t getChildAddress()
IMAGE_RESOURCE_DIRECTORY_ENTRY * getEntryPtr()
offset_t getNameOffset()
virtual void clear()
bool isDir()
static QString translateType(WORD id)
bool isByName()
virtual QString getName()
bool wrap()
IMAGE_RESOURCE_DIRECTORY_STRING * getNameStr()
offset_t getChildOffsetToDirectory()
@ NAME_ID_ADDR
@ OFFSET_TO_DATA
virtual void * getPtr()
virtual void * getFieldPtr(size_t fieldId, size_t subField=FIELD_NONE)
IMAGE_RESOURCE_DATA_ENTRY * leafEntryPtr()
virtual void * getFieldPtr(size_t fieldId, size_t subField)
virtual QString getFieldName(size_t fieldId)
void mapIdToLeafType(long topId, pe::resource_type leafType)
void putLeaf(ResourceLeafWrapper *leaf, long topEntryId)