Skip to content

Commit

Permalink
Merge pull request #111 from tklengyel/process_traps
Browse files Browse the repository at this point in the history
Add support for trapping processes to libdrakvuf
  • Loading branch information
tklengyel committed Mar 30, 2016
2 parents e17f8d3 + 68dfc6d commit c8f5960
Show file tree
Hide file tree
Showing 10 changed files with 199 additions and 162 deletions.
1 change: 1 addition & 0 deletions src/injector.c
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <libvmi/libvmi.h>

#include "libdrakvuf/libdrakvuf.h"
Expand Down
121 changes: 42 additions & 79 deletions src/libdrakvuf/drakvuf.c
Original file line number Diff line number Diff line change
Expand Up @@ -179,92 +179,62 @@ bool drakvuf_add_trap(drakvuf_t drakvuf, drakvuf_trap_t *trap) {
goto done;
}

if(trap->lookup_type == LOOKUP_PID && trap->u.pid == 4) {
if (trap->module) {
vmi_instance_t vmi = drakvuf->vmi;

// Loop kernel modules
addr_t kernel_list_head;
vmi_read_addr_ksym(vmi, "PsLoadedModuleList", &kernel_list_head);
ret = inject_traps_modules(drakvuf, NULL, trap, kernel_list_head, 4, "System");
}

goto done;
}
} else {
ret = inject_trap_mem(drakvuf, trap);
}
if(trap->lookup_type == LOOKUP_PID || trap->lookup_type == LOOKUP_NAME) {
if (trap->addr_type == ADDR_RVA && trap->module) {

done:
vmi_resume_vm(drakvuf->vmi);
return ret;
}
vmi_pid_t pid = ~0;
const char *name = NULL;
addr_t module_list = 0;

bool drakvuf_add_traps(drakvuf_t drakvuf, GSList *traps) {
bool ret = 0;
addr_t kernel_list_head;
vmi_instance_t vmi = drakvuf->vmi;
vmi_pause_vm(vmi);

// Loop kernel modules
vmi_read_addr_ksym(vmi, "PsLoadedModuleList", &kernel_list_head);
ret = inject_traps_modules(drakvuf, traps, NULL, kernel_list_head, 4, "System");

// TODO TODO TODO
/*addr_t current_process = 0, next_list_entry = 0;
vmi_read_addr_ksym(vmi, "PsInitialSystemProcess", &current_process);
addr_t list_head = current_process + offsets[EPROCESS_TASKS];
addr_t current_list_entry = list_head;
status_t status = vmi_read_addr_va(vmi, current_list_entry, 0,
&next_list_entry);
if (status == VMI_FAILURE) {
PRINT_DEBUG(
"Failed to read next pointer at 0x%"PRIx64" before entering loop\n",
current_list_entry);
return;
}
if(trap->u.pid == 4 || !strcmp(trap->u.proc, "System")) {
pid = 4;
name = "System";

do {
if(VMI_FAILURE == vmi_read_addr_ksym(drakvuf->vmi, "PsLoadedModuleList", &module_list))
goto done;
} else {
/* Process library */
addr_t process_base;

vmi_pid_t pid;
uint32_t dtb;
vmi_read_32_va(vmi, current_process + offsets[EPROCESS_PID], 0, (uint32_t*)&pid);
vmi_read_32_va(vmi, current_process + offsets[EPROCESS_PDBASE], 0, &dtb);
if(trap->lookup_type == LOOKUP_PID)
pid = trap->u.pid;
if(trap->lookup_type == LOOKUP_NAME)
name = trap->u.proc;

char *procname = vmi_read_str_va(vmi, current_process + offsets[EPROCESS_PNAME], 0);
if( !drakvuf_find_eprocess(drakvuf, pid, name, &process_base) )
goto done;

if (!procname) {
goto exit;
}
if(pid == ~0 && VMI_FAILURE == vmi_read_32_va(drakvuf->vmi, process_base + offsets[EPROCESS_PID], 0, (uint32_t*)&pid))
goto done;

PRINT(drakvuf, FOUND_PROCESS_STRING, pid, dtb, procname);
if( !drakvuf_get_module_list(drakvuf, process_base, &module_list) )
goto done;
}

free(procname);
ret = inject_traps_modules(drakvuf, trap, module_list, pid);
}

addr_t imagebase = 0, peb = 0, ldr = 0, modlist = 0;
vmi_read_addr_va(vmi, current_process + offsets[EPROCESS_PEB], 0, &peb);
vmi_read_addr_va(vmi, peb + offsets[PEB_IMAGEBASADDRESS], pid,
&imagebase);
vmi_read_addr_va(vmi, peb + offsets[PEB_LDR], pid, &ldr);
vmi_read_addr_va(vmi, ldr + offsets[PEB_LDR_DATA_INLOADORDERMODULELIST],
pid, &modlist);
if(trap->addr_type == ADDR_VA) {
addr_t dtb = vmi_pid_to_dtb(drakvuf->vmi, trap->u.pid);
if(!dtb)
goto done;

inject_traps_pe(drakvuf, traps, imagebase, pid, NULL);
inject_traps_modules(drakvuf, traps, modlist, pid);
addr_t trap_pa = vmi_pagetable_lookup(drakvuf->vmi, dtb, trap->u2.addr);
if(!trap_pa)
goto done;

current_list_entry = next_list_entry;
current_process = current_list_entry - offsets[EPROCESS_TASKS];
ret = inject_trap_pa(drakvuf, trap, trap_pa);
goto done;
}

status = vmi_read_addr_va(vmi, current_list_entry, 0, &next_list_entry);
if (status == VMI_FAILURE) {
PRINT_DEBUG("Failed to read next pointer in loop at %"PRIx64"\n",
current_list_entry);
return;
if(trap->addr_type == ADDR_PA) {
fprintf(stderr, "DRAKVUF Trap misconfiguration: PID lookup specified for PA location\n");
}
}

} while (next_list_entry != list_head);*/
} else {
ret = inject_trap_mem(drakvuf, trap);
}

done:
vmi_resume_vm(drakvuf->vmi);
Expand Down Expand Up @@ -295,13 +265,6 @@ void drakvuf_remove_trap(drakvuf_t drakvuf, drakvuf_trap_t *trap,
}
}

void drakvuf_remove_traps(drakvuf_t drakvuf, GSList *traps) {
while (traps) {
remove_trap(drakvuf, traps->data);
traps = traps->next;
}
}

vmi_instance_t drakvuf_lock_and_get_vmi(drakvuf_t drakvuf) {
g_mutex_lock(&drakvuf->vmi_lock);
return drakvuf->vmi;
Expand Down
30 changes: 28 additions & 2 deletions src/libdrakvuf/injector.c
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,6 @@ struct injector {
page_mode_t pm;

addr_t process_info;

addr_t saved_rsp;
addr_t saved_rip;
addr_t saved_rax;
Expand Down Expand Up @@ -827,8 +826,15 @@ event_response_t cr3_callback(vmi_instance_t vmi, vmi_event_t *event) {
return 0;
}

event_response_t injector_int3_cb(vmi_instance_t vmi, vmi_event_t *event) {

event_response_t singlestep_cb(vmi_instance_t vmi, vmi_event_t *event) {
addr_t *pa = event->data;
vmi_write_8_pa(vmi, *pa, &trap);
free(pa);
return 1u<<VMI_EVENT_RESPONSE_TOGGLE_SINGLESTEP;
}

event_response_t injector_int3_cb(vmi_instance_t vmi, vmi_event_t *event) {
vmi_pause_vm(vmi);

struct injector *injector = event->data;
Expand All @@ -845,6 +851,24 @@ event_response_t injector_int3_cb(vmi_instance_t vmi, vmi_event_t *event) {
PRINT_DEBUG("INT3 Callback @ 0x%lx. PID %u. CR3 0x%lx\n",
event->interrupt_event.gla, pid, cr3);

if ( cr3 != injector->target_cr3 ) {
PRINT_DEBUG("Stepping INT3 as CR3 doesn't match target process\n");

if ( event->interrupt_event.gla == injector->entry )
vmi_write_8_pa(vmi, pa, &injector->entry_backup);
else if ( event->interrupt_event.gla == injector->ret )
vmi_write_8_pa(vmi, pa, &injector->ret_backup);
else
goto notmine;

injector->drakvuf->step_event[event->vcpu_id]->callback = singlestep_cb;
injector->drakvuf->step_event[event->vcpu_id]->data = g_memdup(&pa, sizeof(addr_t));
event->interrupt_event.reinject = 0;
vmi_resume_vm(vmi);

return 1u<<VMI_EVENT_RESPONSE_TOGGLE_SINGLESTEP;
}

if ( event->interrupt_event.gla == injector->entry ) {

if (PM2BIT(injector->pm) == BIT64) {
Expand All @@ -870,6 +894,8 @@ event_response_t injector_int3_cb(vmi_instance_t vmi, vmi_event_t *event) {
ctx.addr = injector->ret;
vmi_write_8(vmi, &ctx, &trap);

PRINT_DEBUG("Stack setup finished and return trap added @ 0x%" PRIx64 "\n", injector->ret);

event->interrupt_event.reinject = 0;
vmi_resume_vm(vmi);
return 0;
Expand Down
57 changes: 30 additions & 27 deletions src/libdrakvuf/libdrakvuf.h
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,6 @@ extern "C" {

#pragma GCC visibility push(default)

#include <glib.h>
#include <libvmi/libvmi.h>
#include <libvmi/events.h>

Expand Down Expand Up @@ -245,13 +244,9 @@ bool drakvuf_init (drakvuf_t *drakvuf,
void drakvuf_close (drakvuf_t drakvuf);
bool drakvuf_add_trap(drakvuf_t drakvuf,
drakvuf_trap_t *trap);
bool drakvuf_add_traps(drakvuf_t drakvuf,
GSList *traps);
void drakvuf_remove_trap (drakvuf_t drakvuf,
drakvuf_trap_t *trap,
void(*free_routine)(drakvuf_trap_t *trap));
void drakvuf_remove_traps(drakvuf_t drakvuf,
GSList *traps);
void drakvuf_loop (drakvuf_t drakvuf);
void drakvuf_interrupt (drakvuf_t drakvuf,
int sig);
Expand Down Expand Up @@ -287,37 +282,45 @@ char *drakvuf_get_current_process_name(drakvuf_t drakvuf,
uint64_t vcpu_id,
x86_registers_t *regs);


bool drakvuf_get_current_thread_id( drakvuf_t drakvuf,
uint64_t vcpu_id,
bool drakvuf_get_current_thread_id(drakvuf_t drakvuf,
uint64_t vcpu_id,
x86_registers_t *regs,
uint32_t *thread_id );
uint32_t *thread_id);

// Microsoft PreviousMode KTHREAD explanation:
// https://msdn.microsoft.com/en-us/library/windows/hardware/ff559860(v=vs.85).aspx
bool drakvuf_get_current_thread_previous_mode( drakvuf_t drakvuf,
drakvuf_trap_info_t *info,
privilege_mode_t *previous_mode );
bool drakvuf_get_current_thread_previous_mode(drakvuf_t drakvuf,
drakvuf_trap_info_t *info,
privilege_mode_t *previous_mode);

bool drakvuf_get_thread_previous_mode(drakvuf_t drakvuf,
addr_t kthread,
privilege_mode_t *previous_mode);

bool drakvuf_is_ethread(drakvuf_t drakvuf,
drakvuf_trap_info_t *info,
addr_t ethread_addr);

bool drakvuf_get_thread_previous_mode( drakvuf_t drakvuf,
addr_t kthread,
privilege_mode_t *previous_mode );
bool drakvuf_is_eprocess(drakvuf_t drakvuf,
drakvuf_trap_info_t *info,
addr_t eprocess_addr);

bool drakvuf_is_ethread( drakvuf_t drakvuf,
drakvuf_trap_info_t *info,
addr_t ethread_addr );
bool drakvuf_find_eprocess(drakvuf_t drakvuf,
vmi_pid_t find_pid,
const char *find_procname,
addr_t *eprocess_addr);

bool drakvuf_is_eprocess( drakvuf_t drakvuf,
drakvuf_trap_info_t *info,
addr_t eprocess_addr );
bool drakvuf_get_module_list(drakvuf_t drakvuf,
addr_t eprocess_base,
addr_t *module_list);

// ObReferenceObjectByHandle
bool drakvuf_obj_ref_by_handle( drakvuf_t drakvuf,
drakvuf_trap_info_t *info,
addr_t current_eprocess,
addr_t handle,
object_manager_object_t obj_type_arg,
addr_t *obj_body_addr );
bool drakvuf_obj_ref_by_handle(drakvuf_t drakvuf,
drakvuf_trap_info_t *info,
addr_t current_eprocess,
addr_t handle,
object_manager_object_t obj_type_arg,
addr_t *obj_body_addr);

#pragma GCC visibility pop

Expand Down
2 changes: 1 addition & 1 deletion src/libdrakvuf/private.h
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@
#include <config.h>
#include <stdio.h>
#include <stdlib.h>

#include <inttypes.h>
#include <glib.h>
#include <libvmi/libvmi.h>
#include <libvmi/events.h>
Expand Down
Loading

0 comments on commit c8f5960

Please sign in to comment.