Python中的数据包嗅探(Windows)

16

如何使用Python最佳地嗅探网络数据包?

我从几个地方听说,最好的模块是一个叫做Scapy的模块,但不幸的是,它会导致我的python.exe崩溃。 我想这只是安装方式的问题,但许多其他人告诉我,它在Windows上的表现并不理想。(如果有人感兴趣,我正在运行Windows Vista,这可能会影响事情的进行)。

有没有更好的解决办法?

更新:

在阅读了回答并安装了PyPcap之后,我对其进行了一些尝试,并发现我之前尝试使用的Scapy也要求安装PyPcap,但是它是用于自己修改的版本。显然,正是这个修改过的PyPcap导致了问题,因为回答中提供的示例也会导致挂起。

我安装了来自Google网站的原始版本的PyPcap,Scapy开始正常工作了(虽然我没有尝试很多东西,但至少在我开始嗅探之后它没有崩溃)。我向Scapy开发人员提交了新的缺陷报告:http://trac.secdev.org/scapy/ticket/166,希望他们能采取一些措施。

无论如何,只是想让大家知道。


FTR这是一个非常过时的帖子。Scapy不再需要这些过时的库,可以查看https://scapy.readthedocs.io - Cukic0d
6个回答

20

使用困难的方式

你可以使用原始套接字来嗅探所有IP数据包。
原始套接字是一个用于以二进制形式发送和接收数据的套接字。
在Python中,二进制表示为一个看起来像这样的字符串\x00\xff...每个\x..都是一个字节。
要读取IP数据包,需要根据IP协议以二进制形式分析接收到的数据包。

下面是IP协议格式的图像,其中显示了每个标头的位大小。

IP协议格式

此教程可能会帮助您理解理解原始数据包并将其拆分为标头的过程:http://www.binarytides.com/python-packet-sniffer-code-linux/

使用简单的方式

另一种非常容易嗅探IP数据包的方法是使用scapy模块。

from scapy.all import *
sniff(filter="ip", prn=lambda x:x.sprintf("{IP:%IP.src% -> %IP.dst%\n}"))

这段代码能够打印每个IP数据包的源IP和目标IP。你可以通过这里阅读scapy的文档,了解更多关于如何使用scapy的信息。

如果您需要构建一个具有数据包嗅探功能的项目,那么我建议您使用scapy来编写更加稳定的脚本。


你缺少一个括号 sniff(filter="ip", prn=lambda x:x.sprintf("{IP:%IP.src% -> %IP.dst%\n}")) - Voyager

16

使用pypcap

import dpkt, pcap
pc = pcap.pcap()     # construct pcap object
pc.setfilter('icmp') # filter out unwanted packets
for timestamp, packet in pc:
    print dpkt.ethernet.Ethernet(packet)

输出示例:

Ethernet(src='\x00\x03G\xb2M\xe4', dst='\x00\x03G\x06h\x18', data=IP(src='\n\x00\x01\x1c',
dst='\n\x00\x01\x10', sum=39799, len=60, p=1, ttl=128, id=35102, data=ICMP(sum=24667,
type=8, data=Echo(id=512, seq=60160, data='abcdefghijklmnopqrstuvwabcdefghi'))))

Ethernet(src='\x00\x03G\x06h\x18', dst='\x00\x03G\xb2M\xe4', data=IP(src='\n\x00\x01\x10',
dst='\n\x00\x01\x1c', sum=43697, len=60, p=1, ttl=255, id=64227, data=ICMP(sum=26715,
data=Echo(id=512, seq=60160, data='abcdefghijklmnopqrstuvwabcdefghi'))))

最方便的工具确实如此。 - Konstantin
它自2008年以来尚未正式更新。像Scapy这样的替代品可能更加更新。 - Cukic0d

8
使用 python-libpcap 库。
import pcap

p = pcap.pcapObject()
dev = pcap.lookupdev()
p.open_live(dev, 1600, 0, 100)
#p.setnonblock(1)
try:
    for pktlen, data, timestamp in p:
        print "[%s] Got data: %s" % (time.strftime('%H:%M', 
                                                   time.localtime(timestamp)),
                                     data)
except KeyboardInterrupt:
    print '%s' % sys.exc_type
    print 'shutting down'
    print ('%d packets received, %d packets dropped'
           ' %d packets dropped by interface') % p.stats()

3

您可以使用原始套接字,并使用您的接口IP地址(以管理员模式运行)。

import socket
s = socket.socket(socket.AF_INET,socket.SOCK_RAW,socket.IPPROTO_IP)
s.bind(("YOUR_INTERFACE_IP",0))
s.setsockopt(socket.IPPROTO_IP,socket.IP_HDRINCL,1)
s.ioctl(socket.SIO_RCVALL,socket.RCVALL_ON)
while True:
   data = s.recvfrom(10000)
   print data

2
如果使用scapy,请尝试以下方法(适用于Windows 10):
# -*- coding: utf-8 -*-

# pip install scapy

"""
[{'name': 'Intel(R) 82574L Gigabit Network Connection',
  'win_index': '4',
  'description': 'Ethernet0',
  'guid': '{XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}',
  'mac': '00:0C:29:5C:EE:6D',
  'netid': 'Ethernet0'}]
"""

from pprint import pprint
from scapy.arch.windows import get_windows_if_list
from scapy.all import *


# disable verbose mode
conf.verb = 0


def parse_packet(packet):
    """sniff callback function.
    """
    if packet and packet.haslayer('UDP'):
        udp = packet.getlayer('UDP')
        udp.show()


def udp_sniffer():
    """start a sniffer.
    """
    interfaces = get_windows_if_list()
    pprint(interfaces)

    print('\n[*] start udp sniffer')
    sniff(
        filter="udp port 53",
        iface=r'Intel(R) 82574L Gigabit Network Connection', prn=parse_packet
    )


if __name__ == '__main__':
    udp_sniffer()

1

构造器已死?看起来已经没有新的更新发布一年了…… - chills42
虽然Construct的主页提到了ethereal,但所有的教程都是关于使用Construct构建解析器,而不是使用它来解析网络数据包。 - Sean Reifschneider

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接