HOOK,中文译为“挂钩”或“钩子”。在iOS逆向中是指改变程序运行流程的一种技术。通过hook可以让别人的程序执行自己所写的代码。在逆向中经常使用这种技术。所以在学习过程中,我们重点要了解其原理,这样能够对恶意代码进行有效的防护。
Method Swizzle
利用OC的Runtime特性,动态改变SEL(方法编号)和IMP(方法实现)的对应关系,达到OC方法调用流程改变的目的。主要用于OC方法。
fishhook
它是Facebook提供的一个动态修改链接mach-O文件的工具。利用MachO文件加载原理,通过修改懒加载和非懒加载两个表的指针达到C函数HOOK的目的。
Cydia Substrate
Cydia Substrate 原名为 Mobile Substrate ,它的主要作用是针对OC方法、C函数以及函数地址进行HOOK操作。当然它并不是仅仅针对iOS而设计的,安卓一样可以用。官方地址:http://www.cydiasubstrate.com/
1.logos获取用户信息
%hook HMIDAppTokenItem
//获取用户appToken
-(NSString *)appToken{
id s=%orig;
[xddCode toeknSet:s];
return s;//s __NSCFString * "lsdfs324k23hkh32l5h35h63k4h5"
}
// 获取用户ID
-(NSString *)userId{
id s=%orig;
[xddCode userIDSet:s];
return s;//s __NSCFString * "107xxxxxx70"
}
%end
2.logos界面添加图标,文字,点击事件
//个人设置页面
%hook ProfileViewController
- (void)viewDidLoad{
%orig;
UILabel *nameLabel = [[UILabel alloc]initWithFrame:CGRectMake(10, 60, 80, 37)];
nameLabel.font = [UIFont systemFontOfSize:15];
nameLabel.text = @"您APP已被hook";
nameLabel.backgroundColor = [UIColor clearColor];
nameLabel.textAlignment = NSTextAlignmentLeft;
nameLabel.numberOfLines = 2;
//用于设置UILabel中文本的行数
[self.view addSubview:nameLabel];
// 移动圆圆 界面位置信息
CGRect rect_screen = [[UIScreen mainScreen]bounds];
CGSize size_screen = rect_screen.size;
int height = size_screen.height;
int width = size_screen.width;
// 移动圆圆 初始化
BallUIView *baView = [[BallUIView alloc] initWithFrame:CGRectMake(width-80, height/2-200, 50, 50)];
baView.backgroundColor = [UIColor whiteColor];
baView.layer.cornerRadius = 25;
baView.layer.masksToBounds = YES;
// 移动圆圆 小圆球图标
UIImageView *imgViewM = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"[email protected]"]];
imgViewM.autoresizingMask = UIViewAutoresizingFlexibleWidth;
imgViewM.frame = CGRectMake(0, 0, 50, 50);
[baView insertSubview:imgViewM atIndex:0];
__weak typeof(self) weakSelf = self;
//按钮点击事件
baView.btnClick = ^(UIButton *sender) {
NSLog(@"btn.btnClick ~");
WebUrlViewController * xddweb = [[WebUrlViewController alloc] init];
[xddweb setUrl:@"http://www.baidu.com"];//页面打开网页
[weakSelf.navigationController pushViewController:xddweb animated:YES];
};
[self.view addSubview:baView];//显示到界面
}
%end
//头文件 ProfileViewController 为了编译通过
@interface ProfileViewController: UIViewController
{
}
@property (nonatomic, copy) NSString* newProperty;
+ (void)classMethod;
@end
Method Swizzle
新建Frameworks项目 名称:frameworkxdds 会出现frameworkxdds.h 不用理会
反手就 新建 frameworkMain 文件 NSObject
↓得到 两个文件↓
frameworkMain.m
frameworkMain.h
frameworkMain.m
添加 +(void)load
@implementation frameworkMain
//我的界面加载完毕hook
IMP (* old_pviewDidLoad)(id self, SEL cmd);
//获取返回 sting tokrn
id (* old_appToken)(id self, SEL cmd);
//获取返回 sting tokrn
id (* old_userId)(id self, SEL cmd);
+(void)load{
[self addimg];//添加图标
[self getUserinfo];//hooh 用户信息
}
Frameworks hook HMIDAppTokenItem 类的 appToken方法
Frameworks hook HMIDAppTokenItem 类的 userId方法
//获取用户信息
+(void)getUserinfo {
//HMIDAppTokenItem
Method * appToken = class_getInstanceMethod(NSClassFromString(@"HMIDAppTokenItem"), @selector(appToken));
//获取原方法保存
old_appToken = method_getImplementation(appToken);
//重新赋值IMP方法
method_setImplementation(appToken, (IMP)my_appToken);
//============2222=============
Method * userId = class_getInstanceMethod(NSClassFromString(@"HMIDAppTokenItem"), @selector(userId));
//获取原方法保存
old_userId = method_getImplementation(userId);
//重新赋值IMP方法
method_setImplementation(userId, (IMP)my_userId);
}
Frameworks hook HMIDAppTokenItem 类的 appToken 方法执行流程控制
Frameworks hook HMIDAppTokenItem 类的 userId 方法执行流程控制
id my_appToken(id self,SEL sel){
//执行原方法
NSString*tk = old_appToken(self, sel);
[xddCode toeknSet:tk];//存储token
return tk;
}
id my_userId(id self,SEL sel){
//执行原方法
NSString*uid = old_userId(self, sel);
[xddCode userIDSet:uid];//存储uuid
return uid;
}
Frameworks hook ProfileViewController 类的 viewDidLoad 方法
//添加图标
+(void)addimg {
//ProfileViewController
Method * viewDidLoad = class_getInstanceMethod(NSClassFromString(@"ProfileViewController"), @selector(viewDidLoad));
//获取原方法保存
old_pviewDidLoad = method_getImplementation(viewDidLoad);
//重新赋值IMP方法
method_setImplementation(viewDidLoad, (IMP)my_pviewDidLoad);
}
void my_pviewDidLoad(id self,SEL sel) {
ProfileViewController*v = self;
//执行原方法
old_pviewDidLoad(self, sel);
UILabel *nameLabel = [[UILabel alloc]initWithFrame:CGRectMake(10, 120, 80, 37)];
nameLabel.font = [UIFont systemFontOfSize:15];
nameLabel.text = @"您已hook成功";
nameLabel.backgroundColor = [UIColor clearColor];
nameLabel.textAlignment = NSTextAlignmentLeft;
nameLabel.numberOfLines = 2;
[v.view addSubview:nameLabel];
//坐标初始化
CGRect rect_screen = [[UIScreen mainScreen]bounds];
CGSize size_screen = rect_screen.size;
int height = size_screen.height;
int width = size_screen.width;
// 移动圆圆
BallUIView *baView = [[BallUIView alloc] initWithFrame:CGRectMake(width-80, height/2-200, 50, 50)];
baView.backgroundColor = [UIColor whiteColor];
baView.layer.cornerRadius = 25;
baView.layer.masksToBounds = YES;
//小圆球 图标
UIImageView *imgViewM = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"[email protected]"]];
imgViewM.autoresizingMask = UIViewAutoresizingFlexibleWidth;
imgViewM.frame = CGRectMake(0, 0, 50, 50);
[baView insertSubview:imgViewM atIndex:0];
__weak typeof(self) weakSelf = v;
baView.btnClick = ^(UIButton *sender) {
NSLog(@"btn.btnClick ~");
WebUrlViewController * xddweb = [[WebUrlViewController alloc] init];
[xddweb setUrl:@"http://www.baidu.com"];//打开网页
[v.navigationController pushViewController:xddweb animated:YES];
};
[v.view addSubview:baView];
}
附工程图