diff options
author | Mark Haines <mark.haines@matrix.org> | 2015-06-21 18:47:06 +0100 |
---|---|---|
committer | Mark Haines <mark.haines@matrix.org> | 2015-06-21 18:47:06 +0100 |
commit | fb980849c4ffc99bca7a2dd5a347e9f0b4b99469 (patch) | |
tree | d223e53f304a8fa7dca8df7b8f442af7bd6ff67e /tracing/graph.py | |
parent | 0ca3797d2d065e63dc5806ba014bcb742b09c5d7 (diff) |
Add gdb script and psuedo-call graph generator python script for tracing calls to crypto primitives
Diffstat (limited to 'tracing/graph.py')
-rwxr-xr-x | tracing/graph.py | 100 |
1 files changed, 100 insertions, 0 deletions
diff --git a/tracing/graph.py b/tracing/graph.py new file mode 100755 index 0000000..ac121aa --- /dev/null +++ b/tracing/graph.py @@ -0,0 +1,100 @@ +#! /usr/bin/python + +import sys +import yaml +import array + +class Call(object): + def __init__(self, call): + self.func, = call + args = dict(call[self.func]) + self.output = array.array("B", args.pop("output")).tostring() + self.inputs = { + name: array.array("B", args[name]).tostring() + for name in args + if not name.endswith("_length") + } + self.bind = {} + + def expr(self, stream, indent=" ", level=""): + stream.write(self.func + "(\n") + for name, value in self.inputs.items(): + stream.write(level + indent + name + "=") + self.bind.get(name, Literal(value)).expr( + stream, indent, level + indent + ) + stream.write(",\n") + stream.write(level + ")") + + +class Literal(str): + def expr(self, stream, indent, level): + stream.write("\"" + self.encode("hex") + "\"") + + +class Slice(object): + def __init__(self, thing, start, end): + self.thing = thing + self.start = start + self.end = end + + def expr(self, stream, indent=" ", level=""): + self.thing.expr(stream, indent, level) + stream.write("[%d:%d]" % (self.start, self.end)) + + +class Concat(list): + def expr(self, stream, indent=" ", level=""): + stream.write("concat(\n") + for thing in self: + stream.write(level + indent) + thing.expr(stream, indent, level + indent) + stream.write(",\n") + stream.write(level + ")") + + +calls = [Call(c) for c in yaml.load(sys.stdin)] + +outputs = {} + +for call in calls: + for i in range(8, len(call.output)): + outputs.setdefault(call.output[i - 8: i], []).append(call) + +for call in calls: + for name, value in call.inputs.items(): + for bind in outputs.get(value[:8], ()): + if value == bind.output: + call.bind[name] = bind + else: + for end in range(len(value), len(bind.output) + 1): + start = end - len(value) + if value == bind.output[start:end]: + call.bind[name] = Slice(bind, start, end) + if not name in call.bind: + i = 0 + j = 1 + k = 0 + concat = Concat() + while i < len(value): + for bind in outputs.get(value[i:i+8], ()): + if value[i:].startswith(bind.output): + if k != i: + concat.append(Literal(value[k:i])) + concat.append(bind) + j = len(bind.output) + k = i + j + break + i += j + j = 1 + if concat: + if k != i: + concat.append(Literal(value[k:i])) + call.bind[name] = concat + +for call in calls: + if call.func.startswith("h"): + sys.stdout.write("\"" + call.output.encode("hex") + "\" = ") + call.expr(sys.stdout) + sys.stdout.write("\n") + |