Skip to content

Commit

Permalink
contrib/elf2dmp: add PE name check and Windows Server 2022 support
Browse files Browse the repository at this point in the history
Since its inception elf2dmp has checked MZ signatures within an
address space above IDT[0] interrupt vector and took first PE image
found as Windows Kernel.
But in Windows Server 2022 memory dump this address space range is
full of invalid PE fragments and the tool must check that PE image
is 'ntoskrnl.exe' actually.
So, introduce additional validation by checking image name from
Export Directory against 'ntoskrnl.exe'.

Signed-off-by: Viktor Prutyanov <viktor@daynix.com>
Tested-by: Yuri Benditovich <yuri.benditovich@daynix.com>
Reviewed-by: Annie Li <annie.li@oracle.com>
Message-id: 20230222211246.883679-4-viktor@daynix.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
  • Loading branch information
viktor-prutyanov authored and pm215 committed Mar 21, 2023
1 parent 06ac60b commit d399d6b
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 2 deletions.
28 changes: 26 additions & 2 deletions contrib/elf2dmp/main.c
Expand Up @@ -17,6 +17,7 @@

#define SYM_URL_BASE "https://msdl.microsoft.com/download/symbols/"
#define PDB_NAME "ntkrnlmp.pdb"
#define PE_NAME "ntoskrnl.exe"

#define INITIAL_MXCSR 0x1f80

Expand Down Expand Up @@ -405,6 +406,25 @@ static int write_dump(struct pa_space *ps,
return fclose(dmp_file);
}

static bool pe_check_export_name(uint64_t base, void *start_addr,
struct va_space *vs)
{
IMAGE_EXPORT_DIRECTORY export_dir;
const char *pe_name;

if (pe_get_data_dir_entry(base, start_addr, IMAGE_FILE_EXPORT_DIRECTORY,
&export_dir, sizeof(export_dir), vs)) {
return false;
}

pe_name = va_space_resolve(vs, base + export_dir.Name);
if (!pe_name) {
return false;
}

return !strcmp(pe_name, PE_NAME);
}

static int pe_get_pdb_symstore_hash(uint64_t base, void *start_addr,
char *hash, struct va_space *vs)
{
Expand Down Expand Up @@ -489,6 +509,7 @@ int main(int argc, char *argv[])
uint64_t KdDebuggerDataBlock;
KDDEBUGGER_DATA64 *kdbg;
uint64_t KdVersionBlock;
bool kernel_found = false;

if (argc != 3) {
eprintf("usage:\n\t%s elf_file dmp_file\n", argv[0]);
Expand Down Expand Up @@ -536,11 +557,14 @@ int main(int argc, char *argv[])
}

if (*(uint16_t *)nt_start_addr == 0x5a4d) { /* MZ */
break;
if (pe_check_export_name(KernBase, nt_start_addr, &vs)) {
kernel_found = true;
break;
}
}
}

if (!nt_start_addr) {
if (!kernel_found) {
eprintf("Failed to find NT kernel image\n");
err = 1;
goto out_ps;
Expand Down
15 changes: 15 additions & 0 deletions contrib/elf2dmp/pe.h
Expand Up @@ -88,6 +88,20 @@ typedef struct IMAGE_NT_HEADERS64 {
IMAGE_OPTIONAL_HEADER64 OptionalHeader;
} __attribute__ ((packed)) IMAGE_NT_HEADERS64;

typedef struct IMAGE_EXPORT_DIRECTORY {
uint32_t Characteristics;
uint32_t TimeDateStamp;
uint16_t MajorVersion;
uint16_t MinorVersion;
uint32_t Name;
uint32_t Base;
uint32_t NumberOfFunctions;
uint32_t NumberOfNames;
uint32_t AddressOfFunctions;
uint32_t AddressOfNames;
uint32_t AddressOfNameOrdinals;
} __attribute__ ((packed)) IMAGE_EXPORT_DIRECTORY;

typedef struct IMAGE_DEBUG_DIRECTORY {
uint32_t Characteristics;
uint32_t TimeDateStamp;
Expand All @@ -102,6 +116,7 @@ typedef struct IMAGE_DEBUG_DIRECTORY {
#define IMAGE_DEBUG_TYPE_CODEVIEW 2
#endif

#define IMAGE_FILE_EXPORT_DIRECTORY 0
#define IMAGE_FILE_DEBUG_DIRECTORY 6

typedef struct guid_t {
Expand Down

0 comments on commit d399d6b

Please sign in to comment.