// 导入常用的UI框架和Foundation框架
// 导入MonkeyDev提供的头文件,这头文件,后边我们创建framework插件时也可使用
/*
定义你需要Hook的类及需要Hook的方法。
*/
@interface DetailViewController : NSObject
// 需要Hook的实例方法
- (void)loginButtonDidClick:(UIButton *)sender;
// 以下两个方法并不存在,在这只是为了演示如何hook多个参数的方法和hook类方法
- (NSString *)loginWithPhone:(NSString *)phone password:(NSString *)pwd;
+ (id)factory:(id)arg1;
@end
CHDeclareClass(DetailViewController); // 步骤1、申明需要Hook的类
/*
步骤3、你的勾子函数,Hook函数被调用时,会执行到这
CHOptimizedMethod的参数说明
第一个参数:固定写死self即可
第二个参数:返回值类型,无返回值写void。c语言的类型,直接写对应的类型即可(int,float,double...)。其他类型,直接写id即可,如果你知道具体的类型,也可写具体的类型
第三个参数:类名
第四个参数:方法名
// 方法名有一个参数时
第五个参数:第一个入参的类型,和第二个参数写法类型
第六个参数:第一个入参的形参名
// 方法名有两个参数时
第七个参数:第二个入参的类型,和第二个参数写法类型
第八个参数:第二个入参的形参名
...
*/
CHOptimizedMethod1(self, void, DetailViewController, loginButtonDidClick, UIButton*, sender) {
CHSuper1(DetailViewController, loginButtonDidClick, sender); // 调用原方法
NSLog(@"witchan =该方法的入参为:%@", sender);
}
// Hook两个入参的实例方法
CHOptimizedMethod2(self, id, DetailViewController, loginWithPhone, NSString *, p, password, NSString*, pwd) {
id result = CHSuper2(DetailViewController, loginWithPhone, p, password, pwd); // 调用原方法
NSLog(@"witchan =该方法的第一个入参为:%@", p);
NSLog(@"witchan =该方法的第二个入参为:%@", pwd);
NSLog(@"witchan =该方法的返回值为:%@", result);
return result;
}
// Hook一个入参的类方法,相对于实例方法,只是在Method前多了个Class单词。其他操作完全一样
CHOptimizedClassMethod1(self, id, DetailViewController, factory, id, arg1) {
id result = CHSuper1(DetailViewController, factory, arg1); // 调用原方法
NSLog(@"witchan =该方法的入参为:%@", arg1);
NSLog(@"witchan =该方法的返回值为:%@", result);
/*
由于deb格式、dylib格式还是framework格式,都支持使用c、c++和OC语言进行开发。
以下代码为oc语法的简单示例。
注意:整个插件的写法,和ios开发完全一致,你可以创建新类,也可以调用oc提供的类及相关方法
如果你不熟悉oc语法,请看我公众号的另一篇文章,iOS快速入门:https://mp.weixin.qq.com/s/g89Sdyqc4ONlyAWtXTCwRA
*/
NSMutableDictionary *params = [NSMutableDictionary dictionary];
params[@"微信公众号"] = @"移动端Android和iOS开发技术分享";
params[@"QQ群"] = @"812546729";
NSData *body = [NSJSONSerialization dataWithJSONObject:params options:NSJSONWritingPrettyPrinted error:nil];
// 调用登录接口
NSURL *loginURL = [NSURL URLWithString:@"534K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1j5I4x3U0N6Q4x3X3f1H3i4K6u0W2x3q4)9J5k6e0q4Q4x3@1p5&6x3o6R3H3i4K6u0r3L8r3!0Y4K9h3^5`."]; // 接口
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:loginURL]; // 请求对象
request.HTTPMethod = @"POST"; // 请求方式
[request setValue:@"d83kd9d323" forHTTPHeaderField:@"x-sign"]; // 设置header
request.HTTPBody = body; // 注意,HTTPBody是一个16进制数据,一般直接16进制输出,再转换成文本查看
NSURLSession *session = [NSURLSession sharedSession]; // 获取网络对象
NSURLSessionTask *task = [session dataTaskWithRequest:request
completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
// 请求结果会调到这
if (error != nil) {
NSLog(@"witchan =网络请求出错了");
} else {
NSLog(@"witchan =网络请求成功");
}
}]; // 创建请求任务
[task resume]; // 发起网络请求
return result;
}
// 入口函数
CHConstructor
{
@autoreleasepool
{
NSLog(@"witchan =FirsFramework hook success!="); // 一般在入口函数输出一条日志,确定你的插件是否加载成功
CHLoadLateClass(DetailViewController); // 步骤2、加载需要Hook的类
CHHook1(DetailViewController, loginButtonDidClick); // 步骤4、注册你需要hook的实例方法
CHHook2(DetailViewController, loginWithPhone, password);
CHClassHook1(DetailViewController, factory); // 注册需要hook的类方法
}
}