enchantedglycerin/frida-banana

GitHub: enchantedglycerin/frida-banana

一个面向 Android arm64 的隐蔽性 Frida 分支,通过 W^X 内存策略和类 ART 运行时伪装来降低动态插桩的检测痕迹。

Stars: 0 | Forks: 0

frida-banana — stealth Frida for Android
![Frida 17.9.1](https://img.shields.io/badge/Frida-17.9.1-6554C0?style=for-the-badge&logo=frida&logoColor=white) ![Android arm64](https://img.shields.io/badge/Android-arm64-3DDC84?style=for-the-badge&logo=android&logoColor=101820) ![QuickJS](https://img.shields.io/badge/Runtime-QuickJS-F7DF1E?style=for-the-badge&logo=javascript&logoColor=101820) ![W^X](https://img.shields.io/badge/Memory-W%5EX-FFB703?style=for-the-badge&logoColor=101820) **一个用于低痕迹 Android 插桩的 Frida 17.9.1 源码级分支。** `frida-banana` 移除了 Frida 的匿名 `rwxp` 痕迹,为 Gum 分配赋予了类似 ART 的名称, 并替换了明显的运行时标识符——所有这些都无需修改目标应用程序的 `.text` 页。 [构建](#-build-from-source) · [使用](#-use-it) · [验证](#-verify-on-device) · [技术说明](STEALTH_FRIDA_BUILD_RESULT.md)
## 🍌 它的特别之处 | 补丁组 | 改变内容 | 运行时表现 | |---|---|---| | **W^X 内存** | Android 报告 `GUM_RWX_NONE`;Gum 写入 `RW` 页并将其提交为 `RX`。XOM 软化使用 `RX`,从不使用 `RWX`。 | 没有 Frida 创建的可写 + 可执行映射。 | | **类 ART VMA** | Gum 的匿名映射通过 `PR_SET_VMA_ANON_NAME` 进行标记。 | 显示为 `[anon:dalvik-LinearAlloc]` 和 `[anon:dalvik-jit-code-cache]`,而不是未命名的映射。 | | **中性线程** | 明显的 Gum/Frida worker 名称在源码级别被替换。 | 名称为 `gc-worker`、`gc-daemon` 和 `gc-container` 等。 | | **中性 agent memfd** | 注入的 agent 资源在创建和查找路径中都保持一致地重命名。 | 显示为 `/memfd:art-jit-cache-64.so (deleted)`,而不是 `frida-agent-64.so`。 | 确切的实现刻意保持精简且易于审查: - [`stealth-frida-gum.patch`](stealth-frida-gum.patch) — 内存策略、VMA 标签和调度器线程名称 - [`stealth-frida-core.patch`](stealth-frida-core.patch) — agent 线程和 memfd 名称 - [`stealth-patches-BASE-COMMITS.txt`](stealth-patches-BASE-COMMITS.txt) — 固定的上游提交 ## 🧭 设计边界
### ✅ 此分支会做 - 保留 Frida **17.9.1** 协议/版本标识 - 强制 Gum 的 Android 代码路径遵循 **W^X** - 重命名 Gum 拥有的匿名区域和可见 worker - 通过使用硬件断点,使捕获助手远离目标 `.text` 页 ### 🚫 此分支不做 - 隐藏所有可能的 Frida 痕迹或保证通用隐蔽性 - 覆盖 V8 的 JIT 生成的映射 - 捆绑 server 二进制文件、Android NDK 或主机工具 - 取代对特定设备进行验收测试的需求
## 🛠 从源码构建 ### 要求 | 依赖项 | 所需版本 | |---|---| | Android NDK | **r29**(参考构建使用 `29.0.14206865`) | | Node.js | **20.x** | | Meson / Ninja | 参考构建使用 Meson **1.11.2** | | 主机 | Linux 或 WSL2 | ``` git clone --branch 17.9.1 https://github.com/enchantedglycerin/frida-banana.git cd frida-banana export ANDROID_NDK_ROOT="$HOME/android-ndk-r29" export PATH="$HOME/opt/node/bin:$HOME/.local/bin:$PATH" ./configure --host=android-arm64 deps/toolchain-linux-x86_64/bin/ninja \ -C build \ subprojects/frida-core/server/frida-server ``` 精简后的 server 生成于: ``` build/subprojects/frida-core/server/frida-server ``` ### 下载与校验和 预编译的二进制文件附在 [**17.9.1 release**](https://github.com/enchantedglycerin/frida-banana/releases/tag/17.9.1): | 产物 | 大小 | SHA-256 | |---|---:|---| | [`stealth-frida-server-17.9.1-android-arm64`](https://github.com/enchantedglycerin/frida-banana/releases/download/17.9.1/stealth-frida-server-17.9.1-android-arm64) | 53,091,240 字节 | `fa087dd74f5b09a24276ae3f5f6d454716c17efaa34a46deca92bb77c34f2f32` | | [`stealth-frida-server-17.9.1-android-arm64.gz`](https://github.com/enchantedglycerin/frida-banana/releases/download/17.9.1/stealth-frida-server-17.9.1-android-arm64.gz) | 23,351,182 字节 | `a8083db53db883200a9dce331a3a9275d482d7992ff3bf2ae35a443b76282c64` | 匹配第一个哈希值意味着您的构建与发布的二进制文件在字节上是完全一致的。目前尚未端到端复现过全新的扁平克隆构建,因此请将此校验和视为已发布二进制文件的参考,而不能保证您本地工具链的输出。 ## 🚀 使用它 主机端的 Frida 包必须与 server 匹配: ``` python -m pip install "frida==17.9.1" frida-tools ``` 以中性的文件名和非默认端口推送并启动您本地构建的 server: ``` adb push build/subprojects/frida-core/server/frida-server /data/local/tmp/.gc-srv adb shell su -c 'chmod 755 /data/local/tmp/.gc-srv' adb shell su -c '/data/local/tmp/.gc-srv -l 127.0.0.1:17173 &' ``` 使用 **QuickJS** 运行脚本: ``` # 最小存在 / mapping probe frida -H 127.0.0.1:17173 --runtime=qjs \ -f com.example.app \ -l presence_only.js # 针对特定项目的 capture helper(配置为 libgame.so / OFF_CIPHER) frida -H 127.0.0.1:17173 --runtime=qjs \ -f com.devsisters.crg \ -l capture_hwbp.js ``` `capture_hwbp.js` 只是一个示例框架,并不是通用的 tracer。对于其他目标,在使用前请更新模块名、`OFF_CIPHER`、调用约定以及捕获的参数大小。 ## 🔍 在设备上验证 切勿仅凭一次过滤后的 grep 结果推断成功。与干净的基线进行比较,并统计**所有**可写 + 可执行映射: ``` PID="$(pidof com.example.app)" # 每个可写 + 可执行的 mapping,无论 named 或 unnamed awk '$2 ~ /rwx/ { print }' "/proc/$PID/maps" # 注入的 agent mapping grep 'art-jit-cache' "/proc/$PID/maps" # 可见的 thread names for COMM in /proc/"$PID"/task/*/comm; do cat "$COMM"; done ``` 一次合格的验收运行应确认: 1. 注入后的 `rwx` 计数等于干净的应用程序基线。 2. Gum 代码映射是 `r-xp`,而不是 `rwxp`。 3. agent memfd 和线程名称与上述中性名称匹配。 4. 目标在预期工作负载下至少保持稳定 60 秒。 5. `capture_hwbp.js` 到达 `[CAPTURED]` 且未修改目标 `.text`。 有关完整的设备操作流程、失败解释和重新构建说明,请参阅 [`STEALTH_FRIDA_BUILD_RESULT.md`](STEALTH_FRIDA_BUILD_RESULT.md)。 ## 🗂 仓库结构 ``` frida-banana/ ├── capture_hwbp.js # resilient hardware-breakpoint capture helper ├── presence_only.js # minimal injection / mapping probe ├── stealth-frida-gum.patch # W^X, VMA labels, scheduler rename ├── stealth-frida-core.patch # agent thread and memfd rename ├── stealth-patches-BASE-COMMITS.txt # pinned upstream bases ├── STEALTH_FRIDA_BUILD_RESULT.md # deep technical and acceptance notes ├── subprojects/ # vendored Frida 17.9.1 source tree └── releng/ # vendored Frida build tooling ``` ## ⚖️ 范围与责任 本项目旨在用于授权研究、互操作性、调试以及对您获准检查的软件和设备的分析。您有责任遵守适用于您所在环境的规则和法律。
标签:Android, DSL, MITM代理, 云资产清单, 内存管理, 反检测, 逆向工程, 预握手