
ALEAPP v2026.3.3
Parser di log, eventi e Protobuf di Android

Android Logs Events And Protobuf Parser
Se vuoi contribuire contattami qui: https://abrignoni.github.io
Post del blog qui: https://leapps.org/blog
Requisiti
Python 3.10 o superiore
Dipendenze
Le dipendenze per il tuo ambiente Python sono elencate in requirements.txt. Installale usando il comando qui sotto. Assicurati che la parte py sia corretta per il tuo ambiente, ad esempio py, python o python3, ecc.
py -m pip install -r requirements.txt
oppure
pip3 install -r requirements.txt
Per eseguire su Linux, dovrai anche installare tkinter separatamente in questo modo:
sudo apt-get install python3-tk
Compilazione in eseguibile
Per compilare in un eseguibile così da poterlo eseguire su un sistema senza Python installato.
Sistema operativo Windows
Per creare aleapp.exe, esegui:
pyinstaller scripts\pyinstaller\aleapp.spec
Per creare aleappGUI.exe, esegui:
pyinstaller scripts\pyinstaller\aleappGUI.spec
macOS
Per creare aleapp, esegui:
pyinstaller scripts/pyinstaller/aleapp_macOS.spec
Per creare aleappGUI.app, esegui:
pyinstaller scripts/pyinstaller/aleappGUI_macOS.spec
Linux
Per creare aleapp, esegui:
pyinstaller scripts/pyinstaller/aleapp_Linux.spec
Per creare aleappGUI, esegui:
pyinstaller scripts/pyinstaller/aleappGUI_Linux.spec
Utilizzo
CLI
$ python aleapp.py -t <zip | tar | fs | gz> -i <percorso_estrazione> -o <percorso_output_report>
GUI
$ python aleappGUI.py
Aiuto
$ python aleapp.py --help
Contribuire con plugin per gli artefatti
Ogni plugin è un file sorgente Python che deve essere aggiunto alla cartella scripts/artifacts e verrà caricato dinamicamente ogni volta che ALEAPP viene eseguito.
Il file sorgente del plugin deve contenere un dizionario chiamato __artifacts_v2__ all'inizio del modulo, che definisce gli artefatti elaborati dal plugin. Le chiavi nel dizionario __artifacts_v2__ devono essere ID per gli artefatti, univoci all'interno di ALEAPP. I valori devono essere dizionari contenenti le seguenti chiavi:
name: Il nome dell'artefatto come stringa.description: Una descrizione dell'artefatto come stringa.author: L'autore del plugin come stringa.version: La versione dell'artefatto come stringa.date: La data dell'ultimo aggiornamento dell'artefatto come stringa.requirements: Eventuali requisiti per l'elaborazione dell'artefatto come stringa.category: La categoria dell'artefatto come stringa.notes: Eventuali note aggiuntive come stringa.paths: Una tupla di stringhe contenente pattern di ricerca glob per corrispondere al percorso dei dati che il plugin si aspetta per l'artefatto.function: Il nome della funzione che è il punto di ingresso per l'elaborazione dell'artefatto come stringa.
Ad esempio:
__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"
}
}
Le funzioni referenziate come punti di ingresso nel dizionario __artifacts__ devono accettare i seguenti argomenti:
- Un iterabile dei file trovati da elaborare (come stringhe)
- Il percorso della cartella di output di ALEAPP (come stringa)
- Il seeker (di tipo FileSeekerBase) che ha trovato i file
- Un valore booleano che indica se il plugin deve o meno andare a capo nel testo
Ad esempio:
def get_cool_data1(files_found, report_folder, seeker, wrap_text):
pass # do processing here
Ci si aspetta generalmente che i plugin forniscano output nel formato HTML di ALEAPP, TSV e, opzionalmente, inviino record alla timeline. Le funzioni per generare questo output si trovano nei moduli artifact_report e ilapfuncs. A livello generale, un esempio potrebbe assomigliare 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)
Dati di test e sample_data per la tua PR
Una PR che aggiunge o modifica un artefatto è più facile da revisionare e unire quando arriva con due cose: una piccola fixture di test tagliata da un'estrazione reale e valori sample_data che registrano ciò che il modulo ha prodotto. Gli script generano entrambi. Ecco l'intero flusso.
Una regola prima di tutto: qualunque cosa committi qui diventa pubblica. Usa solo dati che sei autorizzato a condividere, come un dispositivo di test che hai popolato tu stesso, un'immagine di ricerca pubblica o un file che hai ripulito a mano. Mai dati di casi reali.
1. Taglia una fixture dalla tua estrazione
python admin/test/scripts/make_test_data.py <module> --case 1 --input <extraction.zip>
Questo estrae i file che corrispondono ai pattern paths del tuo modulo dall'estrazione e scrive il file del caso admin/test/cases/testdata.<module>.json più un piccolo zip per ogni artefatto in admin/test/cases/data/<module>/.
Regole sulle dimensioni: sotto i 10 MB per zip, committalo con la PR. Tra 10 e 25 MB, committa il file del caso e allega lo zip a un commento della PR. Più grande di così, dillo nella PR e un maintainer organizzerà un passaggio di consegne.
2. Registra l'output atteso
TZ=UTC python admin/test/scripts/test_module.py <module> -a all -c all
Questo esegue il modulo contro la fixture e scrive un'istantanea dell'output in admin/test/results/<module>/. Committa anche l'istantanea. Diventa la baseline che protegge il modulo dopo l'unione. Mantieni la parte TZ=UTC: le istantanee committate sono in UTC e la CI esegue in UTC.
3. Esegui lo stesso confronto che eseguirà la CI
python admin/test/scripts/run_test_cases.py --module <module>
4. Genera i valori sample_data
python admin/scripts/validate_sample_data.py --emit <extraction.zip> --key <image_name>
Questo esegue ALEAPP end-to-end sulla tua estrazione e stampa blocchi sample_data pronti da incollare per i moduli modificati sul tuo branch. Incollali nel __artifacts_v2__ del tuo modulo e aggiungi il nome dell'app e la versione che hai visto sull'immagine. Se un conteggio è zero, verifica che il file sorgente sia davvero vuoto prima di registrarlo.
5. Committa tutto e apri la PR
Committa insieme il modulo, il file del caso, gli zip delle fixture e l'istantanea registrata. Maggiori dettagli sono disponibili in admin/docs/testing/create_module_test_cases.md.
Se la tua estrazione non può essere condivisa, apri comunque la PR e dillo. Una fixture può spesso essere tagliata da un'immagine di ricerca pubblica, oppure il file reale può essere ripulito a mano. La revisione non si ferma mentre risolviamo la questione.
Ringraziamenti
Questo strumento è il risultato di uno sforzo collaborativo di molte persone nella comunità DFIR.
Logo ALEAPP per gentile concessione di Derek Eiri.