Smali语法(一)

Smali语法(一)

本文主要介绍下Smali语法相关.

一: 简介

Smali是一种用于Android应用逆向工程和动态代码修改的小型低级字节码语言,它是Dalvik虚拟机(Virtual Machine)指令集的一种文本表示形式。它并非Java源代码的直接映射,而是更接近于VM实际运行的机器码。SMALI由四部分组成:

  1. 类(Class): 定义了类的数据结构,包括字段、方法等。
  2. 字段(Field): 表示类变量或实例变量。
  3. 调用(Call): 描述方法的调用,包括方法名、参数列表和返回值类型。
  4. 条件和循环(Conditions and Loops): 控制流指令,如if-else、while等。

二: Smali文件格式.

注: 本篇文章用到代码均是来自.v2rayNG.apk

2.1: 头信息

smali文件的头三行描述了当前类的一些信息,格式如下:

  1. .class <访问权限> <修饰关键字> <类名>

指令指定了当前类的类名.

  1. .super <父类名>

指令指定了当前类的父类

  1. .source <源文件名>

指令指定了当前类的源文件.

我们以MainActivity.smali为例:

.class public final Lcom/v2ray/ang/ui/MainActivity;
.super Lcom/v2ray/ang/ui/BaseActivity;
.source "MainActivity.kt"

MessageUtil.smali如下:

.class public final Lcom/v2ray/ang/util/MessageUtil;
.super Ljava/lang/Object;
.source "MessageUtil.kt"
2.2: 接口信息

MainActivity.smali 头信息紧跟着如下:

# interfaces
.implements Lcom/google/android/material/navigation/NavigationView$OnNavigationItemSelectedListener;

.implements这一行通常出现在类声明.class中,它的作用是声明该类实现了哪些接口(Interface).

也就是代表了MainActivity实现了NavigationView$OnNavigationItemSelectedListener接口.

2.3: 注解

如果一个类使用了注解,那smali代码中会使用".annotation"指令指出.

具体的格式如下:

#annotations

.annotation <注解属性> <注解类名>

.end annotation

2.4: 定义字段

smali中使用.field 来定义字段.

如MainActivity.smali 中定义了修饰符 private 私有 final 不可变的 类型 Lkotlin/Lazy. 用于延时加载的适配器类型字段: adapter$delegate.

# instance fields
.field private final adapter$delegate:Lkotlin/Lazy;
2.5: 定义方法

定义方法则是: 以 .method开始, .end method 结束;

.method public constructor <init>()V
    .registers 8

    .line 46
    invoke-direct {p0}, Lcom/v2ray/ang/ui/BaseActivity;-><init>()V

    .line 49
    new-instance v0, Lcom/v2ray/ang/ui/MainActivity$adapter$2;

    invoke-direct {v0, p0}, Lcom/v2ray/ang/ui/MainActivity$adapter$2;-><init>(Lcom/v2ray/ang/ui/MainActivity;)V

    check-cast v0, Lkotlin/jvm/functions/Function0;

    invoke-static {v0}, Lkotlin/LazyKt;->lazy(Lkotlin/jvm/functions/Function0;)Lkotlin/Lazy;

    move-result-object v0

    iput-object v0, p0, Lcom/v2ray/ang/ui/MainActivity;->adapter$delegate:Lkotlin/Lazy;

    .line 50
    sget-object v0, Lcom/v2ray/ang/ui/MainActivity$mainStorage$2;->INSTANCE:Lcom/v2ray/ang/ui/MainActivity$mainStorage$2;

    check-cast v0, Lkotlin/jvm/functions/Function0;

    invoke-static {v0}, Lkotlin/LazyKt;->lazy(Lkotlin/jvm/functions/Function0;)Lkotlin/Lazy;

    move-result-object v0

    iput-object v0, p0, Lcom/v2ray/ang/ui/MainActivity;->mainStorage$delegate:Lkotlin/Lazy;

    .line 51
    sget-object v0, Lcom/v2ray/ang/ui/MainActivity$settingsStorage$2;->INSTANCE:Lcom/v2ray/ang/ui/MainActivity$settingsStorage$2;

    check-cast v0, Lkotlin/jvm/functions/Function0;

    invoke-static {v0}, Lkotlin/LazyKt;->lazy(Lkotlin/jvm/functions/Function0;)Lkotlin/Lazy;

    move-result-object v0

    iput-object v0, p0, Lcom/v2ray/ang/ui/MainActivity;->settingsStorage$delegate:Lkotlin/Lazy;

    .line 52
    new-instance v0, Landroidx/activity/result/contract/ActivityResultContracts$StartActivityForResult;

    invoke-direct {v0}, Landroidx/activity/result/contract/ActivityResultContracts$StartActivityForResult;-><init>()V

    check-cast v0, Landroidx/activity/result/contract/ActivityResultContract;

    new-instance v1, Lcom/v2ray/ang/ui/MainActivity$$ExternalSyntheticLambda12;

    invoke-direct {v1, p0}, Lcom/v2ray/ang/ui/MainActivity$$ExternalSyntheticLambda12;-><init>(Lcom/v2ray/ang/ui/MainActivity;)V

    invoke-virtual {p0, v0, v1}, Lcom/v2ray/ang/ui/MainActivity;->registerForActivityResult(Landroidx/activity/result/contract/ActivityResultContract;Landroidx/activity/result/ActivityResultCallback;)Landroidx/activity/result/ActivityResultLauncher;

    move-result-object v0

    const-string v1, "registerForActivityResul\u2026rtV2Ray()\n        }\n    }"

    invoke-static {v0, v1}, Lkotlin/jvm/internal/Intrinsics;->checkNotNullExpressionValue(Ljava/lang/Object;Ljava/lang/String;)V

    iput-object v0, p0, Lcom/v2ray/ang/ui/MainActivity;->requestVpnPermission:Landroidx/activity/result/ActivityResultLauncher;

    .line 58
    move-object v0, p0

    check-cast v0, Landroidx/activity/ComponentActivity;

    .line 664
    new-instance v1, Lcom/v2ray/ang/ui/MainActivity$special$$inlined$viewModels$default$1;

    invoke-direct {v1, v0}, Lcom/v2ray/ang/ui/MainActivity$special$$inlined$viewModels$default$1;-><init>(Landroidx/activity/ComponentActivity;)V

    check-cast v1, Lkotlin/jvm/functions/Function0;

    .line 668
    new-instance v2, Landroidx/lifecycle/ViewModelLazy;

    const-class v3, Lcom/v2ray/ang/viewmodel/MainViewModel;

    invoke-static {v3}, Lkotlin/jvm/internal/Reflection;->getOrCreateKotlinClass(Ljava/lang/Class;)Lkotlin/reflect/KClass;

    move-result-object v3

    .line 670
    new-instance v4, Lcom/v2ray/ang/ui/MainActivity$special$$inlined$viewModels$default$2;

    invoke-direct {v4, v0}, Lcom/v2ray/ang/ui/MainActivity$special$$inlined$viewModels$default$2;-><init>(Landroidx/activity/ComponentActivity;)V

    check-cast v4, Lkotlin/jvm/functions/Function0;

    .line 672
    new-instance v5, Lcom/v2ray/ang/ui/MainActivity$special$$inlined$viewModels$default$3;

    const/4 v6, 0x0

    invoke-direct {v5, v6, v0}, Lcom/v2ray/ang/ui/MainActivity$special$$inlined$viewModels$default$3;-><init>(Lkotlin/jvm/functions/Function0;Landroidx/activity/ComponentActivity;)V

    check-cast v5, Lkotlin/jvm/functions/Function0;

    .line 668
    invoke-direct {v2, v3, v4, v1, v5}, Landroidx/lifecycle/ViewModelLazy;-><init>(Lkotlin/reflect/KClass;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function0;)V

    check-cast v2, Lkotlin/Lazy;

    .line 58
    iput-object v2, p0, Lcom/v2ray/ang/ui/MainActivity;->mainViewModel$delegate:Lkotlin/Lazy;

    .line 356
    new-instance v0, Landroidx/activity/result/contract/ActivityResultContracts$StartActivityForResult;

    invoke-direct {v0}, Landroidx/activity/result/contract/ActivityResultContracts$StartActivityForResult;-><init>()V

    check-cast v0, Landroidx/activity/result/contract/ActivityResultContract;

    new-instance v1, Lcom/v2ray/ang/ui/MainActivity$$ExternalSyntheticLambda10;

    invoke-direct {v1, p0}, Lcom/v2ray/ang/ui/MainActivity$$ExternalSyntheticLambda10;-><init>(Lcom/v2ray/ang/ui/MainActivity;)V

    invoke-virtual {p0, v0, v1}, Lcom/v2ray/ang/ui/MainActivity;->registerForActivityResult(Landroidx/activity/result/contract/ActivityResultContract;Landroidx/activity/result/ActivityResultCallback;)Landroidx/activity/result/ActivityResultLauncher;

    move-result-object v0

    const-string v1, "registerForActivityResul\u2026RESULT\"))\n        }\n    }"

    invoke-static {v0, v1}, Lkotlin/jvm/internal/Intrinsics;->checkNotNullExpressionValue(Ljava/lang/Object;Ljava/lang/String;)V

    iput-object v0, p0, Lcom/v2ray/ang/ui/MainActivity;->scanQRCodeForConfig:Landroidx/activity/result/ActivityResultLauncher;

    .line 362
    new-instance v0, Landroidx/activity/result/contract/ActivityResultContracts$StartActivityForResult;

    invoke-direct {v0}, Landroidx/activity/result/contract/ActivityResultContracts$StartActivityForResult;-><init>()V

    check-cast v0, Landroidx/activity/result/contract/ActivityResultContract;

    new-instance v2, Lcom/v2ray/ang/ui/MainActivity$$ExternalSyntheticLambda9;

    invoke-direct {v2, p0}, Lcom/v2ray/ang/ui/MainActivity$$ExternalSyntheticLambda9;-><init>(Lcom/v2ray/ang/ui/MainActivity;)V

    invoke-virtual {p0, v0, v2}, Lcom/v2ray/ang/ui/MainActivity;->registerForActivityResult(Landroidx/activity/result/contract/ActivityResultContract;Landroidx/activity/result/ActivityResultCallback;)Landroidx/activity/result/ActivityResultLauncher;

    move-result-object v0

    invoke-static {v0, v1}, Lkotlin/jvm/internal/Intrinsics;->checkNotNullExpressionValue(Ljava/lang/Object;Ljava/lang/String;)V

    iput-object v0, p0, Lcom/v2ray/ang/ui/MainActivity;->scanQRCodeForUrlToCustomConfig:Landroidx/activity/result/ActivityResultLauncher;

    .line 533
    new-instance v0, Landroidx/activity/result/contract/ActivityResultContracts$StartActivityForResult;

    invoke-direct {v0}, Landroidx/activity/result/contract/ActivityResultContracts$StartActivityForResult;-><init>()V

    check-cast v0, Landroidx/activity/result/contract/ActivityResultContract;

    new-instance v1, Lcom/v2ray/ang/ui/MainActivity$$ExternalSyntheticLambda11;

    invoke-direct {v1, p0}, Lcom/v2ray/ang/ui/MainActivity$$ExternalSyntheticLambda11;-><init>(Lcom/v2ray/ang/ui/MainActivity;)V

    invoke-virtual {p0, v0, v1}, Lcom/v2ray/ang/ui/MainActivity;->registerForActivityResult(Landroidx/activity/result/contract/ActivityResultContract;Landroidx/activity/result/ActivityResultCallback;)Landroidx/activity/result/ActivityResultLauncher;

    move-result-object v0

    const-string v1, "registerForActivityResul\u2026mUri(uri)\n        }\n    }"

    invoke-static {v0, v1}, Lkotlin/jvm/internal/Intrinsics;->checkNotNullExpressionValue(Ljava/lang/Object;Ljava/lang/String;)V

    iput-object v0, p0, Lcom/v2ray/ang/ui/MainActivity;->chooseFileForCustomConfig:Landroidx/activity/result/ActivityResultLauncher;

    return-void
.end method

如上所示: .method public constructor ()V

则代表了无参构造.

注意这里.registers则是指定方法内使用寄存器的总数.

  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值