java开发app启动跳转到一个广告,Android逆向之路---为什么从后台切换回app又显示广告了...

问题

最近发现自己的android机在开网易新闻,知乎等app的时候,明明自己没有杀进程,从后台返回回来的时候还是会再次显示广告,而且又正巧在知乎上看到了有人在提问,于是逆向分析。**就用知乎作为例子吧。**我用的5.4.1版本

先说结果:

不是因为杀进程、杀后台的原因造成的,这是知乎的业务逻辑。

知乎就是为了显示更多次数的广告,故意设计成这个样子的。

你启动知乎的时候如果没显示广告,那么等你切到后台再回来就显示一次。

你启动知乎的时候如果显示广告了,那么你切到后台了不杀死知乎,那么他就不显示。

开始逆向

讨厌的广告界面如下

8e2964dc260bc61328f0a9f15be04721.png

准备工作,利用apktool拆包,然后开始逆向分析。

首先通过搜索字符串方法,搜索“发现更大的直接”然后找到了下面的字符串

发现更大的世界

复制代码

然后根据这个name的值发现了这个广告界面布局文件是"fragment_launch_ad.xml"

继续找,

根据id然后对应"public.xml"等方法,

可以最终找到其实这个页面就是"LaunchAdFragment.java"

首先我们找到讨厌的广告页面了

换一种思路开始寻找Activity

我从后台切回来的时候肯定是当前Activity在作祟,他执行了一些程序才唤起的"LaunchAdFragment"

按照这个思路我就像看看知乎嘴上层的activity叫什么名字,连上adb执行如下命令

adb shell dumpsys activity

复制代码

然后发现了,原来这个activity的名字叫"MainActivity"啊

activity栈如下

Running activities (most recent first):

TaskRecord{b4d2961 #339 A=com.zhihu.android U=0 StackId=1 sz=1}

Run #4: ActivityRecord{bc733c u0 com.zhihu.android/.app.ui.activity.MainActivity t339}

TaskRecord{35c713e #340 A=com.android.gallery3d U=0 StackId=1 sz=1}

Run #3: ActivityRecord{cd14b9f u0 com.android.gallery3d/com.huawei.gallery.app.GalleryMain t340}

TaskRecord{1fb8a4b #333 A=com.android.settings U=0 StackId=1 sz=1}

Run #2: ActivityRecord{d3eec28 u0 com.android.settings/.HWSettings t333}

TaskRecord{69570b7 #335 A=com.tencent.mm U=0 StackId=1 sz=1}

Run #1: ActivityRecord{a82f024 u0 com.tencent.mm/.ui.LauncherUI t335}

TaskRecord{e43bab9 #295 I=com.android.settings/.deviceinfo.UsbConnModeChooserActivity U=0 StackId=1 sz=1}

Run #0: ActivityRecord{9d10efe u0 com.android.settings/.deviceinfo.UsbConnModeChooserActivity t295}

复制代码

综上所述,这个MainActivity和LaunchAdFragment肯定有关系,我就在MainActivity里面,然后就在MainActivity里面搜索LaunchAdFragment,

发现了居然在onResume里面调用了LaunchAdFragment

根据直觉来说,我觉得应该问题就在这里了。我找到了知乎居然有下面这些逻辑。(看不懂没关系,往下读,我已经手动的转成了Java)

.line 533

:cond_3

invoke-static{}, Lcom/zhihu/android/app/util/LaunchAdHelper;->getInstance()Lcom/zhihu/android/app/util/LaunchAdHelper;

move-result-objectv5

invoke-virtual{v5}, Lcom/zhihu/android/app/util/LaunchAdHelper;->isShowLaunchAd()Z

move-resultv5

if-eqzv5,:cond_4

.line 535

const-stringv5, "input_method"

invoke-virtual{p0, v5}, Lcom/zhihu/android/app/ui/activity/MainActivity;->getSystemService(Ljava/lang/String;)Ljava/lang/Object;

move-result-objectv0

check-castv0, Landroid/view/inputmethod/InputMethodManager;

.line 536

.local v0, "imm":Landroid/view/inputmethod/InputMethodManager;

invoke-virtual{v0}, Landroid/view/inputmethod/InputMethodManager;->isActive()Z

move-resultv5

if-nezv5,:cond_4

.line 538

invoke-static{}, Lcom/zhihu/android/app/ui/fragment/LaunchAdFragment;->buildIntent()Lcom/zhihu/android/app/util/ZHIntent;

move-result-objectv5

invoke-virtual{p0, v5}, Lcom/zhihu/android/app/ui/activity/MainActivity;->startFragment(Lcom/zhihu/android/app/util/ZHIntent;)V

复制代码

对应的Java代码

void onResume(){

// 判断是否需要加载广告,

boolean showAd = LaunchAdHelper.getInstance().isShowLaunchAd();

if(!showAd) return ;

//判断系统键盘是否是active的

InputMethodManager imm = ((InputMethodManager)getSystemService("input_method"));

if(imm.isActive()) return ;

//打开广告页面

Intent intent = LaunchAdFragment.buildIntent();

startFragment(intent);

}

复制代码

具体的逻辑已经在代码里面加了注释,所以说,到底显示还是不显示广告主要看这个方法了

LaunchAdHelper.getInstance().isShowLaunchAd()

复制代码

继续寻找LaunchAdHelper里面的控制变量

然后找到这个类,跟进这个方法,具体看源码

.methodpublic isShowLaunchAd()Z

.locals 2

.prologue

const/4v0, 0x0

.line 105

iget-booleanv1, p0, Lcom/zhihu/android/app/util/LaunchAdHelper;->mIsAllowShowLaunchAd:Z

if-eqzv1,:cond_0

.line 106

iput-booleanv0, p0, Lcom/zhihu/android/app/util/LaunchAdHelper;->mIsAllowShowLaunchAd:Z

.line 107

const/4v0, 0x1

.line 110

:cond_0

returnv0.end method

复制代码

转换成java代码如下

public boolean isShowLaunchAd(){

if(!mIsAllowShowLaunchAd) {

return false;

}

mIsAllowShowLaunchAd = false;

return true;

}

复制代码

好了,至少到现在大家应该知道了,显示不显示广告主要靠这个LaunchAdHelper里面的成员变量mIsAllowShowLaunchAd

谁能够改变控制这个变量,业务逻辑主要就是控制他了。

而且已经出现了业务逻辑就是,如果显示了一次,那么这个变量就会为false,然后就不显示了。(至少现在是这样)

然后搜索LaunchAdHelper发现了他在onStart里面初始了这个变量

.methodpublic onStart(Landroid/content/Context;)V

//------略------

iput-booleanv0, p0, Lcom/zhihu/android/app/util/LaunchAdHelper;->mIsAllowShowLaunchAd:Z

.line 88

:cond_0

const/4v0, 0x0

iput-booleanv0, p0, Lcom/zhihu/android/app/util/LaunchAdHelper;->mIsFromInnerActivity:Z

.line 89

iget-booleanv0, p0, Lcom/zhihu/android/app/util/LaunchAdHelper;->mIsAllowShowLaunchAd:Z

iput-booleanv0, p0, Lcom/zhihu/android/app/util/LaunchAdHelper;->mIsLaunchAdShow:Z

//------略------.end method

复制代码

其实这段代码的意思就是初始化了一下这个mIsAllowShowLaunchAd,设置成true,那么紧接着问题就来了,谁调用了LaunchAdHelper的onStart方法呢,

他的父类是Object啊,只是一个普通的类,

继续全局搜索

再次找回到了MainActivity

然后发现绕了一圈我们又绕回来了,在MainActivity里面调用了这个方法,结果如下

.methodprotected onStart()V

.locals 1

.prologue

.line 460

invoke-super{p0}, Lcom/zhihu/android/app/ui/activity/BaseFragmentActivity;->onStart()V

.line 461

invoke-static{}, Lcom/zhihu/android/app/util/LaunchAdHelper;->getInstance()Lcom/zhihu/android/app/util/LaunchAdHelper;

move-result-objectv0

#下面这两句就是调用了初始化广告的方法

invoke-virtual{v0, p0}, Lcom/zhihu/android/app/util/LaunchAdHelper;->onStart(Landroid/content/Context;)V

.line 462

return-void.end method

复制代码

好了,现在为止,大概明白了吧。

在MainActivity的onStart方法里面调用了LaunchAdHelper的onStart方法,随后在这里面初始化将mIsAllowShowLaunchAd 设置成true的。

然后再onResume里面再显示广告显示一次了再次onResume就不显示了

但是如果再次调用onStart那么又初始化了,设置成了显示广告,

那么具体什么时候会调用Activity的onStart呢,

官方文档是这么说的:

30a5ff23b1d93022211a576749e12690.png

具体意思就是显示的时候就会调用onStart。

结果

其实结果已经在文章开始部分说过了,不记得的话往前翻翻吧

写在结尾

这就是知乎的这个闪屏广告显示的逻辑,

有个以为接到了这种业务逻辑的时候程序员会不会心里内心一万只羊驼奔腾飞过

还有,他们没混淆app吗,混淆过的方法不应该是

a.b.a1(p1,p3);

复制代码

这个样子的吗。

转眼一看软件版本5.4.1,恍然大悟。

关于我

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值