作者:苗甦

Android在迅猛发展的同时,其安全问题一直没有引起足够的重视,但在2010年6月研究人员发布Android平台的KernelRootkit以来,Android平台的安全问题引来了越来越多的关注,而同时,Android平台的恶意软件也开始流行起来。[3]

根据以上的Android系统架构分析,可以发现在三个层面可能存在恶意软件。分别是处于最高位置的应用层(Applications),函数库层(Libraries)之上,还有Android的Linux内核中。根据编程语言的不同,也可以叫做Java层,NativeC层,Linux Kernel层[4]

Java层安全

毋庸置疑,Java层安全的恶意软件或安全软件,像普通的应用程序一样,使用Java语言开发,使用Google提供的AndroidSDK,

在恶意软件方面,无非是注册一些系统事件进行相应,比如收到短信,收到邮件等等,再就是在用户不知情的情况下侵犯手机安全,比如偷偷发短信,窃取用户位置信息,窃取用户通话等等。但是同其他Android应用程序的开发一样,这些恶意软件开发时,要为使用这些恶意功能申请权限(比如发短信权限android.permission.SEND_SMS,收短信权限android.permission.RECEIVE_SMS等等),用户在安装时对这些权限一目了然,很容易引起用户的怀疑。

而Java层的安全软件功能更是匮乏,要知道,无论是哪一个平台的安全软件,要保证用户安全,起码要拥有对其他进程的绝对控制权限,比如结束进程,开启进程,获取进程行为等等。而Android SDK并没有提供这么强大的功能,到Android SDK 2.2版本时,通过SDK提供的API,甚至无法去强制结束一个第三方软件的进程。而目前的Java层面的安全软件,只是简单的对已安装的软件进行静态扫描,搜索有没有使用可疑的权限,或者是清理一些软件的自启动行为,主动防御、行为分析等概念在Java层上几乎不存在。总而言之Java层面的安全软件被完全束缚于SDK中,而Java语言不能直接访问内存,相对于自由的C语言来说,Java语言本身就不适合开发安全软件。

Native C层安全

虽然Android平台的软件要用Java开发,但是也并非全部如此。Android底层必定是一个Linux [11],在Linux内核之上又有大量的标准C函数库,在理论上,是可以编译出可以直接依靠这些函数库运行的C语言程序的。事实上,在Android系统自身中已经存在很多这样的程序,在Android的超级终端中,我们可以像在Linux的超级终端中一样调用一些常用的命令,比如ls,ps,cd,free,等等,这样的命令在Android中有几十个。其实这些命令都存在于“/system/bin”或“/system/xbin”下,而且都是C语言编写的程序。

早在Android NDK发布以前,研究人员就已经可以利用Android的源码中的资源(.h文件等)和Linux下的编译工具(gcc,交叉编译器等)编译C语言程序,并且可以像执行这些命令一样执行这些程序,我们可以称之为Native C。

AndroidNDK的发布,使得Native C程序的开发更加方便。AndroidNDK于

2009年7月发布第一个版本(Release1),目前已经发布到第五个版本(Release5)。

Android NDK使得普通的应用程序(.apk)中可以使用库文件(.so),这些库文件用C语言编写,并且在Java语言的代码中,可以通过JNI调用C语言代码。在这些C语言代码中,可以调用一些运行时函数(printf,memcpy等等),以及一些Linux中存在的函数(ptrace,waite等等),甚至是一些Android的核心API。再加之C语言对内存有绝对的控制权限,使得一些安全技术可以在这里大展拳脚,尤其是HOOK技术,这对恶意软件还是安全软件来说,都是一件好事。Android NDK的发布不仅有利于安全编程,对于其他领域的软件,尤其是需要较高效率计算,不适宜在较高层的Java语言编写的软件,比如拥有自己核心的浏览器(火狐,Opera等)和大型游戏,NativeC都给他们带来的好消息。

在2011年三月,一个叫LBE的团队发布了一款基于主动防御的隐私安全软件,LBE隐私卫士。这是第一款正式发布的Android平台的主动防御安全软件。LBE小组曾经将Android的移植到魅族M8(原来运行Mymobile)上,其核心成员常年致力于ARM平台Linux的研究,有很扎实的Linux功底。这款LBE隐私卫士就是用Android NDK开发的,其中用到了APIHOOK技术。

关于HOOK技术:HOOK技术无论对于安全软件还是恶意软件都是十分关键的一项技术,其本质就是劫持函数调用(在Windows中,HOOK也可以理解为窗口消息劫持),不管是Windows 还是Linux平添,HOOK在安全软件中的应用都十分广泛。

NativeC层面的程序虽然是C语言,但是依然处于Android用户态,即Linux的用户态。因此NativeC层上只能对某一进程(当然也可以是所有进程)进行API HOOK。不管是Windows还是Linux,其用户态的每个进程都拥有独立的进程空间,要对其进行API HOOK必须进入其进程空间才能修改这个进程的代码,即必须有能力修改目标进程的内存。对于这一方面Windows和Linux采用了不同的方法。Windows没有API可以修改某一进程的内存,因此一般采用Dll注入(或称远程线程注入)的方法。而Linux则常用ptrace与plt实现API HOOK。

在Windows中,APIHOOK的一般流程为:

①    OpenProcess,打开目标进程。

②    获取LoadLibrary的函数地址,该函数地址一般在每个进程空间内都是相同的。

③    VirtualAllocEx,在打开的进程中申请内存。

④    WriteProcessMemory,在申请的内存中写入要注入的Dll路径字符串(此处也可以直接写入需要的代码,然后CreateRemoteThread执行来进行HOOK,此方法更加隐蔽,但更加复杂困难)。

⑤    CreateRemoteThread,启动远程线程,入口地址为LoadLibrary的函数地址,参数为要注入的Dll路径字符串(也就是远程申请的内存地址)。

⑥    注入的Dll中代码会在自身被加载时开始运行。

⑦    找到要HOOK的API所在的函数库基址。

⑧    找到要HOOK的API再其函数库中的导出表所在位置。

⑨    修改导出表,指向自己的函数入口地址。

⑩    在自己的函数中调用原API。

当然在注入成功后也可以直接修改API的开头几个字节,jmp到自己的函数,然后再jmp回去,这种方法称为InLineHOOK,InLine HOOK更不容易被检测到,但是稳定性,通用性都较差,而且操作更加复杂。

在Linux中,APIHOOK进入目标进程空间时使用了Linux中的ptrace函数[9]。ptrace函数原本是用于调试程序用的,功能十分强大,不仅可以绑定某一进程(PTRACE_ATTACH),而且可以任意修改目标进程的内存空间(PTRACE_PEEKDATA,读内存。PTRACE_POKEDATA,写内存),甚至是寄存器(PTRACE_SETREGS,PTRACE_GETREGS)。其一般过程为:

①    PTRACE_ATTACH,绑定目标进程。

②    PTRACE_GETREGS,获取目标进程寄存器状态,并保存。

③    PTRACE_PEEKDATA与PTRACE_POKEDATA配合,保存原代码,写入要注入的代码到当前运行位置。

④    PTRACE_SETREGS,恢复寄存器状态,并继续执行,这是注入的代码开始在目标进程内执行,注入代码完成HOOK,过程与Windows下相似。

⑤    在HOOK完成后,注入的代码执行int3被ptrace捕获,目标进程再次暂停执行。

⑥    PTRACE_GETREGS,再次保存寄存器。

⑦    PTRACE_PEEKDATA与PTRACE_POKEDATA配合还原代码。

⑧    PTRACE_SETREGS,恢复寄存器,目标进程继续执行。

⑨    PTRACE_DETACH,撤销绑定目标进程。

Linux下还可以LD_PRELOAD来注入代码[7]从而进行HOOK。

在前面提到的Native C级安全软件LBE隐私卫士出现后我对其实现方法进行了研究,发现了类似的方法。LBE隐私卫士中有两个用NativeC编写的函数库,分别为libloader.so和libservice.so。其中libloader.so负责将libservice.so注入到系统进程,libservice.so在注入后负责HOOK相关的API,从而实现对这些API的监控功能。在libloader.so的导出函数中可以看到以下三个函数:

其中inject_phonemgr,inject_server,inject_svcmgr三个函数分别负责将libservice.so注入到phonemgr,server,svcmgr三个系统进程中,在加载了LBE隐私卫士的Android手机中,在终端使用 cat /proc/<pid>/map(其中<pid>为三个系统进程的pid)可以在输出中看到,三个系统进程都加载了 libservice.so。这一点证实了我的推断。

而在libservice.so的函数导出表中,又可以看到以下函数:

目前只能通过函数名大体推断这些函数的具体功能,可能是通过这几个函数hook监控网络,发短信,打电话,位置服务等等功能。

通过与LBE隐私卫士的开发团队的交流,我了解到在其使用的注入技术,ptrace似乎并不起主要作用,而由于商业机密等原因,其团队并不方便透露其具体实现细节,LBE团队毕竟是Linux方面的佼佼者,我刚刚接触Linux安全,ARM汇编代码逆向能力更是有限,目前依然不能完全了解LBE的实现细节,也只能在简单分析的基础上一些猜测。

Linux Kernel 层安全

2010年8月2日,Spider Labs的安全专家在DefCon安全会议上发布了一个内核级别的Android Rootkit工具,这是Android推出以来公布的第一款Rootkit,这次演讲引起的巨大的影响,该Rootkit的源码也被收录在本次会议的CD中,此后到2011年初,Android市场上开始出现Rootkit级的恶意软件,而此时正式推出的安全软件才刚刚达到Native C的级别。其实AndroidRootkit的研究并不比Native C级别的难,SpiderLabs的安全专家曾经列出一个公式:Android == Linux == 20 year old Open Source OS。在Android的Linux内核层更是如此。大量的Linux内核安全专家,以及现有的Linux Rootkit的研究成果使AndroidRootkit的出现提前了很多。

要加载内核级Rootkit,首先要将代码放进Linux内核,在这个问题上,可以将代码编译为一个“可加载内核模块”(Loadable Kernel Module,LKM),Linux内核可以动态的加载这些LKM,它与整个Linux内核拥有同样多的权限,并通过触发器激发这些代码,只要这些代码运行起来,也就意味着有能力经劫持Linux内核,即劫持关键的Linux系统调用[10],例如进程操作,文件操作,网络操作等等,就可以任意对手机进行操作,完成任何功能,比如窃取短信,悄悄打电话,GPS定位,等等,所有这些行为都不会被用户察觉,这些Rootkit可以不被内核外的任何安全软件察觉,甚至不被内核级安全软件所擦察觉,对用户的隐私,甚至财产造成极大的威胁。

LKM加载进Linux内核后就要对系统调用进行HOOK,劫持这些调用,这这其中有以下几个难点:如何获得系统调用表(sys_call_table)的位置[5],如何在Android的源码下进行编译,如何调试这些代码。

Android采用Linux 2.6版本的内核,而2.5及更高版本的Linux内核已经不再导出sys_call_table了,这就意味着extern void *system_call_table[];并不能得到系统调用表。但是依然可以在System.map中找到sys_call_table,而且这个地址是静态的:[12]

                                                                   

图1.4 获取sys_call_table的地址

要调试Android下的Linux内核并不是一件简单的事情,为了得到sys_call_table每个具体函数名及函数地址,可以用sys_write,sys_read,sys_open,sys_close等函数输出。[12]

在这些工作完成后,就可以根据Android的源码以及这些分析结果,编写LKM,通过内核级HOOK劫持系统调用,内核级HOOK相对用户态APIHOOK更加简单,因为内核中并没有进程内存空间等概念,对所有内存有直接的访问权限,在内核级HOOK时依然可以通过修改sys_call_table或Inline HOOK两种方式,两种方式各有优缺点。

完成编写并编译后可以通过Linux下的命令工具集Busybox中的insmod来加载内核模块:

图1.5 加载LKM

该工具集中的lsmod可以列举出已经加载的内核模块,但是Rootkit中可以通过劫持相关系统调用,使自身不被lsmod列举出来,从而达到完全的隐身。[12]

由于在root权限等方面所遇到的问题,目前Android Linux Kernel级的安全软件尚属空白。

Android操作系统安全相关推荐

  1. android操作系统优势,Android操作系统平台最大的优势

    Android操作系统平台最大的优势 2015-12-25 17:10:27 1074浏览 如今移动互联网势不可挡,移动软件应用市场就像是一个巨大的金矿.发展潜力巨大,而Android开发软件平台无疑 ...

  2. 浅谈新一代Android操作系统Android L

    今天早一些的时候,Google发布了新一代Android操作系统Android L.让我非常意外的是命名规则的变化,之前外界纷纷猜测会叫Android5.0,同时会给一个甜品的名字命名.因为Andro ...

  3. Android资源分离,可分离Android操作系统报告:硬件环境检测文件(十)(分析)...

    可分离Android操作系统报告:硬件环境检测文件(十)(分析) (2018-04-18 12:23:58) 标签: it 0x38000-终  1F E0 8E 05 60 29 1C ED A8 ...

  4. Android操作系统手机遇冷 国外辉煌国内难现

    美国市场研究公司NPD近日发布的统计数据显示,今年第一季度期间,Android手机在美国市场的销量已超过iPhone,占据该季度美国智能手 机总销量的28%,iPhone相应份额为21%,北京时间5月 ...

  5. android源码中的ndk,如何在不需要Android操作系统源代码的情况下在Android NDK中创建新的NativeWindow?...

    我想编译一个Android OpenGL控制台应用程序,您可以直接从控制台启动Android x86或从Android x86 GUI中的Android终端应用程序运行.如何在不需要Android操作 ...

  6. Android* 操作系统上的应用程序远程调试

    作者:robert-mueller Android* 操作系统应用程序远程调试 Android* Debug Bridge Android Debug Bridge (ADB) 是一种命令行工具,可处 ...

  7. 使用手机模拟器与android操作系统

    创建手机模拟器: 1. 点击Eclipse中新增的按钮,打开"Android Virtual Device Manager"(不同版本的ADT可能打开路径不同),如下图: 2. 点 ...

  8. Android操作系统版本

    Android操作系统版本 Android1.1(发布于2009年2月) 主要特性: 闹钟 API示例 浏览器 计算器 摄像头 联系人 开发工具包 拨号应用 电子邮件 地图(包含街景) 信息服务 音乐 ...

  9. 适用于 PC 的最佳 Android 操作系统(2022 版)

    想知道您是否可以在 PC 上使用 Android 操作系统? 好吧,您来对了 Internet 上的位置. 您当然可以在您的 PC 上运行 Android. 我们已经尝试并测试了一些适用于 PC 的最 ...

  10. iphone上安装android系统,如何在iPhone上安装Android操作系统?

    关于"如何在iPhone上安装Android操作系统?"相关问题,库巴帮助小帮手为您解答. 本文是教各位如何安装谷歌的Android操作系统到iPhone上.事先警告,动手能力不强 ...

最新文章

  1. ASP.NET设置ie打印两法[转载]
  2. 深入理解并行编程-分割和同步设计(一)
  3. 将表中的值变成字段显示
  4. Spring Boot 2.2.0 正式发布,大幅性能提升 + Java 13 支持
  5. Windows7环境下用VirtualBox (5.1)上安装Ubuntu 17.10
  6. 查询varchar实际大小_微服务和VUE(11): mybatis 动态查询
  7. 第一百五十一期:最新计算机技能需求排名出炉:Python仅排第三,第一你猜得到吗?
  8. 对lIKE语句的优化
  9. Eclipse SonarLint 插件 “SonarLint processing file 。。。 lombok/launch/PatchFixesHider“ 解决办法
  10. [转载] python 中NumPy和Pandas工具包中的函数使用笔记(方便自己查找)
  11. Zepto:实现移动端tab选项
  12. mysql sql文件在哪里打开_mysql怎么打开sql文件
  13. EASY UI tree如何根据部分值来选中checkbox
  14. 小白量化彩票实战(1)彩票分析及爬虫双色球彩票开奖数据
  15. [渝粤教育] 北京理工大学 工程热力学 参考 资料
  16. 印尼穴居小矮人是进化异类还是病态现代人?
  17. 4条地铁线,乘船到西站!杭州西站枢纽综合交通规划设计方案出炉
  18. 宣传片后期制作的要点介绍
  19. getTasks: caller 10079 does not hold REAL_GET_TASKS; limiting output问题解决
  20. 如何解决error: failed to push some refs to ‘git@github.com:......git pull冲突问题

热门文章

  1. STM32驱动WS2812
  2. Tkinter模块GUI界面化编程实战(五)——大鱼吃小鱼游戏(含超详解及完整源码、完整程序免费下载链接)
  3. 决策树ID3详解(西瓜案例)
  4. 自学《STM32不完全手册》的笔记三
  5. 控制期货开户保证金可以降低风险
  6. Golang 031. 《孙子算经》之鸡兔同笼
  7. 小学信息技术教师面试
  8. 【Gatsby】Gatsby初体验
  9. QT MDI多文档打开图像显示
  10. 【深度学习】入门理解ResNet和他的小姨子们(一)---ResNet