addr_t drakvuf_get_current_thread(drakvuf_t drakvuf, uint64_t vcpu_id, x86_registers_t *regs){ vmi_instance_t vmi = drakvuf->vmi; addr_t thread; addr_t prcb; reg_t fsgs; /* * fs_base/gs_base in the info->regs structure are not actually filled in * by Xen for vm_events, so we need to manually ask for these each time */ if(vmi_get_page_mode(vmi) == VMI_PM_IA32E) { if (!regs->gs_base) vmi_get_vcpureg(vmi, &fsgs, GS_BASE, vcpu_id); else fsgs = regs->gs_base; prcb=offsets[KPCR_PRCB]; } else { if (!regs->fs_base) vmi_get_vcpureg(vmi, &fsgs, FS_BASE, vcpu_id); else fsgs = regs->fs_base; prcb=offsets[KPCR_PRCBDATA]; } if (VMI_SUCCESS != vmi_read_addr_va(vmi, fsgs + prcb + offsets[KPRCB_CURRENTTHREAD], 0, &thread)){ return 0; } return thread; }
void ss_callback(vmi_instance_t vmi, vmi_event_t *event) { reg_t rip, cr3; vmi_get_vcpureg(vmi, &rip, RIP, event->vcpu_id); vmi_get_vcpureg(vmi, &cr3, CR3, event->vcpu_id); page_mode_t pm = vmi_get_page_mode(vmi); vmi_pid_t pid = vmi_dtb_to_pid(vmi, cr3); printf("----- Singlestep: CR3 0x%lx PID %u executing RIP 0x%lx\n", cr3, pid, rip); if ((PM2BIT(pm) == BIT32 && rip < KERNEL32) || (PM2BIT(pm) == BIT64 && rip < KERNEL64)) { printf("Good RIP: 0x%lx\n", rip); struct injector *injector = event->data; injector->ss_enabled = 0; injector->target_pid = pid; injector->target_rip = vmi_pagetable_lookup(vmi, cr3, rip); hijack_thread(injector, vmi, event->vcpu_id, pid); vmi_clear_event(vmi, event); vmi_clear_event(vmi, &injector->cr3_event); injector->mm_count++; uint8_t trap = 0xCC; vmi_read_8_pa(vmi, injector->target_rip, &injector->backup); vmi_write_8_pa(vmi, injector->target_rip, &trap); } }
addr_t drakvuf_get_kernel_base(drakvuf_t drakvuf) { reg_t fsgs; if(vmi_get_page_mode(drakvuf->vmi) == VMI_PM_IA32E) { vmi_get_vcpureg(drakvuf->vmi, &fsgs, GS_BASE, 0); } else { vmi_get_vcpureg(drakvuf->vmi, &fsgs, FS_BASE, 0); } return fsgs - drakvuf->offsets[KIINITIALPCR]; }
unicode_string_t * windows_read_unicode_struct( vmi_instance_t vmi, const access_context_t *ctx) { access_context_t _ctx = *ctx; unicode_string_t *us = 0; // return val size_t struct_size = 0; size_t read = 0; addr_t buffer_va = 0; uint16_t buffer_len = 0; if (VMI_PM_IA32E == vmi_get_page_mode(vmi)) { // 64 bit guest win64_unicode_string_t us64 = { 0 }; struct_size = sizeof(us64); // read the UNICODE_STRING struct read = vmi_read(vmi, ctx, &us64, struct_size); if (read != struct_size) { dbprint(VMI_DEBUG_READ, "--%s: failed to read UNICODE_STRING\n",__FUNCTION__); goto out_error; } // if buffer_va = us64.pBuffer; buffer_len = us64.length; } else { win32_unicode_string_t us32 = { 0 }; struct_size = sizeof(us32); // read the UNICODE_STRING struct read = vmi_read(vmi, ctx, &us32, struct_size); if (read != struct_size) { dbprint(VMI_DEBUG_READ, "--%s: failed to read UNICODE_STRING\n",__FUNCTION__); goto out_error; } // if buffer_va = us32.pBuffer; buffer_len = us32.length; } // if-else // allocate the return value us = safe_malloc(sizeof(unicode_string_t)); us->length = buffer_len; us->contents = safe_malloc(sizeof(uint8_t) * (buffer_len + 2)); _ctx.addr = buffer_va; read = vmi_read(vmi, &_ctx, us->contents, us->length); if (read != us->length) { dbprint (VMI_DEBUG_READ, "--%s: failed to read UNICODE_STRING buffer\n",__FUNCTION__); goto out_error; } // if // end with NULL (needed?) us->contents[buffer_len] = 0; us->contents[buffer_len + 1] = 0; us->encoding = "UTF-16"; return us; out_error: if (us) { if (us->contents) { free(us->contents); } free(us); } return 0; }
int main( int argc, char **argv) { vmi_instance_t vmi; uint32_t offset; addr_t next_module, list_head; /* this is the VM or file that we are looking at */ char *name = argv[1]; /* initialize the libvmi library */ if (vmi_init(&vmi, VMI_AUTO | VMI_INIT_COMPLETE, name) == VMI_FAILURE) { printf("Failed to init LibVMI library.\n"); return 1; } /* pause the vm for consistent memory access */ vmi_pause_vm(vmi); /* get the head of the module list */ if (VMI_OS_LINUX == vmi_get_ostype(vmi)) { vmi_read_addr_ksym(vmi, "modules", &next_module); } else if (VMI_OS_WINDOWS == vmi_get_ostype(vmi)) { vmi_read_addr_ksym(vmi, "PsLoadedModuleList", &next_module); } list_head = next_module; /* walk the module list */ while (1) { /* follow the next pointer */ addr_t tmp_next = 0; vmi_read_addr_va(vmi, next_module, 0, &tmp_next); /* if we are back at the list head, we are done */ if (list_head == tmp_next) { break; } /* print out the module name */ /* Note: the module struct that we are looking at has a string * directly following the next / prev pointers. This is why you * can just add the length of 2 address fields to get the name. * See include/linux/module.h for mode details */ if (VMI_OS_LINUX == vmi_get_ostype(vmi)) { char *modname = NULL; if (VMI_PM_IA32E == vmi_get_page_mode(vmi)) { // 64-bit paging modname = vmi_read_str_va(vmi, next_module + 16, 0); } else { modname = vmi_read_str_va(vmi, next_module + 8, 0); } printf("%s\n", modname); free(modname); } else if (VMI_OS_WINDOWS == vmi_get_ostype(vmi)) { /*TODO don't use a hard-coded offsets here */ /* this offset works with WinXP SP2 */ unicode_string_t *us = vmi_read_unicode_str_va(vmi, next_module + 0x2c, 0); unicode_string_t out = { 0 }; // both of these work if (us && VMI_SUCCESS == vmi_convert_str_encoding(us, &out, "UTF-8")) { printf("%s\n", out.contents); // if (us && // VMI_SUCCESS == vmi_convert_string_encoding (us, &out, "WCHAR_T")) { // printf ("%ls\n", out.contents); free(out.contents); } // if if (us) vmi_free_unicode_str(us); } next_module = tmp_next; } error_exit: /* resume the vm */ vmi_resume_vm(vmi); /* cleanup any memory associated with the libvmi instance */ vmi_destroy(vmi); return 0; }
static unicode_string_t * vmi_read_win_unicode_struct_va( vmi_instance_t vmi, addr_t vaddr, vmi_pid_t pid) { unicode_string_t *us = 0; // return val size_t struct_size = 0; size_t read = 0; addr_t buffer_va = 0; uint16_t buffer_len = 0; if (VMI_PM_IA32E == vmi_get_page_mode(vmi)) { // 64 bit guest win64_unicode_string_t us64 = { 0 }; struct_size = sizeof(us64); // read the UNICODE_STRING struct read = vmi_read_va(vmi, vaddr, pid, &us64, struct_size); if (read != struct_size) { dbprint ("--%s: failed to read UNICODE_STRING at VA 0x%.16"PRIx64" for pid %d\n", __FUNCTION__, vaddr, pid); goto out_error; } // if buffer_va = us64.pBuffer; buffer_len = us64.length; } else { win32_unicode_string_t us32 = { 0 }; struct_size = sizeof(us32); // read the UNICODE_STRING struct read = vmi_read_va(vmi, vaddr, pid, &us32, struct_size); if (read != struct_size) { dbprint ("--%s: failed to read UNICODE_STRING at VA 0x%.16"PRIx64" for pid %d\n", __FUNCTION__, vaddr, pid); goto out_error; } // if buffer_va = us32.pBuffer; buffer_len = us32.length; } // if-else // allocate the return value us = safe_malloc(sizeof(unicode_string_t)); us->length = buffer_len; us->contents = safe_malloc(sizeof(uint8_t) * (buffer_len + 2)); read = vmi_read_va(vmi, buffer_va, pid, us->contents, us->length); if (read != us->length) { dbprint ("--%s: failed to read buffer at VA 0x%.16"PRIx64" for pid %d\n", __FUNCTION__, buffer_va, pid); goto out_error; } // if // end with NULL (needed?) us->contents[buffer_len] = 0; us->contents[buffer_len + 1] = 0; us->encoding = "UTF-16"; return us; out_error: if (us) { if (us->contents) { free(us->contents); } free(us); } return 0; }