欢迎关注个人公号:运维开发故事

什么 是scapy

Scapy是功能强大的交互式数据包处理程序。它能够伪造或解码各种协议的数据包,在线发送,捕获,匹配请求和响应等。它可以轻松处理大多数经典任务,例如扫描,跟踪路由,探测,单元测试,***或网络发现,它可以代替hping,arpspoof,arp-sk,arping,p0f甚至Nmap,tcpdump和tshark的某些部分。。它在其他工具无法处理的许多其他特定任务上也表现出色,例如发送无效帧,组合技术(VLAN跳变+ ARP缓存中毒,WEP加密通道上的VOIP解码等等)

安装scapy

直接pip安装即可,我使用的是python3

pip3 install scapy

scapy基本使用

输入scapy回车进入scapy的shell
可以使用ls()来查看scapy支持的协议

使用lsc()查看scapy支持的函数

还可以使用ls()获取协议包含的参数

发送和接收数据包

send

- 在第3层发送数据包(Scapy创建第2层标头),不接收任何数据包。

  • loop 参数默认为0,如果它的值不是0,那么数据包将一直循环发送,直到按CTRL-C为止。
  • count 可用于设置要发送的数据包的确切数量。
  • inter 可用于设置每个数据包之间的秒数。

    >>> send(IP(dst='8.8.8.8')/TCP(dport=53, flags='S')).Sent 1 packets.>>> >>> send(IP(dst='8.8.8.8')/TCP(dport=53, flags='S'), count=10)..........Sent 10 packets.>>>>>> send(IP(dst='8.8.8.8')/TCP(dport=53, flags='S'), loop=1)......................... [... snipped ...]Sent 1503 packets.

    sendp

  • 与send()相同,但在第2层发送数据包(必须提供第2层标头),不接收任何数据包。
  • 使用iface到设置界面上发送数据包。(如果未设置,将使用conf.iface的值)
    >>> sendp(Ether()/IP(dst="1.2.3.4",ttl=(1,4)), iface="eth0")....Sent 4 packets.

sendp("I’m travelling on Ethernet", iface="eth0", loop=1, inter=0.2)

sendp(rdpcap("/tmp/pcapfile")) # tcpreplay
...........
Sent 11 packets.

#### sr
  • 发送数据包并接收响应。
  • sr()返回两个列表,第一个列表包含响应的,第二个列表包含未响应的。

    >>> sr(IP(dst="60.205.177.168")/TCP(dport=[21,22,23]))Begin emission:Finished sending 3 packets....**...............................^CReceived 36 packets, got 2 answers, remaining 1 packets(<Results: TCP:2 UDP:0 ICMP:0 Other:0>,<Unanswered: TCP:1 UDP:0 ICMP:0 Other:0>)>>> ans,unans=_>>> unans.summary()IP / TCP 172.17.51.80:ftp_data > 60.205.177.168:telnet S>>> ans[0](<IP  frag=0 proto=tcp dst=60.205.177.168 |<TCP  dport=ftp |>>,<IP  version=4 ihl=5 tos=0x0 len=40 id=53978 flags=DF frag=0 ttl=64 proto=tcp chksum=0x9a1e src=60.205.177.168 dst=172.17.51.80 |<TCP  sport=ftp dport=ftp_data seq=0 ack=1 dataofs=5 reserved=0 flags=RA window=0 chksum=0xe1cf urgptr=0 |>>)>>> ans[0][0]<IP  frag=0 proto=tcp dst=60.205.177.168 |<TCP  dport=ftp |>>

    sr1

  • 发送所有数据包并仅记录第一个响应。

    >>> p=sr1(IP(dst="www.baidu.com")/ICMP()/"asdqwe")Begin emission:Finished sending 1 packets..*Received 2 packets, got 1 answers, remaining 0 packets

    srloop

  • 循环发送,接收响应并显示响应。
  • 该函数返回几个数据包和响应,以及未响应的。

    >>> packet = IP(dst='60.205.177.168')/ICMP()>>> srloop(packet)RECV 1: IP / ICMP 60.205.177.168 > 172.17.51.80 echo-reply 0RECV 1: IP / ICMP 60.205.177.168 > 172.17.51.80 echo-reply 0RECV 1: IP / ICMP 60.205.177.168 > 172.17.51.80 echo-reply 0RECV 1: IP / ICMP 60.205.177.168 > 172.17.51.80 echo-reply 0^C        Sent 4 packets, received 4 packets. 100.0% hits.(<Results: TCP:0 UDP:0 ICMP:9 Other:0>,<PacketList: TCP:0 UDP:0 ICMP:0 Other:0>)

    使用Scapy创建数据包

  • Scapy数据包的创建与网络中的分层方法一致。
  • 数据包的基本构建块是一层,而整个数据包则是通过将各个层堆叠在一起而构建的。
  • scapy通过在TCP / IP的不同层上为每个协议定义数据包头,然后按顺序堆叠这些层,来构造数据包。

    在一行中创建数据包

    >>> packet = Ether()/IP(dst='8.8.8.8')/TCP(dport=53,flags='S')

    分别创建每个图层并使用'/'运算符将它们堆叠

    >>> l2 = Ether()>>> l3 = IP(dst='8.8.8.8/30')>>> l4 = TCP(dport=53, flags = 'S')>>> packet = l2/l3/l4

    Scapy IP表示法

    Scapy接受普通的IP表示法,CIDR表示法,主机名。

    >>> packet = IP(dst = '8.8.8.8')>>> packet = IP(dst = 'scanme.nmap.org')>>> packet = IP(dst = '8.8.8.8/30')>>> [a for a in packet][<IP  dst=8.8.8.8 |>, <IP  dst=8.8.8.9 |>, <IP  dst=8.8.8.10 |>, <IP  dst=8.8.8.11 |>]>>> packet = IP(dst = 'egadz.metasploit.com/30')

    创建一组数据包

我们可以使用Scapy创建一组数据包

>>> pkts = IP(ttl=[1,3,5,(7,10)])/TCP()>>> [pkt for pkt in pkts][<IP  frag=0 ttl=1 proto=tcp |<TCP  |>>, <IP  frag=0 ttl=3 proto=tcp |<TCP  |>>, <IP  frag=0 ttl=5 proto=tcp |<TCP  |>>, <IP  frag=0 ttl=7 proto=tcp |<TCP  |>>, <IP  frag=0 ttl=8 proto=tcp |<TCP  |>>, <IP  frag=0 ttl=9 proto=tcp |<TCP  |>>, <IP  frag=0 ttl=10 proto=tcp |<TCP  |>>] >>> packet=IP(dst="192.168.*.1-10")/TCP(dport=(0,100)) >>> [a for a in packet][<IP  frag=0 proto=tcp dst=192.168.1.1 |<TCP  dport=0 |>>, <IP  frag=0 proto=tcp dst=192.168.1.1 |<TCP  dport=tcpmux |>>, <IP  frag=0 proto=tcp dst=192.168.1.1 |<TCP  dport=compressnet |>>, <IP  frag=0 proto=tcp dst=192.168.1.1 |<TCP  dport=3 |>>, <IP  frag=0 proto=tcp dst=192.168.1.1 |<TCP  dport=4 |>>, <IP  frag=0 proto=tcp dst=192.168.1.1 |<TCP  dport=rje |>>, <IP  frag=0 proto=tcp dst=192.168.1.1 |<TCP  dport=6 |>>, <IP  frag=0 proto=tcp dst=192.168.1.1 |<TCP  dport=echo |>>, <IP  frag=0 proto=tcp dst=192.168.1.1 |<TCP  dport=8 |>>, <IP  frag=0 proto=tcp dst=192.168.1.1 |<TCP  dport=discard |>>, <IP  frag=0 proto=tcp dst=192.168.1.1 |<TCP  dport=10 |>>, <IP  frag=0 proto=tcp dst=192.168.1.1 |<TCP  dport=systat |>>, <IP  frag=0 proto=tcp dst=192.168.1.1 |<TCP  dport=12 |>>, <IP  frag=0 proto=tcp dst=192.168.1.1 |<TCP  dport=daytime |>>, <IP  frag=0 proto=tcp dst=192.168.1.1 |<TCP  dport=14 |>>, <IP  frag=0 proto=tcp dst=192.168.1.1 |<TCP  dport=netstat |>>, <IP  frag=0 proto=tcp dst=192.168.1.1 |<TCP  dport=16 |>>, <IP  frag=0 proto=tcp dst=192.168.1.1 |<TCP  dport=qotd |>>, <IP  frag=0 proto=tcp dst=192.168.1.1 |<TCP  dport=msp |>>, <IP  frag=0 proto=tcp dst=192.168.1.1 |<TCP  dport=chargen |>>, <IP  frag=0 proto=tcp dst=192.168.1.1 |<TCP  dport=ftp_data |>>, <IP  frag=0 proto=tcp dst=192.168.1.1 |<TCP  dport=ftp |>>, <IP  frag=0 proto=tcp dst=192.168.1.1 |<TCP  dport=ssh |>>, <IP  frag=0 proto=tcp dst=192.168.1.1 |<TCP  dport=telnet |>>, <IP  frag=0 proto=tcp dst=192.168.1.1 |<TCP  dport=lmtp |>>, <IP  frag=0 proto=tcp dst=192.168.1.1 |<TCP  dport=smtp |>>, <IP  frag=0 proto=tcp dst=192.168.1.1 |<TCP  dport=26 |>>, <IP  frag=0 proto=tcp dst=192.168.1.1 |<TCP  dport=nsw_fe |>>, <IP  frag=0 proto=tcp dst=192.168.1.1 |<TCP  dport=28 |>>, <IP  frag=0 proto=tcp dst=192.168.1.1 |<TCP  dport=msg_icp |>>, <IP  frag=0 proto=tcp dst=192.168.1.1 |<TCP  dport=30 |>>,

检查数据包

获取数据包的详细说明以及数据类型

>>> packet = IP()/TCP()>>> ls(packet)version    : BitField             = 4               (4)ihl        : BitField             = None            (None)tos        : XByteField           = 0               (0)len        : ShortField           = None            (None)id         : ShortField           = 1               (1)flags      : FlagsField           = 0               (0)frag       : BitField             = 0               (0)ttl        : ByteField            = 64              (64)proto      : ByteEnumField        = 6               (0)chksum     : XShortField          = None            (None)src        : Emph                 = '127.0.0.1'     (None)dst        : Emph                 = '127.0.0.1'     ('127.0.0.1')options    : PacketListField      = []              ([])[-- snipped --]

show

显示详细的包头

>>> packet.show()###[ IP ]###   version= 4  ihl= None  tos= 0x0  len= None  id= 1  flags=   frag= 0  ttl= 64  proto= tcp  chksum= None  src= 127.0.0.1  dst= 127.0.0.1  \options\###[ TCP ]###      sport= ftp_data     dport= http     seq= 0     ack= 0     dataofs= None     reserved= 0     flags= S     window= 8192     chksum= None     urgptr= 0     options= []

show2

与show()类似,但可以组装数据包并计算校验和和IHL(报头长度,最小值是5)。

>>> packet.show2()###[ IP ]###   version= 4  ihl= 5  tos= 0x0  len= 40  id= 1  flags=   frag= 0  ttl= 64  proto= tcp  chksum= 0x7ccd  src= 127.0.0.1  dst= 127.0.0.1  \options\###[ TCP ]###      sport= ftp_data     dport= http     seq= 0     ack= 0     dataofs= 5     reserved= 0     flags= S     window= 8192     chksum= 0x917c     urgptr= 0     options= []

summary

显示数据包的简短的摘要

>>> packet.summary()'IP / TCP 127.0.0.1:ftp_data > 127.0.0.1:http S'

与数据包内部的字段进行交互

>>> Ether(dst="d8:55:a3:fe:80:78")/IP(dst="8.8.8.8")<Ether  dst=d8:55:a3:fe:80:78 type=IPv4 |<IP  dst=8.8.8.8 |>>>>> packet=_>>> packet.dst'd8:55:a3:fe:80:78'>>> packet[IP].dst'8.8.8.8'

检查数据包中是否存在层

haslayer方法

>>> if packet.haslayer(IP):...:     print (packet[IP].dst)...: 8.8.8.8

使用in构造

>>> pkt = IP()/TCP()/DNS()>>> DNS in pktTrue

Scapy的sprintf

  • sprintf()方法是Scapy的强大功能之一,在编写自定义工具时非常方便。
  • sprintf 用数据包中的值填充格式字符串,就像C语言库中的sprintf一样,不同的是这里用数据包中的字段值填充格式字符串。

    >>> packet.sprintf("Ethernet source is %Ether.src% and IP proto is %IP.proto%")'Ethernet source is 00:16:3e:0c:d1:ad and IP proto is tcp'>>> a.sprintf("%dst% %IP.dst% vlan=%Dot1Q.vlan%")'00:00:d4:ae:3f:71 192.168.0.1 vlan=42'>>>>>>a.sprintf(" %TCP.flags% | %5s,TCP.flags% | %#05xr,TCP.flags%")' RA | RA    | 0x014'

    数据包处理程序

    我们可以使用lambda函数编写处理TCP数据包的数据包处理程序,但该功能仅适用于TCP数据包。

    >>>  f=lambda x:x.sprintf("%IP.dst%:%TCP.dport%")>>> f(IP(dst="8.8.8.8")/TCP())'8.8.8.8:http'>>> f(IP(dst="8.8.8.8")/UDP())'8.8.8.8:??'

    还可以使用sprintf()中的条件子字符串来实现处理其它层的目的。条件子字符串仅在数据包中存在某个层时才触发,否则将被忽略。还可以!用于检查是否缺少图层。
    条件子字符串格式:  {[!]层:子字符串}

    >>> f=lambda x: x.sprintf("=> {IP:ip=%IP.dst% {UDP:dport=%UDP.dport%}\...: ... {TCP:%TCP.dport%/%TCP.flags%}{ICMP:type=%r,ICMP.type%}}\...: ... {!IP:not an IP packet}")>>> f(IP()/TCP())'=> ip=127.0.0.1 http/S'>>> f(IP()/UDP())'=> ip=127.0.0.1 dport=domain'>>> f(IP()/ICMP())'=> ip=127.0.0.1 type=8'>>> f(Ether()/ARP())'=> not an IP packet'

    导入与导出数据

    PCAP格式

    从PCAP文件导入数据包。

    pkts = rdpcap("temp.cap")pkts = sniff(offline="temp.cap")

    将数据包导出到pcap文件。

    wrpcap("temp.cap",pkts)

    十六进制转储格式

  • Scapy允许以各种十六进制格式导出数据包。
  • 使用hexdump()函数使用hexdump格式显示一个或多个数据包:

    >>> hexdump(s)0000  D8 55 A3 FE 80 78 00 16 3E 0C D1 AD 08 00 45 00  .U...x..>.....E.0010  00 28 00 01 00 00 40 06 8B 5E AC 11 33 50 08 08  .(....@..^..3P..0020  08 08 00 14 00 50 00 00 00 00 00 00 00 00 50 02  .....P........P.0030  20 00 A0 0D 00 00       

    十六进制字符串

    还可以使用str()函数将整个数据包转换为十六进制字符串

    >>> s<Ether  dst=d8:55:a3:fe:80:78 type=IPv4 |<IP  frag=0 proto=tcp dst=8.8.8.8 |<TCP  dport=http |>>>>>> str(s)WARNING: Calling str(pkt) on Python 3 makes no sense!"b'\\xd8U\\xa3\\xfe\\x80x\\x00\\x16>\\x0c\\xd1\\xad\\x08\\x00E\\x00\\x00(\\x00\\x01\\x00\\x00@\\x06\\x8b^\\xac\\x113P\\x08\\x08\\x08\\x08\\x00\\x14\\x00P\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00P\\x02 \\x00\\xa0\\r\\x00\\x00'"

    Base64

  • Scapy可以使用export_object()函数导出数据包的base64编码数据。

    >>> export_object(s)b'eNprYEouTk4sqNTLSaxMLSrWyzHici3JSC3iKmTQDCpk1EiOT85PSU0u5krNAzG4Cpki7BkYGA7PCD20+PC+Qw0VDGJ2PIcnHlrLweDKwKDBwMjA4MB2qDvu0BpB4wAOIGAQYQhggIIAJgWGQwt4GRgKmSPYgPycxJLMPMNClrZC1qBCNnfHGxoeDcsdkv2AoKSQPUkPALURLMU='>>> new_pkt = import_object

    嗅探

    Sniff()

  • sniff()函数可帮助我们捕获所有流量:
  • 包括countfilterifacelfilterprntimeout选项。

    >>> sniff(count=4, iface='eth0')<Sniffed: TCP:1 UDP:3 ICMP:0 Other:0>

    可以添加过滤以捕获需要的数据包,使用标准的tcpdump / libpcap语法:

    >>> pkts = sniff(count=1,filter="tcp and host 60.205.177.168 and port 80")>>> pkts.summary()Ether / IP / TCP 172.17.51.80:54578 > 60.205.177.168:http S
  • 可以做类似tcpdump的简单流量分析器

    >>>  pkts = sniff(count=5,filter="host 60.205.177.168",prn=lambda x:x.summary())Ether / IP / TCP 172.17.51.80:54624 > 60.205.177.168:http SEther / IP / TCP 60.205.177.168:54624 > 172.17.51.80:http SEther / IP / TCP 172.17.51.80:http > 60.205.177.168:54624 SAEther / IP / TCP 60.205.177.168:http > 172.17.51.80:54624 SAEther / IP / TCP 172.17.51.80:54624 > 60.205.177.168:http A
  • 也可以从pcap文件中嗅探数据包。
    pkts = sniff(offline='test.pcap')>>> pkts.nsummary()0000 Ether / IP / TCP 172.16.16.128:1606 > 74.125.95.104:http S0001 Ether / IP / TCP 74.125.95.104:http > 172.16.16.128:1606 SA0002 Ether / IP / TCP 172.16.16.128:1606 > 74.125.95.104:http A0003 Ether / IP / TCP 172.16.16.128:1606 > 74.125.95.104:http PA / Raw0004 Ether / IP / TCP 74.125.95.104:http > 172.16.16.128:1606 A / Padding>>> sniff(offline='test.pcap', lfilter = lambda s: s[TCP].flags == 18, prn = lambda x: x[IP].dst)192.168.1.1<Sniffed: TCP:1 UDP:0 ICMP:0 Other:0>

©著作权归作者所有:来自51CTO博客作者cxf210210的原创作品,如需转载,请注明出处,否则将追究法律责任

每一份赞赏源于懂得

赞赏

0人进行了赞赏支持

更多相关文章

  1. 猎鹰与龙飞船基于Linux,采用C++、Chromium与JS开发
  2. 210427 PHP 运算符 流程控制 字符串定义 定界符 require/include
  3. 【每周一库】 simsearch - a simple and lightweight fuzzy
  4. 模拟实现字符串函数及内存函数
  5. 20210508 字符串的格式化输出
  6. PHP:字符串系统函数,ASCII字符集转换,url解析函数,字符串散列处
  7. php之字符串实战注册页面
  8. 从入门到入土(三)RocketMQ 怎么保证的消息不丢失?
  9. 【php基础入门】小白整理PHP常用的字符串函数使用总结分析(推荐)

随机推荐

  1. Android(安卓)中sp、dp、px转换,以及获取
  2. 2011.06.21(2)——— android invalidate
  3. android 长按power键弹出对话框
  4. Android(安卓)Action静态广播收不到(系统
  5. android NoSuchMethodError getDrawable
  6. Android(安卓)简单实现自定义进度条
  7. 如何修改应用兼容Android 3.0系统
  8. Android安装和删除(卸载)应用软件程序(ap
  9. Android(安卓)Q 接入 MQTT
  10. android 扫描SD卡与系统文件(转)