2.1 smali 语言简介

1.smali

apk文件通过apktool反编译出来的都有一个smali文件夹,里面都是以.smali结尾的文件。

smali语言是Davlik的寄存器语言,语法上和汇编语言相似,Dalvik VM与JVM的最大的区别之一就是Dalvik VM是基于寄存器的。基于寄存器的意思是,在smali里的所有操作都必须经过寄存器来进行。

2.基本数据类型

B—byte

C—char

D—double

F—float

I—int

S—short

V—void

J—long

Z—boolean

注意J、Z两个不是对应类型的首字母;

在dalvik字节码中,寄存器都是32位的,能够支持任何类型,Long和Double类型是64位的,需要2个寄存器;

V 只能用于返回值类型;

3.数组和对象是引用类型

数组的表示方式是在基本类型前加上前中括号“[”,例如int数组和float数组分别表示为:[I、[F;

对象类型以L作为开头来表示,格式是Lpackage/ClassName;(用分号表示对象结束是必须的),示例:

String对象在smali中为:Ljava/lang/String;

Class1对象的一个boolean成员表示为:Lcom/disney/Class1;->isRunning:Z

Class1对象的一个String对象成员表示为:Lcom/disney/Class1;->name:Ljava/lang/String;

可以总结为格式为对象类型->成员名:成员类型,->表示所属关系,类型尾部必须包括一个分号。

内部类表示为:Lpackage/ClassName$innerObjectName;,也就是在内部类前加“$”符号。

4.函数

格式:Func-Name (Para-Type1Para-Type2Para-Type3…)Return-Type

返回类型在最后,参数之间没有任何分隔符,示例:

void fun()

fun()V

boolean fun(int, int, int)

fun(III)Z

String fun(boolean, int[], int[], String, long)

fun(Z[I[ILjava/lang/String;J)Ljava/lang/String;

5.语法

#标记,构造函数的返回类型为V,名字为<init>

# static fields        定义静态变量的标记

# instance fields      定义实例变量的标记

# direct methods       定义静态方法的标记??

# virtual methods      定义非静态方法的标记??

.class public Lcom/disney/WMW/WMWActivity;

.super Lcom/disney/common/BaseActivity;

.source "WMWActivity.java"

.implements Lcom/burstly/lib/ui/IBurstlyAdListener;

上面这几行代码表示类名,父类名,源文件名,实现了接口。

.annotation

内部类

.end annotation

6.局部变量

本地寄存器(local register,非参寄存器)用v开头数字结尾的符号来表示,如v0、v1、v2、…,

参数寄存器(parameter register)用p开头数字结尾的符号来表示,如p0、p1、p2、…,

.registers 用来标明方法中寄存器的总数,即参数寄存器和非参寄存器的总数。

.local 0,标明在这个函数中最少要用到的本地寄存器的个数,出现在方法中的第一行。在这里,由于只需要调用一个父类的onDestroy()处理,所以只需要用到p0,所以使用到的本地寄存器数为0,在植入代码后不要忘记可能要修改.local的值。

如 .local 4,则可以使用的寄存器是v0-v3。

当一个方法被调用的时候,方法的参数被置于最后N个寄存器中。

在实例函数中,p0代指“this”,p1表示函数的第一个参数,p2代表函数中的第二个参数…,

在static函数中,p1表示函数的第一个参数,p2代表函数中的第二个参数…,因为Java的static方法中没有this方法。

示例:

const/4 v0, 0x0

iput-boolean v0, p0, Lcom/disney/Class1;->isRunning:Z

上面第一句中把值0x0存到v0本地寄存器中,

第二句用iput-boolean指令把v0中的值存放到this.isRunning这个成员变量中,即this.isRunning = false; 因为在实例函数中p0代表的是“this”,Lcom/disney/Class1;是类名,对应实例是p0。

7.成员变量和指令

# static fields

.field private static final PREFS_INSTALLATION_ID java/lang/String; = "installationId"

# instance fields

.field private _activityPackageName java/lang/String;

获取和操作静态成员变量和实例成员变量有不同的指令。

读取的指令有:iget、sget、iget-boolean、sget-boolean、iget-object、sget-object等,

赋值的指令有:iput、sput、iput-boolean、sput-boolean、iput-object、sput-object等。

带“-object”表示操作的成员变量是对象类型,没有“-object”后缀的表示操作的成员变量对象是基本数据类型,特别地boolean类型则使用带“-boolean”的指令操作。

获取static fields的指令示例:

sget-object v0, Lcom/disney/Class1;->PREFS_INSTALLATION_ID:Ljava/lang/String;

上句中sget-object指令把PREFS_INSTALLATION_ID这个String成员变量获取并放到v0寄存器中。

获取instance fields的指令与static fields的类似,需要指明对象所属的实例。示例:

iget-object v0, p0, Lcom/disney/Class1;->_view:Lcom/disney/Class2;

上句iget-object指令比sget-object多了一个参数p0,就是该变量所在类的实例,在这里就是p0即“this”。

put指令的使用和get指令是统一的,示例:

const/4 v3, 0x0

sput-object v3, Lcom/disney/Class1;->globalIapHandler:Lcom/disney/config/GlobalPurchaseHandler;

上句相当于Class1.globalIapHandler = null;

8.函数调用

smali中的函数调用也分为direct和virtual两种类型,direct method就是private函数,public和protected函数都属于virtual method。在调用函数时,有invoke-direct,invoke-virtual,invoke-static、invoke-super以及invoke-interface等几种不同的指令。还有invoke-XXX/range 指令的,这是参数多于4个的时候调用的指令,比较少见。

invoke-static:就是调用static函数的,示例:

invoke-static {}, Lcom/disney/Class1;->fun()Z

上句invoke-static后面有一对大括号“{}”,内部是调用该方法的实例和参数列表,由于这是static方法也不需要参数,所以{}内为空。

invoke-super:调用父类方法,在onCreate、onDestroy等方法都能看到。

invoke-direct:调用private函数,示例:

invoke-direct {p0}, Lcom/disney/Class1;->getGlobalIapHandler()Lcom/disney/config/GlobalPurchaseHandler;

上句即this->getGlobalIapHandler(),函数GlobalPurchaseHandler getGlobalIapHandler()是定义在Class1中的一个private函数。

invoke-virtual:用于调用protected或public函数,示例:

sget-object v0, Lcom/disney/Class1;->shareHandler:Landroid/os/Handler;

invoke-virtual {v0, v3}, Landroid/os/Handler;->removeCallbacksAndMessages(Ljava/lang/Object;)V

上句v0是shareHandler android/os/Handler,v3是传递给removeCallbackAndMessage方法的Ljava/lang/Object参数。

9.获取函数调用结果

在smali里调用函数和返回函数结果需要分开来完成,在调用的函数返回非void后,用move-result(返回基本数据类型)和move-result-object(返回对象)指令获取返回结果。

示例:

const/4 v2, 0x0

invoke-virtual {p0, v2}, Lcom/disney/Class1;->getPreferences(I)Landroid/content/SharedPreferences;

move-result-object v1

上句v1保存的就是调用this.getPreferences(int)方法返回的SharedPreferences实例。

10.函数体

.method   和  .end method之间。

示例:

.method protected onDestroy()V

.locals 0

.prologue

.line 277

invoke-super {p0}, Lcom/disney/common/BaseActivity;->onDestroy()V

.line 279

return-void

.end method

上段是onDestroy()函数。

.line 277,标注了该代码在原Java文件中的行数,它不是必须的,去掉没有编译问题。它在出错时可以指出错误位置,jd-gui工具即是通过分析这些信息将smali代码还原成Java代码的。

11.条件语法

if-eq p1, v0, :cond_8

:cond_8

invoke-direct {p0}, Lcom/paul/test/a;->d()V

上段表示如果p1和v0相等,则执行cond_8的流程:调用com.paul.test.a的d()方法

if-ne p1, v0, :cond_b

:cond_b

const/4 v0, 0x0

invoke-virtual {p0, v0}, Lcom/paul/test/a;->setPressed(Z)V

invoke-super {p0, p1, p2}, Landroid/view/View;->onKeyUp(ILandroid/view/KeyEvent;)Z

move-result v0

上段表示不相等则执行cond_b的流程。

分析Android APK- smali 语言简介的更多相关文章

  1. Android apk逆向实战

    简介 逆向Android apk其实是一个分析Android apk的一个过程,必须了解Android程序开发的流程.结构.语句分支.解密原理等等. 功能 破解一个注册验证程序(自写一个简单的注册验证 ...

  2. Android逆向分析(2) APK的打包与安装

    http://blog.zhaiyifan.cn/2016/02/13/android-reverse-2/ 2/18日增加对aidl和java编译的描述. 前言 上一次我们反编译了手Q,并遇到了Ap ...

  3. Android APK程序的smali动态调试

    本文博客地址:http://blog.csdn.net/qq1084283172/article/details/71250622 一.Apktool的下载和安装 Apktool是Android逆向分 ...

  4. apk反编译(2)smali语言及文件

    Smali语言是Davlik的虚拟机使用的一种语言,用toolapk反编译apk后,可以见到大量的.smali文件. 可以按照smali语法对其修改,然后重新生成一个未签名的apk. 下面是一个示例: ...

  5. smali 语言语法

    Androidkiller 可以反编译Android的apk,生成一种.smali代码.(这理解好像不对) 网上找了一篇smali的语法手册,可以方便查找,文章名<Smali文件语法参考> ...

  6. Android Apk加固的初步实现思路(dex整体加固)

    一.前 言 Android Apk加固的发展已经有一段时间了,相对来说本篇博客要记录的Android加壳的实现思路是4年的东西了,已经被老鸟玩烂了,Android加固的安全厂商也不会采用这么粗犷的方式 ...

  7. 【转】android Apk打包过程概述_android是如何打包apk的

    最近看了老罗分析android资源管理和apk打包流程的博客,参考其他一些资料,做了一下整理,脱离繁琐的打包细节和数据结构,从整体上概述了apk打包的整个流程.   流程概述: 1.打包资源文件,生成 ...

  8. android apk 逆向中常用工具一览

    关于apk 逆向中的一些工具的使用,看了不少文章,也使用过有很长一段时间了,今天对此做一总结: 几种文件之间的转换命令: 1. odex -> smali java -jar  baksmali ...

  9. 反编译Android APK及防止APK程序被反编译

    怎么逆向工程对Android Apk 进行反编译 google Android开发是开源的,开发过程中有些时候会遇到一些功能,自己不知道该怎么做,然而别的软件里面已经有了,这个时候可以采用反编译的方式 ...

随机推荐

  1. 机器学习-Python 01

    机器学习中最常用最流行的语言工具现阶段应该是Python, 这篇文章主要介绍一些常用的Python语法知识.本篇博文适合那些有其他语言基础的程序员们,如果一点基础都没有,我建议先跳过.博主以前是做移动 ...

  2. 【译】Visual Studio 2019 中 WPF & UWP 的 XAML 开发工具新特性

    原文 | Dmitry 翻译 | 郑子铭 自Visual Studio 2019推出以来,我们为使用WPF或UWP桌面应用程序的XAML开发人员发布了许多新功能.在本周的 Visual Studio ...

  3. Python3 并发编程1

    目录 操作系统发展 穿孔卡片 批处理 多道技术(单核) 并发与并行 进程 程序与进程 进程调度 进程的三个状态 同步和异步 阻塞与非阻塞 僵尸进程与孤儿进程 守护进程 Python中的进程操作 Pro ...

  4. Python3 函数进阶1

    目录 闭包函数 什么是闭包函数 闭包函数的作用 装饰器 什么是装饰器 无参装饰器 有参装饰器 闭包函数 什么是闭包函数 闭包函数本质上就是函数嵌套和高阶函数 闭包函数的满足条件: 必须嵌套函数 内嵌函 ...

  5. 改变SecureCRT的背景颜色

    1.在使用secureCRT客户端时,可以连接服务器,默认为白色底. 2.要进行对把底色的白色改为黑色的底色,右击的窗口的位置. 3.下拉菜单中点击 Session Options 4.点击Appea ...

  6. JMeter之SteppingShape

    1.背景 其实是这样的,最近包括以前都有同事问过宝路一个问题:JMeter测试计划中涉及到梯度压测时,整个测试计划执行完毕,聚合报告看的是整体的结果啊!并不能直观看到每个梯度下的吞吐量的值(虽然可以通 ...

  7. jenkins+gitlab+webhook实现自动发布

    实验环境   Jenkins:192.168.1.15 Gitlab:192.168.1.14   一.Jenkins配置   1:安装gitlab hook plugin插件 2:新建一个job 3 ...

  8. linux目录的读(r)、写(w)、执行(x)权限说明

    linux目录的读.写.执行权限说明 1.可读r #表示具有浏览目录下面文件及子目录的权限.即ls dir 1)如果没有x权限,不能进到目录里,即无法 cd dir 2)如果没有x权限,ls列表可以看 ...

  9. Python爬虫基础——re模块的提取和匹配

    re是Python的一个第三方库. 为了能更直观的看出re的效果,我们先新建一个HTML网页文件(可直接复制): index.html <!DOCTYPE html> <html l ...

  10. NodeJS2-6环境&调试----debug

    13_debug.js //测试的脚本 function test1() { const a = parseInt(Math.random() * 10); const b = parseInt(Ma ...