由于项目需要,对国内与国外的某网盘APP进行了研究,此篇用作记录。
由于上一次进行项目已经时隔两年,APP已经进行了n次的版本迭代了,最近突然提到结项的事情,再次调查发现国内这位升级了两个大版本。国外的更坑,版本号增加了快1倍,晕了。拿到后直接apktool竟然崩溃了(作者认为是windows字符集问题),不过测试了下发现旧版APK就能完成目标,总算有点安慰。
国内的这位整个安全信息页面算是全重做了,伴随着我的项目估计是也得重做了。而且新的要求是得做成一键式的,所以有一些需要GUI的操作或者计算机与手机配合操作的过程算是完蛋了,需要寻求可以脚本实现的新方案。这周一个耗时点就是国内那位的自校验(盗版认证)绕过。
下面主要是一些当时做的时候的记录。
MT大法好
MT管理器的一键式操作如果能给出源代码学习下就好了,虽然不太现实,但是还是要说句:bin,永远滴神。MT操作流程如下:
- 将apk使用apktool重打包
- 使用signapk签名
- 将原APK的META-INF中的.RSA或者整个文件夹拖入安装包
- MT管理器去除校验
- 可以成功绕过百度网盘的自校验(盗版验证)
- 反编译后发现使用的是ApksignaturekillerPlus,未开源
这个的原理后面会专门的进行梳理分析。大致就是从.RSA中读取出了签名信息,劫持(将自己放入Application的attachBaseContext中)PM的getPackageinfo,替换其返回值为原来APK的签名信息,从而绕过校验。
手动分析记录
(哭了,换了一天时间,分析的一团糟,还失败了)
- 通过弹窗提示,定位到两个字符串变量名
- app_check_title ->对应弹窗标题,非官方正版
- app_download_url ->对应弹窗正文,正版下载网址
- 通过这两个变量名定位到了两个弹窗
- smali_classes5/com/baidu/netdisk/ui/manager/___.smali 中的X函数
- smali_classes5/com/baidu/netdisk/ui/launch/AuthenticatorActivity.smali 中的popupAlertDialog函数
- smali_classes5/com/baidu/netdisk/ui/open/AuthenticatorActivity.smali 中的popupAlertDialog函数
- 上述三者均通过Dialog按钮绑定(setOnDismissListener)去调用killMyself终结APP进程
简单尝试
注定失败的尝试。
- 简单注释掉AlertDialog的按钮监听
- 通过注释执行对比,判断哪个针对的是APK刚安装场景,哪个是针对的安装后再次打开场景
- 注释smali_classes5/com/baidu/netdisk/ui/manager/___.smali 中的X函数中dialog的show调用
- 现象:出现盗版提示后闪退,说明无效
- 注释smali_classes5/com/baidu/netdisk/ui/manager/___.smali 中的X函数中dialog的按钮监听
- 现象:apk安装后弹出盗版提示,点击确认后可正常登入,但文件部分出现网络异常,无法操作;杀掉后台后再次登入也出现盗版提示,点击确认后卡死在空白封面
- 到这里手动修改dialog绕过弹窗的方式基本判死刑了。
- 注释smali_classes5/com/baidu/netdisk/ui/manager/___.smali 中的X函数中dialog的show调用
- 下面需要根据这个smali_classes5/com/baidu/netdisk/ui/manager/___.smali 中的X函数调用去寻找校验代码。
- 就是搜索代码Lcom/baidu/netdisk/ui/manager/___;->X
- 找到了全文总共四处
- smali_classes4/com/baidu/netdisk/ui/Navigate$1.smali中的aA(I)V
- smali_classes4/com/baidu/netdisk/ui/ReceivePushFileActivity$1.smali中的aA(I)V
- smali_classes4/com/baidu/netdisk/ui/ReceiveShareFileActivity$2.smali中的aA(I)V
- smali_classes5/com/baidu/netdisk/ui/manager/___.smali 中的注解部分
- smali_classes5/com/baidu/netdisk/ui/searchbox/plugin/SearchboxGroundActivity$3.smali中的aA(I)V
- 修改Navigate$1.smali中的aA(I)V跳转,绕过弹窗:出现闪退
- 根据上述现象,应该有一个机制,弹窗只是外在表现,内部有机制。
- 通过崩溃日志找到了可能跟证书有关的函数smali_classes12/com/baidu/bdcvf/CertVerifier.smali isValid()
- 直接修改其返回值,测试:闪退。
- 放弃手动,尝试寻找命令行工具
- 通过注释执行对比,判断哪个针对的是APK刚安装场景,哪个是针对的安装后再次打开场景
MT的activity记录挺好用
利用activity记录对比正常执行和我自己改的crash掉的执行,diff了一下。
- 通过activity记录定位签名比对位置
- 安装盗版APK
- 安装完第一次启动时activity记录为
- com.baidu.netdisk.ui.Navigate
- 之后启动时,activity记录
- com.baidu.netdisk.ui.DefaultMainActivity
- com.baidu.netdisk.ui.Navigate
- 安装完第一次启动时activity记录为
- mt绕过签名的apk
- 第一次启动时记录
- com.baidu.netdisk.ui.Navigate
- com.baidu.netdisk.ui.account.LoginRegisterActivity
- 点击登录
- com.baidu.sapi2.activity.LoginActivity
- com.baidu.netdisk.ui.NewQuickSettingsActivity
- com.baidu.netdisk.ui.MainActivity
- 之后登录时记录为
- com.baidu.netdisk.ui.DefaultMainActivity
- com.baidu.netdisk.ui.Navigate
- com.baidu.netdisk.ui.MainActivity
- 第一次启动时记录
- 是不是在com.baidu.netdisk.ui.Navigate中呢
- 好吧,失败了。
- 安装盗版APK
- 后续分析发现其通过加载libbdcvf.so库实现签名输出,具体校验代码定位未知。放弃直接定位修改签名校验代码。
注入代码
参考github方案sigkill。
- 先获取原版APK的signature(作者通过安装一个apk调用PM去获取,其实可以直接读取解析apk中的*.RSA文件来得到)
- 向Application.attachBaseContext()中注入hook PakageManager的smali代码,替换其pakageinfo.signature的返回值为原版APK的值,以绕过比对,
- 将smali代码重新打包后签名安装,成功实现绕过效果,文件等也可正常使用。
后续
后面得学习sigkill的hook部分代码。优化代码,简化操作(一键化)。先搞定项目要紧。