使用 Scapy 缩短 TCP 负载会导致 [TCP Previous segment not captured]

Shortening TCP payload with Scapy results in [TCP Previous segment not captured]

我正在尝试通过剥离一些字节来修改 TCP 负载。

只要将字节替换为相同长度的其他字节而不是剥离它们,修改包就可以正常工作。

如果删除了字节,Wireshark 会在转储中显示 [未捕获 TCP 前一段] 消息。

我删除了修改包的校验和和包长度,以便Scapy在发送包时重新计算所有这些:

# Delete the old checksums
del packet_mod[IP].chksum
del packet_mod[TCP].chksum

# Delete the old packet length
del packet_mod[IP].len

如果我在修改后的数据包末尾也切断 len(stripped_bytes) ,则修改有效,因为接收方将重新发送的 TCP 段添加到修改后的数据包中。

例如:我去掉了 20 个字节的 TCP 负载。如果我在有效负载末尾还切断了额外的 20 个字节,那么修改才有效。

我错过了什么?

我不明白这部分是什么意思:

E.g.: I strip out 20 bytes of the TCP payload. The modification then only works, if I also cut off an additional 20 bytes at the end of the payload.

无论如何,你缺少的是每个 TCP 段携带 一个 TCP header 字段——“序列号”字段——表示 该段的数据内容在字节流中的位置 正在通过 TCP 传输。

TCP 接收方使用段序列号和段长度 (段长度是根据 IP 数据报的长度计算的 交付段)以构建连续的字节流 收到的流量。例如,如果接收方之前有 收集到序列位置 200 和下一个传入的所有数据 细分如下所示:

  (segment 1) sequence=200 length=80 data='data data data ...'
  (segment 2) sequence=280 length=60 data='more data ...'
  (segment 3) sequence=340 length=70 data='even more data ...'

然后接收器知道它现在已经收集了所有数据 直到(但不包括)位置 410。由于没有间隙, 此数据已准备好传递给应用程序。

请注意,段号 (1)、(2)、(3) 出现在 TCP header。这些数字只是为了让这个描述 可以参考一下。

显然,如果段 (2) 已经丢失并且接收方只 收集片段 (1) 和 (3) 那么接收者就会知道 接收到的数据有差距。它会确切地知道 那个差距在哪里:它从位置 280 开始丢失了 60 个字节。 TCP 承诺传送完整的 in-order 数据流,所以直到 那个缺口被填补了,接收方不允许交付任何 后来的字节(比如它在段中得到的位置 340 的 70 个字节 3)申请。如果丢失的字节没有很快到达 然后接收者会告诉发送者关于差距和发送者 将重新传输丢失的数据。

这就是为什么从 TCP 段中删除字节会导致问题。如果 您的程序从段 (2) 中删除了 20 个字节,然后接收方 会看到这个:

  (segment 1) sequence=200 length=80 data='data data data ...'
  (segment 2) sequence=280 length=40 data='more data ...'
  (segment 3) sequence=340 length=70 data='even more data ...'

并且接收方会得出结论,它发现了一个差距 位置 320 处的 20 个字节。

如果 Wireshark 正在观察此流量,那么它会得出相同的结论。 TCP 接收方和 Wireshark 都不知道 缺少的字节是段 (2) 已被编辑。 Wireshark 的最 合理的猜测是丢失的字节在一个段中 不知何故无法进行检查,这就是为什么 显示“前一段未捕获”消息。它说“以前” 因为它在检查之前不会发现有差距 段 (3),然后是间隙之后的一段。

接收方将以与处理任何 差距。它会告诉发件人有关间隙并等待丢失 要重传的数据。如果接收方得到丢失的数据 然后它将填补空白,然后照常继续。如果你 继续拦截重传并删除丢失的字节 然后接收者将继续报告它有一个间隙,并且 发件人最终会厌倦重新传输丢失的数据 它将放弃 TCP 连接。

这意味着您不能简单地从 in-flight TCP 段中删除数据 并期望 TCP 不会注意到数据已经丢失。原则上你 可以通过删除一些数据然后操纵序列来做到这一点 来自发件人的所有后续段中的编号 and 在所有 接收方发送的确认,但这是一项更大的任务。

参考:描述了基本的TCP序列号机制 在 RFC 793 和长期 使用序列号提高安全性的最佳实践是 RFC 1948 和 在 RFC 6528.

中正式成为标准