阅读:3024回复:0
Python教程网络安全篇
◆0:概述
本文从实例代码出发,讲解了Python在网络安全分析中的作用,以最基础的示例向读者展示了Python如何解析、发送、以及嗅探网络中的数据包 系统环境:kali 并且具备了scapy,由于涉及底层网络操作,文中的示例代码均为linux下可用,无法直接复制到windows下使用 ◆1:利用Python解析TCP数据包 以下面代码为例进行说明 图片:2014091812462971056.png 首先导入socket(用于网络编程)、struct(用于拆包解析数据包结构)、binascii(方便格式的转化) 创建socket时指定socket.SOCK_RAW以接收原始数据包 Pkt为获取到的数据包 Eth_hdr 为拆包得到的以太网头部,使用unpack解出(请见下图以太网帧格式) 以太网帧结构: 图片:2014091812462971056.png 我们可以看到解出的第一部分(目的地址)为080027bc6ecc 我们可以看到解出的第二部分(源地址)为525400123502 我们可以看到解出的第三部分(长度类型)为0800 图片来自网络,注意图中说的4字节VLAN是不存在的 - - 下面看看自己的mac(eth1) 为080027bc6ecc,与上文结论相符 图片:2014091812462971056.png 同理解出IP包头里的源IP和目的IP,如第一张图所示 IP包头结构: 图片:2014091812462971056.png 本节所用代码如下: #!python #!/usr/bin/python import socket import struct import binascii s=socket.socket(socket.PF_PACKET,socket.SOCK_RAW,socket.htons(◆800)) pkt = s.recvfrom(2048); ethernetHeader=pkt[0][0:14] eth_hdr = struct.unpack("!6s6s2s",ethernetHeader) binascii.hexlify(eth_hdr[0]) binascii.hexlify(eth_hdr[1]) binascii.hexlify(eth_hdr[2]) ipHeader = pkt[0][14:34] ip_hdr = struct.unpack("!12s4s4s",ipHeader) print "Source IP address:"+socket.inet_ntoa(ip_hdr[1]) print "Destination IP address:"+socket.inet_ntoa(ip_hdr[2]) tcpHeader = pkt[0][34:54] tcp_hdr = struct.unpack("!HH16s",tcpHeader) 本节示例输出如下: #!bash root@kali:~/Desktop/wooyunPython# ./◆1.py Source IP address:123.125.125.99 Destination IP address:10.0.3.15 root@kali:~/Desktop/wooyunPython# python Python 2.7.3 (default, Jan 2 2013, 13:56:14) [GCC 4.7.2] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> import socket >>> import struct >>> import binascii >>> s=socket.socket(socket.PF_PACKET,socket.SOCK_RAW,socket.htons(◆800)) >>> pkt = s.recvfrom(2048); >>> ethernetHeader=pkt[0][0:14] >>> eth_hdr = struct.unpack("!6s6s2s",ethernetHeader) >>> binascii.hexlify(eth_hdr[0]) '080027bc6ecc' >>> binascii.hexlify(eth_hdr[1]) '525400123502' >>> binascii.hexlify(eth_hdr[2]) '0800' >>> ipHeader = pkt[0][14:34] >>> ip_hdr = struct.unpack("!12s4s4s",ipHeader) >>> print "Source IP address:"+socket.inet_ntoa(ip_hdr[1]) Source IP address:123.125.125.99 >>> print "Destination IP address:"+socket.inet_ntoa(ip_hdr[2]) Destination IP address:10.0.3.15 >>> tcpHeader = pkt[0][34:54] >>> tcp_hdr = struct.unpack("!HH16s",tcpHeader) ◆2:利用Python发送TCP数据包 本文所用代码如下: #!python #!/usr/bin/python import socket import struct rawSocket = socket.socket(socket.PF_PACKET,socket.SOCK_RAW,socket.htons(◆800)) rawSocket.bind(("eth0",socket.htons(◆800))) packet = struct.pack("!6s6s2s",'xaaxaaxaaxaaxaaxaa','xbbxbbxbbxbbxbbxbb','x08x00') rawSocket.send(packet+"Hello there") 图片:2014091812462971056.png 首先socket类型选择raw,然后bind一个interface就可以发包了,由于发送的是原始的数据包,因此数据包需要自己通过struct.pack包装好 ◆3:利用Python+Scapy嗅探数据包 #!bash root@kali:~# scapy INFO: Can't import python gnuplot wrapper . Won't be able to plot. WARNING: No route found for IPv6 destination :: (no default route?) Welcome to Scapy (2.2.0) >>> ls() ARP : ARP 这里还列出了一大堆的介绍,就不列出了 #!bash >>> pkts = sniff(iface="eth1",count=3) 使用sniff监听eth1接口的3个数据包 #!bash >>> pkts 直接输入pkts会显示嗅探的概况 #!bash >>> pkts[0] >>> pkts[0].show() 使用show显示更详细 #!bash ###[ Ethernet ]### dst= 52:54:00:12:35:02 src= 08:00:27:bc:6e:cc type= 0x800 ###[ IP ]### version= 4L ihl= 5L tos= ◆ len= 116 id= 30377 flags= DF frag= 0L ttl= 64 proto= tcp chksum= 0xbdeb src= 10.0.3.15 dst= 123.125.125.99 options ###[ TCP ]### sport= 49157 dport= http seq= 2358039370 ack= 1044674792 dataofs= 5L reserved= 0L flags= PA window= 24120 chksum= 0x656 urgptr= 0 options= [] ###[ Raw ]### load= 'GET /web_ime/patch.php HTTP/1.1rnHost: web.pinyin.sogou.comrnAccept: */*rnrn' >>> >>> hexdump(pkts[1]) 转成十六进制形式更加亲切 #!bash 0000 08 00 27 BC 6E CC 52 54 00 12 35 02 08 00 45 00 ..'.n.RT..5...E. 0010 00 28 82 39 00 00 40 06 F2 A7 7B 7D 7D 63 0A 00 .(.9..@...{}}c.. 0020 03 0F 00 50 C0 05 3E 44 78 E8 8C 8C D3 96 50 10 ...P..>Dx.....P. 0030 FF FF D2 3F 00 00 00 00 00 00 00 00 ...?........ >>> >>> wrpcap("demo.pcap",pkts) 写出到pcap文件 #!bash >>> read_pkts=rdpcap("demo.pcap") 从pcap文件中读取 #!bash >>> read_pkts 检查发现读出与写入是一致的 #!bash >>> >>> pkts=sniff(iface="eth1",filter="icmp",count=3) 使用filter来过滤想要捕获的数据包类型 注意同时我另开一个shell做了一个ping来发送icmp包 #!bash root@kali:~# ping www.wooyun.org PING wooyun.sinaapp.com (220.181.136.24) 56(84) bytes of data. 64 bytes from 220.181.136.24: icmp_req=1 ttl=54 time=17.1 ms 64 bytes from 220.181.136.24: icmp_req=3 ttl=54 time=11.8 ms 64 bytes from 220.181.136.24: icmp_req=4 ttl=54 time=23.8 ms 64 bytes from 220.181.136.24: icmp_req=5 ttl=54 time=17.1 ms 64 bytes from 220.181.136.24: icmp_req=6 ttl=54 time=5.63 ms ^C --- wooyun.sinaapp.com ping statistics --- 6 packets transmitted, 5 received, 16% packet loss, time 5013ms rtt min/avg/max/mdev = 5.636/15.135/23.824/6.086 ms >>> pkts 发现截获的通过filter果然都是icmp包 #!bash >>> >>> pkts[0] >> recon=Ether(icmp_str) 从str重构数据包 #!bash >>> recon |
|