使用python为Wireshark捕获添加协议

时间:2016-03-20 13:38:27

标签: python wireshark encapsulation pcap

在过去的几年里,我一直在使用Wireshark成功捕获和分析网络流量样本。然后,我通常需要通过将其封装在GTP层中来修改此捕获文件,以便我可以使用专有工具对pcap进行后期处理。我总是在Linux环境中使用python脚本成功地实现了这一点,使用类似

之类的东西添加“固定”GTP前往每个TCP / UDP数据包
import sys
import dpkt
from dpkt.ip import IP
from dpkt.udp import UDP
from optparse import OptionParser
import struct
import socket
# from pcapy import *

ETHERNET_SRC = "\x01\x02\x03\x04\x05\x06"
ETHERNET_DST = "\xA1\xA2\xA3\xA4\xA5\xA6"

GGSN_IP_SRC= "\xd5\xe9\x82\x38"      #"213.233.130.56"
GGSN_IP_DST= "\xd5\xe9\x82\x37"      #"213.233.130.55"

userip = None
global_userip = "\x0a\x44\x17\x5b"
total_packets_writes = 0
pcap_writer = None

# pcap file pid383_session1_272017012778276.pcap is on the Destkop

# GTP HEADER FOR CREATE PDP CONTEXT

# TID \x84\xba\x40\x11 for downstream
# TID 81fbe032 for upstream 
# ip client 0a 44 17 5b 

gtp_pdp_context_request = "\x32\x10\x00\xa1\x00\x00\x00\x00\x20\xac\x00\x00\x02\x72\x02\x71"\
    "\x10\x72\x87\x72\xf6\x0f\xfc\x10\x84\xba\x40\x11\x11\x80\xce\x00"\
    "\x11\x14\x0a\x80\x00\x02\xf1\x21\x83\x00\x15\x05\x74\x65\x73\x74"\
    "\x31\x02\x68\x73\x08\x76\x6f\x64\x61\x66\x6f\x6e\x65\x02\x69\x65"\
    "\x84\x00\x1d\x80\xc0\x23\x06\x01\x06\x00\x06\x00\x00\x80\x21\x10"\
    "\x01\x01\x00\x10\x81\x06\x00\x00\x00\x00\x83\x06\x00\x00\x00\x00"\
    "\x85\x00\x04\xd5\xe9\x82\x38\x85\x00\x04\xd5\xe9\x82\x38\x86\x00"\
    "\x07\x91\x53\x83\x97\x23\x75\x33\x87\x00\x0f\x02\x22\x92\x1f\x93"\
    "\x96\xfe\xfe\x74\x05\x01\x01\x00\x4f\x00\x97\x00\x01\x01\x98\x00"\
    "\x08\x01\x72\xf2\x10\x0b\xcc\xcc\x65\x99\x00\x02\x40\x01\x9a\x00"\
    "\x08\x53\x88\x85\x40\x19\x74\x27\x50"


gtp_pdp_context_response="\x32\x11\x00\x57\x80\xce\x00\x11\x20\xac\x00\x00\x01\x80\x08\xfe"\
    "\x10\x81\xfb\xe0\x32\x11\x95\xca\x80\x32\x7f\x10\x9b\xfb\x08\x80"\
    "\x00\x06\xf1\x21"   "\x0a\x44\x17\x5b"     "\x84\x00\x14\x80\x80\x21\x10\x03"\
    "\x01\x00\x10\x81\x06\x59\x13\x40\xa4\x83\x06\x59\x13\x40\x24\x85"\
    "\x00\x04\xd5\xe9\x82\x37\x85\x00\x04\xd5\xe9\x82\x37\x87\x00\x0f"\
    "\x02\x22\x92\x1f\x93\x96\xfe\xfe\x74\x05\x01\x01\x00\x4f\x00"


gtp_pdp_user_data_up = "\x30\xff\x00\x3c\x81\xfb\xe0\x32"
gtp_pdp_user_data_down = "\x30\xff\x00\x3c\x80\xce\x00\x11"


# GTP HEADER FOR PDP UPDATE
"""
0000   32 12 00 3f 95 ca 80 32 20 ad 00 00 10 84 ba 40
0010   11 14 0a 85 00 04 d5 e9 82 38 85 00 04 d5 e9 82
0020   38 87 00 0f 02 22 92 1f 93 96 fe fe 74 05 01 01
0030   00 4a 00 97 00 01 01 98 00 08 01 72 f2 10 0b cc
0040   cc 65 99 00 02 40 01"""

def parseOptions():
        """Parse the user options"""

        usage = "Usage: %prog [options]"

        p = OptionParser(usage)

        p.add_option("-f", "--pcapfile", dest="pcapfile", 
                help="Pcapfile for add the GTP header.")

        p.add_option("-i", "--userip", dest="userip", 
                help="User IP address.")

        p.add_option("-r", "--remove", dest="remove",action="store_true", 
                help="Remove the GTP layer.")

        p.add_option("-v", "--verbose",action="count",dest="verbose",default=0,
                help="Shows extra information.")
        return p


def generatePdpContextRequest(w):
    eth = dpkt.ethernet.Ethernet(src=ETHERNET_SRC,dst=ETHERNET_DST)
    udp = UDP(sport=1024, dport=2123,data = gtp_pdp_context_request)
    ip = IP(src=GGSN_IP_SRC,dst=GGSN_IP_DST, data = udp)

    ip.p = 17 
    ip.data = udp
    ip.len = 8 + 20 + len(gtp_pdp_context_request) 
    udp.ulen = 8 + len(gtp_pdp_context_request)
    eth.data = ip

    w.writepkt(eth)

def generatePdpContextResponse(w):
        eth = dpkt.ethernet.Ethernet(src=ETHERNET_DST,dst=ETHERNET_SRC)
        udp = UDP(sport=2123, dport=1024,data = gtp_pdp_context_response)
        ip = IP(src=GGSN_IP_DST,dst=GGSN_IP_SRC,data=udp)
        #ip = IP (dst='\x01\x02\x03\x04', src='\x05\x06\x07\x08',data = udp)

        ip.p = 17
        ip.data = udp
        ip.len = 8 + 20 + len(gtp_pdp_context_response)
        udp.ulen = 8 + len(gtp_pdp_context_response)
        eth.data = ip

        w.writepkt(eth)

def generateUserData(w,isUp,length,data):

    if(isUp):
        srceth= ETHERNET_SRC
        dsteth= ETHERNET_DST
        srcip = GGSN_IP_SRC
        dstip = GGSN_IP_DST
        gtp_header = "\x30\xff" + struct.pack(">h",length) + "\x81\xfb\xe0\x32" 
        srcport = 1024
        dstport = 2152
    else:
        srceth= ETHERNET_DST
        dsteth= ETHERNET_SRC
        srcip = GGSN_IP_DST
        dstip = GGSN_IP_SRC
        gtp_header = "\x30\xff" + struct.pack(">h",length) + "\x84\xba\x40\x11"
        srcport = 2152 
        dstport = 1024 

    f_data = gtp_header + data
    f_length = 8 + length

    udp = UDP(sport = srcport,dport=dstport,data=f_data)
    ip = IP(src=srcip,dst=dstip,data = udp)
    eth = dpkt.ethernet.Ethernet(src=srceth,dst=dsteth,data = ip)

    ip.p = 17
    ip.len = 20 + 8+ f_length
    udp.ulen = 8 + f_length

    w.writepkt(eth) 

def processPcapFile(filename):

    total_packets = 0
    total_packets_writes = 0
    total_packets_nowrites = 0
    total_bogus_packets = 0

    pcap=dpkt.pcap.Reader(file(filename,"rb"))

    try:
        for ts, buf in pcap:
            total_packets += 1
            if pcap.datalink() == dpkt.pcap.DLT_LINUX_SLL:
                l2 = dpkt.sll.SLL(buf)
                else:
                l2 = dpkt.ethernet.Ethernet(buf)

            raw_data = l2.data

            if (str(type(l2.data)) != "<class 'dpkt.ip.IP'>"):
                """ Check for other types of encapsulation """
                if (str(type(l2.data)) == "<class 'dpkt.pppoe.PPPoE'>"):
                    raw_data = l2.data.ppp.ip 
                else:   
                    total_bogus_packets += 1
                    continue

            ip = raw_data 

            if(socket.inet_ntoa(ip.src) == userip):
                direction = True
                newip = IP(src=global_userip,dst=ip.dst,p=ip.p,len=ip.len,data=ip.data)
                generateUserData(pcap_writer,direction,ip.len,str(newip))   
                total_packets_writes += 1
            elif(socket.inet_ntoa(ip.dst) == userip):
                direction = False
                total_packets_writes += 1
                newip = IP(src=ip.src,dst=global_userip,p=ip.p,len=ip.len,data=ip.data)
                generateUserData(pcap_writer,direction,ip.len,str(newip))   
            else:
                total_packets_nowrites += 1
    except:
        e = sys.exc_info()[0]
            print("ERROR during processing packets:",e, " packet:",total_packets)

    print "Total bogus packets>:", total_bogus_packets
    print "Total user packets writes:",total_packets_writes
    print "Total nonuser packets    :",total_packets_nowrites


def removeGTPLayerFromPcapfile(filename):

        total_packets_writes = 0
        total_bogus_packets = 0

    f = open("%sGTP.pcap" % filename ,"w")
    writer = dpkt.pcap.Writer(f)

    pcap=dpkt.pcap.Reader(file(filename,"rb"))

        for ts, buf in pcap:
                if pcap.datalink() == dpkt.pcap.DLT_LINUX_SLL:
                        l2 = dpkt.sll.SLL(buf)
                else:
                        l2 = dpkt.ethernet.Ethernet(buf)


                if (str(type(l2.data)) != "<class 'dpkt.ip.IP'>"):
                        total_bogus_packets += 1
                        continue

                ip = l2.data
        udp = ip.data
        gtp = udp.data

        gtp_length = int(gtp[0])
        # print "%d %x" % (gtp_length,gtp_length)
        if (gtp_length ==0):
            offset = 8
        else:
            offset = 12
            eth = dpkt.ethernet.Ethernet(src=ETHERNET_DST,dst=ETHERNET_SRC,data=gtp[offset:])
        writer.writepkt(eth) 

        total_packets_writes += 1

    writer.close()
    f.close()

        print "Total bogus packets>:", total_bogus_packets
        print "Total packets writes:",total_packets_writes


if __name__ == "__main__":

        parser = parseOptions()
        (options, args) = parser.parse_args()
        if(options.pcapfile == None):
                parser.error("Argument is required")
                sys.exit(1)

    if (options.remove == True):
        print "Removing GTP Layer from pcapfile."
        removeGTPLayerFromPcapfile(options.pcapfile)                
        sys.exit(0)

        if(options.userip == None):
                parser.error("Argument is required")
                sys.exit(1)

    userip = options.userip

    f = open("%sGTP.pcap" % options.pcapfile ,"w")
    pcap_writer = dpkt.pcap.Writer(f)

    generatePdpContextRequest(pcap_writer)
    generatePdpContextResponse(pcap_writer)

    processPcapFile(options.pcapfile)

    pcap_writer.close()
    f.close()

    sys.exit(0) 

Wireshark Printscreen

正如我所提到的,这总是在linux环境中成功运行,其中每个额外的GTP头被正确地插入为Hex,但是我的问题是我需要将其移植到Windows,现在突然我的其他GTP头被插入为ascii而不是十六进制导致无效的结果pcap。我想知道这是否与Winpcap V Libpcap有关,或者是否有其他原因,如果有人对如何解决这个问题有任何建议。

亲切的问候

Mandraker

0 个答案:

没有答案