// Tweak.xm

1.预处理指令

%hook

指定需要hook的class,必须以%end结尾

%hook SpringBoard
- (void)_menuButtonDown:(id)down
{
    NSLog(@"你好");
    %orig;//call the original _menuButtonDown;
}
%end

这段代码的意思是勾住(hook) SpringBoard 类里的_menuButtonDown: 函数,先将一句话写入 syslog , 再执行函数的原有操作。

%log

该指令在%hook内部使用,将函数的类名、参数等信息写入syslog。

%hoot SpringBoard
- (void)_menubuttonDown:(id)down
{
    %log((NSString *)@"iOSRE",(NSString *)@"Debug");
    %orig;//call the original _menuButtonDown;
}
%end

%orig

该指令在%hook内部使用,执行被勾住(hook)的函数的原始代码。例如:

%hook SpringBoard
- (void)_menuButtonDown:(id)down
{
    NSLog(@"你好");
    %orig; // 
}
%end

如果去掉 *%orig * 那么原始函数不会执行。

hook SpringBoard
- (void)_menuButtonDown:(id)down
{
    NSLog(@"你好");
}
%end

还可以利用 %orig 更改原始行数的参数。

%hook SBLockScreenDateViewController
- (void)setCustomSubtitleText:(id)arg1 withColor:(id)arg2
{
    %orig(@"Re",arg2);
}
%end

这个方法会改变锁屏界面的日期显示.

%group

该指令用于将* %hook 分组,便于代码管理及按条件初始化分组,必须以 *%end 结尾;一个* %group 可以包含多个 %hook , 所有不属于某个自定义 group %hook 会被隐式归类到 %group_ungroupes *中。用法如下:

%group iOS7Hook
%hook iOS7Class 
- (id)iOS7Method {
     id result = %orig; 
     NSLog(@"This class & method only exist in iOS 7."); 
     return result;
 } %end 
%end // iOS7Hook

%group iOS8Hook 
%hook iOS8Class 
- (id)iOS8Method {
   id result = %orig; 
   NSLog(@"This class & method only exist in iOS 8."); return result;
 }
%end
%end // iOS8Hook

%init

该指令用于初始化某个 * %group ,必须在 %hook %ctor 内调用;如果带参数,则初始化指定的 group,如果不带参数,则初始化 *_ungrouped ,如下:

#ifndef kCFCoreFoundationVersionNumber_iOS_8_0 
#define kCFCoreFoundationVersionNumber_iOS_8_0 1140.10 #endif
%hook SpringBoard 
- (void)applicationDidFinishLaunching:(id)application {
    %orig; 
    %init; // Equals to %init(_ungrouped)
    if (kCFCoreFoundationVersionNumber >= kCFCoreFoundationVersionNumber_iOS_7_0 && kCFCoreFoundationVersionNumber < kCFCoreFoundationVersionNumber_iOS_8_0)
      %init(iOS7Hook);
    if (kCFCoreFoundationVersionNumber >= kCFCoreFoundationVersionNumber_iOS_8_0)
      %init(iOS8Hook);
}
%end

只有调用了 %init,对应的 %group 才能起作用,切 切 !

%ctor

tweak 的* constructor 完成初始化工作;如果不显式定义,Theos会自动生成一个 *%ctor *,并在其中调用 %init(_ungrouped) *。因此,

%hook SpringBoard 
- (void)reboot {
    NSLog(@"If rebooting doesn't work then I'm screwed.");
    %orig;
}
%end

可以成功生效,因为 Theos 隐式定义了如下内容:

%ctor
{
    %init(_ungrouped);
}

%hook SpringBoard
- (void)reboot{
     NSLog(@"If rebooting doesn't work then I'm screwed.");
     %orig;
}
%end

%ctor
{
    // Need to call %init explicitly!
}

里的 %hook 无法生效,因为这里显示定义了 %ctor ,却没有调用 %init%group(_ungrouped) 不起作用。%ctor 一般可以用来初始化 %group ,以及进行 MSHookFunction 等操作。

注意, %ctor 不需要以 %end 结尾 。

%new

%hook 内部使用,给一个现有 class 加新函数,功能与 class_addMethod 相同。它的用法如下:

%hook SpringBoard 
%new 
- (void)namespaceNewMethod {
     NSLog(@"We've added a new method to SpringBoard."); 
}
%end

%c

该指令的作用等同于 objc_getClassNSClassFromString,即动态获 一个类的定义,在 %hook%ctor 内使用。

%subclass

%config