status_t is_WINDOWS_KERNEL(vmi_instance_t vmi, addr_t base_p, uint8_t *pe) { status_t ret = VMI_FAILURE; void *optional_pe_header = NULL; uint16_t optional_header_type = 0; struct export_table et; peparse_assign_headers(pe, NULL, NULL, &optional_header_type, &optional_pe_header, NULL, NULL); addr_t export_header_offset = peparse_get_idd_rva(IMAGE_DIRECTORY_ENTRY_EXPORT, &optional_header_type, optional_pe_header, NULL, NULL); // The kernel's export table is continuously allocated on the PA level with the PE header // This trick may not work for other PE headers (though may work for some drivers) uint32_t nbytes = vmi_read_pa(vmi, base_p + export_header_offset, &et, sizeof(struct export_table)); if(nbytes == sizeof(struct export_table) && !(et.export_flags || !et.name) ) { char *name = vmi_read_str_pa(vmi, base_p + et.name); if(name) { if(strcmp("ntoskrnl.exe", name)==0) ret = VMI_SUCCESS; free(name); } } return ret; }
status_t is_WINDOWS_KERNEL(vmi_instance_t vmi, addr_t base_p, uint8_t *pe) { status_t ret = VMI_FAILURE; void *optional_pe_header = NULL; uint16_t optional_header_type = 0; struct export_table et; peparse_assign_headers(pe, NULL, NULL, &optional_header_type, &optional_pe_header, NULL, NULL); addr_t export_header_offset = peparse_get_idd_rva(IMAGE_DIRECTORY_ENTRY_EXPORT, &optional_header_type, optional_pe_header, NULL, NULL); // The kernel's export table is continuously allocated on the PA level with the PE header // This trick may not work for other PE headers (though may work for some drivers) if ( base_p + export_header_offset < base_p + VMI_PS_4KB ) { if( VMI_SUCCESS == vmi_read_pa(vmi, base_p + export_header_offset, sizeof(struct export_table), &et, NULL) && !(et.export_flags || !et.name)) { char *name = vmi_read_str_pa(vmi, base_p + et.name); if(name) { if(strcmp("ntoskrnl.exe", name)==0) ret = VMI_SUCCESS; free(name); } } } // The export header may be stripped from the kernel so check section names. // This is commonly the case with Windows 10. if ( ret == VMI_FAILURE ) { ret = check_sections(vmi, base_p, pe); } return ret; }