s002android逆向安全初級篇之a(chǎn)ndroid smali語法總結(jié)

總結(jié)一下smali 的分析 。

smali代碼相當于dalvik虛擬機的匯編語言。

--

  1. 如何得到smali代碼參考百度,或我的文章s001android逆向安全初級篇之a(chǎn)pk逆向常用工具及簡單使用一覽 利用這些工具可以得到。
  2. smali 的dalvik 操作碼鏈接dalvik_opcodes

smali 中的數(shù)據(jù)類型

smali中有兩類數(shù)據(jù)類型:基本類型和引用類型。
引用類型是指數(shù)組和對象,其他都是基礎(chǔ)類型。

基礎(chǔ)類型

使用一個簡單的字符表示,在dex文件中實際上以字符串的形式存儲。

V  空類型---僅僅可以用來作為返回類型
Z  Boolean 布爾型
B  Byte字節(jié)型
S  Short短整型(16位)
C  Char字符型
I  Int 整形
J  long (64 bits)長整型(64位)
F  Float浮點型
D  double (64 bits)雙精度型(64位)

引用類型

對象 以Lpackagename/ObjectName;的形式表示

1. 開始的L表明這是一個對象類型
2. packagename  使用"/"代替"."
3. ObjectName是對象的名稱,
4. 分號表明對象名的結(jié)束.

數(shù)組 以[數(shù)據(jù)類型 的形式表示

如:
[I  表示一維整形數(shù)組
[[I 表示二維數(shù)組
[Ljava/lang/String    表示String數(shù)組

方法

Lpackage/name/ObjectName;->MethodName(III)Z

  1. Lpackage/name/ObjectName; 是一個類,
  2. MethodName明顯是一個方法名,
  3. (III)Z是方法的簽名,
  4. ‘III’在這個例子中是三個整形參數(shù),
  5. Z是表示返回一個布爾類型的返回值。

寄存器

在dalvik字節(jié)碼中,寄存器都是32位的,能夠支持任何類型。64位類型(Long和Double型)用2個寄存器表示。
有兩種方式指定一個方法中有多少寄存器是可用的。

.registers指令指定了方法中寄存器的總數(shù)。
.locals指令表明了方法中非參寄存器的數(shù)量。

方法的傳參

  1. 當一個方法被調(diào)用的時候,方法的參數(shù)被置于最后N個寄存器中。如果一個方法有2個參數(shù),5個寄存器(v0-v4),那么參數(shù)將置于最后2個寄存器——v3和v4。
  2. 非靜態(tài)方法中的第一個參數(shù)總是調(diào)用該方法的對象。

例如,
非靜態(tài)方法LMyObject;->callMe(II)V有2個整型參數(shù),另外還有一個隱含的LMyObject;參數(shù),所以總共有3個參數(shù)。假如在該方法中指定了5個寄存器(v0-v4),以.registers方式指定5個或以.locals方式指定2個(即2個local寄存器+3個參數(shù)寄存器)。當該方法被調(diào)用的時候,調(diào)用該方法的對象(即this引用)存放在v2中,第一個整型參數(shù)存放在v3中,第二個整型參數(shù)存放在v4中。
對于靜態(tài)方法除了沒有隱含的this參數(shù)外其它都一樣。
寄存器的命名方式
有兩種方式——V命名方式和P命名方式。P命名方式中的第一個寄存器就是方法中的第一個參數(shù)寄存器。在下表中我們用這兩種命名方式來表示上一個例子中有5個寄存器和3個參數(shù)的方法。

v0    第一個local register
v1    第二個local register
v2    p0    第一個parameter register
v3    p1    第二個parameter register
v4    p2    第三個parameter register

你可以用任何一種方式來引用參數(shù)寄存器——他們沒有任何差別。
注意:baksmali默認對參數(shù)寄存器使用P命名方式。如果想使用V命名方式,可以使用-pl—no-parameter-registers選項。
使用P命名方式是為了防止以后如果要在方法中增加寄存器,需要對參數(shù)寄存器重新進行編號的缺點。
Long/Double值
Long和double類型是64位的,需要2個寄存器(切記切記)。
例如,對于非靜態(tài)方法LMyObject;->MyMethod(IJZ)V,參數(shù)分別是LMyObject;,int,long,bool。故該方法需要5個寄存器來存儲參數(shù)。

p0    this
p1    I
p2,p3    J
p4    Z

方法的修飾詞

對于方法的修飾

.method static constructor <clinit>()V  表示不帶參數(shù)的缺醒構(gòu)造方法。
.registers 指令指定了方法中寄存器的總數(shù)  
.locals 指令表明了方法中非參寄存器的總數(shù),出現(xiàn)在方法中的第一行

如果沒有內(nèi)部類的話一個類在一個文件中;
如果有內(nèi)部類,則內(nèi)部類單獨一個文件文件名格式為:類名$內(nèi)部類

類的聲明

如下:聲明了一個類NetProviderApplication 繼承自Landroid/app/Application

.class public Lcom/android/netprovider/NetProviderApplication;
.super Landroid/app/Application;

集成接口Ljava/io/FilenameFilter 用如下表達

.implements Ljava/io/FilenameFilter;

未完持續(xù)。。。

其他

<clinit>
同樣對于類或者接口的靜態(tài)程序塊,在JVM層面也給了他一個特殊的名字<clinit>,無論是類或者接口在被加載到class loader的時候,Java虛擬機都會調(diào)用這個類或接口的<clinit>的方法,這個方法是個無參的,返回類型為void方法,這個方法名也是編譯器指定的,由于這個方法名并不是一個規(guī)范的方法名,所以我們無法在代碼中直接使用。

說了這么多,其實讀到這里只要記住兩點:在字節(jié)碼層面<init>表示構(gòu)造方法,<clinit>表示靜態(tài)程序塊。

參考鏈接

  1. dalvik_opcodes
  2. s001android逆向安全初級篇之a(chǎn)pk逆向常用工具及簡單使用一覽
  3. apk反匯編之smali語法
  4. Android apk的混淆
  5. Dalvik (software)

smali是一個開源并且注釋清晰的反編譯的java工程
apktool是基于smali開發(fā)的幫助反編譯apk的利器
dedexer是獨立與smali又一個反編譯apk的工具
而dexdump就是android自帶的c語言實現(xiàn)的dump dex文件的工具

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容