mirror of
https://dev.lirent.ru/Vatrog/vm-introspection-engine.git
synced 2026-06-18 04:16:39 +03:00
Define the win32 engine; add a dump source and physical sigscan
Name and isolate the Windows engine as one of potentially several. The public surface moves to include/win32.h with an opaque vmie_win32 handle (vmie_win32_open/close/mem); the engine's Windows internals — host bring-up, the struct-offset profile, process/module/PE/text decode — live under src/engine/win32. The generic address-space layer stays in src/engine (gva.c + engine-arch.h, carrying no offset table): gva.c is de-profiled, and CR3 bring-up reaches the hot translator through a cold gva_translate bridge so the zero-copy hot path stays private and inlinable. A memory source is now first-class and public: vmie_mem_open/_open_segs/ _close open a flat dump (or an explicit segment map) as a vmie_mem, with gpa_seg promoted to the public contract. The physical signature scan is exposed source-agnostically: sig_scan_mem returns GPAs for any vmie_mem, sig_scan_sources scans several sources with per-source attribution, and sig_from_bytes builds an exact needle from a byte span. The pure matcher is unchanged; dumps and the live engine image are scanned uniformly, neither needing the other.
This commit is contained in:
+10
-66
@@ -2,7 +2,7 @@
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "engine.h"
|
||||
#include "engine-arch.h"
|
||||
|
||||
/* PTE permission bits we propagate down the walk. */
|
||||
#define PTE_RW (1ull << 1)
|
||||
@@ -45,7 +45,15 @@ static int gva_gpa(vmie_mem* m, uintptr_t cr3, uintptr_t va,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* zero-copy borrowed read: leaf-bounded host pointer at `va` (see engine.h). */
|
||||
/* cold extern translate: GPA of `va` under `cr3`, or -1. Wraps the hot static
|
||||
* gva_gpa for cold callers outside this TU (win32 bring-up) without exposing the
|
||||
* inlinable hot primitive. Declared in engine-arch.h. */
|
||||
__attribute__((cold))
|
||||
int gva_translate(vmie_mem* m, uintptr_t cr3, uintptr_t va, uintptr_t* gpa) {
|
||||
return gva_gpa(m, cr3, va, gpa, NULL);
|
||||
}
|
||||
|
||||
/* zero-copy borrowed read: leaf-bounded host pointer at `va` (see memmodel.h). */
|
||||
__attribute__((hot))
|
||||
const void* gva_ptr(vmie_mem* m, uintptr_t cr3, uintptr_t va, size_t* avail) {
|
||||
uintptr_t gpa; size_t leaf;
|
||||
@@ -91,47 +99,6 @@ int khalf_score(const vmie_mem* m, uint64_t pml4) {
|
||||
return n;
|
||||
}
|
||||
|
||||
__attribute__((cold))
|
||||
int cr3_recover(vmie* v, uint64_t va_self, uint64_t target_pa, uintptr_t* cr3_out) {
|
||||
vmie_mem* m = &v->mem;
|
||||
int best_score = -1; uint64_t best = 0;
|
||||
for (size_t off = 0; off + 0x1000 <= m->fsize; off += 0x1000) {
|
||||
const uintptr_t cand = offset_gpa(m, off);
|
||||
uintptr_t gpa;
|
||||
if (gva_gpa(m, cand, va_self, &gpa, NULL)) continue;
|
||||
if ((gpa & ~0xFFFull) != (target_pa & ~0xFFFull)) continue;
|
||||
const int score = khalf_score(m, cand);
|
||||
if (score > best_score) { best_score = score; best = cand; }
|
||||
}
|
||||
if (best_score < 0) return -1;
|
||||
*cr3_out = best;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ---- lifecycle (cold) ---------------------------------------------------- */
|
||||
|
||||
__attribute__((cold))
|
||||
vmie* vmie_open(const char* ram_path, uint64_t low) {
|
||||
vmie* v = calloc(1, sizeof *v);
|
||||
if (!v) {
|
||||
return NULL;
|
||||
}
|
||||
if (gpa_open(&v->mem, ram_path, low)) {
|
||||
free(v);
|
||||
return NULL;
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
__attribute__((cold))
|
||||
void vmie_close(vmie* v) {
|
||||
if (!v) {
|
||||
return;
|
||||
}
|
||||
gpa_close(&v->mem);
|
||||
free(v);
|
||||
}
|
||||
|
||||
/* ---- region enumeration -------------------------------------------------- */
|
||||
|
||||
struct rgn_acc {
|
||||
@@ -302,26 +269,3 @@ int gva_sweep(vmie_mem* m, uintptr_t cr3, uint64_t lo, uint64_t hi,
|
||||
free(rg); free(buf);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* ---- physical-image signature bridge ------------------------------------- *
|
||||
* Iterates the core segment map (each seg is one mem_view_t over its file span)
|
||||
* and runs the pure matcher. Reaches into vmie_mem, so it lives engine-side. */
|
||||
struct physcb { uint64_t* out; int max, n; };
|
||||
static int phys_hit(void* u, uint64_t gpa) {
|
||||
struct physcb* c = u;
|
||||
if (c->out && c->n < c->max) c->out[c->n] = gpa;
|
||||
c->n++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int gva_sig_phys(vmie_mem* m, const sig_pattern_t* p, uint64_t* out, int max) {
|
||||
if (!p || p->len == 0) return -1;
|
||||
struct physcb c = { out, max, 0 };
|
||||
|
||||
for (int i = 0; i < m->nseg; i++) {
|
||||
const gpa_seg* s = &m->seg[i];
|
||||
const mem_view_t v = { (const uint8_t*)m->pa + s->file_off, (size_t)s->len, s->gpa };
|
||||
sig_each(v, p, phys_hit, &c);
|
||||
}
|
||||
return c.n;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user