{"id":49734678,"url":"https://github.com/ykus4/fuin","last_synced_at":"2026-05-09T07:16:44.370Z","repository":{"id":354947957,"uuid":"1226173345","full_name":"ykus4/fuin","owner":"ykus4","description":"Web-based Android APK packer. Encrypts DEX bytecode, native libraries, and assets with AES-256-GCM. Supports Unity, multidex, and standard apps. No source changes required.","archived":false,"fork":false,"pushed_at":"2026-05-09T02:36:11.000Z","size":7067,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-09T04:12:37.487Z","etag":null,"topics":["android","android-security","apk","apk-security","code-protection","obfuscation","obfuscation-tool","packer","reverse-engineering"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ykus4.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-05-01T03:58:11.000Z","updated_at":"2026-05-09T02:36:15.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/ykus4/fuin","commit_stats":null,"previous_names":["ykus4/fuin"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/ykus4/fuin","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ykus4%2Ffuin","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ykus4%2Ffuin/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ykus4%2Ffuin/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ykus4%2Ffuin/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ykus4","download_url":"https://codeload.github.com/ykus4/fuin/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ykus4%2Ffuin/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32810597,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-08T08:22:46.396Z","status":"online","status_checked_at":"2026-05-09T02:00:06.633Z","response_time":123,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["android","android-security","apk","apk-security","code-protection","obfuscation","obfuscation-tool","packer","reverse-engineering"],"created_at":"2026-05-09T07:16:42.335Z","updated_at":"2026-05-09T07:16:44.351Z","avatar_url":"https://github.com/ykus4.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cdiv align=\"center\"\u003e\n\n\u003cimg src=\"docs/logo.png\" alt=\"fuin logo\" width=\"600\"\u003e\n\n**Android APK Packer — protect bytecode, block cheating, resist reverse engineering**\n\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)\n[![Python](https://img.shields.io/badge/Python-3.12%2B-blue?logo=python\u0026logoColor=white)](https://www.python.org/)\n[![Docker](https://img.shields.io/badge/Docker-ready-2496ED?logo=docker\u0026logoColor=white)](https://hub.docker.com/)\n[![CI](https://github.com/ykus4/fuin/actions/workflows/ci.yml/badge.svg)](https://github.com/ykus4/fuin/actions/workflows/ci.yml)\n\nProtect any Android APK — Unity, Flutter, or standard — against cheating, piracy, and reverse engineering.\nDEX bytecode, native libraries (.so), and assets are encrypted with AES-256-GCM.\nAnti-tamper, root detection, and emulator blocking guard against runtime instrumentation tools like Frida and Xposed.\nNo source changes. No network at runtime. Works fully offline.\n\n\u003c/div\u003e\n\n---\n\n## Pack time\n\nfuin processes your APK once — via the web UI, REST API, or CLI. The original APK is never modified in-place; a brand-new protected APK is produced.\n\n```\n┌─────────────────────────────────────────────────────────────────┐\n│  📦 PACK TIME  (server or CLI)                                  │\n│                                                                 │\n│  your.apk                                                       │\n│      │                                                          │\n│      ├─ 📝 1. Patch AndroidManifest.xml  (binary AXML)          │\n│      │         android:name → com.fuin.stub.StubApplication     │\n│      │                                                          │\n│      ├─ 🔐 2. Encrypt  classes.dex  (AES-256-GCM)               │\n│      │         key   = os.urandom(32)  ← 256-bit, fresh each run│\n│      │         nonce = os.urandom(12)  ← 96-bit                 │\n│      │         output = nonce ‖ ciphertext ‖ GCM tag (16B)      │\n│      │                                                          │\n│      ├─ 🛡️ 3. Additional protections                            │\n│      │         native libs (.so)  → encrypted                   │\n│      │         user assets        → encrypted                   │\n│      │         DEX strings        → XOR obfuscated (opt-in)     │\n│      │         cert fingerprint   → embedded (anti-tamper)      │\n│      │         security policy    → root/emulator detection     │\n│      │                                                          │\n│      ├─ 🔧 4. Rebuild APK                                       │\n│      │         classes.dex                  ← stub DEX only     │\n│      │         assets/encrypted.dex         ← ciphertext        │\n│      │         assets/key.bin               ← AES key           │\n│      │         assets/cert_fingerprint.bin  ← anti-tamper       │\n│      │         assets/encrypted_libs/*      ← native libs       │\n│      │         assets/encrypted_res/*       ← user assets       │\n│      │         assets/security_policy.json  ← runtime policy    │\n│      │                                                          │\n│      └─ ✅ 5. zipalign → apksigner → report                     │\n│                                                                 │\n│  🔒 protected.apk  (no plaintext bytecode — only ciphertext)   │\n└─────────────────────────────────────────────────────────────────┘\n```\n\n## Runtime\n\nWhen the app launches on the end user's device, the stub decrypts the original bytecode silently in memory — no network call, no visible delay.\n\n```\n┌─────────────────────────────────────────────────────────────────┐\n│  📱 RUNTIME  (on-device, no network required)                   │\n│                                                                 │\n│  StubApplication.attachBaseContext()                            │\n│      │                                                          │\n│      ├─ 🛡️ IntegrityCheck  — verify APK signing cert            │\n│      │                                                          │\n│      ├─ 🛡️ SecurityCheck   — root / emulator detection          │\n│      │                                                          │\n│      ├─ 📖 Read  assets/key.bin  +  assets/encrypted.dex        │\n│      │                                                          │\n│      ├─ 🔧 NativeLibDecryptor  — decrypt .so files              │\n│      │                                                          │\n│      ├─ 🔧 DecryptingAssetManager  — decrypt user assets        │\n│      │                                                          │\n│      ├─ 🔓 AES-256-GCM decrypt → plaintext DEX                  │\n│      │       written to codeCacheDir  (chmod 0600)              │\n│      │                                                          │\n│      ├─ 🔤 StringDecryptor  — de-obfuscate DEX strings          │\n│      │                                                          │\n│      ├─ ⚙️  DexClassLoader  loads original classes              │\n│      │                                                          │\n│      └─ 🔄 ApplicationSwap  (reflection-based hot-swap)         │\n│              stub Application → original Application            │\n│                                                                 │\n│  🚀 original Application.onCreate()  →  normal app launch      │\n└─────────────────────────────────────────────────────────────────┘\n```\n\n## Demo\n\n![fuin demo](docs/demo.gif)\n\n## Features\n\n### Anti-cheat \u0026 protection\n\n| | |\n|---|---|\n| 🔐 **Static analysis resistant** | APK contains only ciphertext — no runnable bytecode visible to decompilers (jadx, apktool) |\n| 🛡️ **Anti-tamper** | Verifies signing certificate at runtime — re-signed or patched APKs refuse to run |\n| 🚫 **Root detection** | Blocks execution on rooted devices — defeats Magisk-based cheat tools |\n| 📵 **Emulator detection** | Prevents running on emulators — blocks bot farms and automated exploit testing |\n| 🔌 **Frida/Xposed resistant** | Root + emulator checks raise the bar against dynamic instrumentation frameworks |\n| 📦 **Native lib encryption** | .so files (Unity/Unreal game engines, custom C++ libs) encrypted — binary analysis blocked |\n| 🗂️ **Asset encryption** | Game configs, level data, databases encrypted at rest — resist asset extraction |\n| 🔤 **String obfuscation** | DEX string constants XOR-encrypted — resist `strings` dumps and config harvesting |\n| 🎮 **Unity \u0026 Flutter support** | Works out of the box with Unity `.so` libs and Flutter engine — no extra config |\n\n### Developer experience\n\n| | |\n|---|---|\n| 📴 **Fully offline** | Key is bundled in the APK — no network call at launch, no external dependency |\n| 🌐 **Web UI + REST API** | Upload via browser or `curl`, download protected APK instantly |\n| ⚡ **CLI support** | One-command local packing with `fuin-pack` |\n| 🐳 **Docker-first** | No local Android SDK needed — everything runs in the image |\n| 🔄 **SSE progress** | Real-time pack progress streamed to the browser |\n| 📊 **Pack report** | Diff report showing size changes, encrypted targets, and metadata |\n| 🔌 **Gradle plugin** | Auto-pack after `assembleRelease` with one DSL block |\n| 🤖 **GitHub Actions** | Composite action for CI/CD pipelines |\n\n---\n\n## Quick start\n\n### Docker (recommended)\n\n```bash\ngit clone https://github.com/ykus4/fuin.git \u0026\u0026 cd fuin\ncp .env.example .env          # set FUIN_API_KEY to any secret string\ndocker compose up --build\n```\n\nOpen **http://localhost:8000**, drag-and-drop your APK, done.\n\n\u003e First build takes a few minutes (downloads Android build-tools + compiles stub DEX).\n\u003e Subsequent starts are instant. Packed APKs persist in a named Docker volume.\n\n### Local setup\n\n\u003cdetails\u003e\n\u003csummary\u003eExpand for local setup (macOS)\u003c/summary\u003e\n\n```bash\n# Dependencies\ncurl -LsSf https://astral.sh/uv/install.sh | sh\nbrew install openjdk@17\n\n# Android build-tools 34 (zipalign + apksigner)\nmkdir -p ~/android-sdk/build-tools\ncurl -L \"https://dl.google.com/android/repository/build-tools_r34-macosx.zip\" \\\n  -o /tmp/bt.zip\nunzip -q /tmp/bt.zip -d /tmp/bt \u0026\u0026 mv /tmp/bt/android-14 ~/android-sdk/build-tools/34.0.0\n\n# Build stub DEX (one-time)\ncd stub \u0026\u0026 ./gradlew :app:assembleRelease \u0026\u0026 cd ..\n\n# Start\nuv sync\ncp .env.example .env          # set FUIN_API_KEY\nuv run fuin-server\n```\n\nfuin auto-discovers tools from `~/android-sdk/build-tools/` — no `PATH` changes needed.\n\n\u003c/details\u003e\n\n---\n\n## Usage\n\n### Web UI\n\nGo to `http://localhost:8000`:\n\n1. Enter your API key → **Save**\n2. Drag-and-drop an `.apk`\n3. Watch the real-time progress bar\n4. Click **Download packed APK**\n\n### REST API\n\n```bash\n# Upload and pack\nJOB=$(curl -sX POST http://localhost:8000/pack \\\n  -H \"X-API-Key: $FUIN_API_KEY\" \\\n  -F \"file=@MyApp.apk\" | jq -r .job_id)\n\n# Stream progress\ncurl -N \"http://localhost:8000/jobs/$JOB/stream?api_key=$FUIN_API_KEY\"\n\n# Download\ncurl -OJ http://localhost:8000/apps/{app_id}/download \\\n  -H \"X-API-Key: $FUIN_API_KEY\"\n```\n\n### CLI\n\n```bash\n# Basic usage\nuv run fuin-pack pack input.apk output_protected.apk\n\n# Full protection with all options\nuv run fuin-pack pack input.apk output.apk \\\n  --root-detection \\\n  --emulator-detection \\\n  --encrypt-strings \\\n  --report\n\n# Disable specific protections\nuv run fuin-pack pack input.apk output.apk \\\n  --no-native-encrypt \\\n  --no-resource-encrypt\n```\n\n**CLI flags:**\n\n| Flag | Description |\n|------|-------------|\n| `--report` | Print human-readable pack diff report |\n| `--report-json` | Print pack diff report as JSON |\n| `--root-detection` | Enable root detection at runtime |\n| `--emulator-detection` | Enable emulator detection at runtime |\n| `--encrypt-strings` | Enable DEX string obfuscation |\n| `--no-native-encrypt` | Disable native library (.so) encryption |\n| `--no-resource-encrypt` | Disable asset/resource encryption |\n| `--keystore` | Signing keystore path |\n| `--key-alias` | Key alias |\n| `--store-pass` | Keystore password |\n| `--key-pass` | Key password |\n\n---\n\n## Gradle Plugin\n\nAdd fuin protection to your Android build pipeline with a single DSL block.\n\n```kotlin\n// settings.gradle.kts\npluginManagement {\n    includeBuild(\"path/to/fuin/gradle-plugin\")\n}\n\n// app/build.gradle.kts\nplugins {\n    id(\"com.fuin.packer\")\n}\n\nfuin {\n    enabled.set(true)\n\n    // CLI mode (default)\n    cliPath.set(\"/usr/local/bin/fuin-pack\")\n\n    // OR server mode\n    // serverUrl.set(\"http://localhost:8000\")\n    // apiKey.set(\"your-api-key\")\n\n    // Signing\n    keystore.set(file(\"release.keystore\").absolutePath)\n    keystoreAlias.set(\"release\")\n    keystorePassword.set(System.getenv(\"STORE_PASS\"))\n    keyPassword.set(System.getenv(\"KEY_PASS\"))\n\n    // Protection options\n    rootDetection.set(true)\n    emulatorDetection.set(true)\n    encryptStrings.set(false)       // opt-in (slight runtime overhead)\n    encryptNativeLibs.set(true)     // default: true\n    encryptResources.set(true)      // default: true\n}\n```\n\nAfter configuration, packing happens automatically after `assembleRelease`:\n\n```bash\n./gradlew assembleRelease   # → fuinPack runs automatically\n```\n\n---\n\n## GitHub Actions\n\n```yaml\n- name: Pack APK with fuin\n  uses: ykus4/fuin@main\n  with:\n    input-apk: app/build/outputs/apk/release/app-release.apk\n    output-apk: app/build/outputs/apk/release/app-release-packed.apk\n    keystore-base64: ${{ secrets.KEYSTORE_BASE64 }}\n    keystore-alias: release\n    keystore-password: ${{ secrets.STORE_PASS }}\n    key-password: ${{ secrets.KEY_PASS }}\n    root-detection: \"true\"\n    emulator-detection: \"true\"\n    encrypt-strings: \"false\"\n```\n\n---\n\n## API reference\n\n| Method | Path | Description |\n|--------|------|-------------|\n| `GET` | `/` | Web UI |\n| `POST` | `/analyze` | Analyze APK — list encryptable files without packing |\n| `POST` | `/pack` | Upload APK → async job → `job_id` |\n| `GET` | `/jobs/{id}/stream` | SSE progress (`text/event-stream`) |\n| `GET` | `/jobs/{id}` | Poll job status |\n| `GET` | `/apps/{id}/download` | Download protected APK |\n| `POST` | `/apps/{id}/mapping/upload` | Upload ProGuard mapping.txt |\n| `GET` | `/apps/{id}/mapping` | Download ProGuard mapping.txt |\n| `GET` | `/apps` | List all packed apps |\n| `DELETE` | `/apps/{id}` | Delete a packed app |\n\nAll endpoints except `GET /` require `X-API-Key` header (or `?api_key=` for SSE).\n\n**SSE event format**\n```json\n{\"status\": \"running\", \"step\": \"encrypting_dex\", \"pct\": 40}\n{\"status\": \"done\",    \"step\": \"done\",            \"pct\": 100, \"result\": {...}}\n{\"status\": \"error\",   \"step\": \"error\",            \"pct\": 0,  \"error\": \"...\"}\n```\n\n---\n\n## Configuration\n\nCopy `.env.example` → `.env` and set at minimum `FUIN_API_KEY`.\n\n| Variable | Required | Default | Description |\n|----------|----------|---------|-------------|\n| `FUIN_API_KEY` | **Yes** | — | API key for all server endpoints |\n| `FUIN_KEYSTORE_PATH` | No | debug keystore | Signing keystore path |\n| `FUIN_KEYSTORE_ALIAS` | No | `fuin` | Key alias |\n| `FUIN_KEYSTORE_STORE_PASS` | No | — | Keystore password |\n| `FUIN_KEYSTORE_KEY_PASS` | No | — | Key password |\n| `FUIN_PACKED_DIR` | No | `./data/packed_apks` | Output dir for packed APKs |\n| `FUIN_DATABASE_URL` | No | `sqlite:///./data/fuin.db` | SQLAlchemy DB URL |\n| `FUIN_STUB_DEX` | No | auto-detected | Path to pre-built `stub.dex` |\n| `FUIN_MAX_UPLOAD_MB` | No | `500` | Max APK upload size (MB) |\n| `FUIN_CLEANUP_DAYS` | No | `30` | Auto-delete packed APKs older than N days (`0` = off) |\n| `FUIN_WEBHOOK_URL` | No | — | POST to this URL when a pack job completes |\n| `FUIN_ROOT_DETECTION` | No | `false` | Enable root detection (server pipeline) |\n| `FUIN_EMULATOR_DETECTION` | No | `false` | Enable emulator detection (server pipeline) |\n| `FUIN_ENCRYPT_STRINGS` | No | `false` | Enable DEX string encryption (server pipeline) |\n\n---\n\n## Repository structure\n\n```\nfuin/\n├── fuin/                      # Python package\n│   ├── config.py              # Config (env vars / .env)\n│   ├── cli.py                 # fuin-pack CLI\n│   ├── crypto.py              # AES-256-GCM\n│   ├── manifest.py            # Binary AXML patcher\n│   ├── apk.py                 # APK repack + zipalign + apksigner\n│   ├── integrity.py           # Anti-tamper: cert fingerprint extraction\n│   ├── native_lib.py          # Native library (.so) encryption\n│   ├── resource_encrypt.py    # Asset/resource encryption\n│   ├── string_encrypt.py      # DEX string XOR obfuscation\n│   ├── report.py              # Pack diff report generation\n│   ├── stub_dex.py            # Stub DEX locator\n│   └── server/                # FastAPI server\n│       ├── main.py            # HTTP endpoints (fuin-server)\n│       ├── pipeline.py        # Pack pipeline\n│       ├── jobs.py            # Async job store (SSE)\n│       ├── models.py          # Pydantic response models\n│       └── static/index.html  # Web UI\n├── tests/                     # pytest suite\n│   ├── conftest.py            # Shared fixtures (minimal APK, AXML builder)\n│   ├── test_crypto.py         # AES-256-GCM roundtrip + tamper detection\n│   ├── test_manifest.py       # AXML patcher\n│   ├── test_apk.py            # inject, zipalign\n│   ├── test_pipeline.py       # End-to-end pack pipeline\n│   └── test_server.py         # FastAPI endpoints\n├── stub/                      # Android stub (Kotlin, minSdk 24)\n│   └── app/src/main/java/com/fuin/stub/\n│       ├── StubApplication.kt      # Entry point: orchestrates all decryption\n│       ├── Crypto.kt                # AES-256-GCM decryption\n│       ├── ApplicationSwap.kt      # Reflection-based app hot-swap\n│       ├── IntegrityCheck.kt       # Anti-tamper: cert verification\n│       ├── SecurityCheck.kt        # Root/emulator detection\n│       ├── NativeLibDecryptor.kt   # .so file decryption + lib path patching\n│       ├── DecryptingAssetManager.kt  # Encrypted asset decryption\n│       └── StringDecryptor.kt      # DEX string de-obfuscation\n├── gradle-plugin/             # Gradle plugin for build integration\n│   ├── build.gradle.kts\n│   └── src/main/kotlin/com/fuin/gradle/\n│       ├── FuinPlugin.kt      # Plugin entry point\n│       ├── FuinExtension.kt   # DSL configuration\n│       └── FuinPackTask.kt    # Pack task implementation\n├── action.yml                 # GitHub Actions composite action\n├── assets/\n│   └── stub.dex               # pre-built stub DEX (committed)\n├── .env.example\n├── docker-compose.yml\n└── Dockerfile\n```\n\n---\n\n## Protection layers\n\nfuin stacks multiple independent layers — defeating one does not defeat the others:\n\n| Layer | Static Analysis | Cheating / Tampering | Reverse Engineering |\n|-------|:-:|:-:|:-:|\n| DEX encryption (AES-256-GCM) | ✅ Blocks jadx/apktool | — | Slows memory dumping |\n| Native lib encryption | ✅ Blocks IDA/Ghidra | — | Slows binary analysis |\n| Asset encryption | ✅ Blocks asset extraction | — | Slows config harvesting |\n| String obfuscation | ✅ Blocks `strings` dumps | — | Slows constant harvesting |\n| Anti-tamper (cert check) | — | ✅ Blocks APK repacking | ✅ Blocks patch-and-resign |\n| Root detection | — | ✅ Blocks Magisk cheats | ✅ Blocks Frida/Xposed |\n| Emulator detection | — | ✅ Blocks bot farms | ✅ Blocks automated exploit rigs |\n\n---\n\n## Security notes\n\n- The AES key lives inside the APK (`assets/key.bin`). This defeats **static analysis** but not a determined attacker with a rooted device who can read app assets at runtime.\n- Anti-tamper verifies the signing certificate, preventing APK re-signing and modification.\n- Root/emulator detection provides a baseline defense against dynamic instrumentation (Frida, Xposed). Determined attackers can bypass these with Magisk Hide or custom ROMs.\n- String encryption adds overhead to every string access — use selectively for sensitive strings.\n- Use a real signing keystore (`FUIN_KEYSTORE_*`) for release builds.\n- The binary AXML patcher (`fuin/manifest.py`) is best-effort. For production, consider [apktool](https://apktool.org/).\n\n---\n\n## License\n\n[MIT](LICENSE) © 2026 yotti\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fykus4%2Ffuin","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fykus4%2Ffuin","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fykus4%2Ffuin/lists"}