Skip to content

Instantly share code, notes, and snippets.

@BrandonFanti
Last active April 13, 2023 08:18
Show Gist options
  • Select an option

  • Save BrandonFanti/8e475a47a5242506fc5f15e09bad4134 to your computer and use it in GitHub Desktop.

Select an option

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
'''
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