Volver a actualizaciones
Nuevo releaseSep 11, 2026

ALEAPP v2026.3.3

Analizador de registros, eventos y protobuf de Android

Compartir

ALEAPP

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.

Categorías