العودة إلى التحديثات
New releaseSep 11, 2026

ALEAPP v2026.3.3

محلل سجلات وأحداث أندرويد وبروتوبوف

مشاركة

ALEAPP

محلّل سجلات وأحداث وأحداث Protobuf لأندرويد

إذا كنت ترغب في المساهمة، تواصل معي هنا: https://abrignoni.github.io

منشورات المدونة هنا: https://leapps.org/blog

المتطلبات

Python 3.10 أو أحدث

التبعيات

التبعيات الخاصة ببيئة Python لديك مدرجة في requirements.txt. قم بتثبيتها باستخدام الأمر أدناه. تأكد من أن جزء py صحيح لبيئتك، مثل py أو python أو python3، إلخ.

py -m pip install -r requirements.txt أو pip3 install -r requirements.txt

للتشغيل على Linux، ستحتاج أيضًا إلى تثبيت tkinter بشكل منفصل كما يلي:

sudo apt-get install python3-tk

الترجمة إلى ملف تنفيذي

للترجمة إلى ملف تنفيذي حتى تتمكن من تشغيله على نظام بدون Python مثبّت.

Windows OS

لإنشاء aleapp.exe، شغّل:

pyinstaller scripts\pyinstaller\aleapp.spec

لإنشاء aleappGUI.exe، شغّل:

pyinstaller scripts\pyinstaller\aleappGUI.spec

macOS

لإنشاء aleapp، شغّل:

pyinstaller scripts/pyinstaller/aleapp_macOS.spec

لإنشاء aleappGUI.app، شغّل:

pyinstaller scripts/pyinstaller/aleappGUI_macOS.spec

Linux

لإنشاء aleapp، شغّل:

pyinstaller scripts/pyinstaller/aleapp_Linux.spec

لإنشاء aleappGUI، شغّل:

pyinstaller scripts/pyinstaller/aleappGUI_Linux.spec

الاستخدام

CLI

$ python aleapp.py -t <zip | tar | fs | gz | raw> -i <path_to_extraction> -o <path_for_report_output>

يقرأ raw صورة قرص (.img أو .dd أو .bin أو أي مقطع مرقّم .001 من مجموعة مقسّمة)، أو حيازة EnCase/EWF بامتداد .E01 والمقاطع المجاورة لها، في مكانها: دون تركيب ودون صلاحيات مسؤول. يتم البحث مباشرة في وحدات تخزين NTFS وFAT32 وexFAT وext2/3/4 وF2FS وHFS+ وAPFS وQNX6 وQNX4 وETFS وEFS وSquashFS وJFFS2 وUBI/UBIFS وYAFFS وQNX IFS، ولا يتم قراءة سوى الملفات التي يطلبها الأثر من الصورة. تختار الواجهة الرسومية raw من تلقاء نفسها لتلك الامتدادات. راجع admin/docs/raw_image_input.md.

يقرأ tar أيضًا ملف tar مضغوطًا بـ xz (.tar.xz)، وتختار الواجهة الرسومية tar لذلك الامتداد. يتم فك ضغط ملف tar المضغوط، بما في ذلك .tar.gz، مرة واحدة إلى مجلد التقرير قبل قراءة أي ملف، لذا يحتاج التشغيل إلى مساحة خالية هناك لملف tar غير المضغوط. يتم حذف النسخة عند انتهاء التشغيل، ويوضّح سجل التشغيل المدة التي استغرقتها هذه الخطوة.

GUI

$ python aleappGUI.py

المساعدة

$ python aleapp.py --help

المساهمة بإضافات الآثار

كل إضافة هي ملف مصدر Python يجب إضافته إلى مجلد scripts/artifacts والذي سيتم تحميله ديناميكيًا في كل مرة يتم فيها تشغيل ALEAPP.

يجب أن يحتوي ملف مصدر الإضافة على قاموس باسم __artifacts_v2__ في بداية الوحدة تمامًا، والذي يعرّف الآثار التي تعالجها الإضافة. يجب أن تكون المفاتيح في قاموس __artifacts_v2__ معرّفات للأثر (أو الآثار) ويجب أن تكون فريدة داخل ALEAPP. يجب أن تكون القيم قواميس تحتوي على المفاتيح التالية:

  • name: اسم الأثر كسلسلة نصية.
  • description: وصف الأثر كسلسلة نصية.
  • author: مؤلف الإضافة كسلسلة نصية.
  • version: إصدار الأثر كسلسلة نصية.
  • date: تاريخ آخر تحديث للأثر كسلسلة نصية.
  • requirements: أي متطلبات لمعالجة الأثر كسلسلة نصية.
  • category: فئة الأثر كسلسلة نصية.
  • notes: أي ملاحظات إضافية كسلسلة نصية.
  • paths: مجموعة (tuple) من السلاسل النصية تحتوي على أنماط بحث glob لمطابقة مسار البيانات التي تتوقعها الإضافة للأثر.
  • function: اسم الدالة التي تُعد نقطة الدخول لمعالجة الأثر كسلسلة نصية.

على سبيل المثال:

__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"
    }
}

يجب أن تأخذ الدوال المشار إليها كنقاط دخول في قاموس __artifacts__ الوسائط التالية:

  • كائن قابل للتكرار من الملفات التي تم العثور عليها والتي سيتم معالجتها (كسلاسل نصية)
  • مسار مجلد مخرجات ALEAPP (كسلسلة نصية)
  • الباحث (seeker) (من نوع FileSeekerBase) الذي وجد الملفات
  • قيمة منطقية تشير إلى ما إذا كان من المتوقع أن تقوم الإضافة بلف النص أم لا

على سبيل المثال:

def get_cool_data1(files_found, report_folder, seeker, wrap_text):
    pass  # do processing here

يُتوقع عمومًا من الإضافات تقديم المخرجات بصيغة HTML الخاصة بـ ALEAPP، وTSV، واختياريًا إرسال سجلات إلى الخط الزمني. يمكن العثور على الدوال الخاصة بإنشاء هذه المخرجات في وحدتي artifact_report وilapfuncs. على مستوى عالٍ، قد يبدو المثال مشابهًا لما يلي:

__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)

بيانات الاختبار وsample_data لطلب السحب (PR) الخاص بك

يكون طلب السحب (PR) الذي يضيف أو يغيّر أثرًا أسهل في المراجعة والدمج عندما يصل مصحوبًا بأمرين: عيّنة اختبار صغيرة مقتطعة من استخراج حقيقي، وقيم sample_data التي تسجّل ما أنتجته الوحدة. تُنشئ السكربتات كليهما. إليك سير العمل كاملًا.

قاعدة واحدة قبل أي شيء آخر: كل ما تلتزم به هنا يصبح عامًا. استخدم فقط البيانات المسموح لك بمشاركتها، مثل جهاز اختبار قمت بتعبئته بنفسك، أو صورة بحثية عامة، أو ملف قمت بتنقيته يدويًا. لا تستخدم أبدًا بيانات قضايا حقيقية.

1. اقتطع عيّنة اختبار من الاستخراج الخاص بك

python admin/test/scripts/make_test_data.py <module> --case 1 --input <extraction.zip>

يقوم هذا بسحب الملفات التي تطابقها أنماط paths الخاصة بوحدتك من الاستخراج ويكتب ملف الحالة admin/test/cases/testdata.<module>.json بالإضافة إلى ملف zip صغير واحد لكل أثر ضمن admin/test/cases/data/<module>/.

قواعد الحجم: أقل من 10 ميغابايت لكل zip، التزم به مع طلب السحب. بين 10 و25 ميغابايت، التزم بملف الحالة وأرفق ملف zip في تعليق على طلب السحب. أكبر من ذلك، اذكر ذلك في طلب السحب وسيرتّب أحد المشرفين عملية التسليم.

2. سجّل المخرجات المتوقعة

TZ=UTC python admin/test/scripts/test_module.py <module> -a all -c all

الفئات