-
Notifications
You must be signed in to change notification settings - Fork 3
/
pup_module.py
86 lines (68 loc) · 2.89 KB
/
pup_module.py
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
import os
import struct
import lzma
import tkinter as tk
from tkinter import filedialog, messagebox
class Pup:
MAGIC = b'MYPUP123'
def __init__(self, file_path, magic, version, mode, entry_table_offset, entry_table_count, entry_table):
self.file_path = file_path
self.magic = magic
self.version = version
self.mode = mode
self.entry_table_offset = entry_table_offset
self.entry_table_count = entry_table_count
self.entry_table = entry_table
def select_file():
root = tk.Tk()
root.withdraw()
return filedialog.askopenfilename(filetypes=[('PUP files', '*.pup')])
def extract_pup_file():
file_path = select_file()
# Extract the file name from the path
pup_name = os.path.basename(file_path)
# Read the file content into a buffer
with open(file_path, 'rb') as f:
buffer = f.read()
# Check if the padding is correct
padding_len = len(buffer) % 16
if padding_len != 0:
raise ValueError(f"The file {pup_name} does not have the correct padding.")
# Extract information from the buffer
magic = buffer[:8]
version = buffer[8:12]
mode = buffer[12:16]
entry_table_offset = struct.unpack("<Q", buffer[32:40])[0]
entry_table_count = struct.unpack("<I", buffer[48:52])[0]
# Check if the MAGIC value is correct
if magic != Pup.MAGIC:
raise ValueError(f"The file {pup_name} does not have the correct MAGIC value.")
# Extract the entry table
entry_table = []
for i in range(entry_table_count):
offset = entry_table_offset + i * 24
entry = struct.unpack("<6sIHQQI", buffer[offset:offset+24])
entry_table.append(entry)
# Create an instance of the Pup class with the extracted information
pup = Pup(file_path, magic, version, mode, entry_table_offset, entry_table_count, entry_table)
# Create a directory with the same name as the .pup file in the same folder
# and save the extracted files inside it
dir_path = os.path.dirname(file_path)
pup_dir_path = os.path.join(dir_path, pup_name[:-4])
if not os.path.exists(pup_dir_path):
os.makedirs(pup_dir_path)
# Estrazione dei file interni
for i, entry in enumerate(pup.entry_table):
entry_data_offset = entry[6]
entry_data_size = entry[4] if entry[2] else entry[3]
if entry[2]:
entry_data = lzma.decompress(buffer[entry_data_offset:entry_data_offset+entry[4]])
else:
entry_data = buffer[entry_data_offset:entry_data_offset+entry_data_size]
file_name = f"{i:06d}.bin"
file_path = os.path.join(pup_dir_path, file_name)
with open(file_path, 'wb') as f:
f.write(entry_data)
messagebox.showinfo("Information", "Extraction completed successfully.")
if __name__ == '__main__':
extract_pup_file()