几年前,我在用某浏览器看小说的时候,那会就被那个广告折磨的不要不要的,想着找学(po)习(jie)版本,但是逛了一圈没有找到。那咋办,自己动手呗~~然而,那会太菜了,分析了好久都没研究出来怎么弄。。。
过了几年,我没有变得更厉害,但是我想再试试,于是有了本文。。
> ps:处于学(hai)习(pa)的目的,本文只会给出核心的思路,不是那种一步步的保姆级教程,看的师傅要注意了~
Reveal 分析一下开屏广告,发现跟 MttSplashWindow
有关系
用class-dump
导出类、方法和属性,并生成相应的头文件
class-dump -H mttlite.app -o headers
发现了一个方法canShowSplash
很可疑:
MonkeyDev 直接hook之,让其返回false
so easy~~
在看小说的时候,想要无广告,就得开会员
这里提取到关键词“悦读卡”
用vscode,打开刚刚的MonkeyDev项目的,下图的路径
开搜
可以看到大部分跟 mttlite.app/res/rn/novelReader
有关,盲猜这玩意就是我们看小说的页面
> 其实测试很简单,随便找个关键词改改,编译运行一下,就知道就是这里了
那接下来的操作其实很简单了,分析一下js代码。我从2.ios.jsbundle
的第一个地方悦读卡已生效
出发
往上看看,可以看到isVipUser
和expireTime
的变量
秉承着大胆猜测小心验证的原则,我把2.ios.jsbundle
这个文件中,所有涉及这两个变量的地方,都改成如下:
{
isVipUser: 1,
expireTime: new Date('2099-01-01T00:00:00Z').getTime(),
}
我一共改了三处,第一处:
第二处:
第三处:
改完,保存文件,MonkeyDev项目重新编译到手机上,框框刷小说,没广告了,稳如狗~
从 clickDownloadButton
入手
简单分析一下这个函数
那么修改思路也很清晰了,直接把原来的case 22
注释掉,放到case 12
上面,如下:
改完,保存文件,MonkeyDev项目重新编译到手机上,点击下载,也没有广告了,稳!
如题,正当我以为结束的时候,开开心心看小说的时候,好家伙,没过两分钟,广告又出来了。。。
思考一件事情,文件是 jsbundle,然后还能动态更新,百度一下,发现这篇文章:https://blog.csdn.net/xu_song/article/details/53286996
开搞,上frida
frida-trace -U -m "*[* *BundleVersion*]" -f com.example.QQLiu
一直刷小说,直到发现出现了广告,即更新了
hook之,发现还是不行
直接hook所有跟version有关的
frida-trace -U -m "*[* *Version*]" -f com.example.QQLiu
看一下头文件,感觉都挺可疑的
看看是哪个updateRes
方法
frida-trace -U -m "*[* *updateRes*]" -M "-[UIImageView _updateResolvedImage]" -M " -[_UINavigationBarLargeTitleViewLayout updateRestingTitleHeight]" -f com.example.QQLiu
掏空它
// See http://iphonedevwiki.net/index.php/Logos
#import
@interface MttSplashWindow : UIWindow
+ (_Bool)canShowSplash;
@end
%hook MttSplashWindow
+ (_Bool)canShowSplash{
%orig;
NSLog(@"[+] hook: canShowSplash 返回false");
return false;
}
%end
%hook ResHubLocalResManager
- (void)updateResWithConfig:(id)arg1 taskId:(id)arg2 mode:(id)arg3{
NSLog(@"[+] hook: updateResWithConfig 掏空");
}
%end
掏空之后,书架显示不了了,得看看这三个参数都是啥,方向没问题,关键是不能全hook,得根据参数判断来hook
xcode打个断点, 查看参数,发现 _sourceRelativeLocalPath
有点可疑
%hook ResHubLocalResManager
- (void)updateResWithConfig:(id)arg1 taskId:(id)arg2 mode:(id)arg3{
NSString *sourceRelativeLocalPath = [arg1 valueForKey:@"_sourceRelativeLocalPath"];
NSLog(@"[+] _sourceRelativeLocalPath: %@",sourceRelativeLocalPath);
%orig;
}
%end
猜测novelReader_1337.zip
有关系,只干掉它试试,因为vip的判断都是这个novelReader关键词
最新的版本
15.7.0.6057
,这里已经变成novelReader_1519.zip
了
%hook ResHubLocalResManager
- (void)updateResWithConfig:(id)arg1 taskId:(id)arg2 mode:(id)arg3{
// %orig;
NSString *sourceRelativeLocalPath = [arg1 valueForKey:@"_sourceRelativeLocalPath"];
if ([sourceRelativeLocalPath containsString:@"novelReader"]) {
NSLog(@"[+] hook: updateResWithConfig 掏空");
NSLog(@"[+] _sourceRelativeLocalPath: %@", sourceRelativeLocalPath);
} else {
%orig;
}
}
%end
编译运行,终于稳了,不容易啊。。
// See http://iphonedevwiki.net/index.php/Logos
#import
@interface MttSplashWindow : UIWindow
+ (_Bool)canShowSplash;
@end
%hook MttSplashWindow
+ (_Bool)canShowSplash{
%orig;
NSLog(@"[+] hook: canShowSplash 返回false");
return false;
}
%end
%hook ResHubLocalResManager
- (void)updateResWithConfig:(id)arg1 taskId:(id)arg2 mode:(id)arg3{
// %orig;
NSString *sourceRelativeLocalPath = [arg1 valueForKey:@"_sourceRelativeLocalPath"];
if ([sourceRelativeLocalPath containsString:@"novelReader"]) {
NSLog(@"[+] hook: updateResWithConfig 掏空");
NSLog(@"[+] _sourceRelativeLocalPath: %@", sourceRelativeLocalPath);
} else {
%orig;
}
}
%end
还是那句话,不会提供成品,仅供学习使用!!!支持正版,从我做起,仅供学习!!
2 篇文章
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!