Android系統由於其開源的屬性,市場上針對開原始碼定製的ROM參差不齊,在系統層面的安全防範和易損性都不一樣,android應用市場對app的審核相對 iOS來說也比較寬泛,為很多漏洞提供了可乘之機。市場上一些主流的app雖然多少都做了一些安全防範,但由於大部分app不涉及資金安全,所以對安全的重視程度不夠。本文通過幾個題目可以讓你基本了解android中簡單的但比較經典的漏洞、以及簡單的android註冊機開發的思路。閱讀本文,你可能需要了解android逆向的基本知識和常用工具、非常簡單的java語言、smali的語法知識。本文適合android入門初學者,最基本的東西。大佬請無視!
一、簡訊欺詐漏洞Android系統有一套比較完善的安全體系,權限管理就是其中的一部分。當應用需要操作敏感數據時,需要申請相應的權限。
該系統漏洞能夠使攻擊者無需申請任何權限發送簡訊到用戶收件箱。
出現該漏洞的原因是Android系統的com.android.mms.transaction.SmsReceiverService系統服務未判斷啟動服務的調用者,攻擊者可以通過該應用發送偽裝簡訊到用戶收件箱。本漏洞實質上是一種能力的洩漏。
理解了原理以後基本上查閱一下資料基本上就很簡單了,通過查閱資料得到以下兩個是簡訊發送代碼中關鍵的兩個點:(詳細的apk源碼和apk見附件第一題)
1、構造簡訊發送代碼:2、通過這個服務發送:注意這兩個關鍵點,然後自己寫個布局文件裡面做好自己想要的布局,這裡我們用了相對布局,然後分別用了兩個EditText和TextView控制項加一個button控制項然後在Acvtivity裡面做好邏輯,傳遞這個intent就可以了。
3、完成上述代碼編譯籤名以後得到app的界面,我們可以自己構造任意號碼任意簡訊內容如下圖所示。代碼參考連結:https://github.com/thomascannon/android-sms-spoof(本人非作者)
二、籤名漏洞利用相關工具將crackme.apk反編譯得到java源碼,閱讀理解邏輯,將代碼中的邏輯修改,得到我們需要植入的程序crackme_killer.apk(這裡只是為了演示理解籤名漏洞,稍作修改改變了籤名漏洞的邏輯,使任意註冊碼都可以註冊成功)其中比較關鍵的一個點就是植入的classed.dex是在原apk的基礎上構造的惡意程序,因為漏洞的關鍵點在於,Android假設一個APK包中的文件是不會重名的。可實際上Zip格式是允許一個Zip文件包含具有相同文件命的文件。Android在安裝應用時,會抽取APK包中每個文件,進行籤名驗證。但如果碰到了相同文件名的文件,則只會校驗第二個文件,而忽略第一個文件。另外在應用運行前會釋放classes.dex到/data/dalvik-cache/目錄生成優化過的odex文件,然後再運行。這個階段如果APK裡有兩個classes.dex,就只會抽取第一個classes.dex進行優化,而忽略第二個。所以,如果我們將一個APK包中放入兩個classes.dex文件。第一個classes.dex是被我們篡改過的惡意dex文件;第二個classes.dex是原來這個APK中的classes.dex文件。那麼在籤名驗證時,就會驗證原來的classes.dex,因此通過驗證;而執行時,卻執行了被篡改過的第一個classes.dex。要注意的是植入的classes.dex需要是基於源文件篡改的apk提取的classes.dex,因為apk包裡除了這個包以外,還有其他的資源文件和一些申明的文件。實驗中碰到的最多的錯誤是安裝的時候提示 沒有證書或者成功安裝但運行失敗。下面是我最終成功的結果步驟。
1) 篡改crackme.apk反編譯修改smali文件重新生成crackme_killer.apk,抽取出其classes.dex保存改名為classes.dcx..(事實證明如果直接將篡改過的classes.dex拖進去是不可以的)
2) 用7z打開原APK包,刪除其中的classes.dex,保存退出7z。
3) 依次將classes.dcx和保存的classes.dex,通過7z塞入APK,然後保存退出7z
4) 用UltraEdit編輯修改過的APK,查找「classes.dcx」,修改為「classes.dex」(共有兩處),然後保存。
5) 終端輸入:adbinstall crackme.apk (這裡的crackme.apk是篡改過的,附件裡已經改成my_result.apk
6) 正常的沒有經過篡改的crackme.apk界面:
7) 利用上述步驟篡改過的apk包:
8) 植入crackme_killer.apk後的crackme.app安裝成功,點擊valide植入成功:
植入的crackme_killer.apk文件、crackme.app原始文件、植入後的文件my_result.apk見附件中第二題。
9) 上述是windows下利用7zip,UE成功植入的步驟。
另附linux下bash腳本(利用unzip寫進去,網上有相關的博客說明):
#!/bin/bashif [ $# != 2 ];then echo "Usage: $0 <platform.apk> <inject.apk>" ; exit1 ; fiPLATFORM="$1"INJECT="$2"if [ ! -f"$PLATFORM" ]; then echo "ERROR: $PLATFORM does not exist"; exit 1; fiif [ ! -f"$INJECT" ]; then echo "ERROR: $INJECT does not exist" ;exit 1; fimkdir tmpcd tmpunzip ../$PLATFORMcp ../$INJECT./out.apkcat >poc.py<<-EOF#!/usr/bin/pythonimport zipfileimport sysz =zipfile.ZipFile(sys.argv[1], "a")z.write(sys.argv[2])z.close()printsys.argv[2],"write succed to ",sys.argv[1]EOFchmod 777 poc.pyecho "writepoc file succeed"lsfor f in `find .-type f |sed -e "s:^\./::g" |egrep -v "(poc.py|out.apk)"` ;do aapt add -v out.apk "$f" ; if [ $? != 0 ]; then ./poc.py out.apk"$f" ; fi ; doneecho "just fordebug"ls cp out.apk../evil.apkcd ..rm -rf tmpecho "ModifiedAPK: evil.apk"
三、破解Crackme2.apk1、拿到這crackeme2.apk,分別用apktool、dex2jar,backsmali,JD-GU工具解壓、得到java源碼和smali源碼。
2 將我們需要破解的apk放到模擬器裡安裝,得到如下界面:
3 很明顯,這裡做了虛擬機檢測機制,後續會分析如何繞過這個檢測機制,但我們先把它放到真機或者更高級的android模擬器下安裝(這裡選用夜神模擬器,後面說的真機均指這個高級模擬器,模擬器是指AVD的模擬器),得到如下界面。很明顯我們的模擬器檢測機制在這個模擬器中並不起作用,這是因為AVD自帶的模擬器機制中一些deviceId是全0,後面我們開發註冊機的時候,註冊機在模擬器運行的時候可以看到區別。
4.用jd-gui打開dex2jar提取出來的jar文件,查看java源碼,閱讀代碼邏輯。或者直接用jeb工具打開apk。這裡可以選擇不同的工具如jeb、ApkIDE來查看代碼,建議根據自己平時的喜好來選擇,這個地方起初我碰到了一些坑,不同工具解析出來的代碼有一些不同。包括下面最後有個做註冊機的時候,源碼也起到了很大的作業。有些工具反編譯的時候可能會丟失掉一些關鍵信息。下面是同一段代碼兩個反編譯工具解析的結果,很顯然是不同的。
得到java源碼以後,很好閱讀。整個界面就只有一個圖片,閱讀源碼,找到對應位置,我們知道android活動的生命周期第一個是Oncreat,那我們就從這裡看起,Main中的oncreat:
5 似乎沒有找到有價值的信息,既然是一把鎖的圖片,我們搜索一下png就定位到了關鍵點:
6 、繼續閱讀下面的代碼,由於是繞過了模擬器檢測機制,直接看這裡:
7 找到這個函數:
8 都是賦值語句,這樣應該就簡單了吧,看一下對應的smali,要擅用搜索,發現最後是將v5 的值賦值給v0.最後返回v0的值。
10 那這樣就簡單了,將0x0改成0x1就可以了。
11、編譯籤名安裝,成功破解:
12、上述只是在真機環境下破解成功的,還不過癮,我們在模擬器下來試試如何繞過模擬器檢測機制,模擬器下界面是這樣:
13 在packageCom.zAWS.KeygenMe搜索相關字符串「MAC」定位源碼,這裡有兩個函數,第一個顯示是challenge1的字符串,想必下面的一個是下一個challenge的函數吧:
14 找到調用者兩個函數的地方,兩處調用了_emulator_dete函數,一處_emulator_dete1函數。
15 根據周圍的字符串函數等定位到smali源碼,修改if(main._mac_address == null)的判斷將nez改為eqz(如果不等於0改為如果等於0):
經過調試第一個if(main.mostCurrent._mywifi.ABLoadWifi(main.processBA))的邏輯並不需要修改,在我的模擬器裡面這個if也能為真,對應源碼在這裡,
這裡不需要修改,如果這裡和上述的地方一起修改了,就會跳到最下面的那個else語句,反而影響我們最後的結果。這裡開始誤導了我一段時間。
16 完成上述一處的修改後我們就來到了challenge2:
17 根據上面的源碼,我們還是直接修改if(v3== 0) 這個邏輯:
將nez改為eqz:
18 原以為應該就快成功了,結果報了下面這個空指針的錯誤。如下圖所示:
19 、上述這個地方很是煩心,沒有認真分析這個空指針,以為這條路行不通,又耽擱了一段時間,最後好好分析上述界面,發現是這裡有問題,定位到上述那個函數,猜測可能是模擬器裡面mac.address為空,引發了這個函數執行空指針,檢查接下來的代碼發現沒有用到這個參數了:
20、簡單暴力的方法,直接刪掉這句沒用的函數調用,如下圖框柱的地方
21 、終於繞過了這個模擬器檢測機制:
22 根據我們在真機中調試的方法,把0x0改成0x1就成功解鎖了。相關apk文件見附件中第三題。
通過apktool或者直接解壓解包提取classes.dex,利用dex2jar 轉換得到源碼文件。然後利用jd-gui查看源碼文件可得到算法。或者直接使用JEB工具得到源碼:
關鍵算法:
基本算法就是得到手機的id 然後利用上述算法計算得到一系列字符串和輸入的字符串進行對比,相等則註冊成功。由於本次實驗需要獲得deviceID,需要利用真機或其他高級模擬器調試。Eclipse自帶的AVD獲得的device id 始終為000000000000000。
1、通過反編譯得到的源碼,我們可以得到基本的算法,將其複製到eclipse做下修改:
2、然後用兩個空間TextView顯示下就可以了:
3、其中很重要的一個點在於註冊機要給讀的權限(這裡卡了一段時間,調試知道的)如下圖:
4、最終註冊機跑的結果為(前面為真機,右圖為AVD自帶模擬器):
5複製註冊碼到軟體註冊成功:
6 成功註冊:
註冊機apk和源碼在附件第四題裡。
相關apk及附件連結:http://pan.baidu.com/s/1geBdqUn
* 本文作者:k00k00,請勿轉載