Last active
April 13, 2023 08:18
-
-
Save BrandonFanti/8e475a47a5242506fc5f15e09bad4134 to your computer and use it in GitHub Desktop.
Find a key for a dictionary - at any level of nesting in either lists or dictionaries
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| ''' | |
| I could not find a function to get the key of a given collection of dictionaries OR arrays, at any depth, AND provide the path | |
| Though SURELY it must exist | |
| ''' | |
| def iter_instructor(x, key_target): | |
| ''' | |
| Recursively searches the object for the given key | |
| Parameters: | |
| (list/dict) x : A list or dictionary | |
| (String) key_target : A key to search for | |
| Returns: | |
| instruct (tuple) : Returns nested tuples up to key_target (Final layer is 'key_target':'key_target') | |
| ''' | |
| for i,key in enumerate(x): | |
| if key == key_target: return (key,x[key]) | |
| if type(x) == type([]): | |
| #print(f"Iterating array {x}") | |
| if hasattr(x[i],'__iter__'): | |
| instruct = (i,iter_instructor(x[i],key_target)) | |
| else: continue | |
| if instruct[1]: return instruct | |
| if type(x) == type({}): | |
| #print(f"Iterating dict {x}") | |
| if hasattr(x[key],'__iter__'): | |
| instruct = (key,iter_instructor(x[key],key_target)) | |
| else: continue | |
| if instruct[1]: return instruct | |
| #Recursively use instructions | |
| def get_key(x, key_target): | |
| if type(key_target) == type(''): | |
| key_target = iter_instructor(x, key_target) | |
| if key_target: | |
| if x[key_target[0]] != key_target[1]: | |
| return get_key(x[key_target[0]], key_target[1]) | |
| else: | |
| return x[key_target[0]] | |
| ''' | |
| Example: | |
| kismet_device = {'dot11.device': {'dot11.device.advertised_ssid_map': [{'dot11.advertisedssid.beacon': ..., | |
| 'dot11.advertisedssid.beaconrate': ..., | |
| 'dot11.advertisedssid.beacons_sec': ..., | |
| 'dot11.advertisedssid.ccx_txpower': ..., | |
| 'dot11.advertisedssid.channel': '157', | |
| 'dot11.advertisedssid.cisco_client_mfp': ..., | |
| 'dot11.advertisedssid.cloaked': ..., | |
| 'dot11.advertisedssid.crypt_set': ..., | |
| 'dot11.advertisedssid.dot11d_country': 'US', | |
| 'dot11.advertisedssid.dot11e_channel_utilization_perc': ..., | |
| 'dot11.advertisedssid.dot11e_qbss': 1, | |
| 'dot11.advertisedssid.dot11e_qbss_stations': ..., | |
| 'dot11.advertisedssid.dot11r_mobility': ..., | |
| 'dot11.advertisedssid.dot11r_mobility_domain_id': ..., | |
| 'dot11.advertisedssid.first_time': ..., | |
| 'dot11.advertisedssid.ht_center_1': ..., | |
| 'dot11.advertisedssid.ht_center_2': ..., | |
| 'dot11.advertisedssid.ht_mode': 'HT80', | |
| 'dot11.advertisedssid.ietag_checksum': ......, | |
| 'dot11.advertisedssid.last_time': ..., | |
| 'dot11.advertisedssid.maxrate': ..., | |
| 'dot11.advertisedssid.probe_response': ..., | |
| 'dot11.advertisedssid.ssid': '', | |
| 'dot11.advertisedssid.ssid_hash': ..., | |
| 'dot11.advertisedssid.ssidlen': ..., | |
| 'dot11.advertisedssid.wpa_mfp_required': ..., | |
| 'dot11.advertisedssid.wpa_mfp_supported': ...}], | |
| 'dot11.device.beacon_fingerprint': ..., | |
| 'dot11.device.bss_timestamp': ..., | |
| 'dot11.device.client_disconnects': ..., | |
| 'dot11.device.client_disconnects_last': ..., | |
| 'dot11.device.datasize': ..., | |
| 'dot11.device.datasize_retry': ..., | |
| 'dot11.device.last_beacon_timestamp': ..., | |
| 'dot11.device.last_beaconed_ssid_record': {'dot11.advertisedssid.beacon': ..., | |
| 'dot11.advertisedssid.beaconrate': ..., | |
| 'dot11.advertisedssid.beacons_sec': ..., | |
| 'dot11.advertisedssid.ccx_txpower': ..., | |
| 'dot11.advertisedssid.channel': '157', | |
| 'dot11.advertisedssid.cisco_client_mfp': ..., | |
| 'dot11.advertisedssid.cloaked': 1, | |
| 'dot11.advertisedssid.crypt_set': ..., | |
| 'dot11.advertisedssid.dot11d_country': 'US', | |
| 'dot11.advertisedssid.dot11e_channel_utilization_perc': ..., | |
| 'dot11.advertisedssid.dot11e_qbss': 1, | |
| 'dot11.advertisedssid.dot11e_qbss_stations': ..., | |
| 'dot11.advertisedssid.dot11r_mobility': ..., | |
| 'dot11.advertisedssid.dot11r_mobility_domain_id': ..., | |
| 'dot11.advertisedssid.first_time': ..., | |
| 'dot11.advertisedssid.ht_center_1': ..., | |
| 'dot11.advertisedssid.ht_center_2': ..., | |
| 'dot11.advertisedssid.ht_mode': 'HT80', | |
| 'dot11.advertisedssid.ietag_checksum': ..., | |
| 'dot11.advertisedssid.last_time': ..., | |
| 'dot11.advertisedssid.maxrate': ..., | |
| 'dot11.advertisedssid.probe_response': ..., | |
| 'dot11.advertisedssid.ssid': '', | |
| 'dot11.advertisedssid.ssid_hash': ..., | |
| 'dot11.advertisedssid.ssidlen': ..., | |
| 'dot11.advertisedssid.wpa_mfp_required': ..., | |
| 'dot11.advertisedssid.wpa_mfp_supported': ...}, | |
| 'dot11.device.last_bssid': '...', | |
| 'dot11.device.last_sequence': ..., | |
| 'dot11.device.link_measurement_capable': ..., | |
| 'dot11.device.max_tx_power': ..., | |
| 'dot11.device.min_tx_power': ..., | |
| 'dot11.device.neighbor_report_capable': ..., | |
| 'dot11.device.num_advertised_ssids': ..., | |
| 'dot11.device.num_associated_clients': ..., | |
| 'dot11.device.num_client_aps': ..., | |
| 'dot11.device.num_fragments': ..., | |
| 'dot11.device.num_probed_ssids': ..., | |
| 'dot11.device.num_responded_ssids': ..., | |
| 'dot11.device.num_retries': ..., | |
| 'dot11.device.probe_fingerprint': ..., | |
| 'dot11.device.response_fingerprint': ..., | |
| 'dot11.device.typeset': ..., | |
| 'dot11.device.wps_m3_count': ..., | |
| 'dot11.device.wps_m3_last': ...}, | |
| 'kismet.device.base.basic_crypt_set': ..., | |
| 'kismet.device.base.basic_type_set': ..., | |
| 'kismet.device.base.channel': '157', | |
| 'kismet.device.base.commonname': '...', | |
| 'kismet.device.base.crypt': 'WPA2-PSK', | |
| 'kismet.device.base.datasize': ..., | |
| 'kismet.device.base.first_time': ..., | |
| 'kismet.device.base.freq_khz_map': {'...':'...'}, | |
| 'kismet.device.base.frequency': ..., | |
| 'kismet.device.base.key': '...', | |
| 'kismet.device.base.last_time': ..., | |
| 'kismet.device.base.macaddr': '...', | |
| 'kismet.device.base.manuf': '...', | |
| 'kismet.device.base.mod_time': ..., | |
| 'kismet.device.base.name': '...', | |
| 'kismet.device.base.num_alerts': ..., | |
| 'kismet.device.base.packets.crypt': ..., | |
| 'kismet.device.base.packets.data': ..., | |
| 'kismet.device.base.packets.error': ..., | |
| 'kismet.device.base.packets.filtered': ..., | |
| 'kismet.device.base.packets.llc': ..., | |
| 'kismet.device.base.packets.rrd': {'kismet.common.rrd.blank_val': ..., | |
| 'kismet.common.rrd.day_vec': [...], | |
| 'kismet.common.rrd.hour_vec': [...], | |
| 'kismet.common.rrd.last_time': ..., | |
| 'kismet.common.rrd.minute_vec': [...], | |
| 'kismet.common.rrd.serial_time': ...}, | |
| 'kismet.device.base.packets.total': ..., | |
| 'kismet.device.base.phyname': 'IEEE802.11', | |
| 'kismet.device.base.related_devices': {}, | |
| 'kismet.device.base.seenby': [{'kismet.common.seenby.first_time': ..., | |
| 'kismet.common.seenby.last_time': ..., | |
| 'kismet.common.seenby.num_packets': ..., | |
| 'kismet.common.seenby.uuid': '...'}], | |
| 'kismet.device.base.signal': {'kismet.common.signal.carrierset': ..., | |
| 'kismet.common.signal.encodingset': ..., | |
| 'kismet.common.signal.last_noise': ..., | |
| 'kismet.common.signal.last_signal': ..., | |
| 'kismet.common.signal.max_noise': ..., | |
| 'kismet.common.signal.max_signal': ..., | |
| 'kismet.common.signal.maxseenrate': ..., | |
| 'kismet.common.signal.min_noise': ..., | |
| 'kismet.common.signal.min_signal': ..., | |
| 'kismet.common.signal.signal_rrd': {'kismet.common.rrd.blank_val': ..., | |
| 'kismet.common.rrd.last_time': ..., | |
| 'kismet.common.rrd.minute_vec': [...], | |
| 'kismet.common.rrd.serial_time': ...}, | |
| 'kismet.common.signal.type': 'dbm'}, | |
| 'kismet.device.base.type': 'Wi-Fi AP', | |
| 'kismet.server.uuid': '...'} | |
| Even in a pretty print... those depths are dumb AF. Luckily - thank you kismet devs - keys are unique! So - | |
| instruct = iter_instructor(device, 'dot11.advertisedssid.ht_mode') | |
| if instruct: | |
| print(instruct) | |
| print(get_key(kismet_device,'dot11.advertisedssid.ht_mode')) | |
| Gives us ~~~ | |
| ('dot11.device', ('dot11.device.advertised_ssid_map', (0, ('dot11.advertisedssid.ht_mode', 'HT80')))) | |
| 'HT80' | |
| ~ A tidy search path and the key value | |
| ' | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment