【手游】有杀气童话 美术资源加密分析

加密原理参考我之前写的 Unity3D 游戏加密解密那些事

0x00 在ida中先找到加密dll的地方

把libmono.so文件拖入IDA中,在函数窗口中搜索mono_image_open_from_data_with_name这个方法

对Dll加密的核心逻辑在mono_image_encrypt

0x01 经过上面的分析,我写了一个C#版的解密算法

//dll读取保存
private void ReadDLLFile(FileInfo f)
{
    if (f.Name.CompareTo("Assembly-CSharp.dll") == 0)
    {
        FileStream inStream = new FileStream(f.FullName, FileMode.Open, FileAccess.ReadWrite);

        byte[] bytes = new byte[inStream.Length];
        inStream.Read(bytes, 0, bytes.Length);
        inStream.Close();

        byte[] dllBytes = new byte[bytes.Length - 12];
        Array.Copy(bytes, 12, dllBytes, 0, bytes.Length - 12);
        dllBytes = mono_image_encrypt(dllBytes);

        string outPath = Path.Combine(f.DirectoryName, Path.GetFileNameWithoutExtension(f.FullName) + "_Fix.dll");

        FileStream outStream = new FileStream(outPath, FileMode.OpenOrCreate, FileAccess.ReadWrite);
        outStream.Seek(0, SeekOrigin.Begin);
        outStream.Write(dllBytes, 0, dllBytes.Length);
        outStream.Close();
    }
}

//dll解密算法
private byte[] mono_image_encrypt(byte[] bytes)
{
    byte[] encryptKey = new byte[16] { 0xE4, 0x1F, 0x7B, 0x6F, 0xE5, 0x2A, 0xE7, 0x1F, 0xE6, 0x04, 0x6F, 0x5D, 0x28, 0x00, 0x06, 0x02 };

    for (int i = 0; i < 5049; i++)
    {
        int index = i % 16;

        bytes[i] = (byte)(bytes[i] ^ encryptKey[index]);
    }

    return bytes;
}
左边是加密的dll,右边是解密后的dll

0x02 在Assembly-CSharp.dll中 定位加密AssetBundle的地方




经过上面的分析 先用AES对AssetBundle进行解密,然后在用GZip进行解压缩,就能得到最原始的AssetBundle

0x03 AssetBundle解密算法

//AssetBundle读取保存
private void ReadAssetBundle(FileInfo f)
{
    FileStream inStream = new FileStream(f.FullName, FileMode.Open, FileAccess.ReadWrite);

    byte[] bytes = new byte[inStream.Length];
    inStream.Read(bytes, 0, bytes.Length);
    inStream.Close();

    byte[] buff = BZip2DeCompression(AESDecrypt(bytes));

    string outPath = Path.Combine(f.DirectoryName, Path.GetFileNameWithoutExtension(f.FullName) + ".AssetBundle");

    FileStream outStream = new FileStream(outPath, FileMode.OpenOrCreate, FileAccess.ReadWrite);
    outStream.Seek(0, SeekOrigin.Begin);
    outStream.Write(buff, 0, buff.Length);
    outStream.Close();
}

//AssetBundle解密算法
private byte[] AESDecrypt(byte[] cipherText)
{
    string key = "magicgame@)!$@PM";
    byte[] key1 = new byte[] { 209, 189, 68, 63, 232, 239, 208, 62, 110, 79, 252, 62, 31, 130, 114, 63 };
    SymmetricAlgorithm symmetricAlgorithm = Rijndael.Create();
    symmetricAlgorithm.Key = Encoding.UTF8.GetBytes(key);
    symmetricAlgorithm.IV = key1;
    byte[] result = null;
    using (MemoryStream memoryStream = new MemoryStream())
    {
        using (CryptoStream cryptoStream = new CryptoStream(memoryStream, symmetricAlgorithm.CreateDecryptor(), CryptoStreamMode.Write))
        {
            cryptoStream.Write(cipherText, 0, cipherText.Length);
            cryptoStream.FlushFinalBlock();
            result = memoryStream.ToArray();
        }
    }
    return result;
}

//AssetBundle解压缩
public byte[] BZip2DeCompression(byte[] bytes)
{
    byte[] result;
    using (MemoryStream memoryStream = new MemoryStream(bytes))
    {
        using (GZipInputStream gZipInputStream = new GZipInputStream(memoryStream))
        {
            using (MemoryStream memoryStream2 = new MemoryStream())
            {
                byte[] array = new byte[4096];
                int num;
                while ((num = gZipInputStream.Read(array, 0, array.Length)) != 0)
                {
                    memoryStream2.Write(array, 0, num);
                }
                result = memoryStream2.ToArray();
            }
        }
    }
    return result;
}
至此资源的解密工作就算完成了, 关于Unity资源的提取参考我之前写的文章 Unity3D 游戏资源提取工具
资源提取源码
链接:http://pan.baidu.com/s/1gffsZtD 密码:j552

你可能感兴趣的:(游戏资源破解提取)