为了帮助学生知道从何开始,我们提供了一个示范程序。该程序捕获所有 TCP 数据包,并对从 A 到 B 的数据包进行一些修改(修改部分并未展示,因为这是任务的一部分)。对于从 B 到 A 的数据包,程序不做任何更改。
#!/usr/bin/env python3
from scapy.all import *

IP_A = "10.9.0.5"
MAC_A = "02:42:0a:09:00:05"
IP_B = "10.9.0.6"
MAC_B = "02:42:0a:09:00:06"

def spoof_pkt(pkt):
    if pkt[IP].src == IP_A and pkt[IP].dst == IP_B:
         # 根据捕获的数据包创建一个新的数据包。
         # 1) 我们需要删除 IP 和 TCP 头部的校验和,
         #    因为我们的修改会使它们无效。
         #    Scapy 会在这些字段缺失时重新计算它们。
         # 2) 我们还删除了原始的 TCP 有效载荷。

         newpkt = IP(bytes(pkt[IP]))
         del(newpkt.chksum)
         del(newpkt[TCP].payload)
         del(newpkt[TCP].chksum)

         #################################################################
         # 根据旧的有效载荷构建新的有效载荷。
         # 学生需要实现这部分代码。

         if pkt[TCP].payload:
             data = pkt[TCP].payload.load  # 原始的有效载荷数据
             newdata = data   # 在此示例代码中未做更改

             send(newpkt/newdata)
         else:
             send(newpkt)
         ################################################################

    elif pkt[IP].src == IP_B and pkt[IP].dst == IP_A:
         # 根据捕获的数据包创建一个新的数据包
         # 不进行任何修改。

         newpkt = IP(bytes(pkt[IP]))
         del(newpkt.chksum)
         del(newpkt[TCP].chksum)
         send(newpkt)

f = 'tcp'
pkt = sniff(iface='eth0', filter=f, prn=spoof_pkt)
需要注意的是,上述代码捕获了所有 TCP 数据包,包括由程序本身生成的数据包。这是不可取的,因为它会影响程序的表现。学生需要更改过滤器以确保不捕获自身的数据包。

Telnet 的行为。 在 Telnet 中,在通常情况下,我们每在 Telnet 窗口中键入一个字符就会触发一个单独的 TCP 数据包,但如果输入速度很快,几个字符可能会在一个数据包中被一起发送。这就是为什么在从客户端到服务器端的 Telnet 数据包中,有效载荷通常只包含一个字符。被发送到服务器的字符将由服务器回弹,并在客户端窗口中显示。因此,我们看到客户端窗口中的内容并不是直接的输入结果。无论我们在客户端窗口中输入什么内容,它都需要经过一次往返才能显示。如果网络断开连接,则无论我们在客户端窗口中输入什么内容都不会显示,直到网络恢复。如果攻击者在这个过程中将字符更改为 Z,则 Z 将在 Telnet 客户端窗口中显示出来,尽管你实际并未输入 Z。
最后修改: 2025年05月7日 星期三 08:56