12 memset(&page_info, 0,
sizeof(MEMORY_BASIC_INFORMATION));
13 SIZE_T out = VirtualQueryEx(processHandle, moduleBase, &page_info,
sizeof(page_info));
14 if (out !=
sizeof(page_info)) {
22 if (page_info.Type == 0) {
25 if ((BYTE*)page_info.BaseAddress > moduleBase) {
28 const size_t offset = (ULONG_PTR)moduleBase - (ULONG_PTR)page_info.BaseAddress;
29 const size_t area_size = page_info.RegionSize - offset;
35 MEMORY_BASIC_INFORMATION page_info = { 0 };
45 MEMORY_BASIC_INFORMATION page_info = { 0 };
49 if (page_info.Type == 0) {
52 return (ULONGLONG) page_info.AllocationBase;
61 SIZE_T
_search_readable_size(HANDLE processHandle, LPVOID start_addr, OUT BYTE* buffer,
const size_t buffer_size,
const SIZE_T minimal_size)
63 if (!buffer || buffer_size == 0) {
66 if ((buffer_size < minimal_size) || minimal_size == 0) {
69 SIZE_T last_failed_size = buffer_size;
70 SIZE_T last_success_size = 0;
72 SIZE_T test_read_size = 0;
73 if (!ReadProcessMemory(processHandle, start_addr, buffer, minimal_size, &test_read_size)) {
75 return test_read_size;
77 last_success_size = minimal_size;
80 SIZE_T to_read_size = buffer_size/2;
82 while (to_read_size > minimal_size && to_read_size < buffer_size)
85 if (ReadProcessMemory(processHandle, start_addr, buffer, to_read_size, &read_size)) {
86 last_success_size = to_read_size;
89 last_failed_size = to_read_size;
91 const size_t delta = (last_failed_size - last_success_size) / 2;
92 if (delta == 0)
break;
93 to_read_size = last_success_size + delta;
95 if (last_success_size) {
97 memset(buffer, 0, buffer_size);
98 if (ReadProcessMemory(processHandle, start_addr, buffer, last_success_size, &read_size)) {
106size_t peconv::read_remote_memory(HANDLE processHandle, LPVOID start_addr, OUT BYTE* buffer,
const size_t buffer_size,
const SIZE_T minimal_size)
108 if (!buffer || buffer_size == 0) {
111 memset(buffer, 0, buffer_size);
113 SIZE_T read_size = 0;
114 DWORD last_error = ERROR_SUCCESS;
116 while (buffer_size > 0)
118 if (ReadProcessMemory(processHandle, start_addr, buffer, buffer_size, &read_size)) {
121 last_error = GetLastError();
122 if (last_error != ERROR_SUCCESS) {
123 if (read_size == 0 && (last_error != ERROR_PARTIAL_COPY)) {
127 if (last_error == ERROR_PARTIAL_COPY) {
130 std::cout <<
"peconv::search_readable_size res: " << std::hex << read_size << std::endl;
137 if (read_size == 0) {
138 std::cerr <<
"[WARNING] Cannot read memory. Last Error : " << last_error << std::endl;
140 else if (read_size < buffer_size) {
141 std::cerr <<
"[WARNING] Read size: " << std::hex << read_size
142 <<
" is smaller than the requested size: " << std::hex << buffer_size
143 <<
". Last Error: " << last_error << std::endl;
147 return static_cast<size_t>(read_size);
150size_t peconv::read_remote_region(HANDLE processHandle, LPVOID start_addr, OUT BYTE* buffer,
const size_t buffer_size,
const bool force_access,
const SIZE_T minimal_size)
152 if (!buffer || buffer_size == 0) {
155 MEMORY_BASIC_INFORMATION page_info = { 0 };
159 if ((page_info.State & MEM_COMMIT) == 0) {
163 if (region_size == 0) {
167 const size_t size_to_read = (region_size > buffer_size) ? buffer_size : region_size;
169 const bool is_accessible = (page_info.Protect & PAGE_NOACCESS) == 0;
170 BOOL access_changed = FALSE;
171 DWORD oldProtect = 0;
174 if (force_access && !is_accessible) {
175 access_changed = VirtualProtectEx(processHandle, start_addr, region_size, PAGE_READONLY, &oldProtect);
177 if (!access_changed) {
178 DWORD err = GetLastError();
179 if (err != ERROR_ACCESS_DENIED) {
180 std::cerr <<
"[!] " << std::hex << start_addr <<
" : " << region_size <<
" inaccessible area, changing page access failed: " << std::dec << err <<
"\n";
186 size_t size_read = 0;
187 if (is_accessible || access_changed) {
189 if ((size_read == 0) && (page_info.Protect & PAGE_GUARD)) {
191 std::cout <<
"Warning: guarded page, trying to read again..." << std::endl;
197 if (access_changed) {
198 VirtualProtectEx(processHandle, start_addr, region_size, oldProtect, &oldProtect);
203size_t peconv::read_remote_area(HANDLE processHandle, LPVOID start_addr, OUT BYTE* buffer,
const size_t buffer_size,
const bool force_access,
const SIZE_T minimal_size)
205 if (!buffer || !start_addr || buffer_size == 0) {
208 memset(buffer, 0, buffer_size);
210 size_t real_read = 0;
211 size_t last_valid = 0;
213 size_t buf_index = 0;
214 for (buf_index = 0; buf_index < buffer_size; ) {
215 LPVOID remote_chunk = LPVOID((ULONG_PTR)start_addr + buf_index);
217 MEMORY_BASIC_INFORMATION page_info = { 0 };
222 if (region_size == 0) {
230 (BYTE*)((ULONG_PTR)buffer + buf_index),
231 buffer_size - buf_index,
235 if (read_chunk == 0) {
237 buf_index += region_size;
240 buf_index += read_chunk;
241 real_read += read_chunk;
242 last_valid = buf_index;
244 if (real_read == 0) {
252 if (buffer ==
nullptr) {
255 SIZE_T read_size =
read_remote_area(processHandle, start_addr, buffer, buffer_size, force_access);
256 if (read_size == 0) {
260 if (nt_ptr ==
nullptr) {
263 const size_t nt_offset = nt_ptr - buffer;
264 const size_t nt_size =
peconv::is64bit(buffer) ?
sizeof(IMAGE_NT_HEADERS64) :
sizeof(IMAGE_NT_HEADERS32);
265 const size_t min_size = nt_offset + nt_size;
267 if (read_size < min_size) {
269 <<
" ][" << std::hex << (ULONGLONG) start_addr
270 <<
"] Read size: " << std::hex << read_size
271 <<
" is smaller that the minimal size:" <<
get_hdrs_size(buffer)
285 size_t parts = size / unit;
286 if (size % unit) parts++;
299 if (section_hdr == NULL || section_hdr->Misc.VirtualSize == 0) {
302 size_t buffer_size = section_hdr->Misc.VirtualSize;
309 if (module_code == NULL) {
312 size_t read_size =
peconv::read_remote_memory(processHandle, LPVOID((ULONG_PTR)start_addr + section_hdr->VirtualAddress), module_code, buffer_size);
313 if (read_size == 0) {
315 read_size =
read_remote_area(processHandle, LPVOID((ULONG_PTR)start_addr + section_hdr->VirtualAddress), module_code, buffer_size, force_access);
317 if (read_size == 0) {
321 section_size = buffer_size;
325size_t peconv::read_remote_pe(
const HANDLE processHandle, LPVOID start_addr,
const size_t mod_size, OUT BYTE* buffer,
const size_t bufferSize)
327 if (buffer ==
nullptr) {
328 std::cerr <<
"[-] Invalid output buffer: NULL pointer" << std::endl;
332 std::cerr <<
"[-] Invalid output buffer: too small size!" << std::endl;
336 PBYTE hdr_buffer = buffer;
339 std::cerr <<
"[-] Failed to read the module header" << std::endl;
343 std::cerr <<
"[-] Sections headers are invalid or atypically aligned" << std::endl;
348 std::cout <<
"Sections: " << sections_count << std::endl;
352 for (
size_t i = 0; i < sections_count; i++) {
355 std::cerr <<
"[-] Failed to read the header of section: " << i << std::endl;
358 const DWORD sec_va = hdr->VirtualAddress;
360 if (sec_va + sec_vsize > bufferSize) {
361 std::cerr <<
"[-] No more space in the buffer!" << std::endl;
364 if (sec_vsize > 0 && !
read_remote_memory(processHandle, LPVOID((ULONG_PTR)start_addr + sec_va), buffer + sec_va, sec_vsize)) {
366 std::cerr <<
"[-] [" << std::hex << start_addr <<
"] Failed to read the module section " << i <<
" : at: " << std::hex << (ULONG_PTR)start_addr + sec_va << std::endl;
370 size_t new_end = sec_va + sec_vsize;
371 if (new_end > read_size) read_size = new_end;
374 std::cout <<
"Total read size: " << read_size << std::endl;
390 IN
const HANDLE processHandle,
391 IN LPVOID start_addr,
397 std::cout <<
"Module Size: " << mod_size << std::endl;
403 if (buffer ==
nullptr) {
404 std::cerr <<
"[-] Failed allocating buffer. Error: " << GetLastError() << std::endl;
408 const size_t read_size =
read_remote_pe(processHandle, start_addr, mod_size, buffer, mod_size);
409 if (read_size == 0) {
410 std::cerr <<
"[-] Failed reading module. Error: " << GetLastError() << std::endl;
418 reinterpret_cast<ULONGLONG
>(start_addr),
419 dump_mode, exportsMap);
Functions and classes responsible for fixing Import Table. A definition of ImportedDllCoverage class.
DWORD get_process_id(HANDLE hProcess)
peconv::UNALIGNED_BUF get_remote_pe_section(HANDLE processHandle, LPVOID moduleBase, const size_t sectionNum, OUT size_t §ionSize, bool roundup, bool force_access=false)
DWORD get_virtual_sec_size(IN const BYTE *pe_hdr, IN const PIMAGE_SECTION_HEADER sec_hdr, IN bool rounded)
bool dump_remote_pe(IN LPCTSTR outputFilePath, IN const HANDLE processHandle, IN LPVOID moduleBase, IN OUT t_pe_dump_mode &dump_mode, IN OPTIONAL peconv::ExportsMapper *exportsMap=nullptr)
bool is_valid_sections_hdr_offset(IN const BYTE *buffer, IN const size_t buffer_size)
UNALIGNED_BUF alloc_unaligned(size_t buf_size)
size_t read_remote_region(HANDLE processHandle, LPVOID start_addr, OUT BYTE *buffer, const size_t buffer_size, const bool force_access, const SIZE_T minimal_size=0x100)
PIMAGE_SECTION_HEADER get_section_hdr(IN const BYTE *pe_buffer, IN const size_t buffer_size, IN size_t section_num)
size_t read_remote_memory(HANDLE processHandle, LPVOID start_addr, OUT BYTE *buffer, const size_t buffer_size, const SIZE_T minimal_size=0x100)
bool fetch_region_info(HANDLE processHandle, LPVOID start_addr, MEMORY_BASIC_INFORMATION &page_info)
DWORD get_image_size(IN const BYTE *payload)
size_t read_remote_area(HANDLE processHandle, LPVOID start_addr, OUT BYTE *buffer, const size_t buffer_size, const bool force_access, const SIZE_T minimal_size=0x100)
bool free_pe_buffer(ALIGNED_BUF buffer, size_t buffer_size=0)
ALIGNED_BUF alloc_pe_buffer(size_t buffer_size, DWORD protect, ULONGLONG desired_base=NULL)
size_t roundup_to_unit(size_t size, size_t unit)
DWORD get_sec_alignment(IN const BYTE *modulePtr, IN bool is_raw)
bool is64bit(IN const BYTE *pe_buffer)
size_t get_sections_count(IN const BYTE *buffer, IN const size_t buffer_size)
SIZE_T _search_readable_size(HANDLE processHandle, LPVOID start_addr, OUT BYTE *buffer, const size_t buffer_size, const SIZE_T minimal_size)
const ULONGLONG MAX_HEADER_SIZE
bool read_remote_pe_header(HANDLE processHandle, LPVOID moduleBase, OUT BYTE *buffer, const size_t bufferSize, bool force_access=false)
bool dump_pe(IN LPCTSTR outputFilePath, IN OUT BYTE *buffer, IN size_t buffer_size, IN const ULONGLONG module_base, IN OUT t_pe_dump_mode &dump_mode, IN OPTIONAL const peconv::ExportsMapper *exportsMap=nullptr)
DWORD get_hdrs_size(IN const BYTE *pe_buffer)
BYTE * get_nt_hdrs(IN const BYTE *pe_buffer, IN OPTIONAL size_t buffer_size=0)
size_t read_remote_pe(const HANDLE processHandle, LPVOID moduleBase, const size_t moduleSize, OUT BYTE *buffer, const size_t bufferSize)
size_t fetch_region_size(HANDLE processHandle, LPVOID start_addr)
ULONGLONG fetch_alloc_base(HANDLE processHandle, LPVOID start_addr)
void free_unaligned(UNALIGNED_BUF section_buffer)
DWORD get_remote_image_size(IN const HANDLE processHandle, IN LPVOID start_addr)
size_t _fetch_region_size(MEMORY_BASIC_INFORMATION &page_info, LPVOID moduleBase)
Reading from a PE module that is loaded within a remote process.
Miscellaneous utility functions.