android逆向之Dalvik指令集

前言

Dalvik指令語(yǔ)法詳解
該篇文章為本人的學(xué)習(xí)筆記,如有不對(duì)之處,請(qǐng)指教.

附參考鏈接:smali文件語(yǔ)法參考

類(lèi)型

字節(jié)碼類(lèi)型描述符

語(yǔ)法 含義
V void,只用于返回值類(lèi)型
Z boolean
B byte
S short
C char
I int
J long
F float
D double
L java類(lèi)類(lèi)型
[ 數(shù)組類(lèi)型

其中L類(lèi)型可以表示Java類(lèi)型中的任何類(lèi).
例如

      java.lang.String  
在smali語(yǔ)法中表示為:
      Ljava.lang.String;

注意后面有個(gè)分號(hào),L類(lèi)型最后的分號(hào)表示對(duì)象名結(jié)束.

[類(lèi)型可以表示所有基本類(lèi)型的數(shù)組. [后面緊跟基本數(shù)據(jù)類(lèi)型描述符. 如[I 相當(dāng)于Java中的int[],即一維數(shù)組. [[I相當(dāng)于Java中的int[][],即二維數(shù)組.
三維、四維等等數(shù)值以此類(lèi)推. 注意多維數(shù)組的維數(shù)最大為255個(gè).

L[ 可以同時(shí)使用用來(lái)表示對(duì)象數(shù)組. 如[Ljava.lang.String;就表示這是一個(gè)String類(lèi)型的數(shù)組.

方法及字段

方法的表現(xiàn)格式如下

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

其中 Lpackage/name/ObjectName;應(yīng)該理解為該方法所在的類(lèi),MethodName為具體方法名,(III)Z 這是方法具體的傳參和返回部分,其中括號(hào)內(nèi)的III為方法參數(shù)(在這里是表示三個(gè)int類(lèi)型的參數(shù)),Z表示方法多維返回值(在這里返回值為boolean類(lèi)型).

字段的格式和方法很像,只是方法的括號(hào)禀综、括號(hào)里面的參數(shù)及返回值,這些字段都是沒(méi)有的,后面取而代之的是字段自己的類(lèi)型.字段格式如下

Lpackage/name/ObjectName;->FieldName:Ljava/lang/String;

其中Lpackage/name/ObjectName;不用說(shuō)還是該字段所在的類(lèi),FieldName為字段名,Ljava/lang/String;為字段類(lèi)型.其中字段名與字段類(lèi)型之間用冒號(hào):隔開(kāi).

Dalvik指令

首先咱們來(lái)解析一條指令

move-wide/from16 vAA,vBBBB

move為基礎(chǔ)字節(jié)碼,即操作符 . wide為名稱(chēng)后綴,標(biāo)識(shí)操作的數(shù)組為64位. from16位字節(jié)碼的后綴,標(biāo)識(shí)源操作數(shù)是一個(gè)16位寄存器引用變量. vAA為目的寄存器,他始終在源寄存器的前面.
vBBBB為源寄存器. 若沒(méi)有wide后綴,默認(rèn)為32位.

move指令

move 指令的作用是將源寄存器的值賦值給目的寄存器,即

move vA,vB

move-wide作用同上,只是賦值的為64位.</br> move-object是為對(duì)象賦值.
move-result 指令的作用是將上一個(gè)invoke類(lèi)型指令的操作結(jié)果賦值給目的寄存器,即

move-result vAA

move-result-wide作用同上,只是賦值的為64位. </br> move-object同上,只是賦值為對(duì)象類(lèi)型.

返回指令

return-void表示函數(shù)從一個(gè)void方法返回.
return 表示函數(shù)返回一個(gè)32位非對(duì)象的值.
return-wide 表示函數(shù)返回一個(gè)64位非對(duì)象的值.
return-object 表示函數(shù)返回一個(gè)對(duì)象類(lèi)型.

數(shù)據(jù)定義

const常用來(lái)定義程序中用到是常量邻奠、字符串框全、類(lèi)等數(shù)據(jù).</br> const 佑女、const/4割笙、const/16給寄存器賦值基本數(shù)據(jù)類(lèi)型.即

const/4 v1, 0x2

當(dāng)const-string給寄存器賦字符串,即

const-string v0, "\u60a8\u7684\u8bd5"

</br>const-class給寄存器賦值一個(gè)類(lèi)引用.

鎖指令

鎖指令用于在多線(xiàn)程程序中對(duì)同一對(duì)象的操作.

monitor-enter v0

為指定的對(duì)象獲取鎖.

monitor-exit v0

釋放指定對(duì)象的鎖.

實(shí)例操作指令

  • 類(lèi)型轉(zhuǎn)換指令
check-cast v0,type@BBBB

v0寄存器轉(zhuǎn)換成指定的類(lèi)型.

  • 檢查指令
instance-of v0,v1,type@BBBB

檢測(cè)v1是否可以轉(zhuǎn)換成指定類(lèi)型,可以轉(zhuǎn)換v0賦值為1,否則賦值 0.

  • 創(chuàng)建指令
new-instance v0,type@BBBB

構(gòu)造一個(gè)指定類(lèi)型的實(shí)例,并把實(shí)例對(duì)象的引用賦值給v0.類(lèi)型符 type指定類(lèi)型不能為數(shù)組.

數(shù)組操作指令

  • 創(chuàng)建數(shù)組
new-array v0,v1,type@BBBB

構(gòu)造指定類(lèi)型的數(shù)組,v1表示數(shù)組的大小,并將數(shù)組賦值給v0.

filed-new-array {v1,v2,v3},type@BBBB

構(gòu)造數(shù)組的另一種方式,即相當(dāng)于Java中的
int[] arrays= {1,2,3,4};

  • 獲取數(shù)組長(zhǎng)度
array-length v0,v1

獲取v1寄存器中的數(shù)組長(zhǎng)度,并賦值給v0寄存器.

跳轉(zhuǎn)指令

  • goto指令
goto +AA

無(wú)條件跳轉(zhuǎn)到指定偏移量處,偏移量不能為0.

  • switch指令
packed-switch v0,+BBBB

分支跳轉(zhuǎn),v0寄存器為switch分支中的判斷值,+BBBB指向的是packed-switch-payload格式的偏移表,表中的值是有規(guī)律的.

sparse-switch v0,+BBBB

作用同上,唯一不同是偏移表中的值是無(wú)規(guī)律的.

  • if指令
    if指令格式如下
    if-eq(此處可替換) v0,v1,+BBBB
    比較兩個(gè)寄存器的值,符合條件進(jìn)行跳轉(zhuǎn).
操作符 作用 對(duì)應(yīng)java語(yǔ)句
if-eq 如果v0等于v1則跳轉(zhuǎn). if(v0==v1)
if-ne 如果v0不等于v1則跳轉(zhuǎn). if(v0!=v1)
if-lt 如果v0小于v1則跳轉(zhuǎn). if(v0<v1)
if-gt 如果v0大于v1則跳轉(zhuǎn). if(v0>v1)
if-le 如果v0小于等于v1則跳轉(zhuǎn). if(v0<=v1)
if-ge 如果v0大于等于v1則跳轉(zhuǎn). if(v0>=v1)
    if-eq(此處可替換) v0,+BBBB

用寄存器中的值和0進(jìn)行比較,符合跳轉(zhuǎn)跳轉(zhuǎn).

操作符 作用 對(duì)應(yīng)java語(yǔ)句
if-eqz 如果v0等于0則跳轉(zhuǎn). if(v0==0)
if-nez 如果v0不等于0則跳轉(zhuǎn). if(v0!=0)
if-ltz 如果v0小于0則跳轉(zhuǎn). if(v0<0)
if-gtz 如果v0大于0則跳轉(zhuǎn). if(v0>0)
if-lez 如果v0小于等于0則跳轉(zhuǎn). if(v0<=0)
if-gez 如果v0大于等于0則跳轉(zhuǎn). if(v0>=0)

比較指令

用于比較兩個(gè)寄存器的值(浮點(diǎn)型或長(zhǎng)整型),比較結(jié)果放到v0寄存器中.
格式

cmpl-float(此處可替換) v0,v1,v2
操作符 作用
cmpl-float 如果v1小于v2則結(jié)果為1,相等則結(jié)果為0,大于則結(jié)果為-1.
cmpg-float 如果v1大于v2則結(jié)果為1,相等則結(jié)果為0,小于則結(jié)果為-1.
cmpl-double 如果v1小于v2則結(jié)果為1,相等則結(jié)果為0,大于則結(jié)果為-1.
cmpg-double 如果v1大于v2則結(jié)果為1,相等則結(jié)果為0,小于則結(jié)果為-1.
cmp-long 如果v1大于v2則結(jié)果為1,相等則結(jié)果為0,小于則結(jié)果為-1.

字段操作指令

字段操作指令分兩大類(lèi):普通字段和靜態(tài)字段,普通字段指令的前綴為i,靜態(tài)字段指令的前綴為s.
字段的讀操作指令為get,寫(xiě)操作指令為put,因此普通字段的操作指令為iget,iput.靜態(tài)字段的操作指令為sget,sput.
指令格式如下

.line 16
iput-object p1, p0, Lcom/view/dialogapplication/PhoneInfo;->context:Landroid/content/Context;

上面是一段iput指令代碼,它所對(duì)應(yīng)的java代碼如下

  this.context = context;

沒(méi)錯(cuò),它就會(huì)一個(gè)簡(jiǎn)單的賦值context的代碼;
由此,可以看出來(lái), p1是要賦值的context,p0是源,而后面的第三個(gè)參數(shù)

Lcom/view/dialogapplication/PhoneInfo;->context:Landroid/content/Context;

可以看出來(lái)是p1的字段名.

此外還有一組以a為前綴的的操作指令,分別為aputaget,不過(guò)它們應(yīng)該不算在字段的范疇了,應(yīng)該為數(shù)組操作范疇,但因?yàn)橐彩呛妥x寫(xiě)操作有關(guān),所以就寫(xiě)在這里了,具體格式如下

aput-object  v2,v1,v0

其具體作用為將v2的值放入到v1數(shù)組的v0位置處.所以可以看出,v2為要放入的值,v1代表著存放v2值的數(shù)組,而v0則是v2要存放在數(shù)組的位置,即v0為index(數(shù)組角標(biāo)).

方法調(diào)用指令

方法調(diào)用指令賦值調(diào)用類(lèi)實(shí)例(也就是對(duì)象)的方法,它的基礎(chǔ)指令為invoke.指令格式如下

invoke-virtual(名稱(chēng)后綴可替換) {v0,v1},method@BBBB(具體的方法)

其中{v0,v1}大括號(hào)中第一位放的是調(diào)用方法的對(duì)象,之后的為方法中的參數(shù).若沒(méi)有參數(shù)則只需傳入調(diào)用方法的對(duì)象,即{v0}.

指令 作用
invoke-virtualinvoke-virtual/range 調(diào)用實(shí)例的虛方法.
invoke-superinvoke-super/range 調(diào)用實(shí)例父類(lèi)的方法.
invoke-directinvoke-direct/range 調(diào)用實(shí)例的直接方法.
invoke-staticinvoke-static/range 調(diào)用實(shí)例的靜態(tài)方法.
invoke-interfaceinvoke-interface/range 調(diào)用實(shí)例的接口方法.

數(shù)字轉(zhuǎn)換指令

數(shù)據(jù)轉(zhuǎn)換指令用于將一種類(lèi)型的數(shù)值轉(zhuǎn)換成另一種類(lèi)型.格式如下

neg-int(可替換如下) v0,v1

指令中,v1存放需要轉(zhuǎn)換的數(shù)據(jù),v0存放轉(zhuǎn)換后的結(jié)果.

指令 作用
neg-int 對(duì)整型輸求補(bǔ).
not-int 對(duì)整型輸求反.
neg-long 對(duì)長(zhǎng)整型數(shù)求補(bǔ).
not-long 對(duì)長(zhǎng)整型數(shù)求反.
neg-float 對(duì)單精度浮點(diǎn)型數(shù)求補(bǔ).
neg-double 對(duì)雙精度浮點(diǎn)數(shù)求補(bǔ).
int-to-long 將整型數(shù)轉(zhuǎn)換為長(zhǎng)整型.
int-to-float 將整型數(shù)轉(zhuǎn)換為單精度浮點(diǎn)型.
int-to-double 將整型數(shù)轉(zhuǎn)換為雙精度浮點(diǎn)型.
long-to-int 將長(zhǎng)整型數(shù)轉(zhuǎn)換位整型.
long-to-float 將長(zhǎng)整型數(shù)轉(zhuǎn)換為單精度浮點(diǎn)型.
long-to-double 將長(zhǎng)整型數(shù)轉(zhuǎn)換為雙精度浮點(diǎn)型.
float-to-int 將單精度浮點(diǎn)轉(zhuǎn)換為整型.
float-to-long 將單精度浮點(diǎn)型轉(zhuǎn)換為長(zhǎng)整型.
float-to-double 將單精度浮點(diǎn)型轉(zhuǎn)換為雙精度浮點(diǎn)型.
double-to-int 將雙精度浮點(diǎn)型轉(zhuǎn)換為整型.
double-to-long 將雙精度浮點(diǎn)型轉(zhuǎn)換為長(zhǎng)整型.
double-to-float 將雙精度浮點(diǎn)型轉(zhuǎn)換為單精度浮點(diǎn)型.
int-to-byte 將整型轉(zhuǎn)換為字節(jié)型.
int-to-char 將整型轉(zhuǎn)換為字符串.
int-to-short 將整型轉(zhuǎn)換為短整型.

數(shù)據(jù)運(yùn)算指令

數(shù)據(jù)運(yùn)算指令分為算術(shù)運(yùn)算指令和邏輯運(yùn)算指令,即 加昼捍、減、乘迁筛、除煤蚌、取模、位移及與细卧、或尉桩、非、異或等.
格式如下

add-int(可替換如下) v0,v1,v2

指令中,將v1v2進(jìn)行運(yùn)算,結(jié)果存到v0.

指令 作用
add-type v1v2進(jìn)行加法運(yùn)算,即v1+v2.
sub-type v1v2進(jìn)行減法運(yùn)算,即v1-v2.
mul-type v1v2進(jìn)行乘法運(yùn)算,即v1*v2.
div-type v1v2進(jìn)行除法運(yùn)算,即v1/v2.
rem-type v1v2進(jìn)行取模運(yùn)算,即v1%v2.
and-type v1v2進(jìn)行與運(yùn)算,即v1 AND v2.
or-type v1v2進(jìn)行或運(yùn)算,即v1 OR v2.
xor-type v1v2進(jìn)行異或運(yùn)算,即v1 XOR v2.
shl-type v1進(jìn)行(有符號(hào)位)左移v2位,即v1<<v2.
shr-type v1進(jìn)行(有符號(hào)位)右移v2位,即v1>>v2.
ushr-type v1進(jìn)行(無(wú)符號(hào)位)右移v2位,即v1>>v2.

其中后面的-type可以是-int贪庙、-long蜘犁、-float、-double.

至此,Dalvik指令集基本就都介紹完了
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末止邮,一起剝皮案震驚了整個(gè)濱河市这橙,隨后出現(xiàn)的幾起案子奏窑,更是在濱河造成了極大的恐慌,老刑警劉巖屈扎,帶你破解...
    沈念sama閱讀 219,270評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件埃唯,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡鹰晨,警方通過(guò)查閱死者的電腦和手機(jī)墨叛,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,489評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)模蜡,“玉大人漠趁,你說(shuō)我怎么就攤上這事∪碳玻” “怎么了闯传?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,630評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀(guān)的道長(zhǎng)卤妒。 經(jīng)常有香客問(wèn)我甥绿,道長(zhǎng),這世上最難降的妖魔是什么荚孵? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,906評(píng)論 1 295
  • 正文 為了忘掉前任妹窖,我火速辦了婚禮,結(jié)果婚禮上收叶,老公的妹妹穿的比我還像新娘骄呼。我一直安慰自己,他們只是感情好判没,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,928評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布蜓萄。 她就那樣靜靜地躺著,像睡著了一般澄峰。 火紅的嫁衣襯著肌膚如雪嫉沽。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,718評(píng)論 1 305
  • 那天俏竞,我揣著相機(jī)與錄音绸硕,去河邊找鬼。 笑死魂毁,一個(gè)胖子當(dāng)著我的面吹牛玻佩,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播席楚,決...
    沈念sama閱讀 40,442評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼咬崔,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起垮斯,我...
    開(kāi)封第一講書(shū)人閱讀 39,345評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤郎仆,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后兜蠕,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體扰肌,經(jīng)...
    沈念sama閱讀 45,802評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,984評(píng)論 3 337
  • 正文 我和宋清朗相戀三年牺氨,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了狡耻。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,117評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡猴凹,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出岭皂,到底是詐尸還是另有隱情郊霎,我是刑警寧澤,帶...
    沈念sama閱讀 35,810評(píng)論 5 346
  • 正文 年R本政府宣布爷绘,位于F島的核電站书劝,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏土至。R本人自食惡果不足惜购对,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,462評(píng)論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望陶因。 院中可真熱鬧骡苞,春花似錦、人聲如沸楷扬。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,011評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)烘苹。三九已至躲株,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間镣衡,已是汗流浹背霜定。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,139評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留廊鸥,地道東北人望浩。 一個(gè)月前我還...
    沈念sama閱讀 48,377評(píng)論 3 373
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像黍图,于是被迫代替她去往敵國(guó)和親曾雕。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,060評(píng)論 2 355

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