幕后小黑

我的Android逆向学习之旅(一)—— Smali中的基本类型以及简单的Smali类结构
关于 Android Kill 或者 APK改之理之类的工具就不废话了。小黑全程采用 APK改之理 毕竟别人集成好...
扫描右侧二维码阅读全文
07
2018/06

我的Android逆向学习之旅(一)—— Smali中的基本类型以及简单的Smali类结构

关于 Android Kill 或者 APK改之理之类的工具就不废话了。小黑全程采用 APK改之理 毕竟别人集成好的APK用起来更加顺手。

这类的东西请自行百度下载和使用环境搭建大把大把的有。本人使用的工具->点击下载

首先我们了解一下dex反编译以后得到的Smali文件中的基本类型

首先我们创建一个java文件,建立一下全局变量

public class LoginActivity extends AppCompatActivity {
private String a = "private";
public float b = 1.0f;
protected double c = 1.0;
boolean d = true;
boolean e = false;
int f = 0;
char g = 'g';
byte h = 'h';
long i = 999999999;
short j = 9999;
int[] k = {1,2,3,4,5,6};
String l = "friendly";
String m;
}

然后编译成APK以后通过IDE解析我们可以获取到Smali文件,通过IDE打开文件后我们可以得到如下信息

.class public Ltop/xiaoheijia/www/netdemo/LoginActivity;
.super Landroid/support/v7/app/AppCompatActivity;
.source "LoginActivity.java"

\# instance fields
.field private a:Ljava/lang/String;

.field public b:F

.field protected c:D

.field d:Z

.field e:Z

.field f:I

.field g:C

.field h:B

.field i:J

.field j:S

.field k:[I

.field l:Ljava/lang/String;

.field m:Ljava/lang/String;

\# direct methods

.method public constructor <init>()V
    .locals 2

    .line 48
    invoke-direct {p0}, Landroid/support/v7/app/AppCompatActivity;-><init>()V

    const-string v0, "private"

    .line 49
    iput-object v0, p0, Ltop/xiaoheijia/www/netdemo/LoginActivity;->a:Ljava/lang/String;

    const/high16 v0, 0x3f800000# 1.0f

    .line 50
    iput v0, p0, Ltop/xiaoheijia/www/netdemo/LoginActivity;->b:F

    const-wide/high16 v0, 0x3ff0000000000000L# 1.0

    .line 51
    iput-wide v0, p0, Ltop/xiaoheijia/www/netdemo/LoginActivity;->c:D

    const/4 v0, 0x1

    .line 52
    iput-boolean v0, p0, Ltop/xiaoheijia/www/netdemo/LoginActivity;->d:Z

    const/4 v0, 0x0

    .line 53
    iput-boolean v0, p0, Ltop/xiaoheijia/www/netdemo/LoginActivity;->e:Z

    .line 54
    iput v0, p0, Ltop/xiaoheijia/www/netdemo/LoginActivity;->f:I

    const/16 v0, 0x67

    .line 55
    iput-char v0, p0, Ltop/xiaoheijia/www/netdemo/LoginActivity;->g:C

    const/16 v0, 0x68

    .line 56
    iput-byte v0, p0, Ltop/xiaoheijia/www/netdemo/LoginActivity;->h:B

    const-wide/32 v0, 0x3b9ac9ff

    .line 57
    iput-wide v0, p0, Ltop/xiaoheijia/www/netdemo/LoginActivity;->i:J

    const/16 v0, 0x270f

    .line 58
    iput-short v0, p0, Ltop/xiaoheijia/www/netdemo/LoginActivity;->j:S

    const/4 v0, 0x6

    .line 59
    new-array v0, v0, [I

    fill-array-data v0, :array_0

    iput-object v0, p0, Ltop/xiaoheijia/www/netdemo/LoginActivity;->k:[I

    const-string v0, "friendly"

    .line 60
    iput-object v0, p0, Ltop/xiaoheijia/www/netdemo/LoginActivity;->l:Ljava/lang/String;

    return-void

    nop

    :array_0
    .array-data 4
        0x1
        0x2
        0x3
        0x4
        0x5
        0x6
    .end array-data
.end method

下面我们分段来说明一个

1.文件头内容

.class public Ltop/xiaoheijia/www/netdemo/LoginActivity;
.super Landroid/support/v7/app/AppCompatActivity;
.source "LoginActivity.java"

第一行描述该Java文件类的完整包路径以及类修饰符,也就是我们最早写在java里的如下代码

public class LoginActivity

top/xiaoheijia/www/netdemo/就是包名路径
可能有些人注意到了
第一行里面包路径前面有一个 L
这个 L 表示后面接入的是一个对象。

第二行表示当前类集成的父类,同时 L 表示对象

.super Landroid/support/v7/app/AppCompatActivity;

第三行表示当前操作的java文件源的名称

.source "LoginActivity.java"

2.变量声明

# instance fields
.field private a:Ljava/lang/String;

.field public b:F

.field protected c:D

.field d:Z

.field e:Z

.field f:I

.field g:C

.field h:B

.field i:J

.field j:S

.field k:[I

.field l:Ljava/lang/String;

.field m:Ljava/lang/String;

这就是我们声明的 a-m的变量
在Smali中 # 表示注释,instance fields 表示文件内的声明
对比之前的Java 代码我们可以得出如下信息

  • 前表示代码中的变量名称,后面表示变量类型
  • Ljava/lang/String 表示 String对象类型
  • F 表示 float 类型
  • D 表示 double 类型
  • Z 表示 boolean 类型
  • I 表示 int 类型
  • C 表示 char 类型
  • B 表示 byte 类型
  • J 表示 long 类型
  • S 表示 short 类型
  • [I 表示 int 类型的数组
  • 也就是说 [ 后面接某种类型表示声明某种类型的数组

3.构造器以及变量赋值

到现在为止,我们都还没有看到我们的在代码中声明的变量被赋值,莫慌,大家往下看,可以看到如下代码

# direct methods
.method public constructor <init>()V
    ………………
.end method

上面就是函数体的表示,.method 表示函数体的开始,end method 表示函数体结束
看函数体函数名 public constructor ()V
constructor 顾名思义就是构造器。也就是我们定义的构造函数,如果我们没有定义,那么就是默认的无参构造
那上面那段Smali我们就可以还原源代码得到

public LoginActivity(){
    ………………
}

由此可见,我们声明全局变量时,给变量赋值实际上实在构造器里面才被执行的。
翻译过来也能能明显的看出来 Smali中 函数()V 就是表示原JAVA函数中的()里的参数类型以及返回值

  • 此处 V 表示void,无返回类型

那如果多参有返回值如何写呢?请看下列代码

//Java Code
public int getAge(String name){
    ………………
}

#Smali Code
.method public getAge <Ljava/lang/String;>()I
    ………………
.end method

其他形式函数或者构造函数以此类推,当然有人说函数并没有声明无返回类型为啥会显示 V ?
V 只是表示不需要返回,你见过有返回的构造函数???

不哔哔,继续看函数体内部第一行Smali 代码

.locals 2

这玩意表示啥?表示当前函数内局部变量的个数,例如:.locals n 那么就是表示函数内有n-1个局部变量,也就是在函数里看到的v0、v1等字段。或许说局部变量不是叫寄存器更合适。至于为什么请往后看。

接着往下看

.line 48
invoke-direct {p0}, Landroid/support/v7/app/AppCompatActivity;-><init>()V

.line 48 表示此处是源代码多少行。
invoke-direct 表示函数调用
P0 表示this
Landroid/support/v7/app/AppCompatActivity;->()V 表示 AppCompatActivity 构造
第二行代码完整的意思是,在 this(当前类)构造时,去执行父类的构造。
继续往后看,就是我们的赋值代码了

const-string v0, "private"

.line 49
iput-object v0, p0, Ltop/xiaoheijia/www/netdemo/LoginActivity;->a:Ljava/lang/String;

创建局部变量v0,存储字符串 “private”,之后把v0的内容赋值给LoginActivity里的a变量,类型为String
后面b、c、d自行参考
但是m的赋值是找不到的,因为在声明的时候就没有给它,所以此处不会创建

下一篇:我的Android逆向学习之旅(二)——Dalvik指令集

1核/512M/20M独享/洛杉矶/128元/年 ---- 双十一特价 102.4元/年
2核/512M/20M独享/洛杉矶CN2 GT/229元/年/39元/月 ---- 双十一特价 183.2元/年/31.2元/月
2核/1G/5M独享/贵州电信/260元/年/40元/月 ---- 双十一特价 208元/年/32元/月
双十一活动时间:10月29日-11月19日!

Last modification:June 28th, 2018 at 08:25 pm
If you think my article is useful to you, please feel free to appreciate

Leave a Comment