END_TEST START_TEST (test_vmi_get_memsize_max_phys_addr) { vmi_instance_t vmi = NULL; uint64_t memsize = 0; addr_t max_physical_addr = 0; vmi_init_complete(&vmi, (void*)get_testvm(), VMI_INIT_DOMAINNAME, NULL, VMI_CONFIG_GLOBAL_FILE_ENTRY, NULL, NULL); memsize = vmi_get_memsize(vmi); max_physical_addr = vmi_get_max_physical_address(vmi); fail_unless(memsize > 0, "guest ram size is 0"); fail_unless(max_physical_addr > 0, "max physical address is 0"); fail_unless(max_physical_addr >= memsize, "max physical address is less than memsize"); vmi_destroy(vmi); }
END_TEST /* test vmi_get_dgpma */ // we use vmi_read_pa() to verify vmi_get_dgpma() START_TEST (test_vmi_get_dgpma) { vmi_instance_t vmi = NULL; vmi_init(&vmi, VMI_AUTO | VMI_INIT_COMPLETE, get_testvm()); vmi_shm_snapshot_create(vmi); addr_t pa = 0x1000; // just because vmi_read_page() deny to fetch frame 0. size_t count = 4096; unsigned long max_size = vmi_get_max_physical_address(vmi); void *buf_readpa = malloc(count); void *buf_dgpma = NULL; for (; pa + count <= max_size; pa += count) { size_t read_pa = vmi_read_pa(vmi, pa, buf_readpa, count); size_t read_dgpma = vmi_get_dgpma(vmi, pa, &buf_dgpma, count); if (read_pa == 0 && read_dgpma == 0) { continue; } fail_unless(read_pa == read_dgpma, "vmi_get_dgpma(0x%"PRIx64 ") read size %d dosn't conform to %d of vmi_read_pa()", pa, read_dgpma, read_pa); int cmp = memcmp(buf_readpa, buf_dgpma, read_pa); fail_unless(0 == cmp, "vmi_get_dgpma(0x%"PRIx64 ") contents dosn't conform to vmi_read_pa()", pa); } free(buf_readpa); vmi_shm_snapshot_destroy(vmi); vmi_destroy(vmi); }
status_t find_kdbg_address_fast( vmi_instance_t vmi, addr_t *kdbg_pa, addr_t *kernel_pa, addr_t *kernel_va) { dbprint(VMI_DEBUG_MISC, "**Trying find_kdbg_address_fast\n"); status_t ret = VMI_FAILURE; reg_t cr3; if (VMI_FAILURE == driver_get_vcpureg(vmi, &cr3, CR3, 0)) { return ret; } addr_t memsize = vmi_get_max_physical_address(vmi); GSList *va_pages = vmi_get_va_pages(vmi, (addr_t)cr3); void *bm = 0; // boyer-moore internal state unsigned char haystack[VMI_PS_4KB]; int find_ofs = 0; if (VMI_PM_IA32E == vmi->page_mode) { bm = boyer_moore_init((unsigned char *)"\x00\xf8\xff\xffKDBG", 8); find_ofs = 0xc; } else { bm = boyer_moore_init((unsigned char *)"\x00\x00\x00\x00\x00\x00\x00\x00KDBG", 12); find_ofs = 0x8; } // if-else GSList *va_pages_loop = va_pages; while (va_pages_loop) { page_info_t *vap = (page_info_t *)va_pages_loop->data; // We might get pages that are greater than 4Kb // so we are just going to split them to 4Kb pages while (vap && vap->size >= VMI_PS_4KB) { vap->size -= VMI_PS_4KB; addr_t page_paddr = vap->paddr+vap->size; if (page_paddr + VMI_PS_4KB - 1 > memsize) { continue; } if ( VMI_FAILURE == vmi_read_pa(vmi, page_paddr, VMI_PS_4KB, haystack, NULL) ) continue; int match_offset = boyer_moore2(bm, haystack, VMI_PS_4KB); if (-1 != match_offset) { addr_t tmp_kva = 0, tmp_kpa = 0; addr_t tmp_kdbg = page_paddr + (unsigned int) match_offset - find_ofs; if (VMI_FAILURE == vmi_read_64_pa(vmi, tmp_kdbg + sizeof(DBGKD_DEBUG_DATA_HEADER64), &tmp_kva)) { continue; } if ( VMI_FAILURE == vmi_pagetable_lookup(vmi, cr3, tmp_kva, &tmp_kpa) ) continue; *kdbg_pa = tmp_kdbg; *kernel_va = tmp_kva; *kernel_pa = tmp_kpa; ret = VMI_SUCCESS; goto done; } } g_free(vap); va_pages_loop = va_pages_loop->next; } done: // free the rest of the list while (va_pages_loop) { g_free(va_pages_loop->data); va_pages_loop = va_pages_loop->next; } g_slist_free(va_pages); if (VMI_SUCCESS == ret) dbprint(VMI_DEBUG_MISC, "--Found KdDebuggerDataBlock at PA %.16"PRIx64"\n", *kdbg_pa); boyer_moore_fini(bm); return ret; }
status_t find_kdbg_address( vmi_instance_t vmi, addr_t *kdbg_pa, addr_t *kernel_va) { dbprint(VMI_DEBUG_MISC, "**Trying find_kdbg_address\n"); status_t ret = VMI_FAILURE; *kdbg_pa = 0; addr_t paddr = 0; unsigned char haystack[VMI_PS_4KB]; addr_t memsize = vmi_get_max_physical_address(vmi); void *bm64 = boyer_moore_init((unsigned char *)"\x00\xf8\xff\xffKDBG", 8); void *bm32 = boyer_moore_init((unsigned char *)"\x00\x00\x00\x00\x00\x00\x00\x00KDBG", 12); uint32_t find_ofs_64 = 0xc, find_ofs_32 = 0x8, find_ofs = 0; for (; paddr<memsize; paddr+=VMI_PS_4KB) { find_ofs = 0; if (VMI_FAILURE == vmi_read_pa(vmi, paddr, VMI_PS_4KB, &haystack, NULL)) continue; int match_offset = boyer_moore2(bm64, haystack, VMI_PS_4KB); if (-1 != match_offset) { find_ofs = find_ofs_64; } else { match_offset = boyer_moore2(bm32, haystack, VMI_PS_4KB); } if (-1 != match_offset) { if (!find_ofs) { find_ofs = find_ofs_32; } // Read "KernBase" from the haystack long unsigned int kernbase_offset = 0; kdbg_symbol_offset("KernBase", &kernbase_offset); if ( match_offset - find_ofs + kernbase_offset + sizeof(uint64_t) >= VMI_PS_4KB ) continue; memcpy(kernel_va, &haystack[(unsigned int) match_offset - find_ofs + kernbase_offset], sizeof(uint64_t)); *kdbg_pa = paddr + (unsigned int) match_offset - find_ofs; ret = VMI_SUCCESS; break; } } dbprint(VMI_DEBUG_MISC, "--Found KdDebuggerDataBlock at PA %.16"PRIx64"\n", *kdbg_pa); boyer_moore_fini(bm32); boyer_moore_fini(bm64); return ret; }
int main(int argc, char **argv) { vmi_instance_t vmi = NULL; vmi_mode_t mode; /* this is the VM that we are looking at */ if (argc != 3) { printf("Usage: %s name|domid <domain name|domain id>\n", argv[0]); return 1; } // if void *domain; uint64_t domid = VMI_INVALID_DOMID; uint64_t init_flags = 0; if(strcmp(argv[1],"name")==0) { domain = (void*)argv[2]; init_flags |= VMI_INIT_DOMAINNAME; } else if(strcmp(argv[1],"domid")==0) { domid = strtoull(argv[2], NULL, 0); domain = (void*)&domid; init_flags |= VMI_INIT_DOMAINID; } else { printf("You have to specify either name or domid!\n"); return 1; } if (VMI_FAILURE == vmi_get_access_mode(vmi, domain, init_flags, NULL, &mode) ) return 1; /* initialize the libvmi library */ if (VMI_FAILURE == vmi_init(&vmi, mode, domain, init_flags, NULL, NULL)) { printf("Failed to init LibVMI library.\n"); return 1; } max_mem = vmi_get_max_physical_address(vmi); /* the nice thing about the windows kernel is that it's page aligned */ uint32_t found = 0; access_context_t ctx = { .translate_mechanism = VMI_TM_NONE, }; for(ctx.addr = 0; ctx.addr < max_mem; ctx.addr += PAGE_SIZE) { uint8_t pe[MAX_HEADER_SIZE]; if(VMI_SUCCESS == peparse_get_image(vmi, &ctx, MAX_HEADER_SIZE, pe)) { if(VMI_SUCCESS == is_WINDOWS_KERNEL(vmi, ctx.addr, pe)) { printf("Windows Kernel found @ 0x%" PRIx64 "\n", ctx.addr); print_os_version(pe); print_guid(vmi, ctx.addr, pe); print_pe_header(vmi, ctx.addr, pe); found=1; break; } } } /* cleanup any memory associated with the LibVMI instance */ vmi_destroy(vmi); if(found) return 0; return 1; }