研究Android近一個月了,總體上來說還是比較容易上手,而且相關的資源也還算豐富。然而一些覺得不錯的應用,沒有提供源碼,想深入研究一下實現原理就只有採用反編譯、破解的辦法了。網上講破解方法的文章很多,但大多是轉載的,大同小異,而且不怎麼完整,這裏總結三種方法,供學習研究,分享如下。首先,用WinRAR解壓apk包,會得到包目錄、classes.dex等文件,之後按以下操作:
一、dexdump方法
dexdump是emulator自帶提供的查看dex文件的工具,可使用類似這樣的命令將dex文件dump到txt文件中:
D:/Program Files/android-sdk-windows-1.6_r1/platforms/android-1.6/tools>dexdump.exe -d classes.dex > spk.dump.txt
得到的文件內容,描述了類的信息,但實在是不好讀啊~~~~
二、dex2jar + XJad 方法
該方法是使用dex2jar.jar包,將classes.dex文件解包成jar,在通過XJad(或者其他class反編譯工具)進行java反編譯。如:
1、dex2jar.bat d:/play/classes.dex
默認的輸出路徑同classes.dex,生成的文件名爲classes.dex.dex2jar.jar
2、使用XJad反編譯該jar包
之後的使用方法,大家都懂的:)
該方法的好處在於,通過XJad反編譯後,大家可直接開到java源文件,缺點在於只能反編譯出開發時的java文件,而開發時使用的lib包不能反編譯出來。
三、AXMLPrinter2.jar + baksmali.jar + smali.jar 方法
這個方法就強大了,AXMLPrinter2是還原AndroidManifest.xml和main.xml的工具,直接打開這兩個xml文件是亂碼,而通過還原之後,可以很明白的看到裏面的內容(我猜測還是使用了字節異或的方式加的密)。
baksmali.jar是反解析dex的工具,smali.jar則是再還原成dex的工具
操作方式如下:
1、java -jar AXMLPrinter2.jar D:/play/AndroidManifest.xml > AndroidManifest.txt
2、java -jar AXMLPrinter2.jar D:/play/res/layout/main.xml > main.txt
3、java -jar baksmali-1.2.5.jar -o classout/ d:/play/classes.dex
baksmali可解析(注意,是解析,不是反編譯)原java包以及引用的lib包,解析出的文件認真看還是能看懂,比如以下片段:
- .class Lcom/paul/test/a;
- .super Landroid/view/View;
- # static fields
- .field private static final a:Landroid/graphics/Typeface;
- # instance fields
- .field private b:I
- .field private c:I
- .field private d:Z
- .field private e:J
- .field private f:I
- .field private l:[Ljava/lang/String;
- # direct methods
- .method static constructor <clinit>()V
- .registers 2
- sget-object v0, Landroid/graphics/Typeface;->SANS_SERIF:Landroid/graphics/Typeface;
- const/4 v1, 0x0
- invoke-static {v0, v1}, Landroid/graphics/Typeface;->create(Landroid/graphics/Typeface;I)Landroid/graphics/Typeface;
- move-result-object v0
- sput-object v0, Lcom/wiyun/ad/a;->a:Landroid/graphics/Typeface;
- return-void
- .end method
- #
- # other methods ..........
- #
- # virtual methods
- .method public onKeyUp(ILandroid/view/KeyEvent;)Z
- .registers 4
- const/16 v0, 0x42
- if-eq p1, v0, :cond_8
- const/16 v0, 0x17
- if-ne p1, v0, :cond_b
- :cond_8
- invoke-direct {p0}, Lcom/paul/test/a;->d()V
- :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
- return v0
- .end method
認真一看,就知道:
# static fields 定義靜態變量的標記
# instance fields 定義實例變量的標記
# direct methods 定義靜態方法的標記
# virtual methods 定義非靜態方法的標記
以onKeyUp方法爲例,其中定義了處理邏輯,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
該方法,能把外部引用的lib包類也解析出來,能開到包的全貌。缺點在於,解析出的smali文件並不是反編譯出的java文件,可讀性降低了,但仔細研究也能看出大概。
以上提到的相關工具包,均可在http://code.google.com上下載到。