当前位置:安全客 >> 知识详情

安卓 Hacking Part 17 破解Android应用

2015-01-06 10:26:47 阅读:0次 收藏 来源: 360安全播报

http://p5.qhimg.com/t019f03bac693564763.jpg

本文中,我们将会介绍一些基本的模拟器检测方法并在检测到模拟器时终止程序运行。然后我会介绍攻击者如何用一些免费的工具来绕过这些检测。本文的主要目标是演示攻击者如何通过修改应用来改变其功能。

逆向工程

计算机编程中,逆向工程是一种软件分析技术,用于识别和理解应用程序,通常是为了重新实现程序,或者是仿照程序,抑或是寻找程序弱点并攻击。

Android中进行许多攻击都要求能对应用进行逆向工程,能让我们在进行攻击之前充分了解应用源代码。

检测模拟器

有些情况下开发者希望应用在模拟器中停止运行,实现的方法也很多,本文会使用一种非常简单检测技术,让应用在检测到模拟器时退出。

方法是检测Build.BRAND:

如果这句代码在基于ARM CPU的模拟器中运行,其值为”generic”,而Intel的模拟器会返回”generic_x86”。我们只需要检查该返回值,如果匹配就认为应用运行在模拟器中,显示提示信息并退出,如下图:

http://p8.qhimg.com/t012af11fb56081fcd1.png

使用APKTOOL检查应用

本部分中,我们会介绍使用流行的APKTOOL工具破解应用。

准备:

1、   一台Ubuntu主机

2、   下载JDK-其中包括keytool、jarsigner等工具-对app签名的时候会用得到

3、   APKTOOL下载地址:http://code.google.com/p/android-apktool/downloads/list

1、   下载应用,与APKTOOL放在同一目录:

http://p2.qhimg.com/t011862c96d440a90ab.png

这里我建立了一个”reserverme”目录,用到的所有文件都放在这个目录里,APK下载:

反编译应用

能完成反编译的工具有很多,本文中我们的目标是通过反编译应用找到其检测虚拟机的地方,修改代码后,重新编译。为此我们需要用APKTOOL,因为dex2jar之类的工具不能重编译。

使用下面的命令反编译:

./apktool d [appname].apk

http://p7.qhimg.com/t01226ca7c33d2d81bb.png

该命令会创建一个新目录,其中包含了反编译后的文件:AndroidManifest.xml,smali文件等,如下图:

http://p9.qhimg.com/t0194dee68c4ef68f8f.png

Smali代码实际上是Android应用的Java字节码,称作baksmaling。Smali类似汇编语言,本系列稍后会有深入的研究。我们现在的目标是破解我们的应用,首先看看反编译生成的smali代码,目录结构如下:

http://p1.qhimg.com/t011554d64f02551069.png

反编译产生的smali代码地址:

ReverseMe -> smali -> com -> androidpentesting -> reverseme

检查MainActivity.smali文件:

http://p8.qhimg.com/t01f1fcf82ea4576696.png

如上图,这个Activity中定义了两个字符串。

brandARM = “generic”
brandINTEL = “generic_x86″

稍微向下滚动,就会看到如下代码,使用checkemulator()方法进行模拟器检测:

.method private checkifemulator()V

该方法使用Build类读取设备BRAND:

.method private checkifemulator()V
    .locals 5
    .prologue
    .line 29
    sget-object v1, Landroid/os/Build;->BRAND:Ljava/lang/String;
    .line 30
    .local v1, output:Ljava/lang/String;
    iget-object v2, p0, Lcom/androidpentesting/reverseme/MainActivity;->brandARM:Ljava/lang/String;
    invoke-virtual {v1, v2}, Ljava/lang/String;->contentEquals(Ljava/lang/CharSequence;)Z
    move-result v2
    if-nez v2, :cond_0
    iget-object v2, p0, Lcom/androidpentesting/reverseme/MainActivity;->brandINTEL:Ljava/lang/String;
    invoke-virtual {v1, v2}, Ljava/lang/String;->contentEquals(Ljava/lang/CharSequence;)Z
    move-result v2
    if-eqz v2, :cond_1
    .line 32
    :cond_0
    new-instance v0, Landroid/os/Handler;
    invoke-direct {v0}, Landroid/os/Handler;-><init>()V
    .line 33
    .local v0, handler:Landroid/os/Handler;
    new-instance v2, Lcom/androidpentesting/reverseme/MainActivity$1;
    invoke-direct {v2, p0}, Lcom/androidpentesting/reverseme/MainActivity$1;-><init>(Lcom/androidpentesting/reverseme/MainActivity;)V
    .line 43
    const-wide/16 v3, 0x64
    .line 33
    invoke-virtual {v0, v2, v3, v4}, Landroid/os/Handler;->postDelayed(Ljava/lang/Runnable;J)Z
    .line 45
    invoke-virtual {p0}, Lcom/androidpentesting/reverseme/MainActivity;->getBaseContext()Landroid/content/Context;
    move-result-object v2
    const-string v3, "We are sorry, terminating"
    const/16 v4, 0x64
    invoke-static {v2, v3, v4}, Landroid/widget/Toast;->makeText(Landroid/content/Context;Ljava/lang/CharSequence;I)Landroid/widget/Toast;
    move-result-object v2
    invoke-virtual {v2}, Landroid/widget/Toast;->show()V
    .line 49
    .end local v0           #handler:Landroid/os/Handler;
    :cond_1
    return-void
.end method

代码中使用”android.os.Build.BRAND”读取设备BRAND信息。

然后检查该值是否等于”generic”或”generic_x86”,如果等于其中一个,应用就弹出提示信息并退出。

上面的代码中,我们还看到了字符串”We are sorry, terminating”:

http://p9.qhimg.com/t01fa90929d3e300ac2.png

该字符串会被显示在toast上。

http://p0.qhimg.com/t0184a1976393bf7685.png

修改代码

现在我们尝试修改应用的执行流程,最简单的办法就是修改相关的字符串,我将两个字符串都修改未如下:

http://p3.qhimg.com/t014ed9e47dcd08d486.png

如图,代码会分别与”generic0x00”和”generic_x86-64”比较,修改后的值永远都不会被匹配到,我们就成功绕过了模拟器检测。

重编译

对代码进行了修改后,我们能重新编译生成apk,这是APKTOOL最重要的特性。

使用一下命令重编译

apktool b [path to the folder with app contents]

apktool使用”aapt”构建apk中的资源,如下图:

http://p3.qhimg.com/t01b159be1b649756e8.png

如上图,APKTOOL将所有文件都打包到apk中。

生成的apk文件默认保存在”dist”目录中:

http://p0.qhimg.com/t014d212f9ee53afe33.png

重新安装

在将修改后的apk重新安装到模拟器之前,需要卸载之前安装的应用。

使用以下命令安装

adb install [filename].apk

http://p2.qhimg.com/t01ff41109c5a3068c6.png

如图,安装报错:[INSTALL_PARSE_FAILED_NO_CERTIFICATES] 这是应为重编译后还没有对apk签名。

Android要去所以的应用在安装前都需要进行数字签名。

我们可以用一个自签名证书对应用进行签名。

对应用签名-使用命令行

         对应用签名,我们首先需要生产一个证书,然后用这个生成的证书对应用签名。这里我们使用”keytool”工具生成证书,使用”jarsigner”对应用签名,这两个工具都包含在JDK中。

我创建了一个”sign”目录,来进行以下操作。

下面开始对应用签名

生成私钥

首先创建一个”key”目录,并运行以下命令:

Keytool –genkey –alias key.keystore –keyalg RSA –validity 20000 –keystore key/key.keystore

该命令会要去用户输入以下详细信息,包括密码。

如下:

http://p6.qhimg.com/t01bdfcde050aa802db.png

该命令会生成一个”key.keystore”文件:

http://p4.qhimg.com/t0182921de7556ed6ea.png

该文件是一个keystore文件,包含生成的私钥,有效期20000天。

我们使用这个文件来对app签名。

对app签名

使用”jarsigner”和之前生成的key文件对应用签名,命令如下:

Jarsigner –verbose –sigalg SHA1withRSA –digestalg SHA1 –keystore key/key.keystore ReverseMe.apk key.keystore

http://p5.qhimg.com/t013569d37944b6623d.png

如上图,jarsinger要求输入密码,签名之后,apk就可以发布了。

可以用jarsigner检查应用是否经过了签名:

jarsigner -verify -verbose -certs my_application.apk
srini@srini:~/sign$ jarsigner -verify -verbose -certs ReverseMe.apk
         772 Mon Dec 08 00:53:08 IST 2014 META-INF/MANIFEST.MF
         893 Mon Dec 08 00:53:08 IST 2014 META-INF/KEY_KEYS.SF
         894 Mon Dec 08 00:53:08 IST 2014 META-INF/KEY_KEYS.RSA
sm      5964 Mon Dec 08 00:41:22 IST 2014 res/drawable-hdpi/ic_launcher.png
      X.509, CN=srini, OU=isi, O=isi, L=notsure, ST=notsure, C=in
      [certificate is valid from 8/12/14 12:49 AM to 10/9/69 12:49 AM]
sm      3112 Mon Dec 08 00:41:22 IST 2014 res/drawable-mdpi/ic_launcher.png
      X.509, CN=srini, OU=isi, O=isi, L=notsure, ST=notsure, C=in
      [certificate is valid from 8/12/14 12:49 AM to 10/9/69 12:49 AM]
sm      9355 Mon Dec 08 00:41:22 IST 2014 res/drawable-xhdpi/ic_launcher.png
      X.509, CN=srini, OU=isi, O=isi, L=notsure, ST=notsure, C=in
      [certificate is valid from 8/12/14 12:49 AM to 10/9/69 12:49 AM]
sm     17889 Mon Dec 08 00:41:22 IST 2014 res/drawable-xxhdpi/ic_launcher.png
      X.509, CN=srini, OU=isi, O=isi, L=notsure, ST=notsure, C=in
      [certificate is valid from 8/12/14 12:49 AM to 10/9/69 12:49 AM]
sm      1176 Mon Dec 08 00:41:22 IST 2014 res/layout/activity_main.xml
      X.509, CN=srini, OU=isi, O=isi, L=notsure, ST=notsure, C=in
      [certificate is valid from 8/12/14 12:49 AM to 10/9/69 12:49 AM]
sm       464 Mon Dec 08 00:41:22 IST 2014 res/menu/main.xml
      X.509, CN=srini, OU=isi, O=isi, L=notsure, ST=notsure, C=in
      [certificate is valid from 8/12/14 12:49 AM to 10/9/69 12:49 AM]
sm      1728 Mon Dec 08 00:41:22 IST 2014 AndroidManifest.xml
      X.509, CN=srini, OU=isi, O=isi, L=notsure, ST=notsure, C=in
      [certificate is valid from 8/12/14 12:49 AM to 10/9/69 12:49 AM]
sm    579200 Mon Dec 08 00:41:22 IST 2014 classes.dex
      X.509, CN=srini, OU=isi, O=isi, L=notsure, ST=notsure, C=in
      [certificate is valid from 8/12/14 12:49 AM to 10/9/69 12:49 AM]
sm      2284 Mon Dec 08 00:41:22 IST 2014 resources.arsc
      X.509, CN=srini, OU=isi, O=isi, L=notsure, ST=notsure, C=in
      [certificate is valid from 8/12/14 12:49 AM to 10/9/69 12:49 AM]
  s = signature was verified
  m = entry is listed in manifest
  k = at least one certificate was found in keystore
  i = at least one certificate was found in identity scope
jar verified.
srini@srini:~/sign$

重新安装

签名了app后,我们就可以安装了,现在安装就不会报错了:

http://p4.qhimg.com/t0185b2066014bf01e7.png

在模拟器中运行,并不会退出:

http://p0.qhimg.com/t0126fb460fda348707.png

总结

本文介绍了用APKTOOL修改应用的方法,如你所见,攻击者可以修改应用的功能并重新打包,这样的方法可以用来向合法应用中插入恶意代码。这要去开发者想想办法来检测应用的修改。尽管没法完全避免被修改,但却能增加攻击的难度,一个例子就是检测应用的签名是否被篡改。同时,作为用户,从第三方软件商店下载安装应用的时候也应该格外小心。

相关阅读

http://developer.android.com/tools/publishing/app-signing.html

http://www.techopedia.com/definition/3868/reverse-engineering


本文由 安全客 翻译,转载请注明“转自安全客”,并附上链接。
原文链接:http://resources.infosecinstitute.com/android-hacking-security-part-17-cracking-android-app-binaries/

参与讨论,请先 | 注册 | 匿名评论
发布
用户评论
无任何评论