z_sy 发表于 2018-7-21 16:12

关于手游王朝崛起调试破解心得分享

本帖最后由 z_sy 于 2018-7-21 16:19 编辑

前提:近日我的一个好朋友安利了一款游戏,说是在删档内测,我跟着一起玩了一下,感觉还是不错的。顺便也试着研究了一波~
先向大家说明一下-根据目前的测试来看,虽然显示的金额改变了,但是毕竟是联网的游戏,在花费金子锻造升级的时候应该还是
有发包验证,大家有兴趣可以继续我的这个往下走。

-------------------------------------------------------------------------------------
友情提示:开发不易,游戏更是如此。建议大家练手娱乐就好,点到为止!
-------------------------------------------------------------------------------------

1.下载游戏安装包,拖入爱盘的Android工具---Android Killer,查看相关结构及加密情况


根据反编译的信息和结构-存在libmono.so和Assembly-CSharp.dll,可以判断出是U3D开发的,并且没有加壳。

2.将libmono.so扔进IDA,反编译查看载入关键dll的相关代码即mono_image_open_from_data_with_name函数

发现了一个rvlt_modify_data_with_name()函数,跟进查看

发现了载入的dll及解密的过程,如下:
(1)对于Assembly-CSharp.dll,将每一个字节进行减去13的解密操作
(2)对于ThreeKindom.dll,将每一个字节进行加上11的解密操作,
以上两步将加密的dll进行了还原。

为了方便分析,临时写了一个解密程序(临时写的,代码结构不好,各位老爷凑活看吧)-源码贴出

#include <stdio.h>
#include <stdlib.h>

int main()
{
        int a=-1; // 0代表解码Assembly-CSharp.dll 1代表解码ThreeKindom.dll
                          // 2代表编码Assembly-CSharp.dll 3代表编码码ThreeKindom.dll
        int num=0;

        FILE *fp_1,*fp_2,*fp_3,*fp_4,*fp_5,*fp_6;

        char buf; //one byte for buffer

        char *st1="Assembly-CSharp.dll";        //dll's name
        char *st2="ThreeKindom.dll";

        char *st3="Assembly-CSharp-NewEncode.dll";        //New Encode dll's name
        char *st4="ThreeKindom.dll-NewEncode.dll";

        char *st5="Assembly-CSharp-Decode.dll";        //Decode dll's name
        char *st6="ThreeKindom.dll-Decode.dll";

        fp_1 = fopen(st1,"rb");
        fp_2 = fopen(st2,"rb");

        fp_3 = fopen(st5,"wb");
        fp_4 = fopen(st6,"wb");

        fp_5 = fopen(st3,"wb");
        fp_6 = fopen(st4,"wb");

        printf("0 - Decode Assembly-CSharp.dll \n");
        printf("1 - Decode ThreeKindom.dll \n");
        printf("2 - Encode Assembly-CSharp.dll \n");
        printf("3 - Encode ThreeKindom.dll \n");
        printf("-1 - Exit \n");
        printf("Please input number you want execute (0~3): ");
        scanf("%d",&a);

        if(fp_1 == NULL || fp_2 == NULL || fp_3 == NULL || fp_4 == NULL)
        {
                printf("Open Error ! \n");
                getchar();
                return 0;
        }

        switch(a)
        {
        case -1:
        {
                break;
        }
        case 0:
        case 1:
        {
                a==0?(num=13):(num=11);
                while(1)
                {
                        if(num == 13)
                        {
                                buf = fgetc(fp_1);
                                buf-=13;
                                fputc(buf,fp_3);
                                if(feof(fp_1))
                                {
                                        break;
                                }
                        }
                        else
                        {
                                buf = fgetc(fp_2);
                                if(feof(fp_2))
                                {
                                        break;
                                }
                                buf+=11;
                                fputc(buf,fp_4);
                               
                        }
                }
                break;
        }
        case 2:
        case 3:
        {
                a==2?(num=13):(num=11);
                while(1)
                {
                        if(num == 13)
                        {
                                buf = fgetc(fp_1);
                                if(feof(fp_1))
                                {
                                        break;
                                }
                                buf+=13;
                                fputc(buf,fp_5);
                        }
                        else
                        {
                                buf = fgetc(fp_2);
                                if(feof(fp_2))
                                {
                                        break;
                                }
                                buf-=11;
                                fputc(buf,fp_6);
                        }
                }
                break;
        }
        default:
        {
                printf("Input Number Error ! \n");
                getchar();
                return 0;
        }
        }

        fclose(fp_1);
        fclose(fp_2);
        fclose(fp_3);
        fclose(fp_4);
        fclose(fp_5);
        fclose(fp_6);

        printf("Decode Finish ! \n");

        getchar();

        return 0;
}

3.将还原出的两个dll拖入爱盘的.Net破解工具Reflector,进行查看分析
加密前的dll导入后,无法识别


解密后的dll导入,可以查看结构


4.猜测关键字,找到我们需要的关键类和方法
由于我们想修改金条,所以先搜索一下gold,看一下有没有我们需要的,
经过搜索,我们找到了一个SetGoldNumber的方法,看一下实现,
发现最后面有个赋值语句,那么我们可以尝试从这个方法里动手脚。
我的思路-将赋值的num变量改为常数,这样,可以永远设置gold的
this.gold为我们设定的那个数值。


5.利用吾爱虚拟机的Reflector+Reflexil修改关键类

将ldarg,1 ----> ldc.i4 99999
将修改的dll保存。

6.加密并替换原apk里面的dll,重新签名打包成apk,安装测试
加密可以用我前面贴出的程序,也可以自己写,很简单,只是把
dll里面的每个字节都加上了13而已。
效果图


----------------------------------------------------------------------
附件是原apk的安装包、破解后的安装包以及我写的加解密的源代码和程序
供大家学习交流使用~
(同步看雪)
链接:https://pan.baidu.com/s/1gj5zV1BWdu-MvjJlBoJHiA 密码:14hk

最后一点,如果大家看的爽的话,请拿你们的C币砸死我,谢谢,嘿嘿!

相知吾爱,相遇吾爱,愿我们大家共同进步。享受吾爱大家庭带给我们的欢乐~

z_sy 发表于 2018-7-25 08:18

@qtfreet00 哇塞,谢谢版主视察!我会再接再厉{:1_919:}

z_sy 发表于 2018-7-22 07:30

feob 发表于 2018-7-22 02:02
金砖不能花啊,买解锁技能,就说 该名字已被使用,也买不了,望能解决,谢谢了

是啊,开文就说了,我认为升级的时候还会有和数据谷的交互,还没有抓包测试。有兴趣可以接着我的这个往下走,但是点到为止哈,开发都不容易:loveliness:

z_sy 发表于 2018-7-22 07:27

a91103581 发表于 2018-7-21 20:23
不错不错,,正好现在正在学习安卓的逆向,向大佬学习

跟你推荐个人,咱们坛有个ID云在天,那个是咱们坛真大佬之一,我等只能仰望:lol

SaberOAO 发表于 2018-7-21 18:16

看不懂大佬的东西 - -

Anakin 发表于 2018-7-21 18:21

甚少玩手游 但看啦楼主分享觉得总体分享还可以 所以支持下

Jxdm 发表于 2018-7-21 18:43

非常感谢~学习了

a91103581 发表于 2018-7-21 20:23

不错不错,,正好现在正在学习安卓的逆向,向大佬学习

feob 发表于 2018-7-22 02:02

金砖不能花啊,买解锁技能,就说 该名字已被使用,也买不了,望能解决,谢谢了

z_sy 发表于 2018-7-22 07:24

Jxdm 发表于 2018-7-21 18:43
非常感谢~学习了

有事直接私信交流就好了,等级太低,不让加:lol

z_sy 发表于 2018-7-22 07:28

Anakin 发表于 2018-7-21 18:21
甚少玩手游 但看啦楼主分享觉得总体分享还可以 所以支持下

话不多说,放下你的C币{:1_918:}
页: [1] 2 3 4
查看完整版本: 关于手游王朝崛起调试破解心得分享