winedump: Dump the alternate version of some data directories for hybrid PE dlls.

This commit is contained in:
Alexandre Julliard 2023-02-16 14:29:20 +01:00
parent 41e708dafa
commit 385ce62761

View file

@ -33,6 +33,7 @@
#define IMAGE_DLLCHARACTERISTICS_PREFER_NATIVE 0x0010 /* Wine extension */
static const IMAGE_NT_HEADERS32* PE_nt_headers;
static const IMAGE_NT_HEADERS32* PE_alt_headers; /* alternative headers for hybrid dlls */
static const char builtin_signature[] = "Wine builtin DLL";
static const char fakedll_signature[] = "Wine placeholder DLL";
@ -105,11 +106,11 @@ void print_fake_dll( void )
}
}
static const void *get_dir_and_size(unsigned int idx, unsigned int *size)
static const void *get_data_dir(const IMAGE_NT_HEADERS32 *hdr, unsigned int idx, unsigned int *size)
{
if(PE_nt_headers->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC)
if(hdr->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC)
{
const IMAGE_OPTIONAL_HEADER64 *opt = (const IMAGE_OPTIONAL_HEADER64*)&PE_nt_headers->OptionalHeader;
const IMAGE_OPTIONAL_HEADER64 *opt = (const IMAGE_OPTIONAL_HEADER64*)&hdr->OptionalHeader;
if (idx >= opt->NumberOfRvaAndSizes)
return NULL;
if(size)
@ -119,7 +120,7 @@ static const void *get_dir_and_size(unsigned int idx, unsigned int *size)
}
else
{
const IMAGE_OPTIONAL_HEADER32 *opt = (const IMAGE_OPTIONAL_HEADER32*)&PE_nt_headers->OptionalHeader;
const IMAGE_OPTIONAL_HEADER32 *opt = (const IMAGE_OPTIONAL_HEADER32*)&hdr->OptionalHeader;
if (idx >= opt->NumberOfRvaAndSizes)
return NULL;
if(size)
@ -129,11 +130,25 @@ static const void *get_dir_and_size(unsigned int idx, unsigned int *size)
}
}
static const void *get_dir_and_size(unsigned int idx, unsigned int *size)
{
return get_data_dir( PE_nt_headers, idx, size );
}
static const void* get_dir(unsigned idx)
{
return get_dir_and_size(idx, 0);
}
static const void *get_alt_dir_and_size(unsigned int idx, unsigned int *size)
{
const void *dir;
if (!PE_alt_headers) return NULL;
dir = get_data_dir( PE_alt_headers, idx, size );
if (dir == get_dir(idx)) return NULL;
return dir;
}
static const char * const DirectoryNames[16] = {
"EXPORT", "IMPORT", "RESOURCE", "EXCEPTION",
"SECURITY", "BASERELOC", "DEBUG", "ARCHITECTURE",
@ -386,9 +401,8 @@ void dump_file_header(const IMAGE_FILE_HEADER *fileHeader, BOOL is_hybrid)
}
printf(" Machine: %04X (%s)\n", fileHeader->Machine, name);
printf(" Number of Sections: %d\n", fileHeader->NumberOfSections);
printf(" TimeDateStamp: %08X (%s) offset %lu\n",
(UINT)fileHeader->TimeDateStamp, get_time_str(fileHeader->TimeDateStamp),
Offset(&(fileHeader->TimeDateStamp)));
printf(" TimeDateStamp: %08X (%s)\n",
(UINT)fileHeader->TimeDateStamp, get_time_str(fileHeader->TimeDateStamp));
printf(" PointerToSymbolTable: %08X\n", (UINT)fileHeader->PointerToSymbolTable);
printf(" NumberOfSymbols: %08X\n", (UINT)fileHeader->NumberOfSymbols);
printf(" SizeOfOptionalHeader: %04X\n", (UINT)fileHeader->SizeOfOptionalHeader);
@ -417,7 +431,13 @@ void dump_file_header(const IMAGE_FILE_HEADER *fileHeader, BOOL is_hybrid)
static void dump_pe_header(void)
{
dump_file_header(&PE_nt_headers->FileHeader, get_hybrid_metadata() != 0);
dump_optional_header((const IMAGE_OPTIONAL_HEADER32*)&PE_nt_headers->OptionalHeader, PE_nt_headers->FileHeader.SizeOfOptionalHeader);
dump_optional_header((const IMAGE_OPTIONAL_HEADER32*)&PE_nt_headers->OptionalHeader,
PE_nt_headers->FileHeader.SizeOfOptionalHeader);
if (!PE_alt_headers) return;
printf( "Alternate Headers\n\n");
dump_file_header(&PE_alt_headers->FileHeader, FALSE);
dump_optional_header((const IMAGE_OPTIONAL_HEADER32*)&PE_alt_headers->OptionalHeader,
PE_alt_headers->FileHeader.SizeOfOptionalHeader);
}
void dump_section_characteristics(DWORD characteristics, const char* sep)
@ -641,58 +661,65 @@ static void dump_section_apiset(void)
static void dump_dir_exported_functions(void)
{
unsigned int size = 0;
const IMAGE_EXPORT_DIRECTORY*exportDir = get_dir_and_size(IMAGE_FILE_EXPORT_DIRECTORY, &size);
UINT i, *funcs;
unsigned int size[2] = { 0 };
const IMAGE_EXPORT_DIRECTORY *dirs[2];
UINT dir, i, *funcs;
const UINT *pFunc;
const UINT *pName;
const WORD *pOrdl;
if (!exportDir) return;
dirs[0] = get_dir_and_size(IMAGE_FILE_EXPORT_DIRECTORY, &size[0]);
if (!dirs[0]) return;
dirs[1] = get_alt_dir_and_size(IMAGE_FILE_EXPORT_DIRECTORY, &size[1]);
printf("Exports table:\n");
printf("\n");
printf(" Name: %s\n", (const char*)RVA(exportDir->Name, sizeof(DWORD)));
printf(" Characteristics: %08x\n", (UINT)exportDir->Characteristics);
printf(" TimeDateStamp: %08X %s\n",
(UINT)exportDir->TimeDateStamp, get_time_str(exportDir->TimeDateStamp));
printf(" Version: %u.%02u\n", exportDir->MajorVersion, exportDir->MinorVersion);
printf(" Ordinal base: %u\n", (UINT)exportDir->Base);
printf(" # of functions: %u\n", (UINT)exportDir->NumberOfFunctions);
printf(" # of Names: %u\n", (UINT)exportDir->NumberOfNames);
printf("Addresses of functions: %08X\n", (UINT)exportDir->AddressOfFunctions);
printf("Addresses of name ordinals: %08X\n", (UINT)exportDir->AddressOfNameOrdinals);
printf("Addresses of names: %08X\n", (UINT)exportDir->AddressOfNames);
printf("\n");
printf(" Entry Pt Ordn Name\n");
pFunc = RVA(exportDir->AddressOfFunctions, exportDir->NumberOfFunctions * sizeof(DWORD));
if (!pFunc) {printf("Can't grab functions' address table\n"); return;}
pName = RVA(exportDir->AddressOfNames, exportDir->NumberOfNames * sizeof(DWORD));
pOrdl = RVA(exportDir->AddressOfNameOrdinals, exportDir->NumberOfNames * sizeof(WORD));
funcs = calloc( exportDir->NumberOfFunctions, sizeof(*funcs) );
if (!funcs) fatal("no memory");
for (i = 0; i < exportDir->NumberOfNames; i++) funcs[pOrdl[i]] = pName[i];
for (i = 0; i < exportDir->NumberOfFunctions; i++)
for (dir = 0; dir < 2 && dirs[dir]; dir++)
{
if (!pFunc[i]) continue;
printf(" %08X %5u ", pFunc[i], (UINT)exportDir->Base + i);
if (funcs[i])
printf("%s", get_symbol_str((const char*)RVA(funcs[i], sizeof(DWORD))));
else
printf("<by ordinal>");
if (dir) printf("Alternate (%s) exports table:\n",
get_machine_str(PE_alt_headers->FileHeader.Machine));
else printf("Exports table:\n");
printf("\n");
printf(" Name: %s\n", (const char*)RVA(dirs[dir]->Name, sizeof(DWORD)));
printf(" Characteristics: %08x\n", (UINT)dirs[dir]->Characteristics);
printf(" TimeDateStamp: %08X %s\n",
(UINT)dirs[dir]->TimeDateStamp, get_time_str(dirs[dir]->TimeDateStamp));
printf(" Version: %u.%02u\n", dirs[dir]->MajorVersion, dirs[dir]->MinorVersion);
printf(" Ordinal base: %u\n", (UINT)dirs[dir]->Base);
printf(" # of functions: %u\n", (UINT)dirs[dir]->NumberOfFunctions);
printf(" # of Names: %u\n", (UINT)dirs[dir]->NumberOfNames);
printf("Addresses of functions: %08X\n", (UINT)dirs[dir]->AddressOfFunctions);
printf("Addresses of name ordinals: %08X\n", (UINT)dirs[dir]->AddressOfNameOrdinals);
printf("Addresses of names: %08X\n", (UINT)dirs[dir]->AddressOfNames);
printf("\n");
printf(" Entry Pt Ordn Name\n");
/* check for forwarded function */
if ((const char *)RVA(pFunc[i],1) >= (const char *)exportDir &&
(const char *)RVA(pFunc[i],1) < (const char *)exportDir + size)
printf(" (-> %s)", (const char *)RVA(pFunc[i],1));
pFunc = RVA(dirs[dir]->AddressOfFunctions, dirs[dir]->NumberOfFunctions * sizeof(DWORD));
if (!pFunc) {printf("Can't grab functions' address table\n"); return;}
pName = RVA(dirs[dir]->AddressOfNames, dirs[dir]->NumberOfNames * sizeof(DWORD));
pOrdl = RVA(dirs[dir]->AddressOfNameOrdinals, dirs[dir]->NumberOfNames * sizeof(WORD));
funcs = calloc( dirs[dir]->NumberOfFunctions, sizeof(*funcs) );
if (!funcs) fatal("no memory");
for (i = 0; i < dirs[dir]->NumberOfNames; i++) funcs[pOrdl[i]] = pName[i];
for (i = 0; i < dirs[dir]->NumberOfFunctions; i++)
{
if (!pFunc[i]) continue;
printf(" %08X %5u ", pFunc[i], (UINT)dirs[dir]->Base + i);
if (funcs[i])
printf("%s", get_symbol_str((const char*)RVA(funcs[i], sizeof(DWORD))));
else
printf("<by ordinal>");
/* check for forwarded function */
if ((const char *)RVA(pFunc[i],1) >= (const char *)dirs[dir] &&
(const char *)RVA(pFunc[i],1) < (const char *)dirs[dir] + size[dir])
printf(" (-> %s)", (const char *)RVA(pFunc[i],1));
printf("\n");
}
free(funcs);
printf("\n");
}
free(funcs);
printf("\n");
}
@ -1652,33 +1679,42 @@ static void dump_arm64_unwind_info( const struct runtime_function_arm64 *func )
static void dump_dir_exceptions(void)
{
unsigned int i, size = 0;
const void *funcs = get_dir_and_size(IMAGE_FILE_EXCEPTION_DIRECTORY, &size);
const IMAGE_FILE_HEADER *file_header = &PE_nt_headers->FileHeader;
unsigned int i, dir, size, sizes[2] = { 0 };
const void *funcs[2];
const IMAGE_FILE_HEADER *file_header;
if (!funcs) return;
funcs[0] = get_dir_and_size(IMAGE_FILE_EXCEPTION_DIRECTORY, &sizes[0]);
if (!funcs[0]) return;
funcs[1] = get_alt_dir_and_size(IMAGE_FILE_EXCEPTION_DIRECTORY, &sizes[1]);
switch (file_header->Machine)
for (dir = 0; dir < 2 && funcs[dir]; dir++)
{
case IMAGE_FILE_MACHINE_AMD64:
size /= sizeof(struct runtime_function_x86_64);
printf( "Exception info (%u functions):\n", size );
for (i = 0; i < size; i++) dump_x86_64_unwind_info( (struct runtime_function_x86_64*)funcs + i );
break;
case IMAGE_FILE_MACHINE_ARMNT:
size /= sizeof(struct runtime_function_armnt);
printf( "Exception info (%u functions):\n", size );
for (i = 0; i < size; i++) dump_armnt_unwind_info( (struct runtime_function_armnt*)funcs + i );
break;
case IMAGE_FILE_MACHINE_ARM64:
size /= sizeof(struct runtime_function_arm64);
printf( "Exception info (%u functions):\n", size );
for (i = 0; i < size; i++) dump_arm64_unwind_info( (struct runtime_function_arm64*)funcs + i );
break;
default:
printf( "Exception information not supported for %s binaries\n",
get_machine_str(file_header->Machine));
break;
size = sizes[dir];
file_header = dir ? &PE_alt_headers->FileHeader : &PE_nt_headers->FileHeader;
switch (file_header->Machine)
{
case IMAGE_FILE_MACHINE_AMD64:
size /= sizeof(struct runtime_function_x86_64);
printf( "%s exception info (%u functions):\n", get_machine_str( file_header->Machine ), size );
for (i = 0; i < size; i++) dump_x86_64_unwind_info( (struct runtime_function_x86_64*)funcs[dir] + i );
break;
case IMAGE_FILE_MACHINE_ARMNT:
size /= sizeof(struct runtime_function_armnt);
printf( "%s exception info (%u functions):\n", get_machine_str( file_header->Machine ), size );
for (i = 0; i < size; i++) dump_armnt_unwind_info( (struct runtime_function_armnt*)funcs[dir] + i );
break;
case IMAGE_FILE_MACHINE_ARM64:
size /= sizeof(struct runtime_function_arm64);
printf( "%s exception info (%u functions):\n", get_machine_str( file_header->Machine ), size );
for (i = 0; i < size; i++) dump_arm64_unwind_info( (struct runtime_function_arm64*)funcs[dir] + i );
break;
default:
printf( "Exception information not supported for %s binaries\n",
get_machine_str(file_header->Machine));
break;
}
printf( "\n" );
}
}
@ -1765,139 +1801,150 @@ static void dump_dir_imported_functions(void)
static void dump_dir_loadconfig(void)
{
unsigned int size;
const IMAGE_LOAD_CONFIG_DIRECTORY32 *loadcfg32 = get_dir_and_size(IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG, &size);
const IMAGE_LOAD_CONFIG_DIRECTORY64 *loadcfg64 = (void*)loadcfg32;
unsigned int dir, size, sizes[2];
const IMAGE_LOAD_CONFIG_DIRECTORY32 *dirs[2];
if (!loadcfg32) return;
size = min( size, loadcfg32->Size );
dirs[0] = get_dir_and_size(IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG, &sizes[0]);
if (!dirs[0]) return;
dirs[1] = get_alt_dir_and_size(IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG, &sizes[1]);
printf( "Loadconfig\n" );
print_dword( "Size", loadcfg32->Size );
print_dword( "TimeDateStamp", loadcfg32->TimeDateStamp );
print_word( "MajorVersion", loadcfg32->MajorVersion );
print_word( "MinorVersion", loadcfg32->MinorVersion );
print_dword( "GlobalFlagsClear", loadcfg32->GlobalFlagsClear );
print_dword( "GlobalFlagsSet", loadcfg32->GlobalFlagsSet );
print_dword( "CriticalSectionDefaultTimeout", loadcfg32->CriticalSectionDefaultTimeout );
if(PE_nt_headers->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC)
for (dir = 0; dir < 2 && dirs[dir]; dir++)
{
print_longlong( "DeCommitFreeBlockThreshold", loadcfg64->DeCommitFreeBlockThreshold );
print_longlong( "DeCommitTotalFreeThreshold", loadcfg64->DeCommitTotalFreeThreshold );
print_longlong( "MaximumAllocationSize", loadcfg64->MaximumAllocationSize );
print_longlong( "VirtualMemoryThreshold", loadcfg64->VirtualMemoryThreshold );
print_dword( "ProcessHeapFlags", loadcfg64->ProcessHeapFlags );
print_longlong( "ProcessAffinityMask", loadcfg64->ProcessAffinityMask );
print_word( "CSDVersion", loadcfg64->CSDVersion );
print_word( "DependentLoadFlags", loadcfg64->DependentLoadFlags );
print_longlong( "SecurityCookie", loadcfg64->SecurityCookie );
if (size <= offsetof( IMAGE_LOAD_CONFIG_DIRECTORY64, SEHandlerTable )) return;
print_longlong( "SEHandlerTable", loadcfg64->SEHandlerTable );
print_longlong( "SEHandlerCount", loadcfg64->SEHandlerCount );
if (size <= offsetof( IMAGE_LOAD_CONFIG_DIRECTORY64, GuardCFCheckFunctionPointer )) return;
print_longlong( "GuardCFCheckFunctionPointer", loadcfg64->GuardCFCheckFunctionPointer );
print_longlong( "GuardCFDispatchFunctionPointer", loadcfg64->GuardCFDispatchFunctionPointer );
print_longlong( "GuardCFFunctionTable", loadcfg64->GuardCFFunctionTable );
print_longlong( "GuardCFFunctionCount", loadcfg64->GuardCFFunctionCount );
print_dword( "GuardFlags", loadcfg64->GuardFlags );
if (size <= offsetof( IMAGE_LOAD_CONFIG_DIRECTORY64, CodeIntegrity )) return;
print_word( "CodeIntegrity.Flags", loadcfg64->CodeIntegrity.Flags );
print_word( "CodeIntegrity.Catalog", loadcfg64->CodeIntegrity.Catalog );
print_dword( "CodeIntegrity.CatalogOffset", loadcfg64->CodeIntegrity.CatalogOffset );
print_dword( "CodeIntegrity.Reserved", loadcfg64->CodeIntegrity.Reserved );
if (size <= offsetof( IMAGE_LOAD_CONFIG_DIRECTORY64, GuardAddressTakenIatEntryTable )) return;
print_longlong( "GuardAddressTakenIatEntryTable", loadcfg64->GuardAddressTakenIatEntryTable );
print_longlong( "GuardAddressTakenIatEntryCount", loadcfg64->GuardAddressTakenIatEntryCount );
print_longlong( "GuardLongJumpTargetTable", loadcfg64->GuardLongJumpTargetTable );
print_longlong( "GuardLongJumpTargetCount", loadcfg64->GuardLongJumpTargetCount );
if (size <= offsetof( IMAGE_LOAD_CONFIG_DIRECTORY64, DynamicValueRelocTable )) return;
print_longlong( "DynamicValueRelocTable", loadcfg64->DynamicValueRelocTable );
print_longlong( "CHPEMetadataPointer", loadcfg64->CHPEMetadataPointer );
if (size <= offsetof( IMAGE_LOAD_CONFIG_DIRECTORY64, GuardRFFailureRoutine )) return;
print_longlong( "GuardRFFailureRoutine", loadcfg64->GuardRFFailureRoutine );
print_longlong( "GuardRFFailureRoutineFunctionPointer", loadcfg64->GuardRFFailureRoutineFunctionPointer );
print_dword( "DynamicValueRelocTableOffset", loadcfg64->DynamicValueRelocTableOffset );
print_word( "DynamicValueRelocTableSection",loadcfg64->DynamicValueRelocTableSection );
print_word( "Reserved2", loadcfg64->Reserved2 );
if (size <= offsetof( IMAGE_LOAD_CONFIG_DIRECTORY64, GuardRFVerifyStackPointerFunctionPointer )) return;
print_longlong( "GuardRFVerifyStackPointerFunctionPointer", loadcfg64->GuardRFVerifyStackPointerFunctionPointer );
print_dword( "HotPatchTableOffset", loadcfg64->HotPatchTableOffset );
print_dword( "Reserved3", loadcfg64->Reserved3 );
if (size <= offsetof( IMAGE_LOAD_CONFIG_DIRECTORY64, EnclaveConfigurationPointer )) return;
print_longlong( "EnclaveConfigurationPointer", loadcfg64->EnclaveConfigurationPointer );
if (size <= offsetof( IMAGE_LOAD_CONFIG_DIRECTORY64, VolatileMetadataPointer )) return;
print_longlong( "VolatileMetadataPointer", loadcfg64->VolatileMetadataPointer );
if (size <= offsetof( IMAGE_LOAD_CONFIG_DIRECTORY64, GuardEHContinuationTable )) return;
print_longlong( "GuardEHContinuationTable", loadcfg64->GuardEHContinuationTable );
print_longlong( "GuardEHContinuationCount", loadcfg64->GuardEHContinuationCount );
if (size <= offsetof( IMAGE_LOAD_CONFIG_DIRECTORY64, GuardXFGCheckFunctionPointer )) return;
print_longlong( "GuardXFGCheckFunctionPointer", loadcfg64->GuardXFGCheckFunctionPointer );
print_longlong( "GuardXFGDispatchFunctionPointer", loadcfg64->GuardXFGDispatchFunctionPointer );
print_longlong( "GuardXFGTableDispatchFunctionPointer", loadcfg64->GuardXFGTableDispatchFunctionPointer );
if (size <= offsetof( IMAGE_LOAD_CONFIG_DIRECTORY64, CastGuardOsDeterminedFailureMode )) return;
print_longlong( "CastGuardOsDeterminedFailureMode", loadcfg64->CastGuardOsDeterminedFailureMode );
if (size <= offsetof( IMAGE_LOAD_CONFIG_DIRECTORY64, GuardMemcpyFunctionPointer )) return;
print_longlong( "GuardMemcpyFunctionPointer", loadcfg64->GuardMemcpyFunctionPointer );
}
else
{
print_dword( "DeCommitFreeBlockThreshold", loadcfg32->DeCommitFreeBlockThreshold );
print_dword( "DeCommitTotalFreeThreshold", loadcfg32->DeCommitTotalFreeThreshold );
print_dword( "MaximumAllocationSize", loadcfg32->MaximumAllocationSize );
print_dword( "VirtualMemoryThreshold", loadcfg32->VirtualMemoryThreshold );
print_dword( "ProcessHeapFlags", loadcfg32->ProcessHeapFlags );
print_dword( "ProcessAffinityMask", loadcfg32->ProcessAffinityMask );
print_word( "CSDVersion", loadcfg32->CSDVersion );
print_word( "DependentLoadFlags", loadcfg32->DependentLoadFlags );
print_dword( "SecurityCookie", loadcfg32->SecurityCookie );
if (size <= offsetof( IMAGE_LOAD_CONFIG_DIRECTORY32, SEHandlerTable )) return;
print_dword( "SEHandlerTable", loadcfg32->SEHandlerTable );
print_dword( "SEHandlerCount", loadcfg32->SEHandlerCount );
if (size <= offsetof( IMAGE_LOAD_CONFIG_DIRECTORY32, GuardCFCheckFunctionPointer )) return;
print_dword( "GuardCFCheckFunctionPointer", loadcfg32->GuardCFCheckFunctionPointer );
print_dword( "GuardCFDispatchFunctionPointer", loadcfg32->GuardCFDispatchFunctionPointer );
print_dword( "GuardCFFunctionTable", loadcfg32->GuardCFFunctionTable );
print_dword( "GuardCFFunctionCount", loadcfg32->GuardCFFunctionCount );
print_dword( "GuardFlags", loadcfg32->GuardFlags );
if (size <= offsetof( IMAGE_LOAD_CONFIG_DIRECTORY32, CodeIntegrity )) return;
print_word( "CodeIntegrity.Flags", loadcfg32->CodeIntegrity.Flags );
print_word( "CodeIntegrity.Catalog", loadcfg32->CodeIntegrity.Catalog );
print_dword( "CodeIntegrity.CatalogOffset", loadcfg32->CodeIntegrity.CatalogOffset );
print_dword( "CodeIntegrity.Reserved", loadcfg32->CodeIntegrity.Reserved );
if (size <= offsetof( IMAGE_LOAD_CONFIG_DIRECTORY32, GuardAddressTakenIatEntryTable )) return;
print_dword( "GuardAddressTakenIatEntryTable", loadcfg32->GuardAddressTakenIatEntryTable );
print_dword( "GuardAddressTakenIatEntryCount", loadcfg32->GuardAddressTakenIatEntryCount );
print_dword( "GuardLongJumpTargetTable", loadcfg32->GuardLongJumpTargetTable );
print_dword( "GuardLongJumpTargetCount", loadcfg32->GuardLongJumpTargetCount );
if (size <= offsetof( IMAGE_LOAD_CONFIG_DIRECTORY32, DynamicValueRelocTable )) return;
print_dword( "DynamicValueRelocTable", loadcfg32->DynamicValueRelocTable );
print_dword( "CHPEMetadataPointer", loadcfg32->CHPEMetadataPointer );
if (size <= offsetof( IMAGE_LOAD_CONFIG_DIRECTORY32, GuardRFFailureRoutine )) return;
print_dword( "GuardRFFailureRoutine", loadcfg32->GuardRFFailureRoutine );
print_dword( "GuardRFFailureRoutineFunctionPointer", loadcfg32->GuardRFFailureRoutineFunctionPointer );
print_dword( "DynamicValueRelocTableOffset", loadcfg32->DynamicValueRelocTableOffset );
print_word( "DynamicValueRelocTableSection", loadcfg32->DynamicValueRelocTableSection );
print_word( "Reserved2", loadcfg32->Reserved2 );
if (size <= offsetof( IMAGE_LOAD_CONFIG_DIRECTORY32, GuardRFVerifyStackPointerFunctionPointer )) return;
print_dword( "GuardRFVerifyStackPointerFunctionPointer", loadcfg32->GuardRFVerifyStackPointerFunctionPointer );
print_dword( "HotPatchTableOffset", loadcfg32->HotPatchTableOffset );
print_dword( "Reserved3", loadcfg32->Reserved3 );
if (size <= offsetof( IMAGE_LOAD_CONFIG_DIRECTORY32, EnclaveConfigurationPointer )) return;
print_dword( "EnclaveConfigurationPointer", loadcfg32->EnclaveConfigurationPointer );
if (size <= offsetof( IMAGE_LOAD_CONFIG_DIRECTORY32, VolatileMetadataPointer )) return;
print_dword( "VolatileMetadataPointer", loadcfg32->VolatileMetadataPointer );
if (size <= offsetof( IMAGE_LOAD_CONFIG_DIRECTORY32, GuardEHContinuationTable )) return;
print_dword( "GuardEHContinuationTable", loadcfg32->GuardEHContinuationTable );
print_dword( "GuardEHContinuationCount", loadcfg32->GuardEHContinuationCount );
if (size <= offsetof( IMAGE_LOAD_CONFIG_DIRECTORY32, GuardXFGCheckFunctionPointer )) return;
print_dword( "GuardXFGCheckFunctionPointer", loadcfg32->GuardXFGCheckFunctionPointer );
print_dword( "GuardXFGDispatchFunctionPointer", loadcfg32->GuardXFGDispatchFunctionPointer );
print_dword( "GuardXFGTableDispatchFunctionPointer", loadcfg32->GuardXFGTableDispatchFunctionPointer );
if (size <= offsetof( IMAGE_LOAD_CONFIG_DIRECTORY32, CastGuardOsDeterminedFailureMode )) return;
print_dword( "CastGuardOsDeterminedFailureMode", loadcfg32->CastGuardOsDeterminedFailureMode );
if (size <= offsetof( IMAGE_LOAD_CONFIG_DIRECTORY32, GuardMemcpyFunctionPointer )) return;
print_dword( "GuardMemcpyFunctionPointer", loadcfg32->GuardMemcpyFunctionPointer );
const IMAGE_LOAD_CONFIG_DIRECTORY32 *loadcfg32 = dirs[dir];
const IMAGE_LOAD_CONFIG_DIRECTORY64 *loadcfg64 = (void*)loadcfg32;
size = min( sizes[dir], loadcfg32->Size );
if (dir)
printf( "\nAlternate (%s) loadconfig\n",
get_machine_str( PE_alt_headers->FileHeader.Machine ));
else
printf( "Loadconfig\n" );
print_dword( "Size", loadcfg32->Size );
print_dword( "TimeDateStamp", loadcfg32->TimeDateStamp );
print_word( "MajorVersion", loadcfg32->MajorVersion );
print_word( "MinorVersion", loadcfg32->MinorVersion );
print_dword( "GlobalFlagsClear", loadcfg32->GlobalFlagsClear );
print_dword( "GlobalFlagsSet", loadcfg32->GlobalFlagsSet );
print_dword( "CriticalSectionDefaultTimeout", loadcfg32->CriticalSectionDefaultTimeout );
if(PE_nt_headers->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC)
{
print_longlong( "DeCommitFreeBlockThreshold", loadcfg64->DeCommitFreeBlockThreshold );
print_longlong( "DeCommitTotalFreeThreshold", loadcfg64->DeCommitTotalFreeThreshold );
print_longlong( "MaximumAllocationSize", loadcfg64->MaximumAllocationSize );
print_longlong( "VirtualMemoryThreshold", loadcfg64->VirtualMemoryThreshold );
print_dword( "ProcessHeapFlags", loadcfg64->ProcessHeapFlags );
print_longlong( "ProcessAffinityMask", loadcfg64->ProcessAffinityMask );
print_word( "CSDVersion", loadcfg64->CSDVersion );
print_word( "DependentLoadFlags", loadcfg64->DependentLoadFlags );
print_longlong( "SecurityCookie", loadcfg64->SecurityCookie );
if (size <= offsetof( IMAGE_LOAD_CONFIG_DIRECTORY64, SEHandlerTable )) return;
print_longlong( "SEHandlerTable", loadcfg64->SEHandlerTable );
print_longlong( "SEHandlerCount", loadcfg64->SEHandlerCount );
if (size <= offsetof( IMAGE_LOAD_CONFIG_DIRECTORY64, GuardCFCheckFunctionPointer )) return;
print_longlong( "GuardCFCheckFunctionPointer", loadcfg64->GuardCFCheckFunctionPointer );
print_longlong( "GuardCFDispatchFunctionPointer", loadcfg64->GuardCFDispatchFunctionPointer );
print_longlong( "GuardCFFunctionTable", loadcfg64->GuardCFFunctionTable );
print_longlong( "GuardCFFunctionCount", loadcfg64->GuardCFFunctionCount );
print_dword( "GuardFlags", loadcfg64->GuardFlags );
if (size <= offsetof( IMAGE_LOAD_CONFIG_DIRECTORY64, CodeIntegrity )) return;
print_word( "CodeIntegrity.Flags", loadcfg64->CodeIntegrity.Flags );
print_word( "CodeIntegrity.Catalog", loadcfg64->CodeIntegrity.Catalog );
print_dword( "CodeIntegrity.CatalogOffset", loadcfg64->CodeIntegrity.CatalogOffset );
print_dword( "CodeIntegrity.Reserved", loadcfg64->CodeIntegrity.Reserved );
if (size <= offsetof( IMAGE_LOAD_CONFIG_DIRECTORY64, GuardAddressTakenIatEntryTable )) return;
print_longlong( "GuardAddressTakenIatEntryTable", loadcfg64->GuardAddressTakenIatEntryTable );
print_longlong( "GuardAddressTakenIatEntryCount", loadcfg64->GuardAddressTakenIatEntryCount );
print_longlong( "GuardLongJumpTargetTable", loadcfg64->GuardLongJumpTargetTable );
print_longlong( "GuardLongJumpTargetCount", loadcfg64->GuardLongJumpTargetCount );
if (size <= offsetof( IMAGE_LOAD_CONFIG_DIRECTORY64, DynamicValueRelocTable )) return;
print_longlong( "DynamicValueRelocTable", loadcfg64->DynamicValueRelocTable );
print_longlong( "CHPEMetadataPointer", loadcfg64->CHPEMetadataPointer );
if (size <= offsetof( IMAGE_LOAD_CONFIG_DIRECTORY64, GuardRFFailureRoutine )) return;
print_longlong( "GuardRFFailureRoutine", loadcfg64->GuardRFFailureRoutine );
print_longlong( "GuardRFFailureRoutineFunctionPointer", loadcfg64->GuardRFFailureRoutineFunctionPointer );
print_dword( "DynamicValueRelocTableOffset", loadcfg64->DynamicValueRelocTableOffset );
print_word( "DynamicValueRelocTableSection",loadcfg64->DynamicValueRelocTableSection );
print_word( "Reserved2", loadcfg64->Reserved2 );
if (size <= offsetof( IMAGE_LOAD_CONFIG_DIRECTORY64, GuardRFVerifyStackPointerFunctionPointer )) return;
print_longlong( "GuardRFVerifyStackPointerFunctionPointer", loadcfg64->GuardRFVerifyStackPointerFunctionPointer );
print_dword( "HotPatchTableOffset", loadcfg64->HotPatchTableOffset );
print_dword( "Reserved3", loadcfg64->Reserved3 );
if (size <= offsetof( IMAGE_LOAD_CONFIG_DIRECTORY64, EnclaveConfigurationPointer )) return;
print_longlong( "EnclaveConfigurationPointer", loadcfg64->EnclaveConfigurationPointer );
if (size <= offsetof( IMAGE_LOAD_CONFIG_DIRECTORY64, VolatileMetadataPointer )) return;
print_longlong( "VolatileMetadataPointer", loadcfg64->VolatileMetadataPointer );
if (size <= offsetof( IMAGE_LOAD_CONFIG_DIRECTORY64, GuardEHContinuationTable )) return;
print_longlong( "GuardEHContinuationTable", loadcfg64->GuardEHContinuationTable );
print_longlong( "GuardEHContinuationCount", loadcfg64->GuardEHContinuationCount );
if (size <= offsetof( IMAGE_LOAD_CONFIG_DIRECTORY64, GuardXFGCheckFunctionPointer )) return;
print_longlong( "GuardXFGCheckFunctionPointer", loadcfg64->GuardXFGCheckFunctionPointer );
print_longlong( "GuardXFGDispatchFunctionPointer", loadcfg64->GuardXFGDispatchFunctionPointer );
print_longlong( "GuardXFGTableDispatchFunctionPointer", loadcfg64->GuardXFGTableDispatchFunctionPointer );
if (size <= offsetof( IMAGE_LOAD_CONFIG_DIRECTORY64, CastGuardOsDeterminedFailureMode )) return;
print_longlong( "CastGuardOsDeterminedFailureMode", loadcfg64->CastGuardOsDeterminedFailureMode );
if (size <= offsetof( IMAGE_LOAD_CONFIG_DIRECTORY64, GuardMemcpyFunctionPointer )) return;
print_longlong( "GuardMemcpyFunctionPointer", loadcfg64->GuardMemcpyFunctionPointer );
}
else
{
print_dword( "DeCommitFreeBlockThreshold", loadcfg32->DeCommitFreeBlockThreshold );
print_dword( "DeCommitTotalFreeThreshold", loadcfg32->DeCommitTotalFreeThreshold );
print_dword( "MaximumAllocationSize", loadcfg32->MaximumAllocationSize );
print_dword( "VirtualMemoryThreshold", loadcfg32->VirtualMemoryThreshold );
print_dword( "ProcessHeapFlags", loadcfg32->ProcessHeapFlags );
print_dword( "ProcessAffinityMask", loadcfg32->ProcessAffinityMask );
print_word( "CSDVersion", loadcfg32->CSDVersion );
print_word( "DependentLoadFlags", loadcfg32->DependentLoadFlags );
print_dword( "SecurityCookie", loadcfg32->SecurityCookie );
if (size <= offsetof( IMAGE_LOAD_CONFIG_DIRECTORY32, SEHandlerTable )) return;
print_dword( "SEHandlerTable", loadcfg32->SEHandlerTable );
print_dword( "SEHandlerCount", loadcfg32->SEHandlerCount );
if (size <= offsetof( IMAGE_LOAD_CONFIG_DIRECTORY32, GuardCFCheckFunctionPointer )) return;
print_dword( "GuardCFCheckFunctionPointer", loadcfg32->GuardCFCheckFunctionPointer );
print_dword( "GuardCFDispatchFunctionPointer", loadcfg32->GuardCFDispatchFunctionPointer );
print_dword( "GuardCFFunctionTable", loadcfg32->GuardCFFunctionTable );
print_dword( "GuardCFFunctionCount", loadcfg32->GuardCFFunctionCount );
print_dword( "GuardFlags", loadcfg32->GuardFlags );
if (size <= offsetof( IMAGE_LOAD_CONFIG_DIRECTORY32, CodeIntegrity )) return;
print_word( "CodeIntegrity.Flags", loadcfg32->CodeIntegrity.Flags );
print_word( "CodeIntegrity.Catalog", loadcfg32->CodeIntegrity.Catalog );
print_dword( "CodeIntegrity.CatalogOffset", loadcfg32->CodeIntegrity.CatalogOffset );
print_dword( "CodeIntegrity.Reserved", loadcfg32->CodeIntegrity.Reserved );
if (size <= offsetof( IMAGE_LOAD_CONFIG_DIRECTORY32, GuardAddressTakenIatEntryTable )) return;
print_dword( "GuardAddressTakenIatEntryTable", loadcfg32->GuardAddressTakenIatEntryTable );
print_dword( "GuardAddressTakenIatEntryCount", loadcfg32->GuardAddressTakenIatEntryCount );
print_dword( "GuardLongJumpTargetTable", loadcfg32->GuardLongJumpTargetTable );
print_dword( "GuardLongJumpTargetCount", loadcfg32->GuardLongJumpTargetCount );
if (size <= offsetof( IMAGE_LOAD_CONFIG_DIRECTORY32, DynamicValueRelocTable )) return;
print_dword( "DynamicValueRelocTable", loadcfg32->DynamicValueRelocTable );
print_dword( "CHPEMetadataPointer", loadcfg32->CHPEMetadataPointer );
if (size <= offsetof( IMAGE_LOAD_CONFIG_DIRECTORY32, GuardRFFailureRoutine )) return;
print_dword( "GuardRFFailureRoutine", loadcfg32->GuardRFFailureRoutine );
print_dword( "GuardRFFailureRoutineFunctionPointer", loadcfg32->GuardRFFailureRoutineFunctionPointer );
print_dword( "DynamicValueRelocTableOffset", loadcfg32->DynamicValueRelocTableOffset );
print_word( "DynamicValueRelocTableSection", loadcfg32->DynamicValueRelocTableSection );
print_word( "Reserved2", loadcfg32->Reserved2 );
if (size <= offsetof( IMAGE_LOAD_CONFIG_DIRECTORY32, GuardRFVerifyStackPointerFunctionPointer )) return;
print_dword( "GuardRFVerifyStackPointerFunctionPointer", loadcfg32->GuardRFVerifyStackPointerFunctionPointer );
print_dword( "HotPatchTableOffset", loadcfg32->HotPatchTableOffset );
print_dword( "Reserved3", loadcfg32->Reserved3 );
if (size <= offsetof( IMAGE_LOAD_CONFIG_DIRECTORY32, EnclaveConfigurationPointer )) return;
print_dword( "EnclaveConfigurationPointer", loadcfg32->EnclaveConfigurationPointer );
if (size <= offsetof( IMAGE_LOAD_CONFIG_DIRECTORY32, VolatileMetadataPointer )) return;
print_dword( "VolatileMetadataPointer", loadcfg32->VolatileMetadataPointer );
if (size <= offsetof( IMAGE_LOAD_CONFIG_DIRECTORY32, GuardEHContinuationTable )) return;
print_dword( "GuardEHContinuationTable", loadcfg32->GuardEHContinuationTable );
print_dword( "GuardEHContinuationCount", loadcfg32->GuardEHContinuationCount );
if (size <= offsetof( IMAGE_LOAD_CONFIG_DIRECTORY32, GuardXFGCheckFunctionPointer )) return;
print_dword( "GuardXFGCheckFunctionPointer", loadcfg32->GuardXFGCheckFunctionPointer );
print_dword( "GuardXFGDispatchFunctionPointer", loadcfg32->GuardXFGDispatchFunctionPointer );
print_dword( "GuardXFGTableDispatchFunctionPointer", loadcfg32->GuardXFGTableDispatchFunctionPointer );
if (size <= offsetof( IMAGE_LOAD_CONFIG_DIRECTORY32, CastGuardOsDeterminedFailureMode )) return;
print_dword( "CastGuardOsDeterminedFailureMode", loadcfg32->CastGuardOsDeterminedFailureMode );
if (size <= offsetof( IMAGE_LOAD_CONFIG_DIRECTORY32, GuardMemcpyFunctionPointer )) return;
print_dword( "GuardMemcpyFunctionPointer", loadcfg32->GuardMemcpyFunctionPointer );
}
}
}
@ -2137,35 +2184,42 @@ static void dump_dynamic_relocs( const char *ptr, unsigned int size, ULONGLONG s
}
}
static void dump_dir_dynamic_reloc(void)
static const IMAGE_DYNAMIC_RELOCATION_TABLE *get_dyn_reloc_table(void)
{
unsigned int size, section, offset;
const char *ptr, *end;
const IMAGE_SECTION_HEADER *sec;
const IMAGE_DYNAMIC_RELOCATION_TABLE *table;
if (PE_nt_headers->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC)
{
const IMAGE_LOAD_CONFIG_DIRECTORY64 *cfg = get_dir_and_size(IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG, &size);
if (!cfg) return;
if (!cfg) return NULL;
size = min( size, cfg->Size );
if (size <= offsetof( IMAGE_LOAD_CONFIG_DIRECTORY64, DynamicValueRelocTableSection )) return;
if (size <= offsetof( IMAGE_LOAD_CONFIG_DIRECTORY64, DynamicValueRelocTableSection )) return NULL;
offset = cfg->DynamicValueRelocTableOffset;
section = cfg->DynamicValueRelocTableSection;
}
else
{
const IMAGE_LOAD_CONFIG_DIRECTORY32 *cfg = get_dir_and_size(IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG, &size);
if (!cfg) return;
if (!cfg) return NULL;
size = min( size, cfg->Size );
if (size <= offsetof( IMAGE_LOAD_CONFIG_DIRECTORY32, DynamicValueRelocTableSection )) return;
if (size <= offsetof( IMAGE_LOAD_CONFIG_DIRECTORY32, DynamicValueRelocTableSection )) return NULL;
offset = cfg->DynamicValueRelocTableOffset;
section = cfg->DynamicValueRelocTableSection;
}
if (!section || section > PE_nt_headers->FileHeader.NumberOfSections) return;
if (!section || section > PE_nt_headers->FileHeader.NumberOfSections) return NULL;
sec = IMAGE_FIRST_SECTION( PE_nt_headers ) + section - 1;
if (offset >= sec->SizeOfRawData) return;
table = PRD( sec->PointerToRawData + offset, sizeof(*table) );
if (offset >= sec->SizeOfRawData) return NULL;
return PRD( sec->PointerToRawData + offset, sizeof(*table) );
}
static void dump_dir_dynamic_reloc(void)
{
const char *ptr, *end;
const IMAGE_DYNAMIC_RELOCATION_TABLE *table = get_dyn_reloc_table();
if (!table) return;
printf( "Dynamic relocations (version %u)\n\n", (UINT)table->Version );
ptr = (const char *)(table + 1);
@ -2207,6 +2261,117 @@ static void dump_dir_dynamic_reloc(void)
printf( "\n" );
}
static const IMAGE_BASE_RELOCATION *get_armx_relocs( unsigned int *size )
{
const char *ptr, *end;
const IMAGE_DYNAMIC_RELOCATION_TABLE *table = get_dyn_reloc_table();
if (!table) return NULL;
ptr = (const char *)(table + 1);
end = ptr + table->Size;
while (ptr < end)
{
switch (table->Version)
{
case 1:
if (PE_nt_headers->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC)
{
const IMAGE_DYNAMIC_RELOCATION64 *reloc = (const IMAGE_DYNAMIC_RELOCATION64 *)ptr;
if (reloc->Symbol == IMAGE_DYNAMIC_RELOCATION_ARM64X)
{
*size = reloc->BaseRelocSize;
return (const IMAGE_BASE_RELOCATION *)(reloc + 1);
}
ptr += sizeof(*reloc) + reloc->BaseRelocSize;
}
else
{
const IMAGE_DYNAMIC_RELOCATION32 *reloc = (const IMAGE_DYNAMIC_RELOCATION32 *)ptr;
if (reloc->Symbol == IMAGE_DYNAMIC_RELOCATION_ARM64X)
{
*size = reloc->BaseRelocSize;
return (const IMAGE_BASE_RELOCATION *)(reloc + 1);
}
ptr += sizeof(*reloc) + reloc->BaseRelocSize;
}
break;
case 2:
if (PE_nt_headers->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC)
{
const IMAGE_DYNAMIC_RELOCATION64_V2 *reloc = (const IMAGE_DYNAMIC_RELOCATION64_V2 *)ptr;
if (reloc->Symbol == IMAGE_DYNAMIC_RELOCATION_ARM64X)
{
*size = reloc->FixupInfoSize;
return (const IMAGE_BASE_RELOCATION *)(reloc + 1);
}
ptr += reloc->HeaderSize + reloc->FixupInfoSize;
}
else
{
const IMAGE_DYNAMIC_RELOCATION32_V2 *reloc = (const IMAGE_DYNAMIC_RELOCATION32_V2 *)ptr;
if (reloc->Symbol == IMAGE_DYNAMIC_RELOCATION_ARM64X)
{
*size = reloc->FixupInfoSize;
return (const IMAGE_BASE_RELOCATION *)(reloc + 1);
}
ptr += reloc->HeaderSize + reloc->FixupInfoSize;
}
break;
}
}
return NULL;
}
static const IMAGE_NT_HEADERS32 *get_alt_header( void )
{
unsigned int page_size, size;
const IMAGE_BASE_RELOCATION *end, *reloc = get_armx_relocs( &size );
char *alt_dos;
const IMAGE_NT_HEADERS32 *hdr;
if (!reloc) return NULL;
page_size = PE_nt_headers->OptionalHeader.SectionAlignment;
alt_dos = malloc( page_size );
memcpy( alt_dos, PRD(0, page_size), page_size );
end = (const IMAGE_BASE_RELOCATION *)((const char *)reloc + size);
hdr = (const IMAGE_NT_HEADERS32 *)(alt_dos + ((IMAGE_DOS_HEADER *)alt_dos)->e_lfanew);
while (reloc < end - 1 && reloc->SizeOfBlock)
{
const USHORT *rel = (const USHORT *)(reloc + 1);
const USHORT *rel_end = (const USHORT *)reloc + reloc->SizeOfBlock / sizeof(USHORT);
if (!reloc->VirtualAddress) /* only apply relocs to page 0 */
{
while (rel < rel_end && *rel)
{
USHORT offset = *rel & 0xfff;
USHORT type = (*rel >> 12) & 3;
USHORT arg = *rel >> 14;
int val;
rel++;
switch (type)
{
case 0: /* zero-fill */
memset( alt_dos + offset, 0, 1 << arg );
break;
case 1: /* set value */
memcpy( alt_dos + offset, rel, 1 << arg );
rel += (1 << arg) / sizeof(USHORT);
break;
case 2: /* add value */
val = (unsigned int)*rel++ * ((arg & 2) ? 8 : 4);
if (arg & 1) val = -val;
*(int *)(alt_dos + offset) += val;
break;
}
}
}
reloc = (const IMAGE_BASE_RELOCATION *)rel_end;
}
return hdr;
}
static void dump_dir_reloc(void)
{
unsigned int i, size = 0;
@ -2673,6 +2838,7 @@ enum FileSig get_kind_exec(void)
void pe_dump(void)
{
PE_nt_headers = get_nt_header();
PE_alt_headers = get_alt_header();
print_fake_dll();
if (globals.do_dumpheader)