libPeConv
A library to load, manipulate, dump PE files.
Loading...
Searching...
No Matches
pe_mode_detector.cpp
Go to the documentation of this file.
2#include "peconv/util.h"
4#include "peconv/relocate.h"
5
6#include "peconv/logger.h"
7
8// Check if gaps between sections are typical for Virtual Alignment.
9// Returns true if confirmed, false if not confirmed. False result can also mean that data was invalid/insufficient to decide.
10bool is_virtual_padding(const BYTE* pe_buffer, size_t pe_size)
11{
12 const size_t r_align = peconv::get_sec_alignment((PBYTE)pe_buffer, true);
13
14 size_t sections_count = peconv::get_sections_count(pe_buffer, pe_size);
15 if (sections_count < 2) return false;
16
17 bool is_valid_padding = false;
18 for (size_t i = 1; i < sections_count; i += 2) {
19 PIMAGE_SECTION_HEADER sec1 = peconv::get_section_hdr(pe_buffer, pe_size, i-1);
20 PIMAGE_SECTION_HEADER sec2 = peconv::get_section_hdr(pe_buffer, pe_size, i);
21 if (!sec1 || !sec2) continue; //skip if fetching any of the sections failed
22
23 if (sec1->SizeOfRawData == 0) continue; //skip empty sections
24
25 const DWORD sec1_end_offset = sec1->VirtualAddress + sec1->SizeOfRawData;
26 if (sec2->VirtualAddress == sec1_end_offset) continue;
27
28 if (sec2->VirtualAddress < sec1_end_offset) {
29 //std::cout << "Invalid size of the section: " << std::hex << sec2->VirtualAddress << " vs "<< sec1_end_offset << std::endl;
30 return false;
31 }
32 const size_t diff = sec2->VirtualAddress - sec1_end_offset;
33 if (diff < r_align) continue; //to small to determine
34
35 BYTE* sec1_end_ptr = (BYTE*)((ULONGLONG)pe_buffer + sec1_end_offset);
36 if (!peconv::validate_ptr((const LPVOID)pe_buffer, pe_size, sec1_end_ptr, diff)) {
37 //std::cout << "Invalid pointer to the section\n";
38 return false;
39 }
40 if (peconv::is_padding(sec1_end_ptr, diff, 0)) {
41 is_valid_padding = true;
42 }
43 else {
44 return false;
45 }
46 }
47 return is_valid_padding;
48}
49
50// Check if the gap between the end of headers and the first section is typical for Virtual Alignment.
51// Returns true if confirmed, false if not confirmed. False result can also mean that data was invalid/insufficient to decide.
52bool is_hdr_virtual_align(const BYTE* pe_buffer, size_t pe_size)
53{
54 const size_t v_align = peconv::get_sec_alignment((PBYTE)pe_buffer, false);
55 if (peconv::get_hdrs_size(pe_buffer) >= v_align) {
56 //undetermined for such case
57 return false;
58 }
59 //walk through sections and check their sizes
60 size_t sections_count = peconv::get_sections_count(pe_buffer, pe_size);
61 if (sections_count == 0) return false;
62 for (size_t i = 0; i < sections_count; i++) {
63 PIMAGE_SECTION_HEADER sec = peconv::get_section_hdr(pe_buffer, pe_size, i);
64 if (!sec || sec->PointerToRawData == 0 || sec->SizeOfRawData == 0) {
65 continue; // check next
66 }
67 if (sec->PointerToRawData >= v_align) continue;
68
69 size_t diff = v_align - sec->PointerToRawData;
70 BYTE* sec_raw_ptr = (BYTE*)((ULONGLONG)pe_buffer + sec->PointerToRawData);
71 if (!peconv::validate_ptr((const LPVOID)pe_buffer, pe_size, sec_raw_ptr, diff)) {
72 return false;
73 }
74 if (peconv::is_padding(sec_raw_ptr, diff, 0)) {
75 return true;
76 }
77 }
78 return false;
79}
80
81bool is_sec_hdrs_erased(IN const BYTE* pe_buffer, IN size_t pe_size, bool is_raw)
82{
83 const size_t count = peconv::get_sections_count(pe_buffer, pe_size);
84 for (size_t i = 0; i < count; i++) {
85 const IMAGE_SECTION_HEADER* hdr = peconv::get_section_hdr(pe_buffer, pe_size, i);
86 if (!hdr) continue;
87 if (is_raw) {
88 if (hdr->PointerToRawData != 0) return false;
89 }
90 else {
91 if (hdr->VirtualAddress != 0) return false;
92 }
93 }
94 return true;
95}
96
97bool peconv::is_pe_raw_eq_virtual(IN const BYTE* pe_buffer, IN size_t pe_size)
98{
99 const size_t count = peconv::get_sections_count(pe_buffer, pe_size);
100 for (size_t i = 0; i < count; i++) {
101 const IMAGE_SECTION_HEADER* hdr = peconv::get_section_hdr(pe_buffer, pe_size, i);
102 if (!hdr) continue;
103
104 if (hdr->VirtualAddress != hdr->PointerToRawData) {
105 return false;
106 }
107 }
108 return true;
109}
110
111bool is_pe_mapped(IN const BYTE* pe_buffer, IN size_t pe_size)
112{
113 size_t v_score = 0;
114 if (peconv::has_valid_import_table((const PBYTE)pe_buffer, pe_size)) {
115 LOG_INFO("Valid Import Table found.");
116 v_score++;
117 }
118 if (peconv::has_valid_relocation_table((const PBYTE)pe_buffer, pe_size)) {
119 LOG_INFO("Valid Relocations Table found.");
120 v_score++;
121 }
122 if (is_hdr_virtual_align(pe_buffer, pe_size)) {
123 LOG_INFO("Header virtual alignment OK.");
124 v_score++;
125 }
126 LOG_INFO("TOTAL v_score: %zu.", v_score);
127 if (v_score > 0) {
128 return true;
129 }
130 return false;
131}
132
133bool peconv::is_pe_raw(IN const BYTE* pe_buffer, IN size_t pe_size)
134{
135 if (peconv::get_sections_count(pe_buffer, pe_size) == 0) {
136 return true;
137 }
138 if (is_pe_mapped(pe_buffer, pe_size)) {
139 // it has artefacts typical for a PE in a virtual alignment
140 return false;
141 }
142 if (is_sec_hdrs_erased(pe_buffer, pe_size, true)) {
143 LOG_INFO("Raw alignment is erased.");
144 // the raw alignment of the sections is erased
145 return false;
146 }
147 return true;
148}
149
150// checks if any sections has been expanded in the memory
151bool peconv::is_pe_expanded(IN const BYTE* pe_buffer, IN size_t pe_size)
152{
153 //walk through sections and check their sizes
154 size_t sections_count = peconv::get_sections_count(pe_buffer, pe_size);
155 for (size_t i = 0; i < sections_count; i++) {
156 PIMAGE_SECTION_HEADER sec = peconv::get_section_hdr(pe_buffer, pe_size, i);
157 if (is_section_expanded(pe_buffer, pe_size, sec)) {
158 return true;
159 }
160 }
161 return false;
162}
163
164// checks if the section's content in memory is bigger than in the raw format
165bool peconv::is_section_expanded(IN const BYTE* pe_buffer, IN size_t pe_size, IN const PIMAGE_SECTION_HEADER sec)
166{
167 if (!sec) return false;
168
169 size_t sec_vsize = peconv::get_virtual_sec_size(pe_buffer, sec, true);
170 size_t sec_rsize = sec->SizeOfRawData;
171
172 if (sec_rsize >= sec_vsize) return false;
173 size_t diff = sec_vsize - sec_rsize;
174
175 BYTE* sec_raw_end_ptr = (BYTE*)((ULONGLONG)pe_buffer + sec->VirtualAddress + sec_rsize);
176 if (!peconv::validate_ptr((const LPVOID)pe_buffer, pe_size, sec_raw_end_ptr, diff)) {
177 return false;
178 }
179 if (!is_padding(sec_raw_end_ptr, diff, 0)) {
180 //this is not padding: non-zero content detected
181 return true;
182 }
183 return false;
184}
Parsing and filling the Import Table.
#define LOG_INFO(fmt,...)
Definition logger.h:50
bool has_valid_import_table(const PBYTE modulePtr, size_t moduleSize, size_t max_count=0)
bool is_section_expanded(IN const BYTE *pe_buffer, IN size_t pe_size, IN const PIMAGE_SECTION_HEADER sec)
DWORD get_virtual_sec_size(IN const BYTE *pe_hdr, IN const PIMAGE_SECTION_HEADER sec_hdr, IN bool rounded)
bool is_pe_raw(IN const BYTE *pe_buffer, IN size_t pe_size)
bool validate_ptr(IN const void *buffer_bgn, IN size_t buffer_size, IN const void *field_bgn, IN size_t field_size)
PIMAGE_SECTION_HEADER get_section_hdr(IN const BYTE *pe_buffer, IN const size_t buffer_size, IN size_t section_num)
bool is_padding(const BYTE *cave_ptr, size_t cave_size, const BYTE padding_char)
Definition util.cpp:106
DWORD get_sec_alignment(IN const BYTE *modulePtr, IN bool is_raw)
bool is_pe_raw_eq_virtual(IN const BYTE *pe_buffer, IN size_t pe_size)
size_t get_sections_count(IN const BYTE *buffer, IN const size_t buffer_size)
bool is_pe_expanded(IN const BYTE *pe_buffer, IN size_t pe_size)
DWORD get_hdrs_size(IN const BYTE *pe_buffer)
bool has_valid_relocation_table(IN const PBYTE modulePtr, IN const size_t moduleSize)
Definition relocate.cpp:185
bool is_hdr_virtual_align(const BYTE *pe_buffer, size_t pe_size)
bool is_virtual_padding(const BYTE *pe_buffer, size_t pe_size)
bool is_sec_hdrs_erased(IN const BYTE *pe_buffer, IN size_t pe_size, bool is_raw)
bool is_pe_mapped(IN const BYTE *pe_buffer, IN size_t pe_size)
Detecting in which mode is the PE in the supplied buffer (i.e. raw, virtual). Analyzes PE features ty...
Operating on PE file's relocations table.
Miscellaneous utility functions.