
ALEAPP v2026.3.3
Analizador de registros, eventos y protobuf de Android

Android Logs Events And Protobuf Parser
Si quieres contribuir, contáctame aquí: https://abrignoni.github.io
Entradas del blog aquí: https://leapps.org/blog
Requisitos
Python 3.10 o superior
Dependencias
Las dependencias para tu entorno de Python se enumeran en requirements.txt. Instálalas con el siguiente comando. Asegúrate
de que la parte py sea correcta para tu entorno, por ejemplo py, python o python3, etc.
py -m pip install -r requirements.txt
o
pip3 install -r requirements.txt
Para ejecutarlo en Linux, también necesitarás instalar tkinter por separado de esta forma:
sudo apt-get install python3-tk
Compilar a ejecutable
Para compilar a un ejecutable y poder ejecutarlo en un sistema sin Python instalado.
Windows OS
Para crear aleapp.exe, ejecuta:
pyinstaller scripts\pyinstaller\aleapp.spec
Para crear aleappGUI.exe, ejecuta:
pyinstaller scripts\pyinstaller\aleappGUI.spec
macOS
Para crear aleapp, ejecuta:
pyinstaller scripts/pyinstaller/aleapp_macOS.spec
Para crear aleappGUI.app, ejecuta:
pyinstaller scripts/pyinstaller/aleappGUI_macOS.spec
Linux
Para crear aleapp, ejecuta:
pyinstaller scripts/pyinstaller/aleapp_Linux.spec
Para crear aleappGUI, ejecuta:
pyinstaller scripts/pyinstaller/aleappGUI_Linux.spec
Uso
CLI
$ python aleapp.py -t <zip | tar | fs | gz | raw> -i <path_to_extraction> -o <path_for_report_output>
raw lee una imagen de disco (.img, .dd, .bin o cualquier segmento numerado .001 de
un conjunto dividido), o una adquisición EnCase/EWF .E01 y los segmentos que la acompañan, in
situ: sin montaje y sin permisos de administrador. Sus volúmenes NTFS, FAT32, exFAT, ext2/3/4,
F2FS, HFS+, APFS, QNX6, QNX4, ETFS, EFS, SquashFS, JFFS2, UBI/UBIFS, YAFFS y QNX IFS
se buscan directamente, y
solo se leen de la imagen los archivos que solicita un artefacto. La GUI selecciona
raw por sí sola para esas extensiones. Consulta admin/docs/raw_image_input.md.
tar también lee un tar comprimido con xz (.tar.xz), y la GUI selecciona tar para esa
extensión. Un tar comprimido, incluido .tar.gz, se descomprime una vez en la carpeta del informe
antes de leer cualquier archivo, por lo que la ejecución necesita espacio libre allí para el tar sin comprimir. La
copia se elimina cuando finaliza la ejecución, y el registro de la ejecución indica cuánto tardó el paso.
GUI
$ python aleappGUI.py
Ayuda
$ python aleapp.py --help
Contribuir con plugins de artefactos
Cada plugin es un archivo fuente de Python que debe añadirse a la carpeta scripts/artifacts, que se cargará dinámicamente cada vez que se ejecute ALEAPP.
El archivo fuente del plugin debe contener un diccionario llamado __artifacts_v2__ al principio del módulo, que define los artefactos que procesa el plugin. Las claves del diccionario __artifacts_v2__ deben ser IDs para el/los artefacto(s) que deben ser únicos dentro de ALEAPP. Los valores deben ser diccionarios que contengan las siguientes claves:
name: El nombre del artefacto como una cadena.description: Una descripción del artefacto como una cadena.author: El autor del plugin como una cadena.version: La versión del artefacto como una cadena.date: La fecha de la última actualización del artefacto como una cadena.requirements: Cualquier requisito para procesar el artefacto como una cadena.category: La categoría del artefacto como una cadena.notes: Cualquier nota adicional como una cadena.paths: Una tupla de cadenas que contienen patrones de búsqueda glob para coincidir con la ruta de los datos que el plugin espera para el artefacto.function: El nombre de la función que es el punto de entrada para el procesamiento del artefacto como una cadena.
Por ejemplo:
__artifacts_v2__ = {
"cool_artifact_1": {
"name": "Cool Artifact 1",
"description": "Extracts cool data from database files",
"author": "@username",
"version": "0.1",
"date": "2022-10-25",
"requirements": "none",
"category": "Really cool artifacts",
"notes": "",
"paths": ('*/com.android.cooldata/databases/database*.db',),
"function": "get_cool_data1"
},
"cool_artifact_2": {
"name": "Cool Artifact 2",
"description": "Extracts cool data from XML files",
"author": "@username",
"version": "0.1",
"date": "2022-10-25",
"requirements": "none",
"category": "Really cool artifacts",
"notes": "",
"paths": ('*/com.android.cooldata/files/cool.xml',),
"function": "get_cool_data2"
}
}
Las funciones referenciadas como puntos de entrada en el diccionario __artifacts__ deben tomar los siguientes argumentos:
- Un iterable de los archivos encontrados que se van a procesar (como cadenas)
- La ruta de la carpeta de salida de ALEAPP (como una cadena)
- El seeker (de tipo FileSeekerBase) que encontró los archivos
- Un valor booleano que indica si se espera o no que el plugin ajuste el texto
Por ejemplo:
def get_cool_data1(files_found, report_folder, seeker, wrap_text):
pass # do processing here
Generalmente se espera que los plugins proporcionen salida en el formato de salida HTML de ALEAPP, TSV y, opcionalmente, envíen registros a
la línea de tiempo. Las funciones para generar esta salida se pueden encontrar en los módulos artifact_report e ilapfuncs.
A alto nivel, un ejemplo podría parecerse a:
__artifacts_v2__ = {
"cool_artifact_1": {
"name": "Cool Artifact 1",
"description": "Extracts cool data from database files",
"author": "@username", # Replace with the actual author's username or name
"version": "0.1", # Version number
"date": "2022-10-25", # Date of the latest version
"requirements": "none",
"category": "Really cool artifacts",
"notes": "",
"paths": ('*/com.android.cooldata/databases/database*.db',),
"function": "get_cool_data1"
}
}
import datetime
from scripts.artifact_report import ArtifactHtmlReport
import scripts.ilapfuncs
def get_cool_data1(files_found, report_folder, seeker, wrap_text):
# let's pretend we actually got this data from somewhere:
rows = [
(datetime.datetime.now(), "Cool data col 1, value 1", "Cool data col 1, value 2", "Cool data col 1, value 3"),
(datetime.datetime.now(), "Cool data col 2, value 1", "Cool data col 2, value 2", "Cool data col 2, value 3"),
]
headers = ["Timestamp", "Data 1", "Data 2", "Data 3"]
# HTML output:
report = ArtifactHtmlReport("Cool stuff")
report_name = "Cool DFIR Data"
report.start_artifact_report(report_folder, report_name)
report.add_script()
report.write_artifact_data_table(headers, rows, files_found[0]) # assuming only the first file was processed
report.end_artifact_report()
# TSV output:
scripts.ilapfuncs.tsv(report_folder, headers, rows, report_name, files_found[0]) # assuming first file only
# Timeline:
scripts.ilapfuncs.timeline(report_folder, report_name, rows, headers)
Datos de prueba y sample_data para tu PR
Un PR que añade o cambia un artefacto es más fácil de revisar y fusionar cuando llega con
dos cosas: un pequeño fixture de prueba extraído de una extracción real, y valores de sample_data que
registran lo que produjo el módulo. Los scripts generan ambos. Aquí está todo el flujo.