diff --git a/README.md b/README.md index e3b5148..559b9d7 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,11 @@ DESCRIPTION =========== +My changes: +* upgraded to python3 +* replaced xlrd with openpyxl ( it is a bit slower, but works) + +Note: I have only tested the systeminfo functions, so there might be some issues. + This tool compares a targets patch levels against the Microsoft vulnerability database in order to detect potential missing patches on the target. It also notifies the user if there are public exploits and Metasploit modules diff --git a/windows-exploit-suggester.py b/windows-exploit-suggester.py index 108c1b6..4d4460f 100755 --- a/windows-exploit-suggester.py +++ b/windows-exploit-suggester.py @@ -323,17 +323,18 @@ # def merge_list(li): # import re +import requests import platform import argparse -import subprocess +#import subprocess import csv -import StringIO +#import StringIO import os import datetime -import urllib2 +#import urllib2 import io -from random import randint -from time import sleep +#from random import randint +#from time import sleep from tempfile import NamedTemporaryFile from sys import exit @@ -387,8 +388,8 @@ def main(): try: dbfile = open(ARGS.database, 'r') - except IOError, e: - ALERT("could not open the file %s" % filename, ALERT.BAD) + except IOError: + ALERT("could not open the file %s" % ARGS.database, ALERT.BAD) exit(1) data = '' @@ -399,24 +400,24 @@ def main(): dbfile.close() # xls or xslx - elif 'xls' in extension: + elif 'xlsx' in extension: ALERT("database file detected as xls or xlsx based on extension", ALERT.NORMAL) try: - import xlrd - except ImportError as e: + import openpyxl + except ImportError: ALERT("please install and upgrade the python-xlrd library", ALERT.BAD) exit(1) # open the xls file try: - wb = xlrd.open_workbook(ARGS.database) - except IOError as e: + wb = openpyxl.load_workbook(ARGS.database, read_only=True) + except IOError: ALERT("no such file or directory '%s'. ensure you have the correct database file passed in --database/-d" % ARGS.database, ALERT.BAD) exit(1) #sh = wb.sheet_by_name('Export Bulletin Search Spreadsh') - sh = wb.sheet_by_index(0) + sh = wb.active # read the spreadsheet into a temp file f = NamedTemporaryFile(mode='wb') @@ -425,19 +426,32 @@ def main(): data = '' # loop through xls - for rownum in xrange(sh.nrows): + for row in sh.iter_rows(): - values = sh.row_values(rownum) + #values = sh.row_values(rownum) + values = row # loop through row values, and process input - for i in range(len(values)): - values[i] = unicode(values[i]).encode('utf8') + + for val in row: + if val.value is None: + continue + + result = str(val.value) + result = result.replace('\n',' ') + result = result.replace(',','') + result = result.replace('.0','') + data += result + "," + data = data[:-1] + "\n" + + """for i in range(len(values)): + values[i] = values[i].encode('utf8') values[i] = values[i].replace('\n',' ') values[i] = values[i].replace(',','') values[i] = values[i].replace('.0','') data += ",".join(values) - data += '\n' + data += '\n'""" # set the database to the csv data database = data @@ -662,10 +676,12 @@ def run(database): # get the potential bulletins try: - for row in csv.reader(StringIO.StringIO(database)): + for row in csv.reader(io.StringIO(database)): + if row == []: + continue bulletinid=row[1] affected=row[6] - + if isaffected(name, release, servicepack, architecture, affected): # only add the bulletin if it's not already in the list @@ -676,7 +692,7 @@ def run(database): if ARGS.verbose: ALERT("%s has been added to potential list '%s'" % (bulletinid, affected)) - except csv.Error, e: + except csv.Error: ALERT('could not parse database file, make sure it is in the proper format', ALERT.BAD) exit(1) @@ -752,7 +768,7 @@ def run(database): if bulletinid in bulletinids and not "remote code execution" in impact.lower(): - remove = getlinkedms([bulletinid], csv.reader(StringIO.StringIO(database))) + remove = getlinkedms([bulletinid], csv.reader(io.StringIO(database))) if ARGS.verbose: ALERT(" removing %s (total of %s MS ids), because of its impact %s" % (bulletinid, len(remove), impact)) @@ -830,7 +846,7 @@ def run(database): if ARGS.sub: # linked ms, the children of this msid - linked = set(getlinkedms([msid], csv.reader(StringIO.StringIO(database)))) + linked = set(getlinkedms([msid], csv.reader(io.StringIO(database)))) linked = linked.intersection(msids) # loop through the linked msids, and only display those that qualify and @@ -843,8 +859,8 @@ def run(database): if lexploit: lalert = lexploit ALERT("|_%s: %s (%s) - %s" % (lmsid, vulns[lmsid][0], vulns[lmsid][1], vulns[lmsid][2]), lalert) - # only allow duplicate events to be displayed when command-line args passed - if not ARGS.duplicates: alerted.add(lmsid) + # only allow duplicate events to be displayed when command-line args passed + if not ARGS.duplicates: alerted.add(lmsid) # end run() @@ -871,7 +887,7 @@ def trace(database): ALERT("searching for bulletin id %s" % bulletinid) # get linked msids - lmsids = getlinkedms([bulletinid], csv.reader(StringIO.StringIO(database))) + lmsids = getlinkedms([bulletinid], csv.reader(io.StringIO(database))) msids = [] @@ -895,7 +911,7 @@ def trace(database): exit(1) # get linked msids, loop through the row - for row in csv.reader(StringIO.StringIO(database)): + for row in csv.reader(io.StringIO(database)): msid = row[1] affected = row[6] @@ -920,7 +936,7 @@ def patches(database): ALERT("searching all kb's for bulletin id %s" % bulletinid) # get linked msids, loop through the row - for row in csv.reader(StringIO.StringIO(database)): + for row in csv.reader(io.StringIO(database)): bulletinkb=row[2] componentkb=row[7] @@ -1526,12 +1542,12 @@ def update(): # compute the filenames to be used filenames = '%s-mssb' % datetime.datetime.now().strftime('%Y-%m-%d') - xlsFile = '%s.%s' % (filenames, 'xls') + xlsFile = '%s.%s' % (filenames, 'xlsx') csvFile = '%s.%s' % (filenames, 'csv') # url request opener with user-agent - opener = urllib2.build_opener() - opener.addheaders = [('User-agent', 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.57 Safari/537.36')] + #opener = urllib2.build_opener() + headers = {'User-agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.57 Safari/537.36'} # grab the new data from ms and scrape the site #try: @@ -1563,12 +1579,12 @@ def update(): # now download the mssb file, with a random sleep try: #sleep(randint(1,3)) - response = opener.open(bulletinUrl) - except urllib2.URLError, e: + response = requests.get(bulletinUrl, headers=headers) + except requests.exceptions.RequestException: ALERT("error getting ms sb url %s" % bulletinUrl, ALERT.BAD) exit(1) - bulletinData = response.read() + bulletinData = response.content ALERT("writing to file %s" % xlsFile, ALERT.GOOD) f = open(xlsFile, 'wb') @@ -1581,7 +1597,7 @@ class ALERT(object): def __init__(self, message, level=0, ansi=True): # default to ansi alerting, if it's detected as windows platform then disable - if platform.system() is "Windows": ansi = False + if platform.system() == "Windows": ansi = False good = '[+]' bad = '[-]' @@ -1604,7 +1620,7 @@ def __init__(self, message, level=0, ansi=True): elif level == ALERT.EXP: print('%s' % exploit), else: print('%s' % normal), - print message + print(message) @staticmethod @property