PE


Introduction

import lief

# Using filepath
pe: lief.PE.Binary = lief.PE.parse(r"C:\Users\test.exe")

# Using a Path from pathlib
pe: lief.PE.Binary = lief.PE.parse(pathlib.Path(r"C:\Users\test.exe"))

# Using an io object
with open(r"C:\Users\test.exe", 'rb') as f:
  pe: lief.PE.Binary = lief.PE.parse(f)

Note

In Python, you can also use the generic lief.parse(), which returns a lief.PE.Binary object.

With the parsed PE binary, you can use the API to inspect or modify the binary itself.
pe: lief.PE.Binary = ...

print(pe.rich_header)
print(pe.authentihash_md5.hex(':'))

for section in pe.sections:
    print(section.name, len(section.content))
pe: lief.PE.Binary = ...

section = lief.PE.Section(".hello")
section.content = [0xCC] * 0x100
pe.add_section(section)

pe.write("new.exe")

Advanced Parsing/Writing

Warning

parser_config = lief.PE.ParserConfig()
parser_config.parse_signature = False

pe: lief.PE.Binary = lief.PE.parse("some.exe", parser_config)

builder_config = lief.PE.Builder.config_t()
builder_config.imports = True

pe.write("new.exe", builder_config)
pe: lief.PE.Binary = ...
new_pe: bytes = pe.write_to_bytes()

PDB Support

For more details regarding PDB support, please refer to the PDB section.

Authenticode

LIEF supports PE Authenticode by providing an API for inspecting and verifying PE executable signatures.

Note

Typically, a signed PE executable contains a single signature, but the format allows for multiple signatures. Consequently, returns an iterator rather than a single signature object.
import lief

pe = lief.PE.parse("signed.exe")
for signature in pe.signatures:
    for crt in signature.certificates:
      print(crt)

assert pe.verify_signature() == lief.PE.Signature.VERIFICATION_FLAGS.OK

You can find additional details about Authenticode support in this tutorial: PE Authenticode