美文网首页
iOS逆向实操笔记6-用Theos Hook代码

iOS逆向实操笔记6-用Theos Hook代码

作者: 水煮杰尼龟 | 来源:发表于2020-12-26 09:13 被阅读0次

前面我们通过Cycript去修改app里的东西,这些修改只是暂时的,即如果退出界面再进来,还是老样子,这一篇就来实操,hook代码。

安装Theos
  • brew install ldid. 安装签名工具
    image.png
    遇上图问题,按照图中提示执行命令,设下权限,然后重新install
  • vim ~/.bash_profile 添加环境变量, 后面2个是后面用tweak时需要添加的
export THEOS=~/theos
export PATH=$THEOS/bin:$PATH

export THEOS_DEVICE_IP=127.0.0.1
export THEOS_DEVICE_PORT=10010
  • source ~/.bash_profile 更新一下
  • git clone --recursive https://github.com/theos/theos.git $THEOS 下载Theos
Tweak
  • 生成Tweak项目,通过nic.pl指令
    image.png
  • 选择15,继续往下


    image.png
Project Name : 项目名
Package Name [com.yourcompany.aqy_tweak]:项目 bundle id
Author/Maintainer Name: 作者名,回车就行
MobileSubstrate Bundle filte:调试的app bundle id (可以通过MJ的工具类获取)
后面就回车就行了

即会生成项目文件夹,然后就可以在Tweak.x 这个文件里做hook的事情了

image.png
Tweak用法
  • hook一个类,如Person,有一个方法-(void)goHome ,-(void)goSchool
%hook Person
-(void)goHome{
    %orig;//保留原app里的实现
    // %orig(nil); //参数
    NSLog(@"别想回家了");
}
%end
  • self调用类的方法
Tweak文件里 调用[self xxxx]时 ,需要申明一下
@interface Person
- (void)goSchool;
@end
%hook Person
-(void)goHome{
    [self goSchool];
}
%end
  • %c(Model) == NSClassFromString(@"Model")
  • %log 打印方法调用情况
  • %new 添加一个新方法
%new
-(void)swichOn{
       %log;
}
/// 加载动态库时调用
%ctor{
  
}
/// 程序退出时调用
%dtor{
  
}
  • 加载图片资源,[UIImage imageWithContentsOfFile:@""];
  • 将你需要加载进去的图片,放在Tweak项目如下路径
    image.png
    HJWeChatFiles 即是你放资源的文件夹,前面文件夹名称需要与图中一致。
  • 也可以放到Library/Caches
  • Tweak.x里 增加宏 #define HJFile(path) @"/Library/PreferenceLoader/Preferences/HJWeChatFiles/" #path
  • [UIImage imageWithContentsOfFile:HJFile(redbag)] 这样就可以拿到图片了。
  • 编写完Tweak代码后,需要执行执行以下命令安装到手机上
make //直接make package 也一样
make package  debug=0  // 生产包
make install //安装到手机上
简单的实践一下,不搞多复杂的分析,毕竟费脑子
image.png
image.png
如上面2张图,来自pp虾的登录界面,假设我看不惯历史记录上面的banner广告位,看不惯更多功能和即玩小游戏模块,想给它全部去掉,并且在这个tableView多加一组,放一个带switchcell
  • 首先通过Reveal查看一下这个界面,找出我要干掉的这几个东西
  • 查看可知,这个控制器是BDSUserHomeViewControllerbanner广告位是个cell->BDSUserHomeBannerCell ,更多功能模块也是个cell->BDSUserHomeFooterCell, 小游戏模块也是个cell->BDSUserGameTableViewCell,搞清楚了这就很简单了。
  • 在BDSUserHomeBannerCell中看到一个方法


    image.png
凭借多年的开发经验,很明显,这就是返回高度的,那我直接返回0不就行了。
image.png
更多功能的BDSUserHomeFooterCell里也找到这么一个高度的方法,同样返回0,顺便给hidden一下,可能高度没了,内容还在。
而在小游戏模块的BDSUserGameTableViewCell里没有发现这样的方法,没关系,看看它的数据源。
image.png
image.png
看到Model有2个数组,不管那么多,直接hook它俩的get方法,返回一个空数组,完事。
以上分析的Tweak代码如下:
@interface BDSUserHomeFooterCell
/// 调用了self.hidden, 申明一下
@property (nonatomic,assign)BOOL hidden;
@end
%hook BDSUserGameModel

-(NSArray *)gameItems{
    return @[];
}

-(NSArray *)remoteItems{
    return @[];
}

%end

%hook BDSUserHomeBannerCell
+ (double)cellHeightWithBanner:(id)arg1{

    return 0;
}

%end
%hook BDSUserHomeFooterCell
+ (double)cellHeight:(id)arg1{
    return 0;
}
- (void)configCellWithModels:(id)arg1{
    self.hidden = YES;
}
%end

我们装到手机上看看效果。

发现确实达到了我想要的结果


image.png
接下来还差一步,在末尾增加一个自己的cell,这里就要操作BDSUserHomeViewController了。

我们在TableView的代理里做点事情,直接贴代码了,里面有注释。

@interface BDSUserHomeViewController
///   [self numberOfSectionsInTableView:tableView]  得申明一下
- (long long)numberOfSectionsInTableView:(id)tableView;
@property(retain, nonatomic) UITableView *tableView;
@end
/// 图片路径 宏, 方便使用
#define HJFile(path) @"/Library/PreferenceLoader/Preferences/HJPPXFiles/" #path
/// 本地数据存储,记录switch 状态
#define HJDefaults [NSUserDefaults standardUserDefaults]
#define HJSwitchKey @"HJSwitchKey"

%hook BDSUserHomeViewController
- (long long)numberOfSectionsInTableView:(id)arg1{
        /// 在原有的section上+1
    return %orig+1;
}
- (long long)tableView:(id)tableView numberOfRowsInSection:(long long)section{

    if (section != [self numberOfSectionsInTableView:tableView]-1)
    {/// 原有的section 直接返回 原来的row
        return %orig;
    }
    ///新增的一组 根据switch状态展示1或2个cell
    BOOL isOn = [HJDefaults boolForKey:HJSwitchKey];

    return isOn?2:1;
}

- (id)tableView:(id)tableView cellForRowAtIndexPath:(id)indexPath{

    if ( [indexPath section] != [self numberOfSectionsInTableView:tableView]-1)
    {/// 原有的section  返回原来的cell
        return %orig;
    }else{
          /// 新增的一组 ,做一个判断 , ps:随便写点脏代码 
        if ([indexPath row] == 0)
        {
            BOOL isOn = [HJDefaults boolForKey:HJSwitchKey];
        UITableViewCell *cell = [[UITableViewCell alloc]
            initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"MyCell"];
                /// 根据switch 的状态 ,显示不同文本
         cell.textLabel.text = isOn?@"隐藏版本号":@"显示版本号";
         cell.backgroundColor = [UIColor whiteColor];
         cell.imageView.image = [UIImage imageWithContentsOfFile:HJFile(redbag)];
         UISwitch *swich = [[UISwitch alloc]init];
        cell.accessoryView = swich;
        cell.selectionStyle = UITableViewCellSelectionStyleNone;
        swich.on = isOn;
        [swich addTarget:self action:@selector(swich:) forControlEvents:UIControlEventValueChanged];
         return cell;
        }else{
            UITableViewCell *cell = [[UITableViewCell alloc]
            initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:@"MyCell2"];
         cell.textLabel.text = @"版本号";
         cell.detailTextLabel.text = [NSString stringWithFormat:@"v%@",[[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleShortVersionString"]];
         cell.backgroundColor = [UIColor whiteColor];
          cell.selectionStyle = UITableViewCellSelectionStyleNone;
         return cell;
        }

    }
}
- (double)tableView:(id)tableView heightForRowAtIndexPath:(id)indexPath{

    if ( [indexPath section] != [self numberOfSectionsInTableView:tableView]-1)
    {/// 原有的section  返回原来的高度
        return %orig;
    }else{ /// 新增随便给个44
        return 44;
    }   
}
- (double)tableView:(id)tableView heightForHeaderInSection:(long long)section{
    if ( section != [self numberOfSectionsInTableView:tableView]-1)
    {/// 原有的section header  返回原来的高度
        return %orig;
    }else{/// 新增给个3,给点间隔
        return 3;
    }   
}
/// 新增一个switch绑定的方法,点击并刷新这一组
%new
-(void)swich:(UISwitch *)swich{
    [HJDefaults setBool:swich.on forKey:HJSwitchKey];
    [HJDefaults synchronize];
    NSIndexSet *indexSet = [[NSIndexSet alloc] initWithIndex:[self numberOfSectionsInTableView:self.tableView]-1];
    [self.tableView reloadSections:indexSet withRowAnimation:UITableViewRowAnimationNone];
}


%end
OK,编写完毕,继续make package debug=0, make install 安装到手机上

来看看效果:


Dec-12-2020 18-12-52.gif

这样你越狱机上的pp虾,我的界面,就一直保持这个样子了。

相关文章

网友评论

      本文标题:iOS逆向实操笔记6-用Theos Hook代码

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