]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
fuzzing: Add script decode_ndr_X_crash to decode crash results
authorDouglas Bagnall <douglas.bagnall@catalyst.net.nz>
Tue, 5 Nov 2019 01:26:56 +0000 (14:26 +1300)
committerAndrew Bartlett <abartlet@samba.org>
Tue, 10 Dec 2019 07:50:28 +0000 (07:50 +0000)
This interprets a file that crashes an fuzz_ndr_X binary

Signed-off-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
lib/fuzzing/decode_ndr_X_crash [new file with mode: 0755]

diff --git a/lib/fuzzing/decode_ndr_X_crash b/lib/fuzzing/decode_ndr_X_crash
new file mode 100755 (executable)
index 0000000..75dc7de
--- /dev/null
@@ -0,0 +1,89 @@
+#!/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
+
+
+TYPE_MASK = 3
+TYPES = ['struct', 'in', 'out']
+
+FLAGS = [
+    (4, 'ndr64', '--ndr64'),
+]
+
+def process_one_file(f):
+    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
+
+    print(f.name)
+    print('-' * len(f.name))
+
+    payload = b[4:]
+
+    cmd = ['bin/ndrdump', pipe, str(function), t]
+    for flag, name, option in FLAGS:
+        if flags & flag:
+            print("flag: %s" % name)
+            cmd.append(option)
+    data64 = b64encode(payload)
+    print("length: %d" % len(payload))
+    cmdstr = ("echo -n '%s' | base64 -d | %s" % (data64.decode('utf-8'),
+                                                 ' '.join(cmd)))
+    print()
+    print(cmdstr)
+    print()
+
+
+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')
+
+    args = parser.parse_args()
+
+    global pipe, opnum, ndr_type
+    pipe = args.pipe
+    opnum = args.opnum
+    ndr_type = args.type
+
+
+    if not args.FILES and not args.honggfuzz_file:
+        parser.print_usage()
+        sys.exit(1)
+
+    for fn in args.FILES:
+        try:
+            if fn == '-':
+                process_one_file(sys.stdin)
+            else:
+                with open(fn, 'rb') as f:
+                    process_one_file(f)
+        except Exception:
+            print("Error processing %s\n" % fn)
+            if args.ignore_errors:
+                continue
+            raise
+
+main()