溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

Smali——初識(shí)

發(fā)布時(shí)間:2020-08-01 11:29:43 來源:網(wǎng)絡(luò) 閱讀:686 作者:wauoen 欄目:開發(fā)技術(shù)

原文鏈接:https://github.com/JesusFreke/smali/wiki

一、概述

    smali和backsmali是dalvik虛擬機(jī)使用的dex文件的匯編器和反匯編器,它寬松的語(yǔ)法基于Jasmin/dedexer語(yǔ)法,并支持dex格式的所有功能。

二、寄存器

    dalvik字節(jié)碼中,寄存器是32位的,可以存放任意類型的值。64位數(shù)據(jù)類型可以使用連個(gè)寄存器來存放。

(1)指定一個(gè)方法中寄存器的數(shù)量

    有兩種方式可以指定一個(gè)方法中可用寄存器的數(shù)量。.register指令指定了方法中寄存器的總數(shù),另一種方式,.locals指令指定了方法中非參數(shù)寄存器的數(shù)量。寄存器的數(shù)量包括存放方法參數(shù)的寄存器。

(2)方法的參數(shù)是如何傳入一個(gè)方法

    當(dāng)一個(gè)方法被執(zhí)行,方法的參數(shù)將被存放到最后n個(gè)寄存器中。如果一個(gè)方法有兩個(gè)參數(shù),五個(gè)寄存器(v0-v4),則參數(shù)將被存放到最后兩個(gè)寄存器v3和v4中。

    非靜態(tài)方法的第一個(gè)參數(shù)總是執(zhí)行該方法的對(duì)象。例如,非靜態(tài)方法LMyObject;->callMe(II)V中有兩個(gè)×××參數(shù),但是它在兩個(gè)×××參數(shù)之前隱含一個(gè)LMyObject;參數(shù),所以該方法中總共有三個(gè)參數(shù)。

    我們可以指定這個(gè)方法中有五個(gè)寄存器,可以使用.registers 5指令或者.local 2指令(連個(gè)local寄存器和3個(gè)參數(shù)寄存器)。一旦這個(gè)方法被執(zhí)行,執(zhí)行該方法的對(duì)象將會(huì)被存放到v2中,第一個(gè)×××參數(shù)存放到v3中,第二個(gè)×××參數(shù)被存放到v4中。

    對(duì)于靜態(tài)方法也是一樣的,只是沒有隱含該參數(shù)。

(3)寄存器命名

    存在兩種寄存器命名方案,正常的v命名方案和針對(duì)參數(shù)的p命名方案。p命名方案中第一個(gè)寄存器是方法中第一個(gè)參數(shù)。上個(gè)例子中有三個(gè)參數(shù)和總共五個(gè)寄存器。下表分別是v命名方案和p命名方案:

LocalParam
v0
第一個(gè)local寄存器
v1
第二個(gè)local寄存器
v2p0第一參數(shù)寄存器
v3p1第二個(gè)參數(shù)寄存器
v4p2第三個(gè)參數(shù)寄存器

(4)引入?yún)?shù)寄存器的動(dòng)機(jī)

    p命名方案的引進(jìn)是很實(shí)用的事情,用來解決在編輯smali代碼時(shí)一個(gè)普通的問題。

    例如存在一個(gè)有一定數(shù)量參數(shù)的方法,你將在該方法中添加一些代碼并且你發(fā)現(xiàn)你需要一個(gè)額外的寄存器。此時(shí)你想:“沒什么大不了的,我只需要修改.register指令就可以了”。不幸的的是,它并沒有這么簡(jiǎn)單。注意,參數(shù)被存放在最后的寄存器中。如果你增加了寄存器的數(shù)量,也就是說你改變了參數(shù)get和put的位置。所以你不得不改變.register指令并且必須對(duì)每個(gè)參數(shù)寄存器進(jìn)行重新編碼。但是如果你使用p命名方案,你可以簡(jiǎn)單的改變寄存器的數(shù)量而不需要擔(dān)心重新編碼已經(jīng)存在的寄存器。

    注意:默認(rèn)情況下,baksmali使用p命名方法。如果你想強(qiáng)制baksmali使用v命名方案,你可以使用

-p/--no-parameter-register選項(xiàng)。

(5)Long、Double

    前面提到過,long和double是64位值,需要兩個(gè)寄存器。這一點(diǎn)是非常重要的。例如,你有個(gè)一非靜態(tài)方法:LMyObject;->MyMethod(IJZ)V.該方法的參數(shù)為:LMyObject;、int、long、bllo。所以該方法需要5個(gè)寄存器存放所有的參數(shù):

RegisterType
p0this
p1I
p2,p3J
p4Z

三、Types、Methods、Fields

(1)Types

    dalvik的字節(jié)碼有兩大類型:primitive types和reference types。Reference types是對(duì)象和數(shù)組,其他的都是primitive type。

    primitives用一個(gè)字母表示。這些縮略詞不是我提出來的,它們實(shí)際上以字符串形式存放在dex文件中。在dex-format.html文檔中有詳細(xì)的說明。

Vvoid-can only be used for return types
Zboolean
Bbyte
Sshort
Cchar
Iint
Jlong(64bits)
Ffloat
Ddouble(64bits)

    對(duì)象的形式:Lpackage/name/ObjectName;L表示它是一個(gè)對(duì)象類型,package/name/是對(duì)象的包,ObjectName是對(duì)象的名字,;表示對(duì)象名字的結(jié)尾。在java中等價(jià)于package.name.ObjectName。例如,Ljava/lang/String;等價(jià)于java.lang.String。數(shù)組的形式[I-表示為一維×××數(shù)組,例如:int[]。要表示多維數(shù)組只需要簡(jiǎn)單的增加‘[’的數(shù)量。[[I=int[][],[[[I=int[][][]等等。注意:數(shù)組的最大維度為255.也可以表示對(duì)象的數(shù)組,例如:[Ljava/lang/String;表示一個(gè)字符串?dāng)?shù)組。

(2)Methods

    methods總是被表示為一個(gè)非常冗長(zhǎng)的形式包括:包含方法的類型、方法的名稱、參數(shù)的類型和返回類型。虛擬機(jī)需要這些信息才能正確的定位方法,在字節(jié)碼中執(zhí)行靜態(tài)方法。

Methods形式例子:

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

在這個(gè)例子中:Lpackage/name/ObjectName;為類型,MethodsName是方法的名稱。(III)Z是方法的聲明。III表示有三個(gè)int類型的參數(shù),Z表示返回類型是boolean。

一個(gè)更加復(fù)雜的例子:

    method(I[[IILjava/lang/String;[Ljava/lang/Object;)Ljava/lang/String;

java中表示為:

    String method(int,int[][],int,String,Object[])

(3)Fields

    同樣的,fields總是表示為一個(gè)冗長(zhǎng)的形式包括:包含field的類型、field的名稱、field的類型。同樣的,這是為了讓虛擬機(jī)可以找到正確的field,同樣的適用于字節(jié)碼上的靜態(tài)分析。

Fieldsde 形式:

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

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI