mirror of
https://dev.lirent.ru/Vatrog/vm-introspection-engine.git
synced 2026-07-09 02:56:36 +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:
@@ -0,0 +1,62 @@
|
||||
/* sigphys.c - physical-image signature bridge (OS-agnostic engine 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 (the segment table), so it is
|
||||
* an engine bridge, not a handler - but it names no Windows concept and depends
|
||||
* on no paging/profile, so it lives engine-side, outside src/engine/win32/. The
|
||||
* dump-only scan set is { core/gpa.c, handlers/sigscan.c, this }, no win32. */
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include "core.h"
|
||||
#include "sigscan.h"
|
||||
#include "scan.h"
|
||||
|
||||
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 sig_scan_mem(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;
|
||||
}
|
||||
|
||||
/* Tagging callback for the multi-source scan: stamps the current source index
|
||||
* onto each hit and writes attributed records up to capacity. */
|
||||
struct srccb { sig_hit_src* out; int max, n, source; };
|
||||
static int src_hit(void* u, uint64_t gpa) {
|
||||
struct srccb* c = u;
|
||||
if (c->out && c->n < c->max) {
|
||||
c->out[c->n].source = c->source;
|
||||
c->out[c->n].gpa = gpa;
|
||||
}
|
||||
c->n++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sig_scan_sources(vmie_mem* const* srcs, int nsrc, const sig_pattern_t* p,
|
||||
sig_hit_src* out, int max) {
|
||||
if (!p || p->len == 0) return -1;
|
||||
struct srccb c = { out, max, 0, 0 };
|
||||
|
||||
for (int si = 0; si < nsrc; si++) {
|
||||
vmie_mem* m = srcs[si];
|
||||
c.source = si;
|
||||
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, src_hit, &c);
|
||||
}
|
||||
}
|
||||
return c.n;
|
||||
}
|
||||
Reference in New Issue
Block a user