本文目录导读:

我来详细介绍使用Scapy构造和发送网络数据包的方法。
安装 Scapy
pip install scapy # 或 pip3 install scapy
基础数据包构造
最简单的数据包
from scapy.all import * # 创建一个IP数据包 pkt = IP(dst="192.168.1.1") print(pkt.show())
常用协议层
# Ethernet层 Ether(dst="ff:ff:ff:ff:ff:ff", src="00:11:22:33:44:55") # IP层 IP(src="192.168.1.100", dst="8.8.8.8") # TCP层 TCP(sport=12345, dport=80, flags="S") # SYN包 # UDP层 UDP(sport=12345, dport=53) # ICMP层 ICMP(type=8) # Echo Request (ping)
构造各类数据包
Ping (ICMP Echo) 数据包
from scapy.all import *
# 构造ping包
ping_pkt = IP(dst="8.8.8.8")/ICMP()
# 发送并等待响应
response = sr1(ping_pkt, timeout=2)
if response:
response.show()
TCP SYN 扫描包
# SYN扫描包
syn_pkt = IP(dst="192.168.1.1")/TCP(dport=80, flags="S")
response = sr1(syn_pkt, timeout=1)
if response:
if response.haslayer(TCP) and response[TCP].flags == 18: # SYN-ACK
print("端口开放")
elif response.haslayer(TCP) and response[TCP].flags == 20: # RST
print("端口关闭")
DNS 查询包
# DNS查询包
dns_pkt = IP(dst="8.8.8.8")/UDP(dport=53)/DNS(rd=1, qd=DNSQR(qname="www.google.com"))
response = sr1(dns_pkt, timeout=2)
if response and response.haslayer(DNS):
print(response[DNS].an.rdata)
ARP 请求包
# ARP请求
arp_pkt = ARP(pdst="192.168.1.1")
response = sr1(arp_pkt, timeout=2)
if response:
print(f"MAC地址: {response.hwsrc}")
发送数据包的方法
基本发送函数
from scapy.all import * # sr(): 发送第3层(IP)数据包并接收响应 response = sr(IP(dst="192.168.1.1")/ICMP(), timeout=2) # sr1(): 发送并只接收第一个响应 response = sr1(IP(dst="192.168.1.1")/ICMP(), timeout=2) # srp(): 发送第2层(Ethernet)数据包 response = srp(Ether(dst="ff:ff:ff:ff:ff:ff")/ARP(pdst="192.168.1.0/24"), timeout=2) # send(): 发送第3层数据包,不等待响应 send(IP(dst="192.168.1.1")/ICMP()) # sendp(): 发送第2层数据包,不等待响应 sendp(Ether()/IP(dst="192.168.1.1")/ICMP())
高级发送选项
# 循环发送 send(IP(dst="192.168.1.1")/ICMP(), loop=1, inter=0.5) # 每0.5秒发送一次 # 发送多包 packets = [IP(dst="192.168.1.1")/ICMP() for _ in range(10)] send(packets) # 设置超时和重试 response = sr1(IP(dst="8.8.8.8")/ICMP(), timeout=3, retry=2)
实际应用示例
简单的端口扫描器
from scapy.all import *
def port_scan(target, ports):
for port in ports:
syn_pkt = IP(dst=target)/TCP(dport=port, flags="S")
response = sr1(syn_pkt, timeout=1, verbose=False)
if response is None:
print(f"端口 {port}: 过滤")
elif response.haslayer(TCP):
if response[TCP].flags == 0x12: # SYN-ACK
print(f"端口 {port}: 开放")
# 发送RST关闭连接
rst_pkt = IP(dst=target)/TCP(sport=response[TCP].dport,
dport=port, flags="R")
send(rst_pkt, verbose=False)
elif response[TCP].flags == 0x14: # RST
print(f"端口 {port}: 关闭")
# 使用示例
port_scan("192.168.1.1", [80, 443, 8080])
自定义HTTP请求
from scapy.all import *
# 构造HTTP GET请求
http_request = (
IP(dst="example.com")/
TCP(sport=RandShort(), dport=80, flags="S")/
Raw(load="GET / HTTP/1.1\r\nHost: example.com\r\n\r\n")
)
# 三次握手
syn = IP(dst="example.com")/TCP(sport=RandShort(), dport=80, flags="S")
syn_ack = sr1(syn, timeout=2)
if syn_ack and syn_ack.haslayer(TCP) and syn_ack[TCP].flags == 0x12:
# 发送ACK和HTTP请求
ack = IP(dst="example.com")/TCP(sport=syn_ack[TCP].dport,
dport=80, flags="A",
seq=syn_ack[TCP].ack, ack=syn_ack[TCP].seq+1)
send(ack)
http_request[TCP].seq = syn_ack[TCP].ack
http_request[TCP].ack = syn_ack[TCP].seq + 1
response = sr1(http_request, timeout=2)
if response:
print(response.show())
注意事项
# 需要root/管理员权限 # 在Linux上:sudo python script.py # Linux可能需要允许IP转发 # sysctl -w net.ipv4.ip_forward=1 # Windows可能需要安装Npcap/WinPcap # 下载地址:https://npcap.com/
调试技巧
# 查看数据包结构
pkt = IP(dst="192.168.1.1")/ICMP()
pkt.show() # 显示详细信息
pkt.summary() # 显示摘要
# 保存数据包到文件
wrpcap("packets.pcap", pkt)
# 从文件读取数据包
packets = rdpcap("packets.pcap")
这些是Scapy构造和发送数据包的基本方法,根据你的具体需求,可以组合不同的协议层来构造各种网络数据包。
标签: 数据包构造
版权声明:除非特别标注,否则均为本站原创文章,转载时请以链接形式注明文章出处。