Monkey实现HOOK
新建一个MonkeyApp
,点TARGETS的工程-->Signing & Capabilities
-->Team
添加自己的开发账号获取描述文件。
细心的你,根据工程的文件结构还发现Monkey支持fishook,对抗调式,Tools里面有LLDB
调式的一些指令支持,还有Cycript
脚本支持,Logos
语法。我们先不用理会其他的,首先进行一下HOOK
OC函数!将.ipa
或者.app
文件放到TargetApp文件目录下,直接运行,就实现了重签名运行到自己的手机上了。(是不是很爽?)
选择.xm | 修改Type类型为Objective-C++ |
---|---|
重新点到别处,在点击.xm文件,里面就变成了我们熟悉的代码了,Monkey
会自动给我们添加了一些代码,为了干净,我们将其全部删除,只留#import <UIKit/UIKit.h>
这一句,就可以还是我们的代码了。
笔者的TargetApp就做了两个按钮,我们看一下.xm如何HOOK按钮的事件的。
目标App界面 | 目标App代码 |
---|---|
Hook代码如下,在%hook.....%end
中添加HOOK
的函数即可,ViewController
是告诉工程要HOOK
的类。
// Hook代码如下:
#import <UIKit/UIKit.h>
%hook ViewController
- (void)button1Click:(id)sender {
NSLog(@"哥们,你的按钮1来不了了");
}
%end
Logos语法
关于Logos语法,不想看笔者碧碧的,可以直接点这里到官网去看英文文档。
Logos是Theos的一个组件,分为三个清单
-
Block level
-
%group
- 语法:
%group 组名
- 必须跟
%end
配对,不应该在C函数或者OC方法里面 - 定义的所有group,都在
%ctor{}
构造函数中调用%init(组名)
初始化 - 例子:看下面代码部分的例子1
- 语法:
-
%hook
- 语法:
%hook 类名
- 必须跟
%end
成对出现,可放在%group
和%end
之间 - 列子:看下面代码部分的例子1
- 语法:
-
%new
- 语法:
%new
或者%new(signature)
- 给hook类或子类添加方法,必须在
%hook
和%end
之间,signature
可省使用第一种语法 - 例子:看下面代码部分的例子2
- 语法:
-
%subclass
- 语法:
%subclass 子类名: 父类名 <协议列表>
- 可以在
%group
和%end
之间 - 一般都会配合
%new
添加方法,使用%c
实例化一个对象(不支持添加成员变量ivar
,可用associated object
) - 例子:看下面代码部分的例子2
- 语法:
-
property
- 语法:
%property (nonatomic|assign|retain|copy|weak|strong|getter|setter) Type name;
- 必须在
%subclass
或者%hook
里面 - 例子:看下面代码部分的例子2
- 语法:
-
%end
- 语法:
%end
- 常跟
%group
、%hook
、%subclass
配合使用
- 语法:
-
%group
**********************例子1:*********************
%group iOS8
%hook IOS8_SPECIFIC_CLASS
// 你的代码
%end // hook结束
%end // 组ios8的结束
%group iOS9
%hook IOS9_SPECIFIC_CLASS
// 你的代码
%end // hook的结束
%end // 组ios9的结束
%ctor {
if (kCFCoreFoundationVersionNumber > 1200) {
%init(iOS9);
} else {
%init(iOS8);
}
}
**********************例子2:*********************
%subclass MyObject : NSObject
%property (nonatomic, copy)NSString *myString;
- (id)init {
self = %orig;
[self setSomeValue:@"value"];
return self;
}
//the following two new methods act as `@property (nonatomic, retain) id someValue;`
%new
- (id)someValue {
return objc_getAssociatedObject(self, @selector(someValue));
}
%new
- (void)setSomeValue:(id)value {
objc_setAssociatedObject(self, @selector(someValue), value, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
%end
%ctor {
MyObject *myObject = [[%c(MyObject) alloc] init];
NSLog(@"myObject: %@", [myObject someValue]);
}
-
Top level (这部分不应该存在group、hook、subclass中)
-
%config
- 语法:
%config(key=value)
- 有个表,去官网看
- 语法:
-
hookf
- 语法:
%hookf(rtype, symbolName, args...)
- 例子:下面代码例子3
- 语法:
-
%ctor
- 语法:
%ctor{...}
- 生成一个匿名构造函数
- 例子:上面代码部分的例子2
- 语法:
-
%dtor
- 语法:
%dtor{...}
- 生成一个匿名析构函数
- 语法:
-
%config
**********************例子3:*********************
// Given the function prototype
FILE *fopen(const char *path, const char *mode);
// The hook is thus made
%hookf(FILE *, fopen, const char *path, const char *mode) {
NSLog(@"Hey, we're hooking fopen to deny relative paths!");
if (path[0] != '/') {
return NULL;
}
return %orig; // Call the original implementation of this function
}
-
Function level(这部分只存在函数中)
-
%init
- 语法:
%inith
或者%init(...)
- 例子:下面代码部分的例子4
- 语法:
-
%class
- 语法:
%class 类名
- 提前声明一个类
- 语法:
-
%c
- 语法:
%c([+|-]类名)
- 例子:上面代码部分的例子2
- 语法:
-
%orig
- 语法:
%orig
或者%orig(arg1,...)
- 调用原始
hook
的函数,也不要添加self
和_cmd
隐式参数 - 例子:上面代码部分的例子2
- 语法:
-
%log
- 语法:
%log
或者%log([(<type>)<expr>, …])
- 语法:
-
%init
**********************例子4:*********************
%hook SomeClass
-(id)init {
return %orig;
}
%end
%ctor {
%init(SomeClass=objc_getClass("class with spaces in the name"));
}