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 /*
8 typedef 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 
36 typedef 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 
57 IMAGE_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 
65 IMAGE_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 
116 void* 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 
133 QString 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 
183 IMAGE_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
198 void* 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 
212 QString ResourceEntryWrapper::getFieldName(size_t fieldId)
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 
252 IMAGE_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 
319 IMAGE_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 
327 void* 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 
341 QString ResourceLeafWrapper::getFieldName(size_t fieldId)
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()
virtual void * getPtr()
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 * 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)