Home | History | Annotate | Download | only in utils
      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 
     13 import os
     14 import sys
     15 import re
     16 import subprocess
     17 import optparse
     18 
     19 # Look for indirect calls/jmps in a binary. re: (call|jmp).*\* 
     20 def 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 
     39 def 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 
     47 if __name__ == '__main__':
     48     main(sys.argv)
     49