Beispiel #1
0
def decrypt_data1_with_decrypt_buf(
    decrypt_buf: bytearray, data: bytearray, game_key1=0
):
    result = bytearray()
    e = 0x76548AEF
    decrypt_index = 0
    for i in range(len(data) >> 2):
        b = int.from_bytes(
            decrypt_buf[decrypt_index * 4 : (decrypt_index * 4) + 4], "little"
        )
        b ^= int.from_bytes(data[i * 4 : (i * 4) + 4], "little")
        b = wrapping_sub(b, 0x4A91C262)
        b = rol(b, 3, 32)
        b = wrapping_sub(b, e)
        result += b.to_bytes(4, "little")

        decrypt_index += 1
        decrypt_index &= 3
        a = game_key1 ^ 0x10FB562A  # If game_key is 0 a is just constant
        e = wrapping_add(e, a)

    for i in range(len(data) & 3, 0, -1):
        index = len(data) - i
        b = int.from_bytes(
            decrypt_buf[decrypt_index * 4 : (decrypt_index * 4) + 4], "little"
        )
        b >>= 6
        b = (b & 0xFF) ^ data[index]
        b = wrapping_add(b, 0x37)
        result += b.to_bytes(1, "little")

        decrypt_index += 1
        decrypt_index &= 3

    return result
Beispiel #2
0
def decrypt_data2_with_decrypt_buf(
    decrypt_buf: bytearray, data: bytearray, game_key2=0
):
    result = bytearray()
    e = 0x2A65CB4F
    decrypt_index = 0
    for i in range(len(data) >> 2):
        b = int.from_bytes(
            decrypt_buf[decrypt_index * 4 : (decrypt_index * 4) + 4], "little"
        )
        b ^= int.from_bytes(data[i * 4 : (i * 4) + 4], "little")
        b = wrapping_sub(b, e)
        b = rol(b, 2, 32)
        b = wrapping_add(b, 0x37A19E8B)
        result += b.to_bytes(4, "little")

        decrypt_index += 1
        decrypt_index &= 3
        a = game_key2 ^ 0x139FA9B  # If game_key is 0 a is just constant
        e = wrapping_sub(e, a)

    for i in range(len(data) & 3, 0, -1):
        index = len(data) - i
        b = int.from_bytes(
            decrypt_buf[decrypt_index * 4 : (decrypt_index * 4) + 4], "little"
        )
        b >>= 4
        b = (b & 0xFF) ^ data[index]
        b = wrapping_add(b, 0x3)
        result += b.to_bytes(1, "little")

        decrypt_index += 1
        decrypt_index &= 3

    return result
Beispiel #3
0
 def __set_buffers(self):
     return [
         self.__C ^ 0x53A76D2E,
         wrapping_add(self.__B, 0x5BB17FDA),
         wrapping_add(self.__A, 0x6853E14D),
         self.__D ^ 0xF5C6A9A3,
     ]
Beispiel #4
0
def get_file_key(file, archive_data, header, game_key3=0, game_key4=0):
    file_key = file.file_decrypt_key
    file_key = wrapping_add(file_key, archive_data.file_decrypt_key)
    file_key ^= header.archive_data_key_decrypted
    file_key = wrapping_add(file_key, header.archive_data_entry_count_decrypted)
    file_key ^= game_key4
    file_key = wrapping_sub(file_key, 0x5C39E87B)
    file_key ^= wrapping_add(
        wrapping_add(
            (ror(header.file_decrypt_key_decrypted, 5, 32) * 0x7DA8F173), 0x13712765,
        ),
        game_key3,
    )
    return file_key
Beispiel #5
0
def init_decrypt_table(key1: int, key2: int):
    table = bytearray()
    for i in range(0x100):
        table += i.to_bytes(1, "little")
    v = key1
    for i in range(0x100):
        x = v
        x >>= 0x10
        x &= 0xFF
        y = table[x]
        z = table[v & 0xFF]
        table[v & 0xFF] = y
        table[x] = z

        z = v
        z >>= 8
        z &= 0xFF

        x = v
        x >>= 0x18
        y = table[x]
        v = ror(v, 2, 32)
        v = (v * 0x1A74F195) & 0xFFFFFFFF
        v = wrapping_add(v, key2)
        a = table[z]
        table[z] = y
        table[x] = a
    return table
Beispiel #6
0
def decrypt_file(
    file_contents: bytearray,
    file_size: int,
    md5_cpz7: bytearray,
    key: int,
    decrypt_table: bytearray,
    password: bytearray,
):
    contents_index = 0
    result = bytearray()
    decrypt_buf = bytearray()  # could need static size
    decrypt_buf2 = bytearray()
    v = int.from_bytes(md5_cpz7[4:8], "little") >> 2
    for b in password:
        decrypt_buf += (decrypt_table[b] ^ (v & 0xFF)).to_bytes(1, "little")
    for chunk in chunks(decrypt_buf, 4):
        decrypt_buf2 += (int.from_bytes(chunk, "little") ^ key).to_bytes(4, "little")
    c = 0x2748C39E
    a = 0x0A
    dx = key
    for i in range(file_size >> 2):
        b = int.from_bytes(decrypt_buf2[a * 4 : (a * 4) + 4], "little") >> 1
        d = (c >> 6) & 0xF
        b ^= int.from_bytes(decrypt_buf2[d * 4 : (d * 4) + 4], "little")
        b ^= int.from_bytes(
            file_contents[contents_index : contents_index + 4], "little"
        )
        b = wrapping_sub(b, dx)
        dx = c & 3
        b ^= int.from_bytes(md5_cpz7[dx * 4 : (dx * 4) + 4], "little")
        dx = key
        sys.exit(0)
        result += b.to_bytes(4, "little")

        c = wrapping_add(c, wrapping_add(key, b))
        a += 1
        a &= 0xF
        contents_index += 4

    for i in range(file_size & 3):
        c = file_contents[contents_index] ^ 0xAE
        result += decrypt_table[c].to_bytes(1, "little")

        contents_index += 1

    return result
Beispiel #7
0
def decrypt_data2(
    data1: bytearray,
    data2: bytearray,
    count: int,
    decrypt_table: bytearray,
    data2_size: int,
    md5_cpz7: bytearray,
    game_key2=0,
):
    result = bytearray()
    previous_data = data1
    for i in range(count):
        offset = int.from_bytes(previous_data[8:12], "little")
        size = data2_size
        next_data = previous_data[int.from_bytes(previous_data[0:4], "little") :]
        if i < count - 1:
            size = int.from_bytes(next_data[8:12], "little")
        size -= offset

        internal_data2 = decrypt_data_with_decrypt_table(
            decrypt_table, data2[offset:], size, 0x7E
        )
        key = int.from_bytes(previous_data[12:16], "little")
        decrypt_buf2 = (
            (int.from_bytes(md5_cpz7[0:4], "little") ^ key).to_bytes(4, "little")
            + (
                int.from_bytes(md5_cpz7[4:8], "little") ^ wrapping_add(key, 0x11003322)
            ).to_bytes(4, "little")
            + (int.from_bytes(md5_cpz7[8:12], "little") ^ key).to_bytes(4, "little")
            + (
                int.from_bytes(md5_cpz7[12:16], "little")
                ^ wrapping_add(key, 0x34216785)
            ).to_bytes(4, "little")
        )
        internal_data2 = decrypt_data2_with_decrypt_buf(
            decrypt_buf2, internal_data2, game_key2
        )
        previous_data = next_data
        result += internal_data2

    return result
Beispiel #8
0
def decrypt_file_entries(file_entries, file_entry_key, key):
    decrypted_file_entries = bytearray()
    for chunk in chunks(file_entries, 4):
        file_entry_key ^= key
        d = wrapping_add(file_entry_key, file_entry_key)
        d ^= file_entry_key
        c = file_entry_key
        c >>= 1
        d = wrapping_add(d, d)
        c ^= file_entry_key
        d = wrapping_add(d, d)
        c >>= 3
        d = wrapping_add(d, d)
        c ^= d
        file_entry_key ^= c
        decrypted_file_entries += (int.from_bytes(chunk, "little")
                                   ^ file_entry_key).to_bytes(4, "little")
    result = list()
    for chunk in chunks(decrypted_file_entries, 12):
        result.append(EscArc2.FileEntry.from_bytes(chunk))
    return result
Beispiel #9
0
def extract_file(filename):
    arc = EscArc2.from_file(filename)
    archive_file = open(filename, "rb")
    unk1 = arc.unk1
    file_count = arc.file_count

    unk1 ^= arc.key
    file_name_table_size = ((unk1 >> 1) ^ unk1) >> 3
    d = wrapping_add(unk1, unk1) ^ unk1
    d = wrapping_add(d, d)
    d = wrapping_add(d, d)
    d = wrapping_add(d, d)
    file_name_table_size ^= d ^ unk1
    file_count ^= file_name_table_size
    file_name_table_size ^= arc.key
    unk1 = (wrapping_add(file_name_table_size, file_name_table_size)
            ^ file_name_table_size)
    unk1 = wrapping_add(unk1, unk1)
    unk1 = wrapping_add(unk1, unk1)
    unk1 = wrapping_add(unk1, unk1)
    file_entry_key = ((file_name_table_size >> 1) ^ file_name_table_size) >> 3
    file_entry_key ^= unk1 ^ file_name_table_size
    file_name_table_size = arc.unk2 ^ file_entry_key
    file_count_in_bytes = file_count * arc.file_entry_size

    archive_file.seek(20)
    file_entries = decrypt_file_entries(archive_file.read(file_count_in_bytes),
                                        file_entry_key, arc.key)
    file_names = archive_file.read(file_name_table_size)

    for file in file_entries:
        name = str(file_names[file.file_name_table_offset:].split(b"\x00")[0],
                   "sjis").replace("\\", "/")
        print(
            name,
            file.file_name_table_offset,
            file.file_offset,
            file.file_size,
        )
        archive_file.seek(file.file_offset)
        d = archive_file.read(file.file_size)
        os.makedirs(os.path.dirname("ext/" + name), exist_ok=True)
        output_file = open(
            "ext/" + name,
            "wb",
        )
        output_file.write(d)
        output_file.close()

    return
Beispiel #10
0
def extract_file(filename, game_data):
    cpz = Cpz7.from_file(filename)
    data3 = decrypt_data3(
        cpz.encryption_data.data, cpz.encryption_data.data_size, cpz.encryption_data.key
    )
    data = xor_with_data3(
        cpz.raw_data[
            : cpz.header.archive_data_size_decrypted
            + cpz.header.file_data_size_decrypted
        ],
        data3,
    )
    data = decrypt_using_password(
        data,
        cpz.header.archive_data_size_decrypted + cpz.header.file_data_size_decrypted,
        PASSWORD,
        cpz.header.archive_data_key_decrypted ^ 0x3795B39A,
    )
    md5_cpz7 = md5cpz7.md5(cpz.header.cpz7_md5).digest()
    decrypt_table = init_decrypt_table(
        cpz.header.archive_data_key_decrypted, int.from_bytes(md5_cpz7[4:8], "little")
    )
    data1 = decrypt_data_with_decrypt_table(
        decrypt_table,
        data[: cpz.header.archive_data_size_decrypted],
        cpz.header.archive_data_size_decrypted,
        0x3A,
    )
    decrypt_buf = (
        (
            wrapping_add(cpz.header.archive_data_key_decrypted, 0x76A3BF29)
            ^ int.from_bytes(md5_cpz7[0:4], "little")
        ).to_bytes(4, "little")
        + (
            cpz.header.archive_data_key_decrypted
            ^ int.from_bytes(md5_cpz7[4:8], "little")
        ).to_bytes(4, "little")
        + (
            wrapping_add(cpz.header.archive_data_key_decrypted, 0x1000_0000)
            ^ int.from_bytes(md5_cpz7[8:12], "little")
        ).to_bytes(4, "little")
        + (
            cpz.header.archive_data_key_decrypted
            ^ int.from_bytes(md5_cpz7[12:16], "little")
        ).to_bytes(4, "little")
    )
    data1 = decrypt_data1_with_decrypt_buf(decrypt_buf, data1, game_data[0])
    data2 = data[
        cpz.header.archive_data_size_decrypted : cpz.header.archive_data_size_decrypted
        + cpz.header.file_data_size_decrypted
    ]
    decrypt_table2 = init_decrypt_table(
        cpz.header.archive_data_key_decrypted, int.from_bytes(md5_cpz7[8:12], "little")
    )
    data2 = decrypt_data2(
        data1,
        data2,
        cpz.header.archive_data_entry_count_decrypted,
        decrypt_table2,
        cpz.header.file_data_size_decrypted,
        md5_cpz7,
        game_data[1],
    )
    decrypt_table3 = init_decrypt_table(
        int.from_bytes(md5_cpz7[12:16], "little"), cpz.header.archive_data_key_decrypted
    )
    archive_data = []
    index = 0
    for i in range(cpz.header.archive_data_entry_count_decrypted):
        entry = cpz.ArchiveDataEntry.from_bytes(data1[index:])
        index += entry.entry_size
        archive_data.append(entry)

    files = {}
    index = 0
    for d in archive_data:
        files[d] = list()
        for i in range(d.file_count):
            file = cpz.FileEntry.from_bytes(data2[index:])
            index += file.entry_size
            files[d].append(file)

    for archive_data, file_list in files.items():
        for file in file_list:
            print(file.file_name)
            contents = cpz.raw_file_data[file.offset : file.offset + file.file_size]
            file_key = get_file_key(
                file, archive_data, cpz.header, game_data[2], game_data[3],
            )
            f_decrypted = decrypt_file(
                contents, file.file_size, md5_cpz7, file_key, decrypt_table3, PASSWORD,
            )
            f = open("ext/" + str(file.file_name.split(b"\x00")[0], "ascii"), "wb")
            f.write(f_decrypted)
            f.close()
Beispiel #11
0
def decompress(src, dest_len):
    src_index = 0
    dest_index = 0
    dest = bytearray(dest_len)
    b = 0
    c = 0
    s = 0
    var_4 = 0
    var_8 = 0
    var_c = 0
    while True:
        while True:
            c >>= 1
            if c <= 0xFFFF:
                c = src[src_index] | (wrapping_shl(
                    (src[src_index + 1] | 0xFFFF_FF00), 8))
                src_index += 2
            if c & 1 == 0:
                break
            dest[dest_index] = src[src_index]
            src_index += 1
            dest_index += 1

        c >>= 1
        if c <= 0xFFFF:
            c = src[src_index] | (wrapping_shl(
                (src[src_index + 1] | 0xFFFF_FF00), 8))
            src_index += 2

        if c & 1 == 0:
            c >>= 1
            b = 2
            var_c = b
            if c <= 0xFFFF:
                c = src[src_index] | wrapping_shl(
                    (src[src_index + 1] | 0xFFFF_FF00), 8)
                src_index += b

            if c & 1 == 0:
                s = src[src_index] + 1
                src_index += 1
                if s == 256:
                    return dest
            else:
                c >>= 1
                if c <= 0xFFFF:
                    c = src[src_index] | wrapping_shl(
                        (src[src_index + 1] | 0xFFFF_FF00), 8)
                    src_index += 2
                d = wrapping_shl((c & 1), 10)
                c >>= 1
                if c <= 0xFFFF:
                    c = src[src_index] | wrapping_shl(
                        (src[src_index + 1] | 0xFFFF_FF00), 8)
                    src_index += 2
                a = wrapping_shl((c & 1), 9)
                c >>= 1
                d |= a
                if c <= 0xFFFF:
                    c = src[src_index] | wrapping_shl(
                        (src[src_index + 1] | 0xFFFF_FF00), 8)
                    src_index += 2
                s = wrapping_add(((wrapping_shl(
                    (c & 1), 8) | src[src_index]) | d), 256)
                src_index += 1
        else:
            c >>= 1
            d = 1
            if c <= 0xFFFF:
                c = src[src_index] | wrapping_shl(
                    (src[src_index + 1] | 0xFFFF_FF00), 8)
                src_index += 2
            s = c
            c >>= 1
            s &= d
            if c <= 0xFFFF:
                c = src[src_index] | wrapping_shl(
                    (src[src_index + 1] | 0xFFFF_FF00), 8)
                src_index += 2
            if c & 1 == 0:
                c >>= 1
                d = 513
                if c <= 0xFFFF:
                    c = src[src_index] | wrapping_shl(
                        (src[src_index + 1] | 0xFFFF_FF00), 8)
                    src_index += 2
                if c & 1 == 0:
                    c >>= 1
                    d = 1025
                    if c <= 0xFFFF:
                        c = src[src_index] | wrapping_shl(
                            (src[src_index + 1] | 0xFFFF_FF00), 8)
                        src_index += 2
                    a = c & 1
                    c >>= 1
                    s = wrapping_add(s, s)
                    s |= a
                    if c <= 0xFFFF:
                        c = src[src_index] | wrapping_shl(
                            (src[src_index + 1] | 0xFFFF_FF00), 8)
                        src_index += 2
                    if c & 1 == 0:
                        c >>= 1
                        d = 2049
                        if c <= 0xFFFF:
                            c = src[src_index] | wrapping_shl(
                                (src[src_index + 1] | 0xFFFF_FF00), 8)
                            src_index += 2
                        a = c & 1
                        c >>= 1
                        s = wrapping_add(s, s)
                        s |= a
                        if c <= 0xFFFF:
                            c = src[src_index] | wrapping_shl(
                                (src[src_index + 1] | 0xFFFF_FF00), 8)
                            src_index += 2
                        if c & 1 == 0:
                            c >>= 1
                            d = 4097
                            if c <= 0xFFFF:
                                c = src[src_index] | wrapping_shl(
                                    (src[src_index + 1] | 0xFFFF_FF00), 8)
                                src_index += 2
                            s = wrapping_add(s, s)
                            s |= c & 1

            s = wrapping_shl(s, 8) | src[src_index]
            src_index += 1
            c >>= 1
            s = wrapping_add(s, d)
            var_4 = src_index
            if c <= 0xFFFF:
                c = src[src_index] | wrapping_shl(
                    (src[src_index + 1] | 0xFFFF_FF00), 8)
                src_index += 2
                var_4 = src_index

            b = 3
            if c & 1 == 0:
                c >>= 1
                if c <= 0xFFFF:
                    c = src[src_index] | (wrapping_shl(
                        (src[src_index + 1] | 0xFFFF_FF00), 8))
                    src_index += 2
                    var_4 = src_index
                b = 4
                if c & 1 == 0:
                    c >>= 1
                    if c <= 0xFFFF:
                        c = src[src_index] | wrapping_shl(
                            (src[src_index + 1] | 0xFFFF_FF00), 8)
                        src_index += 2
                        var_4 = src_index
                    b = 5
                    if c & 1 == 0:
                        c >>= 1
                        if c <= 0xFFFF:
                            c = src[src_index] | wrapping_shl(
                                (src[src_index + 1] | 0xFFFF_FF00), 8)
                            src_index += 2
                            var_4 = src_index
                        b = 6
                        if c & 1 == 0:
                            c >>= 1
                            var_8 = c
                            if c <= 0xFFFF:
                                c = src[src_index] | wrapping_shl(
                                    (src[src_index + 1] | 0xFFFF_FF00), 8)
                                src_index += 2
                                var_8 = c
                                var_4 = src_index
                            if c & 1 == 0:
                                a, var_4, var_8 = some_fn(var_4, var_8, src)
                                if a == 0:
                                    d, var_4, var_8 = some_fn(
                                        var_4, var_8, src)
                                    d = wrapping_shl(d, 2)
                                    a, var_4, var_8 = some_fn(
                                        var_4, var_8, src)
                                    a = wrapping_add(a, a)
                                    d |= a
                                    a, var_4, var_8 = some_fn(
                                        var_4, var_8, src)
                                    src_index = var_4
                                    b = a | d
                                    b = wrapping_add(b, 9)
                                else:
                                    src_index = var_4 + 1
                                    b = src[src_index - 1] + 17
                            else:
                                a, var_4, var_8 = some_fn(var_4, var_8, src)
                                src_index = var_4
                                if a == 0:
                                    b = 7
                                else:
                                    b = 8
                            c = var_8
            var_c = b

        d = dest_index
        d -= s
        var_8 = b
        for _ in range(b):
            dest[d + s] = dest[d]
            d += 1
        if b != 0:
            b = var_c
        dest_index += b