CLE: Common Library for Executables
CLE (Common Library for Executables) is a Python library that loads binaries and their associated libraries, resolves imports, and provides an abstraction of process memory, mimicking how an operating system's loader would present them. It is a core component of the larger angr binary analysis framework. The current version is 9.2.209, and it maintains an active release cadence as part of the angr project.
Warnings
- breaking When migrating from older versions of `cle` (prior to `angr 8`), Python 2 is no longer supported. All code must be migrated to Python 3.
- breaking The `Clemory` API (accessed via `project.loader.memory`) underwent significant refactoring with `angr 8`, specifically around replacing Python 2 string types with Python 3's `bytes`. Functions like `cbackers` and `read_bytes_c` are deprecated.
- breaking Symbol types in CLE (e.g., accessed via `main_object.imports`) are now represented using Enums instead of potentially raw string or integer values, as introduced in `angr 8.19.7.25` (cle#177).
- gotcha By default, `cle.Loader` attempts to automatically load shared libraries. If the `auto_load_libs` option is set to `False`, dependencies requested by loaded objects will not be resolved, potentially leading to incomplete memory maps or unresolved symbols.
- gotcha Loading certain binary formats (e.g., PE for Windows executables) requires optional Python packages like `pefile`. If these dependencies are not installed, `cle` may fail to load the binary or provide incomplete analysis without a clear error message indicating the missing package.
Install
-
pip install cle
Imports
- Loader
import cle loader = cle.Loader(...)
Quickstart
import cle
import os
# For demonstration, use a common system binary like '/bin/ls'
# On Windows, you might use a path to an executable like 'C:\Windows\System32\calc.exe'
binary_path = os.environ.get('CLE_BINARY_PATH', '/bin/ls')
try:
ld = cle.Loader(binary_path)
print(f"Loaded binary: {ld.main_object.binary_path}")
print(f"Entry point: {hex(ld.main_object.entry)}")
print("Shared objects:")
for obj_name, obj_data in ld.shared_objects.items():
print(f" - {obj_name}: {obj_data}")
# Example of accessing an import
if '__libc_start_main' in ld.main_object.imports:
libc_main_reloc = ld.main_object.imports['__libc_start_main']
print(f"Address of __libc_start_main GOT entry: {hex(libc_main_reloc.addr)}")
except Exception as e:
print(f"Error loading binary {binary_path}: {e}")
print("Please ensure the binary exists and is a valid executable format for CLE.")