2015-08-21 5,886 ℃

前言
要找到CC自己的decode函数不难,很容易就能找到这两个函数
DecodeXorData用来解码“.bdl”的文件
DecodeRotData用来解码“.scr”的文件
然后重点来了,这两个函数都被封装到SO里了
蛋疼的保护
用IDA打开libChronicleNUtils.so,结果IDA报了个错

用WinHex打开拉到最后面一看,嘿,整个section都被删了,这下蛋疼了。。。
另辟蹊径
虽说so文件已经被处理了,但是我还是决定将就看一下。这里DecodeXorData从导出表进去,然后右键创建函数后就能F5,F5之后发现,DecodeXorData就是一个异或加密,难怪函数名叫DecodeXorData。根据异或加密的原理,加上之前通过修改DLL导出了一些解密后的文件,于是我就把加密后的文件和解密后的文件进行异或想看看key是什么,结果有了惊人的发现,key是11字节循环的,而且只加密前面256个字节。因为Unity3D的bdl文件开头一大串都是固定的,所以现在只要先用bdl的magic number先去异或一次拿到11字节的key,然后再用key解密就行了,于是DecodeXorData的c#代码就是这样
public static void DecodeXorData(ref byte[] from)
{
if (from.Length <= 8)
{
return;
}
byte[] key = new byte[11];
key[0] = 0x55;
key[1] = 0x6E;
key[2] = 0x69;
key[3] = 0x74;
key[4] = 0x79;
key[5] = 0x57;
key[6] = 0x65;
key[7] = 0x62;
key[8] = 0x00;
key[9] = 0x00;
key[10] = 0x00;
for (int i = 0; i < key.Length; i++)
{
key[i] ^= from[i];
}
int len = from.Length;
if (len > 256)
len = 256;
for (int i = 0; i < len; i++)
{
from[i] ^= key[i % 11];
}
}
搞定了DecodeXorData,接下来DecodeRotData该怎么办呢?。。。
论猪队友的重要性
我打算去找一些老版本的客户端看看里面有没有没处理过的SO文件,结果我点进了国服的官网下了个国服的客户端,然后看了下里面的libChronicleNUtils.so。我去,居然没被处理,那就直接上IDA
BYTE *__fastcall DecodeRotData(BYTE *result, signed int a2, BYTE *a3)
{
signed int v3; // r11@1
int v4; // r8@1
BYTE *v5; // r5@5
int v6; // r9@9
signed int v7; // r10@9
int v8; // r7@10
BYTE *v9; // r6@10
int v10; // r4@10
BYTE *v11; // r12@11
int v12; // r2@11
BYTE *v13; // ST08_4@16
int v14; // off@16
char *v15; // r2@18
signed int v16; // r3@18
BYTE v17; // t1@19
signed int v18; // [sp+4h] [bp-34h]@1
int v19; // [sp+Ch] [bp-2Ch]@16
v3 = dword_D228;
v18 = *a3;
v4 = a2 / 4;
if ( dword_D228 == -1946631667 )
v3 = 0;
if ( dword_D228 != -1946631667 )
v3 = 291242281;
v5 = result;
if ( !*a3 )
--v4;
if ( !*a3 )
v18 = 4;
v6 = a3[1];
v7 = a3[2];
if ( v4 >= 0 )
{
v8 = 0;
v9 = a3;
v10 = 0;
do
{
v11 = (BYTE *)v9[6];
v12 = v9[5];
result = (BYTE *)((v8 + v6) / v7);
if ( v8 == v4 )
{
v11 = (BYTE *)v18;
}
else
{
v12 = 3;
result = (BYTE *)4;
}
if ( v8 == v4 )
v12 = (int)(v11 - 1);
LOBYTE(v13) = v9[7];
BYTE3(v13) = v9[4];
BYTE1(v13) = v9[6];
BYTE2(v13) = v9[5];
v14 = __ROR4__(v13, 32 - (v8 + v6) % v7);
v19 = v3 | v14;
if ( v8 == v4 )
result = v11;
v15 = (char *)&v19 + v12;
v16 = 0;
do
{
v17 = *v15--;
++v16;
v5[v10++] = v17;
}
while ( (signed int)result > v16 );
++v8;
v9 += 4;
}
while ( v4 >= v8 );
}
return result;
}
恩,已经够清晰的了,于是就照着这个写出c#代码
public static byte[] DecodeRotData(byte[] from)
{
int num = from[0];
int num2 = from.Length - (4 + (4 - ((num == 0) ? 4 : num)));
byte[] buffer = new byte[num2];
int v18 = from[0];
int v4 = num2 / 4;
if (from[0] == 0)
{
v4--;
v18 = 4;
}
int v6 = from[1];
int v7 = from[2];
int v9 = 0;
int v10 = 0;
for (int v8 = 0; v8 <= v4; v8++)
{
byte[] v13 = new byte[4];
v13[0] = from[v9 + 7];
v13[1] = from[v9 + 6];
v13[2] = from[v9 + 5];
v13[3] = from[v9 + 4];
uint v14 = BitConverter.ToUInt32(v13, 0);
int ror = 32 - (v8 + v6) % v7;
v14 = (v14 >> ror) | (v14 << 32 - ror);//循环右移
byte[] v15 = BitConverter.GetBytes(v14);
int v16 = 4;
if (v8 == v4)
{
v16 = v18;
}
for (int i = v16 - 1; i >= 0; i--)
{
buffer[v10++] = v15[i];
}
v9 += 4;
}
return buffer;
}
这下两个函数都完成了~
尾声
用国服的so也能写出DecodeXorData的原代码,但是前面已经用另一种方法实现了,我也懒得再去弄了~
想要已写好的工具的可以看这里
解密锁链战记资源的小工具
你好请问能委托你写这游戏的新解密工具包吗?老的不能用了。很抱歉是不是技术人员只能做伸手党,可以的话请留个联系方式进一步沟通好吗
求大神指點,CC日版昨天擋所有修改APK 用戶端不給連線阿,一片哀嚎
请教下,dword_D228这种反编译出来没有值的数是什么意思?不知道该怎么处理. 还有__ROR4__这个函数怎么得到具体算法的? IDA反编译的文件里都没有定义. 难道是通过调试得到的么? 还是就是看逻辑判断的? 谢谢!
ROR就是ida的宏定义,表示循环右移
谢谢指点!
刚开始学用IDA,好多都不懂. 那么如果没猜错, dword_xxxx, unk_xxxx之类的变量只能靠动态调试了吧?
libChronicleNUtils.so文件已经被处理过了
請問大佬,現在還有機會解密libChronicleNUtils.so 然後拿到DLL 嗎?
現在可以通過遊戲解數據了,還在想有沒有可能不通過遊戲,直接調用DLL 來解包數據。
先謝謝了。
我没试过,你可以自己去尝试
大神 能否分析一下makeWebClientString的伪代码呢?实在看不懂
libChronicleNUtils.so文件已经被处理过了,section信息被删除了,除非能修复不然静态调试下的伪代码都是错的
我看了下国服没处理的SO里没有这个函数。比较好的做法就是动态调试然后一行一行去实现
技术不到家 动态调试还没执行到断点就异常中止了