安卓逆向之二__《全民捕魚》遊戲內購破解
環境簡介
系統:Android 4.4
工具:Windows 10 64bit 夜神模擬器
Android Killer
Java Decompiler
全民捕魚遊戲簡介
遊戲名稱:全民捕魚
遊戲類型:休閒益智
遊戲版本:1.7
遊戲界面如下:
逆向分析
首先我們進入商城點擊付費金幣的購買,彈出"購買失敗"的Toast(吐司)
根據這個提示我們使用AndroidKiller分析這個APK.看到入口函數爲LogoActivity很簡單.
直接使用特徵Toast字符串搜索,沒有搜到.
再次測試把字符串轉換爲UniCode形式(下邊的小a大A按鈕),再次搜索,找到一個字符串結果
雙擊到使用處的語句,查看源碼發現此處有購買成功失敗函數的選擇調用語句
我們通過這幾個函數繼續查找對比,最後在搜索payFail的最後一個結果,發現重要函數所在
支付失敗,與支付成功函數離得很近,分析發現,函數參數也相似
所以我們使用的破解內購的辦法可以是,把支付成功函數的函數體,整個複製到支付失敗函數裏邊去,讓支付永遠成功.
兩個函數smali代碼
.method public payFailed(Ljava/util/Map;I)V
.locals 5
.param p1, "params" # Ljava/util/Map;
.param p2, "arg1" # I
.prologue
.line 208
const-string v0, "cocos2d-x debug info"
new-instance v1, Ljava/lang/StringBuilder;
invoke-direct {v1}, Ljava/lang/StringBuilder;-><init>()V
const-string v2, "Failed DX_payCode2 == "
invoke-virtual {v1, v2}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;
move-result-object v1
sget-object v2, Lcom/payCom/org/IAPListener;->DX_PAYCODES:[Ljava/lang/String;
iget-object v3, p0, Lcom/payCom/org/IAPListener$1;->this$0:Lcom/payCom/org/IAPListener;
iget v3, v3, Lcom/payCom/org/IAPListener;->curPayIndex:I
aget-object v2, v2, v3
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;->d(Ljava/lang/String;Ljava/lang/String;)I
.line 209
const-string v0, "cocos2d-x debug info"
new-instance v1, Ljava/lang/StringBuilder;
invoke-direct {v1}, Ljava/lang/StringBuilder;-><init>()V
const-string v2, "FaildCode == "
invoke-virtual {v1, v2}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;
move-result-object v1
invoke-virtual {v1, p2}, Ljava/lang/StringBuilder;->append(I)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;->d(Ljava/lang/String;Ljava/lang/String;)I
.line 210
iget-object v0, p0, Lcom/payCom/org/IAPListener$1;->this$0:Lcom/payCom/org/IAPListener;
iget v0, v0, Lcom/payCom/org/IAPListener;->curPayIndex:I
const/4 v1, 0x0
invoke-static {v0, v1}, Lcom/payCom/org/GameJni;->OderFinish(II)V
.line 211
sget-object v0, Lcom/payCom/org/IAPListener;->iapHandler:Lcom/payCom/org/IAPHandler;
sget-object v1, Lcom/payCom/org/IAPListener;->iapHandler:Lcom/payCom/org/IAPHandler;
const/16 v2, 0x2715
sget-object v3, Lcom/payCom/org/IAPListener;->DX_PAYCODES:[Ljava/lang/String;
iget-object v4, p0, Lcom/payCom/org/IAPListener$1;->this$0:Lcom/payCom/org/IAPListener;
iget v4, v4, Lcom/payCom/org/IAPListener;->curPayIndex:I
aget-object v3, v3, v4
invoke-static {v1, v2, v3}, Landroid/os/Message;->obtain(Landroid/os/Handler;ILjava/lang/Object;)Landroid/os/Message;
move-result-object v1
invoke-virtual {v0, v1}, Lcom/payCom/org/IAPHandler;->sendMessage(Landroid/os/Message;)Z
.line 212
return-void
.end method
.method public paySuccess(Ljava/util/Map;)V
.locals 5
.param p1, "params" # Ljava/util/Map;
.prologue
.line 202
const-string v0, "cocos2d-x debug info"
new-instance v1, Ljava/lang/StringBuilder;
invoke-direct {v1}, Ljava/lang/StringBuilder;-><init>()V
const-string v2, "Success DX_payCode1"
invoke-virtual {v1, v2}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;
move-result-object v1
sget-object v2, Lcom/payCom/org/IAPListener;->DX_PAYCODES:[Ljava/lang/String;
iget-object v3, p0, Lcom/payCom/org/IAPListener$1;->this$0:Lcom/payCom/org/IAPListener;
iget v3, v3, Lcom/payCom/org/IAPListener;->curPayIndex:I
aget-object v2, v2, v3
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;->d(Ljava/lang/String;Ljava/lang/String;)I
.line 203
iget-object v0, p0, Lcom/payCom/org/IAPListener$1;->this$0:Lcom/payCom/org/IAPListener;
iget v0, v0, Lcom/payCom/org/IAPListener;->curPayIndex:I
const/4 v1, 0x1
invoke-static {v0, v1}, Lcom/payCom/org/GameJni;->OderFinish(II)V
.line 204
sget-object v0, Lcom/payCom/org/IAPListener;->iapHandler:Lcom/payCom/org/IAPHandler;
sget-object v1, Lcom/payCom/org/IAPListener;->iapHandler:Lcom/payCom/org/IAPHandler;
const/16 v2, 0x271a
sget-object v3, Lcom/payCom/org/IAPListener;->DX_PAYCODES:[Ljava/lang/String;
iget-object v4, p0, Lcom/payCom/org/IAPListener$1;->this$0:Lcom/payCom/org/IAPListener;
iget v4, v4, Lcom/payCom/org/IAPListener;->curPayIndex:I
aget-object v3, v3, v4
invoke-static {v1, v2, v3}, Landroid/os/Message;->obtain(Landroid/os/Handler;ILjava/lang/Object;)Landroid/os/Message;
move-result-object v1
invoke-virtual {v0, v1}, Lcom/payCom/org/IAPHandler;->sendMessage(Landroid/os/Message;)Z
.line 205
return-void
.end method
修改完成後,保存,並重新編譯
在夜神模擬器上卸載之前的原版遊戲,安裝破解後的遊戲,實現了商城內購破解
添加個人信息的破解
爲了更有趣一點,我們在購買成功的提示上添加自己的個人信息
我們再次搜索到"購買成功"提示,在字符串之前加入"Hades破解:",如下,最後再次編譯,安裝測試
完成破解:
總結:
安卓遊戲內購的破解簡單的思路都是大同小異,也可以更改調用的函數參數等.smail代碼與僞Java代碼很接近自然語言邏輯思路,在沒有安卓加固(殼)的遊戲上做一些內購破解還是很簡單的.去網上Download幾個遊戲練習一下破解就很有成就感.