其實是給 JVM 看的 Byte code ,其實 Android 所編譯出來的 class 檔會再
經過編譯轉換成給 Dalvik VM 看的 byte code,也就是我們會在 apk 檔案中
看到的 classes.dex 檔案。
classes.dex 檔案裏面包含了所有的 class , 我們可以透過幾個工具來進行
Decompile 的動作:
1. Dedexer - dex => ddx (內容為 Dalvik Byte code)
2. smali - dex => smali (內容為 Dalvik Byte code)
3. Dex2jar - 將 dex 轉為 jar , 也就是轉為 .class 並封裝起來
4. JD-GUI - 非常好用的 Java Decompile 工具,是將 .class 轉為 .java
5. Java Bytecode Editor - 就如字面上的意思,對象是 .class 檔
基本上 Dedexer 和 smali 轉換出來的內容是一樣的,但是 smali 另外
有提供再將 .smali 編譯回 .dex 的功能,而且輸出較為強大,所以建
議使用 smali。
Dex2Jar 則是直接將 dex 轉回 .class , 並以封裝好的 jar 呈現
可以搭配 JD-GUI 觀察 java source code。
但是使用這個工具轉換出來的 java code 還要再編譯回去我沒試過
編譯回去的檔案檔案大小有差異,無法保證可以運作。
如果要看懂成是在寫什麼,採用 Dex2Jar + JD-GUI 是很好的選擇
JD-GUI 是將 class (也就是 java bytecode)變成我們看得懂的 .java code
但是經過 dex2jar 轉換,無法保證內容會為完整無誤,而且 JD-GUI 在
某些情況也會有轉不出來或者是「內容詭異 」的情況出現。
而如果要能夠修改後再編回 dex , 就採用 smali 了,使用方式也很簡單,
在 Project Site 可以抓到 baksmali.jar和 smali.jar,前者是 dex=>smali
後者是 smali => dex
使用:( .jar 檔案可能會包含版本號,自己注意一下)
java -jar baksmali.jar -o output_folder the_dex_file
(PS : 加入 -b 可以關閉除錯輸出,但建議是開著比較好找)要編譯回來就使用 smali.jar :
java -jar smali.jar -o output_dex_name the_source_folder
值得一提的是, Java Bytecode 和 Dalvik Bytecode 是不一樣的
Java 是 Stack based , Dalvik 是 register based , 參考底下,大概
就可以理解了:(// 後面的註解是我加上去的,編譯的時候不能保留阿XD)
Java Code
--
public class TestClass { public int testMethod(int a,int b){ int c=a+b; return c+1; } }--
Java Byte Code
--
.method public testMethod(II)I iload_1 //讀出第一個參數 , 型態為 i => int iload_2 //讀出第二個參數 iadd // 加起來(上面兩個) , i => int istore_3 // 存到 var3 (上面加起來的結果),型態是 i => int iload_3 //讀出 var 3 iconst_1 //讀取常數 "1" , 型態 i => int iadd //加起來 (上面兩個) i => int ireturn // 傳回整數 (上面的結果) , i => int .end method // 這就是所謂的 stack based--
Dalvik Byte Code
--
.method public testMethod(II)I .limit registers 5 // 五個變數要註冊 ; this: v2 (Ltw/darkk6/test/TestClass;) // this 註冊為 v2 ; parameter[0] : v3 (I) //參數 1 註冊為 v3 , 型態 I => int ; parameter[1] : v4 (I) //參數 2 註冊為 v4 , 型態 I => int add-int v0,v3,v4 //整數相加, v0 = v3+v4 add-int/lit8 v1,v0,1 //整數相加 : v0 加上 lit8 (lit8 就是這邊的 1) , 存到 v1 return v1 // 傳回 v1 .end method---
(前面分號開頭的應該只是註解,寫出來提醒使用者這幾個變數的註冊情況)
[注意:]
使用 smali 和 dedexer 反編譯出來的 bytecode 有部分不會相同上面的是由
Dedexer 所反編譯,利用 smali 在方法參數和註冊的部分會有點差異:
Delvik Byte Code by Smali
--
.method public testMethod(II)I .registers 5 //註冊五個變數 add-int v0, p1, p2 //p1 和 p2 是參數1 和 參數2 add-int/lit8 v1, v0, 0x1 return v1 .end method--
不過基本上 Dalvik Bytecode 比較容易理,要進行修改也容易許多。
Dalvik Bytecode : http://www.netmite.com/android/mydroid/dalvik/docs/dalvik-bytecode.html
沒有留言:
張貼留言