CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-lief

Library to instrument executable formats including ELF, PE, Mach-O, and Android formats

Pending
Overview
Eval results
Files

pe-format.mddocs/

PE Format

Complete support for PE (Portable Executable) format used by Windows executables, DLLs, and system files. PE format provides comprehensive metadata for Windows loading, imports/exports, resources, and code signing with extensive Windows-specific features.

Capabilities

PE Parsing

Parse PE files with format-specific configuration and validation options.

def parse(filename: str, config: ParserConfig = None) -> Optional[Binary]:
    """Parse PE file from filesystem path."""

def parse(raw: Sequence[int], config: ParserConfig = None) -> Optional[Binary]:
    """Parse PE from raw bytes."""
    
def parse(obj: Union[io.IOBase, os.PathLike], config: ParserConfig = None) -> Optional[Binary]:
    """Parse PE from file-like object."""

def get_type(file: Union[str, Sequence[int]]) -> Union[PE_TYPE, lief_errors]:
    """Determine PE type (PE32 or PE32+)."""

class ParserConfig:
    parse_imports: bool
    parse_exports: bool
    parse_resources: bool  
    parse_relocations: bool
    parse_debug: bool
    parse_tls: bool
    parse_load_config: bool
    parse_exceptions: bool
    parse_signatures: bool
    parse_overlay: bool

enum PE_TYPE:
    PE32 = 0
    PE32_PLUS = 1

Usage example:

import lief.PE as PE

# Check PE type first
pe_type = PE.get_type("C:\\Windows\\System32\\kernel32.dll")
print(f"PE type: {pe_type}")

# Parse with configuration
config = PE.ParserConfig()
config.parse_imports = True
config.parse_exports = True
config.parse_resources = True
binary = PE.parse("C:\\Windows\\System32\\kernel32.dll", config)

PE Binary Operations

PE-specific binary manipulation with Windows executable features.

class Binary(lief.Binary):
    dos_header: DosHeader
    header: Header
    optional_header: OptionalHeader
    sections: Iterator[Section]
    imports: Iterator[Import]
    exports: Optional[Export]
    resources: Optional[ResourceNode]
    relocations: Iterator[Relocation]
    tls: Optional[TLS]
    load_configuration: Optional[LoadConfiguration]
    signatures: Iterator[Signature]
    debug: Iterator[Debug]
    overlay: memoryview
    dos_stub: memoryview
    rich_header: Optional[RichHeader]
    
    def add_section(self, section: Section) -> Section
    def remove_section(self, name: str, clear: bool = False) -> None  
    def add_library(self, library: str) -> Import
    def remove_library(self, library: str) -> None
    def add_import_function(self, library: str, function: str) -> ImportEntry
    def remove_import_function(self, library: str, function: str) -> None
    def has_import(self, library: str) -> bool
    def get_import(self, library: str) -> Optional[Import]
    def has_signature(self) -> bool
    def verify_signature(self) -> Signature.VERIFICATION_FLAGS
    def authentihash(self, algorithm: ALGORITHMS) -> List[int]

Usage example:

binary = PE.parse("C:\\Windows\\System32\\notepad.exe")

# Add new import
import_lib = binary.add_library("user32.dll")
entry = binary.add_import_function("user32.dll", "MessageBoxA")
print(f"Added import: {entry.name}")

# Check code signing
if binary.has_signature():
    verification = binary.verify_signature()
    print(f"Signature verification: {verification}")
    
# Calculate authentihash for verification
auth_hash = binary.authentihash(PE.ALGORITHMS.SHA_256)
print(f"Authentihash: {bytes(auth_hash).hex()}")

DOS and PE Headers

Analyze DOS header, PE header, and optional header information.

class DosHeader(lief.Object):
    magic: int
    bytes_on_last_page: int
    pages_in_file: int
    relocations: int
    size_of_header: int
    minimum_extra_paragraphs: int
    maximum_extra_paragraphs: int
    initial_relative_ss: int
    initial_sp: int
    checksum: int
    initial_ip: int
    initial_relative_cs: int
    addr_relocation_table: int
    overlay_number: int
    reserved: List[int]
    oem_id: int
    oem_info: int
    reserved2: List[int]
    addr_new_exe_header: int

class Header(lief.Object):
    machine: MACHINE_TYPES
    number_of_sections: int
    time_date_stamp: int
    pointer_to_symbol_table: int
    number_of_symbols: int
    size_of_optional_header: int
    characteristics: HEADER_CHARACTERISTICS

class OptionalHeader(lief.Object):
    magic: PE_TYPE
    major_linker_version: int
    minor_linker_version: int
    size_of_code: int
    size_of_initialized_data: int
    size_of_uninitialized_data: int
    addr_of_entry_point: int
    base_of_code: int
    image_base: int
    section_alignment: int
    file_alignment: int
    major_os_version: int
    minor_os_version: int
    major_image_version: int
    minor_image_version: int
    major_subsystem_version: int
    minor_subsystem_version: int
    win32_version_value: int
    size_of_image: int
    size_of_headers: int
    checksum: int
    subsystem: SUBSYSTEM
    dll_characteristics: DLL_CHARACTERISTICS
    size_of_stack_reserve: int
    size_of_stack_commit: int
    size_of_heap_reserve: int
    size_of_heap_commit: int
    loader_flags: int
    number_of_rva_and_size: int

enum MACHINE_TYPES:
    IMAGE_FILE_MACHINE_UNKNOWN = 0x0
    IMAGE_FILE_MACHINE_I386 = 0x14c
    IMAGE_FILE_MACHINE_AMD64 = 0x8664
    IMAGE_FILE_MACHINE_ARM = 0x1c0
    IMAGE_FILE_MACHINE_ARM64 = 0xaa64

enum SUBSYSTEM:
    IMAGE_SUBSYSTEM_UNKNOWN = 0
    IMAGE_SUBSYSTEM_NATIVE = 1
    IMAGE_SUBSYSTEM_WINDOWS_GUI = 2
    IMAGE_SUBSYSTEM_WINDOWS_CUI = 3
    IMAGE_SUBSYSTEM_WINDOWS_CE_GUI = 9

Usage example:

binary = PE.parse("C:\\Windows\\System32\\calc.exe")

# DOS header analysis
dos = binary.dos_header
print(f"DOS signature: 0x{dos.magic:x}")
print(f"PE header offset: 0x{dos.addr_new_exe_header:x}")

# PE header analysis  
header = binary.header
print(f"Machine type: {header.machine}")
print(f"Number of sections: {header.number_of_sections}")
print(f"Timestamp: {header.time_date_stamp}")

# Optional header analysis
opt = binary.optional_header
print(f"Entry point: 0x{opt.addr_of_entry_point:x}")
print(f"Image base: 0x{opt.image_base:x}")
print(f"Subsystem: {opt.subsystem}")

Import/Export Analysis

Comprehensive import and export table analysis with ordinal resolution.

class Import(lief.Object):
    name: str
    import_address_table_rva: int
    import_lookup_table_rva: int
    entries: Iterator[ImportEntry]
    
    def get_function_rva_from_iat(self, function: str) -> int
    def add_entry(self, entry: ImportEntry) -> ImportEntry

class ImportEntry(lief.Object):
    name: str
    data: int
    ordinal: int
    hint: int
    iat_value: int
    
    def is_ordinal(self) -> bool

class Export(lief.Object):
    export_flags: int
    timestamp: int
    major_version: int
    minor_version: int
    ordinal_base: int
    name: str
    entries: Iterator[ExportEntry]

class ExportEntry(lief.Object):
    name: str
    ordinal: int
    address: int
    is_extern: bool
    forward_information: ForwardInformation

def resolve_ordinals(imp: Import, strict: bool = False, use_std: bool = False) -> Union[Import, lief_errors]:
    """Resolve import function names from ordinals."""

def get_imphash(binary: Binary, mode: IMPHASH_MODE = IMPHASH_MODE.DEFAULT) -> str:
    """Calculate import hash for malware analysis."""

Usage example:

binary = PE.parse("C:\\Windows\\System32\\notepad.exe")

# Analyze imports
print("Import libraries:")
for import_lib in binary.imports:
    print(f"  {import_lib.name}")
    for entry in import_lib.entries:
        if entry.is_ordinal():
            print(f"    Ordinal #{entry.ordinal}")
        else:
            print(f"    {entry.name} (hint: {entry.hint})")

# Analyze exports (for DLLs)
if binary.exports:
    print(f"Export DLL name: {binary.exports.name}")
    for entry in binary.exports.entries:
        print(f"  {entry.name} @ ordinal {entry.ordinal}")
        
# Calculate import hash
imphash = PE.get_imphash(binary)
print(f"Import hash: {imphash}")

# Resolve ordinals if needed
for import_lib in binary.imports:
    resolved = PE.resolve_ordinals(import_lib)
    if not isinstance(resolved, PE.lief_errors):
        print(f"Resolved ordinals for {resolved.name}")

Resource Management

Parse and manipulate PE resources including icons, version information, and custom data.

class ResourceNode(lief.Object):
    id: int
    name: str
    childs: Iterator[ResourceNode]
    
    def has_name(self) -> bool
    def has_id(self) -> bool

class ResourceData(ResourceNode):
    content: memoryview
    code_page: int
    reserved: int

class ResourceStringFileInfo(lief.Object):
    type: int
    key: str
    langcode_items: Iterator[LangCodeItem]

class ResourceVarFileInfo(lief.Object):
    type: int
    key: str
    translations: List[int]

class ResourceVersion(lief.Object):
    type: int
    key: str
    fixed_file_info: ResourceFixedFileInfo
    string_file_info: ResourceStringFileInfo
    var_file_info: ResourceVarFileInfo

class ResourceIcon(lief.Object):
    id: int
    lang: int
    sublang: int
    width: int
    height: int
    color_count: int
    reserved: int
    planes: int
    bit_count: int
    size: int
    pixels: memoryview

Usage example:

binary = PE.parse("C:\\Windows\\System32\\calc.exe")

if binary.resources:
    # Walk resource tree
    def walk_resources(node, level=0):
        indent = "  " * level
        if node.has_name():
            print(f"{indent}Name: {node.name}")
        else:
            print(f"{indent}ID: {node.id}")
            
        for child in node.childs:
            walk_resources(child, level + 1)
    
    walk_resources(binary.resources)
    
    # Find version information
    for resource in binary.resources.childs:
        if resource.id == 16:  # RT_VERSION
            version_data = ResourceVersion(resource.childs[0].childs[0])
            print(f"File version: {version_data.key}")

Code Signing

Analyze and verify Authenticode signatures with certificate chain validation.

class Signature(lief.Object):
    version: int
    digest_algorithm: ALGORITHMS
    content_info: ContentInfo
    certificates: Iterator[x509]
    signers: Iterator[SignerInfo]
    
    def find_crt_subject(self, subject: str) -> Optional[x509]
    def find_crt_issuer(self, issuer: str) -> Optional[x509]
    def check(self, checks: VERIFICATION_CHECKS = VERIFICATION_CHECKS.DEFAULT) -> VERIFICATION_FLAGS

class ContentInfo(lief.Object):
    content_type: str
    digest: memoryview

class SignerInfo(lief.Object):
    version: int
    issuer: str
    serial_number: memoryview
    digest_algorithm: ALGORITHMS
    signature_algorithm: ALGORITHMS
    encrypted_digest: memoryview

enum VERIFICATION_FLAGS:
    OK = 0
    INVALID_SIGNATURE = 1
    UNSUPPORTED_ALGORITHM = 2
    INCONSISTENT_DIGEST_ALGORITHM = 4
    CERT_NOT_FOUND = 8
    CORRUPTED_CONTENT_INFO = 16
    CORRUPTED_AUTH_DATA = 32
    MISSING_PKCS9_MESSAGE_DIGEST = 64
    BAD_DIGEST = 128
    BAD_SIGNATURE = 256
    NO_SIGNATURE = 512
    CERT_EXPIRED = 1024
    CERT_FUTURE = 2048

enum ALGORITHMS:
    UNKNOWN = 0
    SHA_1 = 1
    SHA_256 = 2
    SHA_384 = 3
    SHA_512 = 4
    MD5 = 5

Usage example:

binary = PE.parse("C:\\Windows\\System32\\kernel32.dll")

# Check for signatures
if binary.has_signature():
    for signature in binary.signatures:
        print(f"Signature version: {signature.version}")
        print(f"Digest algorithm: {signature.digest_algorithm}")
        
        # Check certificate chain
        for cert in signature.certificates:
            print(f"Certificate subject: {cert.subject}")
            print(f"Certificate issuer: {cert.issuer}")
            
        # Verify signature
        verification = signature.check()
        if verification == PE.VERIFICATION_FLAGS.OK:
            print("Signature verification: VALID")
        else:
            print(f"Signature verification: INVALID ({verification})")

Types

class Section(lief.Section):
    characteristics: SECTION_CHARACTERISTICS
    virtual_size: int
    pointer_to_relocations: int
    pointer_to_line_numbers: int
    number_of_relocations: int
    number_of_line_numbers: int
    
    def has_characteristic(self, characteristic: SECTION_CHARACTERISTICS) -> bool

enum SECTION_CHARACTERISTICS:
    IMAGE_SCN_TYPE_NO_PAD = 0x00000008
    IMAGE_SCN_CNT_CODE = 0x00000020
    IMAGE_SCN_CNT_INITIALIZED_DATA = 0x00000040
    IMAGE_SCN_CNT_UNINITIALIZED_DATA = 0x00000080
    IMAGE_SCN_LNK_OTHER = 0x00000100
    IMAGE_SCN_LNK_INFO = 0x00000200
    IMAGE_SCN_LNK_REMOVE = 0x00000800
    IMAGE_SCN_LNK_COMDAT = 0x00001000
    IMAGE_SCN_NO_DEFER_SPEC_EXC = 0x00004000
    IMAGE_SCN_GPREL = 0x00008000  
    IMAGE_SCN_MEM_FARDATA = 0x00008000
    IMAGE_SCN_MEM_PURGEABLE = 0x00020000
    IMAGE_SCN_MEM_16BIT = 0x00020000
    IMAGE_SCN_MEM_LOCKED = 0x00040000
    IMAGE_SCN_MEM_PRELOAD = 0x00080000
    IMAGE_SCN_ALIGN_1BYTES = 0x00100000
    IMAGE_SCN_ALIGN_2BYTES = 0x00200000
    IMAGE_SCN_ALIGN_4BYTES = 0x00300000
    IMAGE_SCN_ALIGN_8BYTES = 0x00400000
    IMAGE_SCN_ALIGN_16BYTES = 0x00500000
    IMAGE_SCN_ALIGN_32BYTES = 0x00600000
    IMAGE_SCN_ALIGN_64BYTES = 0x00700000
    IMAGE_SCN_ALIGN_128BYTES = 0x00800000
    IMAGE_SCN_ALIGN_256BYTES = 0x00900000
    IMAGE_SCN_ALIGN_512BYTES = 0x00A00000
    IMAGE_SCN_ALIGN_1024BYTES = 0x00B00000
    IMAGE_SCN_ALIGN_2048BYTES = 0x00C00000
    IMAGE_SCN_ALIGN_4096BYTES = 0x00D00000
    IMAGE_SCN_ALIGN_8192BYTES = 0x00E00000
    IMAGE_SCN_LNK_NRELOC_OVFL = 0x01000000
    IMAGE_SCN_MEM_DISCARDABLE = 0x02000000
    IMAGE_SCN_MEM_NOT_CACHED = 0x04000000
    IMAGE_SCN_MEM_NOT_PAGED = 0x08000000
    IMAGE_SCN_MEM_SHARED = 0x10000000
    IMAGE_SCN_MEM_EXECUTE = 0x20000000
    IMAGE_SCN_MEM_READ = 0x40000000
    IMAGE_SCN_MEM_WRITE = 0x80000000

class TLS(lief.Object):
    callbacks: List[int]
    addressof_index: int
    addressof_callbacks: int
    sizeof_zero_fill: int
    characteristics: int
    data_template: memoryview
    section: Section

class LoadConfiguration(lief.Object):
    version: WIN_VERSION
    characteristics: int
    timedatestamp: int
    major_version: int
    minor_version: int
    global_flags_clear: int
    global_flags_set: int
    critical_section_default_timeout: int
    decommit_free_block_threshold: int
    decommit_total_free_threshold: int
    lock_prefix_table: int
    maximum_allocation_size: int
    virtual_memory_threshold: int
    process_affinity_mask: int
    process_heap_flags: int
    csd_version: int
    dependent_load_flags: int
    editlist: int
    security_cookie: int
    guard_cf_check_function_pointer: int
    guard_cf_dispatch_function_pointer: int
    guard_cf_function_table: int
    guard_cf_function_count: int
    guard_flags: int

class RichHeader(lief.Object):
    key: int
    entries: Iterator[RichEntry]

class RichEntry(lief.Object):
    id: int
    build_id: int
    count: int

Install with Tessl CLI

npx tessl i tessl/pypi-lief

docs

android-formats.md

assembly-engine.md

core-operations.md

debug-info.md

elf-format.md

extended-features.md

index.md

macho-format.md

pe-format.md

tile.json