yanghuafang/anti-android-virus
GitHub: yanghuafang/anti-android-virus
一款基于 C++17 的 Android 恶意软件静态检测引擎,通过解析 DEX/APK 字节码并匹配多维度特征签名来识别恶意软件及其家族归属。
Stars: 1 | Forks: 1
# anti-android-virus (aav) — Android 恶意软件静态检测引擎
[](https://github.com/yanghuafang/anti-android-virus/actions/workflows/ci.yml)
[](LICENSE)
[](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++, 云安全监控, 反病毒引擎, 数据擦除, 静态分析