前言

这游戏用烧饼就能很容易的修改攻击力防御力之类的,但是结算的时候发现居然有检测,没办法,只好把通讯拆开来看看了

论一个好电脑对逆向的好处

首先看看这游戏用的是啥引擎
QQ截图20160204213107。。。。。。
这个图标我还是第一次见,不得不说槽点实在太多。。。。。。
这游戏不是用unity3d做的,又得上IDA,不过,你这libnative.so怎么有48.9MB这么大。。。
在我这垃圾电脑静态分析这个so文件时,IDA挂掉了2次。。。最后把其他软件都关了花了30分钟终于是把这个文件静态分析完了,然后赶紧保存数据库。。。我去,居然有400+MB。。。

顺藤摸瓜

随便用一个请求的地址顺藤摸瓜一下,我这里用的是api/home/get,从引用一路摸下去,就能到达0x02502D5C这个地址上的app::WebApi<app::IWebApiHomeGet>::Decrypt函数(早知道命名这么标准我就直接搜Decrypt好了_(:з」∠)_)
引入眼帘的就是一个名为CryptoPP的类,这类库有点熟悉啊,赶紧百度一下,是一个C++用的开源加解密类库。我就喜欢这种用开源类库的游戏,可以省去不少时间。
随便看一下就能知道这游戏用的是AES算法,CFB模式,关键就在SetKeyWithIV这个函数上,我们来看看函数原型

void SetKeyWithIV (const byte *key, size_t length, const byte *iv, size_t ivLength)

OK,Key和IV都在里面了,我们再看看IDA里长啥样
QQ截图20160204215218
那么KEY是什么呢,其实KEY就在这个封包里
QQ截图20160204215321
QQ截图20160204215352
那么IV呢,这里我直接上动态调试了,下个断点停下后直接查看内存,IV如下

private static byte[] IV = new byte[] { 0x2C, 0x38, 0x5F, 0x44, 0x34, 0x75, 0x68, 0x6B, 0x50, 0x3A, 0x25, 0x6E, 0x5A, 0x62, 0x49, 0x4F };

至此逆向结束,接下来就是算法实现了

算法实现

依旧是用C#写的,.net framework封装的加密类用起来就是多快好省233

using System;
using System.Security.Cryptography;

namespace GrimmsNotesHelper
{
    class Crypto
    {
        public static byte[] Key;
        private static byte[] IV = new byte[] { 0x2C, 0x38, 0x5F, 0x44, 0x34, 0x75, 0x68, 0x6B, 0x50, 0x3A, 0x25, 0x6E, 0x5A, 0x62, 0x49, 0x4F };

        public static byte[] Decrypt(byte[] toDecryptArray)
        {
            int paddinglen = 32 - (toDecryptArray.Length % 32);
            byte[] buffer = new byte[toDecryptArray.Length + paddinglen];
            toDecryptArray.CopyTo(buffer, 0);
            RijndaelManaged rDel = new RijndaelManaged();
            rDel.Key = Key;
            rDel.Mode = CipherMode.CFB;
            rDel.Padding = PaddingMode.Zeros;
            rDel.IV = IV;
            ICryptoTransform cTransform = rDel.CreateDecryptor();
            byte[] resultArray = cTransform.TransformFinalBlock(buffer, 0, buffer.Length);
            byte[] buffer2 = new byte[toDecryptArray.Length];
            Array.Copy(resultArray, buffer2, toDecryptArray.Length);
            return buffer2;
        }

        public static byte[] Encrypt(byte[] toEncryptArray)
        {
            RijndaelManaged rDel = new RijndaelManaged();
            rDel.Key = Key;
            rDel.Mode = CipherMode.CFB;
            rDel.Padding = PaddingMode.Zeros;
            rDel.IV = IV;
            ICryptoTransform cTransform = rDel.CreateEncryptor();
            byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);
            byte[] buffer2 = new byte[toEncryptArray.Length];
            Array.Copy(resultArray, buffer2, toEncryptArray.Length);
            return buffer2;
        }
    }
}

游戏修改

那么这样就能看看游戏到底检测了什么,拆开commit包看一下
QQ截图20160204220139
原来是把我方战斗攻击次数,最大伤害,还有敌方对我方照成的最大伤害等数据都传了回去,怎么修改呢?
这里提供一个简单的思路,只修改我方的防御力,然后结算的时候把跟damaged有关的damagedmax_damagedmax_damaged_combomax_damaged_dflagmax_damaged_enemy_idmax_damaged_enemy_levelmax_damaged_hitmax_damaged_idmax_damaged_typemax_damaged_wave的值全部改为0,也就是伪造成对方没有对我方造成伤害,可以成功结算(已测试通过)
但是,既然都已经把通讯解开了,于是干脆就直接撸了一个脱机,把结算封包再发一遍就行(感觉这游戏一下就被玩坏了233)

尾声

写完脱机后猛然发现这游戏居然跟白猫一样没有体力限制,于是我赶紧选择了弃坑233。所以也别向我要了,不过我留了一个Fiddler的脚本,测试上面那个修改思路的时候写的,就是修改防御力为999然后伪造无伤封包。

百度盘

最后,这不出意外的话是过年前的最后一篇博文,就先祝大家新年快乐啦~

超简单的il2cpp游戏修改教程

锁链战记3.0版本也是换上了il2cpp,所以刚好就用它来写一篇简单的il2cpp修改教程 使用的是日服3.0.1版的锁链战记 首先要使用一款工具:Il2CppDumper,暑假pok...

阅读全文

Fate/Grand Order的那些事

日服v1.15 在一个月的时间里经历了太多事情,现在终于可以慢慢的写下这篇马后炮了。 调试 Fate/Grand Order在v1.11换了个保护并禁止了root过的手机,其实当时...

阅读全文

mukaRCrypto

无聊尝试用C++/CLI写的程序,发现这东西还真的有点好用啊 Σ( ° △ °|||)︴ 看到还有人在问怎么得到的,其实这次加密根本就没什么难度,直接搜索“.mukaR”,定位...

阅读全文

11 条评论

  1. 你好,我用ida 6.6調試libnative.so,模擬器是google android sdk提供的,常常遇到調試一半apk退出,或是ida自動中斷調試,請問你有遇到同要的問題嗎?

欢迎留言

7+2=