mirror of
https://dev.lirent.ru/Vatrog/vm-introspection-engine.git
synced 2026-06-18 04:16:39 +03:00
64 lines
2.6 KiB
C
64 lines
2.6 KiB
C
|
|
#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;
|
||
|
|
}
|