使⽤python扩展编写⽹络发包程序⾸先,使⽤C编写模块psnd,如下,将其放⼊某个⽬录下,如sendpacket。
psnd.c
1#include <Python.h>
2
3#include <pcap.h>
4#include <remote-ext.h>
5
6#include <stdlib.h>
7#include <stdio.h>
8
9 static pcap_t *gfp;
10
11 static PyObject *list_device(PyObject *self, PyObject *args)
12 {
13    pcap_if_t *alldevs;
14    pcap_if_t *d;
15    int i=0;
16    char errbuf[PCAP_ERRBUF_SIZE];
17
18    /* Retrieve the device list from the local machine */
19if (pcap_findalldevs_ex(PCAP_SRC_IF_STRING, NULL /* auth is not needed */, &alldevs, errbuf) == -1)
20    {
21        fprintf(stderr,"Error in pcap_findalldevs_ex: %s\n", errbuf);
22        exit(1);
23    }
24
25    /* Print the list */
26for(d= alldevs; d != NULL; d= d->next)
27    {
28        printf("%d. %s", ++i, d->name);
29if (d->description)
30            printf(" (%s)\n", d->description);
31else
32            printf(" (No description available)\n");
33    }
34
35if (i == 0)
36    {
37        printf("\nNo interfaces found! Make sure WinPcap is installed.\n");
38return NULL;
39    }
40
41    /* We don't need any more the device list. Free it */
42    pcap_freealldevs(alldevs);
43
44return Py_BuildValue("i",0);
45 }
46
47
48 static PyObject *open_device(PyObject *self, PyObject *args)
49 {
50    const char *name;
51    char errbuf[PCAP_ERRBUF_SIZE];
52
53if (! PyArg_ParseTuple(args, "s", &name))
54return NULL;
55    /* Open the output device */
56if ( (gfp= pcap_open(name,            // name of the device
57                        100,                // portion of the packet to capture (only the first 100 bytes)
58                        PCAP_OPENFLAG_PROMISCUOUS,  // promiscuous mode
59                        1000,              // read timeout
60                        NULL,              // authentication on the remote machine
61                        errbuf              // error buffer
62                        ) ) == NULL)
63    {
64        fprintf(stderr,"\nUnable to open the adapter. %s is not supported by WinPcap\n", name);
65return NULL;
66    }
67return Py_BuildValue("i",0);
68 }
69
70
71 static PyObject *send_packet(PyObject *self, PyObject *args)
72 {
73    int len = 0;
77
78if (! PyArg_ParseTuple(args, "s#", &pEth,&len)){
79        printf("Parse arge error,pEth = %p,len = %d\n",pEth,len);
80return NULL;
81    }
82  //    if(!gfp){
83  //        fprintf(stderr,"\nInvalid fp,check if device have been opened");
84  //        return NULL;
85  //    }
86assert(gfp);
87#if 0
88for(i = len; i > 16; i -= 16){
89for(j = 0; j < 16; j++)
90            fprintf(stderr,"%02x ",(u_char)pEth[k++]);
91        fprintf(stderr,"\n");
92    }
93for(; i > 0; i--)
94        fprintf(stderr,"%02x ",(u_char)pEth[k++]);
95#endif
96    /* Send down the packet */
97    ret = pcap_sendpacket(gfp, pEth, len /* size */);
98if (ret != 0)
99    {
100        fprintf(stderr,"\nError sending the packet: \n", pcap_geterr(gfp));
101return NULL;
102    }
103
104return Py_BuildValue("i",ret);
105 }
106
107 static PyMethodDef sendPacketMethods[] =
108 {
109    {"list_device",  list_device, METH_VARARGS, "list all devices."},
110    {"open_device",  open_device, METH_VARARGS, "open the specific device."},
111    {"send_packet",  send_packet, METH_VARARGS, "send packet use mehtod in winpcap."},
112    {NULL, NULL, 0, NULL}
113 };
114
115 PyMODINIT_FUNC initpsnd()
116 {
117    Py_InitModule("psnd", sendPacketMethods);
118 }
⼆,定义⼀个安装脚本,我们使⽤pcap的setup.py改写,改变地⽅如下,同样放⼊sendpacket⽬录下。
setup.py
...
def _pcap_config( self, dirs = [ None ] ):
cfg = {}
if not dirs[0]:
dirs = glob.glob( 'c:/wpdpack*' )
...
psnd = Extension('psnd',
sources = ['psnd.c'],
include_dirs = ( 'include_dirs', '' ),
library_dirs = ( 'library_dirs', '' ),
libraries = ( 'libraries', '' ),
extra_compile_args = ( 'extra_compile_args', '' ))
pcap_cmds = { 'config':config_pcap, 'clean':clean_pcap, 'test': test_pcap}
setup (name = 'psnd',
version = '1.0',
description = 'This is a winpcap send package',
cmdclass = pcap_cmds,
ext_modules = [psnd])
脚本中c:/wpdpack*指pcap软件包的安装⽬录。在命令⾏下执⾏该脚本,脚本⽣成好的python模块psnd.pyd在build\lib.win32-2.5⽬录(根据python版本有不同)下,将其拷贝到C:\Python25\Lib\site-packages(根据python安装⽬录有不同)下。
三,安装⼀个⽹络协议数据包封装模块dpkt,然后就可以直接⽤python编写发包程序了,如下⽰例代码,其中name取了⾃⼰的⽹卡名:
send_packet.py
1import sys
2import socket
3import random,getopt
4import signal
5import time
6import psnd,dpkt
7
8 name = "rpcap://\Device\NPF_{41BF634C-A329-467C-8138-70537490C47A}"
9
10 stop = False
11 now = time.time()
12 count = 0
13
14def sendPacket(data,protocol,ip_list):
15    ip = dpkt.ip.IP(id=0, src=ip_list[random.randint(0,ip_range - 1)],
16                    dst=ip_list[random.randint(0,ip_range - 1)],
17                    p=protocol)
18    ip.data = data
19    ip.len += len(data)
20
21    eth = hernet.Ethernet(dst='\x00\x2B\xB9\xF2\x82\xEC',src='\x00\xd0\xd0\xc5\x49\x1b')
22    eth.data = ip
23
24#print dpkt.dpkt.hexdump(eth.pack())
25    psnd.send_packet(eth.pack())
26
27def handler(signo, frame):
28    stop = True
29print"time used ", time.time() - now, " seconds,","send number ",count
30
31
32if__name__ == '__main__':
33    opts, args = pt(sys.argv[1:], 'i:p:r:',["ip=","port=","prot="])
34
35    signal.signal(signal.SIGINT, handler)
36
37    ip_range ,port_range ,protocol_range = 10,10,10
38
39for o,v in opts:
40if o in ("-i","--ip"):
41            ip_range = int(v)
42elif o in ("-p","--port"):
43            port_range = int(v)
44elif o in ("-r","--prot"):
45            protocol_range = int(v)
46
47    psnd.list_device()
48    psnd.open_device(name)
49
50    n = raw_input("\nchose your network interface:")
51
52#generate ip list
53    ip_list = []
54for i in range(ip_range):
55        rip = ''
56for j in range(4):
57            rip += chr(random.randint(1,255))
58        ip_list.append(rip)
59
60    now = time.time()
61#while not stop:
62for i in range(3):
63        u = dpkt.udp.UDP(sport=random.randint(1,port_range),
64                          dport=random.randint(1,port_range))
65        u.data = 'hello world'
66        u.ulen += len(u.data)
67
68        t = p.TCP(sport=random.randint(1,port_range),
69                          dport=random.randint(1,port_range),
70                          flags=random.randint(1,255))
71        t.data = 'how are you?'
72
73print dpkt.dpkt.hexdump(t.pack())
python printf输出格式74#sendPacket(u,dpkt.ip.IP_PROTO_UDP,ip_list)
75#sendPacket(t,dpkt.ip.IP_PROTO_TCP,ip_list)
76        count += 2