Android應用加固原理

Author:楊空明 Date:2019-9-10java

1、前言

Android開發者經常面臨的一個問題就是防破解、 防二次打包。現現在,安全問題愈來愈重要,愈來愈多 的Android開發者也開始尋求安全的保護方案。請看一下下面的幾張圖片:android

1.1

image

1.2

image

1.3

image

2、什麼是加殼?

移動平臺攻防技術的發展基本是沿着PC端發展軌跡在進行,從windows平臺的加殼脫殼反調試反到Andriod的平臺apk加固,反調試代碼混淆,增強殼web

加殼是在二進制的程序中植入一段代碼,在運行的時候優先取得程序的控制權,作一些額外的工做。大多數病毒就是基於此原理。PC EXE文件加殼的過程以下:算法

image

3、加殼做用和分類

做用:數據庫

加殼的程序能夠有效阻止對程序的反彙編分析,以達到它不可告人的目的。這種技術也經常使用來保護軟件版權,防止被軟件破解。windows

分類:安全

從App的加固技術來看:主流分爲dex加密和so加密,目前來看保護dex文件更爲重要,應爲dex反編譯後的java代碼可讀性更強。服務器

4、Android Dex文件加殼原理

4.1.APK文件結構

images

每一個文件及文件夾的做用以下表所示。app

文件或目錄 說明
assets文件夾 存放資源文件的目錄
lib文件夾 存放ndk編譯出來的so文件
META-INF文件夾 1. 該目錄下存放的是簽名信息,用來保證apk包的完整性和系統的安全性 2. CERT.RS 保存着該應用程序的證書和受權信息 3. CERT.SF 保存着SHA-1信息資源列表 4. MANIFEST.MF 清單信息
res文件夾 存放資源文件的目錄
AndroidManifest.xml 一個清單文件,它描述了應用的名字、版本、權限、註冊的服務等信息。
classes.dex java源碼編譯通過編譯後生成的dalvik字節碼文件,主要在Dalvik虛擬機上運行的主要代碼部分
resources.arsc 編譯後的二進制資源文件索引。

4.2DEX文件格式

4.2.1什麼是DEX文件?

他是Android系統的可執行文件,包含應用程序的所有操做指令以及運行時數據dom

因爲dalvik是一種針對嵌入式設備而特殊設計的java虛擬機,因此dex文件與標準的class文件在結構設計上有着本質的區別

當java程序編譯成class後,還須要使用dx工具將全部的class文件整合到一個dex文件,目的是其中各個類可以共享數據,在必定程度上下降了冗餘,同時也是文件結構更加經湊,實驗代表,dex文件是傳統jar文件大小的50%左右

image

4.2.2dex文件結構

Dex文件總體結構以下:

images

Dex文件總體結構說明:

數據名稱 解釋
dex_header dex文件頭部記錄整個dex文件的相關屬性
string_table 字符串數據索引,記錄了每一個字符串在數據區的偏移量
type_table 相似數據索引,記錄了每一個類型的字符串索引
proto_table 原型數據索引,記錄了方法聲明的字符串,返回類型字符串,參數列表
field_table 字段數據索引,記錄了所屬類,類型以及方法名
method_table 類方法索引,記錄方法所屬類名,方法聲明以及方法名等信息
class_def 類定義數據索引,記錄指定類各種信息,包括接口,超類,類數據偏移量
data_section 數據區,保存了各個類的真是數據

下面是DEX文件目錄:

image

這裏面,有3個成員咱們須要特別關注,這在後面加固裏會用到,它們分別是checksum、signature和fileSize。

checksum字段

checksum是校驗碼字段,佔4bytes,主要用來檢查從該字段(不包含checksum字段,也就是從12bytes開始算起)開始到文件末尾,這段數據是否完整,也就是完整性校驗。它使用alder32算法校驗。

signature字段

signature是SHA-1簽名字段,佔20bytes,做用跟checksum同樣,也是作完整性校驗。之因此有兩個完整性校驗字段,是因爲先使用checksum字段校驗能夠先快速檢查出錯的dex文件,而後才使用第二個計算量更大的校驗碼進行計算檢查。

fileSize字段

佔4bytes,保存classes.dex文件總長度。

這3個字段當咱們修改dex文件的時候,這3個字段的值是須要更新的,不然在加載到Dalvik虛擬機的時候會報錯。

爲何說咱們只須要關注這三個字段呢?

由於咱們須要將一個文件(加密以後的源Apk)寫入到Dex中,那麼咱們確定須要修改文件校驗碼(checksum).由於他是檢查文件是否有錯誤。那麼signature也是同樣,也是惟一識別文件的算法。還有就是須要修改dex文件的大小。

不過這裏還須要一個操做,就是標註一下咱們加密的Apk的大小,由於咱們在脫殼的時候,須要知道Apk的大小,才能正確的獲得Apk。那麼這個值放到哪呢?這個值直接放到文件的末尾就能夠了。

因此總結一下咱們須要作:修改Dex的三個文件頭,將源Apk的大小追加到殼dex的末尾就能夠了。

4.3APK打包流程

iamges

上圖中涉及到的工具及其做用以下:

名稱 功能介紹
aapt 打包資源文件,包括res和assets文件夾下的資源、AndroidManifest.xml文件、Android基礎類庫
aidl 將.aidl接口文件轉換成.java文件
javaComiler 編譯java文件,生成.class字節碼文件
dex 將全部的第三方libraries和.class文件轉換成Dalvik虛擬機支持的.dex文件
apkbuilder 打包生成apk文件,但未簽名
jarsigner 對未簽名的apk文件進行簽名
zipalign 對簽名後的apk文件進行對其處理

4.4加固原理

images

Dex文件總體加固原理以下:

images

在該過程當中涉及到三個對象,分別以下:

l 源程序

源程序也就是咱們的要加固的對象,這裏面主要修改的是原apk文件中的classes.dex文件和AndroidManifest.xml文件。

l 殼程序

殼程序主要用於解密通過加密了的dex文件,並加載解密後的原dex文件,並正常啓動原程序。

l 加密程序

加密程序主要是對原dex文件進行加密,加密算法能夠是簡單的異或操做、反轉、rc四、des、rsa等加密算法。

該加固過程能夠分爲以下4個階段:

(1)加密階段

(2)合成新的dex文件

(3)修改原apk文件並重打包簽名

(4)運行殼程序加載原dex文件

4.4.1 加密階段

加密階段主要是講把原apk文件中提取出來的classes.dex文件經過加密程序進行加密。加密的時候若是使用des對稱加密算法,則須要注意處理好密鑰的問題。一樣的,若是採用非對稱加密,也一樣存在公鑰保存的問題。

images

4.4.2 合成新的dex文件

這一階段主要是講上一步生成的加密的dex文件和咱們的殼dex文件合併,將加密的dex文件追加在殼dex文件後面,並在文件末尾追加加密dex文件的大小數值

images

在殼程序裏面,有個重要的類:ProxyApplication類,該類繼承Application類,也是應用程序最早運行的類。因此,咱們就是在這個類裏面,在原程序運行以前,進行一些解密dex文件和加載原dex文件的操做。

4.4.3 修改原apk文件並重打包簽名

在這一階段,咱們首先將apk解壓,會看到以下圖的6個文件和目錄。其中,咱們須要修改的只有2個文件,分別是classes.dex和AndroidManifest.xml文件,其餘文件和文件加都不須要改動。

首先,咱們把解壓後apk目錄下原來的classes.dex文件替換成咱們在0x02上一步合成的新的classes.dex文件。而後,因爲咱們程序運行的時候,首先加載的實際上是殼程序裏的ProxyApplication類。因此,咱們須要修改AndroidManifest.xml文件,指定application爲ProxyApplication,這樣才能正常找到識別ProxyApplication類並運行殼程序。

images

4.4.4運行殼程序加載原dex文件

Dalvik虛擬機會加載咱們通過修改的新的classes.dex文件,並最早運行ProxyApplication類。在這個類裏面,有2個關鍵的方法:attachBaseContext和onCreate方法。ProxyApplication顯示運行attachBaseContext再運行onCreate方法。

在attachBaseContext方法裏,主要作兩個工做:

  1. 讀取classes.dex文件末尾記錄加密dex文件大小的數值,則加密dex文件在新classes.dex文件中的位置爲:len(新classes.dex文件) – len(加密dex文件大小)。而後將加密的dex文件讀取出來,解密並保存到資源目錄下

  2. 而後使用自定義的DexClassLoader加載解密後的原dex文件

在onCreate方法中,主要作兩個工做:

  1. 經過反射修改ActivityThread類,並將Application指向原dex文件中的Application

  2. 建立原Application對象,並調用原Application的onCreate方法啓動原程序

images

5、加殼及脫殼代碼實現

5.一、加殼程序項目:

images

5.二、核心代碼

images

6、常見加固平臺

梆梆加固,愛加密,360加固,騰訊加固

市面上常見的加固工具加固以後,他會把你的dex,so 加密存在apk中,而後運行過程會先運行殼的代碼,殼的代碼再把原來的這個dex、so 解出來加載,不一樣的廠商有本身的方案,略有差距,但目前多數都是這個思路.

7、App加固的利弊

正面:

1.保護本身核心代碼算法,提升破解/盜版/二次打包的難度

2.緩解代碼注入/動態調試/內存注入攻擊

負面:

1.影響兼容性

2.影響程序運行效率.

3.部分流氓、病毒也會使用加殼技術來保護本身

4.部分應用市場會拒絕加殼後的應用上架

8、App安全將來展望

images

一款app的流水線,從開發到內測到平臺到消費者再到破解者再到平臺再到消費者,因此每個環節都不可輕視!!!

9、App安全總結

風險名稱 風險 解決方案
1.App防止反編譯 被反編譯的暴露客戶端邏輯,加密算法,密鑰,等等 加固
2.java層代碼源代碼反編譯風險 被反編譯的暴露客戶端邏輯,加密算法,密鑰,等等 加固 ,混淆
3.so文件破解風險 致使核心代碼泄漏。 so文件加固
4.篡改和二次打包風險 修改文件資源等,二次打包的添加病毒,廣告,或者竊取支付密碼,攔截短信等 資源文件混淆和校驗簽名的hash值
5.資源文件泄露風險 獲取圖片,js文件等文件,經過植入病毒,釣魚頁面獲取用戶敏感信息 資源混淆,加固等等
6.應用簽名未交驗風險 反編譯或者二次打包,添加病毒代碼,惡意代碼,上傳盜版App 對App進行簽名證書校驗
7.代碼爲混淆風險 業務邏輯暴露,加密算法,帳號信息等等。 混淆(中文混淆)
8.webview明文存儲密碼風險 用戶使用webview默認存儲密碼到databases/webview.db root的手機能夠產看webview數據庫,獲取用戶敏感信息 關閉wenview存儲密碼功能
9.明文數字證書風險 APK使用的數字證書用來校驗服務器的合法性,保證數據的保密性和完成性 明文存儲的證書被篡改形成數據被獲取等 客戶端校驗服務器域名和數字證書等
10.調試日誌函數調用風險 日誌信息裏面含有用戶敏感信息等 關閉調試日誌函數,刪除打印的日誌信息
11.AES/DES加密方法不安全使用風險 在使用AES/DES加密使用了ECB或者OFB工做模式,加密數據被選擇明文攻擊破解等 使用CBC和CFB工做模式等
12.RSA加密算法不安全風險 密數據被選擇明文攻擊破解和中間人攻擊等致使用戶敏感信息泄露 密碼不要過短,使用正確的工做模式
13.密鑰硬編碼風險 用戶使用加密算法的密鑰設置成一個固定值致使密鑰泄漏 動態生成加密密鑰或者將密鑰進程分段存儲等
14.動態調試攻擊風險 攻擊者使用GDB,IDA調試追蹤目標程序,獲取用戶敏感信息等 在so文件裏面實現對調試進程的監聽
15.應用數據任意備份風險 AndroidMainfest中allowBackup=true 攻擊者可使用adb命令對APP應用數據進行備份形成用戶數據泄露 allowBackup=false
16.全局可讀寫內部文件風險。 實現不一樣軟件之間數據共享,設置內部文件全局可讀寫形成其餘應用也能夠讀取或者修改文件等 (1).使用MODE_PRIVATE模式建立內部存儲文件(2).加密存儲敏感數據3.避免在文件中存儲明文和敏感信息
17.SharedPrefs全局可讀寫內部文件風險。 被其餘應用讀取或者修改文件等 使用正確的權限
18.Internal Storage數據全局可讀寫風險 當設置MODE_WORLD_READBLE或者設置android:sharedUserId致使敏感信息被其餘應用程序讀取等 設置正確的模式等
19.getDir數據全局可讀寫風險 當設置MODE_WORLD_READBLE或者設置android:sharedUserId致使敏感信息被其餘應用程序讀取等 設置正確的模式等
20.java層動態調試風險 AndroidManifest中調試的標記可使用jdb進行調試,竊取用戶敏感信息。 android:debuggable=「false」
21.內網測試信息殘留風險 經過測試的Url,測試帳號等對正式服務器進行攻擊等 講測試內網的日誌清除,或者測試服務器和生產服務器不要使用同一個
22.隨機數不安全使用風險 在使用SecureRandom類來生成隨機數,其實並非隨機,致使使用的隨機數和加密算法被破解。 (1)不使用setSeed方法(2)使用/dev/urandom或者/dev/random來初始化僞隨機數生成器
23.Http傳輸數據風險 未加密的數據被第三方獲取,形成數據泄露 使用Hpps
24.Htpps未校驗服務器證書風險,Https未校驗主機名風險,Https容許任意主機名風險 客戶端沒有對服務器進行身份完整性校驗,形成中間人攻擊 (1).在X509TrustManager中的checkServerTrusted方法對服務器進行校驗(2).判斷證書是否過時(3).使用HostnameVerifier類檢查證書中的主機名與使用證書的主機名是否一致
25.webview繞過證書校驗風險 webview使用https協議加密的url沒有校驗服務器致使中間人攻擊 校驗服務器證書時候正確
26.界面劫持風險 用戶輸入密碼的時候被一個假冒的頁面遮擋獲取用戶信息等 (1).使用第三方專業防界面劫持SDK(2).校驗當前是不是本身的頁面
27.輸入監聽風險 用戶輸入的信息被監聽或者按鍵位置被監聽形成用戶信息泄露等 自定義鍵盤
28.截屏攻擊風險 對APP運行中的界面進行截圖或者錄製來獲取用戶信息 添加屬性getWindow().setFlags(FLAG_SECURE)不讓用戶截圖和錄屏
29.動態註冊Receiver風險 當動態註冊Receiver默認生命週期是能夠導出的能夠被任意應用訪問 使用帶權限檢驗的registerReceiver API進行動態廣播的註冊
30.Content Provider數據泄露風險 權限設置不當致使用戶信息 正確的使用權限
31.Service ,Activity,Broadcast,content provider組件導出風險 Activity被第三方應用訪問致使被任意應用惡意調用 自定義權限
32.PendingIntent錯誤使用Intent風險 使用PendingIntent的時候,若是使用了一個空Intent,會致使惡意用戶劫持修改Intent的內容 禁止使用一個空Intent去構造PendingIntent
33.Intent組件隱式調用風險 使用隱式Intent沒有對接收端進行限制致使敏感信息被劫持 1.對接收端進行限制 2.建議使用顯示調用方式發送Intent
34.Intent Scheme URL攻擊風險 webview惡意調用App 對Intent作安全限制
35.Fragment注入攻擊風險 出的PreferenceActivity的子類中,沒有加入isValidFragment方法,進行fragment名的合法性校驗,攻擊者可能會繞過限制,訪問未受權的界面 (1).若是應用的Activity組件沒必要要導出,或者組件配置了intent filter標籤,建議顯示設置組件的「android:exported」屬性爲false(2).重寫isValidFragment方法,驗證fragment來源的正確性
36.webview遠程代碼執行風險 風險:WebView.addJavascriptInterface方法註冊可供JavaScript調用的Java對象,經過反射調用其餘java類等 建議不使用addJavascriptInterface接口,對於Android API Level爲17或者以上的Android系統,Google規定容許被調用的函數,必須在Java的遠程方法上面聲明一個@JavascriptInterface註解
37.zip文件解壓目錄遍歷風險 Java代碼在解壓ZIP文件時,會使用到ZipEntry類的getName()方法,若是ZIP文件中包含「../」的字符串,該方法返回值裏面原樣返回,若是沒有過濾掉getName()返回值中的「../」字符串,繼續解壓縮操做,就會在其餘目錄中建立解壓的文件 (1). 對重要的ZIP壓縮包文件進行數字簽名校驗,校驗經過才進行解壓。 (2). 檢查Zip壓縮包中使用ZipEntry.getName()獲取的文件名中是否包含」../」或者」..」,檢查」../」的時候沒必要進行URI Decode(以防經過URI編碼」..%2F」來進行繞過),測試發現ZipEntry.getName()對於Zip包中有「..%2F」的文件路徑不會進行處理。
38.Root設備運行風險 已經root的手機經過獲取應用的敏感信息等 檢測是不是root的手機禁止應用啓動
39.模擬器運行風險 刷單,模擬虛擬位置等 禁止在虛擬器上運行
40.從sdcard加載Dex和so風險 未對Dex和So文件進行安全,完整性及校驗,致使被替換,形成用戶敏感信息泄露 (1).放在APP的私有目錄 (2).對文件進行完成性校驗。

##10、參考

從源碼到apk

Dex文件格式詳解

淺談安卓app加固那點事

Android APK加殼技術方案【1】

Android APK加殼技術方案【2】

ANDROID原理解密之APK生成過程

Android簽名機制之—簽名驗證過程詳解

相關文章
相關標籤/搜索