pe

The pe module allows you to create more fine-grained rules for Portable Executable (PE) files by using attributes and features of the PE file format. This module exposes most of the fields present in a PE header and provides functions which can be used to write more expressive and targeted rules. Let’s see some examples:

import "pe"

rule single_section {
    condition:
        pe.number_of_sections == 1
}

rule control_panel_applet {
    condition:
        pe.exports("CPlApplet")
}

rule is_dll {
    condition:
        pe.characteristics & pe.DLL != 0
}

rule is_pe {
    condition:
        pe.is_pe
}

Functions

exports(fn_name)

Returns true if the PE exports a function with the given name, or false otherwise.

exports(fn_regex)

Returns true if the PE exports a function whose name matches the given regular expression, or false otherwise.

exports(ordinal)

Returns true if the PE exports a function with the given ordinal, or false if otherwise.

exports_index(fn_name)

Returns the index into the export_details array for the first exported function that matches the given name. The result is undefined if no function with such a name exists.

exports_index(fn_regex)

Returns the index into the export_details array for the first exported function that matches the given regular expression. The result is undefined if none of the functions matches.

exports_index(ordinal)

Returns the index into the export_details array for the first exported function that has the given ordinal number. The result is undefined if no function exists with such an ordinal exists.

imports(dll_name)

Returns the number of functions that the PE imports from the given DLL. The DLL name is case-insensitive.

imports(dll_name, fn_name)

Returns true if the PE imports the given function from the given DLL. The DLL name is case-insensitive, but the function name is case-sensitive.

imports(dll_name, ordinal)

Returns true if the PE imports the given function by ordinal from the given DLL. The DLL name is case-insensitive.

imports(dll_regex, fn_regex)

Returns the number of functions imported by the PE where the DLL name matches dll_regexp and the function name matches fn_regexp. Both arguments are case-sensitive, unless you use the /i modifier in the regexp.

Example

import "pe"

rule ProcessMemory {
    condition:
        pe.imports(/kernel32.dll/i, /(Read|Write)ProcessMemory/) > 0
}

imports(type, dll_name, fn_name)

Returns true if the PE imports fn_name from dll_name. The DLL name is case-insensitive. type allows to specify the kind of imports should be taken into account, the allowed values are:

pe.IMPORT_STANDARDStandard imports only
pe.IMPORT_DELAYEDDelayed imports only
pe.IMPORT_ANYBoth standard and delayed imports

Example

import "pe"

rule ProcessMemory {
    condition:
        pe.imports(pe.IMPORT_DELAYED, "kernel32.dll", "WriteProcessMemory")
}

is_32bit()

Returns true if the file is a 32-bit PE.

is_64bit()

Returns true if the file is a 64-bit PE.

is_dll()

Returns true if the file is Dynamic Link Library (DLL).

rva_to_offset(rva)

Given a relative virtual address (RVA) returns the corresponding file offset.

calculate_checksum()

Calculate the PE checksum. Useful for checking if the checksum in the header is correct.

Example

import "pe"

rule WrongChecksum {
    condition:
        pe.calculate_checksum() != pe.checksum
}

section_index(name)

Returns the index into the sections array for the section that has the given name. The name argument is case-sensitive.

section_index(offset)

Returns the index into the sections array for the section that contains the given file offset.

imphash()

Returns 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 for a PE can be also computed with pefile and you can find more information in Mandiant’s blog.

Notice

The returned hash string is always in lowercase.

rich_signature.version(version, [toolid])

The PE rich signature contains information about the tools involved in the creation of the PE file. This function returns the number of tools that matches the given version and toolid, where toolid is optional.

Example

import "pe"

rule WrongChecksum {
    condition:
        pe.rich_signature.version(24215, 261) == 61
}

rich_signature.toolid(toolid, [version])

This function is similar to rich_signature.version, but the toolid argument is required while version is optional.


Module structure

FieldTypeDescription
is_peboolTrue if the file is PE
is_signedboolTrue if the Authenticode signature is correct
machineMachineMachine type
subsystemSubsystemSubsystem type
os_versionVersionOS version
subsystem_versionVersionSubsystem version
image_versionVersionImage version
linker_versionVersionLinker version
opthdr_magicOptionalMagicMagic in optional headers
characteristicsintegerCharacteristics flags
dll_characteristicsintegerDllCharacteristics flags
timestampintegerPE timestamp (as Unix timestamp)
image_baseintegerImage base
checksumintegerPE checksum
base_of_codeintegerBase of code
base_of_dataintegerBase of data
entry_pointintegerEntry point as a file offset
entry_point_rawintegerEntry point as it appears in the PE header (RVA)
dll_namestringDLL name
export_timestampintegerExports timestamp (as Unix timestamp)
section_alignmentintegerSection alignment
file_alignmentintegerFile alignment
loader_flagsintegerLoader flags
size_of_optional_headerintegerSize of optional header
size_of_codeintegerSize of code
size_of_initialized_dataintegerSize of initialized data
size_of_uninitialized_dataintegerSize of uninitialized data
size_of_imageintegerSize of image
size_of_headersintegerSize of headers
size_of_stack_reserveintegerSize of stack reserve
size_of_stack_commitintegerSize of stack commit
size_of_heap_reserveintegerSize of heap reserve
size_of_heap_commitintegerSize of heap commit
pointer_to_symbol_tableintegerFile offset of symbol table
win32_version_valueintegerWin32 version
number_of_symbolsintegerNumber of symbols
number_of_rva_and_sizesintegerNumber of
number_of_sectionsintegerLength of sections
number_of_imported_functionsintegerTotal number of imported functions
number_of_delayed_imported_functionsintegerTotal number of delayed imported functions
number_of_resourcesintegerLength of resources
number_of_version_infosintegerLength of version_info_list
number_of_importsintegerLength of import_details
number_of_delayed_importsintegerLength of delayed_import_details
number_of_exportsintegerLength of export_details
number_of_signaturesintegerLength of signatures
version_infodictionaryDictionary with PE version information
version_info_listKeyValue arrayLike version_info but as array
rich_signatureRichSignatureRich signature information
pdb_pathstringPDB path
sectionsSection arraySections
data_directoriesDirEntry arrayData directory entries
resource_timestampintegerResource timestamp (as Unix timestamp)
resource_versionVersionResource version
resourcesResource arrayResources
import_detailsImport arrayImports information
delayed_import_detailsImport arrayDelayed imports information
export_detailsExport arrayExports information
signaturesSignature arraySignatures information
overlayOverlayPE overlay details

Certificate

This is the structure of each item in the certificates array.

FieldType
issuerstring
subjectstring
thumbprintstring
versioninteger
algorithmstring
algorithm_oidstring
serialstring
not_beforeinteger
not_afterinteger

CounterSignature

FieldType
verifiedbool
sign_timeinteger
digeststring
digest_algstring
chainCertificate array

DirEntry

FieldType
virtual_addressinteger
sizeinteger

Export

FieldType
namestring
ordinalinteger
rvainteger
offsetinteger
forward_namestring

Function

FieldType
namestring
ordinalinteger
rvainteger

Import

FieldType
library_namestring
number_of_functionsinteger
functionsFunction array

KeyValue

FieldType
keystring
valuestring

Overlay

FieldType
offsetinteger
sizeinteger

VersionInfoEntry

FieldType
keystring
valuestring

Resource

FieldType
lengthinteger
rvainteger
offsetinteger
typeResourceType
idinteger
languageinteger
type_stringstring
name_stringstring
language_stringstring

RichSignature

FieldType
offsetinteger
lengthinteger
keyinteger
raw_datastring
clear_datastring
toolsRichTool array

RichTool

FieldType
toolidinteger
versioninteger
timesinteger

Section

FieldType
namestring
full_namestring
characteristicsinteger
raw_data_sizeinteger
raw_data_offsetinteger
virtual_addressinteger
virtual_sizeinteger
pointer_to_relocationsinteger
pointer_to_line_numbersinteger
number_of_relocationsinteger
number_of_line_numbersinteger

Signature

Structure of each of the items in the signatures array.

FieldType
subjectstring
issuerstring
thumbprintstring
versioninteger
algorithmstring
algorithm_oidstring
serialstring
not_beforeinteger
not_afterinteger
verifiedbool
digest_algstring
digeststring
file_digeststring
number_of_certificatesinteger
number_of_countersignaturesinteger
signer_infoSignerInfo
certificatesCertificate array
countersignaturesCounterSignature array

Example

import "pe"

rule NotVerified {
    condition:
        for any sig in pe.signatures : (
            sig.subject contains "Microsoft" and
            not sig.verified
        )
}

SignerInfo

FieldType
program_namestring
digeststring
digest_algstring
chainCertificate array

Version

The structures of fields like os_version, subsystem_version, image_version, linker_version and resource_version.

FieldType
majorinteger
minorinteger

Example

import "pe"

rule Windows_5_2 {
    condition:
        pe.os_version.major == 5 and 
        pe.os_version.minor == 2
}

Characteristics

Possible flags found in the characteristics field.

NameNumberDescription
RELOCS_STRIPPED0x0001Relocation info stripped from file.
EXECUTABLE_IMAGE0x0002File is executable (i.e. no unresolved external references).
LINE_NUMS_STRIPPED0x0004Line numbers stripped from file.
LOCAL_SYMS_STRIPPED0x0008Local symbols stripped from file.
AGGRESIVE_WS_TRIM0x0010Aggressively trim working set
LARGE_ADDRESS_AWARE0x0020App can handle >2gb addresses
BYTES_REVERSED_LO0x0080Bytes of machine word are reversed.
MACHINE_32BIT0x010032 bit word machine.
DEBUG_STRIPPED0x0200Debugging info stripped from file in .DBG file
REMOVABLE_RUN_FROM_SWAP0x0400If Image is on removable media, copy and run from the swap file.
NET_RUN_FROM_SWAP0x0800If Image is on Net, copy and run from the swap file.
SYSTEM0x1000System File.
DLL0x2000File is a DLL.s
UP_SYSTEM_ONLY0x4000File should only be run on a UP machine
BYTES_REVERSED_HI0x8000Bytes of machine word are reversed.

Example

import "pe"

rule IsDLL {
    condition:
        pe.characteristics & pe.DLL != 0
}

DllCharacteristics

Possible flags found in the dll_characteristics field.

NameNumber
HIGH_ENTROPY_VA0x0020
DYNAMIC_BASE0x0040
FORCE_INTEGRITY0x0080
NX_COMPAT0x0100
NO_ISOLATION0x0200
NO_SEH0x0400
NO_BIND0x0800
APPCONTAINER0x1000
WDM_DRIVER0x2000
GUARD_CF0x4000
TERMINAL_SERVER_AWARE0x8000

Example

import "pe"

rule WdmDriver {
    condition:
        pe.dll_characteristics & pe.WDM_DRIVER != 0
}

DirectoryEntry

NameNumber
IMAGE_DIRECTORY_ENTRY_EXPORT0
IMAGE_DIRECTORY_ENTRY_IMPORT1
IMAGE_DIRECTORY_ENTRY_RESOURCE2
IMAGE_DIRECTORY_ENTRY_EXCEPTION3
IMAGE_DIRECTORY_ENTRY_SECURITY4
IMAGE_DIRECTORY_ENTRY_BASERELOC5
IMAGE_DIRECTORY_ENTRY_DEBUG6
IMAGE_DIRECTORY_ENTRY_COPYRIGHT7
IMAGE_DIRECTORY_ENTRY_ARCHITECTURE8
IMAGE_DIRECTORY_ENTRY_GLOBALPTR9
IMAGE_DIRECTORY_ENTRY_TLS10
IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG11
IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT12
IMAGE_DIRECTORY_ENTRY_IAT13
IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT14
IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR15

ImportFlags

NameNumber
IMPORT_STANDARD1
IMPORT_DELAYED2
IMPORT_ANY3

Machine

Each of the possible values in the machine field.

NameNumber
MACHINE_UNKNOWN0
MACHINE_AM33467
MACHINE_AMD6434404
MACHINE_ARM448
MACHINE_ARMNT452
MACHINE_ARM6443620
MACHINE_EBC3772
MACHINE_I386332
MACHINE_IA64512
MACHINE_M32R36929
MACHINE_MIPS16614
MACHINE_MIPSFPU870
MACHINE_MIPSFPU161126
MACHINE_POWERPC496
MACHINE_POWERPCFP497
MACHINE_R4000358
MACHINE_SH3418
MACHINE_SH3DSP419
MACHINE_SH4422
MACHINE_SH5424
MACHINE_THUMB450
MACHINE_WCEMIPSV2361

Example

import "pe"

rule ARM {
    condition:
        pe.machine == pe.MACHINE_ARM
}

OptionalMagic

NameNumber
IMAGE_NT_OPTIONAL_HDR32_MAGIC267
IMAGE_NT_OPTIONAL_HDR64_MAGIC523
IMAGE_ROM_OPTIONAL_HDR_MAGIC263

ResourceType

https://learn.microsoft.com/en-us/windows/win32/menurc/resource-types?redirectedfrom=MSDN

NameNumber
RESOURCE_TYPE_CURSOR1
RESOURCE_TYPE_BITMAP2
RESOURCE_TYPE_ICON3
RESOURCE_TYPE_MENU4
RESOURCE_TYPE_DIALOG5
RESOURCE_TYPE_STRING6
RESOURCE_TYPE_FONTDIR7
RESOURCE_TYPE_FONT8
RESOURCE_TYPE_ACCELERATOR9
RESOURCE_TYPE_RCDATA10
RESOURCE_TYPE_MESSAGETABLE11
RESOURCE_TYPE_GROUP_CURSOR12
RESOURCE_TYPE_GROUP_ICON14
RESOURCE_TYPE_VERSION16
RESOURCE_TYPE_DLGINCLUDE17
RESOURCE_TYPE_PLUGPLAY19
RESOURCE_TYPE_VXD20
RESOURCE_TYPE_ANICURSOR21
RESOURCE_TYPE_ANIICON22
RESOURCE_TYPE_HTML23
RESOURCE_TYPE_MANIFEST24

SectionCharacteristics

NameNumber
SECTION_NO_PAD1
SECTION_CNT_CODE2
SECTION_CNT_INITIALIZED_DATA3
SECTION_CNT_UNINITIALIZED_DATA4
SECTION_LNK_OTHER5
SECTION_LNK_INFO6
SECTION_LNK_REMOVE7
SECTION_LNK_COMDAT8
SECTION_NO_DEFER_SPEC_EXC9
SECTION_GPREL10
SECTION_ALIGN_1BYTES11
SECTION_ALIGN_2BYTES12
SECTION_ALIGN_4BYTES13
SECTION_ALIGN_8BYTES14
SECTION_ALIGN_16BYTES15
SECTION_ALIGN_32BYTES16
SECTION_ALIGN_64BYTES17
SECTION_ALIGN_128BYTES18
SECTION_ALIGN_256BYTES19
SECTION_ALIGN_512BYTES20
SECTION_ALIGN_1024BYTES21
SECTION_ALIGN_2048BYTES22
SECTION_ALIGN_4096BYTES23
SECTION_ALIGN_8192BYTES24
SECTION_ALIGN_MASK25
SECTION_LNK_NRELOC_OVFL26
SECTION_MEM_DISCARDABLE27
SECTION_MEM_NOT_CACHED28
SECTION_MEM_NOT_PAGED29
SECTION_MEM_SHARED30
SECTION_MEM_EXECUTE31
SECTION_MEM_READ32
SECTION_MEM_WRITE33
SECTION_SCALE_INDEX34

Subsystem

NameNumber
SUBSYSTEM_UNKNOWN0
SUBSYSTEM_NATIVE1
SUBSYSTEM_WINDOWS_GUI2
SUBSYSTEM_WINDOWS_CUI3
SUBSYSTEM_OS2_CUI5
SUBSYSTEM_POSIX_CUI7
SUBSYSTEM_NATIVE_WINDOWS8
SUBSYSTEM_WINDOWS_CE_GUI9
SUBSYSTEM_EFI_APPLICATION10
SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER11
SUBSYSTEM_EFI_RUNTIME_DRIVER12
SUBSYSTEM_EFI_ROM_IMAGE13
SUBSYSTEM_XBOX14
SUBSYSTEM_WINDOWS_BOOT_APPLICATION16