typedef enum lookup_type
{
 
    __INVALID_LOOKUP_TYPE,
    LOOKUP_NONE,
    LOOKUP_DTB,
    LOOKUP_PID,
    LOOKUP_NAME,
    LOOKUP_KERNEL,
 
} lookup_type_t;
 
struct drakvuf_trap
{
    trap_type_t type;
    event_response_t (*cb)(drakvuf_t, drakvuf_trap_info_t*);
    void* data;
 
    union
    {
        const char* name; // Only used for informational/debugging purposes
        void* _name;
    };
 
    union
    {
        struct
        {
            lookup_type_t lookup_type;
            union
            {
                vmi_pid_t pid;
                const char* proc;
                addr_t dtb;
            };
 
            /* If specified and RVA is used
               RVA will be calculated from the base
               of this module */
            const char* module;
 
            addr_type_t addr_type;
            union
            {
                addr_t rva;
                addr_t addr;
                const char* symbol;
            };
        } breakpoint;
 
        struct
        {
            addr_t gfn;
            vmi_mem_access_t access;
            memaccess_type_t type;
        } memaccess;
 
        register_t reg;
    };
 
    // How many times trap can be hit in TRAP_TTL_RESET_INTERVAL_SEC interval,
    // before it gets discarded. Protects against api-hammering.
    // 0 for infinity.
    uint64_t ttl;
    time_t last_ttl_rst;
    // Callback invoked when the trap hits api-hammering limit. If not set (NULL),
    // the trap will be simply unhooked (not deleted).
    void(*ah_cb)(drakvuf_t, drakvuf_trap_t*);
};
static bool inject_trap_breakpoint(drakvuf_t drakvuf, drakvuf_trap_t* trap)
{
    if (trap->breakpoint.lookup_type == LOOKUP_NONE)
    {
        return inject_trap_pa(drakvuf, trap, trap->breakpoint.addr);
    }
 
    if ( trap->breakpoint.lookup_type == LOOKUP_KERNEL )
    {
        addr_t pa;
        addr_t va = 0;
 
        if ( trap->breakpoint.addr_type == ADDR_RVA )
            va = drakvuf->kernbase + trap->breakpoint.rva;
        else if ( trap->breakpoint.addr_type == ADDR_VA )
            va = trap->breakpoint.addr;
        else if ( trap->breakpoint.addr_type == ADDR_SYMBOL )
        {
            if ( !drakvuf_get_kernel_symbol_rva(drakvuf, trap->breakpoint.symbol, &va) )
                return 0;
            va += drakvuf->kernbase;
        }
 
        if ( !va )
        {
            PRINT_DEBUG("Invalid setting when using LOOKUP_KERNEL trap type, needs ADDR_RVA or ADDR_VA\n");
            return 0;
        }
 
        if ( VMI_FAILURE == vmi_pagetable_lookup(drakvuf->vmi, drakvuf->kpgd, va, &pa) )
        {
            PRINT_DEBUG("Failed to find PA for breakpoint VA addr 0x%lx in the kernel using kpgd 0x%lx\n", va, drakvuf->kpgd);
            return 0;
        }
 
        return inject_trap_pa(drakvuf, trap, pa);
    }
 
    if (trap->breakpoint.lookup_type == LOOKUP_PID || trap->breakpoint.lookup_type == LOOKUP_NAME)
    {
        if (trap->breakpoint.addr_type == ADDR_RVA && trap->breakpoint.module)
        {
 
            vmi_pid_t pid = -1;
            const char* name = NULL;
            addr_t module_list = 0;
 
            if (VMI_OS_WINDOWS == drakvuf->os && (trap->breakpoint.pid == 0 || trap->breakpoint.pid == 4 || !strcmp(trap->breakpoint.proc, "System")))
            {
 
                pid = 0;
                if (VMI_FAILURE == vmi_read_addr_ksym(drakvuf->vmi, "PsLoadedModuleList", &module_list))
                    return 0;
 
            }
            else
            {
 
                /* Process library */
                addr_t process_base;
 
                if (trap->breakpoint.lookup_type == LOOKUP_PID)
                    pid = trap->breakpoint.pid;
                if (trap->breakpoint.lookup_type == LOOKUP_NAME)
                    name = trap->breakpoint.proc;
 
                if ( !drakvuf_find_process(drakvuf, pid, name, &process_base) )
                    return 0;
 
                if ( pid == -1 && !drakvuf_get_process_pid(drakvuf, process_base, &pid) )
                    return 0;
 
                if ( !drakvuf_get_module_list(drakvuf, process_base, &module_list) )
                    return 0;
            }
 
            return inject_traps_modules(drakvuf, trap, module_list, pid);
        }
 
        if (trap->breakpoint.addr_type == ADDR_VA)
        {
            addr_t dtb;
            addr_t trap_pa;
            if ( VMI_FAILURE == vmi_pid_to_dtb(drakvuf->vmi, trap->breakpoint.pid, &dtb) )
            {
                PRINT_DEBUG("No DTB found for pid %i\n", trap->breakpoint.pid);
                return 0;
            }
 
            if ( VMI_FAILURE == vmi_pagetable_lookup(drakvuf->vmi, dtb, trap->breakpoint.addr, &trap_pa) )
            {
                PRINT_DEBUG("Failed to find PA for breakpoint VA addr 0x%lx in DTB 0x%lx\n", trap->breakpoint.addr, dtb);
                return 0;
            }
 
            return inject_trap_pa(drakvuf, trap, trap_pa);
        }
 
        if (trap->breakpoint.addr_type == ADDR_PA)
        {
            fprintf(stderr, "DRAKVUF Trap misconfiguration: PID lookup specified for PA location\n");
            return 0;
        }
    }
 
    if (trap->breakpoint.lookup_type == LOOKUP_DTB)
    {
        if (trap->breakpoint.addr_type == ADDR_VA)
        {
            addr_t trap_pa;
            if ( VMI_FAILURE == vmi_pagetable_lookup(drakvuf->vmi, trap->breakpoint.dtb, trap->breakpoint.addr, &trap_pa) )
            {
                PRINT_DEBUG("Breakpoint VA 0x%" PRIx64" not found in pagetable at 0x%" PRIx64 "\n", trap->breakpoint.addr, trap->breakpoint.dtb);
                return 0;
            }
 
            PRINT_DEBUG("Breakpoint VA 0x%" PRIx64" -> PA 0x%" PRIx64 "\n", trap->breakpoint.addr, trap_pa);
 
            return inject_trap_pa(drakvuf, trap, trap_pa);
        }
 
        //TODO: ADDR_RVA
    }
 
    return 0;
}

inject_trap_pa

vmi_pagetable_lookup

vmi_pid_to_dtb

inject_traps_modules


🌱 Back to Garden

4 items under this folder.