xyzjr 发表于 2015-4-23 08:49:49

使用python扩展编写网络发包程序

  首先,使用C编写模块psnd,如下,将其放入某个目录下,如sendpacket。


psnd.c



1 #include
2
3#include
4 #include
5
6#include
7 #include
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;
17   
18   /* Retrieve the device list from the local machine */
19   if (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 */
26   for(d= alldevs; d != NULL; d= d->next)
27   {
28         printf("%d. %s", ++i, d->name);
29         if (d->description)
30             printf(" (%s)\n", d->description);
31         else
32             printf(" (No description available)\n");
33   }
34   
35   if (i == 0)
36   {
37         printf("\nNo interfaces found! Make sure WinPcap is installed.\n");
38         return NULL;
39   }
40
41   /* We don't need any more the device list. Free it */
42      pcap_freealldevs(alldevs);
43   
44   return Py_BuildValue("i",0);
45 }
46
47
48 static PyObject *open_device(PyObject *self, PyObject *args)
49 {
50   const char *name;
51   char errbuf;
52   
53   if (! PyArg_ParseTuple(args, "s", &name))
54         return NULL;
55   /* Open the output device */
56   if ( (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);
65         return NULL;
66   }
67   return Py_BuildValue("i",0);
68 }
69
70
71 static PyObject *send_packet(PyObject *self, PyObject *args)
72 {
73   int len = 0;
74   const char *pEth = NULL;
75   
76   int ret,i,j,k = 0;
77
78   if (! PyArg_ParseTuple(args, "s#", &pEth,&len)){
79         printf("Parse arge error,pEth = %p,len = %d\n",pEth,len);
80         return NULL;
81   }
82//    if(!gfp){
83//      fprintf(stderr,"\nInvalid fp,check if device have been opened");
84//      return NULL;
85//    }
86   assert(gfp);
87#if 0   
88      for(i = len; i > 16; i -= 16){
89         for(j = 0; j < 16; j++)
90             fprintf(stderr,"%02x ",(u_char)pEth);
91         fprintf(stderr,"\n");
92   }
93   for(; i > 0; i--)
94         fprintf(stderr,"%02x ",(u_char)pEth);
95 #endif
96   /* Send down the packet */
97   ret = pcap_sendpacket(gfp, pEth, len /* size */);
98   if (ret != 0)
99   {
100         fprintf(stderr,"\nError sending the packet: \n", pcap_geterr(gfp));
101         return NULL;
102   }
103
104   return 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:
            dirs = glob.glob( 'c:/wpdpack*' )
...
psnd = Extension('psnd',
               sources = ['psnd.c'],
               include_dirs = pcap_config.get( 'include_dirs', '' ),
               library_dirs = pcap_config.get( 'library_dirs', '' ),
               libraries = pcap_config.get( 'libraries', '' ),
               extra_compile_args = pcap_config.get( '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 = )
  脚本中c:/wpdpack*指pcap软件包的安装目录。在命令行下执行该脚本,脚本生成好的python模块psnd.pyd在build\lib.win32-2.5目录(根据python版本有不同)下,将其拷贝到C:\Python25\Lib\site-packages(根据python安装目录有不同)下。
  

三,安装一个网络协议数据包封装模块dpkt,然后就可以直接用python编写发包程序了,如下示例代码,其中name取了自己的网卡名:



send_packet.py



1 import sys
2 import socket
3 import random,getopt
4 import signal
5 import time
6 import 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
14 def sendPacket(data,protocol,ip_list):
15   ip = dpkt.ip.IP(id=0, src=ip_list,
16                     dst=ip_list,
17                     p=protocol)
18   ip.data = data
19   ip.len += len(data)
20   
21   eth = dpkt.ethernet.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
27 def handler(signo, frame):
28   stop = True
29   print "time used ", time.time() - now, " seconds,","send number ",count
30   
31
32 if __name__ == '__main__':   
33   opts, args = getopt.getopt(sys.argv, '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
39   for o,v in opts:
40         if o in ("-i","--ip"):
41             ip_range = int(v)
42         elif o in ("-p","--port"):
43             port_range = int(v)
44         elif 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 = []
54   for i in range(ip_range):
55         rip = ''
56         for 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:
62   for 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 = dpkt.tcp.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         
73         print dpkt.dpkt.hexdump(t.pack())
74         #sendPacket(u,dpkt.ip.IP_PROTO_UDP,ip_list)
75         #sendPacket(t,dpkt.ip.IP_PROTO_TCP,ip_list)
76         count += 2
  
  
页: [1]
查看完整版本: 使用python扩展编写网络发包程序