一、前言
笔者最近放暑假,又捡起了舰R这款死宅游戏。对于这类游戏,笔者当然要进行习惯性的寻找外挂和破解。不同于以往的脚本,这次找到了2个与众不同的跨平台脱机挂,一个用C#写,跨平台基于mono,一个用js写基于APICLOUD,前者毫无难度,后者(APICLOUD)值得分析学习。
二、背景介绍
“SuperWebview是APICloud官方推出的另一项重量级API生态产品,以SDK方式提供,致力于提升和改善移动设备Webview体验差的整套解决方案。APP通过嵌入SuperWebview替代系统Webview,即可在HTML5中使用APICloud平台现有的所有端API,以及包括增量更新、版本管理、数据云、推送云、统计分析、积木式模块化开发、所有已经聚合的开方平台服务等在内的云服务能力,增强用户体验,解决移动设备Webview使用过程中出现的兼容能力弱、加载速度慢、功能缺陷等任何问题,帮助开发者解决使用Webview过程中的所有痛点。
SuperWebview继承APICloud终端引擎的包括跨平台能力,模块扩展机制,生命周期管理,窗口系统,事件模型,APP级别的用户体验等在内的所有优秀能力,并且全面打通html5与android和iOS之间的交互,同步提供APICloud平台最新的API技术能力和服务,APICloud团队将保持对SuperWebview的持续更新和优化,兼容Html5的新特性,持续推出优质服务。
-----这是良心广告。”
总结来说有三点:
* 安卓原生Webview的扩展
* 结合native app 和 web app
* APICloud实现安卓框架,自己开发web
上个图,一目了然:
“全包加密
* 网页全包加密:对网页中全包的html,css,javascript代码进行加密,加密后的网友代码都是不可读的,并且不能通过常用的格式化工具恢复。代码在运行前都是加密的,在运行时进行动态解密。
* 一键加密、运行时解密 在开发过程中无需对代码做任何特殊处理,在云编译时选择代码加密即可。
* 零修改、零影响 加密后不改变代码的大小,不影响运行效率。
* 安全盒子 定义了一个安全盒子,在盒子内的代码按照加密和解密进行处理,其他代码不受影响。
* 重新定义资源标准 对保护的代码进行统一资源管理,加速资源加载,加速代码运行。”
使用SuperWebview,安卓app基本上就是框架,一般的核心代码都放在web中。最近遇到一个灰色的软件,需要利用其中的一些东西。经过大半个星期的逆向,最终确定核心代码在web里。
如图:云端加密,本地运行时解密
如图:对于一个web app来说,这就是核心代码
以上引用自看雪原贴,该贴作者采用了注入js的方法,笔者也试过,对本文样本效果并不显著。于是笔者决定直接逆向解密函数。(至少要主动调用解密函数)
三、逆向分析
1.从底向上找解密函数
发现so裸奔,令人失望,靠抄袭发家的小公司就是这样。
从RegisterNative里找到JNI注册的类 com/uzmap/pkg/uzcore/external/Enslecb 找到注册的方法
在xposed里一一hook,最后确认ohs就是关键解密函数
说实话,就是在看到这一步时,笔者决定避其锋芒(其实不难,就是懒),自底向上的寻找java层的解密函数,并且主动调用他,于是看回java层关键解密函数
此处有一校验
Binder.getCallingUid()
方法便可获取线程A的UID,然后利用UID进行权限比对,判断线程A是否有权限调用线程B的某个方法。
PS. 此处存疑,getCallingUid()为什么返回的是-1,而不是正常的UID。而且为什么这些代码需要用synchronized包起来???
继续向上一层层找调用,找到这个类中这个函数。由未被混淆的类名可知,APICLOUD用LruCache实现了所谓的SecurityRam,存放解密后的文件。
把url的hash和对应文件的byte[]放如LruCache的HashMap中
如 file:///data/user/0/com.fbtaiga.biu/widget/Content/js/common/NetHelper.js
看到这里已经没有什么问题了,可以动手实现主动调用解密函数了。因为还有部分文件不知为何hook不到,但是可以手动调用解密,这条思路到此为止。(虽仍存疑)
2.从上往下找解密函数
既然已知 加密的文件只能存放在assets下,那就可以从assets相关的安卓API下手,APICLOUD既然需要解密,孜然也是在assets相关的地方进行解密,于是笔者第一个搜索的API就是openAssetFile。
准确来说一共有两处,都在这个类中。
一看便知,后者没有重写,不是关键函数,所以我们跟进前者的每个函数仔细欣赏。
a.a负责把URI化成标准file://开头的路径
i.d获取小写后缀
i.e判断后缀,这里是对执行逻辑相关文件的解密(实际上本样本也没有对于资源文件的加解密)。
然后就分别进入了解密函数
发现有2个函数,而我们刚才只找到一个。继续跟进后才发现。
他是真的没有保护其它格式的文件啊!直接readByte了。。
在这个样本的逆向中,笔者注意到了开发者安全防护上的诸多不足:1.未加壳 2.混淆不够 3.对资源文件的保护不够。在之前的文章中都提过解决方案,不多赘述。
值得学习的是使用LruCache的资源文件加密方案,可以提进造轮子的日程里。(应该是上得了台面,进的了简历的安全开发技术点吧)