(注:根據(jù)網(wǎng)上所看博文整理而成)
何為APK?
APK全稱:AndroidPackage,即安卓應(yīng)用安裝包;
一個(gè)APK生成的流程:
(圖片來(lái)自于http://www.cnblogs.com/devinzhang/archive/2011/12/20/2294686.html)
(這里是參照這篇博文所寫的筆記)
1.假定系統(tǒng)(Linux和Windows無(wú)所謂)已經(jīng)安裝了(JDK和 android sdk), android sdk的路徑已知為:Android_sdk_home,想要編譯的android 版本為
android_os_version,
我們重點(diǎn)關(guān)注的:
1.此過程的輸入;
2.此過程輸出;
3.此過程使用了什么工具
名稱 | 功能介紹 | 在操作系統(tǒng)中路徑 |
---|---|---|
aapt | android資源打包工具 | ${ANDROID_SDK_HOME}/platform-tools/appt |
aidl | Android接口描述語(yǔ)言轉(zhuǎn)化為.java文件的工具 | ${ANDROID_SDK_HOME}/platform-tools/aidl |
javac | Java Compiler | ${JDK_HOME}/javac或/usr/bin/javac |
dex | 轉(zhuǎn)化.class文件為為Davik VM能識(shí)別的.dex文件 | ${ANDROID_SDK_HOME}/platform-tools/dx |
apkbuilde | 生成apk包 | ${ANDROID_SDK_HOME}/tools/opkbuilder |
jarsigner | .jar文件的簽名工具 | ${JDK_HOME}/jarsigner或/usr/bin/jarsigner |
zipalign | 字節(jié)碼對(duì)齊工具 | ${ANDROID_SDK_HOME}/tools/zipalign |
第一步:打包資源文件,生成r.java文件
輸入:
resource文件(就是工程中res中的文件),Assets文件(另外一種資源,此類資源安卓系統(tǒng)不像對(duì)res中的文件那樣去優(yōu)化),AndroidManifest.xml
(清單文件)(包名就從這里讀取,生成r.java就需要包名)苗缩,android基礎(chǔ)類庫(kù)(android.jar文件)四類文件;
輸出:
打包好的資源(即:一般在Android工程的bin目錄可以看到一個(gè)叫resources.ap_的文件就是它了)析显;R.java文件(在gen目錄中)
工具:
aapt工具纱兑,它的路徑在${ANDROID_SDK_HOME}/platform-tools/aapt(如果你使用的是Windows系統(tǒng)步责,按慣例路徑應(yīng)該這樣寫:%ANDROID_SDK_HOME%\platform-tools\aapt.exe放案,下同)角钩。
第二步:處理AIDL文件,生成對(duì)應(yīng)的.java文件(有很多工程沒有用到AIDL,那么此過程就可以省略)
輸入:
源碼文件迁央、aidl文件、framework.aidl文件
輸出:
對(duì)應(yīng)的.java文件
工具:
aidl工具
第三步:
編譯java文件,生成對(duì)應(yīng)的.class文件
輸入:
源碼文件(包括R.java和AIDL生成的.java文件)僵刮、庫(kù)文件(.jar文件)
輸出:
.class文件
工具:
javac工具
第四步:
把.class文件轉(zhuǎn)化成Davik VM支持的.dex文件
輸入:
.class文件(包括Aidl生成.class文件据忘,R生成的.class文件峡钓,源文件生成的.class文件),庫(kù)文件(.jar文件)
輸出:
.dex文件
工具:
javac工具
第五步:
打包生成未簽名的.apk文件
輸入:
打包后的資源文件若河、打包后類文件(.dex文件)、libs文件(包括.so文件)
輸出:
未簽名的.apk文件
工具:
apkbuilder工具
第六步:
對(duì)未簽名.apk文件進(jìn)行簽名
輸入:
未簽名的.apk文件
輸出:
簽名的.apk文件
工具:
jarsigner
第七步:
對(duì)簽名后的.apk文件進(jìn)行對(duì)齊處理(不進(jìn)行對(duì)齊處理是不能發(fā)布到Google Market的)
輸入:
簽名后的.apk文件
輸出:
對(duì)齊后的.apk文件
工具:
zipalign工具
了解這個(gè)過程可以實(shí)現(xiàn)自動(dòng)化腳本,利用Python寞宫、Perl等,類似于Windows下的批處理萧福,linux下的Bash,Java下的Ant,可以將sdk精簡(jiǎn)到更小辈赋。
2.apk結(jié)構(gòu)
一個(gè)典型的apk結(jié)構(gòu):(原文件名為2,后改為2.zip,然后將其解壓)
2.1AndroidManifest.xml(清單文件)
這里的AndroidManifest.xml就是源代碼中的AndroidManifest.xml編譯后所得到的文件鲫忍。AndroidManifest.xml是安卓應(yīng)用程序的全局配置文件,該文件保存了apk的包名,钥屈,版本信息悟民,sdk版本,四大組件(Activity ,Service, Boardcast Receiver, Content Provider)的配置信息,程序所需要的權(quán)限也在其(AndroidManifest.xml)中;
Android應(yīng)用程序簽名詳解見:
http://blog.csdn.net/lyq8479/article/details/6401093
http://blog.csdn.net/jiangwei0910410003/article/details/50402000
AndroidManifest.xml配置文件詳解
2.2 classes.dex
雖然Android開發(fā)的源語(yǔ)言是java篷就,但是Android應(yīng)用程序卻不在標(biāo)準(zhǔn)的java虛擬機(jī)上運(yùn)行射亏。Google為Android平臺(tái)專門設(shè)計(jì)了一套用于運(yùn)行Android程序的虛擬機(jī),這就是Dalvik虛擬機(jī)(Dalvik Virtual Machine)竭业。而classes.dex就是運(yùn)行在Dalvik虛擬機(jī)上的可執(zhí)行文件智润。從圖2中可以看出,我們編寫的java源代碼經(jīng)過java編譯器編譯后會(huì)生成.class文件未辆;而Android SDK自帶的dx工具(dx.bat在\sdk安裝目錄\sdk\build-tools\android-4.4這條路徑下窟绷,dx.jar在\sdk安裝目錄\sdk\build-tools\android-4.4\lib這條路徑下)會(huì)將這些.class文件轉(zhuǎn)換為classes.dex。值得一提的是咐柜,在Android5.0中兼蜈,Dalvik虛擬機(jī)已經(jīng)被ART虛擬機(jī)(Android Runtime)所取代。有興趣的童靴可以看這篇文章: Android ART運(yùn)行時(shí)無(wú)縫替換Dalvik虛擬機(jī)的過程分析拙友。
雖然在Android5.0中ART虛擬機(jī)已經(jīng)取代了Dalvik虛擬機(jī)为狸,但是使用Android5.0 SDK生成的apk與低版本SDK生成的apk相比,二者的文件結(jié)構(gòu)變化不大遗契。采用Android5.0 SDK生成的apk中也有classes.dex這個(gè)文件钥平。
2.3 resources.arsc
arsc,全稱為application resource files姊途,是一個(gè)包含了已被編譯好的資源的二進(jìn)制格式文件涉瘾。我們知道,一個(gè)安卓應(yīng)用程序往往包含了很多的資源(例如:layout文件捷兰,圖片立叛,字符串,菜單)贡茅。那么程序在運(yùn)行時(shí)秘蛇,是怎么調(diào)用這些資源的呢其做?其實(shí)在apk編譯和生成過程中(參考流程圖),AAPT一方面會(huì)在源代碼中為每個(gè)資源文件都賦予一個(gè)32位的整數(shù)做為標(biāo)記赁还,這些整數(shù)全部保存在R.java這個(gè)源文件中妖泄,R.java是系統(tǒng)自動(dòng)生成的,用戶是無(wú)法對(duì)其進(jìn)行修改的艘策。這里需要注意一點(diǎn):assets文件夾中的資源文件是不會(huì)被編譯的蹈胡,關(guān)于assets文件夾與res文件夾的區(qū)別,感興趣的童靴請(qǐng)看這篇文章:Android中資源文件夾res/raw和assets的使用 朋蔫。另一方面罚渐,AAPT會(huì)生成一個(gè)resources.arsc文件,這個(gè)二進(jìn)制文件包含了所有的資源名字以及標(biāo)記這些資源的數(shù)字驯妄。resources.arsc的作用是當(dāng)app運(yùn)行時(shí)荷并,手機(jī)設(shè)備通過該文件能夠很方便匹配和解析apk中的資源。
2.4 res文件夾
apk中的res文件夾由drawable文件夾青扔,layout文件夾源织,menu文件夾這3個(gè)子文件夾組成。其中微猖,drawable文件夾用于存放apk的圖片資源雀鹃,layout文件夾用于存放布局文件,menu文件夾用于存放菜單文件励两。與原工程項(xiàng)目中的res文件夾相比导帝,apk中的res文件夾少了values這個(gè)文件夾
2.5META-INF文件夾
META-INF文件夾存放著apk的簽名信息棺亭。如果你還不了解安卓簽名機(jī)制复颈,請(qǐng)看上面鏈接脉执;
打開META-INF文件夾,可以看到3個(gè)文件:
CERT.RSA,CERT.SF,MANIFEST.MF盲憎。
其中CERT.RSA包含了公鑰信息和發(fā)布機(jī)構(gòu)信息嗅骄;
MANIFEST.MF中保存了除自身以外所有其他文件的SHA-1并進(jìn)行base64編碼后的值(注意:對(duì)于xml等文本格式的資源文件,系統(tǒng)先將這些文本文件編譯成二進(jìn)制文件饼疙,再獲取二進(jìn)制文件的SHA-1值并進(jìn)行base64編碼)溺森;
CERT.SF的生成過程分兩步:(1)讀取MANIFEST.MF文件的SHA-1,然后將該SHA-1值base64編碼后保存為SHA1-Digest-Manifest窑眯,所以與MANIFEST.MF文件相比屏积,CERT.SF會(huì)多出一個(gè)SHA1-Digest-Manifest值,(2)然后再逐個(gè)讀取MANIFEST.MF中每個(gè)資源文件的Name和SHA1-Digest值再添加2個(gè)空行后進(jìn)行SHA-1磅甩,將該SHA-1值進(jìn)行base64編碼后依次寫到CERT.SF中炊林。是否聽得迷迷糊糊,下面手動(dòng)模擬MANIFEST.MF文件生成classes.dex的SHA1-Digest的過程:
(1)通過HashTab插件可以查看到classes.dex文件的SHA-1卷要,如圖所示
(2)可以得知classes.dex文件的SHA-1值為:AF37C43BD22A4022FA1998F82F08B278B8844EDB(請(qǐng)注意:這是一串16進(jìn)制數(shù)字渣聚,不是字符串)独榴,然后在線對(duì)該SHA-1值進(jìn)行base64編碼可以得到其對(duì)應(yīng)的base64編碼為: rzfEO9IqQCL6GZj4LwiyeLiETts=
打開MANIFEST.MF文件,可以看到classes.dex的SHA1-Digest值為 rzfEO9IqQCL6GZj4LwiyeLiETts= 如圖所示:
這與我們所得到的base64編碼是一樣的奕枝,由此可見我們手動(dòng)生成MANIFEST.MF中classes.dex的SHA1-Digest值是正確的棺榔。
下面是手動(dòng)模擬CERT.SF生成classes.dex的SHA1-Digest的過程:
(1)新建一個(gè)文本文件,將MANIFEST.MF中的classes.dex的Name和SHA1-Digest這兩行拷貝出來(lái)隘道,后面跟上兩個(gè)空行症歇,保存到文件中,如圖7所示:
圖 7 用于保存MANIFEST.MF文件中classes.dex所對(duì)應(yīng)的Name與SHA1-Digest值的文本文件
(2)通過HashTab插件查看該文本文件的SHA-1值薄声,如圖8所示:
可以看出該文本文件的SHA-1值為: 3AD0EBD342ABC2CF801CFAACFAAA45334E0A4337, 將該SHA-1值進(jìn)行base64編碼可以得到base64編碼值:OtDr00Krws+AHPqs+qpFM04KQzc=
(3)打開CERT.SF文件题画,我們可以看到在文件中classes.dex對(duì)應(yīng)的SHA1-Digest值為: OtDr00Krws+AHPqs+qpFM04KQzc=
如圖9所示:
第(2)步最后得到的base64值與該SHA1-Digest值一致默辨,所以可以證明我們手動(dòng)模擬生成classes.dex的SHA1-Digest值是正確的。關(guān)于這3個(gè)文件的詳細(xì)介紹苍息,有興趣的童靴請(qǐng)看這篇文章:android APK簽名匯總整理 缩幸。如果從事安卓逆向,我們必須要清楚一點(diǎn):沒有簽名的apk是無(wú)法在真機(jī)(模擬器)上安裝運(yùn)行的竞思,所以簽名文件對(duì)apk是很重要的表谊。
3.總結(jié)
安卓項(xiàng)目的文件結(jié)構(gòu)與安卓apk的文件結(jié)構(gòu)存在著一一對(duì)應(yīng)的關(guān)系;
安卓應(yīng)用開發(fā)的本質(zhì)是:
將源代碼和各種資源文件編譯整合成一個(gè)apk盖喷。
安卓逆向的本質(zhì)是:
想辦法將apk轉(zhuǎn)化為源代碼和資源文件爆办。 簡(jiǎn)單來(lái)說(shuō),apk就是一個(gè)帶有簽名的zip格式的壓縮包课梳,簽名為了保護(hù)開發(fā)者的權(quán)益和標(biāo)識(shí)apk距辆。
做為android逆向?qū)W習(xí)的第一步,了解apk的文件結(jié)構(gòu)和生成過程是很有必要的暮刃。這篇文章總結(jié)了很多安卓大牛博客的知識(shí)點(diǎn)跨算,主要介紹了基本的一個(gè)apk的文件結(jié)構(gòu)和生成過程,但是真實(shí)的商業(yè)apk的文件結(jié)構(gòu)會(huì)更復(fù)雜椭懊,為了提升apk的安全性能诸蚕,現(xiàn)在很多安卓應(yīng)用程序的核心代碼都采用NDK開發(fā),所以生成的apk中會(huì)多出一個(gè)lib文件夾用于存放so文件氧猬。