某博国际版3.1.6去广告

前些天iPhoneSE正式退役,换了一台安卓机做主力机,三星 A60 元气版,刷微博的时候总是刷到非常低俗恶心的广告,网上经常看到去广告版的微博,全都是被加固过,怕被人暗算,不敢用,周末就自己搞了一下。之前微博平白无故把老子的号给封了,这是第二篇杠微博的文章。

额外多说几句,本文首发于2019.6.11,网上的去广告版有些被加固过,不知道作者有没有夹杂私货,我是不敢用,不建议使用。

一、简介

贴几张图,让你们看看广告是多么恶心,主要是我懒得截图,网友截的图:

如果是好看点的广告可以忍,但这个广告真滴是低俗,本文从技术上讲如何一步一步去掉广告。

版本:3.1.6

MD5 (weico.apk) = a3779d34ea636e7f3469b0e56b788c94

github 地址,可以看每次commit的区别:https://github.com/LeadroyaL/weico316

直接下载:  https://github.com/LeadroyaL/weico316-no-ads/raw/master/weico-patch.apk

二、安卓重打包技术的简介

讲一些基础知识,安卓的 apk 是通过包名来确认唯一性的,并且开发者会长期使用同一份签名来发布它,这个签名不可伪造,用来证明这个包确实是作者颁发的。如果我们对其进行修改的话,是肯定会破坏这个签名的,所以只能卸载掉微博然后再安装我们自己的。

第一步就用 AndroidStudio 的指引,创建一个我们自己的证书,这个步骤就跳过了,太简单了,假设我们生成的文件叫 official.jks ,放好它。

第二步是删掉原先的签名,apk 的签名位置是META-INF 目录,使用

来删除

第三步是将 apk 对齐,要用到 AndroidSDK 里build-tools 里的工具,

第四步是将它签名,同样要用到AndroidSDK 里 build-tools 里的工具,

这时候得到的 apk 就可以安装了,签名会变成我们的签名。

三、绕过重打包检测

参考这篇文章,挺有意思的,少走一些弯路。https://www.jianshu.com/p/79c3adfa483b

一般来说,app 都会做做一些基础防护,例如检测当前 app 是否被修改过,当然这么做不是为了防止爱折腾的人乱搞,而是防止小白用户安装了被人动过手脚的app。微博国际版也不例外,我们篡改签名的 app 装上就 crash了。

crash 的栈回溯和 app 相关的是这两句

 

 

而这个1C60就是简单的校验,然后返回true/false

于是我将对这个函数的调用改掉,直接对 R0 赋值为 1。

同样,另一处引用

然后继续测,这时候不 crash 了,登录时候给弹了个框,而且和输入的用户名密码没有关系,客户端身份校验失败,如图

那篇文章里说是服务器动态下发的,我不服,因为我 grep 到了字符串,但经过一番 dump 后,确实是服务器下发的,通过对 toast 抛出异常的方式,我找到了弹 toast 的地方。

 

onSuccess  解析服务器返回的字符串,显然不能走 return 的分支,而在 checkLoginResponseForWeibo  里可能抛出异常,然后被捕获并且 toast 出来

为了验证我们的猜想,我拿到了 onSuccess  的第一个参数,抓个包,果然是这样

下一步就得追为什么服务器会返回这个神奇的字符串,肯定是客户端告诉它了,前面有三个不认识的函数,稍微瞅一眼

使用hook 对比一下原版和改版的区别

api

origin

patch

securityPsd

xxx

签名校验失败

WeiboPin

xxx

签名校验失败

libnative-lib.so

这次我们使用修改 plt 表的方式,一劳永逸

然后把文件放回去,一切就完美啦!

四、去掉开屏的广告

屏幕上有四个大字,点击跳过x

找到目标:NewSplashActivity

它有很多处引用,有时候Intent 里会传 onlyFinishSelf

如果是 true,就显示后自杀;如果是 false,就登录或进入主界面。

看下引用,有这几处:

LogoActivity.openGDTAD –> 第一次启动时的广告,把doWhatNext里的返回”GDTAD”改成返回”main”

ProcessMonitor.onBackgroundToForeground –> 显示后自杀,直接删掉

BaseFragmentActivity.onResume –> 显示后自杀,直接删掉

SplashActivity.onFailedToReceiveAd –>好像没用,暂时不管了

具体操作看commit。

五、去掉时间线里的广告

这个其实是最难的部分,尝试了如下 N 种不同的方式,最后使用了最复杂的方式,在数据上进行过滤。

抓一下大致位置,发现和这两个 Activity 有关,一个是详情页,一个是时间线的 Adapter

尝试的错误方案如下:

思路1:发现code==23 是广告(其实并不是),在附近修改,不进行渲染。

每次修改后,要么界面全白,要么时间线里的【这是广告】的提醒消失了,感觉有点问题,尝试了十来处都没有成功。

当时是周六下午,我以为我成功了,就和妹子睡午觉,中途醒了刷一下微博,看到一条广告,气得我马上起床打开电脑继续去搞,睡意全无。

两个失败的截图,一般都是这两种失败。要么白屏,要么广告的修饰 UI 被我去掉了,很气。

 

思路 2:调用主动让广告消失的 API

因为广告可以被关掉,所以跟一下让广告消失的事件,用EventBus 吧,主动调用EventBus.getDefault().post(new HomeTimelineNeedDeleteStatusEvent(this.$statusId));

似乎因为没有通知到UI 更新,并没有效果。

思路3:在数据源进行过滤

其实这种方案我最开始就想到了,只是觉得有点复杂,懒得写一堆 smali 代码,没办法,最后的出路了。

第一处: TimeLineRecyclerAdapter 的构造方法,输入是一个 list,我写完代码发现这个 list 其实长度为 0;

第二处: com.jude.easyrecyclerview.adapter.RecyclerArrayAdapter 的 add 添加单个元素,然后发现没人调它,基本每次都是添加一大堆的;

第三处: com.jude.easyrecyclerview.adapter.RecyclerArrayAdapter  的 addAll 批量添加,这个是生效的,我们可以判断元素类型然后打印出它的各个属性。最开始我按照 code 过滤,发现广告并不是23,之后就配合打印出文本内容,发现了一个叫isUVEAd 的布尔值,当它是广告时候是 true

修改后的逻辑如图

06-07 16:48:09.725 25537 25537 E ccttff  : 4
06-07 16:48:09.725 25537 25537 E ccttff  : @神楽坂南音@_青泽今年也是绝赞摸鱼中
06-07 16:48:09.725 25537 25537 E ccttff  : 4
06-07 16:48:09.725 25537 25537 E ccttff  : 【悲剧!DC《沼泽怪物》才播一集就将被砍 烂番茄92%】DC最新美剧《沼泽怪物》刚刚于5月31日首映,口碑不错,烂番茄新鲜度达92%,只是没想到该剧才刚刚播出第一集,就确认了被砍的命运。06-07 16:48:09.725 25537 25537 E ccttff  : 据外媒Variety报道,流媒体平台DC宇宙取消了《沼泽怪物》的第二季预订,第一季的后续内容将继续播出。有消息人士称
06-07 16:48:09.725 25537 25537 E ccttff  : 4
06-07 16:48:09.725 25537 25537 E ccttff  : 天天在线还能赚零花钱,空闲时间看一看新闻[偷笑]玩一玩,链接放这了:httpxxxxxxwjT不知道的赶快了解下[酷]聚头条

这时发现广告和正常微博的 type 是一样的,文本类的都是 4,并不是预期的 23,不是通过这个字段区分是否为广告的。

其实是 isUVEAd 来区分广告的

06-07 17:03:43.267  4351  4351 E ccttff : 2
06-07 17:03:43.267  4351  4351 E ccttff : true

成功!确确实实从数据源头上把恶心广告给去掉了!

这里有个细节,就是一个 java 小知识,使用 iterator 时千万不要对 Collection 进行移除操作,需要使用 iterator 本身的 remove 操作。

错误的修改会触发了ConcurrentModificationException

六、去掉侧边栏的广告

侧边栏的推广

七、拒绝更新

checkUpdateForSinaForceUploadVersion-> 删掉

download -> 删掉

八、总结

顿时没有广告,神清气爽,呵呵,曾经微博国际版的宣传点就是无广告清爽,结果自己活成了自己讨厌的那副样子,一点都不为用户考虑,辣鸡!!!

发表评论

电子邮件地址不会被公开。 必填项已用*标注

*

code