Files
vatrog-vm-introspection-engine/src/engine/win32/pe.c
T

64 lines
2.6 KiB
C
Raw Normal View History

#include "pe.h"
#include <string.h>
#include "memmodel.h" /* gva_read */
#include "sigscan.h" /* mem_sub (pure matcher; engine may use it) */
bool pe_find_section(mem_view_t v, uint64_t module_base, const char* name,
uint64_t* rva_out, uint32_t* vsize_out) {
if (!v.data || !name || module_base < v.base_va) return false;
const size_t mo = (size_t)(module_base - v.base_va);
if (mo + 0x40 > v.size) return false;
if (v.data[mo] != 'M' || v.data[mo + 1] != 'Z') return false;
int32_t e_lfanew;
memcpy(&e_lfanew, v.data + mo + 0x3C, 4);
const size_t nt = mo + (size_t)(uint32_t)e_lfanew;
if (nt + 0x18 > v.size) return false;
if (memcmp(v.data + nt, "PE\0\0", 4) != 0) return false;
uint16_t nsec, opt_size;
memcpy(&nsec, v.data + nt + 6, 2); /* NumberOfSections */
memcpy(&opt_size, v.data + nt + 20, 2); /* SizeOfOptionalHeader */
const size_t sec = nt + 24 + opt_size; /* first section header */
size_t want = strlen(name);
if (want > 8) want = 8;
for (uint16_t i = 0; i < nsec; i++) {
const size_t sh = sec + (size_t)i * 40;
if (sh + 40 > v.size) break;
char nm[9] = {0};
memcpy(nm, v.data + sh, 8);
if (strncmp(nm, name, want) == 0 && (want == 8 || nm[want] == '\0')) {
uint32_t vsize, vaddr;
memcpy(&vsize, v.data + sh + 8, 4); /* Misc.VirtualSize */
memcpy(&vaddr, v.data + sh + 12, 4); /* VirtualAddress */
if (rva_out) *rva_out = vaddr;
if (vsize_out) *vsize_out = vsize;
return true;
}
}
return false;
}
bool pe_section(mem_view_t v, uint64_t module_base, const char* name, mem_view_t* out) {
uint64_t rva; uint32_t vsize;
if (!out || !pe_find_section(v, module_base, name, &rva, &vsize)) return false;
*out = mem_sub(v, module_base + rva, vsize);
return out->data != NULL;
}
int vmie_pe_section(vmie_mem* m, uintptr_t cr3, uint64_t module_base,
const char* name, uint8_t* buf, size_t bufcap, mem_view_t* out) {
uint8_t hdr[0x1000];
if (!out || !buf || gva_read(m, cr3, module_base, hdr, sizeof hdr)) return -1;
const mem_view_t hv = { hdr, sizeof hdr, module_base };
uint64_t rva; uint32_t vsize;
if (!pe_find_section(hv, module_base, name, &rva, &vsize)) return -1;
const size_t n = vsize < bufcap ? vsize : bufcap;
if (gva_read(m, cr3, module_base + rva, buf, n)) return -1;
out->data = buf; out->size = n; out->base_va = module_base + rva;
return 0;
}