fps meter是常用的检测帧率的软件,该软件需要root权限才能工作,一直比较好奇它一个apk是如何知道系统当前的帧率情况的,就针对此apk分析了一下其工作原理。

Apk组成

首先看一下apk的组成,apk文件就是一个压缩包,可以解压缩软件如winrar解压查看,也可以用[apktools]反编译apk,以供进一步分析。

从运行结果和代码组织上的推测

  • java代码主要负责上层控制和显示。
  • bin0和lib0.so是一个真正获取fps的binary工作进程的代码
  • jni层的libnp_read.so,负责和工作进程桥接,通过pipe与工作进程通信,上报分析的数据给java层显示。

Apk的静态分析

Apk的包组成结构如上图。常规的dex/res/lib目录下的内容外,还要看一下res/raw和assets目录下是否有东西,这里通常是藏污纳垢的场所。fps meter这个apk中,在res/raw/下有bin0和lib0.so 两个文件。

使用[dex2jar]反编译java代码,查看其中的信息。对于这个apk,可以看到它使用了[RootTools]的jar库,来实现通过su过的shell执行一些命令或binary程序。从dex文件的常量字符中可以看到,这个apk中使用的库是v2.2版本,该版本的源码可以在[https://code.google.com/p/roottools/source/checkout]下载到到,svn版本号是208。

Java代码:

接下来我们可以分析java代码。java代码都已经被加扰过了,不过如果你有足够的耐心并足够仔细,还是能从中读出很多内容。对java代码的分析,一般都是从activity/Application或service的onCreate方法入手(对外的接口不可能加扰,这些方法还是存在的),可以对照AndroidManifest.xml找到入口的Activity及Service,再查看相关信息

在FPSMActivity的onCreate中,如下两句:

t.a(this, 2131034112, "0", "744");
t.a(this, 2131034113, "0.so", "744");

这是混淆过的代码,不过从参数来分析,这是调用RootTools的installBinary()方法,可以直接对照RootTools的源码来看。这个方法的作用是将apk的res/raw下的bin0和lib0.so分别安装到/data/data/com.aatt.fpsm/files/下,分别命名为0和0.so。

FPSMService的onStartCommand方法中,可以看到这个机制就是创建一个pipe:/data/data/com.aatt.fpsm/pipe,不停的从这个pipe中读取数据,显示在前端创建的的浮动window中。可以在adb shell中,

busybox dumphex /data/data/com.aatt.fpsm/pipe

验证帧率的值,刚好是从这个pipe中读入的。

其他位置未看到特别有用的信息。

JNI代码:

Jni库libnp_reader的分析,主要是一些Java的native方法的实现,并没有看到特别异常的现象。

$ arm-linux-androideabi-readelf -s libnp_read.so  

Symbol table '.dynsym' contains 69 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 00000000 0 NOTYPE LOCAL DEFAULT UND
1: 00000000 0 FUNC GLOBAL DEFAULT UND __cxa_finalize
2: 00000000 0 FUNC GLOBAL DEFAULT UND __cxa_atexit
3: 00000ed5 32 FUNC GLOBAL DEFAULT 7 Java_com_aatt_fpsm_FPSMSe
4: 00000000 0 FUNC GLOBAL DEFAULT UND umask
5: 00000000 0 FUNC GLOBAL DEFAULT UND mknod
6: 000017c4 8 FUNC WEAK DEFAULT 7 __aeabi_unwind_cpp_pr1
7: 00000ef5 16 FUNC GLOBAL DEFAULT 7 Java_com_aatt_fpsm_FPSMSe
8: 00000000 0 FUNC GLOBAL DEFAULT UND remove
9: 00000f05 40 FUNC GLOBAL DEFAULT 7 Java_com_aatt_fpsm_FPSMSe
10: 00000000 0 FUNC GLOBAL DEFAULT UND read
11: 00004004 4 OBJECT GLOBAL DEFAULT 16 fd
12: 00004008 4 OBJECT GLOBAL DEFAULT 16 trash
13: 000017cc 8 FUNC GLOBAL DEFAULT 7 __aeabi_unwind_cpp_pr0
14: 00000f2d 36 FUNC GLOBAL DEFAULT 7 Java_com_aatt_fpsm_FPSMSe
15: 00000000 0 FUNC GLOBAL DEFAULT UND open
16: 00000f51 20 FUNC GLOBAL DEFAULT 7 Java_com_aatt_fpsm_FPSMSe
17: 00000000 0 FUNC GLOBAL DEFAULT UND close
18: 00000f65 36 FUNC GLOBAL DEFAULT 7 Java_com_aatt_fpsm_FPSMSe
19: 0000400c 4 OBJECT GLOBAL DEFAULT 16 value
20: 00004004 0 NOTYPE GLOBAL DEFAULT ABS _edata
21: 00004004 0 NOTYPE GLOBAL DEFAULT ABS __bss_start
22: 00004010 0 NOTYPE GLOBAL DEFAULT ABS _end
23: 00000000 0 FUNC WEAK DEFAULT UND __gnu_Unwind_Find_exidx
24: 00000000 0 FUNC GLOBAL DEFAULT UND abort
25: 00000000 0 FUNC GLOBAL DEFAULT UND memcpy
26: 000017bc 8 FUNC WEAK DEFAULT 7 __aeabi_unwind_cpp_pr2
27: 00001d88 0 FUNC GLOBAL DEFAULT 7 __gnu_Unwind_Restore_VFP_
28: 00001d78 0 FUNC GLOBAL DEFAULT 7 __gnu_Unwind_Restore_VFP
29: 00001d98 0 FUNC GLOBAL DEFAULT 7 __gnu_Unwind_Restore_VFP_
30: 00001da8 0 FUNC GLOBAL DEFAULT 7 __gnu_Unwind_Restore_WMMX
31: 00001e30 0 FUNC GLOBAL DEFAULT 7 __gnu_Unwind_Restore_WMMX
32: 00001d64 20 FUNC GLOBAL DEFAULT 7 restore_core_regs
33: 0000134c 68 FUNC GLOBAL DEFAULT 7 _Unwind_VRS_Get
34: 000013b8 68 FUNC GLOBAL DEFAULT 7 _Unwind_VRS_Set
35: 00000000 0 NOTYPE WEAK DEFAULT UND __cxa_begin_cleanup
36: 00000000 0 NOTYPE WEAK DEFAULT UND __cxa_type_match
37: 00001f64 916 FUNC GLOBAL DEFAULT 7 __gnu_unwind_execute
38: 00000000 0 NOTYPE WEAK DEFAULT UND __cxa_call_unexpected
39: 000017d4 856 FUNC GLOBAL DEFAULT 7 _Unwind_VRS_Pop
40: 00001d90 0 FUNC GLOBAL DEFAULT 7 __gnu_Unwind_Save_VFP_D
41: 00001d80 0 FUNC GLOBAL DEFAULT 7 __gnu_Unwind_Save_VFP
42: 00001da0 0 FUNC GLOBAL DEFAULT 7 __gnu_Unwind_Save_VFP_D_1
43: 00001dec 0 FUNC GLOBAL DEFAULT 7 __gnu_Unwind_Save_WMMXD
44: 00001e44 0 FUNC GLOBAL DEFAULT 7 __gnu_Unwind_Save_WMMXC
45: 00001b2c 8 FUNC GLOBAL DEFAULT 7 _Unwind_GetCFA
46: 00001b34 164 FUNC GLOBAL DEFAULT 7 __gnu_Unwind_RaiseExcepti
47: 00001bd8 28 FUNC GLOBAL DEFAULT 7 __gnu_Unwind_ForcedUnwind
48: 00001bf4 108 FUNC GLOBAL DEFAULT 7 __gnu_Unwind_Resume
49: 00001c60 32 FUNC GLOBAL DEFAULT 7 __gnu_Unwind_Resume_or_Re
50: 00001c80 4 FUNC GLOBAL DEFAULT 7 _Unwind_Complete
51: 00001c84 32 FUNC GLOBAL DEFAULT 7 _Unwind_DeleteException
52: 00001ca4 192 FUNC GLOBAL DEFAULT 7 __gnu_Unwind_Backtrace
53: 00001d64 20 FUNC GLOBAL DEFAULT 7 __restore_core_regs
54: 00001e58 36 FUNC GLOBAL DEFAULT 7 ___Unwind_RaiseException
55: 00001e58 36 FUNC GLOBAL DEFAULT 7 _Unwind_RaiseException
56: 00001e7c 36 FUNC GLOBAL DEFAULT 7 ___Unwind_Resume
57: 00001e7c 36 FUNC GLOBAL DEFAULT 7 _Unwind_Resume
58: 00001ea0 36 FUNC GLOBAL DEFAULT 7 ___Unwind_Resume_or_Rethr
59: 00001ea0 36 FUNC GLOBAL DEFAULT 7 _Unwind_Resume_or_Rethrow
60: 00001ec4 36 FUNC GLOBAL DEFAULT 7 ___Unwind_ForcedUnwind
61: 00001ec4 36 FUNC GLOBAL DEFAULT 7 _Unwind_ForcedUnwind
62: 00001ee8 36 FUNC GLOBAL DEFAULT 7 ___Unwind_Backtrace
63: 00001ee8 36 FUNC GLOBAL DEFAULT 7 _Unwind_Backtrace
64: 000022f8 64 FUNC GLOBAL DEFAULT 7 __gnu_unwind_frame
65: 00002338 44 FUNC GLOBAL DEFAULT 7 _Unwind_GetRegionStart
66: 00002364 56 FUNC GLOBAL DEFAULT 7 _Unwind_GetLanguageSpecif
67: 0000239c 8 FUNC GLOBAL DEFAULT 7 _Unwind_GetDataRelBase
68: 000023a4 8 FUNC GLOBAL DEFAULT 7 _Unwind_GetTextRelBase

从elf信息可以见到,这个库主要是JNI的实现及将unwind实现包含在库中,unwind库一般是用作异常处理的,用它可以获取函数的调用栈信息。

这里由于使用pipe,则怀疑这里需要跨进程通信;而此pipe的通信使用是apk私有的pipe,则推论此apk通过rootTool中提供的Shell类来运行su后的shell,su的作用是通过linux开的后门,允许用户程序通过setuid系统调用,更改用户id,达到root效果。su root后,执行一个native程序,native程序应该就是res/raw/下的bin0。初步怀疑pipe的写端是这个bin0,bin0的symbol信息:

$ readelf.exe -s bin0

Symbol table '.dynsym' contains 32 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 00000000 0 NOTYPE LOCAL DEFAULT UND
1: 00000000 0 FUNC GLOBAL DEFAULT UND __libc_init
2: 00000000 0 FUNC GLOBAL DEFAULT UND __cxa_atexit
3: 00000000 0 FUNC GLOBAL DEFAULT UND snprintf
4: 00000000 0 FUNC GLOBAL DEFAULT UND fopen
5: 00000000 0 FUNC GLOBAL DEFAULT UND fgets
6: 00000000 0 FUNC GLOBAL DEFAULT UND strstr
7: 00000000 0 FUNC GLOBAL DEFAULT UND strtok
8: 00000000 0 FUNC GLOBAL DEFAULT UND strtoul
9: 00000000 0 FUNC GLOBAL DEFAULT UND fclose
10: 00000000 0 FUNC GLOBAL DEFAULT UND __stack_chk_fail
11: 00000000 0 OBJECT GLOBAL DEFAULT UND __stack_chk_guard
12: 00000000 0 FUNC GLOBAL DEFAULT UND memcpy
13: 00000000 0 FUNC GLOBAL DEFAULT UND ptrace
14: 00000000 0 FUNC GLOBAL DEFAULT UND waitpid
15: 00000000 0 FUNC GLOBAL DEFAULT UND opendir
16: 00000000 0 FUNC GLOBAL DEFAULT UND readdir
17: 00000000 0 FUNC GLOBAL DEFAULT UND atoi
18: 00000000 0 FUNC GLOBAL DEFAULT UND sprintf
19: 00000000 0 FUNC GLOBAL DEFAULT UND strcmp
20: 00000000 0 FUNC GLOBAL DEFAULT UND closedir
21: 00000000 0 FUNC GLOBAL DEFAULT UND dlsym
22: 00000000 0 FUNC GLOBAL DEFAULT UND strlen
23: 0000c000 0 NOTYPE GLOBAL DEFAULT ABS _edata
24: 0000c000 0 NOTYPE GLOBAL DEFAULT ABS __bss_start
25: 0000c004 0 NOTYPE GLOBAL DEFAULT ABS _end
26: 00000000 0 FUNC WEAK DEFAULT UND __gnu_Unwind_Find_exidx
27: 00000000 0 FUNC GLOBAL DEFAULT UND abort
28: 00000000 0 FUNC GLOBAL DEFAULT UND raise
29: 00000000 0 NOTYPE WEAK DEFAULT UND __cxa_begin_cleanup
30: 00000000 0 NOTYPE WEAK DEFAULT UND __cxa_type_match
31: 00000000 0 NOTYPE WEAK DEFAULT UND __cxa_call_unexpected

我们通过ps来看一下运行时的进程情况,并没有看到此bin0进程,看样子不像是常驻内存的,那么它太不可能是pipe的write端。

从elf的symbol来看,此bin文件应该会使用dlsym和ptrace。使用ptrace的话,基本可以确定,这个bin文件会通过PTRACE_ATTACH到别的进程中,然后修改别的进程数据或代码,以达到自己的目的。ptrace的执行过程应该就是分析的关键,接下来需要从ptrace入手。

小结

这个fps meter没有按照android应用程序的开发规范,通过使用SDK和NDK开发java和jni代码实现,而是使用第三方库,通过su获取root权限,执行自己的可执行binary程序,apk自己实现的库或binary程序,以android资源的形式打包在apk中。这种运行方式,对用户安全及系统稳定来说,是一个危险的动作。

本小结简单了解了此apk的内容,下节将详细介绍下apk资源包中bin文件通过ptrace感染android系统进程的过程。

android应用程序fps meter[帧数显示]的分析 —— 浅谈root的风险 (1)的更多相关文章

  1. android应用程序fps meter[帧数显示]的分析 —— 浅谈root的风险 (3)

    上节已经详细说了下注入过程,最后寄生进程在宿主进程中下了个蛋,这下完的蛋有什么作用呢?接下来再具体分析一下. lib0的感染过程分析 对于本例注入的so动态库,首先看一下so的符号: $ readel ...

  2. Android应用程序键盘(Keyboard)消息处理机制分析

    在Android系统中,键盘按键事件是由WindowManagerService服务来管理的,然后再以消息的形 式来分发给应用程序处理,不过和普通消息不一样,它是由硬件中断触发的:在上一篇文章< ...

  3. android studio 程序真机执行中文显示乱码

    代码里中文显示正常,真机执行后中文显示乱码,解决的方法: build.gradle中加入一句 android { compileOptions.encoding = "GBK" }

  4. 【Android测试】【第三节】ADB——源码浅谈

    ◆版权声明:本文出自carter_dream的博客,转载必须注明出处. 转载请注明出处:http://www.cnblogs.com/by-dream/p/4651724.html 前言 由于本人精力 ...

  5. app流畅度测试--使用FPS Meter

    1.FFPS Meter是一款非常实用的小软件,能够用数字实时显示安卓界面的每秒帧数,非常直观.此外,FPS Meter还可以显示最大帧数.最小帧数以及平均帧数,用来评价安卓流畅度极具价值.由于涉及到 ...

  6. Android应用程序窗口(Activity)与WindowManagerService服务的连接过程分析

    在前两文中,我们分析了Activity组件的窗口对象和视图对象的创建过程.Activity组件在其窗口对象和视图对象创建完成之后,就会请求与WindowManagerService建立一个连接,即请求 ...

  7. Android应用程序窗口(Activity)的窗口对象(Window)的创建过程分析(转)

    在前文中,我们分析了Android应用程序窗口的运行上下文环境的创建过程.由此可知,每一个Activity组件都有一个关联的ContextImpl对象,同时,它还关联有一个Window对象,用来描述一 ...

  8. Android应用程序窗口(Activity)实现框架简要介绍和学习计划

    文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/8170307 前面我们学习了SurfaceFli ...

  9. 【转】Android应用程序窗口(Activity)窗口对象(Window)创建指南

    在前文中,我们分析了Android应用程序窗口的运行上下文环境的创建过程.由此可知,每一个Activity组件都有一个关联的ContextImpl对象,同时,它还关联有一个Window对象,用来描述一 ...

随机推荐

  1. 在VS下用C语言连接SQLServer2008

    原文:在VS下用C语言连接SQLServer2008 step1:启动SQLSERVER服务 step2:打建立数据库test,在test库中建立test表(a varchar(200),b varc ...

  2. Java 设计模式 -- 示例指南

    设计模式在软件开发者中非常受欢迎的.每个设计模式都是对常见软件问题的通用的描述解决方案. 我们使用设计模式的好处有: 1.设计模式已经对于一个重复出现的问题进行了定义并且提供了工业标准的解决方案,因为 ...

  3. 【硬件】DELLserver硬件监控和DELL系统管理工具OMSA介绍

    1.1.1. DELLserver硬件监控和DELL系统管理工具OMSA介绍 本文介绍了利用使用Nagios和OMSA显示器DELLserver硬件健康状况,Nagios监控的方式是NRPE模式,须要 ...

  4. JQuery在Ajax的Post提交中国乱码的解决方案

    介绍: 在JQuery的Ajax POST要求,一个要求.中国的背景之中,乱码,如何解决呢? 问题简介: var regid = $('#oregion').combobox('getValue'); ...

  5. JSFIDDLE 动力 Threejs 功能探秘

    JSFIDDLE 助力 WebGL 功能探秘 太阳火神的漂亮人生 (http://blog.csdn.net/opengl_es) 本文遵循"署名-非商业用途-保持一致"创作公用协 ...

  6. 如何在局域网安装Redmine(转贴)

    如何在局域网安装Redmine(转贴) 分类: Redmine2009-06-01 10:31 1740人阅读 评论(0) 收藏 举报 phpmyadmin项目管理railssubversion数据库 ...

  7. Object.prototype.propertyIsEnumerable

    语法: obj.propertyIsEnumerable(prop); 此方法返回一个布尔值,表明指定的属性名是否是当前对象可枚举的自身属性. 1.如果是用户自定义了对象的属性,将返回true,比如 ...

  8. Wookmark-jQuery-master 瀑布流插件

    Wookmark-jQuery-master 瀑布流插件使用介绍,含个人测试DEMO 要求 必备知识 本文要求基本了解 Html/CSS,  JavaScript/JQuery. 开发环境 Dream ...

  9. Effective C++(15) 在资源管理类中提供对原始资源的访问

      问题聚焦:     资源管理类是为了对抗资源泄露.     如果一些函数需要访问原始资源,资源管理类应该怎么做呢?        关于资源管理的概念总是显得那么的高大上,其实只是抽象一点. 下面用 ...

  10. jQuery中Ajax的应用

    一.Ajax介绍 1.什么是Ajax 异步的JavaScript与XML技术,是一种广泛应用在浏览器的网页开发技术. 2.Ajax的优点 a.不需要任何浏览器插件,在任何支持JavaScript的浏览 ...