这是一款Q萌系横版封神榜题材策略手游
0x00 先用WinHex看看被加密了的游戏资源
\assets\MyResources\originalRes\background
\assets\MyResources\originalRes\background_UI
\assets\MyResources\originalRes\cardresources
以上3个文件夹里的图片都被加密了texturePacker文件夹里有2个图片加密了,其他的都是没有加密
0x01 在IDA中分析\lib\armeabi\libcocos2dcpp.so
这里分享一个小经验,一般cocos2dx的游戏我会先在IDA查看getFileData和initWithImageData这2个方法,很多游戏调用解密的方法就在这里(机率还是挺高的)
这个游戏加密方法用的是XXTea(Tea的变种算法),算法不难只要找到Key就行了,先看看这个游戏的解密图片的流程
cocos2d::CCFileUtilsAndroid::getFileData(char const*,char const*,ulong *)
↓
cocos2d::CCFileUtilsAndroid::doGetFileData(char const*,char const*,ulong *,bool)
↓
cocos2d::ZipFile::getFileData(std::string const&,ulong *)
↓
cocos2d::ZipFile::getFileData(std::string const&,ulong *,cocos2d::ZipFilePrivate *)
↓
ResourcesDecode::decodeData(uchar *,ulong,ulong *)
↓
xxtea_decrypt
上图红框中sub_6A6E5268这个方法就是XXTea的解密算法v8这个参数就是Key
0x02 关于XXTea算法自己问谷个度娘吧,我这里就不细说了,关键是如何找到这个Key
每个加密文件前29字节都是20151108.fengshen.sunlong.com,在IDA中搜索相关字符串
双击看看在哪里引用了
跳转到AppDelegate::applicationDidFinishLaunching这个方法中
这时已经很明了,key就是sunlong,20151108.fengshen.sunlong.com是为了识别被加密的文件
0x03 下面给出关键代码
XXTea.cs(XXTea算法C#版)
public class XXTea
{
public static byte[] Encrypt(byte[] Data, byte[] Key)
{
if (Data.Length == 0)
{
return Data;
}
return ToByteArray(Encrypt(TouintArray(Data, true), TouintArray(Key, false)), false);
}
public static byte[] Decrypt(byte[] Data, byte[] Key)
{
if (Data.Length == 0)
{
return Data;
}
return ToByteArray(Decrypt(TouintArray(Data, false), TouintArray(Key, false)), true);
}
private static uint[] Encrypt(uint[] v, uint[] k)
{
int n = v.Length - 1;
if (n < 1)
{
return v;
}
if (k.Length < 4)
{
uint[] Key = new uint[4];
k.CopyTo(Key, 0);
k = Key;
}
uint z = v[n], y = v[0], delta = 0x9E3779B9, sum = 0, e;
int p, q = 6 + 52 / (n + 1);
while (q-- > 0)
{
sum = unchecked(sum + delta);
e = sum >> 2 & 3;
for (p = 0; p < n; p++)
{
y = v[p + 1];
z = unchecked(v[p] += (z >> 5 ^ y << 2) + (y >> 3 ^ z << 4) ^ (sum ^ y) + (k[p & 3 ^ e] ^ z));
}
y = v[0];
z = unchecked(v[n] += (z >> 5 ^ y << 2) + (y >> 3 ^ z << 4) ^ (sum ^ y) + (k[p & 3 ^ e] ^ z));
}
return v;
}
private static uint[] Decrypt(uint[] v, uint[] k)
{
int n = v.Length - 1;
if (n < 1)
{
return v;
}
if (k.Length < 4)
{
uint[] Key = new uint[4];
k.CopyTo(Key, 0);
k = Key;
}
uint z = v[n], y = v[0], delta = 0x9E3779B9, sum, e;
int p, q = 6 + 52 / (n + 1);
sum = unchecked((uint)(q * delta));
while (sum != 0)
{
e = sum >> 2 & 3;
for (p = n; p > 0; p--)
{
z = v[p - 1];
y = unchecked(v[p] -= (z >> 5 ^ y << 2) + (y >> 3 ^ z << 4) ^ (sum ^ y) + (k[p & 3 ^ e] ^ z));
}
z = v[n];
y = unchecked(v[0] -= (z >> 5 ^ y << 2) + (y >> 3 ^ z << 4) ^ (sum ^ y) + (k[p & 3 ^ e] ^ z));
sum = unchecked(sum - delta);
}
return v;
}
private static uint[] TouintArray(byte[] Data, bool IncludeLength)
{
int n = (((Data.Length & 3) == 0) ? (Data.Length >> 2) : ((Data.Length >> 2) + 1));
uint[] Result;
if (IncludeLength)
{
Result = new uint[n + 1];
Result[n] = (uint)Data.Length;
}
else
{
Result = new uint[n];
}
n = Data.Length;
for (int i = 0; i < n; i++)
{
Result[i >> 2] |= (uint)Data[i] << ((i & 3) << 3);
}
return Result;
}
private static byte[] ToByteArray(uint[] Data, bool IncludeLength)
{
int n;
if (IncludeLength)
{
n = (int)Data[Data.Length - 1];
}
else
{
n = Data.Length << 2;
}
byte[] Result = new byte[n];
for (int i = 0; i < n; i++)
{
Result[i] = (byte)(Data[i >> 2] >> ((i & 3) << 3));
}
return Result;
}
}
这里是调用XXTea解密的关键代码
//遍历查找文件
public void FindFile(string dirPath) //参数dirPath为指定的目录
{
DirectoryInfo Dir = new DirectoryInfo(dirPath);
try
{
//查找子目录
foreach (DirectoryInfo d in Dir.GetDirectories())
{
FindFile(Dir + "\\" + d.ToString());
}
//查找文件
foreach (FileInfo f in Dir.GetFiles("*.*"))
{
ReadFile(f);
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
//读取加密文件
private void ReadFile(FileInfo f)
{
using (FileStream inStream = new FileStream(f.FullName, FileMode.Open, FileAccess.ReadWrite))
{
byte[] bytes = new byte[inStream.Length];
inStream.Read(bytes, 0, bytes.Length);
inStream.Close();
if (Encoding.Default.GetString(bytes).Contains("20151108.fengshen.sunlong.com"))
{
byte[] encryptByte = new byte[bytes.Length - 29];
Array.Copy(bytes, 29, encryptByte, 0, bytes.Length - 29);
byte[] keyByte = Encoding.Default.GetBytes("sunlong");
byte[] decryptByte = XXTea.Decrypt(encryptByte, keyByte);
OutResFile(f, decryptByte, Path.GetExtension(f.FullName));
}
}
}
//输出文件
private void OutResFile(FileInfo f, byte[] bytes, string extension)
{
string outPath = Path.Combine(f.DirectoryName, Path.GetFileNameWithoutExtension(f.FullName) + extension);
using (FileStream outStream = new FileStream(outPath, FileMode.OpenOrCreate, FileAccess.ReadWrite))
{
outStream.Seek(0, SeekOrigin.Begin);
outStream.Write(bytes, 0, bytes.Length);
}
}
资源提取源码
链接:http://pan.baidu.com/s/1mi9AXRi 密码:4402