/* siggen.h - x86-64 code signature generator (pure handler). * * Turns a span of code into a UNIQUE masked byte signature suitable for the * sigscan matcher: opcode/ModRM/fixed bytes are must-match; the rel/RIP-relative * displacement bytes - the ones that "float" with the load address and with * relocation - are wildcarded. The result is the dual of sigscan: feed its * output back into sig_all/sig_first to relocate the same code in another image. * * Pure: it depends only on sigscan.h (the pattern + view types and the matcher) * and x86dec.h (the length decoder that locates the displacement field). It * touches no vmie_mem and does no I/O; build a view (e.g. a section view) and * pass it in. */ #ifndef VMIE_SIGGEN_H #define VMIE_SIGGEN_H #include #include "sigscan.h" /* sig_pattern_t, mem_view_t, sig_all, sig_free */ #include "x86dec.h" /* x86_decode + x86_insn.disp_off/disp_len */ /* Build a unique masked signature for the code starting at scope.data[start_off]. * Steps instructions with x86_decode; each instruction contributes its * opcode/ModRM/fixed bytes as must-match (mask x) and its rel/RIP-relative * displacement bytes (disp_off..disp_off+disp_len) as wildcards (mask ?), since * those move with load address / relocation. Grows instruction by instruction * until the pattern occurs EXACTLY ONCE in `scope` (verified with sig_all) or * `max_len` bytes are consumed. * scope - search space the signature must be unique within (e.g. a .text * section view). The coordinate of uniqueness is scope's own (use * a MODULE_RVA / SECTION_LOCAL view for an ASLR-stable result * origin). * start_off - byte offset in `scope` where the target code begins (must be < * scope.size). * max_len - cap on signature length in bytes (e.g. 64); guards against * non-unique code. * out - on success, the generated pattern (free with sig_free()). * Returns the pattern length in bytes on success, 0 if it cannot be made unique * within max_len, -1 on bad input. The result matches `scope` exactly once, at * start_off. * * v1 wildcards ONLY rel/RIP-relative displacements (the dominant floating bytes); * absolute immediate relocations are NOT auto-wildcarded (a .reloc cross-check is * a future extension). * * Example - generate a portable signature for a function in .text (MODULE_RVA * view => an ASLR-stable origin), then relocate it elsewhere: * sig_pattern_t p; * int len = sig_generate(text_view, fn_rva - text_view.base_va, 64, &p); * if (len > 0) { * uint64_t rva = sig_first(other_text_view, &p); // re-find the function * sig_free(&p); * } */ int sig_generate(mem_view_t scope, size_t start_off, size_t max_len, sig_pattern_t* out); #endif /* VMIE_SIGGEN_H */