Library to instrument executable formats including ELF, PE, Mach-O, and Android formats
—
Specialized support for Android application formats including DEX bytecode, ART runtime files, OAT optimized executables, and VDEX verification data. These formats enable analysis of Android applications, runtime optimization, and security research.
Identify Android-specific formats for proper parsing and analysis.
def is_dex(file: Union[str, Sequence[int]]) -> bool:
"""Check if file is DEX format."""
def is_art(file: Union[str, Sequence[int]]) -> bool:
"""Check if file is ART format."""
def is_oat(file: Union[str, Sequence[int], ELF.Binary]) -> bool:
"""Check if file is OAT format."""
def is_vdex(file: Union[str, Sequence[int]]) -> bool:
"""Check if file is VDEX format."""Usage example:
import lief
# Check Android format types
apk_dex = "/data/app/com.example.app/base.apk!/classes.dex"
if lief.is_dex(apk_dex):
print("DEX file detected")
oat_file = "/data/dalvik-cache/arm64/system@framework@boot.oat"
if lief.is_oat(oat_file):
print("OAT file detected")
art_file = "/data/dalvik-cache/arm64/system@framework@boot.art"
if lief.is_art(art_file):
print("ART file detected")Identify and work with different Android API versions and their characteristics.
class ANDROID_VERSIONS(enum.Enum):
UNKNOWN = 0
VERSION_601 = 1 # Android 6.0.1
VERSION_700 = 2 # Android 7.0
VERSION_710 = 3 # Android 7.1.0
VERSION_712 = 4 # Android 7.1.2
VERSION_800 = 5 # Android 8.0
VERSION_810 = 6 # Android 8.1
VERSION_900 = 7 # Android 9.0
def code_name(version: ANDROID_VERSIONS) -> str:
"""Get Android codename for version."""
def version_string(version: ANDROID_VERSIONS) -> str:
"""Get version string for Android version."""Usage example:
import lief.Android as Android
# Work with Android versions
version = Android.ANDROID_VERSIONS.VERSION_900
print(f"Codename: {Android.code_name(version)}")
print(f"Version: {Android.version_string(version)}")
# Map all versions
for version in Android.ANDROID_VERSIONS:
if version != Android.ANDROID_VERSIONS.UNKNOWN:
codename = Android.code_name(version)
version_str = Android.version_string(version)
print(f"{version_str} ({codename})")Analyze DEX (Dalvik Executable) files containing Android application bytecode.
# Access through lief.DEX module
import lief.DEX as DEX
def parse(file: Union[str, bytes, io.IOBase]) -> Optional[File]
class File:
header: Header
classes: Iterator[Class]
methods: Iterator[Method]
strings: Iterator[str]
types: Iterator[Type]
fields: Iterator[Field]
prototypes: Iterator[Prototype]
class Header:
magic: bytes
version: int
checksum: int
signature: bytes
file_size: int
header_size: int
link_size: int
link_offset: int
map_offset: int
strings_offset: int
types_offset: int
prototypes_offset: int
fields_offset: int
methods_offset: int
classes_offset: int
data_size: int
data_offset: int
class Class:
fullname: str
package_name: str
name: str
pretty_name: str
access_flags: int
parent: Optional[Class]
source_filename: str
methods: Iterator[Method]
fields: Iterator[Field]
class Method:
name: str
index: int
pretty_name: str
access_flags: int
code_offset: int
prototype: Prototype
class Field:
name: str
index: int
access_flags: int
type: Type
class Type:
type: str
dim: int
class Prototype:
return_type: Type
parameters_type: List[Type]DEX files contain the compiled Java bytecode for Android applications. They include:
Usage example:
import lief.DEX as DEX
# Parse DEX file from APK
dex_binary = DEX.parse("classes.dex")
if dex_binary:
print("DEX file parsed successfully")
# DEX-specific analysis would be available through dex_binary objectAnalyze ART (Android Runtime) files used for ahead-of-time compilation.
# Access through lief.ART module
import lief.ART as ART
def parse(file: Union[str, bytes, io.IOBase]) -> Optional[File]
class File:
header: Header
class Header:
magic: bytes
version: str
image_base: int
image_size: int
image_methods_offset: int
image_methods_count: int
image_roots_offset: int
oat_checksum: int
oat_file_begin: int
oat_data_begin: int
oat_data_end: int
oat_file_end: int
boot_image_begin: int
boot_image_size: int
boot_oat_begin: int
boot_oat_size: int
patch_delta: int
image_roots_size: int
pointer_size: int
compile_pic: bool
is_pic: bool
storage_mode: int
data_size: intART files are used by the Android Runtime for ahead-of-time (AOT) compilation:
Usage example:
import lief.ART as ART
# Parse ART file
art_binary = ART.parse("boot.art")
if art_binary:
print("ART file parsed successfully")
# ART-specific analysis would be availableAnalyze OAT (Optimized Android executables) files containing compiled DEX code.
# Access through lief.OAT module (OAT files are ELF-based)
import lief.OAT as OAT
def parse(file: Union[str, bytes, io.IOBase]) -> Optional[Binary]
class Binary(lief.ELF.Binary):
header: Header
dex_files: Iterator[DexFile]
classes: Iterator[Class]
methods: Iterator[Method]
class Header:
magic: bytes
version: str
adler32_checksum: int
instruction_set: INSTRUCTION_SETS
instruction_set_features: int
dex_file_count: int
executable_offset: int
interpreter_to_interpreter_bridge_offset: int
interpreter_to_compiled_code_bridge_offset: int
jni_dlsym_lookup_offset: int
quick_generic_jni_trampoline_offset: int
quick_imt_conflict_trampoline_offset: int
quick_resolution_trampoline_offset: int
quick_to_interpreter_bridge_offset: int
image_patch_delta: int
image_file_location_oat_checksum: int
image_file_location_oat_data_begin: int
key_value_size: int
class DexFile:
location: str
checksum: int
dex_file_offset: int
classes_offsets: List[int]
lookup_table_offset: int
class Class:
status: int
type: str
bitmap: List[int]
methods: Iterator[Method]
class Method:
native_method_addr: int
native_quick_generic_jni_trampoline: int
native_quick_to_interpreter_bridge: int
enum INSTRUCTION_SETS:
NONE = 0
ARM = 1
ARM64 = 2
X86 = 3
X86_64 = 4
MIPS = 5
MIPS64 = 6OAT files are ELF files with Android-specific extensions:
Usage example:
import lief.ELF as ELF
# OAT files are ELF files, so parse with ELF module
oat_binary = ELF.parse("boot.oat")
if oat_binary and lief.is_oat(oat_binary):
print("OAT file parsed as ELF")
# Look for Android-specific sections
for section in oat_binary.sections:
if section.name.startswith(".oat"):
print(f"OAT section: {section.name}")Analyze VDEX (Verified DEX) files containing verification and optimization data.
# Access through lief.VDEX module
import lief.VDEX as VDEX
def parse(file: Union[str, bytes, io.IOBase]) -> Optional[File]
class File:
header: Header
dex_files: Iterator[DEX.File]
class Header:
magic: bytes
version: str
number_of_dex_files: int
dex_size: int
dex_shared_data_size: int
quickening_info_size: int
verifier_deps_size: int
bootclasspath_checksums_size: intVDEX files contain verification and optimization data:
Usage example:
import lief.VDEX as VDEX
# Parse VDEX file
vdex_binary = VDEX.parse("base.vdex")
if vdex_binary:
print("VDEX file parsed successfully")
# VDEX-specific analysis would be availableIntegrate Android format analysis with APK (Android Package) files.
# APK files are ZIP archives containing:
# - classes.dex (DEX files)
# - AndroidManifest.xml
# - Resources (res/)
# - Native libraries (lib/)
# - Assets (assets/)APK files can be analyzed by extracting their components:
Usage example:
import zipfile
import lief
def analyze_apk(apk_path):
"""Analyze Android APK file contents."""
with zipfile.ZipFile(apk_path, 'r') as apk:
# List all files
print("APK contents:")
for file_info in apk.filelist:
print(f" {file_info.filename}")
# Analyze DEX files
for filename in apk.namelist():
if filename.endswith('.dex'):
print(f"Found DEX file: {filename}")
dex_data = apk.read(filename)
if lief.is_dex(dex_data):
print(f" Valid DEX file: {len(dex_data)} bytes")
# Check for native libraries
native_libs = [f for f in apk.namelist() if f.startswith('lib/')]
if native_libs:
print("Native libraries:")
for lib in native_libs:
print(f" {lib}")
lib_data = apk.read(lib)
if lief.is_elf(lib_data):
elf_binary = lief.ELF.parse(lib_data)
if elf_binary:
print(f" ELF: {elf_binary.header.machine_type}")
# Usage
analyze_apk("app.apk")Support for analyzing Android runtime environments and optimization.
DEX Optimization Process:
Analysis workflow:
def analyze_android_optimization(package_path):
"""Analyze Android app optimization artifacts."""
# Check for different optimization stages
dex_files = find_dex_files(package_path)
vdex_files = find_vdex_files(package_path)
oat_files = find_oat_files(package_path)
art_files = find_art_files(package_path)
print(f"Found {len(dex_files)} DEX files")
print(f"Found {len(vdex_files)} VDEX files")
print(f"Found {len(oat_files)} OAT files")
print(f"Found {len(art_files)} ART files")
# Analyze optimization level
if art_files:
print("Ahead-of-time (AOT) compilation detected")
elif oat_files:
print("Optimized DEX compilation detected")
elif vdex_files:
print("Verified DEX files detected")
else:
print("Unoptimized DEX files only")Android format analysis for security research and malware detection.
Common security analysis tasks:
Usage example:
def security_analysis(apk_path):
"""Perform security analysis on Android APK."""
with zipfile.ZipFile(apk_path, 'r') as apk:
# Check for suspicious files
suspicious_files = []
for filename in apk.namelist():
# Look for native libraries
if filename.startswith('lib/') and filename.endswith('.so'):
lib_data = apk.read(filename)
if lief.is_elf(lib_data):
elf_binary = lief.ELF.parse(lib_data)
if elf_binary:
# Check for packing indicators
if any('upx' in section.name.lower() for section in elf_binary.sections):
suspicious_files.append(f"{filename}: UPX packed")
# Check for anti-debugging
if elf_binary.has_symbol("ptrace"):
suspicious_files.append(f"{filename}: ptrace usage")
# Analyze DEX files
elif filename.endswith('.dex'):
dex_data = apk.read(filename)
if lief.is_dex(dex_data):
# DEX-specific security checks would go here
print(f"Analyzing DEX: {filename}")
if suspicious_files:
print("Suspicious indicators found:")
for indicator in suspicious_files:
print(f" {indicator}")# Android-specific enumerations and constants
enum ANDROID_VERSIONS:
UNKNOWN = 0
VERSION_601 = 1 # Marshmallow 6.0.1
VERSION_700 = 2 # Nougat 7.0
VERSION_710 = 3 # Nougat 7.1.0
VERSION_712 = 4 # Nougat 7.1.2
VERSION_800 = 5 # Oreo 8.0
VERSION_810 = 6 # Oreo 8.1
VERSION_900 = 7 # Pie 9.0
# DEX file format constants
DEX_FILE_MAGIC = "dex\n"
DEX_FILE_VERSION_035 = "035\0"
DEX_FILE_VERSION_037 = "037\0"
DEX_FILE_VERSION_038 = "038\0"
DEX_FILE_VERSION_039 = "039\0"
# OAT file format constants
OAT_MAGIC = "oat\n"
OAT_VERSION_MINIMUM = "045"
OAT_VERSION_MAXIMUM = "199"
# ART file format constants
ART_MAGIC = "art\n"
# VDEX file format constants
VDEX_MAGIC = "vdex"Install with Tessl CLI
npx tessl i tessl/pypi-lief