/* scan.h - typed value scanner, pointer scanner, and gva<->signature bridges. * * Layered above the pure matcher (sigscan.h) and the generic memory-model * contract (memmodel.h): this is the OS-agnostic scanning surface. Everything * here is keyed by a `vmie_mem*` + `cr3` (and, for the pointer scan, a decoded * `range[]`); it names no Windows object. The value scanner narrows a candidate * set across successive snapshots; the pointer scanner discovers range-anchored * pointer chains; the gva_sig_* bridges build mem_view_t windows out of guest * memory and feed them to the signature matcher. * * The Windows-typed convenience entry points (scan_new(process*), * vmie_scan_pointer(process*)) live in the win32 surface (win32.h). */ #ifndef VMIE_SCAN_H #define VMIE_SCAN_H #include #include #include "memmodel.h" /* vmie_mem, range, vregion */ #include "sigscan.h" /* mem_view_t, sig_pattern_t */ /* typed value scanner. ENUMERATOR ORDER IS LOAD-BEARING: scan.c indexes the * table g_tsz[] = {1,2,4,8, 1,2,4,8, 4,8, 2} by these values - do not reorder * without updating scan.c. */ typedef enum { SCAN_I8, SCAN_I16, SCAN_I32, SCAN_I64, /* signed */ SCAN_U8, SCAN_U16, SCAN_U32, SCAN_U64, /* unsigned */ SCAN_F32, SCAN_F64, SCAN_F16 /* float */ } scan_type; typedef enum { SCAN_EQ, SCAN_NEQ, SCAN_GT, SCAN_LT, /* require a value argument */ SCAN_INC, SCAN_DEC, SCAN_CHANGED, SCAN_UNCHANGED /* relative to the previous snapshot */ } scan_op; typedef struct scan scan; /* opaque session */ typedef struct { uint64_t addr; uint64_t value; } scan_hit; #define SCAN_PTR_MAXDEPTH 8 /* DFS depth and size of off[] */ typedef struct { uint64_t base; /* range-anchored base address */ int depth; /* number of offsets in off[] */ int32_t off[SCAN_PTR_MAXDEPTH]; /* dereference chain */ } scan_ptr_path; scan* scan_new_cr3(vmie_mem* m, uintptr_t cr3, scan_type t, const void* value, int be, int aligned, uint64_t lo, uint64_t hi); int64_t scan_next(scan* s, scan_op op, const void* value); int64_t scan_count(scan* s); int scan_results(scan* s, uint64_t offset, int max, scan_hit* out); void scan_free(scan* s); int scan_pointer(vmie_mem* m, uintptr_t cr3, const range* mods, int nmods, uint64_t target, int max_depth, uint32_t max_off, scan_ptr_path* out, int max); /* gva bridges to the signature matcher: build mem_view from guest memory and feed sigscan.h */ int gva_sig_scan (vmie_mem* m, uintptr_t cr3, uint64_t lo, uint64_t hi, uint32_t prot_any, const sig_pattern_t* p, uint64_t* out, int max); int gva_sig_first(vmie_mem* m, uintptr_t cr3, uint64_t lo, uint64_t hi, uint32_t prot_any, const sig_pattern_t* p, uint64_t* va); int gva_sig_rip (vmie_mem* m, uintptr_t cr3, uint64_t hit_va, size_t disp_off, size_t instr_len, uint64_t* target); /* ---- physical-image signature scan (OS-agnostic engine bridge) ----------- * * Scan the raw physical image (the core segment map) for a signature, without a * cr3 or page tables: each seg is one mem_view_t over its file span, fed to the * pure matcher. This is the dump path - a dump (vmie_mem_open*) supports the * physical scan only. Keyed by vmie_mem*, like the rest of this header. */ /* Attributed hit from a multi-source scan: which source matched, and where. */ typedef struct { int source; uint64_t gpa; } sig_hit_src; /* Scan one physical image for `p`. Writes up to `max` GPA hits to `out` (NULL to * count only) and returns the TOTAL number of hits, or -1 on a bad pattern. */ int sig_scan_mem (vmie_mem* m, const sig_pattern_t* p, uint64_t* out, int max); /* Scan `nsrc` physical images for `p`, tagging each hit with its source index. * Writes up to `max` attributed hits to `out` (NULL to count only) and returns * the TOTAL across all sources, or -1 on a bad pattern. */ int sig_scan_sources(vmie_mem* const* srcs, int nsrc, const sig_pattern_t* p, sig_hit_src* out, int max); #endif /* VMIE_SCAN_H */