【手游】皇室战争 Clash Royale 美术资源加密分析

0x00 CR的图片资源是在SC文件夹中 一般为XXX_tex.sc

sc文件是一个压缩文件,它是使用了修改的LZMA压缩算法进行压缩的(和老版的COC资源压缩方法类似)

【手游】皇室战争 Clash Royale 美术资源加密分析_第1张图片

标准的LZMA压缩文件的文件头由5+8个字节组成,其中前5个字节中存储了压缩方式,字典大小等信息,后8个字节为压缩前的文件大小;COC所使用的修改后的LZMA算法,其文件头由5+4个字节组成,跟标准算法相比,仅仅是将表示压缩前的文件大小那8个字节,改成了4个字节

如果要使用标准LZMA算法的解压工具能正确解压COC中的资源,只要在第9个字节后面插入4个0字节,

如上图SC文件,其前26个字节是SC文件头信息, 紧接着的13个字节如下:

0x5D 0x00 0x00 0x04 0x00 0x59 0xD9 0x94 0x00 0x00 0x00 0xB1 0xBA

在第9个字节后插入4个0字节,得到如下格式:

0x5D 0x00 0x00 0x04 0x00 0x59 0xD9 0x94 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0xB1 0xBA

然后可以用LZMA类库 进行解压缩


0x01 解压后的文件我们暂且称为scf文件

【手游】皇室战争 Clash Royale 美术资源加密分析_第2张图片

scf文件前5个字节是文件信息,它的结构如下:

类型1 长度1 数据块1
类型2 长度2 数据块2
... ... ...
类型n 长度n 数据块n

其中:类型为1个字节,标识数据块是何类型;长度为4个字节,表示随后的数据块的字节长度。

 

类型1是纹理(texture),类型2是shape,类型3是movie_clip.....这里只研究Tuxture,其他的类型感兴趣的可自己研究

纹理(texture)其数据块结构如下:

纹理格式 纹理宽度 纹理高度 纹理数据

其中:格式为1个字节,宽度为2个字节,高度为2个字节。

格式为0是RGBA8888格式(32位)

格式为2是RGBA4444格式(16位)

格式为4是RGB565格式(16位)

格式为6是LA88格式(16位)


我用Python 写了个提取脚本ExtractRes.py,里面的LA88灰度算法我不是太确定(但影响也不是太大),

用法 python ExtractRes.py xxx/sc (这里的sc是资源文件夹)

注意安装PyLZMA 和 Pillow 这两个库

PyLZMA https://pypi.python.org/pypi/pylzma

Pillow https://pypi.python.org/pypi/Pillow/


# 皇室战争图片资源提取 By:BlueEffie
# 需要安装2个库
# PyLZMA https://pypi.python.org/pypi/pylzma
# Pillow https://pypi.python.org/pypi/Pillow/

import os
import sys
import pylzma
import struct
import PIL.Image

if len(sys.argv) != 2:
    print('Usage: ./ExtractRes.py [SC_Directory]')
    exit(0)


class PixelType:
    rgba8888 = 0
    rgba4444 = 2
    rgb565 = 4
    la88 = 6


def extract_sc_files(path):
    for root, dirs, files in os.walk(path):
        for name in files:
            if name.endswith('.sc'):
                lzma_decompress(root, name)


# 解压缩
def lzma_decompress(path, name):
    data = os.path.join(path, name)
    filename, exc = os.path.splitext(name)
    with open(data, 'rb') as fin:
        fin.seek(26, 0)
        header = fin.read(5)
        raw_size = fin.read(4)
        size = struct.unpack('> 12) & 15) << 4, ((x >> 8) & 15) << 4, ((x >> 4) & 15) << 4, ((x >> 0) & 15) << 4)
        return r, g, b, a
    elif bmp_type == PixelType.rgb565:
        x, = struct.unpack('> 11) & 31) << 3, ((x >> 5) & 63) << 2, (x & 31) << 3
    elif bmp_type == PixelType.la88:
        x, = struct.unpack('


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