APK是AndroidPackage的縮寫,即Android安裝包(apk),能夠經過將APK文件直接傳到Android模擬器或手機中執行便可安裝。APK的本質是一個zip的壓縮包,用壓縮軟件打開後就能夠看到裏面的文件以及結構。java
APK的文件組成:android
AndroidManifest.xml:清單文件,主要包含四大組件註冊信息,應用權限,和元數據等信息,此文件列出了應用的名稱、版本、訪問權限和引用的庫文件。安全
classes.dex:Dalvid虛擬機上運行的字節碼文件,咱們在將java代碼編譯成class字節碼文件後,經過android SDK提供的工具將class轉換成dex字節碼,dex文件可能有多個。數據結構
META—INF: 包含 CERT.SF 和 CERT.RSA 簽名文件,以及 MANIFEST.MF 清單文件。CERT.SF、MANIFEST.MF是對資源作的SHA1 hash處理,CERT.RSA包含有公鑰證書和簽名。app
res:包含未編譯到 resources.arsc 中的資源例如:佈局xml、圖片、動畫等。函數
resources.arsc 打包工具會提取此 XML 內容,將其編譯爲二進制文件形式,並將相應內容進行歸檔。此內容包括語言字符串和樣式,以及未直接包含在 resources.arsc 文件中的內容(例如佈局文件和圖片)的路徑。工具
lib/:包含特定於處理器軟件層的編譯代碼。此目錄包含每種平臺類型的子目錄,如 armeabi、armeabi-v7a、arm64-v8a、x8六、x86_64 和 mips佈局
由上圖可知,APK打包的流程主要有以下幾個步驟:學習
工具aapt優化
輸入
過程
輸出
總結
這個主要是在aidl接口文件,經過SDK提供的AIDL工具生成相應的java文件,供程序調用,沒有用到aidl的工程,並不會有這個過程
工具
輸入
輸出
總結:
工具
輸入
過程
輸出
android應用須要簽名才能在設備上安裝。
使用JDK自帶簽名工具的jarsigner:
對齊使用的是android-idk/tools目錄下的zipalign工具,主要工做是將apk包中全部的資源文件起始偏移爲4字節的整數倍,這樣經過內存映射訪問apk時的速度會更快。
通過這幾步的編譯,輸出的apk文件,最終是一個具備特定文件格式的靜態文件。若是拿到該文件,分析文件格式和逆向,最終是能夠分析一個破解apk的業務和流程,這就必然對apk產生安全問題。
Android 支持如下三種應用簽名方案:
從一開始,APK 簽名就是Android 的一個有機部分。該方案基於簽名的JAR。 可是v1方案存在如下一些不足:
簽名不保護APK的某些部分,例如ZIP元數據。
APK驗證程序須要處理大量不可信(還沒有通過驗證)的數據結構,而後會捨棄不受簽名保護的數據,這會致使至關大的受攻擊面。
APK 驗證程序必須解壓全部已壓縮的條目,而這須要花費更多時間和內存。
因爲這些不足致使apk簽名後能夠進行許多修改,能夠移動甚至從新壓縮文件,致使一些安全事件的發生。爲了解決這些問題, google在Android 7.0之後引入了V2簽名方案Android 7.0 中引入了APK 簽名方案v2, Android 9以後引入v3(v2+)。
APK v2簽名方案是一種全文件簽名方案,該方案可以:
使用APK簽名方案v2進行簽名時,會在APK文件中插入一個APK簽名分塊,該分塊位於「ZIP中央目錄」部分以前並緊鄰該部分。在「APK 簽名分塊」內,v2簽名和簽名者身份信息會存儲在APK簽名方案v2分塊中。
搭載Android 7.0 及更高版本的設備支持APK 簽名方案v2(v2方案)及更高版本的方案(在Android P(Android 9) 中,v2方案已更新爲v3方案,以便在簽名分塊中包含其餘信息,但在其餘方面保持相同的工做方式)。該方案會對APK的內容進行哈希處理和簽名,而後將生成的「APK簽名分塊」插入到APK中。
在驗證期間,v2+方案會將APK文件視爲Blob,並對整個文件進行簽名檢查。對APK進行的任何修改(包括對ZIP元數據進行的修改)都會使APK簽名做廢。這種形式的APK驗證不只速度要快得多,並且可以發現更多種未經受權的修改。新的簽名格式向後兼容,所以,使用這種新格式簽名的APK 可在更低版本的Android設備上進行安裝(會直接忽略添加到APK 的額外數據),但前提是這些APK 還帶有v1簽名。
驗證程序會對照存儲在「APK簽名分塊」中的v2+簽名對APK的全文件哈希進行驗證。該哈希涵蓋除「APK簽名分塊」(其中包含v2+簽名)以外的全部內容。在「APK簽名分塊」之外對APK進行的任何修改都會使APK的v2+簽名做廢。v2+簽名被刪除的APK也會被拒絕,由於v1簽名指明相應APK帶有v2簽名,因此Android 7.0及更高版本會拒絕使用v1簽名驗證APK。
APK反編譯,就是把編譯後的APK文件經過逆向工程手段獲取到原始代碼和資源的一個過程。因爲APK文件是一個具備固定文件格式的靜態文件,並且可以解析和執行的,因此理論上能夠對一個APK文件進行逆向的分析進行反編譯、破解。若是一個APK沒有進行安全方面的防禦措施,是能夠經過很簡單的幾步給破解掉。
apktool+dex2jar+JD-GUI
使用如下命令:./dex2jar.sh classes.dex
經過JD-GUI打開classes_dex2jar.jar能夠看到大部分源。
經過apktool直接反編譯app.apk便可看到資源文件 ./apktool d app.apk -f -o ./app3
反編譯後AndroidMenifest.xml:
反編譯後layout:
反編譯後color文件:
至此,一個apk中全部的資源文件、代碼文件所有被反編譯出來,因此做爲一個app開發者,爲了數據、業務的安全,必需要對app進行安全處理,防止對用戶形成信息、財產方面的損失,如下是幾個對apk進行安全加固的處理方法。
對於apk安全加固主要分爲兩個方面的安全防禦:
混淆代碼並非讓代碼沒法被反編譯,而是將代碼中的類、方法、變量等信息進行重命名,把它們改爲一些毫無心義的名字。由於對於咱們而言可能CellPhone類的call()方法意味着不少信息,而A類的a()方法則沒有任何意義,可是對於計算機而言,它們都是平等的,計算機不會試圖去理解CellPhone是什麼意思,它只會按照設定好的邏輯來去執行這些代碼。因此說混淆代碼能夠在不影響程序正常運行的前提下讓破解者對代碼邏輯的理解難度加大,從而大大提高了程序的安全性。
APK必須被簽名纔可以安裝到手機中,沒有被簽名的apk是沒法安裝到設備中的。可是簽名在反編譯以後是獲取不到的,因此只能用本身的簽名文件去簽名,可是在已經安裝了應用設備中在安裝一個簽名不一致的應用會致使安裝失敗。
利用該原理,能夠在程序啓動的時候獲取應用簽名,而後和正確的簽名值作比對,若是不符合就直接退出程序。
既然是在程序的入口進行簽名比對,就能夠反編譯找到程序入口處相關的代碼,進行處理刪除或者把簽名信息改爲本身的簽名值,從新打包便可解決這個問題。
- 加密的源apk
- 本身的殼apk,負責解密apk,並動態加載apk的工做
- 加密工具,負責將源apk進行加密和殼dex合併成新的dex
複製代碼
反調試檢測是爲了應對如今不少破解者使用IDA進行動態方式調試so文件,從而獲取重要的信息,知道IDA進行so動態調試是基於進程的注入技術,而後使用Linux中的ptrace機制,進行調試目標進程的附加操做。ptrace機制有一個特色,若是一個進程被調試了,在它進程的status文件中有一個字段TracerPid會記錄調試者的進程id值,如圖所示:
查看文件:/proc/[myPid]/status,在第六行,有一個TracerPid字段,就是記錄了調試者的進程id。那麼就能夠這麼作來達到反調試的功效了:輪詢遍歷本身進程的status文件,而後讀取TracerPid字段值,若是發現它大於0,就表明着本身的應用在被人調試,因此就立馬退出程序。原理知道了,代碼實現也很簡單,這裏用pthread建立一個線程,而後進行輪詢操做: 使用pthreadcreate建立一個線程,線程啓動以後執行threadfunction函數:
看看thread_funcation函數:
Dex-Java2C:將Java代碼翻譯爲C代碼,並實施Native層的代碼混淆保護。
So文件加殼:對SO文件進行總體加殼保護,防止IDA Pro等工具逆向分析。
內存加密:防止內存數據被篡改或Dump,好比Dump解密後的Java代碼。
自身虛擬化保護:專業版採用代碼虛擬化技術對自身代碼進行保護,防止逆向分析。
對於apk安全方面的技術,層出不窮,安全攻防拉鋸技術不斷改進不斷提高。
apk的編譯是把咱們寫的代碼、資源、庫文件打包成能夠在Android設備上運行的過程,而爲了代碼、數據、業務安全訴求須要對apk進行安全防禦工做。
安全攻防是魔高一尺、道高一丈,特別是金融類app須要高度重視的工做,在此與你們一塊兒學習和分享。
Thanks!
焦亞克, 民生科技有限公司用戶體驗技術部開發工程師。