您现在的位置是:网站首页>文章详情文章详情
安卓app动态调试,内购破解滑雪大冒险
inlike2019-09-09【 原创文章 】 浏览(1535) 评论(0) 喜欢(29)
简介内购的游戏是小米版的滑雪大冒险,比价有意思的小游戏;通过对滑雪大冒险小游戏综合运用apk逆向、java代码分析、smali分析、动态调试等基础方法。 内购破解之前的游戏,地图和道具都需要付费:
首先还是需要使用Androidkiller对apk进行反编译,同时使用JEB获取java源码,但是在本次案例中JEB并不能反编译该apk,原因是内存太小。
因此查看该app对应的源码使用Androidkiller继承的GD-GUI软件,andkiller反编译后如图:
但是该如何下手?如何找到支付相关的模块,有几种思路:观察自带的日志信息、命令行打印出操作界面对应的页面信息,如图:
这里首先去看看日志,在点击支付的时候同时观察日志信息,还是会发现一些有价值的信息:
发现其中疑似支付相关的是:Yodo1PayHelper, startPay call ...,那我们可以查找关键词Yodo1PayHelper、startPay ,在查找之后还真有相关的类和方法:
.method public pay(Landroid/app/Activity;Ljava/util/List;Ljava/lang/String;DLjava/lang/String;Z)V
.locals 30
.param p1, "activity" # Landroid/app/Activity;
.param p3, "productId" # Ljava/lang/String;
.param p4, "discount" # D
.param p6, "extraParam" # Ljava/lang/String;
.param p7, "isCheckAccount" # Z
.annotation system Ldalvik/annotation/Signature;
value = {
"(",
"Landroid/app/Activity;",
"Ljava/util/List",
"<",
"Lcom/yodo1/android/sdk/constants/PayType;",
">;",
"Ljava/lang/String;",
"D",
"Ljava/lang/String;",
"Z)V"
}
.end annotation
.prologue
.line 116
.local p2, "payTypes":Ljava/util/List;, "Ljava/util/List<Lcom/yodo1/android/sdk/constants/PayType;>;"
const-string/jumbo v4, "Yodo1PayHelper, startPay call ..."
invoke-static {v4}, Lcom/yodo1/sdk/kit/YLog;->i(Ljava/lang/String;)V
.line 117
new-instance v4, Ljava/lang/StringBuilder;
invoke-direct {v4}, Ljava/lang/StringBuilder;-><init>()V
const-string/jumbo v5, "Yodo1PayHelper, startPay \u6298\u6263\u6bd4\u4f8b \uff1a "
一个带有支付字样的关键词方法pay,那这就是和支付相关的,然后再看这个方法对应的java源码,以便查找相关的逻辑:
private void pay(final Activity paramActivity, final String paramString1, final PayAdapterBase paramPayAdapterBase, final ProductData paramProductData, final String paramString2, final PayType paramPayType)
{
YLog.i("Yodo1PayHelper, pay call ...");
if ((paramPayType == PayType.channel) && (paramPayAdapterBase.needLogin(paramActivity)) && (!Yodo1UserCenter.isLogin()))
{
YLog.i("Yodo1PayHelper, 支付之前必须先登录, 正在自动唤起登录方法");
callLoginFunction(paramActivity, paramString1, new Yodo1ResultCallback()
{
public void onResult(Yodo1ResultCallback.ResultCode paramAnonymousResultCode, String paramAnonymousString)
{
YLog.i("Yodo1PayHelper, pay callback, resultCode = " + paramAnonymousResultCode + ", msg = " + paramAnonymousString);
if (paramAnonymousResultCode == Yodo1ResultCallback.ResultCode.Success)
{
Yodo1UserCenter.getUser().setIsLogin(true);
Yodo1PayHelper.this.pay(paramActivity, paramString1, paramPayAdapterBase, paramProductData, paramString2, paramPayType);
return;
}
Yodo1PayHelper.this.purchased(205, "", paramProductData, paramPayType);
}
});
return;
}
final ChannelPayInfo localChannelPayInfo = toChannelPayInfo(createOrderId(paramActivity, paramPayAdapterBase), paramProductData, paramString2);
final User localUser = Yodo1UserCenter.getUser();
final Element localElement = Yodo1ProductFactory.getInstance().getProductElement(paramProductData.getProductId());
localChannelPayInfo.setChannelFid(localElement.getAttribute("fid" + paramString1));
String str = paramPayAdapterBase.createOrderExtra(localChannelPayInfo, localUser);
YLog.d("Yodo1PayHelper, pay, createOrderExtra = " + str);
showLoading(paramActivity);
this.pay_time = 0L;
placeOrderByOps(paramActivity, paramPayAdapterBase, paramString1, localChannelPayInfo, str, paramPayType, new Yodo1OpsCallback()
{
public void onResult(Yodo1OpsCallback.ResultCode paramAnonymousResultCode, String paramAnonymousString)
{
YLog.d("Yodo1PayHelper, pay createOrder callback, resultCode = " + paramAnonymousResultCode + ", msg = " + paramAnonymousString);
if (System.currentTimeMillis() - Yodo1PayHelper.this.pay_time < 60000L)
{
YLog.e("Yodo1PayHelper, " + paramString1 + "支付回调两次 ");
return;
}
Yodo1PayHelper.this.pay_time = System.currentTimeMillis();
Yodo1PayHelper.this.hideLoading(paramActivity);
boolean bool = paramPayAdapterBase.createOrderByOpsCallback(paramAnonymousResultCode.value(), paramAnonymousString, paramActivity, localChannelPayInfo, localElement, paramString2, localUser);
if (paramAnonymousResultCode == Yodo1OpsCallback.ResultCode.Success)
{
localChannelPayInfo.setResponse(paramAnonymousString);
paramActivity.runOnUiThread(new Runnable()
{
public void run()
{
final String str = Yodo1PayHelper.6.this.val$channelPayInfo.getOrderId();
Yodo1PayHelper.6.this.val$productData.setOrderId(str);
Yodo1PayHelper.6.this.val$productData.setPaytime(System.currentTimeMillis());
Yodo1PayHelper.this.saveProductDatatoLocal(Yodo1PayHelper.6.this.val$activity, Yodo1PayHelper.6.this.val$channelPayInfo);
Yodo1PayHelper.6.this.val$payAdapter.pay(Yodo1PayHelper.6.this.val$activity, Yodo1PayHelper.6.this.val$channelPayInfo, Yodo1PayHelper.6.this.val$payElement, Yodo1PayHelper.6.this.val$extraParam, Yodo1PayHelper.6.this.val$channelUser, new ChannelSDKCallback()
{
public void onResult(int paramAnonymous3Int1, int paramAnonymous3Int2, String paramAnonymous3String)
{
YLog.i("Yodo1PayHelper, pay channelpay callback, status = " + paramAnonymous3Int1 + ", errorCode = " + paramAnonymous3Int2 + ", params = " + paramAnonymous3String);
Yodo1ResultCallback.ResultCode localResultCode = Yodo1ResultCallback.ResultCode.Failed;
if (RegexUtils.isJson(paramAnonymous3String)) {
Yodo1PayHelper.6.this.val$productData.setExtras(paramAnonymous3String);
}
switch (paramAnonymous3Int1)
{
default:
Yodo1PayHelper.this.removeProductDatatoLocal(Yodo1PayHelper.6.this.val$activity, Yodo1PayHelper.6.this.val$productData);
if (paramAnonymous3Int2 == 301)
{
Yodo1PayHelper.this.startPay(Yodo1PayHelper.6.this.val$activity, PayType.carriers, Yodo1PayHelper.6.this.val$productData, Yodo1PayHelper.6.this.val$extraParam);
return;
}
break;
case 1:
YLog.i("Yodo1PayHelper, 正在查询订单状态");
Yodo1PayHelper.this.showLoading(Yodo1PayHelper.6.this.val$activity);
if (Yodo1PayHelper.6.this.val$payAdapter.needQueryOrder(Yodo1PayHelper.6.this.val$activity))
{
Yodo1PayHelper.this.queryOrderByOps(Yodo1PayHelper.6.this.val$activity, str, new Yodo1OpsCallback()
{
public void onResult(Yodo1OpsCallback.ResultCode paramAnonymous4ResultCode, String paramAnonymous4String)
{
YLog.d("Yodo1PayHelper, pay queryOrder, resultCode = " + paramAnonymous4ResultCode + ", msg = " + paramAnonymous4String);
Yodo1PayHelper.this.hideLoading(Yodo1PayHelper.6.this.val$activity);
if (Yodo1PayHelper.6.this.val$payAdapter.queryOrderByOpsCallback(paramAnonymous4ResultCode.value(), paramAnonymous4String, Yodo1PayHelper.6.this.val$activity, Yodo1PayHelper.6.this.val$channelPayInfo, Yodo1PayHelper.6.this.val$payElement, Yodo1PayHelper.6.this.val$extraParam, Yodo1PayHelper.6.this.val$channelUser)) {
return;
}
if (paramAnonymous4ResultCode == Yodo1OpsCallback.ResultCode.Success)
{
Yodo1PayHelper.this.purchased(1, Yodo1PayHelper.6.1.1.this.val$orderId, Yodo1PayHelper.6.this.val$productData, Yodo1PayHelper.6.this.val$payType);
Yodo1PayHelper.this.removeProductDatatoLocal(Yodo1PayHelper.6.this.val$activity, Yodo1PayHelper.6.this.val$productData);
return;
}
if (paramAnonymous4ResultCode == Yodo1OpsCallback.ResultCode.Payment_Omissive)
{
Yodo1PayHelper.this.purchased(203, Yodo1PayHelper.6.1.1.this.val$orderId, Yodo1PayHelper.6.this.val$productData, Yodo1PayHelper.6.this.val$payType);
return;
}
Yodo1PayHelper.this.purchased(0, Yodo1PayHelper.6.1.1.this.val$orderId, Yodo1PayHelper.6.this.val$productData, Yodo1PayHelper.6.this.val$payType);
}
});
return;
}
if (Yodo1PayHelper.6.this.val$payAdapter.needVerifyOrder(Yodo1PayHelper.6.this.val$activity))
{
YLog.i("Yodo1PayHelper, 订单状态校验成功");
Yodo1PayHelper.this.hideLoading(Yodo1PayHelper.6.this.val$activity);
Yodo1PayHelper.this.purchased(1, str, Yodo1PayHelper.6.this.val$productData, Yodo1PayHelper.6.this.val$payType);
Yodo1PayHelper.this.removeProductDatatoLocal(Yodo1PayHelper.6.this.val$activity, Yodo1PayHelper.6.this.val$productData);
return;
}
YLog.i("Yodo1PayHelper, 正在提交订单状态");
Yodo1PayHelper.this.submitOrderByOps(Yodo1PayHelper.6.this.val$activity, str, Yodo1PayHelper.6.this.val$payType, new Yodo1OpsCallback()
{
public void onResult(Yodo1OpsCallback.ResultCode paramAnonymous4ResultCode, String paramAnonymous4String)
{
YLog.d("Yodo1PayHelper, pay submitOrder, resultCode = " + paramAnonymous4ResultCode + ", msg = " + paramAnonymous4String);
Yodo1PayHelper.this.hideLoading(Yodo1PayHelper.6.this.val$activity);
if (Yodo1PayHelper.6.this.val$payAdapter.queryOrderByOpsCallback(paramAnonymous4ResultCode.value(), paramAnonymous4String, Yodo1PayHelper.6.this.val$activity, Yodo1PayHelper.6.this.val$channelPayInfo, Yodo1PayHelper.6.this.val$payElement, Yodo1PayHelper.6.this.val$extraParam, Yodo1PayHelper.6.this.val$channelUser)) {
return;
}
if (paramAnonymous4ResultCode == Yodo1OpsCallback.ResultCode.Success)
{
Yodo1PayHelper.this.purchased(1, Yodo1PayHelper.6.1.1.this.val$orderId, Yodo1PayHelper.6.this.val$productData, Yodo1PayHelper.6.this.val$payType);
Yodo1PayHelper.this.removeProductDatatoLocal(Yodo1PayHelper.6.this.val$activity, Yodo1PayHelper.6.this.val$productData);
return;
}
if (paramAnonymous4ResultCode == Yodo1OpsCallback.ResultCode.Payment_Omissive)
{
Yodo1PayHelper.this.purchased(203, Yodo1PayHelper.6.1.1.this.val$orderId, Yodo1PayHelper.6.this.val$productData, Yodo1PayHelper.6.this.val$payType);
return;
}
Yodo1PayHelper.this.purchased(0, Yodo1PayHelper.6.1.1.this.val$orderId, Yodo1PayHelper.6.this.val$productData, Yodo1PayHelper.6.this.val$payType);
}
});
return;
case 2:
Yodo1PayHelper.this.removeProductDatatoLocal(Yodo1PayHelper.6.this.val$activity, Yodo1PayHelper.6.this.val$productData);
if (paramAnonymous3Int2 == 208)
{
YLog.i("Yodo1PayHelper, 这是已购买的商品,购买成功");
Yodo1PayHelper.this.purchased(1, Yodo1PayHelper.6.this.val$channelPayInfo.getOrderId(), Yodo1PayHelper.6.this.val$productData, Yodo1PayHelper.6.this.val$payType);
return;
}
Yodo1PayHelper.this.purchased(2, Yodo1PayHelper.6.this.val$channelPayInfo.getOrderId(), Yodo1PayHelper.6.this.val$productData, Yodo1PayHelper.6.this.val$payType);
return;
}
switch (paramAnonymous3Int2)
{
}
while (paramAnonymous3Int2 == 208)
{
YLog.i("Yodo1PayHelper, 这是已购买的商品,购买成功");
Yodo1PayHelper.this.purchased(1, Yodo1PayHelper.6.this.val$channelPayInfo.getOrderId(), Yodo1PayHelper.6.this.val$productData, Yodo1PayHelper.6.this.val$payType);
return;
paramAnonymous3Int2 = 205;
continue;
paramAnonymous3Int2 = 3;
}
Yodo1PayHelper.this.purchased(paramAnonymous3Int2, Yodo1PayHelper.6.this.val$channelPayInfo.getOrderId(), Yodo1PayHelper.6.this.val$productData, Yodo1PayHelper.6.this.val$payType);
}
});
}
});
return;
}
if (bool)
{
YLog.w("Yodo1PayHelper, createOder, error msg = " + paramAnonymousString);
localChannelPayInfo.setResponse(paramAnonymousString);
paramActivity.runOnUiThread(new Runnable()
{
public void run()
{
Yodo1PayHelper.6.this.val$payAdapter.pay(Yodo1PayHelper.6.this.val$activity, Yodo1PayHelper.6.this.val$channelPayInfo, Yodo1PayHelper.6.this.val$payElement, Yodo1PayHelper.6.this.val$extraParam, Yodo1PayHelper.6.this.val$channelUser, new ChannelSDKCallback()
{
public void onResult(int paramAnonymous3Int1, int paramAnonymous3Int2, String paramAnonymous3String)
{
YLog.i("Yodo1PayHelper, pay channelpay callback, status = " + paramAnonymous3Int1 + ", errorCode = " + paramAnonymous3Int2 + ", params = " + paramAnonymous3String);
Yodo1PayHelper.this.purchased(paramAnonymous3Int2, Yodo1PayHelper.6.this.val$channelPayInfo.getOrderId(), Yodo1PayHelper.6.this.val$productData, Yodo1PayHelper.6.this.val$payType);
}
});
}
});
return;
}
Yodo1PayHelper.this.purchased(206, localChannelPayInfo.getOrderId(), paramProductData, paramPayType);
}
});
}
这段代码很长,逻辑又相对混乱直接看java源码分析逻辑是比较困难的,那就只有先看看代码中的一些提示信息,比如:这是已购买的商品,购买成功。
if (paramAnonymous3Int2 == 208)
{
YLog.i("Yodo1PayHelper, 这是已购买的商品,购买成功");
Yodo1PayHelper.this.purchased(1, Yodo1PayHelper.6.this.val$channelPayInfo.getOrderId(), Yodo1PayHelper.6.this.val$productData, Yodo1PayHelper.6.this.val$payType);
return;
}
这里有很明显的逻辑逻辑判断,但是我们依旧无法知道这部分是佛在支付成功的前提下执行,或者不管支付成功或失败都会效验一下。
这种情况下要么修改smali代码然后打包运行一下,要么就动态调试一下设置一个断点,看该处逻辑是否被执行。
在Androidstudio中导入反编译后的项目目录,然后设置好断点;接着在smali源码的AndroidManifest.xml文件中,application标签下设置android:debuggable="true",然后打包安装。
安装后在adb命令下设置转发:
adb forward tcp:8700 jdwp:pid
pid是对应的apk进程号,通过下面命令获得:
adb shell "ps -ef | grep packagename"
接下来就是在Androidstudio中设置远程调试端口:
相关文章
本栏推荐
标签云
猜你喜欢
站点信息
- 建站时间:2019-5-24
- 网站程序:like in love
- 主题模板:《今夕何夕》
- 文章统计:104条
- 文章评论:***条
- 微信公众号:扫描二维码,关注我们