You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Scapy提取TCP负载遇NoneType异常及AttributeError问题排查

Scapy提取TCP负载时触发NoneType异常的问题分析

问题场景

我最近尝试用Scapy提取TCP报文的单个字符负载,但处理前两个报文后就持续触发NoneType异常。我的代码是这样的:

from scapy.all import *
import base64
capture = rdpcap('Data.pcapng') # pcap file
output = open('output.bin','wb') # save dumped data to output.bin
for packet in capture:
    # if packet is ICMP and type is 8 (echo request)
    if packet[TCP].src == '172.16.139.128':
        output.write(packet[TCP].payload) # write packet data to output.bin

触发的异常信息:

Traceback (most recent call last):
  File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/scapy/packet.py", line 372, in __getattr__
    fld, v = self.getfield_and_val(attr)
TypeError: cannot unpack non-iterable NoneType object
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
  File "exploit.py", line 10, in <module>
    if packet[TCP].src == '172.16.139.128':
  File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/scapy/packet.py", line 374, in __getattr__
    return self.payload.__getattr__(attr)
  File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/scapy/packet.py", line 372, in __getattr__
    fld, v = self.getfield_and_val(attr)
  File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/scapy/packet.py", line 1600, in getfield_and_val
    raise AttributeError(attr)
AttributeError: src

想搞清楚这个异常的成因,而且预期应该能输出更多内容。


异常成因分析

你这代码其实踩了两个关键的坑:

  1. 没做协议存在性检查:pcap文件里肯定不是所有报文都是TCP包,可能混着ARP、ICMP或者其他协议的包。你直接用packet[TCP]访问TCP层,遇到非TCP包时这个调用会返回None,后续再访问.src自然就会触发NoneType相关的异常。
  2. 属性搞混了协议层:TCP层根本没有src这个属性啊!src是IP层的属性,用来表示源IP地址;TCP层对应的是源端口sport和目的端口dport。你把IP层的属性放到TCP层上调用,不出错才怪。

修复后的代码

针对这两个问题,我调整了代码,不仅解决了异常,还满足你提取单个字符负载的需求:

from scapy.all import *

capture = rdpcap('Data.pcapng')
output = open('output.bin', 'wb')

for packet in capture:
    # 先确认报文同时包含IP和TCP层,避免访问不存在的协议
    if IP in packet and TCP in packet:
        # 从IP层获取源IP地址,这才是正确的姿势
        if packet[IP].src == '172.16.139.128':
            # 先检查TCP有没有负载,避免写入空数据
            if packet[TCP].payload:
                # 提取负载的第一个字节(单个字符)写入文件
                output.write(bytes(packet[TCP].payload)[:1])

# 记得关闭文件,避免数据丢失
output.close()

关键修改点说明

  • 协议存在性校验:用IP in packet和TCP in packet过滤掉不符合要求的报文,确保只处理有IP和TCP层的包。
  • 修正源IP的获取层:把packet[TCP].src改成packet[IP].src,这才是获取源IP的正确方式。
  • 负载非空检查:增加if packet[TCP].payload判断,避免TCP没有负载时写入空内容。
  • 提取单个字符:通过bytes(packet[TCP].payload)[:1]截取负载的第一个字节,满足你提取单个字符的需求。

内容的提问来源于stack exchange,提问作者flowermia

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.11 08:04:13