yanghuafang/anti-android-virus

GitHub: yanghuafang/anti-android-virus

一款基于 C++17 的 Android 恶意软件静态检测引擎,通过解析 DEX/APK 字节码并匹配多维度特征签名来识别恶意软件及其家族归属。

Stars: 1 | Forks: 1

# anti-android-virus (aav) — Android 恶意软件静态检测引擎 [![CI](https://static.pigsec.cn/wp-content/uploads/repos/cas/39/39faa54be350a1dab8afd3b2fb8c1c83e4d9cff84abfef2374d19a18053687c4.svg)](https://github.com/yanghuafang/anti-android-virus/actions/workflows/ci.yml) [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE) [![C++17](https://img.shields.io/badge/C%2B%2B-17-blue.svg)](https://en.cppreference.com/w/cpp/17) `aav`(**Anti-Android-Virus** 的缩写)是一个**静态**(非模拟)的 Android 恶意软件检测引擎。它解析 DEX bytecode(以及 APK 内部的 `classes.dex`),并将其与紧凑、多维度的**特征数据库**进行匹配——包括类路径签名、opcode 序列和 string/operand 序列的 CRC、opcode bitmap 预过滤器,以及 AND/OR/XOR/NOT 逻辑组合——以此来判定文件是否为恶意文件,如果是,则判定其属于哪个家族。 该引擎基于硕士论文《一种高效的 Android 恶意软件静态检测系统》;有关该设计如何映射到代码的内容,请参阅 [`docs/Architecture.md`](docs/Architecture.md)。 ## 为什么开发这个项目 | | | |---|---| | **纯静态,无需模拟** | 通过解析 DEX bytecode 和匹配签名来检测恶意软件——无需沙箱,无需执行——因此在处理不受信任的输入时既快速又安全。 | | **多维度检测** | 结合了类路径签名、opcode 和 string 序列 CRC、opcode bitmap 预过滤器,以及 AND/OR/XOR/NOT 逻辑——而不是单一脆弱的启发式算法。 | | **一种抽象,文件与内存兼顾** | 一个小型的 `IStream` / `ITarget` 层次结构允许*相同*的扫描器在磁盘上的文件**或** RAM 中的块上运行(`Scan` 对比 `ScanBuffer`)——非常适合设备端和网关扫描。参见 [docs/ObjectModel.md](docs/ObjectModel.md)。 | | **真正的 ABI 稳定的 SDK** | 整个引擎由一个命名空间化的外观(`aav::IEngine`)驱动,该外观在跨越边界时仅使用 PODs、C strings 和一个 callback,因此预编译的 `libaav.so` 可以在不同编译器之间保持兼容。 | | **自包含且经过测试** | `sigtool` 会生成一致的样本数据库 + DEX,因此它可以在没有外部资产的情况下进行端到端的构建、运行和测试;在 ASan/UBSan 下进行了 fuzz 测试,并在 Linux、macOS 和 Android 上集成了 CI。 | | **基于学术论文** | 实现了《一种高效的 Android 恶意软件静态检测系统》中的设计——是一个紧凑、易读的代码库,适合用于学习该设计。 | ## 工作原理 ``` file or directory │ FileID: DEX, ZIP/APK, or unknown? (from magic) ▼ ┌── ZIP/APK ─► ApkScanner: unpack classes*.dex (miniz), scan each ─┐ │ │ └── DEX ───────────────────────────────────────────► DexScanner ◄─┘ │ DexFile parse header, id tables, classes, methods, code items │ DexCode per method: opcode buffer + operand/string buffer (+ CRC32s) │ opcode bitmap pre-filter ─► DexSigMgr: path / opcode-CRC / operand-CRC + AND/OR/XOR/NOT logic ─► matched sig IDs │ ▼ ScanReport (path, is_malware, sig IDs + names) ``` 引擎接收一个文件或内存中的镜像,对其进行识别,并——对于 DEX 或 APK 内部的 `classes*.dex`——将每个方法简化为紧凑的**特征**(类路径、opcode 序列、引用的 string),以便与特征数据库进行匹配。完整解析过程:[docs/Architecture.md](docs/Architecture.md);使文件和内存可互换的接口层次结构详见 [docs/ObjectModel.md](docs/ObjectModel.md)。 ## 功能特性 - **DEX 静态分析** — 一个经过强化、带有边界检查的 DEX 解析器(在 ASan/UBSan 下进行了 fuzz 测试),可遍历类、方法和代码项。支持 DEX 版本 `035`–`040`(Android 1.0 到 10+),包括现代的 method-handle / invoke-custom opcode(DEX 038/039)。 - **多维度匹配** - 通过对每个段进行 CRC32 的 Aho–Corasick trie 实现 class-path 签名; - 使用 opcode **bitmap** 预过滤器低成本地跳过无关方法; - opcode 序列和 operand (string) 序列的 **CRC** 签名; - 基于 code CRC 的**逻辑组合**(AND/OR/XOR/NOT)以确认命中。 - **APK 支持** — 从 zip 容器(通过内置的 vendored miniz)中提取每一个 multidex 成员(`classes.dex`、`classes2.dex` 等),扫描它们并合并命中结果。 - **自包含工具** — `sigtool` 可合成一致的样本 DEX 和匹配的加密/压缩特征数据库,因此整个 pipeline 无需外部资产即可实现端到端运行和测试。 - **现代 C++17** — RAII 所有权(`aav::ObjPtr`),工厂函数,无需手动编写引用计数,支持 Linux 和 macOS 跨平台。 ## 环境要求 - CMake ≥ 3.20 - 一个 C++17 编译器(GCC ≥ 9,Clang ≥ 10,或 Apple Clang) - zlib(Debian/Ubuntu 上为 `zlib1g-dev`;macOS 上已预装) - *(可选)* 带有 libFuzzer + sanitizer runtime 的 Clang,用于构建 fuzzer APK/zip 支持(miniz)作为 vendored 依赖包含在 `third_party/` 下——无需额外依赖。 ## 快速开始 ``` # 配置 + 构建(Debug,启用 unit/e2e 测试) cmake --preset debug -DAAV_BUILD_TESTS=ON cmake --build build/debug -j # 生成自洽的样本 DEX + signature DB ./build/debug/bin/sigtool gen-sample samples # 扫描样本: ./build/debug/bin/aavscan samples/sample.sig samples/sample.dex ``` 预期输出: ``` file: samples/sample.dex isMalware: 1 isWhite: 0 sigID: 1002 Trojan!SampleFam.a@Android.Dex sigID: 1001 Trojan!SampleFam.a@Android.Dex scanned 1 file(s), 1 flagged, 0s ``` `aavscan` 接受单个文件或目录(它会遍历目录并扫描找到的每个 `*.apk` / `*.dex`),以及一些可选的运行时 flag: - `--debug` — 详细的引擎诊断(主机上输出到 stderr,Android 上输出到 logcat),默认关闭以保持实时扫描的快速。 - `--analysis` — 扫描后,打印每个方法的 opcode/operand CRC32s 和引用的 string。这是用于编写新签名的数据;默认情况下关闭,因为它会记录每个方法(无 bitmap 预过滤),因此速度较慢。 - `--mt ` — 使用 `` 个 worker thread 扫描目录(默认 `1` = 顺序执行)。只有目录扫描会被并行化;单个文件始终在调用线程中扫描。报告依然会逐一输出,因此除了顺序之外,输出结果与顺序扫描保持一致。 完整用法: `aavscan [--debug] [--analysis] [--mt ] `。 ## 引擎嵌入 引擎通过一个小的外观 `aav/engine_interface.h`(外加 `aav/object_interface.h`,即 `IObject::Destroy()` 基类)来驱动。这是**整个**公共 API,并且特意设计成了 **ABI 稳定**的:跨越边界的只有 PODs、C strings 和一个 callback——没有 `std::` 容器或 smart pointers——因此预编译的 `libaav.so` 可以在不同的编译器/标准库版本之间保持兼容。文件识别、特征数据库加载、扫描器选择、APK 解包和目录遍历全部隐藏在其中: ``` #include "aav/engine_interface.h" static void on_report(const aav::ScanReport* r, void* user) { if (r->is_malware) { // r->path, r->sig_ids[0..sig_count), r->names[...], and r->methods[...] when // analysis is enabled -- all engine-owned, valid only during this call. } } aav::IEngine* engine = aav::MakeEngine(); aav::EngineConfig config; // scan_apk / scan_dex / recurse_dirs / verbose / // analysis / scan_threads (>1 parallelizes dir scans) engine->Init("samples/sample.sig", &config); engine->Scan("path/to/file-or-dir", on_report, nullptr); // file OR dir; APKs unpacked // ...or scan an image already in RAM (no file on disk); apk/dex auto-detected: engine->ScanBuffer(bytes, size, "app.apk", on_report, nullptr); engine->Destroy(); // release the engine (never `delete` it) ``` 使用 `target_link_libraries(app PRIVATE aav::aav)`(静态)或 `aav::shared`(动态)链接引擎。请参阅 [安装 / SDK](#install--sdk),了解如何通过 `find_package(aav)` 将其作为打包的 SDK 使用。 ## 脚本 喜欢单行命令?[`scripts/`](scripts/) 封装了上述命令: ``` scripts/build.sh # configure + build (engine, aavscan, sigtool) scripts/test.sh # build + unit + e2e tests scripts/run.sh # generate a sample and scan it end-to-end scripts/asan.sh # sanitizer build + tests scripts/format.sh # clang-format check (--fix to apply) ``` 完整脚本集合(fuzzing、Android、清理等)请参见 [`scripts/README.md`](scripts/README.md)。 ## 构建选项 | 选项 | 默认值 | 描述 | | ------------------- | ------- | ---------------------------------------------- | | `AAV_BUILD_TOOLS` | `ON` | 构建 `sigtool`(样本/数据库生成器) | | `AAV_BUILD_TESTS` | `OFF` | 构建单元测试 + 注册 CTest suite | | `AAV_BUILD_FUZZERS` | `OFF` | 构建 libFuzzer harness(es)(仅限 Clang) | | `AAV_ENABLE_APK` | `ON` | 通过内置的 miniz 进行 APK/zip 扫描 | | `AAV_BUILD_SHARED` | `ON` | 构建动态库(`libaav.so`/`.dylib`)| | `AAV_INSTALL` | `ON`\* | 生成 SDK 安装规则(\*仅限顶层目录) | 配置预设(`CMakePresets.json`):`debug`、`release`、`asan`。 ## 安装 / SDK 引擎以 SDK 的形式发布——包含公共头文件以及一个静态**和**一个动态库——可以安装到任何 prefix: ``` cmake --preset release && cmake --build build/release -j cmake --install build/release --prefix /path/to/sdk ``` 文件分布如下: ``` /path/to/sdk/ ├── include/aav/ # public headers: engine_interface.h, object_interface.h, aav.h └── lib/ ├── libaav.a # static ├── libaav.so / libaav.dylib # shared (self-contained: miniz built in) └── cmake/aav/ # find_package(aav) config ``` 在另一个 CMake 项目中使用它: ``` find_package(aav REQUIRED) target_link_libraries(myapp PRIVATE aav::aav) # static # 或者: target_link_libraries(myapp PRIVATE aav::shared) ``` ## 测试 ``` # Unit + end-to-end 测试 cmake --preset debug -DAAV_BUILD_TESTS=ON && cmake --build build/debug -j ctest --test-dir build/debug --output-on-failure # AddressSanitizer + UndefinedBehaviorSanitizer cmake --preset asan -DAAV_BUILD_TESTS=ON && cmake --build build/asan -j ctest --test-dir build/asan --output-on-failure ``` 对 DEX 解析器进行 fuzz 测试(需要带有 libFuzzer 的 Clang 工具链): ``` cmake -S . -B build/fuzz -DAAV_BUILD_FUZZERS=ON -DAAV_BUILD_TOOLS=OFF \ -DCMAKE_CXX_COMPILER=clang++ cmake --build build/fuzz --target fuzz_dexfile -j ./build/fuzz/bin/fuzz_dexfile -max_total_time=60 ``` CI(GitHub Actions)涵盖了三个受支持的平台——**Ubuntu 24.04 / 26.04 (x86_64)**(GCC + Clang)和 **macOS (ARM64)** 构建 + 测试,以及 **Android (ARM64, arm64-v8a)** NDK 交叉编译。它还会运行 ASan/UBSan 套件,检查代码格式,并在 Linux 上对 fuzzer 进行冒烟测试。 ## 项目布局 ``` . ├── CMakeLists.txt # root build: aav static lib + aavscan + sigtool ├── CMakePresets.json # debug / release / asan presets ├── include/aav/ # public SDK: engine_interface.h + object_interface.h + aav.h ├── src/ │ ├── engine/ # the IEngine facade implementation │ ├── api/aav/ # internal object API (interfaces, factories, data records) — not exported │ ├── platform/ # file/memory primitives (FileStream, FileTarget, FileMap, MemTarget) │ ├── utils/ # crc32, leb128, blowfish, gzip inflate, logger │ ├── sig/ # signature-DB load/decrypt/decompress, format │ ├── dex/ # DEX parser + path/opcode/operand/logic matchers │ └── scan/ # file-type id (FileID) + APK (zip) white-list check ├── apps/ │ ├── aavscan/ # CLI scanner (thin facade consumer) │ └── sigtool/ # sample DEX + signature-DB generator ├── android/ # Gradle + NDK app; JNI bridge over the engine ├── tests/ # doctest unit tests + generate-and-scan CTest ├── fuzz/ # libFuzzer harness for the DEX parser ├── third_party/ # vendored: miniz (zip), doctest └── docs/ # Architecture.md, SignatureDbFormat.md ``` ## 文档 完整索引:[`docs/README.md`](docs/README.md)。 | 指南 | 主题 | |-------|--------| | [Architecture.md](docs/Architecture.md) | 扫描 pipeline、引擎组件、论文到代码的映射 | | [ObjectModel.md](docs/ObjectModel.md) | 接口层次结构、文件与内存抽象、RAII、命名空间 | | [Building.md](docs/Building.md) | 构建选项、安装/SDK、测试、sanitizer、fuzzing、Android | | [Signatures.md](docs/Signatures.md) | 使用 `sigtool` / `aavscan --analysis` 编写签名 | | [SignatureDbFormat.md](docs/SignatureDbFormat.md) | 磁盘上的 `*.sig` 特征数据库二进制格式 | | [CONTRIBUTING.md](CONTRIBUTING.md) | 构建、测试和 pull-request 工作流 | ## Android 核心引擎(`libaav`)和 `aavscan` CLI **可通过 NDK 对 Android 进行交叉编译**;CI 会在每次更改时构建 arm64-v8a (ARM64) ABI: ``` cmake -S . -B build/android \ -DCMAKE_TOOLCHAIN_FILE="$ANDROID_NDK_HOME/build/cmake/android.toolchain.cmake" \ -DANDROID_ABI=arm64-v8a -DANDROID_PLATFORM=android-24 \ -DAAV_BUILD_CLI=OFF -DAAV_BUILD_TOOLS=OFF -DAAV_BUILD_TESTS=OFF cmake --build build/android -j ``` 一个演示性的 **Android app**(`com.av.aav`)位于 [`android/`](android/README.md) 目录下,它通过 JNI 在设备端驱动引擎;其 JNI bridge 是公共 `IEngine` SDK 外观的消费者,并静态链接了 `libaav`(无需单独的引擎 `.so`)。使用 `cd android && ./gradlew :app:assembleDebug` 构建(SDK 36 / NDK 29 / JDK 17);CI 会在每次更改时编译 debug APK。 ## 贡献 欢迎各种贡献——包括解析器强化、新测试、文档、opcode/版本支持以及引擎功能。请阅读 [CONTRIBUTING.md](CONTRIBUTING.md) 了解构建 / 测试 / 代码风格工作流,并在发起 pull request 之前运行 `scripts/test.sh` 和 `scripts/asan.sh`。 ## 许可证 基于 MIT 许可证授权——详见 [`LICENSE`](LICENSE)。
标签:Android安全, Bash脚本, C++, 云安全监控, 反病毒引擎, 数据擦除, 静态分析