iOS 逆向

Frida 与 Theos 实战:iOS 动态 Hook 技术详解

2025-05-30 wangjun 16 min read
0x

动态分析 vs 静态分析

静态分析看的是"文件里有什么",动态分析看的是"运行时发生了什么"。iOS 逆向的高级阶段几乎都依赖动态 Hook:在方法调用时截获参数、修改返回值、甚至替换整个函数实现。

Method Swizzling:OC 的运行时魔法

Objective-C 的方法调用本质是向对象发送消息 objc_msgSend。每个类都有一个方法列表,method_exchangeImplementations 可以交换两个方法的实现:

+ (void)load {
  Class cls = [ViewController class];
  Method orig = class_getInstanceMethod(cls, @selector(viewDidLoad));
  Method swiz = class_getInstanceMethod(cls, @selector(hook_viewDidLoad));
  method_exchangeImplementations(orig, swiz);
}

- (void)hook_viewDidLoad {
  NSLog(@"[Hook] viewDidLoad 被调用,实例:%@", self);
  [self hook_viewDidLoad]; // 此时实际调用的是原始实现
}

注意交换后,hook_viewDidLoad 里调用的 self 方法其实指向了原始 viewDidLoad -- 这是 Swizzling 最经典的"递归陷阱"。

Frida:跨平台的动态插桩框架

Frida 通过注入一个 JavaScript 引擎到目标进程,让你用 JS 直接操作运行时:

# 设备端运行 frida-server
$ ./frida-server -D &

# 主机端附加到进程
$ frida -U -f com.example.app

拦截 Objective-C 方法

// hook.mjs
ObjC.chooseSync(ObjC.classes.ViewController).forEach(inst => {
  const orig = inst.viewDidLoad;
  inst.viewDidLoad = function () {
    console.log("[+] viewDidLoad called on:", this);
    return orig.call(this);
  };
});

拦截 C 函数

对于纯 C 函数,Interceptor.attach 在指令层面做 inline hook:

const addr = Module.findExportByName(null, "printf");
Interceptor.attach(addr, {
  onEnter(args) {
    console.log("printf called:", Memory.readCString(args[0]));
  }
});

Frida 的常见用途

  • 绕过证书校验:Hook SSL_pin 相关函数,抓取 HTTPS 流量
  • 破解加密:在解密函数返回处打印明文数据
  • 修改逻辑:篡改校验返回值,跳过内购、会员检查
  • UI 自动化:枚举视图层级、模拟点击

Theos:编写越狱 Tweak

如果需要注入逻辑常驻运行,用 Theos 编写 Tweak(Logos 语法):

// Tweak.xm
%hook ViewController

- (void)viewDidLoad {
  %orig;
  UIAlertView *alert = [[UIAlertView alloc]
      initWithTitle:@"Hooked" message:@"Tweak 生效" delegate:nil
      cancelButtonTitle:@"OK" otherButtonTitles:nil];
  [alert show];
}

%end

%hook 会生成对应的 Swizzle 代码并注入目标进程的 __DATA 段。Tweak 打包成 .deb 后通过 Cydia 安装,重启即生效。

越狱环境的注意事项

  • 新版本 iOS 越狱难度加大,越狱检测(jailbreak detection)也日益完善,常见绕过手段是 Hook 检测函数
  • 开发者模式 + get-task-allow 签名的 App 可在未越狱设备上用 Frida 调试
  • 一切逆向行为需在 合法授权 的前提下进行,切勿用于他人 App 的破坏性操作
动态 Hook 是逆向者的"手术刀" -- 它让黑盒变成白盒,让"发生了什么"变成"让它发生什么"。