-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathextract.py
89 lines (68 loc) · 2.56 KB
/
extract.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
87
88
89
"""
Small script to extract .xz archives from a .bin file.
Originally made for the CMF Watch Pro 2's bin file.
Author: github.com/whatotter
8/25/24
"""
import json
import argparse, os
try: # https://stackoverflow.com/a/42079784
import lzma
except ImportError:
from backports import lzma
parser = argparse.ArgumentParser()
parser.add_argument("bin", help="bin to attempt to extract from")
args = parser.parse_args()
# Both of these can be confirmed at http://fileformats.archiveteam.org/wiki/XZ
xzMagicNums = [b'\xfd', b'\x37', b'\x7a', b'\x58', b'\x5a']
xzEndings = [b'\x00', b'\x00', b'\x00', b'\x00', b'\x04', b'\x59', b'\x5a']
lzmaMagicNums = [b'\x4c', b'\x5a', b'\x4d', b'\x41', b'\x10']
binData = b''
begin = False
counter = 1
addr = 0
if not os.path.exists("./xz dumps"):
os.mkdir("xz dumps")
def write(byte):
global counter
with open("./xz dumps/{}.bin.xz".format(counter), "wb") as f:
f.write(byte)
f.flush()
counter += 1
# Read .bin file.
with open(args.bin, "rb") as f:
binData = f.read()
# Extract all .XZ archives from the bin file.
lzmaData = {}
while True:
LZMAstart = binData.find(b''.join(lzmaMagicNums))
start = binData.find(b''.join(xzMagicNums))
end = binData.find(b''.join(xzEndings))+len(xzEndings)
print("[{} / DUMP {}] writing from {} to {} | {} bytes left | last bytes: {}".format(
hex(addr), counter, hex(addr+start), hex(addr+end), len(binData), binData[start:end][-16:]
), flush=True)
if len(binData) == 0 or len(binData[start:end][-16:]) == 0:
print("done: {}".format(len(binData)))
break
lzmaData[str(counter)] = binData[LZMAstart:start].decode("latin-1")
write(binData[start:end])
part = binData.partition(b''.join(xzEndings))
addr += len(part[0])
binData = part[2]
with open("recompile.json", "w") as f:
f.write(json.dumps(lzmaData, indent=4))
f.flush()
# (painfully) Extract all .XZ archives, merge them all into one file.
xzs = os.listdir("./xz dumps")
mergeBin = open("merged.bin", "wb")
for x in range(1, counter):
xz = "{}.bin.xz".format(x)
with lzma.open("./xz dumps/{}".format(xz)) as f:
print("\r[+] merging {} {}".format(xz, " "*25), end="", flush=True)
try:
mergeBin.write(f.read())
except Exception as e: # for some reason some lzma archives are corrupted?
print("\n{}: {}".format(xz, e))
pass
print("\r[+] merged {} {}".format(xz, " "*25), end="", flush=True)
print("\n[!] extracted all .xz files from bin, merged them to 'merged.bin'")