michael@0: #!/usr/bin/env python michael@0: michael@0: # This Source Code Form is subject to the terms of the Mozilla Public michael@0: # License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: # file, You can obtain one at http://mozilla.org/MPL/2.0/. michael@0: michael@0: # run Microsoft's Binscope tool (http://www.microsoft.com/download/en/details.aspx?id=11910) michael@0: # against a fresh Windows build. output a 'binscope.log' file with full details michael@0: # of the run and appropriate strings to integrate with the buildbots michael@0: michael@0: # from the docs : "The error code returned when running under the command line is equal michael@0: # to the number of failures the tool reported plus the number of errors. BinScope will return michael@0: # 0 only if there are no errors or failures." michael@0: michael@0: # the symbol dir should point to the symbol dir hierarchy created michael@0: # via running make buildsymbols in a windows build's objdir michael@0: michael@0: import sys michael@0: import subprocess michael@0: import os michael@0: michael@0: BINSCOPE_OUTPUT_LOGFILE = r".\binscope_xml_output.log" michael@0: michael@0: # usage michael@0: if len(sys.argv) < 3: michael@0: print """usage : autobinscope.by path_to_binary path_to_symbols [log_file_path]" michael@0: log_file_path is optional, log will be written to .\binscope_xml_output.log by default""" michael@0: sys.exit(0) michael@0: michael@0: binary_path = sys.argv[1] michael@0: symbol_path = sys.argv[2] michael@0: michael@0: if len(sys.argv) == 4: michael@0: log_file_path = sys.argv[3] michael@0: else: michael@0: log_file_path = BINSCOPE_OUTPUT_LOGFILE michael@0: michael@0: # execute binscope against the binary, using the BINSCOPE environment michael@0: # variable as the path to binscope.exe michael@0: try: michael@0: binscope_path = os.environ['BINSCOPE'] michael@0: except KeyError: michael@0: print "BINSCOPE environment variable is not set, can't check DEP/ASLR etc. status." michael@0: sys.exit(0) michael@0: michael@0: try: michael@0: proc = subprocess.Popen([binscope_path, "/target", binary_path, michael@0: "/output", log_file_path, "/sympath", symbol_path, michael@0: "/c", "ATLVersionCheck", "/c", "ATLVulnCheck", "/c", "FunctionPointersCheck", michael@0: "/c", "SharedSectionCheck", "/c", "APTCACheck", "/c", "NXCheck", michael@0: "/c", "GSCheck", "/c", "GSFunctionSafeBuffersCheck", "/c", "GSFriendlyInitCheck", michael@0: "/c", "CompilerVersionCheck", "/c", "SafeSEHCheck", "/c", "SNCheck", michael@0: "/c", "DBCheck"], stdout=subprocess.PIPE) michael@0: michael@0: except WindowsError, (errno, strerror): michael@0: if errno != 2 and errno != 3: michael@0: print "Unexpected error ! \nError " + str(errno) + " : " + strerror + "\nExiting !\n" michael@0: sys.exit(0) michael@0: else: michael@0: print "Could not locate binscope at location : %s\n" % binscope_path michael@0: print "Binscope wasn't installed or the BINSCOPE env variable wasn't set correctly, skipping this check and exiting..." michael@0: sys.exit(0) michael@0: michael@0: proc.wait() michael@0: michael@0: output = proc.communicate()[0] michael@0: michael@0: # is this a PASS or a FAIL ? michael@0: if proc.returncode != 0: michael@0: print "Error count: %d" % proc.returncode michael@0: print "TEST-UNEXPECTED-FAIL | autobinscope.py | %s is missing a needed Windows protection, such as /GS or ASLR" % binary_path michael@0: logfile = open(log_file_path, "r") michael@0: for line in logfile: michael@0: print(line), michael@0: else: michael@0: print "TEST-PASS | autobinscope.py | %s succeeded" % binary_path