Logos 语法简单介绍
准备工作
- 新建一个Demo ,类似登录页面,少许逻辑,导出 app 包 和 头文件,以待备用。
- 新建一个 MonkeyDev 项目,导入要 Hook 的 APP 包。
Cydia Substrate
Cydia Substrate 原名为 Mobile Substrate ,它的主要作用是针对OC方法、C函数以及函数地址进行HOOK操作。当然它并不是仅仅针对iOS而设计的,安卓一样可以用。官方地址:http://www.cydiasubstrate.com/
Cydia Substrate主要由3部分组成:
-
MobileHooker
MobileHooker顾名思义用于HOOK。它定义一系列的宏和函数,底层调用objc的runtime和fishhook来替换系统或者目标应用的函数.
其中有两个函数:- MSHookMessageEx 主要作用于Objective-C方法
void MSHookMessageEx(Class class, SEL selector, IMP replacement, IMP result)
- MSHookFunction 主要作用于C和C++函数
void MSHookFunction(voidfunction,void* replacement,void** p_original)
Logos语法的%hook 就是对此函数做了一层封装
Cydia Substrate 底层使用的就是 Method Swizzle 和 fishhook。
Cydia substrate 注入进去之后,就可以用 Logos 语法 来写 Logos 了。
![](https://img.haomeiwen.com/i4790087/696124dfcf1e3d57.png)
![](https://img.haomeiwen.com/i4790087/d9a1fb8867a49567.png)
其中 _02_LoginHookDemoDylib.xm
x : 代表 这个文件支持 Logos 语法
如果后缀为 单独的 x : 说明 源文件支持 Logos 的 C语言 语法。
xm 支持 **Logos ** 的 C,C++,OC 语法。
![](https://img.haomeiwen.com/i4790087/0130525f120d01ec.png)
- 文件扩展名
.X 将由Logos处理,然后进行预处理并编译为objective-c。
.xm 将由Logos处理,然后进行预处理并编译为objective-c ++。
.xi 将首先作为objective-c进行预处理,然后Logos将处理结果,然后将进行编译。
.xmi 将首先作为objective-c ++进行预处理,然后Logos将处理结果,然后将进行编译。
xi或xmi文件可以在#define宏中使用Logos指令。
- %group
![](https://img.haomeiwen.com/i4790087/65865dc321f84d5f.png)
![](https://img.haomeiwen.com/i4790087/ae9313f2025f7ddd.png)
- constructor 构造函数:多组 group 就需要 创建 constructor。
// constructor 构造函数
%ctor{
%init(group1)%init(group2)
}
没创建一个group 就需要 init,前后的初始化顺序很重要,后面会把前面的 group 覆盖掉。
可以判断加载不同的group
- %init 初始化
%ctor{
NSString *version = [UIDevice currentDevice].systemVersion;
if(version.doubleValue >= 11.4){
%init(group1)
}else{
%init(group2)
}
}
默认的会隐式加载
%ctor{
%init(_ungrouped)
}
如果不显示定义,Theos会自动生成一 个%ctor, 并在其中调用%init( ungrouped).
%ctor 一般可以用来初始化%group,以及进行 MSHookFunction 等操作。
-
%dtor 析构函数,与 %ctor 对应
-
%log 输出,直接调用
![](https://img.haomeiwen.com/i4790087/e333d75d5ca96a28.png)
%log;
002-LoginHookDemo/002-LoginHookDemoDylib/Logos/_02_LoginHookDemoDylib.xm:11�[m �[0;30;46mDEBUG:�[m -[<ViewController: 0x105612cb0> btnClick:<UIButton: 0x1057156c0; frame = (164 318; 31 30); opaque = NO; autoresize = RM+BM; layer = <CALayer: 0x1c4229c40>>]
- %orig
![](https://img.haomeiwen.com/i4790087/fafbca05df4e97a3.png)
可以用来接收返回的值并修改,也可以传入参数。
- %new 给某个类添加方法
%new 直接添加,不需要 %end 结束,另外 一个 %new 对应一个方法。
如:
%new
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
[self.view endEditing:YES];
}
%new
+ (void)class_Methiod
{
NSLog(@"这是一个类方法");
}
![](https://img.haomeiwen.com/i4790087/18a57070bd204fd2.png)
上图可以看出 MonkeyDev 原理也是注入的 动态库,可以在内部新建你想创建的任何文件,都会被打包进 动态库中。
- %c() 根据类名获取一个类
![](https://img.haomeiwen.com/i4790087/b566968636531133.png)
如下,这样调用一样的效果:
// 调用类方法
// 1.
// [self.class class_Methiod];
// 2.
// [NSClassFromString(@"ViewController") class_Methiod];
// 3.
[%c(ViewController) class_Methiod];