10.1 Block-level
%hook
指定需要hook的class,必須以%end結(jié)尾。可以被%group包含
%hook SBApplicationController
-(void)uninstallApplication:(SBApplication *)application {
NSLog(@"Hey, we're hooking uninstallApplication:!");
%orig; // Call the original implementation of this method
return;
}
%end
%group
該指令用于將%hook分組,便于代碼管理及按條件初始化分組,必須以%end結(jié)尾。
一個(gè)%group可以包含多個(gè)%hook,所有不屬于某個(gè)自定義group的%hook會(huì)被隱式歸類到%group_ungrouped中。
%group iOS8
%hook IOS8_SPECIFIC_CLASS
// your code here
%end // end hook
%end // end group ios8
%group iOS9
%hook IOS9_SPECIFIC_CLASS
// your code here
%end // end hook
%end // end group ios9
%ctor {
if (kCFCoreFoundationVersionNumber > 1200) {
%init(iOS9);
} else {
%init(iOS8);
}
}
%new
在%hook內(nèi)部使用,給一個(gè)現(xiàn)有class添加新函數(shù),功能與class_addMethod相同。
注: Objective-C的category與class_addMethod的區(qū)別: 前者是靜態(tài)的而后者是動(dòng)態(tài)的。
%hook SBApplicationController
-(void)uninstallApplication:(SBApplication *)application {
NSLog(@"Hey, we're hooking uninstallApplication:!");
%orig; // Call the original implementation of this method
return;
}
%new
- (void)namespaceNewMethod
{
NSLog(@"We've added a new method to SpringBoard.");
}
%end
10.2 Top level
%ctor
tweak的構(gòu)造函數(shù),完成初始化工作;如果不顯示定義,Theos會(huì)自動(dòng)生成一個(gè)%ctor,并在其中調(diào)用%init(_ungrouped)。
%dtor
tweak的構(gòu)造函數(shù),完成收尾。如果不顯示定義,Theos會(huì)自動(dòng)生成一個(gè)%dtor。
10.3 Function level
%init
該指令用于初始化某個(gè)%group,必須在%hook或%ctor內(nèi)調(diào)用;如果帶參數(shù),則初始化指定的group,如果不帶參數(shù),則初始化_ungrouped.
注: 切記,只有調(diào)用了%init,對(duì)應(yīng)的%group才能起作用!
%ctor {
if (kCFCoreFoundationVersionNumber > 1200) %init(iOS9);
else %init(iOS8);
}
%c
該指令的作用等同于objc_getClass或NSClassFromString,即動(dòng)態(tài)獲取一個(gè)類的定義,在%hook或%ctor內(nèi)使用 。
%hook SpringBoard
- (void)_menuButtonDown:(id)down
{
%orig;
SBScreenShotter *shotter = [%c(SBScreenShotter) sharedInstance];
[shotter saveScreenshot:YES];
}
%end@
%log
該指令在%hook內(nèi)部使用,將函數(shù)的類名、參數(shù)等信息寫入syslog,可以%log([(),…..])的格式追加其他打印信息。
%orig
該指令在%hook內(nèi)部使用,執(zhí)行被hook的函數(shù)的原始代碼;也可以用%orig更改原始函數(shù)的參數(shù)。
練習(xí)
@interface SBScreenshotter: NSObject
+ (id)sharedInstance;
- (void)saveScreenshot: (BOOL)arg1;
@end
@interface SpringBoard
+ (void)_AutoScreenSave2;
- (void)_AutoScreenSave;
@end
%hook SpringBoard
- (void)applicationDidFinishLaunching:(id)application
{
%orig;
UIAlertView *alert = [[UIAlertView alloc]
initWithTitle:@"Hello,Tanzhou!"
message:nil
delegate:self cancelButtonTitle:@"OK"
otherButtonTitles:nil];
[alert show];
}
%new
- (void)_AutoScreenSave
{
NSLog(@"instance method");
SBScreenShotter *shotter = [%c(SBScreenShotter) sharedInstance];
[shotter saveScreenshot:YES];
}
%new
+ (void)_AutoScreenSave2
{
NSLog(@"class method");
SBScreenShotter *shotter = [%c(SBScreenShotter) sharedInstance];
[shotter saveScreenshot:YES];
}
- (void)_menuButtonDown:(id)down
{
//SBScreenShotter *shotter = [%c(SBScreenShotter) sharedInstance];
//[shotter saveScreenshot:YES];
//[self _AutoScreenSave];
[%c(SpringBoard) _AutoScreenSave2];
NSLog(@"x=%d, y=%d", 10, 20);
%log((NSString *)@"iOSRE", (NSString *)@"Debug");
%orig; // call the original _menuButtonDown:
}
%end
%hook SBLockScreenDateViewController
- (void)setCustomSubtitleText:(id)arg1 withColor:(id)arg2
{
/*
NSDate *date=[NSDate date];
NSDateFormatter *format1=[[NSDateFormatter alloc]init];
[format1 setDateFormat:@"yyyy/MM/dd HH:mm:ss"];
NSString *str1=[format1 stringFromDate:date];
*/
struct tm *loctime;
char timeBuf[1024] = {0};
time_t now = time(NULL);
loctime = localtime(&now);
strftime(timeBuf, 30, "[%Y/%m/%d %H:%M:%S]", loctime);
%orig([NSString stringWithUTF8String:timeBuf],arg2);
}
%end
/*
%group HookTest
%hook SpringBoard
- (void)_lockButtonDown:(struct __IOHIDEvent *)arg1 fromSource:(int)arg2
{
NSLog(@"_lockButtonDown");
}
- (void)_lockButtonUp:(struct __IOHIDEvent *)arg1 fromSource:(int)arg2
{
NSLog(@"_lockButtonUp");
}
- (void)powerDownCanceled:(id)arg1
{
NSLog(@"powerDownCanceled");
%orig;
}
- (void)powerDown
{
NSLog(@"powerDown");
}
- (void)powerDownRequested:(id)arg1
{
NSLog(@"powerDownRequested");
}
%end
%end
*/
%ctor
{
%init(_ungrouped);
//%init(HookTest);
}