Changelog

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

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.LOGGING_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:
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:

Documentation

Integration:

Acknowledgements

0.6.0 - March 30, 2017

First public release