• Android中一个有趣的crash的日志分析


     很久前写的一篇文章,发出来以作纪念:)

    Android中一个有趣的crash的日志分析

    首先看看bugly平台中异常的统计信息,表面上是一个NullPointerException:

    发生异常设备统计信息如下图,有意思的是全部都是root过的机器:

    接下来看跟踪日志,在最下面可以看到这样的日志,抛出了NullpointerException:

    引起异常的是com.lishu.net.LishuNet$2类,从类名看显然是某一个类的内部类。

    第一个反应,当然是搜索一下应用的源代码,看看是不是有com.lishu.net.LishuNet这样的类,或者异常。如果有,那自然就是继续分析代码了。经过一番搜索,居然没有找到,看来有点意思。

    其次自然想到,应用集成了很多第三方SDK,或许是某个SDK里抛出的异常?不急,解压出所有集成的.jar包,然后批量反编译,导入工具中全局搜一下,有没有这个字符串了。费一番周折发现,还是没有这个字符串。越来越有意思了,代码中没有相关的类,SDK中也没有,奇怪。

    回来继续翻看日志上下文,只有如下信息可用,看来是个http访问超时异常:

    有问题,这个异常和其他异常不太一样,日志里居然连com.chebada包名都没有显示出来的。也许是统计平台出错了,压根不是我们应用导致的crash?

    只有抛异常前打出来的一行日志,看起来有些关系

    访问这个网址看看,有时连不上,有时拒绝服务。源代码里也没有这样的网址。

    这个时候线索好像真的断了,再搜索日志,看不出来和我们的应用有什么关联。

    还是没有思路,再翻一下其他异常,发现异常列表中有些日志会打出来类似下面的内容,之后再访问上图中的网址(http://120.24.74.141:8080/lishu008AppManager/phone/LogicSimpleAction.action):

    总结多个crash日志,发现每次都是先有这个js警告,再访问120.24.74.141域名。

    js又是/data/data目录com.chebada包下的脚本,也许,是WebView的访问触发了相关异常,或许是url劫持?也不像。统计平台异常列表中有些并没有报这个js警告,问过服务器相关同事,js也没有访问http://120.24.74.141:8080/lishu008AppManager这样的网址。

    不过所有crash日志都有访问http的超时异常。

    疑点都集中在http://120.24.74.141:8080/lishu008AppManager这里。

    继续万能的百度搜索,lishu008AppManager露出一点端倪。有一个名叫“008神器”的安卓应用引起了我的注意,该下载链接中有lishu008AppManager字样。打开主页看看该应用能干什么,结果吓一跳:

    下载一个看看,运行需要root过的机器。 找了一台root过的机器,运行后按提示安装框架、安装模块。期间需要重启几次。

    需要的框架、模块都安装好了,再次运行,提示软件到期。卸载重新下载一个破解版的“008神器”,运行后发现,能改的东西还真多,连手机串号也能改:

    这个时候看看日志,发现了LishuNet的踪迹:

    等等,“008神器”的包名不是com.soft.apk008Tool吗,怎么会报com.lishu.net.LishuNet错误呢?反编译apk安装包,原来,除了com.soft.apk008Tool,还有另一个包com.lishu.net这个包,其中有LishuNet这个类,LishuNet还有一个内部类com.lishu.net.LishuNet$2,继承自Thread:

    显然在该线程中触发了NullPointerException异常。往下跟跟,具体打印出异常的地方:

    这个就是在连接http://120.24.74.141:8080失败时,比如连接超时、服务器拒绝服务等异常情况下,打印出异常信息的地方了。原来只要连接出错,就会打印出错信息。

    除了反编译代码中有com.lishu.net这个包,在 “008神器”安装包的assets文件夹下还发现了Apk008Tool.apk这个安装包,安装后会多一个“008神器工具箱”的应用。再反编译“008神器工具箱”,原来com.lishu.net是“008神器工具箱”的包名,而“008神器”中com.lishu.net包下的代码,都是从Apk008Tool.apk来的,最有可能的就是,“008神器”和“008神器工具箱”是同一个作者开发的。

    那是什么触发了异常呢?各种尝试,后来发现运行“008神器”,就会访问网址http://120.24.74.141:8080/lishu008AppManager/phone/LogicSimpleAction.action,接着log中就能看到异常信息,过滤后显示如下图:

    原来只要运行“008神器”就会报异常。继续跟踪com.lishu.net.LishuNet:

    LishuNet对象调用postMessage()方法,在该方法中new一个LishuNet$2的对象,也就是新建了一个Thread线程,并开始运行。异常就是从这个线程里抛出来的。

    那么,哪里调用了LishuNet的postMessage()方法呢?继续搜索,原来是在Apk008Activity的onResume()中:

    其他地方也有调:

    稍微跟踪一下代码,会发现,在“008神器”启动、启动其他应用、网络状态变化、调用工具箱修改了系统属性值时,验证“008神器”的签名时,等等,都会触发这个线程,调用postMessage()方法,向http://120.24.74.141服务器发送特定数据。以启动“008神器”应用发送的数据为例:

    启动时发送的数据是手机的IMEI、系统版本号、系统版本名称。其他不一一列举。

    原来异常是和我们的应用没有关系的,可以这样验证:卸载我们的应用,单独运行“008神器”时,log中依然会不停的报com.lishu.net.LishuNet$2的这个异常。

    Bugly中报这个异常,极有可能是因为,bugly统计平台的SDK在安卓系统log中恰巧同时检测到了com.chebada,和com.lishu.net.LishuNet抛出的异常,就将两者结合,视为com.chebada的bug了。这也可以解释,为什么几千条LishuNet$2抛出的异常,没有统一的错误信息。后续有时间再反编译看看bugly统计SDK的代码,验证一下。

    至于解决方法,实现起来就简单了,既然改不了框架层的东西,就在应用层修改。在应用启动时判断,如果存在“008神器”或“008神器工具箱”,就退出应用。OK,打完收工。

    当然,如果使用008神器或者xposed框架接口,在系统服务层API屏蔽了008神器应用,那使用这种方式就不起作用了。

    附:

    “008神器”工作原理引起了我的好奇,各种改系统功能是怎么实现的呢?经过学习发现,是利用了xposed框架,而xposed框架是需要root权限才能正常运行的,这也解释了为什么报这个crash的设备全部都是root过的了,没有root权限,“008神器”就没法正常工作。

    Xposed框架是开源的,不过作者(也是Supersu的作者)好久没有更新了,所以该框架只支持安卓4.0.3-4.4版本的系统,这个可以解释统计平台设备版本分布情况:安卓系统4.4版本以上信息不会报这个异常。

    有兴趣的同学可以学习研究下这个框架,框架基本原理是修改了安卓系统的心脏zygote,等于在安卓的Java虚拟机上加了一个接口,这个接口为框架修改系统、提供系统级的服务提供了支持,当然,如果拿来搞破坏,其威力也是相当惊人的,可以在应用不知情的情况下,肆意获取输入的用户名、密码等敏感信息。下图是我写的框架Demo程序运行结果截图,拦截了应用登录页面输入的用户名、密码信息:

    经本人实验,不修改第三方应用、不经用户同意,就可以在应用运行时动态拦截、修改应用的数据,并完全可以做到开启后台线程,将用户的数据发送至特定的服务器。

  • 相关阅读:
    我的浏览器收藏夹分类
    我的浏览器收藏夹分类
    Java实现 LeetCode 318 最大单词长度乘积
    Java实现 LeetCode 318 最大单词长度乘积
    Java实现 LeetCode 318 最大单词长度乘积
    Java实现 LeetCode 316 去除重复字母
    Java实现 LeetCode 316 去除重复字母
    Java实现 LeetCode 316 去除重复字母
    Java实现 LeetCode 315 计算右侧小于当前元素的个数
    Java实现 LeetCode 315 计算右侧小于当前元素的个数
  • 原文地址:https://www.cnblogs.com/areful/p/10399409.html
Copyright © 2020-2023  润新知