libPeConv
A library to load, manipulate, dump PE files.
Loading...
Searching...
No Matches
find_base.cpp
Go to the documentation of this file.
1#include <peconv/find_base.h>
3#include <peconv/relocate.h>
4#include <set>
5#include <map>
6
7namespace {
8
9 class CollectCodeRelocs : public peconv::RelocBlockCallback
10 {
11 public:
12 CollectCodeRelocs(BYTE *pe_buffer, size_t buffer_size, IN bool _is64bit, OUT std::set<ULONGLONG> &_relocs)
13 : RelocBlockCallback(_is64bit), relocs(_relocs),
14 peBuffer(pe_buffer), bufferSize(buffer_size)
15 {
16 codeSec = getCodeSection(peBuffer, bufferSize);
17 }
18
19 virtual bool processRelocField(ULONG_PTR relocField)
20 {
21 if (!codeSec) return false;
22
23 ULONGLONG reloc_addr = (relocField - (ULONGLONG)peBuffer);
24 const ULONGLONG code_start = codeSec->VirtualAddress;
25 const ULONGLONG code_end = code_start + codeSec->Misc.VirtualSize;
26 const bool is_in_code = (reloc_addr >= code_start) && (reloc_addr < code_end);
27 if (!is64bit && !is_in_code) {
28 // in case of 32 bit PEs process only the relocations form the code section
29 return true;
30 }
31 ULONGLONG rva = 0;
32 if (is64bit) {
33 ULONGLONG* relocateAddr = (ULONGLONG*)((ULONG_PTR)relocField);
34 rva = (*relocateAddr);
35 //std::cout << std::hex << (relocField - (ULONGLONG)peBuffer) << " : " << rva << std::endl;
36 }
37 else {
38 DWORD* relocateAddr = (DWORD*)((ULONG_PTR)relocField);
39 rva = ULONGLONG(*relocateAddr);
40 //std::cout << std::hex << (relocField - (ULONGLONG)peBuffer) << " : " << rva << std::endl;
41 }
42 relocs.insert(rva);
43 return true;
44 }
45
46 static PIMAGE_SECTION_HEADER getCodeSection(BYTE *peBuffer, size_t bufferSize)
47 {
48 size_t sec_count = peconv::get_sections_count(peBuffer, bufferSize);
49 for (size_t i = 0; i < sec_count; i++) {
50 PIMAGE_SECTION_HEADER hdr = peconv::get_section_hdr(peBuffer, bufferSize, i);
51 if (!hdr) break;
52 if (hdr->VirtualAddress == 0 || hdr->SizeOfRawData == 0) {
53 continue;
54 }
55 if (hdr->Characteristics & IMAGE_SCN_MEM_EXECUTE) {
56 return hdr;
57 }
58 }
59 return nullptr;
60 }
61
62 protected:
63 std::set<ULONGLONG> &relocs;
64 PIMAGE_SECTION_HEADER codeSec;
65
66 BYTE *peBuffer;
67 size_t bufferSize;
68 };
69}
70
71ULONGLONG peconv::find_base_candidate(IN BYTE* modulePtr, IN size_t moduleSize)
72{
73 if (moduleSize == 0) {
74 moduleSize = peconv::get_image_size((const BYTE*)modulePtr);
75 }
76 if (moduleSize == 0) return 0;
77
78 bool is64 = peconv::is64bit(modulePtr);
79 std::set<ULONGLONG> relocs;
80 CollectCodeRelocs callback(modulePtr, moduleSize, is64, relocs);
81 if (!peconv::process_relocation_table(modulePtr, moduleSize, &callback)) {
82 return 0;
83 }
84 if (relocs.size() == 0) {
85 return 0;
86 }
87
88 PIMAGE_SECTION_HEADER hdr = CollectCodeRelocs::getCodeSection(modulePtr, moduleSize);
89 if (!hdr) {
90 return 0;
91 }
92 const ULONGLONG mask = ~ULONGLONG(0xFFFF);
93 std::map<ULONGLONG, size_t>base_candidates;
94
95 std::set<ULONGLONG>::iterator itr;
96
97 for (itr = relocs.begin(); itr != relocs.end(); ++itr) {
98 const ULONGLONG guessed_base = (*itr) & mask;
99 std::map<ULONGLONG, size_t>::iterator found = base_candidates.find(guessed_base);
100 if (found == base_candidates.end()) {
101 base_candidates[guessed_base] = 0;
102 }
103 base_candidates[guessed_base]++;
104 }
105 ULONGLONG most_frequent = 0;
106 size_t max_freq = 0;
107 std::map<ULONGLONG, size_t>::iterator mapItr;
108 for (mapItr = base_candidates.begin(); mapItr != base_candidates.end(); ++mapItr) {
109 if (mapItr->second >= max_freq) {
110 most_frequent = mapItr->first;
111 max_freq = mapItr->second;
112 }
113 }
114 for (itr = relocs.begin(); itr != relocs.end(); ++itr) {
115 ULONGLONG first = *itr;
116 ULONGLONG first_base = first & mask;
117 if (first_base > most_frequent) {
118 break;
119 }
120 ULONGLONG delta = most_frequent - first_base;
121 if (delta < moduleSize) {
122 return first_base;
123 }
124 }
125 return 0;
126}
Functions related to finding a base to which the module was relocated.
ULONGLONG find_base_candidate(IN BYTE *module_ptr, IN size_t module_size)
Definition find_base.cpp:71
PIMAGE_SECTION_HEADER get_section_hdr(IN const BYTE *pe_buffer, IN const size_t buffer_size, IN size_t section_num)
DWORD get_image_size(IN const BYTE *payload)
bool process_relocation_table(IN PVOID modulePtr, IN SIZE_T moduleSize, IN RelocBlockCallback *callback)
Definition relocate.cpp:111
bool is64bit(IN const BYTE *pe_buffer)
size_t get_sections_count(IN const BYTE *buffer, IN const size_t buffer_size)
Wrappers over various fields in the PE header. Read, write, parse PE headers.
Operating on PE file's relocations table.