Android 台灣中文網
標題:
Smail語法(1)
[打印本頁]
作者:
fam1001
時間:
2016-3-28 13:24
標題:
Smail語法(1)
【情景分析】Android apk,反編譯之後,我們能閱讀到的代碼是 dalvik位元組碼 - smali 。有時候,工作需要,必須破解apk裡面的一些協議或者方法。以此,借鑒經驗,來開發自己的項目。
【語法】
一. 資料類型
原始類型:
V void,只能用於返回值類型
Z boolean
B byte
S short
C char
I int
J long(64位)
F float
D double(64位)
引用類型:
對像 和 數組
複製代碼
Smail表現形式
原始類型:用大寫字母代替即可,用法無異
引用類型:
對像:<strong> L + 包名.對像 +</strong> ;
對象的表示則以L作為開頭,格式是LpackageName/objectName;(注意必須有個分號跟在最後),例如String對像在smali中為:Ljava/lang/String;,其中java/lang對應java.lang包,String就是定義在該包中的一個對象。
數組:<strong>[ + 資料類型</strong>
數組的表示方式是:在基本類型前加上前中括號「[」,例如int數組和float數組分別表示為:[I、[F [I——表示一個整型一維數組,相當於java中的int[]。
對於多維數組,只要增加[就行了。[[I相當於int[][],[[[I相當於int[][][]。注意每一維的最多255個。
對像數組的表示:[Ljava/lang/String;表示一個String對像數組。
複製代碼
二. 方法
方法定義:
表示形式:Lpackage/name/ObjectName;->MethodName(III)Z
Lpackage/name/ObjectName;表示類型,MethodName是方法名。III為參數(在此是3個整型參數),Z是返回類型(bool型)。
方法的參數是一個接一個的,中間沒有隔開。
一個更複雜的例子:
method(I[[IILjava/lang/String;[Ljava/lang/Object;)Ljava/lang/String;
在java中則為:
String method(int, int[][], int, String, Object[])
複製代碼
內部類:
既然類是用LpackageName/objectName;來表示,那類裡面的內部類又如何在smali中引用呢?答案是:LpackageName/objectName$subObjectName;。也就是在內部類前加「$」符號
複製代碼
字段:
表示形式:
Lpackage/name/ObjectName;->FieldName:Ljava/lang/String; 即包名,字段名和各字段類型。
複製代碼
標記說明:
# static fields 定義靜態變量的標記
# instance fields 定義實例變量的標記
# direct methods 定義靜態方法的標記
# virtual methods 定義非靜態方法的標記
構造函數的返回類型為V,名字為<init>。
複製代碼
語法:If語句
if-eq p1, v0, :cond_8 表示如果p1和v0相等,則執行cond_8的流程:
:cond_8
invoke-direct {p0}, Lcom/paul/test/a;->d()V
調用com.paul.test.a的d()方法
if-ne p1, v0, :cond_b 表示不相等則執行cond_b的流程:
:cond_b
const/4 v0, 0x0
invoke-virtual {p0, v0}, Lcom/paul/test/a;->setPressed(Z)V
invoke-super {p0, p1, p2}, Landroid/view/View;->onKeyUp(ILandroid/view/KeyEvent;)Z
move-result v0
大概意思就是調用com.paul.test.a的setPressed方法,然後再調用父類View的onKeyUp方法,最後 return v0
複製代碼
三. 寄存器(重點)
概念:
在dalvik位元組碼中,寄存器都是32位的,能夠支援任何類型。64位類型(Long和Double型)用2個寄存器表示。
有兩種方式指定一個方法中有多少寄存器是可用的。
.registers指令指定了方法中寄存器的總數。 [注意:一個方法內,不允許超過15個;如果超過15個,需要做特殊處理,處理方法找google大神,度娘]
.locals指令表明了方法中非參寄存器的數量。
複製代碼
命名方式
有兩種方式——V命名方式和P命名方式。P命名方式中的第一個寄存器就是方法中的第一個參數寄存器。在下表中我們用這兩種命名方式來表示上一個例子中有5個寄存器和3個參數的方法。
v0 第一個local register
v1 第二個local register
v2 p0 第一個parameter register
v3 p1 第二個parameter register
v4 p2 第三個parameter register
你可以用任何一種方式來引用參數寄存器——他們沒有任何差別。
注意:baksmali預設對參數寄存器使用P命名方式。如果想使用V命名方式,可以使用-pl—no-parameter-registers選項。
使用P命名方式是為了防止以後如果要在方法中增加寄存器,需要對參數寄存器重新進行編號的缺點。
Long/Double值
Long和double類型是64位的,需要2個寄存器(切記切記)。
例如,對於非靜態方法LMyObject;->MyMethod(IJZ)V,參數分別是LMyObject;,int,long,bool。故該方法需要5個寄存器來存儲參數。
p0 this
p1 I
p2,p3 J
p4 Z
複製代碼
歡迎光臨 Android 台灣中文網 (https://apk.tw/)
Powered by Discuz! X3.1