1#!/usr/bin/env python 2 3"""A tool for looking for indirect jumps and calls in x86 binaries. 4 5 Helpful to verify whether or not retpoline mitigations are catching 6 all of the indirect branches in a binary and telling you which 7 functions the remaining ones are in (assembly, etc). 8 9 Depends on llvm-objdump being in your path and is tied to the 10 dump format. 11""" 12 13import os 14import sys 15import re 16import subprocess 17import optparse 18 19# Look for indirect calls/jmps in a binary. re: (call|jmp).*\* 20def look_for_indirect(file): 21 args = ['llvm-objdump'] 22 args.extend(["-d"]) 23 args.extend([file]) 24 25 p = subprocess.Popen(args=args, stdin=None, stderr=subprocess.PIPE, stdout=subprocess.PIPE) 26 (stdout,stderr) = p.communicate() 27 28 function = "" 29 for line in stdout.splitlines(): 30 if line.startswith(' ') == False: 31 function = line 32 result = re.search('(call|jmp).*\*', line) 33 if result != None: 34 # TODO: Perhaps use cxxfilt to demangle functions? 35 print function 36 print line 37 return 38 39def main(args): 40 # No options currently other than the binary. 41 parser = optparse.OptionParser("%prog [options] <binary>") 42 (opts, args) = parser.parse_args(args) 43 if len(args) != 2: 44 parser.error("invalid number of arguments: %s" % len(args)) 45 look_for_indirect(args[1]) 46 47if __name__ == '__main__': 48 main(sys.argv) 49