libPeConv
A library to load, manipulate, dump PE files.
Loading...
Searching...
No Matches
caves.cpp
Go to the documentation of this file.
1#include "peconv/caves.h"
3#include "peconv/util.h"
4#include "peconv/logger.h"
5
6using namespace peconv;
7
8PBYTE peconv::find_ending_cave(BYTE* modulePtr, size_t moduleSize, const DWORD minimal_size, const DWORD req_charact, bool reserve)
9{
10 if (!modulePtr || !moduleSize) return nullptr;
11
12 size_t sec_count = peconv::get_sections_count(modulePtr, moduleSize);
13 if (sec_count == 0) return nullptr;
14
15 const size_t last_sec = sec_count - 1;
16 const PIMAGE_SECTION_HEADER section_hdr = peconv::get_section_hdr(modulePtr, moduleSize, last_sec);
17 if (!section_hdr) return nullptr;
18 if (!(section_hdr->Characteristics & req_charact)) return nullptr;
19
20 const DWORD raw_size = section_hdr->SizeOfRawData;
21 const size_t vsize_full = moduleSize - section_hdr->VirtualAddress;
22 if (vsize_full > MAXDWORD) return nullptr;
23
24 const DWORD virtual_size = static_cast<DWORD>(vsize_full);
25 if (raw_size >= virtual_size) {
26 LOG_INFO("Last section's raw_size: 0x%lx >= virtual_size: 0x%lx", raw_size, virtual_size);
27 return nullptr;
28 }
29 const DWORD cave_size = virtual_size - raw_size;
30 if (cave_size < minimal_size) {
31 LOG_INFO("Cave is too small.");
32 return nullptr;
33 }
34 const PBYTE cave_ptr = modulePtr + section_hdr->VirtualAddress + section_hdr->SizeOfRawData;
35 if (!validate_ptr(modulePtr, moduleSize, cave_ptr, minimal_size)) {
36 LOG_INFO("Invalid cave pointer.");
37 return nullptr;
38 }
39 if (reserve) {
40 section_hdr->SizeOfRawData += minimal_size; //book this cave
41 }
42 return cave_ptr;
43}
44
45PBYTE peconv::find_alignment_cave(BYTE* modulePtr, size_t moduleSize, const DWORD minimal_size, const DWORD req_charact, bool reserve)
46{
47 DWORD alignment = peconv::get_sec_alignment(modulePtr, true);
48 if (alignment == 0) return nullptr;
49
50 size_t sec_count = peconv::get_sections_count(modulePtr, moduleSize);
51 for (size_t i = 0; i < sec_count; i++) {
52 PIMAGE_SECTION_HEADER section_hdr = peconv::get_section_hdr(modulePtr, moduleSize, i);
53 if (section_hdr == nullptr) continue;
54 if (!(section_hdr->Characteristics & req_charact)) continue;
55
56 DWORD rem = section_hdr->SizeOfRawData % alignment;
57 if (rem == 0) continue;
58
59 DWORD new_size = peconv::round_up_to_unit(section_hdr->SizeOfRawData, alignment);
60 DWORD cave_size = new_size - section_hdr->SizeOfRawData;
61 if (cave_size < minimal_size) {
62 LOG_INFO("Cave is too small.");
63 continue;
64 }
65 DWORD sec_start = section_hdr->PointerToRawData;
66 if (sec_start == 0) continue;
67
68 DWORD sec_end = sec_start + section_hdr->SizeOfRawData;
69 LOG_INFO("Section: 0x%lx : 0x%lx", sec_start, sec_end);
70 PBYTE cave_ptr = modulePtr + sec_end;
71 if (!validate_ptr(modulePtr, moduleSize, cave_ptr, minimal_size)) {
72 LOG_INFO("Invalid cave pointer.");
73 continue;
74 }
75 if (reserve) {
76 section_hdr->SizeOfRawData += minimal_size; //book this cave
77 }
78 return cave_ptr;
79 }
80 LOG_INFO("Cave not found.");
81 return nullptr;
82}
83
84PBYTE peconv::find_padding_cave(BYTE* modulePtr, size_t moduleSize, const size_t minimal_size, const DWORD req_charact)
85{
86 size_t sec_count = peconv::get_sections_count(modulePtr, moduleSize);
87 for (size_t i = 0; i < sec_count; i++) {
88 PIMAGE_SECTION_HEADER section_hdr = peconv::get_section_hdr(modulePtr, moduleSize, i);
89 if (section_hdr == nullptr) continue;
90 if (!(section_hdr->Characteristics & req_charact)) continue;
91
92 if (section_hdr->SizeOfRawData < minimal_size) continue;
93
94 // we will be searching in the loaded, virtual image:
95 DWORD sec_start = section_hdr->VirtualAddress;
96 if (sec_start == 0) continue;
97
98 DWORD sec_end = sec_start + section_hdr->SizeOfRawData;
99 LOG_INFO("Section: 0x%lx : 0x%lx", sec_start, sec_end);
100 //offset from the end of the section:
101 size_t cave_offset = section_hdr->SizeOfRawData - minimal_size;
102 PBYTE cave_ptr = modulePtr + sec_start + cave_offset;
103 if (!validate_ptr(modulePtr, moduleSize, cave_ptr, minimal_size)) {
104 LOG_INFO("Invalid cave pointer.");
105 continue;
106 }
107 bool found = false;
108 if (is_padding(cave_ptr, minimal_size, 0)) {
109 found = true;
110 }
111 //if the section is code, check also code padding:
112 if (section_hdr->Characteristics & IMAGE_SCN_MEM_EXECUTE) {
113 if (is_padding(cave_ptr, minimal_size, 0xCC)) {
114 found = true;
115 }
116 }
117 if (found) {
118 return cave_ptr;
119 }
120 }
121 LOG_INFO("Cave not found.");
122 return nullptr;
123}
Functions related to finding caves in the loaded PE file.
Compile-time configurable logging macros for peconv.
#define LOG_INFO(fmt,...)
Definition: logger.h:74
PBYTE find_padding_cave(BYTE *module_ptr, size_t module_size, const size_t minimal_size, const DWORD req_charact=IMAGE_SCN_MEM_READ)
Definition: caves.cpp:84
PBYTE find_ending_cave(BYTE *module_ptr, size_t module_size, const DWORD cave_size, const DWORD req_charact=IMAGE_SCN_MEM_READ, bool reserve=true)
Definition: caves.cpp:8
bool validate_ptr(IN const void *buffer_bgn, IN size_t buffer_size, IN const void *field_bgn, IN size_t field_size)
Definition: buffer_util.cpp:9
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)
INT_TYPE round_up_to_unit(const INT_TYPE size, const INT_TYPE unit)
Definition: util.h:43
size_t get_sections_count(IN const BYTE *buffer, IN const size_t buffer_size)
PBYTE find_alignment_cave(BYTE *module_ptr, size_t module_size, const DWORD cave_size, const DWORD req_charact=IMAGE_SCN_MEM_READ, bool reserve=true)
Definition: caves.cpp:45
Wrappers over various fields in the PE header. Read, write, parse PE headers.
Miscellaneous utility functions.