From 54c1ffd63cda4623f88864e9f1c965e671fd0a95 Mon Sep 17 00:00:00 2001 From: Jeroen Oudshoorn Date: Sun, 28 Jan 2024 22:02:57 +0100 Subject: [PATCH 01/19] Updated wiglewifi version to 1.6 --- pwnagotchi/grid.py | 2 +- pwnagotchi/plugins/default/gps.py | 2 +- pwnagotchi/plugins/default/grid.py | 17 ++++--- pwnagotchi/plugins/default/hashie.py | 6 +-- pwnagotchi/plugins/default/net-pos.py | 2 +- pwnagotchi/plugins/default/onlinehashcrack.py | 4 +- pwnagotchi/plugins/default/webgpsmap.py | 44 ++++++++----------- pwnagotchi/plugins/default/wigle.py | 10 ++--- pwnagotchi/plugins/default/wpa-sec.py | 2 +- pwnagotchi/utils.py | 10 ++--- 10 files changed, 45 insertions(+), 54 deletions(-) diff --git a/pwnagotchi/grid.py b/pwnagotchi/grid.py index 6c908dbd..82e0f88b 100644 --- a/pwnagotchi/grid.py +++ b/pwnagotchi/grid.py @@ -89,7 +89,7 @@ def update_data(last_session): 'uname': subprocess.getoutput("uname -a"), 'brain': brain, 'version': pwnagotchi.__version__, - 'build': "Pwnagotchi-Torch by Jayofelony", + 'build': "Test version", 'plugins': enabled, 'language': language, 'bettercap': subprocess.getoutput("bettercap -version").split(".\n\n")[1], diff --git a/pwnagotchi/plugins/default/gps.py b/pwnagotchi/plugins/default/gps.py index a351406b..0e5f958d 100644 --- a/pwnagotchi/plugins/default/gps.py +++ b/pwnagotchi/plugins/default/gps.py @@ -48,7 +48,7 @@ class GPS(plugins.Plugin): if self.running: info = agent.session() self.coordinates = info["gps"] - gps_filename = filename.replace(".pcap", ".gps.json") + gps_filename = filename.replace(".pcapng", ".gps.json") if self.coordinates and all([ # avoid 0.000... measurements diff --git a/pwnagotchi/plugins/default/grid.py b/pwnagotchi/plugins/default/grid.py index cdca794e..fbc3374e 100644 --- a/pwnagotchi/plugins/default/grid.py +++ b/pwnagotchi/plugins/default/grid.py @@ -5,22 +5,21 @@ import glob import re import pwnagotchi.grid as grid -import pwnagotchi.plugins import pwnagotchi.plugins as plugins -from pwnagotchi.utils import StatusFile, WifiInfo, extract_from_pcap +from pwnagotchi.utils import StatusFile, WifiInfo, extract_from_pcapng from threading import Lock def parse_pcap(filename): logging.info("grid: parsing %s ..." % filename) - net_id = os.path.basename(filename).replace('.pcap', '') + net_id = os.path.basename(filename).replace('.pcapng', '') if '_' in net_id: - # /root/handshakes/ESSID_BSSID.pcap + # /root/handshakes/ESSID_BSSID.pcapng essid, bssid = net_id.split('_') else: - # /root/handshakes/BSSID.pcap + # /root/handshakes/BSSID.pcapng essid, bssid = '', net_id mac_re = re.compile('[0-9a-fA-F]{12}') @@ -36,7 +35,7 @@ def parse_pcap(filename): } try: - info = extract_from_pcap(filename, [WifiInfo.BSSID, WifiInfo.ESSID]) + info = extract_from_pcapng(filename, [WifiInfo.BSSID, WifiInfo.ESSID]) except Exception as e: logging.error("grid: %s" % e) @@ -87,10 +86,10 @@ class Grid(plugins.Plugin): agent.view().on_unread_messages(self.unread_messages, self.total_messages) def check_handshakes(self, agent): - logging.debug("checking pcaps") + logging.debug("checking pcapng's") config = agent.config() - pcap_files = glob.glob(os.path.join(agent.config()['bettercap']['handshakes'], "*.pcap")) + pcap_files = glob.glob(os.path.join(agent.config()['bettercap']['handshakes'], "*.pcapng")) num_networks = len(pcap_files) reported = self.report.data_field_or('reported', default=[]) num_reported = len(reported) @@ -103,7 +102,7 @@ class Grid(plugins.Plugin): logging.debug(" exclude: %s" % config['main']['whitelist']) for pcap_file in pcap_files: - net_id = os.path.basename(pcap_file).replace('.pcap', '') + net_id = os.path.basename(pcap_file).replace('.pcapng', '') if net_id not in reported: if self.is_excluded(net_id, agent): logging.debug("skipping %s due to exclusion filter" % pcap_file) diff --git a/pwnagotchi/plugins/default/hashie.py b/pwnagotchi/plugins/default/hashie.py index cd41122b..b5c8e18a 100644 --- a/pwnagotchi/plugins/default/hashie.py +++ b/pwnagotchi/plugins/default/hashie.py @@ -82,12 +82,12 @@ class Hashie(plugins.Plugin): if os.path.isfile(fullpathNoExt + '.22000'): handshake_status.append('Already have {}.22000 (EAPOL)'.format(name)) elif self._writeEAPOL(filename): - handshake_status.append('Created {}.22000 (EAPOL) from pcap'.format(name)) + handshake_status.append('Created {}.22000 (EAPOL) from pcapng'.format(name)) if os.path.isfile(fullpathNoExt + '.16800'): handshake_status.append('Already have {}.16800 (PMKID)'.format(name)) elif self._writePMKID(filename): - handshake_status.append('Created {}.16800 (PMKID) from pcap'.format(name)) + handshake_status.append('Created {}.16800 (PMKID) from pcapng'.format(name)) if handshake_status: logging.info('[Hashie] Good news:\n\t' + '\n\t'.join(handshake_status)) @@ -111,7 +111,7 @@ class Hashie(plugins.Plugin): return False def _process_stale_pcaps(self, handshake_dir): - handshakes_list = [os.path.join(handshake_dir, filename) for filename in os.listdir(handshake_dir) if filename.endswith('.pcap')] + handshakes_list = [os.path.join(handshake_dir, filename) for filename in os.listdir(handshake_dir) if filename.endswith('.pcapng')] failed_jobs = [] successful_jobs = [] lonely_pcaps = [] diff --git a/pwnagotchi/plugins/default/net-pos.py b/pwnagotchi/plugins/default/net-pos.py index 3f226204..ef5f0c59 100644 --- a/pwnagotchi/plugins/default/net-pos.py +++ b/pwnagotchi/plugins/default/net-pos.py @@ -108,7 +108,7 @@ class NetPos(plugins.Plugin): return netpos["ts"] = int("%.0f" % time.time()) - netpos_filename = filename.replace('.pcap', '.net-pos.json') + netpos_filename = filename.replace('.pcapng', '.net-pos.json') logging.debug("NET-POS: Saving net-location to %s", netpos_filename) try: diff --git a/pwnagotchi/plugins/default/onlinehashcrack.py b/pwnagotchi/plugins/default/onlinehashcrack.py index aeb01dda..1eafb9fa 100644 --- a/pwnagotchi/plugins/default/onlinehashcrack.py +++ b/pwnagotchi/plugins/default/onlinehashcrack.py @@ -142,6 +142,6 @@ class OnlineHashCrack(plugins.Plugin): for row in csv.DictReader(cracked_list): if row['password']: filename = re.sub(r'[^a-zA-Z0-9]', '', row['ESSID']) + '_' + row['BSSID'].replace(':','') - if os.path.exists( os.path.join(handshake_dir, filename+'.pcap') ): - with open(os.path.join(handshake_dir, filename+'.pcap.cracked'), 'w') as f: + if os.path.exists( os.path.join(handshake_dir, filename+'.pcapng')): + with open(os.path.join(handshake_dir, filename+'.pcapng.cracked'), 'w') as f: f.write(row['password']) diff --git a/pwnagotchi/plugins/default/webgpsmap.py b/pwnagotchi/plugins/default/webgpsmap.py index f9f513d9..b03fef50 100644 --- a/pwnagotchi/plugins/default/webgpsmap.py +++ b/pwnagotchi/plugins/default/webgpsmap.py @@ -13,8 +13,8 @@ from dateutil.parser import parse webgpsmap shows existing position data stored in your /handshakes/ directory the plugin does the following: - - search for *.pcap files in your /handshakes/ dir - - for every found .pcap file it looks for a .geo.json or .gps.json or .paw-gps.json file with + - search for *.pcapng files in your /handshakes/ dir + - for every found .pcapng file it looks for a .geo.json or .gps.json or file with latitude+longitude data inside and shows this position on the map - if also an .cracked file with a plaintext password inside exist, it reads the content and shows the position as green instead of red and the password inside the infopox of the position @@ -87,7 +87,8 @@ class Webgpsmap(plugins.Plugin): # returns all positions try: self.ALREADY_SENT = list() - response_data = bytes(json.dumps(self.load_gps_from_dir(self.config['bettercap']['handshakes'])), "utf-8") + response_data = bytes( + json.dumps(self.load_gps_from_dir(self.config['bettercap']['handshakes'])), "utf-8") response_status = 200 response_mimetype = "application/json" response_header_contenttype = 'application/json' @@ -100,7 +101,8 @@ class Webgpsmap(plugins.Plugin): self.ALREADY_SENT = list() json_data = json.dumps(self.load_gps_from_dir(self.config['bettercap']['handshakes'])) html_data = self.get_html() - html_data = html_data.replace('var positions = [];', 'var positions = ' + json_data + ';positionsLoaded=true;drawPositions();') + html_data = html_data.replace('var positions = [];', + 'var positions = ' + json_data + ';positionsLoaded=true;drawPositions();') response_data = bytes(html_data, "utf-8") response_status = 200 response_mimetype = "application/xhtml+xml" @@ -163,7 +165,8 @@ class Webgpsmap(plugins.Plugin): all_files = os.listdir(handshake_dir) # print(all_files) - all_pcap_files = [os.path.join(handshake_dir, filename) for filename in all_files if filename.endswith('.pcap')] + all_pcap_files = [os.path.join(handshake_dir, filename) for filename in all_files if + filename.endswith('.pcapng')] all_geo_or_gps_files = [] for filename_pcap in all_pcap_files: filename_base = filename_pcap[:-5] # remove ".pcap" @@ -180,22 +183,18 @@ class Webgpsmap(plugins.Plugin): if check_for in all_files: filename_position = str(os.path.join(handshake_dir, check_for)) - logging.debug("[webgpsmap] search for .paw-gps.json") - check_for = os.path.basename(filename_base) + ".paw-gps.json" - if check_for in all_files: - filename_position = str(os.path.join(handshake_dir, check_for)) - logging.debug(f"[webgpsmap] end search for position data files and use {filename_position}") if filename_position is not None: all_geo_or_gps_files.append(filename_position) - # all_geo_or_gps_files = set(all_geo_or_gps_files) - set(SKIP) # remove skipped networks? No! + # all_geo_or_gps_files = set(all_geo_or_gps_files) - set(SKIP) # remove skipped networks? No! if newest_only: all_geo_or_gps_files = set(all_geo_or_gps_files) - set(self.ALREADY_SENT) - logging.info(f"[webgpsmap] Found {len(all_geo_or_gps_files)} position-data files from {len(all_pcap_files)} handshakes. Fetching positions ...") + logging.info( + f"[webgpsmap] Found {len(all_geo_or_gps_files)} position-data files from {len(all_pcap_files)} handshakes. Fetching positions ...") for pos_file in all_geo_or_gps_files: try: @@ -213,9 +212,7 @@ class Webgpsmap(plugins.Plugin): pos_type = 'gps' elif pos.type() == PositionFile.GEO: pos_type = 'geo' - elif pos.type() == PositionFile.PAWGPS: - pos_type = 'paw' - gps_data[ssid+"_"+mac] = { + gps_data[ssid + "_" + mac] = { 'ssid': ssid, 'mac': mac, 'type': pos_type, @@ -224,10 +221,10 @@ class Webgpsmap(plugins.Plugin): 'acc': pos.accuracy(), 'ts_first': pos.timestamp_first(), 'ts_last': pos.timestamp_last(), - } + } # get ap password if exist - check_for = os.path.basename(pos_file).split(".")[0] + ".pcap.cracked" + check_for = os.path.basename(pos_file).split(".")[0] + ".pcapng.cracked" if check_for in all_files: gps_data[ssid + "_" + mac]["pass"] = pos.password() @@ -265,7 +262,6 @@ class PositionFile: """ GPS = 1 GEO = 2 - PAWGPS = 3 def __init__(self, path): self._file = path @@ -282,7 +278,7 @@ class PositionFile: """ Returns the mac from filename """ - parsed_mac = re.search(r'.*_?([a-zA-Z0-9]{12})\.(?:gps|geo|paw-gps)\.json', self._filename) + parsed_mac = re.search(r'.*_?([a-zA-Z0-9]{12})\.(?:gps|geo)\.json', self._filename) if parsed_mac: mac = parsed_mac.groups()[0] return mac @@ -292,7 +288,7 @@ class PositionFile: """ Returns the ssid from filename """ - parsed_ssid = re.search(r'(.+)_[a-zA-Z0-9]{12}\.(?:gps|geo|paw-gps)\.json', self._filename) + parsed_ssid = re.search(r'(.+)_[a-zA-Z0-9]{12}\.(?:gps|geo)\.json', self._filename) if parsed_ssid: return parsed_ssid.groups()[0] return None @@ -333,7 +329,7 @@ class PositionFile: return_pass = None # 2do: make better filename split/remove extension because this one has problems with "." in path base_filename, ext1, ext2 = re.split('\.', self._file) - password_file_path = base_filename + ".pcap.cracked" + password_file_path = base_filename + ".pcapng.cracked" if os.path.isfile(password_file_path): try: password_file = open(password_file_path, 'r') @@ -354,8 +350,6 @@ class PositionFile: return PositionFile.GPS if self._file.endswith('.geo.json'): return PositionFile.GEO - if self._file.endswith('.paw-gps.json'): - return PositionFile.PAWGPS return None def lat(self): @@ -402,9 +396,7 @@ class PositionFile: def accuracy(self): if self.type() == PositionFile.GPS: - return 50.0 # a default - if self.type() == PositionFile.PAWGPS: - return 50.0 # a default + return 50.0 # a default if self.type() == PositionFile.GEO: try: return self._json['accuracy'] diff --git a/pwnagotchi/plugins/default/wigle.py b/pwnagotchi/plugins/default/wigle.py index 353660ea..11805c3b 100644 --- a/pwnagotchi/plugins/default/wigle.py +++ b/pwnagotchi/plugins/default/wigle.py @@ -7,7 +7,7 @@ import pwnagotchi from io import StringIO from datetime import datetime -from pwnagotchi.utils import WifiInfo, FieldNotFoundError, extract_from_pcap, StatusFile, remove_whitelisted +from pwnagotchi.utils import WifiInfo, FieldNotFoundError, extract_from_pcapng, StatusFile, remove_whitelisted from threading import Lock from pwnagotchi import plugins from pwnagotchi._version import __version__ as __pwnagotchi_version__ @@ -153,11 +153,11 @@ class Wigle(plugins.Plugin): no_err_entries = list() for gps_file in new_gps_files: if gps_file.endswith('.gps.json'): - pcap_filename = gps_file.replace('.gps.json', '.pcap') + pcap_filename = gps_file.replace('.gps.json', '.pcapng') if gps_file.endswith('.geo.json'): - pcap_filename = gps_file.replace('.geo.json', '.pcap') + pcap_filename = gps_file.replace('.geo.json', '.pcapng') if not os.path.exists(pcap_filename): - logging.debug("WIGLE: Can't find pcap for %s", gps_file) + logging.debug("WIGLE: Can't find pcapng for %s", gps_file) self.skip.append(gps_file) continue try: @@ -175,7 +175,7 @@ class Wigle(plugins.Plugin): self.skip.append(gps_file) continue try: - pcap_data = extract_from_pcap(pcap_filename, [WifiInfo.BSSID, + pcap_data = extract_from_pcapng(pcap_filename, [WifiInfo.BSSID, WifiInfo.ESSID, WifiInfo.ENCRYPTION, WifiInfo.CHANNEL, diff --git a/pwnagotchi/plugins/default/wpa-sec.py b/pwnagotchi/plugins/default/wpa-sec.py index 696b53b4..42f1c29f 100644 --- a/pwnagotchi/plugins/default/wpa-sec.py +++ b/pwnagotchi/plugins/default/wpa-sec.py @@ -98,7 +98,7 @@ class WpaSec(plugins.Plugin): reported = self.report.data_field_or('reported', default=list()) handshake_dir = config['bettercap']['handshakes'] handshake_filenames = os.listdir(handshake_dir) - handshake_paths = [os.path.join(handshake_dir, filename) for filename in handshake_filenames if filename.endswith('.pcap')] + handshake_paths = [os.path.join(handshake_dir, filename) for filename in handshake_filenames if filename.endswith('.pcapng')] handshake_paths = remove_whitelisted(handshake_paths, config['main']['whitelist']) handshake_new = set(handshake_paths) - set(reported) - set(self.skip) diff --git a/pwnagotchi/utils.py b/pwnagotchi/utils.py index 4158f94b..eacf8899 100644 --- a/pwnagotchi/utils.py +++ b/pwnagotchi/utils.py @@ -82,7 +82,7 @@ def remove_whitelisted(list_of_handshakes, list_of_whitelisted_strings, valid_on for handshake in list_of_handshakes: try: - normalized_handshake = normalize(os.path.basename(handshake).rstrip('.pcap')) + normalized_handshake = normalize(os.path.basename(handshake).rstrip('.pcapng')) for whitelist in list_of_whitelisted_strings: normalized_whitelist = normalize(whitelist) if normalized_whitelist in normalized_handshake: @@ -440,7 +440,7 @@ def secs_to_hhmmss(secs): def total_unique_handshakes(path): - expr = os.path.join(path, "*.pcap") + expr = os.path.join(path, "*.pcapng") return len(glob.glob(expr)) @@ -498,11 +498,11 @@ def md5(fname): return hash_md5.hexdigest() -def extract_from_pcap(path, fields): +def extract_from_pcapng(path, fields): """ - Search in pcap-file for specified information + Search in pcapng-file for specified information - path: Path to pcap file + path: Path to pcapng file fields: Array of fields that should be extracted If a field is not found, FieldNotFoundError is raised From a0b5078b64d50330ee1669e00b141b0f4f9bbbb9 Mon Sep 17 00:00:00 2001 From: Jeroen Oudshoorn Date: Sun, 28 Jan 2024 22:05:14 +0100 Subject: [PATCH 02/19] Changed setup.py --- apt_packages.txt | 1 - setup.py | 7 ------- 2 files changed, 8 deletions(-) delete mode 100644 apt_packages.txt diff --git a/apt_packages.txt b/apt_packages.txt deleted file mode 100644 index 7723a531..00000000 --- a/apt_packages.txt +++ /dev/null @@ -1 +0,0 @@ -hcxtools \ No newline at end of file diff --git a/setup.py b/setup.py index b0422e0f..0e187ef8 100644 --- a/setup.py +++ b/setup.py @@ -30,13 +30,6 @@ def install_file(source_filename, dest_filename): def install_system_files(): - f = open("apt_packages.txt", "r") - for x in f: - if x == "": - continue - os.system(f"apt-get install {x}") - f.close() - setup_path = os.path.dirname(__file__) data_path = os.path.join(setup_path, "builder/data") From d0617ccfafcbcc104663b16dae447b89b2a21802 Mon Sep 17 00:00:00 2001 From: Jeroen Oudshoorn Date: Sun, 28 Jan 2024 22:08:17 +0100 Subject: [PATCH 03/19] Revert grid name --- pwnagotchi/grid.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pwnagotchi/grid.py b/pwnagotchi/grid.py index 82e0f88b..6c908dbd 100644 --- a/pwnagotchi/grid.py +++ b/pwnagotchi/grid.py @@ -89,7 +89,7 @@ def update_data(last_session): 'uname': subprocess.getoutput("uname -a"), 'brain': brain, 'version': pwnagotchi.__version__, - 'build': "Test version", + 'build': "Pwnagotchi-Torch by Jayofelony", 'plugins': enabled, 'language': language, 'bettercap': subprocess.getoutput("bettercap -version").split(".\n\n")[1], From 7040be2d3079ce5d3496c858a07632da1dfda69b Mon Sep 17 00:00:00 2001 From: Jeroen Oudshoorn Date: Sun, 28 Jan 2024 22:02:57 +0100 Subject: [PATCH 04/19] Testing pcapng fileformat --- pwnagotchi/grid.py | 2 +- pwnagotchi/plugins/default/gps.py | 2 +- pwnagotchi/plugins/default/grid.py | 17 ++++--- pwnagotchi/plugins/default/hashie.py | 6 +-- pwnagotchi/plugins/default/net-pos.py | 2 +- pwnagotchi/plugins/default/onlinehashcrack.py | 4 +- pwnagotchi/plugins/default/webgpsmap.py | 44 ++++++++----------- pwnagotchi/plugins/default/wigle.py | 10 ++--- pwnagotchi/plugins/default/wpa-sec.py | 2 +- pwnagotchi/utils.py | 10 ++--- 10 files changed, 45 insertions(+), 54 deletions(-) diff --git a/pwnagotchi/grid.py b/pwnagotchi/grid.py index 6c908dbd..82e0f88b 100644 --- a/pwnagotchi/grid.py +++ b/pwnagotchi/grid.py @@ -89,7 +89,7 @@ def update_data(last_session): 'uname': subprocess.getoutput("uname -a"), 'brain': brain, 'version': pwnagotchi.__version__, - 'build': "Pwnagotchi-Torch by Jayofelony", + 'build': "Test version", 'plugins': enabled, 'language': language, 'bettercap': subprocess.getoutput("bettercap -version").split(".\n\n")[1], diff --git a/pwnagotchi/plugins/default/gps.py b/pwnagotchi/plugins/default/gps.py index a351406b..0e5f958d 100644 --- a/pwnagotchi/plugins/default/gps.py +++ b/pwnagotchi/plugins/default/gps.py @@ -48,7 +48,7 @@ class GPS(plugins.Plugin): if self.running: info = agent.session() self.coordinates = info["gps"] - gps_filename = filename.replace(".pcap", ".gps.json") + gps_filename = filename.replace(".pcapng", ".gps.json") if self.coordinates and all([ # avoid 0.000... measurements diff --git a/pwnagotchi/plugins/default/grid.py b/pwnagotchi/plugins/default/grid.py index cdca794e..fbc3374e 100644 --- a/pwnagotchi/plugins/default/grid.py +++ b/pwnagotchi/plugins/default/grid.py @@ -5,22 +5,21 @@ import glob import re import pwnagotchi.grid as grid -import pwnagotchi.plugins import pwnagotchi.plugins as plugins -from pwnagotchi.utils import StatusFile, WifiInfo, extract_from_pcap +from pwnagotchi.utils import StatusFile, WifiInfo, extract_from_pcapng from threading import Lock def parse_pcap(filename): logging.info("grid: parsing %s ..." % filename) - net_id = os.path.basename(filename).replace('.pcap', '') + net_id = os.path.basename(filename).replace('.pcapng', '') if '_' in net_id: - # /root/handshakes/ESSID_BSSID.pcap + # /root/handshakes/ESSID_BSSID.pcapng essid, bssid = net_id.split('_') else: - # /root/handshakes/BSSID.pcap + # /root/handshakes/BSSID.pcapng essid, bssid = '', net_id mac_re = re.compile('[0-9a-fA-F]{12}') @@ -36,7 +35,7 @@ def parse_pcap(filename): } try: - info = extract_from_pcap(filename, [WifiInfo.BSSID, WifiInfo.ESSID]) + info = extract_from_pcapng(filename, [WifiInfo.BSSID, WifiInfo.ESSID]) except Exception as e: logging.error("grid: %s" % e) @@ -87,10 +86,10 @@ class Grid(plugins.Plugin): agent.view().on_unread_messages(self.unread_messages, self.total_messages) def check_handshakes(self, agent): - logging.debug("checking pcaps") + logging.debug("checking pcapng's") config = agent.config() - pcap_files = glob.glob(os.path.join(agent.config()['bettercap']['handshakes'], "*.pcap")) + pcap_files = glob.glob(os.path.join(agent.config()['bettercap']['handshakes'], "*.pcapng")) num_networks = len(pcap_files) reported = self.report.data_field_or('reported', default=[]) num_reported = len(reported) @@ -103,7 +102,7 @@ class Grid(plugins.Plugin): logging.debug(" exclude: %s" % config['main']['whitelist']) for pcap_file in pcap_files: - net_id = os.path.basename(pcap_file).replace('.pcap', '') + net_id = os.path.basename(pcap_file).replace('.pcapng', '') if net_id not in reported: if self.is_excluded(net_id, agent): logging.debug("skipping %s due to exclusion filter" % pcap_file) diff --git a/pwnagotchi/plugins/default/hashie.py b/pwnagotchi/plugins/default/hashie.py index cd41122b..b5c8e18a 100644 --- a/pwnagotchi/plugins/default/hashie.py +++ b/pwnagotchi/plugins/default/hashie.py @@ -82,12 +82,12 @@ class Hashie(plugins.Plugin): if os.path.isfile(fullpathNoExt + '.22000'): handshake_status.append('Already have {}.22000 (EAPOL)'.format(name)) elif self._writeEAPOL(filename): - handshake_status.append('Created {}.22000 (EAPOL) from pcap'.format(name)) + handshake_status.append('Created {}.22000 (EAPOL) from pcapng'.format(name)) if os.path.isfile(fullpathNoExt + '.16800'): handshake_status.append('Already have {}.16800 (PMKID)'.format(name)) elif self._writePMKID(filename): - handshake_status.append('Created {}.16800 (PMKID) from pcap'.format(name)) + handshake_status.append('Created {}.16800 (PMKID) from pcapng'.format(name)) if handshake_status: logging.info('[Hashie] Good news:\n\t' + '\n\t'.join(handshake_status)) @@ -111,7 +111,7 @@ class Hashie(plugins.Plugin): return False def _process_stale_pcaps(self, handshake_dir): - handshakes_list = [os.path.join(handshake_dir, filename) for filename in os.listdir(handshake_dir) if filename.endswith('.pcap')] + handshakes_list = [os.path.join(handshake_dir, filename) for filename in os.listdir(handshake_dir) if filename.endswith('.pcapng')] failed_jobs = [] successful_jobs = [] lonely_pcaps = [] diff --git a/pwnagotchi/plugins/default/net-pos.py b/pwnagotchi/plugins/default/net-pos.py index 3f226204..ef5f0c59 100644 --- a/pwnagotchi/plugins/default/net-pos.py +++ b/pwnagotchi/plugins/default/net-pos.py @@ -108,7 +108,7 @@ class NetPos(plugins.Plugin): return netpos["ts"] = int("%.0f" % time.time()) - netpos_filename = filename.replace('.pcap', '.net-pos.json') + netpos_filename = filename.replace('.pcapng', '.net-pos.json') logging.debug("NET-POS: Saving net-location to %s", netpos_filename) try: diff --git a/pwnagotchi/plugins/default/onlinehashcrack.py b/pwnagotchi/plugins/default/onlinehashcrack.py index aeb01dda..1eafb9fa 100644 --- a/pwnagotchi/plugins/default/onlinehashcrack.py +++ b/pwnagotchi/plugins/default/onlinehashcrack.py @@ -142,6 +142,6 @@ class OnlineHashCrack(plugins.Plugin): for row in csv.DictReader(cracked_list): if row['password']: filename = re.sub(r'[^a-zA-Z0-9]', '', row['ESSID']) + '_' + row['BSSID'].replace(':','') - if os.path.exists( os.path.join(handshake_dir, filename+'.pcap') ): - with open(os.path.join(handshake_dir, filename+'.pcap.cracked'), 'w') as f: + if os.path.exists( os.path.join(handshake_dir, filename+'.pcapng')): + with open(os.path.join(handshake_dir, filename+'.pcapng.cracked'), 'w') as f: f.write(row['password']) diff --git a/pwnagotchi/plugins/default/webgpsmap.py b/pwnagotchi/plugins/default/webgpsmap.py index f9f513d9..b03fef50 100644 --- a/pwnagotchi/plugins/default/webgpsmap.py +++ b/pwnagotchi/plugins/default/webgpsmap.py @@ -13,8 +13,8 @@ from dateutil.parser import parse webgpsmap shows existing position data stored in your /handshakes/ directory the plugin does the following: - - search for *.pcap files in your /handshakes/ dir - - for every found .pcap file it looks for a .geo.json or .gps.json or .paw-gps.json file with + - search for *.pcapng files in your /handshakes/ dir + - for every found .pcapng file it looks for a .geo.json or .gps.json or file with latitude+longitude data inside and shows this position on the map - if also an .cracked file with a plaintext password inside exist, it reads the content and shows the position as green instead of red and the password inside the infopox of the position @@ -87,7 +87,8 @@ class Webgpsmap(plugins.Plugin): # returns all positions try: self.ALREADY_SENT = list() - response_data = bytes(json.dumps(self.load_gps_from_dir(self.config['bettercap']['handshakes'])), "utf-8") + response_data = bytes( + json.dumps(self.load_gps_from_dir(self.config['bettercap']['handshakes'])), "utf-8") response_status = 200 response_mimetype = "application/json" response_header_contenttype = 'application/json' @@ -100,7 +101,8 @@ class Webgpsmap(plugins.Plugin): self.ALREADY_SENT = list() json_data = json.dumps(self.load_gps_from_dir(self.config['bettercap']['handshakes'])) html_data = self.get_html() - html_data = html_data.replace('var positions = [];', 'var positions = ' + json_data + ';positionsLoaded=true;drawPositions();') + html_data = html_data.replace('var positions = [];', + 'var positions = ' + json_data + ';positionsLoaded=true;drawPositions();') response_data = bytes(html_data, "utf-8") response_status = 200 response_mimetype = "application/xhtml+xml" @@ -163,7 +165,8 @@ class Webgpsmap(plugins.Plugin): all_files = os.listdir(handshake_dir) # print(all_files) - all_pcap_files = [os.path.join(handshake_dir, filename) for filename in all_files if filename.endswith('.pcap')] + all_pcap_files = [os.path.join(handshake_dir, filename) for filename in all_files if + filename.endswith('.pcapng')] all_geo_or_gps_files = [] for filename_pcap in all_pcap_files: filename_base = filename_pcap[:-5] # remove ".pcap" @@ -180,22 +183,18 @@ class Webgpsmap(plugins.Plugin): if check_for in all_files: filename_position = str(os.path.join(handshake_dir, check_for)) - logging.debug("[webgpsmap] search for .paw-gps.json") - check_for = os.path.basename(filename_base) + ".paw-gps.json" - if check_for in all_files: - filename_position = str(os.path.join(handshake_dir, check_for)) - logging.debug(f"[webgpsmap] end search for position data files and use {filename_position}") if filename_position is not None: all_geo_or_gps_files.append(filename_position) - # all_geo_or_gps_files = set(all_geo_or_gps_files) - set(SKIP) # remove skipped networks? No! + # all_geo_or_gps_files = set(all_geo_or_gps_files) - set(SKIP) # remove skipped networks? No! if newest_only: all_geo_or_gps_files = set(all_geo_or_gps_files) - set(self.ALREADY_SENT) - logging.info(f"[webgpsmap] Found {len(all_geo_or_gps_files)} position-data files from {len(all_pcap_files)} handshakes. Fetching positions ...") + logging.info( + f"[webgpsmap] Found {len(all_geo_or_gps_files)} position-data files from {len(all_pcap_files)} handshakes. Fetching positions ...") for pos_file in all_geo_or_gps_files: try: @@ -213,9 +212,7 @@ class Webgpsmap(plugins.Plugin): pos_type = 'gps' elif pos.type() == PositionFile.GEO: pos_type = 'geo' - elif pos.type() == PositionFile.PAWGPS: - pos_type = 'paw' - gps_data[ssid+"_"+mac] = { + gps_data[ssid + "_" + mac] = { 'ssid': ssid, 'mac': mac, 'type': pos_type, @@ -224,10 +221,10 @@ class Webgpsmap(plugins.Plugin): 'acc': pos.accuracy(), 'ts_first': pos.timestamp_first(), 'ts_last': pos.timestamp_last(), - } + } # get ap password if exist - check_for = os.path.basename(pos_file).split(".")[0] + ".pcap.cracked" + check_for = os.path.basename(pos_file).split(".")[0] + ".pcapng.cracked" if check_for in all_files: gps_data[ssid + "_" + mac]["pass"] = pos.password() @@ -265,7 +262,6 @@ class PositionFile: """ GPS = 1 GEO = 2 - PAWGPS = 3 def __init__(self, path): self._file = path @@ -282,7 +278,7 @@ class PositionFile: """ Returns the mac from filename """ - parsed_mac = re.search(r'.*_?([a-zA-Z0-9]{12})\.(?:gps|geo|paw-gps)\.json', self._filename) + parsed_mac = re.search(r'.*_?([a-zA-Z0-9]{12})\.(?:gps|geo)\.json', self._filename) if parsed_mac: mac = parsed_mac.groups()[0] return mac @@ -292,7 +288,7 @@ class PositionFile: """ Returns the ssid from filename """ - parsed_ssid = re.search(r'(.+)_[a-zA-Z0-9]{12}\.(?:gps|geo|paw-gps)\.json', self._filename) + parsed_ssid = re.search(r'(.+)_[a-zA-Z0-9]{12}\.(?:gps|geo)\.json', self._filename) if parsed_ssid: return parsed_ssid.groups()[0] return None @@ -333,7 +329,7 @@ class PositionFile: return_pass = None # 2do: make better filename split/remove extension because this one has problems with "." in path base_filename, ext1, ext2 = re.split('\.', self._file) - password_file_path = base_filename + ".pcap.cracked" + password_file_path = base_filename + ".pcapng.cracked" if os.path.isfile(password_file_path): try: password_file = open(password_file_path, 'r') @@ -354,8 +350,6 @@ class PositionFile: return PositionFile.GPS if self._file.endswith('.geo.json'): return PositionFile.GEO - if self._file.endswith('.paw-gps.json'): - return PositionFile.PAWGPS return None def lat(self): @@ -402,9 +396,7 @@ class PositionFile: def accuracy(self): if self.type() == PositionFile.GPS: - return 50.0 # a default - if self.type() == PositionFile.PAWGPS: - return 50.0 # a default + return 50.0 # a default if self.type() == PositionFile.GEO: try: return self._json['accuracy'] diff --git a/pwnagotchi/plugins/default/wigle.py b/pwnagotchi/plugins/default/wigle.py index 353660ea..11805c3b 100644 --- a/pwnagotchi/plugins/default/wigle.py +++ b/pwnagotchi/plugins/default/wigle.py @@ -7,7 +7,7 @@ import pwnagotchi from io import StringIO from datetime import datetime -from pwnagotchi.utils import WifiInfo, FieldNotFoundError, extract_from_pcap, StatusFile, remove_whitelisted +from pwnagotchi.utils import WifiInfo, FieldNotFoundError, extract_from_pcapng, StatusFile, remove_whitelisted from threading import Lock from pwnagotchi import plugins from pwnagotchi._version import __version__ as __pwnagotchi_version__ @@ -153,11 +153,11 @@ class Wigle(plugins.Plugin): no_err_entries = list() for gps_file in new_gps_files: if gps_file.endswith('.gps.json'): - pcap_filename = gps_file.replace('.gps.json', '.pcap') + pcap_filename = gps_file.replace('.gps.json', '.pcapng') if gps_file.endswith('.geo.json'): - pcap_filename = gps_file.replace('.geo.json', '.pcap') + pcap_filename = gps_file.replace('.geo.json', '.pcapng') if not os.path.exists(pcap_filename): - logging.debug("WIGLE: Can't find pcap for %s", gps_file) + logging.debug("WIGLE: Can't find pcapng for %s", gps_file) self.skip.append(gps_file) continue try: @@ -175,7 +175,7 @@ class Wigle(plugins.Plugin): self.skip.append(gps_file) continue try: - pcap_data = extract_from_pcap(pcap_filename, [WifiInfo.BSSID, + pcap_data = extract_from_pcapng(pcap_filename, [WifiInfo.BSSID, WifiInfo.ESSID, WifiInfo.ENCRYPTION, WifiInfo.CHANNEL, diff --git a/pwnagotchi/plugins/default/wpa-sec.py b/pwnagotchi/plugins/default/wpa-sec.py index 696b53b4..42f1c29f 100644 --- a/pwnagotchi/plugins/default/wpa-sec.py +++ b/pwnagotchi/plugins/default/wpa-sec.py @@ -98,7 +98,7 @@ class WpaSec(plugins.Plugin): reported = self.report.data_field_or('reported', default=list()) handshake_dir = config['bettercap']['handshakes'] handshake_filenames = os.listdir(handshake_dir) - handshake_paths = [os.path.join(handshake_dir, filename) for filename in handshake_filenames if filename.endswith('.pcap')] + handshake_paths = [os.path.join(handshake_dir, filename) for filename in handshake_filenames if filename.endswith('.pcapng')] handshake_paths = remove_whitelisted(handshake_paths, config['main']['whitelist']) handshake_new = set(handshake_paths) - set(reported) - set(self.skip) diff --git a/pwnagotchi/utils.py b/pwnagotchi/utils.py index 4158f94b..eacf8899 100644 --- a/pwnagotchi/utils.py +++ b/pwnagotchi/utils.py @@ -82,7 +82,7 @@ def remove_whitelisted(list_of_handshakes, list_of_whitelisted_strings, valid_on for handshake in list_of_handshakes: try: - normalized_handshake = normalize(os.path.basename(handshake).rstrip('.pcap')) + normalized_handshake = normalize(os.path.basename(handshake).rstrip('.pcapng')) for whitelist in list_of_whitelisted_strings: normalized_whitelist = normalize(whitelist) if normalized_whitelist in normalized_handshake: @@ -440,7 +440,7 @@ def secs_to_hhmmss(secs): def total_unique_handshakes(path): - expr = os.path.join(path, "*.pcap") + expr = os.path.join(path, "*.pcapng") return len(glob.glob(expr)) @@ -498,11 +498,11 @@ def md5(fname): return hash_md5.hexdigest() -def extract_from_pcap(path, fields): +def extract_from_pcapng(path, fields): """ - Search in pcap-file for specified information + Search in pcapng-file for specified information - path: Path to pcap file + path: Path to pcapng file fields: Array of fields that should be extracted If a field is not found, FieldNotFoundError is raised From 7b7ba02aad76c1ea22b120c2ca5b4160b9861a30 Mon Sep 17 00:00:00 2001 From: Jeroen Oudshoorn Date: Sun, 28 Jan 2024 22:05:14 +0100 Subject: [PATCH 05/19] Changed setup.py --- apt_packages.txt | 1 - setup.py | 7 ------- 2 files changed, 8 deletions(-) delete mode 100644 apt_packages.txt diff --git a/apt_packages.txt b/apt_packages.txt deleted file mode 100644 index 7723a531..00000000 --- a/apt_packages.txt +++ /dev/null @@ -1 +0,0 @@ -hcxtools \ No newline at end of file diff --git a/setup.py b/setup.py index b0422e0f..0e187ef8 100644 --- a/setup.py +++ b/setup.py @@ -30,13 +30,6 @@ def install_file(source_filename, dest_filename): def install_system_files(): - f = open("apt_packages.txt", "r") - for x in f: - if x == "": - continue - os.system(f"apt-get install {x}") - f.close() - setup_path = os.path.dirname(__file__) data_path = os.path.join(setup_path, "builder/data") From 4f62759d6dbf63b036e1b23fb1ecbc6f378196c6 Mon Sep 17 00:00:00 2001 From: Jeroen Oudshoorn Date: Sun, 28 Jan 2024 22:08:17 +0100 Subject: [PATCH 06/19] Revert grid name --- pwnagotchi/grid.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pwnagotchi/grid.py b/pwnagotchi/grid.py index 82e0f88b..6c908dbd 100644 --- a/pwnagotchi/grid.py +++ b/pwnagotchi/grid.py @@ -89,7 +89,7 @@ def update_data(last_session): 'uname': subprocess.getoutput("uname -a"), 'brain': brain, 'version': pwnagotchi.__version__, - 'build': "Test version", + 'build': "Pwnagotchi-Torch by Jayofelony", 'plugins': enabled, 'language': language, 'bettercap': subprocess.getoutput("bettercap -version").split(".\n\n")[1], From e01e4579928706270679a209d06e8966c39a9295 Mon Sep 17 00:00:00 2001 From: Jeroen Oudshoorn Date: Mon, 29 Jan 2024 22:24:20 +0100 Subject: [PATCH 07/19] Remove bettercap client settings, so you cannot mess it up. --- pwnagotchi/agent.py | 17 ++++++++++------- pwnagotchi/defaults.toml | 5 ----- 2 files changed, 10 insertions(+), 12 deletions(-) diff --git a/pwnagotchi/agent.py b/pwnagotchi/agent.py index 00d4f964..5916ce05 100644 --- a/pwnagotchi/agent.py +++ b/pwnagotchi/agent.py @@ -21,11 +21,12 @@ RECOVERY_DATA_FILE = '/root/.pwnagotchi-recovery' class Agent(Client, Automata, AsyncAdvertiser, AsyncTrainer): def __init__(self, view, config, keypair): - Client.__init__(self, config['bettercap']['hostname'], - config['bettercap']['scheme'], - config['bettercap']['port'], - config['bettercap']['username'], - config['bettercap']['password']) + Client.__init__(self, + "127.0.0.1" if "hostname" not in config['bettercap'] else config['bettercap']['hostname'], + "http" if "scheme" not in config['bettercap'] else config['bettercap']['scheme'], + 8081 if "port" not in config['bettercap'] else config['bettercap']['port'], + "pwnagotchi" if "username" not in config['bettercap'] else config['bettercap']['username'], + "pwnagotchi" if "password" not in config['bettercap'] else config['bettercap']['password']) Automata.__init__(self, config, view) AsyncAdvertiser.__init__(self, config, view, keypair) AsyncTrainer.__init__(self, config) @@ -178,7 +179,8 @@ class Agent(Client, Automata, AsyncAdvertiser, AsyncTrainer): for ap in s['wifi']['aps']: if ap['encryption'] == '' or ap['encryption'] == 'OPEN': continue - elif ap['hostname'] in whitelist or ap['mac'][:13].lower() in whitelist or ap['mac'].lower() in whitelist: + elif ap['hostname'] in whitelist or ap['mac'][:13].lower() in whitelist or ap[ + 'mac'].lower() in whitelist: continue else: aps.append(ap) @@ -362,7 +364,8 @@ class Agent(Client, Automata, AsyncAdvertiser, AsyncTrainer): plugins.on('handshake', self, filename, ap_mac, sta_mac) else: (ap, sta) = ap_and_station - self._last_pwnd = ap['hostname'] if ap['hostname'] != '' and ap['hostname'] != '' else ap_mac + self._last_pwnd = ap['hostname'] if ap['hostname'] != '' and ap[ + 'hostname'] != '' else ap_mac logging.warning( "!!! captured new handshake on channel %d, %d dBm: %s (%s) -> %s [%s (%s)] !!!", ap['channel'], ap['rssi'], sta['mac'], sta['vendor'], ap['hostname'], ap['mac'], ap['vendor']) diff --git a/pwnagotchi/defaults.toml b/pwnagotchi/defaults.toml index 3f7b0534..b175fff1 100644 --- a/pwnagotchi/defaults.toml +++ b/pwnagotchi/defaults.toml @@ -198,11 +198,6 @@ ui.display.enabled = false ui.display.rotation = 180 ui.display.type = "waveshare_4" -bettercap.scheme = "http" -bettercap.hostname = "localhost" -bettercap.port = 8081 -bettercap.username = "pwnagotchi" -bettercap.password = "pwnagotchi" bettercap.handshakes = "/root/handshakes" bettercap.silence = [ "ble.device.new", From 3bcbb0ce9a32f91c09d2d37e7aba4bc7ef4e664b Mon Sep 17 00:00:00 2001 From: Jeroen Oudshoorn Date: Mon, 29 Jan 2024 22:52:16 +0100 Subject: [PATCH 08/19] Version 2.8.1 --- pwnagotchi/_version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pwnagotchi/_version.py b/pwnagotchi/_version.py index f2df444a..80e22f7a 100644 --- a/pwnagotchi/_version.py +++ b/pwnagotchi/_version.py @@ -1 +1 @@ -__version__ = '2.8.0' +__version__ = '2.8.1' From 84f66248441e7ef097f8cde0802f942128fd3ba8 Mon Sep 17 00:00:00 2001 From: Jeroen Oudshoorn Date: Thu, 1 Feb 2024 13:04:06 +0100 Subject: [PATCH 09/19] Change to seemoo-lab nexmon --- builder/pwnagotchi.json.pkr.hcl | 4 ++++ builder/raspberrypi64.yml | 39 +++++++++++++++++++++++---------- 2 files changed, 32 insertions(+), 11 deletions(-) diff --git a/builder/pwnagotchi.json.pkr.hcl b/builder/pwnagotchi.json.pkr.hcl index 26edc7cf..18d96f93 100644 --- a/builder/pwnagotchi.json.pkr.hcl +++ b/builder/pwnagotchi.json.pkr.hcl @@ -74,6 +74,10 @@ build { inline = ["chmod +x /usr/bin/*"] } + provisioner "shell" { + inline = ["dpkg --add-architecture armhf"] + } + provisioner "file" { destination = "/etc/systemd/system/" sources = [ diff --git a/builder/raspberrypi64.yml b/builder/raspberrypi64.yml index 958b10ff..e32366ca 100644 --- a/builder/raspberrypi64.yml +++ b/builder/raspberrypi64.yml @@ -79,6 +79,11 @@ - curl - dkms - fbi + - firmware-atheros + - firmware-brcm80211 + - firmware-libertas + - firmware-misc-nonfree + - firmware-realtek - flex - fonts-dejavu - fonts-dejavu-core @@ -97,9 +102,9 @@ - libbz2-dev - libc-ares-dev - libc6-dev + - libc6:armhf - libcap-dev - libcurl-ocaml-dev - - libssl-ocaml-dev - libdbus-1-dev - libdbus-glib-1-dev - libeigen3-dev @@ -112,7 +117,10 @@ - libgmp3-dev - libgstreamer1.0-0 - libhdf5-dev + - libisl23:armhf - liblapack-dev + - libmpc3:armhf + - libmpfr6:armhf - libncursesw5-dev - libnetfilter-queue-dev - libopenblas-dev @@ -126,34 +134,31 @@ - libraspberrypi0 - libsqlite3-dev - libssl-dev + - libssl-ocaml-dev + - libstdc++6:armhf - libswscale5 - libtiff6 - libtool - libusb-1.0-0-dev - lsof - make - - python3-yaml - python3-dbus - python3-flask - python3-flask-cors - python3-flaskext.wtf - python3-gast - python3-pil + - python3-pip - python3-pycryptodome - python3-requests - python3-scapy + - python3-setuptools + - python3-smbus - python3-smbus2 - python3-spidev - python3-tweepy - python3-werkzeug - - firmware-atheros - - firmware-brcm80211 - - firmware-libertas - - firmware-misc-nonfree - - firmware-realtek - - python3-pip - - python3-setuptools - - python3-smbus + - python3-yaml - qpdf - raspberrypi-kernel-headers - rsync @@ -291,9 +296,21 @@ path: /usr/local/src/hcxtools # Install nexmon to fix wireless scanning (takes 2.5G of space) + - name: symlink 1 + file: + src: "/usr/lib/arm-linux-gnueabihf/libisl.so.23.0.0" + dest: "/usr/lib/arm-linux-gnueabihf/libisl.so.10" + state: link + + - name: symlink 2 + file: + src: "/usr/lib/arm-linux-gnueabihf/libmpfr.so.6.1.0" + dest: "/usr/lib/arm-linux-gnueabihf/libmpfr.so.4" + state: link + - name: clone nexmon repository git: - repo: https://github.com/DrSchottky/nexmon.git + repo: https://github.com/seemoo-lab/nexmon.git dest: /usr/local/src/nexmon # FIRST WE BUILD DRIVER FOR RPi5 From 56ebb60662194e0ef464986742faaa01e245225a Mon Sep 17 00:00:00 2001 From: Jeroen Oudshoorn Date: Thu, 1 Feb 2024 13:26:20 +0100 Subject: [PATCH 10/19] Change to seemoo-lab nexmon --- builder/pwnagotchi.json.pkr.hcl | 6 +++++- builder/raspberrypi64.yml | 4 ++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/builder/pwnagotchi.json.pkr.hcl b/builder/pwnagotchi.json.pkr.hcl index 18d96f93..c08ff651 100644 --- a/builder/pwnagotchi.json.pkr.hcl +++ b/builder/pwnagotchi.json.pkr.hcl @@ -95,7 +95,11 @@ build { inline = ["chmod +x /etc/update-motd.d/*"] } provisioner "shell" { - inline = ["apt-get -y --allow-releaseinfo-change update", "apt-get -y dist-upgrade", "apt-get install -y --no-install-recommends ansible"] + inline = [ + "apt-get -y --allow-releaseinfo-change update", + "apt-get -y dist-upgrade", + "apt-get install -y --no-install-recommends ansible" + ] } provisioner "ansible-local" { command = "ANSIBLE_FORCE_COLOR=1 PYTHONUNBUFFERED=1 PWN_VERSION=${var.pwn_version} PWN_HOSTNAME=${var.pwn_hostname} ansible-playbook" diff --git a/builder/raspberrypi64.yml b/builder/raspberrypi64.yml index e32366ca..1b701b8a 100644 --- a/builder/raspberrypi64.yml +++ b/builder/raspberrypi64.yml @@ -298,13 +298,13 @@ # Install nexmon to fix wireless scanning (takes 2.5G of space) - name: symlink 1 file: - src: "/usr/lib/arm-linux-gnueabihf/libisl.so.23.0.0" + src: "/usr/lib/arm-linux-gnueabihf/libisl.so.23.2.0" dest: "/usr/lib/arm-linux-gnueabihf/libisl.so.10" state: link - name: symlink 2 file: - src: "/usr/lib/arm-linux-gnueabihf/libmpfr.so.6.1.0" + src: "/usr/lib/arm-linux-gnueabihf/libmpfr.so.6.2.0" dest: "/usr/lib/arm-linux-gnueabihf/libmpfr.so.4" state: link From 34284aa1bcd75de535424e10013df105a0f534b9 Mon Sep 17 00:00:00 2001 From: Jeroen Oudshoorn Date: Thu, 1 Feb 2024 13:50:51 +0100 Subject: [PATCH 11/19] Change to seemoo-lab nexmon --- builder/raspberrypi64.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/builder/raspberrypi64.yml b/builder/raspberrypi64.yml index 1b701b8a..2eb9ff8f 100644 --- a/builder/raspberrypi64.yml +++ b/builder/raspberrypi64.yml @@ -363,7 +363,7 @@ - name: clone nexmon repository git: - repo: https://github.com/DrSchottky/nexmon.git + repo: https://github.com/seemoo-lab/nexmon.git dest: /usr/local/src/nexmon - name: make firmware, RPi4 From fa7e87b974f5f894c226e64d7e64ce46faf25b78 Mon Sep 17 00:00:00 2001 From: Jeroen Oudshoorn Date: Sun, 4 Feb 2024 17:41:41 +0100 Subject: [PATCH 12/19] remove blind bug, as its not a blind bug anymore. delayed hopping channels by .2 seconds to give firmware time to get ready for hopping. --- bin/pwnagotchi | 2 ++ builder/data/usr/bin/pwnlib | 8 -------- pwnagotchi/agent.py | 3 +-- 3 files changed, 3 insertions(+), 10 deletions(-) diff --git a/bin/pwnagotchi b/bin/pwnagotchi index e09024e1..c0540374 100755 --- a/bin/pwnagotchi +++ b/bin/pwnagotchi @@ -51,6 +51,7 @@ def pwnagotchi_cli(): agent.mode = 'auto' agent.start() config = agent.config() + session = agent.session() while True: try: @@ -60,6 +61,7 @@ def pwnagotchi_cli(): channels = agent.get_access_points_by_channel() # for each channel for ch, aps in channels: + time.sleep(0.2) # This is to make sure it doesn't error (https://github.com/seemoo-lab/nexmon/issues/596) agent.set_channel(ch) if not agent.is_stale() and agent.any_activity(): diff --git a/builder/data/usr/bin/pwnlib b/builder/data/usr/bin/pwnlib index 6447624e..fa25d682 100755 --- a/builder/data/usr/bin/pwnlib +++ b/builder/data/usr/bin/pwnlib @@ -13,14 +13,6 @@ blink_led() { sleep 0.3 } -# check if brcm is stuck -check_brcm() { - if [[ "$(journalctl -n10 -k --since -5m | grep -c 'brcmf_cfg80211_nexmon_set_channel.*Set Channel failed')" -ge 5 ]]; then - return 1 - fi - return 0 -} - # reload mod reload_brcm() { if ! modprobe -r brcmfmac; then diff --git a/pwnagotchi/agent.py b/pwnagotchi/agent.py index 5916ce05..c7199ca7 100644 --- a/pwnagotchi/agent.py +++ b/pwnagotchi/agent.py @@ -179,8 +179,7 @@ class Agent(Client, Automata, AsyncAdvertiser, AsyncTrainer): for ap in s['wifi']['aps']: if ap['encryption'] == '' or ap['encryption'] == 'OPEN': continue - elif ap['hostname'] in whitelist or ap['mac'][:13].lower() in whitelist or ap[ - 'mac'].lower() in whitelist: + elif ap['hostname'] in whitelist or ap['mac'][:13].lower() in whitelist or ap['mac'].lower() in whitelist: continue else: aps.append(ap) From 6381f9443ba0c11620da0c139473a419dd6348ec Mon Sep 17 00:00:00 2001 From: Jeroen Oudshoorn Date: Sun, 4 Feb 2024 17:41:57 +0100 Subject: [PATCH 13/19] remove blind bug, as its not a blind bug anymore. --- builder/data/usr/bin/bettercap-launcher | 9 --------- 1 file changed, 9 deletions(-) diff --git a/builder/data/usr/bin/bettercap-launcher b/builder/data/usr/bin/bettercap-launcher index 179dba72..6a6f981a 100755 --- a/builder/data/usr/bin/bettercap-launcher +++ b/builder/data/usr/bin/bettercap-launcher @@ -9,15 +9,6 @@ if is_crypted_mode; then done fi -# check if wifi driver is bugged -if ! check_brcm; then - if ! reload_brcm; then - echo "Could not reload wifi driver. Reboot" - reboot - fi - sleep 10 -fi - # start mon0 start_monitor_interface From 53b2dd862839311bb29a43373f8ddffd3fa07d83 Mon Sep 17 00:00:00 2001 From: Jeroen Oudshoorn Date: Sun, 4 Feb 2024 17:42:10 +0100 Subject: [PATCH 14/19] update build for latest kernel --- builder/raspberrypi64.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/builder/raspberrypi64.yml b/builder/raspberrypi64.yml index 2eb9ff8f..ec2115b6 100644 --- a/builder/raspberrypi64.yml +++ b/builder/raspberrypi64.yml @@ -6,8 +6,8 @@ vars: kernel: min: "6.1" - full: "6.1.0-rpi7-rpi-v8" - full_pi5: "6.1.0-rpi7-rpi-2712" + full: "6.1.0-rpi8-rpi-v8" + full_pi5: "6.1.0-rpi8-rpi-2712" pwnagotchi: hostname: "{{ lookup('env', 'PWN_HOSTNAME') | default('pwnagotchi', true) }}" version: "{{ lookup('env', 'PWN_VERSION') | default('pwnagotchi-torch', true) }}" From 11a3330153899a732adca0b3e95473d76ab3a49b Mon Sep 17 00:00:00 2001 From: Jeroen Oudshoorn Date: Sun, 4 Feb 2024 17:42:22 +0100 Subject: [PATCH 15/19] small fix --- pwnagotchi/ui/view.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pwnagotchi/ui/view.py b/pwnagotchi/ui/view.py index d93f21a8..50b2ffc5 100644 --- a/pwnagotchi/ui/view.py +++ b/pwnagotchi/ui/view.py @@ -153,8 +153,7 @@ class View(object): self.set('uptime', last_session.duration) self.set('channel', '-') self.set('aps', "%d" % last_session.associated) - self.set('shakes', '%d (%s)' % (last_session.handshakes, \ - utils.total_unique_handshakes(self._config['bettercap']['handshakes']))) + self.set('shakes', '%d (%s)' % (last_session.handshakes, utils.total_unique_handshakes(self._config['bettercap']['handshakes']))) self.set_closest_peer(last_session.last_peer, last_session.peers) self.update() From e558146e28527fd2e88c6e4ab6cc8cf3d07f1e2b Mon Sep 17 00:00:00 2001 From: Jeroen Oudshoorn Date: Sun, 4 Feb 2024 17:42:40 +0100 Subject: [PATCH 16/19] moves the majority of logging to debug --- pwnagotchi/plugins/default/fix_services.py | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/pwnagotchi/plugins/default/fix_services.py b/pwnagotchi/plugins/default/fix_services.py index bd63db7f..5ab9d518 100644 --- a/pwnagotchi/plugins/default/fix_services.py +++ b/pwnagotchi/plugins/default/fix_services.py @@ -122,7 +122,7 @@ class FixServices(plugins.Plugin): # Look for pattern 1 if len(self.pattern.findall(last_lines)) >= 3: - logging.info("[Fix_Services]**** Should trigger a reload of the wlan0mon device:\n%s" % last_lines) + logging.debug("[Fix_Services]**** Should trigger a reload of the wlan0mon device:\n%s" % last_lines) if hasattr(agent, 'view'): display = agent.view() display.set('status', 'Blind-Bug detected. Restarting.') @@ -135,7 +135,7 @@ class FixServices(plugins.Plugin): # Look for pattern 2 elif len(self.pattern2.findall(other_last_lines)) >= 5: - logging.info("[Fix_Services]**** Should trigger a reload of the wlan0mon device:\n%s" % last_lines) + logging.debug("[Fix_Services]**** Should trigger a reload of the wlan0mon device:\n%s" % last_lines) if hasattr(agent, 'view'): display = agent.view() display.set('status', 'Wifi channel stuck. Restarting recon.') @@ -167,7 +167,7 @@ class FixServices(plugins.Plugin): try: # Run the monstart command to restart wlan0mon cmd_output = subprocess.check_output("monstart", shell=True) - logging.info("[Fix_Services monstart]: %s" % repr(cmd_output)) + logging.debug("[Fix_Services monstart]: %s" % repr(cmd_output)) except Exception as err: logging.error("[Fix_Services monstart]: %s" % repr(err)) @@ -181,7 +181,7 @@ class FixServices(plugins.Plugin): try: # Run the monstart command to restart wlan0mon cmd_output = subprocess.check_output("monstart", shell=True) - logging.info("[Fix_Services monstart]: %s" % repr(cmd_output)) + logging.debug("[Fix_Services monstart]: %s" % repr(cmd_output)) except Exception as err: logging.error("[Fix_Services monstart]: %s" % repr(err)) @@ -237,7 +237,7 @@ class FixServices(plugins.Plugin): # is it up? try: cmd_output = subprocess.check_output("ip link show wlan0mon", shell=True) - logging.info("[Fix_Services ip link show wlan0mon]: %s" % repr(cmd_output)) + logging.debug("[Fix_Services ip link show wlan0mon]: %s" % repr(cmd_output)) if ",UP," in str(cmd_output): logging.info("wlan0mon is up. Skip reset?") # not reliable, so don't skip just yet @@ -309,11 +309,9 @@ class FixServices(plugins.Plugin): # stop looping and get back to recon break else: - logging.info( - "[Fix_Services set wifi.interfaceface wlan0mon] failed? %s" % repr(result)) + logging.debug("[Fix_Services set wifi.interfaceface wlan0mon] failed? %s" % repr(result)) except Exception as err: - logging.info( - "[Fix_Services set wifi.interface wlan0mon] except: %s" % repr(err)) + logging.debug("[Fix_Services set wifi.interface wlan0mon] except: %s" % repr(err)) except Exception as cerr: # if not display: print("failed loading wlan0mon attempt #%s: %s" % (tries, repr(cerr))) @@ -362,7 +360,7 @@ class FixServices(plugins.Plugin): "face": faces.HAPPY}) else: print("I can see again") - logging.info("[Fix_Services] wifi.recon on") + logging.debug("[Fix_Services] wifi.recon on") self.LASTTRY = time.time() + 120 # 2-minute pause until next time. else: logging.error("[Fix_Services] wifi.recon did not start up") @@ -378,7 +376,7 @@ class FixServices(plugins.Plugin): try: logging.info("[Fix_Services] unloaded") except Exception as err: - logging.info("[Fix_Services] unload err %s " % repr(err)) + logging.error("[Fix_Services] unload err %s " % repr(err)) pass From d1428403076baa8e63b09212e31c4f60b48301ba Mon Sep 17 00:00:00 2001 From: Jeroen Oudshoorn Date: Sun, 4 Feb 2024 17:42:56 +0100 Subject: [PATCH 17/19] Revert "Testing pcapng fileformat" This reverts commit 7040be2d3079ce5d3496c858a07632da1dfda69b. --- pwnagotchi/plugins/default/gps.py | 2 +- pwnagotchi/plugins/default/grid.py | 17 +++---- pwnagotchi/plugins/default/hashie.py | 6 +-- pwnagotchi/plugins/default/net-pos.py | 2 +- pwnagotchi/plugins/default/onlinehashcrack.py | 4 +- pwnagotchi/plugins/default/webgpsmap.py | 44 +++++++++++-------- pwnagotchi/plugins/default/wigle.py | 10 ++--- pwnagotchi/plugins/default/wpa-sec.py | 2 +- pwnagotchi/utils.py | 10 ++--- 9 files changed, 53 insertions(+), 44 deletions(-) diff --git a/pwnagotchi/plugins/default/gps.py b/pwnagotchi/plugins/default/gps.py index 0e5f958d..a351406b 100644 --- a/pwnagotchi/plugins/default/gps.py +++ b/pwnagotchi/plugins/default/gps.py @@ -48,7 +48,7 @@ class GPS(plugins.Plugin): if self.running: info = agent.session() self.coordinates = info["gps"] - gps_filename = filename.replace(".pcapng", ".gps.json") + gps_filename = filename.replace(".pcap", ".gps.json") if self.coordinates and all([ # avoid 0.000... measurements diff --git a/pwnagotchi/plugins/default/grid.py b/pwnagotchi/plugins/default/grid.py index fbc3374e..cdca794e 100644 --- a/pwnagotchi/plugins/default/grid.py +++ b/pwnagotchi/plugins/default/grid.py @@ -5,21 +5,22 @@ import glob import re import pwnagotchi.grid as grid +import pwnagotchi.plugins import pwnagotchi.plugins as plugins -from pwnagotchi.utils import StatusFile, WifiInfo, extract_from_pcapng +from pwnagotchi.utils import StatusFile, WifiInfo, extract_from_pcap from threading import Lock def parse_pcap(filename): logging.info("grid: parsing %s ..." % filename) - net_id = os.path.basename(filename).replace('.pcapng', '') + net_id = os.path.basename(filename).replace('.pcap', '') if '_' in net_id: - # /root/handshakes/ESSID_BSSID.pcapng + # /root/handshakes/ESSID_BSSID.pcap essid, bssid = net_id.split('_') else: - # /root/handshakes/BSSID.pcapng + # /root/handshakes/BSSID.pcap essid, bssid = '', net_id mac_re = re.compile('[0-9a-fA-F]{12}') @@ -35,7 +36,7 @@ def parse_pcap(filename): } try: - info = extract_from_pcapng(filename, [WifiInfo.BSSID, WifiInfo.ESSID]) + info = extract_from_pcap(filename, [WifiInfo.BSSID, WifiInfo.ESSID]) except Exception as e: logging.error("grid: %s" % e) @@ -86,10 +87,10 @@ class Grid(plugins.Plugin): agent.view().on_unread_messages(self.unread_messages, self.total_messages) def check_handshakes(self, agent): - logging.debug("checking pcapng's") + logging.debug("checking pcaps") config = agent.config() - pcap_files = glob.glob(os.path.join(agent.config()['bettercap']['handshakes'], "*.pcapng")) + pcap_files = glob.glob(os.path.join(agent.config()['bettercap']['handshakes'], "*.pcap")) num_networks = len(pcap_files) reported = self.report.data_field_or('reported', default=[]) num_reported = len(reported) @@ -102,7 +103,7 @@ class Grid(plugins.Plugin): logging.debug(" exclude: %s" % config['main']['whitelist']) for pcap_file in pcap_files: - net_id = os.path.basename(pcap_file).replace('.pcapng', '') + net_id = os.path.basename(pcap_file).replace('.pcap', '') if net_id not in reported: if self.is_excluded(net_id, agent): logging.debug("skipping %s due to exclusion filter" % pcap_file) diff --git a/pwnagotchi/plugins/default/hashie.py b/pwnagotchi/plugins/default/hashie.py index b5c8e18a..cd41122b 100644 --- a/pwnagotchi/plugins/default/hashie.py +++ b/pwnagotchi/plugins/default/hashie.py @@ -82,12 +82,12 @@ class Hashie(plugins.Plugin): if os.path.isfile(fullpathNoExt + '.22000'): handshake_status.append('Already have {}.22000 (EAPOL)'.format(name)) elif self._writeEAPOL(filename): - handshake_status.append('Created {}.22000 (EAPOL) from pcapng'.format(name)) + handshake_status.append('Created {}.22000 (EAPOL) from pcap'.format(name)) if os.path.isfile(fullpathNoExt + '.16800'): handshake_status.append('Already have {}.16800 (PMKID)'.format(name)) elif self._writePMKID(filename): - handshake_status.append('Created {}.16800 (PMKID) from pcapng'.format(name)) + handshake_status.append('Created {}.16800 (PMKID) from pcap'.format(name)) if handshake_status: logging.info('[Hashie] Good news:\n\t' + '\n\t'.join(handshake_status)) @@ -111,7 +111,7 @@ class Hashie(plugins.Plugin): return False def _process_stale_pcaps(self, handshake_dir): - handshakes_list = [os.path.join(handshake_dir, filename) for filename in os.listdir(handshake_dir) if filename.endswith('.pcapng')] + handshakes_list = [os.path.join(handshake_dir, filename) for filename in os.listdir(handshake_dir) if filename.endswith('.pcap')] failed_jobs = [] successful_jobs = [] lonely_pcaps = [] diff --git a/pwnagotchi/plugins/default/net-pos.py b/pwnagotchi/plugins/default/net-pos.py index ef5f0c59..3f226204 100644 --- a/pwnagotchi/plugins/default/net-pos.py +++ b/pwnagotchi/plugins/default/net-pos.py @@ -108,7 +108,7 @@ class NetPos(plugins.Plugin): return netpos["ts"] = int("%.0f" % time.time()) - netpos_filename = filename.replace('.pcapng', '.net-pos.json') + netpos_filename = filename.replace('.pcap', '.net-pos.json') logging.debug("NET-POS: Saving net-location to %s", netpos_filename) try: diff --git a/pwnagotchi/plugins/default/onlinehashcrack.py b/pwnagotchi/plugins/default/onlinehashcrack.py index 1eafb9fa..aeb01dda 100644 --- a/pwnagotchi/plugins/default/onlinehashcrack.py +++ b/pwnagotchi/plugins/default/onlinehashcrack.py @@ -142,6 +142,6 @@ class OnlineHashCrack(plugins.Plugin): for row in csv.DictReader(cracked_list): if row['password']: filename = re.sub(r'[^a-zA-Z0-9]', '', row['ESSID']) + '_' + row['BSSID'].replace(':','') - if os.path.exists( os.path.join(handshake_dir, filename+'.pcapng')): - with open(os.path.join(handshake_dir, filename+'.pcapng.cracked'), 'w') as f: + if os.path.exists( os.path.join(handshake_dir, filename+'.pcap') ): + with open(os.path.join(handshake_dir, filename+'.pcap.cracked'), 'w') as f: f.write(row['password']) diff --git a/pwnagotchi/plugins/default/webgpsmap.py b/pwnagotchi/plugins/default/webgpsmap.py index b03fef50..f9f513d9 100644 --- a/pwnagotchi/plugins/default/webgpsmap.py +++ b/pwnagotchi/plugins/default/webgpsmap.py @@ -13,8 +13,8 @@ from dateutil.parser import parse webgpsmap shows existing position data stored in your /handshakes/ directory the plugin does the following: - - search for *.pcapng files in your /handshakes/ dir - - for every found .pcapng file it looks for a .geo.json or .gps.json or file with + - search for *.pcap files in your /handshakes/ dir + - for every found .pcap file it looks for a .geo.json or .gps.json or .paw-gps.json file with latitude+longitude data inside and shows this position on the map - if also an .cracked file with a plaintext password inside exist, it reads the content and shows the position as green instead of red and the password inside the infopox of the position @@ -87,8 +87,7 @@ class Webgpsmap(plugins.Plugin): # returns all positions try: self.ALREADY_SENT = list() - response_data = bytes( - json.dumps(self.load_gps_from_dir(self.config['bettercap']['handshakes'])), "utf-8") + response_data = bytes(json.dumps(self.load_gps_from_dir(self.config['bettercap']['handshakes'])), "utf-8") response_status = 200 response_mimetype = "application/json" response_header_contenttype = 'application/json' @@ -101,8 +100,7 @@ class Webgpsmap(plugins.Plugin): self.ALREADY_SENT = list() json_data = json.dumps(self.load_gps_from_dir(self.config['bettercap']['handshakes'])) html_data = self.get_html() - html_data = html_data.replace('var positions = [];', - 'var positions = ' + json_data + ';positionsLoaded=true;drawPositions();') + html_data = html_data.replace('var positions = [];', 'var positions = ' + json_data + ';positionsLoaded=true;drawPositions();') response_data = bytes(html_data, "utf-8") response_status = 200 response_mimetype = "application/xhtml+xml" @@ -165,8 +163,7 @@ class Webgpsmap(plugins.Plugin): all_files = os.listdir(handshake_dir) # print(all_files) - all_pcap_files = [os.path.join(handshake_dir, filename) for filename in all_files if - filename.endswith('.pcapng')] + all_pcap_files = [os.path.join(handshake_dir, filename) for filename in all_files if filename.endswith('.pcap')] all_geo_or_gps_files = [] for filename_pcap in all_pcap_files: filename_base = filename_pcap[:-5] # remove ".pcap" @@ -183,18 +180,22 @@ class Webgpsmap(plugins.Plugin): if check_for in all_files: filename_position = str(os.path.join(handshake_dir, check_for)) + logging.debug("[webgpsmap] search for .paw-gps.json") + check_for = os.path.basename(filename_base) + ".paw-gps.json" + if check_for in all_files: + filename_position = str(os.path.join(handshake_dir, check_for)) + logging.debug(f"[webgpsmap] end search for position data files and use {filename_position}") if filename_position is not None: all_geo_or_gps_files.append(filename_position) - # all_geo_or_gps_files = set(all_geo_or_gps_files) - set(SKIP) # remove skipped networks? No! + # all_geo_or_gps_files = set(all_geo_or_gps_files) - set(SKIP) # remove skipped networks? No! if newest_only: all_geo_or_gps_files = set(all_geo_or_gps_files) - set(self.ALREADY_SENT) - logging.info( - f"[webgpsmap] Found {len(all_geo_or_gps_files)} position-data files from {len(all_pcap_files)} handshakes. Fetching positions ...") + logging.info(f"[webgpsmap] Found {len(all_geo_or_gps_files)} position-data files from {len(all_pcap_files)} handshakes. Fetching positions ...") for pos_file in all_geo_or_gps_files: try: @@ -212,7 +213,9 @@ class Webgpsmap(plugins.Plugin): pos_type = 'gps' elif pos.type() == PositionFile.GEO: pos_type = 'geo' - gps_data[ssid + "_" + mac] = { + elif pos.type() == PositionFile.PAWGPS: + pos_type = 'paw' + gps_data[ssid+"_"+mac] = { 'ssid': ssid, 'mac': mac, 'type': pos_type, @@ -221,10 +224,10 @@ class Webgpsmap(plugins.Plugin): 'acc': pos.accuracy(), 'ts_first': pos.timestamp_first(), 'ts_last': pos.timestamp_last(), - } + } # get ap password if exist - check_for = os.path.basename(pos_file).split(".")[0] + ".pcapng.cracked" + check_for = os.path.basename(pos_file).split(".")[0] + ".pcap.cracked" if check_for in all_files: gps_data[ssid + "_" + mac]["pass"] = pos.password() @@ -262,6 +265,7 @@ class PositionFile: """ GPS = 1 GEO = 2 + PAWGPS = 3 def __init__(self, path): self._file = path @@ -278,7 +282,7 @@ class PositionFile: """ Returns the mac from filename """ - parsed_mac = re.search(r'.*_?([a-zA-Z0-9]{12})\.(?:gps|geo)\.json', self._filename) + parsed_mac = re.search(r'.*_?([a-zA-Z0-9]{12})\.(?:gps|geo|paw-gps)\.json', self._filename) if parsed_mac: mac = parsed_mac.groups()[0] return mac @@ -288,7 +292,7 @@ class PositionFile: """ Returns the ssid from filename """ - parsed_ssid = re.search(r'(.+)_[a-zA-Z0-9]{12}\.(?:gps|geo)\.json', self._filename) + parsed_ssid = re.search(r'(.+)_[a-zA-Z0-9]{12}\.(?:gps|geo|paw-gps)\.json', self._filename) if parsed_ssid: return parsed_ssid.groups()[0] return None @@ -329,7 +333,7 @@ class PositionFile: return_pass = None # 2do: make better filename split/remove extension because this one has problems with "." in path base_filename, ext1, ext2 = re.split('\.', self._file) - password_file_path = base_filename + ".pcapng.cracked" + password_file_path = base_filename + ".pcap.cracked" if os.path.isfile(password_file_path): try: password_file = open(password_file_path, 'r') @@ -350,6 +354,8 @@ class PositionFile: return PositionFile.GPS if self._file.endswith('.geo.json'): return PositionFile.GEO + if self._file.endswith('.paw-gps.json'): + return PositionFile.PAWGPS return None def lat(self): @@ -396,7 +402,9 @@ class PositionFile: def accuracy(self): if self.type() == PositionFile.GPS: - return 50.0 # a default + return 50.0 # a default + if self.type() == PositionFile.PAWGPS: + return 50.0 # a default if self.type() == PositionFile.GEO: try: return self._json['accuracy'] diff --git a/pwnagotchi/plugins/default/wigle.py b/pwnagotchi/plugins/default/wigle.py index 11805c3b..353660ea 100644 --- a/pwnagotchi/plugins/default/wigle.py +++ b/pwnagotchi/plugins/default/wigle.py @@ -7,7 +7,7 @@ import pwnagotchi from io import StringIO from datetime import datetime -from pwnagotchi.utils import WifiInfo, FieldNotFoundError, extract_from_pcapng, StatusFile, remove_whitelisted +from pwnagotchi.utils import WifiInfo, FieldNotFoundError, extract_from_pcap, StatusFile, remove_whitelisted from threading import Lock from pwnagotchi import plugins from pwnagotchi._version import __version__ as __pwnagotchi_version__ @@ -153,11 +153,11 @@ class Wigle(plugins.Plugin): no_err_entries = list() for gps_file in new_gps_files: if gps_file.endswith('.gps.json'): - pcap_filename = gps_file.replace('.gps.json', '.pcapng') + pcap_filename = gps_file.replace('.gps.json', '.pcap') if gps_file.endswith('.geo.json'): - pcap_filename = gps_file.replace('.geo.json', '.pcapng') + pcap_filename = gps_file.replace('.geo.json', '.pcap') if not os.path.exists(pcap_filename): - logging.debug("WIGLE: Can't find pcapng for %s", gps_file) + logging.debug("WIGLE: Can't find pcap for %s", gps_file) self.skip.append(gps_file) continue try: @@ -175,7 +175,7 @@ class Wigle(plugins.Plugin): self.skip.append(gps_file) continue try: - pcap_data = extract_from_pcapng(pcap_filename, [WifiInfo.BSSID, + pcap_data = extract_from_pcap(pcap_filename, [WifiInfo.BSSID, WifiInfo.ESSID, WifiInfo.ENCRYPTION, WifiInfo.CHANNEL, diff --git a/pwnagotchi/plugins/default/wpa-sec.py b/pwnagotchi/plugins/default/wpa-sec.py index 42f1c29f..696b53b4 100644 --- a/pwnagotchi/plugins/default/wpa-sec.py +++ b/pwnagotchi/plugins/default/wpa-sec.py @@ -98,7 +98,7 @@ class WpaSec(plugins.Plugin): reported = self.report.data_field_or('reported', default=list()) handshake_dir = config['bettercap']['handshakes'] handshake_filenames = os.listdir(handshake_dir) - handshake_paths = [os.path.join(handshake_dir, filename) for filename in handshake_filenames if filename.endswith('.pcapng')] + handshake_paths = [os.path.join(handshake_dir, filename) for filename in handshake_filenames if filename.endswith('.pcap')] handshake_paths = remove_whitelisted(handshake_paths, config['main']['whitelist']) handshake_new = set(handshake_paths) - set(reported) - set(self.skip) diff --git a/pwnagotchi/utils.py b/pwnagotchi/utils.py index eacf8899..4158f94b 100644 --- a/pwnagotchi/utils.py +++ b/pwnagotchi/utils.py @@ -82,7 +82,7 @@ def remove_whitelisted(list_of_handshakes, list_of_whitelisted_strings, valid_on for handshake in list_of_handshakes: try: - normalized_handshake = normalize(os.path.basename(handshake).rstrip('.pcapng')) + normalized_handshake = normalize(os.path.basename(handshake).rstrip('.pcap')) for whitelist in list_of_whitelisted_strings: normalized_whitelist = normalize(whitelist) if normalized_whitelist in normalized_handshake: @@ -440,7 +440,7 @@ def secs_to_hhmmss(secs): def total_unique_handshakes(path): - expr = os.path.join(path, "*.pcapng") + expr = os.path.join(path, "*.pcap") return len(glob.glob(expr)) @@ -498,11 +498,11 @@ def md5(fname): return hash_md5.hexdigest() -def extract_from_pcapng(path, fields): +def extract_from_pcap(path, fields): """ - Search in pcapng-file for specified information + Search in pcap-file for specified information - path: Path to pcapng file + path: Path to pcap file fields: Array of fields that should be extracted If a field is not found, FieldNotFoundError is raised From c5ee1df855a4570b79f40b9f4df3b8656a99e015 Mon Sep 17 00:00:00 2001 From: Jeroen Oudshoorn Date: Sun, 4 Feb 2024 17:44:05 +0100 Subject: [PATCH 18/19] unused function --- bin/pwnagotchi | 1 - 1 file changed, 1 deletion(-) diff --git a/bin/pwnagotchi b/bin/pwnagotchi index c0540374..81f2f0f2 100755 --- a/bin/pwnagotchi +++ b/bin/pwnagotchi @@ -51,7 +51,6 @@ def pwnagotchi_cli(): agent.mode = 'auto' agent.start() config = agent.config() - session = agent.session() while True: try: From 1cefae55d1c746a27950a0ad4c87f7b5b447fd11 Mon Sep 17 00:00:00 2001 From: Jeroen Oudshoorn Date: Sun, 4 Feb 2024 17:48:22 +0100 Subject: [PATCH 19/19] moved the majority of logging to debug --- pwnagotchi/plugins/default/fix_services.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pwnagotchi/plugins/default/fix_services.py b/pwnagotchi/plugins/default/fix_services.py index 5ab9d518..e79eb3b2 100644 --- a/pwnagotchi/plugins/default/fix_services.py +++ b/pwnagotchi/plugins/default/fix_services.py @@ -46,7 +46,7 @@ class FixServices(plugins.Plugin): last_lines = self.get_last_lines('journalctl', ['-n10', '-k'], 10) try: cmd_output = subprocess.check_output("ip link show wlan0mon", shell=True) - logging.info("[Fix_Services ip link show wlan0mon]: %s" % repr(cmd_output)) + logging.debug("[Fix_Services ip link show wlan0mon]: %s" % repr(cmd_output)) if ",UP," in str(cmd_output): logging.info("wlan0mon is up.")