libPeConv
A library to load, manipulate, dump PE files.
Loading...
Searching...
No Matches
pe_loader.cpp
Go to the documentation of this file.
1#include "peconv/pe_loader.h"
2
3#include "peconv/relocate.h"
8
9#include "peconv/logger.h"
10
11using namespace peconv;
12
13namespace {
14 BYTE* load_no_sec_pe(BYTE* dllRawData, size_t r_size, OUT size_t &v_size, bool executable)
15 {
16 ULONG_PTR desired_base = 0;
17 size_t out_size = (r_size < PAGE_SIZE) ? PAGE_SIZE : r_size;
18 if (executable) {
19 desired_base = get_image_base(dllRawData);
20 out_size = peconv::get_image_size(dllRawData);
21 }
22 DWORD protect = (executable) ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE;
23 BYTE* mappedPE = peconv::alloc_pe_buffer(out_size, protect, reinterpret_cast<void*>(desired_base));
24 if (!mappedPE) {
25 return nullptr;
26 }
27 memcpy(mappedPE, dllRawData, r_size);
28 v_size = out_size;
29 return mappedPE;
30 }
31};
32
33BYTE* peconv::load_pe_module(BYTE* dllRawData, size_t r_size, OUT size_t &v_size, bool executable, bool relocate, ULONG_PTR desired_base)
34{
35 if (!peconv::get_nt_hdrs(dllRawData, r_size)) {
36 return nullptr;
37 }
38 if (peconv::get_sections_count(dllRawData, r_size) == 0) {
39 return load_no_sec_pe(dllRawData, r_size, v_size, executable);
40 }
41 // by default, allow to load the PE at the supplied base
42 // if relocating is required, but the PE has no relocation table...
43 if (relocate && !has_relocations(dllRawData)) {
44 // ...enforce loading the PE image at its default base (so that it will need no relocations)
45 desired_base = get_image_base(dllRawData);
46 }
47 // load a virtual image of the PE file at the desired_base address (random if desired_base is NULL):
48 BYTE *mappedDLL = pe_raw_to_virtual(dllRawData, r_size, v_size, executable, desired_base);
49 if (mappedDLL) {
50 //if the image was loaded at its default base, relocate_module will return always true (because relocating is already done)
51 if (relocate && !relocate_module(mappedDLL, v_size, (ULONGLONG)mappedDLL)) {
52 // relocating was required, but it failed - thus, the full PE image is useless
53 LOG_ERROR("Could not relocate the module.");
54 free_pe_buffer(mappedDLL, v_size);
55 mappedDLL = nullptr;
56 }
57 } else {
58 LOG_ERROR("Could not allocate memory at the desired base.");
59 }
60 return mappedDLL;
61}
62
63BYTE* peconv::load_pe_module(LPCTSTR filename, OUT size_t &v_size, bool executable, bool relocate, ULONG_PTR desired_base)
64{
65 size_t r_size = 0;
66 BYTE *dllRawData = load_file(filename, r_size);
67 if (!dllRawData) {
68 LOG_ERROR("Cannot load the file.");
69 return nullptr;
70 }
71 BYTE* mappedPE = load_pe_module(dllRawData, r_size, v_size, executable, relocate, desired_base);
72 free_file(dllRawData);
73 return mappedPE;
74}
75
76namespace
77{
78 bool validate_and_load_imports(BYTE* loaded_pe, const size_t v_size, t_function_resolver* import_resolver)
79 {
80 if (!has_valid_import_table(loaded_pe, v_size)) {
81 LOG_WARNING("PE does not have a valid Import Table.");
82 return true; // nothing to load, use as is
83 }
84 if (load_imports(loaded_pe, import_resolver)) {
85 return true;
86 }
87 LOG_ERROR("Loading imports failed.");
88 return false;
89 }
90};
91
92BYTE* peconv::load_pe_executable(BYTE* dllRawData, size_t r_size, OUT size_t &v_size, t_function_resolver* import_resolver, ULONG_PTR desired_base)
93{
94 BYTE* loaded_pe = load_pe_module(dllRawData, r_size, v_size, true, true, desired_base);
95 if (!loaded_pe) {
96 LOG_ERROR("Loading failed.");
97 return nullptr;
98 }
99 LOG_DEBUG("Loaded at: %p.", loaded_pe);
100 if (!validate_and_load_imports(loaded_pe, v_size, import_resolver)) {
101 free_pe_buffer(loaded_pe, v_size);
102 return NULL;
103 }
104 return loaded_pe;
105}
106
107
108BYTE* peconv::load_pe_executable(LPCTSTR my_path, OUT size_t &v_size, t_function_resolver* import_resolver)
109{
110 BYTE* loaded_pe = load_pe_module(my_path, v_size, true, true);
111 if (!loaded_pe) {
112 LOG_ERROR("Loading failed.");
113 return NULL;
114 }
115 LOG_DEBUG("Loaded at: %p.", loaded_pe);
116 if (!validate_and_load_imports(loaded_pe, v_size, import_resolver)) {
117 free_pe_buffer(loaded_pe, v_size);
118 return NULL;
119 }
120 return loaded_pe;
121}
Definitions of the used buffer types. Functions for their allocation and deallocation.
Searching specific functions in PE's Exports Table.
Definitions of basic Imports Resolver classes. They can be used for filling imports when the PE is lo...
Parsing and filling the Import Table.
#define LOG_DEBUG(fmt,...)
Definition logger.h:56
#define LOG_ERROR(fmt,...)
Definition logger.h:36
#define LOG_WARNING(fmt,...)
Definition logger.h:44
bool has_valid_import_table(const PBYTE modulePtr, size_t moduleSize, size_t max_count=0)
bool has_relocations(IN const BYTE *pe_buffer)
ULONGLONG get_image_base(IN const BYTE *pe_buffer)
ALIGNED_BUF alloc_pe_buffer(size_t buffer_size, DWORD protect, void *desired_base=nullptr)
peconv::UNALIGNED_BUF load_file(IN LPCTSTR filename, OUT size_t &r_size)
Definition file_util.cpp:9
DWORD get_image_size(IN const BYTE *payload)
bool free_pe_buffer(ALIGNED_BUF buffer, size_t buffer_size=0)
BYTE * load_pe_module(BYTE *payload_raw, size_t r_size, OUT size_t &v_size, bool executable, bool relocate, ULONG_PTR desired_base=0)
Definition pe_loader.cpp:33
BYTE * pe_raw_to_virtual(IN const BYTE *rawPeBuffer, IN size_t rawPeSize, OUT size_t &outputSize, IN OPTIONAL bool executable=true, IN OPTIONAL ULONG_PTR desired_base=0)
size_t get_sections_count(IN const BYTE *buffer, IN const size_t buffer_size)
bool relocate_module(IN BYTE *modulePtr, IN SIZE_T moduleSize, IN ULONGLONG newBase, IN ULONGLONG oldBase=0)
Definition relocate.cpp:164
void free_file(IN peconv::UNALIGNED_BUF buffer)
BYTE * get_nt_hdrs(IN const BYTE *pe_buffer, IN OPTIONAL size_t buffer_size=0)
BYTE * load_pe_executable(BYTE *payload_raw, size_t r_size, OUT size_t &v_size, t_function_resolver *import_resolver=nullptr, ULONG_PTR desired_base=0)
Definition pe_loader.cpp:92
bool load_imports(BYTE *modulePtr, t_function_resolver *func_resolver=nullptr)
#define PAGE_SIZE
Loading PE from a file with the help of the custom loader.
Operating on PE file's relocations table.