const char *pe_directory_name(ImageDirectoryEntry entry) { typedef struct { ImageDirectoryEntry entry; const char * const name; } ImageDirectoryEntryName; #define LIBPE_ENTRY(v) { v, # v } static const ImageDirectoryEntryName names[] = { LIBPE_ENTRY(IMAGE_DIRECTORY_ENTRY_EXPORT), LIBPE_ENTRY(IMAGE_DIRECTORY_ENTRY_IMPORT), LIBPE_ENTRY(IMAGE_DIRECTORY_ENTRY_RESOURCE), LIBPE_ENTRY(IMAGE_DIRECTORY_ENTRY_EXCEPTION), LIBPE_ENTRY(IMAGE_DIRECTORY_ENTRY_SECURITY), LIBPE_ENTRY(IMAGE_DIRECTORY_ENTRY_BASERELOC), LIBPE_ENTRY(IMAGE_DIRECTORY_ENTRY_DEBUG), LIBPE_ENTRY(IMAGE_DIRECTORY_ENTRY_ARCHITECTURE), LIBPE_ENTRY(IMAGE_DIRECTORY_ENTRY_GLOBALPTR), LIBPE_ENTRY(IMAGE_DIRECTORY_ENTRY_TLS), LIBPE_ENTRY(IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG), LIBPE_ENTRY(IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT), LIBPE_ENTRY(IMAGE_DIRECTORY_ENTRY_IAT), LIBPE_ENTRY(IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT), LIBPE_ENTRY(IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR), LIBPE_ENTRY(IMAGE_DIRECTORY_RESERVED) }; #undef LIBPE_ENTRY static const size_t max_index = LIBPE_SIZEOF_ARRAY(names); for (size_t i=0; i < max_index; i++) { if (entry == names[i].entry) return names[i].name; } return NULL; }
const char *pe_image_dllcharacteristic_name(ImageDllCharacteristics characteristic) { typedef struct { ImageDllCharacteristics characteristic; const char * const name; } ImageDllCharacteristicsName; #define LIBPE_ENTRY(v) { v, # v } static const ImageDllCharacteristicsName names[] = { LIBPE_ENTRY(IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE), LIBPE_ENTRY(IMAGE_DLLCHARACTERISTICS_FORCE_INTEGRITY), LIBPE_ENTRY(IMAGE_DLLCHARACTERISTICS_NX_COMPAT), LIBPE_ENTRY(IMAGE_DLLCHARACTERISTICS_NO_ISOLATION), LIBPE_ENTRY(IMAGE_DLLCHARACTERISTICS_NO_SEH), LIBPE_ENTRY(IMAGE_DLLCHARACTERISTICS_NO_BIND), LIBPE_ENTRY(IMAGE_DLLCHARACTERISTICS_WDM_DRIVER), LIBPE_ENTRY(IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE) }; #undef LIBPE_ENTRY static const size_t max_index = LIBPE_SIZEOF_ARRAY(names); for (size_t i=0; i < max_index; i++) { if (characteristic == names[i].characteristic) return names[i].name; } return NULL; }
const char *pe_windows_subsystem_name(WindowsSubsystem subsystem) { typedef struct { WindowsSubsystem subsystem; const char * const name; } WindowsSubsystemName; #define LIBPE_ENTRY(v) { v, # v } static const WindowsSubsystemName names[] = { LIBPE_ENTRY(IMAGE_SUBSYSTEM_UNKNOWN), LIBPE_ENTRY(IMAGE_SUBSYSTEM_NATIVE), LIBPE_ENTRY(IMAGE_SUBSYSTEM_WINDOWS_GUI), LIBPE_ENTRY(IMAGE_SUBSYSTEM_WINDOWS_CUI), LIBPE_ENTRY(IMAGE_SUBSYSTEM_OS2_CUI), LIBPE_ENTRY(IMAGE_SUBSYSTEM_POSIX_CUI), LIBPE_ENTRY(IMAGE_SUBSYSTEM_WINDOWS_CE_GUI), LIBPE_ENTRY(IMAGE_SUBSYSTEM_EFI_APPLICATION), LIBPE_ENTRY(IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER), LIBPE_ENTRY(IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER), LIBPE_ENTRY(IMAGE_SUBSYSTEM_EFI_ROM), LIBPE_ENTRY(IMAGE_SUBSYSTEM_XBOX), LIBPE_ENTRY(IMAGE_SUBSYSTEM_WINDOWS_BOOT_APPLICATION) }; #undef LIBPE_ENTRY static const size_t max_index = LIBPE_SIZEOF_ARRAY(names); for (size_t i=0; i < max_index; i++) { if (subsystem == names[i].subsystem) return names[i].name; } return NULL; }
const char *pe_image_characteristic_name(ImageCharacteristics characteristic) { typedef struct { ImageCharacteristics characteristic; const char * const name; } ImageCharacteristicsName; #define LIBPE_ENTRY(v) { v, # v } static const ImageCharacteristicsName names[] = { LIBPE_ENTRY(IMAGE_FILE_RELOCS_STRIPPED), LIBPE_ENTRY(IMAGE_FILE_EXECUTABLE_IMAGE), LIBPE_ENTRY(IMAGE_FILE_LINE_NUMS_STRIPPED), LIBPE_ENTRY(IMAGE_FILE_LOCAL_SYMS_STRIPPED), LIBPE_ENTRY(IMAGE_FILE_AGGRESSIVE_WS_TRIM), LIBPE_ENTRY(IMAGE_FILE_LARGE_ADDRESS_AWARE), LIBPE_ENTRY(IMAGE_FILE_RESERVED), LIBPE_ENTRY(IMAGE_FILE_BYTES_REVERSED_LO), LIBPE_ENTRY(IMAGE_FILE_32BIT_MACHINE), LIBPE_ENTRY(IMAGE_FILE_DEBUG_STRIPPED), LIBPE_ENTRY(IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP), LIBPE_ENTRY(IMAGE_FILE_NET_RUN_FROM_SWAP), LIBPE_ENTRY(IMAGE_FILE_SYSTEM), LIBPE_ENTRY(IMAGE_FILE_DLL), LIBPE_ENTRY(IMAGE_FILE_UP_SYSTEM_ONLY), LIBPE_ENTRY(IMAGE_FILE_BYTES_REVERSED_HI) }; #undef LIBPE_ENTRY static const size_t max_index = LIBPE_SIZEOF_ARRAY(names); for (size_t i=0; i < max_index; i++) { if (characteristic == names[i].characteristic) return names[i].name; } return NULL; }
/* MEW Packer and others basically stores the entrypoint in a section marked only as readable (without executable and/or writable flags) Windows Loader still executes the binary */ static bool generic_packer(pe_ctx_t *ctx, uint64_t entrypoint) { IMAGE_SECTION_HEADER *section = pe_rva2section(ctx, entrypoint); if (section == NULL) return false; // we count the flags for the section and if there is more than // 2 it means we don't have the mew_packer const SectionCharacteristics invalid_flags[] = { IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE }; // MEW never leave EP in .text section if (memcmp(section->Name, ".text", 5) == 0) return false; unsigned short flags_count = 0; for (size_t i=0; i < LIBPE_SIZEOF_ARRAY(invalid_flags); i++) { if (section->Characteristics & invalid_flags[i]) flags_count++; } return flags_count < 3; }
const char *pe_error_msg(pe_err_e error) { static const char * const errors[] = { "no error", // LIBPE_E_OK, "allocation failure", // LIBPE_E_ALLOCATION_FAILURE, "open() failed", // LIBPE_E_OPEN_FAILED, "fdopen() failed", // LIBPE_E_FDOPEN_FAILED, "fstat() failed", // LIBPE_E_FSTAT_FAILED, "not a regular file", // LIBPE_E_NOT_A_FILE, "not a PE file", // LIBPE_E_NOT_A_PE_FILE, "invalid e_lfanew", // LIBPE_E_INVALID_LFANEW, "missing COFF header", // LIBPE_E_MISSING_COFF_HEADER, "missing OPTIONAL header", // LIBPE_E_MISSING_OPTIONAL_HEADER, "invalid signature", // LIBPE_E_INVALID_SIGNATURE, "unsupported image format", // LIBPE_E_UNSUPPORTED_IMAGE, "mmap() failed", // LIBPE_E_MMAP_FAILED, "munmap() failed", // LIBPE_E_MUNMAP_FAILED, "close() failed", // LIBPE_E_CLOSE_FAILED, "too many directories", // LIBPE_E_TOO_MANY_DIRECTORIES, "too many sections", // LIBPE_E_TOO_MANY_SECTIONS, }; static const size_t index_max = LIBPE_SIZEOF_ARRAY(errors); size_t index = index_max + error; return (index < index_max) ? errors[index] : (index == index_max) ? errors[0] // LIBPE_E_OK : "invalid error code"; }
static const RESOURCE_ENTRY * getResourceEntryByNameOffset(uint32_t nameOffset) { for (size_t i = 0; i < LIBPE_SIZEOF_ARRAY(resource_types); i++) { if (resource_types[i].nameOffset == nameOffset) return &resource_types[i]; } return NULL; }
const char *pe_section_characteristic_name(SectionCharacteristics characteristic) { typedef struct { SectionCharacteristics characteristic; const char * const name; } SectionCharacteristicsName; #define LIBPE_ENTRY(v) { v, # v } static const SectionCharacteristicsName names[] = { LIBPE_ENTRY(IMAGE_SCN_TYPE_NO_PAD), LIBPE_ENTRY(IMAGE_SCN_CNT_CODE), LIBPE_ENTRY(IMAGE_SCN_CNT_INITIALIZED_DATA), LIBPE_ENTRY(IMAGE_SCN_CNT_UNINITIALIZED_DATA), LIBPE_ENTRY(IMAGE_SCN_LNK_OTHER), LIBPE_ENTRY(IMAGE_SCN_LNK_INFO), LIBPE_ENTRY(IMAGE_SCN_LNK_REMOVE), LIBPE_ENTRY(IMAGE_SCN_LNK_COMDAT), LIBPE_ENTRY(IMAGE_SCN_NO_DEFER_SPEC_EXC), LIBPE_ENTRY(IMAGE_SCN_GPREL), LIBPE_ENTRY(IMAGE_SCN_MEM_PURGEABLE), LIBPE_ENTRY(IMAGE_SCN_MEM_LOCKED), LIBPE_ENTRY(IMAGE_SCN_MEM_PRELOAD), LIBPE_ENTRY(IMAGE_SCN_ALIGN_1BYTES), LIBPE_ENTRY(IMAGE_SCN_ALIGN_2BYTES), LIBPE_ENTRY(IMAGE_SCN_ALIGN_4BYTES), LIBPE_ENTRY(IMAGE_SCN_ALIGN_8BYTES), LIBPE_ENTRY(IMAGE_SCN_ALIGN_16BYTES), LIBPE_ENTRY(IMAGE_SCN_ALIGN_32BYTES), LIBPE_ENTRY(IMAGE_SCN_ALIGN_64BYTES), LIBPE_ENTRY(IMAGE_SCN_ALIGN_128BYTES), LIBPE_ENTRY(IMAGE_SCN_ALIGN_256BYTES), LIBPE_ENTRY(IMAGE_SCN_ALIGN_512BYTES), LIBPE_ENTRY(IMAGE_SCN_ALIGN_1024BYTES), LIBPE_ENTRY(IMAGE_SCN_ALIGN_2048BYTES), LIBPE_ENTRY(IMAGE_SCN_ALIGN_4096BYTES), LIBPE_ENTRY(IMAGE_SCN_ALIGN_8192BYTES), LIBPE_ENTRY(IMAGE_SCN_LNK_NRELOC_OVFL), LIBPE_ENTRY(IMAGE_SCN_MEM_DISCARDABLE), LIBPE_ENTRY(IMAGE_SCN_MEM_NOT_CACHED), LIBPE_ENTRY(IMAGE_SCN_MEM_NOT_PAGED), LIBPE_ENTRY(IMAGE_SCN_MEM_SHARED), LIBPE_ENTRY(IMAGE_SCN_MEM_EXECUTE), LIBPE_ENTRY(IMAGE_SCN_MEM_READ), LIBPE_ENTRY(IMAGE_SCN_MEM_WRITE) }; #undef LIBPE_ENTRY static const size_t max_index = LIBPE_SIZEOF_ARRAY(names); for (size_t i=0; i < max_index; i++) { if (characteristic == names[i].characteristic) return names[i].name; } return NULL; }
const char *pe_machine_type_name(MachineType type) { typedef struct { MachineType type; const char * const name; } MachineEntry; #define LIBPE_ENTRY(v) { v, # v } static const MachineEntry names[] = { LIBPE_ENTRY(IMAGE_FILE_MACHINE_UNKNOWN), LIBPE_ENTRY(IMAGE_FILE_MACHINE_AM33), LIBPE_ENTRY(IMAGE_FILE_MACHINE_AMD64), LIBPE_ENTRY(IMAGE_FILE_MACHINE_ARM), LIBPE_ENTRY(IMAGE_FILE_MACHINE_ARMV7), LIBPE_ENTRY(IMAGE_FILE_MACHINE_CEE), LIBPE_ENTRY(IMAGE_FILE_MACHINE_EBC), LIBPE_ENTRY(IMAGE_FILE_MACHINE_I386), LIBPE_ENTRY(IMAGE_FILE_MACHINE_IA64), LIBPE_ENTRY(IMAGE_FILE_MACHINE_M32R), LIBPE_ENTRY(IMAGE_FILE_MACHINE_MIPS16), LIBPE_ENTRY(IMAGE_FILE_MACHINE_MIPSFPU), LIBPE_ENTRY(IMAGE_FILE_MACHINE_MIPSFPU16), LIBPE_ENTRY(IMAGE_FILE_MACHINE_POWERPC), LIBPE_ENTRY(IMAGE_FILE_MACHINE_POWERPCFP), LIBPE_ENTRY(IMAGE_FILE_MACHINE_R4000), LIBPE_ENTRY(IMAGE_FILE_MACHINE_SH3), LIBPE_ENTRY(IMAGE_FILE_MACHINE_SH3DSP), LIBPE_ENTRY(IMAGE_FILE_MACHINE_SH4), LIBPE_ENTRY(IMAGE_FILE_MACHINE_SH5), LIBPE_ENTRY(IMAGE_FILE_MACHINE_THUMB), LIBPE_ENTRY(IMAGE_FILE_MACHINE_WCEMIPSV2) }; #undef LIBPE_ENTRY static const size_t max_index = LIBPE_SIZEOF_ARRAY(names); for (size_t i=0; i < max_index; i++) { if (type == names[i].type) return names[i].name; } return NULL; }