本文同步自wing的地方酒馆
过去了,好像今年没写什么文章,主要是过了写文章的年纪,不过有遇到奇闻轶事或者好玩的,还是会记录下来给大家,一起乐呵乐呵。
跟Iphone X没有太大的缘分,再屏幕又挂了之后,果断搞了一台迈凯伦定制版Android机,正当嗨时,发现使用豌豆荚安装应用完毕的时候,会弹出推荐相关应用的广告,如下图:
在厌烦的背后,也让我有了好奇心,这是怎么做到的? 为什么安装完成的界面会有广告? 为此我将从豌豆荚下载安装的app和正常安装的app进行了对比。
正常安装
豌豆荚安装
观察
通过观察 我们发现,居然安装完毕之后,居然不是同一个Activity,为此,我打开了我的DroidSword插件,来观察安装完毕的Activity到底是何方神圣。
从DroidSword中我们可以看出,安装完毕以后并非系统Activity:
而是 com.pp.assistant.install.installfinish.InstallFinishActivity.
(PP跟豌豆荚合并了?)
什..什么?? 为甚安装完毕的Activity是他自己的Activity,那系统的Activity去哪了?被干掉了吗?Android真的不安全,假想一下,如果其他App掌握了这个技术,我在一个商城下载了美团,直接弹出饿了么,那是多么可怕的一件事情。
好吧,这不是我们今天的重点,我们今天的重点是,豌豆荚是如何把系统的安装界面给干掉了。
破案
于是我就开始沉思,猜测这是怎么实现的。通常的做法是做一个Recevier ,监听完毕,然后关闭掉系统安装完成的Activity,弹出我自己的Activity,可是我如何关闭Activity呢。我为了安全起见,并没有root和给豌豆荚授权辅助功能,所以豌豆荚并没有办法帮我关掉Activity。那这到底是什么黑科技呢?
于是我开启了debug之路,打开DroidSword ,并且开启“调试所有应用”功能,就可以debug任意一个App了,这个功能要感谢XInstaller,因为实在太好用了,为了方便,我就移植到了DroidSwrod中。
调试之路漫漫,从InstallFinishActivity 调试到 startActivity的入口,纠结了很久,都没有发现是如何kill掉系统安装完毕的Activity的。
可以拿到的情报就只有注册了一个StaticPackageReceiver,在这个Receiver里面,做了对新安装应用的监听,以及包名的判断,最终判断是否豌豆荚推荐来的来启动InstallFinishActivity。
这里有个疑问先卖一下关子,为什么豌豆荚要判断是否豌豆荚安装的应用才启动他的Activity,如果有黑科技,那么全程所有安装都替换掉,卖广告岂不是美滋滋?
之后开始怀疑,是否是自己实现了一个安装文件的Activity,可是又好像自己实现的话,并没有权限可以这样做。 然后观察豌豆荚的转跳安装页面,也确实只是系统的
com.android.packageinstaller.PackageInstallerActivity复制代码
那也就是说没有自己实现一个安装时候的Activity。而且DroidSword也看不到在从豌豆荚转跳到安装界面的时候,有另外一个Activity弹出。
哎,愁啊,发愁啊,他到底怎么实现的呢,在我毫无头绪的时候,突然一个意外点击事件,提示了我:
WTF
这什么鬼,说好的豌豆荚自己没有实现一个安装程序呢? 难道是DroidSword 有问题了?他显示的完全就是系统的安装器啊! 于是我点击了下去,选择了豌豆荚的安装器。然后我发现。。。。
豌豆荚居然显示安全安装(推荐),加粗 ,必须加粗!!
打广告也就算了,还把我系统安装器hook掉了,hook掉也就算了,你居然误导用户以系统的身份来打开你的安装器,去接受你推荐的广告。。 真是不敢想象如果一个小白用户,不小心点击了始终,每次安装都会强行,被迫接受来自豌豆荚的广告。这也有点太【文化人】了。
吐槽完毕,然后我打开了豌豆荚的安装器,发现 。。卧槽!!!!转跳的还是系统的com.android.packageinstaller.PackageInstallerActivity,并且没有被DroidSwrod抓下来,什么Gay ,我现在一脸黑人问号,就像这样:
好吧,不知道做了什么幺蛾子,只能全局搜索安装apk时候使用的URI了。结果果然发现一个问题:
在豌豆荚的清单文件中,发现了一个Activity,他接受了与系统安装器同样的URI:
那结果很明确了,肯定是用这个Activity作为跳板,然后转跳到系统Activity了。那为什么DroidSword会跟踪不到呢?于是我打开了这个Activity。。然后发现了。。
他并没有setContentView,而是给自身windowmanager加了个new view(),layoutParams 宽和高设置的大小是v4,而v4是。。
v4是 -2, -2好像是
public static final int WRAP_CONTENT = -2;复制代码
也就是说,这个Activity 根本! 没有! 大小!! 简直比1dp Activity还可怕。 那他做了什么事情呢,是如何干掉系统的安装成功页面的呢?继续跟踪调用栈最后肯定是转跳到系统安装的Activity。只不过在之前,对intent做了包装处理:
在apk版本为:Wandoujia_484050_web_seo_baidu_homepage.apk的混淆下,有一个类叫做:
.class public final Lcom/pp/installhook/e;复制代码
这个类就是从豌豆荚安装中转Activity转跳来的,他对intent做了个加工:
他把普通跳转系统安装Activity的Intent增加了一个Extra ,key为:android.intent.extra.RETURN_RESULT,值为true。不知道这个会有啥效果,于是我写了个Demo,运行一下,发现~!!! 安装完成的界面居然没有了。。 也就是说,系统安装完成的Activity 是可以通过这个extra给干掉的。
结果
最终总结一下豌豆荚是怎么实现的,就是先起了一个监听器,安装完毕会判断包名来决定启动不启动他自己的广告页面,现在也可以解开疑问了,为什么要判断呢,不判断岂不是更好? 原因就在于,再外调起的安装Activity一般是不带android.intent.extra.RETURN_RESULT参数的,所以都会调起系统自身的安装完成页面。 如果豌豆荚不判断包名,那么会同时弹起系统的和他自己的广告页,这时候就东窗事发,做的事情大白于台下,会影响口碑。
我按照豌豆荚的实现,自己写了个Demo,结果如下,效果一毛一样。
试想一下,如果这个页面不是广告页,而我把安装美团成功后的页面调起为饿了么页面(这里只是举例,与美团饿了么无关),无论对用户还是企业,都是一种巨大的伤害。
反思
我没有root也没有给辅助功能权限,就可以有这么大的本领,来把系统狸猫换太子。 那实在是不敢想,如果我有root权限呢? 恰好是小白用户选择了默认通过授权呢? 这些拥有root权限的App会做什么事情? 细思极恐。作为Android用户,我们如何才能保护好自己?
欢迎加入Android开发 QQ群:425983695
如果觉得《为什么豌豆荚可以在应用安装完成界面打广告?》对你有帮助,请点赞、收藏,并留下你的观点哦!