BearParser
Portable Executable parsing library (from PE-bear)
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 case CHILDREN : return (&d->NumberOfIdEntries) + 1;
129 }
130 return this->getPtr();
131}
132
133QString ResourceDirWrapper::getFieldName(size_t fieldId)
134{
135 switch (fieldId) {
136 case CHARACTERISTIC: return "Characteristics";
137 case TIMESTAMP: return "TimeDateStamp";
138 case MAJOR_VER: return "MajorVersion";
139 case MINOR_VER: return "MinorVersion";
140 case NAMED_ENTRIES_NUM : return "NumberOfNamedEntries";
141 case ID_ENTRIES_NUM : return "NumberOfIdEntries";
142 case CHILDREN : return "Entries";
143 }
144 return getName();
145}
146
147//-----------------------------------------------------------------
148
150{
151 delete childDir;
152 this->childDir = NULL;
153 //---
154 delete childLeaf;
155 this->childLeaf = NULL;
156}
157
159{
160 clear();
161 //---
162 offset_t childRaw = getChildAddress();
163 if (childRaw == 0 || childRaw == INVALID_ADDR) return false;
164
165 if (this->isDir()) {
166 long depth = this->parentDir->getDepth() + 1;
167 if (depth >= MAX_DEPTH) return false;
168 //printf("Subdir at: %x ,depth : %lld\n", childRaw, depth);
169 this->childDir = new ResourceDirWrapper(this->m_PE, this->album, childRaw, depth, topEntryID);
170 } else {
171 //printf("Leaf at: %x\n", childRaw);
172 this->childLeaf = new ResourceLeafWrapper(m_Exe, childRaw, topEntryID);
173 //test
174 if (this->album != NULL) {
175 album->putLeaf(childLeaf, topEntryID);
176 //printf("Album: topEntryID: %x\n", topEntryID);
177 }
178 }
179 return true;
180}
181
182
183IMAGE_RESOURCE_DIRECTORY_ENTRY* ResourceEntryWrapper::getEntryPtr()
184{
185 if (this->parentDir == NULL) return NULL;
186 uint64_t offset = parentDir->getFieldOffset(ResourceDirWrapper::ID_ENTRIES_NUM);
187 if (offset == INVALID_ADDR) return NULL;
188
189 size_t lastSize = parentDir->getFieldSize(ResourceDirWrapper::ID_ENTRIES_NUM, FIELD_NONE);
190 offset += lastSize;
191 offset += (this->entryNum * sizeof(IMAGE_RESOURCE_DIRECTORY_ENTRY));
192
193 void *ptr = m_Exe->getContentAt(offset, Executable::RAW, sizeof(IMAGE_RESOURCE_DIRECTORY_ENTRY));
194 return (IMAGE_RESOURCE_DIRECTORY_ENTRY*) ptr;
195}
196
197//IMAGE_RESOURCE_DIRECTORY_ENTRY
198void* ResourceEntryWrapper::getFieldPtr(size_t fieldId, size_t subField)
199{
200 IMAGE_RESOURCE_DIRECTORY_ENTRY* entry = getEntryPtr();
201 if (entry == NULL) return NULL;
202
203 switch (fieldId) {
204 case NAME_ID_ADDR:
205 return &entry->Name;
206 case OFFSET_TO_DATA:
207 return &entry->OffsetToData;
208 }
209 return getPtr();
210}
211
213{
214 switch (fieldId) {
215 case NAME_ID_ADDR:
216 return(isByName()) ? "Name": "ID";
217 case OFFSET_TO_DATA:
218 return "Offset To Data";
219 }
220 return getName();
221}
222
224{
225 IMAGE_RESOURCE_DIRECTORY_ENTRY* entry = getEntryPtr();
226 if (entry == NULL) return false;
227 if (entry->NameIsString == 1) return true;
228 return false;
229}
230
232{
233 IMAGE_RESOURCE_DIRECTORY_ENTRY* entry = getEntryPtr();
234 if (entry == NULL) return false;
235 if (entry->DataIsDirectory == 1) return true;
236 return false;
237}
238
240{
241 IMAGE_RESOURCE_DIRECTORY_ENTRY* entry = getEntryPtr();
242 if (entry == NULL) return INVALID_ADDR;
243
244 if (this->parentDir == NULL) return INVALID_ADDR;
245 offset_t fOff = this->parentDir->getOffset(this->parentDir->getPtr());
246 if (fOff == INVALID_ADDR) return INVALID_ADDR;
247
248 if (entry->NameIsString != 1) return INVALID_ADDR;
249 return fOff + entry->NameOffset;
250}
251
252IMAGE_RESOURCE_DIRECTORY_STRING* ResourceEntryWrapper::getNameStr()
253{
254 offset_t nameOff = getNameOffset();
255 if (nameOff == INVALID_ADDR) return NULL;
256
257 const size_t BASIC_SIZE = sizeof(IMAGE_RESOURCE_DIRECTORY_STRING);
258 IMAGE_RESOURCE_DIRECTORY_STRING *ptr = (IMAGE_RESOURCE_DIRECTORY_STRING*) this->m_Exe->getContentAt(nameOff, Executable::RAW, BASIC_SIZE);
259 return ptr;
260}
261
263{
264 switch (id) {
265 case pe::RESTYPE_CURSOR : return "Cursor";
266 case pe::RESTYPE_FONT :return "Font";
267 case pe::RESTYPE_BITMAP : return "Bitmap";
268 case pe::RESTYPE_ICON : return "Icon";
269 case pe::RESTYPE_MENU : return "Menu";
270 case pe::RESTYPE_DIALOG : return "Dialog";
271 case pe::RESTYPE_STRING : return "String";
272 case pe::RESTYPE_FONTDIR : return "Font Dir";
273 case pe::RESTYPE_ACCELERATOR : return "Accelerator";
274 case pe::RESTYPE_RCDATA : return "RC Data";
275 case pe::RESTYPE_MESSAGETABLE : return "Message Table";
276
277 case pe::RESTYPE_GROUP_CURSOR : return "Cursors Group";
278 case pe::RESTYPE_GROUP_ICON : return "Icons Group";
279 case pe::RESTYPE_VERSION : return "Version";
280 case pe::RESTYPE_DLGINCLUDE : return "Dlg Include";
281 case pe::RESTYPE_PLUGPLAY : return "Plug & Play";
282 case pe::RESTYPE_VXD : return "VXD";
283 case pe::RESTYPE_ANICURSOR : return "Animated Cursor";
284 case pe::RESTYPE_ANIICON : return "Animated Icon";
285 case pe::RESTYPE_HTML : return "HTML";
286 case pe::RESTYPE_MANIFEST : return "Manifest";
287 }
288 return "";
289}
290
292{
293 IMAGE_RESOURCE_DIRECTORY_ENTRY* entry = getEntryPtr();
294 if (entry == NULL) return 0;
295 if (this->isByName()) return 0;
296
297 return entry->Id;
298}
299
301{
302 IMAGE_RESOURCE_DIRECTORY_ENTRY* entry = getEntryPtr();
303 if (entry == NULL) return 0;
304 return entry->OffsetToDirectory;
305}
306
308{
309 if (this->parentDir == NULL) return INVALID_ADDR;
310 offset_t fOff = this->parentDir->getOffset(this->parentDir->mainResourceDir());
311 if (fOff == INVALID_ADDR) return INVALID_ADDR;
312
313 fOff += static_cast<offset_t>(getChildOffsetToDirectory());
314 return fOff;
315}
316
317//-------------------------------------------------------------------------
318
319IMAGE_RESOURCE_DATA_ENTRY* ResourceLeafWrapper::leafEntryPtr()
320{
321 if (this->offset == 0 || this->offset == INVALID_ADDR) return NULL;
322
323 IMAGE_RESOURCE_DATA_ENTRY* leaf = (IMAGE_RESOURCE_DATA_ENTRY*) this->m_Exe->getContentAt(this->offset, Executable::RAW, sizeof(IMAGE_RESOURCE_DATA_ENTRY));
324 return leaf;
325}
326
327void* ResourceLeafWrapper::getFieldPtr(size_t fieldId, size_t subField)
328{
329 IMAGE_RESOURCE_DATA_ENTRY* leaf = leafEntryPtr();
330 if (leaf == NULL) return NULL;
331
332 switch (fieldId) {
333 case OFFSET_TO_DATA: return &leaf->OffsetToData;
334 case DATA_SIZE: return &leaf->Size;
335 case CODE_PAGE: return &leaf->CodePage;
336 case RESERVED: return &leaf->Reserved;
337 }
338 return NULL;
339}
340
342{
343 switch (fieldId) {
344 case OFFSET_TO_DATA: return "OffsetToData";
345 case DATA_SIZE: return "DataSize";
346 case CODE_PAGE: return "CodePage";
347 case RESERVED: return "Reserved";
348 }
349 return "";
350}
351
352
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)
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 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()
DWORD getChildOffsetToDirectory()
static QString translateType(WORD id)
bool isByName()
virtual QString getName()
bool wrap()
IMAGE_RESOURCE_DIRECTORY_STRING * getNameStr()
@ 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)