Android逆向分析学习与研究(2)————通过“轮盘赌”简要看看smali的基本流程控制

1.我写的一个简单的Andriod小Demo,“轮盘赌!”。

我写的这个轮盘赌小游戏(姑且称它为游戏吧),主要玩法是第一次点击屏幕中间的大按钮,会弹出“子弹已上膛”的提示,再次点击会出现“扣动扳机开火吧!”的提示,第三次点击就是“赌命”的时刻了,如果有子弹,会弹出“啪!你被爆头了!”,如果没有,则会弹出“你真幸运”的提示。

游戏很简单,用到了Random,代码可能在一些人看来会稍显幼稚,但没关系,游戏不是重点,重点是我们对于这个Android小Demo的逆向,重点是分析smali的流程控制语法。

先看看java代码

package com.example.forreversedemo;

import java.util.Random;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.Toast;

public class MainActivity extends Activity implements OnClickListener{

    private Button button;    //按钮
    public int count = 0;    //计数
    public int[] bullet =new int[]{0,0,0,0,0,0};    //用数组来表示弹夹,没子弹时数组元素为0,有子弹时,数组元素之一随机赋值为1
    public int a;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        button= (Button) findViewById(R.id.start_count);
        button.setOnClickListener(this);
    }

    @Override
    public void onClick(View arg0) {

        switch(arg0.getId()){
            case R.id.start_count:
                Random random = new Random();
                //第一次点击按钮把第一颗子弹上膛
                if(count == 0){
                    MessageBox("子弹已上膛!");
                    bullet[random.nextInt(6)] = 1;
                    count++;
                    break;
                }
                //第2次点击,实现转动轮盘至停止
                if(count == 1){
                    int count1 = -1;
                    for (int i = 0;i<random.nextInt(6)+60000; i++) {
                        count1++;
                        if(count1 == 6)count1 = 0;        //循环遍历弹夹,也可以用while和for来做,这里为分析方便起见
                        a = bullet[count1];
                    }
                    MessageBox("抠动扳机开火吧!");
                    count++;
                    break;
                }
                //第3次点击就是开火!
                if(count == 2){
                    if(a == 1){
                        MessageBox("啪!爆头!");
                        count = 0;
                    }else{
                        MessageBox("你真幸运!");
                        count = 0;
                    }
                }
                break;
            default:
                break;

        }

    }
    //弹出提示,额,这个函数名很熟悉吧,WinAPI啊,开个玩笑
    public void MessageBox(String text){
        Toast.makeText(this, text, Toast.LENGTH_LONG).show();
    }
}

2.逆向这个Demo!

还是使用apktool d apk文件 这个命令

在分析smali时,我参考了一些文章,但重推的是:

  • 唯一的一本书:非虫大大的书《Android软件安全与逆向分析》
  • 文章:我转的文章:apk反汇编之smali语法(转)

    其中非虫的书的第三章和我转的那篇文章对于smali的语法进行了详细的介绍,当然你也可以下个官方文档看。总之,初学者在看下面的smali代码时,一定要对照参考我给你推荐的,下面的注释,在我看来,我写的还算详细但避免不了疏漏和有争议的地方,希望大家分析代码时,能多加思考,更欢迎大家的建议和批评指正。

得到smali代码如下

MainActivity.smali (表示在用MK写博客时,贴smali代码用ruby格式最好^_^,有没有更好的方法呢?)

.class public Lcom/example/forreversedemo/MainActivity;#类名
.super Landroid/app/Activity;#父类名
.source "MainActivity.java"#原文件名

# interfaces
.implements Landroid/view/View$OnClickListener;#接口

# instance fields#成员变量
.field public a:I#int 整形变量   I 代表整形

.field public bullet:[I        #整形一维数组,[  代表数组,

.field private button:Landroid/widget/Button;    #按钮

.field public count:I

# direct methods
.method public constructor <init>()V  #构造函数,使用该方法来初始化数据成员和所需资源。
    .locals 1

    .prologue
    .line 11
    invoke-direct {p0}, Landroid/app/Activity;-><init>()V

    .line 14
    const/4 v0, 0x0

    iput v0, p0, Lcom/example/forreversedemo/MainActivity;->count:I

    .line 15
    const/4 v0, 0x6

    new-array v0, v0, [I

    iput-object v0, p0, Lcom/example/forreversedemo/MainActivity;->bullet:[I

    .line 11
    return-void
.end method

# virtual methods    #public void MessageBox();
.method public MessageBox(Ljava/lang/String;)V    # MessageBox()方法,参数为String类型
    .locals 1
    .parameter "text"    #参数名text

    .prologue
    .line 68
    const/4 v0, 0x1

    invoke-static {p0, p1, v0}, Landroid/widget/Toast;->makeText(Landroid/content/Context;Ljava/lang/CharSequence;I)Landroid/widget/Toast;

    move-result-object v0    #将上一个invoke类型指令包对象结果存入寄存器v0

    invoke-virtual {v0}, Landroid/widget/Toast;->show()V  #Toast.show();弹出提示框

    .line 69
    return-void
.end method

.method public onClick(Landroid/view/View;)V
    .locals 8
    .parameter "arg0"        # onClick()方法,参数为View对象 对象型

    .prologue            #代码起始指令
    #const为数据定义指令
    const/4 v7, 0x0        #将0x6数值符号扩展为32bit后存入寄存器v7,const为

    const/4 v6, 0x6

    const/4 v5, 0x1

    .line 28
    invoke-virtual {p1}, Landroid/view/View;->getId()I        #调用实例的虚方法  getId() 整形;p0为this指针,p1为View对象。v字开头的为局部变量寄存器,p开头的为参数变量寄存器

    move-result v3            #将上一个invoke类型指令操作的单字(16bit)非对象结果返回给v3寄存器;v3为View对象的id,即v3=p1.getId()

    packed-switch v3, :pswitch_data_0    ##switch(v3),通过pswitch_data_0进行匹配,packed-switch为分支跳转指令,而pswitch_data_0为偏移表,表中的值有规律递增.
    ########switch入口开始
    .line 66
    :cond_0
    :goto_0
    return-void                #表示void类型的函数返回
    ########switch入口结束

    .line 30
    :pswitch_0
    new-instance v2, Ljava/util/Random;        #实例化一个Random对象

    invoke-direct {v2}, Ljava/util/Random;-><init>()V    #调用实例的直接方法

    .line 32
    .local v2, random:Ljava/util/Random;
    iget v3, p0, Lcom/example/forreversedemo/MainActivity;->count:I    #获取count变量的值存入

    if-nez v3, :cond_1        #如果不等跳转到cond_1

    .line 33
    const-string v3, "\u5b50\u5f39\u5df2\u4e0a\u819b\uff01"    #unicode解码:“子弹已上膛!”

    invoke-virtual {p0, v3}, Lcom/example/forreversedemo/MainActivity;->MessageBox(Ljava/lang/String;)V        #调用MessageBox()函数

    .line 34
    iget-object v3, p0, Lcom/example/forreversedemo/MainActivity;->bullet:[I  #iget-object 获得(读)整形数组

    invoke-virtual {v2, v6}, Ljava/util/Random;->nextInt(I)I    #通过上面  const/4 v6, 0x6  可知,v6的值为6,也就是nextInt(6)

    move-result v4

    aput v5, v3, v4    #aput  数组操作指令,v3为数组初始地址(数组名),v4为数组索引

    .line 35
    iget v3, p0, Lcom/example/forreversedemo/MainActivity;->count:I

    add-int/lit8 v3, v3, 0x1     #count++

    iput v3, p0, Lcom/example/forreversedemo/MainActivity;->count:I  #向count变量写入值(从v3寄存器取出)

    goto :goto_0   #跳转到goto_0

    .line 39
    :cond_1
    iget v3, p0, Lcom/example/forreversedemo/MainActivity;->count:I

    if-ne v3, v5, :cond_4   #v3存的count值,v5存的值为1,上面有提到,若果v3!=v5则跳转到cond_4

    .line 40
    const/4 v0, -0x1  

    .line 41
    .local v0, count1:I        #count1=-1

############for循环开始#################################################

    const/4 v1, 0x0    #v1=0

    .local v1, i:I    #i=0,用v1寄存器代表i
    :goto_1    #标志位
    ####### i<random.nextInt(6)+1000 #############
    invoke-virtual {v2, v6}, Ljava/util/Random;->nextInt(I)I

    move-result v3

    const v4, 0xea60        #v4=60000

    add-int/2addr v3, v4        #v3+v4放在v3的地址里

    if-lt v1, v3, :cond_2    #如果v1小于v3,ze跳转到cond_2,若大于则顺序向下执行

    .line 46
    const-string v3, "\u62a0\u52a8\u6273\u673a\u5f00\u706b\u5427\uff01"   #扣动扳机开火吧!,此行也是跳出for循环后执行的代码

    invoke-virtual {p0, v3}, Lcom/example/forreversedemo/MainActivity;->MessageBox(Ljava/lang/String;)V

    .line 47
    iget v3, p0, Lcom/example/forreversedemo/MainActivity;->count:I

    add-int/lit8 v3, v3, 0x1       #将第二个寄存器的值加上0x1放入v3寄存器,实现自增长count++

    iput v3, p0, Lcom/example/forreversedemo/MainActivity;->count:I       #写入count值,iput中i代表整形值,put代表写入(赋值),同理get代表读取(获得)

    goto :goto_0

    .line 42
    :cond_2
    add-int/lit8 v0, v0, 0x1        #将第二个寄存器的值加上0x1放入v0寄存器,实现自增长,就是count1++

    .line 43
    if-ne v0, v6, :cond_3    #count1!=6  则  跳转到cond_3

    const/4 v0, 0x0            #if(count1==6)count1=0;

    .line 44
    :cond_3
    iget-object v3, p0, Lcom/example/forreversedemo/MainActivity;->bullet:[I    #获得bullet数组

    aget v3, v3, v0        #v0此时代表count1.所以用count1作为数组索引

    iput v3, p0, Lcom/example/forreversedemo/MainActivity;->a:I        #把当前对象(p0为this指针)的a属性赋值(写入)为v3,v3也就是从上面数组获取的值,就是a = bullet[count1];

    .line 41
    add-int/lit8 v1, v1, 0x1        #实现v1的自增,就是i++

    goto :goto_1         #跳转到goto_1,一次循环结束

    .line 51
    .end local v0           #count1:I
    .end local v1           #i:I
    :cond_4
    iget v3, p0, Lcom/example/forreversedemo/MainActivity;->count:I

    const/4 v4, 0x2

    if-ne v3, v4, :cond_0

    .line 52
    iget v3, p0, Lcom/example/forreversedemo/MainActivity;->a:I

    if-ne v3, v5, :cond_5

    .line 53
    const-string v3, "\u556a!\u7206\u5934\uff01"    #啪!爆头

    invoke-virtual {p0, v3}, Lcom/example/forreversedemo/MainActivity;->MessageBox(Ljava/lang/String;)V

    .line 54
    iput v7, p0, Lcom/example/forreversedemo/MainActivity;->count:I

    goto :goto_0

    .line 56
    :cond_5
    const-string v3, "\u4f60\u771f\u5e78\u8fd0\uff01"    #你真幸运

    invoke-virtual {p0, v3}, Lcom/example/forreversedemo/MainActivity;->MessageBox(Ljava/lang/String;)V

    .line 57
    iput v7, p0, Lcom/example/forreversedemo/MainActivity;->count:I

    goto :goto_0

    .line 28
    nop

    :pswitch_data_0
    .packed-switch 0x7f080000        #default
        :pswitch_0
    .end packed-switch
.end method

.method protected onCreate(Landroid/os/Bundle;)V    #onCreate()方法
    .locals 1
    .parameter "savedInstanceState"        #方法参数名

    .prologue            #开始
    .line 19
    invoke-super {p0, p1}, Landroid/app/Activity;->onCreate(Landroid/os/Bundle;)V

    .line 20
    const/high16 v0, 0x7f03    #表示布局文件的实际值,可在R.java文件中找到,活在R$.smali文件中找到

    invoke-virtual {p0, v0}, Lcom/example/forreversedemo/MainActivity;->setContentView(I)V

    .line 21
    const/high16 v0, 0x7f08    #表示button的实际id值,同理可在R.java里找到

    invoke-virtual {p0, v0}, Lcom/example/forreversedemo/MainActivity;->findViewById(I)Landroid/view/View;

    move-result-object v0

    check-cast v0, Landroid/widget/Button;

    iput-object v0, p0, Lcom/example/forreversedemo/MainActivity;->button:Landroid/widget/Button;

    .line 22
    iget-object v0, p0, Lcom/example/forreversedemo/MainActivity;->button:Landroid/widget/Button;

    invoke-virtual {v0, p0}, Landroid/widget/Button;->setOnClickListener(Landroid/view/View$OnClickListener;)V

    .line 23
    return-void
.end method

这个小demo里用到了一些基本的流程控制语句,比如if 、else 、for、swtich等,而while循环和嵌套循环等没有提及,在以后的文章里会陆陆续续提到,其实大同小异的。

初学者可能会对其中的一些寄存器啊,跳转啊很是头疼,有过X86汇编和ARM汇编基础的同学,看smali代码会容易些,但是没有关系的,结合我在里面的的注释也是能看懂的。最好还是结合我给你推荐的资料看,这里不再多解释。

^_^

时间: 2024-10-24 05:19:59

Android逆向分析学习与研究(2)————通过“轮盘赌”简要看看smali的基本流程控制的相关文章

Android逆向分析学习与研究(1)————工欲善其事必先利其器

注:头连天参加一个慕课网的活动发表的文章,从那里搬到这里来 工具可到看雪移动下载:点击打开链接下载,里面有工具列表,很详细. 一.什么是逆向 所谓逆向,就是对于程序的"逆向工程",英文叫"reverse",是计算机安全领域中一项重要的技术.常见使用情景:1.手里有一个软件(可以是Win平台的,可以是Android的,也可以是ios的),软件本身功能实现的很好,但是由于商业和版权的原因,大部分软件是不开源的,这时你有很想对其源码层面一探究竟或者你的项目中急需这种功能,

android逆向入门及工具下载

本文所用到的工具下载: 链接:http://pan.baidu.com/s/1i3uw4NN 密码:8hz5 最近在研究如何逆向android的app,于是就有了这篇android逆向入门的总结回馈互联网. 由于Android的.apk文件实际上就是一个zip文件,修改文件后缀后直接可以打开,效果如下图所示: 里面包含了的文件有: META-INF:这个文件夹是用于保存签名文件,确保包的完整性的 res:apk所要用的资源文件,都是原封不动地保存,我们可以直接提取出来,做汉化时就可以直接阅读st

Android 逆向初探(一)

p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Helvetica; color: #000000 } p.p2 { margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Helvetica; color: #000000; min-height: 13.0px } span.s1 { } span.Apple-tab-span { white-space: pre } 逆向分析是一门技术,也是一门艺

Android逆向-Android基础逆向(2-2)

[toc] #0x00 前言##不知所以然,请看Android逆向-Android基础逆向(1)Android逆向-Android基础逆向(2)##以及java系列:Android逆向-java代码基础(1)Android逆向-java代码基础(2)Android逆向-java代码基础(3)Android逆向-java代码基础(4)Android逆向-java代码基础(5)Android逆向-java代码基础(6)Android逆向-java代码基础(7)Android逆向-java代码基础(8

Android逆向系列文章— Android基础逆向(6)

本文作者:HAI_ 0×00 前言 不知所以然,请看 Android逆向-Android基础逆向(1) Android逆向-Android基础逆向(2) Android逆向-Android基础逆向(2-2) Android逆向-Android基础逆向(2-3补充篇) Android逆向-Android基础逆向(3) Android逆向-Android基础逆向(4) Android逆向-Android基础逆向(4-2) Android逆向-Android基础逆向(5) 以及java系列: Andr

Android逆向从未如此简单

哈,又标题党了..不过我一定竭尽所能,写一篇最亲民的入门文章. 本文仅供学习交流之用,切勿用于非法用途,读者若运用所学知识,进行非法任何商业目的或者非法牟利,一切责任由操作者自行承担,与本人无关.希望读者仅仅从了解原理,保护自身APP尽量减少危害出发来阅读本文. 本文发布自wing的地方酒馆,转载请注明出处. 本文以一个最简单的例子,来教给大家Android逆向入门的一些知识.所以首先我们需要准备一个APK,做的简单一些,就是一个EditText,已经一个按钮,模拟验证注册码. 当验证码填写正确

Android与Unity交互研究

Android与Unity交互研究 转载请注明出处:http://blog.csdn.net/crazy1235/article/details/46733221 Android与Unity交互研究 unity与android交互的由来 unity简单介绍 unity与android交互介绍 unity调用android的方法 android调用untiy的方法 unity与android交互的由来 本人在项目开发过程中,遇到这样一个需求,把unity的场景放到android中去显示.刚开始做的

android 1.6 launcher研究之自定义ViewGroup (转 2011.06.03(二)——— android 1.6 launcher研究之自定义ViewGroup )

2011.06.03(2)——— android 1.6 launcher研究之自定义ViewGroup2011.06.03(2)——— android 1.6 launcher研究之自定义ViewGroup 1.用xml来作为ViewGroup里面的View参考:http://www.eoeandroid.com/thread-30888-1-1.html MyViewGroup.java package com.lp; import android.content.Context; impo

Android逆向之动态调试so库JNI_Onload函数-----基于IDA实现

之前看过吾爱破解论坛一个关于Android'逆向动态调试的经验总结帖,那个帖子写的很好,对Android的脱壳和破解很有帮助,之前我们老师在上课的时候也讲过集中调试的方法,但是现在不太实用.对吾爱破解论坛的该贴,我也是看了很多遍,自己也查了不少资料,但是自己动手的时候总觉比较繁琐,并且很多细节的地方没有注意到,按照那个帖子尝试了几遍但是却出现了错误(后面会提到),今天周末重新拾起来试了试,终于把遇到的问题给解决了,顺便做个记录以免忘记了,其中的一些细节我也不是太明白,忘知道的人给指出. 第一步.