diff --git a/docs/modules/pe.rst b/docs/modules/pe.rst index 30ba89476a..4458014bbe 100644 --- a/docs/modules/pe.rst +++ b/docs/modules/pe.rst @@ -32,12 +32,6 @@ write more expressive and targeted rules. Let's see some examples: pe.characteristics & pe.DLL } - rule is_pe - { - condition: - pe.is_pe - } - Reference --------- @@ -69,16 +63,6 @@ Reference .. c:type:: MACHINE_SH5 .. c:type:: MACHINE_THUMB .. c:type:: MACHINE_WCEMIPSV2 - .. c:type:: MACHINE_TARGET_HOST - .. c:type:: MACHINE_R3000 - .. c:type:: MACHINE_R10000 - .. c:type:: MACHINE_ALPHA - .. c:type:: MACHINE_SH3E - .. c:type:: MACHINE_ALPHA64 - .. c:type:: MACHINE_AXP64 - .. c:type:: MACHINE_TRICORE - .. c:type:: MACHINE_CEF - .. c:type:: MACHINE_CEE *Example: pe.machine == pe.MACHINE_AMD64* @@ -111,7 +95,6 @@ Reference .. c:type:: SUBSYSTEM_EFI_APPLICATION .. c:type:: SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER .. c:type:: SUBSYSTEM_EFI_RUNTIME_DRIVER - .. c:type:: SUBSYSTEM_EFI_ROM_IMAGE .. c:type:: SUBSYSTEM_XBOX .. c:type:: SUBSYSTEM_WINDOWS_BOOT_APPLICATION @@ -119,9 +102,7 @@ Reference .. c:type:: timestamp - PE timestamp, as an epoch integer. - - *Example: pe.timestamp >= 1424563200* + PE timestamp. .. c:type:: pointer_to_symbol_table @@ -151,13 +132,6 @@ Reference Value of IMAGE_OPTIONAL_HEADER::Magic. - Integer with one of the following values: - - .. c:type:: IMAGE_NT_OPTIONAL_HDR32_MAGIC - .. c:type:: IMAGE_NT_OPTIONAL_HDR64_MAGIC - .. c:type:: IMAGE_ROM_OPTIONAL_HDR_MAGIC - - .. c:type:: size_of_code .. versionadded:: 3.8.0 @@ -177,17 +151,10 @@ Reference .. c:type:: entry_point - Entry point file offset or virtual address depending on whether YARA is + Entry point raw offset or virtual address depending on whether YARA is scanning a file or process memory respectively. This is equivalent to the deprecated ``entrypoint`` keyword. -.. c:type:: entry_point_raw - - Entry point raw value from the optional header of the PE. This value is not - converted to a file offset or an RVA. - - .. versionadded:: 4.1.0 - .. c:type:: base_of_code .. versionadded:: 3.8.0 @@ -369,10 +336,6 @@ Reference characteristics can be inspected by performing a bitwise AND operation with the following constants: - .. c:type:: HIGH_ENTROPY_VA - - ASLR with 64 bit address space. - .. c:type:: DYNAMIC_BASE File can be relocated - also marks the file as ASLR compatible @@ -389,18 +352,10 @@ Reference set to use SafeSEH .. c:type:: NO_BIND - .. c:type:: APPCONTAINER - - Image should execute in an AppContainer - .. c:type:: WDM_DRIVER Marks the file as a Windows Driver Model (WDM) device driver. - .. c:type:: GUARD_CF - - Image supports Control Flow Guard. - .. c:type:: TERMINAL_SERVER_AWARE Marks the file as terminal server compatible @@ -493,28 +448,6 @@ Reference Data directory for debug information. - IMAGE_DEBUG_DIRECTORY::Type values: - - .. c:type:: IMAGE_DEBUG_TYPE_UNKNOWN - .. c:type:: IMAGE_DEBUG_TYPE_COFF - .. c:type:: IMAGE_DEBUG_TYPE_CODEVIEW - .. c:type:: IMAGE_DEBUG_TYPE_FPO - .. c:type:: IMAGE_DEBUG_TYPE_MISC - .. c:type:: IMAGE_DEBUG_TYPE_EXCEPTION - .. c:type:: IMAGE_DEBUG_TYPE_FIXUP - .. c:type:: IMAGE_DEBUG_TYPE_OMAP_TO_SRC - .. c:type:: IMAGE_DEBUG_TYPE_OMAP_FROM_SRC - .. c:type:: IMAGE_DEBUG_TYPE_BORLAND - .. c:type:: IMAGE_DEBUG_TYPE_RESERVED10 - .. c:type:: IMAGE_DEBUG_TYPE_CLSID - .. c:type:: IMAGE_DEBUG_TYPE_VC_FEATURE - .. c:type:: IMAGE_DEBUG_TYPE_POGO - .. c:type:: IMAGE_DEBUG_TYPE_ILTCG - .. c:type:: IMAGE_DEBUG_TYPE_MPX - .. c:type:: IMAGE_DEBUG_TYPE_REPRO - - .. c:type:: IMAGE_DIRECTORY_ENTRY_ARCHITECTURE - .. c:type:: IMAGE_DIRECTORY_ENTRY_COPYRIGHT .. c:type:: IMAGE_DIRECTORY_ENTRY_TLS Data directory for image thread local storage. @@ -535,7 +468,7 @@ Reference Data directory for Delayed Import Table. Structure of the delayed import table is linker-dependent. Microsoft version of delayed imports is described - in the sources "delayimp.h" and "delayimp.cpp", which can be found + in the souces "delayimp.h" and "delayimp.cpp", which can be found in MS Visual Studio 2008 CRT sources. .. c:type:: IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR @@ -560,16 +493,6 @@ Reference Section name. - .. c:member:: full_name - - If the name in the section table contains a slash (/) followed by - a representation of the decimal number in ASCII format, then this field - contains a string from the specified offset in the string table. - Otherwise, this field contains the same value as a name field. - - Even though it's not a standard, MinGW and Cygwin compilers use this - feature to store section names which are longer than 8 characters. - .. c:member:: characteristics Section characteristics. @@ -619,37 +542,12 @@ Reference Individual section characteristics can be inspected using a bitwise AND operation with the following constants: - .. c:type:: SECTION_NO_PAD .. c:type:: SECTION_CNT_CODE .. c:type:: SECTION_CNT_INITIALIZED_DATA .. c:type:: SECTION_CNT_UNINITIALIZED_DATA - .. c:type:: SECTION_LNK_OTHER - .. c:type:: SECTION_LNK_INFO - .. c:type:: SECTION_LNK_REMOVE - .. c:type:: SECTION_LNK_COMDAT - .. c:type:: SECTION_NO_DEFER_SPEC_EXC .. c:type:: SECTION_GPREL - .. c:type:: SECTION_MEM_FARDATA - .. c:type:: SECTION_MEM_PURGEABLE .. c:type:: SECTION_MEM_16BIT .. c:type:: SECTION_LNK_NRELOC_OVFL - .. c:type:: SECTION_MEM_LOCKED - .. c:type:: SECTION_MEM_PRELOAD - .. c:type:: SECTION_ALIGN_1BYTES - .. c:type:: SECTION_ALIGN_2BYTES - .. c:type:: SECTION_ALIGN_4BYTES - .. c:type:: SECTION_ALIGN_8BYTES - .. c:type:: SECTION_ALIGN_16BYTES - .. c:type:: SECTION_ALIGN_32BYTES - .. c:type:: SECTION_ALIGN_64BYTES - .. c:type:: SECTION_ALIGN_128BYTES - .. c:type:: SECTION_ALIGN_256BYTES - .. c:type:: SECTION_ALIGN_512BYTES - .. c:type:: SECTION_ALIGN_1024BYTES - .. c:type:: SECTION_ALIGN_2048BYTES - .. c:type:: SECTION_ALIGN_4096BYTES - .. c:type:: SECTION_ALIGN_8192BYTES - .. c:type:: SECTION_ALIGN_MASK .. c:type:: SECTION_MEM_DISCARDABLE .. c:type:: SECTION_MEM_NOT_CACHED .. c:type:: SECTION_MEM_NOT_PAGED @@ -657,7 +555,6 @@ Reference .. c:type:: SECTION_MEM_EXECUTE .. c:type:: SECTION_MEM_READ .. c:type:: SECTION_MEM_WRITE - .. c:type:: SECTION_SCALE_INDEX *Example: pe.sections[1].characteristics & pe.SECTION_CNT_CODE* @@ -669,15 +566,13 @@ Reference .. c:member:: offset - Overlay section offset. This is 0 for PE files that don't have overlaid - data and undefined for non-PE files. + Overlay section offset. .. c:member:: size - Overlay section size. This is 0 for PE files that don't have overlaid - data and undefined for non-PE files. + Overlay section size. - *Example: uint8(pe.overlay.offset) == 0x0d and pe.overlay.size > 1024* + *Example: uint8(0x0d) at pe.overlay.offset and pe.overlay.size > 1024* .. c:type:: number_of_resources @@ -707,14 +602,9 @@ Reference Individual resources can be accessed by using the [] operator. Each resource object has the following attributes: - .. c:member:: rva - - The RVA of the resource data. - .. c:member:: offset - Offset for the resource data. This can be undefined if the RVA is - invalid. + Offset for the resource data. .. c:member:: length @@ -802,20 +692,6 @@ Reference *Example: pe.version_info["CompanyName"] contains "Microsoft"* -.. c:type:: version_info_list - - Array of structures containing information about the PE's version information. - - .. c:member:: key - - Key of version information. - - .. c:member:: value - - Value of version information. - - *Example: pe.version_info_list[0].value contains "Microsoft"* - .. c:type:: number_of_signatures Number of authenticode signatures in the PE. @@ -852,26 +728,7 @@ Reference .. c:member:: algorithm - String representation of the algorithm used for this - signature. Usually "sha1WithRSAEncryption". It depends on the - X.509 and PKCS#7 implementations and possibly their versions, - consider using algorithm_oid instead. - - .. c:member:: algorithm_oid - - Object ID of the algorithm used for this signature, expressed - in numeric ASN.1 dot notation. The name contained in - algorithm is derived from this value. The object id is - expected to be stable across X.509 and PKCS#7 implementations - and their versions. - - For example, when using the current OpenSSL-based implementation:: - - algorithm_oid == "1.2.840.113549.1.1.11" - - is functionally equivalent to:: - - algorithm == "sha1WithRSAEncryption" + Algorithm used for this signature. Usually "sha1WithRSAEncryption". .. c:member:: serial @@ -958,11 +815,18 @@ Reference .. c:type:: pdb_path - .. versionadded:: 4.0.0 + .. versionadded:: 3.13.0 Path of the PDB file for this PE if present. - *Example: pe.pdb_path == "D:\\workspace\\2018_R9_RelBld\\target\\checkout\\custprof\\Release\\custprof.pdb"* + * Example: pe.pdb_path == "D:\\workspace\\2018_R9_RelBld\\target\\checkout\\custprof\\Release\\custprof.pdb" + +.. c:type:: is_reproducible_build + + .. versionadded:: 4.0.0 + + Value that indicates if the PE is build using compiler settings to achieve reproducibility. + .. c:function:: exports(function_name) @@ -991,7 +855,7 @@ Reference .. c:function:: exports_index(function_name) - .. versionadded:: 4.0.0 + .. versionadded:: 3.12.0 Function returning the index into the export_details array where the named function is, undefined otherwise. @@ -1000,7 +864,7 @@ Reference .. c:function:: exports_index(ordinal) - .. versionadded:: 4.0.0 + .. versionadded:: 3.12.0 Function returning the index into the export_details array where the exported ordinal is, undefined otherwise. @@ -1009,7 +873,7 @@ Reference .. c:function:: exports_index(/regular_expression/) - .. versionadded:: 4.0.0 + .. versionadded:: 3.12.0 Function returning the first index into the export_details array where the regular expression matches the exported name, undefined otherwise. @@ -1024,9 +888,9 @@ Reference .. c:type:: export_details - .. versionadded:: 4.0.0 + .. versionadded:: 3.11.0 - Array of structures containing information about the PE's exports. + Structure containing information about the PE's exports. .. c:member:: offset @@ -1049,13 +913,13 @@ Reference .. c:type:: dll_name - .. versionadded:: 4.0.0 + .. versionadded:: 3.11.0 The name of the DLL, if it exists in the export directory. .. c:type:: export_timestamp - .. versionadded:: 4.0.0 + .. versionadded:: 3.11.0 The timestamp the export data was created.. @@ -1063,25 +927,7 @@ Reference .. versionadded:: 3.6.0 - Number of imported DLLs in the PE. - -.. c:type:: number_of_imported_functions - - .. versionadded:: 4.1.0 - - Number of imported functions in the PE. - -.. c:type:: number_of_delayed_imports - - .. versionadded:: 4.2.0 - - Number of delayed imported DLLs in the PE. (Number of IMAGE_DELAYLOAD_DESCRIPTOR parsed from file) - -.. c:type:: number_of_delay_imported_functions - - .. versionadded:: 4.2.0 - - Number of delayed imported functions in the PE. + Number of imports in the PE. .. c:function:: imports(dll_name, function_name) @@ -1093,12 +939,12 @@ Reference .. c:function:: imports(dll_name) .. versionadded:: 3.5.0 - .. versionchanged:: 4.0.0 + .. versionchanged:: 3.12.0 Function returning the number of functions from the *dll_name*, in the PE imports. *dll_name* is case insensitive. - Note: Prior to version 4.0.0, this function returned only a boolean value + Note: Prior to version 3.12.0, this function returned only a boolean value indicating if the given DLL name was found in the PE imports. This change is backward compatible, as any number larger than 0 also evaluates as true. @@ -1117,7 +963,7 @@ Reference .. c:function:: imports(dll_regexp, function_regexp) .. versionadded:: 3.8.0 - .. versionchanged:: 4.0.0 + .. versionchanged:: 3.12.0 Function returning the number of functions from the PE imports where a function name matches *function_regexp* and a DLL name matches @@ -1125,123 +971,12 @@ Reference unless you use the "/i" modifier in the regexp, as shown in the example below. - Note: Prior to version 4.0.0, this function returned only a boolean value + Note: Prior to version 3.12.0, this function returned only a boolean value indicating if matching import was found or not. This change is backward compatible, as any number larger than 0 also evaluates as true. *Example: pe.imports(/kernel32\.dll/i, /(Read|Write)ProcessMemory/) == 2* - -.. c:function:: imports(import_flag, dll_name, function_name) - - .. versionadded:: 4.2.0 - - Function returning true if the PE imports *function_name* from *dll_name*, - or false otherwise. *dll_name* is case insensitive. - - *import_flag* is flag which specify type of import which should YARA search for. - This value can be composed by bitwise OR these values: - - .. c:member:: pe.IMPORT_STANDARD - - Search in standard imports - - .. c:member:: pe.IMPORT_DELAYED - - Search in delayed imports - - .. c:member:: pe.IMPORT_ANY - - Search in all imports - - *Example: pe.imports(pe.IMPORT_DELAYED | pe.IMPORT_STANDARD, "kernel32.dll", "WriteProcessMemory")* - -.. c:function:: imports(import_flag, import_flag, dll_name) - - .. versionadded:: 4.2.0 - - Function returning the number of functions from the *dll_name*, in the PE - imports. *dll_name* is case insensitive. - - *Examples: pe.imports(pe.IMPORT_DELAYED, "kernel32.dll"), pe.imports("kernel32.dll") == 10* - -.. c:function:: imports(import_flag, dll_name, ordinal) - - .. versionadded:: 4.2.0 - - Function returning true if the PE imports *ordinal* from *dll_name*, - or false otherwise. *dll_name* is case insensitive. - - *Example: pe.imports(pe.IMPORT_DELAYED, "WS2_32.DLL", 3)* - -.. c:function:: imports(import_flag, dll_regexp, function_regexp) - - .. versionadded:: 4.2.0 - - Function returning the number of functions from the PE imports where a - function name matches *function_regexp* and a DLL name matches - *dll_regexp*. Both *dll_regexp* and *function_regexp* are case sensitive - unless you use the "/i" modifier in the regexp, as shown in the example - below. - - *Example: pe.imports(pe.IMPORT_DELAYED, /kernel32\.dll/i, /(Read|Write)ProcessMemory/) == 2* - -.. c:type:: import_details - - .. versionadded:: 4.2.0 - - Array of structures containing information about the PE's imports libraries. - - .. c:member:: library_name - - Library name. - - .. c:member:: number_of_functions - - Number of imported function. - - .. c:member:: functions - - Array of structures containing information about the PE's imports functions. - - .. c:member:: name - - Name of imported function - - .. c:member:: ordinal - - Ordinal of imported function. If ordinal does not exist this value is YR_UNDEFINED - - *Example: pe.import_details[1].library_name == "library_name" - -.. c:type:: delayed_import_details - - .. versionadded:: 4.2.0 - - Array of structures containing information about the PE's delayed imports libraries. - - .. c:member:: library_name - - Library name. - - .. c:member:: number_of_functions - - Number of imported function. - - .. c:member:: functions - - Array of structures containing information about the PE's imports functions. - - .. c:member:: name - - Name of imported function - - .. c:member:: ordinal - - Ordinal of imported function. If ordinal does not exist this value is YR_UNDEFINED - - *Example: pe.delayed_import_details[1].name == "library_name" - .. c:function:: locale(locale_identifier) .. versionadded:: 3.2.0 @@ -1269,11 +1004,9 @@ Reference .. versionadded:: 3.2.0 Function returning the import hash or imphash for the PE. The imphash is - an MD5 hash of the PE's import table after some normalization. The imphash + a MD5 hash of the PE's import table after some normalization. The imphash for a PE can be also computed with `pefile `_ - and you can find more information in `Mandiant's blog - `_. The returned - hash string is always in lowercase. + and you can find more information in `Mandiant's blog `_. *Example: pe.imphash() == "b8bb385806b89680e13fc0cf24f4431e"* @@ -1293,14 +1026,6 @@ Reference *Example: pe.section_index(pe.entry_point)* -.. c:function:: is_pe() - - .. versionadded:: 3.8.0 - - Return true if the file is a PE. - - *Example: pe.is_pe()* - .. c:function:: is_dll() .. versionadded:: 3.5.0 diff --git a/libyara/include/yara/pe.h b/libyara/include/yara/pe.h index 400598473e..e6ee388441 100644 --- a/libyara/include/yara/pe.h +++ b/libyara/include/yara/pe.h @@ -45,80 +45,71 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // These definitions are not present in older Windows headers. #ifndef IMAGE_FILE_MACHINE_ARMNT -#define IMAGE_FILE_MACHINE_ARMNT 0x01c4 +#define IMAGE_FILE_MACHINE_ARMNT 0x01c4 #endif #ifndef IMAGE_FILE_MACHINE_ARM64 -#define IMAGE_FILE_MACHINE_ARM64 0xaa64 +#define IMAGE_FILE_MACHINE_ARM64 0xaa64 #endif -#ifndef IMAGE_SUBSYSTEM_EFI_ROM_IMAGE -#define IMAGE_SUBSYSTEM_EFI_ROM_IMAGE 13 -#endif - -#ifndef IMAGE_DIRECTORY_ENTRY_COPYRIGHT -#define IMAGE_DIRECTORY_ENTRY_COPYRIGHT 7 // (X86 usage) -#endif -#ifndef IMAGE_FILE_MACHINE_TARGET_HOST -#define IMAGE_FILE_MACHINE_TARGET_HOST 0x0001 -#endif #else #include + #include -typedef uint8_t BYTE; -typedef uint16_t WORD; -typedef uint16_t WCHAR; -typedef int16_t SHORT; -typedef uint32_t DWORD; -typedef int32_t LONG; -typedef uint32_t ULONG; -typedef uint64_t ULONGLONG; +typedef uint8_t BYTE; +typedef uint16_t WORD; +typedef uint32_t DWORD; +typedef int32_t LONG; +typedef uint32_t ULONG; +typedef uint64_t ULONGLONG; + + +#define FIELD_OFFSET(type, field) ((size_t)&(((type *)0)->field)) #ifndef _MAC -#define IMAGE_DOS_SIGNATURE 0x5A4D // MZ -#define IMAGE_OS2_SIGNATURE 0x454E // NE -#define IMAGE_OS2_SIGNATURE_LE 0x454C // LE -#define IMAGE_VXD_SIGNATURE 0x454C // LE -#define IMAGE_NT_SIGNATURE 0x00004550 // PE00 +#define IMAGE_DOS_SIGNATURE 0x5A4D // MZ +#define IMAGE_OS2_SIGNATURE 0x454E // NE +#define IMAGE_OS2_SIGNATURE_LE 0x454C // LE +#define IMAGE_VXD_SIGNATURE 0x454C // LE +#define IMAGE_NT_SIGNATURE 0x00004550 // PE00 #else -#define IMAGE_DOS_SIGNATURE 0x4D5A // MZ -#define IMAGE_OS2_SIGNATURE 0x4E45 // NE -#define IMAGE_OS2_SIGNATURE_LE 0x4C45 // LE -#define IMAGE_NT_SIGNATURE 0x50450000 // PE00 +#define IMAGE_DOS_SIGNATURE 0x4D5A // MZ +#define IMAGE_OS2_SIGNATURE 0x4E45 // NE +#define IMAGE_OS2_SIGNATURE_LE 0x4C45 // LE +#define IMAGE_NT_SIGNATURE 0x50450000 // PE00 #endif #pragma pack(push, 2) -typedef struct _IMAGE_DOS_HEADER -{ // DOS .EXE header - WORD e_magic; // Magic number - WORD e_cblp; // Bytes on last page of file - WORD e_cp; // Pages in file - WORD e_crlc; // Relocations - WORD e_cparhdr; // Size of header in paragraphs - WORD e_minalloc; // Minimum extra paragraphs needed - WORD e_maxalloc; // Maximum extra paragraphs needed - WORD e_ss; // Initial (relative) SS value - WORD e_sp; // Initial SP value - WORD e_csum; // Checksum - WORD e_ip; // Initial IP value - WORD e_cs; // Initial (relative) CS value - WORD e_lfarlc; // File address of relocation table - WORD e_ovno; // Overlay number - WORD e_res[4]; // Reserved words - WORD e_oemid; // OEM identifier (for e_oeminfo) - WORD e_oeminfo; // OEM information; e_oemid specific - WORD e_res2[10]; // Reserved words - LONG e_lfanew; // File address of new exe header -} IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER; +typedef struct _IMAGE_DOS_HEADER { // DOS .EXE header + WORD e_magic; // Magic number + WORD e_cblp; // Bytes on last page of file + WORD e_cp; // Pages in file + WORD e_crlc; // Relocations + WORD e_cparhdr; // Size of header in paragraphs + WORD e_minalloc; // Minimum extra paragraphs needed + WORD e_maxalloc; // Maximum extra paragraphs needed + WORD e_ss; // Initial (relative) SS value + WORD e_sp; // Initial SP value + WORD e_csum; // Checksum + WORD e_ip; // Initial IP value + WORD e_cs; // Initial (relative) CS value + WORD e_lfarlc; // File address of relocation table + WORD e_ovno; // Overlay number + WORD e_res[4]; // Reserved words + WORD e_oemid; // OEM identifier (for e_oeminfo) + WORD e_oeminfo; // OEM information; e_oemid specific + WORD e_res2[10]; // Reserved words + LONG e_lfanew; // File address of new exe header + } IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER; #pragma pack(pop) @@ -126,359 +117,301 @@ typedef struct _IMAGE_DOS_HEADER // File header format. // -#pragma pack(push, 4) - -typedef struct _IMAGE_FILE_HEADER -{ - WORD Machine; - WORD NumberOfSections; - DWORD TimeDateStamp; - DWORD PointerToSymbolTable; - DWORD NumberOfSymbols; - WORD SizeOfOptionalHeader; - WORD Characteristics; +#pragma pack(push,4) + +typedef struct _IMAGE_FILE_HEADER { + WORD Machine; + WORD NumberOfSections; + DWORD TimeDateStamp; + DWORD PointerToSymbolTable; + DWORD NumberOfSymbols; + WORD SizeOfOptionalHeader; + WORD Characteristics; } IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER; -#define IMAGE_SIZEOF_FILE_HEADER 20 - -// Relocation info stripped from file. -#define IMAGE_FILE_RELOCS_STRIPPED 0x0001 -// File is executable (i.e. no unresolved external references). -#define IMAGE_FILE_EXECUTABLE_IMAGE 0x0002 -// Line numbers stripped from file. -#define IMAGE_FILE_LINE_NUMS_STRIPPED 0x0004 -// Local symbols stripped from file. -#define IMAGE_FILE_LOCAL_SYMS_STRIPPED 0x0008 -// Aggressively trim working set -#define IMAGE_FILE_AGGRESIVE_WS_TRIM 0x0010 -// App can handle >2gb addresses -#define IMAGE_FILE_LARGE_ADDRESS_AWARE 0x0020 -// Bytes of machine word are reversed. -#define IMAGE_FILE_BYTES_REVERSED_LO 0x0080 -// 32 bit word machine. -#define IMAGE_FILE_32BIT_MACHINE 0x0100 -// Debugging info stripped from file in .DBG file -#define IMAGE_FILE_DEBUG_STRIPPED 0x0200 -// If Image is on removable media, copy and run from the swap file. -#define IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP 0x0400 -// If Image is on Net, copy and run from the swap file. -#define IMAGE_FILE_NET_RUN_FROM_SWAP 0x0800 -// System File. -#define IMAGE_FILE_SYSTEM 0x1000 -// File is a DLL.s -#define IMAGE_FILE_DLL 0x2000 -// File should only be run on a UP machine -#define IMAGE_FILE_UP_SYSTEM_ONLY 0x4000 -// Bytes of machine word are reversed. -#define IMAGE_FILE_BYTES_REVERSED_HI 0x8000 - -#define IMAGE_FILE_MACHINE_UNKNOWN 0x0000 -#define IMAGE_FILE_MACHINE_AM33 0x01d3 -#define IMAGE_FILE_MACHINE_AMD64 0x8664 -#define IMAGE_FILE_MACHINE_ARM 0x01c0 -#define IMAGE_FILE_MACHINE_ARMNT 0x01c4 -#define IMAGE_FILE_MACHINE_ARM64 0xaa64 -#define IMAGE_FILE_MACHINE_EBC 0x0ebc -#define IMAGE_FILE_MACHINE_I386 0x014c -#define IMAGE_FILE_MACHINE_IA64 0x0200 -#define IMAGE_FILE_MACHINE_M32R 0x9041 -#define IMAGE_FILE_MACHINE_MIPS16 0x0266 -#define IMAGE_FILE_MACHINE_MIPSFPU 0x0366 -#define IMAGE_FILE_MACHINE_MIPSFPU16 0x0466 -#define IMAGE_FILE_MACHINE_POWERPC 0x01f0 -#define IMAGE_FILE_MACHINE_POWERPCFP 0x01f1 -#define IMAGE_FILE_MACHINE_R4000 0x0166 -#define IMAGE_FILE_MACHINE_SH3 0x01a2 -#define IMAGE_FILE_MACHINE_SH3DSP 0x01a3 -#define IMAGE_FILE_MACHINE_SH4 0x01a6 -#define IMAGE_FILE_MACHINE_SH5 0x01a8 -#define IMAGE_FILE_MACHINE_THUMB 0x01c2 -#define IMAGE_FILE_MACHINE_WCEMIPSV2 0x0169 -// Useful for indicating we want to interact with the host and not a WoW guest. -#define IMAGE_FILE_MACHINE_TARGET_HOST 0x0001 -// MIPS little-endian, 0x160 big-endian -#define IMAGE_FILE_MACHINE_R3000 0x0162 // MIPS little-endian -#define IMAGE_FILE_MACHINE_R10000 0x0168 // Alpha_AXP -#define IMAGE_FILE_MACHINE_ALPHA 0x0184 // SH3E little-endian -#define IMAGE_FILE_MACHINE_SH3E 0x01a4 // ALPHA64 -#define IMAGE_FILE_MACHINE_ALPHA64 0x0284 -#define IMAGE_FILE_MACHINE_AXP64 IMAGE_FILE_MACHINE_ALPHA64 -#define IMAGE_FILE_MACHINE_TRICORE 0x0520 // Infineon -#define IMAGE_FILE_MACHINE_CEF 0x0CEF -#define IMAGE_FILE_MACHINE_CEE 0xC0EE + + +#define IMAGE_SIZEOF_FILE_HEADER 20 + + +#define IMAGE_FILE_RELOCS_STRIPPED 0x0001 // Relocation info stripped from file. +#define IMAGE_FILE_EXECUTABLE_IMAGE 0x0002 // File is executable (i.e. no unresolved external references). +#define IMAGE_FILE_LINE_NUMS_STRIPPED 0x0004 // Line numbers stripped from file. +#define IMAGE_FILE_LOCAL_SYMS_STRIPPED 0x0008 // Local symbols stripped from file. +#define IMAGE_FILE_AGGRESIVE_WS_TRIM 0x0010 // Aggressively trim working set +#define IMAGE_FILE_LARGE_ADDRESS_AWARE 0x0020 // App can handle >2gb addresses +#define IMAGE_FILE_BYTES_REVERSED_LO 0x0080 // Bytes of machine word are reversed. +#define IMAGE_FILE_32BIT_MACHINE 0x0100 // 32 bit word machine. +#define IMAGE_FILE_DEBUG_STRIPPED 0x0200 // Debugging info stripped from file in .DBG file +#define IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP 0x0400 // If Image is on removable media, copy and run from the swap file. +#define IMAGE_FILE_NET_RUN_FROM_SWAP 0x0800 // If Image is on Net, copy and run from the swap file. +#define IMAGE_FILE_SYSTEM 0x1000 // System File. +#define IMAGE_FILE_DLL 0x2000 // File is a DLL. +#define IMAGE_FILE_UP_SYSTEM_ONLY 0x4000 // File should only be run on a UP machine +#define IMAGE_FILE_BYTES_REVERSED_HI 0x8000 // Bytes of machine word are reversed. + + +#define IMAGE_FILE_MACHINE_UNKNOWN 0x0000 +#define IMAGE_FILE_MACHINE_AM33 0x01d3 +#define IMAGE_FILE_MACHINE_AMD64 0x8664 +#define IMAGE_FILE_MACHINE_ARM 0x01c0 +#define IMAGE_FILE_MACHINE_ARMNT 0x01c4 +#define IMAGE_FILE_MACHINE_ARM64 0xaa64 +#define IMAGE_FILE_MACHINE_EBC 0x0ebc +#define IMAGE_FILE_MACHINE_I386 0x014c +#define IMAGE_FILE_MACHINE_IA64 0x0200 +#define IMAGE_FILE_MACHINE_M32R 0x9041 +#define IMAGE_FILE_MACHINE_MIPS16 0x0266 +#define IMAGE_FILE_MACHINE_MIPSFPU 0x0366 +#define IMAGE_FILE_MACHINE_MIPSFPU16 0x0466 +#define IMAGE_FILE_MACHINE_POWERPC 0x01f0 +#define IMAGE_FILE_MACHINE_POWERPCFP 0x01f1 +#define IMAGE_FILE_MACHINE_R4000 0x0166 +#define IMAGE_FILE_MACHINE_SH3 0x01a2 +#define IMAGE_FILE_MACHINE_SH3DSP 0x01a3 +#define IMAGE_FILE_MACHINE_SH4 0x01a6 +#define IMAGE_FILE_MACHINE_SH5 0x01a8 +#define IMAGE_FILE_MACHINE_THUMB 0x01c2 +#define IMAGE_FILE_MACHINE_WCEMIPSV2 0x0169 // Section characteristics -#define IMAGE_SCN_TYPE_NO_PAD 0x00000008 -#define IMAGE_SCN_CNT_CODE 0x00000020 -#define IMAGE_SCN_CNT_INITIALIZED_DATA 0x00000040 -#define IMAGE_SCN_CNT_UNINITIALIZED_DATA 0x00000080 -#define IMAGE_SCN_LNK_OTHER 0x00000100 -#define IMAGE_SCN_LNK_INFO 0x00000200 -#define IMAGE_SCN_LNK_REMOVE 0x00000800 -#define IMAGE_SCN_LNK_COMDAT 0x00001000 -#define IMAGE_SCN_NO_DEFER_SPEC_EXC 0x00004000 -#define IMAGE_SCN_GPREL 0x00008000 -#define IMAGE_SCN_MEM_FARDATA 0x00008000 -#define IMAGE_SCN_MEM_PURGEABLE 0x00020000 -#define IMAGE_SCN_MEM_16BIT 0x00020000 -#define IMAGE_SCN_MEM_LOCKED 0x00040000 -#define IMAGE_SCN_MEM_PRELOAD 0x00080000 -#define IMAGE_SCN_ALIGN_1BYTES 0x00100000 -#define IMAGE_SCN_ALIGN_2BYTES 0x00200000 -#define IMAGE_SCN_ALIGN_4BYTES 0x00300000 -#define IMAGE_SCN_ALIGN_8BYTES 0x00400000 -#define IMAGE_SCN_ALIGN_16BYTES 0x00500000 -#define IMAGE_SCN_ALIGN_32BYTES 0x00600000 -#define IMAGE_SCN_ALIGN_64BYTES 0x00700000 -#define IMAGE_SCN_ALIGN_128BYTES 0x00800000 -#define IMAGE_SCN_ALIGN_256BYTES 0x00900000 -#define IMAGE_SCN_ALIGN_512BYTES 0x00A00000 -#define IMAGE_SCN_ALIGN_1024BYTES 0x00B00000 -#define IMAGE_SCN_ALIGN_2048BYTES 0x00C00000 -#define IMAGE_SCN_ALIGN_4096BYTES 0x00D00000 -#define IMAGE_SCN_ALIGN_8192BYTES 0x00E00000 -#define IMAGE_SCN_ALIGN_MASK 0x00F00000 -#define IMAGE_SCN_LNK_NRELOC_OVFL 0x01000000 -#define IMAGE_SCN_MEM_DISCARDABLE 0x02000000 -#define IMAGE_SCN_MEM_NOT_CACHED 0x04000000 -#define IMAGE_SCN_MEM_NOT_PAGED 0x08000000 -#define IMAGE_SCN_MEM_SHARED 0x10000000 -#define IMAGE_SCN_MEM_EXECUTE 0x20000000 -#define IMAGE_SCN_MEM_READ 0x40000000 -#define IMAGE_SCN_MEM_WRITE 0x80000000 -#define IMAGE_SCN_SCALE_INDEX 0x00000001 +#define IMAGE_SCN_CNT_CODE 0x00000020 +#define IMAGE_SCN_CNT_INITIALIZED_DATA 0x00000040 +#define IMAGE_SCN_CNT_UNINITIALIZED_DATA 0x00000080 +#define IMAGE_SCN_GPREL 0x00008000 +#define IMAGE_SCN_MEM_16BIT 0x00020000 +#define IMAGE_SCN_LNK_NRELOC_OVFL 0x01000000 +#define IMAGE_SCN_MEM_DISCARDABLE 0x02000000 +#define IMAGE_SCN_MEM_NOT_CACHED 0x04000000 +#define IMAGE_SCN_MEM_NOT_PAGED 0x08000000 +#define IMAGE_SCN_MEM_SHARED 0x10000000 +#define IMAGE_SCN_MEM_EXECUTE 0x20000000 +#define IMAGE_SCN_MEM_READ 0x40000000 +#define IMAGE_SCN_MEM_WRITE 0x80000000 // // Directory format. // -typedef struct _IMAGE_DATA_DIRECTORY -{ - DWORD VirtualAddress; - DWORD Size; +typedef struct _IMAGE_DATA_DIRECTORY { + DWORD VirtualAddress; + DWORD Size; } IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY; -#define IMAGE_NUMBEROF_DIRECTORY_ENTRIES 16 - -#define IMAGE_DIRECTORY_ENTRY_EXPORT 0 -#define IMAGE_DIRECTORY_ENTRY_IMPORT 1 -#define IMAGE_DIRECTORY_ENTRY_RESOURCE 2 -#define IMAGE_DIRECTORY_ENTRY_EXCEPTION 3 -#define IMAGE_DIRECTORY_ENTRY_SECURITY 4 -#define IMAGE_DIRECTORY_ENTRY_BASERELOC 5 -#define IMAGE_DIRECTORY_ENTRY_DEBUG 6 -#define IMAGE_DIRECTORY_ENTRY_COPYRIGHT 7 -#define IMAGE_DIRECTORY_ENTRY_ARCHITECTURE 7 -#define IMAGE_DIRECTORY_ENTRY_GLOBALPTR 8 -#define IMAGE_DIRECTORY_ENTRY_TLS 9 -#define IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG 10 -#define IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT 11 -#define IMAGE_DIRECTORY_ENTRY_IAT 12 -#define IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT 13 -#define IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR 14 +#define IMAGE_NUMBEROF_DIRECTORY_ENTRIES 16 + + +#define IMAGE_DIRECTORY_ENTRY_EXPORT 0 // Export Directory +#define IMAGE_DIRECTORY_ENTRY_IMPORT 1 // Import Directory +#define IMAGE_DIRECTORY_ENTRY_RESOURCE 2 // Resource Directory +#define IMAGE_DIRECTORY_ENTRY_EXCEPTION 3 // Exception Directory +#define IMAGE_DIRECTORY_ENTRY_SECURITY 4 // Security Directory +#define IMAGE_DIRECTORY_ENTRY_BASERELOC 5 // Base Relocation Table +#define IMAGE_DIRECTORY_ENTRY_DEBUG 6 // Debug Directory +#define IMAGE_DIRECTORY_ENTRY_COPYRIGHT 7 // (X86 usage) +#define IMAGE_DIRECTORY_ENTRY_ARCHITECTURE 7 // Architecture Specific Data +#define IMAGE_DIRECTORY_ENTRY_GLOBALPTR 8 // RVA of GP +#define IMAGE_DIRECTORY_ENTRY_TLS 9 // TLS Directory +#define IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG 10 // Load Configuration Directory +#define IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT 11 // Bound Import Directory in headers +#define IMAGE_DIRECTORY_ENTRY_IAT 12 // Import Address Table +#define IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT 13 // Delay Load Import Descriptors +#define IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR 14 // COM Runtime descriptor + // // Optional header format. // -typedef struct _IMAGE_OPTIONAL_HEADER32 -{ - WORD Magic; - BYTE MajorLinkerVersion; - BYTE MinorLinkerVersion; - DWORD SizeOfCode; - DWORD SizeOfInitializedData; - DWORD SizeOfUninitializedData; - DWORD AddressOfEntryPoint; - DWORD BaseOfCode; - DWORD BaseOfData; - DWORD ImageBase; - DWORD SectionAlignment; - DWORD FileAlignment; - WORD MajorOperatingSystemVersion; - WORD MinorOperatingSystemVersion; - WORD MajorImageVersion; - WORD MinorImageVersion; - WORD MajorSubsystemVersion; - WORD MinorSubsystemVersion; - DWORD Win32VersionValue; - DWORD SizeOfImage; - DWORD SizeOfHeaders; - DWORD CheckSum; - WORD Subsystem; - WORD DllCharacteristics; - DWORD SizeOfStackReserve; - DWORD SizeOfStackCommit; - DWORD SizeOfHeapReserve; - DWORD SizeOfHeapCommit; - DWORD LoaderFlags; - DWORD NumberOfRvaAndSizes; - IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]; +typedef struct _IMAGE_OPTIONAL_HEADER32 { + WORD Magic; + BYTE MajorLinkerVersion; + BYTE MinorLinkerVersion; + DWORD SizeOfCode; + DWORD SizeOfInitializedData; + DWORD SizeOfUninitializedData; + DWORD AddressOfEntryPoint; + DWORD BaseOfCode; + DWORD BaseOfData; + DWORD ImageBase; + DWORD SectionAlignment; + DWORD FileAlignment; + WORD MajorOperatingSystemVersion; + WORD MinorOperatingSystemVersion; + WORD MajorImageVersion; + WORD MinorImageVersion; + WORD MajorSubsystemVersion; + WORD MinorSubsystemVersion; + DWORD Win32VersionValue; + DWORD SizeOfImage; + DWORD SizeOfHeaders; + DWORD CheckSum; + WORD Subsystem; + WORD DllCharacteristics; + DWORD SizeOfStackReserve; + DWORD SizeOfStackCommit; + DWORD SizeOfHeapReserve; + DWORD SizeOfHeapCommit; + DWORD LoaderFlags; + DWORD NumberOfRvaAndSizes; + IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]; } IMAGE_OPTIONAL_HEADER32, *PIMAGE_OPTIONAL_HEADER32; -typedef struct _IMAGE_OPTIONAL_HEADER64 -{ - WORD Magic; - BYTE MajorLinkerVersion; - BYTE MinorLinkerVersion; - DWORD SizeOfCode; - DWORD SizeOfInitializedData; - DWORD SizeOfUninitializedData; - DWORD AddressOfEntryPoint; - DWORD BaseOfCode; - ULONGLONG ImageBase; - DWORD SectionAlignment; - DWORD FileAlignment; - WORD MajorOperatingSystemVersion; - WORD MinorOperatingSystemVersion; - WORD MajorImageVersion; - WORD MinorImageVersion; - WORD MajorSubsystemVersion; - WORD MinorSubsystemVersion; - DWORD Win32VersionValue; - DWORD SizeOfImage; - DWORD SizeOfHeaders; - DWORD CheckSum; - WORD Subsystem; - WORD DllCharacteristics; - ULONGLONG SizeOfStackReserve; - ULONGLONG SizeOfStackCommit; - ULONGLONG SizeOfHeapReserve; - ULONGLONG SizeOfHeapCommit; - DWORD LoaderFlags; - DWORD NumberOfRvaAndSizes; - IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]; + +typedef struct _IMAGE_OPTIONAL_HEADER64 { + WORD Magic; + BYTE MajorLinkerVersion; + BYTE MinorLinkerVersion; + DWORD SizeOfCode; + DWORD SizeOfInitializedData; + DWORD SizeOfUninitializedData; + DWORD AddressOfEntryPoint; + DWORD BaseOfCode; + ULONGLONG ImageBase; + DWORD SectionAlignment; + DWORD FileAlignment; + WORD MajorOperatingSystemVersion; + WORD MinorOperatingSystemVersion; + WORD MajorImageVersion; + WORD MinorImageVersion; + WORD MajorSubsystemVersion; + WORD MinorSubsystemVersion; + DWORD Win32VersionValue; + DWORD SizeOfImage; + DWORD SizeOfHeaders; + DWORD CheckSum; + WORD Subsystem; + WORD DllCharacteristics; + ULONGLONG SizeOfStackReserve; + ULONGLONG SizeOfStackCommit; + ULONGLONG SizeOfHeapReserve; + ULONGLONG SizeOfHeapCommit; + DWORD LoaderFlags; + DWORD NumberOfRvaAndSizes; + IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]; } IMAGE_OPTIONAL_HEADER64, *PIMAGE_OPTIONAL_HEADER64; -#define IMAGE_NT_OPTIONAL_HDR32_MAGIC 0x10b -#define IMAGE_NT_OPTIONAL_HDR64_MAGIC 0x20b -#define IMAGE_ROM_OPTIONAL_HDR_MAGIC 0x107 -typedef struct _IMAGE_NT_HEADERS32 -{ - DWORD Signature; - IMAGE_FILE_HEADER FileHeader; - IMAGE_OPTIONAL_HEADER32 OptionalHeader; +#define IMAGE_NT_OPTIONAL_HDR32_MAGIC 0x10b +#define IMAGE_NT_OPTIONAL_HDR64_MAGIC 0x20b + + +typedef struct _IMAGE_NT_HEADERS32 { + DWORD Signature; + IMAGE_FILE_HEADER FileHeader; + IMAGE_OPTIONAL_HEADER32 OptionalHeader; } IMAGE_NT_HEADERS32, *PIMAGE_NT_HEADERS32; -typedef struct _IMAGE_NT_HEADERS64 -{ - DWORD Signature; - IMAGE_FILE_HEADER FileHeader; - IMAGE_OPTIONAL_HEADER64 OptionalHeader; + +typedef struct _IMAGE_NT_HEADERS64 { + DWORD Signature; + IMAGE_FILE_HEADER FileHeader; + IMAGE_OPTIONAL_HEADER64 OptionalHeader; } IMAGE_NT_HEADERS64, *PIMAGE_NT_HEADERS64; // IMAGE_FIRST_SECTION doesn't need 32/64 versions since the file header is // the same either way. -#define IMAGE_FIRST_SECTION(ntheader) \ - ((PIMAGE_SECTION_HEADER)( \ - (BYTE*) ntheader + offsetof(IMAGE_NT_HEADERS32, OptionalHeader) + \ - yr_le16toh(((PIMAGE_NT_HEADERS32)(ntheader)) \ - ->FileHeader.SizeOfOptionalHeader))) +#define IMAGE_FIRST_SECTION( ntheader ) ((PIMAGE_SECTION_HEADER) \ + ((BYTE*)ntheader + \ + FIELD_OFFSET( IMAGE_NT_HEADERS32, OptionalHeader ) + \ + yr_le16toh(((PIMAGE_NT_HEADERS32)(ntheader))->FileHeader.SizeOfOptionalHeader) \ + )) // Subsystem Values -#define IMAGE_SUBSYSTEM_UNKNOWN 0 -#define IMAGE_SUBSYSTEM_NATIVE 1 -#define IMAGE_SUBSYSTEM_WINDOWS_GUI 2 -#define IMAGE_SUBSYSTEM_WINDOWS_CUI 3 -#define IMAGE_SUBSYSTEM_OS2_CUI 5 -#define IMAGE_SUBSYSTEM_POSIX_CUI 7 -#define IMAGE_SUBSYSTEM_NATIVE_WINDOWS 8 -#define IMAGE_SUBSYSTEM_WINDOWS_CE_GUI 9 -#define IMAGE_SUBSYSTEM_EFI_APPLICATION 10 -#define IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER 11 -#define IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER 12 -#define IMAGE_SUBSYSTEM_EFI_ROM_IMAGE 13 -#define IMAGE_SUBSYSTEM_XBOX 14 -#define IMAGE_SUBSYSTEM_WINDOWS_BOOT_APPLICATION 16 +#define IMAGE_SUBSYSTEM_UNKNOWN 0 +#define IMAGE_SUBSYSTEM_NATIVE 1 +#define IMAGE_SUBSYSTEM_WINDOWS_GUI 2 +#define IMAGE_SUBSYSTEM_WINDOWS_CUI 3 +#define IMAGE_SUBSYSTEM_OS2_CUI 5 +#define IMAGE_SUBSYSTEM_POSIX_CUI 7 +#define IMAGE_SUBSYSTEM_NATIVE_WINDOWS 8 +#define IMAGE_SUBSYSTEM_WINDOWS_CE_GUI 9 +#define IMAGE_SUBSYSTEM_EFI_APPLICATION 10 +#define IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER 11 +#define IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER 12 +#define IMAGE_SUBSYSTEM_EFI_ROM_IMAGE 13 +#define IMAGE_SUBSYSTEM_XBOX 14 +#define IMAGE_SUBSYSTEM_WINDOWS_BOOT_APPLICATION 16 // DllCharacteristics values -#define IMAGE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA 0x0020 -#define IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE 0x0040 -#define IMAGE_DLLCHARACTERISTICS_FORCE_INTEGRITY 0x0080 -#define IMAGE_DLLCHARACTERISTICS_NX_COMPAT 0x0100 -#define IMAGE_DLLCHARACTERISTICS_NO_ISOLATION 0x0200 -#define IMAGE_DLLCHARACTERISTICS_NO_SEH 0x0400 -#define IMAGE_DLLCHARACTERISTICS_NO_BIND 0x0800 -#define IMAGE_DLLCHARACTERISTICS_APPCONTAINER 0x1000 -#define IMAGE_DLLCHARACTERISTICS_WDM_DRIVER 0x2000 -#define IMAGE_DLLCHARACTERISTICS_GUARD_CF 0x4000 -#define IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE 0x8000 +#define IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE 0x0040 +#define IMAGE_DLLCHARACTERISTICS_FORCE_INTEGRITY 0x0080 +#define IMAGE_DLLCHARACTERISTICS_NX_COMPAT 0x0100 +#define IMAGE_DLLCHARACTERISTICS_NO_ISOLATION 0x0200 +#define IMAGE_DLLCHARACTERISTICS_NO_SEH 0x0400 +#define IMAGE_DLLCHARACTERISTICS_NO_BIND 0x0800 +#define IMAGE_DLLCHARACTERISTICS_WDM_DRIVER 0x2000 +#define IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE 0x8000 // // Section header format. // -#define IMAGE_SIZEOF_SHORT_NAME 8 - -typedef struct _IMAGE_SECTION_HEADER -{ - BYTE Name[IMAGE_SIZEOF_SHORT_NAME]; - union - { - DWORD PhysicalAddress; - DWORD VirtualSize; - } Misc; - DWORD VirtualAddress; - DWORD SizeOfRawData; - DWORD PointerToRawData; - DWORD PointerToRelocations; - DWORD PointerToLinenumbers; - WORD NumberOfRelocations; - WORD NumberOfLinenumbers; - DWORD Characteristics; +#define IMAGE_SIZEOF_SHORT_NAME 8 + +typedef struct _IMAGE_SECTION_HEADER { + BYTE Name[IMAGE_SIZEOF_SHORT_NAME]; + union { + DWORD PhysicalAddress; + DWORD VirtualSize; + } Misc; + DWORD VirtualAddress; + DWORD SizeOfRawData; + DWORD PointerToRawData; + DWORD PointerToRelocations; + DWORD PointerToLinenumbers; + WORD NumberOfRelocations; + WORD NumberOfLinenumbers; + DWORD Characteristics; } IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER; -#define IMAGE_SIZEOF_SECTION_HEADER 40 - -typedef struct _IMAGE_EXPORT_DIRECTORY -{ - DWORD Characteristics; - DWORD TimeDateStamp; - WORD MajorVersion; - WORD MinorVersion; - DWORD Name; - DWORD Base; - DWORD NumberOfFunctions; - DWORD NumberOfNames; - DWORD AddressOfFunctions; - DWORD AddressOfNames; - DWORD AddressOfNameOrdinals; -} IMAGE_EXPORT_DIRECTORY, *PIMAGE_EXPORT_DIRECTORY; +#define IMAGE_SIZEOF_SECTION_HEADER 40 -typedef struct _IMAGE_IMPORT_DESCRIPTOR -{ - union - { + +typedef struct _IMAGE_EXPORT_DIRECTORY { DWORD Characteristics; - DWORD OriginalFirstThunk; - }; - DWORD TimeDateStamp; - DWORD ForwarderChain; - DWORD Name; - DWORD FirstThunk; + DWORD TimeDateStamp; + WORD MajorVersion; + WORD MinorVersion; + DWORD Name; + DWORD Base; + DWORD NumberOfFunctions; + DWORD NumberOfNames; + DWORD AddressOfFunctions; + DWORD AddressOfNames; + DWORD AddressOfNameOrdinals; +} IMAGE_EXPORT_DIRECTORY, *PIMAGE_EXPORT_DIRECTORY; + + +typedef struct _IMAGE_IMPORT_DESCRIPTOR { + union { + DWORD Characteristics; + DWORD OriginalFirstThunk; + } ; + DWORD TimeDateStamp; + DWORD ForwarderChain; + DWORD Name; + DWORD FirstThunk; } IMAGE_IMPORT_DESCRIPTOR, *PIMAGE_IMPORT_DESCRIPTOR; -typedef struct _IMAGE_IMPORT_BY_NAME -{ + +typedef struct _IMAGE_IMPORT_BY_NAME { WORD Hint; BYTE Name[1]; } IMAGE_IMPORT_BY_NAME, *PIMAGE_IMPORT_BY_NAME; -typedef struct _IMAGE_THUNK_DATA32 -{ - union - { +typedef struct _IMAGE_THUNK_DATA32 { + union { DWORD ForwarderString; DWORD Function; DWORD Ordinal; @@ -487,57 +420,12 @@ typedef struct _IMAGE_THUNK_DATA32 } IMAGE_THUNK_DATA32, *PIMAGE_THUNK_DATA32; -#define IMAGE_ORDINAL_FLAG32 0x80000000 -#define IMAGE_ORDINAL_FLAG64 0x8000000000000000L - -typedef struct _IMAGE_BOUND_IMPORT_DESCRIPTOR -{ - DWORD TimeDateStamp; - WORD OffsetModuleName; - WORD NumberOfModuleForwarderRefs; - // Array of zero or more IMAGE_BOUND_FORWARDER_REF follows -} IMAGE_BOUND_IMPORT_DESCRIPTOR, *PIMAGE_BOUND_IMPORT_DESCRIPTOR; - -typedef struct _IMAGE_BOUND_FORWARDER_REF -{ - DWORD TimeDateStamp; - WORD OffsetModuleName; - WORD Reserved; -} IMAGE_BOUND_FORWARDER_REF, *PIMAGE_BOUND_FORWARDER_REF; - -typedef struct _IMAGE_DELAYLOAD_DESCRIPTOR -{ - union - { - DWORD AllAttributes; - struct - { - DWORD RvaBased : 1; // Delay load version 2 - DWORD ReservedAttributes : 31; - } DUMMYSTRUCTNAME; - } Attributes; - - // RVA to the name of the target library (NULL-terminate ASCII string) - DWORD DllNameRVA; - // RVA to the HMODULE caching location (PHMODULE) - DWORD ModuleHandleRVA; - // RVA to the start of the IAT (PIMAGE_THUNK_DATA) - DWORD ImportAddressTableRVA; - // RVA to the start of the name table (PIMAGE_THUNK_DATA::AddressOfData) - DWORD ImportNameTableRVA; - // RVA to an optional bound IAT - DWORD BoundImportAddressTableRVA; - // RVA to an optional unload info table - DWORD UnloadInformationTableRVA; - // 0 if not bound, otherwise, date/time of the target DLL - DWORD TimeDateStamp; - -} IMAGE_DELAYLOAD_DESCRIPTOR, *PIMAGE_DELAYLOAD_DESCRIPTOR; - -typedef struct _IMAGE_THUNK_DATA64 -{ - union - { + +#define IMAGE_ORDINAL_FLAG32 0x80000000 +#define IMAGE_ORDINAL_FLAG64 0x8000000000000000L + +typedef struct _IMAGE_THUNK_DATA64 { + union { ULONGLONG ForwarderString; ULONGLONG Function; ULONGLONG Ordinal; @@ -546,268 +434,90 @@ typedef struct _IMAGE_THUNK_DATA64 } IMAGE_THUNK_DATA64, *PIMAGE_THUNK_DATA64; -typedef struct _IMAGE_RESOURCE_DIR_STRING_U -{ - WORD Length; - WCHAR NameString[1]; -} IMAGE_RESOURCE_DIR_STRING_U, *PIMAGE_RESOURCE_DIR_STRING_U; -typedef struct _IMAGE_RESOURCE_DIRECTORY_ENTRY -{ - DWORD Name; - DWORD OffsetToData; +typedef struct _IMAGE_RESOURCE_DIRECTORY_ENTRY { + DWORD Name; + DWORD OffsetToData; } IMAGE_RESOURCE_DIRECTORY_ENTRY, *PIMAGE_RESOURCE_DIRECTORY_ENTRY; -typedef struct _IMAGE_RESOURCE_DATA_ENTRY -{ - DWORD OffsetToData; - DWORD Size; - DWORD CodePage; - DWORD Reserved; -} IMAGE_RESOURCE_DATA_ENTRY, *PIMAGE_RESOURCE_DATA_ENTRY; - -typedef struct _IMAGE_RESOURCE_DIRECTORY -{ - DWORD Characteristics; - DWORD TimeDateStamp; - WORD MajorVersion; - WORD MinorVersion; - WORD NumberOfNamedEntries; - WORD NumberOfIdEntries; -} IMAGE_RESOURCE_DIRECTORY, *PIMAGE_RESOURCE_DIRECTORY; - -#define IMAGE_DEBUG_TYPE_FPO 3 -#define IMAGE_DEBUG_TYPE_MISC 4 -#define IMAGE_DEBUG_TYPE_EXCEPTION 5 -#define IMAGE_DEBUG_TYPE_FIXUP 6 -#define IMAGE_DEBUG_TYPE_OMAP_TO_SRC 7 -#define IMAGE_DEBUG_TYPE_OMAP_FROM_SRC 8 -#define IMAGE_DEBUG_TYPE_BORLAND 9 -#define IMAGE_DEBUG_TYPE_RESERVED10 10 -#define IMAGE_DEBUG_TYPE_CLSID 11 -#define IMAGE_DEBUG_TYPE_VC_FEATURE 12 -#define IMAGE_DEBUG_TYPE_POGO 13 -#define IMAGE_DEBUG_TYPE_ILTCG 14 -#define IMAGE_DEBUG_TYPE_MPX 15 -#define IMAGE_DEBUG_TYPE_REPRO 16 - -typedef struct _IMAGE_DEBUG_DIRECTORY -{ - DWORD Characteristics; - DWORD TimeDateStamp; - WORD MajorVersion; - WORD MinorVersion; - DWORD Type; - DWORD SizeOfData; - DWORD AddressOfRawData; - DWORD PointerToRawData; -} IMAGE_DEBUG_DIRECTORY, *PIMAGE_DEBUG_DIRECTORY; - -#pragma pack(pop) - -// -// Symbol format. -// - -typedef struct _IMAGE_SYMBOL -{ - union - { - BYTE ShortName[8]; - struct - { - DWORD Short; // if 0, use LongName - DWORD Long; // offset into string table - } Name; - DWORD LongName[2]; // PBYTE [2] - } N; - DWORD Value; - SHORT SectionNumber; - WORD Type; - BYTE StorageClass; - BYTE NumberOfAuxSymbols; -} IMAGE_SYMBOL, *PIMAGE_SYMBOL; - -#define IMAGE_SIZEOF_SYMBOL 18 - -typedef struct _IMAGE_SYMBOL_EX -{ - union - { - BYTE ShortName[8]; - struct - { - DWORD Short; // if 0, use LongName - DWORD Long; // offset into string table - } Name; - DWORD LongName[2]; // PBYTE [2] - } N; - DWORD Value; - LONG SectionNumber; - WORD Type; - BYTE StorageClass; - BYTE NumberOfAuxSymbols; -} IMAGE_SYMBOL_EX, *PIMAGE_SYMBOL_EX; - -// -// Section values. -// -// Symbols have a section number of the section in which they are -// defined. Otherwise, section numbers have the following meanings: -// - -#define IMAGE_SYM_UNDEFINED (SHORT) 0 // Symbol is undefined or is common. -#define IMAGE_SYM_ABSOLUTE (SHORT) - 1 // Symbol is an absolute value. -#define IMAGE_SYM_DEBUG (SHORT) - 2 // Symbol is a special debug item. -#define IMAGE_SYM_SECTION_MAX 0xFEFF // Values 0xFF00-0xFFFF are special -#define IMAGE_SYM_SECTION_MAX_EX MAXLONG - -// -// Type (fundamental) values. -// - -#define IMAGE_SYM_TYPE_NULL 0x0000 // no type. -#define IMAGE_SYM_TYPE_VOID 0x0001 // -#define IMAGE_SYM_TYPE_CHAR 0x0002 // type character. -#define IMAGE_SYM_TYPE_SHORT 0x0003 // type short integer. -#define IMAGE_SYM_TYPE_INT 0x0004 // -#define IMAGE_SYM_TYPE_LONG 0x0005 // -#define IMAGE_SYM_TYPE_FLOAT 0x0006 // -#define IMAGE_SYM_TYPE_DOUBLE 0x0007 // -#define IMAGE_SYM_TYPE_STRUCT 0x0008 // -#define IMAGE_SYM_TYPE_UNION 0x0009 // -#define IMAGE_SYM_TYPE_ENUM 0x000A // enumeration. -#define IMAGE_SYM_TYPE_MOE 0x000B // member of enumeration. -#define IMAGE_SYM_TYPE_BYTE 0x000C // -#define IMAGE_SYM_TYPE_WORD 0x000D // -#define IMAGE_SYM_TYPE_UINT 0x000E // -#define IMAGE_SYM_TYPE_DWORD 0x000F // -#define IMAGE_SYM_TYPE_PCODE 0x8000 // -// -// Type (derived) values. -// - -#define IMAGE_SYM_DTYPE_NULL 0 // no derived type. -#define IMAGE_SYM_DTYPE_POINTER 1 // pointer. -#define IMAGE_SYM_DTYPE_FUNCTION 2 // function. -#define IMAGE_SYM_DTYPE_ARRAY 3 // array. - -// -// Storage classes. -// -#define IMAGE_SYM_CLASS_END_OF_FUNCTION (BYTE) - 1 -#define IMAGE_SYM_CLASS_NULL 0x0000 -#define IMAGE_SYM_CLASS_AUTOMATIC 0x0001 -#define IMAGE_SYM_CLASS_EXTERNAL 0x0002 -#define IMAGE_SYM_CLASS_STATIC 0x0003 -#define IMAGE_SYM_CLASS_REGISTER 0x0004 -#define IMAGE_SYM_CLASS_EXTERNAL_DEF 0x0005 -#define IMAGE_SYM_CLASS_LABEL 0x0006 -#define IMAGE_SYM_CLASS_UNDEFINED_LABEL 0x0007 -#define IMAGE_SYM_CLASS_MEMBER_OF_STRUCT 0x0008 -#define IMAGE_SYM_CLASS_ARGUMENT 0x0009 -#define IMAGE_SYM_CLASS_STRUCT_TAG 0x000A -#define IMAGE_SYM_CLASS_MEMBER_OF_UNION 0x000B -#define IMAGE_SYM_CLASS_UNION_TAG 0x000C -#define IMAGE_SYM_CLASS_TYPE_DEFINITION 0x000D -#define IMAGE_SYM_CLASS_UNDEFINED_STATIC 0x000E -#define IMAGE_SYM_CLASS_ENUM_TAG 0x000F -#define IMAGE_SYM_CLASS_MEMBER_OF_ENUM 0x0010 -#define IMAGE_SYM_CLASS_REGISTER_PARAM 0x0011 -#define IMAGE_SYM_CLASS_BIT_FIELD 0x0012 - -#define IMAGE_SYM_CLASS_FAR_EXTERNAL 0x0044 // - -#define IMAGE_SYM_CLASS_BLOCK 0x0064 -#define IMAGE_SYM_CLASS_FUNCTION 0x0065 -#define IMAGE_SYM_CLASS_END_OF_STRUCT 0x0066 -#define IMAGE_SYM_CLASS_FILE 0x0067 -// new -#define IMAGE_SYM_CLASS_SECTION 0x0068 -#define IMAGE_SYM_CLASS_WEAK_EXTERNAL 0x0069 - -#define IMAGE_SYM_CLASS_CLR_TOKEN 0x006B - -// type packing constants - -#define N_BTMASK 0x000F -#define N_TMASK 0x0030 -#define N_TMASK1 0x00C0 -#define N_TMASK2 0x00F0 -#define N_BTSHFT 4 -#define N_TSHIFT 2 -// MACROS - -// Basic Type of x -#define BTYPE(x) ((x) &N_BTMASK) - -// Is x a pointer? -#ifndef ISPTR -#define ISPTR(x) (((x) &N_TMASK) == (IMAGE_SYM_DTYPE_POINTER << N_BTSHFT)) -#endif -// Is x a function? -#ifndef ISFCN -#define ISFCN(x) (((x) &N_TMASK) == (IMAGE_SYM_DTYPE_FUNCTION << N_BTSHFT)) -#endif + typedef struct _IMAGE_RESOURCE_DATA_ENTRY { + DWORD OffsetToData; + DWORD Size; + DWORD CodePage; + DWORD Reserved; + } IMAGE_RESOURCE_DATA_ENTRY,*PIMAGE_RESOURCE_DATA_ENTRY; -// Is x an array? -#ifndef ISARY -#define ISARY(x) (((x) &N_TMASK) == (IMAGE_SYM_DTYPE_ARRAY << N_BTSHFT)) -#endif +typedef struct _IMAGE_RESOURCE_DIRECTORY { + DWORD Characteristics; + DWORD TimeDateStamp; + WORD MajorVersion; + WORD MinorVersion; + WORD NumberOfNamedEntries; + WORD NumberOfIdEntries; +} IMAGE_RESOURCE_DIRECTORY, *PIMAGE_RESOURCE_DIRECTORY; -// Is x a structure, union, or enumeration TAG? -#ifndef ISTAG -#define ISTAG(x) \ - ((x) == IMAGE_SYM_CLASS_STRUCT_TAG || (x) == IMAGE_SYM_CLASS_UNION_TAG || \ - (x) == IMAGE_SYM_CLASS_ENUM_TAG) -#endif +#define IMAGE_DEBUG_TYPE_UNKNOWN 0 +#define IMAGE_DEBUG_TYPE_COFF 1 +#define IMAGE_DEBUG_TYPE_CODEVIEW 2 +#define IMAGE_DEBUG_TYPE_FPO 3 +#define IMAGE_DEBUG_TYPE_MISC 4 +#define IMAGE_DEBUG_TYPE_EXCEPTION 5 +#define IMAGE_DEBUG_TYPE_FIXUP 6 +#define IMAGE_DEBUG_TYPE_OMAP_TO_SRC 7 +#define IMAGE_DEBUG_TYPE_OMAP_FROM_SRC 8 +#define IMAGE_DEBUG_TYPE_BORLAND 9 +#define IMAGE_DEBUG_TYPE_RESERVED10 10 +#define IMAGE_DEBUG_TYPE_CLSID 11 +#define IMAGE_DEBUG_TYPE_REPRO 16 +#define IMAGE_DEBUG_TYPE_EX_DLLCHARACTERISTICS 20 + +typedef struct _IMAGE_DEBUG_DIRECTORY { + DWORD Characteristics; + DWORD TimeDateStamp; + WORD MajorVersion; + WORD MinorVersion; + DWORD Type; + DWORD SizeOfData; + DWORD AddressOfRawData; + DWORD PointerToRawData; +} IMAGE_DEBUG_DIRECTORY, *PIMAGE_DEBUG_DIRECTORY; -#ifndef INCREF -#define INCREF(x) \ - ((((x) & ~N_BTMASK) << N_TSHIFT) | (IMAGE_SYM_DTYPE_POINTER << N_BTSHFT) | \ - ((x) &N_BTMASK)) -#endif -#ifndef DECREF -#define DECREF(x) ((((x) >> N_TSHIFT) & ~N_BTMASK) | ((x) &N_BTMASK)) -#endif +#pragma pack(pop) #endif // _WIN32 -#define CVINFO_PDB70_CVSIGNATURE 0x53445352 // "RSDS" -#define CVINFO_PDB20_CVSIGNATURE 0x3031424e // "NB10" +#define CVINFO_PDB70_CVSIGNATURE 0x53445352 // "RSDS" +#define CVINFO_PDB20_CVSIGNATURE 0x3031424e // "NB10" -typedef struct _CV_HEADER -{ - DWORD dwSignature; - DWORD dwOffset; +typedef struct _CV_HEADER { + DWORD dwSignature; + DWORD dwOffset; } CV_HEADER, *PCV_HEADER; -typedef struct _CV_INFO_PDB20 -{ - CV_HEADER CvHeader; - DWORD dwSignature; - DWORD dwAge; - BYTE PdbFileName[1]; +typedef struct _CV_INFO_PDB20 { + CV_HEADER CvHeader; + DWORD dwSignature; + DWORD dwAge; + BYTE PdbFileName[1]; } CV_INFO_PDB20, *PCV_INFO_PDB20; -typedef struct _CV_INFO_PDB70 -{ - DWORD CvSignature; - DWORD Signature[4]; - DWORD Age; - BYTE PdbFileName[1]; +typedef struct _CV_INFO_PDB70 { + DWORD CvSignature; + DWORD Signature[4]; + DWORD Age; + BYTE PdbFileName[1]; } CV_INFO_PDB70, *PCV_INFO_PDB70; -typedef struct _VERSION_INFO -{ - WORD Length; - WORD ValueLength; - WORD Type; - char Key[0]; +typedef struct _VERSION_INFO { + WORD Length; + WORD ValueLength; + WORD Type; + char Key[0]; } VERSION_INFO, *PVERSION_INFO; + #define MAX_PE_CERTS 16 #define WIN_CERT_REVISION_1_0 0x0100 @@ -818,60 +528,42 @@ typedef struct _VERSION_INFO #define WIN_CERT_TYPE_RESERVED_1 0x0003 #define WIN_CERT_TYPE_TS_STACK_SIGNED 0x0004 -#define WIN_CERTIFICATE_HEADER_SIZE 8 +#define WIN_CERTIFICATE_HEADER_SIZE 8 -typedef struct _WIN_CERTIFICATE -{ - DWORD Length; - WORD Revision; - WORD CertificateType; - BYTE Certificate[0]; +typedef struct _WIN_CERTIFICATE { + DWORD Length; + WORD Revision; + WORD CertificateType; + BYTE Certificate[0]; } WIN_CERTIFICATE, *PWIN_CERTIFICATE; -#define SPC_NESTED_SIGNATURE_OBJID "1.3.6.1.4.1.311.2.4.1" +#define SPC_NESTED_SIGNATURE_OBJID "1.3.6.1.4.1.311.2.4.1" + // // Rich signature. // http://www.ntcore.com/files/richsign.htm // -#define RICH_VERSION_ID(id_version) (id_version >> 16) +#define RICH_VERSION_ID(id_version) (id_version >> 16) #define RICH_VERSION_VERSION(id_version) (id_version & 0xFFFF) -#define IMAGE_DEBUG_TYPE_UNKNOWN 0 -#define IMAGE_DEBUG_TYPE_COFF 1 -#define IMAGE_DEBUG_TYPE_CODEVIEW 2 -#define IMAGE_DEBUG_TYPE_FPO 3 -#define IMAGE_DEBUG_TYPE_MISC 4 -#define IMAGE_DEBUG_TYPE_EXCEPTION 5 -#define IMAGE_DEBUG_TYPE_FIXUP 6 -#define IMAGE_DEBUG_TYPE_OMAP_TO_SRC 7 -#define IMAGE_DEBUG_TYPE_OMAP_FROM_SRC 8 -#define IMAGE_DEBUG_TYPE_BORLAND 9 -#define IMAGE_DEBUG_TYPE_RESERVED10 10 -#define IMAGE_DEBUG_TYPE_CLSID 11 -#define IMAGE_DEBUG_TYPE_VC_FEATURE 12 -#define IMAGE_DEBUG_TYPE_POGO 13 -#define IMAGE_DEBUG_TYPE_ILTCG 14 -#define IMAGE_DEBUG_TYPE_MPX 15 -#define IMAGE_DEBUG_TYPE_REPRO 16 -typedef struct _RICH_VERSION_INFO -{ - DWORD id_version; // tool id and version (use RICH_VERSION_ID and - // RICH_VERSION_VERSION macros) - DWORD times; // number of times this tool was used + +typedef struct _RICH_VERSION_INFO { + DWORD id_version; //tool id and version (use RICH_VERSION_ID and RICH_VERSION_VERSION macros) + DWORD times; //number of times this tool was used } RICH_VERSION_INFO, *PRICH_VERSION_INFO; -typedef struct _RICH_SIGNATURE -{ - DWORD dans; - DWORD key1; - DWORD key2; - DWORD key3; - RICH_VERSION_INFO versions[0]; +typedef struct _RICH_SIGNATURE { + DWORD dans; + DWORD key1; + DWORD key2; + DWORD key3; + RICH_VERSION_INFO versions[0]; } RICH_SIGNATURE, *PRICH_SIGNATURE; -#define RICH_DANS 0x536e6144 // "DanS" -#define RICH_RICH 0x68636952 // "Rich" +#define RICH_DANS 0x536e6144 // "DanS" +#define RICH_RICH 0x68636952 // "Rich" + #pragma pack(pop) #endif diff --git a/libyara/modules/pe/pe.c b/libyara/modules/pe/pe.c index b5cd8f383d..0efab1b9fc 100644 --- a/libyara/modules/pe/pe.c +++ b/libyara/modules/pe/pe.c @@ -27,16 +27,16 @@ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include #include +#include #include #include "../crypto.h" #if defined(HAVE_LIBCRYPTO) +#include #include #include #include -#include #include #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) @@ -44,24 +44,22 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endif #if OPENSSL_VERSION_NUMBER < 0x10100000L -#define X509_get0_notBefore X509_get_notBefore -#define X509_get0_notAfter X509_get_notAfter +#define X509_getm_notBefore X509_get_notBefore +#define X509_getm_notAfter X509_get_notAfter #endif #endif #include -#include -#include #include -#include +#include +#include #include #include -#define MODULE_NAME pe -#define IMPORT_STANDARD 1 -#define IMPORT_DELAYED 2 -#define IMPORT_ANY (~0) +#include + +#define MODULE_NAME pe // http://msdn.microsoft.com/en-us/library/ms648009(v=vs.85).aspx #define RESOURCE_TYPE_CURSOR 1 @@ -75,46 +73,53 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define RESOURCE_TYPE_ACCELERATOR 9 #define RESOURCE_TYPE_RCDATA 10 #define RESOURCE_TYPE_MESSAGETABLE 11 -#define RESOURCE_TYPE_GROUP_CURSOR \ - 12 // MAKEINTRESOURCE((ULONG_PTR)(RT_CURSOR) + 11) -#define RESOURCE_TYPE_GROUP_ICON \ - 14 // MAKEINTRESOURCE((ULONG_PTR)(RT_ICON) + 11) -#define RESOURCE_TYPE_VERSION 16 -#define RESOURCE_TYPE_DLGINCLUDE 17 -#define RESOURCE_TYPE_PLUGPLAY 19 -#define RESOURCE_TYPE_VXD 20 -#define RESOURCE_TYPE_ANICURSOR 21 -#define RESOURCE_TYPE_ANIICON 22 -#define RESOURCE_TYPE_HTML 23 -#define RESOURCE_TYPE_MANIFEST 24 - -#define RESOURCE_CALLBACK_CONTINUE 0 -#define RESOURCE_CALLBACK_ABORT 1 - -#define RESOURCE_ITERATOR_FINISHED 0 -#define RESOURCE_ITERATOR_ABORTED 1 - -#define MAX_PE_IMPORTS 16384 -#define MAX_PE_EXPORTS 8192 -#define MAX_EXPORT_NAME_LENGTH 512 -#define MAX_RESOURCES 65536 +#define RESOURCE_TYPE_GROUP_CURSOR 12 // MAKEINTRESOURCE((ULONG_PTR)(RT_CURSOR) + 11) +#define RESOURCE_TYPE_GROUP_ICON 14 // MAKEINTRESOURCE((ULONG_PTR)(RT_ICON) + 11) +#define RESOURCE_TYPE_VERSION 16 +#define RESOURCE_TYPE_DLGINCLUDE 17 +#define RESOURCE_TYPE_PLUGPLAY 19 +#define RESOURCE_TYPE_VXD 20 +#define RESOURCE_TYPE_ANICURSOR 21 +#define RESOURCE_TYPE_ANIICON 22 +#define RESOURCE_TYPE_HTML 23 +#define RESOURCE_TYPE_MANIFEST 24 + + +#define RESOURCE_CALLBACK_CONTINUE 0 +#define RESOURCE_CALLBACK_ABORT 1 + + +#define RESOURCE_ITERATOR_FINISHED 0 +#define RESOURCE_ITERATOR_ABORTED 1 + + +#define MAX_PE_IMPORTS 16384 +#define MAX_PE_EXPORTS 8192 +#define MAX_EXPORT_NAME_LENGTH 512 + #define IS_RESOURCE_SUBDIRECTORY(entry) \ - (yr_le32toh((entry)->OffsetToData) & 0x80000000) + ((entry)->OffsetToData & 0x80000000) -#define RESOURCE_OFFSET(entry) (yr_le32toh((entry)->OffsetToData) & 0x7FFFFFFF) -typedef int (*RESOURCE_CALLBACK_FUNC)( - PIMAGE_RESOURCE_DATA_ENTRY rsrc_data, - int rsrc_type, - int rsrc_id, - int rsrc_language, - const IMAGE_RESOURCE_DIR_STRING_U* type_string, - const IMAGE_RESOURCE_DIR_STRING_U* name_string, - const IMAGE_RESOURCE_DIR_STRING_U* lang_string, - void* cb_data); +#define RESOURCE_OFFSET(entry) \ + ((entry)->OffsetToData & 0x7FFFFFFF) + + +typedef int (*RESOURCE_CALLBACK_FUNC) ( \ + PIMAGE_RESOURCE_DATA_ENTRY rsrc_data, \ + int rsrc_type, \ + int rsrc_id, \ + int rsrc_language, \ + const uint8_t* type_string, \ + const uint8_t* name_string, \ + const uint8_t* lang_string, \ + void* cb_data); -static size_t available_space(PE* pe, void* pointer) + +static size_t available_space( + PE* pe, + void* pointer) { if ((uint8_t*) pointer < pe->data) return 0; @@ -125,7 +130,10 @@ static size_t available_space(PE* pe, void* pointer) return pe->data + pe->data_size - (uint8_t*) pointer; } -static int wide_string_fits_in_pe(PE* pe, char* data) + +static int wide_string_fits_in_pe( + PE* pe, + char* data) { size_t i = 0; size_t space_left = available_space(pe, data); @@ -141,10 +149,13 @@ static int wide_string_fits_in_pe(PE* pe, char* data) return 0; } + // Parse the rich signature. // http://www.ntcore.com/files/richsign.htm -static void pe_parse_rich_signature(PE* pe, uint64_t base_address) +static void pe_parse_rich_signature( + PE* pe, + uint64_t base_address) { PIMAGE_DOS_HEADER mz_header; PRICH_SIGNATURE rich_signature = NULL; @@ -175,11 +186,10 @@ static void pe_parse_rich_signature(PE* pe, uint64_t base_address) // true. 582ce3eea9c97d5e89f7d83953a6d518b16770e635a19a456c0225449c6967a4 is // one sample which has a Rich header starting at offset 0x200. To properly // find the Rich header we need to start at the NT header and work backwards. - p = (DWORD*) (pe->data + nthdr_offset - 4); - - while (p >= (DWORD*) (pe->data + sizeof(IMAGE_DOS_HEADER))) + p = (DWORD*)(pe->data + nthdr_offset - 4); + while (p > (DWORD*)(pe->data + sizeof(IMAGE_DOS_HEADER))) { - if (yr_le32toh(*p) == RICH_RICH) + if (*p == RICH_RICH) { // The XOR key is the dword following the Rich value. We use this to find // DanS header only. @@ -198,9 +208,9 @@ static void pe_parse_rich_signature(PE* pe, uint64_t base_address) return; // If we have found the key we need to now find the start (DanS). - while (p >= (DWORD*) (pe->data + sizeof(IMAGE_DOS_HEADER))) + while (p > (DWORD*)(pe->data + sizeof(IMAGE_DOS_HEADER))) { - if (yr_le32toh((*(p) ^ key)) == RICH_DANS) + if ((*(p) ^ key) == RICH_DANS) { rich_signature = (PRICH_SIGNATURE) p; break; @@ -219,8 +229,7 @@ static void pe_parse_rich_signature(PE* pe, uint64_t base_address) if (yr_le32toh(rich_signature->key1) != yr_le32toh(rich_signature->key2) || yr_le32toh(rich_signature->key2) != yr_le32toh(rich_signature->key3) || - (yr_le32toh(rich_signature->dans) ^ yr_le32toh(rich_signature->key1)) != - RICH_DANS) + (yr_le32toh(rich_signature->dans) ^ yr_le32toh(rich_signature->key1)) != RICH_DANS) { return; } @@ -236,13 +245,11 @@ static void pe_parse_rich_signature(PE* pe, uint64_t base_address) set_integer( base_address + ((uint8_t*) rich_signature - pe->data), - pe->object, - "rich_signature.offset"); + pe->object, "rich_signature.offset"); set_integer(rich_len, pe->object, "rich_signature.length"); - set_integer( - yr_le32toh(rich_signature->key1), pe->object, "rich_signature.key"); + set_integer(rich_signature->key1, pe->object, "rich_signature.key"); clear_data = (BYTE*) yr_malloc(rich_len); @@ -270,32 +277,38 @@ static void pe_parse_rich_signature(PE* pe, uint64_t base_address) yr_free(raw_data); yr_free(clear_data); + return; } -static void pe_parse_debug_directory(PE* pe) + +static void pe_parse_debug_directory( + PE* pe) { PIMAGE_DATA_DIRECTORY data_dir; PIMAGE_DEBUG_DIRECTORY debug_dir; int64_t debug_dir_offset; + int64_t pcv_hdr_offset; int i, dcount; + int repro = 0; size_t pdb_path_len; char* pdb_path = NULL; + + data_dir = pe_get_directory_entry( + pe, IMAGE_DIRECTORY_ENTRY_DEBUG); - data_dir = pe_get_directory_entry(pe, IMAGE_DIRECTORY_ENTRY_DEBUG); - - if (data_dir == NULL) - return; - - if (yr_le32toh(data_dir->Size) == 0) - return; + if (data_dir == NULL || + yr_le32toh(data_dir->Size) == 0 || + yr_le32toh(data_dir->VirtualAddress) == 0) + { + set_integer(0, pe->object, "is_reproducible_build"); + return; + } if (yr_le32toh(data_dir->Size) % sizeof(IMAGE_DEBUG_DIRECTORY) != 0) return; - if (yr_le32toh(data_dir->VirtualAddress) == 0) - return; - - debug_dir_offset = pe_rva_to_offset(pe, yr_le32toh(data_dir->VirtualAddress)); + debug_dir_offset = pe_rva_to_offset( + pe, yr_le32toh(data_dir->VirtualAddress)); if (debug_dir_offset < 0) return; @@ -304,36 +317,31 @@ static void pe_parse_debug_directory(PE* pe) for (i = 0; i < dcount; i++) { - int64_t pcv_hdr_offset = 0; - - debug_dir = (PIMAGE_DEBUG_DIRECTORY)( - pe->data + debug_dir_offset + i * sizeof(IMAGE_DEBUG_DIRECTORY)); - + debug_dir = (PIMAGE_DEBUG_DIRECTORY) \ + (pe->data + debug_dir_offset + i * sizeof(IMAGE_DEBUG_DIRECTORY)); + if (!struct_fits_in_pe(pe, debug_dir, IMAGE_DEBUG_DIRECTORY)) break; - if (yr_le32toh(debug_dir->Type) != IMAGE_DEBUG_TYPE_CODEVIEW) - continue; - - // The debug info offset may be present either as RVA or as raw offset - // Sample: 0249e00b6d46bee5a17096559f18e671cd0ceee36373e8708f614a9a6c7c079e - if (debug_dir->AddressOfRawData != 0) - { - pcv_hdr_offset = pe_rva_to_offset( - pe, yr_le32toh(debug_dir->AddressOfRawData)); - } - - // Give it chance to read it from the RAW offset - // Sample: 735f72b3fcd72789f01e923c9de2a9ab5b5ffbece23633da81d976ad0ad159e3 - if (pcv_hdr_offset <= 0 && debug_dir->PointerToRawData != 0) + if (yr_le32toh(debug_dir->Type) == IMAGE_DEBUG_TYPE_REPRO) { - pcv_hdr_offset = yr_le32toh(debug_dir->PointerToRawData); + repro = 1; + continue; } + + if (yr_le32toh(debug_dir->Type) != IMAGE_DEBUG_TYPE_CODEVIEW) + continue; + + if (yr_le32toh(debug_dir->AddressOfRawData) == 0) + continue; + + pcv_hdr_offset = pe_rva_to_offset( + pe, yr_le32toh(debug_dir->AddressOfRawData)); - if (pcv_hdr_offset <= 0) + if (pcv_hdr_offset < 0) continue; - PCV_HEADER cv_hdr = (PCV_HEADER)(pe->data + pcv_hdr_offset); + PCV_HEADER cv_hdr = (PCV_HEADER) (pe->data + pcv_hdr_offset); if (!struct_fits_in_pe(pe, cv_hdr, CV_HEADER)) continue; @@ -341,14 +349,14 @@ static void pe_parse_debug_directory(PE* pe) if (yr_le32toh(cv_hdr->dwSignature) == CVINFO_PDB20_CVSIGNATURE) { PCV_INFO_PDB20 pdb20 = (PCV_INFO_PDB20) cv_hdr; - + if (struct_fits_in_pe(pe, pdb20, CV_INFO_PDB20)) pdb_path = (char*) (pdb20->PdbFileName); } else if (yr_le32toh(cv_hdr->dwSignature) == CVINFO_PDB70_CVSIGNATURE) { PCV_INFO_PDB70 pdb70 = (PCV_INFO_PDB70) cv_hdr; - + if (struct_fits_in_pe(pe, pdb70, CV_INFO_PDB70)) pdb_path = (char*) (pdb70->PdbFileName); } @@ -361,47 +369,57 @@ static void pe_parse_debug_directory(PE* pe) if (pdb_path_len > 0 && pdb_path_len < MAX_PATH) { set_sized_string(pdb_path, pdb_path_len, pe->object, "pdb_path"); - break; } } } + + if (repro == 1) + set_integer(1, pe->object, "is_reproducible_build"); + else if (i == dcount) + set_integer(0, pe->object, "is_reproducible_build"); + + return; } // Return a pointer to the resource directory string or NULL. // The callback function will parse this and call set_sized_string(). // The pointer is guaranteed to have enough space to contain the entire string. -static const PIMAGE_RESOURCE_DIR_STRING_U parse_resource_name( +static const uint8_t* parse_resource_name( PE* pe, const uint8_t* rsrc_data, PIMAGE_RESOURCE_DIRECTORY_ENTRY entry) { + // If high bit is set it is an offset relative to rsrc_data, which contains // a resource directory string. if (yr_le32toh(entry->Name) & 0x80000000) { - const PIMAGE_RESOURCE_DIR_STRING_U pNameString = - (PIMAGE_RESOURCE_DIR_STRING_U)( - rsrc_data + (yr_le32toh(entry->Name) & 0x7FFFFFFF)); + DWORD length; + + const uint8_t* rsrc_str_ptr = rsrc_data + \ + (yr_le32toh(entry->Name) & 0x7FFFFFFF); // A resource directory string is 2 bytes for the length and then a variable // length Unicode string. Make sure we have at least 2 bytes. - if (!fits_in_pe(pe, pNameString, 2)) + if (!fits_in_pe(pe, rsrc_str_ptr, 2)) return NULL; + length = *rsrc_str_ptr; + // Move past the length and make sure we have enough bytes for the string. - if (!fits_in_pe( - pe, pNameString, sizeof(uint16_t) + pNameString->Length * 2)) + if (!fits_in_pe(pe, rsrc_str_ptr + 2, length * 2)) return NULL; - return pNameString; + return rsrc_str_ptr; } return NULL; } + static int _pe_iterate_resources( PE* pe, PIMAGE_RESOURCE_DIRECTORY resource_dir, @@ -410,9 +428,9 @@ static int _pe_iterate_resources( int* type, int* id, int* language, - const IMAGE_RESOURCE_DIR_STRING_U* type_string, - const IMAGE_RESOURCE_DIR_STRING_U* name_string, - const IMAGE_RESOURCE_DIR_STRING_U* lang_string, + const uint8_t* type_string, + const uint8_t* name_string, + const uint8_t* lang_string, RESOURCE_CALLBACK_FUNC callback, void* callback_data) { @@ -437,7 +455,7 @@ static int _pe_iterate_resources( // by incrementing resource_dir we skip sizeof(resource_dir) bytes // and get a pointer to the end of the resource directory. - entry = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(resource_dir + 1); + entry = (PIMAGE_RESOURCE_DIRECTORY_ENTRY) (resource_dir + 1); for (i = 0; i < total_entries; i++) { @@ -447,26 +465,26 @@ static int _pe_iterate_resources( break; } - switch (rsrc_tree_level) + switch(rsrc_tree_level) { - case 0: - *type = yr_le32toh(entry->Name); - type_string = parse_resource_name(pe, rsrc_data, entry); - break; - case 1: - *id = yr_le32toh(entry->Name); - name_string = parse_resource_name(pe, rsrc_data, entry); - break; - case 2: - *language = yr_le32toh(entry->Name); - lang_string = parse_resource_name(pe, rsrc_data, entry); - break; + case 0: + *type = yr_le32toh(entry->Name); + type_string = parse_resource_name(pe, rsrc_data, entry); + break; + case 1: + *id = yr_le32toh(entry->Name); + name_string = parse_resource_name(pe, rsrc_data, entry); + break; + case 2: + *language = yr_le32toh(entry->Name); + lang_string = parse_resource_name(pe, rsrc_data, entry); + break; } if (IS_RESOURCE_SUBDIRECTORY(entry) && rsrc_tree_level < 2) { - PIMAGE_RESOURCE_DIRECTORY directory = (PIMAGE_RESOURCE_DIRECTORY)( - rsrc_data + RESOURCE_OFFSET(entry)); + PIMAGE_RESOURCE_DIRECTORY directory = (PIMAGE_RESOURCE_DIRECTORY) \ + (rsrc_data + RESOURCE_OFFSET(entry)); if (struct_fits_in_pe(pe, directory, IMAGE_RESOURCE_DIRECTORY)) { @@ -491,20 +509,20 @@ static int _pe_iterate_resources( } else { - PIMAGE_RESOURCE_DATA_ENTRY data_entry = (PIMAGE_RESOURCE_DATA_ENTRY)( - rsrc_data + RESOURCE_OFFSET(entry)); + PIMAGE_RESOURCE_DATA_ENTRY data_entry = (PIMAGE_RESOURCE_DATA_ENTRY) \ + (rsrc_data + RESOURCE_OFFSET(entry)); if (struct_fits_in_pe(pe, data_entry, IMAGE_RESOURCE_DATA_ENTRY)) { if (callback( - data_entry, - *type, - *id, - *language, - type_string, - name_string, - lang_string, - callback_data) == RESOURCE_CALLBACK_ABORT) + data_entry, + *type, + *id, + *language, + type_string, + name_string, + lang_string, + callback_data) == RESOURCE_CALLBACK_ABORT) { result = RESOURCE_ITERATOR_ABORTED; } @@ -524,6 +542,7 @@ static int _pe_iterate_resources( return result; } + static int pe_iterate_resources( PE* pe, RESOURCE_CALLBACK_FUNC callback, @@ -535,15 +554,15 @@ static int pe_iterate_resources( int id = -1; int language = -1; - IMAGE_RESOURCE_DIR_STRING_U* type_string = NULL; - IMAGE_RESOURCE_DIR_STRING_U* name_string = NULL; - IMAGE_RESOURCE_DIR_STRING_U* lang_string = NULL; + uint8_t* type_string = NULL; + uint8_t* name_string = NULL; + uint8_t* lang_string = NULL; PIMAGE_DATA_DIRECTORY directory = pe_get_directory_entry( pe, IMAGE_DIRECTORY_ENTRY_RESOURCE); if (directory == NULL) - return 0; + return 0; if (yr_le32toh(directory->VirtualAddress) != 0) { @@ -554,24 +573,20 @@ static int pe_iterate_resources( if (offset < 0) return 0; - rsrc_dir = (PIMAGE_RESOURCE_DIRECTORY)(pe->data + offset); + rsrc_dir = (PIMAGE_RESOURCE_DIRECTORY) (pe->data + offset); if (struct_fits_in_pe(pe, rsrc_dir, IMAGE_RESOURCE_DIRECTORY)) { - set_integer( - yr_le32toh(rsrc_dir->TimeDateStamp), + set_integer(yr_le32toh(rsrc_dir->TimeDateStamp), pe->object, "resource_timestamp"); - set_integer( - yr_le16toh(rsrc_dir->MajorVersion), - pe->object, - "resource_version.major"); - - set_integer( - yr_le16toh(rsrc_dir->MinorVersion), - pe->object, - "resource_version.minor"); + set_integer(yr_le16toh(rsrc_dir->MajorVersion), + pe->object, + "resource_version.major"); + set_integer(yr_le16toh(rsrc_dir->MinorVersion), + pe->object, + "resource_version.minor"); _pe_iterate_resources( pe, @@ -594,12 +609,16 @@ static int pe_iterate_resources( return 0; } + // Align offset to a 32-bit boundary and add it to a pointer #define ADD_OFFSET(ptr, offset) \ - (PVERSION_INFO)((uint8_t*) (ptr) + ((offset + 3) & ~3)) + (PVERSION_INFO) ((uint8_t*) (ptr) + ((offset + 3) & ~3)) + -static void pe_parse_version_info(PIMAGE_RESOURCE_DATA_ENTRY rsrc_data, PE* pe) +static void pe_parse_version_info( + PIMAGE_RESOURCE_DATA_ENTRY rsrc_data, + PE* pe) { PVERSION_INFO version_info; @@ -609,7 +628,7 @@ static void pe_parse_version_info(PIMAGE_RESOURCE_DATA_ENTRY rsrc_data, PE* pe) if (version_info_offset < 0) return; - version_info = (PVERSION_INFO)(pe->data + version_info_offset); + version_info = (PVERSION_INFO) (pe->data + version_info_offset); if (!struct_fits_in_pe(pe, version_info, VERSION_INFO)) return; @@ -620,66 +639,63 @@ static void pe_parse_version_info(PIMAGE_RESOURCE_DATA_ENTRY rsrc_data, PE* pe) if (strcmp_w(version_info->Key, "VS_VERSION_INFO") != 0) return; - version_info = ADD_OFFSET(version_info, sizeof(VERSION_INFO) + 86); + version_info = ADD_OFFSET( + version_info, sizeof(VERSION_INFO) + 86); - while (fits_in_pe(pe, version_info->Key, sizeof("VarFileInfo") * 2) && - strcmp_w(version_info->Key, "VarFileInfo") == 0 && - yr_le16toh(version_info->Length) != 0) + while(fits_in_pe(pe, version_info->Key, sizeof("VarFileInfo") * 2) && + strcmp_w(version_info->Key, "VarFileInfo") == 0 && + yr_le16toh(version_info->Length) != 0) { - version_info = ADD_OFFSET(version_info, yr_le16toh(version_info->Length)); + version_info = ADD_OFFSET( + version_info, + yr_le16toh(version_info->Length)); } - while (fits_in_pe(pe, version_info->Key, sizeof("StringFileInfo") * 2) && - strcmp_w(version_info->Key, "StringFileInfo") == 0 && - yr_le16toh(version_info->Length) != 0) + while(fits_in_pe(pe, version_info->Key, sizeof("StringFileInfo") * 2) && + strcmp_w(version_info->Key, "StringFileInfo") == 0 && + yr_le16toh(version_info->Length) != 0) { PVERSION_INFO string_table = ADD_OFFSET( - version_info, sizeof(VERSION_INFO) + 30); + version_info, + sizeof(VERSION_INFO) + 30); - version_info = ADD_OFFSET(version_info, yr_le16toh(version_info->Length)); + version_info = ADD_OFFSET( + version_info, + yr_le16toh(version_info->Length)); while (struct_fits_in_pe(pe, string_table, VERSION_INFO) && wide_string_fits_in_pe(pe, string_table->Key) && - yr_le16toh(string_table->Length) != 0 && string_table < version_info) + yr_le16toh(string_table->Length) != 0 && + string_table < version_info) { PVERSION_INFO string = ADD_OFFSET( string_table, sizeof(VERSION_INFO) + 2 * (strnlen_w(string_table->Key) + 1)); - string_table = ADD_OFFSET(string_table, yr_le16toh(string_table->Length)); + string_table = ADD_OFFSET( + string_table, + yr_le16toh(string_table->Length)); while (struct_fits_in_pe(pe, string, VERSION_INFO) && wide_string_fits_in_pe(pe, string->Key) && - yr_le16toh(string->Length) != 0 && string < string_table) + yr_le16toh(string->Length) != 0 && + string < string_table) { - char* string_value = (char*) ADD_OFFSET( - string, sizeof(VERSION_INFO) + 2 * (strnlen_w(string->Key) + 1)); - - if (wide_string_fits_in_pe(pe, string_value)) + if (yr_le16toh(string->ValueLength) > 0) { - char key[64]; - char value[256]; + char* string_value = (char*) ADD_OFFSET(string, + sizeof(VERSION_INFO) + 2 * (strnlen_w(string->Key) + 1)); - strlcpy_w(key, string->Key, sizeof(key)); - strlcpy_w(value, string_value, sizeof(value)); - - // null terminator of string is not included in version value when - // ValueLength is zero - if (yr_le16toh(string->ValueLength) == 0) - value[yr_le16toh(string->ValueLength)] = '\0'; - - set_string(value, pe->object, "version_info[%s]", key); - - set_string( - key, pe->object, "version_info_list[%i].key", pe->version_infos); + if (wide_string_fits_in_pe(pe, string_value)) + { + char key[64]; + char value[256]; - set_string( - value, - pe->object, - "version_info_list[%i].value", - pe->version_infos); + strlcpy_w(key, string->Key, sizeof(key)); + strlcpy_w(value, string_value, sizeof(value)); - pe->version_infos += 1; + set_string(value, pe->object, "version_info[%s]", key); + } } string = ADD_OFFSET(string, yr_le16toh(string->Length)); @@ -688,89 +704,93 @@ static void pe_parse_version_info(PIMAGE_RESOURCE_DATA_ENTRY rsrc_data, PE* pe) } } -static void pe_set_resource_string_or_id( - IMAGE_RESOURCE_DIR_STRING_U* rsrc_string, - int rsrc_int, - const char* string_description, - const char* int_description, - PE* pe) -{ - if (rsrc_string) - { - // Multiply by 2 because it is a Unicode string. - size_t length = rsrc_string->Length * 2; - - // Check if the whole string fits in the PE image. - // If not, the name becomes UNDEFINED by default. - if (fits_in_pe(pe, rsrc_string->NameString, length)) - { - set_sized_string( - (char*) rsrc_string->NameString, - length, - pe->object, - string_description, - pe->resources); - } - } - else - { - set_integer(rsrc_int, pe->object, int_description, pe->resources); - } -} static int pe_collect_resources( PIMAGE_RESOURCE_DATA_ENTRY rsrc_data, int rsrc_type, int rsrc_id, int rsrc_language, - IMAGE_RESOURCE_DIR_STRING_U* type_string, - IMAGE_RESOURCE_DIR_STRING_U* name_string, - IMAGE_RESOURCE_DIR_STRING_U* lang_string, + uint8_t* type_string, + uint8_t* name_string, + uint8_t* lang_string, PE* pe) { - // Don't collect too many resources. - if (pe->resources > MAX_RESOURCES) - return RESOURCE_CALLBACK_CONTINUE; - - set_integer( - yr_le32toh(rsrc_data->OffsetToData), - pe->object, - "resources[%i].rva", - pe->resources); + DWORD length; int64_t offset = pe_rva_to_offset(pe, yr_le32toh(rsrc_data->OffsetToData)); if (offset < 0) - offset = YR_UNDEFINED; + return RESOURCE_CALLBACK_CONTINUE; + + if (!fits_in_pe(pe, pe->data + offset, yr_le32toh(rsrc_data->Size))) + return RESOURCE_CALLBACK_CONTINUE; - set_integer(offset, pe->object, "resources[%i].offset", pe->resources); + set_integer( + offset, + pe->object, + "resources[%i].offset", + pe->resources); set_integer( - yr_le32toh(rsrc_data->Size), - pe->object, - "resources[%i].length", - pe->resources); + yr_le32toh(rsrc_data->Size), + pe->object, + "resources[%i].length", + pe->resources); - pe_set_resource_string_or_id( - type_string, - rsrc_type, - "resources[%i].type_string", - "resources[%i].type", - pe); + if (type_string) + { + // Multiply by 2 because it is a Unicode string. + length = ((DWORD) *type_string) * 2; + type_string += 2; - pe_set_resource_string_or_id( - name_string, - rsrc_id, - "resources[%i].name_string", - "resources[%i].id", - pe); + set_sized_string( + (char*) type_string, length, pe->object, + "resources[%i].type_string", pe->resources); + } + else + { + set_integer( + rsrc_type, + pe->object, + "resources[%i].type", + pe->resources); + } - pe_set_resource_string_or_id( - lang_string, - rsrc_language, - "resources[%i].language_string", - "resources[%i].language", - pe); + if (name_string) + { + // Multiply by 2 because it is a Unicode string. + length = ((DWORD) *name_string) * 2; + name_string += 2; + set_sized_string( + (char*) name_string, length, pe->object, + "resources[%i].name_string", pe->resources); + } + else + { + set_integer( + rsrc_id, + pe->object, + "resources[%i].id", + pe->resources); + } + + if (lang_string) + { + // Multiply by 2 because it is a Unicode string. + length = ((DWORD) *lang_string) * 2; + lang_string += 2; + set_sized_string( + (char*) lang_string, length, pe->object, + "resources[%i].language_string", pe->resources); + } + else + { + set_integer( + rsrc_language, + pe->object, + "resources[%i].language", + pe->resources); + } // Resources we do extra parsing on if (rsrc_type == RESOURCE_TYPE_VERSION) @@ -780,6 +800,7 @@ static int pe_collect_resources( return RESOURCE_CALLBACK_CONTINUE; } + static IMPORT_FUNCTION* pe_parse_import_descriptor( PE* pe, PIMAGE_IMPORT_DESCRIPTOR import_descriptor, @@ -820,12 +841,12 @@ static IMPORT_FUNCTION* pe_parse_import_descriptor( if (offset >= 0) { - PIMAGE_IMPORT_BY_NAME import = (PIMAGE_IMPORT_BY_NAME)( - pe->data + offset); + PIMAGE_IMPORT_BY_NAME import = (PIMAGE_IMPORT_BY_NAME) \ + (pe->data + offset); if (struct_fits_in_pe(pe, import, IMAGE_IMPORT_BY_NAME)) { - name = (char*) yr_strndup( + name = (char *) yr_strndup( (char*) import->Name, yr_min(available_space(pe, import->Name), 512)); } @@ -842,8 +863,8 @@ static IMPORT_FUNCTION* pe_parse_import_descriptor( if (name != NULL || has_ordinal == 1) { - IMPORT_FUNCTION* imported_func = (IMPORT_FUNCTION*) yr_calloc( - 1, sizeof(IMPORT_FUNCTION)); + IMPORT_FUNCTION* imported_func = (IMPORT_FUNCTION*) + yr_calloc(1, sizeof(IMPORT_FUNCTION)); if (imported_func == NULL) { @@ -874,8 +895,7 @@ static IMPORT_FUNCTION* pe_parse_import_descriptor( PIMAGE_THUNK_DATA32 thunks32 = (PIMAGE_THUNK_DATA32)(pe->data + offset); while (struct_fits_in_pe(pe, thunks32, IMAGE_THUNK_DATA32) && - yr_le32toh(thunks32->u1.Ordinal) != 0 && - *num_function_imports < MAX_PE_IMPORTS) + yr_le32toh(thunks32->u1.Ordinal) != 0 && *num_function_imports < MAX_PE_IMPORTS) { char* name = NULL; uint16_t ordinal = 0; @@ -888,12 +908,12 @@ static IMPORT_FUNCTION* pe_parse_import_descriptor( if (offset >= 0) { - PIMAGE_IMPORT_BY_NAME import = (PIMAGE_IMPORT_BY_NAME)( - pe->data + offset); + PIMAGE_IMPORT_BY_NAME import = (PIMAGE_IMPORT_BY_NAME) \ + (pe->data + offset); if (struct_fits_in_pe(pe, import, IMAGE_IMPORT_BY_NAME)) { - name = (char*) yr_strndup( + name = (char *) yr_strndup( (char*) import->Name, yr_min(available_space(pe, import->Name), 512)); } @@ -910,8 +930,8 @@ static IMPORT_FUNCTION* pe_parse_import_descriptor( if (name != NULL || has_ordinal == 1) { - IMPORT_FUNCTION* imported_func = (IMPORT_FUNCTION*) yr_calloc( - 1, sizeof(IMPORT_FUNCTION)); + IMPORT_FUNCTION* imported_func = (IMPORT_FUNCTION*) + yr_calloc(1, sizeof(IMPORT_FUNCTION)); if (imported_func == NULL) { @@ -941,78 +961,33 @@ static IMPORT_FUNCTION* pe_parse_import_descriptor( return head; } -// -// In Windows PE files, any character including 0x20 and above is allowed. -// The only exceptions are characters that are invalid for file names in -// Windows, which are "*<>?|. While they still can be present in the import -// directory, such module can never be present in Windows, so we can treat them -// as invalid. -// -// Explicit: The above also applies to slash, backslash (these form a relative -// path in a subdirectory, which is allowed in the import directory) and colon -// (which forms a file name with an Alternate Data Stream "test:file.dll" - also -// allowed). -// -// Proof of concept: https://github.com/ladislav-zezula/ImportTest -// -// Samples -// ------- -// f561d60bff4342e529b2c793e216b73a72e6256f90ab24c3cc460646371130ca (imports -// "test/file.dll") -// b7f7b8a001769eb0f9c36cb27626b62cabdca9a716a222066028fcd206244b40 (imports -// "test\file.dll") -// 94cfb8223132da0a76f9dfbd35a29ab78e5806651758650292ab9c7baf2c0bc2 (imports -// "test:file.dll") -// eb2e2c443840276afe095fff05a3a24c00e610ac0e020233d6cd7a0b0b340fb1 (the -// imported DLL) -// -static int pe_valid_dll_name(const char* dll_name, size_t n) +static int pe_valid_dll_name( + const char* dll_name, + size_t n) { - const unsigned char* c = (const unsigned char*) dll_name; + const char* c = dll_name; size_t l = 0; while (l < n && *c != '\0') { - if (*c < ' ' || *c == '\"' || *c == '*' || *c == '<' || *c == '>' || - *c == '?' || *c == '|') + if ((*c >= 'a' && *c <= 'z') || + (*c >= 'A' && *c <= 'Z') || + (*c >= '0' && *c <= '9') || + (*c == '_' || *c == '.' || *c == '-')) + { + c++; + l++; + } + else { return false; } - - c++; - l++; } return (l > 0 && l < n); } -void pe_set_imports( - PE* pe, - IMPORTED_DLL* dll, - const char* dll_name, - const char* dll_number_of_functions, - const char* fun_name, - const char* fun_ordinal) -{ - int dll_cnt = 0; - int fun_cnt = 0; - - for (; dll != NULL; dll = dll->next, dll_cnt++) - { - for (IMPORT_FUNCTION* func = dll->functions; func != NULL; - func = func->next, fun_cnt++) - { - set_string(func->name, pe->object, fun_name, dll_cnt, fun_cnt); - if (func->has_ordinal) - set_integer(func->ordinal, pe->object, fun_ordinal, dll_cnt, fun_cnt); - else - set_integer(YR_UNDEFINED, pe->object, fun_ordinal, dll_cnt, fun_cnt); - } - set_string(dll->name, pe->object, dll_name, dll_cnt); - set_integer(fun_cnt, pe->object, dll_number_of_functions, dll_cnt); - } -} // // Walk the imports and collect relevant information. It is used in the @@ -1020,7 +995,8 @@ void pe_set_imports( // calculation. // -static IMPORTED_DLL* pe_parse_imports(PE* pe) +static IMPORTED_DLL* pe_parse_imports( + PE* pe) { int64_t offset; int num_imports = 0; // Number of imported DLLs @@ -1034,9 +1010,9 @@ static IMPORTED_DLL* pe_parse_imports(PE* pe) // Default to 0 imports until we know there are any set_integer(0, pe->object, "number_of_imports"); - set_integer(0, pe->object, "number_of_imported_functions"); - directory = pe_get_directory_entry(pe, IMAGE_DIRECTORY_ENTRY_IMPORT); + directory = pe_get_directory_entry( + pe, IMAGE_DIRECTORY_ENTRY_IMPORT); if (directory == NULL) return NULL; @@ -1049,7 +1025,8 @@ static IMPORTED_DLL* pe_parse_imports(PE* pe) if (offset < 0) return NULL; - imports = (PIMAGE_IMPORT_DESCRIPTOR)(pe->data + offset); + imports = (PIMAGE_IMPORT_DESCRIPTOR) \ + (pe->data + offset); while (struct_fits_in_pe(pe, imports, IMAGE_IMPORT_DESCRIPTOR) && yr_le32toh(imports->Name) != 0 && num_imports < MAX_PE_IMPORTS) @@ -1060,12 +1037,12 @@ static IMPORTED_DLL* pe_parse_imports(PE* pe) { IMPORTED_DLL* imported_dll; - char* dll_name = (char*) (pe->data + offset); + char* dll_name = (char *) (pe->data + offset); if (!pe_valid_dll_name(dll_name, pe->data_size - (size_t) offset)) { - imports++; - continue; + imports++; + continue; } imported_dll = (IMPORTED_DLL*) yr_calloc(1, sizeof(IMPORTED_DLL)); @@ -1077,8 +1054,7 @@ static IMPORTED_DLL* pe_parse_imports(PE* pe) if (functions != NULL) { - imported_dll->name = yr_strdup(dll_name); - ; + imported_dll->name = yr_strdup(dll_name);; imported_dll->functions = functions; imported_dll->next = NULL; @@ -1102,318 +1078,27 @@ static IMPORTED_DLL* pe_parse_imports(PE* pe) } set_integer(num_imports, pe->object, "number_of_imports"); - set_integer(num_function_imports, pe->object, "number_of_imported_functions"); - pe_set_imports( - pe, - head, - "import_details[%i].library_name", - "import_details[%i].number_of_functions", - "import_details[%i].functions[%i].name", - "import_details[%i].functions[%i].ordinal"); - return head; } -// Delay-import descriptors made by MS Visual C++ 6.0 have old format -// of delay import directory, where all entries are VAs (as opposite to RVAs -// from newer MS compilers). We convert the delay-import directory entries to -// RVAs by checking the lowest bit in the delay-import descriptor's Attributes -// value -uint64_t pe_normalize_delay_import_value( - uint64_t image_base, - uint64_t virtual_address) -{ - // Ignore zero items - if (virtual_address != 0) - { - // Sample: 0fc4cb0620f95bdd624f2c78eea4d2b59594244c6671cf249526adf2f2cb71ec - // Contains artificially created delay import directory with incorrect - // values: - // - // Attributes 0x00000000 <-- Old MS delay import - // record, contains VAs NameRva 0x004010e6 - // ModuleHandleRva 0x00000000 - // DelayImportAddressTableRva 0x00001140 <-- WRONG! This is an RVA - // DelayImportNameTableRva 0x004010c0 - // BoundDelayImportTableRva 0x00000000 - // ... - - if (virtual_address > image_base) - { - virtual_address = virtual_address - image_base; - } - } - - return virtual_address; -} - -int pe_is_termination_delay_import_entry( - PIMAGE_DELAYLOAD_DESCRIPTOR importDescriptor) -{ - return ( - importDescriptor->Attributes.AllAttributes == 0 && - importDescriptor->DllNameRVA == 0 && - importDescriptor->ModuleHandleRVA == 0 && - importDescriptor->ImportAddressTableRVA == 0 && - importDescriptor->ImportNameTableRVA == 0 && - importDescriptor->BoundImportAddressTableRVA == 0 && - importDescriptor->UnloadInformationTableRVA == 0 && - importDescriptor->TimeDateStamp == 0); -} - -char* pe_parse_delay_import_dll_name(PE* pe, uint64_t rva) -{ - const int64_t offset = pe_rva_to_offset(pe, rva); - - if (offset < 0) - return NULL; - - char* dll_name = (char*) (pe->data + offset); - - if (!pe_valid_dll_name(dll_name, pe->data_size - (size_t) offset)) - return NULL; - - return yr_strdup(dll_name); -} - -uint64_t pe_parse_delay_import_pointer( - PE* pe, - uint64_t pointerSize, - uint64_t rva) -{ - const int64_t offset = pe_rva_to_offset(pe, rva); - const uint8_t* data = pe->data + offset; - - if (!fits_in_pe(pe, data, pointerSize)) - return YR_UNDEFINED; - - if (IS_64BITS_PE(pe)) - return yr_le64toh(*(uint64_t*) data); - else - return yr_le32toh(*(uint32_t*) data); -} - -static void* pe_parse_delayed_imports(PE* pe) -{ - int64_t offset; - uint64_t num_imports = 0; // Number of imported DLLs - uint64_t num_function_imports = 0; // Total number of functions imported - uint64_t image_base = OptionalHeader(pe, ImageBase); - uint64_t size_of_image = OptionalHeader(pe, SizeOfImage); - uint64_t pointer_size = (IS_64BITS_PE(pe)) ? 8 : 4; - uint64_t ordinal_mask = (IS_64BITS_PE(pe)) ? IMAGE_ORDINAL_FLAG64 - : IMAGE_ORDINAL_FLAG32; - - IMPORTED_DLL* head_dll = NULL; - IMPORTED_DLL* tail_dll = NULL; - - IMPORT_FUNCTION* head_fun = NULL; - IMPORT_FUNCTION* tail_fun = NULL; - - PIMAGE_DELAYLOAD_DESCRIPTOR import_descriptor = NULL; - PIMAGE_DATA_DIRECTORY directory = NULL; - - // Default to 0 imports until we know there are any - set_integer(0, pe->object, "number_of_delayed_imports"); - set_integer(0, pe->object, "number_of_delayed_imported_functions"); - - directory = pe_get_directory_entry(pe, IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT); - - if (directory == NULL) - return NULL; - - if (yr_le32toh(directory->VirtualAddress) == 0) - return NULL; - - offset = pe_rva_to_offset(pe, yr_le32toh(directory->VirtualAddress)); - - if (offset < 0) - return NULL; - - import_descriptor = (PIMAGE_DELAYLOAD_DESCRIPTOR)(pe->data + offset); - - for (; struct_fits_in_pe(pe, import_descriptor, IMAGE_DELAYLOAD_DESCRIPTOR); - import_descriptor++) - { - // Check for the termination entry - if (pe_is_termination_delay_import_entry(import_descriptor)) - break; - - DWORD Attributes = yr_le32toh(import_descriptor->Attributes.AllAttributes); - DWORD DllNameRVA = yr_le32toh(import_descriptor->DllNameRVA); - DWORD ModuleHandleRVA = yr_le32toh(import_descriptor->ModuleHandleRVA); - DWORD ImportAddressTableRVA = yr_le32toh( - import_descriptor->ImportAddressTableRVA); - DWORD ImportNameTableRVA = yr_le32toh( - import_descriptor->ImportNameTableRVA); - DWORD BoundImportAddressTableRVA = yr_le32toh( - import_descriptor->BoundImportAddressTableRVA); - DWORD UnloadInformationTableRVA = yr_le32toh( - import_descriptor->UnloadInformationTableRVA); - - // Valid delayed import entry starts either with 0 or 0x01. - // We strict require one of the valid values here - if (Attributes > 0x1) - break; - - // Convert older (MS Visual C++ 6.0) delay-import descriptor to newer one. - // These delay-import descriptors are distinguishable by lowest bit in - // rec.Attributes to be zero. Sample: - // 2775d97f8bdb3311ace960a42eee35dbec84b9d71a6abbacb26c14e83f5897e4 - if (!IS_64BITS_PE(pe) && !Attributes) - { - DllNameRVA = pe_normalize_delay_import_value(image_base, DllNameRVA); - ModuleHandleRVA = pe_normalize_delay_import_value( - image_base, ModuleHandleRVA); - ImportAddressTableRVA = pe_normalize_delay_import_value( - image_base, ImportAddressTableRVA); - ImportNameTableRVA = pe_normalize_delay_import_value( - image_base, ImportNameTableRVA); - BoundImportAddressTableRVA = pe_normalize_delay_import_value( - image_base, BoundImportAddressTableRVA); - UnloadInformationTableRVA = pe_normalize_delay_import_value( - image_base, UnloadInformationTableRVA); - } - - // Stop on blatantly invalid delay import entries (old PELIB behavior) - if (ImportNameTableRVA >= size_of_image || - ImportAddressTableRVA >= size_of_image || - DllNameRVA < sizeof(IMAGE_DOS_HEADER) || - ImportNameTableRVA < sizeof(IMAGE_DOS_HEADER)) - break; - - char* dll_name = pe_parse_delay_import_dll_name(pe, DllNameRVA); - - if (dll_name == NULL) - continue; - - IMPORTED_DLL* imported_dll = (IMPORTED_DLL*) yr_calloc( - 1, sizeof(IMPORTED_DLL)); - - if (imported_dll == NULL) - { - yr_free(dll_name); - continue; - } - - imported_dll->name = dll_name; - imported_dll->next = NULL; - imported_dll->functions = NULL; - - head_fun = tail_fun = NULL; - - uint64_t name_rva = ImportNameTableRVA; - uint64_t func_rva = ImportAddressTableRVA; - - for (;;) - { - uint64_t nameAddress = pe_parse_delay_import_pointer( - pe, pointer_size, name_rva); - uint64_t funcAddress = pe_parse_delay_import_pointer( - pe, pointer_size, func_rva); - - // Value of YR_UNDEFINED means that value is outside of pe->data - if (nameAddress == YR_UNDEFINED || funcAddress == YR_UNDEFINED) - break; - - // Value of zero means that this is the end of the bound import name table - if (nameAddress == 0 || funcAddress == 0) - break; - - IMPORT_FUNCTION* imported_func = (IMPORT_FUNCTION*) yr_malloc( - sizeof(IMPORT_FUNCTION)); - - if (imported_func == NULL) - continue; - - imported_func->name = NULL; - imported_func->has_ordinal = 0; - imported_func->ordinal = 0; - imported_func->next = NULL; - - // Check name address. It could be ordinal, VA or RVA - if (!(nameAddress & ordinal_mask)) - { - // Convert name address to RVA, if needed - if (!Attributes) - nameAddress = pe_normalize_delay_import_value( - image_base, nameAddress); - - offset = pe_rva_to_offset(pe, nameAddress + sizeof(uint16_t)); - imported_func->name = (char*) yr_strndup( - (char*) (pe->data + offset), - yr_min(available_space(pe, (char*) (pe->data + offset)), 512)); - } - else - { - // If imported by ordinal. Lookup the ordinal. - imported_func->name = ord_lookup( - dll_name, yr_le64toh(nameAddress) & 0xFFFF); - // Also store the ordinal. - imported_func->ordinal = yr_le64toh(nameAddress) & 0xFFFF; - imported_func->has_ordinal = 1; - } - - num_function_imports++; - name_rva += pointer_size; - func_rva += pointer_size; - - if (head_fun == NULL) - head_fun = imported_func; - - if (tail_fun != NULL) - tail_fun->next = imported_func; - - tail_fun = imported_func; - } - - num_imports++; - - imported_dll->functions = head_fun; - - if (head_dll == NULL) - head_dll = imported_dll; - - if (tail_dll != NULL) - tail_dll->next = imported_dll; - - tail_dll = imported_dll; - } - - set_integer(num_imports, pe->object, "number_of_delayed_imports"); - set_integer( - num_function_imports, pe->object, "number_of_delayed_imported_functions"); - - pe_set_imports( - pe, - head_dll, - "delayed_import_details[%i].library_name", - "delayed_import_details[%i].number_of_functions", - "delayed_import_details[%i].functions[%i].name", - "delayed_import_details[%i].functions[%i].ordinal"); - - return head_dll; -} - // // Walk the exports and collect relevant information. It is used in the // "exports" function for comparison. // -static void pe_parse_exports(PE* pe) +static void pe_parse_exports( + PE* pe) { PIMAGE_DATA_DIRECTORY directory; PIMAGE_EXPORT_DIRECTORY exports; - int64_t offset; - int64_t export_start; - uint32_t i, j; uint32_t number_of_exports; uint32_t number_of_names; uint32_t ordinal_base; - - size_t export_size; + uint32_t export_start; + uint32_t export_size; + int64_t offset; size_t remaining; size_t name_len; @@ -1422,7 +1107,7 @@ static void pe_parse_exports(PE* pe) WORD* ordinals = NULL; DWORD* function_addrs = NULL; - // If not a PE file, return YR_UNDEFINED + // If not a PE file, return UNDEFINED if (pe == NULL) return; @@ -1430,7 +1115,8 @@ static void pe_parse_exports(PE* pe) // Default to 0 exports until we know there are any set_integer(0, pe->object, "number_of_exports"); - directory = pe_get_directory_entry(pe, IMAGE_DIRECTORY_ENTRY_EXPORT); + directory = pe_get_directory_entry( + pe, IMAGE_DIRECTORY_ENTRY_EXPORT); if (directory == NULL) return; @@ -1444,20 +1130,20 @@ static void pe_parse_exports(PE* pe) return; export_start = offset; - export_size = yr_le32toh(directory->Size); + export_size = directory->Size; - exports = (PIMAGE_EXPORT_DIRECTORY)(pe->data + offset); + exports = (PIMAGE_EXPORT_DIRECTORY) (pe->data + offset); if (!struct_fits_in_pe(pe, exports, IMAGE_EXPORT_DIRECTORY)) return; number_of_exports = yr_min( - yr_le32toh(exports->NumberOfFunctions), MAX_PE_EXPORTS); + yr_le32toh(exports->NumberOfFunctions), + MAX_PE_EXPORTS); - ordinal_base = yr_le32toh(exports->Base); + ordinal_base = exports->Base; - set_integer( - yr_le32toh(exports->TimeDateStamp), pe->object, "export_timestamp"); + set_integer(exports->TimeDateStamp, pe->object, "export_timestamp"); offset = pe_rva_to_offset(pe, yr_le32toh(exports->Name)); @@ -1479,11 +1165,10 @@ static void pe_parse_exports(PE* pe) if (offset < 0) return; - if (yr_le32toh(exports->NumberOfNames) * sizeof(DWORD) > - pe->data_size - offset) + if (yr_le32toh(exports->NumberOfNames) * sizeof(DWORD) > pe->data_size - offset) return; - names = (DWORD*) (pe->data + offset); + names = (DWORD*)(pe->data + offset); } offset = pe_rva_to_offset(pe, yr_le32toh(exports->AddressOfNameOrdinals)); @@ -1491,7 +1176,7 @@ static void pe_parse_exports(PE* pe) if (offset < 0) return; - ordinals = (WORD*) (pe->data + offset); + ordinals = (WORD*)(pe->data + offset); if (available_space(pe, ordinals) < sizeof(WORD) * number_of_exports) return; @@ -1501,13 +1186,13 @@ static void pe_parse_exports(PE* pe) if (offset < 0) return; - function_addrs = (DWORD*) (pe->data + offset); + function_addrs = (DWORD*)(pe->data + offset); if (available_space(pe, function_addrs) < sizeof(DWORD) * number_of_exports) return; number_of_names = yr_min( - yr_le32toh(yr_le32toh(exports->NumberOfNames)), number_of_exports); + yr_le32toh(exports->NumberOfNames), number_of_exports); // Mapping out the exports is a bit janky. We start with the export address // array. The index from that array plus the ordinal base is the ordinal for @@ -1543,13 +1228,13 @@ static void pe_parse_exports(PE* pe) for (i = 0; i < number_of_exports; i++) { + offset = pe_rva_to_offset(pe, function_addrs[i]); + if (offset <= 0) + continue; + set_integer( ordinal_base + i, pe->object, "export_details[%i].ordinal", exp_sz); - // Don't check for a failure here since some packers make this an invalid - // value. - offset = pe_rva_to_offset(pe, yr_le32toh(function_addrs[i])); - if (offset > export_start && offset < export_start + export_size) { remaining = pe->data_size - (size_t) offset; @@ -1559,8 +1244,7 @@ static void pe_parse_exports(PE* pe) (char*) (pe->data + offset), yr_min(name_len, MAX_EXPORT_NAME_LENGTH), pe->object, - "export_details[%i].forward_name", - exp_sz); + "export_details[%i].forward_name", exp_sz); } else { @@ -1571,10 +1255,9 @@ static void pe_parse_exports(PE* pe) { for (j = 0; j < number_of_exports; j++) { - if (yr_le16toh(ordinals[j]) == i && j < number_of_names) + if (ordinals[j] == i && j < number_of_names) { - offset = pe_rva_to_offset(pe, yr_le32toh(names[j])); - + offset = pe_rva_to_offset(pe, names[j]); if (offset > 0) { remaining = pe->data_size - (size_t) offset; @@ -1584,8 +1267,7 @@ static void pe_parse_exports(PE* pe) (char*) (pe->data + offset), yr_min(name_len, MAX_EXPORT_NAME_LENGTH), pe->object, - "export_details[%i].name", - exp_sz); + "export_details[%i].name", exp_sz); } break; } @@ -1595,6 +1277,7 @@ static void pe_parse_exports(PE* pe) } set_integer(exp_sz, pe->object, "number_of_exports"); + return; } // BoringSSL (https://boringssl.googlesource.com/boringssl/) doesn't support @@ -1607,11 +1290,14 @@ static void pe_parse_exports(PE* pe) // Parse a PKCS7 blob, looking for certs and nested PKCS7 blobs. // -void _parse_pkcs7(PE* pe, PKCS7* pkcs7, int* counter) +void _parse_pkcs7( + PE* pe, + PKCS7* pkcs7, + int* counter) { int i, j; time_t date_time; - int sig_nid; + const char* sig_alg; char buffer[256]; int bytes; int idx; @@ -1627,7 +1313,7 @@ void _parse_pkcs7(PE* pe, PKCS7* pkcs7, int* counter) ASN1_STRING* value = NULL; X509* cert = NULL; STACK_OF(X509)* certs = NULL; - X509_ATTRIBUTE* xa = NULL; + X509_ATTRIBUTE *xa = NULL; STACK_OF(X509_ATTRIBUTE)* attrs = NULL; if (*counter >= MAX_PE_CERTS) @@ -1653,25 +1339,24 @@ void _parse_pkcs7(PE* pe, PKCS7* pkcs7, int* counter) "signatures[%i].thumbprint", *counter); - X509_NAME_oneline(X509_get_issuer_name(cert), buffer, sizeof(buffer)); + X509_NAME_oneline( + X509_get_issuer_name(cert), buffer, sizeof(buffer)); set_string(buffer, pe->object, "signatures[%i].issuer", *counter); - X509_NAME_oneline(X509_get_subject_name(cert), buffer, sizeof(buffer)); + X509_NAME_oneline( + X509_get_subject_name(cert), buffer, sizeof(buffer)); set_string(buffer, pe->object, "signatures[%i].subject", *counter); set_integer( - X509_get_version(cert) + 1, // Versions are zero based, so add one. + X509_get_version(cert) + 1, // Versions are zero based, so add one. pe->object, - "signatures[%i].version", - *counter); + "signatures[%i].version", *counter); - sig_nid = X509_get_signature_nid(cert); - set_string( - OBJ_nid2ln(sig_nid), pe->object, "signatures[%i].algorithm", *counter); - OBJ_obj2txt(buffer, sizeof(buffer), OBJ_nid2obj(sig_nid), 1); - set_string(buffer, pe->object, "signatures[%i].algorithm_oid", *counter); + sig_alg = OBJ_nid2ln(X509_get_signature_nid(cert)); + + set_string(sig_alg, pe->object, "signatures[%i].algorithm", *counter); serial = X509_get_serialNumber(cert); @@ -1708,7 +1393,7 @@ void _parse_pkcs7(PE* pe, PKCS7* pkcs7, int* counter) if (serial_der != NULL) { unsigned char* serial_bytes; - char* serial_ascii; + char *serial_ascii; bytes = i2d_ASN1_INTEGER(serial, &serial_der); @@ -1737,13 +1422,18 @@ void _parse_pkcs7(PE* pe, PKCS7* pkcs7, int* counter) { // Don't put the colon on the last one. if (j < bytes - 1) - snprintf(serial_ascii + 3 * j, 4, "%02x:", serial_bytes[j]); + snprintf( + serial_ascii + 3 * j, 4, "%02x:", serial_bytes[j]); else - snprintf(serial_ascii + 3 * j, 3, "%02x", serial_bytes[j]); + snprintf( + serial_ascii + 3 * j, 3, "%02x", serial_bytes[j]); } set_string( - serial_ascii, pe->object, "signatures[%i].serial", *counter); + serial_ascii, + pe->object, + "signatures[%i].serial", + *counter); yr_free(serial_ascii); } @@ -1753,10 +1443,10 @@ void _parse_pkcs7(PE* pe, PKCS7* pkcs7, int* counter) } } - date_time = ASN1_get_time_t(X509_get0_notBefore(cert)); + date_time = ASN1_get_time_t(X509_get_notBefore(cert)); set_integer(date_time, pe->object, "signatures[%i].not_before", *counter); - date_time = ASN1_get_time_t(X509_get0_notAfter(cert)); + date_time = ASN1_get_time_t(X509_get_notAfter(cert)); set_integer(date_time, pe->object, "signatures[%i].not_after", *counter); (*counter)++; @@ -1765,16 +1455,12 @@ void _parse_pkcs7(PE* pe, PKCS7* pkcs7, int* counter) // See if there is a nested signature, which is apparently an authenticode // specific feature. See https://github.com/VirusTotal/yara/issues/515. signer_info = sk_PKCS7_SIGNER_INFO_value(pkcs7->d.sign->signer_info, 0); - if (signer_info != NULL) { attrs = PKCS7_get_attributes(signer_info); - idx = X509at_get_attr_by_NID( attrs, OBJ_txt2nid(SPC_NESTED_SIGNATURE_OBJID), -1); - xa = X509at_get_attr(attrs, idx); - for (j = 0; j < MAX_PE_CERTS; j++) { nested = X509_ATTRIBUTE_get0_type(xa, j); @@ -1794,7 +1480,9 @@ void _parse_pkcs7(PE* pe, PKCS7* pkcs7, int* counter) sk_X509_free(certs); } -static void pe_parse_certificates(PE* pe) + +static void pe_parse_certificates( + PE* pe) { int counter = 0; @@ -1817,18 +1505,18 @@ static void pe_parse_certificates(PE* pe) if (yr_le32toh(directory->VirtualAddress) == 0 || yr_le32toh(directory->VirtualAddress) > pe->data_size || yr_le32toh(directory->Size) > pe->data_size || - yr_le32toh(directory->VirtualAddress) + yr_le32toh(directory->Size) > - pe->data_size) + yr_le32toh(directory->VirtualAddress) + yr_le32toh(directory->Size) > pe->data_size) { return; } // Store the end of directory, making comparisons easier. - eod = pe->data + yr_le32toh(directory->VirtualAddress) + - yr_le32toh(directory->Size); + eod = pe->data + \ + yr_le32toh(directory->VirtualAddress) + \ + yr_le32toh(directory->Size); - win_cert = (PWIN_CERTIFICATE)( - pe->data + yr_le32toh(directory->VirtualAddress)); + win_cert = (PWIN_CERTIFICATE) \ + (pe->data + yr_le32toh(directory->VirtualAddress)); // // Walk the directory, pulling out certificates. @@ -1866,28 +1554,22 @@ static void pe_parse_certificates(PE* pe) { end = (uintptr_t)((uint8_t*) win_cert) + yr_le32toh(win_cert->Length); - // Next certificate is aligned to the next 8-bytes boundary. - win_cert = (PWIN_CERTIFICATE)((end + 7) & -8); + win_cert = (PWIN_CERTIFICATE) (end + (end % 8)); continue; } cert_p = win_cert->Certificate; end = (uintptr_t)((uint8_t*) win_cert) + yr_le32toh(win_cert->Length); - while ((uintptr_t) cert_p < end && counter < MAX_PE_CERTS) { - pkcs7 = d2i_PKCS7(NULL, &cert_p, (uint32_t)(end - (uintptr_t) cert_p)); - + pkcs7 = d2i_PKCS7(NULL, &cert_p, (win_cert->Length)); if (pkcs7 == NULL) break; - _parse_pkcs7(pe, pkcs7, &counter); PKCS7_free(pkcs7); - pkcs7 = NULL; } - // Next certificate is aligned to the next 8-bytes boundary. - win_cert = (PWIN_CERTIFICATE)((end + 7) & -8); + win_cert = (PWIN_CERTIFICATE) (end + (end % 8)); } set_integer(counter, pe->object, "number_of_signatures"); @@ -1895,393 +1577,271 @@ static void pe_parse_certificates(PE* pe) #endif // defined(HAVE_LIBCRYPTO) -const char* pe_get_section_full_name( - PE* pe, - const char* section_name, - uint64_t section_name_length, - uint64_t* section_full_name_length) -{ - // section_name is an 8-byte, null-padded UTF-8 encoded string. If the string - // is exactly 8 characters long, there is no terminating null. For longer - // names, this field contains a slash (/) that is followed by an ASCII - // representation of a decimal number that is an offset into the string table. - - // Sample: 2e9c671b8a0411f2b397544b368c44d7f095eb395779de0ad1ac946914dfa34c - - // Check if any param is NULL - if (pe == NULL || section_name == NULL || section_full_name_length == NULL) - return NULL; - - // Set length to zero - *section_full_name_length = 0; - - // Offset and number of records in coff table - uint64_t coff_offset = yr_le32toh( - pe->header->FileHeader.PointerToSymbolTable); - uint64_t coff_number = yr_le32toh(pe->header->FileHeader.NumberOfSymbols); - - // If section name start with '/' and file contain coff table then section - // name is stored in string table - if (coff_offset == 0 || section_name[0] != '/') - { - *section_full_name_length = section_name_length; - return section_name; - } - - // Calculate offset of string table (String table is immediately after coff - // table) - uint64_t string_offset = coff_offset + coff_number * sizeof(IMAGE_SYMBOL); - uint64_t string_index = 0; - - // Calculate string index/offset in string table - for (int i = 1; i < IMAGE_SIZEOF_SHORT_NAME && isdigit(section_name[i]); i++) - string_index = (string_index * 10) + (section_name[i] - '0'); - - // Calculate string pointer - const char* string = (char*) (pe->data + string_offset + string_index); - - // Check string - for (uint64_t len = 0; fits_in_pe(pe, string, len + 1); len++) - { - // Valid string - if (string[len] == 0) - { - *section_full_name_length = len; - return string; - } - - // string contain unprintable character - if (!isprint(string[len])) - return NULL; - } - // String do not fit into pe file - return NULL; -} - -static void pe_parse_header(PE* pe, uint64_t base_address, int flags) +static void pe_parse_header( + PE* pe, + uint64_t base_address, + int flags) { PIMAGE_SECTION_HEADER section; PIMAGE_DATA_DIRECTORY data_dir; char section_name[IMAGE_SIZEOF_SHORT_NAME + 1]; - int sect_name_length, scount, ddcount; + int i, scount, ddcount; uint64_t highest_sec_siz = 0; uint64_t highest_sec_ofs = 0; uint64_t section_end; uint64_t last_section_end; + set_integer(1, pe->object, "is_pe"); set_integer( - yr_le16toh(pe->header->FileHeader.Machine), pe->object, "machine"); + yr_le16toh(pe->header->FileHeader.Machine), + pe->object, "machine"); set_integer( yr_le16toh(pe->header->FileHeader.NumberOfSections), - pe->object, - "number_of_sections"); + pe->object, "number_of_sections"); set_integer( yr_le32toh(pe->header->FileHeader.TimeDateStamp), - pe->object, - "timestamp"); + pe->object, "timestamp"); set_integer( yr_le32toh(pe->header->FileHeader.PointerToSymbolTable), - pe->object, - "pointer_to_symbol_table"); + pe->object, "pointer_to_symbol_table"); set_integer( yr_le32toh(pe->header->FileHeader.NumberOfSymbols), - pe->object, - "number_of_symbols"); + pe->object, "number_of_symbols"); set_integer( yr_le32toh(pe->header->FileHeader.SizeOfOptionalHeader), - pe->object, - "size_of_optional_header"); + pe->object, "size_of_optional_header"); set_integer( yr_le16toh(pe->header->FileHeader.Characteristics), - pe->object, - "characteristics"); - - set_integer( - flags & SCAN_FLAGS_PROCESS_MEMORY - ? base_address + yr_le32toh(OptionalHeader(pe, AddressOfEntryPoint)) - : pe_rva_to_offset( - pe, yr_le32toh(OptionalHeader(pe, AddressOfEntryPoint))), - pe->object, - "entry_point"); + pe->object, "characteristics"); set_integer( - yr_le32toh(OptionalHeader(pe, AddressOfEntryPoint)), - pe->object, - "entry_point_raw"); + flags & SCAN_FLAGS_PROCESS_MEMORY ? + base_address + yr_le32toh(OptionalHeader(pe, AddressOfEntryPoint)) : + pe_rva_to_offset(pe, yr_le32toh(OptionalHeader(pe, AddressOfEntryPoint))), + pe->object, "entry_point"); set_integer( - IS_64BITS_PE(pe) ? yr_le64toh(OptionalHeader(pe, ImageBase)) - : yr_le32toh(OptionalHeader(pe, ImageBase)), - pe->object, - "image_base"); + IS_64BITS_PE(pe) ? + yr_le64toh(OptionalHeader(pe, ImageBase)) : + yr_le32toh(OptionalHeader(pe, ImageBase)), + pe->object, "image_base"); set_integer( yr_le32toh(OptionalHeader(pe, NumberOfRvaAndSizes)), - pe->object, - "number_of_rva_and_sizes"); + pe->object, "number_of_rva_and_sizes"); set_integer( - yr_le32toh(OptionalHeader(pe, Magic)), pe->object, "opthdr_magic"); + yr_le32toh(OptionalHeader(pe, Magic)), + pe->object, "opthdr_magic"); set_integer( OptionalHeader(pe, MajorLinkerVersion), - pe->object, - "linker_version.major"); + pe->object, "linker_version.major"); set_integer( OptionalHeader(pe, MinorLinkerVersion), - pe->object, - "linker_version.minor"); + pe->object, "linker_version.minor"); set_integer( - yr_le32toh(OptionalHeader(pe, SizeOfCode)), pe->object, "size_of_code"); + yr_le32toh(OptionalHeader(pe, SizeOfCode)), + pe->object, "size_of_code"); set_integer( yr_le32toh(OptionalHeader(pe, SizeOfInitializedData)), - pe->object, - "size_of_initialized_data"); + pe->object, "size_of_initialized_data"); set_integer( yr_le32toh(OptionalHeader(pe, SizeOfUninitializedData)), - pe->object, - "size_of_uninitialized_data"); + pe->object, "size_of_uninitialized_data"); set_integer( - yr_le32toh(OptionalHeader(pe, BaseOfCode)), pe->object, "base_of_code"); + yr_le32toh(OptionalHeader(pe, BaseOfCode)), + pe->object, "base_of_code"); if (!IS_64BITS_PE(pe)) { - set_integer( + set_integer( yr_le32toh(pe->header->OptionalHeader.BaseOfData), - pe->object, - "base_of_data"); + pe->object, "base_of_data"); } set_integer( yr_le32toh(OptionalHeader(pe, SectionAlignment)), - pe->object, - "section_alignment"); + pe->object, "section_alignment"); set_integer( yr_le32toh(OptionalHeader(pe, FileAlignment)), - pe->object, - "file_alignment"); + pe->object, "file_alignment"); set_integer( yr_le16toh(OptionalHeader(pe, MajorOperatingSystemVersion)), - pe->object, - "os_version.major"); + pe->object, "os_version.major"); set_integer( yr_le16toh(OptionalHeader(pe, MinorOperatingSystemVersion)), - pe->object, - "os_version.minor"); + pe->object, "os_version.minor"); set_integer( yr_le16toh(OptionalHeader(pe, MajorImageVersion)), - pe->object, - "image_version.major"); + pe->object, "image_version.major"); set_integer( yr_le16toh(OptionalHeader(pe, MinorImageVersion)), - pe->object, - "image_version.minor"); + pe->object, "image_version.minor"); set_integer( yr_le16toh(OptionalHeader(pe, MajorSubsystemVersion)), - pe->object, - "subsystem_version.major"); + pe->object, "subsystem_version.major"); set_integer( yr_le16toh(OptionalHeader(pe, MinorSubsystemVersion)), - pe->object, - "subsystem_version.minor"); + pe->object, "subsystem_version.minor"); set_integer( yr_le32toh(OptionalHeader(pe, Win32VersionValue)), - pe->object, - "win32_version_value"); + pe->object, "win32_version_value"); set_integer( - yr_le32toh(OptionalHeader(pe, SizeOfImage)), pe->object, "size_of_image"); + yr_le32toh(OptionalHeader(pe, SizeOfImage)), + pe->object, "size_of_image"); set_integer( yr_le32toh(OptionalHeader(pe, SizeOfHeaders)), - pe->object, - "size_of_headers"); + pe->object, "size_of_headers"); - set_integer(yr_le32toh(OptionalHeader(pe, CheckSum)), pe->object, "checksum"); + set_integer( + yr_le32toh(OptionalHeader(pe, CheckSum)), + pe->object, "checksum"); set_integer( - yr_le16toh(OptionalHeader(pe, Subsystem)), pe->object, "subsystem"); + yr_le16toh(OptionalHeader(pe, Subsystem)), + pe->object, "subsystem"); set_integer( OptionalHeader(pe, DllCharacteristics), - pe->object, - "dll_characteristics"); + pe->object, "dll_characteristics"); set_integer( - IS_64BITS_PE(pe) ? yr_le64toh(OptionalHeader(pe, SizeOfStackReserve)) - : yr_le32toh(OptionalHeader(pe, SizeOfStackReserve)), - pe->object, - "size_of_stack_reserve"); + IS_64BITS_PE(pe) ? + yr_le64toh(OptionalHeader(pe, SizeOfStackReserve)) : + yr_le32toh(OptionalHeader(pe, SizeOfStackReserve)), + pe->object, "size_of_stack_reserve"); set_integer( - IS_64BITS_PE(pe) ? yr_le64toh(OptionalHeader(pe, SizeOfStackCommit)) - : yr_le32toh(OptionalHeader(pe, SizeOfStackCommit)), - pe->object, - "size_of_stack_commit"); + IS_64BITS_PE(pe) ? + yr_le64toh(OptionalHeader(pe, SizeOfStackCommit)) : + yr_le32toh(OptionalHeader(pe, SizeOfStackCommit)), + pe->object, "size_of_stack_commit"); set_integer( - IS_64BITS_PE(pe) ? yr_le64toh(OptionalHeader(pe, SizeOfHeapReserve)) - : yr_le32toh(OptionalHeader(pe, SizeOfHeapReserve)), - pe->object, - "size_of_heap_reserve"); + IS_64BITS_PE(pe) ? + yr_le64toh(OptionalHeader(pe, SizeOfHeapReserve)) : + yr_le32toh(OptionalHeader(pe, SizeOfHeapReserve)), + pe->object, "size_of_heap_reserve"); set_integer( - IS_64BITS_PE(pe) ? yr_le64toh(OptionalHeader(pe, SizeOfHeapCommit)) - : yr_le32toh(OptionalHeader(pe, SizeOfHeapCommit)), - pe->object, - "size_of_heap_commit"); + IS_64BITS_PE(pe) ? + yr_le64toh(OptionalHeader(pe, SizeOfHeapCommit)) : + yr_le32toh(OptionalHeader(pe, SizeOfHeapCommit)), + pe->object, "size_of_heap_commit"); set_integer( - yr_le32toh(OptionalHeader(pe, LoaderFlags)), pe->object, "loader_flags"); + yr_le32toh(OptionalHeader(pe, LoaderFlags)), + pe->object, "loader_flags"); - data_dir = IS_64BITS_PE(pe) ? pe->header64->OptionalHeader.DataDirectory - : pe->header->OptionalHeader.DataDirectory; + data_dir = IS_64BITS_PE(pe) ? + pe->header64->OptionalHeader.DataDirectory: + pe->header->OptionalHeader.DataDirectory; ddcount = yr_le16toh(OptionalHeader(pe, NumberOfRvaAndSizes)); ddcount = yr_min(ddcount, IMAGE_NUMBEROF_DIRECTORY_ENTRIES); - for (int i = 0; i < ddcount; i++) + for (i = 0; i < ddcount; i++) { if (!struct_fits_in_pe(pe, data_dir, IMAGE_DATA_DIRECTORY)) break; set_integer( - yr_le32toh(data_dir->VirtualAddress), - pe->object, - "data_directories[%i].virtual_address", - i); + yr_le32toh(data_dir->VirtualAddress), + pe->object, "data_directories[%i].virtual_address", i); set_integer( - yr_le32toh(data_dir->Size), pe->object, "data_directories[%i].size", i); + yr_le32toh(data_dir->Size), + pe->object, "data_directories[%i].size", i); data_dir++; } pe_iterate_resources( - pe, (RESOURCE_CALLBACK_FUNC) pe_collect_resources, (void*) pe); + pe, + (RESOURCE_CALLBACK_FUNC) pe_collect_resources, + (void*) pe); set_integer(pe->resources, pe->object, "number_of_resources"); - set_integer(pe->version_infos, pe->object, "number_of_version_infos"); section = IMAGE_FIRST_SECTION(pe->header); scount = yr_min( yr_le16toh(pe->header->FileHeader.NumberOfSections), MAX_PE_SECTIONS); - for (int i = 0; i < scount; i++) + for (i = 0; i < scount; i++) { if (!struct_fits_in_pe(pe, section, IMAGE_SECTION_HEADER)) break; - memcpy(section_name, section->Name, IMAGE_SIZEOF_SHORT_NAME); + strncpy(section_name, (char*) section->Name, IMAGE_SIZEOF_SHORT_NAME); section_name[IMAGE_SIZEOF_SHORT_NAME] = '\0'; - // Basically do rstrip('\0'), find the rightmost non-null character. - // Samples like - // 0043812838495a45449a0ac61a81b9c16eddca1ad249fb4f7fdb1c4505e9bb34 contain - // sections with additional characters after the first null. - for (sect_name_length = IMAGE_SIZEOF_SHORT_NAME - 1; sect_name_length >= 0; - --sect_name_length) - { - if (section_name[sect_name_length] != '\0') - break; - } - - uint64_t sect_full_name_length = 0; - const char* full_section_name = pe_get_section_full_name( - pe, section_name, sect_name_length + 1, §_full_name_length); - - set_sized_string( - (char*) section_name, - sect_name_length + 1, - pe->object, - "sections[%i].name", - i); - - set_sized_string( - full_section_name, - sect_full_name_length, - pe->object, - "sections[%i].full_name", - i); + set_string( + section_name, + pe->object, "sections[%i].name", i); set_integer( yr_le32toh(section->Characteristics), - pe->object, - "sections[%i].characteristics", - i); + pe->object, "sections[%i].characteristics", i); set_integer( yr_le32toh(section->SizeOfRawData), - pe->object, - "sections[%i].raw_data_size", - i); + pe->object, "sections[%i].raw_data_size", i); set_integer( yr_le32toh(section->PointerToRawData), - pe->object, - "sections[%i].raw_data_offset", - i); + pe->object, "sections[%i].raw_data_offset", i); set_integer( yr_le32toh(section->VirtualAddress), - pe->object, - "sections[%i].virtual_address", - i); + pe->object, "sections[%i].virtual_address", i); set_integer( yr_le32toh(section->Misc.VirtualSize), - pe->object, - "sections[%i].virtual_size", - i); + pe->object, "sections[%i].virtual_size", i); set_integer( yr_le32toh(section->PointerToRelocations), - pe->object, - "sections[%i].pointer_to_relocations", - i); + pe->object, "sections[%i].pointer_to_relocations", i); set_integer( yr_le32toh(section->PointerToLinenumbers), - pe->object, - "sections[%i].pointer_to_line_numbers", - i); + pe->object, "sections[%i].pointer_to_line_numbers", i); set_integer( yr_le32toh(section->NumberOfRelocations), - pe->object, - "sections[%i].number_of_relocations", - i); + pe->object, "sections[%i].number_of_relocations", i); set_integer( yr_le32toh(section->NumberOfLinenumbers), - pe->object, - "sections[%i].number_of_line_numbers", - i); + pe->object, "sections[%i].number_of_line_numbers", i); // This will catch the section with the highest raw offset to help checking // if overlay data is present. If two sections have the same raw pointer @@ -2304,20 +1864,14 @@ static void pe_parse_header(PE* pe, uint64_t base_address, int flags) // RawData + RawOffset of the last section on the physical file last_section_end = highest_sec_siz + highest_sec_ofs; - // For PE files that have overlaid data overlay.offset contains the offset - // within the file where the overlay starts and overlay.size contains the - // size. If the PE file doesn't have an overlay both fields are 0, if the - // file is not a PE file (or is a malformed PE) both fields are YR_UNDEFINED. + // "overlay.offset" is set to UNDEFINED for files that do not have an overlay if (last_section_end && (pe->data_size > last_section_end)) - { set_integer(last_section_end, pe->object, "overlay.offset"); + + // "overlay.size" is zero for well formed PE files that do not have an + // overlay and UNDEFINED for malformed PE files or non-PE files. + if (last_section_end && (pe->data_size >= last_section_end)) set_integer(pe->data_size - last_section_end, pe->object, "overlay.size"); - } - else - { - set_integer(0, pe->object, "overlay.offset"); - set_integer(0, pe->object, "overlay.size"); - } } // @@ -2333,7 +1887,7 @@ define_function(valid_on) if (is_undefined(parent(), "not_before") || is_undefined(parent(), "not_after")) { - return_integer(YR_UNDEFINED); + return_integer(UNDEFINED); } timestamp = integer_argument(1); @@ -2341,14 +1895,16 @@ define_function(valid_on) not_before = get_integer(parent(), "not_before"); not_after = get_integer(parent(), "not_after"); - return_integer(timestamp >= not_before && timestamp <= not_after); + return_integer(timestamp >= not_before && timestamp <= not_after); } + define_function(section_index_addr) { YR_OBJECT* module = module(); YR_SCAN_CONTEXT* context = scan_context(); + int i; int64_t offset; int64_t size; @@ -2356,9 +1912,9 @@ define_function(section_index_addr) int64_t n = get_integer(module, "number_of_sections"); if (is_undefined(module, "number_of_sections")) - return_integer(YR_UNDEFINED); + return_integer(UNDEFINED); - for (int i = 0; i < yr_min(n, MAX_PE_SECTIONS); i++) + for (i = 0; i < yr_min(n, MAX_PE_SECTIONS); i++) { if (context->flags & SCAN_FLAGS_PROCESS_MEMORY) { @@ -2375,9 +1931,10 @@ define_function(section_index_addr) return_integer(i); } - return_integer(YR_UNDEFINED); + return_integer(UNDEFINED); } + define_function(section_index_name) { YR_OBJECT* module = module(); @@ -2385,11 +1942,12 @@ define_function(section_index_name) char* name = string_argument(1); int64_t n = get_integer(module, "number_of_sections"); + int i; if (is_undefined(module, "number_of_sections")) - return_integer(YR_UNDEFINED); + return_integer(UNDEFINED); - for (int i = 0; i < yr_min(n, MAX_PE_SECTIONS); i++) + for (i = 0; i < yr_min(n, MAX_PE_SECTIONS); i++) { SIZED_STRING* sect = get_string(module, "sections[%i].name", i); @@ -2397,9 +1955,10 @@ define_function(section_index_name) return_integer(i); } - return_integer(YR_UNDEFINED); + return_integer(UNDEFINED); } + define_function(exports) { SIZED_STRING* search_name = sized_string_argument(1); @@ -2408,30 +1967,33 @@ define_function(exports) YR_OBJECT* module = module(); PE* pe = (PE*) module->data; - // If not a PE, return YR_UNDEFINED. + int i, n; + + // If not a PE, return UNDEFINED. if (pe == NULL) - return_integer(YR_UNDEFINED); + return_integer(UNDEFINED); // If PE, but no exported functions, return false. - int n = (int) get_integer(module, "number_of_exports"); - + n = get_integer(module, "number_of_exports"); if (n == 0) return_integer(0); - for (int i = 0; i < n; i++) + for (i = 0; i < n; i++) { function_name = get_string(module, "export_details[%i].name", i); - if (function_name == NULL) continue; - if (ss_icompare(function_name, search_name) == 0) + if (sized_string_cmp_nocase(function_name, search_name) == 0) + { return_integer(1); + } } return_integer(0); } + define_function(exports_regexp) { RE* regex = regexp_argument(1); @@ -2440,54 +2002,57 @@ define_function(exports_regexp) YR_OBJECT* module = module(); PE* pe = (PE*) module->data; - // If not a PE, return YR_UNDEFINED. + int i, n; + + // If not a PE, return UNDEFINED. if (pe == NULL) - return_integer(YR_UNDEFINED); + return_integer(UNDEFINED); // If PE, but no exported functions, return false. - int n = (int) get_integer(module, "number_of_exports"); - + n = get_integer(module, "number_of_exports"); if (n == 0) return_integer(0); - for (int i = 0; i < n; i++) + for (i = 0; i < n; i++) { function_name = get_string(module, "export_details[%i].name", i); if (function_name == NULL) continue; if (yr_re_match(scan_context(), regex, function_name->c_string) != -1) + { return_integer(1); + } } return_integer(0); } + define_function(exports_ordinal) { - int64_t ordinal = integer_argument(1); + uint64_t ordinal = integer_argument(1); YR_OBJECT* module = module(); PE* pe = (PE*) module->data; + int i, n, exported_ordinal; - // If not a PE, return YR_UNDEFINED. + // If not a PE, return UNDEFINED. if (pe == NULL) - return_integer(YR_UNDEFINED); + return_integer(UNDEFINED); // If PE, but no exported functions, return false. - int n = (int) get_integer(module, "number_of_exports"); - + n = get_integer(module, "number_of_exports"); if (n == 0) return_integer(0); if (ordinal == 0 || ordinal > n) return_integer(0); - for (int i = 0; i < n; i++) + for (i = 0; i < n; i++) { - int64_t exported_ordinal = yr_object_get_integer( + exported_ordinal = yr_object_get_integer( module, "export_details[%i].ordinal", i); - if (exported_ordinal == ordinal) return_integer(1); } @@ -2495,6 +2060,7 @@ define_function(exports_ordinal) return_integer(0); } + define_function(exports_index_name) { SIZED_STRING* search_name = sized_string_argument(1); @@ -2503,62 +2069,65 @@ define_function(exports_index_name) YR_OBJECT* module = module(); PE* pe = (PE*) module->data; - // If not a PE, return YR_UNDEFINED. + int i, n; + + // If not a PE, return UNDEFINED. if (pe == NULL) - return_integer(YR_UNDEFINED); + return_integer(UNDEFINED); // If PE, but no exported functions, return false. - int n = (int) get_integer(module, "number_of_exports"); - + n = get_integer(module, "number_of_exports"); if (n == 0) - return_integer(YR_UNDEFINED); + return_integer(UNDEFINED); - for (int i = 0; i < n; i++) + for (i = 0; i < n; i++) { function_name = get_string(module, "export_details[%i].name", i); - if (function_name == NULL) continue; - if (ss_icompare(function_name, search_name) == 0) + if (sized_string_cmp_nocase(function_name, search_name) == 0) + { return_integer(i); + } } - return_integer(YR_UNDEFINED); + return_integer(UNDEFINED); } + define_function(exports_index_ordinal) { - int64_t ordinal = integer_argument(1); + uint64_t ordinal = integer_argument(1); YR_OBJECT* module = module(); PE* pe = (PE*) module->data; + int i, n, exported_ordinal; - // If not a PE, return YR_UNDEFINED. + // If not a PE, return UNDEFINED. if (pe == NULL) - return_integer(YR_UNDEFINED); + return_integer(UNDEFINED); // If PE, but no exported functions, return false. - int n = (int) get_integer(module, "number_of_exports"); - + n = get_integer(module, "number_of_exports"); if (n == 0) - return_integer(YR_UNDEFINED); + return_integer(UNDEFINED); if (ordinal == 0 || ordinal > n) - return_integer(YR_UNDEFINED); + return_integer(UNDEFINED); - for (int i = 0; i < n; i++) + for (i = 0; i < n; i++) { - int64_t exported_ordinal = yr_object_get_integer( + exported_ordinal = yr_object_get_integer( module, "export_details[%i].ordinal", i); - if (exported_ordinal == ordinal) return_integer(i); } - return_integer(YR_UNDEFINED); + return_integer(UNDEFINED); } + define_function(exports_index_regex) { RE* regex = regexp_argument(1); @@ -2567,17 +2136,18 @@ define_function(exports_index_regex) YR_OBJECT* module = module(); PE* pe = (PE*) module->data; - // If not a PE, return YR_UNDEFINED. + int i, n; + + // If not a PE, return UNDEFINED. if (pe == NULL) - return_integer(YR_UNDEFINED); + return_integer(UNDEFINED); // If PE, but no exported functions, return false. - int n = (int) get_integer(module, "number_of_exports"); - + n = get_integer(module, "number_of_exports"); if (n == 0) - return_integer(YR_UNDEFINED); + return_integer(UNDEFINED); - for (int i = 0; i < n; i++) + for (i = 0; i < n; i++) { function_name = get_string(module, "export_details[%i].name", i); if (function_name == NULL) @@ -2589,10 +2159,12 @@ define_function(exports_index_regex) } } - return_integer(YR_UNDEFINED); + return_integer(UNDEFINED); } -#if defined(HAVE_LIBCRYPTO) || defined(HAVE_WINCRYPT_H) || \ + +#if defined(HAVE_LIBCRYPTO) || \ + defined(HAVE_WINCRYPT_H) || \ defined(HAVE_COMMONCRYPTO_COMMONCRYPTO_H) // @@ -2617,13 +2189,16 @@ define_function(imphash) PE* pe = (PE*) module->data; - // If not a PE, return YR_UNDEFINED. + // If not a PE, return UNDEFINED. if (!pe) - return_string(YR_UNDEFINED); + return_string(UNDEFINED); // Lookup in cache first. - digest_ascii = (char*) yr_hash_table_lookup(pe->hash_table, "imphash", NULL); + digest_ascii = (char*) yr_hash_table_lookup( + pe->hash_table, + "imphash", + NULL); if (digest_ascii != NULL) return_string(digest_ascii); @@ -2643,9 +2218,9 @@ define_function(imphash) char* ext = strstr(dll->name, "."); - if (ext && - (strncasecmp(ext, ".ocx", 4) == 0 || strncasecmp(ext, ".sys", 4) == 0 || - strncasecmp(ext, ".dll", 4) == 0)) + if (ext && (strncasecmp(ext, ".ocx", 4) == 0 || + strncasecmp(ext, ".sys", 4) == 0 || + strncasecmp(ext, ".dll", 4) == 0)) { dll_name_len = (ext - dll->name); } @@ -2656,7 +2231,7 @@ define_function(imphash) // Allocate a new string to hold the dll name. - dll_name = (char*) yr_malloc(dll_name_len + 1); + dll_name = (char *) yr_malloc(dll_name_len + 1); if (!dll_name) return ERROR_INSUFFICIENT_MEMORY; @@ -2671,14 +2246,14 @@ define_function(imphash) size_t final_name_len = dll_name_len + strlen(func->name) + 1; if (!first) - final_name_len++; // Additional byte to accommodate the extra comma + final_name_len++; // Additional byte to accommodate the extra comma final_name = (char*) yr_malloc(final_name_len + 1); if (final_name == NULL) break; - sprintf(final_name, first ? "%s.%s" : ",%s.%s", dll_name, func->name); + sprintf(final_name, first ? "%s.%s": ",%s.%s", dll_name, func->name); // Lowercase the whole thing. @@ -2721,92 +2296,8 @@ define_function(imphash) #endif // defined(HAVE_LIBCRYPTO) || defined(HAVE_WINCRYPT_H) -long long pe_imports_dll(IMPORTED_DLL* dll, char* dll_name) -{ - if (dll == NULL) - return 0; - - long long result = 0; - for (; dll != NULL; dll = dll->next) - { - if (strcasecmp(dll->name, dll_name) == 0) - { - IMPORT_FUNCTION* fun = dll->functions; - for (; fun != NULL; fun = fun->next) - { - result++; - } - } - } - return result; -} - -long long pe_imports(IMPORTED_DLL* dll, char* dll_name, char* fun_name) -{ - if (dll == NULL) - return 0; - - for (; dll != NULL; dll = dll->next) - { - if (strcasecmp(dll->name, dll_name) == 0) - { - IMPORT_FUNCTION* fun = dll->functions; - for (; fun != NULL; fun = fun->next) - { - if (strcasecmp(fun->name, fun_name) == 0) - return 1; - } - } - } - return 0; -} - -long long pe_imports_regexp( - YR_SCAN_CONTEXT* context, - IMPORTED_DLL* dll, - RE* dll_name, - RE* fun_name) -{ - if (dll == NULL) - return 0; - - long long result = 0; - for (; dll != NULL; dll = dll->next) - { - if (yr_re_match(context, dll_name, dll->name) > 0) - { - IMPORT_FUNCTION* fun = dll->functions; - for (; fun != NULL; fun = fun->next) - { - if (yr_re_match(context, fun_name, fun->name) > 0) - result++; - } - } - } - return result; -} - -long long pe_imports_ordinal(IMPORTED_DLL* dll, char* dll_name, int ordinal) -{ - if (dll == NULL) - return 0; - - for (; dll != NULL; dll = dll->next) - { - if (strcasecmp(dll->name, dll_name) == 0) - { - IMPORT_FUNCTION* fun = dll->functions; - for (; fun != NULL; fun = fun->next) - { - if (fun->has_ordinal && fun->ordinal == ordinal) - return 1; - } - } - } - return 0; -} -define_function(imports_standard) +define_function(imports) { char* dll_name = string_argument(1); char* function_name = string_argument(2); @@ -2814,151 +2305,136 @@ define_function(imports_standard) YR_OBJECT* module = module(); PE* pe = (PE*) module->data; + IMPORTED_DLL* imported_dll; + if (!pe) - return_integer(YR_UNDEFINED); + return_integer(UNDEFINED); - return_integer(pe_imports(pe->imported_dlls, dll_name, function_name)); -} + imported_dll = pe->imported_dlls; -define_function(imports) -{ - int flags = integer_argument(1); - char* dll_name = string_argument(2); - char* function_name = string_argument(3); + while (imported_dll != NULL) + { + if (strcasecmp(imported_dll->name, dll_name) == 0) + { + IMPORT_FUNCTION* imported_func = imported_dll->functions; - YR_OBJECT* module = module(); - PE* pe = (PE*) module->data; + while (imported_func != NULL) + { + if (imported_func->name && + strcasecmp(imported_func->name, function_name) == 0) + return_integer(1); - if (!pe) - return_integer(YR_UNDEFINED); + imported_func = imported_func->next; + } + } - if (flags & IMPORT_STANDARD && - pe_imports(pe->imported_dlls, dll_name, function_name)) - { - return_integer(1); - } - if (flags & IMPORT_DELAYED && - pe_imports(pe->delay_imported_dlls, dll_name, function_name)) - { - return_integer(1); + imported_dll = imported_dll->next; } + return_integer(0); } -define_function(imports_standard_ordinal) +define_function(imports_ordinal) { char* dll_name = string_argument(1); - int64_t ordinal = integer_argument(2); + uint64_t ordinal = integer_argument(2); YR_OBJECT* module = module(); PE* pe = (PE*) module->data; + IMPORTED_DLL* imported_dll; + if (!pe) - return_integer(YR_UNDEFINED); + return_integer(UNDEFINED); - return_integer(pe_imports_ordinal(pe->imported_dlls, dll_name, ordinal)) -} + imported_dll = pe->imported_dlls; -define_function(imports_ordinal) -{ - int flags = integer_argument(1); - char* dll_name = string_argument(2); - int64_t ordinal = integer_argument(3); + while (imported_dll != NULL) + { + if (strcasecmp(imported_dll->name, dll_name) == 0) + { + IMPORT_FUNCTION* imported_func = imported_dll->functions; - YR_OBJECT* module = module(); - PE* pe = (PE*) module->data; + while (imported_func != NULL) + { + if (imported_func->has_ordinal && imported_func->ordinal == ordinal) + return_integer(1); - if (!pe) - return_integer(YR_UNDEFINED); + imported_func = imported_func->next; + } + } - if (flags & IMPORT_STANDARD && - pe_imports_ordinal(pe->imported_dlls, dll_name, ordinal)) - { - return_integer(1); - } - if (flags & IMPORT_DELAYED && - pe_imports_ordinal(pe->delay_imported_dlls, dll_name, ordinal)) - { - return_integer(1); + imported_dll = imported_dll->next; } + return_integer(0); } -define_function(imports_standard_regex) +define_function(imports_regex) { - RE* dll_name = regexp_argument(1); - RE* function_name = regexp_argument(2); - YR_OBJECT* module = module(); - PE* pe = (PE*) module->data; + PE* pe = (PE*)module->data; - if (!pe) - return_integer(YR_UNDEFINED); + IMPORTED_DLL* imported_dll; + uint64_t imported_func_count = 0; - return_integer(pe_imports_regexp( - scan_context(), pe->imported_dlls, dll_name, function_name)) -} + if (!pe) + return_integer(UNDEFINED); -define_function(imports_regex) -{ - int flags = integer_argument(1); - RE* dll_name = regexp_argument(2); - RE* function_name = regexp_argument(3); + imported_dll = pe->imported_dlls; - YR_OBJECT* module = module(); - PE* pe = (PE*) module->data; + while (imported_dll != NULL) + { + if (yr_re_match(scan_context(), regexp_argument(1), imported_dll->name) > 0) + { + IMPORT_FUNCTION* imported_func = imported_dll->functions; - if (!pe) - return_integer(YR_UNDEFINED); + while (imported_func != NULL) + { + if (yr_re_match(scan_context(), regexp_argument(2), imported_func->name) > 0) + imported_func_count++; + imported_func = imported_func->next; + } + } - long long result = 0; - if (flags & IMPORT_STANDARD) - { - result += pe_imports_regexp( - scan_context(), pe->imported_dlls, dll_name, function_name); - } - if (flags & IMPORT_DELAYED) - { - result += pe_imports_regexp( - scan_context(), pe->delay_imported_dlls, dll_name, function_name); + imported_dll = imported_dll->next; } - return_integer(result); + + return_integer(imported_func_count); } -define_function(imports_standard_dll) +define_function(imports_dll) { char* dll_name = string_argument(1); YR_OBJECT* module = module(); PE* pe = (PE*) module->data; - if (!pe) - return_integer(YR_UNDEFINED); + IMPORTED_DLL* imported_dll; + uint64_t imported_func_count = 0; - return_integer(pe_imports_dll(pe->imported_dlls, dll_name)); -} + if (!pe) + return_integer(UNDEFINED); -define_function(imports_dll) -{ - int flags = integer_argument(1); - char* dll_name = string_argument(2); + imported_dll = pe->imported_dlls; - YR_OBJECT* module = module(); - PE* pe = (PE*) module->data; + while (imported_dll != NULL) + { + if (strcasecmp(imported_dll->name, dll_name) == 0) + { + IMPORT_FUNCTION* imported_func = imported_dll->functions; - if (!pe) - return_integer(YR_UNDEFINED); + while (imported_func != NULL) + { + imported_func_count++; + imported_func = imported_func->next; + } + } - long long result = 0; - if (flags & IMPORT_STANDARD) - { - result += pe_imports_dll(pe->imported_dlls, dll_name); + imported_dll = imported_dll->next; } - if (flags & IMPORT_DELAYED) - { - result += pe_imports_dll(pe->delay_imported_dlls, dll_name); - } - return_integer(result); + + return_integer(imported_func_count); } define_function(locale) @@ -2967,20 +2443,22 @@ define_function(locale) PE* pe = (PE*) module->data; uint64_t locale = integer_argument(1); + int64_t n, i; if (is_undefined(module, "number_of_resources")) - return_integer(YR_UNDEFINED); + return_integer(UNDEFINED); - // If not a PE file, return YR_UNDEFINED + // If not a PE file, return UNDEFINED if (pe == NULL) - return_integer(YR_UNDEFINED); + return_integer(UNDEFINED); - int n = (int) get_integer(module, "number_of_resources"); + n = get_integer(module, "number_of_resources"); - for (int i = 0; i < n; i++) + for (i = 0; i < n; i++) { - uint64_t rsrc_language = get_integer(module, "resources[%i].language", i); + uint64_t rsrc_language = get_integer( + module, "resources[%" PRId64 "].language", i); if ((rsrc_language & 0xFFFF) == locale) return_integer(1); @@ -2989,26 +2467,29 @@ define_function(locale) return_integer(0); } + define_function(language) { YR_OBJECT* module = module(); PE* pe = (PE*) module->data; uint64_t language = integer_argument(1); + int64_t n, i; if (is_undefined(module, "number_of_resources")) - return_integer(YR_UNDEFINED); + return_integer(UNDEFINED); - // If not a PE file, return YR_UNDEFINED + // If not a PE file, return UNDEFINED if (pe == NULL) - return_integer(YR_UNDEFINED); + return_integer(UNDEFINED); - int n = (int) get_integer(module, "number_of_resources"); + n = get_integer(module, "number_of_resources"); - for (int i = 0; i < n; i++) + for (i = 0; i < n; i++) { - uint64_t rsrc_language = get_integer(module, "resources[%i].language", i); + uint64_t rsrc_language = get_integer( + module, "resources[%" PRId64 "].language", i); if ((rsrc_language & 0xFF) == language) return_integer(1); @@ -3017,40 +2498,44 @@ define_function(language) return_integer(0); } + define_function(is_dll) { int64_t characteristics; YR_OBJECT* module = module(); if (is_undefined(module, "characteristics")) - return_integer(YR_UNDEFINED); + return_integer(UNDEFINED); characteristics = get_integer(module, "characteristics"); return_integer(characteristics & IMAGE_FILE_DLL); } + define_function(is_32bit) { YR_OBJECT* module = module(); PE* pe = (PE*) module->data; if (pe == NULL) - return_integer(YR_UNDEFINED); + return_integer(UNDEFINED); return_integer(IS_64BITS_PE(pe) ? 0 : 1); } + define_function(is_64bit) { YR_OBJECT* module = module(); PE* pe = (PE*) module->data; if (pe == NULL) - return_integer(YR_UNDEFINED); + return_integer(UNDEFINED); return_integer(IS_64BITS_PE(pe) ? 1 : 0); } + // _rich_version // // Returns the number of rich signatures that match the specified version and @@ -3064,6 +2549,8 @@ static uint64_t _rich_version( int64_t rich_length; int64_t rich_count; + int i; + PRICH_SIGNATURE clear_rich_signature; SIZED_STRING* rich_string; @@ -3071,34 +2558,34 @@ static uint64_t _rich_version( // Check if the required fields are set if (is_undefined(module, "rich_signature.length")) - return YR_UNDEFINED; + return UNDEFINED; rich_length = get_integer(module, "rich_signature.length"); rich_string = get_string(module, "rich_signature.clear_data"); - // If the clear_data was not set, return YR_UNDEFINED + // If the clear_data was not set, return UNDEFINED if (rich_string == NULL) - return YR_UNDEFINED; + return UNDEFINED; - if (version == YR_UNDEFINED && toolid == YR_UNDEFINED) - return false; + if (version == UNDEFINED && toolid == UNDEFINED) + return false; clear_rich_signature = (PRICH_SIGNATURE) rich_string->c_string; // Loop over the versions in the rich signature - rich_count = (rich_length - sizeof(RICH_SIGNATURE)) / - sizeof(RICH_VERSION_INFO); + rich_count = \ + (rich_length - sizeof(RICH_SIGNATURE)) / sizeof(RICH_VERSION_INFO); - for (int i = 0; i < rich_count; i++) + for (i = 0; i < rich_count; i++) { DWORD id_version = yr_le32toh(clear_rich_signature->versions[i].id_version); int match_version = (version == RICH_VERSION_VERSION(id_version)); int match_toolid = (toolid == RICH_VERSION_ID(id_version)); - if ((version == YR_UNDEFINED || match_version) && - (toolid == YR_UNDEFINED || match_toolid)) + if ((version == UNDEFINED || match_version) && + (toolid == UNDEFINED || match_toolid)) { result += yr_le32toh(clear_rich_signature->versions[i].times); } @@ -3107,28 +2594,35 @@ static uint64_t _rich_version( return result; } + define_function(rich_version) { - return_integer(_rich_version(module(), integer_argument(1), YR_UNDEFINED)); + return_integer( + _rich_version(module(), integer_argument(1), UNDEFINED)); } + define_function(rich_version_toolid) { return_integer( _rich_version(module(), integer_argument(1), integer_argument(2))); } + define_function(rich_toolid) { - return_integer(_rich_version(module(), YR_UNDEFINED, integer_argument(1))); + return_integer( + _rich_version(module(), UNDEFINED, integer_argument(1))); } + define_function(rich_toolid_version) { return_integer( _rich_version(module(), integer_argument(2), integer_argument(1))); } + define_function(calculate_checksum) { YR_OBJECT* module = module(); @@ -3136,15 +2630,15 @@ define_function(calculate_checksum) uint64_t csum = 0; size_t csum_offset; + size_t i, j; if (pe == NULL) - return_integer(YR_UNDEFINED); + return_integer(UNDEFINED); csum_offset = ((uint8_t*) &(pe->header->OptionalHeader) + - offsetof(IMAGE_OPTIONAL_HEADER32, CheckSum)) - - pe->data; + offsetof(IMAGE_OPTIONAL_HEADER32, CheckSum)) - pe->data; - for (size_t i = 0; i <= pe->data_size / 4; i++) + for (i = 0; i <= pe->data_size / 4; i++) { // Treat the CheckSum field as 0 -- the offset is the same for // PE32 and PE64. @@ -3154,14 +2648,14 @@ define_function(calculate_checksum) if (4 * i + 4 <= pe->data_size) { - csum += - ((uint64_t) pe->data[4 * i] + ((uint64_t) pe->data[4 * i + 1] << 8) + - ((uint64_t) pe->data[4 * i + 2] << 16) + - ((uint64_t) pe->data[4 * i + 3] << 24)); + csum += ((uint64_t) pe->data[4 * i] + + ((uint64_t) pe->data[4 * i + 1] << 8) + + ((uint64_t) pe->data[4 * i + 2] << 16) + + ((uint64_t) pe->data[4 * i + 3] << 24)); } else { - for (size_t j = 0; j < pe->data_size % 4; j++) + for (j = 0; j < pe->data_size % 4; j++) csum += (uint64_t) pe->data[4 * i + j] << (8 * j); } @@ -3177,27 +2671,28 @@ define_function(calculate_checksum) return_integer(csum); } + define_function(rva_to_offset) { YR_OBJECT* module = module(); PE* pe = (PE*) module->data; - uint64_t rva; - int64_t offset; + uint64_t rva, offset; if (pe == NULL) - return_integer(YR_UNDEFINED); + return_integer(UNDEFINED); rva = integer_argument(1); offset = pe_rva_to_offset(pe, rva); - if (offset == -1) - return_integer(YR_UNDEFINED); + return_integer(UNDEFINED); return_integer(offset); } -begin_declarations + +begin_declarations; + declare_integer("MACHINE_UNKNOWN"); declare_integer("MACHINE_AM33"); declare_integer("MACHINE_AMD64"); @@ -3220,16 +2715,6 @@ begin_declarations declare_integer("MACHINE_SH5"); declare_integer("MACHINE_THUMB"); declare_integer("MACHINE_WCEMIPSV2"); - declare_integer("MACHINE_TARGET_HOST"); - declare_integer("MACHINE_R3000"); - declare_integer("MACHINE_R10000"); - declare_integer("MACHINE_ALPHA"); - declare_integer("MACHINE_SH3E"); - declare_integer("MACHINE_ALPHA64"); - declare_integer("MACHINE_AXP64"); - declare_integer("MACHINE_TRICORE"); - declare_integer("MACHINE_CEF"); - declare_integer("MACHINE_CEE"); declare_integer("SUBSYSTEM_UNKNOWN"); declare_integer("SUBSYSTEM_NATIVE"); @@ -3242,20 +2727,16 @@ begin_declarations declare_integer("SUBSYSTEM_EFI_APPLICATION"); declare_integer("SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER"); declare_integer("SUBSYSTEM_EFI_RUNTIME_DRIVER"); - declare_integer("SUBSYSTEM_EFI_ROM_IMAGE"); declare_integer("SUBSYSTEM_XBOX"); declare_integer("SUBSYSTEM_WINDOWS_BOOT_APPLICATION"); - declare_integer("HIGH_ENTROPY_VA"); declare_integer("DYNAMIC_BASE"); declare_integer("FORCE_INTEGRITY"); declare_integer("NX_COMPAT"); declare_integer("NO_ISOLATION"); declare_integer("NO_SEH"); declare_integer("NO_BIND"); - declare_integer("APPCONTAINER"); declare_integer("WDM_DRIVER"); - declare_integer("GUARD_CF"); declare_integer("TERMINAL_SERVER_AWARE"); declare_integer("RELOCS_STRIPPED"); @@ -3282,7 +2763,6 @@ begin_declarations declare_integer("IMAGE_DIRECTORY_ENTRY_BASERELOC"); declare_integer("IMAGE_DIRECTORY_ENTRY_DEBUG"); declare_integer("IMAGE_DIRECTORY_ENTRY_ARCHITECTURE"); - declare_integer("IMAGE_DIRECTORY_ENTRY_COPYRIGHT"); declare_integer("IMAGE_DIRECTORY_ENTRY_GLOBALPTR"); declare_integer("IMAGE_DIRECTORY_ENTRY_TLS"); declare_integer("IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG"); @@ -3291,40 +2771,11 @@ begin_declarations declare_integer("IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT"); declare_integer("IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR"); - declare_integer("IMAGE_NT_OPTIONAL_HDR32_MAGIC"); - declare_integer("IMAGE_NT_OPTIONAL_HDR64_MAGIC"); - declare_integer("IMAGE_ROM_OPTIONAL_HDR_MAGIC"); - - declare_integer("SECTION_NO_PAD"); declare_integer("SECTION_CNT_CODE"); declare_integer("SECTION_CNT_INITIALIZED_DATA"); declare_integer("SECTION_CNT_UNINITIALIZED_DATA"); - declare_integer("SECTION_LNK_OTHER"); - declare_integer("SECTION_LNK_INFO"); - declare_integer("SECTION_LNK_REMOVE"); - declare_integer("SECTION_LNK_COMDAT"); - declare_integer("SECTION_NO_DEFER_SPEC_EXC"); declare_integer("SECTION_GPREL"); - declare_integer("SECTION_MEM_FARDATA"); - declare_integer("SECTION_MEM_PURGEABLE"); declare_integer("SECTION_MEM_16BIT"); - declare_integer("SECTION_MEM_LOCKED"); - declare_integer("SECTION_MEM_PRELOAD"); - declare_integer("SECTION_ALIGN_1BYTES"); - declare_integer("SECTION_ALIGN_2BYTES"); - declare_integer("SECTION_ALIGN_4BYTES"); - declare_integer("SECTION_ALIGN_8BYTES"); - declare_integer("SECTION_ALIGN_16BYTES"); - declare_integer("SECTION_ALIGN_32BYTES"); - declare_integer("SECTION_ALIGN_64BYTES"); - declare_integer("SECTION_ALIGN_128BYTES"); - declare_integer("SECTION_ALIGN_256BYTES"); - declare_integer("SECTION_ALIGN_512BYTES"); - declare_integer("SECTION_ALIGN_1024BYTES"); - declare_integer("SECTION_ALIGN_2048BYTES"); - declare_integer("SECTION_ALIGN_4096BYTES"); - declare_integer("SECTION_ALIGN_8192BYTES"); - declare_integer("SECTION_ALIGN_MASK"); declare_integer("SECTION_LNK_NRELOC_OVFL"); declare_integer("SECTION_MEM_DISCARDABLE"); declare_integer("SECTION_MEM_NOT_CACHED"); @@ -3333,7 +2784,6 @@ begin_declarations declare_integer("SECTION_MEM_EXECUTE"); declare_integer("SECTION_MEM_READ"); declare_integer("SECTION_MEM_WRITE"); - declare_integer("SECTION_SCALE_INDEX"); declare_integer("RESOURCE_TYPE_CURSOR"); declare_integer("RESOURCE_TYPE_BITMAP"); @@ -3357,23 +2807,6 @@ begin_declarations declare_integer("RESOURCE_TYPE_HTML"); declare_integer("RESOURCE_TYPE_MANIFEST"); - declare_integer("IMAGE_DEBUG_TYPE_UNKNOWN"); - declare_integer("IMAGE_DEBUG_TYPE_COFF"); - declare_integer("IMAGE_DEBUG_TYPE_CODEVIEW"); - declare_integer("IMAGE_DEBUG_TYPE_FPO"); - declare_integer("IMAGE_DEBUG_TYPE_MISC"); - declare_integer("IMAGE_DEBUG_TYPE_EXCEPTION"); - declare_integer("IMAGE_DEBUG_TYPE_FIXUP"); - declare_integer("IMAGE_DEBUG_TYPE_OMAP_TO_SRC"); - declare_integer("IMAGE_DEBUG_TYPE_OMAP_FROM_SRC"); - declare_integer("IMAGE_DEBUG_TYPE_BORLAND"); - declare_integer("IMAGE_DEBUG_TYPE_RESERVED10"); - declare_integer("IMAGE_DEBUG_TYPE_CLSID"); - declare_integer("IMAGE_DEBUG_TYPE_VC_FEATURE"); - declare_integer("IMAGE_DEBUG_TYPE_POGO"); - declare_integer("IMAGE_DEBUG_TYPE_ILTCG"); - declare_integer("IMAGE_DEBUG_TYPE_MPX"); - declare_integer("IMAGE_DEBUG_TYPE_REPRO"); declare_integer("is_pe"); declare_integer("machine"); @@ -3383,20 +2816,14 @@ begin_declarations declare_integer("number_of_symbols"); declare_integer("size_of_optional_header"); declare_integer("characteristics"); - + declare_integer("is_reproducible_build"); + declare_integer("entry_point"); - declare_integer("entry_point_raw"); declare_integer("image_base"); declare_integer("number_of_rva_and_sizes"); - declare_integer("number_of_version_infos"); declare_string_dictionary("version_info"); - begin_struct_array("version_info_list") - declare_string("key"); - declare_string("value"); - end_struct_array("version_info_list"); - declare_integer("opthdr_magic"); declare_integer("size_of_code"); declare_integer("size_of_initialized_data"); @@ -3406,22 +2833,22 @@ begin_declarations declare_integer("section_alignment"); declare_integer("file_alignment"); - begin_struct("linker_version") + begin_struct("linker_version"); declare_integer("major"); declare_integer("minor"); end_struct("linker_version"); - begin_struct("os_version") + begin_struct("os_version"); declare_integer("major"); declare_integer("minor"); end_struct("os_version"); - begin_struct("image_version") + begin_struct("image_version"); declare_integer("major"); declare_integer("minor"); end_struct("image_version"); - begin_struct("subsystem_version") + begin_struct("subsystem_version"); declare_integer("major"); declare_integer("minor"); end_struct("subsystem_version"); @@ -3441,14 +2868,13 @@ begin_declarations declare_integer("size_of_heap_commit"); declare_integer("loader_flags"); - begin_struct_array("data_directories") + begin_struct_array("data_directories"); declare_integer("virtual_address"); declare_integer("size"); end_struct_array("data_directories"); - begin_struct_array("sections") + begin_struct_array("sections"); declare_string("name"); - declare_string("full_name"); declare_integer("characteristics"); declare_integer("virtual_address"); declare_integer("virtual_size"); @@ -3460,12 +2886,12 @@ begin_declarations declare_integer("number_of_line_numbers"); end_struct_array("sections"); - begin_struct("overlay") + begin_struct("overlay"); declare_integer("offset"); declare_integer("size"); end_struct("overlay"); - begin_struct("rich_signature") + begin_struct("rich_signature"); declare_integer("offset"); declare_integer("length"); declare_integer("key"); @@ -3477,14 +2903,11 @@ begin_declarations declare_function("toolid", "ii", "i", rich_toolid_version); end_struct("rich_signature"); -#if defined(HAVE_LIBCRYPTO) || defined(HAVE_WINCRYPT_H) || \ - defined(HAVE_COMMONCRYPTO_COMMONCRYPTO_H) + #if defined(HAVE_LIBCRYPTO) || \ + defined(HAVE_WINCRYPT_H) || \ + defined(HAVE_COMMONCRYPTO_COMMONCRYPTO_H) declare_function("imphash", "", "s", imphash); -#endif - - declare_integer("IMPORT_DELAYED"); - declare_integer("IMPORT_STANDARD"); - declare_integer("IMPORT_ANY"); + #endif declare_function("section_index", "s", "i", section_index_name); declare_function("section_index", "i", "i", section_index_addr); @@ -3494,14 +2917,10 @@ begin_declarations declare_function("exports_index", "s", "i", exports_index_name); declare_function("exports_index", "i", "i", exports_index_ordinal); declare_function("exports_index", "r", "i", exports_index_regex); - declare_function("imports", "ss", "i", imports_standard); - declare_function("imports", "si", "i", imports_standard_ordinal); - declare_function("imports", "s", "i", imports_standard_dll); - declare_function("imports", "rr", "i", imports_standard_regex); - declare_function("imports", "iss", "i", imports); - declare_function("imports", "isi", "i", imports_ordinal); - declare_function("imports", "is", "i", imports_dll); - declare_function("imports", "irr", "i", imports_regex); + declare_function("imports", "ss", "i", imports); + declare_function("imports", "si", "i", imports_ordinal); + declare_function("imports", "s", "i", imports_dll); + declare_function("imports", "rr", "i", imports_regex); declare_function("locale", "i", "i", locale); declare_function("language", "i", "i", language); declare_function("is_dll", "", "i", is_dll); @@ -3509,47 +2928,25 @@ begin_declarations declare_function("is_64bit", "", "i", is_64bit); declare_integer("number_of_imports"); - declare_integer("number_of_imported_functions"); - declare_integer("number_of_delayed_imports"); - declare_integer("number_of_delayed_imported_functions"); declare_integer("number_of_exports"); declare_string("dll_name"); declare_integer("export_timestamp"); - begin_struct_array("export_details") + begin_struct_array("export_details"); declare_integer("offset"); declare_string("name"); declare_string("forward_name"); declare_integer("ordinal"); - end_struct_array("export_details") - - begin_struct_array("import_details") - declare_string("library_name"); - declare_integer("number_of_functions"); - begin_struct_array("functions") - declare_string("name"); - declare_integer("ordinal"); - end_struct_array("functions"); - end_struct_array("import_details"); - - begin_struct_array("delay_import_details") - declare_string("library_name"); - declare_integer("number_of_function"); - begin_struct_array("functions") - declare_string("name"); - declare_integer("ordinal"); - end_struct_array("functions"); - end_struct_array("delay_import_details"); + end_struct_array("export_details"); declare_integer("resource_timestamp"); - begin_struct("resource_version") + begin_struct("resource_version"); declare_integer("major"); declare_integer("minor"); - end_struct("resource_version") + end_struct("resource_version"); - begin_struct_array("resources") - declare_integer("rva"); + begin_struct_array("resources"); declare_integer("offset"); declare_integer("length"); declare_integer("type"); @@ -3558,32 +2955,34 @@ begin_declarations declare_string("type_string"); declare_string("name_string"); declare_string("language_string"); - end_struct_array("resources") + end_struct_array("resources"); declare_integer("number_of_resources"); declare_string("pdb_path"); -#if defined(HAVE_LIBCRYPTO) && !defined(BORINGSSL) - begin_struct_array("signatures") + #if defined(HAVE_LIBCRYPTO) && !defined(BORINGSSL) + begin_struct_array("signatures"); declare_string("thumbprint"); declare_string("issuer"); declare_string("subject"); declare_integer("version"); declare_string("algorithm"); - declare_string("algorithm_oid"); declare_string("serial"); declare_integer("not_before"); declare_integer("not_after"); declare_function("valid_on", "i", "i", valid_on); - end_struct_array("signatures") + end_struct_array("signatures"); declare_integer("number_of_signatures"); -#endif + #endif declare_function("rva_to_offset", "i", "i", rva_to_offset); -end_declarations -int module_initialize(YR_MODULE* module) +end_declarations; + + +int module_initialize( + YR_MODULE* module) { #if defined(HAVE_LIBCRYPTO) // Not checking return value here because if it fails we will not parse the @@ -3593,11 +2992,14 @@ int module_initialize(YR_MODULE* module) return ERROR_SUCCESS; } -int module_finalize(YR_MODULE* module) + +int module_finalize( + YR_MODULE* module) { return ERROR_SUCCESS; } + int module_load( YR_SCAN_CONTEXT* context, YR_OBJECT* module_object, @@ -3611,319 +3013,333 @@ int module_load( const uint8_t* block_data = NULL; PE* pe = NULL; - set_integer(IMPORT_DELAYED, module_object, "IMPORT_DELAYED"); - set_integer(IMPORT_STANDARD, module_object, "IMPORT_STANDARD"); - set_integer(IMPORT_ANY, module_object, "IMPORT_ANY"); - - set_integer(IMAGE_FILE_MACHINE_UNKNOWN, module_object, "MACHINE_UNKNOWN"); - set_integer(IMAGE_FILE_MACHINE_AM33, module_object, "MACHINE_AM33"); - set_integer(IMAGE_FILE_MACHINE_AMD64, module_object, "MACHINE_AMD64"); - set_integer(IMAGE_FILE_MACHINE_ARM, module_object, "MACHINE_ARM"); - set_integer(IMAGE_FILE_MACHINE_ARMNT, module_object, "MACHINE_ARMNT"); - set_integer(IMAGE_FILE_MACHINE_ARM64, module_object, "MACHINE_ARM64"); - set_integer(IMAGE_FILE_MACHINE_EBC, module_object, "MACHINE_EBC"); - set_integer(IMAGE_FILE_MACHINE_I386, module_object, "MACHINE_I386"); - set_integer(IMAGE_FILE_MACHINE_IA64, module_object, "MACHINE_IA64"); - set_integer(IMAGE_FILE_MACHINE_M32R, module_object, "MACHINE_M32R"); - set_integer(IMAGE_FILE_MACHINE_MIPS16, module_object, "MACHINE_MIPS16"); - set_integer(IMAGE_FILE_MACHINE_MIPSFPU, module_object, "MACHINE_MIPSFPU"); - set_integer(IMAGE_FILE_MACHINE_MIPSFPU16, module_object, "MACHINE_MIPSFPU16"); - set_integer(IMAGE_FILE_MACHINE_POWERPC, module_object, "MACHINE_POWERPC"); - set_integer(IMAGE_FILE_MACHINE_POWERPCFP, module_object, "MACHINE_POWERPCFP"); - set_integer(IMAGE_FILE_MACHINE_R4000, module_object, "MACHINE_R4000"); - set_integer(IMAGE_FILE_MACHINE_SH3, module_object, "MACHINE_SH3"); - set_integer(IMAGE_FILE_MACHINE_SH3DSP, module_object, "MACHINE_SH3DSP"); - set_integer(IMAGE_FILE_MACHINE_SH4, module_object, "MACHINE_SH4"); - set_integer(IMAGE_FILE_MACHINE_SH5, module_object, "MACHINE_SH5"); - set_integer(IMAGE_FILE_MACHINE_THUMB, module_object, "MACHINE_THUMB"); - set_integer(IMAGE_FILE_MACHINE_WCEMIPSV2, module_object, "MACHINE_WCEMIPSV2"); - set_integer( - IMAGE_FILE_MACHINE_TARGET_HOST, module_object, "MACHINE_TARGET_HOST"); - set_integer(IMAGE_FILE_MACHINE_R3000, module_object, "MACHINE_R3000"); - set_integer(IMAGE_FILE_MACHINE_R10000, module_object, "MACHINE_R10000"); - set_integer(IMAGE_FILE_MACHINE_ALPHA, module_object, "MACHINE_ALPHA"); - set_integer(IMAGE_FILE_MACHINE_SH3E, module_object, "MACHINE_SH3E"); - set_integer(IMAGE_FILE_MACHINE_ALPHA64, module_object, "MACHINE_ALPHA64"); - set_integer(IMAGE_FILE_MACHINE_AXP64, module_object, "MACHINE_AXP64"); - set_integer(IMAGE_FILE_MACHINE_TRICORE, module_object, "MACHINE_TRICORE"); - set_integer(IMAGE_FILE_MACHINE_CEF, module_object, "MACHINE_CEF"); - set_integer(IMAGE_FILE_MACHINE_CEE, module_object, "MACHINE_CEE"); - - set_integer(IMAGE_SUBSYSTEM_UNKNOWN, module_object, "SUBSYSTEM_UNKNOWN"); - set_integer(IMAGE_SUBSYSTEM_NATIVE, module_object, "SUBSYSTEM_NATIVE"); - set_integer( - IMAGE_SUBSYSTEM_WINDOWS_GUI, module_object, "SUBSYSTEM_WINDOWS_GUI"); - set_integer( - IMAGE_SUBSYSTEM_WINDOWS_CUI, module_object, "SUBSYSTEM_WINDOWS_CUI"); - set_integer(IMAGE_SUBSYSTEM_OS2_CUI, module_object, "SUBSYSTEM_OS2_CUI"); - set_integer(IMAGE_SUBSYSTEM_POSIX_CUI, module_object, "SUBSYSTEM_POSIX_CUI"); - set_integer( - IMAGE_SUBSYSTEM_NATIVE_WINDOWS, - module_object, + set_integer( + IMAGE_FILE_MACHINE_UNKNOWN, module_object, + "MACHINE_UNKNOWN"); + set_integer( + IMAGE_FILE_MACHINE_AM33, module_object, + "MACHINE_AM33"); + set_integer( + IMAGE_FILE_MACHINE_AMD64, module_object, + "MACHINE_AMD64"); + set_integer( + IMAGE_FILE_MACHINE_ARM, module_object, + "MACHINE_ARM"); + set_integer( + IMAGE_FILE_MACHINE_ARMNT, module_object, + "MACHINE_ARMNT"); + set_integer( + IMAGE_FILE_MACHINE_ARM64, module_object, + "MACHINE_ARM64"); + set_integer( + IMAGE_FILE_MACHINE_EBC, module_object, + "MACHINE_EBC"); + set_integer( + IMAGE_FILE_MACHINE_I386, module_object, + "MACHINE_I386"); + set_integer( + IMAGE_FILE_MACHINE_IA64, module_object, + "MACHINE_IA64"); + set_integer( + IMAGE_FILE_MACHINE_M32R, module_object, + "MACHINE_M32R"); + set_integer( + IMAGE_FILE_MACHINE_MIPS16, module_object, + "MACHINE_MIPS16"); + set_integer( + IMAGE_FILE_MACHINE_MIPSFPU, module_object, + "MACHINE_MIPSFPU"); + set_integer( + IMAGE_FILE_MACHINE_MIPSFPU16, module_object, + "MACHINE_MIPSFPU16"); + set_integer( + IMAGE_FILE_MACHINE_POWERPC, module_object, + "MACHINE_POWERPC"); + set_integer( + IMAGE_FILE_MACHINE_POWERPCFP, module_object, + "MACHINE_POWERPCFP"); + set_integer( + IMAGE_FILE_MACHINE_R4000, module_object, + "MACHINE_R4000"); + set_integer( + IMAGE_FILE_MACHINE_SH3, module_object, + "MACHINE_SH3"); + set_integer( + IMAGE_FILE_MACHINE_SH3DSP, module_object, + "MACHINE_SH3DSP"); + set_integer( + IMAGE_FILE_MACHINE_SH4, module_object, + "MACHINE_SH4"); + set_integer( + IMAGE_FILE_MACHINE_SH5, module_object, + "MACHINE_SH5"); + set_integer( + IMAGE_FILE_MACHINE_THUMB, module_object, + "MACHINE_THUMB"); + set_integer( + IMAGE_FILE_MACHINE_WCEMIPSV2, module_object, + "MACHINE_WCEMIPSV2"); + + set_integer( + IMAGE_SUBSYSTEM_UNKNOWN, module_object, + "SUBSYSTEM_UNKNOWN"); + set_integer( + IMAGE_SUBSYSTEM_NATIVE, module_object, + "SUBSYSTEM_NATIVE"); + set_integer( + IMAGE_SUBSYSTEM_WINDOWS_GUI, module_object, + "SUBSYSTEM_WINDOWS_GUI"); + set_integer( + IMAGE_SUBSYSTEM_WINDOWS_CUI, module_object, + "SUBSYSTEM_WINDOWS_CUI"); + set_integer( + IMAGE_SUBSYSTEM_OS2_CUI, module_object, + "SUBSYSTEM_OS2_CUI"); + set_integer( + IMAGE_SUBSYSTEM_POSIX_CUI, module_object, + "SUBSYSTEM_POSIX_CUI"); + set_integer( + IMAGE_SUBSYSTEM_NATIVE_WINDOWS, module_object, "SUBSYSTEM_NATIVE_WINDOWS"); set_integer( - IMAGE_SUBSYSTEM_WINDOWS_CE_GUI, - module_object, + IMAGE_SUBSYSTEM_WINDOWS_CE_GUI, module_object, "SUBSYSTEM_WINDOWS_CE_GUI"); set_integer( - IMAGE_SUBSYSTEM_EFI_APPLICATION, - module_object, + IMAGE_SUBSYSTEM_EFI_APPLICATION, module_object, "SUBSYSTEM_EFI_APPLICATION"); set_integer( - IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER, - module_object, + IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER, module_object, "SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER"); set_integer( - IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER, - module_object, + IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER, module_object, "SUBSYSTEM_EFI_RUNTIME_DRIVER"); set_integer( - IMAGE_SUBSYSTEM_EFI_ROM_IMAGE, module_object, "SUBSYSTEM_EFI_ROM_IMAGE"); - set_integer(IMAGE_SUBSYSTEM_XBOX, module_object, "SUBSYSTEM_XBOX"); + IMAGE_SUBSYSTEM_XBOX, module_object, + "SUBSYSTEM_XBOX"); set_integer( - IMAGE_SUBSYSTEM_WINDOWS_BOOT_APPLICATION, - module_object, + IMAGE_SUBSYSTEM_WINDOWS_BOOT_APPLICATION, module_object, "SUBSYSTEM_WINDOWS_BOOT_APPLICATION"); set_integer( - IMAGE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA, - module_object, - "HIGH_ENTROPY_VA"); + IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE, module_object, + "DYNAMIC_BASE"); set_integer( - IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE, module_object, "DYNAMIC_BASE"); - set_integer( - IMAGE_DLLCHARACTERISTICS_FORCE_INTEGRITY, - module_object, + IMAGE_DLLCHARACTERISTICS_FORCE_INTEGRITY, module_object, "FORCE_INTEGRITY"); - set_integer(IMAGE_DLLCHARACTERISTICS_NX_COMPAT, module_object, "NX_COMPAT"); set_integer( - IMAGE_DLLCHARACTERISTICS_NO_ISOLATION, module_object, "NO_ISOLATION"); - set_integer(IMAGE_DLLCHARACTERISTICS_NO_SEH, module_object, "NO_SEH"); - set_integer(IMAGE_DLLCHARACTERISTICS_NO_BIND, module_object, "NO_BIND"); + IMAGE_DLLCHARACTERISTICS_NX_COMPAT, module_object, + "NX_COMPAT"); + set_integer( + IMAGE_DLLCHARACTERISTICS_NO_ISOLATION, module_object, + "NO_ISOLATION"); + set_integer( + IMAGE_DLLCHARACTERISTICS_NO_SEH, module_object, + "NO_SEH"); + set_integer( + IMAGE_DLLCHARACTERISTICS_NO_BIND, module_object, + "NO_BIND"); set_integer( - IMAGE_DLLCHARACTERISTICS_APPCONTAINER, module_object, "APPCONTAINER"); - set_integer(IMAGE_DLLCHARACTERISTICS_WDM_DRIVER, module_object, "WDM_DRIVER"); - set_integer(IMAGE_DLLCHARACTERISTICS_GUARD_CF, module_object, "GUARD_CF"); + IMAGE_DLLCHARACTERISTICS_WDM_DRIVER, module_object, + "WDM_DRIVER"); set_integer( - IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE, - module_object, + IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE, module_object, "TERMINAL_SERVER_AWARE"); - set_integer(IMAGE_FILE_RELOCS_STRIPPED, module_object, "RELOCS_STRIPPED"); - set_integer(IMAGE_FILE_EXECUTABLE_IMAGE, module_object, "EXECUTABLE_IMAGE"); set_integer( - IMAGE_FILE_LINE_NUMS_STRIPPED, module_object, "LINE_NUMS_STRIPPED"); + IMAGE_FILE_RELOCS_STRIPPED, module_object, + "RELOCS_STRIPPED"); set_integer( - IMAGE_FILE_LOCAL_SYMS_STRIPPED, module_object, "LOCAL_SYMS_STRIPPED"); - set_integer(IMAGE_FILE_AGGRESIVE_WS_TRIM, module_object, "AGGRESIVE_WS_TRIM"); + IMAGE_FILE_EXECUTABLE_IMAGE, module_object, + "EXECUTABLE_IMAGE"); set_integer( - IMAGE_FILE_LARGE_ADDRESS_AWARE, module_object, "LARGE_ADDRESS_AWARE"); - set_integer(IMAGE_FILE_BYTES_REVERSED_LO, module_object, "BYTES_REVERSED_LO"); - set_integer(IMAGE_FILE_32BIT_MACHINE, module_object, "MACHINE_32BIT"); - set_integer(IMAGE_FILE_DEBUG_STRIPPED, module_object, "DEBUG_STRIPPED"); + IMAGE_FILE_LINE_NUMS_STRIPPED, module_object, + "LINE_NUMS_STRIPPED"); set_integer( - IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP, - module_object, + IMAGE_FILE_LOCAL_SYMS_STRIPPED, module_object, + "LOCAL_SYMS_STRIPPED"); + set_integer( + IMAGE_FILE_AGGRESIVE_WS_TRIM, module_object, + "AGGRESIVE_WS_TRIM"); + set_integer( + IMAGE_FILE_LARGE_ADDRESS_AWARE, module_object, + "LARGE_ADDRESS_AWARE"); + set_integer( + IMAGE_FILE_BYTES_REVERSED_LO, module_object, + "BYTES_REVERSED_LO"); + set_integer( + IMAGE_FILE_32BIT_MACHINE, module_object, + "MACHINE_32BIT"); + set_integer( + IMAGE_FILE_DEBUG_STRIPPED, module_object, + "DEBUG_STRIPPED"); + set_integer( + IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP, module_object, "REMOVABLE_RUN_FROM_SWAP"); - set_integer(IMAGE_FILE_NET_RUN_FROM_SWAP, module_object, "NET_RUN_FROM_SWAP"); - set_integer(IMAGE_FILE_SYSTEM, module_object, "SYSTEM"); - set_integer(IMAGE_FILE_DLL, module_object, "DLL"); - set_integer(IMAGE_FILE_UP_SYSTEM_ONLY, module_object, "UP_SYSTEM_ONLY"); - set_integer(IMAGE_FILE_BYTES_REVERSED_HI, module_object, "BYTES_REVERSED_HI"); + set_integer( + IMAGE_FILE_NET_RUN_FROM_SWAP, module_object, + "NET_RUN_FROM_SWAP"); + set_integer( + IMAGE_FILE_SYSTEM, module_object, + "SYSTEM"); + set_integer( + IMAGE_FILE_DLL, module_object, + "DLL"); + set_integer( + IMAGE_FILE_UP_SYSTEM_ONLY, module_object, + "UP_SYSTEM_ONLY"); + set_integer( + IMAGE_FILE_BYTES_REVERSED_HI, module_object, + "BYTES_REVERSED_HI"); set_integer( - IMAGE_DIRECTORY_ENTRY_EXPORT, - module_object, + IMAGE_DIRECTORY_ENTRY_EXPORT, module_object, "IMAGE_DIRECTORY_ENTRY_EXPORT"); set_integer( - IMAGE_DIRECTORY_ENTRY_IMPORT, - module_object, + IMAGE_DIRECTORY_ENTRY_IMPORT, module_object, "IMAGE_DIRECTORY_ENTRY_IMPORT"); set_integer( - IMAGE_DIRECTORY_ENTRY_RESOURCE, - module_object, + IMAGE_DIRECTORY_ENTRY_RESOURCE, module_object, "IMAGE_DIRECTORY_ENTRY_RESOURCE"); set_integer( - IMAGE_DIRECTORY_ENTRY_EXCEPTION, - module_object, + IMAGE_DIRECTORY_ENTRY_EXCEPTION, module_object, "IMAGE_DIRECTORY_ENTRY_EXCEPTION"); set_integer( - IMAGE_DIRECTORY_ENTRY_SECURITY, - module_object, + IMAGE_DIRECTORY_ENTRY_SECURITY, module_object, "IMAGE_DIRECTORY_ENTRY_SECURITY"); set_integer( - IMAGE_DIRECTORY_ENTRY_BASERELOC, - module_object, + IMAGE_DIRECTORY_ENTRY_BASERELOC, module_object, "IMAGE_DIRECTORY_ENTRY_BASERELOC"); set_integer( - IMAGE_DIRECTORY_ENTRY_DEBUG, - module_object, + IMAGE_DIRECTORY_ENTRY_DEBUG, module_object, "IMAGE_DIRECTORY_ENTRY_DEBUG"); set_integer( - IMAGE_DIRECTORY_ENTRY_ARCHITECTURE, - module_object, + IMAGE_DIRECTORY_ENTRY_ARCHITECTURE, module_object, "IMAGE_DIRECTORY_ENTRY_ARCHITECTURE"); set_integer( - IMAGE_DIRECTORY_ENTRY_COPYRIGHT, - module_object, - "IMAGE_DIRECTORY_ENTRY_COPYRIGHT"); - set_integer( - IMAGE_DIRECTORY_ENTRY_GLOBALPTR, - module_object, + IMAGE_DIRECTORY_ENTRY_GLOBALPTR, module_object, "IMAGE_DIRECTORY_ENTRY_GLOBALPTR"); set_integer( - IMAGE_DIRECTORY_ENTRY_TLS, module_object, "IMAGE_DIRECTORY_ENTRY_TLS"); + IMAGE_DIRECTORY_ENTRY_TLS, module_object, + "IMAGE_DIRECTORY_ENTRY_TLS"); set_integer( - IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG, - module_object, + IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG, module_object, "IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG"); set_integer( - IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT, - module_object, + IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT, module_object, "IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT"); set_integer( - IMAGE_DIRECTORY_ENTRY_IAT, module_object, "IMAGE_DIRECTORY_ENTRY_IAT"); + IMAGE_DIRECTORY_ENTRY_IAT, module_object, + "IMAGE_DIRECTORY_ENTRY_IAT"); set_integer( - IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT, - module_object, + IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT, module_object, "IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT"); set_integer( - IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR, - module_object, + IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR, module_object, "IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR"); set_integer( - IMAGE_NT_OPTIONAL_HDR32_MAGIC, - module_object, - "IMAGE_NT_OPTIONAL_HDR32_MAGIC"); + IMAGE_SCN_CNT_CODE, module_object, + "SECTION_CNT_CODE"); set_integer( - IMAGE_NT_OPTIONAL_HDR64_MAGIC, - module_object, - "IMAGE_NT_OPTIONAL_HDR64_MAGIC"); - set_integer( - IMAGE_ROM_OPTIONAL_HDR_MAGIC, - module_object, - "IMAGE_ROM_OPTIONAL_HDR_MAGIC"); - - set_integer(IMAGE_SCN_TYPE_NO_PAD, module_object, "SECTION_NO_PAD"); - set_integer(IMAGE_SCN_CNT_CODE, module_object, "SECTION_CNT_CODE"); - set_integer( - IMAGE_SCN_CNT_INITIALIZED_DATA, - module_object, + IMAGE_SCN_CNT_INITIALIZED_DATA, module_object, "SECTION_CNT_INITIALIZED_DATA"); set_integer( - IMAGE_SCN_CNT_UNINITIALIZED_DATA, - module_object, + IMAGE_SCN_CNT_UNINITIALIZED_DATA, module_object, "SECTION_CNT_UNINITIALIZED_DATA"); - set_integer(IMAGE_SCN_LNK_OTHER, module_object, "SECTION_LNK_OTHER"); - set_integer(IMAGE_SCN_LNK_INFO, module_object, "SECTION_LNK_INFO"); - set_integer(IMAGE_SCN_LNK_REMOVE, module_object, "SECTION_LNK_REMOVE"); - set_integer(IMAGE_SCN_LNK_COMDAT, module_object, "SECTION_LNK_COMDAT"); - set_integer( - IMAGE_SCN_NO_DEFER_SPEC_EXC, module_object, "SECTION_NO_DEFER_SPEC_EXC"); - set_integer(IMAGE_SCN_GPREL, module_object, "SECTION_GPREL"); - set_integer(IMAGE_SCN_MEM_FARDATA, module_object, "SECTION_MEM_FARDATA"); - set_integer(IMAGE_SCN_MEM_PURGEABLE, module_object, "SECTION_MEM_PURGEABLE"); - set_integer(IMAGE_SCN_MEM_16BIT, module_object, "SECTION_MEM_16BIT"); - set_integer(IMAGE_SCN_MEM_LOCKED, module_object, "SECTION_MEM_LOCKED"); - set_integer(IMAGE_SCN_MEM_PRELOAD, module_object, "SECTION_MEM_PRELOAD"); - set_integer(IMAGE_SCN_ALIGN_1BYTES, module_object, "SECTION_ALIGN_1BYTES"); - set_integer(IMAGE_SCN_ALIGN_2BYTES, module_object, "SECTION_ALIGN_2BYTES"); - set_integer(IMAGE_SCN_ALIGN_4BYTES, module_object, "SECTION_ALIGN_4BYTES"); - set_integer(IMAGE_SCN_ALIGN_8BYTES, module_object, "SECTION_ALIGN_8BYTES"); - set_integer(IMAGE_SCN_ALIGN_16BYTES, module_object, "SECTION_ALIGN_16BYTES"); - set_integer(IMAGE_SCN_ALIGN_32BYTES, module_object, "SECTION_ALIGN_32BYTES"); - set_integer(IMAGE_SCN_ALIGN_64BYTES, module_object, "SECTION_ALIGN_64BYTES"); set_integer( - IMAGE_SCN_ALIGN_128BYTES, module_object, "SECTION_ALIGN_128BYTES"); + IMAGE_SCN_GPREL, module_object, + "SECTION_GPREL"); set_integer( - IMAGE_SCN_ALIGN_256BYTES, module_object, "SECTION_ALIGN_256BYTES"); + IMAGE_SCN_MEM_16BIT, module_object, + "SECTION_MEM_16BIT"); set_integer( - IMAGE_SCN_ALIGN_512BYTES, module_object, "SECTION_ALIGN_512BYTES"); + IMAGE_SCN_LNK_NRELOC_OVFL, module_object, + "SECTION_LNK_NRELOC_OVFL"); set_integer( - IMAGE_SCN_ALIGN_1024BYTES, module_object, "SECTION_ALIGN_1024BYTES"); + IMAGE_SCN_MEM_DISCARDABLE, module_object, + "SECTION_MEM_DISCARDABLE"); set_integer( - IMAGE_SCN_ALIGN_2048BYTES, module_object, "SECTION_ALIGN_2048BYTES"); + IMAGE_SCN_MEM_NOT_CACHED, module_object, + "SECTION_MEM_NOT_CACHED"); set_integer( - IMAGE_SCN_ALIGN_4096BYTES, module_object, "SECTION_ALIGN_4096BYTES"); + IMAGE_SCN_MEM_NOT_PAGED, module_object, + "SECTION_MEM_NOT_PAGED"); set_integer( - IMAGE_SCN_ALIGN_8192BYTES, module_object, "SECTION_ALIGN_8192BYTES"); - set_integer(IMAGE_SCN_ALIGN_MASK, module_object, "SECTION_ALIGN_MASK"); + IMAGE_SCN_MEM_SHARED, module_object, + "SECTION_MEM_SHARED"); set_integer( - IMAGE_SCN_LNK_NRELOC_OVFL, module_object, "SECTION_LNK_NRELOC_OVFL"); + IMAGE_SCN_MEM_EXECUTE, module_object, + "SECTION_MEM_EXECUTE"); set_integer( - IMAGE_SCN_MEM_DISCARDABLE, module_object, "SECTION_MEM_DISCARDABLE"); + IMAGE_SCN_MEM_READ, module_object, + "SECTION_MEM_READ"); set_integer( - IMAGE_SCN_MEM_NOT_CACHED, module_object, "SECTION_MEM_NOT_CACHED"); - set_integer(IMAGE_SCN_MEM_NOT_PAGED, module_object, "SECTION_MEM_NOT_PAGED"); - set_integer(IMAGE_SCN_MEM_SHARED, module_object, "SECTION_MEM_SHARED"); - set_integer(IMAGE_SCN_MEM_EXECUTE, module_object, "SECTION_MEM_EXECUTE"); - set_integer(IMAGE_SCN_MEM_READ, module_object, "SECTION_MEM_READ"); - set_integer(IMAGE_SCN_MEM_WRITE, module_object, "SECTION_MEM_WRITE"); - set_integer(IMAGE_SCN_SCALE_INDEX, module_object, "SECTION_SCALE_INDEX"); + IMAGE_SCN_MEM_WRITE, module_object, + "SECTION_MEM_WRITE"); - set_integer(RESOURCE_TYPE_CURSOR, module_object, "RESOURCE_TYPE_CURSOR"); - set_integer(RESOURCE_TYPE_BITMAP, module_object, "RESOURCE_TYPE_BITMAP"); - set_integer(RESOURCE_TYPE_ICON, module_object, "RESOURCE_TYPE_ICON"); - set_integer(RESOURCE_TYPE_MENU, module_object, "RESOURCE_TYPE_MENU"); - set_integer(RESOURCE_TYPE_DIALOG, module_object, "RESOURCE_TYPE_DIALOG"); - set_integer(RESOURCE_TYPE_STRING, module_object, "RESOURCE_TYPE_STRING"); - set_integer(RESOURCE_TYPE_FONTDIR, module_object, "RESOURCE_TYPE_FONTDIR"); - set_integer(RESOURCE_TYPE_FONT, module_object, "RESOURCE_TYPE_FONT"); set_integer( - RESOURCE_TYPE_ACCELERATOR, module_object, "RESOURCE_TYPE_ACCELERATOR"); - set_integer(RESOURCE_TYPE_RCDATA, module_object, "RESOURCE_TYPE_RCDATA"); + RESOURCE_TYPE_CURSOR, module_object, + "RESOURCE_TYPE_CURSOR"); set_integer( - RESOURCE_TYPE_MESSAGETABLE, module_object, "RESOURCE_TYPE_MESSAGETABLE"); + RESOURCE_TYPE_BITMAP, module_object, + "RESOURCE_TYPE_BITMAP"); set_integer( - RESOURCE_TYPE_GROUP_CURSOR, module_object, "RESOURCE_TYPE_GROUP_CURSOR"); + RESOURCE_TYPE_ICON, module_object, + "RESOURCE_TYPE_ICON"); set_integer( - RESOURCE_TYPE_GROUP_ICON, module_object, "RESOURCE_TYPE_GROUP_ICON"); - set_integer(RESOURCE_TYPE_VERSION, module_object, "RESOURCE_TYPE_VERSION"); + RESOURCE_TYPE_MENU, module_object, + "RESOURCE_TYPE_MENU"); set_integer( - RESOURCE_TYPE_DLGINCLUDE, module_object, "RESOURCE_TYPE_DLGINCLUDE"); - set_integer(RESOURCE_TYPE_PLUGPLAY, module_object, "RESOURCE_TYPE_PLUGPLAY"); - set_integer(RESOURCE_TYPE_VXD, module_object, "RESOURCE_TYPE_VXD"); + RESOURCE_TYPE_DIALOG, module_object, + "RESOURCE_TYPE_DIALOG"); set_integer( - RESOURCE_TYPE_ANICURSOR, module_object, "RESOURCE_TYPE_ANICURSOR"); - set_integer(RESOURCE_TYPE_ANIICON, module_object, "RESOURCE_TYPE_ANIICON"); - set_integer(RESOURCE_TYPE_HTML, module_object, "RESOURCE_TYPE_HTML"); - set_integer(RESOURCE_TYPE_MANIFEST, module_object, "RESOURCE_TYPE_MANIFEST"); - + RESOURCE_TYPE_STRING, module_object, + "RESOURCE_TYPE_STRING"); set_integer( - IMAGE_DEBUG_TYPE_UNKNOWN, module_object, "IMAGE_DEBUG_TYPE_UNKNOWN"); - set_integer(IMAGE_DEBUG_TYPE_COFF, module_object, "IMAGE_DEBUG_TYPE_COFF"); + RESOURCE_TYPE_FONTDIR, module_object, + "RESOURCE_TYPE_FONTDIR"); set_integer( - IMAGE_DEBUG_TYPE_CODEVIEW, module_object, "IMAGE_DEBUG_TYPE_CODEVIEW"); - set_integer(IMAGE_DEBUG_TYPE_FPO, module_object, "IMAGE_DEBUG_TYPE_FPO"); - set_integer(IMAGE_DEBUG_TYPE_MISC, module_object, "IMAGE_DEBUG_TYPE_MISC"); + RESOURCE_TYPE_FONT, module_object, + "RESOURCE_TYPE_FONT"); set_integer( - IMAGE_DEBUG_TYPE_EXCEPTION, module_object, "IMAGE_DEBUG_TYPE_EXCEPTION"); - set_integer(IMAGE_DEBUG_TYPE_FIXUP, module_object, "IMAGE_DEBUG_TYPE_FIXUP"); + RESOURCE_TYPE_ACCELERATOR, module_object, + "RESOURCE_TYPE_ACCELERATOR"); set_integer( - IMAGE_DEBUG_TYPE_OMAP_TO_SRC, - module_object, - "IMAGE_DEBUG_TYPE_OMAP_TO_SRC"); + RESOURCE_TYPE_RCDATA, module_object, + "RESOURCE_TYPE_RCDATA"); set_integer( - IMAGE_DEBUG_TYPE_OMAP_FROM_SRC, - module_object, - "IMAGE_DEBUG_TYPE_OMAP_FROM_SRC"); + RESOURCE_TYPE_MESSAGETABLE, module_object, + "RESOURCE_TYPE_MESSAGETABLE"); set_integer( - IMAGE_DEBUG_TYPE_BORLAND, module_object, "IMAGE_DEBUG_TYPE_BORLAND"); + RESOURCE_TYPE_GROUP_CURSOR, module_object, + "RESOURCE_TYPE_GROUP_CURSOR"); set_integer( - IMAGE_DEBUG_TYPE_RESERVED10, - module_object, - "IMAGE_DEBUG_TYPE_RESERVED10"); - set_integer(IMAGE_DEBUG_TYPE_CLSID, module_object, "IMAGE_DEBUG_TYPE_CLSID"); + RESOURCE_TYPE_GROUP_ICON, module_object, + "RESOURCE_TYPE_GROUP_ICON"); set_integer( - IMAGE_DEBUG_TYPE_VC_FEATURE, - module_object, - "IMAGE_DEBUG_TYPE_VC_FEATURE"); - set_integer(IMAGE_DEBUG_TYPE_POGO, module_object, "IMAGE_DEBUG_TYPE_POGO"); - set_integer(IMAGE_DEBUG_TYPE_ILTCG, module_object, "IMAGE_DEBUG_TYPE_ILTCG"); - set_integer(IMAGE_DEBUG_TYPE_MPX, module_object, "IMAGE_DEBUG_TYPE_MPX"); - set_integer(IMAGE_DEBUG_TYPE_REPRO, module_object, "IMAGE_DEBUG_TYPE_REPRO"); - + RESOURCE_TYPE_VERSION, module_object, + "RESOURCE_TYPE_VERSION"); + set_integer( + RESOURCE_TYPE_DLGINCLUDE, module_object, + "RESOURCE_TYPE_DLGINCLUDE"); + set_integer( + RESOURCE_TYPE_PLUGPLAY, module_object, + "RESOURCE_TYPE_PLUGPLAY"); + set_integer( + RESOURCE_TYPE_VXD, module_object, + "RESOURCE_TYPE_VXD"); + set_integer( + RESOURCE_TYPE_ANICURSOR, module_object, + "RESOURCE_TYPE_ANICURSOR"); + set_integer( + RESOURCE_TYPE_ANIICON, module_object, + "RESOURCE_TYPE_ANIICON"); + set_integer( + RESOURCE_TYPE_HTML, module_object, + "RESOURCE_TYPE_HTML"); + set_integer( + RESOURCE_TYPE_MANIFEST, module_object, + "RESOURCE_TYPE_MANIFEST"); set_integer(0, module_object, "is_pe"); foreach_memory_block(iterator, block) @@ -3948,27 +3364,26 @@ int module_load( return ERROR_INSUFFICIENT_MEMORY; FAIL_ON_ERROR_WITH_CLEANUP( - yr_hash_table_create(17, &pe->hash_table), yr_free(pe)); + yr_hash_table_create(17, &pe->hash_table), + yr_free(pe)); pe->data = block_data; pe->data_size = block->size; pe->header = pe_header; pe->object = module_object; pe->resources = 0; - pe->version_infos = 0; module_object->data = pe; pe_parse_header(pe, block->base, context->flags); pe_parse_rich_signature(pe, block->base); pe_parse_debug_directory(pe); - -#if defined(HAVE_LIBCRYPTO) && !defined(BORINGSSL) + + #if defined(HAVE_LIBCRYPTO) && !defined(BORINGSSL) pe_parse_certificates(pe); -#endif + #endif pe->imported_dlls = pe_parse_imports(pe); - pe->delay_imported_dlls = pe_parse_delayed_imports(pe); pe_parse_exports(pe); break; @@ -3979,12 +3394,27 @@ int module_load( return ERROR_SUCCESS; } -void free_dlls(IMPORTED_DLL* dll) + +int module_unload( + YR_OBJECT* module_object) { + IMPORTED_DLL* dll = NULL; IMPORTED_DLL* next_dll = NULL; IMPORT_FUNCTION* func = NULL; IMPORT_FUNCTION* next_func = NULL; + PE* pe = (PE *) module_object->data; + + if (pe == NULL) + return ERROR_SUCCESS; + + if (pe->hash_table != NULL) + yr_hash_table_destroy( + pe->hash_table, + (YR_HASH_TABLE_FREE_VALUE_FUNC) yr_free); + + dll = pe->imported_dlls; + while (dll) { if (dll->name) @@ -4006,21 +3436,6 @@ void free_dlls(IMPORTED_DLL* dll) yr_free(dll); dll = next_dll; } -} - -int module_unload(YR_OBJECT* module_object) -{ - PE* pe = (PE*) module_object->data; - - if (pe == NULL) - return ERROR_SUCCESS; - - if (pe->hash_table != NULL) - yr_hash_table_destroy( - pe->hash_table, (YR_HASH_TABLE_FREE_VALUE_FUNC) yr_free); - - free_dlls(pe->imported_dlls); - free_dlls(pe->delay_imported_dlls); yr_free(pe); diff --git a/tests/test-pe.c b/tests/test-pe.c index fe00ae9b3a..b9b0280d22 100644 --- a/tests/test-pe.c +++ b/tests/test-pe.c @@ -1,18 +1,14 @@ +#include #include #include #include -#include - #include "util.h" int main(int argc, char** argv) { - int result = 0; - - YR_DEBUG_INITIALIZE(); - YR_DEBUG_FPRINTF(1, stderr, "+ %s() { // in %s\n", __FUNCTION__, argv[0]); - - init_top_srcdir(); + char *top_srcdir = getenv("TOP_SRCDIR"); + if (top_srcdir) + chdir(top_srcdir); yr_initialize(); @@ -72,190 +68,14 @@ int main(int argc, char** argv) }", "tests/data/tiny-idata-5200"); - /////////////////////////////// - - assert_true_rule_file( - "import \"pe\" \ - rule test { \ - condition: \ - pe.imports(pe.IMPORT_STANDARD, \"KERNEL32.dll\", \"DeleteCriticalSection\") \ - }", - "tests/data/tiny"); - - assert_true_rule_file( - "import \"pe\" \ - rule test { \ - condition: \ - pe.imports(pe.IMPORT_STANDARD, \"KERNEL32.dll\", \"DeleteCriticalSection\") \ - }", - "tests/data/tiny-idata-51ff"); - - assert_false_rule_file( - "import \"pe\" \ - rule test { \ - condition: \ - pe.imports(pe.IMPORT_STANDARD, \"KERNEL32.dll\", \"DeleteCriticalSection\") \ - }", - "tests/data/tiny-idata-5200"); - - assert_true_rule_file( - "import \"pe\" \ - rule test { \ - condition: \ - pe.imports(pe.IMPORT_STANDARD, /.*/, /.*CriticalSection/) == 4 \ - }", - "tests/data/tiny"); - - assert_true_rule_file( - "import \"pe\" \ - rule test { \ - condition: \ - pe.imports(pe.IMPORT_STANDARD, /kernel32\\.dll/i, /.*/) == 21 \ - }", - "tests/data/tiny"); - - assert_true_rule_file( - "import \"pe\" \ - rule test { \ - condition: \ - pe.imports(pe.IMPORT_STANDARD, /.*/, /.*/) \ - }", - "tests/data/tiny-idata-5200"); - - assert_false_rule_file( - "import \"pe\" \ - rule test { \ - condition: \ - pe.imports(pe.IMPORT_STANDARD, /.*/, /.*CriticalSection/) \ - }", - "tests/data/tiny-idata-5200"); - - - assert_true_rule_file( - "import \"pe\" \ - rule test { \ - condition: \ - pe.number_of_imports == 2 and\ - pe.number_of_imported_functions == 48\ - }", - "tests/data/tiny"); - - assert_true_rule_file( - "import \"pe\" \ - rule test { \ - condition: \ - pe.imports(pe.IMPORT_DELAYED, \"USER32.dll\", \"MessageBoxA\") \ - }", - "tests/data/pe_imports"); - - assert_false_rule_file( - "import \"pe\" \ - rule test { \ - condition: \ - pe.imports(pe.IMPORT_DELAYED, \"KERNEL32.dll\", \"DeleteCriticalSection\") \ - }", - "tests/data/pe_imports"); - - assert_true_rule_file( - "import \"pe\" \ - rule test { \ - condition: \ - pe.imports(pe.IMPORT_DELAYED, /.*/, /Message.*/) == 2 \ - }", - "tests/data/pe_imports"); - - assert_true_rule_file( - "import \"pe\" \ - rule test { \ - condition: \ - pe.imports(pe.IMPORT_DELAYED, /USER32\\.dll/i, /.*BoxA/) == 1 \ - }", - "tests/data/pe_imports"); - - assert_false_rule_file( - "import \"pe\" \ - rule test { \ - condition: \ - pe.imports(pe.IMPORT_DELAYED, /.*/, /.*CriticalSection/) \ - }", - "tests/data/pe_imports"); - - assert_true_rule_file( - "import \"pe\" \ - rule test { \ - condition: \ - pe.number_of_delayed_imports == 1 and\ - pe.number_of_delayed_imported_functions == 2\ - }", - "tests/data/pe_imports"); - - assert_true_rule_file( - "import \"pe\" \ - rule test { \ - condition: \ - pe.imports(pe.IMPORT_ANY, \"KERNEL32.dll\", \"DeleteCriticalSection\") and \ - pe.imports(pe.IMPORT_ANY, \"USER32.dll\", \"MessageBoxA\") \ - }", - "tests/data/pe_imports"); - - assert_true_rule_file( - "import \"pe\" \ - rule test { \ - condition: \ - pe.imports(pe.IMPORT_ANY, \"KERNEL32.dll\", \"DeleteCriticalSection\") \ - }", - "tests/data/tiny-idata-51ff"); - - assert_false_rule_file( - "import \"pe\" \ - rule test { \ - condition: \ - pe.imports(pe.IMPORT_ANY, \"KERNEL32.dll\", \"DeleteCriticalSection\") \ - }", - "tests/data/tiny-idata-5200"); - assert_true_rule_file( "import \"pe\" \ rule test { \ condition: \ - pe.imports(pe.IMPORT_ANY, /.*/, /.*CriticalSection/) == 4 \ + pe.number_of_imports == 2 \ }", "tests/data/tiny"); - assert_true_rule_file( - "import \"pe\" \ - rule test { \ - condition: \ - pe.imports(pe.IMPORT_ANY, /kernel32\\.dll/i, /.*/) == 21 \ - }", - "tests/data/tiny"); - - assert_true_rule_file( - "import \"pe\" \ - rule test { \ - condition: \ - pe.imports(pe.IMPORT_ANY, /.*/, /.*/) \ - }", - "tests/data/tiny-idata-5200"); - - assert_false_rule_file( - "import \"pe\" \ - rule test { \ - condition: \ - pe.imports(pe.IMPORT_ANY, /.*/, /.*CriticalSection/) \ - }", - "tests/data/tiny-idata-5200"); - - assert_true_rule( - "import \"pe\" \ - rule test { \ - condition: \ - ( \ - pe.IMPORT_ANY & (pe.IMPORT_STANDARD | pe.IMPORT_DELAYED) \ - ) == (pe.IMPORT_STANDARD | pe.IMPORT_DELAYED)\ - }", - "") - assert_true_rule_file( "import \"pe\" \ rule test { \ @@ -272,14 +92,6 @@ int main(int argc, char** argv) }", "tests/data/tiny"); - assert_true_rule_file( - "import \"pe\" \ - rule test { \ - condition: \ - pe.entry_point_raw == 0x1380 \ - }", - "tests/data/mtxex.dll"); - assert_true_rule_file( "import \"pe\" \ rule test { \ @@ -303,8 +115,9 @@ int main(int argc, char** argv) }", "tests/data/tiny"); -#if defined(HAVE_LIBCRYPTO) || defined(HAVE_WINCRYPT_H) || \ - defined(HAVE_COMMONCRYPTO_COMMONCRYPTO_H) + #if defined(HAVE_LIBCRYPTO) || \ + defined(HAVE_WINCRYPT_H) || \ + defined(HAVE_COMMONCRYPTO_COMMONCRYPTO_H) assert_true_rule_file( "import \"pe\" \ @@ -314,9 +127,9 @@ int main(int argc, char** argv) }", "tests/data/tiny"); -#endif + #endif -#if defined(HAVE_LIBCRYPTO) + #if defined(HAVE_LIBCRYPTO) assert_true_rule_file( "import \"pe\" \ @@ -326,19 +139,9 @@ int main(int argc, char** argv) pe.signatures[0].thumbprint == \"c1bf1b8f751bf97626ed77f755f0a393106f2454\" and \ pe.signatures[0].subject == \"/C=US/ST=California/L=Menlo Park/O=Quicken, Inc./OU=Operations/CN=Quicken, Inc.\" \ }", - "tests/data/" - "079a472d22290a94ebb212aa8015cdc8dd28a968c6b4d3b88acdd58ce2d3b885"); - - assert_true_rule_file( - "import \"pe\" \ - rule test { \ - condition: \ - pe.number_of_signatures == 2 \ - }", - "tests/data/" - "3b8b90159fa9b6048cc5410c5d53f116943564e4d05b04a843f9b3d0540d0c1c"); + "tests/data/079a472d22290a94ebb212aa8015cdc8dd28a968c6b4d3b88acdd58ce2d3b885"); -#endif + #endif assert_true_rule_file( "import \"pe\" \ @@ -392,7 +195,7 @@ int main(int argc, char** argv) "import \"pe\" \ rule test { \ condition: \ - pe.overlay.offset == 0 and pe.overlay.size == 0 \ + pe.overlay.size == 0 \ }", "tests/data/tiny"); @@ -402,8 +205,7 @@ int main(int argc, char** argv) condition: \ pe.pdb_path == \"D:\\\\workspace\\\\2018_R9_RelBld\\\\target\\\\checkout\\\\custprof\\\\Release\\\\custprof.pdb\" \ }", - "tests/data/" - "079a472d22290a94ebb212aa8015cdc8dd28a968c6b4d3b88acdd58ce2d3b885"); + "tests/data/079a472d22290a94ebb212aa8015cdc8dd28a968c6b4d3b88acdd58ce2d3b885"); assert_false_rule_file( "import \"pe\" \ @@ -414,27 +216,29 @@ int main(int argc, char** argv) "tests/data/tiny-idata-51ff"); /* - * mtxex.dll is - * 23e72ce7e9cdbc80c0095484ebeb02f56b21e48fd67044e69e7a2ae76db631e5, which was - * taken from a Windows 10 install. The details of which are: export_timestamp - * = 1827812126 dll_name = "mtxex.dll" number_of_exports = 4 export_details + * mtxex.dll is 23e72ce7e9cdbc80c0095484ebeb02f56b21e48fd67044e69e7a2ae76db631e5, + * which was taken from a Windows 10 install. The details of which are: + * export_timestamp = 1827812126 + * dll_name = "mtxex.dll" + * number_of_exports = 4 + * export_details * [0] * offset = 1072 * name = "DllGetClassObject" - * forward_name = YR_UNDEFINED + * forward_name = UNDEFINED * ordinal = 1 * [1] - * offset = YR_UNDEFINED + * offset = UNDEFINED * name = "GetObjectContext" * forward_name = "COMSVCS.GetObjectContext" * ordinal = 2 * [2] - * offset = YR_UNDEFINED + * offset = UNDEFINED * name = "MTSCreateActivity" * forward_name = "COMSVCS.MTSCreateActivity" * ordinal = 3 * [3] - * offset = YR_UNDEFINED + * offset = UNDEFINED * name = "SafeRef" * forward_name = "COMSVCS.SafeRef" * ordinal = 4 @@ -452,22 +256,6 @@ int main(int argc, char** argv) pe.export_details[1].forward_name == \"COMSVCS.GetObjectContext\" \ }", "tests/data/mtxex.dll"); - /* - * mtxex_modified_rsrc_rva.dll is a modified copy of mtxex.dll from a Windows - * 10 install. The modification was to change the RVA of the only resource to - * be invalid (it was changed to be 0x41585300), to ensure we are still - * parsing resources even if the RVA does not have a corresponding file - * offset. - */ - assert_true_rule_file( - "import \"pe\" \ - rule test { \ - condition: \ - pe.number_of_resources == 1 and \ - pe.resources[0].rva == 5462081 and \ - pe.resources[0].length == 888 \ - }", - "tests/data/mtxex_modified_rsrc_rva.dll"); // Make sure exports function is case insensitive (historically this has been // the case) and supports ordinals... @@ -495,10 +283,17 @@ int main(int argc, char** argv) "import \"pe\" \ rule test { \ condition: \ - pe.export_details[0].name == \"CP_PutItem\" \ + pe.is_reproducible_build == 1 \ + }", + "tests/data/mtxex.dll"); + + assert_true_rule_file( + "import \"pe\" \ + rule test { \ + condition: \ + pe.is_reproducible_build == 0 \ }", - "tests/data/" - "079a472d22290a94ebb212aa8015cdc8dd28a968c6b4d3b88acdd58ce2d3b885.upx"); + "tests/data/079a472d22290a94ebb212aa8015cdc8dd28a968c6b4d3b88acdd58ce2d3b885"); assert_true_rule_file( "import \"pe\" \ @@ -509,109 +304,20 @@ int main(int argc, char** argv) pe.rich_signature.version(30319) and \ pe.rich_signature.version(40219, 170) == 11 \ }", - "tests/data/" - "079a472d22290a94ebb212aa8015cdc8dd28a968c6b4d3b88acdd58ce2d3b885"); + "tests/data/079a472d22290a94ebb212aa8015cdc8dd28a968c6b4d3b88acdd58ce2d3b885"); // This is the first 840 bytes (just enough to make sure the rich header is - // parsed) of - // 3593d3d08761d8ddc269dde945c0cb07e5cef5dd46ad9eefc22d17901f542093. + // parsed) of 3593d3d08761d8ddc269dde945c0cb07e5cef5dd46ad9eefc22d17901f542093. assert_true_rule_file( "import \"pe\" \ rule test { \ condition: \ pe.rich_signature.offset == 0x200 and \ pe.rich_signature.length == 64 and \ - pe.rich_signature.key == 0x9f1d8511 and \ pe.rich_signature.clear_data == \"DanS\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x11\\x00\\x00\\x00\\xc3\\x0f]\\x00\\x03\\x00\\x00\\x00\\x09x\\x95\\x00\\x01\\x00\\x00\\x00\\x09x\\x83\\x00\\x05\\x00\\x00\\x00\\x09x\\x94\\x00\\x01\\x00\\x00\\x00\\x09x\\x91\\x00\\x01\\x00\\x00\\x00\" \ }", "tests/data/weird_rich"); - assert_true_rule_file( - "import \"pe\" \ - rule test { \ - condition: \ - pe.language(0x09) and pe.locale(0x0409) \ - }", - "tests/data/mtxex.dll"); - - assert_true_rule_file( - "import \"pe\" \ - rule version_info_catch \ - {\ - condition:\ - pe.number_of_version_infos > 2 and\ - for any version in pe.version_info_list : ( \ - version.key == \"FileVersion\" and \ - version.value == \"27.1.9.33\" \ - ) \ - }", - "tests/data/079a472d22290a94ebb212aa8015cdc8dd28a968c6b4d3b88acdd58ce2d3b885"); - - assert_true_rule_file( - "import \"pe\" \ - rule iequals_comparison { \ - condition: \ - pe.sections[0].name != \".TEXT\" and \ - pe.sections[0].name iequals \".TEXT\" \ - }", - "tests/data/tiny"); - - assert_true_rule_file( - "import \"pe\" \ - \ - rule import_details_catch \ - {\ - condition:\ - for any import_detail in pe.import_details: (\ - import_detail.library_name == \"MSVCR100.dll\" and\ - for any function in import_detail.functions : (\ - function.name == \"_initterm\"\ - )\ - )\ - }", - "tests/data/079a472d22290a94ebb212aa8015cdc8dd28a968c6b4d3b88acdd58ce2d3b885"); - - assert_true_rule_file( - "import \"pe\" \ - \ - rule zero_length_version_info_value \ - {\ - condition:\ - pe.number_of_version_infos == 12 and \ - pe.version_info[\"Comments\"] == \"\" and \ - pe.version_info[\"CompanyName\"] == \"\" and \ - pe.version_info[\"LegalTrademarks\"] == \"\" and \ - pe.version_info[\"PrivateBuild\"] == \"\" and \ - pe.version_info[\"SpecialBuild\"] == \"\" \ - }", - "tests/data/ca21e1c32065352d352be6cde97f89c141d7737ea92434831f998080783d5386"); - - - assert_true_rule_file( - "import \"pe\" \ - rule section_name_comparison { \ - condition: \ - for all section in pe.sections : ( \ - section.name == section.full_name \ - )\ - }", - "tests/data/tiny"); - - assert_true_rule_file( - "import \"pe\" \ - rule section_name_comparison { \ - condition: \ - for any section in pe.sections : ( \ - section.name == \"/4\" and\ - section.full_name == \".debug_aranges\" \ - )\ - }", - "tests/data/pe_mingw"); - yr_finalize(); - - YR_DEBUG_FPRINTF( - 1, stderr, "} = %d // %s() in %s\n", result, __FUNCTION__, argv[0]); - - return result; + return 0; }