Example #1
0
def main():
    import argparse, sys
    arguments = argparse.ArgumentParser()
    arguments.add_argument('--file', '-f', required=True)
    arguments.add_argument('--output', '-o', default='__types')
    options = arguments.parse_args(sys.argv[1:])
    output = p.abspath(options.output)
    if not p.exists(output): os.makedirs(output)
    MONO_BEHAVIOUR_PERSISTENT_ID = 114

    stream = FileStream(file_path=options.file)
    stream.endian = '<'
    while stream.bytes_available:
        persistent_id = stream.read_uint32()
        script_hash = b'0' * 16
        if persistent_id == MONO_BEHAVIOUR_PERSISTENT_ID:
            script_hash = stream.read(16)
        type_hash = stream.read(16)
        size = stream.read_uint32()
        offset = stream.position
        print(persistent_id, uuid.UUID(bytes=script_hash),
              uuid.UUID(bytes=type_hash), size)
        type_tree = MetadataTypeTree(True)
        type_tree.persistent_type_id = persistent_id
        type_tree.type_hash = type_hash
        type_tree.mono_hash = script_hash
        type_tree.decode_type_tree(fs=stream)
        print(type_tree)
        assert stream.position == offset + size
Example #2
0
def main():
    arguments = argparse.ArgumentParser()
    arguments.add_argument('--file', '-f', nargs='+', required=True)
    arguments.add_argument('--command',
                           '-c',
                           choices=Commands.get_option_choices(),
                           default=Commands.dump)
    arguments.add_argument('--debug', '-d', action='store_true')
    arguments.add_argument('--types', '-t', nargs='+', type=int)
    arguments.add_argument('--dump-mono-scripts', '-dms', action='store_true')
    options = arguments.parse_args(sys.argv[1:])
    if options.dump_mono_scripts:
        mono_script_keys = list(mono_scripts.keys())
        mono_script_keys.sort()
        for identifier in mono_script_keys:
            class_name, namespace, assembly = [
                b2s(x) for x in mono_scripts.get(identifier)
            ]
            print('\033[36m{} \033[33m{}::\033[4m{}\033[0m \033[2m{}\033[0m'.
                  format(identifier, namespace if namespace else 'global',
                         class_name, assembly))

    for file_path in options.file:
        print('>>>', file_path)
        archive = UnityArchiveFile(debug=options.debug)
        try:
            stream = archive.decode(file_path=file_path)
            node = archive.direcory_info.nodes[0]
        except:
            stream = FileStream(file_path=file_path)
            node = FileNode()
            node.size = stream.length
        if archive.direcory_info.nodes:
            for node in archive.direcory_info.nodes:
                if node.flags == NodeFlags.SerializedFile:
                    print('[+] {} {:,}'.format(node.path, node.size))
                    stream.endian = '>'
                    serializer = serialize.SerializedFile(debug=options.debug,
                                                          node=node)
                    serializer.decode(stream)
                    collect_mono_scripts(serializer, stream)
                    processs(parameters=locals())
        else:
            serializer = serialize.SerializedFile(debug=options.debug,
                                                  node=node)
            serializer.decode(stream)
            collect_mono_scripts(serializer, stream)
            processs(parameters=locals())
Example #3
0
    def decode(self, fs: FileStream):
        offset = fs.position
        self.persistent_type_id = fs.read_sint32()
        self.is_stripped = fs.read_boolean()
        self.script_index = fs.read_sint16()
        if self.persistent_type_id == MONO_BEHAVIOUR_PERSISTENT_ID:
            self.mono_hash = fs.read(16)
        self.type_hash = fs.read(16)

        self.nodes = []
        self.strings = {}
        if self.type_tree_enabled:
            self.decode_type_tree(fs)
        else:
            cache_path = self.get_cache_path()
            if p.exists(cache_path):
                tmp = FileStream(file_path=cache_path)
                tmp.endian = '<'
                persistent_type_id = tmp.read_sint32()
                assert persistent_type_id == self.persistent_type_id, '{} != {}'.format(
                    persistent_type_id, self.persistent_type_id)
                tmp.seek(fs.position - offset)
                self.decode_type_tree(fs=tmp)
Example #4
0
    def decode(self, fs: FileStream):
        fs.seek(self.node.offset)
        header = self.header
        header.metadata_size = fs.read_sint32()
        header.file_size = fs.read_sint32()
        assert self.node.size == header.file_size, '{} != {}'.format(
            self.node.size, header.file_size)
        header.version = fs.read_sint32()
        header.data_offset = fs.read_sint32()
        header.endianess = fs.read_boolean()
        fs.read(3)  # reserved bytes
        fs.endian = '>' if header.endianess else '<'
        self.print(vars(header))
        self.version = fs.read_string()
        self.platform = fs.read_uint32()
        self.type_tree_enabled = fs.read_boolean()
        self.print('version={} platform={} type_tree_enabled={}'.format(
            self.version, self.platform, self.type_tree_enabled))
        self.type_trees = []
        type_count = fs.read_uint32()
        self.print('type', type_count)
        for _ in range(type_count):
            offset = fs.position
            type_tree = MetadataTypeTree(
                type_tree_enabled=self.type_tree_enabled)
            type_tree.decode(fs)
            if self.type_tree_enabled:
                position = fs.position
                fs.seek(offset)
                type_data = fs.read(position - offset)
                with open(type_tree.get_cache_path(auto_create=True),
                          'wb') as fp:
                    fp.write(type_data)
            self.type_trees.append(type_tree)
            self.register_type_tree(type_tree=type_tree)
            self.print(type_tree)

        object_count = fs.read_sint32()
        self.print('object', object_count)
        for _ in range(object_count):
            fs.align(4)
            obj = ObjectInfo()
            obj.decode(fs)
            type_tree = self.type_trees[obj.type_id]
            obj.name = type_tree.name
            self.objects.append(obj)
            self.print(vars(obj))

        script_type_count = fs.read_sint32()
        self.print('typeinfo', script_type_count)
        for _ in range(script_type_count):
            st = ScriptTypeInfo()
            st.decode(fs)
            self.typeinfos.append(st)
            self.print(vars(st))

        external_count = fs.read_sint32()
        self.print('external', external_count)
        for _ in range(external_count):
            ext = ExternalInfo()
            ext.decode(fs)
            self.externals.append(ext)
            self.print(ext)
        fs.read_string()