Last active
February 26, 2024 02:32
-
-
Save aviafelix/ef26755a7c50750829906a7ab5efc250 to your computer and use it in GitHub Desktop.
Patching binary files with Python
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#/usr/bin/env python3 | |
""" | |
Yet another simple binary patcher | |
""" | |
patches = [ | |
{ | |
# 1 Windows x64, version 3, build 1234 | |
'file': 'file_1.bin', | |
'offset': 0x0BA950, | |
'original': b'\x00', | |
'patched': b'\x01', | |
}, | |
{ | |
# 2 Windows x64, version 3, build 1324 | |
'file': 'file_2.bin', | |
'offset': 0x233445, | |
'original': b'\x77', | |
'patched': b'\xff', | |
}, | |
{ | |
# 3 Linux x64, version 3, build 1432 | |
'file': 'file_3.bin', | |
'offset': 0xA0B1C2, | |
'original': b'\xcc', | |
'patched': b'\xdd', | |
}, | |
] | |
def patch_all(patches=None): | |
""" | |
Applies all patches | |
:param patches: list (or tuple) of patch info dictionaries | |
""" | |
if patches is None: | |
return | |
for patch in patches: | |
with open(patch['file'], 'r+b') as f: | |
f.seek(patch['offset']) | |
# change it if patch data is longer than one byte | |
data = f.read(1) | |
print(data) | |
if data == patch['original']: | |
print('Ok! Here we are') | |
else: | |
print('Not the place!') | |
return | |
f.seek(patch['offset']) | |
f.write(patch['patched']) | |
def main(): | |
""" | |
Main function | |
""" | |
patch_all(patches=patches) | |
if __name__ == '__main__': | |
main() |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
FILENAME = 'file_to_patch.bin' | |
PATCHES = ( | |
# ST3, 3143 | |
# (Offset, Original, Patched) | |
(0xABCDEF, b'\x00', b'\x55'), | |
(0x111111, b'\xFF', b'\x77'), | |
(0x0A1B2C, b'\xAA', b'\xBB'), | |
) | |
PATCHES_DICT = ( | |
{'offset': 0xABCDEF, 'original': b'\x00', 'patched': b'\x55'}, | |
{'offset': 0x111111, 'original': b'\xFF', 'patched': b'\x77'}, | |
{'offset': 0x0A1B2C, 'original': b'\xAA', 'patched': b'\xBB'}, | |
) | |
def patch_file(filename, patches): | |
""" | |
Patches binary file with patches | |
:param filename: file name | |
:param patches: tuple or list | |
of tuples, lists or dicts of patches | |
""" | |
print("Begin patching...") | |
try: | |
with open(filename, 'r+b') as f: | |
for patch in patches: | |
if isinstance(patch, tuple) or isinstance(patch, list): | |
patch_tuple(f, patch) | |
elif isinstance(patch, dict): | |
patch_dict(f, patch) | |
else: | |
print("Wrong patches type") | |
except Exception as e: | |
print("Error while patching:", e) | |
print("End of patching...") | |
def patch_tuple(file, patch_tuple): | |
""" | |
:param file: binary file variable to patch | |
:param patch_tuple: tuple or list structure of type (offset, original, patched) | |
""" | |
print("Tuple patching") | |
offset, original, patched = patch_tuple | |
file.seek(offset) | |
patched_data = file.read(len(original)) | |
if patched_data == original: | |
print("Found: 0x{:x}: {} -> {}".format(offset, original, patched)) | |
file.seek(offset) | |
file.write(patched) | |
else: | |
print("Patch error at 0x{:x}".format(offset)) | |
def patch_dict(file, patch_dict): | |
""" | |
:param file: binary file variable to patch | |
:param patch_dict: dict structure {'offset': <int>, 'original': <bytes>, 'patched': <bytes>} | |
""" | |
print("Dict patching") | |
file.seek(patch_dict['offset']) | |
patch_dicted_data = file.read(len(patch_dict['original'])) | |
if patch_dicted_data == patch_dict['original']: | |
print("Found: 0x{:x}: {} -> {}".format(patch_dict['offset'], patch_dict['original'], patch_dict['patched'])) | |
file.seek(patch_dict['offset']) | |
file.write(patch_dict['patched']) | |
else: | |
print("Patch error at 0x{:x}".format(patch_dict['offset'])) | |
def main(): | |
# patch_file(FILENAME, PATCHES) | |
patch_file(FILENAME, PATCHES_DICT) | |
if __name__ == '__main__': | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment