mirror of
https://github.com/keylase/nvidia-patch.git
synced 2024-08-30 18:32:50 +00:00
Add tool for producing .1337 patches
This commit is contained in:
parent
241a8aa81a
commit
0123fbd6ae
119
win/tools/1337-diff/1337-diff.py
Executable file
119
win/tools/1337-diff/1337-diff.py
Executable file
@ -0,0 +1,119 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import sys
|
||||
import argparse
|
||||
import os.path
|
||||
import itertools
|
||||
|
||||
PATCH_EXT = ".1337"
|
||||
CRLF = b"\x0d\x0a"
|
||||
HEADER_FORMAT = b">%s"
|
||||
LINE_FORMAT = CRLF + b"%016X:%02X->%02X"
|
||||
OFFSET_ADJUSTMENT = 0xC00
|
||||
|
||||
|
||||
class ByteDiffException(Exception):
|
||||
""" Base class for all exceptions """
|
||||
pass
|
||||
|
||||
|
||||
class LengthMismatchException(ByteDiffException):
|
||||
""" Throwed when length of input sequences do not match """
|
||||
pass
|
||||
|
||||
|
||||
def check_positive_int(value):
|
||||
value = int(value)
|
||||
if value <= 0:
|
||||
raise argparse.ArgumentTypeError(
|
||||
"%s is an invalid positive number value" % value)
|
||||
return value
|
||||
|
||||
|
||||
def parse_args():
|
||||
parser = argparse.ArgumentParser(
|
||||
description="Make .1337 patch file from original and patched files")
|
||||
parser.add_argument("orig_file",
|
||||
metavar="ORIG_FILE",
|
||||
help="original file")
|
||||
parser.add_argument("patched_file",
|
||||
metavar="PATCHED_FILE",
|
||||
help="patched file")
|
||||
parser.add_argument("output_file",
|
||||
metavar="OUTPUT_FILE",
|
||||
nargs='?',
|
||||
help="filename for patch output. Default: basename of "
|
||||
"original filename with .1337 extension")
|
||||
parser.add_argument("-f", "--header-filename",
|
||||
metavar="FILENAME",
|
||||
help="filename specified in resulting patch header. "
|
||||
"Default: basename of original filename.")
|
||||
parser.add_argument("-l", "--limit",
|
||||
help="stop after number of differences",
|
||||
type=check_positive_int)
|
||||
args = parser.parse_args()
|
||||
return args
|
||||
|
||||
|
||||
def feed_chunks(f, chunk_size=4096):
|
||||
""" Reads file-like object with chunks having up to `chunk_size` length """
|
||||
while True:
|
||||
buf = f.read(chunk_size)
|
||||
if not buf:
|
||||
break
|
||||
yield buf
|
||||
|
||||
|
||||
def zip_files_bytes(*files):
|
||||
""" Iterate over two files, returning pair of bytes.
|
||||
Throw LengthMismatch if file sizes is uneven. """
|
||||
class EndMarker(object):
|
||||
pass
|
||||
end_marker = EndMarker()
|
||||
|
||||
iterators = (itertools.chain.from_iterable(feed_chunks(f)) for f in files)
|
||||
for tup in itertools.zip_longest(*iterators, fillvalue=end_marker):
|
||||
if any(v is end_marker for v in tup):
|
||||
raise LengthMismatchException("Length of input files inequal.")
|
||||
yield tup
|
||||
|
||||
|
||||
def diff(left, right):
|
||||
for offset, (a, b) in enumerate(zip_files_bytes(left, right)):
|
||||
if a != b:
|
||||
yield offset, a, b
|
||||
|
||||
|
||||
def compose_diff_file(orig, patched, output, header, offset_adjustment=True):
|
||||
output.write(HEADER_FORMAT % (header.encode('latin-1'),))
|
||||
for offset, a, b in diff(orig, patched):
|
||||
o = offset + OFFSET_ADJUSTMENT if offset_adjustment else offset
|
||||
output.write(LINE_FORMAT % (o, a, b))
|
||||
|
||||
|
||||
def main():
|
||||
args = parse_args()
|
||||
|
||||
output_filename = args.output_file
|
||||
if not output_filename:
|
||||
orig_bname = os.path.basename(args.orig_file)
|
||||
before, _, after = orig_bname.rpartition('.')
|
||||
orig_bname_noext = before if before else after
|
||||
output_filename = orig_bname_noext + PATCH_EXT
|
||||
|
||||
header_filename = args.header_filename
|
||||
if not header_filename:
|
||||
header_filename = os.path.basename(args.orig_file)
|
||||
|
||||
with open(args.orig_file, 'rb') as orig,\
|
||||
open(args.patched_file, 'rb') as patched,\
|
||||
open(output_filename, 'wb') as output:
|
||||
try:
|
||||
compose_diff_file(orig, patched, output, header_filename)
|
||||
except LengthMismatchException:
|
||||
print("Input files have inequal length. Aborting...",
|
||||
file=sys.stderr)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
46
win/tools/1337-diff/README.md
Normal file
46
win/tools/1337-diff/README.md
Normal file
@ -0,0 +1,46 @@
|
||||
1337-diff
|
||||
=========
|
||||
|
||||
This tool accepts two input files and produces patch (diff) in `.1337`-file format. This format is compatible with patches produced by [x64dbg](https://x64dbg.com/) and applied by [Win\_1337\_Apply\_Patch tool](https://github.com/Deltafox79/Win_1337_Apply_Patch).
|
||||
|
||||
This tool is intended for internal usage to automate routine tasks related to windows patches. Implementation is really slow and prefers code transparency and correctness over speed.
|
||||
|
||||
## Requirements
|
||||
|
||||
* Python 3
|
||||
|
||||
## Synopsys
|
||||
|
||||
```
|
||||
$ ./1337-diff.py -h
|
||||
usage: 1337-diff.py [-h] [-f FILENAME] [-l LIMIT]
|
||||
ORIG_FILE PATCHED_FILE [OUTPUT_FILE]
|
||||
|
||||
Make .1337 patch file from original and patched files
|
||||
|
||||
positional arguments:
|
||||
ORIG_FILE original file
|
||||
PATCHED_FILE patched file
|
||||
OUTPUT_FILE filename for patch output. Default: basename of
|
||||
original filename with .1337 extension
|
||||
|
||||
optional arguments:
|
||||
-h, --help show this help message and exit
|
||||
-f FILENAME, --header-filename FILENAME
|
||||
filename specified in resulting patch header. Default:
|
||||
basename of original filename.
|
||||
-l LIMIT, --limit LIMIT
|
||||
stop after number of differences
|
||||
```
|
||||
|
||||
## Example
|
||||
|
||||
```
|
||||
$ ./1337-diff.py ~/w418.81/orig/nvcuvid.dll ~/w418.81/patched/nvcuvid.dll
|
||||
$ cat nvcuvid.1337
|
||||
>nvcuvid.dll
|
||||
00000000000DE736:74->90
|
||||
00000000000DE737:08->90$
|
||||
```
|
||||
|
||||
Note no newline at the end of file and CRLF line breaks.
|
Loading…
Reference in New Issue
Block a user