diff --git a/searchsploit.py b/searchsploit.py index 22d9dd9..4a96268 100755 --- a/searchsploit.py +++ b/searchsploit.py @@ -2,6 +2,7 @@ from sys import argv, exit import os import argparse +import re # Default options COL = 0 @@ -209,7 +210,7 @@ def drawline(lim): print(line) -def highlightTerm(line, term): +def highlightTerm(line: str, term)->str: """ Part one of new highlighting process. Highlights by adding :8 and :9 as escape characters as ansi takes several lines. the rest is compiled in separater unless autocomp is true\n @line: the phrase to be checked\n @term: the term that will be found in line and used to highlight the line\n @@ -219,6 +220,10 @@ def highlightTerm(line, term): if not parseArgs.colour: return line + # Adjustments for if term is version tuple + if type(term) is tuple: + term = term[1] # TODO: Make way to highlight line if fits version parameters + marker = 0 # marks where the term is first found term = term.lower() @@ -309,6 +314,41 @@ def findExploit(id): else: return i, exploit +baseVersion = re.compile(r'((?:(?:<)\s*)|(?:[RrVv]))?((?:\d+(?:\.(?:\d+|x))+)|(?:\d+))') + +def hasVersion(term: str)->bool: + """ Returns true if the string contains any numbers that could resemble a verison + """ + return (len(baseVersion.findall(term)) > 0) + +def getVersion(term: str): + return baseVersion.findall(term) # returns the first found object, taking tuple out of list + +def cmpVersion(leftVersion: str, rightVersion: str)->int: + """ Compares the two versions and returns an integer depending on which one if newer + """ + leftComponent = leftVersion.split(".") + rightComponent = rightVersion.split(".") + for i in range(min(len(leftComponent), len(rightComponent))): + if (leftComponent[i] != rightComponent[i]): + # Dealing with wildcard scenarios + if ("x" in leftComponent[i]): + if (len(re.findall("((?:{0})|(?:{1}))$".format(leftComponent[i],leftComponent[i].replace("x","\\d*")), rightComponent[i])) > 0): + # if the string matches itself or regex replacing all x's with \d's, then it is a match + return 0 + elif ("x" in rightComponent[i]): + if (len(re.findall("((?:{0})|(?:{1}))$".format(rightComponent[i],rightComponent[i].replace("x","\\d*")), leftComponent[i])) > 0): + # if the string matches itself or regex replacing all x's with \d's, then it is a match + return 0 + + # Removing excess chars + # print(leftComponent[i], rightComponent[i]) + for j in re.findall("([A-Za-z]+)", leftComponent[i]): + leftComponent[i] = leftComponent[i].replace(j, "") + for j in re.findall("([A-Za-z]+)", rightComponent[i]): + rightComponent[i] = rightComponent[i].replace(j, "") + return int(rightComponent[i]) - int(leftComponent[i]) + return len(rightComponent) - len(leftComponent) # if they are equal up their shortest version, then the latest is the longest version def validTerm(argsList): """ Takes the terms inputed and returns an organized list with no repeats and no poor word choices @@ -343,6 +383,11 @@ def validTerm(argsList): print("if you want to search with them anyway, run the command again with the -i arguement") exit() + # Converting certain terms into version terms + for i in range(len(argsList)): + if hasVersion(argsList[i]): + argsList[i] = getVersion(argsList[i])[0] # Getting first result from list + return argsList @@ -366,25 +411,50 @@ def searchdb(path="", terms=[], cols=[], lim=-1): db = dbFile.read().split('\n') for lines in db: if (lines != ""): - for ex in parseArgs.exclude: + for ex in parseArgs.exclude: # Removing positive lines with excluded values if parseArgs.case and ex in lines: break elif ex in lines.lower(): break else: for term in terms: - if parseArgs.title: - line = lines.split(",")[2] - if parseArgs.case: - if term not in line: + if type(term) is str: # separate versions from search terms + if parseArgs.title: + line = lines.split(",")[2] + if parseArgs.case: + if term not in line: + break + elif term not in line.lower(): break - elif term not in line.lower(): - break - elif parseArgs.case: - if term not in lines: + elif parseArgs.case: + if term not in lines: + break + elif term not in lines.lower(): break - elif term not in lines.lower(): - break + elif type(term) is tuple: + line = lines.split(",")[2] + versions = getVersion(line) + versionCompatible = False # helps for the or status here + if (len(versions) == 0): + break # if no versions could be detected in line, throw out line + if (term[0] != "") and "<" not in term[0]: # version has r or s in front + for v in versions: + if (v[0].lower() != term[0]): + continue # skip this if version doesnt start with same tag + versionCompatible = versionCompatible or (cmpVersion(term[1], v[1]) >= 0) + # this will only ever be true if just one is true + if not versionCompatible: + break + elif "<" in term[0]: + for v in versions: + versionCompatible = versionCompatible or (cmpVersion(term[1], v[1]) <= 0) + if not versionCompatible: + break + else: + for v in versions: + versionCompatible = versionCompatible or (cmpVersion(term[1], v[1]) >= 0) + if not versionCompatible: + break else: for i in cols: space = lines.split(",")