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 if (!on_entry) {
36 LOG_WARNING("Missing on entry callback.");
37 return false;
38 }
39 return on_entry(modulePtr, root_dir, data_entry);
40 }
41 LOG_DEBUG("Entry is a directory.");
42 //else: it is a next level directory
43 DWORD offset = entry->OffsetToDirectory;
44 LOG_DEBUG("Offset: 0x%x.", offset);
45 IMAGE_RESOURCE_DIRECTORY* next_dir = (IMAGE_RESOURCE_DIRECTORY*)(offset + (ULONGLONG)upper_dir);
46 if (!peconv::validate_ptr(modulePtr, moduleSize, next_dir, sizeof(IMAGE_RESOURCE_DIRECTORY))) {
47 return false;
48 }
49 return parse_resource_dir(modulePtr, moduleSize, root_dir, upper_dir, next_dir, on_entry, depth);
50 }
51
52 bool parse_resource_dir(BYTE* modulePtr, const size_t moduleSize,
53 IMAGE_RESOURCE_DIRECTORY_ENTRY* root_dir,
54 const IMAGE_RESOURCE_DIRECTORY* upper_dir,
55 IMAGE_RESOURCE_DIRECTORY* curr_dir,
57 size_t depth)
58 {
59 if (depth > 8) {
60 LOG_ERROR("Maximum depth exceeded: %lld", (unsigned long long)depth);
61 return false;
62 }
63 size_t total_entries = curr_dir->NumberOfIdEntries + curr_dir->NumberOfNamedEntries;
64 IMAGE_RESOURCE_DIRECTORY_ENTRY* first_entry = (IMAGE_RESOURCE_DIRECTORY_ENTRY*)((ULONGLONG)&curr_dir->NumberOfIdEntries + sizeof(WORD));
65 for (size_t i = 0; i < total_entries; i++) {
66 IMAGE_RESOURCE_DIRECTORY_ENTRY* entry = &first_entry[i];
67 if (!peconv::validate_ptr(modulePtr, moduleSize, entry, sizeof(IMAGE_RESOURCE_DIRECTORY_ENTRY))) {
68 LOG_ERROR("Invalid resource entry pointer");
69 return false;
70 }
71 LOG_DEBUG("Entry: 0x%zx ; Id: %u ; dataOffset: %lu.", i, entry->Id, entry->OffsetToData);
72 if (!root_dir) {
73 root_dir = entry;
74 }
75 if (!parse_resource_entry(modulePtr, moduleSize, root_dir, upper_dir, entry, on_entry, depth + 1)) {
76 LOG_ERROR("Parsing resource entry failed.");
77 return false;
78 }
79 }
80 return true;
81 }
82};
83
84bool peconv::parse_resources(BYTE* modulePtr, t_on_res_entry_found on_entry)
85{
86 const size_t module_size = peconv::get_image_size(modulePtr);
87 IMAGE_DATA_DIRECTORY* dir = peconv::get_directory_entry(modulePtr, IMAGE_DIRECTORY_ENTRY_RESOURCE);
88 if (!dir || dir->VirtualAddress == 0 || dir->Size == 0) {
89 return false;
90 }
91 IMAGE_RESOURCE_DIRECTORY* res_dir = (IMAGE_RESOURCE_DIRECTORY*)(dir->VirtualAddress + (ULONGLONG)modulePtr);
92 if (!peconv::validate_ptr(modulePtr, module_size, res_dir, sizeof(IMAGE_RESOURCE_DIRECTORY))) {
93 return false;
94 }
95 return parse_resource_dir(modulePtr, module_size, nullptr, res_dir, res_dir, on_entry);
96}
Compile-time configurable logging macros for peconv.
#define LOG_DEBUG(fmt,...)
Definition: logger.h:80
#define LOG_ERROR(fmt,...)
Definition: logger.h:60
#define LOG_WARNING(fmt,...)
Definition: logger.h:68
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)
Definition: buffer_util.cpp:9
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.