Skip to content

Latest commit

 

History

History
1046 lines (700 loc) · 38 KB

changelog.rst

File metadata and controls

1046 lines (700 loc) · 38 KB

Changelog

0.12.1 - Not Released Yet

ELF:
  • Fix section inclusion calculations (:pr:`692`)
PE:
Compilation:

0.12.0 - March 25, 2022

ELF:
MachO:
  • 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)
  • :github_user:`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 :class:`~lief.MachO.Binary` from a :class:`~lief.MachO.FatBinary` by its architecture. See: :meth:`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: :issue:`524`)

  • :github_user:`xhochy` fixed performances issues in the Mach-O parser (see :pr:`579`)

PE:
DEX:
Abstraction:
Compilation & Integration:
  • :github_user:`ekilmer` updated and modernized the CMake integration files through the PR: :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. :ref:`lief_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 :ref:`lief_third_party`)
Documentation:
  • New section about the errors handling (:ref:`err_handling`) and the upcoming deprecation of the exceptions.
  • New section about how to compile LIEF for debugging/developing. See: :ref:`lief_debug`
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";
}
.. seealso::

  - :ref:`C++ API for errors handling <cpp-api-error-handling>`
  - :ref:`Python API for errors handling <python-api-error-handling>`
  - `List of the functions that changed <https://gist.github.com/romainthomas/37da45b043c5f8b8db6be2767611f625>`_


0.11.X - Patch Releases

0.11.5 - May 22, 2021

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:

0.11.1 - February 22, 2021

PE:

0.11.0 - January 19, 2021

ELF:
PE:
Mach-O:
  • Add API to access either LC_CODE_SIGNATURE or DYLIB_CODE_SIGN_DRS (issue :issue:`476`)
  • Fix issue when parsing twice a Mach-O file (issue :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:
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.LOGGING_LEVEL.INFO)

See: :func:`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:
PE:
Mach-O:
Abstract Layer:
Android:
Misc:

Many thanks to the contributors: :github_user:`recvfrom`, :github_user:`pbrunet`, :github_user:`mackncheesiest`, :github_user:`wisk`, :github_user:`nezetic`, :github_user:`lkollar`, :github_user:`jbremer`, :github_user:`DaLynX`, :github_user:`1orenz0`, :github_user:`breadchris`, :github_user:`0xbf00`, :github_user:`unratito`, :github_user:`strazzere`, :github_user:`aguinetqb`, :github_user:`mingwandroid`, :github_user:`serge-sans-paille-qb`, :github_user:`yrp604`, :github_user:`majin42`, :github_user:`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 :github_user:`yd0b0N`, ELF parser now supports big and little endian binaries. We also completed the JSON serialization of LIEF objects.

Features

MachO:
PE:
ELF:

API

Misc

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

Acknowledgements

0.8.3

0.8.2

0.8.1 - October 18, 2017

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 :class:`~lief.ELF.DynamicEntryFlags` - :commit:`754b8afa2b41993e6c37d2d9003cebdccc641d23`

  • Handle relocations of object files (.o) - :commit:`483b8dc2eabee3da29ce5e5ff2e25c2a3c9ca297`

  • Global enhancement of the ELF builder:

    One can now add multiple :class:`~lief.ELF.Section` or :class:`~lief.ELF.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: :issue:`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 :commit:`b94900ca7f500912bfe249cd534055942e28e34b`, :commit:`1e410e6c950c391f0d1a3f12cb6f8e4c9fb16539` for details.

  • :commit:`b2d36940f60eacfa602c115cb542e11c70b6841c` 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 - :commit:`985d1249b72494a0e62f34042b3c9cbfa0706e90`

  • 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 :commit:`3be9dd0ff58ec68cb8813e01d6798c16b42dac22` for more details

PE:
MachO:

Fixes

Fix enums conflicts(:issue:`32`) - :commit:`66b4cd4550ecf6cf3adb4900e6ad7ac33f1f7f32`

Fix most of the memory leaks: :commit:`88dafa8db6e752393f69d73f68d295e91963b8da`, :commit:`d9b1436730b5d33a753e7dfa4301697a0c676066`, :commit:`554fa153af943b97a16fc4a52ab8459a3d0a9bc7`, :commit:`3602643f5d02a1c78c4de609cc47f193f3a8840f`

ELF:
PE:
MachO:

API

In the C++ API get_XXX() getters have been renamed into XXX() (e.g. get_header() becomes header()) - :commit:`a4c69f7868da1de5d09aa26e977dedb720e36cbd`, :commit:`e805669865b130057413f456958a471d8f0ac0b1`

Abstract:
ELF:
PE:
MachO:
Logging:

Add an API to configure the logger - :commit:`4600c2ba8d7d17b5965c2b74faeb7e4d2128de17`

Example:

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

See: :class:`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:
ELF:
PE:

Bug Fixes

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

API

Abstract Layer:
ELF:
Notes:
Hash Tables:
PE:
Dos Stub:
Rich Header:
Overlay:
Imports:
Resources:
MachO:
UUID:
Main Command:
Dylinker:

Documentation

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

Acknowledgements

0.6.1 - April 6, 2017

Bug Fixes

ELF:

API

PE:

Documentation

Integration:

Acknowledgements

0.6.0 - March 30, 2017

First public release