PE-Portable-executable
Description
The Portable Executable (PE) format is a file format for executables, object code, DLLs, Font files, and others used in 32-bit and 64-bit versions of Windows operating systems.
For more information, refer to the Microsoft Portable Executable and Common Object File Format Specification.
PE format
MS DOS Header
Offset | Size | Member | Meaning |
---|---|---|---|
0x00 | WORD | emagic | Magic DOS signature MZ (0x4d 0x5A) |
0x02 | WORD | e_cblp | Bytes on last page of file |
0x04 | WORD | e_cp | Pages in file |
0x06 | WORD | e_crlc | Relocations |
0x08 | WORD | e_cparhdr | Size of header in paragraphs |
0x0A | WORD | e_minalloc | Minimum extra paragraphs needed |
0x0C | WORD | e_maxalloc | Maximum extra paragraphs needed |
0x0E | WORD | e_ss | Initial (relative) SS value |
0x10 | WORD | e_sp | Initial SP value |
0x12 | WORD | e_csum | Checksum |
0x14 | WORD | e_ip | Initial IP value |
0x16 | WORD | e_cs | Initial (relative) CS value |
0x18 | WORD | e_lfarlc | File address of relocation table |
0x1A | WORD | e_ovno | Overloay number |
0x1C | WORD | e_res[4] | Reserved words (4 WORDs) |
0x24 | WORD | e_oemid | OEM identifier (for e_oeminfo) |
0x26 | WORD | e_oeminfo | OEM information; e_oemid specific |
0x28 | WORD | e_res2[10] | Reserved words (10 WORDs) |
0x3c | DWORD | e_lfanew | Offset to start of PE header |
PE Header
Offsets shown are from the beginning of this section excepted for the Section Table (offset from the beginning of each section).
Offset | Size | Member | Meaning |
---|---|---|---|
Image File Header (0x00) | |||
0x00 | DWORD | Signature | PE Magic Value |
0x04 | WORD | Machine | For a list of values, see machine types section |
0x06 | WORD | NumberOfSections | Number Of Sections |
0x08 | DWORD | TimeDateStamp | The low 32 bits of the number of seconds since 00:00 January 1, 1970 (a C run-time time_t value), that indicates when the file was created. |
0x0C | DWORD | PointerToSymbolTable | The file offset of the COFF symbol table, or zero if no COFF symbol table is present. This value should be zero for an image because COFF debugging information is deprecated. |
0x10 | DWORD | NumberOfSymbols | The number of entries in the symbol table. This data can be used to locate the string table, which immediately follows the symbol table. This value should be zero for an image because COFF debugging information is deprecated. |
0x14 | WORD | SizeOfOptionalHeader | The size of the optional header, which is required for executable files but not for object files. This value should be zero for an object file. |
0x16 | WORD | Characteristics | The flags that indicate the attributes of the file. For list of values, refer to the Image Characteristics section. |
Optional Header (0x18) | |||
0x18 | WORD | Magic | The unsigned integer that identifies the state of the image file. The most common number is 0x10B, which identifies it as a normal executable file (PE32). 0x107 identifies it as a ROM image, and 0x20B identifies it as a PE32+ executable. |
0x1A | BYTE | MajorLinkerVersion | The linker major version number. |
0x1B | BYTE | MinorLinkerVersion | The linker minor version number. |
0x1C | DWORD | SizeOfCode | The size of the code (text) section, or the sum of all code sections if there are multiple sections. |
0x20 | DWORD | SizeOfInitializedData | The size of the initialized data section, or the sum of all such sections if there are multiple data sections. |
0x24 | DWORD | SizeOfUninitializedData | The size of the uninitialized data section (BSS), or the sum of all such sections if there are multiple BSS sections. |
0x28 | DWORD | AddressOfEntryPoint | The address of the entry point relative to the image base when the executable file is loaded into memory. For program images, this is the starting address. For device drivers, this is the address of the initialization function. An entry point is optional for DLLs. When no entry point is present, this field must be zero. |
0x2C | DWORD | BaseOfCode | The address that is relative to the image base of the beginning-of-code section when it is loaded into memory. |
0x30 | DWORD | BaseOfData | This field does not appear in PE32+. The address that is relative to the image base of the beginning-of-data section when it is loaded into memory. |
0x34 | DWORD | ImageBase | The preferred address of the first byte of image when loaded into memory; must be a multiple of 64 K. The default for DLLs is 0x10000000. The default for Windows CE EXEs is 0x00010000. The default for Windows NT, Windows 2000, Windows XP, Windows 95, Windows 98, and Windows Me is 0x00400000. |
0x38 | DWORD | SectionAlignment | The alignment (in bytes) of sections when they are loaded into memory. It must be greater than or equal to FileAlignment. The default is the page size for the architecture. |
0x3C | DWORD | FileAlignment | The alignment factor (in bytes) that is used to align the raw data of sections in the image file. The value should be a power of 2 between 512 and 64 K, inclusive. The default is 512. If the SectionAlignment is less than the architecture's page size, then FileAlignment must match SectionAlignment. |
0x40 | WORD | MajorOperatingSystemVersion | The major version number of the required operating system. |
0x42 | WORD | MinorOperatingSystemVersion | The minor version number of the required operating system. |
0x44 | WORD | MajorImageVersion | The major version number of the image. |
0x46 | WORD | MinorImageVersion | The minor version number of the image. |
0x48 | WORD | MajorSubsystemVersion | The major version number of the subsystem. |
0x4A | WORD | MinorSubsystemVersion | The minor version number of the subsystem. |
0x4C | DWORD | Win32VersionValue | Reserved, must be zero. |
0x50 | DWORD | SizeOfImage | The size (in bytes) of the image, including all headers, as the image is loaded in memory. It must be a multiple of SectionAlignment. |
0x54 | DWORD | SizeOfHeaders | The combined size of an MS‑DOS stub, PE header, and section headers rounded up to a multiple of FileAlignment. |
0x58 | DWORD | CheckSum | The image file checksum. The algorithm for computing the checksum is incorporated into IMAGHELP.DLL. The following are checked for validation at load time: all drivers, any DLL loaded at boot time, and any DLL that is loaded into a critical Windows process. |
0x5C | WORD | Subsystem | The subsystem that is required to run this image. For list of values, refer to the Windows Subsystem section. |
0x5E | WORD | DllCharacteristics | For list of values, refer to the DLL Characteristics section. |
0x60 | DWORD | SizeOfStackReserve | The size of the stack to reserve. Only SizeOfStackCommit is committed; the rest is made available one page at a time until the reserve size is reached. |
0x64 | DWORD | SizeOfStackCommit | The size of the stack to commit. |
0x68 | DWORD | SizeOfHeapReserve | The size of the local heap space to reserve. Only SizeOfHeapCommit is committed; the rest is made available one page at a time until the reserve size is reached. |
0x6C | DWORD | SizeOfHeapCommit | The size of the local heap space to commit. |
0x70 | DWORD | LoaderFlags | Reserved, must be zero. |
0x74 | DWORD | NumberOfRvaAndSizes |
The number of data-directory entries in the remainder of the optional header. Each describes a location and size. Note
Malware can set an invalid value for this flag to crash the debugger. Read more.
|
Data Directories (0x78) | |||
0x78 | DWORD | Export Table | RVA of Export Directory |
0x7C | DWORD | size of Export Directory | |
0x80 | DWORD | Import Table | RVA of Import Directory (array of IIDs) |
0x84 | DWORD | size of Import Directory (array of IIDs) | |
0x88 | DWORD | Resource Table | RVA of Resource Directory |
0x8C | DWORD | size of Resource Directory | |
0x90 | DWORD | Exception Table | RVA of Exception Directory |
0x94 | DWORD | size of Exception Directory | |
0x98 | DWORD | Certificate Table | Raw Offset of Security Directory |
0x9C | DWORD | size of Security Directory | |
0xA0 | DWORD | Base Relocation Table | RVA of Base Relocation Directory |
0xA4 | DWORD | size of Base Relocation Directory | |
0xA8 | DWORD | Debug | RVA of Debug Directory |
0xAC | DWORD | size of Debug Directory | |
0xB0 | DWORD | Architecture | RVA of Copyright Note |
0xB4 | DWORD | size of Copyright Note | |
0xB8 | DWORD | Global Ptr | RVA to be used as Global Pointer (IA-64 only) |
0xBC | DWORD | Not used | |
0xC0 | DWORD | TLS Table | RVA of Thread Local Storage Directory |
0xC4 | DWORD | size of Thread Local Storage Directory | |
0xC8 | DWORD | Load Config Table | RVA of Load Configuration Directory |
0xCC | DWORD | size of Load Configuration Directory | |
0xD0 | DWORD | Bound Import | RVA of Bound Import Directory |
0xD4 | DWORD | size of Bound Import Directory | |
0xD8 | DWORD | IAT | RVA of first Import Address Table |
0xDC | DWORD | total size of all Import Address Tables | |
0xE0 | DWORD | Delay Import Descriptor | RVA of Delay Import Directory |
0xE4 | DWORD | size of Delay Import Directory | |
0xE8 | DWORD | CLR Runtime Header | RVA of COM Header (top level info & metadata...) |
0xEC | DWORD | size of COM Header (in .NET executables) | |
0xF0 | DWORD | ZERO (Reserved) | Reserved |
0xF4 | DWORD | ZERO (Reserved) | Reserved |
Section Table (0xF8) | |||
0x00 | DWORD | Name | 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. Executable images do not use a string table and do not support section names longer than 8 characters. Long names in object files are truncated if they are emitted to an executable file. |
0x08 | DWORD | VirtualSize | The total size of the section when loaded into memory. If this value is greater than SizeOfRawData, the section is zero-padded. This field is valid only for executable images and should be set to zero for object files. |
0x0C | DWORD | VirtualAddress | For executable images, the address of the first byte of the section relative to the image base when the section is loaded into memory. For object files, this field is the address of the first byte before relocation is applied; for simplicity, compilers should set this to zero. Otherwise, it is an arbitrary value that is subtracted from offsets during relocation. |
0x10 | DWORD | SizeOfRawData |
The size of the section (for object files) or the size of the initialized data on disk (for image files). For executable images, this must be a multiple of FileAlignment from the optional header. If this is less than VirtualSize, the remainder of the section is zero-filled. Because the SizeOfRawData field is rounded but the VirtualSize field is not, it is possible for SizeOfRawData to be greater than VirtualSize as well. When a section contains only uninitialized data, this field should be zero. Note
Malware can set an invalid value for this flag to crash the debugger. Read more.
|
0x14 | DWORD | PointerToRawData | The file pointer to the first page of the section within the COFF file. For executable images, this must be a multiple of FileAlignment from the optional header. For object files, the value should be aligned on a 4‑byte boundary for best performance. When a section contains only uninitialized data, this field should be zero. |
0x18 | DWORD | PointerToRelocations | The file pointer to the beginning of relocation entries for the section. This is set to zero for executable images or if there are no relocations. |
0x1C | DWORD | PointerToLinenumbers | The file pointer to the beginning of line-number entries for the section. This is set to zero if there are no COFF line numbers. This value should be zero for an image because COFF debugging information is deprecated. |
0x20 | WORD | NumberOfRelocations | The number of relocation entries for the section. This is set to zero for executable images. |
0x22 | WORD | NumberOfLineNumbers | The number of line-number entries for the section. This value should be zero for an image because COFF debugging information is deprecated. |
0x24 | DWORD | Characteristics | The flags that describe the characteristics of the section. See values in the Section Characteristics section. |
Repeats for rest of sections | |||
0x00 | 8 Bytes | Name | Name of second section header |
... | ... | ... | ... |
Appendices
Machine Types
Constant | Value | Description |
---|---|---|
IMAGE_FILE_MACHINE_UNKNOWN | 0x0 | The contents of this field are assumed to be applicable to any machine type |
IMAGE_FILE_MACHINE_AM33 | 0x1d3 | Matsushita AM33 |
IMAGE_FILE_MACHINE_AMD64 | 0x8664 | x64 |
IMAGE_FILE_MACHINE_ARM | 0x1c0 | ARM little endian |
IMAGE_FILE_MACHINE_ARMNT | 0x1c4 | ARMv7 (or higher) Thumb mode only |
IMAGE_FILE_MACHINE_ARM64 | 0xaa64 | ARMv8 in 64-bit mode |
IMAGE_FILE_MACHINE_EBC | 0xebc | EFI byte code |
IMAGE_FILE_MACHINE_I386 | 0x14c | Intel 386 or later processors and compatible processors |
IMAGE_FILE_MACHINE_IA64 | 0x200 | Intel Itanium processor family |
IMAGE_FILE_MACHINE_M32R | 0x9041 | Mitsubishi M32R little endian |
IMAGE_FILE_MACHINE_MIPS16 | 0x266 | MIPS16 |
IMAGE_FILE_MACHINE_MIPSFPU | 0x366 | MIPS with FPU |
IMAGE_FILE_MACHINE_MIPSFPU16 | 0x466 | MIPS16 with FPU |
IMAGE_FILE_MACHINE_POWERPC | 0x1f0 | Power PC little endian |
IMAGE_FILE_MACHINE_POWERPCFP | 0x1f1 | Power PC with floating point support |
IMAGE_FILE_MACHINE_R4000 | 0x166 | MIPS little endian |
IMAGE_FILE_MACHINE_SH3 | 0x1a2 | Hitachi SH3 |
IMAGE_FILE_MACHINE_SH3DSP | 0x1a3 | Hitachi SH3 DSP |
IMAGE_FILE_MACHINE_SH4 | 0x1a6 | Hitachi SH4 |
IMAGE_FILE_MACHINE_SH5 | 0x1a8 | Hitachi SH5 |
IMAGE_FILE_MACHINE_THUMB | 0x1c2 | ARM or Thumb (“interworking”) |
IMAGE_FILE_MACHINE_WCEMIPSV2 | 0x169 | MIPS little-endian WCE v2 |
Image Characteristics
The Characteristics field contains flags that indicate attributes of the object or image file. The following flags are currently defined.
Flag | Value | Description |
---|---|---|
IMAGE_FILE_RELOCS_STRIPPED | 0x0001 | Image only, Windows CE, and Windows NT® and later. This indicates that the file does not contain base relocations and must therefore be loaded at its preferred base address. If the base address is not available, the loader reports an error. The default behavior of the linker is to strip base relocations from executable (EXE) files. |
IMAGE_FILE_EXECUTABLE_IMAGE | 0x0002 | Image only. This indicates that the image file is valid and can be run. If this flag is not set, it indicates a linker error. |
IMAGE_FILE_LINE_NUMS_STRIPPED | 0x0004 | COFF line numbers have been removed. This flag is deprecated and should be zero. |
IMAGE_FILE_LOCAL_SYMS_STRIPPED | 0x0008 | COFF symbol table entries for local symbols have been removed. This flag is deprecated and should be zero. |
IMAGE_FILE_AGGRESSIVE_WS_TRIM | 0x0010 | Obsolete. Aggressively trim working set. This flag is deprecated for Windows 2000 and later and must be zero. |
IMAGE_FILE_LARGE_ADDRESS_AWARE | 0x0020 | Application can handle > 2‑GB addresses. |
0x0040 | This flag is reserved for future use. | |
IMAGE_FILE_BYTES_REVERSED_LO | 0x0080 | Little endian: the least significant bit (LSB) precedes the most significant bit (MSB) in memory. This flag is deprecated and should be zero. |
IMAGE_FILE_32BIT_MACHINE | 0x0100 | Machine is based on a 32-bit-word architecture. |
IMAGE_FILE_DEBUG_STRIPPED | 0x0200 | Debugging information is removed from the image file. |
IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP | 0x0400 | If the image is on removable media, fully load it and copy it to the swap file. |
IMAGE_FILE_NET_RUN_FROM_SWAP | 0x0800 | If the image is on network media, fully load it and copy it to the swap file. |
IMAGE_FILE_SYSTEM | 0x1000 | The image file is a system file, not a user program. |
IMAGE_FILE_DLL | 0x2000 | The image file is a dynamic-link library (DLL). Such files are considered executable files for almost all purposes, although they cannot be directly run. |
IMAGE_FILE_UP_SYSTEM_ONLY | 0x4000 | The file should be run only on a uniprocessor machine. |
IMAGE_FILE_BYTES_REVERSED_HI | 0x8000 | Big endian: the MSB precedes the LSB in memory. This flag is deprecated and should be zero. |
Examples
Suppose we are analyzing a 32-bit executable that has a Characteristics value of 0x103. It means that following flags are set:
- 0x100: IMAGE_FILE_32BIT_MACHINE
- 0x002: IMAGE_FILE_EXECUTABLE_IMAGE
- 0x001: IMAGE_FILE_RELOCS_STRIPPED
A 64-bit executable could have a value of 0x22 (IMAGE_FILE_32BIT_MACHINE flag not set, indicating that IMAGE_FILE_64BIT_MACHINE is set instead):
- 0x20: IMAGE_FILE_LARGE_ADDRESS_AWARE
- 0x02: IMAGE_FILE_EXECUTABLE_IMAGE
Windows Subsystem
The following values defined for the Subsystem field of the optional header determine which Windows subsystem (if any) is required to run the image.
Constant | Value | Description |
---|---|---|
IMAGE_SUBSYSTEM_UNKNOWN | 0 | An unknown subsystem |
IMAGE_SUBSYSTEM_NATIVE | 1 | Device drivers and native Windows processes |
IMAGE_SUBSYSTEM_WINDOWS_GUI | 2 | The Windows graphical user interface (GUI) subsystem |
IMAGE_SUBSYSTEM_WINDOWS_CUI | 3 | The Windows character subsystem |
IMAGE_SUBSYSTEM_POSIX_CUI | 7 | The Posix character subsystem |
IMAGE_SUBSYSTEM_WINDOWS_CE_GUI | 9 | Windows CE |
IMAGE_SUBSYSTEM_EFI_APPLICATION | 10 | An Extensible Firmware Interface (EFI) application |
IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER | 11 | An EFI driver with boot services |
IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER | 12 | An EFI driver with run-time services |
IMAGE_SUBSYSTEM_EFI_ROM | 13 | An EFI ROM image |
IMAGE_SUBSYSTEM_XBOX | 14 | XBOX |
DLL Characteristics
The following values are defined for the DllCharacteristics field of the optional header.
Constant | Value | Description |
---|---|---|
0x0001 | Reserved, must be zero. | |
0x0002 | Reserved, must be zero. | |
0x0004 | Reserved, must be zero. | |
0x0008 | Reserved, must be zero. | |
IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE | 0x0040 | DLL can be relocated at load time. |
IMAGE_DLL_CHARACTERISTICS_FORCE_INTEGRITY | 0x0080 | Code Integrity checks are enforced. |
IMAGE_DLL_CHARACTERISTICS_NX_COMPAT | 0x0100 | Image is NX compatible. |
IMAGE_DLLCHARACTERISTICS_NO_ISOLATION | 0x0200 | Isolation aware, but do not isolate the image. |
IMAGE_DLLCHARACTERISTICS_NO_SEH | 0x0400 | Does not use structured exception (SE) handling. No SE handler may be called in this image. |
IMAGE_DLLCHARACTERISTICS_NO_BIND | 0x0800 | Do not bind the image. |
0x1000 | Reserved, must be zero. | |
IMAGE_DLLCHARACTERISTICS_WDM_DRIVER | 0x2000 | A WDM driver. |
IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE | 0x8000 | Terminal Server aware. |
Section Characteristics
The section flags in the Characteristics field of the section header indicate characteristics of the section.
Flag | Value | Description |
---|---|---|
0x00000000 | Reserved for future use. | |
0x00000001 | Reserved for future use. | |
0x00000002 | Reserved for future use. | |
0x00000004 | Reserved for future use. | |
IMAGE_SCN_TYPE_NO_PAD | 0x00000008 | The section should not be padded to the next boundary. This flag is obsolete and is replaced by IMAGE_SCN_ALIGN_1BYTES. This is valid only for object files. |
0x00000010 | Reserved for future use. | |
IMAGE_SCN_CNT_CODE | 0x00000020 | The section contains executable code. |
IMAGE_SCN_CNT_INITIALIZED_DATA | 0x00000040 | The section contains initialized data. |
IMAGE_SCN_CNT_UNINITIALIZED_DATA | 0x00000080 | The section contains uninitialized data. |
IMAGE_SCN_LNK_OTHER | 0x00000100 | Reserved for future use. |
IMAGE_SCN_LNK_INFO | 0x00000200 | The section contains comments or other information. The .drectve section has this type. This is valid for object files only. |
0x00000400 | Reserved for future use. | |
IMAGE_SCN_LNK_REMOVE | 0x00000800 | The section will not become part of the image. This is valid only for object files. |
IMAGE_SCN_LNK_COMDAT | 0x00001000 | The section contains COMDAT data. This is valid only for object files. |
IMAGE_SCN_GPREL | 0x00008000 | The section contains data referenced through the global pointer (GP). |
IMAGE_SCN_MEM_PURGEABLE | 0x00020000 | Reserved for future use. |
IMAGE_SCN_MEM_16BIT | 0x00020000 | For ARM machine types, the section contains Thumb code. Reserved for future use with other machine types. |
IMAGE_SCN_MEM_LOCKED | 0x00040000 | Reserved for future use. |
IMAGE_SCN_MEM_PRELOAD | 0x00080000 | Reserved for future use. |
IMAGE_SCN_ALIGN_1BYTES | 0x00100000 | Align data on a 1-byte boundary. Valid only for object files. |
IMAGE_SCN_ALIGN_2BYTES | 0x00200000 | Align data on a 2-byte boundary. Valid only for object files. |
IMAGE_SCN_ALIGN_4BYTES | 0x00300000 | Align data on a 4-byte boundary. Valid only for object files. |
IMAGE_SCN_ALIGN_8BYTES | 0x00400000 | Align data on an 8-byte boundary. Valid only for object files. |
IMAGE_SCN_ALIGN_16BYTES | 0x00500000 | Align data on a 16-byte boundary. Valid only for object files. |
IMAGE_SCN_ALIGN_32BYTES | 0x00600000 | Align data on a 32-byte boundary. Valid only for object files. |
IMAGE_SCN_ALIGN_64BYTES | 0x00700000 | Align data on a 64-byte boundary. Valid only for object files. |
IMAGE_SCN_ALIGN_128BYTES | 0x00800000 | Align data on a 128-byte boundary. Valid only for object files. |
IMAGE_SCN_ALIGN_256BYTES | 0x00900000 | Align data on a 256-byte boundary. Valid only for object files. |
IMAGE_SCN_ALIGN_512BYTES | 0x00A00000 | Align data on a 512-byte boundary. Valid only for object files. |
IMAGE_SCN_ALIGN_1024BYTES | 0x00B00000 | Align data on a 1024-byte boundary. Valid only for object files. |
IMAGE_SCN_ALIGN_2048BYTES | 0x00C00000 | Align data on a 2048-byte boundary. Valid only for object files. |
IMAGE_SCN_ALIGN_4096BYTES | 0x00D00000 | Align data on a 4096-byte boundary. Valid only for object files. |
IMAGE_SCN_ALIGN_8192BYTES | 0x00E00000 | Align data on an 8192-byte boundary. Valid only for object files. |
IMAGE_SCN_LNK_NRELOC_OVFL | 0x01000000 | The section contains extended relocations. |
IMAGE_SCN_MEM_DISCARDABLE | 0x02000000 | The section can be discarded as needed. |
IMAGE_SCN_MEM_NOT_CACHED | 0x04000000 | The section cannot be cached. |
IMAGE_SCN_MEM_NOT_PAGED | 0x08000000 | The section is not pageable. |
IMAGE_SCN_MEM_SHARED | 0x10000000 | The section can be shared in memory. |
IMAGE_SCN_MEM_EXECUTE | 0x20000000 | The section can be executed as code. |
IMAGE_SCN_MEM_READ | 0x40000000 | The section can be read. |
IMAGE_SCN_MEM_WRITE | 0x80000000 | The section can be written to. |
Export Table
Offsets shown from beginning of table (given at offset 0x78 from start of PE header). The following 40 Bytes repeat for each export library (DLL whose functions are imported by the executable) and ends with one full of zeroes.
Offset | Size | Field | Description |
---|---|---|---|
0x00 | DWORD | Characteristics (Export Flags) | Reserved, must be 0. |
0x04 | DWORD | TimeDateStamp | The time and date that the export data was created. |
0x08 | WORD | MajorVersion | The major version number. The major and minor version numbers can be set by the user. |
0x0A | WORD | MinorVersion | The minor version number. |
0x0C | DWORD | Name (Name RVA) | The address of the ASCII string that contains the name of the DLL. This address is relative to the image base. |
0x10 | DWORD | Base (Ordinal Base) | The starting ordinal number for exports in this image. This field specifies the starting ordinal number for the export address table. It is usually set to 1. |
0x14 | DWORD | NumberOfFunctions (Address Table Entries) | The number of entries in the export address table. |
0x18 | DWORD | NumberOfNames (Number of Name Pointers) | The number of entries in the name pointer table. This is also the number of entries in the ordinal table. |
0x1C | DWORD | AddressOfFunctions (Export Address Table RVA) | The address of the export address table, relative to the image base. |
0x20 | DWORD | AddressOfNames (Name Pointer RVA) | The address of the export name pointer table, relative to the image base. The table size is given by the Number of Name Pointers field. |
0x24 | DWORD | AddressOfNameOrdinals (Ordinal Table RVA) | The address of the ordinal table, relative to the image base. |
Example of kernel32.dll export table viewed in CFF Explorer:
Import Table
Offsets shown from beginning of table (given at offset 0x80 from start of PE header). The following 5 DWORDS repeat for each import library (DLL whose functions are imported by the executable) and ends with one full of zeroes.
Offset | Size | Field | Description |
---|---|---|---|
0x00 | DWORD | OriginalFirstThunk | RVA to Image_Thunk_Data |
0x04 | DWORD | TimeDateStamp | zero unless bound against imported DLL |
0x08 | DWORD | ForwarderChain | pointer to 1st redirected function (or 0) |
0x0C | DWORD | Name1 | RVA to name in null-terminated ASCII |
0x10 | DWORD | FirstThunk | RVA to Image_Thunk_Data |
Analyze PE files
Basic Static Analysis
Operation | Purpose | Windows tools | Linux tools |
---|---|---|---|
Antivirus scanning | Identify whether the executable is already identified by antiviruses | ||
Hashing | Find additional information on the Internet using the hash as searched string (e.g. search in Google) |
| |
Find strings |
|
| |
Detect packer, unpack | Attempt to unpack the malware in case it is packed. More information about packers can be found here. | ||
PE file header and sections | Gather rough information, timestamp, ... | ||
See imports/exports | Guess the purpose of the malware |
| |
View/export resources | E.g. reveal dropped payloads in case of a malware dropper |
|
Basic Dynamic Analysis
Operation | Purpose | Windows tools |
---|---|---|
Mutex | Are there any mutex created (useful to identify the malware, e.g. IOC)? | Process Explorer (procexp) ("View > Lower Pane View > Handles" or CTRL+H) |
Dynamically loaded DLLs? | What are there purposes (e.g. network)? | Process Explorer (procexp) ("View > Lower Pane View > DLLs" or CTRL+D) |
Files created? | Are there any files created/dropped by the malware? | Process Monitor (procmon) |
Registry keys created? | Are there any registry keys created by the malware (e.g. persistence)? | Process Monitor (procmon) |
Network traffic |
|
Advanced Static Analysis
Advanced Dynamic Analysis
Thank you for your comprehension.
Example
Let's analyze a malware provided by the book "Practical Malware Analysis": Lab03-01.exe.
Basic Analysis
Imports
We start our analysis with a basic static analysis.
$ objdump -x /data/tmp/Lab03-01.exe /data/tmp/Lab03-01.exe: file format pei-i386 /data/tmp/Lab03-01.exe architecture: i386, flags 0x0000010a: EXEC_P, HAS_DEBUG, D_PAGED start address 0x00400208 Characteristics 0x10f relocations stripped executable line numbers stripped symbols stripped 32 bit words Time/Date Sun Jan 6 15:51:31 2008 [snip] There is an import table in .text at 0x40021c The Import Tables (interpreted .text section contents) vma: Hint Time Forward DLL First Table Stamp Chain Name Thunk 0000021c 00000244 00000000 00000000 0000025a 00000200 DLL Name: kernel32.dll vma: Hint/Ord Member-Name Bound-To 024c 128 ExitProcess 00000230 00000000 00000000 00000000 00000000 00000000 Sections: Idx Name Size VMA LMA File off Algn 0 .text 00000068 00400200 00400200 00000200 2**2 CONTENTS, ALLOC, LOAD, READONLY, CODE 1 .data 0000168f 00400400 00400400 00000400 2**2 CONTENTS, ALLOC, LOAD, DATA SYMBOL TABLE: no symbols
From the above lines, we know that:
- the malware has been developed for an x86 architecture
- the malware has been created in early 2008
- kernel32.dll is imported, there is 1 import: ExitProcess
And if you prefer a GUI-based tool, you can use pe_view:
Packed?
As there is only 1 import, it's likely that the malware is packed. PEiD finds a signature that matches "PEncrypt 3.1 final":
Strings
Let's see what we can learn from the strings command:
$ strings /data/tmp/Lab03-01.exe ExitProcess [1] kernel32.dll [1] ws2_32 cks=u ttp= cks= CONNECT %s:%i HTTP/1.0 [2] [snip] advapi32 [3] ntdll user32 [snip] advpack StubPath SOFTWARE\Classes\http\shell\open\commandV [4] Software\Microsoft\Active Setup\Installed Components\ [5] test www.practicalmalwareanalysis.com [6] admin VideoDriver [7] WinVMX32- [8] vmx32to64.exe [9] SOFTWARE\Microsoft\Windows\CurrentVersion\Run [10] SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders [11] AppData [12] [snip] |
|
Conclusions of the Basic Static Analysis
This is quite odd that we were able to see so many information from the strings command as we made the assumption the file is probably packed. It could be fake data left by the author of the malware to trick a non-experienced Malware Analyst.
Anyway, we have reached a dead-end for the basic static analysis and we can now start the Basic Dynamic Analysis to confirm our assumptions.
Basic Dynamic Analysis
Network traffic
First of all, our assumptions regarding the network behavior seem to be confirmed.
This feature is confirmed by Process Explorer (procexp) that discloses the call to 2 network DLLs:
- ws2_32.dll: Windows Socket 2.0 32-Bit DLL
- wshtcpip.dll: Windows Sockets Helper DLL
ApateDNS shows a regular connection to "www.practicalmalwareanalysis.com":
Tshark indicates that the traffic is established to port 443/tcp (SSL?)
$ tshark -n -r lab0301-filtered.pcap -z io,phs 1 0.000000 192.168.56.2 -> 192.168.56.3 TCP 62 1049 > 443 [SYN] Seq=0 Win=64240 Len=0 MSS=1460 SACK_PERM=1 2 0.000470 192.168.56.3 -> 192.168.56.2 TCP 62 443 > 1049 [SYN, ACK] Seq=0 Ack=1 Win=5840 Len=0 MSS=1460 SACK_PERM=1 3 0.000495 192.168.56.2 -> 192.168.56.3 TCP 54 1049 > 443 [ACK] Seq=1 Ack=1 Win=64240 Len=0 4 0.000803 192.168.56.2 -> 192.168.56.3 SSL 310 Continuation Data 5 0.001120 192.168.56.3 -> 192.168.56.2 TCP 60 443 > 1049 [ACK] Seq=1 Ack=257 Win=6432 Len=0 6 0.004805 192.168.56.3 -> 192.168.56.2 TCP 60 443 > 1049 [FIN, ACK] Seq=1 Ack=257 Win=6432 Len=0 7 0.004833 192.168.56.2 -> 192.168.56.3 TCP 54 1049 > 443 [ACK] Seq=257 Ack=2 Win=64240 Len=0 8 0.004956 192.168.56.3 -> 192.168.56.2 TCP 60 443 > 1049 [RST, ACK] Seq=2 Ack=257 Win=6432 Len=0 9 0.004968 192.168.56.3 -> 192.168.56.2 TCP 60 443 > 1049 [RST] Seq=2 Win=0 Len=0 10 30.004576 192.168.56.2 -> 192.168.56.3 TCP 62 1050 > 443 [SYN] Seq=0 Win=64240 Len=0 MSS=1460 SACK_PERM=1 11 30.005164 192.168.56.3 -> 192.168.56.2 TCP 62 443 > 1050 [SYN, ACK] Seq=0 Ack=1 Win=5840 Len=0 MSS=1460 SACK_PERM=1 12 30.005198 192.168.56.2 -> 192.168.56.3 TCP 54 1050 > 443 [ACK] Seq=1 Ack=1 Win=64240 Len=0 13 30.005563 192.168.56.2 -> 192.168.56.3 SSL 310 Continuation Data 14 30.005984 192.168.56.3 -> 192.168.56.2 TCP 60 443 > 1050 [ACK] Seq=1 Ack=257 Win=6432 Len=0 15 30.013920 192.168.56.3 -> 192.168.56.2 TCP 60 443 > 1050 [FIN, ACK] Seq=1 Ack=257 Win=6432 Len=0 16 30.013987 192.168.56.2 -> 192.168.56.3 TCP 54 1050 > 443 [ACK] Seq=257 Ack=2 Win=64240 Len=0 17 30.014430 192.168.56.3 -> 192.168.56.2 TCP 60 443 > 1050 [RST, ACK] Seq=2 Ack=257 Win=6432 Len=0 =================================================================== Protocol Hierarchy Statistics Filter: eth frames:17 bytes:1504 ip frames:17 bytes:1504 tcp frames:17 bytes:1504 ssl frames:2 bytes:620 ===================================================================
INetSim confirms the connections, to port 443/tcp. However, it seems that it is not a SSL traffic:
root@inetsim:/opt/inetsim/log# more service.log [2013-07-03 07:40:01] [1021] [https_443_tcp 1052] [192.168.56.2:1037] connect [2013-07-03 07:40:01] [1021] [https_443_tcp 1052] [192.168.56.2:1037] info: Error setting up SSL: SSL accept attempt failed with unknown error error:140760FC:SSL routines:SSL23_GET_CLIENT_HELLO:unknown protocol [2013-07-03 07:40:01] [1021] [https_443_tcp 1052] [192.168.56.2:1037] disconnect [2013-07-03 07:40:31] [1021] [https_443_tcp 1053] [192.168.56.2:1039] connect [2013-07-03 07:40:31] [1021] [https_443_tcp 1053] [192.168.56.2:1039] info: Error setting up SSL: SSL accept attempt failed with unknown error error:140760FC:SSL routines:SSL23_GET_CLIENT_HELLO:unknown protocol [2013-07-03 07:40:31] [1021] [https_443_tcp 1053] [192.168.56.2:1039] disconnect [snip]
WireShark confirms that regular 256 bytes payloads are sent:
Mutex
Process Explorer (procexp) confirms that the malware creates a mutex: WinVMX32.
Files and registry keys
Now, let's have a look at the written files and created registry keys with process monitor (procmon). We create a filter as follows:
The below screenshots shows that the malware:
- drops an executable named vmx32to64.exe that has a size of 7168 (the same as the original Lab03-01.exe)
- creates a persistence registry key in HKLM\Software\Microsoft\Windows\CurrentVersion\Run\VideoDriver to ensure that this dropped executable automatically starts at startup
Conclusions of the Basic Dynamic Analysis
The basic dynamic analysis confirms the initial assumptions:
- the malware has connectivity features. It sends an encrypted 256 bytes payload to www.practicalmalwareanalysis.com over port 443/tcp (though not SSL) every 30 seconds
- the malware drops a copy of itself in C:\Windows\system32\vmw32to64.exe
- it creates a persistence startup registry key to ensure it is automatically started at startup, and hides it in a fake video driver
- the malware creates a mutex (WinVMX32)
At this stage of the analysis, we have gathered enough information to start an Advanced Static Analysis and try to decrypt the network traffic.