Scapy 获取流量包

  • 0x00 参考
  • 0x01 前言
  • 0x02 概述
  • 0x03 安装
  • 0x04 使用
    • 1. ls()
    • 2. lsc()
    • 3. 嗅探流量
    • 4. 发送数据包
      • 构建数据包
      • 发送数据包
  • 0x05. 嗅探例子

0x00 参考

Scapy官方文档

Gitgub地址

Scapy中文文档(第三方)

python之用scapy分层解析pcap报文

使用python中的scapy库抓取并解析pcap包(五元组信息)

0x01 前言

由于云厂商的链路监控做得实在是不咋地,所以我们决定自己实现一套网络链路监控系统。

目的效果:客户端安装agent,实时采集流量数据并且进行上报给服务器端,不管是HTTP、HTTPS、MySQL,以及底层的TCP、UDP,甚至是链路层的,都需要实时采集并上报。

由于我们团队使用Python的居多,所以第一版以Python为开发语言进行开发。一番调研之下,客户端的agent决定使用Scapy来进行流量的获取

0x02 概述

Scapy是一个强大的,用Python编写的交互式数据包处理程序,它能让用户发送、嗅探、解析,以及伪造网络报文,从而用来侦测、扫描和向网络发动攻击。Scapy可以轻松地处理扫描(scanning)、路由跟踪(tracerouting)、探测(probing)、单元测试(unit tests)、攻击(attacks)和发现网络(network discorvery)之类的传统任务。

它可以代替hping,arpspoof,arp-sk,arping,p0f 甚至是部分的Nmap,tcpdump和tshark 的功能。

支持很多协议,比如ARP,BOOTP,Dot1Q,DHCP,DNS,GRE,HSRP,ICMP,IP, NTP,RIP,SNMP,STP,PPPoE,TCP,TFTP,UDP等,可以通过ls()查看支持的协议

简单的说,Scapy主要做两件事:发送报文和接收回应。

0x03 安装

由于Scapy是Python的模块,所以可以使用pip进行安装

pip install scapy

注意:由于Scapy需要root权限才能发送数据包,所以建议使用root用户进行安装

安装完成可以直接在命令行中输入scapy测试是否安装成功:

>scapy
INFO: Can't import matplotlib. Won't be able to plot.
INFO: Can't import PyX. Won't be able to use psdump() or pdfdump().
WARNING: No libpcap provider available ! pcap won't be used
WARNING: No default IPv4 routes found. Your Windows release may no be supported and you have to enter your routes manually
INFO: No IPv6 support in kernel
INFO: Can't import python-cryptography v1.7+. Disabled WEP decryption/encryption. (Dot11)
INFO: Can't import python-cryptography v1.7+. Disabled IPsec encryption/authentication.
WARNING: IPython not available. Using standard Python shell instead.
AutoCompletion, History are disabled.
WARNING: On Windows, colors are also disabledaSPY//YASaapyyyyCY//YCa       |sY//YSpcs  scpCY//Pp     | Welcome to Scapyayp ayyyyyyySCP//Pp           syY//C    | Version 2.4.4AYAsAYYYYYYYY///Ps              cY//S   |pCCCCY//p          cSSps y//Y   | https://github.com/secdev/scapySPPPP///a          pP///AC//Y   |A//A            cyPC   | Have fun!p///Ac            sC///a   |PYCpc           A//A   | To craft a packet, you have to be ascccccp///pSP///p          p//Y   | packet, and learn how to swim insY/y  caa           S//P   | the wires and in the waves.cayCyayP//Ya              pY/Ya   |        -- Jean-Claude Van DammesY/PsYYCc          aC//Yp    |sc  sccaCY//PCypaapyCP//YSsspCPY//YPSpsccaacs

注意:如果没有安装所有的可选包,Scapy会显示有些功能不能用,如:

INFO: Can't import matplotlib. Won't be able to plot.
INFO: Can't import PyX. Won't be able to use psdump() or pdfdump().
WARNING: No libpcap provider available ! pcap won't be used
WARNING: No default IPv4 routes found. Your Windows release may no be supported and you have to enter your routes manually
INFO: No IPv6 support in kernel
INFO: Can't import python-cryptography v1.7+. Disabled WEP decryption/encryption. (Dot11)
INFO: Can't import python-cryptography v1.7+. Disabled IPsec encryption/authentication.

具体可参考:https://scapy.readthedocs.io/en/latest/installation.html#optional-dependencies

注意:Windows平台需要安装Winpcap才能进行嗅探sniff

0x04 使用

1. ls()

进入scapy后,可用ls()来查看scapy支持的网络协议(由于输出内容太长,只截取部分以供参考)

可以看到耳熟能详的ARP,BOOTP,Dot1Q,DHCP,DNS,GRE,HSRP,ICMP,IP,NTP,RIP,SNMP,STP,PPPoE,TCP,TFTP,UDP等等都支持

注意:这里可以带参考,比如ls(IP)来查看IP包的各种默认参数

2. lsc()

进入scapy后,可以用lsc()来查看scapy的函数集。

比较常用的函数有:

  • arpcachepoison(用于arp毒化攻击,也叫arp欺骗攻击)
  • arping(用于构造一个ARP的who-has包)
  • send (用于发3层报文)
  • sendp(用于发2层报文)
  • sniff(用于网络嗅探,类似Wireshark和tcpdump)
  • sr(发送+接收3层报文)
  • srp(发送+接收2层报文)

比如:(由于输出内容太长,只截取部分以供参考)

3. 嗅探流量

嗅探流量的数据包有两种方式:

  • sniff实时抓包
  • 读取pcap文件

sniff函数如下:

def sniff(count=0, store=1, offline=None, prn=None,filter=None, L2socket=None, timeout=None, opened_socket=None, stop_filter=None, iface=None,*args,**kargs)

参数含义:

  • count:抓包的数量,0表示无限制,如无限制会一直抓取
  • store:保存抓取的数据包到内存或者丢弃,1:保存,0:丢弃
  • offline:从 pcap 文件读取数据包,而不进行嗅探,默认为None
  • prn:为每一个数据包定义一个回调函数,例如:prn = lambda x: x.summary(); ( packct.summar()函数返回的是对包的统计性信息 ),则抓取到每个包之后进行显示统计信息
  • filter:过滤规则,bpf过滤器,可参考:BPF语法,比如filter=‘udp’、filter=‘tcp and ( port 80 or port 443)’、filter="( ip and dst 8.8.8.8) "
  • L2socket:使用给定的 L2socket
  • timeout:在给定的时间后停止嗅探,默认为 None,如果为0或不设置则会一直抓取,如果为3则是抓取此时到3秒之间的流量
  • opened_socket:对指定的对象使用 .recv() 进行读取;
  • stop_filter:定义一个函数,决定在抓到指定数据包后停止抓包,如:stop_filter = lambda x: x.haslayer(TCP);
  • iface:指定抓包的接口,一般服务器的默认网卡是eth0,如果没有指定interface,则会在所有的interface上面进行嗅探

注意:如果不设置count和timeout的话,那么sniff会卡在那里一直运行着,sniff后面的代码是不会运行的,一般是会配合prn回调函数,且store建议设置为0,不保存到内存

保存成pcap

wrpcap('xxx.pcap', package)

读取pcap

rdpcap('xxx.pcap')

比如:

>>> from scapy.all import *
>>> packets = sniff(count=1)  # 获取一个流量数据包
>>> wrpcap('test.pcpp', packets)  # 保存成pcap
>>> pcap_packets = rdpcap('test.pcap')  # 读取pcap文件
>>> pcap_packets
<test.pacp: TCP:1 UDP:0 ICMP:0 Other:0>
>>> pcap_packets[0]
<Ether  dst=50:d2:f5:fd:85:e2 src=d4:6d:6d:1c:93:50 type=IPv4 |<IP  version=4 ihl=5 tos=0x0 len=41 id=17191 fla
gs=DF frag=0 ttl=64 proto=tcp chksum=0x574f src=192.168.31.179 dst=14.215.177.38 |<TCP  sport=2894 dport=https
seq=622811909 ack=621991385 dataofs=5 reserved=0 flags=A window=510 chksum=0x8563 urgptr=0 |<Raw  load='\x00' |
>>> pcap_packets[0].src
'd4:6d:6d:1c:93:50'
>>> pcap_packets[0].dst
'50:d2:f5:fd:85:e2'
>>> pcap_packets[0].show()
###[ Ethernet ]### dst       = 50:d2:f5:fd:85:e2src       = d4:6d:6d:1c:93:50type      = IPv4
###[ IP ]###version   = 4ihl       = 5tos       = 0x0len       = 41id        = 17191flags     = DFfrag      = 0ttl       = 64proto     = tcpchksum    = 0x574fsrc       = 192.168.31.179dst       = 14.215.177.38\options   \
###[ TCP ]###sport     = 2894dport     = httpsseq       = 622811909ack       = 621991385dataofs   = 5reserved  = 0flags     = Awindow    = 510chksum    = 0x8563urgptr    = 0options   = []
###[ Raw ]###load      = '\x00'

package[0]是查看第一个数据包的数据,package[0].show()是查看第一个数据包的详细信息

scapy是按照按照 TCP/IP 四层参考模型显示详细包信息的,即:链路层 [Ethernet]、网络层[IP]、传输层[TCP/UDP]、应用层[RAW]

通过上述输出结果,我们可以看出每个层的数据包有哪些属性可以取出。

这里P代表的是Ethernet层。P.dst (取出dst属性)、P.src (取出src属性)、P.type (取出type属性)
每一层都有一个 payload 属性,可以不断进入下一层。

p.payload:IP层(可用 p.payload.* 取出IP层的属性)
p.payload.payload:TCP/UDP层(可用 p.payload.payload.* 取出TCP/UDP层的属性)
p.payload.payload.payload:RAW层(可用 p.payload.payload.payload.* 取出RAW层的属性)

上面显示的是TCP的请求,下面的UDP的请求:

###[ Ethernet ]### dst       = 14:43:d0:65:ae:a2src       = 88:b8:5d:bd:0d:7ftype      = IPv4
###[ IP ]### version   = 4ihl       = 5tos       = 0x0len       = 40id        = 28350flags     = frag      = 0ttl       = 128proto     = udpchksum    = 0x0src       = 192.168.1.56dst       = 192.144.236.192\options   \
###[ UDP ]### sport     = 59297dport     = ms_wbt_serverlen       = 20chksum    = 0x6f27
###[ Raw ]### load      = '\xae;\xf8\x01\x04\x00\x04\x04\x00\x01\x07\x00'

4. 发送数据包

发送数据包之前需要构建数据包

构建数据包

比如使用IP()就可以创建默认的数据包,也可以使用TCP()创建TCP包、使用UDP()创建UDP包等,具体可以通过ls()查看,使用 ls(IP()) 可以查看IP数据包可以有哪些参数

比如:

>>> ip_package = IP(dst='8.8.8.8')  # 创建目的地址是8.8.8.8的数据包
>>> ip_package.show()  # 查看数据包的信息
###[ IP ]###version   = 4ihl       = Nonetos       = 0x0len       = Noneid        = 1flags     =frag      = 0ttl       = 64proto     = ipchksum    = Nonesrc       = 192.168.31.179dst       = 8.8.8.8\options   \
>>> ip_package.summary()  # 查看数据包的概要信息
'192.168.31.179 > 8.8.8.8 ip'

可以使用 ‘/’ 操作符来给数据包加上一层。比如构造一个TCP数据包,在IP层指明数据包的目的地址。在TCP层可以设定数据包的目的端口等等。UDP数据包同理

比如:

>>> ip_package = IP(dst='8.8.8.8')/TCP(dport=(53)) # 创建目的地址是8.8.8.8的数据包,目的端口为53
>>> ip_package.show()
###[ IP ]###version   = 4ihl       = Nonetos       = 0x0len       = Noneid        = 1flags     =frag      = 0ttl       = 64proto     = tcpchksum    = Nonesrc       = 192.168.31.179dst       = 8.8.8.8\options   \
###[ TCP ]###sport     = ftp_datadport     = (80, 443)seq       = 0ack       = 0dataofs   = Nonereserved  = 0flags     = Swindow    = 8192chksum    = Noneurgptr    = 0options   = []
发送数据包

构造完数据包就可以进行发送,有以下方法:

send(pkt):发送三层数据包,但不会受到返回的结果。
sr(pkt):发送三层数据包,返回两个结果,分别是接收到响应的数据包和未收到响应的数据包。
sr1(pkt):发送三层数据包,仅仅返回接收到响应的数据包。
sendp(pkt):发送二层数据包。
srp(pkt):发送二层数据包,并等待响应。
srp1(pkt):发送第二层数据包,并返回响应的数据包

比如:

>>> ip_package = IP(dst='8.8.8.8')/TCP(dport=(53))
>>> ans, unans = sr(ip_package)
Begin emission:
Finished sending 1 packets.
........*
Received 9 packets, got 1 answers, remaining 0 packets
>>> ans
<Results: TCP:1 UDP:0 ICMP:0 Other:0>
>>> unans
<Unanswered: TCP:0 UDP:0 ICMP:0 Other:0>

具体更多的例子可以查看:https://github.com/wizardforcel/scapy-docs-zh/blob/master/3.md

0x05. 嗅探例子

A. 嗅探单个流量数据包

#coding=utf-8
from scapy.all import *sniff(prn=lambda x: x.show(), count=1)

B. 实时捕获TCP并且端口是80的数据包并且输出每个数据包的信息

#coding=utf-8
from scapy.all import *# 数据包回调函数,显示TCP信息
def packet_callback(packet):if packet[TCP].payload:mail_packet = str(packet[TCP].payload)if "user" in mail_packet.lower() or "pass" in mail_packet.lower():print("[*] Server: %s" % packet[IP].dst)print("[*] %s" % packet[TCP].payload)sniff(filter="tcp port 80", prn=packet_callback, store=0)

输出:

# 使用get请求一下接口:
[*] Server: 172.16.6.173
[*] b'GET /api/v1/flow/flow_map?start_time=2020-10-29%2021:34:16 HTTP/1.1\r\nUser-Agent: PostmanRuntime/7.26.5\r\nAccept: */*\r\nCache-Control: no-cache\r\nPostman-Token: f86343d6-de6f-4242-a7b3-cda13b325636\r\nHost: clue.tdevops.svc.com\r\nAccept-Encoding: gzip, deflate, br\r\nConnection: keep-alive\r\n\r\n'# 使用post请求一下接口:
[*] Server: 172.16.6.173
[*] b'POST /message/ajax.php?c=workWeixin HTTP/1.1\r\nsw6: 1-NjI0OS45MS4xNjA0MTMzMDk2NjUyNDAyOQ==-NjI0OS45MS4xNjA0MTMzMDk2NjUyNDAyOA==-0-6249-6249-MTM1-Iy9tZXNzYWdlL2FqYXgucGhw-Iy9tZXNzYWdlL2FqYXgucGhw\r\nContent-Length: 167\r\nContent-Type: text/plain; charset=UTF-8\r\nHost: ttools.svc.com\r\nConnection: Keep-Alive\r\nUser-Agent: auto\r\nCookie: PHPSESSID=u8e6g212n8qu6l81mq8fbiu6v6\r\nAccept-Encoding: gzip,deflate\r\n\r\n{"data":{"user":"xiaokun.wang,zhenggong.hou","msgtype":"text","content":"\xe3\x80\x90sit\xe6\xb5\x8b\xe8\xaf\x95\xe7\x8e\xaf\xe5\xa2\x83\xe3\x80\x91\xe3\x80\x90\xe4\xbf\xa1\xe8\xb4\xb7\xe6\xa0\xb8\xe5\xbf\x83\xe3\x80\x9120540110-20540111\xe4\xbf\xa1\xe8\xb4\xb7\xe6\x97\xa5\xe5\x88\x87\xe8\xb7\x91\xe6\x89\xb9\xe5\xbc\x80\xe5\xa7\x8b"},"m":"send"}'

C. 抓取30秒内的TCP协议的数据包并且保存

#coding=utf-8
from scapy.all import *
import os# 数据包回调函数,显示TCP信息
def packet_callback(packet):if packet[TCP].payload:mail_packet = str(packet[TCP].payload)if "user" in mail_packet.lower() or "pass" in mail_packet.lower():print("[*] Server: %s" % packet[IP].dst)print("[*] %s" % packet[TCP].payload)# 开启嗅探器,过滤出tcp协议,一次抓30秒,
package=sniff(filter="tcp", timeout=30, prn=packet_callback, store=1)flowName = "test.pcap"
wrpcap(flowName, package)  #将抓取到的包保存为test.pcap文件

D. 读取pcap文件并解析HTTP请求

#coding=utf-8
from scapy.all import *try:import scapy.all as scapy
except ImportError:import scapydef parse_http_pcap(pcap_path):pcap_infos = list()packets = scapy.rdpcap(pcap_path)for p in packets:print("----")# 判断是否包含某一层,用haslayerif p.haslayer("IP"):src_ip = p["IP"].srcdst_ip = p["IP"].dstprint("sip: %s" % src_ip)print("dip: %s" % dst_ip)if p.haslayer("TCP"):#获取某一层的原始负载用.payload.originalraw_http = p["TCP"].payload.originalsport = p["TCP"].sportdport = p["TCP"].dportprint("sport: %s" % sport)print("dport: %s" % dport)print("raw_http:\n%s" % raw_http)if p.haslayer("HTTPRequest"):host = p["HTTPRequest"].Hosturi = p["HTTPRequest"].Path# 直接获取提取好的字典形式的http数据用fieldshttp_fields = p["HTTPRequest"].fieldshttp_payload = p["HTTPRequest"].payload.fieldsprint("host: %s" % host)print("uri: %s" % uri)print("http_fields:\n%s" % http_fields)print("http_payload:\n%s" % http_payload)parse_http_pcap("test.pcap")

输出:

# Get请求
sip: 172.30.219.206
dip: 172.16.6.173
sport: 11599
dport: 80
raw_http:
b'GET /api/v1/flow/flow_map?start_time=2020-10-29%2021:34:16 HTTP/1.1\r\nUser-Agent: PostmanRuntime/7.26.5\r\nAccept: */*\r\nCache-Control: no-cache\r\nPostman-Token: 0eb5d6bf-8758-4f3e-baee-b5e4cad11d25\r\nHost: clue.tdevops.svc.com\r\nAccept-Encoding: gzip, deflate, br\r\nConnection: keep-alive\r\n\r\n'

E. 实时获取并解析流量数据包(HTTP和HTTPS)

Python2和Python3都可以运行,并且能够自动检查scapy依赖是否安装,如果没安装则会进行自动安装

注意:python2的话,代码里面的with open()里面要去掉encoding,否则会报错的

注意:当前python文件所在目录,需要有解析包的目录protocol,即https://github.com/HatBoy/Pcap-Analyzer里面的解析包:app/utils/protocol

注意:解析包里面是一些配置文件,对应着端口和对应协议或应用,比如3306:MySQL,不一定能够精确识别到对应的应用

#!/usr/bin/python
# -*- coding: utf-8 -*-
from __future__ import print_function
import sys# protocol目录
PROTOCOL_PATH = './protocol'# 监听的网卡,默认是eth0
NETWORK_INTERFACE = 'eth0'# 需要安装的Python依赖包,注意:如果是开启上报且异步上报的话,还需要安装aiohttp
NEED_INSTALL = ['scapy']class PcapDecode:def __init__(self):# ETHER:读取以太网层协议配置文件with open('%s/ETHER' % PROTOCOL_PATH, 'r', encoding='UTF-8') as f:ethers = f.readlines()self.ETHER_DICT = {}for ether in ethers:ether = ether.strip().strip('\n').strip('\r').strip('\r\n')self.ETHER_DICT[int(ether.split(':')[0])] = ether.split(':')[1]  # 将配置文件中的信息(0257:Experimental)存入dict# IP:读取IP层协议配置文件with open('%s/IP' % PROTOCOL_PATH, 'r', encoding='UTF-8') as f:ips = f.readlines()self.IP_DICT = {}for ip in ips:ip = ip.strip().strip('\n').strip('\r').strip('\r\n')self.IP_DICT[int(ip.split(':')[0])] = ip.split(':')[1]  # 将配置文件中的信息(41:IPv6)存入dic# PORT:读取应用层协议端口配置文件with open('%s/PORT' % PROTOCOL_PATH, 'r', encoding='UTF-8') as f:ports = f.readlines()self.PORT_DICT = {}for port in ports:port = port.strip().strip('\n').strip('\r').strip('\r\n')self.PORT_DICT[int(port.split(':')[0])] = port.split(':')[1]  # 如:21:FTP# TCP:读取TCP层协议配置文件with open('%s/TCP' % PROTOCOL_PATH, 'r', encoding='UTF-8') as f:tcps = f.readlines()self.TCP_DICT = {}for tcp in tcps:tcp = tcp.strip().strip('\n').strip('\r').strip('\r\n')self.TCP_DICT[int(tcp.split(':')[0])] = tcp.split(':')[1]  # 465:SMTPS# UDP:读取UDP层协议配置文件with open('%s/UDP' % PROTOCOL_PATH, 'r', encoding='UTF-8') as f:udps = f.readlines()self.UDP_DICT = {}for udp in udps:udp = udp.strip().strip('\n').strip('\r').strip('\r\n')self.UDP_DICT[int(udp.split(':')[0])] = udp.split(':')[1]  # 513:Who# 解析以太网层协议 ---ether_decode——ip_decode(tcp_decode or udp_decode)def ether_decode(self, p):data = {}  # 解析出的信息以dict的形式保存if p.haslayer("Ether"):  # scapy.haslayer,将pcap包中的信息分层,再处理data = self.ip_decode(p)  # 解析IP层协议return dataelse:data['time'] = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(p.time))data['source_ip'] = ''data['dest_ip'] = ''data['protocol'] = ''data['len'] = len(corrupt_bytes(p))data['info'] = p.summary()data['source_port'] = ''data['dest_port'] = ''return data# 解析IP层协议def ip_decode(self, p):data = {}if p.haslayer("IP"):  # 2048:Internet IP (IPv4) ,分IPV4和IPV6和其他协议ip = p.getlayer("IP")if p.haslayer("TCP"):  # 6:TCPdata = self.tcp_decode(p, ip)return dataelif p.haslayer("UDP"):  # 17:UDPdata = self.udp_decode(p, ip)return dataelse:if ip.proto in self.IP_DICT:  # 若ip分层中的协议信息在字典中,则提取ip分层中的源地址、目的地址、协议(转换)等data['time'] = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(p.time))data['source_ip'] = ip.srcdata['dest_ip'] = ip.dstdata['protocol'] = self.IP_DICT[ip.proto]data['len'] = len(corrupt_bytes(p))data['info'] = p.summary()data['source_port'] = 'UnKnow'data['dest_port'] = 'UnKnow'return dataelse:data['time'] = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(p.time))data['source_ip'] = ip.srcdata['dest_ip'] = ip.dstdata['protocol'] = 'IPv4'data['len'] = len(corrupt_bytes(p))data['info'] = p.summary()data['source_port'] = 'UnKnow'data['dest_port'] = 'UnKnow'return dataelif p.haslayer("IPv6"):  # 34525:IPv6ipv6 = p.getlayer("IPv6")if p.haslayer("TCP"):  # 6:TCPdata = self.tcp_decode(p, ipv6)return dataelif p.haslayer("UDP"):  # 17:UDPdata = self.udp_decode(p, ipv6)return dataelse:if ipv6.nh in self.IP_DICT:data['time'] = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(p.time))data['source_ip'] = ipv6.srcdata['dest_ip'] = ipv6.dstdata['protocol'] = self.IP_DICT[ipv6.nh]data['len'] = len(corrupt_bytes(p))data['info'] = p.summary()data['source_port'] = 'UnKnow'data['dest_port'] = 'UnKnow'return dataelse:data['time'] = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(p.time))data['source_ip'] = ipv6.srcdata['dest_ip'] = ipv6.dstdata['protocol'] = 'IPv6'data['len'] = len(corrupt_bytes(p))data['info'] = p.summary()data['source_port'] = 'UnKnow'data['dest_port'] = 'UnKnow'return dataelse:if p.type in self.ETHER_DICT:data['time'] = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(p.time))data['source_ip'] = p.srcdata['dest_ip'] = p.dstdata['protocol'] = self.ETHER_DICT[p.type]data['len'] = len(corrupt_bytes(p))data['info'] = p.summary()data['source_port'] = 'UnKnow'data['dest_port'] = 'UnKnow'return dataelse:data['time'] = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(p.time))data['source_ip'] = p.srcdata['dest_ip'] = p.dstdata['protocol'] = hex(p.type)  # 若在字典中没有改协议,则以16进制的形式显示data['len'] = len(corrupt_bytes(p))data['info'] = p.summary()data['source_port'] = 'UnKnow'data['dest_port'] = 'UnKnow'return data# 解析TCP层协议def tcp_decode(self, p, ip):data = {}tcp = p.getlayer("TCP")data['time'] = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(p.time))data['source_ip'] = ip.srcdata['dest_ip'] = ip.dstdata['len'] = len(corrupt_bytes(p))data['info'] = p.summary()data['source_port'] = str(ip.sport)data['dest_port'] = str(ip.dport)if tcp.dport in self.PORT_DICT:  # 若端口信息在PORT_DICT\TCP_DICT中则转换为已知data['protocol'] = self.PORT_DICT[tcp.dport]elif tcp.sport in self.PORT_DICT:data['protocol'] = self.PORT_DICT[tcp.sport]elif tcp.dport in self.TCP_DICT:data['protocol'] = self.TCP_DICT[tcp.dport]elif tcp.sport in self.TCP_DICT:data['protocol'] = self.TCP_DICT[tcp.sport]else:data['protocol'] = "TCP"return data# 解析UDP层协议def udp_decode(self, p, ip):data = {}udp = p.getlayer("UDP")data['time'] = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(p.time))data['source_ip'] = ip.srcdata['dest_ip'] = ip.dstdata['len'] = len(corrupt_bytes(p))data['info'] = p.summary()data['source_port'] = str(ip.sport)data['dest_port'] = str(ip.dport)if udp.dport in self.PORT_DICT:  # 若端口信息在PORT_DICT\UDP_DICT中则转换为已知data['protocol'] = self.PORT_DICT[udp.dport]elif udp.sport in self.PORT_DICT:data['protocol'] = self.PORT_DICT[udp.sport]elif udp.dport in self.UDP_DICT:data['protocol'] = self.UDP_DICT[udp.dport]elif udp.sport in self.UDP_DICT:data['protocol'] = self.UDP_DICT[udp.sport]else:data['protocol'] = "UDP"return datadef get_host_ip():"""查询本机ip地址:return: ip"""try:s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)s.connect(('8.8.8.8', 80))ip = s.getsockname()[0]finally:s.close()return ipdef get_host_name():"""查询本机hostname,如果是:xxx.novalocal,则只获取xxx"""hostname = socket.gethostname()name = hostname.split('.')[0] if '.' in hostname else hostnamereturn namedef handle_flow(obj, data):# 解析流量数据data = obj.ether_decode(data)print(data)return datadef check_import(name):try:exec("import %s" % name)return 0, 'success'except:return 1, 'Python模块%s未安装' % namedef check_init():if sys.version_info < (3, 0):return 1, '该脚本只能在Python3下运行,请使用Python3运行该脚本'for app_name in NEED_INSTALL:(code, msg) = check_import(app_name)if code:return 1, msgprint('Python模块%s已安装' % app_name)return 0, 'success'if __name__ == '__main__':PD = PcapDecode()host_ip = get_host_ip()host_name = get_host_name()print('------------------------------------------------------\r\n')print('开始检测是否安装依赖')(code, msg) = check_init()if code:print(msg)sys.exit(1)loop = Nonefrom scapy.all import *print('------------------------------------------------------\r\n')print('主机IP: ', host_ip)print('主机名称:', host_name)print('监听网卡:', NETWORK_INTERFACE)print('------------------------------------------------------\r\n')print('开始监控流量数据')print('------------------------------------------------------\r\n')# 实时抓取流量数据并且每个数据包进行解析输出和上报while True:sniff(iface=NETWORK_INTERFACE, timeout=20, store=0, filter="tcp and ( port 80 or port 443 )", prn=lambda x: handle_flow(PD, x))

每有一条流量过来,会输出:

{"source_ip": "172.16.6.220","source_port": "41804","dest_ip": "172.16.6.173","dest_port": "80","protocol": "HTTP","len": 74,"info": "Ether / IP / TCP 172.16.6.173:41804 > 172.16.6.16:http S","time": "2020-10-29 11:56:28"}

能够获取到五元组,其实也可以做到获取完整的报文信息。

【Scapy】获取流量包【原创】相关推荐

  1. 2021-05-03Wireshark流量包分析

    目录 WEB扫描分析 后台目录爆破分析 后台账号爆破 WEBSHELL上传 其他题目 参考链接 WEB数据包分析的题目主要出现WEB攻击行为的分析上, 典型的WEB攻击行为有:WEB扫描.后台目录爆破 ...

  2. 新媒体运营:23种免费获取流量的运营套路 ,你知道几种? 黎想

    随着以微信为代表的"免费"社交工具,抖音短视频等新媒体技术的快速发展,无论是个人,还是企业,都纷纷加入了新媒体推广行列. 那做新媒体推广时什么才是运营者关注的核心呢?什么样的推广才 ...

  3. 微信视频号推出“创作者流量包”

    我是卢松松,点点上面的头像,欢迎关注我哦! 前两天,微信视频号内测"付费推广"功能,官方称为"创作者流量包",是专门给视频号优创鼓励的流量包,很高兴,视频号送了 ...

  4. Python安全工具编写-pcap流量包重放

    最近因为log4j漏洞,工作量急剧增加,卑微小乙没日没夜地进行应急处理,为了能测试是否能检测到log4j攻击,我专门写了一个脚本,当然这个脚本也不只是检测log4j,只要是pcap包放在指定目录下则可 ...

  5. Wireshark之流量包分析+日志分析 (护网:蓝队)web安全 取证 分析黑客攻击流程(上篇)

    前言:小编也是在前几天通过,安恒的资深项目经理讲解(甘老师),老师风趣幽默,讲解生动形象,在他讲解的时候,我就萌生出要把这知识点分享出来,当然这只是为小白开启分析之路,并没有什么高操作,分享的只是我的 ...

  6. Wireshark之流量包分析+日志分析 (护网:蓝队)web安全 取证 分析黑客攻击流程(下篇)

    前言:咦!确实让我想不到的是,这几天有不少的人催我更新分析的下篇!我以为这像便秘的粑粑,又臭又长没人看!但出乎意料,这不我加班加点就来满足你们咯!所以你懂的(悄悄告诉你:"点赞") ...

  7. 想做网上线上引流怎么做?如何通过网络获取流量?

    想做网上线上引流怎么做?如何通过网络获取流量? 现在很多人都在问关于"引流"."流量"的问题,对于这些问题实际上背后的道理都是一样的,我们需要了解的是: &qu ...

  8. python获取局域网在线主机_python通过scapy获取局域网所有主机mac地址示例

    python通过scapy获取局域网所有主机mac地址示例 发布于 2014-10-10 20:34:48 | 607 次阅读 | 评论: 0 | 来源: 网友投递 Python编程语言Python ...

  9. CTF 流量包相关-流量分析(1)

    声明一下 本文是根据b站-风二西大佬的视频边做题边总结写成的,可以去支持一下风佬,风佬太强辣!!! 风佬流量分析题合集 风佬流量分析配套题与脚本 另外本人也是个初学者,文章里面如果有错误,记得来踢我 ...

最新文章

  1. SDUTOJ [2801] 并查集模板
  2. android编译产生的apk或so不安装 .
  3. 68 cookie在登录中的作用
  4. kibana-7.15.2 中文简体
  5. java如何驱动z4mplus打印二维码_斑马 Zebra 打印机驱动下载
  6. ubuntu install opencv
  7. 高性能服务器架构思路
  8. 日益努力而后风生水起,送3本技术好书
  9. python语言程序设计教程赵璐电子版_python语言程序设计教程 赵璐pdf 相关实例(示例源码)下载 - 好例子网...
  10. MATLAB官方机器学习入门教程
  11. c语言中if函数作用,c语言函数if的用法怎么用
  12. c语言数组中找出相同的数,找出数组中重复的数字(c语言)
  13. badboy 录制脚本,提示:“当前页面的脚本发生错误”
  14. 世界上最好用的FTP服务器管理工具
  15. 黑马粉丝感叹:好可呀,好想要!!【最新福利你还没领?】
  16. android11.0 Launcher3 高端定制之抽屉列表固定APP显示位置
  17. 量化投资:为什么在中国发展之路任重而道远
  18. 系统集成项目需求调研日志
  19. 显示“打不开“XXX”,因为它来着身份不明的开发者【打开任何来源】
  20. 【slam十四讲第二版】【课本例题代码向】【第七讲~视觉里程计Ⅱ】【使用LK光流(cv)】【高斯牛顿法实现单层光流和多层光流】【实现单层直接法和多层直接法】

热门文章

  1. 我是如何用一行代码表白学妹~❤520情人节送女朋友的3D樱花雨相册礼物❤~(程序员表白专属)...
  2. 教养,就是要让别人舒服
  3. 分析| AI智能生图前景几何?
  4. HOJ 2786 Convert Kilometers to Miles
  5. VMware vSphere 7 vCenter 7 ESXi 7 正式版下载地址
  6. BMC-IPMB specification
  7. 用户画像构建方法调研和初步解决方案
  8. 中国版的Google被阉割掉多少?
  9. 初学VUE.js之数据绑定
  10. 你知道我国一共赠送了多少只熊猫给外国吗?来看看这个数据可视化项目