UnityPack
UnityPack copied to clipboard
Support for UnityWebData1.0 files
The signature on these files is UnityWebData1.0.
These files just appear to contain one or more .unity3d
files, so it would be great to cut out the middle-man of extracting them and then extracting the .unity3d
files.
QuickBMS script for these files:
idstring "UnityWebData1.0\0"
get HEADLEN long
do
get OFF long
get SIZE long
get NAMEZ long
getdstring NAME NAMEZ
log NAME OFF SIZE
savepos i
while i < HEADLEN
python code
from unitypack.utils import BinaryReader
SIGNATURE = 'UnityWebData1.0'
class DataFile:
def load(self, file):
buf = BinaryReader(file, endian="<")
self.path = file.name
self.signature = buf.read_string()
header_length = buf.read_int()
if self.signature != SIGNATURE:
raise NotImplementedError('Invalid signature {}'.format(repr(self.signature)))
self.blobs = []
while buf.tell() < header_length:
offset = buf.read_int()
size = buf.read_int()
namez = buf.read_int()
name = buf.read_string(namez)
self.blobs.append({ 'name': name, 'offset': offset, 'size': size })
if buf.tell() > header_length:
raise NotImplementedError('Read past header length, invalid header')
for blob in self.blobs:
buf.seek(blob['offset'])
blob['data'] = buf.read(blob['size'])
if len(blob['data']) < blob['size']:
raise NotImplementedError('Invalid size or offset, reading past file')
usage:
import os
f = open('data', 'rb')
df = DataFile()
df.load(f)
EXTRACTION_DIR = 'extracted'
for blob in df.blobs:
print('extracting @ {}:\t{} ({})'.format(blob['offset'], blob['name'], blob['size']))
dest = os.path.join(EXTRACTION_DIR, blob['name'])
os.makedirs(os.path.dirname(dest), exist_ok=True)
with open(dest, 'wb') as f:
f.write(blob['data'])
Maybe this is obvious, but once it's extracted, remember to set base_path
to the extracted
dir:
file = open(os.path.join(EXTRACTION_DIR, 'data.unity3d'), 'rb')
env = unitypack.environment.UnityEnvironment(base_path=EXTRACTION_DIR)
bundle = unitypack.load(file, env)
Or start python from the extracted directory, because base_path
defaults to the current directory.
This should be documented, IMO.
Otherwise it won't find the assets referenced from the bundle, i.e.:
KeyError: "No such asset: 'sharedassets0.resource'"