Logos基础语法

%hook

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

1
2
3
4
5
6
%hook SpringBoard
- (void)_menuButtonDown:(id)down {
NSLog(@"Home Button Pressed");
%orig; // call the original _menuButtonDown:
}
%end

%log

该指令在%hook内部使用,将函数的类名、参数等信息写入syslog,可以以%log([(<type>)<expr>, ...])的格式追加其他打印信息。

1
2
3
4
5
6
%hook SpringBoard
- (void)_menuButtonDown:(id)down {
%log((NSString *)@"iOSRE", (NSString *)@"Debug");
%orig; // call the original _menuButtonDown:
}
%end

%orig

该指令在%hook内部使用,执行被hook的函数的原始代码。此外,还可以利用%orig更改原始函数的参数。

1
2
3
4
5
%hook SBLockScreenDateViewController
- (void)setCustomSubtitleText:(id)arg1 withColor:(id)arg2 {
%orig(@"iOS 8 App Reverse Engineering", arg2);
}
%end

%group

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
%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

%hook SpringBoard
-(void)powerDown {
%orig;
}
%end

%init

该指令用于初始化某个%group,必须在%hook%ctor内调用;如果带参数,则初始化指定的group;如果不带参数,则初始化_ungroupded。只有调用了%init,对应的%group才能起作用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#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

%ctor

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

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

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

1
2
3
4
%ctor 
{
%init(_ungrouped);
}
%ctor一般可以用来初始化%group,以及进行MSHookFunction等操作。%ctor不需要以%end结尾。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#ifndef kCFCoreFoundationVersionNumber_iOS_8_0
#define kCFCoreFoundationVersionNumber_iOS_8_0 1140.10
#endif
%ctor
{
%init;
if (kCFCoreFoundationVersionNumber >= kCFCoreFoundationVersionNumber_iOS_7_0 &&
kCFCoreFoundationVersionNumber < kCFCoreFoundationVersionNumber_iOS_8_0)
%init(iOS7Hook);
if (kCFCoreFoundationVersionNumber >= kCFCoreFoundationVersionNumber_iOS_8_0)
%init(iOS8Hook);

MSHookFunction((void *)&AudioServicesPlaySystemSound,
(void *)&replaced_AudioServicesPlaySystemSound,
(void **)&original_AudioServicesPlaySystemSound);
}

%new

%hook内部使用,给一个现有class添加一个新函数,功能与class_addMethod相同。注意,Objective-C的Category语法也可以给现有的class添加新函数。但区别在于category是静态的,class_addMethod是动态的

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

%c

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

(完)

参考

  1. 《iOS应用逆向工程(第2版)》
  2. Logos