同步发表于:http://blog.hacktons.cn/2017/12/25/janus-demo/android
12月9号,Andorid对外曝光了一个名为Janus
的重量级系统漏洞CVE-2017-13156)
, 由安全研究公司Guard Square发现。
Janus
原意是神话中的二元身,用于描述这个漏洞还真是贴切。git
整个漏洞其实创建在文件校验规则之上:github
一个文件便是APK,又是DEX,在安装APK和执行阶段的校验规则差别,致使能够在APK头部附加一个恶意DEX来欺骗系统web
下面咱们从市场上随意下载一个apk来作测试。安全
本文涉及的测试APK,只用于单击研究之用,请勿恶意散播或上传,由此引起的纠纷与做者无关
app
能够从豌豆荚,应用宝等市场下一个测试用的APK,为了方便,咱们须要选用一些体积较小的apk,若是apk较大颇有可能通过了分包,替换工做会麻烦点。
less
这里比较恶心的是,下载到的apk并非咱们选取的安装包,而是豌豆荚市场,既然豌豆荚这么强势要入镜,那么姑且直接分析豌豆荚市场吧。ide
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签名。google
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'
接下来开始编码工做,明确下咱们的目标:
所以首先安确认下豌豆荚的自定义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中声明的ContentProvider
和BroadcastReceiver
,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,别的就没有屏蔽办法了,比较问题出在系统校验上面。