翼度科技»论坛 编程开发 python 查看内容

21.3 Python 使用DPKT分析数据包

4

主题

4

帖子

12

积分

新手上路

Rank: 1

积分
12
dpkt项目是一个Python模块,主要用于对网络数据包进行解析和操作。它可以处理多种协议,例如TCP、UDP、IP等,并提供了一些常用的网络操作功能,例如计算校验和、解析DNS数据包等。由于其简单易用的特性,dpkt被广泛应用于网络安全领域,例如流量分析、漏洞利用、入侵检测等。使用该库可以快速解析通过各类抓包工具抓到的数据包,从而提取分析包内的参数。

  • 安装DPKT工具:pip install dpkt
在分析数据包之前我们需要抓取特定数据包并保存为*.pcap格式,通常情况下这种数据包格式可通过WireShark等工具抓取到,当然也可以使用上一篇提到的Scapy库实现,该库中存在一个sniff函数,该函数可以实现网络抓包功能,如下一个演示案例我们分别通过sniff(count=2)函数抓取两个数据包并使用wrpcap()函数将其保存到文件内,当需要分析时可通过调用rdpcap()函数打开数据包即可实现分析。
  1. >>> from scapy.all import *
  2. >>>
  3. >>> packets = sniff(count=2)                            # 动态抓取2个数据包
  4. >>>
  5. >>> wrpcap("d://lyshark.pcap",packets)                  # 保存数据包
  6. >>> pcap_packets = rdpcap("d://lyshark.pcap")           # 读取数据包
  7. >>>
  8. >>> pcap_packets
  9. <lyshark.pcap: TCP:2 UDP:0 ICMP:0 Other:0>
  10. >>>
  11. >>> pcap_packets.show()
  12. 0000 Ether / IP / TCP 192.168.1.101:63995 > 172.217.24.10:https S
  13. 0001 Ether / IP / TCP 192.168.1.101:63907 > 103.235.46.191:https A / Raw
  14. >>>
  15. >>> pcap_packets.summary()
  16. Ether / IP / TCP 192.168.1.101:63995 > 172.217.24.10:https S
  17. Ether / IP / TCP 192.168.1.101:63907 > 103.235.46.191:https A / Raw
  18. >>>
  19. >>> pcap_packets[0].dst
  20. 'FF:2d:1e:0f:1e:a1'
  21. >>>
  22. >>> pcap_packets[0].src
  23. 'a4:7e:33:ee:cc:b3'
  24. >>>
  25. # 如下分别代表: 链路层 [Ethernet]、网络层[IP]、传输层[TCP/UDP]、应用层[RAW]
  26. >>> pcap_packets[0].show()
  27. >>>
  28. # 抓包后直接输出
  29. >>> sniff(prn=lambda x: x.show(), count=1)
复制代码
通过上方的抓包流程读者即可实现简单的抓包功能,当然sniff函数参数众多我们完全可以在抓包时增加不同的抓包条件,同时该函数也支持回调函数,当由新的请求被触发时则自动执行回调函数,如下则是使用Scapy抓包的完整案例,该案例展示了抓取60秒数据包,并将其保存至d://lyshark.pcap目录。
  1. from scapy.all import *
  2. import scapy.all as scapy
  3. # 数据包回调函数
  4. def packet_callback(packet):
  5.     if packet[TCP].payload:
  6.         m_packet = str(packet[TCP].payload)
  7.         print("主机地址: {} ---> 数据包内容: {}".format(packet[IP].dst,packet[TCP].payload))
  8. if __name__ == "__main__":
  9.     # 抓取80端口的数据包并输出到屏幕
  10.     # sniff(filter="tcp port 80", prn=packet_callback, store=0)
  11.     # 抓取 过滤出tcp协议 抓取1分钟后保存到文件中
  12.     package=sniff(filter="tcp", timeout=60, prn=packet_callback, store=1)
  13.     wrpcap("d://lyshark.pcap", package)
复制代码
运行上方抓包程序,读者可看到如下图所示的输出结果,等待60秒后即可看到d://lyshark.pcap文件。

当读者抓取到这些数据包之后,下一步则是解析这些数据包,解析的方法有许多可以使用DPKT解析,也可以使用scapy自带的工具解析,本章首先介绍如何使用Scapy工具实现解析数据包内的HTTP请求,并输出的功能,如下是完整的代码实现;
  1. from scapy.all import *
  2. import scapy.all as scapy
  3. # 解析获取到的数据包
  4. def get_http_pcap(pcap_path):
  5.     pcap_infos = list()
  6.     packets = scapy.rdpcap(pcap_path)
  7.     for p in packets:
  8.         if p.haslayer("IP"):
  9.             src_ip = p["IP"].src
  10.             dst_ip = p["IP"].dst
  11.         if p.haslayer("TCP"):
  12.             raw_http = p["TCP"].payload.original
  13.             sport = p["TCP"].sport
  14.             dport = p["TCP"].dport
  15.         if p.haslayer("HTTPRequest"):
  16.             host = p["HTTPRequest"].Host
  17.             uri = p["HTTPRequest"].Path
  18.             http_fields = p["HTTPRequest"].fields
  19.             # print("主机地址: {} --> URI: {}".format(host,uri))
  20.         print("原IP地址: {}:{} --> 目标IP地址: {}:{}".format(src_ip,sport,dst_ip,dport))
  21. if __name__ == "__main__":
  22.     get_http_pcap("d://lyshark.pcap")
复制代码
读者可自行运行上述代码,并传入刚才抓取到的lyshark.pcap数据包,此时则可解析出当前数据包中所有HTTP访问数据,如下图所示;

对于数据包的解包功能,Dpkt工具包也可以很好的完成,对于使用Dpkt解包而言,首先需要通过open()打开数据包,接着调用dpkt.pcap.Reader(fp)将文件内的字节转化为PCAP格式,最后调用自定义函数GetDpkt根据字段进行解析即可。
  1. import dpkt
  2. import socket
  3. def GetDpkt(pcap):
  4.     for timestamp,packet in pcap:
  5.         try:
  6.             eth = dpkt.ethernet.Ethernet(packet)
  7.             ip = eth.data
  8.             tcp = ip.data
  9.             src = socket.inet_ntoa(ip.src)
  10.             dst = socket.inet_ntoa(ip.dst)
  11.             sport = tcp.sport
  12.             dport = tcp.dport
  13.             print("[+] 源地址: {}:{} --> 目标地址:{}:{}".format(src,sport,dst,dport))
  14.         except Exception:
  15.             pass
  16. # 检测主机是否被DDOS攻击了
  17. def FindDDosAttack(pcap):
  18.     pktCount = {}
  19.     for timestamp,packet in pcap:
  20.         try:
  21.             eth = dpkt.ethernet.Ethernet(packet)
  22.             ip = eth.data
  23.             tcp = ip.data
  24.             src = socket.inet_ntoa(ip.src)
  25.             dst = socket.inet_ntoa(ip.dst)
  26.             sport = tcp.sport
  27.             # 累计判断各个src地址对目标地址80端口访问次数
  28.             if dport == 80:
  29.                 stream = src + ":" + dst
  30.                 if pktCount.has_key(stream):
  31.                     pktCount[stream] = pktCount[stream] + 1
  32.                 else:
  33.                     pktCount[stream] = 1
  34.         except Exception:
  35.             pass
  36.     for stream in pktCount:
  37.         pktSent = pktCount[stream]
  38.         # 如果超过设置的检测阈值500,则判断为DDOS攻击行为
  39.         if pktSent > 500:
  40.             src = stream.split(":")[0]
  41.             dst = stream.split(":")[1]
  42.             print("[+] 源地址: {} 攻击: {} 流量: {} pkts.".format(src,dst,str(pktSent)))
  43. # FindPcapURL 监控提取数据包中的所有URL
  44. def FindPcapURL(pcap):
  45.     Url = []
  46.     for timestamp,packet in pcap:
  47.         try:
  48.             eth = dpkt.ethernet.Ethernet(packet)
  49.             ip = eth.data
  50.             src = socket.inet_ntoa(ip.src)
  51.             tcp = ip.data
  52.             http = dpkt.http.Request(tcp.data)
  53.             if(http.method == "GET"):
  54.                 UrlHead = http.headers
  55.                 for key,value in UrlHead.items():
  56.                     url = re.findall('^https*://.*',str(value))
  57.                     if url:
  58.                         print("[+] 源地址: %10s --> 访问URL: %-80s"%(src, url[0]))
  59.         except Exception:
  60.             pass
  61.     return set(Url)
  62. # 动态保存pcap文件(每1024字节保存一次pcap文件),并读取出其中的网址解析出来
  63. def write_cap(pkt):
  64.     global pkts
  65.     global count
  66.     pkts.append(pkt)
  67.     count += 1
  68.     if count == 1024:
  69.         wrpcap("data.pcap",pkts)
  70.         fp = open("./data.pcap","rb")
  71.         pcap = dpkt.pcap.Reader(fp)
  72.         FindPcapURL(pcap)
  73.         fp.close()
  74.         pkts,count = [],0
  75. if __name__ == "__main__":
  76.     fp = open("d://lyshark.pcap","rb")
  77.     pcap = dpkt.pcap.Reader(fp)
  78.     GetDpkt(pcap)
复制代码
运行上述代码,同样可以输出这些IP信息,如下图所示;

本文作者: 王瑞
本文链接: https://www.lyshark.com/post/29b6bdae.html
版权声明: 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!

来源:https://www.cnblogs.com/LyShark/p/17777817.html
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x

举报 回复 使用道具