作者:申迪
一、概述
这是一个rom级别的木马。木马替换系统进程debuggerd实现自启动,重启回写若干apk/jar/elf文件。支持网络和短信两种远控模式,并且带有十几个可配置参数。
只要/system/bin/debuggerd没有被清理,FakeDebuggerd就能从/system/bin/debuggerd文件尾部将所有被删除的文件重新释放。
而debuggerd是原生服务,本身就是开机启动进程,因此木马不需要对init.rc或者其他脚本做额外修改,这样整个行为会更加隐蔽。
FakeDebuggerd加密所有字符串,回写时修复文件创建时间,即使木马apk被发现,也不能通过在目录中暴力搜索字符串来找到作恶的源头/system/bin/debuggerd。从恶意行为上看,该木马具有回写推广widget、篡改默认浏览器主页、静默安装apk,窃取用户手机号、硬件编号、地理位置等恶意行为,木马作者还可以根据回传的手机号单独下发控制配置。
该样本的衍生程序早期变种在2011年末就被发现,本次发现的是其最新变种。目前360已经能够彻底查杀。(专杀工具下载)
二、追根溯源
起初通过pm命令我只能发现可疑系统程序的路径在 /system/framework/AndroidSecurity.apk
然后我尝试使用 pm uninstall 删除,重启之后这个apk又出现了,于是怀疑有固件级别的程序在回写这个apk。
通过查看init.rc 、svc等多个启动脚本,都没有发现异常。在system分区搜索文件的敏感字符串,也没有结果。
于是开始逆向AndroidSecurity.apk,程序多次调用socketWork连接localsocket,发送命令,这和Oldboot机制类似:
找到local socket的源头很容易:首先取得socket的inode。
然后查找引用了这个inode的进程
至此发现源头是debuggerd,通过逆向发现,debuggerd被彻底替换为木马,可以回写其他衍生程序,所以才会发生AndroidSecurity.apk杀不掉的状况
三、结构图
debuggerd 回写其他文件,执行root权限命令,更新云控配置等
divadv 使用netfilter截获数据包
sm.jar 独立进程用于拦截短信,转发给AndroidSecurity.apk
AndroidSecurity.apk 木马在java层的主程序,向debuggerd下发指令
Widgetmain.apk 一个拉广告的程序
四、流程分析
1. Debuggerd
该程序替换了系统的debuggerd,因此可以通过init.rc的配置开机启动,程序启动后自动释放所有衍生程序,实现所有程序的回写。最后进入无限循环,接收java层程序的命令执行root权限才能执行的操作命令。并且担负起更新云控文件的任务
Phase 0
将文件路径上下文切换到/data/data/com.android.xbrowser/files下,这是木马AndroidSecurity.apk的文件路径,这个文件夹下包含的云端控制命令参数和日志文件
其中1.dat是AndroidSecurity.apk收集的系统信息,由debuggerd回传至云端
2.dat是云端下发的命令,每一行是一个参数。 a.log是debuggerd打印的日志,b.log AndroidSecurity.apk使用的日志 t.dat 记录系统时间
程序接着启动被替换的原始debuggerd,原始debuggerd被命名为aee_aed,并且有一个link /system/bin/testdeb指向aee_aed
执行testdeb
Phase 1
回写所有apk/jar/elf文件,这是debuggerd的核心功能之一。文件数据存放在debuggerd文件内部,所以debuggerd有1.3M之大
这些文件的offset记录在debuggerd文件尾部0x20的地方,debuggerd使用inflate解压数据到系统中进行回写,并且篡改文件的创建时间
获取释放文件的offset
解压文件数据并且释放
修改文件属主、时间以掩人耳目,时间被修改为2013-04-18 15:42,即rom中/system/framework/pm.jar的生成时间
具体而言,以下是代码中写明可能释放的文件,但实际上并不是所有文件都被打包进了debuggerd,所以有些文件没有释放。推测这些没有释放的文件应用于早期版本,现在已经被去掉了。
/data/local/tmp/sm /data/local/tmp/sm.jar /system/framework/sm.jar /system/framework/AndroidSecurity.apk /system/bin/divadv /data/bin/busybox /data/bin/wget /system/framework/PowerAlarm.apk(早期变种存在此文件,没有释放) /system/bin/systemalarm(没有释放) /system/bin/alarmwatcher(没有释放)
另外debuggerd在释放apk时做了判断,针对一些特定版本的安卓系统,则释放为.lar文件
释放出sm.jar后,立即调用app_process加载jar包
fork,以system执行 :export CLASSPATH=/system/framework/sm.jar exec app_process /system/bin com.android.commands.sm.Sm “$@”
释放出 divadv,并且判断系统中netfilter启用,立即执行
Phase 2
读取2.dat的参数配置,可以启动第四行参数制定的程序
启动服务线程,服务线程循环监视系统时间,如果时间超过22时且为整点,配置更新状态为true
(Phase 3中会看到,这一步是用户当天在22时之前,从没有连接wifi的前提下触发的。如果用户联通wifi,会立即触发更新。)
并且开始上传用户隐私1.dat ,获取云端命令 2.dat
Phase 3
创建LocalSocket watchd6213,循环接收命令,命令有以下几种:
根据2.dat配置,安装elf和apk
<cmd:widget
向桌面添加widget
在/data/system/appwidgets.xml中查找默认桌面
/system/etc/customize/default_ui.sql 查询到laucher数据库 /data/data/com.android.launcher/databases/launcher.db
执行sql语句,直接向/data/data/com.android.launcher/databases/launcher.db插入数据,添加widget
<cmd:kpid$pid
杀指定进程,但如果pid是-1000,则清理所有与自己相关的木马文件,并且恢复原始debuggerd
<cmd:hpage
篡改默认浏览器首页,将结果写到 /data/data/com.android.browser/shared_prefs/com.android.browser_preferences.xml 的
<cmd:everyday
通知网络变化状况,如果当前网络变化为wifi环境,则立刻打开云控开关,那么Phase2中的线程立即开始上传用户隐私数据(1.dat),更新云端配置(2.dat)
当然云控的服务器也是可配置的,写在2.dat中
下载配置文件
2. Divadv
这个文件只有22k,debuggerd在初始化阶段调用,并且只有在/proc/net/netfilter/nfnetlink_queue存在的情况下启用,在这台测试手机上该程序跑不起来
静态分析来看,该程序使用netfilter截获数据包
iptables -I OUTPUT -p tcp -j QUEUE iptables -I INPUT -p tcp -j QUEUE
截获数据之后进行一些分析,并返回0或者1给debuggerd
如图所示,debuggerd仅仅是将返回值写入log,并没有针对返回结果进行其他处理,所以这里不深入讨论这个程序。
3. Sm.jar
短信拦截是一个敏感操作,该木马没有将这部分代码放在apk中,而是由debuggerd来启动一个jar包,并且将其pid设置为1000
export CLASSPATH=/system/framework/sm.jar.exec app_process /system/bin com.android.commands.sm.Sm "$@"
Sm.jar拦截短信控制指令,更新配置文件,并且必要时与AndroidSecurity.apk通过广播通信
拦截短信,通过广播将相应指令转发给AndroidSecurity.apk
最后来看AndroidSecurity.apk,这是最早发现问题的源头,整个apk仅由一个广播com.android.xbrowser.ABC组成。
它接收以下广播:
接收 com.htc.lucy.initalarmaction :
这个广播是机器启动时初始化时通过AlarmManager调用的,并且定时触发
在该广播触发时,将手机系统信息写入/data/data/com.android.xbrowser/files/1.dat
如果wifi环境没有开启的情况下,尝试设置APN以使用蜂窝网络
与debuggerd通信,添加Widget 到桌面
这个Widget 在/system/app/widgetmain.apk中实现
最后,还会注册一个com.htc.lucy.alarmaction reciever 定时触发
接收 com.htc.lucy.alarmaction :
与com.htc.lucy.initalarmaction类似,但是省去初始化的一些逻辑,定时监测是否需要更新配置文件2.dat,修正蜂窝网络连通性
接收 android.net.conn.CONNECTIVITY_CHANGE :
网络环境更新消息接收后,检查今天是否有尝试更新过云端配置,如果没有,向debuggerd发送消息请求更新
这时候debuggerd联网获取配置,并将配置存储在2.dat中。并且返回给AndroidSecurity.apk一个结果。如果更新成功,AndroidSecurity.apk从2.dat里面获取smskeys(短信拦截关键字),通过com.android.xbrowser.watchdapkbc广播传送给sm.jar。Sm.jar则去拦截短信指令
接收 com.android.xbrowser.smsapkbc
接收 com.android.xbrowser.sm2watchdapkbc
更新文件版本号
接收 android.intent.action.ACTION_SHUTDOWN
流量统计使用,重启之前要将本次开机之后的流量保存在1.dat中
接收 com.android.xbrowser.wapbc
来自sm.jar的查询配置文件2.dat的请求
接收 com.android.xbrowser.smresetbc
Sm.jar重新启动发来的广播,随后本apk向debuggerd发消息
通常执行的操作是杀掉com.android.poweralarm进程,当sm.jar传来特殊的指令时,此apk发送消息cmd:kpid$-1000 让debuggerd将木马彻底清除
在AndroidSecurity.apk启动时,要求debuggerd向桌面插一个widget
路径是/system/bin/widgetmain.apk 该apk没有特别的恶意行为,目的是推送广告快捷方式到桌面上
五、历史变种
通过样本AndroidSecurity.apk的包名和证书,我搜索到该样本的若干历史版本。最早期版本在2011年末出现,在此期间感染方式也有所变化:比如在早起版本中,AndroidSecurity.apk没有使用LocalSocket与debuggerd通信,后来才出现了debuggerd作为守护进程和提权后门;再如,早期也并没有sm.jar这个文件,而是使用一个叫做com.android.poweralarm的应用去拦截短信,后来显然是为了将短信拦截更为隐蔽,移到了一个jar中,通过app_porcess启动。从出现至今,该样本分别以com.android.systemsecurity、com.android.xbrowser 、com.android.poweralarm 、com.htc.systemsecurity 、com.samsung.systemsecurity 等多个包名出现在包括中兴、三星、HTC等多款手机的第三方rom中,先后使用过至少五个证书。
六、解决方案
目前,我们已经独家发布了专杀工具,下载地址是:
http://msoftdl.360.cn/mobilesafe/shouji360/360safesis/FakedbgKiller.apk
该专杀可以彻底根除FakeDebuggerd木马。同时建议用户从正规渠道购买手机,安装360手机卫士保护手机安全。如遇到病毒反复查杀、手机中静默安装软件等异常现象,及时向我们反馈。
七、结语
这是我们发现的又一个在手机系统启动阶段重新释放衍生APK程序的rootkit。与Oldboot和DroidKungfu不同,该木马没有修改启动脚本,而是选择直接替换系统进程达到自启动的目的,木马还包含强大的云控机制,有很强的扩展能力,被植入此木马的手机存在不可预估的高危风险。同时我们也注意到rom中木马逐渐增多的趋势,我们将会继续关注此类顽固木马并提供相应的解决方案。
Comments