Logos语法其实是CydiaSubstruct框架提供的一组宏定义。便于开发者使用宏进行HOOK操作。语法简单,功能强大且稳定。
1. 新建一个测试工程
#import "ViewController.h"
@interface ViewController ()
@property (weak, nonatomic) IBOutlet UITextField *accountTextfield;
@property (weak, nonatomic) IBOutlet UITextField *passTextfield;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
}
- (IBAction)loginBtnClicked:(id)sender {
if ([self.accountTextfield.text isEqualToString:@"njf"] && [self.passTextfield.text isEqualToString:@"123456"]) {
NSLog(@"登录成功");
}
}
@end
2. 将测试工程的.app文件,放到MonkeyDeviOS逆向-反Hook防护(VI)里有介绍,进行重签名,在视图模式下,我们可以获取到按钮的点击方法和调用者
(lldb) pvc
<ViewController 0x119d35ba0>, state: appeared, view: <UIView 0x119e18400>
(lldb) methods 0x119d35ba0
<ViewController: 0x119d35ba0>:
in ViewController:
Class Methods:
+ (void) classMethod; (0x102b56bf0)
Properties:
@property (weak, nonatomic) UITextField* accountTextField; (@synthesize accountTextField = _accountTextField;)
@property (weak, nonatomic) UITextField* passTextField; (@synthesize passTextField = _passTextField;)
Instance Methods:
- (void) setNewProperty:(id)arg1; (0x102b56cd8)
- (id) newProperty; (0x102b56ca4)
- (void) instanceMethod:(id)arg1; (0x102b56c1c)
- (id) accountTextField; (0x102a95de8)
- (id) passTextField; (0x102a95e6c)
- (void) setAccountTextField:(id)arg1; (0x102a95e1c)
- (void) setPassTextField:(id)arg1; (0x102a95ea0)
- (void) loginBtnClicked:(id)arg1; (0x102b56960)
- (void) .cxx_destruct; (0x102a95ef0)
- (void) viewDidLoad; (0x102a95c00)
(UIViewController ...)
(lldb) search UIButton
<UIButton: 0x119e18560; frame = (149 377; 96 30); opaque = NO; autoresize = RM+BM; layer = <CALayer: 0x281f199a0>>
<FLEXToolbarItem: 0x119d0f580; baseClass = UIButton; frame = (183.333 0; 76.6667 44); opaque = NO; layer = <CALayer: 0x281f31b20>>
<FLEXToolbarItem: 0x119d10c00; baseClass = UIButton; frame = (336.667 0; 77.3333 44); opaque = NO; layer = <CALayer: 0x281f326e0>>
<FLEXToolbarItem: 0x119d0cdc0; baseClass = UIButton; frame = (106.667 0; 76.6667 44); opaque = NO; layer = <CALayer: 0x281f31800>>
<TUICandidateArrowButton: 0x119d4e9f0; baseClass = UIButton; frame = (369 0; 45 45); hidden = YES; opaque = NO; tintColor = UIExtendedGrayColorSpace 0 1; layer = <CALayer: 0x281f6b960>>
<FLEXToolbarItem: 0x119d100c0; baseClass = UIButton; frame = (260 0; 76.6667 44); opaque = NO; layer = <CALayer: 0x281f32060>>
<FLEXToolbarItem: 0x119d05ac0; baseClass = UIButton; frame = (30 0; 76.6667 44); opaque = NO; layer = <CALayer: 0x281f30720>>
(lldb) flicker 0x119e18560
(lldb) pactions 0x119e18560
<ViewController: 0x119d35ba0>: loginBtnClicked:
3. LogosTestDylib.xm文件中编写Logos代码,并修改文件类型,代码高亮显示
// .x 说明源文件支持Logos和C语法
// .xm 说明源文件支持Logos和 c/c++语法
#import <UIKit/UIKit.h>
@interface ViewController: UIViewController
+ (void)classMethod;
-(void)instanceMethod:(NSString *)output;
@property (nonatomic, copy) NSString* newProperty;
@end
%group iOS12
//该指令用于将%hook分组,便于代码管理及按条件初始化分组,必须以%end结尾。一个%group可以包含多个%hook,所有不属于某个自定义group的%hook会被隐式归类到%group_ungrouped中。
%hook ViewController
- (void)loginBtnClicked:(id)sender {
%orig;//执行被hook的函数的原始代码
%log;//将函数的类名、参数等信息写入syslog,可以%log([(),…..])的格式追加其他打印信息。
NSLog(@"Hook!Group1成功");
[%c(ViewController) classMethod];//%c([+|-]Class) 该指令的作用等同于objc_getClass或NSClassFromString,即动态获取一个类的定义,在%hook或%ctor内使用 。
self.newProperty = @"newProperty";
NSLog(@"%@",self.newProperty);
[self instanceMethod: @"output"];
//获取属性变量textField
UITextField *textField = MSHookIvar<UITextField*>(self,"_accountTextField");
NSLog(@"%@",textField);
}
%new
//在%hook内部使用,给一个现有class添加新函数,功能与class_addMethod相同.
+ (void)classMethod{
NSLog(@"add classMethod");
}
%new
-(void)instanceMethod:(NSString *)output{
NSLog(@"instanceMethod : %@", output);
}
%new
- (id)newProperty {
return objc_getAssociatedObject(self, @selector(newProperty));
}
%new
- (void)setNewProperty:(id)value {
objc_setAssociatedObject(self, @selector(newProperty), value, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
%end //end hook
%end //end group iOS12
%group iOS10
%hook ViewController
- (void)loginBtnClicked:(id)sender {
NSLog(@"Hook!Group2成功");
}
%end //end hook
%end //end group iOS10
//构造函数%ctor一般可以用来初始化%group
%ctor{
NSString * v = [UIDevice currentDevice].systemVersion;
if(v.doubleValue > 11.0){
%init(iOS12);
//该指令用于初始化某个%group,必须在%hook或%ctor内调用;如果带参数,则初始化指定的group,如果不带参数,则初始化_ungrouped.
}else{
%init(iOS10);
}
}
MonkeyDev已经帮我们注入了libsubstrate.dylib,所以可以编写logos代码,更多用法可以参照官方文档
修改微信的设置界面
1. 在MonkeyDev中重签名6.7.4版本的微信。想修改设置界面,就的找到设置界面tableview的数据源的代理
(lldb) po 0x28202c4e0
delegate[0x283715e40], class[MMTableViewInfo]
2. 把微信生成的头文件夹拖到Sublime Text工具,Command+shift+f然后在find栏中输入@interface MMTableViewInfo
3. Cycript调试
cy# #0x28202c4e0
#"delegate[0x283715e40], class[MMTableViewInfo]"
cy# #0x283715e40->_tableView
#"<MMTableView: 0x109aa3000; baseClass = UITableView; frame = (0 0; 414 736); clipsToBounds = YES; gestureRecognizers = <NSArray: 0x28202c9c0>; layer = <CALayer: 0x282d344e0>; contentOffset: {0, -64}; contentSize: {414, 649}; adjustedContentInset: {64, 0, 0, 0}; dataSource: delegate[0x283715e40], class[MMTableViewInfo]>"
cy# #0x283715e40->_arrSections
@[#"<MMTableViewSectionInfo: 0x2809d6100>",#"<MMTableViewSectionInfo: 0x2809d6400>",#"<MMTableViewSectionInfo: 0x2809d63a0>",#"<MMTableViewSectionInfo: 0x2809d6340>",#"<MMTableViewSectionInfo: 0x2809d6280>",#"<MMTableViewSectionInfo: 0x2809d62e0>"]
cy# #0x283715e40->_tableView.nextResponder
#"<UIView: 0x10a0ad160; frame = (0 0; 414 736); autoresize = W+H; layer = <CALayer: 0x282d34160>>"
cy# #0x283715e40->_tableView.nextResponder.nextResponder
#"<NewSettingViewController: 0x10ac38000>"
4. 代码部分
#import <UIKit/UIKit.h>
#define HKDefaults [NSUserDefaults standardUserDefaults]
#define HKSWITCHKEY @"HKSWITCHKEY"
#define HKTIMEKEY @"HKTIMEKEY"
//关于界面
@interface MMTableViewInfo
- (long long)numberOfSectionsInTableView:(id)arg1;
@end
@interface NewSettingViewController:UIViewController
@end
%hook MMTableViewInfo
%new
- (void)textFieldDidChangeValue:(NSNotification *)notification{
UITextField *sender = (UITextField *)[notification object];
[HKDefaults setValue:sender.text forKey:HKTIMEKEY];
[HKDefaults synchronize];
}
%new
-(void)switchChang:(UISwitch *)switchView{
[HKDefaults setBool:switchView.isOn forKey:HKSWITCHKEY];
[HKDefaults synchronize];
[MSHookIvar <UITableView *>(self,"_tableView") reloadData];
}
- (void)scrollViewWillBeginDragging:(id)arg1{
%orig;
[MSHookIvar <UITableView *>(self,"_tableView") endEditing:YES];
}
//返回高度
- (double)tableView:
(UITableView *)tableView heightForRowAtIndexPath:(id)indexPath{
//定位设置界面,并且是最后一组
if([tableView.nextResponder.nextResponder isKindOfClass:%c(NewSettingViewController)]
&& [indexPath section] ==[self numberOfSectionsInTableView:tableView]-1){
return 44;
}else{
return %orig;
}
}
//每一个Cell
- (id)tableView:(UITableView *)tableView cellForRowAtIndexPath:(id)indexPath{
//定位设置界面,并且是最后一组
if([tableView.nextResponder.nextResponder isKindOfClass:%c(NewSettingViewController)]
&& [indexPath section] ==[self numberOfSectionsInTableView:tableView]-1){
UITableViewCell * cell = nil;
if([indexPath row] == 0){
static NSString * swCell = @"SWCELL";
cell = [tableView dequeueReusableCellWithIdentifier:swCell];
if(!cell){
cell = [[UITableViewCell alloc] initWithStyle:(UITableViewCellStyleDefault) reuseIdentifier:nil];
}
cell.textLabel.text = @"自动抢红包";
//抢红包开关!!
UISwitch * switchView = [[UISwitch alloc] init];
switchView.on = [HKDefaults boolForKey:HKSWITCHKEY];
[switchView addTarget:self action:@selector(switchChang:) forControlEvents:(UIControlEventValueChanged)];
cell.accessoryView = switchView;
cell.imageView.image = [UIImage imageNamed:([HKDefaults boolForKey:HKSWITCHKEY] == 1) ? @"unlocked" : @"locked"];
}else if([indexPath row] == 1){
static NSString * waitCell = @"waitCell";
cell = [tableView dequeueReusableCellWithIdentifier:waitCell];
if(!cell){
cell = [[UITableViewCell alloc] initWithStyle:(UITableViewCellStyleDefault) reuseIdentifier:nil];
}
cell.textLabel.text = @"等待时间(秒)";
UITextField * textField = [[UITextField alloc] initWithFrame:CGRectMake(0, 0, 150, 40)];
//监听键盘输入
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(textFieldDidChangeValue:) name:UITextFieldTextDidChangeNotification object:textField];
textField.text = [HKDefaults valueForKey:HKTIMEKEY];
textField.borderStyle = UITextBorderStyleRoundedRect;
cell.accessoryView = textField;
cell.imageView.image = [UIImage imageNamed:@"clock"];
}
cell.backgroundColor = [UIColor whiteColor];
return cell;
}else{
return %orig;
}
}
//每组多少行
- (long long)tableView:(UITableView *)tableView numberOfRowsInSection:(long long)section{
//定位设置界面,并且是最后一个
if([tableView.nextResponder.nextResponder isKindOfClass:%c(NewSettingViewController)]
&& section ==[self numberOfSectionsInTableView:tableView]-1){
return 2;
}else{
return %orig;
}
}
//多少组
- (long long)numberOfSectionsInTableView:(id)arg1{
UITableView * tableView = MSHookIvar <UITableView *>(self,"_tableView");
if([tableView.nextResponder.nextResponder isKindOfClass:%c(NewSettingViewController)]){//定位设置界面
//在原来基础上多搞一组
return %orig+1;
}else{
return %orig;
}
}
%end
%hook NewSettingViewController
%new
-(void)keyboardWillShow:(NSNotification*)note{
UIView * view = self.view;
CGRect keyBoardRect=[note.userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue];
view.frame = CGRectMake(0, -keyBoardRect.size.height, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height );
}
%new
-(void)keyboardWillHide:(NSNotification*)note{
UIView * view = self.view;
view.frame = CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height);
}
- (void)viewDidLoad{
%orig;
//监听textField弹出和消失
[[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
[[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];
}
%end
网友评论