2016年9月1日星期四

ANDROID 逆向学习笔记 (一)- smali 简单介绍


由于 Web 安全相对来二进制来说更容易上手,最早的时候选择了相对简单的路。随着接触的时间变长,感觉局限于 Web 而抵触二进制实在狭隘,同时也是生活的百无聊赖给了充足的时间,开始尝试学一些新的事物。


在此之前没有接触过安卓或者是 Java 方面的内容,学起来难免有些迟钝,不过好在时间很多~

OK,闲扯到此结束,q

我是通过《Android 软件安全与逆向分析》这本书结合网上的资源(Drops/Pediy/博客)来开始学习的。书能够给予部分基础知识的详解,而网上的资源则大多偏向于实践,针对具体某个apk进行分析,结合起来学习加上自己亲身实践效果很好。不过有一点需要指出的是《Android 软件安全与逆向分析》中的内容并不完全正确,有描述不准确或是明显有错误的地方最好是多印证。

BTW,为了节省时间部分显而易见的地方只做简单的文字说明,可以通过自己实践或者是简单的搜索解决问题,除非必要关键的地方不上传步骤图。另外本文中操作系统为 OS X,部分终端指令与其他系统有所差异 。

接触安卓逆向最早了解到的是 smali,smali 具体定义是什么不过分追究了,先来看一下语法,下面代码用的是 安卓动态调试七种武器之长生剑 - Smali Instrumentation 中的内容。

package com.mzheng; # JAVA 源代码

public class MZLog {

    public static void Log(String tag, String msg)
    {
        Log.d(tag, msg);
    }

    public static void Log(Object someObj)
    {
        Log("mzheng", someObj.toString());
    }

    public static void Log(Object[] someObj)
    {
        Log("mzheng",Arrays.toString(someObj));
    }

}
对应的 smali 代码
.class public Lcom/mzheng/MZLog; # class的名字
.super Ljava/lang/Object;  #这个类继承的对象
.source "MZLog.java" # java的文件名


# direct methods #直接方法
.method public constructor ()V  #这是class的构造函数实现
    .registers 1 #这个方法所使用的寄存器数量

    .prologue  # prologue并没有什么用
    .line 7 #行号
    invoke-direct {p0}, Ljava/lang/Object;->()V #调用Object的构造方法,p0相当于"this" 指针
    return-void #返回空
.end method

.method public static Log(Ljava/lang/Object;)V # Log(Object)的方法实现
    .registers 3
    .param p0, "someObj"    # Ljava/lang/Object; 参数信息

    .prologue
    .line 16
    const-string v0, "mzheng"  #给v0赋值”mzheng”

    invoke-virtual {p0}, Ljava/lang/Object;->toString()Ljava/lang/String; #调用toString()函数

    move-result-object v1 #将toString()的结果保存在v1

    invoke-static {v0, v1}, Lcom/mzheng/MZLog;->Log(Ljava/lang/String;Ljava/lang/String;)V #调用MZLog的另一个Log函数,参数是v0和v1

    .line 17
    return-void
.end method

.method public static Log(Ljava/lang/String;Ljava/lang/String;)V #Log(String, String)的方法实现
    .registers 2
    .param p0, "tag"    # Ljava/lang/String;
    .param p1, "msg"    # Ljava/lang/String;

    .prologue
    .line 11
    invoke-static {p0, p1}, Landroid/util/Log;->d(Ljava/lang/String;Ljava/lang/String;)I #调用android API里的Log函数实现Log功能

    .line 12
    return-void
.end method

.method public static Log([Ljava/lang/Object;)V #Log(Object[])函数实现 ‘[’符号是数组的意思
    .registers 3
    .param p0, "someObj"    # [Ljava/lang/Object;

    .prologue
    .line 21
    const-string v0, "mzheng"

    invoke-static {p0}, Ljava/util/Arrays;->toString([Ljava/lang/Object;)Ljava/lang/String;  #将Object数组转换为String

    move-result-object v1 #转换后的结果存在v1中

    invoke-static {v0, v1}, Lcom/mzheng/MZLog;->Log(Ljava/lang/String;Ljava/lang/String;)V #调用Log(String, String)函数

    .line 22
    return-void
.end method
可以看到 smali 相对于 JAVA 源代码来说虽然复杂了一点,但是比二进制文件逆向得到的汇编代码简单和直观的多,可读性还是很高的。smali 的具体语法和格式在上面已经很清楚了,更加详细的也在《Android 软件安全与逆向分析》中有所说明,这里不加赘述。

知道了 smali 是什么东西之后再来看看它是怎么来的。每个安卓 apk 其实都是一个压缩文件,解压缩之后可以看到有一个 classes.dex ,而反编译 classes.dex 即可得到很多 smali 文件。

反编译 classes.dex 的方法我这里使用的是 baksmali,反编译后会在当前目录生成一个 out 文件夹,smali 文件就在这个文件夹里。
https://bitbucket.org/JesusFreke/smali/downloads
baksmali classes.dex

另外一种比较傻瓜的方法是直接使用 apktool 反编译整个 apk 文件,反编译后会在当前目录生成 crackme 文件夹,下面有一个 smali 子文件夹就存放了 smali 文件。

brew install apktool
apktool d crakeme.apk

apktool 相对于 baksmali 来说就是很多种工具的结合体,把各个步骤结合起来了。推荐使用 baksmali 自己一步步动手操作,这样对各个流程能够有更清晰地认识,而 apktool 的好处是反编译得到的 xml 内容可以直接查看,通过解压缩得到的部分 xml 存在乱码的情况。

Related Posts:

  • ANDROID 逆向学习笔记 (三)- IDA 动态调试 so 前面几篇所说的均是对安卓进行 smali 静态分析的内容,本节探讨一下动态的调试和分析,将会使用到的是 IDA Pro (金山 leak)和 Android Studio 的部分工具(模拟器,ddms,adb 等)。 Android Studio 的官方网址是: https://dev… Read More
  • Android 逆向学习笔记 (七)- ELF 简单介绍现在越来越多的安卓 app 为了保证软件的安全性,会使用 NDK 来进行 Native 开发,最后会产生一个 .so 这样的 ELF 文件,通过动态加载这个 ELF 文件调用隐藏在 .so 文件里的方法。 不过有的时候经过处理的 ELF 文件直接拖入 IDA 会报错,像下面这样,如果强行在 IDA… Read More
  • Android 逆向学习笔记 (五)- ARM 和 Thumb 指令集学习学习安卓逆向,ARM 和 Thumb 是两个绕不开的内容。Thumb 可以看作是 ARM 指令集压缩形式的子集,是针对指令长度问题而提出的,它具有 16 位的指令长度(ARM:32 位),但操作数、指令地址这两项 Thumb 均和 ARM 相同,为 32 位,所以如果想要区分当前指令是 ARM 还是… Read More
  • Android 逆向学习笔记 (四)- 签名校验突破有的时候在篡改 apk 并且重新打包之后不能直接运行,此时部分情况是因为存在软件的签名校验机制。在前面几篇的学习中可以知道,软件打包之后需要重新签名才可以安装到安卓机器上,此时重新签名一般用的都是公开的  platform.x509.pem 和 platform.pk8 , 有的软件为达到… Read More
  • Android 逆向学习笔记 (六)- 安卓脱壳之 dvmDexFileOpenPartial 加壳 学习脱壳之前,首先先学习一下什么是加壳,加壳是在二进制的程序中植入一段代码,在运行的时候这段植入的代码会优先取得程序的控制权,做一些额外的工作(将原来的代码还原出来执行,以达到保护原来的代码直接暴露的问题)。大多数病毒就是基于此原理。 Android 作为新兴出现的平台,加壳方式不像 PC… Read More