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里没有这个函数。比较好的做法就是动态调试然后一行一行去实现
技术不到家 动态调试还没执行到断点就异常中止了
国服猪队友