Android逆向實例筆記—手遊中的內購破解(火柴人聯盟最新版1.9.2 BB彈 )

最近學到了一些內購的破解方式,就來試試手。然後找個了比較火爆的遊戲BB彈,找個個沒殼的就來練習。

這些東西都是大神寫爛了的東西了,我這裏只是寫出我自己找不到方法的時候的思路。勿笑。


一、BB彈

BB彈的話比較簡單,我們首先弄到模擬器上看看是什麼支付。



我們發現支付寶和話費都可以。

那說明我們有很多種方法去破解內購了。我們的目的就是取消就爲購買!


我們先用支付寶的




該圖爲引用的。


我們直接搜索0x1771




把它改爲0x1771 -> :sswitch_0  就行了。


然後再來試試話費的,我們直接所搜索paysuccess




分別點進去看看


.class public interface abstract Lcn/egame/terminal/paysdk/EgamePayListener;
.super Ljava/lang/Object;
.source "EgamePayListener.java"


# virtual methods
.method public abstract payCancel(Ljava/util/Map;)V
    .annotation system Ldalvik/annotation/Signature;
        value = {
            "(",
            "Ljava/util/Map",
            "<",
            "Ljava/lang/String;",
            "Ljava/lang/String;",
            ">;)V"
        }
    .end annotation
.end method

.method public abstract payFailed(Ljava/util/Map;I)V
    .annotation system Ldalvik/annotation/Signature;
        value = {
            "(",
            "Ljava/util/Map",
            "<",
            "Ljava/lang/String;",
            "Ljava/lang/String;",
            ">;I)V"
        }
    .end annotation
.end method

.method public abstract paySuccess(Ljava/util/Map;)V
    .annotation system Ldalvik/annotation/Signature;
        value = {
            "(",
            "Ljava/util/Map",
            "<",
            "Ljava/lang/String;",
            "Ljava/lang/String;",
            ">;)V"
        }
    .end annotation
.end method

顯然看不出太多的信息

第二處


.class Lcom/zplay/bbtan/plug/EgamePlug$2$1;
.super Ljava/lang/Object;
.source "EgamePlug.java"

# interfaces
.implements Lcn/egame/terminal/paysdk/EgamePayListener;


# annotations
.annotation system Ldalvik/annotation/EnclosingMethod;
    value = Lcom/zplay/bbtan/plug/EgamePlug$2;->run()V
.end annotation

.annotation system Ldalvik/annotation/InnerClass;
    accessFlags = 0x0
    name = null
.end annotation


# instance fields
.field final synthetic this$1:Lcom/zplay/bbtan/plug/EgamePlug$2;


# direct methods
.method constructor <init>(Lcom/zplay/bbtan/plug/EgamePlug$2;)V
    .locals 0

    .prologue
    .line 1
    iput-object p1, p0, Lcom/zplay/bbtan/plug/EgamePlug$2$1;->this$1:Lcom/zplay/bbtan/plug/EgamePlug$2;

    .line 79
    invoke-direct {p0}, Ljava/lang/Object;-><init>()V

    return-void
.end method


# virtual methods
.method public paySuccess(Ljava/util/Map;)V
    .locals 2
    .param p1, "params"    # Ljava/util/Map;

    .prologue
    .line 90
    sget-object v0, Lcom/dubo/android/JniMsgType;->RechargeFail:Lcom/dubo/android/JniMsgType;

    invoke-virtual {v0}, Lcom/dubo/android/JniMsgType;->ordinal()I

    move-result v0

    iget-object v1, p0, Lcom/zplay/bbtan/plug/EgamePlug$2$1;->this$1:Lcom/zplay/bbtan/plug/EgamePlug$2;

    # getter for: Lcom/zplay/bbtan/plug/EgamePlug$2;->this$0:Lcom/zplay/bbtan/plug/EgamePlug;
    invoke-static {v1}, Lcom/zplay/bbtan/plug/EgamePlug$2;->access$0(Lcom/zplay/bbtan/plug/EgamePlug$2;)Lcom/zplay/bbtan/plug/EgamePlug;

    move-result-object v1

    # getter for: Lcom/zplay/bbtan/plug/EgamePlug;->_sku:Ljava/lang/String;
    invoke-static {v1}, Lcom/zplay/bbtan/plug/EgamePlug;->access$1(Lcom/zplay/bbtan/plug/EgamePlug;)Ljava/lang/String;

    move-result-object v1

    invoke-static {v0, v1}, Lcom/dubo/android/PlatformMessage;->SendPlatformMessage(ILjava/lang/String;)V

    .line 91
    return-void
.end method

.method public payFailed(Ljava/util/Map;I)V
    .locals 2
    .param p1, "params"    # Ljava/util/Map;
    .param p2, "errorInt"    # I

    .prologue
    .line 86
    sget-object v0, Lcom/dubo/android/JniMsgType;->RechargeFail:Lcom/dubo/android/JniMsgType;

    invoke-virtual {v0}, Lcom/dubo/android/JniMsgType;->ordinal()I

    move-result v0

    iget-object v1, p0, Lcom/zplay/bbtan/plug/EgamePlug$2$1;->this$1:Lcom/zplay/bbtan/plug/EgamePlug$2;

    # getter for: Lcom/zplay/bbtan/plug/EgamePlug$2;->this$0:Lcom/zplay/bbtan/plug/EgamePlug;
    invoke-static {v1}, Lcom/zplay/bbtan/plug/EgamePlug$2;->access$0(Lcom/zplay/bbtan/plug/EgamePlug$2;)Lcom/zplay/bbtan/plug/EgamePlug;

    move-result-object v1

    # getter for: Lcom/zplay/bbtan/plug/EgamePlug;->_sku:Ljava/lang/String;
    invoke-static {v1}, Lcom/zplay/bbtan/plug/EgamePlug;->access$1(Lcom/zplay/bbtan/plug/EgamePlug;)Ljava/lang/String;

    move-result-object v1

    invoke-static {v0, v1}, Lcom/dubo/android/PlatformMessage;->SendPlatformMessage(ILjava/lang/String;)V

    .line 87
    return-void
.end method

.method public payCancel(Ljava/util/Map;)V
    .locals 2
    .param p1, "params"    # Ljava/util/Map;

    .prologue
    .line 82
    sget-object v0, Lcom/dubo/android/JniMsgType;->Recharge:Lcom/dubo/android/JniMsgType;

    invoke-virtual {v0}, Lcom/dubo/android/JniMsgType;->ordinal()I

    move-result v0

    iget-object v1, p0, Lcom/zplay/bbtan/plug/EgamePlug$2$1;->this$1:Lcom/zplay/bbtan/plug/EgamePlug$2;

    # getter for: Lcom/zplay/bbtan/plug/EgamePlug$2;->this$0:Lcom/zplay/bbtan/plug/EgamePlug;
    invoke-static {v1}, Lcom/zplay/bbtan/plug/EgamePlug$2;->access$0(Lcom/zplay/bbtan/plug/EgamePlug$2;)Lcom/zplay/bbtan/plug/EgamePlug;

    move-result-object v1

    # getter for: Lcom/zplay/bbtan/plug/EgamePlug;->_sku:Ljava/lang/String;
    invoke-static {v1}, Lcom/zplay/bbtan/plug/EgamePlug;->access$1(Lcom/zplay/bbtan/plug/EgamePlug;)Ljava/lang/String;

    move-result-object v1

    invoke-static {v0, v1}, Lcom/dubo/android/PlatformMessage;->SendPlatformMessage(ILjava/lang/String;)V

    .line 83
    return-void
.end method


這裏就很關鍵了。這個看起來眼花的話,我們看看Java的




我們驚奇的發現,這幾個成功,取消和失敗的代碼只有一處不同。


方法一:

那麼我們就可以把取消的RechargeFail換成Recharge就OK了。


方法二:

我們可以把paySuccess和payCancel的函數名調換。也就說說,我們點了取消,卻調用的是paySuccess裏面的代碼。OK。BB彈就簡單的破解了。


二、火柴人聯盟


破解BB彈之後,我本以爲內購破解起來很簡單。也很好玩,然後逛吾愛的時候,看到一篇破解火柴人的帖子。我也就去下了個官方版本去試試破解。(版本比帖子的高,帖子地址:http://www.52pojie.cn/thread-522841-1-1.html)


這不是重點,重點是。這個遊戲在模擬器上打不開。我也不知道爲什麼,直接反編譯。


發現了這個遊戲的購買方式很多,移動,電信,聯通,支付寶都有。然後還是按照之前破解BB彈的方式去破解。


卻發現根本不行。把取消的RechargeFail換成Recharge,不行


把支付寶的代碼換掉也不行。


於是認真參考了剛剛那個帖子,發現很多代碼已經被原作者改了。那就只有自己研究了


這裏就是重點了,我來說說我自己的思路。後來發現這個遊戲坑爹的只能移動購買。


首先是住入口去看看

然後在這個函數去看看移動購買的函數。



然後點過去看看,發現信息不是太多。


.method private payInYidong()V
    .locals 6

    .prologue
    const/4 v1, 0x1

    .line 735
    sget v0, Lcom/DBGame/DiabloLOL/DiabloLOL;->sCMCC_OPEN:I

    if-nez v0, :cond_0

    .line 736
    const-string v0, "\u6b63\u5728\u5904\u7406,\u8bf7\u7a0d\u540e....."

    invoke-static {v0}, Lcom/DBGame/Common/BLHelper;->showShieldLayer(Ljava/lang/String;)V

    .line 738
    :cond_0
    iget-object v0, p0, Lcom/DBGame/DiabloLOL/DiabloLOL;->PAY_CODE_MM:[Ljava/lang/String;

    iget v2, p0, Lcom/DBGame/DiabloLOL/DiabloLOL;->mPayIndex:I

    aget-object v3, v0, v2

    const/4 v4, 0x0

    iget-object v5, p0, Lcom/DBGame/DiabloLOL/DiabloLOL;->payCallback:Lcn/cmgame/billing/api/GameInterface$IPayCallback;

    move-object v0, p0

    move v2, v1

    invoke-static/range {v0 .. v5}, Lcn/cmgame/billing/api/GameInterface;->doBilling(Landroid/content/Context;ZZLjava/lang/String;Ljava/lang/String;Lcn/cmgame/billing/api/GameInterface$IPayCallback;)V

    .line 739
    return-void
.end method

但是我們好像發現了payCallback這個東西。感覺又價值。我們搜索看看。




發現了兩處,有用的是第一處的。

於是我們過去看看


這個時候我們就看出來了


package com.DBGame.DiabloLOL;

import cn.cmgame.billing.api.GameInterface.IPayCallback;
import com.DBGame.Common.BLHelper;

class DiabloLOL$4
  implements GameInterface.IPayCallback
{
  DiabloLOL$4(DiabloLOL paramDiabloLOL) {}
  
  public void onResult(int paramInt, String paramString, Object paramObject)
  {
    switch (paramInt)
    {
    default: 
      new StringBuilder().append("購買道具:[").append(this.this$0.PAY_NAME[DiabloLOL.access$800(this.this$0)]).append("] 取消!").toString();
    }
    for (;;)
    {
      BLHelper.closeShieldLayer();
      return;
      if (!"10".equals(paramObject.toString()))
      {
        new StringBuilder().append("購買道具:[").append(this.this$0.PAY_NAME[DiabloLOL.access$800(this.this$0)]).append("] 成功!").toString();
        BLHelper.purchaseComplete(this.this$0.PRO_ID_Str[DiabloLOL.access$800(this.this$0)], 1);
        continue;
        new StringBuilder().append("購買道具:[").append(this.this$0.PAY_NAME[DiabloLOL.access$800(this.this$0)]).append("] 失敗!").toString();
      }
    }
  }
}


也就說packed-switch p1, :pswitch_data_0,然後pswitch_data_0就購買成功。




直接來個goto大發。OK了

教程就到這裏了,本破解只爲學習交流。


提供樣本

BB彈:https://yunpan.cn/cMN8KD5h2IUg2  訪問密碼 9456

火柴人去官網下就是了

成本:

BB彈:https://yunpan.cn/cM4jkAt4u7m5n  訪問密碼 5c1b

火柴人:https://yunpan.cn/cMN89LIBLqjPq  訪問密碼 67a6

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章