K0lb3 / UnityPy

UnityPy is python module that makes it possible to extract/unpack and edit Unity assets
MIT License
771 stars 114 forks source link

node.m_IsArray should be a byte instead of boolean #142

Closed khronii closed 1 year ago

khronii commented 1 year ago

https://github.com/K0lb3/UnityPy/blob/d1f9f9755be9447148219edefde7126e032d5c63/UnityPy/files/SerializedFile.py#L594

While I was investigating why repacking bundle fails even without modification, I found out that node.m_IsArray is sometimes not 0 or 1 but a multiple of 2 (or so I guess). So far I found 2,4 and 8 can exist.

image (Sorry for the poorly edited image)

K0lb3 commented 1 year ago

You're right, m_IsArray is actually an int. Thanks for figuring out this issue, I will patch it in a bit.

K0lb3 commented 1 year ago

Actually, m_IsArray is only an int for old Unity versions, it's a boolean for all other versions.

See

https://github.com/K0lb3/UnityPy/blob/d1f9f9755be9447148219edefde7126e032d5c63/UnityPy/files/SerializedFile.py#L350

or as comparison

https://github.com/Perfare/AssetStudio/blob/32ce0326550a0db2b181cbfc408214cf9f0b8121/AssetStudio/SerializedFile.cs#L316

The simplification at https://github.com/K0lb3/UnityPy/blob/d1f9f9755be9447148219edefde7126e032d5c63/UnityPy/files/SerializedFile.py#L335 might actually be incorrect though.

khronii commented 1 year ago

Using AssetStudio says it is built with 2021.2.10f1 (doesn't sound that old and UnityPy parses it with *_blob variant) so maybe it's now int again? Just guessing.

I don't think reverting it to int would be harmful by the way.

K0lb3 commented 1 year ago

Writing it as int at the place you marked wouldn't work, but byte would. (int - 4 bytes, byte - 1 byte, boolean - 1 byte) And apparently, AssetStudio also made it work like that....looks like my browser was kinda weird displaying an old file.

K0lb3 commented 1 year ago

Can you try the linked branch and see if it works for you?

khronii commented 1 year ago

Writing it as int at the place you marked wouldn't work, but byte would.

Seems like I mentioned that on a title and immediately forgot about it since github logs title change and there's no log that changed the title before I added a dot for a test.

Can you try the linked branch and see if it works for you?

After testing the original pip package, it looks like ignoring the fact it contains non-boolean values does not cause any crash. So I have to change the source code to spit out raw data again if I have to confirm your changes.

And something to mention : I did make my own homebrew patch directly on the source file

type = f"{reader.endian}hbbIIiii" #L350
writer.write_byte(node.m_IsArray) #L594

and that preserved the aforementioned data well. I should find out what this flag is for though.

khronii commented 1 year ago

I should find out what this flag is for though.

image image

khronii commented 1 year ago

So, about the crash that caused by editing (nothing) via UnityPy, turns out that it was not related to this loss of data. It was because Unity checked CRC of the file (actually, the contents of BundleFile) I was editing, and that CRC data was included in catalog.json, under "m_ExtraDataString". It would be nice if UnityPy can handle catalog.json, too. Should I open another issue about this?

Link to where I found this information

K0lb3 commented 1 year ago

I'm actually already working on a catalog parser and am more or less done with it. I will add it at the weekend to UnityPy.tools.

khronii commented 1 year ago

I'm actually already working on a catalog parser and am more or less done with it. I will add it at the weekend to UnityPy.tools.

Sounds great!

khronii commented 1 year ago

image

I just found out that you bumped the version to 1.9.18 and confirmed #144 does fix this issue. Thank you for working on this!

7aGiven commented 1 year ago

I'm actually already working on a catalog parser and am more or less done with it. I will add it at the weekend to UnityPy.tools.

How can I find the parser in UnityPy.tools?