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
|
import argparse
import json
import os
import hashlib
def get_replacements_for_file(filepath: str, file_data: dict, fixes: dict):
# we cant reliably make any changes unless we can use the md5 to make
# sure the offsets are going to match up.
if file_data.get('md5'):
for byte_offset in file_data:
if byte_offset != 'md5':
if file_data['md5'] in fixes:
fixes[file_data['md5']]['replacements'].extend(file_data[byte_offset].get(
'replacements', []))
else:
fixes[file_data['md5']] = {
'replacements': file_data[byte_offset].get('replacements', []),
'filepath': filepath,
}
def main():
parser = argparse.ArgumentParser()
parser.add_argument(dest="fixes_file", help="Path to fixes file.")
args = parser.parse_args()
fixes = {}
# Extract just the replacement data, organizing by file
with open(args.fixes_file) as fin:
fixes_data = json.load(fin)
for check in fixes_data:
for file in fixes_data[check]:
get_replacements_for_file(file, fixes_data[check][file], fixes)
# This first for loop is for each file we intended to make changes to
for recorded_md5 in fixes:
current_md5 = None
file_bytes = None
if os.path.exists(fixes[recorded_md5]['filepath']):
with open(fixes[recorded_md5]['filepath'], 'rb') as fin:
file_bytes = fin.read()
current_md5 = hashlib.md5(file_bytes).hexdigest()
# if the md5 is not matching up the file must have changed and our offset may
# not be correct, well need to bail on this file.
if current_md5 != recorded_md5:
print(
f'ERROR: not applying replacements for {fixes[recorded_md5]["filepath"]}, the file has changed since the replacement offset was recorded.'
)
continue
# perform the swap replacement of the binary data
file_bytes = bytearray(file_bytes)
for replacement in fixes[recorded_md5]['replacements']:
file_bytes[replacement['Offset']:replacement['Offset'] +
replacement['Length']] = replacement['ReplacementText'].encode()
with open(fixes[recorded_md5]['filepath'], 'wb') as fout:
fout.write(bytes(file_bytes))
if __name__ == '__main__':
main()
|