mirror of
https://dev.lirent.ru/Vatrog/vm-introspection-engine.git
synced 2026-06-18 04:16:39 +03:00
Windows guest VMI core: host library, CLI, guest agent
Static library over a flat RW mmap of guest RAM: GPA/GVA paging walks, beacon-driven bootstrap, dynamic struct-offset profiling, process and module enumeration, a region map, and value/pointer/signature scanners on a shared windowed sweep. Public API in include/; internals under src/. Thin CLI demonstrator over the public API. Guest agent cross-compiled to Windows x86-64 via mingw-w64. CMake: static library + CLI + guest target, C17.
This commit is contained in:
@@ -0,0 +1,105 @@
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/stat.h>
|
||||
#include "include/memory.h"
|
||||
|
||||
#define RAM_H (1ul<<32)
|
||||
#define PROT_RW (PROT_READ | PROT_WRITE)
|
||||
|
||||
__attribute__((hot))
|
||||
static int gpa_offset(const gpa_ctx* ctx, uintptr_t offs, uintptr_t* out) {
|
||||
if (offs < ctx->low) {
|
||||
*out = offs;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (offs >= RAM_H) {
|
||||
const uint64_t x = ctx->low + (offs - RAM_H);
|
||||
|
||||
if (x < ctx->fsize) {
|
||||
*out = x;
|
||||
return 0;
|
||||
} else { /* Out of bounds */ }
|
||||
} else { /* Not RAM */ }
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void clean_ctx(gpa_ctx* ctx) {
|
||||
memset(ctx, 0, sizeof(gpa_ctx));
|
||||
ctx->fd = -1;
|
||||
}
|
||||
|
||||
static int out_of_bounds(gpa_ctx* ctx, uintptr_t* offs, const size_t nmemb) {
|
||||
return gpa_offset(ctx, *offs, offs) || *offs + nmemb > ctx->fsize;
|
||||
}
|
||||
|
||||
__attribute__((hot))
|
||||
int gpa_read(gpa_ctx* ctx, uintptr_t offs, void* buf, const size_t nmemb) {
|
||||
if (out_of_bounds(ctx, &offs, nmemb)) {
|
||||
return -1;
|
||||
}
|
||||
memcpy(buf, ctx->pa + offs, nmemb);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int gpa_write(gpa_ctx* ctx, uintptr_t offs, const void* src, const size_t nmemb) {
|
||||
if (out_of_bounds(ctx, &offs, nmemb)) {
|
||||
return -1;
|
||||
}
|
||||
memcpy(ctx->pa + offs, src, nmemb);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Zero-copy host pointer to [offs, offs+nmemb) GPA, or NULL if that range is not
|
||||
* fully backed by the mapped image. Same split + bounds check as gpa_read. */
|
||||
void* gpa_ptr(gpa_ctx* ctx, uintptr_t offs, const size_t nmemb) {
|
||||
if (out_of_bounds(ctx, &offs, nmemb)) {
|
||||
return NULL;
|
||||
}
|
||||
return (uint8_t*)ctx->pa + offs;
|
||||
}
|
||||
|
||||
__attribute__((cold))
|
||||
int gpa_open(gpa_ctx* ctx, const char* path, uintptr_t low) {
|
||||
struct stat st;
|
||||
|
||||
if ((ctx->fd = open(path, O_RDWR)) < 0) {
|
||||
goto ret_;
|
||||
}
|
||||
|
||||
if (fstat(ctx->fd, &st)) {
|
||||
goto close_;
|
||||
}
|
||||
|
||||
if ((ctx->pa = mmap(NULL, st.st_size, PROT_RW, MAP_SHARED, ctx->fd, 0)) == MAP_FAILED) {
|
||||
close_:
|
||||
close(ctx->fd);
|
||||
ret_:
|
||||
clean_ctx(ctx);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ctx->fsize = st.st_size;
|
||||
ctx->low = low;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
__attribute__((cold))
|
||||
void gpa_close(gpa_ctx* ctx) {
|
||||
if (ctx->pa) {
|
||||
munmap(ctx->pa, ctx->fsize);
|
||||
}
|
||||
|
||||
if (ctx->fd >= 0) {
|
||||
close(ctx->fd);
|
||||
}
|
||||
|
||||
clean_ctx(ctx);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user