Skip to content
KitploitKITPLOIT
도구익스플로잇블로그
Log in
제출
도구익스플로잇블로그
제출

해킹, 침투 테스트 및 사이버 보안 도구를 당신의 보안 무기고에!

Kitploit은 해킹, 사이버 보안 및 침투 테스트 도구 디렉토리입니다. 최신 프로젝트 업데이트를 발견하여 취약점을 찾고, 시스템을 분석하고, 테스트를 자동화하고, 보안을 강화하세요.

피드문의개인정보© 2026 Kitploit

도구 디렉토리

카테고리

모든 카테고리 보기
Loading categories
aotopsy — Flutter/Dart AOT 스냅샷용 정적 분석기 — Dart VM을 임베드하거나 실행하지 않고 libapp.so에서 함수 이름, 클래스 계층 구조, 호출 그래프, 동작 신호를 복구합니다. ARM64 및 x86_64, Dart 2.10–3.12를 지원합니다. | Kitploit
도구/GitHubGitHub/bronils/aotopsy
Static AnalysisMobile App PentestingReverse EngineeringMobile SecurityBinary Analysis
GitHubbronils/aotopsy

aotopsy

Flutter/Dart AOT 스냅샷용 정적 분석기 — Dart VM을 임베드하거나 실행하지 않고 libapp.so에서 함수 이름, 클래스 계층 구조, 호출 그래프, 동작 신호를 복구합니다. ARM64 및 x86_64, Dart 2.10–3.12를 지원합니다.

저장소 보기
3910731개월 전Kitploit 검토 완료

인기

모두 보기 →

커뮤니티에서 가장 많이 사용되는 도구를 찾아보세요.

모든 도구 탐색

도구 컬렉션을 둘러보세요

모든 도구 보기 →
공유

AOTopsy

CI Release License

Dart AOT 스냅샷 분석기입니다. Flutter 릴리스 APK 내부의 컴파일된 Dart 코드인 libapp.so를 함수 이름, 클래스 레이아웃, 호출 그래프, 행위 신호, 그리고 읽을 수 있는 의사코드로 변환합니다. Dart VM도, SDK 컴파일도, 런타임 폴백도 필요 없습니다.

포크 공지: AOTopsy는 원래 Anthony Zboralski가 만든 unflutter의 포크입니다. 원본 zboralski/unflutter 저장소는 더 이상 사용할 수 없으며(작성자가 제거함), 커뮤니티 후속 저장소가 KristijanZic/unflutter에 존재합니다. 원본 스냅샷 파서, 클러스터 역직렬화기, ARM64 디스어셈블리 파이프라인, 그리고 Ghidra/IDA 통합에 대한 모든 공로는 원저자에게 있습니다. AOTopsy는 여기에 x86_64 지원, 네이티브 디컴파일러, 전체 프로그램 타입 추론, Frida 스크립트 생성, 그리고 포괄적인 문서를 추가로 확장했습니다.

복원하는 정보

출력설명
함수 이름각 컴파일된 함수의 원래 Dart 이름
클래스 구조필드 이름, 바이트 오프셋, 상속 체인
호출 그래프출처 정보가 포함된 직접(BL) 및 간접(BLR/디스패치) 호출 엣지
문자열 참조어떤 함수가 객체 풀에서 어떤 문자열 리터럴을 로드하는지
행위 신호암호화, 네트워크, 도박, SIM, 위치, WebView, 블록체인 키워드 분류
의사코드ARM64 또는 x86_64 기계어로부터 생성된 아키텍처 중립적 디컴파일 출력
Dart 소스 내보내기클래스, 필드, 메서드가 재구성된 전체 프로젝트 모듈식 .dart 파일

ARM64와 x86_64를 지원합니다. Dart 2.10부터 3.13까지를 다룹니다(3.13.2가 현재 안정 프런티어) — 모델링된 모든 버전이 두 아키텍처 모두에서 깔끔하게 파싱됩니다. COVERAGE.md 참조(샘플 빌드 93개, 실패 0건).

정확성과 정직성

AOTopsy는 주장이 아니라 정답(ground truth)에 대해 측정됩니다. 두 가지 속성이 모든 변경 시 테스트 스위트에 의해 강제됩니다:

지표값의미
이름 복원 일치율44개 정답 빌드 전반에서 전체 90.2% (최악 구간 81.3%, ≥ 0.81 게이트 하한)복원된 함수 이름을 각 빌드 자체의 ELF .symtab(외부 정답)과 비교 — TestSymtabDifferential. 빌드별 전체 점수표: BENCHMARK.md (make bench).
디컴파일러 구문 유효성100% 유효한 Dart출력된 모든 의사코드 함수가 Dart로 파싱됨 — TestDecompileQualityCorpus.
날조율0%§2 규칙: 추측한 이름, 타입, 호출 대상을 사실로 출력하지 않음. 미지의 항목은 정직하게 표시됨(indirectCall, <unknown>, dynamic).

정답 트윈은 재배포할 수 없는 실제 프로덕션 빌드이므로, 해당 차등 게이트는 로컬에서 실행됩니다. 공개 CI는 빌드, vet, gofmt, staticcheck, 단위 테스트(셔플됨), 그리고 플랫폼 매트릭스 전반의 커버리지 하한을 검증합니다. samples/는 재배포할 수 없으며 gitignore되어 있으므로, 샘플에 의존하는 테스트는 그곳에서 건너뜁니다 — 단, 코퍼스가 완전히 없을 때만 그렇습니다. 코퍼스가 존재하는데 등록된 샘플이 누락된 경우는 실패합니다. 이 둘은 정반대의 의미이기 때문입니다. 여기의 모든 수치가 어떻게 측정되는지(정답, 지표 정의, 재현): METHODOLOGY.md. 릴리스 바이너리 검증과 아래의 정직한 범위는 SECURITY.md를 참조하세요.

빠른 시작

make build
./aotopsy libapp.so                    # full pipeline
./aotopsy doctor libapp.so             # quick diagnostic
./aotopsy export-dart --lib libapp.so --out ./lib  # reconstruct entire Dart source project
./aotopsy _debug decompile-native --lib libapp.so --find MyClass  # find and decompile a function

실제 스냅샷에서 5분 동안 진행되는 워크스루는 DEMO.md를 참조하거나, 원시 APK가 있고 어디서부터 시작해야 할지 모를 때 단계별 방법론은 WORKFLOW.md를 참조하세요.

작동 방식

AOTopsy는 Dart AOT 스냅샷을 결정론적 바이너리 문법으로 취급합니다. 올바른 제약 조건(ELF 구조, 스냅샷 매직, 버전 해시, CID 테이블, 클러스터 인코딩)이 주어지면 모든 바이트는 정확히 하나의 올바른 해석을 가집니다. 파서는 단 하나의 해석만 남을 때까지 제약 조건을 적용합니다 — 휴리스틱도, 추측도 없습니다.

파이프라인은 여러 단계로 실행되며, 각 단계는 바이트에서 구조화된 데이터로 가는 순수 함수입니다:

flowchart TD
    A[libapp.so] --> B[ELF parse]
    B --> C[snapshot region extraction]
    C --> D[version detection]
    D --> E[cluster alloc<br/>object census]
    E --> F[cluster fill<br/>field values, names, strings]
    F --> G[instructions table<br/>code ranges, stub boundaries]
    G --> H{architecture?}
    H -->|ARM64| I[ARM64 disassembly]
    H -->|x86_64| J[x86_64 disassembly]
    I --> K[CFG + call edges<br/>register provenance]
    J --> K
    K --> L[type inference<br/>BLR receiver type resolution]
    L --> M[signal classification<br/>behavioral keyword matching]
    M --> N[JSONL + HTML + DOT<br/>pseudocode output]

두 개의 독립적인 백엔드는 동일한 전반부(ELF부터 클러스터 채우기까지)를 공유한 다음 아키텍처별로 분기됩니다: ARM64용 internal/disasm, x86_64용 internal/disasm/x86.go. 디컴파일러(internal/decompiler)는 통합 IR을 통해 두 아키텍처를 모두 처리합니다.

flowchart LR
    subgraph "Shared front half"
        A[elfx] --> B[snapshot]
        B --> C[cluster]
    end
    subgraph "ARM64 backend"
        C --> D1[disasm ARM64]
        D1 --> E1[callgraph]
        E1 --> F1[signal]
    end
    subgraph "x86_64 backend"
        C --> D2[disasm x86_64]
        D2 --> E2[callgraph]
        E2 --> F2[signal]
    end
    subgraph "Decompiler (both archs)"
        C --> G[decompiler IR]
        G --> H[pseudocode]
    end

Blutter와의 비교

flowchart LR
    subgraph Blutter
        direction TB
        B1[libapp.so] --> B2[Compile matching<br/>Dart SDK]
        B2 --> B3[Embed Dart VM]
        B3 --> B4[Deserialize via<br/>VM internal APIs]
        B4 --> B5[Perfect fidelity]
    end
    subgraph AOTopsy
        direction TB
        A1[libapp.so] --> A2[Parse binary format<br/>directly]
        A2 --> A3[No VM, no SDK]
        A3 --> A4[Version-specific<br/>format modeling]
        A4 --> A5[Portability + speed]
    end

Blutter는 자체 코드 경로를 통해 스냅샷을 역직렬화하기 위해 Dart VM을 내장합니다. 완벽한 충실도를 제공하지만, 대상 버전마다 일치하는 Dart SDK를 컴파일해야 하며, ARM64 전용으로 정적 x86_64 지원이 없습니다. AOTopsy는 네이티브 의사코드 디컴파일러와 공개된 정답(ground-truth) 정확도를 갖춘 유일한 정적·버전 독립적 분석기입니다.

AOTopsy는 바이너리 형식을 직접 파싱합니다. VM도, SDK도 필요 없습니다. 그 대가로, Dart 버전 간의 모든 형식 변경을 명시적으로 모델링해야 합니다. 이를 자동으로 처리해 줄 런타임이 없습니다.

명령어

전체 파이프라인

aotopsy libapp.so              # disasm + call edges + signal + metadata (ARM64: + Ghidra/IDA)
aotopsy signal libapp.so       # same, skip metadata
aotopsy libapp.so --graph      # also build call graph DOT files

플래그: --out <dir> (기본값: <basename>.aotopsy/), --quiet, --strict, --max-steps <n>, --k <n> (시그널 컨텍스트 깊이, 기본값 2), --decompile.

--decompile은 함수별 Dart 의사코드를 <out>/dart/에 기록합니다. 출력 디렉터리 크기가 대략 세 배로 늘어나기 때문에 기본적으로 꺼져 있습니다. 이 옵션 없이 실행할 때마다 그 사실을 알려주므로, 이 기능은 단순히 존재하는 데 그치지 않고 발견 가능합니다.

진단

aotopsy doctor libapp.so       # Dart version, pointer size, support status, build features
aotopsy find-libapp --apk app.apk  # locate libapp.so inside an APK

전체 프로젝트 Dart 소스 내보내기

모든 클래스, 필드, 메서드, getter, setter, 생성자를 원본 라이브러리 URI에 매핑된 모듈식 .dart 파일로 재구성합니다:

aotopsy export-dart --lib libapp.so --out ./reconstructed_lib/   # full project export
aotopsy export-dart --lib libapp.so --out ./lib/ --app-only      # filter out core/flutter framework
aotopsy export-dart --lib libapp.so --out ./lib/ --filter Auth   # targeted export by name

고수준 네이티브 디컴파일러 (ARM64 + x86_64)

바이너리 기계 명령어로부터 깔끔하고 관용적인 Dart 코드를 직접 생성합니다:

  • 구조적 제어 흐름: 정확한 PC 경계를 갖춘 for-in 반복자, while, for, try-catch-finally.
  • Async/Await 선형화: _SuspendState 상태 머신을 선형적인 await future 및 await for로 풀어냅니다.
  • 람다 인라이닝: 호출 지점에서 화살표 콜백 (item) => process(item)을 직접 합성합니다.
  • 타입 격자: 라이브 VM을 실행하지 않고도 SSA 값 전반에 구체적인 Dart 타입(String, int, UserModel)을 전파합니다.
  • Dart 관용구: Null-aware(?., ??, ??=), 캐스케이드(..), Set/List/Map 리터럴, 문자열 보간("${a}${b}").
aotopsy _debug decompile-native --lib libapp.so --find MyClass         # locate by name
aotopsy _debug decompile-native --lib libapp.so --func 0x1a92728       # one function at a VA
aotopsy _debug decompile-native --lib libapp.so --from-main --out out/ # reachability from app entry
aotopsy _debug decompile-native --lib libapp.so --all --filter MyClass # bulk, filtered

경고: 작은 --max 없이 --all을 사용하면 실제 앱에서 약 64GB의 RAM이 필요할 수 있습니다. --find/--func/--from-main을 선호하세요.

Ghidra / IDA (ARM64 전용)

aotopsy ghidra libapp.so        # headless Ghidra with metadata injection
aotopsy ida libapp.so           # headless IDA via idalib

둘 다 x86_64 입력을 거부합니다. x86_64 의사코드에는 decompile-native를 사용하세요.

Frida 스크립트 생성

도구 다운로드