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)