libPeConv
A library to load, manipulate, dump PE files.
Loading...
Searching...
No Matches
resource_parser.cpp
Go to the documentation of this file.
3
4#include "peconv/logger.h"
5
6namespace {
7
8 bool parse_resource_dir(BYTE* modulePtr, const size_t moduleSize,
9 IMAGE_RESOURCE_DIRECTORY_ENTRY* root_dir,
10 const IMAGE_RESOURCE_DIRECTORY* upper_dir,
11 IMAGE_RESOURCE_DIRECTORY* curr_dir,
13 size_t depth = 0);
14
15 bool parse_resource_entry(BYTE* modulePtr, const size_t moduleSize,
16 IMAGE_RESOURCE_DIRECTORY_ENTRY* root_dir,
17 const IMAGE_RESOURCE_DIRECTORY* upper_dir,
18 IMAGE_RESOURCE_DIRECTORY_ENTRY* entry,
20 size_t depth)
21 {
22 if (!entry->DataIsDirectory) {
23 LOG_DEBUG("Entry is NOT a directory.");
24 DWORD offset = entry->OffsetToData;
25 LOG_DEBUG("Offset: %lu.", offset);
26 IMAGE_RESOURCE_DATA_ENTRY* data_entry = (IMAGE_RESOURCE_DATA_ENTRY*)(offset + (ULONGLONG)upper_dir);
27 if (!peconv::validate_ptr(modulePtr, moduleSize, data_entry, sizeof(IMAGE_RESOURCE_DATA_ENTRY))) {
28 return false;
29 }
30 LOG_DEBUG("Data Offset: %lu : %lu.", data_entry->OffsetToData, data_entry->Size);
31 BYTE* data_ptr = (BYTE*)((ULONGLONG)modulePtr + data_entry->OffsetToData);
32 if (!peconv::validate_ptr(modulePtr, moduleSize, data_ptr, data_entry->Size)) {
33 return false;
34 }
35 on_entry(modulePtr, root_dir, data_entry);
36 return true;
37 }
38 LOG_DEBUG("Entry is a directory.");
39 //else: it is a next level directory
40 DWORD offset = entry->OffsetToDirectory;
41 LOG_DEBUG("Offset: 0x%x.", offset);
42 IMAGE_RESOURCE_DIRECTORY* next_dir = (IMAGE_RESOURCE_DIRECTORY*)(offset + (ULONGLONG)upper_dir);
43 if (!peconv::validate_ptr(modulePtr, moduleSize, next_dir, sizeof(IMAGE_RESOURCE_DIRECTORY))) {
44 return false;
45 }
46 return parse_resource_dir(modulePtr, moduleSize, root_dir, upper_dir, next_dir, on_entry, depth);
47 }
48
49 bool parse_resource_dir(BYTE* modulePtr, const size_t moduleSize,
50 IMAGE_RESOURCE_DIRECTORY_ENTRY* root_dir,
51 const IMAGE_RESOURCE_DIRECTORY* upper_dir,
52 IMAGE_RESOURCE_DIRECTORY* curr_dir,
54 size_t depth)
55 {
56 if (depth > 8) {
57 LOG_ERROR("Maximum depth exceeded: %lld", (unsigned long long)depth);
58 return false;
59 }
60 size_t total_entries = curr_dir->NumberOfIdEntries + curr_dir->NumberOfNamedEntries;
61 IMAGE_RESOURCE_DIRECTORY_ENTRY* first_entry = (IMAGE_RESOURCE_DIRECTORY_ENTRY*)((ULONGLONG)&curr_dir->NumberOfIdEntries + sizeof(WORD));
62 for (size_t i = 0; i < total_entries; i++) {
63 IMAGE_RESOURCE_DIRECTORY_ENTRY* entry = &first_entry[i];
64 if (!peconv::validate_ptr(modulePtr, moduleSize, entry, sizeof(IMAGE_RESOURCE_DIRECTORY_ENTRY))) {
65 LOG_ERROR("Invalid resource entry pointer");
66 return false;
67 }
68 LOG_DEBUG("Entry: 0x%zx ; Id: %u ; dataOffset: %lu.", i, entry->Id, entry->OffsetToData);
69 if (!root_dir) {
70 root_dir = entry;
71 }
72 parse_resource_entry(modulePtr, moduleSize, root_dir, upper_dir, entry, on_entry, depth + 1);
73 }
74 return true;
75 }
76};
77
78bool peconv::parse_resources(BYTE* modulePtr, t_on_res_entry_found on_entry)
79{
80 const size_t module_size = peconv::get_image_size(modulePtr);
81 IMAGE_DATA_DIRECTORY *dir = peconv::get_directory_entry(modulePtr, IMAGE_DIRECTORY_ENTRY_RESOURCE);
82 if (!dir || dir->VirtualAddress == 0 || dir->Size == 0) {
83 return false;
84 }
85 IMAGE_RESOURCE_DIRECTORY *res_dir = (IMAGE_RESOURCE_DIRECTORY*)(dir->VirtualAddress + (ULONGLONG)modulePtr);
86 if (!peconv::validate_ptr(modulePtr, module_size, res_dir, sizeof(IMAGE_RESOURCE_DIRECTORY))) {
87 return false;
88 }
89 return parse_resource_dir(modulePtr, module_size, nullptr, res_dir, res_dir, on_entry);
90}
#define LOG_DEBUG(fmt,...)
Definition logger.h:56
#define LOG_ERROR(fmt,...)
Definition logger.h:36
bool parse_resources(BYTE *modulePtr, t_on_res_entry_found on_entry)
bool(* t_on_res_entry_found)(BYTE *modulePtr, IMAGE_RESOURCE_DIRECTORY_ENTRY *root_dir, IMAGE_RESOURCE_DATA_ENTRY *curr_entry)
bool validate_ptr(IN const void *buffer_bgn, IN size_t buffer_size, IN const void *field_bgn, IN size_t field_size)
DWORD get_image_size(IN const BYTE *payload)
IMAGE_DATA_DIRECTORY * get_directory_entry(IN const BYTE *pe_buffer, IN DWORD dir_id, IN bool allow_empty=false)
Wrappers over various fields in the PE header. Read, write, parse PE headers.
Parsing PE's resource directory.