LOGOS语法
初始化函数
%init
%init([<class>=<expr>, …])
%init(Group[, [+|-]<class>=<expr>, …])
初始化一个组,如果没有参数表示初始化’_ungrouped’组.
代码块指令
这类指令定义HOOK代码块,必须以%end结束.
%hook class
对类设置钩子,这一行只是说明hook块的开始,并没有真正设置钩子,theos使用objc_getClass(Classname)获取要被HOOK的类,在%hook和%end之间编写代理函数,对于钩子的安装,Theos使用MSHookMessageEx(Class class, SEL selector, IMP replacement, IMP *result)完成,这些对我们来说是透明的,我们不需要手动调用,Logos预处理器会自动生成这些代码.
例子:
%hook SBApplicationController
-(void)uninstallApplication:(SBApplication *)application {
NSLog(@”Hello World!”);
%orig; // 调用原始方法
return;
}
%end //结束标记
预处理后为:
//先获取类对象,对应%hook SBApplicationController
Class _logos_class$initGroup$SBApplicationController = objc_getClass(“SBApplicationController”);
//设置hook
MSHookMessageEx(
_logos_class$initGroup$SBApplicationController, //要hook的类
@selector(uninstallApplication), //要hook的函数
(IMP)&_logos_method$initGroup$SBApplicationController$uninstallApplication, //代理函数
(IMP*)&_logos_orig$initGroup$SBApplicationController$uninstallApplication); //存储原始函数
%subclass
%subclass Classname: Superclass <Protocol, Protocol>
为现有的类(Supercalss)添加子类,这个动作在运行时创建并填充.
theos使用objc_allocateClassPair()再调用objc_registerClassPair()完成子类的添加功能.
%group
%group Groupname
这是为hook块分组,,由于有些类在一些特殊条件下才会被初始化,一如果在Tweaks初始化时就去设置钩子,肯定是失败的,所以我们也可以在特定条件下init,比如hook一些不常驻内存的类,再或者在不同的IOS版本中hook不同的函数.有些简单的Tweaks并没有显式声明%group,其实Theos也提供了一个默认的组叫”ungrouped”,所有未被分组的hook都会被设置到这个组里,默认在%ctor函数里面调用.
%new
%new(signature)
为类或子类添加一个新的方法.必须在%hook块或%subclass块使用.theos使用class_addMethod完成.
%ctor
%ctor { … }
这是Theos提供的默认构造函数(默认优先级),当然我们可以编写自己的构造函数让Theos来调用,但是自定义的%ctor函数里面必须手动调用%init对%group自定义的组进行初始化.
%end
表示一个钩子/子类/组作用块的结束
%c
%c([+|-]Class)
动态获取一个类,如果用’+’标记,则获取类的对象,如果用’-’标记则获取实例对象,默认是’-’
%c在经过Logos预处理后变为_logos_static_class_lookup(classname),其实内部还是调用objc_getClass(classname)
%orig
%orig(arg1,arg2,arg3)
调用被hook的原始函数,这个函数不能用在%new创建的函数中.
%log
%log([(<type>)<expr>, …])
打印函数的参数.
Logos的文件扩展名
.x 由Logos处理,然后预处理并编译成object-c
.xm 由Logos处理,然后预处理并编译为objective-c++
.xi 先处理为objective-c,然后Logos处理返回结果最后被编译
.xmi 先处理为objective-c++
默认情况下,Logos的预处理器只在生成时处理.xm文件,不过,有时一个hook代码可能要用在多个文件里.首先把主文件名改为.xmi文件,其他的.xm文件可以使用#include命令,Logos在预处理之前会将这些文件添加到主文件中.
%group SSGroup
%hook SSDownloadAsset
– (NSString *)downloadFileName
{
%log;
NSString * r = %orig;
NSLog(@” = %@”, r);
return r;
}
+ (id)assetWithURL:(id)url type:(int)type
{
%log;
id r = %orig;
NSLog(@” = %@”, r);
return r;
}
%end //%hook
%end //%group