Avatar

LIEF v0.17.0

ionicons-v5-k Romain Thomas September 14, 2025
Wave

This new version of LIEF introduces several improvements and features that expand the scope of LIEF’s use cases.

Reverse Engineering Plugins

Reverse engineering frameworks like Binary Ninja and Ghidra provide excellent support for analyzing instructions and functions. However, they might lack an in-depth analysis of all structures associated with executable formats.

For example, the latest version of Ghidra (11.4.2) and Binary Ninja (5.1.8104) are not able to accurately process Windows ARM64EC binaries, which combine ARM64 code with x86_64. ARM64EC binaries use specific structures such as IMAGE_ARM64EC_METADATA, that are not (yet) recognized by most of the reverse engineering frameworks:

                    DAT_1400111f8                             XREF[1]:   140011be8(*)1400111f8 02                                           ??                                                   02h1400111f9 00                                           ??                                                   00h1400111fa 00                                           ??                                                   00h1400111fb 00                                           ??                                                   00h1400111fc 00                                           ??                                                   00h1400111fd 1e                                           ??                                                   1Eh1400111fe 01                                           ??                                                   01h1400111ff 00                                           ??                                                   00h140011200 02                                           ??                                                   02h140011201 00                                           ??                                                   00h140011202 00                                           ??                                                   00h140011203 00                                           ??                                                   00h140011204 b4                                           ??                                                   B4h140011205 1c                                           ??                                                   1Ch140011206 01                                           ??                                                   01h140011207 00                                           ??                                                   00h140011208 00                                           ??                                                   00h140011209 90                                           ??                                                   90h14001120a 01                                           ??                                                   01h14001120b 00                                           ??                                                   00h14001120c 00                                           ??                                                   00h14001120d 10                                           ??                                                   10h14001120e 01                                           ??                                                   01h14001120f 00                                           ??                                                   00h140011210 08                                           ??                                                   08h140011211 10                                           ??                                                   10h140011212 01                                           ??                                                   01h140011213 00                                           ??                                                   00h140011214 18                                           ??                                                   18h
                    IMAGE_ARM64EC_METADATA_V2_1400111f8       XREF[1]:   140011be8(*)1400111f8 02 00 00 00 00 1e 01 00 02 00 00 00 b4       IMAGE_ARM64EC_METADATA_V2          1c 01 00 00 90 01 00 00 10 01 00 08 10          01 00 18 10 01 00 10 10 01 00 20 10 01      1400111f8 02 00 00 00 00 1e 01 00 02 00 00 00 b4  IMAGE_ARM64EC_METADATA                                                                              V1                1c 01 00 00 90 01 00 00 10 01 00 08 10                01 00 18 10 01 00 10 10 01 00 20 10 01         1400111f8 02 00 00 00                             ddw                2h                                                             Version         1400111fc 00 1e 01 00                             ibo32              IMAGE_ARM64EC_METADATA_CODE_RANGE_ARRAY_140011e00              CodeMap         140011200 02 00 00 00                             ddw                2h                                                             CodeMapCount         140011204 b4 1c 01 00                             ibo32              IMAGE_ARM64EC_CODE_RANGE_ENTRY_POINT_ARRAY_140011cb4           CodeRangesToEntryPoints         140011208 00 90 01 00                             ibo32              IMAGE_ARM64EC_METADATA_REDIRECTION_ARRAY_140019000             RedirectionMetadata         14001120c 00 10 01 00                             ibo32              DAT_140011000                                                  __os_arm64x_dispatch_call_no_redirect         140011210 08 10 01 00                             ibo32              DAT_140011008                                                  __os_arm64x_dispatch_ret         140011214 18 10 01 00                             ibo32              DAT_140011018                                                  __os_arm64x_dispatch_call         140011218 10 10 01 00                             ibo32              PTR_DAT_140011010                                              __os_arm64x_dispatch_icall         14001121c 20 10 01 00                             ibo32              PTR_DAT_140011020                                              __os_arm64x_dispatch_icall_cfg         140011220 00 00 00 00                             ibo32              NaP                                                            AlternateEntryPoint         140011224 00 50 01 00                             ibo32              PTR_DAT_140015000                                              AuxiliaryIAT         140011228 01 00 00 00                             ddw                1h                                                             CodeRangesToEntryPointsCount         14001122c 01 00 00 00                             ddw                1h                                                             RedirectionMetadataCount         140011230 28 10 01 00                             ibo32              DAT_140011028                                                  GetX64InformationFunctionPointer         140011234 30 10 01 00                             ibo32              DAT_140011030                                                  SetX64InformationFunctionPointer         140011238 00 70 01 00                             ibo32              IMAGE_ARM64_RUNTIME_FUNCTION_UNPACKED_ENTRY_140017000          ExtraRFETable         14001123c 38 0d 00 00                             ddw                D38h                                                           ExtraRFETableSize         140011240 38 10 01 00                             ibo32              DAT_140011038                                                  __os_arm64x_dispatch_fptr         140011244 48 3e 01 00                             ibo32              PTR_DAT_140013e48                                              AuxiliaryIATCopy      140011248 00 00 00 00                             ibo32              NaP                                                            AuxDelayloadIAT      14001124c 00 00 00 00                             ibo32              NaP                                                            AuxDelayloadIATCopy      140011250 00 00 00 00                             ddw                0h                                                             ReservedBitField

This IMAGE_ARM64EC_METADATA structure contains the ExtraRFE attribute, which is used to reference an exception table that is specific to the ARM64EC:

.rdata section started  {0x140010000-0x1400152d8}140012710  0b 00 20 08 81 e4 e3 e3 14 00 40 40 0a 00 c0 02  .. .......@@....140012720  e1 81 e6 e6 e6 e6 e7 66 89 fc e4 81 e7 4e 88 e7  .......f.....N..140012730  4c 86 e7 4a 84 e7 48 82 e7 66 89 fc e3 e3 e4 e3  L..J..H..f......140012740  06 00 40 08 05 00 80 00 01 e4 e4 00 0b 00 40 10  ..@...........@.
.rdata section started  {0x140010000-0x1400152d8}140012710  struct LIEF_IMAGE_ARM64_RUNTIME_FUNCTION_ENTRY_XDATA __arm64_runtime_function_entry_xdata =140012710  {140012710      uint32_t HeaderData = 0x820000b140012714  }140012714  uint8_t __arm64_unwind_code[0x4] =140012714  {140012714      [0x0] =  0x81140012715      [0x1] =  0xe4140012716      [0x2] =  0xe3140012717      [0x3] =  0xe3140012718  }140012718  struct LIEF_IMAGE_ARM64_RUNTIME_FUNCTION_ENTRY_XDATA __arm64_runtime_function_entry_xdata =140012718  {140012718      uint32_t HeaderData = 0x4040001414001271c  }14001271c  uint32_t __arm64_epilog_scopes[0x1] =14001271c  {14001271c      [0x0] =  0x02c0000a140012720  }140012720  uint8_t __arm64_unwind_code[0x20] =140012720  {140012720      [0x00] =  0xe1140012721      [0x01] =  0x81140012722      [0x02] =  0xe6140012723      [0x03] =  0xe6140012724      [0x04] =  0xe6140012725      [0x05] =  0xe6               [....]140012740  }

As for the x86_64 architecture, this table can be used to increase the coverage of functions recognized by BinaryNinja:

The source code of these plugins is located in the main LIEF repository under the following directories:

This new release of LIEF introduces official and maintained support for both Binary Ninja and Ghidra, enhancing the analysis capabilities and type definitions for these frameworks.

Contextual Assembly Patching

Note

The feature is only available in LIEF Extended

When patching assembly code, we frequently need to refer to external data or functions within our assembly listing.

For instance, we might want to naturally write:

1elf = lief.ELF.parse("libdexprotector.so")
2elf.assemble(
3    elf.get_function_address("libdp_init"),
4    """
5    adrp x4, g_protections_conf
6    add x4, x4, :lo12:g_protections_conf
7    strb wzr, [x4, 0xe] // Disable debug check.
8    """
9)

In this code snippet, we assume that the address of g_protections_conf is known. With the latest release, the assembler engine has introduced support for dynamically resolving symbols referenced in an assembly listing.

This functionality works by providing an additional configuration parameter:

 1class Config(lief.assembly.AssemblerConfig):
 2    def __init__(self, target: lief.Binary):
 3        super().__init__()
 4        self._target = target
 5
 6    def resolve_symbol(self, name: str) -> int | None:
 7        dwarf_info: lief.dwarf.DebugInfo = self._target.debug_info
 8        if var := dwarf_info.find_variable(name):
 9            print(f"'{name}' is located at address: 0x{var.address:016x}")
10            return var.address
11        return super().resolve_symbol(name)
12
13elf = lief.ELF.parse("libdexprotector.so")
14
15config = Config(elf)
16elf.assemble(
17    elf.get_function_address("libdp_init"),
18    """
19    adrp x4, g_protections_conf
20    add x4, x4, :lo12:g_protections_conf
21    strb wzr, [x4, 0xe] // Disable debug check.
22    """, config
23)

The logic of the resolve_symbol function depends on DWARF information that is generated by BinaryNinja (see: BinaryNinja - DWARF Plugin)

After patching, we can see the final results, which show that the adrp instructions have been correctly generated to access the g_protections_conf.debug_check variable:

  uint64_t libdp_init(struct _JNIEnv* env)000504e0  fd7bbba9   stp     fplr[sp#-0x50]! {__saved_fp} {__saved_lr}000504e4  fc6701a9   stp     x28x25[sp#0x10] {__saved_x28} {__saved_x25}000504e8  f85f02a9   stp     x24x23[sp#0x20] {__saved_x24} {__saved_x23}000504ec  f65703a9   stp     x22x21[sp#0x30] {__saved_x22} {__saved_x21}000504f0  f44f04a9   stp     x20x19[sp#0x40] {__saved_x20} {__saved_x19}000504f4  fd030091   mov     fpsp {__saved_fp}000504f8  ff030ed1   sub     spsp#0x380000504fc  f3030091   mov     x19sp {rlim}00050500  57d03bd5   mrs     x23tpidr_el000050504  e81640f9   ldr     x8[x23#0x28]00050508  f40300aa   mov     x20x00005050c  a8831ff8   stur    x8[fp#-0x8 {var_58}]00050510  e996ff97   bl      dp_check_android_version00050514  f603002a   mov     w22w000050518  60100035   cbnz    w00x507240005051c  80008052   mov     w0#0x400050520  e1031f2a   mov     w1wzr  {0x0}00050524  e2031f2a   mov     w2wzr  {0x0}00050528  e3031f2a   mov     w3wzr  {0x0}0005052c  e4031f2a   mov     w4wzr  {0x0}00050530  2811ff97   bl      dp_sys_prctl00050534  c8fdffb0   adrp    x8data_9000  {"supersu.rc#/sbin/daemonsu#/sbin/su#/sbin/supersu/supersu_is_here..."}
  uint64_t libdp_init(struct _JNIEnv* env)000504e0  44010090   adrp    x40x78000000504e4  84802f91   add     x4x4#0xbe0  {g_protections_conf}000504e8  9f380039   strb    wzr[x4#0xe]  {0x0}  {g_protections_conf.debug_check}000504ec  f65703a9   stp     x22x21[sp#0x30] {__saved_x22} {__saved_x21}000504f0  f44f04a9   stp     x20x19[sp#0x40] {__saved_x20} {__saved_x19}000504f4  fd030091   mov     fpsp {arg_0}000504f8  ff030ed1   sub     spsp#0x380000504fc  f3030091   mov     x19sp {rlim}00050500  57d03bd5   mrs     x23tpidr_el000050504  e81640f9   ldr     x8[x23#0x28]00050508  f40300aa   mov     x20x00005050c  a8831ff8   stur    x8[fp#-0x8 {var_8}]00050510  e996ff97   bl      dp_check_android_version00050514  f603002a   mov     w22w000050518  60100035   cbnz    w00x507240005051c  80008052   mov     w0#0x400050520  e1031f2a   mov     w1wzr  {0x0}00050524  e2031f2a   mov     w2wzr  {0x0}00050528  e3031f2a   mov     w3wzr  {0x0}0005052c  e4031f2a   mov     w4wzr  {0x0}00050530  2811ff97   bl      dp_sys_prctl00050534  c8fdffb0   adrp    x8data_9000  {"supersu.rc#/sbin/daemonsu#/sbin/su#/sbin/supersu/supersu_is_here..."}

For more details about the API, you can check: https://lief.re/doc/latest/extended/assembler/index.html#contextual-assembly-patching

PE Refactoring

LIEF’s PE module has been significantly refactored, including improvements to the parser, builder, and documentation. These improvements bring this format to a level of maturity comparable to other formats (ELF/Mach-O). The most notable enhancements involve the ability to modify TLS, as well as manage imports and exports. It also provides support for ARM64EC and ARM64X binaries.

For more details, please refer to:

lief-patchelf

For this release, I started to bootstrap LIEF-based tools (mostly CLI) that aim to provide specific functionalities using LIEF. The first tool of this bootstrap is lief-patchelf, which provides a drop-in replacement for the well-known NixOS/patchelf.

You can find insight about this tool in this blog post: https://lief.re/blog/2025-07-13-patchelf/

COFF Format

The COFF format is now supported by LIEF, but it does not support modifications yet. The API is really similar to the other formats and available in C++/Rust/Python:

 1import lief
 2coff: lief.COFF.Binary = lief.COFF.parse(r"C:\Users\romain\test.obj")
 3
 4# Access symbols and aux info
 5for symbol in coff.symbols:
 6    print(symbol.name)
 7    for aux in symbol.auxiliary_symbols:
 8        assert str(aux) == """
 9          AuxiliaryCLRToken {
10            Aux Type: 1
11            Reserved: 1
12            Symbol index: 10
13            Symbol: ??0CppInlineNamespaceAttribute@?A0xb81de522@vc.cppcli.attributes@@$$FQE$AAM@PE$[...]
14            Rgb reserved:
15              +---------------------------------------------------------------------+
16              | 00 00 00 00 00 00 00 00 00 00 00 00              | ............     |
17              +---------------------------------------------------------------------+
18          }
19          """
20
21# Disassembler support
22for inst in coff.disassemble("?foo@@YAHHH@Z")
23    print(inst)

The documentation for this format is here: https://lief.re/doc/latest/formats/coff/index.html

Final Word

Version 0.17.0 is the latest release in the 0.X.Y series. With significant improvements to the PE format and the global scale at which LIEF is used, I believe the project is now ready for its upcoming 1.0 version.

The complete changelog is here: https://lief.re/doc/latest/changelog.html

Happy LIEF,

Romain

Avatar
Romain Thomas Posted on September 14, 2025