This blog post introduces major changes in LIEF 0.9 as well as work in progress features that will be integrated in further releases. Changelog is available here.
As a quick reminder, LIEF is a library developed at Quarkslab to parse and modify executable file formats. See our previous posts:
Installation
Release packages are available on the Github page and Python package can be installed with:
$ pip install [--user] lief==0.9.0
Release highlight
Android Formats
This new version of LIEF comes with support for Android formats related to the ART runtime: OAT, VDEX, DEX and ART. As the OAT format is a derivation of ELF, it made sense to add it in LIEF. Basically, this format is used by Android to wrap native code being the result of Dalvik bytecode optimization.
Regarding VDEX, DEX, and ART, these formats have somehow a relation with OAT and therefore we also choose to add them. For more information about these Android formats and how to use them, a tutorial is available in the LIEF documentation: Android Formats.
We can currently only parse these formats, but their modification will come step by step in the project. Indeed, some attacks are based on the modification of the OAT format as it has been explained by Collin Mulliner in "Inside Android’s SafetyNetAttestation: Attack and Defense" [1] and "How Samsung Secures Your Wallet & How To Break It" [2] by Tencent’s Xuanwu Lab. In further version we plan to provide an API to add native code in OAT.
JSON serialization
As one purpose of this project is to provide an API that can be easily integrated in other projects, we are glad to announce that JSON serialization is now available for all LIEF objects. It means that one can now access to format information through a JSON interface. Previous versions had a JSON support for ELF and PE formats, the v0.9 now supports all formats and all objects.
Objects can be serialized with the lief.to_json function:
import lief
gcc = lief.parse("/usr/bin/gcc")
lief.to_json(gcc.header)
{'entrypoint': 4209824,
'file_type': 'EXECUTABLE',
'header_size': 64,
'identity_class': 'CLASS64',
'identity_data': 'LSB',
...
libSystem = lief.parse("/usr/lib/libSystem.dylib")
lief.to_json(libSystem.commands[1])
{'command': 'SEGMENT',
'command_offset': 492,
'command_size': 464,
'content_hash': 18446744072658165641,
'data_hash': 1841536728,
'file_offset': 8192,
'file_size': 4096,
'flags': 0,
'init_protection': 3,
'max_protection': 7,
'name': '__DATA',
'numberof_sections': 6,
'sections': ['__nl_symbol_ptr',
'__la_symbol_ptr',
'__mod_init_func',
'__const',
'__data',
'__common'],
'virtual_address': 8192,
'virtual_size': 4096}
One can also disable the JSON module using a CMake configuration flag:
$ cmake -DLIEF_ENABLE_JSON=off ...
What's next
LIEF v0.9 still has a poor support for Mach-O modification and only supports modifications on header and some Load commands.
One of the primitives to do more general modification on Mach-O format is the ability to add arbitrary Load commands. Some tools [3] [4] exist to add commands, but they usually use padding between the load command table and the raw content or they remove / replace existing one. The main limitation with this technique is that the number of load command which can be added depends on the size of the padding. In LIEF, we took advantage of the fact that Mach-O are PIE to shift the content that follow the load command table. This enable us to inject more than one or two commands. To keep a consistent state of format (relocations, segment's virtual address, ...), the Mach-O builder of LIEF rebuilds the export-trie, regenerates binding opcode, rebase opcodes, ...
In our tests, we succeeded in adding arbitrary number of LC_DYLIB command in clang as well as adding 10 new sections in the __TEXT segment. We are currently working on stabilization of the instrumentation process, but it should be merged soon in then master branch. Stay tuned!
We will be also be presenting about file formats instrumentation at ReCon and Pass The Salt for a talk about file formats instrumentation. In this talk we will present techniques to perform code injection, hooking by using formats.
[1] | Slide 58 of Inside Safetynet Attestation Attacks and Defense. |
[2] | Slide 89 of How Samsung Secures Your Wallet And How To Break It. |
[3] | insert_dylib. |
[4] | optool. |