iOS逆向--通过monkey更改优酷设置页面

1,231 阅读3分钟

对页面进行针对性的调试

由于公司自己的项目页面不够复杂,所以我们拿到优酷砸完壳的ipa,拖到我们新创建的monkey工程里面,我们要实现将优酷的设置页面的tableView增加两项功能

然后运行,跳转到设置页面

我们可以打开debugView来拿到当前tabelView的内存地址,但是在控制台里面没法输出tableView的dataSource值,只能打开我们的cycript动态调试,登录进去,用指令打印出tableView的dataSource:

我们发现tableView的dataSource是SettingViewController,我们就去这个类里面去看看它的属性。

首先从ipa里面拿到可执行文件,然后用class-dump命令拿到所有头文件

class-dump -H Youkui4Phone -o ./headers/

再打开subLime工具,找到这个类

我们发现这个类里面有个tableView和一个_datasource,我们猜测这个就是数据源,我们通过Cycript来看一下这个数据源

我们发现是一个数组,数组里元素个数跟页面的分区个数相同,,并且元素是一个字典,字典里面有每行的数据,数据类型是SettingModel,我们再找一下SettingModel类,看看结构

我们看到两个关键属性就是title和subTitle,我们可以先试着hook代理类SettingViewController,给数据源添加数据,并且我们也看到它实现了tableView的代理方法

我们先给他增加一个区,所以只需要hook它的numberOfSectionsInTableView方法就行了,不过我们要获取到数据源datasource,如果直接通过self。datasource是获取不到的,这时候就需要Logos的函数MSHookIvar()

// See http://iphonedevwiki.net/index.php/Logos

#import <UIKit/UIKit.h>
#define FYDefaults  [NSUserDefaults standardUserDefaults]
#define FYSwitchUserDefaultsKey @"FYSwitchUserDefaultsKey"

@interface SettingViewController
- (long long)numberOfSectionsInTableView:(id)arg1;
@end


%hook SettingViewController

%new
-(void)switchChangeAction:(UISwitch *)switchView{
    [FYDefaults setBool:switchView.isOn forKey:FYSwitchUserDefaultsKey];
    [FYDefaults synchronize];
    [MSHookIvar <UITableView *>(self,"_tabview") reloadData];
}


//每组多少行
- (long long)tableView:(UITableView *)tableView numberOfRowsInSection:(long long)section{
    NSLog(@"fy_numberOfRowsInSection:");
    //定位设置界面,并且是最后一个
    if(section == [self numberOfSectionsInTableView:tableView]-1){
        return 1;
    }
    else{
        return %orig;
    }
}

//返回高度
- (double)tableView:
(UITableView *)tableView heightForRowAtIndexPath:(id)indexPath{
    NSLog(@"fy_heightForRowAtIndexPath:");
    //定位设置界面,并且是最后一个
    if([indexPath section] ==[self numberOfSectionsInTableView:tableView]-1){
        return 44;
    }
    else{
        return %orig;
    }
}


//每一个Cell
- (id)tableView:(UITableView *)tableView cellForRowAtIndexPath:(id)indexPath{
    NSLog(@"fy_cellForRowAtIndexPath:");
    //定位设置界面,并且是最后一组
    if([indexPath section] == [self numberOfSectionsInTableView:tableView]-1){
        UITableViewCell * cell = nil;
        if([indexPath row] == 0){
            static NSString *swCell = @"SwCellIdentifier";
            cell = [tableView dequeueReusableCellWithIdentifier:swCell];
            if(!cell){
                cell = [[UITableViewCell alloc] initWithStyle:(UITableViewCellStyleDefault) reuseIdentifier:nil];
            }
            cell.textLabel.text = @"免广告";
            // 免广告开关
            UISwitch *switchView = [[UISwitch alloc] init];
            switchView.on = [FYDefaults boolForKey:FYSwitchUserDefaultsKey];
            [switchView addTarget:self action:@selector(switchChangeAction:) forControlEvents:(UIControlEventValueChanged)];
            cell.accessoryView = switchView;
            cell.imageView.image = [UIImage imageNamed:([FYDefaults boolForKey:FYSwitchUserDefaultsKey] == 1) ? @"unlocked" : @"locked"];
        }
        cell.backgroundColor = [UIColor whiteColor];
        return cell;

    }else{
        return %orig;
    }
}

%end

运行后,

跟之前的对比:

我们发现最后一个分区,已经被我们改过来了

注意点

  • 1、在Logos里面是不能使用项目中自定义的类创建对象,只能通过运行时形式调用,因为Logos是通过framework形式进行注入的,而framework加载比类加载的快,所以在framework里面是无法调用到类的,所以在framework里面只能调用动态库或者静态库里面的类
  • 2、在Logos里面调用类的属性时候需要在xm文件里通过@interface声明一下
  • 3、在修改页面时候,可能一个页面在多个地方使用,这个时候就需要进行判断