锁链战记资源提取

2015-08-21 5,885 ℃

前言

要找到CC自己的decode函数不难,很容易就能找到这两个函数
DecodeXorData用来解码“.bdl”的文件
DecodeRotData用来解码“.scr”的文件
然后重点来了,这两个函数都被封装到SO里了

蛋疼的保护

用IDA打开libChronicleNUtils.so,结果IDA报了个错
QQ截图20150821174551
用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的原代码,但是前面已经用另一种方法实现了,我也懒得再去弄了~
想要已写好的工具的可以看这里
解密锁链战记资源的小工具

超简单的il2cpp游戏修改教程

本文较旧,已不适合参考 锁链战记3.0版本也是换上了il2cpp,所以刚好就用它来写一篇简单的il2cpp修改教程 使用的是日服3.0.1版的锁链战记 首先要使用一款工具...

阅读全文

关于修改锁链战记最后一击为毒伤

日服 2.5.2 上期抽托托莉抽到没石头了,看下了成就还有个最后一击毒伤没做,于是今天就试着改了一下,没想到一下就成功了233 因为sega的优良传统,直...

阅读全文

关于锁链战记的一回合过关

日服 2.5.1 在其他地方已经发过了,这次顺带丢到博客上 我研究过的1w过关有两种方式,其中一种是一开始就是最后一wave,但是因为超过10wave的本从最后...

阅读全文

11 条评论

  1. 你好请问能委托你写这游戏的新解密工具包吗?老的不能用了。很抱歉是不是技术人员只能做伸手党,可以的话请留个联系方式进一步沟通好吗

  2. 请教下,dword_D228这种反编译出来没有值的数是什么意思?不知道该怎么处理. 还有__ROR4__这个函数怎么得到具体算法的? IDA反编译的文件里都没有定义. 难道是通过调试得到的么? 还是就是看逻辑判断的? 谢谢!

    1. 谢谢指点! :mrgreen: 刚开始学用IDA,好多都不懂. 那么如果没猜错, dword_xxxx, unk_xxxx之类的变量只能靠动态调试了吧?

  3. libChronicleNUtils.so文件已经被处理过了

    請問大佬,現在還有機會解密libChronicleNUtils.so 然後拿到DLL 嗎?

    現在可以通過遊戲解數據了,還在想有沒有可能不通過遊戲,直接調用DLL 來解包數據。

    先謝謝了。

    1. libChronicleNUtils.so文件已经被处理过了,section信息被删除了,除非能修复不然静态调试下的伪代码都是错的
      我看了下国服没处理的SO里没有这个函数。比较好的做法就是动态调试然后一行一行去实现

欢迎留言

7 + 0 =