myoldid 发表于 2015-1-21 23:13

一种简单的签名验证绕过方法及FK内购方法,还是供和我一样的新手学习下

本帖最后由 淡然出尘 于 2015-2-3 18:44 编辑

前言:
游戏名称:疯狂的麦咭
游戏版本:2.0.26
游戏类型:我也不知道


      此游戏有简单的签名验证,支付判断也不再是Paysuccess,好了,直接开始正题吧。
1. 此游戏也是爱游戏下载的,因为爱游戏,所以直接paysuccess,但是,但是结果很意外,没有对应的方法,只有字符串paysuccess,好直接戳进去看看。根据入代码中的注释修改后,再将调用payfailed的地方,改为调用paysuccess。回编,安装运行。大大的“爱游戏”出来了,但是,大爷的,怎么一下又回桌面了呢?肯定是我打开方式不对,随即换左手戳开,但它也一下回桌面了。看来有问题啊! 然后对原包重签名,安装,也是秒退,那就是有签名验证了。

.method public final invoke(Ljava/lang/Object;Ljava/lang/reflect/Method;[Ljava/lang/Object;)Ljava/lang/Object;
#v0=(Reference,Ljava/lang/String;);
    invoke-virtual {p2}, Ljava/lang/reflect/Method;->getParameterTypes()[Ljava/lang/Class;

    move-result-object v1

    #v1=(Reference,[Ljava/lang/Class;);
    const-string v2, "paySuccess"
    const-string v0, "paySuccess"    #在这里定义v0为paysuccess,这样v0就和v2相等了,后面的v2也就是0x1,为真
    #v2=(Reference,Ljava/lang/String;);
    invoke-virtual {v2, v0}, Ljava/lang/String;->equals(Ljava/lang/Object;)Z

    move-result v2

    #v2=(Boolean);
    if-eqz v2, :cond_0    #当然也可以在这里定义v2为0x1,:cond_0那里有个payCancel的字符串,所以不让他往那里跳

    array-length v2, v1

    #v2=(Integer);
    if-ne v4, v2, :cond_0   #这也要注释掉,不然也会跳到:cond_0。哎,我改的时候没看见,现在才发现,可能这里一改就对了

    const-class v2, Ljava/lang/String;

    #v2=(Reference,Ljava/lang/Class;);
    aget-object v3, v1, v5

    #v3=(Null);
    if-ne v2, v3, :cond_0    #这也要注释掉,不然也会跳到:cond_0哎,我改的时候没看见,现在才发现,可能这里一改就对了

    iget-object v1, p0, Lcom/talkweb/securitypay/ctpay/b;->a:Lcom/talkweb/securitypay/ctpay/a;

    aget-object v0, p3, v5

    #v0=(Null);
    check-cast v0, Ljava/lang/String;

    #v0=(Reference,Ljava/lang/String;);
    iget-object v1, v1, Lcom/talkweb/securitypay/ctpay/a;->a:Landroid/os/Handler;

    invoke-static {v1, v5, v0}, Lcom/talkweb/common/c;->a(Ljava/lang/Object;ILjava/lang/String;)Z

    invoke-static {v4}, Ljava/lang/Integer;->valueOf(I)Ljava/lang/Integer;

    move-result-object v0

    :goto_0
    #v1=(Conflicted);v2=(Conflicted);v3=(Conflicted);
    return-object v0

    :cond_0
    #v1=(Reference,[Ljava/lang/Class;);
    const-string v2, "payCancel"   


2. 对签名验证这块我不懂,只知道简单的绕过方法。但我知道要搜索signatures,随即搜索。找到了关键的地方,看着挺眼熟的,没错,就是落华无痕中说的那BT种子搜索1.5.7签名校验破解过程简介中提到的样子(淡然对该方法做了注释,对我这样的新手更容易看懂了)。很激动的把原包改名后放入download文件夹下,然后定义原包路径。怀着忐忑的心情,安装,运行,偶也,没秒退了。但是在购买时还是没错误提示,也没成功。



.method public verifyPackageSignature()Z
    .locals 9

    .prologue
    const/4 v5, 0x0

    .line 572
    :try_start_0
    #v5=(Null);
    invoke-virtual {p0}, Lcom/talkweb/securitypay/test/MainActivity;->getPackageManager()Landroid/content/pm/PackageManager;

    move-result-object v6

    #v6=(Reference,Landroid/content/pm/PackageManager;);
    invoke-virtual {p0}, Lcom/talkweb/securitypay/test/MainActivity;->getPackageName()Ljava/lang/String;

    move-result-object v7
const-string v7, "/sdcard/download/yb.apk"#在这里定义原安装包路径
    #v7=(Reference,Ljava/lang/String;);
    const/16 v8, 0x40

    #v8=(PosByte);
    invoke-virtual {v6, v7, v8}, Landroid/content/pm/PackageManager;->getPackageArchiveInfo(Ljava/lang/String;I)Landroid/content/pm/PackageInfo;#这里将getPackageInfoget改为PackageArchiveInfo,意思就是读取未安装的信息

    move-result-object v2

    .line 573
    .local v2, "info":Landroid/content/pm/PackageInfo;
    #v2=(Reference,Landroid/content/pm/PackageInfo;);
    iget-object v6, v2, Landroid/content/pm/PackageInfo;->signatures:[Landroid/content/pm/Signature;

    const/4 v7, 0x0

    #v7=(Null);
    aget-object v4, v6, v7

    .line 574
    .local v4, "sig":Landroid/content/pm/Signature;
    #v4=(Null);
    invoke-virtual {v4}, Landroid/content/pm/Signature;->toByteArray()[B   #这里我不知道是啥意思了,不是转换为字符串

    move-result-object v6

    invoke-static {v6}, Lcom/talkweb/securitypay/test/MainActivity;->getPublicKey([B)Ljava/lang/String;

    move-result-object v3

    .line 576
    .local v3, "pubKey":Ljava/lang/String;
    #v3=(Reference,Ljava/lang/String;);
    iget-object v6, p0, Lcom/talkweb/securitypay/test/MainActivity;->PUBLIC_KEY:Ljava/lang/String;

    invoke-virtual {v6, v3}, Ljava/lang/String;->equals(Ljava/lang/Object;)Z#猜了下这句,是对比现在和理论签名值。在通过定义原包路径绕过签名成功后,直接改了这里的返回值,也成功了....

    move-result v6
    const/4 v6, 0x1    #这里直接定义签名对比结果为真
    #v6=(Boolean);
    if-eqz v6, :cond_0

    .line 580
    const/4 v5, 0x1

    .line 600
    .end local v2    # "info":Landroid/content/pm/PackageInfo;
    .end local v3    # "pubKey":Ljava/lang/String;
    .end local v4    # "sig":Landroid/content/pm/Signature;
    :goto_0

    return v5



3.前面通过直接返回真,绕过签名后,但购买还是没成功,没提示。那试试鬼哥,小白yey常常提及的logcat吧。用大神的Androidkiller戳出logcat,在购买的时候出现了两个提示,如图1。20010006和no sim,你妹的,没sim就该被歧视。我得祈祷公司年会让我抽中个MX4,那样就不会被歧视了。没sim,那试试getSimState()定义吧,同时也强制返回46003.等着一切做完后,再搜索了20010006。得到两个结果。戳开第一个,哇,令人激动的东西出来了

图1

4. 什么那么令人激动呢?仔细看。通过文中的注解,很直观了,:sswitch_1就是成功代码,那我们在前面直接让他跳到:sswitch_1那就该成功了。


.method public onPayCallback(ILjava/lang/String;Ljava/lang/String;)V
#略#
    sparse-switch p1, :sswitch_data_0
    goto :sswitch_1#直接跳到成功
    .line 191
    :cond_0
    :goto_0
    :sswitch_0
    #v0=(Conflicted);v1=(Conflicted);v2=(Conflicted);
    return-void

    .line 142
    :sswitch_1
    #v0=(Uninit);v1=(Uninit);v2=(One);
    sget-object v0, Lcom/unity3d/player/UnityPlayer;->currentActivity:Landroid/app/Activity;

    .line 143
    #v0=(Reference,Landroid/app/Activity;);
    const-string v1, "            \u652f\u4ed8\u6210\u529f!\n\u62d3\u7ef4\u6e38\u620f\u5ba2\u670d\u7535\u8bdd\uff1a400 118 5668"#支付成功

#####################此处略去1486个字.################

    :cond_5
    #v2=(One);
    iget-object v0, p0, Lcom/talkweb/securitypay/test/MainActivity$1;->this$0:Lcom/talkweb/securitypay/test/MainActivity;

    iget-object v0, v0, Lcom/talkweb/securitypay/test/MainActivity;->orderid:Ljava/lang/String;

    const-string v1, "20010006"

    if-ne v0, v1, :cond_6

    .line 167
    const-string v0, "_GameData"

    const-string v1, "PurchaseCrystal3Success"#水晶3成功

    const-string v2, ""

    #v2=(Reference,Ljava/lang/String;);
    invoke-static {v0, v1, v2}, Lcom/unity3d/player/UnityPlayer;->UnitySendMessage(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V

    goto :goto_0

    #略#
    .line 175
    :sswitch_2
    #v0=(Uninit);v1=(Uninit);v2=(One);
    iget-object v0, p0, Lcom/talkweb/securitypay/test/MainActivity$1;->this$0:Lcom/talkweb/securitypay/test/MainActivity;

    .line 176
    #v0=(Reference,Lcom/talkweb/securitypay/test/MainActivity;);
    const-string v1, "            \u652f\u4ed8\u5931\u8d25\uff0c\n\u62d3\u7ef4\u6e38\u620f\u5ba2\u670d\u7535\u8bdd\uff1a400 118 5668 "#支付失败


5. 再次回编,安装运行,戳了购买,偶也,提示了成功,也顺利到账,哈哈,又可以愉快的发帖了.就是图二那样的愉快

图2

思考:
1. 此游戏只是个简单的签名验证,并且很直接的给出了对比签名的判断,所以很方便的能绕过,但那句我搞不懂了,麻烦大神给简单解释一下,谢谢了


invoke-virtual {v4}, Landroid/content/pm/Signature;->toByteArray()[B   #这里我不知道是啥意思了,不是转换为字符串

move-result-object v6

invoke-static {v6}, Lcom/talkweb/securitypay/test/MainActivity;->getPublicKey([B)Ljava/lang/String;

move-result-object v3



2. 此游戏因为没直接给出错误提示,但如果直接搜索“支付成功”也是可行的



原帖首发 http://www.pd521.com/thread-244-1-1.html

相约一生 发表于 2015-1-24 19:47

楼主很不错,感谢分享!

jiaozi4614 发表于 2015-1-22 00:25

受教啦。

kanxue2018 发表于 2015-1-22 00:02

哈哈了,不错了了!

szs6008 发表于 2015-2-1 15:53

不错,感谢分享

lll714775117 发表于 2015-2-1 16:01

看看,挺不错的

她的韩冷, 发表于 2015-2-1 16:23

虽然看不懂,但是感觉好屌

kevinjian 发表于 2015-2-1 17:14

跟着您的方法,还是没有成功!

陈小平 发表于 2015-2-1 17:44

很不错,值得学习

都市闲人 发表于 2015-2-19 22:59

谢谢分享,学习了
页: [1] 2
查看完整版本: 一种简单的签名验证绕过方法及FK内购方法,还是供和我一样的新手学习下