mirror of
https://github.com/samba-team/samba.git
synced 2024-12-25 23:21:54 +03:00
e1c6e7d18b
Signed-off-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abartlet@samba.org>
138 lines
4.0 KiB
Python
Executable File
138 lines
4.0 KiB
Python
Executable File
#!/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()
|