使用 Python 3 编写与 libpcap 的绑定

发布于 2024-12-06 11:53:33 字数 3541 浏览 0 评论 0原文

我已经研究这个问题有一段时间了,但我不确定这里的问题。由于某种原因,我的设备正在被更改,但我不确定原因。我怀疑这与我将 libpcap 库映射到 ctypes 的方式有关,因为用纯 C 编写的相同程序在我的主机上运行得很好。代码如下

#!/usr/bin/env python3.2

import ctypes,sys
from ctypes.util import find_library


#pcap = ctypes.cdll.LoadLibrary("libpcap.so")
pcap = ctypes.cdll.LoadLibrary(find_library("libpcap"))

# required so we can access bpf_program->bf_insns
"""
struct bpf_program {
    u_int bf_len;
    struct bpf_insn *bf_insns;}
"""
class bpf_program(ctypes.Structure):
    _fields_ = [("bf_len", ctypes.c_int),("bf_insns", ctypes.c_void_p)]

class sockaddr(ctypes.Structure):
    _fields_=[("sa_family",ctypes.c_uint16),("sa_data",ctypes.c_char*14)]

class pcap_pkthdr(ctypes.Structure):
    _fields_ = [("tv_sec", ctypes.c_long), ("tv_usec", ctypes.c_long), ("caplen", ctypes.c_uint), ("len", ctypes.c_uint)]

pcap_lookupdev = pcap.pcap_lookupdev
pcap_lookupdev.restype = ctypes.c_char_p
#pcap_lookupnet(dev, &net, &mask, errbuf)
pcap_lookupnet = pcap.pcap_lookupnet
#pcap_t *pcap_open_live(const char *device, int snaplen,int promisc, int to_ms, char *errbuf)
pcap_open_live = pcap.pcap_open_live
pcap_open_live.restype = ctypes.c_char_p
#int pcap_compile(pcap_t *p, struct bpf_program *fp,const char *str, int optimize, bpf_u_int32 netmask)
pcap_compile = pcap.pcap_compile
#int pcap_setfilter(pcap_t *p, struct bpf_program *fp)
pcap_setfilter = pcap.pcap_setfilter
#const u_char *pcap_next(pcap_t *p, struct pcap_pkthdr *h)
pcap_next = pcap.pcap_next

# prepare args
snaplen = ctypes.c_int(1540)
linktype = ctypes.c_int(12) # DLT_RAW on linux
program = bpf_program()
#buf = ctypes.c_char_p(filter)
optimize = ctypes.c_int(0)
mask = ctypes.c_int(0)

errbuf = ctypes.create_string_buffer(256)

dev = pcap_lookupdev(errbuf)
dev = bytes(str('en1'), 'ascii')

if(dev):
    print("{0} is the default interface".format(dev))
else:
    print("Was not able to find default interface {0}".format(errbuf.value))



mask = ctypes.c_uint(32)
net = ctypes.c_uint(32)

if(pcap_lookupnet(dev,ctypes.pointer(net),ctypes.pointer(mask),errbuf) == -1):
    print("Error could not get netmask for device {0}".format(errbuf.value))
    sys.exit(0)
else:
    print("Got Required netmask")



to_ms = ctypes.c_int(1000)
promisc = ctypes.c_int(1)
handle = pcap_open_live(dev,snaplen,promisc,to_ms,errbuf)

if(handle is False):
    print("Error unable to open session : {0}".format(errbuf.value))
    sys.exit(0)
else:
    print("Pcap open live worked!")


filter = bytes(str('port 80'), 'ascii')
buf = ctypes.c_char_p(filter)


if(pcap_compile(handle,ctypes.byref(program),buf,ctypes.c_int(1),mask) == -1):
    # this requires we call pcap_geterr() to get the error
    print("Error could not compile bpf filter because {0}".format(errbuf.value))
else:
    print("Filter Compiled!")


if(pcap_setfilter(handle,ctypes.byref(program) == -1)):
    print("Error couldn't install filter {0}".format(errbuf.value))
    sys.exit(0)
else:
    print("Filter installed!")


header = pcap_pkthdr()
if(pcap_next(handle,ctypes.bref(header)) == -1):
    print("ERROR pcap_next failed!")

print("Got {0} bytes of data".format(pcap_pkthdr().len))
pcap_close = pcap.pcap_close
pcap_close(handle)

由于某种原因,当我们进入 pcap_compile() 时,系统会尝试查找 vmware 接口之一,而不是分配给 dev 的值。这里是输出。

bash-3.2# ./libpcap.py 
b'en1' is the default interface
Got Required netmask
Pcap open live worked!
Error could not compile bpf filter because b'vmnet8: No such device exists (BIOCSETIF    failed: Device not configured)'
Bus error: 10

I've been banging away at this for a while an I'm unsure of the issue here. For some reason my device is being changed and I'm unsure why. I suspect it has to do with how I'm mapping the libpcap libs to ctypes because the same program written in pure C works just fine on my host. The code is as follows

#!/usr/bin/env python3.2

import ctypes,sys
from ctypes.util import find_library


#pcap = ctypes.cdll.LoadLibrary("libpcap.so")
pcap = ctypes.cdll.LoadLibrary(find_library("libpcap"))

# required so we can access bpf_program->bf_insns
"""
struct bpf_program {
    u_int bf_len;
    struct bpf_insn *bf_insns;}
"""
class bpf_program(ctypes.Structure):
    _fields_ = [("bf_len", ctypes.c_int),("bf_insns", ctypes.c_void_p)]

class sockaddr(ctypes.Structure):
    _fields_=[("sa_family",ctypes.c_uint16),("sa_data",ctypes.c_char*14)]

class pcap_pkthdr(ctypes.Structure):
    _fields_ = [("tv_sec", ctypes.c_long), ("tv_usec", ctypes.c_long), ("caplen", ctypes.c_uint), ("len", ctypes.c_uint)]

pcap_lookupdev = pcap.pcap_lookupdev
pcap_lookupdev.restype = ctypes.c_char_p
#pcap_lookupnet(dev, &net, &mask, errbuf)
pcap_lookupnet = pcap.pcap_lookupnet
#pcap_t *pcap_open_live(const char *device, int snaplen,int promisc, int to_ms, char *errbuf)
pcap_open_live = pcap.pcap_open_live
pcap_open_live.restype = ctypes.c_char_p
#int pcap_compile(pcap_t *p, struct bpf_program *fp,const char *str, int optimize, bpf_u_int32 netmask)
pcap_compile = pcap.pcap_compile
#int pcap_setfilter(pcap_t *p, struct bpf_program *fp)
pcap_setfilter = pcap.pcap_setfilter
#const u_char *pcap_next(pcap_t *p, struct pcap_pkthdr *h)
pcap_next = pcap.pcap_next

# prepare args
snaplen = ctypes.c_int(1540)
linktype = ctypes.c_int(12) # DLT_RAW on linux
program = bpf_program()
#buf = ctypes.c_char_p(filter)
optimize = ctypes.c_int(0)
mask = ctypes.c_int(0)

errbuf = ctypes.create_string_buffer(256)

dev = pcap_lookupdev(errbuf)
dev = bytes(str('en1'), 'ascii')

if(dev):
    print("{0} is the default interface".format(dev))
else:
    print("Was not able to find default interface {0}".format(errbuf.value))



mask = ctypes.c_uint(32)
net = ctypes.c_uint(32)

if(pcap_lookupnet(dev,ctypes.pointer(net),ctypes.pointer(mask),errbuf) == -1):
    print("Error could not get netmask for device {0}".format(errbuf.value))
    sys.exit(0)
else:
    print("Got Required netmask")



to_ms = ctypes.c_int(1000)
promisc = ctypes.c_int(1)
handle = pcap_open_live(dev,snaplen,promisc,to_ms,errbuf)

if(handle is False):
    print("Error unable to open session : {0}".format(errbuf.value))
    sys.exit(0)
else:
    print("Pcap open live worked!")


filter = bytes(str('port 80'), 'ascii')
buf = ctypes.c_char_p(filter)


if(pcap_compile(handle,ctypes.byref(program),buf,ctypes.c_int(1),mask) == -1):
    # this requires we call pcap_geterr() to get the error
    print("Error could not compile bpf filter because {0}".format(errbuf.value))
else:
    print("Filter Compiled!")


if(pcap_setfilter(handle,ctypes.byref(program) == -1)):
    print("Error couldn't install filter {0}".format(errbuf.value))
    sys.exit(0)
else:
    print("Filter installed!")


header = pcap_pkthdr()
if(pcap_next(handle,ctypes.bref(header)) == -1):
    print("ERROR pcap_next failed!")

print("Got {0} bytes of data".format(pcap_pkthdr().len))
pcap_close = pcap.pcap_close
pcap_close(handle)

For some reason when we get to pcap_compile() the system tries to look up one of the vmware interfaces instead of the value assigned to dev .. here is the output.

bash-3.2# ./libpcap.py 
b'en1' is the default interface
Got Required netmask
Pcap open live worked!
Error could not compile bpf filter because b'vmnet8: No such device exists (BIOCSETIF    failed: Device not configured)'
Bus error: 10

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

欢你一世 2024-12-13 11:53:33

这是不正确的:

if(handle is False):

ctypes 返回的 NULL 指针是 None。在Python中,习惯上只是说:

if not handle:

我怀疑句柄无效,因为dev的格式不正确。注意,在 Python 中,if 不需要括号。

顺便说一句:

bytes(str('string'), 'ascii')

可以简单地是:

b'string'

This is incorrect:

if(handle is False):

A NULL pointer returned from ctypes is None. In Python it is customary to just say:

if not handle:

I suspect handle is invalid because dev is not in the correct format. Note in Python parentheses are not required with if.

As an aside:

bytes(str('string'), 'ascii')

can simply be:

b'string'
_失温 2024-12-13 11:53:33
ctypes.cdll.LoadLibrary(find_library("pcap"))

在我的 ubuntu 16.04 上,find_library 失败,除非给出的名称不带“lib”前缀。

ctypes.cdll.LoadLibrary(find_library("pcap"))

On my ubuntu 16.04, find_library failed unless the name was given without the 'lib' prefix.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文