Foreword
We have talked about the android decompilation tool before and how to decompile it. After decompiling, you can get the jar or get the smali file. Android uses the Java language for development, but the Android system has its own virtual machine Dalvik. In the end, code compilation does not use Java classes, but uses smali. The code we decompile may not be correctly interpreted in many places if it is jar. If we decompile smali, we can correctly understand the meaning of the program. Therefore, it is necessary for us to be familiar with smali syntax.
Representation of types
Java contains two types, primitive types and reference types (including objects), and there are also these two types mapped to smali.
Primitive type
V void (can only be used for return value types)
Z boolean
B byte
S short
C char
I int
J long
F float
D Double
Object type
Lpackage/name /ObjectName; Equivalent to package.name.ObjectName in java
L Indicates that this is an object type
package/name The package where the object is located
ObjectName Object name
; Identifies the end of the object name
Representation of the array
[ I represents a one-dimensional array of type int, which is equivalent to int[];
Add a dimension and add a [, such as [[I represents int[][]
The maximum number of each dimension of the array is 255;
Object array representation is also Similarly, for example, the representation of String array is [Ljava/lang/String
Registers and Variables
Variables in Java are stored in memory. In order to improve performance in Android, variables are stored in registers, and registers are 32 bits. , can support any type, among which long and double are 64 bits and need to be saved in two registers.
The registers are named with v and p
v represents the local register, p represents the parameter register, the relationship is as follows
If a method has two local variables, there are three parameters
v0 The first local register
v1 The second local Register
v2 p0 (this)
v3 p1 First parameter
v4 p2 Second parameter
v5 p3 Third parameter
Of course, if it is a static method, there are only 5 registers, and there is no need to store this.
.registers Use this instruction to specify the total number of registers in the method
.locals Use this specification to indicate the total number of non-parameter registers in the method and place it on the first line of the method.
Representation of methods and fields
Method signature
methodName(III)Lpackage/name/ObjectName;
If you have done ndk development, you should be familiar with such a signature, which is how to identify a method.
The above methodName identifies the method name, III represents the three integer parameters, and Lpackage/name/ObjectName; represents the type of the return value.
Representation of method
Lpackage/name/ObjectName;——>methodName(III)Z
That is, the function boolean methodondName(int a, int b, int c) in package.name.ObjectName is similar to this
field The representation of
Lpackage/name/ObjectName;——>FieldName:Ljava/lang/String;
means: package name, field name and each field type
方法的定义
比如我下面的一个方法
private static int sum(int a, int b) { return a+b; }
使用编译后是这样
.method private static sum(II)I
.locals 4 #表示需要申请4个本地寄存器
.parameter
.parameter #这里表示有两个参数
.prologue
.line 27
move v0, p0
.local v0, a:I
move v1, p1
.local v1, b:I
move v2, v0
move v3, v1
add-int/2addr v2, v3
move v0, v2
.end local v0 #a:I
return v0
.end method
从上面可以看到函数声明使用.method开始 .end method结束,java中的关键词private,static 等都可以使用,同时使用签名来表示唯一的方法,这里是sum(II)I。
声明成员
.field private name:Lpackage/name/ObjectName;
比如:private TextView mTextView;表示就是
.field private mTextView:Landroid/widget/TextView;
private int mCount;
.field private mCount:I
指令执行
smali字节码是类似于汇编的,如果你有汇编基础,理解起来是非常容易的。
比如:
move v0, v3 #把v3寄存器的值移动到寄存器v0上.
const v0, 0×1 #把值0×1赋值到寄存器v0上。
invoke-static {v4, v5}, Lme/isming/myapplication/MainActivity;->sum(II)I #执行方法sum(),v4,v5的值分别作为sum的参数。
其他
通过前面我们可以看到,smali就是类似汇编,其中很多命令,我们可以去查它的手册来一一对应。学习时,我们可以自己写一个比较简单的java文件,然后转成smali文件来对照学习。
下面,我贴一个我写的一个比较简单的java文件以及其对应的smali,其中包含if判断和for循环。
java文件:
package me.isming.myapplication; import android.support.v7.app.ActionBarActivity; import android.os.Bundle; import android.view.Menu; import android.view.MenuItem; import android.widget.TextView; public class MainActivity extends ActionBarActivity { private TextView mTextView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mTextView = (TextView) findViewById(R.id.text); mTextView.setText("a+b=" + sum(1,2) + "a>b?" + max(1,2) + "5 accumulate:" + accumulate(5)); } private static int sum(int a, int b) { return a+b; } private boolean max(int a, int b) { if (a > b) { return true; } else { return false; } } private int accumulate(int a) { if (a <= 0) { return 0; } int sum = 0; for(int i = 0; i <= a; i++) { sum += a; } return sum; } }
对应的smali:
.class public Lme/isming/myapplication/MainActivity;
.super Landroid/support/v7/app/ActionBarActivity;
.source "MainActivity.java"
# instance fields
.field private mTextView:Landroid/widget/TextView;
# direct methods
.method public constructor <init>()V
.locals 2
.prologue
.line 10
move-object v0, p0
.local v0, this:Lme/isming/myapplication/MainActivity;
move-object v1, v0
invoke-direct {v1}, Landroid/support/v7/app/ActionBarActivity;-><init>()V
return-void
.end method
.method private accumulate(I)I
.locals 6
.parameter
.prologue
.line 39
move-object v0, p0
.local v0, this:Lme/isming/myapplication/MainActivity;
move v1, p1
.local v1, a:I
move v4, v1
if-gtz v4, :cond_0
.line 40
const/4 v4, 0x0
move v0, v4
.line 46
.end local v0 #this:Lme/isming/myapplication/MainActivity;
:goto_0
return v0
.line 42
.restart local v0 #this:Lme/isming/myapplication/MainActivity;
:cond_0
const/4 v4, 0x0
move v2, v4
.line 43
.local v2, sum:I
const/4 v4, 0x0
move v3, v4
.local v3, i:I
:goto_1
move v4, v3
move v5, v1
if-gt v4, v5, :cond_1
.line 44
move v4, v2
move v5, v1
add-int/2addr v4, v5
move v2, v4
.line 43
add-int/lit8 v3, v3, 0x1
goto :goto_1
.line 46
:cond_1
move v4, v2
move v0, v4
goto :goto_0
.end method
.method private max(II)Z
.locals 5
.parameter
.parameter
.prologue
.line 31
move-object v0, p0
.local v0, this:Lme/isming/myapplication/MainActivity;
move v1, p1
.local v1, a:I
move v2, p2
.local v2, b:I
move v3, v1
move v4, v2
if-le v3, v4, :cond_0
.line 32
const/4 v3, 0x1
move v0, v3
.line 34
.end local v0 #this:Lme/isming/myapplication/MainActivity;
:goto_0
return v0
.restart local v0 #this:Lme/isming/myapplication/MainActivity;
:cond_0
const/4 v3, 0x0
move v0, v3
goto :goto_0
.end method
.method private static sum(II)I
.locals 4
.parameter
.parameter
.prologue
.line 27
move v0, p0
.local v0, a:I
move v1, p1
.local v1, b:I
move v2, v0
move v3, v1
add-int/2addr v2, v3
move v0, v2
.end local v0 #a:I
return v0
.end method
# virtual methods
.method protected onCreate(Landroid/os/Bundle;)V
.locals 8
.parameter
.prologue
.line 16
move-object v0, p0
.local v0, this:Lme/isming/myapplication/MainActivity;
move-object v1, p1
.local v1, savedInstanceState:Landroid/os/Bundle;
move-object v2, v0
move-object v3, v1
invoke-super {v2, v3}, Landroid/support/v7/app/ActionBarActivity;->onCreate(Landroid/os/Bundle;)V
.line 17
move-object v2, v0
const v3, 0x7f030017
invoke-virtual {v2, v3}, Lme/isming/myapplication/MainActivity;->setContentView(I)V
.line 19
move-object v2, v0
move-object v3, v0
const v4, 0x7f08003f
invoke-virtual {v3, v4}, Lme/isming/myapplication/MainActivity;->findViewById(I)Landroid/view/View;
move-result-object v3
check-cast v3, Landroid/widget/TextView;
iput-object v3, v2, Lme/isming/myapplication/MainActivity;->mTextView:Landroid/widget/TextView;
.line 21
move-object v2, v0
iget-object v2, v2, Lme/isming/myapplication/MainActivity;->mTextView:Landroid/widget/TextView;
new-instance v3, Ljava/lang/StringBuilder;
move-object v7, v3
move-object v3, v7
move-object v4, v7
invoke-direct {v4}, Ljava/lang/StringBuilder;-><init>()V
const-string v4, "a+b="
invoke-virtual {v3, v4}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;
move-result-object v3
const/4 v4, 0x1
const/4 v5, 0x2
invoke-static {v4, v5}, Lme/isming/myapplication/MainActivity;->sum(II)I
move-result v4
invoke-virtual {v3, v4}, Ljava/lang/StringBuilder;->append(I)Ljava/lang/StringBuilder;
move-result-object v3
const-string v4, "a>b?"
invoke-virtual {v3, v4}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;
move-result-object v3
move-object v4, v0
const/4 v5, 0x1
const/4 v6, 0x2
invoke-direct {v4, v5, v6}, Lme/isming/myapplication/MainActivity;->max(II)Z
move-result v4
invoke-virtual {v3, v4}, Ljava/lang/StringBuilder;->append(Z)Ljava/lang/StringBuilder;
move-result-object v3
const-string v4, "5 accumulate:"
invoke-virtual {v3, v4}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;
move-result-object v3
move-object v4, v0
const/4 v5, 0x5
invoke-direct {v4, v5}, Lme/isming/myapplication/MainActivity;->accumulate(I)I
move-result v4
invoke-virtual {v3, v4}, Ljava/lang/StringBuilder;->append(I)Ljava/lang/StringBuilder;
move-result-object v3
invoke-virtual {v3}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String;
move-result-object v3
invoke-virtual {v2, v3}, Landroid/widget/TextView;->setText(Ljava/lang/CharSequence;)V
.line 23
return-void
.end method
参考资料
最后附上一些参考资料:
http://pallergabor.uw.hu/androidblog/dalvik_opcodes.html
https://code.google.com/p/smali/w/list
http://www.miui.com/thread-409543-1-1.html