Last active
July 3, 2016 15:08
-
-
Save Dither/76768479fe0a51003e4b to your computer and use it in GitHub Desktop.
Python binary patcher for .dif files
This file contains 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 | |
# Small .dif patcher for Python 3+ | |
# File format of .dif file (description and filename should be on the 1st and 3rd lines exactly): | |
# File description | |
# | |
# filename.ext | |
# 0000000a: 00 01 | |
# 0000000b: 00 02 | |
import re,ntpath,sys | |
from sys import argv,exit | |
from ctypes import c_uint8 | |
def path_leaf(path): | |
head, tail = ntpath.split(path) | |
return tail or ntpath.basename(head) | |
def patch(file, dif, revert=False): | |
code = open(file,'rb').read() | |
open(file+'.bak','wb').write(code) | |
dif = open(dif,'r').read() | |
m = re.findall('([0-9a-fA-F]+): ([0-9a-fA-F]+) ([0-9a-fA-F]+)', dif) | |
for offset,orig,new in m: | |
o, orig, new = int(offset,16), int(orig, 16), int(new, 16) | |
print("%08X: %02X %02X" % (o,orig,new)) | |
if revert: | |
if code[o]==new: | |
code = code[:o]+bytes(c_uint8(orig))+code[o+1:] | |
else: | |
raise Exception("patched byte at %s is not %02X" % (offset, new)) | |
else: | |
if code[o]==orig: | |
code = code[:o]+bytes(c_uint8(new))+code[o+1:] | |
else: | |
raise Exception("original byte at %s is not %02X" % (offset, orig)) | |
open(file,'wb').write(code) | |
def main(): | |
if sys.version_info[0] < 3: | |
print("Python 3.0 or higher required.") | |
sys.exit(1) | |
if len(argv)<2: | |
print(" ") | |
print("Usage: %s <.dif file> [-revert]" % path_leaf(argv[0])) | |
print("Applies given .dif file to a binary; use -revert to revert patch.") | |
exit(0) | |
file, dif, revert = "", argv[1], False | |
diff = open(dif,'r') | |
for i, line in enumerate(diff): | |
if i == 2: | |
file = line.replace('\n', '').replace('\r', '') | |
break | |
diff.close() | |
if len(argv)>2: | |
revert = True | |
print("Reverting patch %r on file %r" % (dif, file)) | |
else: | |
print("Patching file %r with %r" % (file, dif)) | |
try: | |
patch(file, dif, revert) | |
print("Done") | |
except Exception as e: | |
print("Error: %s" % str(e)) | |
exit(1) | |
if __name__ == "__main__": | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment