<span id="7ztzv"></span>
<sub id="7ztzv"></sub>

<span id="7ztzv"></span><form id="7ztzv"></form>

<span id="7ztzv"></span>

        <address id="7ztzv"></address>

            原文地址:http://drops.wooyun.org/tips/2568

            0x00:概述


            本文從實例代碼出發,講解了Python在網絡安全分析中的作用,以最基礎的示例向讀者展示了Python如何解析、發送、以及嗅探網絡中的數據包 系統環境:kali 并且具備了scapy,由于涉及底層網絡操作,文中的示例代碼均為linux下可用,無法直接復制到windows下使用

            0x01:利用Python解析TCP數據包


            以下面代碼為例進行說明

            enter image description here

            首先導入socket(用于網絡編程)、struct(用于拆包解析數據包結構)、binascii(方便格式的轉化)

            創建socket時指定socket.SOCK_RAW以接收原始數據包

            Pkt為獲取到的數據包

            Eth_hdr 為拆包得到的以太網頭部,使用unpack解出(請見下圖以太網幀格式)

            以太網幀結構:

            enter image description here

            我們可以看到解出的第一部分(目的地址)為080027bc6ecc 我們可以看到解出的第二部分(源地址)為525400123502 我們可以看到解出的第三部分(長度\類型)為0800 圖片來自網絡,注意圖中說的4字節VLAN是不存在的 - -

            下面看看自己的mac(eth1) 為080027bc6ecc,與上文結論相符

            enter image description here

            同理解出IP包頭里的源IP和目的IP,如第一張圖所示

            IP包頭結構:

            enter image description here

            本節所用代碼如下:

            #!python
            #!/usr/bin/python
            
            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])
            
            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
            [email protected]:~/Desktop/wooyunPython# ./0x01.py
            Source IP address:123.125.125.99
            Destination IP address:10.0.3.15
            [email protected]:~/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(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:利用Python發送TCP數據包


            本文所用代碼如下:

            #!python
            #!/usr/bin/python
            
            import socket
            import struct
            
            rawSocket = 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")
            

            enter image description here

            首先socket類型選擇raw,然后bind一個interface就可以發包了,由于發送的是原始的數據包,因此數據包需要自己通過struct.pack包裝好

            0x03:利用Python+Scapy嗅探數據包


            #!bash
            [email protected]:~# 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
            <Sniffed: TCP:3 UDP:0 ICMP:0 Other:0>
            

            直接輸入pkts會顯示嗅探的概況

            #!bash
            >>> 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顯示更詳細

            #!bash
            ###[ 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])
            

            轉成十六進制形式更加親切

            #!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
            <demo.pcap: TCP:3 UDP:0 ICMP:0 Other:0>
            

            檢查發現讀出與寫入是一致的

            #!bash
            >>> 
            
            >>> pkts=sniff(iface="eth1",filter="icmp",count=3)
            

            使用filter來過濾想要捕獲的數據包類型

            注意同時我另開一個shell做了一個ping來發送icmp包

            #!bash
            [email protected]:~# 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
            <Sniffed: TCP:0 UDP:0 ICMP:3 Other:0>
            

            發現截獲的通過filter果然都是icmp包

            #!bash
            >>> 
            >>> 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])
            

            轉成str

            #!bash
            >>> 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)
            

            從str重構數據包

            #!bash
            >>> 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/jtbOyQ4GG6EKfYxMJ5ZfjiYAQgW
            efOCKAYBQSFhEVExcQlJKWkZWTl5BUUlZRVVNXUNTS1tHV09fQNDI2MTUzPzQkY9AMQIFOY=
            

            導出可讀base64對象

            #!bash
            >>> newPkt=import_object()
            eNprYApNCgphEDJl4mBQ35N3hoPBlYEhhIHBgcGB8cQZLgZm/jtbOyQ4GG6EKfYxMJ5ZfjiYAQgW
            efOCKAYBQSFhEVExcQlJKWkZWTl5BUUlZRVVNXUNTS1tHV09fQNDI2MTUzPzQkY9AMQIFOY=
            

            輸入完成后按(ctrl+D)結束輸入 從base64中讀回對象

            #!bash
            >>> 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' |>>>>
            

            到此我們成功原路返回了導出的數據包

            >>>
            

            接下來就是利用scapy發送數據包了

            enter image description here

            首先Ether/ARP構造一個ARP數據包,之后srp1發送出去,從wireshark中看發現數據包已經成功發送了,不過在這里理論上是可以收到response的,測試時由于不明原因沒有收到

            #!bash
            [email protected]:~# 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)
            >>> 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.
            ..............................................................................^C
            Received 78 packets, got 0 answers, remaining 1 packets
            >>>
            

            <span id="7ztzv"></span>
            <sub id="7ztzv"></sub>

            <span id="7ztzv"></span><form id="7ztzv"></form>

            <span id="7ztzv"></span>

                  <address id="7ztzv"></address>

                      亚洲欧美在线