업데이트로 돌아가기
New releaseSep 11, 2026

ALEAPP v2026.3.3

안드로이드 로그 이벤트 및 Protobuf 파서

공유

ALEAPP

Android Logs Events And Protobuf Parser

기여하고 싶다면 여기로 연락해 주세요: 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 볼륨을 직접 검색하며, 아티팩트가 요청한 파일만 이미지에서 읽어옵니다. GUI는 해당 확장자에 대해 raw를 자동으로 선택합니다. admin/docs/raw_image_input.md를 참조하세요.

tar는 xz로 압축된 tar(.tar.xz)도 읽으며, GUI는 해당 확장자에 대해 tar를 선택합니다. .tar.gz를 포함한 압축된 tar는 파일을 읽기 전에 보고서 폴더에 한 번 압축 해제되므로, 실행 시 압축 해제된 tar를 위한 여유 공간이 해당 폴더에 필요합니다. 복사본은 실행이 끝나면 삭제되며, 실행 로그에 해당 단계에 걸린 시간이 기록됩니다.

GUI

$ python aleappGUI.py

도움말

$ python aleapp.py --help

아티팩트 플러그인 기여

각 플러그인은 scripts/artifacts 폴더에 추가해야 하는 Python 소스 파일이며, ALEAPP이 실행될 때마다 동적으로 로드됩니다.

플러그인 소스 파일은 모듈의 맨 처음에 __artifacts_v2__라는 이름의 딕셔너리를 포함해야 하며, 이 딕셔너리는 플러그인이 처리하는 아티팩트를 정의합니다. __artifacts_v2__ 딕셔너리의 키는 ALEAPP 내에서 고유해야 하는 아티팩트 ID여야 합니다. 값은 다음 키를 포함하는 딕셔너리여야 합니다:

  • name: 아티팩트의 이름 (문자열).
  • description: 아티팩트에 대한 설명 (문자열).
  • author: 플러그인 작성자 (문자열).
  • version: 아티팩트의 버전 (문자열).
  • date: 아티팩트의 마지막 업데이트 날짜 (문자열).
  • requirements: 아티팩트 처리에 필요한 요구 사항 (문자열).
  • category: 아티팩트의 카테고리 (문자열).
  • notes: 추가 참고 사항 (문자열).
  • paths: 플러그인이 아티팩트에 대해 기대하는 데이터 경로와 일치시키기 위한 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

플러그인은 일반적으로 ALEAPP의 HTML 출력 형식, 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)

PR을 위한 테스트 데이터 및 sample_data

아티팩트를 추가하거나 변경하는 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>/ 아래에 작성합니다.

크기 규칙: zip당 10 MB 미만이면 PR과 함께 커밋하세요. 10~25 MB 사이면 케이스 파일을 커밋하고 zip은 PR 댓글에 첨부하세요. 그보다 크면 PR에 그렇게 알려주시면 메인테이너가 전달 방법을 마련해 드립니다.

2. 예상 출력 기록하기

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

이 명령은 픽스처에 대해 모듈을 실행하고 출력 스냅샷을 admin/test/results/<module>/ 아래에 작성합니다. 스냅샷도 커밋하세요. 이는 병합 후 모듈을 보호하는 기준선이 됩니다. TZ=UTC 부분은 유지하세요: 커밋된 스냅샷은 UTC 기준이며 CI도 UTC로 실행됩니다.

3. CI가 실행할 것과 동일한 비교 실행하기

python admin/test/scripts/run_test_cases.py --module <module>

4. sample_data 값 생성하기

python admin/scripts/validate_sample_data.py --emit <extraction.zip> --key <image_name>

이 명령은 추출에 대해 ALEAPP을 처음부터 끝까지 실행하고, 브랜치에서 변경된 모듈에 대해 바로 붙여넣을 수 있는 sample_data 블록을 출력합니다. 이를 모듈의 __artifacts_v2__에 붙여넣고 이미지에서 확인한 앱 이름과 버전을 추가하세요. 개수가 0이면 기록하기 전에 원본 파일이 정말 비어 있는지 확인하세요.

5. 모두 커밋하고 PR 열기

모듈, 케이스 파일, 픽스처 zip, 기록된 스냅샷을 함께 커밋하세요. 자세한 내용은 admin/docs/testing/create_module_test_cases.md에 있습니다.

추출을 공유할 수 없다면 그래도 PR을 열고 그렇게 알려주세요. 픽스처는 종종 공개 연구 이미지에서 잘라낼 수 있거나, 실제 파일을 직접 정제할 수 있습니다. 이를 해결하는 동안에도 검토는 중단되지 않습니다.

감사의 글

이 도구는 DFIR 커뮤니티의 많은 사람들이 협력한 결과물입니다.

ALEAPP 로고는 Derek Eiri가 제공했습니다.

카테고리