diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 17:20:00 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 17:20:00 +0000 |
commit | 8daa83a594a2e98f39d764422bfbdbc62c9efd44 (patch) | |
tree | 4099e8021376c7d8c05bdf8503093d80e9c7bad0 /lib/fuzzing/decode_ndr_X_crash | |
parent | Initial commit. (diff) | |
download | samba-8daa83a594a2e98f39d764422bfbdbc62c9efd44.tar.xz samba-8daa83a594a2e98f39d764422bfbdbc62c9efd44.zip |
Adding upstream version 2:4.20.0+dfsg.upstream/2%4.20.0+dfsg
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'lib/fuzzing/decode_ndr_X_crash')
-rwxr-xr-x | lib/fuzzing/decode_ndr_X_crash | 137 |
1 files changed, 137 insertions, 0 deletions
diff --git a/lib/fuzzing/decode_ndr_X_crash b/lib/fuzzing/decode_ndr_X_crash new file mode 100755 index 0000000..63c3cd7 --- /dev/null +++ b/lib/fuzzing/decode_ndr_X_crash @@ -0,0 +1,137 @@ +#!/usr/bin/env python3 +# +# Interpret a file that crashes an fuzz_ndr_X binary. +# +# Copyright (C) Catalyst IT Ltd. 2019 + + +import sys +import os +from base64 import b64encode +import struct +import argparse +import re + +TYPE_MASK = 3 +TYPES = ['struct', 'in', 'out'] + +FLAGS = [ + (4, 'ndr64', '--ndr64'), +] + + +def print_if_verbose(*args, **kwargs): + if verbose: + print(*args, **kwargs) + + +def process_one_file(f): + print_if_verbose(f.name) + print_if_verbose('-' * len(f.name)) + + b = f.read() + flags, function = struct.unpack('<HH', b[:4]) + if opnum is not None and opnum != function: + return + + t = TYPES[flags & TYPE_MASK] + if ndr_type and ndr_type != t: + return + + payload = b[4:] + data64 = b64encode(payload).decode('utf-8') + + cmd = ['bin/ndrdump', + pipe, + str(function), + t, + '--base64-input', + '--input', data64, + ] + + for flag, name, option in FLAGS: + if flags & flag: + print_if_verbose("flag: %s" % name) + cmd.append(option) + + print_if_verbose("length: %d\n" % len(payload)) + print(' '.join(cmd)) + print_if_verbose() + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument('-p', '--pipe', default='$PIPE', + help='pipe name (for output command line)') + parser.add_argument('-t', '--type', default=None, choices=TYPES, + help='restrict to this type') + parser.add_argument('-o', '--opnum', default=None, type=int, + help='restrict to this function/struct number') + parser.add_argument('FILES', nargs='*', default=(), + help="read from these files") + parser.add_argument('-k', '--ignore-errors', action='store_true', + help='do not stop on errors') + parser.add_argument('-v', '--verbose', action='store_true', + help='say more') + parser.add_argument('-H', '--honggfuzz-file', + help="extract crashes from this honggfuzz report") + parser.add_argument('-f', '--crash-filter', + help="only print crashes matching this rexexp") + + args = parser.parse_args() + + global pipe, opnum, ndr_type, verbose + pipe = args.pipe + opnum = args.opnum + ndr_type = args.type + verbose = args.verbose + + if not args.FILES and not args.honggfuzz_file: + parser.print_usage() + sys.exit(1) + + for fn in args.FILES: + if args.crash_filter is not None: + if not re.search(args.crash_filter, fn): + print_if_verbose(f"skipping {fn}") + continue + try: + if fn == '-': + process_one_file(sys.stdin) + else: + with open(fn, 'rb') as f: + process_one_file(f) + except Exception: + print_if_verbose("Error processing %s\n" % fn) + if args.ignore_errors: + continue + raise + + if args.honggfuzz_file: + print_if_verbose(f"looking at {args.honggfuzz_file}") + with open(args.honggfuzz_file) as f: + pipe = None + crash = None + for line in f: + m = re.match(r'^\s*fuzzTarget\s*:\s*bin/fuzz_ndr_(\w+)\s*$', line) + if m: + pipe = m.group(1).split('_TYPE_', 1)[0] + print_if_verbose(f"found pipe {pipe}") + m = re.match(r'^FUZZ_FNAME: (\S+)$', line) + if m: + crash = m.group(1) + if args.crash_filter is not None: + if not re.search(args.crash_filter, crash): + print_if_verbose(f"skipping {crash}") + pipe = None + crash = None + continue + print_if_verbose(f"found crash {crash}") + if pipe is not None and crash is not None: + with open(crash, 'rb') as f: + process_one_file(f) + pipe = None + crash = None + + +main() |