关闭

支付宝、微信后台不死的黑科技

标签: android支付宝微信后台保活
3864人阅读 评论(0) 收藏 举报
分类:

转载请标明出处:http://blog.csdn.net/xx326664162/article/details/52382358 文章出自:薛瑄的博客
你也可以查看我的其他同类文章,也会让你有一定的收货

近期支付宝升级到了9.0,除了加入微信功能外,还新增了金钟罩功能,不要说普通的各种加速球,火箭神马的不能杀死他外,连格外牛逼的绿色守护也奈何不了他。在绿色守护里面,支付宝始终显示为“服务正在被 支付宝 使用”,不会自动休眠,恼火死了。那么问题来了,他是怎么做到的呢?

支付宝干了啥?

这就是支付宝在绿色守护里的状态,它一直处在不会被自动休眠的这个category里面。不要问我第一个是啥,后面会有。

这里写图片描述

我们知道,Android有一个oom的机制,系统会根据进程的优先级,给每个进程一个oom权重值,当系统内存紧张时,系统会根据这个优先级去选择将哪些进程杀掉,以腾出空间保证更高优先级的进程能正常运行。要想让进程长期存活,提高优先级是个不二之选。这个可以在adb中,通过以下命令查看:

 cat /proc/pid/oom_adj

这个值越小,说明进程的优先级越高,越不容易被进程kill掉。

  • 如果是负数,表示该进程为系统进程,肯定不会被杀掉,
  • 如果是0,表示是前台进程,即当前用户正在操作的进程,除非万不得已,也不会被杀掉,
  • 1则表示是可见进程,通常表示有一个前台服务,会再通知栏有一个划不掉的通知,比如放歌,下载文件什么的。
  • 再增大,则优先级逐渐降低,顺序为服务进程,缓存进程,空进程等等。

关于oom的详细介绍可以查看Android平台App进程优先级

查看支付宝进程的oom_adj

因此首先,我们来查看支付宝进程的oom_adj。不出意料,其值很高:1。(查看微信进程的oom_adj值,你会发现也是1)但这又在意料之外,因为支付宝既没有添加系统服务,也没有常驻通知栏,也没有显示弹窗啊。不过既然情况已经这样了,那我们还是看一下他的服务状态吧:

shell@NX505J:/ $ dumpsys activity services com.eg.android.AlipayGphone

* ServiceRecord{17d6e8a5 u0 com.eg.android.AlipayGphone/com.alipay.android.launcher.service.LauncherService$InnerService}
    intent={cmp=com.eg.android.AlipayGphone/com.alipay.android.launcher.service.LauncherService$InnerService}
    packageName=com.eg.android.AlipayGphone
    processName=com.eg.android.AlipayGphone
    baseDir=/data/app/com.eg.android.AlipayGphone-2/base.apk
    dataDir=/data/data/com.eg.android.AlipayGphone
    app=ProcessRecord{38365c98 14176:com.eg.android.AlipayGphone/u0a66}
    isForeground=true foregroundId=168816881 foregroundNoti=Notification(pri=0 contentView=com.eg.android.AlipayGphone/0x1090077 vibrate=null sound=null defaults=0x0 flags=0x40 color=0xff00bcd4 vis=PRIVATE)
    createTime=-19m10s188ms startingBgTimeout=-18m55s186ms
    lastActivity=-19m10s188ms restartTime=-19m10s188ms createdFromFg=false
    startRequested=true delayedStop=false stopIfKilled=true callStart=true lastStartId=1

原来真有一个前台服务!
这不科学!Service的startForeground函数是要提供一个Notification参数的啊。

这里直接给出结论:

  • API level < 18 :调用startForeground(ID, new Notification()),发送空的Notification ,图标则不会显示。打开adb看一看,18以下确实就LauncherService自己在负责前台。

  • 对于 API level >= 18:在需要提优先级的service A启动一个InnerService,两个服务同时startForeground,且绑定同样的 ID。Stop 掉InnerService ,这样通知栏图标即被移除。

Android的漏洞在哪?

API level < 18漏洞的修补

原来,google在4.3的时候终于发现有太多流氓应用,为了提高优先级,开启了前台服务,但又不想让用户知道,因此需要不显示通知栏。于是找到了android在开启前台服务时候的一个漏洞,给一个非法的Notification参数,让系统先把ServiceRecord里面的isForeground标记给打上,然后等到显示通知栏时,发现参数并不合法,android于是什么也不干,就不显示通知栏提醒了。
当一票app都这么干的时候,google觉得不能忍了,于是在ServiceRecord的postNotification函数里面,我们看到了如下代码:

try {
    if (localForegroundNoti.icon == 0) {
        // It is not correct for the caller to supply a notification
        icon, but this used to be able to slip through, so for
        those dirty apps give it the app's icon.
        localForegroundNoti.icon = appInfo.icon;
      }
        // Do not allow apps to present a sneaky invisible content view either.
        localForegroundNoti.contentView = null;
        localForegroundNoti.bigContentView = null;
        CharSequence appName = appInfo.loadLabel(
            ams.mContext.getPackageManager());
        if (appName == null) {
            appName = appInfo.packageName;
        }
        ctx = null;
        try {
            ctx = ams.mContext.createPackageContext(
                appInfo.packageName, 0);
        Intent runningIntent = new Intent(
            Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
        runningIntent.setData(Uri.fromParts("package",
            appInfo.packageName, null));
        PendingIntent pi = PendingIntent.getActivity(ams.mContext, 0,
            runningIntent, PendingIntent.FLAG_UPDATE_CURRENT);
        localForegroundNoti.setLatestEventInfo(ctx,
            ams.mContext.getString(
                com.android.internal.R.string
                    .app_running_notification_title,
                        appName),
        ams.mContext.getString(
             com.android.internal.R.string
                .app_running_notification_text,
             appName),
            pi);
    } catch (PackageManager.NameNotFoundException e) {
        localForegroundNoti.icon = 0;
    }
}

上面代码可以发现,如果notification为空,系统会自动帮你赋值,来显示到notification tray
于是,像豌豆荚,360这些,在高版本系统上也没有前台服务了,默默的再后台,然后等着被干掉。

API level >= 18漏洞利用原理

在启动前台服务的时候一定要给一个Notification,那我可不可以在启动前台服务后,调用NotificationManager的cancelNotification把这个Notification给取消掉呢?来看看源码:

// 在NotificationManagerService.java中
public void cancelNotificationWithTag(String pkg, String tag, int id, int userId) {
        checkCallerIsSystemOrSameApp(pkg);
        userId = ActivityManager.handleIncomingUser(Binder.getCallingPid(),
                Binder.getCallingUid(), userId, true, false, "cancelNotificationWithTag", pkg);
        // Don't allow client applications to cancel foreground service notis.
        cancelNotification(pkg, tag, id, 0,
                Binder.getCallingUid() == Process.SYSTEM_UID
                ? 0 : Notification.FLAG_FOREGROUND_SERVICE, false, userId);
}

// 实现函数的声明,如果在mustNotHaveFlags里面,请求会被直接弹掉,通知不会被取消。
boolean cancelAllNotificationsInt(String pkg, int mustHaveFlags,
            int mustNotHaveFlags, boolean doit, int userId) {
            ...
        }
  • 对于不是系统UID的用户来说,如果Notification带有FLAG_FOREGROUND_SERVICE标记,你是取消不掉的,这类通知只有系统能取消,

  • 给用户的唯一入口就是Service#stopForeground (boolean removeNotification),在调用这个接口的时候,会将前台状态置为false。如果传入参数为true,再同时把Notification给cancel掉。

假如同时启动两个service,并且将他们同时置为前台状态,共享同一个NotificationID,此时会出现两个前台服务,但通知管理器里只有一个关联的通知。 这时我们在其中一个服务中调用 stopForeground(true),这个服务前台状态会被取消,同时状态栏通知也被移除。 另外一个服务呢?他并没有受到影响,还是前台服务状态,但是此时,状态栏通知已经没了! 这就是支付宝的黑科技。

下面是一个示例程序,Service名字就叫AlipayService啦: sneaky_foreground_service. 第一个图里面那个和支付宝一起不会被干掉的就是它了。支付宝的service因为还被其他进程绑定,所以显示 服务正在被 支付宝 使用, 而这个Circles纯粹是演示用,就懒得整了。

参考:支付宝后台不死的黑科技
微信Android客户端后台保活经验分享

2
0
查看评论

Android进程保活及黑科技

> Android进程保活招式大全 -- http://dev.qq.com/topic/57ac4a0ea374c75371c08ce8 关于 Android 进程保活,你所需要知道的一切- http://blog.csdn.net/f2006116/article/de...
  • ShareUs
  • ShareUs
  • 2016-07-31 00:05
  • 4733

【腾讯Bugly干货分享】Android进程保活招式大全

目前市面上的应用,貌似除了微信和手Q都会比较担心被用户或者系统(厂商)杀死问题。本文对 Android 进程拉活进行一个总结。
  • Tencent_Bugly
  • Tencent_Bugly
  • 2016-08-12 15:54
  • 3179

微信Android客户端后台保活经验分享

原文地址:http://mp.weixin.qq.com/s?__biz=MzA3ODg4MDk0Ng==&mid=403254393&idx=1&sn=8dc0e3a03031177777b5a5876cb210cc&scene=0#wechat_redirect ...
  • pengpenggxp
  • pengpenggxp
  • 2016-07-12 18:04
  • 2901

Android进程保活的一般套路

自己曾经也在这个问题上伤过脑经,前几日刚好有一个北京的哥们在QQ说在做IM类的项目,问我进程保活如何处理比较恰当,决定去总结一下,网上搜索一下进程常驻的方案好多好多,但是很多的方案都是不靠谱的或者不是最好的,结合很多资料,今天总结一下Android进程保活的一些方案,都附有完整的实现源码,有些可能你...
  • u013263323
  • u013263323
  • 2017-02-21 15:45
  • 8453

Android如何降低service被杀死概率

让app 的service常驻其实是很流氓的做法,但是需求摆在那里。。。 但是要清除一点:想百分百保活service在当前是无法做到的,只能降低service被杀死的概率,曾经看了多少篇网上大神的牛逼博客,从各个层面分析如何让service不被杀死或者被杀死后重启,特别是从android系统底层分...
  • lhd201006
  • lhd201006
  • 2016-03-18 09:22
  • 7548

Android之service保活

这段时间做的项目需要service保活,也就是实时监听设备的通知栏消息,并可以捕获到通知的内容,然后进行对应的操作。之前尝试过很多方式,最后感觉前台service对于服务保活相对好使(据说这个微信也用过的方案),知情者可能要问了:前台service不是有个通知栏一直显示么?这样对用户来说不是很好。我...
  • qq_26420489
  • qq_26420489
  • 2017-03-20 18:02
  • 2201

支付宝安全控件为什么常驻那么多进程?

近日用了支付宝,安装了支付宝安全控件,交易正常。 后来发现不开浏览器的情况下,系统会有4个支付宝的常驻进程,如下: 太讨厌了,浏览器我都不开,你干嘛启动这么多进程呢? 菜单中还没有删除项,只能到添加删除程序中删除。
  • ultrapro
  • ultrapro
  • 2012-09-06 09:34
  • 1527

Alipay(支付宝)接口相关

1.alipay 双功能支付简介  1.1 使用流程   在网站中生成订单信息,并记录到数据库中,将订单信息及其他必要信息按照alipayto指定的形式,发给支付宝,也就是生成完了调AlipayService.BuildForm() 方法,该方法会返回一串字符串,里面记录着表单信息,无...
  • CHBSRZF
  • CHBSRZF
  • 2015-09-06 11:16
  • 834

关于Alipay支付宝接口(Java版)

1.alipay 双功能支付简介 2.alipay 提交支付订单 3.alipay 整合双功能支付及发货信息同步 4.alipay 页面跳转同步通知处理 5.alipay 服务器异步通知处理   ======================  华丽丽的分割线 ...
  • u011203602
  • u011203602
  • 2015-08-28 10:17
  • 12257

支付宝双功能支付详解

零碎 关于Alipay 每篇一语:理想很丰满,现实很骨感! 1.alipay 双功能支付简介 2.alipay 提交支付订单 3.alipay 整合双功能支付及发货信息同步 4.alipay 页面跳转同步通知处理 5.alipay 服务器异步通知处理   =======...
  • u013810758
  • u013810758
  • 2014-07-21 14:06
  • 2558
    个人资料
    • 访问:1018559次
    • 积分:11171
    • 等级:
    • 排名:第1702名
    • 原创:192篇
    • 转载:139篇
    • 译文:0篇
    • 评论:239条
    关于我
    你的鼠标里,有老鼠喜欢的食物
    博客专栏
    最新评论
    有问题,联系我