Python tutorial Network Security
0x00: overview
This document describes the role of Python in network security analysis based on the instance code. It provides the following basic examples to show you how to parse, send, and sniff the data packet system environment in the network: kali and scapy are available. Due to underlying network operations, the sample code in this article is available in linux and cannot be directly copied to windows for use.
0x01: parse TCP data packets using Python
The following code is used as an example.
First, import socket (for Network Programming), struct (for packet splitting and parsing packet structure), binascii (for easy format conversion)
Specify socket. SOCK_RAW when creating a socket to receive the original data packet
Pkt is the obtained data packet.
Eth_hdr is the Ethernet header obtained by unpacking and is unpacked (see Ethernet frame format)
Ethernet frame structure:
We can see that the first part (Destination Address) is 080027bc6ecc. We can see that the second part (Source Address) is 525400123502. We can see the third part (length \ type) the figure 0800 is from the network. Note that the 4-byte VLAN in the figure does not exist --
Next, let's take a look at your mac (eth1) as 080027bc6ecc, which is consistent with the conclusion above.
Solve the source IP address and destination IP address in the IP Address Header, as shown in the first figure.
IP header structure:
The code used in this section is as follows:
#!/usr/bin/pythonimport socketimport structimport binasciis=socket.socket(socket.PF_PACKET,socket.SOCK_RAW,socket.htons(0x0800))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)
The sample output in this section is as follows:
root@kali:~/Desktop/wooyunPython# ./0x01.pySource IP address:123.125.125.99Destination IP address:10.0.3.15root@kali:~/Desktop/wooyunPython# pythonPython 2.7.3 (default, Jan 2 2013, 13:56:14)[GCC 4.7.2] on linux2Type "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(0x0800))>>> 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)
0x02: Send TCP data packets using Python
The code used in this article is as follows:
#!/usr/bin/pythonimport socketimport structrawSocket = socket.socket(socket.PF_PACKET,socket.SOCK_RAW,socket.htons(0x0800))rawSocket.bind(("eth0",socket.htons(0x0800)))packet = struct.pack("!6s6s2s",'\xaa\xaa\xaa\xaa\xaa\xaa','\xbb\xbb\xbb\xbb\xbb\xbb','\x08\x00')rawSocket.send(packet+"Hello there")
First, select raw for the socket type, and then bind an interface to send packets. Because raw data packets are sent, the data packets must be packed by struct. pack.
0x03: Use Python + Scapy to sniff data packets
root@kali:~# scapyINFO: 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
A lot of introductions are also listed here, so they will not be listed.
>>> pkts = sniff(iface="eth1",count=3)
Use sniff to listen to three data packets of the eth1 Interface
>>> pkts<Sniffed: TCP:3 UDP:0 ICMP:0 Other:0>
Directly input pkts to display the sniffing Overview
>>> pkts[0]<Ether dst=52:54:00:12:35:02 src=08:00:27:bc:6e:cc type=0x800 |<IP version=4L ihl=5L tos=0x0 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.1\r\nHost: web.pinyin.sogou.com\r\nAccept: */*\r\n\r\n' |>>>>>>> pkts[0].show()
Show more details
###[ Ethernet ]### dst= 52:54:00:12:35:02 src= 08:00:27:bc:6e:cc type= 0x800###[ IP ]### version= 4L ihl= 5L tos= 0x0 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.1\r\nHost: web.pinyin.sogou.com\r\nAccept: */*\r\n\r\n'>>>>>> hexdump(pkts[1])
Convert to hexadecimal format more friendly
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)
Write to pcap File
>>> read_pkts=rdpcap(
"demo.pcap")
Read from pcap File
>>> read_pkts<demo.pcap: TCP:3 UDP:0 ICMP:0 Other:0>
Check that the read and write operations are consistent.
>>>>>> pkts=sniff(iface="eth1",filter="icmp",count=3)
Filter is used to filter the data packet types to be captured.
Note that at the same time, I opened another shell and ping it to send the icmp packet.
root@kali:~# ping www.wooyun.orgPING 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 ms64 bytes from 220.181.136.24: icmp_req=3 ttl=54 time=11.8 ms64 bytes from 220.181.136.24: icmp_req=4 ttl=54 time=23.8 ms64 bytes from 220.181.136.24: icmp_req=5 ttl=54 time=17.1 ms64 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 5013msrtt min/avg/max/mdev = 5.636/15.135/23.824/6.086 ms>>> pkts<Sniffed: TCP:0 UDP:0 ICMP:3 Other:0>
All the intercepted filters are icmp packets.
>>>>>> pkts[0]<Ether dst=52:54:00:12:35:02 src=08:00:27:bc:6e:cc type=0x800 |<IP version=4L ihl=5L tos=0x0 len=84 id=0 flags=DF frag=0L ttl=64 proto=icmp chksum=0xc8cc src=10.0.3.15 dst=220.181.136.24 options=[] |<ICMP type=echo-request code=0 chksum=0xd856 id=0x218e seq=0x1 |<Raw load='\xcc\xa7\xc3S\x00\x00\x00\x00\xa2K\r\x00\x00\x00\x00\x00\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !"#$%&\'()*+,-./01234567' |>>>>>>> pkts[1]<Ether dst=08:00:27:bc:6e:cc src=52:54:00:12:35:02 type=0x800 |<IP version=4L ihl=5L tos=0x1 len=84 id=33433 flags= frag=0L ttl=54 proto=icmp chksum=0x9032 src=220.181.136.24 dst=10.0.3.15 options=[] |<ICMP type=echo-reply code=0 chksum=0xe056 id=0x218e seq=0x1 |<Raw load='\xcc\xa7\xc3S\x00\x00\x00\x00\xa2K\r\x00\x00\x00\x00\x00\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !"#$%&\'()*+,-./01234567' |>>>>>>>>>> icmp_str=str(pkts[0])
Convert to str
>>> icmp_str'RT\x00\x125\x02\x08\x00\'\xbcn\xcc\x08\x00E\x00\x00T\x00\x00@\x00@\x01\xc8\xcc\n\x00\x03\x0f\xdc\xb5\x88\x18\x08\x00\xd8V!\x8e\x00\x01\xcc\xa7\xc3S\x00\x00\x00\x00\xa2K\r\x00\x00\x00\x00\x00\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !"#$%&\'()*+,-./01234567'>>> recon=Ether(icmp_str)
Refactored data packets from str
>>> recon<Ether dst=52:54:00:12:35:02 src=08:00:27:bc:6e:cc type=0x800 |<IP version=4L ihl=5L tos=0x0 len=84 id=0 flags=DF frag=0L ttl=64 proto=icmp chksum=0xc8cc src=10.0.3.15 dst=220.181.136.24 options=[] |<ICMP type=echo-request code=0 chksum=0xd856 id=0x218e seq=0x1 |<Raw load='\xcc\xa7\xc3S\x00\x00\x00\x00\xa2K\r\x00\x00\x00\x00\x00\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !"#$%&\'()*+,-./01234567' |>>>>>>> export_object(icmp_str)eNprYApNCgphEDJl4mBQ35N3hoPBlYEhhIHBgcGB8cQZLgZm/jtbOyQ4GG6EKfYxMJ5ZfjiYAQgWefOCKAYBQSFhEVExcQlJKWkZWTl5BUUlZRVVNXUNTS1tHV09fQNDI2MTUzPzQkY9AMQIFOY=
Export readable base64 objects
>>> newPkt=import_object()eNprYApNCgphEDJl4mBQ35N3hoPBlYEhhIHBgcGB8cQZLgZm/jtbOyQ4GG6EKfYxMJ5ZfjiYAQgWefOCKAYBQSFhEVExcQlJKWkZWTl5BUUlZRVVNXUNTS1tHV09fQNDI2MTUzPzQkY9AMQIFOY=
After the input is complete, press (ctrl + D) to end the input and read the object back from base64.
>>> newPkt'RT\x00\x125\x02\x08\x00\'\xbcn\xcc\x08\x00E\x00\x00T\x00\x00@\x00@\x01\xc8\xcc\n\x00\x03\x0f\xdc\xb5\x88\x18\x08\x00\xd8V!\x8e\x00\x01\xcc\xa7\xc3S\x00\x00\x00\x00\xa2K\r\x00\x00\x00\x00\x00\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !"#$%&\'()*+,-./01234567'>>> Ether(newPkt)<Ether dst=52:54:00:12:35:02 src=08:00:27:bc:6e:cc type=0x800 |<IP version=4L ihl=5L tos=0x0 len=84 id=0 flags=DF frag=0L ttl=64 proto=icmp chksum=0xc8cc src=10.0.3.15 dst=220.181.136.24 options=[] |<ICMP type=echo-request code=0 chksum=0xd856 id=0x218e seq=0x1 |<Raw load='\xcc\xa7\xc3S\x00\x00\x00\x00\xa2K\r\x00\x00\x00\x00\x00\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !"#$%&\'()*+,-./01234567' |>>>>
At this point, we have successfully returned the exported data packet.
>>>
The next step is to use scapy to send data packets.
First, Ether/ARP constructs an ARP packet, and then srp1 sends it out. From wireshark, we can see that the packet has been successfully sent, but in theory we can receive response, not received for unknown reasons during testing
root@kali:~# scapyINFO: 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)>>> from scapy.all import *>>> pkt=Ether(dst="ff:ff:ff:ff:ff:ff")/ARP(pdst='192.168.1.3',hwdst="ff:ff:ff:ff:ff:ff")>>> pkt<Ether dst=ff:ff:ff:ff:ff:ff type=0x806 |<ARP hwdst=ff:ff:ff:ff:ff:ff pdst=192.168.1.3 |>>>>> pkt.show()###[ Ethernet ]### dst= ff:ff:ff:ff:ff:ff src= 00:00:00:00:00:00 type= 0x806###[ ARP ]### hwtype= 0x1 ptype= 0x800 hwlen= 6 plen= 4 op= who-has hwsrc= 00:00:00:00:00:00 psrc= 192.168.1.3 hwdst= ff:ff:ff:ff:ff:ff pdst= 192.168.1.3>>> srp1(pkt)Begin emission:Finished to send 1 packets...............................................................................^CReceived 78 packets, got 0 answers, remaining 1 packets>>>