forked from K0lb3/UnityPy
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathrebundle.py
More file actions
138 lines (112 loc) · 3.63 KB
/
Copy pathrebundle.py
File metadata and controls
138 lines (112 loc) · 3.63 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
"""
This script shows how to create a bundle from dumped assets from the memory.
The dumped assets consist of SerializedFiles and their resources(cabs).
A sample file of the original game is required for this script.
This example uses the globalgamemanager as this asset should exist in all Unity games.
"""
import os
import uuid
import random
from copy import copy
import re
import UnityPy
from UnityPy.enums import ClassIDType
from UnityPy.files import BundleFile
from UnityPy.files.SerializedFile import FileIdentifier, ObjectReader, SerializedType
SERIALIZED_PATH = "globalgamemanagers"
DATA_PATH = os.path.join(os.path.dirname(os.path.realpath(__file__)), "data")
def main():
bf = Fake(
signature="UnityFS",
version=6,
format=6,
version_engine="2017.4.30f1",
version_player="5.x.x",
_class=BundleFile,
files={},
)
# load default serialized file and prepare some variables for easier access to key objects
env = UnityPy.load(SERIALIZED_PATH)
sf = env.file # serialized file
or_bp = list(sf.objects.values())[0].__dict__ # object data
bf.files["serialized_file"] = sf
sf._flag = 4
# remove all unnesessary stuff
for key in list(sf.objects.keys()):
del sf.objects[key]
sf.externals = []
# add all files from DATA_PATH
for root, dirs, files in os.walk(DATA_PATH):
for f in files:
fp = os.path.join(root, f)
if f[:3] == "CAB":
add_cab(bf, sf, root, f)
else:
add_object(sf, fp, or_bp)
# save edited bundle
open("bundle_edited.unity3d", "wb").write(bf.save())
def add_cab(bf, sf, root, f):
fp = os.path.join(root, f)
bf.files[f] = Fake(data=open(fp, "rb").read(), _flag=4)
sf.externals.append(
Fake(
temp_empty="",
guid=generate_16_byte_uid(),
path=f"archive:/{os.path.basename(root)}/{f}",
type=0,
_class=FileIdentifier,
)
)
def add_object(sf, fp, or_bp):
# get correct type id
path_id, class_name = os.path.splitext(os.path.basename(fp))
path_id = int(path_id) if re.match(
r"^\d+$", path_id) else generate_path_id(sf.objects)
class_id = getattr(
ClassIDType, class_name[1:], ClassIDType.UnknownType).value
type_id = -1
for i, styp in enumerate(sf.types):
if styp.class_id == class_id:
type_id = i
if type_id == -1: # not found, add type
type_id = len(sf.types)
sf.types.append(
Fake(
class_id=class_id,
is_stripped_type=False,
node=[],
script_type_index=-1,
old_type_hash=generate_16_byte_uid(),
_class=SerializedType,
)
)
# add new object
odata = copy(or_bp)
odata.update(
{
"data": open(fp, "rb").read(),
"path_id": generate_path_id(sf.objects),
"class_id": class_id,
"type_id": type_id,
}
)
sf.objects[path_id] = Fake(**odata, _class=ObjectReader)
def generate_path_id(objects):
while True:
uid = random.randint(-(2 ** 16), 2 ** 16 - 1)
if uid not in objects:
return uid
def generate_16_byte_uid():
return uuid.uuid1().urn[-16:].encode("ascii")
class Fake(object):
"""
fake class for easy class creation without init call
"""
def __init__(self, **kwargs):
self.__dict__.update(kwargs)
if "_class" in kwargs:
self.__class__ = kwargs["_class"]
def save(self):
return self.data
if __name__ == "__main__":
main()