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;}