// search for the given module+symbol in the given module list static status_t modlist_sym2va(drakvuf_t drakvuf, addr_t list_head, access_context_t *ctx, const char *mod_name, const char *symbol, addr_t *va) { vmi_instance_t vmi = drakvuf->vmi; addr_t next_module = list_head; /* walk the module list */ while (1) { /* follow the next pointer */ addr_t tmp_next = 0; ctx->addr = next_module; if(VMI_FAILURE==vmi_read_addr(vmi, ctx, &tmp_next)) break; /* if we are back at the list head, we are done */ if (list_head == tmp_next || !tmp_next) { break; } ctx->addr = next_module + drakvuf->offsets[LDR_DATA_TABLE_ENTRY_BASEDLLNAME]; unicode_string_t *us = vmi_read_unicode_str(vmi, ctx); unicode_string_t out = { .contents = NULL }; if (us && VMI_SUCCESS == vmi_convert_str_encoding(us, &out, "UTF-8")) { PRINT_DEBUG("Found module %s\n", out.contents); if (!strcasecmp((char*) out.contents, mod_name)) { addr_t dllbase; ctx->addr = next_module + drakvuf->offsets[LDR_DATA_TABLE_ENTRY_DLLBASE]; vmi_read_addr(vmi, ctx, &dllbase); ctx->addr = dllbase; *va = vmi_translate_sym2v(vmi, ctx, (char *) symbol); PRINT_DEBUG("\t%s @ 0x%lx\n", symbol, *va); free(out.contents); vmi_free_unicode_str(us); return VMI_SUCCESS; } free(out.contents); } if (us) vmi_free_unicode_str(us); next_module = tmp_next; } return VMI_FAILURE; }
// search for the given module+symbol in the given module list static status_t modlist_va2sym(drakvuf_t drakvuf, addr_t list_head, addr_t va, access_context_t *ctx, char **out_mod, char **out_sym) { vmi_instance_t vmi = drakvuf->vmi; addr_t next_module = list_head; /* walk the module list */ while (1) { /* follow the next pointer */ addr_t tmp_next = 0; ctx->addr = next_module; if(VMI_FAILURE == vmi_read_addr(vmi, ctx, &tmp_next)) break; /* if we are back at the list head, we are done */ if (list_head == tmp_next || !tmp_next) { break; } ctx->addr = next_module + drakvuf->offsets[LDR_DATA_TABLE_ENTRY_BASEDLLNAME]; unicode_string_t *us = vmi_read_unicode_str(vmi, ctx); unicode_string_t out = { .contents = NULL }; if (us && VMI_SUCCESS == vmi_convert_str_encoding(us, &out, "UTF-8")) { addr_t dllbase; ctx->addr = next_module + drakvuf->offsets[LDR_DATA_TABLE_ENTRY_DLLBASE]; if(VMI_FAILURE == vmi_read_addr(vmi, ctx, &dllbase)) { free(us); break; } ctx->addr = dllbase; const char *sym = vmi_translate_v2sym(vmi, ctx, va); if (sym) { *out_mod = g_strdup((char*)out.contents); *out_sym = (char*) sym; free(out.contents); vmi_free_unicode_str(us); return VMI_SUCCESS; } else { free(out.contents); } } if (us) vmi_free_unicode_str(us); next_module = tmp_next; } return VMI_FAILURE; }
bool drakvuf_get_module_base_addr( drakvuf_t drakvuf, addr_t module_list_head, const char *module_name, addr_t *base_addr_out ) { addr_t base_addr ; size_t name_len = strlen( module_name ); vmi_instance_t vmi = drakvuf->vmi; addr_t next_module = module_list_head; while( 1 ) { addr_t tmp_next = 0; if ( vmi_read_addr_va( vmi, next_module, 4, &tmp_next ) != VMI_SUCCESS ) break; if ( module_list_head == tmp_next ) break; base_addr = 0 ; if ( vmi_read_addr_va( vmi, next_module + offsets[LDR_DATA_TABLE_ENTRY_DLLBASE], 4, &base_addr ) != VMI_SUCCESS ) break; if ( ! base_addr ) break; unicode_string_t *us = vmi_read_unicode_str_va( vmi, next_module + offsets[LDR_DATA_TABLE_ENTRY_BASEDLLNAME], 4 ); if ( us ) { unicode_string_t out = { 0 }; if ( vmi_convert_str_encoding( us, &out, "UTF-8" ) == VMI_SUCCESS ) { if ( ! strncasecmp( (char *)out.contents, module_name, name_len ) ) { free( out.contents ); vmi_free_unicode_str( us ); *base_addr_out = base_addr ; return true ; } free( out.contents ); } vmi_free_unicode_str( us ); } next_module = tmp_next ; } return false ; }
static event_response_t file_name_cb(drakvuf_t drakvuf, drakvuf_trap_info_t *info) { vmi_instance_t vmi = drakvuf_lock_and_get_vmi(drakvuf); struct file_watch *watch = (struct file_watch*)info->trap->data; filetracer *f = watch->f; if (info->trap_pa == watch->file_name_buffer) { addr_t file_name = 0; uint16_t length = 0; vmi_read_addr_pa(vmi, watch->file_name_buffer, &file_name); vmi_read_16_pa(vmi, watch->file_name_length, &length); //printf("File name @ 0x%lx. Length: %u\n", file_name, length); if (file_name && length > 0 && length < VMI_PS_4KB) { char *procname = drakvuf_get_current_process_name(drakvuf, info->vcpu, info->regs); unicode_string_t str = { .contents = NULL }; str.length = length; str.encoding = "UTF-16"; str.contents = (unsigned char *)g_malloc0(length); vmi_read_va(vmi, file_name, 0, str.contents, length); unicode_string_t str2 = { .contents = NULL }; status_t rc = vmi_convert_str_encoding(&str, &str2, "UTF-8"); if (VMI_SUCCESS == rc) { switch(f->format) { case OUTPUT_CSV: printf("filetracer,%" PRIu32 ",0x%" PRIx64 ",%s,%s\n", info->vcpu, info->regs->cr3, procname, str2.contents); break; default: case OUTPUT_DEFAULT: printf("[FILETRACER] VCPU:%" PRIu32 " CR3:0x%" PRIx64 ",%s %s\n", info->vcpu, info->regs->cr3, procname, str2.contents); break; }; g_free(str2.contents); } free(str.contents); free(procname); //printf("Requesting to free writetrap @ %p\n", info->trap); info->trap->data=f; drakvuf_remove_trap(drakvuf, info->trap, free_writetrap); }
void carve_file_from_memory(drakvuf_t *drakvuf, addr_t ph_base, addr_t block_size) { addr_t aligned_file_size = struct_sizes[FILE_OBJECT]; if(PM2BIT(drakvuf->pm) == BIT32) { // 8-byte alignment on 32-bit mode if(struct_sizes[FILE_OBJECT] % 8) { aligned_file_size += 8 - (struct_sizes[FILE_OBJECT] % 8); } } else { // 16-byte alignment on 64-bit mode if(struct_sizes[FILE_OBJECT] % 16) { aligned_file_size += 16 - (struct_sizes[FILE_OBJECT] % 16); } } addr_t file_base = ph_base + block_size - aligned_file_size; addr_t file_name = file_base + offsets[FILE_OBJECT_FILENAME]; addr_t file_name_str = 0; uint16_t length = 0; vmi_read_addr_pa(drakvuf->vmi, file_name + offsets[UNICODE_STRING_BUFFER], &file_name_str); vmi_read_16_pa(drakvuf->vmi, file_name + offsets[UNICODE_STRING_LENGTH], &length); if (file_name_str && length) { unicode_string_t str = { .contents = NULL }; str.length = length; str.encoding = "UTF-16"; str.contents = malloc(length); vmi_read_va(drakvuf->vmi, file_name, 0, str.contents, length); unicode_string_t str2 = { .contents = NULL }; status_t rc = vmi_convert_str_encoding(&str, &str2, "UTF-8"); if (VMI_SUCCESS == rc) { PRINT_DEBUG("\tFile closing: %s.\n", str2.contents); volatility_extract_file(drakvuf, file_base); g_free(str2.contents); } free(str.contents); }
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; }