当前位置:首页>iOSAPP>非越狱 iOS 设备上结合 MonkeyDev 和 Frida调试App

非越狱 iOS 设备上结合 MonkeyDev 和 Frida调试App

  • 2026-11-06 10:05:00
非越狱 iOS 设备上结合 MonkeyDev 和 Frida调试App

1️⃣ 前置条件

  1. 非越狱 iOS 设备(iPhone/iPad)。
  2. Mac 环境(Xcode + MonkeyDev)。
  3. Frida 已安装在 Mac 上(pip install frida-tools)。
  4. 你要调试的 App 可以是自签名的或者使用企业签名/调试证书安装。

⚠️ 非越狱设备无法直接注入所有系统 App,只能调试用户安装的 App。


2️⃣ MonkeyDev + Frida 的结合思路

MonkeyDev 是 iOS 动态库注入 + 开发工具链,主要用于:

  • Hook App 方法
  • 调试内部逻辑
  • 修改行为(类似 tweak)

Frida 是 动态 hook 工具,可远程注入 JS 脚本 hook App 函数。

两者结合的核心逻辑:

  1. 用 MonkeyDev 注入自定义动态库

    • MonkeyDev 可以通过 Xcode 工程生成一个 dylib 并附加到目标 App。
    • 这个 dylib 可以在加载时初始化一些你自定义的 hook 或日志。
  2. 在 dylib 中初始化 Frida Gadget

    • Frida 官方提供了 FridaGadget.dylib,可以静态编译进你的 dylib。
    • MonkeyDev 项目中,可以把 FridaGadget 加入 Linked Libraries。
    • 当 App 启动时,Frida Gadget 会自动加载,允许你从 Mac 端 Frida 客户端附加并执行 JS 脚本。
  3. 在 Mac 上连接设备并使用 Frida

    frida-ps -U   # 查看设备上运行的 Appfrida -U -n AppName -l your_script.js
    • -U 表示连接 USB 设备
    • -n 是 App 名称
    • -l 是你的 Frida JS 脚本

3️⃣ 非越狱设备注意点

  • 代码签名
    • 所有 MonkeyDev 编译的动态库 + Frida Gadget 都必须使用合法证书签名。
    • 否则 App 无法启动。
  • iOS 系统限制
    • 某些安全敏感 API 可能被沙箱/系统保护阻止。
    • 非越狱设备上,不能 hook 系统级 App(如 Safari、设置)。

4️⃣ 操作流程总结

  1. 使用 MonkeyDev 创建一个 iOS 动态库工程。
  2. 将 FridaGadget.dylib 添加到 MonkeyDev 项目。
  3. 编译并安装到非越狱设备上的目标 App(签名合法)。
  4. 确认 App 启动时 Frida Gadget 被加载。
  5. 在 Mac 上使用 frida-ps -U 和 frida -U -n AppName 附加,执行 JS 脚本 hook 逻辑。

问题总结

1、日志窗口出现如下信息,没有其他后续日志以及APP不显示UI页面

Frida: Listening on 127.0.0.1 TCP port 27042

原因:

Gadget 在 constructor 里启动后,会监听 127.0.0.1:27042,然后 阻塞进程继续启动,直到 Frida 客户端 attach 或显式 resume。

解决方式是加一个 FridaGadget.config,把启动行为改成不等待:

{"interaction": {"type": "listen","address": "127.0.0.1","port": 27042,"on_port_conflict": "fail","on_load": "resume"  }}

注意配置文件名必须和最终 dylib 名匹配:你最终包里是 Frameworks/FridaGadget.dylib,所以配置文件应叫 FridaGadget.config,放在 Frameworks 旁边或 App bundle 根目录都可以,Frida 文档也特别提到 iOS/Xcode 场景会查找这两个位置。

手动配置FridaGadget

1. 放文件

在工程根目录建一个目录,例如:

dylib/   frida-gadget.dylib   FridaGadget.config 

FridaGadget.config 内容建议先用不阻塞启动的版本:

{"interaction": {"type": "listen","address": "127.0.0.1","port": 27042,"on_port_conflict": "fail","on_load": "resume"  }}

2. 确认 dylib install name

otool -D dylib/frida-gadget.dylib 

最好显示:

@executable_path/Frameworks/FridaGadget.dylib 

如果不是,改一下:

install_name_tool -id @executable_path/Frameworks/FridaGadget.dylib dylib/frida-gadget.dylib 

3. 在 Xcode 里链接 FridaGadget.dylib

选中 MonkeyDev 的注入 dylib target,比如 xxxDylib:

Build Phases -> Link Binary With Libraries -> + -> Add Other...

选择:

dylib/frida-gadget.dylib 

然后建议在 Xcode 中把显示名改成或确认最终依赖路径是:

@executable_path/Frameworks/FridaGadget.dylib 

最终效果用这个确认:

otool -L path/to/libYourMonkeyDevDylib.dylib 

里面应有:

@executable_path/Frameworks/FridaGadget.dylib 

4. 把 Gadget 和 config 复制进 App

选中 App target,也就是 MonkeyDev 生成的宿主 target,不是 xxxDylib target。

Build Phases -> + -> New Run Script Phase

放在 MonkeyDev 最终 codesign 脚本之前,脚本内容:

set -eGADGET_SRC="${SRCROOT}/dylib/frida-gadget.dylib"CONFIG_SRC="${SRCROOT}/dylib/FridaGadget.config"GADGET_DIR="${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"GADGET_DST="${GADGET_DIR}/FridaGadget.dylib"CONFIG_DST="${GADGET_DIR}/FridaGadget.config"mkdir -p "$GADGET_DIR"cp -f "$GADGET_SRC""$GADGET_DST"cp -f "$CONFIG_SRC""$CONFIG_DST"echo"Frida Gadget copied to $GADGET_DST"echo"Frida Gadget config copied to $CONFIG_DST"

5. 加初始化日志

在 MonkeyDev 注入 dylib 的 constructor 里检查 dyld image,类似:

#import <mach-o/dyld.h>#include<string.h>staticvoid LogFridaGadgetStatus(void) {    uint32_t count = _dyld_image_count();for (uint32_t i = 0; i < count; i++) {constchar *name = _dyld_get_image_name(i);if (name && strstr(name, "FridaGadget.dylib")) {NSLog(@"[FridaGadget] loaded: %s", name);return;        }    }NSLog(@"[FridaGadget] not loaded");}

然后在 CHConstructor 或 %ctor 里调用:

LogFridaGadgetStatus(); 

关键点就三个:xxxDylib target 负责链接 Gadget,App target 负责复制 FridaGadget.dylib + FridaGadget.config 到 Frameworks,最终签名阶段必须在复制之后执行。

脚本执行验证

查找app相关信息

frida-ps -Uai 

看到对应App 后,用显示出来的进程名或 bundle id。比如 bundle id 方式通常更稳:

frida -U -f com.demo.test -l fridajs/disable-flutter-tls.js 

现在是 Xcode 已经启动 App 的场景,所以优先用 attach:

frida -U -n "进程名" -l fridajs/disable-flutter-tls.js 

进入 Frida 交互后,看到类似这些日志就说明脚本跑起来了:

     ____    / _  |   Frida 17.9.7 - A world-class dynamic instrumentation toolkit   | (_| |    > _  |   Commands:   /_/ |_|       help      -> Displays the help system   . . . .       object?   -> Display information about 'object'   . . . .       exit/quit -> Exit

最新文章

随机文章