frankheat/frida-jdwp-loader

GitHub: frankheat/frida-jdwp-loader

一款通过 JDWP 协议在非 Root 环境下将 Frida 动态注入 Android 应用的 Python 工具,无需重打包即可实现运行时插桩。

Stars: 151 | Forks: 16

# frida-jdwp-loader **一个 Python 脚本,通过 JDWP 将 Frida 动态附加到任何可调试的 Android 进程,无需 Root 权限或重打包 APK 即可实现运行时插桩。**
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) [![Python Version](https://img.shields.io/badge/python-3.9%2B-blue.svg)](https://www.python.org/)
[frida-jdwp-loader](https://github.com/frankheat/frida-jdwp-loader) 是一个 Python 脚本,提供了一种在非 Root Android 设备上使用 Frida 的方法。它利用 Java Debug Wire Protocol (JDWP) 将原生共享库(如 frida-gadget.so)动态注入到运行中的应用程序中。 ## 灵感与起源 这个脚本的灵感源自 Frida 创建者 Ole André Vadla Ravnås 的一条[评论](https://www.linkedin.com/feed/update/urn:li:activity:7373729315080974336/?commentUrn=urn%3Ali%3Acomment%3A%28activity%3A7373729315080974336%2C7374082257801777153%29&dashCommentUrn=urn%3Ali%3Afsd_comment%3A%287374082257801777153%2Curn%3Ali%3Aactivity%3A7373729315080974336%29)。他提到,Frida 不再需要 Root 权限或应用程序重打包。相反,可以使用 Java Debug Wire Protocol (JDWP) 和 ADB 将其动态注入到任何可调试应用程序的进程中。 这项技术由 Yiannis Kozyrakis (ikoz) 在他的博文 [Library injection for debuggable Android apps](https://koz.io/library-injection-for-debuggable-android-apps/) 中进行了专家级的演示。他的工作为本项目提供了基础性的[概念验证](https://github.com/ikoz/jdwp-lib-injector)。 ## 为什么开发这个新工具? 在使用原始脚本时,我看到了增强其灵活性和自动化整个工作流程的机会。这个项目就是为了满足这些需求而诞生的,它最初是 hugsy 的 [jdwp-shellifier](https://github.com/hugsy/jdwp-shellifier) 一个分支的 Python 3 重写版本,并由此发展而来。 ## 增强功能 - 现代且健壮:完全使用 Python 3 重写。 - 早期插桩:实现了标准早期插桩的替代方案,允许你在应用程序代码甚至开始运行之前对其进行 Hook。 - 增加了对多种 frida 交互类型的支持。这允许你更改监听的地址/端口,并以完全自主的方式运行脚本(绕过 INTERNET 权限要求)等。 - 自动化: - 自动管理的 frida gadget:脚本会自动检测目标设备的架构(ARM, ARM64, x86, x86_64)并为你下载正确版本的 Frida gadget。 - 多设备管理:如果你连接了多个设备,可以轻松选择并在它们之间切换。 - 零接触操作:所有操作均通过编程方式执行。你不需要在注入过程中手动在设备上启用或禁用设置。 - 其他小功能。 # 背景 通常,在 Android 上使用 Frida 涉及两种主要方法,每种方法都有显著的权衡: | Method | How it Works | Pros | Cons | | --- | --- | --- | --- | | Frida-Server | 一个服务端二进制文件以 Root 权限在设备上运行,注入到任何目标进程中。 | 功能强大,可以附加到任何进程。 | 需要已 Root 的设备。 | | Frida-Gadget | 将 frida-gadget.so 库添加到 APK 中,然后重新签名并重新安装。 | 适用于非 Root 设备。 | 需要重打包 APK,这很复杂、容易出错,且常被防篡改控件检测到。 | 创建 [frida-jdwp-loader](https://github.com/frankheat/frida-jdwp-loader) 是为了克服这些限制,提供 Frida-Gadget 方法的优点(无需 Root)而没有其最大的缺点(重打包)。 # 前置条件 这整个过程只有在目标应用程序可调试(`AndroidManifest.xml` 中的 `android:debuggable="true"`)时才可能实现。 如果应用程序不可调试,你可以: - 在设置了 `ro.debuggable` 属性为 `1` 的模拟器中运行应用程序。 - 使用已 Root 的手机,以便修改 `ro.debuggable`。通常此值是只读的。但是使用 magisk 你可以使用 `resetprop`。 - 重打包应用程序并在 `AndroidManifest.xml` 中设置 `android:debuggable="true"`。 # 入门指南 ## 系统要求 - Python 3 - ADB (Android Debug Bridge) 已添加到 PATH - 已开启 USB/无线调试的 Android 设备 ## 安装 ``` # 克隆仓库 git clone https://github.com/frankheat/frida-jdwp-loader.git cd frida-jdwp-loader ``` ## 快速开始 ``` # 自动下载并注入 frida-gadget.so python frida-jdwp-loader.py frida -n com.example.myapplication # 使用特定版本的 frida-gadget.so python frida-jdwp-loader.py frida -n com.example.myapplication -g 16.1.2 # 在 Spawn 应用后保持命中断点的线程处于挂起状态 python frida-jdwp-loader.py frida -n com.example.myapplication -s # Spawn 特定 Activity 模式 python frida-jdwp-loader.py frida -n com.example.myapplication -a .MainActivity # 更改监听地址/端口 python frida-jdwp-loader.py frida -n com.example.myapplication -i listen -L 0.0.0.0 -P 27043 # 以完全自主的方式运行脚本 python frida-jdwp-loader.py frida -n com.example.myapplication -i script -l script.js # 注入目录中的所有文件 python frida-jdwp-loader.py custom -n com.example.myapplication -l /path/to/lib_directory/ ``` # 用法示例 ## 在 Listen 交互模式下运行 Frida Gadget 在此示例中,我们暴露了一个兼容 frida-server 的接口,以便你可以远程附加到进程。确保目标应用程序声明了 `INTERNET` 权限;没有它,远程连接将失败。 ![image](https://static.pigsec.cn/wp-content/uploads/repos/2026/03/1a1821846e103040.jpg) ## 完全自主运行脚本 在此示例中,我们将插桩脚本直接注入并在目标进程内运行,使其独立运行。如果你需要在这种方式下运行时收集运行时输出,请从你的 frida 代码中调用 Android 的原生日志函数。这些日志将出现在 Logcat 中。 https://github.com/user-attachments/assets/1639a833-76fc-4a8d-9750-9a8467689c4d **视频中使用的脚本** ``` var android_log_write = new NativeFunction( Module.getExportByName(null, '__android_log_write'), 'int', ['int', 'pointer', 'pointer'] ); var tag = Memory.allocUtf8String('frida-script'); android_log_write(3, tag, Memory.allocUtf8String('hello world')); ``` # 命令行选项 ## frida-mode 选项 ``` usage: frida-jdwp-loader.py frida [-h] [-g GADGET] [-i {listen,script,custom}] [-L ADDRESS] [-P PORT] [-l SCRIPT] [-f CONFIG] -n PACKAGE_NAME [-a ACTIVITY_NAME] [-m MODE] [-b JAVA_METHOD] [-p JDWP_PORT] [-nc] [-d DELAY] [-s] [-v] options: -h, --help show this help message and exit -g GADGET, --gadget GADGET Could be one of the following: Path to the frida gadget library file Frida version (e.g., '16.6.6') auto, to automatically detect (Default) -i {listen,script,custom}, --interaction {listen,script,custom} Interaction mode (Default: listen) -L ADDRESS, --listen ADDRESS Listen on ADDRESS (used with --interaction listener) (Default: 127.0.0.1) -P PORT, --frida-port PORT Listen on PORT (used with --interaction listener) (Default: 27042) -l SCRIPT, --load SCRIPT load SCRIPT (Required with --interaction script) -f CONFIG, --config-file CONFIG load CONFIG-FILE (Required with --interaction custom) -n PACKAGE_NAME, --package PACKAGE_NAME Target Android package name (e.g., com.example.app) -a ACTIVITY_NAME, --activity ACTIVITY_NAME Target activity name (Default: launcher activity) -m MODE, --mode MODE Select mode: spawn (Default) attach -b JAVA_METHOD, --break-on JAVA_METHOD Java method to break on for injection (full path required) Default depends on mode: spawn -> android.app.Application.onCreate attach -> android.app.Activity.onStart -p JDWP_PORT, --port JDWP_PORT Local port number for JDWP forwarding (Default: 8715) -nc, --no-clear Don't clear after injection -d DELAY, --delay DELAY Delay between operations (Default: 2) -s, -suspended Keep the thread that hits the breakpoint suspended after spawning the app -k, --keep-files Keep uploaded files after execution (default: files are removed) -v, --verbose Enable verbose logging output ``` ## custom-mode 选项 ``` usage: frida-jdwp-loader.py custom [-h] -l LIB_PATH -n PACKAGE_NAME [-a ACTIVITY_NAME] [-m MODE] [-b JAVA_METHOD] [-p JDWP_PORT] [-nc] [-d DELAY] [-s] [-v] options: -h, --help show this help message and exit -l LIB_PATH, --lib-path LIB_PATH Path to the custom library file/directory to inject -n PACKAGE_NAME, --package PACKAGE_NAME Target Android package name (e.g., com.example.app) -a ACTIVITY_NAME, --activity ACTIVITY_NAME Target activity name (Default: launcher activity) -m MODE, --mode MODE Select mode: spawn (Default) attach -b JAVA_METHOD, --break-on JAVA_METHOD Java method to break on for injection (full path required) Default depends on mode: spawn -> android.app.Application.onCreate attach -> android.app.Activity.onStart -p JDWP_PORT, --port JDWP_PORT Local port number for JDWP forwarding (Default: 8715) -nc, --no-clear Don't clear after injection -d DELAY, --delay DELAY Delay between operations (Default: 2) -s, -suspended Keep the thread that hits the breakpoint suspended after spawning the app -k, --keep-files Keep uploaded files after execution (default: files are removed) -v, --verbose Enable verbose logging output ``` # 许可证 本项目根据 MIT 许可证授权 - 有关详细信息,请参阅 [LICENSE](LICENSE) 文件。 # 致谢 - [ikoz](https://github.com/ikoz) - [jdwp-lib-injector](https://github.com/ikoz/jdwp-lib-injector), [Library injection for debuggable Android apps](https://koz.io/library-injection-for-debuggable-android-apps/) - [hugsy](https://github.com/hugsy) - [jdwp-shellifier](https://github.com/hugsy/jdwp-shellifier) - [oleavr](https://github.com/oleavr) - [Frida](https://frida.re/)
标签:Android安全, Docker支持, Frida, JDWP, Python, 云资产清单, 免Root, 安全测试, 攻击性安全, 无Root检测, 无后门, 注入工具, 漏洞分析, 目录枚举, 移动安全, 调试技术, 路径探测, 运行时插桩, 逆向工程, 黑盒测试