Cnass commited on
Commit
debb79d
·
verified ·
1 Parent(s): 5dc6044

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +96 -116
app.py CHANGED
@@ -20,168 +20,148 @@ app.add_middleware(
20
  )
21
 
22
  @app.post("/generate_dll")
23
- async def generate_dll(
24
- binary_file: UploadFile = File(...),
25
- metadata_file: UploadFile = File(...)
26
- ):
27
  temp_dir = tempfile.mkdtemp()
28
  binary_path = os.path.join(temp_dir, binary_file.filename)
29
  metadata_path = os.path.join(temp_dir, metadata_file.filename)
30
-
31
  with open(binary_path, "wb") as f: f.write(await binary_file.read())
32
  with open(metadata_path, "wb") as f: f.write(await metadata_file.read())
33
-
34
  output_dir = os.path.join(temp_dir, "output")
35
  os.makedirs(output_dir, exist_ok=True)
36
-
37
- config_path = "/app/dumper/config.json"
38
- if os.path.exists(config_path):
39
- try:
40
- with open(config_path, "r") as f: config_data = f.read()
41
- config_data = config_data.replace('"RequireAnyKey": true', '"RequireAnyKey": false')
42
- with open(config_path, "w") as f: f.write(config_data)
43
- except Exception: pass
44
-
45
- try:
46
- subprocess.run(["/app/dumper/Il2CppDumper", binary_path, metadata_path, output_dir], capture_output=True)
47
- except subprocess.CalledProcessError: pass
48
-
49
- dummy_dll_dir_1 = os.path.join(output_dir, "DummyDll")
50
- dummy_dll_dir_2 = os.path.join(output_dir, "DummyDlls")
51
- target_dir = dummy_dll_dir_1 if os.path.exists(dummy_dll_dir_1) else dummy_dll_dir_2
52
-
53
- if os.path.exists(target_dir):
54
- zip_path = os.path.join(temp_dir, "DummyDlls.zip")
55
- with zipfile.ZipFile(zip_path, 'w', zipfile.ZIP_DEFLATED) as zipf:
56
- for root, _, files in os.walk(target_dir):
57
- for file in files:
58
- if file.endswith(".dll"):
59
- file_path = os.path.join(root, file)
60
- zipf.write(file_path, arcname=file)
61
- return FileResponse(zip_path, media_type="application/zip", filename="DummyDlls.zip")
62
- else:
63
- return {"error": "İşlem başarısız.", "details": "DLL klasörü bulunamadı."}
64
 
65
  @app.post("/extract")
66
- async def extract_dialogues(
67
- file: UploadFile = File(...),
68
- assembly_file: Optional[UploadFile] = File(None)
69
- ):
70
  temp_dir = tempfile.mkdtemp()
71
  asset_path = os.path.join(temp_dir, file.filename)
72
  with open(asset_path, "wb") as f: f.write(await file.read())
73
 
74
  env = UnityPy.load(asset_path)
75
-
76
- # EĞER KULLANICI DUMMYDLLS.ZIP YÜKLEDİYSE:
77
- if assembly_file:
78
- assembly_path = os.path.join(temp_dir, assembly_file.filename)
79
- with open(assembly_path, "wb") as f: f.write(await assembly_file.read())
80
-
81
- dummy_dll_dir = os.path.join(temp_dir, "ExtractedDlls")
82
- os.makedirs(dummy_dll_dir, exist_ok=True)
83
-
84
- if assembly_file.filename.endswith(".zip"):
85
- with zipfile.ZipFile(assembly_path, 'r') as zipf:
86
- zipf.extractall(dummy_dll_dir)
87
- else:
88
- # Sadece tek bir DLL dosyasıysa onu da klasöre kopyala
89
- import shutil
90
- shutil.copy2(assembly_path, os.path.join(dummy_dll_dir, assembly_file.filename))
91
-
92
- # İŞTE EKSİK OLAN O ALTIN KOD: TYPE TREE GENERATOR API
93
- try:
94
- from UnityPy.helpers.TypeTreeGenerator import TypeTreeGenerator
95
- # Çıkartılan tüm DLL'lerin olduğu klasörü API'ye gösteriyoruz.
96
- env.typetree_generator = TypeTreeGenerator(dummy_dll_dir)
97
- except Exception as e:
98
- pass
99
-
100
  zip_filename = os.path.join(temp_dir, f"{file.filename}_dialogues.zip")
101
  extracted_count = 0
102
- log_content = ["=== UNITYPY İŞLEM RAPORU ==="]
103
 
104
  with zipfile.ZipFile(zip_filename, 'w', zipfile.ZIP_DEFLATED) as zipf:
105
  for obj in env.objects:
106
  if obj.type.name in ["TextAsset", "MonoBehaviour"]:
107
- log_content.append(f"\nBulundu: {obj.type.name} (ID: {obj.path_id})")
 
108
  try:
109
  data = obj.read()
110
- file_name = getattr(data, "name", f"{obj.type.name}_{obj.path_id}")
111
- if obj.type.name == "TextAsset":
112
- content = data.text.encode('utf-8')
113
- zipf.writestr(f"{file_name}.txt", content)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
114
  extracted_count += 1
115
- log_content.append(f" -> Başarılı: {file_name}.txt oluşturuldu.")
116
- elif obj.type.name == "MonoBehaviour":
117
- tree = obj.read_typetree()
118
- if tree:
119
- zipf.writestr(f"{file_name}.json", json.dumps(tree, indent=4).encode('utf-8'))
120
- extracted_count += 1
121
- log_content.append(f" -> Başarılı: {file_name}.json oluşturuldu.")
122
- else:
123
- log_content.append(" -> Atlandı: TypeTree okunamadı.")
124
- except Exception as e:
125
- log_content.append(f" -> HATA: {str(e)}")
126
 
127
- if extracted_count == 0: log_content.append("\nSONUÇ: Çıkarılabilir metin bulunamadı.")
128
  zipf.writestr("islem_raporu.txt", "\n".join(log_content).encode('utf-8'))
129
 
130
  return FileResponse(zip_filename, media_type="application/zip", filename=f"{file.filename}_dialogues.zip")
131
 
132
  @app.post("/repack")
133
- async def repack_dialogues(
134
- asset_file: UploadFile = File(...),
135
- mod_zip: UploadFile = File(...),
136
- assembly_file: Optional[UploadFile] = File(None)
137
- ):
138
  temp_dir = tempfile.mkdtemp()
139
  asset_path = os.path.join(temp_dir, asset_file.filename)
140
  zip_path = os.path.join(temp_dir, mod_zip.filename)
141
-
142
  with open(asset_path, "wb") as f: f.write(await asset_file.read())
143
  with open(zip_path, "wb") as f: f.write(await mod_zip.read())
144
 
145
  env = UnityPy.load(asset_path)
146
 
147
- if assembly_file:
148
- assembly_path = os.path.join(temp_dir, assembly_file.filename)
149
- with open(assembly_path, "wb") as f: f.write(await assembly_file.read())
150
-
151
- dummy_dll_dir = os.path.join(temp_dir, "ExtractedDlls")
152
- os.makedirs(dummy_dll_dir, exist_ok=True)
153
-
154
- if assembly_file.filename.endswith(".zip"):
155
- with zipfile.ZipFile(assembly_path, 'r') as zipf:
156
- zipf.extractall(dummy_dll_dir)
157
- else:
158
- import shutil
159
- shutil.copy2(assembly_path, os.path.join(dummy_dll_dir, assembly_file.filename))
160
-
161
- try:
162
- from UnityPy.helpers.TypeTreeGenerator import TypeTreeGenerator
163
- env.typetree_generator = TypeTreeGenerator(dummy_dll_dir)
164
- except Exception as e:
165
- pass
166
-
167
  with zipfile.ZipFile(zip_path, 'r') as zipf:
168
  for file_info in zipf.infolist():
169
  filename = file_info.filename
170
  if filename == "islem_raporu.txt": continue
171
  content = zipf.read(filename)
 
172
  for obj in env.objects:
 
173
  try:
174
- data = obj.read()
175
- obj_name = getattr(data, "name", f"{obj.type.name}_{obj.path_id}")
176
- if obj.type.name == "TextAsset" and filename == f"{obj_name}.txt":
 
 
 
177
  data.text = content.decode('utf-8')
178
  data.save()
179
- break
180
- elif obj.type.name == "MonoBehaviour" and filename == f"{obj_name}.json":
181
- tree = json.loads(content.decode('utf-8'))
182
- obj.save_typetree(tree)
183
- break
184
- except: pass
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
185
 
186
  output_path = os.path.join(temp_dir, f"repacked_{asset_file.filename}")
187
  with open(output_path, "wb") as f: f.write(env.file.save())
 
20
  )
21
 
22
  @app.post("/generate_dll")
23
+ async def generate_dll(binary_file: UploadFile = File(...), metadata_file: UploadFile = File(...)):
24
+ # Bu adımı değiştirmedik, DummyDll üretmek isteyenler için sağlam duruyor
 
 
25
  temp_dir = tempfile.mkdtemp()
26
  binary_path = os.path.join(temp_dir, binary_file.filename)
27
  metadata_path = os.path.join(temp_dir, metadata_file.filename)
 
28
  with open(binary_path, "wb") as f: f.write(await binary_file.read())
29
  with open(metadata_path, "wb") as f: f.write(await metadata_file.read())
 
30
  output_dir = os.path.join(temp_dir, "output")
31
  os.makedirs(output_dir, exist_ok=True)
32
+ subprocess.run(["/app/dumper/Il2CppDumper", binary_path, metadata_path, output_dir], capture_output=True)
33
+ zip_path = os.path.join(temp_dir, "DummyDlls.zip")
34
+ with zipfile.ZipFile(zip_path, 'w', zipfile.ZIP_DEFLATED) as zipf:
35
+ for root, _, files in os.walk(output_dir):
36
+ for file in files:
37
+ if file.endswith(".dll"): zipf.write(os.path.join(root, file), arcname=file)
38
+ return FileResponse(zip_path, media_type="application/zip", filename="DummyDlls.zip")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
39
 
40
  @app.post("/extract")
41
+ async def extract_dialogues(file: UploadFile = File(...), assembly_file: Optional[UploadFile] = File(None)):
 
 
 
42
  temp_dir = tempfile.mkdtemp()
43
  asset_path = os.path.join(temp_dir, file.filename)
44
  with open(asset_path, "wb") as f: f.write(await file.read())
45
 
46
  env = UnityPy.load(asset_path)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
47
  zip_filename = os.path.join(temp_dir, f"{file.filename}_dialogues.zip")
48
  extracted_count = 0
49
+ log_content = ["=== UNITYPY İKİLİ (BINARY) İŞLEM RAPORU ==="]
50
 
51
  with zipfile.ZipFile(zip_filename, 'w', zipfile.ZIP_DEFLATED) as zipf:
52
  for obj in env.objects:
53
  if obj.type.name in ["TextAsset", "MonoBehaviour"]:
54
+ # Dosya adını güvenli şekilde al
55
+ obj_name = f"{obj.type.name}_{obj.path_id}"
56
  try:
57
  data = obj.read()
58
+ if hasattr(data, "name") and data.name: obj_name = data.name
59
+ except: pass
60
+
61
+ log_content.append(f"\nİnceleniyor: {obj.type.name} (ID: {obj.path_id})")
62
+
63
+ if obj.type.name == "TextAsset":
64
+ try:
65
+ content = obj.read().text.encode('utf-8')
66
+ zipf.writestr(f"{obj_name}.txt", content)
67
+ extracted_count += 1
68
+ log_content.append(f" -> Başarılı: {obj_name}.txt oluşturuldu.")
69
+ except: pass
70
+
71
+ elif obj.type.name == "MonoBehaviour":
72
+ # TİP AĞACI ÇÖKERSE DOĞRUDAN HAM BELLEK TARAMASI YAP
73
+ raw_data = obj.get_raw_data()
74
+ found_strings = {}
75
+ i = 28 # MonoBehaviour ana başlığını atla
76
+
77
+ while i <= len(raw_data) - 4:
78
+ length = int.from_bytes(raw_data[i:i+4], 'little')
79
+ # Mantıklı bir metin uzunluğu arıyoruz (2 ile 5000 karakter arası)
80
+ if 2 <= length <= 5000 and (i + 4 + length) <= len(raw_data):
81
+ str_bytes = raw_data[i+4 : i+4+length]
82
+ pad_len = (4 - (length % 4)) % 4
83
+
84
+ # Padding (Boşluk) kontrolü
85
+ if (i + 4 + length + pad_len) <= len(raw_data):
86
+ padding = raw_data[i+4+length : i+4+length+pad_len]
87
+ if all(b == 0 for b in padding):
88
+ try:
89
+ text = str_bytes.decode('utf-8')
90
+ # Metin sadece sayılardan veya bozuk sembollerden oluşmuyorsa al
91
+ if len(text.strip()) > 1 and any(c.isalpha() for c in text):
92
+ found_strings[text] = text
93
+ i += 4 + length + pad_len
94
+ continue
95
+ except UnicodeDecodeError:
96
+ pass
97
+ i += 4 # Unity bayt dizilimleri her zaman 4'ün katıdır
98
+
99
+ if found_strings:
100
+ zipf.writestr(f"{obj_name}_raw.json", json.dumps(found_strings, indent=4, ensure_ascii=False).encode('utf-8'))
101
  extracted_count += 1
102
+ log_content.append(f" -> BİNARY BAŞARISI: {obj_name}_raw.json ({len(found_strings)} metin bulundu)")
103
+ else:
104
+ log_content.append(f" -> Atlandı: Bellekte metin bulunamadı.")
 
 
 
 
 
 
 
 
105
 
106
+ if extracted_count == 0: log_content.append("\nSONUÇ: Hedef dosyada metin bulunamadı.")
107
  zipf.writestr("islem_raporu.txt", "\n".join(log_content).encode('utf-8'))
108
 
109
  return FileResponse(zip_filename, media_type="application/zip", filename=f"{file.filename}_dialogues.zip")
110
 
111
  @app.post("/repack")
112
+ async def repack_dialogues(asset_file: UploadFile = File(...), mod_zip: UploadFile = File(...), assembly_file: Optional[UploadFile] = File(None)):
 
 
 
 
113
  temp_dir = tempfile.mkdtemp()
114
  asset_path = os.path.join(temp_dir, asset_file.filename)
115
  zip_path = os.path.join(temp_dir, mod_zip.filename)
 
116
  with open(asset_path, "wb") as f: f.write(await asset_file.read())
117
  with open(zip_path, "wb") as f: f.write(await mod_zip.read())
118
 
119
  env = UnityPy.load(asset_path)
120
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
121
  with zipfile.ZipFile(zip_path, 'r') as zipf:
122
  for file_info in zipf.infolist():
123
  filename = file_info.filename
124
  if filename == "islem_raporu.txt": continue
125
  content = zipf.read(filename)
126
+
127
  for obj in env.objects:
128
+ obj_name = f"{obj.type.name}_{obj.path_id}"
129
  try:
130
+ if hasattr(obj.read(), "name") and obj.read().name: obj_name = obj.read().name
131
+ except: pass
132
+
133
+ if obj.type.name == "TextAsset" and filename == f"{obj_name}.txt":
134
+ try:
135
+ data = obj.read()
136
  data.text = content.decode('utf-8')
137
  data.save()
138
+ except: pass
139
+ break
140
+
141
+ elif obj.type.name == "MonoBehaviour" and filename == f"{obj_name}_raw.json":
142
+ # HAM BELLEK YAMASI (BINARY PATCHING)
143
+ translations = json.loads(content.decode('utf-8'))
144
+ raw_data = obj.get_raw_data()
145
+ patched_data = bytearray(raw_data)
146
+
147
+ for orig_str, trans_str in translations.items():
148
+ if orig_str == trans_str: continue
149
+
150
+ # Orijinal metnin bayt bloğunu oluştur
151
+ orig_bytes = orig_str.encode('utf-8')
152
+ orig_pad = (4 - (len(orig_bytes) % 4)) % 4
153
+ orig_block = len(orig_bytes).to_bytes(4, 'little') + orig_bytes + (b'\x00' * orig_pad)
154
+
155
+ # Çevrilmiş metnin bayt bloğunu oluştur
156
+ trans_bytes = trans_str.encode('utf-8')
157
+ trans_pad = (4 - (len(trans_bytes) % 4)) % 4
158
+ trans_block = len(trans_bytes).to_bytes(4, 'little') + trans_bytes + (b'\x00' * trans_pad)
159
+
160
+ # Bellekteki bloğu yenisiyle değiştir
161
+ patched_data = patched_data.replace(orig_block, trans_block)
162
+
163
+ obj.set_raw_data(bytes(patched_data))
164
+ break
165
 
166
  output_path = os.path.join(temp_dir, f"repacked_{asset_file.filename}")
167
  with open(output_path, "wb") as f: f.write(env.file.save())