哔哩哔哩:https://www.bilibili.com/video/BV1UE411A7rW?p=1
Android 逆向工程師系統教育訓練‹第九期›( 課程目錄 ):https://ke.yijincc.com/course-21.htm
安卓逆向工程師:https://ke.yijincc.com/profession/1.htm
打造年輕人的第一套安卓逆向環境!
原味鏡像介紹文章:https://mp.weixin.qq.com/s/gBdcaAx8EInRXPUGeJ5ljQ
原味鏡像介紹視訊:https://www.bilibili.com/video/BV1qQ4y1R7wW/
下載下傳位址:
谷歌盤:https://drive.google.com/drive/folders/1AdZ1x5G9CcJGXiLqGL9mhDJWlRz8KZl_?usp=sharing
GoFile:https://gofile.io/d/GeqM2O
百度盤:連結:https://pan.baidu.com/s/1anvG0Ol_qICt8u7q5_eQJw 提取碼:3x2a
阿裡盤:http://49.235.84.125:8080/r0env
登入時使用者名:root 密碼:toor

1. 逆向環境配置
1. java 開發環境:java jdk、java jre
java jdk 最好安裝 jdk8 的最新版本,如果安裝更高的 java 版本,一些逆向工具可能使用不了。
安裝 java jdk8 的時候會自動彈出 對應 jre 的安裝。
2. 安卓開發環境:安卓 sdk、ndk
安卓 sdk 和 ndk 下載下傳完成後,直接解壓,然後配置環境變量即可。。。
也可以通過 android studio 進行 sdk 和 ndk 的安裝
通過 Android studio下載下傳的 sdk 中沒有 tools 檔案夾的解決辦法:
https://blog.csdn.net/General_Ma/article/details/104707265/
sdk 主要配置兩個目錄:tools、platform_tools
ndk 的安裝:官網下載下傳 ( https://developer.android.google.cn/ndk/ ) ndk 進行安裝
2. APK 檔案結構
APK 是 Android PacKage 的縮寫,即 Android 安裝包。apk 檔案也就是 Android 打包流程的産物。那麼 apk 是一個什麼類型的檔案?它包含了一些什麼内容? 弄清楚了這些,我們就可以帶着目的性,去分析打包流程,可以更好的關注 apk 檔案中的這些内容是在打包流程的哪個過程中産生,以及是如何産生的。
衆所周知,apk 檔案本質上其實是一個 zip 格式的壓縮包。想要知道其中包含了什麼,改字尾然後用解壓縮工具即可打開任何一個APK檔案。 如果有 代碼混淆 和 加密,通過普通解壓縮工具打開裡面的檔案或目錄會看到各種亂碼。
apk 概覽
- assets (程式資源目錄)
- META-INF(簽名證書目錄)
- res(界面布局/圖檔資源目錄)
- AndroidManifest.xml(APK屬性/權限/元件聲明)
- classes.dex(Android 虛拟機可執行位元組碼)
- resources.arsc(字元串/資源索引檔案)
圖示:
這裡解壓了某個未經過 加強加殼 或者 其他手段加密的 Android 安裝封包件,以下為結果截圖:
https://www.sohu.com/a/149758866_675634
主要注意紅色标注部分,這一些檔案和檔案夾是一個 Android 應用基本都具備的。而其他的一些檔案和檔案夾則是一些第三方庫,或者是其他一些代碼生成的。 接下來,依次大概介紹一下這些檔案和檔案夾的作用。
- AndroidManifest.xml:這是 Android 應用的全局配置檔案,它包含了這個應用的很多配置資訊,例如包名、版本号、所需權限、注冊的服務等。可以根據這個檔案在相當程度上了解這個應用的一些資訊。該檔案目前狀态是被編譯為二進制的 XML 檔案,可以通過一些工具(如 apktool)反編譯後進行檢視。Analyze apk 是一個很不錯的 apk 分析(~~hack 入門~~)工具。我們可以通過它直接反編譯看到原始的 AndroidManifest.xml 檔案。
安卓逆向_1 --- 逆向環境配置、APK 檔案結構、APK 打包流程打造年輕人的第一套安卓逆向環境!1. 逆向環境配置2. APK 檔案結構3. APK 打包流程4. APK 安裝流程虛拟機 - assets 檔案夾:assets 檔案夾用于儲存需要保持原始檔案的資源檔案夾,開發過程中拖了什麼到裡面,打包完之後裡面還是什麼。一般用于存放音頻,網頁(幫助頁面之類的),字型等檔案。主要需要知道的點是,它與 res 檔案夾的區分以及如何在應用中通路該檔案夾的資源,如它可以有多級目錄而 res 則隻有兩級。
安卓逆向_1 --- 逆向環境配置、APK 檔案結構、APK 打包流程打造年輕人的第一套安卓逆向環境!1. 逆向環境配置2. APK 檔案結構3. APK 打包流程4. APK 安裝流程虛拟機 - dex 檔案:classes.dex 檔案是 Android 系統運作于 Dalvik Virtual Machine 上的可執行檔案,也是Android 應用程式的核心所在。項目工程中的 Java 源碼通過 javac 生成 class 檔案,再通過 dx 工具轉換為 classes.dex,注意到我們這裡有 classes2.dex 和 classes3.dex。這是方法數超過一個 dex 的上限,分 dex 的結果。分 dex 在 Android 5.0 之前需要開發者自行完成,5.0 後 dx 自帶支援。dex 檔案的資料結構不算複雜,如下圖所示。目前一些熱更新檔有關的技術,主要便是對 dex 做各種處理。
- lib 檔案夾:該目錄存放着應用需要的 native 庫檔案。比如一些底層實作的圖檔處理、音視訊處理、資料加密的庫以 so 庫的形式在該檔案夾中。而該檔案夾下有時會多一個層級,這是根據不同CPU 型号而劃分的,如 ARM,ARM-v7a,x86等。
安卓逆向_1 --- 逆向環境配置、APK 檔案結構、APK 打包流程打造年輕人的第一套安卓逆向環境!1. 逆向環境配置2. APK 檔案結構3. APK 打包流程4. APK 安裝流程虛拟機 -
META-INF 檔案夾:該目錄的主要作用是用于保證 APK 的完整性以及安全性。該檔案夾下,主要有三個檔案。
MANIFEST.MF:這個檔案儲存了 整個apk檔案 中 所有檔案的檔案名 + SHA-1後的編碼值。
這也就意味着,MANIFEST.MF 象征着 apk 包的完整性。
XXX.RSA:這個檔案儲存了公鑰和加密方式的資訊。
XXX.SF:這個檔案與 MANIFEST.MF 的結構一樣,隻是其編碼會被被私鑰加密。
這樣一來每次安裝時,通過該檔案夾中的檔案,就可以完成驗證的過程。
如果 apk 包被改變了,而篡改者沒有私鑰生成 CERT.SF,則無法完成校驗。
安卓逆向_1 --- 逆向環境配置、APK 檔案結構、APK 打包流程打造年輕人的第一套安卓逆向環境!1. 逆向環境配置2. APK 檔案結構3. APK 打包流程4. APK 安裝流程虛拟機 - res 檔案夾:顧名思義,該檔案夾是資源檔案夾。它裡面存放的所有檔案都會被映射到 R 檔案中,生成對應的資源 ID,便于代碼中通過 ID 直接通路。其中的資源檔案包括了動畫(anim),圖像(drwable),布局(layout),常量值(values),顔色值(colors),尺寸值(dimens),字元串(strings),自定義樣式(styles)等。
-
resource.arsc 檔案:這個檔案可以說是所有檔案中結構最複雜的。它記錄了資源檔案,資源檔案位置(各個次元的路徑)和資源 id 的映射關系。并且将所有的 string 都存放在了 string pool 中,節省了在查找資源時,字元串處理的開銷。
我們可以使用 Androdi Studio 2.2 Preview 中的新功能 Analyze apk (這個新功能用來分析 apk 非常好用,強烈推薦各位讀者可以嘗試一下)來看看它到底包含了些什麼,一圖勝過千言:
安卓逆向_1 --- 逆向環境配置、APK 檔案結構、APK 打包流程打造年輕人的第一套安卓逆向環境!1. 逆向環境配置2. APK 檔案結構3. APK 打包流程4. APK 安裝流程虛拟機 可以看到,首先是有個 package 可選,實際上 resource.arsc 是可以包含多個 package 的資源的。 然後可以看到一個 Resource Types 的清單。這裡看到的是 drawable 的 type。 右邊顯示了有多少個 drawable 以及多少項 configurations,以及表的具體内容為 ID - Name - 各個次元的值(在這裡即是資源的路徑),通過這個,我們可以完成通過 id + 對應的 configuration 擷取對應資源的操作。
而後面要提到資源混淆的原理,就是修改這裡各個次元的值,并修改對應 res 裡面的檔案夾以及檔案名實作的。
具體其完整的資料結構比較複雜,在這裡就不展開說了,有興趣的讀者可以自行查閱資訊,甚至寫一個 parser 出來也是非常有意思的。
總結:
3. APK 打包流程
android配置建構 官方文檔
Android應用程式(APK)的編譯打包過程:https://www.cnblogs.com/sjm19910902/p/6416022.html
Android APK打包流程:https://www.cnblogs.com/xunbu7/p/7345912.html
APK打包流程:https://blog.csdn.net/loongago/article/details/89646920
apk檔案以及打包流程:https://blog.csdn.net/mysimplelove/article/details/93516904
淺述Android Apk打包流程:https://www.jianshu.com/p/d29c37dda256
Android 打包之流程:https://www.jianshu.com/p/d22f52a6a6fb
APK打包安裝過程:https://segmentfault.com/a/1190000004916563
原創]記一次APP脫殼重打包過程:https://bbs.pediy.com/thread-220151.htm
下圖的是官網對于Android編譯打包流程的介紹。
官方的介紹非常籠統,簡而言之,其大緻流程就是: 編譯–>DEX–>打包–>簽名和對齊
來一張外國大神的圖檔(注:這張圖少了簽名的步驟)
流程圖:
重點關心的是
- (1)這個過程的輸入是什麼?
- (2)這個過程的輸出是什麼?
- (3)這個過程使用了什麼工具?至于使用什麼參數,可以自己去看對應指令的幫助檔案,或者在網上搜尋,
aapt -> aidl -> javac -> dx(dex) -> apkbuilder -> jarsigner -> zipalign
步驟中提到的工具如下表:
名稱 | 功能介紹 | 在作業系統中的路徑 |
aapt | Android 資源打包工具 | ${ANDROID_SDK_HOME}/platform-tools/appt |
aidl | Android接口描述語言轉化為.java檔案的工具 ( aidl 全名 Android Interface Definition Language,即Android接口定義語言 ) | ${ANDROID_SDK_HOME}/platform-tools/aidl |
javac | Java Compiler | ${JDK_HOME}/javac或/usr/bin/javac |
dex | 轉化.class檔案為Davik VM能識别的.dex檔案 | ${ANDROID_SDK_HOME}/platform-tools/dx |
apkbuilder | 生成 apk 包 (SDK3.0 之後棄用,而使用 sdklib.jar 打包 apk) | ${ANDROID_SDK_HOME}/tools/opkbuilder |
jarsigner | .jar檔案的簽名工具 | ${JDK_HOME}/jarsigner或/usr/bin/jarsigner |
zipalign | 位元組碼對齊工具 | ${ANDROID_SDK_HOME}/tools/zipalign |
補充:apkbuilder 在 SDK3.0 之前使用 apkbuilder 去打包,在 SDK3.0 之後就棄用了,而使用 sdklib.jar 打包 apk。
下面各個工具在打包中的用法:
編譯打包步驟:
- 1. 打包資源檔案,生成R.java檔案。打包資源的工具是aapt(The Android Asset Packaing Tool)(E:\Documents\Android\sdk\build-tools\25.0.0\aapt.exe)。在這個過程中,項目中的AndroidManifest.xml檔案和布局檔案XML都會編譯,然後生成相應的R.java,另外AndroidManifest.xml會被aapt編譯成二進制。存放在APP的res目錄下的資源,該類資源在APP打包前大多會被編譯,變成二進制檔案,并會為每個該類檔案賦予一個resource id。對于該類資源的通路,應用層代碼則是通過resource id進行通路的。Android應用在編譯過程中aapt工具會對資源檔案進行編譯,并生成一個resource.arsc檔案,resource.arsc檔案相當于一個檔案索引表,記錄了很多跟資源相關的資訊。
- 2. 處理aidl檔案,生成相應的Java檔案。這一過程中使用到的工具是aidl(Android Interface Definition Language),即Android接口描述語言(E:\Documents\Android\sdk\build-tools\25.0.0\aidl.exe)。aidl工具解析接口定義檔案然後生成相應的Java代碼接口供程式調用。如果在項目沒有使用到aidl檔案,則可以跳過這一步。
- 3. 編譯項目源代碼,生成class檔案。項目中所有的Java代碼,包括R.java和.aidl檔案,都會變Java編譯器(javac)編譯成.class檔案,生成的class檔案位于工程中的bin/classes目錄下。
- 4. 轉換所有的class檔案,生成classes.dex檔案。dx工具生成可供Android系統Dalvik虛拟機執行的classes.dex檔案,該工具位于(E:\Documents\Android\sdk\build-tools\25.0.0\dx.bat)。任何第三方的libraries和.class檔案都會被轉換成.dex檔案。dx工具的主要工作是将Java位元組碼轉成成Dalvik位元組碼、壓縮常量池、消除備援資訊等。
- 5. 打包生成APK檔案。所有沒有編譯的資源,如images、assets目錄下資源(該類檔案是一些原始檔案,APP打包時并不會對其進行編譯,而是直接打包到APP中,對于這一類資源檔案的通路,應用層代碼需要通過檔案名對其進行通路);編譯過的資源和.dex檔案都會被apkbuilder工具打包到最終的.apk檔案中。打包的工具apkbuilder位于 android-sdk/tools目錄下。apkbuilder為一個腳本檔案,實際調用的是(E:\Documents\Android\sdk\tools\lib)檔案中的com.android.sdklib.build.ApkbuilderMain類。
- 6. 對APK檔案進行簽名。一旦APK檔案生成,它必須被簽名才能被安裝在裝置上。在開發過程中,主要用到的就是兩種簽名的keystore。一種是用于調試的debug.keystore,它主要用于調試,在Eclipse或者Android Studio中直接run以後跑在手機上的就是使用的debug.keystore。另一種就是用于釋出正式版本的keystore。
- 7. 對簽名後的APK檔案進行對齊處理。如果你釋出的 apk 是正式版的話,就必須對APK進行對齊處理,用到的工具是zipalign(E:\Documents\Android\sdk\build-tools\25.0.0\zipalign.exe)。對齊的主要過程是将APK包中所有的資源檔案距離檔案起始偏移為4位元組整數倍,這樣通過記憶體映射通路apk檔案時的速度會更快。對齊的作用就是減少運作時記憶體的使用。
上述流程都是Android Studio在編譯時調用各種
編譯指令
自動完成的
第一步:打包資源檔案,生成R.java檔案
編譯 R.java 類 需要用到 AndroidSDK 提供的 aapt 工具,aapt 參數衆多,以下是主要參數:
-d one or more device assets to include, separated by commas
-f force overwrite of existing files
-g specify a pixel tolerance to force images to grayscale, default 0
-j specify a jar or zip file containing classes to include
-k junk path of file(s) added
-m make package directories under location specified by -J
-u update existing packages (add new, replace older, remove deleted files)
-v verbose output
-x create extending (non-application) resource IDs
-z require localization of resource attributes marked with
localization="suggested"
-A additional directory in which to find raw asset files
-G A file to output proguard options into.
-F specify the apk file to output
-I add an existing package to base include set
-J specify where to output R.java resource constant definitions
-M specify full path to AndroidManifest.xml to include in zip
-P specify where to output public resource definitions
-S directory in which to find resources. Multiple directories will be scann
aapt 編譯 R.java 檔案具體如下:
需要進入應用程式目錄,建立一個gen目錄,沒有gen目錄,指令将會出現找不到檔案的錯誤!
指令成功執行後将會在 gen 目錄下生成成包結構的目錄樹,及 R.java 檔案。
列子:
aapt 資源編譯
- 編譯assets目錄和res/raw目錄下的資源
- 編譯res目錄下的資源檔案
- 給res目錄下的每個資源賦予一個資源ID,生成resource.arsc資源索引檔案
- 解析并編譯AndroidMainifest.xml
- 資源打包成*.ap_,資源ID常量定義自R.java
資源索引
aapt 給每一個非 assets 目錄的資源定義一個資源ID,它是一個4位元組(byte = 32bit)的數字,格式是PPTTNNNN,PP代表資源所屬的包(package),TT代表資源的類型(Type),NNNN代表這個類型下面的資源名稱(Entry ID)。
- Package ID相當于是一個命名空間,标定資源的來源。系統資源的命名空間,它的package ID等于0x01;自己的APP資源名稱空間,Package ID一般定義為0x7f。
- Type ID是指資源的類型ID。資源的類型都有animator、anim、color、drawable、layout、menu、raw、string和xml等等若幹種,每一種都會被賦予一個ID。
- Entry ID是指每一個資源在其所屬的資源類型中所出現的次序。
代碼編譯和打包
- AIDL -> 生成對應的java接口
- Javac -> 生成.class檔案
- dex-> 生成dex檔案
- APkBuilder:aapt打包好的資源、dex打包好的代碼檔案、第三方庫資源和jar檔案、native -> apk
第二步:處理AIDL檔案,生成對應的.java檔案
(當然,有很多工程沒有用到AIDL,那這個過程就可以省了)
将 .aidl 檔案生成 .java 檔案需要用到 AndroidSDK 自帶的 aidl 工具,此工具具體參數如下:
-I<DIR> search path for import statements.
-d<FILE> generate dependency file.
-p<FILE> file created by --preprocess to import.
-o<FOLDER> base output folder for generated files.
-b fail when trying to compile a parcelable.
值得注意的是:這個工具的參數與參數值之間不能有空格,Google也有對工資不滿意的工程師!
例子:
第三步:編譯Java檔案,生成對應的.class檔案
javac 指令用法如下:
其中,可能的選項包括:
-g 生成所有調試資訊
-g:none 不生成任何調試資訊
-g:{lines,vars,source} 隻生成某些調試資訊
-nowarn 不生成任何警告
-verbose 輸出有關編譯器正在執行的操作的消息
-deprecation 輸出使用已過時的 API 的源位置
-classpath <路徑> 指定查找使用者類檔案和注釋處理程式的位置
-cp <路徑> 指定查找使用者類檔案和注釋處理程式的位置
-sourcepath <路徑> 指定查找輸入源檔案的位置
-bootclasspath <路徑> 覆寫引導類檔案的位置
-extdirs <目錄> 覆寫安裝的擴充目錄的位置
-endorseddirs <目錄> 覆寫簽名的标準路徑的位置
-proc:{none,only} 控制是否執行注釋處理和/或編譯。
-processor <class1>[,<class2>,<class3>...]要運作的注釋處理程式的名稱;繞過預設的搜尋程序
-processorpath <路徑> 指定查找注釋處理程式的位置
-d <目錄> 指定存放生成的類檔案的位置
-s <目錄> 指定存放生成的源檔案的位置
-implicit:{none,class} 指定是否為隐式引用檔案生成類檔案
-encoding <編碼> 指定源檔案使用的字元編碼
-source <版本> 提供與指定版本的源相容性
-target <版本> 生成特定 VM 版本的類檔案
-version 版本資訊
-help 輸出标準選項的提要
-Akey[=value] 傳遞給注釋處理程式的選項
-X 輸出非标準選項的提要
-J<标志> 直接将 <标志> 傳遞給運作時系統
例子:
javac -encoding utf-8 -target 1.5 -bootclasspath E:\Androiddev\android-sdk-windows2.2\platforms\android-3\android.jar -d bin src\com\byread\reader\*.java gen\com\byread\reader\R.java
第四步:把.class檔案轉化成Davik VM支援的.dex檔案
将工程 bin目錄下的 class 檔案編譯成 classes.dex,Android 虛拟機隻能執行 dex 檔案。
例子:
第五步:打包生成未簽名的 .apk 檔案
- 【輸入】打包後的資源檔案、打包後類檔案(.dex檔案)、libs檔案(包括.so檔案,當然很多工程都沒有這樣的檔案,如果你不使用C/C++開發的話)
- 【輸出】未簽名的.apk檔案
- 【工具】apkbuilder工具
apkbuilder 工具用法如下:
-v Verbose.
-d Debug Mode: Includes debug files in the APK file.
-u Creates an unsigned package.
-storetype Forces the KeyStore type. If ommited the default is used.
-z Followed by the path to a zip archive.
Adds the content of the application package.
-f Followed by the path to a file.
Adds the file to the application package.
-rf Followed by the path to a source folder.
Adds the java resources found in that folder to the application
package, while keeping their path relative to the source folder.
-rj Followed by the path to a jar file or a folder containing
jar files.
Adds the java resources found in the jar file(s) to the application
package.
-nf Followed by the root folder containing native libraries to
include in the application package.
列子:
apkbuilder ${output.apk.file} -u -z ${packagedresource.file} -f ${dex.file} -rf ${source.dir} -rj ${libraries.dir}
第六步:對未簽名 .apk 檔案進行簽名
通過 jarsigner 指令用證書檔案對未簽名的 APK 檔案進行簽名
【輸入】未簽名的.apk檔案
【輸出】簽名的.apk檔案
【工具】jarsigner
用法:jarsigner [選項] jar 檔案别名
jarsigner -verify [選項] jar 檔案
[-keystore <url>] 密鑰庫位置
[-storepass <密碼>] 用于密鑰庫完整性的密碼
[-storetype <類型>] 密鑰庫類型
[-keypass <密碼>] 專用密鑰的密碼(如果不同)
[-sigfile <檔案>] .SF/.DSA 檔案的名稱
[-signedjar <檔案>] 已簽名的 JAR 檔案的名稱
[-digestalg <算法>] 摘要算法的名稱
[-sigalg <算法>] 簽名算法的名稱
[-verify] 驗證已簽名的 JAR 檔案
[-verbose] 簽名/驗證時輸出詳細資訊
[-certs] 輸出詳細資訊和驗證時顯示證書
[-tsa <url>] 時間戳機構的位置
[-tsacert <别名>] 時間戳機構的公共密鑰證書
[-altsigner <類>] 替代的簽名機制的類名
[-altsignerpath <路徑清單>] 替代的簽名機制的位置
[-internalsf] 在簽名塊内包含 .SF 檔案
[-sectionsonly] 不計算整個清單的散列
[-protected] 密鑰庫已保護驗證路徑
[-providerName <名稱>] 提供者名稱
[-providerClass <類> 加密服務提供者的名稱
[-providerArg <參數>]] ... 主類檔案和構造函數參數
隻需要按步驟生成 MANIFEST.MF, CERT.RSA,CERT.SF 并放入META-INF 檔案夾即可。
第七步:對簽名後的.apk檔案進行對齊處理
(不進行對齊處理是不能釋出到Google Market的)
【輸入】簽名後的.apk檔案
【輸出】對齊後的.apk檔案
【工具】zipalign工具
知道了這些細節之後,我們就可以實作很多我們想實作東西了,比如:自動化,我們可以使用某種腳本,像Windows下的批處理,linux下的Bash,Java下的Ant,Python、Perl這樣的腳本語言,甚至直接用Java、.net這們的強類型語言也是可以的。
以上便是APK打包的整個流程,我們再來總結一下:
- 除了assets和res/raw資源被原裝不動地打包進APK之外,其它的資源都會被編譯或者處理;
- 除了assets資源之外,其它的資源都會被賦予一個資源ID;
- 打包工具負責編譯和打包資源,編譯完成之後,會生成一個resources.arsc檔案和一個R.java,前者儲存的是一個資源索引表,後者定義了各個資源ID常量。
- 應用程式配置檔案AndroidManifest.xml同樣會被編譯成二進制的XML檔案,然後再打包到APK裡面去。
- 應用程式在運作時通過AssetManager來通路資源,或通過資源ID來通路,或通過檔案名來通路。
4. APK 安裝流程
Android中APK安裝流程解析:https://blog.csdn.net/mysimplelove/article/details/93619361
APK安裝後最終放置在了哪裡?安裝APP到底是怎樣的一個過程?如何打開并修改APK程式包?
如果使用 WinHex 打開apk檔案,從檔案頭就可以看出APK安裝包其實就是一個zip格式的壓縮包,是以我們隻需将apk檔案的字尾修改為 .zip 或 .rar ,就可以輕松的在電腦上打開并檢視apk軟體内部的檔案和資料(當然你也可以使用手機R.E管理器檢視)。
Android 安裝 apk包的五種方式:
- 1, 通過工具安裝:R.P 或 ES等管理工具,有安裝界面。
- 2,adb install 安裝,無安裝界面。
- 3,android market 線上安裝,無安裝界面。
- 4,直接 copy 到系統目錄/system/app下,無安裝界面。此目錄下的應用一般是系統自帶的系統級程式和常歸應用。
- 5,pm(android 系統自帶工具) 指令行安裝,無安裝界面。
apk 檔案在安裝到手機過程中,涉及到如下幾個目錄:
/system/framwork: 儲存的是資源型的應用程式,它們用來打包資源檔案。
/data/app-private: 儲存受DRM保護的私有應用程式。
/vendor/app: 儲存裝置廠商提供的應用程式。
/system/app ------- 系統自帶的應用安裝目錄,獲得 adb root權限才能删除
/data/app ------- 使用者程式安裝的目錄,安裝時把 apk檔案 複制到 此目錄
/data/data ------- 存放應用程式的資料
/data/dalvik-cache 将 apk 中的 dex檔案 安裝到 dalvik-cache 目錄下
(dex檔案是dalvik虛拟機的可執行檔案,其大小約為原始apk檔案大小的四分之一)
/data/system:該目錄下的packages.xml檔案,類似于Windows的系統資料庫,記錄了系統的permissions,
每個apk的name,codePath,,version,userid等資訊,這些資訊主要通過AndroidManifest.xml
檔案解析擷取,解析完apk後将更新資訊寫入這個檔案并儲存到flash,下次開機的時候直接從裡
面讀取相關資訊并添加到記憶體相關清單中。當有APK安裝、更新或者删除時會更新這個檔案。
/data/system/packages.xml /data/system/packages.list:
packages.list指定了應用的預設存儲位置/data/data/com.xxx.xxx;package.xml中包含了該應用
權限、應用包名、APK的安裝位置、版本、userID等資訊,并且兩者都有同一個userld。之是以每個
應用都要一個userId,是因為Android在系統設計上把每個應用當做Linux系統上的一個使用者對待,
這樣就可以利用已有的Linux使用者管理機制來設計Android應用,
比如應用目錄,應用權限,應用程序管理等。
安裝過程:
當我們新安裝一個應用的時候,通常系統會執行以下流程:
校驗apk包簽名 → 複制程式包到 /data/app 目錄 → 建立 /data/data/com.xxx 資料目錄 → 提取釋放lib檔案 → dexopt優化classes.dex處理後釋放到 /data/dalvik-cache 目錄
在這個過程中,Android 系統服務還會更新以下系統檔案:
- /data/system/packages.list -- 配置設定存儲APP的uid/gid,也就是使用者/所屬組
- /data/system/packages.xml -- 記錄儲存APP權限、簽名證書、安裝路徑、版本資訊等
由此可見,我們安裝好的軟體程式包被原本不動存放在 /data/app 目錄之下,資料目錄則被安放在 /data/data/pkg_name(包名) 目錄之中。而解除安裝過程則相反,進行删除相關檔案處理。
整個 apk 安裝流程:
- 複制 APK 到 /data/app 目錄 下,解壓(會放到 data/app/包名/ 目錄下面,同時 apk 中的 so 檔案 也會拷貝到此目錄下的 lib 檔案目錄中。)并掃描安裝包。而系統出廠的 apk 被放到 /system分區下,這就是沒有ROOT手機前,我們無法删除系統app的原因。( 下面 是用 MT 管理器 (需要擷取root 權限) 打開)
安卓逆向_1 --- 逆向環境配置、APK 檔案結構、APK 打包流程打造年輕人的第一套安卓逆向環境!1. 逆向環境配置2. APK 檔案結構3. APK 打包流程4. APK 安裝流程虛拟機 - 資料總管解析 APK 裡的資源檔案。
- 解析 AndroidManifest.xml(Android應用程式的解析過程就是解析這個xml檔案的過程)。解析的内容會被更新到
和/data/system/packages.xml
中,packages.list 中指名了該應用預設存儲的位置,packages.xml 中包含了該應用申請的權限、簽名和代碼所在位置等資訊,并且兩者都有一個 相同的 userId。之是以每個應用都有一個userId,是因為Android 在系統設計上把每個應用當作Linux系統上的一個使用者對待,這樣就可以利用已有的Linux上使用者管理機制來設計Android應用,比如應用目錄,應用權限,應用程序管理等。做完以上操作,就相當于應用在系統注冊了,可以被系統識别。接下來就得儲存應用的執行檔案了,根據/data/system/packages.list
中指定的packages.xml
,建立一個目錄,即在 /data/data/ 目錄 下建立對應的 應用資料目錄。apk會被命名成codePath
并拷貝到此,其中 lib 目錄用來存放 native 庫base.apk
- 然後對 dex 檔案進行優化,并儲存在 dalvik-cache目錄 下。其命名規則是 apk路徑+classes.dex。(此時應用就可以運作了,但如果每次應用運作還得去base.apk中取dex檔案,效率就太低了。為了提升效率,Android系統在應用安裝時還會做些優化操作,把所有可運作的dex檔案單獨提取放在一塊并做些優化。在Dalvik模式下,會使用dexopt把base.apk中的dex檔案優化為odex,存儲在
中,如果是ART模式,則會使用dex2oat優化成oat檔案也存儲在該目錄下,并且檔案名一樣,但檔案大小會大很多,因為ART模式會在安裝時把dex優化為機器碼,是以在ART模式下的應用運作更快,但apk安裝速度相對Dalvik模式下變慢,并且會占用更多的ROM。)/data/dalvik-cache
- 将 AndroidManifest 檔案解析出的四大元件資訊注冊到 PackageManagerService 中。
- 安裝完成後,發送廣播。
- 顯示icon圖示:應用程式經過PMS中的邏輯處理後,相當于已經注冊好了,如果想要在Android桌面上看到icon圖示,則需要Launcher将系統中已經安裝的程式展現在桌面上。
安裝圖解和過程描述:
安裝過程并沒有把資源檔案, assets目錄下檔案拷貝出來,他們還在apk包裡面呆着,是以,當應用要通路資源的時候,其實是從apk包裡讀取出來的。其過程是,首先加載apk裡的resources.arsc(這個檔案是存儲資源Id與值的映射檔案),根據資源id讀取加載相應的資源。
删除安裝過程:就是删除在上述三個目錄下建立的檔案及目錄。
總體說來就兩件事情:拷貝APK 和 解析APK,解析APK主要是解析 AndroidManifest.xml,以便獲得它的安裝資訊。在安裝的過程中還會這個應用配置設定 Linux使用者ID 和 Linux使用者組ID(以便它可以在系統中擷取合适的運作權限)。
涉及的三個程序
- PackageInstaller程序:PackageInstaller事實上是一個應用,它負責APK安裝以及解除安裝過程中與使用者的互動流程。
- SystemServer程序:該程序主要運作的是系統服務,APK的安裝、解除安裝和查詢都由PackageManagerService負責,它也是Android核心系統服務的一種,在SystemServer裡初始化系統服務的時候被啟動。
- DefaultContainerService程序:DefaultContainerService也是一個單獨的程序,它主要負責檢查和複制裝置上的檔案,APK的複制就是由DefaultContainerService來完成的。
apk 解析流程
-
Android不同類型
/system/framwork:儲存的是資源型的應用程式,它們用來打包資源檔案。
/system/app:儲存系統自帶的應用程式。
/data/app:儲存使用者安裝的應用程式。
/data/app-private:儲存受DRM保護的私有應用程式。
/vendor/app:儲存裝置廠商提供的應用程式。
-
DEX的dexopt流程
dexopt操作實際上對DEX檔案在執行前進行一些優化,但是不同的虛拟機操作有所不同。
Davlik:将dex檔案優化生成odex檔案,這個odex檔案的字尾也是dex,儲存在/data/dalvik-cache目錄下。
ART:将dex檔案翻譯生成oat檔案
如何修改 & 反編譯APK軟體包?
如果隻是修改程式包的一些圖檔/assets資源,直接在電腦上用解壓縮工具,解壓後就可以修改替換,但是重新打包後需要重新簽名,否則沒有簽名或者簽名校驗不正确的應用是無法安裝成功的。
而如果想要修改apk包中其他的已經編譯後的檔案,則需要反編譯。由于 Android 本質上就是一個 Java 虛拟機,而 classes.dex 檔案則是衆多 .class 檔案的打包集合,一般我們先要使用 dex2jar 将 classes.dex 解包為 Java jar 檔案,然後再通過 JD-GUI 将 jar 檔案的 .class 檔案反編譯為 .java 源碼。
整個反編譯dex的過程原理大緻簡單來說就是這樣,但是實際操作起來難度不小,因為很多程式都經過了混淆加密處理(比如QQ,微信等等大公司的軟體不可能讓人分分鐘反編譯破解,否則整個安卓APP世界還不亂套了...)
對于apk程式包其他的一些xml布局檔案,直接打開是亂碼怎麼辦?dex位元組碼都能反編譯成功,xml就更簡單一些了。網上有很多現成的工具,比如 AXMLPrinter2.jar ,可以直接解碼反編譯xml檔案,當然執行 .jar檔案需要在電腦上事先安裝好 JRE(Java運作環境)喲!
關于 Android 應用的反編譯這裡僅是簡單介紹一下原理和過程,明白了解一下就好。具體的方法百度一搜一大把。