APK介紹 - Android逆向(一)
手頭上有個(gè)校園寬帶客戶端爽航,拿著想要破解掉讥珍,于是開(kāi)始了我的不歸之路,現(xiàn)在整理一下我的學(xué)習(xí)歷程趟卸,也算是一個(gè)知識(shí)儲(chǔ)備吧锄列。
首先奉上enjarify的github地址惯悠,小伙伴們可以clone到本地使用哦
APK結(jié)構(gòu)
首先來(lái)講一下我們拿到的Android安裝包.apk
文件克婶。.apk
文件可以使用WinRAR或者7zip等壓縮工具解壓,其本質(zhì)是一個(gè)MIME為ZIP的壓縮包萝风,我們將.apk
修改為.zip
后可以看到安裝包內(nèi)的文件結(jié)構(gòu)紫岩,下面是一些常見(jiàn)文件夾:
- assets目錄 存放需要打包到APK中的靜態(tài)文件
- lib目錄 程序依賴的Native庫(kù)
- res目錄 存放應(yīng)用程序的資源
- META-INF目錄 存放應(yīng)用程序簽名和證書(shū)的目錄
- AndroidManifest.xml 應(yīng)用程序的配置文件
- classes.dex dex可執(zhí)行文件
- resources.arsc 資源配置文件
一個(gè)典型的文件結(jié)構(gòu)如下:
下面我們就具體講講這些文件或目錄的作用和在逆向中的涉及到的修改操作:
assets目錄
用于存放需要打包到APK中的靜態(tài)文件,和res的不同點(diǎn)在于揩晴,assets目錄支持任意深度的子目錄,用戶可以根據(jù)自己的需求任意部署文件夾架構(gòu)诅愚,而且res目錄下的文件會(huì)在.R文件中生成對(duì)應(yīng)的資源ID违孝,assets不會(huì)自動(dòng)生成對(duì)應(yīng)的ID,訪問(wèn)的時(shí)候需要AssetManager類雌桑。里面可以存放一些html文件或者圖片等資源校坑,可以看一下在正常寫(xiě)Android程序時(shí)對(duì)assets目錄的使用
lib目錄
這里存放應(yīng)用程序依賴的native庫(kù)文件,一般是用C/C++編寫(xiě)膏斤,這里的lib庫(kù)可能包含4中不同類型掸绞,根據(jù)CPU型號(hào)的不同耕捞,大體可以分為ARM俺抽,ARM-v7a,MIPS振愿,X86冕末,分別對(duì)應(yīng)著ARM架構(gòu)侣颂,ARM-V7架構(gòu),MIPS架構(gòu)和X86架構(gòu)藻肄,這些so庫(kù)在APK包中的構(gòu)成如下:
這里的文件都是一些相對(duì)不容易被逆向的程序邏輯嘹屯,在抖音中州弟,其加密邏輯被編譯到.so
文件中,防止被輕易地破解桐经。案例
res目錄
res是resource的縮寫(xiě)阴挣,這個(gè)目錄存放資源文件纺腊,存在這個(gè)文件夾下的所有文件都會(huì)映射到Android工程的.R文件中,生成對(duì)應(yīng)的ID誓沸,訪問(wèn)的時(shí)候直接使用資源ID即R.id.filename拜隧,res文件夾下可以包含多個(gè)文件夾趁仙,其中anim存放動(dòng)畫(huà)文件雀费;drawable目錄存放圖像資源;layout目錄存放布局文件忿峻;values目錄存放一些特征值逛尚,colors.xml存放color顏色值刁愿,dimens.xml定義尺寸值,string.xml定義字符串的值克握,styles.xml定義樣式對(duì)象枷踏;xml文件夾存放任意xml文件旭蠕,在運(yùn)行時(shí)可以通過(guò)Resources.getXML()讀取佑稠;raw是可以直接復(fù)制到設(shè)備中的任意文件舌胶,他們無(wú)需編譯疮丛。
res內(nèi)的內(nèi)容常用來(lái)做apk漢化等工作誊薄,因?yàn)樵谏厦娴拿枋鲋形覀兛梢钥吹剑诓簧婕斑壿嫷那闆r下切心,所有的字符串圖像等都在res目錄中被保存绽昏,只要我們替換掉那些非本國(guó)語(yǔ)言的字符圖像俏脊,就可以實(shí)現(xiàn)程序的漢化,不得不說(shuō)這非常方便啼县。
META-INF目錄
保存應(yīng)用的簽名信息季眷,簽名信息可以驗(yàn)證APK文件的完整性卷胯。AndroidSDK在打包APK時(shí)會(huì)計(jì)算APK包中所有文件的完整性,并且把這些完整性保存到META-INF文件夾下挺峡,應(yīng)用程序在安裝的時(shí)候首先會(huì)根據(jù)META-INF文件夾校驗(yàn)APK的完整性橱赠,這樣就可以保證APK中的每一個(gè)文件都不能被篡改箫津。以此來(lái)確保APK應(yīng)用程序不被惡意修改或者病毒感染,有利于確保Android應(yīng)用的完整性和系統(tǒng)的安全性饼拍。META-INF目錄下包含的文件有CERT.RSA,CERT.DSA漓柑,CERT.SF和MANIFEST.MF欺缘,其中CERT.RSA是開(kāi)發(fā)者利用私鑰對(duì)APK進(jìn)行簽名的簽名文件挤安,CERT.SF蛤铜,MANIFEST.MF記錄了文件中文件的SHA-1哈希值。
在逆向完成后重新打包的過(guò)程中剿干,我們需要對(duì)其進(jìn)行重新簽名穆刻,會(huì)對(duì)這里的內(nèi)容進(jìn)行修改
具體可以看這里:
- apk中的META-INF目錄
- What are the purposes of files in META-INF folder of an APK file?
- android中簽名原理和安全性分析之meta-inf文件講解
AndroidManifest.xml
是Android應(yīng)用程序的配置文件氢伟,是一個(gè)用來(lái)描述Android應(yīng)用“整體資訊”的設(shè)定文件朵锣,簡(jiǎn)單來(lái)說(shuō),相當(dāng)于Android應(yīng)用向Android系統(tǒng)“自我介紹”的配置文件飞傀,Android系統(tǒng)可以根據(jù)這個(gè)“自我介紹”完整地了解APK應(yīng)用程序的資訊砸烦,每個(gè)Android應(yīng)用程序都必須包含一個(gè)AndroidManifest.xml文件绞吁,且它的名字是固定的,不能修改雪隧。我們?cè)陂_(kāi)發(fā)Android應(yīng)用程序的時(shí)候脑沿,一般都把代碼中的每一個(gè)Activity马僻,Service,Provider和Receiver在AndroidManifest.xml中注冊(cè)措近,只有這樣系統(tǒng)才能啟動(dòng)對(duì)應(yīng)的組件瞭郑,另外這個(gè)文件還包含一些權(quán)限聲明以及使用的SDK版本信息等等鸭你。程序打包時(shí)袱巨,會(huì)把AndroidManifest.xml進(jìn)行簡(jiǎn)單的編譯,便于Android系統(tǒng)識(shí)別场绿,編譯之后的格式是AXML格式焰盗,如下圖所示:
在正常的應(yīng)用開(kāi)發(fā)工程中姨谷,AndroidMainifest.xml里包括了應(yīng)用的配置和程序入口映九,我們可以在這里找到一些有用的信息。
具體可以看Android Developers
而逆向出來(lái)的AndroidMainifest.xml是axml捌议,其結(jié)構(gòu)如上圖瓣颅,具體內(nèi)容如下:
axml頭:其中的axml頭是固定標(biāo)識(shí)axml文件的譬正,其值固定時(shí)0x00080003。
axml文件長(zhǎng)度:標(biāo)識(shí)axml文件的大小粉怕。
StringDataSegment:xml文件中所有字符串類型保存在此。
ResourceIdSegment:xml文件中聲明的資源文件ID保存于此秉犹。
XmlContentSegment:是xml的內(nèi)容段崇堵,按照xml文件中的結(jié)構(gòu)依次排開(kāi)客燕,保存xml的數(shù)據(jù)內(nèi)容。
classes.dex
這個(gè)是我們逆向時(shí)主要關(guān)注的內(nèi)容之一棍辕。傳統(tǒng)的Java程序楚昭,首先先把Java文件編譯成class文件拍顷,字節(jié)碼都保存在了class文件中,Java虛擬機(jī)可以通過(guò)解釋執(zhí)行這些class文件尿贫。而Dalvik虛擬機(jī)是在Java虛擬機(jī)進(jìn)行了優(yōu)化庆亡,執(zhí)行的是Dalvik字節(jié)碼捞稿,而這些Dalvik字節(jié)碼是由Java字節(jié)碼轉(zhuǎn)換而來(lái)娱局,一般情況下,Android應(yīng)用在打包時(shí)通過(guò)AndroidSDK中的dx工具將Java字節(jié)碼轉(zhuǎn)換為Dalvik字節(jié)碼任斋。dx工具可以對(duì)多個(gè)class文件進(jìn)行合并废酷,重組,優(yōu)化澈蟆,可以達(dá)到減小體積,縮短運(yùn)行時(shí)間的目的背蟆。dx工具的轉(zhuǎn)換過(guò)程如圖所示:
如圖,dx工具把每個(gè).class文件的每個(gè)區(qū)域的內(nèi)容進(jìn)行去重志珍,重組,優(yōu)化重排后生成dex文件柜某,生成的dex文件可以在Dalvik虛擬機(jī)執(zhí)行喂击,且速度比較快淤翔。
這里有Google的官方檔案
resources.arsc
用來(lái)記錄資源文件和資源ID之間的映射關(guān)系旁壮,用來(lái)根據(jù)資源ID尋找資源。Android的開(kāi)發(fā)是分模塊的裁奇,res目錄專門用來(lái)存放資源文件麦撵,當(dāng)在代碼中需要調(diào)用資源文件時(shí),只需要調(diào)用findviewbyId()就可以得到資源文件五垮,每當(dāng)在res文件夾下放一個(gè)文件放仗,aapt就會(huì)自動(dòng)生成對(duì)應(yīng)的ID保存在.R文件撬碟,我們調(diào)用這個(gè)ID就可以莉撇,但是只有這個(gè)ID還不夠棍郎,.R文件只是保證編譯程序不報(bào)錯(cuò)涂佃,實(shí)際上在程序運(yùn)行時(shí)蜈敢,系統(tǒng)要根據(jù)ID去尋找對(duì)應(yīng)的資源路徑,而resources.arsc文件就是用來(lái)記錄這些ID和資源文件位置對(duì)應(yīng)關(guān)系的文件伯病。
APK打包流程
具體的操作如下
- 使用 aapt(The Android Asset Packing Tool) 對(duì)資源文件進(jìn)行打包午笛,生成 R.java 文件药磺。
- 如果項(xiàng)目中使用到了 AIDL(Android Interface Definition Language)提供的服務(wù)煤伟,則需要使用 AIDL 工具解析 AIDL 接口文件生成相應(yīng)的 Java 代碼。
- 使用 javac 將 R.java 和 AIDL 文件編譯為 .class 文件驼卖。
- 使用 dx 工具將 class 和第三方的 library 轉(zhuǎn)換為 dex 文件酌畜。
- 利用 apkbuilder 將第一步編譯后的資源卿叽、第四步生成的 .dex 文件,以及一些其它資源打包到 APK 文件中贩虾。
- 這一部主要是對(duì) APK 進(jìn)行簽名缎罢。可以分為兩種情況舰始,如果我們是要發(fā)布 App丸卷,那就采用 RealeaseKeystore 簽名询刹;反之,我們?nèi)绻皇窍胍獙?duì) App 進(jìn)行調(diào)試沐兰,那就使用 debug.keystore 簽名僧鲁。
- 在發(fā)布正式版之前象泵,我們需要將 APK 包中資源文件距離文件的起始偏移修改為 4 字節(jié)的整數(shù)倍數(shù)斟叼,這樣,在之后運(yùn)行 App 的時(shí)候忽孽,速度會(huì)比較快谢床。
APK安裝過(guò)程
Adroid的應(yīng)用安裝涉及到如下幾個(gè)目錄:
/data/app:存放用戶安裝的APK的目錄识腿,安裝時(shí),把APK拷貝于此骂束。
/data/data:應(yīng)用安裝完成后成箫,在/data/data目錄下自動(dòng)生成和APK包名(packagename)一樣的文件夾蹬昌,用于存放應(yīng)用程序的數(shù)據(jù)。
/data/dalvik-cache:存放APK的odex文件栖榨,便于應(yīng)用啟動(dòng)時(shí)直接執(zhí)行。
具體安裝過(guò)程如下:
安裝過(guò)程:復(fù)制apk安裝包到/data/app目錄下筹煮,解壓并掃描安裝包败潦,向資源管理器注入apk資源准脂,解析AndroidManifest文件,并在/data/data目錄下創(chuàng)建對(duì)應(yīng)的應(yīng)用數(shù)據(jù)目錄沟饥,贤旷,如果APK中有l(wèi)ib庫(kù)砾脑,系統(tǒng)會(huì)判斷這些so庫(kù)的名字,查看是否以lib開(kāi)頭盅藻,是否以.so結(jié)尾氏淑,再根據(jù)CPU的架構(gòu)解壓對(duì)應(yīng)的so庫(kù)到/data/data/{pkg}/lib下硕噩。然后針對(duì)dalvik/art環(huán)境優(yōu)化dex文件,保存到dalvik-cache目錄守问,將AndroidManifest文件解析出的組件坑资、權(quán)限注冊(cè)到PackageManagerService袱贮,完成后發(fā)送廣播。
APK安裝的時(shí)候會(huì)把DEX文件解壓并且優(yōu)化位odex嗽仪,odex的格式如圖所示:
odex在原來(lái)的dex文件頭添加了一些數(shù)據(jù)闻坚,在文件尾部添加了程序運(yùn)行時(shí)需要的依賴庫(kù)和輔助數(shù)據(jù),使得程序運(yùn)行速度更快仅偎。
下面是一張整體的流程圖:
時(shí)序圖如下:
參考資料
APK文件結(jié)構(gòu)和安裝過(guò)程 - CSDN
Android應(yīng)用安裝流程分析 - solart
首發(fā)于個(gè)人博客Bismuth