diff --git a/app/hostmodels.py b/app/hostmodels.py index 5146dfa..84d4ad6 100644 --- a/app/hostmodels.py +++ b/app/hostmodels.py @@ -41,7 +41,7 @@ def headerData(self, section, orientation, role): if section < len(self.__headers): return self.__headers[section] else: - return "!not implemented" + return "not implemented in view model" def data(self, index, role): # this method takes care of how the information is displayed if role == QtCore.Qt.DecorationRole: # to show the operating system icon instead of text @@ -108,6 +108,8 @@ def data(self, index, role): # this metho value = self.__hosts[row]['state'] elif column == 15: value = self.__hosts[row]['count'] + else: + value = 'Not set in view model' return value if role == QtCore.Qt.FontRole: diff --git a/app/logic.py b/app/logic.py index da15eb5..a2606cd 100644 --- a/app/logic.py +++ b/app/logic.py @@ -19,6 +19,8 @@ from app.auxiliary import * from ui.ancillaryDialog import * from six import u as unicode +from pyShodan import PyShodan +from scripts.python import pyShodan class Logic(): def __init__(self): @@ -562,7 +564,7 @@ def isCanceledProcess(self, procId): return True return False -class ShodanImporter(QtCore.QThread): +class PythonImporter(QtCore.QThread): tick = QtCore.pyqtSignal(int, name="changed") # New style signal done = QtCore.pyqtSignal(name="done") # New style signal schedule = QtCore.pyqtSignal(object, bool, name="schedule") # New style signal @@ -571,6 +573,9 @@ class ShodanImporter(QtCore.QThread): def __init__(self): QtCore.QThread.__init__(self, parent=None) self.output = '' + self.hostIp = '' + self.pythonScriptDispatch = {'pyShodan': pyShodan.PyShodanScript()} + self.pythonScriptObj = None self.importProgressWidget = ProgressWidget('Importing shodan data..') def tsLog(self, msg): @@ -579,8 +584,11 @@ def tsLog(self, msg): def setDB(self, db): self.db = db - def setFilename(self, filename): - self.filename = filename + def setHostIp(self, hostIp): + self.hostIp = hostIp + + def setPythonScript(self, pythonScript): + self.pythonScriptObj = self.pythonScriptDispatch[pythonScript] def setOutput(self, output): self.output = output @@ -590,22 +598,15 @@ def run(self): # it is nece session = self.db.session() startTime = time() self.db.dbsemaphore.acquire() # ensure that while this thread is running, no one else can write to the DB - - for h in parser.getAllHosts(): # create all the hosts that need to be created - db_host = session.query(hostObj).filter_by(ip=h.ip).first() - - if not db_host: # if host doesn't exist in DB, create it first - hid = hostObj(osMatch='', osAccuracy='', ip=h.ip, ipv4=h.ipv4, ipv6=h.ipv6, macaddr=h.macaddr, status=h.status, hostname=h.hostname, vendor=h.vendor, uptime=h.uptime, \ - lastboot=h.lastboot, distance=h.distance, state=h.state, count=h.count) - self.tsLog("Adding db_host") - session.add(hid) - else: - self.tsLog("Found db_host already in db") + #self.setPythonScript(self.pythonScript) + db_host = session.query(hostObj).filter_by(ip = self.hostIp).first() + self.pythonScriptObj.setDbHost(db_host) + self.pythonScriptObj.setSession(session) + self.pythonScriptObj.run() session.commit() self.db.dbsemaphore.release() # we are done with the DB - self.tsLog('Finished in '+ str(time()-startTime) + ' seconds.') + self.tsLog('Finished in ' + str(time() - startTime) + ' seconds.') self.done.emit() - self.schedule.emit(parser, self.output == '') # call the scheduler (if there is no terminal output it means we imported nmap) except Exception as e: self.tsLog(e) diff --git a/controller/controller.py b/controller/controller.py index 826519f..b136419 100644 --- a/controller/controller.py +++ b/controller/controller.py @@ -28,7 +28,7 @@ class Controller(): def __init__(self, view, logic): self.name = "LEGION" self.version = '0.3.5' - self.build = '1557146732' + self.build = '1557176518' self.author = 'GoVanguard' self.copyright = '2019' self.links = ['http://github.com/GoVanguard/legion/issues', 'https://GoVanguard.io/legion'] @@ -49,7 +49,7 @@ def __init__(self, view, logic): self.loadSettings() # creation of context menu actions from settings file and set up of various settings self.initNmapImporter() - self.initShodanImporter() + self.initPythonImporter() self.initScreenshooter() self.initBrowserOpener() self.start() # initialisations (globals, etc) @@ -64,7 +64,7 @@ def start(self, title='*untitled'): self.fastProcessesRunning = 0 # counts the number of fast processes currently running self.slowProcessesRunning = 0 # counts the number of slow processes currently running self.nmapImporter.setDB(self.logic.db) # tell nmap importer which db to use - self.shodanImporter.setDB(self.logic.db) + self.pythonImporter.setDB(self.logic.db) self.updateOutputFolder() # tell screenshooter where the output folder is self.view.start(title) @@ -74,11 +74,11 @@ def initNmapImporter(self): self.nmapImporter.schedule.connect(self.scheduler) # run automated attacks self.nmapImporter.log.connect(self.view.ui.LogOutputTextView.append) - def initShodanImporter(self): - self.shodanImporter = ShodanImporter() - self.shodanImporter.done.connect(self.importFinished) - self.shodanImporter.schedule.connect(self.scheduler) # run automated attacks - self.shodanImporter.log.connect(self.view.ui.LogOutputTextView.append) + def initPythonImporter(self): + self.pythonImporter = PythonImporter() + self.pythonImporter.done.connect(self.importFinished) + self.pythonImporter.schedule.connect(self.scheduler) # run automated attacks + self.pythonImporter.log.connect(self.view.ui.LogOutputTextView.append) def initScreenshooter(self): self.screenshooter = Screenshooter(self.settings.general_screenshooter_timeout) # screenshot taker object (different thread) @@ -316,6 +316,8 @@ def handleHostAction(self, ip, hostid, actions, action): if 'nmap' in name: # to make sure different nmap scans appear under the same tool name name = 'nmap' invisibleTab = True + elif 'python-script' in name: + invisibleTab = True # remove all chars that are not alphanumeric from tool name (used in the outputfile's name) outputfile = self.logic.runningfolder+"/"+re.sub("[^0-9a-zA-Z]", "", str(name))+"/"+getTimestamp()+"-"+re.sub("[^0-9a-zA-Z]", "", str(self.settings.hostActions[i][1]))+"-"+ip command = str(self.settings.hostActions[i][2]) @@ -388,6 +390,8 @@ def handleServiceNameAction(self, targets, actions, action, restoring=True): if 'nmap' in tabTitle: # we don't want to show nmap tabs restoring = True + elif 'python-script' in tabTitle: # we don't want to show nmap tabs + restoring = True self.runCommand(tool, tabTitle, ip[0], ip[1], ip[2], command, getTimestamp(True), outputfile, self.view.createNewTabForHost(ip[0], tabTitle, restoring)) break @@ -466,7 +470,7 @@ def handleProcessAction(self, selectedProcesses, action): # selectedPr self.view.updateProcessesTableView() return - if action.text() == 'Clear': # hide all the processes that are not running + if action.text() == 'Clear': # h.ide all the processes that are not running self.logic.toggleProcessDisplayStatus() self.view.updateProcessesTableView() @@ -723,6 +727,8 @@ def processCrashed(self, proc): self.logic.storeProcessCrashStatusInDB(str(proc.id)) log.info('Process {qProcessId} Crashed!'.format(qProcessId=str(proc.id))) qProcessOutput = "\n\t" + str(proc.display.toPlainText()).replace('\n','').replace("b'","") + #self.view.closeHostToolTab(self, index)) + self.view.findFinishedServiceTab(str(self.logic.getPidForProcess(str(proc.id)))) log.info('Process {qProcessId} Output: {qProcessOutput}'.format(qProcessId=str(proc.id), qProcessOutput=qProcessOutput)) # this function handles everything after a process ends @@ -732,13 +738,21 @@ def processFinished(self, qProcess): if not self.logic.isKilledProcess(str(qProcess.id)): # if process was not killed if not qProcess.outputfile == '': self.logic.moveToolOutput(qProcess.outputfile) # move tool output from runningfolder to output folder if there was an output file - - if 'nmap' in qProcess.name: # if the process was nmap, use the parser to store it + print(qProcess.command) + if 'nmap' in qProcess.command : # if the process was nmap, use the parser to store it if qProcess.exitCode() == 0: # if the process finished successfully newoutputfile = qProcess.outputfile.replace(self.logic.runningfolder, self.logic.outputfolder) self.nmapImporter.setFilename(str(newoutputfile)+'.xml') self.nmapImporter.setOutput(str(qProcess.display.toPlainText())) self.nmapImporter.start() + elif 'PythonScript' in qProcess.command: + pythonScript = str(qProcess.command).split(' ')[2] + print('PythonImporter running for script: {0}'.format(pythonScript)) + if qProcess.exitCode() == 0: # if the process finished successfully + self.pythonImporter.setOutput(str(qProcess.display.toPlainText())) + self.pythonImporter.setHostIp(str(qProcess.hostIp)) + self.pythonImporter.setPythonScript(pythonScript) + self.pythonImporter.start() exitCode = qProcess.exitCode() if exitCode != 0 and exitCode != 255: log.info("Process {qProcessId} exited with code {qProcessExitCode}".format(qProcessId=qProcess.id, qProcessExitCode=qProcess.exitCode())) @@ -814,6 +828,8 @@ def runToolsFor(self, service, ip, port, protocol='tcp'): if 'nmap' in tabTitle: # we don't want to show nmap tabs restoring = True + elif 'python-script' in tabTitle: + restoring = True tab = self.view.ui.HostsTabWidget.tabText(self.view.ui.HostsTabWidget.currentIndex()) self.runCommand(tool[0], tabTitle, ip, port, protocol, command, getTimestamp(True), outputfile, self.view.createNewTabForHost(ip, tabTitle, not (tab == 'Hosts'))) diff --git a/db/database.py b/db/database.py index 08e7b43..93901cf 100644 --- a/db/database.py +++ b/db/database.py @@ -284,6 +284,14 @@ def __init__(self, **kwargs): self.distance = kwargs.get('distance') or 'unknown' self.state = kwargs.get('state') or 'unknown' self.count = kwargs.get('count') or 'unknown' + self.city = kwargs.get('city') or 'unknown' + self.countryCode = kwargs.get('countryCode') or 'unknown' + self.postalCode = kwargs.get('postalCode') or 'unknown' + self.longitude = kwargs.get('longitude') or 'unknown' + self.latitude = kwargs.get('latitude') or 'unknown' + self.isp = kwargs.get('isp') or 'unknown' + self.asn = kwargs.get('asn') or 'unknown' + class note(Base): diff --git a/deps/installDeps.sh b/deps/installDeps.sh index f87b322..e63259f 100644 --- a/deps/installDeps.sh +++ b/deps/installDeps.sh @@ -9,4 +9,10 @@ source ./deps/apt.sh apt-get update -m echo "Installing deps..." -DEBIAN_FRONTEND="noninteractive" apt-get -yqqqm --allow-unauthenticated --force-yes -o DPkg::Options::="--force-overwrite" -o DPkg::Options::="--force-confdef" install nmap finger hydra nikto whatweb nbtscan nfs-common rpcbind smbclient sra-toolkit ldap-utils sslscan rwho medusa x11-apps cutycapt leafpad xvfb imagemagick eog hping3 sqlmap wapiti libqt5core5a python-pip python-impacket ruby perl dnsmap urlscan git xsltproc +DEBIAN_FRONTEND="noninteractive" apt-get -yqqqm --allow-unauthenticated --force-yes -o DPkg::Options::="--force-overwrite" -o DPkg::Options::="--force-confdef" install nmap finger hydra nikto nbtscan nfs-common rpcbind smbclient sra-toolkit ldap-utils sslscan rwho x11-apps cutycapt leafpad xvfb imagemagick eog hping3 sqlmap wapiti libqt5core5a python-pip ruby perl urlscan git xsltproc + +DEBIAN_FRONTEND="noninteractive" apt-get -yqqqm --allow-unauthenticated --force-yes -o DPkg::Options::="--force-overwrite" -o DPkg::Options::="--force-confdef" dnsmap +DEBIAN_FRONTEND="noninteractive" apt-get -yqqqm --allow-unauthenticated --force-yes -o DPkg::Options::="--force-overwrite" -o DPkg::Options::="--force-confdef" wapiti +DEBIAN_FRONTEND="noninteractive" apt-get -yqqqm --allow-unauthenticated --force-yes -o DPkg::Options::="--force-overwrite" -o DPkg::Options::="--force-confdef" python-impacket +DEBIAN_FRONTEND="noninteractive" apt-get -yqqqm --allow-unauthenticated --force-yes -o DPkg::Options::="--force-overwrite" -o DPkg::Options::="--force-confdef" whatweb +DEBIAN_FRONTEND="noninteractive" apt-get -yqqqm --allow-unauthenticated --force-yes -o DPkg::Options::="--force-overwrite" -o DPkg::Options::="--force-confdef" medusa diff --git a/deps/installPythonLibs.sh b/deps/installPythonLibs.sh index 90e9179..059c7af 100644 --- a/deps/installPythonLibs.sh +++ b/deps/installPythonLibs.sh @@ -5,3 +5,5 @@ source ./deps/detectPython.sh # Setup Python deps ${PIP3BIN} install -r requirements.txt --upgrade ${PIP3BIN} install service-identity --upgrade + +${PIP3BIN} ./deps/primeExploitDb.py diff --git a/deps/primeExploitDb.py b/deps/primeExploitDb.py new file mode 100644 index 0000000..202289a --- /dev/null +++ b/deps/primeExploitDb.py @@ -0,0 +1,9 @@ +from pyExploitDb import PyExploitDb + +def prime(): + pEdb = PyExploitDb() + pEdb.debug = False + pEdb.openFile() + +if __name__ == "__main__": + prime() diff --git a/deps/setupWsl.sh b/deps/setupWsl.sh index 3dabfa4..1d35be0 100644 --- a/deps/setupWsl.sh +++ b/deps/setupWsl.sh @@ -1,13 +1,24 @@ #!/bin/bash # Setup linked Windows NMAP -if [ ! -f "/sbin/nmap" ] +if [ -f "/usr/bin/nmap" ] +then + nmapBinCheck=$(cat /usr/bin/nmap | grep -c "nmap.exe") +else + nmapBinCheck=1 +fi + +if [ ! -f "/sbin/nmap" ] | [ ${nmapBinCheck} -eq 0 ] then echo "Installing Link to Windows NMAP..." - mv /usr/bin/nmap /usr/bin/nmap_lin + today=$(date +%s) + mv /usr/bin/nmap /usr/bin/nmap_lin_${today} cp ./deps/nmap-wsl.sh /sbin/nmap chmod a+x /sbin/nmap - ln -s /sbin/nmap /usr/bin/nmap + if [ ! -f "/sbin/nmap" ] + then + ln -s /sbin/nmap /usr/bin/nmap + fi else echo "Link to Windows NMAP already exists; skipping." fi diff --git a/legion.conf b/legion.conf index bff5e3b..b6f58ba 100644 --- a/legion.conf +++ b/legion.conf @@ -29,8 +29,8 @@ nmap-fast-tcp=Run nmap (fast TCP), nmap -Pn -sV -sC -F -T4 -vvvv [IP] -oA \"[OUT nmap-fast-udp=Run nmap (fast UDP), "nmap -n -Pn -sU -F --min-rate=1000 -vvvvv [IP] -oA \"[OUTPUT]\"" nmap-full-tcp=Run nmap (full TCP), nmap -Pn -sV -sC -O -p- -T4 -vvvvv [IP] -oA \"[OUTPUT]\" nmap-full-udp=Run nmap (full UDP), nmap -n -Pn -sU -p- -T4 -vvvvv [IP] -oA \"[OUTPUT]\" -nmap-script-Shodan=Run nmap script - Shodan, "nmap -sn -Pn -n --script=./scripts/nmap/shodan-api.nse --script-args shodan-api.apikey=SNYEkE0gdwNu9BRURVDjWPXePCquXqht [IP] -vvvv -oA [OUTPUT]" -nmap-script-Shodan-HQ=Run nmap script - Shodan HQ, "nmap -sn -Pn -n --script=./scripts/nmap/shodan-hq.nse --script-args apikey=SNYEkE0gdwNu9BRURVDjWPXePCquXqht [IP] -vvvv -oA [OUTPUT]" +python-script-PyShodan=Run PyShodan python script, /bin/echo PythonScript pyShodan +python-script-CrashMe=Run CrashMe python scripy, python3 ./scripts/python/dummy.py nmap-script-Vulners=Run nmap script - Vulners, "nmap -sV --script=./scripts/nmap/vulners.nse -vvvv [IP] -oA \"[OUTPUT]\"" nmap-udp-1000=Run nmap (top 1000 quick UDP), "nmap -n -Pn -sU --min-rate=1000 -vvvvv [IP] -oA \"[OUTPUT]\"" unicornscan-full-udp=Run unicornscan (full UDP), unicornscan -mU -Ir 1000 [IP]:a -v diff --git a/parsers/CVE.py b/parsers/CVE.py index 4173692..c4a3833 100644 --- a/parsers/CVE.py +++ b/parsers/CVE.py @@ -15,12 +15,12 @@ class CVE: exploitUrl = '' def __init__(self, cveData): - self.name = cveData['id'] - self.product = cveData['product'] - self.version = cveData['version'] - self.url = cveData['url'] - self.source = cveData['source'] - self.severity = cveData['severity'] - self.exploitId = cveData['exploitId'] - self.exploit = cveData['exploit'] - self.exploitUrl = cveData['exploitUrl'] + self.name = cveData.get('id', 'unknown') + self.product = cveData.get('product', 'unknown') + self.version = cveData.get('version', 'unknown') + self.url = cveData.get('url', 'unknown') + self.source = cveData.get('source', 'unknown') + self.severity = cveData.get('severity', 'unknown') + self.exploitId = cveData.get('exploitId', 'unknown') + self.exploit = cveData.get('exploit', 'unknown') + self.exploitUrl = cveData.get('exploitUrl', 'unknown') diff --git a/parsers/Script.py b/parsers/Script.py index 76e48ec..2de8df5 100644 --- a/parsers/Script.py +++ b/parsers/Script.py @@ -81,7 +81,7 @@ def processVulnersScriptOutput(self, vulnersOutput): if exploitResults: resultCveDict['exploitId'] = exploitResults['edbid'] resultCveDict['exploit'] = exploitResults['exploit'] - resultCveDict['exploitUrl'] = "https://www.exploit-db.com/exploits/{0}".format(resultCveDict['exploit']) + resultCveDict['exploitUrl'] = "https://www.exploit-db.com/exploits/{0}".format(resultCveDict['exploitId']) resultCvesProcessed.append(resultCveDict) resultCpeDetails['cves'] = resultCvesProcessed resultsDict[resultCpeData[3]] = resultCpeDetails diff --git a/scripts/python/__init__.py b/scripts/python/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/scripts/python/dummy.py b/scripts/python/dummy.py new file mode 100644 index 0000000..3548452 --- /dev/null +++ b/scripts/python/dummy.py @@ -0,0 +1,5 @@ +#!/usr/bin/python3 + +import sys +print('Dummy!') +sys.exit(1) diff --git a/scripts/python/pyShodan.py b/scripts/python/pyShodan.py new file mode 100644 index 0000000..108bc32 --- /dev/null +++ b/scripts/python/pyShodan.py @@ -0,0 +1,31 @@ +from pyShodan import PyShodan + +class PyShodanScript(): + def __init__(self): + self.dbHost = None + self.session = None + + def setDbHost(self, dbHost): + self.dbHost = dbHost + + def setSession(self, session): + self.session = session + + def run(self): + print('Running PyShodan Class') + if self.dbHost: + pyShodanObj = PyShodan() + pyShodanObj.apiKey = "SNYEkE0gdwNu9BRURVDjWPXePCquXqht" + pyShodanObj.createSession() + pyShodanResults = pyShodanObj.searchIp(self.dbHost.ipv4, allData = True) + if pyShodanResults: + self.dbHost.latitude = pyShodanResults.get('latitude', 'unknown') + self.dbHost.longitude = pyShodanResults.get('longitude', 'unknown') + self.dbHost.asn = pyShodanResults.get('asn', 'unknown') + self.dbHost.ips = pyShodanResults.get('isp', 'unknown') + self.dbHost.city = pyShodanResults.get('city', 'unknown') + self.dbHost.countryCode = pyShodanResults.get('country_code', 'unknown') + self.session.add(self.dbHost) + +if __name__ == "__main__": + pass diff --git a/ui/dialogs.py b/ui/dialogs.py index 1117596..5149392 100644 --- a/ui/dialogs.py +++ b/ui/dialogs.py @@ -568,6 +568,22 @@ def setupLayout(self): self.MacLayout.addWidget(self.MacLabel) self.MacLayout.addWidget(self.MacText) self.MacLayout.addStretch() + + self.AsnLabel = QtWidgets.QLabel() + self.AsnText = QtWidgets.QLabel() + self.AsnLayout = QtWidgets.QHBoxLayout() + self.AsnLayout.addSpacing(20) + self.AsnLayout.addWidget(self.AsnLabel) + self.AsnLayout.addWidget(self.AsnText) + self.AsnLayout.addStretch() + + self.IspLabel = QtWidgets.QLabel() + self.IspText = QtWidgets.QLabel() + self.IspLayout = QtWidgets.QHBoxLayout() + self.IspLayout.addSpacing(20) + self.IspLayout.addWidget(self.IspLabel) + self.IspLayout.addWidget(self.IspText) + self.IspLayout.addStretch() self.dummyLabel = QtWidgets.QLabel() self.dummyText = QtWidgets.QLabel() @@ -608,6 +624,8 @@ def setupLayout(self): self.IP4Label.setText('IPv4:') self.IP6Label.setText('IPv6:') self.MacLabel.setText('MAC:') + self.AsnLabel.setText('ASN:') + self.IspLabel.setText('ISP:') self.OSLabel.setText('Operating System') self.OSLabel.setFont(font) self.OSNameLabel.setText('Name:') @@ -628,6 +646,8 @@ def setupLayout(self): self.vlayout_2.addLayout(self.IP4Layout) self.vlayout_2.addLayout(self.IP6Layout) self.vlayout_2.addLayout(self.MacLayout) + self.vlayout_2.addLayout(self.AsnLayout) + self.vlayout_2.addLayout(self.IspLayout) self.vlayout_2.addLayout(self.dummyLayout) self.hlayout_1.addLayout(self.vlayout_1) @@ -657,5 +677,7 @@ def updateFields(self, **kwargs): self.IP4Text.setText(kwargs.get('ipv4') or 'unknown') self.IP6Text.setText(kwargs.get('ipv6') or 'unknown') self.MacText.setText(kwargs.get('macaddr') or 'unknown') + self.AsnText.setText(kwargs.get('asn') or 'unknown') + self.IspText.setText(kwargs.get('isp') or 'unknown') self.OSNameText.setText(kwargs.get('osMatch') or 'unknown') self.OSAccuracyText.setText(kwargs.get('osAccuracy') or 'unknown') diff --git a/ui/view.py b/ui/view.py index 25dfbd6..2929f34 100644 --- a/ui/view.py +++ b/ui/view.py @@ -175,8 +175,8 @@ def startConnections(self): # signal ini def initTables(self): # this function prepares the default settings for each table # hosts table (left) - headers = ["Id", "OS", "Accuracy", "Host", "IPv4", "IPv6", "Mac", "Status", "Hostname", "Vendor", "Uptime", "Lastboot", "Distance", "CheckedHost", "State", "Count", "Padding"] - setTableProperties(self.ui.HostsTableView, len(headers), [0, 2, 4, 5, 6, 7, 8, 9, 10 , 11, 12, 13, 14, 15, 16]) + headers = ["Id", "OS", "Accuracy", "Host", "IPv4", "IPv6", "Mac", "Status", "Hostname", "Vendor", "Uptime", "Lastboot", "Distance", "CheckedHost", "State", "Count", "Closed"] + setTableProperties(self.ui.HostsTableView, len(headers), [0, 2, 4, 5, 6, 7, 8, 9, 10 , 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24]) self.ui.HostsTableView.horizontalHeader().resizeSection(1, 30) # service names table (left) @@ -184,7 +184,7 @@ def initTables(self): # this funct setTableProperties(self.ui.ServiceNamesTableView, len(headers)) # cves table (right) - headers = ["Id", "Severity", "Product", "Version", "URL", "Source", "Exploit ID", "Exploit", "Exploit URL"] + headers = ["CVE Id", "Severity", "Product", "Version", "CVE URL", "Source", "ExploitDb ID", "ExploitDb", "ExploitDb URL"] setTableProperties(self.ui.CvesTableView, len(headers)) self.ui.CvesTableView.setSortingEnabled(True) @@ -931,16 +931,17 @@ def contextMenuScreenshot(self, pos): #################### LEFT PANEL INTERFACE UPDATE FUNCTIONS #################### def updateHostsTableView(self): - headers = ["Id", "OS", "Accuracy", "Host", "IPv4", "IPv6", "Mac", "Status", "Hostname", "Vendor", "Uptime", "Lastboot", "Distance", "CheckedHost", "State", "Count", "Padding"] + headers = ["Id", "OS", "Accuracy", "Host", "IPv4", "IPv6", "Mac", "Status", "Hostname", "Vendor", "Uptime", "Lastboot", "Distance", "CheckedHost", "State", "Count", "Closed"] + print(str(self.controller.getHostsFromDB(self.filters))) self.HostsTableModel = HostsTableModel(self.controller.getHostsFromDB(self.filters), headers) self.ui.HostsTableView.setModel(self.HostsTableModel) self.lazy_update_hosts = False # to indicate that it doesn't need to be updated anymore - for i in [0,2,4,5,6,7,8,9,10,11,12,13,14,15,16]: # hide some columns + for i in [0, 2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24]: # hide some columns self.ui.HostsTableView.setColumnHidden(i, True) - self.ui.HostsTableView.horizontalHeader().resizeSection(1,30) + self.ui.HostsTableView.horizontalHeader().resizeSection(1, 30) self.HostsTableModel.sort(3, Qt.DescendingOrder) ips = [] # ensure that there is always something selected @@ -991,7 +992,7 @@ def updateToolsTableView(self): self.lazy_update_tools = False # to indicate that it doesn't need to be updated anymore # Hides columns we don't want to see - for i in [0, 1, 2, 3, 4, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]: # hide some columns + for i in [0, 1, 2, 3, 4, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]: # hide some columns self.ui.ToolsTableView.setColumnHidden(i, True) tools = [] # ensure that there is always something selected @@ -1060,7 +1061,7 @@ def updateInformationView(self, hostIP): else: counterFiltered = 65535 - counterOpen - counterClosed - self.hostInfoWidget.updateFields(status=host.status, openPorts=counterOpen, closedPorts=counterClosed, filteredPorts=counterFiltered, ipv4=host.ipv4, ipv6=host.ipv6, macaddr=host.macaddr, osMatch=host.osMatch, osAccuracy=host.osAccuracy) + self.hostInfoWidget.updateFields(status=host.status, openPorts=counterOpen, closedPorts=counterClosed, filteredPorts=counterFiltered, ipv4=host.ipv4, ipv6=host.ipv6, macaddr=host.macaddr, osMatch=host.osMatch, osAccuracy=host.osAccuracy, asn=host.asn, isp=host.isp) def updateScriptsView(self, hostIP): headers = ["Id", "Script", "Port", "Protocol"] @@ -1088,7 +1089,7 @@ def updateScriptsView(self, hostIP): self.ui.ScriptsTableView.update() def updateCvesByHostView(self, hostIP): - headers = ["ID", "CVSS Score", "Product", "Version", "URL", "Source", "Exploit ID", "Exploit", "Exploit URL"] + headers = ["CVE Id", "CVSS Score", "Product", "Version", "CVE URL", "Source", "ExploitDb ID", "ExploitDb", "ExploitDb URL"] cves = self.controller.getCvesFromDB(hostIP) self.CvesTableModel = CvesTableModel(self, cves, headers) @@ -1550,6 +1551,13 @@ def findFinishedBruteTab(self, pid): self.bruteProcessFinished(self.ui.BruteTabWidget.widget(i)) return + def findFinishedServiceTab(self, pid): + for i in range(0, self.ui.ServicesTabWidget.count()): + if str(self.ui.ServicesTabWidget.widget(i).pid) == pid: + #self.bruteProcessFinished(self.ui.BruteTabWidget.widget(i)) + print("Close Tab: {0}".format(str(i))) + return + def blinkBruteTab(self, bWidget): self.ui.MainTabWidget.tabBar().setTabTextColor(1, QtGui.QColor('red')) for i in range(0, self.ui.BruteTabWidget.count()):