什么是Smali

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

因为安卓软件编译后,就得不到源代码了,我们只可以通过反编译后的Smail代码去修改来实现逆向的目的。

静态分析Android程序的两种方法

阅读反编译生成的Dalvik字节码。

  • 使用AndroidKiller_1.3.1分析dex文件
  • 使用MT管理器分析dex文件
  • 使用jadx查看

头信息------类的主体信息

在打开smali文件的时候,它的头三行描述了当前类的一些信息

.class <访问权限> [关键修饰字] <类名>;
.super <父类名>
.source <源文件名>
Java代码如下:
public class MainActivity extends AppComatActivity{
//......
}
对应的Smali代码如下:
.class Lcom/example/myapplication/MainActivity$1; //该表示MainActivity是该包的一个对象
.super Ljava/lang/Object;
.source "MainActivity.java"

.class 指令表示当前的类名,类的访问权限是public,类名是Lcom/example/myapplication/MainActivity$1; ,类开头的L是遵循Dalvik字节码的相关约定,表示后面跟随的字符串是一个类。

.super指定了当前类所继承的父类,后面指的就是这个父类的类名,L表示后面跟的字符串是一个类

.source指定了当前类的源文件名

数据原始类型

  • B---byte
  • C---char
  • D---double
  • F---float
  • I---int
  • L---long
  • S---short
  • V---void
  • Z---boolean
  • [XXX---array
  • Lxxx/yyy---object

Smali的数组表示

在基本类型前加上"["即表示该类型的数组;如

[I:表示整型的数组;[F:表示浮点型float的数组

  • 如果是对象类型,则以L作为开头,格式是LpackageName/objectName;如Ljava/lang/String;表示String是该包的一个对象。

  • 类对象表示为LpackageName/objectName;类对象中的内部类则使用"$"来连接。

Smali方法的定义

方法的一般定义为:

Func-Name(Para-Type1Para-Type-2Para-Type...)Return-Type

参数之间没有任何间隔;如

Hello()V:表示 void hello()

Hello(III)Z表示:Boolean hello(int,int,int)

Hello(Z[I[ILjava/lang/String;L)Ljava/lang/String; 表示:String Hello(boolean,int[],int[],String,,long)

Smali的一些关键词

  • .filed private isFlage:z 定义变量
  • .method 方法
  • .parameter 方法参数
  • .prologue 方法开始
  • .line 此方法位于第123行
  • .invoke-super 调用父函数
  • .const/high16 v0,0x7fo3 把0x7fo3赋值给v0
  • .invoke-direct 调用函数
  • .return-void 函数返回void
  • .end-method 函数结束
  • new-instance 创建实列
  • input-object 对象赋值
  • iget-object 调用对象
  • invoke-static 调用静态函数

Smali的条件跳转

  • "if-eq vA,vB:cond_" 如果vA等于vB则跳转到cond**(eq==equal)

  • "if-ne vA,vB:cond_" 如果vA不等于vB则跳转到cond**

    (nq == not equal)

  • "if-lt vA,vB:cond_" 如果vA小于vB则跳转到cond**

    (lt == less)

  • "if-ge vA,vB:cond_" 如果vA大于等于vB则跳转到cond**

    (ge==greater equal)

  • "if-gt vA,vB:cond_" 如果vA大于vB则跳转到cond**

  • "if-le vA,vB:cond_" 如果vA小于等于vB则跳转到cond**

  • "if-eqz vA :cond_" 如果vA等于0则跳转到cond**

  • "if-nez vA :cond_" 如果vA不等于0则跳转到cond**

  • "if-ltz vA :cond_" 如果vA小于0则跳转到cond**

  • "if-gez vA :cond_" 如果vA大于等于0则跳转到cond**

  • "if-gtz vA :cond_" 如果vA大于0则跳转到cond**

  • "if-lez vA :cond_" 如果vA小于于等于0则跳转到cond**

Smali中内部类声明

一般来说在Smail文件中是这个样子的:

annotations

.annotation system Ldalvik/annotation/MemberClasses;

value = {

Lcom/aaa$qqq;

Lcom/aaa$wwww;

}

.end annotation

这个声明式内部类的声明;aaa这个类它有两个内部类----qqq和www。

Smali类的信息

.class public Lcom/aaaaa;

.super Lcom/bbbbb;

.source "ccccc.java"

这是一个由ccccc.java编译得到的smail文件(第三行)

它是com.aaaaa这个package下的一个类(第一行)

继承自com.bbbbb这个类(第二行)

Smali类中成员变量表示和操作

  • 成员变量格式是:.filed public/private[static][final] varName<类型>
  • 获取的指令有:iget sget、iget-boolean、sget-boolean、iget-object 、sget-object等
  • 写入的指令有:iput、sput、iput-boolean、sput-boolean、iput-object、sput-object等。
  • 没有"-object"后缀的表示操作的成员变量对象是基本数据类型,带"-object"表示操作的成员变量是对象类型,特别地,boolean类型则使用"-boolean"的指令操作

Smail成员变量指令简析

  • sget-object v0,Lcom/aaa;->ID:Ljava/lang/String

    sget-object用来获取变量赋值并保存到紧接着的参数的寄存器中,本例中,它获取ID这个String类型的成员变量并发到v0这个寄存器中。

    注意:前面需要该变量所属的类的类型,后面需要加一个冒号和该成员变量的类型,中间"->"表示所属关系。
  • iget-object v0,p0,Lcom/aaa;->view:Lcom/aaa/view;

    可以看到iget-object指令比sget-object多了一个参数,就是该变量所在类的实例,在这里就是p0即"this"。

Smali代码函数的调用

1.invoke-static:用于调用static函数

  • const-string v0,"NDKLIB"
  • invoke-static{v0},Ljava/lang/System;->loadLibrary(Ljava/kang/String;)V

    调用static void System.loadLibrary(String)来加载NDK编译的so库用的方法;这里v0就是参数"NDKLIB"

    2.invoke-super:一般用于onCreate、onDestory等方法。调用父类方法用的指令。

    3.invoke-direct:调用private函数

    invoke-direct{p0},Landroid/app/TabActivity;->()V

    这里init()就是定义在TabActivity中的一个private函数

    4.invoke-virtual:用于调用protected或public函数。

    sget-object v0,Lcom/dddd;->bbb:Lcom/ccc

    invoke-virtual{v0,v1},Lcom/ccc;->Message(Ljava/lang/Object;)V

    V0是bbb:Lcom/ccc

    v1是爨地给Messages方法的Ljava/lang/Object参数。

    5.invoke-xxxx/range:当方法的参数多于5个时(含5个),不能直接使用以上的指令,而是在后面加上"range",range表示范围,使用方法也有所不同:

    invoke-direct/range{v0......v5},Lcmb/pb/ui/PBContainerActivity;->h(ILjava/lang/CharSequence;Ljava/lang/String;Landroid/content/Intent;l)Z 需要传递v0到v5一共6个参数,这时候大括号的参数采用省略形式,且需要连续。

Smali返回结果的操作

  • 在java代码中调用函数和返回函数结果可以用一条语句完成,而在Smail里则需要分开来完成,在使用上述指令后,如果调用的函数返回非void,那么还需要用到move-result(返回基本数据类型)和move-result-object(返回对象)指令:

    const-string v0,"Eric"

    invoke-static{v0},Lcmb/pbi;->t(Ljava/lang/String;)Ljava/lang/String;

    move-result-object v2

    v2保存的就是调用t方法的String字符串。

Smali语言的更多相关文章

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

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

  2. smali 语言语法

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

  3. Smali语言基础语法

    1.Smali语言基础语法-数据类型与描述符 smali中有两类数据类型:基本类型和引用类型.引用类型是指数组和对象,其它都是基础类型. 基本类型以及每种类型的描述符: Java类型 类型描述符 说明 ...

  4. 安卓动态调试七种武器之长生剑 - Smali Instrumentation

    安卓动态调试七种武器之长生剑 - Smali Instrumentation 作者:蒸米@阿里聚安全 0x00 序 随着移动安全越来越火,各种调试工具也都层出不穷,但因为环境和需求的不同,并没有工具是 ...

  5. Smali语法

    看阿里巴巴的<深入探索Android热修复>,里面的代码看不懂,一查才知道是Smali语法,百度了语法,转载如下 转载自smali 语言语法 1.smali apk文件通过apktool反 ...

  6. 【Smali】Smali文件的动态调试

    1.简介 smalidea是一个IntelliJ IDEA/Android Studio smali语言插件,可实现动态调试smali代码.下载地址为:https://github.com/Jesus ...

  7. Smali语法简单介绍

    Smali语言其实就是Davlik的寄存器语言: Smali语言就是android的应用程序.apk通过apktool反编译出来的都有一个smali文件夹,里面都是以.smali结尾的文件,文件的展示 ...

  8. Android逆向基础知识Smali

    什么是Smali: 我们用工具反编译一些APP的时候,会看到一个smali文件夹,里面其实就是每个Java类所对应的smali文件.Android虚拟机Dalvik并不是执行java虚拟机JVM编译后 ...

  9. smali语法积累记录

    1.constructor 我们知道运行一个类的时候会先调用static方法中的内容,比如: static { System.loadLibrary("qihooTest"); } ...

  10. Smali相关的基础知识点

    通过本篇博客的学习,相信你可以无压力的读懂Smali语言文件,并可以将Smali还原成java!!! 其实Smali语言并不是很难,如果你有一些汇编指令的基础,学习Smali就更加简单了,有兴趣的可以 ...

随机推荐

  1. PowerBI(一) : 如何将powerBI报表嵌入内部web应用程序?

    最近做了一个PowerBI报表嵌入内部web应用系统的项目,分享一下主要步骤以及踩坑记录. 微软官网完整教程这里:https://learn.microsoft.com/zh-cn/power-bi/ ...

  2. [Pytorch框架] 5.1 kaggle介绍

    文章目录 5.1 kaggle介绍 5.1.1 Kaggle 平台简介 比赛介绍 5.1.2 Kaggle板块介绍 Data Rules Team Kernels Discussion Leaderb ...

  3. [C++基础入门] 7、 指针

    文章目录 7 指针 7.1 指针的基本概念 7.2 指针变量的定义和使用 7.3 指针所占内存空间 7.4 空指针和野指针 7.5 const修饰指针 7.6 指针和数组 7.7 指针和函数 7.8 ...

  4. 新概念英语(New Concept English),前言

    本书向读者提供了一套完整的,经过实践检验的英语学习体系,使得学生能够发挥自己的最大潜能. 听力 口语 阅读 写作 学习语言不在于掌握一套规则和积累大量词汇. 而在于如何运用所学的知识. 学习单词,必须 ...

  5. #Powerquery 利用M函数合并文件(CSV、Text、Xlsx)

    在日常工作中,我们往往会遇到多个文件需要合并的情况,本文一起探讨一下利用M函数合并文件的案例. 由于需要合并的文件的格式不同,也需要选择不同的M函数来进行合并,本文将分享三个格式的合并案例. 首先介绍 ...

  6. 把ChatGPT调教成机器学习专家,以逻辑回归模型的学习为例

    大家好我是章北海mlpy 看到一个蛮有意思的项目,可以把ChatGPT调教成导师 https://github.com/JushBJJ/Mr.-Ranedeer-AI-Tutor 可以根据你选择的学习 ...

  7. 2023-04-26:给定一个数组componets,长度为A, componets[i] = j,代表i类型的任务需要耗时j 给定一个二维数组orders,长度为M, orders[i][0]代表i

    2023-04-26:给定一个数组componets,长度为A, componets[i] = j,代表i类型的任务需要耗时j 给定一个二维数组orders,长度为M, orders[i][0]代表i ...

  8. 2023-04-23:给定你一个整数数组 nums 我们要将 nums 数组中的每个元素移动到 A 集合 或者 B 集合中 使得 A 集合和 B 集合不为空,并且 average(A) == aver

    2023-04-23:给定你一个整数数组 nums 我们要将 nums 数组中的每个元素移动到 A 集合 或者 B 集合中 使得 A 集合和 B 集合不为空,并且 average(A) == aver ...

  9. 2022-03-15:给定一棵树的头节点head,原本是一棵正常的树, 现在,在树上多加了一条冗余的边, 请找到这条冗余的边并返回。

    2022-03-15:给定一棵树的头节点head,原本是一棵正常的树, 现在,在树上多加了一条冗余的边, 请找到这条冗余的边并返回. 答案2022-03-15: 1.指向头,入度没有0的.入度没有2的 ...

  10. Grafana系列-统一展示-8-ElasticSearch日志快速搜索仪表板

    系列文章 Grafana 系列文章 概述 我们是基于这篇文章: Grafana 系列文章(十二):如何使用 Loki 创建一个用于搜索日志的 Grafana 仪表板, 创建一个类似的, 但是基于 El ...