2016年9月5日星期一

ANDROID 逆向学习笔记 (二)- Smali 和 Dalvik


上一篇文章说到了 apk 解压得到 classes.dex 再反编译得到 smali 代码文件,那么这个关键的 classes.dex 是什么呢?提到 .dex 那么就会想到 Dalvik,Dalvik 是谷歌专门为安卓设计的虚拟机而 .dex 之于 Dalvik 就相当于 Windows 里的 .exe,是 Dalvik 可以直接执行的格式所以分析 .dex 文件是安卓逆向很重要的一部分。

关于 Dalvik 存在的意义、运行方式和 JVM 虚拟机之间差异的问题感兴趣的可以自行搜索了解,另外在高版本的安卓系统中,谷歌已经使用 ART 代替了 Dalvik 为实现更高的效率,可能存在部分差异,后续文中如果没有特殊说明均是针对 Dalvik。

因为 classes.dex 是运行在 Dalvik 的可执行文件,所以是否熟悉 Dalvik 的操作指令是决定我们阅读反编译文件快慢的重要因素。Dalvik 全部的 OpCodes 可以在 这里 查看,另外关于 OpCodes 的解释可以看 什么是 OpCode,Dalvik 的 OpCodes 相对来说很多还是很好理解的,不过结合英文和《Android 软件安全与逆向分析》来看仍然发现部分表述不很清晰的地方,本篇主要对一些容易混淆和迷惑的地方做一个注解。

Dalvik OpCodes

iget v2, p1, Lcom/tencent/mm/sdk/modelbase/BaseResp;->errCode:I
#将 p1 中的 errCode 以 I (整型)的方式取出放在 v2 变量里,
#另外 p1 的类型是 com.tencent.mm.sdk.modlbase.BaseResp。

nop #不进行任何操作,
#不过需要注意的是有的情况不存在 nop 指令,需要使用 movs r0,r0 代替。
*put*  # 赋值操作
iput-object v0, p0, Lcom/yodo1/sdk/wxapi/WXPayEntryActivity;->api:Lcom/tencent/mm/sdk/openapi/IWXAPI;
# 将 v0 的值放入 p0 类指针指向的类的 api 元素
# 并且 v0 和 api 的类型为 com.tencent.mm.sdk.openapi.IWXAPI

invoke* # 执行方法操作
invoke-direct {p0}, Ljava/lang/Object;->()V
# 执行类指针 p0 指向的类的初始化函数,此时大括号里的内容为参数
# 即 p0,而 baksmali 反编译出来的 p0 代表的是 $this 指针

Smali Program

*field* # 定义变量
.field public static final STATUS_FAILED:I = 0x0
# 定义 STATUS_FAILED 为一个 I 型的静态变量,并且值为 0
# .field 可能会存在 synthetic 属性,而这个属性在 Java 源代码里是不会出现的,一般涌来表示继承类之间的相互关系


.class public Lcom/disney/WMW/WMWActivity;          # 当前类名
.super Lcom/disney/common/BaseActivity;             # 父类名
.source "WMWActivity.java"                          # 源文件名
.implements Lcom/burstly/lib/ui/IBurstlyAdListener; # 接口名

.locals    3 # 当前代码段使用 3 个本地变量
.registers 5 # 当前代码总共使用 5 个寄存器,包括本地变量和函数参数
# 两种命名所达到的效果一样,不同的是 .locals 声明不包括函数参数所使用的寄存器,
# 而 .registers 包含当前代码段所有使用到的寄存器。修改 smali 时需要注意使用的寄存器是否增加

.method public onResult(IILjava/lang/String;)V # 当前函数的调用参数有 4 个,分别是 p0(this->)、p1(I)、p2(I)、p3(L) 
    .locals 6                                  # V 命名法,6 个本地变量,对应的则是 .registers 10

Strings.xml

使用将 apk 解压之后得到的 res 文件夹中会存在很多 strings.xml 文件,这样的文件往往是用来将代码中的特殊字符串替换为较简单字符串。
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="yodo1_string_dialog_btn_no"></string>
    <string name="yodo1_string_dialog_btn_yes"></string>
    <string name="yodo1_string_dialog_exit_message">真的要退出游戏吗?</string>
    <string name="yodo1_string_dialog_tips_wait">请稍后 ...</string>
    .........
</resources>
有时这样的对应关系可能会透漏部分关键字的信息,所以根据对应的 name 来查找全文可能会有不错的收获。

静态分析步骤

crackme.apk -> 解压 -> 查看 xml 文件 -> baksmali / classes.dex -> MainActivity.smali ->  lib/armeabi/crackme.so -> smali -> 重新打包 crackme.apk -> 重新签名