当前位置:首页 > 核心成员 2018年05月25日
apk安卓逆向尝试之-免费购买道具

apk安卓逆向尝试之-免费购买道具                 作者:0x80

准备工具:apktool
apktoolkit
模拟器
 
图片


首先找到购买,发送,任何APK反编译都可以这样尝试
代码段:
搜索:支付成功,支付失败,发送成功,发送失败

 正在搜索...  - 成功!
  - 找到 1 个文件
> 正在搜索...  - 成功!
  - 找到 0 个文件

这种情况需要转码搜索

\u652f\u4ed8\u6210\u529f


图片


我们可以跟进看一下代码
 invoke-static {v0, v1}, Lcom/tencent/webnet/y;->a(Lcom/tencent/webnet/y;Ljava/lang/String;)V

这是支付成功的信息
可以发现使用了pswitch判断,通过不同的定义返回不同的结果,然后break跳出循环
这样更直观
图片

 
我们再来看看

 支付失败的信息

    sparse-switch v0, :sswitch_data_6
    iget-object v0, p0, Lcom/tencent/webnet/z;->eW:Lcom/tencent/webnet/y;
    const-string v1, "\u652f\u4ed8\u5931\u8d25"
    invoke-static {v0, v1}, Lcom/tencent/webnet/y;->a(Lcom/tencent/webnet/y;Ljava/lang/String;)V

那么这一段就是支付失败的信息
发送成功
 
 const-string v0, "\u77ed\u4fe1\u53d1\u9001\u4e2d,\u8bf7\u7a0d\u4faf......"

    sput-object v0, Lcn/game189/sms/SMS;->g:Ljava/lang/String;
    const-string v0, "\u53d1\u9001\u6210\u529f!"

我们重点关注的就是发送失败
   sput-object v0, Lcn/game189/sms/SMS;->h:Ljava/lang/String;
    const-string v0, "\u53d1\u9001\u5931\u8d25!\u8bf7\u786e\u8ba4\u624b\u673a\u77ed\u4fe1\u529f\u80fd\u6b63\u5e38,\u5185\u5b58\u7a7a\u95f4\u8db3\u591f."
    sput-object v0, Lcn/game189/sms/SMS;->i:Ljava/lang/String;
    const/16 v0, 0x66

 我们可以看到


android.permission.SEND_SMS,我们找到对应的 sms文件处
.class public interface abstract Lcn/game189/sms/b;
.super Ljava/lang/Object;
# virtual methods
.method public abstract a(Ljava/lang/String;)V
.end method
.method public abstract a(Ljava/lang/String;I)V
.end method
.method public abstract b(Ljava/lang/String;I)V
.end method


图片


我们一个一个来搜索,看代表的含义

首先搜索:
method public abstract a(Ljava/lang/String;)V

图片

我们找到对应的SMS.smali,其余的我们不管

然后打开
图片
 
我们使用java的源码打开,看到以下代码
class d
  extends BroadcastReceiver
{
  d(SMS paramSMS) {}
  
  public void onReceive(Context paramContext, Intent paramIntent)
  {
    switch (getResultCode())
    {
    default: 
      SMS.a(-1);
      Log.e("SMS", "SMS send err:" + getResultCode());
      SMS.a(this.a).sendEmptyMessage(104);
    }
    for (;;)
    {
      SMS.a(false);
      return;
      SMS.a(2);
      Log.i("SMS", "SMS send ok");
      SMS.b(105);
      SMS.a(this.a).sendEmptyMessage(103);
    }
  }
}


这里做了一个switch判断,发送失败和成功
iget-object v0, p0, Lcn/game189/sms/SMS;->p:Landroid/telephony/SmsManager;
我们可以知道,这是成功的意思

那我们再来搜索一下

method public abstract a(Ljava/lang/String;I)V

    sget-object v0, Lcn/game189/sms/SMS;->d:Ljava/lang/String;
    invoke-static {v0}, Lcn/game189/sms/SMS;->c(Ljava/lang/String;)Z
    new-instance v0, Landroid/content/Intent;
    invoke-direct {v0}, Landroid/content/Intent;-><init>()V
    const-string v1, "re"
    const-string v2, "err"

 发现这里就是失败的地方了
我们再来搜索下

.method public abstract b(Ljava/lang/String;I)V

    const/4 v3, 0x0
    sget-object v0, Lcn/game189/sms/SMS;->d:Ljava/lang/String;
    invoke-static {v0}, Lcn/game189/sms/SMS;->c(Ljava/lang/String;)Z
    new-instance v0, Landroid/content/Intent;
    invoke-direct {v0}, Landroid/content/Intent;-><init>()V
    const-string v1, "re"
    const-string v2, "cancel"


我们可以看到这里的代码就是取消的意思

那么,大概我们明白了,成功,失败,取消

我们直接定位到成功的地方
对应的d.class就是d.smali
那么查看代码
invoke-static {v0}, Lcn/game189/sms/SMS;->a(I)V
    const-string v0, "SMS"
    const-string v1, "SMS send ok"
    invoke-static {v0, v1}, Landroid/util/Log;->i(Ljava/lang/String;Ljava/lang/String;)I
    const/16 v0, 0x69
    invoke-static {v0}, Lcn/game189/sms/SMS;->b(I)V
    iget-object v0, p0, Lcn/game189/sms/d;->a:Lcn/game189/sms/SMS;
    invoke-static {v0}, Lcn/game189/sms/SMS;->a(Lcn/game189/sms/SMS;)Landroid/os/Handler;
    move-result-object v0
    const/16 v1, 0x67
    invoke-virtual {v0, v1}, Landroid/os/Handler;->sendEmptyMessage(I)Z
    goto :goto_0

也就是说,这里会发送成功
我们如果 要改,那么就是要考虑,他执行完这一条语句,会到哪里

.method public handleMessage(Landroid/os/Message;)V
    .locals 1
    invoke-super {p0, p1}, Landroid/os/Handler;->handleMessage(Landroid/os/Message;)V
    iget v0, p1, Landroid/os/Message;->what:I
    packed-switch v0, :pswitch_data_0
    :goto_0
    return-void
    :pswitch_0
    iget-object v0, p0, Lcn/game189/sms/e;->a:Lcn/game189/sms/SMS;
    invoke-static {v0}, Lcn/game189/sms/SMS;->b(Lcn/game189/sms/SMS;)V
    goto :goto_0
    :pswitch_1
goto :pswitch_0
    iget-object v0, p0, Lcn/game189/sms/e;->a:Lcn/game189/sms/SMS;
    invoke-static {v0}, Lcn/game189/sms/SMS;->c(Lcn/game189/sms/SMS;)V
    goto :goto_0
    :pswitch_2
    iget-object v0, p0, Lcn/game189/sms/e;->a:Lcn/game189/sms/SMS;
    invoke-static {v0}, Lcn/game189/sms/SMS;->d(Lcn/game189/sms/SMS;)V
    goto :goto_0
    :pswitch_3
    iget-object v0, p0, Lcn/game189/sms/e;->a:Lcn/game189/sms/SMS;
    invoke-static {v0}, Lcn/game189/sms/SMS;->e(Lcn/game189/sms/SMS;)V
    goto :goto_0
    nop
    :pswitch_data_0
    .packed-switch 0x66
        :pswitch_2
        :pswitch_0
        :pswitch_1
        :pswitch_3


 按照逻辑,我们应该是先购买成功,接着再无条件转移语句
pswitch_0就是我们想要的判断

那么,我们只需要在
:pswitch_0
    const/4 v0, 0x2
    
    invoke-static {v0}, Lcn/game189/sms/SMS;->a(I)V
    const-string v0, "SMS"
    const-string v1, "SMS send ok"

 

加上一个goto :pswitch_0就可以了

接着,保存,编译APK,然后用他玩这个游戏,就可以成功的
免费购买游戏道具了。

 
  - 找到 21 个文件
> 正在搜索...  - 成功!
  - 找到 1 个文件
> 正在搜索...  - 成功!
  - 找到 11 个文件
> 正在搜索...  - 成功!
  - 找到 13 个文件
> 正在编译Apk...  - 成功!
> 正在签名Apk...  - 成功!
> 生成的Apk:D:\迅雷下载\ApkIDE_jywqnyh_2265.com.apk