IT博客汇
  • 首页
  • 精华
  • 技术
  • 设计
  • 资讯
  • 扯淡
  • 权利声明
  • 登录 注册

    "**游"强制更新破解

    凸一_一凸发表于 2016-06-22 23:31:33
    love 0

    好久没有更新博客了,因为一些特操蛋的事情,一直没有心思写。上两周终于把《Android 软件安全与逆向分析》 看完了,然后就老是想找个 apk 练练手,但是水平太差,稍微加密就啃不动了。刚好遇到了这个 apk 习惯性逆向分析。

    传送门:"**游"强制更新破解

    0x00 前言

    前几天客户有提到一个作弊工具,所以就想下载体验一下。结果下载的应该是一个较早的版本需要强制更新到最新版本,不然不能运行。
    更新提示:
    1.png
    所以就想破解一下他的强制更新练练手,因为感觉不难。

    0x01 分析Java代码

    利用 jadx-gui 反编译 apk,jadx-gui 这个工具还是挺好用的。一条命令就可以看到反编译后的 Java 代码,还有资源文件。

    AndroidManifest.xml分析

    Application 是 Android 程序的主入口,也是分析 apk 的开始点。而且通过运行程序也可以发现。跳出的升级的 Dialog 是在程序运行后第二个页面跳出的,第一个页面为启动页面。所以重点分析对象就是 Application 到第二个页面。
    AndroidManifest 查找 application 标签看有没有自定义 Application
    2.png

    过滤 android.intent.action.MAIN 查找第一个页面。
    3.png

    Activity分析

    自定义的 Application 中没有什么信息,只是做了一些配置的初始化和第三方 SDK 初始化的。

    SplashActivity

    SplashActivity 是 apk 的第一个页面也就是启动页面,因为代码没有做混淆处理,其中我们还是可以发现一些关键的代码。
    4.png
    5.png
    变量 isUpdate 是关键点,也可以发现这个页面停了100ms后会跳转到 MainActivity 页面。但是这个页面只是对变量 isUpdate 进行了判断赋值没有进行升级的处理。

    MainActivity

    MainActivity 真正的主页面,查看 onCreate方法。
    6.png
    当时只看到了第二个标注的代码,心想这不是改下 if-else 的事吗。(下面会将第一个标注)

    0x02 修改Smali代码

    apktool 反编译 APK,没有做过加固处理直接。定位到 MainActivity.onCreate 方法,修改if-else逻辑,将if-eqz v3, :cond_3改为以下代码:
    7.png
    原本为 isUpdate 为 true时,执行 isUpdateAlert() 方法。改为 false时执行。 顺便还加了一个 Log,回编安装运行。
    8.png
    结果发现自己还是太年轻,没有绕过升级。虽然Log是有打印了,证明代码是没有问题的,但是在升级的 Dialog 还是出现了,并且之前还有一个 Dialog。
    9.png
    那天研究太晚了就睡觉去了。

    0x03 重新分析代码逻辑

    第二天想想肯定是自己哪里分析错了,又重新看了一遍代码。首先看下之前认为是改变逻辑后执行的函数 isUpdateAlert():
    10.png
    可以看到当用户点击确定的时候只改变了 SplashActivity.isUpdate 的值,没有其他操作了。再查找一下 R.string.str_reminder 的值在目录 res/values-zh/strings.xml:
    11.png
    好吧事实证明自己还太年轻啊。

    分析变量 isUpdate 的作用

    所以可以先回到 SplashActivity 看看变量是怎么赋值的。
    12.png
    可以看到 isUpate 的值是根据 Initialized 文件中保存的值跟当前APK的版本做比较得到的值。
    13.png
    方法 setInitFlag 则是将当前版本写入 Initialized。这样看来貌似 isUpdate 不可能为 true了。 再看下什么地方调用了这两个函数:
    14.png
    到这里可以明白了,Initialized 文件是写入当前版本号,但是当apk更新后版本号变了,跟 Initialized 中的版本号就不一样了。所以 isUpdate 记录的是当前 APK 是不是已经更新过了并且第一次打开,而不是当前 APK 是不是需要更新。

    0x04 burp抓包分析

    通过重新分析可以断定之前的修改是错误的了,但是既然 APK 需要判断是否需要更新那么就必须有网络请求,burp 该上场了,挂上代理打开APK:
    15.png
    这里请求成功的只有三个 HTTP 请求(百度地图的忽略),HTTP 还省了导入证书了。一个一个分析请求的 response 。抓包这个技能还是必须掌握的:
    16.png
    知道了哪个接口调用的那就简单了,直接找出这个接口的类:
    17.png
    用的友盟的更新模块,所以我上面忽略的才是真正的更新代码。

    UmengUpdateAgent.setUpdateOnlyWifi(false);
    UmengUpdateAgent.forceUpdate(this);

    再看 com.umeng.update.UpdateResponse 这个类的 a(JSONObject) 方法:
    18.png
    对比返回的 response (burp复制出来中文乱码了,看key就好)

    {
      "update": "Yes",
      "version": "12.1.2",
      "path": "http://au.apk.umeng.com/uploads/apps/5386ea3b6c738f0de0000025/_umeng_%40_188_%40_09e2ea839754f61d4fb24ddb96a638bf.apk",
      "origin": "",
      "update_log": "天下游12.1.2\r\n1.修复小米5不能使用的问题\r\n2.降低电量消耗、提高稳定性和兼容性\r\n3.更新会清除12.0以前版本数据\r\n4.更新完成后请重启手机,以使更新生效!!!\r\n5.如遇到不能使用的情况,请到“问题反馈”中描述问题并留下您的联系方式",
      "proto_ver": "1.4",
      "delta": false,
      "new_md5": "09e2ea839754f61d4fb24ddb96a638bf",
      "size": "18278969",
      "patch_md5": "",
      "target_size": "18278969",
      "display_ads": false
    }

    所以这个类就是处理返回值的地方了。这不是修改一下 Yes字符串就完了,哈哈哈哈哈哈。

    0x05 再次修改Smali

    添加了Log 将 Yes 改为 No:

    19.png

    回编 安装 运行,终于不再提示更新了。。。。。。。

    0x06 总结

    逆向分析真是一个细致活啊,稍微有点忽略就走了弯路。另外对于 release 的版本的APK 最好可以进行 proguard 混淆和加固,现在有很多第三方加固都提供免费的服务了,做了这两步我想就能挡住很多像我这样的菜鸟了。
    很久没更新博客,这篇也写了好几天才写好。。。。。。。。。



沪ICP备19023445号-2号
友情链接