初学练手:某些游戏中Google Play 许可证验证的简单去除方法
注册论坛有一段时间了,这段时间里学到了不少东西。在此献丑,发一篇简单的过程记录,希望能激发更多像我一样的新手的兴趣,引导更多人走上学习的路。
首先要感谢qtfreet00大神的安卓逆向入门教程!非常详细!传送门:https://www.52pojie.cn/thread-408645-1-1.html
前言:一些以 Google Play 为官方发布渠道的应用、游戏会在启动时通过手机上的 Google Play 框架查询当前应用是否是从Google Play商店合法购买安装的,如果不是,会拒绝运行。如Minecraft(国际版):(本方法适用但不局限于此应用)
分析:对于此类应用,一般是使用了Google Play的许可证验证API。要想去除,要先学会如何加上,让我们前往Google的Android开发文档查询一下:https://developer.android.com/google/play/licensing/overview.html (自备梯子)
这里面有一张图,演示了许可证的检查过程:
可以看出,应用先向手机上的Google Play框架提出请求,然后由Google Play向服务器进行验证(过程加密),再回复给应用。
另一张图更实用,展示了应用在验证过程中的具体操作:
由此看出,关键函数就是LicenseChecker.checkAccess()。应用会调用LicenseChecker.checkAccess(),checkAccess()方法会进行检查,如果结果是许可证有效则会调用应用给出的回调中的allow(),否则调用dontAllow(),遇到错误则调用applicationError()。由此可得出思路:修改checkAccess(),使其不管查询结果为何,都无条件调用LisenceCheckerCallback.allow()。
分析完毕,开始操作:在手机上使用MT管理器(BinMT)完成
第一步:打开安装包中的classes.dex文件
第二步:找到com.googleplay.licensing.LicenseChecker并打开,查看Smali。在Smali编辑器界面使用搜索功能,搜索checkAccess。
第三步:接下来开始分析这段代码
[Asm] 纯文本查看 复制代码 .method public declared-synchronized checkAccess(Lcom/googleplay/licensing/LicenseCheckerCallback;)V
.registers 11
.param p1, "callback" # Lcom/googleplay/licensing/LicenseCheckerCallback;
.prologue
.line 139
monitor-enter p0
:try_start_1
iget-object v1, p0, Lcom/googleplay/licensing/LicenseChecker;->mPolicy:Lcom/googleplay/licensing/Policy;
invoke-interface {v1}, Lcom/googleplay/licensing/Policy;->allowAccess()Z
move-result v1
if-eqz v1, :cond_17
.line 140
const-string v1, "LicenseChecker"
const-string v2, "Using cached license response"
invoke-static {v1, v2}, Landroid/util/Log;->i(Ljava/lang/String;Ljava/lang/String;)I
.line 141
const/16 v1, 0x100
invoke-interface {p1, v1}, Lcom/googleplay/licensing/LicenseCheckerCallback;->allow(I)V
:try_end_15
.catchall {:try_start_1 .. :try_end_15} :catchall_62
.line 174
:goto_15
monitor-exit p0
return-void
这个函数从图中第623行(行号说的都是截图中的行号)开始,开头是一些信息之类的内容。从627行开始是函数体,631行是一个try-catch异常处理块的开头,里面是可能出现异常的代码。这个块里便是我们要寻找的关键。
632到636行的代码用Java写出来就是:
bool v1 = this.mPolicy.allowAccess();
这是尝试在本地缓存中查找有没有此应用的许可证,如有就返回true,没有就返回false。
紧接着重头戏就来了,638行判断如果v1是0(即false)就跳转到:cond_17(在哪里进行联网检查许可证)否则继续执行。而继续执行便是我们希望看到的allow()。
因此我们只要不让程序跳到:cond_17就一定能通过验证。因此修改方式便是:
把638行的if-eqz v1, :cond_17改成nop(或在此也可以直接删掉)。
第四步:保存、编译、保存、签名、安装。
大功告成!
总结:对于逆向的学习,个人认为有编程基础的话学起来会容易一些、上手快一些。当然,没有也不是说就不能学会,只要认真,耐心,逆向并不难学,但是我还是觉得入门之后应当把编程知识多少补上一些,方便以后发展。
最后,这是我第一次发主题帖,哪里说的不好,请多指正!谢谢!
|