1. 程式人生 > >Janus 二元神漏洞測試

Janus 二元神漏洞測試

wallpaper 執行 2-2 發現 paper tar 作者 lock pre

技術分享圖片

同步發表於:http://blog.hacktons.cn/2017/12/25/janus-demo/

背景

12月9號,Andorid對外曝光了一個名為Janus的重量級系統漏洞CVE-2017-13156), 由安全研究公司Guard Square發現。
Janus原意是神話中的二元身,用於描述這個漏洞還真是貼切。

技術分享圖片

整個漏洞其實建立在文件校驗規則之上:

一個文件即是APK,又是DEX,在安裝APK和執行階段的校驗規則差異,導致可以在APK頭部附加一個惡意DEX來欺騙系統

下面我們從市場上隨意下載一個apk來做測試。

測試APK

本文涉及的測試APK,只用於單擊研究之用,請勿惡意散播或上傳,由此引發的糾紛與作者無關

可以從豌豆莢,應用寶等市場下一個測試用的APK,為了方便,我們需要選用一些體積較小的apk,如果apk較大很有可能經過了分包,替換工作會麻煩點。
技術分享圖片

這裏比較惡心的是,下載到的apk並不是我們選取的安裝包,而是豌豆莢市場,既然豌豆莢這麽強勢要入鏡,那麽姑且直接分析豌豆莢市場吧。

技術分享圖片

MD5 (Wandoujia_224660_web_inner_referral_binded.apk) = d3c1d9b2a74a3f8fd9fce38d38423c58

簽名檢查

首先檢查下豌豆莢的這個apk是不是v2簽名的,因為我們要測試的Janus只能在v1下驗證

檢查簽名信息可以通過*.SF來確認,根據公開信息,如果v2簽名的話,會在SF文件內寫入一個字段X-Android-APK-Signed:2


豌豆莢的SF文件名字是META-INF/DEAMON2.SF, 比較幸運啊,可以確認其使用的就是v1簽名。

aven$ unzip -l Wandoujia_224660_web_inner_referral_binded.apk |grep META-INF
   120009  12-15-17 14:38   META-INF/MANIFEST.MF
   120130  12-15-17 14:38   META-INF/DEAMON2.SF
      891  12-15-17 14:38   META-INF/DEAMON2.RSA
aven$ unzip -p Wandoujia_224660_web_inner_referral_binded.apk META-INF/DEAMON2.SF|less
Signature-Version: 1.0
SHA1-Digest-Manifest-Main-Attributes: jq/6qzaCk3O+H4OBJsDhMXm+FvE=
Created-By: 1.6.0_30 (Sun Microsystems Inc.)
SHA1-Digest-Manifest: Dts4zfEM9pZstNDahVfVh4e4jGA=

Name: res/drawable-xhdpi-v4/il.png
SHA1-Digest: QCves3Cr/wm3X2w4PR4ESXGMBOw=

Name: res/layout/dh.xml
SHA1-Digest: DCuKb0PRLuNV6jTEbSDGMTEW174=

包名確認

接下來我們需要構造一個新的dex,嫁接到豌豆莢的apk前面;這裏需要確認豌豆莢使用的包名:com.wandoujia.phoenix2

package: name='com.wandoujia.phoenix2' versionCode='16861' versionName='5.68.21'
sdkVersion:'14'
targetSdkVersion:'16'

另外值得一提的是,豌豆莢的權限還是比較流氓的會要求大量敏感權限,因此在使用該市場的時候註意權限的問題,否則很有可能裸奔了:

比如讀/寫短信,讀/寫通訊錄等等,還有一些第三方權限

uses-permission:'android.permission.READ_SMS'
uses-permission:'android.permission.RECEIVE_SMS'
uses-permission:'android.permission.MANAGE_ACCOUNTS'
uses-permission:'android.permission.AUTHENTICATE_ACCOUNTS'
uses-permission:'android.permission.USE_CREDENTIALS'
uses-permission:'android.permission.READ_SETTINGS'
uses-permission:'android.permission.READ_EXTERNAL_STORAGE'
uses-permission:'android.permission.SEND_SMS'
uses-permission:'android.permission.WRITE_EXTERNAL_STORAGE'
uses-permission:'android.permission.MOUNT_UNMOUNT_FILESYSTEMS'
uses-permission:'android.permission.INTERNET'
uses-permission:'android.permission.ACCESS_NETWORK_STATE'
uses-permission:'android.permission.ACCESS_WIFI_STATE'
uses-permission:'android.permission.CHANGE_WIFI_STATE'
uses-permission:'android.permission.CHANGE_WIFI_MULTICAST_STATE'
uses-permission:'android.permission.SET_WALLPAPER'
uses-permission:'android.permission.SET_WALLPAPER_HINTS'
uses-permission:'android.permission.WRITE_SETTINGS'
uses-permission:'android.permission.CAMERA'
uses-permission:'android.permission.FLASHLIGHT'
uses-permission:'com.android.launcher.permission.INSTALL_SHORTCUT'
uses-permission:'com.android.launcher.permission.UNINSTALL_SHORTCUT'
uses-permission:'android.permission.READ_PHONE_STATE'
uses-permission:'android.permission.MODIFY_AUDIO_SETTINGS'
uses-permission:'android.permission.SYSTEM_ALERT_WINDOW'
uses-permission:'android.permission.ACCESS_SUPPERUSER'
uses-permission:'android.permission.GET_PACKAGE_SIZE'
uses-permission:'android.permission.KILL_BACKGROUND_PROCESSES'
uses-permission:'android.permission.CLEAR_APP_CACHE'
uses-permission:'android.permission.DISABLE_KEYGUARD'
uses-permission:'com.android.launcher.permission.READ_SETTINGS'
uses-permission:'com.android.launcher.permission.WRITE_SETTINGS'
uses-permission:'com.android.launcher3.permission.READ_SETTINGS'
uses-permission:'com.android.launcher3.permission.WRITE_SETTINGS'
uses-permission:'com.meizu.flyme.launcher.permission.READ_SETTINGS'
uses-permission:'com.meizu.flyme.launcher.permission.WRITE_SETTINGS'
uses-permission:'org.adw.launcher.permission.READ_SETTINGS'
uses-permission:'org.adw.launcher.permission.WRITE_SETTINGS'
uses-permission:'com.qihoo360.launcher.permission.READ_SETTINGS'
uses-permission:'com.qihoo360.launcher.permission.WRITE_SETTINGS'
uses-permission:'com.lge.launcher.permission.READ_SETTINGS'
uses-permission:'com.lge.launcher.permission.WRITE_SETTINGS'
uses-permission:'net.qihoo.launcher.permission.READ_SETTINGS'
uses-permission:'net.qihoo.launcher.permission.WRITE_SETTINGS'
uses-permission:'org.adwfreak.launcher.permission.READ_SETTINGS'
uses-permission:'org.adwfreak.launcher.permission.WRITE_SETTINGS'
uses-permission:'com.huawei.launcher3.permission.READ_SETTINGS'
uses-permission:'com.huawei.launcher3.permission.WRITE_SETTINGS'
uses-permission:'com.fede.launcher.permission.READ_SETTINGS'
uses-permission:'com.fede.launcher.permission.WRITE_SETTINGS'
uses-permission:'com.sec.android.app.twlauncher.settings.READ_SETTINGS'
uses-permission:'com.sec.android.app.twlauncher.settings.WRITE_SETTINGS'
uses-permission:'com.anddoes.launcher.permission.READ_SETTINGS'
uses-permission:'com.anddoes.launcher.permission.WRITE_SETTINGS'
uses-permission:'com.lenovo.launcher.permission.READ_SETTINGS'
uses-permission:'com.lenovo.launcher.permission.WRITE_SETTINGS'
uses-permission:'com.google.android.launcher.permission.READ_SETTINGS'
uses-permission:'com.google.android.launcher.permission.WRITE_SETTINGS'
uses-permission:'com.oppo.launcher.permission.WRITE_SETTINGS'
uses-permission:'com.oppo.launcher.permission.READ_SETTINGS'
uses-permission:'com.yulong.android.launcher3.permission.WRITE_SETTINGS'
uses-permission:'com.yulong.android.launcher3.permission.READ_SETTINGS'
uses-permission:'com.huawei.android.launcher.permission.READ_SETTINGS'
uses-permission:'com.huawei.android.launcher.permission.WRITE_SETTINGS'
uses-permission:'com.htc.launcher.permission.READ_SETTINGS'
uses-permission:'com.htc.launcher.permission.WRITE_SETTINGS'
uses-permission:'com.bbk.launcher2.permission.READ_SETTINGS'
uses-permission:'com.bbk.launcher2.permission.WRITE_SETTINGS'
uses-permission:'android.permission.WAKE_LOCK'
uses-permission:'android.permission.BROADCAST_PACKAGE_ADDED'
uses-permission:'android.permission.BROADCAST_PACKAGE_CHANGED'
uses-permission:'android.permission.BROADCAST_PACKAGE_INSTALL'
uses-permission:'android.permission.BROADCAST_PACKAGE_REPLACED'
uses-permission:'android.permission.RESTART_PACKAGES'
uses-permission:'android.permission.GET_TASKS'
uses-permission:'android.permission.RECEIVE_BOOT_COMPLETED'
uses-permission:'android.permission.CHANGE_NETWORK_STATE'
uses-permission:'android.permission.GET_ACCOUNTS'
uses-permission:'android.permission.VIBRATE'
uses-permission:'android.permission.BIND_ACCESSIBILITY_SERVICE'
uses-permission:'android.permission.READ_CONTACTS'
uses-permission:'android.permission.WRITE_CONTACTS'
uses-permission:'android.permission.CALL_PHONE'
uses-permission:'android.permission.WRITE_SMS'
uses-permission:'android.permission.WRITE_CALL_LOG'
uses-permission:'android.permission.READ_CALL_LOG'
uses-permission:'android.permission.AUTHENTICATE_ACCOUNTS'
uses-permission:'android.permission.WRITE_SYNC_SETTINGS'
uses-permission:'android.permission.MANAGE_ACCOUNTS'
uses-permission:'android.permission.ACCESS_FINE_LOCATION'
uses-permission:'android.permission.ACCESS_COARSE_LOCATION'
uses-permission:'com.wandoujia.phoenix2.permission.MIPUSH_RECEIVE'
uses-permission:'android.permission.PACKAGE_USAGE_STATS'
uses-permission:'android.permission.PERSISTENT_ACTIVITY'
uses-permission:'android.permission.ACCESS_MTK_MMHW'

Hack

接下來開始編碼工作,明確下我們的目標:

  • 替換Application,並且在app進程啟動時彈出一個toast;
  • 替換啟動頁,顯示一個特殊文案;

因此首先安確認下豌豆莢的自定義application:com.pp.assistant.PPApplication

aven$ aapt dump xmltree Wandoujia_224660_web_inner_referral_binded.apk AndroidManifest.xml|less

    E: application (line=155)
      A: android:theme(0x01010000)=@0x7f0a0001
      A: android:label(0x01010001)=@0x7f0c038a
      A: android:icon(0x01010002)=@0x7f02009d
      A: android:name(0x01010003)="com.pp.assistant.PPApplication" (Raw: "com.pp.assistant.PPApplication")
      A: android:stateNotNeeded(0x01010016)=(type 0x12)0xffffffff
      A: android:windowSoftInputMode(0x0101022b)=(type 0x11)0x3
      A: android:allowBackup(0x01010280)=(type 0x12)0xffffffff

創建同名的PPApplication的,然後加上toast即可,接下來編譯得到新的apk,並將其中的dex抽離出來備用。

插曲

在實際插入dex的時候,遇到了一些小插曲,比如插入完後,啟動崩潰,所以如果是插入全新的dex的話,需要確認和原有dex的關系,如果完全摒棄原有邏輯,那麽需要手動補全manifest中聲明的ContentProviderBroadcastReceiver,Activity根據需要替換,Service可選替換

另外合並apk和dex不是簡單的字節疊加,需要修改最終apk的偏移量,確保zip的正確性。筆者使用的是一個Python腳本

https://github.com/V-E-O/PoC/tree/master/CVE-2017-13156

效果

搞定之後,可以直接安裝apk,也可以覆蓋升級安裝,接下來啟動app就可以看到完全不同的效果;

在這裏我們出於實驗性質,將豌豆莢市場的application和啟動Activity做了整體替換,因此直接感受就是原有邏輯全部沒有了,如果我們通過反編譯後增量修改的方式來新增dex,納悶可以實現和原app功能幾乎一致的串改,這樣可以惡意插入代碼,同時不容易被用戶發現。

技術分享圖片

修復

這個bug看起來挺嚴重的,不過實際上影響有限,如果用戶通過正規市場下載程序基本沒什麽問題,同時Android官方已經做fix,相信後續很快就會在新版本中生效。
對於開發者來說比較被動,最好升級簽名為V2,別的就沒有屏蔽辦法了,比較問題出在系統校驗上面。

Janus 二元神漏洞測試