Smali语法小记

news2024/10/6 8:30:18

Smali语法小记

介绍

在执行 Android Java 层的代码时,其实就是 Dalvik(ART) 虚拟机(使用 C 或 C++ 代码实现)在解析 Dalvik 字节码,从而模拟程序的执行过程。

自然,Dalvik 字节码晦涩难懂,研究人员们给出了 Dalvik 字节码的一种助记方式:smali 语法。通过一些工具(如 apktool),我们可以把已有的 dex 文件转化为若干个 smali 文件(一般而言,一个 smali 文件对应着一个类),然后进行阅读。对于不同的工具来说,其转换后的 smali 代码一般都不一样,毕竟这个语法不是官方的标准。

下文说明

<> 中的内容必须存在,[] 的内容是可选的

结构

  • 声明语句
  • 执行语句

声明语句

声明语句一般都是以 . 开始

寄存器

Dalvik 最多支持 65536 个寄存器 (编号从 0~65535),但是 ARM 架构的 cpu 中只有 37 个寄存器。那 Dalvik 是怎么做的呢?其实,每个 Dalvik 虚拟机维护了一个调用栈,该调用栈用来支持虚拟寄存器和真实寄存器相互映射的。

寄存器命名规则

  • v命名
    • 局部变量 v0 ~ vm-1
    • 函数参数vm ~ vm+n
  • P命名
    • 局部变量 v0 ~ vm-1
    • 函数参数pm ~ pm+n

变量

javasmali
booleanZ
byteB
shortS
charC
intI
longL
floatF
doubleD
voidV
objectL
array[

对象类型

对象类型可以表示 Java 代码中的所有类
例如:

  • Lpackage/name/ObjectName;
  • Ljava/lang/String;

数组

比如说 int 数组 int [] 在 smali 中的表示形式为 [I 。
比如说数组类型 String[][] 在 smali 中的表示形式为 [[Ljava/lang/String;

字段声明

#instance fields
.field <访问权限修饰符> [非权限修饰符] <字段名>:<字段类型>

访问权限修饰符

  • public
  • private
  • protected

非权限修饰符

  • final
  • volidate
  • transient

综上举例:

  • private java.lang.String str1; == .field private str1:Ljava/lang/String;
  • public static java.lang.String str2; == .field public static str2:Ljava/lang/String;

方法

# 描述方法类型
.method <访问权限修饰符> [修饰符] <方法原型>
      <.locals>(.locals 会指定方法使用的局部变量。)
      [.parameter](参数就正常用 p0 开始)
      [.prologue](程序的开始处)
      [.line](第几行)
      <代码逻辑>
      [.line]
      <代码逻辑>
.end

方法类型

一般是反编译工具加上去的

  • 直接方法,direct method
  • 虚方法,virtual method

方法原型

方法原型一般为方法名(参数类型描述符)返回值类型描述符 。

.class <访问权限修饰符> [非权限修饰符] <类名>
.super <父类名>
.source <源文件名称>

例如:

.class public final Lcom/a/b/c;
.super Ljava/lang/Object;
.source "Demo.java"

类的引用

this$[层数]
例如

public class MainActivity extends Activity {   //this$0
   public class firstinner  //this$1
   {
      public class secondinner //this$2
      {
         public class thirdinner //this$3
         {

         }
      }
   }
}

接口

#interfaces
.implements <接口名称>

注解

#annotations
.annotation [注解的属性] <注解范围>
    [注解字段=]
    ...
.end

位描述元素

  • 一个 op,8 位指令码
  • 若干个字符,每一个字符表示 4 位
  • 若干个 | ,进行分割,方便阅读。
  • 若干个 ∅同样也是 4 个字符,表示该部分位为 0。
    例如:
    指令 B|A|op CCCC 包含 2 个 word,一共 32 位。其中,第一个字的低 8 位是操作码,中间 4 位是 A,高 4 位是 B。第二个字是单独的 16 位的数值

格式ID

指令格式,根据 ID 的不同,仍然可以表示不同的指令含义
在这里插入图片描述

  • 第一个数字表示 word 的数量
  • 第二个数字的话表示指令包含的寄存器的最大数量
  • 第二个如果是r 的话,表示使用了一定范围内的寄存器 (range)。
  • 第三个字符表示指令使用到的额外数据的类型
  • 第四个s表示静态链接
  • 第四个i表示内联

指令句语法

  • 指令以操作码 op 开始
  • op后面跟参数
  • 参数间以逗号分隔。
  • 参数Vx表示寄存器,如 v0、v1 等。
  • 参数 #+X 表示常量数字。
  • 参数 +X 表示相对指令的地址偏移。
  • 参数 kind@X 表示常量池索引值,其中 kind 表示常量池类型,可以是string type field meth

例如:
指令 op vAA, type@BBBB 为例,指令使用了 1 个寄存器 vAA,一个 32 位的类型常量池索引。

指令后缀

  • 32 位运算不标记。
  • 64 位运算以 -wide 为后缀。
  • 特定类型的运算码以其类型(或简单缩写)为后缀,这些类型包括-boolean、-byte、-char、-short、-int、-long、-float、-double、-object、-string、-class 和 -void。

空指令

nop 无任何操作

数据定义指令

主要就是const
举例

byte b = 1; ==const/4 v0, 0x1
short s = 2;==const/4 v8, 0x2
String str = "test"; ==const-string v9, "test"
Class c = Object.class; const-class v1, Ljava/lang/Object;

数据移动指令

主要就是move

  • move、move-result 用于处理小于等于 32 位的基本类型。
  • move-wide、move-result-wide用于处理 64 位类型
  • move-object系列指令和move-result-object用于处理对象
  • 后缀(/from16、/16)只影响字节码的位数和寄存器的范围

数据转换指令

明显的两种类型的单词组合
举个例子int-to-short v0,v1 即将寄存器 v1 的值强制转换为 short 类型,并放入 v0 中。

运算指令

运算类型如下

类型说明
add-typevBB + vCC
sub-typevBB - vCC
mul-typevBB * vCC
div-typevBB / vCC
rem-typevBB % vCC
and-typevBB & vCC
or-typevBB | vCC
xor-typevBB ^ vCC
shl-typevBB << vCC
shr-typevBB >> vCC
ushr-typevBB >>> vCC无符号
  • type 可以是 - int,-long, -float,-double。
    举例:
int a = 5, b = 2;
a += b;
a -= b;
a *= b;
a /= b;
a %= b;
a &= b;
a |= b;
a ^= b;
a <<= b;
a >>= b;
a >>>= b;

smali

const/4 v0, 0x5
const/4 v1, 0x2
add-int/2addr v0, v1
sub-int/2addr v0, v1
mul-int/2addr v0, v1
div-int/2addr v0, v1
rem-int/2addr v0, v1
and-int/2addr v0, v1
or-int/2addr v0, v1
xor-int/2addr v0, v1
shl-int/2addr v0, v1
shr-int/2addr v0, v1
ushr-int/2addr v0, v1

数组操作

指令说明
array-length vA, vB获取给定 vB 寄存器中数组的长度并赋给 vA 寄存器
new-array vA, vB, type@CCCC新建数组
new-array/jumbo vAAAA, vBBBB,type@CCCCCCCC新建数组范围更大
filled-new-array {vC, vD, vE, vF, vG},type@BBBB新建数组指定内容
filled-new-array/range {vCCCC …vNNNN}, type@BBBB新建数组指定范围
fill-array-data vAA, +BBBBBBBB填充数组

例如:

int[] arr = new int[10];
int[] arr = {1, 2, 3, 4, 5};

==

const/4 v1, 0xa
new-array v0, v1, I
const/4 v1, 0x1
const/4 v2, 0x2
const/4 v3, 0x3
const/4 v4, 0x4
const/4 v5, 0x5
filled-new-array {v1, v2, v3, v4, v5}, I
move-result v0
寄存器若连续,则可改为
filled-new-array {v1...v5}, I

实例操作

指令说明
check-cast vAA, type@BBBB、check-cast/jumbo vAAAA, type@BBBBBBBB转成B
instance-of vA, vB, type@CCCC、instance-of/jumbo vAAAA, vBBBB, type@CCCCCCCCif能转成B,vA=1 else vA=0
new-instance vAA, type@BBBB、new-instance/jumbo vAAAA, type@BBBBBBBB构造新实例

例如:

Object obj = new Object();

String s = "test";
boolean b = s instanceof String;

String s = "test";
Object o = (Object)s;

==

new-instance v0, Ljava/lang/Object;
invoke-direct-empty {v0}, Ljava/lang/Object;-><init>()V

const-string v0, "test"
instance-of v1, v0, Ljava/lang/String;

const-string v0, "test"
check-cast v0, Ljava/lang/Object;
move-object v1, v0

字段操作指令

字段操作指令主要是对实例的字段进行读写操作

  • 读=get
  • 写=put
  • 普通字段+i
  • 静态字段+s

例如:iget,iget-wide,iget-object,iget-boolean,iget-byte,iget-char,iget-short

例如:

int[] arr = new int[2];
int b = arr[0];
arr[1] = b;

==

const/4 v0, 0x2
new-array v1, v0, I
const/4 v0, 0x0
aget-int v2, v1, v0
const/4 v0, 0x1
aput-int v2, v1, v0

比较指令

cmp(l/g)-kind(kind可以选float、long、double) vAA(结果放这里), vBB, vCC
如果 vBB 寄存器大于 vCC 寄存器,结果为 - 1,相等则结果为 0,小于的话结果为 1

跳转指令

  • goto,无条件跳转
  • switch,分支跳转
    • packed-switch vAA,+BBBBBBBB 规律递增跳转
    • sparse-switch vAA,+BBBBBBBB 无规律递增跳转
  • if,条件跳转
    • if-eq vA,vB,target 如果 vA=vB,跳转。
    • if-ne vA,vB,target 如果 vA!=vB,跳转。
    • if-lt vA,vB,target 如果 vA<vB,跳转。
    • if-gt vA,vB,target 如果 vA>vB,跳转。
    • if-ge vA,vB,target 如果 vA>=vB,跳转。
    • if-le vA,vB,target 如果 vA<=vB,跳转。
    • if-eqz vAA,target 如果 vA=0,跳转(加z则是和0比较)

例如

int a = 10
if(a > 0)
    a = 1;
else
    a = 0;

==

const/4 v0, 0xa
if-lez v0, :cond_0 # if 块开始
const/4 v0, 0x1
goto :cond_1       # if 块结束
:cond_0            # else 块开始
const/4 v0, 0x0
:cond_1            # else 块结束

锁指令

  • monitor-enter vAA 为指定的对象获取锁
  • monitor-exit vAA 释放指定的对象的锁

方法调用指令

  • invoke-kind {vC, vD, vE, vF, vG},meth@BBBB
  • invoke-kind/range {vCCCC … vNNNN},meth@BBBB 两类

kind类型:

  • invoke-direct 直接调用
  • invoke-super 调父类
  • invoke-virtual 虚方法(对于protected或者public方法都叫做虚方法。)
  • invoke-static 静态
  • invoke-interface 接口

异常指令

try-catch

int a = 10;
try {
    callSomeMethod();
} catch (Exception e) {
    a = 0;
}
callAnotherMethod();

==

const/16 v0, 0xa

:try_start_0            # try 块开始
invoke-direct {p0}, Lnet/flygon/myapplication/SubActivity;->callSomeMethod()V
:try_end_0              # try 块结束

.catch Ljava/lang/Exception; {:try_start_0 .. :try_end_0} :catch_0

:goto_0
invoke-direct {p0}, Lnet/flygon/myapplication/SubActivity;->callAnotherMethod()V
return-void

:catch_0                # catch 块开始
move-exception v1
const/4 v0, 0x0
goto :goto_0            # catch 块结束

返回指令

return-kind

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/183246.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

通过 eShopOnContainers 项目学习一下微服务

这里是项目地址 https://github.com/dotnet-architecture/eShopOnContainers, 这是微软创建的一个基于 .NET 平台的微服务架构的示例应用程序&#xff0c;里面基本上市面上主流的时髦的技术都用上了。 因为涉及的内容比较多&#xff0c;所以我们只简单查看一下微服务的代码实现…

信息抽取命名实体识别和关系抽取)

信息抽取的定义为&#xff1a;从自然语言文本中抽取指定类型的实体&#xff0c;关系、事件等事实信息。并形成结构化数据输出的文本处理技术。 信息抽取是从文本数据中抽取特定信息的一种技术&#xff0c;文本数据由医学具体的单位构成&#xff0c;例如&#xff0c;句子、段落、…

JavaWeb—Vue的简单介绍

1 Vue介绍 概述 Vue是一套构建用户界面的渐进式前端框架。只关注视图层&#xff0c;并且非常容易学习&#xff0c;还可以很方便的与其它库或已有项目整合。通过尽可能简单的API来实现响应数据的绑定和组合的视图组件。 数据渲染 数据库 --JDBC–> java程序 --http协议–>…

《MySQL实战45讲》——学习笔记23 “binlogredolog 的写入机制/组提交机制“

本篇主要介绍数据的可靠性有关的知识&#xff0c;包括binlog的写入机制和redolog的写入机制&#xff0c;通过了解这些机制从而可以在MySQL的IO性能瓶颈上做些优化&#xff1b;前文介绍了MySQL在可靠性、性能相关的概念&#xff0c;包括WAL技术、redolog与binlog、2阶段提交、ch…

阿里云图标使用 (symbol 引用方式)

阿里云图标网址: https://www.iconfont.cn/ 一、登录注册 这个简单&#xff0c;就不说了 二、给当前项目找图库 2.1、添加项目 2.2、寻找图标添加入库 添加入库 2.3、打开入库 的图标添加到指定项目 添加到当前项目 1 2 三、项目使用图标 ( symbol 引用方式) 3.1、下…

《HelloGitHub》第 82 期

兴趣是最好的老师&#xff0c;HelloGitHub 让你对编程感兴趣&#xff01;简介HelloGitHub 分享 GitHub 上有趣、入门级的开源项目。https://github.com/521xueweihan/HelloGitHub这里有实战项目、入门教程、黑科技、开源书籍、大厂开源项目等&#xff0c;涵盖多种编程语言 Pyth…

Studio One6有哪些新功能及系统配置要求介绍

Studio One6全新版本上线记录、生产、混合、掌握和执行所有操作。从工作室到舞台&#xff0c;Studio One6以易用为核心&#xff0c;是您的创意合作伙伴。当你准备好登上舞台时&#xff0c;Studio One就在那里。只有Studio One从最初的灵感到完整的制作&#xff0c;最终混音到精…

一个数码管显示0-F

数码管的一种是半导体发光器件&#xff0c;数码管可分为七段数码管和八段数码管&#xff0c;区别在于八段数码管比七段数码管多一个用于显示小数点的发光二极管单元DP&#xff08;decimal point&#xff09;&#xff0c;其基本单元是发光二极管。七段数码管是一类价格便宜使用简…

VuePress 搭建结合GitHub Pages CI

简介 VuePress 是尤雨溪&#xff08;vue.js 框架作者&#xff09;4月12日发布的一个全新的基于 vue 的静态网站生成器&#xff0c;实际上就是一个 vue 的 spa 应用&#xff0c;内置 webpack&#xff0c;可以用来写文档。详见 VuePress中文网 其实类似的建站工具有很多&#x…

Java多线程 - 创建线程池的方法 - ThreadPoolExecutor和Executors

文章目录线程池(重点)线程池介绍实现线程池的方式方式一: 实现类ThreadPoolExecutorThreadPoolExecutor构造器的参数线程池处理Runnable任务线程池处理Callable任务方式二: Executors工具类创建线程池线程池(重点) 线程池介绍 什么是线程池? 线程池就是一个可以复用线程的技…

以太网报文详解

以太网数据帧格式 以太网链路传输的数据包称做以太帧&#xff0c;或者以太网数据帧。在以太网中&#xff0c;网络访问层的软件必须把数据转换成能够通过网络适配器硬件进行传输的格式。 以太帧的工作机制 当以太网软件从网络层接收到数据报之后&#xff0c;需要完成如下操作&am…

模拟实现stack queue/dequeue/适配器/优先级队列/仿函数

⭐前言&#xff1a;学习C的STL&#xff0c;我们不仅仅要要求自己能够熟练地使用上层语法&#xff0c;我们还必须要求自己了解其底层原理&#xff0c;不需要了解得太深入&#xff0c;但一定得知道我们写出的各种代码后面&#xff0c;究竟采用了哪种设计思想&#xff0c;为什么要…

口碑巨制《流浪地球2》,再燃中国科幻电影新高度!

2019年&#xff0c;中国本土科幻电影《流浪地球》以炸裂之势吸引一众目光。上映26天&#xff0c;票房突破45亿&#xff0c;强势开启中国科幻电影的元年。如今时隔4年&#xff0c;《流浪地球2》再度登陆春节档&#xff0c;票房口碑双丰收&#xff0c;上映四天票房破13亿、淘票票…

Android渗透测试12:IDA动态调试so

0x00 前言 上一篇分享了使用 Android studio 和 Jeb 对 Apk 文件直接进行动态调试&#xff0c;本文将分享使用 IDA pro 调试 so 。 调试的 apk 文件还是使用 CTF案例4 的文件&#xff0c;已经上传到知识星球&#xff0c;可自行下载 本文涉及技术&#xff1a; IDA pro 工具使…

论文解读 - 城市自动驾驶车辆运动规划与控制技术综述 (第4部分)

文章目录&#x1f697; IV. Mothon Planning&#xff08;运动规划&#xff09;&#x1f7e2; D. Graph Search Methods&#xff08;图搜索算法&#xff09;&#x1f7e5; 1) Lane Graph&#xff08;车道图&#xff09;&#x1f7e7; 2) Geometric Methods&#xff08;几何方法&…

AtCoder Beginner Contest 287 A-G 赛时思路+正解

一把给我加到1219了&#xff0c;青大小蒟蒻表示很开心。 A - Majority 题意 问你"For""For""For"字符串数量是否比"Against""Against""Against"数量多。 思路 mapmapmap暴力即可。 A题代码 B - Postal Card 题意…

电脑技巧:教你关闭Win11内存压缩,解决电脑卡顿的问题

很多朋友都注意到&#xff0c;Win11默认开启了内存压缩功能。内存压缩顾名思义&#xff0c;可以压缩内存中的数据&#xff0c;让内存占用更少&#xff0c;同时减少Swap频次&#xff0c;带来更高的I/O效率。 但与此同时&#xff0c;压缩数据需要耗费CPU资源&#xff0c;一些朋友…

Dr4g0n-b4ll靶机总结

Dr4g0n-b4ll靶机渗透测试总结 靶机下载地址: https://download.vulnhub.com/dr4g0nb4ll/Dr4g0n-b4ll.zip 打开靶机,使用nmap扫描靶机的ip和所有开放的端口 可以看到靶机开放了80端口和22端口 根据80端口打开网站 信息收集,目录爆破 在robots.txt下发现一串base64编码 eW91IG…

编写循环(RH294)

循环这东西你早就懂的不是么就像python里的for一样在ansible中 使用loop关键字来实现迭代简单循环简单循环中一般使用loop关键字来开始循环使用循环变量item来存储每个迭代过程中使用的值举个例子 栗子啊首先让我们拿出两个任务片段- name: Postfix is runningservice:name: po…

索引15连问

前言 大家好&#xff0c;我是田螺。 金三银四很快就要来啦&#xff0c;准备了索引的15连问&#xff0c;相信大家看完肯定会有帮助的。 公众号&#xff1a;捡田螺的小男孩 1. 索引是什么&#xff1f; 索引是一种能提高数据库查询效率的数据结构。它可以比作一本字典的目录&am…