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#include <iostream>
7
8namespace peconv {
9
11 {
12 public:
13 CollectCodeRelocs(BYTE *pe_buffer, size_t buffer_size, IN bool _is64bit, OUT std::set<ULONGLONG> &_relocs)
14 : RelocBlockCallback(_is64bit), relocs(_relocs),
15 peBuffer(pe_buffer), bufferSize(buffer_size)
16 {
18 }
19
20 virtual bool processRelocField(ULONG_PTR relocField)
21 {
22 if (!codeSec) return false;
23
24 ULONGLONG reloc_addr = (relocField - (ULONGLONG)peBuffer);
25 const bool is_in_code = (reloc_addr >= codeSec->VirtualAddress) && (reloc_addr < codeSec->Misc.VirtualSize);
26 if (!is64bit && !is_in_code) {
27 // in case of 32 bit PEs process only the relocations form the code section
28 return true;
29 }
30 ULONGLONG rva = 0;
31 if (is64bit) {
32 ULONGLONG* relocateAddr = (ULONGLONG*)((ULONG_PTR)relocField);
33 rva = (*relocateAddr);
34 //std::cout << std::hex << (relocField - (ULONGLONG)peBuffer) << " : " << rva << std::endl;
35 }
36 else {
37 DWORD* relocateAddr = (DWORD*)((ULONG_PTR)relocField);
38 rva = ULONGLONG(*relocateAddr);
39 //std::cout << std::hex << (relocField - (ULONGLONG)peBuffer) << " : " << rva << std::endl;
40 }
41 relocs.insert(rva);
42 return true;
43 }
44
45 static PIMAGE_SECTION_HEADER getCodeSection(BYTE *peBuffer, size_t bufferSize)
46 {
48 for (size_t i = 0; i < sec_count; i++) {
49 PIMAGE_SECTION_HEADER hdr = peconv::get_section_hdr(peBuffer, bufferSize, i);
50 if (!hdr) break;
51 if (hdr->VirtualAddress == 0 || hdr->SizeOfRawData == 0) {
52 continue;
53 }
54 if (hdr->Characteristics & IMAGE_SCN_MEM_EXECUTE) {
55 return hdr;
56 }
57 }
58 return nullptr;
59 }
60
61 protected:
62 std::set<ULONGLONG> &relocs;
63 PIMAGE_SECTION_HEADER codeSec;
64
65 BYTE *peBuffer;
66 size_t bufferSize;
67 };
68}
69
70ULONGLONG peconv::find_base_candidate(IN BYTE* modulePtr, IN size_t moduleSize)
71{
72 if (moduleSize == 0) {
73 moduleSize = peconv::get_image_size((const BYTE*)modulePtr);
74 }
75 if (moduleSize == 0) return 0;
76
77 bool is64 = peconv::is64bit(modulePtr);
78 std::set<ULONGLONG> relocs;
79 peconv::CollectCodeRelocs callback(modulePtr, moduleSize, is64, relocs);
80 if (!peconv::process_relocation_table(modulePtr, moduleSize, &callback)) {
81 return 0;
82 }
83 if (relocs.size() == 0) {
84 return 0;
85 }
86
87 PIMAGE_SECTION_HEADER hdr = peconv::CollectCodeRelocs::getCodeSection(modulePtr, moduleSize);
88 if (!hdr) {
89 return 0;
90 }
91 const ULONGLONG mask = ~ULONGLONG(0xFFFF);
92 std::map<ULONGLONG, size_t>base_candidates;
93
94 std::set<ULONGLONG>::iterator itr = relocs.begin();
95
96 for (itr = relocs.begin(); itr != relocs.end(); ++itr) {
97 const ULONGLONG guessed_base = (*itr) & mask;
98 std::map<ULONGLONG, size_t>::iterator found = base_candidates.find(guessed_base);
99 if (found == base_candidates.end()) {
100 base_candidates[guessed_base] = 0;
101 }
102 base_candidates[guessed_base]++;
103 }
104 ULONGLONG most_freqent = 0;
105 size_t max_freq = 0;
106 std::map<ULONGLONG, size_t>::iterator mapItr;
107 for (mapItr = base_candidates.begin(); mapItr != base_candidates.end(); ++mapItr) {
108 if (mapItr->second >= max_freq) {
109 most_freqent = mapItr->first;
110 max_freq = mapItr->second;
111 }
112 }
113 for (itr = relocs.begin(); itr != relocs.end(); ++itr) {
114 ULONGLONG first = *itr;
115 ULONGLONG first_base = first & mask;
116 if (first_base > most_freqent) {
117 break;
118 }
119 ULONGLONG delta = most_freqent - first_base;
120 if (delta < moduleSize) {
121 return first_base;
122 }
123 }
124 return 0;
125}
CollectCodeRelocs(BYTE *pe_buffer, size_t buffer_size, IN bool _is64bit, OUT std::set< ULONGLONG > &_relocs)
Definition find_base.cpp:13
virtual bool processRelocField(ULONG_PTR relocField)
Definition find_base.cpp:20
static PIMAGE_SECTION_HEADER getCodeSection(BYTE *peBuffer, size_t bufferSize)
Definition find_base.cpp:45
PIMAGE_SECTION_HEADER codeSec
Definition find_base.cpp:63
std::set< ULONGLONG > & relocs
Definition find_base.cpp:62
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:70
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:101
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.