Eacho 发表于 2018-2-27 23:59

史小坑的黑暗料理v1.0.2内购破解过程2

本帖最后由 Eacho 于 2018-2-28 00:06 编辑

初学勿喷,如果有什么错误的地方,还请指点一下
因为初学,想找一些APP练手,说来惭愧,我被https://www.52pojie.cn/thread-656493-1-1.html这个帖子里的app难住了,看了一天,都没成功破解,明天再努力努力看看能不能破解,不行我要来发帖提问了
然后这次是从这里看到的帖子https://www.52pojie.cn/thread-702259-1-1.html,我和这位楼主的想法一样,用自己学到的一些知识尝试破解,我破解完然后回过头来看他的方法(本来以为这个也破解不出来,可以参考他的方法,或者跟着他的方法去做,但是似乎不用了),思路还是不同的

0x1 预备知识
Java基础
Smali语法

0x2 准备工具
AndroidKiller/ApkIDE/IDA..等等自己挑一个,我选AndroidKiller,我感觉界面比较舒服
jadx-gui/Java Decompiler/jd-gui/jeb..等等自己挑一个,我这次选了jeb,因为都说这是神器,我就来用用看,感觉都差不多,可能我打开方式不对

0x3 望
先打开APP看看长什么样的进入商城,跟其他APP都一个样


随便点一个购买看看,弹出了支付方式选择窗口


点取消看看,toast了一个支付取消信息,那第一破解反应就是点取消执行成功的代码(APP是破解后才写的,懒得装原版的了,点取消就购买成功了,打码的地方是购买成功提示)


0x4 闻
拖到jeb里看看进去先搜字符串,像这种内购的,虽然我之前仅仅CM了两个内购,但是经验已经总结起来了,字符串直接搜"支付","Pay"基本都能应付这是搜到的字符串,往下一拖 就能看到之前的那个提示 “道具支付已取消”


双击这个关键词,进入到关键词所在代码,jeb首先跳转到的是smali里,我们右键反编译一下,就能获取到java源码
可以看到关键词所在的方法名为payCancel,里面的代码也很简单
给v1赋值提示语句 String v1 = String.valueOf("道具支付已取消") + "\nalias: " + arg6.get("toolsAlias");
点取消后看到的提示内容Toast.makeText(Telecom3Pay.this.mContext, ((CharSequence)v1), 0).show();
日志Log.i("KengSDK", v1);
最后有一个调用代码,从前面几行代码可以看到,都是跟支付取消业务逻辑没有一点关系的代码,那么总要有一个地方来处理取消支付后该怎么运行吧?所以这一行一定是支付取消后的业务逻辑
Telecom3Pay.this.mOnPayListener.onPostPay(false, Telecom3Pay.this._id);

往下翻,还可以看到payFailed和paySuccess两个方法,通过名字我们也知道这两个方法是干嘛的吧,一个支付失败,一个支付成功
我们对比一下,发现在最后都有调用Telecom3Pay.this.mOnPayListener.onPostPay(参数...)
只是参数不太一样,我们全部复制下来 就能很清楚的看到他们的参数有什么不同了
支付取消Telecom3Pay.this.mOnPayListener.onPostPay(false, Telecom3Pay.this._id);
支付失败Telecom3Pay.this.mOnPayListener.onPostPay(false, Telecom3Pay.this._id);
支付成功Telecom3Pay.this.mOnPayListener.onPostPay(true, Telecom3Pay.this._id);
很明显,未支付成功的,第一个参数都是false,所以我们只要在smali里把这个false改成true就ok了


0x5 问
把apk拖到AndroidKiller
找到关键词所在的smali文件Telecom3Pay.smali
但是好像有好几个类似的文件名

带$符号的代表是内部类,这个是java基础里的
那就算不知道这个也没关系,也就4个文件吗,一个个的打开找也可以,反正我知道也是一个个打开来找的,或者从工程搜索里搜索关键词都行,很简单就能找到payCancel方法虽然在Java里看起来只有几行代码,但是在smali还是很长的,这是整个payCanel方法代码
.method public payCancel(Ljava/util/Map;)V
    .locals 5
    .parameter
    .annotation system Ldalvik/annotation/Signature;
      value = {
            "(",
            "Ljava/util/Map",
            "<",
            "Ljava/lang/String;",
            "Ljava/lang/String;",
            ">;)V"
      }
    .end annotation

    .prologue
    .local p1, params:Ljava/util/Map;,"Ljava/util/Map<Ljava/lang/String;Ljava/lang/String;>;"
    const/4 v4, 0x0

    .line 139
    const-string v1, "\u9053\u5177\u652f\u4ed8\u5df2\u53d6\u6d88"

    .line 140
    .local v1, msg:Ljava/lang/String;
    new-instance v2, Ljava/lang/StringBuilder;

    invoke-static {v1}, Ljava/lang/String;->valueOf(Ljava/lang/Object;)Ljava/lang/String;

    move-result-object v3

    invoke-direct {v2, v3}, Ljava/lang/StringBuilder;-><init>(Ljava/lang/String;)V

    const-string v3, "\nalias: "

    invoke-virtual {v2, v3}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;

    move-result-object v3

    .line 141
    const-string v2, "toolsAlias"

    invoke-interface {p1, v2}, Ljava/util/Map;->get(Ljava/lang/Object;)Ljava/lang/Object;

    move-result-object v2

    check-cast v2, Ljava/lang/String;

    invoke-virtual {v3, v2}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;

    move-result-object v2

    .line 140
    invoke-virtual {v2}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String;

    move-result-object v1

    .line 142
    iget-object v2, p0, Lcom/ipeaksoft/pay/libpaytelecom3/Telecom3Pay$1;->this$0:Lcom/ipeaksoft/pay/libpaytelecom3/Telecom3Pay;

    #getter for: Lcom/ipeaksoft/pay/libpaytelecom3/Telecom3Pay;->mContext:Landroid/content/Context;
    invoke-static {v2}, Lcom/ipeaksoft/pay/libpaytelecom3/Telecom3Pay;->access$2(Lcom/ipeaksoft/pay/libpaytelecom3/Telecom3Pay;)Landroid/content/Context;

    move-result-object v2

    invoke-static {v2, v1, v4}, Landroid/widget/Toast;->makeText(Landroid/content/Context;Ljava/lang/CharSequence;I)Landroid/widget/Toast;

    move-result-object v2

    invoke-virtual {v2}, Landroid/widget/Toast;->show()V

    .line 143
    const-string v2, "KengSDK"

    invoke-static {v2, v1}, Landroid/util/Log;->i(Ljava/lang/String;Ljava/lang/String;)I

    .line 145
    iget-object v2, p0, Lcom/ipeaksoft/pay/libpaytelecom3/Telecom3Pay$1;->this$0:Lcom/ipeaksoft/pay/libpaytelecom3/Telecom3Pay;

    #getter for: Lcom/ipeaksoft/pay/libpaytelecom3/Telecom3Pay;->_id:I
    invoke-static {v2}, Lcom/ipeaksoft/pay/libpaytelecom3/Telecom3Pay;->access$0(Lcom/ipeaksoft/pay/libpaytelecom3/Telecom3Pay;)I

    move-result v0

    .line 146
    .local v0, id:I
    iget-object v2, p0, Lcom/ipeaksoft/pay/libpaytelecom3/Telecom3Pay$1;->this$0:Lcom/ipeaksoft/pay/libpaytelecom3/Telecom3Pay;

    #getter for: Lcom/ipeaksoft/pay/libpaytelecom3/Telecom3Pay;->mOnPayListener:Lzygame/ipk/pay/OnPayListener;
    invoke-static {v2}, Lcom/ipeaksoft/pay/libpaytelecom3/Telecom3Pay;->access$1(Lcom/ipeaksoft/pay/libpaytelecom3/Telecom3Pay;)Lzygame/ipk/pay/OnPayListener;

    move-result-object v2

    invoke-interface {v2, v4, v0}, Lzygame/ipk/pay/OnPayListener;->onPostPay(ZI)V

    .line 147
    return-void
.end method

我们到最后找到调用onPostPay的代码就好了invoke-interface {v2, v4, v0}, Lzygame/ipk/pay/OnPayListener;->onPostPay(ZI)V
到这不知道该哪个参数怎么办,没关系,我们找到paySuccess的调用代码就好了
const/4 v3, 0x1
invoke-interface {v2, v3, v0}, Lzygame/ipk/pay/OnPayListener;->onPostPay(ZI)V
可以看到唯一不同的就是v4和v3
那么在paySuccess里v3 是赋了个0x1的值,我们就回到payCancel里把他的v4赋个0x1的值
也就是在调用onPostPay前面加一个赋值代码const/4 v4, 0x1最终结果就是加一行代码就可以CM了


0x6 切
用Andriod Killer把apk回编就好了
样本文件的话,从原帖里去下https://www.52pojie.cn/thread-697256-1-1.html
破解文件的话,第一版破解的应该比我的更完美,还是下载他的吧

shijielaoren 发表于 2018-2-28 00:25

学习了,感谢分享!

亲亲宝贝A静 发表于 2018-2-28 00:46

共同学习共同进步~

挥洒灵魂 发表于 2018-2-28 10:39

谁能帮我看下我的啊,,,小弟谢谢了,,200cb,
https://www.52pojie.cn/thread-701197-1-1.html

tp5945 发表于 2018-2-28 15:00

学习。多谢楼主分享

爸爸爱你 发表于 2018-2-28 17:20

学习了。

王美君 发表于 2018-2-28 21:31

看看就好了,自己还有待进步

Eacho 发表于 2018-2-28 21:35

王美君 发表于 2018-2-28 21:31
看看就好了,自己还有待进步

会继续努力学习的

xp9477 发表于 2018-3-1 10:27

支持一下

偶来啦 发表于 2018-3-1 11:03

支持原创感谢分享
页: [1]
查看完整版本: 史小坑的黑暗料理v1.0.2内购破解过程2