ykus4/fuin
GitHub: ykus4/fuin
fuin 是一款基于 Web UI、REST API 和 CLI 操作的 Android APK 加固工具,通过 AES-256-GCM 加密字节码和资源来抵御逆向工程与应用篡改。
Stars: 0 | Forks: 1

**Android APK Packer — 保护字节码,阻断作弊,抵御逆向工程**
[](LICENSE)
[](https://www.python.org/)
[](https://hub.docker.com/)
[](https://github.com/ykus4/fuin/actions/workflows/ci.yml)
保护任何 Android APK — Unity、Flutter 或标准应用 — 抵御作弊、盗版和逆向工程。
DEX 字节码、原生库(.so)和资源使用 AES-256-GCM 加密。
防篡改、root 检测和模拟器拦截防御 Frida 和 Xposed 等运行时 instrumentation 工具。
无需修改源码。运行时无需网络。完全离线运行。
## 打包时
fuin 通过 Web UI、REST API 或 CLI 对您的 APK 进行一次性处理。原始 APK 绝不会被原地修改;而是生成一个全新的受保护 APK。
```
┌─────────────────────────────────────────────────────────────────┐
│ 📦 PACK TIME (server or CLI) │
│ │
│ your.apk │
│ │ │
│ ├─ 📝 1. Patch AndroidManifest.xml (binary AXML) │
│ │ android:name → com.fuin.stub.StubApplication │
│ │ │
│ ├─ 🔐 2. Encrypt classes.dex (AES-256-GCM) │
│ │ key = os.urandom(32) ← 256-bit, fresh each run│
│ │ nonce = os.urandom(12) ← 96-bit │
│ │ output = nonce ‖ ciphertext ‖ GCM tag (16B) │
│ │ │
│ ├─ 🛡️ 3. Additional protections │
│ │ native libs (.so) → encrypted │
│ │ user assets → encrypted │
│ │ DEX strings → XOR obfuscated (opt-in) │
│ │ cert fingerprint → embedded (anti-tamper) │
│ │ security policy → root/emulator detection │
│ │ │
│ ├─ 🔧 4. Rebuild APK │
│ │ classes.dex ← stub DEX only │
│ │ assets/encrypted.dex ← ciphertext │
│ │ assets/key.bin ← AES key │
│ │ assets/cert_fingerprint.bin ← anti-tamper │
│ │ assets/encrypted_libs/* ← native libs │
│ │ assets/encrypted_res/* ← user assets │
│ │ assets/security_policy.json ← runtime policy │
│ │ │
│ └─ ✅ 5. zipalign → apksigner → report │
│ │
│ 🔒 protected.apk (no plaintext bytecode — only ciphertext) │
└─────────────────────────────────────────────────────────────────┘
```
## 运行时
当应用在最终用户设备上启动时,stub 会在内存中静默解密原始字节码 — 无网络调用,无可见延迟。
```
┌─────────────────────────────────────────────────────────────────┐
│ 📱 RUNTIME (on-device, no network required) │
│ │
│ StubApplication.attachBaseContext() │
│ │ │
│ ├─ 🛡️ IntegrityCheck — verify APK signing cert │
│ │ │
│ ├─ 🛡️ SecurityCheck — root / emulator detection │
│ │ │
│ ├─ 📖 Read assets/key.bin + assets/encrypted.dex │
│ │ │
│ ├─ 🔧 NativeLibDecryptor — decrypt .so files │
│ │ │
│ ├─ 🔧 DecryptingAssetManager — decrypt user assets │
│ │ │
│ ├─ 🔓 AES-256-GCM decrypt → plaintext DEX │
│ │ written to codeCacheDir (chmod 0600) │
│ │ │
│ ├─ 🔤 StringDecryptor — de-obfuscate DEX strings │
│ │ │
│ ├─ ⚙️ DexClassLoader loads original classes │
│ │ │
│ └─ 🔄 ApplicationSwap (reflection-based hot-swap) │
│ stub Application → original Application │
│ │
│ 🚀 original Application.onCreate() → normal app launch │
└─────────────────────────────────────────────────────────────────┘
```
## 演示

## 功能特性
### 反作弊与保护
| | |
|---|---|
| 🔐 **抗静态分析** | APK 仅包含密文 — 反编译器(jadx、apktool)无法看到任何可运行的字节码 |
| 🛡️ **防篡改** | 运行时验证签名证书 — 重新签名或修补过的 APK 拒绝运行 |
| 🚫 **root 检测** | 阻止在已 root 的设备上执行 — 击败基于 Magisk 的作弊工具 |
| 📵 **模拟器检测** | 阻止在模拟器上运行 — 拦截机器人农场和自动化漏洞测试 |
| 🔌 **抗 Frida/Xposed** | root + 模拟器检查提高了对抗动态 instrumentation 框架的门槛 |
| 📦 **原生库加密** | 加密 .so 文件(Unity/Unreal 游戏引擎、自定义 C++ 库)— 阻断二进制分析 |
| 🗂️ **资源加密** | 游戏配置、关卡数据、数据库在静态存储时加密 — 抵御资源提取 |
| 🔤 **字符串混淆** | DEX 字符串常量进行 XOR 加密 — 抵御 `strings` 转储和配置收集 |
| 🎮 **支持 Unity 与 Flutter** | 开箱即用地支持 Unity `.so` 库和 Flutter 引擎 — 无需额外配置 |
### 开发者体验
| | |
|---|---|
| 📴 **完全离线** | 密钥内嵌于 APK 中 — 启动时无网络调用,无外部依赖 |
| 🌐 **Web UI + REST API** | 通过浏览器或 `curl` 上传,即时下载受保护的 APK |
| ⚡ **支持 CLI** | 使用 `fuin-pack` 实现单条命令本地打包 |
| 🐳 **Docker 优先** | 无需本地 Android SDK — 一切均在镜像中运行 |
| 🔄 **SSE 进度** | 实时打包进度推流至浏览器 |
| 📊 **打包报告** | 显示体积变化、加密目标和元数据的对比报告 |
| 🔌 **Gradle 插件** | 在 `assembleRelease` 后通过一个 DSL 块自动打包 |
| 🤖 **GitHub Actions** | 用于 CI/CD pipeline 的复合 action |
## 快速开始
### Docker(推荐)
```
git clone https://github.com/ykus4/fuin.git && cd fuin
cp .env.example .env # set FUIN_API_KEY to any secret string
docker compose up --build
```
打开 **http://localhost:8000**,将您的 APK 拖拽进去,即可完成。
### 本地设置
展开查看本地设置 (macOS)
```
# Dependencies
curl -LsSf https://astral.sh/uv/install.sh | sh
brew install openjdk@17
# Android build-tools 34 (zipalign + apksigner)
mkdir -p ~/android-sdk/build-tools
curl -L "https://dl.google.com/android/repository/build-tools_r34-macosx.zip" \
-o /tmp/bt.zip
unzip -q /tmp/bt.zip -d /tmp/bt && mv /tmp/bt/android-14 ~/android-sdk/build-tools/34.0.0
# 构建 stub DEX(一次性)
cd stub && ./gradlew :app:assembleRelease && cd ..
# 开始
uv sync
cp .env.example .env # set FUIN_API_KEY
uv run fuin-server
```
fuin 会自动从 `~/android-sdk/build-tools/` 发现工具 — 无需更改 `PATH`。
## 用法
### Web UI
前往 `http://localhost:8000`:
1. 输入您的 API key → **保存**
2. 拖拽一个 `.apk`
3. 观看实时进度条
4. 点击 **下载打包后的 APK**
### REST API
```
# 上传并打包
JOB=$(curl -sX POST http://localhost:8000/pack \
-H "X-API-Key: $FUIN_API_KEY" \
-F "file=@MyApp.apk" | jq -r .job_id)
# 流式传输进度
curl -N "http://localhost:8000/jobs/$JOB/stream?api_key=$FUIN_API_KEY"
# 下载
curl -OJ http://localhost:8000/apps/{app_id}/download \
-H "X-API-Key: $FUIN_API_KEY"
```
### CLI
```
# 基本用法
uv run fuin-pack pack input.apk output_protected.apk
# 启用所有选项的完整保护
uv run fuin-pack pack input.apk output.apk \
--root-detection \
--emulator-detection \
--encrypt-strings \
--report
# 禁用特定保护
uv run fuin-pack pack input.apk output.apk \
--no-native-encrypt \
--no-resource-encrypt
```
**CLI 标志:**
| 标志 | 描述 |
|------|-------------|
| `--report` | 打印人类可读的打包对比报告 |
| `--report-json` | 以 JSON 格式打印打包对比报告 |
| `--root-detection` | 在运行时启用 root 检测 |
| `--emulator-detection` | 在运行时启用模拟器检测 |
| `--encrypt-strings` | 启用 DEX 字符串混淆 |
| `--no-native-encrypt` | 禁用原生库(.so)加密 |
| `--no-resource-encrypt` | 禁用资源加密 |
| `--no-strict-manifest-patch` | 当 manifest 补丁无法验证时,允许尽力打包 |
| `--verify-signature` | 在签名后运行 `apksigner verify` |
| `--keystore` | 签名 keystore 路径 |
| `--key-alias` | 密钥别名 |
| `--store-pass` | Keystore 密码 |
| `--key-pass` | 密钥密码 |
## Gradle 插件
只需一个 DSL 块即可将 fuin 保护添加到您的 Android 构建 pipeline 中。
```
// settings.gradle.kts
pluginManagement {
includeBuild("path/to/fuin/gradle-plugin")
}
// app/build.gradle.kts
plugins {
id("com.fuin.packer")
}
fuin {
enabled.set(true)
// CLI mode (default)
cliPath.set("/usr/local/bin/fuin-pack")
// OR server mode
// serverUrl.set("http://localhost:8000")
// apiKey.set("your-api-key")
// Signing
keystore.set(file("release.keystore").absolutePath)
keystoreAlias.set("release")
keystorePassword.set(System.getenv("STORE_PASS"))
keyPassword.set(System.getenv("KEY_PASS"))
// Protection options
rootDetection.set(true)
emulatorDetection.set(true)
encryptStrings.set(false) // opt-in (slight runtime overhead)
encryptNativeLibs.set(true) // default: true
encryptResources.set(true) // default: true
}
```
配置完成后,打包会在 `assembleRelease` 之后自动进行:
```
./gradlew assembleRelease # → fuinPack runs automatically
```
## GitHub Actions
```
- name: Pack APK with fuin
uses: ykus4/fuin@main
with:
input-apk: app/build/outputs/apk/release/app-release.apk
output-apk: app/build/outputs/apk/release/app-release-packed.apk
keystore-base64: ${{ secrets.KEYSTORE_BASE64 }}
keystore-alias: release
keystore-password: ${{ secrets.STORE_PASS }}
key-password: ${{ secrets.KEY_PASS }}
root-detection: "true"
emulator-detection: "true"
encrypt-strings: "false"
```
## API 参考
| 方法 | 路径 | 描述 |
|--------|------|-------------|
| `GET` | `/` | Web UI |
| `POST` | `/analyze` | 分析 APK — 列出可加密的文件,但不进行打包 |
| `POST` | `/pack` | 上传 APK → 异步任务 → `job_id` |
| `GET` | `/jobs/{id}/stream` | SSE 进度 (`text/event-stream`) |
| `GET` | `/jobs/{id}` | 轮询任务状态 |
| `GET` | `/apps/{id}/download` | 下载受保护的 APK |
| `POST` | `/apps/{id}/mapping/upload` | 上传 ProGuard mapping.txt |
| `GET` | `/apps/{id}/mapping` | 下载 ProGuard mapping.txt |
| `GET` | `/apps` | 列出所有已打包的应用 |
| `DELETE` | `/apps/{id}` | 删除一个已打包的应用 |
除 `GET /` 外的所有 endpoint 都需要 `X-API-Key` 请求头(或对于 SSE 使用 `?api_key=`)。
**SSE 事件格式**
```
{"status": "running", "step": "encrypting_dex", "pct": 40}
{"status": "done", "step": "done", "pct": 100, "result": {...}}
{"status": "error", "step": "error", "pct": 0, "error": "..."}
```
## 配置
将 `.env.example` 复制为 `.env`,并至少设置 `FUIN_API_KEY`。
| 变量 | 必填 | 默认值 | 描述 |
|----------|----------|---------|-------------|
| `FUIN_API_KEY` | **是** | — | 用于所有服务器 endpoint 的 API key |
| `FUIN_KEYSTORE_PATH` | 否 | debug keystore | 签名 keystore 路径 |
| `FUIN_KEYSTORE_ALIAS` | 否 | `fuin` | 密钥别名 |
| `FUIN_KEYSTORE_STORE_PASS` | 否 | — | Keystore 密码 |
| `FUIN_KEYSTORE_KEY_PASS` | 否 | — | 密钥密码 |
| `FUIN_PACKED_DIR` | 否 | `./data/packed_apks` | 打包后 APK 的输出目录 |
| `FUIN_DATABASE_URL` | 否 | `sqlite:///./data/fuin.db` | SQLAlchemy 数据库 URL |
| `FUIN_STUB_DEX` | 否 | 自动检测 | 预构建的 `stub.dex` 路径 |
| `FUIN_MAX_UPLOAD_MB` | 否 | `500` | 最大 APK 上传大小 (MB) |
| `FUIN_CLEANUP_DAYS` | 否 | `30` | 自动删除超过 N 天的打包 APK(`0` = 关闭) |
| `FUIN_WEBHOOK_URL` | 否 | — | 当打包任务完成时向此 URL 发送 POST 请求 |
| `FUIN_ROOT_DETECTION` | 否 | `false` | 启用 root 检测(服务器 pipeline) |
| `FUIN_EMULATOR_DETECTION` | 否 | `false` | 启用模拟器检测(服务器 pipeline) |
| `FUIN_ENCRYPT_STRINGS` | 否 | `false` | 启用 DEX 字符串加密(服务器 pipeline) |
| `FUIN_STRICT_MANIFEST_PATCH` | 否 | `true` | 如果 `StubApplication` 无法插入 manifest 则失败 |
| `FUIN_VERIFY_SIGNATURE` | 否 | `false` | 在签名后运行 `apksigner verify` |
## 仓库结构
```
fuin/
├── fuin/ # Python package
│ ├── config.py # Config (env vars / .env)
│ ├── cli.py # fuin-pack CLI
│ ├── crypto.py # AES-256-GCM
│ ├── manifest.py # Binary AXML patcher
│ ├── apk.py # APK repack + zipalign + apksigner
│ ├── integrity.py # Anti-tamper: cert fingerprint extraction
│ ├── native_lib.py # Native library (.so) encryption
│ ├── resource_encrypt.py # Asset/resource encryption
│ ├── string_encrypt.py # DEX string XOR obfuscation
│ ├── report.py # Pack diff report generation
│ ├── stub_dex.py # Stub DEX locator
│ └── server/ # FastAPI server
│ ├── main.py # HTTP endpoints (fuin-server)
│ ├── pipeline.py # Pack pipeline
│ ├── jobs.py # Async job store (SSE)
│ ├── models.py # Pydantic response models
│ └── static/index.html # Web UI
├── tests/ # pytest suite
│ ├── conftest.py # Shared fixtures (minimal APK, AXML builder)
│ ├── test_crypto.py # AES-256-GCM roundtrip + tamper detection
│ ├── test_manifest.py # AXML patcher
│ ├── test_apk.py # inject, zipalign
│ ├── test_pipeline.py # End-to-end pack pipeline
│ └── test_server.py # FastAPI endpoints
├── stub/ # Android stub (Kotlin, minSdk 24)
│ └── app/src/main/java/com/fuin/stub/
│ ├── StubApplication.kt # Entry point: orchestrates all decryption
│ ├── Crypto.kt # AES-256-GCM decryption
│ ├── ApplicationSwap.kt # Reflection-based app hot-swap
│ ├── IntegrityCheck.kt # Anti-tamper: cert verification
│ ├── SecurityCheck.kt # Root/emulator detection
│ ├── NativeLibDecryptor.kt # .so file decryption + lib path patching
│ ├── DecryptingAssetManager.kt # Encrypted asset decryption
│ └── StringDecryptor.kt # DEX string de-obfuscation
├── gradle-plugin/ # Gradle plugin for build integration
│ ├── build.gradle.kts
│ └── src/main/kotlin/com/fuin/gradle/
│ ├── FuinPlugin.kt # Plugin entry point
│ ├── FuinExtension.kt # DSL configuration
│ └── FuinPackTask.kt # Pack task implementation
├── action.yml # GitHub Actions composite action
├── assets/
│ └── stub.dex # pre-built stub DEX (committed)
├── .env.example
├── docker-compose.yml
└── Dockerfile
```
## 保护层
fuin 叠加了多个独立的保护层 — 击破其中一层并不会击破其他的:
| 保护层 | 静态分析 | 作弊 / 篡改 | 逆向工程 |
|-------|:-:|:-:|:-:|
| DEX 加密 (AES-256-GCM) | ✅ 阻断 jadx/apktool | — | 减缓内存转储 |
| 原生库加密 | ✅ 阻断 IDA/Ghidra | — | 减缓二进制分析 |
| 资源加密 | ✅ 阻断资源提取 | — | 减缓配置收集 |
| 字符串混淆 | ✅ 阻断 `strings` 转储 | — | 减缓常量收集 |
| 防篡改(证书检查) | — | ✅ 阻断 APK 重打包 | ✅ 阻断修补与重新签名 |
| root 检测 | — | ✅ 阻断 Magisk 作弊 | ✅ 阻断 Frida/Xposed |
| 模拟器检测 | — | ✅ 阻断机器人农场 | ✅ 阻断自动化漏洞测试环境 |
## 安全说明
- AES 密钥存在于 APK 内部(`assets/key.bin`)。这足以防御**静态分析**,但对于拥有已 root 设备、能在运行时读取应用资源的顽固攻击者无效。
- 防篡改机制会验证签名证书,防止 APK 被重新签名和修改。
- root/模拟器检测为防范动态 instrumentation(Frida、Xposed)提供了基础防御。坚决的攻击者可以通过 Magisk Hide 或自定义 ROM 绕过这些防御。
- 字符串加密会增加每次字符串访问的开销 — 请有选择地将其用于敏感字符串。
- 发布构建请使用真实的签名 keystore(`FUIN_KEYSTORE_*`)。
- 二进制 AXML 修补程序(`fuin/manifest.py`)在无法确认 `StubApplication` 已插入时,默认会以失败关闭。若需更广泛的 manifest 重写支持,请考虑使用 [apktool](https://apktool.org/)。
- 有关确切的保护边界和推荐的发布设置,请参阅[威胁模型](docs/THREAT_MODEL.md)。
## 许可证
[MIT](LICENSE) © 2026 yotti
标签:APK打包, JS文件枚举, Python, 代码加密, 后台面板检测, 安卓加固, 无后门, 移动应用开发, 请求拦截, 逆向工具, 防篡改