更多關(guān)于Android安全的知識(shí),可前往:https://blog.csdn.net/ananas_orangey/category_11955914.html

車機(jī)滲透,博主感覺大致可分為:軟件層、系統(tǒng)層、硬件層
例如,我們測(cè)試軟件層以及系統(tǒng)層的時(shí)候,會(huì)關(guān)注一些加密算法以及該密碼或敏感數(shù)據(jù)是否加密或加密后又如何解析,它們又存放在哪個(gè)位置等等。
例如,Android設(shè)備(也可以是手機(jī),也可以是智能大屏等)解鎖屏幕時(shí)輸入的密碼,那么這個(gè)密碼存放在哪里?是否為明文存儲(chǔ)?如果是加密存儲(chǔ),那么加密算法是什么?
例如,連接一些車機(jī)WI-FI時(shí),為了安全考慮會(huì)要求輸入PIN碼才能連接成功,那么此時(shí)我們要考慮該P(yáng)IN碼輸入的密碼,那么這個(gè)密碼存放在哪里?是否為明文存儲(chǔ)?如果是加密存儲(chǔ),那么加密算法是什么?
這里以Android 里面的鎖屏為例,來(lái)對(duì)加密算法了解,以點(diǎn)蓋面
Android 設(shè)備中常見的鎖屏密碼主要有兩種:一種是手勢(shì)密碼(九宮格密碼圖);一種是輸入密碼,分為PIN密碼和復(fù)雜字符密碼,而PIN密碼就是數(shù)字密碼,比較簡(jiǎn)單;還有一種是指紋密碼
我們這里主要關(guān)注PIN碼來(lái)說(shuō)說(shuō),通過工具獲取當(dāng)前PIN輸入界面的View類,然后定位到一個(gè)鎖屏密碼工具類:LockPatternUtils.java
此處,大家可以思考一個(gè)小問題:假如有一臺(tái)智能后視鏡,智能電視機(jī)等硬件設(shè)備, 本身開啟熱點(diǎn),但需要輸入PIN碼才能接入,但當(dāng)前設(shè)備可root接入,你會(huì)怎么辦呢?是拆卸機(jī)器從串口進(jìn)行攻擊?還是adb進(jìn)入系統(tǒng)?
這里以5.1版本的源碼進(jìn)行分析,至于真機(jī)或模擬器,當(dāng)前按照自身?xiàng)l件來(lái)。
mkdir ~/bin
PATH=~/bin:$PATH
curl https://storage.googleapis.com/git-repo-downloads/repo > ~/bin/repochmod a+x ~/bin/repo
編輯 ~/bin/repo,把 REPO_URL 一行替換成下面的:
REPO_URL = 'https://gerrit-googlesource.lug.ustc.edu.cn/git-repo'

然后repo sync 一下同步

后續(xù)步驟省略,,自行查找。網(wǎng)上容易出現(xiàn)問題的是源地址錯(cuò)誤等問題。
Windows 下載Android源碼教程鏈接
模擬器博主用的是夜神模擬器(夜神默認(rèn)手機(jī)機(jī)型是三星,大家可切換一下機(jī)型方便測(cè)試):
探測(cè)一下試試是否能成功連接夜神模擬器:
adb connect 127.0.0.1:62001adb devices
adb shell
簡(jiǎn)短的Android版本歷史
Android 1.5紙杯蛋糕:2009年4月27日
Android 1.6,Donut:2009年9月15日
Android 2.0-2.1,Eclair:2009年10月26日(初始版本)
Android 2.2-2.2.3,F(xiàn)royo:2010年5月20日(初始版本)
Android 2.3-2.3.7,姜餅:2010年12月6日(初始版本)
Android 3.0-3.2.6,Honeycomb:2011年2月22日(初始版本)
Android 4.0-4.0.4,冰淇淋三明治:2011年10月18日(初始版本)
Android 4.1-4.3.1,Jelly Bean:2012年7月9日(初始版本)
Android 4.4-4.4.4,KitKat:2013年10月31日(初始版本)
Android 5.0-5.1.1,棒棒糖:2014年11月12日(初始版本)
Android 6.0-6.0.1,棉花糖:2015年10月5日(初始版本)
Android 7.0-7.1.2,牛軋?zhí)牵?016年8月22日(初始版本)
Android 8.0-8.1,奧利奧(Oreo):2017年8月21日(初始版本)
Android 9.0,Pie:八月6,2018
Android 10.0:2019年9月3日
Android 11:2020年9月8日
Android 12:2021年10月4日
博主,編譯老是出錯(cuò),最后直接下載現(xiàn)有的好了,地址如下(Android 5.1.1):Android 5.1.1源碼:https://github.com/AndroidSDKSources/android-sdk-sources-for-api-level-22
源碼下載好后,開始正式進(jìn)入正題,定位到鎖屏的java代碼,了解鎖屏界面輸入密碼的規(guī)則,此處我們使用Android-SDK 3.0.1 (這里你也可以使用最新版的,都是一樣的)中的uiautomatorviewer.bat(該工具默認(rèn)是安裝在C盤當(dāng)前用戶的/AppData/local/Android/Sdk/tools/bin目錄下)工具分析獲取當(dāng)前的鎖屏View類LockPattern,一步步追蹤,最終會(huì)跟到一個(gè)包名為com.android.internal.widget鎖屏密碼工類:LockPatternUtils.java,如下圖:
下載地址:https://developer.android.com/studio/archive?hl=zh-cn
鎖屏代碼的目錄路徑:frameworks/base/core/java/com/android/internal/widget/LockPatternView.java
如果是,下載的Github的源碼的話在文件的android\internal\widget目錄下
checkPasswordHistory的方法,這個(gè)方法就是來(lái)對(duì)比密碼是否一致的,能否成功解鎖手機(jī)的

passwordToHash方法就是輸入密碼的算法,繼續(xù)跟蹤(passwordToHash()方法):

從上面代碼的注釋中已經(jīng)告訴我們,這個(gè)View是用于繪制九宮格和手勢(shì)密碼的地方。passwordToHash 方法中的參數(shù)為用戶輸入的密碼和當(dāng)前用戶對(duì)應(yīng)的id,一般設(shè)備不會(huì)有多個(gè)用戶,所以這里的userId是默認(rèn)值0。再往下看就是加密算法了:原文密碼+設(shè)備的salt值,然后分別進(jìn)行SHA-1和Md5加密,將數(shù)據(jù)復(fù)制到一個(gè)數(shù)組中后轉(zhuǎn)換成Hex編碼進(jìn)行拼接,得到的就是最終保存到本地的加密密碼內(nèi)容。而這里最重要的是如何獲取設(shè)備對(duì)應(yīng)的salt值,這可以跟蹤代碼(getsalt()方法):

查看getsalt方法(如何獲取到設(shè)備對(duì)應(yīng)的salt值),long salt = getLong(LOCK_PASSWORD_SALT_KEY, 0, userId);,首先根據(jù)字段key為lockscreen.password_salt從某個(gè)地方獲取salt值,通過if判斷該值為0的話,就調(diào)用SecureRandom.getInstance("SHA1PRNG").nextLong()隨機(jī)生成一個(gè),然后將其保存到key為L(zhǎng)OCK_PASSWORD_SALT_KEY的那個(gè)方法,最后將salt值轉(zhuǎn)換為Hex值即可,繼續(xù)跟蹤代碼(getLong()方法):

應(yīng)該是把密碼保存起來(lái)了,繼續(xù)跟蹤代碼(getLockSettings()方法):

通過getLong()方法發(fā)現(xiàn)這個(gè)地方用了AIDL類型,通過在ServiceManager中獲取一個(gè)服務(wù)來(lái)進(jìn)行操作,那么它應(yīng)該是有相應(yīng)的Service類,這里是在包名為com.android.server.locksettings下的LockSettingsService.java類,找到這個(gè)類,查看它的getLong方法
frameworks/base/services/core/java/com /android/server /LockSettingsService.java
如果是,下載的Github的源碼的話在文件的com\android\server目錄下

到此,我們已經(jīng)可以確定該Service類是保存在數(shù)據(jù)庫(kù)中的了,而且在LockSettingsService構(gòu)造方法中存在SQLiteDatabase的字眼
PS:SQLiteDatabase代表一個(gè)數(shù)據(jù)庫(kù)對(duì)象,提供了操作數(shù)據(jù)庫(kù)的一些方法


這里調(diào)用了mStorage方法,繼續(xù)跟蹤代碼

從上圖中的mStorage = new LockSettingsStorage(context, new LockSettingsStorage.Callback() 可以看到,將輸入的密碼存放到了數(shù)據(jù)庫(kù)中,繼續(xù)跟蹤代碼:
到LockSettingsStorage方法中去看一下


數(shù)據(jù)庫(kù)名字叫做:locksettings.db,那么它保存在哪里呢?

兩個(gè)key文件,那么這個(gè)就是用來(lái)保存加密之后的手勢(shì)密碼和輸入密碼的信息到本地,下次開機(jī)解鎖就需要讀取這個(gè)文件內(nèi)容進(jìn)行密碼比對(duì)了,查看具體的存在路徑:
find -name / locksettings.db

SQLite Expert Professional 是一個(gè)專用高級(jí)可靠的工具,旨在幫助大家同時(shí)管理多個(gè)數(shù)據(jù)庫(kù),并且執(zhí)行各種數(shù)據(jù)庫(kù)語(yǔ)法。由于所有菜單功能集成到一個(gè)簡(jiǎn)約易懂的窗口中,剛?cè)腴T的人員和專業(yè)人員都能很好的掌握該工具。在主窗口中,用戶可以直接明了的查看所有已連接的數(shù)據(jù)庫(kù),并使用相關(guān)的語(yǔ)法進(jìn)行操作。左側(cè)區(qū)域?yàn)榭捎帽?,能夠進(jìn)行字段重組、外鍵、觸發(fā)器等功能,并且不會(huì)丟失任何數(shù)據(jù)庫(kù)信息。如果需要連接或者打開新的數(shù)據(jù)庫(kù),則可以通過菜單中的文件選項(xiàng)進(jìn)行操作,并為文件名或者新數(shù)據(jù)庫(kù)重新命名。除此之外,該工具還能輕松處理并糾正故障,保證數(shù)據(jù)庫(kù)不會(huì)受到外界的干擾和影響。
首先設(shè)置鎖屏密碼(模擬器中設(shè)置鎖屏密碼):

PS:
/data/data/com.android.providers.settings/databases/databasessettings.db(Android 4.0及以前)/data/system/locksettings.db(Android4.1及以后)
單獨(dú)拷貝locksettings.db 是沒數(shù)據(jù)的,如下:

應(yīng)該將locksettings.db-shm、locksettings.db-wal 一起拷貝出來(lái)
adb pull /data/system/locksettings.db
adb pull /data/system/locksettings.db-shm
adb pull /data/system/locksettings.db-wal

salt值:-2428488924405522123
還有一個(gè)加密密碼Key文件
adb pull /data/system/password.key .E03FF03CA6C923FC3D7BE13ECA1AD9E159917CD7F901431E8569A3F7F815E570E758EBD5
最終的值應(yīng)該是類似這樣的(MD5(輸入明文密碼+設(shè)備的salt).Hex+SHA1(輸入明文密碼+設(shè)備的salt).Hex就是最終的加密內(nèi)容)拼接起來(lái)就是密碼:


但我這里借出來(lái)跟原生程序不太一樣,發(fā)現(xiàn)是模擬器用的是三星的系統(tǒng),這個(gè)系統(tǒng)對(duì)鎖屏做過修改,沒有用原生程序,網(wǎng)上有代碼說(shuō)是做了1024次Sha1運(yùn)算,此處可以使用hashcat 爆破,三星做了1024次Sha1運(yùn)算代碼如下:
public byte[] passwordToHash(String paramString)
{
if (paramString == null)
return null;
String str = null;
byte[] arrayOfByte1 = null;
try
{
byte[] arrayOfByte2 = (paramString + getSalt()).getBytes();
byte[] arrayOfByte3 = null;
str = "SHA-1";
MessageDigest localMessageDigest = MessageDigest.getInstance(str);
long l1 = System.currentTimeMillis();
for (int i = 0; i < 1024; i++)
{
arrayOfByte1 = null;
if (arrayOfByte3 != null)
localMessageDigest.update(arrayOfByte3);
localMessageDigest.update(("" + i).getBytes());
localMessageDigest.update(arrayOfByte2);
arrayOfByte3 = localMessageDigest.digest();
}
arrayOfByte1 = toHex(arrayOfByte3).getBytes();
long l2 = System.currentTimeMillis();
Log.w("LockPatternUtils", "passwordToHash time = " + (l2 - l1) + "ms");
return arrayOfByte1;
}
catch (NoSuchAlgorithmException localNoSuchAlgorithmException)
{
Log.w("LockPatternUtils", "Failed to encode string because of missing algorithm: " + str);
}
return arrayOfByte1;
}
PIN或復(fù)雜密碼,因?yàn)閟alt 值是隨機(jī)的,且輸入密碼加salt后再sha1+md5拼接復(fù)雜的多,所以安全性相對(duì)九宮格密碼要安全一些
參考鏈接:
http://blog.md5.red/?p=456
http://www.520monkey.com/archives/1022