BinaryNinja & Ghidra Plugins
LIEF-based plugins for Binary Ninja and Ghidra have been bootstrapped here:
LIEF Tools
I initiated a Tools section which aims at providing utilities based on LIEF (mostly
CLI):
Add support for Contextual Assembly Patching
Add enum for the latest dyld shared cache version introducing
changes in the header layout (dyld-1284.13 - 2025-04-25)
uint64_t dynamicDataOffset;
uint64_t dynamicDataMaxSize;
uint32_t tproMappingsOffset;
uint32_t tproMappingsCount;
+ uint64_t functionVariantInfoAddr;
+ uint64_t functionVariantInfoSize;
+ uint64_t prewarmingDataOffset;
+ uint64_t prewarmingDataSize;
};
Add enum for the latest dyld shared cache version introducing
changes in the header layout (dyld-1231.3 - 2024-09-24)
uint64_t dynamicDataOffset;
uint64_t dynamicDataMaxSize;
+ uint32_t tproMappingsOffset;
+ uint32_t tproMappingsCount;
};
Fix symbol resolution issue: #1127
Please check LIEF 0.17.0 - PE changelog
luadebug added support for pretty printing OID value and non-roman characters in X509 certificates (see: #1226, #1219)
Initial support for the COFF format: see the COFF section
LC_FUNCTION_VARIANTS, LC_FUNCTION_VARIANT_FIXUPS)LC_NOTE)LC_ATOM_INFO)Add support for modifying Mach-O commands that embed variable-length data (#1204, #1125). See: RPath and Library Path Modification.
# Change library name
for lib in macho.libraries:
lib.name += "/some/path/lib.dylib"
# Change rpath
for rpath in macho.rpaths:
rpath.path += '/a/very/long/path/that/needs/expansion'
To void #define conflicts with Apple SDK, the following enums have been renamed:
- lief.MachO.FAT_MAGIC
+ lief.MachO.MAGIC_FAT
- lief.MachO.FAT_CIGAM
+ lief.MachO.CIGAM_FAT
- lief.MachO.Symbol.ORIGIN.LC_SYMTAB
+ lief.MachO.Symbol.ORIGIN.SYMTAB
- lief.MachO.Section.TYPE.S_4BYTE_LITERALS
+ lief.MachO.Section.TYPE.IS_4BYTE_LITERALS
- lief.MachO.Section.TYPE.S_8BYTE_LITERALS
+ lief.MachO.Section.TYPE.IS_8BYTE_LITERALS
- lief.MachO.Section.TYPE.S_16BYTE_LITERALS
+ lief.MachO.Section.TYPE.IS_16BYTE_LITERALS
- MACHO_TYPES::MH_MAGIC
- MACHO_TYPES::MH_CIGAM
- MACHO_TYPES::MH_MAGIC_64
- MACHO_TYPES::MH_CIGAM_64
- MACHO_TYPES::FAT_MAGIC
- MACHO_TYPES::FAT_CIGAM
+ MACHO_TYPES::MAGIC
+ MACHO_TYPES::CIGAM
+ MACHO_TYPES::MAGIC_64
+ MACHO_TYPES::CIGAM_64
+ MACHO_TYPES::MAGIC_FAT
+ MACHO_TYPES::CIGAM_FAT
- Section::TYPE::S_16BYTE_LITERALS
+ Section::TYPE::IS_16BYTE_LITERALS
- Section::TYPE::S_4BYTE_LITERALS
+ Section::TYPE::IS_4BYTE_LITERALS
- Section::TYPE::S_8BYTE_LITERALS
+ Section::TYPE::IS_8BYTE_LITERALS
- Symbol::ORIGIN::LC_SYMTAB
+ Symbol::ORIGIN::SYMTAB
LIEF newly-inserted sections are now compatible with a strip after the
modification of the binary (see: Adding a section/segment)
Enhance support for IA64 architecture.
Introduce lief.ELF.Segment.raw_flags to access the raw (integer)
value of the flag
Add support for SH4
Add suport for x32/ILP32 ELF binaries (#1225)
Add support for S390x
Better endianess support when writing back a binary.
Enhance support for removing or modifying symbol versions (related to the lief-patchelf initiative)
New doc section: Symbol Versions
New doc section: R[UN]PATH Modification
LIEF extended can now process DWARF debug info in PE binaries
Add support for creating DWARF: DWARF Editor
(require extended version >= 0.17.0.2623)
S_COMPILE3, S_COMPILE2, S_BUILDINFO, S_ENVBLOCK.
These symbols are exposed through the interface ,
which can be accessed using .
This metadata provides build time information such as:Module Name : * Linker *
Build Metadata:
Frontend Version: 0.0.0.0
Backend Version : 14.37.32825.0
Tool Version : Microsoft (R) LINK
Language : LINK
Target : X64
Environment:
cwd: C:\Users\romai\dev\rust\ast-grep
exe: C:\Program Files\Microsoft Visual Studio\2022\Community\[...]
pdb: C:\Users\romai\dev\rust\ast-grep\target\debug\deps\ast_grep.pdb
cmd: /NOLOGO /LIBPATH:C:\Users\romai\dev\rust\ast-grep\target\[...]
Module Name : std-4ee9ee8805e6ac55.std.ddad90bab7781587-cgu.0.rcgu.o
Object : C:\Users\romai\scoop\persist\rustup\.rustup\toolchains\[...]
Build Metadata:
Frontend Version: 1.74.0.0
Backend Version : 17004.0.0.0
Tool Version : clang LLVM (rustc version 1.74.0 (79e9716c9 2023-11-13))
Language : RUST
Target : X64
Build Info:
Current directory: /rustc/79e9716c980570bfd1f666e3b16ac583f0168962
Build tool : C:\a\rust\rust\build\x86_64-pc-windows-msvc\stage1\bin\rustc.exe
Source file : library\std\src\lib.rs\@\std.ddad90bab7781587-cgu.0
Command line : "-cc1" "--crate-name" "std" "--edition=2021" [...]
Parsing Android OAT files requires to explicitly use lief.OAT.parse()
import lief
# Before LIEF 0.17.0 this function returned a lief.OAT.Binary object
lief.parse("CallDeviceId.oat")
# Since LIEF 0.17.0 this function returns a lief.ELF.Binary object
lief.parse("CallDeviceId.oat")
# Return a lief.OAT.Binary object
lief.OAT.parse("CallDeviceId.oat")
Fix issue in the Python bindings while trying to access lief.__LIEF_MAIN_COMMIT__
Fix CMake issue with find_package(lief-extended)
Use LLVM 21.1.x
Move to tl-expected 1.2.0
Move to utfcpp 4.0.6
Move to mbedtls 3.6.4
Move to spdlog 1.15.3
Move to nlohmann/json 3.12.0
Upgrade nanobind to version v2.8.x
Relax the condition over the DT_SYMENT entry (#1177)
Add Python, Rust, SDK packages for Windows ARM64 (aarch64-pc-windows-msvc)
Add Python, Rust, SDK packages for Linux Musl ARM64 (aarch64-unknown-linux-musl)
Add Python, Rust, SDK packages for Linux Musl i686 (i686-unknown-linux-musl)
Fix export forwarding issue (#1168)
Fix truncated nlist_t.n_type when rewriting a Mach-O binary
Fix broken aarch64 Python wheel which is related to a toolchain issue
(#1146)
Various fixes from DzenIsRich & peledins-zimperium Thanks to them, Mach-O modification is more reliable.
Fix issue when building with -DLIEF_MACHO=ON (see: #1138)
Fix min-rustc version issue (see: 75a27f0)
C++
LIEF::Binary& bin;
uint16_t short_value = bin.get_int_from_virtual_address<uint16_>(0x140002CC8);
Python
some_bin: lief.Binary = ...
long_value = some_bin.get_int_from_virtual_address(0x140002CC8, 4)
# or
long_value = some_bin.get_int_from_virtual_address(0x140002CC8, ctypes.sizeof(ctypes.c_uint32))
Rust
elf: &lief::elf::Binary
let value: i16 = elf.get_int_from_virtual_address::<i16>(0x401126).unwrap();
lief.ARCHITECTURES into lief.MODES into lief.OBJECT_TYPES into lief.ENDIANNESS into Fix endianness support (#1110)
Add helpers to determine the platform targeted by a Mach-O binary:
Expose an iterator over the stub entries located in __stubs,__auth_stubs,__symbol_stub,__picsymbolstub4:
LC_SUBCLIENT command: LC_ROUTINE/LC_ROUTINE64 command: Fix authenticode error while reading RSA PKCS#1 1.5 padding
Fix issue when multiple empty strings are present in the .symtab section
(#1124)
Add support for eBPF relocations.
GNU_PROPERTY_AARCH64_FEATURE_PAUTH GNU property note:
.Fix a critical error when rewriting ELF file with DT_RELR relocations.
This error leads to a crash of the modified binary.
Fix error while (re)generating ELF’s RELR relocations (#1097)
Add support for RISC-V architecture
Fix bug when trying to remove a dynamic symbol that is associated with multiple relocations (#1089)
Mutable API are progressively introduced:
Thanks to Huntragon Rust bindings can be used without openssl (see: #1105)
Rust precompiled Linux packages are now supported for Debian 10 & Ubuntu 19.10. Before, they require at least Debian 11 & Ubuntu 20.04
Add support for the x86_64-unknown-linux-musl target which allows to
generate full static executable.
Before
@interface GCKUIImageHints<NSCopying,NSSecureCoding> {
long long _imageType;
NSObject<NSSecureCoding> * _customData;
struct CGSize _imageSize;
}
+ (bool)supportsSecureCoding:(GCKUIImageHints *)self :(SEL)id;
- (bool)isEqual:(GCKUIImageHints *)self :(SEL)id :(NSObject *)arg2;
After
@interface GCKUIImageHints<NSCopying,NSSecureCoding> {
long long _imageType;
NSObject<NSSecureCoding> * _customData;
struct CGSize _imageSize;
}
// Address: 0x00001aa448
+ (bool)supportsSecureCoding:(GCKUIImageHints *)self :(SEL)id;
// Address: 0x00001aa5ec
- (bool)isEqual:(GCKUIImageHints *)self :(SEL)id :(NSObject *)arg2;
Add DW_TAG_typedef support
Note
LIEF extended is now open to everyone
C++ SDK is now available
Rust package is now available
Initial assembler support: Assembler
Initial disassembler support: Disassembler
Linux Python wheels are now manylinux_2_27 compliants. In other words,
they are working with a glibc from at least 2018.
Support for Dyld shared cache
pe = lief.PE.parse("some.exe")
if exp := pe.get_export():
for entry in exp.entries:
# e.g.void __cdecl Platform::Details::EventSourceUninitialize(void **)
print(entry.demangled_name)
for imp in pe.imports:
for entry in imp.entries:
# e.g. void __cdecl std::_Xlength_error(char const *)
print(entry.demangled_name)
The extended version is now using a versioning matching LIEF regular version
Upgrade nanobind from 1.8.0 to 2.4.0
*.pyi stubs are now generated by nanobind (replacing mypy’s stugen)
Upgrade MbedTLS from 3.2.1 to 3.6.1
Global restructuring of the documentation
Add Sphinx cross-reference support for Rust. For instance, this link:
lief::elf::Binary::debug_info references the
documentation of debug_info in the Rust documentation page.
Fix missing commit for .hwx support
Note
Add support for DWARF: DWARF
Add support for PDB: PDB
Add support for Objective-C: Objective-C
master branch has been renamed main
First (beta) release of the bindings (c.f. Rust)
Add support to create custom notes (#1026):
elf: lief.ELF.Binary = ...
elf += lief.ELF.Note.create(
name="my-custom-note",
original_type=lief.ELF.Note.TYPE.UNKNOWN,
description=list(b"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed"),
section_name=".lief.note.custom"
)
config = lief.ELF.Builder.config_t()
config.notes = True
elf.write("/tmp/new-binary.elf", config)
Add lief.ELF.Binary.get_relocated_dynamic_array() which allows
to get a relocated view of the of init/fini entries. This function can
handy ELF init array/fini array functions are defined through relocations.
See: #1058, #626
Add support for QNX Stack note (#1065)
The static_symbols API functions has been renamed in symtab_symbols.
LIEF was naming symbols located in the .symtab sections as static
symbols in opposition to the .dynsym symbols. This naming can be
confusing since the concept of static symbol in a program is well
defined (i.e. static bool my_var) and not applicable in this case.
Therefore, the ``xxx_static_symbols`` API is has been renamed ``xxx_symtab_symbol``.
Re-scope DYNAMIC_TAGS into lief.ELF.DynamicEntry.TAG
Re-scope E_TYPE into lief.ELF.Header.FILE_TYPE
Re-scope VERSION into lief.ELF.Header.VERSION
Re-scope ELF_CLASS into lief.ELF.Header.CLASS
Re-scope ELF_DATA into lief.ELF.Header.ELF_DATA
Re-scope OS_ABI into lief.ELF.Header.OS_ABI
Re-scope ELF_SECTION_TYPES into lief.ELF.Section.TYPE
Re-scope ELF_SECTION_FLAGS into lief.ELF.Section.FLAGS
Re-scope SYMBOL_BINDINGS into lief.ELF.Symbol.BINDING
Re-scope ELF_SYMBOL_TYPES into lief.ELF.Symbol.TYPE
Re-scope ELF_SYMBOL_VISIBILITY into lief.ELF.Symbol.VISIBILITY
Re-scope SEGMENT_TYPES into lief.ELF.Segment.TYPE
Re-scope ELF_SEGMENT_FLAGS into lief.ELF.Segment.FLAG
Re-scope DYNAMIC_FLAGS_1 into lief.ELF.DynamicEntryFlags.FLAG
Re-scope DYNAMIC_FLAGS into lief.ELF.DynamicEntryFlags.FLAG
Re-scope DYNSYM_COUNT_METHODS into lief.ELF.ParserConfig.DYNSYM_COUNT
Re-scope RELOCATION_PURPOSES into lief.ELF.Relocation.PURPOSE
RELOC_x86_64, RELOC_i386, … have been re-scoped and merged
into lief.ELF.Relocation.TYPE
Add support for Android packed relocation format (DT_ANDROID_REL{A})
Add support for relative relocation format (DT_RELR)
Authenticode: Add partial support for the following PKCS #7 attributes:
1.3.6.1.4.1.311.3.3.1 - Ms-CounterSign(lief.PE.MsCounterSign)
1.3.6.1.4.1.311.10.3.28 - Ms-ManifestBinaryID(lief.PE.MsManifestBinaryID)
1.3.6.1.4.1.311.2.6.1 - SPC_RELAXED_PE_MARKER_CHECK_OBJID(lief.PE.SpcRelaxedPeMarkerCheck)
1.2.840.113549.1.9.16.2.47 - SIGNING_CERTIFICATE_V2(lief.PE.SigningCertificateV2)
1.2.840.113549.1.9.16.1.4 - PKCS#9 TSTInfo (lief.PE.PKCS9TSTInfo)
Add lief.PE.CodeViewPDB.guid attribute (#480)
Move lief.PE.OptionalHeader.computed_checksum to lief.PE.Binary.compute_checksum()
In previous versions of LIEF, lief.PE.OptionalHeader.checksum was
re-computed (on purpose) in the parsing phase. On large
binaries, this re-computation can have a strong impact on the performances.
Thus, this computation has been deferred to a dedicated method lief.PE.Binary.compute_checksum()
pe = lief.PE.parse("...")
# Before:
computed = pe.optional_header.computed_checksum
# Now:
computed = pe.compute_checksum()
Add support to modify Mach-O rpath (see: #1074)
Add helper lief.MachO.Binary.support_arm64_ptr_auth to check if a
Mach-O binary is supporting ARM64 pointer authentication (arm64e)
Fix major performance issue when processing Mach-O binaries on Windows & macOS
Add generic lief.MachO.UnknownCommand to support Apple private Load
commands not officially supported by LIEF.
Re-scope LOAD_COMMAND_TYPES into lief.MachO.LoadCommand.TYPE
Re-scope FILE_TYPES into lief.MachO.Header.FILE_TYPE
Re-scope HEADER_FLAGS into lief.MachO.Header.FLAGS
Re-scope MACHO_SEGMENTS_FLAGS into lief.MachO.SegmentCommand.FLAGS
Re-scope MACHO_SECTION_TYPES into lief.MachO.Section.TYPE
Re-scope MACHO_SECTION_FLAGS into lief.MachO.Section.FLAGS
Re-scope REBASE_TYPES into lief.MachO.DyldInfo.REBASE_TYPE
Re-scope REBASE_OPCODES into lief.MachO.DyldInfo.REBASE_OPCODES
Re-scope BIND_OPCODES into lief.MachO.DyldInfo.BIND_OPCODES
Re-scope BINDING_CLASS into lief.MachO.DyldBindingInfo.CLASS
Re-scope BIND_TYPES into lief.MachO.DyldBindingInfo.TYPE
Re-scope EXPORT_SYMBOL_FLAGS into lief.MachO.ExportInfo.FLAGS
Re-scope EXPORT_SYMBOL_KINDS into lief.MachO.ExportInfo.KIND
Re-scope RELOCATION_ORIGINS into lief.MachO.Relocation.ORIGIN
Re-scope SYMBOL_ORIGINS into lief.MachO.Symbol.ORIGIN
Re-scope VM_PROTECTIONS into lief.MachO.SegmentCommand.VM_PROTECTIONS
Re-scope CPU_TYPES into lief.MachO.Header.CPU_TYPE
LIEFConfig.cmake is now installed in <prefix>/lib/cmake/LIEF/
instead of <prefix>/share/LIEF/cmake/
Add lief.disable_leak_warning() to disable Nanobind warning about “leaks”.
Warning
These warnings does not necessarily mean that LIEF leak objects. These warnings might happen in Cyclic garbage collection.
Add icons
Include inheritance diagram for Python API (e.g. lief.ELF.Note)
Add support for the GNU note properies (#975).
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.
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)
The fileset name is now stored in lief.MachO.Binary.fileset_name
(instead of lief.MachO.Binary.name)
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).
config = lief.PE.ParserConfig()
# Skip parsing PE authenticode
config.parse_signature = False
pe = lief.PE.parse("pe.exe", config)
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);
}
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.
Fix overflow issue in segments (c.f. #845 found by liyansong2018)
Fix missing relationship between symbols and sections (c.f. #841)
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.
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:
Add support for parsing Mach-O in memory
[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.
sec = bin.get_section("__DATA", "__objc_metadata")
Add API to remove a Section from a specified segment’s name and section’s name.
sec = bin.remove_section("__DATA", "__objc_metadata")
Add lief.MachO.Binary.page_size
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.
Fix multiple parsing issues raised by bladchan
Move to a build system compliant with pyproject.toml
Provide typing stubs: #650
PyPI releases no longer provide source distribution (sdist)
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
This release contains several security fixes:
ahaensler added the support to insert and assign a lief.ELF.SymbolVersionAuxRequirement (see: #670)
Enhance the ELF parser to support corner cases described by netspooky in :
https://tmpout.sh/2/14.html (84 byte aarch64 ELF)
https://tmpout.sh/2/3.html (Some ELF Parser Bugs)
New ELF Builder which is more efficient in terms of speed and in terms of number of segments added when modifying binaries (see: https://lief-project.github.io/blog/2022-01-23-new-elf-builder/)
Clcanny improved (see #507 and #509) the reconstruction of the dynamic symbol table
by sorting local symbols and non-exported symbols. It fixes the following warning when parsing
a modified binary with readelf
Warning: local symbol 29 found at index >= .dynsym's sh_info value of 1
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)
Adding lief.PE.OptionalHeader.computed_checksum that re-computes the lief.PE.OptionalHeader.checksum
(c.f. issue #660)
Enable to recompute the RichHeader (issue: #587)
Add support for PE’s delayed imports. see:
lief.PE.LoadConfiguration.reserved1 has been aliased to lief.PE.LoadConfiguration.dependent_load_flags
lief.PE.LoadConfiguration.characteristics has been aliased to lief.PE.LoadConfiguration.size
Thanks to gdesmar, we updated the PE checks to support PE files that have a corrupted
lief.PE.OptionalHeader.magic (cf. #644)
Abstract binary imagebase for PE, ELF and Mach-O (lief.Binary.imagebase)
Add PE imports/exports as abstracted symbols
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 !.
Upgrade to MbedTLS 3.1.0
Upgrade Catch2 to 2.13.8
The different dependencies can be linked externally (cf. above and Third Party)
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
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)
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";
}
Remove usage of not in public headers (b8e825b)
Fix issue when computing lief.PE.Binary.sizeof_headers (ab3f073)
Fix error on property lief.MachO.BuildVersion.sdk (see #533)
Fix missing bound check when computing the authentihash
Add sanity check on the signature’s length that could lead to a std::bad_alloc exception
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)
lief.PE.x509.is_trusted_by() and lief.PE.x509.verify() now return
a better lief.PE.x509.VERIFICATION_FLAGS instead of just lief.PE.x509.VERIFICATION_FLAGS.BADCERT_NOT_TRUSTED
(see: #532)
Fix errors in the computation of the Authentihash
aeflores added MIPS relocations support in the ELF parser
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)
Add PT_GNU_PROPERTY enum
Bug fix in the symbols table reconstruction (ELF)
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)
See also
Remove the padding entry (0) from the rich header
lief.PE.LangCodeItem.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)
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
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
Add Python 3.9 support
FindLIEF.cmake deprecates LIEF_ROOT. You should use LIEF_DIR instead.
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)
Note
The log functions now output on stderr instead of stdout
Fix regression in parsing Python bytes
Add Python API to demangle strings: lief.demangle
Add build support for ELF notes
Add coredump support (9fc3a8a)
Enable to bind a relocation with a symbol (a9f3cb8)
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)
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)
Add partial support for Android 9 (bce9ebe)
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
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.
Enable to configure the Mach-O parser for quick parsing: 880b99a
Add lief.MachO.EncryptionInfo command: f4e2d81
Add lief.MachO.RPathCommand command: 196994d
Add lief.MachO.DataInCode command: a16e1c4
Add lief.MachO.SubFramework command: 9e3b5b4
Add lief.MachO.SegmentSplitInfo command: 9e3b5b4
Add lief.MachO.DyldEnvironment command: 9e3b5b4
API to show export-trie, rebase and binding opcodes: 5d56141
Add PE Code View: eab4a76
lief.breakp()andlief.shell()
lief.parse()now supportiostreams as inputParser now returns a
std::unique_ptrinstead of a raw pointer: cd1cc45
Use frozen for some internal std::map (If C++14 is supported by the compiler)
[Mach-O] Fix typo on comparison operator - abbc264
[ELF] Increase the upper limit of relocation number - 077bc32
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
Relocation are now abstracted from the 3 formats - 9503f2f
PIE and NX are abstracted through the is_pie and has_nx properties
Add the lief.Section.search() and lief.Section.search_all() methods to look for patterns in the section’s content.
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
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]
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
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
The dyld structure is parsed (deeply) into DyldInfo. It includes:
Binding opcodes
Rebases opcodes
Export trie
Section relocations are now parsed into lief.MachO.Section.relocations - 29c8157
LC_FUNCTION_STARTS is parsed into FunctionStarts (18d8919)
LC_SOURCE_VERSION, LC_VERSION_MIN_MACOSX and LC_VERSION_MIN_IPHONEOS are
parsed into SourceVersion and VersionMin (c359778, 0b4bb7d, 5b99311, #45)
LC_THREAD and LC_UNIXTHREAD are now parsed into ThreadCommand - 2325783
Fix enums conflicts(#32) - 66b4cd4
Fix most of the memory leaks: 88dafa8, d9b1436, 554fa15, 3602643
In the C++ API get_XXX() getters have been renamed into XXX() (e.g. get_header() becomes header()) - a4c69f7, e805669
lief.Binary gains the format property - 9391238
lief.parse() can now takes a list of integers - f330fa8
Add has_symbol() and get_symbol() to lief.Binary - f121af5
[Python API] Enhance the access to the abstract layer through the abstract attribute - 0713854
One can now do:
elf = lief.ELF.parse("/bin/ls") # Could be lief.MachO / lief.PE
abstract = elf.abstract # Return the lief.Binary object
Add lief.ELF.Binary.symbols which return an iterator over all symbols (static and dynamic) - af6ab65
Header.sizeof_section_header has been renamed into section_header_size - d96971b
Add:
arm_flags_list,
mips_flags_list
ppc64_flags_list
hexagon_flags_list
To check if a given flag is set, one can do:
>>> if lief.ELF.ARM_EFLAGS.EABI_VER5 in lief.ELF.Header "yes" else "no"
[Python] Segment flags: PF_X, PF_W, PF_X has been renamed into X, W, X - d70ef9e
Enhancement for DynamicEntryRpath and DynamicEntryRunPath: c375a47
Enhancement for DynamicEntryArray: 81440ce
Add some operators 5666351
lief.MachO.parse() can now takes a list of integers - f330fa8
lief.MachO.parse() now returns a FatBinary instead of a list of Binary. FatBinary has a similar API as a list - 3602643
Add some operators: cbe8354
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
Add FindLIEF.cmake - 6dd8b10
Add ASAN, TSAN, USAN, LSAN - 7f6aeb0
Add LibFuzzer - 7a0dc28
recomposer, bearparser, IAT_patcher, PEframe, Manalyze, MachOView, elf-dissector
lief.ELF.Segment.data has been renamed to lief.ELF.Segment.content
lief.ELF.parse() takes an optional parameters: symbol counting - lief.ELF.DYNSYM_COUNT_METHODS
lief.ELF.Relocation.size
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
lief.PE.Builder.build_dos_stub
lief.PE.Builder.build_overlay
lief.PE.LangCodeItem
lief.PE.ResourceDialogItem
lief.PE.ResourceFixedFileInfo
lief.PE.ResourceStringFileInfo
elfsteem, pelook, PortEx, elfsharp, metasm, amoco, Goblin
Don’t rely on lief.ELF.Section.entry_size to count symbols - 004c676
Philippe for the proofreading.
First public release