warlocks-stave/demo.c

102 lines
3.9 KiB
C

/*
* Warlock's Stave — Quick FFI Demo Harness
*
* Compile: gcc -o demo demo.c -ldl -Wl,-rpath,./target/release
* Run: LD_LIBRARY_PATH=./target/release ./demo
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dlfcn.h>
/* Mirrors the 4 C-FFI functions from libstave_core.so */
typedef void* (*init_fn)(void);
typedef const char* (*ingest_fn)(void*, const unsigned char*, size_t, unsigned long, unsigned int);
typedef void (*free_str_fn)(const char*);
typedef void (*destroy_fn)(void*);
int main(void) {
printf("=== Warlock's Stave FFI Demo ===\n\n");
/* --- Load the shared library --- */
void *lib = dlopen("./target/release/libstave_core.so", RTLD_NOW);
if (!lib) {
fprintf(stderr, "dlopen failed: %s\n", dlerror());
fprintf(stderr, "Run ./build.sh first, then use:\n");
fprintf(stderr, " LD_LIBRARY_PATH=./target/release ./demo\n");
return 1;
}
init_fn init = (init_fn) dlsym(lib, "initialize_warlock_stave");
ingest_fn ingest = (ingest_fn) dlsym(lib, "stave_ingest_frame");
free_str_fn freestr = (free_str_fn)dlsym(lib, "free_stave_string");
destroy_fn destroy = (destroy_fn) dlsym(lib, "destroy_warlock_stave");
if (!init || !ingest || !freestr || !destroy) {
fprintf(stderr, "dlsym failed: %s\n", dlerror());
dlclose(lib);
return 1;
}
/* --- Initialize the engine --- */
void *ctx = init();
printf("[Engine] Context created: %p\n\n", ctx);
/*
* Feed a realistic x86-64 sequence.
* Each frame: (bytes, length, RIP, EFLAGS)
*
* Instructions:
* 0x7FF0: 48 31 C0 xor rax, rax
* 0x7FF3: 48 89 C3 mov rbx, rax
* 0x7FF6: 0F 84 10 00 00 00 je +0x10 (conditional — ZF=1 in EFLAGS)
* 0x7FFC: E9 05 00 00 00 jmp +0x5 (unconditional)
* 0x8001: 48 83 C4 28 add rsp, 0x28
*/
struct { unsigned char *bytes; size_t len; unsigned long rip; unsigned int eflags; } frames[] = {
{ (unsigned char[]){ 0x48, 0x31, 0xC0 }, 3, 0x7FF0, 0x202 }, /* ZF=1 */
{ (unsigned char[]){ 0x48, 0x89, 0xC3 }, 3, 0x7FF3, 0x202 },
{ (unsigned char[]){ 0x0F, 0x84, 0x10, 0x00, 0x00, 0x00 }, 6, 0x7FF6, 0x246 }, /* ZF=1, SF=1 */
{ (unsigned char[]){ 0xE9, 0x05, 0x00, 0x00, 0x00 }, 5, 0x7FFC, 0x246 },
{ (unsigned char[]){ 0x48, 0x83, 0xC4, 0x28 }, 4, 0x8001, 0x246 },
};
int n = sizeof(frames) / sizeof(frames[0]);
for (int i = 0; i < n; i++) {
const char *json = ingest(ctx, frames[i].bytes, frames[i].len,
frames[i].rip, frames[i].eflags);
printf("[Frame %d] RIP=0x%04lX bytes=%zu EFLAGS=0x%X\n",
i+1, frames[i].rip, frames[i].len, frames[i].eflags);
printf(" %s\n\n", json);
freestr(json);
}
/* --- Telemetry round-trip: hit the same cell twice --- */
printf("[Frame 6] Re-visiting RIP=0x7FF0 (heatmap intensity should increase)...\n");
const char *json = ingest(ctx,
(unsigned char[]){ 0x48, 0x31, 0xC0 }, 3, 0x7FF0, 0x202);
printf(" %s\n\n", json);
freestr(json);
/* --- Conditional branch with ZF=0 (not-taken path) --- */
printf("[Frame 7] je with ZF=0 (should report ConditionNotMet)...\n");
json = ingest(ctx,
(unsigned char[]){ 0x0F, 0x84, 0x10, 0x00, 0x00, 0x00 }, 6, 0x7FF6, 0x242);
printf(" %s\n\n", json);
freestr(json);
/* --- Dictionary scan: URL pattern in bytes --- */
printf("[Frame 8] Bytes containing 'http://' (dictionary hit expected)...\n");
json = ingest(ctx,
(unsigned char[]){ 0x68, 0x74, 0x74, 0x70, 0x3A, 0x2F, 0x2F }, 7, 0x9000, 0x246);
printf(" %s\n\n", json);
freestr(json);
/* --- Cleanup --- */
destroy(ctx);
dlclose(lib);
printf("=== Done. ===\n");
return 0;
}