From 15b6bd21c1138d2c862568986d9396ab02d2951e Mon Sep 17 00:00:00 2001 From: sscottgvit <sscott@govanguard.com> Date: Mon, 20 Nov 2023 19:18:52 -0600 Subject: [PATCH] Updates --- CHANGELOG.txt | 7 +++++++ app/ApplicationInfo.py | 4 ++-- buildHugeNmapTest.py | 37 +++++++++++++++++++++++++++++++++---- controller/controller.py | 3 +++ debian/changelog | 9 +++++++++ debian/control | 2 +- ui/view.py | 10 ++++++++++ 7 files changed, 65 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 48fdd59c..5d109203 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -1,3 +1,10 @@ +LEGION 0.4.3 + +* Revise NMAP import process +* Fix import progress calculations +* Doubleckick to copy hostname (Linux only) +* Script to generate huge bogus NMAP XML imports for testing. + LEGION 0.4.2 * Tweak the screenshooter to use eyewitness as suggested by daniruiz diff --git a/app/ApplicationInfo.py b/app/ApplicationInfo.py index cec3597b..c4eb6a6a 100644 --- a/app/ApplicationInfo.py +++ b/app/ApplicationInfo.py @@ -18,8 +18,8 @@ applicationInfo = { "name": "LEGION", - "version": "0.4.2", - "build": '1700525714', + "version": "0.4.3", + "build": '1700529501', "author": "Gotham Security", "copyright": "2023", "links": ["http://github.com/GoVanguard/legion/issues", "https://gotham-security.com/legion"], diff --git a/buildHugeNmapTest.py b/buildHugeNmapTest.py index d0928b4c..feaf03fe 100644 --- a/buildHugeNmapTest.py +++ b/buildHugeNmapTest.py @@ -1,5 +1,5 @@ import xml.etree.ElementTree as ET -from random import randint, choice, sample +from random import randint, choice, choices, sample import datetime def generate_nmap_xml(num_hosts=1000, base_subnet="172.16"): @@ -62,20 +62,49 @@ def generate_nmap_xml(num_hosts=1000, base_subnet="172.16"): "afp": {"product": "Netatalk AFP", "version": "3.1.12"} } + # Expanded lists for generating hostnames + colors = ["Red", "Blue", "Green", "Yellow", "Purple", "Orange", "Cyan", "Magenta", "Lime", "Pink"] + foods = ["Apple", "Burger", "Cake", "Dumpling", "Eclair", "Pizza", "Sushi", "Taco", "Waffle", "Bagel"] + cities = ["Tokyo", "Paris", "London", "NewYork", "Sydney", "Berlin", "Rome", "Madrid", "Moscow", "Beijing"] + verbs = ["Jumping", "Running", "Flying", "Swimming", "Dancing", "Singing", "Playing", "Walking", "Reading", "Writing"] + + # Unique hostname tracker + generated_hostnames = set() + + # Function to create unique random hostnames + def generate_hostname(): + while True: + parts = [choice(colors), choice(foods), choice(cities), choice(verbs)] + hostname = '.'.join(parts) + # Ensure uniqueness by appending a number if needed + if hostname not in generated_hostnames: + generated_hostnames.add(hostname) + return hostname + else: + hostname += str(randint(0, 9999)) + if hostname not in generated_hostnames: + generated_hostnames.add(hostname) + return hostname + # Function to create a random IP address within the extended subnet range def random_ip(base_subnet, host_number): subnet_third_octet = host_number // 254 host_fourth_octet = host_number % 254 + 1 return f"{base_subnet}.{subnet_third_octet}.{host_fourth_octet}" - # Generating hosts with updated IP address method + # Generating hosts with updated IP address and hostname method for i in range(num_hosts): host_os = choice(list(os_services.keys())) host = ET.Element("host") ET.SubElement(host, "status", {"state": "up", "reason": "arp-response", "reason_ttl": "0"}) ET.SubElement(host, "address", {"addr": random_ip(base_subnet, i), "addrtype": "ipv4"}) - ET.SubElement(host, "hostnames") + + # Hostnames + hostnames = ET.SubElement(host, "hostnames") + num_hostnames = randint(1, 3) # Random number of hostnames per host + for _ in range(num_hostnames): + ET.SubElement(hostnames, "hostname", {"name": generate_hostname(), "type": "user"}) # Ports ports = ET.SubElement(host, "ports") @@ -135,7 +164,7 @@ def random_ip(base_subnet, host_number): xml_str = xml_header + '\n' + ET.tostring(nmaprun, encoding='unicode', method='xml') return xml_str -def save_nmap_xml(filename, num_hosts=1000, base_subnet="172.16"): +def save_nmap_xml(filename, num_hosts=200, base_subnet="172.16"): # Generate the XML content xml_content = generate_nmap_xml(num_hosts, base_subnet) diff --git a/controller/controller.py b/controller/controller.py index 453f7011..0b33214d 100644 --- a/controller/controller.py +++ b/controller/controller.py @@ -236,6 +236,9 @@ def closeProject(self): self.view.updateProcessesTableView() # clear process table self.logic.projectManager.closeProject(self.logic.activeProject) + def copyToClipboard(self, data): + clipboard = QtWidgets.QApplication.clipboard() + clipboard.setText(data) # Assuming item.text() contains the IP or hostname @timing def addHosts(self, targetHosts, runHostDiscovery, runStagedNmap, nmapSpeed, scanMode, nmapOptions = []): diff --git a/debian/changelog b/debian/changelog index 85075016..1aeb8142 100644 --- a/debian/changelog +++ b/debian/changelog @@ -32,3 +32,12 @@ legion (0.4.2-0) UNRELEASED; urgency=medium * Fix typo in startLegion.sh -- Shane Scott <sscot@gotham-security.com> Mon, 20 Nov 2023 12:50:55 -0600 + +legion (0.4.3-0) UNRELEASED; urgency=medium + + * Revise NMAP import process + * Fix import progress calculations + * Doubleckick to copy hostname (Linux only) + * Script to generate huge bogus NMAP XML imports for testing. + + -- Shane Scott <sscott@gotham-security.com> Mon, 20 Nov 2023 19:17:00 -0600 diff --git a/debian/control b/debian/control index 304a99fd..30150457 100644 --- a/debian/control +++ b/debian/control @@ -4,7 +4,7 @@ Priority: optional Maintainer: GoVanguard <hello@gotham-security.com> Uploaders: Shane Scott <sscott@gotham-security.com> Build-Depends: debhelper, python3, python3-requests -Standards-Version: 0.4.2 +Standards-Version: 0.4.3 Homepage: https://github.com/GoVanguard/Legion Package: legion diff --git a/ui/view.py b/ui/view.py index 35c58eb3..ccfa3075 100644 --- a/ui/view.py +++ b/ui/view.py @@ -192,6 +192,7 @@ def initTables(self): # this function prepares the default settings for each ta self.HostsTableModel.sort(3, Qt.SortOrder.DescendingOrder) # Connect the clicked signal of the HostsTableView to the hostTableClick() method self.ui.HostsTableView.clicked.connect(self.hostTableClick) + self.ui.HostsTableView.doubleClicked.connect(self.hostTableDoubleClick) ## @@ -580,6 +581,15 @@ def hostTableClick(self): def connectServiceNamesTableClick(self): self.ui.ServiceNamesTableView.clicked.connect(self.serviceNamesTableClick) + + def hostTableDoubleClick(self, index): + # Get the item from the model using the index + model = self.ui.HostsTableView.model() + row = index.row() + new_index = model.index(row, 3) + data = model.data(new_index, QtCore.Qt.ItemDataRole.DisplayRole) + if data: + self.controller.copyToClipboard(data) def serviceNamesTableClick(self): if self.ui.ServiceNamesTableView.selectionModel().selectedRows():