Pyshark: может получить только первое значение поля, если одно и то же имя ключа (имя поля) показывает несколько записей с различным значением

Я использую Pyshark для анализа журнала анализатора Wireshark, и я использовал экспортированный файл формата Json (на основе файла pcapny), чтобы найти имена полей при использовании функции 'get_field_value' для получения значения поля.

Например, чтобы получить значение BSSID:

  • В файле формата Json эта информация отображается как

    "wlan.bssid": "11:22:33:44:55:66"
    
  • Тогда я мог бы использовать:

    value = packet['wlan'].get_field_value('bssid')
    
  • Результат ожидается:

    value == '11:22:33:44:55:66'
    
  • В этом случае все работает нормально.

Но я сталкиваюсь с проблемой с условием ниже, когда я перехожу к разделу 'wlan_mgt' в пакете маяка, как пример, показанный ниже: - В файле формата Json он показывает:

      "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"
        },

Как мы видим, существует несколько записей для "wlan_mgt.supported_rates", имя поля (ключ) одинаковое, а значение для каждой записи различно, и мне нужно будет получить их все. Но если я использую: - Если я использую:

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

- Тогда это только дает мне значение "24", которое является значением 1-й записи. И я понятия не имею, как получить другие значения записи, так как имя ключа такое же.

Должен ли он возвращать список всех значений, таких как ['24', '164','48','72','96','108'], а не только 1-е значение записи? Поскольку на основе журнала сниффера (в формате Json) есть много других записей с тем же именем поля, например, "wlan_mgt.tag.number", но с другим значением поля, так что эта проблема для меня блокирует.

Просьба совет, как получить все данные, и большое спасибо заранее!

BR,
Alex

4 ответа

Я столкнулся с подобной проблемой, я проверял поле option_len и получил только одно значение вместо массива и не смог найти простой ответ напрямую; Решение, которое я в конечном итоге использовал, состояло в том, чтобы получить доступ к альтернативным полям, доступным внутри поля, как в следующем коде:

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)

Надеюсь, это поможет

Во-первых, вам не нужно использовать подмножество элементов и get_field_value, чтобы получить значения полей. Так что вместо

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

Ты можешь использовать:

value = packet.wlan_mgt.supported_rates

Чтобы получить теги для пакета Wi-Fi в режиме JSON, вы можете использовать packet.wlan_mgt.tagged.all.tag, Это дает вам список всех тегов, которые вы можете отфильтровать, используя python, чтобы найти только тег поддерживаемых ставок. Я планировал сделать расширение специально для таких вещей, как WiFi, так как это громоздко, но у меня еще не было возможности. Если вы посмотрите на поле на Wireshark, вы увидите, что категория помечена.

Кроме того, при поиске полей и т.п. я рекомендую использовать интерпретатор с автозаполнением (например, IPython), чтобы вы могли просто посмотреть, какие поля доступны, или просто использовать packet_layer.field_names чтобы увидеть все доступные поля.

Это серьезная проблема, и она существует в других местах в "инструментах Wireshark".

Например, при использовании tshark для чтения файла pcap.

tshark -r some_file.pcap -T json

он также возвращает JSON, который содержит несколько ключей.

Это также опубликовать в Wireshark-dev, и кто-то исправит это, но код еще не вставлен.

Вы можете исправить это с помощью этого кода:

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)

У меня также была эта проблема в течение длительного времени, что я не мог получить значения полей с тем же именем, но, наконец, я нашел способ решить проблему:

Вы можете использоватьall_fieldsатрибут поля, у которого есть несколько альтернатив . Он возвращаетlistподобных полей.

например

      >> packet.layer.field.all_fields
[<field>, <field>, <field>, ...]

Образец кода:

      import pyshark
cap = pyshark.FileCapture('/tmp/mycapture.cap')

for pkt in cap:
   if hasattr(pkt.layer.field, "all_fields"):
       similar_fields = pkt.layer.field.all_fields
       for f in similar_fields:
           print(f.show)
Другие вопросы по тегам