本文仅作逆向学习交流,如有侵权,请联系我删稿。
今日头条:你关心的,才是头条!
哈哈,不得不说头条还是很强大的,根据你日常点击资讯,推送符合你口味的新闻,视频。还是蛮强大的。
那好吧,作为我的第一个逆向项目,拿来试试手还是挺不错的。毕竟我也是非常喜欢头条的产品的。?
需求
- 去除启动页广告
- 去除列表推荐广告
- 去除评论顶部推荐广告
- 去除烦人的置顶(额,其实我本次逆向,就是为了去除这个置顶的)
好了,需求有了,那就着手准备工具吧。
工具及软件
- 越狱的手机一部
- Mac开发环境
- Mac上脱壳软件:dumpdecrypted.dylib
- Mac上导出头文件软件:class-dump
- 手机上抓包软件:Thor
- 电脑上插件开发:Theos
- 电脑和手机上:Reveal
- 文本编辑 Sublime Text
逆向过程
前期准备
既然逆向开发,那肯定先得给原生的App脱壳,导出头文件,这些基本的操作就不在本文详述。感兴趣的可以网上自行搜索学习。利用Thor先抓一个今日头条的数据包,一般来说直接看返回值,json格式的,然后复制到网页上解析。如下
去除启动页广告
用Reveal分析app布局,由于广告闪屏跳转太快,未能捕捉到完整的页面,不过没关系。,通过最底层的红色view,我们可以找到这是一个由TTAdSplashControllerView展示的视图。
我们在头文件中看看TTAdSplashControllerView有什么方法
可以看到这里有他的初始化方法,我们只要hook掉这个方法,当前的广告视图就不会初始化,也不会显示。因此我们可以这样写
%hook TTAdSplashControllerView
/*去除启动页广告*/
- (void)setModel:(NSArray *)model{
}
- (id)initWithFrame:(struct CGRect)arg1 model:(id)arg2{
return nil;
}
%end
%hook TTAdSplashView /*这个是广告视图的子视图,我们直接hook掉他们的显示方法,这样他们也不会再显示*/
- (void)showADVideoView{};
- (void)showADImage{};
%end
到此,我们直接编译安装到手机看看,测试效果,果然去除了启动页的广告。
去除评论广告
就是每篇文章评论的顶部。通过Reveal分析找到它的类是ExploreDetailADContainerView。
+ (void)trackAppHideIfExists:(id)arg1;
@property(nonatomic) double referHeight; // @synthesize referHeight=_referHeight;
@property(retain, nonatomic) NSMutableDictionary *showEvents; // @synthesize showEvents=_showEvents;
@property(retain, nonatomic) NSMutableDictionary *adViewFrames; // @synthesize adViewFrames=_adViewFrames;
@property(retain, nonatomic) NSMutableArray *adViews; // @synthesize adViews=_adViews;
@property(retain, nonatomic) TTAdDetailViewModel *viewModel; // @synthesize viewModel=_viewModel;
@property(nonatomic) __weak id <TTAdDetailContainerViewDelegate> delegate; // @synthesize delegate=_delegate;
@property(nonatomic) _Bool isVideoAd; // @synthesize isVideoAd=_isVideoAd;
@property(copy, nonatomic) NSArray *adModels; // @synthesize adModels=_adModels;
可以清楚的看到一个属性TTAdDetailViewModel *viewModel;,我们hook它的set方法。%hook ExploreDetailADContainerView
/*去除顶部广告*/
- (void)setAdModels:(NSArray *)adModels{
}
%end
去除置顶消息和列表广告
其实通过分析得知,今日头条的横向列表,是由collectionview构造的。比如上面的关注、推荐、军事等。采用collectionView他可以循环利用cell,减少内存支出。每个collectionView的Cell又是一个自定义的tableview,这样就解决了竖向列表循环复用,节省内存开支。
但是有一个题外话,我通过打印得出当前的tableview共有三个section。但是我点击列表中的cell,打印出当前的section都是最后一个。没找到前两个section去哪里了。这也是我此次逆向困惑的地方。如果有大佬知道,希望告知下小弟,不胜感激。
利用cycript打印出当前tableview的dataSource,为ExploreMixedListBaseView,查看它的头文件,我从属性找了一圈也没找到数组之类的。那他肯定是封装成模型,或者有一个管理类来管理。然后就看到了
@property(retain, nonatomic) ExploreFetchListManager *fetchListManager;
接着我们在查看ExploreFetchListManager的头文件,就可以看到他有一个NSArray的属性,功夫不负有心人啊。@property(retain, nonatomic) NSArray *items;
接着我们修改插件代码,这样写,打印下这个数组看看,到底装的是啥%hook ExploreFetchListManager
- (void)setItems:(NSArray *)items{
NSLog(@"****1items = %@",items);
%orig;
}
%end
利用xcode的控制台,看看输出的日志,果不其然
这样,咱们就找到数据的模型ExploreOrderedData了。我们通过之前抓包,找到对应的关键词去过滤,筛选当前的model,即可过滤广告了。
通过查看抓包的的json数据,我们不难得出当stick_label为“置顶”时,就是某某某数据。过滤,删了。?
过滤的代码可以这么写
%hook ExploreFetchListManager
- (void)setItems:(NSArray *)items{
NSMutableArray *temArray = [NSMutableArray new];
NSMutableArray *adArray = [NSMutableArray new];
NSLog(@"****1items = %@",items);
if(items.count > 0){
for (ExploreOrderedData * model in items) {
[temArray addObject: model];
}
}
[temArray enumerateObjectsUsingBlock:^(ExploreOrderedData * model, NSUInteger idx, BOOL * _Nonnull stop) {
if([[model stickLabel] isEqualToString:@"置顶"] || [[model adIDStr] length] > 0){
[adArray addObject: model];
}
}];
if(adArray.count > 0){
[temArray removeObjectsInArray:adArray];
}
items = [temArray mutableCopy];
%orig;
}
%end
这样,基本上,几个主要的广告,都可以去掉了,完结,撒花!
当然,这个app更适合头条卡,工行e卡等互联网资费卡,因为这个不存在跳转第三方广告浪费流量了啊,嘿嘿
安装使用
- 未越狱的手机等我下次打包安装包吧
- 越狱的手机,先把deb导入到手机的某个目录,然后直接使用Filza 安装 deb即可
你的评论可以一针见血
有安卓去广告的吗?
我不做Android开发??
大佬求带逆向
才疏学浅,带不动,哈哈