|
1.加菲猫影视1.6.2
2.HttpCanary
3.jadx-gui
4.Android Studio
5.MT管理器
一、前言:
---
前几天简简在研究加菲猫影视,我一起看了下。这个软件的前身叫南瓜影视,之前很多人研究,不过自从它换皮又上了服务器校验之后,我便很少看到有人研究了。此次教程便以去广告为主,搭配简简的
https://bbs.binmt.cc/thread-76889-1-1.html
理论上来说,可以白嫖一阵子了。
一般来说,以前的去广告都是修改xml为主,我这次便想挑战一下,用xposed写一个去广告插件。那么,教程开始了。
二、过程:
---
这个软件广告是真的多,而且还有一些是少儿不宜的。
先来看一下最终的效果图

它总共有八处广告,我一一来述。
1、启动广告
先看看广告长什么样子

启动广告采用的是activity纪录分析法,从中可以看出软件的activity的过程是由SplashActivity->AdActivity->HomepageActivity,由此可见,在AdActivity中必然有一个方法会启动HomepageActivity。

打开jadx-gui,很快就发现了调用的方法
代码如下:
- public void b2() {
- ARouter.getInstance().build("/homepage/activity").withTransition(R.anim.anim_activity_enter_alpha, R.anim.anim_activity_exit_alpha).navigation(this);
- }
复制代码
按x查找用例

发现都是在本类中调用,稍微分析了下,发现一个可以方法,代码如下:
- public void p1() {
- SplashBean splashBean = this.T;
- if (splashBean == null) {
- return;
- }
- if (splashBean.getPicUrl() == null) { //getPicUrl为空时,跳转到home页
- if (u3()) {
- b2();
- }
- finish();
- return;
- }
- TextView textView = this.mTvWebUel;
- if (textView != null) {
- textView.setVisibility(8);
- w.b("AdActivity", splashBean.getPicUrl());
- AdPresenter adPresenter = (AdPresenter) this.Q;
- String picUrl = splashBean.getPicUrl();
- j.b(picUrl, "it.picUrl");
- ImageView imageView = this.mIvAd;
- if (imageView != null) {
- adPresenter.u(picUrl, imageView);
- } else {
- j.q("mIvAd");
- throw null;
- }
- } else {
- j.q("mTvWebUel");
- throw null;
- }
- }
复制代码
跳转到getPicUrl方法看看,返回值是字符串也就是广告的url
- public String getPicUrl() {
- return this.picUrl;
- }
复制代码
编写xpoesd模块,直接让其返回值为空即可
- //去除启动广告
- XposedHelpers.findAndHookMethod("com.video.test.javabean.SplashBean", classLoader, "getPicUrl", new XC_MethodReplacement() {
- @Override
- protected Object replaceHookedMethod(MethodHookParam methodHookParam) throws Throwable {
- return null;
- }
- });
复制代码
---
**2.主页弹窗**
在解决启动广告后,我们进入主页。映入眼帘的就是两个弹窗广告
长这个样子

这个广告也同样是activity纪录分析法,这个弹窗是在HomepageActivity界面弹窗,那我们不妨搜一下dialog,因为一般这种弹窗都是属于dialog,果不其然,又发现了一个可疑的方法
- public void C0(List<HomeDialogBean> list) {
- if (!(list == null || list.isEmpty())) { 当传入的List参数不为空时,弹出主页弹窗,而这个List就是弹窗广告的图片url,但是因为晚上在写教程的软件死活不弹,我也没办法给你们验证
- ArrayList arrayList = new ArrayList();
- for (HomeDialogBean homeDialogBean : list) {
- HomeNoticeDialogFragment homeNoticeDialogFragment = null;
- homeDialogBean.getActivityType();
- if (homeDialogBean.getActivityType() == 2) {
- homeNoticeDialogFragment = HomeNoticeDialogFragment.b0.a(homeDialogBean);
- }
- if (homeNoticeDialogFragment != null) {
- arrayList.add(homeNoticeDialogFragment);
- homeNoticeDialogFragment.q3(new b(arrayList));
- homeNoticeDialogFragment.h3(new BaseHomeDialogFragment.a(arrayList) { // from class: e.m.a.r.l.b
- /* renamed from: b reason: collision with root package name */
- public final /* synthetic */ List f15178b;
- {
- this.f15178b = r2;
- }
- @Override // com.video.test.ui.widget.BaseHomeDialogFragment.a
- public final void a(BaseHomeDialogFragment baseHomeDialogFragment) {
- HomepageActivity.this.u4(this.f15178b, baseHomeDialogFragment);
- }
- });
- }
- }
- if (!arrayList.isEmpty()) {
- ((BaseHomeDialogFragment) arrayList.get(0)).F2(I3(), "dialog0");
- }
- }
- }
复制代码
从上面的逻辑可以看出来,如果List的值为空,那它就不会弹弹窗,我们可以把List置空,当然也可以直接把方法置空,这并不会影响软件的使用
代码如下:
- //去除主页弹窗广告
- XposedHelpers.findAndHookMethod("com.video.test.module.homepage.HomepageActivity", classLoader, "C0", List.class, new XC_MethodReplacement() {
- @Override
- protected Object replaceHookedMethod(MethodHookParam methodHookParam) throws Throwable {
- return null;
- }
- });
复制代码
---
**3.轮播图广告**
老样子先看看长什么样子

这个需要我们先用小黄鸟抓个包,过滤一下ad,这几个都是关键的url请求
这里的响应都是密文,所以我们直接用简简帖子里的来解密,可以得知轮播图广告弹窗的url就是bannerInfo

在代码中搜索url中的Ad/bannerInfo,结果只有一个,而且是retrofit2的接口类,这就比较麻烦,没办法直接进行hook,只能找到关键的实例去修改

多次按x查找用例,因为层级有点多,我这里做了一个堆栈流程图,你们可以参考一下

最终聚焦一下这个s方法,代码如下:
- public void s(List<? extends BannerBean> list) {
- j.f(list, "list");
- if (!list.isEmpty()) {
- int size = list.size();
- ArrayList arrayList = new ArrayList(size);
- ArrayList arrayList2 = new ArrayList(size);
- for (BannerBean bannerBean : list) {
- String slidePic = bannerBean.getSlidePic();
- j.b(slidePic, "bannerBean.slidePic");
- arrayList.add(slidePic);
- String a2 = h0.a(bannerBean.getBannerContent());
- j.b(a2, "StringUtils.emptyIfNull(bannerBean.bannerContent)");
- arrayList2.add(a2);
- String str = this.f8643d;
- //这里向f方法里传入三个参数,分别是广告图片url、广告id、广告文字
- w.f(str, "picUrls == " + bannerBean.getSlidePic() + " vodId == " + bannerBean.getVodId() + " bannerContent : " + bannerBean.getBannerContent());
- }
- ((e.m.a.r.j0.a) this.f8265b).f0(arrayList, arrayList2, list);
- return;
- }
- ((e.m.a.r.j0.a) this.f8265b).d2();
- }
复制代码
最终这些数据又转为List传入f0方法中,f0传入的三个参数也就分别代表了广告图片url、广告id、广告文字,这三个数据要同时进行修改,不然会报错,这里我们就去除两个广告,然后对其中一个广告的url和文字进行修改(从轮播图中我们可以知道,第一、第二、第四个都是广告)
注意索引!
xposed代码如下:
- //去除轮播图广告
- XposedHelpers.findAndHookMethod("com.video.test.module.videotype.BaseVideoTypeListFragment", classLoader, "f0",List.class,List.class,List.class,
- new XC_MethodHook() {
- @Override
- protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
- super.beforeHookedMethod(param);
- List URL = (List) param.args[0];
- URL.set(0,"https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fc-ssl.duitang.com%2Fuploads%2Fitem%2F201810%2F22%2F20181022224306_ydqyt.thumb.1000_0.jpg&refer=http%3A%2F%2Fc-ssl.duitang.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1641197983&t=178238b2c2ce9ef7398dcc9876b54e42");
- URL.remove(1);
- URL.remove(3);
- param.args[0] = URL;
- List content = (List) param.args[1];
- content.set(0,"正己修改");
- content.remove(1);
- content.remove(3);
- param.args[1] = content;
- List layout = (List) param.args[2];
- layout.remove(1);
- layout.remove(3);
- param.args[2] = layout;
- }
- });
复制代码
效果图:

---
**4.公告广告**
就是在轮播图下面的公告广告,同样是通过请求的url定位,直接分析有点混乱,我还是做个流程图,不得不说接口类找实例真麻烦

分析一下重写的w2代码:
- public void w2(List<HomePageNoticeBean> list) {
- //当list为空时
- if (list == null || list.isEmpty()) {
- this.mSwitcherNotice.d(); //开发者助手抓布局时发现id刚好为SwitcherNotice
- this.mSwitcherNotice.setVisibility(8); // 隐藏布局
- return;
- }
- if (this.R == null) {
- this.R = new ViewSwitcher.ViewFactory() { // from class: e.m.a.r.i0.b
- @Override // android.widget.ViewSwitcher.ViewFactory
- public final View makeView() {
- return VideoRecommendFragment.this.z3();
- }
- };
- }
- if (this.S == null) {
- this.S = new a();
- }
- this.mSwitcherNotice.setFactory(this.R);
- this.mSwitcherNotice.setTextBinder(this.S);
- this.S.d(list);
- this.mSwitcherNotice.c();
- }
复制代码
由此可知,只需将传入的参数置空即可,xposed代码如下:
- //去除公告广告
- XposedHelpers.findAndHookMethod("com.video.test.module.videorecommend.VideoRecommendFragment", classLoader, "w2", List.class, new XC_MethodHook() {
- @Override
- protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
- super.beforeHookedMethod(param);
- param.args[0] = null;
- }
- });
复制代码
---
**5.横幅广告**
老样子,搜索url中的关键词(这里说一下,我抓包的那张截图中横幅广告的标记和公告广告的标记写反了),所以横幅广告应该搜索
Ad/noticeInfo

这里主要看一下com.video.test.module.videorecommend.VideoRecommendPresenter.z的代码:
- public /* synthetic */ void y(List list) throws Exception {
- if (list.isEmpty()) { //当传入的lsit为空时,执行q0的方法
- ((m) this.f8265b).q0();
- return;
- }
- ((m) this.f8265b).a3(list);
- ((m) this.f8265b).h1();
- }
复制代码
q0的方法重写之后就是一个很明显的隐藏布局的代码
- public void q0() {
- this.mRvModule.setVisibility(8);
- }
复制代码
所以xpoesd代码如下:
- //去除主页notice广告
- XposedHelpers.findAndHookMethod("com.video.test.module.videorecommend.VideoRecommendPresenter", classLoader, "y", List.class, new XC_MethodHook() {
- @Override
- protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
- super.beforeHookedMethod(param);
- param.args[0] = null;
- }
- });
复制代码
---
**6.页面中间广告**
先看一下长什么样子

搜索字符串/Ad/barsIndexAdInfo,堆栈图

在j方法中注意传入的第一个参数,当他不为2时都会显示广告,分别是在加载顶栏的热门、电影、电视剧、综艺、动漫所加载的广告对应的值(可以打印一下进行验证)
- public final g.b.m<AdInfoBean> j(int i2, Context context) {
- String str;
- if (i2 == 1) {
- str = m.a.l();
- } else if (i2 == 3) {
- str = m.a.j();
- } else if (i2 == 4) {
- str = m.a.n();
- } else if (i2 == 5) {
- str = m.a.a();
- } else if (i2 != 6) {
- g.b.m<AdInfoBean> B = g.b.m.B(AdInfoBean.EMPTY_INSTANCE);
- j.b(B, "Observable.just(AdInfoBean.EMPTY_INSTANCE)");
- return B;
- } else {
- str = m.a.p();
- }
- g.b.m<AdInfoBean> F = this.a.n(i2).e0(this.a.m(context, str), a.a).F(b.a);
- j.b(F, "mModel.getAd(pid)\n \u2026InfoBean.EMPTY_INSTANCE }");
- return F;
- }
复制代码
所以我们只需要将第一个参数写死即可
- //去除中间广告
- XposedHelpers.findAndHookMethod("com.video.test.module.videotype.BaseVideoTypeListPresenter", classLoader, "j", int.class,Context.class, new XC_MethodHook() {
- @Override
- protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
- super.beforeHookedMethod(param);
- param.args[0] = 2;
- }
- });
复制代码
---
**7.播放页广告**
看一下

根据抓包搜索字符串Ad/barsPlayAdInfo,堆栈图

代码如下:
- public void g1(AdInfoBean adInfoBean) {
- if (adInfoBean != null) { //当传入的参数为空,隐藏布局
- e.m.a.p.b.d(this).load(adInfoBean.getAdPic()).listener(new l(adInfoBean)).centerCrop().into(this.mIvAd);
- ImageView imageView = this.mIvAd;
- imageView.setTag(imageView.getId(), adInfoBean);
- return;
- }
- this.mIvAd.setVisibility(8);
- }
复制代码
所以xposed代码如下:
- //去除播放页广告,自定义类参数
-
- Class<?> personClass = XposedHelpers.findClass("com.video.test.javabean.AdInfoBean",classLoader);
- XposedHelpers.findAndHookMethod("com.video.test.module.player.PlayerActivity", classLoader, "g1", personClass,new XC_MethodHook() {
- @Override
- protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
- super.beforeHookedMethod(param);
- param.args[0] = null;
- }
- });
复制代码
---
**8.个人页广告**
这个就当给一些新手同学留个小问题,效果如下:
不要直接修改xml哦,尝试去推导堆栈,然后找到关键方法进行hook

---
三、尾声
啥时候MT能支持一下MD语法,转换挺头疼的
写个教程真的废时间呀,第一次尝试去hook接口类的实例,真的很麻烦,也有可能是还有其他更好的方法俺还不会,如果有大佬有其他更好的思路,请赐教 |
-
查看全部评分
总评分:好评 +3
金币 +3
|