Split the library into CORE / ENGINE / HANDLERS layers

CORE (src/core): vmie_mem — guest-physical substrate with a data-driven
segment map (replaces the hardcoded 4 GiB PCI-hole topology). ENGINE
(src/engine): x86-64 paging + Windows bring-up; produces the generic memory
model. HANDLERS (src/handlers): the signature/value/pointer scanners, which
now consume an OS-agnostic contract.

Keystone: gva_ctx is split into vmie_mem (core) + vmie (engine); the generic
access functions take vmie_mem* + cr3 and no longer compile in the Windows
offset table. New public contract include/memmodel.h (vmie_mem, mem_view_t,
vregion, task, range, the gva_* access); win32 surface in include/vmie.h.
Leak relocations: the PE parser, UTF-16 decode and CR3-recovery heuristics
move engine-side; the matcher stays a pure, source-agnostic handler, and the
pointer scanner takes a generic range[] instead of reaching into the process
enumerator.
This commit is contained in:
2026-06-15 02:57:46 +03:00
parent 7c0995a4f2
commit b3441dd6f6
24 changed files with 1014 additions and 766 deletions
+11 -10
View File
@@ -2,7 +2,8 @@
*
* Opens a guest RAM backing file, brings up the VMI context, lists processes,
* and for the first user process dumps its loaded modules and mapped regions.
* Public surface only (include/include.h); never reaches into src/include.
* Public surface only (include/vmie.h); the region walk takes a vmie_mem*,
* borrowed from the engine via vmie_memory().
*
* argv[1] path to the guest RAM backing file
* argv[2] `low` - size in bytes of below-4G guest RAM (strtoull, base 0)
@@ -13,7 +14,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>
#include "include.h"
#include "vmie.h"
#define DEFAULT_NMAX 512
#define MOD_CAP 256
@@ -40,7 +41,7 @@ static void decode_prot(uint32_t prot, char out[5]) {
out[4] = 0;
}
static void dump_modules(gva_ctx* ctx, const process* pr) {
static void dump_modules(vmie* ctx, const process* pr) {
pmodule mods[MOD_CAP];
const int nm = proc_modules(ctx, pr, mods, MOD_CAP);
if (nm <= 0) {
@@ -67,12 +68,12 @@ static void dump_modules(gva_ctx* ctx, const process* pr) {
}
}
static void dump_regions(gva_ctx* ctx, const process* pr) {
static void dump_regions(vmie* ctx, const process* pr) {
vregion* rg = malloc((size_t)RGN_CAP * sizeof *rg);
if (!rg) {
return;
}
const int total = gva_regions(ctx, pr->cr3, 0, ~0ull, 0, rg, RGN_CAP);
const int total = gva_regions(vmie_memory(ctx), pr->cr3, 0, ~0ull, 0, rg, RGN_CAP);
const int shown = total < 0 ? 0 : (total < RGN_CAP ? total : RGN_CAP);
for (int i = 0; i < shown; i++) {
char prot[5];
@@ -102,7 +103,7 @@ int main(int argc, char** argv) {
}
}
gva_ctx* ctx = gva_ctx_alloc(ram_path, low);
vmie* ctx = vmie_open(ram_path, low);
if (!ctx) {
fprintf(stderr, "error: cannot open RAM backing file '%s'\n", ram_path);
return 1;
@@ -111,14 +112,14 @@ int main(int argc, char** argv) {
const int rc = host_bootstrap(ctx);
if (rc != 0) {
fprintf(stderr, "error: bootstrap failed (%d): %s\n", rc, bootstrap_stage(rc));
gva_ctx_free(ctx);
vmie_close(ctx);
return 1;
}
process* procs = malloc(nmax * sizeof *procs);
if (!procs) {
fprintf(stderr, "error: out of memory\n");
gva_ctx_free(ctx);
vmie_close(ctx);
return 1;
}
@@ -126,7 +127,7 @@ int main(int argc, char** argv) {
if (np < 0) {
fprintf(stderr, "error: proc_list failed (%d)\n", np);
free(procs);
gva_ctx_free(ctx);
vmie_close(ctx);
return 1;
}
@@ -156,6 +157,6 @@ int main(int argc, char** argv) {
}
free(procs);
gva_ctx_free(ctx);
vmie_close(ctx);
return 0;
}