在过去的几年里,我一直在使用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)
正如我所提到的,这总是在linux环境中成功运行,其中每个额外的GTP头被正确地插入为Hex,但是我的问题是我需要将其移植到Windows,现在突然我的其他GTP头被插入为ascii而不是十六进制导致无效的结果pcap。我想知道这是否与Winpcap V Libpcap有关,或者是否有其他原因,如果有人对如何解决这个问题有任何建议。
亲切的问候
Mandraker