總結(jié)一下smali 的分析 。
smali代碼相當于dalvik虛擬機的匯編語言。
--
- 如何得到smali代碼參考百度,或我的文章s001android逆向安全初級篇之a(chǎn)pk逆向常用工具及簡單使用一覽 利用這些工具可以得到。
- 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
- Lpackage/name/ObjectName; 是一個類,
- MethodName明顯是一個方法名,
- (III)Z是方法的簽名,
- ‘III’在這個例子中是三個整形參數(shù),
- Z是表示返回一個布爾類型的返回值。
寄存器
在dalvik字節(jié)碼中,寄存器都是32位的,能夠支持任何類型。64位類型(Long和Double型)用2個寄存器表示。
有兩種方式指定一個方法中有多少寄存器是可用的。
.registers指令指定了方法中寄存器的總數(shù)。
.locals指令表明了方法中非參寄存器的數(shù)量。
方法的傳參
- 當一個方法被調(diào)用的時候,方法的參數(shù)被置于最后N個寄存器中。如果一個方法有2個參數(shù),5個寄存器(v0-v4),那么參數(shù)將置于最后2個寄存器——v3和v4。
- 非靜態(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)程序塊。
參考鏈接
- dalvik_opcodes
- s001android逆向安全初級篇之a(chǎn)pk逆向常用工具及簡單使用一覽
- apk反匯編之smali語法
- Android apk的混淆
- Dalvik (software)
smali是一個開源并且注釋清晰的反編譯的java工程
apktool是基于smali開發(fā)的幫助反編譯apk的利器
dedexer是獨立與smali又一個反編譯apk的工具
而dexdump就是android自帶的c語言實現(xiàn)的dump dex文件的工具