011 smali语法详解
文章目錄
- smali文件解讀
- 描述類信息
- 靜態字段
- 實例字段
- 直接方法
- 虛方法
- 接口
- Smali基礎語法
- 寄存器
- 數據類型
- 字段和方法的表示
- Smali指令集
- 空操作指令
- 數據操作指令
- 返回指令
- 數據定義指令
- 跳轉指令
- 方法調用指令
smali文件解讀
描述類信息
在打開Smali文件時,它的頭三行描述了當前類的一些信息:
.class public Lcom/test/helloworld16/MainActivity; .super Landroid/support/v7/app/AppCompatActivity; .source "MainActivity.java"- 第一行表示的含義是當前class的包名和類名
- 第二行表示的是父類的包名和類名
- 第三行表示的是源文件的名稱
靜態字段
Smali文件類的主體部分:一個類由字段和方法組成。.field字段聲明,字段分兩類:靜態字段和實例字段
語法格式如下
.field < 訪問權限> static [ 修飾關鍵字]< 字段名>:< 字段類型>實例字段
實例字段相比于靜態字段少了一個static的靜態聲明,其他均相同
直接方法
smali的方法聲明使用的.method指令,方法分為直接方法和虛方法兩種。
方法格式如下:
.method <訪問權限> [ 修飾關鍵字] < 方法原型>其他字段含義
- **.registers:**指令指定了方法中寄存器的總數,這個數量是參數和本地變量總和
- **.param :**表明了方法的參數,每個.param指令表示一個參數,方法使用了幾個參數就有幾個.parameter指令
- **.prologue:**指定了代碼的開始處,混淆過的代碼可能去掉了該指令
- **.line:**指明了該處代碼在源代碼中的行號,同樣,混淆后的代碼可能去掉了行號
- **.local:**使用這個指定表明方法中非參寄存器
虛方法
虛方法:是指從父類中繼承的方法或者實現的接口的方法,它的聲明跟直接方法相同,只是起始的初始為virtual methods ,格式如下
.method <訪問權限> [ 修飾關鍵字] < 方法原型>接口
如果一個類實現了一個接口,那么會在smali文件中用.implements指令指出
Smali基礎語法
寄存器
Dalvik中的寄存器都是32位大小,支持所有類型。對于小于或等于32位類型,使用一個寄存器就可以了,對64位(long和double)類型,需要使用兩個相鄰的寄存器來存儲。
寄存器的命名法有兩種:V命名法和P命名法:
v命名法:局部變量寄存器V0-Vn,參數寄存器是Vn-Vn+m。
p命名法:參數寄存器P0-Pn,變量寄存器V0-Vn。
- p0->this
- p1,p2參數
- v0,v1局部變量
數據類型
在smali代碼中數據類型以類型描述符來表示
基本數據類型標識方法如下:
引用數據類型標識方法如下:
- String–>Ljava/lang/String;
- int[]–>I[
- String[]–>Ljava/lang/String;[
例如:
.method protected onCreate(Landroid/os/Bundle;)V上面的smali代碼,翻譯成JAVA源碼則是下面的方式
protected void onCreate(Bundle bundle);字段和方法的表示
字段格式:類型(包名+類名)+字段名稱+字段類型
字段描述
在JAVA中假設有一個類:com.test.Person,類有一個屬性:int id,在smali中則用下面的方法表示:
Lcom/test/Person;->id:I語法為:類名->屬性名:屬性類型
方法描述
在JAVA中假設有一個類:com.test.Person,類有一個方法:void setId(int id);,在smali中則用下面的方法表示:
Lcom/test/Person;->setId(I)V語法為:完整類名->方法名(參數類型)返回類型
Smali指令集
Dalvik的指令格式:
基礎字節碼 - 名稱后綴/字節碼后綴 目的寄存器 源寄存器
名稱后綴是wide,表示數據寬度為64位。字節碼后綴是from16,表示源寄存器為16位。
Dalvik指令集中大多數指令用到了寄存器作為目的操作數或者是源操作數,其中A/B/C/D/E/F/G表示一個4位的數值,AA/BB/HH表示一個8位的數值,AAAA/BBBB表示16位的數值
空操作指令
空操作指令的助記符為nop,它的值為00,通常nop指令被用來做對齊代碼之用,無實際操作含義
數據操作指令
數據操作指令為move。move指令根據字節碼大小和類型不同,后面會跟上不同的后綴,表達的意義也不同
- **“move vA, vB”:**將vB寄存器的值賦給vA寄存器,源寄存器與目的寄存器都為4位
- **“move/from16 vAA, vBBBB”:**將vBBBB寄存器的值賦給vAA寄存器,寄存器為16位,目的寄存器為8位
- **“move/16 vAAAA, vBBBB”:**將vBBBB寄存器的值賦給vAAAA寄存器,源寄存器與目的寄存器都為16位。
- **“move-wide vA, vB”:**為4位的寄存器對賦值。源寄存器與目的寄存器都為4位。
- **“move-object vA, vB”:**object是對象的意思,出現這個詞即表示為對象賦值。源寄存器與目的寄存器都為4位
- **“move-result vAA”:**將上一個invoke類型指令操作的單字非對象結果賦給vAA寄存器
- **“move-exception vAA”:**保存運行時發生的異常到vAA寄存器。這條指令必須是異常發生時的異常處理器的一條指令,否則指令無效。
總結起來move指令有三種作用:
返回指令
返回指令即return指令,指的是函數結尾時運行的最后一條指令。共有以下四條返回指令 :
- **“return-void”:**表示函數從一個void方法返回,返回值為空
- **“return vAA”:**表示函數返回一個32位非對象類型的值,返回值寄存器為8位的寄存器vAA。
- **“return-wide vAA”:**表示函數返回一個64位非對象類型的值,返回值為8位的寄存器對vAA
- **“return-object vAA”:**表示函數返回一個對象類型的值,返回值為8位的寄存器vAA
數據定義指令
數據定義指令用來定義程序中用到的常量,字符串,類等數據。它的基礎字節碼為const
- **“const/4 vA, #+B”:**將數值符號擴展為32位后賦給寄存器vA。
- **“const/16 vAA, #+BBBB”:**將數據符號擴展為32位后賦給寄存器vAA
- **“const-wide/16 vAA, #+BBBB”:**將數值符號擴展為64位后賦給寄存器對vAA
- **“const-string vAA, string@BBBB”:**通過字符串索引構造一個字符串并賦給寄存器vAA
- **“const-class vAA, type@BBBB”:**通過類型索引獲取一個類引用并賦給寄存器vAA
跳轉指令
if條件跳轉有如下幾種
跟x86的JCC跳轉有異曲同工之妙
方法調用指令
方法調用指令負責調用類實例的方法,它的基礎指令為invoke
- invoke-virtual或invoke-virtual/range :調用實例的虛方法
- invoke-super或invoke-super/range :調用實例的父類/基類方法
- invoke-direct或invoke-direct/range :調用實例的直接方法
- invoke-static或invoke-static/range :調用實例的靜態方法
- invoke-interface或invoke-interface/range :調用實例的接口方法
總結
以上是生活随笔為你收集整理的011 smali语法详解的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 010 Android之逆向入门
- 下一篇: 《全民捕鱼》游戏分析