mirror of
https://dev.lirent.ru/Vatrog/vm-introspection-engine.git
synced 2026-07-09 01:46:38 +03:00
Add operand-normalized semantic code signatures
New semsig_hash(mem_view_t) primitive (include/semsig.h): a position-,
register-, immediate- and instruction-order-invariant function fingerprint.
It folds per-instruction operand-canonical tokens, splitting the body into
basic blocks via cfg_blocks and using a within-block order-insensitive
sort-then-fold (between-block order preserved), so it survives compiler
register reallocation and instruction scheduling that the byte-mask
func_hash/sig_generate cannot. Distinct hash domain from func_hash.
The operand decode is delegated to an OPTIONAL external disassembler behind
a private adapter seam (src/handlers/semsig_backend.h); semsig.c stays
backend-neutral and includes no backend header. VMIE_DISASM={OFF|zydis|
capstone} gates the build: OFF (default) compiles only semsig_stub.c and
keeps the zero-dependency build (VMIE_HAVE_DISASM=0, packages unchanged).
The backend is brought from VMIE_DISASM_SRC or find_package - never
vendored. Adds the vmie_win32_func_semsig wrapper.
The CI deb job builds with the Zydis backend (libzydis-dev); the runtime
package dependency on libzydis is derived automatically by dpkg-shlibdeps.
This commit is contained in:
@@ -6,6 +6,7 @@
|
||||
#include "sigscan.h" /* mem_sub (pure matcher; engine may use it) */
|
||||
#include "win32.h" /* public surface: vmie_win32, section_desc, view_base */
|
||||
#include "x86dec.h" /* x86_decode / x86_branch_target (call-graph step) */
|
||||
#include "semsig.h" /* semsig_hash (generic; no backend header pulled here) */
|
||||
|
||||
/* IMAGE_SECTION_HEADER: 8-byte Name, then Misc.VirtualSize(+8), VirtualAddress
|
||||
* (+12), and Characteristics(+36); the header is 40 bytes wide. */
|
||||
@@ -775,3 +776,51 @@ int vmie_win32_func_imports(vmie_win32* v, uint64_t cr3, uint64_t module_base,
|
||||
free(fb);
|
||||
return total;
|
||||
}
|
||||
|
||||
/* Semantic hash of one function by func_rva: reuse the func_imports gather (find
|
||||
* the extent from .pdata, read the body), then delegate to the generic
|
||||
* semsig_hash over a SECTION_LOCAL view. No normalization/fold is duplicated
|
||||
* here, and no backend header is included - the feature is inherited via the
|
||||
* generic (a stub returning 0 in an OFF build). Cold: one-shot per function. */
|
||||
uint64_t vmie_win32_func_semsig(vmie_win32* v, uint64_t cr3,
|
||||
uint64_t module_base, uint32_t func_rva)
|
||||
__attribute__((cold));
|
||||
uint64_t vmie_win32_func_semsig(vmie_win32* v, uint64_t cr3,
|
||||
uint64_t module_base, uint32_t func_rva) {
|
||||
vmie_mem* m = vmie_win32_mem(v);
|
||||
if (!m) { return 0; }
|
||||
|
||||
/* locate the function's extent from .pdata (count then gather). */
|
||||
const int nfn = vmie_win32_functions(v, cr3, module_base, NULL, 0);
|
||||
if (nfn < 0) { return 0; }
|
||||
func_range stack_fr[256];
|
||||
func_range* fr = stack_fr;
|
||||
func_range* heap_fr = NULL;
|
||||
if (nfn > (int)(sizeof stack_fr / sizeof stack_fr[0])) {
|
||||
heap_fr = malloc((size_t)nfn * sizeof *heap_fr);
|
||||
if (!heap_fr) { return 0; }
|
||||
fr = heap_fr;
|
||||
}
|
||||
const int got = vmie_win32_functions(v, cr3, module_base, fr, nfn);
|
||||
if (got < 0) { free(heap_fr); return 0; }
|
||||
uint32_t fn_size = 0;
|
||||
for (int f = 0; f < got; f++) {
|
||||
if (fr[f].rva == func_rva) { fn_size = fr[f].size; break; }
|
||||
}
|
||||
free(heap_fr);
|
||||
if (fn_size == 0) { return 0; } /* not a known function start */
|
||||
|
||||
/* gather the body and view it SECTION_LOCAL (base_va = 0): semsig_hash is
|
||||
* position-independent, so the local base is enough for a stable value. */
|
||||
uint8_t* fb = malloc(fn_size);
|
||||
if (!fb) { return 0; }
|
||||
if (gva_read(m, cr3, module_base + func_rva, fb, fn_size)) {
|
||||
free(fb);
|
||||
return 0;
|
||||
}
|
||||
const mem_view_t view = { .data = fb, .size = fn_size, .base_va = 0 };
|
||||
const uint64_t h = semsig_hash(view);
|
||||
|
||||
free(fb);
|
||||
return h;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user