Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Question: access object directly with file_id and path_id #41

Closed
Helyos96 opened this issue Mar 30, 2021 · 3 comments
Closed

Question: access object directly with file_id and path_id #41

Helyos96 opened this issue Mar 30, 2021 · 3 comments

Comments

@Helyos96
Copy link

Hi, sorry to use the issues system to ask a question.

I'm using UnityPy to automatically dump stuff, and I've added the ability to automatically dump files referenced by a pptr.
I face two issues however:

  • I don't know how to access an object directly based on its file_id/path_id, so I have to iterate over all objects every time to find it which is unbearably slow. I've browsed UnityPy's code and I'm not sure what I could use to directly access an object knowing its file_id/path_id.
  • There doesn't seem to be support for file_ids ? What I work on unfortunately has objects with same path_id in different asset files (differents file_id) and I don't know how to check for that with UnityPy. I have to currently check only for path_id and hope it's the right file.

Would appreciate any guidance, thanks!

@Helyos96
Copy link
Author

Nevermind, I hadn't looked close enough at the PPtr class and borrowed code from there to resolve an object from file_id+path_id.

@K0lb3
Copy link
Owner

K0lb3 commented Mar 31, 2021

I'm not sure if you already figured it out completely or not,
so I will simply explain some points.

The objects are stored inside of the SerializedFiles, which in turn are usually stored within BundleFiles.
The path_id is the unique identifier of an object within a SerializedFile. In BundleFiles with multiple SerializedFiles it can happen, that multiple of those SerializesFiles use the same path_id, but each for different objects.
So to find a specific object via the path_id you will also have to know the name of its SerializedFile.
Then you can simply search through env.files..files until you reach a SerializedFIle and then check its name and if it contains an object with the specific id.

The pointers themself usually only refer to objects within the same SerializedFile as the object that uses them.
If this isn't the case, then the reference uses the external list of the parent(SerializedFile) of the object and find the specified SerializedFile that way.

@Helyos96
Copy link
Author

Helyos96 commented Apr 1, 2021

Thanks for the additional info! What I ended up doing is something like this:

def get_obj_pptr(env, objref, file_id : int, path_id : int):
	if path_id == 0:
		return None

	manager = None
	if file_id == 0:
		manager = objref.assets_file
	elif file_id > 0 and file_id - 1 < len(objref.assets_file.externals):
		external_name = objref.assets_file.externals[file_id - 1].name
		parent = objref.assets_file.parent
		if parent is not None:
			if external_name not in parent.files:
				external_name = external_name.upper()
			if external_name in parent.files:
				manager = parent.files[external_name]
		else:
			if external_name not in env.files:
				typ, reader = ImportHelper.check_file_type(external_name)
				if typ == FileType.AssetsFile:
					env.files[external_name] = files.SerializedFile(reader)
			if external_name in env.files:
				manager = env.files[external_name]

	if manager and path_id in manager.objects:
		return manager.objects[path_id]
	return None

So pretty much what the PPtr class does but from a setting outside of UnityPy.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants