Pyshark: can only get the first value of a field if the same key name (field name) shows multiple records with different value

I am using Pyshark to parse the Wifferhark sniffer log and I used an exported Json file (based on the pcapny file) to find the field names while using the get_field_value function to retrieve the field value.

For example, to get the BSSID value:

  • In a Json format file this information is displayed as

    "wlan.bssid": "11:22:33:44:55:66"
    
          

  • Then I could use:

    value = packet['wlan'].get_field_value('bssid')
    
          

  • Result expected:

    value == '11:22:33:44:55:66'
    
          

  • In this case, it works fine.

But I faced the problem with the below condition when I go to the "wlan_mgt" section in the beacon packet like below: - In the Json format file it shows:

      "wlan_mgt.tagged.all": {
        "wlan_mgt.tag": {
          "wlan_mgt.tag.number": "0",
          "wlan_mgt.tag.length": "5",
          "wlan_mgt.ssid": "MWIFI"
        },
        "wlan_mgt.tag": {
          "wlan_mgt.tag.number": "1",
          "wlan_mgt.tag.length": "6",
          "wlan_mgt.supported_rates": "24",
          "wlan_mgt.supported_rates": "164",
          "wlan_mgt.supported_rates": "48",
          "wlan_mgt.supported_rates": "72",
          "wlan_mgt.supported_rates": "96",
          "wlan_mgt.supported_rates": "108"
        },
        "wlan_mgt.tag": {
          "wlan_mgt.tag.number": "5",
          "wlan_mgt.tag.length": "7",
          "wlan_mgt.tim.dtim_count": "0",
          "wlan_mgt.tim.dtim_period": "1",
          "wlan_mgt.tim.bmapctl": "0x00000000",
          "wlan_mgt.tim.bmapctl_tree": {
            "wlan_mgt.tim.bmapctl.multicast": "0",
            "wlan_mgt.tim.bmapctl.offset": "0x00000000"
          },
          "wlan_mgt.tim.partial_virtual_bitmap": "00:10:00:00",
          "wlan.tim.aid": "0x0000000c"
        },

      

As we can see, there are multiple records for "wlan_mgt.supported_rates", the field name (key) is the same, and the value for each record is different from what I need to get them all. But if I use: - If I use:

    value = packet['wlan_mgt'].get_field_value('supported_rates')

      

- Then this gives me the value "24" which is the value of the first entry. And I have no idea how to get other input values ​​since the key name is the same.

Should it return a list of all values ​​like ['24', '164', '48', '72', '96', '108'] and not just the 1st position? Since based on the sniffer log (Json format) there are many other entries with the same field name like 'wlan_mgt.tag.number' but different field value, so this problem is blocker for me.

Please advise us how to get all the data and thanks a lot in advance!

BR,
Alex

+3


source to share


3 answers


First, you don't need to use subset of elements and get_field_value to get field values. Therefore, instead of

value = packet['wlan_mgt'].get_field_value('supported_rates')

      

You can use:



value = packet.wlan_mgt.supported_rates

      

To get tags on wifi packet in JSON mode you can use packet.wlan_mgt.tagged.all.tag

. This gives you a list of all tags, you can filter this with python to find only the supported bid tag. I was planning to make an extension specifically for this type of WiFi as it is cumbersome, but I haven't had the option yet. If you look at the field on wireshark, you can see that the category is tagged.all.

Also, when searching for fields, etc. I recommend using an autocomplete interpreter (like IPython) so you can just see which fields are available, or just use packet_layer.field_names

to see all available fields.

+1


source


I faced a similar problem, I checked the option_len field and only got one value instead of an array and couldn't find a simple answer directly; The solution I ended up using was to access the alternate fields available inside the field, as in the following code:

ol_arr = []
for x in cap[3].tcp._all_fields.values():
    if x.name == 'tcp.option_len':
        print(x.all_fields)
        for k in x.all_fields:
            print(k.get_default_value())
            ol_arr.append(k.get_default_value())
        break
print(ol_arr)

      



Hope this helps

+1


source


This is a serious problem and exists elsewhere in "Wireshark tools".

For example, when using tshark to read pcap.

tshark -r some_file.pcap -T json

      

it also returns JSON which contains multiple keys.

This is also post to Wireshark-dev and someone will fix it, but the code hasn't been pasted yet. You can read about it here

You can fix it with this code:

import json

def parse_object_pairs(pairs):
    """
    This function get list of tuple's
    and check if have duplicate keys.
    if have then return the pairs list itself.
    but if haven't return dict that contain pairs.

    >>> parse_object_pairs([("color": "red"), ("size": 3)])
    {"color": "red", "size": 3}

    >>> parse_object_pairs([("color": "red"), ("size": 3), ("color": "blue")])
    [("color": "red"), ("size": 3), ("color": "blue")]

    :param pairs: list of tuples.
    :return dict or list that contain pairs.
    """
    dict_without_duplicate = dict()
    for k, v in pairs:
        if k in dict_without_duplicate:
            return pairs
        else:
            dict_without_duplicate[k] = v

    return dict_without_duplicate

decoder = json.JSONDecoder(object_pairs_hook=parse_object_pairs)

str_json_can_be_with_duplicate_keys = '{"color": "red", "size": 3, "color": "red"}'

data_after_decode = decoder.decode(str_json_can_be_with_duplicate_keys)

      

+1


source







All Articles