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 <tchar.h>
10#include <iostream>
11
12using namespace peconv;
13
14namespace peconv {
15 BYTE* load_no_sec_pe(BYTE* dllRawData, size_t r_size, OUT size_t &v_size, bool executable)
16 {
17 ULONGLONG desired_base = 0;
18 size_t out_size = (r_size < PAGE_SIZE) ? PAGE_SIZE : r_size;
19 if (executable) {
20 desired_base = get_image_base(dllRawData);
21 out_size = peconv::get_image_size(dllRawData);
22 }
23 DWORD protect = (executable) ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE;
24 BYTE* mappedPE = peconv::alloc_pe_buffer(out_size, protect, desired_base);
25 if (!mappedPE) {
26 return NULL;
27 }
28 memcpy(mappedPE, dllRawData, r_size);
29 v_size = out_size;
30 return mappedPE;
31 }
32};
33
34BYTE* peconv::load_pe_module(BYTE* dllRawData, size_t r_size, OUT size_t &v_size, bool executable, bool relocate, ULONGLONG desired_base)
35{
36 if (!peconv::get_nt_hdrs(dllRawData, r_size)) {
37 return NULL;
38 }
39 if (peconv::get_sections_count(dllRawData, r_size) == 0) {
40 return load_no_sec_pe(dllRawData, r_size, v_size, executable);
41 }
42 // by default, allow to load the PE at the supplied base
43 // if relocating is required, but the PE has no relocation table...
44 if (relocate && !has_relocations(dllRawData)) {
45 // ...enforce loading the PE image at its default base (so that it will need no relocations)
46 desired_base = get_image_base(dllRawData);
47 }
48 // load a virtual image of the PE file at the desired_base address (random if desired_base is NULL):
49 BYTE *mappedDLL = pe_raw_to_virtual(dllRawData, r_size, v_size, executable, desired_base);
50 if (mappedDLL) {
51 //if the image was loaded at its default base, relocate_module will return always true (because relocating is already done)
52 if (relocate && !relocate_module(mappedDLL, v_size, (ULONGLONG)mappedDLL)) {
53 // relocating was required, but it failed - thus, the full PE image is useless
54 std::cerr << "[!] Could not relocate the module!\n";
55 free_pe_buffer(mappedDLL, v_size);
56 mappedDLL = NULL;
57 }
58 } else {
59 std::cerr << "[!] Could not allocate memory at the desired base!\n";
60 }
61 return mappedDLL;
62}
63
64BYTE* peconv::load_pe_module(LPCTSTR filename, OUT size_t &v_size, bool executable, bool relocate, ULONGLONG desired_base)
65{
66 size_t r_size = 0;
67 BYTE *dllRawData = load_file(filename, r_size);
68 if (!dllRawData) {
69#ifdef _DEBUG
70 std::cerr << "Cannot load the file: " << filename << std::endl;
71#endif
72 return NULL;
73 }
74 BYTE* mappedPE = load_pe_module(dllRawData, r_size, v_size, executable, relocate, desired_base);
75 free_file(dllRawData);
76 return mappedPE;
77}
78
79BYTE* peconv::load_pe_executable(BYTE* dllRawData, size_t r_size, OUT size_t &v_size, t_function_resolver* import_resolver, ULONGLONG desired_base)
80{
81 BYTE* loaded_pe = load_pe_module(dllRawData, r_size, v_size, true, true, desired_base);
82 if (!loaded_pe) {
83 std::cerr << "[-] Loading failed!\n";
84 return NULL;
85 }
86#if _DEBUG
87 printf("Loaded at: %p\n", loaded_pe);
88#endif
89 if (has_valid_import_table(loaded_pe, v_size)) {
90 if (!load_imports(loaded_pe, import_resolver)) {
91 printf("[-] Loading imports failed!");
92 free_pe_buffer(loaded_pe, v_size);
93 return NULL;
94 }
95 }
96 else {
97 printf("[-] PE doesn't have a valid Import Table!\n");
98 }
99 return loaded_pe;
100}
101
102
103BYTE* peconv::load_pe_executable(LPCTSTR my_path, OUT size_t &v_size, t_function_resolver* import_resolver)
104{
105#if _DEBUG
106 _tprintf(TEXT("Module: %s\n"), my_path);
107#endif
108 BYTE* loaded_pe = load_pe_module(my_path, v_size, true, true);
109 if (!loaded_pe) {
110 printf("[-] Loading failed!\n");
111 return NULL;
112 }
113#if _DEBUG
114 printf("Loaded at: %p\n", loaded_pe);
115#endif
116 if (!load_imports(loaded_pe, import_resolver)) {
117 printf("[-] Loading imports failed!");
118 free_pe_buffer(loaded_pe, v_size);
119 return NULL;
120 }
121 return loaded_pe;
122}
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.
bool has_relocations(IN const BYTE *pe_buffer)
bool has_valid_import_table(const PBYTE modulePtr, size_t moduleSize)
peconv::UNALIGNED_BUF load_file(IN LPCTSTR filename, OUT size_t &r_size)
Definition file_util.cpp:11
BYTE * load_no_sec_pe(BYTE *dllRawData, size_t r_size, OUT size_t &v_size, bool executable)
Definition pe_loader.cpp:15
ULONGLONG get_image_base(IN const BYTE *pe_buffer)
BYTE * load_pe_module(BYTE *payload_raw, size_t r_size, OUT size_t &v_size, bool executable, bool relocate, ULONGLONG desired_base=0)
Definition pe_loader.cpp:34
DWORD get_image_size(IN const BYTE *payload)
bool free_pe_buffer(ALIGNED_BUF buffer, 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, ULONGLONG desired_base=0)
Definition pe_loader.cpp:79
ALIGNED_BUF alloc_pe_buffer(size_t buffer_size, DWORD protect, ULONGLONG desired_base=NULL)
BYTE * pe_raw_to_virtual(IN const BYTE *rawPeBuffer, IN size_t rawPeSize, OUT size_t &outputSize, IN OPTIONAL bool executable=true, IN OPTIONAL ULONGLONG 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:158
void free_file(IN peconv::UNALIGNED_BUF buffer)
BYTE * get_nt_hdrs(IN const BYTE *pe_buffer, IN OPTIONAL size_t buffer_size=0)
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.