从scapy中更改src/dst的pcap发送数据包

Jas*_*art 19 python scapy pcap

我试图用scapy发送以前记录的流量(以pcap格式捕获).目前我被困在剥离原始的Ether层.流量是在另一台主机上捕获的,我基本上需要更改IP和Ether层src和dst.我设法替换IP层并重新计算校验和,但以太层给我带来了麻烦.

任何人都有经验重新发送来自捕获文件的数据包,并对IP和以太层(src和dst)应用了更改?此外,捕获相当大的Gb,如此具有这样的流量的scapy性能?

Abd*_*man 26

检查这个例子

from scapy.all import *
from scapy.utils import rdpcap

pkts=rdpcap("FileName.pcap")  # could be used like this rdpcap("filename",500) fetches first 500 pkts
for pkt in pkts:
     pkt[Ether].src= new_src_mac  # i.e new_src_mac="00:11:22:33:44:55"
     pkt[Ether].dst= new_dst_mac
     pkt[IP].src= new_src_ip # i.e new_src_ip="255.255.255.255"
     pkt[IP].dst= new_dst_ip
     sendp(pkt) #sending packet at layer 2
Run Code Online (Sandbox Code Playgroud)

评论:

  • 使用rdpcap,wrpcap scapy方法从pcap格式化文件中读写
  • 您可以使用sniff(offline="filename")读取数据包,sniff(offline="filename",prn=My_Function)在这种情况下您可以使用这样的prn 参数My_Functions将应用于每个pkt嗅探
  • 编写新ip或mac的正确方法是将其视为字符串ex:ip="1.1.1.1"等等,如上图所示.
  • 在示例中:for循环中包含的sendp方法比使其他循环发送数据包慢
  • 性能提示:在python中使用for循环太慢使用map而不是你想要像C中的for循环那样的速度,参考
  • 上面使用的rdpcap立即读取文件,如果读取时可用的内存为1.5 Gb,而您正在读取2,3,... Gb文件则会失败.
  • 如果性能问题对你来说至关重要,你可以使用winpcap,但你必须在C中编写更复杂的代码;使用python/scapy执行相同的任务非常简单,但它并不比c快
  • 它取决于在所需性能水平上使用哪一个
  • 如果我的猜测是正确的,你发送视频流数据包,在这种情况下我会使用winpcap,如果我发送1百万像素视频或scapy在其他情况下(每帧较小)
  • 在使用C/winpcap的情况下,您将获得读取pcaps并更改数据并重新发送的出色性能,但您必须知道同样的问题(大文件)您必须创建具有适当大小的缓冲区才能使用它阅读以相当高的性能发送数据包
  • 如果数据包大小是恒定的(在大多数情况下这是罕见的,我猜)你可能有一个优势,可以获得大部分可用内存
  • 如果你想在整个"项目/程序"中使用python/scapy,你可以在C/Wincap中创建高性能函数并编译为dll然后你可以将这个dll导入你的python程序,你可以在python程序中使用它.通过这种方式,您可以获得精彩简单的python/Scapy的优势,并且您只需在c中编写特定的功能,这样您就可以更快地完成工作,并且您的代码可以集中精力和可维护

  • 感谢 Abdurahman 的提示,尤其是有关性能问题的提示!Scapy 是一个不错的工具,但可能不适合大流量模拟(至少“开箱即用”)。 (2认同)

Pie*_*rre 6

如果我是你,我会让Scapy处理该Ether层,并使用该send()功能.例如:

ip_map = {"1.2.3.4": "10.0.0.1", "1.2.3.5": "10.0.0.2"}
for p in PcapReader("filename.cap"):
    if IP not in p:
        continue
    p = p[IP]
    # if you want to use a constant map, only let the following line
    p.src = "10.0.0.1"
    p.dst = "10.0.0.2"
    # if you want to use the original src/dst if you don't find it in ip_map
    p.src = ip_map.get(p.src, p.src)
    p.dst = ip_map.get(p.dst, p.dst)
    # if you want to drop the packet if you don't find both src and dst in ip_map
    if p.src not in ip_map or p.dst not in ip_map:
        continue
    p.src = ip_map[p.src]
    p.dst = ip_map[p.dst]
    # as suggested by @AliA, we need to let Scapy compute the correct checksum
    del(p.chksum)
    # then send the packet
    send(p)
Run Code Online (Sandbox Code Playgroud)

  • 为我工作,我得到的唯一问题是错误的IP校验和,通过在发送之前添加del p.chksum可以轻松修复(p) (3认同)

Jas*_*art 5

好吧,有了scapy,我想出了以下内容(抱歉我的Python).希望它会帮助某人.有一种可能更简单的方案,其中来自pcap文件的所有数据包都被读入内存,但这可能会导致大型捕获文件出现问题.

from scapy.all import *
global src_ip, dst_ip
src_ip = 1.1.1.1
dst_ip = 2.2.2.2
infile = "dump.pcap"

try:
    my_reader = PcapReader(infile)
    my_send(my_reader)
except IOError:
    print "Failed reading file %s contents" % infile
    sys.exit(1)

def my_send(rd, count=100):
    pkt_cnt = 0
    p_out = []

    for p in rd:
        pkt_cnt += 1
        np = p.payload
        np[IP].dst = dst_ip
        np[IP].src = src_ip
        del np[IP].chksum
        p_out.append(np)
        if pkt_cnt % count == 0:
            send(PacketList(p_out))
            p_out = []

    # Send remaining in final batch
    send(PacketList(p_out))
    print "Total packets sent %d" % pkt_cn
Run Code Online (Sandbox Code Playgroud)