iOS hook delegate (一)

本文介绍了一种利用MethodSwizzling技术hook未知调用类的方法,通过重写UIWebView的setDelegate方法来捕获代理对象,并进一步交换指定代理方法的实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

利用method Swizzling黑魔法可以轻松的 hook 系统的已知类的方法, 但是对于系统的delegate方法, 其实际调用类存在多种, 如何针对未知调用类的 hook 呢?

我们结合webView进行探讨, 并且假定调用webView的类已经实现了其所有的代理方法, 在不改变原类调用的请求下, 如何 hook 它呢?

首先,如果我们设置webView的代理方法, 一定会调用:

webView.delegate = xxx;

这样一定会调用webView的setDelegate方法, 因此我们想到可不可以hook webView的setDelegate拿到实际调用其代理的类, 然后对其进行方法交换.

- (void)hook_setDelegate:(id<UIWebViewDelegate>)delegate{
    [self hook_setDelegate:delegate];
    // 获得delegate的实际调用类
    Class aClass = [delegate class];
    // 传递给HookWebViewDelegateMonitor来交互方法
    [HookWebViewDelegateMonitor exchangeUIWebViewDelegateMethod:aClass];
}
// 在load中交换系统的setDelegate 和我们要hook的代理方法
+ (void)load{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        Method originalMethod = class_getInstanceMethod([UIWebView class], @selector(setDelegate:));
        Method swizzledMethod = class_getInstanceMethod([UIWebView class], @selector(hook_setDelegate:));
        method_exchangeImplementations(originalMethod, swizzledMethod);
    });
}

首先我们新建一个类(HookWebViewDelegateMonitor), 用于交互方法并实现:

#import "HookWebViewDelegateMonitor.h"
#import <objc/runtime.h>
#import <objc/message.h>

static void hook_exchangeMethod(Class originalClass, SEL originalSel, Class replacedClass, SEL replacedSel){
    Method originalMethod = class_getInstanceMethod(originalClass, originalSel);
    Method replacedMethod = class_getInstanceMethod(replacedClass, replacedSel);
    IMP replacedMethodIMP = method_getImplementation(replacedMethod);
    // 将样替换的方法往代理类中添加, (一般都能添加成功, 因为代理类中不会有我们自定义的函数)
    BOOL didAddMethod =
    class_addMethod(originalClass,
                    replacedSel,
                    replacedMethodIMP,
                    method_getTypeEncoding(replacedMethod));

    if (didAddMethod) {// 添加成功
        NSLog(@"class_addMethod succeed --> (%@)", NSStringFromSelector(replacedSel));
        // 获取新方法在代理类中的地址
        Method newMethod = class_getInstanceMethod(originalClass, replacedSel);
        // 交互原方法和自定义方法
        method_exchangeImplementations(originalMethod, newMethod);
    }else{// 如果失败, 则证明自定义方法在代理方法中, 直接交互就可以
        method_exchangeImplementations(originalMethod, replacedMethod);
    }
}

@implementation HookWebViewDelegateMonitor

+ (void)exchangeUIWebViewDelegateMethod:(Class)aClass{
    hook_exchangeMethod(aClass, @selector(webViewDidStartLoad:), [self class], @selector(replaced_webViewDidStartLoad:));
    hook_exchangeMethod(aClass, @selector(webViewDidFinishLoad:), [self class], @selector(replaced_webViewDidFinishLoad:));
    hook_exchangeMethod(aClass, @selector(webView:didFailLoadWithError:), [self class], @selector(replaced_webView:didFailLoadWithError:));
    hook_exchangeMethod(aClass, @selector(webView:shouldStartLoadWithRequest:navigationType:), [self class], @selector(replaced_webView:shouldStartLoadWithRequest:navigationType:));

}

- (BOOL)replaced_webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
    NSLog(@"-------replaced_webView-shouldStartLoadWithRequest---------");
    return [self replaced_webView:webView shouldStartLoadWithRequest:request navigationType:navigationType];
}

- (void)replaced_webViewDidStartLoad:(UIWebView *)webView
{
    NSLog(@"-------replaced_webViewDidStartLoad--------");
    [self replaced_webViewDidStartLoad:webView];
}

- (void)replaced_webViewDidFinishLoad:(UIWebView *)webView
{
    NSLog(@"-------replaced_webViewDidFinishLoad--------");
    [self replaced_webViewDidFinishLoad:webView];
}

- (void)replaced_webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error{
    NSLog(@"--------replaced_webView-didFailLoadWithError--------");
    [self replaced_webView:webView didFailLoadWithError:error];
}

@end

当我们在ViewController中实现了WebView的调用打印日志如下:
这里写图片描述
这个方法还有一个弊端就是只能hook 原类中已经调用了的方法 , 如果原类中没有实现shouldStartLoadWithRequest这个方法的话, replace_shouldStartLoadWithRequest这个方法也不会调用.
这里写图片描述

Demo 地址如下
Demo

本人还在进一步的探索中, 如有问题, 欢迎指正, 非常感谢. 如果大佬们有更好的hook方案, 也希望可以告知小弟.

参考资料:
通过Method Swizzling实现Hook中的深坑
小白笔记(“动态”hook某class的delegate方法”)
Objective-C的hook方案(一): Method Swizzling
利用Objective-C运行时hook函数的三种方法

<think>我们正在讨论Theos,根据用户提供的引用信息,Theos是个用于开发越狱插件的工具。引用中提到了Theos的符号链接和环境变量设置,以及生成.deb包时对control文件的处理。用户现在想了解Theos是什么。 因此,我们需要给用户解释Theos的定义、用途以及它在越狱开发中的角色。同时,我们可以结合引用中提到的内容,说明Theos的些特性(如符号链接设置、打包行为等)。 注意:用户提供的引用[1]和[2]是关于Theos的具体配置和打包行为的,我们在解释Theos时可以作为补充说明。 回答结构: 1. 定义Theos:是什么,主要用途。 2. 说明Theos的特点:比如它支持哪些开发语言,提供了哪些工具和功能。 3. 结合引用信息:解释引用中提到的符号链接和环境变量设置,以及打包行为。 4. 补充Theos在越狱开发中的重要性。 5. 生成相关问题。 注意:我们不需要深入技术细节,但要让用户对Theos有个基本的认识。</think>### Theos 越狱开发框架详解 Theos 是个专为 iOS/macOS 越狱环境设计的开发框架,用于创建插件、主题和系统级修改工具。它提供了套完整的工具链,简化了越狱插件的开发流程[^1]。 #### 核心功能与特性 1. **跨平台支持** - 支持 iOS/macOS 越狱插件开发 - 兼容 ARM/ARM64/X86 架构 - 提供 Makefile 模板系统:`$THEOS/makefiles` 2. **模块化构建系统** ```makefile # 基础工程模板 TARGET := iphone:clang ARCHS := arm64 arm64e include $(THEOS)/makefiles/common.mk TWEAK_NAME = MyTweak MyTweak_FILES = Tweak.xm include $(THEOS_MAKE_PATH)/tweak.mk ``` 3. **包管理机制** - 自动生成 DEB 安装包(Debian 格式) - 智能处理 control 文件: - 自动添加版本标识:`Version: 0.0.1-N`[^2] - 计算安装大小:`Installed-Size` 字段[^2] - 支持多架构依赖声明 #### 环境配置特性 1. **符号链接模式** - 通过 `link_theos` 布尔值控制(默认 0)[^1] - `0`:依赖 `$THEOS` 环境变量 - `1`:创建指向 Theos 安装位置的符号链接 ```bash # 手动设置符号链接模式 export LINK_THEOS=1 ``` 2. **工作流优势** - **键编译**:`make package` 生成 DEB - **自动签名**:集成 ldid 签名工具 - **热加载**:`make install` 直接部署到设备 #### 典型应用场景 1. **系统功能扩展** - SpringBoard 界面修改 - 系统 API Hook(通过 Substrate 或 libhooker) 2. **应用增强** ```objc // Tweak.xm 示例:修改应用行为 %hook SpringBoard - (void)applicationDidFinishLaunching:(id)application { %orig; UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Theos" message:@"插件已加载" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil]; [alert show]; [alert release]; } %end ``` 3. **主题引擎开发** - 图标包制作(.theme 格式) - 动态界面元素替换 > **注意**:Theos 需要配合越狱环境(如 Checkra1n/Unc0ver)使用,在非越狱设备上无法运行[^1][^2]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值