美文网首页
iOS逆向-Logos语法(Ⅸ)

iOS逆向-Logos语法(Ⅸ)

作者: 鼬殿 | 来源:发表于2019-11-09 13:21 被阅读0次

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

相关文章

网友评论

      本文标题:iOS逆向-Logos语法(Ⅸ)

      本文链接:https://www.haomeiwen.com/subject/ghkwbctx.html