安卓逆向--简单游戏破解

(文章仅用于记录学习过程,相关破解技术仅限于研究使用,不准用于非法目的,否则后果自负)

说明

学习逆向基础之后就开始真实实战,这边我是跟着这篇文章看到逆向资源,虽然文章是17年的文章,但是毕竟是在学习吗,不要管时间勒.这里采用和文章不同的方法

使用工具

1:apltool
2: jadx
3:sublime Text2

看源码

这个apk是一个简单的切水果应用,并没有加壳,我们直接将apk拖进jadx里面去


image.png

我们打开将失败字符串转为unicode,也就是\u5931\u8d25,(ps:失败怎么来的,可以玩下游戏点下支付然后取消)我们搜索看看

image.png

我们看到这个命名,com.mydefinemmpay.tool.Mymmpay,这个明显就是一个管理支付的类,

看下后面的方法payResultFalse,这是支付失败的意思吗?我们点进去看看,这边有3个方法,分别是支付成功,支付失败,支付取消,看来我们找对了类,这个类就是管理支付的
方法名

我们接着看下哪里调用了payResultSuccees(),我们看到在当前类的doBilling方法调用了payResultSuccees,也就是同一个类下面
这边调用了
//doBilling方法
public void doBilling() {
        float totalMoney = Float.valueOf(RecordOpreate.getInstance().getData(RecordOpreate.totalMoey)).floatValue();
        Printlog("-------totalMoney--------" + totalMoney);
        Printlog("-------MessageUtil.getInstance().limitMoney--------" + MessageUtil.getInstance().limitMoney);
        WinPayResult.getInstance();
        this.payCodeMoney = WinPayResult.Tmone[payId - WinPayResult.addPayCode];
        showDebug("\u5f00\u59cb\u652f\u4ed8\uff1a;\n\u5df2\u7ecf\u6d88\u8d39\uff1a" + totalMoney + ";\n" + "\u652f\u4ed8\u4e0a\u9650\uff1a" + MessageUtil.getInstance().limitMoney + ";\n" + "\u5546\u54c1\u91d1\u989d\uff1a" + WinPayResult.Tmone[payId - WinPayResult.addPayCode] + ";\n" + "\u652f\u4ed8\u4ee3\u7801\uff1a" + this.mPaycode + ";\n");
        if (totalMoney >= MessageUtil.getInstance().limitMoney) {
            ((Activity) this.context).runOnUiThread(new Runnable() {
                public void run() {
                    MymmPay.this.payResultSuccess();
                }
            });
        } else if (this.onlineNumName.equals("EMPTY")) {
            payResultSuccess();
        } else {
            System.out.println("tianlibao" + tanLibao());
            if (!tanLibao()) {
                payResultFalse();
            } else if (MessageUtil.getInstance().free.equals("1")) {
                payResultSuccess();
            } else {
                Printlog("paysuss-----" + this.paysuss);
                Printlog("theymoney-----" + WinPayResult.Tmone[payId - WinPayResult.addPayCode]);
                String sdkKind = MessageUtil.getInstance().sdkKind;
                if (sdkKind.equals("0")) {
                    if (mgif == null) {
                        showDebug("\u9519\u8bef\uff1a\u54aa\u5495sdk\u4e3a\u7a7a");
                    } else if (getLibKind() == 0) {
                        mgif.pay();
                    } else if (getLibKind() == 1) {
                        if (this.cardKind != 0) {
                            osif.pay();
                        } else if (this.migfalseTime >= 1) {
                            osif.pay();
                        } else {
                            mgif.pay();
                        }
                    } else if (getLibKind() == 2) {
                        osif.pay();
                    }
                }
                if (sdkKind.equals("1")) {
                    if (osif == null) {
                        showDebug("\u9519\u8bef\uff1aothersdk\u4e3a\u7a7a");
                    } else if (getLibKind() == 0) {
                        osif.pay();
                    } else if (this.cardKind == 0) {
                        mgif.pay();
                    } else {
                        osif.pay();
                    }
                }
                if (sdkKind.equals("2")) {
                    if (osif2 == null) {
                        showDebug("\u9519\u8bef\uff1aother2\u4e3a\u7a7a");
                    } else {
                        osif2.pay();
                    }
                }
                if (sdkKind.equals("3")) {
                    if (osif3 == null) {
                        showDebug("\u9519\u8bef\uff1aother3sdk\u4e3a\u7a7a");
                    } else {
                        osif3.pay();
                    }
                }
                if (!sdkKind.equals("4")) {
                    return;
                }
                if (osif4 == null) {
                    showDebug("\u9519\u8bef\uff1aother4sdk\u4e3a\u7a7a");
                } else {
                    osif4.pay();
                }
            }
        }
    }

我们看下谁调用了doBilling方法,我们看到是当前类的pay方法调用了doBilling
image.png
//pay方法
public void pay() {
        if (XmlTran.getInstance().getAddDialog(payId + 1).equals("0")) {
            System.out.println("----------------------strdialog0-----------------:" + XmlTran.getInstance().getAddDialog(payId + 1));
            doBilling();
            return;
        }
        System.out.println("----------------------strdialog1-----------------:" + XmlTran.getInstance().getAddDialog(payId + 1));
        if (MessageUtil.getInstance().Um_Number.equals("1")) {
            Printlog("--------------00000000000----------------");
            new Builder(this.context).setMessage(XmlTran.getInstance().getAddDialog(payId + 1)).setPositiveButton("\u8d2d\u4e70", new OnClickListener() {
                public void onClick(DialogInterface dialog, int which) {
                    MymmPay.this.doBilling();
                }
            }).setOnKeyListener(new OnKeyListener() {
                public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {
                    if (keyCode == 4 && event.getRepeatCount() == 0) {
                        MymmPay.this.payResultFalse();
                    }
                    return false;
                }
            }).setNegativeButton("\u53d6\u6d88", new OnClickListener() {
                public void onClick(DialogInterface dialog, int which) {
                    MymmPay.this.payResultFalse();
                }
            }).show();
            return;
        }
        doBilling();
    }


整理思路

我们发现MymmPay这个是负责管理支付的,这个里面有pay(),doBilling(),payResultSucceed(),payResultFalse(),payResultCancel()等主要方法,整理下逻辑,点击支付,然后调用pay(),pay调用dobilling方法,然后返回结果
image.png

整理方法

有好几种方法

1:原文说的,将payResultFalse()内容替换成payResultSucceed的内容,这样支付失败和支付成功是一样都是成功,

2:pay->doBilling->我们看了下源码,doBillding()里面调用了payResultSucceed(),payResultCancel().payResultFalse(),这个类应该是一个判断类,我们直接把doBilling()内部直接调用payResultSuccess()方法,这样连判断都不用判断了

反编译

使用apktool命令将apk反编译,fruit文件夹,我这边的apk命名是fruit.apk,所以就生成了fruit文件夹,如果你不是叫fruit那就是其他文件名

apktool d fruit.apk
反编译结果

我们找MymmPay这个类的,这个类在com.mydefinemmpay.tool文件下面,打开fruit->smali->com->mydefinemmpay->tool下面

image.png

我们使用sublime Text打开MymmPay.smali(sublime text增加了smali语法高亮和提示的支持,需要的童鞋可以自己百度一下,这边就不说)

我们搜索下doBilling

//方法开头 修改前
.method public doBilling()V
    .locals 7
   .prologue
  //中间省略

//方法结尾
.end method

将方法中间删掉,然后将locals 修改为0,然后在增加payResultSuccess()方法的调用

///修改后
.method public doBilling()V
    .locals 0
    .prologue
    //其他的不要 只增加一条方法
    //只调用payResultSuccess()方法就可以
    invoke-virtual {v0}, Lcom/mydefinemmpay/tool/MymmPay;->payResultSuccess()V

return-void
.end method

完成

之后就保存,然后使用apktool重新打包生成apk文件,然后使用jarsigner重新签名安装就可以了

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

友情链接更多精彩内容