請勿轉載,謝謝!!!?
另祝大家新年快樂,萬事大吉!
引
Dalvik 字節碼格式的官方說明:
字節碼格式:?https://source.android.google.cn/devices/tech/dalvik/dalvik-bytecode
說明格式:?https://source.android.google.cn/devices/tech/dalvik/instruction-formats
之前有介紹過指令字節碼如何反編譯的,參考文章最后部分:
每段指令字節碼的第一個字節就是指令碼,指令碼的范圍在[0x00 - 0xff],就是256個以內。
每個指令碼都對應一個格式解析說明,該說明詳細指出了該段字節指令碼占用了幾個字節,使用幾個寄存器,以及如何讀取的。
以這個指令格式說明為基礎,我設計了反匯編框架,代碼地址:
https://github.com/callmejacob/dexfactory/tree/master/disassemble
指令字節數組的最小單位解析
指令字節數組的最小單位,只有一個指令碼,后面跟著對應的指令數據。
以'4rcc'指令格式為例子,它的格式說明如下:
它占用了4 * 2 = 8個字節,這8個字節可以按照最左側的格式進行分解,得到AA, BB, CCCC, HHHH,繼而算出 NNNN = CCCC + AA - 1。
反編譯出來的代碼如下:
op> {vCCCC ... vNNNN}, meth@BBBB, proto@HHHH
其中op就是字節碼; CCCC, NNNN, BBBB,HHHH是解析或者計算好的數值。
而meth是一種kind類型,表示一種常量池的索引,而且每個指令碼對應的kind類型可能不一樣(后面有詳細說明)。
最后的proto是固定的,表示proto類型的常量池。
我們把這個反編譯出來的用格式化表示:?
總格式: ?'%s> {v%d ... v%d}, %s, %s' % (op_map[op], CCCC, NNNN, '%s', '%s')
最后兩個為什么用%s呢? 因為也把kind類型的和proto類型的做格式化處理,最后合并到上面的總格式中。
這兩個格式都用下述格式表示:
kind格式: ?'%s@%.4x'
它的第一個參數是kind類型,第二個就是kind類型的數值,比如
meth@0003
代表method常量池的第3個子項。
我們用代碼實現如下:
上面的desc就是我們說的總格式,而kind_x, proto_x都是用來形成kind格式的數值。
如果我們拼接好kind格式之后,使用下面的方法匯總到總格式:
打印方法:
上面的例子中,'4rcc'格式比較有代表性,它包含了[op, 變量,kind, proto]四個重要的信息。
下面我們介紹通用的解碼過程(decode)。
decode會根據指令碼和對應的說明格式進行一一解析,這需要建立一些指令碼類型的映射集合,詳細如下。
指令碼集合(片段):
常量池類型定義(kind):
指令碼對應的kind類型映射(片段):
指令碼到解釋格式的映射集合(片段):
利用op_map可以獲取到指令碼描述;
利用format_map可以獲取到指令碼說明格式,并根據該格式進行變量解析;
利用kind_map可以獲取到拼接kind格式的類型。
最后,根據上述信息,匯總到總格式字符串中。
這樣,一個最小單位的指令字節碼就解析完成了。
我們將上述方法都封裝到類InsnsItem中,它能夠解析一個最基本的指令字節碼,并且能夠打印出來相關的反匯編代碼。
代碼片段如下:
指令字節碼全段解析
指令字節數組可以分解為若干個最小單位的指令字節碼,形成一個item_list。
其中的InsnsItem中的kind格式信息,還是最原始的,比如meth@0003。
為了獲取它實際信息,我們定義一個kind到對應section信息的一個映射和獲取方法:
在上述映射的基礎上,我們可以把item信息轉換成真實的反匯編信息。
打印過程:
其中的context,就是包含section信息的上下文,通過它我們把kind和proto兩個格式字符串格式化,獲取到kind_desc和proto_desc(它們包含了真實信息),最終再填充到總格式化字符串中。
最后我們把這兩個過程封裝到類Insns中,它以指令字節數組為參數,可以反編譯出對應的指令代碼。
反匯編和Dex解析框架
我們把這個反匯編框架和之前的dex格式解析框架結合起來。
全解析框架參考:
先在Context類中,定義一個變量來代表反編譯類的class,并提供設置方法。
然后在code_item段中,對于解析出來的每段insns字節碼數組進行反匯編:
反匯編測試
其中"#反匯編"這段不是必要的,因為后面反匯編類掛接到context中后,也能夠直接反匯編解析,這里是為了測試。?
這段的打印結果如下: ?(格式是字節碼數組和反匯編解釋)
使用反匯編的類信息打印如下: