• Android逆向-Android基础逆向7(内购干货集合)


    本文作者:MSTLab-EvilChen

    0×00 前言

    首先,本来想写NDK的,但是还是先把这个流程过一遍吧,这个流程是必不可少的。
    其次,RMB真的是一个好东西。

    导航

    由于本人为了节省时间,不想贴太多的代码,所以总结了一个导航栏目。并且在栏目中有内容的说明。帮助了解。希望一起进步。
    博客系列导航
    为了练习方便,顺便把apk进行了一个整理。
    练习传送门

    内容

    1.内购基础

    0×01 内购知识

    基本知识

    什么是内购?

    内购就是游戏内部购买。

    SDK厂商

    1.移动
    2.电信
    3.联通
    4.支付宝
    5.微信
    6.其他

    其他破解

    拇指玩
    网侠手机站
    7723
    爱吾
    7yw趣游
    软天空
    西西软件园
    葫芦侠三楼

    游戏平台

    1.某咕游戏

    0×02 经验总结

    关键点通用总结

    通用1

    最古老的方法就是搜索关键字:
    “成功“
    “失败”

    绕过通用

    switch

    (1)覆盖switch失败转为成功。
    (2)更改switch跳转
    (3)最后一种我最喜欢作用,思路最明确,使用goto进行跳转。跳转到成功即可。

    某咕游戏总结

    方法 :onResult

    移动总结

    onbillingfinish()
    dobilling()
    onresult()

    联通总结

    payCallback()
    PayResult()

    电信总结

    paySuccess()

    支付宝总结

    支付失败
    9000
    ResultStaus

    0×03 某咕游戏破解实例

    也不能说是因为篇幅问题吧,就是有点犯懒,不想截取一些简单的步骤。所以能简写就简写,这样能多分析几个实例。

    实例是我刚找的。

    原版apk:练习传送门在这里找,编号:2001

    实例分析(1)

    暂停:2018年2月12日00:34:05
    原因:吵到我爸睡觉了。

    开始时间: 2018年2月12日14:58:17

    第一步:试玩。

    自己玩

    1.png

    第二步:反编译,搜索关键字。

    1.搜索“成功”

    这里搜索到了三条数据

    2.png

    点进去之后是这样一个方法:

    .method public static d()V
        .locals 4
    
        const/4 v3, 0x1
    
        const/4 v2, 0x0
    
        sget v0, Lcom/xy/kom/d/bk;->i:I
    
        invoke-static {v0}, Lcom/xy/kom/g/p;->b(I)Z
    
        sget v0, Lcom/xy/kom/d/bk;->h:I
    
        invoke-static {v0}, Lcom/xy/kom/g/p;->c(I)Z
    
        sget-boolean v0, Lcom/xy/kom/d/bk;->G:Z
    
        if-eqz v0, :cond_4
    
        sget-object v0, Lcom/xy/kom/GameActivity;->A:Lcom/xy/kom/GameActivity;
    
        iget-object v0, v0, Lcom/xy/kom/GameActivity;->m:Lcom/xy/kom/g/p;
    
        invoke-virtual {v0}, Lcom/xy/kom/g/p;->x()Ljava/util/ArrayList;
    
        move-result-object v0
    
        invoke-static {}, Lcom/xy/kom/g/f;->l()Lcom/xy/kom/g/f;
    
        move-result-object v1
    
        invoke-virtual {v0, v1}, Ljava/util/ArrayList;->add(Ljava/lang/Object ;) Z
    
    
        :goto_0
        sget-object v0, Lcom/xy/kom/GameActivity;->A:Lcom/xy/kom/GameActivity;
    
        iget-object v0, v0, Lcom/xy/kom/GameActivity;->m:Lcom/xy/kom/g/p;
    
        invoke-virtual {v0}, Lcom/xy/kom/g/p;->t()V
    
        sget-object v0, Lcom/xy/kom/GameActivity;->A:Lcom/xy/kom/GameActivity;
    
        iget-object v0, v0, Lcom/xy/kom/GameActivity;->r:Lcom/xy/kom/d/ei;
    
        if-eqz v0, :cond_0
    
        sget-object v0, Lcom/xy/kom/GameActivity;->A:Lcom/xy/kom/GameActivity;
    
        iget-object v0, v0, Lcom/xy/kom/GameActivity;->r:Lcom/xy/kom/d/ei;
    
        invoke-virtual {v0, v2}, Lcom/xy/kom/d/ei;->a(I)V
    
        :cond_0
        sget-object v0, Lcom/xy/kom/GameActivity;->A:Lcom/xy/kom/GameActivity;
    
        const/4 v1, 0x6
    
        invoke-virtual {v0, v1}, Lcom/xy/kom/GameActivity;->a(I)V
    
        invoke-static {}, Lcom/xy/kom/d/bk;->h()V
    
        sget-object v0, Lcom/xy/kom/GameActivity;->A:Lcom/xy/kom/GameActivity;
    
        const-string v1, "u8d2du4e70u6210u529fuff01u9053u5177u5df2u53d1u653e"
    
        invoke-static {v0, v1, v2}, Landroid/widget/Toast;->makeText(Landroid/content/Context;Ljava/lang/CharSequence;I)Landroid/widget/Toast;
    
        move-result-object v0
    
        invoke-virtual {v0}, Landroid/widget/Toast;->show()V
    
        sget-object v0, Lcom/xy/kom/GameActivity;->N:Lcom/xy/kom/e/a;
    
        invoke-virtual {v0, v3}, Lcom/xy/kom/e/a;->a(I)V
    
        sput-boolean v3, Lcom/xy/kom/GameActivity;->M:Z
    
        invoke-static {}, Lcom/xy/kom/a/h;->f()I
    
        move-result v0
    
        const/16 v1, 0xd
    
        if-ne v0, v1, :cond_2
    
        sget v0, Lcom/xy/kom/GameActivity;->h:I
    
        const/4 v1, 0x2
    
        if-ne v0, v1, :cond_2
    
        sget-object v0, Lcom/xy/kom/GameActivity;->A:Lcom/xy/kom/GameActivity;
    
        iget-object v0, v0, Lcom/xy/kom/GameActivity;->m:Lcom/xy/kom/g/p;
    
        invoke-virtual {v0}, Lcom/xy/kom/g/p;->w()Ljava/util/ArrayList;
    
        move-result-object v0
    
        invoke-interface {v0}, Ljava/util/List;->size()I
    
        move-result v1
    
        sget-object v2, Lcom/xy/kom/GameActivity;->A:Lcom/xy/kom/GameActivity;
    
        iget-object v2, v2, Lcom/xy/kom/GameActivity;->m:Lcom/xy/kom/g/p;
    
        invoke-virtual {v2}, Lcom/xy/kom/g/p;->l()I
    
        move-result v2
    
        if-ne v1, v2, :cond_1
    
        sget-object v1, Lcom/xy/kom/GameActivity;->A:Lcom/xy/kom/GameActivity;
    
        iget-object v1, v1, Lcom/xy/kom/GameActivity;->r:Lcom/xy/kom/d/ei;
    
        invoke-interface {v0}, Ljava/util/List;->size()I
    
        move-result v2
    
        add-int/lit8 v2, v2, -0x1
    
        invoke-interface {v0, v2}, Ljava/util/List;->get(I)Ljava/lang/Object;
    
        move-result-object v0
    
        check-cast v0, Lcom/xy/kom/g/f;
    
        invoke-virtual {v1, v0}, Lcom/xy/kom/d/ei;->b(Lcom/xy/kom/g/f;)V
    
        :cond_1
        sget-object v0, Lcom/xy/kom/GameActivity;->A:Lcom/xy/kom/GameActivity;
    
        iget-object v0, v0, Lcom/xy/kom/GameActivity;->r:Lcom/xy/kom/d/ei;
    
        sget-object v1, Lcom/xy/kom/d/bk;->d:Lcom/xy/kom/g/f;
    
        invoke-virtual {v0, v1}, Lcom/xy/kom/d/ei;->a(Lcom/xy/kom/g/f;)V
    
        invoke-static {}, Lcom/xy/kom/d/bk;->m()V
    
        :cond_2
        sget-boolean v0, Lcom/xy/kom/d/bk;->G:Z
    
        if-nez v0, :cond_3
    
        const/4 v0, 0x0
    
        sput-object v0, Lcom/xy/kom/d/bk;->d:Lcom/xy/kom/g/f;
    
        :cond_3
        return-void
    
        :cond_4
        sget-object v0, Lcom/xy/kom/GameActivity;->A:Lcom/xy/kom/GameActivity;
    
        iget-object v0, v0, Lcom/xy/kom/GameActivity;->m:Lcom/xy/kom/g/p;
    
        invoke-virtual {v0}, Lcom/xy/kom/g/p;->x()Ljava/util/ArrayList;
    
        move-result-object v0
    
        sget-object v1, Lcom/xy/kom/d/bk;->d:Lcom/xy/kom/g/f;
    
        invoke-virtual {v0, v1}, Ljava/util/ArrayList;->add(Ljava/lang/Object  Z
    
    
        goto/16 :goto_0
    .end method

    3.png

    这里找到一个调用成功的方法。我们继续溯源查看。

    发现是一个onResult方法。

    4.png

    解决方法:
    (1)覆盖switch失败转为成功。
    (2)更改switch跳转
    (3)最后一种我最喜欢作用,思路最明确,使用goto进行跳转。跳转到成功即可。

    恩,改完之后汇编,整个游戏就破解好了。
    没什么好说的。

    测试成果。

    是成功的,懒的玩。不想发图,自己测试吧,有疑问可以找我。

    实例分析(2)

    之前没有找好,现在去找找。
    找练习的APK的时候主要注意三点。
    (1)最好是单机
    (2)选择大小的时候选小一点的,恩,反编译快。我们的目的是为了练习。
    (3)无壳,现阶段可定脱不了壳。

    找到了一个什么酷跑什么的游戏。
    三步走

    第一步 试玩

    原版apk:练习传送门在这里找,编号:2002

    拿到游戏,首先就要玩一下是不,人家怎么购买的你总要知道吧。说不定会有新的发现。

    5.png

    反编译破解

    搜索关键字“成功失败”

    6.png

    点开之后进去,发现,原来还是一个onResult。

    .method public onResult(ILjava/lang/String;Ljava/lang/Object;)V
        .locals 3
        .param p1, "paramAnonymousInt"    # I
        .param p2, "paramAnonymousString"    # Ljava/lang/String;
        .param p3, "paramAnonymousObject"    # Ljava/lang/Object;
    
        .prologue
        goto :pswitch_0
        .line 26
        packed-switch p1, :pswitch_data_0
    
        .line 37
        const-string v0, "Unity"
    
        new-instance v1, Ljava/lang/StringBuilder;
    
        const-string v2, "u8d2du4e70u9053u5177uff1a["
    
        invoke-direct {v1, v2}, Ljava/lang/StringBuilder;-><init>(Ljava/lang/String;)V
    
        invoke-virtual {v1, p2}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;
    
        move-result-object v1
    
        const-string v2, "]u53d6u6d88uff01"
    
        invoke-virtual {v1, v2}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;
    
        move-result-object v1
    
        invoke-virtual {v1}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String;
    
        move-result-object v1
    
        invoke-static {v0, v1}, Landroid/util/Log;->v(Ljava/lang/String;Ljava/lang/String;)I
    
        .line 38
        invoke-static {}, Lcom/huibang/paopao/MainActivity;->access$0()Ljava/lang/String;
    
        move-result-object v0
    
        invoke-static {}, Lcom/huibang/paopao/MainActivity;->access$1()Ljava/lang/String;
    
        move-result-object v1
    
        const-string v2, "cancel"
    
        invoke-static {v0, v1, v2}, Lcom/unity3d/player/UnityPlayer;->UnitySendMessage(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
    
        .line 41
        :goto_0
        return-void
    
        .line 29
        :pswitch_0
        const-string v0, "Unity"
    
        new-instance v1, Ljava/lang/StringBuilder;
    
        const-string v2, "u8d2du4e70u9053u5177uff1a["
    
        invoke-direct {v1, v2}, Ljava/lang/StringBuilder;-><init>(Ljava/lang/String;)V
    
        invoke-virtual {v1, p2}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;
    
        move-result-object v1
    
        const-string v2, "]  u6210u529fuff01"
    
        invoke-virtual {v1, v2}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;
    
        move-result-object v1
    
        invoke-virtual {v1}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String;
    
        move-result-object v1
    
        invoke-static {v0, v1}, Landroid/util/Log;->v(Ljava/lang/String;Ljava/lang/String;)I
    
        .line 30
        invoke-static {}, Lcom/huibang/paopao/MainActivity;->access$0()Ljava/lang/String;
    
        move-result-object v0
    
        invoke-static {}, Lcom/huibang/paopao/MainActivity;->access$1()Ljava/lang/String;
    
        move-result-object v1
    
        const-string v2, "success"
    
        invoke-static {v0, v1, v2}, Lcom/unity3d/player/UnityPlayer;->UnitySendMessage(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
    
        goto :goto_0
    
        .line 33
        :pswitch_1
        const-string v0, "Unity"
    
        new-instance v1, Ljava/lang/StringBuilder;
    
        const-string v2, "u8d2du4e70u9053u5177uff1a["
    
        invoke-direct {v1, v2}, Ljava/lang/StringBuilder;-><init>(Ljava/lang/String;)V
    
        invoke-virtual {v1, p2}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;
    
        move-result-object v1
    
        const-string v2, "] u5931u8d25uff01"
    
        invoke-virtual {v1, v2}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;
    
        move-result-object v1
    
        invoke-virtual {v1}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String;
    
        move-result-object v1
    
        invoke-static {v0, v1}, Landroid/util/Log;->v(Ljava/lang/String;Ljava/lang/String;)I
    
        .line 34
        invoke-static {}, Lcom/huibang/paopao/MainActivity;->access$0()Ljava/lang/String;
    
        move-result-object v0
    
        invoke-static {}, Lcom/huibang/paopao/MainActivity;->access$1()Ljava/lang/String;
    
        move-result-object v1
    
        const-string v2, "fail"
    
        invoke-static {v0, v1, v2}, Lcom/unity3d/player/UnityPlayer;->UnitySendMessage(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
    
        goto :goto_0
    
        .line 26
        nop
    
        :pswitch_data_0
        .packed-switch 0x1
            :pswitch_0
            :pswitch_1
        .end packed-switch
    .end method

    7.png

    咪咕整个支付流程大概就是这个样子。(我猜的)

    原本游戏(隐藏不可见)—咪咕支付接口(可见)——咪咕支付处理(不可见)——返回结果(可见)——回馈给原本游戏(不可见)

    我们搞的其实就是在返回结果上动手脚。

    测试

    测试我做了,但是截图不了,有兴趣的可以自己去做下尝试。

    总结

    咪咕游戏最明显的一个特征就是 onResult()这个方法,只要改了这个方法,那么就可以轻松搞定了。当然你也可以通过其他手段找到它的特征。不过经验是可以提高效率哒嘛。

    0×04 结束语

    说明

    这些只是对方法的一个总结,在总结的时候,可能没有时间整理实例了,但是在之后有时间或者遇到的话,那么我们就可以从这里找到方法去破解内购等。当然也包括了二次破解等说明。
    之后如果需要则进行补充。

  • 相关阅读:
    树莓派使用MJPG-Streamer实现网络监控
    树莓派USB摄像头与camera模块对比
    机器人教程
    win10开始菜单打不开怎么办 win菜单键没反应解决办法
    solr查询语法
    Substance 6 设置 watermark(水印)
    在SWING里嵌入SWT的组件
    solr 5.5.1安装并配置中文分词IKAnalyzer
    [简单]docx4j常用方法小结
    Java串口通信详解
  • 原文地址:https://www.cnblogs.com/ichunqiu/p/8485005.html
Copyright © 2020-2023  润新知