Заставить scapy повторно анализировать слой после изменений

Я работаю с вилкой scapy (инструмент для манипулирования пакетами Python) под названием scapy-com. Это реализует разбор / манипулирование 802.15.4 и Zigbee, среди других протоколов.

Изюминка протокола Zigbee находится в заголовке безопасности сетевого уровня. Первоначально уровень безопасности (который определяет шифрование и длину кода целостности сообщения) устанавливается правильно, но затем устанавливается в 0 (без шифрования) перед его отправкой. Из спецификации:

Подполе уровня безопасности поля управления безопасностью должно быть перезаписано 3-битной строкой со всеми нулями '000'

Спецификацию можно найти здесь. Соответствующий раздел - "4.3.1.1 Обработка безопасности исходящих кадров".

Это означает, что перехваты пакетов указывают на то, что не используется ни код шифрования, ни код целостности сообщения. Уровень безопасности должен передаваться вне диапазона.

scapy-com с этим не справляется. Он наивно анализирует уровень безопасности и устанавливает длину MIC равной 0. Код, который делает это:

def util_mic_len(pkt):
    ''' Calculate the length of the attribute value field '''
    # NWK security level 0 seems to implicitly be same as 5
    if ( pkt.nwk_seclevel == 0 ): # no encryption, no mic
        return 0
    elif ( pkt.nwk_seclevel == 1 ): # MIC-32
        return 4
    elif ( pkt.nwk_seclevel == 2 ): # MIC-64
        return 8
    elif ( pkt.nwk_seclevel == 3 ): # MIC-128
        return 16
    elif ( pkt.nwk_seclevel == 4 ): # ENC
        return 0
    elif ( pkt.nwk_seclevel == 5 ): # ENC-MIC-32
        return 4
    elif ( pkt.nwk_seclevel == 6 ): # ENC-MIC-64
        return 8
    elif ( pkt.nwk_seclevel == 7 ): # ENC-MIC-128
        return 16
    else:
        return 0

Проект, который использует scapy-com, пытается справиться с этим, установив уровень безопасности на 5:

#TODO: Investigate and issue a different fix:
# https://code.google.com/p/killerbee/issues/detail?id=30
# This function destroys the packet, therefore work on a copy - @cutaway
pkt = pkt.copy()   #this is hack to fix the below line
pkt.nwk_seclevel=5 #the issue appears to be when this is set

mic = pkt.mic

Однако это не работает - код целостности сообщения уже установлен. Я работал над этим, просто изменив функцию util_mic_len для правильной установки длины микрофона.

Вопрос в том, как следует изменить синтаксический анализатор Zigbee, чтобы изменение nwk_seclevel после первоначального вскрытия приводило к обновлению длины микрофона?

Я вижу два решения:

  1. Измените код scapy-com так, чтобы изменение nwk_seclevel автоматически изменяло длину микрофона.
  2. Повторно рассмотрите пакеты снаружи scapy-com, когда они будут изменены.

Проблема с 1 - я понятия не имею, как это сделать.

Проблема с 2 заключается в том, что у меня есть идея, но я не могу заставить ее работать - я не могу понять, как вызвать анализ на пакет после его загрузки. Вызов pkt.dissect (pkt) не работает и выглядит странно.

Какое лучшее или рекомендуемое решение здесь?

2 ответа

Исправление звуков scapy правильное решение. scapy-com довольно старый. Специфичный для Zigbee код в scapy-com - это 1244 строки кода, которые в значительной степени являются перечислениями и списками полей. Таким образом, не должно быть слишком сложно перенести его на scapy-python3. Если бы вы помогли перенести его на scapy-python3 http://github.com/phaethon/scapy, я мог бы помочь решить проблему.

Проект, на который вы ссылаетесь, это KillerBee, и у меня была именно эта проблема с расшифровкой. Я просто "исправил" код таким образом:

from struct import pack
f = pkt.getlayer(ZigbeeSecurityHeader).fields

pkt.nwk_seclevel = 5
nwk_mic = pkt.mic
nwk_encrypted = f['data'][:-6]

ext_source = f['ext_source']

nwk_sec_ctrl_byte = str(pkt.getlayer(ZigbeeSecurityHeader))[0]
nwk_nonce = struct.pack('Q',ext_source) + struct.pack('I',f['fc']) + nwk_sec_ctrl_byte

nwk_crop_size = 4 + 2 + len(pkt.getlayer(ZigbeeSecurityHeader).fields['data'])  # The length of the encrypted data, mic and FCS

# the Security Control Field flags have to be adjusted before this is calculated, so we store their original values so we can reset them later
zigbeeData = pkt.getlayer(ZigbeeNWK).do_build()
zigbeeData = zigbeeData[:-nwk_crop_size]

(nwk_payload, nwk_micCheck) = zigbee_crypt.decrypt_ccm(nkey, nwk_nonce, nwk_mic, nwk_encrypted, zigbeeData)
Другие вопросы по тегам