Skip to content

Instantly share code, notes, and snippets.

@aviafelix
Last active February 26, 2024 02:32
Show Gist options
  • Star 9 You must be signed in to star a gist
  • Fork 5 You must be signed in to fork a gist
  • Save aviafelix/ef26755a7c50750829906a7ab5efc250 to your computer and use it in GitHub Desktop.
Save aviafelix/ef26755a7c50750829906a7ab5efc250 to your computer and use it in GitHub Desktop.
Patching binary files with Python
#/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()
#!/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