smali语法复习

特点

Smali汇编指令特点:
参数操作从目标到源的顺序(类似x86汇编)
根据字节码的类型和大小,添加后缀消除歧义
64位常规字节码添加-wide
特殊字节码添加具体类型
基于寄存器操作,不存在传统汇编的栈操作,没有pop,push
每个寄存器均为32位,64位数据类型用连续两个寄存器存储表示

基本类型
V void (只能用于返回值类型) 
Z boolean 
B byte 
S short 
C char 
I int 
J long 
F float 
D Double 

数据类型

对象类型
表示方法:L包名+类名;(L;作为起始结束符)
eg:
java.lang.String
Ljava/lang/String;
com.example.applicationandjni.MainActivity
Lcom/example/applicationandjni/MainActivity;
数组表示,类型前面加[
int[] --> [I
Int[][] --> [[I
String[] --> Ljava/lang/String;

方法的表示形式:
Lpackage/name/ObjectName;——>methodName(III)Z  详解如下:
Lpackage/name/ObjectName  表示类型
methodName   表示方法名
III   表示参数(这里表示为3个整型参数)

字段的表示形式:
Lpackage/name/ObjectName;——>FieldName:Ljava/lang/String;表示: 包名,字段名和各字段类型

寄存器

有两种方式指定一个方法中有多少寄存器是可用的:
.registers  指令指定了方法中寄存器的总数
.locals        指令表明了方法中非参寄存器的总数,出现在方法中的第一
方法的传参:
当一个方法被调用的时候,方法的参数被置于最后N个寄存器中;
例如,一个方法有2个参数,5个寄存器(v0~v4)
那么,参数将置于最后2个寄存器(v3和v4)
非静态方法中的第一个参数总是调用该方法的对象;一般都为p0
说明:对于静态方法除了没有隐含的this参数外,其他都一样

常用命令法V和P
v表示本地寄存器,p表示参数寄存器
eg:一个方法有两个局部变量,三个参数
v0         v0第一个本地寄存器 
v1         v1第二个本地寄存器 
v2         p0 (this) 
v3         p1 第一个参数 
v4         p2 第二个参数 
v5         p3 第三个参数

V命名法和P命名法的比较:使用P命名是为了防止以后如果在方法中增加寄存器,需要对参数寄存器重新进行编号的缺点

再次强调:Long和Double类型是64位的,需要2个寄存器
例如:对于非静态方法
LMyObject——>myMethod(IJZ)V;
有4个参数:LMyObject,int,long,bool;   需要5个寄存器来存储参数;
P0    this
P1    I (int)
P2,P3  J (long)不能分开用,因为JAVA解释执行,没有这种
P4    Z(bool)

smali文件

头部
.class public Lcom/example/applicationandjni/MyApplication;
.super Landroid/app/Application;
.source "MyApplication.java"
.field
成员变量(静态,非静态)
.method
成员方法
其他
通过读dex确定的smali文件结构。

字段声明表示
public static aa:F
作用域 变量名:变量类型

方法声明表示:
public pri_method(ILjava/lang/String;)Ljava/lang/String;
作用域 方法名(参数类型)返回值类型

public 、protected声明
invoke-virtual(因为继承,有重载)
private声明
invoke-direct
Static声明
invoke-static
调用父类方法
invoke-super

所有smali汇编调用的方法没有默认返回值比如x86/64的eaxrax,必须要调用一个move-result-object/其他类型 vx
 

Demo

下面分析一个汇编demo,先变成class,再变成dex,将dex,用baksmali解包

像那些R$的都是一些资源文件。跟资源文件耦合。

# virtual methods
.method protected onCreate(Landroid/os/Bundle;)V
    .registers 6
    .param p1, "savedInstanceState"    # Landroid/os/Bundle;p0传的是this

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

    .line 52
    const/high16 v0, 0x7f030000

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

    .line 54
    const/4 v0, 0x1

    const-string v1, "1"

    invoke-virtual {p0, v0, v1}, Lcom/example/testtype/MainActivity;->pub_method(ILjava/lang/String;)V

    .line 55
    const/4 v0, 0x2

    const-string v1, "2"

    invoke-virtual {p0, v0, v1}, Lcom/example/testtype/MainActivity;->pro_method(ILjava/lang/String;)I

    .line 56
    const/4 v0, 0x3

    const-string v1, "3"

    invoke-direct {p0, v0, v1}, Lcom/example/testtype/MainActivity;->pri_method(ILjava/lang/String;)Ljava/lang/String;

    .line 58
    const/4 v0, 0x4

    const-string v1, "4"

    invoke-static {v0, v1}, Lcom/example/testtype/MainActivity;->pub_static_method(ILjava/lang/String;)V

    .line 59
    const/4 v0, 0x5

    const-string v1, "5"

    invoke-static {v0, v1}, Lcom/example/testtype/MainActivity;->pro_static_method(ILjava/lang/String;)I

    .line 60
    const/4 v0, 0x6

    const-string v1, "6"

    invoke-static {v0, v1}, Lcom/example/testtype/MainActivity;->pri_static_method(ILjava/lang/String;)Ljava/lang/String;

    .line 62
    const-wide/16 v0, 0xa#long

    iput-wide v0, p0, Lcom/example/testtype/MainActivity;->a:J #看起来用了v0,实际上是v0v1,因为是long

    .line 63
    const/16 v0, 0x14

    iput v0, p0, Lcom/example/testtype/MainActivity;->b:I

    .line 64
    const/high16 v0, 0x41f00000    # 30.0f

    sput v0, Lcom/example/testtype/MainActivity;->aa:F

    .line 65
    const-wide/high16 v0, 0x4044000000000000L    # 40.0

    sput-wide v0, Lcom/example/testtype/MainActivity;->bb:D

    .line 67
    const-string v0, "MF"

    new-instance v1, Ljava/lang/StringBuilder;#java特性,字符串不可变,将2个字符串相加先newstringbuild,然后拼接起来,然后tostring
   

    iget-wide v2, p0, Lcom/example/testtype/MainActivity;->a:J

    invoke-static {v2, v3}, Ljava/lang/String;->valueOf(J)Ljava/lang/String;#java/lang/String类的valueOf方法传入一个Jlong型,返回字符串型。

    move-result-object v2

    invoke-direct {v1, v2}, Ljava/lang/StringBuilder;-><init>(Ljava/lang/String;)V#两个参数第一个参数相当于this是个对象,第二个参数是含参的构造函数,就是new一个对象,先new对象,上面的函数,再调用他的构造函数

    invoke-virtual {v1}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String;//掉stringbuilder转成String

    move-result-object v1#生成strign给v1

    invoke-static {v0, v1}, Landroid/util/Log;->i(Ljava/lang/String;Ljava/lang/String;)I

    .line 68
    const-string v0, "MF"

    new-instance v1, Ljava/lang/StringBuilder;

    iget v2, p0, Lcom/example/testtype/MainActivity;->b:I

    invoke-static {v2}, Ljava/lang/String;->valueOf(I)Ljava/lang/String;

    move-result-object v2

    invoke-direct {v1, v2}, Ljava/lang/StringBuilder;-><init>(Ljava/lang/String;)V

    invoke-virtual {v1}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String;

    move-result-object v1

    invoke-static {v0, v1}, Landroid/util/Log;->i(Ljava/lang/String;Ljava/lang/String;)I

    .line 69
    const-string v0, "MF"

    new-instance v1, Ljava/lang/StringBuilder;

    sget v2, Lcom/example/testtype/MainActivity;->aa:F

    invoke-static {v2}, Ljava/lang/String;->valueOf(F)Ljava/lang/String;

    move-result-object v2

    invoke-direct {v1, v2}, Ljava/lang/StringBuilder;-><init>(Ljava/lang/String;)V

    invoke-virtual {v1}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String;

    move-result-object v1

    invoke-static {v0, v1}, Landroid/util/Log;->i(Ljava/lang/String;Ljava/lang/String;)I

    .line 70
    const-string v0, "MF"

    new-instance v1, Ljava/lang/StringBuilder;

    sget-wide v2, Lcom/example/testtype/MainActivity;->bb:D

    invoke-static {v2, v3}, Ljava/lang/String;->valueOf(D)Ljava/lang/String;

    move-result-object v2

    invoke-direct {v1, v2}, Ljava/lang/StringBuilder;-><init>(Ljava/lang/String;)V

    invoke-virtual {v1}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String;

    move-result-object v1

    invoke-static {v0, v1}, Landroid/util/Log;->i(Ljava/lang/String;Ljava/lang/String;)I

    .line 71
    return-void
.end method

.method protected pro_method(ILjava/lang/String;)I
    .registers 7
    .param p1, "n"    # I
    .param p2, "tag"    # Ljava/lang/String;

    .prologue
    .line 21
    mul-int/lit8 v0, p1, 0x2

    .line 22
    .local v0, "m":I
    const-string v1, "MF"

    new-instance v2, Ljava/lang/StringBuilder;

    invoke-static {p2}, Ljava/lang/String;->valueOf(Ljava/lang/Object;)Ljava/lang/String;

    move-result-object v3

    invoke-direct {v2, v3}, Ljava/lang/StringBuilder;-><init>(Ljava/lang/String;)V

    const-string v3, ": "

    invoke-virtual {v2, v3}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;

    move-result-object v2

    invoke-virtual {v2, v0}, Ljava/lang/StringBuilder;->append(I)Ljava/lang/StringBuilder;

    move-result-object v2

    invoke-virtual {v2}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String;

    move-result-object v2

    invoke-static {v1, v2}, Landroid/util/Log;->i(Ljava/lang/String;Ljava/lang/String;)I

    .line 23
    return v0
.end method

.method public pub_method(ILjava/lang/String;)V
    .registers 7
    .param p1, "n"    # I
    .param p2, "tag"    # Ljava/lang/String;

    .prologue
    .line 16
    mul-int/lit8 v0, p1, 0x2

    .line 17
    .local v0, "m":I
    const-string v1, "MF"

    new-instance v2, Ljava/lang/StringBuilder;

    invoke-static {p2}, Ljava/lang/String;->valueOf(Ljava/lang/Object;)Ljava/lang/String;

    move-result-object v3

    invoke-direct {v2, v3}, Ljava/lang/StringBuilder;-><init>(Ljava/lang/String;)V

    const-string v3, ": "

    invoke-virtual {v2, v3}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;

    move-result-object v2

    invoke-virtual {v2, v0}, Ljava/lang/StringBuilder;->append(I)Ljava/lang/StringBuilder;

    move-result-object v2

    invoke-virtual {v2}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String;

    move-result-object v2

    invoke-static {v1, v2}, Landroid/util/Log;->i(Ljava/lang/String;Ljava/lang/String;)I

    .line 18
    return-void
.end method

第二个pro_method逆向写伪代码如下 

package com.example.testtype
class Mainactivity extends Activity{
    protected int pro_method(int n,String tag)
    {
        int v0=n*0x2;
        string v1="MF";
        String v3=String.valueOf(tag);
        SrtringBuilder v2=new StringBuilder(v3);
        v3=":";
        v2=v2.append(v3);
        v2=v2.append.(v0);
        String v2=v2.toString();
        log.i(v1,v2);
        return v0;
    //其实这些代码再java里就是
            int m=n*0x02;
        Log.i("MF",tag+":"+m);
        return m;

    }
}

之所以要逆smali代码,因为是如果是大数组,jeb反编译回是空,不是正常的。只能看smali汇编。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章