dyncvoke-core 0.1.0

PEB walking, dynamic invoke, and Tartarus Gate indirect syscalls for Dyncvoke
// Phase 3 acceptance — Hell's Hall variadic do_syscall works end-to-end.

use dyncvoke_core::{do_syscall, resolve_syscall};
use std::ffi::c_void;

#[test]
fn do_syscall_nt_close_garbage_handle_returns_invalid_handle_status() {
    let (ssn, addr) = resolve_syscall("NtClose").expect("resolve NtClose");
    // 0xDEADBEEF is not a kernel handle. NtClose must reject it with
    // STATUS_INVALID_HANDLE = 0xC0000008.
    let status = unsafe {
        do_syscall(ssn, addr, 1, 0xDEADBEEFusize as *mut c_void)
    } as i32;
    assert_eq!(
        status as u32, 0xC0000008,
        "expected STATUS_INVALID_HANDLE, got 0x{:08X}",
        status as u32
    );
}

#[test]
fn do_syscall_nt_allocate_six_args() {
    let (ssn, addr) = resolve_syscall("NtAllocateVirtualMemory").expect("resolve");
    let mut base: *mut c_void = std::ptr::null_mut();
    let mut size: usize = 0x1000;
    let status = unsafe {
        do_syscall(
            ssn,
            addr,
            6,
            -1isize as *mut c_void,                          // process handle
            &mut base as *mut *mut c_void as *mut c_void,    // base address out
            0usize as *mut c_void,                           // zero bits
            &mut size as *mut usize as *mut c_void,          // size in/out
            0x3000u32 as usize as *mut c_void,               // MEM_COMMIT|MEM_RESERVE
            0x04u32 as usize as *mut c_void,                 // PAGE_READWRITE
        )
    } as i32;
    assert_eq!(status, 0, "NtAllocateVirtualMemory NTSTATUS=0x{:08X}", status as u32);
    assert!(!base.is_null());

    // Touch the page to confirm it's mapped and writable.
    unsafe { *(base as *mut u8) = 0x42; }

    // Free it back.
    let (free_ssn, free_addr) = resolve_syscall("NtFreeVirtualMemory").expect("resolve free");
    let mut free_size: usize = 0;
    let status = unsafe {
        do_syscall(
            free_ssn,
            free_addr,
            4,
            -1isize as *mut c_void,
            &mut base as *mut *mut c_void as *mut c_void,
            &mut free_size as *mut usize as *mut c_void,
            0x8000u32 as usize as *mut c_void, // MEM_RELEASE
        )
    } as i32;
    assert_eq!(status, 0, "NtFreeVirtualMemory NTSTATUS=0x{:08X}", status as u32);
}