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. 整合多个maven工程时Spring配置加载JDBC问题

    问题叙述: 两个工程都通过JDBC访问mysql数据库,各自运行OK, 但合并成一个maven工程后,发现前一个工程访问数据库异常,貌似拿不到自己的DAO. 解决办法: 发现这两个工程的xml配置中, ...

  2. luogu P4677 山区建小学 |dp

    题目描述 政府在某山区修建了一条道路,恰好穿越总共nnn个村庄的每个村庄一次,没有回路或交叉,任意两个村庄只能通过这条路来往.已知任意两个相邻的村庄之间的距离为did_idi​(为正整数),其中,0& ...

  3. JsonModel的使用

    本人最近在开发一款医疗类的APP 发现接口返回的数据很复杂 手动解析的话对新手来说就是一场灾难 在分解成所需要的model类型时工作量非常的大,于是从网上查阅相关资料,发现JsonModel这个第三方 ...

  4. git 使用详解(7)-- 远程仓库的使用

    要参与任何一个 Git 项目的协作,必须要了解该如何管理远程仓库.远程仓库是指 托管在网络上 的项目仓库,可能会有好多个,其中有些你 只能读,另外有些可以写.同他人协作开发某个项目时,需要管理这些远程 ...

  5. openstack学习之neutron ml2初始化代码分析

    这里没有 去详细考虑neutron server怎么初始化的,而是直接从加载插件的地方开始分析.首先我们看下下面这个文件. Neutron/api/v2/router.py class APIRout ...

  6. JS操作document对象

    找到对象: document.getElementById():返回对拥有指定 id 的第一个对象的引用. document.getElementsByName():返回带有指定名称的对象集合. do ...

  7. drf源码分析系列---版本控制

    版本的使用 第一步:写路由url(r'^api/(P<version>\w+)/user/$',views.UserView.as_view()), 第二步:写模块导入from rest_ ...

  8. js方法中参数传过来的值包含括号

    前提,传递的id为变量值,比如从后台获取数据循环,在每个循环里调用shenpi()方法,假设传的id包含括号,例如 20190329100833(更正) 这样的数据,那么直接调用会报错,控制台会报错: ...

  9. re常用模块

    re模块:从字符串里面找到特定的字符串 re的基本语法(匹配规则) import re s = '王大炮打炮被大炮打死了 王大炮打炮被大炮打死了' ^:开头 print(re.findall('^王大 ...

  10. Django forms组件里的ChoiceField、ModelChoiceField和ModelMutipleChoiceField的区别

    阅读简要 首先我们要明白Django forms组件里的ChoiceField.ModelChoiceField和ModelMutipleChoiceField是继承关系 ChoiceField 1. ...