libmwemu 0.24.4

x86 32/64bits and system internals emulator, for securely emulating malware and other stuff.
Documentation
use crate::context::context32::Context32;
use crate::debug::console::Console;
use crate::emu;
use crate::windows::constants;
use crate::windows::structures;

pub(super) fn dispatch(api: &str, emu: &mut emu::Emu) -> bool {
    match api {
        "NtGetContextThread" => NtGetContextThread(emu),
        "RtlVectoredExceptionHandler" => RtlVectoredExceptionHandler(emu),
        "RtlExitUserThread" => RtlExitUserThread(emu),
        "NtGetTickCount" => NtGetTickCount(emu),
        "NtQueryPerformanceCounter" => NtQueryPerformanceCounter(emu),
        "RtlGetVersion" => RtlGetVersion(emu),
        "RtlSetUnhandledExceptionFilter" => RtlSetUnhandledExceptionFilter(emu),
        "VerSetConditionMask" => VerSetConditionMask(emu),
        _ => return false,
    }
    true
}

fn NtGetContextThread(emu: &mut emu::Emu) {
    let handle = emu
        .maps
        .read_dword(emu.regs().get_esp())
        .expect("ntdll_NtGetContextThread: error reading stack") as u64;
    let ctx_ptr = emu
        .maps
        .read_dword(emu.regs().get_esp() + 4)
        .expect("ntdll_NtGetContextThread: error reading context pointer") as u64;
    let ctx_ptr2 = emu
        .maps
        .read_dword(ctx_ptr)
        .expect("ntdll_NtGetContextThread: error reading context ptr") as u64;

    log_red!(emu, "ntdll_NtGetContextThread   ctx");

    let ctx = Context32::new(&emu.regs());
    ctx.save(ctx_ptr2 as u32, &mut emu.maps);

    emu.regs_mut().rax = 0;
    emu.stack_pop32(false);
    emu.stack_pop32(false);
}

fn RtlVectoredExceptionHandler(emu: &mut emu::Emu) {
    let p1 = emu
        .maps
        .read_dword(emu.regs().get_esp())
        .expect("ntdll_RtlVectoredExceptionHandler: error reading p1") as u64;
    let fptr = emu
        .maps
        .read_dword(emu.regs().get_esp() + 4)
        .expect("ntdll_RtlVectoredExceptionHandler: error reading fptr") as u64;

    log_red!(
        emu,
        "ntdll!RtlVectoredExceptionHandler  {} callback: 0x{:x}",
        p1,
        fptr
    );

    emu.set_veh(fptr);

    emu.regs_mut().rax = 0x2c2878;
    emu.stack_pop32(false);
    emu.stack_pop32(false);
}

fn RtlExitUserThread(emu: &mut emu::Emu) {
    log_red!(emu, "ntdll!RtlExitUserThread");
    Console::spawn_console(emu);
    emu.stop();
}

fn NtGetTickCount(emu: &mut emu::Emu) {
    log_red!(emu, "ntdll!NtGetTickCount");
    emu.regs_mut().rax = emu.tick as u64;
}

fn NtQueryPerformanceCounter(emu: &mut emu::Emu) {
    let perf_counter_ptr = emu
        .maps
        .read_dword(emu.regs().get_esp())
        .expect("ntdll!NtQueryPerformanceCounter error reading perf_counter_ptr")
        as u64;
    let perf_freq_ptr = emu
        .maps
        .read_dword(emu.regs().get_esp() + 4)
        .expect("ntdll!NtQueryPerformanceCounter error reading perf_freq_ptr") as u64;

    log_red!(emu, "ntdll!NtQueryPerformanceCounter");

    emu.maps.write_dword(perf_counter_ptr, 0);

    emu.stack_pop32(false);
    emu.stack_pop32(false);

    emu.regs_mut().rax = constants::STATUS_SUCCESS;
}

fn RtlGetVersion(emu: &mut emu::Emu) {
    let versioninfo_ptr = emu
        .maps
        .read_dword(emu.regs().get_esp())
        .expect("ntdll!RtlLeaveCriticalSection error reading versioninfo_ptr param")
        as u64;

    log_red!(emu, "ntdll!RtlGetVersion");

    let versioninfo = structures::OsVersionInfoExA::new();
    versioninfo.save(versioninfo_ptr, &mut emu.maps);

    emu.stack_pop32(false);
    emu.regs_mut().rax = 1;
}

fn RtlSetUnhandledExceptionFilter(emu: &mut emu::Emu) {
    let filter = emu
        .maps
        .read_dword(emu.regs().get_esp())
        .expect("ntdll!RtlSetUnhandledExceptionFilter error reading filter") as u64;

    log_red!(
        emu,
        "ntdll!RtlSetUnhandledExceptionFilter filter: 0x{:x}",
        filter
    );

    emu.set_uef(filter);
    emu.stack_pop32(false);
    emu.regs_mut().rax = 1;
}

fn VerSetConditionMask(emu: &mut emu::Emu) {
    log_red!(emu, "ntdll!VerSetConditionMask");

    emu.stack_pop32(false);
    emu.stack_pop32(false);
    emu.stack_pop32(false);
    emu.regs_mut().rax = 0xffff;
}