安卓逆向一——Smali学习

安卓逆向一——Smali学习

Something u have to know:

       虽然Android平台使用Java来开发应用程序,但Android程序却不是运行在标准的Java虚拟机上,而是将Java字节码转换成Dalvik字节码,并打包到一个DEX可执行文档当中,Dalvik虚拟机通过解析DEX文件来执行这些字节码。

       因此我们想了解安卓逆向,就要先了解一下Dalvik的语法。

目录

Something u have to know

0x01 工具准备

0x02 语法了解

0x03 举例解读



0x01 工具准备:

        学习时我们可以用J2S2J(Java to Smali to Java转换工具):

            https://www.onlinedown.net/download/1209079?module=download

0x02 语法了解:

       本章节只录入部分,初次阅读快速浏览熟悉部分语法即可。

    1、数据类型对应表:

smali类型 java类型
V void (用于返回类型)
Z boolean
B byte
S short
C char
I int
J long (64 bits)
F float
D double (64 bits)

    2、运算符描述表:

smali运算符 描述
add-int v0, p1, p2 v0 = p1 + p2
sub-int v0, p1, p2 v0 = p1 - p2
mul-int v0, p1, p2 v0 = p1 * p2
div-int v0, p1, p2 v0 = p1 / p2
rem-int v0, p1, p2 v0 = p1 % p2
and-int v0, p1, p2 v0 = p1 & p2
or-int v0, p1, p2 v0 = p1 │ p2
xor-int v0, p1, p2 v0 = p1 ^ p2
shl-int v0, p1, p2 v0 = p1 << p2
shr-int v0, p1, p2 v0 = p1 >> p2
ushr-int v0, p1, p2 v0 = p1 >>> p2
add-int/2addr v0, v1 v0 = v0 + v1
sub-int/2addr v0, v1 v0 = v0 - v1
add-int/lit16 v0, v1, lit16 v0 = v1 + lit16
sub-int/lit16 v0, v1, lit16 v0 = v1 - lit16
add-int/lit8 v0, v1, lit8 v0 = v1 + lit8
sub-int/lit8 v0, v1, lit8 v0 = v1 - lit8

    3、类名对照表:

smali类名 java类名
Ljava/lang/String; java.lang.String
Ljava/lang/Object; java.lang.Object

4、数组对照表:

smali数组 Java数组
[I int[]
[[I int[][]
[Ljava/lang/String; String[]
几维就在类型前加几个[号,最多255维

    5、其他指令描述表:

常用指令 描述
const/4 v0, 0x0

给v0寄存器赋值0(此格式为int4bit)

move v0, v1 将v1的值移入v0中
invoke- 调用某方法
if-eq v0, v1, :cond_0

if (v0 == v1) cond_0

(eq==,ne!=,gt>,ge>=,lt<,le<=,eqz==0)

iget 取值(默认int,iget-类型)
iput 赋值(int,iget-类型)

0x03 举例解读:

    1、乘法运算:

        J2S:

安卓逆向一——Smali学习

        Java:

public class BaseData
{
    public int add(int i, int j)
    {
        return i * j;
    }
}

        Smali:

.class public LBaseData;    // 本类
.super Ljava/lang/Object;    // 父类
.source "BaseData.java"    // 文件名


# direct methods
// 构造方法, 方法名为<init>
.method public constructor <init>()V    // 该段未在java代码中显示,java中默认有一个隐藏的无参数的构造方法
    .registers 1    // 声明算上参数, 一共需要几个寄存器(寄存器用p) 不算参数使用locals(寄存器用v)

    .prologue
    .line 1
    invoke-direct {p0}, Ljava/lang/Object;-><init>()V

    return-void
.end method


# virtual methods
// 自定义的add方法
.method public add(II)I
    .registers 4

    .prologue
    .line 5
    mul-int v0, p1, p2    // v0=p1*p2

    return v0
.end method

     2、for循环:

        J2S:

安卓逆向一——Smali学习

 

        Java:

public class ForData
{
    public void forFuc()
    {
        for(int i = 0;i<10;i++)
        {
            System.out.println(i);
        };
    };
    public static void main(String[] args)
    {
        ForData data = new ForData();
        data.forFuc();
    }
}

        Smali:

.class public LForData;    // 本类
.super Ljava/lang/Object;    // 父类
.source "ForData.java"    // 文件名


# direct methods
// 构造方法, 方法名为<init>
.method public constructor <init>()V    // 该段未在java代码中显示,java中默认有一个隐藏的无参数的构造方法
    .registers 1    // 声明算上参数, 一共需要几个寄存器(寄存器用p) 不算参数使用locals(寄存器用v)

    .prologue
    .line 1
    invoke-direct {p0}, Ljava/lang/Object;-><init>()V

    return-void
.end method

// 主方法
.method public static main([Ljava/lang/String;)V
    .registers 2

    .prologue
    .line 12
    new-instance v0, LForData;    //根据ForData类创建对象,保存在v0中

    invoke-direct {v0}, LForData;-><init>()V    //调用<init>构造方法

    .line 13
    invoke-virtual {v0}, LForData;->forFuc()V    //调用自定义方法forFuc

    .line 14
    return-void
.end method


# virtual methods
// 自定义方法forFuc
.method public forFuc()V
    .registers 3

    .prologue
    .line 5
    const/4 v0, 0x0    // v0 = 0

    :goto_1
    const/16 v1, 0xa    // v1 = 10

    if-ge v0, v1, :cond_d    // if ( v0 > v1 ) 跳转cond_d

    .line 7
    sget-object v1, Ljava/lang/System;->out:Ljava/io/PrintStream;    //获取PrintStream类成员变量out对象,并放到v1寄存器中 v1=out()

    invoke-virtual {v1, v0}, Ljava/io/PrintStream;->println(I)V    //调用printLn方法中V1实例打印v0    println.out(v0)

    .line 5
    add-int/lit8 v0, v0, 0x1    // v0++

    goto :goto_1    // 循环

    .line 9
    :cond_d
    return-void    // 直接返回、跳出
.end method

       本篇基础引导,可以把自己的一些Java项目通过J2S2J工具转换并分析,熟练掌握Java代码和Smali代码的互相转换,为安卓逆向代码层打好基础。

上一篇:android-“ smali”语法规范| smali原木注射


下一篇:如何通过代码插桩的方式在任何apk添加自己的逻辑代码