Library to instrument executable formats including ELF, PE, Mach-O, and Android formats
—
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.
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 = 1Usage 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-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()}")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 = 9Usage 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}")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}")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: memoryviewUsage 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}")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 = 5Usage 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})")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: intInstall with Tessl CLI
npx tessl i tessl/pypi-lief