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: {
151 PEFile* myPe = dynamic_cast<PEFile*>(this->m_Exe);
152 if (myPe && myPe->isReproBuild()) {
153 return "ReproChecksum";
154 }
155 return "TimeDateStamp";
156 }
157 case MAJOR_VER: return "MajorVersion";
158 case MINOR_VER: return "MinorVersion";
159 case NAMED_ENTRIES_NUM : return "NumberOfNamedEntries";
160 case ID_ENTRIES_NUM : return "NumberOfIdEntries";
161 }
162 return getName();
163}
164
165//-----------------------------------------------------------------
166
168{
169 delete childDir;
170 this->childDir = NULL;
171 //---
172 delete childLeaf;
173 this->childLeaf = NULL;
174}
175
177{
178 clear();
179 //---
180 offset_t childRaw = getChildAddress();
181 if (childRaw == 0 || childRaw == INVALID_ADDR) return false;
182
183 if (this->isDir()) {
184 long depth = this->parentDir->getDepth() + 1;
185 if (depth >= MAX_DEPTH) return false;
186 this->childDir = new ResourceDirWrapper(this->m_PE, this->album, childRaw, depth, topEntryID);
187 } else {
188 this->childLeaf = new ResourceLeafWrapper(m_Exe, childRaw, topEntryID);
189 if (this->album != NULL) {
190 album->putLeaf(childLeaf, topEntryID);
191 }
192 }
193 return true;
194}
195
196
197IMAGE_RESOURCE_DIRECTORY_ENTRY* ResourceEntryWrapper::getEntryPtr()
198{
199 if (this->parentDir == NULL) return NULL;
200 uint64_t offset = parentDir->getFieldOffset(ResourceDirWrapper::ID_ENTRIES_NUM);
201 if (offset == INVALID_ADDR) return NULL;
202
203 size_t lastSize = parentDir->getFieldSize(ResourceDirWrapper::ID_ENTRIES_NUM, FIELD_NONE);
204 offset += lastSize;
205 offset += (this->entryNum * sizeof(IMAGE_RESOURCE_DIRECTORY_ENTRY));
206
207 void *ptr = m_Exe->getContentAt(offset, Executable::RAW, sizeof(IMAGE_RESOURCE_DIRECTORY_ENTRY));
208 return (IMAGE_RESOURCE_DIRECTORY_ENTRY*) ptr;
209}
210
211//IMAGE_RESOURCE_DIRECTORY_ENTRY
212void* ResourceEntryWrapper::getFieldPtr(size_t fieldId, size_t subField)
213{
214 IMAGE_RESOURCE_DIRECTORY_ENTRY* entry = getEntryPtr();
215 if (entry == NULL) return NULL;
216
217 switch (fieldId) {
218 case NAME_ID_ADDR:
219 return &entry->Name;
220 case OFFSET_TO_DATA:
221 return &entry->OffsetToData;
222 }
223 return getPtr();
224}
225
227{
228 switch (fieldId) {
229 case NAME_ID_ADDR:
230 return(isByName()) ? "Name": "ID";
231 case OFFSET_TO_DATA:
232 return "Offset To Data";
233 }
234 return getName();
235}
236
238{
239 IMAGE_RESOURCE_DIRECTORY_ENTRY* entry = getEntryPtr();
240 if (entry == NULL) return false;
241 if (entry->NameIsString == 1) return true;
242 return false;
243}
244
246{
247 IMAGE_RESOURCE_DIRECTORY_ENTRY* entry = getEntryPtr();
248 if (entry == NULL) return false;
249 if (entry->DataIsDirectory == 1) return true;
250 return false;
251}
252
254{
255 IMAGE_RESOURCE_DIRECTORY_ENTRY* entry = getEntryPtr();
256 if (entry == NULL) return INVALID_ADDR;
257
258 if (this->parentDir == NULL) return INVALID_ADDR;
259 offset_t fOff = this->parentDir->getOffset(this->parentDir->getPtr());
260 if (fOff == INVALID_ADDR) return INVALID_ADDR;
261
262 if (entry->NameIsString != 1) return INVALID_ADDR;
263 return fOff + entry->NameOffset;
264}
265
266IMAGE_RESOURCE_DIRECTORY_STRING* ResourceEntryWrapper::getNameStr()
267{
268 offset_t nameOff = getNameOffset();
269 if (nameOff == INVALID_ADDR) return NULL;
270
271 const size_t BASIC_SIZE = sizeof(IMAGE_RESOURCE_DIRECTORY_STRING);
272 IMAGE_RESOURCE_DIRECTORY_STRING *ptr = (IMAGE_RESOURCE_DIRECTORY_STRING*) this->m_Exe->getContentAt(nameOff, Executable::RAW, BASIC_SIZE);
273 return ptr;
274}
275
277{
278 switch (id) {
279 case pe::RESTYPE_CURSOR : return "Cursor";
280 case pe::RESTYPE_FONT :return "Font";
281 case pe::RESTYPE_BITMAP : return "Bitmap";
282 case pe::RESTYPE_ICON : return "Icon";
283 case pe::RESTYPE_MENU : return "Menu";
284 case pe::RESTYPE_DIALOG : return "Dialog";
285 case pe::RESTYPE_STRING : return "String";
286 case pe::RESTYPE_FONTDIR : return "Font Dir";
287 case pe::RESTYPE_ACCELERATOR : return "Accelerator";
288 case pe::RESTYPE_RCDATA : return "RC Data";
289 case pe::RESTYPE_MESSAGETABLE : return "Message Table";
290
291 case pe::RESTYPE_GROUP_CURSOR : return "Cursors Group";
292 case pe::RESTYPE_GROUP_ICON : return "Icons Group";
293 case pe::RESTYPE_VERSION : return "Version";
294 case pe::RESTYPE_DLGINCLUDE : return "Dlg Include";
295 case pe::RESTYPE_PLUGPLAY : return "Plug & Play";
296 case pe::RESTYPE_VXD : return "VXD";
297 case pe::RESTYPE_ANICURSOR : return "Animated Cursor";
298 case pe::RESTYPE_ANIICON : return "Animated Icon";
299 case pe::RESTYPE_HTML : return "HTML";
300 case pe::RESTYPE_MANIFEST : return "Manifest";
301 }
302 return "";
303}
304
306{
307 IMAGE_RESOURCE_DIRECTORY_ENTRY* entry = getEntryPtr();
308 if (entry == NULL) return 0;
309 if (this->isByName()) return 0;
310
311 return entry->Id;
312}
313
315{
316 const IMAGE_RESOURCE_DIRECTORY_ENTRY* entry = getEntryPtr();
317 if (!entry) {
318 return INVALID_ADDR;
319 }
320 if (entry->DataIsDirectory) {
321 return entry->OffsetToDirectory;
322 }
323 return entry->OffsetToData;
324}
325
327{
328 if (!this->parentDir) return INVALID_ADDR;
329
330 const offset_t fOff = this->parentDir->getOffset(this->parentDir->mainResourceDir());
331 if (fOff == INVALID_ADDR) return INVALID_ADDR;
332
333 const offset_t childOff = getChildOffsetToDirectory();
334 if (childOff == INVALID_ADDR) return INVALID_ADDR;
335
336 return fOff + childOff;
337}
338
339//-------------------------------------------------------------------------
340
341IMAGE_RESOURCE_DATA_ENTRY* ResourceLeafWrapper::leafEntryPtr()
342{
343 if (this->offset == 0 || this->offset == INVALID_ADDR) return NULL;
344
345 IMAGE_RESOURCE_DATA_ENTRY* leaf = (IMAGE_RESOURCE_DATA_ENTRY*) this->m_Exe->getContentAt(this->offset, Executable::RAW, sizeof(IMAGE_RESOURCE_DATA_ENTRY));
346 return leaf;
347}
348
349void* ResourceLeafWrapper::getFieldPtr(size_t fieldId, size_t subField)
350{
351 IMAGE_RESOURCE_DATA_ENTRY* leaf = leafEntryPtr();
352 if (!leaf) return NULL;
353
354 switch (fieldId) {
355 case OFFSET_TO_DATA: return &leaf->OffsetToData;
356 case DATA_SIZE: return &leaf->Size;
357 case CODE_PAGE: return &leaf->CodePage;
358 case RESERVED: return &leaf->Reserved;
359 }
360 return NULL;
361}
362
364{
365 switch (fieldId) {
366 case OFFSET_TO_DATA: return "OffsetToData";
367 case DATA_SIZE: return "DataSize";
368 case CODE_PAGE: return "CodePage";
369 case RESERVED: return "Reserved";
370 }
371 return "";
372}
373
374
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
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:65
bool isReproBuild()
Definition PEFile.h:336
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)