Changelog

0.15.1 - July 23th, 2024

MachO:
  • Fix missing commit for .hwx support

0.15.0 - July 21th, 2024

Extended:
Repo:
  • master branch has been renamed main

Rust:
  • First (beta) release of the bindings (c.f. Rust)

ELF:
PE:
MachO:
CMake:
  • LIEFConfig.cmake is now installed in <prefix>/lib/cmake/LIEF/ instead of <prefix>/share/LIEF/cmake/

Python Bindings:

Warning

These warnings does not necessarily mean that LIEF leak objects. These warnings might happen in Cyclic garbage collection.

Documentation:
  • Add icons

  • Include inheritance diagram for Python API (e.g. lief.ELF.Note)

0.14.1 - February 11th, 2024

ELF:
  • Fix regression in Symbol Version Definition processing (#1014)

PE:
Python:
  • Fix regression in iterator’s performances

0.14.0 - January 20, 2024

ELF:
  • Add support for the GNU note properies (#975).

    Example:
    elf = lief.ELF.parse("...")
    note = elf.get(lief.ELF.Note.TYPE.GNU_PROPERTY_TYPE_0)
    aarch64_feat: lief.ELF.AArch64Feature = note.find(lief.ELF.NoteGnuProperty.Property.TYPE.AARCH64_FEATURES)
    if lief.ELF.AArch64Feature.FEATURE.BTI in aarch64_feat.features:
        print("BTI supported")
    

    See:

  • Refactoring of the ELF note processing

  • Fix relocation issue when using -Wl,--emit-relocs (c.f. #897 / #898 by adamjseitz)

  • Improve the computation of the dynamic symbols thanks to adamjseitz (c.f. #922)

  • Add support for the LoongArch architecture thanks to loongson-zn (c.f. #921)

  • Add a lief.ELF.ParserConfig interface that can be used to tweak which parts of the ELF format should be parsed.

    Example:
    config = lief.ELF.ParserConfig()
    
    # Skip parsing static and dynamic symbols
    config.parse_static_symbols = False
    config.parse_dyn_symbols = False
    
    elf = lief.ELF.parse("target.elf", config)
    
MachO:
PE:
  • RESOURCE_SUBLANGS has been removed

  • RESOURCE_LANGS is now defined in a dedicated header: LIEF/PE/resources/langs.hpp

  • RESOURCE_TYPES is now scoped in ResourcesManager::TYPE

  • GUARD_CF_FLAGS is now scoped as IMAGE_GUARD in lief.PE.LoadConfigurationV1

  • SECTION_CHARACTERISTICS is now scoped within the Section class instead of being globally defined:

    # Before
    lief.PE.SECTION_CHARACTERISTICS.CNT_CODE
    # Now:
    lief.PE.Section.CHARACTERISTICS.CNT_CODE
    
  • DATA_DIRECTORY is now scoped within the DataDirectory class instead of being globally defined:

    # Before
    lief.PE.DATA_DIRECTORY.IAT
    # Now:
    lief.PE.DataDirectory.TYPES.IAT
    
  • MACHINE_TYPES and HEADER_CHARACTERISTICS are now scoped within the Header class instead of being globally defined:

    # Before
    lief.PE.MACHINE_TYPES.AMD64
    # Now:
    lief.PE.Header.MACHINE_TYPES.AMD64
    
  • lief.PE.Header.characteristics now returns a list/std::vector instead of a set.

  • lief.PE.OptionalHeader.dll_characteristics_lists now returns a list/std::vector instead of a set.

  • SUBSYSTEM and DLL_CHARACTERISTICS are now scoped within the OptionalHeader class instead of being globally defined:

    # Before
    lief.PE.SUBSYSTEM.NATIVE
    # Now:
    lief.PE.OptionalHeader.SUBSYSTEM.NATIVE
    
  • lief.PE.DosHeader.used_bytes_in_the_last_page has been renamed in lief.PE.DosHeader.used_bytes_in_last_page

  • Refactoring of the Debug directory processing: lief.PE.Debug is now the root class of: lief.PE.CodeView / lief.PE.CodeView, lief.PE.Pogo, lief.PE.Repro.

    The parsing logic has been cleaned and the tests updated.

  • Add a lief.PE.ParserConfig interface that can be used to tweak which parts of the PE format should be parsed (#839).

    Example:
    config = lief.PE.ParserConfig()
    
    # Skip parsing PE authenticode
    config.parse_signature = False
    
    pe = lief.PE.parse("pe.exe", config)
    
Abstraction:
  • LIEF::EXE_FORMATS is now scoped in LIEF::Binary::FORMATS

  • All the Binary classes now implement classof:

    std::unique_ptr<LIEF::Binary> bin = LIEF::Parser::parse("...");
    if (LIEF::PE::Binary::classof(bin.get())) {
      auto& pe_file = static_cast<LIEF::PE::Binary&>(*bin);
    }
    
General Design:
  • Python parser functions (like: lief.PE.parse()) now accept os.PathLike arguments like pathlib.Path (#974).

  • Remove the lief.Binary.name attribute

  • LIEF is now compiled with C++17 (the API remains C++11 compliant)

  • Switch to nanobind for the Python bindings.

  • CI are now more efficient.

  • The Python documentation for properties now contains the type of the property.

0.13.2 - June 17, 2023

PE:

Fix authenticode inconsitency (#932)

ELF:

Fix missing undef (#929)

0.13.1 - May 28, 2023

PE:
  • Fix PE authenticode verification issue in the case of special characters (#912)

Misc:
  • Fix mypy stubs (#909)

  • Fix missing include (#918)

  • Fix C99 comments (#916)

  • Fix AArch64 docker image (#904)

0.13.0 - April 9, 2023

ELF:
  • Fix overflow issue in segments (c.f. #845 found by liyansong2018)

  • Fix missing relationship between symbols and sections (c.f. #841)

  • Fix coredump parsing issue (c.f. #830 found by Lan1keA)

  • Fix and (re)enable removing dynamic symbols (c.f. #828)

  • Add support for NT_GNU_BUILD_ATTRIBUTE_OPEN and NT_GNU_BUILD_ATTRIBUTE_FUNC (c.f. #816)

  • [CVE-2022-38497] Fix ELF core parsing issue (#766 found by CCWANG19)

  • [CVE-2022-38306] Fix a heap overflow found by CCWANG19 (#763)

  • aeflores fixed an issue when there are multiple versions associated with a symbol (see: #749 for the details).

  • Handle binaries compiled with the -static-pie flag correctly (see: #747)

  • Add support for modifying section-less binaries. The ELF Section objects gain the lief.ELF.Section.as_frame() method which defines the section as a framed section.

    A framed section is a section that concretely does not wraps data and can be corrupted.

    Example:
    elf = lief.parse("/bin/ssh")
    text = elf.get_section(".text").as_frame()
    
    # We can now corrupt all the fields of the section
    text.offset  = 0xdeadc0de
    text.size    = 0xffffff
    text.address = 0x123
    
    elf.write("/tmp/out")
    
  • Add API to precisely define how the segments table should be relocated. One might want to enforce a certain ELF layout while adding sections/ segments. It is now possible to call the method: relocate_phdr_table() to define how the segments table should be relocated for welcoming the new sections/segments:

    elf = lief.parse("...")
    # Enforce a specific relocation type:
    # The new segments table will be shift at the end
    # of the file
    elf.relocate_phdr_table(Binary.PHDR_RELOC.FILE_END)
    
    # Add sections/segments
    # [...]
    elf.write("out.elf")
    

    See:

MachO:
  • Add rpaths iterator (#291)

  • Add support for parsing Mach-O in memory

  • Fix a memory issue (found by bladchan via #806)

  • [CVE-2022-40923] Fix parsing issue (#784 found by bladchan)

  • [CVE-2022-40922] Fix parsing issue (#781 found by bladchan)

  • [CVE-2022-38307] Fix a segfault when the Mach-O binary does not have segments (found by CCWANG19 via #764)

  • Enable to create exports

  • Fix the layout of the binaries modified by LIEF such as they can be (re)signed.

  • Add support for LC_DYLD_CHAINED_FIXUPS and LC_DYLD_EXPORTS_TRIE

  • Global enhancement when modifying the __LINKEDIT content

  • Add API to get a Section from a specified segment’s name and section’s name.

Example:
sec = bin.get_section("__DATA", "__objc_metadata")
  • Add API to remove a Section from a specified segment’s name and section’s name.

Example:
sec = bin.remove_section("__DATA", "__objc_metadata")
PE:
  • The Python API now returns bytes objects instead of List[int]

  • Remove lief.PE.ResourceNode.sort_by_id()

  • Fix the ordering of children of ResourceNode

  • Remove deprecated functions related to PE hooking.

  • Add support for new PE LoadConfiguration structures.

DEX:
  • Fix multiple parsing issues raised by bladchan

Other:
General Design:
  • ZehMatt added the support to write LIEF binaries object through a std::ostream interface (9d55f53)

  • Remove the exceptions

  • The library contains less static initializers which should improve the loading time.

Python Bindings:
  • Move to a build system compliant with pyproject.toml

  • Provide typing stubs: #650

  • PyPI releases no longer provide source distribution (sdist)

Dependencies:
  • Move to spdlog 1.11.0

  • Move to Pybind11 - 2.10.1

  • Move to nlohmann/json 3.11.2

  • Move to MbedTLS 3.2.1

  • Move to utfcpp 3.2.1

0.12.3 - November 1, 2022

This release contains several security fixes:

  • [CVE-2022-38497] Fix ELF core parsing issue (#766 found by CCWANG19)

  • [CVE-2022-38306] Fix a heap overflow found by CCWANG19 (#763)

  • Fix a memory issue (found by bladchan via #806)

  • [CVE-2022-40923] Fix parsing issue (#784 found by bladchan)

  • [CVE-2022-40922] Fix parsing issue (#781 found by bladchan)

  • [CVE-2022-38307] Fix a segfault when the Mach-O binary does not have segments (found by CCWANG19 via #764)

0.12.1 - April 08, 2022

ELF:
  • Fix section inclusion calculations (#692)

PE:
Compilation:

0.12.0 - March 25, 2022

ELF:
MachO:
  • Change the layout of the binaries generated by LIEF such as they are compliant with codesign checks

  • The API to configure the MachO parser has been redesigned to provide a better granularity

    config = lief.MachO.ParserConfig()
    config.parse_dyld_bindings = False
    config.parse_dyld_exports  = True
    config.parse_dyld_rebases  = False
    
    lief.MachO.parse("/tmp/big.macho", config)
    
  • LucaMoroSyn added the support for the LC_FILESET_ENTRY. This command is usually found in kernel cache files

  • LIEF::MachO::Binary::get_symbol now returns a pointer (instead of a reference). If the symbol can’t be found, it returns a nullptr.

  • Add API to select a Binary from a FatBinary by its architecture. See: lief.MachO.FatBinary.take().

    fat = lief.MachO.parse("/bin/ls")
    fit = fat.take(lief.MachO.CPU_TYPES.x86_64)
    
  • Handle the 0x0D binding opcode (see: #524)

  • xhochy fixed performances issues in the Mach-O parser (see #579)

PE:
DEX:
Abstraction:
Compilation & Integration:
  • ekilmer updated and modernized the CMake integration files through the PR: #674

  • Enable to use a pre-compiled version of spdlog. This feature aims at improving compilation time when developing on LIEF.

    One can provide path to spdlog install through:

    $ python ./setup.py --spdlog-dir=path/to/lib/cmake/spdlog [...]
    # or
    $ cmake -DLIEF_EXTERNAL_SPDLOG=ON -Dspdlog_DIR=path/to/lib/cmake/spdlog ...
    
  • Enable to feed LIEF’s dependencies externally (c.f. Third Party)

  • Replace the keywords and, or, not with &&, || and !.

Dependencies:
  • Upgrade to MbedTLS 3.1.0

  • Upgrade Catch2 to 2.13.8

  • The different dependencies can be linked externally (cf. above and Third Party)

Documentation:
  • New section about the errors handling (Error Handling) and the upcoming deprecation of the exceptions.

  • New section about how to compile LIEF for debugging/developing. See: Debugging

General Design:
span:

LIEF now exposes Section/Segment’s data through a span interface. As std::span is available in the STL from C++20 and the LIEF public API aims at being C++11 compliant, we expose this span thanks to tcbrindle/span. This new interface enables to avoid copies of std::vector<uint8_t> which can be costly. With this new interface, the original std::vector<uint8_t> can be retrieved as follows:

auto bin = LIEF::ELF::Parser::parse("/bin/ls");

if (const auto* section = bin->get_section(".text")) {
  LIEF::span<const uint8_t> text_ref =  section->content();
  std::vector<uint8_t> copy = {std::begin(text_ref), std::end(text_ref)};
}

In Python, span are wrapped by a read-only memory view. The original list of bytes can be retrieved as follows:

bin = lief.parse("/bin/ls")
section = bin.get_section(".text")

if section is not None:
  memory_view = section.content
  list_of_bytes = list(memory_view)
Exceptions:

Warning

We started to refactor the API and the internal design to remove C++ exceptions. These changes are described a the dedicated blog (LIEF RTTI & Exceptions)

To highlighting the content of the blog for the end users, functions that returned a reference and which threw an exception in the case of a failure are now returning a pointer that is set to nullptr in the case of a failure.

If we consider this original code:

LIEF::MachO::Binary& bin = ...;

try {
  LIEF::MachO::UUIDCommand& cmd = bin.uuid();
  std::cout << cmd << "\n";
} catch (const LIEF::not_found&) {
  // ... dedicated processing
}

// Other option with has_uuid()
if (bin.has_uuid()) {
  LIEF::MachO::UUIDCommand& cmd = bin.uuid();
  std::cout << cmd << "\n";
}

It can now be written as:

LIEF::MachO::Binary& bin = ...;

if (LIEF::MachO::UUIDCommand* cmd = bin.uuid();) {
  std::cout << *cmd << "\n";
} else {
  // ... dedicated processing as it is a nullptr
}

// Other option with has_uuid()
if (bin.has_uuid()) { // It ensures that it is not a nullptr
  LIEF::MachO::UUIDCommand& cmd = *bin.uuid();
  std::cout << cmd << "\n";
}

0.11.X - Patch Releases

0.11.5 - May 22, 2021

  • Remove usage of not in public headers (b8e825b)

ELF:
PE:
MachO:

0.11.4 - March 09, 2021

PE:
  • Fix missing bound check when computing the authentihash

0.11.3 - March 03, 2021

PE:
  • Add sanity check on the signature’s length that could lead to a std::bad_alloc exception

0.11.2 - February 24, 2021

PE:
  • Fix regression in the behavior of the PE section’s name. One can now access the full section’s name (with trailing bytes) through lief.PE.Section.fullname (see: #551)

0.11.1 - February 22, 2021

PE:

0.11.0 - January 19, 2021

ELF:
  • mkomet updated enums related to Android (see: 9dd641d)

  • aeflores added MIPS relocations support in the ELF parser

  • Fix extend() on a ELF section (cf. issue #477)

  • Fix issue when exporting symbols on empty-gnu-hash ELF binary (1381f9a)

  • Fix reconstruction issue when the binary is prelinked (cf. issue #466)

  • Add DF_1_PIE flag

  • Fix parsing issue of the .eh_frame section when the base address is not 0.

  • JanuszL enhanced the algorithm that computes the string table. It moves from a N^2 algorithm to a Nlog(N) (1e0c4e8).

  • Fix .eh_frame parsing issue (b57f323)

  • aeflores fixed parsing issue in ELF relocations (6c53646)

  • Add PT_GNU_PROPERTY enum

  • Bug fix in the symbols table reconstruction (ELF)

PE:
  • Enhance PE Authenticode. See PE Authenticode

  • get_imphash() can now generate the same value as pefile and Virus Total (#299)

    pe = lief.parse("example.exe")
    vt_imphash = lief.PE.get_imphash(pe, lief.PE.IMPHASH_MODE.PEFILE)
    lief_imphash = lief.PE.get_imphash(pe, lief.PE.IMPHASH_MODE.DEFAULT)
    
  • Remove the padding entry (0) from the rich header

  • items now returns a dictionary for which the values are bytes (instead of str object). This change is related to utf-16 support.

  • kohnakagawa fixed wrong enums values: c031250, 6ee808a, cd05f34

  • kohnakagawa fixed a bug in the PE resources parser (a7254d1)

  • Handle PE forwarded exports (issue #307)

Mach-O:
  • Add API to access either LC_CODE_SIGNATURE or DYLIB_CODE_SIGN_DRS (issue #476)

  • Fix issue when parsing twice a Mach-O file (issue #479)

Dependencies:
  • Replace easyloggingpp with spdlog 1.8.1

  • Upgrade frozen to 1.0.0

  • Upgrade json to 3.7.3

  • Upgrade pybind11 to 2.6.0

  • Upgrade mbedtls to 2.16.6

Documentation:
  • aguinet updated the bin2lib tutorial with the support of the new glibc versions (7884e57)

  • Global update and enable to build the documentation out-of-tree

  • Changing the theme

Misc:
  • Add Python 3.9 support

  • FindLIEF.cmake deprecates LIEF_ROOT. You should use LIEF_DIR instead.

Logging:

We changed the logging interface. The following log levels have been removed:

  • LOG_GLOBAL

  • LOG_FATAL

  • LOG_VERBOSE

  • LOG_UNKNOWN

We also moved from an class-interface based to functions.

Example:

lief.logging.disable()
lief.logging.enable()
lief.logging.set_level(lief.logging.LEVEL.INFO)

See: lief.logging.set_level()

Note

The log functions now output on stderr instead of stdout

0.10.1 - November 29, 2019

  • Fix regression in parsing Python bytes

  • Add Python API to demangle strings: lief.demangle

0.10.0 - November 24, 2019

ELF:
  • Add build support for ELF notes

  • Add coredump support (9fc3a8a)

  • Enable to bind a relocation with a symbol (a9f3cb8)

    Example:
    relocation = "..."
    
    symbol = lief.ELF.Symbol()
    symbol.name = "printf123"
    relocation.symbol = symbol
    
  • Add constructors (67d924a)

  • Expose ELF destructors (957384c)

  • Add remove_static_symbol (c677970)

  • Add support for static relocation writing (d1b98d6)

  • Expose function to get strings located in the .rodata section (02f4851)

  • Export ELF ABI version (8d7ec26)

PE:
  • Improve PE Authenticode parsing (535623d)

  • Fix alignment issue when removing a PE section (04dddd3)

  • Parse PE debug data directory as a list of debug entries (by 1orenz0 - fcc75dd)

  • Add support to parse POGO debug entries (by 1orenz0 - 3537440)

Mach-O:
  • Enhance Mach-O modifications by exposing an API to:

    • Add load commands

    • Add sections

    • Add segments

    See: 406115c

  • Enable write() on FAT Mach-O (1659531)

  • Introduce Mach-O Build Version command (6f96723)

  • Enable to remove Mach-O symbols (616d739)

  • Add support for adding LC_UNIXTHREAD commands in a MachO (by nezetic - 64d2597)

Abstract Layer:
  • Expose remove_section() in the abstract layer (918438c)

  • Expose write() in the abstract layer (af4d48e)

  • Expose API to list functions found in a binary (b5a0846)

Android:
  • Add partial support for Android 9 (bce9ebe)

Misc:
  • lkollar added support for Python 3.8 in CI (Linux & OSX only)

  • Update Pybind11 dependency to v2.4.3

  • Enhance Python install

  • Thanks to lkollar, Linux CI now produces manylinux1-compliant wheels

Many thanks to the contributors: recvfrom, pbrunet, mackncheesiest, wisk, nezetic, lkollar, jbremer, DaLynX, 1orenz0, breadchris, 0xbf00, unratito, strazzere, aguinetqb, mingwandroid, serge-sans-paille-qb, yrp604, majin42, KOLANICH

0.9.0 - June 11, 2018

LIEF 0.9 comes with new formats related to Android: OAT, DEX, VDEX and ART. It also fixes bugs and thanks to yd0b0N, ELF parser now supports big and little endian binaries. We also completed the JSON serialization of LIEF objects.

Features

MachO:
PE:
ELF:
  • Add support for .note.android.ident section: d13db18

  • Enable to add unlimited number of dynamic entries: a40da3e

  • Add support for PPC relocations: 08b5141

  • Endianness support: e794ac1

API

  • lief.breakp() and lief.shell()

  • lief.parse() now support io streams as input

  • Parser now returns a std::unique_ptr instead of a raw pointer: cd1cc45

Misc

  • Use frozen for some internal std::map (If C++14 is supported by the compiler)

Acknowledgements

0.8.3

  • [Mach-O] Fix typo on comparison operator - abbc264

0.8.2

  • [ELF] Increase the upper limit of relocation number - 077bc32

0.8.1 - October 18, 2017

  • Fix an alignment issue in the ELF builder. See 8db199c

  • Add assertion on the setuptools version: 62e5825

0.8.0 - October 16, 2017

LIEF 0.8.0 mainly improves the MachO parser and the ELF builder. It comes with Dockerfiles for CentOS and Android.

LibFuzzer has also been integrated in the project to enhance the parsers

Features

Abstract Layer:
ELF:
  • DT_FLAGS and DT_FLAGS_1 are now parsed into DynamicEntryFlags - 754b8af

  • Handle relocations of object files (.o) - 483b8dc

  • Global enhancement of the ELF builder:

    One can now add multiple Section or Segment into an ELF:

    elf = lief.parse("/bin/cat")
    
    for i in range(3):
      segment = Segment()
      segment.type = SEGMENT_TYPES.LOAD
      segment.content = [i & 0xFF] * 0x1000
      elf += segment
    
    
    for i in range(3):
      section = Section("lief_{:02d}".format(i))
      section.content = [i & 0xFF] * 0x1000
      elf += section
    
    elf.write("foo")
    
    $ readelf -l ./foo
    PHDR           0x0000000000000040 0x0000000000000040 0x0000000000000040
                   0x00000000000061f8 0x00000000000061f8  R E    0x8
    INTERP         0x0000000000006238 0x0000000000006238 0x0000000000006238
                   0x000000000000001c 0x000000000000001c  R      0x1
        [Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]
    LOAD           0x0000000000000000 0x0000000000000000 0x0000000000000000
                   0x000000000000d6d4 0x000000000000d6d4  R E    0x200000
    LOAD           0x000000000000da90 0x000000000020da90 0x000000000020da90
                   0x0000000000000630 0x00000000000007d0  RW     0x200000
    LOAD           0x000000000000f000 0x000000000040f000 0x000000000040f000
                   0x0000000000001000 0x0000000000001000         0x1000
    LOAD           0x0000000000010000 0x0000000000810000 0x0000000000810000
                   0x0000000000001000 0x0000000000001000         0x1000
    LOAD           0x0000000000011000 0x0000000001011000 0x0000000001011000
                   0x0000000000001000 0x0000000000001000         0x1000
    ....
    
    $ readelf -S ./foo
    ...
    [27] lief_00           PROGBITS         0000000002012000  00012000
         0000000000001000  0000000000000000           0     0     4096
    [28] lief_01           PROGBITS         0000000004013000  00013000
         0000000000001000  0000000000000000           0     0     4096
    [29] lief_02           PROGBITS         0000000008014000  00014000
         0000000000001000  0000000000000000           0     0     4096
    

    Warning

    There are issues with executables statically linked with libraries that use TLS

    See: #98

    One can now add multiple entries in the dynamic table:

    elf = lief.parse("/bin/cat")
    
    elf.add_library("libfoo.so")
    elf.add(DynamicEntryRunPath("$ORIGIN"))
    elf.add(DynamicEntry(DYNAMIC_TAGS.INIT, 123))
    elf.add(DynamicSharedObject("libbar.so"))
    
    elf.write("foo")
    
    $ readelf -d foo
      0x0000000000000001 (NEEDED)  Shared library: [libfoo.so]
      0x0000000000000001 (NEEDED)  Shared library: [libc.so.6]
      0x000000000000000c (INIT)    0x7b
      0x000000000000000c (INIT)    0x3600
      ...
      0x000000000000001d (RUNPATH) Bibliothèque runpath:[$ORIGIN]
      0x000000000000000e (SONAME)  Bibliothèque soname: [libbar.so]
    

    See b94900c, 1e410e6 for details.

  • b2d3694 enables modification of the ELF interpreter without length restriction

    elf = lief.parse("/bin/cat")
    elf.interpreter = "/a/very/long/path/to/another/interpreter"
    elf.write("foo")
    
    $ readelf -l foo
    Program Headers:
    Type           Offset             VirtAddr           PhysAddr
                   FileSiz            MemSiz              Flags  Align
    PHDR           0x0000000000000040 0x0000000000000040 0x0000000000000040
                   0x00000000000011f8 0x00000000000011f8  R E    0x8
    INTERP         0x000000000000a000 0x000000000040a000 0x000000000040a000
                   0x0000000000001000 0x0000000000001000  R      0x1
        [Requesting program interpreter: /a/very/long/path/to/another/interpreter]
    ....
    
  • Enhancement of the dynamic symbols counting - 985d124

  • Enable editing ELF’s notes:

    elf = lief.parse("/bin/ls")
    build_id = elf[NOTE_TYPES.BUILD_ID]
    build_id.description = [0xFF] * 20
    elf.write("foo")
    
    $ readelf -n foo
    Displaying notes found in: .note.gnu.build-id
    Owner                 Data size Description
    GNU                  0x00000014 NT_GNU_BUILD_ID (unique build ID bitstring)
      Build ID: ffffffffffffffffffffffffffffffffffffffff
    

    See commit 3be9dd0 for more details

PE:
  • Add get_imphash() and resolve_ordinals() functions - a89bc6d, dfa8e98

  • Parse the Load Config Table into LoadConfiguration (up to Windows 10 SDK 15002 with hotpatch_table_offset)

    from lief import to_json
    import json
    pe = lief.parse("some.exe")
    loadconfig = to_json(pe.load_configuration)) # Using the lief.to_json function
    pprint(json.loads(to_json(loadconfig)))
    
    {'characteristics': 248,
     'code_integrity': {'catalog': 0,
                        'catalog_offset': 0,
                        'flags': 0,
                        'reserved': 0},
     'critical_section_default_timeout': 0,
     'csd_version': 0,
     'editlist': 0,
     ...
     'guard_cf_check_function_pointer': 5368782848,
     'guard_cf_dispatch_function_pointer': 5368782864,
     'guard_cf_function_count': 15,
     'guard_cf_function_table': 5368778752,
     'guard_flags': 66816,
     'guard_long_jump_target_count': 0,
     'guard_long_jump_target_table': 0,
     'guard_rf_failure_routine': 5368713280,
     'guard_rf_failure_routine_function_pointer': 5368782880,
     ...
    

    For details, see commit: 0234e3b

MachO:

Fixes

Fix enums conflicts(#32) - 66b4cd4

Fix most of the memory leaks: 88dafa8, d9b1436, 554fa15, 3602643

ELF:
  • Bug Fix when counting dynamic symbols from the GnuHash Table - 9036a24

PE:
  • Fix nullptr dereference in resources - e90fe1b

  • Handle encoding issues in the Python API - 8c7ceaf

  • Sanitize DLL names

MachO:
  • Fix #87, #92

  • Fix memory leaks and some performance issues: #94

API

In the C++ API get_XXX() getters have been renamed into XXX() (e.g. get_header() becomes header()) - a4c69f7, e805669

Abstract:
ELF:
PE:
MachO:
Logging:

Add an API to configure the logger - 4600c2b

Example:

from lief import Logger
Logger.disable()
Logger.enable()
Logger.set_level(lief.LEVEL.INFO)

See: lief.Logger

Build system

Documentation

References:
  • recomposer, bearparser, IAT_patcher, PEframe, Manalyze, MachOView, elf-dissector

Acknowledgements

0.7.0 - July 3, 2017

Features

Abstract Layer:
  • Add bitness (32bits / 64bits) - 78d1adb

  • Add object type (Library, executable etc) - 78d1adb

  • Add mode Thumbs, 16bits etc - 78d1adb

  • Add endianness - 7ea08f7, #29

ELF:
PE:
  • Parse PE Overlay - e0634c1

  • Enable PE Hooking - 24f6b72

  • Parse and rebuilt dos stub - 3f06397

  • Add a resources manager to provide an enhanced API over the resources - 8473c8e

  • Serialize PE objects into JSON - 673f5a3, #18

  • Parse Rich Header - 0893bd9, #15

Bug Fixes

ELF:
  • Bug fix when a GNU hash has empty buckets - 21a6c30

PE:
  • Bug fix in the signature parser: #30, 4af0256

  • Bug fix in the resources parser: Infinite loop - a569cc1

  • Add more out-of-bounds checks on relocations and exports - 9364f64

  • Use min(SizeOfRawData, VirtualSize) for the section’s size and truncate the size to the file size - 61bf14b

MachO:
  • Bug fix when a binary hasn’t a LC_MAIN command - 957501f

API

Abstract Layer:
ELF:
Notes:
Hash Tables:
PE:
  • lief.PE.Symbol.has_section

  • lief.PE.Binary.hook_function()

  • lief.PE.Binary.get_content_from_virtual_address() takes either an Absolute virtual address or a Relative virtual address

  • lief.PE.Binary.section_from_virtual_address has been renamed to lief.PE.Binary.section_from_rva().

  • lief.PE.parse_from_raw has been removed. One can use lief.PE.parse().

  • lief.PE.Section.data has been removed. Please use lief.PE.Section.content

Dos Stub:
Rich Header:
Overlay:
Imports:
Resources:
MachO:
UUID:
Main Command:
Dylinker:

Documentation

References:
  • elfsteem, pelook, PortEx, elfsharp, metasm, amoco, Goblin

Tutorials:
Integration:

Acknowledgements

  • ek0: #24

  • ACSC-CyberLab: #33, #34, #37, #39

  • Hyrum Anderson who pointed bugs in the PE parser

  • My collegues for the feedbacks and suggestions (Adrien, SebK, Pierrick)

0.6.1 - April 6, 2017

Bug Fixes

ELF:

API

PE:

Documentation

Integration:

Acknowledgements

0.6.0 - March 30, 2017

First public release