(文章僅用于記錄學(xué)習(xí)過程,相關(guān)破解技術(shù)僅限于研究使用,不準(zhǔn)用于非法目的,否則后果自負(fù))
說明
學(xué)習(xí)逆向基礎(chǔ)之后就開始真實(shí)實(shí)戰(zhàn),這邊我是跟著這篇文章看到逆向資源,雖然文章是17年的文章,但是畢竟是在學(xué)習(xí)嗎,不要管時(shí)間勒.這里采用和文章不同的方法
使用工具
1:apltool
2: jadx
3:sublime Text2
看源碼
這個(gè)apk是一個(gè)簡單的切水果應(yīng)用,并沒有加殼,我們直接將apk拖進(jìn)jadx里面去
我們打開將失敗字符串轉(zhuǎn)為unicode,也就是\u5931\u8d25,(ps:失敗怎么來的,可以玩下游戲點(diǎn)下支付然后取消)我們搜索看看
我們看到這個(gè)命名,com.mydefinemmpay.tool.Mymmpay,這個(gè)明顯就是一個(gè)管理支付的類,
我們接著看下哪里調(diào)用了payResultSuccees(),我們看到在當(dāng)前類的doBilling方法調(diào)用了payResultSuccees,也就是同一個(gè)類下面
//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();
}
}
}
}
我們看下誰調(diào)用了doBilling方法,我們看到是當(dāng)前類的pay方法調(diào)用了doBilling//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();
}
整理思路
我們發(fā)現(xiàn)MymmPay這個(gè)是負(fù)責(zé)管理支付的,這個(gè)里面有pay(),doBilling(),payResultSucceed(),payResultFalse(),payResultCancel()等主要方法,整理下邏輯,點(diǎn)擊支付,然后調(diào)用pay(),pay調(diào)用dobilling方法,然后返回結(jié)果整理方法
有好幾種方法
1:原文說的,將payResultFalse()內(nèi)容替換成payResultSucceed的內(nèi)容,這樣支付失敗和支付成功是一樣都是成功,
2:pay->doBilling->我們看了下源碼,doBillding()里面調(diào)用了payResultSucceed(),payResultCancel().payResultFalse(),這個(gè)類應(yīng)該是一個(gè)判斷類,我們直接把doBilling()內(nèi)部直接調(diào)用payResultSuccess()方法,這樣連判斷都不用判斷了
反編譯
使用apktool命令將apk反編譯,fruit文件夾,我這邊的apk命名是fruit.apk,所以就生成了fruit文件夾,如果你不是叫fruit那就是其他文件名
apktool d fruit.apk
我們找MymmPay這個(gè)類的,這個(gè)類在com.mydefinemmpay.tool文件下面,打開fruit->smali->com->mydefinemmpay->tool下面
我們使用sublime Text打開MymmPay.smali(sublime text增加了smali語法高亮和提示的支持,需要的童鞋可以自己百度一下,這邊就不說)
我們搜索下doBilling
//方法開頭 修改前
.method public doBilling()V
.locals 7
.prologue
//中間省略
//方法結(jié)尾
.end method
將方法中間刪掉,然后將locals 修改為0,然后在增加payResultSuccess()方法的調(diào)用
///修改后
.method public doBilling()V
.locals 0
.prologue
//其他的不要 只增加一條方法
//只調(diào)用payResultSuccess()方法就可以
invoke-virtual {v0}, Lcom/mydefinemmpay/tool/MymmPay;->payResultSuccess()V
return-void
.end method
完成
之后就保存,然后使用apktool重新打包生成apk文件,然后使用jarsigner重新簽名安裝就可以了