我正在使用名为scapy的scapy-com(一个Python数据包操作工具)的分支。这实现了802.15.4和Zigbee解析/操作,以及其他协议。
在网络级安全标头中找到了Zigbee protcol的怪癖。最初,安全级别(定义消息完整性代码的加密和长度)已正确设置,但在发送之前设置为0(无加密)。来自规范:
安全控制字段的安全级别子字段应为 被3位全零字符串'000'覆盖。
规范可以是found here。相关部分是“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的问题是我不知道该怎么做。
2的问题是我有一些想法,但无法让它工作 - 我无法弄清楚如何在数据包加载后调用解剖。调用 pkt.dissect(pkt)似乎不起作用,看起来很奇怪。
这里最好的或推荐的解决方案是什么?
答案 0 :(得分:2)
Fixing scapy sounds right solution. scapy-com is quite old. Zigbee specific code in scapy-com is 1244 lines of code, which in large part are enumerations and field lists. So, it should not be too hard to migrate it to scapy-python3. If you would assist in migrating it to scapy-python3 http://github.com/phaethon/scapy , I could help with fixing the issue.
答案 1 :(得分:1)
您所指的项目是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)