From 0d0216bdd3e1b5fbeda4409705293a15af6d84d2 Mon Sep 17 00:00:00 2001 From: Kirk Strauser Date: Fri, 30 Jan 2015 18:16:21 -0800 Subject: [PATCH 001/166] First partial Pylint sweep of decode.py --- bin/decode.py | 811 +++++++++++++++++++++++++++++--------------------- 1 file changed, 466 insertions(+), 345 deletions(-) diff --git a/bin/decode.py b/bin/decode.py index 561352d..24130bb 100755 --- a/bin/decode.py +++ b/bin/decode.py @@ -1,127 +1,163 @@ #!/usr/bin/env python -import sys,os,glob,copy -import optparse -import logging,traceback -import gzip,zipfile,tempfile -import output,util +# pylint: disable-msg=C0103,E501 + +import copy import dshell -try: import pcap -except: - pcap=None +import glob +import gzip +import logging +import optparse +import os +import output +import sys +import tempfile +import traceback +import util +import zipfile +try: + import pcap +except ImportError: + pcap = None print 'pcap not available: decoders requiring pcap are not usable' -def import_module(name=None,silent=False,search={}): + +def import_module(name=None, silent=False, search=None): + if search is None: + search = {} try: - #we will first check search[name] for the module - #else split foo.bar:baz to get from foo.bar import baz - #else split dotted path to perform a 'from foo import bar' operation - try: module=search[name] #a -> from search[a] import a - except: - module,name=name.split('.')[:-1],name.split('.')[-1] #a.b.c from a.b import c - if module: module='.'.join(module) - else: module=name - path=None - if os.path.sep in module: #was a full path to a decoder given? - path,module=os.path.dirname(module),os.path.basename(module) - #print module,name - if path: sys.path.append(path) - obj=__import__(module,fromlist=[name]) - if path: sys.path.remove(path) - if 'dObj' in dir(obj) or 'obj' in dir(obj): return obj + # we will first check search[name] for the module + # else split foo.bar:baz to get from foo.bar import baz + # else split dotted path to perform a 'from foo import bar' operation + try: + module = search[name] # a -> from search[a] import a + except KeyError: + module, name = name.split('.')[:-1], name.split('.')[-1] # a.b.c from a.b import c + if module: + module = '.'.join(module) + else: + module = name + path = None + if os.path.sep in module: # was a full path to a decoder given? + path, module = os.path.dirname(module), os.path.basename(module) + # print module,name + if path: + sys.path.append(path) + obj = __import__(module, fromlist=[name]) + if path: + sys.path.remove(path) + if 'dObj' in dir(obj) or 'obj' in dir(obj): + return obj elif name in dir(obj): obj = getattr(obj, name) - if 'dObj' in dir(obj) or 'obj' in dir(obj): return obj - except Exception, err: - if not silent: sys.stderr.write( "Error '%s' loading module %s\n" % (str(err),module)) + if 'dObj' in dir(obj) or 'obj' in dir(obj): + return obj + except Exception as err: + if not silent: + sys.stderr.write("Error '%s' loading module %s\n" % (str(err), module)) return False + def setDecoderPath(decoder_path): '''set the base decoder path, add it to sys.path for importing, and walk it to return all subpaths''' - paths=[] - paths.append(decoder_path) #append base path first + paths = [] + paths.append(decoder_path) # append base path first # walk decoder directories an add to sys.path for root, dirs, files in os.walk(decoder_path): - [dirs.remove(d) for d in dirs if d.startswith('.')] #skip hidden dirs like .svn - for d in sorted(dirs): paths.append(os.path.join(root,d)) - return paths #return the paths we found + [dirs.remove(d) for d in dirs if d.startswith('.')] # skip hidden dirs like .svn + for d in sorted(dirs): + paths.append(os.path.join(root, d)) + return paths # return the paths we found + def getDecoders(decoder_paths): ''' find all decoders and map decoder to import.path.decoder expect common prefix to start with basepath''' - import_base=os.path.commonprefix(decoder_paths).split(os.path.sep)[:-1] #keep last part as base - decoders={} + import_base = os.path.commonprefix(decoder_paths).split(os.path.sep)[:-1] # keep last part as base + decoders = {} for path in decoder_paths: # split path and trim off part before base - import_path=path.split(os.path.sep)[len(import_base):] + import_path = path.split(os.path.sep)[len(import_base):] for f in glob.iglob("%s/*.py" % path): - name=os.path.splitext(os.path.basename(f))[0] - if name != '__init__': #skip package stubs - #build topdir.path...module name from topdir/dir.../file - decoders[name]='.'.join(import_path+[name]) + name = os.path.splitext(os.path.basename(f))[0] + if name != '__init__': # skip package stubs + # build topdir.path...module name from topdir/dir.../file + decoders[name] = '.'.join(import_path+[name]) return decoders -def printDecoders(decoder_map,silent=True): + +def printDecoders(decoder_map, silent=True): '''Print list of decoders with additional info''' dList = [] - FS=' %-40s %-30s %-10s %s %1s %s' - for name,module in sorted(decoder_map.iteritems()): + FS = ' %-40s %-30s %-10s %s %1s %s' + for name, module in sorted(decoder_map.iteritems()): try: - try: decoder=import_module(module,silent).dObj - except Exception, e: - print "Exception loading module '%s': %s" % (module, e) + try: + decoder = import_module(module, silent).dObj + except Exception as exc: + print "Exception loading module '%s': %s" % (module, exc) continue # get the type of decoder it is dtype = 'RAW' - if 'IP' in dir(decoder): dtype = 'IP ' - if 'UDP' in dir(decoder): dtype = 'UDP' - if 'TCP' in dir(decoder): dtype = 'TCP' - dList.append( FS % (module,decoder.name, + if 'IP' in dir(decoder): + dtype = 'IP ' + if 'UDP' in dir(decoder): + dtype = 'UDP' + if 'TCP' in dir(decoder): + dtype = 'TCP' + dList.append(FS % ( + module, decoder.name, decoder.author, - dtype,'+' if decoder.chainable else '', + dtype, '+' if decoder.chainable else '', decoder.description)) - except: pass + except: # :-( + pass + + print FS % ('module', 'name', 'author', ' ', ' ', 'desc') + print FS % ('-' * 40, '-' * 30, '-' * 10, '---', '-', '-' * 50) + for d in sorted(dList): + print d - print FS %('module','name','author',' ',' ','desc') - print FS %('-'*40,'-'*30,'-'*10,'---','-','-'*50) - for d in sorted(dList): print d def readInFilter(fname): '''Read in a BPF filter provided by a command line argument''' filter = '' - tmpfd = open(fname,'r') + tmpfd = open(fname, 'r') for line in tmpfd: if '#' in line: - line = line.split('#')[0]+'\n' # keep \n for visual output sanity + line = line.split('#')[0]+'\n' # keep \n for visual output sanity filter += line tmpfd.close() return filter -def decode_live(out,options,decoder,decoder_args,decoder_options): - #set decoder options - initDecoderOptions(decoder,out,options,decoder_args,decoder_options) +def decode_live(out, options, decoder, decoder_args, decoder_options): + # set decoder options + initDecoderOptions(decoder, out, options, decoder_args, decoder_options) if 'preModule' in dir(decoder): decoder.preModule() - decoder.input_file = options.interface # give the interface name to the decoder - stats=None - if options.verbose: log('Attempting to listen on %s' % options.interface) + decoder.input_file = options.interface # give the interface name to the decoder + stats = None + if options.verbose: + log('Attempting to listen on %s' % options.interface) try: - if not pcap: raise NotImplementedError("raw capture support not implemented") - decoder.capture=pcap.pcap(options.interface,65535,True) - if decoder.filter: decoder.capture.setfilter(decoder.filter) - while not options.count or decoder.count -1: - (path,wildcard) = os.path.split(file_path) + (path, wildcard) = os.path.split(file_path) # If just file is specified (no path) if len(path) == 0: @@ -613,7 +719,7 @@ def main(*largs,**kwargs): # Otherwise, recursion specified and there is a directory. # Recurse directory and add files else: - addFilesFromDirectory(inputs,path,wildcard) + addFilesFromDirectory(inputs, path, wildcard) # Just a normal file, append to list of inputs else: @@ -621,30 +727,31 @@ def main(*largs,**kwargs): if options.parallel or options.threaded: import multiprocessing - procs=[] - q=multiprocessing.Queue() - kwargs=options.__dict__.copy() #put parsed base options in kwargs - kwargs.update(config=None,outfile=None,queue=q) #pass the q, - #do not pass the config file or outfile because we handled that here - for d in decoder_options: #put pre-parsed decoder options in kwargs - for k,v in decoder_options[d].items(): kwargs[d+'_'+k]=v + procs = [] + q = multiprocessing.Queue() + kwargs = options.__dict__.copy() # put parsed base options in kwargs + kwargs.update(config=None, outfile=None, queue=q) # pass the q, + # do not pass the config file or outfile because we handled that here + for d in decoder_options: # put pre-parsed decoder options in kwargs + for k, v in decoder_options[d].items(): + kwargs[d+'_' + k] = v #check here to see if we are running in parallel-file mode - if options.parallel and len(inputs)>1: + if options.parallel and len(inputs) > 1: for f in inputs: - #create a child process for each input file - procs.append(multiprocessing.Process(target=main,kwargs=kwargs,args=[f])) - runChildProcs(procs,q,out,numprocs=options.numprocs) + # create a child process for each input file + procs.append(multiprocessing.Process(target=main, kwargs=kwargs, args=[f])) + runChildProcs(procs, q, out, numprocs=options.numprocs) - #check here to see if we are running decoders multithreaded - elif options.threaded and len(options.decoder)>1: + # check here to see if we are running decoders multithreaded + elif options.threaded and len(options.decoder) > 1: for d in options.decoder: - #create a child for each decoder + # create a child for each decoder kwargs.update(decoder=d) - procs.append(multiprocessing.Process(target=main,kwargs=kwargs,args=inputs)) - runChildProcs(procs,q,out,numprocs=options.numprocs) + procs.append(multiprocessing.Process(target=main, kwargs=kwargs, args=inputs)) + runChildProcs(procs, q, out, numprocs=options.numprocs) - #fall through to here (single threaded or child process) + # fall through to here (single threaded or child process) else: # # Here is where we use the decoder(s) to process the pcap @@ -654,21 +761,21 @@ def main(*largs,**kwargs): for module in decoders.keys(): decoder = decoders[module] - initDecoderOptions(decoder,out,options,decoder_args,decoder_options) + initDecoderOptions(decoder, out, options, decoder_args, decoder_options) # If the decoder has a preModule function, will execute it now decoder.preModule() - for input_file in inputs: - # Decoder-specific options may be seen as input files - # Skip anything starts with "--" + # Decoder-specific options may be seen as input files + # Skip anything starts with "--" if input_file[:2] == '--': continue # Recursive directory processing is handled elsewhere, # so we should only be dealing with files at this point. - if os.path.isdir(input_file): continue + if os.path.isdir(input_file): + continue log('+Processing file %s' % input_file) @@ -679,17 +786,18 @@ def main(*largs,**kwargs): # needed. Might consider using mkstemp() since this implementation # requires Python >= 2.6. try: - exts = ['.gz','.bz2','.zip'] + exts = ['.gz', '.bz2', '.zip'] if os.path.splitext(input_file)[1] not in exts: - pcapfile=input_file + pcapfile = input_file else: # we have a compressed file - tmpfile = expandCompressedFile(input_file,options.verbose,options.tmpdir) + tmpfile = expandCompressedFile(input_file, options.verbose, options.tmpdir) temporaryFiles.append(tmpfile) - pcapfile=tmpfile + pcapfile = tmpfile except: - if options.verbose: sys.stderr.write('+Error processing file %s' % (input_file)) + if options.verbose: + sys.stderr.write('+Error processing file %s' % (input_file)) continue # give the decoder access to the input filename @@ -705,15 +813,21 @@ def main(*largs,**kwargs): decoder.preFile() try: - if not pcap: raise NotImplementedError("pcap support not implemented") - decoder.capture=pcap.pcap(pcapfile) - if decoder.filter: decoder.capture.setfilter(decoder.filter) - while not options.count or decoder.count Date: Sat, 31 Jan 2015 22:45:36 -0500 Subject: [PATCH 002/166] Adds Styling to Linux Commands on README --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 7d1087c..4c7e4db 100644 --- a/README.md +++ b/README.md @@ -25,9 +25,9 @@ Key features: 1. Install all of the necessary Python modules listed above. Many of them are available via pip and/or apt-get. Pygeoip is not yet available as a package and must be installed with pip or manually. All except dpkt are available with pip. - 1. sudo apt-get install python-crypto python-dpkt python-ipy python-pypcap + 1. `sudo apt-get install python-crypto python-dpkt python-ipy python-pypcap` - 2. sudo pip install pygeoip + 2. `sudo pip install pygeoip` 2. Configure pygeoip by moving the MaxMind data files (GeoIP.dat, GeoIPv6.dat, GeoIPASNum.dat, GeoIPASNumv6.dat) to /share/GeoIP/ From 1f9a5b4a4cca6c84925acc2c7ccc113de84aead0 Mon Sep 17 00:00:00 2001 From: Joshua Stone Date: Sun, 1 Feb 2015 15:35:40 -0500 Subject: [PATCH 003/166] Port Ubuntu installer script to Python --- install-ubuntu.py | 29 +++++++++++++++++++++++++++++ install-ubuntu.sh | 41 ----------------------------------------- 2 files changed, 29 insertions(+), 41 deletions(-) create mode 100755 install-ubuntu.py delete mode 100755 install-ubuntu.sh diff --git a/install-ubuntu.py b/install-ubuntu.py new file mode 100755 index 0000000..6bdf367 --- /dev/null +++ b/install-ubuntu.py @@ -0,0 +1,29 @@ +#!/usr/bin/env python + +from pkgutil import iter_modules +from subprocess import call + +dependencies = { + "Crypto": "crypto", + "dpkt": "dpkt", + "IPy": "ipy", + "pcap": "pypcap" +} + +installed, missing_pkgs = [pkg[1] for pkg in iter_modules()], [] + +for module, pkg in dependencies.items(): + if module not in installed: + print("dshell requires {}".format(module)) + missing_pkgs.append("python-{}".format(pkg)) + else: + print("{} is installed".format(module)) + +if missing_pkgs: + cmd = ["sudo", "apt-get", "install"] + missing_pkgs + + print(" ".join(cmd)) + call(cmd) + +call(["make", "all"]) + diff --git a/install-ubuntu.sh b/install-ubuntu.sh deleted file mode 100755 index aff213b..0000000 --- a/install-ubuntu.sh +++ /dev/null @@ -1,41 +0,0 @@ -#!/bin/bash - -pkgs="" - -if `python -c 'import Crypto'`; -then echo "PyCrypto is installed" -else - echo "dshell requires PyCrypto" - pkgs="$pkgs python-crypto" -fi - -if `python -c 'import dpkt'`; -then echo "dpkt is installed" -else - echo "dshell requires dpkt" - pkgs="$pkgs python-dpkt" -fi - -if `python -c 'from IPy import IP'`; -then echo "IPy is installed" -else - echo "dshell requires IPy" - pkgs="$pkgs python-ipy" -fi - -if `python -c 'from pcap import pcap'`; -then echo "pypcap is installed" -else - echo "dshell requires pypcap" - pkgs="$pkgs python-pypcap" -fi - -cmd="sudo apt-get install $pkgs" -if [ "$pkgs" ]; then - echo - echo $cmd - echo - $cmd; -fi - -make all From 0a71e9ffda67fcc6347c37f14813873a007b43ce Mon Sep 17 00:00:00 2001 From: dev195 Date: Tue, 3 Feb 2015 13:12:50 -0500 Subject: [PATCH 004/166] ran autopep8 across code --- bin/decode.py | 266 ++++--- bin/generate-dshellrc.py | 57 +- bin/pcapanon.py | 281 ++++--- decoders/dns/dns-asn.py | 73 +- decoders/dns/dns-cc.py | 89 ++- decoders/dns/dns.py | 113 +-- decoders/dns/innuendo-dns.py | 77 +- decoders/dns/reservedips.py | 165 +++-- decoders/filter/country.py | 113 +-- decoders/filter/snort.py | 262 ++++--- decoders/filter/track.py | 136 ++-- decoders/flows/large-flows.py | 25 +- decoders/flows/long-flows.py | 29 +- decoders/flows/netflow.py | 30 +- decoders/http/httpdump.py | 111 +-- decoders/http/rip-http.py | 185 +++-- decoders/http/web.py | 109 +-- decoders/misc/followstream.py | 153 ++-- decoders/misc/merge.py | 25 +- decoders/misc/synrst.py | 32 +- decoders/misc/writer.py | 51 +- decoders/misc/xor.py | 103 +-- decoders/protocol/ether.py | 33 +- decoders/protocol/ip.py | 31 +- decoders/protocol/protocol.py | 27 +- decoders/templates/PacketDecoder.py | 20 +- decoders/templates/SessionDecoder.py | 28 +- install-ubuntu.py | 1 - lib/dfile.py | 80 +- lib/dnsdecoder.py | 62 +- lib/dshell.py | 1016 +++++++++++++++----------- lib/httpdecoder.py | 74 +- lib/output/colorout.py | 97 ++- lib/output/csvout.py | 60 +- lib/output/jsonout.py | 30 +- lib/output/netflowout.py | 84 ++- lib/output/output.py | 608 ++++++++------- lib/output/xmlout.py | 60 +- lib/util.py | 341 +++++---- 39 files changed, 3028 insertions(+), 2109 deletions(-) diff --git a/bin/decode.py b/bin/decode.py index 24130bb..4ddc096 100755 --- a/bin/decode.py +++ b/bin/decode.py @@ -32,7 +32,8 @@ def import_module(name=None, silent=False, search=None): try: module = search[name] # a -> from search[a] import a except KeyError: - module, name = name.split('.')[:-1], name.split('.')[-1] # a.b.c from a.b import c + # a.b.c from a.b import c + module, name = name.split('.')[:-1], name.split('.')[-1] if module: module = '.'.join(module) else: @@ -54,7 +55,8 @@ def import_module(name=None, silent=False, search=None): return obj except Exception as err: if not silent: - sys.stderr.write("Error '%s' loading module %s\n" % (str(err), module)) + sys.stderr.write( + "Error '%s' loading module %s\n" % (str(err), module)) return False @@ -66,7 +68,8 @@ def setDecoderPath(decoder_path): paths.append(decoder_path) # append base path first # walk decoder directories an add to sys.path for root, dirs, files in os.walk(decoder_path): - [dirs.remove(d) for d in dirs if d.startswith('.')] # skip hidden dirs like .svn + # skip hidden dirs like .svn + [dirs.remove(d) for d in dirs if d.startswith('.')] for d in sorted(dirs): paths.append(os.path.join(root, d)) return paths # return the paths we found @@ -75,7 +78,8 @@ def setDecoderPath(decoder_path): def getDecoders(decoder_paths): ''' find all decoders and map decoder to import.path.decoder expect common prefix to start with basepath''' - import_base = os.path.commonprefix(decoder_paths).split(os.path.sep)[:-1] # keep last part as base + import_base = os.path.commonprefix(decoder_paths).split( + os.path.sep)[:-1] # keep last part as base decoders = {} for path in decoder_paths: # split path and trim off part before base @@ -84,7 +88,7 @@ def getDecoders(decoder_paths): name = os.path.splitext(os.path.basename(f))[0] if name != '__init__': # skip package stubs # build topdir.path...module name from topdir/dir.../file - decoders[name] = '.'.join(import_path+[name]) + decoders[name] = '.'.join(import_path + [name]) return decoders @@ -127,7 +131,8 @@ def readInFilter(fname): tmpfd = open(fname, 'r') for line in tmpfd: if '#' in line: - line = line.split('#')[0]+'\n' # keep \n for visual output sanity + # keep \n for visual output sanity + line = line.split('#')[0] + '\n' filter += line tmpfd.close() @@ -141,7 +146,8 @@ def decode_live(out, options, decoder, decoder_args, decoder_options): if 'preModule' in dir(decoder): decoder.preModule() - decoder.input_file = options.interface # give the interface name to the decoder + # give the interface name to the decoder + decoder.input_file = options.interface stats = None if options.verbose: log('Attempting to listen on %s' % options.interface) @@ -153,7 +159,8 @@ def decode_live(out, options, decoder, decoder_args, decoder_options): if decoder.filter: decoder.capture.setfilter(decoder.filter) while not options.count or decoder.count < options.count: - decoder.capture.dispatch(1, decoder.decode) # use dispatch so we can handle signals + # use dispatch so we can handle signals + decoder.capture.dispatch(1, decoder.decode) except KeyboardInterrupt: pass except Exception as exc: @@ -230,14 +237,15 @@ class dshellOptionParser(optparse.OptionParser): def error(self, msg): pass - #create options for all loaded decoders + # create options for all loaded decoders def add_decoder_options(self, d): if d.subDecoder: # if we have a subdecoder, recurse down until we don't self.add_decoder_options(d.subDecoder) try: if d.optiondict: - group = optparse.OptionGroup(self, "%s decoder options" % d.name) + group = optparse.OptionGroup( + self, "%s decoder options" % d.name) for argname, optargs in d.optiondict.iteritems(): optname = "%s_%s" % (d.name, argname) group.add_option("--" + optname, dest=optname, **optargs) @@ -251,13 +259,15 @@ def parse_args(self, args, **kwargs): options, args = optparse.OptionParser.parse_args(self, args) options.__dict__.update(kwargs) except UnboundLocalError: - # probably missing a value for an argument, e.g. 'decode -d' without a decoder + # probably missing a value for an argument, e.g. 'decode -d' + # without a decoder self.print_help() return None, None return options, args # Fix for handling unknown options (e.g. decoder-specific options) - # reference: http://stackoverflow.com/questions/1885161/how-can-i-get-optparses-optionparser-to-ignore-invalid-arguments + # reference: + # http://stackoverflow.com/questions/1885161/how-can-i-get-optparses-optionparser-to-ignore-invalid-arguments def _process_args(self, largs, rargs, values): while rargs: try: @@ -287,18 +297,22 @@ def initDecoderOptions(decoder, out, options, decoder_args, decoder_options): # recurse from the bottom of the chain to the top if decoder.subDecoder: - initDecoderOptions(decoder.subDecoder, out, options, decoder_args, decoder_options) + initDecoderOptions( + decoder.subDecoder, out, options, decoder_args, decoder_options) # give the decoder the output object if the decoder doesn't pick one # or if an output object is specified via command line options if not decoder.out or options.output != 'output': decoder.out = out else: - # initialize the decoder's custom output using the channels from the global - decoder.globalout = out # provide global output module under alternate name + # initialize the decoder's custom output using the channels from the + # global + # provide global output module under alternate name + decoder.globalout = out # decoder.out.__init__(fh=out.fh) #re-init the decoder try: - # If the decoder's default output doesn't have a filehandle set, use the user provided one + # If the decoder's default output doesn't have a filehandle set, + # use the user provided one if decoder.out.fh == sys.stdout: decoder.out.fh = out.fh except AttributeError: @@ -319,7 +333,8 @@ def initDecoderOptions(decoder, out, options, decoder_args, decoder_options): # set verbosity decoder.verbose = options.verbose if options.debug: - decoder._DEBUG = options.debug # debug() is already taken, and _DEBUG might already be set + # debug() is already taken, and _DEBUG might already be set + decoder._DEBUG = options.debug # override decoder BPF if options.bpf != None: @@ -334,7 +349,8 @@ def initDecoderOptions(decoder, out, options, decoder_args, decoder_options): try: tmpbpf = readInFilter(options.filefilter) except: - log("Invalid tcpdump filter file: %s" % (options.filefilter), level=logging.ERROR) + log("Invalid tcpdump filter file: %s" % + (options.filefilter), level=logging.ERROR) return decoder.filter = tmpbpf @@ -360,108 +376,146 @@ def initDecoderOptions(decoder, out, options, decoder_args, decoder_options): if not options.novlan and not(decoder.filter.startswith('vlan')): if decoder.filter: - decoder.filter = '( '+decoder.filter+' ) or ( vlan and ( '+decoder.filter+' ) )' + decoder.filter = '( ' + decoder.filter + \ + ' ) or ( vlan and ( ' + decoder.filter + ' ) )' else: - decoder.filter = '' #fix for null filter case + decoder.filter = '' # fix for null filter case - #pass args and config file to decoder + # pass args and config file to decoder decoder.parseArgs(decoder_args, decoder_options) - log('Using module '+repr(decoder)) + log('Using module ' + repr(decoder)) def main(*largs, **kwargs): global log bin_path = os.environ['BINPATH'] sys.path.insert(0, bin_path) - #get map of name to module import path + # get map of name to module import path decoder_map = getDecoders(setDecoderPath(os.environ['DECODERPATH'])) # The main argument parser. It will have every command line option # available and should be used when actually parsing parser = dshellOptionParser( usage="usage: %prog [options] [decoder options] file1 file2 ... filen [-- [decoder args]+]", - version="%prog "+str(dshell.__version__), add_help_option=False) + version="%prog " + str(dshell.__version__), add_help_option=False) # A short argument parser, meant to only hold the shorter list of # arguments for when a decoder is called without a pcap file. DO # NOT USE for any serious argument parsing. parser_short = dshellOptionParser( usage="usage: %prog [options] [decoder options] file1 file2 ... filen [-- [decoder args]+]", - version="%prog "+str(dshell.__version__), add_help_option=False) + version="%prog " + str(dshell.__version__), add_help_option=False) parser.add_option('-h', '-?', '--help', dest='help', help="Print common command-line flags and exit", action='store_true', default=False) parser_short.add_option('-h', '-?', '--help', dest='help', help="Print common command-line flags and exit", action='store_true', default=False) - parser.add_option('-d', '--decoder', dest="decoder", action='append', help="Use a specific decoder module") - parser.add_option('-l', '--ls', '--list', action="store_true", help='List all available decoders', dest='list') - parser.add_option('-C', '--config', dest='config', help='specify config.ini file') - parser.add_option('--tmpdir', dest='tmpdir', type='string', default=tempfile.gettempdir(), help='alternate temp directory (for use when processing compressed pcap files)') - parser.add_option('-r', '--recursive', dest='recursive', action='store_true', help='recursively process all PCAP files under input directory') + parser.add_option('-d', '--decoder', dest="decoder", + action='append', help="Use a specific decoder module") + parser.add_option('-l', '--ls', '--list', action="store_true", + help='List all available decoders', dest='list') + parser.add_option( + '-C', '--config', dest='config', help='specify config.ini file') + parser.add_option('--tmpdir', dest='tmpdir', type='string', default=tempfile.gettempdir(), + help='alternate temp directory (for use when processing compressed pcap files)') + parser.add_option('-r', '--recursive', dest='recursive', action='store_true', + help='recursively process all PCAP files under input directory') group = optparse.OptionGroup(parser, "Multiprocessing options") - group.add_option('-p', '--parallel', dest='parallel', action='store_true', help='process multiple files in parallel') - group.add_option('-t', '--threaded', dest='threaded', action='store_true', help='run multiple decoders in parallel') - group.add_option('-n', '--nprocs', dest='numprocs', type='int', default=4, help='number of simultaneous processes') + group.add_option('-p', '--parallel', dest='parallel', + action='store_true', help='process multiple files in parallel') + group.add_option('-t', '--threaded', dest='threaded', + action='store_true', help='run multiple decoders in parallel') + group.add_option('-n', '--nprocs', dest='numprocs', type='int', + default=4, help='number of simultaneous processes') parser.add_option_group(group) # decode-pcap specific options group = optparse.OptionGroup(parser, "Input options") - group.add_option('-i', '--interface', dest='interface', default=None, help='listen live on INTERFACE') - group.add_option('-c', '--count', dest='count', type='int', help='number of packets to process', default=0) - group.add_option('-f', '--bpf', dest='bpf', help='replace default decoder filter (use carefully)') - group.add_option('--nofilterfn', dest='nofilterfn', action="store_true", help='Set filterfn to pass-thru') - group.add_option('-F', dest='filefilter', help='Use filefilter as input for the filter expression. An additional expression given on the command line is ignored.') - group.add_option('--ebpf', dest='ebpf', help='BPF filter to exclude traffic, extends other filters') - group.add_option('--no-vlan', dest='novlan', action="store_true", help='do not examine traffic which has VLAN headers present') - group.add_option('--layer2', dest='layer2', default='ethernet.Ethernet', help='select the layer-2 protocol module') - group.add_option('--strip', dest='striplayers', default=0, help='extra data-link layers to strip') + group.add_option('-i', '--interface', dest='interface', + default=None, help='listen live on INTERFACE') + group.add_option('-c', '--count', dest='count', type='int', + help='number of packets to process', default=0) + group.add_option('-f', '--bpf', dest='bpf', + help='replace default decoder filter (use carefully)') + group.add_option('--nofilterfn', dest='nofilterfn', + action="store_true", help='Set filterfn to pass-thru') + group.add_option('-F', dest='filefilter', + help='Use filefilter as input for the filter expression. An additional expression given on the command line is ignored.') + group.add_option( + '--ebpf', dest='ebpf', help='BPF filter to exclude traffic, extends other filters') + group.add_option('--no-vlan', dest='novlan', action="store_true", + help='do not examine traffic which has VLAN headers present') + group.add_option('--layer2', dest='layer2', default='ethernet.Ethernet', + help='select the layer-2 protocol module') + group.add_option('--strip', dest='striplayers', default=0, + help='extra data-link layers to strip') parser.add_option_group(group) group = optparse.OptionGroup(parser_short, "Input options") - group.add_option('-i', '--interface', dest='interface', default=None, help='listen live on INTERFACE') - group.add_option('-c', '--count', dest='count', type='int', help='number of packets to process', default=0) - group.add_option('-f', '--bpf', dest='bpf', help='replace default decoder filter (use carefully)') - group.add_option('--nofilterfn', dest='nofilterfn', action="store_true", help='Set filterfn to pass-thru') - group.add_option('-F', dest='filefilter', help='Use filefilter as input for the filter expression. An additional expression given on the command line is ignored.') - group.add_option('--ebpf', dest='ebpf', help='BPF filter to exclude traffic, extends other filters') - group.add_option('--no-vlan', dest='novlan', action="store_true", help='do not examine traffic which has VLAN headers present') - group.add_option('--layer2', dest='layer2', default='ethernet.Ethernet', help='select the layer-2 protocol module') - group.add_option('--strip', dest='striplayers', default=0, help='extra data-link layers to strip') + group.add_option('-i', '--interface', dest='interface', + default=None, help='listen live on INTERFACE') + group.add_option('-c', '--count', dest='count', type='int', + help='number of packets to process', default=0) + group.add_option('-f', '--bpf', dest='bpf', + help='replace default decoder filter (use carefully)') + group.add_option('--nofilterfn', dest='nofilterfn', + action="store_true", help='Set filterfn to pass-thru') + group.add_option('-F', dest='filefilter', + help='Use filefilter as input for the filter expression. An additional expression given on the command line is ignored.') + group.add_option( + '--ebpf', dest='ebpf', help='BPF filter to exclude traffic, extends other filters') + group.add_option('--no-vlan', dest='novlan', action="store_true", + help='do not examine traffic which has VLAN headers present') + group.add_option('--layer2', dest='layer2', default='ethernet.Ethernet', + help='select the layer-2 protocol module') + group.add_option('--strip', dest='striplayers', default=0, + help='extra data-link layers to strip') parser_short.add_option_group(group) - group = optparse.OptionGroup(parser, "Output options") - group.add_option('-o', '--outfile', dest='outfile', help='write output to the file OUTFILE. Additional output can be set with KEYWORD=VALUE,...\n'+\ - '\tmode= 1: for f in inputs: # create a child process for each input file - procs.append(multiprocessing.Process(target=main, kwargs=kwargs, args=[f])) + procs.append( + multiprocessing.Process(target=main, kwargs=kwargs, args=[f])) runChildProcs(procs, q, out, numprocs=options.numprocs) # check here to see if we are running decoders multithreaded @@ -748,7 +812,8 @@ def main(*largs, **kwargs): for d in options.decoder: # create a child for each decoder kwargs.update(decoder=d) - procs.append(multiprocessing.Process(target=main, kwargs=kwargs, args=inputs)) + procs.append( + multiprocessing.Process(target=main, kwargs=kwargs, args=inputs)) runChildProcs(procs, q, out, numprocs=options.numprocs) # fall through to here (single threaded or child process) @@ -761,7 +826,8 @@ def main(*largs, **kwargs): for module in decoders.keys(): decoder = decoders[module] - initDecoderOptions(decoder, out, options, decoder_args, decoder_options) + initDecoderOptions( + decoder, out, options, decoder_args, decoder_options) # If the decoder has a preModule function, will execute it now decoder.preModule() @@ -792,12 +858,14 @@ def main(*largs, **kwargs): else: # we have a compressed file - tmpfile = expandCompressedFile(input_file, options.verbose, options.tmpdir) + tmpfile = expandCompressedFile( + input_file, options.verbose, options.tmpdir) temporaryFiles.append(tmpfile) pcapfile = tmpfile except: if options.verbose: - sys.stderr.write('+Error processing file %s' % (input_file)) + sys.stderr.write( + '+Error processing file %s' % (input_file)) continue # give the decoder access to the input filename @@ -814,13 +882,15 @@ def main(*largs, **kwargs): try: if not pcap: - raise NotImplementedError("pcap support not implemented") + raise NotImplementedError( + "pcap support not implemented") decoder.capture = pcap.pcap(pcapfile) if decoder.filter: decoder.capture.setfilter(decoder.filter) while not options.count or decoder.count < options.count: try: - ts, pkt = decoder.capture.next() # read next packet and break on EOF + # read next packet and break on EOF + ts, pkt = decoder.capture.next() except: break # no data decoder.decode(ts, pkt) @@ -861,7 +931,8 @@ def main(*largs, **kwargs): def runChildProcs(procs, q, out, numprocs=4): import Queue running = [] - while procs or running: # while we still have processes to spawn or running + # while we still have processes to spawn or running + while procs or running: if procs and len(running) < numprocs: proc = procs.pop(0) proc.start() @@ -869,7 +940,8 @@ def runChildProcs(procs, q, out, numprocs=4): running.append(proc) for proc in running: if not proc.is_alive(): # see if it finished - out.log('%d exited (%d)' % (proc.pid, proc.exitcode), level=logging.INFO) + out.log('%d exited (%d)' % + (proc.pid, proc.exitcode), level=logging.INFO) running.remove(proc) try: # get from the output queue until empty while True: diff --git a/bin/generate-dshellrc.py b/bin/generate-dshellrc.py index 6a6f225..2de6bd3 100755 --- a/bin/generate-dshellrc.py +++ b/bin/generate-dshellrc.py @@ -1,38 +1,43 @@ #!/usr/bin/python -import os, sys +import os +import sys -if __name__=='__main__': +if __name__ == '__main__': cwd = sys.argv[1] - #environment variables used by shell and modules - envvars={ - 'DSHELL':'%s'%(cwd), - 'DECODERPATH':'%s/decoders' %(cwd), - 'BINPATH':'%s/bin' % (cwd), - 'LIBPATH':'%s/lib' %(cwd), - 'DATAPATH':'%s/share' % (cwd), + # environment variables used by shell and modules + envvars = { + 'DSHELL': '%s' % (cwd), + 'DECODERPATH': '%s/decoders' % (cwd), + 'BINPATH': '%s/bin' % (cwd), + 'LIBPATH': '%s/lib' % (cwd), + 'DATAPATH': '%s/share' % (cwd), } - #further shell environment setup - envsetup= { - 'LD_LIBRARY_PATH':'$LIBPATH:$LD_LIBRARY_PATH', - 'PATH':'$BINPATH:$PATH', - 'PYTHONPATH':'$DSHELL:$LIBPATH:$LIBPATH/output:'+os.path.join('$LIBPATH','python'+'.'.join(sys.version.split('.',3)[:2]).split(' ')[0],'site-packages')+':$PYTHONPATH' } + # further shell environment setup + envsetup = { + 'LD_LIBRARY_PATH': '$LIBPATH:$LD_LIBRARY_PATH', + 'PATH': '$BINPATH:$PATH', + 'PYTHONPATH': '$DSHELL:$LIBPATH:$LIBPATH/output:' + os.path.join('$LIBPATH', 'python' + '.'.join(sys.version.split('.', 3)[:2]).split(' ')[0], 'site-packages') + ':$PYTHONPATH'} try: - os.mkdir(os.path.join(cwd,'lib','python'+'.'.join(sys.version.split('.',3)[:2]).split(' ')[0])) - os.mkdir(os.path.join(cwd,'lib','python'+'.'.join(sys.version.split('.',3)[:2]).split(' ')[0],'site-packages')) - except Exception,e: print e - - envdict={} + os.mkdir(os.path.join( + cwd, 'lib', 'python' + '.'.join(sys.version.split('.', 3)[:2]).split(' ')[0])) + os.mkdir(os.path.join(cwd, 'lib', 'python' + + '.'.join(sys.version.split('.', 3)[:2]).split(' ')[0], 'site-packages')) + except Exception, e: + print e + + envdict = {} envdict.update(envvars) envdict.update(envsetup) #.dshellrc text - env = [ 'export PS1="`whoami`@`hostname`:\w Dshell> "' ]+['export %s=%s'%(k,v) for k,v in envvars.items()]+['export %s=%s'%(k,v) for k,v in envsetup.items()] - outfd = open('.dshellrc','w') + env = ['export PS1="`whoami`@`hostname`:\w Dshell> "'] + ['export %s=%s' % + (k, v) for k, v in envvars.items()] + ['export %s=%s' % (k, v) for k, v in envsetup.items()] + outfd = open('.dshellrc', 'w') outfd.write("\n".join(env)) - if len(sys.argv)>2 and sys.argv[2]=='with_bash_completion': + if len(sys.argv) > 2 and sys.argv[2] == 'with_bash_completion': outfd.write(''' @@ -128,14 +133,14 @@ ''') outfd.close() - #dshell text - outfd = open('dshell','w') + # dshell text + outfd = open('dshell', 'w') outfd.write('#!/bin/bash\n') outfd.write('/bin/bash --rcfile %s/.dshellrc\n' % (cwd)) outfd.close() - #dshell-decode text - outfd = open('dshell-decode','w') + # dshell-decode text + outfd = open('dshell-decode', 'w') outfd.write('#!/bin/bash\n') outfd.write('source %s/.dshellrc\n' % (cwd)) outfd.write('decode "$@"') diff --git a/bin/pcapanon.py b/bin/pcapanon.py index 29d1b12..1a61478 100755 --- a/bin/pcapanon.py +++ b/bin/pcapanon.py @@ -5,138 +5,190 @@ @author: tparker ''' -import sys,dpkt,struct,pcap,socket,time +import sys +import dpkt +import struct +import pcap +import socket +import time from Crypto.Random import random from Crypto.Hash import SHA from output import PCAPWriter from util import getopts -def hashaddr(addr,*extra): - #hash key+address plus any extra data (ports if flow) - global key,ip_range,ip_mask - sha=SHA.new(key+addr) - for e in extra: sha.update(str(extra)) - #take len(addr) octets of digest as address, to int, mask, or with range, back to octets - return inttoip( ( iptoint(sha.digest()[0:len(addr)]) & ip_mask) | ip_range ) + +def hashaddr(addr, *extra): + # hash key+address plus any extra data (ports if flow) + global key, ip_range, ip_mask + sha = SHA.new(key + addr) + for e in extra: + sha.update(str(extra)) + # take len(addr) octets of digest as address, to int, mask, or with range, + # back to octets + return inttoip((iptoint(sha.digest()[0:len(addr)]) & ip_mask) | ip_range) + def mangleMAC(addr): global zero_mac - if zero_mac: return "\x00\x00\x00\x00\x00\x00" - if addr in emap: return emap[addr] - haddr=None - if addr == "\x00\x00\x00\x00\x00\x00": haddr=addr #return null MAC - if ord(addr[0])&0x01: haddr=addr #mac&0x800000000000 == broadcast addr, do not touch + if zero_mac: + return "\x00\x00\x00\x00\x00\x00" + if addr in emap: + return emap[addr] + haddr = None + if addr == "\x00\x00\x00\x00\x00\x00": + haddr = addr # return null MAC + if ord(addr[0]) & 0x01: + haddr = addr # mac&0x800000000000 == broadcast addr, do not touch if not haddr: - haddr=hashaddr(addr) - haddr=chr(ord(haddr[0])&0xfc|0x2)+haddr[1:6] #return hash bytes with first byte set to xxxxxx10 (LAA unicast) - emap[addr]=haddr + haddr = hashaddr(addr) + # return hash bytes with first byte set to xxxxxx10 (LAA unicast) + haddr = chr(ord(haddr[0]) & 0xfc | 0x2) + haddr[1:6] + emap[addr] = haddr return haddr -def mangleIP(addr,*ports): #addr,extra=our_port,other_port - global exclude,exclude_port,anon_all,by_flow - haddr=None - intip=iptoint(addr) - if len(addr)==4 and intip>=0xE0000000: haddr=addr #pass multicast 224.x.x.x and higher - ip=iptoa(addr) - #pass 127.x.x.x, IANA reserved, and autoconfig ranges - if not anon_all and (ip.startswith('127.') \ - or ip.startswith('10.') \ - or ip.startswith('172.16.') \ - or ip.startswith('192.168.') \ - or ip.startswith('169.254.')): haddr=addr - #pass ips matching exclude + +def mangleIP(addr, *ports): # addr,extra=our_port,other_port + global exclude, exclude_port, anon_all, by_flow + haddr = None + intip = iptoint(addr) + if len(addr) == 4 and intip >= 0xE0000000: + haddr = addr # pass multicast 224.x.x.x and higher + ip = iptoa(addr) + # pass 127.x.x.x, IANA reserved, and autoconfig ranges + if not anon_all and (ip.startswith('127.') + or ip.startswith('10.') + or ip.startswith('172.16.') + or ip.startswith('192.168.') + or ip.startswith('169.254.')): + haddr = addr + # pass ips matching exclude for x in exclude: - if ip.startswith(x): haddr=addr - if ports and ports[0] in exclude_port: haddr=addr #if our port is exclude + if ip.startswith(x): + haddr = addr + if ports and ports[0] in exclude_port: + haddr = addr # if our port is exclude if not haddr: - if by_flow: haddr=hashaddr(addr,*ports) #use ports if by flow, else just use ip - else: haddr=hashaddr(addr) + if by_flow: + # use ports if by flow, else just use ip + haddr = hashaddr(addr, *ports) + else: + haddr = hashaddr(addr) return haddr -def mangleIPs(src,dst,sport,dport): - if by_flow: #if by flow, hash addresses with s/d ports - if (src,sport,dst,dport) in ipmap: src,dst=ipmap[(src,sport,dst,dport)] - elif (dst,dport,src,sport) in ipmap: dst,src=ipmap[(dst,dport,src,sport)] #make sure reverse flow maps same - else: src,dst=ipmap.setdefault((src,sport,dst,dport),(mangleIP(src,sport,dport),mangleIP(dst,dport,sport))) + +def mangleIPs(src, dst, sport, dport): + if by_flow: # if by flow, hash addresses with s/d ports + if (src, sport, dst, dport) in ipmap: + src, dst = ipmap[(src, sport, dst, dport)] + elif (dst, dport, src, sport) in ipmap: + # make sure reverse flow maps same + dst, src = ipmap[(dst, dport, src, sport)] + else: + src, dst = ipmap.setdefault( + (src, sport, dst, dport), (mangleIP(src, sport, dport), mangleIP(dst, dport, sport))) else: - if src in ipmap: src=ipmap[src] - else: src=ipmap.setdefault(src,mangleIP(src,sport)) - if dst in ipmap: dst=ipmap[dst] - else: dst=ipmap.setdefault(dst,mangleIP(dst,dport)) - return src,dst + if src in ipmap: + src = ipmap[src] + else: + src = ipmap.setdefault(src, mangleIP(src, sport)) + if dst in ipmap: + dst = ipmap[dst] + else: + dst = ipmap.setdefault(dst, mangleIP(dst, dport)) + return src, dst + def mactoa(addr): - return ':'.join(['%02x'%b for b in struct.unpack('6B',addr)]) + return ':'.join(['%02x' % b for b in struct.unpack('6B', addr)]) + def iptoa(addr): - if len(addr) is 16: return socket.inet_ntop(socket.AF_INET6,addr) - else: return socket.inet_ntop(socket.AF_INET,addr) + if len(addr) is 16: + return socket.inet_ntop(socket.AF_INET6, addr) + else: + return socket.inet_ntop(socket.AF_INET, addr) + def iptoint(addr): - if len(addr) is 16: #ipv6 to long - ip=struct.unpack('!IIII',addr) - return ip[0]<<96|ip[1]<<64|ip[2]<<32|ip[3] - else: return struct.unpack('!I',addr)[0] #ip to int + if len(addr) is 16: # ipv6 to long + ip = struct.unpack('!IIII', addr) + return ip[0] << 96 | ip[1] << 64 | ip[2] << 32 | ip[3] + else: + return struct.unpack('!I', addr)[0] # ip to int + def inttoip(l): - if l>0xffffffff: #ipv6 - return struct.pack('!IIII',l>>96,l>>64&0xffffffff,l>>32&0xffffffff,l&0xffffffff) - else: return struct.pack('!I',l) - -def pcap_handler(ts,pktdata): - global init_ts,start_ts,replace_ts,by_flow,anon_mac,zero_mac - if not init_ts: init_ts=ts - if replace_ts: ts=start_ts+(ts-init_ts) #replace timestamps + if l > 0xffffffff: # ipv6 + return struct.pack('!IIII', l >> 96, l >> 64 & 0xffffffff, l >> 32 & 0xffffffff, l & 0xffffffff) + else: + return struct.pack('!I', l) + + +def pcap_handler(ts, pktdata): + global init_ts, start_ts, replace_ts, by_flow, anon_mac, zero_mac + if not init_ts: + init_ts = ts + if replace_ts: + ts = start_ts + (ts - init_ts) # replace timestamps try: - pkt=dpkt.ethernet.Ethernet(pktdata) + pkt = dpkt.ethernet.Ethernet(pktdata) if anon_mac or zero_mac: - pkt.src=mangleMAC(pkt.src) - pkt.dst=mangleMAC(pkt.dst) - if pkt.type==dpkt.ethernet.ETH_TYPE_IP: - try: sport,dport=pkt.data.data.sport,pkt.data.data.dport #TCP or UDP? - except: sport=dport=None #nope - pkt.data.src,pkt.data.dst=mangleIPs(pkt.data.src,pkt.data.dst,sport,dport) - pktdata=str(pkt) - except Exception,e: print e - out.write(len(pktdata),pktdata,ts) + pkt.src = mangleMAC(pkt.src) + pkt.dst = mangleMAC(pkt.dst) + if pkt.type == dpkt.ethernet.ETH_TYPE_IP: + try: + # TCP or UDP? + sport, dport = pkt.data.data.sport, pkt.data.data.dport + except: + sport = dport = None # nope + pkt.data.src, pkt.data.dst = mangleIPs( + pkt.data.src, pkt.data.dst, sport, dport) + pktdata = str(pkt) + except Exception, e: + print e + out.write(len(pktdata), pktdata, ts) if __name__ == '__main__': - global key,init_ts,start_ts,replace_ts,by_flow,anon_mac,zero_mac,exclude,exclude_port,anon_all,ip_range,ip_mask - opts,args=getopts(sys.argv[1:],'i:aezftx:p:rk:',['ip=','all','ether','zero','flow','ts','exclude=','random','key=','port='],['-x','--exclude','-p','--port']) - - if '-r' in opts or '--random' in opts: key=random.long_to_bytes(random.getrandbits(64),8) - else: key='' - key=opts.get('-k',opts.get('--key',key)) - - ip_range=opts.get('-i',opts.get('--ip','0.0.0.0')) - ip_mask=0 #bitmask for hashed address - ipr='' - for o in map(int,ip_range.split('.')): - ipr+=chr(o) - ip_mask<<=8 #shift by 8 bits - if not o: ip_mask|=0xff #set octet mask to 0xff if ip_range octet is zero - ip_range=iptoint(ipr) #convert to int value for hash&mask|ip_range - - replace_ts='-t' in opts or '--ts' in opts - by_flow='-f' in opts or '--flow' in opts - anon_mac='-e' in opts or '--ether' in opts - zero_mac='-z' in opts or '--zero' in opts - anon_all='-a' in opts or '--all' in opts + global key, init_ts, start_ts, replace_ts, by_flow, anon_mac, zero_mac, exclude, exclude_port, anon_all, ip_range, ip_mask + opts, args = getopts(sys.argv[1:], 'i:aezftx:p:rk:', [ + 'ip=', 'all', 'ether', 'zero', 'flow', 'ts', 'exclude=', 'random', 'key=', 'port='], ['-x', '--exclude', '-p', '--port']) - start_ts=time.time() - init_ts=None - - exclude=opts.get('-x',[]) - exclude.extend(opts.get('--exclude',[])) - - exclude_port=map(int,opts.get('-p',[])) - exclude_port.extend(map(int,opts.get('--port',[]))) - - emap={} - ipmap={} - - if len(args)<2: + if '-r' in opts or '--random' in opts: + key = random.long_to_bytes(random.getrandbits(64), 8) + else: + key = '' + key = opts.get('-k', opts.get('--key', key)) + + ip_range = opts.get('-i', opts.get('--ip', '0.0.0.0')) + ip_mask = 0 # bitmask for hashed address + ipr = '' + for o in map(int, ip_range.split('.')): + ipr += chr(o) + ip_mask <<= 8 # shift by 8 bits + if not o: + ip_mask |= 0xff # set octet mask to 0xff if ip_range octet is zero + ip_range = iptoint(ipr) # convert to int value for hash&mask|ip_range + + replace_ts = '-t' in opts or '--ts' in opts + by_flow = '-f' in opts or '--flow' in opts + anon_mac = '-e' in opts or '--ether' in opts + zero_mac = '-z' in opts or '--zero' in opts + anon_all = '-a' in opts or '--all' in opts + + start_ts = time.time() + init_ts = None + + exclude = opts.get('-x', []) + exclude.extend(opts.get('--exclude', [])) + + exclude_port = map(int, opts.get('-p', [])) + exclude_port.extend(map(int, opts.get('--port', []))) + + emap = {} + ipmap = {} + + if len(args) < 2: print "usage: pcapanon.py [options] > mapping.csv\nOptions:\n\t[-i/--ip range]\n\t[-r/--random | -k/--key 'salt' ]\n\t[-a/--all] [-t/--ts] [-f/--flow]\n\t[-e/--ether | -z/--zero]\n\t[-x/--exclude pattern...]\n\t[-p/--port list...]" print "Will anonymize all non-reserved IPs to be in range specified by -i/--ip option," print "\tnonzero range octets are copied to anonymized address,\n\t(default range is 0.0.0.0 for fully random IPs)" @@ -154,21 +206,24 @@ def pcap_handler(ts,pktdata): print "-z/--zero will zero all MAC addresses" sys.exit(0) - out=PCAPWriter(args[-1]) + out = PCAPWriter(args[-1]) print '#file, packets' for f in args[0:-1]: - p=0 - cap=pcap.pcap(f) - while cap.dispatch(1,pcap_handler): p+=1 #process whole file + p = 0 + cap = pcap.pcap(f) + while cap.dispatch(1, pcap_handler): + p += 1 # process whole file del cap - print '%s,%s'%(f,p) + print '%s,%s' % (f, p) out.close() print "#type,is-anonymized, original, anonymized" - for ia,oa in sorted(emap.items()): print 'ether,%d, %s, %s'%(int(not ia==oa),mactoa(ia),mactoa(oa)) - for ia,oa in sorted(ipmap.items()): + for ia, oa in sorted(emap.items()): + print 'ether,%d, %s, %s' % (int(not ia == oa), mactoa(ia), mactoa(oa)) + for ia, oa in sorted(ipmap.items()): if by_flow: - sip,sp,dip,dp=ia - osip,odip=oa - print "flow,%d, %s:%s,%s:%s, %s:%s,%s:%s"%(int(sip!=osip or dip!=odip),iptoa(sip),sp,iptoa(dip),dp,iptoa(osip),sp,iptoa(odip),dp) - else: print 'ip,%d, %s, %s'%(int(ia!=oa),iptoa(ia),iptoa(oa)) + sip, sp, dip, dp = ia + osip, odip = oa + print "flow,%d, %s:%s,%s:%s, %s:%s,%s:%s" % (int(sip != osip or dip != odip), iptoa(sip), sp, iptoa(dip), dp, iptoa(osip), sp, iptoa(odip), dp) + else: + print 'ip,%d, %s, %s' % (int(ia != oa), iptoa(ia), iptoa(oa)) diff --git a/decoders/dns/dns-asn.py b/decoders/dns/dns-asn.py index c545658..bb97401 100644 --- a/decoders/dns/dns-asn.py +++ b/decoders/dns/dns-asn.py @@ -1,18 +1,22 @@ -import dshell,dpkt,socket +import dshell +import dpkt +import socket from dnsdecoder import DNSDecoder + class DshellDecoder(DNSDecoder): + def __init__(self): DNSDecoder.__init__(self, - name = 'dns-asn', - description = 'identify AS of DNS A/AAAA record responses', - filter = '(port 53)', - author = 'bg', - cleanupinterval=10, - maxblobs=2, - ) + name='dns-asn', + description='identify AS of DNS A/AAAA record responses', + filter='(port 53)', + author='bg', + cleanupinterval=10, + maxblobs=2, + ) - def decode_q(self,dns): + def decode_q(self, dns): queried = "" if dns.qd[0].type == dpkt.dns.DNS_A: queried = queried + "A? %s" % (dns.qd[0].name) @@ -20,45 +24,52 @@ def decode_q(self,dns): queried = queried + "AAAA? %s" % (dns.qd[0].name) return queried - def DNSHandler(self,conn,request,response,**kwargs): - anstext='' - queried='' - id=None - for dns in request,response: - if dns is None: continue - id=dns.id - #DNS Question, update connection info with query - if dns.qr==dpkt.dns.DNS_Q: conn.info(query=self.decode_q(dns)) + def DNSHandler(self, conn, request, response, **kwargs): + anstext = '' + queried = '' + id = None + for dns in request, response: + if dns is None: + continue + id = dns.id + # DNS Question, update connection info with query + if dns.qr == dpkt.dns.DNS_Q: + conn.info(query=self.decode_q(dns)) # DNS Answer with data and no errors - elif (dns.qr == dpkt.dns.DNS_A and dns.rcode == dpkt.dns.DNS_RCODE_NOERR and len(dns.an)>0): + elif (dns.qr == dpkt.dns.DNS_A and dns.rcode == dpkt.dns.DNS_RCODE_NOERR and len(dns.an) > 0): - queried=self.decode_q(dns) + queried = self.decode_q(dns) answers = [] for an in dns.an: if an.type == dpkt.dns.DNS_A: try: - cc = self.getASN( socket.inet_ntoa(an.ip) ) - answers.append('A: %s (%s) (ttl %s)' % (socket.inet_ntoa(an.ip), cc, an.ttl) ) - except: continue + cc = self.getASN(socket.inet_ntoa(an.ip)) + answers.append( + 'A: %s (%s) (ttl %s)' % (socket.inet_ntoa(an.ip), cc, an.ttl)) + except: + continue elif an.type == dpkt.dns.DNS_AAAA: try: - cc = self.getASN( socket.inet_ntop(socket.AF_INET6, an.ip6) ) - answers.append('AAAA: %s (%s) (ttl %s)' % (socket.inet_ntop(socket.AF_INET6, an.ip6), cc, an.ttl) ) - except: continue + cc = self.getASN( + socket.inet_ntop(socket.AF_INET6, an.ip6)) + answers.append('AAAA: %s (%s) (ttl %s)' % ( + socket.inet_ntop(socket.AF_INET6, an.ip6), cc, an.ttl)) + except: + continue else: # un-handled type continue if queried != '': - anstext =", ".join(answers) - - if anstext: #did we get an answer? - self.alert(str(id)+' '+queried+' / '+anstext,**conn.info(response=anstext)) + anstext = ", ".join(answers) + if anstext: # did we get an answer? + self.alert( + str(id) + ' ' + queried + ' / ' + anstext, **conn.info(response=anstext)) -if __name__=='__main__': +if __name__ == '__main__': dObj = DshellDecoder() print dObj else: diff --git a/decoders/dns/dns-cc.py b/decoders/dns/dns-cc.py index e2154f7..99fbe51 100644 --- a/decoders/dns/dns-cc.py +++ b/decoders/dns/dns-cc.py @@ -1,20 +1,24 @@ -import dshell,dpkt,socket +import dshell +import dpkt +import socket from dnsdecoder import DNSDecoder + class DshellDecoder(DNSDecoder): + def __init__(self): DNSDecoder.__init__(self, - name = 'dns-cc', - description = 'identify country code of DNS A/AAAA record responses', - filter = '(port 53)', - author = 'bg', - cleanupinterval=10, - maxblobs=2, - optiondict={'foreign':{'action':'store_true','help':'report responses in foreign countries'}, - 'code':{'type':'string', 'help':'filter on a specific country code (ex. US)'}} - ) + name='dns-cc', + description='identify country code of DNS A/AAAA record responses', + filter='(port 53)', + author='bg', + cleanupinterval=10, + maxblobs=2, + optiondict={'foreign': {'action': 'store_true', 'help': 'report responses in foreign countries'}, + 'code': {'type': 'string', 'help': 'filter on a specific country code (ex. US)'}} + ) - def decode_q(self,dns): + def decode_q(self, dns): queried = "" if dns.qd[0].type == dpkt.dns.DNS_A: queried = queried + "A? %s" % (dns.qd[0].name) @@ -22,49 +26,60 @@ def decode_q(self,dns): queried = queried + "AAAA? %s" % (dns.qd[0].name) return queried - def DNSHandler(self,conn,request,response,**kwargs): - anstext='' - queried='' - id=None - for dns in request,response: - if dns is None: continue - id=dns.id - #DNS Question, update connection info with query - if dns.qr==dpkt.dns.DNS_Q: conn.info(query=self.decode_q(dns)) + def DNSHandler(self, conn, request, response, **kwargs): + anstext = '' + queried = '' + id = None + for dns in request, response: + if dns is None: + continue + id = dns.id + # DNS Question, update connection info with query + if dns.qr == dpkt.dns.DNS_Q: + conn.info(query=self.decode_q(dns)) # DNS Answer with data and no errors - elif (dns.qr == dpkt.dns.DNS_A and dns.rcode == dpkt.dns.DNS_RCODE_NOERR and len(dns.an)>0): + elif (dns.qr == dpkt.dns.DNS_A and dns.rcode == dpkt.dns.DNS_RCODE_NOERR and len(dns.an) > 0): - queried=self.decode_q(dns) + queried = self.decode_q(dns) answers = [] for an in dns.an: if an.type == dpkt.dns.DNS_A: try: - cc = self.getGeoIP( socket.inet_ntoa(an.ip) ) - if self.foreign and ( cc == 'US' or cc == '--' ): continue - elif self.code != None and cc != self.code: continue - answers.append('A: %s (%s) (ttl %ss)' % (socket.inet_ntoa(an.ip), cc, an.ttl) ) - except: continue + cc = self.getGeoIP(socket.inet_ntoa(an.ip)) + if self.foreign and (cc == 'US' or cc == '--'): + continue + elif self.code != None and cc != self.code: + continue + answers.append( + 'A: %s (%s) (ttl %ss)' % (socket.inet_ntoa(an.ip), cc, an.ttl)) + except: + continue elif an.type == dpkt.dns.DNS_AAAA: try: - cc = self.getGeoIP( socket.inet_ntop(socket.AF_INET6, an.ip6) ) - if self.foreign and ( cc == 'US' or cc == '--' ): continue - elif self.code != None and cc != self.code: continue - answers.append('AAAA: %s (%s) (ttl %ss)' % (socket.inet_ntop(socket.AF_INET6, an.ip6), cc, an.ttl) ) - except: continue + cc = self.getGeoIP( + socket.inet_ntop(socket.AF_INET6, an.ip6)) + if self.foreign and (cc == 'US' or cc == '--'): + continue + elif self.code != None and cc != self.code: + continue + answers.append('AAAA: %s (%s) (ttl %ss)' % ( + socket.inet_ntop(socket.AF_INET6, an.ip6), cc, an.ttl)) + except: + continue else: # un-handled type continue if queried != '': - anstext =", ".join(answers) - - if anstext: #did we get an answer? - self.alert(str(id)+' '+queried+' / '+anstext,**conn.info(response=anstext)) + anstext = ", ".join(answers) + if anstext: # did we get an answer? + self.alert( + str(id) + ' ' + queried + ' / ' + anstext, **conn.info(response=anstext)) -if __name__=='__main__': +if __name__ == '__main__': dObj = DshellDecoder() print dObj else: diff --git a/decoders/dns/dns.py b/decoders/dns/dns.py index f097782..5991f10 100644 --- a/decoders/dns/dns.py +++ b/decoders/dns/dns.py @@ -1,21 +1,24 @@ -import dpkt,socket +import dpkt +import socket from dnsdecoder import DNSDecoder + class DshellDecoder(DNSDecoder): + def __init__(self): DNSDecoder.__init__(self, - name = 'dns', - description = 'extract and summarize DNS queries/responses (defaults: A,AAAA,CNAME,PTR records)', - filter = '(udp and port 53)', - author = 'bg/twp', - optiondict={'show_noanswer':{'action':'store_true','help':'report unanswered queries alongside other queries'}, - 'show_norequest':{'action':'store_true','help':'report unsolicited responses alongside other responses'}, - 'only_noanswer':{'action':'store_true','help':'report only unanswered queries'}, - 'only_norequest':{'action':'store_true','help':'report only unsolicited responses'}, - 'showall':{'action':'store_true','help':'show all answered queries/responses'}} - ) + name='dns', + description='extract and summarize DNS queries/responses (defaults: A,AAAA,CNAME,PTR records)', + filter='(udp and port 53)', + author='bg/twp', + optiondict={'show_noanswer': {'action': 'store_true', 'help': 'report unanswered queries alongside other queries'}, + 'show_norequest': {'action': 'store_true', 'help': 'report unsolicited responses alongside other responses'}, + 'only_noanswer': {'action': 'store_true', 'help': 'report only unanswered queries'}, + 'only_norequest': {'action': 'store_true', 'help': 'report only unsolicited responses'}, + 'showall': {'action': 'store_true', 'help': 'show all answered queries/responses'}} + ) - def decode_q(self,dns): + def decode_q(self, dns): queried = "" if dns.qd[0].type == dpkt.dns.DNS_A: queried = queried + "A? %s" % (dns.qd[0].name) @@ -25,12 +28,14 @@ def decode_q(self,dns): queried = queried + "AAAA? %s" % (dns.qd[0].name) if dns.qd[0].type == dpkt.dns.DNS_PTR: if dns.qd[0].name.endswith('.in-addr.arpa'): - query_name = '.'.join(reversed(dns.qd[0].name.split('.in-addr.arpa')[0].split('.'))) + query_name = '.'.join( + reversed(dns.qd[0].name.split('.in-addr.arpa')[0].split('.'))) else: query_name = dns.qd[0].name queried = queried + "PTR? %s" % (query_name) - if not self.showall: return queried + if not self.showall: + return queried if dns.qd[0].type == dpkt.dns.DNS_NS: queried = queried + "NS? %s" % (dns.qd[0].name) @@ -43,55 +48,75 @@ def decode_q(self,dns): return queried - def DNSHandler(self,conn,request,response,**kwargs): - if self.only_norequest and request is not None: return - if not self.show_norequest and request is None: return - anstext='' - queried='' - id=None - for dns in request,response: - if dns is None: continue - id=dns.id - #DNS Question, update connection info with query - if dns.qr==dpkt.dns.DNS_Q: conn.info(query=self.decode_q(dns)) + def DNSHandler(self, conn, request, response, **kwargs): + if self.only_norequest and request is not None: + return + if not self.show_norequest and request is None: + return + anstext = '' + queried = '' + id = None + for dns in request, response: + if dns is None: + continue + id = dns.id + # DNS Question, update connection info with query + if dns.qr == dpkt.dns.DNS_Q: + conn.info(query=self.decode_q(dns)) # DNS Answer with data and no errors - elif (dns.qr == dpkt.dns.DNS_A and dns.rcode == dpkt.dns.DNS_RCODE_NOERR and len(dns.an)>0): + elif (dns.qr == dpkt.dns.DNS_A and dns.rcode == dpkt.dns.DNS_RCODE_NOERR and len(dns.an) > 0): - queried=self.decode_q(dns) + queried = self.decode_q(dns) answers = [] for an in dns.an: if an.type == dpkt.dns.DNS_A: - try: answers.append('A: %s (ttl %ss)' % (socket.inet_ntoa(an.ip), str(an.ttl))) - except: continue + try: + answers.append( + 'A: %s (ttl %ss)' % (socket.inet_ntoa(an.ip), str(an.ttl))) + except: + continue elif an.type == dpkt.dns.DNS_AAAA: - try: answers.append('AAAA: %s (ttl %ss)' % (socket.inet_ntop(socket.AF_INET6,an.ip6),str(an.ttl))) - except: continue - elif an.type == dpkt.dns.DNS_CNAME: answers.append('CNAME: '+an.cname) - elif an.type == dpkt.dns.DNS_PTR: answers.append('PTR: '+an.ptrname) - elif an.type == dpkt.dns.DNS_NS: answers.append('NS: '+an.nsname) - elif an.type == dpkt.dns.DNS_MX: answers.append('MX: '+an.mxname) - elif an.type == dpkt.dns.DNS_TXT: answers.append('TXT: '+' '.join(an.text)) - elif an.type == dpkt.dns.DNS_SRV: answers.append('SRV: '+an.srvname) + try: + answers.append('AAAA: %s (ttl %ss)' % ( + socket.inet_ntop(socket.AF_INET6, an.ip6), str(an.ttl))) + except: + continue + elif an.type == dpkt.dns.DNS_CNAME: + answers.append('CNAME: ' + an.cname) + elif an.type == dpkt.dns.DNS_PTR: + answers.append('PTR: ' + an.ptrname) + elif an.type == dpkt.dns.DNS_NS: + answers.append('NS: ' + an.nsname) + elif an.type == dpkt.dns.DNS_MX: + answers.append('MX: ' + an.mxname) + elif an.type == dpkt.dns.DNS_TXT: + answers.append('TXT: ' + ' '.join(an.text)) + elif an.type == dpkt.dns.DNS_SRV: + answers.append('SRV: ' + an.srvname) else: # un-handled type continue if queried != '': - anstext =", ".join(answers) + anstext = ", ".join(answers) #NXDOMAIN in response elif dns.qr == dpkt.dns.DNS_A and dns.rcode == dpkt.dns.DNS_RCODE_NXDOMAIN: - queried = self.decode_q(dns) #decode query part + queried = self.decode_q(dns) # decode query part - if queried != '': anstext='NXDOMAIN' + if queried != '': + anstext = 'NXDOMAIN' - if anstext and not self.only_noanswer and not self.only_norequest: #did we get an answer? - self.alert(str(id)+' '+queried+' / '+anstext,**conn.info(response=anstext)) + # did we get an answer? + if anstext and not self.only_noanswer and not self.only_norequest: + self.alert( + str(id) + ' ' + queried + ' / ' + anstext, **conn.info(response=anstext)) elif not anstext and (self.show_noanswer or self.only_noanswer): - self.alert(str(id)+' '+conn.query+' / (no answer)',**conn.info()) + self.alert( + str(id) + ' ' + conn.query + ' / (no answer)', **conn.info()) -if __name__=='__main__': +if __name__ == '__main__': dObj = DshellDecoder() print dObj else: diff --git a/decoders/dns/innuendo-dns.py b/decoders/dns/innuendo-dns.py index 2810570..0799c18 100644 --- a/decoders/dns/innuendo-dns.py +++ b/decoders/dns/innuendo-dns.py @@ -2,82 +2,91 @@ from dnsdecoder import DNSDecoder import base64 + class DshellDecoder(DNSDecoder): + """ Proof-of-concept Dshell decoder to detect INNUENDO DNS Channel - Based on the short marketing video [http://vimeo.com/115206626] the INNUENDO - DNS Channel relies on DNS to communicate with an authoritative name server. - The name server will respond with a base64 encoded TXT answer. This decoder - will analyze DNS TXT queries and responses to determine if it matches the - network traffic described in the video. There are multiple assumptions (*very - poor*) in this detection plugin but serves as a proof-of-concept detector. This - detector has not been tested against authentic INNUENDO DNS Channel traffic. + Based on the short marketing video [http://vimeo.com/115206626] the INNUENDO + DNS Channel relies on DNS to communicate with an authoritative name server. + The name server will respond with a base64 encoded TXT answer. This decoder + will analyze DNS TXT queries and responses to determine if it matches the + network traffic described in the video. There are multiple assumptions (*very + poor*) in this detection plugin but serves as a proof-of-concept detector. This + detector has not been tested against authentic INNUENDO DNS Channel traffic. - Usage: decode -d innuendo-dns *.pcap + Usage: decode -d innuendo-dns *.pcap """ def __init__(self): DNSDecoder.__init__(self, - name = 'innuendo-dns', - description = 'proof-of-concept detector for INNUENDO DNS channel', - filter = '(port 53)', - author = 'primalsec', - ) - self.whitelist = [] # probably be necessary to whitelist A/V domains - - def in_whitelist(self, domain): + name='innuendo-dns', + description='proof-of-concept detector for INNUENDO DNS channel', + filter='(port 53)', + author='primalsec', + ) + self.whitelist = [] # probably be necessary to whitelist A/V domains + + def in_whitelist(self, domain): # add logic return False def decrypt_payload(payload): pass - def DNSHandler(self,conn,request,response,**kwargs): + def DNSHandler(self, conn, request, response, **kwargs): query = '' answers = [] - for dns in request,response: + for dns in request, response: - if dns is None: continue + if dns is None: + continue id = dns.id - #DNS Question, extract query name if it is a TXT record request - if dns.qr==dpkt.dns.DNS_Q and dns.qd[0].type == dpkt.dns.DNS_TXT: + # DNS Question, extract query name if it is a TXT record request + if dns.qr == dpkt.dns.DNS_Q and dns.qd[0].type == dpkt.dns.DNS_TXT: query = dns.qd[0].name # DNS Answer with data and no errors - elif (dns.qr == dpkt.dns.DNS_A and dns.rcode == dpkt.dns.DNS_RCODE_NOERR and len(dns.an)>0): + elif (dns.qr == dpkt.dns.DNS_A and dns.rcode == dpkt.dns.DNS_RCODE_NOERR and len(dns.an) > 0): for an in dns.an: if an.type == dpkt.dns.DNS_TXT: answers.append(an.text[0]) - if query != '' and len(answers)>0: - # add check here to see if the second level domain and top level domain are not in a white list - if self.in_whitelist(query): return + if query != '' and len(answers) > 0: + # add check here to see if the second level domain and top level + # domain are not in a white list + if self.in_whitelist(query): + return # assumption: INNUENDO will use the lowest level domain for C2 - # example: AAAABBBBCCCC.foo.bar.com -> AAAABBBBCCCC is the INNUENDO data + # example: AAAABBBBCCCC.foo.bar.com -> AAAABBBBCCCC is the INNUENDO + # data subdomain = query.split('.')[0] - if subdomain.isupper(): # weak test based on video observation *very poor assumption* + # weak test based on video observation *very poor assumption* + if subdomain.isupper(): # check each answer in the TXT response for answer in answers: try: - # INNUENDO DNS channel base64 encodes the response, check to see if + # INNUENDO DNS channel base64 encodes the response, check to see if # it contains a valid base64 string *poor assumption* - dummy = base64.b64decode( answer ) + dummy = base64.b64decode(answer) + + self.alert( + 'INNUENDO DNS Channel', query, '/', answer, **conn.info()) - self.alert('INNUENDO DNS Channel', query ,'/',answer,**conn.info()) - # here would be a good place to decrypt the payload (if you have the keys) # decrypt_payload( answer ) - except: pass - + except: + pass + -if __name__=='__main__': +if __name__ == '__main__': dObj = DshellDecoder() print dObj else: diff --git a/decoders/dns/reservedips.py b/decoders/dns/reservedips.py index 655152f..8478dce 100644 --- a/decoders/dns/reservedips.py +++ b/decoders/dns/reservedips.py @@ -1,61 +1,98 @@ -import dshell, dpkt, socket +import dshell +import dpkt +import socket from dnsdecoder import DNSDecoder import IPy + class DshellDecoder(DNSDecoder): + def __init__(self): DNSDecoder.__init__(self, - name = 'reservedips', - description = 'identify DNS resolutions that fall into reserved ip space', - filter = '(port 53)', - author = 'bg', - cleanupinterval=10, - maxblobs=2, - ) + name='reservedips', + description='identify DNS resolutions that fall into reserved ip space', + filter='(port 53)', + author='bg', + cleanupinterval=10, + maxblobs=2, + ) # source: https://en.wikipedia.org/wiki/Reserved_IP_addresses - nets = [ '0.0.0.0/8', # Used for broadcast messages to the current ("this") network as specified by RFC 1700, page 4. - '10.0.0.0/8', # Used for local communications within a private network as specified by RFC 1918. - '100.64.0.0/10', #Used for communications between a service provider and its subscribers when using a Carrier-grade NAT, as specified by RFC 6598. - '127.0.0.0/8', # Used for loopback addresses to the local host, as specified by RFC 990. - '169.254.0.0/16', # Used for autoconfiguration between two hosts on a single link when no IP address is otherwise specified - '172.16.0.0/12', # Used for local communications within a private network as specified by RFC 1918 - '192.0.0.0/29', # Used for the DS-Lite transition mechanism as specified by RFC 6333 - '192.0.2.0/24', # Assigned as "TEST-NET" in RFC 5737 for use solely in documentation and example source code and should not be used publicly - '192.88.99.0/24', # Used by 6to4 anycast relays as specified by RFC 3068 - '192.168.0.0/16', # Used for local communications within a private network as specified by RFC 1918 - '198.18.0.0/15', # Used for testing of inter-network communications between two separate subnets as specified in RFC 2544 - '198.51.100.0/24', # Assigned as "TEST-NET-2" in RFC 5737 for use solely in documentation and example source code and should not be used publicly - '203.0.113.0/24', # Assigned as "TEST-NET-3" in RFC 5737 for use solely in documentation and example source code and should not be used publicly - '224.0.0.0/4', # Reserved for multicast assignments as specified in RFC 5771 - '240.0.0.0/4', # Reserved for future use, as specified by RFC 6890 - '255.255.255.255/32', # Reserved for the "limited broadcast" destination address, as specified by RFC 6890 + nets = ['0.0.0.0/8', # Used for broadcast messages to the current ("this") network as specified by RFC 1700, page 4. + # Used for local communications within a private network as + # specified by RFC 1918. + '10.0.0.0/8', + # Used for communications between a service provider and its + # subscribers when using a Carrier-grade NAT, as specified by + # RFC 6598. + '100.64.0.0/10', + # Used for loopback addresses to the local host, as specified + # by RFC 990. + '127.0.0.0/8', + # Used for autoconfiguration between two hosts on a single + # link when no IP address is otherwise specified + '169.254.0.0/16', + # Used for local communications within a private network as + # specified by RFC 1918 + '172.16.0.0/12', + # Used for the DS-Lite transition mechanism as specified by + # RFC 6333 + '192.0.0.0/29', + # Assigned as "TEST-NET" in RFC 5737 for use solely in + # documentation and example source code and should not be used + # publicly + '192.0.2.0/24', + # Used by 6to4 anycast relays as specified by RFC 3068 + '192.88.99.0/24', + # Used for local communications within a private network as + # specified by RFC 1918 + '192.168.0.0/16', + # Used for testing of inter-network communications between two + # separate subnets as specified in RFC 2544 + '198.18.0.0/15', + # Assigned as "TEST-NET-2" in RFC 5737 for use solely in + # documentation and example source code and should not be used + # publicly + '198.51.100.0/24', + # Assigned as "TEST-NET-3" in RFC 5737 for use solely in + # documentation and example source code and should not be used + # publicly + '203.0.113.0/24', + # Reserved for multicast assignments as specified in RFC 5771 + '224.0.0.0/4', + # Reserved for future use, as specified by RFC 6890 + '240.0.0.0/4', + # Reserved for the "limited broadcast" destination address, as + # specified by RFC 6890 + '255.255.255.255/32', - '::/128', # Unspecified address - '::1/128', # loopback address to the local host. - '::ffff:0:0/96', # IPv4 mapped addresses - '100::/64', # Discard Prefix RFC 6666 - '64:ff9b::/96', # IPv4/IPv6 translation (RFC 6052) - '2001::/32', # Teredo tunneling - '2001:10::/28', # Overlay Routable Cryptographic Hash Identifiers (ORCHID) - '2001:db8::/32', # Addresses used in documentation - '2002::/16', # 6to4 - 'fc00::/7', # Unique local address - 'fe80::/10', # Link-local address - 'ff00::/8', # Multicast + '::/128', # Unspecified address + '::1/128', # loopback address to the local host. + '::ffff:0:0/96', # IPv4 mapped addresses + '100::/64', # Discard Prefix RFC 6666 + '64:ff9b::/96', # IPv4/IPv6 translation (RFC 6052) + '2001::/32', # Teredo tunneling + # Overlay Routable Cryptographic Hash Identifiers (ORCHID) + '2001:10::/28', + '2001:db8::/32', # Addresses used in documentation + '2002::/16', # 6to4 + 'fc00::/7', # Unique local address + 'fe80::/10', # Link-local address + 'ff00::/8', # Multicast ] - self.reservednets= [] + self.reservednets = [] for net in nets: self.reservednets.append(IPy.IP(net)) self.domains = [] # list for known domains - def inReservedSpace(self,ipaddress): + def inReservedSpace(self, ipaddress): for net in self.reservednets: - if ipaddress in net: return True + if ipaddress in net: + return True return False - def decode_q(self,dns): + def decode_q(self, dns): queried = "" if dns.qd[0].type == dpkt.dns.DNS_A: queried = queried + "A? %s" % (dns.qd[0].name) @@ -63,43 +100,51 @@ def decode_q(self,dns): queried = queried + "AAAA? %s" % (dns.qd[0].name) return queried - def DNSHandler(self,conn,request,response,**kwargs): - anstext='' - queried='' - id=None - for dns in request,response: - if dns is None: continue - id=dns.id - #DNS Question, update connection info with query - if dns.qr==dpkt.dns.DNS_Q: conn.info(query=self.decode_q(dns)) + def DNSHandler(self, conn, request, response, **kwargs): + anstext = '' + queried = '' + id = None + for dns in request, response: + if dns is None: + continue + id = dns.id + # DNS Question, update connection info with query + if dns.qr == dpkt.dns.DNS_Q: + conn.info(query=self.decode_q(dns)) # DNS Answer with data and no errors - elif (dns.qr == dpkt.dns.DNS_A and dns.rcode == dpkt.dns.DNS_RCODE_NOERR and len(dns.an)>0): + elif (dns.qr == dpkt.dns.DNS_A and dns.rcode == dpkt.dns.DNS_RCODE_NOERR and len(dns.an) > 0): - queried=self.decode_q(dns) + queried = self.decode_q(dns) answers = [] for an in dns.an: if an.type == dpkt.dns.DNS_A: try: - if self.inReservedSpace(socket.inet_ntoa(an.ip)): answers.append('A: '+socket.inet_ntoa(an.ip)+' (ttl '+str(an.ttl)+'s)') - except: continue + if self.inReservedSpace(socket.inet_ntoa(an.ip)): + answers.append( + 'A: ' + socket.inet_ntoa(an.ip) + ' (ttl ' + str(an.ttl) + 's)') + except: + continue elif an.type == dpkt.dns.DNS_AAAA: try: - if self.inReservedSpace(socket.inet_ntop(socket.AF_INET6,an.ip6)): answers.append('AAAA: '+socket.inet_ntop(socket.AF_INET6,an.ip6)+' (ttl '+str(an.ttl)+'s)') - except: continue + if self.inReservedSpace(socket.inet_ntop(socket.AF_INET6, an.ip6)): + answers.append( + 'AAAA: ' + socket.inet_ntop(socket.AF_INET6, an.ip6) + ' (ttl ' + str(an.ttl) + 's)') + except: + continue else: # un-handled type continue if queried != '': - anstext =", ".join(answers) - - if anstext: #did we get an answer? - self.alert(str(id)+' '+queried+' / '+anstext,**conn.info(response=anstext)) + anstext = ", ".join(answers) + if anstext: # did we get an answer? + self.alert( + str(id) + ' ' + queried + ' / ' + anstext, **conn.info(response=anstext)) -if __name__=='__main__': +if __name__ == '__main__': dObj = DshellDecoder() print dObj else: diff --git a/decoders/filter/country.py b/decoders/filter/country.py index 46498e7..cfde218 100644 --- a/decoders/filter/country.py +++ b/decoders/filter/country.py @@ -2,22 +2,26 @@ @author: tparker ''' -import dshell,util +import dshell +import util import netflowout + class DshellDecoder(dshell.TCPDecoder): + '''activity tracker ''' - def __init__(self,**kwargs): + + def __init__(self, **kwargs): ''' Constructor ''' - self.sessions={} - self.alerts=False - self.file=None + self.sessions = {} + self.alerts = False + self.file = None dshell.TCPDecoder.__init__(self, - name = 'country', - description = 'filter connections on geolocation (country code)', - longdescription=""" + name='country', + description='filter connections on geolocation (country code)', + longdescription=""" country: filter connections on geolocation (country code) Chainable decoder to filter TCP/UDP streams on geolocation data. If no @@ -51,57 +55,70 @@ def __init__(self,**kwargs): decode -d country traffic.pcap -W USonly.pcap --country_code US decode -d country+followstream traffic.pcap --country_code US --country_notboth """, - filter="ip or ip6", - author='twp', - optiondict={ - 'code':{'type':'string','help':'two-char country code'}, - 'neither':{'action':'store_true','help':'neither (client/server) is in specified country'}, - 'both':{'action':'store_true','help':'both (client/server) ARE in specified country'}, - 'notboth':{'action':'store_true','help':'specified country is not both client and server'}, - 'alerts':{'action':'store_true'}} ) + filter="ip or ip6", + author='twp', + optiondict={ + 'code': {'type': 'string', 'help': 'two-char country code'}, + 'neither': {'action': 'store_true', 'help': 'neither (client/server) is in specified country'}, + 'both': {'action': 'store_true', 'help': 'both (client/server) ARE in specified country'}, + 'notboth': {'action': 'store_true', 'help': 'specified country is not both client and server'}, + 'alerts': {'action': 'store_true'}}) '''instantiate an decoder that will call back to us once the IP decoding is done''' - self.__decoder=dshell.IPDecoder() - self.out=netflowout.NetflowOutput() - self.chainable=True - - def decode(self,*args): - if len(args) is 3: pktlen,pktdata,ts=args #orig_len,packet,ts format (pylibpcap) - else: #ts,pktdata (pypcap) - ts,pktdata=args - pktlen=len(pktdata) + self.__decoder = dshell.IPDecoder() + self.out = netflowout.NetflowOutput() + self.chainable = True + + def decode(self, *args): + if len(args) is 3: + pktlen, pktdata, ts = args # orig_len,packet,ts format (pylibpcap) + else: # ts,pktdata (pypcap) + ts, pktdata = args + pktlen = len(pktdata) '''do normal decoder stack to track session ''' - dshell.TCPDecoder.decode(self,pktlen,pktdata,ts) + dshell.TCPDecoder.decode(self, pktlen, pktdata, ts) '''our hook to decode the ip/ip6 addrs, then dump the addrs and raw packet to our callback''' - self.__decoder.IPHandler=self.__callback #set private decoder to our callback - self.__decoder.decode(pktlen,pktdata,ts,raw=pktdata) + self.__decoder.IPHandler = self.__callback # set private decoder to our callback + self.__decoder.decode(pktlen, pktdata, ts, raw=pktdata) - def __callback(self,addr,pkt,ts,raw=None,**kw): + def __callback(self, addr, pkt, ts, raw=None, **kw): '''substitute IPhandler for forwarding packets to subdecoders''' - if addr in self.sessions or (addr[1],addr[0]) in self.sessions: #if we are not passing this session, drop the packet - if self.subDecoder: self.subDecoder.decode(len(raw),str(raw),ts) #make it look like a capture - else: self.dump(raw,ts) - - def connectionInitHandler(self,conn): + if addr in self.sessions or (addr[1], addr[0]) in self.sessions: # if we are not passing this session, drop the packet + if self.subDecoder: + # make it look like a capture + self.subDecoder.decode(len(raw), str(raw), ts) + else: + self.dump(raw, ts) + + def connectionInitHandler(self, conn): '''see if we have a country match and if so, flag this session for forwarding or dumping''' - m=self.__countryTest(conn) - if m: self.sessions[conn.addr]=m + m = self.__countryTest(conn) + if m: + self.sessions[conn.addr] = m def __countryTest(self, conn): # If no country code specified, pass all traffic through - if self.code == None or not len(self.code): return True - #check criteria - if self.neither and conn.clientcountrycode != self.code and conn.servercountrycode != self.code: return 'neither '+self.code - if self.both and conn.clientcountrycode == self.code and conn.servercountrycode == self.code: return 'both '+self.code - if self.notboth and (conn.clientcountrycode != self.code or conn.servercountrycode != self.code): return 'not both '+self.code - if conn.clientcountrycode == self.code: return 'client '+self.code - if conn.servercountrycode == self.code: return 'server '+self.code - #no match + if self.code == None or not len(self.code): + return True + # check criteria + if self.neither and conn.clientcountrycode != self.code and conn.servercountrycode != self.code: + return 'neither ' + self.code + if self.both and conn.clientcountrycode == self.code and conn.servercountrycode == self.code: + return 'both ' + self.code + if self.notboth and (conn.clientcountrycode != self.code or conn.servercountrycode != self.code): + return 'not both ' + self.code + if conn.clientcountrycode == self.code: + return 'client ' + self.code + if conn.servercountrycode == self.code: + return 'server ' + self.code + # no match return None - def connectionHandler(self,conn): - if conn.addr in self.sessions and self.alerts: self.alert(self.sessions[conn.addr],**conn.info()) + def connectionHandler(self, conn): + if conn.addr in self.sessions and self.alerts: + self.alert(self.sessions[conn.addr], **conn.info()) - def connectionCloseHandler(self,conn): - if conn.addr in self.sessions: del self.sessions[conn.addr] + def connectionCloseHandler(self, conn): + if conn.addr in self.sessions: + del self.sessions[conn.addr] dObj = DshellDecoder() diff --git a/decoders/filter/snort.py b/decoders/filter/snort.py index 021e29a..8a79340 100644 --- a/decoders/filter/snort.py +++ b/decoders/filter/snort.py @@ -1,11 +1,13 @@ import dshell + class DshellDecoder(dshell.IPDecoder): + def __init__(self): dshell.IPDecoder.__init__(self, - name = 'snort', - description = 'filter packets by snort rule', - longdescription="""Chainable decoder to filter TCP/UDP streams by snort rule + name='snort', + description='filter packets by snort rule', + longdescription="""Chainable decoder to filter TCP/UDP streams by snort rule rule is parsed by dshell, a limited number of options are supported: currently supported rule options: content @@ -33,120 +35,174 @@ def __init__(self): decode -d snort+followstream traffic.pcap --snort_rule 'alert tcp any any -> any any (content:"....."; nocase; depth .... )' """, - filter = 'ip or ip6', - author = 'twp', - optiondict={ 'rule':{'type':'string','help':'snort rule to filter packets'}, - 'conf':{'type':'string','help':'snort.conf file to read'}, - 'alerts':{'action':'store_true','help':'alert if rule matched' }, - 'none':{'action':'store_true','help':'pass if NO rules matched' }, - 'all':{'action':'store_true','help':'all rules must match to pass' } - } - ) - self.chainable=True + filter='ip or ip6', + author='twp', + optiondict={'rule': {'type': 'string', 'help': 'snort rule to filter packets'}, + 'conf': {'type': 'string', 'help': 'snort.conf file to read'}, + 'alerts': {'action': 'store_true', 'help': 'alert if rule matched'}, + 'none': {'action': 'store_true', 'help': 'pass if NO rules matched'}, + 'all': {'action': 'store_true', 'help': 'all rules must match to pass'} + } + ) + self.chainable = True def preModule(self): - rules=[] - if self.conf: # - fh=file(self.conf) - rules=[r for r in (r.strip() for r in fh.readlines()) if len(r)] + rules = [] + if self.conf: + fh = file(self.conf) + rules = [r for r in (r.strip() for r in fh.readlines()) if len(r)] fh.close() else: - if not self.rule or not len(self.rule): self.warn("No rule specified (--%s_rule)" % self.name) - else: rules=[self.rule] - self.rules=[] + if not self.rule or not len(self.rule): + self.warn("No rule specified (--%s_rule)" % self.name) + else: + rules = [self.rule] + self.rules = [] for r in rules: - try: self.rules.append( ( self.parseSnortRule(r) ) ) - except Exception,e: - self.error('bad snort rule "%s": %s'%(r,e)) - if self._DEBUG: self._exc(e) - if self.subDecoder: self.subDecoder.ignore_handshake=True #we filter individual packets so session-based subdecoders will need this set + try: + self.rules.append((self.parseSnortRule(r))) + except Exception, e: + self.error('bad snort rule "%s": %s' % (r, e)) + if self._DEBUG: + self._exc(e) + if self.subDecoder: + # we filter individual packets so session-based subdecoders will + # need this set + self.subDecoder.ignore_handshake = True dshell.IPDecoder.preModule(self) - def rawHandler(self,pktlen,pkt,ts,**kwargs): - kwargs['raw']=pkt #put the raw frame in the kwargs - return dshell.IPDecoder.rawHandler(self,pktlen,pkt,ts,**kwargs) #continue decoding + def rawHandler(self, pktlen, pkt, ts, **kwargs): + kwargs['raw'] = pkt # put the raw frame in the kwargs + # continue decoding + return dshell.IPDecoder.rawHandler(self, pktlen, pkt, ts, **kwargs) - def IPHandler(self,addr,pkt,ts,**kwargs): + def IPHandler(self, addr, pkt, ts, **kwargs): '''check packets using filterfn here''' - raw=str(kwargs['raw']) #get the raw frame for forwarding if we match - p=dshell.Packet(self,addr,pkt=str(pkt),ts=ts,**kwargs) - a=[] - match=None - for r,msg in self.rules: - if r(p): #if this rule matched - match=True - if msg: a.append(msg) #append rule message to alerts - if self.none or not self.all: break #unless matching all, one match does it - else: #last rule did not match - match=False - if self.all: break #stop once no match if all - - #all rules processed, match = state of last rule match + raw = str( + kwargs['raw']) # get the raw frame for forwarding if we match + p = dshell.Packet(self, addr, pkt=str(pkt), ts=ts, **kwargs) + a = [] + match = None + for r, msg in self.rules: + if r(p): # if this rule matched + match = True + if msg: + a.append(msg) # append rule message to alerts + if self.none or not self.all: + break # unless matching all, one match does it + else: # last rule did not match + match = False + if self.all: + break # stop once no match if all + + # all rules processed, match = state of last rule match if (match is not None) and ((match and not self.none) or (self.none and not match)): - self.decodedbytes+=len(str(pkt)) - self.count+=1 - if self.alerts: self.alert(*a,**p.info()) - if self.subDecoder: self.subDecoder.decode(len(raw),raw,ts) #decode or dump packet - else: self.dump(len(raw),raw,ts) - - def parseSnortRule(self,ruletext): + self.decodedbytes += len(str(pkt)) + self.count += 1 + if self.alerts: + self.alert(*a, **p.info()) + if self.subDecoder: + # decode or dump packet + self.subDecoder.decode(len(raw), raw, ts) + else: + self.dump(len(raw), raw, ts) + + def parseSnortRule(self, ruletext): '''returns a lambda function that can be used to filter traffic and the alert message this function will expect a Packet() object and return True or False''' - KEYWORDS=('msg','content') #rule start, signal when we process all seen keywords - msg='' - f=[] - rule=ruletext.split(' ',7) - (a,proto,sip,sp,arrow,dip,dp)=rule[:7] - if len(rule)>7: rule=rule[7] - else: rule=None - if a != 'alert': raise Exception('Must be alert rule') - f.append('p.proto == "'+proto.upper()+'"') - if sip != 'any': f.append('p.sip == "'+sip+'"') - if dip != 'any': f.append('p.dip == "'+dip+'"') - if sp != 'any': f.append('p.sport == '+sp) - if dp != 'any': f.append('p.dport == '+dp) - f=['(' + (' and '.join(f)) + ')' ] #create header condition - if rule: rule=rule.strip('()').split(';') #split between () and split on ; - last=None #no last match + KEYWORDS = ( + 'msg', 'content') # rule start, signal when we process all seen keywords + msg = '' + f = [] + rule = ruletext.split(' ', 7) + (a, proto, sip, sp, arrow, dip, dp) = rule[:7] + if len(rule) > 7: + rule = rule[7] + else: + rule = None + if a != 'alert': + raise Exception('Must be alert rule') + f.append('p.proto == "' + proto.upper() + '"') + if sip != 'any': + f.append('p.sip == "' + sip + '"') + if dip != 'any': + f.append('p.dip == "' + dip + '"') + if sp != 'any': + f.append('p.sport == ' + sp) + if dp != 'any': + f.append('p.dport == ' + dp) + f = ['(' + (' and '.join(f)) + ')'] # create header condition + if rule: + # split between () and split on ; + rule = rule.strip('()').split(';') + last = None # no last match while rule: - try: k,v=rule.pop(0).strip().split(':',1) - except: continue - if k.lower() == 'content': #reset content match - content=v.strip().strip('"') - if content.startswith('|') and content.endswith('|'): #hex bytes? - content=''.join( '\\x'+c for c in content.strip('|').split() ) - nocase=depth=offset=distance=within=None + try: + k, v = rule.pop(0).strip().split(':', 1) + except: + continue + if k.lower() == 'content': # reset content match + content = v.strip().strip('"') + # hex bytes? + if content.startswith('|') and content.endswith('|'): + content = ''.join( + '\\x' + c for c in content.strip('|').split()) + nocase = depth = offset = distance = within = None while rule: - r=rule[0].strip() - if ':' in r: k,v=r.split(':',1) - else: k,v=r,None - k=k.lower() - if k in KEYWORDS: break #next rule part - elif k == 'nocase': nocase=True - elif k == 'depth': depth=int(v) - elif k == 'offset': offset=int(v) - elif k == 'distance': distance=int(v) - elif k == 'within': within=int(v) - rule.pop(0) #remove this keyword:valuea - #add coerce to lower if nocase? - if nocase: nocase='.lower()' - else: nocase='' - st,end=offset,depth #start,end offsets of find(), maybe number or result of another find() - if last: #if we have a last content match, use the distance/within kws - #within means this match has to be within X from previous+distance, so use previous as offset and within as depth - if within: st,end=last,last+'+'+str(within) #set to last match and X from last match - #distance means the next match must be AT LEAST X from the last - if distance: st=last+'+'+str(distance)# set start to last match+distance - #else use the offset/depth values as given - last='p.pkt'+nocase+'.find('+"'"+content+"'"+nocase+','+str(st)+','+str(end)+') != -1' - if k.lower() == 'msg': msg=v.strip().strip('"')#get alert message - if last: f.append('('+last+')') - f=' and '.join(f) - self.debug('%s\t%s\t"%s"'%(ruletext,f,msg)) - return eval('lambda(p): '+f),msg # return fn and msg - - -if __name__=='__main__': + r = rule[0].strip() + if ':' in r: + k, v = r.split(':', 1) + else: + k, v = r, None + k = k.lower() + if k in KEYWORDS: + break # next rule part + elif k == 'nocase': + nocase = True + elif k == 'depth': + depth = int(v) + elif k == 'offset': + offset = int(v) + elif k == 'distance': + distance = int(v) + elif k == 'within': + within = int(v) + rule.pop(0) # remove this keyword:valuea + # add coerce to lower if nocase? + if nocase: + nocase = '.lower()' + else: + nocase = '' + # start,end offsets of find(), maybe number or result of + # another find() + st, end = offset, depth + # if we have a last content match, use the distance/within kws + if last: + # within means this match has to be within X from + # previous+distance, so use previous as offset and within + # as depth + if within: + # set to last match and X from last match + st, end = last, last + '+' + str(within) + # distance means the next match must be AT LEAST X from the + # last + if distance: + # set start to last match+distance + st = last + '+' + str(distance) + # else use the offset/depth values as given + last = 'p.pkt' + nocase + \ + '.find(' + "'" + content + "'" + nocase + ',' + \ + str(st) + ',' + str(end) + ') != -1' + if k.lower() == 'msg': + msg = v.strip().strip('"') # get alert message + if last: + f.append('(' + last + ')') + f = ' and '.join(f) + self.debug('%s\t%s\t"%s"' % (ruletext, f, msg)) + return eval('lambda(p): ' + f), msg # return fn and msg + + +if __name__ == '__main__': dObj = DshellDecoder() print dObj else: diff --git a/decoders/filter/track.py b/decoders/filter/track.py index cda1a77..3d83d7b 100644 --- a/decoders/filter/track.py +++ b/decoders/filter/track.py @@ -2,114 +2,134 @@ @author: tparker ''' -import dshell,util +import dshell +import util + class DshellDecoder(dshell.TCPDecoder): + '''activity tracker ''' - def __init__(self,**kwargs): + + def __init__(self, **kwargs): ''' Constructor ''' - self.sources=[] - self.targets=[] - self.sessions={} - self.alerts=False - self.file=None + self.sources = [] + self.targets = [] + self.sessions = {} + self.alerts = False + self.file = None dshell.TCPDecoder.__init__(self, - name='track', - description='tracked activity recorder', - longdescription='''captures all traffic to/from target while a specific connection to the target is up + name='track', + description='tracked activity recorder', + longdescription='''captures all traffic to/from target while a specific connection to the target is up specify target(s) ip and/or port as --track_target=ip:port,ip... --track_source=ip,ip.. can be used to limit to specified sources --track_alerts will turn on alerts for session start/end''', - filter="ip", - author='twp', - optiondict={'target':{'action':'append'}, - 'source':{'action':'append'}, - 'alerts':{'action':'store_true'}} ) - self.chainable=True + filter="ip", + author='twp', + optiondict={'target': {'action': 'append'}, + 'source': {'action': 'append'}, + 'alerts': {'action': 'store_true'}}) + self.chainable = True '''instantiate an IPDecoder and replace the IPHandler to decode the ip/ip6 addr and then pass the packet to _IPHandler, which will write the packet if in addr is in session''' - self.__decoder=dshell.IPDecoder() - + self.__decoder = dshell.IPDecoder() def preModule(self): '''parse the source and target lists''' if self.target: for tstr in self.target: - targets=util.strtok(tstr, as_list=True)[0] + targets = util.strtok(tstr, as_list=True)[0] for t in targets: try: - parts=t.split(':') - if len(parts)==2: ip,port=parts #IP:port - else: ip,port=t,None #IPv6 addr - except: ip,port=t,None #IP - if ip=='': ip=None # :port - self.targets.append((ip,port)) + parts = t.split(':') + if len(parts) == 2: + ip, port = parts # IP:port + else: + ip, port = t, None # IPv6 addr + except: + ip, port = t, None # IP + if ip == '': + ip = None # :port + self.targets.append((ip, port)) if self.source: for sstr in self.source: - sources=util.strtok(sstr, as_list=True)[0] + sources = util.strtok(sstr, as_list=True)[0] for ip in sources: self.sources.append(ip) dshell.TCPDecoder.preModule(self) - def decode(self,*args): - if len(args) is 3: pktlen,pktdata,ts=args #orig_len,packet,ts format (pylibpcap) - else: #ts,pktdata (pypcap) - ts,pktdata=args - pktlen=len(pktdata) + def decode(self, *args): + if len(args) is 3: + pktlen, pktdata, ts = args # orig_len,packet,ts format (pylibpcap) + else: # ts,pktdata (pypcap) + ts, pktdata = args + pktlen = len(pktdata) '''do normal decoder stack to track session ''' - dshell.TCPDecoder.decode(self,pktlen,pktdata,ts) + dshell.TCPDecoder.decode(self, pktlen, pktdata, ts) '''our hook to decode the ip/ip6 addrs, then dump the addrs and raw packet to our session check routine''' - self.__decoder.IPHandler=self.__callback #set private decoder to our callback - self.__decoder.decode(pktlen,pktdata,ts,raw=pktdata) + self.__decoder.IPHandler = self.__callback # set private decoder to our callback + self.__decoder.decode(pktlen, pktdata, ts, raw=pktdata) - def __callback(self,addr,pkt,ts,raw=None,**kw): + def __callback(self, addr, pkt, ts, raw=None, **kw): '''check to see if this packet is to/from an IP in a session, if so write it. the packet will be passed in the 'raw' kwarg''' - if addr[0][0] in self.sessions: ip=addr[0][0] #source ip - elif addr[1][0] in self.sessions: ip=addr[1][0] #dest ip - else: return #not tracked + if addr[0][0] in self.sessions: + ip = addr[0][0] # source ip + elif addr[1][0] in self.sessions: + ip = addr[1][0] # dest ip + else: + return # not tracked for s in self.sessions[ip].values(): - s.sessionpackets+=1 - s.sessionbytes+=len(raw) #actual captured data len - #dump the packet or sub-decode it - if self.subDecoder: self.subDecoder.decode(len(raw),str(raw),ts) #make it look like a capture - else: self.dump(raw,ts) + s.sessionpackets += 1 + s.sessionbytes += len(raw) # actual captured data len + # dump the packet or sub-decode it + if self.subDecoder: + # make it look like a capture + self.subDecoder.decode(len(raw), str(raw), ts) + else: + self.dump(raw, ts) - def connectionInitHandler(self,conn): + def connectionInitHandler(self, conn): '''see if dest ip and/or port is in target list and (if a source list) source ip is in source list if so, put the connection in the tracked-session list by dest ip if a new connection to the target comes in from an allowed source, the existing connection will still be tracked''' - ((sip,sport),(dip,dport))=conn.addr - sport,dport=str(sport),str(dport) - if ((dip,dport) in self.targets) or ((dip,None) in self.targets) or ((None,dport) in self.targets): + ((sip, sport), (dip, dport)) = conn.addr + sport, dport = str(sport), str(dport) + if ((dip, dport) in self.targets) or ((dip, None) in self.targets) or ((None, dport) in self.targets): if not self.sources or (sip in self.sources): - s=self.sessions.setdefault(dip,{}) - s[conn.addr]=conn - if self.alerts: self.alert('session started',**conn.info()) - conn.info(sessionpackets=0,sessionbytes=0) + s = self.sessions.setdefault(dip, {}) + s[conn.addr] = conn + if self.alerts: + self.alert('session started', **conn.info()) + conn.info(sessionpackets=0, sessionbytes=0) - def connectionHandler(self,conn): + def connectionHandler(self, conn): '''if a connection to a tracked-session host, alert and write if no subdecoder''' if self.alerts: - if conn.serverip in self.sessions: self.alert('inbound',**conn.info()) - if conn.clientip in self.sessions: self.alert('outbound',**conn.info()) + if conn.serverip in self.sessions: + self.alert('inbound', **conn.info()) + if conn.clientip in self.sessions: + self.alert('outbound', **conn.info()) if conn.serverip in self.sessions or conn.clientip in self.sessions: - if not self.subDecoder: self.write(conn) + if not self.subDecoder: + self.write(conn) - def connectionCloseHandler(self,conn): + def connectionCloseHandler(self, conn): '''close the tracked session if the initiating connection is closing make sure the conn in the session list matches, as we may have had more incoming connections to the same ip during the session''' if conn.serverip in self.sessions and conn.addr in self.sessions[conn.serverip]: - if self.alerts: self.alert('session ended',**conn.info()) + if self.alerts: + self.alert('session ended', **conn.info()) del self.sessions[conn.serverip][conn.addr] - if not self.sessions[conn.serverip]: del self.sessions[conn.serverip] + if not self.sessions[conn.serverip]: + del self.sessions[conn.serverip] dObj = DshellDecoder() diff --git a/decoders/flows/large-flows.py b/decoders/flows/large-flows.py index 23789a2..3a05fcc 100644 --- a/decoders/flows/large-flows.py +++ b/decoders/flows/large-flows.py @@ -1,30 +1,35 @@ import dshell import netflowout + class DshellDecoder(dshell.TCPDecoder): + def __init__(self): dshell.TCPDecoder.__init__(self, - name = 'large-flows', - description = 'display netflows that have at least 1MB transferred', - filter = 'tcp', - author = 'bg', - optiondict={'size': {'type':'float','default':1,'help':'number of megabytes transferred'}} - ) + name='large-flows', + description='display netflows that have at least 1MB transferred', + filter='tcp', + author='bg', + optiondict={'size': { + 'type': 'float', 'default': 1, 'help': 'number of megabytes transferred'}} + ) self.out = netflowout.NetflowOutput() self.min = 1048576 # 1MB def preModule(self): if self.size <= 0: - self.warn("Cannot have a size that's less than or equal to zero. (size: %s)" % (self.size)) + self.warn( + "Cannot have a size that's less than or equal to zero. (size: %s)" % (self.size)) self.size = 1 self.min = 104857 * self.size self.debug("Input: %s, Final size: %s bytes" % (self.size, self.min)) - def connectionHandler(self,conn): - if (conn.clientbytes + conn.serverbytes) >= self.min: self.alert(**conn.info()) + def connectionHandler(self, conn): + if (conn.clientbytes + conn.serverbytes) >= self.min: + self.alert(**conn.info()) -if __name__=='__main__': +if __name__ == '__main__': dObj = DshellDecoder() print dObj else: diff --git a/decoders/flows/long-flows.py b/decoders/flows/long-flows.py index 44a644f..6fefcb2 100644 --- a/decoders/flows/long-flows.py +++ b/decoders/flows/long-flows.py @@ -1,25 +1,28 @@ import dshell import netflowout + class DshellDecoder(dshell.TCPDecoder): + def __init__(self): - self.len=5 + self.len = 5 dshell.TCPDecoder.__init__(self, - name = 'long-flows', - description = 'display netflows that have a duration of at least 5mins', - filter = '(tcp or udp)', - author = 'bg', - optiondict={ - 'len':{'type':'int','default':5,'help':'set minimum connection time to alert on, in minutes [default: 5 mins]'}, - } - ) - self.out=netflowout.NetflowOutput() + name='long-flows', + description='display netflows that have a duration of at least 5mins', + filter='(tcp or udp)', + author='bg', + optiondict={ + 'len': {'type': 'int', 'default': 5, 'help': 'set minimum connection time to alert on, in minutes [default: 5 mins]'}, + } + ) + self.out = netflowout.NetflowOutput() - def connectionHandler(self,conn): - if (conn.endtime - conn.starttime) >= (60*self.len): self.alert(**conn.info()) + def connectionHandler(self, conn): + if (conn.endtime - conn.starttime) >= (60 * self.len): + self.alert(**conn.info()) -if __name__=='__main__': +if __name__ == '__main__': dObj = DshellDecoder() print dObj else: diff --git a/decoders/flows/netflow.py b/decoders/flows/netflow.py index 5f8c6f6..a563ae2 100644 --- a/decoders/flows/netflow.py +++ b/decoders/flows/netflow.py @@ -1,32 +1,36 @@ import dshell import netflowout + class DshellDecoder(dshell.TCPDecoder): + def __init__(self): dshell.TCPDecoder.__init__(self, - name = 'netflow', - description = 'generate netflow information from pcap', - longdescription = 'generate netflow information from pcap', - filter = '(tcp or udp)', - author = 'bg', - optiondict={'group':dict()} #grouping for output module - ) - self.out=netflowout.NetflowOutput() + name='netflow', + description='generate netflow information from pcap', + longdescription='generate netflow information from pcap', + filter='(tcp or udp)', + author='bg', + # grouping for output module + optiondict={'group': dict()} + ) + self.out = netflowout.NetflowOutput() def preModule(self): - #pass grouping to output module - if self.group: self.out.group=self.group.split(',') + # pass grouping to output module + if self.group: + self.out.group = self.group.split(',') dshell.TCPDecoder.preModule(self) - def connectionHandler(self,conn): + def connectionHandler(self, conn): self.alert(**conn.info()) def postModule(self): - self.out.close() #write flow groups if grouping + self.out.close() # write flow groups if grouping dshell.TCPDecoder.postModule(self) -if __name__=='__main__': +if __name__ == '__main__': dObj = DshellDecoder() print dObj else: diff --git a/decoders/http/httpdump.py b/decoders/http/httpdump.py index 684122c..73440a2 100644 --- a/decoders/http/httpdump.py +++ b/decoders/http/httpdump.py @@ -1,29 +1,36 @@ import dshell import util -import hashlib, urllib, re +import hashlib +import urllib +import re from httpdecoder import HTTPDecoder + class DshellDecoder(HTTPDecoder): + def __init__(self): HTTPDecoder.__init__(self, - name='httpdump', - description='Dump useful information about HTTP sessions', - filter='tcp and (port 80 or port 8080 or port 8000)', - filterfn=lambda ((sip,sp),(dip,dp)): sp in (80, 8000, 8080) or dp in (80, 8000, 8080), - author='amm', - optiondict={ - 'maxurilen':{'type':'int','default':30,'help':'Truncate URLs longer than max len. Set to 0 for no truncating. (default: 30)'}, - 'maxpost':{'type':'int','default':1000,'help':'Truncate POST body longer than max chars. Set to 0 for no truncating. (default: 1000)'}, - 'showcontent':{'action':'store_true','help':'Display response BODY.'}, - 'showhtml':{'action':'store_true','help':'Display response BODY only if HTML.'}, - 'urlfilter':{'type':'string','default':None,'help':'Filter to URLs matching this regex'}, - }, - ) - self.output='colorout' - self.gunzip=False # Disable auto-gunzip as we want to indicate content that was compressed in the output - - def HTTPHandler(self,conn,request,response,requesttime,responsetime): + name='httpdump', + description='Dump useful information about HTTP sessions', + filter='tcp and (port 80 or port 8080 or port 8000)', + filterfn=lambda ((sip, sp), (dip, dp)): sp in ( + 80, 8000, 8080) or dp in (80, 8000, 8080), + author='amm', + optiondict={ + 'maxurilen': {'type': 'int', 'default': 30, 'help': 'Truncate URLs longer than max len. Set to 0 for no truncating. (default: 30)'}, + 'maxpost': {'type': 'int', 'default': 1000, 'help': 'Truncate POST body longer than max chars. Set to 0 for no truncating. (default: 1000)'}, + 'showcontent': {'action': 'store_true', 'help': 'Display response BODY.'}, + 'showhtml': {'action': 'store_true', 'help': 'Display response BODY only if HTML.'}, + 'urlfilter': {'type': 'string', 'default': None, 'help': 'Filter to URLs matching this regex'}, + }, + ) + self.output = 'colorout' + # Disable auto-gunzip as we want to indicate content that was + # compressed in the output + self.gunzip = False + + def HTTPHandler(self, conn, request, response, requesttime, responsetime): host = '' loc = '' uri = '' @@ -46,82 +53,96 @@ def HTTPHandler(self,conn,request,response,requesttime,responsetime): reason = '' if self.urlfilter: - if not re.search(self.urlfilter, host+request.uri): return + if not re.search(self.urlfilter, host + request.uri): + return if '?' in request.uri: - [uri_location, uri_data] = request.uri.split('?',1) + [uri_location, uri_data] = request.uri.split('?', 1) else: uri_location = request.uri uri_data = '' - if self.maxurilen > 0 and len(uri_location)> self.maxurilen: - uri_location = uri_location[:self.maxurilen]+'[truncated]' + if self.maxurilen > 0 and len(uri_location) > self.maxurilen: + uri_location = uri_location[:self.maxurilen] + '[truncated]' else: uri_location = uri_location - if response == None: - response_message = "%s (%s) %s%s" % (request.method, 'NO RESPONSE', host, uri_location) + response_message = "%s (%s) %s%s" % ( + request.method, 'NO RESPONSE', host, uri_location) else: - response_message = "%s (%s) %s%s (%s)" % (request.method, response.status, host, uri_location, util.getHeader(response, 'content-type')) + response_message = "%s (%s) %s%s (%s)" % ( + request.method, response.status, host, uri_location, util.getHeader(response, 'content-type')) urlParams = util.URLDataToParameterDict(uri_data) postParams = util.URLDataToParameterDict(request.body) clientCookies = self._parseCookies(util.getHeader(request, 'cookie')) - serverCookies = self._parseCookies(util.getHeader(response, 'set-cookie')) + serverCookies = self._parseCookies( + util.getHeader(response, 'set-cookie')) self.alert(response_message, - urlParams=urlParams, postParams=postParams, clientCookies=clientCookies, serverCookies=serverCookies, - **conn.info() - ) + urlParams=urlParams, postParams=postParams, clientCookies=clientCookies, serverCookies=serverCookies, + **conn.info() + ) referer = util.getHeader(request, 'referer') - if len(referer): self.out.write(' Referer: %s\n' % referer) + if len(referer): + self.out.write(' Referer: %s\n' % referer) if clientCookies: self.out.write(' Client Transmitted Cookies:\n', direction='cs') for key in clientCookies: - self.out.write(' %s -> %s\n' % (util.printableUnicode(key),util.printableUnicode(clientCookies[key])), direction='cs') + self.out.write(' %s -> %s\n' % (util.printableUnicode(key), + util.printableUnicode(clientCookies[key])), direction='cs') if serverCookies: self.out.write(' Server Set Cookies:\n', direction='sc') for key in serverCookies: - self.out.write(' %s -> %s\n' % (util.printableUnicode(key),util.printableUnicode(serverCookies[key])), direction='sc') + self.out.write(' %s -> %s\n' % (util.printableUnicode(key), + util.printableUnicode(serverCookies[key])), direction='sc') if urlParams: self.out.write(' URLParameters:\n', direction='cs') for key in urlParams: - self.out.write(' %s -> %s\n' % (util.printableUnicode(key),util.printableUnicode(urlParams[key])), direction='cs') + self.out.write(' %s -> %s\n' % (util.printableUnicode(key), + util.printableUnicode(urlParams[key])), direction='cs') if postParams: self.out.write(' POSTParameters:\n', direction='cs') for key in postParams: - self.out.write(' %s -> %s\n' % (util.printableUnicode(key),util.printableUnicode(postParams[key])), direction='cs') + self.out.write(' %s -> %s\n' % (util.printableUnicode(key), + util.printableUnicode(postParams[key])), direction='cs') elif len(request.body): self.out.write(' POST Body:\n', direction='cs') if len(request.body) > self.maxpost and self.maxpost > 0: - self.out.write('%s[truncated]\n' % util.printableUnicode(request.body[:self.maxpost]), direction='cs') + self.out.write('%s[truncated]\n' % util.printableUnicode( + request.body[:self.maxpost]), direction='cs') else: - self.out.write(util.printableUnicode(request.body) + u"\n", direction='cs') + self.out.write( + util.printableUnicode(request.body) + u"\n", direction='cs') if self.showcontent or self.showhtml: - if self.showhtml and 'html' not in util.getHeader(response, 'content-type'): return + if self.showhtml and 'html' not in util.getHeader(response, 'content-type'): + return if 'gzip' in util.getHeader(response, 'content-encoding'): content = self.decompressGzipContent(response.body) - if content == None: content = '(gunzip failed)\n' + response.body - else: content = '(gzip encoded)\n' + content - else: content = response.body + if content == None: + content = '(gunzip failed)\n' + response.body + else: + content = '(gzip encoded)\n' + content + else: + content = response.body self.out.write("Body Content:\n", direction='sc') - self.out.write(util.printableUnicode(content) + u"\n", direction='sc') + self.out.write( + util.printableUnicode(content) + u"\n", direction='sc') def _parseCookies(self, data): - p,kwp=util.strtok(data,sep='; ') - return dict((urllib.unquote(k),urllib.unquote(kwp[k]))for k in kwp.keys()) - + p, kwp = util.strtok(data, sep='; ') + return dict((urllib.unquote(k), urllib.unquote(kwp[k]))for k in kwp.keys()) -if __name__=='__main__': +if __name__ == '__main__': dObj = DshellDecoder() print dObj else: diff --git a/decoders/http/rip-http.py b/decoders/http/rip-http.py index cc75317..8f7768d 100644 --- a/decoders/http/rip-http.py +++ b/decoders/http/rip-http.py @@ -1,70 +1,86 @@ -import dshell,re -import datetime, sys, string +import dshell +import re +import datetime +import sys +import string -#import any other modules here +# import any other modules here # import binascii -import re, os, hashlib, util +import re +import os +import hashlib +import util -#we extend this +# we extend this from httpdecoder import HTTPDecoder + class DshellDecoder(HTTPDecoder): + def __init__(self): HTTPDecoder.__init__(self, - name = 'rip-http', - description = 'rip files from HTTP traffic', - filter = 'tcp and port 80', - author = 'bg/twp', - optiondict = {'append_conn':{'action':'store_true','help':'append sourceip-destip to filename'}, - 'append_ts':{'action':'store_true','help':'append timestamp to filename'}, - 'direction':{'help':'cs=only capture client POST, sc=only capture server GET response'}, - 'content_filter':{'help':'regex MIME type filter for files to save'}, - 'name_filter':{'help':'regex filename filter for files to save'}} - ) + name='rip-http', + description='rip files from HTTP traffic', + filter='tcp and port 80', + author='bg/twp', + optiondict={'append_conn': {'action': 'store_true', 'help': 'append sourceip-destip to filename'}, + 'append_ts': {'action': 'store_true', 'help': 'append timestamp to filename'}, + 'direction': {'help': 'cs=only capture client POST, sc=only capture server GET response'}, + 'content_filter': {'help': 'regex MIME type filter for files to save'}, + 'name_filter': {'help': 'regex filename filter for files to save'}} + ) def preModule(self): - if self.content_filter: self.content_filter=re.compile(self.content_filter) - if self.name_filter: self.name_filter=re.compile(self.name_filter) + if self.content_filter: + self.content_filter = re.compile(self.content_filter) + if self.name_filter: + self.name_filter = re.compile(self.name_filter) HTTPDecoder.preModule(self) self.openfiles = {} # dict of httpfile objects, indexed by url - def splitstrip(self,data,sep,strip=' '): + def splitstrip(self, data, sep, strip=' '): return [lpart.strip(strip) for lpart in data.split(sep)] - def POSTHandler(self,postdata): - next_line_is_data=False + def POSTHandler(self, postdata): + next_line_is_data = False for l in postdata.split("\r\n"): - if next_line_is_data: break - if l=='': - next_line_is_data=True #\r\n\r\n before data + if next_line_is_data: + break + if l == '': + next_line_is_data = True # \r\n\r\n before data continue try: - k,v=self.splitstrip(l,':') - if k=='Content-Type': contenttype=v - if k=='Content-Disposition': - cdparts=self.splitstrip(v,';') + k, v = self.splitstrip(l, ':') + if k == 'Content-Type': + contenttype = v + if k == 'Content-Disposition': + cdparts = self.splitstrip(v, ';') for cdpart in cdparts: try: - k,v=self.splitstrip(cdpart,'=','"') - if k=='filename': filename=v - except: pass - except: pass - return contenttype,filename,l - - - def HTTPHandler(self,conn,request,response,requesttime,responsetime): - self.debug ('%s %s'%(repr(request),repr(response))) - if (not self.direction or self.direction=='cs') and request and request.method=='POST' and request.body: - contenttype,filename,data=self.POSTHandler(request.body) + k, v = self.splitstrip(cdpart, '=', '"') + if k == 'filename': + filename = v + except: + pass + except: + pass + return contenttype, filename, l + + def HTTPHandler(self, conn, request, response, requesttime, responsetime): + self.debug('%s %s' % (repr(request), repr(response))) + if (not self.direction or self.direction == 'cs') and request and request.method == 'POST' and request.body: + contenttype, filename, data = self.POSTHandler(request.body) if not self.content_filter or self.content_filter.search(contenttype): if not self.name_filter or self.name_filter.search(filename): - if self.append_conn: filename+='_%s-%s'%(conn.clientip,conn.serverip) - if self.append_ts: filename+='_%d'%(conn.ts) + if self.append_conn: + filename += '_%s-%s' % (conn.clientip, conn.serverip) + if self.append_ts: + filename += '_%d' % (conn.ts) self.debug(filename) - f=open(filename,'w') + f = open(filename, 'w') f.write(data) f.close() - elif (not self.direction or self.direction=='sc') and response and response.status[0]=='2': + elif (not self.direction or self.direction == 'sc') and response and response.status[0] == '2': if not self.content_filter or self.content_filter.search(response.headers['content-type']): # Calculate URL host = util.getHeader(request, 'host') @@ -74,65 +90,83 @@ def HTTPHandler(self,conn,request,response,requesttime,responsetime): # File already open if url in self.openfiles: self.debug("Adding response section to %s" % url) - (s,e) = self.openfiles[url].handleresponse(response) - self.write(" --> Range: %d - %d\n" % (s,e)) + (s, e) = self.openfiles[url].handleresponse(response) + self.write(" --> Range: %d - %d\n" % (s, e)) # New file else: - filename=request.uri.split('?')[0].split('/')[-1] + filename = request.uri.split('?')[0].split('/')[-1] self.debug("New file with URL: %s" % url) if not self.name_filter or self.name_filter.search(filename): - if self.append_conn: filename+='_%s-%s'%(conn.serverip,conn.clientip) - if self.append_ts: filename+='_%d'%(conn.ts) - if not len(filename): filename ='%s-%s_index.html'%(conn.serverip,conn.clientip) - while os.path.exists(filename): filename += '_' - self.alert("New file: %s (%s)" % (filename, url), conn.info()) + if self.append_conn: + filename += '_%s-%s' % (conn.serverip, + conn.clientip) + if self.append_ts: + filename += '_%d' % (conn.ts) + if not len(filename): + filename = '%s-%s_index.html' % ( + conn.serverip, conn.clientip) + while os.path.exists(filename): + filename += '_' + self.alert("New file: %s (%s)" % + (filename, url), conn.info()) self.openfiles[url] = httpfile(filename) - (s,e) = self.openfiles[url].handleresponse(response) - self.write(" --> Range: %d - %d\n" % (s,e)) + (s, e) = self.openfiles[url].handleresponse(response) + self.write(" --> Range: %d - %d\n" % (s, e)) if self.openfiles[url].done(): - self.alert("File done: %s (%s)" % (self.openfiles[url].filename, url), conn.info()) + self.alert("File done: %s (%s)" % + (self.openfiles[url].filename, url), conn.info()) del self.openfiles[url] + class httpfile: - def __init__(self,filename): + def __init__(self, filename): self.complete = False self.size = 0 # Expected size in bytes of full file transfer - self.ranges = [] # List of tuples indicating byte chunks already received and written to disk + # List of tuples indicating byte chunks already received and written to + # disk + self.ranges = [] self.filename = filename - self.fh = open(filename,'w') + self.fh = open(filename, 'w') def __del__(self): self.fh.close() if not self.done(): print "Incomplete file: %s" % self.filename - try: os.rename(self.filename, self.filename+"_INCOMPLETE") - except: pass + try: + os.rename(self.filename, self.filename + "_INCOMPLETE") + except: + pass ls = 0 le = 0 - for s,e in self.ranges: - if s>le+1: + for s, e in self.ranges: + if s > le + 1: print "Missing bytes between %d and %d" % (le, s) - ls,le = s,e + ls, le = s, e - - def handleresponse(self,response): + def handleresponse(self, response): # Check for Content Range range_start = 0 - range_end = len(response.body)-1 + range_end = len(response.body) - 1 if 'content-range' in response.headers: - m = re.search('bytes (\d+)-(\d+)/(\d+|\*)', response.headers['content-range']) + m = re.search( + 'bytes (\d+)-(\d+)/(\d+|\*)', response.headers['content-range']) if m: range_start = int(m.group(1)) range_end = int(m.group(2)) - if len(response.body) < (range_end-range_start+1): range_end=range_start+len(response.body)-1 + if len(response.body) < (range_end - range_start + 1): + range_end = range_start + len(response.body) - 1 try: - if int(m.group(3)) > self.size: self.size = int(m.group(3)) - except: pass + if int(m.group(3)) > self.size: + self.size = int(m.group(3)) + except: + pass elif 'content-length' in response.headers: try: - if int(response.headers['content-length']) > self.size: self.size = int(response.headers['content-length']) - except: pass + if int(response.headers['content-length']) > self.size: + self.size = int(response.headers['content-length']) + except: + pass # Update range tracking self.ranges.append((range_start, range_end)) # Write part of file @@ -149,19 +183,20 @@ def checkranges(self): current_start = 0 current_end = 0 foundgap = False - #print self.ranges - for s,e in self.ranges: - if s <= current_end+1: current_end = e + # print self.ranges + for s, e in self.ranges: + if s <= current_end + 1: + current_end = e else: foundgap = True current_start = s current_end = e if not foundgap: - if (current_end+1) >= self.size: + if (current_end + 1) >= self.size: self.complete = True return foundgap -if __name__=='__main__': +if __name__ == '__main__': dObj = DshellDecoder() print dObj else: diff --git a/decoders/http/web.py b/decoders/http/web.py index 86975d6..8730f9d 100644 --- a/decoders/http/web.py +++ b/decoders/http/web.py @@ -1,25 +1,29 @@ -import dshell, dfile +import dshell +import dfile import util import hashlib from httpdecoder import HTTPDecoder + class DshellDecoder(HTTPDecoder): + def __init__(self): HTTPDecoder.__init__(self, - name='web', - description='Improved version of web that tracks server response', - filter='tcp and (port 80 or port 8080 or port 8000)', - filterfn=lambda ((sip,sp),(dip,dp)): sp in (80, 8000, 8080) or dp in (80, 8000, 8080), - author='bg,twp', - optiondict={ - 'maxurilen':{'type':'int','default':30,'help':'Truncate URLs longer than max len. Set to 0 for no truncating. (default: 30)'}, - 'md5':{'action':'store_true','help':'calculate MD5 for each response. Available in CSV output.'} - }, - ) + name='web', + description='Improved version of web that tracks server response', + filter='tcp and (port 80 or port 8080 or port 8000)', + filterfn=lambda ((sip, sp), (dip, dp)): sp in ( + 80, 8000, 8080) or dp in (80, 8000, 8080), + author='bg,twp', + optiondict={ + 'maxurilen': {'type': 'int', 'default': 30, 'help': 'Truncate URLs longer than max len. Set to 0 for no truncating. (default: 30)'}, + 'md5': {'action': 'store_true', 'help': 'calculate MD5 for each response. Available in CSV output.'} + }, + ) self.gunzip = False # Not interested in response body - def HTTPHandler(self,conn,request,response,requesttime,responsetime): + def HTTPHandler(self, conn, request, response, requesttime, responsetime): host = '' loc = '' lastmodified = '' @@ -44,7 +48,7 @@ def HTTPHandler(self,conn,request,response,requesttime,responsetime): if status[:2] == '30': loc = util.getHeader(response, 'location') if len(loc): - loc = '-> '+loc + loc = '-> ' + loc lastmodified = util.HTTPlastmodified(response) referer = util.getHeader(request, 'referer') @@ -56,7 +60,6 @@ def HTTPHandler(self,conn,request,response,requesttime,responsetime): except: responsesize = 0 - if self.md5: md5 = self._bodyMD5(response) else: @@ -64,26 +67,35 @@ def HTTPHandler(self,conn,request,response,requesttime,responsetime): # File objects try: - if len(response.body) > 0: responsefile = dfile.dfile(name=request.uri,data=response.body) - else: responsefile = '' - except: responsefile = '' + if len(response.body) > 0: + responsefile = dfile.dfile( + name=request.uri, data=response.body) + else: + responsefile = '' + except: + responsefile = '' if request.method == 'POST' and len(request.body): - ulcontenttype,ulfilename,uldata=self.POSTHandler(request.body) - uploadfile=dfile.dfile(name=ulfilename,data=uldata) - else: uploadfile = None + ulcontenttype, ulfilename, uldata = self.POSTHandler(request.body) + uploadfile = dfile.dfile(name=ulfilename, data=uldata) + else: + uploadfile = None requestInfo = '%s %s%s HTTP/%s' % (request.method, - host, - request.uri[:self.maxurilen]+'[truncated]' if self.maxurilen > 0 and len(request.uri)> self.maxurilen else request.uri, - request.version) - if response: responseInfo = '%s %s %s %s' % (status,reason,loc,lastmodified) - else: responseInfo='' + host, + request.uri[:self.maxurilen] + '[truncated]' if self.maxurilen > 0 and len( + request.uri) > self.maxurilen else request.uri, + request.version) + if response: + responseInfo = '%s %s %s %s' % (status, reason, loc, lastmodified) + else: + responseInfo = '' - self.alert( "%-80s // %s" % (requestInfo,responseInfo),referer=referer,useragent=useragent,request=requestInfo,response=responseInfo,request_time=requesttime,response_time=responsetime,request_method=request.method,host=host,uri=request.uri,status=status,reason=reason,lastmodified=lastmodified,md5=md5,responsesize=responsesize,contenttype=util.getHeader(response, 'content-type'),responsefile=responsefile,uploadfile=uploadfile,via=via,**conn.info()) + self.alert("%-80s // %s" % (requestInfo, responseInfo), referer=referer, useragent=useragent, request=requestInfo, response=responseInfo, request_time=requesttime, response_time=responsetime, request_method=request.method, host=host, + uri=request.uri, status=status, reason=reason, lastmodified=lastmodified, md5=md5, responsesize=responsesize, contenttype=util.getHeader(response, 'content-type'), responsefile=responsefile, uploadfile=uploadfile, via=via, **conn.info()) if self.out.sessionwriter: - self.write(request.data,direction='cs') - if response: self.write(response.body,direction='sc') - + self.write(request.data, direction='cs') + if response: + self.write(response.body, direction='sc') # MD5sum(hex) of the body portion of the response def _bodyMD5(self, response): @@ -95,33 +107,38 @@ def _bodyMD5(self, response): except: return '' - def POSTHandler(self,postdata): - next_line_is_data=False + def POSTHandler(self, postdata): + next_line_is_data = False contenttype = '' filename = '' for l in postdata.split("\r\n"): - if next_line_is_data: break - if l=='': - next_line_is_data=True #\r\n\r\n before data + if next_line_is_data: + break + if l == '': + next_line_is_data = True # \r\n\r\n before data continue try: - k,v=self.splitstrip(l,':') - if k=='Content-Type': contenttype=v - if k=='Content-Disposition': - cdparts=self.splitstrip(v,';') + k, v = self.splitstrip(l, ':') + if k == 'Content-Type': + contenttype = v + if k == 'Content-Disposition': + cdparts = self.splitstrip(v, ';') for cdpart in cdparts: try: - k,v=self.splitstrip(cdpart,'=','"') - if k=='filename': filename=v - except: pass - except: pass - return contenttype,filename,l - - def splitstrip(self,data,sep,strip=' '): + k, v = self.splitstrip(cdpart, '=', '"') + if k == 'filename': + filename = v + except: + pass + except: + pass + return contenttype, filename, l + + def splitstrip(self, data, sep, strip=' '): return [lpart.strip(strip) for lpart in data.split(sep)] -if __name__=='__main__': +if __name__ == '__main__': dObj = DshellDecoder() print dObj else: diff --git a/decoders/misc/followstream.py b/decoders/misc/followstream.py index 40ff267..38581fd 100644 --- a/decoders/misc/followstream.py +++ b/decoders/misc/followstream.py @@ -1,20 +1,23 @@ -import dshell, util +import dshell +import util import colorout #from impacket.ImpactDecoder import EthDecoder -import datetime, sys +import datetime +import sys import traceback import logging -#import any other modules here +# import any other modules here import cgi + class DshellDecoder(dshell.TCPDecoder): - def __init__(self): - dshell.TCPDecoder.__init__(self, - name='followstream', - description='Generates color-coded Screen/HTML output similar to Wireshark Follow Stream', - longdescription=""" + def __init__(self): + dshell.TCPDecoder.__init__(self, + name='followstream', + description='Generates color-coded Screen/HTML output similar to Wireshark Follow Stream', + longdescription=""" Generates color-coded Screen/HTML output similar to Wireshark Follow Stream. Output by default uses the "colorout" output class. This will send TTY @@ -36,66 +39,76 @@ def __init__(self): decode -d followstream --ebpf 'port 80' mypcap.pcap -o file.html --followstream_time """, - filter="tcp", - author='amm', - optiondict={ - 'hex':{'action':'store_true','help':'two-column hex/ascii output'}, - 'time':{'action':'store_true','help':'include timestamp for each blob'}, - 'encoding':{'type':'string','help':'attempt to interpret text as encoded with specified schema'}, - } - ) - self.out = colorout.ColorOutput() - - def __errorHandler(self, blob, expected, offset, caller): - # Custom error handler that is called when data in a blob is missing or overlapping - if offset > expected: # data is missing - self.data_missing_message += "[%d missing bytes]" % (offset-expected) - elif offset < expected: # data is overlapping - self.data_missing_message += "[%d overlapping bytes]" % (offset-expected) - return True - - def preModule(self): - self.connectionCount = 0 - # Reset the color mode, in case a file is specified - self.out.setColorMode() - # Used to indicate when data is missing or overlapping - self.data_missing_message = '' - # overwrite the output module's default error handler - self.out.errorH = self.__errorHandler - - def connectionHandler(self,connection): - - try: - - # Skip Connections with no data transferred - if connection.clientbytes + connection.serverbytes < 1: - return - - # Update Connection Counter - self.connectionCount += 1 - - # Connection Header Information - self.out.write("Connection %d (%s)\n" % (self.connectionCount, str(connection.proto)), formatTag='H1') - self.out.write("Start: %s UTC\n End: %s UTC\n" % (datetime.datetime.utcfromtimestamp(connection.starttime), datetime.datetime.utcfromtimestamp(connection.endtime)), formatTag='H2') - self.out.write("%s:%s -> %s:%s (%d bytes)\n" % (connection.clientip, connection.clientport, connection.serverip, connection.serverport, connection.clientbytes), formatTag="H2", direction="cs") - self.out.write("%s:%s -> %s:%s (%d bytes)\n\n" % (connection.serverip, connection.serverport, connection.clientip, connection.clientport, connection.serverbytes), formatTag="H2", direction="sc") - - self.out.write(connection, hex=self.hex, time=self.time, encoding=self.encoding) - if self.data_missing_message: self.out.write(self.data_missing_message+"\n", level=logging.WARNING, time=self.time) - self.data_missing_message = '' - - # Line break before next session - self.out.write("\n\n") - - except KeyboardInterrupt: - raise - except: - print 'Error in connectionHandler: ', sys.exc_info()[1] - traceback.print_exc(file=sys.stdout) - - -if __name__=='__main__': - dObj = DshellDecoder() - print dObj + filter="tcp", + author='amm', + optiondict={ + 'hex': {'action': 'store_true', 'help': 'two-column hex/ascii output'}, + 'time': {'action': 'store_true', 'help': 'include timestamp for each blob'}, + 'encoding': {'type': 'string', 'help': 'attempt to interpret text as encoded with specified schema'}, + } + ) + self.out = colorout.ColorOutput() + + def __errorHandler(self, blob, expected, offset, caller): + # Custom error handler that is called when data in a blob is missing or + # overlapping + if offset > expected: # data is missing + self.data_missing_message += "[%d missing bytes]" % ( + offset - expected) + elif offset < expected: # data is overlapping + self.data_missing_message += "[%d overlapping bytes]" % ( + offset - expected) + return True + + def preModule(self): + self.connectionCount = 0 + # Reset the color mode, in case a file is specified + self.out.setColorMode() + # Used to indicate when data is missing or overlapping + self.data_missing_message = '' + # overwrite the output module's default error handler + self.out.errorH = self.__errorHandler + + def connectionHandler(self, connection): + + try: + + # Skip Connections with no data transferred + if connection.clientbytes + connection.serverbytes < 1: + return + + # Update Connection Counter + self.connectionCount += 1 + + # Connection Header Information + self.out.write("Connection %d (%s)\n" % ( + self.connectionCount, str(connection.proto)), formatTag='H1') + self.out.write("Start: %s UTC\n End: %s UTC\n" % (datetime.datetime.utcfromtimestamp( + connection.starttime), datetime.datetime.utcfromtimestamp(connection.endtime)), formatTag='H2') + self.out.write("%s:%s -> %s:%s (%d bytes)\n" % (connection.clientip, connection.clientport, + connection.serverip, connection.serverport, connection.clientbytes), formatTag="H2", direction="cs") + self.out.write("%s:%s -> %s:%s (%d bytes)\n\n" % (connection.serverip, connection.serverport, + connection.clientip, connection.clientport, connection.serverbytes), formatTag="H2", direction="sc") + + self.out.write( + connection, hex=self.hex, time=self.time, encoding=self.encoding) + if self.data_missing_message: + self.out.write( + self.data_missing_message + "\n", level=logging.WARNING, time=self.time) + self.data_missing_message = '' + + # Line break before next session + self.out.write("\n\n") + + except KeyboardInterrupt: + raise + except: + print 'Error in connectionHandler: ', sys.exc_info()[1] + traceback.print_exc(file=sys.stdout) + + +if __name__ == '__main__': + dObj = DshellDecoder() + print dObj else: - dObj = DshellDecoder() + dObj = DshellDecoder() diff --git a/decoders/misc/merge.py b/decoders/misc/merge.py index 8c2dbc6..fd9f868 100644 --- a/decoders/misc/merge.py +++ b/decoders/misc/merge.py @@ -1,27 +1,32 @@ import dshell import dpkt + class DshellDecoder(dshell.Decoder): + """ merge.py - merge all pcap in to a single file Example: decode -d merge *.pcap -W merged.pcap """ + def __init__(self): dshell.Decoder.__init__(self, - name = 'merge', - description = 'dump all packets to single file', - longdescription ="""Example: decode -d merge *.pcap -W merged.pcap""", - author = 'bg/twp' - ) - self.chainable=True + name='merge', + description='dump all packets to single file', + longdescription="""Example: decode -d merge *.pcap -W merged.pcap""", + author='bg/twp' + ) + self.chainable = True - def rawHandler(self,pktlen,pkt,ts,**kw): - if self.subDecoder: return self.subDecoder.rawHandler(pktlen,str(pkt),ts,**kw) - else: return self.dump(pktlen,pkt,ts) + def rawHandler(self, pktlen, pkt, ts, **kw): + if self.subDecoder: + return self.subDecoder.rawHandler(pktlen, str(pkt), ts, **kw) + else: + return self.dump(pktlen, pkt, ts) -if __name__=='__main__': +if __name__ == '__main__': dObj = DshellDecoder() print dObj else: diff --git a/decoders/misc/synrst.py b/decoders/misc/synrst.py index 4c1c69b..4cac0f5 100644 --- a/decoders/misc/synrst.py +++ b/decoders/misc/synrst.py @@ -1,34 +1,40 @@ -import dshell, dpkt +import dshell +import dpkt + class DshellDecoder(dshell.IPDecoder): + """ Simple TCP syn/rst filter (ipv4) only """ + def __init__(self): dshell.IPDecoder.__init__(self, - name = 'synrst', - description = 'detect failed attempts to connect (SYN followed by a RST/ACK)', - filter = "tcp[13]=2 or tcp[13]=20", - author = 'bg' - ) + name='synrst', + description='detect failed attempts to connect (SYN followed by a RST/ACK)', + filter="tcp[13]=2 or tcp[13]=20", + author='bg' + ) self.tracker = {} # key = (srcip,srcport,seqnum,dstip,dstport) - def packetHandler(self,ip=None): + def packetHandler(self, ip=None): tcp = dpkt.ip.IP(ip.pkt).data - if tcp.flags & 2: # check for SYN flag + if tcp.flags & 2: # check for SYN flag seqnum = tcp.seq - key = '%s:%s:%d:%s:%s' % (ip.sip,ip.sport,seqnum,ip.dip,ip.dport) + key = '%s:%s:%d:%s:%s' % ( + ip.sip, ip.sport, seqnum, ip.dip, ip.dport) self.tracker[key] = '' - elif tcp.flags & 20: # check for RST/ACK flags + elif tcp.flags & 20: # check for RST/ACK flags acknum = tcp.ack - 1 - tmpkey = '%s:%s:%d:%s:%s' % (ip.dip,ip.dport,acknum,ip.sip,ip.sport) + tmpkey = '%s:%s:%d:%s:%s' % ( + ip.dip, ip.dport, acknum, ip.sip, ip.sport) if self.tracker.__contains__(tmpkey): - self.alert('Failed connection',**ip.info()) + self.alert('Failed connection', **ip.info()) del self.tracker[tmpkey] -if __name__=='__main__': +if __name__ == '__main__': dObj = DshellDecoder() print dObj else: diff --git a/decoders/misc/writer.py b/decoders/misc/writer.py index 656b644..92e315e 100644 --- a/decoders/misc/writer.py +++ b/decoders/misc/writer.py @@ -4,41 +4,46 @@ @author: tparker ''' -import dshell,dpkt +import dshell +import dpkt from output import PCAPWriter + class DshellDecoder(dshell.Decoder): + ''' session writer - chain to a decoder to end the chain if the decoder does not output session or packets on its own if chained to a packet-based decoder, writes all packets to pcap file, can be used to convert or concatenate files if chained to a connection-based decoder, writes selected streams to session file ''' - def __init__(self,**kwargs): + + def __init__(self, **kwargs): ''' Constructor ''' - self.file=None + self.file = None dshell.Decoder.__init__(self, - name='writer', - description='pcap/session writer', - author='twp', - raw=True, - optiondict=dict( filename=dict(default='%(clientip)s:%(clientport)s-%(serverip)s:%(serverport)s-%(direction)s.txt'), - ) - ) - - def rawHandler(self,pktlen,pkt,ts): - self.decodedbytes+=pktlen - self.count+=1 - self.dump(pktlen,pkt,ts) #pktlen may be wrong if we stripped vlan - - def IPHandler(self,addr,ip,ts,pkttype=None,**kw): - self.decodedbytes+=len(ip.data) - self.count+=1 - #if we are passed in IP data vs layer-2 frames, we need to encapsulate them - self.dump(dpkt.ethernet.Ethernet(data=str(ip),pkttype=type),ts=ts) - - def connectionHandler(self,conn): + name='writer', + description='pcap/session writer', + author='twp', + raw=True, + optiondict=dict(filename=dict(default='%(clientip)s:%(clientport)s-%(serverip)s:%(serverport)s-%(direction)s.txt'), + ) + ) + + def rawHandler(self, pktlen, pkt, ts): + self.decodedbytes += pktlen + self.count += 1 + self.dump(pktlen, pkt, ts) # pktlen may be wrong if we stripped vlan + + def IPHandler(self, addr, ip, ts, pkttype=None, **kw): + self.decodedbytes += len(ip.data) + self.count += 1 + # if we are passed in IP data vs layer-2 frames, we need to encapsulate + # them + self.dump(dpkt.ethernet.Ethernet(data=str(ip), pkttype=type), ts=ts) + + def connectionHandler(self, conn): self.write(conn) dObj = DshellDecoder() diff --git a/decoders/misc/xor.py b/decoders/misc/xor.py index 0d747dd..c95a6c9 100644 --- a/decoders/misc/xor.py +++ b/decoders/misc/xor.py @@ -1,76 +1,93 @@ -import dshell, util +import dshell +import util import struct + class DshellDecoder(dshell.TCPDecoder): + def __init__(self): - self.xorconn={} # required to track each individual connection + self.xorconn = {} # required to track each individual connection dshell.TCPDecoder.__init__(self, - name='xor', - description='XOR an entire stream with a given single byte key', - filter="tcp", - author='twp', - optiondict={ - 'key':{'type':'str','default':'0xff','help':'xor key [default 255]'}, - 'cskey':{'type':'str','default':None,'help':'c->s xor key [default None]'}, - 'sckey':{'type':'str','default':None,'help':'s->c xor key [default None]'}, - 'resync':{'action':'store_true','help':'resync if the key is seen in the stream'}, - } - ) - self.chainable=True # sets chainable to true and requires connectionInitHandler() and connectionCloseHandler() + name='xor', + description='XOR an entire stream with a given single byte key', + filter="tcp", + author='twp', + optiondict={ + 'key': {'type': 'str', 'default': '0xff', 'help': 'xor key [default 255]'}, + 'cskey': {'type': 'str', 'default': None, 'help': 'c->s xor key [default None]'}, + 'sckey': {'type': 'str', 'default': None, 'help': 's->c xor key [default None]'}, + 'resync': {'action': 'store_true', 'help': 'resync if the key is seen in the stream'}, + } + ) + # sets chainable to true and requires connectionInitHandler() and + # connectionCloseHandler() + self.chainable = True - def preModule(self,*args,**kwargs): + def preModule(self, *args, **kwargs): dshell.TCPDecoder.preModule(self, *args, **kwargs) - #twp handle hex keys - self.key=self.makeKey(self.key) - if self.cskey: self.cskey=self.makeKey(self.cskey) - if self.sckey: self.sckey=self.makeKey(self.sckey) + # twp handle hex keys + self.key = self.makeKey(self.key) + if self.cskey: + self.cskey = self.makeKey(self.cskey) + if self.sckey: + self.sckey = self.makeKey(self.sckey) - def makeKey(self,key): - if key.startswith('"'): return key[1:-1] + def makeKey(self, key): + if key.startswith('"'): + return key[1:-1] if key.startswith('0x'): - k,key='',key[2:] - for i in xrange(0,len(key),2): k+=chr(int(key[i:i+2],16)) + k, key = '', key[2:] + for i in xrange(0, len(key), 2): + k += chr(int(key[i:i + 2], 16)) return k - else: return struct.pack('I', int(key)) + else: + return struct.pack('I', int(key)) # # connectionInitHandler is required as this module (and all other chainable modules) will have to track all # each connection independently of dshell.TCPDecoder # - def connectionInitHandler(self,conn): + def connectionInitHandler(self, conn): # need to set up a custom connection tracker to handle - self.xorconn[conn.addr]=dshell.Connection(self,conn.addr,conn.ts) - #self.xorconn[conn.addr]=conn + self.xorconn[conn.addr] = dshell.Connection(self, conn.addr, conn.ts) + # self.xorconn[conn.addr]=conn # # Each blob will be xor'ed and the "newblob" data will be added to the connection # we are individually tracking # - def blobHandler(self,conn,blob): - k=0 #key index + def blobHandler(self, conn, blob): + k = 0 # key index # create new data (ie. pkt data) # with appropriate key - data,newdata=blob.data(),'' - self.debug('IN '+util.hexPlusAscii(blob.data())) - if self.cskey != None and blob.direction == 'cs': key=self.cskey - elif self.sckey != None and blob.direction == 'sc': key=self.sckey - else: key=self.key + data, newdata = blob.data(), '' + self.debug('IN ' + util.hexPlusAscii(blob.data())) + if self.cskey != None and blob.direction == 'cs': + key = self.cskey + elif self.sckey != None and blob.direction == 'sc': + key = self.sckey + else: + key = self.key for i in xrange(len(data)): - if self.resync and data[i:i+len(key)]==key: k=0 #resync if the key is seen - newdata+=chr(ord(data[i])^ord(key[k])) #xor this byte with the aligned byte from the key - k = (k+1) % len(key) #move key position + if self.resync and data[i:i + len(key)] == key: + k = 0 # resync if the key is seen + # xor this byte with the aligned byte from the key + newdata += chr(ord(data[i]) ^ ord(key[k])) + k = (k + 1) % len(key) # move key position # update our connection object with the new data - newblob = self.xorconn[conn.addr].update(conn.endtime,blob.direction,newdata) - self.debug('OUT '+repr(self.key)+' '+util.hexPlusAscii(newdata)) + newblob = self.xorconn[conn.addr].update( + conn.endtime, blob.direction, newdata) + self.debug('OUT ' + repr(self.key) + ' ' + util.hexPlusAscii(newdata)) # if there is another decoder we want to pass this data too if newblob and 'blobHandler' in dir(self.subDecoder): - self.subDecoder.blobHandler(self.xorconn[conn.addr],newblob) # pass to the subDecoder's blobHandler() + # pass to the subDecoder's blobHandler() + self.subDecoder.blobHandler(self.xorconn[conn.addr], newblob) # # The connection has finished without errors, then we pass the entire connection to the subDecoder's # connectionHandler() # - def connectionHandler(self,conn): + def connectionHandler(self, conn): if conn.addr in self.xorconn: self.xorconn[conn.addr].proto = conn.proto if 'connectionHandler' in dir(self.subDecoder): @@ -87,14 +104,14 @@ def connectionHandler(self,conn): # we will have to pass it to the subDecoder's connectionCloseHandler # # - def connectionCloseHandler(self,conn): + def connectionCloseHandler(self, conn): if conn.addr in self.xorconn: if 'connectionCloseHandler' in dir(self.subDecoder): self.subDecoder.connectionCloseHandler(self.xorconn[conn.addr]) del self.xorconn[conn.addr] -if __name__=='__main__': +if __name__ == '__main__': dObj = DshellDecoder() print dObj else: diff --git a/decoders/protocol/ether.py b/decoders/protocol/ether.py index b5e34db..23b3c2e 100644 --- a/decoders/protocol/ether.py +++ b/decoders/protocol/ether.py @@ -1,23 +1,30 @@ -import dshell,util,dpkt,datetime,binascii +import dshell +import util +import dpkt +import datetime +import binascii + class DshellDecoder(dshell.Decoder): def __init__(self): dshell.Decoder.__init__(self, - name = 'ether', - description = 'raw ethernet capture decoder', - filter = '', - author = 'twp',asdatetime=True - ) + name='ether', + description='raw ethernet capture decoder', + filter='', + author='twp', asdatetime=True + ) - def rawHandler(self,dlen,data,ts,**kw): - if self.verbose: self.log("%.06f %d\n%s"%(ts,dlen,util.hexPlusAscii(str(data)))) - eth=dpkt.ethernet.Ethernet(str(data)) - src=binascii.hexlify(eth.src) - dst=binascii.hexlify(eth.dst) - self.alert('%6x->%6x %4x len %d'%(long(src,16),long(dst,16),eth.type,len(eth.data)),type=eth.type,bytes=len(eth.data),src=src,dst=dst,ts=ts) + def rawHandler(self, dlen, data, ts, **kw): + if self.verbose: + self.log("%.06f %d\n%s" % (ts, dlen, util.hexPlusAscii(str(data)))) + eth = dpkt.ethernet.Ethernet(str(data)) + src = binascii.hexlify(eth.src) + dst = binascii.hexlify(eth.dst) + self.alert('%6x->%6x %4x len %d' % (long(src, 16), long(dst, 16), eth.type, + len(eth.data)), type=eth.type, bytes=len(eth.data), src=src, dst=dst, ts=ts) -if __name__=='__main__': +if __name__ == '__main__': dObj = DshellDecoder() print dObj else: diff --git a/decoders/protocol/ip.py b/decoders/protocol/ip.py index cdd9e94..f432172 100644 --- a/decoders/protocol/ip.py +++ b/decoders/protocol/ip.py @@ -1,23 +1,30 @@ -import dshell,util,dpkt,traceback +import dshell +import util +import dpkt +import traceback + class DshellDecoder(dshell.IP6Decoder): - _PROTO_MAP={dpkt.ip.IP_PROTO_TCP:'TCP',17:'UDP'} + _PROTO_MAP = {dpkt.ip.IP_PROTO_TCP: 'TCP', 17: 'UDP'} def __init__(self): dshell.IP6Decoder.__init__(self, - name = 'ip', - description = 'IPv4/IPv6 decoder', - filter = 'ip or ip6', - author = 'twp', - ) + name='ip', + description='IPv4/IPv6 decoder', + filter='ip or ip6', + author='twp', + ) - def packetHandler(self,ip=None,proto=None): - if self.verbose: self.out.log(util.hexPlusAscii(ip.pkt)) + def packetHandler(self, ip=None, proto=None): + if self.verbose: + self.out.log(util.hexPlusAscii(ip.pkt)) self.alert(**ip.info()) - if self.out.sessionwriter: self.write(ip) + if self.out.sessionwriter: + self.write(ip) -if __name__=='__main__': +if __name__ == '__main__': dObj = DshellDecoder() print dObj -else: dObj = DshellDecoder() +else: + dObj = DshellDecoder() diff --git a/decoders/protocol/protocol.py b/decoders/protocol/protocol.py index cad82dd..de402dc 100644 --- a/decoders/protocol/protocol.py +++ b/decoders/protocol/protocol.py @@ -2,10 +2,15 @@ import dpkt # Build a list of known IP protocols from dpkt -try: PROTOCOL_MAP = dict((v,k[9:]) for k,v in dpkt.ip.__dict__.iteritems() if type(v) == int and k.startswith('IP_PROTO_') and k != 'IP_PROTO_HOPOPTS') -except: PROTOCOL_MAP = {} +try: + PROTOCOL_MAP = dict((v, k[9:]) for k, v in dpkt.ip.__dict__.iteritems() if type( + v) == int and k.startswith('IP_PROTO_') and k != 'IP_PROTO_HOPOPTS') +except: + PROTOCOL_MAP = {} + class DshellDecoder(dshell.IPDecoder): + """ protocol.py @@ -14,19 +19,21 @@ class DshellDecoder(dshell.IPDecoder): References: http://www.networksorcery.com/enp/protocol/ip.htm """ + def __init__(self): dshell.IPDecoder.__init__(self, - name = 'protocol', - description = 'Identifies non-standard protocols (not tcp, udp or icmp)', - filter = '(ip and not tcp and not udp and not icmp)', - author = 'bg', - ) + name='protocol', + description='Identifies non-standard protocols (not tcp, udp or icmp)', + filter='(ip and not tcp and not udp and not icmp)', + author='bg', + ) - def packetHandler(self,ip): + def packetHandler(self, ip): p = PROTOCOL_MAP.get(ip.proto, ip.proto) - self.alert('PROTOCOL: %s (%d)' % (p, ip.proto), sip=ip.sip, dip=ip.dip, ts=ip.ts) + self.alert('PROTOCOL: %s (%d)' % + (p, ip.proto), sip=ip.sip, dip=ip.dip, ts=ip.ts) -if __name__=='__main__': +if __name__ == '__main__': dObj = DshellDecoder() print dObj else: diff --git a/decoders/templates/PacketDecoder.py b/decoders/templates/PacketDecoder.py index f58893f..16becda 100644 --- a/decoders/templates/PacketDecoder.py +++ b/decoders/templates/PacketDecoder.py @@ -1,27 +1,31 @@ #!/usr/bin/env python -import dshell, output, util +import dshell +import output +import util + class DshellDecoder(dshell.IPDecoder): + '''generic packet-level decoder template''' - def __init__(self,**kwargs): + def __init__(self, **kwargs): '''decoder-specific config''' '''pairs of 'option':{option-config}''' - self.optiondict={} + self.optiondict = {} '''bpf filter, for ipV4''' - self.filter='' + self.filter = '' '''filter function''' - #self.filterfn= + # self.filterfn= '''init superclasses''' self.__super__().__init__(**kwargs) - def packetHandler(self,ip): + def packetHandler(self, ip): '''handle as Packet() ojects''' pass -#create an instance at load-time -dObj=DshellDecoder() +# create an instance at load-time +dObj = DshellDecoder() diff --git a/decoders/templates/SessionDecoder.py b/decoders/templates/SessionDecoder.py index f97579f..c2bc04d 100644 --- a/decoders/templates/SessionDecoder.py +++ b/decoders/templates/SessionDecoder.py @@ -1,43 +1,47 @@ #!/usr/bin/env python -import dshell, output, util +import dshell +import output +import util + class DshellDecoder(dshell.TCPDecoder): + '''generic session-level decoder template''' - def __init__(self,**kwargs): + def __init__(self, **kwargs): '''decoder-specific config''' '''pairs of 'option':{option-config}''' - self.optiondict={} + self.optiondict = {} '''bpf filter, for ipV4''' - self.filter='' + self.filter = '' '''filter function''' - #self.filterfn= + # self.filterfn= '''init superclasses''' self.__super__().__init__(**kwargs) - def packetHandler(self,udp,data): + def packetHandler(self, udp, data): '''handle UDP as Packet(),payload data remove this if you want to make UDP into pseudo-sessions''' pass - def connectionInitHandler(self,conn): + def connectionInitHandler(self, conn): '''called when connection starts, before any data''' pass - def blobHandler(self,conn,blob): + def blobHandler(self, conn, blob): '''handle session data as soon as reassembly is possible''' pass - def connectionHandler(self,conn): + def connectionHandler(self, conn): '''handle session once all data is reassembled''' pass - def connectionCloseHandler(self,conn): + def connectionCloseHandler(self, conn): '''called when connection ends, after data is handled''' -#create an instance at load-time -dObj=DshellDecoder() +# create an instance at load-time +dObj = DshellDecoder() diff --git a/install-ubuntu.py b/install-ubuntu.py index 6bdf367..75f1b4d 100755 --- a/install-ubuntu.py +++ b/install-ubuntu.py @@ -26,4 +26,3 @@ call(cmd) call(["make", "all"]) - diff --git a/lib/dfile.py b/lib/dfile.py index 04ebe3f..2fc9145 100644 --- a/lib/dfile.py +++ b/lib/dfile.py @@ -12,7 +12,7 @@ ''' Mode Constants ''' -FILEONDISK = 1 # Object refers to file already written to disk +FILEONDISK = 1 # Object refers to file already written to disk FILEINMEMORY = 2 # Object contains file contents in data member ''' @@ -32,25 +32,28 @@ FILEINMEMORY ''' + + class dfile(Blob): - def __init__(self,mode=FILEINMEMORY,name=None,data=None,**kwargs): + def __init__(self, mode=FILEINMEMORY, name=None, data=None, **kwargs): # Initialize Segments # Only really used in memory mode - self.segments={} - self.startoffset=0 - self.endoffset=0 + self.segments = {} + self.startoffset = 0 + self.endoffset = 0 # Initialize consistent info members - self.mode=mode - self.name=name - self.diskpath=None - self.info_keys = ['mode','name','diskpath','startoffset','endoffset'] + self.mode = mode + self.name = name + self.diskpath = None + self.info_keys = [ + 'mode', 'name', 'diskpath', 'startoffset', 'endoffset'] - #update with additional info + # update with additional info self.info(**kwargs) - #update data + # update data if data != None: self.update(data) @@ -93,7 +96,8 @@ def load(self): ''' Load file from disk. Converts object to mode FILEINMEMORY ''' - if not self.mode == FILEONDISK: return False + if not self.mode == FILEONDISK: + return False try: fh = open(self.diskpath, 'r') self.update(fh.read()) @@ -102,7 +106,7 @@ def load(self): except: return False - def write(self,path='.',name=None,clobber=False,errorHandler=None,padding=None,overlap=True): + def write(self, path='.', name=None, clobber=False, errorHandler=None, padding=None, overlap=True): ''' Write file contents at location relative to path. Name on disk will be based on internal name unless one is provided. @@ -113,33 +117,38 @@ def write(self,path='.',name=None,clobber=False,errorHandler=None,padding=None,o ''' olddiskpath = self.diskpath - if name == None: name=self.name - self.diskpath = self.__localfilename(name, path, clobber) + if name == None: + name = self.name + self.diskpath = self.__localfilename(name, path, clobber) if self.mode == FILEINMEMORY: fh = open(self.diskpath, 'w') fh.write(self.data()) fh.close() - self.segments={} - self.startoffset=0 - self.endoffset=0 + self.segments = {} + self.startoffset = 0 + self.endoffset = 0 return self.diskpath elif self.mode == FILEONDISK: move(olddiskpath, self.diskpath) return self.diskpath - def update(self,data,offset=None): - if self.mode != FILEINMEMORY: return - #if offsets are not being provided, just keep packets in wire order - if offset==None: offset=self.endoffset - #don't buffer duplicate packets - if offset not in self.segments: self.segments[offset]=data - #update the end offset if this packet goes at the end - if offset >= self.endoffset: self.endoffset=offset+len(data) + def update(self, data, offset=None): + if self.mode != FILEINMEMORY: + return + # if offsets are not being provided, just keep packets in wire order + if offset == None: + offset = self.endoffset + # don't buffer duplicate packets + if offset not in self.segments: + self.segments[offset] = data + # update the end offset if this packet goes at the end + if offset >= self.endoffset: + self.endoffset = offset + len(data) # # Generate a local (extracted) filename based on the original # - def __localfilename(self, origname, path = '.', clobber = False): + def __localfilename(self, origname, path='.', clobber=False): tmp = origname.replace("\\", "_") tmp = tmp.replace("/", "_") tmp = tmp.replace(":", "_") @@ -151,16 +160,19 @@ def __localfilename(self, origname, path = '.', clobber = False): localname += c else: localname += "%%%02X" % ord(c) - # Truncate (from left) to max filename length on filesystem (-3 in case we need to add a suffix) - localname = localname[os.statvfs(path).f_namemax*-1:] + # Truncate (from left) to max filename length on filesystem (-3 in case + # we need to add a suffix) + localname = localname[os.statvfs(path).f_namemax * -1:] # Empty filename not allowed - if localname == '': localname = 'blank' - localname = os.path.realpath(os.path.join(path,localname)) - if clobber: return localname + if localname == '': + localname = 'blank' + localname = os.path.realpath(os.path.join(path, localname)) + if clobber: + return localname # No Clobber mode, check to see if file exists suffix = '' i = 0 - while os.path.exists(localname+suffix): + while os.path.exists(localname + suffix): i += 1 suffix = "_%02d" % i - return localname+suffix + return localname + suffix diff --git a/lib/dnsdecoder.py b/lib/dnsdecoder.py index 5cd9024..604b351 100644 --- a/lib/dnsdecoder.py +++ b/lib/dnsdecoder.py @@ -1,8 +1,12 @@ #!/usr/bin/env python -import dshell, util, dpkt +import dshell +import util +import dpkt + class DNSDecoder(dshell.TCPDecoder): + '''extend DNSDecoder to handle DNS request/responses pairs request and response(s) by connection and query ID to allow for detection of DNS spoofing, etc.. (multiple responses to request with same ID) @@ -18,44 +22,54 @@ class DNSDecoder(dshell.TCPDecoder): config: noanswer: if True and discarding w/o response, will call with response,responsetime=None,None (True) ''' - def __init__(self,**kwargs): - self.noanswer=True - dshell.TCPDecoder.__init__(self,**kwargs) #DNS is over UDP and TCP! - self.requests={} - self.maxblobs=None - def blobHandler(self,conn,blob): + def __init__(self, **kwargs): + self.noanswer = True + dshell.TCPDecoder.__init__(self, **kwargs) # DNS is over UDP and TCP! + self.requests = {} + self.maxblobs = None + + def blobHandler(self, conn, blob): '''for each blob, examine each segment (UDP packet) seperately as each will be a DNS Q/A pair Q/A by ID and return as pairs''' - connrqs=self.requests.setdefault(conn,{}) - for data in blob: #iterate blob as each packet will be a seperate request (catches spoofing) - try: dns=dpkt.dns.DNS(data) - except Exception,e: self._exc(e) + connrqs = self.requests.setdefault(conn, {}) + # iterate blob as each packet will be a seperate request (catches + # spoofing) + for data in blob: + try: + dns = dpkt.dns.DNS(data) + except Exception, e: + self._exc(e) if dns.qr == dpkt.dns.DNS_Q: - connrqs[dns.id]=[blob.starttime,dns,0] + connrqs[dns.id] = [blob.starttime, dns, 0] elif dns.qr == dpkt.dns.DNS_A: - rq=connrqs.get(dns.id,[None,None,0]) - rq[2]+=1 + rq = connrqs.get(dns.id, [None, None, 0]) + rq[2] += 1 if "DNSHandler" in dir(self): - self.DNSHandler(conn=conn,request=rq[1],response=dns,requesttime=rq[0],responsetime=blob.starttime,responsecount=rq[2]) + self.DNSHandler(conn=conn, request=rq[1], response=dns, requesttime=rq[ + 0], responsetime=blob.starttime, responsecount=rq[2]) - def connectionHandler(self,conn): + def connectionHandler(self, conn): '''clean up unanswered requests when we discard the connection''' if self.noanswer and "DNSHandler" in dir(self) and self.requests.get(conn): - for requesttime,request,responsecount in self.requests[conn].values(): + for requesttime, request, responsecount in self.requests[conn].values(): if not responsecount: - self.DNSHandler(conn=conn,request=request,response=None,requesttime=requesttime,responsetime=None,responsecount=responsecount) - if conn in self.requests: del self.requests[conn] + self.DNSHandler(conn=conn, request=request, response=None, + requesttime=requesttime, responsetime=None, responsecount=responsecount) + if conn in self.requests: + del self.requests[conn] + class displaystub(dshell.Decoder): + def __init__(self): dshell.Decoder.__init__(self, - name='dnsdecoder', - description='Intermediate class to support DNS based decoders.', - longdescription="See source code or pydoc for details on use." - ) + name='dnsdecoder', + description='Intermediate class to support DNS based decoders.', + longdescription="See source code or pydoc for details on use." + ) -if __name__=='__main__': +if __name__ == '__main__': dObj = displaystub() print dObj else: diff --git a/lib/dshell.py b/lib/dshell.py index 5af0686..186e2b6 100644 --- a/lib/dshell.py +++ b/lib/dshell.py @@ -5,17 +5,24 @@ __version__ = "3.0" import dpkt -import struct,socket,traceback +import struct +import socket +import traceback import util -import os, datetime,logging +import os +import datetime +import logging import binascii # For IP lookups -try: import pygeoip -except: pass +try: + import pygeoip +except: + pass class Decoder(object): + """ Base class that all decoders will inherit @@ -49,68 +56,87 @@ class Decoder(object): """ + def __super__(self): '''convenience function to get bound instance of superclass''' - return super(self.__class__,self) + return super(self.__class__, self) - def __init__(self,**kwargs): + def __init__(self, **kwargs): self.name = 'unnamed' self.description = '' self.longdescription = '' self.filter = '' self.author = 'xx' - self.decodedbytes=0 - self.count=0 + self.decodedbytes = 0 + self.count = 0 '''dict of options specific to this decoder in format 'optname':{configdict} translates to --decodername_optname''' - self.optiondict={} - - #out holds the output plugin. If None, will inherit the global output - self.out=None - #format is the format string for this plugin, if None, uses global - self.format=None - - #capture options - self.l2decoder=dpkt.ethernet.Ethernet #decoder to use if raw mode - self.striplayers=0 #strip extra layers before IP/IPv6? (such as PPPoE, IP-over-IP, etc..) - - self._DEBUG=False - - self.chainable=False #can we chain a decoder off the output of this one? - self.subDecoder=None #decoder to pass output to for chaining - - #set flags to indicate if handlers are present - if 'packetHandler' in dir(self): self.isPacketHandlerPresent = True - else: self.isPacketHandlerPresent = False - if 'connectionHandler' in dir(self): self.isConnectionHandlerPresent = True - else: self.isConnectionHandlerPresent = False - if 'blobHandler' in dir(self): self.isBlobHandlerPresent = True - else: self.isBlobHandlerPresent = False - - #for connection tracking, if applicable + self.optiondict = {} + + # out holds the output plugin. If None, will inherit the global output + self.out = None + # format is the format string for this plugin, if None, uses global + self.format = None + + # capture options + self.l2decoder = dpkt.ethernet.Ethernet # decoder to use if raw mode + # strip extra layers before IP/IPv6? (such as PPPoE, IP-over-IP, etc..) + self.striplayers = 0 + + self._DEBUG = False + + # can we chain a decoder off the output of this one? + self.chainable = False + self.subDecoder = None # decoder to pass output to for chaining + + # set flags to indicate if handlers are present + if 'packetHandler' in dir(self): + self.isPacketHandlerPresent = True + else: + self.isPacketHandlerPresent = False + if 'connectionHandler' in dir(self): + self.isConnectionHandlerPresent = True + else: + self.isConnectionHandlerPresent = False + if 'blobHandler' in dir(self): + self.isBlobHandlerPresent = True + else: + self.isBlobHandlerPresent = False + + # for connection tracking, if applicable self.connectionsDict = {} - self.cleanupts=0 + self.cleanupts = 0 - #instantiate and save references to lookup function + # instantiate and save references to lookup function try: - self.geoccdb = [ pygeoip.GeoIP(os.environ['DATAPATH']+'/GeoIP/GeoIP.dat', pygeoip.MEMORY_CACHE).country_code_by_addr ] - try: self.geoccdb.append( pygeoip.GeoIP(os.environ['DATAPATH']+'/GeoIP/GeoIPv6.dat', pygeoip.MEMORY_CACHE).country_code_by_addr ) - except: pass + self.geoccdb = [pygeoip.GeoIP(os.environ[ + 'DATAPATH'] + '/GeoIP/GeoIP.dat', pygeoip.MEMORY_CACHE).country_code_by_addr] + try: + self.geoccdb.append(pygeoip.GeoIP(os.environ[ + 'DATAPATH'] + '/GeoIP/GeoIPv6.dat', pygeoip.MEMORY_CACHE).country_code_by_addr) + except: + pass except: self.geoccdb = None try: - self.geoasndb = [ pygeoip.GeoIP(os.environ['DATAPATH']+'/GeoIP/GeoIPASNum.dat', pygeoip.MEMORY_CACHE).org_by_addr ] - try: self.geoasndb.append( pygeoip.GeoIP(os.environ['DATAPATH']+'/GeoIP/GeoIPASNumv6.dat', pygeoip.MEMORY_CACHE).org_by_addr ) - except: pass + self.geoasndb = [pygeoip.GeoIP( + os.environ['DATAPATH'] + '/GeoIP/GeoIPASNum.dat', pygeoip.MEMORY_CACHE).org_by_addr] + try: + self.geoasndb.append(pygeoip.GeoIP(os.environ[ + 'DATAPATH'] + '/GeoIP/GeoIPASNumv6.dat', pygeoip.MEMORY_CACHE).org_by_addr) + except: + pass except: self.geoasndb = None - #import kw args into class members - if kwargs: self.__dict__.update(kwargs) + # import kw args into class members + if kwargs: + self.__dict__.update(kwargs) '''convenience functions for alert output and logging''' - def alert(self,*args,**kw): + + def alert(self, *args, **kw): '''sends alert to output handler typically self.alert will be called with the decoded data and the packet/connection info dict last, as follows: @@ -133,100 +159,115 @@ def alert(self,*args,**kw): - remaining keyword arguments that do not match fields will be represented by "key=value" strings concatenated together into the "extra" field ''' - oargs=[] + oargs = [] for a in args: - #merge dict args, overriding kws - if type(a)==dict: kw.update(a) - elif type(a)==list: oargs.extend(a) - else: oargs.append(a) - if 'decoder' not in kw: kw['decoder']=self.name - self.out.alert(*oargs,**kw) #add decoder name - - def write(self,obj,**kw): + # merge dict args, overriding kws + if type(a) == dict: + kw.update(a) + elif type(a) == list: + oargs.extend(a) + else: + oargs.append(a) + if 'decoder' not in kw: + kw['decoder'] = self.name + self.out.alert(*oargs, **kw) # add decoder name + + def write(self, obj, **kw): '''write session data''' - self.out.write(obj,**kw) + self.out.write(obj, **kw) - def dump(self,*args,**kw): + def dump(self, *args, **kw): '''write packet data (probably to the PCAP writer if present)''' - if len(args)==3: - kw['len'],kw['pkt'],kw['ts']=args - elif len(args)==2: - kw['pkt'],kw['ts']=args - elif len(args)==1: - kw['pkt']=args[0] + if len(args) == 3: + kw['len'], kw['pkt'], kw['ts'] = args + elif len(args) == 2: + kw['pkt'], kw['ts'] = args + elif len(args) == 1: + kw['pkt'] = args[0] self.out.dump(**kw) - def log(self,msg,level=logging.INFO): + def log(self, msg, level=logging.INFO): '''logs msg at specified level (default of INFO is for -v/--verbose output)''' - self.out.log(msg,level=level) #default level is INFO (verbose) can be overridden + self.out.log( + msg, level=level) # default level is INFO (verbose) can be overridden - def debug(self,msg): + def debug(self, msg): '''logs msg at debug level''' - self.log(msg,level=logging.DEBUG) + self.log(msg, level=logging.DEBUG) - def warn(self,msg): + def warn(self, msg): '''logs msg at warning level''' - self.log(msg,level=logging.WARN) + self.log(msg, level=logging.WARN) pass - def error(self,msg): + def error(self, msg): '''logs msg at error level''' - self.log(msg,level=logging.ERROR) + self.log(msg, level=logging.ERROR) def __repr__(self): - return '%s %s %s' % (self.name,self.filter, - ' '.join([ ('%s=%s'%(x, str(self.__dict__.get(x)))) for x in self.optiondict.keys() ] ) ) - + return '%s %s %s' % (self.name, self.filter, + ' '.join([('%s=%s' % (x, str(self.__dict__.get(x)))) for x in self.optiondict.keys()])) def preModule(self): '''preModule is called before capture starts default preModule, dumps object data to debug''' - if self.subDecoder: self.subDecoder.preModule() - self.debug (self.name+' '+str(self.__dict__)) + if self.subDecoder: + self.subDecoder.preModule() + self.debug(self.name + ' ' + str(self.__dict__)) def postModule(self): '''postModule is called after capture stops default postModule, prints basic decoding stats''' self.cleanConnectionStore() - self.log("%s: %d packets (%d bytes) decoded"%(self.name,self.count,self.decodedbytes)) - if self.subDecoder: self.subDecoder.postModule() + self.log("%s: %d packets (%d bytes) decoded" % + (self.name, self.count, self.decodedbytes)) + if self.subDecoder: + self.subDecoder.postModule() def preFile(self): - if self.subDecoder: self.subDecoder.preFile() + if self.subDecoder: + self.subDecoder.preFile() def postFile(self): - if self.subDecoder: self.subDecoder.postFile() + if self.subDecoder: + self.subDecoder.postFile() - def parseOptions(self,options={}): + def parseOptions(self, options={}): '''option keys:values will set class members (self.key=value) if key is in optiondict''' for optname in self.optiondict.iterkeys(): - if optname in options: self.__dict__[optname]=options[optname] + if optname in options: + self.__dict__[optname] = options[optname] def parseArgs(self, args, options={}): '''called to parse command-line arguments and cli/config file options if options dict contains 'all' or the decoder name as a key class members will be updated from value''' - #get positional args after the -- + # get positional args after the -- self.args = args - #update from all decoders section of config file - if 'all' in options: self.parseOptions(options['all']) - #update from named section of config file - if self.name in options: self.parseOptions(options[self.name]) + # update from all decoders section of config file + if 'all' in options: + self.parseOptions(options['all']) + # update from named section of config file + if self.name in options: + self.parseOptions(options[self.name]) def getGeoIP(self, ip, db=[], notfound='--'): """ Get record associated with an IP requires GeoIP """ - o=None - if db == []: db = self.geoccdb # default to self.geoccdb + o = None + if db == []: + db = self.geoccdb # default to self.geoccdb for d in db: - try: o=d(ip) + try: + o = d(ip) except: - #traceback.print_exc() # removed by bg on 20121203 - continue #passing ipv6 address to ipv4 lookup or v/v - if o: return o #stop when we get a result + # traceback.print_exc() # removed by bg on 20121203 + continue # passing ipv6 address to ipv4 lookup or v/v + if o: + return o # stop when we get a result return notfound def getASN(self, ip, db=[], notfound='--'): @@ -234,134 +275,173 @@ def getASN(self, ip, db=[], notfound='--'): Get record associated with an IP requires GeoIP """ - o=None - if db == []: db = self.geoasndb # default to self.geoccdb + o = None + if db == []: + db = self.geoasndb # default to self.geoccdb for d in db: - try: o=d(ip) + try: + o = d(ip) except: - #traceback.print_exc() # removed by bg on 20121203 - continue #passing ipv6 address to ipv4 lookup or v/v - if o: return o #stop when we get a result + # traceback.print_exc() # removed by bg on 20121203 + continue # passing ipv6 address to ipv4 lookup or v/v + if o: + return o # stop when we get a result return notfound - def close(self,conn,ts=None): + def close(self, conn, ts=None): '''for connection based decoders close and discard the connection object''' - #just return if we have already been called on this connection - #prevents infinite loop of a handler calling close() when we call it - if conn.state=='closed': return - - #set state to closed - conn.state='closed' - if ts: conn.endtime=ts - # we have already stopped this so don't call the handlers if we have already stopped + # just return if we have already been called on this connection + # prevents infinite loop of a handler calling close() when we call it + if conn.state == 'closed': + return + + # set state to closed + conn.state = 'closed' + if ts: + conn.endtime = ts + # we have already stopped this so don't call the handlers if we have + # already stopped if not conn.stop: - #flush out the last blob to the blob handler - if self.isBlobHandlerPresent and conn.blobs: self.blobHandler(conn,conn.blobs[-1]) + # flush out the last blob to the blob handler + if self.isBlobHandlerPresent and conn.blobs: + self.blobHandler(conn, conn.blobs[-1]) # process connection handler - if self.isConnectionHandlerPresent: self.connectionHandler(conn) - #connection close handler - #will be called regardless of conn.stop right before conn object is destroyed - if 'connectionCloseHandler' in dir(self): self.connectionCloseHandler(conn) - #discard but check first in case a handler deleted it - if conn.addr in self.connectionsDict: del self.connectionsDict[conn.addr] - - def stop(self,conn): + if self.isConnectionHandlerPresent: + self.connectionHandler(conn) + # connection close handler + # will be called regardless of conn.stop right before conn object is + # destroyed + if 'connectionCloseHandler' in dir(self): + self.connectionCloseHandler(conn) + # discard but check first in case a handler deleted it + if conn.addr in self.connectionsDict: + del self.connectionsDict[conn.addr] + + def stop(self, conn): '''stop following connection handlers will not be called, except for connectionCloseHandler''' conn.stop = True - def cleanup(self,ts): + def cleanup(self, ts): '''if cleanup interval expired, close connections not updated in last interval''' - ts=util.mktime(ts) - #if cleanup interval has passed - if self.cleanupts<(ts-self.cleanupinterval): + ts = util.mktime(ts) + # if cleanup interval has passed + if self.cleanupts < (ts - self.cleanupinterval): for conn in self.connectionsDict.values(): - if util.mktime(conn.endtime)<=self.cleanupts: self.close(conn) - self.cleanupts=ts + if util.mktime(conn.endtime) <= self.cleanupts: + self.close(conn) + self.cleanupts = ts def cleanConnectionStore(self): '''cleans connection store of all information, flushing out data''' - for conn in self.connectionsDict.values(): self.close(conn) + for conn in self.connectionsDict.values(): + self.close(conn) - def _exc(self,e): + def _exc(self, e): '''exception handler''' self.warn(str(e)) - if self._DEBUG: traceback.print_exc() - - def find(self,addr,state=None): - if addr in self.connectionsDict: conn=self.connectionsDict[addr] - elif (addr[1],addr[0]) in self.connectionsDict: conn=self.connectionsDict[(addr[1],addr[0])] - else: return None - if not state or conn.state==state: return conn - else: return None - - def track(self,addr,data=None,ts=None,offset=None,**kwargs): + if self._DEBUG: + traceback.print_exc() + + def find(self, addr, state=None): + if addr in self.connectionsDict: + conn = self.connectionsDict[addr] + elif (addr[1], addr[0]) in self.connectionsDict: + conn = self.connectionsDict[(addr[1], addr[0])] + else: + return None + if not state or conn.state == state: + return conn + else: + return None + + def track(self, addr, data=None, ts=None, offset=None, **kwargs): '''connection tracking for TCP and UDP finds or creates connection based on addr updates connection with data if provided (using offset to reorder) tracks timestamps if ts provided extra args get passed to new connection objects ''' - conn=self.find(addr) - #look for forward and reverse address tuples - if not conn: #create new connection - #if swapping and source has low port, swap source/dest so dest has low port - if self.swaplowport and addr[0][1]1: conn.blobs.pop(0) - - self.cleanup(ts) #do stale state cleanup - return conn #return a reference to the connection + # forward or reverse direction? + if addr == conn.addr: + direction = 'cs' + else: + direction = 'sc' + + # check direction and blob count. + # If we have switched direction but already have max blobs + # close connection and replace it with a new one + if self.maxblobs and (direction != conn.direction) and (len(conn.blobs) == self.maxblobs): + self.close(conn) # close and call handlers + # recurse to create a new connection for the next + # request/response + return self.track(addr, data, ts) + + # update the connection to update current blob or start a new one + # and return the last one + # we will get a blob back if there is data to flush + blob = conn.update(ts, direction, data, offset=offset) + if blob and self.isBlobHandlerPresent: + self.blobHandler(conn, blob) + # we can discard all but the last blob + if not self.isConnectionHandlerPresent: + while len(conn.blobs) > 1: + conn.blobs.pop(0) + + self.cleanup(ts) # do stale state cleanup + return conn # return a reference to the connection '''directly extend Decoder and set raw=True to capture raw PCAP data''' - #we get the raw output from pcapy as header, data - def decode(self,*args,**kw): - if len(args) is 3: pktlen,pktdata,ts=args #orig_len,packet,ts format (pylibpcap) - else: #ts,pktdata (pypcap) - ts,pktdata=args - pktlen=len(pktdata) + # we get the raw output from pcapy as header, data + def decode(self, *args, **kw): + if len(args) is 3: + pktlen, pktdata, ts = args # orig_len,packet,ts format (pylibpcap) + else: # ts,pktdata (pypcap) + ts, pktdata = args + pktlen = len(pktdata) try: - if pktlen!=len(pktdata): raise Exception('packet truncated',pktlen,pktdata) - #decode with the L2 decoder (probably Ether) - pkt=self.l2decoder(pktdata) - #strip any intermediate layers (PPPoE, etc) - for l in xrange(int(self.striplayers)): pkt=pkt.data + if pktlen != len(pktdata): + raise Exception('packet truncated', pktlen, pktdata) + # decode with the L2 decoder (probably Ether) + pkt = self.l2decoder(pktdata) + # strip any intermediate layers (PPPoE, etc) + for l in xrange(int(self.striplayers)): + pkt = pkt.data '''will call self.rawHandler(len,pkt,ts) (hdr,data) is the PCAP header and raw packet data''' if 'rawHandler' in dir(self): - self.rawHandler(pktlen,pkt,ts,**kw) - else: pass - except Exception,e: self._exc(e) + self.rawHandler(pktlen, pkt, ts, **kw) + else: + pass + except Exception, e: + self._exc(e) + +# IP handler + -#IP handler class IPDecoder(Decoder): + '''extend IP6Decoder to capture IPv4 and IPv6 data (but does basic IPv4 defragmentation) config: @@ -378,108 +458,130 @@ class IPDecoder(Decoder): so keep your BPF to 'tcp' or 'udp' and set something like self.filterfn = lambda ((sip,sp),(dip,dp)): (sp==53 or dp==53) ''' - IP_PROTO_MAP={ - dpkt.ip.IP_PROTO_ICMP:'ICMP', - dpkt.ip.IP_PROTO_ICMP6:'ICMP6', - dpkt.ip.IP_PROTO_TCP:'TCP', - dpkt.ip.IP_PROTO_UDP:'UDP', - dpkt.ip.IP_PROTO_IP6:'IP6', - dpkt.ip.IP_PROTO_IP:'IP'} + IP_PROTO_MAP = { + dpkt.ip.IP_PROTO_ICMP: 'ICMP', + dpkt.ip.IP_PROTO_ICMP6: 'ICMP6', + dpkt.ip.IP_PROTO_TCP: 'TCP', + dpkt.ip.IP_PROTO_UDP: 'UDP', + dpkt.ip.IP_PROTO_IP6: 'IP6', + dpkt.ip.IP_PROTO_IP: 'IP'} def __init__(self, **kwargs): - self.v6only=False - self.decode6to4=True - self.defrag=True - self.striplayers=0 - self.l2decoder=dpkt.ethernet.Ethernet - self.filterfn=lambda addr: True - Decoder.__init__(self,**kwargs) - self.frags={} - - def ipdefrag(self,pkt): + self.v6only = False + self.decode6to4 = True + self.defrag = True + self.striplayers = 0 + self.l2decoder = dpkt.ethernet.Ethernet + self.filterfn = lambda addr: True + Decoder.__init__(self, **kwargs) + self.frags = {} + + def ipdefrag(self, pkt): '''ip fragment reassembly''' - #if pkt.off&dpkt.ip.IP_DF or pkt.off==0: return pkt #DF or !MF and offset 0 - f=self.frags.setdefault((pkt.src,pkt.dst,pkt.id),{}) #if we need to create a store for this IP addr/id - f[pkt.off&dpkt.ip.IP_OFFMASK]=pkt - offset=0 - data='' + # if pkt.off&dpkt.ip.IP_DF or pkt.off==0: return pkt #DF or !MF and + # offset 0 + # if we need to create a store for this IP addr/id + f = self.frags.setdefault((pkt.src, pkt.dst, pkt.id), {}) + f[pkt.off & dpkt.ip.IP_OFFMASK] = pkt + offset = 0 + data = '' while True: - if offset not in f: return None #we don't have this offset, can't reassemble yet - data+=str(pkt.data) #add this to the data - if not pkt.off&dpkt.ip.IP_MF: break #this is the next packet in order and no more fragments - offset=len(data)/8 #calculate the next fragment's offset - #we hit no MF and last offset, so return a defragged packet - del self.frags[(pkt.src,pkt.dst,pkt.id)] #discard store - pkt.data=data #replace payload with defragged data - pkt.off=0 #no frags, offset 0 - pkt.sum=0 #recompute checksum - return dpkt.ip.IP(str(pkt)) #dump and redecode packet to get checksum right - - def rawHandler(self,pktlen,pkt,ts,**kwargs): + if offset not in f: + return None # we don't have this offset, can't reassemble yet + data += str(pkt.data) # add this to the data + if not pkt.off & dpkt.ip.IP_MF: + break # this is the next packet in order and no more fragments + offset = len(data) / 8 # calculate the next fragment's offset + # we hit no MF and last offset, so return a defragged packet + del self.frags[(pkt.src, pkt.dst, pkt.id)] # discard store + pkt.data = data # replace payload with defragged data + pkt.off = 0 # no frags, offset 0 + pkt.sum = 0 # recompute checksum + # dump and redecode packet to get checksum right + return dpkt.ip.IP(str(pkt)) + + def rawHandler(self, pktlen, pkt, ts, **kwargs): '''takes ethernet data and determines if it contains IP or IP6. defragments IPv4 if 6to4, unencaps the IPv6 If IP/IP6, hands off to IPDecoder via IPHandler()''' try: - #if this is an IPv4 packet, defragment, decode and hand it off - if type(pkt.data)==dpkt.ip.IP: - if self.defrag: pkt=self.ipdefrag(pkt.data) #return packet if whole, None if more frags needed - else: pkt=pkt.data #get the layer 3 packet - if pkt: #do we have a whole IP packet? - if self.decode6to4 and pkt.p == dpkt.ip.IP_PROTO_IP6: pass #fall thru to ip6 decode - elif not self.v6only: #if we are decoding ip4 - sip,dip=socket.inet_ntoa(pkt.src),socket.inet_ntoa(pkt.dst) - #try to decode ports + # if this is an IPv4 packet, defragment, decode and hand it off + if type(pkt.data) == dpkt.ip.IP: + if self.defrag: + # return packet if whole, None if more frags needed + pkt = self.ipdefrag(pkt.data) + else: + pkt = pkt.data # get the layer 3 packet + if pkt: # do we have a whole IP packet? + if self.decode6to4 and pkt.p == dpkt.ip.IP_PROTO_IP6: + pass # fall thru to ip6 decode + elif not self.v6only: # if we are decoding ip4 + sip, dip = socket.inet_ntoa( + pkt.src), socket.inet_ntoa(pkt.dst) + # try to decode ports try: - sport,dport=pkt.data.sport,pkt.data.dport - except: #no ports in this layer-4 protocol - sport,dport=None,None - #generate int forms of src/dest ips - sipint,dipint=struct.unpack('!L',pkt.src)[0],struct.unpack('!L',pkt.dst)[0] - #call IPHandler with extra data - self.IPHandler(((sip,sport),(dip,dport)),pkt,ts, - pkttype=dpkt.ethernet.ETH_TYPE_IP, - proto=self.IP_PROTO_MAP.get(pkt.p,pkt.p), - sipint=sipint,dipint=dipint, - **kwargs) - if pkt and type(pkt.data)==dpkt.ip6.IP6: - pkt=pkt.data #no defrag of ipv6 - #decode ipv6 addresses - sip,dip=socket.inet_ntop(socket.AF_INET6,pkt.src), socket.inet_ntop(socket.AF_INET6,pkt.dst) - #try to get layer-4 ports + sport, dport = pkt.data.sport, pkt.data.dport + except: # no ports in this layer-4 protocol + sport, dport = None, None + # generate int forms of src/dest ips + sipint, dipint = struct.unpack( + '!L', pkt.src)[0], struct.unpack('!L', pkt.dst)[0] + # call IPHandler with extra data + self.IPHandler(((sip, sport), (dip, dport)), pkt, ts, + pkttype=dpkt.ethernet.ETH_TYPE_IP, + proto=self.IP_PROTO_MAP.get( + pkt.p, pkt.p), + sipint=sipint, dipint=dipint, + **kwargs) + if pkt and type(pkt.data) == dpkt.ip6.IP6: + pkt = pkt.data # no defrag of ipv6 + # decode ipv6 addresses + sip, dip = socket.inet_ntop(socket.AF_INET6, pkt.src), socket.inet_ntop( + socket.AF_INET6, pkt.dst) + # try to get layer-4 ports try: - sport,dport=pkt.data.sport,pkt.data.dport + sport, dport = pkt.data.sport, pkt.data.dport except: - sport,dport=None,None - #call ipv6 handler - self.IPHandler(((sip,sport),(dip,dport)),pkt,ts, - pkttype=dpkt.ethernet.ETH_TYPE_IP6, - proto=self.IP_PROTO_MAP.get(pkt.nxt,pkt.nxt), - **kwargs) - except Exception, e: self._exc(e) - - def IPHandler(self,addr,pkt,ts,**kwargs): + sport, dport = None, None + # call ipv6 handler + self.IPHandler(((sip, sport), (dip, dport)), pkt, ts, + pkttype=dpkt.ethernet.ETH_TYPE_IP6, + proto=self.IP_PROTO_MAP.get(pkt.nxt, pkt.nxt), + **kwargs) + except Exception, e: + self._exc(e) + + def IPHandler(self, addr, pkt, ts, **kwargs): '''called if packet is IPv4/IPv6 check packets using filterfn here''' - self.decodedbytes+=len(str(pkt)) - self.count+=1 + self.decodedbytes += len(str(pkt)) + self.count += 1 if self.isPacketHandlerPresent and self.filterfn(addr): - return self.packetHandler(ip=Packet(self,addr,pkt=str(pkt),ts=ts,**kwargs)) -class IP6Decoder(IPDecoder): pass + return self.packetHandler(ip=Packet(self, addr, pkt=str(pkt), ts=ts, **kwargs)) + + +class IP6Decoder(IPDecoder): + pass + class UDPDecoder(IPDecoder): + '''extend UDPDecoder to decode UDP optionally track state config if tracking state with connectionHandler or blobHandler maxblobs - if tracking state, max blobs to track before flushing swaplowport - when establishing state, swap source/dest so dest has low port cleanupinterval - seconds with no activity before state is discarded (default 60) ''' - def __init__(self, **kwargs): - self.maxblobs=2 #by default limit UDP 'connections' to a single request and response - self.swaplowport=True #can we swap source/dest so dest always has low port? - self.cleanupinterval=60 - IPDecoder.__init__(self,**kwargs) - def UDP(self,addr,data,pkt,ts=None,**kwargs): + def __init__(self, **kwargs): + # by default limit UDP 'connections' to a single request and response + self.maxblobs = 2 + # can we swap source/dest so dest always has low port? + self.swaplowport = True + self.cleanupinterval = 60 + IPDecoder.__init__(self, **kwargs) + + def UDP(self, addr, data, pkt, ts=None, **kwargs): ''' will call self.packetHandler(udp=Packet(),data=data) (see Packet() for Packet object common attributes) udp.pkt will contain the raw IP data @@ -506,26 +608,32 @@ def UDP(self,addr,data,pkt,ts=None,**kwargs): self.connectionCloseHandler(conn=Connection()) when state is discarded (always) ''' - self.decodedbytes+=len(data) - self.count+=1 + self.decodedbytes += len(data) + self.count += 1 try: if self.isPacketHandlerPresent: - #create a Packet object and populate it - return self.packetHandler(udp=Packet(self,addr,pkt=pkt,ts=ts,**kwargs),data=data) + # create a Packet object and populate it + return self.packetHandler(udp=Packet(self, addr, pkt=pkt, ts=ts, **kwargs), data=data) - #if no PacketHandler, we need to track state - self.track(addr,data,ts,**kwargs) + # if no PacketHandler, we need to track state + self.track(addr, data, ts, **kwargs) - except Exception,e: self._exc(e) + except Exception, e: + self._exc(e) - def IPHandler(self,addr,pkt,ts,**kwargs): + def IPHandler(self, addr, pkt, ts, **kwargs): '''IPv4 dispatch, hands address, UDP payload and packet up to UDP callback''' if self.filterfn(addr): - if type(pkt.data)==dpkt.udp.UDP: return self.UDP(addr,str(pkt.data.data),str(pkt),ts,**kwargs) + if type(pkt.data) == dpkt.udp.UDP: + return self.UDP(addr, str(pkt.data.data), str(pkt), ts, **kwargs) + + +class UDP6Decoder(UDPDecoder): + pass -class UDP6Decoder(UDPDecoder): pass class TCPDecoder(UDPDecoder): + '''IPv6 TCP/UDP decoder reassembles TCP and UDP streams For TCP and UDP (if no packetHandler) @@ -551,54 +659,65 @@ class TCPDecoder(UDPDecoder): if packetHandler is present, it will be called only for UDP (and UDP will not be tracked)''' def __init__(self, **kwargs): - self.maxblobs=None #no limit on connections - self.swaplowport=False #can we swap source/dest so dest always has low port? - self.ignore_handshake=False #if set true, will requre TCP handshake to track connection - self.cleanupinterval=300 - #up two levels to IPDecoder - IPDecoder.__init__(self,**kwargs) - self.optiondict['ignore_handshake']={'action':'store_true','help':'ignore TCP handshake'} - - def IPHandler(self,addr,pkt,ts,**kwargs): + self.maxblobs = None # no limit on connections + # can we swap source/dest so dest always has low port? + self.swaplowport = False + # if set true, will requre TCP handshake to track connection + self.ignore_handshake = False + self.cleanupinterval = 300 + # up two levels to IPDecoder + IPDecoder.__init__(self, **kwargs) + self.optiondict['ignore_handshake'] = { + 'action': 'store_true', 'help': 'ignore TCP handshake'} + + def IPHandler(self, addr, pkt, ts, **kwargs): '''IPv4 dispatch''' if self.filterfn(addr): - if type(pkt.data)==dpkt.udp.UDP: return self.UDP(addr,str(pkt.data.data),str(pkt),ts,**kwargs) - elif type(pkt.data)==dpkt.tcp.TCP: return self.TCP(addr,pkt.data,ts,**kwargs) + if type(pkt.data) == dpkt.udp.UDP: + return self.UDP(addr, str(pkt.data.data), str(pkt), ts, **kwargs) + elif type(pkt.data) == dpkt.tcp.TCP: + return self.TCP(addr, pkt.data, ts, **kwargs) - def TCP(self,addr,tcp,ts,**kwargs): + def TCP(self, addr, tcp, ts, **kwargs): '''TCP dispatch''' - self.decodedbytes+=len(str(tcp)) - self.count+=1 + self.decodedbytes += len(str(tcp)) + self.count += 1 try: - #close connection - if tcp.flags&(dpkt.tcp.TH_FIN|dpkt.tcp.TH_RST): - conn=self.find(addr) + # close connection + if tcp.flags & (dpkt.tcp.TH_FIN | dpkt.tcp.TH_RST): + conn = self.find(addr) if conn: - #we might occasionally have data in a FIN packet - self.track(addr,str(tcp.data),ts,offset=tcp.seq) + # we might occasionally have data in a FIN packet + self.track(addr, str(tcp.data), ts, offset=tcp.seq) self.close(conn, ts) - #init connection, set TCP ISN - elif not self.ignore_handshake and tcp.flags==dpkt.tcp.TH_SYN: - conn=self.track(addr,ts=ts,state='init',**kwargs) - if conn: conn.nextoffset['cs']=tcp.seq+1 - #SYN ACK - elif not self.ignore_handshake and tcp.flags==(dpkt.tcp.TH_SYN|dpkt.tcp.TH_ACK): - conn=self.find(addr,state='init') - if conn and tcp.ack==conn.nextoffset['cs']: - conn.nextoffset['sc']=tcp.seq+1 - conn.state='established' + # init connection, set TCP ISN + elif not self.ignore_handshake and tcp.flags == dpkt.tcp.TH_SYN: + conn = self.track(addr, ts=ts, state='init', **kwargs) + if conn: + conn.nextoffset['cs'] = tcp.seq + 1 + # SYN ACK + elif not self.ignore_handshake and tcp.flags == (dpkt.tcp.TH_SYN | dpkt.tcp.TH_ACK): + conn = self.find(addr, state='init') + if conn and tcp.ack == conn.nextoffset['cs']: + conn.nextoffset['sc'] = tcp.seq + 1 + conn.state = 'established' - #all other states, or always if ignoring handshake - if self.ignore_handshake or self.find(addr,state='established'): self.track(addr,str(tcp.data),ts, - state='established',offset=tcp.seq,**kwargs) + # all other states, or always if ignoring handshake + if self.ignore_handshake or self.find(addr, state='established'): + self.track(addr, str(tcp.data), ts, + state='established', offset=tcp.seq, **kwargs) - except Exception,e: self._exc(e) + except Exception, e: + self._exc(e) -class TCP6Decoder(TCPDecoder): pass + +class TCP6Decoder(TCPDecoder): + pass class Data(object): + '''base class for data objects (packets,connections, etc..) these objects hold data (appendable array, typically of strings) and info members (updateable/accessible as members or as dict via info()) @@ -606,52 +725,56 @@ class Data(object): and associated functions (update,iter,str,repr) with a data() function and functions to manipulate the data''' - def __init__(self,*args,**kwargs): + def __init__(self, *args, **kwargs): self.info_keys = [] - #update with list data - self.data=list(args) - #update with keyword data + # update with list data + self.data = list(args) + # update with keyword data self.info(**kwargs) - def info(self,*args,**kwargs): + def info(self, *args, **kwargs): '''update/return info stored in this object data can be passwd as dict(s) or keyword args''' - args=list(args)+[kwargs] + args = list(args) + [kwargs] for a in args: - for k,v in a.iteritems(): - if k not in self.info_keys: self.info_keys.append(k) - self.__dict__[k]=v - return dict((k,self.__dict__[k]) for k in self.info_keys) + for k, v in a.iteritems(): + if k not in self.info_keys: + self.info_keys.append(k) + self.__dict__[k] = v + return dict((k, self.__dict__[k]) for k in self.info_keys) - def unpack(self,fmt,data,*args): + def unpack(self, fmt, data, *args): '''unpacks data using fmt to keys listed in args''' - self.info(dict(zip(args,struct.unpack(fmt,data)))) + self.info(dict(zip(args, struct.unpack(fmt, data)))) - def pack(self,fmt,*args): + def pack(self, fmt, *args): '''packs info keys in args using fmt''' - return struct.pack(fmt,*[self.__dict__[k] for k in args]) + return struct.pack(fmt, *[self.__dict__[k] for k in args]) - def update(self,*args,**kwargs): + def update(self, *args, **kwargs): '''updates data (and optionally keyword args)''' self.data.extend(args) self.info(kwargs) def __iter__(self): '''returns each data element in order added''' - for data in self.data: yield data + for data in self.data: + yield data def __str__(self): '''return string built from data''' return ''.join(self.data) def __repr__(self): - return ' '.join(['%s=%s'%(k,v) for k,v in self.info().iteritems()]) + return ' '.join(['%s=%s' % (k, v) for k, v in self.info().iteritems()]) - def __getitem__(self,k): return self.__dict__[k] - def __setitem__(self,k,v): self.__dict__[k]=v + def __getitem__(self, k): return self.__dict__[k] + + def __setitem__(self, k, v): self.__dict__[k] = v class Packet(Data): + '''metadata class for connectionless data Members: sip, sport, dip, dport : source ip and port, dest ip and port @@ -661,38 +784,43 @@ class Packet(Data): pkt : raw packet data any additional args will be added to info dict ''' - def __init__(self,decoder,addr,ts=None,pkt=None,**kwargs): - self.info_keys = ['addr','sip','dip','sport','dport','ts'] - self.addr=addr - #do not define pkt unless passed in - self.ts=ts - ((self.sip,self.sport),(self.dip,self.dport))=self.addr + + def __init__(self, decoder, addr, ts=None, pkt=None, **kwargs): + self.info_keys = ['addr', 'sip', 'dip', 'sport', 'dport', 'ts'] + self.addr = addr + # do not define pkt unless passed in + self.ts = ts + ((self.sip, self.sport), (self.dip, self.dport)) = self.addr if pkt: - self.pkt=pkt + self.pkt = pkt self.info(bytes=len(self.pkt)) - #pass instantiating decoder's cc/asn lookup objects to keep global cache + # pass instantiating decoder's cc/asn lookup objects to keep global + # cache try: - self.info(sipcc = decoder.getGeoIP(self.sip,db=decoder.geoccdb), - sipasn = decoder.getGeoIP(self.sip,db=decoder.geoasndb), - dipcc = decoder.getGeoIP(self.dip,db=decoder.geoccdb), - dipasn = decoder.getGeoIP(self.dip,db=decoder.geoasndb)) + self.info(sipcc=decoder.getGeoIP(self.sip, db=decoder.geoccdb), + sipasn=decoder.getGeoIP(self.sip, db=decoder.geoasndb), + dipcc=decoder.getGeoIP(self.dip, db=decoder.geoccdb), + dipasn=decoder.getGeoIP(self.dip, db=decoder.geoasndb)) except: - self.sipcc,self.sipasn,self.dipcc,self.dipasn=None,None,None,None + self.sipcc, self.sipasn, self.dipcc, self.dipasn = None, None, None, None - #update with additional info + # update with additional info self.info(**kwargs) def __iter__(self): - for p in self.pkt: yield ord(p) + for p in self.pkt: + yield ord(p) def __str__(self): return self.pkt def __repr__(self): - return "%(ts)s %(sip)16s :%(sport)-5s -> %(dip)5s :%(dport)-5s (%(sipcc)s -> %(dipcc)s)\n"%self.info() + return "%(ts)s %(sip)16s :%(sport)-5s -> %(dip)5s :%(dport)-5s (%(sipcc)s -> %(dipcc)s)\n" % self.info() + class Connection(Packet): + """ Connection class is used for tracking all information contained within an established TCP connection / UDP pseudoconnection @@ -715,74 +843,88 @@ class Connection(Packet): stop: if True, stopped following stream """ - MAX_OFFSET=0xffffffff #max offset before wrap, default is MAXINT32 for TCP sequence numbers - - def __init__(self,decoder,addr,ts=None,**kwargs): - self.state=None - self.nextoffset={'cs':0,'sc':0} #the offset we expect for the next blob in this direction - Packet.__init__(self,decoder,addr,ts=ts,**kwargs) #init IP-level data - self.clientip,self.clientport,self.serverip, self.serverport=(self.sip,self.sport,self.dip,self.dport) - self.info_keys.extend(['clientip','serverip','clientport','serverport']) - self.clientcountrycode,self.clientasn,self.servercountrycode,self.serverasn=(self.sipcc,self.sipasn,self.dipcc,self.dipasn) - self.info_keys.extend(['clientcountrycode','servercountrycode','clientasn','serverasn']) + MAX_OFFSET = 0xffffffff # max offset before wrap, default is MAXINT32 for TCP sequence numbers + + def __init__(self, decoder, addr, ts=None, **kwargs): + self.state = None + # the offset we expect for the next blob in this direction + self.nextoffset = {'cs': 0, 'sc': 0} + # init IP-level data + Packet.__init__(self, decoder, addr, ts=ts, **kwargs) + self.clientip, self.clientport, self.serverip, self.serverport = ( + self.sip, self.sport, self.dip, self.dport) + self.info_keys.extend( + ['clientip', 'serverip', 'clientport', 'serverport']) + self.clientcountrycode, self.clientasn, self.servercountrycode, self.serverasn = ( + self.sipcc, self.sipasn, self.dipcc, self.dipasn) + self.info_keys.extend( + ['clientcountrycode', 'servercountrycode', 'clientasn', 'serverasn']) self.clientpackets = 0 # we have the first packet for each connection self.serverpackets = 0 self.clientbytes = 0 self.serverbytes = 0 self.starttime = self.ts # datetime Obj containing start time self.endtime = self.ts - self.direction = 'init' # first update will change this, creating first blob - self.info_keys.extend(['clientpackets','clientbytes','serverpackets','serverbytes','starttime','endtime','state','direction']) - - self.blobs = [] #list of tuples of (direction,halfstream,startoffset,endoffset) indicating where each side talks + # first update will change this, creating first blob + self.direction = 'init' + self.info_keys.extend(['clientpackets', 'clientbytes', 'serverpackets', + 'serverbytes', 'starttime', 'endtime', 'state', 'direction']) + + # list of tuples of (direction,halfstream,startoffset,endoffset) + # indicating where each side talks + self.blobs = [] self.stop = False - def __repr__(self): # starttime cip sip return '%s %16s -> %16s (%s -> %s) %6s %6s %5d %5d %7d %7d %6ds %s' % ( - self.starttime, - self.clientip, - self.serverip, - self.clientcountrycode, - self.servercountrycode, - self.clientport, - self.serverport, - self.clientpackets, - self.serverpackets, - self.clientbytes, - self.serverbytes, - (util.mktime(self.endtime) - util.mktime(self.starttime)), - self.state) - - def update(self,ts,direction,data,offset=None): - #if we have no blobs or direction changes, start a new blob - lastblob=None + self.starttime, + self.clientip, + self.serverip, + self.clientcountrycode, + self.servercountrycode, + self.clientport, + self.serverport, + self.clientpackets, + self.serverpackets, + self.clientbytes, + self.serverbytes, + (util.mktime(self.endtime) - util.mktime(self.starttime)), + self.state) + + def update(self, ts, direction, data, offset=None): + # if we have no blobs or direction changes, start a new blob + lastblob = None if direction != self.direction: - self.direction=direction - #if we have a finished blob, return it - if self.blobs: lastblob=self.blobs[-1] - #for tracking offsets across blobs (TCP) set the startoffset of this blob to what we know it should be - #this may not necessarily be the offset of THIS data if packets are out of order - self.blobs.append(Blob(ts,direction,startoffset=self.nextoffset[direction])) - self.blobs[-1].update(ts,data,offset=offset) #update latest blob - if direction=='cs': - self.clientpackets+=1 - self.clientbytes+=len(data) - elif direction=='sc': - self.serverpackets+=1 - self.serverbytes+=len(data) - self.endtime=ts - #if we are tracking offsets, expect the next blob to be where this one ends so far - if offset!=None and offset >= self.nextoffset[direction]: self.nextoffset[direction]=(offset+len(data))&self.MAX_OFFSET + self.direction = direction + # if we have a finished blob, return it + if self.blobs: + lastblob = self.blobs[-1] + # for tracking offsets across blobs (TCP) set the startoffset of this blob to what we know it should be + # this may not necessarily be the offset of THIS data if packets + # are out of order + self.blobs.append( + Blob(ts, direction, startoffset=self.nextoffset[direction])) + self.blobs[-1].update(ts, data, offset=offset) # update latest blob + if direction == 'cs': + self.clientpackets += 1 + self.clientbytes += len(data) + elif direction == 'sc': + self.serverpackets += 1 + self.serverbytes += len(data) + self.endtime = ts + # if we are tracking offsets, expect the next blob to be where this one + # ends so far + if offset != None and offset >= self.nextoffset[direction]: + self.nextoffset[direction] = (offset + len(data)) & self.MAX_OFFSET return lastblob - #return one or both sides of the stream + # return one or both sides of the stream def data(self, direction=None, errorHandler=None, padding=None, overlap=True, caller=None): '''returns reassembled half-stream selected by direction 'sc' or 'cs' if no direction, return all stream data interleaved see Blob.data() for errorHandler docs''' - return ''.join( [b.data(errorHandler=errorHandler, padding=padding, overlap=overlap, caller=caller) for b in self.blobs if (not direction or b.direction==direction)] ) + return ''.join([b.data(errorHandler=errorHandler, padding=padding, overlap=overlap, caller=caller) for b in self.blobs if (not direction or b.direction == direction)]) def __str__(self): '''return all data interleaved''' @@ -790,9 +932,12 @@ def __str__(self): def __iter__(self): '''return each blob in capture order''' - for blob in self.blobs: yield blob + for blob in self.blobs: + yield blob + class Blob(Data): + '''a blob containins a contiguous part of the half-stream Members: starttime,endtime : start and end timestamps of this blob @@ -801,34 +946,40 @@ class Blob(Data): startoffset,endoffset: offset of this blob start/end in bytes from start of stream ''' - MAX_OFFSET=0xffffffff #max offset before wrap, default is MAXINT32 for TCP sequence numbers - - def __init__(self,ts,direction,startoffset): - self.starttime=ts - self.endtime=ts - self.direction=direction - self.segments={} # offset:[segments with offset] - self.startoffset=startoffset - self.endoffset=startoffset - self.info_keys = ['starttime','endtime','direction','startoffset','endoffset'] - - def update(self,ts,data,offset=None): - #if offsets are not being provided, just keep packets in wire order - if offset==None: offset=self.endoffset - #buffer each segment in a list, keyed by offset (captures retrans, etc) - self.segments.setdefault(offset,[]).append(data) - if ts>self.endtime: self.endtime=ts - #update the end offset if this packet goes at the end - if offset >= self.endoffset: self.endoffset=(offset+len(data))&self.MAX_OFFSET + # max offset before wrap, default is MAXINT32 for TCP sequence numbers + MAX_OFFSET = 0xffffffff + + def __init__(self, ts, direction, startoffset): + self.starttime = ts + self.endtime = ts + self.direction = direction + self.segments = {} # offset:[segments with offset] + self.startoffset = startoffset + self.endoffset = startoffset + self.info_keys = [ + 'starttime', 'endtime', 'direction', 'startoffset', 'endoffset'] + + def update(self, ts, data, offset=None): + # if offsets are not being provided, just keep packets in wire order + if offset == None: + offset = self.endoffset + # buffer each segment in a list, keyed by offset (captures retrans, + # etc) + self.segments.setdefault(offset, []).append(data) + if ts > self.endtime: + self.endtime = ts + # update the end offset if this packet goes at the end + if offset >= self.endoffset: + self.endoffset = (offset + len(data)) & self.MAX_OFFSET def __repr__(self): - return '%s %s (%s) +%s %d' % (self.starttime,self.endtime,self.direction,self.startoffset,len(self.segments)) + return '%s %s (%s) +%s %d' % (self.starttime, self.endtime, self.direction, self.startoffset, len(self.segments)) def __str__(self): '''returns segments of blob as string''' return self.data(padding='') - def data(self,errorHandler=None,padding=None,overlap=True,caller=None,dup=-1): + def data(self, errorHandler=None, padding=None, overlap=True, caller=None, dup=-1): '''returns segments of blob reassembled into a string if next segment offset is not the expected offset errorHandler(blob,expected,offset) will be called @@ -846,21 +997,31 @@ def data(self,errorHandler=None,padding=None,overlap=True,caller=None,dup=-1): 0: use first segment seen -1 (default): use last segment seen ''' - d='' - nextoffset=self.startoffset + d = '' + nextoffset = self.startoffset for segoffset in sorted(self.segments.iterkeys()): - if segoffset!=nextoffset: - if errorHandler: #errorhandler can mangle blob data - if not errorHandler(blob=self, expected=nextoffset, offset=segoffset, caller=caller): continue #errorhandler determines pass or fail here - elif segoffset>nextoffset: - if padding is not None: #data missing and padding specified - if len(padding): d+=str(padding)*(segoffset-nextoffset) #add padding to data - else: raise KeyError(nextoffset) #data missing, and no padding - elif segoffset nextoffset: + # data missing and padding specified + if padding is not None: + if len(padding): + # add padding to data + d += str(padding) * (segoffset - nextoffset) + else: + # data missing, and no padding + raise KeyError(nextoffset) + elif segoffset < nextoffset and not overlap: + continue # skip if not allowing overlap + # advance next expected offset + nextoffset = ( + segoffset + len(self.segments[segoffset][dup])) & self.MAX_OFFSET + # append or splice data + d = d[:segoffset - self.startoffset] + \ + self.segments[segoffset][dup] + \ + d[nextoffset - self.startoffset:] return d def __iter__(self): @@ -870,4 +1031,5 @@ def __iter__(self): for UDP this will return datagrams payloads in capture order, (very useful for RTP or other streaming protocol.) ''' - for segoffset in sorted(self.segments.iterkeys()): yield self.segments[segoffset][-1] + for segoffset in sorted(self.segments.iterkeys()): + yield self.segments[segoffset][-1] diff --git a/lib/httpdecoder.py b/lib/httpdecoder.py index 3c1fe8e..35e8b78 100644 --- a/lib/httpdecoder.py +++ b/lib/httpdecoder.py @@ -1,11 +1,15 @@ #!/usr/bin/env python -import dshell, util, dpkt +import dshell +import util +import dpkt # for HTTPDecoder gzip decompression import gzip import cStringIO + class HTTPDecoder(dshell.TCPDecoder): + '''extend HTTPDecoder to handle HTTP request/responses will call HTTPHandler( conn=Connection(), @@ -21,68 +25,76 @@ class HTTPDecoder(dshell.TCPDecoder): ''' def __init__(self, **kwargs): - self.noresponse=True - self.gunzip=True - dshell.TCPDecoder.__init__(self,**kwargs) - self.requests={} + self.noresponse = True + self.gunzip = True + dshell.TCPDecoder.__init__(self, **kwargs) + self.requests = {} # Custom error handler for data reassembly --- ignores errors, keep data def errorH(self, **x): return True - def blobHandler(self,conn,blob): + def blobHandler(self, conn, blob): '''buffer the request blob and call the handler once we have the response blob''' - if blob.direction=='cs': + if blob.direction == 'cs': try: - self.requests[conn]=(blob.starttime,dpkt.http.Request(blob.data(self.errorH))) - except Exception, e: self.UnpackError(e) - elif blob.direction=='sc' and conn in self.requests: + self.requests[conn] = ( + blob.starttime, dpkt.http.Request(blob.data(self.errorH))) + except Exception, e: + self.UnpackError(e) + elif blob.direction == 'sc' and conn in self.requests: try: if 'HTTPHandler' in dir(self): - response=dpkt.http.Response(blob.data(self.errorH)) + response = dpkt.http.Response(blob.data(self.errorH)) if self.gunzip and 'gzip' in util.getHeader(response, 'content-encoding'): bodyUnzip = self.decompressGzipContent(response.body) - if bodyUnzip != None: response.body = bodyUnzip + if bodyUnzip != None: + response.body = bodyUnzip self.HTTPHandler(conn=conn, - request=self.requests[conn][1], - response=response, - requesttime=self.requests[conn][0], - responsetime=blob.starttime) + request=self.requests[conn][1], + response=response, + requesttime=self.requests[conn][0], + responsetime=blob.starttime) del self.requests[conn] - except Exception,e: + except Exception, e: self.UnpackError(e) - self.HTTPHandler(conn=conn,request=self.requests[conn][1],response=None,requesttime=self.requests[conn][0],responsetime=blob.starttime) + self.HTTPHandler(conn=conn, request=self.requests[conn][ + 1], response=None, requesttime=self.requests[conn][0], responsetime=blob.starttime) del self.requests[conn] - def connectionHandler(self,conn): + def connectionHandler(self, conn): '''when the connection closes, flush out any request blobs that did not have a response''' if conn in self.requests: if self.noresponse and 'HTTPHandler' in dir(self): self.HTTPHandler(conn=conn, - request=self.requests[conn][1], - response=None, - requesttime=self.requests[conn][0], - responsetime=self.requests[conn][0]) + request=self.requests[conn][1], + response=None, + requesttime=self.requests[conn][0], + responsetime=self.requests[conn][0]) del self.requests[conn] - def decompressGzipContent(self,httpcontent): + def decompressGzipContent(self, httpcontent): '''utility function to decompress gzip compressed content''' cstr = cStringIO.StringIO(httpcontent) - try: return gzip.GzipFile(fileobj=cstr).read() - except: return None + try: + return gzip.GzipFile(fileobj=cstr).read() + except: + return None def UnpackError(self, error): self._exc(error) + class displaystub(dshell.Decoder): + def __init__(self): dshell.Decoder.__init__(self, - name='httpdecoder', - description='Intermediate class to support HTTP based decoders.', - longdescription="See source code or pydoc for details on use." - ) + name='httpdecoder', + description='Intermediate class to support HTTP based decoders.', + longdescription="See source code or pydoc for details on use." + ) -if __name__=='__main__': +if __name__ == '__main__': dObj = displaystub() print dObj else: diff --git a/lib/output/colorout.py b/lib/output/colorout.py index 03e471d..ff7d336 100644 --- a/lib/output/colorout.py +++ b/lib/output/colorout.py @@ -2,11 +2,17 @@ @author: amm ''' -import output,util,dshell +import output +import util +import dshell import sys -import cgi, string, datetime +import cgi +import string +import datetime + class ColorOutput(output.TextOutput): + ''' Color-coded Output module use with --output=colorout @@ -58,45 +64,51 @@ class ColorOutput(output.TextOutput): def errorH(self, **x): return True - def __init__(self,*args,**kwargs): + def __init__(self, *args, **kwargs): if 'format' in kwargs: - fmtstr=kwargs['format'] - del kwargs['format'] #don't let base class process this - else: fmtstr='' + fmtstr = kwargs['format'] + del kwargs['format'] # don't let base class process this + else: + fmtstr = '' # Title if 'title' not in dir(self): if 'title' in kwargs: - self.title=kwargs['title'] - del kwargs['title'] #don't let base class process this - else: self.title='Dshell' + self.title = kwargs['title'] + del kwargs['title'] # don't let base class process this + else: + self.title = 'Dshell' # Check for html generator mode if 'htmlgenerator' not in dir(self): if 'htmlgenerator' in kwargs: - self.htmlgenerator=kwargs['htmlgenerator'] - del kwargs['htmlgenerator'] #don't let base class process this - else: self.htmlgenerator=False + self.htmlgenerator = kwargs['htmlgenerator'] + # don't let base class process this + del kwargs['htmlgenerator'] + else: + self.htmlgenerator = False if self.htmlgenerator: self.htmlbuffer = '' # Check for force color mode if 'force' not in dir(self): if 'force' in kwargs: - self.force=True - del kwargs['force'] #don't let base class process this - else: self.force=False + self.force = True + del kwargs['force'] # don't let base class process this + else: + self.force = False # Override HTML for stdout if 'html' not in dir(self): if 'html' in kwargs: - self.html=True + self.html = True del kwargs['html'] - else: self.html=False + else: + self.html = False # Call parent init - output.TextOutput.__init__(self,format=fmtstr,**kwargs) + output.TextOutput.__init__(self, format=fmtstr, **kwargs) self.setColorMode() @@ -123,8 +135,6 @@ def setColorMode(self): # File. Use HTML. self._COLORMODE = 'HTML' - - # Internal function to write HTML # or buffer it in factory mode def _htmlwrite(self, text): @@ -143,7 +153,6 @@ def htmldump(self): self.htmlbuffer = '' return tmp - def close(self): # Footer if self._COLORMODE == 'HTML': @@ -155,28 +164,35 @@ def _reset_offsets(self, value=0): self._SC_offset = value self._NODIR_offset = value - def write(self,*args,**kw): + def write(self, *args, **kw): # KW Options - if 'hex' in kw and kw['hex']: self._hexmode = True - else: self._hexmode = False + if 'hex' in kw and kw['hex']: + self._hexmode = True + else: + self._hexmode = False if 'time' in kw and kw['time']: self._timemode = True self._htmldisplaytimes = True - else: self._timemode = False + else: + self._timemode = False # KW formatTag if 'formatTag' in kw: formatTag = kw['formatTag'] del kw['formatTag'] - else: formatTag = '' + else: + formatTag = '' # KW Direction - if 'direction' in kw: kwdirection = kw['direction'] - else: kwdirection = '' + if 'direction' in kw: + kwdirection = kw['direction'] + else: + kwdirection = '' # KW Offset - if 'offset' in kw: self._reset_offsets(kw['offset']) + if 'offset' in kw: + self._reset_offsets(kw['offset']) # KW Timestamp if 'timestamp' in kw and kw['timestamp'] != None: @@ -209,19 +225,22 @@ def write(self,*args,**kw): if len(formatTag) and self._COLORMODE == 'HTML': self._htmlwrite('' % formatTag) - def _write_blob(self, blob, encoding = None): - self._write_string(blob.data(errorHandler=self.errorH), blob.direction, blob.starttime, encoding) + def _write_blob(self, blob, encoding=None): + self._write_string( + blob.data(errorHandler=self.errorH), blob.direction, blob.starttime, encoding) - def _write_string(self, text, direction, timestamp, encoding = None): + def _write_string(self, text, direction, timestamp, encoding=None): - colorTag='' + colorTag = '' # Print TimestampcolorTag if self._COLORMODE == 'HTML' and timestamp != None: - self._htmlwrite('
\n%s UTC:
' % datetime.datetime.utcfromtimestamp(timestamp)) + self._htmlwrite('
\n%s UTC:
' % + datetime.datetime.utcfromtimestamp(timestamp)) #if self._hexmode: self._htmlwrite("
") elif self._COLORMODE == 'TTY' and self._timemode and timestamp != None: - self.fh.write('\x1b[36m%s UTC:\x1b[0m\n' % datetime.datetime.utcfromtimestamp(timestamp)) + self.fh.write('\x1b[36m%s UTC:\x1b[0m\n' % + datetime.datetime.utcfromtimestamp(timestamp)) # Set Direction if direction.lower() == 'cs': @@ -336,9 +355,11 @@ def _HTMLHeader(self, title="Dshell"): """ def _HTMLFooter(self): - if self._htmldisplaytimes: display_timestamps = "\n"; - else: display_timestamps = '' - return display_timestamps+""" + if self._htmldisplaytimes: + display_timestamps = "\n" + else: + display_timestamps = '' + return display_timestamps + """ """ diff --git a/lib/output/csvout.py b/lib/output/csvout.py index b37a24f..7b87b84 100644 --- a/lib/output/csvout.py +++ b/lib/output/csvout.py @@ -2,9 +2,12 @@ @author: tparker ''' -import output,util +import output +import util + class CSVOutput(output.TextOutput): + ''' CSV Output module use with --output=csvout,[,data,customfield[:type],...] (a list of field:types to append to end of default format) @@ -15,47 +18,54 @@ class CSVOutput(output.TextOutput): _NULL = '' - _DEFAULT_DELIM=',' + _DEFAULT_DELIM = ',' - _DEFAULT_FIELDS=[('decoder','s'),('datetime','s'),('sip','s'),('sport','s'),('dip','s'),('dport','s')] + _DEFAULT_FIELDS = [('decoder', 's'), ('datetime', 's'), + ('sip', 's'), ('sport', 's'), ('dip', 's'), ('dport', 's')] - def __init__(self,*args,**kwargs): + def __init__(self, *args, **kwargs): ''' sets up an output module, be sure to call Output.__init__ first or last args will have the name of the module as args[0], anything else after ''' - #start with a set of default fields - fields=self._DEFAULT_FIELDS + # start with a set of default fields + fields = self._DEFAULT_FIELDS if 'format' in kwargs: - fields=[] - fmtstr=kwargs['format'] - del kwargs['format'] #don't let base class process this - else: fmtstr='' + fields = [] + fmtstr = kwargs['format'] + del kwargs['format'] # don't let base class process this + else: + fmtstr = '' - #set delimiter + # set delimiter if 'delim' in kwargs: - delim=kwargs['delim'] - if delim.lower() == 'tab': delim = "\t" - else: delim=self._DEFAULT_DELIM + delim = kwargs['delim'] + if delim.lower() == 'tab': + delim = "\t" + else: + delim = self._DEFAULT_DELIM - #parse args as fields + # parse args as fields if len(args): for a in args: - try: f,t=a.split(':') #split on field:type - except:f,t=a,'s' #default to string type - fields.append((f,t)) + try: + f, t = a.split(':') # split on field:type + except: + f, t = a, 's' # default to string type + fields.append((f, t)) - #build format string to pass to textoutput - if fmtstr: fmtstr+=delim - fmtstr+=delim.join(['%%(%s)%s'%(f,t) for f,t in fields]) + # build format string to pass to textoutput + if fmtstr: + fmtstr += delim + fmtstr += delim.join(['%%(%s)%s' % (f, t) for f, t in fields]) - #everything else is exactly like the text output module - output.TextOutput.__init__(self,format=fmtstr,**kwargs) + # everything else is exactly like the text output module + output.TextOutput.__init__(self, format=fmtstr, **kwargs) - #print header if not suppressed + # print header if not suppressed if self.fh and 'noheader' not in kwargs: - self.fh.write('#'+delim.join([f[0] for f in fields])+"\n") + self.fh.write('#' + delim.join([f[0] for f in fields]) + "\n") '''NOTE: output modules return obj=reference to the CLASS instead of a dObj=instance so we can init with args''' diff --git a/lib/output/jsonout.py b/lib/output/jsonout.py index d006ab8..b8aa259 100644 --- a/lib/output/jsonout.py +++ b/lib/output/jsonout.py @@ -6,7 +6,9 @@ import datetime import json + class JSONOutput(output.TextOutput): + ''' JSON Output module use with --output=jsonout @@ -21,9 +23,10 @@ class JSONOutput(output.TextOutput): ''' - _TIMESTAMP_FIELDS=('ts', 'starttime', 'endtime', 'request_time', 'response_time') + _TIMESTAMP_FIELDS = ( + 'ts', 'starttime', 'endtime', 'request_time', 'response_time') - def __init__(self,*args,**kwargs): + def __init__(self, *args, **kwargs): # Options self.options = {} @@ -42,9 +45,9 @@ def __init__(self,*args,**kwargs): self.jsonfields.append(a) # Call parent init - output.TextOutput.__init__(self,**kwargs) + output.TextOutput.__init__(self, **kwargs) - def alert(self,*args,**kw): + def alert(self, *args, **kw): # User specified field list?? if self.jsonfields != None: @@ -54,20 +57,27 @@ def alert(self,*args,**kw): elif not self.options['notrim']: # Remove Common Redundant Fields for name in ('addr', 'direction', 'clientport', 'serverport', 'clientip', 'serverip', 'sipint', 'dipint'): - if name in kw: del kw[name] + if name in kw: + del kw[name] # Time Fields # Rename 'ts' to 'starttime' if 'starttime' not present if 'ts' in kw: - if 'starttime' not in kw: kw['starttime'] = kw['ts'] + if 'starttime' not in kw: + kw['starttime'] = kw['ts'] del kw['ts'] # Convert known timestamp fields to string format for name in self._TIMESTAMP_FIELDS: - try: kw[name] = datetime.datetime.fromtimestamp(float(kw[name])).strftime(self.timeformat) - except: pass + try: + kw[name] = datetime.datetime.fromtimestamp( + float(kw[name])).strftime(self.timeformat) + except: + pass # Remove GEOIP Fields if not self.options['geoip']: for name in ('servercountrycode', 'clientcountrycode', 'sipcc', 'dipcc', 'clientasn', 'serverasn', 'dipasn', 'sipasn'): - if name in kw: del kw[name] - self.fh.write(json.dumps(kw, ensure_ascii=self.options['ensure_ascii']) + "\n") + if name in kw: + del kw[name] + self.fh.write( + json.dumps(kw, ensure_ascii=self.options['ensure_ascii']) + "\n") obj = JSONOutput diff --git a/lib/output/netflowout.py b/lib/output/netflowout.py index 48dfe83..311b710 100644 --- a/lib/output/netflowout.py +++ b/lib/output/netflowout.py @@ -2,11 +2,14 @@ @author: amm ''' -import output,util +import output +import util import sys import datetime + class NetflowOutput(output.TextOutput): + ''' Netflow Output module use with --output=netflowoutput @@ -15,50 +18,67 @@ class NetflowOutput(output.TextOutput): #_DEFAULT_FIELDS=[('decoder','s'),('datetime','s'),('sip','s'),('sport','s'),('dip','s'),('dport','s')] #_DEFAULT_FORMAT="%(starttime)s %(sip)16s:%(sport)-5s -> %(dip)16s:%(dport)-5s" - def __init__(self,*args,**kwargs): - self.group=kwargs.get('group') - self.groups={} - if self.group: self.group=self.group.split('/') + def __init__(self, *args, **kwargs): + self.group = kwargs.get('group') + self.groups = {} + if self.group: + self.group = self.group.split('/') # Call parent init - output.TextOutput.__init__(self,**kwargs) + output.TextOutput.__init__(self, **kwargs) - def alert(self,*args,**kw): + def alert(self, *args, **kw): if self.group: - k=tuple(kw[g] for g in self.group) #group by selected fields + k = tuple(kw[g] for g in self.group) # group by selected fields if k not in self.groups: - r=k[::-1] - if r in self.groups: k=r #is other dir in groups - else: self.groups[k]=[] + r = k[::-1] + if r in self.groups: + k = r # is other dir in groups + else: + self.groups[k] = [] self.groups[k].append(kw) - else: self.__alert(**kw) #not grouping, just print it + else: + self.__alert(**kw) # not grouping, just print it def close(self): - #dump groups if we are closing output + # dump groups if we are closing output if self.group: for k in sorted(self.groups.iterkeys()): - #write header - self.fh.write(' '.join( '%s=%s'%(self.group[i],k[i]) for i in xrange(len(self.group)))+'\n') + # write header + self.fh.write(' '.join( + '%s=%s' % (self.group[i], k[i]) for i in xrange(len(self.group))) + '\n') for kw in self.groups[k]: self.fh.write('\t') - self.__alert(self,**kw) + self.__alert(self, **kw) self.fh.write('\n') output.TextOutput.close(self) - def __alert(self,*args,**kw): - self.fh.write('%s %16s -> %16s (%s -> %s) %4s %6s %6s %5d %5d %7d %7d %-.4fs\n' % ( datetime.datetime.utcfromtimestamp(kw['starttime']), - kw['clientip'], - kw['serverip'], - kw['clientcountrycode'], - kw['servercountrycode'], - kw['proto'], - kw['clientport'], - kw['serverport'], - kw['clientpackets'], - kw['serverpackets'], - kw['clientbytes'], - kw['serverbytes'], - (kw['endtime']-kw['starttime']) - ) - ) + def __alert(self, *args, **kw): + self.fh.write('%s %16s -> %16s (%s -> %s) %4s %6s %6s %5d %5d %7d %7d %-.4fs\n' % (datetime.datetime.utcfromtimestamp(kw['starttime']), + kw[ + 'clientip'], + kw[ + 'serverip'], + kw[ + 'clientcountrycode'], + kw[ + 'servercountrycode'], + kw[ + 'proto'], + kw[ + 'clientport'], + kw[ + 'serverport'], + kw[ + 'clientpackets'], + kw[ + 'serverpackets'], + kw[ + 'clientbytes'], + kw[ + 'serverbytes'], + ( + kw['endtime'] - kw['starttime']) + ) + ) obj = NetflowOutput diff --git a/lib/output/output.py b/lib/output/output.py index 5fe63fb..791c2b7 100644 --- a/lib/output/output.py +++ b/lib/output/output.py @@ -3,23 +3,30 @@ @author: tparker ''' -import os,sys,logging,struct,datetime -import dshell,util +import os +import sys +import logging +import struct +import datetime +import dshell +import util class Output(object): + ''' dShell output base class, extended by output types ''' - _DEFAULT_FORMAT='' - _DEFAULT_TIMEFORMAT='%Y-%m-%d %H:%M:%S' - _DEFAULT_DELIM=' ' - _NULL=None + _DEFAULT_FORMAT = '' + _DEFAULT_TIMEFORMAT = '%Y-%m-%d %H:%M:%S' + _DEFAULT_DELIM = ' ' + _NULL = None - _FILTER_EXTRA=False #true if you want to remove extra fields from the parsed record + # true if you want to remove extra fields from the parsed record + _FILTER_EXTRA = False - def __init__(self,*a,**kw): + def __init__(self, *a, **kw): ''' base output class constructor configuration kwords: @@ -27,34 +34,38 @@ def __init__(self,*a,**kw): format='format string' to override default formatstring for output class pcap = filename to write pcap ''' - #setup the logger - self.logger=kw.get('logger',logging) - - #parse the format string - self.setformat(kw.get('format',self._DEFAULT_FORMAT)) - self.timeformat=(kw.get('timeformat',self._DEFAULT_TIMEFORMAT)) - self.delim=(kw.get('delim',self._DEFAULT_DELIM)) - - if 'pcap' in kw: self.pcapwriter=PCAPWriter(kw['pcap']) - else: self.pcapwriter=None - - #this is up to the output plugin to process - #by default stuffs extra fields and data into 'extra' field - #if _FILTER_EXTRA is true - self.extra=kw.get('extra',False) - - #create the default session writer - if 'session' in kw: self.sessionwriter=SessionWriter(**kw) - else: self.sessionwriter=None - - #write a message to the log - def log(self,msg,level=logging.INFO,*args,**kw): + # setup the logger + self.logger = kw.get('logger', logging) + + # parse the format string + self.setformat(kw.get('format', self._DEFAULT_FORMAT)) + self.timeformat = (kw.get('timeformat', self._DEFAULT_TIMEFORMAT)) + self.delim = (kw.get('delim', self._DEFAULT_DELIM)) + + if 'pcap' in kw: + self.pcapwriter = PCAPWriter(kw['pcap']) + else: + self.pcapwriter = None + + # this is up to the output plugin to process + # by default stuffs extra fields and data into 'extra' field + # if _FILTER_EXTRA is true + self.extra = kw.get('extra', False) + + # create the default session writer + if 'session' in kw: + self.sessionwriter = SessionWriter(**kw) + else: + self.sessionwriter = None + + # write a message to the log + def log(self, msg, level=logging.INFO, *args, **kw): '''write a message to the log passes all args and kwargs thru to logging except for level= is used to set logging level''' - self.logger.log(level,msg,*args,**kw) + self.logger.log(level, msg, *args, **kw) - def setformat(self,formatstr=None,typemap=None): + def setformat(self, formatstr=None, typemap=None): '''parse a format string and extract the field info if no string given, reverts to default for class will set self.fields to be a list of (name,type,spec) tuples @@ -67,41 +78,58 @@ def setformat(self,formatstr=None,typemap=None): a typemap of [intype]=outtype (or [in]=(newintype,outtype) can be used to map and replace types ''' - if formatstr: self.format=formatstr+"\n" - else: self.format=self._DEFAULT_FORMAT+"\n" - self.fields=[] #will be a (name,type,length) tuple - self.fieldnames=[] - self.fieldmap={} - #get all the field names - e=0 + if formatstr: + self.format = formatstr + "\n" + else: + self.format = self._DEFAULT_FORMAT + "\n" + self.fields = [] # will be a (name,type,length) tuple + self.fieldnames = [] + self.fieldmap = {} + # get all the field names + e = 0 while True: - s=self.format.find('%',e)+1 #find the next format spec of %(...) - if s<1 or self.format[s]!='(': break #not %(... - e=self.format.find(')',s) - if e<0: break #didn't find a closing paren - fname=self.format[s+1:e] #get text between parens as field name - fspec='' #len/precision specs will be 0-9 between ) and type char - for i in xrange(e+1,len(self.format)): - if self.format[i] in '1234567890.+-# lLh': fspec+=self.format[i] - else: break #this char is not a spec char, it is the type char - ftype=self.format[i] - i+=1 - if idatetime , Xtime -> Xdatetime - kw[dt]=datetime.datetime.fromtimestamp(float(kw[ts])).strftime(self.timeformat) #format properly - if kw.get('direction') is 'cs': kw['dir_arrow']='->' - elif kw.get('direction') is 'sc': kw['dir_arrow']='<-' - else: kw['dir_arrow']='--' + # convert timestamps to proper format + for ts in [k for k in kw if k == 'ts' or k.endswith('time')]: + dt = ts[:-4] + 'datetime' # ts->datetime , Xtime -> Xdatetime + kw[dt] = datetime.datetime.fromtimestamp( + float(kw[ts])).strftime(self.timeformat) # format properly + if kw.get('direction') is 'cs': + kw['dir_arrow'] = '->' + elif kw.get('direction') is 'sc': + kw['dir_arrow'] = '<-' + else: + kw['dir_arrow'] = '--' if 'format' in kw: - self.setformat(kw['format']) #change the format string? + self.setformat(kw['format']) # change the format string? del kw['format'] - #create the record initialized to the _NULL value - rec=dict((f,self._NULL) for f in self.fieldnames) - #populate record from datadict if datadict key is a field + # create the record initialized to the _NULL value + rec = dict((f, self._NULL) for f in self.fieldnames) + # populate record from datadict if datadict key is a field if self._FILTER_EXTRA: - rec.update(dict((f,kw[f]) for f in self.fieldnames if (f in kw and kw[f]!=None))) - #place extra datadict keys into the extra field (and exclude the addr tuple) - if self.extra: rec['extra']=self.delim.join(['%s=%s'%(f,kw[f]) for f in sorted(kw.keys()) if f not in self.fieldnames and f != 'addr']) - else: #not filtering extra, just lump them in as fields + rec.update( + dict((f, kw[f]) for f in self.fieldnames if (f in kw and kw[f] != None))) + # place extra datadict keys into the extra field (and exclude the + # addr tuple) + if self.extra: + rec['extra'] = self.delim.join(['%s=%s' % (f, kw[f]) for f in sorted( + kw.keys()) if f not in self.fieldnames and f != 'addr']) + else: # not filtering extra, just lump them in as fields rec.update(kw) - #populate the data field - if args: rec['data']=self.delim.join(map(str,args)) + # populate the data field + if args: + rec['data'] = self.delim.join(map(str, args)) return rec - def dump(self,pkt=None,**kw): #pass packets to pcap + def dump(self, pkt=None, **kw): # pass packets to pcap '''dump raw packet data to an output override this if you want a format other than pcap''' - pktdata=str(pkt) #might be string, might be a dpkt object - pktlen=kw.get('len',len(pktdata)) - if self.pcapwriter: self.pcapwriter.write(pktlen,pktdata,kw['ts']) - else: self.log(util.hexPlusAscii(str(pkt)),level=logging.DEBUG) - - #close the PCAP output + pktdata = str(pkt) # might be string, might be a dpkt object + pktlen = kw.get('len', len(pktdata)) + if self.pcapwriter: + self.pcapwriter.write(pktlen, pktdata, kw['ts']) + else: + self.log(util.hexPlusAscii(str(pkt)), level=logging.DEBUG) + + # close the PCAP output def close(self): - if self.pcapwriter: self.pcapwriter.close() + if self.pcapwriter: + self.pcapwriter.close() - def dispatch(self,m,*args,**kwargs): + def dispatch(self, m, *args, **kwargs): '''dispatch from Q pop''' - if m=='write': self.write(*args,**kwargs) - if m=='alert': self.alert(*args,**kwargs) - if m=='dump': self.dump(*args,**kwargs) + if m == 'write': + self.write(*args, **kwargs) + if m == 'alert': + self.alert(*args, **kwargs) + if m == 'dump': + self.dump(*args, **kwargs) + class FileOutput(Output): - def __init__(self,*args,**kw): + + def __init__(self, *args, **kw): '''configuration for fileoutput: fh= file=filename to write to mode=mode to open file as, default 'w' ''' - #do base init first - Output.__init__(self,*args,**kw) - #get the output filehandle or file - f=None + # do base init first + Output.__init__(self, *args, **kw) + # get the output filehandle or file + f = None if 'fh' in kw: - self.fh=kw['fh'] + self.fh = kw['fh'] return - elif 'file' in kw: f=kw['file'] - elif args: f=args[0] + elif 'file' in kw: + f = kw['file'] + elif args: + f = args[0] if f: - if 'mode' in kw: mode=kw['mode'] - else: mode='w' - if mode=='noclobber': - mode='w' + if 'mode' in kw: + mode = kw['mode'] + else: + mode = 'w' + if mode == 'noclobber': + mode = 'w' try: while os.stat(f): - p=f.split('-') - try: p,n=p[:-1],int(p[-1]) - except ValueError: n=0 - f='-'.join(p+['%04d'%(int(n)+1)]) - except OSError: pass #file not found - self.fh=open(f,mode) - else: self.fh=sys.stdout - - def write(self,obj,**kw): + p = f.split('-') + try: + p, n = p[:-1], int(p[-1]) + except ValueError: + n = 0 + f = '-'.join(p + ['%04d' % (int(n) + 1)]) + except OSError: + pass # file not found + self.fh = open(f, mode) + else: + self.fh = sys.stdout + + def write(self, obj, **kw): '''write session data to the session output or stdout''' - if self.sessionwriter: self.sessionwriter.write(obj,**kw) - elif self.fh: self.fh.write(str(obj)) + if self.sessionwriter: + self.sessionwriter.write(obj, **kw) + elif self.fh: + self.fh.write(str(obj)) def close(self): '''close output if not stdout''' - if self.fh != sys.stdout: self.fh.close() + if self.fh != sys.stdout: + self.fh.close() Output.close(self) class TextOutput(FileOutput): + '''formatted text output to file or stdout''' - _DEFAULT_FORMAT="%(decoder)s %(datetime)s %(sip)16s:%(sport)-5s %(dir_arrow)s %(dip)16s:%(dport)-5s ** %(data)s **" + _DEFAULT_FORMAT = "%(decoder)s %(datetime)s %(sip)16s:%(sport)-5s %(dir_arrow)s %(dip)16s:%(dport)-5s ** %(data)s **" _NULL = '' - _FILTER_EXTRA=True + _FILTER_EXTRA = True - def __init__(self,*args,**kw): - if 'extra' in kw: self._DEFAULT_FORMAT += " [ %(extra)s ]" - FileOutput.__init__(self,*args,**kw) + def __init__(self, *args, **kw): + if 'extra' in kw: + self._DEFAULT_FORMAT += " [ %(extra)s ]" + FileOutput.__init__(self, *args, **kw) - def alert(self,*args,**kw): + def alert(self, *args, **kw): '''write an alert record we pass in the decoder object and args/dict''' - rec=self.parse(*args,**kw) - if rec: self.fh.write(self.format%rec) + rec = self.parse(*args, **kw) + if rec: + self.fh.write(self.format % rec) + class DBOutput(Output): + '''format strings as used by the DBOutput module to create tables and map fields these follow the usual %(name)type and in most cases a custom format string will work defualt type maps are: @@ -235,27 +296,30 @@ class DBOutput(Output): (note this also breaks compatibility with text format strings) ''' - _DEFAULT_FORMAT="%(decoder)T %(ts:timestamp)t %(sip)s %(sport)s %(dip)s %(dport)s %(data:alert)s" - _NULL=None - #format type to (type,coltype) map - _TYPEMAP={ 's':'VARCHAR', 'r':'VARCHAR', 'c':'CHAR(1)', - 'x':'VARCHAR', 'X':'VARCHAR', 'o':'VARCHAR', - 'd':'INTEGER', 'i':'INTEGER', 'u':'INTEGER', - 'e':'DECIMAL', 'E':'DECIMAL', - 'f':'DECIMAL', 'F':'DECIMAL', - 'g':'DECIMAL', 'G':'DECIMAL', - 'b':('d','BOOLEAN'), #'b' isn't a python type, so (ftype,DBTYPE) tuple for value formats input as ftype - 't':('f','TIMESTAMP'), 'D':('s','DATETIME'), #not standard across database types! - 'A': ('s','INET'), 'H':('s','HOST'), 'N':('s','CIDR') ,'M':('s','MACADDR') } #these are postgres specific - - #acceptable params to pass to db module connect method - _DBCONNPARAMS=['host','user','passwd','password','db','database','port','charset'] - - #map of db type to insert placeholder. '%s' is the default, but sqlite3 doesn't like it - #you can override this with the 'placeholder' config keyword - _DBTYPE_PLACEHOLDER_MAP={'sqlite3':'?'} - - def __init__(self,*args,**kw): + _DEFAULT_FORMAT = "%(decoder)T %(ts:timestamp)t %(sip)s %(sport)s %(dip)s %(dport)s %(data:alert)s" + _NULL = None + # format type to (type,coltype) map + _TYPEMAP = {'s': 'VARCHAR', 'r': 'VARCHAR', 'c': 'CHAR(1)', + 'x': 'VARCHAR', 'X': 'VARCHAR', 'o': 'VARCHAR', + 'd': 'INTEGER', 'i': 'INTEGER', 'u': 'INTEGER', + 'e': 'DECIMAL', 'E': 'DECIMAL', + 'f': 'DECIMAL', 'F': 'DECIMAL', + 'g': 'DECIMAL', 'G': 'DECIMAL', + # 'b' isn't a python type, so (ftype,DBTYPE) tuple for value formats input as ftype + 'b': ('d', 'BOOLEAN'), + # not standard across database types! + 't': ('f', 'TIMESTAMP'), 'D': ('s', 'DATETIME'), + 'A': ('s', 'INET'), 'H': ('s', 'HOST'), 'N': ('s', 'CIDR'), 'M': ('s', 'MACADDR')} # these are postgres specific + + # acceptable params to pass to db module connect method + _DBCONNPARAMS = ['host', 'user', 'passwd', + 'password', 'db', 'database', 'port', 'charset'] + + # map of db type to insert placeholder. '%s' is the default, but sqlite3 doesn't like it + # you can override this with the 'placeholder' config keyword + _DBTYPE_PLACEHOLDER_MAP = {'sqlite3': '?'} + + def __init__(self, *args, **kw): '''configuration: config=db config .ini file name to parse @@ -274,39 +338,49 @@ def __init__(self,*args,**kw): format_types=types to format before insert (default=x) ('s' to pad strings, 'x' to convert to hex, 'f' to format floats, 'fx' for hex and floats...) ''' - self.dbconfig=kw.copy() - #if we were passed a config.ini file, parse it and add the k/v pairs to the config + self.dbconfig = kw.copy() + # if we were passed a config.ini file, parse it and add the k/v pairs + # to the config if 'config' in self.dbconfig: import ConfigParser config = ConfigParser.ConfigParser() config.read(self.dbconfig['config']) sections = config.sections() if len(sections) > 0: - self.dbconfig['dbtype']=sections[0] - for k,v in config.items(sections[0],raw=True): - self.dbconfig[k]=v - #import the db module - self.db=__import__(self.dbconfig['dbtype']) - #create a connection, using a dict filtered to db conn params - self.dbconn=self.db.connect(*args,**dict((k,self.dbconfig[k]) for k in self._DBCONNPARAMS if k in self.dbconfig)) - #do the base init last to catch the format string, etc.. (as it may have come from the config file) - Output.__init__(self,*args,**self.dbconfig) - - def createtable(self,table=None): + self.dbconfig['dbtype'] = sections[0] + for k, v in config.items(sections[0], raw=True): + self.dbconfig[k] = v + # import the db module + self.db = __import__(self.dbconfig['dbtype']) + # create a connection, using a dict filtered to db conn params + self.dbconn = self.db.connect( + *args, **dict((k, self.dbconfig[k]) for k in self._DBCONNPARAMS if k in self.dbconfig)) + # do the base init last to catch the format string, etc.. (as it may + # have come from the config file) + Output.__init__(self, *args, **self.dbconfig) + + def createtable(self, table=None): '''creates a table based on the format string''' - if not table and 'table' in self.dbconfig: table=self.dbconfig['table'] + if not table and 'table' in self.dbconfig: + table = self.dbconfig['table'] try: - cursor = self.dbconn.cursor() - sqlfields=[] - for fname,ftype,fspec in [f for f in self.fields if f[1]!='T']: - ctype=self.fieldmap[fname][1] - #if no width spec, use TEXT instead of VARCHAR and hope the db likes it - if ctype=='VARCHAR' and not fspec: ctype='TEXT' - fdef=self.fieldmap[fname][0]+' '+ctype - if fspec: fdef+='('+fspec.strip('+-# lLh').replace('.',',')+')' #try to conver python format spec to something SQL will take + cursor = self.dbconn.cursor() + sqlfields = [] + for fname, ftype, fspec in [f for f in self.fields if f[1] != 'T']: + ctype = self.fieldmap[fname][1] + # if no width spec, use TEXT instead of VARCHAR and hope the db + # likes it + if ctype == 'VARCHAR' and not fspec: + ctype = 'TEXT' + fdef = self.fieldmap[fname][0] + ' ' + ctype + if fspec: + # try to conver python format spec to something SQL will + # take + fdef += '(' + \ + fspec.strip('+-# lLh').replace('.', ',') + ')' sqlfields.append(fdef) - sql = 'CREATE TABLE "' + table +'" ('+','.join(sqlfields)+')' - self.log(sql,logging.DEBUG) + sql = 'CREATE TABLE "' + table + '" (' + ','.join(sqlfields) + ')' + self.log(sql, logging.DEBUG) return cursor.execute(sql) except: raise @@ -316,120 +390,158 @@ def close(self): self.dbconn.close() Output.close(self) - def alert(self,*args,**kw): + def alert(self, *args, **kw): '''write an output record we pass in the decoder object and args/dict''' - rec=self.parse(self,*args,**kw) - if rec: self.insert(rec) + rec = self.parse(self, *args, **kw) + if rec: + self.insert(rec) - def setformat(self,formatstr=None): + def setformat(self, formatstr=None): '''calls main setformat and then builds the insert SQL''' - #what is the insert param?? some databases use %s, some use ? - #try to map it or take the placeholder keyword from config - ph=self.dbconfig.get('insert_param', - self._DBTYPE_PLACEHOLDER_MAP.get(self.dbconfig['dbtype'],'%%s') - ) - #these are the types we need to format before passing to the db - self.format_types=self.dbconfig.get('format_types','x') + # what is the insert param?? some databases use %s, some use ? + # try to map it or take the placeholder keyword from config + ph = self.dbconfig.get('insert_param', + self._DBTYPE_PLACEHOLDER_MAP.get( + self.dbconfig['dbtype'], '%%s') + ) + # these are the types we need to format before passing to the db + self.format_types = self.dbconfig.get('format_types', 'x') Output.setformat(self, formatstr, typemap=self._TYPEMAP) - #build all fields we map (except for [T]able select) - self.tablefield='decoder' #default to decodername - for fname,ftype,fspec in self.fields: - if ftype=='T': self.tablefield=fname - sqlfields=[self.fieldmap[fname][0] for (fname,ftype,fspec) in self.fields if fname in self.fieldmap] - self.insertsql='INSERT INTO "%%s" (%s) VALUES (%s)'%(','.join(sqlfields), ','.join([ph]*len(sqlfields)) ) - - - def insert(self,rec,table=None): + # build all fields we map (except for [T]able select) + self.tablefield = 'decoder' # default to decodername + for fname, ftype, fspec in self.fields: + if ftype == 'T': + self.tablefield = fname + sqlfields = [self.fieldmap[fname][0] + for (fname, ftype, fspec) in self.fields if fname in self.fieldmap] + self.insertsql = 'INSERT INTO "%%s" (%s) VALUES (%s)' % ( + ','.join(sqlfields), ','.join([ph] * len(sqlfields))) + + def insert(self, rec, table=None): ''' inserts rec dict using self.format into table (if given, else default or specified by field) if insert fails, tries to create table and insert again before raising exception ''' if not table: - if 'table' in self.dbconfig: table=self.dbconfig['table'] - elif rec[self.tablefield]: table=rec[self.tablefield] + if 'table' in self.dbconfig: + table = self.dbconfig['table'] + elif rec[self.tablefield]: + table = rec[self.tablefield] try: - sqlvalues=[] + sqlvalues = [] cursor = self.dbconn.cursor() - for fname,ftype,fspec in self.fields: + for fname, ftype, fspec in self.fields: if fname in self.fieldmap: - if ftype in self.format_types: #do we preformat this data? - sqlvalues.append(('%'+fspec+ftype)%rec[fname]) - else: sqlvalues.append(rec[fname]) - sql=self.insertsql%table #create a INSERT INTO table (fields) VALUES (?,?,?) for execute - self.log(sql+' %s'%sqlvalues,logging.DEBUG) + # do we preformat this data? + if ftype in self.format_types: + sqlvalues.append(('%' + fspec + ftype) % rec[fname]) + else: + sqlvalues.append(rec[fname]) + # create a INSERT INTO table (fields) VALUES (?,?,?) for execute + sql = self.insertsql % table + self.log(sql + ' %s' % sqlvalues, logging.DEBUG) except: raise - #try once, if it fails, try to create table and retry - #throws on second failure or create table failure - fail=False + # try once, if it fails, try to create table and retry + # throws on second failure or create table failure + fail = False while True: try: - cursor.execute(sql,sqlvalues) + cursor.execute(sql, sqlvalues) self.dbconn.commit() - break #success - except Exception,e: - self.log(e,level=logging.WARNING) - if fail: raise + break # success + except Exception, e: + self.log(e, level=logging.WARNING) + if fail: + raise else: - fail=True - try: self.createtable(table) - except: raise + fail = True + try: + self.createtable(table) + except: + raise + class PCAPWriter(FileOutput): + '''writes a pcap file''' - def __init__(self,*args,**kw): - FileOutput.__init__(self,*args,**kw) - if self.fh: self.fh.write(struct.pack('IHHIIII',0xa1b2c3d4,2,4,0,0,65535,1)) - #overrides Output.write to write session as PCAP - #data flow is Output.dump->pcapwriter.write - def write(self,pktlen,pktdata,ts): + def __init__(self, *args, **kw): + FileOutput.__init__(self, *args, **kw) + if self.fh: + self.fh.write( + struct.pack('IHHIIII', 0xa1b2c3d4, 2, 4, 0, 0, 65535, 1)) + + # overrides Output.write to write session as PCAP + # data flow is Output.dump->pcapwriter.write + def write(self, pktlen, pktdata, ts): if self.fh: - self.fh.write(struct.pack('II',int(ts),int((ts-int(ts))*1000000))) - self.fh.write(struct.pack('II',len(pktdata),pktlen)) #captured length, original length + self.fh.write( + struct.pack('II', int(ts), int((ts - int(ts)) * 1000000))) + # captured length, original length + self.fh.write(struct.pack('II', len(pktdata), pktlen)) self.fh.write(pktdata) + class SessionWriter(Output): + '''writes the session to one or more files''' - def __init__(self,session=None,**kw): - self.file=kw.get('session',session) - self.dir=kw.get('direction','both') - self.mode=kw.get('mode','a') - self.timeformat=(kw.get('timeformat',self._DEFAULT_TIMEFORMAT)) - self.fieldnames=[] - - def write(self,obj,**kwargs): - out=None - kw=dict(**kwargs) - try: # if a session object with info() and data() methods (conn or blob, but not packet) - kw.update(**obj.info()) #get object info - kw=self.parse(**kw) - if self.dir=='both': ds=[None] - elif self.dir=='split': ds=['cs','sc'] - else: ds=[self.dir] + + def __init__(self, session=None, **kw): + self.file = kw.get('session', session) + self.dir = kw.get('direction', 'both') + self.mode = kw.get('mode', 'a') + self.timeformat = (kw.get('timeformat', self._DEFAULT_TIMEFORMAT)) + self.fieldnames = [] + + def write(self, obj, **kwargs): + out = None + kw = dict(**kwargs) + # if a session object with info() and data() methods (conn or blob, but + # not packet) + try: + kw.update(**obj.info()) # get object info + kw = self.parse(**kw) + if self.dir == 'both': + ds = [None] + elif self.dir == 'split': + ds = ['cs', 'sc'] + else: + ds = [self.dir] for d in ds: - kw.update(direction=d if d else 'both') #set direction - out=FileOutput(self.file%kw,mode=self.mode)#format filename and open - out.fh.write(obj.data(direction=d)) #write obj data for direction + kw.update(direction=d if d else 'both') # set direction + # format filename and open + out = FileOutput(self.file % kw, mode=self.mode) + # write obj data for direction + out.fh.write(obj.data(direction=d)) out.close() - except:#if not a session object - out=FileOutput(self.file%kw,mode=self.mode) #build filename from kw + except: # if not a session object + # build filename from kw + out = FileOutput(self.file % kw, mode=self.mode) out.fh.write(str(obj)) out.close() + class QueueOutput(Output): + '''pipes pickled packets to parent process''' - def __init__(self,q,**kwargs): - self.queue=q - Output.__init__(self,**kwargs) - def write(self,*args,**kw): self.dispatch('write',*args,**kw) - def alert(self,*args,**kw): self.dispatch('alert',*args,**kw) - def dump(self,*args,**kw): self.dispatch('dump',*args,**kw) - def dispatch(self,m,*args,**kw): #takes (method,...) to Q - self.queue.put((m,args,kw)) + + def __init__(self, q, **kwargs): + self.queue = q + Output.__init__(self, **kwargs) + + def write(self, *args, **kw): self.dispatch('write', *args, **kw) + + def alert(self, *args, **kw): self.dispatch('alert', *args, **kw) + + def dump(self, *args, **kw): self.dispatch('dump', *args, **kw) + + def dispatch(self, m, *args, **kw): # takes (method,...) to Q + self.queue.put((m, args, kw)) + def close(self): self.queue.close() Output.close(self) -#default output module -obj=TextOutput +# default output module +obj = TextOutput diff --git a/lib/output/xmlout.py b/lib/output/xmlout.py index e4d8449..37a5e7a 100644 --- a/lib/output/xmlout.py +++ b/lib/output/xmlout.py @@ -2,40 +2,54 @@ @author: tparker ''' -import output,util,dshell +import output +import util +import dshell from xml.etree import ElementTree as ET + class XMLOutput(output.FileOutput): + '''XMLOutput Module''' - def __init__(self,*args,**kwargs): + + def __init__(self, *args, **kwargs): '''init the underlying file output to get the file handle''' - output.FileOutput.__init__(self,*args,**kwargs) #pass all to fileoutput - self.root=ET.Element('dshell') - self.element=self.root + output.FileOutput.__init__( + self, *args, **kwargs) # pass all to fileoutput + self.root = ET.Element('dshell') + self.element = self.root - def alert(self,*args,**kwargs): + def alert(self, *args, **kwargs): '''we will assume we get alerts before we get the matching session data''' - self.element=ET.SubElement(self.root,'alert',self._filter_attr(kwargs)) - self.element.text= self._filter_text( ' '.join(args) ) + self.element = ET.SubElement( + self.root, 'alert', self._filter_attr(kwargs)) + self.element.text = self._filter_text(' '.join(args)) - def write(self,obj,parent=None,**kwargs): + def write(self, obj, parent=None, **kwargs): '''write the object data under the last alert element (or the root if no alert) if a conn object recurse in by iterating else write the string output of the object''' - if not parent: parent=self.element - kw=dict(**kwargs) - tag=str(type(obj)).split("'",2)[1] # turns "" into "yyyy" - if tag.startswith('dshell.'): #is a dshell object - kw.update(**obj.info()) #get attribs - tag=tag.split('dshell.')[1] # turns "dshell.Connection" into "Connection" - e=ET.SubElement(parent,tag,self._filter_attr(kw)) - if tag=='Connection': #recurse on blobs in conn - for blob in obj: self.write(blob,parent=e) - return #subobjects will have the data - e.text=self._filter_text( str(obj) ) #leave this up to the object to handle - - def _filter_attr(self,d): return dict((k,str(v)) for (k,v) in d.iteritems()) - def _filter_text(self,t): return ''.join(c for c in t if ord(c)<128) + if not parent: + parent = self.element + kw = dict(**kwargs) + # turns "" into "yyyy" + tag = str(type(obj)).split("'", 2)[1] + if tag.startswith('dshell.'): # is a dshell object + kw.update(**obj.info()) # get attribs + # turns "dshell.Connection" into "Connection" + tag = tag.split('dshell.')[1] + e = ET.SubElement(parent, tag, self._filter_attr(kw)) + if tag == 'Connection': # recurse on blobs in conn + for blob in obj: + self.write(blob, parent=e) + return # subobjects will have the data + # leave this up to the object to handle + e.text = self._filter_text(str(obj)) + + def _filter_attr(self, d): return dict((k, str(v)) + for (k, v) in d.iteritems()) + + def _filter_text(self, t): return ''.join(c for c in t if ord(c) < 128) def close(self): '''write the ElementTree to the file''' diff --git a/lib/util.py b/lib/util.py index b15f734..0b2494a 100644 --- a/lib/util.py +++ b/lib/util.py @@ -1,13 +1,19 @@ -import urllib,sys,time,socket,struct,datetime +import urllib +import sys +import time +import socket +import struct +import datetime # dShell Utility Functions -def xor(input,key): - """ - Xor an input string with a given character key. - """ - output = ''.join([chr(ord(c)^key) for c in input]) - return output + +def xor(input, key): + """ + Xor an input string with a given character key. + """ + output = ''.join([chr(ord(c) ^ key) for c in input]) + return output # decode_base64 - decodes Base64 text with (optional) custom alphabet # @@ -18,41 +24,46 @@ def xor(input,key): # padchar: char, single character used for padding bytes in input (optional) # Returns: decoded string # -def decode_base64(intext, alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/', padchar = '=', debug=False): - # Build dictionary from alphabet - b64DictDec = {} - i = 0 - for c in alphabet: - if c in b64DictDec: - print '%c already exists in alphabet' % (c) - sys.exit(-1) - b64DictDec[c] = i - i += 1 - b64DictDec[padchar] = 0 - alphabet += padchar +def decode_base64(intext, alphabet='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/', padchar='=', debug=False): + + # Build dictionary from alphabet + b64DictDec = {} + i = 0 + for c in alphabet: + if c in b64DictDec: + print '%c already exists in alphabet' % (c) + sys.exit(-1) + b64DictDec[c] = i + i += 1 - outtext = '' + b64DictDec[padchar] = 0 + alphabet += padchar - intext = intext.rstrip('\n') + outtext = '' - i = 0 - while i < len(intext)-3: - if intext[i] not in alphabet or intext[i+1] not in alphabet or intext[i+2] not in alphabet or intext[i+3] not in alphabet: - if debug: sys.stderr.write("Non-alphabet character found in chunk: %s\n" % (hexPlusAscii(intext[i:i+4]))) - if debug: sys.stderr.write("Input: %s" % hexPlusAscii(intext)) - raise Exception - val = b64DictDec[intext[i]] * 262144 - val += b64DictDec[intext[i+1]] * 4096 - val += b64DictDec[intext[i+2]] * 64 - val += b64DictDec[intext[i+3]] - i += 4 - for factor in [65536, 256, 1]: - outtext += chr(int(val / factor)) - val = val % factor + intext = intext.rstrip('\n') - return outtext + i = 0 + while i < len(intext) - 3: + if intext[i] not in alphabet or intext[i + 1] not in alphabet or intext[i + 2] not in alphabet or intext[i + 3] not in alphabet: + if debug: + sys.stderr.write( + "Non-alphabet character found in chunk: %s\n" % (hexPlusAscii(intext[i:i + 4]))) + if debug: + sys.stderr.write("Input: %s" % hexPlusAscii(intext)) + raise Exception + val = b64DictDec[intext[i]] * 262144 + val += b64DictDec[intext[i + 1]] * 4096 + val += b64DictDec[intext[i + 2]] * 64 + val += b64DictDec[intext[i + 3]] + i += 4 + for factor in [65536, 256, 1]: + outtext += chr(int(val / factor)) + val = val % factor + + return outtext # printableText - returns text suitable for screen display @@ -64,12 +75,14 @@ def decode_base64(intext, alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnop # True = Don't print tab and line-feed chars # Output: string # -def printableText(intext, onlyText = False): - if onlyText: - FILTER_std_display=''.join([ chr(x) if x in range(32,127) else '.' for x in range(256) ]) - else: - FILTER_std_display=''.join([ chr(x) if x in [9,10,13]+range(32,127) else '.' for x in range(256) ]) - return intext.translate(FILTER_std_display) +def printableText(intext, onlyText=False): + if onlyText: + FILTER_std_display = ''.join( + [chr(x) if x in range(32, 127) else '.' for x in range(256)]) + else: + FILTER_std_display = ''.join( + [chr(x) if x in [9, 10, 13] + range(32, 127) else '.' for x in range(256)]) + return intext.translate(FILTER_std_display) # printableUnicode - returns unicode text minus control characters # @@ -82,21 +95,24 @@ def printableText(intext, onlyText = False): # # Reference: http://en.wikipedia.org/wiki/Unicode_control_characters # -UNICODE_CONTROL_CHARS = [ unichr(x) for x in range(0,9)+[11,12]+range(14,0x20)+[0x7f]+range(0x80,0xA0) ] -def printableUnicode(intext, onlyText = False): - if not type(intext) == unicode: - # Attempt to cast it - try: - intext = unicode(intext) - except: - try: - intext = unicode(intext, 'utf-8') - except: - return unicode(printableText(intext, onlyText)) - if onlyText: - return ''.join([ x for x in intext if x not in UNICODE_CONTROL_CHARS+[u'\t', u'\n', u'\r'] ]) - else: - return ''.join([ x for x in intext if x not in UNICODE_CONTROL_CHARS ]) +UNICODE_CONTROL_CHARS = [unichr(x) for x in range( + 0, 9) + [11, 12] + range(14, 0x20) + [0x7f] + range(0x80, 0xA0)] + + +def printableUnicode(intext, onlyText=False): + if not type(intext) == unicode: + # Attempt to cast it + try: + intext = unicode(intext) + except: + try: + intext = unicode(intext, 'utf-8') + except: + return unicode(printableText(intext, onlyText)) + if onlyText: + return ''.join([x for x in intext if x not in UNICODE_CONTROL_CHARS + [u'\t', u'\n', u'\r']]) + else: + return ''.join([x for x in intext if x not in UNICODE_CONTROL_CHARS]) # hexPlusAscii - returns two-column hex/ascii display text for binary input # @@ -106,16 +122,20 @@ def printableUnicode(intext, onlyText = False): # offset (optional, byte offset for display) # Output: string # -def hexPlusAscii(data, width = 16, offset = 0): - FILTER_hex_display=''.join([(len(repr(chr(x)))==3) and chr(x) or '.' for x in range(256)]) - dlen = len(data) - output = '' - for i in xrange(0, dlen, width): - s = data[i:i+width] - hexa = ' '.join(["%02X"%ord(x) for x in s]) - printable = s.translate(FILTER_hex_display) - output += "%08X %-*s %s\n" % (i+offset, 16*3 + 1, hexa, printable) - return output + + +def hexPlusAscii(data, width=16, offset=0): + FILTER_hex_display = ''.join( + [(len(repr(chr(x))) == 3) and chr(x) or '.' for x in range(256)]) + dlen = len(data) + output = '' + for i in xrange(0, dlen, width): + s = data[i:i + width] + hexa = ' '.join(["%02X" % ord(x) for x in s]) + printable = s.translate(FILTER_hex_display) + output += "%08X %-*s %s\n" % (i + + offset, 16 * 3 + 1, hexa, printable) + return output # URLDataToParameterDict - parses URL format string (i.e. the stuff after # the question mark) and returns dictionary @@ -126,77 +146,98 @@ def hexPlusAscii(data, width = 16, offset = 0): # Output: dictionary, indexed by parameter names # Requires: urllib # + + def URLDataToParameterDict(data): - if not ' ' in data: - p,kwp=strtok(data,sep='&') - return dict((urllib.unquote(k),urllib.unquote(kwp[k]))for k in kwp.keys()) - + if not ' ' in data: + p, kwp = strtok(data, sep='&') + return dict((urllib.unquote(k), urllib.unquote(kwp[k]))for k in kwp.keys()) + # strtok - string tokenizer a lot like C strtok # Author: twp # Input: a string, optionally a param sep and a key/value sep, as_list will force a list even if 0/1 params # Output: tuple of: None or string or list of params, dictionary indexed by key=value names of k/v params # Example : a,b,c=d,e=f returns ([a,b],{c:d,e:f}) -def strtok(data,sep=',',kvsep='=',as_list=False): - kwparams = {} - params = [] - for p in data.split(sep): - if kvsep in p: - (k,v) = p.split(kvsep,1) - kwparams[k.strip()] = v.strip() - else: params.append(p.strip()) - if not as_list: - if not len(params): params=None - elif len(params)==1: params=params[0] - return params,kwparams - -#mktime: if python timestamp object convery back to POSIX timestamp -#utctime: return UTC POSIX timestamp -#Author tparker + + +def strtok(data, sep=',', kvsep='=', as_list=False): + kwparams = {} + params = [] + for p in data.split(sep): + if kvsep in p: + (k, v) = p.split(kvsep, 1) + kwparams[k.strip()] = v.strip() + else: + params.append(p.strip()) + if not as_list: + if not len(params): + params = None + elif len(params) == 1: + params = params[0] + return params, kwparams + +# mktime: if python timestamp object convery back to POSIX timestamp +# utctime: return UTC POSIX timestamp +# Author tparker + + def mktime(ts): - if type(ts)==datetime.datetime: - return time.mktime(ts.timetuple()) - return ts + if type(ts) == datetime.datetime: + return time.mktime(ts.timetuple()) + return ts + def utctime(): - return time.mktime(time.gmtime()) - -#xordecode(key,data) -def xorStringDecode(key=None,data=None): - ptext = '' - for pos in range(0,len(data)): - ptext += chr( ord(data[pos]) ^ ord(key[pos % len(key)]) ) - return ptext - -def iptoint(ip): return struct.unpack('!L',socket.inet_aton(ip))[0] - -def inttoip(i): return socket.inet_ntoa(struct.pack('!L',i)) - -#universal q&d options parser -#standard args: -#args = cmdline args to parse (usually sys.argv[1:]) -#options = short option string, see getopt docs -#long_options = long options string, see getopt docs -# -#for repeated options: -#list_options = list of repeatable option keys ['-o','--option'] to make into lists -#auto_list = True to place any repeated options' values into lists -#replace_value = True to replace existing value if repeated option -def getopts(args,options, - long_options=[], - list_options=None, - auto_list=False, - replace_value=False): - import getopt - optd={} - opts,args=getopt.getopt(args,options,long_options) - for o,v in opts: - if o not in optd: #new option - if list_options and o in list_options: optd[o]=[v] #this option wil be a list - else: optd[o]=v #else set to value - elif type(optd[o])==list: optd[o].append(v) #append this value to list - elif auto_list: optd[o]=[optd[o],v] #else make value into a list - elif replace_value: optd[o]=v #replace value if desired - return optd,args + return time.mktime(time.gmtime()) + +# xordecode(key,data) + + +def xorStringDecode(key=None, data=None): + ptext = '' + for pos in range(0, len(data)): + ptext += chr(ord(data[pos]) ^ ord(key[pos % len(key)])) + return ptext + + +def iptoint(ip): return struct.unpack('!L', socket.inet_aton(ip))[0] + + +def inttoip(i): return socket.inet_ntoa(struct.pack('!L', i)) + +# universal q&d options parser +# standard args: +# args = cmdline args to parse (usually sys.argv[1:]) +# options = short option string, see getopt docs +# long_options = long options string, see getopt docs +# +# for repeated options: +# list_options = list of repeatable option keys ['-o','--option'] to make into lists +# auto_list = True to place any repeated options' values into lists +# replace_value = True to replace existing value if repeated option + + +def getopts(args, options, + long_options=[], + list_options=None, + auto_list=False, + replace_value=False): + import getopt + optd = {} + opts, args = getopt.getopt(args, options, long_options) + for o, v in opts: + if o not in optd: # new option + if list_options and o in list_options: + optd[o] = [v] # this option wil be a list + else: + optd[o] = v # else set to value + elif type(optd[o]) == list: + optd[o].append(v) # append this value to list + elif auto_list: + optd[o] = [optd[o], v] # else make value into a list + elif replace_value: + optd[o] = v # replace value if desired + return optd, args # getHeader - Extracts header information from dpkt HTTP request or response # objects. @@ -214,18 +255,20 @@ def getopts(args,options, # Input: request_or_response, header_name # Output: string (always) # + + def getHeader(request_or_response, header_name): - try: - httpHdr = request_or_response.headers[header_name] - except: - return '' - if type(httpHdr) == str: - return httpHdr - elif type(httpHdr) == list: - # return unique list joined by ',' - return ', '.join(set(httpHdr)) - else: - return '' + try: + httpHdr = request_or_response.headers[header_name] + except: + return '' + if type(httpHdr) == str: + return httpHdr + elif type(httpHdr) == list: + # return unique list joined by ',' + return ', '.join(set(httpHdr)) + else: + return '' # HTTPlastmodified - Extracts last-modified (or date) header from # HTTP response headers and normalizes date string format @@ -234,13 +277,13 @@ def getHeader(request_or_response, header_name): # Input: dpkt.http.response # Output: normalized datetime string # -def HTTPlastmodified(response): - try: - return datetime.datetime.strptime(response.headers['last-modified'], '%a, %d %b %Y %H:%M:%S %Z').strftime('%Y-%m-%d %H:%M:%S') - except: - try: - return datetime.datetime.strptime(response.headers['date'], '%a, %d %b %Y %H:%M:%S %Z').strftime('%Y-%m-%d %H:%M:%S') - except: - return '' - + +def HTTPlastmodified(response): + try: + return datetime.datetime.strptime(response.headers['last-modified'], '%a, %d %b %Y %H:%M:%S %Z').strftime('%Y-%m-%d %H:%M:%S') + except: + try: + return datetime.datetime.strptime(response.headers['date'], '%a, %d %b %Y %H:%M:%S %Z').strftime('%Y-%m-%d %H:%M:%S') + except: + return '' From 525d7608534844211a3cdfb1ebedd08da6916e3d Mon Sep 17 00:00:00 2001 From: dev195 Date: Wed, 4 Feb 2015 08:59:05 -0500 Subject: [PATCH 005/166] Updated rip-http decoder to allow a different output directory --- decoders/http/rip-http.py | 41 +++++++++++++++++++++++++++++---------- 1 file changed, 31 insertions(+), 10 deletions(-) diff --git a/decoders/http/rip-http.py b/decoders/http/rip-http.py index 8f7768d..02e2fbd 100644 --- a/decoders/http/rip-http.py +++ b/decoders/http/rip-http.py @@ -5,7 +5,6 @@ import string # import any other modules here -# import binascii import re import os import hashlib @@ -26,6 +25,7 @@ def __init__(self): optiondict={'append_conn': {'action': 'store_true', 'help': 'append sourceip-destip to filename'}, 'append_ts': {'action': 'store_true', 'help': 'append timestamp to filename'}, 'direction': {'help': 'cs=only capture client POST, sc=only capture server GET response'}, + 'outdir': {'help': 'directory to write output files (Default: current directory)', 'metavar': 'DIRECTORY', 'default': '.'}, 'content_filter': {'help': 'regex MIME type filter for files to save'}, 'name_filter': {'help': 'regex filename filter for files to save'}} ) @@ -36,8 +36,18 @@ def preModule(self): if self.name_filter: self.name_filter = re.compile(self.name_filter) HTTPDecoder.preModule(self) + self.openfiles = {} # dict of httpfile objects, indexed by url + # Create output directory, if necessary + if not os.path.exists(self.outdir): + try: + os.makedirs(self.outdir) + except (IOError, OSError) as e: + self.error("Could not create directory '%s': %s" % + (self.outdir, e)) + sys.exit(1) + def splitstrip(self, data, sep, strip=' '): return [lpart.strip(strip) for lpart in data.split(sep)] @@ -76,8 +86,8 @@ def HTTPHandler(self, conn, request, response, requesttime, responsetime): filename += '_%s-%s' % (conn.clientip, conn.serverip) if self.append_ts: filename += '_%d' % (conn.ts) - self.debug(filename) - f = open(filename, 'w') + self.debug(os.path.join(self.outdir, filename)) + f = open(os.path.join(self.outdir, filename), 'w') f.write(data) f.close() elif (not self.direction or self.direction == 'sc') and response and response.status[0] == '2': @@ -105,11 +115,12 @@ def HTTPHandler(self, conn, request, response, requesttime, responsetime): if not len(filename): filename = '%s-%s_index.html' % ( conn.serverip, conn.clientip) - while os.path.exists(filename): + while os.path.exists(os.path.join(self.outdir, filename)): filename += '_' self.alert("New file: %s (%s)" % (filename, url), conn.info()) - self.openfiles[url] = httpfile(filename) + self.openfiles[url] = httpfile( + os.path.join(self.outdir, filename), self) (s, e) = self.openfiles[url].handleresponse(response) self.write(" --> Range: %d - %d\n" % (s, e)) if self.openfiles[url].done(): @@ -120,16 +131,25 @@ def HTTPHandler(self, conn, request, response, requesttime, responsetime): class httpfile: - def __init__(self, filename): + def __init__(self, filename, decoder_instance): self.complete = False - self.size = 0 # Expected size in bytes of full file transfer + # Expected size in bytes of full file transfer + self.size = 0 # List of tuples indicating byte chunks already received and written to # disk self.ranges = [] + self.decoder = decoder_instance self.filename = filename - self.fh = open(filename, 'w') + try: + self.fh = open(filename, 'w') + except IOError as e: + self.decoder.error( + "Could not create file '%s': %s" % (filename, e)) + self.fh = None def __del__(self): + if self.fh is None: + return self.fh.close() if not self.done(): print "Incomplete file: %s" % self.filename @@ -170,8 +190,9 @@ def handleresponse(self, response): # Update range tracking self.ranges.append((range_start, range_end)) # Write part of file - self.fh.seek(range_start) - self.fh.write(response.body) + if self.fh is not None: + self.fh.seek(range_start) + self.fh.write(response.body) return (range_start, range_end) def done(self): From 022cd30085a4f17b53fea1bccf5f2dc20bd69939 Mon Sep 17 00:00:00 2001 From: Thomas Wunderlich Date: Thu, 5 Feb 2015 22:58:17 -0500 Subject: [PATCH 006/166] dpkt IS actually available from pip dpkt IS actually available from pip: sudo pip install dpkt Updating documentation to correct this. --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 4c7e4db..ed755c1 100644 --- a/README.md +++ b/README.md @@ -23,8 +23,8 @@ Key features: ## Installation -1. Install all of the necessary Python modules listed above. Many of them are available via pip and/or apt-get. Pygeoip is not yet available as a package and must be installed with pip or manually. All except dpkt are available with pip. - +1. Install all of the necessary Python modules listed above. Many of them are available via pip and/or apt-get. Pygeoip is not yet available as a package and must be installed with pip or manually. + 1. `sudo apt-get install python-crypto python-dpkt python-ipy python-pypcap` 2. `sudo pip install pygeoip` From 83139d4f24131ee6a675061dfdb778bc89fa095d Mon Sep 17 00:00:00 2001 From: Drew Winstel Date: Mon, 9 Feb 2015 11:19:20 -0600 Subject: [PATCH 007/166] util: support DOS/Unix line endings in decode_base64() In case the function gets fed Windows strings, the code should handle it. As suggested in http://stackoverflow.com/a/275401 --- lib/util.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/util.py b/lib/util.py index 0b2494a..4159f9b 100644 --- a/lib/util.py +++ b/lib/util.py @@ -43,7 +43,8 @@ def decode_base64(intext, alphabet='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr outtext = '' - intext = intext.rstrip('\n') + # support DOS and Unix line endings + intext = intext.rstrip('\r\n') i = 0 while i < len(intext) - 3: From ca66f9dffe1fa426e6ec0b244901d95bd52a8d25 Mon Sep 17 00:00:00 2001 From: dev195 Date: Tue, 10 Feb 2015 09:20:55 -0500 Subject: [PATCH 008/166] Updated README to use proper notation for GeoIP install location --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index ed755c1..2a734a8 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,7 @@ Key features: 2. `sudo pip install pygeoip` -2. Configure pygeoip by moving the MaxMind data files (GeoIP.dat, GeoIPv6.dat, GeoIPASNum.dat, GeoIPASNumv6.dat) to /share/GeoIP/ +2. Configure pygeoip by moving the MaxMind data files (GeoIP.dat, GeoIPv6.dat, GeoIPASNum.dat, GeoIPASNumv6.dat) to <install-location>/share/GeoIP/ 2. Run `make`. This will build Dshell. From bf5bafe611de94ef08c5e05c22395195a8a02dca Mon Sep 17 00:00:00 2001 From: William Glodek Date: Fri, 13 Feb 2015 10:07:13 -0500 Subject: [PATCH 009/166] Similar to ngrep but allows streams to be passed to downstream decoders --- decoders/misc/grep.py | 205 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 205 insertions(+) create mode 100644 decoders/misc/grep.py diff --git a/decoders/misc/grep.py b/decoders/misc/grep.py new file mode 100644 index 0000000..ea7f10a --- /dev/null +++ b/decoders/misc/grep.py @@ -0,0 +1,205 @@ +import dshell +import datetime +import sys + +# import any other modules here +import re + + +class grepDecoder(dshell.TCPDecoder): + + def __init__(self): + dshell.TCPDecoder.__init__(self, + name='grep', + description='Search for patterns in streams.', + longdescription=""" +Grep is a utility decoder, useful on it's own or in combination with +downstream (chained) decoders. Your search expression is specified with the +--grep_expression option, and the default behavior is that the entire "line" +of text surround each match will be printed, along with the standard +connection information. However, granular match information is passed to the +output decoder giving the user more control about the type of output they +would like to see. Following is the named-variable convention passed to +output: + + match: Full expression match + m1: First sub-match + m2: Second sub-match + .. + mn: N'th sub-match + +Examples: + + Snag User-Agent, display as CSV: + + decode -d grep --grep_ignorecase --grep_expression 'User-Agent: (.*?)$' --output csvout,m1 + + The text following User-Agent will be the first sub-match and then + printed as a named field in CSV output. + + Better yet: + + decode -d grep --grep_ignorecase --grep_expression 'User-Agent: (.*?)$' --oformat "%(m1)s" + + This uses the same expression but instead of the default output, + specifies "m1" in a format string which makes it the ONLY value + displayed. This is nice for piping into sort/uniq or other + command-line filters. + +Iterative matching + +Rather than alerting on an entire line or just the first hit within that line, +Python's regular expression module offers a function called "finditer" which +scans across input text and provides an iterable object of ALL the matches. +So with "--grep_iterate" we can use that. + +Examples: + + Simplistically grab all hyperlinks and dump to stdout: + + decode -d grep --grep_expression '' --grep_iterate --grep_ignorecase --oformat "%(m1)s" + +Chainable + +Grep is chainable. What does this mean? If data within a connection +matches a grep expression, the entire connection is considered a "hit" and is +then allowed to be processed by subDecoders. Non-hits are dropped. + +So this means you can search for an expression and view all matching +connections in followstream, or process all as web traffic, etc. + +Examples: + + View all web traffic that originated from Windows 7 machines: + + decode -d grep+web --grep_ignorecase --grep_expression 'User-Agent: [^\\r\\n]*Windows 6.1' +""", + author='amm', + filter='tcp', + optiondict={ + 'expression': {'type': 'string', 'help': 'Search expression'}, + 'ignorecase': {'action': 'store_true', 'help': 'Case insensitive search.'}, + 'singleline': {'action': 'store_true', 'help': 'Treat entire connection as single line of text.'}, + 'iterate': {'action': 'store_true', 'help': 'Iterate hits on match string.'}, + 'invert': {'action': 'store_true', 'help': 'For chained only: Invert hit results.'} + } + ) + self.chainable = True + + def preModule(self): + + # + # Does subdecoder have a blobHandler + # + if self.subDecoder and 'blobHandler' in dir(self.subDecoder): + self.debug("subDecoder has blobHandler") + self.subblobHandler = True + # Indexed by connection, storage for all blobs being deferred + self.deferredBlobs = {} + else: + self.subblobHandler = False + + # Pass/Drop dictionary of connections to use in chain mode + self.connstate = {} + + # Must use singleLine mode when subDecoder is present + if self.subDecoder: + self.singleline = True + + # Re parameters + self.reFlags = 0 + if self.ignorecase: + self.reFlags = self.reFlags | re.IGNORECASE + if self.singleline or self.iterate: + self.reFlags = self.reFlags | re.S + + # Re Expression -> Object + if self.expression == None or not len(self.expression): + self.error( + "Must specify expression using --%s_expression" % self.name) + sys.exit(1) + else: + sys.stderr.write("Using expression: '%s'\n" % self.expression) + self.reObj = re.compile(self.expression, self.reFlags) + + dshell.TCPDecoder.preModule(self) + + def errorH(self, **x): + # custom errorHandler here + pass + + def blobHandler(self, connection, blob): + # Defer all Blob processing until the connection is handled, so we can + # grep the entire connection stream + if self.subblobHandler: + if connection not in self.deferredBlobs: + self.deferredBlobs[connection] = [] + self.deferredBlobs[connection].append(blob) + + def connectionHandler(self, connection): + + # Normal processing, no subDecoder + if not self.subDecoder: + self.__searchStream(connection.data(direction='cs', errorHandler=self.errorH) + + "\n" + connection.data(direction='sc', errorHandler=self.errorH), connection) + return + + # Call sub blobHandler for all blobs + if self.subblobHandler and self.__connectionTest(connection): + self.debug("Preparing to process %d blobs in subdecoder" % + len(self.deferredBlobs)) + for b in self.deferredBlobs[connection]: + self.subDecoder.blobHandler(connection, b) + self.deferredBlobs[connection] = None + + # Call sub connectionHandler if necessary + if 'connectionHandler' in dir(self.subDecoder) and self.__connectionTest(connection): + self.subDecoder.connectionHandler(connection) + + def __alert(self, conn, hitstring, matchObj): + kwargs = {'match': matchObj.group(0)} + matchNumber = 0 + for mgroup in matchObj.groups(): + matchNumber += 1 + kwargs['m' + str(matchNumber)] = mgroup + self.alert(hitstring, kwargs, **conn.info()) + + def __connectionTest(self, connection): + if connection not in self.connstate: + if self.reObj.search(connection.data(direction='cs', errorHandler=self.errorH) + "\n" + connection.data(direction='sc', errorHandler=self.errorH)): + self.connstate[connection] = True + else: + self.connstate[connection] = False + if self.invert: + self.connstate[connection] = not self.connstate[connection] + if self.connstate[connection]: + return True + else: + return False + + def __searchStream(self, d, conn): + + if self.singleline or self.iterate: + self.__runSearch(d, conn) + else: + lines = d.split('\n') + for l in lines: + l = l.rstrip() + self.__runSearch(l, conn) + + def __runSearch(self, d, conn): + if self.iterate: + for m in self.reObj.finditer(d): + self.__alert(conn, m.group(0), m) + else: + m = self.reObj.search(d) + if m: + self.__alert(conn, d, m) + + +# always instantiate an dObj of the class +if __name__ == '__main__': + dObj = grepDecoder() + print dObj +else: + dObj = grepDecoder() From 46e691cfbf3e9597e9f5aab993b8d1087390f036 Mon Sep 17 00:00:00 2001 From: William Glodek Date: Thu, 19 Feb 2015 13:44:33 -0500 Subject: [PATCH 010/166] ftp decoder to track and dissect ftp sessions --- decoders/ftp/ftp.py | 291 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 291 insertions(+) create mode 100644 decoders/ftp/ftp.py diff --git a/decoders/ftp/ftp.py b/decoders/ftp/ftp.py new file mode 100644 index 0000000..8acfe58 --- /dev/null +++ b/decoders/ftp/ftp.py @@ -0,0 +1,291 @@ +############################################## +# File Transfer Protocol (FTP) +# +# Goes through TCP connections and tries to find FTP control channels and +# associated data channels. Optionally, it will write out any file data it +# sees into a separate directory. +# +# More specifically, it sets up an initial BPF that looks for control channels. +# As it finds them, it updates the BPF to include the data connection along +# ephemeral ports. +# +# If a data connection is seen, it prints a message indicating the user, pass, +# and file requested. If the dump flag is set, it also dumps the file into the +# __OUTDIR directory. +############################################## + +import dshell +import os +import re + +class DshellDecoder(dshell.TCPDecoder): + + def __init__(self): + dshell.TCPDecoder.__init__(self, + name='ftp', + description='ftp', + filter="tcp", + author='amm', + optiondict={ + 'port':{'type':'string', + 'default':'21', + 'help':'Port (or ports) to watch for control connections (Default: 21)'}, + 'dump':{'action':'store_true','help':'Dump files (Default: Off)'} + } + ) + + # Constants for channel type + __CTRLCONN = 0 + __DATACONN = 1 + __OUTDIR = 'ftpout' + + # Dynamically change the BPF filter + # to allow processing of data transfer channels + def __updatebpf(self): + dynfilters = [ '(host %s and host %s)' % self.conns[x]['tempippair'] for x in self.conns.keys() if 'tempippair' in self.conns[x] and self.conns[x]['tempippair'] != None ] + dynfilters.extend( [ '(host %s and port %d)' % (a,p) for a,p in self.datachan.keys() ] ) + self.filter = 'tcp and (%s%s)' % ( + ' or '.join(['port %d'%p for p in self.ctrlports]), + ' or '+' or '.join(dynfilters) if len(dynfilters) else '' + ) + self.debug("Setting BPF filter to: %s" % self.filter) + if 'capture' in dir(self): + self.capture.setfilter(self.filter,1) + + def preModule(self): + # Convert port specification from string to list of integers + self.ctrlports = [int(p) for p in self.port.split(',')] + self.datachan = {} # Dictionary of control channels indexed by data channel (host, port) tuples + self.conns = {} # Dictionary of information about connections + self.__updatebpf() # Set initial bpf + + # Attempt to create output directory + if self.dump: + self.__OUTDIR = self.__mkoutdir(self.__OUTDIR) + self.warn("Using output directory: %s" % self.__OUTDIR) + + def connectionInitHandler(self, conn): + # + # Setup conn info for New Data Channel + # + if conn.serverport in self.ctrlports: + self.conns[conn.addr] = { 'mode': self.__CTRLCONN, 'user':'', 'pass':'', 'path':[], 'lastcommand':'', 'filedata':None, 'file':('', '', '')} + elif self.dump and (conn.clientip, conn.clientport) in self.datachan: + self.conns[conn.addr] = { 'mode': self.__DATACONN, 'ctrlchan': self.datachan[(conn.clientip, conn.clientport)] } + elif self.dump and (conn.serverip, conn.serverport) in self.datachan: + self.conns[conn.addr] = { 'mode': self.__DATACONN, 'ctrlchan': self.datachan[(conn.serverip, conn.serverport)] } + elif self.dump: + # No match. Track as a DATACONN with unknown CTRLCHAN as it may be + # a passive mode transfer that we don't have port info on yet. + self.conns[conn.addr] = { 'mode': self.__DATACONN, 'ctrlchan': None } + + def connectionCloseHandler(self, conn): + info = self.conns[conn.addr] + ######################################################### + # Upon close of data channels, store file content in + # 'filedata' associated with the ctrlchan. + # ctrlchan will then write it out to disk after it knows + # for sure the file name + # + if self.dump and info['mode'] == self.__DATACONN: + # Associated Control Channel + if info['ctrlchan'] == None: + if (conn.clientip, conn.clientport) in self.datachan: + info['ctrlchan'] = self.datachan[(conn.clientip, conn.clientport)] + if (conn.serverip, conn.serverport) in self.datachan: + info['ctrlchan'] = self.datachan[(conn.serverip, conn.serverport)] + ctrlchan = self.conns[info['ctrlchan']] + # Add data to control channel + ctrlchan['filedata'] = conn.data() + # Update BPF and DataChan Knowledge + if (conn.serverip, conn.serverport) == ctrlchan['datachan'] or (conn.clientip, conn.clientport) == ctrlchan['datachan']: + del self.datachan[ctrlchan['datachan']] + ctrlchan['datachan'] = None + self.__updatebpf() + # Remove Data Channel from tracker + del self.conns[conn.addr] + + elif info['mode'] == self.__CTRLCONN: + if 'file' not in info or info['file'] == None: + del self.conns[conn.addr] + + def postModule(self): + for x in self.conns: + info = self.conns[x] + if self.dump and 'filedata' in info and info['filedata']: + origname = info['file'][0] + '_' + os.path.join(*info['file'][1:3]) + outname = self.__localfilename(self.__OUTDIR, origname) + fh = open(outname, 'w') + fh.write(info['filedata']) + fh.close() + numbytes = len(info['filedata']) + info['filedata'] = None + info['outfile'] = outname + #info.update(conn.info()) + msg = 'User: %s, Pass: %s, %s File: %s (Incomplete: %d bytes written to %s)' % (info['user'], info['pass'], info['file'][0], os.path.join(*info['file'][1:3]), numbytes, os.path.basename(outname)) + self.alert(msg, **info) + + + + def blobHandler(self, conn, blob): + + info = self.conns[conn.addr] + data = blob.data() + + # + # Data Channel + # + if info['mode'] == self.__DATACONN: + return + + + # + # Control Channel + # + + # Client Commands + if blob.direction == 'cs': + + try: + if ' ' not in data: (command, param) = (data.rstrip(), '') + else: (command, param) = data.rstrip().split(' ', 1) + command = command.upper() + info['lastcommand'] = command + except: + return + + if command == 'USER': + info['user'] = param + elif command == 'PASS': + info['pass'] = param + elif command == 'CWD': + info['path'].append(param) + elif command == 'PASV' or command == 'EPSV': + if self.dump: + # Temporarily store the pair of IP addresses + # to open up the bpf filter until blobHandler processes + # the response with the full IP/Port information + # (Note: Due to the way blob processing works, we don't get this information + # until after the data channel is established) + info['tempippair'] = tuple(sorted((conn.clientip, conn.serverip))) + self.__updatebpf() + # + # For file transfers (including LIST), store tuple (Direction, Path, Filename) in info['file'] + # + elif command == 'LIST': + if param == '': + info['file'] = ( 'RETR', os.path.normpath(os.path.join(*info['path'])) if len(info['path']) else '', 'LIST' ) + else: + info['file'] = ( 'RETR', os.path.normpath(os.path.join(os.path.join(*info['path']), param)) if len(info['path']) else '', 'LIST' ) + elif command == 'RETR': + info['file'] = ( 'RETR', os.path.normpath(os.path.join(*info['path'])) if len(info['path']) else '', param ) + elif command == 'STOR': + info['file'] = ( 'STOR', os.path.normpath(os.path.join(*info['path'])) if len(info['path']) else '', param ) + + # Responses + else: + # + # Rollback directory change unless 2xx response + # + if info['lastcommand'] == 'CWD' and data[0] != '2': info['path'].pop() + # + # Write out files upon resonse to transfer commands + # + if info['lastcommand'] in ('LIST', 'RETR', 'STOR'): + if self.dump and info['filedata']: + origname = info['file'][0] + '_' + os.path.join(*info['file'][1:3]) + outname = self.__localfilename(self.__OUTDIR, origname) + fh = open(outname, 'w') + fh.write(info['filedata']) + fh.close() + numbytes = len(info['filedata']) + info['filedata'] = None + info['outfile'] = outname + info.update(conn.info()) + msg = 'User: %s, Pass: %s, %s File: %s (%d bytes written to %s)' % (info['user'], info['pass'], info['file'][0], os.path.join(*info['file'][1:3]), numbytes, os.path.basename(outname)) + else: + info.update(conn.info()) + msg = 'User: %s, Pass: %s, %s File: %s' % (info['user'], info['pass'], info['file'][0], os.path.join(*info['file'][1:3])) + if data[0] not in ('1','2'): msg += ' (%s)' % data.rstrip() + self.alert(msg, **info) + info['file'] = None + # + # Handle EPSV mode port setting + # + if info['lastcommand'] == 'EPSV' and data[0] == '2': + ret = re.findall('\(\|\|\|\d+\|\)', data) + if ret: + tport = int(ret[0].split('|')[3]) + info['datachan'] = (conn.serverip, tport) + if self.dump: + self.datachan[(conn.serverip, tport)] = conn.addr + info['tempippair'] = None + self.__updatebpf() + + # + # Look for ip/port information, assuming PSV response + # + ret = re.findall('\d+,\d+,\d+,\d+,\d+\,\d+', data) + if len(ret)==1: + tip, tport = self.calculateTransfer(ret[0]) # transfer ip, transfer port + info['datachan'] = (tip, tport) # Update this control channel's knowledge of currently working data channel + if self.dump: + self.datachan[(tip,tport)] = conn.addr # Update decoder's global datachan knowledge + info['tempippair'] = None + self.__updatebpf() + + + def calculateTransfer(self,val): + # calculate passive FTP data port + tmp = val.split(',') + ip = '.'.join(tmp[:4]) + port = int(tmp[4])*256 + int(tmp[5]) + return ip, port + + # + # Create output directory. Returns full path to output directory. + # + def __mkoutdir(self, outdir): + path = os.path.realpath(outdir) + if os.path.exists(path): return path + try: + os.mkdir(path) + return path + except OSError: + pass # most likely a permission denied issue, continue and try system temp directory + except: + raise # other errors, abort + if os.path.exists('/tmp'): path = os.path.realpath(os.path.join('/tmp', outdir)) + if os.path.exists(path): return path + try: + os.mkdir(path) + return path + except: + raise + + # + # Generate a local (extracted) filename based on the original + # + def __localfilename(self, path, origname): + tmp = origname.replace("\\", "_") + tmp = tmp.replace("/", "_") + tmp = tmp.replace(":", "_") + localname = '' + for c in tmp: + if ord(c) > 32 and ord(c) < 127: + localname += c + else: + localname += "%%%02X" % ord(c) + localname = path + '/' + localname + postfix = '' + i = 0 + while os.path.exists(localname+postfix): + i += 1 + postfix = "_%02d" % i + return localname+postfix + +if __name__=='__main__': + dObj = DshellDecoder() + print dObj +else: + dObj = DshellDecoder() From cfbee9aa65a9181ccafa33d67388b39605ddf20d Mon Sep 17 00:00:00 2001 From: dev195 Date: Mon, 23 Feb 2015 15:35:25 -0500 Subject: [PATCH 011/166] added --nobuf flag --- bin/decode.py | 4 ++++ lib/output/colorout.py | 8 ++++++++ lib/output/jsonout.py | 2 ++ lib/output/netflowout.py | 2 ++ lib/output/output.py | 7 +++++++ 5 files changed, 23 insertions(+) diff --git a/bin/decode.py b/bin/decode.py index 4ddc096..5df5ed0 100755 --- a/bin/decode.py +++ b/bin/decode.py @@ -480,6 +480,8 @@ def main(*largs, **kwargs): '\tpcap=PCAPFILE to write packets to a PCAP file\n' + '\tsession=SESSION to write session text\n' + '\tdirection=data direction to write (c,s,both,split)') + group.add_option('--nobuf', help='turn off output buffering', dest='nobuffer', + action='store_true', default=False) group.add_option('-w', '--session', dest='session', help='write session file, same as -o session=') group.add_option('-W', '--pcap', dest='pcap', default=None, @@ -566,6 +568,8 @@ def main(*largs, **kwargs): # set output file (and other args if -o filename,key=val...) if options.outfile: outfile, outkw = util.strtok(options.outfile) + if options.nobuffer: + outkw.update(nobuffer=True) # output extra? if options.oextra: outkw.update(extra=True) diff --git a/lib/output/colorout.py b/lib/output/colorout.py index ff7d336..f34faab 100644 --- a/lib/output/colorout.py +++ b/lib/output/colorout.py @@ -142,6 +142,8 @@ def _htmlwrite(self, text): self.htmlbuffer += text else: self.fh.write(text) + if self.nobuffer: + self.fh.flush() def htmldump(self): ''' @@ -241,6 +243,8 @@ def _write_string(self, text, direction, timestamp, encoding=None): elif self._COLORMODE == 'TTY' and self._timemode and timestamp != None: self.fh.write('\x1b[36m%s UTC:\x1b[0m\n' % datetime.datetime.utcfromtimestamp(timestamp)) + if self.nobuffer: + self.fh.flush() # Set Direction if direction.lower() == 'cs': @@ -275,6 +279,8 @@ def _write_string(self, text, direction, timestamp, encoding=None): self._write_tty(text, colorTag) else: self.fh.write(text) + if self.nobuffer: + self.fh.flush() # Plain Text else: @@ -308,6 +314,8 @@ def _write_tty(self, text, colorTag): self.fh.write(colorTag + _line[0] + '\x1b[0m') if len(_line) > 1: self.fh.write('\n') + if self.nobuffer: + self.fh.flush() def _HTMLHeader(self, title="Dshell"): diff --git a/lib/output/jsonout.py b/lib/output/jsonout.py index b8aa259..afed2b3 100644 --- a/lib/output/jsonout.py +++ b/lib/output/jsonout.py @@ -79,5 +79,7 @@ def alert(self, *args, **kw): del kw[name] self.fh.write( json.dumps(kw, ensure_ascii=self.options['ensure_ascii']) + "\n") + if self.nobuffer: + self.fh.flush() obj = JSONOutput diff --git a/lib/output/netflowout.py b/lib/output/netflowout.py index 311b710..0c943c4 100644 --- a/lib/output/netflowout.py +++ b/lib/output/netflowout.py @@ -80,5 +80,7 @@ def __alert(self, *args, **kw): kw['endtime'] - kw['starttime']) ) ) + if self.nobuffer: + self.fh.flush() obj = NetflowOutput diff --git a/lib/output/output.py b/lib/output/output.py index 791c2b7..9088765 100644 --- a/lib/output/output.py +++ b/lib/output/output.py @@ -42,6 +42,9 @@ def __init__(self, *a, **kw): self.timeformat = (kw.get('timeformat', self._DEFAULT_TIMEFORMAT)) self.delim = (kw.get('delim', self._DEFAULT_DELIM)) + # Run flush() after every relevant write() if this is true + self.nobuffer = (kw.get('nobuffer', False)) + if 'pcap' in kw: self.pcapwriter = PCAPWriter(kw['pcap']) else: @@ -241,6 +244,8 @@ def write(self, obj, **kw): self.sessionwriter.write(obj, **kw) elif self.fh: self.fh.write(str(obj)) + if self.nobuffer: + self.fh.flush() def close(self): '''close output if not stdout''' @@ -269,6 +274,8 @@ def alert(self, *args, **kw): rec = self.parse(*args, **kw) if rec: self.fh.write(self.format % rec) + if self.nobuffer: + self.fh.flush() class DBOutput(Output): From d94a1fe0f10ac56366258840a0d1425756cd8505 Mon Sep 17 00:00:00 2001 From: Travis Parker Date: Mon, 23 Feb 2015 16:11:14 -0500 Subject: [PATCH 012/166] DNSDecoder class now uses packetHandler to process UDP in realtime --- lib/dnsdecoder.py | 51 +++++++++++++++++++++++++++++++++++------------ 1 file changed, 38 insertions(+), 13 deletions(-) diff --git a/lib/dnsdecoder.py b/lib/dnsdecoder.py index 604b351..64a4c7c 100644 --- a/lib/dnsdecoder.py +++ b/lib/dnsdecoder.py @@ -29,35 +29,60 @@ def __init__(self, **kwargs): self.requests = {} self.maxblobs = None + def packetHandler(self,udp,data): + '''for each UDP packet , examine each segment (UDP packet) seperately as each will be a DNS Q/A + pair Q/A by ID and return as pairs''' + addr=udp.addr + if addr[0][1] < addr[1][1]: addr=addr[1],addr[0] #swap ports if source port is lower, to keep tuple (client,server) + connrqs = self.requests.setdefault(addr, {}) + try: + dns = dpkt.dns.DNS(data) + except Exception, e: + self._exc(e) + if dns.qr == dpkt.dns.DNS_Q: + connrqs[dns.id] = [udp.ts, dns, 0] + elif dns.qr == dpkt.dns.DNS_A: + rq = connrqs.get(dns.id, [None, None, 0]) + rq[2] += 1 + if "DNSHandler" in dir(self): + self.DNSHandler(conn=udp, request=rq[1], response=dns, requesttime=rq[0], + responsetime=udp.ts, responsecount=rq[2]) + def blobHandler(self, conn, blob): '''for each blob, examine each segment (UDP packet) seperately as each will be a DNS Q/A pair Q/A by ID and return as pairs''' connrqs = self.requests.setdefault(conn, {}) - # iterate blob as each packet will be a seperate request (catches - # spoofing) + # iterate blob as each packet will be a seperate request (catches spoofing) for data in blob: try: dns = dpkt.dns.DNS(data) except Exception, e: self._exc(e) + continue if dns.qr == dpkt.dns.DNS_Q: connrqs[dns.id] = [blob.starttime, dns, 0] elif dns.qr == dpkt.dns.DNS_A: rq = connrqs.get(dns.id, [None, None, 0]) rq[2] += 1 if "DNSHandler" in dir(self): - self.DNSHandler(conn=conn, request=rq[1], response=dns, requesttime=rq[ - 0], responsetime=blob.starttime, responsecount=rq[2]) + self.DNSHandler(conn=conn, request=rq[1], response=dns, requesttime=rq[0], + responsetime=blob.starttime, responsecount=rq[2]) - def connectionHandler(self, conn): + def connectionHandler(self,conn): '''clean up unanswered requests when we discard the connection''' - if self.noanswer and "DNSHandler" in dir(self) and self.requests.get(conn): - for requesttime, request, responsecount in self.requests[conn].values(): - if not responsecount: - self.DNSHandler(conn=conn, request=request, response=None, - requesttime=requesttime, responsetime=None, responsecount=responsecount) - if conn in self.requests: - del self.requests[conn] + if self.noanswer and "DNSHandler" in dir(self) and self.requests.get(conn): + for requesttime, request, responsecount in self.requests[conn].values(): + if not responsecount: + if type(conn) is tuple: conn=dshell.Packet(self,conn) #wrap UDP addresses + self.DNSHandler(conn=conn, request=request, response=None, + requesttime=requesttime, responsetime=None, responsecount=responsecount) + if conn in self.requests: + del self.requests[conn] + + def postModule(self): + '''flush out all remaining request state when module exits''' + for conn in self.requests.keys(): + self.connectionHandler(conn) class displaystub(dshell.Decoder): @@ -72,5 +97,5 @@ def __init__(self): if __name__ == '__main__': dObj = displaystub() print dObj -else: +else: # do we always want to print something here? Maybe only in debug mode?: dObj = displaystub() From 896ab900e1de404e58488ec1192d9600af0ff790 Mon Sep 17 00:00:00 2001 From: William Glodek Date: Wed, 18 Mar 2015 08:27:54 -0400 Subject: [PATCH 013/166] decoder to identify and extract tftp file transfers --- decoders/tftp/tftp.py | 290 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 290 insertions(+) create mode 100644 decoders/tftp/tftp.py diff --git a/decoders/tftp/tftp.py b/decoders/tftp/tftp.py new file mode 100644 index 0000000..f5a8c96 --- /dev/null +++ b/decoders/tftp/tftp.py @@ -0,0 +1,290 @@ +""" +TFTP Decoder +In short: + Goes through UDP traffic, packet by packet, and ties together TFTP file + streams. If the command line argument is set (--tftp_rip), it will dump the + files to a directory (--tftp_outdir=) + +In long: + Goes through each UDP packet and parses out the TFTP opcode. For read or + write requests, it sets a placeholder in unsetReadStreams or unsetWriteStreams, + respectively. These placeholders are moved to openStreams when we first see + data for the read request or an ACK code for a write request. The reason for + these placeholders is to allow the server to set the ephemeral port during + data transfer. + + When it sees a DATA packet, it stores the data under the IP-port-IP-port + openStream key as 'filedata'. Each of these data packets has an ordered block + number, and the file data is stored under that block number. It is reassembled + later. When we consider a stream finished (either the DATA packet is too short + or there are no more packets), we rebuild the file data, print information + about the stream, dump the file (optional), and move the information from + openStreams to closedStreams. + +Example: + Running on sample pcap available here: https://wiki.wireshark.org/TFTP + With default values, it will display transfers performed + Dshell> decode -d tftp ~/pcap/tftp_*.pcap + tftp 2013-05-01 08:24:11 192.168.0.253:50618 -- 192.168.0.10:3445 ** read rfc1350.txt (24599 bytes) ** + tftp 2013-04-27 05:07:59 192.168.0.1:57509 -- 192.168.0.13:2087 ** write rfc1350.txt (24599 bytes) ** + With the --tftp_rip flag, it will generate the same output while reassembling + the files and saving them in a defined directory (./tftp_out by default) + Dshell> decode -d tftp --tftp_rip --tftp_outdir=./MyTFTP ~/pcap/tftp_*.pcap + tftp 2013-05-01 08:24:11 192.168.0.253:50618 -- 192.168.0.10:3445 ** read rfc1350.txt (24599 bytes) ** + tftp 2013-04-27 05:07:59 192.168.0.1:57509 -- 192.168.0.13:2087 ** write rfc1350.txt (24599 bytes) ** + Dshell> ls ./MyTFTP/ + rfc1350.txt rfc1350.txt_01 + Note: The two files have the same name in the traffic, but have incremented + filenames when saved + +""" + +import dshell +import dpkt +import struct +import os + + +class DshellDecoder(dshell.IPDecoder): + "Primary decoder class" + # packet opcodes (http://www.networksorcery.com/enp/default1101.htm) + RRQ = 1 # read request + WRQ = 2 # write request + DATA = 3 + ACK = 4 + ERROR = 5 + OACK = 6 # option acknowledgment + + def __init__(self, **kwargs): + dshell.IPDecoder.__init__(self, + name="tftp", + filter="udp", + description="Find TFTP streams and, optionally, extract the files", + longdescription="Find TFTP streams and, optionally, extract the files", + author="dev195", + optiondict={ + "rip": {"action": "store_true", "help": "Rip files from traffic (default: off)", "default": False}, + "outdir": {"help": "Directory to place files when using --rip", "default": "./tftp_out", "metavar": "DIRECTORY"}} + ) + + # default information for streams we didn't see the start for + self.defaultStream = { + 'filename': '', + 'mode': '', + 'readwrite': '', + 'closed_connection': False, + 'filedata': {}, + 'timestamp': 0 + } + + # containers for various states of streams + self.openStreams = {} + self.closedStreams = [] + # These two are holders while waiting for the server to decide on which + # ephemeral port to use + self.unsetWriteStreams = {} + self.unsetReadStreams = {} + + def preModule(self): + "if needed, create the directory for file output" + if self.rip and not os.path.exists(self.outdir): + try: + os.makedirs(self.outdir) + except OSError: + self.error( + "Could not create directory '%s'. Files will not be dumped." % self.outdir) + self.rip = False + + def postModule(self): + "cleanup any unfinished streams" + self.debug("Unset Read Streams: %s" % self.unsetReadStreams) + self.debug("Unset Write Streams: %s" % self.unsetWriteStreams) + while(len(self.openStreams) > 0): + k = self.openStreams.keys()[0] + self.__closeStream(k, "POSSIBLY INCOMPLETE") + + def packetHandler(self, ip=None): + """ + Handles each UDP packet. It checks the TFTP opcode and parses + accordingly. + """ + try: + udp = dpkt.ip.IP(ip.pkt).data + except dpkt.UnpackError: + return + data = udp.data + try: + flag = struct.unpack("!H", data[:2])[0] + except struct.error: + return # awful small packet + data = data[2:] + if flag == self.RRQ: + # this packet is requesting to read a file from the server + try: + filename, mode = data.split("\x00")[0:2] + except ValueError: + return # probably not TFTP + clientIP, clientPort, serverIP, serverPort = ip.sip, udp.sport, ip.dip, udp.dport + self.unsetReadStreams[(clientIP, clientPort, serverIP)] = { + 'filename': filename, + 'mode': mode, + 'readwrite': 'read', + 'closed_connection': False, + 'filedata': {}, + 'timestamp': ip.ts + } + + elif flag == self.WRQ: + # this packet is requesting to write a file to the server + try: + filename, mode = data.split("\x00")[0:2] + except ValueError: + return # probably not TFTP + # in this case, we are writing to the "server" + clientIP, clientPort, serverIP, serverPort = ip.sip, udp.sport, ip.dip, udp.dport + self.unsetWriteStreams[(clientIP, clientPort, serverIP)] = { + 'filename': filename, + 'mode': mode, + 'readwrite': 'write', + 'closed_connection': False, + 'filedata': {}, + 'timestamp': ip.ts + } + + elif flag == self.DATA: + # this packet is sending a chunk of data + clientIP, clientPort, serverIP, serverPort = ip.sip, udp.sport, ip.dip, udp.dport + key = (clientIP, clientPort, serverIP, serverPort) + if key not in self.openStreams: + # this is probably an unset read stream; there is no + # acknowledgement, it just starts sending data + if (serverIP, serverPort, clientIP) in self.unsetReadStreams: + self.openStreams[key] = self.unsetReadStreams[ + (serverIP, serverPort, clientIP)] + del(self.unsetReadStreams[ + (serverIP, serverPort, clientIP)]) + else: + self.openStreams[key] = self.defaultStream + blockNum = struct.unpack("!H", data[:2])[0] + data = data[2:] + if len(data) < 512: + # TFTP uses fixed length data chunks. If it's smaller than the + # length, then the stream is finished + closedConn = True + else: + closedConn = False + self.openStreams[key]['filedata'][blockNum] = data + self.openStreams[key]['closed_connection'] = closedConn + + elif flag == self.ACK: + # this packet has acknowledged the receipt of a data chunk or + # allows a write process to begin + blockNum = struct.unpack("!H", data[:2])[0] + clientIP, clientPort, serverIP, serverPort = ip.sip, udp.sport, ip.dip, udp.dport + + # special case: this is acknowledging a write operation and sets + # the port for receiving + if blockNum == 0: + clientIP, clientPort, serverIP, serverPort = ip.dip, udp.dport, ip.sip, udp.sport + i = (clientIP, clientPort, serverIP) + if i in self.unsetWriteStreams: + self.openStreams[ + (clientIP, clientPort, serverIP, serverPort)] = self.unsetWriteStreams[i] + del(self.unsetWriteStreams[i]) + # otherwise, check if this is the confirmation for the end of a + # connection + elif (clientIP, clientPort, serverIP, serverPort) in self.openStreams and self.openStreams[(clientIP, clientPort, serverIP, serverPort)]['closed_connection']: + self.__closeStream( + (clientIP, clientPort, serverIP, serverPort)) + elif (serverIP, serverPort, clientIP, clientPort) in self.openStreams and self.openStreams[(serverIP, serverPort, clientIP, clientPort)]['closed_connection']: + self.__closeStream( + (serverIP, serverPort, clientIP, clientPort)) + + elif flag == self.ERROR: + # this package is sending an error message + # TODO handle more of these properly + errCode = struct.unpack("!H", data[:2])[0] + errMessage = data[2:].strip() + if errCode == 1: # File not found + clientIP, clientPort, serverIP, serverPort = ip.dip, udp.dport, ip.sip, udp.sport + i = (clientIP, clientPort, serverIP) + if i in self.unsetReadStreams: + self.openStreams[ + (serverIP, serverPort, clientIP, clientPort)] = self.unsetReadStreams[i] + del(self.unsetReadStreams[i]) + self.__closeStream( + (serverIP, serverPort, clientIP, clientPort), errMessage) + + elif flag == self.OACK: + pass # TODO handle options + + def __closeStream(self, key, message=''): + """ + Called when a stream is finished. It moves the stream from + openStreams to closedStreams, prints output, and dumps the file + """ + theStream = self.openStreams[key] + if not theStream['filename']: + message = "INCOMPLETE -- missing filename" + + # Rebuild the file from the individual blocks + rebuiltFile = '' + for i in sorted(theStream['filedata'].keys()): + rebuiltFile += theStream['filedata'][i] + + # if we're reading, swap the client and server IP so the output better + # shows who requested the connection + if theStream['readwrite'] == 'read': + ipsNports = (key[2], key[3], key[0], key[1]) + else: + ipsNports = key + + # print out information about the stream + msg = "%s %s (%s bytes) %s" % ( + theStream['readwrite'], theStream['filename'], len(rebuiltFile), message) + self.alert(msg, ts=theStream['timestamp'], sip=ipsNports[0], + sport=ipsNports[1], dip=ipsNports[2], dport=ipsNports[3]) + + # dump the file, if that's what the user wants + if self.rip and len(rebuiltFile) > 0: + outpath = self.__localfilename( + self.outdir, theStream['filename']) + outfile = open(outpath, 'wb') + outfile.write(rebuiltFile) + outfile.close() + + # remove the stream from the list of open streams + self.closedStreams.append(( + key, + self.openStreams[key]['closed_connection'] + )) + del(self.openStreams[key]) + + def __localfilename(self, path, origname): + """ + Generates a local file name based on the original + Taken from FTP decoder + """ + tmp = origname.replace("\\", "_") + tmp = tmp.replace("/", "_") + tmp = tmp.replace(":", "_") + localname = '' + for c in tmp: + if ord(c) > 32 and ord(c) < 127: + localname += c + else: + localname += "%%%02X" % ord(c) + localname = path + '/' + localname + postfix = '' + i = 0 + while os.path.exists(localname + postfix): + i += 1 + postfix = "_%02d" % i + return localname + postfix + + +if __name__ == '__main__': + dObj = DshellDecoder() + print dObj +else: + dObj = DshellDecoder() From cc15c85835a76bdf908b43912cf2a22220304820 Mon Sep 17 00:00:00 2001 From: William Glodek Date: Wed, 15 Apr 2015 13:59:59 -0400 Subject: [PATCH 014/166] proof-of-concept detector for MS15-034 / CVE-2105-1635 --- decoders/http/ms15-034.py | 74 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 decoders/http/ms15-034.py diff --git a/decoders/http/ms15-034.py b/decoders/http/ms15-034.py new file mode 100644 index 0000000..f5bfed1 --- /dev/null +++ b/decoders/http/ms15-034.py @@ -0,0 +1,74 @@ +import dshell +import util +from httpdecoder import HTTPDecoder + +class DshellDecoder(HTTPDecoder): + ''' + 15 April 2015 + + Proof-of-concept code to detect attempts to enumerate MS15-034 vulnerable + IIS servers and/or cause a denial of service. Each event will generate an + alert that prints out the HTTP Request method and the range value contained + with the HTTP stream. + + Usage: + decode -d ms15-034 -q *.pcap + decode -d ms15-034 -i -q + + References: + https://technet.microsoft.com/library/security/ms15-034 + https://ma.ttias.be/remote-code-execution-via-http-request-in-iis-on-windows/ + ''' + def __init__(self): + HTTPDecoder.__init__(self, + name='ms15-034', + description='detect attempts to enumerate MS15-034 vulnerable IIS servers', + longdescription=''' +Proof-of-concept code to detect attempts to enumerate MS15-034 vulnerable +IIS servers and/or cause a denial of service. Each event will generate an +alert that prints out the HTTP Request method and the range value contained +with the HTTP stream. + +Usage: +decode -d ms15-034 -q *.pcap +decode -d ms15-034 -i -q +''', + filter='tcp and (port 80 or port 8080 or port 8000)', + filterfn=lambda ((sip, sp), (dip, dp)): sp in ( + 80, 8000, 8080) or dp in (80, 8000, 8080), + author='bg', + ) + + def HTTPHandler(self, conn, request, response, requesttime, responsetime): + if response == None: # Denial of Service (no server response) + try: + rangestr = util.getHeader(request,'range') + # check range value to reduce false positive rate + if not rangestr.endswith('18446744073709551615'): return + except: return + self.alert('MS15-034 DoS [Request Method: "%s" URI: "%s" Range: "%s"]' % \ + (request.method, request.uri, rangestr), conn.info()) + + else: # probing for vulnerable server + try: + rangestr = util.getHeader(request,'range') + # check range value to reduce false positive rate + if not rangestr.endswith('18446744073709551615'): return + except: return + + # indication of vulnerable server + if rangestr and (response.status == '416' or \ + response.reason == 'Requested Range Not Satisfiable'): + + self.alert('MS15-034 Vulnerable Server [Request Method: "%s" Range: "%s"]' % + (request.method,rangestr), conn.info()) + + if request.method != 'GET': # this could be interesting + pass # waiting on more details + + +if __name__ == '__main__': + dObj = DshellDecoder() + print dObj +else: + dObj = DshellDecoder() From 5e543bcc82ed1c47239aae9d247b770eefea75c5 Mon Sep 17 00:00:00 2001 From: William Glodek Date: Fri, 17 Apr 2015 09:15:35 -0400 Subject: [PATCH 015/166] adding capability to analyze and rip files from SMB traffic --- decoders/smb/psexec.py | 247 ++++++++++++++++++ decoders/smb/rip-smb-uploads.py | 126 ++++++++++ decoders/smb/smbfiles.py | 210 ++++++++++++++++ lib/smbdecoder.py | 429 ++++++++++++++++++++++++++++++++ 4 files changed, 1012 insertions(+) create mode 100644 decoders/smb/psexec.py create mode 100644 decoders/smb/rip-smb-uploads.py create mode 100644 decoders/smb/smbfiles.py create mode 100644 lib/smbdecoder.py diff --git a/decoders/smb/psexec.py b/decoders/smb/psexec.py new file mode 100644 index 0000000..d9a3762 --- /dev/null +++ b/decoders/smb/psexec.py @@ -0,0 +1,247 @@ +""" +2015 Feb 13 + +Processes SMB traffic and attempts to extract command/response information +from psexec. + +When a successful SMB connection is seen and it matches a psexec regular +expression, it creates a new "psexec" object to store connection information +and messages. + +Once the connection closes, an alert is generated (of configurable verbosity) +relaying basic information and messages passed. +""" + +#import dshell +from smbdecoder import SMBDecoder +import colorout +import util +import re +import datetime + +SMB_STATUS_SUCCESS = 0x0 +SMB_COM_OPEN = 0x02 # Open a file. +SMB_COM_CLOSE = 0x04 # Close a file. +SMB_COM_NT_CREATE_ANDX = 0xa2 # Create or open a file or a directory. +SMB_COM_WRITE_ANDX = 0x2f # Extended file write with AndX chaining. +SMB_COM_READ_ANDX = 0x2E +SMB_COM_SESSION_SETUP_ANDX = 0x73 + + +class DshellDecoder(SMBDecoder): + + def __init__(self): + # dictionary indexed by uid, points to login domain\name (string) + self.uidname = {} + self.fidhandles = {} # dictionary to map fid handles to psexec objects + # dictionary of psexec objects, indexed by conn+PID (use sessIndex + # function) + self.psexecobjs = {} + # FID won't work as an index because each stream has its own + SMBDecoder.__init__(self, + name='psexec', + description='Extract command/response information from psexec over smb', + filter='tcp and (port 445 or port 139)', + filterfn=lambda t: t[0][1] == 445 or t[1][1] == 445 or t[0][1] == 139 or t[1][1] == 139, + author='amm', + optiondict={ + 'alertsonly': {'action': 'store_true', 'help': 'only dump alerts, not content'}, + 'htmlalert': {'action': 'store_true', 'help': 'include html as named value in alerts'}, + 'time': {'action': 'store_true', 'help': 'display command/response timestamps'} + } + ) + self.legacy = True + # self.out=colorout.ColorOutput(title='psexec') + self.output = 'colorout' + + def sessIndexFromPID(self, conn, pid): + return ':'.join((str(conn.starttime), conn.sip, str(conn.sport), conn.dip, str(conn.dport), pid)) + + def connectionHandler(self, conn): + SMBDecoder.connectionHandler(self, conn) + for k in self.psexecobjs.keys(): + del self.psexecobjs[k] + + # + # Internal class to contain psexec session information + # + class psexec: + + def __init__(self, parent, conn, hostname, pid, opentime): + self.parent = parent + self.conn = conn + self.hostname = hostname + self.pid = pid + self.opentime = opentime + self.closetime = conn.endtime + self.username = '' + self.open_iohandles = {} # indexed by FID, points to filename + self.closed_iohandles = {} + self.msgList = [] # List of tuples (text, direction) + self.csCount = 0 + self.scCount = 0 + self.csBytes = 0 + self.scBytes = 0 + self.lastDirection = '' + + def addmsg(self, text, direction, ts): + # Only store timestamp information if this is a change in direction + if direction == self.lastDirection: + self.msgList.append((text, direction, None)) + else: + self.msgList.append((text, direction, ts)) + self.lastDirection = direction + if direction == 'cs': + self.csCount += 1 + self.csBytes += len(text) + elif direction == 'sc': + self.scCount += 1 + self.scBytes += len(text) + + def addIO(self, fid, name): + if fid in self.open_iohandles: + self.parent.warn("IO Handle with FID %s (%s) is already associated with psexec session %d" % ( + hex(fid), name, self.pid)) + self.open_iohandles[fid] = name + + def delIO(self, fid): + if fid in self.open_iohandles: + self.closed_iohandles[fid] = self.open_iohandles[fid] + del self.open_iohandles[fid] + + def handleCount(self): + return len(self.open_iohandles) + # + # Long output (screen/html) + # + + def write(self, out=None): + if out == None: + out = self.parent.out + out.write("PSEXEC Service from host %s with PID %s\n" % + (self.hostname, self.pid), formatTag='H1') + if len(self.username): + out.write("User: %s\n" % (self.username), formatTag='H2') + out.write("Start: %s UTC\n End: %s UTC\n" % (datetime.datetime.utcfromtimestamp( + self.conn.starttime), datetime.datetime.utcfromtimestamp(self.conn.endtime)), formatTag='H2') + out.write("%s:%s -> %s:%s\n" % (self.conn.clientip, self.conn.clientport, + self.conn.serverip, self.conn.serverport), formatTag="H2", direction="cs") + out.write("%s:%s -> %s:%s\n\n" % (self.conn.serverip, self.conn.serverport, + self.conn.clientip, self.conn.clientport), formatTag="H2", direction="sc") + for msg in self.msgList: + out.write( + msg[0], direction=msg[1], timestamp=msg[2], time=self.parent.time) + out.write("\n") + # + # Short output (alert) + # + + def alert(self): + kwargs = {'hostname': self.hostname, 'pid': self.pid, 'username': self.username, + 'opentime': self.opentime, 'closetime': self.closetime, + 'csCount': self.csCount, 'scCount': self.scCount, 'csBytes': self.csBytes, 'scBytes': self.scBytes} + if self.parent.htmlalert: + htmlfactory = colorout.ColorOutput( + htmlgenerator=True, title="psexec") + self.write(htmlfactory) + htmlfactory.close() + kwargs['html'] = htmlfactory.htmldump() + kwargs.update(self.conn.info()) + kwargs['ts'] = self.opentime + self.parent.alert( + "Host: %s, PID: %s, CS: %d, SC: %d, User: %s" % ( + self.hostname, self.pid, self.csBytes, self.scBytes, self.username), + kwargs + ) + + def __del__(self): + if self.parent.alertsonly: + self.alert() + else: + self.write() + + def SMBHandler(self, conn, request=None, response=None, requesttime=None, responsetime=None, cmd=None, status=None): + # we only care about valid responses and matching request/response user + # IDs + if status == SMB_STATUS_SUCCESS and request.uid == response.uid: + + if cmd == SMB_COM_SESSION_SETUP_ANDX and type(status) != type(None): + auth_record = request.PARSE_SESSION_SETUP_ANDX_REQUEST( + request.smbdata) + if not(auth_record): + return + domain_name = auth_record.domain_name + user_name = auth_record.user_name + self.uidname[response.uid] = "%s\\%s" % ( + domain_name, user_name) + + # file is being requested/opened + elif cmd == SMB_COM_NT_CREATE_ANDX: + self.debug('%s UID: %s MID: %s NT Create AndX Status: %s' % ( + conn.addr, request.uid, response.mid, hex(status))) + filename = request.PARSE_NT_CREATE_ANDX_REQUEST( + request.smbdata) + if type(filename) == type(None): + self.debug('Error: smb.SMB.PARSE_NT_CREATE_ANDX_REQUEST\n%s' % util.hexPlusAscii( + request.smbdata)) + return + + fid = response.PARSE_NT_CREATE_ANDX_RESPONSE(response.smbdata) + + if fid == -1: + self.debug('Error: smb.SMB.PARSE_NT_CREATE_ANDX_RESPONSE\n%s' % util.hexPlusAscii( + response.smbdata)) + self.debug(util.hexPlusAscii(response.smbdata)) + return + match = re.search( + r'psexecsvc-(.*)-(\d+)-(stdin|stdout|stderr)', filename) + if not match: + return + + # We have a PSEXEC File Handle! + hostname = match.group(1) + pid = match.group(2) + iohandleName = match.group(3) + sessionIndex = self.sessIndexFromPID(conn, pid) + if not sessionIndex in self.psexecobjs: + self.psexecobjs[sessionIndex] = self.psexec( + self, conn, hostname, pid, requesttime) + self.fidhandles[fid] = self.psexecobjs[sessionIndex] + self.fidhandles[fid].addIO(fid, filename) + if response.uid in self.uidname: + self.fidhandles[fid].username = self.uidname[response.uid] + + elif cmd == SMB_COM_WRITE_ANDX: # write data to the file + fid, rawbytes = request.PARSE_WRITE_ANDX(request.smbdata) + self.debug('COM_WRITE_ANDX\n%s' % + (util.hexPlusAscii(request.smbdata))) + if fid in self.fidhandles: + self.fidhandles[fid].addmsg(rawbytes, 'cs', requesttime) + + elif cmd == SMB_COM_READ_ANDX: # write data to the file + fid = request.PARSE_READ_ANDX_Request(request.smbdata) + rawbytes = response.PARSE_READ_ANDX_Response(response.smbdata) + self.debug('COM_READ_ANDX (FID %s)\n%s' % + (fid, util.hexPlusAscii(response.smbdata))) + if fid in self.fidhandles: + self.fidhandles[fid].addmsg(rawbytes, 'sc', responsetime) + + elif cmd == SMB_COM_CLOSE: # file is being closed + fid = request.PARSE_COM_CLOSE(request.smbdata) + if fid in self.fidhandles.keys(): + self.fidhandles[fid].delIO(fid) + self.debug('Closing FID: %s Filename: %s' % + (hex(fid), self.fidhandles[fid])) + if self.fidhandles[fid].handleCount() < 1 and self.sessIndexFromPID(conn, self.fidhandles[fid].pid) in self.psexecobjs: + self.psexecobjs[ + self.sessIndexFromPID(conn, self.fidhandles[fid].pid)].closetime = responsetime + del self.psexecobjs[ + self.sessIndexFromPID(conn, self.fidhandles[fid].pid)] + del self.fidhandles[fid] + + +if __name__ == '__main__': + dObj = DshellDecoder() + print dObj +else: + dObj = DshellDecoder() diff --git a/decoders/smb/rip-smb-uploads.py b/decoders/smb/rip-smb-uploads.py new file mode 100644 index 0000000..5abe9e6 --- /dev/null +++ b/decoders/smb/rip-smb-uploads.py @@ -0,0 +1,126 @@ +""" +2015 Feb 13 + +Goes through SMB traffic and snips out any file uploads it sees. + +Specifically, it looks for create, write, and close commands and creates a +local file, writes the raw data to the local file, and closes the file, +respectively. +""" + +import dshell +from smbdecoder import SMBDecoder +import sys +import util +import os + +SMB_STATUS_SUCCESS = 0x0 +SMB_COM_OPEN = 0x02 # Open a file. +SMB_COM_CLOSE = 0x04 # Close a file. +SMB_COM_NT_CREATE_ANDX = 0xa2 # Create or open a file or a directory. +SMB_COM_WRITE_ANDX = 0x2f # Extended file write with AndX chaining. + + +class DshellDecoder(SMBDecoder): + + def __init__(self): + self.fidhandles = {} # dictionary to map fid handles to filenames + # dictionary to map fid handles to local filedescriptors + # (ie. fd = open(fname,'wb')) + self.fds = {} + self.outdir = None + SMBDecoder.__init__(self, + name='rip-smb-uploads', + description='Extract files uploaded via SMB', + filter='tcp and port 445', + filterfn=lambda t: t[0][1] == 445 or t[1][1] == 445, + author='bg', + optiondict={ + "outdir": {"help": "Directory to place files (default: ./smb_out)", "default": "./smb_out", "metavar": "DIRECTORY"}, + } + ) + self.legacy = True + + def preModule(self): + if not os.path.exists(self.outdir): + try: + os.makedirs(self.outdir) + except OSError as e: + self.error("Could not create directory '%s'\n%s" % (self.outdir, e)) + sys.exit(1) + + def SMBHandler(self, conn, request=None, response=None, requesttime=None, responsetime=None, cmd=None, status=None): + # we only care about valid responses and matching request/response user + # IDs + if status == SMB_STATUS_SUCCESS and request.uid == response.uid: + + if cmd == SMB_COM_NT_CREATE_ANDX: # file is being requested/opened + self.debug('%s UID: %s MID: %s NT Create AndX Status: %s' % ( + conn.addr, request.uid, response.mid, hex(status))) + filename = request.PARSE_NT_CREATE_ANDX_REQUEST( + request.smbdata) + if type(filename) == type(None): + self.debug('Error: smb.SMB.PARSE_NT_CREATE_ANDX_REQUEST\n%s' % util.hexPlusAscii(request.smbdata)) + return + + fid = response.PARSE_NT_CREATE_ANDX_RESPONSE(response.smbdata) + self.debug('%s FID: %s' % (conn.addr, fid)) + + if fid == -1: + self.debug('Error: smb.SMB.PARSE_NT_CREATE_ANDX_RESPONSE\n%s' % util.hexPlusAscii(response.smbdata)) + self.debug(util.hexPlusAscii(response.smbdata)) + return + self.fidhandles[fid] = self.__localfilename(self.outdir, os.path.normpath(filename)) + + elif cmd == SMB_COM_WRITE_ANDX: # write data to the file + fid, rawbytes = request.PARSE_WRITE_ANDX(request.smbdata) + + # do we have a local fd already open to handle this write? + if fid in self.fds.keys(): + self.fds[fid].write(rawbytes) + else: + try: + fidhandle = self.fidhandles[fid] + self.fds[fid] = open(fidhandle, 'wb') + self.fds[fid].write(rawbytes) + except KeyError: + self.debug("Error: Could not find fidhandle for FID %s" % (fid)) + return + + elif cmd == SMB_COM_CLOSE: # file is being closed + fid = request.PARSE_COM_CLOSE(request.smbdata) + if fid in self.fds.keys(): + self.log(repr(conn) + '\t%s' % (self.fidhandles[fid])) + self.fds[fid].close() + del self.fds[fid] + if fid in self.fidhandles.keys(): + self.debug('Closing FID: %s Filename: %s' % + (hex(fid), self.fidhandles[fid])) + del self.fidhandles[fid] + + + def __localfilename(self, path, origname): + # Generates a local file name based on the original + tmp = origname.replace("\\", "_") + tmp = tmp.replace("/", "_") + tmp = tmp.replace(":", "_") + localname = '' + for c in tmp: + if ord(c) > 32 and ord(c) < 127: + localname += c + else: + localname += "%%%02X" % ord(c) + localname = os.path.join(path, localname) + postfix = '' + i = 0 + while os.path.exists(localname + postfix): + i += 1 + postfix = "_%02d" % i + return localname + postfix + + +if __name__ == '__main__': + dObj = DshellDecoder() + print dObj +else: + dObj = DshellDecoder() diff --git a/decoders/smb/smbfiles.py b/decoders/smb/smbfiles.py new file mode 100644 index 0000000..6b87ad1 --- /dev/null +++ b/decoders/smb/smbfiles.py @@ -0,0 +1,210 @@ +""" +2015 Feb 13 + +Processes SMB traffic and tries to find file reads and writes. + +When a read or write action is seen, the size of the transfer is recorded in +a new "smbfile" object and a count is incremented for the type of action taken +(i.e. reads+1 or writes+1). + +After the connection closes, an alert is generated showing some information +about the connection, the action taken (read, write, or both), the full name +of the file and how much data was transferred. +""" + +from smbdecoder import SMBDecoder +import util + +SMB_STATUS_SUCCESS = 0x0 +SMB_COM_OPEN = 0x02 # Open a file. +SMB_COM_CLOSE = 0x04 # Close a file. +SMB_COM_NT_CREATE_ANDX = 0xa2 # Create or open a file or a directory. +SMB_COM_WRITE_ANDX = 0x2f # Extended file write with AndX chaining. +SMB_COM_READ_ANDX = 0x2E +SMB_COM_SESSION_SETUP_ANDX = 0x73 +SMB_COM_TREE_CONNECT_ANDX = 0x75 + + +class DshellDecoder(SMBDecoder): + + def __init__(self): + # dictionary indexed by uid, points to login tuple (hostname, + # domain\name) (string) + self.uidname = {} + self.tidmap = {} # dictionary indexed by tid, points to tree path + # dictionary of smb file objects, indexed by conn+fid (use + # sessIndexFromFID function) + self.smbfileobjs = {} + SMBDecoder.__init__(self, + name='smbfiles', + description='List files accessed via smb', + filter='tcp and (port 445 or port 139)', + filterfn=lambda t: t[0][1] == 445 or t[1][1] == 445 or t[0][1] == 139 or t[1][1] == 139, + author='amm', + optiondict={ + 'nopsexec': {'action': 'store_true', 'help': 'supress psexecsvc streams from output'}, + 'activeonly': {'action': 'store_true', 'help': 'only output files with reads or writes'} + } + ) + + def fileIndexFromFID(self, conn, fid): + return ':'.join((str(conn.starttime), conn.sip, str(conn.sport), conn.dip, str(conn.dport), str(fid))) + + def connectionHandler(self, conn): + SMBDecoder.connectionHandler(self, conn) + for k in self.smbfileobjs.keys(): + del self.smbfileobjs[k] + + # + # Internal class to contain info about files + # + class smbfile: + + def __init__(self, parent, conn, fid, opentime, filename, username, hostname, treepath): + self.parent = parent + self.conn = conn + self.opentime = opentime + self.closetime = conn.endtime + self.filename = filename + self.username = username + self.hostname = hostname + self.treepath = treepath + self.writes = 0 + self.reads = 0 + self.byteswritten = 0 + self.bytesread = 0 + + def writeblock(self, data): + self.writes += 1 + self.byteswritten += len(data) + + def readblock(self, data): + self.reads += 1 + self.bytesread += len(data) + + def alert(self): + if self.parent.nopsexec and self.filename.lower().startswith('\psexecsvc'): + return + if self.reads > 0 and self.writes > 0: + mode = 'B' + elif self.reads > 0: + mode = 'R' + elif self.writes > 0: + mode = 'W' + else: + mode = '-' + if self.parent.activeonly and mode == '-': + return + kwargs = { + 'filename': self.filename, 'username': self.username, 'hostname': self.hostname, 'treepath': self.treepath, + 'opentime': self.opentime, 'closetime': self.closetime, 'mode': mode, + 'writes': self.writes, 'reads': self.reads, 'byteswritten': self.byteswritten, 'bytesread': self.bytesread + } + kwargs.update(self.conn.info()) + kwargs['ts'] = self.opentime + self.parent.alert( + "%s %s%s (%s)" % ( + self.username, self.treepath, self.filename, mode), + kwargs + ) + + def __del__(self): + self.alert() + + def SMBHandler(self, conn, request=None, response=None, requesttime=None, responsetime=None, cmd=None, status=None): + # we only care about valid responses and matching request/response user + # IDs + if status == SMB_STATUS_SUCCESS and request.uid == response.uid: + + # + # SMB_COM_SESSION_SETUP - Start tracking user authentication by UID + # + if cmd == SMB_COM_SESSION_SETUP_ANDX and type(status) != type(None): + auth_record = request.PARSE_SESSION_SETUP_ANDX_REQUEST( + request.smbdata) + if not(auth_record): + return + domain_name = auth_record.domain_name + user_name = auth_record.user_name + host_name = auth_record.host_name + self.uidname[response.uid] = ( + host_name, "%s\%s" % (domain_name, user_name)) + + # + # SMB_COM_TREE_CONNECT - Start tracking tree by TID + # + if cmd == SMB_COM_TREE_CONNECT_ANDX: + request_path = unicode(request.SMB_COM_TREE_CONNECT_ANDX_Request( + request.smbdata), 'utf-16').encode('utf-8').rstrip('\0') + self.tidmap[response.tid] = request_path + + # + # SMB_COM_NT_CREATE - Start tracking file handle by FID + # + # file is being requested/opened + elif cmd == SMB_COM_NT_CREATE_ANDX: + self.debug('%s UID: %s MID: %s NT Create AndX Status: %s' % ( + conn.addr, request.uid, response.mid, hex(status))) + filename = request.PARSE_NT_CREATE_ANDX_REQUEST( + request.smbdata) + if type(filename) == type(None): + self.debug('Error: smb.SMB.PARSE_NT_CREATE_ANDX_REQUEST\n%s' % util.hexPlusAscii( + request.smbdata)) + return + fid = response.PARSE_NT_CREATE_ANDX_RESPONSE(response.smbdata) + if fid == -1: + self.debug('Error: smb.SMB.PARSE_NT_CREATE_ANDX_RESPONSE\n%s' % util.hexPlusAscii( + response.smbdata)) + self.debug(util.hexPlusAscii(response.smbdata)) + return + # Setup smbfile object + if response.uid in self.uidname: + hostname, username = self.uidname[response.uid] + else: + hostname = 'Unknown' + username = 'Unknown\\Unknown' + if response.tid in self.tidmap: + treepath = self.tidmap[response.tid] + else: + treepath = '' + fileobj = self.smbfile( + self, conn, fid, requesttime, filename, username, hostname, treepath) + fileIndex = self.fileIndexFromFID(conn, fid) + self.smbfileobjs[fileIndex] = fileobj + + # + # SMB_COM_WRITE - File writes + # + elif cmd == SMB_COM_WRITE_ANDX: # write data to the file + fid, rawbytes = request.PARSE_WRITE_ANDX(request.smbdata) + #self.debug('COM_WRITE_ANDX\n%s' % (util.hexPlusAscii(request.smbdata))) + fileIndex = self.fileIndexFromFID(conn, fid) + if fileIndex in self.smbfileobjs: + self.smbfileobjs[fileIndex].writeblock(rawbytes) + + # + # SMB_COM_READ - File reads + # + elif cmd == SMB_COM_READ_ANDX: # read data from the file + fid = request.PARSE_READ_ANDX_Request(request.smbdata) + rawbytes = response.PARSE_READ_ANDX_Response(response.smbdata) + #self.debug('COM_READ_ANDX (FID %s)\n%s' % (fid, util.hexPlusAscii(response.smbdata))) + fileIndex = self.fileIndexFromFID(conn, fid) + if fileIndex in self.smbfileobjs: + self.smbfileobjs[fileIndex].readblock(rawbytes) + + # + # SMB_COM_CLOSE - Closing file + # + elif cmd == SMB_COM_CLOSE: # file is being closed + fid = request.PARSE_COM_CLOSE(request.smbdata) + fileIndex = self.fileIndexFromFID(conn, fid) + if fileIndex in self.smbfileobjs: + self.smbfileobjs[fileIndex].closetime = responsetime + del self.smbfileobjs[fileIndex] + +if __name__ == '__main__': + dObj = DshellDecoder() + print dObj +else: + dObj = DshellDecoder() diff --git a/lib/smbdecoder.py b/lib/smbdecoder.py new file mode 100644 index 0000000..3266e99 --- /dev/null +++ b/lib/smbdecoder.py @@ -0,0 +1,429 @@ +''' +2015 Feb 13 + +Extend dshell.TCPDecoder to handle SMB Message Requests/Responses + +Will call SMBHandler( + conn = Connection(), + request=dshell.smb.smbdecoder.SMB(), + response=dshell.smb.smbdecoder.SMB(), + requesttime=timestamp, + responsetime=timestamp, + cmd= [3] + status= [2] A 32-bit field used to communicate error + messages from the server to the client + ) + +Requests are tracked by MID + +It will be up to the decoder to handle each SMB Command. + +Several functions create throw-away variables when unpacking data. Because of +this, pylint checks were run with "-d unused-variables" + +References: +[1] http://anonsvn.wireshark.org/viewvc/trunk/epan/dissectors/packet-smb.c?revision=32650&view=co&pathrev=32650 +[2] http://msdn.microsoft.com/en-us/library/ee441774%28v=prot.13%29.aspx SMB Header Protocol Definition +[3] http://msdn.microsoft.com/en-us/library/ee441616(v=prot.13).aspx +''' + + +import dshell +import struct +#import binascii + +SMB_PROTOCOL = '\xffSMB' +SMB_STATUS_SUCCESS = 0x0 +NTLMSSP_IDENT = 'NTLMSSP\x00' +NTLMSSP_AUTH = 0x00000003 +NTLMSSP_CHALLENGE = 0x00000002 + + +class SMBDecoder(dshell.TCPDecoder): + + def __init__(self, **kwargs): + self.requests = {} # requests are stored by MID + dshell.TCPDecoder.__init__(self, **kwargs) + + def connectionInitHandler(self, conn): + self.requests[conn.addr] = {} + + def blobHandler(self, conn, blob): + data = blob.data() + offset = 0 + datalen = len(data) + while offset < datalen: + try: + offset += self.smbFactory(conn, blob, data[offset:]) + except InsufficientData: + return + + # Returns number of bytes used by NetBIOS+SMB + # e.g. mlength+4 + def smbFactory(self, conn, blob, data): + + try: + msgtype, mlength, smbdata = self.parseNetBIOSSessionService(data) + except InsufficientData: + raise + + try: + # create SMB Message (abstract data model: SMB header + extra) + smb = SMB(smbdata) + except InsufficientData: + raise + + if smb.proto != SMB_PROTOCOL: + return mlength + 4 + + if blob.direction == 'cs': + self.requests[conn.addr][smb.mid] = [blob.starttime, smb] + elif blob.direction == 'sc': + if smb.mid in self.requests[conn.addr].keys(): + requesttime, request = self.requests[conn.addr][smb.mid] + responsetime, response = blob.starttime, smb + + if 'SMBHandler' in dir(self): + self.SMBHandler(conn=conn, request=request, response=response, + requesttime=requesttime, responsetime=responsetime, cmd=smb.cmd, status=smb.status) + + del self.requests[conn.addr][smb.mid] + + return mlength + 4 + + def connectionHandler(self, conn): + """ clean up all requests associated with this connection """ + if conn.addr in self.requests: + if len(self.requests[conn.addr]) > 0: + for mid in self.requests[conn.addr].keys(): + requesttime, request = self.requests[conn.addr][mid] + self.SMBHandler(conn=conn, request=request, response=None, + requesttime=requesttime, responsetime=None, cmd=request.cmd, status=-1) + del self.requests[conn.addr][mid] + del self.requests[conn.addr] + + def postModule(self): + """ clean up self.requests to process all SMB messages that only have a single request and no response """ + for k in self.requests.keys(): + for mid in self.requests[k].keys(): + requesttime, request = self.requests[k][mid] + self.SMBHandler(conn=None, request=request, response=None, + requesttime=requesttime, responsetime=None, cmd=request.cmd, status=-1) + del self.requests[k][mid] + del self.requests[k] + + def parseNetBIOSSessionService(self, data): + """ parse the NetBIOS Session Service header [2]""" + if len(data) < 4: + raise InsufficientData + msgtype = struct.unpack('B', data[0])[0] + arg1, arg2, arg3 = struct.unpack('3B', data[1:4]) + mlength = (arg1 * 512) + (arg2 * 256) + arg3 + smbdata = data[4:] + return msgtype, mlength, smbdata + + def SMBHandler(self, conn, request=None, response=None, requesttime=None, responsetime=None, cmd=None, status=None): + "Placeholder. Overwrite in separate decoders." + pass + + +class InsufficientData(Exception): + pass + + +class SMB(): + + def __init__(self, pktdata): + """ + Generic SMB class. Handles parsing of SMB Header Messages and some specific SMB Command Objects + + Reference: + [1] http://msdn.microsoft.com/en-us/library/ee441774%28v=prot.13%29.aspx SMB Header Protocol Definition + [2] http://msdn.microsoft.com/en-us/library/ee441616(v=prot.13).aspx + + + proto = 4 bytes 4s 4-byte literal string '\xFF', 'S', 'M', 'B' + cmd = 1 byte B one-byte command code, commands listed at [2] + status = 4 bytes I A 32-bit field used to communicate error messages from the server to the client [SUCCESS = 0x0000 + flags1 = 1 byte B + flags2 = 2 bytes H + pidhigh = 2 bytes H + security = 8 bytes 8s + reserved = 2 bytes H + tid = 2 bytes H + pidlow = 2 bytes H + uid = 2 bytes H Associate a session with a specific user + mid = 2 bytes H Multiplexer identifier + """ + self.filename = None + if len(pktdata) < 32: + raise InsufficientData + self.proto, self.cmd, self.status, self.flags1, self.flags2, self.pidhigh, self.security, self.reserved, self.tid, self.pidlow, self.uid, self.mid = struct.unpack( + '<4sBIBHH8sHHHHH', pktdata[:32]) + self.smbdata = pktdata[32:] + + def PARSE_NT_CREATE_ANDX_REQUEST(self, data): + """ return the filename associated with the request (return None if err)""" + try: + wct, andxcmd, rsrv1, andxoffset, rsrv2, filenamelen, cflags, rootfid, mask, size, attrib, share = struct.unpack( + ' len(secblob): + return None + msgtype = struct.unpack( + ' Date: Tue, 19 May 2015 08:30:29 -0400 Subject: [PATCH 016/166] bug fix --- decoders/flows/large-flows.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/decoders/flows/large-flows.py b/decoders/flows/large-flows.py index 3a05fcc..a954aaa 100644 --- a/decoders/flows/large-flows.py +++ b/decoders/flows/large-flows.py @@ -21,7 +21,7 @@ def preModule(self): self.warn( "Cannot have a size that's less than or equal to zero. (size: %s)" % (self.size)) self.size = 1 - self.min = 104857 * self.size + self.min = 1048576 * self.size self.debug("Input: %s, Final size: %s bytes" % (self.size, self.min)) def connectionHandler(self, conn): From 448207bbd6194a49af389c81ccd9332e947c656c Mon Sep 17 00:00:00 2001 From: dev195 Date: Fri, 12 Jun 2015 10:59:20 -0400 Subject: [PATCH 017/166] Added MAC address handling to dshell.py --- lib/dshell.py | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/lib/dshell.py b/lib/dshell.py index 186e2b6..713e497 100644 --- a/lib/dshell.py +++ b/lib/dshell.py @@ -10,9 +10,7 @@ import traceback import util import os -import datetime import logging -import binascii # For IP lookups try: @@ -134,7 +132,7 @@ def __init__(self, **kwargs): if kwargs: self.__dict__.update(kwargs) - '''convenience functions for alert output and logging''' + ### convenience functions for alert output and logging ### def alert(self, *args, **kw): '''sends alert to output handler @@ -426,10 +424,10 @@ def decode(self, *args, **kw): # decode with the L2 decoder (probably Ether) pkt = self.l2decoder(pktdata) # strip any intermediate layers (PPPoE, etc) - for l in xrange(int(self.striplayers)): + for _ in xrange(int(self.striplayers)): pkt = pkt.data - '''will call self.rawHandler(len,pkt,ts) - (hdr,data) is the PCAP header and raw packet data''' + # will call self.rawHandler(len,pkt,ts) + # (hdr,data) is the PCAP header and raw packet data if 'rawHandler' in dir(self): self.rawHandler(pktlen, pkt, ts, **kw) else: @@ -506,6 +504,13 @@ def rawHandler(self, pktlen, pkt, ts, **kwargs): if 6to4, unencaps the IPv6 If IP/IP6, hands off to IPDecoder via IPHandler()''' try: + # If this packet has an Ethernet header, try and grab the MAC address + if type(pkt) == dpkt.ethernet.Ethernet: + try: + smac = "%02x:%02x:%02x:%02x:%02x:%02x" % (struct.unpack("BBBBBB", pkt.src)) + dmac = "%02x:%02x:%02x:%02x:%02x:%02x" % (struct.unpack("BBBBBB", pkt.dst)) + except: # couldn't get MAC address + smac, dmac = None, None # if this is an IPv4 packet, defragment, decode and hand it off if type(pkt.data) == dpkt.ip.IP: if self.defrag: @@ -533,6 +538,7 @@ def rawHandler(self, pktlen, pkt, ts, **kwargs): proto=self.IP_PROTO_MAP.get( pkt.p, pkt.p), sipint=sipint, dipint=dipint, + smac=smac, dmac=dmac, **kwargs) if pkt and type(pkt.data) == dpkt.ip6.IP6: pkt = pkt.data # no defrag of ipv6 @@ -544,10 +550,17 @@ def rawHandler(self, pktlen, pkt, ts, **kwargs): sport, dport = pkt.data.sport, pkt.data.dport except: sport, dport = None, None + # generate int forms of src/dest ips + h, l = struct.unpack("!QQ", pkt.src) + sipint = ( (h << 64) | l ) + h, l = struct.unpack("!QQ", pkt.dst) + dipint = ( (h << 64) | l ) # call ipv6 handler self.IPHandler(((sip, sport), (dip, dport)), pkt, ts, pkttype=dpkt.ethernet.ETH_TYPE_IP6, proto=self.IP_PROTO_MAP.get(pkt.nxt, pkt.nxt), + sipint=sipint, dipint=dipint, + smac=smac, dmac=dmac, **kwargs) except Exception, e: self._exc(e) From be4fdc0607e170095f954f7414039aef5dc758ef Mon Sep 17 00:00:00 2001 From: dev195 Date: Fri, 12 Jun 2015 11:09:49 -0400 Subject: [PATCH 018/166] Exception handling for MAC addresses --- lib/dshell.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/dshell.py b/lib/dshell.py index 713e497..9dac78d 100644 --- a/lib/dshell.py +++ b/lib/dshell.py @@ -509,7 +509,7 @@ def rawHandler(self, pktlen, pkt, ts, **kwargs): try: smac = "%02x:%02x:%02x:%02x:%02x:%02x" % (struct.unpack("BBBBBB", pkt.src)) dmac = "%02x:%02x:%02x:%02x:%02x:%02x" % (struct.unpack("BBBBBB", pkt.dst)) - except: # couldn't get MAC address + except struct.error: # couldn't get MAC address smac, dmac = None, None # if this is an IPv4 packet, defragment, decode and hand it off if type(pkt.data) == dpkt.ip.IP: From 93ef2f238f0369d22f9576c8f908d33bb2b4c4ce Mon Sep 17 00:00:00 2001 From: William Glodek Date: Tue, 30 Jun 2015 19:17:43 -0400 Subject: [PATCH 019/166] Dockerfile and documentation to build a Dshell Docker image --- docker/Dockerfile | 34 ++++++++++++++++++++++++++++++++++ docker/README.md | 16 ++++++++++++++++ 2 files changed, 50 insertions(+) create mode 100644 docker/Dockerfile create mode 100644 docker/README.md diff --git a/docker/Dockerfile b/docker/Dockerfile new file mode 100644 index 0000000..9f00752 --- /dev/null +++ b/docker/Dockerfile @@ -0,0 +1,34 @@ +FROM ubuntu:14.04 + +# install depdencies +RUN apt-get update && apt-get install -y \ + python-crypto \ + python-dpkt \ + python-ipy \ + python-pypcap \ + python-pip \ + wget \ + git + +RUN pip install pygeoip + +# Download the latest version of the code from GitHub +WORKDIR /opt/ +RUN git clone https://github.com/USArmyResearchLab/Dshell.git + +# download and gunzip GeoIP files +WORKDIR /opt/Dshell/share/GeoIP/ +RUN wget http://geolite.maxmind.com/download/geoip/database/GeoLiteCountry/GeoIP.dat.gz +RUN wget http://geolite.maxmind.com/download/geoip/database/GeoIPv6.dat.gz +RUN wget http://download.maxmind.com/download/geoip/database/asnum/GeoIPASNum.dat.gz +RUN wget http://download.maxmind.com/download/geoip/database/asnum/GeoIPASNumv6.dat.gz +RUN gunzip *.gz + +# make Dshell +WORKDIR /opt/Dshell/ +RUN make + +# Used to mount pcap from a host OS directory +VOLUME ["/mnt/pcap"] + +CMD ["/opt/Dshell/dshell"] diff --git a/docker/README.md b/docker/README.md new file mode 100644 index 0000000..5cf8cd6 --- /dev/null +++ b/docker/README.md @@ -0,0 +1,16 @@ +## Building a Dshell Docker image + +Step 1: Build a Docker image that has Dshell installed and configured +```bash +sudo docker build -t dshell . +``` + +Step 2: Run the container with a native host directory (/home/user/pcap/) mounted in /mnt/pcap +```bash +sudo docker run -v /home/user/pcap:/mnt/pcap -it dshell +``` + +Step 3: Use Dshell to analyze network traffic +```bash +decode -d netflow /mnt/pcap/*.pcap +``` From f9a0efaeae64b4d3d1c3b86fa61c033494d45a76 Mon Sep 17 00:00:00 2001 From: John Volk Date: Wed, 8 Jul 2015 11:04:59 -0400 Subject: [PATCH 020/166] Fix looking for headers in request.body --- decoders/http/rip-http.py | 105 +++++++++++++------------------------- 1 file changed, 35 insertions(+), 70 deletions(-) diff --git a/decoders/http/rip-http.py b/decoders/http/rip-http.py index 02e2fbd..2606944 100644 --- a/decoders/http/rip-http.py +++ b/decoders/http/rip-http.py @@ -48,85 +48,50 @@ def preModule(self): (self.outdir, e)) sys.exit(1) - def splitstrip(self, data, sep, strip=' '): - return [lpart.strip(strip) for lpart in data.split(sep)] - - def POSTHandler(self, postdata): - next_line_is_data = False - for l in postdata.split("\r\n"): - if next_line_is_data: - break - if l == '': - next_line_is_data = True # \r\n\r\n before data - continue - try: - k, v = self.splitstrip(l, ':') - if k == 'Content-Type': - contenttype = v - if k == 'Content-Disposition': - cdparts = self.splitstrip(v, ';') - for cdpart in cdparts: - try: - k, v = self.splitstrip(cdpart, '=', '"') - if k == 'filename': - filename = v - except: - pass - except: - pass - return contenttype, filename, l - def HTTPHandler(self, conn, request, response, requesttime, responsetime): self.debug('%s %s' % (repr(request), repr(response))) if (not self.direction or self.direction == 'cs') and request and request.method == 'POST' and request.body: - contenttype, filename, data = self.POSTHandler(request.body) if not self.content_filter or self.content_filter.search(contenttype): + payload = request + elif (not self.direction or self.direction == 'sc') and response and response.status[0] == '2': + if not self.content_filter or self.content_filter.search(response.headers['content-type']): + payload = response + if 'payload' in locals(): + # Calculate URL + host = util.getHeader(request, 'host') + if host == '': + host = conn.serverip + url = host + request.uri + # File already open + if url in self.openfiles: + self.debug("Adding response section to %s" % url) + (s, e) = self.openfiles[url].handleresponse(response) + self.write(" --> Range: %d - %d\n" % (s, e)) + # New file + else: + filename = request.uri.split('?')[0].split('/')[-1] + self.debug("New file with URL: %s" % url) if not self.name_filter or self.name_filter.search(filename): if self.append_conn: - filename += '_%s-%s' % (conn.clientip, conn.serverip) + filename += '_%s-%s' % (conn.serverip, + conn.clientip) if self.append_ts: filename += '_%d' % (conn.ts) - self.debug(os.path.join(self.outdir, filename)) - f = open(os.path.join(self.outdir, filename), 'w') - f.write(data) - f.close() - elif (not self.direction or self.direction == 'sc') and response and response.status[0] == '2': - if not self.content_filter or self.content_filter.search(response.headers['content-type']): - # Calculate URL - host = util.getHeader(request, 'host') - if host == '': - host = conn.serverip - url = host + request.uri - # File already open - if url in self.openfiles: - self.debug("Adding response section to %s" % url) - (s, e) = self.openfiles[url].handleresponse(response) + if not len(filename): + filename = '%s-%s_index.html' % ( + conn.serverip, conn.clientip) + while os.path.exists(os.path.join(self.outdir, filename)): + filename += '_' + self.alert("New file: %s (%s)" % + (filename, url), conn.info()) + self.openfiles[url] = httpfile( + os.path.join(self.outdir, filename), self) + (s, e) = self.openfiles[url].handleresponse(payload) self.write(" --> Range: %d - %d\n" % (s, e)) - # New file - else: - filename = request.uri.split('?')[0].split('/')[-1] - self.debug("New file with URL: %s" % url) - if not self.name_filter or self.name_filter.search(filename): - if self.append_conn: - filename += '_%s-%s' % (conn.serverip, - conn.clientip) - if self.append_ts: - filename += '_%d' % (conn.ts) - if not len(filename): - filename = '%s-%s_index.html' % ( - conn.serverip, conn.clientip) - while os.path.exists(os.path.join(self.outdir, filename)): - filename += '_' - self.alert("New file: %s (%s)" % - (filename, url), conn.info()) - self.openfiles[url] = httpfile( - os.path.join(self.outdir, filename), self) - (s, e) = self.openfiles[url].handleresponse(response) - self.write(" --> Range: %d - %d\n" % (s, e)) - if self.openfiles[url].done(): - self.alert("File done: %s (%s)" % - (self.openfiles[url].filename, url), conn.info()) - del self.openfiles[url] + if self.openfiles[url].done(): + self.alert("File done: %s (%s)" % + (self.openfiles[url].filename, url), conn.info()) + del self.openfiles[url] class httpfile: From 7d22899207c3610c27fb1d335a015144503cb13a Mon Sep 17 00:00:00 2001 From: John Volk Date: Thu, 9 Jul 2015 16:05:52 -0400 Subject: [PATCH 021/166] Fix content filter and re-add filename extraction from content-disposition --- decoders/http/rip-http.py | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/decoders/http/rip-http.py b/decoders/http/rip-http.py index 2606944..4b49f9f 100644 --- a/decoders/http/rip-http.py +++ b/decoders/http/rip-http.py @@ -48,15 +48,20 @@ def preModule(self): (self.outdir, e)) sys.exit(1) + def splitstrip(self, data, sep, strip=' '): + return [lpart.strip(strip) for lpart in data.split(sep)] + def HTTPHandler(self, conn, request, response, requesttime, responsetime): + payload = None self.debug('%s %s' % (repr(request), repr(response))) if (not self.direction or self.direction == 'cs') and request and request.method == 'POST' and request.body: - if not self.content_filter or self.content_filter.search(contenttype): payload = request elif (not self.direction or self.direction == 'sc') and response and response.status[0] == '2': - if not self.content_filter or self.content_filter.search(response.headers['content-type']): payload = response - if 'payload' in locals(): + if payload: + if not (not self.content_filter or self.content_filter.search(payload.headers['content-type'])): + payload = None + if payload: # Calculate URL host = util.getHeader(request, 'host') if host == '': @@ -70,6 +75,15 @@ def HTTPHandler(self, conn, request, response, requesttime, responsetime): # New file else: filename = request.uri.split('?')[0].split('/')[-1] + if 'content-disposition' in payload.headers: + cdparts = self.splitstrip(payload.headers['content-disposition'], ';') + for cdpart in cdparts: + try: + k, v = self.splitstrip(cdpart, '=') + if k == 'filename': + filename = v + except: + pass self.debug("New file with URL: %s" % url) if not self.name_filter or self.name_filter.search(filename): if self.append_conn: From dcd24eacdffed347988738eae6f830103c446346 Mon Sep 17 00:00:00 2001 From: Nate Date: Fri, 17 Jul 2015 15:14:23 -0400 Subject: [PATCH 022/166] new decoder to filter by asn code --- decoders/filter/asn-filter.py | 100 ++++++++++++++++++++++++++++++++++ 1 file changed, 100 insertions(+) create mode 100644 decoders/filter/asn-filter.py diff --git a/decoders/filter/asn-filter.py b/decoders/filter/asn-filter.py new file mode 100644 index 0000000..6abf064 --- /dev/null +++ b/decoders/filter/asn-filter.py @@ -0,0 +1,100 @@ +import dshell +import util +import netflowout + + +class DshellDecoder(dshell.TCPDecoder): + + def __init__(self, **kwargs): + self.sessions = {} + self.alerts = False + self.file = None + dshell.TCPDecoder.__init__(self, + name='asn-filter', + description='filter connections on autonomous system number (ASN)', + longdescription=""" +This decoder filters connections by autonomous system numbers/names (ASN). + +Chainable decoder used to filter TCP/UDP streams by ASNs. If no +downstream (+) decoder is used the netflow data will be printed to +the screen (when using --asn-filter_alerts). If used without specifying +a asn string, the asn-filter will filter nothing out and pass +everything onto the next decoder or print it. + +Examples: + + decode -d asn-filter --asn-filter_asn AS8075 --asn-filter_alerts + + This will print the connection info for all connections where + AS8075 is the ASN for either the server of client. + + decode -d asn-filter --asn-filter_asn Google --asn-filter_alerts + + This will print the connection info for all connections where + "Google" appeared in the ASN information. + + decode -d asn-filter+followstream --asn-filter_asn AS8075 + + This will filter the streams by ASN and feed them into the + followstream decoder. +""", + filter="ip or ip6", + author='twp/nl', + optiondict={ + 'asn': {'type': 'string', 'help': 'asn for client or server'}, + 'alerts': {'action': 'store_true'}}) + '''instantiate an decoder that will call back to us once the IP decoding is done''' + self.__decoder = dshell.IPDecoder() + self.out = netflowout.NetflowOutput() + self.chainable = True + + def decode(self, *args): + if len(args) is 3: + pktlen, pktdata, ts = args # orig_len,packet,ts format (pylibpcap) + else: # ts,pktdata (pypcap) + ts, pktdata = args + pktlen = len(pktdata) + '''do normal decoder stack to track session ''' + dshell.TCPDecoder.decode(self, pktlen, pktdata, ts) + '''our hook to decode the ip/ip6 addrs, then dump the addrs and raw packet to our callback''' + self.__decoder.IPHandler = self.__callback # set private decoder to our callback + self.__decoder.decode(pktlen, pktdata, ts, raw=pktdata) + + def __callback(self, addr, pkt, ts, raw=None, **kw): + '''substitute IPhandler for forwarding packets to subdecoders''' + if addr in self.sessions or (addr[1], addr[0]) in self.sessions: # if we are not passing this session, drop the packet + if self.subDecoder: + # make it look like a capture + self.subDecoder.decode(len(raw), str(raw), ts) + else: + self.dump(raw, ts) + + def connectionInitHandler(self, conn): + '''see if we have an ASN match and if so, flag this session for forwarding or dumping''' + m = self.__asnTest(conn) + if m: + self.sessions[conn.addr] = m + + def __asnTest(self, conn): + # If no ASN specified, pass all traffic through + if not self.asn: + return True + # check criteria + if self.asn.lower() in conn.clientasn.lower(): + return u'client {0}'.format(conn.clientasn) + if self.asn.lower() in conn.serverasn.lower(): + return u'server {0}'.format(conn.serverasn) + # no match + return None + + def connectionHandler(self, conn): + if conn.addr in self.sessions and self.alerts: + self.alert(self.sessions[conn.addr], **conn.info()) + + def connectionCloseHandler(self, conn): + if conn.addr in self.sessions: + del self.sessions[conn.addr] + +dObj = DshellDecoder() +if __name__ == "__main__": + print dObj From 5be276003687d59ddf300116f8ed6ff956d4cf3c Mon Sep 17 00:00:00 2001 From: dekrych Date: Sun, 19 Jul 2015 22:31:46 -0400 Subject: [PATCH 023/166] Extracts client information from DHCP messages --- decoders/dhcp/dhcp.py | 89 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 89 insertions(+) create mode 100644 decoders/dhcp/dhcp.py diff --git a/decoders/dhcp/dhcp.py b/decoders/dhcp/dhcp.py new file mode 100644 index 0000000..003109b --- /dev/null +++ b/decoders/dhcp/dhcp.py @@ -0,0 +1,89 @@ +import dpkt +import dshell +import util +from struct import unpack +import binascii + +class DshellDecoder(dshell.UDPDecoder): + + def __init__(self): + dshell.UDPDecoder.__init__(self, + name='dhcp', + description='extract client information from DHCP messages', + longdescription=""" +The dhcp decoder will extract the Transaction ID, Client Hostname, and +Client MAC address from every UDP DHCP packet found in the given pcap +destined for port 67. DHCP uses BOOTP as its transport protocol. +BOOTP traffic generally uses ports 67 and 68 for outgoing and incoming traffic. +This filter pulls DHCP Inform packets destined for the server. + +Examples: + + General usage: + + decode -d dhcp + + This will display the connection info including the timestamp, + the source IP : source port, destination IP : destination port, + Transaction ID, Client Hostname, and the Client MAC address + in a tabular format. + + + Malware Traffic Analysis Exercise Traffic from 2015-03-03 where a user was hit with an Angler exploit kit: + + We want to find out more about the infected machine, and some of this information can be pulled from DHCP traffic + + decode -d dhcp /2015-03-03-traffic-analysis-exercise.pcap + + OUTPUT: + dhcp 2015-03-03 14:05:10 172.16.101.196:68 -- 172.16.101.1:67 ** Transaction ID: 0xba5a2cfe Client Hostname: Gregory-PC Client MAC: 38:2c:4a:3d:ef:01 ** + dhcp 2015-03-03 14:08:40 172.16.101.196:68 -- 255.255.255.255:67 ** Transaction ID: 0x6a482406 Client Hostname: Gregory-PC Client MAC: 38:2c:4a:3d:ef:01 ** + dhcp 2015-03-03 14:10:11 172.16.101.196:68 -- 172.16.101.1:67 ** Transaction ID: 0xe74b17fe Client Hostname: Gregory-PC Client MAC: 38:2c:4a:3d:ef:01 ** + dhcp 2015-03-03 14:12:50 172.16.101.196:68 -- 255.255.255.255:67 ** Transaction ID: 0xd62614a0 Client Hostname: Gregory-PC Client MAC: 38:2c:4a:3d:ef:01 ** +""", + filter='(udp and port 67)', + author='dek', + ) + self.mac_address = None + self.client_hostname = None + self.xid = None + + + # A packetHandler is used to ensure that every DHCP packet in the traffic is parsed + def packetHandler(self, udp, data): + try: + dhcp_packet = dpkt.dhcp.DHCP(data) + except dpkt.NeedData as e: + self.warn('{} dpkt could not parse session data (DHCP packet not found)'.format(str(e))) + return + + # Pull the transaction ID from the packet + self.xid = hex(dhcp_packet.xid) + + # if we have a DHCP INFORM PACKET + if dhcp_packet.op == dpkt.dhcp.DHCP_OP_REQUEST: + self.debug(dhcp_packet.op) + for option_code, msg_value in dhcp_packet.opts: + + # if opt is CLIENT_ID (61) + # unpack the msg_value and reformat the MAC address + if option_code == dpkt.dhcp.DHCP_OPT_CLIENT_ID: + hardware_type, mac = unpack('B6s', msg_value) + mac = binascii.hexlify(mac) + self.mac_address = ':'.join([mac[i:i+2] for i in range(0, len(mac), 2)]) + + # if opt is HOSTNAME (12) + elif option_code == dpkt.dhcp.DHCP_OPT_HOSTNAME: + self.client_hostname = msg_value + + + if self.xid and self.client_hostname and self.mac_address: + self.alert('Transaction ID: {0:<12} Client Hostname: {1:<15} Client MAC: {2:<20}'.format( + self.xid, self.client_hostname, self.mac_address), **udp.info()) + + +if __name__ == '__main__': + dObj = DshellDecoder() + print dObj +else: + dObj = DshellDecoder() From 71a4a55aa02447b10afb2d9c4cd47d6887d4ce5d Mon Sep 17 00:00:00 2001 From: Dan Date: Mon, 20 Jul 2015 08:35:09 -0400 Subject: [PATCH 024/166] Update dhcp.py --- decoders/dhcp/dhcp.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/decoders/dhcp/dhcp.py b/decoders/dhcp/dhcp.py index 003109b..6795a3d 100644 --- a/decoders/dhcp/dhcp.py +++ b/decoders/dhcp/dhcp.py @@ -13,9 +13,9 @@ def __init__(self): longdescription=""" The dhcp decoder will extract the Transaction ID, Client Hostname, and Client MAC address from every UDP DHCP packet found in the given pcap -destined for port 67. DHCP uses BOOTP as its transport protocol. +using port 67. DHCP uses BOOTP as its transport protocol. BOOTP traffic generally uses ports 67 and 68 for outgoing and incoming traffic. -This filter pulls DHCP Inform packets destined for the server. +This filter pulls DHCP Inform packets. Examples: From 8b2b2a5a3ca7bccf68cc0751166cc55ce344eedb Mon Sep 17 00:00:00 2001 From: Eric Kilmer Date: Mon, 20 Jul 2015 10:46:50 -0400 Subject: [PATCH 025/166] Add flash-detect decoder to detect Flash file downloads --- decoders/http/flash-detect.py | 236 ++++++++++++++++++++++++++++++++++ 1 file changed, 236 insertions(+) create mode 100644 decoders/http/flash-detect.py diff --git a/decoders/http/flash-detect.py b/decoders/http/flash-detect.py new file mode 100644 index 0000000..59eb255 --- /dev/null +++ b/decoders/http/flash-detect.py @@ -0,0 +1,236 @@ +import util +import hashlib +import os +from httpdecoder import HTTPDecoder + + +class DshellDecoder(HTTPDecoder): + + # Constant for dump directory + __OUTDIR = 'flashout' + + # Constants for MD5sum option + NOMD5 = 0 + MD5 = 1 + MD5_EXPLICIT_FILENAME = 2 + + def __init__(self): + HTTPDecoder.__init__(self, + name='flash-detect', + description='Detects successful Flash file download.', + filter='tcp and (port 80 or port 8080 or port 8000)', + filterfn=lambda ((sip, sp), (dip, dp)): sp in ( + 80, 8000, 8080) or dp in (80, 8000, 8080), + optiondict={ + 'dump': {'action': 'store_true', 'help': '''\ +Dump the flash file to a file based off its name, md5sum (if specified), or +its URI. The file is dumped to the local directory "flashout". The file +extension is ".flash" to prevent accidental execution.''' + }, + 'md5sum': {'type': 'int', 'default': 0, 'help': '''\ +Calculate and print the md5sum of the file. There are three options: + 0: (default) No md5sum calculations or labeling + + 1: Calculate md5sum; Print out md5sum in alert; Name all dumped files by +their md5sum (must be used with 'dump' option) + + 2: Calculate md5sum; Print out md5sum in alert; If found, a file's explicitly +listed save name (found in 'content-disposition' HTTP header) will be used +for file dump name instead of md5sum. + +Any other numbers will be ignored and the default action will be used.''' + } + }, + longdescription='''\ +flash-detect identifies HTTP requests where the server response contains a Flash +file. Many exploit kits utilize Flash to deliver exploits to potentially vulnerable +browsers. If a flash file is successfully downloaded, an alert will occur stating +the full URL of the downloaded file, its content-type, and (optionally) its md5sum. + +Usage Examples: +=============== + Search all pcap files for Flash file downloads, and upon detection, calculate + and print alerts containing the md5sum to screen: + + decode -d flash-detect --flash-detect_md5sum=1 *.pcap + + If you wanted to save every detected Flash file to a local directory + "./flashout/" with its md5sum as the file name: + + decode -d flash-detect --flash-detect_md5sum=1 --flash-detect_dump *.pcap + The output directory can be changed by modifying the `__OUTDIR` variable. + + An example of a real pcap file, taken from + http://malware-traffic-analysis.net/2014/12/12/index.html: + decode -d flash-detect --flash-detect_md5sum=1 2014-12-12-Nuclear-EK-traffic.pcap + + The following text should be displayed in the output, and the md5sum + can be checked on a site like virustotal: +** yquesrerman.ga/AwoVG1ADAw4OUhlVDlRTBQoHRUJTXVYOUVYaAwtGXFRVVFxXVwBOVRtA (application/octet-stream) md5sum: 9b3ad66a2a61e8760602d98b537b7734 ** + +Implementation Logic +==================== + +1. Check if the HTTP response status is 200 OK + +2. Test the content-type of the HTTP response for the follwing strings: + 'application/x-shockwave-flash' + 'application/octet-stream' + 'application/vnd.adobe.flash-movie' + +3. Test filedownload following known Flash magic byte substrings: + 'CWS' + 'ZWS' + 'FWS' + +Note: Encoded or obfuscated flash files will *not* be detected. + +Chainable + +flash-detect is chainable. If a connection contains an HTTP response with a +successful Flash file download, then the entire connection (in the case of a +connectionHandler), and the request, response, requesttime, and responsetime +(in the case of an HTTPHandler) is/are passed to the subDecoders for additional +processing. Undetected or non-Flash files are dropped. +''', + author='ekilmer', + ) + self.chainable = True + + def preModule(self): + # Attempt to create output directory + if self.dump: + self.__OUTDIR = self.__mkoutdir(self.__OUTDIR) + self.log("Using output directory: {0}".format(self.__OUTDIR)) + + def HTTPHandler(self, conn, request, response, requesttime, responsetime): + if response and response.status != '200': + return + + content_type = util.getHeader(response, 'content-type') + if content_type not in ('application/x-shockwave-flash', + 'application/octet-stream', + 'application/vnd.adobe.flash-movie'): + return + + # Check for known flash file header characters + if not response.body.startswith(('CWS', 'ZWS', 'FWS')): + return + + host = util.getHeader(request, 'host') + # Grab file info as dict with keys: 'file_name', 'md5sum', 'uri' + file_info = self.get_file_info(request, response) + if self.md5sum == self.MD5 or self.md5sum == self.MD5_EXPLICIT_FILENAME: + # Print MD5 sum in the alert + self.alert('{0}{1} ({2}) md5sum: {3}'.format(host, request.uri, content_type, + file_info['md5sum']), **conn.info()) + else: + self.alert('{0}{1} ({2})'.format(host, request.uri, content_type), **conn.info()) + + # Dump the file if chosen + if self.dump: + # Name output files based on options + if self.md5sum == self.MD5: + origname = file_info['md5sum'] + # Check for explicitly listed filename + elif file_info['file_name']: + origname = file_info['file_name'] + # If explicit name not found, but still want MD5, give it MD5 + elif self.md5sum == self.MD5_EXPLICIT_FILENAME: + origname = file_info['md5sum'] + # Else name the file by its URI (which can be long) + else: + origname = file_info['uri'] + outname = self.__localfilename(self.__OUTDIR, origname) + with open('{0}.flash'.format(outname), 'wb') as outfile: + outfile.write(response.body) + + # Pass to subdecoder if necessary + if 'HTTPHandler' in dir(self.subDecoder): + self.subDecoder.HTTPHandler(conn, request, response, requesttime, responsetime) + elif 'connectionHandler' in dir(self.subDecoder): + self.subDecoder.connectionHandler(conn) + + def get_file_info(self, request, response): + """Checks for an explicitly listed file name. Returns a dictionary containing the + explicitly listed filename (if present), the URI, and an md5sum (if requested) + """ + file_info = {'file_name': '', 'uri': '', 'md5sum': ''} + + content = util.getHeader(response, 'content-disposition') + if content and 'filename' in content: + # RFC 1806: content contains a string with parameters separated by semi-colons + text = content.split(';') + for parm in text: + if parm.strip().startswith('filename='): + file_info['file_name'] = parm.split('filename=', 1)[1] + + # CAVEAT: When the URI is very long and it is used as a filename in a dump, + # then the file name may become unwieldy + file_info['uri'] = request.uri + + if self.md5sum == self.MD5 or self.md5sum == self.MD5_EXPLICIT_FILENAME: + file_info['md5sum'] = self.__body_md5(response) + + return file_info + + def __body_md5(self, response): + """Calculate the MD5sum(hex) of the body portion of the response.""" + if len(response.body) > 0: + return hashlib.md5(response.body.rstrip('\0')).hexdigest() + else: + self.warn("Nothing to hash") + return '' + + def __mkoutdir(self, outdir): + """Creates output directory. Returns full path to output directory.""" + path = os.path.realpath(outdir) + if os.path.exists(path): + return path + try: + os.mkdir(path) + return path + except OSError: + # most likely a permission denied issue, continue and try system temp directory + pass + except: + self.warn('Unable to create a directory for file dump') + # other errors, abort + raise + + # Trying temp directory + if os.path.exists('/tmp'): + path = os.path.realpath(os.path.join('/tmp', outdir)) + if os.path.exists(path): + return path + try: + os.mkdir(path) + return path + except: + self.warn('Unable to create a directory for file dump') + raise + + def __localfilename(self, path, origname): + """Generate a local (extracted) filename based on the original""" + tmp = origname.replace('\\', '_') + tmp = tmp.replace('/', '_') + tmp = tmp.replace(':', '_') + localname = '' + for c in tmp: + if ord(c) > 32 and ord(c) < 127: + localname += c + else: + localname += '%{0:02X}'.format(ord(c)) + localname = '{0}/{1}'.format(path, localname) + postfix = '' + i = 0 + while os.path.exists(localname+postfix): + i += 1 + postfix = '_{0:02d}'.format(i) + return localname+postfix + +if __name__ == '__main__': + dObj = DshellDecoder() + print dObj +else: + dObj = DshellDecoder() From 77c6fb8b810be40d4c5b730ae4946dfba49c286d Mon Sep 17 00:00:00 2001 From: Marina Elmore Date: Tue, 11 Aug 2015 13:37:53 -0400 Subject: [PATCH 026/166] reverse-flow decoder --- decoders/flows/reverse-flow.py | 68 ++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 decoders/flows/reverse-flow.py diff --git a/decoders/flows/reverse-flow.py b/decoders/flows/reverse-flow.py new file mode 100644 index 0000000..d9545bd --- /dev/null +++ b/decoders/flows/reverse-flow.py @@ -0,0 +1,68 @@ +import dshell + +class DshellDecoder(dshell.TCPDecoder): + + '''Reverse-Flow Decoder''' + + def __init__(self): + dshell.TCPDecoder.__init__(self, + name='reverse-flow', + description='Generate an alert if the client transmits more data than the server', + longdescription=""" + + Generate an alert when a client transmits more data than the server. + + Additionally, the user can specify a threshold. This means that an alert + will be generated if the client transmits more than three times as much data + as the server. + + The default threshold value is 3.0, meaning that any client transmits + more than three times as much data as the server will generate an alert. + + Examples: + 1) decode -d reverse-flow + Generates an alert for client transmissions that are three times + greater than the server transmission. + + 2) decode -d reverse-flow --reverse-flow_threshold 61 + Generates an alert for all client transmissions that are 61 times + greater than the server transmission + + 3) decode -d reverse-flow --reverse-flow_threshold 61 --reverse-flow_zero + Generates an alert for all client transmissions that are 61 times greater + than the server transmission. + + + + """, + filter="tcp or udp", + author='me', + optiondict={ + 'threshold':{'type':'float', 'default':3.0, + 'help':'Alerts if client transmits more than threshold times the data of the server'}, + 'minimum':{'type':'int', 'default':0, 'help':'alert on client transmissions larger than min bytes [default: 0]'}, + 'zero':{'action':'store_true', 'default':False, 'help':'alert if the server transmits zero bytes [default: false]'}, + } + ) + + def preModule(self): + if self.threshold < 0: + self.warn( + "Cannot have a negative threshold. (threshold: {0})".format(self.threshold)) + self.threshold = 3.0 + elif not self.threshold: + self.warn( + "Displaying all client-server transmissions (threshold: {0})".format%(self.threshold)) + + def connectionHandler(self, conn): + if conn.clientbytes < self.minimum: + return + + if self.zero or (conn.serverbytes and float(conn.clientbytes)/conn.serverbytes > self.threshold): + self.alert('client sent {:>6.2f} more than the server'.format(conn.clientbytes/float(conn.serverbytes)), **conn.info()) + +if __name__ == '__main__': + dObj = DshellDecoder() + print dObj +else: + dObj = DshellDecoder() From fe610b481ebfd8906e927d8e68dce786208ec584 Mon Sep 17 00:00:00 2001 From: Adam Maddock Date: Tue, 17 Nov 2015 15:37:08 +0000 Subject: [PATCH 027/166] In preModule, changed call to setColorMode so that it is only executed if available in the output decoder. --- decoders/misc/followstream.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/decoders/misc/followstream.py b/decoders/misc/followstream.py index 38581fd..ea1e1c7 100644 --- a/decoders/misc/followstream.py +++ b/decoders/misc/followstream.py @@ -63,7 +63,8 @@ def __errorHandler(self, blob, expected, offset, caller): def preModule(self): self.connectionCount = 0 # Reset the color mode, in case a file is specified - self.out.setColorMode() + if 'setColorMode' in dir(self.out): + self.out.setColorMode() # Used to indicate when data is missing or overlapping self.data_missing_message = '' # overwrite the output module's default error handler From 165b77b272485bcbc9918e12b39d15b32373a837 Mon Sep 17 00:00:00 2001 From: Adam Maddock Date: Tue, 17 Nov 2015 15:37:56 +0000 Subject: [PATCH 028/166] Added support for out.write to jsonout. --- lib/output/jsonout.py | 58 ++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 54 insertions(+), 4 deletions(-) diff --git a/lib/output/jsonout.py b/lib/output/jsonout.py index afed2b3..3af2078 100644 --- a/lib/output/jsonout.py +++ b/lib/output/jsonout.py @@ -2,9 +2,12 @@ @author: amm ''' +import dshell +import dfile import output import datetime import json +import base64 class JSONOutput(output.TextOutput): @@ -48,6 +51,14 @@ def __init__(self, *args, **kwargs): output.TextOutput.__init__(self, **kwargs) def alert(self, *args, **kw): + self.fh.write( + json.dumps(self._filter_data(kw), ensure_ascii=self.options['ensure_ascii']) + "\n") + if self.nobuffer: + self.fh.flush() + + + # Reusable function to filter data in alerts and writes + def _filter_data(self, kw): # User specified field list?? if self.jsonfields != None: @@ -77,9 +88,48 @@ def alert(self, *args, **kw): for name in ('servercountrycode', 'clientcountrycode', 'sipcc', 'dipcc', 'clientasn', 'serverasn', 'dipasn', 'sipasn'): if name in kw: del kw[name] - self.fh.write( - json.dumps(kw, ensure_ascii=self.options['ensure_ascii']) + "\n") - if self.nobuffer: - self.fh.flush() + + outdata = {} + for n,v in kw.iteritems(): + if not isinstance(v, dfile.dfile): + outdata[n] = v + + return outdata + + + def write(self,*args,**kw): + + # Iterate *args + for a in args: + if type(a) == dshell.Blob: + self.fh.write(json.dumps(self._blob_to_dict(blob), ensure_ascii=self.options['ensure_ascii']) + "\n") + elif type(a) == dshell.Connection: + outdata = self._filter_data(a.info()) + outdata['type'] = 'conn' + outdata['data'] = [] + for blob in a: + #self._write_blob(blob, kw) + outdata['data'].append(self._blob_to_dict(blob)) + self.fh.write(json.dumps(outdata, ensure_ascii=self.options['ensure_ascii']) + "\n") + else: + d = self._filter_data(kw) + d['type'] = 'raw' + if type(a) == unicode: + d['data'] = base64.b64encode(a.encode('utf-8')) + else: + d['data'] = base64.b64encode(a) + self.fh.write(json.dumps(d, ensure_ascii=self.options['ensure_ascii']) + "\n") + + # Custom error handler for data reassembly --- ignores all errors + def errorH(self, **x): + return True + + def _blob_to_dict(self, blob): + d = self._filter_data(blob.info()) + d['type'] = 'blob' + d['data'] = base64.b64encode(blob.data(errorHandler=self.errorH)) + return d + + obj = JSONOutput From 949831a2e240f969c559ed01afe247949ccb4be0 Mon Sep 17 00:00:00 2001 From: J Date: Wed, 18 Nov 2015 10:41:48 -0500 Subject: [PATCH 029/166] Added "Partners" section to README --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.md b/README.md index 2a734a8..989d607 100644 --- a/README.md +++ b/README.md @@ -46,6 +46,12 @@ Key features: * `decode -d ` * Run the selected decoder on a pcap file +## Partners + +Below are repositories from partners Dshell has worked together with. + +* [DeKrych/Dshell-plugins](https://github.com/DeKrych/Dshell-plugins) + ## Usage Examples Showing DNS lookups in [sample traffic](http://wiki.wireshark.org/SampleCaptures#General_.2F_Unsorted) From 4fb4c362101ad60ce632a46d1d605a3e5f92e19b Mon Sep 17 00:00:00 2001 From: Adam Maddock Date: Wed, 18 Nov 2015 21:44:38 +0000 Subject: [PATCH 030/166] Updated httpdecoder to be less picky about directionality of HTTP REQUEST on the C->S and RESPONSE on the converse. I've seen anomalies where the opposite occurs, sometimes due to packet loss, but also intentionally by way of proxy or tcp relay. --- lib/httpdecoder.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/httpdecoder.py b/lib/httpdecoder.py index 35e8b78..a661a65 100644 --- a/lib/httpdecoder.py +++ b/lib/httpdecoder.py @@ -36,13 +36,13 @@ def errorH(self, **x): def blobHandler(self, conn, blob): '''buffer the request blob and call the handler once we have the response blob''' - if blob.direction == 'cs': + if conn not in self.requests: try: self.requests[conn] = ( blob.starttime, dpkt.http.Request(blob.data(self.errorH))) except Exception, e: self.UnpackError(e) - elif blob.direction == 'sc' and conn in self.requests: + else: try: if 'HTTPHandler' in dir(self): response = dpkt.http.Response(blob.data(self.errorH)) From e8b14e3c3ecd976eabbe762a4186784ceb534103 Mon Sep 17 00:00:00 2001 From: Adam Maddock Date: Thu, 19 Nov 2015 19:32:11 +0000 Subject: [PATCH 031/166] A utility to split pcap files by ip src/dst pair or tcp/udp stream. --- bin/pcapslice.py | 227 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 227 insertions(+) create mode 100755 bin/pcapslice.py diff --git a/bin/pcapslice.py b/bin/pcapslice.py new file mode 100755 index 0000000..0b78d64 --- /dev/null +++ b/bin/pcapslice.py @@ -0,0 +1,227 @@ +#!/usr/bin/env python +''' +split pcap files by ip src/dst pair or tcp/udp stream + +Originally created February 2013 +Updated from pylibpcap to pypcap, November 2015 + +@author: amm +''' + +import sys +import os +import pcap +import dpkt +import signal +import socket +import output +from optparse import OptionParser + +IPprotocols = { + 0: 'IP', 1: 'ICMP', 2: 'IGMP', 3: 'GGP', 4: 'IP-ENCAP', 133: 'FC', 6: 'TCP', 8: 'EGP', 137: 'MPLS-IN-IP', 138: 'MANET', 139: 'HIP', 12: 'PUP', 17: 'UDP', 20: 'HMP', 22: 'XNS-IDP', 132: 'SCTP', 27: 'RDP', 29: 'ISO-TP4', 5: 'ST', 36: 'XTP', 37: 'DDP', 38: 'IDPR-CMTP', 41: 'IPV6', 43: 'IPV6-ROUTE', 44: 'IPV6-FRAG', + 45: 'IDRP', 46: 'RSVP', 47: 'GRE', 136: 'UDPLITE', 50: 'IPSEC-ESP', 51: 'IPSEC-AH', 9: 'IGP', 57: 'SKIP', 58: 'IPV6-ICMP', 59: 'IPV6-NONXT', 60: 'IPV6-OPTS', 73: 'RSPF', 81: 'VMTP', 88: 'EIGRP', 89: 'OSPFIGP', 93: 'AX.25', 94: 'IPIP', 97: 'ETHERIP', 98: 'ENCAP', 103: 'PIM', 108: 'IPCOMP', 112: 'VRRP', 115: 'L2TP', 124: 'ISIS'} +flowtimeout = 1800 # seconds +ctrl_c_Received = False + +''' +main +''' +def main(): + global options, ctrl_c_Received + + flows = flowstore() + + parser = OptionParser( + usage="usage: %prog [options] file", version="%prog: PCAP Slicer") + parser.add_option('-f', '--bpf', dest='bpf', help='BPF input filter') + parser.add_option('--no-vlan', dest='novlan', action="store_true", + help='do not examine traffic which has VLAN headers present') + parser.add_option('--debug', action='store_true', dest='debug') + (options, args) = parser.parse_args(sys.argv[1:]) + + if not args: + parser.print_version() + parser.print_help() + sys.exit() + + filter = '' + if options.bpf != None: + filter = options.bpf + if not options.novlan and not(filter.startswith('vlan')): + if filter: + filter = '( ' + filter + ' ) or ( vlan and ( ' + filter + ' ) )' + else: + filter = '' # fix for null filter case + + pcount = 0 + for f in args: + pcapreader = pcap.pcap(f) + if options.bpf: + pcapreader.setfilter(filter) + while True: + # Pick a packet + try: + ts, spkt = pcapreader.next() + except: + break # EOF + # Parse IP/Port/Proto Information + try: + pkt = dpkt.ethernet.Ethernet(spkt) + # Only handle IP4/6 + if type(pkt.data) != dpkt.ip.IP and type(pkt.data) != dpkt.ip6.IP6: + continue + # Populate addr tuple + # (proto, sip, sport, dip, dport) + if pkt.data.p == dpkt.ip.IP_PROTO_TCP or pkt.data.p == dpkt.ip.IP_PROTO_UDP: + addr = ( + pkt.data.p, pkt.data.src, pkt.data.data.sport, pkt.data.dst, pkt.data.data.dport) + else: + addr = (pkt.data.p, pkt.data.src, None, pkt.data.dst, None) + except: + continue # Skip Packet if unable to parse + pcount += 1 + # + # Look for existing open flow or start new one + # + thisflow = flows.find(addr) + if thisflow == None: + thisflow = flow(addr) + flows.add(thisflow) + warn("New flow to file: %s" % str(thisflow)) + # + # Write this packet to correct flow + # + thisflow.write(len(spkt), spkt, ts) + # + # Check for TCP reset or fin + # + try: + if pkt.data.data.flags & (dpkt.tcp.TH_RST | dpkt.tcp.TH_FIN): + thisflow.done() + except: + pass # probably not a TCP packet + # + # Cleanup Routine + # + if pcount % 1000 == 0: + flows.cleanup(ts) + # + # Clean exit + # + if ctrl_c_Received: + sys.stderr.write("Exiting on interrupt signal.\n") + sys.exit(0) +''' +flow class + instantiated for each bi-directional flow of data + maintains pcapwriter for each open session +''' +class flow: + + def __init__(self, addr): + self.addr = addr + self.outfilename = localfilename(addr) + self.pcapwriter = output.PCAPWriter(self.outfilename) + self.state = 1 + self.lastptime = 0 + + def write(self, l, spkt, ts): + self.pcapwriter.write(l, spkt, ts) + self.lastptime = ts + + # Mark flow as done (RST/FIN received) + # but don't close the pcap file yet + def done(self): + self.state = 0 + + def __del__(self): + warn("Closing file: %s" % self.outfilename) + + def __str__(self): + return self.outfilename + + def __repr__(self): + return self.outfilename + +''' +flowstore class +''' +class flowstore: + global flowtimeout + + def __init__(self): + self.data = {} # indexed by addr tuple (proto, sip, sport, dip, dport) + + def find(self, addr): + # Fwd Search + if addr in self.data: + return self.data[addr] + # Rev Search + (proto, sip, sport, dip, dport) = addr + if (proto, dip, dport, sip, sport) in self.data: + return self.data[(proto, dip, dport, sip, sport)] + return None + + def add(self, newflow): + self.data[newflow.addr] = newflow + + def cleanup(self, currentPtime): + for k in self.data.keys(): + if self.data[k].state > 0: + continue + # Check timeout + if currentPtime - self.data[k].lastptime > flowtimeout: + del self.data[k] + + +def warn(text): + sys.stdout.write("WARN: " + str(text) + "\n") + + +def normalizedIP(packed): + ip = socket.inet_ntoa(packed) + if '.' in ip: + parts = ip.split('.') + return '.'.join(['%03d' % int(p) for p in parts]) + return ip + + +def localfilename(addr): + global IPprotocols + (proto, sip, sport, dip, dport) = addr + # Convert Numeric Protocol to Text + if proto in IPprotocols: + proto = IPprotocols[proto] + else: + proto = '%05d' % int(proto) + # Convert packed IPs to Text + sip = normalizedIP(sip) + dip = normalizedIP(dip) + sport = '%05d' % int(sport) + dport = '%05d' % int(dport) + # Filename + fname = '_'.join((proto, sip, sport, dip, dport)) + inc = 0 + while True: + fullname = '%s_%03d.pcap' % (fname, inc) + if not os.path.exists(fullname): + return fullname + inc += 1 + + +''' +handle interupt events +''' +def ctrlchandler(signum, frame): + global ctrl_c_Received + ctrl_c_Received = True + sys.stderr.write("Interrupt received. Will exit at next clean break.\n") + +if __name__ == '__main__': + signal.signal(signal.SIGINT, ctrlchandler) + # sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 0) # reopen STDOUT + # unbuffered + try: + main() + except KeyboardInterrupt: + sys.exit(0) From eb51b1b61c9b2075096021e40031c79c59c3c448 Mon Sep 17 00:00:00 2001 From: Adam Maddock Date: Thu, 19 Nov 2015 20:56:20 +0000 Subject: [PATCH 032/166] ElasticSearch Output module --- lib/output/elasticout.py | 212 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 212 insertions(+) create mode 100644 lib/output/elasticout.py diff --git a/lib/output/elasticout.py b/lib/output/elasticout.py new file mode 100644 index 0000000..5f76367 --- /dev/null +++ b/lib/output/elasticout.py @@ -0,0 +1,212 @@ +''' +Created on May 6, 2015 + +@author: amm +''' + +import sys +import output +import dshell +import dfile +import logging +import datetime +import elasticsearch + + +class elasticout(output.TextOutput): + ''' + ElasticSearch Output module + use with --output=elasticout + + e.g. decode -d web *pcap --output elasticout,host=192.168.10.10,index=dshell + + options + ------- + host: : of an Elasticsearch search node + index: Elasticsearch index + geoip: If set to Y, output module won't discard geoip tags + notrim: If set to Y, do not trim any fields from the output + message: If set to Y, add the decoder output message (args[0]) + as a "message" field in elasticsearch + ''' + + ELASTIC_HOST_LIST = [] + ELASTIC_INDEX = None + + # Fields to format as timestamp string + _TIMESTAMP_FIELDS = ( + 'ts', 'starttime', 'endtime', 'request_time', 'response_time') + # Fields to delete (redundant or unnecessary) + _DELETE_FIELDS = ('addr', 'direction', 'clientport', 'serverport', + 'clientip', 'serverip', 'sipint', 'dipint', 'pkttype') + # Dshell geolocation fields + _GEO_FIELDS = ('servercountrycode', 'clientcountrycode', + 'sipcc', 'dipcc', 'clientasn', 'serverasn', 'dipasn', 'sipasn') + + def __init__(self, *args, **kwargs): + + # + # Specified host - prepend to any list hard coded into the module + # + if 'host' in kwargs: + self.ELASTIC_HOST_LIST.insert(0, kwargs['host']) + + # + # Instantiate Elasticsearch client + # + if len(self.ELASTIC_HOST_LIST): + self.es = elasticsearch.Elasticsearch(self.ELASTIC_HOST_LIST) + else: + self.es = elasticsearch.Elasticsearch() + + # + # Index + # + if 'index' in kwargs: + self.ELASTIC_INDEX = kwargs['index'] + + # + # Document Type + # + self.doc_type = 'general' # fallback. should be set by the decoder. + + # + # Handle boolean options + # + self.options = {} + for o in ('geoip', 'notrim', 'message'): + self.options[o] = False + if o in kwargs: + if kwargs[o].upper() in ('Y', 'T', '1', 'YES', 'ON', 'TRUE'): + self.options[o] = True + del kwargs[o] + + # + # Check for existence of preInsert function + # this function allows child classes to have one last access + # to the data -- as will be inserted to Elasticsearch -- before + # the actual insert + # + # Function should return boolean value + # True to proceed with insert + # False to skip + # + # + if 'preInsert' in dir(self): + self.hasPreInsert = True + else: + self.hasPreInsert = False + + # Call parent init + output.TextOutput.__init__(self, **kwargs) + + def alert(self, *args, **kw): + + # + # DocType + # + if 'decoder' in kw: + self.doc_type = kw['decoder'] + del kw['decoder'] + + # + # Remove Common Redundant Fields + # + if not self.options['notrim']: + for name in self._DELETE_FIELDS: + if name in kw: + del kw[name] + + # + # Time Fields + # + # Rename 'ts' to 'starttime' if 'starttime' not present + if 'ts' in kw: + if 'starttime' not in kw: + kw['starttime'] = kw['ts'] + del kw['ts'] + + # + # Remove GEOIP Fields + # + if not self.options['geoip']: + for name in self._GEO_FIELDS: + if name in kw: + del kw[name] + + # + # Perform multiple tasks, iterating across the kw dict + # + for k in kw.keys(): + # + # Convert known timestamp fields to datetime format + # Remove empty fields + # + if k.lower() in self._TIMESTAMP_FIELDS: + if type(kw[k]) == datetime: + continue + elif type(kw[k]) == str: + if len(kw[k]) == 0: + del kw[k] + continue + else: + # dshell has a different default date/time string format than elastic, + # so let's try to parse that into a datetime object + try: + kw[k] = datetime.datetime.strptime( + kw[k], '%Y-%m-%d %H:%M:%S') + except: + pass # if fail, pass it through and let elastic try to parse it + else: + # if not a string, try to + try: + kw[k] = datetime.datetime.fromtimestamp(float(kw[k])) + except: + pass + # + # Get Rid of Dfiles. Must be handled elsewhere. + # + if isinstance(kw[k], dfile.dfile): + del kw[k] + + # + # Message + # + if self.options['message']: + if 'message' not in kw: + kw['message'] = args[0].rstrip() + + # + # Allow child classes to access the data one last time before the insert + # + if self.hasPreInsert: + if not self.preInsert(kw): + return (False, None) + + # + # Insert into elastic + # + if '_id' in kw: + docid = kw['_id'] + del kw['_id'] + es_response = self.es.index( + index=self.ELASTIC_INDEX, id=docid, doc_type=self.doc_type, body=kw) + else: + es_response = self.es.index( + index=self.ELASTIC_INDEX, doc_type=self.doc_type, body=kw) + if es_response['created']: + return (True, es_response) + else: + if es_response['_version'] > 1: + self.log("Possible key collision: %s" % + (str(es_response)), logging.WARN) + # sys.stderr.write(repr(kw)) + else: + self.log("Elasticsearch error: %s" % + (str(es_response)), logging.WARN) + return (False, es_response) + + def write(self, *args, **kwargs): + print "WRITE CALLED (Not implemented in output decoder)" + +obj = elasticout From 5a0018da41db251fd0754514be2bcdb10cf3cc35 Mon Sep 17 00:00:00 2001 From: Adam Maddock Date: Fri, 20 Nov 2015 13:26:37 +0000 Subject: [PATCH 033/166] Added option for doc_type so that this can be specified with a command line argument. In doing so, changed the doc_type variable as used in the alert() function to a local variable; and created a class member called _DOC_TYPE that will store the user-specified type name (default to None which allows dynamic setting of the doc_type from the decoder name). --- lib/output/elasticout.py | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/lib/output/elasticout.py b/lib/output/elasticout.py index 5f76367..1366c7a 100644 --- a/lib/output/elasticout.py +++ b/lib/output/elasticout.py @@ -32,6 +32,7 @@ class elasticout(output.TextOutput): ELASTIC_HOST_LIST = [] ELASTIC_INDEX = None + _DOC_TYPE = None # Fields to format as timestamp string _TIMESTAMP_FIELDS = ( @@ -68,7 +69,8 @@ def __init__(self, *args, **kwargs): # # Document Type # - self.doc_type = 'general' # fallback. should be set by the decoder. + if 'doc_type' in kwargs: + self._DOC_TYPE = kwargs['doc_type'] # # Handle boolean options @@ -105,9 +107,13 @@ def alert(self, *args, **kw): # # DocType # - if 'decoder' in kw: - self.doc_type = kw['decoder'] - del kw['decoder'] + if self._DOC_TYPE: + doc_type = self._DOC_TYPE + elif 'decoder' in kw: + doc_type = kw['decoder'] + del kw['decoder'] + else: + doc_type = 'dshell' # # Remove Common Redundant Fields @@ -190,10 +196,10 @@ def alert(self, *args, **kw): docid = kw['_id'] del kw['_id'] es_response = self.es.index( - index=self.ELASTIC_INDEX, id=docid, doc_type=self.doc_type, body=kw) + index=self.ELASTIC_INDEX, id=docid, doc_type=doc_type, body=kw) else: es_response = self.es.index( - index=self.ELASTIC_INDEX, doc_type=self.doc_type, body=kw) + index=self.ELASTIC_INDEX, doc_type=doc_type, body=kw) if es_response['created']: return (True, es_response) else: From 627529abd5b0f3319aa3968e3ecceb38b69769ed Mon Sep 17 00:00:00 2001 From: Adam Maddock Date: Fri, 20 Nov 2015 15:50:22 +0000 Subject: [PATCH 034/166] Update comments on decoder options. --- lib/output/elasticout.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/output/elasticout.py b/lib/output/elasticout.py index 1366c7a..1e36c0e 100644 --- a/lib/output/elasticout.py +++ b/lib/output/elasticout.py @@ -22,8 +22,9 @@ class elasticout(output.TextOutput): options ------- - host: : of an Elasticsearch search node - index: Elasticsearch index + host: : of an Elasticsearch search node (REQUIRED) + index: Elasticsearch index (REQUIRED) + doc_type: Elasticsearch document type for indexed documents geoip: If set to Y, output module won't discard geoip tags notrim: If set to Y, do not trim any fields from the output message: If set to Y, add the decoder output message (args[0]) From 2c6ff0e375cc2a10b8b866a82ae41ee89ac071d7 Mon Sep 17 00:00:00 2001 From: William Glodek Date: Fri, 20 Nov 2015 11:12:51 -0500 Subject: [PATCH 035/166] initial commit of Emdivi HTTP bot C2 decoder. credit goes to @JPCERTCC --- decoders/malware/emdivi/emdivi_c2.py | 98 ++++++++++++++++++++++++++++ 1 file changed, 98 insertions(+) create mode 100644 decoders/malware/emdivi/emdivi_c2.py diff --git a/decoders/malware/emdivi/emdivi_c2.py b/decoders/malware/emdivi/emdivi_c2.py new file mode 100644 index 0000000..b436ca0 --- /dev/null +++ b/decoders/malware/emdivi/emdivi_c2.py @@ -0,0 +1,98 @@ +from httpdecoder import HTTPDecoder +import urllib +from collections import defaultdict + +''' +JPCERT Coordination Center (JPCERT/CC) released a series of capabilities to +detect and understand compromises involving the Emdivi HTTP bot. Additional +references from JPCERT: + +http://blog.jpcert.or.jp/2015/11/emdivi-and-the-rise-of-targeted-attacks-in-japan.html +https://github.com/JPCERTCC/aa-tools +https://github.com/JPCERTCC/aa-tools/blob/master/emdivi_postdata_decoder.py + +The emdivi_c2 decoder is based on the hardwork of JPCERT/CC and thus deserve +all the credit. +''' + + +class DshellDecoder(HTTPDecoder): + + def __init__(self): + HTTPDecoder.__init__(self, + name='emdivi_c2', + description='deobfuscate Emdivi http c2', + filter='tcp and port 80', + author='bg', + ) + + def decode_payload(self, payload): + '''logic from JPCERTCC emdivi_postdata_decoder.py''' + + decoded = defaultdict() + + if ';' in payload: + delim = ';' + else: + delim = '&' + + fields = [x for x in payload.split(delim) if x] + + for field in fields: + try: + name, value = field.split('=') + except ValueError: + continue + + xor_key = 0x00 + for c in name: + xor_key = (ord(c)) ^ xor_key + + plaintext = '' + for c in urllib.unquote(value): + plaintext += chr(ord(c) ^ xor_key) + + decoded[name] = plaintext + return decoded + + def validate_payload(self, payload_dict): + ''' attempt to validate Emdivi payload. if a valid payload is found, + return the key associated with Emdivi version information ''' + # this check is very simple and will only validate payloads that content like: + # ?VER: t20.09.Koitochu.8530.7965.4444 | NT: 5.1.2600.5512 [en-US] | MEM: 128M | GMT(-6) + + version_info_key = None + for k in payload_dict: + if 'GMT' in payload_dict[k]: + version_info_key = k + break + + return version_info_key + + def HTTPHandler(self, conn, request, response, requesttime, responsetime): + if not request: + return + + decoded = defaultdict() + + if request.method in ('GET', 'POST'): + # first check the body of the GET or POST + if len(request.body) > 0: + decoded.update(self.decode_payload(request.body)) + + if not decoded and 'cookie' in request.headers: + # some traffic had encoded information + # embedded within the Cookie header + decoded.update(self.decode_payload(request.headers['cookie'])) + + if decoded: + version_info_key = self.validate_payload(decoded) + + if version_info_key: + self.alert('{}'.format(decoded[version_info_key]), **conn.info()) + +if __name__ == '__main__': + dObj = DshellDecoder() + print dObj +else: + dObj = DshellDecoder() From 76942c3739a938735d1549a980a2f500c386fe34 Mon Sep 17 00:00:00 2001 From: Adam Maddock Date: Fri, 20 Nov 2015 20:11:11 +0000 Subject: [PATCH 036/166] Change to the way hosts are displayed when hosts are repeated in the URI (such as with proxy CONNECT). --- decoders/http/web.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/decoders/http/web.py b/decoders/http/web.py index 8730f9d..accc47b 100644 --- a/decoders/http/web.py +++ b/decoders/http/web.py @@ -81,7 +81,7 @@ def HTTPHandler(self, conn, request, response, requesttime, responsetime): uploadfile = None requestInfo = '%s %s%s HTTP/%s' % (request.method, - host, + host if host != request.uri else '', # With CONNECT method, the URI is or contains the host, making this redudant request.uri[:self.maxurilen] + '[truncated]' if self.maxurilen > 0 and len( request.uri) > self.maxurilen else request.uri, request.version) From 965b382113c691c2581c191693f19b0e61cb7e7b Mon Sep 17 00:00:00 2001 From: J Date: Mon, 23 Nov 2015 14:26:49 -0500 Subject: [PATCH 037/166] Update README.md Updated README to include elasticsearch module prerequisite --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 989d607..386cd13 100644 --- a/README.md +++ b/README.md @@ -20,6 +20,7 @@ Key features: * [dpkt](https://code.google.com/p/dpkt/), New BSD License * [IPy](https://github.com/haypo/python-ipy), BSD 2-Clause License * [pypcap](https://code.google.com/p/pypcap/), New BSD License +* [elasticsearch-py](https://www.elastic.co/guide/en/elasticsearch/client/python-api/current/index.html), Apache License, Version 2.0 - optional, used only with Dshell's elasticout output module ## Installation From 7c568e8832bc2819153650b503e55f9e965ca6a2 Mon Sep 17 00:00:00 2001 From: Adam Maddock Date: Mon, 23 Nov 2015 20:27:45 +0000 Subject: [PATCH 038/166] Added an --outdir argument, similar to rip-http. --- bin/pcapslice.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/bin/pcapslice.py b/bin/pcapslice.py index 0b78d64..a305edb 100755 --- a/bin/pcapslice.py +++ b/bin/pcapslice.py @@ -34,6 +34,7 @@ def main(): parser = OptionParser( usage="usage: %prog [options] file", version="%prog: PCAP Slicer") parser.add_option('-f', '--bpf', dest='bpf', help='BPF input filter') + parser.add_option('-o', '--outdir', dest='outdir', default='.', help='directory to write output files (Default: current directory)') parser.add_option('--no-vlan', dest='novlan', action="store_true", help='do not examine traffic which has VLAN headers present') parser.add_option('--debug', action='store_true', dest='debug') @@ -187,7 +188,7 @@ def normalizedIP(packed): def localfilename(addr): - global IPprotocols + global IPprotocols, options (proto, sip, sport, dip, dport) = addr # Convert Numeric Protocol to Text if proto in IPprotocols: @@ -203,7 +204,7 @@ def localfilename(addr): fname = '_'.join((proto, sip, sport, dip, dport)) inc = 0 while True: - fullname = '%s_%03d.pcap' % (fname, inc) + fullname = os.path.join(options.outdir, '%s_%03d.pcap' % (fname, inc)) if not os.path.exists(fullname): return fullname inc += 1 From a2bf1504dd30b0f377d4146d8204dac6a7057a09 Mon Sep 17 00:00:00 2001 From: Adam Maddock Date: Mon, 23 Nov 2015 20:59:44 +0000 Subject: [PATCH 039/166] Fix for IPv6 and port-less L4 protocols. --- bin/pcapslice.py | 40 ++++++++++++++++++++++++++-------------- 1 file changed, 26 insertions(+), 14 deletions(-) diff --git a/bin/pcapslice.py b/bin/pcapslice.py index a305edb..1b15a02 100755 --- a/bin/pcapslice.py +++ b/bin/pcapslice.py @@ -69,15 +69,19 @@ def main(): try: pkt = dpkt.ethernet.Ethernet(spkt) # Only handle IP4/6 - if type(pkt.data) != dpkt.ip.IP and type(pkt.data) != dpkt.ip6.IP6: + if type(pkt.data) == dpkt.ip.IP: + proto = pkt.data.p + elif type(pkt.data) == dpkt.ip6.IP6: + proto = pkt.data.nxt + else: continue # Populate addr tuple # (proto, sip, sport, dip, dport) - if pkt.data.p == dpkt.ip.IP_PROTO_TCP or pkt.data.p == dpkt.ip.IP_PROTO_UDP: + if proto == dpkt.ip.IP_PROTO_TCP or proto == dpkt.ip.IP_PROTO_UDP: addr = ( - pkt.data.p, pkt.data.src, pkt.data.data.sport, pkt.data.dst, pkt.data.data.dport) + proto, pkt.data.src, pkt.data.data.sport, pkt.data.dst, pkt.data.data.dport) else: - addr = (pkt.data.p, pkt.data.src, None, pkt.data.dst, None) + addr = (proto, pkt.data.src, None, pkt.data.dst, None) except: continue # Skip Packet if unable to parse pcount += 1 @@ -180,11 +184,14 @@ def warn(text): def normalizedIP(packed): - ip = socket.inet_ntoa(packed) - if '.' in ip: - parts = ip.split('.') - return '.'.join(['%03d' % int(p) for p in parts]) - return ip + if len(packed) == 16: + return socket.inet_ntop(socket.AF_INET6, packed) + else: + ip = socket.inet_ntoa(packed) + if '.' in ip: + parts = ip.split('.') + return '.'.join(['%03d' % int(p) for p in parts]) + return ip def localfilename(addr): @@ -196,12 +203,17 @@ def localfilename(addr): else: proto = '%05d' % int(proto) # Convert packed IPs to Text - sip = normalizedIP(sip) - dip = normalizedIP(dip) - sport = '%05d' % int(sport) - dport = '%05d' % int(dport) + nameparts = [proto, normalizedIP(sip), normalizedIP(dip)] + try: + nameparts.append('%05d' % int(sport)) + except: + pass + try: + nameparts.append('%05d' % int(dport)) + except: + pass # Filename - fname = '_'.join((proto, sip, sport, dip, dport)) + fname = '_'.join(nameparts) inc = 0 while True: fullname = os.path.join(options.outdir, '%s_%03d.pcap' % (fname, inc)) From 2ce818b19eae9a1bc20d7fa68ab3b1ad30a26b78 Mon Sep 17 00:00:00 2001 From: Adam Maddock Date: Mon, 23 Nov 2015 21:02:17 +0000 Subject: [PATCH 040/166] Ran autopep8 on pcapslice --- bin/pcapslice.py | 33 +++++++++++++++++++++------------ 1 file changed, 21 insertions(+), 12 deletions(-) diff --git a/bin/pcapslice.py b/bin/pcapslice.py index 1b15a02..9e7998b 100755 --- a/bin/pcapslice.py +++ b/bin/pcapslice.py @@ -26,6 +26,8 @@ ''' main ''' + + def main(): global options, ctrl_c_Received @@ -34,9 +36,10 @@ def main(): parser = OptionParser( usage="usage: %prog [options] file", version="%prog: PCAP Slicer") parser.add_option('-f', '--bpf', dest='bpf', help='BPF input filter') - parser.add_option('-o', '--outdir', dest='outdir', default='.', help='directory to write output files (Default: current directory)') + parser.add_option('-o', '--outdir', dest='outdir', default='.', + help='directory to write output files (Default: current directory)') parser.add_option('--no-vlan', dest='novlan', action="store_true", - help='do not examine traffic which has VLAN headers present') + help='do not examine traffic which has VLAN headers present') parser.add_option('--debug', action='store_true', dest='debug') (options, args) = parser.parse_args(sys.argv[1:]) @@ -121,6 +124,8 @@ def main(): instantiated for each bi-directional flow of data maintains pcapwriter for each open session ''' + + class flow: def __init__(self, addr): @@ -151,6 +156,8 @@ def __repr__(self): ''' flowstore class ''' + + class flowstore: global flowtimeout @@ -185,13 +192,13 @@ def warn(text): def normalizedIP(packed): if len(packed) == 16: - return socket.inet_ntop(socket.AF_INET6, packed) + return socket.inet_ntop(socket.AF_INET6, packed) else: - ip = socket.inet_ntoa(packed) - if '.' in ip: - parts = ip.split('.') - return '.'.join(['%03d' % int(p) for p in parts]) - return ip + ip = socket.inet_ntoa(packed) + if '.' in ip: + parts = ip.split('.') + return '.'.join(['%03d' % int(p) for p in parts]) + return ip def localfilename(addr): @@ -205,13 +212,13 @@ def localfilename(addr): # Convert packed IPs to Text nameparts = [proto, normalizedIP(sip), normalizedIP(dip)] try: - nameparts.append('%05d' % int(sport)) + nameparts.append('%05d' % int(sport)) except: - pass + pass try: - nameparts.append('%05d' % int(dport)) + nameparts.append('%05d' % int(dport)) except: - pass + pass # Filename fname = '_'.join(nameparts) inc = 0 @@ -225,6 +232,8 @@ def localfilename(addr): ''' handle interupt events ''' + + def ctrlchandler(signum, frame): global ctrl_c_Received ctrl_c_Received = True From 8688be3c707393a2f1509e0f2440dca3c227ca3a Mon Sep 17 00:00:00 2001 From: Adam Maddock Date: Wed, 25 Nov 2015 21:13:45 +0000 Subject: [PATCH 041/166] Changes in info dictionary for kw values in alert() --- decoders/ftp/ftp.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/decoders/ftp/ftp.py b/decoders/ftp/ftp.py index 8acfe58..dbfb055 100644 --- a/decoders/ftp/ftp.py +++ b/decoders/ftp/ftp.py @@ -151,6 +151,7 @@ def blobHandler(self, conn, blob): else: (command, param) = data.rstrip().split(' ', 1) command = command.upper() info['lastcommand'] = command + info['request_time'] = blob.starttime except: return @@ -184,6 +185,7 @@ def blobHandler(self, conn, blob): # Responses else: + info['response_time'] = blob.endtime # # Rollback directory change unless 2xx response # @@ -207,6 +209,9 @@ def blobHandler(self, conn, blob): info.update(conn.info()) msg = 'User: %s, Pass: %s, %s File: %s' % (info['user'], info['pass'], info['file'][0], os.path.join(*info['file'][1:3])) if data[0] not in ('1','2'): msg += ' (%s)' % data.rstrip() + info['ts'] = info['response_time'] + (info['Direction'], info['Path'], info['Filename']) = info['file'] + del info['file'] self.alert(msg, **info) info['file'] = None # From 58b9007e93ee544de044280c0c4b31575d69f38e Mon Sep 17 00:00:00 2001 From: William Glodek Date: Tue, 15 Dec 2015 19:46:19 -0500 Subject: [PATCH 042/166] detect and parse CVE-2015-8562 attempts --- decoders/http/joomla-cve-2015-8562.py | 51 +++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 decoders/http/joomla-cve-2015-8562.py diff --git a/decoders/http/joomla-cve-2015-8562.py b/decoders/http/joomla-cve-2015-8562.py new file mode 100644 index 0000000..fdb93ba --- /dev/null +++ b/decoders/http/joomla-cve-2015-8562.py @@ -0,0 +1,51 @@ +import dshell +import util +from httpdecoder import HTTPDecoder + + +class DshellDecoder(HTTPDecoder): + + def __init__(self): + HTTPDecoder.__init__(self, + name='joomla-cve-2015-8562', + description='detect and dissect malformed HTTP headers targeting Joomla', + filter='tcp and (port 80 or port 8080 or port 8000)', + filterfn=lambda ((sip, sp), (dip, dp)): sp in ( + 80, 8000, 8080) or dp in (80, 8000, 8080), + author='bg', + ) + self.ioc = 'JFactory::getConfig();exit;' + + def parse_cmd(self, data): + start = data.find('"feed_url";')+11 + end = data.find(self.ioc) + chunk = data[start:end] + + try: + cmd = chunk.split(':')[-1] + return cmd + except: + return None + + def HTTPHandler(self, conn, request, response, requesttime, responsetime): + if not request: + return + + if self.ioc not in str(request): + return + + # there is an attempt to exploit Joomla! + + # The Joomla exploit could be sent any HTTP header field + for hdr in request.headers: + if self.ioc in request.headers[hdr]: + cmd = self.parse_cmd(request.headers[hdr]) + if cmd: + self.alert('{} -> {}'.format(hdr, cmd), **conn.info()) + + +if __name__ == '__main__': + dObj = DshellDecoder() + print dObj +else: + dObj = DshellDecoder() From cd0a9a9f1850a6bc459c9821a15c79f3accf157e Mon Sep 17 00:00:00 2001 From: William Glodek Date: Tue, 15 Dec 2015 20:33:58 -0500 Subject: [PATCH 043/166] bug fix --- decoders/http/joomla-cve-2015-8562.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/decoders/http/joomla-cve-2015-8562.py b/decoders/http/joomla-cve-2015-8562.py index fdb93ba..a722e35 100644 --- a/decoders/http/joomla-cve-2015-8562.py +++ b/decoders/http/joomla-cve-2015-8562.py @@ -14,7 +14,7 @@ def __init__(self): 80, 8000, 8080) or dp in (80, 8000, 8080), author='bg', ) - self.ioc = 'JFactory::getConfig();exit;' + self.ioc = 'JFactory::getConfig();exit' def parse_cmd(self, data): start = data.find('"feed_url";')+11 From d37d432d858674a20e42200c699d4854700fc75a Mon Sep 17 00:00:00 2001 From: William Glodek Date: Tue, 15 Dec 2015 20:58:46 -0500 Subject: [PATCH 044/166] added functionality to decode the encoded cmd payload --- decoders/http/joomla-cve-2015-8562.py | 46 ++++++++++++++++++++++----- 1 file changed, 38 insertions(+), 8 deletions(-) diff --git a/decoders/http/joomla-cve-2015-8562.py b/decoders/http/joomla-cve-2015-8562.py index a722e35..6539706 100644 --- a/decoders/http/joomla-cve-2015-8562.py +++ b/decoders/http/joomla-cve-2015-8562.py @@ -2,20 +2,45 @@ import util from httpdecoder import HTTPDecoder +import re + class DshellDecoder(HTTPDecoder): def __init__(self): HTTPDecoder.__init__(self, - name='joomla-cve-2015-8562', - description='detect and dissect malformed HTTP headers targeting Joomla', - filter='tcp and (port 80 or port 8080 or port 8000)', - filterfn=lambda ((sip, sp), (dip, dp)): sp in ( - 80, 8000, 8080) or dp in (80, 8000, 8080), - author='bg', - ) + name='joomla-cve-2015-8562', + description='detect and dissect malformed HTTP headers targeting Joomla', + filter='tcp and (port 80 or port 8080 or port 8000)', + filterfn=lambda ((sip, sp), (dip, dp)): sp in ( + 80, 8000, 8080) or dp in (80, 8000, 8080), + author='bg', + optiondict={ + 'no_eval': {'action': 'store_true', 'help':'attempt to decode chr encoding'} + }, + longdescription=''' +Usage Examples: +--------------- + + decode -d joomla-cve-2015-8562 *.pcap +joomla-cve-2015-8562 2015-12-15 20:17:18 192.168.1.119:43865 <- 192.168.1.139:80 ** x-forwarded-for -> system('touch /tmp/2'); ** + + The module assumes the cmd payload is encoded using chr. To turn this off run: + + decode -d joomla-cve-2015-8562 --joomla-cve-2015-8562_no_eval *.pcap +oomla-cve-2015-8562 2015-12-15 20:17:18 192.168.1.119:43865 <- 192.168.1.139:80 ** x-forwarded-for -> "eval(chr(115).chr(121).chr(115).chr(116).chr(101).chr(109).chr(40).chr(39).chr(116).chr(111).chr(117).chr(99).chr(104).chr(32).chr(47).chr(116).chr(109).chr(112).chr(47).chr(50).chr(39).chr(41).chr(59)); ** +''' + ) + self.ioc = 'JFactory::getConfig();exit' + def attempt_decode(self, cmd): + ptext = '' + for c in re.findall('\d+', cmd): + ptext += chr(int(c)) + return ptext + + def parse_cmd(self, data): start = data.find('"feed_url";')+11 end = data.find(self.ioc) @@ -23,7 +48,11 @@ def parse_cmd(self, data): try: cmd = chunk.split(':')[-1] - return cmd + if self.no_eval: + return cmd + + plaintext_cmd = self.attempt_decode(cmd) + return plaintext_cmd except: return None @@ -32,6 +61,7 @@ def HTTPHandler(self, conn, request, response, requesttime, responsetime): return if self.ioc not in str(request): + # indicator of (potential) compromise is not here return # there is an attempt to exploit Joomla! From b5d02bab35c8b83f0a0dc11cf4eef9c7748bbcfa Mon Sep 17 00:00:00 2001 From: William Glodek Date: Thu, 17 Dec 2015 22:01:18 -0500 Subject: [PATCH 045/166] link to license --- decoders/malware/emdivi/emdivi_c2.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/decoders/malware/emdivi/emdivi_c2.py b/decoders/malware/emdivi/emdivi_c2.py index b436ca0..3f1ed33 100644 --- a/decoders/malware/emdivi/emdivi_c2.py +++ b/decoders/malware/emdivi/emdivi_c2.py @@ -13,6 +13,8 @@ The emdivi_c2 decoder is based on the hardwork of JPCERT/CC and thus deserve all the credit. + +License: https://github.com/JPCERTCC/aa-tools/raw/master/LICENSE.txt ''' From b0165ebaa80d3b0bf158c471068b390e74b11478 Mon Sep 17 00:00:00 2001 From: wglodek Date: Fri, 18 Dec 2015 10:01:10 -0500 Subject: [PATCH 046/166] updated documentation --- decoders/http/joomla-cve-2015-8562.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/decoders/http/joomla-cve-2015-8562.py b/decoders/http/joomla-cve-2015-8562.py index 6539706..691d8d1 100644 --- a/decoders/http/joomla-cve-2015-8562.py +++ b/decoders/http/joomla-cve-2015-8562.py @@ -16,7 +16,7 @@ def __init__(self): 80, 8000, 8080) or dp in (80, 8000, 8080), author='bg', optiondict={ - 'no_eval': {'action': 'store_true', 'help':'attempt to decode chr encoding'} + 'raw_payload': {'action': 'store_true', 'help':'return the raw payload (do not attempt to decode chr encoding)'} }, longdescription=''' Usage Examples: @@ -48,7 +48,7 @@ def parse_cmd(self, data): try: cmd = chunk.split(':')[-1] - if self.no_eval: + if self.raw_payload: return cmd plaintext_cmd = self.attempt_decode(cmd) From bece2215bba0acd38affc077e35cc47fbe4beb48 Mon Sep 17 00:00:00 2001 From: wglodek Date: Tue, 22 Dec 2015 10:22:13 -0500 Subject: [PATCH 047/166] updated LICENSE --- decoders/malware/emdivi/emdivi_c2.py | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/decoders/malware/emdivi/emdivi_c2.py b/decoders/malware/emdivi/emdivi_c2.py index 3f1ed33..119058c 100644 --- a/decoders/malware/emdivi/emdivi_c2.py +++ b/decoders/malware/emdivi/emdivi_c2.py @@ -14,7 +14,22 @@ The emdivi_c2 decoder is based on the hardwork of JPCERT/CC and thus deserve all the credit. -License: https://github.com/JPCERTCC/aa-tools/raw/master/LICENSE.txt +LICENSE +Copyright (C) 2015 JPCERT Coordination Center. All Rights Reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, +this list of conditions and the following acknowledgments and disclaimers. +2. Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following acknowledgments and disclaimers in +the documentation and/or other materials provided with the distribution. +3. Products derived from this software may not include "JPCERT Coordination +Center" in the name of such derived product, nor shall "JPCERT Coordination +Center" be used to endorse or promote products derived from this software +without prior written permission. For written permission, please contact +pr@jpcret.or.jp. ''' From 4900b4081814d3a0fce852be816198552aade650 Mon Sep 17 00:00:00 2001 From: dev195 Date: Thu, 17 Mar 2016 11:02:06 -0400 Subject: [PATCH 048/166] added 'setup' function to output modules --- bin/decode.py | 4 +++- lib/output/colorout.py | 13 ++++++++----- lib/output/csvout.py | 26 +++++++++++++++----------- lib/output/output.py | 8 ++++++++ 4 files changed, 34 insertions(+), 17 deletions(-) diff --git a/bin/decode.py b/bin/decode.py index 5df5ed0..86d26c3 100755 --- a/bin/decode.py +++ b/bin/decode.py @@ -309,7 +309,6 @@ def initDecoderOptions(decoder, out, options, decoder_args, decoder_options): # global # provide global output module under alternate name decoder.globalout = out - # decoder.out.__init__(fh=out.fh) #re-init the decoder try: # If the decoder's default output doesn't have a filehandle set, # use the user provided one @@ -325,6 +324,9 @@ def initDecoderOptions(decoder, out, options, decoder_args, decoder_options): # set the logger decoder.out.logger = logging.getLogger(decoder.name) + # perform any output module setup before processing data + decoder.out.setup() + # set output format string, or reset to default # do not override --oformat specified string if decoder.format and not options.oformat: diff --git a/lib/output/colorout.py b/lib/output/colorout.py index f34faab..34f7716 100644 --- a/lib/output/colorout.py +++ b/lib/output/colorout.py @@ -110,11 +110,6 @@ def __init__(self, *args, **kwargs): # Call parent init output.TextOutput.__init__(self, format=fmtstr, **kwargs) - self.setColorMode() - - # Write Header - if self._COLORMODE == 'HTML': - self._htmlwrite(self._HTMLHeader(self.title)) # In HTML mode, if we get any single call # to write() with the time option set, we will set @@ -123,6 +118,14 @@ def __init__(self, *args, **kwargs): # until toggled by the user self._htmldisplaytimes = False + def setup(self): + # Write Header + self.setColorMode() + + if self._COLORMODE == 'HTML': + self._htmlwrite(self._HTMLHeader(self.title)) + + def setColorMode(self): # Determine output mode if self.fh == sys.stdout and not self.htmlgenerator and not self.html: diff --git a/lib/output/csvout.py b/lib/output/csvout.py index 7b87b84..ebbdbc2 100644 --- a/lib/output/csvout.py +++ b/lib/output/csvout.py @@ -29,10 +29,10 @@ def __init__(self, *args, **kwargs): args will have the name of the module as args[0], anything else after ''' # start with a set of default fields - fields = self._DEFAULT_FIELDS + self.fields = self._DEFAULT_FIELDS if 'format' in kwargs: - fields = [] + self.fields = [] fmtstr = kwargs['format'] del kwargs['format'] # don't let base class process this else: @@ -40,11 +40,13 @@ def __init__(self, *args, **kwargs): # set delimiter if 'delim' in kwargs: - delim = kwargs['delim'] - if delim.lower() == 'tab': - delim = "\t" + self.delim = kwargs['delim'] + if self.delim.lower() == 'tab': + self.delim = "\t" else: - delim = self._DEFAULT_DELIM + self.delim = self._DEFAULT_DELIM + + self.noheader = 'noheader' in kwargs # parse args as fields if len(args): @@ -53,19 +55,21 @@ def __init__(self, *args, **kwargs): f, t = a.split(':') # split on field:type except: f, t = a, 's' # default to string type - fields.append((f, t)) + self.fields.append((f, t)) # build format string to pass to textoutput if fmtstr: - fmtstr += delim - fmtstr += delim.join(['%%(%s)%s' % (f, t) for f, t in fields]) + fmtstr += self.delim + fmtstr += self.delim.join(['%%(%s)%s' % (f, t) for f, t in self.fields]) # everything else is exactly like the text output module output.TextOutput.__init__(self, format=fmtstr, **kwargs) + + def setup(self): # print header if not suppressed - if self.fh and 'noheader' not in kwargs: - self.fh.write('#' + delim.join([f[0] for f in fields]) + "\n") + if self.fh and not self.noheader: + self.fh.write('#' + self.delim.join([f[0] for f in self.fields]) + "\n") '''NOTE: output modules return obj=reference to the CLASS instead of a dObj=instance so we can init with args''' diff --git a/lib/output/output.py b/lib/output/output.py index 9088765..41a2122 100644 --- a/lib/output/output.py +++ b/lib/output/output.py @@ -197,6 +197,14 @@ def dispatch(self, m, *args, **kwargs): if m == 'dump': self.dump(*args, **kwargs) + def setup(self): + """ + Perform any additional setup outside of the standard __init__. + Runs after command-line arguments are parsed, but before decoders are run. + For example, printing header data to the outfile. + """ + pass + class FileOutput(Output): From 8e5c309b75720bc493d69f1a883e9754177787a0 Mon Sep 17 00:00:00 2001 From: dev195 Date: Mon, 4 Apr 2016 12:51:26 -0400 Subject: [PATCH 049/166] Updated decode logic to better handle MAC addresses (traviswparker, dev195) --- lib/dshell.py | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/lib/dshell.py b/lib/dshell.py index 9dac78d..bf20e29 100644 --- a/lib/dshell.py +++ b/lib/dshell.py @@ -423,6 +423,14 @@ def decode(self, *args, **kw): raise Exception('packet truncated', pktlen, pktdata) # decode with the L2 decoder (probably Ether) pkt = self.l2decoder(pktdata) + # attempt to collect MAC addresses + if type(pkt) == dpkt.ethernet.Ethernet: + try: + smac = "%02x:%02x:%02x:%02x:%02x:%02x" % (struct.unpack("BBBBBB", pkt.src)) + dmac = "%02x:%02x:%02x:%02x:%02x:%02x" % (struct.unpack("BBBBBB", pkt.dst)) + except struct.error: # couldn't get MAC address + smac, dmac = None, None + kw.update(smac=smac, dmac=dmac) # strip any intermediate layers (PPPoE, etc) for _ in xrange(int(self.striplayers)): pkt = pkt.data @@ -504,13 +512,6 @@ def rawHandler(self, pktlen, pkt, ts, **kwargs): if 6to4, unencaps the IPv6 If IP/IP6, hands off to IPDecoder via IPHandler()''' try: - # If this packet has an Ethernet header, try and grab the MAC address - if type(pkt) == dpkt.ethernet.Ethernet: - try: - smac = "%02x:%02x:%02x:%02x:%02x:%02x" % (struct.unpack("BBBBBB", pkt.src)) - dmac = "%02x:%02x:%02x:%02x:%02x:%02x" % (struct.unpack("BBBBBB", pkt.dst)) - except struct.error: # couldn't get MAC address - smac, dmac = None, None # if this is an IPv4 packet, defragment, decode and hand it off if type(pkt.data) == dpkt.ip.IP: if self.defrag: @@ -538,7 +539,6 @@ def rawHandler(self, pktlen, pkt, ts, **kwargs): proto=self.IP_PROTO_MAP.get( pkt.p, pkt.p), sipint=sipint, dipint=dipint, - smac=smac, dmac=dmac, **kwargs) if pkt and type(pkt.data) == dpkt.ip6.IP6: pkt = pkt.data # no defrag of ipv6 @@ -560,7 +560,6 @@ def rawHandler(self, pktlen, pkt, ts, **kwargs): pkttype=dpkt.ethernet.ETH_TYPE_IP6, proto=self.IP_PROTO_MAP.get(pkt.nxt, pkt.nxt), sipint=sipint, dipint=dipint, - smac=smac, dmac=dmac, **kwargs) except Exception, e: self._exc(e) From 743361e1180225ede0337e671db077eb5bd6ba19 Mon Sep 17 00:00:00 2001 From: dev195 Date: Thu, 21 Apr 2016 09:43:09 -0400 Subject: [PATCH 050/166] Added new partner to README --- README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 386cd13..dd62447 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,11 @@ # Dshell -An extensible network forensic analysis framework. Enables rapid development of plugins to support the dissection of network packet captures. +An extensible network forensic analysis framework. Enables rapid development of plugins to support the dissection of network packet captures. Key features: -* Robust stream reassembly +* Robust stream reassembly * IPv4 and IPv6 support * Custom output handlers * Chainable decoders @@ -52,6 +52,7 @@ Key features: Below are repositories from partners Dshell has worked together with. * [DeKrych/Dshell-plugins](https://github.com/DeKrych/Dshell-plugins) +* [terry-wen/Network-Visualization-Project](https://github.com/terry-wen/Network-Visualization-Project) ## Usage Examples From 42b146c9f98bfdb0251115454a397d4bce1ec90c Mon Sep 17 00:00:00 2001 From: "D((!T3ch$0ln$" Date: Fri, 3 Jun 2016 13:58:09 -0400 Subject: [PATCH 051/166] End offset for blob update logic was incomplete --- lib/dshell.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/dshell.py b/lib/dshell.py index bf20e29..52250fb 100644 --- a/lib/dshell.py +++ b/lib/dshell.py @@ -981,7 +981,7 @@ def update(self, ts, data, offset=None): if ts > self.endtime: self.endtime = ts # update the end offset if this packet goes at the end - if offset >= self.endoffset: + if (offset + len(data)) & self.MAX_OFFSET >= self.endoffset: self.endoffset = (offset + len(data)) & self.MAX_OFFSET def __repr__(self): From 0e7ce45b369bfc9cffba6c0ba55811292ac4f9ce Mon Sep 17 00:00:00 2001 From: "D((!T3ch$0ln$" Date: Fri, 3 Jun 2016 14:26:46 -0400 Subject: [PATCH 052/166] Fix for retransmission bytes that are only partial previous messages --- lib/dshell.py | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/lib/dshell.py b/lib/dshell.py index 52250fb..c266e84 100644 --- a/lib/dshell.py +++ b/lib/dshell.py @@ -907,17 +907,20 @@ def __repr__(self): def update(self, ts, direction, data, offset=None): # if we have no blobs or direction changes, start a new blob lastblob = None - if direction != self.direction: - self.direction = direction - # if we have a finished blob, return it - if self.blobs: - lastblob = self.blobs[-1] - # for tracking offsets across blobs (TCP) set the startoffset of this blob to what we know it should be - # this may not necessarily be the offset of THIS data if packets - # are out of order - self.blobs.append( - Blob(ts, direction, startoffset=self.nextoffset[direction])) - self.blobs[-1].update(ts, data, offset=offset) # update latest blob + if len(self.blobs) > 1 and self.blobs[-2].startoffset <= offset < self.blobs[-2].endoffset: + self.blobs[-2].update(ts,data,offset=offset) + else: + if direction != self.direction: + self.direction = direction + # if we have a finished blob, return it + if self.blobs: + lastblob = self.blobs[-1] + # for tracking offsets across blobs (TCP) set the startoffset of this blob to what we know it should be + # this may not necessarily be the offset of THIS data if packets + # are out of order + self.blobs.append( + Blob(ts, direction, startoffset=self.nextoffset[direction])) + self.blobs[-1].update(ts, data, offset=offset) # update latest blob if direction == 'cs': self.clientpackets += 1 self.clientbytes += len(data) From 1dc0d66e87f63d007437a0e66100ba71d6274e1f Mon Sep 17 00:00:00 2001 From: DeKrych Date: Mon, 6 Jun 2016 11:27:39 -0400 Subject: [PATCH 053/166] Added Bitcoin and NBNS decoders, updated DHCP desc Changed dhcp decoder's description for uniformity. Added the bitcoin and nbns decoders which were posted on my repo: DeKrych/Dshell-plugins. Updated their descriptions as well, and minor changes to comments for clarity. --- decoders/dhcp/dhcp.py | 2 +- decoders/nbns/nbns.py | 139 +++++++++++++++++ decoders/protocol/bitcoin.py | 284 +++++++++++++++++++++++++++++++++++ 3 files changed, 424 insertions(+), 1 deletion(-) create mode 100644 decoders/nbns/nbns.py create mode 100644 decoders/protocol/bitcoin.py diff --git a/decoders/dhcp/dhcp.py b/decoders/dhcp/dhcp.py index 6795a3d..7073bf5 100644 --- a/decoders/dhcp/dhcp.py +++ b/decoders/dhcp/dhcp.py @@ -9,7 +9,7 @@ class DshellDecoder(dshell.UDPDecoder): def __init__(self): dshell.UDPDecoder.__init__(self, name='dhcp', - description='extract client information from DHCP messages', + description='Extract client information from DHCP messages', longdescription=""" The dhcp decoder will extract the Transaction ID, Client Hostname, and Client MAC address from every UDP DHCP packet found in the given pcap diff --git a/decoders/nbns/nbns.py b/decoders/nbns/nbns.py new file mode 100644 index 0000000..55e9bed --- /dev/null +++ b/decoders/nbns/nbns.py @@ -0,0 +1,139 @@ +import dpkt +import dshell +from struct import unpack + + +# A few common NBNS Protocol Info Opcodes +# Due to a typo in RFC 1002, 0x9 is also acceptable, but rarely used +# for 'NetBios Refresh' +# 'NetBios Multi-Homed Name Regsitration' (0xf) was added after the RFC +nbns_op = { 0: 'NB_NAME_QUERY', + 5: 'NB_REGISTRATION', + 6: 'NB_RELEASE', + 7: 'NB_WACK', + 8: 'NB_REFRESH', + 9: 'NB_REFRESH', + 15: 'NB_MULTI_HOME_REG' } + + +class DshellDecoder(dshell.UDPDecoder): + + def __init__(self): + dshell.UDPDecoder.__init__(self, + name='nbns', + description='Extract client information from NBNS traffic', + longdescription=""" +The nbns (NetBIOS Name Service) decoder will extract the Transaction ID, Protocol Info, +Client Hostname, and Client MAC address from every UDP NBNS packet found in the given +pcap using port 137. UDP is the standard transport protocol for NBNS traffic. +This filter pulls pertinent information from NBNS packets. + +Examples: + + General usage: + + decode -d nbns + + This will display the connection info including the timestamp, + the source IP, destination IP, Transaction ID, Protocol Info, + Client Hostname, and the Client MAC address in a tabular format. + + + Malware Traffic Analysis Exercise Traffic from 2014-12-08 where a user was hit with a Fiesta exploit kit: + + We want to find out more about the infected machine, and some of this information can be pulled from NBNS traffic + + decode -d nbns /2014-12-08-traffic-analysis-exercise.pcap + + OUTPUT (first few packets): + nbns 2014-12-08 18:19:13 192.168.204.137:137 -- 192.168.204.2:137 ** + Transaction ID: 0xb480 + Info: NB_NAME_QUERY + Client Hostname: WPAD + Client MAC: 00:0c:29:9d:b8:6d + ** + nbns 2014-12-08 18:19:14 192.168.204.137:137 -- 192.168.204.2:137 ** + Transaction ID: 0xb480 + Info: NB_NAME_QUERY + Client Hostname: WPAD + Client MAC: 00:0c:29:9d:b8:6d + ** + nbns 2014-12-08 18:19:16 192.168.204.137:137 -- 192.168.204.2:137 ** + Transaction ID: 0xb480 + Info: NB_NAME_QUERY + Client Hostname: WPAD + Client MAC: 00:0c:29:9d:b8:6d + ** + nbns 2014-12-08 18:19:17 192.168.204.137:137 -- 192.168.204.255:137 ** + Transaction ID: 0xb480 + Info: NB_NAME_QUERY + Client Hostname: WPAD + Client MAC: 00:0c:29:9d:b8:6d + """, + filter='udp and port 137', + author='dek', + ) + self.mac_address = None + self.client_hostname = None + self.xid = None + self.prot_info = None + + + def packetHandler(self, udp, data): + try: + nbns_packet = dpkt.netbios.NS(data) + except (dpkt.dpkt.UnpackError, IndexError) as e: + self.warn('{}: dpkt could not parse session data \ + (NBNS packet not found)'.format(str(e))) + return + + + # Extract the Client hostname from the connection data + # It is represented as 32-bytes half-ASCII + try: + nbns_name = unpack('32s', data[13:45])[0] + except error as e: + self.warn('{}: (NBNS packet not found)'.format(str(e))) + return + + + # Decode the 32-byte half-ASCII name to its 16 byte NetBIOS name + try: + self.client_hostname = dpkt.netbios.decode_name(nbns_name) + + # For uniformity, strip excess byte + self.client_hostname = self.client_hostname[0:-1] + except ValueError as e: + self.warn('{}: Hostname in improper format \ + (NBNS packet not found)'.format(str(e))) + return + + + # Extract the Transaction ID from the NBNS packet + self.xid = hex(nbns_packet.id) + + # Extract the opcode info from the NBNS Packet + op = nbns_packet.op + # Remove excess bits + op = (op >> 11) & 15 + + # Extract protocol info if present in the payload + if nbns_op[op]: + self.prot_info = nbns_op[op] + else: + self.prot_info = hex(nbns_packet.op) + + # Extract the MAC address from the ethernet layer of the packet + self.mac_address = udp.smac + + + if self.xid and self.prot_info and self.client_hostname and self.mac_address: + self.alert('\n\tTransaction ID:\t\t{:<8} \n\tInfo:\t\t\t{:<16} \n\tClient Hostname:\t{:<16} \n\tClient MAC:\t\t{:<18}\n'.format( + self.xid, self.prot_info, self.client_hostname, self.mac_address), **udp.info()) + + +if __name__ == '__main__': + dObj = DshellDecoder() + print dObj +else: + dObj = DshellDecoder() diff --git a/decoders/protocol/bitcoin.py b/decoders/protocol/bitcoin.py new file mode 100644 index 0000000..37035bc --- /dev/null +++ b/decoders/protocol/bitcoin.py @@ -0,0 +1,284 @@ +import dshell +import util +import binascii +import json +from struct import unpack + +# Magic values used to determine Bitcoin Network Type +# Bitcoin Testnet is an alternative blockchain used for testing +MAGIC_VALS = {'F9 BE B4 D9': 'BITCOIN-MAIN', + 'FA BF B5 DA': 'BITCOIN-TESTNET', + '0B 11 09 07': 'BITCOIN-TESTNET3'} + + +class DshellDecoder(dshell.TCPDecoder): + + def __init__(self): + dshell.TCPDecoder.__init__(self, + name='bitcoin', + description='Extract Bitcoin traffic, including Stratum mining protocol (pooled) traffic', + longdescription=''' +The bitcoin decoder will extract any Bitcoin traffic attempting to find and output: + Client/server IP addresses, src/dst port numbers, MAC addresses of the machines + used in the Bitcoin communication/transactions, timestamps of the packets, + packet payload sizes in KB, and the Network type + ('Bitcoin Main' if Bitcoin data traffic) + +Additionally for Stratum mining, it will attempt to extract: + Bitcoin miner being used, transaction methods used in each connection + (mining.notify, mining.authorize, mining.get_transaction, mining.submit, etc.), + User ID (Auth ID) used to access the Bitcoin mining pool, and possibly the password + used to connect to the pool if it is stored in the JSON of the payload. + + Also, the: + range of job IDs (per connection), previous block hash, generation transaction (part 1), + generation transaction (part 2), merkle tree branches (hashes), block version, + and the hash difficulty (n-bits) + (The generation transactions and merkle tree branches are only optionally outputted + to a file: See Example (3) below) + + Note (1): The first time that all of this Stratum mining information is + collected (per connection), all of the packets decoded after this + point from within the same connection (same exact sip, dip, sport, dport) + will continue to output the same collection of information since it + will be the same. + + Note (2): The gen_tx1 and gen_tx2 fields enable the miner to build the coinbase + transaction for the block by concatentating gen_tx1, the extranonce1 + at the start of gen_tx1, the extranonce2 generated by the miner, and + gen_tx2 (hashes with scriptPubKeys) + + Note (3): Some pools recommend miners use their Bitcoin wallet ID + (address used for payment) as their 'Auth ID'. This will be easily + spotted as it is an address consisting of 26-35 alphanumeric characters, + and it always begins with either the number '1' or '3' + + + For additional information: + Bitcoin Protocol: + Stratum Mining Protocol: + + +--------Main ports / Some secondary ports used for Bitcoin Traffic--------- + Bitcoin Main traffic uses port 8333 + Bitcoin Testnet uses port 18333 + Several pools use ports 3333, 8332, 8337 + The other ports checked are known ports used by specific BTC mining pools + Other Bitcoin pools utilize alternate ports (even 80 / 443) + + +Examples: + + (1) Basic usage: + + decode -d bitcoin + + (2) If pcap starts in middle of connection (then we need to ignore TCP handshake): + + decode -d bitcoin --bitcoin_ignore_handshake + + (3) Saving Generation Transaction Data and Merkle Branches to a specified file: + + decode -d bitcoin --bitcoin_gentx='foo.txt.' +''', + filter='''tcp and port (3332 or 3333 or 3334 or 3335 or + 4008 or 4012 or 4016 or 4024 or + 4032 or 4048 or 4064 or 4096 or + 4128 or 4256 or 5050 or 7033 or + 7065 or 7129 or 7777 or 8332 or + 8333 or 8334 or 8336 or 8337 or + 8344 or 8347 or 8361 or 8888 or + 9332 or 9337 or 9999 or 11111 or + 12222 or 17777 or 18333)''', + author='dek', + optiondict={ + 'gentx' : {'type' : 'str', 'default' : '', 'help' : 'The name of the file to output the fields used to generate the block transaction (gen_tx1, gen_tx2, merkle_branches).'}, + } + ) + self.auth_ids = {} + self.notify_params = {} + self.methods = {} + self.miners = {} + self.job_ids = {} + self.smac = None + self.dmac = None + self.bc_net = None + self.size = 0 + self.JSON = False + self.NOTIFY = False + + + # blobHandler to reassemble the packets in the traffic + # Bitcoin traffic uses TCP + def blobHandler(self, conn, blob): + + try: + data = blob.data() + except: + self.warn('could not parse session data') + return + + # Only continue if the packet contains data + if not data: + return + + # Default mining.notify fields to None + job_id = None + prev_blk_hash = None + gen_tx1 = None + gen_tx2 = None + merkle_branches = None + blk_ver = None + difficulty = None + curr_time = None + clean_jobs = None + + # If the payload contains JSON + if data.startswith('{"'): + self.JSON = True + try: + # split JSON objects by newline + for rawjs in data.split("\n"): + if rawjs: + js = json.loads(rawjs) + try: + if "method" in js and js["method"]: + # Create a dictionary of sets of mining methods + # indexed by their associated conn.addr (sip, dip, sport, dport) + self.methods.setdefault(conn.addr, set([])).add(js["method"]) + + if js["method"] == "mining.subscribe": + self.miners[conn.addr] = js["params"][0] + + if js["method"] == "mining.authorize": + if "params" in js and js['params'][0]: + # Grab the Bitcoin User ID (sometimes a wallet id) + # which is being authorized + self.auth_ids[conn.addr] = js["params"][0] + + if js['params'][1]: + self.auth_ids[conn.addr] = "".join(( + self.auth_ids[conn.addr], " / ", str(js['params'][1]) )) + + if js["method"] == "mining.notify": + self.NOTIFY = True + if "params" in js and js['params']: + job_id, prev_blk_hash, gen_tx1, gen_tx2, merkle_branches, blk_ver, difficulty, curr_time, clean_jobs = js['params'] + self.job_ids.setdefault(conn.addr, []).append(job_id) + self.notify_params[conn.addr] = [self.job_ids, prev_blk_hash, gen_tx1, + gen_tx2, merkle_branches, + blk_ver, difficulty, curr_time, + clean_jobs] + + except KeyError as e: + self.warn("{} - Error extracting auth ID".format(str(e))) + except ValueError as e: + self.warn('{} - json data not found'.format(str(e))) + return + + # Grab the first 4 bytes of the payload to search for the magic values + # used to determine which Bitcoin network is being accessed + # Additionally, reformat bytes + try: + magic_val = binascii.hexlify(data[0:4]).upper() + magic_val = ' '.join([magic_val[i:i+2] for i in range(0, len(magic_val), 2)]) + except: + self.warn('could not parse session data') + return + + # Attempt to translate first 4 bytes of payload + # into a Bitcoin (bc) network type + try: + self.bc_net = str(MAGIC_VALS[magic_val]) + except: + self.bc_net = 'N/A' + + + # Pull pertinent information from packet's contents + self.size = '{0:.2f}'.format((len(blob.data())/1024.0)) + self.smac = conn.smac + self.dmac = conn.dmac + + + # Truncate the list Job IDs per connection for printing purposes if JSON + # data was found in the blob + if self.JSON and self.NOTIFY: + jids_end = (len(self.notify_params[conn.addr][0][conn.addr]) - 1) + if jids_end >= 1: + self.notify_params[conn.addr][0][conn.addr] = [ self.notify_params[conn.addr][0][conn.addr][0], + '...', + self.notify_params[conn.addr][0][conn.addr][jids_end] ] + elif jids_end >= 0: + self.notify_params[conn.addr][0][conn.addr] = [self.notify_params[conn.addr][0][conn.addr][0]] + + # Reset the JSON data found in the current blob boolean + # and the mining.notify method type found in payload boolean + self.JSON = False + self.NOTIFY = False + + # If able to pull the Bitcoin Pool User ID (sometimes a wallet ID) + # Also if the transcation is mining.notify (seen in Stratum mining) + # then output the current Block information + if (self.size and self.smac and self.dmac and + self.miners.get(conn.addr, None) and self.methods.get(conn.addr, None) and self.auth_ids.get(conn.addr, None) + and self.notify_params.get(conn.addr, None) and not self.gentx): + self.alert("\n\tSRC_MAC: \t{0:<20} \n\tDST_MAC: \t{1:<20} \n\tSIZE: \t\t{2:>3}KB\n\t" + "MINER: \t\t{3:<20} \n\tMETHODS: \t{4:<25} \n\tUSER ID/PW: \t{5:<50}\n\t" + "JOB IDs: \t{6:<20} \n\tPREV BLK HASH: \t{7:<65} \n\tBLOCK VER: \t{8:<15}\n\t" + "HASH DIFF: \t{9:<10}\n\n".format( + self.smac, self.dmac, self.size, + self.miners[conn.addr], self.methods[conn.addr], self.auth_ids[conn.addr], + self.notify_params[conn.addr][0][conn.addr], self.notify_params[conn.addr][1], + self.notify_params[conn.addr][5], self.notify_params[conn.addr][6]), + ts=blob.starttime, sip=conn.sip, dip=conn.dip, sport=conn.sport, + dport=conn.dport, direction=blob.direction) + + + # If able to pull the Bitcoin Pool User ID (sometimes a wallet ID) + # Also if the transcation is mining.notify (seen in Stratum mining) and the user + # specifies that they want to save the fields used to generate the block transaction + # (gen_tx1, gen_tx2 (hashes with scriptPubKeys), merkle tree branches), then + # output all information possible, and write the gentx information to the specified file + elif (self.size and self.smac and self.dmac and + self.miners.get(conn.addr, None) and self.methods.get(conn.addr, None) and self.auth_ids.get(conn.addr, None) + and self.notify_params.get(conn.addr, None) and self.gentx): + self.alert("\n\tSRC_MAC: \t{0:<20} \n\tDST_MAC: \t{1:<20} \n\tSIZE: \t\t{2:>3}KB\n\t" + "MINER: \t\t{3:<20} \n\tMETHODS: \t{4:<25} \n\tUSER ID/PW: \t{5:<50}\n\t" + "JOB IDs: \t{6:<20} \n\tPREV BLK HASH: \t{7:<65} \n\tBLOCK VER: \t{8:<15}\n\t" + "HASH DIFF: \t{9:<10}\n\n".format( + self.smac, self.dmac, self.size, + self.miners[conn.addr], self.methods[conn.addr], self.auth_ids[conn.addr], + self.notify_params[conn.addr][0][conn.addr], self.notify_params[conn.addr][1], + self.notify_params[conn.addr][5], self.notify_params[conn.addr][6]), + ts=blob.starttime, sip=conn.sip, dip=conn.dip, sport=conn.sport, + dport=conn.dport, direction=blob.direction) + + # Write the verbose block information (gen tx1/2, merkle branches) gathered + # from mining.notify payloads to the command-line specified output file + # The extra information (JOB ID, BLOCK VER, etc.) will be useful in matching the + # information outputted by the alerts to the payload containing the + # generation transaction info and merkle branches + fout = open(self.gentx, "a+") + fout.write(("\nJOB IDs: \t\t{0:<20} \nPREV BLK HASH: \t{1:<65} \n\nGEN TX1: \t\t{2:<20}" + "\n\nGEN TX2: \t\t{3:<20} \n\nMERKLE BRANCHES: {4:<20} \n\nBLOCK VER: \t\t{5:<20}" + "\nHASH DIFF: \t\t{6:<10}\n").format( + self.notify_params[conn.addr][0][conn.addr], self.notify_params[conn.addr][1], + self.notify_params[conn.addr][2], self.notify_params[conn.addr][3], + self.notify_params[conn.addr][4], self.notify_params[conn.addr][5], + self.notify_params[conn.addr][6])) + fout.write(("\n" + "-"*100)*2) + + + # Else if we dont have Bitcoin User IDs, or Block information + # and the user doesn't want verbose block information (gentx) + elif (self.size and self.smac and self.dmac and self.bc_net): + self.alert("\n\tNETWORK: \t{0:<15} \n\tSRC_MAC: \t{1:<20} \n\tDST_MAC: \t{2:<20} \n\tSIZE: \t\t{3:>3}KB\n\n".format( + self.bc_net, self.smac, self.dmac, self.size), ts=blob.starttime, sip=conn.sip, + dip=conn.dip, sport=conn.sport, dport=conn.dport, direction=blob.direction) + + +if __name__ == '__main__': + dObj = DshellDecoder() + print dObj +else: + dObj = DshellDecoder() From bf9725dc5c6789c0955db5fd295ee9ffedf8023b Mon Sep 17 00:00:00 2001 From: J Date: Thu, 1 Sep 2016 08:39:23 -0400 Subject: [PATCH 054/166] Fixed typo in reverse-flow.py Removed errant percent sign in reverse-flow.py. --- decoders/flows/reverse-flow.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/decoders/flows/reverse-flow.py b/decoders/flows/reverse-flow.py index d9545bd..84c2e45 100644 --- a/decoders/flows/reverse-flow.py +++ b/decoders/flows/reverse-flow.py @@ -52,7 +52,7 @@ def preModule(self): self.threshold = 3.0 elif not self.threshold: self.warn( - "Displaying all client-server transmissions (threshold: {0})".format%(self.threshold)) + "Displaying all client-server transmissions (threshold: {0})".format(self.threshold)) def connectionHandler(self, conn): if conn.clientbytes < self.minimum: From 5212e8eddf55a5937eca04b23f67b2f4f56ce92b Mon Sep 17 00:00:00 2001 From: "D((!T3ch$0ln$" Date: Wed, 7 Sep 2016 12:33:30 -0400 Subject: [PATCH 055/166] Fix to prevent reused ports from the previous TCP connection. TCP handshaking fix for SYN flag. --- lib/dshell.py | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/lib/dshell.py b/lib/dshell.py index c266e84..f3734cb 100644 --- a/lib/dshell.py +++ b/lib/dshell.py @@ -681,6 +681,8 @@ def __init__(self, **kwargs): IPDecoder.__init__(self, **kwargs) self.optiondict['ignore_handshake'] = { 'action': 'store_true', 'help': 'ignore TCP handshake'} + self.serverclosed = False + self.clientclosed = False def IPHandler(self, addr, pkt, ts, **kwargs): '''IPv4 dispatch''' @@ -697,14 +699,25 @@ def TCP(self, addr, tcp, ts, **kwargs): try: # close connection - if tcp.flags & (dpkt.tcp.TH_FIN | dpkt.tcp.TH_RST): - conn = self.find(addr) + conn = self.find(addr) + if tcp.flags & (dpkt.tcp.TH_FIN | dpkt.tcp.TH_RST) and conn: + if conn.direction == 'sc': + self.serverclosed = True + elif conn.direction == 'cs': + self.clientclosed = True + + if self.serverclosed and self.clientclosed: if conn: # we might occasionally have data in a FIN packet self.track(addr, str(tcp.data), ts, offset=tcp.seq) self.close(conn, ts) + self.serverclosed = False + self.clientclosed = False # init connection, set TCP ISN - elif not self.ignore_handshake and tcp.flags == dpkt.tcp.TH_SYN: + elif not self.ignore_handshake and (tcp.flags == dpkt.tcp.TH_SYN or tcp.flags == dpkt.tcp.TH_SYN | dpkt.tcp.TH_CWR | dpkt.tcp.TH_ECE): + if conn: + self.track(addr, str(tcp.data), ts, offset=tcp.seq) + self.close(conn, ts) conn = self.track(addr, ts=ts, state='init', **kwargs) if conn: conn.nextoffset['cs'] = tcp.seq + 1 From 850f79e37e1d4c0191a5dad7ffd3eeeca497778c Mon Sep 17 00:00:00 2001 From: "jeffrey.mates.dmz" Date: Tue, 20 Sep 2016 15:40:30 -0400 Subject: [PATCH 056/166] Better detects TCP connection closure. This also better detects next offset when it receives an unexpected sequence number. --- lib/dshell.py | 29 ++++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-) mode change 100644 => 100755 lib/dshell.py diff --git a/lib/dshell.py b/lib/dshell.py old mode 100644 new mode 100755 index f3734cb..bac397f --- a/lib/dshell.py +++ b/lib/dshell.py @@ -701,11 +701,13 @@ def TCP(self, addr, tcp, ts, **kwargs): # close connection conn = self.find(addr) if tcp.flags & (dpkt.tcp.TH_FIN | dpkt.tcp.TH_RST) and conn: - if conn.direction == 'sc': - self.serverclosed = True - elif conn.direction == 'cs': - self.clientclosed = True + conn.closeIP(addr[0]) #track if FIN has been seen in connection + if conn: + if conn.connectionClosed(): #if FIN has been seen from both sides, trigger old logic + self.clientclosed = True + self.serverclosed = True + if self.serverclosed and self.clientclosed: if conn: # we might occasionally have data in a FIN packet @@ -857,6 +859,7 @@ class Connection(Packet): {client|server}countrycode, {client|server}asn: aliases of sip/dip country codes and ASNs clientpackets, serverpackets: counts of packets from client and server clientbytes, serverbytes: total bytes from client and server + clientclosed, serverclosed: flag indicating if a direction has closed the connection starttime,endtime: timestamps of start and end (or last packet) time of connection. direction: indicates direction of last traffic: 'init' : established, no traffic @@ -868,6 +871,7 @@ class Connection(Packet): stop: if True, stopped following stream """ + MAX_OFFSET = 0xffffffff # max offset before wrap, default is MAXINT32 for TCP sequence numbers def __init__(self, decoder, addr, ts=None, **kwargs): @@ -888,6 +892,8 @@ def __init__(self, decoder, addr, ts=None, **kwargs): self.serverpackets = 0 self.clientbytes = 0 self.serverbytes = 0 + self.clientclosed = False + self.serverclosed = False self.starttime = self.ts # datetime Obj containing start time self.endtime = self.ts # first update will change this, creating first blob @@ -917,6 +923,19 @@ def __repr__(self): (util.mktime(self.endtime) - util.mktime(self.starttime)), self.state) + def connectionClosed(self): + return self.serverclosed and self.clientclosed + + def closeIP(self, tuple): + ''' + Track if we have seen a FIN packet from given tuple + tuple should be of form (ip, port) + ''' + if tuple == (self.clientip, self.clientport): + self.clientclosed = True + if tuple == (self.serverip, self.serverport): + self.serverclosed = True + def update(self, ts, direction, data, offset=None): # if we have no blobs or direction changes, start a new blob lastblob = None @@ -943,7 +962,7 @@ def update(self, ts, direction, data, offset=None): self.endtime = ts # if we are tracking offsets, expect the next blob to be where this one # ends so far - if offset != None and offset >= self.nextoffset[direction]: + if offset != None and ((offset + len(data)) & self.MAX_OFFSET) >= self.nextoffset[direction]: self.nextoffset[direction] = (offset + len(data)) & self.MAX_OFFSET return lastblob From e4d241238bf092f2d2f50e7a927a3410327db80d Mon Sep 17 00:00:00 2001 From: "jeffrey.mates.dmz" Date: Thu, 22 Sep 2016 14:41:24 -0400 Subject: [PATCH 057/166] Removed unnecessary variables based on feedback. --- lib/dshell.py | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/lib/dshell.py b/lib/dshell.py index bac397f..d96b74a 100755 --- a/lib/dshell.py +++ b/lib/dshell.py @@ -681,8 +681,6 @@ def __init__(self, **kwargs): IPDecoder.__init__(self, **kwargs) self.optiondict['ignore_handshake'] = { 'action': 'store_true', 'help': 'ignore TCP handshake'} - self.serverclosed = False - self.clientclosed = False def IPHandler(self, addr, pkt, ts, **kwargs): '''IPv4 dispatch''' @@ -702,19 +700,11 @@ def TCP(self, addr, tcp, ts, **kwargs): conn = self.find(addr) if tcp.flags & (dpkt.tcp.TH_FIN | dpkt.tcp.TH_RST) and conn: conn.closeIP(addr[0]) #track if FIN has been seen in connection - - if conn: - if conn.connectionClosed(): #if FIN has been seen from both sides, trigger old logic - self.clientclosed = True - self.serverclosed = True - if self.serverclosed and self.clientclosed: - if conn: - # we might occasionally have data in a FIN packet - self.track(addr, str(tcp.data), ts, offset=tcp.seq) - self.close(conn, ts) - self.serverclosed = False - self.clientclosed = False + if conn and conn.connectionClosed(): + # we might occasionally have data in a FIN packet + self.track(addr, str(tcp.data), ts, offset=tcp.seq) + self.close(conn, ts) # init connection, set TCP ISN elif not self.ignore_handshake and (tcp.flags == dpkt.tcp.TH_SYN or tcp.flags == dpkt.tcp.TH_SYN | dpkt.tcp.TH_CWR | dpkt.tcp.TH_ECE): if conn: From e4d4dec123741acab1f465d38cf928052c030e75 Mon Sep 17 00:00:00 2001 From: 1_modm Date: Mon, 3 Oct 2016 22:48:31 +0100 Subject: [PATCH 058/166] VoIP decoder --- decoders/voip/rtp.py | 224 ++++++++++++++++++++++++++++++++++ decoders/voip/sip.py | 283 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 507 insertions(+) create mode 100644 decoders/voip/rtp.py create mode 100644 decoders/voip/sip.py diff --git a/decoders/voip/rtp.py b/decoders/voip/rtp.py new file mode 100644 index 0000000..7f161ef --- /dev/null +++ b/decoders/voip/rtp.py @@ -0,0 +1,224 @@ +# +# Author: MM - https://github.com/1modm +# +# RTP provides end-to-end network transport functions suitable for applications transmitting real-time data, +# such as audio, video or simulation data, over multicast or unicast network services. +# +# RFC: https://www.ietf.org/rfc/rfc3550.txt +# +# RTP Payload: +# https://tools.ietf.org/html/rfc2198 +# https://tools.ietf.org/html/rfc4855 +# https://www.iana.org/assignments/rtp-parameters/rtp-parameters.xhtml +# +# VoIP - Per Call Bandwidth: +# http://www.cisco.com/c/en/us/support/docs/voice/voice-quality/7934-bwidth-consume.html + + +import dshell +import output +import util +import dpkt +import datetime +from struct import unpack +import socket + + + +class DshellDecoder(dshell.Decoder): + + def __init__(self): + dshell.Decoder.__init__(self, + name='rtp', + description='real-time transport protocol (RTP) capture decoder', + longdescription=""" +The real-time transport protocol (RTP) decoder will extract the Hosts, Payload Type, Synchronization source, +Sequence Number, Padding, Marker and Client MAC address from every RTP packet found in the given pcap. + +General usage: + + decode -d rtp + +Examples: + + https://wiki.wireshark.org/SampleCaptures#SIP_and_RTP + https://wiki.wireshark.org/SampleCaptures?action=AttachFile&do=get&target=rtp_example.raw.gz + + decode -d rtp rtp_example.pcap + + Output: + + rtp 2002-07-26 07:19:10 10.1.6.18:2006 -- 10.1.3.143:5000 ** + From: 10.1.6.18 (00:08:21:91:64:60) to 10.1.3.143 (00:04:76:22:20:17) + Payload Type (7 bits): PCMA - Audio - 8000 Hz - 1 Channel + Sequence Number (16 bits): 9825 + Timestamp (32 bits): 54240 + Synchronization source (32 bits): 4090175489 + Arrival Time: 1027664350.17 + Contributing source (32 bits): 0, Padding (1 bit): 0, Extension (1 bit): 0, Marker (1 bit): 0 + ** + rtp 2002-07-26 07:19:10 10.1.3.143:5000 -- 10.1.6.18:2006 ** + From: 10.1.3.143 (00:04:76:22:20:17) to 10.1.6.18 (00:d0:50:10:01:66) + Payload Type (7 bits): PCMA - Audio - 8000 Hz - 1 Channel + Sequence Number (16 bits): 59364 + Timestamp (32 bits): 55680 + Synchronization source (32 bits): 3739283087 + Arrival Time: 1027664350.2 + Contributing source (32 bits): 0, Padding (1 bit): 0, Extension (1 bit): 0, Marker (1 bit): 0 + ** + + """, + filter='', + author='mm', asdatetime=True, + ) + + def mac_addr(self, address): + """Convert a MAC address to a readable/printable string + Args: + address (str): a MAC address in hex form (e.g. '\x01\x02\x03\x04\x05\x06') + Returns: + str: Printable/readable MAC address + """ + return ':'.join('%02x' % ord(b) for b in address) + + + def payload_type(self, payload): + """Return RTP payload type + Args: + payload: Payload type + Returns: + str: Payload type translation + """ + payload_type = "" + if (payload == 0): return "PCMU - Audio - 8000 Hz - 1 Channel" + elif (payload == 1): return "Reserved" + elif (payload == 2): return "Reserved" + elif (payload == 3): return "GSM - Audio - 8000 Hz - 1 Channel" + elif (payload == 4): return "G723 - Audio - 8000 Hz - 1 Channel" + elif (payload == 5): return "DVI4 - Audio - 8000 Hz - 1 Channel" + elif (payload == 6): return "DVI4 - Audio - 16000 Hz - 1 Channel" + elif (payload == 7): return "LPC - Audio - 8000 Hz - 1 Channel" + elif (payload == 8): return "PCMA - Audio - 8000 Hz - 1 Channel" + elif (payload == 9): return "G722 - Audio - 8000 Hz - 1 Channel" + elif (payload == 10): return "L16 - Audio - 44100 Hz - 2 Channel" + elif (payload == 11): return "L16 - Audio - 44100 Hz - 1 Channel" + elif (payload == 12): return "QCELP - Audio - 8000 Hz - 1 Channel" + elif (payload == 13): return "CN - Audio - 8000 Hz - 1 Channel" + elif (payload == 14): return "MPA - Audio - 90000 Hz" + elif (payload == 15): return "G728 - Audio - 8000 Hz - 1 Channel" + elif (payload == 16): return "DVI4 - Audio - 11025 Hz - 1 Channel" + elif (payload == 17): return "DVI4 - Audio - 22050 Hz - 1 Channel" + elif (payload == 18): return "G729 - Audio - 8000 Hz - 1 Channel" + elif (payload == 19): return "Reserved - Audio" + elif (payload == 20): return "Unassigned - Audio" + elif (payload == 21): return "Unassigned - Audio" + elif (payload == 22): return "Unassigned - Audio" + elif (payload == 23): return "Unassigned - Audio" + elif (payload == 24): return "Unassigned - Video" + elif (payload == 25): return "CelB - Video - 90000 Hz" + elif (payload == 26): return "JPEG - Video - 90000 Hz" + elif (payload == 27): return "Unassigned - Video" + elif (payload == 28): return "nv - Video - 90000 Hz" + elif (payload == 29): return "Unassigned - Video" + elif (payload == 30): return "Unassigned - Video" + elif (payload == 31): return "H261 - Video - 90000 Hz" + elif (payload == 32): return "MPV - Video - 90000 Hz" + elif (payload == 33): return "MP2T - Audio/Video - 90000 Hz" + elif (payload == 34): return "H263 - Video - 90000 Hz" + elif (35 <= payload <= 71): return "Unassigned" + elif (72 <= payload <= 76): return "Reserved for RTCP conflict avoidance" + elif (77 <= payload <= 95): return "Unassigned" + elif (96 <= payload <= 127): return "Dynamic" + else: return "" + + + + def rawHandler(self, dlen, data, ts, **kw): + """Packet handle function + Args: + dlen: length + data: packet + ts: timestamp + kw: kwargs - keyword arguments + """ + + if self.verbose: + self.log("%.06f %d\n%s" % (ts, dlen, util.hexPlusAscii(str(data)))) + + packetype = "VoIP" # by default :) + + try: + # If Ethernet is being replaced by Linux Cooked Capture + # the traces are encapsulated similarly but we need to use dpkt.sll.SLL(data) + # rather than dpkt.ethernet.Ethernet(data) + eth = "SLL" + ethsll = dpkt.sll.SLL(str(data)) + ethethernet = dpkt.ethernet.Ethernet(str(data)) + layer3 = ethsll.data + layer4 = layer3.data + + except Exception: + eth = "Ethernet" + ethethernet = dpkt.ethernet.Ethernet(str(data)) + # Check if string to discard + if not isinstance(ethethernet.data, basestring): + layer3 = ethethernet.data + layer4 = layer3.data + + # Make sure the Ethernet data contains an IP packet + if (eth == "SLL"): + if not (ethsll.data.__class__.__name__ == "IP"): + # ARP, IPv6 + packetype = "ARP or Non IP" + else: + try: + if not (ethethernet.data.__class__.__name__ == "IP"): + # ARP, IPv6 + packetype = "ARP or Non IP" + except Exception: + packetype = "ARP or Non IP" + + # Discard IGMP and ICMP packets + try: + if isinstance(layer3.data, dpkt.igmp.IGMP): + packetype = "IGMP" + except Exception: + pass + + try: + if isinstance(layer3.data, dpkt.icmp.ICMP): + packetype = "ICMP" + except Exception: + pass + + # Process packets with Layer 5 data and RTP type + if (packetype == "VoIP"): + try: + src = socket.inet_ntoa(layer3.src) + dst = socket.inet_ntoa(layer3.dst) + except Exception: + pass + + dictinfo = {'sip': src, 'dip': dst, 'sport': layer4.sport, 'dport': layer4.dport} + + if len(layer4.data) > 0: + try: + layer5 = dpkt.rtp.RTP(layer4.data) + except dpkt.UnpackError, e: + pass + + else: + + pt = self.payload_type(layer5.pt) + + if src and dst: + self.alert('\n\tFrom: {0} ({1}) to {2} ({3}) \n\tPayload Type (7 bits): {4}\n\tSequence Number (16 bits): {5}\n\tTimestamp (32 bits): {6} \n\tSynchronization source (32 bits): {7}\n\tArrival Time: {8}\n\tContributing source (32 bits): {9}, Padding (1 bit): {10}, Extension (1 bit): {11}, Marker (1 bit): {12}\n'.format( + src, self.mac_addr(ethethernet.src), dst, self.mac_addr(ethethernet.dst), pt, layer5.seq, layer5.ts,layer5.ssrc, ts, layer5.cc, layer5.p, + layer5.x, layer5.m), ts=ts, **dictinfo) + + +if __name__ == '__main__': + dObj = DshellDecoder() + print dObj +else: + dObj = DshellDecoder() \ No newline at end of file diff --git a/decoders/voip/sip.py b/decoders/voip/sip.py new file mode 100644 index 0000000..2322b36 --- /dev/null +++ b/decoders/voip/sip.py @@ -0,0 +1,283 @@ +# +# Author: MM - https://github.com/1modm +# +# The Session Initiation Protocol (SIP) is the IETF protocol for VOIP and other text and multimedia sessions +# and is a communications protocol for signaling and controlling +# +# Rate and codec calculation thanks to https://git.ucd.ie/volte-and-of/voip-pcapy +# +# RFC: https://www.ietf.org/rfc/rfc3261.txt +# +# SIP is a text-based protocol with syntax similar to that of HTTP. +# There are two different types of SIP messages: requests and responses. +# - Requests initiate a SIP transaction between two SIP entities for establishing, controlling, and terminating sessions. +# - Responses are send by the user agent server indicating the result of a received request. +# +# - SIP session setup example: +# +# Alice's . . . . . . . . . . . . . . . . . . . . Bob's +# softphone SIP Phone +# | | | | +# | INVITE F1 | | | +# |--------------->| INVITE F2 | | +# | 100 Trying F3 |--------------->| INVITE F4 | +# |<---------------| 100 Trying F5 |--------------->| +# | |<-------------- | 180 Ringing F6 | +# | | 180 Ringing F7 |<---------------| +# | 180 Ringing F8 |<---------------| 200 OK F9 | +# |<---------------| 200 OK F10 |<---------------| +# | 200 OK F11 |<---------------| | +# |<---------------| | | +# | ACK F12 | +# |------------------------------------------------->| +# | Media Session | +# |<================================================>| +# | BYE F13 | +# |<-------------------------------------------------| +# | 200 OK F14 | +# |------------------------------------------------->| +# | | +# + + + +import dshell +import output +import util +import dpkt +import datetime +from struct import unpack +import socket + + +class DshellDecoder(dshell.Decoder): + + def __init__(self): + dshell.Decoder.__init__(self, + name='sip', + description='Session Initiation Protocol (SIP) capture decoder', + longdescription=""" +The Session Initiation Protocol (SIP) decoder will extract the Call ID, User agent, Codec, Method, +SIP call, Host, and Client MAC address from every SIP request or response packet found +in the given pcap using by default the port 5060. + +General usage: + + decode -d sip + or + decode -d sip --sip_port=5062 + +Examples: + + https://wiki.wireshark.org/SampleCaptures#SIP_and_RTP + http://vignette3.wikia.nocookie.net/networker/images/f/fb/Sample_SIP_call_with_RTP_in_G711.pcap/revision/latest?cb=20140723121754 + + decode -d sip metasploit-sip-invite-spoof.pcap + decode -d sip Sample_SIP_call_with_RTP_in_G711.pcap + + Output: + + sip 2016-09-21 23:44:20 10.5.1.7:5060 -- 10.1.30.60:5060 ** + --> SIP Request <-- + From: 10.5.1.7 (81:89:23:d6:c2:a1) to 10.1.30.60 (a1:03:fc:f2:01:bc) + Sequence and Method: 414 PUBLISH + Via: SIP/2.0/UDP 10.5.1.7:5060;branch=z9hG1bK8e35adab-ba7e-e611-937f-68a3c4f0d5ce;rport + SIP call: --> + With: Ekiga/4.0.1 + Call ID: ee8ace41-ab7e-e511-917f-64a3a4f0d5ce@ProBook + ** + sip 2016-09-21 23:44:27 10.5.1.7:5060 -- 10.5.1.8:5060 ** + --> SIP Response <-- + From: 10.5.1.7 (00:00:00:00:00:00) to 10.5.1.8 (a1:03:fc:f2:02:bc) + Sequence and Method: 1 INVITE + Via: SIP/2.0/UDP 10.5.1.8:5060;branch=z2hG4bK25a8d5a4-8a13-1920-9d58-04002772a5e9;rport=5060;received=10.5.1.8 + SIP call: "M" ;tag=0ba2d5c4-8a13-1910-9d55-08002772a6e9 --> "miguel" ;tag=84548c9d-ba7e-e611-937f-68a3c4f0d5ce + With: Ekiga/4.0.1 + Call ID: 0ba2d7c4-8a13-1940-9d57-08002372a6e9@M-PC + Allow: INVITE,ACK,OPTIONS,BYE,CANCEL,SUBSCRIBE,NOTIFY,REFER,MESSAGE,INFO,PING,PRACK + Codec: PCMU + Rate: 8000 Hz + ** + """, + filter='', + author='mm', asdatetime=True, + optiondict={ + 'port':{'type':'string', + 'default':'5060', + 'help':'SIP Port used (Default: 5060)'} + } + ) + + def mac_addr(self, address): + """Convert a MAC address to a readable/printable string + Args: + address (str): a MAC address in hex form (e.g. '\x01\x02\x03\x04\x05\x06') + Returns: + str: Printable/readable MAC address + """ + return ':'.join('%02x' % ord(b) for b in address) + + + def layer5_header(self, layer_received, header): + """Return packet header information + Args: + header: Packet header + Returns: + str: Packet layer 5 header + """ + try: + return layer_received.headers[header] + except Exception: + return "" + + + def rawHandler(self, dlen, data, ts, **kw): + """Packet handle function + Args: + dlen: length + data: packet + ts: timestamp + kw: kwargs - keyword arguments + """ + + if self.verbose: + self.log("%.06f %d\n%s" % (ts, dlen, util.hexPlusAscii(str(data)))) + + packetype = "VoIP" # by default :) + + try: + # If Ethernet is being replaced by Linux Cooked Capture + # the traces are encapsulated similarly but we need to use dpkt.sll.SLL(data) + # rather than dpkt.ethernet.Ethernet(data) + eth = "SLL" + ethsll = dpkt.sll.SLL(str(data)) + ethethernet = dpkt.ethernet.Ethernet(str(data)) + layer3 = ethsll.data + layer4 = layer3.data + + except Exception: + eth = "Ethernet" + ethethernet = dpkt.ethernet.Ethernet(str(data)) + # Check if string to discard + if not isinstance(ethethernet.data, basestring): + layer3 = ethethernet.data + layer4 = layer3.data + + # Make sure the Ethernet data contains an IP packet + if (eth == "SLL"): + if not (ethsll.data.__class__.__name__ == "IP"): + # ARP, IPv6 + packetype = "ARP or Non IP" + else: + try: + if not (ethethernet.data.__class__.__name__ == "IP"): + # ARP, IPv6 + packetype = "ARP or Non IP" + except Exception: + packetype = "ARP or Non IP" + + # Discard IGMP and ICMP packets + try: + if isinstance(layer3.data, dpkt.igmp.IGMP): + packetype = "IGMP" + except Exception: + pass + + try: + if isinstance(layer3.data, dpkt.icmp.ICMP): + packetype = "ICMP" + except Exception: + pass + + # Process packets with Layer 5 data and port defined for SIP + if (packetype == "VoIP"): + try: + src = socket.inet_ntoa(layer3.src) + dst = socket.inet_ntoa(layer3.dst) + except Exception: + pass + + sipport = int(self.port) + dictinfo = {'sip': src, 'dip': dst, 'sport': layer4.sport, 'dport': layer4.dport} + + # SIP REQUEST + if (layer4.dport==sipport or layer4.sport==sipport) and len(layer4.data) > 0: + try: + layer5 = dpkt.sip.Request(layer4.data) + sip_type = "SIP Request" + except dpkt.UnpackError, e: + pass + + else: + user_agent = self.layer5_header(layer5, 'user-agent') + allow = self.layer5_header(layer5, 'allow') + l5_from = self.layer5_header(layer5, 'from') + l5_to = self.layer5_header(layer5, 'to') + l5_callid = self.layer5_header(layer5, 'call-id') + via = self.layer5_header(layer5, 'via') + cseq = self.layer5_header(layer5, 'cseq') + + try: + rate = "" + codec = "" + for x in range(layer5.body.find(' ',layer5.body.find('a='))+1,layer5.body.find('/',layer5.body.find('a='))): + codec += layer5.body[x] + for x in range(layer5.body.find(' ',layer5.body.find('a='))+6,layer5.body.find('/',layer5.body.find('a='))+5): + rate+=layer5.body[x] + except: + pass + + if src and dst and layer5.headers: + if not allow: + self.alert('\n\t--> {0} <--\n\tFrom: {1} ({2}) to {3} ({4}) \n\tSequence and Method: {5}\n\tVia: {6}\n\tSIP call: {7} --> {8} \n\tWith: {9}\n\tCall ID: {10}\n'.format(sip_type, src, + self.mac_addr(ethethernet.src), dst, self.mac_addr(ethethernet.dst), cseq, via, l5_from, + l5_to, user_agent, l5_callid), ts=ts, **dictinfo) + else: + self.alert('\n\t--> {0} <--\n\tFrom: {1} ({2}) to {3} ({4}) \n\tSequence and Method: {5}\n\tVia: {6}\n\tSIP call: {7} --> {8} \n\tWith: {9}\n\tCall ID: {10}\n\tAllow: {11}\n\tCodec: {12}\n\tRate: {13} Hz\n'.format(sip_type, src, + self.mac_addr(ethethernet.src), dst, self.mac_addr(ethethernet.dst), cseq, via, l5_from, + l5_to, user_agent, l5_callid, allow, codec, rate), ts=ts, **dictinfo) + + + # SIP RESPONSE + if (layer4.sport==sipport or layer4.dport==sipport) and len(layer4.data) > 0: + try : + layer5 = dpkt.sip.Response(layer4.data) + sip_type = "SIP Response" + except dpkt.UnpackError, e: + pass + else: + user_agent = self.layer5_header(layer5, 'user-agent') + allow = self.layer5_header(layer5, 'allow') + l5_from = self.layer5_header(layer5, 'from') + l5_to = self.layer5_header(layer5, 'to') + l5_callid = self.layer5_header(layer5, 'call-id') + via = self.layer5_header(layer5, 'via') + cseq = self.layer5_header(layer5, 'cseq') + + try: + rate = "" + codec = "" + for x in range(layer5.body.find(' ',layer5.body.find('a='))+1,layer5.body.find('/',layer5.body.find('a='))): + codec += layer5.body[x] + for x in range(layer5.body.find(' ',layer5.body.find('a='))+6,layer5.body.find('/',layer5.body.find('a='))+5): + rate+=layer5.body[x] + except: + pass + + if src and dst and layer5.headers: + if not allow: + self.alert('\n\t--> {0} <--\n\tFrom: {1} ({2}) to {3} ({4}) \n\tSequence and Method: {5}\n\tVia: {6}\n\tSIP call: {7} --> {8} \n\tWith: {9}\n\tCall ID: {10}\n'.format(sip_type, src, + self.mac_addr(ethethernet.src), dst, self.mac_addr(ethethernet.dst), cseq, via, l5_from, + l5_to, user_agent, l5_callid), ts=ts, **dictinfo) + else: + + self.alert('\n\t--> {0} <--\n\tFrom: {1} ({2}) to {3} ({4}) \n\tSequence and Method: {5}\n\tVia: {6}\n\tSIP call: {7} --> {8} \n\tWith: {9}\n\tCall ID: {10}\n\tAllow: {11}\n\tCodec: {12}\n\tRate: {13} Hz\n'.format(sip_type, src, + self.mac_addr(ethethernet.src), dst, self.mac_addr(ethethernet.dst), cseq, via, l5_from, + l5_to, user_agent, l5_callid, allow, codec, rate), ts=ts, **dictinfo) + + +if __name__ == '__main__': + dObj = DshellDecoder() + print dObj +else: + dObj = DshellDecoder() \ No newline at end of file From a7821d22e9cad6110066181010a7674006762a47 Mon Sep 17 00:00:00 2001 From: 1_modm Date: Wed, 5 Oct 2016 23:50:39 +0100 Subject: [PATCH 059/166] cleaning up --- decoders/voip/rtp.py | 109 +++++++++------------------------ decoders/voip/sip.py | 140 ++++++++++++------------------------------- 2 files changed, 66 insertions(+), 183 deletions(-) diff --git a/decoders/voip/rtp.py b/decoders/voip/rtp.py index 7f161ef..42e68e5 100644 --- a/decoders/voip/rtp.py +++ b/decoders/voip/rtp.py @@ -72,65 +72,25 @@ def __init__(self): author='mm', asdatetime=True, ) - def mac_addr(self, address): - """Convert a MAC address to a readable/printable string - Args: - address (str): a MAC address in hex form (e.g. '\x01\x02\x03\x04\x05\x06') - Returns: - str: Printable/readable MAC address - """ - return ':'.join('%02x' % ord(b) for b in address) - - - def payload_type(self, payload): - """Return RTP payload type - Args: - payload: Payload type - Returns: - str: Payload type translation - """ - payload_type = "" - if (payload == 0): return "PCMU - Audio - 8000 Hz - 1 Channel" - elif (payload == 1): return "Reserved" - elif (payload == 2): return "Reserved" - elif (payload == 3): return "GSM - Audio - 8000 Hz - 1 Channel" - elif (payload == 4): return "G723 - Audio - 8000 Hz - 1 Channel" - elif (payload == 5): return "DVI4 - Audio - 8000 Hz - 1 Channel" - elif (payload == 6): return "DVI4 - Audio - 16000 Hz - 1 Channel" - elif (payload == 7): return "LPC - Audio - 8000 Hz - 1 Channel" - elif (payload == 8): return "PCMA - Audio - 8000 Hz - 1 Channel" - elif (payload == 9): return "G722 - Audio - 8000 Hz - 1 Channel" - elif (payload == 10): return "L16 - Audio - 44100 Hz - 2 Channel" - elif (payload == 11): return "L16 - Audio - 44100 Hz - 1 Channel" - elif (payload == 12): return "QCELP - Audio - 8000 Hz - 1 Channel" - elif (payload == 13): return "CN - Audio - 8000 Hz - 1 Channel" - elif (payload == 14): return "MPA - Audio - 90000 Hz" - elif (payload == 15): return "G728 - Audio - 8000 Hz - 1 Channel" - elif (payload == 16): return "DVI4 - Audio - 11025 Hz - 1 Channel" - elif (payload == 17): return "DVI4 - Audio - 22050 Hz - 1 Channel" - elif (payload == 18): return "G729 - Audio - 8000 Hz - 1 Channel" - elif (payload == 19): return "Reserved - Audio" - elif (payload == 20): return "Unassigned - Audio" - elif (payload == 21): return "Unassigned - Audio" - elif (payload == 22): return "Unassigned - Audio" - elif (payload == 23): return "Unassigned - Audio" - elif (payload == 24): return "Unassigned - Video" - elif (payload == 25): return "CelB - Video - 90000 Hz" - elif (payload == 26): return "JPEG - Video - 90000 Hz" - elif (payload == 27): return "Unassigned - Video" - elif (payload == 28): return "nv - Video - 90000 Hz" - elif (payload == 29): return "Unassigned - Video" - elif (payload == 30): return "Unassigned - Video" - elif (payload == 31): return "H261 - Video - 90000 Hz" - elif (payload == 32): return "MPV - Video - 90000 Hz" - elif (payload == 33): return "MP2T - Audio/Video - 90000 Hz" - elif (payload == 34): return "H263 - Video - 90000 Hz" - elif (35 <= payload <= 71): return "Unassigned" - elif (72 <= payload <= 76): return "Reserved for RTCP conflict avoidance" - elif (77 <= payload <= 95): return "Unassigned" - elif (96 <= payload <= 127): return "Dynamic" - else: return "" - + def preModule(self): + self.payload_type = {0: "PCMU - Audio - 8000 Hz - 1 Channel", 1: "Reserved", 2: "Reserved", 3: "GSM - Audio - 8000 Hz - 1 Channel", + 4: "G723 - Audio - 8000 Hz - 1 Channel", 5: "DVI4 - Audio - 8000 Hz - 1 Channel", 6: "DVI4 - Audio - 16000 Hz - 1 Channel", + 7: "LPC - Audio - 8000 Hz - 1 Channel", 8: "PCMA - Audio - 8000 Hz - 1 Channel", 9: "G722 - Audio - 8000 Hz - 1 Channel", + 10: "L16 - Audio - 44100 Hz - 2 Channel", 11: "L16 - Audio - 44100 Hz - 1 Channel", 12: "QCELP - Audio - 8000 Hz - 1 Channel", + 13: "CN - Audio - 8000 Hz - 1 Channel", 14: "MPA - Audio - 90000 Hz", 15: "G728 - Audio - 8000 Hz - 1 Channel", 16: "DVI4 - Audio - 11025 Hz - 1 Channel", + 17: "DVI4 - Audio - 22050 Hz - 1 Channel", 18: "G729 - Audio - 8000 Hz - 1 Channel", 19: "Reserved - Audio", 20: "Unassigned - Audio", + 21: "Unassigned - Audio", 22: "Unassigned - Audio", 23: "Unassigned - Audio", 24: "Unassigned - Video", 25: "CelB - Video - 90000 Hz", + 26: "JPEG - Video - 90000 Hz", 27: "Unassigned - Video", 28: "nv - Video - 90000 Hz", 29: "Unassigned - Video", 30: "Unassigned - Video", + 31: "H261 - Video - 90000 Hz", 32: "MPV - Video - 90000 Hz", 33: "MP2T - Audio/Video - 90000 Hz", 34: "H263 - Video - 90000 Hz"} + + for i in range(35,72): + self.payload_type[i] = "Unassigned" + for i in range(72,77): + self.payload_type[i] = "Reserved for RTCP conflict avoidance" + for i in range(77,96): + self.payload_type[i] = "Unassigned" + for i in range(96,128): + self.payload_type[i] = "Dynamic" def rawHandler(self, dlen, data, ts, **kw): @@ -157,7 +117,7 @@ def rawHandler(self, dlen, data, ts, **kw): layer3 = ethsll.data layer4 = layer3.data - except Exception: + except AttributeError: eth = "Ethernet" ethethernet = dpkt.ethernet.Ethernet(str(data)) # Check if string to discard @@ -171,34 +131,28 @@ def rawHandler(self, dlen, data, ts, **kw): # ARP, IPv6 packetype = "ARP or Non IP" else: - try: - if not (ethethernet.data.__class__.__name__ == "IP"): - # ARP, IPv6 - packetype = "ARP or Non IP" - except Exception: - packetype = "ARP or Non IP" + if not (ethethernet.data.__class__.__name__ == "IP"): + # ARP, IPv6 + packetype = "ARP or Non IP" # Discard IGMP and ICMP packets try: if isinstance(layer3.data, dpkt.igmp.IGMP): packetype = "IGMP" - except Exception: + except AttributeError: pass try: if isinstance(layer3.data, dpkt.icmp.ICMP): packetype = "ICMP" - except Exception: + except AttributeError: pass # Process packets with Layer 5 data and RTP type if (packetype == "VoIP"): - try: - src = socket.inet_ntoa(layer3.src) - dst = socket.inet_ntoa(layer3.dst) - except Exception: - pass + src = socket.inet_ntoa(layer3.src) + dst = socket.inet_ntoa(layer3.dst) dictinfo = {'sip': src, 'dip': dst, 'sport': layer4.sport, 'dport': layer4.dport} if len(layer4.data) > 0: @@ -206,16 +160,11 @@ def rawHandler(self, dlen, data, ts, **kw): layer5 = dpkt.rtp.RTP(layer4.data) except dpkt.UnpackError, e: pass - else: - - pt = self.payload_type(layer5.pt) - + pt = self.payload_type.get(layer5.pt) if src and dst: self.alert('\n\tFrom: {0} ({1}) to {2} ({3}) \n\tPayload Type (7 bits): {4}\n\tSequence Number (16 bits): {5}\n\tTimestamp (32 bits): {6} \n\tSynchronization source (32 bits): {7}\n\tArrival Time: {8}\n\tContributing source (32 bits): {9}, Padding (1 bit): {10}, Extension (1 bit): {11}, Marker (1 bit): {12}\n'.format( - src, self.mac_addr(ethethernet.src), dst, self.mac_addr(ethethernet.dst), pt, layer5.seq, layer5.ts,layer5.ssrc, ts, layer5.cc, layer5.p, - layer5.x, layer5.m), ts=ts, **dictinfo) - + src, kw['smac'], dst, kw['dmac'], pt, layer5.seq, layer5.ts,layer5.ssrc, ts, layer5.cc, layer5.p, layer5.x, layer5.m), ts=ts, **dictinfo) if __name__ == '__main__': dObj = DshellDecoder() diff --git a/decoders/voip/sip.py b/decoders/voip/sip.py index 2322b36..5dd2c9e 100644 --- a/decoders/voip/sip.py +++ b/decoders/voip/sip.py @@ -102,35 +102,12 @@ def __init__(self): filter='', author='mm', asdatetime=True, optiondict={ - 'port':{'type':'string', - 'default':'5060', + 'port':{'type':'int', + 'default': 5060, 'help':'SIP Port used (Default: 5060)'} } ) - def mac_addr(self, address): - """Convert a MAC address to a readable/printable string - Args: - address (str): a MAC address in hex form (e.g. '\x01\x02\x03\x04\x05\x06') - Returns: - str: Printable/readable MAC address - """ - return ':'.join('%02x' % ord(b) for b in address) - - - def layer5_header(self, layer_received, header): - """Return packet header information - Args: - header: Packet header - Returns: - str: Packet layer 5 header - """ - try: - return layer_received.headers[header] - except Exception: - return "" - - def rawHandler(self, dlen, data, ts, **kw): """Packet handle function Args: @@ -154,8 +131,7 @@ def rawHandler(self, dlen, data, ts, **kw): ethethernet = dpkt.ethernet.Ethernet(str(data)) layer3 = ethsll.data layer4 = layer3.data - - except Exception: + except AttributeError: eth = "Ethernet" ethethernet = dpkt.ethernet.Ethernet(str(data)) # Check if string to discard @@ -169,113 +145,71 @@ def rawHandler(self, dlen, data, ts, **kw): # ARP, IPv6 packetype = "ARP or Non IP" else: - try: - if not (ethethernet.data.__class__.__name__ == "IP"): - # ARP, IPv6 - packetype = "ARP or Non IP" - except Exception: - packetype = "ARP or Non IP" + if not (ethethernet.data.__class__.__name__ == "IP"): + # ARP, IPv6 + packetype = "ARP or Non IP" # Discard IGMP and ICMP packets try: if isinstance(layer3.data, dpkt.igmp.IGMP): packetype = "IGMP" - except Exception: + except AttributeError: pass try: if isinstance(layer3.data, dpkt.icmp.ICMP): packetype = "ICMP" - except Exception: + except AttributeError: pass # Process packets with Layer 5 data and port defined for SIP if (packetype == "VoIP"): - try: - src = socket.inet_ntoa(layer3.src) - dst = socket.inet_ntoa(layer3.dst) - except Exception: - pass - - sipport = int(self.port) + src = socket.inet_ntoa(layer3.src) + dst = socket.inet_ntoa(layer3.dst) + sipport = self.port dictinfo = {'sip': src, 'dip': dst, 'sport': layer4.sport, 'dport': layer4.dport} - # SIP REQUEST + # SIP REQUEST and SIP RESPONSE if (layer4.dport==sipport or layer4.sport==sipport) and len(layer4.data) > 0: + sip_packet = False try: layer5 = dpkt.sip.Request(layer4.data) sip_type = "SIP Request" + sip_packet = True except dpkt.UnpackError, e: - pass - - else: - user_agent = self.layer5_header(layer5, 'user-agent') - allow = self.layer5_header(layer5, 'allow') - l5_from = self.layer5_header(layer5, 'from') - l5_to = self.layer5_header(layer5, 'to') - l5_callid = self.layer5_header(layer5, 'call-id') - via = self.layer5_header(layer5, 'via') - cseq = self.layer5_header(layer5, 'cseq') - try: - rate = "" - codec = "" - for x in range(layer5.body.find(' ',layer5.body.find('a='))+1,layer5.body.find('/',layer5.body.find('a='))): - codec += layer5.body[x] - for x in range(layer5.body.find(' ',layer5.body.find('a='))+6,layer5.body.find('/',layer5.body.find('a='))+5): - rate+=layer5.body[x] - except: + layer5 = dpkt.sip.Response(layer4.data) + sip_type = "SIP Response" + sip_packet = True + except dpkt.UnpackError, e: pass - - if src and dst and layer5.headers: - if not allow: - self.alert('\n\t--> {0} <--\n\tFrom: {1} ({2}) to {3} ({4}) \n\tSequence and Method: {5}\n\tVia: {6}\n\tSIP call: {7} --> {8} \n\tWith: {9}\n\tCall ID: {10}\n'.format(sip_type, src, - self.mac_addr(ethethernet.src), dst, self.mac_addr(ethethernet.dst), cseq, via, l5_from, - l5_to, user_agent, l5_callid), ts=ts, **dictinfo) - else: - self.alert('\n\t--> {0} <--\n\tFrom: {1} ({2}) to {3} ({4}) \n\tSequence and Method: {5}\n\tVia: {6}\n\tSIP call: {7} --> {8} \n\tWith: {9}\n\tCall ID: {10}\n\tAllow: {11}\n\tCodec: {12}\n\tRate: {13} Hz\n'.format(sip_type, src, - self.mac_addr(ethethernet.src), dst, self.mac_addr(ethethernet.dst), cseq, via, l5_from, - l5_to, user_agent, l5_callid, allow, codec, rate), ts=ts, **dictinfo) - - - # SIP RESPONSE - if (layer4.sport==sipport or layer4.dport==sipport) and len(layer4.data) > 0: - try : - layer5 = dpkt.sip.Response(layer4.data) - sip_type = "SIP Response" - except dpkt.UnpackError, e: - pass - else: - user_agent = self.layer5_header(layer5, 'user-agent') - allow = self.layer5_header(layer5, 'allow') - l5_from = self.layer5_header(layer5, 'from') - l5_to = self.layer5_header(layer5, 'to') - l5_callid = self.layer5_header(layer5, 'call-id') - via = self.layer5_header(layer5, 'via') - cseq = self.layer5_header(layer5, 'cseq') - try: + finally: + if (sip_packet): + user_agent = layer5.headers.get('user-agent') + allow = layer5.headers.get('allow') + l5_from = layer5.headers.get('from') + l5_to = layer5.headers.get('to') + l5_callid = layer5.headers.get('call-id') + via = layer5.headers.get('via') + cseq = layer5.headers.get('cseq') rate = "" codec = "" for x in range(layer5.body.find(' ',layer5.body.find('a='))+1,layer5.body.find('/',layer5.body.find('a='))): codec += layer5.body[x] for x in range(layer5.body.find(' ',layer5.body.find('a='))+6,layer5.body.find('/',layer5.body.find('a='))+5): rate+=layer5.body[x] - except: - pass - - if src and dst and layer5.headers: - if not allow: - self.alert('\n\t--> {0} <--\n\tFrom: {1} ({2}) to {3} ({4}) \n\tSequence and Method: {5}\n\tVia: {6}\n\tSIP call: {7} --> {8} \n\tWith: {9}\n\tCall ID: {10}\n'.format(sip_type, src, - self.mac_addr(ethethernet.src), dst, self.mac_addr(ethethernet.dst), cseq, via, l5_from, - l5_to, user_agent, l5_callid), ts=ts, **dictinfo) - else: - - self.alert('\n\t--> {0} <--\n\tFrom: {1} ({2}) to {3} ({4}) \n\tSequence and Method: {5}\n\tVia: {6}\n\tSIP call: {7} --> {8} \n\tWith: {9}\n\tCall ID: {10}\n\tAllow: {11}\n\tCodec: {12}\n\tRate: {13} Hz\n'.format(sip_type, src, - self.mac_addr(ethethernet.src), dst, self.mac_addr(ethethernet.dst), cseq, via, l5_from, - l5_to, user_agent, l5_callid, allow, codec, rate), ts=ts, **dictinfo) + + if src and dst and layer5.headers: + if not allow: + self.alert('\n\t--> {0} <--\n\tFrom: {1} ({2}) to {3} ({4}) \n\tSequence and Method: {5}\n\tVia: {6}\n\tSIP call: {7} --> {8} \n\tWith: {9}\n\tCall ID: {10}\n'.format(sip_type, src, + kw['smac'], dst, kw['dmac'], cseq, via, l5_from, + l5_to, user_agent, l5_callid), ts=ts, **dictinfo) + else: + self.alert('\n\t--> {0} <--\n\tFrom: {1} ({2}) to {3} ({4}) \n\tSequence and Method: {5}\n\tVia: {6}\n\tSIP call: {7} --> {8} \n\tWith: {9}\n\tCall ID: {10}\n\tAllow: {11}\n\tCodec: {12}\n\tRate: {13} Hz\n'.format(sip_type, src, + kw['smac'], dst, kw['dmac'], cseq, via, l5_from, + l5_to, user_agent, l5_callid, allow, codec, rate), ts=ts, **dictinfo) - if __name__ == '__main__': dObj = DshellDecoder() print dObj From dd2654726ad49df504b3bb621df5020be6365c21 Mon Sep 17 00:00:00 2001 From: 1_modm Date: Tue, 11 Oct 2016 23:03:29 +0100 Subject: [PATCH 060/166] UDPDecoder rewrite --- decoders/voip/rtp.py | 145 +++++++-------------- decoders/voip/sip.py | 296 +++++++++++++++++++++++-------------------- 2 files changed, 202 insertions(+), 239 deletions(-) diff --git a/decoders/voip/rtp.py b/decoders/voip/rtp.py index 42e68e5..34946da 100644 --- a/decoders/voip/rtp.py +++ b/decoders/voip/rtp.py @@ -11,26 +11,17 @@ # https://tools.ietf.org/html/rfc4855 # https://www.iana.org/assignments/rtp-parameters/rtp-parameters.xhtml # -# VoIP - Per Call Bandwidth: -# http://www.cisco.com/c/en/us/support/docs/voice/voice-quality/7934-bwidth-consume.html - import dshell -import output -import util import dpkt import datetime -from struct import unpack -import socket - - -class DshellDecoder(dshell.Decoder): +class DshellDecoder(dshell.UDPDecoder): def __init__(self): - dshell.Decoder.__init__(self, + dshell.UDPDecoder.__init__(self, name='rtp', - description='real-time transport protocol (RTP) capture decoder', + description='Real-time transport protocol (RTP) capture decoder', longdescription=""" The real-time transport protocol (RTP) decoder will extract the Hosts, Payload Type, Synchronization source, Sequence Number, Padding, Marker and Client MAC address from every RTP packet found in the given pcap. @@ -38,6 +29,7 @@ def __init__(self): General usage: decode -d rtp + decode -d rtp --no-vlan --layer2=sll.SLL Examples: @@ -46,31 +38,32 @@ def __init__(self): decode -d rtp rtp_example.pcap - Output: +Output: - rtp 2002-07-26 07:19:10 10.1.6.18:2006 -- 10.1.3.143:5000 ** - From: 10.1.6.18 (00:08:21:91:64:60) to 10.1.3.143 (00:04:76:22:20:17) - Payload Type (7 bits): PCMA - Audio - 8000 Hz - 1 Channel - Sequence Number (16 bits): 9825 - Timestamp (32 bits): 54240 - Synchronization source (32 bits): 4090175489 - Arrival Time: 1027664350.17 - Contributing source (32 bits): 0, Padding (1 bit): 0, Extension (1 bit): 0, Marker (1 bit): 0 - ** - rtp 2002-07-26 07:19:10 10.1.3.143:5000 -- 10.1.6.18:2006 ** - From: 10.1.3.143 (00:04:76:22:20:17) to 10.1.6.18 (00:d0:50:10:01:66) - Payload Type (7 bits): PCMA - Audio - 8000 Hz - 1 Channel - Sequence Number (16 bits): 59364 - Timestamp (32 bits): 55680 - Synchronization source (32 bits): 3739283087 - Arrival Time: 1027664350.2 + rtp 2016-09-21 23:44:40 50.197.16.141:1195 -- 192.168.9.12:44352 ** + From: 50.197.16.141 (00:02:31:11:a5:97) to 192.168.9.12 (45:20:01:31:45:40) + Payload Type (7 bits): Dynamic + Sequence Number (16 bits): 58635 + Timestamp (32 bits): 1331328074 + Synchronization source (32 bits): 1948709792 + Arrival Time: 1474497880.6 --> 2016-09-21 22:44:40.604135 + Contributing source (32 bits): 1, Padding (1 bit): 1, Extension (1 bit): 1, Marker (1 bit): 0 + ** + rtp 2016-09-21 23:44:40 10.5.1.8:5086 -- 10.5.1.7:5070 ** + From: 10.5.1.8 (00:02:81:11:a0:d7) to 10.5.1.7 (45:00:20:c8:a3:26) + Payload Type (7 bits): PCMU - Audio - 8000 Hz - 1 Channel + Sequence Number (16 bits): 17664 + Timestamp (32 bits): 98240 + Synchronization source (32 bits): 1671095215 + Arrival Time: 1474497880.6 --> 2016-09-21 22:44:40.604160 Contributing source (32 bits): 0, Padding (1 bit): 0, Extension (1 bit): 0, Marker (1 bit): 0 - ** - + ** """, - filter='', + filter='udp', author='mm', asdatetime=True, ) + self.smac = None + self.dmac = None def preModule(self): self.payload_type = {0: "PCMU - Audio - 8000 Hz - 1 Channel", 1: "Reserved", 2: "Reserved", 3: "GSM - Audio - 8000 Hz - 1 Channel", @@ -92,80 +85,34 @@ def preModule(self): for i in range(96,128): self.payload_type[i] = "Dynamic" + def packetHandler(self, udp, data): - def rawHandler(self, dlen, data, ts, **kw): - """Packet handle function - Args: - dlen: length - data: packet - ts: timestamp - kw: kwargs - keyword arguments - """ - - if self.verbose: - self.log("%.06f %d\n%s" % (ts, dlen, util.hexPlusAscii(str(data)))) - - packetype = "VoIP" # by default :) - + # Get MAC addr for layer2 packets try: - # If Ethernet is being replaced by Linux Cooked Capture - # the traces are encapsulated similarly but we need to use dpkt.sll.SLL(data) - # rather than dpkt.ethernet.Ethernet(data) - eth = "SLL" - ethsll = dpkt.sll.SLL(str(data)) - ethethernet = dpkt.ethernet.Ethernet(str(data)) - layer3 = ethsll.data - layer4 = layer3.data - - except AttributeError: - eth = "Ethernet" - ethethernet = dpkt.ethernet.Ethernet(str(data)) - # Check if string to discard - if not isinstance(ethethernet.data, basestring): - layer3 = ethethernet.data - layer4 = layer3.data - - # Make sure the Ethernet data contains an IP packet - if (eth == "SLL"): - if not (ethsll.data.__class__.__name__ == "IP"): - # ARP, IPv6 - packetype = "ARP or Non IP" - else: - if not (ethethernet.data.__class__.__name__ == "IP"): - # ARP, IPv6 - packetype = "ARP or Non IP" - - # Discard IGMP and ICMP packets + self.smac = udp.info()['smac'] + except LookupError: + ethernet = dpkt.ethernet.Ethernet(data) + self.smac = ':'.join('%02x' % ord(b) for b in ethernet.src) + try: - if isinstance(layer3.data, dpkt.igmp.IGMP): - packetype = "IGMP" - except AttributeError: - pass + self.dmac = udp.info()['dmac'] + except LookupError: + ethernet = dpkt.ethernet.Ethernet(data) + self.dmac = ':'.join('%02x' % ord(b) for b in ethernet.dst) try: - if isinstance(layer3.data, dpkt.icmp.ICMP): - packetype = "ICMP" - except AttributeError: - pass + if dpkt.rtp.RTP(str(data)): + rtppkt = dpkt.rtp.RTP(data) + pt = self.payload_type.get(rtppkt.pt) - # Process packets with Layer 5 data and RTP type - if (packetype == "VoIP"): - - src = socket.inet_ntoa(layer3.src) - dst = socket.inet_ntoa(layer3.dst) - dictinfo = {'sip': src, 'dip': dst, 'sport': layer4.sport, 'dport': layer4.dport} - - if len(layer4.data) > 0: - try: - layer5 = dpkt.rtp.RTP(layer4.data) - except dpkt.UnpackError, e: - pass - else: - pt = self.payload_type.get(layer5.pt) - if src and dst: - self.alert('\n\tFrom: {0} ({1}) to {2} ({3}) \n\tPayload Type (7 bits): {4}\n\tSequence Number (16 bits): {5}\n\tTimestamp (32 bits): {6} \n\tSynchronization source (32 bits): {7}\n\tArrival Time: {8}\n\tContributing source (32 bits): {9}, Padding (1 bit): {10}, Extension (1 bit): {11}, Marker (1 bit): {12}\n'.format( - src, kw['smac'], dst, kw['dmac'], pt, layer5.seq, layer5.ts,layer5.ssrc, ts, layer5.cc, layer5.p, layer5.x, layer5.m), ts=ts, **dictinfo) + self.alert('\n\tFrom: {0} ({1}) to {2} ({3}) \n\tPayload Type (7 bits): {4}\n\tSequence Number (16 bits): {5}\n\tTimestamp (32 bits): {6} \n\tSynchronization source (32 bits): {7}\n\tArrival Time: {8} --> {9}\n\tContributing source (32 bits): {10}, Padding (1 bit): {11}, Extension (1 bit): {12}, Marker (1 bit): {13}\n'.format( + udp.info()['sip'], self.smac, udp.info()['dip'], self.dmac, pt, rtppkt.seq, rtppkt.ts, rtppkt.ssrc, udp.info()['ts'], datetime.datetime.utcfromtimestamp( + udp.info()['ts']), rtppkt.cc, rtppkt.p, rtppkt.x, rtppkt.m), **udp.info()) + except dpkt.UnpackError, e: + pass + + if __name__ == '__main__': dObj = DshellDecoder() print dObj diff --git a/decoders/voip/sip.py b/decoders/voip/sip.py index 5dd2c9e..f3715fe 100644 --- a/decoders/voip/sip.py +++ b/decoders/voip/sip.py @@ -2,13 +2,15 @@ # Author: MM - https://github.com/1modm # # The Session Initiation Protocol (SIP) is the IETF protocol for VOIP and other text and multimedia sessions -# and is a communications protocol for signaling and controlling +# and is a communications protocol for signaling and controlling. +# SIP is independent from the underlying transport protocol. It runs on the Transmission Control Protocol (TCP), +# the User Datagram Protocol (UDP) or the Stream Control Transmission Protocol (SCTP) # # Rate and codec calculation thanks to https://git.ucd.ie/volte-and-of/voip-pcapy # # RFC: https://www.ietf.org/rfc/rfc3261.txt # -# SIP is a text-based protocol with syntax similar to that of HTTP. +# SIP is a text-based protocol with syntax similar to that of HTTudp. # There are two different types of SIP messages: requests and responses. # - Requests initiate a SIP transaction between two SIP entities for establishing, controlling, and terminating sessions. # - Responses are send by the user agent server indicating the result of a received request. @@ -39,33 +41,35 @@ # | | # - - import dshell -import output -import util import dpkt import datetime -from struct import unpack -import socket +import colorout - -class DshellDecoder(dshell.Decoder): +class DshellDecoder(dshell.UDPDecoder): def __init__(self): - dshell.Decoder.__init__(self, + dshell.UDPDecoder.__init__(self, name='sip', description='Session Initiation Protocol (SIP) capture decoder', longdescription=""" The Session Initiation Protocol (SIP) decoder will extract the Call ID, User agent, Codec, Method, -SIP call, Host, and Client MAC address from every SIP request or response packet found -in the given pcap using by default the port 5060. +SIP call, Host, and Client MAC address from every SIP request or response packet found in the given pcap. General usage: - decode -d sip - or - decode -d sip --sip_port=5062 + +Detailed usage: + decode -d sip --sip_showpkg + +Layer2 sll usage: + decode -d sip --no-vlan --layer2=sll.SLL + +SIP over TCP: + decode -d sip --bpf 'tcp' + +SIP is a text-based protocol with syntax similar to that of HTTP, so you can use followstream decoder: + decode -d followstream --ebpf 'port 5060' --bpf 'udp' Examples: @@ -75,140 +79,152 @@ def __init__(self): decode -d sip metasploit-sip-invite-spoof.pcap decode -d sip Sample_SIP_call_with_RTP_in_G711.pcap - Output: - - sip 2016-09-21 23:44:20 10.5.1.7:5060 -- 10.1.30.60:5060 ** - --> SIP Request <-- - From: 10.5.1.7 (81:89:23:d6:c2:a1) to 10.1.30.60 (a1:03:fc:f2:01:bc) - Sequence and Method: 414 PUBLISH - Via: SIP/2.0/UDP 10.5.1.7:5060;branch=z9hG1bK8e35adab-ba7e-e611-937f-68a3c4f0d5ce;rport - SIP call: --> - With: Ekiga/4.0.1 - Call ID: ee8ace41-ab7e-e511-917f-64a3a4f0d5ce@ProBook - ** - sip 2016-09-21 23:44:27 10.5.1.7:5060 -- 10.5.1.8:5060 ** - --> SIP Response <-- - From: 10.5.1.7 (00:00:00:00:00:00) to 10.5.1.8 (a1:03:fc:f2:02:bc) - Sequence and Method: 1 INVITE - Via: SIP/2.0/UDP 10.5.1.8:5060;branch=z2hG4bK25a8d5a4-8a13-1920-9d58-04002772a5e9;rport=5060;received=10.5.1.8 - SIP call: "M" ;tag=0ba2d5c4-8a13-1910-9d55-08002772a6e9 --> "miguel" ;tag=84548c9d-ba7e-e611-937f-68a3c4f0d5ce - With: Ekiga/4.0.1 - Call ID: 0ba2d7c4-8a13-1940-9d57-08002372a6e9@M-PC - Allow: INVITE,ACK,OPTIONS,BYE,CANCEL,SUBSCRIBE,NOTIFY,REFER,MESSAGE,INFO,PING,PRACK - Codec: PCMU - Rate: 8000 Hz - ** - """, - filter='', +Output: + + <-- SIP Request --> + Timestamp: 2016-09-21 22:44:28.220185 UTC - Protocol: UDP - Size: 435 bytes + Sequence and Method: 1 ACK + From: 10.5.1.8:5060 (00:20:80:a1:13:db) to 10.5.1.7:5060 (15:2a:01:b4:0f:47) + Via: SIP/2.0/UDP 10.5.1.8:5060;branch=z9hG4bK940bdac4-8a13-1410-9e58-08002772a6e9;rport + SIP call: "M" ;tag=0ba2d5c4-8a13-1910-9d56-08002772a6e9 --> "miguel" ;tag=84538c9d-ba7e-e611-937f-68a3c4f0d6ce + Call ID: 0ba2d5c4-8a13-1910-9d57-08002772a6e9@M-PC + + --> SIP Response <-- + Timestamp: 2016-09-21 22:44:27.849761 UTC - Protocol: UDP - Size: 919 bytes + Sequence and Method: 1 INVITE + From: 10.5.1.7:5060 (02:0a:40:12:30:23) to 10.5.1.8:5060 (d5:02:03:94:31:1b) + Via: SIP/2.0/UDP 10.5.1.8:5060;branch=z9hG4bK26a8d5c4-8a13-1910-9d58-08002772a6e9;rport=5060;received=10.5.1.8 + SIP call: "M" ;tag=0ba2d5c4-8a13-1910-9d56-08002772a6e9 --> "miguel" ;tag=84538c9d-ba7e-e611-937f-68a3c4f0d6ce + Call ID: 0ba2d5c4-8a13-1910-9d57-08002772a6e9@M-PC + Codec selected: PCMU + Rate selected: 8000 + +Detailed Output: + + --> SIP Response <-- + Timestamp: 2016-09-21 22:44:25.360974 UTC - Protocol: UDP - Size: 349 bytes + From: 10.5.1.7:5060 (15:2a:01:b4:0f:47) to 10.5.1.8:5060 (00:20:80:a1:13:db) + SIP/2.0 100 Trying + content-length: 0 + via: SIP/2.0/UDP 10.5.1.8:5060;branch=z9hG4bK26a8d5c4-8a13-1910-9d58-08002772a6e9;rport=5060;received=10.5.1.8 + from: "M" ;tag=0ba2d5c4-8a13-1910-9d56-08002772a6e9 + to: + cseq: 1 INVITE + call-id: 0ba2d5c4-8a13-1910-9d57-08002772a6e9@M-PC + + --> SIP Response <-- + Timestamp: 2016-09-21 22:44:25.387780 UTC - Protocol: UDP - Size: 585 bytes + From: 10.5.1.7:5060 (15:2a:01:b4:0f:47) to 10.5.1.8:5060 (00:20:80:a1:13:db) + SIP/2.0 180 Ringing + content-length: 0 + via: SIP/2.0/UDP 10.5.1.8:5060;branch=z9hG4bK26a8d5c4-8a13-1910-9d58-08002772a6e9;rport=5060;received=10.5.1.8 + from: "M" ;tag=0ba2d5c4-8a13-1910-9d56-08002772a6e9 + require: 100rel + rseq: 694867676 + user-agent: Ekiga/4.0.1 + to: "miguel" ;tag=84538c9d-ba7e-e611-937f-68a3c4f0d6ce + contact: "miguel" + cseq: 1 INVITE + allow: INVITE,ACK,OPTIONS,BYE,CANCEL,SUBSCRIBE,NOTIFY,REFER,MESSAGE,INFO,PING,PRACK + call-id: 0ba2d5c4-8a13-1910-9d57-08002772a6e9@M-PC +""", + filter='udp', author='mm', asdatetime=True, optiondict={ - 'port':{'type':'int', - 'default': 5060, - 'help':'SIP Port used (Default: 5060)'} + 'showpkt': {'action': 'store_true', 'default': False, 'help': 'Display the full SIP response or request body.'} } - ) - - def rawHandler(self, dlen, data, ts, **kw): - """Packet handle function - Args: - dlen: length - data: packet - ts: timestamp - kw: kwargs - keyword arguments - """ - - if self.verbose: - self.log("%.06f %d\n%s" % (ts, dlen, util.hexPlusAscii(str(data)))) - - packetype = "VoIP" # by default :) - - try: - # If Ethernet is being replaced by Linux Cooked Capture - # the traces are encapsulated similarly but we need to use dpkt.sll.SLL(data) - # rather than dpkt.ethernet.Ethernet(data) - eth = "SLL" - ethsll = dpkt.sll.SLL(str(data)) - ethethernet = dpkt.ethernet.Ethernet(str(data)) - layer3 = ethsll.data - layer4 = layer3.data - except AttributeError: - eth = "Ethernet" - ethethernet = dpkt.ethernet.Ethernet(str(data)) - # Check if string to discard - if not isinstance(ethethernet.data, basestring): - layer3 = ethethernet.data - layer4 = layer3.data - - # Make sure the Ethernet data contains an IP packet - if (eth == "SLL"): - if not (ethsll.data.__class__.__name__ == "IP"): - # ARP, IPv6 - packetype = "ARP or Non IP" - else: - if not (ethethernet.data.__class__.__name__ == "IP"): - # ARP, IPv6 - packetype = "ARP or Non IP" + ) - # Discard IGMP and ICMP packets + self.out = colorout.ColorOutput() + self.rate = None + self.codec = None + self.smac = None + self.dmac = None + self.direction = None + self.output = None + + def preModule(self): + if 'setColorMode' in dir(self.out): + self.out.setColorMode() + + def packetHandler(self, udp, data): + + # Initialize + self.output = False + self.rate = str() + self.codec = str() + self.direction = str() + + # Check if exists SIP Request try: - if isinstance(layer3.data, dpkt.igmp.IGMP): - packetype = "IGMP" - except AttributeError: + if dpkt.sip.Request(data): + siptxt = "<-- SIP Request -->" + sippkt = dpkt.sip.Request(data) + self.direction = "sc" + self.output = True + except dpkt.UnpackError, e: pass + # Check if exists SIP Response try: - if isinstance(layer3.data, dpkt.icmp.ICMP): - packetype = "ICMP" - except AttributeError: + if dpkt.sip.Response(data): + siptxt = "--> SIP Response <--" + sippkt = dpkt.sip.Response(data) + self.direction = "cs" + self.output = True + except dpkt.UnpackError, e: pass - # Process packets with Layer 5 data and port defined for SIP - if (packetype == "VoIP"): - src = socket.inet_ntoa(layer3.src) - dst = socket.inet_ntoa(layer3.dst) - sipport = self.port - dictinfo = {'sip': src, 'dip': dst, 'sport': layer4.sport, 'dport': layer4.dport} - - # SIP REQUEST and SIP RESPONSE - if (layer4.dport==sipport or layer4.sport==sipport) and len(layer4.data) > 0: - sip_packet = False - try: - layer5 = dpkt.sip.Request(layer4.data) - sip_type = "SIP Request" - sip_packet = True - except dpkt.UnpackError, e: - try: - layer5 = dpkt.sip.Response(layer4.data) - sip_type = "SIP Response" - sip_packet = True - except dpkt.UnpackError, e: - pass - - finally: - if (sip_packet): - user_agent = layer5.headers.get('user-agent') - allow = layer5.headers.get('allow') - l5_from = layer5.headers.get('from') - l5_to = layer5.headers.get('to') - l5_callid = layer5.headers.get('call-id') - via = layer5.headers.get('via') - cseq = layer5.headers.get('cseq') - rate = "" - codec = "" - for x in range(layer5.body.find(' ',layer5.body.find('a='))+1,layer5.body.find('/',layer5.body.find('a='))): - codec += layer5.body[x] - for x in range(layer5.body.find(' ',layer5.body.find('a='))+6,layer5.body.find('/',layer5.body.find('a='))+5): - rate+=layer5.body[x] - - if src and dst and layer5.headers: - if not allow: - self.alert('\n\t--> {0} <--\n\tFrom: {1} ({2}) to {3} ({4}) \n\tSequence and Method: {5}\n\tVia: {6}\n\tSIP call: {7} --> {8} \n\tWith: {9}\n\tCall ID: {10}\n'.format(sip_type, src, - kw['smac'], dst, kw['dmac'], cseq, via, l5_from, - l5_to, user_agent, l5_callid), ts=ts, **dictinfo) - else: - self.alert('\n\t--> {0} <--\n\tFrom: {1} ({2}) to {3} ({4}) \n\tSequence and Method: {5}\n\tVia: {6}\n\tSIP call: {7} --> {8} \n\tWith: {9}\n\tCall ID: {10}\n\tAllow: {11}\n\tCodec: {12}\n\tRate: {13} Hz\n'.format(sip_type, src, - kw['smac'], dst, kw['dmac'], cseq, via, l5_from, - l5_to, user_agent, l5_callid, allow, codec, rate), ts=ts, **dictinfo) + # If a SIP request or SIP response exists, print the results + if self.output: + # Get MAC addr for layer2 packets + try: + self.smac = udp.info()['smac'] + except LookupError: + ethernet = dpkt.ethernet.Ethernet(data) + self.smac = ':'.join('%02x' % ord(b) for b in ethernet.src) + + try: + self.dmac = udp.info()['dmac'] + except LookupError: + ethernet = dpkt.ethernet.Ethernet(data) + self.dmac = ':'.join('%02x' % ord(b) for b in ethernet.dst) + + # Common output + self.out.write("\n{0} \nTimestamp: {1} UTC - Protocol: {2} - Size: {3} bytes\n".format(siptxt, datetime.datetime.utcfromtimestamp( + udp.info()['ts']), udp.info()['proto'], udp.info()['bytes']), formatTag="H2", direction=self.direction) + self.out.write("From: {0}:{1} ({2}) to {3}:{4} ({5}) \n".format(udp.info()['sip'], udp.info()['sport'], self.smac, + udp.info()['dip'], udp.info()['dport'], self.dmac), formatTag="H2", direction=self.direction) + + # Show full SIP packet detail + if self.showpkt: + self.out.write("{0}\n".format(sippkt), formatTag="H2", direction=self.direction) + + # Show minimum SIP Requests or Responses headers + else: + user_agent = sippkt.headers.get('user-agent') + allow = sippkt.headers.get('allow') + sip_from = sippkt.headers.get('from') + sip_to = sippkt.headers.get('to') + sip_callid = sippkt.headers.get('call-id') + via = sippkt.headers.get('via') + cseq = sippkt.headers.get('cseq') + + if cseq: + self.out.write("Sequence and Method: {0}\n".format(cseq), formatTag="H2", direction=self.direction) + + if via: + self.out.write("Via: {0}\nSIP call: {1} --> {2}\nCall ID: {3}\n".format(via, + sip_from, sip_to, sip_callid), formatTag="H2", direction=self.direction) + + # codec and rate negotiated + for x in range(sippkt.body.find(' ',sippkt.body.find('a='))+1,sippkt.body.find('/',sippkt.body.find('a='))): + self.codec += sippkt.body[x] + for x in range(sippkt.body.find(' ',sippkt.body.find('a='))+6,sippkt.body.find('/',sippkt.body.find('a='))+5): + self.rate +=sippkt.body[x] + + if (self.codec and self.rate): + self.out.write("Codec selected: {0} \nRate selected: {1} \n".format(self.codec, self.rate), formatTag="H2", direction=self.direction) if __name__ == '__main__': dObj = DshellDecoder() From 69125523378b5a80ea81ef2d495d7cbeaba4ec36 Mon Sep 17 00:00:00 2001 From: M <1modm@users.noreply.github.com> Date: Thu, 13 Oct 2016 10:56:20 +0100 Subject: [PATCH 061/166] usage change --- decoders/voip/sip.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/decoders/voip/sip.py b/decoders/voip/sip.py index f3715fe..9fcca5f 100644 --- a/decoders/voip/sip.py +++ b/decoders/voip/sip.py @@ -60,7 +60,7 @@ def __init__(self): decode -d sip Detailed usage: - decode -d sip --sip_showpkg + decode -d sip --sip_showpkt Layer2 sll usage: decode -d sip --no-vlan --layer2=sll.SLL @@ -230,4 +230,4 @@ def packetHandler(self, udp, data): dObj = DshellDecoder() print dObj else: - dObj = DshellDecoder() \ No newline at end of file + dObj = DshellDecoder() From 347a4e3cb121cc4e167e81247468d93f5d2392cc Mon Sep 17 00:00:00 2001 From: dev195 Date: Fri, 14 Oct 2016 13:13:58 -0400 Subject: [PATCH 062/166] Updated dshell.py to capture the source MAC address from SLL traffic --- lib/dshell.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/lib/dshell.py b/lib/dshell.py index d96b74a..6819225 100755 --- a/lib/dshell.py +++ b/lib/dshell.py @@ -431,6 +431,14 @@ def decode(self, *args, **kw): except struct.error: # couldn't get MAC address smac, dmac = None, None kw.update(smac=smac, dmac=dmac) + elif type(pkt) == dpkt.sll.SLL: + if pkt.type in (0, 4) and pkt.hrd == 1: + try: + smac = "%02x:%02x:%02x:%02x:%02x:%02x" % (struct.unpack("BBBBBB", pkt.hdr[:pkt.hlen])) + dmac = None + except struct.error: + smac, dmac = None, None + kw.update(smac=smac, dmac=None) # strip any intermediate layers (PPPoE, etc) for _ in xrange(int(self.striplayers)): pkt = pkt.data @@ -700,7 +708,6 @@ def TCP(self, addr, tcp, ts, **kwargs): conn = self.find(addr) if tcp.flags & (dpkt.tcp.TH_FIN | dpkt.tcp.TH_RST) and conn: conn.closeIP(addr[0]) #track if FIN has been seen in connection - if conn and conn.connectionClosed(): # we might occasionally have data in a FIN packet self.track(addr, str(tcp.data), ts, offset=tcp.seq) @@ -915,7 +922,7 @@ def __repr__(self): def connectionClosed(self): return self.serverclosed and self.clientclosed - + def closeIP(self, tuple): ''' Track if we have seen a FIN packet from given tuple From 5a65fb2fa9a6d7d30d3f09ca5a264295433e8a58 Mon Sep 17 00:00:00 2001 From: J Date: Tue, 18 Oct 2016 08:31:34 -0400 Subject: [PATCH 063/166] Update MAC address handling for SLL in dshell.py Altered MAC address handling for SLL protocol. Will now attempt to collect MAC address no matter the type. --- lib/dshell.py | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/lib/dshell.py b/lib/dshell.py index 6819225..2587a63 100755 --- a/lib/dshell.py +++ b/lib/dshell.py @@ -432,13 +432,14 @@ def decode(self, *args, **kw): smac, dmac = None, None kw.update(smac=smac, dmac=dmac) elif type(pkt) == dpkt.sll.SLL: - if pkt.type in (0, 4) and pkt.hrd == 1: - try: - smac = "%02x:%02x:%02x:%02x:%02x:%02x" % (struct.unpack("BBBBBB", pkt.hdr[:pkt.hlen])) - dmac = None - except struct.error: - smac, dmac = None, None - kw.update(smac=smac, dmac=None) + try: + # Sometimes MAC address will show up as 00:00:00:00:00:00 + # TODO decide if it should be set to None or kept as-is + smac = "%02x:%02x:%02x:%02x:%02x:%02x" % (struct.unpack("BBBBBB", pkt.hdr[:pkt.hlen])) + dmac = None + except struct.error: + smac, dmac = None, None + kw.update(smac=smac, dmac=dmac) # strip any intermediate layers (PPPoE, etc) for _ in xrange(int(self.striplayers)): pkt = pkt.data From 8fe7c2962c7bc745b54dbdec32beebbf7b866dc1 Mon Sep 17 00:00:00 2001 From: 1_modm Date: Tue, 18 Oct 2016 21:47:15 +0100 Subject: [PATCH 064/166] Update decoders to update MAC address handling for SLL in dshell --- decoders/voip/rtp.py | 29 ++++++----------------------- decoders/voip/sip.py | 30 +++++++----------------------- 2 files changed, 13 insertions(+), 46 deletions(-) diff --git a/decoders/voip/rtp.py b/decoders/voip/rtp.py index 34946da..a4f242e 100644 --- a/decoders/voip/rtp.py +++ b/decoders/voip/rtp.py @@ -10,7 +10,6 @@ # https://tools.ietf.org/html/rfc2198 # https://tools.ietf.org/html/rfc4855 # https://www.iana.org/assignments/rtp-parameters/rtp-parameters.xhtml -# import dshell import dpkt @@ -60,10 +59,8 @@ def __init__(self): ** """, filter='udp', - author='mm', asdatetime=True, + author='mm' ) - self.smac = None - self.dmac = None def preModule(self): self.payload_type = {0: "PCMU - Audio - 8000 Hz - 1 Channel", 1: "Reserved", 2: "Reserved", 3: "GSM - Audio - 8000 Hz - 1 Channel", @@ -86,33 +83,19 @@ def preModule(self): self.payload_type[i] = "Dynamic" def packetHandler(self, udp, data): - - # Get MAC addr for layer2 packets - try: - self.smac = udp.info()['smac'] - except LookupError: - ethernet = dpkt.ethernet.Ethernet(data) - self.smac = ':'.join('%02x' % ord(b) for b in ethernet.src) - try: - self.dmac = udp.info()['dmac'] - except LookupError: - ethernet = dpkt.ethernet.Ethernet(data) - self.dmac = ':'.join('%02x' % ord(b) for b in ethernet.dst) - - try: - if dpkt.rtp.RTP(str(data)): + if dpkt.rtp.RTP(data): rtppkt = dpkt.rtp.RTP(data) pt = self.payload_type.get(rtppkt.pt) self.alert('\n\tFrom: {0} ({1}) to {2} ({3}) \n\tPayload Type (7 bits): {4}\n\tSequence Number (16 bits): {5}\n\tTimestamp (32 bits): {6} \n\tSynchronization source (32 bits): {7}\n\tArrival Time: {8} --> {9}\n\tContributing source (32 bits): {10}, Padding (1 bit): {11}, Extension (1 bit): {12}, Marker (1 bit): {13}\n'.format( - udp.info()['sip'], self.smac, udp.info()['dip'], self.dmac, pt, rtppkt.seq, rtppkt.ts, rtppkt.ssrc, udp.info()['ts'], datetime.datetime.utcfromtimestamp( - udp.info()['ts']), rtppkt.cc, rtppkt.p, rtppkt.x, rtppkt.m), **udp.info()) - + udp.sip, udp.smac, udp.dip, udp.dmac, pt, rtppkt.seq, rtppkt.ts, rtppkt.ssrc, + udp.ts, datetime.datetime.utcfromtimestamp(udp.ts), + rtppkt.cc, rtppkt.p, rtppkt.x, rtppkt.m), **udp.info()) + except dpkt.UnpackError, e: pass - if __name__ == '__main__': dObj = DshellDecoder() print dObj diff --git a/decoders/voip/sip.py b/decoders/voip/sip.py index 9fcca5f..7850dc1 100644 --- a/decoders/voip/sip.py +++ b/decoders/voip/sip.py @@ -10,7 +10,7 @@ # # RFC: https://www.ietf.org/rfc/rfc3261.txt # -# SIP is a text-based protocol with syntax similar to that of HTTudp. +# SIP is a text-based protocol with syntax similar to that of HTTP. # There are two different types of SIP messages: requests and responses. # - Requests initiate a SIP transaction between two SIP entities for establishing, controlling, and terminating sessions. # - Responses are send by the user agent server indicating the result of a received request. @@ -129,7 +129,7 @@ def __init__(self): call-id: 0ba2d5c4-8a13-1910-9d57-08002772a6e9@M-PC """, filter='udp', - author='mm', asdatetime=True, + author='mm', optiondict={ 'showpkt': {'action': 'store_true', 'default': False, 'help': 'Display the full SIP response or request body.'} } @@ -138,8 +138,6 @@ def __init__(self): self.out = colorout.ColorOutput() self.rate = None self.codec = None - self.smac = None - self.dmac = None self.direction = None self.output = None @@ -148,7 +146,6 @@ def preModule(self): self.out.setColorMode() def packetHandler(self, udp, data): - # Initialize self.output = False self.rate = str() @@ -177,30 +174,17 @@ def packetHandler(self, udp, data): # If a SIP request or SIP response exists, print the results if self.output: - # Get MAC addr for layer2 packets - try: - self.smac = udp.info()['smac'] - except LookupError: - ethernet = dpkt.ethernet.Ethernet(data) - self.smac = ':'.join('%02x' % ord(b) for b in ethernet.src) - - try: - self.dmac = udp.info()['dmac'] - except LookupError: - ethernet = dpkt.ethernet.Ethernet(data) - self.dmac = ':'.join('%02x' % ord(b) for b in ethernet.dst) - # Common output self.out.write("\n{0} \nTimestamp: {1} UTC - Protocol: {2} - Size: {3} bytes\n".format(siptxt, datetime.datetime.utcfromtimestamp( - udp.info()['ts']), udp.info()['proto'], udp.info()['bytes']), formatTag="H2", direction=self.direction) - self.out.write("From: {0}:{1} ({2}) to {3}:{4} ({5}) \n".format(udp.info()['sip'], udp.info()['sport'], self.smac, - udp.info()['dip'], udp.info()['dport'], self.dmac), formatTag="H2", direction=self.direction) + udp.ts), udp.proto, udp.info()['bytes']), formatTag="H2", direction=self.direction) + self.out.write("From: {0}:{1} ({2}) to {3}:{4} ({5}) \n".format(udp.sip, udp.sport, udp.smac, + udp.dip, udp.dport, udp.dmac), formatTag="H2", direction=self.direction) # Show full SIP packet detail if self.showpkt: self.out.write("{0}\n".format(sippkt), formatTag="H2", direction=self.direction) - # Show minimum SIP Requests or Responses headers + # Show essential SIP Requests or Responses headers else: user_agent = sippkt.headers.get('user-agent') allow = sippkt.headers.get('allow') @@ -230,4 +214,4 @@ def packetHandler(self, udp, data): dObj = DshellDecoder() print dObj else: - dObj = DshellDecoder() + dObj = DshellDecoder() \ No newline at end of file From 39cdf83be560409df51dcfea0002534befff139a Mon Sep 17 00:00:00 2001 From: adam Date: Wed, 16 Nov 2016 20:39:53 +0000 Subject: [PATCH 065/166] When output modules are instantiated in the decoder __init__, they are not closed by decode.py --- decoders/misc/followstream.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/decoders/misc/followstream.py b/decoders/misc/followstream.py index ea1e1c7..be89d97 100644 --- a/decoders/misc/followstream.py +++ b/decoders/misc/followstream.py @@ -70,6 +70,9 @@ def preModule(self): # overwrite the output module's default error handler self.out.errorH = self.__errorHandler + def postModule(self): + self.out.close() + def connectionHandler(self, connection): try: From fa24358eda8e250ef8a2fe87c668c5eb454bf09e Mon Sep 17 00:00:00 2001 From: adam Date: Mon, 28 Nov 2016 20:40:09 +0000 Subject: [PATCH 066/166] Attempting to fix behavior of default nextoffset selection when using ignore_handshake flag. --- lib/dshell.py | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/lib/dshell.py b/lib/dshell.py index 2587a63..a206055 100755 --- a/lib/dshell.py +++ b/lib/dshell.py @@ -730,6 +730,18 @@ def TCP(self, addr, tcp, ts, **kwargs): # all other states, or always if ignoring handshake if self.ignore_handshake or self.find(addr, state='established'): + # When ignoring handshakes, we can be tolerant of unknown nextoffsets and set them by inference + if self.ignore_handshake: + if not conn: + conn = self.track(addr, ts=ts, state='init', **kwargs) + if addr == conn.addr: + # Direction for this packet is CS + if conn.nextoffset['cs'] == None: + conn.nextoffset['cs'] = tcp.seq + 1 + else: + # Direction for this packet is SC + if conn.nextoffset['sc'] == None: + conn.nextoffset['sc'] = tcp.seq + 1 self.track(addr, str(tcp.data), ts, state='established', offset=tcp.seq, **kwargs) @@ -875,7 +887,7 @@ class Connection(Packet): def __init__(self, decoder, addr, ts=None, **kwargs): self.state = None # the offset we expect for the next blob in this direction - self.nextoffset = {'cs': 0, 'sc': 0} + self.nextoffset = {'cs': None, 'sc': None} # init IP-level data Packet.__init__(self, decoder, addr, ts=ts, **kwargs) self.clientip, self.clientport, self.serverip, self.serverport = ( From 4e77d600b16826d878eabdbd531303b3d677603b Mon Sep 17 00:00:00 2001 From: J Date: Tue, 29 Nov 2016 11:02:25 -0500 Subject: [PATCH 067/166] Update dshell.py to better handle --ignore_handshake Another update to have dshell.py better handle --ignore_handshake flags for decoders. This update tries to clean up the TCPDecoder.TCP function and fix a bug in the UDPDecoder.UDP function. --- lib/dshell.py | 78 ++++++++++++++++++++++++++++----------------------- 1 file changed, 43 insertions(+), 35 deletions(-) diff --git a/lib/dshell.py b/lib/dshell.py index a206055..d503a04 100755 --- a/lib/dshell.py +++ b/lib/dshell.py @@ -637,6 +637,10 @@ def UDP(self, addr, data, pkt, ts=None, **kwargs): return self.packetHandler(udp=Packet(self, addr, pkt=pkt, ts=ts, **kwargs), data=data) # if no PacketHandler, we need to track state + if not self.find(addr): + conn = self.track(addr, ts=ts, state='init', **kwargs) + conn.nextoffset['cs'] = 0 + conn.nextoffset['sc'] = 0 self.track(addr, data, ts, **kwargs) except Exception, e: @@ -705,45 +709,49 @@ def TCP(self, addr, tcp, ts, **kwargs): self.count += 1 try: - # close connection + # attempt to find an existing connection for this address conn = self.find(addr) - if tcp.flags & (dpkt.tcp.TH_FIN | dpkt.tcp.TH_RST) and conn: - conn.closeIP(addr[0]) #track if FIN has been seen in connection - if conn and conn.connectionClosed(): - # we might occasionally have data in a FIN packet - self.track(addr, str(tcp.data), ts, offset=tcp.seq) - self.close(conn, ts) - # init connection, set TCP ISN - elif not self.ignore_handshake and (tcp.flags == dpkt.tcp.TH_SYN or tcp.flags == dpkt.tcp.TH_SYN | dpkt.tcp.TH_CWR | dpkt.tcp.TH_ECE): - if conn: - self.track(addr, str(tcp.data), ts, offset=tcp.seq) - self.close(conn, ts) - conn = self.track(addr, ts=ts, state='init', **kwargs) - if conn: + + if self.ignore_handshake: + # if we are ignoring handshakes, we will track all connections, + # even if we did not see the initialization handshake. + if not conn: + conn = self.track(addr, ts=ts, state='init', **kwargs) + # align the sequence numbers when we first see a connection + if conn.nextoffset['cs'] is None and addr == conn.addr: conn.nextoffset['cs'] = tcp.seq + 1 - # SYN ACK - elif not self.ignore_handshake and tcp.flags == (dpkt.tcp.TH_SYN | dpkt.tcp.TH_ACK): - conn = self.find(addr, state='init') - if conn and tcp.ack == conn.nextoffset['cs']: + elif conn.nextoffset['sc'] is None and addr != conn.addr: conn.nextoffset['sc'] = tcp.seq + 1 - conn.state = 'established' - - # all other states, or always if ignoring handshake - if self.ignore_handshake or self.find(addr, state='established'): - # When ignoring handshakes, we can be tolerant of unknown nextoffsets and set them by inference - if self.ignore_handshake: - if not conn: - conn = self.track(addr, ts=ts, state='init', **kwargs) - if addr == conn.addr: - # Direction for this packet is CS - if conn.nextoffset['cs'] == None: - conn.nextoffset['cs'] = tcp.seq + 1 - else: - # Direction for this packet is SC - if conn.nextoffset['sc'] == None: - conn.nextoffset['sc'] = tcp.seq + 1 self.track(addr, str(tcp.data), ts, - state='established', offset=tcp.seq, **kwargs) + state='established', offset=tcp.seq, **kwargs) + + else: + # otherwise, only track connections if we see a TCP handshake + if (tcp.flags == dpkt.tcp.TH_SYN + or tcp.flags == dpkt.tcp.TH_SYN | dpkt.tcp.TH_CWR | dpkt.tcp.TH_ECE): + # SYN + if conn: + # if a connection already exists for the addr, + # close the old one to start fresh + self.close(conn, ts) + conn = self.track(addr, ts=ts, state='init', **kwargs) + if conn: + conn.nextoffset['cs'] = tcp.seq + 1 + elif tcp.flags == (dpkt.tcp.TH_SYN | dpkt.tcp.TH_ACK): + # SYN ACK + if conn and tcp.ack == conn.nextoffset['cs']: + conn.nextoffset['sc'] = tcp.seq + 1 + conn.state = 'established' + if conn and conn.state == 'established': + self.track(addr, str(tcp.data), ts, + state='established', offset=tcp.seq, **kwargs) + + # close connection + if conn and tcp.flags & (dpkt.tcp.TH_FIN | dpkt.tcp.TH_RST): + # flag that an IP is closing a connection with FIN or RST + conn.closeIP(addr[0]) + if conn and conn.connectionClosed(): + self.close(conn, ts) except Exception, e: self._exc(e) From 7328fe83043c9b221bec8df787fdbec2cae9d1bc Mon Sep 17 00:00:00 2001 From: dev195 Date: Tue, 11 Apr 2017 08:46:38 -0400 Subject: [PATCH 068/166] fixed maxblobs bug in dshell.py --- lib/dshell.py | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/lib/dshell.py b/lib/dshell.py index d503a04..c8e4588 100755 --- a/lib/dshell.py +++ b/lib/dshell.py @@ -386,14 +386,7 @@ def track(self, addr, data=None, ts=None, offset=None, **kwargs): else: direction = 'sc' - # check direction and blob count. - # If we have switched direction but already have max blobs - # close connection and replace it with a new one - if self.maxblobs and (direction != conn.direction) and (len(conn.blobs) == self.maxblobs): - self.close(conn) # close and call handlers - # recurse to create a new connection for the next - # request/response - return self.track(addr, data, ts) + original_direction = conn.direction # update the connection to update current blob or start a new one # and return the last one @@ -401,6 +394,16 @@ def track(self, addr, data=None, ts=None, offset=None, **kwargs): blob = conn.update(ts, direction, data, offset=offset) if blob and self.isBlobHandlerPresent: self.blobHandler(conn, blob) + + # check direction and blob count. + # If we have switched direction but already have max blobs + # close connection and replace it with a new one + if self.maxblobs and (direction != original_direction) and (len(conn.blobs) >= self.maxblobs): + self.close(conn) # close and call handlers + # recurse to create a new connection for the next + # request/response + return self.track(addr, ts=ts, **kwargs) + # we can discard all but the last blob if not self.isConnectionHandlerPresent: while len(conn.blobs) > 1: @@ -637,9 +640,12 @@ def UDP(self, addr, data, pkt, ts=None, **kwargs): return self.packetHandler(udp=Packet(self, addr, pkt=pkt, ts=ts, **kwargs), data=data) # if no PacketHandler, we need to track state - if not self.find(addr): + conn = self.find(addr) + if not conn: conn = self.track(addr, ts=ts, state='init', **kwargs) + if conn.nextoffset['cs'] is None: conn.nextoffset['cs'] = 0 + if conn.nextoffset['sc'] is None: conn.nextoffset['sc'] = 0 self.track(addr, data, ts, **kwargs) From 93a6ede821419534d4c52985a7535115ac59a733 Mon Sep 17 00:00:00 2001 From: DC3-DCCI Date: Tue, 16 May 2017 14:30:37 -0400 Subject: [PATCH 069/166] Fixes blob reconstruction in cases where multiple packets of different sizes were sent. This takes the approach that we should always take the largest data packet since they should all contain the same data. --- lib/dshell.py | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/lib/dshell.py b/lib/dshell.py index c8e4588..be2692b 100755 --- a/lib/dshell.py +++ b/lib/dshell.py @@ -1050,7 +1050,7 @@ def __str__(self): '''returns segments of blob as string''' return self.data(padding='') - def data(self, errorHandler=None, padding=None, overlap=True, caller=None, dup=-1): + def data(self, errorHandler=None, padding=None, overlap=True, caller=None): '''returns segments of blob reassembled into a string if next segment offset is not the expected offset errorHandler(blob,expected,offset) will be called @@ -1067,6 +1067,7 @@ def data(self, errorHandler=None, padding=None, overlap=True, caller=None, dup=- dup: how to handle duplicate segments: 0: use first segment seen -1 (default): use last segment seen + changing duplicate segment handling to always take largest segment ''' d = '' nextoffset = self.startoffset @@ -1086,12 +1087,17 @@ def data(self, errorHandler=None, padding=None, overlap=True, caller=None, dup=- raise KeyError(nextoffset) elif segoffset < nextoffset and not overlap: continue # skip if not allowing overlap + #find most data in segments + seg = '' + for x in self.segments[segoffset]: + if len(x) > len(seg): + seg = x # advance next expected offset nextoffset = ( - segoffset + len(self.segments[segoffset][dup])) & self.MAX_OFFSET + segoffset + len(seg)) & self.MAX_OFFSET # append or splice data d = d[:segoffset - self.startoffset] + \ - self.segments[segoffset][dup] + \ + seg + \ d[nextoffset - self.startoffset:] return d From c0b7ef90978608d015a561520aa9f56a36c1f581 Mon Sep 17 00:00:00 2001 From: 1_modm Date: Tue, 20 Jun 2017 22:06:25 +0100 Subject: [PATCH 070/166] peht decoder --- decoders/http/peht.py | 260 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 260 insertions(+) create mode 100644 decoders/http/peht.py diff --git a/decoders/http/peht.py b/decoders/http/peht.py new file mode 100644 index 0000000..c39926a --- /dev/null +++ b/decoders/http/peht.py @@ -0,0 +1,260 @@ +# +# Author: MM - https://github.com/1modm +# +# Most of the Penetration/Exploit/Hijacking Tools use the HTTP methods to try to inject +# or execute code into the attacked server, also this tools usually have a well known +# "hardcoded" User-Agent, URI or request content. +# +# So if the original scanner is not modified can be detected. This is a PoC in order to generate +# simple rules to detect and identified some of the most commons Penetration/Exploit/Hijacking Tools. +# +# Some of the most commons tools source and information: +# +# Nmap +# User-Agent header by default it is "Mozilla/5.0 (compatible; Nmap Scripting Engine; https://nmap.org/book/nse.html)". +# https://nmap.org/nsedoc/lib/http.html +# +# OpenVAS +# http://www.openvas.org/src-doc/openvas-libraries/nasl__http_8c_source.html +# User-Agent header by default: #define OPENVAS_USER_AGENT "Mozilla/5.0 [en] (X11, U; OpenVAS)" +# +# MASSCAN +# https://github.com/robertdavidgraham/masscan +# +# Morpheus +# https://github.com/r00t-3xp10it/morpheus +# https://latesthackingnews.com/2016/12/19/morpheus-automated-ettercap-tcpip-hijacking-tool/ +# +# DataCha0s Web Scanner +# http://eromang.zataz.com/2011/05/23/suc026-datacha0s-web-scannerrobot/ +# https://blogs.harvard.edu/zeroday/2006/06/12/data-cha0s-connect-back-backdoor/ +# +# HNAP (Home Network Administration Protocol) +# https://nmap.org/nsedoc/scripts/hnap-info.html +# +# ZmEu Scanner +# https://en.wikipedia.org/wiki/ZmEu_(vulnerability_scanner) +# http://linux.m2osw.com/zmeu-attack +# https://code.google.com/archive/p/caffsec-malware-analysis/wikis/ZmEu.wiki +# https://ensourced.wordpress.com/2011/02/25/zmeu-attacks-some-basic-forensic/ +# http://philriesch.com/computersecurity_zmeu.html +# +# Jorgee Scanner +# http://www.skepticism.us/2015/05/new-malware-user-agent-value-jorgee/ +# https://www.checkpoint.com/defense/advisories/public/2016/cpai-2016-0214.html +# https://blog.paranoidpenguin.net/2017/04/jorgee-goes-on-a-rampage/ + +import re +import util +import dshell +import datetime +import colorout +from httpdecoder import HTTPDecoder + +class DshellDecoder(HTTPDecoder): + + def __init__(self): + HTTPDecoder.__init__(self, + name='peht', + description='Penetration/Exploit/Hijacking Tool detector', + longdescription=""" +The Penetration/Exploit/Hijacking Tool detector will identify the tool used to scan or exploit a server using the +User agent, URI or HTTP content. + +General usage: + decode -d peht + +Detailed usage: + decode -d peht --peht_showcontent + +Output: + + Request Timestamp (UTC): 2017-07-16 02:41:47.238549 + Penetration/Exploit/Hijacking Tool: Open Vulnerability Assessment System + User-Agent: Mozilla/5.0 [en] (X11, U; OpenVAS 8.0.9) + Request Method: GET + URI: /scripts/session/login.php + Source IP: 1.2.3.4 - Source port: 666 - MAC: 50:b4:02:39:24:56 + Host requested: example.com + + Response Timestamp (UTC): 2017-07-16 02:41:48.238549 + Response Reason: Not Found + Response Status: 404 + Destination IP: 192.168.1.1 - Destination port: 80 - MAC: a4:42:ab:56:b6:23 + + + Detailed Output: + + Request Timestamp (UTC): 2017-07-16 02:41:47.238549 + Penetration/Exploit/Hijacking Tool: Arbitrary Remote Code Execution/injection + User-Agent: Wget(linux) + Request Method: POST + URI: /command.php + Source IP: 1.2.3.4 - Source port: 666 - MAC: 50:b4:02:39:24:56 + Host requested: example.com + + cmd=%63%64%20%2F%76%61%72%2F%74%6D%70%20%26%26%20%65%63%68%6F%20%2D%6E%65%20%5C%5C%78%33%6B%65%72%20%3E%20%6B%65%72%2E%74%78%74%20%26%26%20%63%61%74%20%6B%65%72%2E%74%78%74 + + Response Timestamp (UTC): 2017-07-16 02:41:48.238549 + Response Reason: Found + Response Status: 302 + Destination IP: 192.168.1.1 - Destination port: 80 - MAC: a4:42:ab:56:b6:23 + + + + 302 Found + +

Found

+

The document has moved here.

+ + +""", + filter='tcp', + author='mm', + optiondict={ + 'showcontent': {'action': 'store_true', 'default': False, 'help': 'Display the request and response body content.'} + } + ) + + self.out = colorout.ColorOutput() + self.direction = None + self.request_ioc = None + self.request_method = None + self.request_user_agent = None + self.request_host = None + self.request_rangestr = None + self.request_body = None + self.request_referer = None + self.response_content_type = None + self.response_body = None + self.response_contentencoding = None + self.response_status = None + self.response_contentlength = None + self.response_reason = None + + def preModule(self): + if 'setColorMode' in dir(self.out): + self.out.setColorMode() + + def check_payload(self, payloadheader, payloaduri, requestbody): + + ET_identified = None + + r = re.compile(r'\bbash\b | \bcmd\b | \bsh\b | \bwget\b', flags=re.I | re.X) + if r.findall(requestbody): + ET_identified = 'Arbitrary Remote Code Execution/injection' + + if payloadheader.has_key('content-type'): + if ('cmd' and 'ProcessBuilder' and 'struts') in payloadheader['content-type']: + ET_identified = 'Apache Struts Content-Type arbitrary command execution' + + if payloadheader.has_key('user-agent'): + if 'Jorgee' in payloadheader['user-agent']: + ET_identified = 'Jorgee Scanner' + elif 'Nmap' in payloadheader['user-agent']: + ET_identified = 'Nmap' + elif 'masscan' in payloadheader['user-agent']: + ET_identified = 'Mass IP port scanner' + elif ('ZmEu' in payloadheader['user-agent'] and 'w00tw00t' in payloaduri): + ET_identified = 'ZmEu Vulnerability Scanner' + elif 'immoral' in payloadheader['user-agent']: + ET_identified = 'immoral' + elif 'chroot' in payloadheader['user-agent']: + ET_identified = 'chroot' + elif 'DataCha0s' in payloadheader['user-agent']: + ET_identified = 'DataCha0s Web Scanner' + elif 'OpenVAS' in payloadheader['user-agent']: + ET_identified = 'Open Vulnerability Assessment System' + elif ('bash' or 'sh' or 'cmd' or 'wget') in (payloadheader['user-agent']): + ET_identified = 'Arbitrary Remote Code Execution/injection' + + if 'muieblackcat' in payloaduri: + ET_identified = 'Muieblackcat Web Scanner/Robot' + if '/HNAP1/' in payloaduri: + ET_identified = 'Home Network Administration Protocol' + + return ET_identified + + + + def HTTPHandler(self, conn, request, response, requesttime, responsetime): + + if not request: + return + + # Obtain the response content + try: + if 'gzip' in util.getHeader(response, 'content-encoding'): + self.response_body = self.decompressGzipContent(response.body) + if self.response_body == None: + self.response_body = '(gunzip failed)\n' + response.body + else: + self.response_body = '(gzip encoded)\n' + self.response_body + else: + self.response_body = response.body + except AttributeError as e: + self.response_body = None + + # Obtain the request content + try: + if 'gzip' in util.getHeader(request, 'content-encoding'): + self.request_body = self.decompressGzipContent(request.body) + if self.request_body == None: + self.request_body = '(gunzip failed)\n' + request.body + else: + self.request_body = '(gzip encoded)\n' + self.request_body + else: + self.request_body = request.body + except AttributeError as e: + self.request_body = None + + # Identify the Exploit/Hijacking Tool + self.request_ioc = self.check_payload(request.headers, request.uri, self.request_body) + + if self.request_ioc: + + # REQUEST + if request.method in ('GET', 'POST', 'HEAD'): + self.direction = "sc" + self.request_method = request.method + self.request_user_agent = request.headers.get('user-agent') + self.request_host = util.getHeader(request, 'host') + self.request_rangestr = util.getHeader(request,'range') + self.request_body = request.body + self.request_referer = util.getHeader(request, 'referer') + + if request.headers.has_key('user-agent'): + self.request_user_agent = request.headers['user-agent'] + + self.out.write("\nRequest Timestamp (UTC): {0} \nPenetration/Exploit/Hijacking Tool: {1}\nUser-Agent: {2}\nRequest Method: {3}\nURI: {4}\nSource IP: {5} - Source port: {6} - MAC: {7}\nHost requested: {8}\n".format(datetime.datetime.utcfromtimestamp( + requesttime), self.request_ioc, self.request_user_agent, self.request_method, request.uri, conn.sip, conn.sport, conn.smac, self.request_host), formatTag="H2", direction=self.direction) + + # Show request body content + if self.showcontent: + self.out.write("\n{0}\n".format(self.request_body), formatTag="H2", direction=self.direction) + + if not response: + self.direction = "cs" + self.out.write('\nNo response\n', formatTag="H2", direction=self.direction) + + # RESPONSE + else: + self.direction = "cs" + self.response_content_type = util.getHeader(response, 'content-type') + self.response_contentencoding = util.getHeader(response, 'content-encoding') + self.response_status = response.status + self.response_reason = response.reason + + self.out.write("\nResponse Timestamp (UTC): {0} \nResponse Reason: {1}\nResponse Status: {2}\nDestination IP: {3} - Destination port: {4} - MAC: {5}\n".format(datetime.datetime.utcfromtimestamp( + responsetime), self.response_reason, self.response_status, conn.dip, conn.dport, conn.dmac), formatTag="H2", direction=self.direction) + + # Show response body content + if self.showcontent: + self.out.write("\n{0}\n".format(self.response_body), formatTag="H2", direction=self.direction) + + +if __name__ == '__main__': + dObj = DshellDecoder() + print dObj +else: + dObj = DshellDecoder() \ No newline at end of file From aba8d3d9f8f83d6b6e6b6b6448db6aa6428a975f Mon Sep 17 00:00:00 2001 From: DC3-DCCI Date: Fri, 30 Jun 2017 14:17:46 -0400 Subject: [PATCH 071/166] Add instructions for setting up Dshell in PyCharm. --- README.md | 3 ++ doc/UsingDshellWithPyCharm.md | 88 ++++++++++++++++++++++++++++++++++ doc/image1.png | Bin 0 -> 82574 bytes doc/image10.png | Bin 0 -> 38111 bytes doc/image2.png | Bin 0 -> 59264 bytes doc/image3.png | Bin 0 -> 109282 bytes doc/image4.png | Bin 0 -> 32473 bytes doc/image5.png | Bin 0 -> 50002 bytes doc/image6.png | Bin 0 -> 63140 bytes doc/image7.png | Bin 0 -> 104139 bytes doc/image8.png | Bin 0 -> 44200 bytes doc/image9.png | Bin 0 -> 47337 bytes 12 files changed, 91 insertions(+) create mode 100644 doc/UsingDshellWithPyCharm.md create mode 100644 doc/image1.png create mode 100644 doc/image10.png create mode 100644 doc/image2.png create mode 100644 doc/image3.png create mode 100644 doc/image4.png create mode 100644 doc/image5.png create mode 100644 doc/image6.png create mode 100644 doc/image7.png create mode 100644 doc/image8.png create mode 100644 doc/image9.png diff --git a/README.md b/README.md index dd62447..9e41d0c 100644 --- a/README.md +++ b/README.md @@ -47,6 +47,9 @@ Key features: * `decode -d ` * Run the selected decoder on a pcap file +## Development +* [Using Dshell With PyCharm](doc/UsingDshellWithPyCharm.md) + ## Partners Below are repositories from partners Dshell has worked together with. diff --git a/doc/UsingDshellWithPyCharm.md b/doc/UsingDshellWithPyCharm.md new file mode 100644 index 0000000..2e82496 --- /dev/null +++ b/doc/UsingDshellWithPyCharm.md @@ -0,0 +1,88 @@ +# Using DShell with PyCharm + +This document will outline how Dshell decoders and the framework itself can be setup to allow development and +debugging within the Python IDE, PyCharm. If preferred, the concepts can likely be translated to other IDE’s and debugging environments. + +After first installing all prerequistes mentioned in the [README](../README.md) and then opening the source repository +in Pycharm, the following needs to be done in order for PyCharm to correctly recognize the Dshell source code and executables. + + +## Settings + +### Project Structure +In order to properly use PyCharm with Dshell, we need to tell it where to find the relevant Python files. +Under `File -> Settings -> Project: DShell -> Project Structure` set the folders `bin`, `decoders`, `lib`, and `lib/output` +as sources. Then click OK. After a few seconds, you should now see all the red underlines on imports disappear. + +![](image1.png) + +### Project Interpreter +We also need to tell the Python interpreter where to find the relevant files. This is useful if you want to import +Dshell modules within the interpreter. Under `File -> Settings -> Project: DShell -> Project Interpreter` click the +gear icon next to the dropdown with the project interpreter you are going to use, and then select `More…` + +![](image2.png) + +Then with your current Python interpreter highlighted, click the small folder tree icon (below the filter icon) to see a +window of `Interpreter Paths`. In this window click the `+` icon to the right and add the four folders added earlier +(`bin`, `decoders`, `lib`, and `lib/output`). + +![](image3.png) + +You should now be able to import decoders and other Dshell modules using the built in Python interpreter. + +![](image4.png) + + +## Run Configurations +Run configurations in PyCharm allow a user to specify how to run tasks and programs. In the context of Dshell, a +configuration can be setup to specify which decoder to run, how to setup the environment variables needed by Dshell, and what working directory to use. + +### Opening Configurations +The first step within PyCharm is to open up the interface to edit configurations. This can be done through the toolbar as +shown below or by using the menu to navigate to `Run -> Edit Configurations…` + +![](image5.png) + +### Adding a New Python Configuration for Dshell +Once the configurations interface is open, the next step is to add a new configuration. Since Dshell utilizes Python, a +Python configuration needs to be created. Select the `+` symbol near the top left and select `Python` in the drop down menu. + +![](image6.png) + +### Specifying the Configuration Details +Now that the configuration window is open, the following fields need to be populated: + +- Script: The full path to the `decode.py` script in Dshell. +- Script parameters: The parameters that would be passed in when running the decode command. +- Environment variables: The environment variables found in the `.dshellrc` file in Dshell’s root directory. This is detailed more below. +- Working directory: If all the settings use absolute paths, the working directory can be set to anything. Setting the working directory to a location where output files should be placed is a reasonable option. + +![](image7.png) + +### Specifying the Environment Variables +The environment variables in the configuration are important to mirror the Dshell shell. + +When first running Dshell, some of the first steps are to build the project using make and to run the "dshell" script. +The build step is relevant here because it produces the `.dshellrc` file that the "dshell" script depends on to configure the shell’s environment. + +For the PyCharm configuration, open up the `.dshellrc` file in Dshell’s directory and take a look at the environment +variables. Use these values to set the `Environment variables` field in the configuration. + +![](image8.png) + +### Save the Configuration +Now that the configuration has been setup, just give it a name and hit OK. + + +## Debugging + +### Select Your Configuration +Before debugging, make sure the configuration you want is selected. + +![](image9.png) + +### Start Debugging +Once the configuration is set, make sure to set any breakpoints. Then, start up the debugger. Further details on how to use the debugger can be found online. + +![](image10.png) diff --git a/doc/image1.png b/doc/image1.png new file mode 100644 index 0000000000000000000000000000000000000000..a2733042f07c92e673547aea243fd1b656b3b0ea GIT binary patch literal 82574 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

I23XrRc@c<6tj|8{1QI$NQ9rTUb8 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 V0v`GD2N*+>kyMZ<5&Qi0{{X8mH9-IX literal 0 HcmV?d00001 diff --git a/doc/image10.png b/doc/image10.png new file mode 100644 index 0000000000000000000000000000000000000000..0ff29dcae4a85ce4e4043a3f212673e1d8f978a3 GIT binary patch literal 38111 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�l8{p%M)SVr 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 literal 0 HcmV?d00001 diff --git a/doc/image3.png b/doc/image3.png new file mode 100644 index 0000000000000000000000000000000000000000..23a9f582cea1b6d4cda48c1d9088922b72c3fb5c GIT binary patch literal 109282 zcmZ^~WmH?;8ZAsqp+$lgDO$X^ySr0dOCh+sl;RewxVyW%YoJ(g4Ni-@6t^#Z-*e7) z?~ltE86zY+Yp-XmN9Hr<+F{B{(g0)vWH>lDfUJy!DjXbqH5}aQhIg-FpBQIkz&?O` z<*X_#23Ivsv=95|jk&0zC>&gEG|D3o0S@k^O;$ow{oB{0OoVUm2iFIazrQp#%gO7> zMSicP+;tpS?UbS&h~H4onH1B@z;&1L`}WT9^zjJ!0;IO3M8=vgm zhoDs`v=!RfzCr_DVNxrVom{HLXv>ogPU~qj{^$~{>;<_KMEqu2;NI2tX{C`uuiuO3 z;Tvm3a?!){b>?cwgo7yrMah>sY3IoC8*);%+e*5cib_&P8GZZqoQlvL4z&F^%S7vI z9nqC7aeUIfd9s$pkp|h(&ea}8V;X3 zJk*)H=KeY<0SR9B=j_AEJN)gt*oUO3=5L3XAWLosXCqoh-02RQkPg&ayZ1zQ_pUpQ ztX&8zx@)=q%q+x3!MGalL&k!%e(F8p+TEbOLtYfTWCz_Dc?h^vf3lcfhRBNxUM$`Z z(Cqm13oJN)&f5)LF!->MRnvVM!Te`2bA$D9TUsa!ueU4jPgA}t*PkrzwoWu}nm4zH z)!lB#ON9WR({- zPpK-88{LRybK?;l?ciqb_~>KWES>GTlqgG&#Olz8`Nrd&PP3hUmuM8JaF@%z>aFa; zAv{5W;-S%8nMOIMPP?0}g@uJj>-BEnS0iKN{c)=tDEwQr{=va&gKiR^=kr0*hBBWV z%r+B@V$Nr8?ziHG{L3DQ-+-mnagzStg3wqL9v=efz;%@P*80QX zHPapv>0!_BqS3qvXx?o?K;6YfU4XHCo8U;2-pSC&jwDxmM+e7#G}94Ub=1W;J#&;c zTozn5)Idov)abY9ew?$na{#F@83_7b4oA# z@bBq6Pw3FGQ*mC&2m0Im+B`f{a{Bvdaf;hIF|7qeJm&J{3v)A38&d&`*Z3gnyYX^xe>brvWMC zQ!s(lpD(+Y^q*#V$_p*q-*(Rzt)@JQcIya&8wj_vdYh~_<}A(%3mY3bEa8uC?-!o8 z9=E^$_#WxueKfxvH<)dlEncPUw}~C~aY+2#kcE|?%x$80QqPR9oKSo}Vv^zJ0>R1}o;}e*32@#71%b_o714|g^z@^b#5a6kfpepF z_jS+Tz9ysY&v!cQ$Gn7Yi}4zonyTjD)|#X`;|=R0y3yaCg?>I?cFFTBYi^#mW;+Z( z)TXzmB=a;%K5jr#*g^wmEg}@zV{NBe^-g>?y%XhRpzDeB!4o~*C;_pG2$s=a&=CnWVt$X7lJq5kJ(QPw# z|6pAf%oWY5wkaxJW)qFsZQXefKpjY$lbjuTE)BuG2&M?HgnRbCxu3-mlXUs`JnVW6 zvt%Siw&mIxF$d$dAg+H1i9fSVy~jmCH8$zn!lj zIyxHSkvt&K%-FTLf0AuN@*G1sT5sI6ARRN?No-*op!xa7zO(2p`F=bEMUabHq%|w+ z(96eFct4JxSe{cU&^N;DeUoCU<8(?EJ)4FPur)sH6@lUdA(+`c(25w&_+@hC} znUAY;-P^etiI=x6ch2olqRT(q0#gp9ZAmAP_Gty0-hs3G`pzH)TD>OrP>hqmWz9ZTJOP6Va5w>O>3mOT133K%{6)42(>Ta(@J@ivttK7lyPd@$%k(U>#w zR=y^pSz?0ONgh`Re|qRbESMCuT~8=i7np>8 zvT}{IqZ5+(LATtsM?9O))oLt_69ECCK}MwKU`h&f(xaB}-J-Y0?l^1b{%Wt@-ph#n zQichtj?ru_bu;nRGhq48QF@&08ni&b=LSNO-FeTW_jo(1Pkmn(qMgz*(fUx#Tx-5v z$~`7k^$xv7XCjcV`)4MAhjgOx$>gjl!Kg$np>CIdMvK&U&FAfn1TKwj z&9^v@uG6m<4MnF1S45Wu1NW3obP-){4daLrUByz7o7k^=JPFr?1C!fE%}?Bff5p3P z2*wz4k=RVH3d=Zq3ePFZSz|YN8mVVT80n~a&%5b+VOH!Pw2tp;O~j99&y9spca93I z8_Tot`XdbDxq2krIp}`8shYmAn&k^Js@c>c^%#ylBx+9d=sZk5UL5rPQ#kQ`j5lG# zElo9}VG41rw>s+2q`-P)-f%^J##Y1kf z>I_jIeOCy3Ozl&w?tqsD0v}=i=OUhe>-2d->A~}#qMHG@&*l8#7h0{f0eyuN6%i2_ zjS9c_pcimZLp|$07qe*yswy4yyJ}@7geNe;xHUfPQr6ILeY`#Q^Mh-v8jhXIk3?PF z?0x+?>K*uR>EKf5!NjRwKh^$o4qy7PHueVnI}+56GO`P zTYo;0eZLLY!(VO9`|)YN_s*p=>icJ&fRE^8G1Pay7r`6qi)C(Y}rS5k{QupO0GqX*>O-`O^BWhrM)vy34zV(5NMv-o? zUa0Em5YP=O>5Zr8OTm84MMOxLo{*4`mX?O;{>kHpKQ)B^r;S%+ zwZO0RTW)$Bd)JX+wIcs86i$GboZ!0{@+CXgO`2qtcO<1_vns1ZEW?|Y>s}ES$%j&_QvvcW?U7(8 zt7OAT`CP-A6<*#YqUhDk&o`4kbJ9Q*xVBfs*VotMV`GJqp#-p-p9QTLp9N98GxAGG z!9UTn9fRXQm~_+Q!oz>lqdnszfIId`_-oI#mfl$v0<3a$HYCKw8_D(9O)d=?+h>eYHfxxOBLl%5g#K2xd63`-4Hi5qpUS23H$^HoJKC9Qp5N4o^;RiXyKc}Uta*4>L4tQ}=r;8o6 zELwExY=kI)%XudCwB?l4G&gouN7dA`;QvjR1=W|#C{YY~oXNHVhch=Cyj$BhQpp<)CI^wv< zjjg{suFK&&pVvBLu7J-wDP>i?{$-oaGpu6Qq(s2?f<<1|9YIgcoQ#917GEHqF@v); zdPQ_T)&9+YH?;=AMjK6quE4D+3AS-WoK7qz{b!#)&oL z!rWX=EIwkD9`l%w2OhGSCM4>hYj7`G+1c5VtHl6~v9YmHJn-lff8ZE+RMXlhVi>3` znpiE3iJ2DbTbSn_P}et{3fmmjWHn7!&F}0KVX;@S;;N}(qv&W^#Qf=BS?N=M(mt~& zqFz{to#v{Z8ms?b&#C-03)*I@fA!>vX&dbKtgAcp7X4_9>7Uoh zsC{snQ)=lrvB%Av4*ANINP%1aZVfWOZABm|(Y$(DoqL^gjC(z6a;bV!5tegt?(d=r zCj|MdQvslt0X>SPd172M(6#8AoBP z`FhmScq{T>I~WCKL8hwlu@rlI%)>Fg-jxj7ou0ffkH@tm;5Euo7c10k$OjVQ{$29& zT&4=|HYH-{s;U(oE4#{&f(=xsyUfmP2hF(1$?kw{Au(PBV{r|cFg2)o^R8;fjQ6wi zb5nBRY)~^WQp_KaK543HwLA73cW2^pN%Vm7)QVi=3ST&rK9$q+rwN~}v8p@OZA0FT zN!5ke0xi2aB;}NEUL~CC$G-tSbKjRzfB9-lHEcL#N?bacfLvj{YjsQ`&d0kwVkDPZ zrgEIP*Za=&7;7^M(TJS$l+}!FO4(uN!#d#5o}N3|C5ir+vaCxD+9wOHfGD)3mfU+! zMC~i>k4D`hQ%k0#xWvn~m8iQd1>@4`>2slunyo5m1X6=9Dq4TrYM4=DT|Uo1z0JLr z#m$z+Am4A_8-bD4u*0q#wA^O;U(u;yyOjl{2Fj81A^(%dSnw4_(T%I(#7$JyVgcv` zv&$o@LOH&lZ+T$}qAR1EOP!i^sx|)=A?~roN4mtqFo~juL&1ykQ}fzsq|`fc-^6JJ zI@d=lAx6x8(}GM13$U3|xZPxwf@QV-r?-;xwqUH%)D^S$+-Hx0@k9v==Z6S20-hOx zsimp?0nI?FlG=VZhD@k{@e;TAy|(P}R_5Ka@qhMRSH1^iiqQ(OIos&!SU~%*vM?>i zYNAZ)mYOMEfzQ@L%G?MGzC?LN*At6HP%uA1sA_54h=QpTuS`j4zf(_8YK1#rbPekv zwc{g*bM{WHn^4eZR>l>?1C^mPyU3F83eih*)pFA)HTgJ;RVmiGRtvNcqs52gO5}0m z5-_g_?4O-gumJ0CA?va1KIeBkn%$T#lbSMO5+nR4zZPwWEY+woIl9!42;05kp*NWw zA`=h!L-C)4;7W8{iGxh%n+MzS#(ZaKc-F)vzALu|6*&c{?7Q$RlZ%rI)@xPlusgpG z72bTG2@I)%D_7f6hZ8iNu<3&fQ~Mps`I8s6J>87Nxz*IvtP>NX#GF5I`~Y#2h z^>Z1Ek>a$txlaS;LG5xl*K)M{(tYYioHl&3soQK2F_-uMO~Of}R^T1FQUxnMqy7y? z;}C3*xetr5_a9RsKi0dE_zxoczo&c;kkH@p+BT%!H!>867g&obNg8 zDwbST?OXRg{V$Y-I{>2z$YF)SMvu3#_Z_$+!1CZ$vC^0ePfk;5?^xYylB=;Bruq`U zarb9nUnogZoZYn?d+_v#y3zR8D@f{>D~RjKk5egLnWJs}0y@I5x`!0fA}qm7evg*? ziuBe#x$;RFLbGmrn%I;ZBEFpvQW~YqKUe*wM-)sMd!M*DW0z1V^><;r&`61o|rHm#=DL@#!m5L-noiC4(4Qh|!_%59p z`>8?!0$H@g__KpcjV!B0Soi^2rk>^=KcoQlKwi;|w`;m!dW{3H@_{^Ekr7eRtlHs-Z)8OEqA;~j%KH$oIIl>1 zY*m;LC-h(3p{vpZ68(LU7n43*SR~lC9EmSv@p!AU?#++p)8~Xv!`})~CwrSeSMs-@ zH%*p66csg|peR+Xf0v{vBGJ{63*y00K-vb_2oh^oEKt{U=E#gbL}gqI>m#IG@$~8mc~Rnf>dhCtoG9 zJ5t^l0#~;c0V8v8HerUKpxj{|CTP0zH9S^nm*B_4`tYM*{ zC1QVZo}$wHAT6WP;V;zb?;?bDn3%FGVX-6(aUGs97izmCei=NDd02nppoX$>XNWSw zd_Z^&L0M0l@|>8ifCczQm>h|^bRkd@RK`yJ0)7|B_2c8a0F075f*@U3?-k5j^4eO= z7R3^p16bb;rA+DfLyquDj+VJ%xk9wXhmFe$*J#LC@(xynAfhy(#k{d;dHoM6&3WzVo&y`)6+gJ;Dv-;|7j|(RqGwIg=mlmfsT98j7zWTo zG3Yv^L|jt>30Rd!>`VE9P3@2p9nhb z&K5G>$;-yIhjy_aeNz{;G?m@{V2njV@)h)V;5W)IoCF7bX|RQspzMd4NJL_%vDXAV z+o15zHSCGNV?O_Lp)@fRRD5;NX#GN_Sfm+2pmoz``PHx)6dasL4l^8`NZp?hVGgKRf>xeOULi%< zKN~!!jDjojgkmYXSF;%xKGR)wYr8+4U0>&1(n~h>=E^{^1i@Juv+8qj>9vz`8Nj=E5l%>(o|E=2bb`CYYUmFnIdM|>3<#zON zN^?&PU}E4eWi|v4zzi6If1CIVBwnZu2OHh0|9eJ@sF(r{swJz%qJzfOfNA&R_r038 zuG|H8ITz(fjfQA+efJvLl)dVnyd}fPIhu%#t4NPeArl6szHA@ z!$FzWjz>KlL78?ZN3~-97d0}gh$O1zD~rXN;^>#~MEc(Ud(u}WEa!$IpZ+_xoHnVi z@TA1x&(A4m-cC|VKC*>w0fB)im|2gr8&8B<3}0%P1d@~R#qCylHBgFtE|25#p?sRK zZb}zXJ^nCIt`?4NfJi-@myucwb>rQ6plBvQD?^Ce_TJ^&*U~P>9{J6)O)w#k;j6Cz z7kDEMbsx@LT!^UTVh%FOU|=I4rLB^HE->wj&nIYy>2mn`^ALU2q>{3-a&ITO@LkVB zw$PZs6SUcm_O77y1dZnSH-g_aN zC*P7+&|`9FLNN?k7&m#Y1utD?Yv4prXt!7~Hx=Oh!*jBE9+lHnu>`N2Oi2NQuht?a zrHw^8FbF?~5456nV8g>g=>;R%W;b~9^7FN*+X=L{P7+Q6u zoyZd_$IAmYe+5c4>2-eQ?anHth49= z(k#jGC~GHcB5h-^*XCkigQnk&vPJ#4=DzB(W1&*hsrL92@KI6+t#GuGQt^nz> zyu|@hsHfZ*mi1U674?mZdM5>r82d8I!iOh**m0=FW_jBI{ccI?c$jL0(i zt_`wFViNOi)>w?Jh*Mu9t%D}R$D7*9nbBR@AH6t^!rIeUj z%?}}@4x-CMC9Ld;N{NZ}u*@`u4I7TV0$<9n|8CEkY%D&KB0Jr~Qg}MrFoB z-i6~J^NB3L1TtsK%QL^%Ela4qsw$TLE*u$13?2P3EmKALWiBYZW(u1!6#4RZuNYF% zPWgVE*06Me|RSDQ~2-)p4aro))jg!DvT*p98EOA?5pXMPY64vpx!&DeRYa;- zev62GqTBlX81Vw*d;0VO)iD_LPugn!p{H#&1=Z)ywbI>L#m##<=UoZ&QN>dvt+Hf~ z5aWIGE`m?F%N#Q22K&D*BFyu4tdpqdsUY6JnJ@MAzkJzYc=m3$=h&A~a+4d%a_xTP zNM7Aw^SnD5QczVIQsQ+xt2V$J53sFrPPY3a4;kUmAp-YbOdk3 zU08o!Q4sTVm^@(|vBRWa&(9LJ%uQ?fa4O840#2$Ed^9!}5fFTLg6ZKSgrVo|03DV- zymrcLwmGh%aQxsBKOQpgj8$i}n$!k)iWjisbpt z%>x@3#;EV5 zpO;eUzi-`Xef2zUUT;y)4OAa}r>Qu|0gK=FAIUWWMiTsay>1iZg3SvaN zFKb6<*YuwS&!HU~F1?!q_wU_fdP3B^)PVNz#JD8M*Jad`VM@^~_K{G+Y*~2@iz)N; zLyYK>a#wH9UzScrA9mtDOj-&m&iM+xx&o4@B{z6n_#XUxseUN?z28PRxNqCKF9<~c zBJ7MV2{wO0)1M?rpj^ipA0I^Ohx;#$Q5zB9k%#B7M1dLQEP^H1pfE$D#v9U6uKZvkc`>g4j;nCoMV*B`JAC&cTHM zMS>fpgXQJI2Y--Q+M3!~8*dugNB#r)VMi9&p zMdYyQqy(0IaGEHs-~4qkQmR%Q5UG+o1BTX{dys)lb;BK$Uo^yVQUbrRd{hN`=l5+b zVZwIrED5_4o%NrlYGqJcuN1~N*VjWM(&90Vyw#{nP@LZd!ypW-kI)9Va%_E7F$Wh< z7_2qfrdL-pbMilB@ViI7JBKM&7MOjajM@O$%n$l90M_L!9|>@%7nIqxh9yr$93ePz z!3s?5@v@4ASZXjjS*~!l?+aNKtz5o)|KE;vXEQ3X5LqaPot-^cjDdg*k#L?C2Fa&D zdRVSpsI&~U*{sHh0s!@sKk#Blo12cme*)T~9F$QsDJ~5CNbz?xw0T${wmTi`@$wqMe&G49nW3BDNZGoex~!rT=x}q$IgpzwseM z=FN=wc<~+icg*c(Tige54Vy`RAb@yZH1W%Rakj`*$vPRpU$=%JlM8~58lj$oih6mo z@R56##SknPEKwM9b-G}ETl4BKKb?QG#36kosXhGYQgr zZA2*K{e1fLfX<-b_CDhW9f=XgY`~STGa3dOs}yDA<{Dh;dt8?t|~DJy0E) zmgjJi>?xR!9yI~|!wPzZ)~r~*`z&7K$jEyJO}~CfzuelKTzQfICv`5Y)Tg~trU)}{ z?*0*oER0z<wJo)?l47>-+C%(&~#2NJ{}E``5gmwa+Iham?Ml`8MS-13oCns6K%B;!?M0_=%Zp3R5 zcbRurZ?U74&FTo5JfVZ}%hr`6_v9*kG7N|lTe>ML(kCAe8OjVlIwf{W%saESpKbw@ z;!cojW$Wo|%s7pxms>6|oUNb4zSyhXFfbO={Pq2*4@O{1OG}gM8iy{4nQCTHVnD0b zUJWpA_D=-@3NDjg69Wgw`z(BAZY!@)pAr3_7?tG*=e>}(wd0{B|m z*_qO@8oTfM6)~9T=X%eJUU3vw3)3YA@8KVB!ck$hjccBm<*@OREirP-ezsWVryIPCunn{o=8ag&1HHi66k+9W38%gDGD z`1aZ?`JdO#cC(lwjG@|%>UcO{z=ZMjeL$@mF16OCxgy!$gZ_mU3*PSb*MeTZ)`5 zqVH2@eL4I7qStPi!A)~rlB)`x$J;rJ5h>H$dSOjvre;jy{LU4p$pvh)wwRy#yGk!^ z3I_DfvRc;qiBN2#qG>ywIU+&Fn6%RGs82vX_q-k6i7d7E!V6 zut{Ce-Y=}aO<)bs=Nqh%TypqJv=|?Z!8k3KqOyDPf(rIBNNVo zh64rJ?bKi4Gm_iI$fHWQ37XqDT3fhD+wT+1w(-ojaEo@|?==8ZXHB-=@!iX_nK&5G z%X^%DjXJ|l3Qm`b!vB=0T#9r2ABy}Z@Gs_IEcQY$zUr816@4mbQ=qoF@9X@WgcXqAh;7w93neA{k_Cmm zk!RdJlWWu??XtPEV)2!kH?$r5FssX>u@s`t?Xs}{xN~z2BpcHkfb-1w9 z2ZKKD6F%3P;6nAYmH_O$>g}SNe$_cowgvy-DmAn56xMauiv0Js_^_g$MsxNm6Q=UV z#feeNhcYn%ztz2|1qLV);)*5$TCHKghL#*@N39wVh#X!lS{V~<_Y(-rBZ+dW7qhOQ?Ig4;z!u3R=|W#n_zfO|vpN}AE)A)y7 z3p19481MFFN>XmJ?ev8 zxk5{@t8s(PV1b!ay2^^hA-WPWfUrn0b%^NCwKTbl@-_Z8T_i0j7jj~0-MUNDa{}f@ zbsjc(2zFlcHuX*ah=LLSeCli}>v1}ncSV8Q#rUJ;--4^41`9ga37q@CZX*Ce|2La8 z6HS8B-^aeWoU#VfOd#9ht81Hpc@YZxK{Iuiyo5<9QkedY`_P5(|`6f3YfamIiY%z*JKSE&<>91WRlwG$&eEe8&BB$n{?5MW-{`&sjn4TS*IDZIqyzRs;NovR8 zKJuv+;LbH!2l!KNDd-QM{AuI#P5M7-)hM(`O6Tw!FYvF6VEUt5)NB?MP#S^rP|#6q zQ%Fgq2<>YB#t$D=N;E4MLk5R}4G(>H%92Bo9iiq3RTSF%@4-ko^WYx@ye4}wJ|-Vt zk1C5L9Ph!FASlmrM1NbvXlYDtN-}ppc*9(^F!O`3S{`>Q?YZEg zn{)SmA!~$)k(rPoqTZOtG#ou`1GF+dRl$;qn^j9&o&hmVas5W47W;Ku>d1D{#t=3X zsg7y=CZ=|Mi=DGkYwoIpjB5o);md3SGKu1qjnDjGO`Fze06{flZisLoyylahY6N$Cbi zcdCVyzH_!%Wzr$)=i4?<#Xj&@(I16^6^NKci!iKW{RO`pY9Ywhee z+d8_d$8Awc<@F}u&O72OZO+K}2hMS@!VJg5OHN6V>5>`zOpLq4l5-m20tc%?uWVan zEi?W}q1q4hF0gb!`=Rx_O^P?RuI{Iw(WIpl*11GYx+(N6se@xR`Ca(-VC52Z-832X z)es-fz;=ZbOE-B_63GIZG_TTL&k(_)wG#ebxH}stTNSH)#+mK$T@wakl zGQqrl61216R{5R-1R!LOP| z(?PjtnsHTI8UG~7Ffy);m>7{NK87}0;yd!pA&?{(3~OrNHf&NCPH~~qF*E@yt0(;d z^jlboahAwo$9wS!{(mw)W1A<$8hNl8SklB*VdVS-KH-zbwPJ+xcanT-pu0`rK_AR$B$&~X*#K;GE*o%8A35Pp zw-`+g5aS~Y{;GeaQ>kV2iQ8YCE9^7tz8)2rU9$onR$^k`R?zK0k%cLP*PjxSip=II ziXbV203cHu=aPTsmLXl)ye_%cl7&Ku;eh&=w|`r5bdintgvFX`Q>q|?0t#4-V+6V(QmGL^6|pn+>!M)|0+mj52q_n3ixHdd;dYcMqrCFTJ%^b7gZx z);#l06~DEs2M`5qYj6VfA8-j?IJ4~WBW_Fovi36 zD~l}8p~F_h=m$Uzoy!8;7XiQ~R2m*aAWRyCzywrH__1cfo!?^<#m zx$$Izfrya0;kp(WyUN9(gu?cgIqJ0e(_K1FZNmV&xroW8#8e_R9E|`Soz>;en2WwJ zY+dBomumKmz=mL1ODOCd(0?V{nLJq4>;S}%%E2lFpEqvd_16?By)By*CeF7%8$f?o zrw7#9KKY>u_-q7=o_{EYhOIL$1-l-y2H++YY~3T#ZO>oTZ^lb@84Ftt8a2|LG<-V@ z#LTz3HQ5dui$CV?yhJ>Ub=os}NpKS6%D{ejFszSW_q@DXFtA7ISo0T>he=`Y0vcF) zK*q+#l3Wl2C+%!NL=e7h3c77A!qQpT&|Y2qT%Oo(Cm~=W@orzw?mB5DA8pmy$9{Z5 zrl>C_h$JiH4HGGwJEwiqArxr1IEM|JN5=Jvy+QuXYx`&8>9)($=170F*BD$-69C1& z$DeCuauQcB2jKbb+c!^78p`5;%`mRH_;6#jt~cmDT6R;I&z9?+TK6BWisEIvedpAs zT8%x&6V?w8IDA?S4odI2M3wL!Dj(-hi3!LrgjIaZHt)OEpxv^k^$+k3^0l=dz2nI^Z-ow}>(Vo|Dh!I6K1 z=Ox9QR(sr#^3A@{I!?ed!?kSbG!UHX`Mm~Nfa&9niAIbwo_3RNx{Adls2##XkR6+z zpvs+3^sjxvusqkCKVu1&2!)lp9KdBRW0L|QH4!gXOrqYWr7~eW=M||A^ti?0?VFqtQ}TCiG~? zsA-H{RE@8D?im~{{E*+=Ac?(s` zjbKk?im_G4U_%hsVmZnSBkv`P)1+w2|XW>1lr*K0bamNs zxhC+OM>Ca=r&HRk*iPzBA^IxOq}rrVZC=#f zCPvu@qStq5fw+N5N1Kt%s%V+X)`Jws>tZ`N)Adgn48+-UJgzC|ZNMMDFb z^2~u@YU$tSXG9UI@({=D!G6ifT1uj|C25~(`u2m{lu$2Co}i->evz8LH);;`61I`yby!P>PlC+9pn(5E#iipu5V6Eu5h$oXiE! z!(-o0wy;!PQ-x0Syxs7eGPR^X``XMGX3x}Y*0p34Lr*8XH)jWf=790l?v#=hwVpSb z%->&dll9zGn*qL)isbRKZC?NX&h>*}qBQDqjl(y5+eHzJi2J9xv9V*=iEtN3N7zGb ztFSB^1^~aV5F@j3a(6G*K;Y;GyhTLV#Yqf1u-I0Z{Gp_d#%Zx`?McQjt3_G5-TS*G zck#qi{`0|l!YO+IAC`M>knOL-14?prprq-`YYm;S~EhouiYZV>sy#>H4=6x-)9NCo_Ial?;PPm>q^v; zKWED6Qu^a$a@m+D0ti8ajfPrF{1u^0B_JuLgoKPTKk40vOEsAt+Uo$UZ7Qhaow;Z* z0+$!HTOlt$xy_5Y*f#VczIX<0VnZr){oC&dOCN+I4x}1b#|TT)a{u#66%`d&mHuX7 z%TxU8r?0Mri9V(VHmJ#B(qN%VUw*~?_G}ZI$Iw5ahgw%Qey0}rnYnuLwtr-1BlA~f zn-lH2GvsXrweDja0cy9BL!oCeRX*oS zTp`t{`#GAI*LpKO)Iq=dG_((ec)5jN;MBSOMjB42`$V^VfxOaC4%1IUfmZdOzFd%6uXbEd7Vq^We7)FYE4!-Zo#7yD>?ho&; z4qM3#HAB01KhmMvEY|pIP8Sp|oxvxxn}Smn>wv+Rti{20HIt`W)vxHi@2k&FYHxG; zc)w`x3Q1k*xr!<(W_acXFuM$AC#hVn?;nWPACz%&dZjx@Jo7!QH_o!rs~`+zOh1`h zGZ$#^wOQCsr%K(-P*uO&hg+6k9R6@ldj7h4xD^TL)NuZNsv{gW0$b~%xdN(12VGr) zB?mRJ|KuhnCZ>MxMn_lIPCYGc>sn09y(i@AZZRZW4~Gx*z2>83Wn>x13#-9s>M&}J zE%}Qwd3R7YM@C#M3LQ~)hUofRL|(U}lv!Rq{6uSuiEQ+nuP3}4?%lc8(P%o@llH;U zR+^zDy82(75RZ5Wzh0eIE-fvkEf@0ceo5+M#*5?&H!VgnET=Ax#!I)>q^N!BbaI|< z{6){Xp{=%SZRa|io$S1;G_dbqe}HU?G8(;JF?RDxxQgD!=wK;B4(@CJb`$wP66@X6(C~>c z38KK7PVgy{q#y&wjPoVsD!}+UqVM75gnI-1MX39`9t3%*&3vgSll_4S74K2Xj3V7& z$N5=P^-pT>@~FAz*P(8GJw3+ezWaiJ$WH@5J%&)cbsc{t1hkB_e`o?D_k#5xyNoy?_%7m|k_qq+(-QWp`XSqji16*kCdt zwbt;1zcHElN4EIQfyc&o#p5f}?z+JNHC*ii^3JxaQx7)=t;5YPmo&t!8574&zxx`+ z?Ibm~)CrGF)UqUQ=?hD)mG*YN0EuDFWk7)|^ur(jcQxIOKWxP@e%tc!@e$azw2J9* zj2mpKM{j)OvhmY21CvkL;8?0~Rlum``pL1A;y}vl2y{LM-mTmEkQuhm+Q+p$hhE={ zFF$0K#S7y-HqC|0XUXqmE}`s7P0TMz#6Qf1=@~XSn21U|i9?2JeJhc5lbkT19e&xqoeMo5*)s+6gzHs4}Ro96qB}FXL7r+)1)e&d#ha zwV9qTQ-n76axFX~cbm9gsp)&1?9`DqYuL)YE$qaujXo~^eNql{g_VZ5qZEFsC#7TP z!R96OH(#AZnfrn1%?yd(3N$KwH?l?ET-+R8Zj%z8)KU~i2d(X_C-|T(u z0K6{{poGs7LY`~;*)pQ{jxG&{J6@=5r@(o(vY$yuL;EKRoyAeLp3~ShHRm)EnhwKd zUD^rc_l(yyhHnRpg-S$QE)l#h=5%2FKJ0(t2|B~o*E8Sfk&tgM*QNx38)nZaWI}*d@uCmQ4I-7lS*N5xgxYnb6KQ*VhR77s=tAns(U#2qzmAYNseDqNY8QAsh zsGHdLrJWdVk4%rs4jl;Ff%>J|#!zf@NFScBng?nSV5KY+!kB)`RLs|FlNCS1Qn0xB z9Kl46jplJH#HtHw@a|#Q!qaa4h{&IL*hC zDZRXjctb0XCyP#YL}-PuuAzeQR$6sLqP`MylYUf`!NTz~s($$vV`^48TZ`pE)4U9V zRal^(Wa88^ZQ-Fj$=^=dFdlK=%6OxbO^Y<0Ym4viikPaEF_luao$oys3(MNtEn~N- zlTk&8yd@Yi+lw0zN_b3>+AA2wcn3{1HJg%u6SX0+a)53ivw0`Jd-^F&0(YR%2^wUE6dr6E2ayVmll^Xlsm1`Sw^AI z`3NQe^;|7F0_%fMzE8UFItPy?gN}>Ql|zk*{W>GzcM%-MgvY~krJ6RJR_c6!lM zps4xnaO0B#T~~!F!GZG*oz<}zG41yw{phjRJv zMwyVB^*uR@#SG2eN8DEj_Yn>41i7s2^uFm8mNS>wLz3qgg7(QYV^JnHk#YuGke71M~vV{*{&|MHno2H=~tD@Pv z?C~)M_)W>i#UnsXM#;uVlitpN3}n$WrYHY4mk4*#4xQWdOV{a5gz;4+dH(Wcx39(3 zx8=*jWIA8RN~`Vpeuw$X^-gQX#njbZ<0cbRQ4x=pfUVqL@Dw}rw#5K$BAi|^Pp1A~ zNYHfciu;!OaFlb0`Nf0P^Z?1K_mRu+QDf(Mg?iF+oLkNI$ki3yKCNibGw>yzo7mk+ z8uqm-k5z~3B3b!%nh_yy?ItH535j)iOdR(%+bklitdRY{%!!ho|Ts_-XTP7+JB(u$6JwpnjQ=tc1eC+Y`QqPO7RWg+^VD; zX)2#{1xDHIY&W+_oG@6wQ-aLDIFwdp^fEcQ$V;Nha#vBkg)#GWaxvP)M8Q8>o^wq) z@Ka*?pNb~p_Mig>*Z>TP!z>0`V;V0@lgKkCo=G%dD=^MOVbZKL{F@^VR4C{-JME2v zURu5G&JBF-wq^``^{R}2|4E?p-MQU}0rHl$>rzZm;0j5Mi2FRC2rnzE-hHfI2=4Xq z8OfqV;PZ~(VHjb1-qM5BM$Vj1SKdZK zedA*aGX5YM#9jD-8+YHQ{4Y6H&dEA|=98$3JRPw=C?{DnPKK#opRW1}i56fcZFT=i ztc;df?(rK8nwiBZPrvgVG?(Xnr}XU6oVD%JpQwuue;m$6$A? z6P^8z%hg^9T>a)B3v;b+vZIkNj-+A)ML-R$(0sY zTut-}?Bj9+cIVmwwelu6hJ&{YhevcX0bUVDQ_TpmOtc`Vg3I%}itRDXscOX0YF|6i zBfgjIv`hvm#PF57-{bN(mx0^kCMkZ<3^l zj3J*kI0_{`TMLVQwxalFjHzG<7JotNH`+zB?ygG}D`-Kr&6ahY7N!MJcR+m)W&%X= zW=&^aUzv)A?9FuH5XTWe?+k^7{hs5y0hpD?z?F{UqQk}5rEI;Ho8fx}t@_Q>W2%#C zYtq!1`wh!A_YrlvM?Fuchg;%u^$@1gUixc>PtX=+Qkp#NfKT|l#L5od5`i!PbiA!`zk6y3SmNtly1G+HCKjvaN7W*)3b{KYen}|f~20A z&6k!2UY}mMEX$b@o9VFbea8V`-by-B?+rbNs(sny1$1>+5YbVR#yTjH&A{?}siFVv zVCu4pNxJJV*D+1`4(>5nm}`62bhM@SV2R~7nN3eqQk zEO`Jam~lA95ZBi?5_Ke36fmr!^^X^l&tt){`S!TB;M4r0eQ>-LwxDMbxk&_cNxxnJ zF+)YEVCK=?l11h98h1rpgjo?`>6}3OBiW{^ne-S}X6N|>1T{fjG2Pp)(N$c0pbB4a z?sKLb;s8hwn|&})C)uGk5^Fl%Vz5Ns+`_y^{21>H!^X`wPa$YNcy5VKA(OwV*%i)( z^sXDsCNfvXMUF-V7z-F-3UP58Z1#Bxl2s@gmL)_=rSX7sv0M-CAt<|PA0Kijn7h|m z2FrOcKB|`fM{B1)1poIhXNFx;6D=9z&9D~Fq`?GiZJ z4sAtIFR;+Rk65)vX}WwGC_qSUZ_;qI{7n-_PjlGEh;h`Dn~VM7u9K!FU2iJ6gQaoT zYb)9D%fdrdjb{hA)+L|j@nP-LN!kQ1yK{ZFkbC686o$PTPA=jRHz+-y5ZI?d-P15tPgJCG! zi|*w9I=1|$WcLIdt}ye1ow9wblKjU;!CWnmpbzjlXvGatLH89nlfHFXakpcBoRRE7 z+YM`gj#q@Dz@zU)>$)?OKAYf@8MT~bpzmEp?;iE8Wq$d(;74TqVGzOR2-c1B;=NmI z;Pt{KSd{OW&@R)*F_3Wh9bx&zoI{LK>18|H5cSRFo!81Y(n>l*h=s9w;cR-IjDl)f zMPaBxr;oRSC4?B3l)i{tFa4Y4TRyH_y_w`b`EaipdodDO;DF)Iy}c|SbJCo3CAan! z<1}@3laM&0sh&cA$+#dqCAyenYT~jKX6tNl=du1KxqU}Qmb42CrD0s);#Gb0Ax5Ra zQdoe!IkSNgSK{`TQf=nR%wEs80`S&j>`C{709v4;6qtO*t^L2rn*%vwyn$oEMs?&q z$ZEZ5gaQ!@*A31(>zO&q%1Ab)s4hKkU;`cX zeakn|sMmrvWJ65Ez`cb%&ny#ywmZIXU1B1X!r}dYCsmYXHF`GGmesA)bj))1mBsym z+yV2PZqNMbQRist0Y87@x=O`NpZ z9J^}Xu;yF*HYrNg$t@a+#BSkBXWVK$ti+aG#(Cx~8H9fVbV|+uJk=FRMi;$9%6cw& zr}jJKO|4NL4SNAfd~z3%`0QCk@4aLA)uB6ex`U*mRnwVu#RLe@_4XduZaQiS+BloU z1XvmOxq?0);x?j55!(mnvVJI&aK1Ojtxz^ku8jX-nHdm@>7yIMBbi z$G^BRE&M5#2c3E2w)MOOs9wkraJlGpS2l>yDL~~FSjs<0=_ahr!bh)lXSe`_{H`wC zy?lv@Kp%auGWWi@LN?T%XBouE&vtHl)^UTN<0dqPuk%}Vh)JJBs( zXB|8G?myl0SNG&|93!%ng9HH03e@_zfTzsE<&^p>hOF=%1R@G z$9t>oT)uueXLCYxc(b!iSpV^Xp2h+|tkeo;b3Pt3S2&#I!-~rUkum%UMk5}bCHm3G z!R+p7zaKqTn{Kq%(#>{FG&=7|?s-!+)VMfKN6jTvp1~uvAJL>$H+nrFImC(cl4};V z(`rL%)~@?|Z>KC`fUpnT{>;sHeW$9!mNeUueVSSPu^g!TdV2h*ySFp)&4%oQP5gy? ze)?qX(}d#QUkyIAXUa$RpU@(dPX&*w4dG}Df)l~E;dcgbg9C8q6%KWux;bBHK#y(v zkouR6eZl*4YI(M6bG`O=2_yH{?!oRR#a4=?v~5A$7zsBNU1`Z>RfQPbc;!wL4aaxk=yv>!AoRp-voRa`#OnVM18 z8o{{FW^b2}T6MiG{Ey#a_rekU^V=Ad2xM?fe*hV;0C>14XDNW!<@U!@vu=xvoi<|> z9nOHID1^^Cdp=kIxXTif#NNjJR8PkUUbK&11SC>ne>pAe!1Rww>c5LBSFJF!x?i2` z3#OJ+ikOI%xtD{4tcaDW7pr#?9#EjNiPM*#8@3>#+z^r<>xX^#de)4}OjFH{R79&?qPy7o`gWpqUsAX5?mKqG0d zddbq!=Gk2`d#}OPNke+X>KJ0DSovbK^0Vf}{^3jQz?6}GeOmRlU&TvT9Y`wEh$Q|o z(Oa$!!RFTAgjRt+xxK{aeqYTK)st1)>m_R7Lld*v?%21)OW&B%_Rzs+!IF zvQ)JPTM`RF%^wmj{H}Q~HA8S0DkXCpR(u`?PMAN^^qjY-W<*j)scrdpaX?5Y^*AqzfD3>0fl|5w+HC*KEpWhu&{+_cCAWa+R zb95)oS2=y1?%7BrUyklp#;hHu?Mp&HxJ(4D6$mUoJw8P~Y2>e%)eUvE(Kl5e_@%O( zL^~tQm{>-3#nGhHEPgg?vb`|K6EkH8!G-j-4z=843sx+`eL|IYm9&42GQhgE`)fJTVyhf`lZO}7sH0J&_ zirh*?cgLeEWdzxzo|qGfE38-#p70Ly;<&V@W57zlR)6qiLnb)(u<&+gJL*qcy#i|{ z(`d8Dh1Ez!CL0qf5-+tNqtFXPFFa#XewLH}I=CF!r1_U@4aBc7p382zQ4vgpy?&Pz zA*!<-%e2$0pSKlwK)Gw+RyFyNN(T?&(eFB)6j{02`c@jaW*$|DS2$0`+gD!G9_k3;6}@ zvrs4{+as1<8>MFtRZ43i7ZrVl1;=VGy?hcJ!~DpE@99OC z1du|e6p1CsaQ+2$60g{gpf6xVt{y*e5099C7b`OeE~A0;P+91}Cmx-3N2;Be{l_T_ z2MxW#%MLfzTVu1%-^E!n)G-FU#NVE*IEoDV5+XA}W*K|Vx2ow;dh+_G2#{7AkmsNg z$ah6=LeRVrV_$AgH)_T11LDQc4PkqgSmL+ywhqoD2b|V1Cx73J9xZY$ z>+jZ;fH`c|j$y@A6jFy|)Z;ZyZqE1`uiIuMZT1ezkNczw9p>0*!2z3dXnX zJ8hHxh~Mi-uYk`_t!qrHKK;1en#_m)ewJ+1ji9VFLcpq+Q2ReSxpY#pK@9TC%d8@6%ThL78CzIL3G zKN1qNA$E~7!rAmkmQT8&VUAJY{&RuwAf&i_JgT$q{AnrE2wcBH#3w1kxO0fNas=?4 z>}~ZAA4SKKWjsiuw?1oiDm-;~1+{h0PaGwzJSJ$CEg1<_&eS2U;MZri-otqQ7|OkGHHtIo2&HY(33>pgbLBF1d82|{)Z!@iS;kG0WxIo z>13f*HDllarj3~CFIaNrsqLu$wX-{5=bJPWJ3bB7-Xi-V&7c~jan=iEHi!6$YOD#? z4V7_|_;F)Q<&P%u@;wxtdGTPNuG2tFP6gRl+6I2#z7$)(FSHRh$H*8UKI=- zqzUsH>=FRar%%}V7__Ad{^HStl6eKal6jR;|Bqud0RwI@pmH??uDOAQ%uU4v$sc1= zl2hZlP>>7Edns$UOrxU}!a}9_Nr=(xG63 z(DXCZi}gxBw%4&**y_t_z2W3%&PpjSY0^%2=I5s!_gw;`Ww?3gX>4I@zmC~8>wLk! z5Xt(rz?Q@KJ60|_(%-#`=j-#_=+DsK5o?R7URA7N69|f$Q96lD-a|M=-Cy9Q^8ZLl z+#w08)oK39@NUehkH!u=JjLB}cR*%-R`;9RdFR0G|pWK zGr5{=VyLXfd*DPky{G$W7z?+vnIzO1z=O@0Lz|YXzBZ)$wb$N71d$joI$XiLKw9iK zX+&gDgJK&D42i1OaVn}nAL}@SqOP?O5u^)k%b+42!2j)keg(khH zt8s^|#(>QWx`XhWQfSkFOqU^4Wa=7d2+Luoy|St7`dMM)X+Pd=YPJ4q`Zd?9@Z*}L zyy&I)arzyHF~?*mPa%diFAE||3`?&GzeIgvLPA1nDiUcAB_*YqnHlgmYK07b?|Ua_ z=PO`-KzXeF+4}FnB&K)`fGaVeGM7b-ku{o0b(w4};O5~GhwIX|_+U}vLx{6i!7Qg? zl#XeWcOGt2m;HLNU28|C{+F<`Ex;X-U|0vYgDnEUA7E(H`ikv6Pz#y)nA3ie436NL zGnL|C#M{%eGSZXhcfxlDuMNKs=@Qx)9F~F$ET+?+ka!1 z4E;oi@YmQj6bma93tAPOeG5T|49CI1hMR)}JCK{28cs0c4#QYKbYN0{y$8Sw;C^9w zaYD*8JAV&-$)hf+s|DkJt%HFEWV$N_4Y=7SzMy5cLvh;3LTs3_N0mW` z?B;iHe0==G_;|k;!Ywx=E$ui>&(zeEMaf_s^mPj<6K{!&@$*b6PlImQRBYtckCU8f`U#F+Re>ecPc*!AW~m#5 z6+rz$!HU}sp1;6AU50dvx(5{q^gDV2g}q41N!6yirf_rPQl{nQiqUn;h%WF;TU%RSU%vdkaC&2p-R9uXLOg_SO7ypBE!fw6*Yg_T5<3gQU7(g+`xgq< znE(lfnznQBjiHnPEfCTwu*%y6wc4`o!COOG5pfgKhc45lY}_2R&Gdy6ckI}xhcq{0 zl~Yn{=U`3oY-Z_J{0_r=CWXXC<{MA*>5z$^)I#=|xY)qR&@}@?0ePm|)kaMDRHug5 zBaVka_`1b&z3oV?i5-m+6AFcmiWuYPs?m0Pd)ujl1ngH$G3XsEuoB*cX|OTJ$$jw?_1Cf{+1})$V~1 z)_Jj|c&#Ae_Rc`vWSzW)KhGw-ZM`lS}H5(6H)R!jSKw}+K>Cidg3Fd0j9oh5ay7lJtAEfQ1|tr zs}wH&05L)hOo;t@K1Rxg8}3L|CdI+?VGt9M;N!WxUDmr=KRS|I)&S}>q+|l{V&p?% z&(KN96{*KB4E9a)Q1ZURv+#vXa+Brb(EGiryev9sfKQuze46&LzI#SmOutr#3UG?_Q}y~ zHSHZw2H%)jP(F&=G%kf?df(4k7-;i&n!dN#G9v;{CeXpInNcghIk_<)&CmkJwpM_w z`#W`rmxIUGTH=0Z%wPV;dA1-Z&@~^s(x9jdfFA>2=6>YW(n}dznTr&62Fx{e7ybP< zpp@197ojg#3ma7cgV=$d_S0q0-ybHYJLYYjnRJ%}|JKTz9=l87){v0>7=mKZ{R?3_ zJPSx_aSX%Qs>`bI(Mp)O=E~l{#%-dq0o=!jn$~8%P_M>Dylgn{#lOVFF}xFkI%JX= zrPI_0xmdmCutuZ8Nk~lG@<8?sb9Ww-09_kHvSaaoJ*IQYe@olWIkys+`J^!jfh`lX@{j92|MRc`Jivi&3j+I3@7@YCrEOFKBam*y3$R5U#WlLpg%)i=EhW}lnWVZQ86+Al4jUrwhe(QmD#P^_IR4M|U-RvcaeK^>g+R_6 z+0_tXVo7U1#k}7+!p4elX{=C-xP+YEt;5u8{3eZem^6Je+MwZ9zTaHtt{pEX&lNY@ zjjfN5K&U|O@Ui(2B5Gi~oZ?pNmnx_Y27*4mH-5+uC0O zIkZDS@t>=eQIS_8T~;$9FK45Ag8NASZ1$O%xS$%_Hl@KP}HpkSu{EMDt6JcM@vGG)3k zRD%M#6<~r%(BKho(2(Ug-nuF8roI+9H8r4z72)o4rzlRWWn~V${f&{rQt`X{+q&n6 zo=J8cXkb+uWMh%;-*&X~ZD8{2nvSv!)sW74*STr9Nst`$1SP|T_@O9p$Cb2$*c2Jx zyiaa0^=oehmSQZ`rP<``QdIv>QW-mNgP=twgB@~YXZ}=>)$;=}lV3+2N7Cl@LYjL~@WZ5;G`qf_ICG zXUA9I{5LIwiiBt)w$A7RJ68Hz%R@U##L_n@Q;M5 zk(S+xdrPJgSOnMSfUC06&gn`|o~SGKR`u3$w<@=*?=dF$o&-gn#XkTJEzT9=HGJ#H z!pViB(# zLwfS^^YaUSlPw<`a4vgW}p_+@HgKY+7~4h2&8* zsUarm>)T@!mnk1nFC!1kM#o|;!I?tlVJYuJP);>uxImx2}ffoaVn3$N5kdTx#6AT8YrKJHN|HQ<^*w{_J zC(+=$$AZ(Lv|7l&3P!2<)^!OighC~hYQ^s)B53<8JAJ+(`Bo7#* z1Xrx=T-?xMaBf9jFC^n{2yvvDNly*Y6h?Pv-I(>-3{tU*PY3qLm8~EttyAv)23Eqo z$t7b;UV#P>&1^3qYdYo|B|&4!I9u9i3T5Yj$2ES2>J--)pI z^|m*>cQ@%I9i-Czp)vFFwr>$Dg-MtIGeFx+D@Xq7@U8hco{;GoVJ?FpuOHfsF zKOj63XVQ$jkP2Q`>r3L7m?3@nE3w?>IQua7m^Cbq@5rMLF`BTI++r;4eQU!%Sb_8{oX)XCx=} zEel1&n=Hq;hkm*k)5xH@be{IG%t7&OU#c2>7NpQydPw#_4eoqv0FP~{CYNFb$?5>= z=YoD6&TL1jtrfEwLXhfg@X~G|-w0-g}$3P;UR~IXWJk zw}0?iz=|KQHW6)jT%8O`CxH61@MX0+m!@>Pmvmv1Rq9%aul{nW9ChXS8#ir&+El1* z+lt3g-OTcF4Nvd?cqbNi5(V;pkXA|UbNrv*QaEF!1} z1z-6SsysT(z}5%-bo0bI@(4+4iYQ`v@oc*Qm#wk%)kp80?_=o#-MLoOA`J+C zre$ORNyV7AgIS{nUV#igYZFQ>>otxJJpEC%q4*c*;@jCwOme%{C0ApuY?RGJ`*7KG zuq=Oq#bJj+@R&&?;No-(5PZIW{|@vmT3cHK8ks}@jI{7@|IsbYt5O7? zbulX|D*{Pgi{8z*MOs9g(@>W_+E%YVg_}%uxi$5A7(CllUT=PR z7ImX%BLX!?=d`6qU1I+3&^XN%{jMmxH26VNBfw=ke@8PfI#9CLDzHwU)37b=R-%dr z2LWNNn}C_Ai)`_|(eXUSv!tk342=5&oX1_2Xm=^1=WQeLwSR+p+u>qUd~4Fb5B{zW zkD+h`K8rE;j&#d!EGEcYwpMeq=k!i4P?O#4t<7vFJWG|4-~K5yyNH*8&Fsnw=);E( zpFVv87*K(D*Zyc`+33_16n^N`l$2-kvbA8{57@PuroH@^YQKWp!R*-;1+Sa;X&+zd zYfcs*-n1fKaOzediXwh4`EdV=HeHiq1}@>x=j(KFdfpxcBv7oh@_3;|XKU}(4GQP2 zg1H$Z!X+i^Mqc!154aj^NvaeGS2+e0Z|k;xHb-M)6JMBdYry@#W<=&|%w4 z){fu}`c?hx>8kFwtwAjYo*%QAvh94HEW8Mm|XWAgl_GgtL}mW-(m$ z4w^23e7$lj?pF+2v#rA*^QQ}+clr_?>~}K#t|v)O5pPpU@ly|o83q~rnVA^bd`H~v zo``42qq3qUpYYKWq> zoA~w?7+fV4F~D6V6)LVm)ql!tIP?=?znkbE=6Twmz*45$jZo0}elq-4Ew`Px?V(>^ zJ1;1gcBS1Lfd91sJsjISZ(gOQ&&)SKnNQ%UOAK*eq~KY)N-8jF>v z|Kqr2HXYIvn9C#^Cjjdrpr;kx+P5e=QwVwYy|FRG&xkDlyyP9nSYjX`$Iw1ncaZ{} z)E=idLX18JA0dn}^Z>%tkF>?R)C83u@ftrhG_@6V^;NaCl=aor-HX>ZlmDnp zQIDqasd+y;T?MgOFsWy@sCqx2&ms9{wz$1>cpg{l4;q~Lfcw&p+T^qaJFr#q0)KH+ zmpb3%@T6XXWLv=-=s_6_D5+}jRCc$_m$-E&n;LK>3{BW3NX!ioq_gRdDH*j@v zsBBmutAK_RxM?DWMO$uL@tzTENcTjwS*f!-7!i1us5F8En_oIiht25Nc+Y8Ie7PEcx!K_CFF9AF+2P5N?V!_LPs z_qw@ZXAtc?PF00{bOFFG!a3C3goYq0F?zBOg9TU;RQl!)ojE3(;`2tXp|>OG33D5YrM&U=g=-36pM8SQ8^%+552;RA3s#pqhC0NiYI~5 z5vuG1Z|ea3tL- z)eE=LWaxKD@MSMR7(s?L`H(A#nkHzw4ipBAPfT=$U7VjIA|et1$oE&uZ4|DtpLQjV zs<_UZ;3&xu#0n);e&)x`z4+Q-Km~WDIpwt><{a{@gu>pI3?hS7)$}Z9F0@y)yzL1y zh{Bt<7%GI?=tCs}xuE|eVBiJdbDNv`j;#;Gw}*vA{}~zC4$|Bq0=7M5PMb&IDAQ|9 zSg;pW!xJKGm-&usgj8p=93akV6N!kckp_##sUP$)XMAC0$ccewi<5_0)`7E+<2tXy4P4Ro*~1m=QI!l@rxgjAA^Nbgr{iPY(LRywS+ z@BteZs5VvB4nes9K7XYkHYdLZ09G~i7jyDDZ@xNMRaj8^c#lTBNcivnkPTq<*z_X{ z@UUI3B@+=+T{zDdJCkM=gFIa0QA|m48zzSbwk6L9! zhNJIN)|4-+h;0kC%a-BYp#V!5tO_HWcKDFXLW>OW1b@}a6Hcod`9uefAYjhjQHlit z=q(kti`%B|R>TnT9^~B}c1xjAVQ7!t!A>7})N6H|ZHJ&m05lqqnYisB2{#D!)Er?I zKE6x*ZyaC5@mULTy}-RaJ$~o~d3mO$rk1`%$D0H31qzwLqi*Qy7dxW|sjR{_nmWMu zYbZwO;f?AW9JHRTGx&R7n$b z$Cn1QRWs2J3xCM;Mv}A}J|BX79?X{JS5~R%WAHhU3D_$?Zhy_!xFNZAaY+GMI6e7BsnwrYW%79#`r6nB*;3-pZjR7RvPlQ*J zt{WJjn7%T8*-?S@fU7G;t2aAV%0~3II4&=D{d6eSA&7d4TQ)MgpoLt?qF`{jG?f6-)w&)|_+{{y{sH#$IF2`0 z=ky}f{_gzWk!g>;xS$e^GR>y-9Rpu25r7a@?KJR~Plqm@k5j<=!R6%d#8-P#Po=xI zQSXy5bvTdt8@w^!$p*F^ZiRyig7Jmmir3a?U@BNa*)?cET3TA5B$3P_C39s01h+S!FXd#BecXqACID)Spls;WI12Ija{)DLO5YqjPz8^18FmPmx|GLyXr!xp^X^WljS@De6 zq&5l#-FL-KI=P@;;BSf7$=e2fd6#|?g#V$@at z@F#}Id45@zNomT`*Cs6Bd>BDlNOw2TSFdX{3EexlytFhD8SMfq6a}Exk>Q}A0qo^q zVZyJL+RZ4|k%$Kbc(B;Peu(kkjdHrXzppj(V1_}lH7jBJJUL(Qln{}kXe|{ad3Oj# z=Unb>W&KF`#e>$uZLumoszHyKX}(;yOtz!b8M%UHC7uVlscqvNdtdlM}& zO~p4N9WdO`>~l)7%f1W`k!CV7t`x|060%x!-qx?}P6vozjn$Gi7dU!;COB{ks@}|1QzKcHeGtFPrIT+_) zXZGir!X#EHcNO%UZr36Ukg& zVko7jq&j?419Z0YGiyi>TdJ62?qy{xsnG@n5{4g75BJEDf2&p7E#a?C zDjP{m{Y5>-{nIhktMTsbrbyE`$J}=xX%LY_54lmzWg@(a*l)>3~ zb90yJT4--iKJ7W4Ka{$nR8*KnPEu&r<4~`g|0LlpGYT>?G71Vd3L26H+C{_Wss&p7 zfs7vtv;-=e3a$j;X^Vy z_}b49$C@kFBZ+#kl=($_$$y1AU`W@(DzdnLUUvbc5F-n zC3i!v$y}~fFpD=c1~^F2l%`md-%}m|bY!iOBwf+C!|A%fGK+K=W!ih3o`=IUzRHka zd6GBnR_|1)ZCn(RZG=WiJ_kW&2J1-`Ac~04OP~Rx9n5iZxoOC~vkJu4Z zttquclYrKmd?6Gi4O;j`RA*x}ik!y2UJHv$%Hhk%Y!*&I48>{!R$J51zjK=1Cy}29 z4!cjRMPIfW!sB!KE_j~W?ncf8074$E#K)*MF*U`I1%+pPWFdNQM0 z8ftFwsNSf^E*IGE{S3rNvU!O5b#s_lDiJItqMBwyi)VE~$*Q_qR5L3MDxNv2*C+Cs zNhC|2@FPNYMMXo+FE_ptl_hEHG6}41@J+wcMPtY=q#i(5KR(y-j@5YDt^IXob4I%HSh83x@%npS6BK|WaH(<(*4J>qYAu1U$Ny)yxzWCH{ z@OCpp3W=*BAp@>^ft;m|)j*UOJX^^*seFPBbmSsumQQFu9yo)&0X2q#ZUHj7D6jk>S4+Qg-hy!SSuKJu~` zF}TGai@~YJzcQQF4AV6StZTcEHc{}zY`ZT8-^ir33Q4ke_Ib7NFI_{(wg{p6r}sDk zGZ}_$V>dd4$z#D=0f*R?6-{zX02ysBtB6_JTCyEyZ9EV66(;90q*r2_`+!>q z^w{w1z&88`r(WQ)fj*X_jCv{E<`!~tJQ)CjP6-3CPpOyNr!|hSiRSVjHu$i9N0~t7 z=DqssyFc`E`{Q%?$Cf_gg$5gK-;0dt4`a@wZ(r9tGH_nEwYCZo-wt5roQ$6}R zoUZ%={si_|V3`A8vUKiJ9OLC+gjd}C)a#l*{cK%}Qla1G5ha}Uwyan>-bRyM?yV|# z);?pk+sY8Y?ddZZP-8Gblc{u1OAUYvv(*w%g?EfqJQy zc#X#Z7c@O~cRuW_6fuz}l8nck=D=aTV{X}635P8nEum#o$FJ%z0SuD%coWxH6x_Vv z5MtdL`_i^wvPM@=8D5`;E>@Z?=OgDjGC%nt0tXE-I&u2$JM%$t8Oa|SR^V-?Ej$yz4~W&wB@IF(L`i+^$7 z22Z{l=->-*TM9UcG&E+O9&VBn5`=+XXs$GJRcnCKQ^p1VTIT-6@0EZ&{^JW~_aJio z7tA!22YB0CDMhe>P-W7}-++wv=#QTx1L!z^m>{r9BHL7%N`1E3GFDFdno?$r}U z@n{OQubgNqHSRgy0Z+zI!z;$WuKK=?Dp>Jfsg&vZmes3CT%rk3tr+TDSNnoZ>SI)a zW}nw!=g_Me{s!qp%rJ8^x|R%B?L@9J>TZaulRahz6oTgfoJ#W0(113h#@vlQK@W+~ zsVp4Oj38X;fi0WB8e*9c-_v0b#f1O#FzzfhM zNCXIQaBzScPM|$4DJfH{QqAcf%z0cAPKRokS?27z*;A&D$7%q6d9=`Q@|C-C21p-4 zq{f+N84n&PntmQ32Z`(KZ1MHuNO9b+CbNATeQ2IGw_dOj|k;EF2WX zDNBVC|1kO;MIoEBb&2Z`X0~!PRtPQgBb&R^Rk23lpNr_6z!0_*I4zD%8To`#jdZpQFaQ5*{6XPmxEiF zUC|yNXDW@Nq~9SnDeeuKRv*_y+vDndk{y*(V2sw`kfn+JL+mq)4Z#+PLz+Dar)-MR zxT;k~NZq$)sH!_DV*H-BWu70`rpy&n9WNu6KumOK>L8iUa8sYiQ3ZU2h6dO7^OXUA zdZgQ=zx*HC-a9I)ZCMvbQ9z-IO0bC{q5_he3@Qjp6v;W~oN1aU(13s>$vK0Pb4F>& zIfn+CoO8~+g?pcK_SxsYcklZJ|IjfQveue4t7_I)Rr9NJxrq=Fmm zk#s(Ce(e_AKL&t*12PF@2Pw+&h&Uh6^VNSkrX%yWGC50^^z<`+k9XY;?N%iL>n>oyn zAbCSYI@Q2v)U1&T>HFFDz^);7gLZ>#-q)mhIwOc_#c$SUj;BX`KKeblgKX)z`DA9} zh$eN!>-;YB4cHDOfr6wN5>7&JGP>aY!o-OWQ`TT5Cci$tCkmz}&bSdbL^L~#9Op4k z^0NHmpk`qp?iUtV;X^NL!`%J(^N|`~dF@b7i{g-1Ke6E(FmV#ESwQTf|Dt>U?!uX6 zbNek!53*4SlcwWaHyIZ=I#t%z))sFzF1V^^Vs$Y4=YUA%?95w`Gn%>cM45@aIT*VP zZ4f zu~n#`(L0(H66f`ZEGyU}$8uri!Y^(QG#I-V)9R^<(#4;HA@+S^thCg6qImQ)-w|-! zI~pU^=?%b$(Aqc347I#tDq~|j@5ebK1QoN692E`kV=ITflT0ulk0XX0eat0;Vc$E7 zBFd`YeDJ~8%#1zg!XQc}s;p11{y0p{J-o9h?7uSLg@P8{eUaCuvEx4z^<9PfCXnc(lV+5v#S zrzR)chGtVzsAq?C`lVLO3QMyF;SM#Av@^cnlJC27qjo8v%KNIZzv*#F1$3PxvtvK!>0RjLcaHjP!j&!|qUVvJpD(*Df#- zeETF8qSavDyBFuPUt& zetfJ)qyiSaX?eN@*#P4&tb(ok21(4vCd5t5^em}&a4T7&86Ft2<>t!k-WGajd++O* za-i8wR%%-*&z#&BGKp*wk^ilOq={a5gKpbV*{qEYQZ!gGZa-`>zn97f+`~XAs3rp8H8)m{pf*teMv5w#ME=2r{nL%hUh~6aUcuNg z>y_PSMLHf^H@m&%SASeXQBtPe*bN8l3!qEs2UZ7^PIjUrvF_dT>V@sS^8CPe8X zE(EykCyJz%21hs(3tEH?@-rt`Sd6k!GXku_N1xGsivko0fsv<5Ci%cC)k8o=BjYR{ zuYnmez;<|owt1}kn$$5o`u~`|WMV&qcmS}r=K;sXN(te`Wo$qWAPeZ;6W29xkk#4gBX~5ldJK>( zGbK~my+{5Hd}BXu=M8{VfA3f29}Lp2zFz{4<5h zyQ5QMHd=s=iR%eEKR@@rVP3`u6Km)P`#-WmECkv=R$@;vd!sa;+A-o{PHKIzuiVSj zN>lVI(BA7taEE~40B3df5+eDsP!#xks~zxB^kXb;l7Dbo{^&{M`w17|=l=l*xJTM9 zV^1Y;jr8?Ns}_pdhH=*8`i7lzO3Gh=D^$R12TI&`00P~YKtlTk5bWn-f^`s0YF5C+ z)-7ECy?P^PmBCBD-&A3i4F1O((8hMIF3*3$FE1|I-j1}<`Tc|gd2?rA5w^-m_#v>A zQO-HjJG$m*3Kfb5h$xRc<5pO{KW;M(094Kzi?@n@Z%#xYXdgmO7T<>?dobX=fIE;Y3YY#oa1-~G)pZHxdm z`f!5fweg=H+oAPEx$u73C9U>W@>bb95+J6G#O#2dg8Ns?b$$k~oTym=_oQyxAWMq? z0|$zTgka)nPhr&NiU{yT{mt28ozq_T`s*EydJ8IzQFLI%nLx4e!9^mP6!UAB)~tuUum#p!TtD!bL?e&;q7hE6@osf zk!e3EfB&n6R$52^P@JWHM}!6*f!Z0Sf+B#&S;SPuu|gzYfgw0RV#!1ljJuq|fMHSx zSOF0*67631%V(_Ghy_u52MBq@%rPvaQklZNa{C+Y8j=lmxtiv3NSAI-${T$1WIU#W z`95m3N=rH}qa}-&$%I(IgqFJMKuU^=k4zAC_?5iiq(5VyF$g&`b0IJbO_)zq5Zf35 z%B(gg<#(p_V|`=ZRhl~r1e-MH$JKGAQXdF8Wm&NdrlKG6Saq>w zya@R-Q7(fT(K5jzVDww`bF2diLBHBYe!zcDI|GsgK7<=+?A1rin2JuYSefVd!$++- zr2PT20yYVw2Yr+Dl<~=vY`ScNETbjE#Rm%u4;LRs5kH6~iBydGsuZb^^o<*uwI_er z&b}>g)Zb7P_KOO5K+wx?@CO&4yP zS&jwjjl*jLj1Wor6J}gJpRpLD!B7w|miRV!y3&e@OX1pD{mo}V@E4i(8H*F;g)nQzbd;$ zM~gWE&kxYlvR7Myegt4gJ3FEYYkmEUHu(PjesCGUN=|A)%2L8vHVe;s4#|`Ay$AQb z*|BHfr!R2Gk9LA�R+`I1tyzyh-J=^I?7-t5?J;I}C}U)i^HK21T7 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 literal 0 HcmV?d00001 diff --git a/doc/image4.png b/doc/image4.png new file mode 100644 index 0000000000000000000000000000000000000000..c4dbc1850b4b6a62d597c20a06ce6909dd24737b GIT binary patch literal 32473 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 YPbDILcfM&Ttbc!7MgpOHMZfy~FX8VlegFUf literal 0 HcmV?d00001 diff --git a/doc/image5.png b/doc/image5.png new file mode 100644 index 0000000000000000000000000000000000000000..a9b02f9c3cafa7c3ec261a5af1a1222f8cae3057 GIT binary patch literal 50002 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%0A&+|^J-79U{BCKHH72!A)yn_ux%}AzD(TOB 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 z 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 literal 0 HcmV?d00001 diff --git a/doc/image7.png b/doc/image7.png new file mode 100644 index 0000000000000000000000000000000000000000..25dfbf868c97916605eb7ea37dcab8b362ebedf3 GIT binary patch literal 104139 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

|Gfp?8S{j!yB4 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

    or>2tO#r*M?9haOKOX+$??nkx1_Z$81 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 literal 0 HcmV?d00001 From c517d4801cff96840e4597e176da2f0ffafc0229 Mon Sep 17 00:00:00 2001 From: 1_modm Date: Thu, 20 Jul 2017 21:28:22 +0100 Subject: [PATCH 072/166] peht fix --- decoders/http/peht.py | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/decoders/http/peht.py b/decoders/http/peht.py index c39926a..9ce0e3d 100644 --- a/decoders/http/peht.py +++ b/decoders/http/peht.py @@ -109,7 +109,9 @@ def __init__(self): """, - filter='tcp', + filter='tcp and (port 80 or port 81 or port 8080 or port 8000)', + filterfn=lambda ((sip, sp), (dip, dp)): sp in ( + 80, 81, 8000, 8080) or dp in (80, 81, 8000, 8080), author='mm', optiondict={ 'showcontent': {'action': 'store_true', 'default': False, 'help': 'Display the request and response body content.'} @@ -145,7 +147,10 @@ def check_payload(self, payloadheader, payloaduri, requestbody): ET_identified = 'Arbitrary Remote Code Execution/injection' if payloadheader.has_key('content-type'): - if ('cmd' and 'ProcessBuilder' and 'struts') in payloadheader['content-type']: + struts_ioc = ['cmd', 'ProcessBuilder', 'struts'] + #Will return empty if all words from struts_ioc are in payloadheader['content-type'] + struts_check = list(filter(lambda x: x not in payloadheader['content-type'], struts_ioc)) + if not struts_check: ET_identified = 'Apache Struts Content-Type arbitrary command execution' if payloadheader.has_key('user-agent'): @@ -226,8 +231,8 @@ def HTTPHandler(self, conn, request, response, requesttime, responsetime): if request.headers.has_key('user-agent'): self.request_user_agent = request.headers['user-agent'] - self.out.write("\nRequest Timestamp (UTC): {0} \nPenetration/Exploit/Hijacking Tool: {1}\nUser-Agent: {2}\nRequest Method: {3}\nURI: {4}\nSource IP: {5} - Source port: {6} - MAC: {7}\nHost requested: {8}\n".format(datetime.datetime.utcfromtimestamp( - requesttime), self.request_ioc, self.request_user_agent, self.request_method, request.uri, conn.sip, conn.sport, conn.smac, self.request_host), formatTag="H2", direction=self.direction) + self.out.write("\nRequest Timestamp (UTC): {0} \nPenetration/Exploit/Hijacking Tool: {1}\nUser-Agent: {2}\nRequest Method: {3}\nURI: {4}\nSource IP: {5} - Source port: {6} - MAC: {7}\nHost requested: {8}\nReferer: {9}\n".format(datetime.datetime.utcfromtimestamp( + requesttime), self.request_ioc, self.request_user_agent, self.request_method, request.uri, conn.sip, conn.sport, conn.smac, self.request_host, self.request_referer), formatTag="H2", direction=self.direction) # Show request body content if self.showcontent: @@ -252,7 +257,6 @@ def HTTPHandler(self, conn, request, response, requesttime, responsetime): if self.showcontent: self.out.write("\n{0}\n".format(self.response_body), formatTag="H2", direction=self.direction) - if __name__ == '__main__': dObj = DshellDecoder() print dObj From 2a0fdde137d4dbef75a2661227bf71512688cafc Mon Sep 17 00:00:00 2001 From: Adam Maddock Date: Sun, 24 Sep 2017 18:10:23 +0000 Subject: [PATCH 073/166] These decoders were specifying their output preference using the deprecated method of setting "self.output" to the string/name of the output library. --- decoders/http/httpdump.py | 3 ++- decoders/smb/psexec.py | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/decoders/http/httpdump.py b/decoders/http/httpdump.py index 73440a2..d32b00f 100644 --- a/decoders/http/httpdump.py +++ b/decoders/http/httpdump.py @@ -3,6 +3,7 @@ import hashlib import urllib import re +import colorout from httpdecoder import HTTPDecoder @@ -25,7 +26,7 @@ def __init__(self): 'urlfilter': {'type': 'string', 'default': None, 'help': 'Filter to URLs matching this regex'}, }, ) - self.output = 'colorout' + self.out = colorout.ColorOutput() # Disable auto-gunzip as we want to indicate content that was # compressed in the output self.gunzip = False diff --git a/decoders/smb/psexec.py b/decoders/smb/psexec.py index d9a3762..8d2455d 100644 --- a/decoders/smb/psexec.py +++ b/decoders/smb/psexec.py @@ -52,7 +52,7 @@ def __init__(self): ) self.legacy = True # self.out=colorout.ColorOutput(title='psexec') - self.output = 'colorout' + self.out = colorout.ColorOutput() def sessIndexFromPID(self, conn, pid): return ':'.join((str(conn.starttime), conn.sip, str(conn.sport), conn.dip, str(conn.dport), pid)) From 8e48c3549fb5487d8710886cb4c8efaebb483da6 Mon Sep 17 00:00:00 2001 From: Adam Maddock Date: Tue, 26 Sep 2017 21:07:40 +0000 Subject: [PATCH 074/166] Establish starting nextoffset for internally created Connection object --- decoders/misc/xor.py | 1 + 1 file changed, 1 insertion(+) diff --git a/decoders/misc/xor.py b/decoders/misc/xor.py index c95a6c9..c8155b4 100644 --- a/decoders/misc/xor.py +++ b/decoders/misc/xor.py @@ -50,6 +50,7 @@ def makeKey(self, key): def connectionInitHandler(self, conn): # need to set up a custom connection tracker to handle self.xorconn[conn.addr] = dshell.Connection(self, conn.addr, conn.ts) + self.xorconn[conn.addr].nextoffset = conn.nextoffset # self.xorconn[conn.addr]=conn # From 0bf45959c1ac29cff6e3147ab1d26a02407f54b1 Mon Sep 17 00:00:00 2001 From: Adam Maddock Date: Wed, 15 Nov 2017 21:05:10 +0000 Subject: [PATCH 075/166] * removed old line, which has been commented out for a while * added assignment of existing conn's protocol to new connectio nobject --- decoders/misc/xor.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/decoders/misc/xor.py b/decoders/misc/xor.py index c8155b4..40f1f9c 100644 --- a/decoders/misc/xor.py +++ b/decoders/misc/xor.py @@ -51,7 +51,8 @@ def connectionInitHandler(self, conn): # need to set up a custom connection tracker to handle self.xorconn[conn.addr] = dshell.Connection(self, conn.addr, conn.ts) self.xorconn[conn.addr].nextoffset = conn.nextoffset - # self.xorconn[conn.addr]=conn + self.xorconn[conn.addr].proto = conn.proto + self.xorconn[conn.addr].info(proto=conn.proto) # # Each blob will be xor'ed and the "newblob" data will be added to the connection From 709d087b93917c4d4fcb3a224244f227ea040172 Mon Sep 17 00:00:00 2001 From: adam Date: Thu, 13 Sep 2018 18:19:05 +0000 Subject: [PATCH 076/166] Account for condition where ECE flag is set on SYN-ACK packet. --- lib/dshell.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/dshell.py b/lib/dshell.py index be2692b..15ab5ea 100755 --- a/lib/dshell.py +++ b/lib/dshell.py @@ -743,7 +743,8 @@ def TCP(self, addr, tcp, ts, **kwargs): conn = self.track(addr, ts=ts, state='init', **kwargs) if conn: conn.nextoffset['cs'] = tcp.seq + 1 - elif tcp.flags == (dpkt.tcp.TH_SYN | dpkt.tcp.TH_ACK): + elif (tcp.flags == dpkt.tcp.TH_SYN | dpkt.tcp.TH_ACK + or tcp.flags == dpkt.tcp.TH_SYN | dpkt.tcp.TH_ACK | dpkt.tcp.TH_ECE): # SYN ACK if conn and tcp.ack == conn.nextoffset['cs']: conn.nextoffset['sc'] = tcp.seq + 1 From 64098ecb60ecbce828a0e550b13057d1a3174aef Mon Sep 17 00:00:00 2001 From: dev195 Date: Tue, 5 Feb 2019 10:13:16 -0500 Subject: [PATCH 077/166] Fixed bug in 'writer' decoder that caused it to raise an exception when passed additional keyword arguments. --- decoders/misc/writer.py | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/decoders/misc/writer.py b/decoders/misc/writer.py index 92e315e..28479b2 100644 --- a/decoders/misc/writer.py +++ b/decoders/misc/writer.py @@ -23,15 +23,18 @@ def __init__(self, **kwargs): ''' self.file = None dshell.Decoder.__init__(self, - name='writer', - description='pcap/session writer', - author='twp', - raw=True, - optiondict=dict(filename=dict(default='%(clientip)s:%(clientport)s-%(serverip)s:%(serverport)s-%(direction)s.txt'), - ) - ) - - def rawHandler(self, pktlen, pkt, ts): + name='writer', + description='pcap/session writer', + author='twp', + raw=True, + optiondict=dict( + filename=dict( + default='%(clientip)s:%(clientport)s-%(serverip)s:%(serverport)s-%(direction)s.txt' + ), + ) + ) + + def rawHandler(self, pktlen, pkt, ts, **kwargs): self.decodedbytes += pktlen self.count += 1 self.dump(pktlen, pkt, ts) # pktlen may be wrong if we stripped vlan From f13a53c8ae15971e8a9cae301e6ca0ebad703dcd Mon Sep 17 00:00:00 2001 From: dev195 Date: Mon, 11 Feb 2019 10:08:19 -0500 Subject: [PATCH 078/166] Removed deprecated pygeoip dependency from dshell.py, and replaced it with geoip2. Updated documentation to reflect. --- README.md | 16 ++++--- docker/Dockerfile | 18 ++++---- lib/dshell.py | 96 +++++++++++++++++++++--------------------- share/GeoIP/readme.txt | 2 +- 4 files changed, 67 insertions(+), 65 deletions(-) diff --git a/README.md b/README.md index 9e41d0c..6e45522 100644 --- a/README.md +++ b/README.md @@ -14,8 +14,8 @@ Key features: * Linux (developed on Ubuntu 12.04) * Python 2.7 -* [pygeoip](https://github.com/appliedsec/pygeoip), GNU Lesser GPL - * [MaxMind GeoIP Legacy datasets](http://dev.maxmind.com/geoip/legacy/geolite/) +* [geoip2](https://github.com/maxmind/GeoIP2-python), Apache License, Version 2.0 + * [MaxMind GeoIP datasets](https://dev.maxmind.com/geoip/geoip2/geolite2/) * [PyCrypto](https://pypi.python.org/pypi/pycrypto), custom license * [dpkt](https://code.google.com/p/dpkt/), New BSD License * [IPy](https://github.com/haypo/python-ipy), BSD 2-Clause License @@ -24,13 +24,11 @@ Key features: ## Installation -1. Install all of the necessary Python modules listed above. Many of them are available via pip and/or apt-get. Pygeoip is not yet available as a package and must be installed with pip or manually. +1. Install all of the necessary Python modules listed above. Many of them are available via pip and/or apt-get. - 1. `sudo apt-get install python-crypto python-dpkt python-ipy python-pypcap` + * `sudo pip install geoip2 pycrypto dpkt IPy pypcap` - 2. `sudo pip install pygeoip` - -2. Configure pygeoip by moving the MaxMind data files (GeoIP.dat, GeoIPv6.dat, GeoIPASNum.dat, GeoIPASNumv6.dat) to <install-location>/share/GeoIP/ +2. Configure GeoIP by moving the MaxMind data files (GeoLite2-Country.mmdb, GeoLite2-ASN.mmdb) to <install-location>/share/GeoIP/ 2. Run `make`. This will build Dshell. @@ -50,6 +48,10 @@ Key features: ## Development * [Using Dshell With PyCharm](doc/UsingDshellWithPyCharm.md) +## Recent Major Updates + +* Feb 2019 - Removed deprecated pygeoip dependency, and replaced it with geoip2. This requires the use of new GeoIP data files, listed in the Prerequisites and Installation sections above. + ## Partners Below are repositories from partners Dshell has worked together with. diff --git a/docker/Dockerfile b/docker/Dockerfile index 9f00752..e964de7 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -4,25 +4,25 @@ FROM ubuntu:14.04 RUN apt-get update && apt-get install -y \ python-crypto \ python-dpkt \ - python-ipy \ + python-ipy \ python-pypcap \ python-pip \ + python-geoip2 \ wget \ git -RUN pip install pygeoip - # Download the latest version of the code from GitHub WORKDIR /opt/ RUN git clone https://github.com/USArmyResearchLab/Dshell.git -# download and gunzip GeoIP files +# download and untar GeoIP files WORKDIR /opt/Dshell/share/GeoIP/ -RUN wget http://geolite.maxmind.com/download/geoip/database/GeoLiteCountry/GeoIP.dat.gz -RUN wget http://geolite.maxmind.com/download/geoip/database/GeoIPv6.dat.gz -RUN wget http://download.maxmind.com/download/geoip/database/asnum/GeoIPASNum.dat.gz -RUN wget http://download.maxmind.com/download/geoip/database/asnum/GeoIPASNumv6.dat.gz -RUN gunzip *.gz +RUN wget https://geolite.maxmind.com/download/geoip/database/GeoLite2-Country.tar.gz +RUN wget https://geolite.maxmind.com/download/geoip/database/GeoLite2-ASN.tar.gz +RUN tar -zxf GeoLite2-Country.tar.gz +RUN tar -zxf GeoLite2-ASN.tar.gz +RUN GeoLite2-Country*/GeoLite2-Country.mmdb . +RUN GeoLite2-ASN*/GeoLite2-ASN.mmdb . # make Dshell WORKDIR /opt/Dshell/ diff --git a/lib/dshell.py b/lib/dshell.py index 15ab5ea..a2e461e 100755 --- a/lib/dshell.py +++ b/lib/dshell.py @@ -14,7 +14,7 @@ # For IP lookups try: - import pygeoip + import geoip2.database except: pass @@ -106,25 +106,18 @@ def __init__(self, **kwargs): self.cleanupts = 0 # instantiate and save references to lookup function + geoip_dir = os.path.join(os.environ['DATAPATH'], "GeoIP") try: - self.geoccdb = [pygeoip.GeoIP(os.environ[ - 'DATAPATH'] + '/GeoIP/GeoIP.dat', pygeoip.MEMORY_CACHE).country_code_by_addr] - try: - self.geoccdb.append(pygeoip.GeoIP(os.environ[ - 'DATAPATH'] + '/GeoIP/GeoIPv6.dat', pygeoip.MEMORY_CACHE).country_code_by_addr) - except: - pass + self.geoccdb = geoip2.database.Reader( + os.path.join(geoip_dir, "GeoLite2-Country.mmdb") + ).country except: self.geoccdb = None try: - self.geoasndb = [pygeoip.GeoIP( - os.environ['DATAPATH'] + '/GeoIP/GeoIPASNum.dat', pygeoip.MEMORY_CACHE).org_by_addr] - try: - self.geoasndb.append(pygeoip.GeoIP(os.environ[ - 'DATAPATH'] + '/GeoIP/GeoIPASNumv6.dat', pygeoip.MEMORY_CACHE).org_by_addr) - except: - pass + self.geoasndb = geoip2.database.Reader( + os.path.join(geoip_dir, "GeoLite2-ASN.mmdb") + ).asn except: self.geoasndb = None @@ -250,41 +243,48 @@ class members will be updated from value''' if self.name in options: self.parseOptions(options[self.name]) - def getGeoIP(self, ip, db=[], notfound='--'): + def getGeoIP(self, ip, db=None, notfound='--'): """ - Get record associated with an IP - requires GeoIP + Get country code associated with an IP. + Requires GeoIP library (geoip2) and data files. """ - o = None - if db == []: - db = self.geoccdb # default to self.geoccdb - for d in db: - try: - o = d(ip) - except: - # traceback.print_exc() # removed by bg on 20121203 - continue # passing ipv6 address to ipv4 lookup or v/v - if o: - return o # stop when we get a result - return notfound - - def getASN(self, ip, db=[], notfound='--'): + if not db: + db = self.geoccdb + try: + # Get country code based on order of importance + # 1st: Country that owns an IP address registered in another + # location (e.g. military bases in foreign countries) + # 2nd: Country in which the IP address is registered + # 3rd: Physical country where IP address is located + # https://dev.maxmind.com/geoip/geoip2/whats-new-in-geoip2/#Country_Registered_Country_and_Represented_Country + location = db(ip) + country = ( + location.represented_country.iso_code or + location.registered_country.iso_code or + location.country.iso_code or + notfound + ) + return country + except Exception: + # Many expected exceptions can occur here. Ignore them all and + # return default value. + return notfound + + def getASN(self, ip, db=None, notfound='--'): """ - Get record associated with an IP - requires GeoIP + Get ASN associated with an IP. + Requires GeoIP library (geoip2) and data files. """ - o = None - if db == []: - db = self.geoasndb # default to self.geoccdb - for d in db: - try: - o = d(ip) - except: - # traceback.print_exc() # removed by bg on 20121203 - continue # passing ipv6 address to ipv4 lookup or v/v - if o: - return o # stop when we get a result - return notfound + if not db: + db = self.geoasndb + try: + template = "AS{0.autonomous_system_number} {0.autonomous_system_organization}" + asn = template.format( db(ip) ) + return asn + except Exception: + # Many expected exceptions can occur here. Ignore them all and + # return default value. + return notfound def close(self, conn, ts=None): '''for connection based decoders @@ -851,9 +851,9 @@ def __init__(self, decoder, addr, ts=None, pkt=None, **kwargs): # cache try: self.info(sipcc=decoder.getGeoIP(self.sip, db=decoder.geoccdb), - sipasn=decoder.getGeoIP(self.sip, db=decoder.geoasndb), + sipasn=decoder.getASN(self.sip, db=decoder.geoasndb), dipcc=decoder.getGeoIP(self.dip, db=decoder.geoccdb), - dipasn=decoder.getGeoIP(self.dip, db=decoder.geoasndb)) + dipasn=decoder.getASN(self.dip, db=decoder.geoasndb)) except: self.sipcc, self.sipasn, self.dipcc, self.dipasn = None, None, None, None diff --git a/share/GeoIP/readme.txt b/share/GeoIP/readme.txt index e0e8211..eb5f048 100644 --- a/share/GeoIP/readme.txt +++ b/share/GeoIP/readme.txt @@ -1 +1 @@ -GeoIP Legacy data sets go here. +GeoIP data sets go here. From 645673da6c0dd3260fee2a7be4b12110f3510d53 Mon Sep 17 00:00:00 2001 From: dev195 Date: Thu, 14 Feb 2019 08:29:25 -0500 Subject: [PATCH 079/166] Updated Makefile to remove bin/decode symlink when running 'make clean'. This helps avoid an error when re-running 'make' and bin/decode already exists. --- Makefile | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/Makefile b/Makefile index daa5cc5..7dba82f 100755 --- a/Makefile +++ b/Makefile @@ -5,7 +5,7 @@ all: rc dshell dshell: rc initpy pydoc rc: - # Generating .dshellrc and dshell files + # Generating .dshellrc and dshell files python $(PWD)/bin/generate-dshellrc.py $(PWD) chmod 755 $(PWD)/dshell chmod 755 $(PWD)/dshell-decode @@ -16,17 +16,19 @@ initpy: find $(PWD)/decoders -type d -not -path \*.svn\* -print -exec touch {}/__init__.py \; pydoc: - (cd $(PWD)/doc && ./generate-doc.sh $(PWD) ) + (cd $(PWD)/doc && ./generate-doc.sh $(PWD) ) -clean: clean_pyc +clean: clean_pyc clean_ln distclean: clean clean_py clean_pydoc clean_rc - + clean_rc: rm -fv $(PWD)/dshell rm -fv $(PWD)/dshell-decode rm -fv $(PWD)/.dshellrc - rm -fv $(PWD)/bin/decode + +clean_ln: + rm -fv $(PWD)/bin/decode clean_py: find $(PWD)/decoders -name '__init__.py' -exec rm -v {} \; From 747dff8e0d8d93104453eed38873f697856f4f7f Mon Sep 17 00:00:00 2001 From: Davis Schirmer Date: Sun, 17 Feb 2019 12:50:45 -0500 Subject: [PATCH 080/166] Add .gitignore --- .gitignore | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f8233a9 --- /dev/null +++ b/.gitignore @@ -0,0 +1,9 @@ +*.pyc +__init__.py +__pycache__ + +# Ignore built files +/.dshellrc +/bin/decode +/dshell +/dshell-decode From 21fbbada4eab2c224f1f2ef8fa23c7a543d4ab04 Mon Sep 17 00:00:00 2001 From: Davis Schirmer Date: Sun, 17 Feb 2019 13:25:11 -0500 Subject: [PATCH 081/166] Update Dockerfile to Ubuntu 18.04 and cleanup syntax --- docker/Dockerfile | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/docker/Dockerfile b/docker/Dockerfile index e964de7..f41132f 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -1,4 +1,6 @@ -FROM ubuntu:14.04 +FROM ubuntu:18.04 + +ENV DEBIAN_FRONTEND="noninteractive" # install depdencies RUN apt-get update && apt-get install -y \ @@ -12,17 +14,17 @@ RUN apt-get update && apt-get install -y \ git # Download the latest version of the code from GitHub -WORKDIR /opt/ -RUN git clone https://github.com/USArmyResearchLab/Dshell.git +RUN git -C /opt clone https://github.com/USArmyResearchLab/Dshell.git # download and untar GeoIP files WORKDIR /opt/Dshell/share/GeoIP/ -RUN wget https://geolite.maxmind.com/download/geoip/database/GeoLite2-Country.tar.gz -RUN wget https://geolite.maxmind.com/download/geoip/database/GeoLite2-ASN.tar.gz -RUN tar -zxf GeoLite2-Country.tar.gz -RUN tar -zxf GeoLite2-ASN.tar.gz -RUN GeoLite2-Country*/GeoLite2-Country.mmdb . -RUN GeoLite2-ASN*/GeoLite2-ASN.mmdb . +RUN wget https://geolite.maxmind.com/download/geoip/database/GeoLite2-Country.tar.gz \ + && wget https://geolite.maxmind.com/download/geoip/database/GeoLite2-ASN.tar.gz \ + && tar -zxf GeoLite2-Country.tar.gz \ + && tar -zxf GeoLite2-ASN.tar.gz \ + && ln -s GeoLite2-Country*/GeoLite2-Country.mmdb . \ + && ln -s GeoLite2-ASN*/GeoLite2-ASN.mmdb . \ + && rm -rf /var/lib/apt/lists/* # make Dshell WORKDIR /opt/Dshell/ @@ -31,4 +33,4 @@ RUN make # Used to mount pcap from a host OS directory VOLUME ["/mnt/pcap"] -CMD ["/opt/Dshell/dshell"] +ENTRYPOINT ["/opt/Dshell/dshell"] From c59e9571ea5be7f5c252c5c3d787a2612da0ed4e Mon Sep 17 00:00:00 2001 From: dev195 Date: Thu, 16 May 2019 08:52:02 -0400 Subject: [PATCH 082/166] Fixed bug in country filter that ignored --country_both flag --- decoders/filter/country.py | 43 +++++++++++++++++++------------------- 1 file changed, 22 insertions(+), 21 deletions(-) diff --git a/decoders/filter/country.py b/decoders/filter/country.py index cfde218..72386ba 100644 --- a/decoders/filter/country.py +++ b/decoders/filter/country.py @@ -3,7 +3,6 @@ ''' import dshell -import util import netflowout @@ -19,9 +18,9 @@ def __init__(self, **kwargs): self.alerts = False self.file = None dshell.TCPDecoder.__init__(self, - name='country', - description='filter connections on geolocation (country code)', - longdescription=""" + name='country', + description='filter connections on geolocation (country code)', + longdescription=""" country: filter connections on geolocation (country code) Chainable decoder to filter TCP/UDP streams on geolocation data. If no @@ -55,28 +54,30 @@ def __init__(self, **kwargs): decode -d country traffic.pcap -W USonly.pcap --country_code US decode -d country+followstream traffic.pcap --country_code US --country_notboth """, - filter="ip or ip6", - author='twp', - optiondict={ - 'code': {'type': 'string', 'help': 'two-char country code'}, - 'neither': {'action': 'store_true', 'help': 'neither (client/server) is in specified country'}, - 'both': {'action': 'store_true', 'help': 'both (client/server) ARE in specified country'}, - 'notboth': {'action': 'store_true', 'help': 'specified country is not both client and server'}, - 'alerts': {'action': 'store_true'}}) - '''instantiate an decoder that will call back to us once the IP decoding is done''' + filter="ip or ip6", + author='twp', + optiondict={ + 'code': {'type': 'string', 'help': 'two-char country code'}, + 'neither': {'action': 'store_true', 'help': 'neither (client/server) is in specified country'}, + 'both': {'action': 'store_true', 'help': 'both (client/server) ARE in specified country'}, + 'notboth': {'action': 'store_true', 'help': 'specified country is not both client and server'}, + 'alerts': {'action': 'store_true'} + } + ) + # instantiate a decoder that will call back to us once the IP decoding is done self.__decoder = dshell.IPDecoder() self.out = netflowout.NetflowOutput() self.chainable = True def decode(self, *args): if len(args) is 3: - pktlen, pktdata, ts = args # orig_len,packet,ts format (pylibpcap) - else: # ts,pktdata (pypcap) + pktlen, pktdata, ts = args + else: ts, pktdata = args pktlen = len(pktdata) - '''do normal decoder stack to track session ''' + # do normal decoder stack to track session dshell.TCPDecoder.decode(self, pktlen, pktdata, ts) - '''our hook to decode the ip/ip6 addrs, then dump the addrs and raw packet to our callback''' + # our hook to decode the ip/ip6 addrs, then dump the addrs and raw packet to our callback self.__decoder.IPHandler = self.__callback # set private decoder to our callback self.__decoder.decode(pktlen, pktdata, ts, raw=pktdata) @@ -97,18 +98,18 @@ def connectionInitHandler(self, conn): def __countryTest(self, conn): # If no country code specified, pass all traffic through - if self.code == None or not len(self.code): + if not self.code: return True # check criteria if self.neither and conn.clientcountrycode != self.code and conn.servercountrycode != self.code: return 'neither ' + self.code if self.both and conn.clientcountrycode == self.code and conn.servercountrycode == self.code: return 'both ' + self.code - if self.notboth and (conn.clientcountrycode != self.code or conn.servercountrycode != self.code): + if self.notboth and (conn.clientcountrycode == self.code ^ conn.servercountrycode == self.code): return 'not both ' + self.code - if conn.clientcountrycode == self.code: + if not self.both and conn.clientcountrycode == self.code: return 'client ' + self.code - if conn.servercountrycode == self.code: + if not self.both and conn.servercountrycode == self.code: return 'server ' + self.code # no match return None From 6f15c39691c4cdcf548067512d36b9db5177c4a3 Mon Sep 17 00:00:00 2001 From: dev195 Date: Mon, 20 May 2019 09:10:37 -0400 Subject: [PATCH 083/166] Fixed bug in bug fix for country filter --- decoders/filter/country.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/decoders/filter/country.py b/decoders/filter/country.py index 72386ba..921b168 100644 --- a/decoders/filter/country.py +++ b/decoders/filter/country.py @@ -105,7 +105,7 @@ def __countryTest(self, conn): return 'neither ' + self.code if self.both and conn.clientcountrycode == self.code and conn.servercountrycode == self.code: return 'both ' + self.code - if self.notboth and (conn.clientcountrycode == self.code ^ conn.servercountrycode == self.code): + if self.notboth and ((conn.clientcountrycode == self.code) ^ (conn.servercountrycode == self.code)): return 'not both ' + self.code if not self.both and conn.clientcountrycode == self.code: return 'client ' + self.code From cf182f70d50599400b83b21dd7eb1bf78ff68ece Mon Sep 17 00:00:00 2001 From: adam Date: Fri, 24 Jan 2020 19:02:15 +0000 Subject: [PATCH 084/166] Clean up edge case handling in util.getHeader() --- lib/util.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) mode change 100644 => 100755 lib/util.py diff --git a/lib/util.py b/lib/util.py old mode 100644 new mode 100755 index 4159f9b..2e8684f --- a/lib/util.py +++ b/lib/util.py @@ -259,6 +259,8 @@ def getopts(args, options, def getHeader(request_or_response, header_name): + if request_or_response == None: + return '' try: httpHdr = request_or_response.headers[header_name] except: @@ -269,7 +271,10 @@ def getHeader(request_or_response, header_name): # return unique list joined by ',' return ', '.join(set(httpHdr)) else: - return '' + try: + return unicode(httpHdr).encode('utf-8') + except: + return '' # HTTPlastmodified - Extracts last-modified (or date) header from # HTTP response headers and normalizes date string format From 843b2cb0a1bf22292468eb01ca6a8f797d4d0db4 Mon Sep 17 00:00:00 2001 From: adam Date: Fri, 24 Jan 2020 19:02:41 +0000 Subject: [PATCH 085/166] Clean up web plugin and expand kw values passed to alert() --- decoders/http/web.py | 123 +++++++++++++++++++++++++++---------------- 1 file changed, 79 insertions(+), 44 deletions(-) mode change 100644 => 100755 decoders/http/web.py diff --git a/decoders/http/web.py b/decoders/http/web.py old mode 100644 new mode 100755 index accc47b..752d1dc --- a/decoders/http/web.py +++ b/decoders/http/web.py @@ -24,48 +24,87 @@ def __init__(self): self.gunzip = False # Not interested in response body def HTTPHandler(self, conn, request, response, requesttime, responsetime): - host = '' - loc = '' - lastmodified = '' - - #request_time, request, response = self.httpDict[conn.addr] - - # extract method,uri,host from response - host = util.getHeader(request, 'host') - if host == '': - host = conn.serverip - try: - status = response.status - except: - status = '' - try: - reason = response.reason - except: - reason = '' + # + # Establish kw_items dictionary for extracted details from tcp/ip layer and request/response + # + kw_items = conn.info() + + # + # Extract useful information from HTTP *request* + # + for h in request.headers.keys(): + kw_items[h] = util.getHeader(request, h) + # Rename user-agent for backward compatability + if 'user-agent' in kw_items: + kw_items['useragent'] = kw_items.pop('user-agent') + + # Override non-existent host header with server IP address + if kw_items['host'] == '': + kw_items['host'] = conn.serverip + + # request info string for standard output + requestInfo = '%s %s%s HTTP/%s' % (request.method, + kw_items['host'] if kw_items['host'] != request.uri else '', # With CONNECT method, the URI is or contains the host, making this redudant + request.uri[:self.maxurilen] + '[truncated]' if self.maxurilen > 0 and len( + request.uri) > self.maxurilen else request.uri, + request.version) + # + # Extract useful information from HTTP *response* (if available) + # + status = '' + reason = '' + responsesize = 0 loc = '' - if status[:2] == '30': - loc = util.getHeader(response, 'location') - if len(loc): - loc = '-> ' + loc + lastmodified = '' + md5 = '' + if response!=None: - lastmodified = util.HTTPlastmodified(response) - referer = util.getHeader(request, 'referer') - useragent = util.getHeader(request, 'user-agent') - via = util.getHeader(request, 'via') + try: + responsesize = len(response.body.rstrip('\0')) + except: + responsesize = 0 - try: - responsesize = len(response.body.rstrip('\0')) - except: - responsesize = 0 + if self.md5: + md5 = self._bodyMD5(response) + else: + md5 = '' + + try: + status = response.status + except: + status = '' + try: + reason = response.reason + except: + reason = '' + + for h in response.headers.keys(): + if not h in kw_items: + kw_items[h] = util.getHeader(response, h) + else: + kw_items['server_'+h] = util.getHeader(response, h) + if 'content-type' in kw_items: + kw_items['contenttype'] = kw_items.pop('content-type') + + loc = '' + if status[:2] == '30': + loc = util.getHeader(response, 'location') + if len(loc): + loc = '-> ' + loc + + lastmodified = util.HTTPlastmodified(response) + + # response info string for standard output + responseInfo = '%s %s %s %s' % (status, reason, loc, lastmodified) - if self.md5: - md5 = self._bodyMD5(response) else: - md5 = '' + responseInfo = '' + # # File objects + # try: if len(response.body) > 0: responsefile = dfile.dfile( @@ -80,18 +119,14 @@ def HTTPHandler(self, conn, request, response, requesttime, responsetime): else: uploadfile = None - requestInfo = '%s %s%s HTTP/%s' % (request.method, - host if host != request.uri else '', # With CONNECT method, the URI is or contains the host, making this redudant - request.uri[:self.maxurilen] + '[truncated]' if self.maxurilen > 0 and len( - request.uri) > self.maxurilen else request.uri, - request.version) - if response: - responseInfo = '%s %s %s %s' % (status, reason, loc, lastmodified) - else: - responseInfo = '' + # + # Call alert with text info and kw values + # + self.alert("%-80s // %s" % (requestInfo, responseInfo), request=requestInfo, response=responseInfo, + request_time=requesttime, response_time=responsetime, request_method=request.method, + uri=request.uri, status=status, reason=reason, lastmodified=lastmodified, + md5=md5, responsesize=responsesize, responsefile=responsefile, uploadfile=uploadfile, **kw_items) - self.alert("%-80s // %s" % (requestInfo, responseInfo), referer=referer, useragent=useragent, request=requestInfo, response=responseInfo, request_time=requesttime, response_time=responsetime, request_method=request.method, host=host, - uri=request.uri, status=status, reason=reason, lastmodified=lastmodified, md5=md5, responsesize=responsesize, contenttype=util.getHeader(response, 'content-type'), responsefile=responsefile, uploadfile=uploadfile, via=via, **conn.info()) if self.out.sessionwriter: self.write(request.data, direction='cs') if response: From c14264415332f1e9f26ee36cd0e25d99a210013d Mon Sep 17 00:00:00 2001 From: adam Date: Tue, 11 Feb 2020 19:39:40 +0000 Subject: [PATCH 086/166] Check for postParams with single null value --- decoders/http/httpdump.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/decoders/http/httpdump.py b/decoders/http/httpdump.py index d32b00f..264cb42 100644 --- a/decoders/http/httpdump.py +++ b/decoders/http/httpdump.py @@ -76,6 +76,9 @@ def HTTPHandler(self, conn, request, response, requesttime, responsetime): request.method, response.status, host, uri_location, util.getHeader(response, 'content-type')) urlParams = util.URLDataToParameterDict(uri_data) postParams = util.URLDataToParameterDict(request.body) + # If URLData parser only returns a single element with null value, it's probably an eroneous evaluation. Most likely base64 encoded payload ending in an '=' character. + if len(postParams)==1 and postParams[postParams.keys()[0]] == '\x00': + postParams = None clientCookies = self._parseCookies(util.getHeader(request, 'cookie')) serverCookies = self._parseCookies( From 86aaf7f2c7fa527648ce1a7701fcd49437c77725 Mon Sep 17 00:00:00 2001 From: adam Date: Tue, 11 Feb 2020 20:09:58 +0000 Subject: [PATCH 087/166] Add SOA --- decoders/dns/dns.py | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) mode change 100644 => 100755 decoders/dns/dns.py diff --git a/decoders/dns/dns.py b/decoders/dns/dns.py old mode 100644 new mode 100755 index 5991f10..1971c7d --- a/decoders/dns/dns.py +++ b/decoders/dns/dns.py @@ -22,11 +22,13 @@ def decode_q(self, dns): queried = "" if dns.qd[0].type == dpkt.dns.DNS_A: queried = queried + "A? %s" % (dns.qd[0].name) - if dns.qd[0].type == dpkt.dns.DNS_CNAME: + elif dns.qd[0].type == dpkt.dns.DNS_CNAME: queried = queried + "CNAME? %s" % (dns.qd[0].name) - if dns.qd[0].type == dpkt.dns.DNS_AAAA: + elif dns.qd[0].type == dpkt.dns.DNS_AAAA: queried = queried + "AAAA? %s" % (dns.qd[0].name) - if dns.qd[0].type == dpkt.dns.DNS_PTR: + elif dns.qd[0].type == dpkt.dns.DNS_SOA: + queried = queried + "SOA? %s" % (dns.qd[0].name) + elif dns.qd[0].type == dpkt.dns.DNS_PTR: if dns.qd[0].name.endswith('.in-addr.arpa'): query_name = '.'.join( reversed(dns.qd[0].name.split('.in-addr.arpa')[0].split('.'))) @@ -39,11 +41,11 @@ def decode_q(self, dns): if dns.qd[0].type == dpkt.dns.DNS_NS: queried = queried + "NS? %s" % (dns.qd[0].name) - if dns.qd[0].type == dpkt.dns.DNS_MX: + elif dns.qd[0].type == dpkt.dns.DNS_MX: queried = queried + "MX? %s" % (dns.qd[0].name) - if dns.qd[0].type == dpkt.dns.DNS_TXT: + elif dns.qd[0].type == dpkt.dns.DNS_TXT: queried = queried + "TXT? %s" % (dns.qd[0].name) - if dns.qd[0].type == dpkt.dns.DNS_SRV: + elif dns.qd[0].type == dpkt.dns.DNS_SRV: queried = queried + "SRV? %s" % (dns.qd[0].name) return queried @@ -65,7 +67,7 @@ def DNSHandler(self, conn, request, response, **kwargs): conn.info(query=self.decode_q(dns)) # DNS Answer with data and no errors - elif (dns.qr == dpkt.dns.DNS_A and dns.rcode == dpkt.dns.DNS_RCODE_NOERR and len(dns.an) > 0): + elif (dns.rcode == dpkt.dns.DNS_RCODE_NOERR and len(dns.an) > 0): queried = self.decode_q(dns) @@ -108,6 +110,16 @@ def DNSHandler(self, conn, request, response, **kwargs): if queried != '': anstext = 'NXDOMAIN' + #SOA response + elif dns.qd[0].type == dpkt.dns.DNS_SOA and len(dns.ns): + queried = self.decode_q(dns) + answers = [] + for ns in dns.ns: + if ns.type == dpkt.dns.DNS_SOA: + answers.append('SOA: '+ ns.mname) + anstext = ", ".join(answers) + + # did we get an answer? if anstext and not self.only_noanswer and not self.only_norequest: self.alert( From 87524b8a0d9f4d152d9303528d5740f49a135867 Mon Sep 17 00:00:00 2001 From: dek <41297634+dek443@users.noreply.github.com> Date: Mon, 31 Aug 2020 14:12:38 -0400 Subject: [PATCH 088/166] Update README.md Dshell 3 announcement --- README.md | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 6e45522..d7014eb 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,7 @@ # Dshell +**_A new version of Dshell for Python 3 is coming in September 2020, Dshell 3. See ‘News’ section for additional information._** -An extensible network forensic analysis framework. Enables rapid development of plugins to support the dissection of network packet captures. +An extensible network forensic analysis framework. Enables rapid development of plugins to support the dissection of network packet captures. Key features: @@ -48,8 +49,19 @@ Key features: ## Development * [Using Dshell With PyCharm](doc/UsingDshellWithPyCharm.md) -## Recent Major Updates - +## News + +* Sep 2020 - A new version of Dshell for Python 3 is coming, Dshell 3. + * This is a major framework update to Dshell. Plugins written for the previous version are not compatible with this version, and vice versa. + * Uses Python 3 + * Rewritten in Python 3 from the ground up. Python 2 language deprecated on [1 JAN 2020](https://www.python.org/doc/sunset-python-2/) + * By extension, dpkt and pypcap have been replaced with Python 3-friendly pypacker and pcapy (respectively). + * Is a Python package + * All plugins are chainable + * Plugins can use all output modules + * Improved error handling + * Enables development of external plugin packs, allowing the sharing and installation of new, externally-developed plugins without overlapping the core Dshell libraries. +* Sep 2020 - This Python 2 version of Dshell will be deprecated and tagged with its current version number after Dshell 3 is released. It will still be available via this repository. Issues and Pull requests for the previous version will be closed when the new version is released. * Feb 2019 - Removed deprecated pygeoip dependency, and replaced it with geoip2. This requires the use of new GeoIP data files, listed in the Prerequisites and Installation sections above. ## Partners From bf6bdf639aa9ad6821e2e80e731fd511de550886 Mon Sep 17 00:00:00 2001 From: dek443 <41297634+dek443@users.noreply.github.com> Date: Mon, 21 Sep 2020 15:39:03 -0400 Subject: [PATCH 089/166] Major version update/rewrite to Dshell, now using Python 3. See README for more details. Highlights: - This is a major framework update to Dshell. Plugins written for the previous version are not compatible with this version, and vice versa. - Uses Python 3 - Rewritten in Python 3 from the ground up. Python 2 language deprecated on 1 JAN 2020 - By extension, dpkt and pypcap have been replaced with Python 3-friendly pypacker and pcapy (respectively). - Is a Python package - All plugins are chainable - Plugins can use all output modules - Improved error handling - Enables development of external plugin packs, allowing the sharing and installation of new, externally-developed plugins without overlapping the core Dshell libraries. --- .gitignore | 8 +- Dshell-Training-Pack-0.1.tar.gz | Bin 0 -> 1924 bytes LICENSE | 8 + LICENSE.txt | 5 - Makefile | 41 - README | 207 +++ README.md | 230 +-- bin/decode.py | 964 ----------- bin/generate-dshellrc.py | 147 -- bin/pcapanon.py | 229 --- bin/pcapslice.py | 249 --- decoders/dhcp/dhcp.py | 89 - decoders/dns/dns-asn.py | 76 - decoders/dns/dns-cc.py | 86 - decoders/dns/dns.py | 135 -- decoders/dns/innuendo-dns.py | 93 -- decoders/dns/reservedips.py | 151 -- decoders/filter/asn-filter.py | 100 -- decoders/filter/country.py | 125 -- decoders/filter/snort.py | 209 --- decoders/filter/track.py | 135 -- decoders/flows/large-flows.py | 36 - decoders/flows/long-flows.py | 29 - decoders/flows/netflow.py | 37 - decoders/flows/reverse-flow.py | 68 - decoders/ftp/ftp.py | 296 ---- decoders/http/flash-detect.py | 236 --- decoders/http/httpdump.py | 153 -- decoders/http/joomla-cve-2015-8562.py | 81 - decoders/http/ms15-034.py | 74 - decoders/http/peht.py | 264 --- decoders/http/rip-http.py | 203 --- decoders/http/web.py | 180 -- decoders/malware/emdivi/emdivi_c2.py | 115 -- decoders/misc/followstream.py | 118 -- decoders/misc/grep.py | 205 --- decoders/misc/merge.py | 33 - decoders/misc/synrst.py | 41 - decoders/misc/writer.py | 52 - decoders/misc/xor.py | 120 -- decoders/nbns/nbns.py | 139 -- decoders/protocol/ether.py | 31 - decoders/protocol/ip.py | 30 - decoders/protocol/protocol.py | 40 - decoders/smb/psexec.py | 247 --- decoders/smb/rip-smb-uploads.py | 126 -- decoders/smb/smbfiles.py | 210 --- decoders/templates/PacketDecoder.py | 31 - decoders/templates/SessionDecoder.py | 47 - decoders/voip/sip.py | 217 --- dist/Dshell-3.1.3.tar.gz | Bin 0 -> 85139 bytes doc/UsingDshellWithPyCharm.md | 88 - doc/generate-doc.sh | 12 - doc/image1.png | Bin 82574 -> 0 bytes doc/image10.png | Bin 38111 -> 0 bytes doc/image2.png | Bin 59264 -> 0 bytes doc/image3.png | Bin 109282 -> 0 bytes doc/image4.png | Bin 32473 -> 0 bytes doc/image5.png | Bin 50002 -> 0 bytes doc/image6.png | Bin 63140 -> 0 bytes doc/image7.png | Bin 104139 -> 0 bytes doc/image8.png | Bin 44200 -> 0 bytes doc/image9.png | Bin 47337 -> 0 bytes docker/Dockerfile | 36 - docker/README.md | 16 - dshell/__init__.py | 0 dshell/core.py | 1448 +++++++++++++++++ {share => dshell/data}/GeoIP/readme.txt | 0 dshell/data/dshellrc | 2 + dshell/data/empty.pcap | Bin 0 -> 24 bytes dshell/decode.py | 742 +++++++++ dshell/dshellargparse.py | 40 + dshell/dshellgeoip.py | 144 ++ dshell/dshelllist.py | 55 + dshell/output/__init__.py | 0 dshell/output/alertout.py | 15 + dshell/output/colorout.py | 88 + dshell/output/csvout.py | 61 + dshell/output/elasticout.py | 74 + dshell/output/htmlout.py | 127 ++ dshell/output/jsonout.py | 44 + dshell/output/netflowout.py | 86 + dshell/output/output.py | 247 +++ dshell/output/pcapout.py | 64 + dshell/plugins/__init__.py | 0 dshell/plugins/dhcp/__init__.py | 0 dshell/plugins/dhcp/dhcp.py | 102 ++ dshell/plugins/dns/__init__.py | 0 dshell/plugins/dns/dns.py | 174 ++ dshell/plugins/dns/dnscc.py | 84 + dshell/plugins/dns/innuendo-dns.py | 85 + dshell/plugins/dns/specialips.py | 110 ++ dshell/plugins/dnsplugin.py | 124 ++ dshell/plugins/filter/__init__.py | 0 dshell/plugins/filter/country.py | 102 ++ dshell/plugins/filter/track.py | 153 ++ dshell/plugins/flows/__init__.py | 0 dshell/plugins/flows/largeflows.py | 38 + dshell/plugins/flows/longflows.py | 38 + dshell/plugins/flows/netflow.py | 20 + dshell/plugins/flows/reverseflows.py | 84 + dshell/plugins/flows/toptalkers.py | 83 + dshell/plugins/ftp/__init__.py | 0 dshell/plugins/ftp/ftp.py | 352 ++++ dshell/plugins/http/__init__.py | 0 dshell/plugins/http/httpdump.py | 168 ++ dshell/plugins/http/joomla.py | 86 + dshell/plugins/http/ms15-034.py | 64 + dshell/plugins/http/riphttp.py | 205 +++ dshell/plugins/http/web.py | 67 + dshell/plugins/httpplugin.py | 255 +++ dshell/plugins/malware/__init__.py | 0 dshell/plugins/malware/sweetorange.py | 82 + dshell/plugins/misc/__init__.py | 0 dshell/plugins/misc/followstream.py | 25 + dshell/plugins/misc/pcapwriter.py | 64 + dshell/plugins/misc/search.py | 92 ++ dshell/plugins/misc/sslalerts.py | 107 ++ dshell/plugins/misc/synrst.py | 53 + dshell/plugins/misc/xor.py | 101 ++ dshell/plugins/nbns/__init__.py | 0 dshell/plugins/nbns/nbns.py | 160 ++ dshell/plugins/portscan/__init__.py | 0 dshell/plugins/portscan/indegree.py | 35 + dshell/plugins/portscan/trw.py | 93 ++ dshell/plugins/protocol/__init__.py | 0 .../plugins}/protocol/bitcoin.py | 187 ++- dshell/plugins/protocol/ether.py | 66 + dshell/plugins/protocol/ip.py | 24 + dshell/plugins/protocol/protocol.py | 22 + dshell/plugins/ssl/__init__.py | 0 dshell/plugins/ssl/sslblacklist.py | 124 ++ dshell/plugins/tftp/__init__.py | 0 {decoders => dshell/plugins}/tftp/tftp.py | 217 ++- dshell/plugins/visual/__init__.py | 0 dshell/plugins/visual/piecharts.py | 314 ++++ dshell/plugins/voip/__init__.py | 0 {decoders => dshell/plugins}/voip/rtp.py | 90 +- dshell/plugins/voip/sip.py | 174 ++ dshell/plugins/wifi/__init__.py | 0 dshell/plugins/wifi/wifi80211.py | 88 + dshell/plugins/wifi/wifibeacon.py | 66 + dshell/util.py | 151 ++ install-ubuntu.py | 28 - lib/dfile.py | 178 -- lib/dnsdecoder.py | 101 -- lib/dshell.py | 1113 ------------- lib/httpdecoder.py | 101 -- lib/output/colorout.py | 377 ----- lib/output/csvout.py | 76 - lib/output/elasticout.py | 219 --- lib/output/jsonout.py | 135 -- lib/output/netflowout.py | 86 - lib/output/output.py | 562 ------- lib/output/xmlout.py | 60 - lib/smbdecoder.py | 429 ----- lib/util.py | 295 ---- scripts/dshell | 3 + setup.py | 35 + 159 files changed, 8121 insertions(+), 10541 deletions(-) create mode 100644 Dshell-Training-Pack-0.1.tar.gz create mode 100644 LICENSE delete mode 100644 LICENSE.txt delete mode 100755 Makefile create mode 100644 README delete mode 100755 bin/decode.py delete mode 100755 bin/generate-dshellrc.py delete mode 100755 bin/pcapanon.py delete mode 100755 bin/pcapslice.py delete mode 100644 decoders/dhcp/dhcp.py delete mode 100644 decoders/dns/dns-asn.py delete mode 100644 decoders/dns/dns-cc.py delete mode 100755 decoders/dns/dns.py delete mode 100644 decoders/dns/innuendo-dns.py delete mode 100644 decoders/dns/reservedips.py delete mode 100644 decoders/filter/asn-filter.py delete mode 100644 decoders/filter/country.py delete mode 100644 decoders/filter/snort.py delete mode 100644 decoders/filter/track.py delete mode 100644 decoders/flows/large-flows.py delete mode 100644 decoders/flows/long-flows.py delete mode 100644 decoders/flows/netflow.py delete mode 100644 decoders/flows/reverse-flow.py delete mode 100644 decoders/ftp/ftp.py delete mode 100644 decoders/http/flash-detect.py delete mode 100644 decoders/http/httpdump.py delete mode 100644 decoders/http/joomla-cve-2015-8562.py delete mode 100644 decoders/http/ms15-034.py delete mode 100644 decoders/http/peht.py delete mode 100644 decoders/http/rip-http.py delete mode 100755 decoders/http/web.py delete mode 100644 decoders/malware/emdivi/emdivi_c2.py delete mode 100644 decoders/misc/followstream.py delete mode 100644 decoders/misc/grep.py delete mode 100644 decoders/misc/merge.py delete mode 100644 decoders/misc/synrst.py delete mode 100644 decoders/misc/writer.py delete mode 100644 decoders/misc/xor.py delete mode 100644 decoders/nbns/nbns.py delete mode 100644 decoders/protocol/ether.py delete mode 100644 decoders/protocol/ip.py delete mode 100644 decoders/protocol/protocol.py delete mode 100644 decoders/smb/psexec.py delete mode 100644 decoders/smb/rip-smb-uploads.py delete mode 100644 decoders/smb/smbfiles.py delete mode 100644 decoders/templates/PacketDecoder.py delete mode 100644 decoders/templates/SessionDecoder.py delete mode 100644 decoders/voip/sip.py create mode 100644 dist/Dshell-3.1.3.tar.gz delete mode 100644 doc/UsingDshellWithPyCharm.md delete mode 100755 doc/generate-doc.sh delete mode 100644 doc/image1.png delete mode 100644 doc/image10.png delete mode 100644 doc/image2.png delete mode 100644 doc/image3.png delete mode 100644 doc/image4.png delete mode 100644 doc/image5.png delete mode 100644 doc/image6.png delete mode 100644 doc/image7.png delete mode 100644 doc/image8.png delete mode 100644 doc/image9.png delete mode 100644 docker/Dockerfile delete mode 100644 docker/README.md create mode 100644 dshell/__init__.py create mode 100644 dshell/core.py rename {share => dshell/data}/GeoIP/readme.txt (100%) create mode 100644 dshell/data/dshellrc create mode 100644 dshell/data/empty.pcap create mode 100755 dshell/decode.py create mode 100644 dshell/dshellargparse.py create mode 100644 dshell/dshellgeoip.py create mode 100644 dshell/dshelllist.py create mode 100644 dshell/output/__init__.py create mode 100644 dshell/output/alertout.py create mode 100644 dshell/output/colorout.py create mode 100644 dshell/output/csvout.py create mode 100644 dshell/output/elasticout.py create mode 100644 dshell/output/htmlout.py create mode 100644 dshell/output/jsonout.py create mode 100644 dshell/output/netflowout.py create mode 100644 dshell/output/output.py create mode 100644 dshell/output/pcapout.py create mode 100644 dshell/plugins/__init__.py create mode 100644 dshell/plugins/dhcp/__init__.py create mode 100644 dshell/plugins/dhcp/dhcp.py create mode 100644 dshell/plugins/dns/__init__.py create mode 100644 dshell/plugins/dns/dns.py create mode 100644 dshell/plugins/dns/dnscc.py create mode 100644 dshell/plugins/dns/innuendo-dns.py create mode 100644 dshell/plugins/dns/specialips.py create mode 100644 dshell/plugins/dnsplugin.py create mode 100644 dshell/plugins/filter/__init__.py create mode 100644 dshell/plugins/filter/country.py create mode 100644 dshell/plugins/filter/track.py create mode 100644 dshell/plugins/flows/__init__.py create mode 100644 dshell/plugins/flows/largeflows.py create mode 100644 dshell/plugins/flows/longflows.py create mode 100644 dshell/plugins/flows/netflow.py create mode 100644 dshell/plugins/flows/reverseflows.py create mode 100644 dshell/plugins/flows/toptalkers.py create mode 100644 dshell/plugins/ftp/__init__.py create mode 100644 dshell/plugins/ftp/ftp.py create mode 100644 dshell/plugins/http/__init__.py create mode 100644 dshell/plugins/http/httpdump.py create mode 100644 dshell/plugins/http/joomla.py create mode 100644 dshell/plugins/http/ms15-034.py create mode 100644 dshell/plugins/http/riphttp.py create mode 100644 dshell/plugins/http/web.py create mode 100644 dshell/plugins/httpplugin.py create mode 100644 dshell/plugins/malware/__init__.py create mode 100644 dshell/plugins/malware/sweetorange.py create mode 100644 dshell/plugins/misc/__init__.py create mode 100644 dshell/plugins/misc/followstream.py create mode 100644 dshell/plugins/misc/pcapwriter.py create mode 100644 dshell/plugins/misc/search.py create mode 100644 dshell/plugins/misc/sslalerts.py create mode 100644 dshell/plugins/misc/synrst.py create mode 100644 dshell/plugins/misc/xor.py create mode 100644 dshell/plugins/nbns/__init__.py create mode 100644 dshell/plugins/nbns/nbns.py create mode 100644 dshell/plugins/portscan/__init__.py create mode 100644 dshell/plugins/portscan/indegree.py create mode 100644 dshell/plugins/portscan/trw.py create mode 100644 dshell/plugins/protocol/__init__.py rename {decoders => dshell/plugins}/protocol/bitcoin.py (64%) create mode 100644 dshell/plugins/protocol/ether.py create mode 100644 dshell/plugins/protocol/ip.py create mode 100644 dshell/plugins/protocol/protocol.py create mode 100644 dshell/plugins/ssl/__init__.py create mode 100644 dshell/plugins/ssl/sslblacklist.py create mode 100644 dshell/plugins/tftp/__init__.py rename {decoders => dshell/plugins}/tftp/tftp.py (58%) create mode 100644 dshell/plugins/visual/__init__.py create mode 100644 dshell/plugins/visual/piecharts.py create mode 100644 dshell/plugins/voip/__init__.py rename {decoders => dshell/plugins}/voip/rtp.py (62%) create mode 100644 dshell/plugins/voip/sip.py create mode 100644 dshell/plugins/wifi/__init__.py create mode 100644 dshell/plugins/wifi/wifi80211.py create mode 100644 dshell/plugins/wifi/wifibeacon.py create mode 100644 dshell/util.py delete mode 100755 install-ubuntu.py delete mode 100644 lib/dfile.py delete mode 100644 lib/dnsdecoder.py delete mode 100755 lib/dshell.py delete mode 100644 lib/httpdecoder.py delete mode 100644 lib/output/colorout.py delete mode 100644 lib/output/csvout.py delete mode 100644 lib/output/elasticout.py delete mode 100644 lib/output/jsonout.py delete mode 100644 lib/output/netflowout.py delete mode 100644 lib/output/output.py delete mode 100644 lib/output/xmlout.py delete mode 100644 lib/smbdecoder.py delete mode 100755 lib/util.py create mode 100755 scripts/dshell create mode 100644 setup.py diff --git a/.gitignore b/.gitignore index f8233a9..e37d53a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,9 +1,3 @@ *.pyc -__init__.py __pycache__ - -# Ignore built files -/.dshellrc -/bin/decode -/dshell -/dshell-decode +Dshell.egg-info diff --git a/Dshell-Training-Pack-0.1.tar.gz b/Dshell-Training-Pack-0.1.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..5841d34e1f4a9497557d656b21114c30e7168e8b GIT binary patch literal 1924 zcmV-~2YdJ*iwFoRCP`lc|72-%bT346Xk~0{EmU%0X>Mt5XDv`+V{0uiE-@~2VR8WN zTI+AyHW1He{S}1vA$FE1l3yAOxIoZ$Ytb$Vns)mT1OhG5wpL2iNGfR>a$Osqj@!0->buqH zI9Yi?J5Jke0k!RJYsYrFovyQkx;tB-R7lJb+WCixNs7r*xmXO>PEt)|`g|euW|{tj zjN!?Gakx$Wx9pzdYW+Ve{d*ofrRQ16^+WXE>#fs&x8wF&?M|x=`fs`I)(*0@{-2Nj zB@uEWW%Bg;cN}o`!v9;Y>w^A4s;Bk84GN=#afxzmTR!8&7;zR&3lf@+!&q2K^Z7d} zYP|dW`Sdg^sZ?O8Oj2oKO1Omgsq~ThKFN57;ZrOG$}KN%qA_o+**6eSKt^Z^ISoPR zs3=z?(uD9v)0**T97QpX$iRI24Mzzj*)Yxhioh@#4NU1L2*&|xWW)Q-MvSB4wen%x z&06(*hJ(_K8Wax+9eAGV+Vh$-@uo4Gi&{W$0zE>tY(D$QXK}obIQcgP*HSMcVX+{k zi55H(c%dW_8X)uL7Tw$)-rSnji17%^Mj>KFL{3;RYtEVw91t$fcPC89-HSOR<>7pQ zY9Q7Xht?a_zV^}Ho*JJO#v|5fHcLa2DUX+p-PqCevgls;{{ZaYWdHBBdvpBnX8XU> z>uCJ{LHJ)SssZ{!^e)x5lmQVr!}2Eqb7gyrQF!qntrg(BzX+X^Y|u4)&I`*!oulR6 zUd~;Hk2%-)iTt1B8|p(KV2%HG9J@RB|5iu&e^1B%&m#VNU^rI>gx3%%5MPEYe$oI> zVFH3EZb@)gD-MY8d6=kC49wRojio?xLQtGWL&6aoAsI$Qpj{Yqw2N?(5X=RFa2IE> zPCkKJqm;$tr)e0a0(=Zb5UXWXpn*{uXDos6B@O|^Aefb`SmxS5a01CGX9q!^X)zn&2PYwmH1w<}P9CC+A$Th2_@hc1+er35U>t}=wlrra3jvh!VB z^6P%ZbXE`k*8%b?;*~5(^*ZB{Z$3#R`arJVa?W^vLA8a-T%*TR9!`-bTl{QZCH_fF zugjyFx>=@HFfV_S)%BI@D-Nd1*CHI{%TWRYl`yYfqF2c7-*L}Kj8#%QA2DFcZPntJ zHQ2n%ZG`b^f;%s-^iF$~FFP;{RtSUp~Eld$x)9Z}9)u?biL@?zFZ4Z-WFx zwdzdQSgr5V4}ToIKmPs1*w`%ANCqS!aX@1K+M{9oRcugIX82~(NQ2IA^)D&%An z(aLUStho7LEdMKNEIBYSp70?3`S^c%aUbpfz^(g#x1-O0wy1x-59G*#;^e2&6oroO#MYsrA+((XO z8^<^zeYD6njF}u5iE)-j5$4x@bcB3HY4J~+jf$$MxITzdL4y2Psb~u&DNmRn!g$9b za**IL^rxa?(LX#KhjNk*)v3VYm$M@tU4J5iVD3*o;$dNz#!+_U*++K-3eEwEa7clF z{NecI?_=X*=#yBGdBL0c!R@^8lwzq)ALb?6|2N9T9_9Z|ub%(+I$c})|2F8nNKXq- zy)cT577b7>akUDLp%Pec0bi9H)9iK$U$G1wbG!impZ*wnfh+-9ah;y4 z{eK&joj+%~mW)v`z2G$p7GzLaoblob\_handler, rawHandler->raw\_handler, connectionInitHandler->connection\_init\_handler, etc. +* All plugins are now chainable + * To accommodate this, handler functions in plugins must now use return statements indicating whether a packet, connection, or similar will continue to the next plugin. The type of object(s) to return depends on the type of handler, but will generally match the types of the handler's input. Dshell will display a warning if it's not the right type. +* Plugins can now use all output modules\* available to the command line switch, -O + * That does not mean every output module will be _useful_ to every plugin (e.g. using netflow output for a plugin that looks at individual packets), but they are available. + * alert(), write(), and dump() are now the same function: write() + * Output modules can be listed with a new flag in decode.py, --list-output or --lo + * Arguments for output modules are now passed with the --oargs command-line argument + * \* pcapout is (currently) the exception to this rule. A method has yet to arise that allows it to work with connection-based plugins +* No more dObj declaration + * decode.py just looks for the class named DshellPlugin and creates an instance of that +* Improved error handling + * Dshell handles more of the most common exceptions during everyday use +* Enables development of external plugin packs, allowing the sharing and installation of new, externally-developed plugins without overlapping the core Dshell libraries. + +## Installation + +1. Install Dshell with pip + * `sudo python3 -m pip install Dshell/` OR `sudo python3 -m pip install ` +2. Configure geoip2 by moving the MaxMind data files (GeoLite2-ASN.mmdb, GeoLite2-City.mmdb, GeoLite2-Country.mmdb) to <install-location>/data/GeoIP/ +3. Run `dshell`. This should drop you into a `Dshell> ` prompt. + +## Basic Usage + +* `decode -l` + * This will list all available plugins, alongside basic information about them +* `decode -h` + * Show generic command-line flags available to most plugins +* `decode -p ` + * Display information about a plugin, including available command line flags +* `decode -p ` + * Run the selected plugin on a pcap file +* `decode -p + ` + * Chain two (or more) plugins together and run them on a pcap file +* `decode -p -i ` + * Run the selected plugin live on an interface (may require superuser privileges) + +## Usage Examples +Showing DNS lookups in [sample traffic](http://wiki.wireshark.org/SampleCaptures#General_.2F_Unsorted) + +``` +Dshell> decode -p dns ~/pcap/dns.cap |sort +[DNS] 2005-03-30 03:47:46 192.168.170.8:32795 -- 192.168.170.20:53 ** ID: 4146, TXT? google.com., TXT: b'\x0fv=spf1 ptr ?all' ** +[DNS] 2005-03-30 03:47:50 192.168.170.8:32795 -- 192.168.170.20:53 ** ID: 63343, MX? google.com., MX: b'\x00(\x05smtp4\xc0\x0c', MX: b'\x00\n\x05smtp5\xc0\x0c', MX: b'\x00\n\x05smtp6\xc0\x0c', MX: b'\x00\n\x05smtp1\xc0\x0c', MX: b'\x00\n\x05smtp2\xc0\x0c', MX: b'\x00(\x05smtp3\xc0\x0c' ** +[DNS] 2005-03-30 03:47:59 192.168.170.8:32795 -- 192.168.170.20:53 ** ID: 18849, LOC? google.com. ** +[DNS] 2005-03-30 03:48:07 192.168.170.8:32795 -- 192.168.170.20:53 ** ID: 39867, PTR? 104.9.192.66.in-addr.arpa., PTR: 66-192-9-104.gen.twtelecom.net. ** +[DNS] 2005-03-30 03:49:18 192.168.170.8:32795 -- 192.168.170.20:53 ** ID: 30144, A? www.netbsd.org., A: 204.152.190.12 (ttl 82159s) ** +[DNS] 2005-03-30 03:49:35 192.168.170.8:32795 -- 192.168.170.20:53 ** ID: 61652, AAAA? www.netbsd.org., AAAA: 2001:4f8:4:7:2e0:81ff:fe52:9a6b (ttl 86400s) ** +[DNS] 2005-03-30 03:50:35 192.168.170.8:32795 -- 192.168.170.20:53 ** ID: 32569, AAAA? www.netbsd.org., AAAA: 2001:4f8:4:7:2e0:81ff:fe52:9a6b (ttl 86340s) ** +[DNS] 2005-03-30 03:50:44 192.168.170.8:32795 -- 192.168.170.20:53 ** ID: 36275, AAAA? www.google.com., CNAME: 'www.l.google.com.' ** +[DNS] 2005-03-30 03:50:54 192.168.170.8:32795 -- 192.168.170.20:53 ** ID: 56482, AAAA? www.l.google.com. ** +[DNS] 2005-03-30 03:51:35 192.168.170.8:32795 -- 192.168.170.20:53 ** ID: 48159, AAAA? www.example.com. ** +[DNS] 2005-03-30 03:51:46 192.168.170.8:32795 -- 192.168.170.20:53 ** ID: 9837, AAAA? www.example.notginh., NXDOMAIN ** +[DNS] 2005-03-30 03:52:17 192.168.170.8:32795 -- 192.168.170.20:53 ** ID: 65251, AAAA: 2001:4f8:0:2::d (ttl 600s), A: 204.152.184.88 (ttl 600s) ** +[DNS] 2005-03-30 03:52:17 192.168.170.8:32796 -- 192.168.170.20:53 ** ID: 23123, PTR? 1.0.0.127.in-addr.arpa., PTR: localhost. ** +[DNS] 2005-03-30 03:52:17 192.168.170.8:32797 -- 192.168.170.20:53 ** ID: 8330, NS: b'\x06ns-ext\x04nrt1\xc0\x0c', NS: b'\x06ns-ext\x04sth1\xc0\x0c', NS: b'\x06ns-ext\xc0\x0c', NS: b'\x06ns-ext\x04lga1\xc0\x0c' ** +[DNS] 2005-03-30 03:52:17 192.168.170.56:1707 -- 217.13.4.24:53 ** ID: 12910, SRV? _ldap._tcp.Default-First-Site-Name._sites.dc._msdcs.utelsystems.local., NXDOMAIN ** +[DNS] 2005-03-30 03:52:17 192.168.170.56:1708 -- 217.13.4.24:53 ** ID: 61793, SRV? _ldap._tcp.dc._msdcs.utelsystems.local., NXDOMAIN ** +[DNS] 2005-03-30 03:52:17 192.168.170.56:1709 -- 217.13.4.24:53 ** ID: 33633, SRV? _ldap._tcp.05b5292b-34b8-4fb7-85a3-8beef5fd2069.domains._msdcs.utelsystems.local., NXDOMAIN ** +[DNS] 2005-03-30 03:52:17 192.168.170.56:1710 -- 217.13.4.24:53 ** ID: 53344, A? GRIMM.utelsystems.local., NXDOMAIN ** +[DNS] 2005-03-30 03:52:25 192.168.170.56:1711 -- 217.13.4.24:53 ** ID: 30307, A? GRIMM.utelsystems.local., NXDOMAIN ** +``` + +Following and reassembling a stream in [sample traffic](http://wiki.wireshark.org/SampleCaptures#General_.2F_Unsorted) + +``` +Dshell> decode -p followstream ~/pcap/v6-http.cap +Connection 1 (TCP) +Start: 2007-08-05 15:16:44.189851 +End: 2007-08-05 15:16:44.219460 +2001:6f8:102d:0:2d0:9ff:fee3:e8de: 59201 -> 2001:6f8:900:7c0::2: 80 (300 bytes) +2001:6f8:900:7c0::2: 80 -> 2001:6f8:102d:0:2d0:9ff:fee3:e8de: 59201 (2379 bytes) + +GET / HTTP/1.0 +Host: cl-1985.ham-01.de.sixxs.net +Accept: text/html, text/plain, text/css, text/sgml, */*;q=0.01 +Accept-Encoding: gzip, bzip2 +Accept-Language: en +User-Agent: Lynx/2.8.6rel.2 libwww-FM/2.14 SSL-MM/1.4.1 OpenSSL/0.9.8b + + + +HTTP/1.1 200 OK +Date: Sun, 05 Aug 2007 19:16:44 GMT +Server: Apache +Content-Length: 2121 +Connection: close +Content-Type: text/html + + + + + Index of / + + +

    Index of /

    +
    + +``` + +Chaining plugins to view flow data for a specific country code in [sample traffic](http://wiki.wireshark.org/SampleCaptures#General_.2F_Unsorted) (note: TCP handshakes are not included in the packet count) + +``` +Dshell> decode -p country+netflow --country_code=JP ~/pcap/SkypeIRC.cap +2006-08-25 15:32:20.766761 192.168.1.2 -> 202.232.205.123 (-- -> JP) UDP 60583 33438 1 0 64 0 0.0000s +2006-08-25 15:32:20.634046 192.168.1.2 -> 202.232.205.123 (-- -> JP) UDP 60583 33435 1 0 64 0 0.0000s +2006-08-25 15:32:20.747503 192.168.1.2 -> 202.232.205.123 (-- -> JP) UDP 60583 33437 1 0 64 0 0.0000s +2006-08-25 15:32:20.651501 192.168.1.2 -> 202.232.205.123 (-- -> JP) UDP 60583 33436 1 0 64 0 0.0000s +``` + +Collecting DNS traffic from several files and storing it in a new pcap file. + +``` +Dshell> decode -p dns+pcapwriter --pcapwriter_outfile=test.pcap ~/pcap/*.cap >/dev/null +Dshell> tcpdump -nnr test.pcap |head +reading from file test.pcap, link-type EN10MB (Ethernet) +15:36:08.670569 IP 192.168.1.2.2131 > 192.168.1.1.53: 40209+ A? ui.skype.com. (30) +15:36:08.670687 IP 192.168.1.2.2131 > 192.168.1.1.53: 40210+ AAAA? ui.skype.com. (30) +15:36:08.674022 IP 192.168.1.1.53 > 192.168.1.2.2131: 40209- 1/0/0 A 212.72.49.131 (46) +15:36:09.011208 IP 192.168.1.1.53 > 192.168.1.2.2131: 40210 0/1/0 (94) +15:36:10.171350 IP 192.168.1.2.2131 > 192.168.1.1.53: 40210+ AAAA? ui.skype.com. (30) +15:36:10.961350 IP 192.168.1.1.53 > 192.168.1.2.2131: 40210* 0/1/0 (85) +15:36:10.961608 IP 192.168.1.2.2131 > 192.168.1.1.53: 40211+ AAAA? ui.skype.com. (30) +15:36:11.294333 IP 192.168.1.1.53 > 192.168.1.2.2131: 40211 0/1/0 (94) +15:32:21.664798 IP 192.168.1.2.2130 > 192.168.1.1.53: 39862+ A? ui.skype.com. (30) +15:32:21.664913 IP 192.168.1.2.2130 > 192.168.1.1.53: 39863+ AAAA? ui.skype.com. (30) +``` + +Collecting TFTP data and converting alerts to JSON format using [sample traffic](https://wiki.wireshark.org/SampleCaptures#TFTP) + +``` +Dshell> decode -p tftp -O jsonout ~/pcap/tftp_*.pcap +{"dport": 3445, "dip": "192.168.0.10", "data": "read rfc1350.txt (24599 bytes) ", "sport": 50618, "readwrite": "read", "sip": "192.168.0.253", "plugin": "tftp", "ts": 1367411051.972852, "filename": "rfc1350.txt"} +{"dport": 2087, "dip": "192.168.0.13", "data": "write rfc1350.txt (24599 bytes) ", "sport": 57509, "readwrite": "write", "sip": "192.168.0.1", "plugin": "tftp", "ts": 1367053679.45274, "filename": "rfc1350.txt"} +``` + +Running a plugin within a separate Python script using [sample traffic](https://wiki.wireshark.org/SampleCaptures#TFTP) + +``` +# Import required Dshell libraries +import dshell.decode as decode +import dshell.plugins.tftp.tftp as tftp + +# Instantiate plugin +plugin = tftp.DshellPlugin() +# Define plugin-specific arguments, if needed +dargs = {plugin: {"outdir": "/tmp/"}} +# Add plugin(s) to plugin chain +decode.plugin_chain = [plugin] +# Run decode main function with all other arguments +decode.main( + debug=True, + files=["/home/user/pcap/tftp_rrq.pcap", "/home/user/pcap/tftp_wrq.pcap"], + plugin_args=dargs +) +``` diff --git a/README.md b/README.md index d7014eb..3c1feea 100644 --- a/README.md +++ b/README.md @@ -1,102 +1,112 @@ # Dshell -**_A new version of Dshell for Python 3 is coming in September 2020, Dshell 3. See ‘News’ section for additional information._** - An extensible network forensic analysis framework. Enables rapid development of plugins to support the dissection of network packet captures. Key features: - - +* Deep packet analysis using specialized plugins * Robust stream reassembly * IPv4 and IPv6 support * Custom output handlers -* Chainable decoders - -## Prerequisites - -* Linux (developed on Ubuntu 12.04) -* Python 2.7 -* [geoip2](https://github.com/maxmind/GeoIP2-python), Apache License, Version 2.0 - * [MaxMind GeoIP datasets](https://dev.maxmind.com/geoip/geoip2/geolite2/) -* [PyCrypto](https://pypi.python.org/pypi/pycrypto), custom license -* [dpkt](https://code.google.com/p/dpkt/), New BSD License -* [IPy](https://github.com/haypo/python-ipy), BSD 2-Clause License -* [pypcap](https://code.google.com/p/pypcap/), New BSD License -* [elasticsearch-py](https://www.elastic.co/guide/en/elasticsearch/client/python-api/current/index.html), Apache License, Version 2.0 - optional, used only with Dshell's elasticout output module +* Chainable plugins + +## Requirements +* Linux (developed on Red Hat Enterprise Linux 6.7) +* Python 3 (developed with Python 3.5.1) +* [pypacker](https://github.com/mike01/pypacker) +* [pcapy](http://www.coresecurity.com/corelabs-research/open-source-tools/pcapy) +* [geoip2](https://github.com/maxmind/GeoIP2-python) + * [MaxMind GeoIP2 datasets](https://dev.maxmind.com/geoip/geoip2/geolite2/) + +## Optional +* [oui.txt](http://standards-oui.ieee.org/oui.txt) + * used by some plugins that handle MAC addresses + * place in <dshell>/data/ +* [elasticsearch](https://www.elastic.co/guide/en/elasticsearch/client/python-api/current/index.html) + * used in the elasticout output module + * only necessary if planning to use elasticsearch to store output + +## Major Changes Since Previous Release +* This is a major framework update to Dshell. Plugins written for the previous version are not compatible with this version, and vice versa. +* Uses Python 3 + * Rewritten in Python 3 from the ground up. Python 2 language deprecated on [1 JAN 2020](https://www.python.org/doc/sunset-python-2/) + * By extension, dpkt and pypcap have been replaced with Python3-friendly pypacker and pcapy (respectively). +* Is a Python package + * Converted into a single package, removing the need for the shell to set several environment variables. + * Allows easier use of Dshell plugins in other Python scripts +* Changed "decoders" to "plugins" + * Primarily a word-swap, to clarify that "decoders" can do more than simply decode traffic, and to put Dshell more in line with the terminology of other frameworks. +* Significant reduction in camelCase functions, replaced with more Pythonic snake\_case functions. + * Notable examples include blobHandler->blob\_handler, rawHandler->raw\_handler, connectionInitHandler->connection\_init\_handler, etc. +* All plugins are now chainable + * To accommodate this, handler functions in plugins must now use return statements indicating whether a packet, connection, or similar will continue to the next plugin. The type of object(s) to return depends on the type of handler, but will generally match the types of the handler's input. Dshell will display a warning if it's not the right type. +* Plugins can now use all output modules\* available to the command line switch, -O + * That does not mean every output module will be _useful_ to every plugin (e.g. using netflow output for a plugin that looks at individual packets), but they are available. + * alert(), write(), and dump() are now the same function: write() + * Output modules can be listed with a new flag in decode.py, --list-output or --lo + * Arguments for output modules are now passed with the --oargs command-line argument + * \* pcapout is (currently) the exception to this rule. A method has yet to arise that allows it to work with connection-based plugins +* No more dObj declaration + * decode.py just looks for the class named DshellPlugin and creates an instance of that +* Improved error handling + * Dshell handles more of the most common exceptions during everyday use +* Enables development of external plugin packs, allowing the sharing and installation of new, externally-developed plugins without overlapping the core Dshell libraries. ## Installation -1. Install all of the necessary Python modules listed above. Many of them are available via pip and/or apt-get. - - * `sudo pip install geoip2 pycrypto dpkt IPy pypcap` - -2. Configure GeoIP by moving the MaxMind data files (GeoLite2-Country.mmdb, GeoLite2-ASN.mmdb) to <install-location>/share/GeoIP/ +1. Install Dshell with pip + * `sudo python3 -m pip install Dshell/` OR `sudo python3 -m pip install ` +2. Configure geoip2 by moving the MaxMind data files (GeoLite2-ASN.mmdb, GeoLite2-City.mmdb, GeoLite2-Country.mmdb) to <install-location>/data/GeoIP/ +3. Run `dshell`. This should drop you into a `Dshell> ` prompt. -2. Run `make`. This will build Dshell. - -3. Run `./dshell`. This is Dshell. If you get a Dshell> prompt, you're good to go! - -## Basic usage +## Basic Usage * `decode -l` - * This will list all available decoders alongside basic information about them + * This will list all available plugins, alongside basic information about them * `decode -h` - * Show generic command-line flags available to most decoders -* `decode -d ` - * Display information about a decoder, including available command-line flags -* `decode -d ` - * Run the selected decoder on a pcap file - -## Development -* [Using Dshell With PyCharm](doc/UsingDshellWithPyCharm.md) - -## News - -* Sep 2020 - A new version of Dshell for Python 3 is coming, Dshell 3. - * This is a major framework update to Dshell. Plugins written for the previous version are not compatible with this version, and vice versa. - * Uses Python 3 - * Rewritten in Python 3 from the ground up. Python 2 language deprecated on [1 JAN 2020](https://www.python.org/doc/sunset-python-2/) - * By extension, dpkt and pypcap have been replaced with Python 3-friendly pypacker and pcapy (respectively). - * Is a Python package - * All plugins are chainable - * Plugins can use all output modules - * Improved error handling - * Enables development of external plugin packs, allowing the sharing and installation of new, externally-developed plugins without overlapping the core Dshell libraries. -* Sep 2020 - This Python 2 version of Dshell will be deprecated and tagged with its current version number after Dshell 3 is released. It will still be available via this repository. Issues and Pull requests for the previous version will be closed when the new version is released. -* Feb 2019 - Removed deprecated pygeoip dependency, and replaced it with geoip2. This requires the use of new GeoIP data files, listed in the Prerequisites and Installation sections above. - -## Partners - -Below are repositories from partners Dshell has worked together with. - -* [DeKrych/Dshell-plugins](https://github.com/DeKrych/Dshell-plugins) -* [terry-wen/Network-Visualization-Project](https://github.com/terry-wen/Network-Visualization-Project) + * Show generic command-line flags available to most plugins +* `decode -p ` + * Display information about a plugin, including available command line flags +* `decode -p ` + * Run the selected plugin on a pcap file +* `decode -p + ` + * Chain two (or more) plugins together and run them on a pcap file +* `decode -p -i ` + * Run the selected plugin live on an interface (may require superuser privileges) ## Usage Examples - Showing DNS lookups in [sample traffic](http://wiki.wireshark.org/SampleCaptures#General_.2F_Unsorted) ``` -Dshell> decode -d dns ~/pcap/dns.cap -dns 2005-03-30 03:47:46 192.168.170.8:32795 -> 192.168.170.20:53 ** 39867 PTR? 66.192.9.104 / PTR: 66-192-9-104.gen.twtelecom.net ** -dns 2005-03-30 03:47:46 192.168.170.8:32795 -> 192.168.170.20:53 ** 30144 A? www.netbsd.org / A: 204.152.190.12 (ttl 82159s) ** -dns 2005-03-30 03:47:46 192.168.170.8:32795 -> 192.168.170.20:53 ** 61652 AAAA? www.netbsd.org / AAAA: 2001:4f8:4:7:2e0:81ff:fe52:9a6b (ttl 86400s) ** -dns 2005-03-30 03:47:46 192.168.170.8:32795 -> 192.168.170.20:53 ** 32569 AAAA? www.netbsd.org / AAAA: 2001:4f8:4:7:2e0:81ff:fe52:9a6b (ttl 86340s) ** -dns 2005-03-30 03:47:46 192.168.170.8:32795 -> 192.168.170.20:53 ** 36275 AAAA? www.google.com / CNAME: www.l.google.com ** -dns 2005-03-30 03:47:46 192.168.170.8:32795 -> 192.168.170.20:53 ** 9837 AAAA? www.example.notginh / NXDOMAIN ** -dns 2005-03-30 03:52:17 192.168.170.8:32796 <- 192.168.170.20:53 ** 23123 PTR? 127.0.0.1 / PTR: localhost ** -dns 2005-03-30 03:52:25 192.168.170.56:1711 <- 217.13.4.24:53 ** 30307 A? GRIMM.utelsystems.local / NXDOMAIN ** -dns 2005-03-30 03:52:17 192.168.170.56:1710 <- 217.13.4.24:53 ** 53344 A? GRIMM.utelsystems.local / NXDOMAIN ** +Dshell> decode -p dns ~/pcap/dns.cap |sort +[DNS] 2005-03-30 03:47:46 192.168.170.8:32795 -- 192.168.170.20:53 ** ID: 4146, TXT? google.com., TXT: b'\x0fv=spf1 ptr ?all' ** +[DNS] 2005-03-30 03:47:50 192.168.170.8:32795 -- 192.168.170.20:53 ** ID: 63343, MX? google.com., MX: b'\x00(\x05smtp4\xc0\x0c', MX: b'\x00\n\x05smtp5\xc0\x0c', MX: b'\x00\n\x05smtp6\xc0\x0c', MX: b'\x00\n\x05smtp1\xc0\x0c', MX: b'\x00\n\x05smtp2\xc0\x0c', MX: b'\x00(\x05smtp3\xc0\x0c' ** +[DNS] 2005-03-30 03:47:59 192.168.170.8:32795 -- 192.168.170.20:53 ** ID: 18849, LOC? google.com. ** +[DNS] 2005-03-30 03:48:07 192.168.170.8:32795 -- 192.168.170.20:53 ** ID: 39867, PTR? 104.9.192.66.in-addr.arpa., PTR: 66-192-9-104.gen.twtelecom.net. ** +[DNS] 2005-03-30 03:49:18 192.168.170.8:32795 -- 192.168.170.20:53 ** ID: 30144, A? www.netbsd.org., A: 204.152.190.12 (ttl 82159s) ** +[DNS] 2005-03-30 03:49:35 192.168.170.8:32795 -- 192.168.170.20:53 ** ID: 61652, AAAA? www.netbsd.org., AAAA: 2001:4f8:4:7:2e0:81ff:fe52:9a6b (ttl 86400s) ** +[DNS] 2005-03-30 03:50:35 192.168.170.8:32795 -- 192.168.170.20:53 ** ID: 32569, AAAA? www.netbsd.org., AAAA: 2001:4f8:4:7:2e0:81ff:fe52:9a6b (ttl 86340s) ** +[DNS] 2005-03-30 03:50:44 192.168.170.8:32795 -- 192.168.170.20:53 ** ID: 36275, AAAA? www.google.com., CNAME: 'www.l.google.com.' ** +[DNS] 2005-03-30 03:50:54 192.168.170.8:32795 -- 192.168.170.20:53 ** ID: 56482, AAAA? www.l.google.com. ** +[DNS] 2005-03-30 03:51:35 192.168.170.8:32795 -- 192.168.170.20:53 ** ID: 48159, AAAA? www.example.com. ** +[DNS] 2005-03-30 03:51:46 192.168.170.8:32795 -- 192.168.170.20:53 ** ID: 9837, AAAA? www.example.notginh., NXDOMAIN ** +[DNS] 2005-03-30 03:52:17 192.168.170.8:32795 -- 192.168.170.20:53 ** ID: 65251, AAAA: 2001:4f8:0:2::d (ttl 600s), A: 204.152.184.88 (ttl 600s) ** +[DNS] 2005-03-30 03:52:17 192.168.170.8:32796 -- 192.168.170.20:53 ** ID: 23123, PTR? 1.0.0.127.in-addr.arpa., PTR: localhost. ** +[DNS] 2005-03-30 03:52:17 192.168.170.8:32797 -- 192.168.170.20:53 ** ID: 8330, NS: b'\x06ns-ext\x04nrt1\xc0\x0c', NS: b'\x06ns-ext\x04sth1\xc0\x0c', NS: b'\x06ns-ext\xc0\x0c', NS: b'\x06ns-ext\x04lga1\xc0\x0c' ** +[DNS] 2005-03-30 03:52:17 192.168.170.56:1707 -- 217.13.4.24:53 ** ID: 12910, SRV? _ldap._tcp.Default-First-Site-Name._sites.dc._msdcs.utelsystems.local., NXDOMAIN ** +[DNS] 2005-03-30 03:52:17 192.168.170.56:1708 -- 217.13.4.24:53 ** ID: 61793, SRV? _ldap._tcp.dc._msdcs.utelsystems.local., NXDOMAIN ** +[DNS] 2005-03-30 03:52:17 192.168.170.56:1709 -- 217.13.4.24:53 ** ID: 33633, SRV? _ldap._tcp.05b5292b-34b8-4fb7-85a3-8beef5fd2069.domains._msdcs.utelsystems.local., NXDOMAIN ** +[DNS] 2005-03-30 03:52:17 192.168.170.56:1710 -- 217.13.4.24:53 ** ID: 53344, A? GRIMM.utelsystems.local., NXDOMAIN ** +[DNS] 2005-03-30 03:52:25 192.168.170.56:1711 -- 217.13.4.24:53 ** ID: 30307, A? GRIMM.utelsystems.local., NXDOMAIN ** ``` Following and reassembling a stream in [sample traffic](http://wiki.wireshark.org/SampleCaptures#General_.2F_Unsorted) ``` -Dshell> decode -d followstream ~/pcap/v6-http.cap +Dshell> decode -p followstream ~/pcap/v6-http.cap Connection 1 (TCP) -Start: 2007-08-05 19:16:44.189852 UTC - End: 2007-08-05 19:16:44.204687 UTC -2001:6f8:102d:0:2d0:9ff:fee3:e8de:59201 -> 2001:6f8:900:7c0::2:80 (240 bytes) -2001:6f8:900:7c0::2:80 -> 2001:6f8:102d:0:2d0:9ff:fee3:e8de:59201 (2259 bytes) +Start: 2007-08-05 15:16:44.189851 +End: 2007-08-05 15:16:44.219460 +2001:6f8:102d:0:2d0:9ff:fee3:e8de: 59201 -> 2001:6f8:900:7c0::2: 80 (300 bytes) +2001:6f8:900:7c0::2: 80 -> 2001:6f8:102d:0:2d0:9ff:fee3:e8de: 59201 (2379 bytes) GET / HTTP/1.0 Host: cl-1985.ham-01.de.sixxs.net @@ -105,6 +115,8 @@ Accept-Encoding: gzip, bzip2 Accept-Language: en User-Agent: Lynx/2.8.6rel.2 libwww-FM/2.14 SSL-MM/1.4.1 OpenSSL/0.9.8b + + HTTP/1.1 200 OK Date: Sun, 05 Aug 2007 19:16:44 GMT Server: Apache @@ -137,31 +149,59 @@ Content-Type: text/html ``` -Chaining decoders to view flow data for a specific country code in [sample traffic](http://wiki.wireshark.org/SampleCaptures#General_.2F_Unsorted) (note: TCP handshakes are not included in the packet count) +Chaining plugins to view flow data for a specific country code in [sample traffic](http://wiki.wireshark.org/SampleCaptures#General_.2F_Unsorted) (note: TCP handshakes are not included in the packet count) + +``` +Dshell> decode -p country+netflow --country_code=JP ~/pcap/SkypeIRC.cap +2006-08-25 15:32:20.766761 192.168.1.2 -> 202.232.205.123 (-- -> JP) UDP 60583 33438 1 0 64 0 0.0000s +2006-08-25 15:32:20.634046 192.168.1.2 -> 202.232.205.123 (-- -> JP) UDP 60583 33435 1 0 64 0 0.0000s +2006-08-25 15:32:20.747503 192.168.1.2 -> 202.232.205.123 (-- -> JP) UDP 60583 33437 1 0 64 0 0.0000s +2006-08-25 15:32:20.651501 192.168.1.2 -> 202.232.205.123 (-- -> JP) UDP 60583 33436 1 0 64 0 0.0000s +``` + +Collecting DNS traffic from several files and storing it in a new pcap file. + +``` +Dshell> decode -p dns+pcapwriter --pcapwriter_outfile=test.pcap ~/pcap/*.cap >/dev/null +Dshell> tcpdump -nnr test.pcap |head +reading from file test.pcap, link-type EN10MB (Ethernet) +15:36:08.670569 IP 192.168.1.2.2131 > 192.168.1.1.53: 40209+ A? ui.skype.com. (30) +15:36:08.670687 IP 192.168.1.2.2131 > 192.168.1.1.53: 40210+ AAAA? ui.skype.com. (30) +15:36:08.674022 IP 192.168.1.1.53 > 192.168.1.2.2131: 40209- 1/0/0 A 212.72.49.131 (46) +15:36:09.011208 IP 192.168.1.1.53 > 192.168.1.2.2131: 40210 0/1/0 (94) +15:36:10.171350 IP 192.168.1.2.2131 > 192.168.1.1.53: 40210+ AAAA? ui.skype.com. (30) +15:36:10.961350 IP 192.168.1.1.53 > 192.168.1.2.2131: 40210* 0/1/0 (85) +15:36:10.961608 IP 192.168.1.2.2131 > 192.168.1.1.53: 40211+ AAAA? ui.skype.com. (30) +15:36:11.294333 IP 192.168.1.1.53 > 192.168.1.2.2131: 40211 0/1/0 (94) +15:32:21.664798 IP 192.168.1.2.2130 > 192.168.1.1.53: 39862+ A? ui.skype.com. (30) +15:32:21.664913 IP 192.168.1.2.2130 > 192.168.1.1.53: 39863+ AAAA? ui.skype.com. (30) +``` + +Collecting TFTP data and converting alerts to JSON format using [sample traffic](https://wiki.wireshark.org/SampleCaptures#TFTP) ``` -Dshell> decode -d country+netflow --country_code=JP ~/pcap/SkypeIRC.cap -2006-08-25 19:32:20.651502 192.168.1.2 -> 202.232.205.123 (-- -> JP) UDP 60583 33436 1 0 36 0 0.0000s -2006-08-25 19:32:20.766761 192.168.1.2 -> 202.232.205.123 (-- -> JP) UDP 60583 33438 1 0 36 0 0.0000s -2006-08-25 19:32:20.634046 192.168.1.2 -> 202.232.205.123 (-- -> JP) UDP 60583 33435 1 0 36 0 0.0000s -2006-08-25 19:32:20.747503 192.168.1.2 -> 202.232.205.123 (-- -> JP) UDP 60583 33437 1 0 36 0 0.0000s +Dshell> decode -p tftp -O jsonout ~/pcap/tftp_*.pcap +{"dport": 3445, "dip": "192.168.0.10", "data": "read rfc1350.txt (24599 bytes) ", "sport": 50618, "readwrite": "read", "sip": "192.168.0.253", "plugin": "tftp", "ts": 1367411051.972852, "filename": "rfc1350.txt"} +{"dport": 2087, "dip": "192.168.0.13", "data": "write rfc1350.txt (24599 bytes) ", "sport": 57509, "readwrite": "write", "sip": "192.168.0.1", "plugin": "tftp", "ts": 1367053679.45274, "filename": "rfc1350.txt"} ``` -Collecting netflow data for [sample traffic](http://wiki.wireshark.org/SampleCaptures#General_.2F_Unsorted) with vlan headers, then tracking the connection to a specific IP address +Running a plugin within a separate Python script using [sample traffic](https://wiki.wireshark.org/SampleCaptures#TFTP) ``` -Dshell> decode -d netflow ~/pcap/vlan.cap -1999-11-05 18:20:43.170500 131.151.20.254 -> 255.255.255.255 (US -> --) UDP 520 520 1 0 24 0 0.0000s -1999-11-05 18:20:42.063074 131.151.32.71 -> 131.151.32.255 (US -> US) UDP 138 138 1 0 201 0 0.0000s -1999-11-05 18:20:43.096540 131.151.1.254 -> 255.255.255.255 (US -> --) UDP 520 520 1 0 24 0 0.0000s -1999-11-05 18:20:43.079765 131.151.5.254 -> 255.255.255.255 (US -> --) UDP 520 520 1 0 24 0 0.0000s -1999-11-05 18:20:41.521798 131.151.104.96 -> 131.151.107.255 (US -> US) UDP 137 137 3 0 150 0 1.5020s -1999-11-05 18:20:43.087010 131.151.6.254 -> 255.255.255.255 (US -> --) UDP 520 520 1 0 24 0 0.0000s -1999-11-05 18:20:43.368210 131.151.111.254 -> 255.255.255.255 (US -> --) UDP 520 520 1 0 24 0 0.0000s -1999-11-05 18:20:43.250410 131.151.32.254 -> 255.255.255.255 (US -> --) UDP 520 520 1 0 24 0 0.0000s -1999-11-05 18:20:43.115330 131.151.10.254 -> 255.255.255.255 (US -> --) UDP 520 520 1 0 24 0 0.0000s -1999-11-05 18:20:43.375145 131.151.115.254 -> 255.255.255.255 (US -> --) UDP 520 520 1 0 24 0 0.0000s -1999-11-05 18:20:43.363348 131.151.107.254 -> 255.255.255.255 (US -> --) UDP 520 520 1 0 24 0 0.0000s -1999-11-05 18:20:40.112031 131.151.5.55 -> 131.151.5.255 (US -> US) UDP 138 138 1 0 201 0 0.0000s -1999-11-05 18:20:43.183825 131.151.32.79 -> 131.151.32.255 (US -> US) UDP 138 138 1 0 201 0 0.0000s +# Import required Dshell libraries +import dshell.decode as decode +import dshell.plugins.tftp.tftp as tftp + +# Instantiate plugin +plugin = tftp.DshellPlugin() +# Define plugin-specific arguments, if needed +dargs = {plugin: {"outdir": "/tmp/"}} +# Add plugin(s) to plugin chain +decode.plugin_chain = [plugin] +# Run decode main function with all other arguments +decode.main( + debug=True, + files=["/home/user/pcap/tftp_rrq.pcap", "/home/user/pcap/tftp_wrq.pcap"], + plugin_args=dargs +) ``` diff --git a/bin/decode.py b/bin/decode.py deleted file mode 100755 index 86d26c3..0000000 --- a/bin/decode.py +++ /dev/null @@ -1,964 +0,0 @@ -#!/usr/bin/env python - -# pylint: disable-msg=C0103,E501 - -import copy -import dshell -import glob -import gzip -import logging -import optparse -import os -import output -import sys -import tempfile -import traceback -import util -import zipfile -try: - import pcap -except ImportError: - pcap = None - print 'pcap not available: decoders requiring pcap are not usable' - - -def import_module(name=None, silent=False, search=None): - if search is None: - search = {} - try: - # we will first check search[name] for the module - # else split foo.bar:baz to get from foo.bar import baz - # else split dotted path to perform a 'from foo import bar' operation - try: - module = search[name] # a -> from search[a] import a - except KeyError: - # a.b.c from a.b import c - module, name = name.split('.')[:-1], name.split('.')[-1] - if module: - module = '.'.join(module) - else: - module = name - path = None - if os.path.sep in module: # was a full path to a decoder given? - path, module = os.path.dirname(module), os.path.basename(module) - # print module,name - if path: - sys.path.append(path) - obj = __import__(module, fromlist=[name]) - if path: - sys.path.remove(path) - if 'dObj' in dir(obj) or 'obj' in dir(obj): - return obj - elif name in dir(obj): - obj = getattr(obj, name) - if 'dObj' in dir(obj) or 'obj' in dir(obj): - return obj - except Exception as err: - if not silent: - sys.stderr.write( - "Error '%s' loading module %s\n" % (str(err), module)) - return False - - -def setDecoderPath(decoder_path): - '''set the base decoder path, - add it to sys.path for importing, - and walk it to return all subpaths''' - paths = [] - paths.append(decoder_path) # append base path first - # walk decoder directories an add to sys.path - for root, dirs, files in os.walk(decoder_path): - # skip hidden dirs like .svn - [dirs.remove(d) for d in dirs if d.startswith('.')] - for d in sorted(dirs): - paths.append(os.path.join(root, d)) - return paths # return the paths we found - - -def getDecoders(decoder_paths): - ''' find all decoders and map decoder to import.path.decoder - expect common prefix to start with basepath''' - import_base = os.path.commonprefix(decoder_paths).split( - os.path.sep)[:-1] # keep last part as base - decoders = {} - for path in decoder_paths: - # split path and trim off part before base - import_path = path.split(os.path.sep)[len(import_base):] - for f in glob.iglob("%s/*.py" % path): - name = os.path.splitext(os.path.basename(f))[0] - if name != '__init__': # skip package stubs - # build topdir.path...module name from topdir/dir.../file - decoders[name] = '.'.join(import_path + [name]) - return decoders - - -def printDecoders(decoder_map, silent=True): - '''Print list of decoders with additional info''' - dList = [] - FS = ' %-40s %-30s %-10s %s %1s %s' - for name, module in sorted(decoder_map.iteritems()): - try: - try: - decoder = import_module(module, silent).dObj - except Exception as exc: - print "Exception loading module '%s': %s" % (module, exc) - continue - # get the type of decoder it is - dtype = 'RAW' - if 'IP' in dir(decoder): - dtype = 'IP ' - if 'UDP' in dir(decoder): - dtype = 'UDP' - if 'TCP' in dir(decoder): - dtype = 'TCP' - dList.append(FS % ( - module, decoder.name, - decoder.author, - dtype, '+' if decoder.chainable else '', - decoder.description)) - except: # :-( - pass - - print FS % ('module', 'name', 'author', ' ', ' ', 'desc') - print FS % ('-' * 40, '-' * 30, '-' * 10, '---', '-', '-' * 50) - for d in sorted(dList): - print d - - -def readInFilter(fname): - '''Read in a BPF filter provided by a command line argument''' - filter = '' - tmpfd = open(fname, 'r') - for line in tmpfd: - if '#' in line: - # keep \n for visual output sanity - line = line.split('#')[0] + '\n' - filter += line - tmpfd.close() - - return filter - - -def decode_live(out, options, decoder, decoder_args, decoder_options): - # set decoder options - initDecoderOptions(decoder, out, options, decoder_args, decoder_options) - - if 'preModule' in dir(decoder): - decoder.preModule() - - # give the interface name to the decoder - decoder.input_file = options.interface - stats = None - if options.verbose: - log('Attempting to listen on %s' % options.interface) - try: - - if not pcap: - raise NotImplementedError("raw capture support not implemented") - decoder.capture = pcap.pcap(options.interface, 65535, True) - if decoder.filter: - decoder.capture.setfilter(decoder.filter) - while not options.count or decoder.count < options.count: - # use dispatch so we can handle signals - decoder.capture.dispatch(1, decoder.decode) - except KeyboardInterrupt: - pass - except Exception as exc: - log(str(exc), level=logging.ERROR) - - if 'cleanConnectionStore' in dir(decoder): - decoder.cleanConnectionStore() - - if 'postModule' in dir(decoder): - decoder.postModule() - - -def expandCompressedFile(fname, verbose, tmpdir): - ''' Expand a file compressed with gzip, bzip2, or zip. - Only handles zip files with 1 file. Need to add handling - for zip files containing multiple pcap files.''' - try: - # print fname - ext = os.path.splitext(fname)[1] - if verbose: - log('+Attempting to process %s compressed file' % (ext)) - if ext == '.gz': - f = gzip.open(fname, 'rb') - elif ext == '.bz2': - f = bz2.BZ2File(fname, 'r') - elif ext == '.zip': - print "Enter password for .zip file [default:none]:", - pswd = raw_input() - z = zipfile.ZipFile(fname) - f = z.open(z.namelist()[0], 'r', pswd) - else: - log('+Error decompressing %s' % (fname), level=logging.ERROR) - return - - h = tempfile.NamedTemporaryFile(dir=tmpdir, delete=False) - if verbose: - log('+Temp directory: %s' % (tempfile.gettempdir())) - log('+Expanding to tempfile %s' % (h.name)) - - for line in f.readlines(): - h.write(line) - h.close() - f.close() - return h.name - except: - return None - - -# This is a support function for the code in main() that supports -# recursive directory crawling when looking for pcap files to parse -# This function recurses through a directory structure, applying -# the wildcard (if any) from the command line. If no wildcard -# is specified, then all files are included. -def addFilesFromDirectory(inputs, curDir, wildcard='*'): - # STEP 1: Add files matching wildcard from current directory... - - # concatenate into path - full_path = os.path.join(curDir, wildcard) - inputs.extend(glob.glob(full_path)) - - # STEP 2: Recurse into child directories - for path in os.listdir(curDir): - fullDir = os.path.join(curDir, path) - - if os.path.isdir(fullDir): - addFilesFromDirectory(inputs, fullDir, wildcard) - - -# The default OptionParser will raise an error when it encounters an option that -# it doesn't understand. By creating a new option parser, dshellOptionParser, -# we can ignore the unknown options (read: Module specific options) -class dshellOptionParser(optparse.OptionParser): - - def error(self, msg): - pass - - # create options for all loaded decoders - def add_decoder_options(self, d): - if d.subDecoder: - # if we have a subdecoder, recurse down until we don't - self.add_decoder_options(d.subDecoder) - try: - if d.optiondict: - group = optparse.OptionGroup( - self, "%s decoder options" % d.name) - for argname, optargs in d.optiondict.iteritems(): - optname = "%s_%s" % (d.name, argname) - group.add_option("--" + optname, dest=optname, **optargs) - self.add_option_group(group) - except: - raise # :-( - - # pass thru to parse_args, but add in kwargs - def parse_args(self, args, **kwargs): - try: - options, args = optparse.OptionParser.parse_args(self, args) - options.__dict__.update(kwargs) - except UnboundLocalError: - # probably missing a value for an argument, e.g. 'decode -d' - # without a decoder - self.print_help() - return None, None - return options, args - - # Fix for handling unknown options (e.g. decoder-specific options) - # reference: - # http://stackoverflow.com/questions/1885161/how-can-i-get-optparses-optionparser-to-ignore-invalid-arguments - def _process_args(self, largs, rargs, values): - while rargs: - try: - optparse.OptionParser._process_args(self, largs, rargs, values) - except (optparse.BadOptionError, optparse.AmbiguousOptionError) as exc: - largs.append(exc.opt_str) - - -def printDecoderBriefs(decoders): - """Prints a brief overview of a decoder when using --help with a decoder""" - print - for d in decoders.values(): - print 'Module name:', d.name - print '=' * 20 - if d.longdescription: - print d.longdescription - else: - print d.description - print 'Default filter: %s' % (d.filter) - return - - -def initDecoderOptions(decoder, out, options, decoder_args, decoder_options): - """ - pass global config to decoder - """ - - # recurse from the bottom of the chain to the top - if decoder.subDecoder: - initDecoderOptions( - decoder.subDecoder, out, options, decoder_args, decoder_options) - - # give the decoder the output object if the decoder doesn't pick one - # or if an output object is specified via command line options - if not decoder.out or options.output != 'output': - decoder.out = out - else: - # initialize the decoder's custom output using the channels from the - # global - # provide global output module under alternate name - decoder.globalout = out - try: - # If the decoder's default output doesn't have a filehandle set, - # use the user provided one - if decoder.out.fh == sys.stdout: - decoder.out.fh = out.fh - except AttributeError: - # A filehandle doesn't always exist, such as with QueueOutput - pass - if not decoder.out.sessionwriter: - decoder.out.sessionwriter = out.sessionwriter - if not decoder.out.pcapwriter: - decoder.out.pcapwriter = out.pcapwriter - # set the logger - decoder.out.logger = logging.getLogger(decoder.name) - - # perform any output module setup before processing data - decoder.out.setup() - - # set output format string, or reset to default - # do not override --oformat specified string - if decoder.format and not options.oformat: - decoder.out.setformat(decoder.format) - - # set verbosity - decoder.verbose = options.verbose - if options.debug: - # debug() is already taken, and _DEBUG might already be set - decoder._DEBUG = options.debug - - # override decoder BPF - if options.bpf != None: - decoder.filter = options.bpf - - # override decoder filterfn - if options.nofilterfn: - decoder.filterfn = lambda addr: True - - # read BPF from file - if options.filefilter != None: - try: - tmpbpf = readInFilter(options.filefilter) - except: - log("Invalid tcpdump filter file: %s" % - (options.filefilter), level=logging.ERROR) - return - - decoder.filter = tmpbpf - - # extend bpf filter if necessary - if options.ebpf != None: - ebpf = options.ebpf - if not decoder.filter: - decoder.filter = ebpf - elif ebpf.startswith('or '): - decoder.filter = decoder.filter + ' ' + ebpf - else: - decoder.filter = decoder.filter + ' and ' + ebpf - - # do we change the layer-2 decoder for raw capture - if options.layer2: - import dpkt - decoder.l2decoder = eval('dpkt.' + options.layer2) - - # strip extra layers? - if options.striplayers: - decoder.striplayers = int(options.striplayers) - - if not options.novlan and not(decoder.filter.startswith('vlan')): - if decoder.filter: - decoder.filter = '( ' + decoder.filter + \ - ' ) or ( vlan and ( ' + decoder.filter + ' ) )' - else: - decoder.filter = '' # fix for null filter case - - # pass args and config file to decoder - decoder.parseArgs(decoder_args, decoder_options) - - log('Using module ' + repr(decoder)) - - -def main(*largs, **kwargs): - global log - bin_path = os.environ['BINPATH'] - sys.path.insert(0, bin_path) - # get map of name to module import path - decoder_map = getDecoders(setDecoderPath(os.environ['DECODERPATH'])) - - # The main argument parser. It will have every command line option - # available and should be used when actually parsing - parser = dshellOptionParser( - usage="usage: %prog [options] [decoder options] file1 file2 ... filen [-- [decoder args]+]", - version="%prog " + str(dshell.__version__), add_help_option=False) - # A short argument parser, meant to only hold the shorter list of - # arguments for when a decoder is called without a pcap file. DO - # NOT USE for any serious argument parsing. - parser_short = dshellOptionParser( - usage="usage: %prog [options] [decoder options] file1 file2 ... filen [-- [decoder args]+]", - version="%prog " + str(dshell.__version__), add_help_option=False) - parser.add_option('-h', '-?', '--help', dest='help', - help="Print common command-line flags and exit", action='store_true', - default=False) - parser_short.add_option('-h', '-?', '--help', dest='help', - help="Print common command-line flags and exit", action='store_true', - default=False) - parser.add_option('-d', '--decoder', dest="decoder", - action='append', help="Use a specific decoder module") - parser.add_option('-l', '--ls', '--list', action="store_true", - help='List all available decoders', dest='list') - parser.add_option( - '-C', '--config', dest='config', help='specify config.ini file') - parser.add_option('--tmpdir', dest='tmpdir', type='string', default=tempfile.gettempdir(), - help='alternate temp directory (for use when processing compressed pcap files)') - parser.add_option('-r', '--recursive', dest='recursive', action='store_true', - help='recursively process all PCAP files under input directory') - - group = optparse.OptionGroup(parser, "Multiprocessing options") - group.add_option('-p', '--parallel', dest='parallel', - action='store_true', help='process multiple files in parallel') - group.add_option('-t', '--threaded', dest='threaded', - action='store_true', help='run multiple decoders in parallel') - group.add_option('-n', '--nprocs', dest='numprocs', type='int', - default=4, help='number of simultaneous processes') - parser.add_option_group(group) - - # decode-pcap specific options - group = optparse.OptionGroup(parser, "Input options") - group.add_option('-i', '--interface', dest='interface', - default=None, help='listen live on INTERFACE') - group.add_option('-c', '--count', dest='count', type='int', - help='number of packets to process', default=0) - group.add_option('-f', '--bpf', dest='bpf', - help='replace default decoder filter (use carefully)') - group.add_option('--nofilterfn', dest='nofilterfn', - action="store_true", help='Set filterfn to pass-thru') - group.add_option('-F', dest='filefilter', - help='Use filefilter as input for the filter expression. An additional expression given on the command line is ignored.') - group.add_option( - '--ebpf', dest='ebpf', help='BPF filter to exclude traffic, extends other filters') - group.add_option('--no-vlan', dest='novlan', action="store_true", - help='do not examine traffic which has VLAN headers present') - group.add_option('--layer2', dest='layer2', default='ethernet.Ethernet', - help='select the layer-2 protocol module') - group.add_option('--strip', dest='striplayers', default=0, - help='extra data-link layers to strip') - parser.add_option_group(group) - - group = optparse.OptionGroup(parser_short, "Input options") - group.add_option('-i', '--interface', dest='interface', - default=None, help='listen live on INTERFACE') - group.add_option('-c', '--count', dest='count', type='int', - help='number of packets to process', default=0) - group.add_option('-f', '--bpf', dest='bpf', - help='replace default decoder filter (use carefully)') - group.add_option('--nofilterfn', dest='nofilterfn', - action="store_true", help='Set filterfn to pass-thru') - group.add_option('-F', dest='filefilter', - help='Use filefilter as input for the filter expression. An additional expression given on the command line is ignored.') - group.add_option( - '--ebpf', dest='ebpf', help='BPF filter to exclude traffic, extends other filters') - group.add_option('--no-vlan', dest='novlan', action="store_true", - help='do not examine traffic which has VLAN headers present') - group.add_option('--layer2', dest='layer2', default='ethernet.Ethernet', - help='select the layer-2 protocol module') - group.add_option('--strip', dest='striplayers', default=0, - help='extra data-link layers to strip') - parser_short.add_option_group(group) - - group = optparse.OptionGroup(parser, "Output options") - group.add_option('-o', '--outfile', dest='outfile', help='write output to the file OUTFILE. Additional output can be set with KEYWORD=VALUE,...\n' + - '\tmode= -1: - (path, wildcard) = os.path.split(file_path) - - # If just file is specified (no path) - if len(path) == 0: - inputs.extend(glob.glob(wildcard)) - - # If there is a path, but recursion not specified, - # then just add matching files from specified dir - elif not len(path) == 0 and not options.recursive: - inputs.extend(glob.glob(file_path)) - - # Otherwise, recursion specified and there is a directory. - # Recurse directory and add files - else: - addFilesFromDirectory(inputs, path, wildcard) - - # Just a normal file, append to list of inputs - else: - inputs.append(file_path) - - if options.parallel or options.threaded: - import multiprocessing - procs = [] - q = multiprocessing.Queue() - kwargs = options.__dict__.copy() # put parsed base options in kwargs - kwargs.update(config=None, outfile=None, queue=q) # pass the q, - # do not pass the config file or outfile because we handled that here - for d in decoder_options: # put pre-parsed decoder options in kwargs - for k, v in decoder_options[d].items(): - kwargs[d + '_' + k] = v - - # check here to see if we are running in parallel-file mode - if options.parallel and len(inputs) > 1: - for f in inputs: - # create a child process for each input file - procs.append( - multiprocessing.Process(target=main, kwargs=kwargs, args=[f])) - runChildProcs(procs, q, out, numprocs=options.numprocs) - - # check here to see if we are running decoders multithreaded - elif options.threaded and len(options.decoder) > 1: - for d in options.decoder: - # create a child for each decoder - kwargs.update(decoder=d) - procs.append( - multiprocessing.Process(target=main, kwargs=kwargs, args=inputs)) - runChildProcs(procs, q, out, numprocs=options.numprocs) - - # fall through to here (single threaded or child process) - else: - # - # Here is where we use the decoder(s) to process the pcap - # - - temporaryFiles = [] # used when uncompressing files - - for module in decoders.keys(): - decoder = decoders[module] - initDecoderOptions( - decoder, out, options, decoder_args, decoder_options) - - # If the decoder has a preModule function, will execute it now - decoder.preModule() - - for input_file in inputs: - # Decoder-specific options may be seen as input files - # Skip anything starts with "--" - if input_file[:2] == '--': - continue - - # Recursive directory processing is handled elsewhere, - # so we should only be dealing with files at this point. - if os.path.isdir(input_file): - continue - - log('+Processing file %s' % input_file) - - # assume the input_file is not compressed - # Allows the processing of .pcap files that are compressed with - # gzip, bzip2, or zip. Writes uncompressed file to a - # NamedTemporaryFile and unlinks the file once it is no longer - # needed. Might consider using mkstemp() since this implementation - # requires Python >= 2.6. - try: - exts = ['.gz', '.bz2', '.zip'] - if os.path.splitext(input_file)[1] not in exts: - pcapfile = input_file - - else: - # we have a compressed file - tmpfile = expandCompressedFile( - input_file, options.verbose, options.tmpdir) - temporaryFiles.append(tmpfile) - pcapfile = tmpfile - except: - if options.verbose: - sys.stderr.write( - '+Error processing file %s' % (input_file)) - continue - - # give the decoder access to the input filename - # motivation: run a decoder against a large number of pcap - # files and have the decoder print the filename - # so you can go straight to the pcap file for - # further analysis - decoder.input_file = input_file - - # Check to see if the decoder has a preFile function - # This will be called before the decoder processes each - # input file - decoder.preFile() - - try: - if not pcap: - raise NotImplementedError( - "pcap support not implemented") - decoder.capture = pcap.pcap(pcapfile) - if decoder.filter: - decoder.capture.setfilter(decoder.filter) - while not options.count or decoder.count < options.count: - try: - # read next packet and break on EOF - ts, pkt = decoder.capture.next() - except: - break # no data - decoder.decode(ts, pkt) - except KeyboardInterrupt: - raise - except: - traceback.print_exc() - - if options.verbose: - log('+Done processing %s' % (input_file)) - - # call that decoder's processFile() - decoder.postFile() - - # check to see if the decoder is using the Messages class - # if so, we need to clean up the connection store to - # purge any unfinished connections - if 'cleanConnectionStore' in dir(decoder): - decoder.cleanConnectionStore() - - # Check to see if the decoder has a postModule function - # A postModule function will be called when the module - # has finished running against all of the input files - if 'postModule' in dir(decoder): - decoder.postModule() - - # remove any temporary files that were created during execution - for tmpfile in temporaryFiles: - if options.verbose: - log('+Unlinking %s' % (tmpfile)) - os.unlink(tmpfile) - - # close output - out.close() - return - - -def runChildProcs(procs, q, out, numprocs=4): - import Queue - running = [] - # while we still have processes to spawn or running - while procs or running: - if procs and len(running) < numprocs: - proc = procs.pop(0) - proc.start() - out.log('started %d' % proc.pid, level=logging.INFO) - running.append(proc) - for proc in running: - if not proc.is_alive(): # see if it finished - out.log('%d exited (%d)' % - (proc.pid, proc.exitcode), level=logging.INFO) - running.remove(proc) - try: # get from the output queue until empty - while True: - m, args, kw = q.get(True, 1) # method, listargs, kwargs - out.dispatch(m, *args, **kw) # dispatch to method - except Queue.Empty: - pass # q empty - - -if __name__ == '__main__': - try: - main(*sys.argv[1:]) - except KeyboardInterrupt: - sys.exit(0) diff --git a/bin/generate-dshellrc.py b/bin/generate-dshellrc.py deleted file mode 100755 index 2de6bd3..0000000 --- a/bin/generate-dshellrc.py +++ /dev/null @@ -1,147 +0,0 @@ -#!/usr/bin/python - -import os -import sys - -if __name__ == '__main__': - cwd = sys.argv[1] - - # environment variables used by shell and modules - envvars = { - 'DSHELL': '%s' % (cwd), - 'DECODERPATH': '%s/decoders' % (cwd), - 'BINPATH': '%s/bin' % (cwd), - 'LIBPATH': '%s/lib' % (cwd), - 'DATAPATH': '%s/share' % (cwd), - } - # further shell environment setup - envsetup = { - 'LD_LIBRARY_PATH': '$LIBPATH:$LD_LIBRARY_PATH', - 'PATH': '$BINPATH:$PATH', - 'PYTHONPATH': '$DSHELL:$LIBPATH:$LIBPATH/output:' + os.path.join('$LIBPATH', 'python' + '.'.join(sys.version.split('.', 3)[:2]).split(' ')[0], 'site-packages') + ':$PYTHONPATH'} - - try: - os.mkdir(os.path.join( - cwd, 'lib', 'python' + '.'.join(sys.version.split('.', 3)[:2]).split(' ')[0])) - os.mkdir(os.path.join(cwd, 'lib', 'python' + - '.'.join(sys.version.split('.', 3)[:2]).split(' ')[0], 'site-packages')) - except Exception, e: - print e - - envdict = {} - envdict.update(envvars) - envdict.update(envsetup) - - #.dshellrc text - env = ['export PS1="`whoami`@`hostname`:\w Dshell> "'] + ['export %s=%s' % - (k, v) for k, v in envvars.items()] + ['export %s=%s' % (k, v) for k, v in envsetup.items()] - outfd = open('.dshellrc', 'w') - outfd.write("\n".join(env)) - if len(sys.argv) > 2 and sys.argv[2] == 'with_bash_completion': - outfd.write(''' - - -if [ `echo $BASH_VERSION | cut -d'.' -f1` -ge '4' ]; then -if [ -f ~/.bash_aliases ]; then -. ~/.bash_aliases -fi - -if [ -f /etc/bash_completion ]; then -. /etc/bash_completion -fi - -find_decoder() -{ -local IFS="+" -for (( i=0; i<${#COMP_WORDS[@]}; i++ )); -do - if [ "${COMP_WORDS[$i]}" == '-d' ] ; then - decoders=(${COMP_WORDS[$i+1]}) - fi -done -} - -get_decoders() -{ - decoders=$(for x in `find $DECODERPATH -iname '*.py' | grep -v '__init__'`; do basename ${x} .py; done) -} - -_decode() -{ -local dashdashcommands=' --ebpf --output --outfile --logfile' - -local cur prev xspec decoders -COMPREPLY=() -cur=`_get_cword` -_expand || return 0 -prev="${COMP_WORDS[COMP_CWORD-1]}" - -case "${cur}" in ---*) - find_decoder - local options="" -# if [ -n "$decoders" ]; then -# for decoder in "${decoders[@]}" -# do -# options+=`/usr/bin/python $BINPATH/gen_decoder_options.py $decoder` -# options+=" " -# done -# fi - - options+=$dashdashcommands - COMPREPLY=( $(compgen -W "${options}" -- ${cur}) ) - return 0 - ;; - -*+*) - get_decoders - firstdecoder=${cur%+*}"+" - COMPREPLY=( $(compgen -W "${decoders}" -P $firstdecoder -- ${cur//*+}) ) - return 0 - ;; - -esac - -xspec="*.@(cap|pcap)" -xspec="!"$xspec -case "${prev}" in --d) - get_decoders - COMPREPLY=( $(compgen -W "${decoders[0]}" -- ${cur}) ) - return 0 - ;; - ---output) - local outputs=$(for x in `find $DSHELL/lib/output -iname '*.py' | grep -v 'output.py'`; do basename ${x} .py; done) - - COMPREPLY=( $(compgen -W "${outputs}" -- ${cur}) ) - return 0 - ;; - --F | -o | --outfile | -L | --logfile) - xspec= - ;; - -esac - -COMPREPLY=( $( compgen -f -X "$xspec" -- "$cur" ) \ -$( compgen -d -- "$cur" ) ) -} -complete -F _decode -o filenames decode -complete -F _decode -o filenames decode.py -fi -''') - outfd.close() - - # dshell text - outfd = open('dshell', 'w') - outfd.write('#!/bin/bash\n') - outfd.write('/bin/bash --rcfile %s/.dshellrc\n' % (cwd)) - outfd.close() - - # dshell-decode text - outfd = open('dshell-decode', 'w') - outfd.write('#!/bin/bash\n') - outfd.write('source %s/.dshellrc\n' % (cwd)) - outfd.write('decode "$@"') - outfd.close() diff --git a/bin/pcapanon.py b/bin/pcapanon.py deleted file mode 100755 index 1a61478..0000000 --- a/bin/pcapanon.py +++ /dev/null @@ -1,229 +0,0 @@ -#!/usr/bin/env python -''' -Created on Feb 6, 2012 - -@author: tparker -''' - -import sys -import dpkt -import struct -import pcap -import socket -import time -from Crypto.Random import random -from Crypto.Hash import SHA -from output import PCAPWriter -from util import getopts - - -def hashaddr(addr, *extra): - # hash key+address plus any extra data (ports if flow) - global key, ip_range, ip_mask - sha = SHA.new(key + addr) - for e in extra: - sha.update(str(extra)) - # take len(addr) octets of digest as address, to int, mask, or with range, - # back to octets - return inttoip((iptoint(sha.digest()[0:len(addr)]) & ip_mask) | ip_range) - - -def mangleMAC(addr): - global zero_mac - if zero_mac: - return "\x00\x00\x00\x00\x00\x00" - if addr in emap: - return emap[addr] - haddr = None - if addr == "\x00\x00\x00\x00\x00\x00": - haddr = addr # return null MAC - if ord(addr[0]) & 0x01: - haddr = addr # mac&0x800000000000 == broadcast addr, do not touch - if not haddr: - haddr = hashaddr(addr) - # return hash bytes with first byte set to xxxxxx10 (LAA unicast) - haddr = chr(ord(haddr[0]) & 0xfc | 0x2) + haddr[1:6] - emap[addr] = haddr - return haddr - - -def mangleIP(addr, *ports): # addr,extra=our_port,other_port - global exclude, exclude_port, anon_all, by_flow - haddr = None - intip = iptoint(addr) - if len(addr) == 4 and intip >= 0xE0000000: - haddr = addr # pass multicast 224.x.x.x and higher - ip = iptoa(addr) - # pass 127.x.x.x, IANA reserved, and autoconfig ranges - if not anon_all and (ip.startswith('127.') - or ip.startswith('10.') - or ip.startswith('172.16.') - or ip.startswith('192.168.') - or ip.startswith('169.254.')): - haddr = addr - # pass ips matching exclude - for x in exclude: - if ip.startswith(x): - haddr = addr - if ports and ports[0] in exclude_port: - haddr = addr # if our port is exclude - if not haddr: - if by_flow: - # use ports if by flow, else just use ip - haddr = hashaddr(addr, *ports) - else: - haddr = hashaddr(addr) - return haddr - - -def mangleIPs(src, dst, sport, dport): - if by_flow: # if by flow, hash addresses with s/d ports - if (src, sport, dst, dport) in ipmap: - src, dst = ipmap[(src, sport, dst, dport)] - elif (dst, dport, src, sport) in ipmap: - # make sure reverse flow maps same - dst, src = ipmap[(dst, dport, src, sport)] - else: - src, dst = ipmap.setdefault( - (src, sport, dst, dport), (mangleIP(src, sport, dport), mangleIP(dst, dport, sport))) - else: - if src in ipmap: - src = ipmap[src] - else: - src = ipmap.setdefault(src, mangleIP(src, sport)) - if dst in ipmap: - dst = ipmap[dst] - else: - dst = ipmap.setdefault(dst, mangleIP(dst, dport)) - return src, dst - - -def mactoa(addr): - return ':'.join(['%02x' % b for b in struct.unpack('6B', addr)]) - - -def iptoa(addr): - if len(addr) is 16: - return socket.inet_ntop(socket.AF_INET6, addr) - else: - return socket.inet_ntop(socket.AF_INET, addr) - - -def iptoint(addr): - if len(addr) is 16: # ipv6 to long - ip = struct.unpack('!IIII', addr) - return ip[0] << 96 | ip[1] << 64 | ip[2] << 32 | ip[3] - else: - return struct.unpack('!I', addr)[0] # ip to int - - -def inttoip(l): - if l > 0xffffffff: # ipv6 - return struct.pack('!IIII', l >> 96, l >> 64 & 0xffffffff, l >> 32 & 0xffffffff, l & 0xffffffff) - else: - return struct.pack('!I', l) - - -def pcap_handler(ts, pktdata): - global init_ts, start_ts, replace_ts, by_flow, anon_mac, zero_mac - if not init_ts: - init_ts = ts - if replace_ts: - ts = start_ts + (ts - init_ts) # replace timestamps - try: - pkt = dpkt.ethernet.Ethernet(pktdata) - if anon_mac or zero_mac: - pkt.src = mangleMAC(pkt.src) - pkt.dst = mangleMAC(pkt.dst) - if pkt.type == dpkt.ethernet.ETH_TYPE_IP: - try: - # TCP or UDP? - sport, dport = pkt.data.data.sport, pkt.data.data.dport - except: - sport = dport = None # nope - pkt.data.src, pkt.data.dst = mangleIPs( - pkt.data.src, pkt.data.dst, sport, dport) - pktdata = str(pkt) - except Exception, e: - print e - out.write(len(pktdata), pktdata, ts) - -if __name__ == '__main__': - - global key, init_ts, start_ts, replace_ts, by_flow, anon_mac, zero_mac, exclude, exclude_port, anon_all, ip_range, ip_mask - opts, args = getopts(sys.argv[1:], 'i:aezftx:p:rk:', [ - 'ip=', 'all', 'ether', 'zero', 'flow', 'ts', 'exclude=', 'random', 'key=', 'port='], ['-x', '--exclude', '-p', '--port']) - - if '-r' in opts or '--random' in opts: - key = random.long_to_bytes(random.getrandbits(64), 8) - else: - key = '' - key = opts.get('-k', opts.get('--key', key)) - - ip_range = opts.get('-i', opts.get('--ip', '0.0.0.0')) - ip_mask = 0 # bitmask for hashed address - ipr = '' - for o in map(int, ip_range.split('.')): - ipr += chr(o) - ip_mask <<= 8 # shift by 8 bits - if not o: - ip_mask |= 0xff # set octet mask to 0xff if ip_range octet is zero - ip_range = iptoint(ipr) # convert to int value for hash&mask|ip_range - - replace_ts = '-t' in opts or '--ts' in opts - by_flow = '-f' in opts or '--flow' in opts - anon_mac = '-e' in opts or '--ether' in opts - zero_mac = '-z' in opts or '--zero' in opts - anon_all = '-a' in opts or '--all' in opts - - start_ts = time.time() - init_ts = None - - exclude = opts.get('-x', []) - exclude.extend(opts.get('--exclude', [])) - - exclude_port = map(int, opts.get('-p', [])) - exclude_port.extend(map(int, opts.get('--port', []))) - - emap = {} - ipmap = {} - - if len(args) < 2: - print "usage: pcapanon.py [options] > mapping.csv\nOptions:\n\t[-i/--ip range]\n\t[-r/--random | -k/--key 'salt' ]\n\t[-a/--all] [-t/--ts] [-f/--flow]\n\t[-e/--ether | -z/--zero]\n\t[-x/--exclude pattern...]\n\t[-p/--port list...]" - print "Will anonymize all non-reserved IPs to be in range specified by -i/--ip option," - print "\tnonzero range octets are copied to anonymized address,\n\t(default range is 0.0.0.0 for fully random IPs)" - print "CSV output maps original to anonymized addresses" - print "By default anonymization will use a straight SHA1 hash of the address" - print "\t***this is crackable as mapping is always the same***".upper() - print "Use -r/--random to generate a random salt (cannot easily reverse without knowing map)" - print "\tor use -k/--key 'salt' (will generate same mapping given same salt)," - print "-f/--flows will anonymize by flow (per source:port<->dest:port tuples)" - print "-a/--all will also anonymize reserved IPs" - print "-x/--exclude will leave IPs starting with pattern unchanged" - print "-p/--port port will leave IP unchanged if port is in list" - print "-t/--ts will replace timestamp of first packet with time pcapanon was run,\n\tsubsequent packets will preserve delta from initial ts" - print "-e/--ether will also anonymize non-broadcast MAC addresses" - print "-z/--zero will zero all MAC addresses" - sys.exit(0) - - out = PCAPWriter(args[-1]) - print '#file, packets' - for f in args[0:-1]: - p = 0 - cap = pcap.pcap(f) - while cap.dispatch(1, pcap_handler): - p += 1 # process whole file - del cap - print '%s,%s' % (f, p) - out.close() - - print "#type,is-anonymized, original, anonymized" - for ia, oa in sorted(emap.items()): - print 'ether,%d, %s, %s' % (int(not ia == oa), mactoa(ia), mactoa(oa)) - for ia, oa in sorted(ipmap.items()): - if by_flow: - sip, sp, dip, dp = ia - osip, odip = oa - print "flow,%d, %s:%s,%s:%s, %s:%s,%s:%s" % (int(sip != osip or dip != odip), iptoa(sip), sp, iptoa(dip), dp, iptoa(osip), sp, iptoa(odip), dp) - else: - print 'ip,%d, %s, %s' % (int(ia != oa), iptoa(ia), iptoa(oa)) diff --git a/bin/pcapslice.py b/bin/pcapslice.py deleted file mode 100755 index 9e7998b..0000000 --- a/bin/pcapslice.py +++ /dev/null @@ -1,249 +0,0 @@ -#!/usr/bin/env python -''' -split pcap files by ip src/dst pair or tcp/udp stream - -Originally created February 2013 -Updated from pylibpcap to pypcap, November 2015 - -@author: amm -''' - -import sys -import os -import pcap -import dpkt -import signal -import socket -import output -from optparse import OptionParser - -IPprotocols = { - 0: 'IP', 1: 'ICMP', 2: 'IGMP', 3: 'GGP', 4: 'IP-ENCAP', 133: 'FC', 6: 'TCP', 8: 'EGP', 137: 'MPLS-IN-IP', 138: 'MANET', 139: 'HIP', 12: 'PUP', 17: 'UDP', 20: 'HMP', 22: 'XNS-IDP', 132: 'SCTP', 27: 'RDP', 29: 'ISO-TP4', 5: 'ST', 36: 'XTP', 37: 'DDP', 38: 'IDPR-CMTP', 41: 'IPV6', 43: 'IPV6-ROUTE', 44: 'IPV6-FRAG', - 45: 'IDRP', 46: 'RSVP', 47: 'GRE', 136: 'UDPLITE', 50: 'IPSEC-ESP', 51: 'IPSEC-AH', 9: 'IGP', 57: 'SKIP', 58: 'IPV6-ICMP', 59: 'IPV6-NONXT', 60: 'IPV6-OPTS', 73: 'RSPF', 81: 'VMTP', 88: 'EIGRP', 89: 'OSPFIGP', 93: 'AX.25', 94: 'IPIP', 97: 'ETHERIP', 98: 'ENCAP', 103: 'PIM', 108: 'IPCOMP', 112: 'VRRP', 115: 'L2TP', 124: 'ISIS'} -flowtimeout = 1800 # seconds -ctrl_c_Received = False - -''' -main -''' - - -def main(): - global options, ctrl_c_Received - - flows = flowstore() - - parser = OptionParser( - usage="usage: %prog [options] file", version="%prog: PCAP Slicer") - parser.add_option('-f', '--bpf', dest='bpf', help='BPF input filter') - parser.add_option('-o', '--outdir', dest='outdir', default='.', - help='directory to write output files (Default: current directory)') - parser.add_option('--no-vlan', dest='novlan', action="store_true", - help='do not examine traffic which has VLAN headers present') - parser.add_option('--debug', action='store_true', dest='debug') - (options, args) = parser.parse_args(sys.argv[1:]) - - if not args: - parser.print_version() - parser.print_help() - sys.exit() - - filter = '' - if options.bpf != None: - filter = options.bpf - if not options.novlan and not(filter.startswith('vlan')): - if filter: - filter = '( ' + filter + ' ) or ( vlan and ( ' + filter + ' ) )' - else: - filter = '' # fix for null filter case - - pcount = 0 - for f in args: - pcapreader = pcap.pcap(f) - if options.bpf: - pcapreader.setfilter(filter) - while True: - # Pick a packet - try: - ts, spkt = pcapreader.next() - except: - break # EOF - # Parse IP/Port/Proto Information - try: - pkt = dpkt.ethernet.Ethernet(spkt) - # Only handle IP4/6 - if type(pkt.data) == dpkt.ip.IP: - proto = pkt.data.p - elif type(pkt.data) == dpkt.ip6.IP6: - proto = pkt.data.nxt - else: - continue - # Populate addr tuple - # (proto, sip, sport, dip, dport) - if proto == dpkt.ip.IP_PROTO_TCP or proto == dpkt.ip.IP_PROTO_UDP: - addr = ( - proto, pkt.data.src, pkt.data.data.sport, pkt.data.dst, pkt.data.data.dport) - else: - addr = (proto, pkt.data.src, None, pkt.data.dst, None) - except: - continue # Skip Packet if unable to parse - pcount += 1 - # - # Look for existing open flow or start new one - # - thisflow = flows.find(addr) - if thisflow == None: - thisflow = flow(addr) - flows.add(thisflow) - warn("New flow to file: %s" % str(thisflow)) - # - # Write this packet to correct flow - # - thisflow.write(len(spkt), spkt, ts) - # - # Check for TCP reset or fin - # - try: - if pkt.data.data.flags & (dpkt.tcp.TH_RST | dpkt.tcp.TH_FIN): - thisflow.done() - except: - pass # probably not a TCP packet - # - # Cleanup Routine - # - if pcount % 1000 == 0: - flows.cleanup(ts) - # - # Clean exit - # - if ctrl_c_Received: - sys.stderr.write("Exiting on interrupt signal.\n") - sys.exit(0) -''' -flow class - instantiated for each bi-directional flow of data - maintains pcapwriter for each open session -''' - - -class flow: - - def __init__(self, addr): - self.addr = addr - self.outfilename = localfilename(addr) - self.pcapwriter = output.PCAPWriter(self.outfilename) - self.state = 1 - self.lastptime = 0 - - def write(self, l, spkt, ts): - self.pcapwriter.write(l, spkt, ts) - self.lastptime = ts - - # Mark flow as done (RST/FIN received) - # but don't close the pcap file yet - def done(self): - self.state = 0 - - def __del__(self): - warn("Closing file: %s" % self.outfilename) - - def __str__(self): - return self.outfilename - - def __repr__(self): - return self.outfilename - -''' -flowstore class -''' - - -class flowstore: - global flowtimeout - - def __init__(self): - self.data = {} # indexed by addr tuple (proto, sip, sport, dip, dport) - - def find(self, addr): - # Fwd Search - if addr in self.data: - return self.data[addr] - # Rev Search - (proto, sip, sport, dip, dport) = addr - if (proto, dip, dport, sip, sport) in self.data: - return self.data[(proto, dip, dport, sip, sport)] - return None - - def add(self, newflow): - self.data[newflow.addr] = newflow - - def cleanup(self, currentPtime): - for k in self.data.keys(): - if self.data[k].state > 0: - continue - # Check timeout - if currentPtime - self.data[k].lastptime > flowtimeout: - del self.data[k] - - -def warn(text): - sys.stdout.write("WARN: " + str(text) + "\n") - - -def normalizedIP(packed): - if len(packed) == 16: - return socket.inet_ntop(socket.AF_INET6, packed) - else: - ip = socket.inet_ntoa(packed) - if '.' in ip: - parts = ip.split('.') - return '.'.join(['%03d' % int(p) for p in parts]) - return ip - - -def localfilename(addr): - global IPprotocols, options - (proto, sip, sport, dip, dport) = addr - # Convert Numeric Protocol to Text - if proto in IPprotocols: - proto = IPprotocols[proto] - else: - proto = '%05d' % int(proto) - # Convert packed IPs to Text - nameparts = [proto, normalizedIP(sip), normalizedIP(dip)] - try: - nameparts.append('%05d' % int(sport)) - except: - pass - try: - nameparts.append('%05d' % int(dport)) - except: - pass - # Filename - fname = '_'.join(nameparts) - inc = 0 - while True: - fullname = os.path.join(options.outdir, '%s_%03d.pcap' % (fname, inc)) - if not os.path.exists(fullname): - return fullname - inc += 1 - - -''' -handle interupt events -''' - - -def ctrlchandler(signum, frame): - global ctrl_c_Received - ctrl_c_Received = True - sys.stderr.write("Interrupt received. Will exit at next clean break.\n") - -if __name__ == '__main__': - signal.signal(signal.SIGINT, ctrlchandler) - # sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 0) # reopen STDOUT - # unbuffered - try: - main() - except KeyboardInterrupt: - sys.exit(0) diff --git a/decoders/dhcp/dhcp.py b/decoders/dhcp/dhcp.py deleted file mode 100644 index 7073bf5..0000000 --- a/decoders/dhcp/dhcp.py +++ /dev/null @@ -1,89 +0,0 @@ -import dpkt -import dshell -import util -from struct import unpack -import binascii - -class DshellDecoder(dshell.UDPDecoder): - - def __init__(self): - dshell.UDPDecoder.__init__(self, - name='dhcp', - description='Extract client information from DHCP messages', - longdescription=""" -The dhcp decoder will extract the Transaction ID, Client Hostname, and -Client MAC address from every UDP DHCP packet found in the given pcap -using port 67. DHCP uses BOOTP as its transport protocol. -BOOTP traffic generally uses ports 67 and 68 for outgoing and incoming traffic. -This filter pulls DHCP Inform packets. - -Examples: - - General usage: - - decode -d dhcp - - This will display the connection info including the timestamp, - the source IP : source port, destination IP : destination port, - Transaction ID, Client Hostname, and the Client MAC address - in a tabular format. - - - Malware Traffic Analysis Exercise Traffic from 2015-03-03 where a user was hit with an Angler exploit kit: - - We want to find out more about the infected machine, and some of this information can be pulled from DHCP traffic - - decode -d dhcp /2015-03-03-traffic-analysis-exercise.pcap - - OUTPUT: - dhcp 2015-03-03 14:05:10 172.16.101.196:68 -- 172.16.101.1:67 ** Transaction ID: 0xba5a2cfe Client Hostname: Gregory-PC Client MAC: 38:2c:4a:3d:ef:01 ** - dhcp 2015-03-03 14:08:40 172.16.101.196:68 -- 255.255.255.255:67 ** Transaction ID: 0x6a482406 Client Hostname: Gregory-PC Client MAC: 38:2c:4a:3d:ef:01 ** - dhcp 2015-03-03 14:10:11 172.16.101.196:68 -- 172.16.101.1:67 ** Transaction ID: 0xe74b17fe Client Hostname: Gregory-PC Client MAC: 38:2c:4a:3d:ef:01 ** - dhcp 2015-03-03 14:12:50 172.16.101.196:68 -- 255.255.255.255:67 ** Transaction ID: 0xd62614a0 Client Hostname: Gregory-PC Client MAC: 38:2c:4a:3d:ef:01 ** -""", - filter='(udp and port 67)', - author='dek', - ) - self.mac_address = None - self.client_hostname = None - self.xid = None - - - # A packetHandler is used to ensure that every DHCP packet in the traffic is parsed - def packetHandler(self, udp, data): - try: - dhcp_packet = dpkt.dhcp.DHCP(data) - except dpkt.NeedData as e: - self.warn('{} dpkt could not parse session data (DHCP packet not found)'.format(str(e))) - return - - # Pull the transaction ID from the packet - self.xid = hex(dhcp_packet.xid) - - # if we have a DHCP INFORM PACKET - if dhcp_packet.op == dpkt.dhcp.DHCP_OP_REQUEST: - self.debug(dhcp_packet.op) - for option_code, msg_value in dhcp_packet.opts: - - # if opt is CLIENT_ID (61) - # unpack the msg_value and reformat the MAC address - if option_code == dpkt.dhcp.DHCP_OPT_CLIENT_ID: - hardware_type, mac = unpack('B6s', msg_value) - mac = binascii.hexlify(mac) - self.mac_address = ':'.join([mac[i:i+2] for i in range(0, len(mac), 2)]) - - # if opt is HOSTNAME (12) - elif option_code == dpkt.dhcp.DHCP_OPT_HOSTNAME: - self.client_hostname = msg_value - - - if self.xid and self.client_hostname and self.mac_address: - self.alert('Transaction ID: {0:<12} Client Hostname: {1:<15} Client MAC: {2:<20}'.format( - self.xid, self.client_hostname, self.mac_address), **udp.info()) - - -if __name__ == '__main__': - dObj = DshellDecoder() - print dObj -else: - dObj = DshellDecoder() diff --git a/decoders/dns/dns-asn.py b/decoders/dns/dns-asn.py deleted file mode 100644 index bb97401..0000000 --- a/decoders/dns/dns-asn.py +++ /dev/null @@ -1,76 +0,0 @@ -import dshell -import dpkt -import socket -from dnsdecoder import DNSDecoder - - -class DshellDecoder(DNSDecoder): - - def __init__(self): - DNSDecoder.__init__(self, - name='dns-asn', - description='identify AS of DNS A/AAAA record responses', - filter='(port 53)', - author='bg', - cleanupinterval=10, - maxblobs=2, - ) - - def decode_q(self, dns): - queried = "" - if dns.qd[0].type == dpkt.dns.DNS_A: - queried = queried + "A? %s" % (dns.qd[0].name) - if dns.qd[0].type == dpkt.dns.DNS_AAAA: - queried = queried + "AAAA? %s" % (dns.qd[0].name) - return queried - - def DNSHandler(self, conn, request, response, **kwargs): - anstext = '' - queried = '' - id = None - for dns in request, response: - if dns is None: - continue - id = dns.id - # DNS Question, update connection info with query - if dns.qr == dpkt.dns.DNS_Q: - conn.info(query=self.decode_q(dns)) - - # DNS Answer with data and no errors - elif (dns.qr == dpkt.dns.DNS_A and dns.rcode == dpkt.dns.DNS_RCODE_NOERR and len(dns.an) > 0): - - queried = self.decode_q(dns) - - answers = [] - for an in dns.an: - if an.type == dpkt.dns.DNS_A: - try: - cc = self.getASN(socket.inet_ntoa(an.ip)) - answers.append( - 'A: %s (%s) (ttl %s)' % (socket.inet_ntoa(an.ip), cc, an.ttl)) - except: - continue - elif an.type == dpkt.dns.DNS_AAAA: - try: - cc = self.getASN( - socket.inet_ntop(socket.AF_INET6, an.ip6)) - answers.append('AAAA: %s (%s) (ttl %s)' % ( - socket.inet_ntop(socket.AF_INET6, an.ip6), cc, an.ttl)) - except: - continue - else: - # un-handled type - continue - if queried != '': - anstext = ", ".join(answers) - - if anstext: # did we get an answer? - self.alert( - str(id) + ' ' + queried + ' / ' + anstext, **conn.info(response=anstext)) - - -if __name__ == '__main__': - dObj = DshellDecoder() - print dObj -else: - dObj = DshellDecoder() diff --git a/decoders/dns/dns-cc.py b/decoders/dns/dns-cc.py deleted file mode 100644 index 99fbe51..0000000 --- a/decoders/dns/dns-cc.py +++ /dev/null @@ -1,86 +0,0 @@ -import dshell -import dpkt -import socket -from dnsdecoder import DNSDecoder - - -class DshellDecoder(DNSDecoder): - - def __init__(self): - DNSDecoder.__init__(self, - name='dns-cc', - description='identify country code of DNS A/AAAA record responses', - filter='(port 53)', - author='bg', - cleanupinterval=10, - maxblobs=2, - optiondict={'foreign': {'action': 'store_true', 'help': 'report responses in foreign countries'}, - 'code': {'type': 'string', 'help': 'filter on a specific country code (ex. US)'}} - ) - - def decode_q(self, dns): - queried = "" - if dns.qd[0].type == dpkt.dns.DNS_A: - queried = queried + "A? %s" % (dns.qd[0].name) - if dns.qd[0].type == dpkt.dns.DNS_AAAA: - queried = queried + "AAAA? %s" % (dns.qd[0].name) - return queried - - def DNSHandler(self, conn, request, response, **kwargs): - anstext = '' - queried = '' - id = None - for dns in request, response: - if dns is None: - continue - id = dns.id - # DNS Question, update connection info with query - if dns.qr == dpkt.dns.DNS_Q: - conn.info(query=self.decode_q(dns)) - - # DNS Answer with data and no errors - elif (dns.qr == dpkt.dns.DNS_A and dns.rcode == dpkt.dns.DNS_RCODE_NOERR and len(dns.an) > 0): - - queried = self.decode_q(dns) - - answers = [] - for an in dns.an: - if an.type == dpkt.dns.DNS_A: - try: - cc = self.getGeoIP(socket.inet_ntoa(an.ip)) - if self.foreign and (cc == 'US' or cc == '--'): - continue - elif self.code != None and cc != self.code: - continue - answers.append( - 'A: %s (%s) (ttl %ss)' % (socket.inet_ntoa(an.ip), cc, an.ttl)) - except: - continue - elif an.type == dpkt.dns.DNS_AAAA: - try: - cc = self.getGeoIP( - socket.inet_ntop(socket.AF_INET6, an.ip6)) - if self.foreign and (cc == 'US' or cc == '--'): - continue - elif self.code != None and cc != self.code: - continue - answers.append('AAAA: %s (%s) (ttl %ss)' % ( - socket.inet_ntop(socket.AF_INET6, an.ip6), cc, an.ttl)) - except: - continue - else: - # un-handled type - continue - if queried != '': - anstext = ", ".join(answers) - - if anstext: # did we get an answer? - self.alert( - str(id) + ' ' + queried + ' / ' + anstext, **conn.info(response=anstext)) - - -if __name__ == '__main__': - dObj = DshellDecoder() - print dObj -else: - dObj = DshellDecoder() diff --git a/decoders/dns/dns.py b/decoders/dns/dns.py deleted file mode 100755 index 1971c7d..0000000 --- a/decoders/dns/dns.py +++ /dev/null @@ -1,135 +0,0 @@ -import dpkt -import socket -from dnsdecoder import DNSDecoder - - -class DshellDecoder(DNSDecoder): - - def __init__(self): - DNSDecoder.__init__(self, - name='dns', - description='extract and summarize DNS queries/responses (defaults: A,AAAA,CNAME,PTR records)', - filter='(udp and port 53)', - author='bg/twp', - optiondict={'show_noanswer': {'action': 'store_true', 'help': 'report unanswered queries alongside other queries'}, - 'show_norequest': {'action': 'store_true', 'help': 'report unsolicited responses alongside other responses'}, - 'only_noanswer': {'action': 'store_true', 'help': 'report only unanswered queries'}, - 'only_norequest': {'action': 'store_true', 'help': 'report only unsolicited responses'}, - 'showall': {'action': 'store_true', 'help': 'show all answered queries/responses'}} - ) - - def decode_q(self, dns): - queried = "" - if dns.qd[0].type == dpkt.dns.DNS_A: - queried = queried + "A? %s" % (dns.qd[0].name) - elif dns.qd[0].type == dpkt.dns.DNS_CNAME: - queried = queried + "CNAME? %s" % (dns.qd[0].name) - elif dns.qd[0].type == dpkt.dns.DNS_AAAA: - queried = queried + "AAAA? %s" % (dns.qd[0].name) - elif dns.qd[0].type == dpkt.dns.DNS_SOA: - queried = queried + "SOA? %s" % (dns.qd[0].name) - elif dns.qd[0].type == dpkt.dns.DNS_PTR: - if dns.qd[0].name.endswith('.in-addr.arpa'): - query_name = '.'.join( - reversed(dns.qd[0].name.split('.in-addr.arpa')[0].split('.'))) - else: - query_name = dns.qd[0].name - queried = queried + "PTR? %s" % (query_name) - - if not self.showall: - return queried - - if dns.qd[0].type == dpkt.dns.DNS_NS: - queried = queried + "NS? %s" % (dns.qd[0].name) - elif dns.qd[0].type == dpkt.dns.DNS_MX: - queried = queried + "MX? %s" % (dns.qd[0].name) - elif dns.qd[0].type == dpkt.dns.DNS_TXT: - queried = queried + "TXT? %s" % (dns.qd[0].name) - elif dns.qd[0].type == dpkt.dns.DNS_SRV: - queried = queried + "SRV? %s" % (dns.qd[0].name) - - return queried - - def DNSHandler(self, conn, request, response, **kwargs): - if self.only_norequest and request is not None: - return - if not self.show_norequest and request is None: - return - anstext = '' - queried = '' - id = None - for dns in request, response: - if dns is None: - continue - id = dns.id - # DNS Question, update connection info with query - if dns.qr == dpkt.dns.DNS_Q: - conn.info(query=self.decode_q(dns)) - - # DNS Answer with data and no errors - elif (dns.rcode == dpkt.dns.DNS_RCODE_NOERR and len(dns.an) > 0): - - queried = self.decode_q(dns) - - answers = [] - for an in dns.an: - if an.type == dpkt.dns.DNS_A: - try: - answers.append( - 'A: %s (ttl %ss)' % (socket.inet_ntoa(an.ip), str(an.ttl))) - except: - continue - elif an.type == dpkt.dns.DNS_AAAA: - try: - answers.append('AAAA: %s (ttl %ss)' % ( - socket.inet_ntop(socket.AF_INET6, an.ip6), str(an.ttl))) - except: - continue - elif an.type == dpkt.dns.DNS_CNAME: - answers.append('CNAME: ' + an.cname) - elif an.type == dpkt.dns.DNS_PTR: - answers.append('PTR: ' + an.ptrname) - elif an.type == dpkt.dns.DNS_NS: - answers.append('NS: ' + an.nsname) - elif an.type == dpkt.dns.DNS_MX: - answers.append('MX: ' + an.mxname) - elif an.type == dpkt.dns.DNS_TXT: - answers.append('TXT: ' + ' '.join(an.text)) - elif an.type == dpkt.dns.DNS_SRV: - answers.append('SRV: ' + an.srvname) - else: - # un-handled type - continue - if queried != '': - anstext = ", ".join(answers) - - #NXDOMAIN in response - elif dns.qr == dpkt.dns.DNS_A and dns.rcode == dpkt.dns.DNS_RCODE_NXDOMAIN: - queried = self.decode_q(dns) # decode query part - - if queried != '': - anstext = 'NXDOMAIN' - - #SOA response - elif dns.qd[0].type == dpkt.dns.DNS_SOA and len(dns.ns): - queried = self.decode_q(dns) - answers = [] - for ns in dns.ns: - if ns.type == dpkt.dns.DNS_SOA: - answers.append('SOA: '+ ns.mname) - anstext = ", ".join(answers) - - - # did we get an answer? - if anstext and not self.only_noanswer and not self.only_norequest: - self.alert( - str(id) + ' ' + queried + ' / ' + anstext, **conn.info(response=anstext)) - elif not anstext and (self.show_noanswer or self.only_noanswer): - self.alert( - str(id) + ' ' + conn.query + ' / (no answer)', **conn.info()) - -if __name__ == '__main__': - dObj = DshellDecoder() - print dObj -else: - dObj = DshellDecoder() diff --git a/decoders/dns/innuendo-dns.py b/decoders/dns/innuendo-dns.py deleted file mode 100644 index 0799c18..0000000 --- a/decoders/dns/innuendo-dns.py +++ /dev/null @@ -1,93 +0,0 @@ -import dpkt -from dnsdecoder import DNSDecoder -import base64 - - -class DshellDecoder(DNSDecoder): - - """ - Proof-of-concept Dshell decoder to detect INNUENDO DNS Channel - - Based on the short marketing video [http://vimeo.com/115206626] the INNUENDO - DNS Channel relies on DNS to communicate with an authoritative name server. - The name server will respond with a base64 encoded TXT answer. This decoder - will analyze DNS TXT queries and responses to determine if it matches the - network traffic described in the video. There are multiple assumptions (*very - poor*) in this detection plugin but serves as a proof-of-concept detector. This - detector has not been tested against authentic INNUENDO DNS Channel traffic. - - Usage: decode -d innuendo-dns *.pcap - - """ - - def __init__(self): - DNSDecoder.__init__(self, - name='innuendo-dns', - description='proof-of-concept detector for INNUENDO DNS channel', - filter='(port 53)', - author='primalsec', - ) - self.whitelist = [] # probably be necessary to whitelist A/V domains - - def in_whitelist(self, domain): - # add logic - return False - - def decrypt_payload(payload): pass - - def DNSHandler(self, conn, request, response, **kwargs): - query = '' - answers = [] - - for dns in request, response: - - if dns is None: - continue - - id = dns.id - - # DNS Question, extract query name if it is a TXT record request - if dns.qr == dpkt.dns.DNS_Q and dns.qd[0].type == dpkt.dns.DNS_TXT: - query = dns.qd[0].name - - # DNS Answer with data and no errors - elif (dns.qr == dpkt.dns.DNS_A and dns.rcode == dpkt.dns.DNS_RCODE_NOERR and len(dns.an) > 0): - - for an in dns.an: - if an.type == dpkt.dns.DNS_TXT: - answers.append(an.text[0]) - - if query != '' and len(answers) > 0: - # add check here to see if the second level domain and top level - # domain are not in a white list - if self.in_whitelist(query): - return - - # assumption: INNUENDO will use the lowest level domain for C2 - # example: AAAABBBBCCCC.foo.bar.com -> AAAABBBBCCCC is the INNUENDO - # data - subdomain = query.split('.')[0] - - # weak test based on video observation *very poor assumption* - if subdomain.isupper(): - # check each answer in the TXT response - for answer in answers: - try: - # INNUENDO DNS channel base64 encodes the response, check to see if - # it contains a valid base64 string *poor assumption* - dummy = base64.b64decode(answer) - - self.alert( - 'INNUENDO DNS Channel', query, '/', answer, **conn.info()) - - # here would be a good place to decrypt the payload (if you have the keys) - # decrypt_payload( answer ) - except: - pass - - -if __name__ == '__main__': - dObj = DshellDecoder() - print dObj -else: - dObj = DshellDecoder() diff --git a/decoders/dns/reservedips.py b/decoders/dns/reservedips.py deleted file mode 100644 index 8478dce..0000000 --- a/decoders/dns/reservedips.py +++ /dev/null @@ -1,151 +0,0 @@ -import dshell -import dpkt -import socket -from dnsdecoder import DNSDecoder -import IPy - - -class DshellDecoder(DNSDecoder): - - def __init__(self): - DNSDecoder.__init__(self, - name='reservedips', - description='identify DNS resolutions that fall into reserved ip space', - filter='(port 53)', - author='bg', - cleanupinterval=10, - maxblobs=2, - ) - - # source: https://en.wikipedia.org/wiki/Reserved_IP_addresses - nets = ['0.0.0.0/8', # Used for broadcast messages to the current ("this") network as specified by RFC 1700, page 4. - # Used for local communications within a private network as - # specified by RFC 1918. - '10.0.0.0/8', - # Used for communications between a service provider and its - # subscribers when using a Carrier-grade NAT, as specified by - # RFC 6598. - '100.64.0.0/10', - # Used for loopback addresses to the local host, as specified - # by RFC 990. - '127.0.0.0/8', - # Used for autoconfiguration between two hosts on a single - # link when no IP address is otherwise specified - '169.254.0.0/16', - # Used for local communications within a private network as - # specified by RFC 1918 - '172.16.0.0/12', - # Used for the DS-Lite transition mechanism as specified by - # RFC 6333 - '192.0.0.0/29', - # Assigned as "TEST-NET" in RFC 5737 for use solely in - # documentation and example source code and should not be used - # publicly - '192.0.2.0/24', - # Used by 6to4 anycast relays as specified by RFC 3068 - '192.88.99.0/24', - # Used for local communications within a private network as - # specified by RFC 1918 - '192.168.0.0/16', - # Used for testing of inter-network communications between two - # separate subnets as specified in RFC 2544 - '198.18.0.0/15', - # Assigned as "TEST-NET-2" in RFC 5737 for use solely in - # documentation and example source code and should not be used - # publicly - '198.51.100.0/24', - # Assigned as "TEST-NET-3" in RFC 5737 for use solely in - # documentation and example source code and should not be used - # publicly - '203.0.113.0/24', - # Reserved for multicast assignments as specified in RFC 5771 - '224.0.0.0/4', - # Reserved for future use, as specified by RFC 6890 - '240.0.0.0/4', - # Reserved for the "limited broadcast" destination address, as - # specified by RFC 6890 - '255.255.255.255/32', - - '::/128', # Unspecified address - '::1/128', # loopback address to the local host. - '::ffff:0:0/96', # IPv4 mapped addresses - '100::/64', # Discard Prefix RFC 6666 - '64:ff9b::/96', # IPv4/IPv6 translation (RFC 6052) - '2001::/32', # Teredo tunneling - # Overlay Routable Cryptographic Hash Identifiers (ORCHID) - '2001:10::/28', - '2001:db8::/32', # Addresses used in documentation - '2002::/16', # 6to4 - 'fc00::/7', # Unique local address - 'fe80::/10', # Link-local address - 'ff00::/8', # Multicast - ] - - self.reservednets = [] - for net in nets: - self.reservednets.append(IPy.IP(net)) - self.domains = [] # list for known domains - - def inReservedSpace(self, ipaddress): - for net in self.reservednets: - if ipaddress in net: - return True - return False - - def decode_q(self, dns): - queried = "" - if dns.qd[0].type == dpkt.dns.DNS_A: - queried = queried + "A? %s" % (dns.qd[0].name) - if dns.qd[0].type == dpkt.dns.DNS_AAAA: - queried = queried + "AAAA? %s" % (dns.qd[0].name) - return queried - - def DNSHandler(self, conn, request, response, **kwargs): - anstext = '' - queried = '' - id = None - for dns in request, response: - if dns is None: - continue - id = dns.id - # DNS Question, update connection info with query - if dns.qr == dpkt.dns.DNS_Q: - conn.info(query=self.decode_q(dns)) - - # DNS Answer with data and no errors - elif (dns.qr == dpkt.dns.DNS_A and dns.rcode == dpkt.dns.DNS_RCODE_NOERR and len(dns.an) > 0): - - queried = self.decode_q(dns) - - answers = [] - for an in dns.an: - if an.type == dpkt.dns.DNS_A: - try: - if self.inReservedSpace(socket.inet_ntoa(an.ip)): - answers.append( - 'A: ' + socket.inet_ntoa(an.ip) + ' (ttl ' + str(an.ttl) + 's)') - except: - continue - elif an.type == dpkt.dns.DNS_AAAA: - try: - if self.inReservedSpace(socket.inet_ntop(socket.AF_INET6, an.ip6)): - answers.append( - 'AAAA: ' + socket.inet_ntop(socket.AF_INET6, an.ip6) + ' (ttl ' + str(an.ttl) + 's)') - except: - continue - else: - # un-handled type - continue - if queried != '': - anstext = ", ".join(answers) - - if anstext: # did we get an answer? - self.alert( - str(id) + ' ' + queried + ' / ' + anstext, **conn.info(response=anstext)) - - -if __name__ == '__main__': - dObj = DshellDecoder() - print dObj -else: - dObj = DshellDecoder() diff --git a/decoders/filter/asn-filter.py b/decoders/filter/asn-filter.py deleted file mode 100644 index 6abf064..0000000 --- a/decoders/filter/asn-filter.py +++ /dev/null @@ -1,100 +0,0 @@ -import dshell -import util -import netflowout - - -class DshellDecoder(dshell.TCPDecoder): - - def __init__(self, **kwargs): - self.sessions = {} - self.alerts = False - self.file = None - dshell.TCPDecoder.__init__(self, - name='asn-filter', - description='filter connections on autonomous system number (ASN)', - longdescription=""" -This decoder filters connections by autonomous system numbers/names (ASN). - -Chainable decoder used to filter TCP/UDP streams by ASNs. If no -downstream (+) decoder is used the netflow data will be printed to -the screen (when using --asn-filter_alerts). If used without specifying -a asn string, the asn-filter will filter nothing out and pass -everything onto the next decoder or print it. - -Examples: - - decode -d asn-filter --asn-filter_asn AS8075 --asn-filter_alerts - - This will print the connection info for all connections where - AS8075 is the ASN for either the server of client. - - decode -d asn-filter --asn-filter_asn Google --asn-filter_alerts - - This will print the connection info for all connections where - "Google" appeared in the ASN information. - - decode -d asn-filter+followstream --asn-filter_asn AS8075 - - This will filter the streams by ASN and feed them into the - followstream decoder. -""", - filter="ip or ip6", - author='twp/nl', - optiondict={ - 'asn': {'type': 'string', 'help': 'asn for client or server'}, - 'alerts': {'action': 'store_true'}}) - '''instantiate an decoder that will call back to us once the IP decoding is done''' - self.__decoder = dshell.IPDecoder() - self.out = netflowout.NetflowOutput() - self.chainable = True - - def decode(self, *args): - if len(args) is 3: - pktlen, pktdata, ts = args # orig_len,packet,ts format (pylibpcap) - else: # ts,pktdata (pypcap) - ts, pktdata = args - pktlen = len(pktdata) - '''do normal decoder stack to track session ''' - dshell.TCPDecoder.decode(self, pktlen, pktdata, ts) - '''our hook to decode the ip/ip6 addrs, then dump the addrs and raw packet to our callback''' - self.__decoder.IPHandler = self.__callback # set private decoder to our callback - self.__decoder.decode(pktlen, pktdata, ts, raw=pktdata) - - def __callback(self, addr, pkt, ts, raw=None, **kw): - '''substitute IPhandler for forwarding packets to subdecoders''' - if addr in self.sessions or (addr[1], addr[0]) in self.sessions: # if we are not passing this session, drop the packet - if self.subDecoder: - # make it look like a capture - self.subDecoder.decode(len(raw), str(raw), ts) - else: - self.dump(raw, ts) - - def connectionInitHandler(self, conn): - '''see if we have an ASN match and if so, flag this session for forwarding or dumping''' - m = self.__asnTest(conn) - if m: - self.sessions[conn.addr] = m - - def __asnTest(self, conn): - # If no ASN specified, pass all traffic through - if not self.asn: - return True - # check criteria - if self.asn.lower() in conn.clientasn.lower(): - return u'client {0}'.format(conn.clientasn) - if self.asn.lower() in conn.serverasn.lower(): - return u'server {0}'.format(conn.serverasn) - # no match - return None - - def connectionHandler(self, conn): - if conn.addr in self.sessions and self.alerts: - self.alert(self.sessions[conn.addr], **conn.info()) - - def connectionCloseHandler(self, conn): - if conn.addr in self.sessions: - del self.sessions[conn.addr] - -dObj = DshellDecoder() -if __name__ == "__main__": - print dObj diff --git a/decoders/filter/country.py b/decoders/filter/country.py deleted file mode 100644 index 921b168..0000000 --- a/decoders/filter/country.py +++ /dev/null @@ -1,125 +0,0 @@ -''' -@author: tparker -''' - -import dshell -import netflowout - - -class DshellDecoder(dshell.TCPDecoder): - - '''activity tracker ''' - - def __init__(self, **kwargs): - ''' - Constructor - ''' - self.sessions = {} - self.alerts = False - self.file = None - dshell.TCPDecoder.__init__(self, - name='country', - description='filter connections on geolocation (country code)', - longdescription=""" -country: filter connections on geolocation (country code) - -Chainable decoder to filter TCP/UDP streams on geolocation data. If no -downstream (+) decoders are specified, netflow data will be printed to -the screen. - -Mandatory option: - - --country_code: specify (2 character) country code to filter on - -Default behavior: - - If either the client or server IP address matches the specified country, - the stream will be included. - -Modifier options: - - --country_neither: Include only streams where neither the client nor the - server IP address matches the specified country. - - --country_both: Include only streams where both the client AND the server - IP addresses match the specified country. - - --country_notboth: Include streams where the specified country is NOT BOTH - the client and server IP. Streams where it is one or - the other may be included. - - -Example: - - decode -d country traffic.pcap -W USonly.pcap --country_code US - decode -d country+followstream traffic.pcap --country_code US --country_notboth -""", - filter="ip or ip6", - author='twp', - optiondict={ - 'code': {'type': 'string', 'help': 'two-char country code'}, - 'neither': {'action': 'store_true', 'help': 'neither (client/server) is in specified country'}, - 'both': {'action': 'store_true', 'help': 'both (client/server) ARE in specified country'}, - 'notboth': {'action': 'store_true', 'help': 'specified country is not both client and server'}, - 'alerts': {'action': 'store_true'} - } - ) - # instantiate a decoder that will call back to us once the IP decoding is done - self.__decoder = dshell.IPDecoder() - self.out = netflowout.NetflowOutput() - self.chainable = True - - def decode(self, *args): - if len(args) is 3: - pktlen, pktdata, ts = args - else: - ts, pktdata = args - pktlen = len(pktdata) - # do normal decoder stack to track session - dshell.TCPDecoder.decode(self, pktlen, pktdata, ts) - # our hook to decode the ip/ip6 addrs, then dump the addrs and raw packet to our callback - self.__decoder.IPHandler = self.__callback # set private decoder to our callback - self.__decoder.decode(pktlen, pktdata, ts, raw=pktdata) - - def __callback(self, addr, pkt, ts, raw=None, **kw): - '''substitute IPhandler for forwarding packets to subdecoders''' - if addr in self.sessions or (addr[1], addr[0]) in self.sessions: # if we are not passing this session, drop the packet - if self.subDecoder: - # make it look like a capture - self.subDecoder.decode(len(raw), str(raw), ts) - else: - self.dump(raw, ts) - - def connectionInitHandler(self, conn): - '''see if we have a country match and if so, flag this session for forwarding or dumping''' - m = self.__countryTest(conn) - if m: - self.sessions[conn.addr] = m - - def __countryTest(self, conn): - # If no country code specified, pass all traffic through - if not self.code: - return True - # check criteria - if self.neither and conn.clientcountrycode != self.code and conn.servercountrycode != self.code: - return 'neither ' + self.code - if self.both and conn.clientcountrycode == self.code and conn.servercountrycode == self.code: - return 'both ' + self.code - if self.notboth and ((conn.clientcountrycode == self.code) ^ (conn.servercountrycode == self.code)): - return 'not both ' + self.code - if not self.both and conn.clientcountrycode == self.code: - return 'client ' + self.code - if not self.both and conn.servercountrycode == self.code: - return 'server ' + self.code - # no match - return None - - def connectionHandler(self, conn): - if conn.addr in self.sessions and self.alerts: - self.alert(self.sessions[conn.addr], **conn.info()) - - def connectionCloseHandler(self, conn): - if conn.addr in self.sessions: - del self.sessions[conn.addr] - -dObj = DshellDecoder() diff --git a/decoders/filter/snort.py b/decoders/filter/snort.py deleted file mode 100644 index 8a79340..0000000 --- a/decoders/filter/snort.py +++ /dev/null @@ -1,209 +0,0 @@ -import dshell - - -class DshellDecoder(dshell.IPDecoder): - - def __init__(self): - dshell.IPDecoder.__init__(self, - name='snort', - description='filter packets by snort rule', - longdescription="""Chainable decoder to filter TCP/UDP streams by snort rule -rule is parsed by dshell, a limited number of options are supported: - currently supported rule options: - content - nocase - depth - offset - within - distance - -Mandatory option: - ---snort_rule: snort rule to filter by - -or - --snort_conf: snort.conf formatted file to read for multiple rules - -Modifier options: - ---snort_all: Pass only if all rules pass ---snort_none: Pass only if no rules pass ---snort_alert: Alert if rule matches? - -Example: -decode -d snort+followstream traffic.pcap --snort_rule 'alert tcp any any -> any any (content:"....."; nocase; depth .... )' - -""", - filter='ip or ip6', - author='twp', - optiondict={'rule': {'type': 'string', 'help': 'snort rule to filter packets'}, - 'conf': {'type': 'string', 'help': 'snort.conf file to read'}, - 'alerts': {'action': 'store_true', 'help': 'alert if rule matched'}, - 'none': {'action': 'store_true', 'help': 'pass if NO rules matched'}, - 'all': {'action': 'store_true', 'help': 'all rules must match to pass'} - } - ) - self.chainable = True - - def preModule(self): - rules = [] - if self.conf: - fh = file(self.conf) - rules = [r for r in (r.strip() for r in fh.readlines()) if len(r)] - fh.close() - else: - if not self.rule or not len(self.rule): - self.warn("No rule specified (--%s_rule)" % self.name) - else: - rules = [self.rule] - self.rules = [] - for r in rules: - try: - self.rules.append((self.parseSnortRule(r))) - except Exception, e: - self.error('bad snort rule "%s": %s' % (r, e)) - if self._DEBUG: - self._exc(e) - if self.subDecoder: - # we filter individual packets so session-based subdecoders will - # need this set - self.subDecoder.ignore_handshake = True - dshell.IPDecoder.preModule(self) - - def rawHandler(self, pktlen, pkt, ts, **kwargs): - kwargs['raw'] = pkt # put the raw frame in the kwargs - # continue decoding - return dshell.IPDecoder.rawHandler(self, pktlen, pkt, ts, **kwargs) - - def IPHandler(self, addr, pkt, ts, **kwargs): - '''check packets using filterfn here''' - raw = str( - kwargs['raw']) # get the raw frame for forwarding if we match - p = dshell.Packet(self, addr, pkt=str(pkt), ts=ts, **kwargs) - a = [] - match = None - for r, msg in self.rules: - if r(p): # if this rule matched - match = True - if msg: - a.append(msg) # append rule message to alerts - if self.none or not self.all: - break # unless matching all, one match does it - else: # last rule did not match - match = False - if self.all: - break # stop once no match if all - - # all rules processed, match = state of last rule match - if (match is not None) and ((match and not self.none) or (self.none and not match)): - self.decodedbytes += len(str(pkt)) - self.count += 1 - if self.alerts: - self.alert(*a, **p.info()) - if self.subDecoder: - # decode or dump packet - self.subDecoder.decode(len(raw), raw, ts) - else: - self.dump(len(raw), raw, ts) - - def parseSnortRule(self, ruletext): - '''returns a lambda function that can be used to filter traffic and the alert message - this function will expect a Packet() object and return True or False''' - KEYWORDS = ( - 'msg', 'content') # rule start, signal when we process all seen keywords - msg = '' - f = [] - rule = ruletext.split(' ', 7) - (a, proto, sip, sp, arrow, dip, dp) = rule[:7] - if len(rule) > 7: - rule = rule[7] - else: - rule = None - if a != 'alert': - raise Exception('Must be alert rule') - f.append('p.proto == "' + proto.upper() + '"') - if sip != 'any': - f.append('p.sip == "' + sip + '"') - if dip != 'any': - f.append('p.dip == "' + dip + '"') - if sp != 'any': - f.append('p.sport == ' + sp) - if dp != 'any': - f.append('p.dport == ' + dp) - f = ['(' + (' and '.join(f)) + ')'] # create header condition - if rule: - # split between () and split on ; - rule = rule.strip('()').split(';') - last = None # no last match - while rule: - try: - k, v = rule.pop(0).strip().split(':', 1) - except: - continue - if k.lower() == 'content': # reset content match - content = v.strip().strip('"') - # hex bytes? - if content.startswith('|') and content.endswith('|'): - content = ''.join( - '\\x' + c for c in content.strip('|').split()) - nocase = depth = offset = distance = within = None - while rule: - r = rule[0].strip() - if ':' in r: - k, v = r.split(':', 1) - else: - k, v = r, None - k = k.lower() - if k in KEYWORDS: - break # next rule part - elif k == 'nocase': - nocase = True - elif k == 'depth': - depth = int(v) - elif k == 'offset': - offset = int(v) - elif k == 'distance': - distance = int(v) - elif k == 'within': - within = int(v) - rule.pop(0) # remove this keyword:valuea - # add coerce to lower if nocase? - if nocase: - nocase = '.lower()' - else: - nocase = '' - # start,end offsets of find(), maybe number or result of - # another find() - st, end = offset, depth - # if we have a last content match, use the distance/within kws - if last: - # within means this match has to be within X from - # previous+distance, so use previous as offset and within - # as depth - if within: - # set to last match and X from last match - st, end = last, last + '+' + str(within) - # distance means the next match must be AT LEAST X from the - # last - if distance: - # set start to last match+distance - st = last + '+' + str(distance) - # else use the offset/depth values as given - last = 'p.pkt' + nocase + \ - '.find(' + "'" + content + "'" + nocase + ',' + \ - str(st) + ',' + str(end) + ') != -1' - if k.lower() == 'msg': - msg = v.strip().strip('"') # get alert message - if last: - f.append('(' + last + ')') - f = ' and '.join(f) - self.debug('%s\t%s\t"%s"' % (ruletext, f, msg)) - return eval('lambda(p): ' + f), msg # return fn and msg - - -if __name__ == '__main__': - dObj = DshellDecoder() - print dObj -else: - dObj = DshellDecoder() diff --git a/decoders/filter/track.py b/decoders/filter/track.py deleted file mode 100644 index 3d83d7b..0000000 --- a/decoders/filter/track.py +++ /dev/null @@ -1,135 +0,0 @@ -''' -@author: tparker -''' - -import dshell -import util - - -class DshellDecoder(dshell.TCPDecoder): - - '''activity tracker ''' - - def __init__(self, **kwargs): - ''' - Constructor - ''' - self.sources = [] - self.targets = [] - self.sessions = {} - self.alerts = False - self.file = None - dshell.TCPDecoder.__init__(self, - name='track', - description='tracked activity recorder', - longdescription='''captures all traffic to/from target while a specific connection to the target is up - specify target(s) ip and/or port as --track_target=ip:port,ip... - --track_source=ip,ip.. can be used to limit to specified sources - --track_alerts will turn on alerts for session start/end''', - filter="ip", - author='twp', - optiondict={'target': {'action': 'append'}, - 'source': {'action': 'append'}, - 'alerts': {'action': 'store_true'}}) - self.chainable = True - - '''instantiate an IPDecoder and replace the IPHandler - to decode the ip/ip6 addr and then pass the packet - to _IPHandler, which will write the packet if in addr is in session''' - self.__decoder = dshell.IPDecoder() - - def preModule(self): - '''parse the source and target lists''' - if self.target: - for tstr in self.target: - targets = util.strtok(tstr, as_list=True)[0] - for t in targets: - try: - parts = t.split(':') - if len(parts) == 2: - ip, port = parts # IP:port - else: - ip, port = t, None # IPv6 addr - except: - ip, port = t, None # IP - if ip == '': - ip = None # :port - self.targets.append((ip, port)) - if self.source: - for sstr in self.source: - sources = util.strtok(sstr, as_list=True)[0] - for ip in sources: - self.sources.append(ip) - dshell.TCPDecoder.preModule(self) - - def decode(self, *args): - if len(args) is 3: - pktlen, pktdata, ts = args # orig_len,packet,ts format (pylibpcap) - else: # ts,pktdata (pypcap) - ts, pktdata = args - pktlen = len(pktdata) - '''do normal decoder stack to track session ''' - dshell.TCPDecoder.decode(self, pktlen, pktdata, ts) - '''our hook to decode the ip/ip6 addrs, then dump the addrs and raw packet - to our session check routine''' - self.__decoder.IPHandler = self.__callback # set private decoder to our callback - self.__decoder.decode(pktlen, pktdata, ts, raw=pktdata) - - def __callback(self, addr, pkt, ts, raw=None, **kw): - '''check to see if this packet is to/from an IP in a session, - if so write it. the packet will be passed in the 'raw' kwarg''' - if addr[0][0] in self.sessions: - ip = addr[0][0] # source ip - elif addr[1][0] in self.sessions: - ip = addr[1][0] # dest ip - else: - return # not tracked - for s in self.sessions[ip].values(): - s.sessionpackets += 1 - s.sessionbytes += len(raw) # actual captured data len - # dump the packet or sub-decode it - if self.subDecoder: - # make it look like a capture - self.subDecoder.decode(len(raw), str(raw), ts) - else: - self.dump(raw, ts) - - def connectionInitHandler(self, conn): - '''see if dest ip and/or port is in target list and (if a source list) - source ip is in source list - if so, put the connection in the tracked-session list by dest ip - if a new connection to the target comes in from an allowed source, - the existing connection will still be tracked''' - ((sip, sport), (dip, dport)) = conn.addr - sport, dport = str(sport), str(dport) - if ((dip, dport) in self.targets) or ((dip, None) in self.targets) or ((None, dport) in self.targets): - if not self.sources or (sip in self.sources): - s = self.sessions.setdefault(dip, {}) - s[conn.addr] = conn - if self.alerts: - self.alert('session started', **conn.info()) - conn.info(sessionpackets=0, sessionbytes=0) - - def connectionHandler(self, conn): - '''if a connection to a tracked-session host, alert and write if no subdecoder''' - if self.alerts: - if conn.serverip in self.sessions: - self.alert('inbound', **conn.info()) - if conn.clientip in self.sessions: - self.alert('outbound', **conn.info()) - if conn.serverip in self.sessions or conn.clientip in self.sessions: - if not self.subDecoder: - self.write(conn) - - def connectionCloseHandler(self, conn): - '''close the tracked session if the initiating connection is closing - make sure the conn in the session list matches, - as we may have had more incoming connections to the same ip during the session''' - if conn.serverip in self.sessions and conn.addr in self.sessions[conn.serverip]: - if self.alerts: - self.alert('session ended', **conn.info()) - del self.sessions[conn.serverip][conn.addr] - if not self.sessions[conn.serverip]: - del self.sessions[conn.serverip] - -dObj = DshellDecoder() diff --git a/decoders/flows/large-flows.py b/decoders/flows/large-flows.py deleted file mode 100644 index a954aaa..0000000 --- a/decoders/flows/large-flows.py +++ /dev/null @@ -1,36 +0,0 @@ -import dshell -import netflowout - - -class DshellDecoder(dshell.TCPDecoder): - - def __init__(self): - dshell.TCPDecoder.__init__(self, - name='large-flows', - description='display netflows that have at least 1MB transferred', - filter='tcp', - author='bg', - optiondict={'size': { - 'type': 'float', 'default': 1, 'help': 'number of megabytes transferred'}} - ) - self.out = netflowout.NetflowOutput() - self.min = 1048576 # 1MB - - def preModule(self): - if self.size <= 0: - self.warn( - "Cannot have a size that's less than or equal to zero. (size: %s)" % (self.size)) - self.size = 1 - self.min = 1048576 * self.size - self.debug("Input: %s, Final size: %s bytes" % (self.size, self.min)) - - def connectionHandler(self, conn): - if (conn.clientbytes + conn.serverbytes) >= self.min: - self.alert(**conn.info()) - - -if __name__ == '__main__': - dObj = DshellDecoder() - print dObj -else: - dObj = DshellDecoder() diff --git a/decoders/flows/long-flows.py b/decoders/flows/long-flows.py deleted file mode 100644 index 6fefcb2..0000000 --- a/decoders/flows/long-flows.py +++ /dev/null @@ -1,29 +0,0 @@ -import dshell -import netflowout - - -class DshellDecoder(dshell.TCPDecoder): - - def __init__(self): - self.len = 5 - dshell.TCPDecoder.__init__(self, - name='long-flows', - description='display netflows that have a duration of at least 5mins', - filter='(tcp or udp)', - author='bg', - optiondict={ - 'len': {'type': 'int', 'default': 5, 'help': 'set minimum connection time to alert on, in minutes [default: 5 mins]'}, - } - ) - self.out = netflowout.NetflowOutput() - - def connectionHandler(self, conn): - if (conn.endtime - conn.starttime) >= (60 * self.len): - self.alert(**conn.info()) - - -if __name__ == '__main__': - dObj = DshellDecoder() - print dObj -else: - dObj = DshellDecoder() diff --git a/decoders/flows/netflow.py b/decoders/flows/netflow.py deleted file mode 100644 index a563ae2..0000000 --- a/decoders/flows/netflow.py +++ /dev/null @@ -1,37 +0,0 @@ -import dshell -import netflowout - - -class DshellDecoder(dshell.TCPDecoder): - - def __init__(self): - dshell.TCPDecoder.__init__(self, - name='netflow', - description='generate netflow information from pcap', - longdescription='generate netflow information from pcap', - filter='(tcp or udp)', - author='bg', - # grouping for output module - optiondict={'group': dict()} - ) - self.out = netflowout.NetflowOutput() - - def preModule(self): - # pass grouping to output module - if self.group: - self.out.group = self.group.split(',') - dshell.TCPDecoder.preModule(self) - - def connectionHandler(self, conn): - self.alert(**conn.info()) - - def postModule(self): - self.out.close() # write flow groups if grouping - dshell.TCPDecoder.postModule(self) - - -if __name__ == '__main__': - dObj = DshellDecoder() - print dObj -else: - dObj = DshellDecoder() diff --git a/decoders/flows/reverse-flow.py b/decoders/flows/reverse-flow.py deleted file mode 100644 index 84c2e45..0000000 --- a/decoders/flows/reverse-flow.py +++ /dev/null @@ -1,68 +0,0 @@ -import dshell - -class DshellDecoder(dshell.TCPDecoder): - - '''Reverse-Flow Decoder''' - - def __init__(self): - dshell.TCPDecoder.__init__(self, - name='reverse-flow', - description='Generate an alert if the client transmits more data than the server', - longdescription=""" - - Generate an alert when a client transmits more data than the server. - - Additionally, the user can specify a threshold. This means that an alert - will be generated if the client transmits more than three times as much data - as the server. - - The default threshold value is 3.0, meaning that any client transmits - more than three times as much data as the server will generate an alert. - - Examples: - 1) decode -d reverse-flow - Generates an alert for client transmissions that are three times - greater than the server transmission. - - 2) decode -d reverse-flow --reverse-flow_threshold 61 - Generates an alert for all client transmissions that are 61 times - greater than the server transmission - - 3) decode -d reverse-flow --reverse-flow_threshold 61 --reverse-flow_zero - Generates an alert for all client transmissions that are 61 times greater - than the server transmission. - - - - """, - filter="tcp or udp", - author='me', - optiondict={ - 'threshold':{'type':'float', 'default':3.0, - 'help':'Alerts if client transmits more than threshold times the data of the server'}, - 'minimum':{'type':'int', 'default':0, 'help':'alert on client transmissions larger than min bytes [default: 0]'}, - 'zero':{'action':'store_true', 'default':False, 'help':'alert if the server transmits zero bytes [default: false]'}, - } - ) - - def preModule(self): - if self.threshold < 0: - self.warn( - "Cannot have a negative threshold. (threshold: {0})".format(self.threshold)) - self.threshold = 3.0 - elif not self.threshold: - self.warn( - "Displaying all client-server transmissions (threshold: {0})".format(self.threshold)) - - def connectionHandler(self, conn): - if conn.clientbytes < self.minimum: - return - - if self.zero or (conn.serverbytes and float(conn.clientbytes)/conn.serverbytes > self.threshold): - self.alert('client sent {:>6.2f} more than the server'.format(conn.clientbytes/float(conn.serverbytes)), **conn.info()) - -if __name__ == '__main__': - dObj = DshellDecoder() - print dObj -else: - dObj = DshellDecoder() diff --git a/decoders/ftp/ftp.py b/decoders/ftp/ftp.py deleted file mode 100644 index dbfb055..0000000 --- a/decoders/ftp/ftp.py +++ /dev/null @@ -1,296 +0,0 @@ -############################################## -# File Transfer Protocol (FTP) -# -# Goes through TCP connections and tries to find FTP control channels and -# associated data channels. Optionally, it will write out any file data it -# sees into a separate directory. -# -# More specifically, it sets up an initial BPF that looks for control channels. -# As it finds them, it updates the BPF to include the data connection along -# ephemeral ports. -# -# If a data connection is seen, it prints a message indicating the user, pass, -# and file requested. If the dump flag is set, it also dumps the file into the -# __OUTDIR directory. -############################################## - -import dshell -import os -import re - -class DshellDecoder(dshell.TCPDecoder): - - def __init__(self): - dshell.TCPDecoder.__init__(self, - name='ftp', - description='ftp', - filter="tcp", - author='amm', - optiondict={ - 'port':{'type':'string', - 'default':'21', - 'help':'Port (or ports) to watch for control connections (Default: 21)'}, - 'dump':{'action':'store_true','help':'Dump files (Default: Off)'} - } - ) - - # Constants for channel type - __CTRLCONN = 0 - __DATACONN = 1 - __OUTDIR = 'ftpout' - - # Dynamically change the BPF filter - # to allow processing of data transfer channels - def __updatebpf(self): - dynfilters = [ '(host %s and host %s)' % self.conns[x]['tempippair'] for x in self.conns.keys() if 'tempippair' in self.conns[x] and self.conns[x]['tempippair'] != None ] - dynfilters.extend( [ '(host %s and port %d)' % (a,p) for a,p in self.datachan.keys() ] ) - self.filter = 'tcp and (%s%s)' % ( - ' or '.join(['port %d'%p for p in self.ctrlports]), - ' or '+' or '.join(dynfilters) if len(dynfilters) else '' - ) - self.debug("Setting BPF filter to: %s" % self.filter) - if 'capture' in dir(self): - self.capture.setfilter(self.filter,1) - - def preModule(self): - # Convert port specification from string to list of integers - self.ctrlports = [int(p) for p in self.port.split(',')] - self.datachan = {} # Dictionary of control channels indexed by data channel (host, port) tuples - self.conns = {} # Dictionary of information about connections - self.__updatebpf() # Set initial bpf - - # Attempt to create output directory - if self.dump: - self.__OUTDIR = self.__mkoutdir(self.__OUTDIR) - self.warn("Using output directory: %s" % self.__OUTDIR) - - def connectionInitHandler(self, conn): - # - # Setup conn info for New Data Channel - # - if conn.serverport in self.ctrlports: - self.conns[conn.addr] = { 'mode': self.__CTRLCONN, 'user':'', 'pass':'', 'path':[], 'lastcommand':'', 'filedata':None, 'file':('', '', '')} - elif self.dump and (conn.clientip, conn.clientport) in self.datachan: - self.conns[conn.addr] = { 'mode': self.__DATACONN, 'ctrlchan': self.datachan[(conn.clientip, conn.clientport)] } - elif self.dump and (conn.serverip, conn.serverport) in self.datachan: - self.conns[conn.addr] = { 'mode': self.__DATACONN, 'ctrlchan': self.datachan[(conn.serverip, conn.serverport)] } - elif self.dump: - # No match. Track as a DATACONN with unknown CTRLCHAN as it may be - # a passive mode transfer that we don't have port info on yet. - self.conns[conn.addr] = { 'mode': self.__DATACONN, 'ctrlchan': None } - - def connectionCloseHandler(self, conn): - info = self.conns[conn.addr] - ######################################################### - # Upon close of data channels, store file content in - # 'filedata' associated with the ctrlchan. - # ctrlchan will then write it out to disk after it knows - # for sure the file name - # - if self.dump and info['mode'] == self.__DATACONN: - # Associated Control Channel - if info['ctrlchan'] == None: - if (conn.clientip, conn.clientport) in self.datachan: - info['ctrlchan'] = self.datachan[(conn.clientip, conn.clientport)] - if (conn.serverip, conn.serverport) in self.datachan: - info['ctrlchan'] = self.datachan[(conn.serverip, conn.serverport)] - ctrlchan = self.conns[info['ctrlchan']] - # Add data to control channel - ctrlchan['filedata'] = conn.data() - # Update BPF and DataChan Knowledge - if (conn.serverip, conn.serverport) == ctrlchan['datachan'] or (conn.clientip, conn.clientport) == ctrlchan['datachan']: - del self.datachan[ctrlchan['datachan']] - ctrlchan['datachan'] = None - self.__updatebpf() - # Remove Data Channel from tracker - del self.conns[conn.addr] - - elif info['mode'] == self.__CTRLCONN: - if 'file' not in info or info['file'] == None: - del self.conns[conn.addr] - - def postModule(self): - for x in self.conns: - info = self.conns[x] - if self.dump and 'filedata' in info and info['filedata']: - origname = info['file'][0] + '_' + os.path.join(*info['file'][1:3]) - outname = self.__localfilename(self.__OUTDIR, origname) - fh = open(outname, 'w') - fh.write(info['filedata']) - fh.close() - numbytes = len(info['filedata']) - info['filedata'] = None - info['outfile'] = outname - #info.update(conn.info()) - msg = 'User: %s, Pass: %s, %s File: %s (Incomplete: %d bytes written to %s)' % (info['user'], info['pass'], info['file'][0], os.path.join(*info['file'][1:3]), numbytes, os.path.basename(outname)) - self.alert(msg, **info) - - - - def blobHandler(self, conn, blob): - - info = self.conns[conn.addr] - data = blob.data() - - # - # Data Channel - # - if info['mode'] == self.__DATACONN: - return - - - # - # Control Channel - # - - # Client Commands - if blob.direction == 'cs': - - try: - if ' ' not in data: (command, param) = (data.rstrip(), '') - else: (command, param) = data.rstrip().split(' ', 1) - command = command.upper() - info['lastcommand'] = command - info['request_time'] = blob.starttime - except: - return - - if command == 'USER': - info['user'] = param - elif command == 'PASS': - info['pass'] = param - elif command == 'CWD': - info['path'].append(param) - elif command == 'PASV' or command == 'EPSV': - if self.dump: - # Temporarily store the pair of IP addresses - # to open up the bpf filter until blobHandler processes - # the response with the full IP/Port information - # (Note: Due to the way blob processing works, we don't get this information - # until after the data channel is established) - info['tempippair'] = tuple(sorted((conn.clientip, conn.serverip))) - self.__updatebpf() - # - # For file transfers (including LIST), store tuple (Direction, Path, Filename) in info['file'] - # - elif command == 'LIST': - if param == '': - info['file'] = ( 'RETR', os.path.normpath(os.path.join(*info['path'])) if len(info['path']) else '', 'LIST' ) - else: - info['file'] = ( 'RETR', os.path.normpath(os.path.join(os.path.join(*info['path']), param)) if len(info['path']) else '', 'LIST' ) - elif command == 'RETR': - info['file'] = ( 'RETR', os.path.normpath(os.path.join(*info['path'])) if len(info['path']) else '', param ) - elif command == 'STOR': - info['file'] = ( 'STOR', os.path.normpath(os.path.join(*info['path'])) if len(info['path']) else '', param ) - - # Responses - else: - info['response_time'] = blob.endtime - # - # Rollback directory change unless 2xx response - # - if info['lastcommand'] == 'CWD' and data[0] != '2': info['path'].pop() - # - # Write out files upon resonse to transfer commands - # - if info['lastcommand'] in ('LIST', 'RETR', 'STOR'): - if self.dump and info['filedata']: - origname = info['file'][0] + '_' + os.path.join(*info['file'][1:3]) - outname = self.__localfilename(self.__OUTDIR, origname) - fh = open(outname, 'w') - fh.write(info['filedata']) - fh.close() - numbytes = len(info['filedata']) - info['filedata'] = None - info['outfile'] = outname - info.update(conn.info()) - msg = 'User: %s, Pass: %s, %s File: %s (%d bytes written to %s)' % (info['user'], info['pass'], info['file'][0], os.path.join(*info['file'][1:3]), numbytes, os.path.basename(outname)) - else: - info.update(conn.info()) - msg = 'User: %s, Pass: %s, %s File: %s' % (info['user'], info['pass'], info['file'][0], os.path.join(*info['file'][1:3])) - if data[0] not in ('1','2'): msg += ' (%s)' % data.rstrip() - info['ts'] = info['response_time'] - (info['Direction'], info['Path'], info['Filename']) = info['file'] - del info['file'] - self.alert(msg, **info) - info['file'] = None - # - # Handle EPSV mode port setting - # - if info['lastcommand'] == 'EPSV' and data[0] == '2': - ret = re.findall('\(\|\|\|\d+\|\)', data) - if ret: - tport = int(ret[0].split('|')[3]) - info['datachan'] = (conn.serverip, tport) - if self.dump: - self.datachan[(conn.serverip, tport)] = conn.addr - info['tempippair'] = None - self.__updatebpf() - - # - # Look for ip/port information, assuming PSV response - # - ret = re.findall('\d+,\d+,\d+,\d+,\d+\,\d+', data) - if len(ret)==1: - tip, tport = self.calculateTransfer(ret[0]) # transfer ip, transfer port - info['datachan'] = (tip, tport) # Update this control channel's knowledge of currently working data channel - if self.dump: - self.datachan[(tip,tport)] = conn.addr # Update decoder's global datachan knowledge - info['tempippair'] = None - self.__updatebpf() - - - def calculateTransfer(self,val): - # calculate passive FTP data port - tmp = val.split(',') - ip = '.'.join(tmp[:4]) - port = int(tmp[4])*256 + int(tmp[5]) - return ip, port - - # - # Create output directory. Returns full path to output directory. - # - def __mkoutdir(self, outdir): - path = os.path.realpath(outdir) - if os.path.exists(path): return path - try: - os.mkdir(path) - return path - except OSError: - pass # most likely a permission denied issue, continue and try system temp directory - except: - raise # other errors, abort - if os.path.exists('/tmp'): path = os.path.realpath(os.path.join('/tmp', outdir)) - if os.path.exists(path): return path - try: - os.mkdir(path) - return path - except: - raise - - # - # Generate a local (extracted) filename based on the original - # - def __localfilename(self, path, origname): - tmp = origname.replace("\\", "_") - tmp = tmp.replace("/", "_") - tmp = tmp.replace(":", "_") - localname = '' - for c in tmp: - if ord(c) > 32 and ord(c) < 127: - localname += c - else: - localname += "%%%02X" % ord(c) - localname = path + '/' + localname - postfix = '' - i = 0 - while os.path.exists(localname+postfix): - i += 1 - postfix = "_%02d" % i - return localname+postfix - -if __name__=='__main__': - dObj = DshellDecoder() - print dObj -else: - dObj = DshellDecoder() diff --git a/decoders/http/flash-detect.py b/decoders/http/flash-detect.py deleted file mode 100644 index 59eb255..0000000 --- a/decoders/http/flash-detect.py +++ /dev/null @@ -1,236 +0,0 @@ -import util -import hashlib -import os -from httpdecoder import HTTPDecoder - - -class DshellDecoder(HTTPDecoder): - - # Constant for dump directory - __OUTDIR = 'flashout' - - # Constants for MD5sum option - NOMD5 = 0 - MD5 = 1 - MD5_EXPLICIT_FILENAME = 2 - - def __init__(self): - HTTPDecoder.__init__(self, - name='flash-detect', - description='Detects successful Flash file download.', - filter='tcp and (port 80 or port 8080 or port 8000)', - filterfn=lambda ((sip, sp), (dip, dp)): sp in ( - 80, 8000, 8080) or dp in (80, 8000, 8080), - optiondict={ - 'dump': {'action': 'store_true', 'help': '''\ -Dump the flash file to a file based off its name, md5sum (if specified), or -its URI. The file is dumped to the local directory "flashout". The file -extension is ".flash" to prevent accidental execution.''' - }, - 'md5sum': {'type': 'int', 'default': 0, 'help': '''\ -Calculate and print the md5sum of the file. There are three options: - 0: (default) No md5sum calculations or labeling - - 1: Calculate md5sum; Print out md5sum in alert; Name all dumped files by -their md5sum (must be used with 'dump' option) - - 2: Calculate md5sum; Print out md5sum in alert; If found, a file's explicitly -listed save name (found in 'content-disposition' HTTP header) will be used -for file dump name instead of md5sum. - -Any other numbers will be ignored and the default action will be used.''' - } - }, - longdescription='''\ -flash-detect identifies HTTP requests where the server response contains a Flash -file. Many exploit kits utilize Flash to deliver exploits to potentially vulnerable -browsers. If a flash file is successfully downloaded, an alert will occur stating -the full URL of the downloaded file, its content-type, and (optionally) its md5sum. - -Usage Examples: -=============== - Search all pcap files for Flash file downloads, and upon detection, calculate - and print alerts containing the md5sum to screen: - - decode -d flash-detect --flash-detect_md5sum=1 *.pcap - - If you wanted to save every detected Flash file to a local directory - "./flashout/" with its md5sum as the file name: - - decode -d flash-detect --flash-detect_md5sum=1 --flash-detect_dump *.pcap - The output directory can be changed by modifying the `__OUTDIR` variable. - - An example of a real pcap file, taken from - http://malware-traffic-analysis.net/2014/12/12/index.html: - decode -d flash-detect --flash-detect_md5sum=1 2014-12-12-Nuclear-EK-traffic.pcap - - The following text should be displayed in the output, and the md5sum - can be checked on a site like virustotal: -** yquesrerman.ga/AwoVG1ADAw4OUhlVDlRTBQoHRUJTXVYOUVYaAwtGXFRVVFxXVwBOVRtA (application/octet-stream) md5sum: 9b3ad66a2a61e8760602d98b537b7734 ** - -Implementation Logic -==================== - -1. Check if the HTTP response status is 200 OK - -2. Test the content-type of the HTTP response for the follwing strings: - 'application/x-shockwave-flash' - 'application/octet-stream' - 'application/vnd.adobe.flash-movie' - -3. Test filedownload following known Flash magic byte substrings: - 'CWS' - 'ZWS' - 'FWS' - -Note: Encoded or obfuscated flash files will *not* be detected. - -Chainable - -flash-detect is chainable. If a connection contains an HTTP response with a -successful Flash file download, then the entire connection (in the case of a -connectionHandler), and the request, response, requesttime, and responsetime -(in the case of an HTTPHandler) is/are passed to the subDecoders for additional -processing. Undetected or non-Flash files are dropped. -''', - author='ekilmer', - ) - self.chainable = True - - def preModule(self): - # Attempt to create output directory - if self.dump: - self.__OUTDIR = self.__mkoutdir(self.__OUTDIR) - self.log("Using output directory: {0}".format(self.__OUTDIR)) - - def HTTPHandler(self, conn, request, response, requesttime, responsetime): - if response and response.status != '200': - return - - content_type = util.getHeader(response, 'content-type') - if content_type not in ('application/x-shockwave-flash', - 'application/octet-stream', - 'application/vnd.adobe.flash-movie'): - return - - # Check for known flash file header characters - if not response.body.startswith(('CWS', 'ZWS', 'FWS')): - return - - host = util.getHeader(request, 'host') - # Grab file info as dict with keys: 'file_name', 'md5sum', 'uri' - file_info = self.get_file_info(request, response) - if self.md5sum == self.MD5 or self.md5sum == self.MD5_EXPLICIT_FILENAME: - # Print MD5 sum in the alert - self.alert('{0}{1} ({2}) md5sum: {3}'.format(host, request.uri, content_type, - file_info['md5sum']), **conn.info()) - else: - self.alert('{0}{1} ({2})'.format(host, request.uri, content_type), **conn.info()) - - # Dump the file if chosen - if self.dump: - # Name output files based on options - if self.md5sum == self.MD5: - origname = file_info['md5sum'] - # Check for explicitly listed filename - elif file_info['file_name']: - origname = file_info['file_name'] - # If explicit name not found, but still want MD5, give it MD5 - elif self.md5sum == self.MD5_EXPLICIT_FILENAME: - origname = file_info['md5sum'] - # Else name the file by its URI (which can be long) - else: - origname = file_info['uri'] - outname = self.__localfilename(self.__OUTDIR, origname) - with open('{0}.flash'.format(outname), 'wb') as outfile: - outfile.write(response.body) - - # Pass to subdecoder if necessary - if 'HTTPHandler' in dir(self.subDecoder): - self.subDecoder.HTTPHandler(conn, request, response, requesttime, responsetime) - elif 'connectionHandler' in dir(self.subDecoder): - self.subDecoder.connectionHandler(conn) - - def get_file_info(self, request, response): - """Checks for an explicitly listed file name. Returns a dictionary containing the - explicitly listed filename (if present), the URI, and an md5sum (if requested) - """ - file_info = {'file_name': '', 'uri': '', 'md5sum': ''} - - content = util.getHeader(response, 'content-disposition') - if content and 'filename' in content: - # RFC 1806: content contains a string with parameters separated by semi-colons - text = content.split(';') - for parm in text: - if parm.strip().startswith('filename='): - file_info['file_name'] = parm.split('filename=', 1)[1] - - # CAVEAT: When the URI is very long and it is used as a filename in a dump, - # then the file name may become unwieldy - file_info['uri'] = request.uri - - if self.md5sum == self.MD5 or self.md5sum == self.MD5_EXPLICIT_FILENAME: - file_info['md5sum'] = self.__body_md5(response) - - return file_info - - def __body_md5(self, response): - """Calculate the MD5sum(hex) of the body portion of the response.""" - if len(response.body) > 0: - return hashlib.md5(response.body.rstrip('\0')).hexdigest() - else: - self.warn("Nothing to hash") - return '' - - def __mkoutdir(self, outdir): - """Creates output directory. Returns full path to output directory.""" - path = os.path.realpath(outdir) - if os.path.exists(path): - return path - try: - os.mkdir(path) - return path - except OSError: - # most likely a permission denied issue, continue and try system temp directory - pass - except: - self.warn('Unable to create a directory for file dump') - # other errors, abort - raise - - # Trying temp directory - if os.path.exists('/tmp'): - path = os.path.realpath(os.path.join('/tmp', outdir)) - if os.path.exists(path): - return path - try: - os.mkdir(path) - return path - except: - self.warn('Unable to create a directory for file dump') - raise - - def __localfilename(self, path, origname): - """Generate a local (extracted) filename based on the original""" - tmp = origname.replace('\\', '_') - tmp = tmp.replace('/', '_') - tmp = tmp.replace(':', '_') - localname = '' - for c in tmp: - if ord(c) > 32 and ord(c) < 127: - localname += c - else: - localname += '%{0:02X}'.format(ord(c)) - localname = '{0}/{1}'.format(path, localname) - postfix = '' - i = 0 - while os.path.exists(localname+postfix): - i += 1 - postfix = '_{0:02d}'.format(i) - return localname+postfix - -if __name__ == '__main__': - dObj = DshellDecoder() - print dObj -else: - dObj = DshellDecoder() diff --git a/decoders/http/httpdump.py b/decoders/http/httpdump.py deleted file mode 100644 index 264cb42..0000000 --- a/decoders/http/httpdump.py +++ /dev/null @@ -1,153 +0,0 @@ -import dshell -import util -import hashlib -import urllib -import re -import colorout - -from httpdecoder import HTTPDecoder - - -class DshellDecoder(HTTPDecoder): - - def __init__(self): - HTTPDecoder.__init__(self, - name='httpdump', - description='Dump useful information about HTTP sessions', - filter='tcp and (port 80 or port 8080 or port 8000)', - filterfn=lambda ((sip, sp), (dip, dp)): sp in ( - 80, 8000, 8080) or dp in (80, 8000, 8080), - author='amm', - optiondict={ - 'maxurilen': {'type': 'int', 'default': 30, 'help': 'Truncate URLs longer than max len. Set to 0 for no truncating. (default: 30)'}, - 'maxpost': {'type': 'int', 'default': 1000, 'help': 'Truncate POST body longer than max chars. Set to 0 for no truncating. (default: 1000)'}, - 'showcontent': {'action': 'store_true', 'help': 'Display response BODY.'}, - 'showhtml': {'action': 'store_true', 'help': 'Display response BODY only if HTML.'}, - 'urlfilter': {'type': 'string', 'default': None, 'help': 'Filter to URLs matching this regex'}, - }, - ) - self.out = colorout.ColorOutput() - # Disable auto-gunzip as we want to indicate content that was - # compressed in the output - self.gunzip = False - - def HTTPHandler(self, conn, request, response, requesttime, responsetime): - host = '' - loc = '' - uri = '' - lastmodified = '' - - #request_time, request, response = self.httpDict[conn.addr] - - # extract method,uri,host from response - host = util.getHeader(request, 'host') - if host == '': - host = conn.serverip - - try: - status = response.status - except: - status = '' - try: - reason = response.reason - except: - reason = '' - - if self.urlfilter: - if not re.search(self.urlfilter, host + request.uri): - return - - if '?' in request.uri: - [uri_location, uri_data] = request.uri.split('?', 1) - else: - uri_location = request.uri - uri_data = '' - - if self.maxurilen > 0 and len(uri_location) > self.maxurilen: - uri_location = uri_location[:self.maxurilen] + '[truncated]' - else: - uri_location = uri_location - - if response == None: - response_message = "%s (%s) %s%s" % ( - request.method, 'NO RESPONSE', host, uri_location) - else: - response_message = "%s (%s) %s%s (%s)" % ( - request.method, response.status, host, uri_location, util.getHeader(response, 'content-type')) - urlParams = util.URLDataToParameterDict(uri_data) - postParams = util.URLDataToParameterDict(request.body) - # If URLData parser only returns a single element with null value, it's probably an eroneous evaluation. Most likely base64 encoded payload ending in an '=' character. - if len(postParams)==1 and postParams[postParams.keys()[0]] == '\x00': - postParams = None - - clientCookies = self._parseCookies(util.getHeader(request, 'cookie')) - serverCookies = self._parseCookies( - util.getHeader(response, 'set-cookie')) - - self.alert(response_message, - urlParams=urlParams, postParams=postParams, clientCookies=clientCookies, serverCookies=serverCookies, - **conn.info() - ) - - referer = util.getHeader(request, 'referer') - if len(referer): - self.out.write(' Referer: %s\n' % referer) - - if clientCookies: - self.out.write(' Client Transmitted Cookies:\n', direction='cs') - for key in clientCookies: - self.out.write(' %s -> %s\n' % (util.printableUnicode(key), - util.printableUnicode(clientCookies[key])), direction='cs') - if serverCookies: - self.out.write(' Server Set Cookies:\n', direction='sc') - for key in serverCookies: - self.out.write(' %s -> %s\n' % (util.printableUnicode(key), - util.printableUnicode(serverCookies[key])), direction='sc') - - if urlParams: - self.out.write(' URLParameters:\n', direction='cs') - for key in urlParams: - self.out.write(' %s -> %s\n' % (util.printableUnicode(key), - util.printableUnicode(urlParams[key])), direction='cs') - if postParams: - self.out.write(' POSTParameters:\n', direction='cs') - for key in postParams: - self.out.write(' %s -> %s\n' % (util.printableUnicode(key), - util.printableUnicode(postParams[key])), direction='cs') - elif len(request.body): - self.out.write(' POST Body:\n', direction='cs') - if len(request.body) > self.maxpost and self.maxpost > 0: - self.out.write('%s[truncated]\n' % util.printableUnicode( - request.body[:self.maxpost]), direction='cs') - else: - self.out.write( - util.printableUnicode(request.body) + u"\n", direction='cs') - - if self.showcontent or self.showhtml: - - if self.showhtml and 'html' not in util.getHeader(response, 'content-type'): - return - - if 'gzip' in util.getHeader(response, 'content-encoding'): - content = self.decompressGzipContent(response.body) - if content == None: - content = '(gunzip failed)\n' + response.body - else: - content = '(gzip encoded)\n' + content - else: - content = response.body - - self.out.write("Body Content:\n", direction='sc') - self.out.write( - util.printableUnicode(content) + u"\n", direction='sc') - - def _parseCookies(self, data): - p, kwp = util.strtok(data, sep='; ') - return dict((urllib.unquote(k), urllib.unquote(kwp[k]))for k in kwp.keys()) - - -if __name__ == '__main__': - dObj = DshellDecoder() - print dObj -else: - dObj = DshellDecoder() diff --git a/decoders/http/joomla-cve-2015-8562.py b/decoders/http/joomla-cve-2015-8562.py deleted file mode 100644 index 691d8d1..0000000 --- a/decoders/http/joomla-cve-2015-8562.py +++ /dev/null @@ -1,81 +0,0 @@ -import dshell -import util -from httpdecoder import HTTPDecoder - -import re - - -class DshellDecoder(HTTPDecoder): - - def __init__(self): - HTTPDecoder.__init__(self, - name='joomla-cve-2015-8562', - description='detect and dissect malformed HTTP headers targeting Joomla', - filter='tcp and (port 80 or port 8080 or port 8000)', - filterfn=lambda ((sip, sp), (dip, dp)): sp in ( - 80, 8000, 8080) or dp in (80, 8000, 8080), - author='bg', - optiondict={ - 'raw_payload': {'action': 'store_true', 'help':'return the raw payload (do not attempt to decode chr encoding)'} - }, - longdescription=''' -Usage Examples: ---------------- - - decode -d joomla-cve-2015-8562 *.pcap -joomla-cve-2015-8562 2015-12-15 20:17:18 192.168.1.119:43865 <- 192.168.1.139:80 ** x-forwarded-for -> system('touch /tmp/2'); ** - - The module assumes the cmd payload is encoded using chr. To turn this off run: - - decode -d joomla-cve-2015-8562 --joomla-cve-2015-8562_no_eval *.pcap -oomla-cve-2015-8562 2015-12-15 20:17:18 192.168.1.119:43865 <- 192.168.1.139:80 ** x-forwarded-for -> "eval(chr(115).chr(121).chr(115).chr(116).chr(101).chr(109).chr(40).chr(39).chr(116).chr(111).chr(117).chr(99).chr(104).chr(32).chr(47).chr(116).chr(109).chr(112).chr(47).chr(50).chr(39).chr(41).chr(59)); ** -''' - ) - - self.ioc = 'JFactory::getConfig();exit' - - def attempt_decode(self, cmd): - ptext = '' - for c in re.findall('\d+', cmd): - ptext += chr(int(c)) - return ptext - - - def parse_cmd(self, data): - start = data.find('"feed_url";')+11 - end = data.find(self.ioc) - chunk = data[start:end] - - try: - cmd = chunk.split(':')[-1] - if self.raw_payload: - return cmd - - plaintext_cmd = self.attempt_decode(cmd) - return plaintext_cmd - except: - return None - - def HTTPHandler(self, conn, request, response, requesttime, responsetime): - if not request: - return - - if self.ioc not in str(request): - # indicator of (potential) compromise is not here - return - - # there is an attempt to exploit Joomla! - - # The Joomla exploit could be sent any HTTP header field - for hdr in request.headers: - if self.ioc in request.headers[hdr]: - cmd = self.parse_cmd(request.headers[hdr]) - if cmd: - self.alert('{} -> {}'.format(hdr, cmd), **conn.info()) - - -if __name__ == '__main__': - dObj = DshellDecoder() - print dObj -else: - dObj = DshellDecoder() diff --git a/decoders/http/ms15-034.py b/decoders/http/ms15-034.py deleted file mode 100644 index f5bfed1..0000000 --- a/decoders/http/ms15-034.py +++ /dev/null @@ -1,74 +0,0 @@ -import dshell -import util -from httpdecoder import HTTPDecoder - -class DshellDecoder(HTTPDecoder): - ''' - 15 April 2015 - - Proof-of-concept code to detect attempts to enumerate MS15-034 vulnerable - IIS servers and/or cause a denial of service. Each event will generate an - alert that prints out the HTTP Request method and the range value contained - with the HTTP stream. - - Usage: - decode -d ms15-034 -q *.pcap - decode -d ms15-034 -i -q - - References: - https://technet.microsoft.com/library/security/ms15-034 - https://ma.ttias.be/remote-code-execution-via-http-request-in-iis-on-windows/ - ''' - def __init__(self): - HTTPDecoder.__init__(self, - name='ms15-034', - description='detect attempts to enumerate MS15-034 vulnerable IIS servers', - longdescription=''' -Proof-of-concept code to detect attempts to enumerate MS15-034 vulnerable -IIS servers and/or cause a denial of service. Each event will generate an -alert that prints out the HTTP Request method and the range value contained -with the HTTP stream. - -Usage: -decode -d ms15-034 -q *.pcap -decode -d ms15-034 -i -q -''', - filter='tcp and (port 80 or port 8080 or port 8000)', - filterfn=lambda ((sip, sp), (dip, dp)): sp in ( - 80, 8000, 8080) or dp in (80, 8000, 8080), - author='bg', - ) - - def HTTPHandler(self, conn, request, response, requesttime, responsetime): - if response == None: # Denial of Service (no server response) - try: - rangestr = util.getHeader(request,'range') - # check range value to reduce false positive rate - if not rangestr.endswith('18446744073709551615'): return - except: return - self.alert('MS15-034 DoS [Request Method: "%s" URI: "%s" Range: "%s"]' % \ - (request.method, request.uri, rangestr), conn.info()) - - else: # probing for vulnerable server - try: - rangestr = util.getHeader(request,'range') - # check range value to reduce false positive rate - if not rangestr.endswith('18446744073709551615'): return - except: return - - # indication of vulnerable server - if rangestr and (response.status == '416' or \ - response.reason == 'Requested Range Not Satisfiable'): - - self.alert('MS15-034 Vulnerable Server [Request Method: "%s" Range: "%s"]' % - (request.method,rangestr), conn.info()) - - if request.method != 'GET': # this could be interesting - pass # waiting on more details - - -if __name__ == '__main__': - dObj = DshellDecoder() - print dObj -else: - dObj = DshellDecoder() diff --git a/decoders/http/peht.py b/decoders/http/peht.py deleted file mode 100644 index 9ce0e3d..0000000 --- a/decoders/http/peht.py +++ /dev/null @@ -1,264 +0,0 @@ -# -# Author: MM - https://github.com/1modm -# -# Most of the Penetration/Exploit/Hijacking Tools use the HTTP methods to try to inject -# or execute code into the attacked server, also this tools usually have a well known -# "hardcoded" User-Agent, URI or request content. -# -# So if the original scanner is not modified can be detected. This is a PoC in order to generate -# simple rules to detect and identified some of the most commons Penetration/Exploit/Hijacking Tools. -# -# Some of the most commons tools source and information: -# -# Nmap -# User-Agent header by default it is "Mozilla/5.0 (compatible; Nmap Scripting Engine; https://nmap.org/book/nse.html)". -# https://nmap.org/nsedoc/lib/http.html -# -# OpenVAS -# http://www.openvas.org/src-doc/openvas-libraries/nasl__http_8c_source.html -# User-Agent header by default: #define OPENVAS_USER_AGENT "Mozilla/5.0 [en] (X11, U; OpenVAS)" -# -# MASSCAN -# https://github.com/robertdavidgraham/masscan -# -# Morpheus -# https://github.com/r00t-3xp10it/morpheus -# https://latesthackingnews.com/2016/12/19/morpheus-automated-ettercap-tcpip-hijacking-tool/ -# -# DataCha0s Web Scanner -# http://eromang.zataz.com/2011/05/23/suc026-datacha0s-web-scannerrobot/ -# https://blogs.harvard.edu/zeroday/2006/06/12/data-cha0s-connect-back-backdoor/ -# -# HNAP (Home Network Administration Protocol) -# https://nmap.org/nsedoc/scripts/hnap-info.html -# -# ZmEu Scanner -# https://en.wikipedia.org/wiki/ZmEu_(vulnerability_scanner) -# http://linux.m2osw.com/zmeu-attack -# https://code.google.com/archive/p/caffsec-malware-analysis/wikis/ZmEu.wiki -# https://ensourced.wordpress.com/2011/02/25/zmeu-attacks-some-basic-forensic/ -# http://philriesch.com/computersecurity_zmeu.html -# -# Jorgee Scanner -# http://www.skepticism.us/2015/05/new-malware-user-agent-value-jorgee/ -# https://www.checkpoint.com/defense/advisories/public/2016/cpai-2016-0214.html -# https://blog.paranoidpenguin.net/2017/04/jorgee-goes-on-a-rampage/ - -import re -import util -import dshell -import datetime -import colorout -from httpdecoder import HTTPDecoder - -class DshellDecoder(HTTPDecoder): - - def __init__(self): - HTTPDecoder.__init__(self, - name='peht', - description='Penetration/Exploit/Hijacking Tool detector', - longdescription=""" -The Penetration/Exploit/Hijacking Tool detector will identify the tool used to scan or exploit a server using the -User agent, URI or HTTP content. - -General usage: - decode -d peht - -Detailed usage: - decode -d peht --peht_showcontent - -Output: - - Request Timestamp (UTC): 2017-07-16 02:41:47.238549 - Penetration/Exploit/Hijacking Tool: Open Vulnerability Assessment System - User-Agent: Mozilla/5.0 [en] (X11, U; OpenVAS 8.0.9) - Request Method: GET - URI: /scripts/session/login.php - Source IP: 1.2.3.4 - Source port: 666 - MAC: 50:b4:02:39:24:56 - Host requested: example.com - - Response Timestamp (UTC): 2017-07-16 02:41:48.238549 - Response Reason: Not Found - Response Status: 404 - Destination IP: 192.168.1.1 - Destination port: 80 - MAC: a4:42:ab:56:b6:23 - - - Detailed Output: - - Request Timestamp (UTC): 2017-07-16 02:41:47.238549 - Penetration/Exploit/Hijacking Tool: Arbitrary Remote Code Execution/injection - User-Agent: Wget(linux) - Request Method: POST - URI: /command.php - Source IP: 1.2.3.4 - Source port: 666 - MAC: 50:b4:02:39:24:56 - Host requested: example.com - - cmd=%63%64%20%2F%76%61%72%2F%74%6D%70%20%26%26%20%65%63%68%6F%20%2D%6E%65%20%5C%5C%78%33%6B%65%72%20%3E%20%6B%65%72%2E%74%78%74%20%26%26%20%63%61%74%20%6B%65%72%2E%74%78%74 - - Response Timestamp (UTC): 2017-07-16 02:41:48.238549 - Response Reason: Found - Response Status: 302 - Destination IP: 192.168.1.1 - Destination port: 80 - MAC: a4:42:ab:56:b6:23 - - - - 302 Found - -

    Found

    -

    The document has moved here.

    - - -""", - filter='tcp and (port 80 or port 81 or port 8080 or port 8000)', - filterfn=lambda ((sip, sp), (dip, dp)): sp in ( - 80, 81, 8000, 8080) or dp in (80, 81, 8000, 8080), - author='mm', - optiondict={ - 'showcontent': {'action': 'store_true', 'default': False, 'help': 'Display the request and response body content.'} - } - ) - - self.out = colorout.ColorOutput() - self.direction = None - self.request_ioc = None - self.request_method = None - self.request_user_agent = None - self.request_host = None - self.request_rangestr = None - self.request_body = None - self.request_referer = None - self.response_content_type = None - self.response_body = None - self.response_contentencoding = None - self.response_status = None - self.response_contentlength = None - self.response_reason = None - - def preModule(self): - if 'setColorMode' in dir(self.out): - self.out.setColorMode() - - def check_payload(self, payloadheader, payloaduri, requestbody): - - ET_identified = None - - r = re.compile(r'\bbash\b | \bcmd\b | \bsh\b | \bwget\b', flags=re.I | re.X) - if r.findall(requestbody): - ET_identified = 'Arbitrary Remote Code Execution/injection' - - if payloadheader.has_key('content-type'): - struts_ioc = ['cmd', 'ProcessBuilder', 'struts'] - #Will return empty if all words from struts_ioc are in payloadheader['content-type'] - struts_check = list(filter(lambda x: x not in payloadheader['content-type'], struts_ioc)) - if not struts_check: - ET_identified = 'Apache Struts Content-Type arbitrary command execution' - - if payloadheader.has_key('user-agent'): - if 'Jorgee' in payloadheader['user-agent']: - ET_identified = 'Jorgee Scanner' - elif 'Nmap' in payloadheader['user-agent']: - ET_identified = 'Nmap' - elif 'masscan' in payloadheader['user-agent']: - ET_identified = 'Mass IP port scanner' - elif ('ZmEu' in payloadheader['user-agent'] and 'w00tw00t' in payloaduri): - ET_identified = 'ZmEu Vulnerability Scanner' - elif 'immoral' in payloadheader['user-agent']: - ET_identified = 'immoral' - elif 'chroot' in payloadheader['user-agent']: - ET_identified = 'chroot' - elif 'DataCha0s' in payloadheader['user-agent']: - ET_identified = 'DataCha0s Web Scanner' - elif 'OpenVAS' in payloadheader['user-agent']: - ET_identified = 'Open Vulnerability Assessment System' - elif ('bash' or 'sh' or 'cmd' or 'wget') in (payloadheader['user-agent']): - ET_identified = 'Arbitrary Remote Code Execution/injection' - - if 'muieblackcat' in payloaduri: - ET_identified = 'Muieblackcat Web Scanner/Robot' - if '/HNAP1/' in payloaduri: - ET_identified = 'Home Network Administration Protocol' - - return ET_identified - - - - def HTTPHandler(self, conn, request, response, requesttime, responsetime): - - if not request: - return - - # Obtain the response content - try: - if 'gzip' in util.getHeader(response, 'content-encoding'): - self.response_body = self.decompressGzipContent(response.body) - if self.response_body == None: - self.response_body = '(gunzip failed)\n' + response.body - else: - self.response_body = '(gzip encoded)\n' + self.response_body - else: - self.response_body = response.body - except AttributeError as e: - self.response_body = None - - # Obtain the request content - try: - if 'gzip' in util.getHeader(request, 'content-encoding'): - self.request_body = self.decompressGzipContent(request.body) - if self.request_body == None: - self.request_body = '(gunzip failed)\n' + request.body - else: - self.request_body = '(gzip encoded)\n' + self.request_body - else: - self.request_body = request.body - except AttributeError as e: - self.request_body = None - - # Identify the Exploit/Hijacking Tool - self.request_ioc = self.check_payload(request.headers, request.uri, self.request_body) - - if self.request_ioc: - - # REQUEST - if request.method in ('GET', 'POST', 'HEAD'): - self.direction = "sc" - self.request_method = request.method - self.request_user_agent = request.headers.get('user-agent') - self.request_host = util.getHeader(request, 'host') - self.request_rangestr = util.getHeader(request,'range') - self.request_body = request.body - self.request_referer = util.getHeader(request, 'referer') - - if request.headers.has_key('user-agent'): - self.request_user_agent = request.headers['user-agent'] - - self.out.write("\nRequest Timestamp (UTC): {0} \nPenetration/Exploit/Hijacking Tool: {1}\nUser-Agent: {2}\nRequest Method: {3}\nURI: {4}\nSource IP: {5} - Source port: {6} - MAC: {7}\nHost requested: {8}\nReferer: {9}\n".format(datetime.datetime.utcfromtimestamp( - requesttime), self.request_ioc, self.request_user_agent, self.request_method, request.uri, conn.sip, conn.sport, conn.smac, self.request_host, self.request_referer), formatTag="H2", direction=self.direction) - - # Show request body content - if self.showcontent: - self.out.write("\n{0}\n".format(self.request_body), formatTag="H2", direction=self.direction) - - if not response: - self.direction = "cs" - self.out.write('\nNo response\n', formatTag="H2", direction=self.direction) - - # RESPONSE - else: - self.direction = "cs" - self.response_content_type = util.getHeader(response, 'content-type') - self.response_contentencoding = util.getHeader(response, 'content-encoding') - self.response_status = response.status - self.response_reason = response.reason - - self.out.write("\nResponse Timestamp (UTC): {0} \nResponse Reason: {1}\nResponse Status: {2}\nDestination IP: {3} - Destination port: {4} - MAC: {5}\n".format(datetime.datetime.utcfromtimestamp( - responsetime), self.response_reason, self.response_status, conn.dip, conn.dport, conn.dmac), formatTag="H2", direction=self.direction) - - # Show response body content - if self.showcontent: - self.out.write("\n{0}\n".format(self.response_body), formatTag="H2", direction=self.direction) - -if __name__ == '__main__': - dObj = DshellDecoder() - print dObj -else: - dObj = DshellDecoder() \ No newline at end of file diff --git a/decoders/http/rip-http.py b/decoders/http/rip-http.py deleted file mode 100644 index 4b49f9f..0000000 --- a/decoders/http/rip-http.py +++ /dev/null @@ -1,203 +0,0 @@ -import dshell -import re -import datetime -import sys -import string - -# import any other modules here -import re -import os -import hashlib -import util - -# we extend this -from httpdecoder import HTTPDecoder - - -class DshellDecoder(HTTPDecoder): - - def __init__(self): - HTTPDecoder.__init__(self, - name='rip-http', - description='rip files from HTTP traffic', - filter='tcp and port 80', - author='bg/twp', - optiondict={'append_conn': {'action': 'store_true', 'help': 'append sourceip-destip to filename'}, - 'append_ts': {'action': 'store_true', 'help': 'append timestamp to filename'}, - 'direction': {'help': 'cs=only capture client POST, sc=only capture server GET response'}, - 'outdir': {'help': 'directory to write output files (Default: current directory)', 'metavar': 'DIRECTORY', 'default': '.'}, - 'content_filter': {'help': 'regex MIME type filter for files to save'}, - 'name_filter': {'help': 'regex filename filter for files to save'}} - ) - - def preModule(self): - if self.content_filter: - self.content_filter = re.compile(self.content_filter) - if self.name_filter: - self.name_filter = re.compile(self.name_filter) - HTTPDecoder.preModule(self) - - self.openfiles = {} # dict of httpfile objects, indexed by url - - # Create output directory, if necessary - if not os.path.exists(self.outdir): - try: - os.makedirs(self.outdir) - except (IOError, OSError) as e: - self.error("Could not create directory '%s': %s" % - (self.outdir, e)) - sys.exit(1) - - def splitstrip(self, data, sep, strip=' '): - return [lpart.strip(strip) for lpart in data.split(sep)] - - def HTTPHandler(self, conn, request, response, requesttime, responsetime): - payload = None - self.debug('%s %s' % (repr(request), repr(response))) - if (not self.direction or self.direction == 'cs') and request and request.method == 'POST' and request.body: - payload = request - elif (not self.direction or self.direction == 'sc') and response and response.status[0] == '2': - payload = response - if payload: - if not (not self.content_filter or self.content_filter.search(payload.headers['content-type'])): - payload = None - if payload: - # Calculate URL - host = util.getHeader(request, 'host') - if host == '': - host = conn.serverip - url = host + request.uri - # File already open - if url in self.openfiles: - self.debug("Adding response section to %s" % url) - (s, e) = self.openfiles[url].handleresponse(response) - self.write(" --> Range: %d - %d\n" % (s, e)) - # New file - else: - filename = request.uri.split('?')[0].split('/')[-1] - if 'content-disposition' in payload.headers: - cdparts = self.splitstrip(payload.headers['content-disposition'], ';') - for cdpart in cdparts: - try: - k, v = self.splitstrip(cdpart, '=') - if k == 'filename': - filename = v - except: - pass - self.debug("New file with URL: %s" % url) - if not self.name_filter or self.name_filter.search(filename): - if self.append_conn: - filename += '_%s-%s' % (conn.serverip, - conn.clientip) - if self.append_ts: - filename += '_%d' % (conn.ts) - if not len(filename): - filename = '%s-%s_index.html' % ( - conn.serverip, conn.clientip) - while os.path.exists(os.path.join(self.outdir, filename)): - filename += '_' - self.alert("New file: %s (%s)" % - (filename, url), conn.info()) - self.openfiles[url] = httpfile( - os.path.join(self.outdir, filename), self) - (s, e) = self.openfiles[url].handleresponse(payload) - self.write(" --> Range: %d - %d\n" % (s, e)) - if self.openfiles[url].done(): - self.alert("File done: %s (%s)" % - (self.openfiles[url].filename, url), conn.info()) - del self.openfiles[url] - - -class httpfile: - - def __init__(self, filename, decoder_instance): - self.complete = False - # Expected size in bytes of full file transfer - self.size = 0 - # List of tuples indicating byte chunks already received and written to - # disk - self.ranges = [] - self.decoder = decoder_instance - self.filename = filename - try: - self.fh = open(filename, 'w') - except IOError as e: - self.decoder.error( - "Could not create file '%s': %s" % (filename, e)) - self.fh = None - - def __del__(self): - if self.fh is None: - return - self.fh.close() - if not self.done(): - print "Incomplete file: %s" % self.filename - try: - os.rename(self.filename, self.filename + "_INCOMPLETE") - except: - pass - ls = 0 - le = 0 - for s, e in self.ranges: - if s > le + 1: - print "Missing bytes between %d and %d" % (le, s) - ls, le = s, e - - def handleresponse(self, response): - # Check for Content Range - range_start = 0 - range_end = len(response.body) - 1 - if 'content-range' in response.headers: - m = re.search( - 'bytes (\d+)-(\d+)/(\d+|\*)', response.headers['content-range']) - if m: - range_start = int(m.group(1)) - range_end = int(m.group(2)) - if len(response.body) < (range_end - range_start + 1): - range_end = range_start + len(response.body) - 1 - try: - if int(m.group(3)) > self.size: - self.size = int(m.group(3)) - except: - pass - elif 'content-length' in response.headers: - try: - if int(response.headers['content-length']) > self.size: - self.size = int(response.headers['content-length']) - except: - pass - # Update range tracking - self.ranges.append((range_start, range_end)) - # Write part of file - if self.fh is not None: - self.fh.seek(range_start) - self.fh.write(response.body) - return (range_start, range_end) - - def done(self): - self.checkranges() - return self.complete - - def checkranges(self): - self.ranges.sort() - current_start = 0 - current_end = 0 - foundgap = False - # print self.ranges - for s, e in self.ranges: - if s <= current_end + 1: - current_end = e - else: - foundgap = True - current_start = s - current_end = e - if not foundgap: - if (current_end + 1) >= self.size: - self.complete = True - return foundgap - -if __name__ == '__main__': - dObj = DshellDecoder() - print dObj -else: - dObj = DshellDecoder() diff --git a/decoders/http/web.py b/decoders/http/web.py deleted file mode 100755 index 752d1dc..0000000 --- a/decoders/http/web.py +++ /dev/null @@ -1,180 +0,0 @@ -import dshell -import dfile -import util -import hashlib - -from httpdecoder import HTTPDecoder - - -class DshellDecoder(HTTPDecoder): - - def __init__(self): - HTTPDecoder.__init__(self, - name='web', - description='Improved version of web that tracks server response', - filter='tcp and (port 80 or port 8080 or port 8000)', - filterfn=lambda ((sip, sp), (dip, dp)): sp in ( - 80, 8000, 8080) or dp in (80, 8000, 8080), - author='bg,twp', - optiondict={ - 'maxurilen': {'type': 'int', 'default': 30, 'help': 'Truncate URLs longer than max len. Set to 0 for no truncating. (default: 30)'}, - 'md5': {'action': 'store_true', 'help': 'calculate MD5 for each response. Available in CSV output.'} - }, - ) - self.gunzip = False # Not interested in response body - - def HTTPHandler(self, conn, request, response, requesttime, responsetime): - - # - # Establish kw_items dictionary for extracted details from tcp/ip layer and request/response - # - kw_items = conn.info() - - # - # Extract useful information from HTTP *request* - # - for h in request.headers.keys(): - kw_items[h] = util.getHeader(request, h) - # Rename user-agent for backward compatability - if 'user-agent' in kw_items: - kw_items['useragent'] = kw_items.pop('user-agent') - - # Override non-existent host header with server IP address - if kw_items['host'] == '': - kw_items['host'] = conn.serverip - - # request info string for standard output - requestInfo = '%s %s%s HTTP/%s' % (request.method, - kw_items['host'] if kw_items['host'] != request.uri else '', # With CONNECT method, the URI is or contains the host, making this redudant - request.uri[:self.maxurilen] + '[truncated]' if self.maxurilen > 0 and len( - request.uri) > self.maxurilen else request.uri, - request.version) - - # - # Extract useful information from HTTP *response* (if available) - # - status = '' - reason = '' - responsesize = 0 - loc = '' - lastmodified = '' - md5 = '' - if response!=None: - - try: - responsesize = len(response.body.rstrip('\0')) - except: - responsesize = 0 - - if self.md5: - md5 = self._bodyMD5(response) - else: - md5 = '' - - try: - status = response.status - except: - status = '' - try: - reason = response.reason - except: - reason = '' - - for h in response.headers.keys(): - if not h in kw_items: - kw_items[h] = util.getHeader(response, h) - else: - kw_items['server_'+h] = util.getHeader(response, h) - if 'content-type' in kw_items: - kw_items['contenttype'] = kw_items.pop('content-type') - - loc = '' - if status[:2] == '30': - loc = util.getHeader(response, 'location') - if len(loc): - loc = '-> ' + loc - - lastmodified = util.HTTPlastmodified(response) - - # response info string for standard output - responseInfo = '%s %s %s %s' % (status, reason, loc, lastmodified) - - else: - responseInfo = '' - - # - # File objects - # - try: - if len(response.body) > 0: - responsefile = dfile.dfile( - name=request.uri, data=response.body) - else: - responsefile = '' - except: - responsefile = '' - if request.method == 'POST' and len(request.body): - ulcontenttype, ulfilename, uldata = self.POSTHandler(request.body) - uploadfile = dfile.dfile(name=ulfilename, data=uldata) - else: - uploadfile = None - - # - # Call alert with text info and kw values - # - self.alert("%-80s // %s" % (requestInfo, responseInfo), request=requestInfo, response=responseInfo, - request_time=requesttime, response_time=responsetime, request_method=request.method, - uri=request.uri, status=status, reason=reason, lastmodified=lastmodified, - md5=md5, responsesize=responsesize, responsefile=responsefile, uploadfile=uploadfile, **kw_items) - - if self.out.sessionwriter: - self.write(request.data, direction='cs') - if response: - self.write(response.body, direction='sc') - - # MD5sum(hex) of the body portion of the response - def _bodyMD5(self, response): - try: - if len(response.body) > 0: - return hashlib.md5(response.body.rstrip('\0')).hexdigest() - else: - return '' - except: - return '' - - def POSTHandler(self, postdata): - next_line_is_data = False - contenttype = '' - filename = '' - for l in postdata.split("\r\n"): - if next_line_is_data: - break - if l == '': - next_line_is_data = True # \r\n\r\n before data - continue - try: - k, v = self.splitstrip(l, ':') - if k == 'Content-Type': - contenttype = v - if k == 'Content-Disposition': - cdparts = self.splitstrip(v, ';') - for cdpart in cdparts: - try: - k, v = self.splitstrip(cdpart, '=', '"') - if k == 'filename': - filename = v - except: - pass - except: - pass - return contenttype, filename, l - - def splitstrip(self, data, sep, strip=' '): - return [lpart.strip(strip) for lpart in data.split(sep)] - - -if __name__ == '__main__': - dObj = DshellDecoder() - print dObj -else: - dObj = DshellDecoder() diff --git a/decoders/malware/emdivi/emdivi_c2.py b/decoders/malware/emdivi/emdivi_c2.py deleted file mode 100644 index 119058c..0000000 --- a/decoders/malware/emdivi/emdivi_c2.py +++ /dev/null @@ -1,115 +0,0 @@ -from httpdecoder import HTTPDecoder -import urllib -from collections import defaultdict - -''' -JPCERT Coordination Center (JPCERT/CC) released a series of capabilities to -detect and understand compromises involving the Emdivi HTTP bot. Additional -references from JPCERT: - -http://blog.jpcert.or.jp/2015/11/emdivi-and-the-rise-of-targeted-attacks-in-japan.html -https://github.com/JPCERTCC/aa-tools -https://github.com/JPCERTCC/aa-tools/blob/master/emdivi_postdata_decoder.py - -The emdivi_c2 decoder is based on the hardwork of JPCERT/CC and thus deserve -all the credit. - -LICENSE -Copyright (C) 2015 JPCERT Coordination Center. All Rights Reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -1. Redistributions of source code must retain the above copyright notice, -this list of conditions and the following acknowledgments and disclaimers. -2. Redistributions in binary form must reproduce the above copyright notice, -this list of conditions and the following acknowledgments and disclaimers in -the documentation and/or other materials provided with the distribution. -3. Products derived from this software may not include "JPCERT Coordination -Center" in the name of such derived product, nor shall "JPCERT Coordination -Center" be used to endorse or promote products derived from this software -without prior written permission. For written permission, please contact -pr@jpcret.or.jp. -''' - - -class DshellDecoder(HTTPDecoder): - - def __init__(self): - HTTPDecoder.__init__(self, - name='emdivi_c2', - description='deobfuscate Emdivi http c2', - filter='tcp and port 80', - author='bg', - ) - - def decode_payload(self, payload): - '''logic from JPCERTCC emdivi_postdata_decoder.py''' - - decoded = defaultdict() - - if ';' in payload: - delim = ';' - else: - delim = '&' - - fields = [x for x in payload.split(delim) if x] - - for field in fields: - try: - name, value = field.split('=') - except ValueError: - continue - - xor_key = 0x00 - for c in name: - xor_key = (ord(c)) ^ xor_key - - plaintext = '' - for c in urllib.unquote(value): - plaintext += chr(ord(c) ^ xor_key) - - decoded[name] = plaintext - return decoded - - def validate_payload(self, payload_dict): - ''' attempt to validate Emdivi payload. if a valid payload is found, - return the key associated with Emdivi version information ''' - # this check is very simple and will only validate payloads that content like: - # ?VER: t20.09.Koitochu.8530.7965.4444 | NT: 5.1.2600.5512 [en-US] | MEM: 128M | GMT(-6) - - version_info_key = None - for k in payload_dict: - if 'GMT' in payload_dict[k]: - version_info_key = k - break - - return version_info_key - - def HTTPHandler(self, conn, request, response, requesttime, responsetime): - if not request: - return - - decoded = defaultdict() - - if request.method in ('GET', 'POST'): - # first check the body of the GET or POST - if len(request.body) > 0: - decoded.update(self.decode_payload(request.body)) - - if not decoded and 'cookie' in request.headers: - # some traffic had encoded information - # embedded within the Cookie header - decoded.update(self.decode_payload(request.headers['cookie'])) - - if decoded: - version_info_key = self.validate_payload(decoded) - - if version_info_key: - self.alert('{}'.format(decoded[version_info_key]), **conn.info()) - -if __name__ == '__main__': - dObj = DshellDecoder() - print dObj -else: - dObj = DshellDecoder() diff --git a/decoders/misc/followstream.py b/decoders/misc/followstream.py deleted file mode 100644 index be89d97..0000000 --- a/decoders/misc/followstream.py +++ /dev/null @@ -1,118 +0,0 @@ -import dshell -import util -import colorout -#from impacket.ImpactDecoder import EthDecoder -import datetime -import sys -import traceback -import logging - -# import any other modules here -import cgi - - -class DshellDecoder(dshell.TCPDecoder): - - def __init__(self): - dshell.TCPDecoder.__init__(self, - name='followstream', - description='Generates color-coded Screen/HTML output similar to Wireshark Follow Stream', - longdescription=""" -Generates color-coded Screen/HTML output similar to Wireshark Follow Stream. - -Output by default uses the "colorout" output class. This will send TTY -color-formatted text to stdout (the screen) if available. If output -is directed to a file (-o or --outfile), the output will be in HTML format. - -Note that the default bpf filter is to view all tcp traffic. The decoder -can also process UDP traffic, or it can be limited to specific streams -with --bpf/--ebpf. - -Useful options: - - --followstream_hex -- generates output in hex mode - --followstream_time -- includes timestamp for each blob/transmission - -Example: - - decode -d followstream --ebpf 'port 80' mypcap.pcap --followstream_time - decode -d followstream --ebpf 'port 80' mypcap.pcap -o file.html --followstream_time - -""", - filter="tcp", - author='amm', - optiondict={ - 'hex': {'action': 'store_true', 'help': 'two-column hex/ascii output'}, - 'time': {'action': 'store_true', 'help': 'include timestamp for each blob'}, - 'encoding': {'type': 'string', 'help': 'attempt to interpret text as encoded with specified schema'}, - } - ) - self.out = colorout.ColorOutput() - - def __errorHandler(self, blob, expected, offset, caller): - # Custom error handler that is called when data in a blob is missing or - # overlapping - if offset > expected: # data is missing - self.data_missing_message += "[%d missing bytes]" % ( - offset - expected) - elif offset < expected: # data is overlapping - self.data_missing_message += "[%d overlapping bytes]" % ( - offset - expected) - return True - - def preModule(self): - self.connectionCount = 0 - # Reset the color mode, in case a file is specified - if 'setColorMode' in dir(self.out): - self.out.setColorMode() - # Used to indicate when data is missing or overlapping - self.data_missing_message = '' - # overwrite the output module's default error handler - self.out.errorH = self.__errorHandler - - def postModule(self): - self.out.close() - - def connectionHandler(self, connection): - - try: - - # Skip Connections with no data transferred - if connection.clientbytes + connection.serverbytes < 1: - return - - # Update Connection Counter - self.connectionCount += 1 - - # Connection Header Information - self.out.write("Connection %d (%s)\n" % ( - self.connectionCount, str(connection.proto)), formatTag='H1') - self.out.write("Start: %s UTC\n End: %s UTC\n" % (datetime.datetime.utcfromtimestamp( - connection.starttime), datetime.datetime.utcfromtimestamp(connection.endtime)), formatTag='H2') - self.out.write("%s:%s -> %s:%s (%d bytes)\n" % (connection.clientip, connection.clientport, - connection.serverip, connection.serverport, connection.clientbytes), formatTag="H2", direction="cs") - self.out.write("%s:%s -> %s:%s (%d bytes)\n\n" % (connection.serverip, connection.serverport, - connection.clientip, connection.clientport, connection.serverbytes), formatTag="H2", direction="sc") - - self.out.write( - connection, hex=self.hex, time=self.time, encoding=self.encoding) - if self.data_missing_message: - self.out.write( - self.data_missing_message + "\n", level=logging.WARNING, time=self.time) - self.data_missing_message = '' - - # Line break before next session - self.out.write("\n\n") - - except KeyboardInterrupt: - raise - except: - print 'Error in connectionHandler: ', sys.exc_info()[1] - traceback.print_exc(file=sys.stdout) - - -if __name__ == '__main__': - dObj = DshellDecoder() - print dObj -else: - dObj = DshellDecoder() diff --git a/decoders/misc/grep.py b/decoders/misc/grep.py deleted file mode 100644 index ea7f10a..0000000 --- a/decoders/misc/grep.py +++ /dev/null @@ -1,205 +0,0 @@ -import dshell -import datetime -import sys - -# import any other modules here -import re - - -class grepDecoder(dshell.TCPDecoder): - - def __init__(self): - dshell.TCPDecoder.__init__(self, - name='grep', - description='Search for patterns in streams.', - longdescription=""" -Grep is a utility decoder, useful on it's own or in combination with -downstream (chained) decoders. Your search expression is specified with the ---grep_expression option, and the default behavior is that the entire "line" -of text surround each match will be printed, along with the standard -connection information. However, granular match information is passed to the -output decoder giving the user more control about the type of output they -would like to see. Following is the named-variable convention passed to -output: - - match: Full expression match - m1: First sub-match - m2: Second sub-match - .. - mn: N'th sub-match - -Examples: - - Snag User-Agent, display as CSV: - - decode -d grep --grep_ignorecase --grep_expression 'User-Agent: (.*?)$' --output csvout,m1 - - The text following User-Agent will be the first sub-match and then - printed as a named field in CSV output. - - Better yet: - - decode -d grep --grep_ignorecase --grep_expression 'User-Agent: (.*?)$' --oformat "%(m1)s" - - This uses the same expression but instead of the default output, - specifies "m1" in a format string which makes it the ONLY value - displayed. This is nice for piping into sort/uniq or other - command-line filters. - -Iterative matching - -Rather than alerting on an entire line or just the first hit within that line, -Python's regular expression module offers a function called "finditer" which -scans across input text and provides an iterable object of ALL the matches. -So with "--grep_iterate" we can use that. - -Examples: - - Simplistically grab all hyperlinks and dump to stdout: - - decode -d grep --grep_expression '' --grep_iterate --grep_ignorecase --oformat "%(m1)s" - -Chainable - -Grep is chainable. What does this mean? If data within a connection -matches a grep expression, the entire connection is considered a "hit" and is -then allowed to be processed by subDecoders. Non-hits are dropped. - -So this means you can search for an expression and view all matching -connections in followstream, or process all as web traffic, etc. - -Examples: - - View all web traffic that originated from Windows 7 machines: - - decode -d grep+web --grep_ignorecase --grep_expression 'User-Agent: [^\\r\\n]*Windows 6.1' -""", - author='amm', - filter='tcp', - optiondict={ - 'expression': {'type': 'string', 'help': 'Search expression'}, - 'ignorecase': {'action': 'store_true', 'help': 'Case insensitive search.'}, - 'singleline': {'action': 'store_true', 'help': 'Treat entire connection as single line of text.'}, - 'iterate': {'action': 'store_true', 'help': 'Iterate hits on match string.'}, - 'invert': {'action': 'store_true', 'help': 'For chained only: Invert hit results.'} - } - ) - self.chainable = True - - def preModule(self): - - # - # Does subdecoder have a blobHandler - # - if self.subDecoder and 'blobHandler' in dir(self.subDecoder): - self.debug("subDecoder has blobHandler") - self.subblobHandler = True - # Indexed by connection, storage for all blobs being deferred - self.deferredBlobs = {} - else: - self.subblobHandler = False - - # Pass/Drop dictionary of connections to use in chain mode - self.connstate = {} - - # Must use singleLine mode when subDecoder is present - if self.subDecoder: - self.singleline = True - - # Re parameters - self.reFlags = 0 - if self.ignorecase: - self.reFlags = self.reFlags | re.IGNORECASE - if self.singleline or self.iterate: - self.reFlags = self.reFlags | re.S - - # Re Expression -> Object - if self.expression == None or not len(self.expression): - self.error( - "Must specify expression using --%s_expression" % self.name) - sys.exit(1) - else: - sys.stderr.write("Using expression: '%s'\n" % self.expression) - self.reObj = re.compile(self.expression, self.reFlags) - - dshell.TCPDecoder.preModule(self) - - def errorH(self, **x): - # custom errorHandler here - pass - - def blobHandler(self, connection, blob): - # Defer all Blob processing until the connection is handled, so we can - # grep the entire connection stream - if self.subblobHandler: - if connection not in self.deferredBlobs: - self.deferredBlobs[connection] = [] - self.deferredBlobs[connection].append(blob) - - def connectionHandler(self, connection): - - # Normal processing, no subDecoder - if not self.subDecoder: - self.__searchStream(connection.data(direction='cs', errorHandler=self.errorH) + - "\n" + connection.data(direction='sc', errorHandler=self.errorH), connection) - return - - # Call sub blobHandler for all blobs - if self.subblobHandler and self.__connectionTest(connection): - self.debug("Preparing to process %d blobs in subdecoder" % - len(self.deferredBlobs)) - for b in self.deferredBlobs[connection]: - self.subDecoder.blobHandler(connection, b) - self.deferredBlobs[connection] = None - - # Call sub connectionHandler if necessary - if 'connectionHandler' in dir(self.subDecoder) and self.__connectionTest(connection): - self.subDecoder.connectionHandler(connection) - - def __alert(self, conn, hitstring, matchObj): - kwargs = {'match': matchObj.group(0)} - matchNumber = 0 - for mgroup in matchObj.groups(): - matchNumber += 1 - kwargs['m' + str(matchNumber)] = mgroup - self.alert(hitstring, kwargs, **conn.info()) - - def __connectionTest(self, connection): - if connection not in self.connstate: - if self.reObj.search(connection.data(direction='cs', errorHandler=self.errorH) + "\n" + connection.data(direction='sc', errorHandler=self.errorH)): - self.connstate[connection] = True - else: - self.connstate[connection] = False - if self.invert: - self.connstate[connection] = not self.connstate[connection] - if self.connstate[connection]: - return True - else: - return False - - def __searchStream(self, d, conn): - - if self.singleline or self.iterate: - self.__runSearch(d, conn) - else: - lines = d.split('\n') - for l in lines: - l = l.rstrip() - self.__runSearch(l, conn) - - def __runSearch(self, d, conn): - if self.iterate: - for m in self.reObj.finditer(d): - self.__alert(conn, m.group(0), m) - else: - m = self.reObj.search(d) - if m: - self.__alert(conn, d, m) - - -# always instantiate an dObj of the class -if __name__ == '__main__': - dObj = grepDecoder() - print dObj -else: - dObj = grepDecoder() diff --git a/decoders/misc/merge.py b/decoders/misc/merge.py deleted file mode 100644 index fd9f868..0000000 --- a/decoders/misc/merge.py +++ /dev/null @@ -1,33 +0,0 @@ -import dshell -import dpkt - - -class DshellDecoder(dshell.Decoder): - - """ - merge.py - merge all pcap in to a single file - - Example: decode -d merge *.pcap -W merged.pcap - """ - - def __init__(self): - dshell.Decoder.__init__(self, - name='merge', - description='dump all packets to single file', - longdescription="""Example: decode -d merge *.pcap -W merged.pcap""", - author='bg/twp' - ) - self.chainable = True - - def rawHandler(self, pktlen, pkt, ts, **kw): - if self.subDecoder: - return self.subDecoder.rawHandler(pktlen, str(pkt), ts, **kw) - else: - return self.dump(pktlen, pkt, ts) - - -if __name__ == '__main__': - dObj = DshellDecoder() - print dObj -else: - dObj = DshellDecoder() diff --git a/decoders/misc/synrst.py b/decoders/misc/synrst.py deleted file mode 100644 index 4cac0f5..0000000 --- a/decoders/misc/synrst.py +++ /dev/null @@ -1,41 +0,0 @@ -import dshell -import dpkt - - -class DshellDecoder(dshell.IPDecoder): - - """ - Simple TCP syn/rst filter (ipv4) only - """ - - def __init__(self): - dshell.IPDecoder.__init__(self, - name='synrst', - description='detect failed attempts to connect (SYN followed by a RST/ACK)', - filter="tcp[13]=2 or tcp[13]=20", - author='bg' - ) - self.tracker = {} # key = (srcip,srcport,seqnum,dstip,dstport) - - def packetHandler(self, ip=None): - tcp = dpkt.ip.IP(ip.pkt).data - - if tcp.flags & 2: # check for SYN flag - seqnum = tcp.seq - key = '%s:%s:%d:%s:%s' % ( - ip.sip, ip.sport, seqnum, ip.dip, ip.dport) - self.tracker[key] = '' - elif tcp.flags & 20: # check for RST/ACK flags - acknum = tcp.ack - 1 - tmpkey = '%s:%s:%d:%s:%s' % ( - ip.dip, ip.dport, acknum, ip.sip, ip.sport) - if self.tracker.__contains__(tmpkey): - self.alert('Failed connection', **ip.info()) - del self.tracker[tmpkey] - - -if __name__ == '__main__': - dObj = DshellDecoder() - print dObj -else: - dObj = DshellDecoder() diff --git a/decoders/misc/writer.py b/decoders/misc/writer.py deleted file mode 100644 index 28479b2..0000000 --- a/decoders/misc/writer.py +++ /dev/null @@ -1,52 +0,0 @@ -''' -Created on Jan 13, 2012 - -@author: tparker -''' - -import dshell -import dpkt -from output import PCAPWriter - - -class DshellDecoder(dshell.Decoder): - - ''' - session writer - chain to a decoder to end the chain if the decoder does not output session or packets on its own - if chained to a packet-based decoder, writes all packets to pcap file, can be used to convert or concatenate files - if chained to a connection-based decoder, writes selected streams to session file - ''' - - def __init__(self, **kwargs): - ''' - Constructor - ''' - self.file = None - dshell.Decoder.__init__(self, - name='writer', - description='pcap/session writer', - author='twp', - raw=True, - optiondict=dict( - filename=dict( - default='%(clientip)s:%(clientport)s-%(serverip)s:%(serverport)s-%(direction)s.txt' - ), - ) - ) - - def rawHandler(self, pktlen, pkt, ts, **kwargs): - self.decodedbytes += pktlen - self.count += 1 - self.dump(pktlen, pkt, ts) # pktlen may be wrong if we stripped vlan - - def IPHandler(self, addr, ip, ts, pkttype=None, **kw): - self.decodedbytes += len(ip.data) - self.count += 1 - # if we are passed in IP data vs layer-2 frames, we need to encapsulate - # them - self.dump(dpkt.ethernet.Ethernet(data=str(ip), pkttype=type), ts=ts) - - def connectionHandler(self, conn): - self.write(conn) - -dObj = DshellDecoder() diff --git a/decoders/misc/xor.py b/decoders/misc/xor.py deleted file mode 100644 index 40f1f9c..0000000 --- a/decoders/misc/xor.py +++ /dev/null @@ -1,120 +0,0 @@ -import dshell -import util -import struct - - -class DshellDecoder(dshell.TCPDecoder): - - def __init__(self): - self.xorconn = {} # required to track each individual connection - dshell.TCPDecoder.__init__(self, - name='xor', - description='XOR an entire stream with a given single byte key', - filter="tcp", - author='twp', - optiondict={ - 'key': {'type': 'str', 'default': '0xff', 'help': 'xor key [default 255]'}, - 'cskey': {'type': 'str', 'default': None, 'help': 'c->s xor key [default None]'}, - 'sckey': {'type': 'str', 'default': None, 'help': 's->c xor key [default None]'}, - 'resync': {'action': 'store_true', 'help': 'resync if the key is seen in the stream'}, - } - ) - # sets chainable to true and requires connectionInitHandler() and - # connectionCloseHandler() - self.chainable = True - - def preModule(self, *args, **kwargs): - dshell.TCPDecoder.preModule(self, *args, **kwargs) - # twp handle hex keys - self.key = self.makeKey(self.key) - if self.cskey: - self.cskey = self.makeKey(self.cskey) - if self.sckey: - self.sckey = self.makeKey(self.sckey) - - def makeKey(self, key): - if key.startswith('"'): - return key[1:-1] - if key.startswith('0x'): - k, key = '', key[2:] - for i in xrange(0, len(key), 2): - k += chr(int(key[i:i + 2], 16)) - return k - else: - return struct.pack('I', int(key)) - - # - # connectionInitHandler is required as this module (and all other chainable modules) will have to track all - # each connection independently of dshell.TCPDecoder - # - def connectionInitHandler(self, conn): - # need to set up a custom connection tracker to handle - self.xorconn[conn.addr] = dshell.Connection(self, conn.addr, conn.ts) - self.xorconn[conn.addr].nextoffset = conn.nextoffset - self.xorconn[conn.addr].proto = conn.proto - self.xorconn[conn.addr].info(proto=conn.proto) - - # - # Each blob will be xor'ed and the "newblob" data will be added to the connection - # we are individually tracking - # - def blobHandler(self, conn, blob): - k = 0 # key index - # create new data (ie. pkt data) - # with appropriate key - data, newdata = blob.data(), '' - self.debug('IN ' + util.hexPlusAscii(blob.data())) - if self.cskey != None and blob.direction == 'cs': - key = self.cskey - elif self.sckey != None and blob.direction == 'sc': - key = self.sckey - else: - key = self.key - for i in xrange(len(data)): - if self.resync and data[i:i + len(key)] == key: - k = 0 # resync if the key is seen - # xor this byte with the aligned byte from the key - newdata += chr(ord(data[i]) ^ ord(key[k])) - k = (k + 1) % len(key) # move key position - # update our connection object with the new data - newblob = self.xorconn[conn.addr].update( - conn.endtime, blob.direction, newdata) - self.debug('OUT ' + repr(self.key) + ' ' + util.hexPlusAscii(newdata)) - # if there is another decoder we want to pass this data too - if newblob and 'blobHandler' in dir(self.subDecoder): - # pass to the subDecoder's blobHandler() - self.subDecoder.blobHandler(self.xorconn[conn.addr], newblob) - - # - # The connection has finished without errors, then we pass the entire connection to the subDecoder's - # connectionHandler() - # - def connectionHandler(self, conn): - if conn.addr in self.xorconn: - self.xorconn[conn.addr].proto = conn.proto - if 'connectionHandler' in dir(self.subDecoder): - self.subDecoder.connectionHandler(self.xorconn[conn.addr]) - else: - self.write(self.xorconn[conn.addr]) - - # - # connectionCloseHandler is called when: - # - a connection finishes w/o errors (no data loss) - # - a connection finishes w errors - # - # If the connection exists in our custom connection tracker (self.xorconn), - # we will have to pass it to the subDecoder's connectionCloseHandler - # - # - def connectionCloseHandler(self, conn): - if conn.addr in self.xorconn: - if 'connectionCloseHandler' in dir(self.subDecoder): - self.subDecoder.connectionCloseHandler(self.xorconn[conn.addr]) - del self.xorconn[conn.addr] - - -if __name__ == '__main__': - dObj = DshellDecoder() - print dObj -else: - dObj = DshellDecoder() diff --git a/decoders/nbns/nbns.py b/decoders/nbns/nbns.py deleted file mode 100644 index 55e9bed..0000000 --- a/decoders/nbns/nbns.py +++ /dev/null @@ -1,139 +0,0 @@ -import dpkt -import dshell -from struct import unpack - - -# A few common NBNS Protocol Info Opcodes -# Due to a typo in RFC 1002, 0x9 is also acceptable, but rarely used -# for 'NetBios Refresh' -# 'NetBios Multi-Homed Name Regsitration' (0xf) was added after the RFC -nbns_op = { 0: 'NB_NAME_QUERY', - 5: 'NB_REGISTRATION', - 6: 'NB_RELEASE', - 7: 'NB_WACK', - 8: 'NB_REFRESH', - 9: 'NB_REFRESH', - 15: 'NB_MULTI_HOME_REG' } - - -class DshellDecoder(dshell.UDPDecoder): - - def __init__(self): - dshell.UDPDecoder.__init__(self, - name='nbns', - description='Extract client information from NBNS traffic', - longdescription=""" -The nbns (NetBIOS Name Service) decoder will extract the Transaction ID, Protocol Info, -Client Hostname, and Client MAC address from every UDP NBNS packet found in the given -pcap using port 137. UDP is the standard transport protocol for NBNS traffic. -This filter pulls pertinent information from NBNS packets. - -Examples: - - General usage: - - decode -d nbns - - This will display the connection info including the timestamp, - the source IP, destination IP, Transaction ID, Protocol Info, - Client Hostname, and the Client MAC address in a tabular format. - - - Malware Traffic Analysis Exercise Traffic from 2014-12-08 where a user was hit with a Fiesta exploit kit: - - We want to find out more about the infected machine, and some of this information can be pulled from NBNS traffic - - decode -d nbns /2014-12-08-traffic-analysis-exercise.pcap - - OUTPUT (first few packets): - nbns 2014-12-08 18:19:13 192.168.204.137:137 -- 192.168.204.2:137 ** - Transaction ID: 0xb480 - Info: NB_NAME_QUERY - Client Hostname: WPAD - Client MAC: 00:0c:29:9d:b8:6d - ** - nbns 2014-12-08 18:19:14 192.168.204.137:137 -- 192.168.204.2:137 ** - Transaction ID: 0xb480 - Info: NB_NAME_QUERY - Client Hostname: WPAD - Client MAC: 00:0c:29:9d:b8:6d - ** - nbns 2014-12-08 18:19:16 192.168.204.137:137 -- 192.168.204.2:137 ** - Transaction ID: 0xb480 - Info: NB_NAME_QUERY - Client Hostname: WPAD - Client MAC: 00:0c:29:9d:b8:6d - ** - nbns 2014-12-08 18:19:17 192.168.204.137:137 -- 192.168.204.255:137 ** - Transaction ID: 0xb480 - Info: NB_NAME_QUERY - Client Hostname: WPAD - Client MAC: 00:0c:29:9d:b8:6d - """, - filter='udp and port 137', - author='dek', - ) - self.mac_address = None - self.client_hostname = None - self.xid = None - self.prot_info = None - - - def packetHandler(self, udp, data): - try: - nbns_packet = dpkt.netbios.NS(data) - except (dpkt.dpkt.UnpackError, IndexError) as e: - self.warn('{}: dpkt could not parse session data \ - (NBNS packet not found)'.format(str(e))) - return - - - # Extract the Client hostname from the connection data - # It is represented as 32-bytes half-ASCII - try: - nbns_name = unpack('32s', data[13:45])[0] - except error as e: - self.warn('{}: (NBNS packet not found)'.format(str(e))) - return - - - # Decode the 32-byte half-ASCII name to its 16 byte NetBIOS name - try: - self.client_hostname = dpkt.netbios.decode_name(nbns_name) - - # For uniformity, strip excess byte - self.client_hostname = self.client_hostname[0:-1] - except ValueError as e: - self.warn('{}: Hostname in improper format \ - (NBNS packet not found)'.format(str(e))) - return - - - # Extract the Transaction ID from the NBNS packet - self.xid = hex(nbns_packet.id) - - # Extract the opcode info from the NBNS Packet - op = nbns_packet.op - # Remove excess bits - op = (op >> 11) & 15 - - # Extract protocol info if present in the payload - if nbns_op[op]: - self.prot_info = nbns_op[op] - else: - self.prot_info = hex(nbns_packet.op) - - # Extract the MAC address from the ethernet layer of the packet - self.mac_address = udp.smac - - - if self.xid and self.prot_info and self.client_hostname and self.mac_address: - self.alert('\n\tTransaction ID:\t\t{:<8} \n\tInfo:\t\t\t{:<16} \n\tClient Hostname:\t{:<16} \n\tClient MAC:\t\t{:<18}\n'.format( - self.xid, self.prot_info, self.client_hostname, self.mac_address), **udp.info()) - - -if __name__ == '__main__': - dObj = DshellDecoder() - print dObj -else: - dObj = DshellDecoder() diff --git a/decoders/protocol/ether.py b/decoders/protocol/ether.py deleted file mode 100644 index 23b3c2e..0000000 --- a/decoders/protocol/ether.py +++ /dev/null @@ -1,31 +0,0 @@ -import dshell -import util -import dpkt -import datetime -import binascii - - -class DshellDecoder(dshell.Decoder): - - def __init__(self): - dshell.Decoder.__init__(self, - name='ether', - description='raw ethernet capture decoder', - filter='', - author='twp', asdatetime=True - ) - - def rawHandler(self, dlen, data, ts, **kw): - if self.verbose: - self.log("%.06f %d\n%s" % (ts, dlen, util.hexPlusAscii(str(data)))) - eth = dpkt.ethernet.Ethernet(str(data)) - src = binascii.hexlify(eth.src) - dst = binascii.hexlify(eth.dst) - self.alert('%6x->%6x %4x len %d' % (long(src, 16), long(dst, 16), eth.type, - len(eth.data)), type=eth.type, bytes=len(eth.data), src=src, dst=dst, ts=ts) - -if __name__ == '__main__': - dObj = DshellDecoder() - print dObj -else: - dObj = DshellDecoder() diff --git a/decoders/protocol/ip.py b/decoders/protocol/ip.py deleted file mode 100644 index f432172..0000000 --- a/decoders/protocol/ip.py +++ /dev/null @@ -1,30 +0,0 @@ -import dshell -import util -import dpkt -import traceback - - -class DshellDecoder(dshell.IP6Decoder): - - _PROTO_MAP = {dpkt.ip.IP_PROTO_TCP: 'TCP', 17: 'UDP'} - - def __init__(self): - dshell.IP6Decoder.__init__(self, - name='ip', - description='IPv4/IPv6 decoder', - filter='ip or ip6', - author='twp', - ) - - def packetHandler(self, ip=None, proto=None): - if self.verbose: - self.out.log(util.hexPlusAscii(ip.pkt)) - self.alert(**ip.info()) - if self.out.sessionwriter: - self.write(ip) - -if __name__ == '__main__': - dObj = DshellDecoder() - print dObj -else: - dObj = DshellDecoder() diff --git a/decoders/protocol/protocol.py b/decoders/protocol/protocol.py deleted file mode 100644 index de402dc..0000000 --- a/decoders/protocol/protocol.py +++ /dev/null @@ -1,40 +0,0 @@ -import dshell -import dpkt - -# Build a list of known IP protocols from dpkt -try: - PROTOCOL_MAP = dict((v, k[9:]) for k, v in dpkt.ip.__dict__.iteritems() if type( - v) == int and k.startswith('IP_PROTO_') and k != 'IP_PROTO_HOPOPTS') -except: - PROTOCOL_MAP = {} - - -class DshellDecoder(dshell.IPDecoder): - - """ - protocol.py - - Identifies non-standard protocols (not tcp, udp or icmp) - - References: - http://www.networksorcery.com/enp/protocol/ip.htm - """ - - def __init__(self): - dshell.IPDecoder.__init__(self, - name='protocol', - description='Identifies non-standard protocols (not tcp, udp or icmp)', - filter='(ip and not tcp and not udp and not icmp)', - author='bg', - ) - - def packetHandler(self, ip): - p = PROTOCOL_MAP.get(ip.proto, ip.proto) - self.alert('PROTOCOL: %s (%d)' % - (p, ip.proto), sip=ip.sip, dip=ip.dip, ts=ip.ts) - -if __name__ == '__main__': - dObj = DshellDecoder() - print dObj -else: - dObj = DshellDecoder() diff --git a/decoders/smb/psexec.py b/decoders/smb/psexec.py deleted file mode 100644 index 8d2455d..0000000 --- a/decoders/smb/psexec.py +++ /dev/null @@ -1,247 +0,0 @@ -""" -2015 Feb 13 - -Processes SMB traffic and attempts to extract command/response information -from psexec. - -When a successful SMB connection is seen and it matches a psexec regular -expression, it creates a new "psexec" object to store connection information -and messages. - -Once the connection closes, an alert is generated (of configurable verbosity) -relaying basic information and messages passed. -""" - -#import dshell -from smbdecoder import SMBDecoder -import colorout -import util -import re -import datetime - -SMB_STATUS_SUCCESS = 0x0 -SMB_COM_OPEN = 0x02 # Open a file. -SMB_COM_CLOSE = 0x04 # Close a file. -SMB_COM_NT_CREATE_ANDX = 0xa2 # Create or open a file or a directory. -SMB_COM_WRITE_ANDX = 0x2f # Extended file write with AndX chaining. -SMB_COM_READ_ANDX = 0x2E -SMB_COM_SESSION_SETUP_ANDX = 0x73 - - -class DshellDecoder(SMBDecoder): - - def __init__(self): - # dictionary indexed by uid, points to login domain\name (string) - self.uidname = {} - self.fidhandles = {} # dictionary to map fid handles to psexec objects - # dictionary of psexec objects, indexed by conn+PID (use sessIndex - # function) - self.psexecobjs = {} - # FID won't work as an index because each stream has its own - SMBDecoder.__init__(self, - name='psexec', - description='Extract command/response information from psexec over smb', - filter='tcp and (port 445 or port 139)', - filterfn=lambda t: t[0][1] == 445 or t[1][1] == 445 or t[0][1] == 139 or t[1][1] == 139, - author='amm', - optiondict={ - 'alertsonly': {'action': 'store_true', 'help': 'only dump alerts, not content'}, - 'htmlalert': {'action': 'store_true', 'help': 'include html as named value in alerts'}, - 'time': {'action': 'store_true', 'help': 'display command/response timestamps'} - } - ) - self.legacy = True - # self.out=colorout.ColorOutput(title='psexec') - self.out = colorout.ColorOutput() - - def sessIndexFromPID(self, conn, pid): - return ':'.join((str(conn.starttime), conn.sip, str(conn.sport), conn.dip, str(conn.dport), pid)) - - def connectionHandler(self, conn): - SMBDecoder.connectionHandler(self, conn) - for k in self.psexecobjs.keys(): - del self.psexecobjs[k] - - # - # Internal class to contain psexec session information - # - class psexec: - - def __init__(self, parent, conn, hostname, pid, opentime): - self.parent = parent - self.conn = conn - self.hostname = hostname - self.pid = pid - self.opentime = opentime - self.closetime = conn.endtime - self.username = '' - self.open_iohandles = {} # indexed by FID, points to filename - self.closed_iohandles = {} - self.msgList = [] # List of tuples (text, direction) - self.csCount = 0 - self.scCount = 0 - self.csBytes = 0 - self.scBytes = 0 - self.lastDirection = '' - - def addmsg(self, text, direction, ts): - # Only store timestamp information if this is a change in direction - if direction == self.lastDirection: - self.msgList.append((text, direction, None)) - else: - self.msgList.append((text, direction, ts)) - self.lastDirection = direction - if direction == 'cs': - self.csCount += 1 - self.csBytes += len(text) - elif direction == 'sc': - self.scCount += 1 - self.scBytes += len(text) - - def addIO(self, fid, name): - if fid in self.open_iohandles: - self.parent.warn("IO Handle with FID %s (%s) is already associated with psexec session %d" % ( - hex(fid), name, self.pid)) - self.open_iohandles[fid] = name - - def delIO(self, fid): - if fid in self.open_iohandles: - self.closed_iohandles[fid] = self.open_iohandles[fid] - del self.open_iohandles[fid] - - def handleCount(self): - return len(self.open_iohandles) - # - # Long output (screen/html) - # - - def write(self, out=None): - if out == None: - out = self.parent.out - out.write("PSEXEC Service from host %s with PID %s\n" % - (self.hostname, self.pid), formatTag='H1') - if len(self.username): - out.write("User: %s\n" % (self.username), formatTag='H2') - out.write("Start: %s UTC\n End: %s UTC\n" % (datetime.datetime.utcfromtimestamp( - self.conn.starttime), datetime.datetime.utcfromtimestamp(self.conn.endtime)), formatTag='H2') - out.write("%s:%s -> %s:%s\n" % (self.conn.clientip, self.conn.clientport, - self.conn.serverip, self.conn.serverport), formatTag="H2", direction="cs") - out.write("%s:%s -> %s:%s\n\n" % (self.conn.serverip, self.conn.serverport, - self.conn.clientip, self.conn.clientport), formatTag="H2", direction="sc") - for msg in self.msgList: - out.write( - msg[0], direction=msg[1], timestamp=msg[2], time=self.parent.time) - out.write("\n") - # - # Short output (alert) - # - - def alert(self): - kwargs = {'hostname': self.hostname, 'pid': self.pid, 'username': self.username, - 'opentime': self.opentime, 'closetime': self.closetime, - 'csCount': self.csCount, 'scCount': self.scCount, 'csBytes': self.csBytes, 'scBytes': self.scBytes} - if self.parent.htmlalert: - htmlfactory = colorout.ColorOutput( - htmlgenerator=True, title="psexec") - self.write(htmlfactory) - htmlfactory.close() - kwargs['html'] = htmlfactory.htmldump() - kwargs.update(self.conn.info()) - kwargs['ts'] = self.opentime - self.parent.alert( - "Host: %s, PID: %s, CS: %d, SC: %d, User: %s" % ( - self.hostname, self.pid, self.csBytes, self.scBytes, self.username), - kwargs - ) - - def __del__(self): - if self.parent.alertsonly: - self.alert() - else: - self.write() - - def SMBHandler(self, conn, request=None, response=None, requesttime=None, responsetime=None, cmd=None, status=None): - # we only care about valid responses and matching request/response user - # IDs - if status == SMB_STATUS_SUCCESS and request.uid == response.uid: - - if cmd == SMB_COM_SESSION_SETUP_ANDX and type(status) != type(None): - auth_record = request.PARSE_SESSION_SETUP_ANDX_REQUEST( - request.smbdata) - if not(auth_record): - return - domain_name = auth_record.domain_name - user_name = auth_record.user_name - self.uidname[response.uid] = "%s\\%s" % ( - domain_name, user_name) - - # file is being requested/opened - elif cmd == SMB_COM_NT_CREATE_ANDX: - self.debug('%s UID: %s MID: %s NT Create AndX Status: %s' % ( - conn.addr, request.uid, response.mid, hex(status))) - filename = request.PARSE_NT_CREATE_ANDX_REQUEST( - request.smbdata) - if type(filename) == type(None): - self.debug('Error: smb.SMB.PARSE_NT_CREATE_ANDX_REQUEST\n%s' % util.hexPlusAscii( - request.smbdata)) - return - - fid = response.PARSE_NT_CREATE_ANDX_RESPONSE(response.smbdata) - - if fid == -1: - self.debug('Error: smb.SMB.PARSE_NT_CREATE_ANDX_RESPONSE\n%s' % util.hexPlusAscii( - response.smbdata)) - self.debug(util.hexPlusAscii(response.smbdata)) - return - match = re.search( - r'psexecsvc-(.*)-(\d+)-(stdin|stdout|stderr)', filename) - if not match: - return - - # We have a PSEXEC File Handle! - hostname = match.group(1) - pid = match.group(2) - iohandleName = match.group(3) - sessionIndex = self.sessIndexFromPID(conn, pid) - if not sessionIndex in self.psexecobjs: - self.psexecobjs[sessionIndex] = self.psexec( - self, conn, hostname, pid, requesttime) - self.fidhandles[fid] = self.psexecobjs[sessionIndex] - self.fidhandles[fid].addIO(fid, filename) - if response.uid in self.uidname: - self.fidhandles[fid].username = self.uidname[response.uid] - - elif cmd == SMB_COM_WRITE_ANDX: # write data to the file - fid, rawbytes = request.PARSE_WRITE_ANDX(request.smbdata) - self.debug('COM_WRITE_ANDX\n%s' % - (util.hexPlusAscii(request.smbdata))) - if fid in self.fidhandles: - self.fidhandles[fid].addmsg(rawbytes, 'cs', requesttime) - - elif cmd == SMB_COM_READ_ANDX: # write data to the file - fid = request.PARSE_READ_ANDX_Request(request.smbdata) - rawbytes = response.PARSE_READ_ANDX_Response(response.smbdata) - self.debug('COM_READ_ANDX (FID %s)\n%s' % - (fid, util.hexPlusAscii(response.smbdata))) - if fid in self.fidhandles: - self.fidhandles[fid].addmsg(rawbytes, 'sc', responsetime) - - elif cmd == SMB_COM_CLOSE: # file is being closed - fid = request.PARSE_COM_CLOSE(request.smbdata) - if fid in self.fidhandles.keys(): - self.fidhandles[fid].delIO(fid) - self.debug('Closing FID: %s Filename: %s' % - (hex(fid), self.fidhandles[fid])) - if self.fidhandles[fid].handleCount() < 1 and self.sessIndexFromPID(conn, self.fidhandles[fid].pid) in self.psexecobjs: - self.psexecobjs[ - self.sessIndexFromPID(conn, self.fidhandles[fid].pid)].closetime = responsetime - del self.psexecobjs[ - self.sessIndexFromPID(conn, self.fidhandles[fid].pid)] - del self.fidhandles[fid] - - -if __name__ == '__main__': - dObj = DshellDecoder() - print dObj -else: - dObj = DshellDecoder() diff --git a/decoders/smb/rip-smb-uploads.py b/decoders/smb/rip-smb-uploads.py deleted file mode 100644 index 5abe9e6..0000000 --- a/decoders/smb/rip-smb-uploads.py +++ /dev/null @@ -1,126 +0,0 @@ -""" -2015 Feb 13 - -Goes through SMB traffic and snips out any file uploads it sees. - -Specifically, it looks for create, write, and close commands and creates a -local file, writes the raw data to the local file, and closes the file, -respectively. -""" - -import dshell -from smbdecoder import SMBDecoder -import sys -import util -import os - -SMB_STATUS_SUCCESS = 0x0 -SMB_COM_OPEN = 0x02 # Open a file. -SMB_COM_CLOSE = 0x04 # Close a file. -SMB_COM_NT_CREATE_ANDX = 0xa2 # Create or open a file or a directory. -SMB_COM_WRITE_ANDX = 0x2f # Extended file write with AndX chaining. - - -class DshellDecoder(SMBDecoder): - - def __init__(self): - self.fidhandles = {} # dictionary to map fid handles to filenames - # dictionary to map fid handles to local filedescriptors - # (ie. fd = open(fname,'wb')) - self.fds = {} - self.outdir = None - SMBDecoder.__init__(self, - name='rip-smb-uploads', - description='Extract files uploaded via SMB', - filter='tcp and port 445', - filterfn=lambda t: t[0][1] == 445 or t[1][1] == 445, - author='bg', - optiondict={ - "outdir": {"help": "Directory to place files (default: ./smb_out)", "default": "./smb_out", "metavar": "DIRECTORY"}, - } - ) - self.legacy = True - - def preModule(self): - if not os.path.exists(self.outdir): - try: - os.makedirs(self.outdir) - except OSError as e: - self.error("Could not create directory '%s'\n%s" % (self.outdir, e)) - sys.exit(1) - - def SMBHandler(self, conn, request=None, response=None, requesttime=None, responsetime=None, cmd=None, status=None): - # we only care about valid responses and matching request/response user - # IDs - if status == SMB_STATUS_SUCCESS and request.uid == response.uid: - - if cmd == SMB_COM_NT_CREATE_ANDX: # file is being requested/opened - self.debug('%s UID: %s MID: %s NT Create AndX Status: %s' % ( - conn.addr, request.uid, response.mid, hex(status))) - filename = request.PARSE_NT_CREATE_ANDX_REQUEST( - request.smbdata) - if type(filename) == type(None): - self.debug('Error: smb.SMB.PARSE_NT_CREATE_ANDX_REQUEST\n%s' % util.hexPlusAscii(request.smbdata)) - return - - fid = response.PARSE_NT_CREATE_ANDX_RESPONSE(response.smbdata) - self.debug('%s FID: %s' % (conn.addr, fid)) - - if fid == -1: - self.debug('Error: smb.SMB.PARSE_NT_CREATE_ANDX_RESPONSE\n%s' % util.hexPlusAscii(response.smbdata)) - self.debug(util.hexPlusAscii(response.smbdata)) - return - self.fidhandles[fid] = self.__localfilename(self.outdir, os.path.normpath(filename)) - - elif cmd == SMB_COM_WRITE_ANDX: # write data to the file - fid, rawbytes = request.PARSE_WRITE_ANDX(request.smbdata) - - # do we have a local fd already open to handle this write? - if fid in self.fds.keys(): - self.fds[fid].write(rawbytes) - else: - try: - fidhandle = self.fidhandles[fid] - self.fds[fid] = open(fidhandle, 'wb') - self.fds[fid].write(rawbytes) - except KeyError: - self.debug("Error: Could not find fidhandle for FID %s" % (fid)) - return - - elif cmd == SMB_COM_CLOSE: # file is being closed - fid = request.PARSE_COM_CLOSE(request.smbdata) - if fid in self.fds.keys(): - self.log(repr(conn) + '\t%s' % (self.fidhandles[fid])) - self.fds[fid].close() - del self.fds[fid] - if fid in self.fidhandles.keys(): - self.debug('Closing FID: %s Filename: %s' % - (hex(fid), self.fidhandles[fid])) - del self.fidhandles[fid] - - - def __localfilename(self, path, origname): - # Generates a local file name based on the original - tmp = origname.replace("\\", "_") - tmp = tmp.replace("/", "_") - tmp = tmp.replace(":", "_") - localname = '' - for c in tmp: - if ord(c) > 32 and ord(c) < 127: - localname += c - else: - localname += "%%%02X" % ord(c) - localname = os.path.join(path, localname) - postfix = '' - i = 0 - while os.path.exists(localname + postfix): - i += 1 - postfix = "_%02d" % i - return localname + postfix - - -if __name__ == '__main__': - dObj = DshellDecoder() - print dObj -else: - dObj = DshellDecoder() diff --git a/decoders/smb/smbfiles.py b/decoders/smb/smbfiles.py deleted file mode 100644 index 6b87ad1..0000000 --- a/decoders/smb/smbfiles.py +++ /dev/null @@ -1,210 +0,0 @@ -""" -2015 Feb 13 - -Processes SMB traffic and tries to find file reads and writes. - -When a read or write action is seen, the size of the transfer is recorded in -a new "smbfile" object and a count is incremented for the type of action taken -(i.e. reads+1 or writes+1). - -After the connection closes, an alert is generated showing some information -about the connection, the action taken (read, write, or both), the full name -of the file and how much data was transferred. -""" - -from smbdecoder import SMBDecoder -import util - -SMB_STATUS_SUCCESS = 0x0 -SMB_COM_OPEN = 0x02 # Open a file. -SMB_COM_CLOSE = 0x04 # Close a file. -SMB_COM_NT_CREATE_ANDX = 0xa2 # Create or open a file or a directory. -SMB_COM_WRITE_ANDX = 0x2f # Extended file write with AndX chaining. -SMB_COM_READ_ANDX = 0x2E -SMB_COM_SESSION_SETUP_ANDX = 0x73 -SMB_COM_TREE_CONNECT_ANDX = 0x75 - - -class DshellDecoder(SMBDecoder): - - def __init__(self): - # dictionary indexed by uid, points to login tuple (hostname, - # domain\name) (string) - self.uidname = {} - self.tidmap = {} # dictionary indexed by tid, points to tree path - # dictionary of smb file objects, indexed by conn+fid (use - # sessIndexFromFID function) - self.smbfileobjs = {} - SMBDecoder.__init__(self, - name='smbfiles', - description='List files accessed via smb', - filter='tcp and (port 445 or port 139)', - filterfn=lambda t: t[0][1] == 445 or t[1][1] == 445 or t[0][1] == 139 or t[1][1] == 139, - author='amm', - optiondict={ - 'nopsexec': {'action': 'store_true', 'help': 'supress psexecsvc streams from output'}, - 'activeonly': {'action': 'store_true', 'help': 'only output files with reads or writes'} - } - ) - - def fileIndexFromFID(self, conn, fid): - return ':'.join((str(conn.starttime), conn.sip, str(conn.sport), conn.dip, str(conn.dport), str(fid))) - - def connectionHandler(self, conn): - SMBDecoder.connectionHandler(self, conn) - for k in self.smbfileobjs.keys(): - del self.smbfileobjs[k] - - # - # Internal class to contain info about files - # - class smbfile: - - def __init__(self, parent, conn, fid, opentime, filename, username, hostname, treepath): - self.parent = parent - self.conn = conn - self.opentime = opentime - self.closetime = conn.endtime - self.filename = filename - self.username = username - self.hostname = hostname - self.treepath = treepath - self.writes = 0 - self.reads = 0 - self.byteswritten = 0 - self.bytesread = 0 - - def writeblock(self, data): - self.writes += 1 - self.byteswritten += len(data) - - def readblock(self, data): - self.reads += 1 - self.bytesread += len(data) - - def alert(self): - if self.parent.nopsexec and self.filename.lower().startswith('\psexecsvc'): - return - if self.reads > 0 and self.writes > 0: - mode = 'B' - elif self.reads > 0: - mode = 'R' - elif self.writes > 0: - mode = 'W' - else: - mode = '-' - if self.parent.activeonly and mode == '-': - return - kwargs = { - 'filename': self.filename, 'username': self.username, 'hostname': self.hostname, 'treepath': self.treepath, - 'opentime': self.opentime, 'closetime': self.closetime, 'mode': mode, - 'writes': self.writes, 'reads': self.reads, 'byteswritten': self.byteswritten, 'bytesread': self.bytesread - } - kwargs.update(self.conn.info()) - kwargs['ts'] = self.opentime - self.parent.alert( - "%s %s%s (%s)" % ( - self.username, self.treepath, self.filename, mode), - kwargs - ) - - def __del__(self): - self.alert() - - def SMBHandler(self, conn, request=None, response=None, requesttime=None, responsetime=None, cmd=None, status=None): - # we only care about valid responses and matching request/response user - # IDs - if status == SMB_STATUS_SUCCESS and request.uid == response.uid: - - # - # SMB_COM_SESSION_SETUP - Start tracking user authentication by UID - # - if cmd == SMB_COM_SESSION_SETUP_ANDX and type(status) != type(None): - auth_record = request.PARSE_SESSION_SETUP_ANDX_REQUEST( - request.smbdata) - if not(auth_record): - return - domain_name = auth_record.domain_name - user_name = auth_record.user_name - host_name = auth_record.host_name - self.uidname[response.uid] = ( - host_name, "%s\%s" % (domain_name, user_name)) - - # - # SMB_COM_TREE_CONNECT - Start tracking tree by TID - # - if cmd == SMB_COM_TREE_CONNECT_ANDX: - request_path = unicode(request.SMB_COM_TREE_CONNECT_ANDX_Request( - request.smbdata), 'utf-16').encode('utf-8').rstrip('\0') - self.tidmap[response.tid] = request_path - - # - # SMB_COM_NT_CREATE - Start tracking file handle by FID - # - # file is being requested/opened - elif cmd == SMB_COM_NT_CREATE_ANDX: - self.debug('%s UID: %s MID: %s NT Create AndX Status: %s' % ( - conn.addr, request.uid, response.mid, hex(status))) - filename = request.PARSE_NT_CREATE_ANDX_REQUEST( - request.smbdata) - if type(filename) == type(None): - self.debug('Error: smb.SMB.PARSE_NT_CREATE_ANDX_REQUEST\n%s' % util.hexPlusAscii( - request.smbdata)) - return - fid = response.PARSE_NT_CREATE_ANDX_RESPONSE(response.smbdata) - if fid == -1: - self.debug('Error: smb.SMB.PARSE_NT_CREATE_ANDX_RESPONSE\n%s' % util.hexPlusAscii( - response.smbdata)) - self.debug(util.hexPlusAscii(response.smbdata)) - return - # Setup smbfile object - if response.uid in self.uidname: - hostname, username = self.uidname[response.uid] - else: - hostname = 'Unknown' - username = 'Unknown\\Unknown' - if response.tid in self.tidmap: - treepath = self.tidmap[response.tid] - else: - treepath = '' - fileobj = self.smbfile( - self, conn, fid, requesttime, filename, username, hostname, treepath) - fileIndex = self.fileIndexFromFID(conn, fid) - self.smbfileobjs[fileIndex] = fileobj - - # - # SMB_COM_WRITE - File writes - # - elif cmd == SMB_COM_WRITE_ANDX: # write data to the file - fid, rawbytes = request.PARSE_WRITE_ANDX(request.smbdata) - #self.debug('COM_WRITE_ANDX\n%s' % (util.hexPlusAscii(request.smbdata))) - fileIndex = self.fileIndexFromFID(conn, fid) - if fileIndex in self.smbfileobjs: - self.smbfileobjs[fileIndex].writeblock(rawbytes) - - # - # SMB_COM_READ - File reads - # - elif cmd == SMB_COM_READ_ANDX: # read data from the file - fid = request.PARSE_READ_ANDX_Request(request.smbdata) - rawbytes = response.PARSE_READ_ANDX_Response(response.smbdata) - #self.debug('COM_READ_ANDX (FID %s)\n%s' % (fid, util.hexPlusAscii(response.smbdata))) - fileIndex = self.fileIndexFromFID(conn, fid) - if fileIndex in self.smbfileobjs: - self.smbfileobjs[fileIndex].readblock(rawbytes) - - # - # SMB_COM_CLOSE - Closing file - # - elif cmd == SMB_COM_CLOSE: # file is being closed - fid = request.PARSE_COM_CLOSE(request.smbdata) - fileIndex = self.fileIndexFromFID(conn, fid) - if fileIndex in self.smbfileobjs: - self.smbfileobjs[fileIndex].closetime = responsetime - del self.smbfileobjs[fileIndex] - -if __name__ == '__main__': - dObj = DshellDecoder() - print dObj -else: - dObj = DshellDecoder() diff --git a/decoders/templates/PacketDecoder.py b/decoders/templates/PacketDecoder.py deleted file mode 100644 index 16becda..0000000 --- a/decoders/templates/PacketDecoder.py +++ /dev/null @@ -1,31 +0,0 @@ -#!/usr/bin/env python - -import dshell -import output -import util - - -class DshellDecoder(dshell.IPDecoder): - - '''generic packet-level decoder template''' - - def __init__(self, **kwargs): - '''decoder-specific config''' - - '''pairs of 'option':{option-config}''' - self.optiondict = {} - - '''bpf filter, for ipV4''' - self.filter = '' - '''filter function''' - # self.filterfn= - - '''init superclasses''' - self.__super__().__init__(**kwargs) - - def packetHandler(self, ip): - '''handle as Packet() ojects''' - pass - -# create an instance at load-time -dObj = DshellDecoder() diff --git a/decoders/templates/SessionDecoder.py b/decoders/templates/SessionDecoder.py deleted file mode 100644 index c2bc04d..0000000 --- a/decoders/templates/SessionDecoder.py +++ /dev/null @@ -1,47 +0,0 @@ -#!/usr/bin/env python - -import dshell -import output -import util - - -class DshellDecoder(dshell.TCPDecoder): - - '''generic session-level decoder template''' - - def __init__(self, **kwargs): - '''decoder-specific config''' - - '''pairs of 'option':{option-config}''' - self.optiondict = {} - - '''bpf filter, for ipV4''' - self.filter = '' - '''filter function''' - # self.filterfn= - - '''init superclasses''' - self.__super__().__init__(**kwargs) - - def packetHandler(self, udp, data): - '''handle UDP as Packet(),payload data - remove this if you want to make UDP into pseudo-sessions''' - pass - - def connectionInitHandler(self, conn): - '''called when connection starts, before any data''' - pass - - def blobHandler(self, conn, blob): - '''handle session data as soon as reassembly is possible''' - pass - - def connectionHandler(self, conn): - '''handle session once all data is reassembled''' - pass - - def connectionCloseHandler(self, conn): - '''called when connection ends, after data is handled''' - -# create an instance at load-time -dObj = DshellDecoder() diff --git a/decoders/voip/sip.py b/decoders/voip/sip.py deleted file mode 100644 index 7850dc1..0000000 --- a/decoders/voip/sip.py +++ /dev/null @@ -1,217 +0,0 @@ -# -# Author: MM - https://github.com/1modm -# -# The Session Initiation Protocol (SIP) is the IETF protocol for VOIP and other text and multimedia sessions -# and is a communications protocol for signaling and controlling. -# SIP is independent from the underlying transport protocol. It runs on the Transmission Control Protocol (TCP), -# the User Datagram Protocol (UDP) or the Stream Control Transmission Protocol (SCTP) -# -# Rate and codec calculation thanks to https://git.ucd.ie/volte-and-of/voip-pcapy -# -# RFC: https://www.ietf.org/rfc/rfc3261.txt -# -# SIP is a text-based protocol with syntax similar to that of HTTP. -# There are two different types of SIP messages: requests and responses. -# - Requests initiate a SIP transaction between two SIP entities for establishing, controlling, and terminating sessions. -# - Responses are send by the user agent server indicating the result of a received request. -# -# - SIP session setup example: -# -# Alice's . . . . . . . . . . . . . . . . . . . . Bob's -# softphone SIP Phone -# | | | | -# | INVITE F1 | | | -# |--------------->| INVITE F2 | | -# | 100 Trying F3 |--------------->| INVITE F4 | -# |<---------------| 100 Trying F5 |--------------->| -# | |<-------------- | 180 Ringing F6 | -# | | 180 Ringing F7 |<---------------| -# | 180 Ringing F8 |<---------------| 200 OK F9 | -# |<---------------| 200 OK F10 |<---------------| -# | 200 OK F11 |<---------------| | -# |<---------------| | | -# | ACK F12 | -# |------------------------------------------------->| -# | Media Session | -# |<================================================>| -# | BYE F13 | -# |<-------------------------------------------------| -# | 200 OK F14 | -# |------------------------------------------------->| -# | | -# - -import dshell -import dpkt -import datetime -import colorout - -class DshellDecoder(dshell.UDPDecoder): - - def __init__(self): - dshell.UDPDecoder.__init__(self, - name='sip', - description='Session Initiation Protocol (SIP) capture decoder', - longdescription=""" -The Session Initiation Protocol (SIP) decoder will extract the Call ID, User agent, Codec, Method, -SIP call, Host, and Client MAC address from every SIP request or response packet found in the given pcap. - -General usage: - decode -d sip - -Detailed usage: - decode -d sip --sip_showpkt - -Layer2 sll usage: - decode -d sip --no-vlan --layer2=sll.SLL - -SIP over TCP: - decode -d sip --bpf 'tcp' - -SIP is a text-based protocol with syntax similar to that of HTTP, so you can use followstream decoder: - decode -d followstream --ebpf 'port 5060' --bpf 'udp' - -Examples: - - https://wiki.wireshark.org/SampleCaptures#SIP_and_RTP - http://vignette3.wikia.nocookie.net/networker/images/f/fb/Sample_SIP_call_with_RTP_in_G711.pcap/revision/latest?cb=20140723121754 - - decode -d sip metasploit-sip-invite-spoof.pcap - decode -d sip Sample_SIP_call_with_RTP_in_G711.pcap - -Output: - - <-- SIP Request --> - Timestamp: 2016-09-21 22:44:28.220185 UTC - Protocol: UDP - Size: 435 bytes - Sequence and Method: 1 ACK - From: 10.5.1.8:5060 (00:20:80:a1:13:db) to 10.5.1.7:5060 (15:2a:01:b4:0f:47) - Via: SIP/2.0/UDP 10.5.1.8:5060;branch=z9hG4bK940bdac4-8a13-1410-9e58-08002772a6e9;rport - SIP call: "M" ;tag=0ba2d5c4-8a13-1910-9d56-08002772a6e9 --> "miguel" ;tag=84538c9d-ba7e-e611-937f-68a3c4f0d6ce - Call ID: 0ba2d5c4-8a13-1910-9d57-08002772a6e9@M-PC - - --> SIP Response <-- - Timestamp: 2016-09-21 22:44:27.849761 UTC - Protocol: UDP - Size: 919 bytes - Sequence and Method: 1 INVITE - From: 10.5.1.7:5060 (02:0a:40:12:30:23) to 10.5.1.8:5060 (d5:02:03:94:31:1b) - Via: SIP/2.0/UDP 10.5.1.8:5060;branch=z9hG4bK26a8d5c4-8a13-1910-9d58-08002772a6e9;rport=5060;received=10.5.1.8 - SIP call: "M" ;tag=0ba2d5c4-8a13-1910-9d56-08002772a6e9 --> "miguel" ;tag=84538c9d-ba7e-e611-937f-68a3c4f0d6ce - Call ID: 0ba2d5c4-8a13-1910-9d57-08002772a6e9@M-PC - Codec selected: PCMU - Rate selected: 8000 - -Detailed Output: - - --> SIP Response <-- - Timestamp: 2016-09-21 22:44:25.360974 UTC - Protocol: UDP - Size: 349 bytes - From: 10.5.1.7:5060 (15:2a:01:b4:0f:47) to 10.5.1.8:5060 (00:20:80:a1:13:db) - SIP/2.0 100 Trying - content-length: 0 - via: SIP/2.0/UDP 10.5.1.8:5060;branch=z9hG4bK26a8d5c4-8a13-1910-9d58-08002772a6e9;rport=5060;received=10.5.1.8 - from: "M" ;tag=0ba2d5c4-8a13-1910-9d56-08002772a6e9 - to: - cseq: 1 INVITE - call-id: 0ba2d5c4-8a13-1910-9d57-08002772a6e9@M-PC - - --> SIP Response <-- - Timestamp: 2016-09-21 22:44:25.387780 UTC - Protocol: UDP - Size: 585 bytes - From: 10.5.1.7:5060 (15:2a:01:b4:0f:47) to 10.5.1.8:5060 (00:20:80:a1:13:db) - SIP/2.0 180 Ringing - content-length: 0 - via: SIP/2.0/UDP 10.5.1.8:5060;branch=z9hG4bK26a8d5c4-8a13-1910-9d58-08002772a6e9;rport=5060;received=10.5.1.8 - from: "M" ;tag=0ba2d5c4-8a13-1910-9d56-08002772a6e9 - require: 100rel - rseq: 694867676 - user-agent: Ekiga/4.0.1 - to: "miguel" ;tag=84538c9d-ba7e-e611-937f-68a3c4f0d6ce - contact: "miguel" - cseq: 1 INVITE - allow: INVITE,ACK,OPTIONS,BYE,CANCEL,SUBSCRIBE,NOTIFY,REFER,MESSAGE,INFO,PING,PRACK - call-id: 0ba2d5c4-8a13-1910-9d57-08002772a6e9@M-PC -""", - filter='udp', - author='mm', - optiondict={ - 'showpkt': {'action': 'store_true', 'default': False, 'help': 'Display the full SIP response or request body.'} - } - ) - - self.out = colorout.ColorOutput() - self.rate = None - self.codec = None - self.direction = None - self.output = None - - def preModule(self): - if 'setColorMode' in dir(self.out): - self.out.setColorMode() - - def packetHandler(self, udp, data): - # Initialize - self.output = False - self.rate = str() - self.codec = str() - self.direction = str() - - # Check if exists SIP Request - try: - if dpkt.sip.Request(data): - siptxt = "<-- SIP Request -->" - sippkt = dpkt.sip.Request(data) - self.direction = "sc" - self.output = True - except dpkt.UnpackError, e: - pass - - # Check if exists SIP Response - try: - if dpkt.sip.Response(data): - siptxt = "--> SIP Response <--" - sippkt = dpkt.sip.Response(data) - self.direction = "cs" - self.output = True - except dpkt.UnpackError, e: - pass - - # If a SIP request or SIP response exists, print the results - if self.output: - # Common output - self.out.write("\n{0} \nTimestamp: {1} UTC - Protocol: {2} - Size: {3} bytes\n".format(siptxt, datetime.datetime.utcfromtimestamp( - udp.ts), udp.proto, udp.info()['bytes']), formatTag="H2", direction=self.direction) - self.out.write("From: {0}:{1} ({2}) to {3}:{4} ({5}) \n".format(udp.sip, udp.sport, udp.smac, - udp.dip, udp.dport, udp.dmac), formatTag="H2", direction=self.direction) - - # Show full SIP packet detail - if self.showpkt: - self.out.write("{0}\n".format(sippkt), formatTag="H2", direction=self.direction) - - # Show essential SIP Requests or Responses headers - else: - user_agent = sippkt.headers.get('user-agent') - allow = sippkt.headers.get('allow') - sip_from = sippkt.headers.get('from') - sip_to = sippkt.headers.get('to') - sip_callid = sippkt.headers.get('call-id') - via = sippkt.headers.get('via') - cseq = sippkt.headers.get('cseq') - - if cseq: - self.out.write("Sequence and Method: {0}\n".format(cseq), formatTag="H2", direction=self.direction) - - if via: - self.out.write("Via: {0}\nSIP call: {1} --> {2}\nCall ID: {3}\n".format(via, - sip_from, sip_to, sip_callid), formatTag="H2", direction=self.direction) - - # codec and rate negotiated - for x in range(sippkt.body.find(' ',sippkt.body.find('a='))+1,sippkt.body.find('/',sippkt.body.find('a='))): - self.codec += sippkt.body[x] - for x in range(sippkt.body.find(' ',sippkt.body.find('a='))+6,sippkt.body.find('/',sippkt.body.find('a='))+5): - self.rate +=sippkt.body[x] - - if (self.codec and self.rate): - self.out.write("Codec selected: {0} \nRate selected: {1} \n".format(self.codec, self.rate), formatTag="H2", direction=self.direction) - -if __name__ == '__main__': - dObj = DshellDecoder() - print dObj -else: - dObj = DshellDecoder() \ No newline at end of file diff --git a/dist/Dshell-3.1.3.tar.gz b/dist/Dshell-3.1.3.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..b3fc79d056acad8c8030c2f4ba3a1601662e2f21 GIT binary patch literal 85139 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 Settings -> Project: DShell -> Project Structure` set the folders `bin`, `decoders`, `lib`, and `lib/output` -as sources. Then click OK. After a few seconds, you should now see all the red underlines on imports disappear. - -![](image1.png) - -### Project Interpreter -We also need to tell the Python interpreter where to find the relevant files. This is useful if you want to import -Dshell modules within the interpreter. Under `File -> Settings -> Project: DShell -> Project Interpreter` click the -gear icon next to the dropdown with the project interpreter you are going to use, and then select `More…` - -![](image2.png) - -Then with your current Python interpreter highlighted, click the small folder tree icon (below the filter icon) to see a -window of `Interpreter Paths`. In this window click the `+` icon to the right and add the four folders added earlier -(`bin`, `decoders`, `lib`, and `lib/output`). - -![](image3.png) - -You should now be able to import decoders and other Dshell modules using the built in Python interpreter. - -![](image4.png) - - -## Run Configurations -Run configurations in PyCharm allow a user to specify how to run tasks and programs. In the context of Dshell, a -configuration can be setup to specify which decoder to run, how to setup the environment variables needed by Dshell, and what working directory to use. - -### Opening Configurations -The first step within PyCharm is to open up the interface to edit configurations. This can be done through the toolbar as -shown below or by using the menu to navigate to `Run -> Edit Configurations…` - -![](image5.png) - -### Adding a New Python Configuration for Dshell -Once the configurations interface is open, the next step is to add a new configuration. Since Dshell utilizes Python, a -Python configuration needs to be created. Select the `+` symbol near the top left and select `Python` in the drop down menu. - -![](image6.png) - -### Specifying the Configuration Details -Now that the configuration window is open, the following fields need to be populated: - -- Script: The full path to the `decode.py` script in Dshell. -- Script parameters: The parameters that would be passed in when running the decode command. -- Environment variables: The environment variables found in the `.dshellrc` file in Dshell’s root directory. This is detailed more below. -- Working directory: If all the settings use absolute paths, the working directory can be set to anything. Setting the working directory to a location where output files should be placed is a reasonable option. - -![](image7.png) - -### Specifying the Environment Variables -The environment variables in the configuration are important to mirror the Dshell shell. - -When first running Dshell, some of the first steps are to build the project using make and to run the "dshell" script. -The build step is relevant here because it produces the `.dshellrc` file that the "dshell" script depends on to configure the shell’s environment. - -For the PyCharm configuration, open up the `.dshellrc` file in Dshell’s directory and take a look at the environment -variables. Use these values to set the `Environment variables` field in the configuration. - -![](image8.png) - -### Save the Configuration -Now that the configuration has been setup, just give it a name and hit OK. - - -## Debugging - -### Select Your Configuration -Before debugging, make sure the configuration you want is selected. - -![](image9.png) - -### Start Debugging -Once the configuration is set, make sure to set any breakpoints. Then, start up the debugger. Further details on how to use the debugger can be found online. - -![](image10.png) diff --git a/doc/generate-doc.sh b/doc/generate-doc.sh deleted file mode 100755 index 878fd98..0000000 --- a/doc/generate-doc.sh +++ /dev/null @@ -1,12 +0,0 @@ -#!/bin/bash -d=`pwd` -if [ "$1" ]; then d=$1; fi -source $d/.dshellrc || exit - -for f in $d/lib/*.py $d/lib/output/*.py $d/bin/*.py; do - pydoc -w `basename $f|cut -d. -f1` -done - -for f in `find $d/decoders -name \*.py -not -name __init__.py`; do - pydoc -w $f -done diff --git a/doc/image1.png b/doc/image1.png deleted file mode 100644 index a2733042f07c92e673547aea243fd1b656b3b0ea..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 82574 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

    I23XrRc@c<6tj|8{1QI$NQ9rTUb8 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 V0v`GD2N*+>kyMZ<5&Qi0{{X8mH9-IX diff --git a/doc/image10.png b/doc/image10.png deleted file mode 100644 index 0ff29dcae4a85ce4e4043a3f212673e1d8f978a3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 38111 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�l8{p%M)SVr z%!el|R2L}=Ep7&hH>NSZ}iBa!_xl^rBCkcfnRe-F#n8YfbPe8x86T1r@E6uKx9{wY}md zabtdj<1urtqAJ%ew!S(G+OiG8YO8bHPl8c)x@A4Ddc0msk!yZ1w++p01&T{3TDI4` zBO06Q`@8D8n(_i~Z(^)mrEa^=CpxvQy?&str6$31uV{s$D%0xV^^}5=-rn{X?P)i5 zi0HbTed98^x?2ZYi{l=iu~S!2Qe{}|y^@q))Z5u0?x?NLezeVyrbrR(zUom}ST}!%9HF>MnPY#(yH(tf>AG8o zz7ne`@hGN%M=YGwN<7$&jw1z?Yx*$1rY-jF8s1_mO^rt^J%dG2lGoT0kWt!O5p~{< zPN%4-()oI85BtX@H@7zScQ^I57e~1sV60%?j*(f)ri{CL_$wHeu3?NCoseQwybZMsU!RCZkTn6kq( z7yD(48TVpSp`o4H$_;KY9cA&yKr;utq3Zqp!euLHwny*fR#w7kyW6YFBCeRTS8CWE zspxyRn>v$DGgq$KcIhF8xMW15>uvCg&*|>z=x>ZaX(wc?Tqdt6YbaIF44+45P-sG{ z-SKsjZ<>i4`+Hl5+lt*ca8&umS7p2<=+*|srOZ1qgoYa!D>OErPbw-O=xb}ta??Zh ze8~-iUNNDm@{F%|g*UY|4|P=+M7r)XgNq68$y%P+L?Sh$iUJ0m!DO4B%&)ELX{~Io zFYoARX-&CrBT_crb3MDFYOoJf;Co`Vx{#{KVo_JB?}^PW&I>!QtGtp*7py<+R8U>n zD{gKs3ct8X-*DTF+RoabOB)25JF;u4-*(vC5P#>$`MVX(HGvm5>aRJSQ&j_(=xwja zk968=fisL6u?NQowBMi*G=m%*gfS*4Rbx=>>C2NezG~F{q+R!uPQ6dsbU&%r`7A*F zYaOZrjY&gzl~iW1SQG|b&Co#C#@ZabVrOfKGC^HM~MBER5BK#FvuEYEufEO&91ISld|H*;v_Ho15zLIBKg{Of@E#FVvO%p2ptF zQlHDEsc?k4R(6)Qnsg?cr)_F$Zz@pdQkgUgg(EVtu(GqYwl>!@5~y*p{!D?6skyy@ zK*Ug`a5POUEo?NI>Kp`@iK9a>3!0JwXeO(o?C~C5HboxkGp0}8Vp5e=O%5d%l%#p? zQCD8Y=g?Vvk%74-p{y7W&#;DqCdq?!sJ`L1S;d8QEJCa=@I8gFB1O;cM!f zTVfrpZOrww*a}QKmCe&Mwzh(y)HysuYioN0zK}`d8rZC{(4x`VTW&^?%{f#R*qO@J zFtM~Gnp+qeYB1C}RFpAAdREpjzLm9+hAvkHj-f_ns_UEB+F9FK8ySjdbTw6$hQ5`J zwVfq&Q)1C6u%Q~2A=D>~U}s}tVWh6bqYz(YrE_&n%KWh!suDbM!ilnblXd1?yWNyZryE>?{r(6g{!V=B^y zl9ECWmq};RXqubCGV^l-&l{^PCx2t8iZoWJV{V0+T3MSL8fh?iEH?2|jCV_EYNSb{ z(vCOD=U2# zk3}UFgM+ac6lEGu$Jo@?79NHCU!=>YV4JEkxVom6_O@0QdK?Z-k;$B)Lnf2X(UoYZ z%TnX%o7r0$8t|d2Dd}|_293(#Y7w?2wwReNSIAQ1s_R(Nc z&ycIEM(1i7ni30brmexEjSb4Csz`jy%HGDzNJL>#Rak5xIj^xzM0CX>M#mX~AuzJQ z(6+=%+1c5ywb0fEK~q_p#^&~RmS);)0ZoC67{#Gcxw=LONW^dQ)Cd=a!A;EV?X4~K zd3>5Ym8WZFVQM0xF?sqHR@U!2G}jWT!)&<4VDd%!rU--ZY7>1SjZ0M;i+;axA!r79 z2KJb&V0qLSRCS8NG1g*F?pJ~QFI~9vcQTg3+Yz%TRAwFfrLCo|r>mu-EfNZd zpMB8jsuOB*SX3%S87YpYh7dJ%bu>llJa{LKiqJE$TUmjkOq#NavOFOw3KWV85(pw> zaA=IT1D6V@rmCvMWD#vSYzjqHfl5_H^k*~G za2KtRqf8i@6!bt*kQeQ}R@mOvQVjv3HpdZNuRTLSLhFC`|9Pt*mlC*kP2MyKGP!c#;6spvK3S><> zRS6beCC}S^)2p+mD5&VLD?rnMP(Jj>15neDq|^$(-=8-X*I$Pq&7s3 zf+j>K$_iLGWGsZ=LPHi@QJz92a;Y)Ju!6+I)kte75N0I8C}Yf>up>x6pP@q>AICIg z!f0><_L!=~5@1JQ%aFE}XgI}g!e(K@my{LAO~jyL_pMS^R8U}OoqLu%*-(T?R*ga$ zffTGAvFMBm-ZExGHqj9IBr#ts2YMJARHl^zjra`{F>9Kd(iEFWGCGDPH$Eva3bD9s zDmha)6Ix02WK$`siU=d5`ytaMJ?(8^AwvW*;PD-*DKi;rYO2KIjx7gtfNt-4{>=+P zGYI|gS{Z>UY1q~9SygOwSPpAQRa2u=vCOzd+Pzq>dNK&_pV>uvs#}akFZ7DW#XhMT)X4Y&8z!OxfBjVO}6tfdE3vp@-fB6DLkn; z(NMOg$hLhAB*VSZeye*MlkCjhWX6&xyLiVoo`fZ8y?xbpx3%p9NsqE8}GEHR5C$u7zoT?S7k)uyJ^tjI7R+ec?luW22^Y&f&q>^#BNCjpE zLeLCFO%WN%)Pl_>D--U@h-9hW$%MNTj+ zQbB$txM*f8{fxq9Q5X~jMTtHtk`!%1h3^&gz+xyV$uGx2k@@4*{u`VByaHutYVr#5 zD=2j75}<@BSuX{}RkXK-KUUaGRf_To`S)Xv@3YJrYF1_tf@YA^6TdQ>m06jUS(%kt z`MHIlnH9?yD=QMe8=sX~nUz_Ym09_Dg`k<(*qGRu=vkSSS(%ktnU$Yi2%35R{Q2PE z&<_z36AFI@`8#zxE8i=#mj7ji#Dv2C7vxu+7l{dlv-183K{H~pxMK!%c6Rslh`TyF zI=XuM`g+8j?d{S#KNrNky}dnz4&v^fZgCebItfVb{djbt7icMc_v_=w>hrhE{l{X= z@_#>I`WOVm5FYe>_$BB5YoN1RvW2AY-g|U*iFFnwo zLV6>`i{U|WM{`w0WqnIWXMLXIg$v$sRsDTGW<}fEJHXs)mMG5UP}+-Cs7!r(Az>yd%Jo|$@iXZh52@sDI>n4qhBY)wao z2Yb6o+l&WMtEaQIp*TM;H@~>Px$XNnJ@r7BzCTePX-17VD!nKwx-|UqCe3q1w3jkJOzoVu-eSbPcqJ zyWepN&J}l07a2Ocy4nlk!Xjd_+N7RMcw0(TL{d?u|7j~l-tNqX9!czzDoJ+p_W!`U z%dxxDfEcSNF)}i-ptHXZJ$7|>R^=pxMrAa#!Cvnmtu50T=yGVJ>&XcV8GR(fNkG;a zSAZSc*%0bBaqiOl?>e3W*nZu813m3E3Bf)tF3zrxeB&}paW;^Fw59~_EKjj=?&$9) z#*$W>aTp1(rtJ+CiNTUJb#nFzimzoh=!lOw@D@!0PBFZ|u`+F)5smn7rd3C{&I%V(8 zfazR4G$OSO$N0g)-s-$WA9ojL7gyhqxYGL0esM!u#1mKefV)p@Mo}xARMOD|z~0Se zSrNhEB@J!FX6zIXK7T&g*G;fbcUwVfOmtRh_EQJ7Ra$PzO@jm7Qe_E9dywDnp)P-g(V;=NHNK(?;z=D7Vibd(M%U2VO{!$ z1^@X!bCoo8v_wLoXzjVUoRV-Kuh{(NuJRDAr7O2O7l3BEdwTo(`+9r(`uqEPyJtvl zI(vpk>Z9(d{rkVpSKw%AYpM%{#=G1qnsIFH?(HAw9~gY`yyc>vGR4YOJlK`^%+oKb zsK2*l3u7twK+xdxk*SZ#IOz;@2kc?|X_0zxZT}#)K<{vO;X~@&kIZi;R%C>G_(avT zAQ+0FU|%0HYC_qrE-^+#hd3T#?7@Lv;&=!*9T=GDfljBmf3W?Y-h%)8;fiY!rx3{OKhj=2?hp7;%A{UelK^!x?deAdGzaT!)T}B^5q29iM0aBB8 z>{3YweFLy0tSTQCr3=KENInjUrFY^_Nf15{P$zrbAp`_|| zSOe|f8oY1t`EdHpwF?&tTw?MoDyr(6+Qg)>B-X-IK#gLo1W^|a28X%}H%&43amvG5 zFdbpS?|GQh+5ciB?fTkJ{`C(k#2;d(EnB$4`iM(q7h!pV5n%_c>_C4H;RHwsh@~QC zPpr$d{)}X?v%cWkI$fbqDF69?{p-JdK;f$kwagq-st1RLh!vEzbEkB_PG*gpgw`_sc z`NZ!=M_&vN4-F1>RHdETwDoR8ZGTOuww(Mnm%`Vthnw;vj@W9m*eng3{ULb`eZAA| z%ua-)y2u-9pDJ9BZW$eYGcr6xY;vUQ;`+eryG0BpPg5lK*UzYH9`}#5d!5+1|7QH) zP}Kq6(ht8<;0pwH7yaux`X)a}ftxm_-;?|6{LM}|&qw+Po)5-dvixG6dU#!Tme+-i zd+wLC^bhqlhuu4@$7QitqJz${4TTZAjf`%G6+eGH7=8Dk`Q}???av45B6r%ETnsD5 zcAwfOiD1<3YNPUB|LgyJreNxq*EKpi9C*a&Yo)E(tuML?0(V>Ri9hsfv@Ia7rK>n> zyMf`|h~oa|uf#=u8?DUUvgC69KO3@2t9Rw(O&&ny&H1P0h_U zrManDr5!yzCDAVH^jS#R#emKc1T|LOb^`N zuIXP_I0RM<4G&Z&-d6bRBmFB$&xbq0?;VjCTz%i2aPg~=@RJsweDF0_q^-5)d~!)+ z?1LSA4u?q>ZoBAP-3e9tT8d*%uG6J4S$wO5k;O&FMRGE8A1aTLRlaL@WS}IZJ0sHd_q0U2 z9Mk79m`vgJD}L3TgCl*Fhc%SATYdUQdeeO_nQO4P9QNwdzO`*Lapp9xE)1<3YKpn0 z^wA%*54aXqH#XN-<>i%>rMXb%{(*low0CfzrKU8$pklfwmB?QDYJ-HUzSOxGKm6il zbB^=EIdjz3+-i9<`n)pOeB~$h_u^`E0=KU_5?R{QSr$wD<0-HZoo2rKW^NrZ!AV<~ za3rj#>+vOfHEwph+LWFwtX7o*Su!hn+yN8*BgTvjjz8YFIJY0K3Q;ECHw{N5;`tA{39Q-teXo)N=gh{K2AAU^p%ht#f%f487JGmCgh_veo0L}Eb-Zp12^bej|OJAn3uW0aP zoIjTvS|<)UqW7iz zmVEK6!pDb~elgGN;El%~7b$Z;Q9mBuKQvfZ5c@PZJTl;}=JI*k$0A0CE2VP}35hSL ztxfUJQ(k3v#xp+jzV5082B-YMR+G(vQ-5Q&+sZ%BU2`}4o9|xqNwUom95OS#HJ5$P zv^(bRdPPt1OC{?obwe*Qop+44y!XIM@uS^ZtGKH@!(#63(_5sV>s!(_NSs8cgk()4 zZm4~(azCXP4)nY}h&}%!&5H?nUWb(xxTL`q7AQExS45t*p1;iC?&H9an6#RPmg3Zq zr(w}gZtYq&Z`HA(1Hx5fb8pD>(Uy}{{%XVX7vU#N z{`v{+)EzgEr%@&KozrIm1kEHm*esQ^&BJ1hj#h>q{rID0XG2rL;>=zC{V!hDr`=!j zh1~Jz_7@E?dh2jmv1>%tzK7Z^IcMpvWh9A>dL9xy08F~JEq$SH+ zYrLIn2VWL=9a=Vbq3yBTE?0Id%$sX@DQ0M-?x>~`Z)b2{L!fB+r~F-aB0~JUg2$dA zPmQTveZ6zFsa9heo?&5ijweDeQjXf{Ec{MCatfm0* zu&cN70B?no$?fjfFXFFT{q;ZoFaQBT{=T1T8PWKrGx3hvXYx1Wn`^?(F8qYymeb!9 zb!q7b^XyMO^t!uW8ApncIwalTIG6dL!PVk zr;9kx8eg`jp8xMT|EhT?_|>bXbGi$ZEUz{WKcDhABMC%l8<&5kX0YG+q4Rx5mj{=& z%FX+1omc+L=UoqFe08y+QBYOYIb9X*How6aEoU^A&sAIN=IwEO4e!&hR4#{C!7$QJ zXYuQSq#5Z-5UX34v2DelK3PQ7)z{V3&_3xH)?Alhw0zYzmy+QIf@XGmR<>teng79` zXl7duAKGInko%Xz?G}CbN8zbwUI(=0bkA27#;h02 z`_KQ9zmZuJamq}NwfbYKVG^azq9Yz5#9N;U6nm;x7RY1tZ%fweieEg`W%2hXU$hGGPznmH2UpG z*;ei<&7;A6Bg4(biT53j?Afzju;?=dW5=GMw{w5_>dlMpkjtk3^`}L~8}}bRw4J-; z&mVA(7PSscR<)R53U7KfC|QV3@z7vr;CcOz6)a;KUtyUmeD*B;lHy;G zd&YdFtmWzU-u>;ddUAi6&oYHGeggQ>z1|J zlog7ijq#O54%YJjGiLA){=h#K7JAl7j=8U}{rSjHe{WA$Nus~Qv3(&O^B@RMds>HCV>UyKaS{1pu1 zp;^k6we$XGfsx(DjcY8aE0(Blx?0v=zE`NAekid2`HO}O7o{btXXDzR*G1?pgNK(P z+fH-d{P{9{|B}ApnZD=J**DM|azwOT%{r@V2$6g$JLjFVlwV?Ty>aN9Z{H00@8K*| zTU*rAa7tU5x8qrVd(vvgmvUO0y<>~I2ZwsU=Nkl5xcZskn$b74$BdVKX?V4^dwA@d zjN+c&#@x{3>rCiM3KR{i+t0GPdZ%5-{(;_Sd)SL8tMl87_h~WLpK!2cs~+;sN`18B zt5v4qO|R=i&#zjj{wS}%Aq*EHkF3Gb(Vn{-m<#kSH22k?GL{?XNOsLv{UOczbY5kOx%|p)Zp7pFDRp}rh(7%5 zLN#q&ZA~q0EuP|sAO2;Nf5pqT7#$g3{o{XseZVj6k_m;Nndi-?w3IlTd|>id;^IBD zFW4LIwLKsHo=3p5`1@lL&D12XmRn$cGGg%MU{^;M6884eFnu|aX2P`O6!-hoHpd{F(C?uiSbRT2#|M&AF0%z;cuFnf&Fjx|c79dWomJ!!O0zJ2d90?e*?@ z`Q5AG=8O8O<7uX12agD~gCoPe(|;AXt8ZwaCdyLrE33-^UMKaJ@OET&ym6u64ftraJN(Q(l=xqpjc^EN!WG+M~WuLAdMm`7K)VpUbUHZGP36e2uc4 ze#6_vk}AK;J^R(@i=d+teVPjP>ddDccr1P~`g)*b8&5&|WXw=|%4X3@d3Bo;XO8Qw zoU3H|pnIrtCpq`$FJ6zd`<~$a=U0@SXRbP&Ieqc!4VPzW4Q0komcAM{e(TuU~)HnRr2Y{&JV3*aLctWGzo$?b}=D&tCE; zC5ye6E}TDe?!t}xo(cI4Ju_xA_0jiPfBuWee*a!O-hcel2irW#N8eQJ)BQ@u;19y{ zs)LT3E~V|tZs;2v9H>dU!(F*pXus#|;Z2Hvoxko{Ms@W5xpGXmvf*!r`g;2YhkA;( zaR{0r=k7UPd8N6F?&mc|oVFl4obutJ42Wzd`SP0iA1+;Y;Ft~j>wo^e8p7r1^YU%% zRq6*qUVQUSOU^@ODa}N}!#Cg0Lt>Wo=+F{5-N$+2>C$rvWNBvj^yx{b; z<2;&SXicN%9xbN%fzumU%4R2P-;7p0Ju9V|a0mH?LYL%D(2V;oZ8@!T4ecfSwC9g^ zB%kgYKlbvkHu;sldinCzVAD+3UUpTeN%zpD0eND@=4tr^IJ^#v{ z!D$$9ED)KU2p@PpAnqCJDSs?bn77)i?0KypYq5;4I{IXk6r9ji;qQDp@}e2$PB8nN3*l|#V`fU*e_dPaVl!~6^=;6XKkPvy=5!6x|EDGL~4As zVEz5Po(do87oQuQkLVd36t}muw6u01NKbtplhTaZCo3HSD~E=9i6`3~;-R6ohdcQn zEj4_S-89f!b5bO)V&O*6jFvKUgZJR`#-seDism>yp)23g| zS6un^(hYY~hMo@%zvz8-#Apd^Us<=dj|TOlQz)5{BYhf zn`2M%q8%uoeEj7~?(OK>p`qzrk)#=86=nUa%>zR(M#Q04tp4Ml=KLqqp}sD44fTJN zx48C>j+We8FDGXnSJnS&u=13N;^&K&D{@yy)(n61%>b!Sxwy+^3-e=no5*r;UsIx` z%3`gvDg8xvrbqeTjlO(jPgB;v-Zj#6jGQ|x)!Clnw)4}E<+`o%m3+z4WZ+{EwIGd#9GSw6@k)l@yg#C%f&L`7L($}creZtDv_X-anZLue+^!Dh)4vy|pnFWXW!u@@=YTx%E--!xn~ zpR>QHqrWcY-tw;%PQ?;50}tOs(9B4t$AQHJ&2;|&no*ZiwaV;-OY~)Wj8}D;Neb+| zPx#lB79qv$-A&nhxbs#SUThg^JjRz(wQ*|g?r3c3=o=c!bXxn@-+z8Jp?aXNN80z4 zn8MWu(7ZI@l-wVFZ*sz`w63|esjetLzo@V2uYe*wLl=DneK-> zHI{0esvYR_+AA36NS5vc1Eo7T3*}5NRdn>$r+Emz`m5R5@Ry?_v9~ub{o*g5Q8&fs z#vd_fef7}?%uS9h{R7jT?cN2V)6v7PhkN^<_gDF;D|}_|QShp-XcI%mSDV`h2dWQo z<rb9G7SDD`O(f3^b&zUOLbGRLsk7U-tL* z4h)TSmW67}U$pLC;WvYo=XDot#wpb=DVu`c!jo@bHVKV}j+XcJ6&I zM^f%?miy!rB__jUw+r#Lw5j~DySux8_|0%lAnz~#_V0@lJq{9^O0b0f%tj#S_l|@Td zu!R~NhMM-qd*wA{4|a$aEnd!LDlU+t9D0-{9)8(b5;4y5yPx53T^f8@ebwB>N-Q3m zZL|A!-S?=z zvEu%A^>@m9W(nx7~BU7J24&k4#T9y}f-SFNY(JsxMQq&g*+I zGBncPT5@}faJ-#gbrpwg)mXWB6_us5bP2=cVOqoUk)FV#x*vbZz2WY8bc41)OP{B@ zOjUDxLRI^WU)Lni)jQl%=12dZ|Mf3(jpCXH2C+Py-Tl3d&#r7%{Oa?iiZm{pvWjke z_3phx>oh4euBHZGVaXzm%@=c9r~aNqdwaXMr~ma(yZh!vbN=_&*Q2Umz4_+#NbPa< z$N%z&m9B*Yqoc2jpPXFuIqP9=e?#b*C7-h#6A7AefkSc+7KvZ?ltoT(q`sHW%fqf~ zC@fe>;VQ~4P%}T0T#GZwa92Tq@XvET(7)F9>Q(ev6c&7tLLzzdN>4 zOnjAa7QZ&e(~MYLl$Y`N!9CBXu{pUpS(%wx+1U-%#VJuS86}Oqz1@vvDgFTwMYUan z{hj#BK8l_T3kx$dvvYIP z{ao%lx(8+DLE)^D(&Fm8l!(}@hF0PW#ckF3!9EW$gilaHO-qNkySuqEBQ!d$qOH5P zvn4++EHSIJbGq-CNdTKvS675Qa(4Cz&dAQj5P1c8aY5eq9DOni%lkST)53jSoSa-e zydzSITG~6iy2KsLWf8$qITdZ_nD~)RZgNCSRzq7?Z(mPid3K2ZlgAIwQRjbYay?;S zc%-YYDBSO%vy-#C&$E>Lnog)VHutFP*6xAc_PWI2$F43e550p6s++o|$}=R^D9SG^ z%1MoIzH$BpjC|U`**mDIv$wCKF8P5UZ9t&>qFnv zk|yH&weXF`qVV9562vQOY=D3 zm1f3B7S7E#I4&tYwrYyUtgug4S7l`-c6n^D$CcZUVp515 zkL?uW<9yfgVSH9@etupEAMm}`B>m8n0 zU0pLUG$8A%tzvXv6c!wsRZ`?&sH&iI*yr&hcb|}gnhwe6v-tJ#j%Kih`uh6z?A>Qz zY+|UVtsz3GikY^!E^dV@BLNFfu$yoFhBM;0ehujfeZmUm;8dBph|MwZ^9A zMy6)(U~0U7&u)wbmwfwcWpqM(n;zNIV1GB!+uL6<4-NEAc1EeHd-g~a)Plk$M*5nP zH@kN28hZYc{K+(-a8Ez^qj=)a0}$W!$L1IqA)b-pW@jJq)Bc|6lqWGVGV(H_4N+)m4>??*t+4!>9ad5 zcq>&5ys{hmy1To2`lLo6ezPsHfZnmcimR37!mcQ_MJxeE?9L_C?1 z4Ah0h>yf)FsV!+E6C(p1O^rCIhZF17)!m0C@NmK;lR(V9uFlxlm@u`zk+HD>(sLst zquOchOj-jgOB`j;KTI$@Jk-|MeKKk9u=fksqe&+qbxNHW%M(P<4th)5xPldE28DJFYy}tpI zRRw;Qo+m&o#$j~|{Ft#i#l1b%>7f_)Z`!nJtLo~Bhn`@hw)GMLgD(tCdgNC%L? z-^21hJEmO9AM4@LW-^f8cn>gnf@42dn2hNhdkoTgzXqoCXJGp2Abo8Lb-I4%aazaB zzj&R+FAkDs-mM(A+yqE({0)$HG#=7>e*>f)O@j3H&kAYRlOVnQ13;XVd-|WhdIP+E z^>UCn-cFk_`~*l98V~8czXPNLjED5z`wgkCGLYW*!H_nSf%L}v0jW-JAuXK-(n`}n zTItt-RD(&7-ku7`YKR|;4fRTrs#&~8AZUj8!zZ(t#Vlqqi&^{~K+sH5Qc}V!W-*Id z%wiUQ2M{z8^!N97&tev{_-#P?Vfqh-wAn0X@l!GJD*&^Y z#Vr0G1~xmkJzjqZ$ePlYvzWzC#Xls?v`Zj;^NZux9sMWc*H!zy8ojf#Q+iPUhr-{u zPswj;<>lqMxw+lCb?f%`0d<_6opW+>#(v%TE3V)_5GFX=Ps7jB$@_!%i)P5LE8=xb zCIe32(9lp-HT7?s|K6Bxbl7l8Gfr173-}Z2^b!A77x7Q9;Prc(OaR#&n64qTh0f4? zve6KFaA=i$AEXx-cq_f}eLz=;eLqCu8AksFFky74+S=Nhm6eq}9yvMhhKGkoL`2|q>;kW2B>=9UJb7~e{{6DDGSV^1 z%gb9@T4wf;AMQUB@RJ+*(Tu!%@J*<3^HRtFQojVU<#Tc{VLryE@s zxb+iO?R(b?kR2WM;gjUIUlL`Inv$HBnw*}Rl9@(GN^+9)#`^?#NK;eO1joPz>+0<4 z7x(pa5r5`PS~?Z5K-JaNmoHyVmmn=IEi*F{?1gK*l5ffKF@WAcOUcQ}a4MJ%t2}{b z&?jkCa`o{_UZ9Y?kk*?7%mQ`Bs^JyavOP%aO#`y6ETlK40V-fb66hbVFa`V;K96a_ zlTj$GIu%I8q;F;f2AaaviT2%H-Mxe$s7hu>C@le5MHVQW9ArqqG-RAakR;-yxT|M! zhT8?pYn$q7Tbi3XyWrN}KM~jtheRBgu#Is*7?J=Nc#FcB4?#WM zU5(AH-tmR!{nHZit9Cz3*!L)L|D(ix9tn>Vi%>zf?F?%`VsiNmL(2jUYieo`sS)?5 zYcl2NFd%lIpPwJjn`6er1>T~N48dgK1i)el9BplF*ylbzKHlEmI6U6EbqnWB41vuc ztv3zOZAeH+P*4z9Dm67VB_##tP4b{RVMJ&<+51rkOA{Cv_~5|U{nr!WcJ z#XzLCWJ4z>r`Xt7thH?aW0-PuS)d%I0Hp7KFkm{k7Mjnn#ImCU2-aAU*RNl{e2Z`2 zye_TpxZs<5Fpnb7cXACdh_jf-+l86*V3{n@Z!bGZ@wEH{r2_S zi#J5kjCk|r4eW!(g~P~Bw!gbCsXT3S(EhZFtN}41&$J7NRYPpOdi5$?1^yNs9DMES zwS<_2@MmE@?vD#H^PTQFdU<+fWM;sTNZ=R&nn5_8l4j81vuDr1Oz?AfFWe?NI{N0# zn@EGu(An7;E-~4WumteB$B!RZR8-{V=01J;6!Y@+^@ZD`E3A&It7}e94)&n5!6cvu zEGXO_tpHr$EefT#Cjni7K_5MONe5UJG+|dYEpb|#k!oXDape@9{s>|F(`~ip2cN>wv&Sl057j@YzfLNa|q7b z^*Cj>PwJJhoYa!q@2BNo8{=pOOxw~_AAWUXn1f~bMcdHxmQiN=kH&_rJ1Hge0D^ZB;feO;9;{kFmt8F~!m27r9`lNq)RBomD z{kXLclWm-m&IM+b*EUV~TanYP0SR(+xY5{dgaROs8DiWR;Esibg)S~GGce6`qhl28 zF>GCwqalC`Z~$yF9b3R4(DTlnJ9qEi#b$=PqX#G-8X5|7!S%5Zr_&kgq50t8AdX|$ zsMxgF)$Z=@*rM03U&o%GFev(&;Qi$6uto3PyNA7vxB%b+ZxK7-`ecR4Ko8g(7|YGg z4d+}Oc(I2uQ|wqwXL48pCXX%)sES)4EzD&)Cz%p3LQzo>)F9VOS~>}`qXRG(jNIQ( z{EP9x$l$>9p@FmBiQ63`*WL|h9rtA(@xJ1p*4y`@zkfthrAP7#KsyrB_mhEpoh|hh zRSh_|PG1Yvx*IA=N~)Us`g@3r%4QTv?@a?t5a%|8NH{ZQA)Q-C$58iRWLf;;M_hG3 zYxhhaWH-ocr1!=HOEX3@DXA$LX&G+Lu9qCIT=Bbk%H6>&%5(pf!(nj|*^;M;*u39M zGg!E=urS1H&xghLoM2%HBVi+N#P;Jw%dvJ;#D z%mR1ex6lo13g7}}LANt(H1z4<-~f(+p4eZw7~3zPAE=EA)449nkxHUI)E*cZAeVp2 z$^hz5aCLESUs+~+$i>y6r$k|=)q~EO=0!d(udId+m@Fnj21&9q3A9BIlY>m3xXUrF zK>c>Kwqv}Nd$NgJlJ|6NUnKNgw2Jq%55>!=H;VlZWw5TAhDub?0 z97x+w`K8%8CIn|!in}^9%IY?Grtb~N-}*S)F{TidHsNpOPPYaC)*h|^_l4i!=z+xp zPy#Omf6Nex;G<{@AHpWV+Qa$s^YhVm@+O&XbiBox4j~U)6a!(_IFaFPU0vOD9tnR% zV8!VV!5ur9JZd3uLt9u9YzOjy3r?OUN=Qn;_C^o5hPLGAx;UVLw?I))URqlMG@0Q2 zs8CQ)0B(zmi^HHqO5*5<$bz>h#H|TEi~;2s6m`HZIJbh9uw5}(kkiA552u{(F&lkCMmD{ zW?D)Rx z2E_xhmC35XrfR{aie5ThE)3F?IC+tKl%H*X)Z*ViT zf|FxiaDh0EL=d|M7w{;!)|9&y6Nk58ci?1(n%LR^)Wcgu7~FzN(yB7RaM&z2ZrmV` z7kGuv0NfQbB@cNBR+Ie)nxisy8Fm)76{rYm<1JRitpU6QK^fi#pMVb`-XSMNstX4~@P#Hbgdx0whoB_+ zAP6qyVc6M>$WE?t72yXozi`o12TBJY`}rd2|x!3I`F8E7ZV5&`)LeFVlNO!9;&M5BO`}~74|D6f1|)x6xvQs-{G-%E1AW6Udj0q7 ze66;(toOTbU%!y~_q2(>7EM$dA^ri`{+{yv{1uGNenZde4+>V&H+gmSzxy|*VL%uk zF&Dtam4TNs56+>?k{GsHL2jhNh3*lic8*&h9?(xZ@!DA!#NpH4QX# zF6z4cGi|j9Q%;l}E84~;dhhjzx1H`gUbt`(u8SliEiG+knt>Wv1yneH{yerk?2l_) zz|^RNBMVLdlXnn+c_9tGaNz>ZSf~IO0zW}F@~M=suP-tTaJjU$3~(2n!}&2HjyP}< z02jzqz*Xe9(yB6m@+8ebTX+aY0lgtaV839S!*jqi@Zrf@6_qgyP!YMypfJV-a3n$x zFb*s*VMLTnaP{u~k%I8MF%H7o;;g2IhU9y8`9AxDLc)(6IZEy_a4PnZ?C5BV9;OU3 z@ zp20Ct0Cq!tvLQ&Cq#2|an2WUPTTC7ufMpQ25YaGSv?W&x%3}$DDd`G853mVRH`Kv; z0f?JW08>T@cC73WBxFYiU}P8#99z`^&LI9xBX1YDoPTtl zc(^y{nCaJxwJ+Xtd+6zxQql<5MZVtM+g*_v`OwMH%`c*~sdu=y{E&tcXRBZTP~8z+ zZ1F-z9qmNW1b5PSQ+9YIyM>O&&WUw zfhS~SWK3Rt42L}qPlJo1f0RHU(l~gFLfk@yG4;j(<;Q3S`oO{nN7&;~n*>J0WGAZ% zJ#kt^&Vjb@F7O{V8h|D+BYME-vTFh0?F3iv?i((S^$0tr8gyDe@Qhj5QA**{GyYG5 zjvhM(+roNy#V(NDuxLA7kO2@2`?|X->zd94W(e*?TRuvSE~t6W|0eYmG!uPE2VBxU z_!4i&q^rBXt)(&MvTk9-Js6H`EDNv*f;IVk3`ZfXD}W2UJ$v>nyk|<98Sd+Li7PU` z6H{5=0^7lYi3L>^b

    !5*<=Y@yMun7XD`Bs9_nQ>_6m;6Mm8I2^%aBsB2=Btgbp zTqBB22)koIThawl6ZO$*tT{@MCZmq5<4zu(1m0o@9Kp~8$8!J|c#FabHODX(=%GC7 zz{^n|@g3u0L}WIY%M3JwSdSj?7JCeD5#~TMBw79tnn4AmBNzfBf-n%g0K_sRM(7HM z%?Uk>0X-lHVs-#13i}Y(x`&+T z0b^m$Bcp;EXab-FQ-Be$j)+hb6p$SqK%_e~es%xn(Un1Ik zqq3{|n5H6Ut55Ghjf7@A+q%VVt%%_*P#DX1?AS4o?!}82PnT>_U`cEocq1%4CC!k4pY-+iG`F@nM(5s&%yo_{Xl}z; zgg;MMhzY>@qHTY7Ur9|_R9-?4QbtMYgTg5rq7eEcpR1{1!3g^O6?BS(%LJa`Z>bHXRMXp0^u2N@DL zju%!nYJYCgQwCe%Kx4dSnd}Gu$G9mB!)a8wm zwVQ?$jC%G7u^DsK^uva1qaX3O^cq2T|=uS*s^Y_yXnUNs+AZjCW z!GTEHz%c>41r?_AAsm9>XW%Eik|%4lCHV#(j5-qs$& zwvLvTR&ihZlS76Jl-9+ScQs`{WPJ6B(ex%`RlvHwk%rryhF>UP~!t0?*7lMS>!;q1o1m)5i(_^5gzp}P^ z?UTK#F1n9WpA3lmKu^+plK{WM!XXDj#tgGyTjB5uLqRKeBMNZ~*OT3EjAq~`&>!B5 z$~dKAj@aYmvoBebP5{X?*cw;`%pDjQ7{ES-eSXMyZ8|#IyTsk%-oc83)bgCT&~#Mj#ky9I^Q z(G2(mEV9)j$>MhOt>8@lxu7j>380ygfu7>32J<`7hkVo9+QxkgV9GThui-Rc2t+RI z4IHlF3S>3eC6oouHE>YWM~s8#A!6cy4|fE|kViqpinCx_;V|J*IRyfUJ zP%s=Oh5ZkJHYUdl085ETfze3|K->=`MwxUZebJJ83G6TM z3Od0BUI7>ZN=VW79!1~zj2M!!~?CFtN(|#wR5|UZd;p6oPg}8+Z(yB6ON5dX*W_g|Q?HKCW zAm)YeU0$hu-CZe#mFpkGa4&?$7F73+|3>q4Yk;=^=z&aVz!`8jluXAl02UaB6znMY z3S0q84mX7(!in*A%7*B0!sw*;WB2Cd5X z7O8DXENky-&fLsi$>005weqQ8$*0`?kE?2`%SubjD{C6-vUl@VvNm~lb(ieH#YT^& z_LjO@Xe0&HLl~{9sv`9yfx`+?w+XhD&`j(X52^FLIg20jcPE@JZY)DuF!ro$46rsy zGdLNfr=+K*r|$4MD)cga82+HWDQR@Hpu0OcG(7OpBjSXFMWNAX0)aqIPL5ocDQN~L z>4xUk{a%SHPWZ8}hpFF-#_RIqekegXd|Fy>5_-hl1r!{TB_C`8NHR!gPZI zXp0KyXF}&BVDpliMz`4f^pcwQ{%M&M1kH%wZcYi!)Wuyl3qQ&6-%s=3Pal&f`)SV( zGb2v23c?>unav<*Vhv!#kN{t|luG`sc!+CqMM!`j3ULb+q*Y}Ak8N*ne-u~1yBxv1 z60LF}e79HXqnJG9!@m5Bp^sBaVaEw)q8ZizC2%SD9FAi+u1>i~vOopwWE>dDXp2`I z;lVL*i|NALM>p}_}8;j!}+`8)I{nYWG{+Aywe~?k;vq$r@6>DOPTRR$3?Nz>} zY<|?zQG0hI=aYFVJI~#|f9v`k=ckoTWoNaQeJZ~?GQaSm{)$gm*#>1)Kn-#@63`IN zDSaaW-cF{Ok)ENTqKH2{kfZqGAdMxqNT<9klQE3+_c%u7e!An)PWO16(Wj16?-|C?j0EkiO?9nJ zwQW;LYhz7YOA|p3QvuA6Re>Wmx3$+bw?c4%x5NXAX@1}hU(7D6-RTy;(LH&OZ|3Gl zsrRDteUpk0JxZzq>X ztI7bbM&|N3kCOo9;G~1i1CNBoFa>GV@gQl2{6aGcw7q@%HtLT>d}-CUfVPvpe>$Lt z($Z3#@}R>6Q=n(q7P}hMh~e;xO^!1i%25;3L`sLPKB3jjqoWlf3-)|^dir!5eoA0a z*cP-g1IGZeqXSQ#Ji!!D0xp!GqP(J}JU5^;M8D*jdP$IOX}DEIUI0<}78O<1)kSHS zR;#N~Xbc9OCD7h{{7!scRYOB#Rra&}_8N4QvPHYEJ}Gak55BhB*#2B{QGH`g=9%>t zn=U=8u5YX^O1!qml1ZV`X{^-;?&Q}uX84`gQ8#q(%FGYGsH1Lh);+bMp}Imk;M4%k z_(}fK1ZE+f8}Z%N{`m5g)uFpmYb1XKpmPdOBLO>)(F|g1aBzsT)9uuxpqDSR-qK9& zci&|vB?X3sMIsV*D>H&HeD0U6yXb77&#Ee8UtJoK99Sy3qb-UQ@T32JK*6UEu7(I z_H(qI9Aw7O*WHy|SiQ$9#V@6#XQ~SCAtuud@o7KOnrWm5ww2bK1k#j*?K_Fg4uT83 zB?_kx+_=*#?&|O9>hC55#Dj)lX>iPxjb>g0fK)^J=Eq|ORe|Y7$6GinFjhXfWCEZh za(N^oI2Or*{9GM(r)!AvtgNiq*jS|VV@OI$nj8YgfF@IV|8zjLDOU}JNSJV_BrD(* zAse&6^;m_m>oI)q=on}QL(PC6(olAE09ze_2KS}8csjG=6ST&Uu<)uV%MK$p>s|Gi5x1y}9vbwguuBM_KBb3+F)gwj0RRv0M zU5A?Jq6#;OYV~zh73I>4N}|CGz!VVrk@k)G1_|u3ZgKZe&tP9Sw$Z!t$v|ks=%5+o z>p*&Xa%^m1XJ;ak7zxLak~cV*8Wx5le=L*91g{`Kz=rzz`dhbdMMOqFvZIfozo)yg zwLKucw6Ucf*V5AOLw|Q)VMFoR)Ej5gZn)?9_KJyzz%u|tOS0~1G1>QI0dGNt37Brn zj6t%ACt|vWP;yFF$6GKKRuEYf?#?_YDx(hina~Ld@V8hRA%FCK`L!?w&HVC!$;X7m z42v-H8vMQSGmcK?^2lkBf=qz4#`HkQkXC&Q>@n%RsQ_)K^!^_UQfF*4>3hj0LSNkwj#!-xW&B z33*#GR!yeuwBqXO{`m2e%*>qH+J?HiM!d>OUG2n@$l?^^G0PEqKNCguBy8 zO>KQ+eM@h1AEdKM{KFbzrc(>d($GLWdH!DJ`1@f7SBF;Qw*B5+fC}FmWPY_7{v^B? zH1neX)8pWX^!a;N>+gYIcl4hOXbYX8`LAWP_h)qMc90^r@!yEX#)iVe%&;(@@bJf> zq27OQ2?_Cvit>+(3yh6@78myuB{ueHM1*g2bU;Lee^yrTH{WExeOx9hD9J4>3{_E4 zE-EVi?z`_urfF(w5{Wd-%}t;~e0=bPo_}?LS>ogI8kn9w?Wa4x0Dcx%N85kIATtC0 z@n{APM1J1$t9a6{JNi!sv?V__`?ZYrUX6|mY~a5I$l+RBTjSz_+S?N(3BfNWlUdTb+r9Q3^Fr-pqW0&Pip^xfZP+1zWK%R>yG}D@$0Jn|Jdlgy}bw~I6;43y#5Cj z&`h?L7Be+912lsefs?hau8xtBft;M&AOHAYfq|EP4$k{~NPb;iRC03az`%fXseW<% zEY9|`bn^aypqaAra_Q%s?>97E8pAj1y8y+4W5)y(7Y0)o;prD|rsHk6M=vlmnfF~f9MMe3O&zF9@6poG- zOe*|Qf)M{>d-#Ea7LnBq4EXL3J$XFN$DjPUpdjDN%g4e(y|*_8q5L~ybo4f%At`7+ z!6u}tBq!k(8bZiqh%EfcGI>V%EiG}rzEA!kV%l#91kF@cRY|^=|6T)WdqF_~G#>w> zhhG9Xx~8P0Bqk>Q!sE{3y#>56FRyS?Hd8t}S}BooNwgg+mlf2{?`*%xzn z?KX8dv(Coa;`QrqjExNf11}I$`!+Ep=zLm3s$`nv=;V|$3M0?^#h`iqyKbRsZ~X9! zOiBNFBfU{gjUgR9$r4pjGB)}I!L5q7^Mc?+j6yU)Ap~P(RV7^v$_^Vp<@~0mnDFqZ znwo0qQqAH$06{bOpES35?}3y8=agUg`4xuC&dv@F4hF;hT2Jj}@m@jV60#4?h}Yga z@96NWPy8GLf^X&3-~@-DFB{Nt4MFrQO1hx2oV}*uMe+DJJE5}dH7R2yMK7E0YAY+B zkBS`~&2B1m3JbpE=jRX<=~UB|E@8W|nq|@rS=IadLJuHa0zddL6oIj@+cI#0acH+qBB8djb9z0)lTB)Wm!@ntaW8 z1%Jo2(NTDYgLBA&Kox?a&NgmeK_m;TreWz_%ImVI}PX^Ses;Vd_Iv)cXS5#s^>Dvh)$BK=OCI9q2SvZT| zGA7Xs5xD)=$^G{qKG!l}i+HOP6_>7dxY+TEjDU!q2)j6df-v##}9oXW8S zQI0wgk^r*b)+gg8dcZYaQ4_CZVbSa6yE?0uoJmd{{VwEy{O>-Tzrx6v$!9K8q*2fM zd%cnNNsJ{C#O}$1l3n2z**{)U9(P_(PIT}d0{U*zQqGP`qoWB|Oja&1*`le<(9>nd z#5sdEdQ^YibG~d4ucX(c!1Nmi+sl z<}Wui;ppiw^miVp=!_3KB~)0o!cbRnl_JGCHEMJuU<>PO``ZsCW0BLDrJ45;)6z_F zVO~*wc2Pl2QGQNwK^_sfr^+FUi%Y;B^^HYG+nSw1Zb zlvY%fCIoq$Jbc6@GP}C6=$Z4?qo*$gWt3LEB>{wcU}9ELTm(G{Z6ylhEkQPuP+C@2 znwR8w`I1{;Mpc!x2ZRhXNlVMfD=eNaO_F@%n;jY&nwy(Do6yW+Dw@gkuv$(r+&es4 z^lC66FJPnmr@u41>-?GsxM>;QTg)_6g+k^j&xhZPmSDlmaAQ^nzU%S7v)|0W zIe+w}|CSYB*j;u5a}0JwJUhq#__KLe({R`?sEj(aT3=N|Lv8Ezd*6(fW!=#K;*TG5 zgj7DCam>x>xrBR0UxfRdGtyL76Bz10N{<8qY!j30yIe3>u5l3AOv**#0$h?8b>93^ zY+!49cwKGan{SI>6dh!&Sox?XZ*=fBWA1-xUUT_wwB+SLbaQJGTHQ5U_Lt8VX{l3q zx;hUNg9!o{2)Mr2)-xk%^o7rwB_AwMp&A-!Tn_P%yrBJ;KYzj1U>F`aP%!|Wt9Vm! z($2;zvpth&HR!i_)mQ6p`;3k@NS?@*_vP+e{`I^IX^ErXCO_P^;%l9??W5&s*Lf>+ z?P}k^$mBxI(#-pascELPyeh@#Oxzv&xCa~J?yrk?+L{yZUshRLR#i{DR@RkPRFgH! z%FD77BR!p+oSYmT9i1L}K8edLs;#RjC({pXM+qt`s|ykzs{Mce`~iP;NO4nL<+w;K zt%Mj~TG7y0bZwpBf6e(9YuA+4`c(UsfBC0BExj05(I9DpIypHx6P{l|nY`4Z>IW(Qvp&&r6;NCNh%eze@I@w@Vd z!1YvB%FSmF6MQ$QE|t4e5SMqy@QaTYAHDDJ_}*I8uRpfF;r`ud++OxP{xPHxRU=jB zmd{;uF(+&EO~hG)1q(R3uFr1W+^YH~IraDsgk#AgukW(Id6iCNErWhr<>#)w?(z1M zjEJ4IFI3lE{pPu|zQSL$j-F0Wz7v-E6ikqQRp+a(RIdBnbibhW^=I?0q=Slb1CMc( zHBADOJs+PE%27ngJ@L0pSB%k&=m7GPqHkZNz4;Dv1T7I{P~l{>O4*=vxODW5{~oRR z3wfr2sR1L>(GzbPFI&hoeiC%;oZa#-6?h2)Wuv{Wx(nv+cpN$U`myzjuZ)hIP0w(z z?MVzdDOgC=^NV&#FM2jaJm?dTHXczIXy*;1tNPLBPj@N&m1Dal!2fE1|HbUGnD)%g zbLTH}Z-i}In?me9Um{2us_0AHv1%nJq#ibrm}Qn`-b+kNGs&Juqpumq+_Zp1UpI}r zzdrrhjf{{78Nqimg6?F;`bYwId2M60&k^(A%^AbLeXSxo=@ME}MSKKTT~kZ^8K=71 z`nvl3c;{9BH0Srcwb3=*?M-CT11c&d{@fGs2cb~0rmC_EG;`UWGiT2KvUUT_q*yQc zV9p0iWN8Mk6P{lYG?Nk*ecg=IHs%JzJjwH@RNIhy8Nv4ob5cvnDkL=HslIUO>Z=JI zZS^%ZHBh6XqAWW;@Xk%AsPv)=@F5C`zl}@$f5LOL=^xq6;xwmoI2g_7B_AB& zR<^78a(T^N&qto@;D4rIWF4FnAz`56Lwo?*_gr+q0~>kG@iZeDXl$B=@#jP<`0E;8qP%#d-tEc`Egn^lWuX5kF?4h^ z^_uZY^}V-8M;k|*E~_nGav?oqboi0E{L%ydQKK(CE##LS^heHwiRV2%%$7Ia)k9pD zK5u?-?ttA6YsD|Wm}|VweAlUSK4N;B@j4cB(=y(1WBh}Scm>VG-m#6nZ4-Oj zHtLFgqWiwm@=DaJZLIR#Yw+)L<}A`X{K(7g)E2!D=gj%vAJFfF<=2)ZU)yCazg%wd zqUF{noRg9tGk*WC|NNhSoV#eLJlo`gXH;nw@qLiQCpWEls}?O@!ZO+AlTg&!R(53# z@1N%Ui;aY4Y~}v^Pk&l==`GCwlb>HnXeJ!m5{Vb7@Pm!9cUP0z#@w=sx~!L*99&va z1DYvGeWJhMlex>8Tn2@rZgs;yrM9U)^V!`sRy%!?DoRuQ_Zah4DO8H8ir$8^(b;8{ z71D7@O#R4i7QZpfn9Y=v*^K{gmA|aA>v|q>&hm>-*t*y59lCjAue1BPjE2PI%UUb> z>zm)8W=-h>!7>$%y3vGFn#*)gJCBamzHYcemC(%dwAJ(ERRg^qtv zJNw;e<#3bd-2<9bY12y~=1;x8z%7uR7eFZtXs^o&NQ_h3gJ%yyASTq0VQw%DmNA-6h{>z__q;!8iRu zF#+ejJ@(tuKKR0LecNc$>#U=+g=${;>9aKRK7*hc9Ni}z&p|Uu9tRR1?kz4ZEGo#A zmEz)}B=>!Z?)%4R#%rI!|D7|3w&!WPSlnKddwI=DBsE6oJ$!F({?9pcez!=O&ETv( zem^D6hyJ^N{pbJwaKWPazyIHJ{_i4v@3gwI==_ z&!2&20B9@w{7Rb5TrAr8?$Er7?s`Gr0FZ|<|X8Uj6zp!Q1Cm(7Yax1E?BmNSv1Q>4Yk=+D~&Ehu& ztp1dr&8Qjd8T_vBMSpyb-};rG{LcJ7qGZvt!<4_s>!f$0TEXj=nM7i7PPmwAT{T=Z z(&@LC^H)`yLoY{jU9FZZ5^ZQ3DjF_7tFTz^dO^;2ZC9vY{B^C9*Nblpb6id4DTv~x zqM0o#zOcRM0sC-KYr@dnwEWCXF2GBpqZ${ z8cX%gxs84oxsU(FO4~y{uaSY}yn2Za6VGcbWNfe>oN!lLc>(cFv&uIucSI}X&cqWmW4>z1ehJOs zVvm$&3gb?5=PMc(c4v%?q`vwV2~*Q(*={<8m)wc#s?lM;EvvpV<{86ngc)gsGFsg0LEVDH8K7yc`$x9-o8TSKal{KYh6|!IADyytb@;Eqw zX8yl9b5yr_R@T-wH&yywG6l`39lGOnW8;6!nKPeZc-}R*sHUkj*;V16=X@yInp|0R z#Q-_a!b?8!J`OslJda_xW2^0oPyS`joW-tbS+_T-6EyR1TABgK=T~I7AETMPl!&sb zx^dc8)#ar|$kL4Dvl+Ry*OJ72;@U(f-sc~0yce17b85wW_MMpO9IwO6=5cRF)(-Vo zUa(R7O1M9{q_%R5XCy#26B83N>&L%kOhq%2Z<_t?Q*~XYfW1ONaoO67mn7dbD}CAE zvQKy6f|bj(wAA#hH`IPxQ1-}n(Vzds&|qL5h9w|(95PnUusU>J8axeF5_2c)z8Eq*?^i)1uPEpYms%|`S z=J{xG`X#|9Un+X$#^>J_ee#98b86h%M1hp@H+AO)s}|qPOB)?_KVYq_N>$d@RF+@# znbwYd^)FJc>n)~lx(ot%(|nV&VBzr?(2Tpm;`zILB1d0(;9~ouU`d8l+Mj<$U+&LK zC<+>@x8$~h5zD^oa`*DQ(m06glF>n*b&Ec>yx=O~B#fIs`b|RUIX!jGDiu|ggO2xx z2>QuLPh0I zmnaIg^$ZM+%&d2X=4D@B$DcFjUsii%cQvJ0E&bC!{YmadN?mhRne11Pv$C>6LqiJ+ z3dYflgiE9~B$#k(jAm9}iEkHow&eO5EdI0gm1n6wr=>LGeMD{^`&w{mm$>rQ2Eiik zuK2>5F`B_pMMXtOq!JPmCO>JM#cv0bXoir!`p2=6*8}`7J`1^1P!}tCbVlAS{&pZN zHR^Iez@?}ZpP}z^-wZ|-rrvrMaN%j#{n{SnH;Ch?ncrRQ5&G<6z_V*kD1OL$6=iqWU>iFKckDPf~J6ze{f}a*hbS;_rVkB-*)FoFO^#=a0UMD@wZ=;D6z1 z=>6JWVu=1mzpVVA7ewBWUR(I6xFMdXHd;8?n+WKE}=KPsrdg=Z{r#n|~K8~zxthl|73+_?bd?&Xg zWs}06=KP$8z1;SSax{qvlEUTOR!r=I*8G^iy#Jv}Tetgx_< zjP+wFORC@bj8Mn%+B&BCIe>xkl0ylasi-Q;47OGH{G)k_T&B{zujcC?xL?@Vmg=(i z>rW^*qpNc~58&c*V5wMKam}7Fm%c4dhGvS3i$QP6$;q={0r-t$8k+feC2#bb!9{9OQP&63i}nmTg4`nnqEMe0yjUrYS;0`fvKSVeVh zU2WCdKXXGs_DS6=e#?OG<>ux`MEJjanIU;bgkU!-zq$|$k&zJ|9UWU~YiTx{&qoSfj?+*$ec1q+d! z9261~GW!GS_YKq2%zKGn<*^mUn*5}07QbB zf@bRK>Z*P)h(EGiSxNjGEM;YQ{pF;b_>3eXJUk^ixw5ii;@!Wil$T{@W`u+ULjh3o z#JjWd-U#87<>l~CoCbaYU?6M<;!hU6uYhj9DPYQoQPSm^#e0L%(b4}OwtkS%2+a}`DDl1B%Arm4)K|!I(NQ!a#nbfCKFS`2p>s zDkTb4Jw<#3d3a|bq96hVRTq!)YzzklbwDp8E~4&fc$y98i6cW6UeZeJ$o-C1mG)e< zzpJ&smjZ$K&gmC)ct5TOU=gTVit=8UUKp2teuJn2F4t%;C3}KL-~Y3 zwmSY!Xo&jh?wpXrIc=R}oKvkhhDgYGzH+o68BZ~T->ug0t^37oUmpJx^M98s)xZq6 znB^~c@Zt+d#3^`ab$`4R*&T{Y;~Z4Zaxx7wtts;Jm=1b*8-q{XUHw5BR_Css;Dkei zPHOf!&&Vjs|K$el#v+EO&$@rCHF6I1CR`y+a5o+)#6ppTx&*3&d-mBvV2X$`-Li}{P)?qV! zeil_9uvKlq$3-N4T1sU)q(ETSx_4>!6d3Wlu=RJLGytPwZfzem+n76TK{d+>rx=a+ zb%}DFd+N_`vzM(QG!=Dj^XK`X#QR6(Z$A}Jq~uA;XwLr|?|ea#^Z+7Y;VZ|G&k^E2 z3%Y-dT-vaXUa@^9ukB4Kh1#dsUIGEvXSwvs3h^#l>I zeFJY11_!5gC55?MJ8t|X#T<6~k=mcUFQqHnuduGDQpZZU?B?s>GI+{G{$gE|;e}oe zSl63RO5fGET@rS-jdugK{BM9iddxBAaygyW$r-O+p48OF)x%+jV)A&+Bw4M1p3nO2 zuxYFQyu7fI=u6p>8nGmt)|K7p0+bsyxpCF!5YMI?{EJ9(+>f*`0sW5rZ}|MGC8=xA zL130wJfXWsQ$)4o*Cpu^p8el|Y}s!$3EuEQMWZ|Ux| zT3x2##Tin-;;E*!*P}T+Iv!`3Cu$twMRxE`e>Tq(G8@X#a~FhujdTrJ#=Bc;nZ_4V zw^$vR!TBVQ&pqO}62wsb3Mlh4eF+gbo4lXS`Yi8pcnR9oByGOFDHt<-4$+U%ihsCr z68YEAF{SU0Wz34JMwEuOIb6CeODjlzpdJ9{q@12WRvGqd8D5ifD+Eb0IFdVuC%0S8 zZo7+2CoQ(GLq`sTF~hj&Z}Yn8kWfGC}AT%R1ans;(z z16X=982lOa>P?^EA%>WIww$;^VQzE+g1vN!*H}FUB6?wm;?m7NyC*VefDgCXyZrqS zV%BUE1Gx;i;sH79MVcHpWWSBJzWn0uk4%swN$W$}{d6>rW%R6FQ!~|SFa>t91UGs0 z-@4t<*ak?Ro%mS%xrBbXDJFBF0aoyR*{pd7(A>`5s zeQq(oJc`XJk33AMn8LLyC&2j`pY>#dtz0bpYriWzs;)O5x)6Ft{fMx~?`;(m5J}{q z$7N^q^ifHi&+Fb)P)`Y3&Szot>kkrsF_W_{YVLq7Ald}6|@+)ZsC3CNxquk%fSaQ2Be-7E{ z4=4OmMau2gf!md|crm~j;t!j;8Cl|bJ=)bErI<^_({w*=C5CVu4<1i1cjjT0aCo$Y z?XT;Xic6=`<2FB~k^u7k{!+SZAAW*LK8_U_}X=_0793ESKgSj_abk zK`&qHMd3x2|JpI;qI`TB$L)0eA1eU z!`&Z_p7q)O#;78-O1JGDf=#t;8vQza%lnH`D%fxZy>9o>$~stto0ByqkNNV7%_Mzz zBi+xnJ)5Bhq)C>Ke5YxgtpP&i{>#fU{WnALgcU-TkqYe9$c?%js2AMAOJ9JNVgl)X zGNwZ^Q4RrcKt53|septZT(|nulS}bjzscIN2;iBz`y~~~*u?RK`~pG<2Sk_pRP)(T1wf50&`$@z0mYp6HB+S5v-J^Ujican0tqbB}@pzKYX-C^)b zCYFUC_B;4(Sc5>-YXutjdDGf1{9ekau~Molw#um$Rs;SlrUzlz97u3UT|y;ZNZ9 zWN*k#3S&->>nO}~jcwXhFYK)jAN|;OIvd4}Iv=bFL>tSPE!c6KiemKHbaw0CBQvIM zXsD?qoyW&`(o68+UOG93?5?xQ*%Sq+XsB9QE}pUg7<6>(qh$H4T z+l#=$K@FeXQk_w9Nce%{cCa1D#wJN{L&9#$ND9RU!yiZi`$QB+JP`x^-$Y9h9EQg7 z`S;1&^!Mr%Q@(d`OY&Lk$ZyeP4#cy#sTd^IpRM;W+j{wqPtfoMoR@E`5^Il`)82?6 z#gvr8nU-0r-t=K&_)?Vuy?q2D3IA^n@PGWf zKE=Odzvl`{e@{mUDi!PO>Y9V}-%wD>roz4y$Jm%g|9Nov|Mrl_Px)>P-C6M~6zE&2 zoUku66jY!yOdZ?yQ}A?W68LJ?rPKGNW~;O7?N_ftW=rMkNlg)y^3<TYfjwfAl_ zLASozxAcUi+Jr#x-!p^IyL#0cw7VJ5|Cv&O!X7Tk z^!JYfDdTE9Fb^Vnw048JoxBOXoL71vSe7E9MOr}ue7`BDOc$Iqf@dG!WeR83F%j8gp$$u+?vmxjPp1O6XjpVo zSV^a4@s#zKp6kx_xpYR}P)Gp7>V&Wiq2_21LhrGWbvrc78#}s0gi z=_2c;ye;p)U0uyNFX%_VNRThZ4*ikp%5k|FyDudDQ9^e6k%VBikp9K>ee#K8J9>J< z=w77r?!yjHFKCK$$tL>4Lcs2~xUm3I>Ze{mxv@#<1bzU19k(l>bx&yT>K$PD`TLC1 z6QbbCD?Fmfx_wTEuMl^#ZN-EKK2aW&iH1>d1pehNq>~E`eOK9LF`a{kjO;CSef3AK zGZMvk6R%WQpS8`_^eymf7dL$b07NAJXKW9;cu;gaEnzAHR6s_o+hn3uVlxq`(!eow4>Jk8z>2?v zA1>59eHgi7OeOCYg2``;qUeK5!iXAN8XH6AV}5NCZ?>v^0*cz$fNzMDjXlo~0>C3I zDYw8<=I)p+MC{Hf`En&YEdony3i;h`?jC3T9(S~~wuSP^;T*qFx!rGT1e3>WoxIFt z`aN@p9I1Zk_n&kmM^IW;II6VNte5D~I%3u=KTzeQzaQWid>zhncPmxoICjhO9?E5C z{(#jpRj>4ZXu0}Wg=pclex6@e_o6VINgl~f@JVWk{w7W!#1;CS)G5d0AI=skE6#sVyD`NRFr7flGmr;kX|wDvv{O&&xE`N&%I!} z9D?Kj6sd*Zs}#*6D%kppU;O+%O}n48x24x7z6I=ZC*${9SY!y3cNh<_hNBU|e7P)~ z30m8u0R)8N!&!*M%r6Hzz&h!9VNS!05ex!-&ewTPTfz5uE5%;-=OoPh0k8Zk@PW=s zzM`{tBz)S7(Q2xo!GZMHVk#7?i<|uqnIFq_QBoJP&9Lw+dMeS>Ld%se7)+02SkU_b zt_k#?Vmf;ANepz#?EBkqVCT&jD96M?k)}>Mz6+>moDw$;t;h8aezYl5uaRjmpVYm1 z80X;`{Q4E8y%Hq4NSrfK3u0(^`?=|AS~Z!Y?|-=x6f-ryG;cjuXnva$4g}mm1cb?vsrgA%8@7vhoS;{qCP~hc>~ro4|qEFkSxUkUSavWQH4W-a6EiaG+6FQbQB;*FI&`r4&i)?HqMl!U+J zei0I$^1%*?#{^#lOfph@Ds zWK>A11%6B(=+z3DziJs&MCm$Y<#tO7i{VMnPaP)F!#*&P+nBf@vFc)EkUG=?s*BLKIJwFRpA{^&H}j8fM?o)q(V%SpoGQ%I?eB zpi{MC$*fzS`&<^=g?NCODUYrKOp%aQd$6Rn(ppAfadj_4+-*wk&(2$flqWz?0n^L$ zW0gqu>+PRnI)cw9RJB|>h`S^y>{8M$ZR^un$rlYw-+Vzu!=EBr1%m|LvORf^;r_p{wp&@jNT9=WwiRnu@>AA+E{yzErygN0t7AhX<;F)siDP zKY6fHV2_w4#-f~_KtIl;Yl@nr#Nwl0TcW{!$P z>89r#W?8xfW2wcHDu==c0r|e_B1ed`F2Cvly>0X1mtJ!%3Wen%t{NNAI-VarD}Q%@ z(@!r`n)zR_(WJgGU{X_5Hz zDIPl(o+^w6&H{=ultfKDLywEumw zI++^-eEetN-Kpe!_i4Y`D*egBiB$f3#%}KNDe#zoE7QusF=>Hmv+<3~E{NKzqIMp- zg*ACSS_Jd@FlmMq2VhNtQ5*^!zwsJK@Fx<-)|8X^xfi}hs^O@{xo9}y#G=W}hrgg0 zoR2joL?k-|pF}d?QUpO5G>CB!(+IX3Z^9}S+eqHmx3j3Ihy~6664F%Jc5QbH!&&-lYi zN(MG_5P0lNcJ#X$Mq-lkJouZYRw(`bio!;=SaV%MPLDqoz49@E5o3b!T}ez#oW94+ z6^8GQy_T?rcW(liItG#=!m_=O1aC{+Pvls}6;Scrj^16hMTtJ%ffBt8dIqkw8I5LTFXO6)pS}XR@$Dl9n`JhL=E798Y!0uk z4I>-bA_?Oy2wg%ZJ>)Oef*ETo7b@2Z#Wn}v)L`xHvVM2b6>xK8-0Izu2hs1tZ|DmY zax{olapEXGl?-SDE_87;E?P%o3@x-#r{BPcj~|RsH3IB5Z1#c;xCZaBq62E}9oM`k zs+>8Fn@PaKMHXRSI`coKbD>OPlWO^m@?+7POReBOa?n+0dHBf{L3{Yk;q>rlfTVly^jP4y2u2@ z+p~IHt@_A=vOBdAv0+I!S&JREzcwCR!ufc2Cz74m**V(+G|bH!-$v+gY=j;qJs_>b znf~|fx64mQbCz#)a_I91gW60*shEgBex|7zF)m(9TM~8OpgA7`k}k(M(#dnNp_c5B z(U#KD0Bgv`SjSTR<2)7CR|owS8l-O(aW;$DpB#pmsv7YE{S}R;2b&xL0U;kXYII`4 zY#ma%65c}#KkW9ry{@&pW!^^%r(Cf@j!Y>eoq-`6bT!I$KhBk+$oF@8B~ap?e6O`O zbB}FPWrc&Tg7rI?;GREc7D$FOiQ@ObjUoNrh<$Qm{95loj06!spoI_{jr-xB6Dfgt z_@~{Ai;E6h-PCJP%CD{7x5wY2KQV6M9`Hpv)L)lR-P*7?3@&kYGW)?o=fylcOmRjy zeA_=6)Jh{HAv`^B-p!lYWDuOdYlQj(Bk7`pxq~Ybs+DtveE>5CJ@PU-x6$Fzllr=e z3{~pL?|J!UI;U&&88zi1>N&|Pl8E9m-~ zk{%igH*{oVBmhDZRDyV@UApA|p(qkW)wN(gc7BYwiyBBhOooYwpreKZ^Nx6_Ls56j z2aEQ3oIT$E3WBY!t_B|hQS_CZNF`i@i=n#CGRf!j#Bl1}$c|KvGiF6ItwWtHR%)PF`V~`g0nzL@999_ zg#Cg4&?WQ`LkK^1vJZImm~{;_TSf%Sh-FppQI(VJjmV+%EU}Y!W4a;zhn2|tDDFm0 z4na+pR?aQ*$`qHMYO*gz=OOA_~XAQ%hIa5t@lku z#6!bkL5i45&hmr=%WIV4AOq46=QBftAUZBoH=>FGQpDvf=7GkSu9zzmD!>05;1|jL zm&))(a;~=eAKN7SUl3<$mEFotU5$+~W3ga~Zxu$ub)!3z7ExI63zGhC{v_f5L=0kR za<$|4icay?LXK4K40aab6_KejcJM?9SahEH9~WXroJIX(DBKAy1E9{}#|8FvK85ui zb$(AqX%s90NK1HXHT8d#6;vDMLUI^)%@_kQ{t52%mFy$46C{o`Gnh|m@>G9A`Ce=a zfabC)@_)>kF!Nt;PB9pF;irJdrf#EXyb1n%m5&Y@Np0N4_QS#YndbP{>XDEvHLSfD zDT$!}y`O%>nXGW57F9RIPZ8H+6SsuWxbObw_%D#o1p-cX*~(OorRdml#8Sk-e+J`b z2L?jf*qn@~0&)?cplB(l=!Ud28rUtwvx<2nT(0(HFt?&$A^_qBFhISTHt*Z=k`fDR zYx)&TBTJoWQdMt^j+$~Ju{Z?GlLDSXr z#$cIqJxNQaMoBxj9ne?nfZ{-~rfV%YK?*X95rT>V)_}Ve{-43xN<7LX@AM8X$e-Vj zsro*E(4%=xh;|*rvVED&mdaIFXFF>uiPkF6+~|4Ha(sUAd{ih#!!b@8g$c1IVLxgZ z+G(`hf{1U)!`Y%eo_Ax4zG^S%Cv!^nj@;ZD#dj9S5e^av5Euv62mfa;v5WgyfvEfB z`n3UJ982TtRj82n|Mg+ZB4=~-*;VtW_2?BJPZTGud`oh?|J9KgwG3#ZB4k=58d~iQ z>}SdMEbS9SqV>9h*||QfO;ggO>BIEn&H2&ZF@F5J6=Qlmj**CN)OFjLO>;W;@Ih^b zfAwF(|0Ww+hKS3kFLaP)H{@!ZXmieS^#E)eL?k3=5Z8Z+u4!s&%FfO<`hp4Q3MEW> zG_%8~G_ku4x7>ZRRBXrkn6tl!Ky1X?o0rN->3;Tz&n)OEBz;*#Pi)-xQZO!gn@7*l zfu7y6M3JTrBC}8bU882>UBW3423Wl(4~ia#GuCQh#4lJ&K2m77zbH1QyV6sg<}>V} z@iJ5#4r*{;iR7KeDRkLjw#%xNBS9>Y7#5MUfA?9f7I~O5nYJOaHRvv37?gf=uJ^b- zOvyZ;tVB=r1C0LpN~t%~ithgHNY3tl8Js4?rF;`3?pybHPAad6?Q66|U_xRdsfQc( zLj5gc1+8qE3+1_dLGv1*9yQh7(zq`KhhgZZI7-)zfYm4U8yO&#wEVPfGC#Mv?;RvA z1>(Lq32k!mYv^09rUUz#uJ(+4#(1d%)C)p6?=RE>&RU5WdGZP^O1SL#k8;SV*1kd? zu`wU__G&Q1dl!EP*5pqN(M7l~w>(dak$z<@uMtf<^s;~X)bLqw1%4h2lK1zb08WN* zaz4~mT=ewFkR{2bd#T8UXs$N-nHa?dxOfBwN~OwXesxVtXVwlmhD4w_dM(uW*0rk_X7sdg}&GkrUM00U4cE{cW&04{qrvAb1808OE9_krye>9{ z+Qu5hOM6D$EYpg%uoHNL9?B>&xbe!KKo$@IGUY*mAmyAO?Z*U|p72T4Ln> z!V%Qah>2Y`iHF_RIMer%NpJOU2dF{bjOmCNwS9Rt1I;{;Lm$P@4C$`=iQ} zmDK6bMO`ZpoK^O+Q|N7bq1kpCpy5)tY8R50u-^jy$Id9B-(eK13|%8ZSVp4~=*!-el$7I= zz9`p58McNV^kAly6k(Z#mR-uN^IQU#xUg=@H6d8!!PMS`NdZBfZ(MWVuu7!V6boAb zj#WTP@c?J(36q z&|JM&U*q8jqR<6Vj~YsJ)Be_h+-*ww@E;3D4XgAVPY>v-o(eXZNyriR-UO_ad>5(evB`f zKB&sY- zC7i!)Vm3XFD@+ZfeSX##3T-DrrTswbMSHaKbZG~lC+<7F@+8mwMd0ZB*$ocHewJH? z-~P;e0eXpTr*soz-`>H}V*JHoA>k{5R{4@Y_}C`Mwqf_-?5t1!9k!!p`v@Pcf6Q7@ zEE`%Q(ZcUizD35kBR;F{;Xs4StE-YjpK3Ge5{`X@Q&|gt(1g^#OXvB?mDVzY zmoYqdks!yHNPg6-Z~ceCB3P$Bp`1JXn^~V~)Q=(K6&T~Jhees2`O>rxiA-Lnn~v(% z=_IZ}hS}>bi70@0euwcaBbrw2TXQZMHI9Ravd0lVxK>3ePj^l0EG7{?4$O#zZZ!4yXh}>SY(<;A zAyLVDdw+4=wVp)#U@PD?dDR{5P3h8JD#3{rzaS1u;ueT z=s66GQS;`-P&bkgewBYotnz*QODeO$I#>3p zL^XK7e36yrw47q0d^l`)y_0+2OHZ+lnyI@EQsq_{xsEr9%U8au0YX=>?)2bQaZ2rc zl&2S70+>Z3Q(U!eeA%v5pOr9*kac5vuxh}l(ktaRU|ce1bH&yb+w%T%26X20u(vg< zbeyJ8v3v%|-HkEvmjNwN<_D1y1k1er0AA|r{);MtjV_67+4)A5+o=jNwK<8-&lP8h z?HrXc(bmngdalPvI;f-G=?CyzFBbYGMr8svEhO!ak8)Qqlkv41990%L&-tZJxS+U~-uHFq=A zq09A+d*n*TlrYbGDR`{t)!b|{o>$(re;Vcr&Scm zDoZboR>(N(@l!_%Mnt9FyMh5TbBWFY$oQjzM>ZH77fT&q(bh|y`_I+fSEN`D)UN8) zosn3i@5(OwB3OvDP&o9SrP<@Yvw;Ir4TpVCSC*jI$_Xb4)j|@ycqQJ*=!o{TUNGCb zC9{>!knXjwuLIj5-S=0};9|6~!o5j;ets=D?Atd#8DF7KgeU4%>NULOELR`iaOjet z2kzGjlzq?6NP_!6J`kv0(Fn;*1-KXAL=~q4Vn6lT*_k|Z^Qk9?r*JHXr!M)&UP}$VvWWmbrF~f)nOWl<%a?11*|ZU zqXP|2^M$VdCUzO%<0SD&$WEh`9-OXrNIk{Q?6mwn0^B$w5XEj+Le_{L^wCf-m$4{-Yh!oy52K{4Y zEH!HouA~8hE-nXnQt*fWpXznLrn>ax+l>=*B~v&nnfN6);nJB1GzX9XZss{7gt(_p3WxE{j{_#!G^n+8Y^850vzmjfsZOJpY9o% z?6X(ce{zVrN#>$pll{2aVK}^Ffd7Tk!&?Vk&UGhRiwv}>JsLu!yjJmHOpn>L;W5u$ zScc^cL$Cww+tD1H{?1u37GN`Ur{o)v!1waAwVQWNUY9^+kHkoA5pEhbL{HSY6fHB> zP}i$4jc(UaN#?afO~Lp1(Sw7?!WFJ1ArRM@#7!)6$P-eYjF5$zKlVP_;kY3dEH&fz zt?rhR2BAR?@2tP<&e{N=?%H(C=i4aQ2l%_G(a`{ zEmmdxt&M&i7TiXj!w^ykW`!KOnhoo~^tuO_q@=H3L4MaJc5-M{RrV=t#}sD){hNs< zQ7umUCsI}~!Eg0*mcIw{mH^o96@^hEkzjv$7e4L^Ez{%pQC+*R%67uX_V4rW{l+}K zUG00!Z$jlZ;u;)^eHkACy=JPJtF2H!t%)~^v_2vqE?R%==4@{620XWk!sQN|&~Ocz z8~ez{hY=&czevFGc4O@tbGz&fWcC%k-3E`Vfx*Sf)+2@sj=cVY?2!~XGO{CFCC#+XyE{|A;Flv*b zF8uvuy{j%=|&nBKEO!LMa9@aOv zDjb*=ZI&MJDM&IODZ7Eah@w+BQXhK~jzngl(qy^;n82t1d;^2MBz zu@;+oO{%29->=2W3*z)5R%CvB5okg$=kwgqiI%F4uTo?>R!8DUx1eMJOx$iPU@c^P zAysN-dCr^T)hIvAM*E2-UkCoQI$ahI;AcA;#J!qMbIq;f489zvw1$)yLuV;gE@~p1aOBO=OrE@dbKjIJIu37efmp9 zlUTD^-4}PTG~t;~0T;RwW-YSi1GMkAxS-egDCf=AtBLN(baD-5T6oLtJOz^NZ}VPMsW8}v*uQs^hI~`C3oxf1qQsRMX))o-kwR=d>Ib9##kHvEoYjnzJs`Hivb{; zOKmOCoZdl+4Jl2ZxtSj>(Tq8kxrnsdXuGK8k({308%dXCDjLMQppIbQYOv()5)RTW z{nFacBXQ(en1E{%0FIyOI%*or;uMgY*l?e`yUW;|U;IMpaO6XULdiUFEaR6H_q$%~ z!kBF_t1cRI15<2(nq1E$yv$RHD9*hAtHJ;oPW?9&Hg3Y(Ffz|i0tyUB zOG~8;<-B0u(xd=ZM9L{sj1zxa2cGX+LK|#_q@r%^ac^5JnZL};L!GDbE0o-c{D1vCN4yn?uAr{ao}>a$OyE5x zwSIoL^GU4Y=Ty>zb1spa4J!a1i4W{mIyf3d~sVW$P%?4?O*XvwvOp$c$Q!A zRb(U5glpO$6t~YLugejU(O`j41E0s;ebMHvH(Wke=6*9bwa#12bTs<5;*MjTuNe?s zZbm2HV;cDV^~{xD*9~*a0h@YC9pr|rs-nsYvg)4MQyxkBr&Knmt43PPJDkvxC~NaVkM1)I-rGzr?G824|x0Tqw5>Qt%`(6)+*1hIkd@ZCd$Ra*nJ>74Er8u^}Zo;=kYgN_Xi+>QO;X0Dd9qR zdek|MWY5l~?}MpxHPs*IX$>C)8{eg`B@Z~E?LFD{NX}<2f|z8S9DR>Sw0&Az<+5#eEaX|Kjn4Df`fd>gs zUOw35X;b1W;wO@Ubj|p0U%u+awo}GENKcTA1-;tp zCI_W{)P|)gY_C}mPaa{_uB_TuJNa1*#PC)bSjX4Iz2%oAEOg4fIEunOE!XaC-CX0# zqleFr)JOqit9H4&4FT-c0nSrtwz;!*og}AQmU%Lm7d6WNX@51K<)pz9HLw)F+M=BiE$Czg>WUgn{WHf-_VMzKvUIXj4Sf?J z29tev2LpN;gOJu^BHiD>Ks?_Ajx#K4Uh}zc9VuM#j7Ms)3xxg|uQ@QILw(#&MOB#P zB`v4Fzp}|)XC9!Rc0UKpCG#=b#45jtRK)4G**M*=uCRUR)rTB9cNSFaLeTIg&kclJ zPR)fu<>I)5TFnR&f4j)`ckvOA`tw~j;i-33k>z(=Qd_~A&2@dd^e<5Fu(*mjtJW=_ zsjc1B2z5ZQQA*ur7cPCzR>22XW~p)OB?hYNydapR%iv~5*hP?`{XX2;&NpIA=a5l! z6VD*2Ck@f;x9;5=?a&GbRHOZsZz@`0>JqDb)IwL(3t=Z6HAY|6EiQ{~FtV!9r)?wY z-L@#4$k3nVr#(DGnrPO)o^$@X-CV(1VC|%Ha%h;h$ZW*2{_Ojbo_RlUVW_yag;?P{W6a~?|A3d+E zhNMV1zpT?DPv2k;e)gB^VlagvwX0^sfP-Kh{qmbPK+1zkza z4}0mM8}w!Lk~6B|@)dOpKlZ(a%oExUT~-D9Go)Qiw>$EukM1SaB{GP_HQ3vl``MM_ z=WeK6RaCkQj5TCHcC90@19&iHo)4VBXd|Ki%4P*K`+oI;qVs$;rIErzoF46VF4Tc|3wFrX!0f3bxW->A0U zPSxS6=vx?zbC8!zSR1Q8j_n}W{XqZ|30^;DuOV09cJz_6bd`3rrGJHTFI>-oWUGwS zt)psHw}5jK<*Na={)Iud%7)AhJMEH-oX-u)(|#Qtfcd3NY0C>Ww|Z4!?c~i$lIgRw zqkh3$)+62atoK=XO&fuDWab1x;v9|8-s(q^DoOeHWd8-y2O%{w9=T8*0~vi$=f^^# z@t)6??{-q9cGXtRW?*NW&F?tAmtP*yCcOnvdDPT^DS-Zvlu!*C=Pp}gfED5p_mqHy z^{2EiM5`Onx=Xa9pr8;D5s4b$nsYaSbgx`5Dl9BsQw_)Yk1hsRQBj-k&JUxMNkV#J zs5X^S%I*PBc6>ZQsqAH6ij}XVL*PF&D#oE`FHS4X29A zDUG^XU;d;2X$-bhO1m2_5_9NY=7Fm=k%MBilF5=H9LA#0>h5%9;`w$5gbvB2(V|@} zbFpi~)!($i6bIo8m9q!GQ0$NA(Ckz;=q8dZ2|!(s&%kd#9$ig4%1JoKJMJZTsCtc^ zT;`vr!*Ndol(rej`xyQTK-9qKD#(@dWp4ryZa}?4BzTilQ)9>{I_k>cU_q*hX5}mH z2VB3gE8Zq)qr?ZcYUd420h)7+k6Ut;g;5Yr+A5>^vdG*;sJM+JZFGIA()^^Cp(ZRL z-E<-#c=*ZU_NRkISUJbc#_?P6rN-r;kZT4T4o<1Afa3JvJzH7)mfx7`3VW%}f>8;7 z0`_?n>R*ZO3c?X#p1h2_PHj5fs@(3RO5~!I)2hpZaGm?}&k({lZ3)~f;1mz5KCobf zA+=!@K1wBCnW>e?x=CiUz8NvxoXFcm>Sg+Il-URPUCI-!9mDyhCgAcflW z6{w%Gv5&9DgxV~{JyfM>K)rJre{b-#TgQQma>&-{*wuV-Yvr?|AAS30RsGlFyrA!r zA*2oQLUNV(C-9-5a~iFxF6h+?!@p_fAD#u0W%d*8w0%QDLPUHSF#l@OqxXi#P)QuP zIuMBr-22bJdjEihoiT*;Ya8P+I@=Iwa_3)(mVx)Lu$u%Cx*>{vit>Ljp4wIf8{q&4 z^N&Pab@*2gSGI;22O*QUP3=&f2es}D&6mCZyC4!o5j>bJk^_OhK2R`2LCqulGusbv zx9(&CrIMBx?5E$(nnt$H?KieT+RLp<)&pXiLLUJ`ETKj7Z!oG69q`EhR z*!GFh{G^(Dxc*P(4_p-u)p|Fx35WzVZ#pw|L%5VKGJe#tSMlbaj28bBK1~PSapsW6 zZWDsBy`#-=TbpP?CJ;UO+E!*grcv*>-y^a7ebY2{SpsU0oJ&(#Fz0UEBej_{SD3KB z@_#N*{QEZLJK09k<%P6IbE6Wfz9@4J zCn^@=3FTpN5Ax#9}qUOlwxp6@N7sKECLR;n#Gb;X?@md9RdZaTGQ?nt9P4`L0|h@Ci>jGJIKL{?Y%RQHJh8Oa-K(`17(77(GV}GiHb_I5-2wljX6(}fSI|@i)uyjBgga{ImgZIfNS?#5(r9MaX zC`6XymFpJQRpIvMitZTwSAuw5cN@P+H7>fYfMQA*;W#erKO`^uRkZa{jJ~aHHF(@! zdYgDy+Y^QIUc~0Prrb@LM^C(5a*K+ZvTfqgpNhx_-H(}<9$&7BvgW;+pnFIp-^i<$ zdTGjll1Xw-=jd>Z;7n6+w{l8$xBT9NA`y9BPBq|9>pf5Rk3D_vJ#E*!;s%sUKF(RY za?JPAX7QAAb%Pzb10n^$(Md&M)<%4XK^@4)&>HvdYFCEjGEiKY#H1VN!cD?{Dt1@-}LgBFMe&37eSi##r6 zQx8@v{KmSjW}&(Fv0HpVW8H&admSV^e#_N&(qhw8$%ZPI6wh1erC~qeDEC=`3_SciawJKSHSZEkU;7BRs-+;JoUG83 zMX#G*=%Zob(6f%Gg{Q{+87+sH!40!x!6)l0nvG2Bq%N>Cx1A(Wn?$tc{SXf$)m)uw z3_JSxheC;5w!*^JVfgscl1v|dT^}XmrJeO`Ij%Sh2|Rqd$s?}oxk*IqMEQ+q(eN2r~Itw=t4kR=wbu4 z2&qPSj!DG+Sbv>Mxa1BA$3@u$c4{z+Q*+HHtO*u+LsS)P1J)T~KArGStc|wL+V6oH zsvNhJa0aFs()6Eo*p6WNk8;JSs@0JwPWxLp%nvqC{9qF+P#9A2((l;vZ!M6C^l{J` zgj{zbhUC*AlU#mzZxAPtsi8pw8}fAc@U|v;@iFKznb@aD^u_NuOSM%cYR?mAUvd^T zs_b3b9Z6fJ;bf*gFyEB*9(;}~TqrRaS!om;Z=LsU@lnRGp0~N(OIp*o^znnR{NSXL zLwA}5_G#Ayglz}j$k7h4R7asW)zb4~dkL9r_jWZEj1Puh%=W=VgDuAV&5e@jYA|Rl zW`CE~`d095h~NyN2BAe-s6Wcj{*6T6$X4+%?rwf@o5-r>)vKYftB z;e3{cLH+_ask3Al2Z`)lNj6;de?a~D8IhKU;>W+A_k5=lfO<~`pnB>jGViN?(1_;m zeLa0`|C`_ao!iK2TatvHe$~=Ig1IrICyDdLBzfh2$|Uu44|?55TDd%2`9#oNkMAol zqu{~j9y#W+Yj*4Vv+B3wzsnIW&1XuRB2xD361ZRaD*yU|N}h?~mNzXjk!X^vbKStV z24%Q%mN@7*cNWPXok^W0O(Ew?ycs8a3De+SkLcUDq?oXnP5n_E5ek=G7#{3elTk)k zG-`n3wRklkk<*H5pe87-6%2D>E&;otoVbckXsw#Sq4SFpQ+JI(Gg#iJa!RXcq*odxl#)(o>A3vnV3?fT zb&l8TjZ)za>_MNof4~6JHKKA} z)9r9mBDBk5Z&{|v*tsvL>Ek7|Q{7_?bjn9QFMxfsKi(o&U+4OMC+Vch>Uyks{8vrH z=7F~w_qtLdb20))(dABz)P8wFbA^VjtUJTYsOmxeFJy;^hNg3tN^ z*6Cl4?Z3V#fN}maCfu%bI^glcahN!fo7Mb#eJg!&exK`^+1c5kbs#XnAQyCYb_O3V ze+ELMmX?;1l9I5nu-MpGe}Dgm1|A?}d3-+*6$3EJePwle$jBHN3l_O9l!U>4V71ud zb$+%t$7R2WgM-uTb8|Uaq;+v|(E$8U9v&SX9YR7v_^Bub=AnCYOiWC6_N#y6j?6|l zYb)a8WxkKc>k3CN9zg`Q!7VJ-4Bs5|L$#d<$IZ>+*P1*$JWSSx1_$Mpl<<-L!Gh@n zYpher-@gOEdgGnAXumO}2!5p6PBK)M&h6R}-Bao(3~^D%H(EcZ_<>~~RiYU|R@KE2 z@Zl-V(~v-T4*nwu$N%vbU?oh}xUEqqF;S}Qxvv642}`0{T%gK zLi~t>;Elj+noV^PSE5~{t}yZ=orw!i(`QzH^Eg8~Z81&{V~PGPpM=r61{7H8T1#n$^VMEUCA43@Rc7d{Kk$E583s z?rOA`)cyPU6S^XxWOwl3XL^bj-8wcg#Y+tz+i~CirCh;luxbhG?B^!lAG~ZNT;NX8_)0AZ z?{7U$e`W=s$8imRNF6Oe9^0%K=SpQ)j+DPk)duGYVScy$VfOCjPf(xP%Inu4*zgR1 z4v8PH@~isw1#wSeWYi{uS*0HzGO6V4gee%>r6AqrOy9iM)~whv$u^6pji#lZgt;+7 zd>dYm_cItSwpA`BBqZeL=LZJ90JbVtEnHVmZ*F$>;yD6rOvBKH0&8jCCY`3TkoDMI zM$l4=@a#j_4oB13Xzp(oX!1P~*#{^9e`@p!Ld9F=ET7|sPs`6;VIpr|Xi&r~W^qt? zxU#0Y=2u>%hZj1!S17|Zy?fJSr5y(+q{M6h&RF8o7a^WmmiWt+=}**@gxM5q?b=dL zIgI|$_R9Er^eb243E=9N=(Ju~dV9=fN>-eo4{k1G)0Y;g=iN-8WDr_`YU`w2a%Y_! zO4{67MbIWZD>U>q!z&e`B#DG|n9pjbsy6 z#d{IGKVl<|KUTeP_==3dem;bFr~Cb#Z0v-!z~P9Kl2~SDd&hOLtAYv@q(i}|1w;?_ z0Sya_wtkdMUSGq*^d0(qOeGPy0zw|HM?ULjP%$B5&yLKn{^mBvAn^qa}~Wer(s2P1;oqv_)RhA z!mamhw2_6$#I9#F6}7+-|Eb);yB`!^bjk-l;d0&1hRIDc?UEFi?fr}=-7epfVND;2 zs7s%F#F6H43t?M_jmK96$-LB*)623pSl?@LoZf}TIgn(JdfeRnc$6GlqJm2UZ)rnVR6I8 zY=`S{PxCMgcyi&a;JKUXP@^2Mx5#gC{Q7x_w5BHBtn$^`0exzPO^9|zkopBpSnx9E=NeND>n5gBh%$&{&rxMymJY12Qzw6xNfPd zT&%U^{0(z@+Wm2Yp4?dwa-)k$E4c{BXX z$zxu7Zi(neToGAUAf%aTamoE1N7%k3AbkL`_wq3oSD0`u`O-7lcd9JV1tmUhn)8)N z7qakX4u+5mDQ6pD?>GBsoyZ&-sf62)Dd&E4+T9MgsCYgBIdELmPJE3zC*D8Z*cv{3 zbDda77wQ|u{S4nO$YAH1{tueQ31`vr`YCt0CGPQmv20~>w83-L2f~{y)AX#=pkW_F zV*O&C6+@~?RqL>W_)e~29}zzNDeG<9d4l+l3tFS=d`GH`O1fZ5OpSkB4qr!jMz{AC z*I_67CdWp;4I}w9&DD~&P^nai=j3=D* z&lX%-Ldh8BYf(Fln16ZKyQ9Dskz2~!h5yJqOvbf*y5?i z<=1uB5Js#;JLa+!g7e!!;$s66sPx8m z#sC_xasFilTP-T9c;g++;17X}ua1MhzJC2_d+wkM-On<$Qm>1Ivgv{>ZE%(rf)Bmy z$jtUx#-_reuEm&}9<*dPa~Ho^tWV-jA}9PuGLxgXk^0H#oPX;d*7Jk|KE?sT!R&d&pi3hvi#^#Df6aT{@CQMy z>~WGDNN0|RThM2nJaLeQLuUW(J@th3_P&j)B6Gz4^*Aoyj`1CiVe<;Pf=VhK9!oZ< z*x0y&ZoYK{VU`}%gjppl#7wm~KN``OUBo3%H<&l5B1ILk#&9F9*YvWC^DvP50$C;a zb(#n))8QuN-OHEA{$^rK(r7G%I@ngXBRqoJ`zJ;!1F;cU3CRBUUu-gw(R=X&FN(iantwf(t_$Lz=T4(>ZW1w1yMt9pu6jw;w87|38+v@shiR| zlllS?%Qvuvo#ak)!K`k~gT}~9bB?tohNBVawxA(3ZuIi=}Ny7SN=Ci!8vGp$5bUrYV55=nL-7hDRPKo<+?o$R1Y&ozVJ3^ zf(k|JJ8EBs(X*^|!?`zc z<1>`O&t=Xn)z~^xR5qy9*pA`t^2{w0#_Srjy4&wcKNdWFmMN=_zl7sLaj~`~IH8J| z{!EpEc2HdDsSD?k2|ZOQMoIgi@2eJe&U`;^UtaNX+^_EEVSB$o(fi*nl84tRChQ74 z-eWOq&IH}Te2Ao-YSb7FBC)Il2}2H&dK~Do@48#{Bx%`PtRLgO6if%y3cgAgd4&Bc zi&om5EXy6;Gr}0f%|CoXF+I~FUCAVqa#gGN;*|eu8B>r&p9p?{W^}z~^pmiFDd80J zaCoKZDW2`Io*2N}-1NJiRq5GL5O-8vrUU#EvIDr;dMzp{CB6#`RAew>g8fFc6t%#w zaql=ZC<3LYv#<@yjK85KD(cDkx$o_DLs?mwC~Sem zEl}?yGHEI->EJTsjnKx3FZOUA?%HKu=sZr##JQ=8MYp{kRY1z{@SDqPxJmWQ2(4ZV z1HEUHTNw$A)DeNpBKk`7)evS*B=!H$Bx4VvDcr(9QdI{;=U-3EcJ5AJJul&_w%l(A zA||VfT($fwLFGBpxjJjUHOUX96aY(6%r{s0`cLgymEAL3-+Hu8d{sXngb3Oe_PdkW z=6F|UNkWH-y;m=box#a=Zdg<4_OZSy2T^q4>}uHpDI+e#LBab*=-i;*XXmnOMaur7 zySx5F8xadkk$Z9U)M#OQa~igh)UOQB01eZc!yyDVG?&{m6=oOwececL6dr^v zI)q;%o}V@h71$_SfLM8sz3*wrV;TJ6qgx)Botqnl=0e%+;v{ux0R5c>Lg0}N5+zuV#2wW^|I&{E$Cdf(J;LHt{+f9Q&ZyQ|>y z71h09Sl`=yV{vRL#Z<;6D%!k+bS+ob)l3~<7F_Rh;GjHn6AO>m*dc5JC7a$fG!*cO z8l3Zoga(Bl39!}k7UooK&(MrlA%=w-__e1Qr3c(W%I4e_r?MG_e-wHCp?*5UTC*9x_Y*@eB&Fw{15KsM;$l`i<44giEQ zMSY91m%?cR*_@Pc=1E0k%e(&J6e8KGLg0?P%x(%ltW8TWm`Nv-b!$IajhnZX^C0T0 z&K@NZ8P@?cHoOH%o3>0j%4%1Xm0fgZvc=RhbK4uMWV@^EF}7b6knd4aF0e2yM5rOj zL71{-mL*H}kA(W~S6-GUX8XAQ%9Febyd&(eh@7HK?^1h$=^6*z#!TZf+*)Im;hhRe z`Fc`WjUM-O0z;HZGKb%#Ko^#^c41RZq4b_BWqBl1kWpB%)>{6CsJV>P?}8@21iu2E*2P79uUFEl{6lRTouRY171F`n$)b z@c1JMBP5fKupc@tJ+eidwLN^ zY4ute=ox3ky`fB(80Q!g6669Y9yXvHvLnwc$YxcU2P|OjRhO2V+6nT=U2w2q%L%4k zOG@QB(Otq*`^z|KZ|eP(>&%q5i(iM3$)m|8xbHzFAi9zBA$_v+6*JE?*^Pt~0zN() zl0(!&FN`SM+IPZu9lMQ)7YQVyD<3~vB5;8$2F?Y)Bf;-@&-_K(l@O@2g@n8;+dMr! z#?~tXD(ds{Ui(bCAFT!frz3IuxZur2#&z;(IENPi5cX zLh$`aOY#HFAH|;s$@8DaKN~S0RtPwU0^h=Pd?j=>{|b=TX9rZaJMP~3JQu-lGpkELW|dQ=sM?6iC&%EVzURJL~Ao$ zYS7|&dbBo>o11$Nb^QH>tL-7gd$Gi8`96?4D6x6^AYm2a84?|RCz-O_{3NA#emaq- zjJ5K3yy|F-&1sy~@$1&?b+tT6DTRRlYkAqV*RPJDSZb!w=qwX#fIlGn7heQ^Q)MnD z2#!2fr41!c?*!-o+K>OyJp}X?#ci|n!8E5@k#J~vCl|}}&N}Gxe^5k!K%22Zjai<|l7!9mnz9cc9N`nBY@Ckt&K;C!~ zJrsWQl`s^}IsgXdjrZ_soj}k{{b_Jf#5@_#@1?hkJXvbE*`qdjzK{uKOzEv--euvX z{(M-1@4<|Aiq0<;05G`}h8q?R*?jIAyv!dyEOAS77i{u1lSKL2xQ_}BD{_4PnX6XO zTF$$R-Wr(yXX$Kb=zuOD?}Q)l(r7A-R2a;F{P60;Akc9_=};KknZNUOk_j=;{sEGX~P zBAEmx?;^!!kq81rr@!L-i`1%GKi zldx;axO6!nVlL`>ZcS`=1`ba#jb4b~tC2_ne40xJJfkUV#MzNLmLgKBtd$OGQ?ZV$ zFJjbRM5&(miQX7}gFi*{S!ngWW9eGfo$sERfqzEk?mtu}!)MlaKiQ1L z4r3cKCBjd#2SNJ6o#q_5Q(TWp;Jfs(9ZHT%tfC=V9M(lB5g;{`&-qcT*h{s(3(h{< z>wm}zlG6-|sSnhObFclX-I@nOAV2gj;_0TIIN(0Zv{u*I{ytKbtSXgtC33m<0Z4@WGxd!SXwmz`vek{bgtCgjP?^BMV3d$RB&3k`ePRNV?)rm}PZZtW zG^g>7Mua!9G4Co687htA5aUPco0`bEKQ7msd}Ok7y1n)=sg$KOVR($E&l0+2!fepk z31^m6^fazG5?55gR)F{gwS_ynA8LD0|<^ZF-5DGFEh ziea&`-Qz;Z8F&mON*INjmcdW8tb@^?s4x-kqY!5_j_;{$?YtiM4Tu{In5%r^YMo(3 z%V!o9l@hO4tz1Hf@f^wtoS@!#DlOpdiwBOcHR9C9oOTgurU`aeG-Srx2q8eOu}s^y z;;QmAp7UJ;7GwC#x30(u6A9ynqw|sI*GlMQ{O+PG^>}s0>+f4%ywpPqT$D96F`=Ss zLe=(In4d2oXyM{03VKc-wCffJr))~@Hx}XEau7Tll zSW1_yC}edY1v-&z!Z|xtlrw1qCZ9T*u$ey8w|UDfzLemDl>cRD@w`UM=lH;JCwb zv4QK)!Tm&?4A-j-)cyIW!uNAJZo`!1+S;g;7iZ8bO3+1`vF+C+X1AetS|SvMv_g}1 zbMAB5un?Q2v$%U#m zl%b#%;3~YY`Le1olrV`tm|eE&7x3fzi-&Do1OLqO&S8d((YAvIc_6mc7r@IRNO&A| z?>{*U3yX2esSQQc&bH@TKkkP{RFkEyk#1=@QC?*WB1 zv;kQQN_AzNH~ByBTpw-goS?!H)5P zt-*Hm$t0%oKQdql*~5H5Ca~BEBT3+HEdr0l>+H2PX4uPvD`&icyETymBTB8+5lx%% zXB7QlrSWXwjke6I$%}x_>FM*C3e)c3pEdPEfIv}THNAgt@e_icF8x-YR2Bo&ID>9C z7DGeBnP>g(VP&s)ljlt<+zJ^X4rj*&-%4^9gL@VVX(5TTBKVRjL!Neyf7Xyx)9gru zZH>LA5@91-QVxeQ+=1Ln%HS%a;)8sEFWRw)GK{di6vv8o-$Xz)Ei)KiN$X9s01TO; zVNB}?Vlm_0WkaTYIY98%23?y((!a|%MSCh#BVs1QSN;0>S}}#&!SH_Z8(jB@UQS}Q zyE8pCtxF*0vRn48SP%aBq-}X+MePh)G@G%}CgZzbzm6R(IV~GfMzO!hU8vEM6Y-T1 zNO`}~RcMO-a&ztYuADEwtcQ9f-mD_n3W);77aeI^~qpOKT zr1P3%^78UBo8@rA8-!^nXH+4*#l~=IQ}%@xk^VocOTfm)*6qLo5{Hk%udaN(V7TAN za@OKle}_aC5b|H)8YJ#%?(u!c$YUY5lM898_!MU%BTEI5QQ|yb{iy4RNQ5D7@Z}CfWmg2~6|P=2KV-L4MUe#M4ujUIhkV(|1;Or0$NLLSb%2za$8qkD zAIqmZ(`AM&{UakILqkKu!^8dk{QyP9S#-+80%3VV?7%Kd%=bV6%JdP9py)+QqYfg zJ?g)vui9L}RSKTr*A@UkHMB7k}Oju>)-0-B2EEUbR#2+D4cL?h^O( zf|@fgOC6S7MhTzCjY~v~eo&3nElz;s^AaXUWo zh6ePu`dJl!!sq(8Xw;oXUwa)dXnA=rph=E8eGhdc+`;w-(xVSg#$B%bN zqVM~o;ki8qnfvfxszqw}usSuyw@S+uNg@$5pyvy=1UzL+$jl zBEYqvC=)xPu+|@ymX@vuUmV#!_5@5koqT85nrql=f*(w z63m5aC~qdqaWuB;##1XUG(Rp{sw$`?T)7L{wO^#WJ*G2uU*pfAE#z58IH#t22T$3n zE@u(-tQ$j?L3$*8$g)>4+8OS0xTaas)uvHrx=0UE6g218EeTWJ+hQ)04hn3qgVplo zomy*>x~UcTyzUsPr6ZTdee{SGb1wGN`?5|y#LyYnM^ezk5t zg8B9$o?t&VgJZf>8<|hIUke^foo&QB-y^d79*&cBZ%1t8B6MAdG~%cs{vLL6ziUYv zw>O!*q>8Eryfh{9mw*ysX{JYy7y(f;u|X|=jK+$2E&kJi&9a$KETPZXFkj|UQWX>2 z&j=u)03rK=#{G4qb0^`)7__0*_A_T zeC!kVxIk026Tg0MTkvF&jootX3aABpkXM#46}DSxHaMoQR8XzKU%e&PL*aO@hQgt< zfBX&S$)~_4WkSh68rjIr#!IgRoh`l8J$e;BukxXylB?M(+D*KV+KR?*SsjAo;rf8@ zR8|MFk+W2JakBW)i&T74kW8xom7kmut$4j6b&Ln7JVA(;GR@AO*}$%ZpfOkJ-? zD=2hXdnw&pqMwDbt0xTan(>_OZoQAB$^HqRgX{sl-Oa-MQ4=Lk12N;cj%rViZ-y&A zp7_-{Ox7m>UV;nAYKP7~-V?LE)_PJChi;Y@W9PQZxwZLQSRo;oM3bnbT?&ss{SlkE zRm?y7IKT)kwofm!{~hREyqrSbfq&w;(?M@Q0T?Xas{i_%}+ps}6@bK_X`GF_%#CZC6tHd18m3zs)s4^@day>Qr zfE611^qA5_NeXRvdt)%ke`IUj)JAjL4Ud6&9s69>NIf=b${WAAMF3iSG#t+Vt44K2 zqSV9R9<0eOLFy{iMr9;Sq|tefeXyS3nL=Z?sszdb+~~gDb4{YwZ~@|5N!irLkCb1$ zG(>tBs>U{ipyJAe;KrQdmf^9=GDsx5K9dp$*?ytXyx`s*^=fEnP_Qx#0rKK~)Gtq_ zXI|bzO~7!MTz44LJ+3aFOF22+G2jIP`@foklTqZ#;6!u@BhsrzrKLg1&{XZu5|Ktx z?l5%pl;ND42Cp^RA7?o3%(kHb`zaf5=IVl0`=0{#rm~P8KeN=Ry{|8bA4|m7oArTJM`r_L8mvy$ma}LPO*<}b z%)ix-Z_b=nTE7YY{egD;;~hz;3W-Wo0e@{rll`{kxE}vx)ps6cW$wIhLxj4+5YQxKzz!n0v99MxohP zCV|($NsaxMP}Yw*SMuJ>!Xha#arVLXJ8Ed)1`f&|!(paJ(%&W~)G?PFv5ozX6;@j2 z+z5q~EVV@XsUCDZg=OwXGvFztK-F;61}qYm2A~Vh z%&h$pSB0fB{=bQWM!B^qUwf2}j?aA3Vmj!xIQ|#XBdzm~&gmPvPS+gDVL7pTMNZUC zFu-VyMXXpzkJ;V*P+aT!@F5&EnCL279BAOyFa@Q0mMpY04#oI80ckqsjh@*-J1N}r zg{{IENMDUOQNeY-F>Zg>NAtky}bq%JSVHJz3UCJii)+b$wSr(xZ4LlX>_B&c>aTsj1A|>1`uDpOMT2C zNXMRM5Jqo)cMmTVFbjhR?Elfl9TNfW1Sn8tcOlyZdiv6^3p4R%tGBPO!R;We<*$`s z(e@bml@Eo`U>n)k*f1{pd=_bT*1-Lqz6zI;lD(|P=j&$m-*Sk5J&s)4mcO(#dm}=lu#14mm0Q z%IOSr*Su^7wNa$+3O}eUaF~HqZH>$zu63%H z)k%spMZOO2c&b|Doi=&!uYH^^A27{7ztIb03;P2_Amq;*@>GASD7RPo`{e2Hr;;?J z`rsL|+!{^d{#4s1c5jCVw^)VUghyO$CDW1m;-cD77dsSqol$n9CdS`YZ!DsAe>0fZ z(_`{%CuG}wk7?ubj0^f(+q2bYt_3@%C_kpqw*p?fJ5ePylIGogz0)7<cgm^)g~$U~4Hu))wbjunl%aOvj5P%-O6eW9skKzRwyDWul zol5c+gE!1AE>cMpZLNmbLa52)LoCuy74>~A6l3;+OWlh)Oq$GU_Z%(=k<$1sRr!eT zVG7d>8~~<}=2-cb^he!0!2G_?;DF7wrv}8wym7Zc=yI;DV%kKPH$Yww ziz)V-c?+t^IZc?^M<*xhh*h98^FLyM)S>L0*;BOD?9C*dXftBISS43P=kAT1!^RnS z8f_-o4hbjf%;OsU<6%z|5Nus6uAMGbNH~lbMj3~F9@k{o-z)MtdzD_%>yk+s2CvDS z#*sQ3<7kWmvVcnLio8K~zHWK+t0DGVms%2F2lajZiKp4SK+wS@bg|!P#fJXOqMS?& z05(=PkOw>y%jfX}%v&mrWwwm?yj}jJhSHL zeZ*W4{OCy=`tzb$C*0+Ws4sLF*BUS-E%D+-+CmW^eGTT+HR)5TYr8o<4hpFcv zq!P-;hy7k5QY_<@RtP=`8OXFYw^iyz3sT6#<2n4INLZWcnrubRFd7OF1e3NEs&(7+ zN39?GLm4o?rDx&;oq=0?g-q@k8F@HaU^xdXJGtm0qSggsR+mbRLdmsP00*XkrnOz( z+M#N2ly2|(<#AreiO@0fuQVA)$jO@_H)@}3PmeLC92+gqr^j*MpbjGPJ8FW<2GsmjZ{UPTP!XkH>-8K zoZR)ZXE4(IGQraBQ6mQ)ZczFp(3cG?0qokZ<}FdiG9^i`goKvb+o6zuZ_n=T?$A>x zVzx934W1FPp57Avtv)4FE{$~Dola&niDDgY#4Csul|Y~4^P4R$nj zm5%J!$qwUF2AA8Lr^a~F_dp8cEaL-@q%jwMY`kZ=&^BCH2!~q21lVMTk3w$en#bj4 zeRYesaE?6cT>o-UikmM!(4?Y>MW7oa|5j|4o~?4P{?006)fIoAVVq(p6?F7keec`h zz7eXZ@m;bk_4Yz_2=GhIBf%NRew<7QOnhe6#=bl7^o1g-i4Aw@H0LTm=RAXfX>zVA zZ}{O^MNYlK5Q_y;S0zkg8Y|`!TJ6#9ixBo zrF8tKjJOkvuC~Al-@5ui~ zh`RPD&0_#B{XQKlBV(6RP>KM(9^n(pAOF!%>3F_x1r&Uh_T(zQ;2>)`4fapHsL1gy%=(=r zkL9@7tkfuwNx$9vI{VRiBEDOJ(3#0z%jb#t#ktMnr|gAc&9TVGPTQ$ZZWoYRDTYoz z6yR>SC}xjGj<#yrwXP?A!qa!C^gDZ>)h}j;5-4WraXX7+R5UzMgZx>zpP6wf7FEu2 zk`2J{Dyyr(Kknn7H(DB@+3+Z;uKNtQIuLF)k)p_t$N^o=yykXO=SecYRgsPzYhW&c zOV<*J^4F}DEa=ZCcP5IcZ77D&3}?w5O+hEq`Pnv6QRnO4{Vgmt$_nZd=iuumt>^7c zrq=32A1SwEJKs`R$8)K0S#pUetZN@S&T6Q`YgepQL%=F7q*<@6c3UII4Dh)`(KZBz zDQPZL5F077-56wkM^Iw+P6w6zaQ>v_zaGc<*#cO#rPFpRT0&t`0mzOxJWMGuI34)-4scVn6mJg z;Rh0}yTEH2m^ge$J^0@kd@fu!?-V-!Si#+DrLLx4aOJ9GF%_;B-F|T`TIW+cV-yO>gvoBX;LnhD?g!!cO0X*yAukHY(r{x);Bfa3>Ru;}4x# z^7=^f%mQ@Kd{fUTx?QYRWEai?ROKirtP`~;@$=ZH-t%vP-Fcg2702e|I3!$hg>Z~a z)!zZ!!K0fFM}6E5)~|t0u0)f2!ypT( zfnz1cuJ=X1UXA2`2$<~|AQuijUX&A_TewCd;j1fLJR_X0;`y`nsa&?Cwu&Vr%Gi@+ z9&~Apro9mYqe?(GM9adbb<1LcOLkN))046{iakGh5jhlmuB}pK^LI2EFpMxjv_3!m z>OAPC*pf8t_%B>{85nCuFzn~O&ceTRi1qMo)DqPKTA2r&&2Fl;i_PdWN(;juiX#(C z))M_m88X)84p5d?qA+{w&;~Rq%ZyrYGvQFqevO*!e>Qswkg7~RdH2O?{P-O;1i&-7*m{Ipi)oWNHdx zSEDu!H#STPY;_A>GSzs{h5JVA&eszeXoZYB9mVNoOvI}xLm8~aTw>F$>umMCwv`GB zhfd>?+wir8DV7)*FVr^fMfO5Rg*X8%m z0)9=v*PJig*uX!p2K;p}*IqG-TkF=cwV(`${sps>3zfVG8B|qd{ zW20VRr`Qu6EI9>Xws-_q5(c+o`b1sDz0@TsQPDGS2Pf)kw6DCr@bD5+ z>Nk#!*NGzCs9pQWy|>PDIIAJs{=3LIRT#o76bn@BwzAJQ@2el`RifRGY%M%p{ci%D zOzOW9=>65#s;c*02D}MK&=q3~ZcN|~Zm+A`yxi^!zzU zH|P8@a%@0*l_3nwrT@|1SYe}kciccRdiAs8$F7o@p1B|`@wuo58tHK#=l$zr_Zg9(l zfpW@nx-dZYlY2Jx)B{vxhxi>=?1OMC?vF`7EhoiOFDn zBX0&(9!SQ%|+C>B52UvrUZG z?hWc%jMO-^^Foau)G@5JhDyaY_FP`z1*Wm5?zmd5m>Jj>j^mL6-NRo};Dr1W{yCYF z?-7iqjobBF%yC;K#*uNRlW%ystYBKiP%E|m$StZ8-8&m0oNu7fn5eDVPZ1N`%6#d_ zU9y#{%d1wa{VY%_=Y1Om1kjOtxzt`q2ZFy?FY6Pjy=b8Wr)agu<$;vP%ed3xVC(QI>G)gI+_xjPGIMcaTBI%J2k%{6dF;Mi0(yrL6T$yCRR04|$N^*b zH^IAKAKQNT0JK19qp8=gB;*@I2$D0|Td&PPMj%J-rRS7Tv|-XOY?)yWI{z4ruGTr4 z9Y_05lvzq=_4OfGbv6fL)#_zO?x(e$w99$DnDsMk&7JZV!+;n=w!FRtK5rzbHxP{h71N`CYZ_U5uo?(x;fpjUsi6qyAudN z-g&eEC`JMLm!`sOjMOhC-xpSOrR%22g_HpuKqDufE%<`-7Sx(Je#rV*33*l-&?nY- z5nDohVx~a#+F2s_fQDu-?$VQ`ni5Rwrr$Jj!>9*6>~&wNJUL23oAM_udJBs($_W2l z#Oyb_n2--OR@+Q&LU=wAC1)BxT8fK6vOGz8uQcO%vmUjM1!d^6nbvVpE<*dfE0lmN z1i5?TI8*0iqx++un)IlbGox*1gf@SF5OLPI={$pP?%pdxUcLd&0p$6b0oVa(FO2;M z_p_X~?F=1fZ(h(A;V38-UBO1lwl2+uk2#*kL*GZzF~5&MR(DRGA3Gr?64%pSLaWea zNr4P{pC;(WZUS3eg;p@z+TMB4Gi;({7^Hl&=HS~|zUM(KKDnnScS=H55W6RN z_@%OX!cJo~k7&~P`GU{#>PM%$1B0So>?N&I?cSoW#-1dUY!B@67B*3Z?!88byU5d7 zT<@Z+-`}RygrG#8DX~`{Ag8~E7W(#$wHGZVIvzou`lr94^WJH#_2-A(=zl*tf!ANg z)^Nd_RasT^60Eo`@Fy*% zjqUA~Ql@_s33byHbM6MBM)?oZo@>jf;m8=K-1xcH|9DXG-`79asJ;kq#u#tx}*C&)2aVPJwZU8$L$yjM%J%Vr|*DjyE@RTK)&%5}*>f6WJP ze^UtApv5;#i+cP89v2V;Na}h+leVqZS?ihM`sxX`Hrm9K;u0FoP%*F7rBh|B?XL#R?tNGe-h<1-`{~ z0JgP?+F^d<;vzn>R=BC4;e3~GE|A-g z;lULKJ6szfVDHt`0xeiACi{b`;nuF3JRir>`ARQ3vqx*_Lk`|x)4{@O(xpH&o19Jy zwF-LTvo50?bX?&D);w!?df*|{Ed$Ml7)3B!3kG^_F!vV>1hYR_b}1VQaY}Z(yb~0izr{fq@g3dbr>!@oY+XfK#|YK^{qmvMM5mIn7>mPR`E^1M6J z?6AmJ9WnTP6eqGg!2Dl%BS}jUFd&4Mrj80*%dr&t=-fFKa@Q51Q{zZwzg^AE8r6fw z@&73M%DAZ7?p*^xMOr{wK)R#_grPg68>AbgYXAeJyBq25jzQ^0x)~WtnxSUsv(e{y z|L-}!b3PouA)DEI-*fM^*SfB?u8T;4n~=rzbz=J@CHL>4cg1?nljJiWE=DZ>h?&Gi z!ip(frjn?at0u##tMTw2O}f~QU(eNgNAObw^PU5fLH4BPZL5(`0$W~92=Ez{vuA6@ z=6sbKD6#jh!bI(*ZTai^K2f*~MCs^!GrV1s{5AVuL0B?Gvc0edh&dI?`Y;MQz)cIU<9^?1|Y*DoWz9O>b?Hf7FI3 z$q%|FSm>h$Kmeva$e79`zybPtp3zsT8Q?S4{kPqokCQ7F1r$f-O>0+X>DSv= z@e}&M#$n#-5aa*_>g*UoY)l0$<-q|yFd8`Lq(R>r+0I`UEE#K+XtK7vN|XTfn;!}m zy?}+{5#xk+^D=XMRc8g!0Hf}x2REo*BKIXv{?6J|2`wgMm^Nk8sfI4peFItK`@Ih0 z=sxlH_H)Y_ZGjYWNK`uv()H!!xFDHuxKQeuTSX9wn-Hif(fZrwNqnqK7(uG>W~E2gzl|@ zl5N4>z7BKmFFF@H($G}5xsz(W?P~_w6ni-3P)z+}HhdR(;WVGWPU1P221`4<2^ub%BB;SN0Mt~YJ>MbjHDs-chBhH8m*$*jr|)T5_-dl^Ow zxlPd*ALEAJ;A1>Q`qC2`W~vV>4>OEZ0B@(m_|dOt#HT&UT@X4Nj(?fBp>KZG2c0*2 z_bBWi-usoRY}7^AyD$@}p8c8z-;mTOZRtmMXUl|rVHwD7!Y)&-Xd(G}gp1%GG)9}h zWXc&Sx|;PoA5A3pJVT<>`(0U;(An$7l{C@#0?Aps^zzQ#EbjMXc~N0Wfx2I7S8It{ ze=urXxS4kZ9oKjT+Yf!jXgK~j)?OxLjYuPsF*iut*=OKSPZGGQ{|C}}YBTn^7OCRH zNc_S6^TB$&iC6uGOOnNC?A&vVCr2!R;i&Ej`_|RHZH*>Zi}wdC9UB7i&AiqC;FX(if8 z!*e|@z2aBY_N~8^&o=*uQQXGxk7P(ZVf?l)KzjW^9Ho2RH^%yl->lSyx}*Z_Zo>zs zH|@2~G+o*oU)cbqxQ`CP61Y%`n8~Q)P6iV-yJ%Jvl^8$|i@-;*;f3zQsm#rRxDCG1 zqCo2~ZbGPvh$y|`r9IhXHfo(3fz{-JY2(zVLGZg>F<83UHHj($2e1{e*i+s9T6_yn zM-1-*Vx|NSY@5phZRrrduH)8St)n5d$6NUWuDYjbjUeg$g}HweZob@*KV*iva$hRW zxn)LTAWTvgJ|zzULq+xEtw+}M$v@)-ILj6ylI*jIdJAo~Sm5dqQV zIm*?(zpgPn~U>}Gg5LaTlU@^jLi6382_Onfw%&2-on0Ge`vCMzr63p7OpCRVZDlFFo3-QweC^;zen8l z2|hRn)S>?V!9PDTM8Zlgm0qD_W1bgvHN2dd@K`OTzS$~0su;ETwiA5nmyXf@KK_n2 zKvC)Vdul*KrlwWXy>QvISsiAR%t%||+_AV@>J!jZdc;Nx+SkHTbFCH3RKGdx$5@)X zKb3s0)yEikcQv{Gf6p#U4LKhRZ03Mo4ZvpR6z95!pVRQ}&c^w6@_^O}`_$O`!Oev@ zak9u|KW)>o~u^l`EVtulAkQ4u52MO63UEQFq!S7asV7Z(+$<0V~3G)GtQTa>?VyLubw-S%~1_yh1|4+Xm4gVQz6$X3P)@BqpFI z_Vt*2Gb-jve4xloxtLVh;O31dK+KcC>NA>uZ8Axo%N>?n7>)$9K?)Y6OrkWz69f8ddX z3f=9)?ehe;!g;M7E_2R7UvvFQ(_~%Rw&Y_cXMxENE3sV7jvJxFc0VgPDa>SKOhxKP z=K_3Ejfq4GC1ZU_!1Uj~b!*CBrc-J+zGjs@0#EsB}fp}yr&%6jTpO;u4rG?tK3 zI8g|dY42ro>f)t4Qp56ZCJ!;Db#XQsLFAABxv8qF&P@mcmKpRijrT11U4K~Iqhs!;n6s$4Sw-CS$MQGjj;>UWF8 z2d1KT*STrEIrWHi-Zxo`@=I1dGR=hwIQrTPYTnAln@|)2HLGg%gB; zk|7GR_3<-V&-h!~1-o#9;$@pHBDBq39yE)3QR22Ulr~@WsQt=9BGEG1Tkoau<(@7} z`%T89X{5O)i%mpvWW8b@4^$Gc?YYd$(FiYo7=~9^z=WN$qU?^G0TIqHdQeG%NuKHZ z9F^C#bqA|A13oP`fz;LAO83vF89e0rZ4yRhBi_P&(($%jOiwD}7b-ky-_`n~7JT$` z?_iU57L<#q`46N`@fXt09(nx(>yt1<0wB)07Gj1tp4NP6GU4r4V;If{czSr?7gyhwFYBXj2MU$78X74P{Y)Ick79$v9}D4)8o-gAHU-!=2P>`n|tpQesY@IAq(8*ndtLs>-^B#7H;q zz$8^djj}OaM5GTiVsHb$3crjRN9{@+$xrg@5Q=82VPd>EIcu-{$((~XM&s7V0`C=t zUNq5$(-$G_<*J$JaU1C{&Er>XL#}z73WM0vsXD3ks(xr#f zw2ODiggcOjM246Z9J5n|F(Y2WoQ$J zMV?goPa=>^fxZY3RwG>{roKW~Hko|0xe@?imc+4|P?Vom<|*hk+Bt1B9mJCeJ}Rik zJmNq+1$2x;mSVN7I!AU6ZJc$julSEVu$zWn-MtfpApmx|_1Y;pw&vLQC`7Jkp_GHX z01%gkw0OJ?Svn#C#saB&1%-5ZN_m`AdtjIOFD?Bv)hxd1cT9Ar(K@HakePE|xz2xi zF_Rb0;zqDw z-F{eLH86a|{e5`l2eo&al+f7RL5%^it8hG;VI<iO}tdPmX2L!*s3&GeF#73%2v^O@%0{qE+db$N2e& zCV>v1jTYrd@F7f2N|N;y0T+83%JDY#t8Ik-&J905;@HBPwej_h3=Dhm{XeoJYGW;F zyc!!%I+GZd|EO3z{Tvg>zVxr+$keW##*g70$1h1o!|Y5HYf=!#uJuf)&xa-w3t`=y zr01I`7D>w zESWmS8|lyxw~e? ztk)DjD&}@t2+LRZB9F+P*?@RK$^@<7*d5O{7f#$Hp7dVf3*vYWox?3KinDl9TdRaa z7la{VaiJBLA?Ae}D1ppdM~DXq*FCQ7aGr?1IL1Wjua_N?h5Ig-Y8RUsTkT@#LW`)t z-qHs4R$oxXa{JaV@|ctZ;my~GXKr1qs; zZ2N}P{43XZ2iyw^0w<*!7_~7OQn&Hn#?te-NJx)uTR$}k-2bYQDKU7uxcCSZzdtb1K$=EYI&w3u z_X!E<&oh6>KJ_)JE7rSwT|8}HEd06E-eX!s(7O}ylcbW9C9mP-xgQtv5mt6M#k?yz zxO`N7?&xx0&J2p>M#L@|T3}!VKxc8=etMS!wevVQQYp3IDp~Y6vICOyE93-!{JWVl z4RQ#%f&A6yM-F-O0QFs&*_=M7Ma`)@$cZkXAv&D6O!(bJ2uKcT@5A#t`|@7eO`jDS z37F(($O@92;k0Z~PrMME9}l5(w4yt^(2CoL7MJDe-VbA79_UYLSC<8!hIx#F2qflz zUIf+rBNGDua=3phvpeEn-^0e{8buyej4&Xa9r=n6z?OrdjM**6~X)0kRh(-Wu{^_6x6SOTJQnn6Z{-r@AekXSFOEu~_BBQrWhffPz!sf08+AKJ?bstx5)f3mQ z%b+eTF#TAiMt9Mf${u8zv6}1r*{8Jc^1k`f$rjQsPuWnKeFPAODEsehLT{NIInR|& z7`tufzMq9BkG@kchW3A0DtkPammTFmZUrBfbG-64-RznAO(DmkINGmkAE09RRz${b zLN@$Gk%HeFnbu`p|9w~Aa#NB;UEkuRddIyY(0DP=jIR9y!}s_9d3IhqG06N_xYP*l zwfkenjiu>mr35a)1BxKaxho^)~-J8(2LuZ+(c(huWld-V`@r#dk`mZZ;sD) z&LquPjBL#Q5saxFFl!QiG>Vl16cv9;gzAsT@#r`?jrg#j6j-8(O%k2m%iw*}eEP*dx9ty(rrRfAT6*s@^rrb*jEHA+0dI3@qDaf(}i{_Gwy z=%|{oUw1pJ^3SQT2n>iH+4zf9$TC$PS8^57y8r(g$*Goj7!I?o5mlcwCuxGmERApXpz^H~cc(GA#M zE_gWS$`Sw>Br=7*Hql{T(>eVV$*|j|+r~5u$jlaul?t(tQGagOB-lsxaTjNdM#9s9 z+IdT$6u;FQ46=IW%(zAl`Fv+1;~VmRI6h$NEB;?<^v~NKNC9yV*74Vo1G-i3GLBN zu<+0%iPzzXAbH-292-jU{EqL&iJnp^T#*`eQr%F&h?RS5DBY9 zLd&PSauBlyUEix|2cO<;1&cYecbS6BszQXXyg(i=;;w^j3Gsb`=4WuG z(pPU%Y!gWa!0)SjF@cYX16o6YsyN|*4nmO~UVxxz>P%gHpYzOf_1eN@(p>HXoU8aE zsA9M3wiGPyZOc_m zBHNf6(&|1qdE5G!YmXKeZoCO~Id@=tzTs)NrCg$zGjLb1U)}qA(c>Wpeots)=O^=N zXWnr~?2j|yJfcGP{Ff3E{Ywc2S%7KMBJ*rK5mM@sf}^i|x*|dFGR_Ah7l zYY=G*oQCbLEY>9kGs$#UW)@*v%UzZS!B@f{!s31_omj@ADYsevP=7=&H@N`R3NdMq zQCMs^AGvIscyXVw_@>p#JyE=WjQyd_H{L96?&^VX?@_+(=YI?ht511S!&y?3}XK9c;SicrIWIx?llMJU#7UCO2zjL^! zxc6uARCM5gSg^g{=<-zOPViDulO6VUEAQu{_Wz6fUYY1UO{Sn;=h%oo9pisH5 z*&c?_kmiXroO0vjyVssZ%O*H$IpQABcmC^AmAqRsDjDrlq1eFtA~B;2vWNaB4h4h& z)b+2MTdACNIGdRRU=d`=E^L%A{M)*4XY9?uvrr*)hu@Two1y~+*^v%MPR^E2hCUuF zOC*xTvDu@acP<{Ewk2IWK_nURH8)GPJNJvDIFl7jOQvH<-WJRsGtOU^#lY#`@-I3! zuQ#R?cI(_W6ldZUbs8N6oD+2;!e_>N3RkGGE>aoUDOMxh#rl5P=ZDQ~fYOAO#&fp4 zybb%b6>kg|8QPl3EUEL^6z`sO2~WV+rTUsQQ_krpGT%Zi)asNx!d&zHWa}qC<$w2< z;8e4ySBo8eJ8`o%iYLP#1pNj?FC_Ut?Jamvy#*uU!rm?Mp8O*+j1mrD0?^7t>!G8D zXH;E$NEf30_m_0#cq4PGp@LXhX2?lGlKcG~UFDkk?i%k91-SD?8;-hi4SqIGi1MB% z{yuB)fRyG5d$$XA9oMTD6w%w>G6UtiRZLq2FqL0Twd}>bgY1Dqdv{p+VE|SGK0dP4 zI>K7fF(GC2Iw|$J#Eo8X&|{xg1rl`%t8I!*xIw=X9w4D#`VVeL2RZoCP$yQ{2|JEh zzPW$jUg{#2$dK9WlRz_-TJJA56DAAZnM*=~4{N~=W0!}5`qmq4L z2?{3N&~llp0z zG)2VF-OW8XrrefpA1Lhiza~(`+)Q*U_kT0E=!6ckn7y5Db&9n@pdja&9>1+S{a7?5 zrpaqTGC_t11Qd@SIlH4OcCS9=0q>Nnmw%(PO8H&L`m1lAga|2_T0PMNgJP5YF8{@p zadQ5_l!K0>659R1V=adfW~o)xF#O|Mi& zk|FX7GoKDieLHT)t1VhsQ(u2k+DfF5&LeA`s%|YWx3~FhbJ(Pr%ZRmKhvhIR1jQHH3_V>SGN zqu&t&35@A0Xeu;-TC^s1BHiDH20m7geeJ`AUF*%yy&n$)Qwb5b z?9#Cl#$7_0E^dPk&%1m2L#vQwf`Jo$(a}W#0cFEeHJ8(Nb&m-?BNKA2eETKt0E$1l z|3D@Iw0iM}Au$Cgf&yY#S0wd#ZGUW?M_Q=pd>$@u>b$gW$lcIgz+7HQ_a}M0x`)L= zK3|8=YCYp{G(UI)A9`N#YhB1E;tbXcmv88Jv*Uw~>YjgQTfymEBH_ZQnvvjfJ6jzs z$mQrMXZIyQGe^a0^?6PUD5`d7NbZBdRPcl^AvuxQ^leP%78kUOnlF%n zGI~kEt#F`Av(AWqOJpQj*`+U={WjN#3vpJaTODmn3rNBMm;5KY8#n55?<0c7o%rW= z-NR}TL-%reqn|MEOq9x;(Uq4r>!m@Wc%VT3L|(>gv5v^DibQB#E|?88Z9IRwAaGEb zUk<{g_^z#4mW^Bg^5xT@!e52DIPUs+mX4!3b(m@DJB6TzZsj~{5yzKQPl9aG#F*ZT zysJeqrH%4$d#Vn1A05Up$D^X@@db@uzI7UHMl2$G2m6}{#g?iHRElUuHSaqsSc=^y zCZ+rC*qD6V2X|empeUxzG)D_sarrC+4`O*Nk7l99?NT`w!R-8N&N`s1_RlM%cNKZghwjnJD3 zX>Rx-C>9$_Y_Kc z9b(uagGe!vuUYWbbSV*AHk`>P`dK<72{SVhF?`_bdCT&7AFNfCda>HA94%_KCI|v0 zygNyU&&BA!0;Wsgn@0Y$hB7Pdnp)Dj_-%LR%}|_<19?7%(-a!6uXo-yLBiF9!KoRt z1}8<~C79jLT?2nYO;=(zJ8W=cU22z9GH341K|9Pn)z`Wc#U!P_6rHV0KPr{5*70Sy zIeYis%-{+3ZEB(tX**7D&-xGhGp>~N+A{Lxu=gMewn$-fOx}sqN{flD7FM+7X2-1) zg&#cH23F=LKOV_7P&9w&48(C+9jLIM@Sd=oF8O>s8>64A$H?n-`+>M@v~gJ#`6O4@oVz+#GrUyzJRI{@49`SasHY3pJy7LJfq_NfX$Lb9(?QmDhA^4e+DC>wzE5&*t`>1C`mT0=?l~XQ zMI(r)=b_?lIjc^+Q1!r6-}iezW_cuN%q7Ouo6cV0k;f;qT+)l^u0WmG6ZBGT{H63h zE?2_4G?jCp2c>~##9YvNxxPe+vtI|!%50T5APb-88Xig7Ewix}beTuJVA{rVruQJK zmW=YXFqJQoy5+{XJ(Ob4g_ckAW^zC*Ma{Q#D4->u%fi<)z`FN`rytzBg`*nzd0k# zMP1k*Iy;G|!PKu^4t3}cH7wEK^$*N$xC2!9)g z6!@+UpmuXFDzqA=n+&$D77=hdFO47h{%8}{m>UphVW@wTXVoy;_q2?SnYQ#)e&sMx zP6l2UxfQ8|4vo|pZso|q8+SW1iHC`Bu*vThT2*nU6if!o#`x_9@DE`Q_EHaSXRNoG z7Fsp95t}OL=HQgDwy&+6Wk1HEX_qr9-b`Wd@eowWsp-bvITMBHrmVM{q?lPOmZbO3 zQh+(0t`8GNp(2(a*i9Ot3Z`BKc{(n5QI#2O*1(tW@{kpwvCS^&9{g7yPrczZ^CS&` z?uH)2B2Z}xs{>1gGq)ngV#OuM)O#xAC%d0`@17Ms6NGygr5)jEm6=68rzg^(!?8*`$4hT=peUPFD5-DTs*3_ptwcey@?(?a6 zq$ODuegx~n)bXhoVpKj7r-CgAyH|Yw`B67xf!31Rw1&3`c71w?LoTbBD69DWGx_5! zrG@pa!N&Efg*^9AFE~qxp2=q&gf5I6o7ipVyRA>|n1hmW!0!126?*waldrXs9yLX` zoB?BUEqIx7^yfI}%166DqZB2XI-Fz=v%LY9-=FPwwpH7KuMTR1POc#E^)lX-O7UYT zx@3&Utj{F-esJcf$n)C_4vsGc)(cD8S9Pn@^FKdsY%2Xs`oPV|NW#vl9-78lc${?p zWuc*RKKbQ({Ntw?(xt`Zb4zlZBMZQUv0#q)ZgGfzO8>q}il>zax@jYOL<%tW7g)V( zlcQ@hOKxFIP4}KNzgBF+TO}mO0Aqv@`+Km~B))4hiH3YU(2X#M`|U>}=ef<*^LUv+ zQvRg!&|i~>pwC`#vq#M@Ty0B&XBL%b?xQQdU6WzO2Sg#cNPyBliz5yndNi53P%yvk zw@hqRyFd8}`{}|2+W-xq4@*S(vTvnfi1-Pd#Z-RNLFA>e>!GK*=M=O8Z0<%C5ym4) zc(j1cbt6ut9^$$w+3Z4F%lC=SOW0riZ7>nSH%jCJqNL(^Q)yH9(+cEK2Xlp>~?C27Wq9j$dxCzq~}Q3}&Ys$&T!q zT|BN6?nAabCcl-lGgEw}mS>4T%+PwNpDRImW9RY`@Dyh4dbQniL)ccj%A_(v!o6c& z{j!2F9fhNeZ=g#{d@95AYkw>F@zy&)T7JnmWP9O#Vj(g%=I~w5eBrb8 zE?&gNV+>Q*$7~b0fvu^ly0U}=A$p^5yXgHCdQqVe^0Mj9&~y&S#H~PRRaW5Fo9ZmO zcK&*)3#QMrNCvLI*XAB<_u_fSu&Fx`t=P*k#ytFL6btymLnh zqc9QsSLKDP@{*XIB%W{q`B&ujOy&hNleca-?iMC&lU|b*SSm*z+3p#aAKHYh`3UZ8 z`lbL|(tC_zeDL+_s=3FMc$$dRXsjG#QN(<3X>K-~WSNlfp2o)mxcZr$vfO27k%V}K zYytwwQ+OT3lJUtU6MY{d|E+<4GNDS8;6%7KZ^bjdjz(Td^wFt?cr{}@e{|HhfrDkW zyQBoS4cLyDm`r|6q}aqCj@NkkKL;)_dQz4=!`Xgod&-u$MfuEdl=`+ML66EALS=!r ztQuWO(LQ3^v0rin**_lUjvk2-c2fWzoKkX~`H9wvpi#BPwnL3TmHe3qGAUn#1^{7VIm|T^lqJP|k#4R(y0Ig@K0$q^Q;0Z2Isspe zZJ|>OZ#r^1A+e?tvuS=uwL)_z%VMuqAVOz>bvXMV#cCplTYF06c8~?pSiL!T@IYE6 zK@7?>_PqUddEUscb@DZe%I~lR{hAUmoJIES8=H^hr?LWea=osbna_Xp0Kru4@t=KU zMqwZODT(aHn`&u06Z=~@C>diRCRxT^l->i1sW`8&M>nsV+A z{F(L=7ZXlyL8n8;hwuGW9utg8O37iPt!Gum{Yxyl@+f@=DdhS5ruwIEc}M{TW&W7XK? zwvV}-4JSG0-C!hP6Gd0=$2A2F?0?|g6wb^-roKC zsZp)5Md3}CoZzh?d%<&8jupOX zLY^n0$5S%}zTc}{`0#J%ee`g4vuyX}9^QIVNRk**l&9h20ntTl;(%46vc=5f@D zB5Ul&q|kMEHi*X=-_dA7eK;2N1#2!lf@Ve6GZ{;%+^L%V)l-a%6W-3Y=Xi!Cbyx<$ zYL3~MVLc`O34`GAkhw+D9t2NU^q5OzBe*q>`|z;ZaawBz<034rh4*D}<7;0jMf?875>jX@Fe8Ygnf+w3Lh%Ir8pC(4)9XDLnl-yvqPsK0KwLRZRr z#W+xI>(=x$PFg6hX^*9B9{*=QY*Rw6P#!ILo_%J}U?RhTvy7P2rWqOsMD}J-4XMb$ zS)^Nj+lJ`k%9_eD;zc;Y0M@{jJ-=s~R?u)zqv|Xiz zRl|C$G&nJ`+|V(5R zU`FdAx14`?heUtUq&tVPSe)K6x@>}Z0&T@E!Kr!{Y#-@l7-baQ8Y^|I1!dT=H z9*!rkpj_n<9r~wF!Qy_4%P+3XYMo%I$7{$BizB-v6^Z`)ufJ%X^#q1Pw|}{u6E!VS zZT4@;XnhO2fYoS$y~C3SnT8ekK=)hpZcizjm<{0Qw*ViJV-WgVJFjU}kj_Ybnyl$^ zUrrQ_FRivzG(i+LSb?h-{}X_m1WDmrVfl@q{xt$xLpmj?8s|`0kbLIxb_x^2=guW~ zip%voV`;qW-9T@&6%G?ZRJoB|am8MiAh%3&e{YQIEv$@LG|J5s=Zp-ZFMjns$HSP0 zUqO_3gzcm&o6oi9uy|rhZhhJ#>Mu_0u|U zpQc4#1UIY2r62EN>7|8flLp~naB6v5DOI3V7t$49X_SR@^2<-s?5vjS1P`zz)orDy z??v$eVPj+47IOH6RJ+6v+qG}!8REy%5Us;$Yps@4LgjQ@xu?Q4kf)P1ND^9wW6efk)?bxG#NNqSi(lI$_d1u>Yo7%^xVwhR53Zb8i>Z`2= zo~thClx^Ae$GRwg>X3$vIL5|JNhoDIjhA4^DKH<64xR2u`ejO+U7iy0yuWp>1GI=wLL?KT7-&)_`a$%*VQjvb1B`4Dqs-l?;rE7QTvUO$LYQPI{@-ir-sL>|RF zY7P9_(<~u$HmRUXZbQDC>-?6wx8&WrErDx`~1nBEc|2 zsEh5o5!+7w)jdV0?6LGZwuK|zqowzY89^3n`JdB znY0@n#pdAld4kAqFHuZ>@4QTXZExK$xDSo;ASIX&(%km3m1Iq&dA<6*N{++^l`0s& z@vW7+*tUX3813x#yWS>_=iexoNk!?U+4p{f8$K6%YideoP7<7I-DHKe6KFb)=EVjf zAr4pk3#)?!eI7Qr<#-{BaHbqWHxd1fB?hn@{;x?#pWcS)7a#aTU4FYC$bN=c2YOL> zFu>b*#h0?9Dj_4M=lKHLH!NRnb)#zkjO$KG2zDV7+HZ4u;Z5hcpXon;|NdB&z2-G< z9(i}c*adUTnI?N`YVWT>-0*yd`A{!485QtxELJS0%{Uo} z(4v&RNu9R4(n+5F0h`zxR5zP_j@xEF3Y&`V&m=_2j=ep<4mK~D&jyE9O)tu^(*n%j zi)Wbi-9L)vQ0zI)%f-MQo3`h3b}4Qy3=pQ%lyZ&Yz)w{T+R1tQyb+}*`ben@opOO*34lH-kg z1I91HaodJ>B%I>^u04@pJM3kb(Jj48Ggna={+}gk#R>Dk0n6vDGjjs7z+o!wmc2`RbUmKm)u`&HWL;Tq`HH6r|Hs_CiM zTtrG;Px?(-ufz8Nu*-If%-T+6&X>p#e_+1YVyy&821`BTU&|P-^{=Ny(uu?X&!hTf7||UnCDiro25} zyJN)Sfc|d*Izp&>MD`^I;T%jZ zf*Em?8(cA&Is|eMqo;$^jUvuO`YiW@KhA&z}0!RA}|_ zja(Q(51teXQA+o-fB=zsw~Jbp1)gCjw!ol!m8qiZ3$l(|T-DXgaB=(ArpR=2Hm8wp z$rJj((;=^-Z(3dG)@S|k#7N3xE7u*H60sM1`xd7amcq?n(1>d(QOCyXU4?K}`x@{9 zdMi9?Pv!I%$tc5tY*hE5QxVXKpLEoL3&SL%AuS29SZ@T=~Iz%mU* zL#Q8J+_xDI2mgghw7Z(9ko7M{Z6wXJab}`F1(TA%pWom3z{_M> zyiV54ynbK*z7)w2pmmWblQQh1h{dX5$Fl=D9y#bH9bJM8pM z-A+wXHN-*YD6;Kc;GEI9@j8Vl(Qy#BHDAULTqeT&>^C$q`w04W@xN%gkkFrVf}g?$ zTiUajIA*b-aZJPCr6kO@CUzF`b=-UXKIzod%pt=y4K;!qDCq~yY%?cI1jh>T?fOEF zW%A67G3c$|D6tJ?f7_SK{*{UXTr35);V)In%q_o-O$BI$z)=*n!D$t6JK(Fh^}uH0 zE#IbHzxJi~dP2>U#WbSVkwPr^HX6}~HR%N7Zi}w#(-`iW&KS8hYi_>bmZ|f&XLuE5 zs^Q#lsOlD=6!90?6vF?nsvlk)iND_6@b+M2bfkXi37SX>*^qgL5*uwdVcpc$G=Z+f zKVY-+9#gE60*__jpfXeXC-jkSM;U5{(Hw^~(;R5@NfeLIG^m40C270KJdE9-VdA$f zdslN?6f(j5{2UZ1$H&O@{*(QZ;rTF zIZ^M~+iA~iNmJ`FgirmhnZMR~xtg$9|78C0+^z!5k4C>!@$m9mQd(LZStmAv`Z)PO zzQaq_ZEU*%&U^cFAuQDwzBvB>0ZTtJ1h?5B| zOA!Xg5z_9ni|J6e&P^5=zG$lz*nTabc6AvzV7-`ixFSmoJQeqfMKHP$A}+QBCDDp! zP(0|al=oinlO4

    |Gfp?8S{j!yB4 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

      or>2tO#r*M?9haOKOX+$??nkx1_Z$81 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 diff --git a/docker/Dockerfile b/docker/Dockerfile deleted file mode 100644 index f41132f..0000000 --- a/docker/Dockerfile +++ /dev/null @@ -1,36 +0,0 @@ -FROM ubuntu:18.04 - -ENV DEBIAN_FRONTEND="noninteractive" - -# install depdencies -RUN apt-get update && apt-get install -y \ - python-crypto \ - python-dpkt \ - python-ipy \ - python-pypcap \ - python-pip \ - python-geoip2 \ - wget \ - git - -# Download the latest version of the code from GitHub -RUN git -C /opt clone https://github.com/USArmyResearchLab/Dshell.git - -# download and untar GeoIP files -WORKDIR /opt/Dshell/share/GeoIP/ -RUN wget https://geolite.maxmind.com/download/geoip/database/GeoLite2-Country.tar.gz \ - && wget https://geolite.maxmind.com/download/geoip/database/GeoLite2-ASN.tar.gz \ - && tar -zxf GeoLite2-Country.tar.gz \ - && tar -zxf GeoLite2-ASN.tar.gz \ - && ln -s GeoLite2-Country*/GeoLite2-Country.mmdb . \ - && ln -s GeoLite2-ASN*/GeoLite2-ASN.mmdb . \ - && rm -rf /var/lib/apt/lists/* - -# make Dshell -WORKDIR /opt/Dshell/ -RUN make - -# Used to mount pcap from a host OS directory -VOLUME ["/mnt/pcap"] - -ENTRYPOINT ["/opt/Dshell/dshell"] diff --git a/docker/README.md b/docker/README.md deleted file mode 100644 index 5cf8cd6..0000000 --- a/docker/README.md +++ /dev/null @@ -1,16 +0,0 @@ -## Building a Dshell Docker image - -Step 1: Build a Docker image that has Dshell installed and configured -```bash -sudo docker build -t dshell . -``` - -Step 2: Run the container with a native host directory (/home/user/pcap/) mounted in /mnt/pcap -```bash -sudo docker run -v /home/user/pcap:/mnt/pcap -it dshell -``` - -Step 3: Use Dshell to analyze network traffic -```bash -decode -d netflow /mnt/pcap/*.pcap -``` diff --git a/dshell/__init__.py b/dshell/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/dshell/core.py b/dshell/core.py new file mode 100644 index 0000000..bc78a9e --- /dev/null +++ b/dshell/core.py @@ -0,0 +1,1448 @@ +""" +The core Dshell library + +This library contains the base level plugins that all others will inherit. + +PacketPlugin contains attributes and functions for plugins that work with +individual packets. + +ConnectionPlugin inherits from PacketPlugin and includes additional functions +for handling reassembled connections. + +It also contains class definitions used by the plugins, including definitions +for Blob, Connection, and Packet. + +""" + +# standard Python imports +import datetime +import inspect +import ipaddress +import logging +import os +#import pprint +import struct +from collections import defaultdict +from multiprocessing import Value + +# Dshell imports +from dshell.output.output import Output +from dshell.dshellgeoip import DshellGeoIP, DshellFailedGeoIP + +# third-party imports +import pcapy +from pypacker.layer12 import can, ethernet, ieee80211, linuxcc, ppp, pppoe, radiotap +from pypacker.layer3 import ip, ip6, icmp, icmp6 +from pypacker.layer4 import tcp, udp + +logging.basicConfig(format="%(levelname)s (%(name)s) - %(message)s") +logger = logging.getLogger("dshell.core") + +__version__ = "1.1" + +class SequenceNumberError(Exception): + """ + Raised when reassembling connections and data is missing or overlapping. + See Blob.reassemble function + """ + pass + +class DataError(Exception): + """ + Raised when any data being handled just isn't right. + For example, invalid headers in httpplugin.py + """ + pass + + +# Create GeoIP refrence object +try: + geoip = DshellGeoIP(logger=logging.getLogger("dshellgeoip.py")) +except FileNotFoundError: + logger.error("Could not find GeoIP data files! Country and ASN lookups will not be possible. Check README for instructions on where to find and install necessary data files.") + geoip = DshellFailedGeoIP() + + +def print_handler_exception(e, plugin, handler): + """ + A convenience function to display an error message when a handler raises + an exception. + + If using --debug, it will print a full traceback. + + Args: + e: the exception object + plugin: the plugin object + handler: name of the handler function + """ + etype = e.__class__.__name__ + if logger.isEnabledFor(logging.DEBUG): + logger.error("The {!s} for the {!r} plugin raised an exception and failed! ({}: {!s})".format(handler, plugin.name, etype, e)) + logger.exception(e) + else: + logger.error("The {!s} for the {!r} plugin raised an exception and failed! ({}: {!s}) Use --debug for more details.".format(handler, plugin.name, etype, e)) + + +class PacketPlugin(object): + """ + Base level class that plugins will inherit. + + This plugin handles individual packets. To handle reconstructed + connections, use the ConnectionPlugin. + + Attributes: + name: the name of the plugin + description: short description of the plugin (used with decode -l) + longdescription: verbose description of the plugin (used with -h) + bpf: default BPF to apply to traffic entering plugin + compiled_bpf: a compiled BPF for pcapy, usually created in bin/decode + vlan_bpf: boolean that tells whether BPF should be compiled with + VLAN support + author: preferably, the initials of the plugin's author + seen_packet_count: number of packets this plugin has seen + handled_packet_count: number of packets this plugin has passed + through a handler function + seen_conn_count: number of connections this plugin has seen + handled_conn_count: number of connections this plugin has passed + through a handler function + out: output module instance + raw_decoder: pypacker module to use for unpacking packet + link_layer_type: numeric label for link layer + striplayers: number of layers to automatically strip before handling + (such as PPPoE, IP-over-IP, etc.) + defrag_ip: rebuild fragmented IP packets (default: True) + """ + + IP_PROTOCOL_MAP = dict((v, k[9:]) for k, v in ip.__dict__.items() if type(v) == int and k.startswith('IP_PROTO_') and k != 'IP_PROTO_HOPOPTS') + + def __init__(self, **kwargs): + self.name = kwargs.get('name', __name__) + self.description = kwargs.get('description', '') + self.longdescription = kwargs.get('longdescription', self.description) + self.bpf = kwargs.get('bpf', '') + self.compiled_bpf = kwargs.get('compiled_bpf', None) + self.vlan_bpf = kwargs.get("vlan_bpf", True) + self.author = kwargs.get('author', '') + # define overall counts as multiprocessing Values for --parallel + self.seen_packet_count = Value('i', 0) + self.handled_packet_count = Value('i', 0) + self.seen_conn_count = Value('i', 0) + self.handled_conn_count = Value('i', 0) + # dict of options specific to this plugin in format + # 'optname':{configdict} translates to --pluginname_optname + self.optiondict = kwargs.get('optiondict', {}) + + # queues used by decode.py + # if a handler decides a packet is worth keeping, it is placed in a + # queue and later grabbed by decode.py to pass to subplugins + self.raw_packet_queue = [] + self.packet_queue = [] + + # self.out holds the output plugin instance + # can be overwritten in decode.py by user selection + self.out = kwargs.get('output', Output(label=__name__)) + + # capture options + # these can be updated with set_link_layer_type function + self.raw_decoder = ethernet.Ethernet # assumed link-layer type + self.link_layer_type = 1 # assume Ethernet + # strip extra layers before IP/IPv6? (such as PPPoE, IP-over-IP, etc..) + self.striplayers = 0 + # rebuild fragmented IP packets + self.defrag_ip = True + + # holder for the pcap file being processing + self.current_pcap_file = None + + # get the list of functions for this plugin + # this is used in decode.py + self.members = tuple([x[0] for x in inspect.getmembers(self, inspect.ismethod)]) + + # a holder for IP packet fragments when attempting to reassemble them + self.packet_fragments = defaultdict(dict) + + def write(self, *args, **kwargs): + """ + Sends information to the output formatter, after adding some + additional fields. + """ + if 'plugin' not in kwargs: + kwargs['plugin'] = self.name + if 'pcapfile' not in kwargs: + kwargs['pcapfile'] = self.current_pcap_file + self.out.write(*args, **kwargs) + + def log(self, msg, level=logging.INFO): + ''' + logs msg argument at specified level + (default of INFO is for -v/--verbose output) + + Arguments: + msg: text string to log + level: logging level (default: logging.INFO) + ''' + self.out.log(msg, level=level) + + def debug(self, msg): + '''logs msg argument at debug level''' + self.log(msg, level=logging.DEBUG) + + def warn(self, msg): + '''logs msg argument at warning level''' + self.log(msg, level=logging.WARN) + + def error(self, msg): + '''logs msg argument at error level''' + self.log(msg, level=logging.ERROR) + + def __str__(self): + return "<{}: {}>".format("Plugin", self.name) + + def __repr__(self): + return '<{}: {}/{}/{}>'.format("Plugin", self.name, self.bpf, + ','.join([('%s=%s' % (x, str(self.__dict__.get(x)))) for x in self.optiondict])) + + def set_link_layer_type(self, datalink): + """ + Attempts to set the raw_decoder attribute based on the capture file's + datalink type, which is fetched by pcapy when used in decode.py. It + takes one argument: the numeric value of the link layer. + + http://www.tcpdump.org/linktypes.html + """ + # NOTE: Not all of these have been tested + # TODO add some more of these + self.link_layer_type = datalink + if datalink == 1: + self.raw_decoder = ethernet.Ethernet + elif datalink == 9: + self.raw_decoder = ppp.PPP + elif datalink == 51: + self.raw_decoder = pppoe.PPPoE + elif datalink == 105: + self.raw_decoder = ieee80211.IEEE80211 + elif datalink == 113: + self.raw_decoder = linuxcc.LinuxCC + elif datalink == 127: + self.raw_decoder = radiotap.Radiotap + elif datalink == 204: + self.raw_decoder = ppp.PPP + elif datalink == 227: + self.raw_decoder = can.CAN + elif datalink == 228: + self.raw_decoder = ip.IP + elif datalink == 229: + self.raw_decoder = ip6.IP6 + else: + # by default, assume Ethernet and hope for the best + self.link_layer_type = 1 + self.raw_decoder = ethernet.Ethernet + self.debug("Datalink input: {!s}. Setting raw_decoder to {!r}, link_layer_type to {!s}".format(datalink, self.raw_decoder, self.link_layer_type)) + + def recompile_bpf(self): + "Compile the BPF stored in the .bpf attribute" + # This function is normally only called by the bin/decode.py script, + # but can also be called by plugins that need to dynamically update + # their filter. + if not self.bpf: + logger.debug("Cannot compile BPF: .bpf attribute not set for plugin {!r}.".format(self.name)) + self.compiled_bpf = None + return + + # Add VLAN wrapper, if necessary + if self.vlan_bpf: + bpf = "({0}) or (vlan and {0})".format(self.bpf) + else: + bpf = self.bpf + self.debug("Compiling BPF as {!r}".format(bpf)) + + # Compile BPF and handle any expected errors + try: + self.compiled_bpf = pcapy.compile( + self.link_layer_type, 65536, bpf, True, 0xffffffff + ) + except pcapy.PcapError as e: + if str(e).startswith("no VLAN support for data link type"): + logger.error("Cannot use VLAN filters for {!r} plugin. Recommend running with --no-vlan argument.".format(self.name)) + elif str(e) == "syntax error": + logger.error("Fatal error when compiling BPF: {!r}".format(bpf)) + sys.exit(1) + else: + raise e + + def ipdefrag(self, pkt): + "IP fragment reassembly" + if isinstance(pkt, ip.IP): # IPv4 + f = self.packet_fragments[(pkt.src, pkt.dst, pkt.id)] + f[pkt.offset] = pkt + + if not pkt.flags & 0x1: + data = b'' + for key in sorted(f.keys()): + data += f[key].body_bytes + del self.packet_fragments[(pkt.src, pkt.dst, pkt.id)] + newpkt = ip.IP(pkt.header_bytes + data) + newpkt.bin(update_auto_fields=True) # refresh checksum + return newpkt + + elif isinstance(pkt, ip6.IP6): # IPv6 + # TODO handle IPv6 offsets https://en.wikipedia.org/wiki/IPv6_packet#Fragment + return pkt + + def handle_plugin_options(self): + """ + A placeholder. + + This function is called immediately after plugin args are processed + and set in decode.py. A plugin can overwrite this function to perform + actions based on the arg values as soon as they are set, before + decoder.py does any further processing (e.g. updating a BPF based on + provided arguments before handling --ebpf and --bpf flags). + """ + pass + + def _premodule(self): + """ + _premodule is called before capture starts or files are read. It will + attempt to call the child plugin's premodule function. + """ + self.premodule() + self.out.setup() +# self.debug('{}'.format(pprint.pformat(self.__dict__))) + self.debug(str(self.__dict__)) + + def premodule(self): + """ + A placeholder. + + A plugin can overwrite this function to perform an action before + capture starts or files are read. + """ + pass + + def _postmodule(self): + """ + _postmodule is called when capture ends. It will attempt to call the + child plugin's postmodule function. It will also print stats if in + debug mode. + """ + self.postmodule() + self.out.close() + self.log("{} seen packets, {} handled packets, {} seen connections, {} handled connections".format(self.seen_packet_count.value, self.handled_packet_count.value, self.seen_conn_count.value, self.handled_conn_count.value)) + + def postmodule(self): + """ + A placeholder. + + A plugin can overwrite this function to perform an action after + capture ends or all files are processed. + """ + pass + + def _prefile(self, infile=None): + """ + _prefile is called just before an individual file is processed. + Stores the current pcap file string and calls the child plugin's + prefile function. + """ + self.current_pcap_file = infile + self.prefile(infile) + self.log('working on file "{}"'.format(infile)) + + def prefile(self, infile=None): + """ + A placeholder. + + A plugin will be able to overwrite this function to perform an action + before an individual file is processed. + + Arguments: + infile: filepath or interface that will be processed + """ + pass + + def _postfile(self): + """ + _postfile is called just after an individual file is processed. + It may expand some day, but for now it just calls a child's postfile + function. + """ + self.postfile() + + def postfile(self): + """ + A placeholder. + + A plugin will be able to overwrite this function to perform an action + after an individual file is processed. + """ + pass + + def _raw_handler(self, pktlen, pkt, ts): + """ + Accepts raw packet data (pktlen, pkt, ts), and handles decapsulation + and layer stripping. + + Then, it passes the massaged data to the child's raw_handler function, + if additional custom handling is necessary. The raw_handler function + should return (pktlen, pkt, ts) if it wishes to continue with the call + chain. Otherwise, return None. + """ +# with self.seen_packet_count.get_lock(): +# self.seen_packet_count.value += 1 +# +# # call raw_handler and check its output +# # decode.py will continue down the chain if it returns proper output or +# # display a warning if it doesn't return the correct things +# try: +# raw_handler_out = self.raw_handler(pktlen, pkt, ts) +# except Exception as e: +# print_handler_exception(e, self, 'raw_handler') +# return +# +# failed_msg = "The output of {} raw_handler must be (pktlen, pkt, ts) or a list of such lists! Further packet refinement and plugin chaining will not be possible".format(self.name) +# if raw_handler_out and isinstance(raw_handler_out, (list, tuple)): +# self.warn(failed_msg) +# return + + with self.seen_packet_count.get_lock(): + self.seen_packet_count.value += 1 + # decode with the raw decoder (probably ethernet.Ethernet) + pkt = self.raw_decoder(pkt) + + # strip any intermediate layers (e.g. PPPoE, etc.) + # NOTE: make sure only the first plugin in a chain has striplayers set + for _ in range(self.striplayers): + try: + pkt = pkt.upper_layer + except AttributeError: + # No more layers to strip + break + + # call raw_handler and check its output + # decode.py will continue down the chain if it returns proper output or + # display a warning if it doesn't return the correct things + try: + raw_handler_out = self.raw_handler(pktlen, pkt, ts) + except Exception as e: + print_handler_exception(e, self, 'raw_handler') + return + failed_msg = "The output of {} raw_handler must be (pktlen, pkt, ts) or a list of such lists! Further packet refinement and plugin chaining will not be possible".format(self.name) + if isinstance(raw_handler_out, (list, tuple)): + if len(raw_handler_out) == 3 and ( + isinstance(raw_handler_out[0], type(pktlen)) and + isinstance(raw_handler_out[1], type(pkt)) and + isinstance(raw_handler_out[2], type(ts))): + # If it returns one properly formed response, queue and continue + self.raw_packet_queue.append(raw_handler_out) + else: + # If it returns several responses, check them individually + for rhout in raw_handler_out: + if isinstance(rhout, (list, tuple)) and \ + len(rhout) == 3 and \ + isinstance(rhout[0], type(pktlen)) and \ + isinstance(rhout[1], type(pkt)) and \ + isinstance(rhout[2], type(ts)): + self.raw_packet_queue.append(rhout) + elif rhout: + self.warn(failed_msg) + elif raw_handler_out: + self.warn(failed_msg) + + + def raw_handler(self, pktlen, pkt, ts): + """ + A placeholder. + + Plugins will be able to overwrite this to perform custom activites on + raw packet data, such as decapsulation or decryption, before it + becomes further refined down the chain. It should return the same + arguments: pktlen, pkt, ts + + Generally speaking, however, this should never be overwritten unless + there is a very, very good reason for it. + + Arguments: + pktlen: length of packet + pkt: raw bytes of the packet + ts: timestamp of packet + """ + return pktlen, pkt, ts + + def _packet_handler(self, pktlen, pkt, ts): + """ + Accepts the output of raw_handler, pulls out addresses, and converts + it all into a dshell.Packet object before calling the child's + packet_handler function. + """ + # Attempt to perform defragmentation + if isinstance(pkt.upper_layer, (ip.IP, ip6.IP6)): + ipp = pkt.upper_layer + if self.defrag_ip: + ipp = self.ipdefrag(ipp) + if not ipp: + # we do not yet have all of the packet fragments, so move + # on to next packet for now + return + else: + pkt.upper_layer = ipp + + # Initialize a Packet object + # This will be populated with values as we continue through + # the function and eventually be passed to packet_handler + packet = Packet(self, pktlen, pkt, ts) + + # call packet_handler and return its output + # decode.py will continue down the chain if it returns anything + try: + packet_handler_out = self.packet_handler(packet) + except Exception as e: + print_handler_exception(e, self, 'packet_handler') + return + failed_msg = "The output from {} packet_handler must be of type dshell.Packet or a list of such objects! Handling connections or chaining from this plugin may not be possible.".format(self.name) + if isinstance(packet_handler_out, (list, tuple)): + for phout in packet_handler_out: + if isinstance(phout, Packet): + self.packet_queue.append(phout) + with self.handled_packet_count.get_lock(): + self.handled_packet_count.value += 1 + elif phout: + self.warn(failed_msg) + elif isinstance(packet_handler_out, Packet): + self.packet_queue.append(packet_handler_out) + with self.handled_packet_count.get_lock(): + self.handled_packet_count.value += 1 + elif packet_handler_out: + self.warn(failed_msg) + + + def packet_handler(self, pkt): + """ + A placeholder. + + Plugins will be able to overwrite this to perform custom activites on + Packet data. + + It should return a Packet object for functions further down the chain + (i.e. connection_handler and/or blob_handler) + + Arguments: + pkt: a Packet object + """ + return pkt + + + +class ConnectionPlugin(PacketPlugin): + """ + Base level class that plugins will inherit. + + This plugin reassembles connections from packets. + """ + + def __init__(self, **kwargs): + PacketPlugin.__init__(self, **kwargs) + + # similar to packet_queue and raw_packet_queue in superclass + self.connection_queue = [] + + # dictionary to store packets for connections according to addr() + self.connection_tracker = {} + # maximum number of blobs a connection will store before calling + # connection_handler + # it defaults to infinite, but this should be lowered for huge datasets + self.maxblobs = float("inf") # infinite + # how long do we wait before deciding a connection is "finished" + # time is checked by iterating over cached connections and checking if + # the timestamp of the connection's last packet is older than the + # timestamp of the current packet, minus this value + self.connection_timeout = datetime.timedelta(hours=1) + + def _connection_handler(self, pkt): + """ + Accepts a single Packet object and tracks the connection it belongs to. + + If it is the first packet in a connection, it creates a new Connection + object and passes it to connection_init_handler. Otherwise, it will + find the existing Connection in self.connection_tracker. + + The Connection will then be passed to connection_handler. + + If a connection changes direction with this packet, blob_handler will + be called. + + Finally, if this packet is a FIN or RST, it will determine if the + connection should close. + """ + # Sort the addr value for consistent dictionary key purposes + addr = tuple(sorted(pkt.addr)) + + # If this is a new connection, initialize it and call the init handler + if addr not in self.connection_tracker: + conn = Connection(self, pkt) + self.connection_tracker[addr] = conn + try: + self.connection_init_handler(conn) + except Exception as e: + print_handler_exception(e, self, 'connection_init_handler') + return + with self.seen_conn_count.get_lock(): + self.seen_conn_count.value += 1 + else: + conn = self.connection_tracker[addr] + + if conn.stop: + # This connection was flagged to not be tracked + return + + # If connection data is about to change, we set it to a "dirty" state + # for future calls to connection_handler + if pkt.data: + conn.handled = False + + # Check and update the connection's current state + if pkt.tcp_flags in (tcp.TH_SYN, tcp.TH_ACK, tcp.TH_SYN|tcp.TH_ACK, tcp.TH_SYN|tcp.TH_ACK|tcp.TH_ECE): + # if new connection and a handshake is taking place, set to "init" + if not conn.client_state: + conn.client_state = "init" + if not conn.server_state: + conn.server_state = "init" + else: + # otherwise, if the connection isn't closed, set to "established" + # TODO do we care about "listen", "syn-sent", and other in-between states? + if conn.client_state not in ('finishing', 'closed'): + conn.client_state = "established" + if conn.server_state not in ('finishing', 'closed'): + conn.server_state = "established" + + # Add the packet to the connection + # If the direction changed, a Blob will be returned for handling + # Note: The Blob will not be reassembled ahead of time. reassemble() + # must be run inside the blob_handler to catch any unwanted exceptions. + previous_blob = conn.add_packet(pkt) + if previous_blob: + try: + blob_handler_out = self._blob_handler(conn, previous_blob) + except Exception as e: + print_handler_exception(e, self, 'blob_handler') + return + if (blob_handler_out + and not isinstance(blob_handler_out[0], Connection) + and not isinstance(blob_handler_out[1], Blob)): + self.warn("The output from {} blob_handler must be of type (dshell.Connection, dshell.Blob)! Chaining plugins from here may not be possible.".format(self.name)) + blob_handler_out = None + # If the blob_handler decides this Blob isn't interesting, it sets + # the hidden flag, which excludes it and its packets from further + # processing along the plugin chain + if not blob_handler_out: + conn.blobs[-2].hidden = True + + # Check if a side of the connection is attempting to close the + # connection using a FIN or RST packet. Once both sides make a + # closing gesture, the connection is considered closed and handled + if pkt.tcp_flags and pkt.tcp_flags & (tcp.TH_RST | tcp.TH_FIN): + if pkt.sip == conn.clientip: + conn.client_state = "closed" + else: + conn.server_state = "closed" + + if conn.connection_closed: + # Both sides have closed the connection + self._close_connection(conn, full=True) + + elif len(conn.blobs) > self.maxblobs: + # Max blobs hit, so we will run connection_handler and decode.py + # will clear the connection's blob cache + self._close_connection(conn) + + # The current connection is done processing. Now, look over existing + # connections and look for any that have timed out. + # This is based on comparing the time of the current packet, minus + # self.connection_timeout, to each connection's current endtime value. + for addr, conn in self.connection_tracker.items(): + if conn.handled: + continue + if conn.endtime < (pkt.dt - self.connection_timeout): + self._close_connection(conn) + + + def _close_connection(self, conn, full=False): + """ + Runs through some standard actions to close a connection + """ + try: + connection_handler_out = self.connection_handler(conn) + except Exception as e: + print_handler_exception(e, self, 'connection_handler') + return None + conn.handled = True + if connection_handler_out and not isinstance(connection_handler_out, Connection): + self.warn("The output from {} connection_handler must be of type dshell.Connection! Chaining plugins from here may not be possible.".format(self.name)) + connection_handler_out = None + if connection_handler_out: + self.connection_queue.append(connection_handler_out) + with self.handled_conn_count.get_lock(): + self.handled_conn_count.value += 1 + if full: + try: + self.connection_close_handler(conn) + except Exception as e: + print_handler_exception(e, self, 'connection_close_handler') + return connection_handler_out + + + def _cleanup_connections(self): + """ + decode.py will often reach the end of packet capture before all of the + connections are closed properly. This function is called at the end + of things to process those dangling connections. + + NOTE: Because the connections did not close cleanly, + connection_close_handler will not be called. + """ + for addr, conn in self.connection_tracker.items(): + if not conn.stop and not conn.handled: + # try to process the final blob in the connection + try: + blob_handler_out = self._blob_handler(conn, conn.blobs[-1]) + except Exception as e: + print_handler_exception(e, self, 'blob_handler') + blob_handler_out = None + if (blob_handler_out + and not isinstance(blob_handler_out[0], Connection) + and not isinstance(blob_handler_out[1], Blob)): + self.warn("The output from {} blob_handler must be of type (dshell.Connection, dshell.Blob)! Chaining plugins from here may not be possible.".format(self.name)) + blob_handler_out = None + if not blob_handler_out: + conn.blobs[-1].hidden = True + + # then, handle the connection itself + connection_handler_out = self._close_connection(conn) + yield connection_handler_out + + def _purge_connections(self): + """ + When finished with handling a pcap file, calling this will clear all + caches in preparation for next file. + """ + self.connection_queue = [] + self.connection_tracker = {} + + def _blob_handler(self, conn, blob): + """ + Accepts a Connection and a Blob. + + It doesn't really do anything except call the blob_handler and is only + here for consistency and possible future features. + """ + return self.blob_handler(conn, blob) + + def blob_handler(self, conn, blob): + """ + A placeholder. + + Plugins will be able to overwrite this to perform custom activites on + Blob data. + + It should return a Connection object and a Blob object for functions + further down the chain. + + Args: + conn: Connection object + blob: Blob object + """ + return conn, blob + + def connection_init_handler(self, conn): + """ + A placeholder. + + Plugins will be able to overwrite this to perform custom activites on + a connection it is first seen. + + Args: + conn: Connection object + """ + return + + def connection_handler(self, conn): + """ + A placeholder. + + Plugins will be able to overwrite this to perform custom activites on + Connection data. + + It should return a Connection object for functions further down the chain + + Args: + conn: Connection object + """ + return conn + + def connection_close_handler(self, conn): + """ + A placeholder. + + Plugins will be able to overwrite this to perform custom activites on + a TCP connection when it is cleanly closed with RST or FIN. + + Args: + conn: Connection object + """ + return + +class Packet(object): + """ + Class for holding data of individual packets + + def __init__(self, plugin, pktlen, pkt, ts): + + Args: + plugin: an instance of the plugin creating this packet + pktlen: length of packet + pkt: pypacker object for the packet + ts: timestamp of packet + + Attributes: + plugin: name of plugin creating Packet + ts: timestamp of packet + dt: datetime of packet + pkt: pypacker object for the packet + rawpkt: raw bytestring of the packet + pktlen: length of packet + byte_count: length of packet body + sip: source IP + dip: destination IP + sip_bytes: source IP as bytes + dip_bytes: destination IP as bytes + sport: source port + dport: destination port + smac: source MAC + dmac: destination MAC + sipcc: source IP country code + dipcc: dest IP country code + siplat: source IP latitude + diplat: dest IP latitude + siplon: source IP longitude + diplon: dest IP longitude + sipasn: source IP ASN + dipasn: dest IP ASN + protocol: text version of protocol in layer-3 header + protocol_num: numeric version of protocol in layer-3 header + data: data of the packet after TCP layer, or highest layer + sequence_number: TCP sequence number, or None + ack_number: TCP ACK number, or None + tcp_flags: TCP header flags, or None + """ + + def __init__(self, plugin, pktlen, pkt, ts): + self.plugin = plugin.name + self.ts = ts + self.dt = datetime.datetime.fromtimestamp(ts) + self.pkt = pkt + self.rawpkt = pkt.bin() + self.pktlen = pktlen + self.byte_count = None + self.sip = None + self.dip = None + self.sport = None + self.dport = None + self.smac = None + self.dmac = None + self.sipcc = None + self.dipcc = None + self.siplat = None + self.diplat = None + self.siplon = None + self.diplon = None + self.sipasn = None + self.dipasn = None + self.protocol = None + self.protocol_num = None + self.data = b'' + self.sequence_number = None + self.ack_number = None + self.tcp_flags = None + + # these are the layers Dshell will help parse + # try to find them in the packet and eventually pull out useful data + ethernet_p = None + ieee80211_p = None + ip_p = None + tcp_p = None + udp_p = None + current_layer = pkt + while current_layer: + if isinstance(current_layer, ethernet.Ethernet) and not ethernet_p: + ethernet_p = current_layer + elif isinstance(current_layer, ieee80211.IEEE80211) and not ieee80211_p: + ieee80211_p = current_layer + elif isinstance(current_layer, (ip.IP, ip6.IP6)) and not ip_p: + ip_p = current_layer + elif isinstance(current_layer, tcp.TCP) and not tcp_p: + tcp_p = current_layer + elif isinstance(current_layer, udp.UDP) and not udp_p: + udp_p = current_layer + try: + current_layer = current_layer.upper_layer + except AttributeError: + break + + # attempt to grab MAC addresses + if ethernet_p: + # from Ethernet + self.smac = ethernet_p.src_s + self.dmac = ethernet_p.dst_s + elif ieee80211_p: + # from 802.11 + try: + if ieee80211_p.subtype == ieee80211.M_BEACON: + ieee80211_p2 = ieee80211_p.beacon + elif ieee80211_p.subtype == ieee80211.M_DISASSOC: + ieee80211_p2 = ieee80211_p.disassoc + elif ieee80211_p.subtype == ieee80211.M_AUTH: + ieee80211_p2 = ieee80211_p.auth + elif ieee80211_p.subtype == ieee80211.M_DEAUTH: + ieee80211_p2 = ieee80211_p.deauth + elif ieee80211_p.subtype == ieee80211.M_ACTION: + ieee80211_p2 = ieee80211_p.action + else: + # can't figure out how pypacker stores the other subtypes + raise AttributeError + self.smac = ieee80211_p2.src_s + self.dmac = ieee80211_p2.dst_s + except AttributeError as e: + pass + + # process IP addresses and associated metadata (if applicable) + if ip_p: + # get IP addresses + sip = ipaddress.ip_address(ip_p.src) + dip = ipaddress.ip_address(ip_p.dst) + self.sip = sip.compressed + self.dip = dip.compressed + self.sip_bytes = sip.packed + self.dip_bytes = dip.packed + + # get protocols, country codes, and ASNs + self.protocol_num = ip_p.p if isinstance(ip_p, ip.IP) else ip_p.nxt + self.protocol = PacketPlugin.IP_PROTOCOL_MAP.get(self.protocol_num, str(self.protocol_num)) + self.sipcc, self.siplat, self.siplon = geoip.geoip_location_lookup(self.sip) + self.sipasn = geoip.geoip_asn_lookup(self.sip) + self.dipcc, self.diplat, self.diplon = geoip.geoip_location_lookup(self.dip) + self.dipasn = geoip.geoip_asn_lookup(self.dip) + + if tcp_p: + self.sport = tcp_p.sport + self.dport = tcp_p.dport + self.sequence_number = tcp_p.seq + self.ack_number = tcp_p.ack + self.tcp_flags = tcp_p.flags + self.data = tcp_p.body_bytes + + elif udp_p: + self.sport = udp_p.sport + self.dport = udp_p.dport + self.data = udp_p.body_bytes + + else: + self.data = pkt.highest_layer.body_bytes + + self.byte_count = len(self.data) + + + + @property + def addr(self): + """ + A standard representation of the address: + ((self.sip, self.sport), (self.dip, self.dport)) + or + ((self.smac, self.sport), (self.dmac, self.dport)) + """ + # try using IP addresses first + if self.sip or self.dip: + return ((self.sip, self.sport), (self.dip, self.dport)) + # then try MAC addresses + elif self.smac or self.dmac: + return ((self.smac, self.sport), (self.dmac, self.dport)) + # if all else fails, return Nones + else: + return ((None, None), (None, None)) + + @property + def packet_tuple(self): + """ + A standard representation of the raw packet tuple: + (self.pktlen, self.rawpkt, self.ts) + """ + return (self.pktlen, self.rawpkt, self.ts) + + def __repr__(self): + return "%s %16s :%-5s -> %5s :%-5s (%s -> %s)" % (self.dt, self.sip, self.sport, self.dip, self.dport, self.sipcc, self.dipcc) + + def info(self): + """ + Provides a dictionary with information about a packet. Useful for + calls to a plugin's write() function, e.g. self.write(\\*\\*pkt.info()) + """ + d = dict(self.__dict__) + del d['pkt'] + del d['rawpkt'] + del d['data'] + return d + + +class Connection(object): + """ + Class for holding data about connections + + def __init__(self, plugin, first_packet) + + Args: + plugin: an instance of the plugin creating this connection + first_packet: the first Packet object to initialize connection + + Attributes: + plugin: name of the plugin that created object + addr: .addr attribute of first packet + sip: source IP + smac: source MAC address + sport: source port + sipcc: country code of source IP + siplat: latitude of source IP + siplon: longitude of source IP + sipasn: ASN of source IP + clientip: same as sip + clientmac: same as smac + clientport: same as sport + clientcc: same as sipcc + clientlat: same as siplat + clientlon: same as siplon + clientasn: same as sipasn + dip: dest IP + dmac: dest MAC address + dport: dest port + dipcc: country code of dest IP + diplat: latitude of dest IP + diplon: longitude of dest IP + dipasn: ASN of dest IP + serverip: same as dip + servermac: same as dmac + serverport: same as dport + servercc: same as dipcc + serverlat: same as diplat + serverlon: same as diplon + serverasn: same as dipasn + protocol: text version of protocol in layer-3 header + clientpackets: counts of packets from client side + clientbytes: total bytes transferred from client side + serverpackets: counts of packets from server side + serverbytes: total bytes transferred from server side + ts: timestamp of first packet + dt: datetime of first packet + starttime: datetime of first packet + endtime: datetime of last packet + client_state: the TCP state on the client side ("init", + "established", "closed", etc.) + server_state: the TCP state on server side + blobs: list of reassembled half-stream Blobs + stop: if True, stop following connection + handled: used to indicate if a connection was already passed through + a plugin's connection_handler function. Resets when new + data for a connection comes in. + + """ + + def __init__(self, plugin, first_packet): + """ + Initializes Connection object + + Args: + plugin: an instance of the plugin creating this connection + first_packet: the first Packet object to initialize connection + """ + self.plugin = plugin.name + self.addr = first_packet.addr + self.sip = first_packet.sip + self.smac = first_packet.smac + self.sport = first_packet.sport + self.sipcc = first_packet.sipcc + self.siplat = first_packet.siplat + self.siplon = first_packet.siplon + self.sipasn = first_packet.sipasn + self.clientip = first_packet.sip + self.clientmac = first_packet.smac + self.clientport = first_packet.sport + self.clientcc = first_packet.sipcc + self.clientlat = first_packet.siplat + self.clientlon = first_packet.siplon + self.clientasn = first_packet.sipasn + self.dip = first_packet.dip + self.dmac = first_packet.dmac + self.dport = first_packet.dport + self.dipcc = first_packet.dipcc + self.diplat = first_packet.diplat + self.diplon = first_packet.diplon + self.dipasn = first_packet.dipasn + self.serverip = first_packet.dip + self.servermac = first_packet.dmac + self.serverport = first_packet.dport + self.servercc = first_packet.dipcc + self.serverlat = first_packet.diplat + self.serverlon = first_packet.diplon + self.serverasn = first_packet.dipasn + self.protocol = first_packet.protocol + self.clientpackets = 0 + self.clientbytes = 0 + self.serverpackets = 0 + self.serverbytes = 0 + self.ts = first_packet.ts + self.dt = first_packet.dt + self.starttime = first_packet.dt + self.endtime = first_packet.dt + self.client_state = None + self.server_state = None + self.blobs = [] + self.stop = False + self.handled = False + # used to determine if direction changes + self._current_addr_pair = None + + @property + def duration(self): + "total seconds from starttime to endtime" + tdelta = self.endtime - self.starttime + return tdelta.total_seconds() + + @property + def connection_closed(self): + return self.client_state == "closed" and self.server_state == "closed" + + def add_packet(self, packet): + """ + Accepts a Packet object and attempts to push it into the current Blob. + If the direction changes, it creates a new Blob and returns the old one + to the caller. + + Args: + packet: a Packet object to add to the connection + + Returns: + Previous Blob if direction has changed + """ + if packet.sip == self.clientip and (not packet.sport or packet.sport == self.clientport): + # packet moving from client to server + direction = 'cs' + else: + # packet moving from server to client + direction = 'sc' + + if (packet.addr != self._current_addr_pair and packet.data) or len(self.blobs) == 0: + try: + old_blob = self.blobs[-1] + except IndexError: + old_blob = None + self.blobs.append(Blob(packet, direction)) + self._current_addr_pair = packet.addr + else: + old_blob = None + + blob = self.blobs[-1] + blob.add_packet(packet) + + # Only count packets if they have data (i.e. ignore SYNs, ACKs, etc.) + if packet.data: + if packet.addr == self.addr: + self.clientpackets += 1 + self.clientbytes += packet.byte_count + else: + self.serverpackets += 1 + self.serverbytes += packet.byte_count + + if packet.dt > self.endtime: + self.endtime = packet.dt + + if old_blob: + return old_blob + + def info(self): + """ + Provides a dictionary with information about a connection. Useful for + calls to a plugin's write() function, e.g. self.write(\\*\\*conn.info()) + + Returns: + Dictionary with information + """ + d = dict(self.__dict__) + d['duration'] = self.duration + del d['blobs'] + del d['stop'] + del d['_current_addr_pair'] + del d['handled'] + return d + + def __repr__(self): + return '%s %16s -> %16s (%s -> %s) %6s %6s %5d %5d %7d %7d %-.4fs' % ( + self.starttime, + self.clientip, + self.serverip, + self.clientcc, + self.servercc, + self.clientport, + self.serverport, + self.clientpackets, + self.serverpackets, + self.clientbytes, + self.serverbytes, + self.duration, + ) + +class Blob(object): + """ + Class for holding and reassembling pieces of a connection. + + A Blob holds the packets and reassembled data for traffic moving in one + direction in a connection, before direction changes. + + def __init__(self, first_packet, direction) + + Args: + first_packet: the first Packet object to initialize Blob + direction: direction of blob - + 'cs' for client-to-server, 'sc' for sever-to-client + + Attributes: + addr: .addr attribute of the first packet + ts: timestamp of the first packet + starttime: datetime for first packet + endtime: datetime of last packet + sip: source IP + smac: source MAC address + sport: source port + sipcc: country code of source IP + sipasn: ASN of source IP + dip: dest IP + dmac: dest MAC address + dport: dest port + dipcc: country code of dest IP + dipasn: ASN of dest IP + protocol: text version of protocol in layer-3 header + direction: direction of the blob - + 'cs' for client-to-server, 'sc' for sever-to-client + ack_sequence_numbers: set of ACK numbers from the receiver for #################################### + collected data packets + all_packets: list of all packets in the blob + hidden (bool): Used to indicate that a Blob should not be passed to + next plugin. Can theoretically be overruled in, say, a + connection_handler to force a Blob to be passed to next + plugin. + """ + + # max offset before wrap, default is MAXINT32 for TCP sequence numbers + MAX_OFFSET = 0xffffffff + + def __init__(self, first_packet, direction): + self.addr = first_packet.addr + self.ts = first_packet.ts + self.starttime = first_packet.dt + self.endtime = first_packet.dt + self.sip = first_packet.sip + self.smac = first_packet.smac + self.sport = first_packet.sport + self.sipcc = first_packet.sipcc + self.sipasn = first_packet.sipasn + self.dip = first_packet.dip + self.dmac = first_packet.dmac + self.dport = first_packet.dport + self.dipcc = first_packet.dipcc + self.dipasn = first_packet.dipasn + self.protocol = first_packet.protocol + self.direction = direction +# self.ack_sequence_numbers = {} + self.all_packets = [] +# self.data_packets = [] + self.__data_bytes = b'' + + # Used to indicate that a Blob should not be passed to next plugin. + # Can theoretically be overruled in, say, a connection_handler to + # force a Blob to be passed to next plugin. + self.hidden = False + + @property + def data(self): + """ + Returns the reassembled byte string. + + If it was not already reassembled, reassemble is called with default + arguments. + """ + if not self.__data_bytes: + self.reassemble() + return self.__data_bytes + + def reassemble(self, allow_padding=True, allow_overlap=True, padding=b'\x00'): + """ + Rebuild the data string from the current list of data packets + For each packet, the TCP sequence number is checked. + + If overlapping or padding is disallowed, it will raise a + SequenceNumberError exception if a respective event occurs. + + Args: + allow_padding (bool): If data is missing and allow_padding = True + (default: True), then the padding argument + will be used to fill the gaps. + allow_overlap (bool): If data is overlapping, the new data is + used if the allow_overlap argument is True + (default). Otherwise, the earliest data is + kept. + padding: Byte character(s) to use to fill in missing data. Used + in conjunction with allow_padding (default: b'\\\\x00') + """ + data = b"" + unacknowledged_data = [] + acknowledged_data = {} + for pkt in self.all_packets: + if not pkt.sequence_number: + # if there are no sequence numbers (i.e. not TCP), just rebuild + # in chronological order + data += pkt.data + continue + + if pkt.data: + if pkt.sequence_number in acknowledged_data: + continue + unacknowledged_data.append(pkt) + + elif pkt.tcp_flags and pkt.tcp_flags & tcp.TH_ACK: + ackpkt = pkt + for i, datapkt in enumerate(unacknowledged_data): + if (datapkt.ack_number == ackpkt.sequence_number + and ackpkt.ack_number == (datapkt.sequence_number + len(datapkt.data))): + # if the seq/ack numbers align, this is the data packet + # we want + # TODO confirm this logic is correct + acknowledged_data[datapkt.sequence_number] = datapkt.data + unacknowledged_data.pop(i) + break + + if not acknowledged_data and not unacknowledged_data: + # For non-sequential protocols, just return what we have + self.__data_bytes = data + + else: + # Create a list of each segment of the complete data. Use + # acknowledged data first, and then try to fill in the blanks with + # unacknowledged data. + segments = acknowledged_data.copy() + for pkt in reversed(unacknowledged_data): + if pkt.sequence_number in segments: continue + segments[pkt.sequence_number] = pkt.data + + offsets = sorted(segments.keys()) + # iterate over the segments and try to piece them together + # handle any instances of missing or overlapping segments + nextoffset = offsets[0] + startoffset = offsets[0] + for offset in offsets: + if offset > nextoffset: + # data is missing + if allow_padding: + data += padding * (offset - nextoffset) + else: + raise SequenceNumberError("Missing data for sequence number %d %s" % (nextoffset, self.addr)) + elif offset < nextoffset: + # data is overlapping + if not allow_overlap: + raise SequenceNumberError("Overlapping data for sequence number %d %s" % (nextoffset, self.addr)) + + nextoffset = (offset + len(segments[offset])) & self.MAX_OFFSET + data = data[:offset - startoffset] + \ + segments[offset] + \ + data[nextoffset - startoffset:] + self.__data_bytes = data + + return data + + + + +# segments = {} +# for pkt in self.data_packets: +# if pkt.sequence_number: +# segments.setdefault(pkt.sequence_number, []).append(pkt.data) +# else: +# # if there are no sequence numbers (i.e. not TCP), just rebuild +# # in chronological order +# data += pkt.data +# +# if not segments: +# # For non-sequential protocols, just return what we have +# self.__data_bytes = data +# return data +# +# offsets = sorted(segments.keys()) +# +# # iterate over the segments and try to piece them together +# # handle any instances of missing or overlapping segments +# nextoffset = offsets[0] +# startoffset = offsets[0] +# for offset in offsets: +# # TODO do we still want to implement custom error handling? +# if offset > nextoffset: +# # data is missing +# if allow_padding: +# data += padding * (offset - nextoffset) +# else: +# raise SequenceNumberError("Missing data for sequence number %d %s" % (nextoffset, self.addr)) +# elif offset < nextoffset: +# # data is overlapping +# if not allow_overlap: +# raise SequenceNumberError("Overlapping data for sequence number %d %s" % (nextoffset, self.addr)) +## nextoffset = (offset + len(segments[offset][dup])) & self.MAX_OFFSET +## if nextoffset in self.ack_sequence_numbers: +# if offset in self.ack_sequence_numbers: +# # If the data packet was acknowledged by the receiver, +# # we use the first packet received. +# dup = 0 +# else: +# # If it went unacknowledged, we use the last packet and hope +# # for the best. +# dup = -1 +# print(dup) +# print(offset) +# print(nextoffset) +# print(str(self.ack_sequence_numbers)) +# nextoffset = (offset + len(segments[offset][dup])) & self.MAX_OFFSET +# data = data[:offset - startoffset] + \ +# segments[offset][dup] + \ +# data[nextoffset - startoffset:] +# self.__data_bytes = data +# return data + + def info(self): + """ + Provides a dictionary with information about a blob. Useful for + calls to a plugin's write() function, e.g. self.write(\\*\\*conn.info()) + + Returns: + Dictionary with information + """ + d = dict(self.__dict__) + del d['hidden'] + del d['_Blob__data_bytes'] + del d['all_packets'] + return d + + def add_packet(self, packet): + """ + Accepts a Packet object and stores it. + + Args: + packet: a Packet object + """ + self.all_packets.append(packet) + + if packet.dt > self.endtime: + self.endtime = packet.dt diff --git a/share/GeoIP/readme.txt b/dshell/data/GeoIP/readme.txt similarity index 100% rename from share/GeoIP/readme.txt rename to dshell/data/GeoIP/readme.txt diff --git a/dshell/data/dshellrc b/dshell/data/dshellrc new file mode 100644 index 0000000..f428e2e --- /dev/null +++ b/dshell/data/dshellrc @@ -0,0 +1,2 @@ +export PS1="`whoami`@`hostname`:\w Dshell> " +alias decode="python3 -m dshell.decode " diff --git a/dshell/data/empty.pcap b/dshell/data/empty.pcap new file mode 100644 index 0000000000000000000000000000000000000000..a324304509bdd12aef4a69458a409cefefafe614 GIT binary patch literal 24 Ycmca|c+)~A1{MYw`2U}Qff2|708wKE@Bjb+ literal 0 HcmV?d00001 diff --git a/dshell/decode.py b/dshell/decode.py new file mode 100755 index 0000000..2afa423 --- /dev/null +++ b/dshell/decode.py @@ -0,0 +1,742 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +This is the core script for running plugins. + +It works by grabbing individual packets from a file or interface and feeding +them into a chain of plugins (plugin_chain). Each plugin in the chain +decides if the packet will continue on to the next plugin or just fade away. + +In practice, users generally only use one plugin, so the "chain" will only +have one plugin, which is perfectly fine. The chain exists to allow plugins +to alter or filter packets before passing them to more general plugins. For +example, --plugin=country+netflow would pass packets through the country +plugin, and then the netflow plugin. This would allow filtering traffic by +country code before viewing flow data. + +Many things go into making this chain run smoothly, however. This includes +reading in user arguments, setting filters, opening files/interfaces, etc. All +of this largely takes place in the main() function. +""" + +# set up logging first, since some third-party libraries would try to +# configure things their own way +import logging +logging.basicConfig(format="%(levelname)s (%(name)s) - %(message)s") +logger = logging.getLogger("decode.py") + +# since pypacker handles its own exceptions (loudly), this attempts to keep +# it quiet +from pypacker import pypacker +pypacker.logger.setLevel(logging.CRITICAL) + +import dshell.core +from dshell.dshelllist import get_plugins, get_output_modules +from dshell.dshellargparse import DshellArgumentParser +from dshell.output.output import QueueOutputWrapper +from dshell.util import get_output_path + +import pcapy + +# standard Python library imports +import bz2 +import copy +import faulthandler +import gzip +import multiprocessing +import operator +import os +import queue +#import signal +import sys +import tempfile +import zipfile +from collections import OrderedDict +from getpass import getpass +from glob import glob +from importlib import import_module + +# plugin_chain will eventually hold the user-selected plugins that packets +# will trickle through. +plugin_chain = [] + +def feed_plugin_chain(plugin_index, packet_tuple): + """ + Every packet fed into Dshell goes through this function. + Its goal is to pass each packet down the chain of selected plugins. + Each plugin decides whether the packet(s) will proceed to the next + plugin, i.e. act as a filter. + """ + global plugin_chain + (pktlen, pkt, ts) = packet_tuple + current_plugin = plugin_chain[plugin_index] + next_plugin_index = plugin_index + 1 + if next_plugin_index >= len(plugin_chain): + next_plugin_index = None + + # Check the plugin's filter to see if this packet should go any further + if current_plugin.compiled_bpf and not current_plugin.compiled_bpf.filter(pkt): + return + + # Begin stepping through the plugin and feeding each handler function in + # order: + # raw_handler --> packet_handler -?-> connection_handler (init/blob_handler/close) + current_plugin._raw_handler(pktlen, pkt, ts) + + # feed any available raw packets to the packet_handler + while len(current_plugin.raw_packet_queue) > 0: + rawpacket = current_plugin.raw_packet_queue.pop(0) + current_plugin._packet_handler(*rawpacket) + + # Check if this plugin handles connections + # If it doesn't, we can just pass the packet to the next plugin now + if "_connection_handler" not in current_plugin.members: + if next_plugin_index: + while len(current_plugin.packet_queue) > 0: + packet = current_plugin.packet_queue.pop(0) + feed_plugin_chain(next_plugin_index, packet.packet_tuple) + return + + # Connection handlers are a little different. + # They only enqueue anything when a connection closes or times out. + while len(current_plugin.packet_queue) > 0: + packet = current_plugin.packet_queue.pop(0) + current_plugin._connection_handler(packet) + + # Connections are "passed" to the next plugin by popping off their blobs, + # then passing all of the packets within. + # Afterwards, the connection is cleared from the plugin's cache. + while len(current_plugin.connection_queue) > 0: + connection = current_plugin.connection_queue.pop(0) + if next_plugin_index: + for blob in connection.blobs: + if not blob.hidden: + for packet in blob.all_packets: + feed_plugin_chain(next_plugin_index, packet.packet_tuple) + conn_key = tuple(sorted(connection.addr)) + try: + # Attempt to clear out the connection, now that it has been handled. + del current_plugin.connection_tracker[conn_key] + except KeyError: + # If the plugin messed with the connection's address, it might + # fail to clear it. + # TODO find some way to better handle this scenario + pass + + +def clean_plugin_chain(plugin_index): + """ + This is called at the end of packet capture. + It will go through the plugins and attempt to cleanup any connections + that were not yet closed. + """ + current_plugin = plugin_chain[plugin_index] + next_plugin_index = plugin_index + 1 + if next_plugin_index >= len(plugin_chain): + next_plugin_index = None + + # Check if the plugin handles connections + # If it does, close out its open connections and pass the stored packets + # down the chain. + if "_connection_handler" in current_plugin.members: + for connection_handler_out in current_plugin._cleanup_connections(): + if not connection_handler_out: + continue + if next_plugin_index: + for blob in connection_handler_out.blobs: + if not blob.hidden: + for packet in blob.all_packets: + feed_plugin_chain(next_plugin_index, packet.packet_tuple) + if next_plugin_index: + clean_plugin_chain(next_plugin_index) + + +def decompress_file(filepath, extension, unzipdir): + """ + Attempts to decompress a provided file and write the data to a temporary + file. The list of created temporary files is returned. + """ + filename = os.path.split(filepath)[-1] + openfiles = [] + logger.debug("Attempting to decompress {!r}".format(filepath)) + if extension == '.gz': + f = gzip.open(filepath, 'rb') + openfiles.append(f) + elif extension == '.bz2': + f = bz2.open(filepath, 'rb') + openfiles.append(f) + elif extension == '.zip': + pswd = getpass("Enter password for .zip file {!r} [default: none]: ".format(filepath)) + pswd = pswd.encode() # TODO I'm not sure encoding to utf-8 will work in all cases + try: + z = zipfile.ZipFile(filepath) + for z2 in z.namelist(): + f = z.open(z2, 'r', pswd) + openfiles.append(f) + except (RuntimeError, zipfile.BadZipFile) as e: + logger.error("Could not process .zip file {!r}. {!s}".format(filepath, e)) + return [] + + tempfiles = [] + for openfile in openfiles: + try: + # check if this file is actually something decompressable + openfile.peek(1) + except OSError as e: + logger.error("Could not process compressed file {!r}. {!s}".format(filepath, e)) + openfile.close() + continue + tfile = tempfile.NamedTemporaryFile(dir=unzipdir, delete=False, prefix=filename) + for piece in openfile: + tfile.write(piece) + tempfiles.append(tfile.name) + openfile.close() + tfile.close() + return tempfiles + + + +def print_plugins(plugins): + "Print list of plugins with additional info" + row = "{:<40} {:15} {:<20} {:<20} {:<10} {}" + print(row.format('module', 'name', 'title', 'type', 'author', 'description')) + print('-' * 121) + for name, module in plugins.items(): + print(row.format(module.__module__, + name, + module.name, + module.__class__.__bases__[0].__name__, + module.author, + module.description)) + +def main(plugin_args={}, **kwargs): + global plugin_chain + + # dictionary of all available plugins: {name: module path} + plugin_map = get_plugins(logger) + + # Attempt to catch segfaults caused when certain linktypes (e.g. 204) are + # given to pcapy + faulthandler.enable() + + if not plugin_chain: + logger.error("No plugin selected") + sys.exit(1) + + plugin_chain[0].defrag_ip = kwargs.get("defrag", False) + + if kwargs.get("verbose", False): + logger.setLevel(logging.INFO) + dshell.core.logger.setLevel(logging.INFO) + dshell.core.geoip.logger.setLevel(logging.INFO) + # Activate verbose mode in each of the plugins + for plugin in plugin_chain: + plugin.out.set_level(logging.INFO) + + if kwargs.get("allcc", False): + # Activate all country code (allcc) mode to display all 3 GeoIP2 country + # codes + dshell.core.geoip.acc = True + + if kwargs.get("debug", False): + pypacker.logger.setLevel(logging.WARNING) + logger.setLevel(logging.DEBUG) + dshell.core.logger.setLevel(logging.DEBUG) + dshell.core.geoip.logger.setLevel(logging.DEBUG) + # Activate debug mode in each of the plugins + for plugin in plugin_chain: + plugin.out.set_level(logging.DEBUG) + + if kwargs.get("quiet", False): + logger.disabled = True + dshell.core.logger.disabled = True + dshell.core.geoip.logger.disabled = True + # Disable logging for each of the plugins + for plugin in plugin_chain: + plugin.out.logger.disabled = True + + dshell.core.geoip.check_file_dates() + + # If alternate output module is selected, tell each plugin to use that + # instead + if kwargs.get("omodule", None): + # Check if any user-defined output arguments are provided + oargs = {} + if kwargs.get("oargs", None): + for oarg in kwargs["oargs"]: + if '=' in oarg: + key, val = oarg.split('=', 1) + oargs[key] = val + else: + oargs[oarg] = True + try: + omodule = import_module("dshell.output."+kwargs["omodule"]) + omodule = omodule.obj + for plugin in plugin_chain: + oargs['label'] = plugin.__module__ + oomodule = omodule(**oargs) + if kwargs.get("verbose", False): + oomodule.set_level(logging.INFO) + if kwargs.get("debug", False): + oomodule.set_level(logging.DEBUG) + if kwargs.get("quiet", False): + oomodule.logger.disabled = True + plugin.out = oomodule + except ImportError as e: + logger.error("Could not import module named '{}'. Use --list-output flag to see available modules".format(kwargs["omodule"])) + sys.exit(1) + + # If writing to a file, set for each output module here + if kwargs.get("outfile", None): + for plugin in plugin_chain: + try: + plugin.out.reset_fh(filename=kwargs["outfile"]) + # Try and catch common exceptions to avoid lengthy tracebacks + except OSError as e: + if not self.debug: + logger.error(str(e)) + sys.exit(1) + else: + raise e + + # Set nobuffer mode if that's what the user wants + if kwargs.get("nobuffer", False): + for plugin in plugin_chain: + plugin.out.nobuffer = True + + # Set the extra flag for all output modules + if kwargs.get("extra", False): + for plugin in plugin_chain: + plugin.out.extra = True + plugin.out.set_format(plugin.out.format) + + # Set the BPF filters + # Each plugin has its own default BPF that will be extended or replaced + # based on --no-vlan, --ebpf, or --bpf arguments. + for plugin in plugin_chain: + if kwargs.get("bpf", None): + plugin.bpf = kwargs.get("bpf", "") + continue + if plugin.bpf: + if kwargs.get("ebpf", None): + plugin.bpf = "({}) and ({})".format(plugin.bpf, kwargs.get("ebpf", "")) + else: + if kwargs.get("ebpf", None): + plugin.bpf = kwargs.get("ebpf", "") + if kwargs.get("novlan", False): + plugin.vlan_bpf = False + + # Decide on the inputs to use for pcap + # If --interface is set, ignore all files and listen live on the wire + # Otherwise, use all of the files and globs to open offline pcap. + # Recurse through any directories if the command-line flag is set. + if kwargs.get("interface", None): + inputs = [kwargs.get("interface")] + else: + inputs = [] + inglobs = kwargs.get("files", []) + infiles = [] + for inglob in inglobs: + outglob = glob(inglob) + if not outglob: + logger.warning("Could not find file(s) matching {!r}".format(inglob)) + continue + infiles.extend(outglob) + while len(infiles) > 0: + infile = infiles.pop(0) + if kwargs.get("recursive", False) and os.path.isdir(infile): + morefiles = os.listdir(infile) + for morefile in morefiles: + infiles.append(os.path.join(infile, morefile)) + elif os.path.isfile(infile): + inputs.append(infile) + + # Process plugin-specific options + for plugin in plugin_chain: + for option, args in plugin.optiondict.items(): + if option in plugin_args.get(plugin, {}): + setattr(plugin, option, plugin_args[plugin][option]) + else: + setattr(plugin, option, args.get("default", None)) + plugin.handle_plugin_options() + + + #### Dshell is ready to read pcap! #### + for plugin in plugin_chain: + plugin._premodule() + + # If we are not multiprocessing, simply pass the files for processing + if not kwargs.get("multiprocessing", False): + process_files(inputs, **kwargs) + # If we are multiprocessing, things get more complicated. + else: + # Create an output queue, and wrap the 'write' function of each + # plugins's output module to send calls to the multiprocessing queue + output_queue = multiprocessing.Queue() + output_wrappers = {} + for plugin in plugin_chain: + qo = QueueOutputWrapper(plugin.out, output_queue) + output_wrappers[qo.id] = qo + plugin.out.write = qo.write + + # Create processes to handle each separate input file + processes = [] + for i in inputs: + processes.append( + multiprocessing.Process(target=process_files, args=([i]), kwargs=kwargs) + ) + + # Spawn processes, and keep track of which ones are running + running = [] + max_writes_per_batch = 50 + while processes or running: + if processes and len(running) < kwargs.get("process_max", 4): + # Start a process and move it to the 'running' list + proc = processes.pop(0) + proc.start() + logger.debug("Started process {}".format(proc.pid)) + running.append(proc) + for proc in running: + if not proc.is_alive(): + # Remove finished processes from 'running' list + logger.debug("Ended process {} (exit code: {})".format(proc.pid, proc.exitcode)) + running.remove(proc) + try: + # Process write commands in the output queue. + # Since some plugins write copiously and may block other + # processes from launching, only write up to a maximum number + # before breaking and rechecking the processes. + writes = 0 + while writes < max_writes_per_batch: + wrapper_id, args, kwargs = output_queue.get(True, 1) + owrapper = output_wrappers[wrapper_id] + owrapper.true_write(*args, **kwargs) + writes += 1 + except queue.Empty: + pass + + output_queue.close() + + for plugin in plugin_chain: + plugin._postmodule() + + +def process_files(inputs, **kwargs): + # Iterate over each of the input files + # For live capture, the "input" would just be the name of the interface + global plugin_chain + + while len(inputs) > 0: + input0 = inputs.pop(0) + + # Check if file needs to be decompressed by its file extension + extension = os.path.splitext(input0)[-1] + if extension in (".gz", ".bz2", ".zip") and not "interface" in kwargs: + tempfiles = decompress_file(input0, extension, kwargs.get("unzipdir", tempfile.gettempdir())) + inputs = tempfiles + inputs + continue + + for plugin in plugin_chain: + plugin._prefile(input0) + + if kwargs.get("interface", None): + # Listen on an interface if the option is set + try: + capture = pcapy.open_live(input0, 65536, True, 0) + except pcapy.PcapError as e: + # User probably doesn't have permission to listen on interface + # In any case, print just the error without traceback + logger.error(str(e)) + sys.exit(1) + else: + # Otherwise, read from pcap file(s) + try: + capture = pcapy.open_offline(input0) + except pcapy.PcapError as e: + logger.error("Could not open '{}': {!s}".format(input0, e)) + continue + + # Try and use the first plugin's BPF as the initial filter + # The BPFs for other plugins will be applied along the chain as needed + initial_bpf = plugin_chain[0].bpf + try: + if initial_bpf: + capture.setfilter(initial_bpf) + except pcapy.PcapError as e: + if str(e).startswith("no VLAN support for data link type"): + logger.error("Cannot use VLAN filters for {!r}. Recommend running with --no-vlan argument.".format(input0)) + continue + elif "syntax error" in str(e) or "link layer applied in wrong context" == str(e): + logger.error("Could not compile BPF: {!s} ({!r})".format(e, initial_bpf)) + sys.exit(1) + elif "802.11 link-layer types supported only on 802.11" == str(e): + logger.error("BPF incompatible with pcap file: {!s}".format(e)) + continue + else: + raise e + + # Set the datalink layer for each plugin, based on the pcapy capture. + # Also compile a pcapy BPF object for each. + for plugin in plugin_chain: + # TODO Find way around libpcap bug that segfaults when certain BPFs + # are used with certain datalink types + # (e.g. datalink=204, bpf="ip") + plugin.set_link_layer_type(capture.datalink()) + plugin.recompile_bpf() + + # Iterate over the file/interface and pass the packets down the chain + while True: + try: + header, packet = capture.next() + if header == None and not packet: + # probably the end of the capture + break + if kwargs.get("count", 0) and plugin_chain[0].seen_packet_count.value >= kwargs["count"]: + # we've reached the maximum number of packets to process + break + pktlen = header.getlen() + ts = header.getts() + ts = ts[0] + ts[1] / 1000000.0 + feed_plugin_chain(0, (pktlen, packet, ts)) + except pcapy.PcapError as e: + estr = str(e) + eformat = "Error processing '{i}' - {e}" + if estr.startswith("truncated dump file"): + logger.error( eformat.format(i=input0, e=estr) ) + if kwargs.get("debug", False): + logger.exception(e) + elif estr.startswith("bogus savefile header"): + logger.error( eformat.format(i=input0, e=estr) ) + if kwargs.get("debug", False): + logger.exception(e) + else: + raise e + break + + clean_plugin_chain(0) + for plugin in plugin_chain: + try: + plugin._purge_connections() + except AttributeError: + # probably just a packet plugin + pass + plugin._postfile() + + +def main_command_line(): + global plugin_chain + # dictionary of all available plugins: {name: module path} + plugin_map = get_plugins(logger) + # dictionary of plugins that the user wants to use: {name: object} + active_plugins = OrderedDict() + + # The main argument parser. It will have every command line option + # available and should be used when actually parsing + parser = DshellArgumentParser( + usage="%(prog)s [options] [plugin options] file1 file2 ... fileN", + add_help=False) + parser.add_argument('-c', '--count', type=int, default=0, + help='Number of packets to process') + parser.add_argument('--debug', action="store_true", + help="Show debug messages") + parser.add_argument('-v', '--verbose', action="store_true", + help="Show informational messages") + parser.add_argument('-acc', '--allcc', action="store_true", + help="Show all 3 GeoIP2 country code types (represented_country/registered_country/country)") + parser.add_argument('-d', '-p', '--plugin', dest='plugin', type=str, + action='append', metavar="DECODER", + help="Use a specific plugin module. Can be chained with '+'.") + parser.add_argument('--defragment', dest='defrag', action='store_true', + help='Reconnect fragmented IP packets') + parser.add_argument('-h', '-?', '--help', dest='help', + help="Print common command-line flags and exit", action='store_true', + default=False) + parser.add_argument('-i', '--interface', default=None, type=str, + help="Listen live on INTERFACE instead of reading pcap") + parser.add_argument('-l', '--ls', '--list', action="store_true", + help='List all available plugins', dest='list') + parser.add_argument('-r', '--recursive', dest='recursive', action='store_true', + help='Recursively process all PCAP files under input directory') + parser.add_argument('--unzipdir', type=str, metavar="DIRECTORY", + default=tempfile.gettempdir(), + help='Directory to use when decompressing input files (.gz, .bz2, and .zip only)') + + multiprocess_group = parser.add_argument_group("multiprocessing arguments") + multiprocess_group.add_argument('-P', '--parallel', dest='multiprocessing', action='store_true', + help='Handle each file in separate parallel processes') + multiprocess_group.add_argument('-n', '--nprocs', type=int, default=4, + metavar='NUMPROCS', dest='process_max', + help='Define max number of parallel processes (default: 4)') + + filter_group = parser.add_argument_group("filter arguments") + filter_group.add_argument('--bpf', default='', type=str, + help="Overwrite all BPFs and use provided input. Use carefully!") + filter_group.add_argument('--ebpf', default='', type=str, metavar="BPF", + help="Extend existing BPFs with provided input for additional filtering. It will transform input into \"() and ()\"") + filter_group.add_argument("--no-vlan", action="store_true", dest="novlan", + help="Ignore packets with VLAN headers") + + output_group = parser.add_argument_group("output arguments") + output_group.add_argument("--lo", "--list-output", action="store_true", + help="List available output modules", + dest="listoutput") + output_group.add_argument("--no-buffer", action="store_true", + help="Do not buffer plugin output", + dest="nobuffer") + output_group.add_argument("-x", "--extra", action="store_true", + help="Appends extra data to all plugin output.") + # TODO Figure out how to make --extra flag play nicely with user-only + # output modules, like jsonout and csvout + output_group.add_argument("-O", "--omodule", type=str, dest="omodule", + metavar="MODULE", + help="Use specified output module for plugins instead of defaults. For example, --omodule=jsonout for JSON output.") + output_group.add_argument("--oarg", type=str, metavar="ARG=VALUE", + dest="oargs", action="append", + help="Supply a specific keyword argument to user-defined output module. Only used in conjunction with --omodule. Can be used multiple times for multiple arguments. Not using an equal sign will treat it as a flag and set the value to True. Example: --omodule=alertout --oarg \"timeformat=%%H %%M %%S\"") + output_group.add_argument("-q", "--quiet", action="store_true", + help="Disable logging") + output_group.add_argument("-W", metavar="OUTFILE", dest="outfile", + help="Write to OUTFILE instead of stdout") + + parser.add_argument('files', nargs='*', + help="pcap files or globs to process") + + # A short argument parser, meant to only hold the simplified list of + # arguments for when a plugin is called without a pcap file. + # DO NOT USE for any serious argument parsing. + parser_short = DshellArgumentParser( + usage="%(prog)s [options] [plugin options] file1 file2 ... fileN", + add_help=False) + parser_short.add_argument('-h', '-?', '--help', dest='help', + help="Print common command-line flags and exit", action='store_true', + default=False) + parser.add_argument('--version', action='version', + version="Dshell " + str(dshell.core.__version__)) + parser_short.add_argument('-d', '-p', '--plugin', dest='plugin', type=str, + action='append', metavar="DECODER", + help="Use a specific plugin module") + parser_short.add_argument('--ebpf', default='', type=str, metavar="BPF", + help="Extend existing BPFs with provided input for additional filtering. It will transform input into \"() and ()\"") + parser_short.add_argument('-i', '--interface', + help="Listen live on INTERFACE instead of reading pcap") + parser_short.add_argument('-l', '--ls', '--list', action="store_true", + help='List all available plugins', dest='list') + parser_short.add_argument("--lo", "--list-output", action="store_true", + help="List available output modules") + parser_short.add_argument("-o", "--omodule", type=str, metavar="MODULE", + help="Use specified output module for plugins instead of defaults. For example, --omodule=jsonout for JSON output.") + parser_short.add_argument('files', nargs='*', + help="pcap files or globs to process") + + # Start parsing the arguments + # Specifically, we want to grab the desired plugin list + # This will let us add the plugin-specific arguments and reprocess the args + opts, xopts = parser.parse_known_args() + if opts.plugin: + # Multiple plugins can be chained using either multiple instances + # of -d/-p/--plugin or joining them together with + signs. + plugins = '+'.join(opts.plugin) + plugins = plugins.split('+') + # check for invalid plugins + for plugin in plugins: + plugin = plugin.strip() + if not plugin: + # User probably mistyped '++' instead of '+' somewhere. + # Be nice and ignore this minor infraction. + continue + if plugin not in plugin_map: + parser_short.epilog = "ERROR! Invalid plugin provided: '{}'".format(plugin) + parser_short.print_help() + sys.exit(1) + # While we're at it, go ahead and import the plugin modules now + # This can probably be done further down the line, but here is + # just convenient + plugin_module = import_module(plugin_map[plugin]) + # Handle multiple instances of same plugin by appending number to + # end of plugin name. This is used mostly to separate + # plugin-specific arguments from each other + if plugin in active_plugins: + i = 1 + plugin = plugin + str(i) + while plugin in active_plugins: + i += 1 + plugin = plugin[:-(len(str(i-1)))] + str(i) + # Add copy of plugin object to chain and add to argument parsers + active_plugins[plugin] = plugin_module.DshellPlugin() + plugin_chain.append(active_plugins[plugin]) + parser.add_plugin_arguments(plugin, active_plugins[plugin]) + parser_short.add_plugin_arguments(plugin, active_plugins[plugin]) + opts, xopts = parser.parse_known_args() + + if xopts: + for xopt in xopts: + logger.warning('Could not understand argument {!r}'.format(xopt)) + + if opts.help: + # Just print the full help message and exit + parser.print_help() + print("\n") + for plugin in plugin_chain: + print("############### {}".format(plugin.name)) + print(plugin.longdescription) + print("\n") + print('Default BPF: "{}"'.format(plugin.bpf)) + print("\n") + sys.exit() + + if opts.list: + # Import ALL of the plugins and print info about them before exiting + listing_plugins = OrderedDict() + for name, module in sorted(plugin_map.items(), key=operator.itemgetter(1)): + try: + module = import_module(module) + if not module.DshellPlugin: + continue + module = module.DshellPlugin() + listing_plugins[name] = module + except Exception as e: + logger.error("Could not load {!r}. ({!s})".format(module, e)) + if opts.debug: + logger.exception(e) + print_plugins(listing_plugins) + sys.exit() + + if opts.listoutput: + # List available output modules and a brief description + output_map = get_output_modules(get_output_path(), logger) + for modulename in sorted(output_map): + try: + module = import_module("dshell.output."+modulename) + module = module.obj + except Exception as e: + etype = e.__class__.__name__ + logger.debug("Could not load {} module. ({}: {!s})".format(modulename, etype, e)) + else: + print("\t{:<25} {}".format(modulename, module._DESCRIPTION)) + sys.exit() + + if not opts.plugin: + # If a plugin isn't provided, print the short help message + parser_short.epilog = "Select a plugin to use with -d or --plugin" + parser_short.print_help() + sys.exit() + + if not opts.files and not opts.interface: + # If no files are provided, print the short help message + parser_short.epilog = "Include a pcap file to get started. Use --help for more information." + parser_short.print_help() + sys.exit() + + # Process the plugin-specific args and set the attributes within them + plugin_args = {} + for plugin_name, plugin in active_plugins.items(): + plugin_args[plugin] = {} + args_and_attrs = parser.get_plugin_arguments(plugin_name, plugin) + for darg, dattr in args_and_attrs: + value = getattr(opts, darg) + plugin_args[plugin][dattr] = value + + main(plugin_args=plugin_args, **vars(opts)) + +if __name__ == "__main__": + main_command_line() diff --git a/dshell/dshellargparse.py b/dshell/dshellargparse.py new file mode 100644 index 0000000..82feaa0 --- /dev/null +++ b/dshell/dshellargparse.py @@ -0,0 +1,40 @@ +""" +This argument parser is almost identical to the Python standard argparse. +This one adds a function to automatically add plugin-specific arguments. +""" + +import argparse + +class DshellArgumentParser(argparse.ArgumentParser): + + def add_plugin_arguments(self, plugin_name, plugin_obj): + """ + add_plugin_arguments(self, plugin_name, plugin_obj) + + Give it the name of the plugin and an instance of the plugin, and + it will automatically create argument entries. + """ + if plugin_obj.optiondict: + group = '{} plugin options'.format(plugin_obj.name) + group = self.add_argument_group(group) + for argname, optargs in plugin_obj.optiondict.items(): + optname = "{}_{}".format(plugin_name, argname) + group.add_argument("--" + optname, dest=optname, **optargs) + + def get_plugin_arguments(self, plugin_name, plugin_obj): + """ + get_plugin_arguments(self, plugin_name, plugin_obj) + + Returns a list of argument names and the attributes they're associated + with. + + e.g. --country_code for the "country" plugin ties to the "code" attr + in the plugin object. Thus, the return would be + [("country_code", "code"), ...] + """ + args_and_attrs = [] + if plugin_obj.optiondict: + for argname in plugin_obj.optiondict.keys(): + optname = "{}_{}".format(plugin_name, argname) + args_and_attrs.append((optname, argname)) + return args_and_attrs diff --git a/dshell/dshellgeoip.py b/dshell/dshellgeoip.py new file mode 100644 index 0000000..f53b257 --- /dev/null +++ b/dshell/dshellgeoip.py @@ -0,0 +1,144 @@ +# -*- coding: utf-8 -*- +""" +A wrapper around GeoIP2 that provides convenience functions for querying and +collecting GeoIP data +""" + +import datetime +import logging +import os +from collections import OrderedDict + +import geoip2.database +import geoip2.errors + +from dshell.util import get_data_path + +class DshellGeoIP(object): + + MAX_CACHE_SIZE = 5000 + + def __init__(self, acc=False, logger=logging.getLogger("dshellgeoip.py")): + self.logger = logger + self.geodir = os.path.join(get_data_path(), 'GeoIP') + self.geoccfile = os.path.join(self.geodir, 'GeoLite2-City.mmdb') + self.geoasnfile = os.path.join(self.geodir, 'GeoLite2-ASN.mmdb') + self.geoccdb = geoip2.database.Reader(self.geoccfile) + self.geoasndb = geoip2.database.Reader(self.geoasnfile) + self.geo_asn_cache = DshellGeoIPCache(max_cache_size=self.MAX_CACHE_SIZE) + self.geo_loc_cache = DshellGeoIPCache(max_cache_size=self.MAX_CACHE_SIZE) + self.acc = acc + + def check_file_dates(self): + "Check the data file age, and log a warning if it's over a year old" + cc_mtime = datetime.datetime.fromtimestamp(os.path.getmtime(self.geoccfile)) + asn_mtime = datetime.datetime.fromtimestamp(os.path.getmtime(self.geoasnfile)) + n = datetime.datetime.now() + year = datetime.timedelta(days=365) + if (n - cc_mtime) > year or (n - asn_mtime) > year: + self.logger.debug("GeoIP data file(s) over a year old, and possibly outdated.") + + def geoip_country_lookup(self, ip): + "Looks up the IP and returns the two-character country code." + location = self.geoip_location_lookup(ip) + return location[0] + + def geoip_asn_lookup(self, ip): + """ + Looks up the IP and returns an ASN string. + Example: + print geoip_asn_lookup("74.125.26.103") + "AS15169 Google LLC" + """ + try: + return self.geo_asn_cache[ip] + except KeyError: + try: + template = "AS{0.autonomous_system_number} {0.autonomous_system_organization}" + asn = template.format(self.geoasndb.asn(ip)) + self.geo_asn_cache[ip] = asn + return asn + except geoip2.errors.AddressNotFoundError: + return None + + def geoip_location_lookup(self, ip): + """ + Looks up the IP and returns a tuple containing country code, latitude, + and longitude. + """ + try: + return self.geo_loc_cache[ip] + except KeyError: + try: + location = self.geoccdb.city(ip) + # Get country code based on order of importance + # 1st: Country that owns an IP address registered in another + # location (e.g. military bases in foreign countries) + # 2nd: Country in which the IP address is registered + # 3rd: Physical country where IP address is located + # https://dev.maxmind.com/geoip/geoip2/whats-new-in-geoip2/#Country_Registered_Country_and_Represented_Country + # Handle flag from plugin optional args to enable all 3 country codes + if self.acc: + try: + cc = "{}/{}/{}".format(location.represented_country.iso_code, + location.registered_country.iso_code, + location.country.iso_code) + cc = cc.replace("None", "--") + + except KeyError: + pass + else: + cc = (location.represented_country.iso_code or + location.registered_country.iso_code or + location.country.iso_code or + '--') + + location = ( + cc, + location.location.latitude, + location.location.longitude + ) + self.geo_loc_cache[ip] = location + return location + except geoip2.errors.AddressNotFoundError: + # Handle flag from plugin optional args to enable all 3 country codes + if self.acc: + location = ("--/--/--", None, None) + else: + location = ("--", None, None) + self.geo_loc_cache[ip] = location + return location + +class DshellFailedGeoIP(object): + "Class used in place of DshellGeoIP if GeoIP database files are not found." + + def __init__(self): + self.geodir = os.path.join(get_data_path(), 'GeoIP') + self.geoccdb = None + self.geoasndb = None + + def check_file_dates(self): + pass + + def geoip_country_lookup(self, ip): + return "??" + + def geoip_asn_lookup(self, ip): + return None + + def geoip_location_lookup(self, ip): + return ("??", None, None) + +class DshellGeoIPCache(OrderedDict): + "A cache for storing recent IP lookups to improve performance." + def __init__(self, *args, **kwargs): + self.max_cache_size = kwargs.pop("max_cache_size", 500) + OrderedDict.__init__(self, *args, **kwargs) + + def __setitem__(self, key, value): + OrderedDict.__setitem__(self, key, value) + self.check_max_size() + + def check_max_size(self): + while len(self) > self.max_cache_size: + self.popitem(last=False) diff --git a/dshell/dshelllist.py b/dshell/dshelllist.py new file mode 100644 index 0000000..450f14e --- /dev/null +++ b/dshell/dshelllist.py @@ -0,0 +1,55 @@ +""" +A library containing functions for generating lists of important modules. +These are mostly used in decode.py and in unit tests +""" + +import os +import pkg_resources +from glob import iglob + +from dshell.util import get_plugin_path + +#def get_plugins(plugin_path, logger=None): +def get_plugins(logger=None): + """ + Generate a list of all available plugin modules, either in the + dshell.plugins directory or external packages + """ + plugins = {} + # List of directories above the plugins directory that we don't care about + import_base = get_plugin_path().split(os.path.sep)[:-1] + + # Walk through the plugin path and find any Python modules that aren't + # __init__.py. These are assumed to be plugin modules and will be + # treated as such. + for root, dirs, files in os.walk(get_plugin_path()): + if '__init__.py' in files: + import_path = root.split(os.path.sep)[len(import_base):] + for f in iglob("{}/*.py".format(root)): + name = os.path.splitext(os.path.basename(f))[0] + if name != '__init__': + if name in plugins and logger: + logger.warning("Duplicate plugin name found: {}".format(name)) + module = '.'.join(["dshell"] + import_path + [name]) + plugins[name] = module + + # Next, try to discover additional plugins installed externally. + # Uses entry points in setup.py files. + for ep_plugin in pkg_resources.iter_entry_points("dshell_plugins"): + if ep_plugin.name in plugins and logger: + logger.warning("Duplicate plugin name found: {}".format(name)) + plugins[ep_plugin.name] = ep_plugin.module_name + + return plugins + +def get_output_modules(output_module_path, logger=None): + """ + Generate a list of all available output modules under an output_module_path + """ + modules = [] + for f in iglob("{}/*.py".format(output_module_path)): + name = os.path.splitext(os.path.basename(f))[0] + if name != '__init__' and name != 'output': + # Ignore __init__ and the base output.py module + modules.append(name) + return modules diff --git a/dshell/output/__init__.py b/dshell/output/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/dshell/output/alertout.py b/dshell/output/alertout.py new file mode 100644 index 0000000..e977599 --- /dev/null +++ b/dshell/output/alertout.py @@ -0,0 +1,15 @@ +""" +This output module is used to display single-line alerts + +It inherits nearly everything from the base Output class, and only resets the +_DEFAULT_FORMAT to a more expressive format. +""" + +from dshell.output.output import Output + +class AlertOutput(Output): + "A class that provides a default format for printing a single-line alert" + _DESCRIPTION = "Default format for printing a single-line alert" + _DEFAULT_FORMAT = "[%(plugin)s] %(ts)s %(sip)16s:%(sport)-5s %(dir_arrow)s %(dip)16s:%(dport)-5s ** %(data)s **\n" + +obj = AlertOutput diff --git a/dshell/output/colorout.py b/dshell/output/colorout.py new file mode 100644 index 0000000..04fb17d --- /dev/null +++ b/dshell/output/colorout.py @@ -0,0 +1,88 @@ +""" +Generates packet or reconstructed stream output with ANSI color codes. + +Based on output module originally written by amm +""" + +from dshell.output.output import Output +import dshell.core +import dshell.util + +class ColorOutput(Output): + _DESCRIPTION = "Reconstructed output with ANSI color codes" + _PACKET_FORMAT = """Packet %(counter)s (%(proto)s) +Start: %(ts)s +%(sip)16s:%(sport)6s -> %(dip)16s:%(dport)6s (%(bytes)s bytes) + +%(data)s + +""" + _CONNECTION_FORMAT = """Connection %(counter)s (%(protocol)s) +Start: %(starttime)s +End: %(endtime)s +%(clientip)16s:%(clientport)6s -> %(serverip)16s:%(serverport)6s (%(clientbytes)s bytes) +%(serverip)16s:%(serverport)6s -> %(clientip)16s:%(clientport)6s (%(serverbytes)s bytes) + +%(data)s + +""" + _DEFAULT_FORMAT = _PACKET_FORMAT + + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self.counter = 1 + self.colors = { + 'cs': '31', # client-to-server is red + 'sc': '32', # server-to-client is green + '--': '34', # everything else is blue + } # TODO configurable for color-blind users? + self.delim = "\n\n" + self.hexmode = kwargs.get('hex', False) + self.format_is_set = False + + def write(self, *args, **kwargs): + if not self.format_is_set: + if 'clientip' in kwargs: + self.set_format(self._CONNECTION_FORMAT) + else: + self.set_format(self._PACKET_FORMAT) + self.format_is_set = True + + # a template string for data output + colorformat = "\x1b[%sm%s\x1b[0m" + + # Iterate over the args and try to parse out any raw data strings + rawdata = [] + for arg in args: + if type(arg) == dshell.core.Blob: + if arg.data: + rawdata.append((arg.data, arg.direction)) + elif type(arg) == dshell.core.Connection: + for blob in arg.blobs: + if blob.data: + rawdata.append((blob.data, blob.direction)) + elif type(arg) == dshell.core.Packet: + rawdata.append((arg.pkt.body_bytes, kwargs.get('direction', '--'))) + else: + rawdata.append((arg, kwargs.get('direction', '--'))) + + # Clean up the rawdata into something more presentable + if self.hexmode: + cleanup_func = dshell.util.hex_plus_ascii + else: + cleanup_func = dshell.util.printable_text + for k, v in enumerate(rawdata): + newdata = cleanup_func(v[0]) + rawdata[k] = (newdata, v[1]) + + # Convert the raw data strings into color-coded output + data = [] + for arg in rawdata: + datastring = colorformat % (self.colors.get(arg[1], '0'), arg[0]) + data.append(datastring) + + super().write(counter=self.counter, *data, **kwargs) + self.counter += 1 + +obj = ColorOutput diff --git a/dshell/output/csvout.py b/dshell/output/csvout.py new file mode 100644 index 0000000..e23e864 --- /dev/null +++ b/dshell/output/csvout.py @@ -0,0 +1,61 @@ +""" +This output module converts plugin output into a CSV format +""" + +import csv +from dshell.output.output import Output + +class CSVOutput(Output): + """ + Takes specified fields provided to the write function and print them in + a CSV format. + + Delimiter can be set with --oarg delim= + + A header row can be printed with --oarg header + + Additional fields can be included with --oarg fields=field1,field2,field3 + + Note: Field names much match the variable names in the plugin + """ + + # TODO refine plugin to do things like wrap quotes around long strings + + _DEFAULT_FIELDS = ['plugin', 'ts', 'sip', 'sport', 'dip', 'dport', 'data'] + _DEFAULT_DELIM = ',' + _DESCRIPTION = "CSV format output" + + def __init__(self, *args, **kwargs): + self.delimiter = kwargs.get('delim', self._DEFAULT_DELIM) + if self.delimiter == 'tab': + self.delimiter = '\t' + + self.use_header = kwargs.get("header", False) + + self.fields = list(self._DEFAULT_FIELDS) + exfields = kwargs.get("fields", "") + for field in exfields.split(','): + self.fields.append(field) + + super().__init__(**kwargs) + + self.set_format() + + def set_format(self, _=None): + "Set the format to a CSV list of fields" + columns = [] + for f in self.fields: + if f: + columns.append(f) + if self.extra: + columns.append("extra") + fmt = self.delimiter.join('%%(%s)r' % f for f in columns) + fmt += "\n" + super().set_format(fmt) + + def setup(self): + if self.use_header: + self.fh.write(self.delimiter.join([f for f in self.fields]) + "\n") + + +obj = CSVOutput diff --git a/dshell/output/elasticout.py b/dshell/output/elasticout.py new file mode 100644 index 0000000..9cec05d --- /dev/null +++ b/dshell/output/elasticout.py @@ -0,0 +1,74 @@ +""" +This output module converts plugin output into JSON and indexes it into +an Elasticsearch datastore + +NOTE: This module requires the third-party 'elasticsearch' Python module +""" + +import ipaddress +import json + +from elasticsearch import Elasticsearch + +import dshell.output.jsonout + +class ElasticOutput(dshell.output.jsonout.JSONOutput): + """ + Elasticsearch output module + Use with --output=elasticsearchout + + It is recommended that it be run with some options set: + host: server hosting the database (localhost) + port: HTTP port listening (9200) + index: name of index storing results ("dshell") + type: the type for each alert ("alerts") + + Example use: + decode --output=elasticout --oargs="index=dshellalerts" --oargs="type=netflowout" -d netflow ~/pcap/example.pcap + """ + + _DESCRIPTION = "Automatically insert data into an elasticsearch instance" + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs.copy()) + + self.options = {} + self.options['host'] = kwargs.get('host', 'localhost') + self.options['port'] = int(kwargs.get('port', 9200)) + self.options['index'] = kwargs.get('index', 'dshell') + self.options['type'] = kwargs.get('type', 'alerts') + + self.es = Elasticsearch([self.options['host']], port=self.options['port']) + + def write(self, *args, **kwargs): + "Converts alert's keyword args to JSON and indexes it into Elasticsearch datastore." + if args and 'data' not in kwargs: + kwargs['data'] = self.delim.join(map(str, args)) + + # Elasticsearch can't handle IPv6 (at time of writing) + # Just delete the ints and expand the string notation. + # Hopefully, it will be possible to perform range searches on this + # consistent IP string format. + try: + del kwargs['dipint'] + except KeyError: + pass + try: + del kwargs['sipint'] + except KeyError: + pass + try: + kwargs['dip'] = ipaddress.ip_address(kwargs['dip']).exploded + except KeyError: + pass + try: + kwargs['sip'] = ipaddress.ip_address(kwargs['sip']).exploded + except KeyError: + pass + + jsondata = json.dumps(kwargs, ensure_ascii=self.ensure_ascii, default=self.json_default) +# from pprint import pprint +# pprint(jsondata) + self.es.index(index=self.options['index'], doc_type=self.options['type'], body=jsondata) + +obj = ElasticOutput diff --git a/dshell/output/htmlout.py b/dshell/output/htmlout.py new file mode 100644 index 0000000..57ab4b3 --- /dev/null +++ b/dshell/output/htmlout.py @@ -0,0 +1,127 @@ +""" +Generates packet or reconstructed stream output as a HTML page. + +Based on colorout module originally written by amm +""" + +from dshell.output.output import Output +import dshell.util +import dshell.core +from xml.sax.saxutils import escape + +class HTMLOutput(Output): + _DESCRIPTION = "HTML format output" + _PACKET_FORMAT = """

      Packet %(counter)s (%(protocol)s)

      Start: %(ts)s +%(sip)s:%(sport)s -> %(dip)s:%(dport)s (%(bytes)s bytes) +

      +%(data)s +""" + _CONNECTION_FORMAT = """

      Connection %(counter)s (%(protocol)s)

      Start: %(starttime)s +End: %(endtime)s +%(clientip)s:%(clientport)s -> %(serverip)s:%(serverport)s (%(clientbytes)s bytes) +%(serverip)s:%(serverport)s -> %(clientip)s:%(clientport)s (%(serverbytes)s bytes) +

      +%(data)s +""" + _DEFAULT_FORMAT = _PACKET_FORMAT + + _HTML_HEADER = """ + + + + Dshell Output + + + +""" + + _HTML_FOOTER = """ + + +""" + + def __init__(self, *args, **kwargs): + "Can be called with an optional 'hex' argument to display output in hex" + super().__init__(*args, **kwargs) + self.counter = 1 + self.colors = { + 'cs': 'red', # client-to-server is red + 'sc': 'green', # server-to-client is green + '--': 'blue', # everything else is blue + } + self.delim = "
      " + self.hexmode = kwargs.get('hex', False) + self.format_is_set = False + + def setup(self): + self.fh.write(self._HTML_HEADER) + + def write(self, *args, **kwargs): + if not self.format_is_set: + if 'clientip' in kwargs: + self.set_format(self._CONNECTION_FORMAT) + else: + self.set_format(self._PACKET_FORMAT) + self.format_is_set = True + + # a template string for data output + colorformat = '%s' + + # Iterate over the args and try to parse out any raw data strings + rawdata = [] + for arg in args: + if type(arg) == dshell.core.Blob: + if arg.data: + rawdata.append((arg.data, arg.direction)) + elif type(arg) == dshell.core.Connection: + for blob in arg.blobs: + if blob.data: + rawdata.append((blob.data, blob.direction)) + elif type(arg) == dshell.core.Packet: + rawdata.append((arg.pkt.body_bytes, kwargs.get('direction', '--'))) + else: + rawdata.append((arg, kwargs.get('direction', '--'))) + + # Clean up the rawdata into something more presentable + if self.hexmode: + cleanup_func = dshell.util.hex_plus_ascii + else: + cleanup_func = dshell.util.printable_text + for k, v in enumerate(rawdata): + newdata = cleanup_func(v[0]) + newdata = escape(newdata) + rawdata[k] = (newdata, v[1]) + + # Convert the raw data strings into color-coded output + data = [] + for arg in rawdata: + datastring = colorformat % (self.colors.get(arg[1], ''), arg[0]) + data.append(datastring) + + super().write(counter=self.counter, *data, **kwargs) + self.counter += 1 + + def close(self): + self.fh.write(self._HTML_FOOTER) + Output.close(self) + +obj = HTMLOutput diff --git a/dshell/output/jsonout.py b/dshell/output/jsonout.py new file mode 100644 index 0000000..49014d9 --- /dev/null +++ b/dshell/output/jsonout.py @@ -0,0 +1,44 @@ +""" +This output module converts plugin output into JSON +""" + +from datetime import datetime +import json +from dshell.output.output import Output + +class JSONOutput(Output): + """ + Converts arguments for every write into JSON + Can be called with ensure_ascii=True to pass flag on to the json module. + """ + _DEFAULT_FORMAT = "%(jsondata)s\n" + _DESCRIPTION = "JSON format output" + + def __init__(self, *args, **kwargs): + self.ensure_ascii = kwargs.get('ensure_ascii', False) + super().__init__(*args, **kwargs) + + def write(self, *args, **kwargs): + if self.extra: + # JSONOutput does not make use of the --extra flag, so disable it + # before printing output + self.extra = False + if args and 'data' not in kwargs: + kwargs['data'] = self.delim.join(map(str, args)) + jsondata = json.dumps(kwargs, ensure_ascii=self.ensure_ascii, default=self.json_default) + super().write(jsondata=jsondata) + + def json_default(self, obj): + """ + JSON serializer for objects not serializable by default json code + https://stackoverflow.com/a/22238613 + """ + if isinstance(obj, datetime): + serial = obj.strftime(self.timeformat) + return serial + if isinstance(obj, bytes): + serial = repr(obj) + return serial + raise TypeError ("Type not serializable ({})".format(str(type(obj)))) + +obj = JSONOutput diff --git a/dshell/output/netflowout.py b/dshell/output/netflowout.py new file mode 100644 index 0000000..48469ca --- /dev/null +++ b/dshell/output/netflowout.py @@ -0,0 +1,86 @@ +""" +This output module is used for generating flow-format output +""" + +from dshell.output.output import Output +from datetime import datetime + +class NetflowOutput(Output): + """ + A class for printing connection information for pcap + + Output can be grouped by setting the group flag to a field or fields + separated by a forward-slash + For example: + --output=netflowout --oarg="group=clientip/serverip" + """ + + _DESCRIPTION = "Flow (connection overview) format output" + # Define two types of formats: + # Those for plugins handling individual packets (not really helpful) + _PACKET_FORMAT = "%(ts)s %(sip)16s -> %(dip)16s (%(sipcc)s -> %(dipcc)s) %(protocol)5s %(sport)6s %(dport)6s %(bytes)7s %(msg)s\n" + _PACKET6_FORMAT = "%(ts)s %(sip)40s -> %(dip)40s (%(sipcc)s -> %(dipcc)s) %(protocol)5s %(sport)6s %(dport)6s %(bytes)7s %(msg)s\n" + # And those plugins handling full connections (more useful and common) + _CONNECTION_FORMAT = "%(starttime)s %(clientip)16s -> %(serverip)16s (%(clientcc)s -> %(servercc)s) %(protocol)5s %(clientport)6s %(serverport)6s %(clientpackets)5s %(serverpackets)5s %(clientbytes)7s %(serverbytes)7s %(duration)-.4fs %(data)s\n" + _CONNECTION6_FORMAT = "%(starttime)s %(clientip)40s -> %(serverip)40s (%(clientcc)s -> %(servercc)s) %(protocol)5s %(clientport)6s %(serverport)6s %(clientpackets)5s %(serverpackets)5s %(clientbytes)7s %(serverbytes)7s %(duration)-.4fs %(data)s\n" + # TODO decide if IPv6 formats are necessary, and how to switch between them + # and IPv4 formats + # Default to packets since those fields are in both types of object + _DEFAULT_FORMAT = _PACKET_FORMAT + + def __init__(self, *args, **kwargs): + # Are we grouping the results, and by what fields? + if 'group' in kwargs: + self.group = True + self.group_fields = kwargs['group'].split('/') + else: + self.group = False + self.group_cache = {} # results will be stored here, if grouping + self.format_is_set = False + Output.__init__(self, *args, **kwargs) + + def write(self, *args, **kwargs): + # Change output format depending on if we're handling a connection or + # a single packet + if not self.format_is_set: + if "clientip" in kwargs: + self.set_format(self._CONNECTION_FORMAT) + else: + self.set_format(self._PACKET_FORMAT) + self.format_is_set = True + + if self.group: + # If grouping, check if the IP tuple is in the cache already. + # If not, check the reverse of the tuple (i.e. opposite direction) + try: + key = tuple([kwargs[g] for g in self.group_fields]) + except KeyError as e: + self.logger.error("Could not group by key %s" % str(e)) + Output.write(self, *args, **kwargs) + return + if key not in self.group_cache: + rkey = key[::-1] + if rkey in self.group_cache: + key = rkey + else: + self.group_cache[key] = [] + self.group_cache[key].append(kwargs) + else: + # If not grouping, just write out the connection immediately + Output.write(self, *args, **kwargs) + + def close(self): + if self.group: + self.group = False # we're done grouping, so turn it off + for key in sorted(self.group_cache.keys()): + # write header by mapping key index with user's group list + self.fh.write(' '.join([ + '%s=%s' % (self.group_fields[i], key[i]) for i in range(len(self.group_fields))]) + + "\n") + for kw in self.group_cache[key]: + self.fh.write("\t") + Output.write(self, **kw) + self.fh.write("\n") + Output.close(self) + +obj = NetflowOutput diff --git a/dshell/output/output.py b/dshell/output/output.py new file mode 100644 index 0000000..b543ab2 --- /dev/null +++ b/dshell/output/output.py @@ -0,0 +1,247 @@ +""" +Generic Dshell output class(es) + +Contains the base-level Output class that other modules inherit from. +""" + +import logging +import os +import re +import sys +from collections import defaultdict +from datetime import datetime + +class Output(): + """ + Base-level output class + + Arguments: + label : name to use for logging.getLogger(label) + format : 'format string' to override default formatstring for output class + timeformat : 'format string' for datetime representation + delim : set a delimiter for CSV or similar output + nobuffer : true/false to run flush() after every relevant write + noclobber : set to true to avoid overwriting existing files + fh : existing open file handle + file : filename to write to, assuming fh is not defined + mode : mode to open file, assuming fh is not defined (default 'w') + """ + _DEFAULT_FORMAT = "%(data)s\n" + _DEFAULT_TIME_FORMAT = "%Y-%m-%d %H:%M:%S" + _DEFAULT_DELIM = ',' + _DESCRIPTION = "Base output class" + + def __init__(self, *args, **kwargs): + self.logger = logging.getLogger(kwargs.get("label", "dshell")) + + self.format_fields = [] + self.timeformat = kwargs.get('timeformat', self._DEFAULT_TIME_FORMAT) + self.delim = kwargs.get('delim', self._DEFAULT_DELIM) + self.nobuffer = kwargs.get('nobuffer', False) + self.noclobber = kwargs.get('noclobber', False) + self.mode = kwargs.get('mode', 'w') + self.extra = kwargs.get('extra', False) + + self.set_format( kwargs.get('format', self._DEFAULT_FORMAT) ) + + # Set the filehandle for any output + f = None + if 'fh' in kwargs: + self.fh = kwargs['fh'] + return + elif 'file' in kwargs: + f = kwargs['file'] + elif len(args) > 0: + f = args[0] + if f: + if self.noclobber: + f = self.__incrementFilename(f) + self.fh = open(f, self.mode) + else: + self.fh = sys.stdout + + + def reset_fh(self, filename=None, fh=None, mode=None): + """ + Alter the module's open file handle without changing any of the other + settings. Must supply at least a filename or a filehandle (fh). + reset_fh(filename=None, fh=None, mode=None) + """ + if fh: + self.fh = fh + elif filename: + if self.noclobber: + filename = self.__incrementFilename(filename) + if mode: + self.mode = mode + self.fh = open(filename, mode) + else: + self.fh = open(filename, self.mode) + + def set_level(self, lvl): + "Set the logging level. Just a wrapper around logging.setLevel(lvl)." + self.logger.setLevel(lvl) + + def set_format(self, fmt): + "Set the output format to a new format string" + # Use a regular expression to identify all fields that the format will + # populate, based on limited printf-style formatting. + # https://docs.python.org/3/library/stdtypes.html#old-string-formatting + regexmatch = "%\((?P.*?)\)[diouxXeEfFgGcrs]" + self.format_fields = re.findall(regexmatch, fmt) + + self.format = fmt + + def __incrementFilename(self, filename): + """ + Used with the noclobber argument. + Creates a distinct filename by appending a sequence number. + """ + try: + while os.stat(filename): + p = filename.rsplit('-', 1) + try: + p, n = p[0], int(p[1]) + except ValueError: + n = 0 + filename = '-'.join(p + ['%04d' % (int(n) + 1)]) + except OSError: + pass # file not found + return filename + + def setup(self): + """ + Perform any additional setup outside of the standard __init__. + For example, printing header data to the outfile. + """ + pass + + def close(self): + "Close output file, assuming it's not stdout" + if self.fh not in (sys.stdout, sys.stdout.buffer): + self.fh.close() + + def log(self, msg, level=logging.INFO, *args, **kwargs): + """ + Write a message to the log + Passes all args and kwargs thru to logging, except for 'level' + """ + self.logger.log(level, msg, *args, **kwargs) + + def convert(self, *args, **kwargs): + """ + Attempts to convert the args/kwargs into the format defined in + self.format and self.timeformat + """ + # Have the keyword arguments default to empty strings, in the event + # of missing keys for string formatting + outdict = defaultdict(str, **kwargs) + outformat = self.format + extras = [] + + # Convert raw timestamps into a datetime object + if 'ts' in outdict: + try: + outdict['ts'] = datetime.fromtimestamp(float(outdict['ts'])) + outdict['ts'] = outdict['ts'].strftime(self.timeformat) + outdict['starttime'] = datetime.fromtimestamp(float(outdict['starttime'])) + outdict['starttime'] = outdict['starttime'].strftime(self.timeformat) + outdict['endtime'] = datetime.fromtimestamp(float(outdict['endtime'])) + outdict['endtime'] = outdict['endtime'].strftime(self.timeformat) + except TypeError: + pass + except KeyError: + pass + except ValueError: + pass + + # Create directional arrows + if 'dir_arrow' not in outdict: + if outdict.get('direction') == 'cs': + outdict['dir_arrow'] = '->' + elif outdict.get('direction') == 'sc': + outdict['dir_arrow'] = '<-' + else: + outdict['dir_arrow'] = '--' + + # Convert Nones into empty strings. + # If --extra flag used, generate string representing otherwise hidden + # fields. + for key, val in sorted(outdict.items()): + if val is None: + val = '' + outdict[key] = val + if self.extra: + if key not in self.format_fields: + extras.append("%s=%s" % (key, val)) + + # Dump the args into a 'data' field + outdict['data'] = self.delim.join(map(str, args)) + + # Create an optional 'extra' field + if self.extra: + if 'extra' not in self.format_fields: + outformat = outformat[:-1] + " [ %(extra)s ]\n" + outdict['extra'] = ', '.join(extras) + + # Convert the output dictionary into a string that is dumped to the + # output location. + output = outformat % outdict + return output + + def write(self, *args, **kwargs): + "Primary output function. Should be overwritten by subclasses." + line = self.convert(*args, **kwargs) + try: + self.fh.write(line) + if self.nobuffer: + self.fh.flush() + except BrokenPipeError: + pass + + def alert(self, *args, **kwargs): + """ + DEPRECATED + Use the write function of the AlertOutput class + """ + self.write(*args, **kwargs) + + def dump(self, *args, **kwargs): + """ + DEPRECATED + Use the write function of the PCAPOutput class + """ + self.write(*args, **kwargs) + + + +class QueueOutputWrapper(object): + """ + Wraps an instance of any other Output-like object to make its + write function more thread safe. + """ + + def __init__(self, oobject, oqueue): + self.__oobject = oobject + self.__owrite = oobject.write + self.queue = oqueue + self.id = str(self.__oobject) + + def true_write(self, *args, **kwargs): + "Calls the wrapped class's write function. Called from decode.py." + self.__owrite(*args, **kwargs) + + def write(self, *args, **kwargs): + """ + Adds a message to the queue indicating that this wrapper is ready to + run its write function + """ + self.queue.put((self.id, args, kwargs)) + + +############################################################################### + +# The "obj" variable is used in decode.py as a standard name for each output +# module's primary class. It technically imports this variable and uses it to +# construct an instance. +obj = Output diff --git a/dshell/output/pcapout.py b/dshell/output/pcapout.py new file mode 100644 index 0000000..96a7af3 --- /dev/null +++ b/dshell/output/pcapout.py @@ -0,0 +1,64 @@ +""" +This output module generates pcap output when given very specific arguments. +""" + +from dshell.output.output import Output +import struct +import sys + +# TODO get this module to work with ConnectionPlugins + +class PCAPOutput(Output): + "Writes data to a pcap file." + _DESCRIPTION = "Writes data to a pcap file (does not work with connection-based plugins)" + + def __init__(self, *args, **kwargs): + super().__init__(*args, mode='wb', **kwargs) + if self.fh == sys.stdout: + # Switch to a stdout that can handle byte output + self.fh = sys.stdout.buffer + # Since we have to wait until the link-layer type is set, we wait + # until the first write() operation before writing the pcap header + self.header_written = False + + def write(self, *args, **kwargs): + """ + Write a packet to the pcap file. + + Arguments: + pktlen : raw packet length + rawpkt : raw packet data string + ts : timestamp + link_layer_type : link-layer type (optional) (default: 1) + (e.g. 1 for Ethernet, 105 for 802.11, etc.) + """ + # The first time write() is called, the pcap header is written. + # This is to allow the plugin enough time to figure out what the + # link-layer type is for the data. + if not self.header_written: + link_layer_type = kwargs.get('link_layer_type', 1) + # write the header: + # magic_number, version_major, version_minor, thiszone, sigfigs, + # snaplen, link-layer type + self.fh.write( + struct.pack('IHHIIII', 0xa1b2c3d4, 2, 4, 0, 0, 65535, link_layer_type)) + self.header_written = True + + # Attempt to fetch the required fields + pktlen = kwargs.get('pktlen', None) + rawpkt = kwargs.get('rawpkt', None) + ts = kwargs.get('ts', None) + if pktlen is None or rawpkt is None or ts is None: + raise TypeError("PCAPOutput.write() requires at least these arguments to write packet data: pktlen, rawpkt, and ts.\n\tIt is possible this plugin is not configured to handle pcap output.") + + self.fh.write( + struct.pack('II', int(ts), int((ts - int(ts)) * 1000000))) + self.fh.write(struct.pack('II', len(rawpkt), pktlen)) + self.fh.write(rawpkt) + + def close(self): + if self.fh == sys.stdout.buffer: + self.fh = sys.stdout + super().close() + +obj = PCAPOutput diff --git a/dshell/plugins/__init__.py b/dshell/plugins/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/dshell/plugins/dhcp/__init__.py b/dshell/plugins/dhcp/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/dshell/plugins/dhcp/dhcp.py b/dshell/plugins/dhcp/dhcp.py new file mode 100644 index 0000000..3bb3755 --- /dev/null +++ b/dshell/plugins/dhcp/dhcp.py @@ -0,0 +1,102 @@ +""" +DHCP Plugin +""" + +import dshell.core +import dshell.util +from dshell.output.alertout import AlertOutput + +from pypacker.layer4 import udp +from pypacker.layer567 import dhcp + +from struct import unpack + +class DshellPlugin(dshell.core.PacketPlugin): + def __init__(self, **kwargs): + super().__init__(name='dhcp', + description='extract client information from DHCP messages', + longdescription=""" +The dhcp plugin will extract the Transaction ID, Hostname, and +Client ID (MAC address) from every UDP DHCP packet found in the given pcap +using port 67. DHCP uses BOOTP as its transport protocol. +BOOTP assigns port 67 for the 'BOOTP server' and port 68 for the 'BOOTP client'. +This filter pulls DHCP Inform packets. + +Examples: + + General usage: + + decode -d dhcp + + This will display the connection info including the timestamp, + the source IP : source port, destination IP : destination port, + Transaction ID, Client Hostname, and the Client MAC address + in a tabular format. + + + Malware Traffic Analysis Exercise Traffic from 2015-03-03 where a user was hit with an Angler exploit kit: + + We want to find out more about the infected machine, and some of this information can be pulled from DHCP traffic + + decode -d dhcp 2015-03-03-traffic-analysis-exercise.pcap + + OUTPUT: +[dhcp] 2015-03-03 14:05:10 172.16.101.196:68 -> 172.16.101.1:67 ** Transaction ID: 0xba5a2cfe Client ID (MAC): 38:2C:4A:3D:EF:01 Hostname: Gregory-PC ** +[dhcp] 2015-03-03 14:08:40 172.16.101.196:68 -> 255.255.255.255:67 ** Transaction ID: 0x6a482406 Client ID (MAC): 38:2C:4A:3D:EF:01 Hostname: Gregory-PC ** +[dhcp] 2015-03-03 14:10:11 172.16.101.196:68 -> 172.16.101.1:67 ** Transaction ID: 0xe74b17fe Client ID (MAC): 38:2C:4A:3D:EF:01 Hostname: Gregory-PC ** +[dhcp] 2015-03-03 14:12:50 172.16.101.196:68 -> 255.255.255.255:67 ** Transaction ID: 0xd62614a0 Client ID (MAC): 38:2C:4A:3D:EF:01 Hostname: Gregory-PC ** +""", + bpf='(udp and port 67)', + output=AlertOutput(label=__name__), + author='dek', + ) + self.mac_address = None + self.client_hostname = None + self.xid = None + + # A packetHandler is used to ensure that every DHCP packet in the traffic is parsed + def packet_handler(self, pkt): + + # iterate through the layers and find the DHCP layer + dhcp_packet = pkt.pkt.upper_layer + while not isinstance(dhcp_packet, dhcp.DHCP): + try: + dhcp_packet = dhcp_packet.upper_layer + except AttributeError: + # There doesn't appear to be a DHCP layer + return + + # Pull the transaction ID from the packet + self.xid = hex(dhcp_packet.xid) + + # if we have a DHCP INFORM PACKET + if dhcp_packet.op == dhcp.DHCP_OP_REQUEST: + for opt in list(dhcp_packet.opts): + try: + option_code = opt.type + msg_value = opt.body_bytes + except AttributeError: + continue + + # if opt is CLIENT_ID (61) + # unpack the msg_value and reformat the MAC address + if option_code == dhcp.DHCP_OPT_CLIENT_ID: + hardware_type, mac = unpack('B6s', msg_value) + mac = mac.hex().upper() + self.mac_address = ':'.join([mac[i:i+2] for i in range(0, len(mac), 2)]) + + # if opt is HOSTNAME (12) + elif option_code == dhcp.DHCP_OPT_HOSTNAME: + self.client_hostname = msg_value.decode('utf-8') + + # Allow for unknown hostnames + if not self.client_hostname: + self.client_hostname = "" + + if self.xid and self.mac_address: + self.write('Transaction ID: {0:<12} Client ID (MAC): {1:<20} Hostname: {2:<}'.format( + self.xid, self.mac_address, self.client_hostname), **pkt.info(), dir_arrow='->') + return pkt + +if __name__ == "__main__": + print(DshellPlugin()) diff --git a/dshell/plugins/dns/__init__.py b/dshell/plugins/dns/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/dshell/plugins/dns/dns.py b/dshell/plugins/dns/dns.py new file mode 100644 index 0000000..afb9e0b --- /dev/null +++ b/dshell/plugins/dns/dns.py @@ -0,0 +1,174 @@ +""" +Extracts and summarizes DNS queries and responses. +""" + +import dshell.core +from dshell.plugins import dnsplugin +from dshell.output.alertout import AlertOutput + +from pypacker.pypacker import dns_name_decode +from pypacker.layer567 import dns + +import ipaddress + +RESPONSE_ERRORS = { + dns.DNS_RCODE_FORMERR: "FormErr", + dns.DNS_RCODE_SERVFAIL: "ServFail", + dns.DNS_RCODE_NXDOMAIN: "NXDOMAIN", + dns.DNS_RCODE_NOTIMP: "NotImp", + dns.DNS_RCODE_REFUSED: "Refused", + dns.DNS_RCODE_YXDOMAIN: "YXDp,aom", + dns.DNS_RCODE_YXRRSET: "YXRRSet", + dns.DNS_RCODE_NXRRSET: "NXRRSet", + dns.DNS_RCODE_NOTAUTH: "NotAuth", + dns.DNS_RCODE_NOTZONE: "NotZone", +} + +class DshellPlugin(dnsplugin.DNSPlugin): + + def __init__(self, *args, **kwargs): + super().__init__( + name="DNS", + description="Extract and summarize DNS queries/responses", + longdescription=""" +The DNS plugin extracts and summarizes DNS queries and their responses. If +possible, each query is paired with its response(s). + +Possible anomalies can be found using the --dns_show_noanswer, +--dns_only_noanswer, --dns_show_norequest, or --dns_only_norequest flags +(see --help). + +For example, looking for responses that did not come from a request: + decode -d dns --dns_only_norequest + +Additional information for responses can be seen with --dns_country and +--dns_asn to show country codes and ASNs, respectively. These results can be +piped to grep for filtering results. + +For example, to look for all traffic from Germany: + decode -d dns --dns_country |grep "country: DE" + +To look for non-US traffic, try: + decode -d dns --dns_country |grep "country:" |grep -v "country: US" +""", + author="bg/twp", + bpf="udp and port 53", + output=AlertOutput(label=__name__), + optiondict={'show_noanswer': {'action': 'store_true', 'help': 'report unanswered queries alongside other queries'}, + 'show_norequest': {'action': 'store_true', 'help': 'report unsolicited responses alongside other responses'}, + 'only_noanswer': {'action': 'store_true', 'help': 'report only unanswered queries'}, + 'only_norequest': {'action': 'store_true', 'help': 'report only unsolicited responses'}, + 'country': {'action': 'store_true', 'help': 'show country code for returned IP addresses'}, + 'asn': {'action': 'store_true', 'help': 'show ASN for returned IP addresses'}, + } + ) + + def premodule(self): + if self.only_norequest: + self.show_norequest = True + if self.only_noanswer: + self.show_noanswer = True + + + def dns_handler(self, conn, requests, responses): + if self.only_norequest and requests is not None: + return + if self.only_noanswer and responses is not None: + return + if not self.show_norequest and requests is None: + return + if not self.show_noanswer and responses is None: + return + + msg = [] + + # For simplicity, we focus only on the last request if there's more + # than one. + if requests: + request_pkt = requests[-1] + request = request_pkt.pkt.highest_layer + id = request.id + for query in request.queries: + if query.type == dns.DNS_A: + msg.append("A? {}".format(query.name_s)) + elif query.type == dns.DNS_AAAA: + msg.append("AAAA? {}".format(query.name_s)) + elif query.type == dns.DNS_CNAME: + msg.append("CNAME? {}".format(query.name_s)) + elif query.type == dns.DNS_LOC: + msg.append("LOC? {}".format(query.name_s)) + elif query.type == dns.DNS_MX: + msg.append("MX? {}".format(query.name_s)) + elif query.type == dns.DNS_PTR: + msg.append("PTR? {}".format(query.name_s)) + elif query.type == dns.DNS_SRV: + msg.append("SRV? {}".format(query.name_s)) + elif query.type == dns.DNS_TXT: + msg.append("TXT? {}".format(query.name_s)) + else: + request = None + + if responses: + response_pkt = responses[-1] + for response in responses: + rcode = response.rcode + response = response.pkt.highest_layer + id = response.id + # Check for errors in the response code + err = RESPONSE_ERRORS.get(rcode, None) + if err: + msg.append(err) + continue + # Get the response counts + msg.append("{}/{}/{}".format(response.answers_amount, response.authrr_amount, response.addrr_amount)) + # Parse the answers from the response + for answer in response.answers: + if answer.type == dns.DNS_A or answer.type == dns.DNS_AAAA: + msg_fields = {} + msg_format = "A: {ip} (ttl {ttl}s)" + answer_ip = ipaddress.ip_address(answer.address) + msg_fields['ip'] = str(answer_ip) + msg_fields['ttl'] = str(answer.ttl) + if self.country: + msg_fields['country'] = dshell.core.geoip.geoip_country_lookup(msg_fields['ip']) or '--' + msg_format += " (country: {country})" + if self.asn: + msg_fields['asn'] = dshell.core.geoip.geoip_asn_lookup(msg_fields['ip']) + msg_format += " (ASN: {asn})" + msg.append(msg_format.format(**msg_fields)) + # TODO pypacker doesn't really parse CNAMEs out. We try + # to get what we can manually, but keep checking if + # if it gets officially included in pypacker + elif answer.type == dns.DNS_CNAME: + if request: + cname = dnsplugin.basic_cname_decode(request.queries[0].name, answer.address) + else: + cname = dns_name_decode(answer.address) + msg.append('CNAME: {!r}'.format(cname)) + elif answer.type == dns.DNS_LOC: + msg.append("LOC: {!s}".format(answer.address)) + elif answer.type == dns.DNS_MX: + msg.append('MX: {!s}'.format(answer.address)) + elif answer.type == dns.DNS_NS: + msg.append('NS: {!s}'.format(answer.address)) + elif answer.type == dns.DNS_PTR: + ptr = dns_name_decode(answer.address) + msg.append('PTR: {!s}'.format(ptr)) + elif answer.type == dns.DNS_SRV: + msg.append('SRV: {!s}'.format(answer.address)) + elif answer.type == dns.DNS_TXT: + msg.append('TXT: {!s}'.format(answer.address)) + + else: + msg.append("No response") + + msg.insert(0, "ID: {}".format(id)) + msg = ", ".join(msg) + if request: + self.write(msg, **request_pkt.info()) + elif response: + self.write(msg, **response_pkt.info()) + else: + self.write(msg, **conn.info()) + + return conn, requests, responses diff --git a/dshell/plugins/dns/dnscc.py b/dshell/plugins/dns/dnscc.py new file mode 100644 index 0000000..a58a98f --- /dev/null +++ b/dshell/plugins/dns/dnscc.py @@ -0,0 +1,84 @@ +""" +Identifies DNS queries and finds the country code of the record response. +""" + +import dshell.core +from dshell.plugins import dnsplugin +from dshell.output.alertout import AlertOutput + +from pypacker.pypacker import dns_name_decode +from pypacker.layer567 import dns + +import ipaddress + +class DshellPlugin(dnsplugin.DNSPlugin): + + def __init__(self, *args, **kwargs): + super().__init__( + name="DNS Country Code", + description="identify country code of DNS A/AAAA record responses", + bpf="port 53", + author="bg", + output=AlertOutput(label=__name__), + optiondict={ + 'foreign': { + 'action': 'store_true', + 'help': 'report responses in non-US countries' + }, + 'code': { + 'type': str, + 'help': 'filter on a specific country code (ex. US, DE, JP, etc.)' + } + } + ) + + def dns_handler(self, conn, requests, responses): + "pull out the A/AAAA queries from the last DNS request in a connection" + queries = [] + if requests: + request = requests[-1].pkt.highest_layer + id = request.id + for query in request.queries: + if query.type == dns.DNS_A: + queries.append("A? {}".format(query.name_s)) + elif query.type == dns.DNS_AAAA: + queries.append("AAAA? {}".format(query.name_s)) + queries = ', '.join(queries) + + answers = [] + if responses: + for response in responses: + response = response.pkt.highest_layer + id = response.id + for answer in response.answers: + if answer.type == dns.DNS_A: + ip = ipaddress.ip_address(answer.address).compressed + cc = dshell.core.geoip.geoip_country_lookup(ip) or '--' + if self.foreign and (cc == 'US' or cc == '--'): + continue + elif self.code and cc != self.code: + continue + answers.append("A: {} ({}) (ttl: {}s)".format( + ip, cc, answer.ttl)) + elif answer.type == dns.DNS_AAAA: + ip = ipaddress.ip_address(answer.address).compressed + if ip == '::': + cc = '--' + else: + cc = dshell.core.geoip.geoip_country_lookup(ip) or '--' + if self.foreign and (cc == 'US' or cc == '--'): + continue + elif self.code and cc != self.code: + continue + answers.append("AAAA: {} ({}) (ttl: {}s)".format( + ip, cc, answer.ttl)) + answers = ', '.join(answers) + + if answers: + msg = "ID: {}, {} / {}".format(id, queries, answers) + self.write(msg, queries=queries, answers=answers, **conn.info()) + return conn, requests, responses + else: + return + + diff --git a/dshell/plugins/dns/innuendo-dns.py b/dshell/plugins/dns/innuendo-dns.py new file mode 100644 index 0000000..d7fb508 --- /dev/null +++ b/dshell/plugins/dns/innuendo-dns.py @@ -0,0 +1,85 @@ +""" +Proof-of-concept Dshell plugin to detect INNUENDO DNS Channel + +Based on the short marketing video (http://vimeo.com/115206626) the +INNUENDO DNS Channel relies on DNS to communicate with an authoritative +name server. The name server will respond with a base64 encoded TXT +answer. This plugin will analyze DNS TXT queries and responses to +determine if it matches the network traffic described in the video. +There are multiple assumptions (*very poor*) in this detection plugin +but serves as a proof-of-concept detector. This detector has not been +tested against authentic INNUENDO DNS Channel traffic. +""" + + +from dshell.plugins.dnsplugin import DNSPlugin +from dshell.output.alertout import AlertOutput + +from pypacker.layer567 import dns + +import base64 + +class DshellPlugin(DNSPlugin): + """ + Proof-of-concept Dshell plugin to detect INNUENDO DNS Channel + + Usage: decode -d innuendo *.pcap + """ + + def __init__(self): + super().__init__( + name="innuendo-dns", + description="proof-of-concept detector for INNUENDO DNS channel", + bpf="port 53", + author="primalsec", + output=AlertOutput(label=__name__), + ) + + def dns_handler(self, conn, requests, responses): + response = responses[-1] + + query = None + answers = [] + + if requests: + request = requests[-1].pkt.highest_layer + query = request.queries[-1] + # DNS Question, extract query name if it is a TXT record request + if query.type == dns.DNS_TXT: + query = query.name_s + + if responses: + for response in responses: + rcode = response.rcode + response = response.pkt.highest_layer + # DNS Answer with data and no errors + if rcode == dns.DNS_RCODE_NOERR and response.answers: + for answer in response.answers: + if answer.type == dns.DNS_TXT: + answers.append(answer.address) + + if query and answers: + # assumption: INNUENDO will use the lowest level domain for C2 + # example: AAAABBBBCCCC.foo.bar.com -> AAAABBBBCCCC is the INNUENDO + # data + subdomain = query.split('.', 1)[0] + + # weak test based on video observation *very poor assumption* + if subdomain.isupper(): + # check each answer in the TXT response + for answer in answers: + try: + # INNUENDO DNS channel base64 encodes the response, check to see if + # it contains a valid base64 string *poor assumption* + dummy = base64.b64decode(answer) + + self.write('INNUENDO DNS Channel', query, '/', answer, **conn.info()) + + # here would be a good place to decrypt the payload (if you have the keys) + # decrypt_payload( answer ) + except: + return None + return conn, requests, responses + + return None + diff --git a/dshell/plugins/dns/specialips.py b/dshell/plugins/dns/specialips.py new file mode 100644 index 0000000..a5fc4e0 --- /dev/null +++ b/dshell/plugins/dns/specialips.py @@ -0,0 +1,110 @@ +""" +Identifies DNS resolutions that fall into special IP spaces (i.e. private, +reserved, loopback, multicast, link-local, or unspecified). + +When found, it will print an alert for the request/response pair. The alert +will include the type of special IP in parentheses: + (loopback) + (private) + (reserved) + (multicast) + (link-local) + (unspecified) +""" + +from dshell.plugins import dnsplugin +from dshell.output.alertout import AlertOutput + +from pypacker.layer567 import dns + +import ipaddress + + +class DshellPlugin(dnsplugin.DNSPlugin): + + def __init__(self, *args, **kwargs): + super().__init__( + name="special-ips", + description="identify DNS resolutions that fall into special IP (IPv4 and IPv6) spaces (i.e. private, reserved, loopback, multicast, link-local, or unspecified)", + bpf="port 53", + author="dev195", + output=AlertOutput(label=__name__), + longdescription=""" +Identifies DNS resolutions that fall into special IP spaces (i.e. private, +reserved, loopback, multicast, link-local, or unspecified). + +When found, it will print an alert for the request/response pair. The alert +will include the type of special IP in parentheses: + (loopback) + (private) + (reserved) + (multicast) + (link-local) + (unspecified) + +For example, to look for responses with private IPs: + Dshell> decode -d specialips ~/pcap/SkypeIRC.cap |grep "(private)" + [special-ips] 2006-08-25 15:31:06 192.168.1.2:2128 -- 192.168.1.1:53 ** ID: 12579, A? voyager.home., A: 192.168.1.1 (private) (ttl 10000s) ** + +Finding can also be written to a separate pcap file by chaining: + Dshell> decode -d specialips+pcapwriter --pcapwriter_outfile="special-dns.pcap" ~/pcap/example.pcap +""", + ) + + + def dns_handler(self, conn, requests, responses): + """ + Stores the DNS request, then iterates over responses looking for + special IP addresses. If it finds one, it will print an alert for the + request/response pair. + """ + msg = [] + + if requests: + request_pkt = requests[-1] + request = request_pkt.pkt.highest_layer + id = request.id + for query in request.queries: + if query.type == dns.DNS_A: + msg.append("A? {}".format(query.name_s)) + elif query.type == dns.DNS_AAAA: + msg.append("AAAA? {}".format(query.name_s)) + + + if responses: + keep_responses = False + for response in responses: + response = response.pkt.highest_layer + for answer in response.answers: + if answer.type == dns.DNS_A or answer.type == dns.DNS_AAAA: + answer_ip = ipaddress.ip_address(answer.address) + msg_fields = {} + msg_format = "A: {ip} ({type}) (ttl {ttl}s)" + msg_fields['ip'] = str(answer_ip) + msg_fields['ttl'] = str(answer.ttl) + msg_fields['type'] = '' + if answer_ip.is_loopback: + msg_fields['type'] = 'loopback' + keep_responses = True + elif answer_ip.is_private: + msg_fields['type'] = 'private' + keep_responses = True + elif answer_ip.is_reserved: + msg_fields['type'] = 'reserved' + keep_responses = True + elif answer_ip.is_multicast: + msg_fields['type'] = 'multicast' + keep_responses = True + elif answer_ip.is_link_local: + msg_fields['type'] = 'link-local' + keep_responses = True + elif answer_ip.is_unspecified: + msg_fields['type'] = 'unspecified' + keep_responses = True + msg.append(msg_format.format(**msg_fields)) + if keep_responses: + msg.insert(0, "ID: {}".format(id)) + msg = ", ".join(msg) + self.write(msg, **conn.info()) + return conn, requests, responses + diff --git a/dshell/plugins/dnsplugin.py b/dshell/plugins/dnsplugin.py new file mode 100644 index 0000000..48da51b --- /dev/null +++ b/dshell/plugins/dnsplugin.py @@ -0,0 +1,124 @@ +""" +This is a base-level plugin intended to handle DNS lookups and responses + +It inherits from the base ConnectionPlugin and provides a new handler +function: dns_handler(conn, requests, responses) + +It automatically pairs request/response packets by ID and passes them to the +handler for a custom plugin, such as dns.py, to use. +""" + +import dshell.core as dshell + +from pypacker.pypacker import dns_name_decode +from pypacker.layer567 import dns + +import struct + +def basic_cname_decode(request, answer): + """ + DIRTY HACK ALERT + + This function exists to convert DNS CNAME responses into human-readable + strings. pypacker cannot currently convert these, so this one attempts + to do it. However, it is not complete and will only work for the most + common situations (i.e. no pointers, or pointers that only point to the + first request). + + Feed it the bytes (query.name) of the first request and the bytes for the + answer (answer.address) with a CNAME, and it will return the parsed string. + """ + + if b"\xc0" not in answer: + # short-circuit if there is no pointer + return dns_name_decode(answer) + # Get the offset into the question by grabbing the number after \xc0 + # Then, offset the offset by subtracting the query header length (12) + snip_index = answer[answer.index(b"\xc0") + 1] - 12 + # Grab the necessary piece from the request + snip = request[snip_index:] + # Reassemble and return + rebuilt = answer[:answer.index(b"\xc0")] + snip + return dns_name_decode(rebuilt) + +class DNSPlugin(dshell.ConnectionPlugin): + """ + A base-level plugin that overwrites the connection_handler in + ConnectionPlugin. It provides a new handler function: dns_handler. + """ + + def __init__(self, **kwargs): + dshell.ConnectionPlugin.__init__(self, **kwargs) + + def connection_handler(self, conn): + requests = {} + responses = {} + id_to_blob_map = {} + id_to_packets_map = {} + + for blob in conn.blobs: + for pkt in blob.all_packets: + packet = pkt.pkt + if not isinstance(packet.highest_layer, dns.DNS): + # First packet is not DNS, so we don't care + blob.hidden = True + break + + dnsp = packet.highest_layer + id_to_blob_map.setdefault(dnsp.id, []).append(blob) + id_to_packets_map.setdefault(dnsp.id, []).append(pkt) + qr_flag = dnsp.flags >> 15 + rcode = dnsp.flags & 15 + setattr(pkt, 'qr', qr_flag) + setattr(pkt, 'rcode', rcode) +# print("{0:016b}".format(dnsp.flags)) + if qr_flag == dns.DNS_Q: + requests.setdefault(dnsp.id, []).append(pkt) + elif qr_flag == dns.DNS_A: + responses.setdefault(dnsp.id, []).append(pkt) + + all_ids = set(list(requests.keys()) + list(responses.keys())) + keep_connection = False + for id in all_ids: + request_list = requests.get(id, None) + response_list = responses.get(id, None) + dns_handler_out = self.dns_handler(conn, requests=request_list, responses=response_list) + if not dns_handler_out: + # remove packets from connections that dns_handler did not like + for blob in id_to_blob_map[id]: + for pkt in id_to_packets_map[id]: + try: blob.all_packets.remove(pkt) + except ValueError: continue + else: + for blob in id_to_blob_map[id]: + blob.hidden = False + try: + if dns_handler_out and not isinstance(dns_handler_out[0], dshell.Connection): + self.warn("The output from {} dns_handler must be a list with a dshell.Connection as the first element! Chaining plugins from here may not be possible.".format(self.name)) + continue + except TypeError: + self.warn("The output from {} dns_handler must be a list with a dshell.Connection as the first element! Chaining plugins from here may not be possible.".format(self.name)) + continue + keep_connection = True + if keep_connection: + return conn + + def dns_handler(self, conn, requests, responses): + """ + A placeholder. + + Plugins will be able to overwrite this to perform custom activites + on DNS data. + + It takes in a Connection, a list of requests (or None), and a list of + responses (or None). The requests and responses are not intermixed; + the responses in the list correspond to the requests according to ID. + + It should return a list containing the same types of values that came + in as arguments (i.e. return (conn, requests, responses)). This is + mostly a consistency thing, as only the Connection is passed along to + other plugins. + """ + return (conn, requests, responses) + +DshellPlugin = None diff --git a/dshell/plugins/filter/__init__.py b/dshell/plugins/filter/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/dshell/plugins/filter/country.py b/dshell/plugins/filter/country.py new file mode 100644 index 0000000..47f90ec --- /dev/null +++ b/dshell/plugins/filter/country.py @@ -0,0 +1,102 @@ +""" +A filter for connections by IP address country code. Will generally be chained +with other plugins. +""" + +import dshell.core +from dshell.output.netflowout import NetflowOutput + +class DshellPlugin(dshell.core.ConnectionPlugin): + def __init__(self, *args, **kwargs): + super().__init__( + name="Country Filter", + bpf='ip or ip6', + description="filter connections by IP address country code", + longdescription=""" +country: filter connections on geolocation (country code) + +Mandatory option: + + --country_code: specify (2 character) country code to filter on + +Default behavior: + + If either the client or server IP address matches the specified country, + the stream will be included. + +Modifier options: + + --country_neither: Include only streams where neither the client nor the + server IP address matches the specified country. + + --country_both: Include only streams where both the client AND the server + IP addresses match the specified country. + + --country_notboth: Include streams where the specified country is NOT BOTH + the client and server IP. Streams where it is one or + the other may be included. + + --country_alerts: Show alerts for this plugin (default: false) + + +Example: + + decode -d country+pcapwriter traffic.pcap --pcapwriter_outfile=USonly.pcap --country_code US + decode -d country+followstream traffic.pcap --country_code US --country_notboth +""", + author="tp", + output=NetflowOutput(label=__name__), + optiondict={ + 'code': {'type': str, 'help': 'two-char country code', 'metavar':'CC'}, + 'neither': {'action': 'store_true', 'help': 'neither (client/server) is in specified country'}, + 'both': {'action': 'store_true', 'help': 'both (client/server) ARE in specified country'}, + 'notboth': {'action': 'store_true', 'help': 'specified country is not both client and server'}, + 'alerts': {'action': 'store_true', 'default':False, 'help':'have this filter show alerts for matches'} + }, + ) + + def premodule(self): + # Several of the args are mutually exclusive + # Check if more than one is set, and print a warning if so + if (self.neither + self.both + self.notboth) > 1: + self.warn("Can only use one of these args at a time: 'neither', 'both', or 'notboth'") + + def connection_handler(self, conn): + # If no country code specified, pass all traffic through + if not self.code: + return conn + + if self.neither: + if conn.clientcc != self.code and conn.servercc != self.code: + if self.alerts: self.write('neither', **conn.info()) + return conn + else: + return + + elif self.both: + if conn.clientcc == self.code and conn.servercc == self.code: + if self.alerts: self.write('both', **conn.info()) + return conn + else: + return + + elif self.notboth: + if ((conn.clientcc != self.code and conn.servercc == self.code) + or + (conn.clientcc == self.code and conn.servercc != self.code)): + if self.alerts: self.write('notboth', **conn.info()) + return conn + else: + return + + else: + if conn.clientcc == self.code or conn.servercc == self.code: + if self.alerts: self.write('match', **conn.info()) + return conn + + # no match + return None + + +if __name__ == "__main__": + print (DshellPlugin()) diff --git a/dshell/plugins/filter/track.py b/dshell/plugins/filter/track.py new file mode 100644 index 0000000..eeab990 --- /dev/null +++ b/dshell/plugins/filter/track.py @@ -0,0 +1,153 @@ +""" +Only follows connections that match user-provided IP addresses and ports. Is +generally chained with other plugins. +""" + +import dshell.core +from dshell.output.alertout import AlertOutput + +import ipaddress +import sys + +class DshellPlugin(dshell.core.ConnectionPlugin): + def __init__(self, **kwargs): + super().__init__( + name="track", + author="twp,dev195", + description="Only follow connections that match user-provided IP addresses and ports", + longdescription="""Only follow connections that match user-provided IP addresses + +IP addresses can be specified with --track_source and --track_target. +Multiple IPs can be used with commas (e.g. --track_source=192.168.1.1,127.0.0.1). +Ports can be included with IP addresses by joining them with a 'p' (e.g. --track_target=192.168.1.1p80,127.0.0.1). +Ports can be used alone with just a 'p' (e.g. --track_target=p53). +CIDR notation is okay (e.g. --track_source=196.168.0.0/16). + +--track_source : used to limit connections by the IP that initiated the connection (usually the client) +--trace_target : used to limit connections by the IP that received the connection (usually the server) +--track_alerts : used to display optional alerts indicating when a connection starts/ends""", + bpf="ip or ip6", + output=AlertOutput(label=__name__), + optiondict={ + "target": { + "default": [], + "action": "append", + "metavar": "IPpPORT"}, + "source": { + "default": [], + "action": "append", + "metavar": "IPpPORT"}, + "alerts": { + "action": "store_true"} + } + ) + self.sources = [] + self.targets = [] + + def __split_ips(self, input): + """ + Used to split --track_target and --track_source arguments into + list-of-lists used in the connection handler + """ + return_val = [] + for piece in input.split(','): + if 'p' in piece: + ip, port = piece.split('p', 1) + try: + port = int(port) + except ValueError as e: + self.error("Could not parse port number in {!r} - {!s}".format(piece, e)) + sys.exit(1) + if 0 < port > 65535: + self.error("Could not parse port number in {!r} - must be in valid port range".format(piece)) + sys.exit(1) + else: + ip, port = piece, None + if '/' in ip: + try: + ip = ipaddress.ip_network(ip) + except ValueError as e: + self.error("Could not parse CIDR netrange - {!s}".format(e)) + sys.exit(1) + elif ip: + try: + ip = ipaddress.ip_address(ip) + except ValueError as e: + self.error("Could not parse IP address - {!s}".format(e)) + sys.exit(1) + else: + ip = None + return_val.append((ip, port)) + return return_val + + def __check_ips(self, masterip, masterport, checkip, checkport): + "Checks IPs and ports for matches against the user-selected values" + # masterip, masterport are the values selected by the user + # checkip, checkport are the values to be checked against masters + ip_okay = False + port_okay = False + + if masterip is None: + ip_okay = True + elif (isinstance(masterip, (ipaddress.IPv4Network, ipaddress.IPv6Network)) + and checkip in masterip): + ip_okay = True + elif (isinstance(masterip, (ipaddress.IPv4Address, ipaddress.IPv6Address)) + and masterip == checkip): + ip_okay = True + + if masterport is None: + port_okay = True + elif masterport == checkport: + port_okay = True + + if port_okay and ip_okay: + return True + else: + return False + + + def premodule(self): + if self.target: + for tstr in self.target: + self.targets.extend(self.__split_ips(tstr)) + if self.source: + for sstr in self.source: + self.sources.extend(self.__split_ips(sstr)) + self.debug("targets: {!s}".format(self.targets)) + self.debug("sources: {!s}".format(self.sources)) + + def connection_handler(self, conn): + if self.targets: + conn_okay = False + for target in self.targets: + targetip = target[0] + targetport = target[1] + serverip = ipaddress.ip_address(conn.serverip) + serverport = conn.serverport + if self.__check_ips(targetip, targetport, serverip, serverport): + conn_okay = True + break + if not conn_okay: + return + + if self.sources: + conn_okay = False + for source in self.sources: + sourceip = source[0] + sourceport = source[1] + clientip = ipaddress.ip_address(conn.clientip) + clientport = conn.clientport + if self.__check_ips(sourceip, sourceport, clientip, clientport): + conn_okay = True + break + if not conn_okay: + return + + if self.alerts: + self.write("matching connection", **conn.info()) + + return conn + +if __name__ == "__main__": + print(DshellPlugin()) diff --git a/dshell/plugins/flows/__init__.py b/dshell/plugins/flows/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/dshell/plugins/flows/largeflows.py b/dshell/plugins/flows/largeflows.py new file mode 100644 index 0000000..ee40046 --- /dev/null +++ b/dshell/plugins/flows/largeflows.py @@ -0,0 +1,38 @@ +""" +Displays netflows that have at least 1MB transferred, by default. +Megabyte threshold can be updated by the user. +""" + +import dshell.core +from dshell.output.netflowout import NetflowOutput + +class DshellPlugin(dshell.core.ConnectionPlugin): + + def __init__(self): + super().__init__( + name="large-flows", + description="Display netflows that have at least 1MB transferred", + author="bg", + output=NetflowOutput(label=__name__), + optiondict={ + 'size': { + 'type': float, + 'default': 1, + 'metavar': 'SIZE', + 'help': 'number of megabytes transferred (default: 1)'} + } + ) + + def premodule(self): + if self.size <= 0: + self.warn("Cannot have a size that's less than or equal to zero (size: {}). Setting to 1.".format(self.size)) + self.size = 1 + self.min = 1048576 * self.size + self.debug("Input: {}, Final size: {} bytes".format(self.size, self.min)) + + def connection_handler(self, conn): + if conn.clientbytes + conn.serverbytes >= self.min: + self.write(**conn.info()) + return conn + + diff --git a/dshell/plugins/flows/longflows.py b/dshell/plugins/flows/longflows.py new file mode 100644 index 0000000..3bccfc9 --- /dev/null +++ b/dshell/plugins/flows/longflows.py @@ -0,0 +1,38 @@ +""" +Displays netflows that have a duration of at least 5 minutes. +Minute threshold can be updated by the user. +""" + +import dshell.core +from dshell.output.netflowout import NetflowOutput + +class DshellPlugin(dshell.core.ConnectionPlugin): + + def __init__(self): + super().__init__( + name="long-flows", + description="Display netflows that have a duration of at least 5 minutes", + author="bg", + output=NetflowOutput(label=__name__), + optiondict={ + "len": { + "type": float, + "default": 5, + "help": "set minimum connection time to MIN minutes (default: 5)", + "metavar": "MIN", + } + } + ) + + def premodule(self): + if self.len <= 0: + self.warn("Cannot have a time that's less than or equal to zero (size: {}). Setting to 5.".format(self.len)) + self.len = 5 + self.secs = 60 * self.len + + def connection_handler(self, conn): + tdelta = (conn.endtime - conn.starttime).total_seconds() + if tdelta >= self.secs: + self.write(**conn.info()) + return conn + diff --git a/dshell/plugins/flows/netflow.py b/dshell/plugins/flows/netflow.py new file mode 100644 index 0000000..89a30e9 --- /dev/null +++ b/dshell/plugins/flows/netflow.py @@ -0,0 +1,20 @@ +""" +Collects and displays statistics about connections (a.k.a. flow data) +""" + +import dshell.core +from dshell.output.netflowout import NetflowOutput + +class DshellPlugin(dshell.core.ConnectionPlugin): + def __init__(self, *args, **kwargs): + super().__init__( + name="Netflow", + description="Collects and displays statistics about connections", + author="dev195", + bpf="ip or ip6", + output=NetflowOutput(label=__name__), + ) + + def connection_handler(self, conn): + self.write(**conn.info()) + return conn diff --git a/dshell/plugins/flows/reverseflows.py b/dshell/plugins/flows/reverseflows.py new file mode 100644 index 0000000..921458a --- /dev/null +++ b/dshell/plugins/flows/reverseflows.py @@ -0,0 +1,84 @@ +""" +Generate an alert when a client transmits more data than the server. + +Additionally, the user can specify a threshold. This means that an alert +will be generated if the client transmits more than three times as much data +as the server. + +The default threshold value is 3.0, meaning that any client transmits +more than three times as much data as the server will generate an alert. + +Examples: +1) decode -d reverse-flow + Generates an alert for client transmissions that are three times + greater than the server transmission. + +2) decode -d reverse-flow --reverse-flow_threshold 61 + Generates an alert for all client transmissions that are 61 times + greater than the server transmission + +3) decode -d reverse-flow --reverse-flow_threshold 61 --reverse-flow_zero + Generates an alert for all client transmissions that are 61 times greater + than the server transmission. +""" + +import dshell.core +from dshell.output.alertout import AlertOutput + +class DshellPlugin(dshell.core.ConnectionPlugin): + + def __init__(self): + super().__init__( + name="reverse-flows", + description="Generate an alert if the client transmits more data than the server", + author="me", + bpf="tcp or udp", + output=AlertOutput(label=__name__), + optiondict={ + 'threshold': {'type':float, 'default':3.0, + 'help':'Alerts if client transmits more than threshold times the data of the server'}, + 'minimum': {'type':int, 'default':0, + 'help':'alert on client transmissions larger than min bytes [default: 0]'}, + 'zero': {'action':'store_true', 'default':False, + 'help':'alert if the server transmits zero bytes [default: false]'}, + }, + longdescription=""" +Generate an alert when a client transmits more data than the server. + +Additionally, the user can specify a threshold. This means that an alert +will be generated if the client transmits more than three times as much data +as the server. + +The default threshold value is 3.0, meaning that any client transmits +more than three times as much data as the server will generate an alert. + +Examples: +1) decode -d reverse-flow + Generates an alert for client transmissions that are three times + greater than the server transmission. + +2) decode -d reverse-flow --reverse-flow_threshold 61 + Generates an alert for all client transmissions that are 61 times + greater than the server transmission + +3) decode -d reverse-flow --reverse-flow_threshold 61 --reverse-flow_zero + Generates an alert for all client transmissions that are 61 times greater + than the server transmission. + """, + ) + + def premodule(self): + if self.threshold < 0: + self.warn("Cannot have a negative threshold. Defaulting to 3.0. (threshold: {0})".format(self.threshold)) + self.threshold = 3.0 + elif not self.threshold: + self.warn("Threshold not set. Displaying all client-server transmissions (threshold: {0})".format(self.threshold)) + + def connection_handler(self, conn): + if conn.clientbytes < self.minimum: + return + + if self.zero or (conn.serverbytes and float(conn.clientbytes)/conn.serverbytes > self.threshold): + self.write('client sent {:>6.2f} more than the server'.format(conn.clientbytes/float(conn.serverbytes)), **conn.info(), dir_arrow="->") + return conn + diff --git a/dshell/plugins/flows/toptalkers.py b/dshell/plugins/flows/toptalkers.py new file mode 100644 index 0000000..b26f2df --- /dev/null +++ b/dshell/plugins/flows/toptalkers.py @@ -0,0 +1,83 @@ +""" +Finds the top-talkers in a file or on an interface based on byte count. +""" + +import dshell.core +from dshell.output.alertout import AlertOutput +from dshell.util import human_readable_filesize + +class DshellPlugin(dshell.core.ConnectionPlugin): + + def __init__(self, *args, **kwargs): + super().__init__( + name="Top Talkers", + description="Find top-talkers based on byte count", + author="dev195", + bpf="tcp or udp", + output=AlertOutput(label=__name__), + optiondict={ + "top_x": { + "type": int, + "default": 20, + "help": "Only display the top X results (default: 20)", + "metavar": "X" + }, + "total": { + "action": "store_true", + "help": "Sum byte counts from both directions instead of separate entries for individual directions" + }, + "h": { + "action": "store_true", + "help": "Print byte counts in human-readable format" + } + }, + longdescription=""" +Finds top 20 connections with largest transferred byte count. + +Can be configured to display an arbitrary Top X list with arguments. + +Does not pass connections down plugin chain. +""" + ) + + def premodule(self): + """ + Initialize a list to hold the top X talkers + Format of each entry: + (bytes, direction, Connection object) + """ + self.top_talkers = [(0, '---', None)] + + def connection_handler(self, conn): + if self.total: + # total up the client and server bytes + self.__process_bytes(conn.clientbytes + conn.serverbytes, '<->', conn) + else: + # otherwise, treat client and server bytes separately + self.__process_bytes(conn.clientbytes, '-->', conn) + self.__process_bytes(conn.serverbytes, '<--', conn) + + def postmodule(self): + "Iterate over the entries in top_talkers list and print them" + for bytecount, direction, conn in self.top_talkers: + if conn is None: + break + if self.h: + byte_display = human_readable_filesize(bytecount) + else: + byte_display = "{} B".format(bytecount) + msg = "client {} server {}".format(direction, byte_display) + self.write(msg, **conn.info(), dir_arrow="->") + + def __process_bytes(self, bytecount, direction, conn): + """ + Check if the bytecount for a connection belongs in top_talkers + If so, insert it into the list and pop off the lowest entry + """ + for i, oldbytecount in enumerate(self.top_talkers): + if bytecount >= oldbytecount[0]: + self.top_talkers.insert(i, (bytecount, direction, conn)) + break + + while len(self.top_talkers) > self.top_x: + self.top_talkers.pop(-1) diff --git a/dshell/plugins/ftp/__init__.py b/dshell/plugins/ftp/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/dshell/plugins/ftp/ftp.py b/dshell/plugins/ftp/ftp.py new file mode 100644 index 0000000..29328f2 --- /dev/null +++ b/dshell/plugins/ftp/ftp.py @@ -0,0 +1,352 @@ +""" +Goes through TCP connections and tries to find FTP control channels and +associated data channels. Optionally, it will write out any file data it +sees into a separate directory. + +If a data connection is seen, it prints a message indicating the user, pass, +and file requested. If the --ftp_dump flag is set, it also dumps the file into the +--ftp_outdir directory. +""" + +import dshell.core +import dshell.util +from dshell.output.alertout import AlertOutput + +import os +import re +import sys + +# constants for channel type +CTRL_CONN = 0 +DATA_CONN = 1 + +class DshellPlugin(dshell.core.ConnectionPlugin): + + def __init__(self): + super().__init__( + name="ftp", + description="alerts on FTP traffic and, optionally, rips files", + longdescription=""" +Goes through TCP connections and tries to find FTP control channels and +associated data channels. Optionally, it will write out any file data it +sees into a separate directory. + +If a data connection is seen, it prints a message indicating the user, pass, +and file requested. If the --ftp_dump flag is set, it also dumps the file into the +--ftp_outdir directory. +""", + author="amm,dev195", + bpf="tcp", + output=AlertOutput(label=__name__), + optiondict={ + "ports": { + 'help': 'comma-separated list of ports to watch for control connections (default: 21)', + 'metavar': 'PORT,PORT,PORT,[...]', + 'default': '21'}, + "dump": { + 'action': 'store_true', + 'help': 'dump files from stream'}, + "outdir": { + 'help': 'directory to write output files (default: "ftpout")', + 'metavar': 'DIRECTORY', + 'default': 'ftpout'} + } + ) + + def __update_bpf(self): + """ + Dynamically change the BPF to allow processing of data transfer + channels. + """ + dynfilters = [] + for conn, metadata in self.conns.items(): + try: + dynfilters += ["(host %s and host %s)" % metadata["tempippair"]] + except (KeyError, TypeError): + continue + for a, p in self.data_channel_map.keys(): + dynfilters += ["(host %s and port %d)" % (a, p)] + self.bpf = "(%s) and ((%s)%s)" % ( + self.original_bpf, + " or ".join( "port %d" % p for p in self.control_ports ), + " or " + " or ".join(dynfilters) if dynfilters else "" + ) + self.recompile_bpf() + + def premodule(self): + # dictionary containing metadata for connections + self.conns = {} + # dictionary mapping data channels (host, port) to their control channels + self.data_channel_map = {} + # ports used for control channels + self.control_ports = set() + # Original BPF without manipulation + self.original_bpf = self.bpf + # set control ports using user-provided info + for p in self.ports.split(','): + try: + self.control_ports.add(int(p)) + except ValueError as e: + self.error("{!r} is not a valid port. Skipping.".format(p)) + if not self.control_ports: + self.error("Could not find any control ports. At least one must be set for this plugin.") + sys.exit(1) + + # create output directory + # break if it cannot be created + if self.dump and not os.path.exists(self.outdir): + try: + os.makedirs(self.outdir) + except (IOError, OSError) as e: + self.error("Could not create output directory: {!r}: {!s}" + .format(self.outdir, e)) + sys.exit(1) + + def connection_init_handler(self, conn): + # Create metadata containers for any new connections + if conn.serverport in self.control_ports: + self.conns[conn.addr] = { + 'mode': CTRL_CONN, + 'user': '', + 'pass': '', + 'path': [], + 'datachan': None, + 'lastcommand': '', + 'tempippair': None, + 'filedata': None, + 'file': ['', '', ''] + } + elif self.dump and (conn.clientip, conn.clientport) in self.data_channel_map: + self.conns[conn.addr] = { + 'mode': DATA_CONN, + 'ctrlchan': self.data_channel_map[(conn.clientip, conn.clientport)], + 'filedata': None + } + elif self.dump and (conn.serverip, conn.serverport) in self.data_channel_map: + self.conns[conn.addr] = { + 'mode': DATA_CONN, + 'ctrlchan': self.data_channel_map[(conn.serverip, conn.serverport)], + 'filedata': None + } + elif self.dump: + # This is a data connection with an unknown control connection. It + # may be a passive mode transfer without known port info, yet. + self.conns[conn.addr] = { + 'mode': DATA_CONN, + 'ctrlchan': None, + 'filedata': None + } + + def connection_close_handler(self, conn): + # After data channel closes, store file content in control channel's + # 'filedata' field. + # Control channel will write it to disk after it determines the + # filename. + try: + info = self.conns[conn.addr] + except KeyError: + return + + if self.dump and info['mode'] == DATA_CONN: + # find the associated control channel + if info['ctrlchan'] == None: + if (conn.clientip, conn.clientport) in self.data_channel_map: + info['ctrlchan'] = self.data_channel_map[(conn.clientip, conn.clientport)] + if (conn.serverip, conn.serverport) in self.data_channel_map: + info['ctrlchan'] = self.data_channel_map[(conn.serverip, conn.serverport)] + try: + ctrlchan = self.conns[info['ctrlchan']] + except KeyError: + return + # add data to control channel dictionary + for blob in conn.blobs: + if ctrlchan['filedata']: + ctrlchan['filedata'] += blob.data + else: + ctrlchan['filedata'] = blob.data + # update port list and data channel knowledge + if (conn.serverip, conn.serverport) == ctrlchan['datachan']: + del self.data_channel_map[ctrlchan['datachan']] + ctrlchan['datachan'] = None + self.__update_bpf() + if (conn.clientip, conn.clientport) == ctrlchan['datachan']: + del self.data_channel_map[ctrlchan['datachan']] + ctrlchan['datachan'] = None + self.__update_bpf() + del self.conns[conn.addr] + + elif info['mode'] == CTRL_CONN: + # clear control channels if they've been alerted on + if info['file'] == None: + del self.conns[conn.addr] + + def postmodule(self): + for addr, info in self.conns.items(): + if self.dump and 'filedata' in info and info['filedata']: + origname = info['file'][0] + '_' + os.path.join(*info['file'][1:3]) + outname = dshell.util.gen_local_filename(self.outdir, origname) + with open(outname, 'wb') as fh: + fh.write(info['filedata']) + numbytes = len(info['filedata']) + info['filedata'] = None + info['outfile'] = outname + msg = 'User: %s, Pass: %s, %s File: %s (Incomplete: %d bytes written to %s)' % (info['user'], info['pass'], info['file'][0], os.path.join(*info['file'][1:3]), numbytes, os.path.basename(outname)) + self.write(msg, **info) + + + def blob_handler(self, conn, blob): + try: + info = self.conns[conn.addr] + except KeyError: + # connection was not initialized correctly + # set the blob to hidden and move on + blob.hidden = True + return + + if info['mode'] == DATA_CONN: + return conn, blob + + try: + data = blob.data + data = data.decode('ascii') + except UnicodeDecodeError as e: + # Could not convert command data to readable ASCII + blob.hidden = True + return + + if blob.direction == 'cs': + # client-to-server: try and get the command issued + if ' ' not in data.rstrip(): + command = data.rstrip() + param = '' + else: + command, param = data.rstrip().split(' ', 1) + command = command.upper() + info['lastcommand'] = command + + if command == 'USER': + info['user'] = param + + elif command == 'PASS': + info['pass'] = param + + elif command == 'CWD': + info['path'].append(param) + + elif command == 'PASV' or command == 'EPSV': + if self.dump: + # Temporarily store the pair of IP addresses + # to open up the BPF filter until blob_handler processes + # the response with the full IP/Port information. + # Note: Due to the way blob processing works, we don't + # get this information until after the data channel is + # established. + info['tempippair'] = tuple( + sorted((conn.clientip, conn.serverip)) + ) + self.__update_bpf() + + # For file transfers (including LIST), store tuple + # (Direction, Path, Filename) in info['file'] + elif command == 'LIST': + if param == '': + info['file'] = ( + 'RETR', os.path.normpath(os.path.join(*info['path'])) + if len(info['path']) + else '', 'LIST' + ) + else: + info['file'] = ( + 'RETR', os.path.normpath(os.path.join(os.path.join(*info['path']), param)) + if len(info['path']) + else '', 'LIST' + ) + elif command == 'RETR': + info['file'] = ( + 'RETR', os.path.normpath(os.path.join(*info['path'])) + if len(info['path']) + else '', param + ) + elif command == 'STOR': + info['file'] = ( + 'STOR', os.path.normpath(os.path.join(*info['path'])) + if len(info['path']) + else '', param + ) + + # Responses + else: + # Rollback directory change unless 2xx response + if info['lastcommand'] == 'CWD' and data[0] != '2': + info['path'].pop() + # Write out files upon resonse to transfer commands + if info['lastcommand'] in ('LIST', 'RETR', 'STOR'): + if self.dump and info['filedata']: + origname = info['file'][0] + '_' + os.path.join(*info['file'][1:3]) + outname = dshell.util.gen_local_filename(self.outdir, origname) + with open(outname, 'wb') as fh: + fh.write(info['filedata']) + numbytes = len(info['filedata']) + info['filedata'] = None + info['outfile'] = outname + info.update(conn.info()) + msg = 'User: "{}", Pass: "{}", {} File: {} ({:,} bytes written to {})'.format( + info['user'], + info['pass'], + info['file'][0], + os.path.join(*info['file'][1:3]), + numbytes, + os.path.basename(outname) + ) + else: + info.update(conn.info()) + msg = 'User: "{}", Pass: "{}", {} File: {}'.format( + info['user'], + info['pass'], + info['file'][0], + os.path.join(*info['file'][1:3]) + ) + if data[0] not in ('1','2'): + msg += ' ({})'.format(data.rstrip()) + info['ts'] = blob.ts + if (blob.sip == conn.sip): + self.write(msg, **info, dir_arrow="->") + else: + self.write(msg, **info, dir_arrow="<-") + info['file'] = None + + # Handle EPSV mode port setting + if info['lastcommand'] == 'EPSV' and data[0] == '2': + ret = re.findall('\(\|\|\|\d+\|\)', data) + # TODO delimiters other than pipes + if ret: + tport = int(ret[0].split('|')[3]) + info['datachan'] = (conn.serverip, tport) + if self.dump: + self.data_channel_map[(conn.serverip, tport)] = conn.addr + info['tempippair'] = None + self.__update_bpf() + + # Look for ip/port information, assuming PSV response + ret = re.findall('\d+,\d+,\d+,\d+,\d+\,\d+', data) + if len(ret) == 1: + tip, tport = self.calculateTransfer(ret[0]) # transfer ip, transfer port + info['datachan'] = (tip, tport) # Update this control channel's knowledge of currently working data channel + if self.dump: + self.data_channel_map[(tip,tport)] = conn.addr # Update plugin's global datachan knowledge + info['tempippair'] = None + self.__update_bpf() + + return conn, blob + + + def calculateTransfer(self, val): + # calculate passive FTP data port + tmp = val.split(',') + ip = '.'.join(tmp[:4]) + port = int(tmp[4])*256 + int(tmp[5]) + return ip, port + + +if __name__ == "__main__": + print(DshellPlugin()) diff --git a/dshell/plugins/http/__init__.py b/dshell/plugins/http/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/dshell/plugins/http/httpdump.py b/dshell/plugins/http/httpdump.py new file mode 100644 index 0000000..1aeeb4a --- /dev/null +++ b/dshell/plugins/http/httpdump.py @@ -0,0 +1,168 @@ +""" +Presents useful information points for HTTP sessions +""" + +import dshell.core +import dshell.util +from dshell.plugins.httpplugin import HTTPPlugin +from dshell.output.colorout import ColorOutput + +from urllib.parse import parse_qs +from http import cookies + +class DshellPlugin(HTTPPlugin): + def __init__(self): + super().__init__( + name="httpdump", + description="Dump useful information about HTTP sessions", + bpf="tcp and (port 80 or port 8080 or port 8000)", + author="amm", + output=ColorOutput(label=__name__), + optiondict={ + "maxurilen": { + "type": int, + "default": 30, + "metavar": "LENGTH", + "help": "Truncate URLs longer than LENGTH (default: 30). Set to 0 for no truncating."}, + "maxpost": { + "type": int, + "default": 1000, + "metavar": "LENGTH", + "help": "Truncate POST bodies longer than LENGTH characters (default: 1000). Set to 0 for no truncating."}, + "maxcontent": { + "type": int, + "default": 0, + "metavar": "LENGTH", + "help": "Truncate response bodies longer than LENGTH characters (default: no truncating). Set to 0 for no truncating."}, + "showcontent": { + "action": "store_true", + "help": "Display response body"}, + "showhtml": { + "action": "store_true", + "help": "Display only HTML results"}, + "urlfilter": { + "type": str, + "default": None, + "metavar": "REGEX", + "help": "Filter to URLs matching this regular expression"} + } + ) + + def premodule(self): + if self.urlfilter: + import re + self.urlfilter = re.compile(self.urlfilter) + + def http_handler(self, conn, request, response): + host = request.headers.get('host', conn.serverip) + url = host + request.uri + pretty_url = url + + # separate URL-encoded data from the location + if '?' in request.uri: + uri_location, uri_data = request.uri.split('?', 1) + pretty_url = host + uri_location + else: + uri_location, uri_data = request.uri, "" + + # Check if the URL matches a user-defined filter + if self.urlfilter and not self.urlfilter.search(pretty_url): + return + + if self.maxurilen > 0 and len(uri_location) > self.maxurilen: + uri_location = "{}[truncated]".format(uri_location[:self.maxurilen]) + pretty_url = host + uri_location + + # Set the first line of the alert to show some basic metadata + if response == None: + msg = ["{} (NO RESPONSE) {}".format(request.method, pretty_url)] + else: + msg = ["{} ({}) {} ({})".format(request.method, response.status, pretty_url, response.headers.get("content-type", "[no content-type]"))] + + # Determine if there is any POST data from the client and parse + if request and request.method == "POST": + try: + post_params = parse_qs(request.body.decode("utf-8"), keep_blank_values=True) + # If parse_qs only returns a single element with a null + # value, it's probably an eroneous evaluation. Most likely + # base64 encoded payload ending in an '=' character. + if len(post_params) == 1 and list(post_params.values()) == [["\x00"]]: + post_params = request.body + except UnicodeDecodeError: + post_params = request.body + else: + post_params = {} + + # Get some additional useful data + url_params = parse_qs(uri_data, keep_blank_values=True) + referer = request.headers.get("referer", None) + client_cookie = cookies.SimpleCookie(request.headers.get("cookie", "")) + server_cookie = cookies.SimpleCookie(response.headers.get("cookie", "")) + + # Piece together the alert message + if referer: + msg.append("Referer: {}".format(referer)) + + if client_cookie: + msg.append("Client Transmitted Cookies:") + for k, v in client_cookie.items(): + msg.append("\t{} -> {}".format(k, v.value)) + + if server_cookie: + msg.append("Server Set Cookies:") + for k, v in server_cookie.items(): + msg.append("\t{} -> {}".format(k, v.value)) + + if url_params: + msg.append("URL Parameters:") + for k, v in url_params.items(): + msg.append("\t{} -> {}".format(k, v)) + + if post_params: + if isinstance(post_params, dict): + msg.append("POST Parameters:") + for k, v in post_params.items(): + msg.append("\t{} -> {}".format(k, v)) + else: + msg.append("POST Data:") + msg.append(dshell.util.printable_text(str(post_params))) + elif request.body: + msg.append("POST Body:") + request_body = dshell.util.printable_text(request_body) + if self.maxpost > 0 and len(request.body) > self.maxpost: + msg.append("{}[truncated]".format(request_body[:self.maxpost])) + else: + msg.append(request_body) + + if self.showcontent or self.showhtml: + if self.showhtml and 'html' not in response.headers.get('content-type', ''): + return + if 'gzip' in response.headers.get('content-encoding', ''): + # TODO gunzipping + content = '(gzip encoded)\n{}'.format(response.body) + else: + content = response.body + content = dshell.util.printable_text(content) + if self.maxcontent and len(content) > self.maxcontent: + content = "{}[truncated]".format(content[:self.maxcontent]) + msg.append("Body Content:") + msg.append(content) + + # Display the start and end times based on Blob instead of Connection + kwargs = conn.info() + if request: + kwargs['starttime'] = request.blob.starttime + kwargs['clientbytes'] = len(request.blob.data) + else: + kwargs['starttime'] = None + kwargs['clientbytes'] = 0 + if response: + kwargs['endtime'] = response.blob.endtime + kwargs['serverbytes'] = len(response.blob.data) + else: + kwargs['endtime'] = None + kwargs['serverbytes'] = 0 + + self.write('\n'.join(msg), **kwargs) + + return conn, request, response diff --git a/dshell/plugins/http/joomla.py b/dshell/plugins/http/joomla.py new file mode 100644 index 0000000..e0a8225 --- /dev/null +++ b/dshell/plugins/http/joomla.py @@ -0,0 +1,86 @@ +""" +Detect and dissect malformed HTTP headers targeting Joomla + +https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2015-8562 +""" + +from dshell.plugins.httpplugin import HTTPPlugin +from dshell.output.alertout import AlertOutput + +import re + +class DshellPlugin(HTTPPlugin): + def __init__(self): + super().__init__( + name="Joomla CVE-2015-8562", + author="bg", + description='detect attempts to enumerate MS15-034 vulnerable IIS servers', + bpf='tcp and (port 80 or port 8080 or port 8000)', + output=AlertOutput(label=__name__), + optiondict={ + "raw_payload": { + "action": "store_true", + "help": "return the raw payload (do not attempt to decode chr encoding)", + } + }, + longdescription=''' +Detect and dissect malformed HTTP headers targeting Joomla + +https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2015-8562 + +Usage Examples: +--------------- + +Dshell> decode -d joomla *.pcap +[Joomla CVE-2015-8562] 2015-12-15 20:17:18 192.168.1.119:43865 <- 192.168.1.139:80 ** x-forwarded-for -> system('touch /tmp/2'); ** + +The module assumes the cmd payload is encoded using chr. To turn this off run: + +Dshell> decode -d joomla --joomla_raw_payload *.pcap +[Joomla CVE-2015-8562] 2015-12-15 20:17:18 192.168.1.119:43865 <- 192.168.1.139:80 ** x-forwarded-for -> "eval(chr(115).chr(121).chr(115).chr(116).chr(101).chr(109).chr(40).chr(39).chr(116).chr(111).chr(117).chr(99).chr(104).chr(32).chr(47).chr(116).chr(109).chr(112).chr(47).chr(50).chr(39).chr(41).chr(59)); ** +''', + ) + + # Indicator of (potential) compromise + self.ioc = "JFactory::getConfig();exit" + self.ioc_bytes = bytes(self.ioc, "ascii") + + def attempt_decode(self, cmd): + ptext = '' + for c in re.findall('\d+', cmd): + ptext += chr(int(c)) + return ptext + + def parse_cmd(self, data): + start = data.find('"feed_url";')+11 + end = data.find(self.ioc) + chunk = data[start:end] + + try: + cmd = chunk.split(':')[-1] + if self.raw_payload: + return cmd + + plaintext_cmd = self.attempt_decode(cmd) + return plaintext_cmd + except: + return None + + def http_handler(self, conn, request, response): + if not request: + return + + if self.ioc_bytes not in request.blob.data: + # indicator of (potential) compromise is not here + return + + # there is an attempt to exploit Joomla! + + # The Joomla exploit could be sent any HTTP header field + for hdr, val in request.headers.items(): + if self.ioc in val: + cmd = self.parse_cmd(val) + if cmd: + self.alert('{} -> {}'.format(hdr, cmd), **conn.info()) + return conn, request, response + diff --git a/dshell/plugins/http/ms15-034.py b/dshell/plugins/http/ms15-034.py new file mode 100644 index 0000000..9210603 --- /dev/null +++ b/dshell/plugins/http/ms15-034.py @@ -0,0 +1,64 @@ +""" +Proof-of-concept code to detect attempts to enumerate MS15-034 vulnerable +IIS servers and/or cause a denial of service. Each event will generate an +alert that prints out the HTTP Request method and the range value contained +with the HTTP stream. +""" + +from dshell.plugins.httpplugin import HTTPPlugin +from dshell.output.alertout import AlertOutput + +class DshellPlugin(HTTPPlugin): + def __init__(self): + super().__init__( + name="ms15-034", + author="bg", + description='detect attempts to enumerate MS15-034 vulnerable IIS servers', + bpf='tcp and (port 80 or port 8080 or port 8000)', + output=AlertOutput(label=__name__), + longdescription=''' +Proof-of-concept code to detect attempts to enumerate MS15-034 vulnerable +IIS servers and/or cause a denial of service. Each event will generate an +alert that prints out the HTTP Request method and the range value contained +with the HTTP stream. + +Usage: +decode -d ms15-034 -q *.pcap +decode -d ms15-034 -i -q + +References: +https://technet.microsoft.com/library/security/ms15-034 +https://ma.ttias.be/remote-code-execution-via-http-request-in-iis-on-windows/ +''', + ) + + + def http_handler(self, conn, request, response): + if response == None: + # Denial of Service (no server response) + try: + rangestr = request.headers.get("range", '') + # check range value to reduce false positive rate + if not rangestr.endswith('18446744073709551615'): + return + except: + return + self.write('MS15-034 DoS [Request Method: "{0}" URI: "{1}" Range: "{2}"]'.format(request.method, request.uri, rangestr), conn.info()) + return conn, request, response + + else: + # probing for vulnerable server + try: + rangestr = request.headers.get("range", '') + if not rangestr.endswith('18446744073709551615'): + return + except: + return + + # indication of vulnerable server + if rangestr and (response.status == '416' or \ + response.reason == 'Requested Range Not Satisfiable'): + self.write('MS15-034 Vulnerable Server [Request Method: "{0}" Range: "{1}"]'.format(request.method,rangestr), conn.info()) + return conn, request, response + + diff --git a/dshell/plugins/http/riphttp.py b/dshell/plugins/http/riphttp.py new file mode 100644 index 0000000..d5b5ccf --- /dev/null +++ b/dshell/plugins/http/riphttp.py @@ -0,0 +1,205 @@ +""" +Identifies HTTP traffic and reassembles file transfers before writing them to +files. +""" + +from dshell.plugins.httpplugin import HTTPPlugin +from dshell.output.alertout import AlertOutput + +import os +import sys +import re + +class DshellPlugin(HTTPPlugin): + def __init__(self): + super().__init__( + name="rip-http", + author="bg,twp", + bpf="tcp and (port 80 or port 8080 or port 8000)", + description="Rips files from HTTP traffic", + output=AlertOutput(label=__name__), + optiondict={'append_conn': + {'action': 'store_true', + 'help': 'append sourceip-destip to filename'}, + 'append_ts': + {'action': 'store_true', + 'help': 'append timestamp to filename'}, + 'direction': + {'help': 'cs=only capture client POST, sc=only capture server GET response', + 'metavar': '"cs" OR "sc"', + 'default': None}, + 'outdir': + {'help': 'directory to write output files (Default: current directory)', + 'metavar': 'DIRECTORY', + 'default': '.'}, + 'content_filter': + {'help': 'regex MIME type filter for files to save', + 'metavar': 'REGEX'}, + 'name_filter': + {'help': 'regex filename filter for files to save', + 'metavar': 'REGEX'} + } + ) + + def premodule(self): + if self.direction not in ('cs', 'sc', None): + self.error("Invalid value for direction: {!r}. Argument must be either 'sc' for server-to-client or 'cs' for client-to-server.".format(self.direction)) + sys.exit(1) + + if self.content_filter: + self.content_filter = re.compile(self.content_filter) + if self.name_filter: + self.name_filter = re.compile(self.name_filter) + + self.openfiles = {} + + if not os.path.exists(self.outdir): + try: + os.makedirs(self.outdir) + except (IOError, OSError) as e: + self.error("Could not create output directory: {!r}: {!s}" + .format(self.outdir, e)) + sys.exit(1) + + def http_handler(self, conn, request, response): + if (not self.direction or self.direction == 'cs') and request and request.method == "POST" and request.body: + if not self.content_filter or self.content_filter.search(request.headers.get('content-type', '')): + payload = request + elif (not self.direction or self.direction == 'sc') and response and response.status[0] == '2': + if not self.content_filter or self.content_filter.search(response.headers.get('content-type', '')): + payload = response + else: + payload = None + + if not payload: + # Connection did not match any filters, so get rid of it + return + + host = request.headers.get('host', conn.serverip) + url = host + request.uri + + if url in self.openfiles: + # File is already open, so just insert the new data + s, e = self.openfiles[url].handleresponse(response) + self.debug("{0!r} --> Range: {1} - {2}".format(url, s, e)) + else: + # A new file! + filename = request.uri.split('?', 1)[0].split('/')[-1] + if self.name_filter and self.name_filter.search(filename): + # Filename did not match filter, so get rid of it + return + if not filename: + # Assume index.html if there is no filename + filename = "index.html" + if self.append_conn: + filename += "_{0}-{1}".format(conn.serverip, conn.clientip) + if self.append_ts: + filename += "_{}".format(conn.ts) + while os.path.exists(os.path.join(self.outdir, filename)): + filename += "_" + self.write("New file {} ({})".format(filename, url), **conn.info(), dir_arrow="<-") + self.openfiles[url] = HTTPFile(os.path.join(self.outdir, filename), self) + s, e = self.openfiles[url].handleresponse(payload) + self.debug("{0!r} --> Range: {1} - {2}".format(url, s, e)) + if self.openfiles[url].done(): + self.write("File done {} ({})".format(filename, url), **conn.info(), dir_arrow="<-") + del self.openfiles[url] + + return conn, request, response + +class HTTPFile(object): + """ + An internal class used to hold metadata for open HTTP files. + Used mostly to reassemble fragmented transfers. + """ + + def __init__(self, filename, plugin_instance): + self.complete = False + # Expected size in bytes of full file transfer + self.size = 0 + # List of tuples indicating byte chunks already received and written to + # disk + self.ranges = [] + self.plugin = plugin_instance + self.filename = filename + try: + self.fh = open(filename, 'wb') + except IOError as e: + self.plugin.error( + "Could not create file {!r}: {!s}".format(filename, e)) + self.fh = None + + def __del__(self): + if self.fh is None: + return + self.fh.close() + if not self.done(): + self.plugin.warning("Incomplete file: {!r}".format(self.filename)) + try: + os.rename(self.filename, self.filename + "_INCOMPLETE") + except: + pass + ls = 0 + le = 0 + for s, e in self.ranges: + if s > le + 1: + self.plugin.warning( + "Missing bytes between {0} and {1}".format(le, s)) + ls, le = s, e + + def handleresponse(self, response): + # Check for Content Range + range_start = 0 + range_end = len(response.body) - 1 + if 'content-range' in response.headers: + m = re.search( + 'bytes (\d+)-(\d+)/(\d+|\*)', response.headers['content-range']) + if m: + range_start = int(m.group(1)) + range_end = int(m.group(2)) + if len(response.body) < (range_end - range_start + 1): + range_end = range_start + len(response.body) - 1 + try: + if int(m.group(3)) > self.size: + self.size = int(m.group(3)) + except: + pass + elif 'content-length' in response.headers: + try: + if int(response.headers['content-length']) > self.size: + self.size = int(response.headers['content-length']) + except: + pass + # Update range tracking + self.ranges.append((range_start, range_end)) + # Write part of file + if self.fh is not None: + self.fh.seek(range_start) + self.fh.write(response.body) + return (range_start, range_end) + + def done(self): + self.checkranges() + return self.complete + + def checkranges(self): + self.ranges.sort() + current_start = 0 + current_end = 0 + foundgap = False + # print self.ranges + for s, e in self.ranges: + if s <= current_end + 1: + current_end = e + else: + foundgap = True + current_start = s + current_end = e + if not foundgap: + if (current_end + 1) >= self.size: + self.complete = True + return foundgap + + +if __name__ == "__main__": + print(DshellPlugin()) diff --git a/dshell/plugins/http/web.py b/dshell/plugins/http/web.py new file mode 100644 index 0000000..7d4d3cd --- /dev/null +++ b/dshell/plugins/http/web.py @@ -0,0 +1,67 @@ +""" +Displays basic information for web requests/responses in a connection. +""" + +from dshell.plugins.httpplugin import HTTPPlugin +from dshell.output.alertout import AlertOutput + +from hashlib import md5 + +class DshellPlugin(HTTPPlugin): + def __init__(self): + super().__init__( + name="web", + author="bg,twp", + description="Displays basic information for web requests/responses in a connection", + bpf="tcp and (port 80 or port 8080 or port 8000)", + output=AlertOutput(label=__name__), + optiondict={ + "md5": {"action": "store_true", + "help": "Calculate MD5 for each response."} + }, + ) + + def http_handler(self, conn, request, response): + if request: + # Collect basics about the request, if available + method = request.method + host = request.headers.get("host", "") + print(request.headers) + uri = request.uri +# useragent = request.headers.get("user-agent", None) +# referer = request.headers.get("referer", None) + version = request.version + else: + method = "(no request)" + host = "" + uri = "" + version = "" + + if response: + # Collect basics about the response, if available + status = response.status + reason = response.reason + if self.md5: + hash = "(md5: {})".format(md5(response.body).hexdigest()) + else: + hash = "" + else: + status = "(no response)" + reason = "" + hash = "" + + data = "{} {}{} HTTP/{} {} {} {}".format(method, + host, + uri, + version, + status, + reason, + hash) + if not request: + self.write(data, method=method, host=host, uri=uri, version=version, status=status, reason=reason, hash=hash, **response.blob.info()) + else: + self.write(data, method=method, uri=uri, version=version, status=status, reason=reason, hash=hash, **request.headers, **request.blob.info()) + return conn, request, response + +if __name__ == "__main__": + print(DshellPlugin()) diff --git a/dshell/plugins/httpplugin.py b/dshell/plugins/httpplugin.py new file mode 100644 index 0000000..99fe472 --- /dev/null +++ b/dshell/plugins/httpplugin.py @@ -0,0 +1,255 @@ +""" +This is a base-level plugin inteded to handle HTTP connections. + +It inherits from the base ConnectionPlugin and provides a new handler +function: http_handler(conn, request, response). + +It automatically pairs requests/responses, parses headers, reassembles bodies, +and collects them into HTTPRequest and HTTPResponse objects that are passed +to the http_handler. +""" + +import dshell.core + +from pypacker.layer567 import http + +import gzip +import io + +def parse_headers(obj, f): + """Return dict of HTTP headers parsed from a file object.""" + # Logic lifted mostly from dpkt's http module + d = {} + while 1: + line = f.readline() + line = line.decode('utf-8') + line = line.strip() + if not line: + break + l = line.split(None, 1) + if not l[0].endswith(':'): + obj.errors.append(dshell.core.DataError("Invalid header {!r}".format(line))) + k = l[0][:-1].lower() + v = len(l) != 1 and l[1] or '' + if k in d: + if not type(d[k]) is list: + d[k] = [d[k]] + d[k].append(v) + else: + d[k] = v + return d + +def parse_body(obj, f, headers): + """Return HTTP body parsed from a file object, given HTTP header dict.""" + # Logic lifted mostly from dpkt's http module + if headers.get('transfer-encoding', '').lower() == 'chunked': + l = [] + found_end = False + while 1: + try: + sz = f.readline().split(None, 1)[0] + except IndexError: + obj.errors.append(dshell.core.DataError('missing chunk size')) + n = int(sz, 16) + if n == 0: + found_end = True + buf = f.read(n) + if f.readline().strip(): + break + if n and len(buf) == n: + l.append(buf) + else: + break + if not found_end: + obj.errors.append(dshell.core.DataError('premature end of chunked body')) + body = b''.join(l) + elif 'content-length' in headers: + n = int(headers['content-length']) + body = f.read(n) + if len(body) != n: + obj.errors.append(dshell.core.DataError('short body (missing {} bytes)'.format(n - len(body)))) + elif 'content-type' in headers: + body = f.read() + else: + # XXX - need to handle HTTP/0.9 + body = b'' + return body + +class HTTPRequest(object): + """ + A class for HTTP requests + + Attributes: + blob : the Blob instance of the request + errors : a list of caught exceptions from parsing + method : the method of the request (e.g. GET, PUT, POST, etc.) + uri : the URI being requested (host not included) + version : the HTTP version (e.g. "1.1" for "HTTP/1.1") + headers : a dictionary containing the headers and values + body : bytestring of the reassembled body, after the headers + """ + _methods = ( + 'GET', 'PUT', 'ICY', + 'COPY', 'HEAD', 'LOCK', 'MOVE', 'POLL', 'POST', + 'BCOPY', 'BMOVE', 'MKCOL', 'TRACE', 'LABEL', 'MERGE', + 'DELETE', 'SEARCH', 'UNLOCK', 'REPORT', 'UPDATE', 'NOTIFY', + 'BDELETE', 'CONNECT', 'OPTIONS', 'CHECKIN', + 'PROPFIND', 'CHECKOUT', 'CCM_POST', + 'SUBSCRIBE', 'PROPPATCH', 'BPROPFIND', + 'BPROPPATCH', 'UNCHECKOUT', 'MKACTIVITY', + 'MKWORKSPACE', 'UNSUBSCRIBE', 'RPC_CONNECT', + 'VERSION-CONTROL', + 'BASELINE-CONTROL' + ) + + def __init__(self, blob): + self.errors = [] + self.headers = {} + self.body = b'' + self.blob = blob + data = io.BytesIO(blob.data) + rawline = data.readline() + try: + line = rawline.decode('utf-8') + except UnicodeDecodeError: + line = '' + l = line.strip().split() + if len(l) != 3 or l[0] not in self._methods or not l[2].startswith('HTTP'): + self.errors.append(dshell.core.DataError('invalid HTTP request: {!r}'.format(rawline))) + self.method = '' + self.uri = '' + self.version = '' + return + else: + self.method = l[0] + self.uri = l[1] + self.version = l[2][5:] + self.headers = parse_headers(self, data) + self.body = parse_body(self, data, self.headers) + +class HTTPResponse(object): + """ + A class for HTTP responses + + Attributes: + blob : the Blob instance of the request + errors : a list of caught exceptions from parsing + version : the HTTP version (e.g. "1.1" for "HTTP/1.1") + status : the status code of the response (e.g. "200" or "304") + reason : the status text of the response (e.g. "OK" or "Not Modified") + headers : a dictionary containing the headers and values + body : bytestring of the reassembled body, after the headers + """ + def __init__(self, blob): + self.errors = [] + self.headers = {} + self.body = b'' + self.blob = blob + data = io.BytesIO(blob.data) + rawline = data.readline() + try: + line = rawline.decode('utf-8') + except UnicodeDecodeError: + line = '' + l = line.strip().split(None, 2) + if len(l) < 2 or not l[0].startswith("HTTP") or not l[1].isdigit(): + self.errors.append(dshell.core.DataError('invalid HTTP response: {!r}'.format(rawline))) + self.version = '' + self.status = '' + self.reason = '' + return + else: + self.version = l[0][5:] + self.status = l[1] + self.reason = l[2] + self.headers = parse_headers(self, data) + self.body = parse_body(self, data, self.headers) + + def decompress_gzip_content(self): + """ + If this response has Content-Encoding set to something with "gzip", + this function will decompress it and store it in the body. + """ + if "gzip" in self.headers.get("content-encoding", ""): + try: + iobody = io.BytesIO(self.body) + except TypeError as e: + self.errors.append(dshell.core.DataError("Body was not a byte string ({!s}). Could not decompress.".format(type(self.body)))) + return + try: + self.body = gzip.GzipFile(fileobj=iobody).read() + except OSError as e: + self.errors.append(OSError("Could not gunzip body. {!s}".format(e))) + return + + +class HTTPPlugin(dshell.core.ConnectionPlugin): + + def __init__(self, **kwargs): + super().__init__(**kwargs) + # Use "gunzip" argument to automatically decompress gzipped responses + self.gunzip = kwargs.get("gunzip", False) + + def connection_handler(self, conn): + """ + Goes through each Blob in a Connection, assuming they appear in pairs + of requests and responses, and builds HTTPRequest and HTTPResponse + objects. + + After a response (or only a request at the end of a connection), + http_handler is called. If it returns nothing, the respective blobs + are marked as hidden so they won't be passed to additional plugins. + """ + request = None + response = None + for blob in conn.blobs: + blob.reassemble(allow_overlap=True, allow_padding=True) + if not blob.data: + continue + if blob.direction == 'cs': + # client-to-server request + request = HTTPRequest(blob) + for req_error in request.errors: + self.debug("Request Error: {!r}".format(req_error)) + elif blob.direction == 'sc': + # server-to-client response + response = HTTPResponse(blob) + for rep_error in response.errors: + self.debug("Response Error: {!r}".format(rep_error)) + if self.gunzip: + response.decompress_gzip_content() + http_handler_out = self.http_handler(conn=conn, request=request, response=response) + if not http_handler_out: + if request: + request.blob.hidden = True + if response: + response.blob.hidden = True + request = None + response = None + if request and not response: + http_handler_out = self.http_handler(conn=conn, request=request, response=None) + if not http_handler_out: + blob.hidden = True + return conn + + def http_handler(self, conn, request, response): + """ + A placeholder. + + Plugins will be able to overwrite this to perform custom activites + on HTTP data. + + It SHOULD return a list containing the sames types of values that came + in as arguments (i.e. return (conn, request, response)) or None. This + is mostly a consistency thing. Realistically, it only needs to return + some value that evaluates to True to pass the Blobs along to additional + plugins. + + Arguments: + conn: a Connection object + request: a HTTPRequest object + response: a HTTPResponse object + """ + return conn, request, response + +DshellPlugin = None diff --git a/dshell/plugins/malware/__init__.py b/dshell/plugins/malware/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/dshell/plugins/malware/sweetorange.py b/dshell/plugins/malware/sweetorange.py new file mode 100644 index 0000000..f45e328 --- /dev/null +++ b/dshell/plugins/malware/sweetorange.py @@ -0,0 +1,82 @@ +""" +2015 Feb 13 + +Sometimes, attackers will try to obfuscate links to the Sweet Orange exploit +kit. This plugin is an attempt to decode that sort of traffic. + +It will use a regular expression to try and detect certain variable names that +can be contained in JavaScript code. It will then take the value assigned to +it and decode the domain address hidden inside the value. + +Samples: +http://malware-traffic-analysis.net/2014/10/27/index2.html +http://malware-traffic-analysis.net/2014/10/03/index.html +http://malware-traffic-analysis.net/2014/09/25/index.html +""" + +from dshell.output.alertout import AlertOutput +from dshell.plugins.httpplugin import HTTPPlugin + +import re + + +class DshellPlugin(HTTPPlugin): + + def __init__(self): + super().__init__( + name="sweetorange", + longdescription="Used to decode certain variants of the Sweet Orange exploit kit redirect traffic. Looks for telltale Javascript variable names (e.g. 'ajax_data_source' and 'main_request_data_content') and automatically decodes the exploit landing page contained.", + description="Used to decode certain variants of the Sweet Orange exploit kit redirect traffic", + bpf="tcp and (port 80 or port 8080 or port 8000)", + output=AlertOutput(label=__name__), + author="dev195", + gunzip=True, + optiondict={ + "variable": { + "type": str, + "action": "append", + "help": 'Variable names to search for. Default ("ajax_data_source", "main_request_data_content")', + "default": ["ajax_data_source", "main_request_data_content"] + }, + "color": { + "action": "store_true", + "help": "Display encoded/decoded lines in different TTY colors.", + "default": False + }, + } + ) + + + def premodule(self): + self.sig_regex = re.compile( + r"var (" + '|'.join(map(re.escape, self.variable)) + ")='(.*?)';") + self.hexregex = re.compile(r'[^a-fA-F0-9]') + self.debug('Variable regex: "%s"' % self.sig_regex.pattern) + + def http_handler(self, conn, request, response): + try: + response_body = response.body.decode("ascii") + except UnicodeError: + return + except AttributeError: + return + + if response and any([v in response_body for v in self.variable]): + # Take the variable's value, extract the hex characters, and + # convert to ASCII + matches = self.sig_regex.search(response_body) + try: + hidden = matches.groups()[1] + match = bytes.fromhex(self.hexregex.sub('', hidden)) + match = match.decode('utf-8') + except: + return + if self.color: + # If desired, add TTY colors to the alerts for differentiation + # between encoded/decoded strings + hidden = "\x1b[37;2m%s\x1b[0m" % hidden + match = "\x1b[32m%s\x1b[0m" % match + self.log(hidden) + self.write(match, **conn.info()) + return (conn, request, response) + diff --git a/dshell/plugins/misc/__init__.py b/dshell/plugins/misc/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/dshell/plugins/misc/followstream.py b/dshell/plugins/misc/followstream.py new file mode 100644 index 0000000..5e73d57 --- /dev/null +++ b/dshell/plugins/misc/followstream.py @@ -0,0 +1,25 @@ +""" +Generates color-coded Screen/HTML output similar to Wireshark Follow Stream +""" + +import dshell.core +from dshell.output.colorout import ColorOutput + +class DshellPlugin(dshell.core.ConnectionPlugin): + + def __init__(self): + super().__init__( + name="Followstream", + author="amm/dev195", + description="Generates color-coded Screen/HTML output similar to Wireshark Follow Stream. Empty connections will be skipped.", + bpf="tcp", + output=ColorOutput(label=__name__), + ) + + def connection_handler(self, conn): + if (conn.clientbytes + conn.serverbytes > 0): + self.write(conn, **conn.info()) + return conn + +if __name__ == "__main__": + print(DshellPlugin()) diff --git a/dshell/plugins/misc/pcapwriter.py b/dshell/plugins/misc/pcapwriter.py new file mode 100644 index 0000000..2407bc9 --- /dev/null +++ b/dshell/plugins/misc/pcapwriter.py @@ -0,0 +1,64 @@ +""" +Generates pcap output + +Can be used alone or chained at the end of plugins for a kind of filter. + +Use --pcapwriter_outfile to separate its output from that of other plugins. + +Example uses include: + - merging multiple pcap files into one + (decode -d pcapwriter ~/pcap/* >merged.pcap) + - saving relevant traffic by chaining with another plugin + (decode -d track+pcapwriter --track_source=192.168.1.1 --pcapwriter_outfile=merged.pcap ~/pcap/*) + - getting pcap output from plugins that can't use pcapout + (decode -d web+pcapwriter ~/pcap/*) +""" + +import dshell.core +from dshell.output.pcapout import PCAPOutput + +import sys + +class DshellPlugin(dshell.core.PacketPlugin): + + def __init__(self, *args, **kwargs): + super().__init__( + name="pcap writer", + description="Used to generate pcap output for plugins that can't use -o pcapout", + longdescription="""Generates pcap output + +Can be used alone or chained at the end of plugins for a kind of filter. + +Use --pcapwriter_outfile to separate its output from that of other plugins. + +Example uses include: + - merging multiple pcap files into one (decode -d pcapwriter ~/pcap/* >merged.pcap) + - saving relevant traffic by chaining with another plugin (decode -d track+pcapwriter --track_source=192.168.1.1 --pcapwriter_outfile=merged.pcap ~/pcap/*) + - getting pcap output from plugins that can't use pcapout (decode -d web+pcapwriter ~/pcap/*) +""", + author="dev195", + output=PCAPOutput(label=__name__), + optiondict={ + "outfile": { + "type": str, + "help": "Write to FILE instead of stdout", + "metavar": "FILE", + } + } + ) + + def premodule(self): + if self.outfile: + try: + self.out.reset_fh(filename=self.outfile, mode='wb') + except OSError as e: + self.error(str(e)) + sys.exit(1) + + def raw_handler(self, pktlen, pkt, ts): + rawpkt = pkt.header_bytes + pkt.body_bytes + self.write(pktlen=pktlen, rawpkt=rawpkt, ts=ts, link_layer_type=self.link_layer_type) + return pktlen, pkt, ts + +if __name__ == "__main__": + print(DshellPlugin()) diff --git a/dshell/plugins/misc/search.py b/dshell/plugins/misc/search.py new file mode 100644 index 0000000..d4d99a6 --- /dev/null +++ b/dshell/plugins/misc/search.py @@ -0,0 +1,92 @@ +import dshell.core +from dshell.util import printable_text +from dshell.output.alertout import AlertOutput + +import re +import sys + +class DshellPlugin(dshell.core.ConnectionPlugin): + + def __init__(self): + super().__init__( + name="search", + author="dev195", + bpf="tcp or udp", + description="Search for patterns in connections", + longdescription=""" +Reconstructs streams and searches the content for a user-provided regular +expression. Requires definition of the --search_expression argument. Additional +options can be provided to alter behavior. + """, + output=AlertOutput(label=__name__), + optiondict={ + "expression": { + "help": "Search expression", + "type": str, + "metavar": "REGEX"}, + "ignorecase": { + "help": "Ignore case when searching", + "action": "store_true"}, + "invert": { + "help": "Return connections that DO NOT match expression", + "action": "store_true"}, + "quiet": { + "help": "Do not display matches from this plugin. Useful when chaining plugins.", + "action": "store_true"} + }) + + + + def premodule(self): + # make sure the user actually provided an expression to search for + if not self.expression: + self.error("Must define an expression to search for using --search_expression") + sys.exit(1) + + # define the regex flags, based on arguments + re_flags = 0 + if self.ignorecase: + re_flags = re_flags | re.IGNORECASE + + # Create the regular expression + try: + # convert expression to bytes so it can accurately compare to + # the connection data (which is also of type bytes) + byte_expression = bytes(self.expression, 'utf-8') + self.regex = re.compile(byte_expression, re_flags) + except Exception as e: + self.error("Could not compile regex ({0})".format(e)) + sys.exit(1) + + + + def connection_handler(self, conn): + """ + Go through the data of each connection. + If anything is a hit, return the entire connection. + """ + + match_found = False + for blob in conn.blobs: + for line in blob.data.splitlines(): + match = self.regex.search(line) + if match and self.invert: + return None + elif match and not self.invert: + match_found = True + if not self.quiet: + if blob.sip == conn.sip: + self.write(printable_text(line, False), **conn.info(), dir_arrow="->") + else: + self.write(printable_text(line, False), **conn.info(), dir_arrow="<-") + elif self.invert and not match: + if not self.quiet: + self.write(**conn.info()) + return conn + if match_found: + return conn + + + +if __name__ == "__main__": + print(DshellPlugin()) diff --git a/dshell/plugins/misc/sslalerts.py b/dshell/plugins/misc/sslalerts.py new file mode 100644 index 0000000..d5ddc3f --- /dev/null +++ b/dshell/plugins/misc/sslalerts.py @@ -0,0 +1,107 @@ +""" +Looks for SSL alert messages +""" + +# handy reference: +# http://blog.fourthbit.com/2014/12/23/traffic-analysis-of-an-ssl-slash-tls-session + +import dshell.core +from dshell.output.alertout import AlertOutput + +import hashlib +import io +import struct +from pprint import pprint + +# SSLv3/TLS version +SSL3_VERSION = 0x0300 +TLS1_VERSION = 0x0301 +TLS1_1_VERSION = 0x0302 +TLS1_2_VERSION = 0x0303 + +# Record type +SSL3_RT_CHANGE_CIPHER_SPEC = 20 +SSL3_RT_ALERT = 21 +SSL3_RT_HANDSHAKE = 22 +SSL3_RT_APPLICATION_DATA = 23 + +# Handshake message type +SSL3_MT_HELLO_REQUEST = 0 +SSL3_MT_CLIENT_HELLO = 1 +SSL3_MT_SERVER_HELLO = 2 +SSL3_MT_CERTIFICATE = 11 +SSL3_MT_SERVER_KEY_EXCHANGE = 12 +SSL3_MT_CERTIFICATE_REQUEST = 13 +SSL3_MT_SERVER_DONE = 14 +SSL3_MT_CERTIFICATE_VERIFY = 15 +SSL3_MT_CLIENT_KEY_EXCHANGE = 16 +SSL3_MT_FINISHED = 20 + +alert_types = { + 0x00: "CLOSE_NOTIFY", + 0x0a: "UNEXPECTED_MESSAGE", + 0x14: "BAD_RECORD_MAC", + 0x15: "DECRYPTION_FAILED", + 0x16: "RECORD_OVERFLOW", + 0x1e: "DECOMPRESSION_FAILURE", + 0x28: "HANDSHAKE_FAILURE", + 0x29: "NO_CERTIFICATE", + 0x2a: "BAD_CERTIFICATE", + 0x2b: "UNSUPPORTED_CERTIFICATE", + 0x2c: "CERTIFICATE_REVOKED", + 0x2d: "CERTIFICATE_EXPIRED", + 0x2e: "CERTIFICATE_UNKNOWN", + 0x2f: "ILLEGAL_PARAMETER", + 0x30: "UNKNOWN_CA", + 0x31: "ACCESS_DENIED", + 0x32: "DECODE_ERROR", + 0x33: "DECRYPT_ERROR", + 0x3c: "EXPORT_RESTRICTION", + 0x46: "PROTOCOL_VERSION", + 0x47: "INSUFFICIENT_SECURITY", + 0x50: "INTERNAL_ERROR", + 0x5a: "USER_CANCELLED", + 0x64: "NO_RENEGOTIATION", +} + +alert_severities = { + 0x01: "warning", + 0x02: "fatal", +} + +class DshellPlugin(dshell.core.ConnectionPlugin): + + def __init__(self): + super().__init__( + name="sslalerts", + author="dev195", + bpf="tcp and (port 443 or port 993 or port 1443 or port 8531)", + description="Looks for SSL alert messages", + output=AlertOutput(label=__name__), + ) + + def blob_handler(self, conn, blob): + data = io.BytesIO(blob.data) + alert_seen = False + # Iterate over each layer of the connection, paying special attention to the certificate + while True: + try: + content_type, proto_version, record_len = struct.unpack("!BHH", data.read(5)) + except struct.error: + break + if proto_version not in (SSL3_VERSION, TLS1_VERSION, TLS1_1_VERSION, TLS1_2_VERSION): + return None + if content_type == SSL3_RT_ALERT: + handshake_len = struct.unpack("!I", data.read(4))[0] +# assert handshake_len == 2 # TODO remove when live + severity = struct.unpack("!B", data.read(1))[0] + if severity not in alert_severities: + continue + severity_msg = alert_severities.get(severity, severity) + alert_type = struct.unpack("!B", data.read(1))[0] + alert_msg = alert_types.get(alert_type, str(alert_type)) + self.write("SSL alert: ({}) {}".format(severity_msg, alert_msg), **conn.info()) + alert_seen = True + + if alert_seen: + return conn, blob diff --git a/dshell/plugins/misc/synrst.py b/dshell/plugins/misc/synrst.py new file mode 100644 index 0000000..ccf9227 --- /dev/null +++ b/dshell/plugins/misc/synrst.py @@ -0,0 +1,53 @@ +""" +Detects failed attempts to connect (SYN followed by RST/ACK) +""" + +import dshell.core +from dshell.output.alertout import AlertOutput + +from pypacker.layer4 import tcp + +class DshellPlugin(dshell.core.PacketPlugin): + + def __init__(self): + super().__init__( + name="SYN/RST", + description="Detects failed attempts to connect (SYN followed by RST/ACK)", + author="bg", + bpf="(ip and (tcp[13]=2 or tcp[13]=20)) or (ip6 and tcp)", + output=AlertOutput(label=__name__) + ) + + def premodule(self): + # Cache to hold SYNs waiting to pair with RST/ACKs + self.tracker = {} + + def packet_handler(self, pkt): + # Check if SYN or RST/ACK. Discard non-matches. + if pkt.tcp_flags not in (tcp.TH_SYN, tcp.TH_RST|tcp.TH_ACK): + return + + # Try to find the TCP layer + tcpp = pkt.pkt.upper_layer + while not isinstance(tcpp, tcp.TCP): + try: + tcpp = tcpp.upper_layer + except AttributeError: + # There doesn't appear to be a TCP layer, for some reason + return + + if tcpp.flags == tcp.TH_SYN: + seqnum = tcpp.seq + key = "{}|{}|{}|{}|{}".format( + pkt.sip, pkt.sport, seqnum, pkt.dip, pkt.dport) + self.tracker[key] = pkt + elif tcpp.flags == tcp.TH_RST|tcp.TH_ACK: + acknum = tcpp.ack - 1 + tmpkey = "{}|{}|{}|{}|{}".format( + pkt.dip, pkt.dport, acknum, pkt.sip, pkt.sport) + if tmpkey in self.tracker: + msg = "Failed connection [initiated by {}]".format(pkt.dip) + self.write(msg, **pkt.info()) + oldpkt = self.tracker[tmpkey] + del self.tracker[tmpkey] + return [oldpkt, pkt] diff --git a/dshell/plugins/misc/xor.py b/dshell/plugins/misc/xor.py new file mode 100644 index 0000000..8e98385 --- /dev/null +++ b/dshell/plugins/misc/xor.py @@ -0,0 +1,101 @@ +""" +XOR the data in every packet with a user-provided key. Multiple keys can be used +for different data directions. +""" + +import dshell.core +import dshell.util +from dshell.output.output import Output + +import struct + +class DshellPlugin(dshell.core.ConnectionPlugin): + def __init__(self): + super().__init__( + name="xor", + description="XOR every packet with a given key", + output=Output(label=__name__), + bpf="tcp", + author="twp,dev195", + optiondict={ + "key": { + "type": str, + "default": "0xff", + "help": "xor key in hex format (default: 0xff)", + "metavar": "0xHH" + }, + "cskey": { + "type": str, + "default": None, + "help": "xor key to use for client-to-server data (default: None)", + "metavar": "0xHH" + }, + "sckey": { + "type": str, + "default": None, + "help": "xor key to use for server-to-client data (default: None)", + "metavar": "0xHH" + }, + "resync": { + "action": "store_true", + "help": "resync the key index if the key is seen in the data" + } + } + ) + + def __make_key(self, key): + "Convert a user-provided key into a standard format plugin can use." + if key.startswith("0x") or key.startswith("\\x"): + # Convert a hex key + oldkey = key[2:] + newkey = b'' + for i in range(0, len(oldkey), 2): + try: + newkey += struct.pack('B', int(oldkey[i:i + 2], 16)) + except ValueError as e: + self.warn("Error converting hex. Will treat as raw string. - {!s}".format(e)) + newkey = key.encode('ascii') + break + else: + try: + # See if it's a numeric key + newkey = int(key) + newkey = struct.pack('I', newkey) + except ValueError: + # otherwise, convert string key to bytes as it is + newkey = key.encode('ascii') + self.debug("__make_key: {!r} -> {!r}".format(key, newkey)) + return newkey + + def premodule(self): + self.key = self.__make_key(self.key) + if self.cskey: + self.cskey = self.__make_key(self.cskey) + if self.sckey: + self.sckey = self.__make_key(self.sckey) + + def connection_handler(self, conn): + for blob in conn.blobs: + key_index = 0 + if self.sckey and blob.direction == 'sc': + key = self.sckey + elif self.cskey and blob.direction == 'cs': + key = self.cskey + else: + key = self.key + for pkt in blob.all_packets: + # grab the data from the TCP layer and down + data = pkt.pkt.upper_layer.upper_layer.body_bytes + self.debug("Original:\n{}".format(dshell.util.hex_plus_ascii(data))) + # XOR the data and store it in new_data + new_data = b'' + for i in range(len(data)): + if self.resync and data[i:i + len(key)] == key: + key_index = 0 + x = data[i] ^ key[key_index] + new_data += struct.pack('B', x) + key_index = (key_index + 1) % len(key) + # rebuild the packet by adding together each of the layers + pkt.rawpkt = pkt.pkt.header_bytes + pkt.pkt.upper_layer.header_bytes + pkt.pkt.upper_layer.upper_layer.header_bytes + new_data + self.debug("New:\n{}".format(dshell.util.hex_plus_ascii(new_data))) + return conn diff --git a/dshell/plugins/nbns/__init__.py b/dshell/plugins/nbns/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/dshell/plugins/nbns/nbns.py b/dshell/plugins/nbns/nbns.py new file mode 100644 index 0000000..413c3ff --- /dev/null +++ b/dshell/plugins/nbns/nbns.py @@ -0,0 +1,160 @@ +""" +NBNS plugin +""" + +import dshell.core +from dshell.output.alertout import AlertOutput + +from struct import unpack + + +# A few common NBNS Protocol Info Opcodes +# Due to a typo in RFC 1002, 0x9 is also acceptable, but rarely used +# for 'NetBios Refresh' +# 'NetBios Multi-Homed Name Regsitration' (0xf) was added after the RFC +nbns_op = { 0: 'NB_NAME_QUERY', + 5: 'NB_REGISTRATION', + 6: 'NB_RELEASE', + 7: 'NB_WACK', + 8: 'NB_REFRESH', + 9: 'NB_REFRESH', + 15: 'NB_MULTI_HOME_REG' } + + +class DshellPlugin(dshell.core.PacketPlugin): + def __init__(self): + super().__init__( name='nbns', + description='Extract client information from NBNS traffic', + longdescription=""" +The nbns (NetBIOS Name Service) plugin will extract the Transaction ID, Protocol Info, +Client Hostname, and Client MAC address from every UDP NBNS packet found in the given +pcap using port 137. UDP is the standard transport protocol for NBNS traffic. +This filter pulls pertinent information from NBNS packets. + +Examples: + + General usage: + + decode -d nbns + + This will display the connection info including the timestamp, + the source IP, destination IP, Transaction ID, Protocol Info, + Client Hostname, and the Client MAC address in a tabular format. + + + Malware Traffic Analysis Exercise Traffic from 2014-12-08 where a user was hit with a Fiesta exploit kit: + + We want to find out more about the infected machine, and some of this information can be pulled from NBNS traffic + + decode -d nbns 2014-12-08-traffic-analysis-exercise.pcap + + OUTPUT (first few packets): + [nbns] 2014-12-08 18:19:13 192.168.204.137:137 -> 192.168.204.2:137 ** + Transaction ID: 0xb480 + Info: NB_NAME_QUERY + Client Hostname: WPAD + Client MAC: 00:0C:29:9D:B8:6D + ** + [nbns] 2014-12-08 18:19:14 192.168.204.137:137 -> 192.168.204.2:137 ** + Transaction ID: 0xb480 + Info: NB_NAME_QUERY + Client Hostname: WPAD + Client MAC: 00:0C:29:9D:B8:6D + ** + [nbns] 2014-12-08 18:19:16 192.168.204.137:137 -> 192.168.204.2:137 ** + Transaction ID: 0xb480 + Info: NB_NAME_QUERY + Client Hostname: WPAD + Client MAC: 00:0C:29:9D:B8:6D + ** + [nbns] 2014-12-08 18:19:17 192.168.204.137:137 -> 192.168.204.255:137 ** + Transaction ID: 0xb480 + Info: NB_NAME_QUERY + Client Hostname: WPAD + Client MAC: 00:0C:29:9D:B8:6D + ** + """, + bpf='(udp and port 137)', + output=AlertOutput(label=__name__), + author='dek', + ) + self.mac_address = None + self.client_hostname = None + self.xid = None + self.prot_info = None + + + def packet_handler(self, pkt): + + # iterate through the layers and find the NBNS layer + nbns_packet = pkt.pkt.upper_layer + try: + nbns_packet = nbns_packet.upper_layer + except (IndexError) as e: + self.out.log('{}: could not parse session data \ + (NBNS packet not found)'.format(str(e))) + # pypacker may throw an Exception here; could use + # further testing + return + + + # Extract the Client hostname from the connection data + # It is represented as 32-bytes half-ASCII + try: + nbns_name = unpack('32s', pkt.data[13:45])[0] + except error as e: + self.out.log('{}: (NBNS packet not found)'.format(str(e))) + return + + + # Decode the 32-byte half-ASCII name to its 16 byte NetBIOS name + try: + if len(nbns_name) == 32: + decoded = [] + for i in range(0,32,2): + nibl = hex(ord(chr(nbns_name[i])) - ord('A'))[2:] + nibh = hex(ord(chr(nbns_name[i+1])) - ord('A'))[2:] + decoded.append(chr(int(''.join((nibl, nibh)), 16))) + + # For uniformity, strip excess byte and space chars + self.client_hostname = ''.join(decoded)[0:-1].strip() + else: + self.client_hostname = str(nbns_name) + + except ValueError as e: + self.out.log('{}: Hostname in improper format \ + (NBNS packet not found)'.format(str(e))) + return + + + # Extract the Transaction ID from the NBNS packet + xid = unpack('2s', pkt.data[0:2])[0] + self.xid = "0x{}".format(xid.hex()) + + # Extract the opcode info from the NBNS Packet + op = unpack('2s', pkt.data[2:4])[0] + op_hex = op.hex() + op = int(op_hex, 16) + # Remove excess bits + op = (op >> 11) & 15 + + # Decode protocol info if it was present in the payload + try: + self.prot_info = nbns_op[op] + except: + self.prot_info = "0x{}".format(op_hex) + + # Extract the MAC address from the ethernet layer of the packet + self.mac_address = pkt.smac + + # Allow for unknown hostnames + if not self.client_hostname: + self.client_hostname = "" + + if self.xid and self.prot_info and self.client_hostname and self.mac_address: + self.write('\n\tTransaction ID:\t\t{:<8} \n\tInfo:\t\t\t{:<16} \n\tClient Hostname:\t{:<16} \n\tClient MAC:\t\t{:<18}\n'.format( + self.xid, self.prot_info, self.client_hostname, self.mac_address), **pkt.info(), dir_arrow='->') + return pkt + +if __name__ == "__main__": + print(DshellPlugin()) diff --git a/dshell/plugins/portscan/__init__.py b/dshell/plugins/portscan/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/dshell/plugins/portscan/indegree.py b/dshell/plugins/portscan/indegree.py new file mode 100644 index 0000000..4bdc338 --- /dev/null +++ b/dshell/plugins/portscan/indegree.py @@ -0,0 +1,35 @@ +""" +Parse traffic to detect scanners based on connection to IPs that are rarely touched by others +""" + +import dshell.core + +class DshellPlugin(dshell.core.ConnectionPlugin): + + def __init__(self): + super().__init__( + name='parse indegree', + description='Parse traffic to detect scanners based on connection to IPs that are rarely touched by others', + bpf='(tcp or udp)', + author='dev195', + ) + self.client_conns = {} + self.server_conns = {} + self.minhits = 3 + + def connection_handler(self, conn): + self.client_conns.setdefault(conn.clientip, set()) + self.server_conns.setdefault(conn.serverip, set()) + + self.client_conns[conn.clientip].add(conn.serverip) + self.server_conns[conn.serverip].add(conn.clientip) + + def postfile(self): + for clientip, serverips in self.client_conns.items(): + target_count = len(serverips) + S = min((len(self.server_conns[serverip]) for serverip in serverips)) + if S > 2 or target_count < 5: + continue + # TODO implement whitelist + self.write("Scanning IP: {} / S score: {:.1f} / Number of records: {}".format(clientip, S, target_count)) + diff --git a/dshell/plugins/portscan/trw.py b/dshell/plugins/portscan/trw.py new file mode 100644 index 0000000..e2f638b --- /dev/null +++ b/dshell/plugins/portscan/trw.py @@ -0,0 +1,93 @@ +""" +Uses the Threshold Random Walk algorithm described in this paper: + +Limitations to threshold random walk scan detection and mitigating enhancements +Written by: Mell, P.; Harang, R. +http://ieeexplore.ieee.org/xpls/icp.jsp?arnumber=6682723 +""" + +import dshell.core +from dshell.output.output import Output + +from pypacker.layer4 import tcp + +from collections import defaultdict + +o0 = 0.8 # probability IP is benign given successful connection +o1 = 0.2 # probability IP is a scanner given successful connection +is_success = o0/o1 +is_failure = o1/o0 + +max_fp_prob = 0.01 +min_detect_prob = 0.99 +hi_threshold = min_detect_prob / max_fp_prob +lo_threshold = max_fp_prob / min_detect_prob + +OUTPUT_FORMAT = "(%(plugin)s) %(data)s\n" + +class DshellPlugin(dshell.core.PacketPlugin): + def __init__(self, *args, **kwargs): + super().__init__( + name="trw", + author="dev195", + bpf="tcp", + output=Output(label=__name__, format=OUTPUT_FORMAT), + description="Uses Threshold Random Walk to detect network scanners", + optiondict={ + "mark_benigns": { + "action": "store_true", + "help": "Use an upper threshold to mark IPs as benign, thus removing them from consideration as scanners" + } + } + ) + self.synners = set() + self.ip_scores = defaultdict(lambda: 1) + self.classified_ips = set() + + def check_score(self, ip, score): + if self.mark_benigns and score >= hi_threshold: + self.write("IP {} is benign (score: {})".format(ip, score)) + self.classified_ips.add(ip) + elif score <= lo_threshold: + self.write("IP {} IS A SCANNER! (score: {})".format(ip, score)) + self.classified_ips.add(ip) + + def packet_handler(self, pkt): + if not pkt.tcp_flags: + return + + # If we have a SYN, store it in a set and wait for some kind of + # response or the end of pcap + if pkt.tcp_flags == tcp.TH_SYN and pkt.sip not in self.classified_ips: + self.synners.add(pkt.addr) + return pkt + + # If we get the SYN/ACK, score the destination IP with a success + elif pkt.tcp_flags == (tcp.TH_SYN | tcp.TH_ACK) and pkt.dip not in self.classified_ips: + alt_addr = ((pkt.dip, pkt.dport), (pkt.sip, pkt.sport)) + if alt_addr in self.synners: + self.ip_scores[pkt.dip] *= is_success + self.check_score(pkt.dip, self.ip_scores[pkt.dip]) + self.synners.remove(alt_addr) + return pkt + + # If we get a RST, assume the connection was refused and score the + # destination IP with a failure + elif pkt.tcp_flags & tcp.TH_RST and pkt.dip not in self.classified_ips: + alt_addr = ((pkt.dip, pkt.dport), (pkt.sip, pkt.sport)) + if alt_addr in self.synners: + self.ip_scores[pkt.dip] *= is_failure + self.check_score(pkt.dip, self.ip_scores[pkt.dip]) + self.synners.remove(alt_addr) + return pkt + + + def postfile(self): + # Go through any SYNs that didn't get a response and assume they failed + for addr in self.synners: + ip = addr[0][0] + if ip in self.classified_ips: + continue + self.ip_scores[ip] *= is_failure + self.check_score(ip, self.ip_scores[ip]) + diff --git a/dshell/plugins/protocol/__init__.py b/dshell/plugins/protocol/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/decoders/protocol/bitcoin.py b/dshell/plugins/protocol/bitcoin.py similarity index 64% rename from decoders/protocol/bitcoin.py rename to dshell/plugins/protocol/bitcoin.py index 37035bc..015be19 100644 --- a/decoders/protocol/bitcoin.py +++ b/dshell/plugins/protocol/bitcoin.py @@ -1,9 +1,14 @@ -import dshell -import util -import binascii +""" +Bitcoin plugin +""" + +import dshell.core +from dshell.output.alertout import AlertOutput + import json from struct import unpack + # Magic values used to determine Bitcoin Network Type # Bitcoin Testnet is an alternative blockchain used for testing MAGIC_VALS = {'F9 BE B4 D9': 'BITCOIN-MAIN', @@ -11,20 +16,25 @@ '0B 11 09 07': 'BITCOIN-TESTNET3'} -class DshellDecoder(dshell.TCPDecoder): +class DshellPlugin(dshell.core.ConnectionPlugin): def __init__(self): - dshell.TCPDecoder.__init__(self, - name='bitcoin', + super().__init__( name='bitcoin', description='Extract Bitcoin traffic, including Stratum mining protocol (pooled) traffic', longdescription=''' -The bitcoin decoder will extract any Bitcoin traffic attempting to find and output: +The bitcoin plugin will extract any Bitcoin traffic attempting to find and output: Client/server IP addresses, src/dst port numbers, MAC addresses of the machines used in the Bitcoin communication/transactions, timestamps of the packets, packet payload sizes in KB, and the Network type - ('Bitcoin Main' if Bitcoin data traffic) + ('Bitcoin Main' if Bitcoin data traffic). -Additionally for Stratum mining, it will attempt to extract: +Connection tuples are cached when BITCOIN-MAIN traffic is detected, such that following this, +any blobs in a cached connection that do not contain BITCOIN-MAIN magic bytes, are labeled +as part of a connection containing Bitcoin traffic. + +Any traffic on BITCOIN-MAIN's designated port will be labeled as potential Bitcoin traffic. + +Additionally for Stratum mining, the plugin will attempt to extract: Bitcoin miner being used, transaction methods used in each connection (mining.notify, mining.authorize, mining.get_transaction, mining.submit, etc.), User ID (Auth ID) used to access the Bitcoin mining pool, and possibly the password @@ -35,13 +45,13 @@ def __init__(self): generation transaction (part 2), merkle tree branches (hashes), block version, and the hash difficulty (n-bits) (The generation transactions and merkle tree branches are only optionally outputted - to a file: See Example (3) below) + to a file: See Example (2) below) Note (1): The first time that all of this Stratum mining information is collected (per connection), all of the packets decoded after this point from within the same connection (same exact sip, dip, sport, dport) will continue to output the same collection of information since it - will be the same. + will be the same, and is cumulative per connection. Note (2): The gen_tx1 and gen_tx2 fields enable the miner to build the coinbase transaction for the block by concatentating gen_tx1, the extranonce1 @@ -68,20 +78,17 @@ def __init__(self): Examples: - + (1) Basic usage: decode -d bitcoin - (2) If pcap starts in middle of connection (then we need to ignore TCP handshake): - - decode -d bitcoin --bitcoin_ignore_handshake - (3) Saving Generation Transaction Data and Merkle Branches to a specified file: + (2) Saving Generation Transaction Data and Merkle Branches to a specified file: decode -d bitcoin --bitcoin_gentx='foo.txt.' ''', - filter='''tcp and port (3332 or 3333 or 3334 or 3335 or + bpf='''(tcp and port (3332 or 3333 or 3334 or 3335 or 4008 or 4012 or 4016 or 4024 or 4032 or 4048 or 4064 or 4096 or 4128 or 4256 or 5050 or 7033 or @@ -89,12 +96,17 @@ def __init__(self): 8333 or 8334 or 8336 or 8337 or 8344 or 8347 or 8361 or 8888 or 9332 or 9337 or 9999 or 11111 or - 12222 or 17777 or 18333)''', + 12222 or 17777 or 18333))''', + output=AlertOutput(label=__name__), author='dek', optiondict={ - 'gentx' : {'type' : 'str', 'default' : '', 'help' : 'The name of the file to output the fields used to generate the block transaction (gen_tx1, gen_tx2, merkle_branches).'}, + 'gentx': { + 'type': str, + 'default': None, + 'help': 'The name of the file to output the fields used to generate the block transaction (gen_tx1, gen_tx2, merkle_branches) (default: None)' }, } - ) + ) + self.auth_ids = {} self.notify_params = {} self.methods = {} @@ -104,24 +116,26 @@ def __init__(self): self.dmac = None self.bc_net = None self.size = 0 + self.bcm_cache = set() self.JSON = False self.NOTIFY = False - # blobHandler to reassemble the packets in the traffic # Bitcoin traffic uses TCP - def blobHandler(self, conn, blob): - + def blob_handler(self, conn, blob): try: - data = blob.data() + data = blob.data + data_str = ''.join(chr(x) for x in data) + data_len = len(data) except: - self.warn('could not parse session data') + self.out.log('could not parse session data') return - + # Only continue if the packet contains data if not data: return + # Default mining.notify fields to None job_id = None prev_blk_hash = None @@ -132,13 +146,13 @@ def blobHandler(self, conn, blob): difficulty = None curr_time = None clean_jobs = None - + # If the payload contains JSON - if data.startswith('{"'): + if data_str.startswith('{"'): self.JSON = True try: # split JSON objects by newline - for rawjs in data.split("\n"): + for rawjs in data_str.split("\n"): if rawjs: js = json.loads(rawjs) try: @@ -149,7 +163,7 @@ def blobHandler(self, conn, blob): if js["method"] == "mining.subscribe": self.miners[conn.addr] = js["params"][0] - + if js["method"] == "mining.authorize": if "params" in js and js['params'][0]: # Grab the Bitcoin User ID (sometimes a wallet id) @@ -159,7 +173,7 @@ def blobHandler(self, conn, blob): if js['params'][1]: self.auth_ids[conn.addr] = "".join(( self.auth_ids[conn.addr], " / ", str(js['params'][1]) )) - + if js["method"] == "mining.notify": self.NOTIFY = True if "params" in js and js['params']: @@ -171,34 +185,47 @@ def blobHandler(self, conn, blob): clean_jobs] except KeyError as e: - self.warn("{} - Error extracting auth ID".format(str(e))) + self.out.log("{} - Error extracting auth ID".format(str(e))) except ValueError as e: - self.warn('{} - json data not found'.format(str(e))) + self.out.log('{} - json data not found'.format(str(e))) return - + + # Grab the first 4 bytes of the payload to search for the magic values # used to determine which Bitcoin network is being accessed # Additionally, reformat bytes try: - magic_val = binascii.hexlify(data[0:4]).upper() + magic_val = data[0:4].hex().upper() magic_val = ' '.join([magic_val[i:i+2] for i in range(0, len(magic_val), 2)]) except: - self.warn('could not parse session data') + self.out.log('could not parse session data') return - # Attempt to translate first 4 bytes of payload - # into a Bitcoin (bc) network type + # Attempt to translate first 4 bytes of payload into a Bitcoin (bc) + # network type, and determine if blob is part of connection which + # contained BITCOIN-MAIN traffic, or if using BITCOIN-MAIN port, or + # if part of Stratum mining try: self.bc_net = str(MAGIC_VALS[magic_val]) + if self.bc_net == 'BITCOIN-MAIN': + self.bcm_cache.add(conn.addr) except: - self.bc_net = 'N/A' + if conn.addr in self.bcm_cache: + self.bc_net = 'Potential BITCOIN-MAIN (part of connection which detected BITCOIN-MAIN traffic)' + elif (blob.sport == 8333 or blob.dport == 8333): + self.bc_net = 'Potential BITCOIN-MAIN traffic (using designated port)' + # Stratum mining methods have been detected + elif (self.methods): + self.bc_net = 'STRATUM MINING' + else: + self.bc_net = 'N/A (Likely just traffic over a known Bitcoin/Stratum mining port)' # Pull pertinent information from packet's contents - self.size = '{0:.2f}'.format((len(blob.data())/1024.0)) - self.smac = conn.smac - self.dmac = conn.dmac - + self.size = '{0:.2f}'.format(data_len/1024.0) + # Pull source MAC and dest MAC from first packet in each connection + self.smac = blob.smac + self.dmac = blob.dmac # Truncate the list Job IDs per connection for printing purposes if JSON # data was found in the blob @@ -216,55 +243,57 @@ def blobHandler(self, conn, blob): self.JSON = False self.NOTIFY = False + # If able to pull the Bitcoin Pool User ID (sometimes a wallet ID) - # Also if the transcation is mining.notify (seen in Stratum mining) + # Also if the transcation is mining.notify (seen in Stratum mining) or Stratum mining + # detected via keywords # then output the current Block information if (self.size and self.smac and self.dmac and self.miners.get(conn.addr, None) and self.methods.get(conn.addr, None) and self.auth_ids.get(conn.addr, None) and self.notify_params.get(conn.addr, None) and not self.gentx): - self.alert("\n\tSRC_MAC: \t{0:<20} \n\tDST_MAC: \t{1:<20} \n\tSIZE: \t\t{2:>3}KB\n\t" - "MINER: \t\t{3:<20} \n\tMETHODS: \t{4:<25} \n\tUSER ID/PW: \t{5:<50}\n\t" - "JOB IDs: \t{6:<20} \n\tPREV BLK HASH: \t{7:<65} \n\tBLOCK VER: \t{8:<15}\n\t" - "HASH DIFF: \t{9:<10}\n\n".format( - self.smac, self.dmac, self.size, - self.miners[conn.addr], self.methods[conn.addr], self.auth_ids[conn.addr], - self.notify_params[conn.addr][0][conn.addr], self.notify_params[conn.addr][1], - self.notify_params[conn.addr][5], self.notify_params[conn.addr][6]), - ts=blob.starttime, sip=conn.sip, dip=conn.dip, sport=conn.sport, - dport=conn.dport, direction=blob.direction) + self.write("\n\tNETWORK: \t{0:<15} \n\tSRC_MAC: \t{1:<20} \n\tDST_MAC: \t{2:<20} \n\tSIZE: \t\t{3:>3}KB\n\t" + "MINER: \t\t{4:<20} \n\tMETHODS: \t{5:<25} \n\tUSER ID/PW: \t{6:<50}\n\t" + "JOB IDs: \t{7:<20} \n\tPREV BLK HASH: \t{8:<65} \n\tBLOCK VER: \t{9:<15}\n\t" + "HASH DIFF: \t{10:<10}\n\n".format( + self.bc_net, self.smac, self.dmac, self.size, + self.miners[conn.addr], ', '.join(self.methods[conn.addr]), self.auth_ids[conn.addr], + ', '.join(self.notify_params[conn.addr][0][conn.addr]), self.notify_params[conn.addr][1], + self.notify_params[conn.addr][5], self.notify_params[conn.addr][6]), + ts=blob.starttime, sip=conn.sip, dip=conn.dip, sport=conn.sport, + dport=conn.dport, direction=blob.direction) # If able to pull the Bitcoin Pool User ID (sometimes a wallet ID) - # Also if the transcation is mining.notify (seen in Stratum mining) and the user - # specifies that they want to save the fields used to generate the block transaction - # (gen_tx1, gen_tx2 (hashes with scriptPubKeys), merkle tree branches), then - # output all information possible, and write the gentx information to the specified file + # Also if the transcation is mining.notify (seen in Stratum mining) or Stratum mining + # detected via keywords and the user specifies that they want to save the fields used + # to generate the block transaction (gen_tx1, gen_tx2 (hashes with scriptPubKeys), merkle tree branches), + # then output all information possible, and write the gentx information to the specified file elif (self.size and self.smac and self.dmac and self.miners.get(conn.addr, None) and self.methods.get(conn.addr, None) and self.auth_ids.get(conn.addr, None) and self.notify_params.get(conn.addr, None) and self.gentx): - self.alert("\n\tSRC_MAC: \t{0:<20} \n\tDST_MAC: \t{1:<20} \n\tSIZE: \t\t{2:>3}KB\n\t" - "MINER: \t\t{3:<20} \n\tMETHODS: \t{4:<25} \n\tUSER ID/PW: \t{5:<50}\n\t" - "JOB IDs: \t{6:<20} \n\tPREV BLK HASH: \t{7:<65} \n\tBLOCK VER: \t{8:<15}\n\t" - "HASH DIFF: \t{9:<10}\n\n".format( - self.smac, self.dmac, self.size, - self.miners[conn.addr], self.methods[conn.addr], self.auth_ids[conn.addr], - self.notify_params[conn.addr][0][conn.addr], self.notify_params[conn.addr][1], - self.notify_params[conn.addr][5], self.notify_params[conn.addr][6]), - ts=blob.starttime, sip=conn.sip, dip=conn.dip, sport=conn.sport, - dport=conn.dport, direction=blob.direction) + self.write("\n\tNETWORK: \t{0:<15} \n\tSRC_MAC: \t{1:<20} \n\tDST_MAC: \t{2:<20} \n\tSIZE: \t\t{3:>3}KB\n\t" + "MINER: \t\t{4:<20} \n\tMETHODS: \t{5:<25} \n\tUSER ID/PW: \t{6:<50}\n\t" + "JOB IDs: \t{7:<20} \n\tPREV BLK HASH: \t{8:<65} \n\tBLOCK VER: \t{9:<15}\n\t" + "HASH DIFF: \t{10:<10}\n\n".format( + self.bc_net, self.smac, self.dmac, self.size, + self.miners[conn.addr], ', '.join(self.methods[conn.addr]), self.auth_ids[conn.addr], + ', '.join(self.notify_params[conn.addr][0][conn.addr]), self.notify_params[conn.addr][1], + self.notify_params[conn.addr][5], self.notify_params[conn.addr][6]), + ts=blob.starttime, sip=conn.sip, dip=conn.dip, sport=conn.sport, + dport=conn.dport, direction=blob.direction) # Write the verbose block information (gen tx1/2, merkle branches) gathered # from mining.notify payloads to the command-line specified output file # The extra information (JOB ID, BLOCK VER, etc.) will be useful in matching the # information outputted by the alerts to the payload containing the # generation transaction info and merkle branches - fout = open(self.gentx, "a+") + fout = open(self.gentx, "a+") fout.write(("\nJOB IDs: \t\t{0:<20} \nPREV BLK HASH: \t{1:<65} \n\nGEN TX1: \t\t{2:<20}" "\n\nGEN TX2: \t\t{3:<20} \n\nMERKLE BRANCHES: {4:<20} \n\nBLOCK VER: \t\t{5:<20}" "\nHASH DIFF: \t\t{6:<10}\n").format( - self.notify_params[conn.addr][0][conn.addr], self.notify_params[conn.addr][1], + ', '.join(self.notify_params[conn.addr][0][conn.addr]), self.notify_params[conn.addr][1], self.notify_params[conn.addr][2], self.notify_params[conn.addr][3], - self.notify_params[conn.addr][4], self.notify_params[conn.addr][5], + ', '.join(self.notify_params[conn.addr][4]), self.notify_params[conn.addr][5], self.notify_params[conn.addr][6])) fout.write(("\n" + "-"*100)*2) @@ -272,13 +301,15 @@ def blobHandler(self, conn, blob): # Else if we dont have Bitcoin User IDs, or Block information # and the user doesn't want verbose block information (gentx) elif (self.size and self.smac and self.dmac and self.bc_net): - self.alert("\n\tNETWORK: \t{0:<15} \n\tSRC_MAC: \t{1:<20} \n\tDST_MAC: \t{2:<20} \n\tSIZE: \t\t{3:>3}KB\n\n".format( + self.write("\n\tNETWORK: \t{0:<15} \n\tSRC_MAC: \t{1:<20} \n\tDST_MAC: \t{2:<20} \n\tSIZE: \t\t{3:>3}KB\n\n".format( self.bc_net, self.smac, self.dmac, self.size), ts=blob.starttime, sip=conn.sip, dip=conn.dip, sport=conn.sport, dport=conn.dport, direction=blob.direction) - -if __name__ == '__main__': - dObj = DshellDecoder() - print dObj -else: - dObj = DshellDecoder() + + return conn, blob + + + +if __name__ == "__main__": + print(DshellPlugin()) + diff --git a/dshell/plugins/protocol/ether.py b/dshell/plugins/protocol/ether.py new file mode 100644 index 0000000..b6e5826 --- /dev/null +++ b/dshell/plugins/protocol/ether.py @@ -0,0 +1,66 @@ +""" +Shows MAC address information and optionally filters by it. It is highly +recommended that oui.txt be included in the share/ directory (see README). +""" + +import os +import dshell.core +from dshell.output.output import Output +from dshell.util import get_data_path + +class DshellPlugin(dshell.core.PacketPlugin): + OUTPUT_FORMAT = "[%(plugin)s] %(dt)s %(sip)-15s %(smac)-18s %(smac_org)-35s -> %(dip)-15s %(dmac)-18s %(dmac_org)-35s %(byte_count)d\n" + + def __init__(self, *args, **kwargs): + super().__init__( + name="Ethernet", + description="Show MAC address information and optionally filter by it", + author="dev195", + output=Output(label=__name__, format=self.OUTPUT_FORMAT), + optiondict={ + "org": {"default":[], "action":"append", "metavar":"ORGANIZATION", "help":"Organizations owning MAC address to inclusively filter on (exact match only). Can be used multiple times to look for multiple organizations."}, + "org_exclusive": {"default":False, "action":"store_true", "help":"Set organization filter to be exclusive"}, + 'quiet': {'action': 'store_true', 'default':False, 'help':'disable alerts for this plugin'} + } + ) + self.oui_map = {} + + def premodule(self): + # Create a mapping of MAC address prefix to organization + # http://standards-oui.ieee.org/oui.txt + ouifilepath = os.path.join(get_data_path(), 'oui.txt') + try: + with open(ouifilepath, encoding="utf-8") as ouifile: + for line in ouifile: + if "(hex)" not in line: + continue + line = line.strip().split(None, 2) + prefix = line[0].replace('-', ':') + org = line[2] + self.oui_map[prefix] = org + except FileNotFoundError: + # user probably did not download it + # print warning and continue + self.warn("Could not find {} (see README). Will not be able to determine MAC organizations.".format(ouifilepath)) + + def packet_handler(self, pkt): + if not pkt.smac or not pkt.dmac: + return + smac_prefix = pkt.smac[:8].upper() + smac_org = self.oui_map.get(smac_prefix, '???') + dmac_prefix = pkt.dmac[:8].upper() + dmac_org = self.oui_map.get(dmac_prefix, '???') + + # Filter out any packets that do not match organization filter + if self.org: + if self.org_exclusive and (smac_org in self.org or dmac_org in self.org): + return + elif not self.org_exclusive and not (smac_org in self.org or dmac_org in self.org): + return + + if not self.quiet: + self.write("", smac_org=smac_org, dmac_org=dmac_org, **pkt.info()) + return pkt + +if __name__ == "__main__": + print(DshellPlugin()) diff --git a/dshell/plugins/protocol/ip.py b/dshell/plugins/protocol/ip.py new file mode 100644 index 0000000..607c2ed --- /dev/null +++ b/dshell/plugins/protocol/ip.py @@ -0,0 +1,24 @@ +""" +Outputs all IPv4/IPv6 traffic, and hex plus ascii with verbose flag +""" + +import dshell.core +import dshell.util +from dshell.output.alertout import AlertOutput + +class DshellPlugin(dshell.core.PacketPlugin): + + def __init__(self): + super().__init__( + name='ip', + description='IPv4/IPv6 plugin', + bpf='ip or ip6', + author='twp', + output=AlertOutput(label=__name__), + ) + + def packet_handler(self, packet): + self.write(**packet.info(), dir_arrow='->') + # If verbose flag set, outputs packet contents in hex and ascii alongside packet info + self.out.log("\n" + dshell.util.hex_plus_ascii(packet.rawpkt)) + return packet diff --git a/dshell/plugins/protocol/protocol.py b/dshell/plugins/protocol/protocol.py new file mode 100644 index 0000000..d8c175b --- /dev/null +++ b/dshell/plugins/protocol/protocol.py @@ -0,0 +1,22 @@ +""" +Tries to find traffic that does not belong to the following protocols: +TCP, UDP, or ICMP +""" + +import dshell.core +from dshell.output.alertout import AlertOutput + +class DshellPlugin(dshell.core.PacketPlugin): + + def __init__(self): + super().__init__( + name="Uncommon Protocols", + description="Finds uncommon (i.e. not tcp, udp, or icmp) protocols in IP traffic", + bpf="(ip or ip6) and not tcp and not udp and not icmp and not icmp6", + author="bg", + output=AlertOutput(label=__name__), + ) + + def packet_handler(self, packet): + self.write("PROTOCOL: {} ({})".format(packet.protocol, packet.protocol_num), **packet.info(), dir_arrow="->") + return packet diff --git a/dshell/plugins/ssl/__init__.py b/dshell/plugins/ssl/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/dshell/plugins/ssl/sslblacklist.py b/dshell/plugins/ssl/sslblacklist.py new file mode 100644 index 0000000..668bcea --- /dev/null +++ b/dshell/plugins/ssl/sslblacklist.py @@ -0,0 +1,124 @@ +""" +Looks for certificates in SSL/TLS traffic and tries to find any hashes that +match those in the abuse.ch blacklist. +(https://sslbl.abuse.ch/blacklist/) +""" + +# handy reference: +# http://blog.fourthbit.com/2014/12/23/traffic-analysis-of-an-ssl-slash-tls-session + +import dshell.core +from dshell.output.alertout import AlertOutput + +import hashlib +import io +import struct + +# SSLv3/TLS version +SSL3_VERSION = 0x0300 +TLS1_VERSION = 0x0301 +TLS1_1_VERSION = 0x0302 +TLS1_2_VERSION = 0x0303 + +# Record type +SSL3_RT_CHANGE_CIPHER_SPEC = 20 +SSL3_RT_ALERT = 21 +SSL3_RT_HANDSHAKE = 22 +SSL3_RT_APPLICATION_DATA = 23 + +# Handshake message type +SSL3_MT_HELLO_REQUEST = 0 +SSL3_MT_CLIENT_HELLO = 1 +SSL3_MT_SERVER_HELLO = 2 +SSL3_MT_CERTIFICATE = 11 +SSL3_MT_SERVER_KEY_EXCHANGE = 12 +SSL3_MT_CERTIFICATE_REQUEST = 13 +SSL3_MT_SERVER_DONE = 14 +SSL3_MT_CERTIFICATE_VERIFY = 15 +SSL3_MT_CLIENT_KEY_EXCHANGE = 16 +SSL3_MT_FINISHED = 20 + + +class DshellPlugin(dshell.core.ConnectionPlugin): + + def __init__(self): + super().__init__( + name="sslblacklist", + author="dev195", + bpf="tcp and (port 443 or port 993 or port 1443 or port 8531)", + description="Looks for certificate SHA1 matches in the abuse.ch blacklist", + longdescription=""" + Looks for certificates in SSL/TLS traffic and tries to find any hashes that + match those in the abuse.ch blacklist. + + Requires downloading the blacklist CSV from abuse.ch: + https://sslbl.abuse.ch/blacklist/ + + If the CSV is not in the current directory, use the --sslblacklist_csv + argument to provide a file path. +""", + output=AlertOutput(label=__name__), + optiondict={ + "csv": { + "help": "filepath to the sslblacklist.csv file", + "default": "./sslblacklist.csv", + "metavar": "FILEPATH" + }, + } + ) + + def premodule(self): + self.parse_blacklist_csv(self.csv) + + def parse_blacklist_csv(self, filepath): + "parses the SSL blacklist CSV, given the 'filepath'" + # Python's standard csv module doesn't seem to handle it properly + self.hashes = {} + with open(filepath, 'r') as csv: + for line in csv: + line = line.split('#')[0] # ignore comments + line = line.strip() + try: + timestamp, sha1, reason = line.split(',', 3) + self.hashes[sha1] = reason + except ValueError: + continue + + def blob_handler(self, conn, blob): + if blob.direction == 'cs': + return None + + data = io.BytesIO(blob.data) + + # Iterate over each layer of the connection, paying special attention to the certificate + while True: + try: + content_type, proto_version, record_len = struct.unpack("!BHH", data.read(5)) + except struct.error: + break + if proto_version not in (SSL3_VERSION, TLS1_VERSION, TLS1_1_VERSION, TLS1_2_VERSION): + return None + if content_type == SSL3_RT_HANDSHAKE: + handshake_type = struct.unpack("!B", data.read(1))[0] + handshake_len = struct.unpack("!I", b"\x00"+data.read(3))[0] + if handshake_type == SSL3_MT_CERTIFICATE: + # Process the certificate itself + cert_chain_len = struct.unpack("!I", b"\x00"+data.read(3))[0] + bytes_processed = 0 + while (bytes_processed < cert_chain_len): + try: + cert_data_len = struct.unpack("!I", b"\x00"+data.read(3))[0] + cert_data = data.read(cert_data_len) + bytes_processed = 3 + cert_data_len + sha1 = hashlib.sha1(cert_data).hexdigest() + if sha1 in self.hashes: + bad_guy = self.hashes[sha1] + self.write("Certificate hash match: {}".format(bad_guy), **conn.info()) + except struct.error as e: + break + else: + # Ignore any layers that are not a certificate + data.read(handshake_len) + continue + + return conn, blob diff --git a/dshell/plugins/tftp/__init__.py b/dshell/plugins/tftp/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/decoders/tftp/tftp.py b/dshell/plugins/tftp/tftp.py similarity index 58% rename from decoders/tftp/tftp.py rename to dshell/plugins/tftp/tftp.py index f5a8c96..de5e9dd 100644 --- a/decoders/tftp/tftp.py +++ b/dshell/plugins/tftp/tftp.py @@ -1,5 +1,5 @@ """ -TFTP Decoder +TFTP Plugin In short: Goes through UDP traffic, packet by packet, and ties together TFTP file streams. If the command line argument is set (--tftp_rip), it will dump the @@ -7,8 +7,8 @@ In long: Goes through each UDP packet and parses out the TFTP opcode. For read or - write requests, it sets a placeholder in unsetReadStreams or unsetWriteStreams, - respectively. These placeholders are moved to openStreams when we first see + write requests, it sets a placeholder in unset_read_streams or unset_write_streams, + respectively. These placeholders are moved to open_streams when we first see data for the read request or an ACK code for a write request. The reason for these placeholders is to allow the server to set the ephemeral port during data transfer. @@ -19,34 +19,37 @@ later. When we consider a stream finished (either the DATA packet is too short or there are no more packets), we rebuild the file data, print information about the stream, dump the file (optional), and move the information from - openStreams to closedStreams. + open_streams to closed_streams. Example: Running on sample pcap available here: https://wiki.wireshark.org/TFTP With default values, it will display transfers performed - Dshell> decode -d tftp ~/pcap/tftp_*.pcap + Dshell> decode -d tftp ~/pcap/tftp_*.pcap tftp 2013-05-01 08:24:11 192.168.0.253:50618 -- 192.168.0.10:3445 ** read rfc1350.txt (24599 bytes) ** tftp 2013-04-27 05:07:59 192.168.0.1:57509 -- 192.168.0.13:2087 ** write rfc1350.txt (24599 bytes) ** - With the --tftp_rip flag, it will generate the same output while reassembling + With the --tftp_rip flag, it will generate the same output while reassembling the files and saving them in a defined directory (./tftp_out by default) - Dshell> decode -d tftp --tftp_rip --tftp_outdir=./MyTFTP ~/pcap/tftp_*.pcap + Dshell> decode -d tftp --tftp_rip --tftp_outdir=./MyTFTP ~/pcap/tftp_*.pcap tftp 2013-05-01 08:24:11 192.168.0.253:50618 -- 192.168.0.10:3445 ** read rfc1350.txt (24599 bytes) ** tftp 2013-04-27 05:07:59 192.168.0.1:57509 -- 192.168.0.13:2087 ** write rfc1350.txt (24599 bytes) ** Dshell> ls ./MyTFTP/ rfc1350.txt rfc1350.txt_01 - Note: The two files have the same name in the traffic, but have incremented + Note: The two files have the same name in the traffic, but have incremented filenames when saved - """ -import dshell -import dpkt -import struct +import dshell.core +import dshell.util +from dshell.output.alertout import AlertOutput + +from pypacker.layer4 import udp + import os +import struct -class DshellDecoder(dshell.IPDecoder): - "Primary decoder class" +class DshellPlugin(dshell.core.PacketPlugin): + "Primary plugin class" # packet opcodes (http://www.networksorcery.com/enp/default1101.htm) RRQ = 1 # read request WRQ = 2 # write request @@ -56,19 +59,26 @@ class DshellDecoder(dshell.IPDecoder): OACK = 6 # option acknowledgment def __init__(self, **kwargs): - dshell.IPDecoder.__init__(self, - name="tftp", - filter="udp", - description="Find TFTP streams and, optionally, extract the files", - longdescription="Find TFTP streams and, optionally, extract the files", - author="dev195", - optiondict={ - "rip": {"action": "store_true", "help": "Rip files from traffic (default: off)", "default": False}, - "outdir": {"help": "Directory to place files when using --rip", "default": "./tftp_out", "metavar": "DIRECTORY"}} - ) + super().__init__( + name="tftp", + bpf="udp", + description="Find TFTP streams and, optionally, extract the files", + author="dev195", + output=AlertOutput(label=__name__), + optiondict={ + "rip": { + "action": "store_true", + "help": "Rip files from traffic (default: off)", + "default": False}, + "outdir": { + "help": "Directory to place files when using --rip (default: tftp_out)", + "default": "./tftp_out", + "metavar": "DIRECTORY"} + } + ) # default information for streams we didn't see the start for - self.defaultStream = { + self.default_stream = { 'filename': '', 'mode': '', 'readwrite': '', @@ -78,41 +88,45 @@ def __init__(self, **kwargs): } # containers for various states of streams - self.openStreams = {} - self.closedStreams = [] + self.open_streams = {} + self.closed_streams = [] # These two are holders while waiting for the server to decide on which # ephemeral port to use - self.unsetWriteStreams = {} - self.unsetReadStreams = {} + self.unset_write_streams = {} + self.unset_read_streams = {} - def preModule(self): + def premodule(self): "if needed, create the directory for file output" if self.rip and not os.path.exists(self.outdir): try: os.makedirs(self.outdir) except OSError: - self.error( - "Could not create directory '%s'. Files will not be dumped." % self.outdir) + self.error("Could not create directory {!r}. Files will not be dumped.".format(self.outdir)) self.rip = False - def postModule(self): + def postmodule(self): "cleanup any unfinished streams" - self.debug("Unset Read Streams: %s" % self.unsetReadStreams) - self.debug("Unset Write Streams: %s" % self.unsetWriteStreams) - while(len(self.openStreams) > 0): - k = self.openStreams.keys()[0] + self.debug("Unset Read Streams: {!s}".format(self.unset_read_streams)) + self.debug("Unset Write Streams: {!s}".format(self.unset_write_streams)) + while(len(self.open_streams) > 0): + k = list(self.open_streams)[0] self.__closeStream(k, "POSSIBLY INCOMPLETE") - def packetHandler(self, ip=None): + def packet_handler(self, pkt): """ Handles each UDP packet. It checks the TFTP opcode and parses accordingly. """ - try: - udp = dpkt.ip.IP(ip.pkt).data - except dpkt.UnpackError: - return - data = udp.data + udpp = pkt.pkt.upper_layer + while not isinstance(udpp, udp.UDP): + try: + udpp = udpp.upper_layer + except AttributeError: + # There doesn't appear to be a UDP layer, for some reason + return + + data = udpp.body_bytes + try: flag = struct.unpack("!H", data[:2])[0] except struct.error: @@ -121,50 +135,50 @@ def packetHandler(self, ip=None): if flag == self.RRQ: # this packet is requesting to read a file from the server try: - filename, mode = data.split("\x00")[0:2] + filename, mode = data.split(b"\x00")[0:2] except ValueError: return # probably not TFTP - clientIP, clientPort, serverIP, serverPort = ip.sip, udp.sport, ip.dip, udp.dport - self.unsetReadStreams[(clientIP, clientPort, serverIP)] = { + clientIP, clientPort, serverIP, serverPort = pkt.sip, udpp.sport, pkt.dip, udpp.dport + self.unset_read_streams[(clientIP, clientPort, serverIP)] = { 'filename': filename, 'mode': mode, 'readwrite': 'read', 'closed_connection': False, 'filedata': {}, - 'timestamp': ip.ts + 'timestamp': pkt.ts } elif flag == self.WRQ: # this packet is requesting to write a file to the server try: - filename, mode = data.split("\x00")[0:2] + filename, mode = data.split(b"\x00")[0:2] except ValueError: return # probably not TFTP # in this case, we are writing to the "server" - clientIP, clientPort, serverIP, serverPort = ip.sip, udp.sport, ip.dip, udp.dport - self.unsetWriteStreams[(clientIP, clientPort, serverIP)] = { + clientIP, clientPort, serverIP, serverPort = pkt.sip, udpp.sport, pkt.dip, udpp.dport + self.unset_write_streams[(clientIP, clientPort, serverIP)] = { 'filename': filename, 'mode': mode, 'readwrite': 'write', 'closed_connection': False, 'filedata': {}, - 'timestamp': ip.ts + 'timestamp': pkt.ts } elif flag == self.DATA: # this packet is sending a chunk of data - clientIP, clientPort, serverIP, serverPort = ip.sip, udp.sport, ip.dip, udp.dport + clientIP, clientPort, serverIP, serverPort = pkt.sip, udpp.sport, pkt.dip, udpp.dport key = (clientIP, clientPort, serverIP, serverPort) - if key not in self.openStreams: + if key not in self.open_streams: # this is probably an unset read stream; there is no # acknowledgement, it just starts sending data - if (serverIP, serverPort, clientIP) in self.unsetReadStreams: - self.openStreams[key] = self.unsetReadStreams[ + if (serverIP, serverPort, clientIP) in self.unset_read_streams: + self.open_streams[key] = self.unset_read_streams[ (serverIP, serverPort, clientIP)] - del(self.unsetReadStreams[ + del(self.unset_read_streams[ (serverIP, serverPort, clientIP)]) else: - self.openStreams[key] = self.defaultStream + self.open_streams[key] = self.default_stream blockNum = struct.unpack("!H", data[:2])[0] data = data[2:] if len(data) < 512: @@ -173,30 +187,30 @@ def packetHandler(self, ip=None): closedConn = True else: closedConn = False - self.openStreams[key]['filedata'][blockNum] = data - self.openStreams[key]['closed_connection'] = closedConn + self.open_streams[key]['filedata'][blockNum] = data + self.open_streams[key]['closed_connection'] = closedConn elif flag == self.ACK: # this packet has acknowledged the receipt of a data chunk or # allows a write process to begin blockNum = struct.unpack("!H", data[:2])[0] - clientIP, clientPort, serverIP, serverPort = ip.sip, udp.sport, ip.dip, udp.dport + clientIP, clientPort, serverIP, serverPort = pkt.sip, udpp.sport, pkt.dip, udpp.dport # special case: this is acknowledging a write operation and sets # the port for receiving if blockNum == 0: - clientIP, clientPort, serverIP, serverPort = ip.dip, udp.dport, ip.sip, udp.sport + clientIP, clientPort, serverIP, serverPort = pkt.dip, udpp.dport, pkt.sip, udpp.sport i = (clientIP, clientPort, serverIP) - if i in self.unsetWriteStreams: - self.openStreams[ - (clientIP, clientPort, serverIP, serverPort)] = self.unsetWriteStreams[i] - del(self.unsetWriteStreams[i]) + if i in self.unset_write_streams: + self.open_streams[ + (clientIP, clientPort, serverIP, serverPort)] = self.unset_write_streams[i] + del(self.unset_write_streams[i]) # otherwise, check if this is the confirmation for the end of a # connection - elif (clientIP, clientPort, serverIP, serverPort) in self.openStreams and self.openStreams[(clientIP, clientPort, serverIP, serverPort)]['closed_connection']: + elif (clientIP, clientPort, serverIP, serverPort) in self.open_streams and self.open_streams[(clientIP, clientPort, serverIP, serverPort)]['closed_connection']: self.__closeStream( (clientIP, clientPort, serverIP, serverPort)) - elif (serverIP, serverPort, clientIP, clientPort) in self.openStreams and self.openStreams[(serverIP, serverPort, clientIP, clientPort)]['closed_connection']: + elif (serverIP, serverPort, clientIP, clientPort) in self.open_streams and self.open_streams[(serverIP, serverPort, clientIP, clientPort)]['closed_connection']: self.__closeStream( (serverIP, serverPort, clientIP, clientPort)) @@ -206,29 +220,33 @@ def packetHandler(self, ip=None): errCode = struct.unpack("!H", data[:2])[0] errMessage = data[2:].strip() if errCode == 1: # File not found - clientIP, clientPort, serverIP, serverPort = ip.dip, udp.dport, ip.sip, udp.sport + clientIP, clientPort, serverIP, serverPort = pkt.dip, udpp.dport, pkt.sip, udpp.sport i = (clientIP, clientPort, serverIP) - if i in self.unsetReadStreams: - self.openStreams[ - (serverIP, serverPort, clientIP, clientPort)] = self.unsetReadStreams[i] - del(self.unsetReadStreams[i]) + if i in self.unset_read_streams: + self.open_streams[ + (serverIP, serverPort, clientIP, clientPort)] = self.unset_read_streams[i] + del(self.unset_read_streams[i]) self.__closeStream( (serverIP, serverPort, clientIP, clientPort), errMessage) elif flag == self.OACK: pass # TODO handle options + return pkt + def __closeStream(self, key, message=''): """ Called when a stream is finished. It moves the stream from - openStreams to closedStreams, prints output, and dumps the file + open_streams to closed_streams, prints output, and dumps the file """ - theStream = self.openStreams[key] + theStream = self.open_streams[key] if not theStream['filename']: message = "INCOMPLETE -- missing filename" + else: + theStream['filename'] = theStream['filename'].decode('utf-8', "backslashreplace") # Rebuild the file from the individual blocks - rebuiltFile = '' + rebuiltFile = b'' for i in sorted(theStream['filedata'].keys()): rebuiltFile += theStream['filedata'][i] @@ -240,51 +258,26 @@ def __closeStream(self, key, message=''): ipsNports = key # print out information about the stream - msg = "%s %s (%s bytes) %s" % ( - theStream['readwrite'], theStream['filename'], len(rebuiltFile), message) - self.alert(msg, ts=theStream['timestamp'], sip=ipsNports[0], - sport=ipsNports[1], dip=ipsNports[2], dport=ipsNports[3]) + msg = "{:5} {} ({} bytes) {}".format( + theStream['readwrite'], + theStream['filename'], + len(rebuiltFile), + message) + self.write(msg, ts=theStream['timestamp'], sip=ipsNports[0], + sport=ipsNports[1], dip=ipsNports[2], dport=ipsNports[3], + readwrite=theStream['readwrite'], filename=theStream['filename']) # dump the file, if that's what the user wants if self.rip and len(rebuiltFile) > 0: - outpath = self.__localfilename( - self.outdir, theStream['filename']) + outpath = dshell.util.gen_local_filename(self.outdir, theStream['filename']) outfile = open(outpath, 'wb') outfile.write(rebuiltFile) outfile.close() # remove the stream from the list of open streams - self.closedStreams.append(( + self.closed_streams.append(( key, - self.openStreams[key]['closed_connection'] + self.open_streams[key]['closed_connection'] )) - del(self.openStreams[key]) - - def __localfilename(self, path, origname): - """ - Generates a local file name based on the original - Taken from FTP decoder - """ - tmp = origname.replace("\\", "_") - tmp = tmp.replace("/", "_") - tmp = tmp.replace(":", "_") - localname = '' - for c in tmp: - if ord(c) > 32 and ord(c) < 127: - localname += c - else: - localname += "%%%02X" % ord(c) - localname = path + '/' + localname - postfix = '' - i = 0 - while os.path.exists(localname + postfix): - i += 1 - postfix = "_%02d" % i - return localname + postfix - + del(self.open_streams[key]) -if __name__ == '__main__': - dObj = DshellDecoder() - print dObj -else: - dObj = DshellDecoder() diff --git a/dshell/plugins/visual/__init__.py b/dshell/plugins/visual/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/dshell/plugins/visual/piecharts.py b/dshell/plugins/visual/piecharts.py new file mode 100644 index 0000000..404fc26 --- /dev/null +++ b/dshell/plugins/visual/piecharts.py @@ -0,0 +1,314 @@ +""" +Plugin that generates HTML+JavaScript pie charts for flow information +""" + +import dshell.core +from dshell.output.output import Output + +import operator +from collections import defaultdict + +class VisualizationOutput(Output): + """ + Special output class intended to only be used for this specific plugin. + """ + + _DEFAULT_FORMAT='{"value":%(data)s, "datatype":"%(datatype)s", "label":"%(label)s"},' + + _HTML_HEADER = """ + + + + Dshell - Pie Chart Output + + + + + +
      +
      + + + + + + + + + + + + + + +
      +

      Source Countries

      +
      +
      +

      Destination Countries

      +
      +
      +

      Source ASNs

      +
      +
      +

      Destination ASNs

      +
      +
      +

      Source Ports

      +
      +
      +

      Destination Ports

      +
      +
      +

      Protocols

      +
      +
      +
      + + +
      +
      + + + +""" + + def setup(self): + Output.setup(self) + self.fh.write(self._HTML_HEADER) + + def close(self): + self.fh.write(self._HTML_FOOTER) + Output.close(self) + +class DshellPlugin(dshell.core.ConnectionPlugin): + + def __init__(self): + super().__init__( + name='Pie Charts', + author='dev195', + bpf="ip", + description='Generates visualizations based on connections', + longdescription=""" +Generates HTML+JavaScript pie chart visualizations based on connections. + +Output should be redirected to a file and placed in a directory that has the d3.js JavaScript library. Library is available for download at https://d3js.org/ +""", + output=VisualizationOutput(label=__name__), + ) + + self.top_x = 10 + + def premodule(self): + "Set each of the counter dictionaries as defaultdict(int)" + # source + self.s_country_count = defaultdict(int) + self.s_asn_count = defaultdict(int) + self.s_port_count = defaultdict(int) + self.s_ip_count = defaultdict(int) + # dest + self.d_country_count = defaultdict(int) + self.d_asn_count = defaultdict(int) + self.d_port_count = defaultdict(int) + self.d_ip_count = defaultdict(int) + # protocol + self.proto = defaultdict(int) + + + def postmodule(self): + "Write the top X results for each type of data we're counting" + t = self.top_x + 1 + for i in sorted(self.proto.items(), reverse=True, key=operator.itemgetter(1))[:t]: + if i[0]: + self.write(int(i[1]), datatype="protocol", label=i[0]) + for i in sorted(self.s_country_count.items(), reverse=True, key=operator.itemgetter(1))[:t]: + if i[0] and i[0] != '--': + self.write(int(i[1]), datatype="source_country", label=i[0]) + for i in sorted(self.d_country_count.items(), reverse=True, key=operator.itemgetter(1))[:t]: + if i[0] and i[0] != '--': + self.write(int(i[1]), datatype="dest_country", label=i[0]) + for i in sorted(self.s_asn_count.items(), reverse=True, key=operator.itemgetter(1))[:t]: + if i[0] and i[0] != '--': + self.write(int(i[1]), datatype="source_asn", label=i[0]) + for i in sorted(self.d_asn_count.items(), reverse=True, key=operator.itemgetter(1))[:t]: + if i[0] and i[0] != '--': + self.write(int(i[1]), datatype="dest_asn", label=i[0]) + for i in sorted(self.s_port_count.items(), reverse=True, key=operator.itemgetter(1))[:t]: + if i[0]: + self.write(int(i[1]), datatype="source_port", label=i[0]) + for i in sorted(self.d_port_count.items(), reverse=True, key=operator.itemgetter(1))[:t]: + if i[0]: + self.write(int(i[1]), datatype="dest_port", label=i[0]) + + def connection_handler(self, conn): + "For each conn, increment the counts for the relevant dictionary keys" + self.proto[conn.protocol] += 1 + self.s_country_count[conn.sipcc] += 1 + self.s_asn_count[conn.sipasn] += 1 + self.s_port_count[conn.sport] += 1 + self.s_ip_count[conn.sip] += 1 + self.d_country_count[conn.dipcc] += 1 + self.d_asn_count[conn.dipasn] += 1 + self.d_port_count[conn.dport] += 1 + self.d_ip_count[conn.dip] += 1 + return conn + diff --git a/dshell/plugins/voip/__init__.py b/dshell/plugins/voip/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/decoders/voip/rtp.py b/dshell/plugins/voip/rtp.py similarity index 62% rename from decoders/voip/rtp.py rename to dshell/plugins/voip/rtp.py index a4f242e..7481af5 100644 --- a/decoders/voip/rtp.py +++ b/dshell/plugins/voip/rtp.py @@ -1,28 +1,25 @@ -# -# Author: MM - https://github.com/1modm -# -# RTP provides end-to-end network transport functions suitable for applications transmitting real-time data, -# such as audio, video or simulation data, over multicast or unicast network services. -# -# RFC: https://www.ietf.org/rfc/rfc3550.txt -# -# RTP Payload: -# https://tools.ietf.org/html/rfc2198 -# https://tools.ietf.org/html/rfc4855 -# https://www.iana.org/assignments/rtp-parameters/rtp-parameters.xhtml - -import dshell -import dpkt +""" +Real-time transport protocol (RTP) capture plugin +""" + import datetime -class DshellDecoder(dshell.UDPDecoder): +import dshell.core +from dshell.output.alertout import AlertOutput + +from pypacker.layer4 import udp +from pypacker.layer567 import rtp + +class DshellPlugin(dshell.core.PacketPlugin): def __init__(self): - dshell.UDPDecoder.__init__(self, - name='rtp', - description='Real-time transport protocol (RTP) capture decoder', - longdescription=""" -The real-time transport protocol (RTP) decoder will extract the Hosts, Payload Type, Synchronization source, + super().__init__( + name="RTP", + author="mm/dev195", + bpf="udp", + description="Real-time transport protocol (RTP) capture plugin", + longdescription=""" +The real-time transport protocol (RTP) plugin will extract the Hosts, Payload Type, Synchronization source, Sequence Number, Padding, Marker and Client MAC address from every RTP packet found in the given pcap. General usage: @@ -58,11 +55,10 @@ def __init__(self): Contributing source (32 bits): 0, Padding (1 bit): 0, Extension (1 bit): 0, Marker (1 bit): 0 ** """, - filter='udp', - author='mm' - ) + output=AlertOutput(label=__name__) + ) - def preModule(self): + def premodule(self): self.payload_type = {0: "PCMU - Audio - 8000 Hz - 1 Channel", 1: "Reserved", 2: "Reserved", 3: "GSM - Audio - 8000 Hz - 1 Channel", 4: "G723 - Audio - 8000 Hz - 1 Channel", 5: "DVI4 - Audio - 8000 Hz - 1 Channel", 6: "DVI4 - Audio - 16000 Hz - 1 Channel", 7: "LPC - Audio - 8000 Hz - 1 Channel", 8: "PCMA - Audio - 8000 Hz - 1 Channel", 9: "G722 - Audio - 8000 Hz - 1 Channel", @@ -82,22 +78,28 @@ def preModule(self): for i in range(96,128): self.payload_type[i] = "Dynamic" - def packetHandler(self, udp, data): - try: - if dpkt.rtp.RTP(data): - rtppkt = dpkt.rtp.RTP(data) - pt = self.payload_type.get(rtppkt.pt) - - self.alert('\n\tFrom: {0} ({1}) to {2} ({3}) \n\tPayload Type (7 bits): {4}\n\tSequence Number (16 bits): {5}\n\tTimestamp (32 bits): {6} \n\tSynchronization source (32 bits): {7}\n\tArrival Time: {8} --> {9}\n\tContributing source (32 bits): {10}, Padding (1 bit): {11}, Extension (1 bit): {12}, Marker (1 bit): {13}\n'.format( - udp.sip, udp.smac, udp.dip, udp.dmac, pt, rtppkt.seq, rtppkt.ts, rtppkt.ssrc, - udp.ts, datetime.datetime.utcfromtimestamp(udp.ts), - rtppkt.cc, rtppkt.p, rtppkt.x, rtppkt.m), **udp.info()) - - except dpkt.UnpackError, e: - pass - -if __name__ == '__main__': - dObj = DshellDecoder() - print dObj -else: - dObj = DshellDecoder() \ No newline at end of file + def packet_handler(self, pkt): + # Scrape out the UDP layer of the packet + udpp = pkt.pkt.upper_layer + while not isinstance(udpp, udp.UDP): + try: + udpp = udpp.upper_layer + except AttributeError: + # There doesn't appear to be an UDP layer + return + + # Parse the RTP protocol from above the UDP layer + rtpp = rtp.RTP(udpp.body_bytes) + + if rtpp.version != 2: + # RTP should always be version 2 + return + + pt = self.payload_type.get(rtpp.pt, "??") + + self.write("\n\tFrom: {0} ({1}) to {2} ({3}) \n\tPayload Type (7 bits): {4}\n\tSequence Number (16 bits): {5}\n\tTimestamp (32 bits): {6} \n\tSynchronization source (32 bits): {7}\n\tArrival Time: {8} --> {9}\n\tContributing source (32 bits): {10}, Padding (1 bit): {11}, Extension (1 bit): {12}, Marker (1 bit): {13}\n".format( + pkt.sip, pkt.smac, pkt.dip, pkt.dmac, pt, rtpp.seq, rtpp.ts, + rtpp.ssrc, pkt.ts, datetime.datetime.utcfromtimestamp(pkt.ts), + rtpp.cc, rtpp.p, rtpp.x, rtpp.m), **pkt.info()) + + return pkt diff --git a/dshell/plugins/voip/sip.py b/dshell/plugins/voip/sip.py new file mode 100644 index 0000000..52cf7b5 --- /dev/null +++ b/dshell/plugins/voip/sip.py @@ -0,0 +1,174 @@ +""" + Author: MM - https://github.com/1modm + + The Session Initiation Protocol (SIP) is the IETF protocol for VOIP and other + text and multimedia sessions and is a communications protocol for signaling + and controlling. + SIP is independent from the underlying transport protocol. It runs on the + Transmission Control Protocol (TCP), the User Datagram Protocol (UDP) or the + Stream Control Transmission Protocol (SCTP) + + Rate and codec calculation thanks to https://git.ucd.ie/volte-and-of/voip-pcapy + + RFC: https://www.ietf.org/rfc/rfc3261.txt + + SIP is a text-based protocol with syntax similar to that of HTTP. + There are two different types of SIP messages: requests and responses. + - Requests initiate a SIP transaction between two SIP entities for + establishing, controlling, and terminating sessions. + - Responses are send by the user agent server indicating the result of a + received request. + + - SIP session setup example: + + Alice's . . . . . . . . . . . . . . . . . . . . Bob's + softphone SIP Phone + | | | | + | INVITE F1 | | | + |--------------->| INVITE F2 | | + | 100 Trying F3 |--------------->| INVITE F4 | + |<---------------| 100 Trying F5 |--------------->| + | |<-------------- | 180 Ringing F6 | + | | 180 Ringing F7 |<---------------| + | 180 Ringing F8 |<---------------| 200 OK F9 | + |<---------------| 200 OK F10 |<---------------| + | 200 OK F11 |<---------------| | + |<---------------| | | + | ACK F12 | + |------------------------------------------------->| + | Media Session | + |<================================================>| + | BYE F13 | + |<-------------------------------------------------| + | 200 OK F14 | + |------------------------------------------------->| + | | + +""" + +import dshell.core +from dshell.output.colorout import ColorOutput + +from pypacker.layer4 import udp +from pypacker.layer567 import sip + +class DshellPlugin(dshell.core.PacketPlugin): + + def __init__(self): + super().__init__( + name="SIP", + author="mm/dev195", + output=ColorOutput(label=__name__), + bpf="udp", + description="(UNFINISHED) Session Initiation Protocol (SIP) capture plugin", + longdescription=""" +The Session Initiation Protocol (SIP) plugin will extract the Call ID, User agent, Codec, Method, +SIP call, Host, and Client MAC address from every SIP request or response packet found in the given pcap. + +General usage: + decode -d sip + +Detailed usage: + decode -d sip --sip_showpkt + +Layer2 sll usage: + decode -d sip --no-vlan --layer2=sll.SLL + +SIP over TCP: + decode -d sip --bpf 'tcp' + +SIP is a text-based protocol with syntax similar to that of HTTP, so you can use followstream plugin: + decode -d followstream --ebpf 'port 5060' --bpf 'udp' + +Examples: + + https://wiki.wireshark.org/SampleCaptures#SIP_and_RTP + http://vignette3.wikia.nocookie.net/networker/images/f/fb/Sample_SIP_call_with_RTP_in_G711.pcap/revision/latest?cb=20140723121754 + + decode -d sip metasploit-sip-invite-spoof.pcap + decode -d sip Sample_SIP_call_with_RTP_in_G711.pcap + +Output: + + <-- SIP Request --> + Timestamp: 2016-09-21 22:44:28.220185 UTC - Protocol: UDP - Size: 435 bytes + Sequence and Method: 1 ACK + From: 10.5.1.8:5060 (00:20:80:a1:13:db) to 10.5.1.7:5060 (15:2a:01:b4:0f:47) + Via: SIP/2.0/UDP 10.5.1.8:5060;branch=z9hG4bK940bdac4-8a13-1410-9e58-08002772a6e9;rport + SIP call: "M" ;tag=0ba2d5c4-8a13-1910-9d56-08002772a6e9 --> "miguel" ;tag=84538c9d-ba7e-e611-937f-68a3c4f0d6ce + Call ID: 0ba2d5c4-8a13-1910-9d57-08002772a6e9@M-PC + + --> SIP Response <-- + Timestamp: 2016-09-21 22:44:27.849761 UTC - Protocol: UDP - Size: 919 bytes + Sequence and Method: 1 INVITE + From: 10.5.1.7:5060 (02:0a:40:12:30:23) to 10.5.1.8:5060 (d5:02:03:94:31:1b) + Via: SIP/2.0/UDP 10.5.1.8:5060;branch=z9hG4bK26a8d5c4-8a13-1910-9d58-08002772a6e9;rport=5060;received=10.5.1.8 + SIP call: "M" ;tag=0ba2d5c4-8a13-1910-9d56-08002772a6e9 --> "miguel" ;tag=84538c9d-ba7e-e611-937f-68a3c4f0d6ce + Call ID: 0ba2d5c4-8a13-1910-9d57-08002772a6e9@M-PC + Codec selected: PCMU + Rate selected: 8000 + +Detailed Output: + + --> SIP Response <-- + Timestamp: 2016-09-21 22:44:25.360974 UTC - Protocol: UDP - Size: 349 bytes + From: 10.5.1.7:5060 (15:2a:01:b4:0f:47) to 10.5.1.8:5060 (00:20:80:a1:13:db) + SIP/2.0 100 Trying + content-length: 0 + via: SIP/2.0/UDP 10.5.1.8:5060;branch=z9hG4bK26a8d5c4-8a13-1910-9d58-08002772a6e9;rport=5060;received=10.5.1.8 + from: "M" ;tag=0ba2d5c4-8a13-1910-9d56-08002772a6e9 + to: + cseq: 1 INVITE + call-id: 0ba2d5c4-8a13-1910-9d57-08002772a6e9@M-PC + + --> SIP Response <-- + Timestamp: 2016-09-21 22:44:25.387780 UTC - Protocol: UDP - Size: 585 bytes + From: 10.5.1.7:5060 (15:2a:01:b4:0f:47) to 10.5.1.8:5060 (00:20:80:a1:13:db) + SIP/2.0 180 Ringing + content-length: 0 + via: SIP/2.0/UDP 10.5.1.8:5060;branch=z9hG4bK26a8d5c4-8a13-1910-9d58-08002772a6e9;rport=5060;received=10.5.1.8 + from: "M" ;tag=0ba2d5c4-8a13-1910-9d56-08002772a6e9 + require: 100rel + rseq: 694867676 + user-agent: Ekiga/4.0.1 + to: "miguel" ;tag=84538c9d-ba7e-e611-937f-68a3c4f0d6ce + contact: "miguel" + cseq: 1 INVITE + allow: INVITE,ACK,OPTIONS,BYE,CANCEL,SUBSCRIBE,NOTIFY,REFER,MESSAGE,INFO,PING,PRACK + call-id: 0ba2d5c4-8a13-1910-9d57-08002772a6e9@M-PC +""", + optiondict={ + "showpkt": { + "action": "store_true", + "default": False, + "help": "Display the full SIP response or request body" + } + } + ) + + self.rate = None + self.codec = None + self.direction = None + + def packet_handler(self, pkt): + self.rate = str() + self.codec = str() + self.direction = str() + + # Scrape out the UDP layer of the packet + udpp = pkt.pkt.upper_layer + while not isinstance(udpp, udp.UDP): + try: + udpp = udpp.upper_layer + except AttributeError: + # There doesn't appear to be an UDP layer + return + + # Check if exists SIP Request + if sip.SIP(udpp.body_bytes): + siptxt = "<-- SIP Request -->" + sippkt = sip.SIP(udpp.body_bytes) + self.direction = "sc" + self.output = True + + # TODO finish SIP plugin (pypacker needs to finish SIP, too) diff --git a/dshell/plugins/wifi/__init__.py b/dshell/plugins/wifi/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/dshell/plugins/wifi/wifi80211.py b/dshell/plugins/wifi/wifi80211.py new file mode 100644 index 0000000..5dc7db2 --- /dev/null +++ b/dshell/plugins/wifi/wifi80211.py @@ -0,0 +1,88 @@ +""" +Shows 802.11 information for individual packets. +""" + +import dshell.core +from dshell.output.output import Output + +from pypacker.layer12 import ieee80211 + +# Create a dictionary of string representations of frame types +TYPE_KEYS = { + ieee80211.MGMT_TYPE: "MGMT", + ieee80211.CTL_TYPE: "CTRL", + ieee80211.DATA_TYPE: "DATA" +} + +# Create a dictionary of subtype keys from constants defined in ieee80211 +# Its keys will be tuple pairs of (TYPE, SUBTYPE) +SUBTYPE_KEYS = dict() +# Management frame subtypes +SUBTYPE_KEYS.update(dict(((ieee80211.MGMT_TYPE, v), k[2:]) for k, v in ieee80211.__dict__.items() if type(v) == int and k.startswith("M_"))) +# Control frame subtypes +SUBTYPE_KEYS.update(dict(((ieee80211.CTL_TYPE, v), k[2:]) for k, v in ieee80211.__dict__.items() if type(v) == int and k.startswith("C_"))) +# Data frame subtypes +SUBTYPE_KEYS.update(dict(((ieee80211.DATA_TYPE, v), k[2:]) for k, v in ieee80211.__dict__.items() if type(v) == int and k.startswith("D_"))) + +class DshellPlugin(dshell.core.PacketPlugin): + + OUTPUT_FORMAT = "[%(plugin)s] %(dt)s [%(ftype)s] [%(encrypted)s] [%(fsubtype)s] %(bodybytes)r %(retry)s\n" + + def __init__(self, *args, **kwargs): + super().__init__( + name="802.11", + description="Show 802.11 packet information", + author="dev195", + bpf="wlan type mgt or wlan type ctl or wlan type data", + output=Output(label=__name__, format=self.OUTPUT_FORMAT), + optiondict={ + "ignore_mgt": {"action": "store_true", "help": "Ignore management frames"}, + "ignore_ctl": {"action": "store_true", "help": "Ignore control frames"}, + "ignore_data": {"action": "store_true", "help": "Ignore data frames"}, + "ignore_beacon": {"action": "store_true", "help": "Ignore beacons"}, + }, + longdescription=""" +Shows basic information for 802.11 packets, including: + - Frame type + - Encryption + - Frame subtype + - Data sample +""" + ) + + def handle_plugin_options(self): + "Update the BPF based on 'ignore' flags" + # NOTE: This function is naturally called in decode.py + bpf_pieces = [] + if not self.ignore_mgt: + if self.ignore_beacon: + bpf_pieces.append("(wlan type mgt and not wlan type mgt subtype beacon)") + else: + bpf_pieces.append("wlan type mgt") + if not self.ignore_ctl: + bpf_pieces.append("wlan type ctl") + if not self.ignore_data: + bpf_pieces.append("wlan type data") + self.bpf = " or ".join(bpf_pieces) + + def packet_handler(self, pkt): + try: + frame = pkt.pkt.ieee80211 + except AttributeError: + frame = pkt.pkt + encrypted = "encrypted" if frame.protected else " " + frame_type = TYPE_KEYS.get(frame.type, '----') + frame_subtype = SUBTYPE_KEYS.get((frame.type, frame.subtype), "") + retry = "[resent]" if frame.retry else "" + bodybytes = frame.body_bytes[:50] + + self.write( + encrypted=encrypted, + ftype=frame_type, + fsubtype=frame_subtype, + retry=retry, + bodybytes=bodybytes, + **pkt.info() + ) + + return pkt diff --git a/dshell/plugins/wifi/wifibeacon.py b/dshell/plugins/wifi/wifibeacon.py new file mode 100644 index 0000000..9ead90b --- /dev/null +++ b/dshell/plugins/wifi/wifibeacon.py @@ -0,0 +1,66 @@ +""" +Shows 802.11 wireless beacons and related information +""" + +from collections import defaultdict +from datetime import datetime + +import dshell.core +from dshell.output.output import Output + +class DshellPlugin(dshell.core.PacketPlugin): + + OUTPUT_FORMAT = "[%(plugin)s]\t%(dt)s\tInterval: %(interval)s TU,\tSSID: %(ssid)s\t%(count)s\n" + + def __init__(self, *args, **kwargs): + super().__init__( + name="Wi-fi Beacons", + description="Show SSIDs of 802.11 wireless beacons", + author="dev195", + bpf="wlan type mgt subtype beacon", + output=Output(label=__name__, format=self.OUTPUT_FORMAT), + optiondict={ + "group": {"action": "store_true", "help": "Group beacons together with counts"}, + } + ) + self.group_counts = defaultdict(int) + self.group_times = defaultdict(datetime.now) + + def packet_handler(self, pkt): + # Extract 802.11 frame from packet + try: + frame = pkt.pkt.ieee80211 + except AttributeError: + frame = pkt.pkt + + # Confirm that packet is, in fact, a beacon + if not frame.is_beacon(): + return + + # Extract SSID from frame + beacon = frame.beacon + ssid = "" + try: + for param in beacon.params: + # Find the SSID parameter + if param.id == 0: + ssid = param.body_bytes.decode("utf-8") + break + except IndexError: + # Sometimes pypacker fails to parse a packet + return + + if self.group: + self.group_counts[(ssid, beacon.interval)] += 1 + self.group_times[(ssid, beacon.interval)] = pkt.ts + else: + self.write(ssid=ssid, interval=beacon.interval, **pkt.info()) + + return pkt + + def postfile(self): + if self.group: + for key, val in self.group_counts.items(): + ssid, interval = key + dt = self.group_times[key] + self.write(ssid=ssid, interval=interval, plugin=self.name, dt=dt, count=val) diff --git a/dshell/util.py b/dshell/util.py new file mode 100644 index 0000000..37669bc --- /dev/null +++ b/dshell/util.py @@ -0,0 +1,151 @@ +""" +A collection of useful utilities used in several plugins and libraries. +""" + +import os +import string + +def xor(xinput, key): + """ + Xor an input string with a given character key. + + Arguments: + input: plain text input string + key: xor key + """ + output = ''.join([chr(ord(c) ^ key) for c in xinput]) + return output + + +def get_data_path(): + dpath = os.path.dirname(__file__) + return os.path.sep.join( (dpath, 'data') ) + +def get_plugin_path(): + dpath = os.path.dirname(__file__) + return os.path.sep.join( (dpath, 'plugins') ) + +def get_output_path(): + dpath = os.path.dirname(__file__) + return os.path.sep.join( (dpath, 'output') ) + +def decode_base64(intext, alphabet='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/', padchar='='): + """ + Decodes a base64-encoded string, optionally using a custom alphabet. + + Arguments: + intext: input plaintext string + alphabet: base64 alphabet to use + padchar: padding character + """ + # Build dictionary from alphabet + alphabet_index = {} + for i, c in enumerate(alphabet): + if c in alphabet_index: + raise ValueError("'{}' used more than once in alphabet".format(c)) + alphabet_index[c] = i + alphabet_index[padchar] = 0 + + alphabet += padchar + + outtext = '' + intext = intext.rstrip('\n') + + i = 0 + while i < len(intext) - 3: + if intext[i] not in alphabet or intext[i + 1] not in alphabet or intext[i + 2] not in alphabet or intext[i + 3] not in alphabet: + raise KeyError("Non-alphabet character in encoded text.") + val = alphabet_index[intext[i]] * 262144 + val += alphabet_index[intext[i + 1]] * 4096 + val += alphabet_index[intext[i + 2]] * 64 + val += alphabet_index[intext[i + 3]] + i += 4 + for factor in [65536, 256, 1]: + outtext += chr(int(val / factor)) + val = val % factor + + return outtext + + +def printable_text(intext, include_whitespace=True): + """ + Replaces non-printable characters with dots. + + Arguments: + intext: input plaintext string + include_whitespace (bool): set to False to mark whitespace characters + as unprintable + """ + printable = string.ascii_letters + string.digits + string.punctuation + if include_whitespace: + printable += string.whitespace + + if isinstance(intext, bytes): + intext = intext.decode("ascii", errors="replace") + + outtext = [c if c in printable else '.' for c in intext] + outtext = ''.join(outtext) + + return outtext + + +def hex_plus_ascii(data, width=16, offset=0): + """ + Converts a data string into a two-column hex and string layout, + similar to tcpdump with -X + + Arguments: + data: incoming data to format + width: width of the columns + offset: offset output from the left by this value + """ + output = "" + for i in range(0, len(data), width): + s = data[i:i + width] + if isinstance(s, bytes): + outhex = ' '.join(["{:02X}".format(x) for x in s]) + else: + outhex = ' '.join(["{:02X}".format(ord(x)) for x in s]) + outstr = printable_text(s, include_whitespace=False) + outstr = "{:08X} {:49} {}\n".format(i + offset, outhex, outstr) + output += outstr + return output + +def gen_local_filename(path, origname): + """ + Generates a local filename based on the original. Automatically adds a + number to the end, if file already exists. + + Arguments: + path: output path for file + origname: original name of the file to transform + """ + + tmp = origname.replace("\\", "_") + tmp = tmp.replace("/", "_") + tmp = tmp.replace(":", "_") + localname = '' + for c in tmp: + if ord(c) > 32 and ord(c) < 127: + localname += c + else: + localname += "%%%02X" % ord(c) + localname = os.path.join(path, localname) + postfix = '' + i = 0 + while os.path.exists(localname + postfix): + i += 1 + postfix = "_{:04d}".format(i) + return localname + postfix + +def human_readable_filesize(bytecount): + """ + Converts the raw byte counts into a human-readable format + https://stackoverflow.com/questions/1094841/reusable-library-to-get-human-readable-version-of-file-size/1094933#1094933 + """ + for unit in ('B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB'): + if abs(bytecount) < 1024.0: + return "{:3.2f} {}".format(bytecount, unit) + bytecount /= 1024.0 + return "{:3.2f} {}".format(bytecount, "YB") + diff --git a/install-ubuntu.py b/install-ubuntu.py deleted file mode 100755 index 75f1b4d..0000000 --- a/install-ubuntu.py +++ /dev/null @@ -1,28 +0,0 @@ -#!/usr/bin/env python - -from pkgutil import iter_modules -from subprocess import call - -dependencies = { - "Crypto": "crypto", - "dpkt": "dpkt", - "IPy": "ipy", - "pcap": "pypcap" -} - -installed, missing_pkgs = [pkg[1] for pkg in iter_modules()], [] - -for module, pkg in dependencies.items(): - if module not in installed: - print("dshell requires {}".format(module)) - missing_pkgs.append("python-{}".format(pkg)) - else: - print("{} is installed".format(module)) - -if missing_pkgs: - cmd = ["sudo", "apt-get", "install"] + missing_pkgs - - print(" ".join(cmd)) - call(cmd) - -call(["make", "all"]) diff --git a/lib/dfile.py b/lib/dfile.py deleted file mode 100644 index 2fc9145..0000000 --- a/lib/dfile.py +++ /dev/null @@ -1,178 +0,0 @@ -''' -Dshell external file class/utils -for use in rippers, dumpers, etc. - -@author: amm -''' -import os -from dshell import Blob -from shutil import move -from hashlib import md5 - -''' -Mode Constants -''' -FILEONDISK = 1 # Object refers to file already written to disk -FILEINMEMORY = 2 # Object contains file contents in data member - -''' -dfile -- Dshell file class. - -Extends blob for offset based file chunk (segment) reassembly. -Removes time and directionality from segments. - -Decoders can instantiate this class and pass it to -output modules or other decoders. - -Decoders can choose to pass a file in memory or already -written to disk. - -A dfile object can have one of the following modes: - FILEONDISK - FILEINMEMORY - -''' - - -class dfile(Blob): - - def __init__(self, mode=FILEINMEMORY, name=None, data=None, **kwargs): - - # Initialize Segments - # Only really used in memory mode - self.segments = {} - self.startoffset = 0 - self.endoffset = 0 - - # Initialize consistent info members - self.mode = mode - self.name = name - self.diskpath = None - self.info_keys = [ - 'mode', 'name', 'diskpath', 'startoffset', 'endoffset'] - - # update with additional info - self.info(**kwargs) - # update data - if data != None: - self.update(data) - - def __iter__(self): - ''' - Undefined - ''' - pass - - def __str__(self): - ''' - Returns filename (string) - ''' - return self.name - - def __repr__(self): - ''' - Returns filename (string) - ''' - return self.name - - def md5(self): - ''' - Returns md5 of file - Calculate based on reassembly from FILEINMEMORY - or loads from FILEONDISK - ''' - if self.mode == FILEINMEMORY: - return md5(self.data()).hexdigest() - elif self.mode == FILEONDISK: - m = md5() - fh = open(self.diskpath, 'r') - m.update(fh.read()) - fh.close() - return m.hexdigest() - else: - return None - - def load(self): - ''' - Load file from disk. Converts object to mode FILEINMEMORY - ''' - if not self.mode == FILEONDISK: - return False - try: - fh = open(self.diskpath, 'r') - self.update(fh.read()) - fh.close() - self.mode = FILEINMEMORY - except: - return False - - def write(self, path='.', name=None, clobber=False, errorHandler=None, padding=None, overlap=True): - ''' - Write file contents at location relative to path. - Name on disk will be based on internal name unless one is provided. - - For mode FILEINMEMORY, file will data() will be called for reconstruction. - After writing to disk, mode will be changed to FILEONDISK. - If mode is already FILEONDISK, file will be moved to new location. - - ''' - olddiskpath = self.diskpath - if name == None: - name = self.name - self.diskpath = self.__localfilename(name, path, clobber) - if self.mode == FILEINMEMORY: - fh = open(self.diskpath, 'w') - fh.write(self.data()) - fh.close() - self.segments = {} - self.startoffset = 0 - self.endoffset = 0 - return self.diskpath - elif self.mode == FILEONDISK: - move(olddiskpath, self.diskpath) - return self.diskpath - - def update(self, data, offset=None): - if self.mode != FILEINMEMORY: - return - # if offsets are not being provided, just keep packets in wire order - if offset == None: - offset = self.endoffset - # don't buffer duplicate packets - if offset not in self.segments: - self.segments[offset] = data - # update the end offset if this packet goes at the end - if offset >= self.endoffset: - self.endoffset = offset + len(data) - - # - # Generate a local (extracted) filename based on the original - # - def __localfilename(self, origname, path='.', clobber=False): - tmp = origname.replace("\\", "_") - tmp = tmp.replace("/", "_") - tmp = tmp.replace(":", "_") - tmp = tmp.replace("?", "_") - tmp = tmp.lstrip('_') - localname = '' - for c in tmp: - if ord(c) > 32 and ord(c) < 127: - localname += c - else: - localname += "%%%02X" % ord(c) - # Truncate (from left) to max filename length on filesystem (-3 in case - # we need to add a suffix) - localname = localname[os.statvfs(path).f_namemax * -1:] - # Empty filename not allowed - if localname == '': - localname = 'blank' - localname = os.path.realpath(os.path.join(path, localname)) - if clobber: - return localname - # No Clobber mode, check to see if file exists - suffix = '' - i = 0 - while os.path.exists(localname + suffix): - i += 1 - suffix = "_%02d" % i - return localname + suffix diff --git a/lib/dnsdecoder.py b/lib/dnsdecoder.py deleted file mode 100644 index 64a4c7c..0000000 --- a/lib/dnsdecoder.py +++ /dev/null @@ -1,101 +0,0 @@ -#!/usr/bin/env python - -import dshell -import util -import dpkt - - -class DNSDecoder(dshell.TCPDecoder): - - '''extend DNSDecoder to handle DNS request/responses - pairs request and response(s) by connection and query ID - to allow for detection of DNS spoofing, etc.. (multiple responses to request with same ID) - will call DNSHandler( - conn=Connection(), - request=dpkt.dns.DNS, - response=dpkt.dns.DNS, - requesttime=timestamp, responsetime=timestamp, - responsecount=responsecount - ) - after each response. - - config: noanswer: if True and discarding w/o response, will call with response,responsetime=None,None (True) - - ''' - - def __init__(self, **kwargs): - self.noanswer = True - dshell.TCPDecoder.__init__(self, **kwargs) # DNS is over UDP and TCP! - self.requests = {} - self.maxblobs = None - - def packetHandler(self,udp,data): - '''for each UDP packet , examine each segment (UDP packet) seperately as each will be a DNS Q/A - pair Q/A by ID and return as pairs''' - addr=udp.addr - if addr[0][1] < addr[1][1]: addr=addr[1],addr[0] #swap ports if source port is lower, to keep tuple (client,server) - connrqs = self.requests.setdefault(addr, {}) - try: - dns = dpkt.dns.DNS(data) - except Exception, e: - self._exc(e) - if dns.qr == dpkt.dns.DNS_Q: - connrqs[dns.id] = [udp.ts, dns, 0] - elif dns.qr == dpkt.dns.DNS_A: - rq = connrqs.get(dns.id, [None, None, 0]) - rq[2] += 1 - if "DNSHandler" in dir(self): - self.DNSHandler(conn=udp, request=rq[1], response=dns, requesttime=rq[0], - responsetime=udp.ts, responsecount=rq[2]) - - def blobHandler(self, conn, blob): - '''for each blob, examine each segment (UDP packet) seperately as each will be a DNS Q/A - pair Q/A by ID and return as pairs''' - connrqs = self.requests.setdefault(conn, {}) - # iterate blob as each packet will be a seperate request (catches spoofing) - for data in blob: - try: - dns = dpkt.dns.DNS(data) - except Exception, e: - self._exc(e) - continue - if dns.qr == dpkt.dns.DNS_Q: - connrqs[dns.id] = [blob.starttime, dns, 0] - elif dns.qr == dpkt.dns.DNS_A: - rq = connrqs.get(dns.id, [None, None, 0]) - rq[2] += 1 - if "DNSHandler" in dir(self): - self.DNSHandler(conn=conn, request=rq[1], response=dns, requesttime=rq[0], - responsetime=blob.starttime, responsecount=rq[2]) - - def connectionHandler(self,conn): - '''clean up unanswered requests when we discard the connection''' - if self.noanswer and "DNSHandler" in dir(self) and self.requests.get(conn): - for requesttime, request, responsecount in self.requests[conn].values(): - if not responsecount: - if type(conn) is tuple: conn=dshell.Packet(self,conn) #wrap UDP addresses - self.DNSHandler(conn=conn, request=request, response=None, - requesttime=requesttime, responsetime=None, responsecount=responsecount) - if conn in self.requests: - del self.requests[conn] - - def postModule(self): - '''flush out all remaining request state when module exits''' - for conn in self.requests.keys(): - self.connectionHandler(conn) - - -class displaystub(dshell.Decoder): - - def __init__(self): - dshell.Decoder.__init__(self, - name='dnsdecoder', - description='Intermediate class to support DNS based decoders.', - longdescription="See source code or pydoc for details on use." - ) - -if __name__ == '__main__': - dObj = displaystub() - print dObj -else: # do we always want to print something here? Maybe only in debug mode?: - dObj = displaystub() diff --git a/lib/dshell.py b/lib/dshell.py deleted file mode 100755 index a2e461e..0000000 --- a/lib/dshell.py +++ /dev/null @@ -1,1113 +0,0 @@ -""" -Dshell base classes -""" - -__version__ = "3.0" - -import dpkt -import struct -import socket -import traceback -import util -import os -import logging - -# For IP lookups -try: - import geoip2.database -except: - pass - - -class Decoder(object): - - """ - Base class that all decoders will inherit - - The Dshell class initializes the decoder to work in the framework - and provides common functions such as CC/ASN lookup - - Configuration attributes, settable by Dshell.__init__(attr=value,...) or in subclass __init__: - name: name of this decoder. - description: single-line description of this decoder - longdescription: multi-line description of this decoder - author: who to blame for this decoder - - filter: default BPF filter for capture. - - format: output format string for this decoder, overrides default for - Please read how text, DB, etc.. Output() classes parse a format string. - - optionsdict: optionParser compatible config, specific to decoder - dict of { 'optname':{'default':..., 'help':..., etc... - }, - 'optname':... } - 'optname' is set by --deodername_optname=... on command line - and under [decodername] section in config file - - - cleanupinterval - seconds with no activity before state is discarded (default 60) - - chainable - set True to indicate this decoder can be chained (can pass output to another decoder) - subDecoder - decoder to pass output to, if not None. - (create new Data objects and call subDecoder.XHandler from XHandler, etc..) - - - """ - - def __super__(self): - '''convenience function to get bound instance of superclass''' - return super(self.__class__, self) - - def __init__(self, **kwargs): - self.name = 'unnamed' - self.description = '' - self.longdescription = '' - self.filter = '' - self.author = 'xx' - self.decodedbytes = 0 - self.count = 0 - '''dict of options specific to this decoder in format - 'optname':{configdict} translates to --decodername_optname''' - self.optiondict = {} - - # out holds the output plugin. If None, will inherit the global output - self.out = None - # format is the format string for this plugin, if None, uses global - self.format = None - - # capture options - self.l2decoder = dpkt.ethernet.Ethernet # decoder to use if raw mode - # strip extra layers before IP/IPv6? (such as PPPoE, IP-over-IP, etc..) - self.striplayers = 0 - - self._DEBUG = False - - # can we chain a decoder off the output of this one? - self.chainable = False - self.subDecoder = None # decoder to pass output to for chaining - - # set flags to indicate if handlers are present - if 'packetHandler' in dir(self): - self.isPacketHandlerPresent = True - else: - self.isPacketHandlerPresent = False - if 'connectionHandler' in dir(self): - self.isConnectionHandlerPresent = True - else: - self.isConnectionHandlerPresent = False - if 'blobHandler' in dir(self): - self.isBlobHandlerPresent = True - else: - self.isBlobHandlerPresent = False - - # for connection tracking, if applicable - self.connectionsDict = {} - self.cleanupts = 0 - - # instantiate and save references to lookup function - geoip_dir = os.path.join(os.environ['DATAPATH'], "GeoIP") - try: - self.geoccdb = geoip2.database.Reader( - os.path.join(geoip_dir, "GeoLite2-Country.mmdb") - ).country - except: - self.geoccdb = None - - try: - self.geoasndb = geoip2.database.Reader( - os.path.join(geoip_dir, "GeoLite2-ASN.mmdb") - ).asn - except: - self.geoasndb = None - - # import kw args into class members - if kwargs: - self.__dict__.update(kwargs) - - ### convenience functions for alert output and logging ### - - def alert(self, *args, **kw): - '''sends alert to output handler - typically self.alert will be called with the decoded data and the packet/connection info dict last, as follows: - - self.alert(alert_arg,alert_arg2...,alert_data=value,alert_data2=value2....,**conn/pkt.info()) - - example: self.alert(decoded_data,conn.info(),blob.info()) [blob info overrides conn info] - - this will pass all information about the decoder, the connection, and the specific event up to the output module - - if a positional arg is a dict, it updates the kwargs - if an arg is a list, it extends the arg list - else it is appended to the arg list - - all arguments are optional, at the very least you want to pass the **pkt/conn.info() so all traffic info is available. - - output modules handle this data as follows: - - the name of the alerting decoder is available in the "decoder" field - - all non-keyword arguments will be concatenated into the "data" field - - keyword arguments, including all provided by .info() will be used to populate matching fields - - remaining keyword arguments that do not match fields will be represented by "key=value" strings - concatenated together into the "extra" field - ''' - oargs = [] - for a in args: - # merge dict args, overriding kws - if type(a) == dict: - kw.update(a) - elif type(a) == list: - oargs.extend(a) - else: - oargs.append(a) - if 'decoder' not in kw: - kw['decoder'] = self.name - self.out.alert(*oargs, **kw) # add decoder name - - def write(self, obj, **kw): - '''write session data''' - self.out.write(obj, **kw) - - def dump(self, *args, **kw): - '''write packet data (probably to the PCAP writer if present)''' - if len(args) == 3: - kw['len'], kw['pkt'], kw['ts'] = args - elif len(args) == 2: - kw['pkt'], kw['ts'] = args - elif len(args) == 1: - kw['pkt'] = args[0] - self.out.dump(**kw) - - def log(self, msg, level=logging.INFO): - '''logs msg at specified level (default of INFO is for -v/--verbose output)''' - self.out.log( - msg, level=level) # default level is INFO (verbose) can be overridden - - def debug(self, msg): - '''logs msg at debug level''' - self.log(msg, level=logging.DEBUG) - - def warn(self, msg): - '''logs msg at warning level''' - self.log(msg, level=logging.WARN) - pass - - def error(self, msg): - '''logs msg at error level''' - self.log(msg, level=logging.ERROR) - - def __repr__(self): - return '%s %s %s' % (self.name, self.filter, - ' '.join([('%s=%s' % (x, str(self.__dict__.get(x)))) for x in self.optiondict.keys()])) - - def preModule(self): - '''preModule is called before capture starts - default preModule, dumps object data to debug''' - if self.subDecoder: - self.subDecoder.preModule() - self.debug(self.name + ' ' + str(self.__dict__)) - - def postModule(self): - '''postModule is called after capture stops - default postModule, prints basic decoding stats''' - self.cleanConnectionStore() - self.log("%s: %d packets (%d bytes) decoded" % - (self.name, self.count, self.decodedbytes)) - if self.subDecoder: - self.subDecoder.postModule() - - def preFile(self): - if self.subDecoder: - self.subDecoder.preFile() - - def postFile(self): - if self.subDecoder: - self.subDecoder.postFile() - - def parseOptions(self, options={}): - '''option keys:values will set class members (self.key=value) - if key is in optiondict''' - for optname in self.optiondict.iterkeys(): - if optname in options: - self.__dict__[optname] = options[optname] - - def parseArgs(self, args, options={}): - '''called to parse command-line arguments and cli/config file options - if options dict contains 'all' or the decoder name as a key - class members will be updated from value''' - # get positional args after the -- - self.args = args - # update from all decoders section of config file - if 'all' in options: - self.parseOptions(options['all']) - # update from named section of config file - if self.name in options: - self.parseOptions(options[self.name]) - - def getGeoIP(self, ip, db=None, notfound='--'): - """ - Get country code associated with an IP. - Requires GeoIP library (geoip2) and data files. - """ - if not db: - db = self.geoccdb - try: - # Get country code based on order of importance - # 1st: Country that owns an IP address registered in another - # location (e.g. military bases in foreign countries) - # 2nd: Country in which the IP address is registered - # 3rd: Physical country where IP address is located - # https://dev.maxmind.com/geoip/geoip2/whats-new-in-geoip2/#Country_Registered_Country_and_Represented_Country - location = db(ip) - country = ( - location.represented_country.iso_code or - location.registered_country.iso_code or - location.country.iso_code or - notfound - ) - return country - except Exception: - # Many expected exceptions can occur here. Ignore them all and - # return default value. - return notfound - - def getASN(self, ip, db=None, notfound='--'): - """ - Get ASN associated with an IP. - Requires GeoIP library (geoip2) and data files. - """ - if not db: - db = self.geoasndb - try: - template = "AS{0.autonomous_system_number} {0.autonomous_system_organization}" - asn = template.format( db(ip) ) - return asn - except Exception: - # Many expected exceptions can occur here. Ignore them all and - # return default value. - return notfound - - def close(self, conn, ts=None): - '''for connection based decoders - close and discard the connection object''' - # just return if we have already been called on this connection - # prevents infinite loop of a handler calling close() when we call it - if conn.state == 'closed': - return - - # set state to closed - conn.state = 'closed' - if ts: - conn.endtime = ts - # we have already stopped this so don't call the handlers if we have - # already stopped - if not conn.stop: - # flush out the last blob to the blob handler - if self.isBlobHandlerPresent and conn.blobs: - self.blobHandler(conn, conn.blobs[-1]) - # process connection handler - if self.isConnectionHandlerPresent: - self.connectionHandler(conn) - # connection close handler - # will be called regardless of conn.stop right before conn object is - # destroyed - if 'connectionCloseHandler' in dir(self): - self.connectionCloseHandler(conn) - # discard but check first in case a handler deleted it - if conn.addr in self.connectionsDict: - del self.connectionsDict[conn.addr] - - def stop(self, conn): - '''stop following connection - handlers will not be called, except for connectionCloseHandler''' - conn.stop = True - - def cleanup(self, ts): - '''if cleanup interval expired, close connections not updated in last interval''' - ts = util.mktime(ts) - # if cleanup interval has passed - if self.cleanupts < (ts - self.cleanupinterval): - for conn in self.connectionsDict.values(): - if util.mktime(conn.endtime) <= self.cleanupts: - self.close(conn) - self.cleanupts = ts - - def cleanConnectionStore(self): - '''cleans connection store of all information, flushing out data''' - for conn in self.connectionsDict.values(): - self.close(conn) - - def _exc(self, e): - '''exception handler''' - self.warn(str(e)) - if self._DEBUG: - traceback.print_exc() - - def find(self, addr, state=None): - if addr in self.connectionsDict: - conn = self.connectionsDict[addr] - elif (addr[1], addr[0]) in self.connectionsDict: - conn = self.connectionsDict[(addr[1], addr[0])] - else: - return None - if not state or conn.state == state: - return conn - else: - return None - - def track(self, addr, data=None, ts=None, offset=None, **kwargs): - '''connection tracking for TCP and UDP - finds or creates connection based on addr - updates connection with data if provided (using offset to reorder) - tracks timestamps if ts provided - extra args get passed to new connection objects - ''' - conn = self.find(addr) - # look for forward and reverse address tuples - if not conn: # create new connection - # if swapping and source has low port, swap source/dest so dest has - # low port - if self.swaplowport and addr[0][1] < addr[1][1]: - addr = (addr[1], addr[0]) - # create connection and call init handler - conn = Connection(self, addr=addr, ts=ts, **kwargs) - if 'connectionInitHandler' in dir(self): - self.connectionInitHandler(conn) - # save in state dict - self.connectionsDict[addr] = conn - - # has tracking been stopped? - if conn.stop: - return False - - if data: - # forward or reverse direction? - if addr == conn.addr: - direction = 'cs' - else: - direction = 'sc' - - original_direction = conn.direction - - # update the connection to update current blob or start a new one - # and return the last one - # we will get a blob back if there is data to flush - blob = conn.update(ts, direction, data, offset=offset) - if blob and self.isBlobHandlerPresent: - self.blobHandler(conn, blob) - - # check direction and blob count. - # If we have switched direction but already have max blobs - # close connection and replace it with a new one - if self.maxblobs and (direction != original_direction) and (len(conn.blobs) >= self.maxblobs): - self.close(conn) # close and call handlers - # recurse to create a new connection for the next - # request/response - return self.track(addr, ts=ts, **kwargs) - - # we can discard all but the last blob - if not self.isConnectionHandlerPresent: - while len(conn.blobs) > 1: - conn.blobs.pop(0) - - self.cleanup(ts) # do stale state cleanup - return conn # return a reference to the connection - - '''directly extend Decoder and set raw=True to capture raw PCAP data''' - - # we get the raw output from pcapy as header, data - def decode(self, *args, **kw): - if len(args) is 3: - pktlen, pktdata, ts = args # orig_len,packet,ts format (pylibpcap) - else: # ts,pktdata (pypcap) - ts, pktdata = args - pktlen = len(pktdata) - try: - if pktlen != len(pktdata): - raise Exception('packet truncated', pktlen, pktdata) - # decode with the L2 decoder (probably Ether) - pkt = self.l2decoder(pktdata) - # attempt to collect MAC addresses - if type(pkt) == dpkt.ethernet.Ethernet: - try: - smac = "%02x:%02x:%02x:%02x:%02x:%02x" % (struct.unpack("BBBBBB", pkt.src)) - dmac = "%02x:%02x:%02x:%02x:%02x:%02x" % (struct.unpack("BBBBBB", pkt.dst)) - except struct.error: # couldn't get MAC address - smac, dmac = None, None - kw.update(smac=smac, dmac=dmac) - elif type(pkt) == dpkt.sll.SLL: - try: - # Sometimes MAC address will show up as 00:00:00:00:00:00 - # TODO decide if it should be set to None or kept as-is - smac = "%02x:%02x:%02x:%02x:%02x:%02x" % (struct.unpack("BBBBBB", pkt.hdr[:pkt.hlen])) - dmac = None - except struct.error: - smac, dmac = None, None - kw.update(smac=smac, dmac=dmac) - # strip any intermediate layers (PPPoE, etc) - for _ in xrange(int(self.striplayers)): - pkt = pkt.data - # will call self.rawHandler(len,pkt,ts) - # (hdr,data) is the PCAP header and raw packet data - if 'rawHandler' in dir(self): - self.rawHandler(pktlen, pkt, ts, **kw) - else: - pass - except Exception, e: - self._exc(e) - -# IP handler - - -class IPDecoder(Decoder): - - '''extend IP6Decoder to capture IPv4 and IPv6 data - (but does basic IPv4 defragmentation) - config: - - l2decoder: dpkt class for layer-2 decoding (Ethernet) - striplayers: strip n layers above layer-2, removes PPP/PPPoE encap, IP-over-IP, etc.. (0) - defrag: defragment IPv4 (True) - v6only: if True, will ignore IPv4 data. (False) - decode6to4: if True, will decode IPv6-over-IP, if False will treat as IP (True) - - filterfn: lambda function that accepts addr 2x2tuples and returns if packet should pass (addr:True) - - filterfn is required for IPv6 as port-based BPF filters don't work, - so keep your BPF to 'tcp' or 'udp' and set something like - self.filterfn = lambda ((sip,sp),(dip,dp)): (sp==53 or dp==53) ''' - - IP_PROTO_MAP = { - dpkt.ip.IP_PROTO_ICMP: 'ICMP', - dpkt.ip.IP_PROTO_ICMP6: 'ICMP6', - dpkt.ip.IP_PROTO_TCP: 'TCP', - dpkt.ip.IP_PROTO_UDP: 'UDP', - dpkt.ip.IP_PROTO_IP6: 'IP6', - dpkt.ip.IP_PROTO_IP: 'IP'} - - def __init__(self, **kwargs): - self.v6only = False - self.decode6to4 = True - self.defrag = True - self.striplayers = 0 - self.l2decoder = dpkt.ethernet.Ethernet - self.filterfn = lambda addr: True - Decoder.__init__(self, **kwargs) - self.frags = {} - - def ipdefrag(self, pkt): - '''ip fragment reassembly''' - # if pkt.off&dpkt.ip.IP_DF or pkt.off==0: return pkt #DF or !MF and - # offset 0 - # if we need to create a store for this IP addr/id - f = self.frags.setdefault((pkt.src, pkt.dst, pkt.id), {}) - f[pkt.off & dpkt.ip.IP_OFFMASK] = pkt - offset = 0 - data = '' - while True: - if offset not in f: - return None # we don't have this offset, can't reassemble yet - data += str(pkt.data) # add this to the data - if not pkt.off & dpkt.ip.IP_MF: - break # this is the next packet in order and no more fragments - offset = len(data) / 8 # calculate the next fragment's offset - # we hit no MF and last offset, so return a defragged packet - del self.frags[(pkt.src, pkt.dst, pkt.id)] # discard store - pkt.data = data # replace payload with defragged data - pkt.off = 0 # no frags, offset 0 - pkt.sum = 0 # recompute checksum - # dump and redecode packet to get checksum right - return dpkt.ip.IP(str(pkt)) - - def rawHandler(self, pktlen, pkt, ts, **kwargs): - '''takes ethernet data and determines if it contains IP or IP6. - defragments IPv4 - if 6to4, unencaps the IPv6 - If IP/IP6, hands off to IPDecoder via IPHandler()''' - try: - # if this is an IPv4 packet, defragment, decode and hand it off - if type(pkt.data) == dpkt.ip.IP: - if self.defrag: - # return packet if whole, None if more frags needed - pkt = self.ipdefrag(pkt.data) - else: - pkt = pkt.data # get the layer 3 packet - if pkt: # do we have a whole IP packet? - if self.decode6to4 and pkt.p == dpkt.ip.IP_PROTO_IP6: - pass # fall thru to ip6 decode - elif not self.v6only: # if we are decoding ip4 - sip, dip = socket.inet_ntoa( - pkt.src), socket.inet_ntoa(pkt.dst) - # try to decode ports - try: - sport, dport = pkt.data.sport, pkt.data.dport - except: # no ports in this layer-4 protocol - sport, dport = None, None - # generate int forms of src/dest ips - sipint, dipint = struct.unpack( - '!L', pkt.src)[0], struct.unpack('!L', pkt.dst)[0] - # call IPHandler with extra data - self.IPHandler(((sip, sport), (dip, dport)), pkt, ts, - pkttype=dpkt.ethernet.ETH_TYPE_IP, - proto=self.IP_PROTO_MAP.get( - pkt.p, pkt.p), - sipint=sipint, dipint=dipint, - **kwargs) - if pkt and type(pkt.data) == dpkt.ip6.IP6: - pkt = pkt.data # no defrag of ipv6 - # decode ipv6 addresses - sip, dip = socket.inet_ntop(socket.AF_INET6, pkt.src), socket.inet_ntop( - socket.AF_INET6, pkt.dst) - # try to get layer-4 ports - try: - sport, dport = pkt.data.sport, pkt.data.dport - except: - sport, dport = None, None - # generate int forms of src/dest ips - h, l = struct.unpack("!QQ", pkt.src) - sipint = ( (h << 64) | l ) - h, l = struct.unpack("!QQ", pkt.dst) - dipint = ( (h << 64) | l ) - # call ipv6 handler - self.IPHandler(((sip, sport), (dip, dport)), pkt, ts, - pkttype=dpkt.ethernet.ETH_TYPE_IP6, - proto=self.IP_PROTO_MAP.get(pkt.nxt, pkt.nxt), - sipint=sipint, dipint=dipint, - **kwargs) - except Exception, e: - self._exc(e) - - def IPHandler(self, addr, pkt, ts, **kwargs): - '''called if packet is IPv4/IPv6 - check packets using filterfn here''' - self.decodedbytes += len(str(pkt)) - self.count += 1 - if self.isPacketHandlerPresent and self.filterfn(addr): - return self.packetHandler(ip=Packet(self, addr, pkt=str(pkt), ts=ts, **kwargs)) - - -class IP6Decoder(IPDecoder): - pass - - -class UDPDecoder(IPDecoder): - - '''extend UDPDecoder to decode UDP optionally track state - config if tracking state with connectionHandler or blobHandler - maxblobs - if tracking state, max blobs to track before flushing - swaplowport - when establishing state, swap source/dest so dest has low port - cleanupinterval - seconds with no activity before state is discarded (default 60) ''' - - def __init__(self, **kwargs): - # by default limit UDP 'connections' to a single request and response - self.maxblobs = 2 - # can we swap source/dest so dest always has low port? - self.swaplowport = True - self.cleanupinterval = 60 - IPDecoder.__init__(self, **kwargs) - - def UDP(self, addr, data, pkt, ts=None, **kwargs): - ''' will call self.packetHandler(udp=Packet(),data=data) - (see Packet() for Packet object common attributes) - udp.pkt will contain the raw IP data - data will contain the decoded UDP payload - - State tracking: - only if connectionHandler or blobHandler is present - and packetHandler is not present - - UDPDecoder will call: - self.connectionInitHandler(conn=Connection()) - when UDP state is established - (see Connection() for Connection object attributes) - - self.blobHandler(conn=Connection(),blob=Blob()) - when stream direction switches (if following stream) - blob=(see Blob() objects) - - self.connectionHandler(conn=Connection()) - when UDP state is flushed (if following stream) - state is flushed when stale or when maxblobs is exceeded - if maxblobs exceeded, current data will go into new connection - - self.connectionCloseHandler(conn=Connection()) - when state is discarded (always) - ''' - self.decodedbytes += len(data) - self.count += 1 - try: - if self.isPacketHandlerPresent: - # create a Packet object and populate it - return self.packetHandler(udp=Packet(self, addr, pkt=pkt, ts=ts, **kwargs), data=data) - - # if no PacketHandler, we need to track state - conn = self.find(addr) - if not conn: - conn = self.track(addr, ts=ts, state='init', **kwargs) - if conn.nextoffset['cs'] is None: - conn.nextoffset['cs'] = 0 - if conn.nextoffset['sc'] is None: - conn.nextoffset['sc'] = 0 - self.track(addr, data, ts, **kwargs) - - except Exception, e: - self._exc(e) - - def IPHandler(self, addr, pkt, ts, **kwargs): - '''IPv4 dispatch, hands address, UDP payload and packet up to UDP callback''' - if self.filterfn(addr): - if type(pkt.data) == dpkt.udp.UDP: - return self.UDP(addr, str(pkt.data.data), str(pkt), ts, **kwargs) - - -class UDP6Decoder(UDPDecoder): - pass - - -class TCPDecoder(UDPDecoder): - - '''IPv6 TCP/UDP decoder - reassembles TCP and UDP streams - For TCP and UDP (if no packetHandler) - self.connectionInitHandler(conn=Connection()) - when TCP connection is established - (see Connection() for Connection object attributes) - - self.blobHandler(conn=Connection(),blob=Blob()) - when stream direction switches (if following stream) - blob=(see Blob() objects) - - self.connectionHandler(conn=Connection()) - when connection closes (if following stream) - - self.connectionCloseHandler(conn=Connection()) - when connection closes (always) - - For UDP only: - self.packetHandler(udp=Packet(),data=data) - with every packet - data=decoded UDP data - - if packetHandler is present, it will be called only for UDP (and UDP will not be tracked)''' - - def __init__(self, **kwargs): - self.maxblobs = None # no limit on connections - # can we swap source/dest so dest always has low port? - self.swaplowport = False - # if set true, will requre TCP handshake to track connection - self.ignore_handshake = False - self.cleanupinterval = 300 - # up two levels to IPDecoder - IPDecoder.__init__(self, **kwargs) - self.optiondict['ignore_handshake'] = { - 'action': 'store_true', 'help': 'ignore TCP handshake'} - - def IPHandler(self, addr, pkt, ts, **kwargs): - '''IPv4 dispatch''' - if self.filterfn(addr): - if type(pkt.data) == dpkt.udp.UDP: - return self.UDP(addr, str(pkt.data.data), str(pkt), ts, **kwargs) - elif type(pkt.data) == dpkt.tcp.TCP: - return self.TCP(addr, pkt.data, ts, **kwargs) - - def TCP(self, addr, tcp, ts, **kwargs): - '''TCP dispatch''' - self.decodedbytes += len(str(tcp)) - self.count += 1 - - try: - # attempt to find an existing connection for this address - conn = self.find(addr) - - if self.ignore_handshake: - # if we are ignoring handshakes, we will track all connections, - # even if we did not see the initialization handshake. - if not conn: - conn = self.track(addr, ts=ts, state='init', **kwargs) - # align the sequence numbers when we first see a connection - if conn.nextoffset['cs'] is None and addr == conn.addr: - conn.nextoffset['cs'] = tcp.seq + 1 - elif conn.nextoffset['sc'] is None and addr != conn.addr: - conn.nextoffset['sc'] = tcp.seq + 1 - self.track(addr, str(tcp.data), ts, - state='established', offset=tcp.seq, **kwargs) - - else: - # otherwise, only track connections if we see a TCP handshake - if (tcp.flags == dpkt.tcp.TH_SYN - or tcp.flags == dpkt.tcp.TH_SYN | dpkt.tcp.TH_CWR | dpkt.tcp.TH_ECE): - # SYN - if conn: - # if a connection already exists for the addr, - # close the old one to start fresh - self.close(conn, ts) - conn = self.track(addr, ts=ts, state='init', **kwargs) - if conn: - conn.nextoffset['cs'] = tcp.seq + 1 - elif (tcp.flags == dpkt.tcp.TH_SYN | dpkt.tcp.TH_ACK - or tcp.flags == dpkt.tcp.TH_SYN | dpkt.tcp.TH_ACK | dpkt.tcp.TH_ECE): - # SYN ACK - if conn and tcp.ack == conn.nextoffset['cs']: - conn.nextoffset['sc'] = tcp.seq + 1 - conn.state = 'established' - if conn and conn.state == 'established': - self.track(addr, str(tcp.data), ts, - state='established', offset=tcp.seq, **kwargs) - - # close connection - if conn and tcp.flags & (dpkt.tcp.TH_FIN | dpkt.tcp.TH_RST): - # flag that an IP is closing a connection with FIN or RST - conn.closeIP(addr[0]) - if conn and conn.connectionClosed(): - self.close(conn, ts) - - except Exception, e: - self._exc(e) - - -class TCP6Decoder(TCPDecoder): - pass - - -class Data(object): - - '''base class for data objects (packets,connections, etc..) - these objects hold data (appendable array, typically of strings) - and info members (updateable/accessible as members or as dict via info()) - typically one will extend the Data class and replace the data member - and associated functions (update,iter,str,repr) with a data() function - and functions to manipulate the data''' - - def __init__(self, *args, **kwargs): - self.info_keys = [] - # update with list data - self.data = list(args) - # update with keyword data - self.info(**kwargs) - - def info(self, *args, **kwargs): - '''update/return info stored in this object - data can be passwd as dict(s) or keyword args''' - args = list(args) + [kwargs] - for a in args: - for k, v in a.iteritems(): - if k not in self.info_keys: - self.info_keys.append(k) - self.__dict__[k] = v - return dict((k, self.__dict__[k]) for k in self.info_keys) - - def unpack(self, fmt, data, *args): - '''unpacks data using fmt to keys listed in args''' - self.info(dict(zip(args, struct.unpack(fmt, data)))) - - def pack(self, fmt, *args): - '''packs info keys in args using fmt''' - return struct.pack(fmt, *[self.__dict__[k] for k in args]) - - def update(self, *args, **kwargs): - '''updates data (and optionally keyword args)''' - self.data.extend(args) - self.info(kwargs) - - def __iter__(self): - '''returns each data element in order added''' - for data in self.data: - yield data - - def __str__(self): - '''return string built from data''' - return ''.join(self.data) - - def __repr__(self): - return ' '.join(['%s=%s' % (k, v) for k, v in self.info().iteritems()]) - - def __getitem__(self, k): return self.__dict__[k] - - def __setitem__(self, k, v): self.__dict__[k] = v - - -class Packet(Data): - - '''metadata class for connectionless data - Members: - sip, sport, dip, dport : source ip and port, dest ip and port - addr : ((sip,sport),(dip,dport)) tuple. sport/dport will be None if N/A - sipcc, dipcc, sipasn, dipasn : country codes and ASNs for source and dest IPs - ts : datetime.datetime() UTC timestamp of packet. use util.mktime(ts) to get POSIX timestamp - pkt : raw packet data - any additional args will be added to info dict - ''' - - def __init__(self, decoder, addr, ts=None, pkt=None, **kwargs): - self.info_keys = ['addr', 'sip', 'dip', 'sport', 'dport', 'ts'] - self.addr = addr - # do not define pkt unless passed in - self.ts = ts - ((self.sip, self.sport), (self.dip, self.dport)) = self.addr - if pkt: - self.pkt = pkt - self.info(bytes=len(self.pkt)) - - # pass instantiating decoder's cc/asn lookup objects to keep global - # cache - try: - self.info(sipcc=decoder.getGeoIP(self.sip, db=decoder.geoccdb), - sipasn=decoder.getASN(self.sip, db=decoder.geoasndb), - dipcc=decoder.getGeoIP(self.dip, db=decoder.geoccdb), - dipasn=decoder.getASN(self.dip, db=decoder.geoasndb)) - except: - self.sipcc, self.sipasn, self.dipcc, self.dipasn = None, None, None, None - - # update with additional info - self.info(**kwargs) - - def __iter__(self): - for p in self.pkt: - yield ord(p) - - def __str__(self): - return self.pkt - - def __repr__(self): - return "%(ts)s %(sip)16s :%(sport)-5s -> %(dip)5s :%(dport)-5s (%(sipcc)s -> %(dipcc)s)\n" % self.info() - - -class Connection(Packet): - - """ - Connection class is used for tracking all information - contained within an established TCP connection / UDP pseudoconnection - - Extends Packet() - - Additional members: - {client|server}ip, {client|server}port: aliases of sip,sport,dip,dport - {client|server}countrycode, {client|server}asn: aliases of sip/dip country codes and ASNs - clientpackets, serverpackets: counts of packets from client and server - clientbytes, serverbytes: total bytes from client and server - clientclosed, serverclosed: flag indicating if a direction has closed the connection - starttime,endtime: timestamps of start and end (or last packet) time of connection. - direction: indicates direction of last traffic: - 'init' : established, no traffic - 'cs': client to server - 'sc': server to client - state: TCP state of this connection - blobs: array of reassembled half stream blobs - a new blob is started when the direction changes - stop: if True, stopped following stream - - """ - - MAX_OFFSET = 0xffffffff # max offset before wrap, default is MAXINT32 for TCP sequence numbers - - def __init__(self, decoder, addr, ts=None, **kwargs): - self.state = None - # the offset we expect for the next blob in this direction - self.nextoffset = {'cs': None, 'sc': None} - # init IP-level data - Packet.__init__(self, decoder, addr, ts=ts, **kwargs) - self.clientip, self.clientport, self.serverip, self.serverport = ( - self.sip, self.sport, self.dip, self.dport) - self.info_keys.extend( - ['clientip', 'serverip', 'clientport', 'serverport']) - self.clientcountrycode, self.clientasn, self.servercountrycode, self.serverasn = ( - self.sipcc, self.sipasn, self.dipcc, self.dipasn) - self.info_keys.extend( - ['clientcountrycode', 'servercountrycode', 'clientasn', 'serverasn']) - self.clientpackets = 0 # we have the first packet for each connection - self.serverpackets = 0 - self.clientbytes = 0 - self.serverbytes = 0 - self.clientclosed = False - self.serverclosed = False - self.starttime = self.ts # datetime Obj containing start time - self.endtime = self.ts - # first update will change this, creating first blob - self.direction = 'init' - self.info_keys.extend(['clientpackets', 'clientbytes', 'serverpackets', - 'serverbytes', 'starttime', 'endtime', 'state', 'direction']) - - # list of tuples of (direction,halfstream,startoffset,endoffset) - # indicating where each side talks - self.blobs = [] - self.stop = False - - def __repr__(self): - # starttime cip sip - return '%s %16s -> %16s (%s -> %s) %6s %6s %5d %5d %7d %7d %6ds %s' % ( - self.starttime, - self.clientip, - self.serverip, - self.clientcountrycode, - self.servercountrycode, - self.clientport, - self.serverport, - self.clientpackets, - self.serverpackets, - self.clientbytes, - self.serverbytes, - (util.mktime(self.endtime) - util.mktime(self.starttime)), - self.state) - - def connectionClosed(self): - return self.serverclosed and self.clientclosed - - def closeIP(self, tuple): - ''' - Track if we have seen a FIN packet from given tuple - tuple should be of form (ip, port) - ''' - if tuple == (self.clientip, self.clientport): - self.clientclosed = True - if tuple == (self.serverip, self.serverport): - self.serverclosed = True - - def update(self, ts, direction, data, offset=None): - # if we have no blobs or direction changes, start a new blob - lastblob = None - if len(self.blobs) > 1 and self.blobs[-2].startoffset <= offset < self.blobs[-2].endoffset: - self.blobs[-2].update(ts,data,offset=offset) - else: - if direction != self.direction: - self.direction = direction - # if we have a finished blob, return it - if self.blobs: - lastblob = self.blobs[-1] - # for tracking offsets across blobs (TCP) set the startoffset of this blob to what we know it should be - # this may not necessarily be the offset of THIS data if packets - # are out of order - self.blobs.append( - Blob(ts, direction, startoffset=self.nextoffset[direction])) - self.blobs[-1].update(ts, data, offset=offset) # update latest blob - if direction == 'cs': - self.clientpackets += 1 - self.clientbytes += len(data) - elif direction == 'sc': - self.serverpackets += 1 - self.serverbytes += len(data) - self.endtime = ts - # if we are tracking offsets, expect the next blob to be where this one - # ends so far - if offset != None and ((offset + len(data)) & self.MAX_OFFSET) >= self.nextoffset[direction]: - self.nextoffset[direction] = (offset + len(data)) & self.MAX_OFFSET - return lastblob - - # return one or both sides of the stream - def data(self, direction=None, errorHandler=None, padding=None, overlap=True, caller=None): - '''returns reassembled half-stream selected by direction 'sc' or 'cs' - if no direction, return all stream data interleaved - see Blob.data() for errorHandler docs''' - return ''.join([b.data(errorHandler=errorHandler, padding=padding, overlap=overlap, caller=caller) for b in self.blobs if (not direction or b.direction == direction)]) - - def __str__(self): - '''return all data interleaved''' - return self.data(padding='') - - def __iter__(self): - '''return each blob in capture order''' - for blob in self.blobs: - yield blob - - -class Blob(Data): - - '''a blob containins a contiguous part of the half-stream - Members: - starttime,endtime : start and end timestamps of this blob - direction : direction of this blob's data 'sc' or 'cs' - data(): this blob's data - startoffset,endoffset: offset of this blob start/end in bytes from start of stream - ''' - - # max offset before wrap, default is MAXINT32 for TCP sequence numbers - MAX_OFFSET = 0xffffffff - - def __init__(self, ts, direction, startoffset): - self.starttime = ts - self.endtime = ts - self.direction = direction - self.segments = {} # offset:[segments with offset] - self.startoffset = startoffset - self.endoffset = startoffset - self.info_keys = [ - 'starttime', 'endtime', 'direction', 'startoffset', 'endoffset'] - - def update(self, ts, data, offset=None): - # if offsets are not being provided, just keep packets in wire order - if offset == None: - offset = self.endoffset - # buffer each segment in a list, keyed by offset (captures retrans, - # etc) - self.segments.setdefault(offset, []).append(data) - if ts > self.endtime: - self.endtime = ts - # update the end offset if this packet goes at the end - if (offset + len(data)) & self.MAX_OFFSET >= self.endoffset: - self.endoffset = (offset + len(data)) & self.MAX_OFFSET - - def __repr__(self): - return '%s %s (%s) +%s %d' % (self.starttime, self.endtime, self.direction, self.startoffset, len(self.segments)) - - def __str__(self): - '''returns segments of blob as string''' - return self.data(padding='') - - def data(self, errorHandler=None, padding=None, overlap=True, caller=None): - '''returns segments of blob reassembled into a string - if next segment offset is not the expected offset - errorHandler(blob,expected,offset) will be called - blob is a reference to the blob - if expectedoffset, data is overlapping - else a KeyError will be raised. - if the exception is passed and data is missing - if padding != None it will be used to fill the gap - if segment overlaps existing data - new data is kept if overlap=True - existing data is kept if overlap=False - caller: a ref to the calling object, passed to errorhandler - dup: how to handle duplicate segments: - 0: use first segment seen - -1 (default): use last segment seen - changing duplicate segment handling to always take largest segment - ''' - d = '' - nextoffset = self.startoffset - for segoffset in sorted(self.segments.iterkeys()): - if segoffset != nextoffset: - if errorHandler: # errorhandler can mangle blob data - if not errorHandler(blob=self, expected=nextoffset, offset=segoffset, caller=caller): - continue # errorhandler determines pass or fail here - elif segoffset > nextoffset: - # data missing and padding specified - if padding is not None: - if len(padding): - # add padding to data - d += str(padding) * (segoffset - nextoffset) - else: - # data missing, and no padding - raise KeyError(nextoffset) - elif segoffset < nextoffset and not overlap: - continue # skip if not allowing overlap - #find most data in segments - seg = '' - for x in self.segments[segoffset]: - if len(x) > len(seg): - seg = x - # advance next expected offset - nextoffset = ( - segoffset + len(seg)) & self.MAX_OFFSET - # append or splice data - d = d[:segoffset - self.startoffset] + \ - seg + \ - d[nextoffset - self.startoffset:] - return d - - def __iter__(self): - '''return each segment data in offset order - for TCP this will return segments ordered but not reassembled - (gaps and overlaps may exist) - for UDP this will return datagrams payloads in capture order, - (very useful for RTP or other streaming protocol.) - ''' - for segoffset in sorted(self.segments.iterkeys()): - yield self.segments[segoffset][-1] diff --git a/lib/httpdecoder.py b/lib/httpdecoder.py deleted file mode 100644 index a661a65..0000000 --- a/lib/httpdecoder.py +++ /dev/null @@ -1,101 +0,0 @@ -#!/usr/bin/env python -import dshell -import util -import dpkt - -# for HTTPDecoder gzip decompression -import gzip -import cStringIO - - -class HTTPDecoder(dshell.TCPDecoder): - - '''extend HTTPDecoder to handle HTTP request/responses - will call HTTPHandler( - conn=Connection(), - request=dpkt.http.Request, - response=dpkt.http.Response, - requesttime=timestamp, responsetime=timestamp - ) - after each response. - - config: noresponse: if True and connection closes w/o response, will call with response,responsetime=None,None (True) - gunzip: if True will decompress gzip encoded response bodies (default True) - - ''' - - def __init__(self, **kwargs): - self.noresponse = True - self.gunzip = True - dshell.TCPDecoder.__init__(self, **kwargs) - self.requests = {} - - # Custom error handler for data reassembly --- ignores errors, keep data - def errorH(self, **x): - return True - - def blobHandler(self, conn, blob): - '''buffer the request blob and call the handler once we have the response blob''' - if conn not in self.requests: - try: - self.requests[conn] = ( - blob.starttime, dpkt.http.Request(blob.data(self.errorH))) - except Exception, e: - self.UnpackError(e) - else: - try: - if 'HTTPHandler' in dir(self): - response = dpkt.http.Response(blob.data(self.errorH)) - if self.gunzip and 'gzip' in util.getHeader(response, 'content-encoding'): - bodyUnzip = self.decompressGzipContent(response.body) - if bodyUnzip != None: - response.body = bodyUnzip - self.HTTPHandler(conn=conn, - request=self.requests[conn][1], - response=response, - requesttime=self.requests[conn][0], - responsetime=blob.starttime) - del self.requests[conn] - except Exception, e: - self.UnpackError(e) - self.HTTPHandler(conn=conn, request=self.requests[conn][ - 1], response=None, requesttime=self.requests[conn][0], responsetime=blob.starttime) - del self.requests[conn] - - def connectionHandler(self, conn): - '''when the connection closes, flush out any request blobs that did not have a response''' - if conn in self.requests: - if self.noresponse and 'HTTPHandler' in dir(self): - self.HTTPHandler(conn=conn, - request=self.requests[conn][1], - response=None, - requesttime=self.requests[conn][0], - responsetime=self.requests[conn][0]) - del self.requests[conn] - - def decompressGzipContent(self, httpcontent): - '''utility function to decompress gzip compressed content''' - cstr = cStringIO.StringIO(httpcontent) - try: - return gzip.GzipFile(fileobj=cstr).read() - except: - return None - - def UnpackError(self, error): - self._exc(error) - - -class displaystub(dshell.Decoder): - - def __init__(self): - dshell.Decoder.__init__(self, - name='httpdecoder', - description='Intermediate class to support HTTP based decoders.', - longdescription="See source code or pydoc for details on use." - ) - -if __name__ == '__main__': - dObj = displaystub() - print dObj -else: - dObj = displaystub() diff --git a/lib/output/colorout.py b/lib/output/colorout.py deleted file mode 100644 index 34f7716..0000000 --- a/lib/output/colorout.py +++ /dev/null @@ -1,377 +0,0 @@ -''' -@author: amm -''' - -import output -import util -import dshell -import sys -import cgi -import string -import datetime - - -class ColorOutput(output.TextOutput): - - ''' - Color-coded Output module - use with --output=colorout - Output to STDOUT will use XTERM color tags, if possible. - Output to FILE will use HTML - - Decoders should call self.out.write() with string data and the following kwargs: - formatTag: H1 and H2 are currently implemented - direction: cs / sc - timestamp: specify unix timestamp for current object being written - time: (bool) to display timestamp - - Note Regarding Timestamps: - ------------------------- - Decoders should *always* specify timestamp information if available in their - calls to write. (If passing a full blob or connection, colorout will extract - this information from those objects.) In HTML output mode, the timestamps will - always be embedded in the HTML with a javascript option to show/hide them. - Initial display is govered by the boolean kwarg 'time' specified in calls - to write(). (Defaults to hidden unless a single 'true' value is passed.) - - Instantiation options - --------------------- - keyword title: specify HTML title - keyword force: specify force=true color output (e.g for piping to less -R) - keyword html: specify html=true for HTML output, even when writing to STDOUT - - HTML Generator Mode: - This mode makes the HTML generation/formatting available - as a utility to other code: - 1) Instantiate with keyword htmlgenerator=True: - colorout.ColorOutput(htmlgenerator=True, title="test") - 2) After one or more calls to write(), call close() - 3) Dump HTML with htmldump() - - ''' - # COLORMODEs: - # TEXT - Plain text. No color coding. (Default) - # TTY - TTY style color encoding. - # HTML - HTML/CSS output - _COLORMODE = 'TEXT' - - # Offsets for HEX Mode - _CS_offset = 0 - _SC_offset = 0 - _NODIR_offset = 0 - - # Custom error handler for data reassembly --- ignores all errors - def errorH(self, **x): - return True - - def __init__(self, *args, **kwargs): - - if 'format' in kwargs: - fmtstr = kwargs['format'] - del kwargs['format'] # don't let base class process this - else: - fmtstr = '' - - # Title - if 'title' not in dir(self): - if 'title' in kwargs: - self.title = kwargs['title'] - del kwargs['title'] # don't let base class process this - else: - self.title = 'Dshell' - - # Check for html generator mode - if 'htmlgenerator' not in dir(self): - if 'htmlgenerator' in kwargs: - self.htmlgenerator = kwargs['htmlgenerator'] - # don't let base class process this - del kwargs['htmlgenerator'] - else: - self.htmlgenerator = False - if self.htmlgenerator: - self.htmlbuffer = '' - - # Check for force color mode - if 'force' not in dir(self): - if 'force' in kwargs: - self.force = True - del kwargs['force'] # don't let base class process this - else: - self.force = False - - # Override HTML for stdout - if 'html' not in dir(self): - if 'html' in kwargs: - self.html = True - del kwargs['html'] - else: - self.html = False - - # Call parent init - output.TextOutput.__init__(self, format=fmtstr, **kwargs) - - - # In HTML mode, if we get any single call - # to write() with the time option set, we will set - # this master boolean value to True and display all timestamps - # on initial page load. Otherwise, timestamps will be hidden - # until toggled by the user - self._htmldisplaytimes = False - - def setup(self): - # Write Header - self.setColorMode() - - if self._COLORMODE == 'HTML': - self._htmlwrite(self._HTMLHeader(self.title)) - - - def setColorMode(self): - # Determine output mode - if self.fh == sys.stdout and not self.htmlgenerator and not self.html: - # STDOUT. Use Text Based Mode. - if sys.stdout.isatty() or self.force: - self._COLORMODE = 'TTY' - else: - self._COLORMODE = 'TEXT' - else: - # File. Use HTML. - self._COLORMODE = 'HTML' - - # Internal function to write HTML - # or buffer it in factory mode - def _htmlwrite(self, text): - if self.htmlgenerator: - self.htmlbuffer += text - else: - self.fh.write(text) - if self.nobuffer: - self.fh.flush() - - def htmldump(self): - ''' - For use in HTML Generator Mode: - In this mode, HTML generated by calls to write() is buffered. This - function returns the contents of and clears the buffer. - ''' - tmp = self.htmlbuffer - self.htmlbuffer = '' - return tmp - - def close(self): - # Footer - if self._COLORMODE == 'HTML': - self._htmlwrite(self._HTMLFooter()) - output.TextOutput.close(self) - - def _reset_offsets(self, value=0): - self._CS_offset = value - self._SC_offset = value - self._NODIR_offset = value - - def write(self, *args, **kw): - - # KW Options - if 'hex' in kw and kw['hex']: - self._hexmode = True - else: - self._hexmode = False - if 'time' in kw and kw['time']: - self._timemode = True - self._htmldisplaytimes = True - else: - self._timemode = False - - # KW formatTag - if 'formatTag' in kw: - formatTag = kw['formatTag'] - del kw['formatTag'] - else: - formatTag = '' - - # KW Direction - if 'direction' in kw: - kwdirection = kw['direction'] - else: - kwdirection = '' - - # KW Offset - if 'offset' in kw: - self._reset_offsets(kw['offset']) - - # KW Timestamp - if 'timestamp' in kw and kw['timestamp'] != None: - kwtimestamp = kw['timestamp'] - else: - kwtimestamp = None - - # KW Encoding (to specify character encoding) - if 'encoding' in kw and kw['encoding'] != None: - kwencoding = kw['encoding'] - else: - kwencoding = None - - # FormatTag (HTML) - if len(formatTag) and self._COLORMODE == 'HTML': - self._htmlwrite('<%s>' % formatTag) - - # Iterate *args - for a in args: - if type(a) == dshell.Blob: - self._write_blob(a, kwencoding) - elif type(a) == dshell.Connection: - self._reset_offsets() - for blob in a: - self._write_blob(blob, kwencoding) - else: - self._write_string(a, kwdirection, kwtimestamp, kwencoding) - - # Format Post Tag - if len(formatTag) and self._COLORMODE == 'HTML': - self._htmlwrite('' % formatTag) - - def _write_blob(self, blob, encoding=None): - self._write_string( - blob.data(errorHandler=self.errorH), blob.direction, blob.starttime, encoding) - - def _write_string(self, text, direction, timestamp, encoding=None): - - colorTag = '' - - # Print TimestampcolorTag - if self._COLORMODE == 'HTML' and timestamp != None: - self._htmlwrite('
      \n%s UTC:
      ' % - datetime.datetime.utcfromtimestamp(timestamp)) - #if self._hexmode: self._htmlwrite("
      ") - elif self._COLORMODE == 'TTY' and self._timemode and timestamp != None: - self.fh.write('\x1b[36m%s UTC:\x1b[0m\n' % - datetime.datetime.utcfromtimestamp(timestamp)) - if self.nobuffer: - self.fh.flush() - - # Set Direction - if direction.lower() == 'cs': - if self._COLORMODE == 'HTML': - self._htmlwrite('') - elif self._COLORMODE == 'TTY': - colorTag = '\x1b[0;31m' - elif direction.lower() == 'sc': - if self._COLORMODE == 'HTML': - self._htmlwrite('') - elif self._COLORMODE == 'TTY': - colorTag = '\x1b[0;32m' - - # Hex Mode Data - if self._hexmode: - # Hex Output - dlen = len(text) - if direction.lower() == 'cs': - msgOffset = self._CS_offset - self._CS_offset += dlen - elif direction.lower() == 'sc': - msgOffset = self._SC_offset - self._SC_offset += dlen - else: - msgOffset = self._NODIR_offset - self._NODIR_offset += dlen - text = util.hexPlusAscii(str(text), 16, msgOffset) - if self._COLORMODE == 'HTML': - text = cgi.escape(text) - self._htmlwrite(text) - elif self._COLORMODE == 'TTY': - self._write_tty(text, colorTag) - else: - self.fh.write(text) - if self.nobuffer: - self.fh.flush() - - # Plain Text - else: - if type(text) == unicode: - text = util.printableUnicode(text).encode('utf-8') - elif encoding: - try: - utext = unicode(text, encoding) - text = util.printableUnicode(utext).encode('utf-8') - except: - text = util.printableText(str(text)) - else: - text = util.printableText(str(text)) - if self._COLORMODE == 'HTML': - text = cgi.escape(text) - self._htmlwrite(text) - elif self._COLORMODE == 'TTY': - self._write_tty(text, colorTag) - else: - self.fh.write(text) - - # Close direction - if self._COLORMODE == 'HTML' and direction != '': - self._htmlwrite("") - - def _write_tty(self, text, colorTag): - - # Write color escape sequences on every line (less -R requires this) - for line in text.splitlines(True): - _line = line.split('\n') - self.fh.write(colorTag + _line[0] + '\x1b[0m') - if len(_line) > 1: - self.fh.write('\n') - if self.nobuffer: - self.fh.flush() - - def _HTMLHeader(self, title="Dshell"): - - return """ - - - -""" + title + """ - - - -
      -""" - - def _HTMLFooter(self): - if self._htmldisplaytimes: - display_timestamps = "\n" - else: - display_timestamps = '' - return display_timestamps + """ - -""" - -obj = ColorOutput diff --git a/lib/output/csvout.py b/lib/output/csvout.py deleted file mode 100644 index ebbdbc2..0000000 --- a/lib/output/csvout.py +++ /dev/null @@ -1,76 +0,0 @@ -''' -@author: tparker -''' - -import output -import util - - -class CSVOutput(output.TextOutput): - - ''' - CSV Output module - use with --output=csvout,[,data,customfield[:type],...] (a list of field:types to append to end of default format) - add [,file=...[,mode=...]] to write to outfile (or use -w arg on cmdline) - add format=... to replace the default fields or use a format string - add delim= to change delimeter from comma - ''' - - _NULL = '' - - _DEFAULT_DELIM = ',' - - _DEFAULT_FIELDS = [('decoder', 's'), ('datetime', 's'), - ('sip', 's'), ('sport', 's'), ('dip', 's'), ('dport', 's')] - - def __init__(self, *args, **kwargs): - ''' - sets up an output module, be sure to call Output.__init__ first or last - args will have the name of the module as args[0], anything else after - ''' - # start with a set of default fields - self.fields = self._DEFAULT_FIELDS - - if 'format' in kwargs: - self.fields = [] - fmtstr = kwargs['format'] - del kwargs['format'] # don't let base class process this - else: - fmtstr = '' - - # set delimiter - if 'delim' in kwargs: - self.delim = kwargs['delim'] - if self.delim.lower() == 'tab': - self.delim = "\t" - else: - self.delim = self._DEFAULT_DELIM - - self.noheader = 'noheader' in kwargs - - # parse args as fields - if len(args): - for a in args: - try: - f, t = a.split(':') # split on field:type - except: - f, t = a, 's' # default to string type - self.fields.append((f, t)) - - # build format string to pass to textoutput - if fmtstr: - fmtstr += self.delim - fmtstr += self.delim.join(['%%(%s)%s' % (f, t) for f, t in self.fields]) - - # everything else is exactly like the text output module - output.TextOutput.__init__(self, format=fmtstr, **kwargs) - - - def setup(self): - # print header if not suppressed - if self.fh and not self.noheader: - self.fh.write('#' + self.delim.join([f[0] for f in self.fields]) + "\n") - -'''NOTE: output modules return obj=reference to the CLASS - instead of a dObj=instance so we can init with args''' -obj = CSVOutput diff --git a/lib/output/elasticout.py b/lib/output/elasticout.py deleted file mode 100644 index 1e36c0e..0000000 --- a/lib/output/elasticout.py +++ /dev/null @@ -1,219 +0,0 @@ -''' -Created on May 6, 2015 - -@author: amm -''' - -import sys -import output -import dshell -import dfile -import logging -import datetime -import elasticsearch - - -class elasticout(output.TextOutput): - ''' - ElasticSearch Output module - use with --output=elasticout - - e.g. decode -d web *pcap --output elasticout,host=192.168.10.10,index=dshell - - options - ------- - host: : of an Elasticsearch search node (REQUIRED) - index: Elasticsearch index (REQUIRED) - doc_type: Elasticsearch document type for indexed documents - geoip: If set to Y, output module won't discard geoip tags - notrim: If set to Y, do not trim any fields from the output - message: If set to Y, add the decoder output message (args[0]) - as a "message" field in elasticsearch - ''' - - ELASTIC_HOST_LIST = [] - ELASTIC_INDEX = None - _DOC_TYPE = None - - # Fields to format as timestamp string - _TIMESTAMP_FIELDS = ( - 'ts', 'starttime', 'endtime', 'request_time', 'response_time') - # Fields to delete (redundant or unnecessary) - _DELETE_FIELDS = ('addr', 'direction', 'clientport', 'serverport', - 'clientip', 'serverip', 'sipint', 'dipint', 'pkttype') - # Dshell geolocation fields - _GEO_FIELDS = ('servercountrycode', 'clientcountrycode', - 'sipcc', 'dipcc', 'clientasn', 'serverasn', 'dipasn', 'sipasn') - - def __init__(self, *args, **kwargs): - - # - # Specified host - prepend to any list hard coded into the module - # - if 'host' in kwargs: - self.ELASTIC_HOST_LIST.insert(0, kwargs['host']) - - # - # Instantiate Elasticsearch client - # - if len(self.ELASTIC_HOST_LIST): - self.es = elasticsearch.Elasticsearch(self.ELASTIC_HOST_LIST) - else: - self.es = elasticsearch.Elasticsearch() - - # - # Index - # - if 'index' in kwargs: - self.ELASTIC_INDEX = kwargs['index'] - - # - # Document Type - # - if 'doc_type' in kwargs: - self._DOC_TYPE = kwargs['doc_type'] - - # - # Handle boolean options - # - self.options = {} - for o in ('geoip', 'notrim', 'message'): - self.options[o] = False - if o in kwargs: - if kwargs[o].upper() in ('Y', 'T', '1', 'YES', 'ON', 'TRUE'): - self.options[o] = True - del kwargs[o] - - # - # Check for existence of preInsert function - # this function allows child classes to have one last access - # to the data -- as will be inserted to Elasticsearch -- before - # the actual insert - # - # Function should return boolean value - # True to proceed with insert - # False to skip - # - # - if 'preInsert' in dir(self): - self.hasPreInsert = True - else: - self.hasPreInsert = False - - # Call parent init - output.TextOutput.__init__(self, **kwargs) - - def alert(self, *args, **kw): - - # - # DocType - # - if self._DOC_TYPE: - doc_type = self._DOC_TYPE - elif 'decoder' in kw: - doc_type = kw['decoder'] - del kw['decoder'] - else: - doc_type = 'dshell' - - # - # Remove Common Redundant Fields - # - if not self.options['notrim']: - for name in self._DELETE_FIELDS: - if name in kw: - del kw[name] - - # - # Time Fields - # - # Rename 'ts' to 'starttime' if 'starttime' not present - if 'ts' in kw: - if 'starttime' not in kw: - kw['starttime'] = kw['ts'] - del kw['ts'] - - # - # Remove GEOIP Fields - # - if not self.options['geoip']: - for name in self._GEO_FIELDS: - if name in kw: - del kw[name] - - # - # Perform multiple tasks, iterating across the kw dict - # - for k in kw.keys(): - # - # Convert known timestamp fields to datetime format - # Remove empty fields - # - if k.lower() in self._TIMESTAMP_FIELDS: - if type(kw[k]) == datetime: - continue - elif type(kw[k]) == str: - if len(kw[k]) == 0: - del kw[k] - continue - else: - # dshell has a different default date/time string format than elastic, - # so let's try to parse that into a datetime object - try: - kw[k] = datetime.datetime.strptime( - kw[k], '%Y-%m-%d %H:%M:%S') - except: - pass # if fail, pass it through and let elastic try to parse it - else: - # if not a string, try to - try: - kw[k] = datetime.datetime.fromtimestamp(float(kw[k])) - except: - pass - # - # Get Rid of Dfiles. Must be handled elsewhere. - # - if isinstance(kw[k], dfile.dfile): - del kw[k] - - # - # Message - # - if self.options['message']: - if 'message' not in kw: - kw['message'] = args[0].rstrip() - - # - # Allow child classes to access the data one last time before the insert - # - if self.hasPreInsert: - if not self.preInsert(kw): - return (False, None) - - # - # Insert into elastic - # - if '_id' in kw: - docid = kw['_id'] - del kw['_id'] - es_response = self.es.index( - index=self.ELASTIC_INDEX, id=docid, doc_type=doc_type, body=kw) - else: - es_response = self.es.index( - index=self.ELASTIC_INDEX, doc_type=doc_type, body=kw) - if es_response['created']: - return (True, es_response) - else: - if es_response['_version'] > 1: - self.log("Possible key collision: %s" % - (str(es_response)), logging.WARN) - # sys.stderr.write(repr(kw)) - else: - self.log("Elasticsearch error: %s" % - (str(es_response)), logging.WARN) - return (False, es_response) - - def write(self, *args, **kwargs): - print "WRITE CALLED (Not implemented in output decoder)" - -obj = elasticout diff --git a/lib/output/jsonout.py b/lib/output/jsonout.py deleted file mode 100644 index 3af2078..0000000 --- a/lib/output/jsonout.py +++ /dev/null @@ -1,135 +0,0 @@ -''' -@author: amm -''' - -import dshell -import dfile -import output -import datetime -import json -import base64 - - -class JSONOutput(output.TextOutput): - - ''' - JSON Output module - use with --output=jsonout - - usage: as with csvout, you can pass a list of field names that will be included in the JSON output - - options - ------- - geoip: If set to Y, output module won't discard geoip tags - notrim: If set to Y, do not trim any fields from the output - ensure_ascii: Enable this option in json library - - ''' - - _TIMESTAMP_FIELDS = ( - 'ts', 'starttime', 'endtime', 'request_time', 'response_time') - - def __init__(self, *args, **kwargs): - - # Options - self.options = {} - for o in ('geoip', 'notrim', 'ensure_ascii'): - self.options[o] = False - if o in kwargs: - if kwargs[o] == True or kwargs[o].upper() in ('Y', 'T', '1', 'YES', 'ON', 'TRUE'): - self.options[o] = True - del kwargs[o] - - # Args as fields - self.jsonfields = None - if len(args): - self.jsonfields = [] - for a in args: - self.jsonfields.append(a) - - # Call parent init - output.TextOutput.__init__(self, **kwargs) - - def alert(self, *args, **kw): - self.fh.write( - json.dumps(self._filter_data(kw), ensure_ascii=self.options['ensure_ascii']) + "\n") - if self.nobuffer: - self.fh.flush() - - - # Reusable function to filter data in alerts and writes - def _filter_data(self, kw): - - # User specified field list?? - if self.jsonfields != None: - for f in kw.keys(): - if f not in self.jsonfields: - del kw[f] - elif not self.options['notrim']: - # Remove Common Redundant Fields - for name in ('addr', 'direction', 'clientport', 'serverport', 'clientip', 'serverip', 'sipint', 'dipint'): - if name in kw: - del kw[name] - # Time Fields - # Rename 'ts' to 'starttime' if 'starttime' not present - if 'ts' in kw: - if 'starttime' not in kw: - kw['starttime'] = kw['ts'] - del kw['ts'] - # Convert known timestamp fields to string format - for name in self._TIMESTAMP_FIELDS: - try: - kw[name] = datetime.datetime.fromtimestamp( - float(kw[name])).strftime(self.timeformat) - except: - pass - # Remove GEOIP Fields - if not self.options['geoip']: - for name in ('servercountrycode', 'clientcountrycode', 'sipcc', 'dipcc', 'clientasn', 'serverasn', 'dipasn', 'sipasn'): - if name in kw: - del kw[name] - - outdata = {} - for n,v in kw.iteritems(): - if not isinstance(v, dfile.dfile): - outdata[n] = v - - return outdata - - - def write(self,*args,**kw): - - # Iterate *args - for a in args: - if type(a) == dshell.Blob: - self.fh.write(json.dumps(self._blob_to_dict(blob), ensure_ascii=self.options['ensure_ascii']) + "\n") - elif type(a) == dshell.Connection: - outdata = self._filter_data(a.info()) - outdata['type'] = 'conn' - outdata['data'] = [] - for blob in a: - #self._write_blob(blob, kw) - outdata['data'].append(self._blob_to_dict(blob)) - self.fh.write(json.dumps(outdata, ensure_ascii=self.options['ensure_ascii']) + "\n") - else: - d = self._filter_data(kw) - d['type'] = 'raw' - if type(a) == unicode: - d['data'] = base64.b64encode(a.encode('utf-8')) - else: - d['data'] = base64.b64encode(a) - self.fh.write(json.dumps(d, ensure_ascii=self.options['ensure_ascii']) + "\n") - - # Custom error handler for data reassembly --- ignores all errors - def errorH(self, **x): - return True - - def _blob_to_dict(self, blob): - d = self._filter_data(blob.info()) - d['type'] = 'blob' - d['data'] = base64.b64encode(blob.data(errorHandler=self.errorH)) - return d - - - -obj = JSONOutput diff --git a/lib/output/netflowout.py b/lib/output/netflowout.py deleted file mode 100644 index 0c943c4..0000000 --- a/lib/output/netflowout.py +++ /dev/null @@ -1,86 +0,0 @@ -''' -@author: amm -''' - -import output -import util -import sys -import datetime - - -class NetflowOutput(output.TextOutput): - - ''' - Netflow Output module - use with --output=netflowoutput -` use group=clientip,serverip for grouping by clientip,serverip - ''' - #_DEFAULT_FIELDS=[('decoder','s'),('datetime','s'),('sip','s'),('sport','s'),('dip','s'),('dport','s')] - #_DEFAULT_FORMAT="%(starttime)s %(sip)16s:%(sport)-5s -> %(dip)16s:%(dport)-5s" - - def __init__(self, *args, **kwargs): - self.group = kwargs.get('group') - self.groups = {} - if self.group: - self.group = self.group.split('/') - # Call parent init - output.TextOutput.__init__(self, **kwargs) - - def alert(self, *args, **kw): - if self.group: - k = tuple(kw[g] for g in self.group) # group by selected fields - if k not in self.groups: - r = k[::-1] - if r in self.groups: - k = r # is other dir in groups - else: - self.groups[k] = [] - self.groups[k].append(kw) - else: - self.__alert(**kw) # not grouping, just print it - - def close(self): - # dump groups if we are closing output - if self.group: - for k in sorted(self.groups.iterkeys()): - # write header - self.fh.write(' '.join( - '%s=%s' % (self.group[i], k[i]) for i in xrange(len(self.group))) + '\n') - for kw in self.groups[k]: - self.fh.write('\t') - self.__alert(self, **kw) - self.fh.write('\n') - output.TextOutput.close(self) - - def __alert(self, *args, **kw): - self.fh.write('%s %16s -> %16s (%s -> %s) %4s %6s %6s %5d %5d %7d %7d %-.4fs\n' % (datetime.datetime.utcfromtimestamp(kw['starttime']), - kw[ - 'clientip'], - kw[ - 'serverip'], - kw[ - 'clientcountrycode'], - kw[ - 'servercountrycode'], - kw[ - 'proto'], - kw[ - 'clientport'], - kw[ - 'serverport'], - kw[ - 'clientpackets'], - kw[ - 'serverpackets'], - kw[ - 'clientbytes'], - kw[ - 'serverbytes'], - ( - kw['endtime'] - kw['starttime']) - ) - ) - if self.nobuffer: - self.fh.flush() - -obj = NetflowOutput diff --git a/lib/output/output.py b/lib/output/output.py deleted file mode 100644 index 41a2122..0000000 --- a/lib/output/output.py +++ /dev/null @@ -1,562 +0,0 @@ -''' -dShell output classes - -@author: tparker -''' -import os -import sys -import logging -import struct -import datetime -import dshell -import util - - -class Output(object): - - ''' - dShell output base class, extended by output types - ''' - - _DEFAULT_FORMAT = '' - _DEFAULT_TIMEFORMAT = '%Y-%m-%d %H:%M:%S' - _DEFAULT_DELIM = ' ' - _NULL = None - - # true if you want to remove extra fields from the parsed record - _FILTER_EXTRA = False - - def __init__(self, *a, **kw): - ''' - base output class constructor - configuration kwords: - logger= to pass in a logger - format='format string' to override default formatstring for output class - pcap = filename to write pcap - ''' - # setup the logger - self.logger = kw.get('logger', logging) - - # parse the format string - self.setformat(kw.get('format', self._DEFAULT_FORMAT)) - self.timeformat = (kw.get('timeformat', self._DEFAULT_TIMEFORMAT)) - self.delim = (kw.get('delim', self._DEFAULT_DELIM)) - - # Run flush() after every relevant write() if this is true - self.nobuffer = (kw.get('nobuffer', False)) - - if 'pcap' in kw: - self.pcapwriter = PCAPWriter(kw['pcap']) - else: - self.pcapwriter = None - - # this is up to the output plugin to process - # by default stuffs extra fields and data into 'extra' field - # if _FILTER_EXTRA is true - self.extra = kw.get('extra', False) - - # create the default session writer - if 'session' in kw: - self.sessionwriter = SessionWriter(**kw) - else: - self.sessionwriter = None - - # write a message to the log - def log(self, msg, level=logging.INFO, *args, **kw): - '''write a message to the log - passes all args and kwargs thru to logging - except for level= is used to set logging level''' - self.logger.log(level, msg, *args, **kw) - - def setformat(self, formatstr=None, typemap=None): - '''parse a format string and extract the field info - if no string given, reverts to default for class - will set self.fields to be a list of (name,type,spec) tuples - self.fieldnames to a list of fieldnames - and self.fieldmap to a list of key=in value=out mappings - format string can also map in field to out field with %(in:out)spectype - or specify an explicit out type with %(in:out)specintype:outtype - (note this breaks compatibility with text formatting, - but useful for db or other output modules) - a typemap of [intype]=outtype (or [in]=(newintype,outtype) - can be used to map and replace types - ''' - if formatstr: - self.format = formatstr + "\n" - else: - self.format = self._DEFAULT_FORMAT + "\n" - self.fields = [] # will be a (name,type,length) tuple - self.fieldnames = [] - self.fieldmap = {} - # get all the field names - e = 0 - while True: - # find the next format spec of %(...) - s = self.format.find('%', e) + 1 - if s < 1 or self.format[s] != '(': - break # not %(... - e = self.format.find(')', s) - if e < 0: - break # didn't find a closing paren - # get text between parens as field name - fname = self.format[s + 1:e] - # len/precision specs will be 0-9 between ) and type char - fspec = '' - for i in xrange(e + 1, len(self.format)): - if self.format[i] in '1234567890.+-# lLh': - fspec += self.format[i] - else: - break # this char is not a spec char, it is the type char - ftype = self.format[i] - i += 1 - # is the field type a intype:outtype def? - if i < len(self.format) and self.format[i] == ':': - e = self.format.find(' ', i) # find the end whitespace - # split on: to get input:output mapping - ftype, outtype = self.format[i - 1:e].split(':') - else: - outtype = None # output will be same as input type - e = i # start at next char on loop - try: # field name to column mapping - fname, fmap = fname.split(':') - except: - fmap = fname # no mapping - if typemap and ftype in typemap and not outtype: - try: - (ftype, outtype) = typemap[ftype] - except: - outtype = typemap[ftype] - # append the field name,type,spec,mapping - self.fields.append((fname, ftype, fspec)) - self.fieldnames.append(fname) - if outtype: - self.fieldmap[fname] = (fmap, outtype) # map of in to out,type - - def parse(self, *args, **kw): - '''parse the input args/kwargs into a record dict according to format string - - timestamps are formatted to date/time strings - - fields not in the input will be defined but blank - - extra fields in the record will be formatted into a - "name=value name2=value2..." string and put in 'extra' - - args will go into 'data' - - format keyword can contain a new format string to use (this also sets format for future output) - ''' - # convert timestamps to proper format - for ts in [k for k in kw if k == 'ts' or k.endswith('time')]: - dt = ts[:-4] + 'datetime' # ts->datetime , Xtime -> Xdatetime - kw[dt] = datetime.datetime.fromtimestamp( - float(kw[ts])).strftime(self.timeformat) # format properly - if kw.get('direction') is 'cs': - kw['dir_arrow'] = '->' - elif kw.get('direction') is 'sc': - kw['dir_arrow'] = '<-' - else: - kw['dir_arrow'] = '--' - if 'format' in kw: - self.setformat(kw['format']) # change the format string? - del kw['format'] - # create the record initialized to the _NULL value - rec = dict((f, self._NULL) for f in self.fieldnames) - # populate record from datadict if datadict key is a field - if self._FILTER_EXTRA: - rec.update( - dict((f, kw[f]) for f in self.fieldnames if (f in kw and kw[f] != None))) - # place extra datadict keys into the extra field (and exclude the - # addr tuple) - if self.extra: - rec['extra'] = self.delim.join(['%s=%s' % (f, kw[f]) for f in sorted( - kw.keys()) if f not in self.fieldnames and f != 'addr']) - else: # not filtering extra, just lump them in as fields - rec.update(kw) - # populate the data field - if args: - rec['data'] = self.delim.join(map(str, args)) - return rec - - def dump(self, pkt=None, **kw): # pass packets to pcap - '''dump raw packet data to an output - override this if you want a format other than pcap''' - pktdata = str(pkt) # might be string, might be a dpkt object - pktlen = kw.get('len', len(pktdata)) - if self.pcapwriter: - self.pcapwriter.write(pktlen, pktdata, kw['ts']) - else: - self.log(util.hexPlusAscii(str(pkt)), level=logging.DEBUG) - - # close the PCAP output - def close(self): - if self.pcapwriter: - self.pcapwriter.close() - - def dispatch(self, m, *args, **kwargs): - '''dispatch from Q pop''' - if m == 'write': - self.write(*args, **kwargs) - if m == 'alert': - self.alert(*args, **kwargs) - if m == 'dump': - self.dump(*args, **kwargs) - - def setup(self): - """ - Perform any additional setup outside of the standard __init__. - Runs after command-line arguments are parsed, but before decoders are run. - For example, printing header data to the outfile. - """ - pass - - -class FileOutput(Output): - - def __init__(self, *args, **kw): - '''configuration for fileoutput: - fh= - file=filename to write to - mode=mode to open file as, default 'w' - ''' - # do base init first - Output.__init__(self, *args, **kw) - # get the output filehandle or file - f = None - if 'fh' in kw: - self.fh = kw['fh'] - return - elif 'file' in kw: - f = kw['file'] - elif args: - f = args[0] - if f: - if 'mode' in kw: - mode = kw['mode'] - else: - mode = 'w' - if mode == 'noclobber': - mode = 'w' - try: - while os.stat(f): - p = f.split('-') - try: - p, n = p[:-1], int(p[-1]) - except ValueError: - n = 0 - f = '-'.join(p + ['%04d' % (int(n) + 1)]) - except OSError: - pass # file not found - self.fh = open(f, mode) - else: - self.fh = sys.stdout - - def write(self, obj, **kw): - '''write session data to the session output or stdout''' - if self.sessionwriter: - self.sessionwriter.write(obj, **kw) - elif self.fh: - self.fh.write(str(obj)) - if self.nobuffer: - self.fh.flush() - - def close(self): - '''close output if not stdout''' - if self.fh != sys.stdout: - self.fh.close() - Output.close(self) - - -class TextOutput(FileOutput): - - '''formatted text output to file or stdout''' - - _DEFAULT_FORMAT = "%(decoder)s %(datetime)s %(sip)16s:%(sport)-5s %(dir_arrow)s %(dip)16s:%(dport)-5s ** %(data)s **" - _NULL = '' - - _FILTER_EXTRA = True - - def __init__(self, *args, **kw): - if 'extra' in kw: - self._DEFAULT_FORMAT += " [ %(extra)s ]" - FileOutput.__init__(self, *args, **kw) - - def alert(self, *args, **kw): - '''write an alert record - we pass in the decoder object and args/dict''' - rec = self.parse(*args, **kw) - if rec: - self.fh.write(self.format % rec) - if self.nobuffer: - self.fh.flush() - - -class DBOutput(Output): - - '''format strings as used by the DBOutput module to create tables and map fields - these follow the usual %(name)type and in most cases a custom format string will work - defualt type maps are: - s,r = VARCHAR (if field len given) /TEXT (if no len) - c = CHAR(1) - x,X,o = VARCHAR - d,i,u = INTEGER - e,E,f,F,g,G = DECIMAL - with the following extra: (using these breaks text format string compatibility) - b = boolean - t = timestamp - D = datetime - T = this field selects table - (following are postgres-only) - A = inet - H = host - N = cidr - M = macaddr - format string can also map field to column with %(field:column)type - or specify an explicit column type with %(field:column)pytype:DBTYPE - (note this also breaks compatibility with text format strings) - ''' - - _DEFAULT_FORMAT = "%(decoder)T %(ts:timestamp)t %(sip)s %(sport)s %(dip)s %(dport)s %(data:alert)s" - _NULL = None - # format type to (type,coltype) map - _TYPEMAP = {'s': 'VARCHAR', 'r': 'VARCHAR', 'c': 'CHAR(1)', - 'x': 'VARCHAR', 'X': 'VARCHAR', 'o': 'VARCHAR', - 'd': 'INTEGER', 'i': 'INTEGER', 'u': 'INTEGER', - 'e': 'DECIMAL', 'E': 'DECIMAL', - 'f': 'DECIMAL', 'F': 'DECIMAL', - 'g': 'DECIMAL', 'G': 'DECIMAL', - # 'b' isn't a python type, so (ftype,DBTYPE) tuple for value formats input as ftype - 'b': ('d', 'BOOLEAN'), - # not standard across database types! - 't': ('f', 'TIMESTAMP'), 'D': ('s', 'DATETIME'), - 'A': ('s', 'INET'), 'H': ('s', 'HOST'), 'N': ('s', 'CIDR'), 'M': ('s', 'MACADDR')} # these are postgres specific - - # acceptable params to pass to db module connect method - _DBCONNPARAMS = ['host', 'user', 'passwd', - 'password', 'db', 'database', 'port', 'charset'] - - # map of db type to insert placeholder. '%s' is the default, but sqlite3 doesn't like it - # you can override this with the 'placeholder' config keyword - _DBTYPE_PLACEHOLDER_MAP = {'sqlite3': '?'} - - def __init__(self, *args, **kw): - '''configuration: - config=db config .ini file name to parse - - config keywords: - - dbtype=database type, selects DB API module to load - in conf file use [dbtype] section name instead - - host,user,passwd,password,db,database,port will be passed to db module if present - - table=db table to use if not specified by a field - - insert_param=character to use as parameter placeholder for INSERT - (sqlite3=?, default=%%s) - - format_types=types to format before insert (default=x) - ('s' to pad strings, 'x' to convert to hex, 'f' to format floats, 'fx' for hex and floats...) - ''' - self.dbconfig = kw.copy() - # if we were passed a config.ini file, parse it and add the k/v pairs - # to the config - if 'config' in self.dbconfig: - import ConfigParser - config = ConfigParser.ConfigParser() - config.read(self.dbconfig['config']) - sections = config.sections() - if len(sections) > 0: - self.dbconfig['dbtype'] = sections[0] - for k, v in config.items(sections[0], raw=True): - self.dbconfig[k] = v - # import the db module - self.db = __import__(self.dbconfig['dbtype']) - # create a connection, using a dict filtered to db conn params - self.dbconn = self.db.connect( - *args, **dict((k, self.dbconfig[k]) for k in self._DBCONNPARAMS if k in self.dbconfig)) - # do the base init last to catch the format string, etc.. (as it may - # have come from the config file) - Output.__init__(self, *args, **self.dbconfig) - - def createtable(self, table=None): - '''creates a table based on the format string''' - if not table and 'table' in self.dbconfig: - table = self.dbconfig['table'] - try: - cursor = self.dbconn.cursor() - sqlfields = [] - for fname, ftype, fspec in [f for f in self.fields if f[1] != 'T']: - ctype = self.fieldmap[fname][1] - # if no width spec, use TEXT instead of VARCHAR and hope the db - # likes it - if ctype == 'VARCHAR' and not fspec: - ctype = 'TEXT' - fdef = self.fieldmap[fname][0] + ' ' + ctype - if fspec: - # try to conver python format spec to something SQL will - # take - fdef += '(' + \ - fspec.strip('+-# lLh').replace('.', ',') + ')' - sqlfields.append(fdef) - sql = 'CREATE TABLE "' + table + '" (' + ','.join(sqlfields) + ')' - self.log(sql, logging.DEBUG) - return cursor.execute(sql) - except: - raise - - def close(self): - '''closes database connection''' - self.dbconn.close() - Output.close(self) - - def alert(self, *args, **kw): - '''write an output record - we pass in the decoder object and args/dict''' - rec = self.parse(self, *args, **kw) - if rec: - self.insert(rec) - - def setformat(self, formatstr=None): - '''calls main setformat and then builds the insert SQL''' - # what is the insert param?? some databases use %s, some use ? - # try to map it or take the placeholder keyword from config - ph = self.dbconfig.get('insert_param', - self._DBTYPE_PLACEHOLDER_MAP.get( - self.dbconfig['dbtype'], '%%s') - ) - # these are the types we need to format before passing to the db - self.format_types = self.dbconfig.get('format_types', 'x') - Output.setformat(self, formatstr, typemap=self._TYPEMAP) - # build all fields we map (except for [T]able select) - self.tablefield = 'decoder' # default to decodername - for fname, ftype, fspec in self.fields: - if ftype == 'T': - self.tablefield = fname - sqlfields = [self.fieldmap[fname][0] - for (fname, ftype, fspec) in self.fields if fname in self.fieldmap] - self.insertsql = 'INSERT INTO "%%s" (%s) VALUES (%s)' % ( - ','.join(sqlfields), ','.join([ph] * len(sqlfields))) - - def insert(self, rec, table=None): - ''' inserts rec dict using self.format into table (if given, else default or specified by field) - if insert fails, tries to create table and insert again before raising exception ''' - if not table: - if 'table' in self.dbconfig: - table = self.dbconfig['table'] - elif rec[self.tablefield]: - table = rec[self.tablefield] - try: - sqlvalues = [] - cursor = self.dbconn.cursor() - for fname, ftype, fspec in self.fields: - if fname in self.fieldmap: - # do we preformat this data? - if ftype in self.format_types: - sqlvalues.append(('%' + fspec + ftype) % rec[fname]) - else: - sqlvalues.append(rec[fname]) - # create a INSERT INTO table (fields) VALUES (?,?,?) for execute - sql = self.insertsql % table - self.log(sql + ' %s' % sqlvalues, logging.DEBUG) - except: - raise - # try once, if it fails, try to create table and retry - # throws on second failure or create table failure - fail = False - while True: - try: - cursor.execute(sql, sqlvalues) - self.dbconn.commit() - break # success - except Exception, e: - self.log(e, level=logging.WARNING) - if fail: - raise - else: - fail = True - try: - self.createtable(table) - except: - raise - - -class PCAPWriter(FileOutput): - - '''writes a pcap file''' - - def __init__(self, *args, **kw): - FileOutput.__init__(self, *args, **kw) - if self.fh: - self.fh.write( - struct.pack('IHHIIII', 0xa1b2c3d4, 2, 4, 0, 0, 65535, 1)) - - # overrides Output.write to write session as PCAP - # data flow is Output.dump->pcapwriter.write - def write(self, pktlen, pktdata, ts): - if self.fh: - self.fh.write( - struct.pack('II', int(ts), int((ts - int(ts)) * 1000000))) - # captured length, original length - self.fh.write(struct.pack('II', len(pktdata), pktlen)) - self.fh.write(pktdata) - - -class SessionWriter(Output): - - '''writes the session to one or more files''' - - def __init__(self, session=None, **kw): - self.file = kw.get('session', session) - self.dir = kw.get('direction', 'both') - self.mode = kw.get('mode', 'a') - self.timeformat = (kw.get('timeformat', self._DEFAULT_TIMEFORMAT)) - self.fieldnames = [] - - def write(self, obj, **kwargs): - out = None - kw = dict(**kwargs) - # if a session object with info() and data() methods (conn or blob, but - # not packet) - try: - kw.update(**obj.info()) # get object info - kw = self.parse(**kw) - if self.dir == 'both': - ds = [None] - elif self.dir == 'split': - ds = ['cs', 'sc'] - else: - ds = [self.dir] - for d in ds: - kw.update(direction=d if d else 'both') # set direction - # format filename and open - out = FileOutput(self.file % kw, mode=self.mode) - # write obj data for direction - out.fh.write(obj.data(direction=d)) - out.close() - except: # if not a session object - # build filename from kw - out = FileOutput(self.file % kw, mode=self.mode) - out.fh.write(str(obj)) - out.close() - - -class QueueOutput(Output): - - '''pipes pickled packets to parent process''' - - def __init__(self, q, **kwargs): - self.queue = q - Output.__init__(self, **kwargs) - - def write(self, *args, **kw): self.dispatch('write', *args, **kw) - - def alert(self, *args, **kw): self.dispatch('alert', *args, **kw) - - def dump(self, *args, **kw): self.dispatch('dump', *args, **kw) - - def dispatch(self, m, *args, **kw): # takes (method,...) to Q - self.queue.put((m, args, kw)) - - def close(self): - self.queue.close() - Output.close(self) - - -# default output module -obj = TextOutput diff --git a/lib/output/xmlout.py b/lib/output/xmlout.py deleted file mode 100644 index 37a5e7a..0000000 --- a/lib/output/xmlout.py +++ /dev/null @@ -1,60 +0,0 @@ -''' -@author: tparker -''' - -import output -import util -import dshell -from xml.etree import ElementTree as ET - - -class XMLOutput(output.FileOutput): - - '''XMLOutput Module''' - - def __init__(self, *args, **kwargs): - '''init the underlying file output to get the file handle''' - output.FileOutput.__init__( - self, *args, **kwargs) # pass all to fileoutput - self.root = ET.Element('dshell') - self.element = self.root - - def alert(self, *args, **kwargs): - '''we will assume we get alerts before we get the matching session data''' - self.element = ET.SubElement( - self.root, 'alert', self._filter_attr(kwargs)) - self.element.text = self._filter_text(' '.join(args)) - - def write(self, obj, parent=None, **kwargs): - '''write the object data under the last alert element (or the root if no alert) - if a conn object recurse in by iterating - else write the string output of the object''' - if not parent: - parent = self.element - kw = dict(**kwargs) - # turns "" into "yyyy" - tag = str(type(obj)).split("'", 2)[1] - if tag.startswith('dshell.'): # is a dshell object - kw.update(**obj.info()) # get attribs - # turns "dshell.Connection" into "Connection" - tag = tag.split('dshell.')[1] - e = ET.SubElement(parent, tag, self._filter_attr(kw)) - if tag == 'Connection': # recurse on blobs in conn - for blob in obj: - self.write(blob, parent=e) - return # subobjects will have the data - # leave this up to the object to handle - e.text = self._filter_text(str(obj)) - - def _filter_attr(self, d): return dict((k, str(v)) - for (k, v) in d.iteritems()) - - def _filter_text(self, t): return ''.join(c for c in t if ord(c) < 128) - - def close(self): - '''write the ElementTree to the file''' - ET.ElementTree(self.root).write(self.fh) - -'''NOTE: output modules return obj=reference to the CLASS - instead of a dObj=instance so we can init with args''' -obj = XMLOutput diff --git a/lib/smbdecoder.py b/lib/smbdecoder.py deleted file mode 100644 index 3266e99..0000000 --- a/lib/smbdecoder.py +++ /dev/null @@ -1,429 +0,0 @@ -''' -2015 Feb 13 - -Extend dshell.TCPDecoder to handle SMB Message Requests/Responses - -Will call SMBHandler( - conn = Connection(), - request=dshell.smb.smbdecoder.SMB(), - response=dshell.smb.smbdecoder.SMB(), - requesttime=timestamp, - responsetime=timestamp, - cmd= [3] - status= [2] A 32-bit field used to communicate error - messages from the server to the client - ) - -Requests are tracked by MID - -It will be up to the decoder to handle each SMB Command. - -Several functions create throw-away variables when unpacking data. Because of -this, pylint checks were run with "-d unused-variables" - -References: -[1] http://anonsvn.wireshark.org/viewvc/trunk/epan/dissectors/packet-smb.c?revision=32650&view=co&pathrev=32650 -[2] http://msdn.microsoft.com/en-us/library/ee441774%28v=prot.13%29.aspx SMB Header Protocol Definition -[3] http://msdn.microsoft.com/en-us/library/ee441616(v=prot.13).aspx -''' - - -import dshell -import struct -#import binascii - -SMB_PROTOCOL = '\xffSMB' -SMB_STATUS_SUCCESS = 0x0 -NTLMSSP_IDENT = 'NTLMSSP\x00' -NTLMSSP_AUTH = 0x00000003 -NTLMSSP_CHALLENGE = 0x00000002 - - -class SMBDecoder(dshell.TCPDecoder): - - def __init__(self, **kwargs): - self.requests = {} # requests are stored by MID - dshell.TCPDecoder.__init__(self, **kwargs) - - def connectionInitHandler(self, conn): - self.requests[conn.addr] = {} - - def blobHandler(self, conn, blob): - data = blob.data() - offset = 0 - datalen = len(data) - while offset < datalen: - try: - offset += self.smbFactory(conn, blob, data[offset:]) - except InsufficientData: - return - - # Returns number of bytes used by NetBIOS+SMB - # e.g. mlength+4 - def smbFactory(self, conn, blob, data): - - try: - msgtype, mlength, smbdata = self.parseNetBIOSSessionService(data) - except InsufficientData: - raise - - try: - # create SMB Message (abstract data model: SMB header + extra) - smb = SMB(smbdata) - except InsufficientData: - raise - - if smb.proto != SMB_PROTOCOL: - return mlength + 4 - - if blob.direction == 'cs': - self.requests[conn.addr][smb.mid] = [blob.starttime, smb] - elif blob.direction == 'sc': - if smb.mid in self.requests[conn.addr].keys(): - requesttime, request = self.requests[conn.addr][smb.mid] - responsetime, response = blob.starttime, smb - - if 'SMBHandler' in dir(self): - self.SMBHandler(conn=conn, request=request, response=response, - requesttime=requesttime, responsetime=responsetime, cmd=smb.cmd, status=smb.status) - - del self.requests[conn.addr][smb.mid] - - return mlength + 4 - - def connectionHandler(self, conn): - """ clean up all requests associated with this connection """ - if conn.addr in self.requests: - if len(self.requests[conn.addr]) > 0: - for mid in self.requests[conn.addr].keys(): - requesttime, request = self.requests[conn.addr][mid] - self.SMBHandler(conn=conn, request=request, response=None, - requesttime=requesttime, responsetime=None, cmd=request.cmd, status=-1) - del self.requests[conn.addr][mid] - del self.requests[conn.addr] - - def postModule(self): - """ clean up self.requests to process all SMB messages that only have a single request and no response """ - for k in self.requests.keys(): - for mid in self.requests[k].keys(): - requesttime, request = self.requests[k][mid] - self.SMBHandler(conn=None, request=request, response=None, - requesttime=requesttime, responsetime=None, cmd=request.cmd, status=-1) - del self.requests[k][mid] - del self.requests[k] - - def parseNetBIOSSessionService(self, data): - """ parse the NetBIOS Session Service header [2]""" - if len(data) < 4: - raise InsufficientData - msgtype = struct.unpack('B', data[0])[0] - arg1, arg2, arg3 = struct.unpack('3B', data[1:4]) - mlength = (arg1 * 512) + (arg2 * 256) + arg3 - smbdata = data[4:] - return msgtype, mlength, smbdata - - def SMBHandler(self, conn, request=None, response=None, requesttime=None, responsetime=None, cmd=None, status=None): - "Placeholder. Overwrite in separate decoders." - pass - - -class InsufficientData(Exception): - pass - - -class SMB(): - - def __init__(self, pktdata): - """ - Generic SMB class. Handles parsing of SMB Header Messages and some specific SMB Command Objects - - Reference: - [1] http://msdn.microsoft.com/en-us/library/ee441774%28v=prot.13%29.aspx SMB Header Protocol Definition - [2] http://msdn.microsoft.com/en-us/library/ee441616(v=prot.13).aspx - - - proto = 4 bytes 4s 4-byte literal string '\xFF', 'S', 'M', 'B' - cmd = 1 byte B one-byte command code, commands listed at [2] - status = 4 bytes I A 32-bit field used to communicate error messages from the server to the client [SUCCESS = 0x0000 - flags1 = 1 byte B - flags2 = 2 bytes H - pidhigh = 2 bytes H - security = 8 bytes 8s - reserved = 2 bytes H - tid = 2 bytes H - pidlow = 2 bytes H - uid = 2 bytes H Associate a session with a specific user - mid = 2 bytes H Multiplexer identifier - """ - self.filename = None - if len(pktdata) < 32: - raise InsufficientData - self.proto, self.cmd, self.status, self.flags1, self.flags2, self.pidhigh, self.security, self.reserved, self.tid, self.pidlow, self.uid, self.mid = struct.unpack( - '<4sBIBHH8sHHHHH', pktdata[:32]) - self.smbdata = pktdata[32:] - - def PARSE_NT_CREATE_ANDX_REQUEST(self, data): - """ return the filename associated with the request (return None if err)""" - try: - wct, andxcmd, rsrv1, andxoffset, rsrv2, filenamelen, cflags, rootfid, mask, size, attrib, share = struct.unpack( - ' len(secblob): - return None - msgtype = struct.unpack( - ' Date: Tue, 22 Sep 2020 16:17:36 +0000 Subject: [PATCH 090/166] Removing print statement, appears to be leftover from debugging module --- dshell/plugins/http/web.py | 1 - 1 file changed, 1 deletion(-) diff --git a/dshell/plugins/http/web.py b/dshell/plugins/http/web.py index 7d4d3cd..ad11ca1 100644 --- a/dshell/plugins/http/web.py +++ b/dshell/plugins/http/web.py @@ -26,7 +26,6 @@ def http_handler(self, conn, request, response): # Collect basics about the request, if available method = request.method host = request.headers.get("host", "") - print(request.headers) uri = request.uri # useragent = request.headers.get("user-agent", None) # referer = request.headers.get("referer", None) From ccd45dcd67185f048dd96d326c0ecd1c207b8827 Mon Sep 17 00:00:00 2001 From: adam Date: Tue, 22 Sep 2020 16:24:52 +0000 Subject: [PATCH 091/166] Pass complete response headers to alertout --- dshell/plugins/http/web.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/dshell/plugins/http/web.py b/dshell/plugins/http/web.py index ad11ca1..141b5c8 100644 --- a/dshell/plugins/http/web.py +++ b/dshell/plugins/http/web.py @@ -58,8 +58,10 @@ def http_handler(self, conn, request, response): hash) if not request: self.write(data, method=method, host=host, uri=uri, version=version, status=status, reason=reason, hash=hash, **response.blob.info()) - else: + elif not response: self.write(data, method=method, uri=uri, version=version, status=status, reason=reason, hash=hash, **request.headers, **request.blob.info()) + else: + self.write(data, method=method, uri=uri, version=version, status=status, reason=reason, hash=hash, response_headers=response.headers, **request.headers, **request.blob.info()) return conn, request, response if __name__ == "__main__": From b0100183a974e86ae3fe6f3e489b2b1861bea9cb Mon Sep 17 00:00:00 2001 From: adam Date: Wed, 23 Sep 2020 12:47:57 +0000 Subject: [PATCH 092/166] Move request.headers into nested dictionary request_headers --- dshell/plugins/http/web.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dshell/plugins/http/web.py b/dshell/plugins/http/web.py index 141b5c8..a8b5836 100644 --- a/dshell/plugins/http/web.py +++ b/dshell/plugins/http/web.py @@ -61,7 +61,7 @@ def http_handler(self, conn, request, response): elif not response: self.write(data, method=method, uri=uri, version=version, status=status, reason=reason, hash=hash, **request.headers, **request.blob.info()) else: - self.write(data, method=method, uri=uri, version=version, status=status, reason=reason, hash=hash, response_headers=response.headers, **request.headers, **request.blob.info()) + self.write(data, method=method, uri=uri, version=version, status=status, reason=reason, hash=hash, request_headers=request.headers, response_headers=response.headers, **request.blob.info()) return conn, request, response if __name__ == "__main__": From 2f4dbdd6fafb78bca151a6676cdefeccec860e52 Mon Sep 17 00:00:00 2001 From: dev195 Date: Wed, 23 Sep 2020 13:33:41 -0400 Subject: [PATCH 093/166] Fixed minor code documentation wording, a README reference, and .gitignore directory list --- .gitignore | 1 + README | 2 +- README.md | 2 +- dshell/core.py | 6 +++--- 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/.gitignore b/.gitignore index e37d53a..b78f06b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ *.pyc __pycache__ Dshell.egg-info +build/ diff --git a/README b/README index 3c1feea..f6594d0 100644 --- a/README +++ b/README @@ -11,7 +11,7 @@ Key features: ## Requirements * Linux (developed on Red Hat Enterprise Linux 6.7) * Python 3 (developed with Python 3.5.1) -* [pypacker](https://github.com/mike01/pypacker) +* [pypacker](https://gitlab.com/mike01/pypacker) * [pcapy](http://www.coresecurity.com/corelabs-research/open-source-tools/pcapy) * [geoip2](https://github.com/maxmind/GeoIP2-python) * [MaxMind GeoIP2 datasets](https://dev.maxmind.com/geoip/geoip2/geolite2/) diff --git a/README.md b/README.md index 3c1feea..f6594d0 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ Key features: ## Requirements * Linux (developed on Red Hat Enterprise Linux 6.7) * Python 3 (developed with Python 3.5.1) -* [pypacker](https://github.com/mike01/pypacker) +* [pypacker](https://gitlab.com/mike01/pypacker) * [pcapy](http://www.coresecurity.com/corelabs-research/open-source-tools/pcapy) * [geoip2](https://github.com/maxmind/GeoIP2-python) * [MaxMind GeoIP2 datasets](https://dev.maxmind.com/geoip/geoip2/geolite2/) diff --git a/dshell/core.py b/dshell/core.py index bc78a9e..70ab91d 100644 --- a/dshell/core.py +++ b/dshell/core.py @@ -38,7 +38,7 @@ logging.basicConfig(format="%(levelname)s (%(name)s) - %(message)s") logger = logging.getLogger("dshell.core") -__version__ = "1.1" +__version__ = "3.1.3" class SequenceNumberError(Exception): """ @@ -95,7 +95,7 @@ class PacketPlugin(object): description: short description of the plugin (used with decode -l) longdescription: verbose description of the plugin (used with -h) bpf: default BPF to apply to traffic entering plugin - compiled_bpf: a compiled BPF for pcapy, usually created in bin/decode + compiled_bpf: a compiled BPF for pcapy, usually created in decode.py vlan_bpf: boolean that tells whether BPF should be compiled with VLAN support author: preferably, the initials of the plugin's author @@ -241,7 +241,7 @@ def set_link_layer_type(self, datalink): def recompile_bpf(self): "Compile the BPF stored in the .bpf attribute" - # This function is normally only called by the bin/decode.py script, + # This function is normally only called by the decode.py script, # but can also be called by plugins that need to dynamically update # their filter. if not self.bpf: From 640d4dbbc8cce3607e40ac7e2120f357f02fa3b3 Mon Sep 17 00:00:00 2001 From: dev195 Date: Wed, 23 Sep 2020 13:40:48 -0400 Subject: [PATCH 094/166] Fixed logging bug when using the -v flag without geoip data files --- dshell/dshellgeoip.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/dshell/dshellgeoip.py b/dshell/dshellgeoip.py index f53b257..f8c0bbe 100644 --- a/dshell/dshellgeoip.py +++ b/dshell/dshellgeoip.py @@ -112,7 +112,8 @@ def geoip_location_lookup(self, ip): class DshellFailedGeoIP(object): "Class used in place of DshellGeoIP if GeoIP database files are not found." - def __init__(self): + def __init__(self, logger=logging.getLogger("dshellgeoip.py")): + self.logger = logger self.geodir = os.path.join(get_data_path(), 'GeoIP') self.geoccdb = None self.geoasndb = None From cadbacc9646ef32d844ad201e0a4c782292485ef Mon Sep 17 00:00:00 2001 From: adam Date: Mon, 5 Oct 2020 15:38:11 +0000 Subject: [PATCH 095/166] Decoder to extract host public key and other metadata from SSH connections. --- dshell/plugins/ssh/__init__.py | 0 dshell/plugins/ssh/ssh-pubkey.py | 162 +++++++++++++++++++++++++++++++ 2 files changed, 162 insertions(+) create mode 100644 dshell/plugins/ssh/__init__.py create mode 100644 dshell/plugins/ssh/ssh-pubkey.py diff --git a/dshell/plugins/ssh/__init__.py b/dshell/plugins/ssh/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/dshell/plugins/ssh/ssh-pubkey.py b/dshell/plugins/ssh/ssh-pubkey.py new file mode 100644 index 0000000..fffcd15 --- /dev/null +++ b/dshell/plugins/ssh/ssh-pubkey.py @@ -0,0 +1,162 @@ +""" +Generates color-coded Screen/HTML output similar to Wireshark Follow Stream +""" + +import dshell.core +from dshell.output.alertout import AlertOutput +import struct +import base64 +import hashlib + +class DshellPlugin(dshell.core.ConnectionPlugin): + + def __init__(self): + super().__init__( + name="ssh-pubkey", + author="amm", + description="Extract server ssh public key from key exchange", + bpf="tcp port 22", + output=AlertOutput(label=__name__) + ) + + def connection_handler(self, conn): + + server_banner = '' + sc_blob_count = 0 + cs_blob_count = 0 + + info = {} + + for blob in conn.blobs: + + # + # CS Blobs: Only interest is a client banner + # + if blob.direction == 'cs': + cs_blob_count += 1 + if cs_blob_count > 1: + continue + else: + blob.reassemble(allow_overlap=True, allow_padding=True) + if not blob.data: + continue + info['clientbanner'] = blob.data.split(b'\x0d')[0].rstrip().decode('utf-8') + if not info['clientbanner'].startswith('SSH'): + return # NOT AN SSH CONNECTION + continue + + # + # SC Blobs: Banner and public key + # + sc_blob_count += 1 + blob.reassemble(allow_overlap=True, allow_padding=True) + if not blob.data: + continue + d = blob.data + + + # Server Banner + if sc_blob_count == 1: + info['serverbanner'] = d.split(b'\x0d')[0].rstrip().decode('utf-8') + if not info['serverbanner'].startswith('SSH'): + return # NOT AN SSH CONNECTION + continue + + # Key Exchange Packet/Messages + mlist = messagefactory(d) + stop_blobs = False + for m in mlist: + if m.message_code == 31: + info['host_pubkey'] = m.host_pub_key + stop_blobs = True + break + if stop_blobs: + break + + + if 'host_pubkey' in info: + # Calculate key fingerprints + info['host_fingerprints'] = {} + for hash_scheme in ("md5", "sha1", "sha256"): + hashfunction = eval("hashlib."+hash_scheme) + thisfp = key_fingerprint(info['host_pubkey'], hashfunction) + info['host_fingerprints'][hash_scheme] = ':'.join(['%02x'%b for b in thisfp]) + + msg = "%s" % (info['host_pubkey']) + self.write(msg, **info, **conn.info()) + + +def messagefactory(data): + + datalen = len(data) + offset = 0 + msglist = [] + while offset < datalen: + try: + msg = sshmessage(data[offset:]) + except ValueError: + return msglist + msglist.append(msg) + offset += msg.packet_len + 4 + + return msglist + +class sshmessage: + + def __init__(self, rawdata): + self.__parse_raw(rawdata) + + def __parse_raw(self, data): + datalen = len(data) + if datalen < 6: + raise ValueError + + (self.packet_len, self.padding_len, self.message_code) = struct.unpack(">IBB", data[0:6]) + if datalen < self.packet_len + 4: + raise ValueError + self.body = data[6:4+self.packet_len] + + # ECDH Kex Reply + if self.message_code == 31: + host_key_len = struct.unpack(">I", self.body[0:4])[0] + full_key_net = self.body[4:4+host_key_len] + key_type_name_len = struct.unpack(">I", full_key_net[0:4])[0] + key_type_name = full_key_net[4:4+key_type_name_len] + key_data = full_key_net[4+key_type_name_len:] + if key_type_name_len > 50: + # something went wrong + # this probably isn't a code 31 + self.message_code = 0 + else: + self.host_pub_key = "%s %s" % (key_type_name.decode('utf-8'), base64.b64encode(full_key_net).decode('utf-8')) + +def key_fingerprint(ssh_pubkey, hashfunction=hashlib.sha256): + + # Treat as bytes, not string + if type(ssh_pubkey) == str: + ssh_pubkey = ssh_pubkey.encode('utf-8') + + # Strip space from end + ssh_pubkey = ssh_pubkey.rstrip(b"\r\n\0 ") + + # Only look at first line + ssh_pubkey = ssh_pubkey.split(b"\n")[0] + # If two spaces, look at middle segment + if ssh_pubkey.count(b" ") >= 1: + ssh_pubkey = ssh_pubkey.split(b" ")[1] + + # Try to decode key as base64 + try: + keybin = base64.b64decode(ssh_pubkey) + except: + sys.stderr.write("Invalid key value:\n") + sys.stderr.write(" \"%s\":\n" % ssh_pubkey) + return None + + # Fingerprint + return hashfunction(keybin).digest() + + + +if __name__ == "__main__": + print(DshellPlugin()) From 18980f6cf00be342b748683f888a28357538537b Mon Sep 17 00:00:00 2001 From: adam Date: Mon, 5 Oct 2020 15:58:05 +0000 Subject: [PATCH 096/166] Fix comment --- dshell/plugins/ssh/ssh-pubkey.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dshell/plugins/ssh/ssh-pubkey.py b/dshell/plugins/ssh/ssh-pubkey.py index fffcd15..8f2d34c 100644 --- a/dshell/plugins/ssh/ssh-pubkey.py +++ b/dshell/plugins/ssh/ssh-pubkey.py @@ -1,5 +1,5 @@ """ -Generates color-coded Screen/HTML output similar to Wireshark Follow Stream +Extract server ssh public key from key exchange """ import dshell.core From bf23dbb57f4baa2c53ecc7bd58becb3f84c9033c Mon Sep 17 00:00:00 2001 From: adam Date: Tue, 6 Oct 2020 15:52:13 +0000 Subject: [PATCH 097/166] Decode to string after checking for SSH magicbytes --- dshell/plugins/ssh/ssh-pubkey.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/dshell/plugins/ssh/ssh-pubkey.py b/dshell/plugins/ssh/ssh-pubkey.py index 8f2d34c..9e48d6b 100644 --- a/dshell/plugins/ssh/ssh-pubkey.py +++ b/dshell/plugins/ssh/ssh-pubkey.py @@ -40,9 +40,13 @@ def connection_handler(self, conn): blob.reassemble(allow_overlap=True, allow_padding=True) if not blob.data: continue - info['clientbanner'] = blob.data.split(b'\x0d')[0].rstrip().decode('utf-8') - if not info['clientbanner'].startswith('SSH'): + info['clientbanner'] = blob.data.split(b'\x0d')[0].rstrip() + if not info['clientbanner'].startswith(b'SSH'): return # NOT AN SSH CONNECTION + try: + info['clientbanner'] = info['clientbanner'].decode('utf-8') + except UnicodeDecodeError: + return continue # From f867b107bd696da546912416a0b5e576bf317ef0 Mon Sep 17 00:00:00 2001 From: adam Date: Wed, 7 Oct 2020 13:50:09 +0000 Subject: [PATCH 098/166] Return connection objects --- dshell/plugins/ssh/ssh-pubkey.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/dshell/plugins/ssh/ssh-pubkey.py b/dshell/plugins/ssh/ssh-pubkey.py index 9e48d6b..df42ba7 100644 --- a/dshell/plugins/ssh/ssh-pubkey.py +++ b/dshell/plugins/ssh/ssh-pubkey.py @@ -42,11 +42,11 @@ def connection_handler(self, conn): continue info['clientbanner'] = blob.data.split(b'\x0d')[0].rstrip() if not info['clientbanner'].startswith(b'SSH'): - return # NOT AN SSH CONNECTION + return conn # NOT AN SSH CONNECTION try: info['clientbanner'] = info['clientbanner'].decode('utf-8') except UnicodeDecodeError: - return + return conn continue # @@ -63,7 +63,7 @@ def connection_handler(self, conn): if sc_blob_count == 1: info['serverbanner'] = d.split(b'\x0d')[0].rstrip().decode('utf-8') if not info['serverbanner'].startswith('SSH'): - return # NOT AN SSH CONNECTION + return conn # NOT AN SSH CONNECTION continue # Key Exchange Packet/Messages @@ -88,6 +88,7 @@ def connection_handler(self, conn): msg = "%s" % (info['host_pubkey']) self.write(msg, **info, **conn.info()) + return conn def messagefactory(data): From 486e25095e455147dd8e1b2581bc3b7369b91fd3 Mon Sep 17 00:00:00 2001 From: adam Date: Thu, 8 Oct 2020 10:27:07 +0000 Subject: [PATCH 099/166] Filter to pass flows with non-zero amounts of data --- dshell/plugins/flows/dataflows.py | 36 +++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 dshell/plugins/flows/dataflows.py diff --git a/dshell/plugins/flows/dataflows.py b/dshell/plugins/flows/dataflows.py new file mode 100644 index 0000000..ea31d51 --- /dev/null +++ b/dshell/plugins/flows/dataflows.py @@ -0,0 +1,36 @@ +""" +Displays netflows that have at least 1 byte transferred, by default. +Bytes threshold can be updated by the user. +""" + +import dshell.core +from dshell.output.netflowout import NetflowOutput + +class DshellPlugin(dshell.core.ConnectionPlugin): + + def __init__(self): + super().__init__( + name="dataflows", + description="Display netflows that have at least 1 byte transferred", + author="amm", + output=NetflowOutput(label=__name__), + optiondict={ + 'size': { + 'type': int, + 'default': 1, + 'metavar': 'SIZE', + 'help': 'number of bytes transferred (default: 1)'} + } + ) + + def premodule(self): + if self.size <= 0: + self.warn("Cannot have a size that's less than or equal to zero (size: {}). Setting to 1.".format(self.size)) + self.size = 1 + + def connection_handler(self, conn): + if conn.clientbytes + conn.serverbytes >= self.size: + self.write(**conn.info()) + return conn + + From b3731de0fc49d821ec47cdc357276ac1fae75b73 Mon Sep 17 00:00:00 2001 From: adam Date: Fri, 9 Oct 2020 10:05:30 +0000 Subject: [PATCH 100/166] Correct unicodedecode error on server banner --- dshell/plugins/ssh/ssh-pubkey.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/dshell/plugins/ssh/ssh-pubkey.py b/dshell/plugins/ssh/ssh-pubkey.py index df42ba7..5b0cc17 100644 --- a/dshell/plugins/ssh/ssh-pubkey.py +++ b/dshell/plugins/ssh/ssh-pubkey.py @@ -61,9 +61,13 @@ def connection_handler(self, conn): # Server Banner if sc_blob_count == 1: - info['serverbanner'] = d.split(b'\x0d')[0].rstrip().decode('utf-8') - if not info['serverbanner'].startswith('SSH'): + info['serverbanner'] = d.split(b'\x0d')[0].rstrip() + if not info['serverbanner'].startswith(b'SSH'): return conn # NOT AN SSH CONNECTION + try: + info['serverbanner'] = info['serverbanner'].decode('utf-8') + except UnicodeDecodeError: + pass continue # Key Exchange Packet/Messages From 9c641158a1600a241dcf61fd37eea6c202c88447 Mon Sep 17 00:00:00 2001 From: Davis Schirmer Date: Sat, 10 Oct 2020 01:38:25 -0400 Subject: [PATCH 101/166] Add initial Dockerfile --- Dockerfile | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 Dockerfile diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..4ecc200 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,32 @@ +FROM python:3-alpine as builder + +COPY . /src + +WORKDIR /src + +ARG BUILD_DEPS="curl gcc g++ libpcap-dev" +ARG OUI_SRC="http://standards-oui.ieee.org/oui.txt" + +RUN apk add --no-cache ${BUILD_DEPS} && python -m venv "/opt/venv" + +RUN curl --location --silent --output "/src/dshell/data/oui.txt" "${OUI_SRC}" + +ENV PATH="/opt/venv/bin:${PATH}" + +RUN pip install --upgrade pip wheel && pip install --use-feature=2020-resolver . + +FROM python:3-alpine + +ARG RUN_DEPS="bash libstdc++ libpcap" + +COPY --from=builder /opt/venv /opt/venv + +RUN apk add --no-cache ${RUN_DEPS} + +VOLUME ["/data"] + +WORKDIR "/data" + +ENV PATH="/opt/venv/bin:${PATH}" + +ENTRYPOINT ["dshell"] From ac150e5a958e5bc3ff7f722697158d418890610a Mon Sep 17 00:00:00 2001 From: adam Date: Thu, 15 Oct 2020 19:17:00 +0000 Subject: [PATCH 102/166] autopep8 --- dshell/plugins/ssh/ssh-pubkey.py | 80 +++++++++++++++++--------------- 1 file changed, 42 insertions(+), 38 deletions(-) diff --git a/dshell/plugins/ssh/ssh-pubkey.py b/dshell/plugins/ssh/ssh-pubkey.py index 5b0cc17..f81cc00 100644 --- a/dshell/plugins/ssh/ssh-pubkey.py +++ b/dshell/plugins/ssh/ssh-pubkey.py @@ -8,6 +8,7 @@ import base64 import hashlib + class DshellPlugin(dshell.core.ConnectionPlugin): def __init__(self): @@ -42,12 +43,13 @@ def connection_handler(self, conn): continue info['clientbanner'] = blob.data.split(b'\x0d')[0].rstrip() if not info['clientbanner'].startswith(b'SSH'): - return conn # NOT AN SSH CONNECTION + return conn # NOT AN SSH CONNECTION try: - info['clientbanner'] = info['clientbanner'].decode('utf-8') + info['clientbanner'] = info['clientbanner'].decode( + 'utf-8') except UnicodeDecodeError: - return conn - continue + return conn + continue # # SC Blobs: Banner and public key @@ -57,13 +59,12 @@ def connection_handler(self, conn): if not blob.data: continue d = blob.data - # Server Banner if sc_blob_count == 1: info['serverbanner'] = d.split(b'\x0d')[0].rstrip() if not info['serverbanner'].startswith(b'SSH'): - return conn # NOT AN SSH CONNECTION + return conn # NOT AN SSH CONNECTION try: info['serverbanner'] = info['serverbanner'].decode('utf-8') except UnicodeDecodeError: @@ -81,22 +82,22 @@ def connection_handler(self, conn): if stop_blobs: break - if 'host_pubkey' in info: # Calculate key fingerprints info['host_fingerprints'] = {} for hash_scheme in ("md5", "sha1", "sha256"): hashfunction = eval("hashlib."+hash_scheme) thisfp = key_fingerprint(info['host_pubkey'], hashfunction) - info['host_fingerprints'][hash_scheme] = ':'.join(['%02x'%b for b in thisfp]) - + info['host_fingerprints'][hash_scheme] = ':'.join( + ['%02x' % b for b in thisfp]) + msg = "%s" % (info['host_pubkey']) self.write(msg, **info, **conn.info()) return conn def messagefactory(data): - + datalen = len(data) offset = 0 msglist = [] @@ -110,8 +111,9 @@ def messagefactory(data): return msglist + class sshmessage: - + def __init__(self, rawdata): self.__parse_raw(rawdata) @@ -120,11 +122,12 @@ def __parse_raw(self, data): if datalen < 6: raise ValueError - (self.packet_len, self.padding_len, self.message_code) = struct.unpack(">IBB", data[0:6]) + (self.packet_len, self.padding_len, + self.message_code) = struct.unpack(">IBB", data[0:6]) if datalen < self.packet_len + 4: raise ValueError self.body = data[6:4+self.packet_len] - + # ECDH Kex Reply if self.message_code == 31: host_key_len = struct.unpack(">I", self.body[0:4])[0] @@ -137,34 +140,35 @@ def __parse_raw(self, data): # this probably isn't a code 31 self.message_code = 0 else: - self.host_pub_key = "%s %s" % (key_type_name.decode('utf-8'), base64.b64encode(full_key_net).decode('utf-8')) + self.host_pub_key = "%s %s" % (key_type_name.decode( + 'utf-8'), base64.b64encode(full_key_net).decode('utf-8')) -def key_fingerprint(ssh_pubkey, hashfunction=hashlib.sha256): - - # Treat as bytes, not string - if type(ssh_pubkey) == str: - ssh_pubkey = ssh_pubkey.encode('utf-8') - - # Strip space from end - ssh_pubkey = ssh_pubkey.rstrip(b"\r\n\0 ") - - # Only look at first line - ssh_pubkey = ssh_pubkey.split(b"\n")[0] - # If two spaces, look at middle segment - if ssh_pubkey.count(b" ") >= 1: - ssh_pubkey = ssh_pubkey.split(b" ")[1] - # Try to decode key as base64 - try: - keybin = base64.b64decode(ssh_pubkey) - except: - sys.stderr.write("Invalid key value:\n") - sys.stderr.write(" \"%s\":\n" % ssh_pubkey) - return None - - # Fingerprint - return hashfunction(keybin).digest() +def key_fingerprint(ssh_pubkey, hashfunction=hashlib.sha256): + # Treat as bytes, not string + if type(ssh_pubkey) == str: + ssh_pubkey = ssh_pubkey.encode('utf-8') + + # Strip space from end + ssh_pubkey = ssh_pubkey.rstrip(b"\r\n\0 ") + + # Only look at first line + ssh_pubkey = ssh_pubkey.split(b"\n")[0] + # If two spaces, look at middle segment + if ssh_pubkey.count(b" ") >= 1: + ssh_pubkey = ssh_pubkey.split(b" ")[1] + + # Try to decode key as base64 + try: + keybin = base64.b64decode(ssh_pubkey) + except: + sys.stderr.write("Invalid key value:\n") + sys.stderr.write(" \"%s\":\n" % ssh_pubkey) + return None + + # Fingerprint + return hashfunction(keybin).digest() if __name__ == "__main__": From 701e1c65365710247d9ad905b962b7f33b04d2ec Mon Sep 17 00:00:00 2001 From: adam Date: Fri, 16 Oct 2020 20:10:45 +0000 Subject: [PATCH 103/166] TLS Plugin --- dshell/plugins/ssl/tls.py | 966 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 966 insertions(+) create mode 100644 dshell/plugins/ssl/tls.py diff --git a/dshell/plugins/ssl/tls.py b/dshell/plugins/ssl/tls.py new file mode 100644 index 0000000..7302ad9 --- /dev/null +++ b/dshell/plugins/ssl/tls.py @@ -0,0 +1,966 @@ +""" +Extract interesting metadata from TLS connection setup +""" + +import dshell.core +from dshell.output.alertout import AlertOutput +import sys +import struct +import binascii +import hashlib +import OpenSSL +import time +import ja3.ja3 + +################################################################################################## +# +# Reference RFC 2246 (TLS Protocol Version 1.0) +# and RFC 3546 (TLS Extensions) +# +# http://www.ietf.org/rfc/rfc2246.txt +# http://www.ietf.org/rfc/rfc3546.txt +# http://www.ietf.org/rfc/rfc3280.txt +# +################################################################################################## + +##################### +# Custom Exceptions # +##################### + + +class Error(Exception): + pass + + +class InsufficientData(Exception): + pass + + +class UnsupportedOption(Exception): + pass + +#################################### +# Constants borrowed from dpkt.ssl # +#################################### + + +# SSLv3/TLS version +SSL3_VERSION = 0x0300 +TLS1_VERSION = 0x0301 +TLS1_2_VERSION = 0x0303 + +# Record type +SSL3_RT_CHANGE_CIPHER_SPEC = 20 +SSL3_RT_ALERT = 21 +SSL3_RT_HANDSHAKE = 22 +SSL3_RT_APPLICATION_DATA = 23 + +# Handshake message type +SSL3_MT_HELLO_REQUEST = 0 +SSL3_MT_CLIENT_HELLO = 1 +SSL3_MT_SERVER_HELLO = 2 +SSL3_MT_CERTIFICATE = 11 +SSL3_MT_SERVER_KEY_EXCHANGE = 12 +SSL3_MT_CERTIFICATE_REQUEST = 13 +SSL3_MT_SERVER_DONE = 14 +SSL3_MT_CERTIFICATE_VERIFY = 15 +SSL3_MT_CLIENT_KEY_EXCHANGE = 16 +SSL3_MT_FINISHED = 20 + +# Cipher Suit Text Strings +ciphersuit_text = { + 0x0000: 'TLS_NULL_WITH_NULL_NULL', + 0x0001: 'TLS_RSA_WITH_NULL_MD5', + 0x0002: 'TLS_RSA_WITH_NULL_SHA', + 0x0003: 'TLS_RSA_EXPORT_WITH_RC4_40_MD5', + 0x0004: 'TLS_RSA_WITH_RC4_128_MD5', + 0x0005: 'TLS_RSA_WITH_RC4_128_SHA', + 0x0006: 'TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5', + 0x0007: 'TLS_RSA_WITH_IDEA_CBC_SHA', + 0x0008: 'TLS_RSA_EXPORT_WITH_DES40_CBC_SHA', + 0x0009: 'TLS_RSA_WITH_DES_CBC_SHA', + 0x000A: 'TLS_RSA_WITH_3DES_EDE_CBC_SHA', + 0x000B: 'TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA', + 0x000C: 'TLS_DH_DSS_WITH_DES_CBC_SHA', + 0x000D: 'TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA', + 0x000E: 'TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA', + 0x000F: 'TLS_DH_RSA_WITH_DES_CBC_SHA', + 0x0010: 'TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA', + 0x0011: 'TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA', + 0x0012: 'TLS_DHE_DSS_WITH_DES_CBC_SHA', + 0x0013: 'TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA', + 0x0014: 'TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA', + 0x0015: 'TLS_DHE_RSA_WITH_DES_CBC_SHA', + 0x0016: 'TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA', + 0x0017: 'TLS_DH_anon_EXPORT_WITH_RC4_40_MD5', + 0x0018: 'TLS_DH_anon_WITH_RC4_128_MD5', + 0x0019: 'TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA', + 0x001A: 'TLS_DH_anon_WITH_DES_CBC_SHA', + 0x001B: 'TLS_DH_anon_WITH_3DES_EDE_CBC_SHA', + 0x001E: 'TLS_KRB5_WITH_DES_CBC_SHA', + 0x001F: 'TLS_KRB5_WITH_3DES_EDE_CBC_SHA', + 0x0020: 'TLS_KRB5_WITH_RC4_128_SHA', + 0x0021: 'TLS_KRB5_WITH_IDEA_CBC_SHA', + 0x0022: 'TLS_KRB5_WITH_DES_CBC_MD5', + 0x0023: 'TLS_KRB5_WITH_3DES_EDE_CBC_MD5', + 0x0024: 'TLS_KRB5_WITH_RC4_128_MD5', + 0x0025: 'TLS_KRB5_WITH_IDEA_CBC_MD5', + 0x0026: 'TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA', + 0x0027: 'TLS_KRB5_EXPORT_WITH_RC2_CBC_40_SHA', + 0x0028: 'TLS_KRB5_EXPORT_WITH_RC4_40_SHA', + 0x0029: 'TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5', + 0x002A: 'TLS_KRB5_EXPORT_WITH_RC2_CBC_40_MD5', + 0x002B: 'TLS_KRB5_EXPORT_WITH_RC4_40_MD5', + 0x002C: 'TLS_PSK_WITH_NULL_SHA', + 0x002D: 'TLS_DHE_PSK_WITH_NULL_SHA', + 0x002E: 'TLS_RSA_PSK_WITH_NULL_SHA', + 0x002F: 'TLS_RSA_WITH_AES_128_CBC_SHA', + 0x0030: 'TLS_DH_DSS_WITH_AES_128_CBC_SHA', + 0x0031: 'TLS_DH_RSA_WITH_AES_128_CBC_SHA', + 0x0032: 'TLS_DHE_DSS_WITH_AES_128_CBC_SHA', + 0x0033: 'TLS_DHE_RSA_WITH_AES_128_CBC_SHA', + 0x0034: 'TLS_DH_anon_WITH_AES_128_CBC_SHA', + 0x0035: 'TLS_RSA_WITH_AES_256_CBC_SHA', + 0x0036: 'TLS_DH_DSS_WITH_AES_256_CBC_SHA', + 0x0037: 'TLS_DH_RSA_WITH_AES_256_CBC_SHA', + 0x0038: 'TLS_DHE_DSS_WITH_AES_256_CBC_SHA', + 0x0039: 'TLS_DHE_RSA_WITH_AES_256_CBC_SHA', + 0x003A: 'TLS_DH_anon_WITH_AES_256_CBC_SHA', + 0x003B: 'TLS_RSA_WITH_NULL_SHA256', + 0x003C: 'TLS_RSA_WITH_AES_128_CBC_SHA256', + 0x003D: 'TLS_RSA_WITH_AES_256_CBC_SHA256', + 0x003E: 'TLS_DH_DSS_WITH_AES_128_CBC_SHA256', + 0x003F: 'TLS_DH_RSA_WITH_AES_128_CBC_SHA256', + 0x0040: 'TLS_DHE_DSS_WITH_AES_128_CBC_SHA256', + 0x0041: 'TLS_RSA_WITH_CAMELLIA_128_CBC_SHA', + 0x0042: 'TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA', + 0x0043: 'TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA', + 0x0044: 'TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA', + 0x0045: 'TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA', + 0x0046: 'TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA', + 0x0067: 'TLS_DHE_RSA_WITH_AES_128_CBC_SHA256', + 0x0068: 'TLS_DH_DSS_WITH_AES_256_CBC_SHA256', + 0x0069: 'TLS_DH_RSA_WITH_AES_256_CBC_SHA256', + 0x006A: 'TLS_DHE_DSS_WITH_AES_256_CBC_SHA256', + 0x006B: 'TLS_DHE_RSA_WITH_AES_256_CBC_SHA256', + 0x006C: 'TLS_DH_anon_WITH_AES_128_CBC_SHA256', + 0x006D: 'TLS_DH_anon_WITH_AES_256_CBC_SHA256', + 0x0084: 'TLS_RSA_WITH_CAMELLIA_256_CBC_SHA', + 0x0085: 'TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA', + 0x0086: 'TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA', + 0x0087: 'TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA', + 0x0088: 'TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA', + 0x0089: 'TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA', + 0x008A: 'TLS_PSK_WITH_RC4_128_SHA', + 0x008B: 'TLS_PSK_WITH_3DES_EDE_CBC_SHA', + 0x008C: 'TLS_PSK_WITH_AES_128_CBC_SHA', + 0x008D: 'TLS_PSK_WITH_AES_256_CBC_SHA', + 0x008E: 'TLS_DHE_PSK_WITH_RC4_128_SHA', + 0x008F: 'TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA', + 0x0090: 'TLS_DHE_PSK_WITH_AES_128_CBC_SHA', + 0x0091: 'TLS_DHE_PSK_WITH_AES_256_CBC_SHA', + 0x0092: 'TLS_RSA_PSK_WITH_RC4_128_SHA', + 0x0093: 'TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA', + 0x0094: 'TLS_RSA_PSK_WITH_AES_128_CBC_SHA', + 0x0095: 'TLS_RSA_PSK_WITH_AES_256_CBC_SHA', + 0x0096: 'TLS_RSA_WITH_SEED_CBC_SHA', + 0x0097: 'TLS_DH_DSS_WITH_SEED_CBC_SHA', + 0x0098: 'TLS_DH_RSA_WITH_SEED_CBC_SHA', + 0x0099: 'TLS_DHE_DSS_WITH_SEED_CBC_SHA', + 0x009A: 'TLS_DHE_RSA_WITH_SEED_CBC_SHA', + 0x009B: 'TLS_DH_anon_WITH_SEED_CBC_SHA', + 0x009C: 'TLS_RSA_WITH_AES_128_GCM_SHA256', + 0x009D: 'TLS_RSA_WITH_AES_256_GCM_SHA384', + 0x009E: 'TLS_DHE_RSA_WITH_AES_128_GCM_SHA256', + 0x009F: 'TLS_DHE_RSA_WITH_AES_256_GCM_SHA384', + 0x00A0: 'TLS_DH_RSA_WITH_AES_128_GCM_SHA256', + 0x00A1: 'TLS_DH_RSA_WITH_AES_256_GCM_SHA384', + 0x00A2: 'TLS_DHE_DSS_WITH_AES_128_GCM_SHA256', + 0x00A3: 'TLS_DHE_DSS_WITH_AES_256_GCM_SHA384', + 0x00A4: 'TLS_DH_DSS_WITH_AES_128_GCM_SHA256', + 0x00A5: 'TLS_DH_DSS_WITH_AES_256_GCM_SHA384', + 0x00A6: 'TLS_DH_anon_WITH_AES_128_GCM_SHA256', + 0x00A7: 'TLS_DH_anon_WITH_AES_256_GCM_SHA384', + 0x00A8: 'TLS_PSK_WITH_AES_128_GCM_SHA256', + 0x00A9: 'TLS_PSK_WITH_AES_256_GCM_SHA384', + 0x00AA: 'TLS_DHE_PSK_WITH_AES_128_GCM_SHA256', + 0x00AB: 'TLS_DHE_PSK_WITH_AES_256_GCM_SHA384', + 0x00AC: 'TLS_RSA_PSK_WITH_AES_128_GCM_SHA256', + 0x00AD: 'TLS_RSA_PSK_WITH_AES_256_GCM_SHA384', + 0x00AE: 'TLS_PSK_WITH_AES_128_CBC_SHA256', + 0x00AF: 'TLS_PSK_WITH_AES_256_CBC_SHA384', + 0x00B0: 'TLS_PSK_WITH_NULL_SHA256', + 0x00B1: 'TLS_PSK_WITH_NULL_SHA384', + 0x00B2: 'TLS_DHE_PSK_WITH_AES_128_CBC_SHA256', + 0x00B3: 'TLS_DHE_PSK_WITH_AES_256_CBC_SHA384', + 0x00B4: 'TLS_DHE_PSK_WITH_NULL_SHA256', + 0x00B5: 'TLS_DHE_PSK_WITH_NULL_SHA384', + 0x00B6: 'TLS_RSA_PSK_WITH_AES_128_CBC_SHA256', + 0x00B7: 'TLS_RSA_PSK_WITH_AES_256_CBC_SHA384', + 0x00B8: 'TLS_RSA_PSK_WITH_NULL_SHA256', + 0x00B9: 'TLS_RSA_PSK_WITH_NULL_SHA384', + 0x00BA: 'TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256', + 0x00BB: 'TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256', + 0x00BC: 'TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256', + 0x00BD: 'TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256', + 0x00BE: 'TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256', + 0x00BF: 'TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA256', + 0x00C0: 'TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256', + 0x00C1: 'TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256', + 0x00C2: 'TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256', + 0x00C3: 'TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256', + 0x00C4: 'TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256', + 0x00C5: 'TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA256', + 0x00FF: 'TLS_EMPTY_RENEGOTIATION_INFO_SCSV', + 0xC001: 'TLS_ECDH_ECDSA_WITH_NULL_SHA', + 0xC002: 'TLS_ECDH_ECDSA_WITH_RC4_128_SHA', + 0xC003: 'TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA', + 0xC004: 'TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA', + 0xC005: 'TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA', + 0xC006: 'TLS_ECDHE_ECDSA_WITH_NULL_SHA', + 0xC007: 'TLS_ECDHE_ECDSA_WITH_RC4_128_SHA', + 0xC008: 'TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA', + 0xC009: 'TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA', + 0xC00A: 'TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA', + 0xC00B: 'TLS_ECDH_RSA_WITH_NULL_SHA', + 0xC00C: 'TLS_ECDH_RSA_WITH_RC4_128_SHA', + 0xC00D: 'TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA', + 0xC00E: 'TLS_ECDH_RSA_WITH_AES_128_CBC_SHA', + 0xC00F: 'TLS_ECDH_RSA_WITH_AES_256_CBC_SHA', + 0xC010: 'TLS_ECDHE_RSA_WITH_NULL_SHA', + 0xC011: 'TLS_ECDHE_RSA_WITH_RC4_128_SHA', + 0xC012: 'TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA', + 0xC013: 'TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA', + 0xC014: 'TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA', + 0xC015: 'TLS_ECDH_anon_WITH_NULL_SHA', + 0xC016: 'TLS_ECDH_anon_WITH_RC4_128_SHA', + 0xC017: 'TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA', + 0xC018: 'TLS_ECDH_anon_WITH_AES_128_CBC_SHA', + 0xC019: 'TLS_ECDH_anon_WITH_AES_256_CBC_SHA', + 0xC01A: 'TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA', + 0xC01B: 'TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA', + 0xC01C: 'TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA', + 0xC01D: 'TLS_SRP_SHA_WITH_AES_128_CBC_SHA', + 0xC01E: 'TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA', + 0xC01F: 'TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA', + 0xC020: 'TLS_SRP_SHA_WITH_AES_256_CBC_SHA', + 0xC021: 'TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA', + 0xC022: 'TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA', + 0xC023: 'TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256', + 0xC024: 'TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384', + 0xC025: 'TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256', + 0xC026: 'TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384', + 0xC027: 'TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256', + 0xC028: 'TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384', + 0xC029: 'TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256', + 0xC02A: 'TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384', + 0xC02B: 'TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256', + 0xC02C: 'TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384', + 0xC02D: 'TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256', + 0xC02E: 'TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384', + 0xC02F: 'TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256', + 0xC030: 'TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384', + 0xC031: 'TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256', + 0xC032: 'TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384', + 0xC033: 'TLS_ECDHE_PSK_WITH_RC4_128_SHA', + 0xC034: 'TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA', + 0xC035: 'TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA', + 0xC036: 'TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA', + 0xC037: 'TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256', + 0xC038: 'TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384', + 0xC039: 'TLS_ECDHE_PSK_WITH_NULL_SHA', + 0xC03A: 'TLS_ECDHE_PSK_WITH_NULL_SHA256', + 0xC03B: 'TLS_ECDHE_PSK_WITH_NULL_SHA384', + 0xC03C: 'TLS_RSA_WITH_ARIA_128_CBC_SHA256', + 0xC03D: 'TLS_RSA_WITH_ARIA_256_CBC_SHA384', + 0xC03E: 'TLS_DH_DSS_WITH_ARIA_128_CBC_SHA256', + 0xC03F: 'TLS_DH_DSS_WITH_ARIA_256_CBC_SHA384', + 0xC040: 'TLS_DH_RSA_WITH_ARIA_128_CBC_SHA256', + 0xC041: 'TLS_DH_RSA_WITH_ARIA_256_CBC_SHA384', + 0xC042: 'TLS_DHE_DSS_WITH_ARIA_128_CBC_SHA256', + 0xC043: 'TLS_DHE_DSS_WITH_ARIA_256_CBC_SHA384', + 0xC044: 'TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256', + 0xC045: 'TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384', + 0xC046: 'TLS_DH_anon_WITH_ARIA_128_CBC_SHA256', + 0xC047: 'TLS_DH_anon_WITH_ARIA_256_CBC_SHA384', + 0xC048: 'TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256', + 0xC049: 'TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384', + 0xC04A: 'TLS_ECDH_ECDSA_WITH_ARIA_128_CBC_SHA256', + 0xC04B: 'TLS_ECDH_ECDSA_WITH_ARIA_256_CBC_SHA384', + 0xC04C: 'TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256', + 0xC04D: 'TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384', + 0xC04E: 'TLS_ECDH_RSA_WITH_ARIA_128_CBC_SHA256', + 0xC04F: 'TLS_ECDH_RSA_WITH_ARIA_256_CBC_SHA384', + 0xC050: 'TLS_RSA_WITH_ARIA_128_GCM_SHA256', + 0xC051: 'TLS_RSA_WITH_ARIA_256_GCM_SHA384', + 0xC052: 'TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256', + 0xC053: 'TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384', + 0xC054: 'TLS_DH_RSA_WITH_ARIA_128_GCM_SHA256', + 0xC055: 'TLS_DH_RSA_WITH_ARIA_256_GCM_SHA384', + 0xC056: 'TLS_DHE_DSS_WITH_ARIA_128_GCM_SHA256', + 0xC057: 'TLS_DHE_DSS_WITH_ARIA_256_GCM_SHA384', + 0xC058: 'TLS_DH_DSS_WITH_ARIA_128_GCM_SHA256', + 0xC059: 'TLS_DH_DSS_WITH_ARIA_256_GCM_SHA384', + 0xC05A: 'TLS_DH_anon_WITH_ARIA_128_GCM_SHA256', + 0xC05B: 'TLS_DH_anon_WITH_ARIA_256_GCM_SHA384', + 0xC05C: 'TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256', + 0xC05D: 'TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384', + 0xC05E: 'TLS_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256', + 0xC05F: 'TLS_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384', + 0xC060: 'TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256', + 0xC061: 'TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384', + 0xC062: 'TLS_ECDH_RSA_WITH_ARIA_128_GCM_SHA256', + 0xC063: 'TLS_ECDH_RSA_WITH_ARIA_256_GCM_SHA384', + 0xC064: 'TLS_PSK_WITH_ARIA_128_CBC_SHA256', + 0xC065: 'TLS_PSK_WITH_ARIA_256_CBC_SHA384', + 0xC066: 'TLS_DHE_PSK_WITH_ARIA_128_CBC_SHA256', + 0xC067: 'TLS_DHE_PSK_WITH_ARIA_256_CBC_SHA384', + 0xC068: 'TLS_RSA_PSK_WITH_ARIA_128_CBC_SHA256', + 0xC069: 'TLS_RSA_PSK_WITH_ARIA_256_CBC_SHA384', + 0xC06A: 'TLS_PSK_WITH_ARIA_128_GCM_SHA256', + 0xC06B: 'TLS_PSK_WITH_ARIA_256_GCM_SHA384', + 0xC06C: 'TLS_DHE_PSK_WITH_ARIA_128_GCM_SHA256', + 0xC06D: 'TLS_DHE_PSK_WITH_ARIA_256_GCM_SHA384', + 0xC06E: 'TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256', + 0xC06F: 'TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384', + 0xC070: 'TLS_ECDHE_PSK_WITH_ARIA_128_CBC_SHA256', + 0xC071: 'TLS_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384', + 0xC072: 'TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256', + 0xC073: 'TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384', + 0xC074: 'TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256', + 0xC075: 'TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384', + 0xC076: 'TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256', + 0xC077: 'TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384', + 0xC078: 'TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256', + 0xC079: 'TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384', + 0xC07A: 'TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256', + 0xC07B: 'TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384', + 0xC07C: 'TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256', + 0xC07D: 'TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384', + 0xC07E: 'TLS_DH_RSA_WITH_CAMELLIA_128_GCM_SHA256', + 0xC07F: 'TLS_DH_RSA_WITH_CAMELLIA_256_GCM_SHA384', + 0xC080: 'TLS_DHE_DSS_WITH_CAMELLIA_128_GCM_SHA256', + 0xC081: 'TLS_DHE_DSS_WITH_CAMELLIA_256_GCM_SHA384', + 0xC082: 'TLS_DH_DSS_WITH_CAMELLIA_128_GCM_SHA256', + 0xC083: 'TLS_DH_DSS_WITH_CAMELLIA_256_GCM_SHA384', + 0xC084: 'TLS_DH_anon_WITH_CAMELLIA_128_GCM_SHA256', + 0xC085: 'TLS_DH_anon_WITH_CAMELLIA_256_GCM_SHA384', + 0xC086: 'TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256', + 0xC087: 'TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384', + 0xC088: 'TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256', + 0xC089: 'TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384', + 0xC08A: 'TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256', + 0xC08B: 'TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384', + 0xC08C: 'TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256', + 0xC08D: 'TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384', + 0xC08E: 'TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256', + 0xC08F: 'TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384', + 0xC090: 'TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256', + 0xC091: 'TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384', + 0xC092: 'TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256', + 0xC093: 'TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384', + 0xC094: 'TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256', + 0xC095: 'TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384', + 0xC096: 'TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256', + 0xC097: 'TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384', + 0xC098: 'TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256', + 0xC099: 'TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384', + 0xC09A: 'TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256', + 0xC09B: 'TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384', + 0xC09C: 'TLS_RSA_WITH_AES_128_CCM', + 0xC09D: 'TLS_RSA_WITH_AES_256_CCM', + 0xC09E: 'TLS_DHE_RSA_WITH_AES_128_CCM', + 0xC09F: 'TLS_DHE_RSA_WITH_AES_256_CCM', + 0xC0A0: 'TLS_RSA_WITH_AES_128_CCM_8', + 0xC0A1: 'TLS_RSA_WITH_AES_256_CCM_8', + 0xC0A2: 'TLS_DHE_RSA_WITH_AES_128_CCM_8', + 0xC0A3: 'TLS_DHE_RSA_WITH_AES_256_CCM_8', + 0xC0A4: 'TLS_PSK_WITH_AES_128_CCM', + 0xC0A5: 'TLS_PSK_WITH_AES_256_CCM', + 0xC0A6: 'TLS_DHE_PSK_WITH_AES_128_CCM', + 0xC0A7: 'TLS_DHE_PSK_WITH_AES_256_CCM', + 0xC0A8: 'TLS_PSK_WITH_AES_128_CCM_8', + 0xC0A9: 'TLS_PSK_WITH_AES_256_CCM_8', + 0xC0AA: 'TLS_PSK_DHE_WITH_AES_128_CCM_8', + 0xC0AB: 'TLS_PSK_DHE_WITH_AES_256_CCM_8', +} + +keytypes = { + OpenSSL.crypto.TYPE_RSA: 'RSA', + OpenSSL.crypto.TYPE_DSA: 'DSA', +} + + +##################################################################### +# TLS - TLS message object, initialized from TCP segment +# +# Status: Currently only supports TLS 1.0 Handshake messages +# +##################################################################### +class TLS(object): + + def __init__(self, data): + + data_length = len(data) + offset = 0 + + ######################### + # Unpack TLSPlaintext # + ######################### + if data_length >= offset+5: + (self.ContentType, self.ProtocolVersion, self.TLSRecordLength) = struct.unpack( + '!BHH', data[offset:offset+5]) + offset += 5 + else: + raise InsufficientData('%d bytes received by TLS' % data_length) + + # + # For now, only interested in TLS 1.0. + # Reason: SSL2.0 records do not support the server_name extension, which is the primary + # motivation for creating this library. Needs to be updated/extended eventually. + # + if self.ProtocolVersion != TLS1_VERSION and self.ProtocolVersion != SSL3_VERSION and self.ProtocolVersion != TLS1_2_VERSION: + raise UnsupportedOption( + 'Protocol version 0x%x not supported' % self.ProtocolVersion) + + ################# + # Check Size # + ################# + self.recordbytes = self.TLSRecordLength + 5 + if data_length < self.recordbytes: + raise InsufficientData('%d bytes received by TLS' % data_length) + + ######################################################################### + # Content Types - Only Handshake supported for now + ######################################################################### + self.Handshakes = [] + if self.ContentType == SSL3_RT_HANDSHAKE: + + ############################### + # Loop Through Handshakes # + ############################### + while self.recordbytes >= offset + 4: # Need minimum four bytes for the rest to contain another Handshake + + HandshakeType = data[offset] + offset += 1 + + # + # Handshake Record length + # + HandshakeLength = struct.unpack( + '!I', b'\x00' + data[offset:offset+3])[0] + offset += 3 + + # + # Parse Handshake SubType + # + if HandshakeType == SSL3_MT_CLIENT_HELLO: + try: + self.Handshakes.append(TLSClientHello( + HandshakeType, HandshakeLength, data[offset:offset+HandshakeLength])) + except: + raise + elif HandshakeType == SSL3_MT_SERVER_HELLO: + try: + self.Handshakes.append(TLSServerHello( + HandshakeType, HandshakeLength, data[offset:offset+HandshakeLength])) + except: + raise + elif HandshakeType == SSL3_MT_CERTIFICATE: + try: + self.Handshakes.append(TLSCertificate( + HandshakeType, HandshakeLength, data[offset:offset+HandshakeLength])) + except: + raise + + offset += HandshakeLength + ############################### + # End Handshakes Loop # + ############################### + + +##################################################################### +# TLSHandshake +##################################################################### +class TLSHandshake(object): + + def __init__(self, HandshakeType, HandshakeLength): + self.HandshakeType = HandshakeType + self.HandshakeLength = HandshakeLength + +##################################################################### +# TLSCertificate - Certificate Handshake type +##################################################################### + + +class TLSCertificate(TLSHandshake): + + def __init__(self, HandshakeType, HandshakeLength, data): + + TLSHandshake.__init__(self, HandshakeType, HandshakeLength) + data_length = len(data) + offset = 0 + + # length of all certificates + if data_length >= offset+3: + certificates_length = struct.unpack( + '!I', b'\x00' + data[offset:offset+3])[0] + offset += 3 + else: + raise InsufficientData( + '%d bytes received by TLSCertificate, expected %d for client_version' % (data_length, offset + 2)) + + if data_length >= offset + certificates_length: + try: + self.Certificates = self.__parse_certs( + data[offset:offset+certificates_length]) + offset += certificates_length + except: + offset += certificates_length + raise + else: + raise InsufficientData('%d bytes received by TLSCertificate, expected %d for client_version' % ( + data_length, offset + certificates_length)) + + # Returns array of x509 objects (defined below) + def __parse_certs(self, data): + + certs = [] + while data: + try: + clen, data = self.l24(data) + if len(data) < clen: + raise InsufficientData( + '%d bytes in buffer, need %d' % (len(data), clen)) + try: + cert = OpenSSL.crypto.load_certificate( + OpenSSL.crypto.FILETYPE_ASN1, data[:clen]) + except: + return certs + certs.append(cert) + data = data[clen:] + except: + raise + return certs + + def l24(self, data): + '''24-bit length decoder''' + (lh, ll), data = struct.unpack('!BH', data[0:3]), data[3:] + return lh << 16 | ll, data + + +##################################################################### +# TLSClientHello - ClientHello Handshake type +##################################################################### +class TLSClientHello(TLSHandshake): + + def __init__(self, HandshakeType, HandshakeLength, data): + TLSHandshake.__init__(self, HandshakeType, HandshakeLength) + data_length = len(data) + offset = 0 + self.ja3_data = [] + + # self.client_version + if data_length >= offset+2: + self.client_version = struct.unpack('!H', data[offset:offset+2])[0] + self.ja3_data.append(self.client_version) + offset += 2 + else: + raise InsufficientData( + '%d bytes received by TLSClientHello, expected %d for client_version' % (data_length, offset + 2)) + + # self.random + if data_length >= offset+32: + self.random = data[offset:offset+32] + offset += 32 + else: + raise InsufficientData('%d bytes received by TLSClientHello, expected %d for random block' % ( + data_length, offset + 32)) + + # self.session_id_length + if data_length >= offset+1: + self.session_id_length = struct.unpack( + '!B', data[offset:offset+1])[0] + offset += 1 + else: + raise InsufficientData( + '%d bytes received by TLSClientHello, expected %d for session_id_length' % (data_length, offset + 1)) + + # self.session_id + if self.session_id_length > 0: + if data_length >= offset+self.session_id_length: + self.session_id = data[offset:offset+self.session_id_length] + offset += self.session_id_length + else: + raise InsufficientData('%d bytes received by TLSClientHello, expected %d for session_id' % ( + data_length, offset + self.session_id_length)) + else: + self.session_id = None + + # self.cipher_suites_length + if data_length >= offset+2: + self.cipher_suites_length = struct.unpack( + '!H', data[offset:offset+2])[0] + offset += 2 + else: + raise InsufficientData( + '%d bytes received by TLSClientHello, expected %d for cipher_suites_length' % (data_length, offset + 2)) + + # self.cipher_suites (array, two bytes each) + self.cipher_suites = [] + if self.cipher_suites_length > 0: + self.ja3_data.append(ja3.ja3.convert_to_ja3_segment( + data[offset:offset+self.cipher_suites_length], 2)) + if data_length >= offset + self.cipher_suites_length: + for j in range(0, self.cipher_suites_length, 2): + self.cipher_suites.append(data[offset+j:offset+j+2]) + offset += self.cipher_suites_length + else: + raise InsufficientData('%d bytes received by TLSClientHello, expected %d for cipher_suites' % ( + data_length, offset + self.cipher_suites_length)) + + # self.compression_methods_length + if data_length >= offset+1: + self.compression_methods_length = data[offset] + offset += 1 + else: + raise InsufficientData( + '%d bytes received by TLSClientHello, expected %d for compression_methods_length' % (data_length, offset + 1)) + + # self.compression_methods (array, one bytes each) + self.compression_methods = [] + if self.compression_methods_length > 0: + if data_length >= offset + self.compression_methods_length: + for j in range(0, self.compression_methods_length): + self.compression_methods.append(data[offset+j]) + offset += self.compression_methods_length + else: + raise InsufficientData('%d bytes received by TLSClientHello, expected %d for compression_methods' % ( + data_length, offset + self.compression_methods_length)) + + ################################ + # Slice Off the Extensions + ################################ + self.ja3_data.extend(ja3.ja3.process_extensions( + ja3.ja3.dpkt.ssl.TLSClientHello(data))) + self.extensions = {} + self.raw_extensions = [] # ordered list of tuples (ex_type, ex_data) + # self.extensions_length + if data_length >= offset+2: + self.extensions_length = struct.unpack( + '!H', data[offset:offset+2])[0] + offset += 2 + else: + # No extensions + return + + # Copy Extension Blob into a new working variable + try: + extensions_data = data[offset:offset+self.extensions_length] + except: + raise InsufficientData('%d bytes received by TLSClientHello, expected %d for extensions' % ( + data_length, offset + self.extensions_length)) + + ########################### + # Iterate the Extensions + ########################### + extension_server_name_list = [] + while len(extensions_data) >= 4: + + (ex_type, length) = struct.unpack('!HH', extensions_data[:4]) + if len(extensions_data) > length+4: + this_extension_data = extensions_data[4:4+length] + extensions_data = extensions_data[4+length:] + else: + this_extension_data = extensions_data[4:] + extensions_data = '' + + self.raw_extensions.append((ex_type, this_extension_data)) + + # server_name extension + # this_extension_data is defined on page 8 of RFC 3546 + # It is essentially a list of hostnames + if ex_type == 0: + server_name_list_length = struct.unpack( + '!H', this_extension_data[:2])[0] + if server_name_list_length > len(this_extension_data) - 2: + raise Error("Malformed ServerNameList") + server_name_list = this_extension_data[2:] + # Iterate the list + while len(server_name_list) > 0: + (name_type, name_length) = struct.unpack( + '!BH', server_name_list[0:3]) + name_data = server_name_list[3:name_length + 3] + if len(server_name_list) > name_length + 3: + server_name_list = server_name_list[name_length + 3:] + else: + server_name_list = '' + if name_type == 0: + extension_server_name_list.append(name_data) + else: + raise UnsupportedOption("Unknown NameType") + # After Loop + # add extension information to dictionary + self.extensions['server_name'] = extension_server_name_list + + def ja3(self): + return ','.join([str(x) for x in self.ja3_data]) + + def ja3_digest(self): + h = hashlib.md5(self.ja3().encode('utf-8')) + return h.hexdigest() + + +##################################################################### +# TLSServerHello - ServerHello Handshake type +##################################################################### +class TLSServerHello(TLSHandshake): + + def __init__(self, HandshakeType, HandshakeLength, data): + TLSHandshake.__init__(self, HandshakeType, HandshakeLength) + data_length = len(data) + offset = 0 + + # self.server_version + if data_length >= offset+2: + self.server_version = struct.unpack('!H', data[offset:offset+2])[0] + offset += 2 + else: + raise InsufficientData( + '%d bytes received by TLSServerHello, expected %d for server_version' % (data_length, offset + 2)) + + # self.random + if data_length >= offset+32: + self.random = data[offset:offset+32] + offset += 32 + else: + raise InsufficientData('%d bytes received by TLSServerHello, expected %d for random block' % ( + data_length, offset + 32)) + + # self.session_id_length + if data_length >= offset+1: + self.session_id_length = struct.unpack( + '!B', data[offset:offset+1])[0] + offset += 1 + else: + raise InsufficientData( + '%d bytes received by TLSServerHello, expected %d for session_id_length' % (data_length, offset + 1)) + + # self.session_id + if self.session_id_length > 0: + if data_length >= offset+self.session_id_length: + self.session_id = data[offset:offset+self.session_id_length] + offset += self.session_id_length + else: + raise InsufficientData('%d bytes received by TLSServerHello, expected %d for session_id' % ( + data_length, offset + self.session_id_length)) + else: + self.session_id = None + + # self.cipher_suite (single value, two bytes) + if data_length >= offset + 2: + self.cipher_suite = data[offset:offset+2] + offset += 2 + else: + self.cipher_suite = None + raise InsufficientData( + '%d bytes received by TLSServerHello, expected %d for cipher_suite' % (data_length, offset + 2)) + + # self.compression_method (single value, one byte) + if data_length >= offset + 1: + self.compression_method = data[offset] + offset += 1 + else: + raise InsufficientData( + '%d bytes received by TLSServerHello, expected %d for compression_method' % (data_length, offset + 1)) + + +############################################################################## +# Some Utility Functions +############################################################################## +def keyTypeToString(kt): + global keytypes + if kt in keytypes: + return keytypes[kt] + else: + try: + return "UNKNOWN(%s)" % str(kt) + except: + return "UNKNOWN(%s)" % repr(kt) + + +def parse_x509_dtm(dtm): + if type(dtm) == bytes: + dtm = dtm.decode('utf-8') + # Fmt: YYYYMMDDhhmmssZ + t = time.strptime(dtm, '%Y%m%d%H%M%SZ') + return time.strftime('%Y-%m-%d %H:%M:%S', t) + + +def render_x509_object(n): + output = b'' + for component in n.get_components(): + output += b"%s=%s " % component + return output.rstrip().decode('utf-8') + + +def openSSL_cert_to_info_dictionary(c): + d = {'fingerprints': {}} + for h in ('md5', 'sha1', 'sha256'): + d['fingerprints'][h] = c.digest(h).decode('utf-8') + + d['subject'] = render_x509_object(c.get_subject()) + d['subject_cn'] = c.get_subject().CN + d['issuer'] = render_x509_object(c.get_issuer()) + d['notAfter'] = parse_x509_dtm(c.get_notAfter()) + d['notBefore'] = parse_x509_dtm(c.get_notBefore()) + # + # Look for subjectAltName + # + for i in range(0, c.get_extension_count()): + ext = c.get_extension(i) + if ext.get_short_name() == b'subjectAltName': + d['subjectAltName'] = str(ext) + public_key = c.get_pubkey() + d['pubkey_bits'] = public_key.bits() + d['pubkey_type'] = keyTypeToString(public_key.type()) + d['pubkey_sha1'] = hashlib.sha1(OpenSSL.crypto.dump_publickey( + OpenSSL.crypto.FILETYPE_ASN1, public_key)).hexdigest() + return d + + +def split_subjectAltName_string(subjectAltName): + l = [] + for an in subjectAltName.split(', '): + if an.startswith('DNS:'): + an = an[4:] + l.append(an) + return l + + +class DshellPlugin(dshell.core.ConnectionPlugin): + + def __init__(self): + super().__init__( + name="tls", + author="amm", + description="Extract interesting metadata from TLS connection setup", + bpf="tcp and (port 443 or port 993 or port 25 or port 587 or port 465 or port 5269 or port 995 or port 3389)", + output=AlertOutput(label=__name__) + ) + + def connection_handler(self, conn): + + inverted_ssl = False + info = conn.info() + client_names = set() # Agregate list of names specified by client + server_names = set() # Agregate list of names specified by server + certs_cs = [] + certs_sc = [] + server_cipher = None + client_cipher_list = [] + + for blob in conn.blobs: + + blob.reassemble(allow_overlap=True, allow_padding=True) + data = blob.data + offset = 0 + + while offset < len(data): + + tlsrecord = None + try: + tlsrecord = TLS(data[offset:]) + offset += tlsrecord.recordbytes + + if tlsrecord.ContentType == SSL3_RT_HANDSHAKE: + for hs in tlsrecord.Handshakes: + # + # Client hello. Looking for inversion. + # + if hs.HandshakeType == SSL3_MT_CLIENT_HELLO: + if blob.direction != 'cs': + inverted_ssl = True + if 'server_name' in hs.extensions: + for server in hs.extensions['server_name']: + client_names.add( + server.decode('utf-8')) + info['ja3'] = hs.ja3() + info['ja3_digest'] = hs.ja3_digest() + client_cipher_list = hs.cipher_suites + + elif hs.HandshakeType == SSL3_MT_SERVER_HELLO: + server_cipher = hs.cipher_suite + + # + # Certificate. Looking for first server cert. + # + elif hs.HandshakeType == SSL3_MT_CERTIFICATE: + for cert in hs.Certificates: + cert_info = openSSL_cert_to_info_dictionary( + cert) + if blob.direction == 'cs': + certs_cs.append(cert_info) + else: + certs_sc.append(cert_info) + + except InsufficientData: + self.log('Skipping small blob: %s\n' % (sys.exc_info()[1])) + offset += len(data) + except UnsupportedOption: + self.log('Unsupported type: %s\n' % (sys.exc_info()[1])) + offset += len(data) + except: + offset += len(data) + self.log('Unknown error in connectionHandler: %s' % + sys.exc_info()[1]) + break + + # Post processing + if inverted_ssl: + info['inverted_ssl'] = True + info['client_certs'] = certs_sc + info['server_certs'] = certs_cs + else: + info['client_certs'] = certs_cs + info['server_certs'] = certs_sc + if len(info['client_certs']): + client_names.add(info['client_certs'][0]['subject_cn']) + if len(info['server_certs']): + server_names.add(info['server_certs'][0]['subject_cn']) + try: + server_names.update(split_subjectAltName_string( + info['server_certs'][0]['subjectAltName'])) + except KeyError: + pass + info['client_names'] = list(client_names) + info['server_names'] = list(server_names) + # Cipher Lists + if server_cipher in client_cipher_list: + cipher_index = client_cipher_list.index(server_cipher) + else: + cipher_index = None + info['cipher_index'] = cipher_index + try: + info['cipher_text'] = ciphersuit_text[struct.unpack('!H', server_cipher)[ + 0]] + except: + info['cipher_text'] = 'UNKNOWN' + + # + # Determine output message + # + if len(client_names) + len(server_names) == 0: + return conn + client_name = ','.join(info['client_names']) + server_name = ','.join(info['server_names']) + if len(client_name) and client_name != server_name: + msg = "%s / %s" % (client_name, server_name) + else: + msg = server_name + self.write(msg, **info) + return conn + + +if __name__ == "__main__": + print(DshellPlugin()) From b2e1e6b5c1bb52f6f0bce0d93362d36aa2909d1f Mon Sep 17 00:00:00 2001 From: adam Date: Fri, 16 Oct 2020 20:27:04 +0000 Subject: [PATCH 104/166] Gracefully continue if missing JA3 module --- dshell/plugins/ssl/tls.py | 41 ++++++++++++++++++++++++++++----------- 1 file changed, 30 insertions(+), 11 deletions(-) diff --git a/dshell/plugins/ssl/tls.py b/dshell/plugins/ssl/tls.py index 7302ad9..4c5ee3f 100644 --- a/dshell/plugins/ssl/tls.py +++ b/dshell/plugins/ssl/tls.py @@ -10,7 +10,12 @@ import hashlib import OpenSSL import time -import ja3.ja3 +try: + import ja3.ja3 + ja3_available = True +except ModuleNotFoundError: + ja3_available = False + ################################################################################################## # @@ -563,7 +568,8 @@ def __init__(self, HandshakeType, HandshakeLength, data): # self.client_version if data_length >= offset+2: self.client_version = struct.unpack('!H', data[offset:offset+2])[0] - self.ja3_data.append(self.client_version) + if ja3_available: + self.ja3_data.append(self.client_version) offset += 2 else: raise InsufficientData( @@ -609,8 +615,9 @@ def __init__(self, HandshakeType, HandshakeLength, data): # self.cipher_suites (array, two bytes each) self.cipher_suites = [] if self.cipher_suites_length > 0: - self.ja3_data.append(ja3.ja3.convert_to_ja3_segment( - data[offset:offset+self.cipher_suites_length], 2)) + if ja3_available: + self.ja3_data.append(ja3.ja3.convert_to_ja3_segment( + data[offset:offset+self.cipher_suites_length], 2)) if data_length >= offset + self.cipher_suites_length: for j in range(0, self.cipher_suites_length, 2): self.cipher_suites.append(data[offset+j:offset+j+2]) @@ -641,8 +648,9 @@ def __init__(self, HandshakeType, HandshakeLength, data): ################################ # Slice Off the Extensions ################################ - self.ja3_data.extend(ja3.ja3.process_extensions( - ja3.ja3.dpkt.ssl.TLSClientHello(data))) + if ja3_available: + self.ja3_data.extend(ja3.ja3.process_extensions( + ja3.ja3.dpkt.ssl.TLSClientHello(data))) self.extensions = {} self.raw_extensions = [] # ordered list of tuples (ex_type, ex_data) # self.extensions_length @@ -704,11 +712,17 @@ def __init__(self, HandshakeType, HandshakeLength, data): self.extensions['server_name'] = extension_server_name_list def ja3(self): - return ','.join([str(x) for x in self.ja3_data]) + if ja3_available: + return ','.join([str(x) for x in self.ja3_data]) + else: + return None def ja3_digest(self): - h = hashlib.md5(self.ja3().encode('utf-8')) - return h.hexdigest() + if ja3_available: + h = hashlib.md5(self.ja3().encode('utf-8')) + return h.hexdigest() + else: + return None ##################################################################### @@ -849,6 +863,10 @@ def __init__(self): output=AlertOutput(label=__name__) ) + def premodule(self): + if not ja3_available: + self.debug("ja3 capability disabled due to missing python module") + def connection_handler(self, conn): inverted_ssl = False @@ -885,8 +903,9 @@ def connection_handler(self, conn): for server in hs.extensions['server_name']: client_names.add( server.decode('utf-8')) - info['ja3'] = hs.ja3() - info['ja3_digest'] = hs.ja3_digest() + if ja3_available: + info['ja3'] = hs.ja3() + info['ja3_digest'] = hs.ja3_digest() client_cipher_list = hs.cipher_suites elif hs.HandshakeType == SSL3_MT_SERVER_HELLO: From 3364dceb329aa19592d3e242fa0871019b855d00 Mon Sep 17 00:00:00 2001 From: adam Date: Fri, 16 Oct 2020 20:32:13 +0000 Subject: [PATCH 105/166] Add longdescription with comment about pyja3 module --- dshell/plugins/ssl/tls.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/dshell/plugins/ssl/tls.py b/dshell/plugins/ssl/tls.py index 4c5ee3f..a1ff2d2 100644 --- a/dshell/plugins/ssl/tls.py +++ b/dshell/plugins/ssl/tls.py @@ -860,7 +860,12 @@ def __init__(self): author="amm", description="Extract interesting metadata from TLS connection setup", bpf="tcp and (port 443 or port 993 or port 25 or port 587 or port 465 or port 5269 or port 995 or port 3389)", - output=AlertOutput(label=__name__) + output=AlertOutput(label=__name__), + longdescription=""" +Extract interesting metadata from TLS connection setup, including the ClientHello and Certificate handshake structures. + +For JA3 support (ClientHello hash), install module pyja3 + """ ) def premodule(self): From f7f74e8ba5efc393469f0f6af2e8fa910960bb09 Mon Sep 17 00:00:00 2001 From: dek <41297634+dek443@users.noreply.github.com> Date: Mon, 19 Oct 2020 12:17:51 -0400 Subject: [PATCH 106/166] Update setup.py Added pyOpenSSL as a 3rd-party library requirement. --- setup.py | 1 + 1 file changed, 1 insertion(+) diff --git a/setup.py b/setup.py index efbc739..9ce3a3a 100644 --- a/setup.py +++ b/setup.py @@ -22,6 +22,7 @@ "geoip2", "pcapy", "pypacker", + "pyopenssl", ], entry_points={ "console_scripts": [ From a4f29e334b4a2e6d16fa52b0fed0c29becdcdaa9 Mon Sep 17 00:00:00 2001 From: dek <41297634+dek443@users.noreply.github.com> Date: Mon, 19 Oct 2020 12:35:46 -0400 Subject: [PATCH 107/166] Update README.md Added pyOpenSSL as a 3rd-party library requirement, pyJA3 as an optional 3rd-party library for use with the new tls plugin, and updated the link to the pcapy 3rd-party library. --- README.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index f6594d0..11d8e04 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,8 @@ Key features: * Linux (developed on Red Hat Enterprise Linux 6.7) * Python 3 (developed with Python 3.5.1) * [pypacker](https://gitlab.com/mike01/pypacker) -* [pcapy](http://www.coresecurity.com/corelabs-research/open-source-tools/pcapy) +* [pcapy](https://github.com/helpsystems/pcapy) +* [pyOpenSSL](https://github.com/pyca/pyopenssl) * [geoip2](https://github.com/maxmind/GeoIP2-python) * [MaxMind GeoIP2 datasets](https://dev.maxmind.com/geoip/geoip2/geolite2/) @@ -23,6 +24,8 @@ Key features: * [elasticsearch](https://www.elastic.co/guide/en/elasticsearch/client/python-api/current/index.html) * used in the elasticout output module * only necessary if planning to use elasticsearch to store output +* [pyJA3](https://github.com/salesforce/ja3/tree/master/python) + * used in the tls plugin ## Major Changes Since Previous Release * This is a major framework update to Dshell. Plugins written for the previous version are not compatible with this version, and vice versa. From bc77a84b474faa14977a42fa0befec7be4f22c28 Mon Sep 17 00:00:00 2001 From: dek <41297634+dek443@users.noreply.github.com> Date: Mon, 19 Oct 2020 13:23:32 -0400 Subject: [PATCH 108/166] Update README Added pyOpenSSL as a 3rd-party library requirement, pyJA3 as an optional 3rd-party library for use with the new tls plugin, and updated the link to the pcapy 3rd-party library. --- README | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/README b/README index f6594d0..11d8e04 100644 --- a/README +++ b/README @@ -12,7 +12,8 @@ Key features: * Linux (developed on Red Hat Enterprise Linux 6.7) * Python 3 (developed with Python 3.5.1) * [pypacker](https://gitlab.com/mike01/pypacker) -* [pcapy](http://www.coresecurity.com/corelabs-research/open-source-tools/pcapy) +* [pcapy](https://github.com/helpsystems/pcapy) +* [pyOpenSSL](https://github.com/pyca/pyopenssl) * [geoip2](https://github.com/maxmind/GeoIP2-python) * [MaxMind GeoIP2 datasets](https://dev.maxmind.com/geoip/geoip2/geolite2/) @@ -23,6 +24,8 @@ Key features: * [elasticsearch](https://www.elastic.co/guide/en/elasticsearch/client/python-api/current/index.html) * used in the elasticout output module * only necessary if planning to use elasticsearch to store output +* [pyJA3](https://github.com/salesforce/ja3/tree/master/python) + * used in the tls plugin ## Major Changes Since Previous Release * This is a major framework update to Dshell. Plugins written for the previous version are not compatible with this version, and vice versa. From 3cf3cbf939a7e1d7feff340cb12def9182bb2a82 Mon Sep 17 00:00:00 2001 From: Adam M Date: Tue, 29 Dec 2020 13:25:16 +0000 Subject: [PATCH 109/166] Allow passing of "raw" (data,direction) tuples to write() --- dshell/output/colorout.py | 2 ++ dshell/output/htmlout.py | 2 ++ 2 files changed, 4 insertions(+) diff --git a/dshell/output/colorout.py b/dshell/output/colorout.py index 04fb17d..154659a 100644 --- a/dshell/output/colorout.py +++ b/dshell/output/colorout.py @@ -64,6 +64,8 @@ def write(self, *args, **kwargs): rawdata.append((blob.data, blob.direction)) elif type(arg) == dshell.core.Packet: rawdata.append((arg.pkt.body_bytes, kwargs.get('direction', '--'))) + elif type(arg) == tuple: + rawdata.append(arg) else: rawdata.append((arg, kwargs.get('direction', '--'))) diff --git a/dshell/output/htmlout.py b/dshell/output/htmlout.py index 57ab4b3..bff3ec7 100644 --- a/dshell/output/htmlout.py +++ b/dshell/output/htmlout.py @@ -98,6 +98,8 @@ def write(self, *args, **kwargs): rawdata.append((blob.data, blob.direction)) elif type(arg) == dshell.core.Packet: rawdata.append((arg.pkt.body_bytes, kwargs.get('direction', '--'))) + elif type(arg) == tuple: + rawdata.append(arg) else: rawdata.append((arg, kwargs.get('direction', '--'))) From 0f497e4220f61b09e334a9788302c35f3b19984d Mon Sep 17 00:00:00 2001 From: Adam M Date: Tue, 29 Dec 2020 13:57:23 +0000 Subject: [PATCH 110/166] Check additional message code --- dshell/plugins/ssh/ssh-pubkey.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/dshell/plugins/ssh/ssh-pubkey.py b/dshell/plugins/ssh/ssh-pubkey.py index f81cc00..0101d0b 100644 --- a/dshell/plugins/ssh/ssh-pubkey.py +++ b/dshell/plugins/ssh/ssh-pubkey.py @@ -75,13 +75,15 @@ def connection_handler(self, conn): mlist = messagefactory(d) stop_blobs = False for m in mlist: - if m.message_code == 31: + if m.message_code == 31 or m.message_code == 33: info['host_pubkey'] = m.host_pub_key stop_blobs = True break if stop_blobs: break + #print(repr(info)) + if 'host_pubkey' in info: # Calculate key fingerprints info['host_fingerprints'] = {} @@ -129,7 +131,7 @@ def __parse_raw(self, data): self.body = data[6:4+self.packet_len] # ECDH Kex Reply - if self.message_code == 31: + if self.message_code == 31 or self.message_code == 33: host_key_len = struct.unpack(">I", self.body[0:4])[0] full_key_net = self.body[4:4+host_key_len] key_type_name_len = struct.unpack(">I", full_key_net[0:4])[0] From 43e7da6785765ca4f30f3463ee600da6e079ab7d Mon Sep 17 00:00:00 2001 From: Adam M Date: Tue, 29 Dec 2020 14:01:06 +0000 Subject: [PATCH 111/166] Add sanity checks to web decoder --- dshell/plugins/http/web.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/dshell/plugins/http/web.py b/dshell/plugins/http/web.py index a8b5836..b559908 100644 --- a/dshell/plugins/http/web.py +++ b/dshell/plugins/http/web.py @@ -22,7 +22,12 @@ def __init__(self): ) def http_handler(self, conn, request, response): + if request: + if request.method=="": + # It's impossible to have a properly formed HTTP request without a method + # indicating, the httpplugin is calling http_handler without a full object + return conn, request, response # Collect basics about the request, if available method = request.method host = request.headers.get("host", "") @@ -37,6 +42,9 @@ def http_handler(self, conn, request, response): version = "" if response: + if response.status == "" and response.reason == "": + # Another indication of improperly parsed HTTP object in httpplugin + return conn, request, response # Collect basics about the response, if available status = response.status reason = response.reason From 0424d6d4613bb27a5a676f740052ece5e6fc1042 Mon Sep 17 00:00:00 2001 From: DC3-DCCI <12175126+DC3-DCCI@users.noreply.github.com> Date: Fri, 15 May 2020 10:14:27 -0400 Subject: [PATCH 112/166] - Refactored framework to improve code flow. - Added support for modifying packet data for the next plugin in the chain or pcap output. - Updated logging to follow best practices. - Fixed httpplugin to gracefully throw an exception if it fails in a state it cannot recover from. - General bugfixes and improvements. --- .gitignore | 1 + dshell/__init__.py | 15 + dshell/api.py | 36 + dshell/core.py | 1215 ++++++++++++++++--------- dshell/decode.py | 477 +++++----- dshell/dshellargparse.py | 23 + dshell/dshellgeoip.py | 42 +- dshell/dshelllist.py | 15 +- dshell/output/jsonout.py | 1 + dshell/output/output.py | 73 +- dshell/plugins/dnsplugin.py | 19 +- dshell/plugins/filter/country.py | 9 +- dshell/plugins/filter/track.py | 12 +- dshell/plugins/flows/largeflows.py | 9 +- dshell/plugins/flows/longflows.py | 7 +- dshell/plugins/flows/reverseflows.py | 9 +- dshell/plugins/http/httpdump.py | 2 +- dshell/plugins/http/riphttp.py | 17 +- dshell/plugins/httpplugin.py | 21 +- dshell/plugins/malware/sweetorange.py | 10 +- dshell/plugins/misc/pcapwriter.py | 56 +- dshell/plugins/misc/xor.py | 24 +- dshell/plugins/nbns/nbns.py | 16 +- dshell/plugins/protocol/bitcoin.py | 11 +- dshell/plugins/protocol/ether.py | 8 +- dshell/plugins/protocol/ip.py | 7 +- dshell/plugins/tftp/tftp.py | 15 +- dshell/util.py | 20 +- setup.py | 2 + 29 files changed, 1363 insertions(+), 809 deletions(-) create mode 100644 dshell/api.py diff --git a/.gitignore b/.gitignore index b78f06b..ccb9333 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ __pycache__ Dshell.egg-info build/ +.idea/ diff --git a/dshell/__init__.py b/dshell/__init__.py index e69de29..8031e98 100644 --- a/dshell/__init__.py +++ b/dshell/__init__.py @@ -0,0 +1,15 @@ + +# Expose classes and functions that external users will need to access as the API +from .core import ConnectionPlugin, PacketPlugin, Packet +# TODO: Make process_files()/main() function more API friendly through documentation and unwrapping the kwargs. +from .decode import process_files, main_command_line +from .api import get_plugins, get_plugin_information + +from .output.alertout import AlertOutput +from .output.colorout import ColorOutput +from .output.csvout import CSVOutput +from .output.elasticout import ElasticOutput +from .output.htmlout import HTMLOutput +from .output.jsonout import JSONOutput +from .output.netflowout import NetflowOutput +from .output.pcapout import PCAPOutput diff --git a/dshell/api.py b/dshell/api.py new file mode 100644 index 0000000..94307b6 --- /dev/null +++ b/dshell/api.py @@ -0,0 +1,36 @@ +""" +Dshell3 Python API +""" + +import logging +import operator +from importlib import import_module + +# TODO: Move get_plugins() here? +from .dshelllist import get_plugins + + +logger = logging.getLogger(__name__) + + +# TODO: Should this be renamed to "load_plugins()" since it actually imports the modules? +def get_plugin_information() -> dict: + """ + Generates and returns a dictionary of plugins. + :return: dictionary containing plugin name -> plugin module + :raises ImportError: If a plugin could not be imported. + """ + plugin_map = get_plugins() + # Import ALL of the decoders and print info about them before exiting + plugins = {} + for name, module in sorted(plugin_map.items(), key=operator.itemgetter(1)): + try: + module = import_module(module) + if not module.DshellPlugin: + continue + module = module.DshellPlugin() + plugins[name] = module + except Exception as e: + raise ImportError(f"Could not load {repr(module)} with error: {e}") + + return plugins diff --git a/dshell/core.py b/dshell/core.py index 70ab91d..635dca4 100644 --- a/dshell/core.py +++ b/dshell/core.py @@ -16,14 +16,12 @@ # standard Python imports import datetime -import inspect import ipaddress import logging -import os -#import pprint -import struct +import warnings from collections import defaultdict from multiprocessing import Value +from typing import Iterable, List, Tuple # Dshell imports from dshell.output.output import Output @@ -31,12 +29,13 @@ # third-party imports import pcapy +from pypacker import pypacker from pypacker.layer12 import can, ethernet, ieee80211, linuxcc, ppp, pppoe, radiotap from pypacker.layer3 import ip, ip6, icmp, icmp6 from pypacker.layer4 import tcp, udp -logging.basicConfig(format="%(levelname)s (%(name)s) - %(message)s") -logger = logging.getLogger("dshell.core") + +logger = logging.getLogger(__name__) __version__ = "3.1.3" @@ -47,6 +46,7 @@ class SequenceNumberError(Exception): """ pass + class DataError(Exception): """ Raised when any data being handled just isn't right. @@ -57,9 +57,10 @@ class DataError(Exception): # Create GeoIP refrence object try: - geoip = DshellGeoIP(logger=logging.getLogger("dshellgeoip.py")) + geoip = DshellGeoIP() except FileNotFoundError: - logger.error("Could not find GeoIP data files! Country and ASN lookups will not be possible. Check README for instructions on where to find and install necessary data files.") + logger.error( + "Could not find GeoIP data files! Country and ASN lookups will not be possible. Check README for instructions on where to find and install necessary data files.") geoip = DshellFailedGeoIP() @@ -76,11 +77,10 @@ def print_handler_exception(e, plugin, handler): handler: name of the handler function """ etype = e.__class__.__name__ - if logger.isEnabledFor(logging.DEBUG): - logger.error("The {!s} for the {!r} plugin raised an exception and failed! ({}: {!s})".format(handler, plugin.name, etype, e)) - logger.exception(e) - else: - logger.error("The {!s} for the {!r} plugin raised an exception and failed! ({}: {!s}) Use --debug for more details.".format(handler, plugin.name, etype, e)) + logger.error( + "The {!s} for the {!r} plugin raised an exception and failed! ({}: {!s})".format( + handler, plugin.name, etype, e)) + logger.debug(e, exc_info=True) class PacketPlugin(object): @@ -106,15 +106,11 @@ class PacketPlugin(object): handled_conn_count: number of connections this plugin has passed through a handler function out: output module instance - raw_decoder: pypacker module to use for unpacking packet link_layer_type: numeric label for link layer - striplayers: number of layers to automatically strip before handling - (such as PPPoE, IP-over-IP, etc.) defrag_ip: rebuild fragmented IP packets (default: True) """ - IP_PROTOCOL_MAP = dict((v, k[9:]) for k, v in ip.__dict__.items() if type(v) == int and k.startswith('IP_PROTO_') and k != 'IP_PROTO_HOPOPTS') - + # TODO: Move attributes like name, author, and description to be class attributes instead of instance. def __init__(self, **kwargs): self.name = kwargs.get('name', __name__) self.description = kwargs.get('description', '') @@ -123,11 +119,11 @@ def __init__(self, **kwargs): self.compiled_bpf = kwargs.get('compiled_bpf', None) self.vlan_bpf = kwargs.get("vlan_bpf", True) self.author = kwargs.get('author', '') + # define overall counts as multiprocessing Values for --parallel self.seen_packet_count = Value('i', 0) self.handled_packet_count = Value('i', 0) - self.seen_conn_count = Value('i', 0) - self.handled_conn_count = Value('i', 0) + # dict of options specific to this plugin in format # 'optname':{configdict} translates to --pluginname_optname self.optiondict = kwargs.get('optiondict', {}) @@ -135,32 +131,39 @@ def __init__(self, **kwargs): # queues used by decode.py # if a handler decides a packet is worth keeping, it is placed in a # queue and later grabbed by decode.py to pass to subplugins - self.raw_packet_queue = [] - self.packet_queue = [] + self._packet_queue = [] # self.out holds the output plugin instance # can be overwritten in decode.py by user selection - self.out = kwargs.get('output', Output(label=__name__)) + self.out = kwargs.get('output', Output()) # capture options # these can be updated with set_link_layer_type function - self.raw_decoder = ethernet.Ethernet # assumed link-layer type - self.link_layer_type = 1 # assume Ethernet - # strip extra layers before IP/IPv6? (such as PPPoE, IP-over-IP, etc..) - self.striplayers = 0 + self.link_layer_type = 1 # assume Ethernet # rebuild fragmented IP packets self.defrag_ip = True # holder for the pcap file being processing self.current_pcap_file = None - # get the list of functions for this plugin - # this is used in decode.py - self.members = tuple([x[0] for x in inspect.getmembers(self, inspect.ismethod)]) - # a holder for IP packet fragments when attempting to reassemble them self.packet_fragments = defaultdict(dict) + def produce_packets(self) -> Iterable["Packet"]: + """ + Produces packets ready to be processed by the next plugin in the chain. + """ + while self._packet_queue: + yield self._packet_queue.pop(0) + + def flush(self): + """ + Triggers plugin to finish processing any remaining packets that are being held onto. + """ + # By default we don't need to do anything because any consumed packet is placed onto the queue + # right away. + pass + def write(self, *args, **kwargs): """ Sends information to the output formatter, after adding some @@ -173,27 +176,37 @@ def write(self, *args, **kwargs): self.out.write(*args, **kwargs) def log(self, msg, level=logging.INFO): - ''' - logs msg argument at specified level + """ + Logs msg argument at specified level (default of INFO is for -v/--verbose output) Arguments: msg: text string to log level: logging level (default: logging.INFO) - ''' - self.out.log(msg, level=level) + """ + warnings.warn("log() function is deprecated. Please use logging library instead.", DeprecationWarning) + logger.log(level, msg) def debug(self, msg): - '''logs msg argument at debug level''' - self.log(msg, level=logging.DEBUG) + """ + Logs msg argument at debug level + """ + warnings.warn("debug() function is deprecated. Please use logging library instead.", DeprecationWarning) + logger.debug(msg) def warn(self, msg): - '''logs msg argument at warning level''' - self.log(msg, level=logging.WARN) + """ + Logs msg argument at warning level + """ + warnings.warn("warn() function is deprecated. Please use logging library instead.", DeprecationWarning) + logger.warning(msg) def error(self, msg): - '''logs msg argument at error level''' - self.log(msg, level=logging.ERROR) + """ + Logs msg argument at error level. + """ + warnings.warn("error() function is deprecated. Please use logging library instead.", DeprecationWarning) + logger.warning(msg) def __str__(self): return "<{}: {}>".format("Plugin", self.name) @@ -202,45 +215,11 @@ def __repr__(self): return '<{}: {}/{}/{}>'.format("Plugin", self.name, self.bpf, ','.join([('%s=%s' % (x, str(self.__dict__.get(x)))) for x in self.optiondict])) - def set_link_layer_type(self, datalink): - """ - Attempts to set the raw_decoder attribute based on the capture file's - datalink type, which is fetched by pcapy when used in decode.py. It - takes one argument: the numeric value of the link layer. - - http://www.tcpdump.org/linktypes.html - """ - # NOTE: Not all of these have been tested - # TODO add some more of these - self.link_layer_type = datalink - if datalink == 1: - self.raw_decoder = ethernet.Ethernet - elif datalink == 9: - self.raw_decoder = ppp.PPP - elif datalink == 51: - self.raw_decoder = pppoe.PPPoE - elif datalink == 105: - self.raw_decoder = ieee80211.IEEE80211 - elif datalink == 113: - self.raw_decoder = linuxcc.LinuxCC - elif datalink == 127: - self.raw_decoder = radiotap.Radiotap - elif datalink == 204: - self.raw_decoder = ppp.PPP - elif datalink == 227: - self.raw_decoder = can.CAN - elif datalink == 228: - self.raw_decoder = ip.IP - elif datalink == 229: - self.raw_decoder = ip6.IP6 - else: - # by default, assume Ethernet and hope for the best - self.link_layer_type = 1 - self.raw_decoder = ethernet.Ethernet - self.debug("Datalink input: {!s}. Setting raw_decoder to {!r}, link_layer_type to {!s}".format(datalink, self.raw_decoder, self.link_layer_type)) - + # TODO: Perhaps make bpf a property which auto-triggers this when the property value is set. def recompile_bpf(self): - "Compile the BPF stored in the .bpf attribute" + """ + Compile the BPF stored in the .bpf attribute + """ # This function is normally only called by the decode.py script, # but can also be called by plugins that need to dynamically update # their filter. @@ -254,7 +233,7 @@ def recompile_bpf(self): bpf = "({0}) or (vlan and {0})".format(self.bpf) else: bpf = self.bpf - self.debug("Compiling BPF as {!r}".format(bpf)) + logger.debug("Compiling BPF as {!r}".format(bpf)) # Compile BPF and handle any expected errors try: @@ -265,14 +244,15 @@ def recompile_bpf(self): if str(e).startswith("no VLAN support for data link type"): logger.error("Cannot use VLAN filters for {!r} plugin. Recommend running with --no-vlan argument.".format(self.name)) elif str(e) == "syntax error": - logger.error("Fatal error when compiling BPF: {!r}".format(bpf)) - sys.exit(1) + raise ValueError("Fatal error when compiling BPF: {!r}".format(bpf)) else: raise e def ipdefrag(self, pkt): - "IP fragment reassembly" - if isinstance(pkt, ip.IP): # IPv4 + """ + IP fragment reassembly + """ + if isinstance(pkt, ip.IP): # IPv4 f = self.packet_fragments[(pkt.src, pkt.dst, pkt.id)] f[pkt.offset] = pkt @@ -285,7 +265,7 @@ def ipdefrag(self, pkt): newpkt.bin(update_auto_fields=True) # refresh checksum return newpkt - elif isinstance(pkt, ip6.IP6): # IPv6 + elif isinstance(pkt, ip6.IP6): # IPv6 # TODO handle IPv6 offsets https://en.wikipedia.org/wiki/IPv6_packet#Fragment return pkt @@ -296,7 +276,7 @@ def handle_plugin_options(self): This function is called immediately after plugin args are processed and set in decode.py. A plugin can overwrite this function to perform actions based on the arg values as soon as they are set, before - decoder.py does any further processing (e.g. updating a BPF based on + decode.py does any further processing (e.g. updating a BPF based on provided arguments before handling --ebpf and --bpf flags). """ pass @@ -308,7 +288,7 @@ def _premodule(self): """ self.premodule() self.out.setup() -# self.debug('{}'.format(pprint.pformat(self.__dict__))) + # self.debug('{}'.format(pprint.pformat(self.__dict__))) self.debug(str(self.__dict__)) def premodule(self): @@ -328,7 +308,10 @@ def _postmodule(self): """ self.postmodule() self.out.close() - self.log("{} seen packets, {} handled packets, {} seen connections, {} handled connections".format(self.seen_packet_count.value, self.handled_packet_count.value, self.seen_conn_count.value, self.handled_conn_count.value)) + logger.info( + f"{self.seen_packet_count.value} seen packets, " + f"{self.handled_packet_count.value} handled packets " + ) def postmodule(self): """ @@ -347,7 +330,7 @@ def _prefile(self, infile=None): """ self.current_pcap_file = infile self.prefile(infile) - self.log('working on file "{}"'.format(infile)) + logger.info('working on file "{}"'.format(infile)) def prefile(self, infile=None): """ @@ -378,106 +361,35 @@ def postfile(self): """ pass - def _raw_handler(self, pktlen, pkt, ts): - """ - Accepts raw packet data (pktlen, pkt, ts), and handles decapsulation - and layer stripping. - - Then, it passes the massaged data to the child's raw_handler function, - if additional custom handling is necessary. The raw_handler function - should return (pktlen, pkt, ts) if it wishes to continue with the call - chain. Otherwise, return None. - """ -# with self.seen_packet_count.get_lock(): -# self.seen_packet_count.value += 1 -# -# # call raw_handler and check its output -# # decode.py will continue down the chain if it returns proper output or -# # display a warning if it doesn't return the correct things -# try: -# raw_handler_out = self.raw_handler(pktlen, pkt, ts) -# except Exception as e: -# print_handler_exception(e, self, 'raw_handler') -# return -# -# failed_msg = "The output of {} raw_handler must be (pktlen, pkt, ts) or a list of such lists! Further packet refinement and plugin chaining will not be possible".format(self.name) -# if raw_handler_out and isinstance(raw_handler_out, (list, tuple)): -# self.warn(failed_msg) -# return - - with self.seen_packet_count.get_lock(): - self.seen_packet_count.value += 1 - # decode with the raw decoder (probably ethernet.Ethernet) - pkt = self.raw_decoder(pkt) - - # strip any intermediate layers (e.g. PPPoE, etc.) - # NOTE: make sure only the first plugin in a chain has striplayers set - for _ in range(self.striplayers): - try: - pkt = pkt.upper_layer - except AttributeError: - # No more layers to strip - break - - # call raw_handler and check its output - # decode.py will continue down the chain if it returns proper output or - # display a warning if it doesn't return the correct things - try: - raw_handler_out = self.raw_handler(pktlen, pkt, ts) - except Exception as e: - print_handler_exception(e, self, 'raw_handler') - return - failed_msg = "The output of {} raw_handler must be (pktlen, pkt, ts) or a list of such lists! Further packet refinement and plugin chaining will not be possible".format(self.name) - if isinstance(raw_handler_out, (list, tuple)): - if len(raw_handler_out) == 3 and ( - isinstance(raw_handler_out[0], type(pktlen)) and - isinstance(raw_handler_out[1], type(pkt)) and - isinstance(raw_handler_out[2], type(ts))): - # If it returns one properly formed response, queue and continue - self.raw_packet_queue.append(raw_handler_out) - else: - # If it returns several responses, check them individually - for rhout in raw_handler_out: - if isinstance(rhout, (list, tuple)) and \ - len(rhout) == 3 and \ - isinstance(rhout[0], type(pktlen)) and \ - isinstance(rhout[1], type(pkt)) and \ - isinstance(rhout[2], type(ts)): - self.raw_packet_queue.append(rhout) - elif rhout: - self.warn(failed_msg) - elif raw_handler_out: - self.warn(failed_msg) - - - def raw_handler(self, pktlen, pkt, ts): + def filter(self, packet) -> bool: """ - A placeholder. - - Plugins will be able to overwrite this to perform custom activites on - raw packet data, such as decapsulation or decryption, before it - becomes further refined down the chain. It should return the same - arguments: pktlen, pkt, ts + Determines if plugin accepts the packet or it should be filtered out. - Generally speaking, however, this should never be overwritten unless - there is a very, very good reason for it. - - Arguments: - pktlen: length of packet - pkt: raw bytes of the packet - ts: timestamp of packet + :param packet: dshell.Packet object + :return: """ - return pktlen, pkt, ts + # By default we filter by running the compiled bpf, but a plugin can + # inherit this to do extra stuff if desired. + if not self.compiled_bpf: + return True + return bool(self.compiled_bpf.filter(packet.rawpkt)) - def _packet_handler(self, pktlen, pkt, ts): + # NOTE: This was originally called '_packet_handler' + def consume_packet(self, packet: "Packet"): """ - Accepts the output of raw_handler, pulls out addresses, and converts - it all into a dshell.Packet object before calling the child's - packet_handler function. + Filters and defragments packet and then passes the packet along to the packet_handler() + function to determine whether we should pass the packet(s) along to the next plugin. """ + # First apply filter to packet. + if not self.filter(packet): + return + + with self.seen_packet_count.get_lock(): + self.seen_packet_count.value += 1 + # Attempt to perform defragmentation - if isinstance(pkt.upper_layer, (ip.IP, ip6.IP6)): - ipp = pkt.upper_layer + if isinstance(packet.pkt.upper_layer, (ip.IP, ip6.IP6)): + ipp = packet.pkt.upper_layer if self.defrag_ip: ipp = self.ipdefrag(ipp) if not ipp: @@ -485,12 +397,7 @@ def _packet_handler(self, pktlen, pkt, ts): # on to next packet for now return else: - pkt.upper_layer = ipp - - # Initialize a Packet object - # This will be populated with values as we continue through - # the function and eventually be passed to packet_handler - packet = Packet(self, pktlen, pkt, ts) + packet.pkt.upper_layer = ipp # call packet_handler and return its output # decode.py will continue down the chain if it returns anything @@ -499,24 +406,26 @@ def _packet_handler(self, pktlen, pkt, ts): except Exception as e: print_handler_exception(e, self, 'packet_handler') return - failed_msg = "The output from {} packet_handler must be of type dshell.Packet or a list of such objects! Handling connections or chaining from this plugin may not be possible.".format(self.name) + failed_msg = ( + f"The output from {self.name} packet_handler must be of type dshell.Packet or a list of " + f"such objects! Handling connections or chaining from this plugin may not be possible." + ) if isinstance(packet_handler_out, (list, tuple)): for phout in packet_handler_out: if isinstance(phout, Packet): - self.packet_queue.append(phout) + self._packet_queue.append(phout) with self.handled_packet_count.get_lock(): self.handled_packet_count.value += 1 elif phout: - self.warn(failed_msg) + logger.warning(failed_msg) elif isinstance(packet_handler_out, Packet): - self.packet_queue.append(packet_handler_out) + self._packet_queue.append(packet_handler_out) with self.handled_packet_count.get_lock(): self.handled_packet_count.value += 1 elif packet_handler_out: - self.warn(failed_msg) - + logger.warning(failed_msg) - def packet_handler(self, pkt): + def packet_handler(self, pkt: "Packet"): """ A placeholder. @@ -532,7 +441,6 @@ def packet_handler(self, pkt): return pkt - class ConnectionPlugin(PacketPlugin): """ Base level class that plugins will inherit. @@ -540,14 +448,27 @@ class ConnectionPlugin(PacketPlugin): This plugin reassembles connections from packets. """ + # Determines whether to filter out packets based on blobs or to produce packets directly. + # Turning this off if the plugin doesn't mark any blobs as hidden can help improve speed. + # TODO: There is another hacky reason this boolean exists. + # Due to how we modified the blob creation code, the ACK and handshake methods are not + # part of any of the blobs. Therefore, when the produce_packets() function is called, those + # packets are missing if we are only producing the packets within a blob. + BLOB_FILTERING = True + def __init__(self, **kwargs): - PacketPlugin.__init__(self, **kwargs) + super().__init__(**kwargs) # similar to packet_queue and raw_packet_queue in superclass - self.connection_queue = [] + self._connection_queue = [] # dictionary to store packets for connections according to addr() - self.connection_tracker = {} + self._connection_tracker = {} + + # define overall counts as multiprocessing Values for --parallel + self.seen_conn_count = Value('i', 0) + self.handled_conn_count = Value('i', 0) + # maximum number of blobs a connection will store before calling # connection_handler # it defaults to infinite, but this should be lowered for huge datasets @@ -558,7 +479,66 @@ def __init__(self, **kwargs): # timestamp of the current packet, minus this value self.connection_timeout = datetime.timedelta(hours=1) - def _connection_handler(self, pkt): + def _postmodule(self): + """ + Overwriting _postmodule to add log info about connection counts. + """ + super()._postmodule() + logger.info( + f"{self.seen_conn_count.value} seen connections, " + f"{self.handled_conn_count.value} handled connections" + ) + + def produce_connections(self) -> Iterable["Connection"]: + """ + Produces recently closed connections ready to be passed down to the next plugin in the chain. + """ + while self._connection_queue: + connection = self._connection_queue.pop(0) + yield connection + + # Attempt to clear out the connection, now that it has been handled. + conn_key = tuple(sorted(connection.addr)) + try: + del self._connection_tracker[conn_key] + except KeyError: + # If the plugin messed with the connection's address, it might + # fail to clear it. + # TODO find some way to better handle this scenario + pass + + def produce_packets(self) -> Iterable["Packet"]: + """ + Produces packets ready to be processed by the next plugin in the chain. + """ + # Produce connections + for connection in self.produce_connections(): + if self.BLOB_FILTERING: + for blob in connection.blobs: + if not blob.hidden: + yield from blob.packets + else: + # TODO: Perhaps have a "hidden" field on the packet itself? + yield from connection.packets + + def consume_packet(self, packet: "Packet"): + # First run super() to handle the individual packets. + super().consume_packet(packet) + + # Now process any produced packets to be processed through connection handler. + for _packet in super().produce_packets(): + self._connection_handler(_packet) + + def flush(self): + """ + Triggers plugin to finish processing any remaining packets that are being held onto. + """ + super().flush() + # Call cleanup_connections() to force close any remaining open connections so they are + # on the queue ready to be passed down the chain. + self._cleanup_connections() + + def _connection_handler(self, packet: "Packet"): """ Accepts a single Packet object and tracks the connection it belongs to. @@ -575,12 +555,12 @@ def _connection_handler(self, pkt): connection should close. """ # Sort the addr value for consistent dictionary key purposes - addr = tuple(sorted(pkt.addr)) + addr = tuple(sorted(packet.addr)) # If this is a new connection, initialize it and call the init handler - if addr not in self.connection_tracker: - conn = Connection(self, pkt) - self.connection_tracker[addr] = conn + if addr not in self._connection_tracker: + conn = Connection(packet) + self._connection_tracker[addr] = conn try: self.connection_init_handler(conn) except Exception as e: @@ -589,99 +569,63 @@ def _connection_handler(self, pkt): with self.seen_conn_count.get_lock(): self.seen_conn_count.value += 1 else: - conn = self.connection_tracker[addr] + conn = self._connection_tracker[addr] if conn.stop: # This connection was flagged to not be tracked return - # If connection data is about to change, we set it to a "dirty" state - # for future calls to connection_handler - if pkt.data: - conn.handled = False - - # Check and update the connection's current state - if pkt.tcp_flags in (tcp.TH_SYN, tcp.TH_ACK, tcp.TH_SYN|tcp.TH_ACK, tcp.TH_SYN|tcp.TH_ACK|tcp.TH_ECE): - # if new connection and a handshake is taking place, set to "init" - if not conn.client_state: - conn.client_state = "init" - if not conn.server_state: - conn.server_state = "init" - else: - # otherwise, if the connection isn't closed, set to "established" - # TODO do we care about "listen", "syn-sent", and other in-between states? - if conn.client_state not in ('finishing', 'closed'): - conn.client_state = "established" - if conn.server_state not in ('finishing', 'closed'): - conn.server_state = "established" - - # Add the packet to the connection - # If the direction changed, a Blob will be returned for handling - # Note: The Blob will not be reassembled ahead of time. reassemble() - # must be run inside the blob_handler to catch any unwanted exceptions. - previous_blob = conn.add_packet(pkt) - if previous_blob: - try: - blob_handler_out = self._blob_handler(conn, previous_blob) - except Exception as e: - print_handler_exception(e, self, 'blob_handler') - return - if (blob_handler_out - and not isinstance(blob_handler_out[0], Connection) - and not isinstance(blob_handler_out[1], Blob)): - self.warn("The output from {} blob_handler must be of type (dshell.Connection, dshell.Blob)! Chaining plugins from here may not be possible.".format(self.name)) - blob_handler_out = None - # If the blob_handler decides this Blob isn't interesting, it sets - # the hidden flag, which excludes it and its packets from further - # processing along the plugin chain - if not blob_handler_out: - conn.blobs[-2].hidden = True - - # Check if a side of the connection is attempting to close the - # connection using a FIN or RST packet. Once both sides make a - # closing gesture, the connection is considered closed and handled - if pkt.tcp_flags and pkt.tcp_flags & (tcp.TH_RST | tcp.TH_FIN): - if pkt.sip == conn.clientip: - conn.client_state = "closed" - else: - conn.server_state = "closed" - - if conn.connection_closed: - # Both sides have closed the connection + # TODO: Do we need this? This flag is set to False when the connection is initialized and not + # set to true until it is closed. + # Is there any scenario where we would want to undo a True handled state? + # # If connection data is about to change, we set it to a "dirty" state + # # for future calls to connection_handler + # if pkt.data: + # conn.handled = False + + conn.add_packet(packet) + + if conn.closed: + # Both sides have closed the connection, process blobs (messages) and + # close connection. + for blob in conn.blobs: + self._blob_handler(conn, blob) self._close_connection(conn, full=True) - elif len(conn.blobs) > self.maxblobs: - # Max blobs hit, so we will run connection_handler and decode.py - # will clear the connection's blob cache - self._close_connection(conn) + # TODO: Switch to a max_packets option. + # elif len(conn.blobs) > self.maxblobs: + # # Max blobs hit, so we will run connection_handler and decode.py + # # will clear the connection's blob cache + # self._close_connection(conn) # The current connection is done processing. Now, look over existing # connections and look for any that have timed out. # This is based on comparing the time of the current packet, minus # self.connection_timeout, to each connection's current endtime value. - for addr, conn in self.connection_tracker.items(): + for addr, conn in self._connection_tracker.items(): if conn.handled: continue - if conn.endtime < (pkt.dt - self.connection_timeout): + if conn.endtime < (packet.dt - self.connection_timeout): self._close_connection(conn) - def _close_connection(self, conn, full=False): """ Runs through some standard actions to close a connection """ try: - connection_handler_out = self.connection_handler(conn) + connection_handler_out = self.connection_handler(conn) except Exception as e: print_handler_exception(e, self, 'connection_handler') return None conn.handled = True if connection_handler_out and not isinstance(connection_handler_out, Connection): - self.warn("The output from {} connection_handler must be of type dshell.Connection! Chaining plugins from here may not be possible.".format(self.name)) + logger.warning( + "The output from {} connection_handler must be of type dshell.Connection! Chaining plugins from here may not be possible.".format( + self.name)) connection_handler_out = None if connection_handler_out: - self.connection_queue.append(connection_handler_out) - with self.handled_conn_count.get_lock(): + self._connection_queue.append(connection_handler_out) + with self.handled_packet_count.get_lock(): self.handled_conn_count.value += 1 if full: try: @@ -690,7 +634,6 @@ def _close_connection(self, conn, full=False): print_handler_exception(e, self, 'connection_close_handler') return connection_handler_out - def _cleanup_connections(self): """ decode.py will often reach the end of packet capture before all of the @@ -700,44 +643,47 @@ def _cleanup_connections(self): NOTE: Because the connections did not close cleanly, connection_close_handler will not be called. """ - for addr, conn in self.connection_tracker.items(): + for addr, conn in self._connection_tracker.items(): if not conn.stop and not conn.handled: # try to process the final blob in the connection - try: - blob_handler_out = self._blob_handler(conn, conn.blobs[-1]) - except Exception as e: - print_handler_exception(e, self, 'blob_handler') - blob_handler_out = None - if (blob_handler_out - and not isinstance(blob_handler_out[0], Connection) - and not isinstance(blob_handler_out[1], Blob)): - self.warn("The output from {} blob_handler must be of type (dshell.Connection, dshell.Blob)! Chaining plugins from here may not be possible.".format(self.name)) - blob_handler_out = None - if not blob_handler_out: - conn.blobs[-1].hidden = True + # TODO: Refactoring most likely made processing the last blob obsolete. + # self._blob_handler(conn, conn.blobs[-1]) # then, handle the connection itself - connection_handler_out = self._close_connection(conn) - yield connection_handler_out + self._close_connection(conn) def _purge_connections(self): """ When finished with handling a pcap file, calling this will clear all caches in preparation for next file. """ - self.connection_queue = [] - self.connection_tracker = {} + self._connection_queue = [] + self._connection_tracker = {} - def _blob_handler(self, conn, blob): + # TODO: Have blobs handled with consumer/producer model just like Packets and Connections? + def _blob_handler(self, conn: "Connection", blob: "Blob"): """ Accepts a Connection and a Blob. It doesn't really do anything except call the blob_handler and is only here for consistency and possible future features. """ - return self.blob_handler(conn, blob) + try: + blob_handler_out = self.blob_handler(conn, blob) + except Exception as e: + print_handler_exception(e, self, 'blob_handler') + blob_handler_out = None + if blob_handler_out: + connection, blob = blob_handler_out + if not isinstance(connection, Connection) or not isinstance(blob, Blob): + logger.warning( + "The output from {} blob_handler must be of type (dshell.Connection, dshell.Blob)! Chaining plugins from here may not be possible.".format( + self.name)) + blob_handler_out = None + if not blob_handler_out: + blob.hidden = True - def blob_handler(self, conn, blob): + def blob_handler(self, conn: "Connection", blob: "Blob"): """ A placeholder. @@ -753,7 +699,7 @@ def blob_handler(self, conn, blob): """ return conn, blob - def connection_init_handler(self, conn): + def connection_init_handler(self, conn: "Connection"): """ A placeholder. @@ -765,7 +711,7 @@ def connection_init_handler(self, conn): """ return - def connection_handler(self, conn): + def connection_handler(self, conn: "Connection"): """ A placeholder. @@ -779,7 +725,7 @@ def connection_handler(self, conn): """ return conn - def connection_close_handler(self, conn): + def connection_close_handler(self, conn: "Connection"): """ A placeholder. @@ -791,6 +737,7 @@ def connection_close_handler(self, conn): """ return + class Packet(object): """ Class for holding data of individual packets @@ -798,13 +745,11 @@ class Packet(object): def __init__(self, plugin, pktlen, pkt, ts): Args: - plugin: an instance of the plugin creating this packet pktlen: length of packet pkt: pypacker object for the packet ts: timestamp of packet Attributes: - plugin: name of plugin creating Packet ts: timestamp of packet dt: datetime of packet pkt: pypacker object for the packet @@ -835,13 +780,17 @@ def __init__(self, plugin, pktlen, pkt, ts): tcp_flags: TCP header flags, or None """ - def __init__(self, plugin, pktlen, pkt, ts): - self.plugin = plugin.name - self.ts = ts - self.dt = datetime.datetime.fromtimestamp(ts) - self.pkt = pkt - self.rawpkt = pkt.bin() - self.pktlen = pktlen + IP_PROTOCOL_MAP = dict((v, k[9:]) for k, v in ip.__dict__.items() if + type(v) == int and k.startswith('IP_PROTO_') and k != 'IP_PROTO_HOPOPTS') + + def __init__(self, pktlen, packet: pypacker.Packet, timestamp: int, frame=0): + # TODO: Use full variable names. + self.ts = timestamp + self.dt = datetime.datetime.fromtimestamp(timestamp) + self.frame = frame + self.pkt = packet + self.pktlen = pktlen # TODO: Is this needed? + self.byte_count = None self.sip = None self.dip = None @@ -859,7 +808,7 @@ def __init__(self, plugin, pktlen, pkt, ts): self.dipasn = None self.protocol = None self.protocol_num = None - self.data = b'' + self._data = None # data cache self.sequence_number = None self.ack_number = None self.tcp_flags = None @@ -871,8 +820,10 @@ def __init__(self, plugin, pktlen, pkt, ts): ip_p = None tcp_p = None udp_p = None - current_layer = pkt + current_layer = packet + self._highest_layer = current_layer while current_layer: + self._highest_layer = current_layer if isinstance(current_layer, ethernet.Ethernet) and not ethernet_p: ethernet_p = current_layer elif isinstance(current_layer, ieee80211.IEEE80211) and not ieee80211_p: @@ -914,6 +865,11 @@ def __init__(self, plugin, pktlen, pkt, ts): except AttributeError as e: pass + # Cache ip, tcp, and udp layer for future use. + self._ip_layer = ip_p + self._tcp_layer = tcp_p + self._udp_layer = udp_p + # process IP addresses and associated metadata (if applicable) if ip_p: # get IP addresses @@ -926,7 +882,7 @@ def __init__(self, plugin, pktlen, pkt, ts): # get protocols, country codes, and ASNs self.protocol_num = ip_p.p if isinstance(ip_p, ip.IP) else ip_p.nxt - self.protocol = PacketPlugin.IP_PROTOCOL_MAP.get(self.protocol_num, str(self.protocol_num)) + self.protocol = self.IP_PROTOCOL_MAP.get(self.protocol_num, str(self.protocol_num)) self.sipcc, self.siplat, self.siplon = geoip.geoip_location_lookup(self.sip) self.sipasn = geoip.geoip_asn_lookup(self.sip) self.dipcc, self.diplat, self.diplon = geoip.geoip_location_lookup(self.dip) @@ -938,20 +894,13 @@ def __init__(self, plugin, pktlen, pkt, ts): self.sequence_number = tcp_p.seq self.ack_number = tcp_p.ack self.tcp_flags = tcp_p.flags - self.data = tcp_p.body_bytes elif udp_p: self.sport = udp_p.sport self.dport = udp_p.dport - self.data = udp_p.body_bytes - - else: - self.data = pkt.highest_layer.body_bytes self.byte_count = len(self.data) - - @property def addr(self): """ @@ -962,13 +911,13 @@ def addr(self): """ # try using IP addresses first if self.sip or self.dip: - return ((self.sip, self.sport), (self.dip, self.dport)) + return (self.sip, self.sport), (self.dip, self.dport) # then try MAC addresses elif self.smac or self.dmac: - return ((self.smac, self.sport), (self.dmac, self.dport)) + return (self.smac, self.sport), (self.dmac, self.dport) # if all else fails, return Nones else: - return ((None, None), (None, None)) + return (None, None), (None, None) @property def packet_tuple(self): @@ -976,10 +925,62 @@ def packet_tuple(self): A standard representation of the raw packet tuple: (self.pktlen, self.rawpkt, self.ts) """ - return (self.pktlen, self.rawpkt, self.ts) + return self.pktlen, self.rawpkt, self.ts + + @property + def rawpkt(self): + """ + The raw data that represents the full packet. + """ + return self.pkt.bin() + + @property + def data(self): + """ + Retrieve data bytes from TCP/UDP data layer. Backtracks to data from highest layer. + """ + if self._data is None: + # NOTE: Using cached layers because pypacker's __getitem__ is slow. + # best_layer = self.pkt[tcp.TCP] or self.pkt[udp.UDP] or self.pkt.highest_layer + best_layer = self._tcp_layer or self._udp_layer or self._highest_layer + + # Pypacker doesn't handle Ethernet trailers correctly, so we need to + # do some header calculation in order to determine the true body_bytes size. + ip_layer = self._ip_layer + tcp_layer = self._tcp_layer + if ip_layer and tcp_layer: + data_size = ip_layer.len - (ip_layer.header_len + tcp_layer.header_len) + self._data = best_layer.body_bytes[:data_size] + else: + self._data = best_layer.body_bytes + + return self._data + + @data.setter + def data(self, data): + """ + Sets data bytes to TCP/UDP data layer. Backtracks to setting data at highest layer. + """ + # NOTE: Using cached layers because pypacker's __getitem__ is slow. + # best_layer = self.pkt[tcp.TCP] or self.pkt[udp.UDP] or self.pkt.highest_layer + best_layer = self._tcp_layer or self._udp_layer or self._highest_layer + + # Pypacker doesn't handle Ethernet trailers correctly, so we need to + # do some header calculation in order to determine the true body_bytes size. + ip_layer = self._ip_layer + tcp_layer = self._tcp_layer + if ip_layer and tcp_layer: + data_size = ip_layer.len - (ip_layer.header_len + tcp_layer.header_len) + best_layer.body_bytes = data + best_layer.body_bytes[data_size:] + else: + best_layer.body_bytes = data + + self._data = data + # TODO: Rebuild packet object to allow for pypacker to do its thing. def __repr__(self): - return "%s %16s :%-5s -> %5s :%-5s (%s -> %s)" % (self.dt, self.sip, self.sport, self.dip, self.dport, self.sipcc, self.dipcc) + return "%s %16s :%-5s -> %5s :%-5s (%s -> %s)" % ( + self.dt, self.sip, self.sport, self.dip, self.dport, self.sipcc, self.dipcc) def info(self): """ @@ -1000,11 +1001,9 @@ class Connection(object): def __init__(self, plugin, first_packet) Args: - plugin: an instance of the plugin creating this connection first_packet: the first Packet object to initialize connection Attributes: - plugin: name of the plugin that created object addr: .addr attribute of first packet sip: source IP smac: source MAC address @@ -1054,16 +1053,23 @@ def __init__(self, plugin, first_packet) """ - def __init__(self, plugin, first_packet): + # status + # NOTE: Using strings instead of int enum to stay backwards compatible. + INIT = "init" + ESTABLISHED = "established" + FINISHING = "finishing" + CLOSED = "closed" + + def __init__(self, first_packet): """ Initializes Connection object Args: - plugin: an instance of the plugin creating this connection first_packet: the first Packet object to initialize connection """ - self.plugin = plugin.name self.addr = first_packet.addr + # TODO: Rename these variables to something more verbose like "source_ip" + # I keep getting confused whether the "s" stands for "source" or "server". self.sip = first_packet.sip self.smac = first_packet.smac self.sport = first_packet.sport @@ -1103,53 +1109,101 @@ def __init__(self, plugin, first_packet): self.endtime = first_packet.dt self.client_state = None self.server_state = None - self.blobs = [] + # self.blobs = [] + self.packets = [] # keeps track of packets in connection. self.stop = False self.handled = False # used to determine if direction changes self._current_addr_pair = None + self.add_packet(first_packet) + @property def duration(self): - "total seconds from starttime to endtime" + """ + Total seconds from start_time to end_time. + """ tdelta = self.endtime - self.starttime return tdelta.total_seconds() @property - def connection_closed(self): - return self.client_state == "closed" and self.server_state == "closed" + def closed(self): + return self.client_state == self.CLOSED and self.server_state == self.CLOSED - def add_packet(self, packet): + @property + def established(self): + return self.client_state == self.ESTABLISHED and self.server_state == self.ESTABLISHED + + @property + def blobs(self) -> Iterable["Blob"]: """ - Accepts a Packet object and attempts to push it into the current Blob. - If the direction changes, it creates a new Blob and returns the old one - to the caller. + Iterates the blobs (or messages) contained in this tcp connection - Args: - packet: a Packet object to add to the connection + This is dynamically generated on-demand based on the current set of packets in the connection. + """ + blobs = [] - Returns: - Previous Blob if direction has changed + for packet in self.packets: + # TODO: skipping packets without data greatly improves speed, but we may want to + # allow them if we support using ack numbers. + if not packet.data: + continue + + # If we see a sequence for an old blob, this is a retransmission. + # Find the blob and add this packet. + # NOTE: There is probably more to it than this, but this seems to work for now. + seq = packet.sequence_number + if seq is not None: + found = False + for blob in blobs: + if blob.sip == packet.sip and seq in blob.sequence_range: + blob.add_packet(packet) + found = True + break + if found: + continue + + # Create a new message if the first or the other direction has started sending data. + if not blobs or (packet.sip != blobs[-1].sip and packet.data): + blobs.append(Blob(self, packet)) + + # Otherwise add packet to last blob. + else: + blobs[-1].add_packet(packet) + + yield from blobs + + def add_packet(self, packet: Packet): """ - if packet.sip == self.clientip and (not packet.sport or packet.sport == self.clientport): - # packet moving from client to server - direction = 'cs' - else: - # packet moving from server to client - direction = 'sc' + Adds packet to connection. - if (packet.addr != self._current_addr_pair and packet.data) or len(self.blobs) == 0: - try: - old_blob = self.blobs[-1] - except IndexError: - old_blob = None - self.blobs.append(Blob(packet, direction)) - self._current_addr_pair = packet.addr - else: - old_blob = None + :param packet: a Packet object to add to the connection + """ + if packet.sip not in (self.sip, self.dip): + raise ValueError(f"Address {repr(packet.sip)} is not part of connection.") - blob = self.blobs[-1] - blob.add_packet(packet) + self.packets.append(packet) + + # Adjust state if packet is part of a startup or shutdown. + if packet.tcp_flags is not None: + # Acknowledging a completed handshake to open connection. + if packet.tcp_flags == (tcp.TH_SYN | tcp.TH_ACK): + self.server_state = self.ESTABLISHED + self.client_state = self.ESTABLISHED + + # Asking to close connection. + elif packet.tcp_flags & (tcp.TH_FIN | tcp.TH_RST): + if packet.sip == self.serverip: + self.server_state = self.FINISHING + else: + self.client_state = self.FINISHING + + # Closing connection acknowledged. + elif packet.tcp_flags & tcp.TH_ACK: + if packet.dip == self.serverip and self.server_state == self.FINISHING: + self.server_state = self.CLOSED + elif packet.dip == self.clientip and self.client_state == self.FINISHING: + self.client_state = self.CLOSED # Only count packets if they have data (i.e. ignore SYNs, ACKs, etc.) if packet.data: @@ -1163,9 +1217,6 @@ def add_packet(self, packet): if packet.dt > self.endtime: self.endtime = packet.dt - if old_blob: - return old_blob - def info(self): """ Provides a dictionary with information about a connection. Useful for @@ -1176,7 +1227,6 @@ def info(self): """ d = dict(self.__dict__) d['duration'] = self.duration - del d['blobs'] del d['stop'] del d['_current_addr_pair'] del d['handled'] @@ -1198,6 +1248,8 @@ def __repr__(self): self.duration, ) + +# TODO: Rename this "TCPBlob" and then have a more generic "Blob" class it inherits from. class Blob(object): """ Class for holding and reassembling pieces of a connection. @@ -1208,12 +1260,13 @@ class Blob(object): def __init__(self, first_packet, direction) Args: + connection: The Connection object that this Blob comes from. (Used for validating packets.) first_packet: the first Packet object to initialize Blob - direction: direction of blob - - 'cs' for client-to-server, 'sc' for sever-to-client Attributes: addr: .addr attribute of the first packet + direction: direction of blob - + 'cs' for client-to-server, 'sc' for server-to-client ts: timestamp of the first packet starttime: datetime for first packet endtime: datetime of last packet @@ -1229,10 +1282,10 @@ def __init__(self, first_packet, direction) dipasn: ASN of dest IP protocol: text version of protocol in layer-3 header direction: direction of the blob - - 'cs' for client-to-server, 'sc' for sever-to-client + 'cs' for client-to-server, 'sc' for server-to-client ack_sequence_numbers: set of ACK numbers from the receiver for #################################### collected data packets - all_packets: list of all packets in the blob + packets: list of all packets in the blob hidden (bool): Used to indicate that a Blob should not be passed to next plugin. Can theoretically be overruled in, say, a connection_handler to force a Blob to be passed to next @@ -1242,11 +1295,13 @@ def __init__(self, first_packet, direction) # max offset before wrap, default is MAXINT32 for TCP sequence numbers MAX_OFFSET = 0xffffffff - def __init__(self, first_packet, direction): + CLIENT_TO_SERVER = 'cs' + SERVER_TO_CLIENT = 'sc' + + def __init__(self, connection: Connection, first_packet): + self.connection = connection self.addr = first_packet.addr self.ts = first_packet.ts - self.starttime = first_packet.dt - self.endtime = first_packet.dt self.sip = first_packet.sip self.smac = first_packet.smac self.sport = first_packet.sport @@ -1258,29 +1313,248 @@ def __init__(self, first_packet, direction): self.dipcc = first_packet.dipcc self.dipasn = first_packet.dipasn self.protocol = first_packet.protocol - self.direction = direction -# self.ack_sequence_numbers = {} - self.all_packets = [] -# self.data_packets = [] + # self.ack_sequence_numbers = {} + self.packets = [] + # self.data_packets = [] self.__data_bytes = b'' + # Used for data caching + self._data = None + self._segments = None + + # Maps sequence number with packets + self._seq_map = {} + # Used to indicate that a Blob should not be passed to next plugin. # Can theoretically be overruled in, say, a connection_handler to # force a Blob to be passed to next plugin. self.hidden = False + if self.sip == self.connection.clientip and \ + (not self.sport or self.sport == self.connection.clientport): + # packet moving from client to server + self.direction = self.CLIENT_TO_SERVER + else: + # packet moving from server to client + self.direction = self.SERVER_TO_CLIENT + + self.add_packet(first_packet) + + @property + def all_packets(self): + warnings.warn("all_packets has been replaced with packets attribute", DeprecationWarning) + return self.packets + + @property + def starttime(self): + return min(packet.dt for packet in self.packets) + + @property + def start_time(self): + return self.starttime + + @property + def endtime(self): + return max(packet.dt for packet in self.packets) + + @property + def end_time(self): + return self.endtime + + @property + def frames(self) -> List[int]: + """ + The frame identifiers for the packets which contain the message. + """ + return [packet.frame for packet in self.packets] + + def get_packets(self, start, end=None) -> List["Packet"]: + """ + Returns the packets that contain data for the given start offset up to the end offset. + If end offset is not provided, just the packet containing the start offset is provided. + """ + packets = [] + + # TODO: Double check logic on this. + + # If not a TCP connection, return frames that had data. + if self.packets[0].tcp_flags is None: + offset = 0 + for packet in self.packets: + if not packet.data: + continue + + offset += len(packet.data) + if offset > start: + packets.append(packet) + if end is None or offset >= end: + break + + # Otherwise, base offsets on sequence numbers. + else: + initial_seq = None + for seq, packet in self.segments: + if initial_seq is None: + initial_seq = seq + offset = seq - initial_seq + end_offset = offset + len(packet.data) + if end_offset > start: + packets.append(packet) + if end is None or end_offset >= end: + break + + return packets + + def get_frames(self, start, end=None) -> List[int]: + return [packet.frame for packet in self.get_packets(start, end=end)] + + @property + def sequence_numbers(self) -> List[int]: + """ + The starting sequence numbers found within the packets. + """ + return list(self._seq_map.keys()) + + @property + def sequence_range(self) -> range: + """ + The range of sequence numbers found within the packets. + """ + sequence_numbers = self.sequence_numbers + if not sequence_numbers: + return range(0, 0) + + min_seq = min(sequence_numbers) + max_seq = max(sequence_numbers) + return range(min_seq, max_seq + len(self._seq_map[max_seq].data)) + + @property + def segments(self) -> List[Tuple[int, "Packet"]]: + """ + List of valid (sequence number, packet) tuples in order by sequence number. + """ + if self._segments is not None: + return self._segments + + segments = [] + # Iterate through segments, ignoring segments that cause overlap in data. + expected_seq = None + prev_packet = None + for seq, packet in sorted(self._seq_map.items()): + if expected_seq is None: + expected_seq = seq + + # If the sequence is greater than or equal to the expected sequence, this segment is valid. + if seq >= expected_seq: + segments.append((seq, packet)) + missing_num_bytes = seq - expected_seq + if missing_num_bytes: + logger.debug( + f"Missing {missing_num_bytes} bytes of data between packets " + f"{prev_packet and prev_packet.frame} and {packet.frame}" + ) + expected_seq += missing_num_bytes + len(packet.data) + prev_packet = packet + + # Otherwise, we have some overlap in data and need to remove the invalid segment/packet + # and ignoring adding it to the segments list. + else: + logger.debug(f"Packet {packet.frame} contains overlapped data. Removing...") + self._remove_packet(packet) + + self._segments = segments # cache for next time. + return segments + + # # TODO: Should this account for pulling data before all packets have been added? + # @property + # def data(self): + # """ + # Returns the reassembled byte string. + # + # If it was not already reassembled, reassemble is called with default + # arguments. + # """ + # if not self.__data_bytes: + # self.reassemble() + # return self.__data_bytes + @property def data(self): """ - Returns the reassembled byte string. + Raw data of tcp message. + """ + # Return cache if set. + if self._data is not None: + return self._data + + # If not a TCP connection, just join packet data as they arrived on the wire. + # TODO: Move this logic to a base class. + if self.packets[0].tcp_flags is None: + return b''.join(packet.data for packet in self.packets) + + # Join packet data based on segment data. + data = bytearray() # using bytearray to improve speed. + initial_seq = None + for seq, packet in self.segments: + if initial_seq is None: + initial_seq = seq - If it was not already reassembled, reassemble is called with default - arguments. + # Check if we have missing packets. + if seq - initial_seq != len(data): + # logger.warning('Missing packets in TCP stream.') + # buffer data with null bytes + data += b'\x00' * (seq - initial_seq - len(data)) + + data += packet.data + data = bytes(data) + + self._data = data # set cache + return data + + @data.setter + def data(self, data): """ - if not self.__data_bytes: - self.reassemble() - return self.__data_bytes + Replaces message data with new data. + + WARNING: Currently, data must match original length. + """ + # TODO: Support different amount of bytes by adding packets or padding/removing packets. + orig_len = len(self.data) + if len(data) != orig_len: + raise ValueError( + f'Message data must be of the same length as original. ' + f'Expected {orig_len} bytes, got {len(data)} bytes.') + + # If not a TCP connection, just add data to packets in same order they arrived on wire. + if self.packets[0].tcp_flags is None: + written_bytes = 0 + for packet in self.packets: + packet.data = data[written_bytes : written_bytes + len(packet.data)] + written_bytes += len(packet.data) + # Clear old cache. + self._data = None + return + # If TCP connection, add data based on sequence numbers. + written_bytes = 0 + initial_seq = None + for seq, packet in self.segments: + if initial_seq is None: + initial_seq = seq + + # Skip holes in data. (User should have put padding in these areas) + if seq - initial_seq != written_bytes: + # logger.warning('Missing packets in TCP stream.') + written_bytes += seq - initial_seq - written_bytes + + packet.data = data[written_bytes:written_bytes + len(packet.data)] + written_bytes += len(packet.data) + + # Clear old cache. + self._data = None + + # TODO: Merge this in with the add_packet() logic, however I am unsure how using acknowledge numbers + # works if we are only looking at one side. def reassemble(self, allow_padding=True, allow_overlap=True, padding=b'\x00'): """ Rebuild the data string from the current list of data packets @@ -1303,7 +1577,7 @@ def reassemble(self, allow_padding=True, allow_overlap=True, padding=b'\x00'): data = b"" unacknowledged_data = [] acknowledged_data = {} - for pkt in self.all_packets: + for pkt in self.packets: if not pkt.sequence_number: # if there are no sequence numbers (i.e. not TCP), just rebuild # in chronological order @@ -1319,7 +1593,7 @@ def reassemble(self, allow_padding=True, allow_overlap=True, padding=b'\x00'): ackpkt = pkt for i, datapkt in enumerate(unacknowledged_data): if (datapkt.ack_number == ackpkt.sequence_number - and ackpkt.ack_number == (datapkt.sequence_number + len(datapkt.data))): + and ackpkt.ack_number == (datapkt.sequence_number + len(datapkt.data))): # if the seq/ack numbers align, this is the data packet # we want # TODO confirm this logic is correct @@ -1355,7 +1629,8 @@ def reassemble(self, allow_padding=True, allow_overlap=True, padding=b'\x00'): elif offset < nextoffset: # data is overlapping if not allow_overlap: - raise SequenceNumberError("Overlapping data for sequence number %d %s" % (nextoffset, self.addr)) + raise SequenceNumberError( + "Overlapping data for sequence number %d %s" % (nextoffset, self.addr)) nextoffset = (offset + len(segments[offset])) & self.MAX_OFFSET data = data[:offset - startoffset] + \ @@ -1365,61 +1640,58 @@ def reassemble(self, allow_padding=True, allow_overlap=True, padding=b'\x00'): return data - - - -# segments = {} -# for pkt in self.data_packets: -# if pkt.sequence_number: -# segments.setdefault(pkt.sequence_number, []).append(pkt.data) -# else: -# # if there are no sequence numbers (i.e. not TCP), just rebuild -# # in chronological order -# data += pkt.data -# -# if not segments: -# # For non-sequential protocols, just return what we have -# self.__data_bytes = data -# return data -# -# offsets = sorted(segments.keys()) -# -# # iterate over the segments and try to piece them together -# # handle any instances of missing or overlapping segments -# nextoffset = offsets[0] -# startoffset = offsets[0] -# for offset in offsets: -# # TODO do we still want to implement custom error handling? -# if offset > nextoffset: -# # data is missing -# if allow_padding: -# data += padding * (offset - nextoffset) -# else: -# raise SequenceNumberError("Missing data for sequence number %d %s" % (nextoffset, self.addr)) -# elif offset < nextoffset: -# # data is overlapping -# if not allow_overlap: -# raise SequenceNumberError("Overlapping data for sequence number %d %s" % (nextoffset, self.addr)) -## nextoffset = (offset + len(segments[offset][dup])) & self.MAX_OFFSET -## if nextoffset in self.ack_sequence_numbers: -# if offset in self.ack_sequence_numbers: -# # If the data packet was acknowledged by the receiver, -# # we use the first packet received. -# dup = 0 -# else: -# # If it went unacknowledged, we use the last packet and hope -# # for the best. -# dup = -1 -# print(dup) -# print(offset) -# print(nextoffset) -# print(str(self.ack_sequence_numbers)) -# nextoffset = (offset + len(segments[offset][dup])) & self.MAX_OFFSET -# data = data[:offset - startoffset] + \ -# segments[offset][dup] + \ -# data[nextoffset - startoffset:] -# self.__data_bytes = data -# return data + # segments = {} + # for pkt in self.data_packets: + # if pkt.sequence_number: + # segments.setdefault(pkt.sequence_number, []).append(pkt.data) + # else: + # # if there are no sequence numbers (i.e. not TCP), just rebuild + # # in chronological order + # data += pkt.data + # + # if not segments: + # # For non-sequential protocols, just return what we have + # self.__data_bytes = data + # return data + # + # offsets = sorted(segments.keys()) + # + # # iterate over the segments and try to piece them together + # # handle any instances of missing or overlapping segments + # nextoffset = offsets[0] + # startoffset = offsets[0] + # for offset in offsets: + # # TODO do we still want to implement custom error handling? + # if offset > nextoffset: + # # data is missing + # if allow_padding: + # data += padding * (offset - nextoffset) + # else: + # raise SequenceNumberError("Missing data for sequence number %d %s" % (nextoffset, self.addr)) + # elif offset < nextoffset: + # # data is overlapping + # if not allow_overlap: + # raise SequenceNumberError("Overlapping data for sequence number %d %s" % (nextoffset, self.addr)) + ## nextoffset = (offset + len(segments[offset][dup])) & self.MAX_OFFSET + ## if nextoffset in self.ack_sequence_numbers: + # if offset in self.ack_sequence_numbers: + # # If the data packet was acknowledged by the receiver, + # # we use the first packet received. + # dup = 0 + # else: + # # If it went unacknowledged, we use the last packet and hope + # # for the best. + # dup = -1 + # print(dup) + # print(offset) + # print(nextoffset) + # print(str(self.ack_sequence_numbers)) + # nextoffset = (offset + len(segments[offset][dup])) & self.MAX_OFFSET + # data = data[:offset - startoffset] + \ + # segments[offset][dup] + \ + # data[nextoffset - startoffset:] + # self.__data_bytes = data + # return data def info(self): """ @@ -1432,9 +1704,15 @@ def info(self): d = dict(self.__dict__) del d['hidden'] del d['_Blob__data_bytes'] - del d['all_packets'] + del d['packets'] return d + + # TODO: Trying to determine if we should do this or take into account acknowledgement numbers + # like originally implemented. + # Perhaps rewrite their assemble to do some work in add_packet()? + # Do we want to ensure all segments are acknowledged or should we avoid that so we can handle + # partial/corrupt pcaps? def add_packet(self, packet): """ Accepts a Packet object and stores it. @@ -1442,7 +1720,76 @@ def add_packet(self, packet): Args: packet: a Packet object """ - self.all_packets.append(packet) + # Clear old data and segment cache. + self._data = None + self._segments = None - if packet.dt > self.endtime: - self.endtime = packet.dt + seq = packet.sequence_number + + # If packet is not TCP just add packet to list. + if seq is None: + self.packets.append(packet) + return + + # If this a new sequence number we haven't seen before, add it to the map. + if seq not in self._seq_map: + self._seq_map[seq] = packet + self.packets.append(packet) + return + + # Otherwise, if we already have the packet for the given sequence + # then we have a retransmission and will need to determine which packet to keep + # and possibly remove other packets if this packet overlaps them. + orig_packet = self._seq_map[seq] + + # ignore duplicate packet. + if len(packet.data) <= len(orig_packet.data): + # TODO: should we still handle duplicate packets. + logger.debug(f'Ignoring duplicate packet: {packet.frame}') + return + + # If this packet would create more inconsistencies in our sequence numbers (more holes) + # than the packet to be replaced, then this is most likely an out-of-order packet that the + # sender has ignored, and we should too. + orig_next_seq = seq + len(orig_packet.data) + next_seq = seq + len(packet.data) + if ( + next_seq < max(self.sequence_numbers) + and orig_packet.data + and next_seq not in self._seq_map + and orig_next_seq in self._seq_map + ): + logger.debug(f'Ignoring out-of-order packet: {packet.frame}') + return + + # Replace packet(s) with retransmitted packet + else: + # First add the retransmitted packet, replacing the original packet matching the + # sequence number. + logger.debug(f'Replacing packet {orig_packet.frame} with {packet.frame}') + self._seq_map[seq] = packet + self.packets = [packet if p.sequence_number == seq else p for p in self.packets] + + # Now remove any packets that contained data that is now part of the retransmitted packet. + packets_to_remove = [] + for seq_, packet_ in self._seq_map.items(): + if 0 < (seq_ - seq) < len(packet.data): + logger.debug(f'Removing packet: {packet_.frame}') + packets_to_remove.append(packet_) + # NOTE: need to remove packets outside the above loop because removing packets affect seq_map + for packet_ in packets_to_remove: + self._remove_packet(packet_) + + def _remove_packet(self, packet): + """ + Removes packet from Blob. (internal use only) + """ + # Clear old data and segment cache. + self._data = None + self._segments = None + + for seq, packet_ in list(self._seq_map.items()): + if packet_ == packet: + del self._seq_map[seq] + + self.packets.remove(packet) diff --git a/dshell/decode.py b/dshell/decode.py index 2afa423..2e7da66 100755 --- a/dshell/decode.py +++ b/dshell/decode.py @@ -19,35 +19,15 @@ of this largely takes place in the main() function. """ -# set up logging first, since some third-party libraries would try to -# configure things their own way -import logging -logging.basicConfig(format="%(levelname)s (%(name)s) - %(message)s") -logger = logging.getLogger("decode.py") - -# since pypacker handles its own exceptions (loudly), this attempts to keep -# it quiet -from pypacker import pypacker -pypacker.logger.setLevel(logging.CRITICAL) - -import dshell.core -from dshell.dshelllist import get_plugins, get_output_modules -from dshell.dshellargparse import DshellArgumentParser -from dshell.output.output import QueueOutputWrapper -from dshell.util import get_output_path - -import pcapy - # standard Python library imports import bz2 -import copy import faulthandler import gzip import multiprocessing +import logging import operator import os import queue -#import signal import sys import tempfile import zipfile @@ -55,12 +35,30 @@ from getpass import getpass from glob import glob from importlib import import_module +from typing import Iterable + +import pcapy +from pypacker.layer12 import ethernet, ppp, pppoe, ieee80211, linuxcc, radiotap, can +from pypacker.layer3 import ip, ip6 + +import dshell.core +from dshell.api import get_plugin_information +from dshell.core import Packet +from dshell.dshelllist import get_plugins, get_output_modules +from dshell.dshellargparse import DshellArgumentParser +from dshell.output.output import QueueOutputWrapper +from dshell.util import get_output_path +from tabulate import tabulate + +logger = logging.getLogger(__name__) + # plugin_chain will eventually hold the user-selected plugins that packets # will trickle through. plugin_chain = [] -def feed_plugin_chain(plugin_index, packet_tuple): + +def feed_plugin_chain(plugin_index: int, packet: Packet): """ Every packet fed into Dshell goes through this function. Its goal is to pass each packet down the chain of selected plugins. @@ -68,60 +66,19 @@ def feed_plugin_chain(plugin_index, packet_tuple): plugin, i.e. act as a filter. """ global plugin_chain - (pktlen, pkt, ts) = packet_tuple + current_plugin = plugin_chain[plugin_index] next_plugin_index = plugin_index + 1 if next_plugin_index >= len(plugin_chain): next_plugin_index = None - # Check the plugin's filter to see if this packet should go any further - if current_plugin.compiled_bpf and not current_plugin.compiled_bpf.filter(pkt): - return - - # Begin stepping through the plugin and feeding each handler function in - # order: - # raw_handler --> packet_handler -?-> connection_handler (init/blob_handler/close) - current_plugin._raw_handler(pktlen, pkt, ts) - - # feed any available raw packets to the packet_handler - while len(current_plugin.raw_packet_queue) > 0: - rawpacket = current_plugin.raw_packet_queue.pop(0) - current_plugin._packet_handler(*rawpacket) - - # Check if this plugin handles connections - # If it doesn't, we can just pass the packet to the next plugin now - if "_connection_handler" not in current_plugin.members: - if next_plugin_index: - while len(current_plugin.packet_queue) > 0: - packet = current_plugin.packet_queue.pop(0) - feed_plugin_chain(next_plugin_index, packet.packet_tuple) - return - - # Connection handlers are a little different. - # They only enqueue anything when a connection closes or times out. - while len(current_plugin.packet_queue) > 0: - packet = current_plugin.packet_queue.pop(0) - current_plugin._connection_handler(packet) - - # Connections are "passed" to the next plugin by popping off their blobs, - # then passing all of the packets within. - # Afterwards, the connection is cleared from the plugin's cache. - while len(current_plugin.connection_queue) > 0: - connection = current_plugin.connection_queue.pop(0) - if next_plugin_index: - for blob in connection.blobs: - if not blob.hidden: - for packet in blob.all_packets: - feed_plugin_chain(next_plugin_index, packet.packet_tuple) - conn_key = tuple(sorted(connection.addr)) - try: - # Attempt to clear out the connection, now that it has been handled. - del current_plugin.connection_tracker[conn_key] - except KeyError: - # If the plugin messed with the connection's address, it might - # fail to clear it. - # TODO find some way to better handle this scenario - pass + # Pass packet into plugin for processing. + current_plugin.consume_packet(packet) + + # Process produced packets. + if next_plugin_index: + for _packet in current_plugin.produce_packets(): + feed_plugin_chain(next_plugin_index, _packet) def clean_plugin_chain(plugin_index): @@ -135,19 +92,12 @@ def clean_plugin_chain(plugin_index): if next_plugin_index >= len(plugin_chain): next_plugin_index = None - # Check if the plugin handles connections - # If it does, close out its open connections and pass the stored packets - # down the chain. - if "_connection_handler" in current_plugin.members: - for connection_handler_out in current_plugin._cleanup_connections(): - if not connection_handler_out: - continue - if next_plugin_index: - for blob in connection_handler_out.blobs: - if not blob.hidden: - for packet in blob.all_packets: - feed_plugin_chain(next_plugin_index, packet.packet_tuple) + # need to flush even if there are no more plugins in the chain to ensure all packets are processed. + current_plugin.flush() + if next_plugin_index: + for _packet in current_plugin.produce_packets(): + feed_plugin_chain(next_plugin_index, _packet) clean_plugin_chain(next_plugin_index) @@ -179,41 +129,47 @@ def decompress_file(filepath, extension, unzipdir): tempfiles = [] for openfile in openfiles: - try: - # check if this file is actually something decompressable - openfile.peek(1) - except OSError as e: - logger.error("Could not process compressed file {!r}. {!s}".format(filepath, e)) - openfile.close() - continue - tfile = tempfile.NamedTemporaryFile(dir=unzipdir, delete=False, prefix=filename) - for piece in openfile: - tfile.write(piece) - tempfiles.append(tfile.name) - openfile.close() - tfile.close() + with openfile: + try: + # check if this file is actually something decompressable + openfile.peek(1) + except OSError as e: + logger.error("Could not process compressed file {!r}. {!s}".format(filepath, e)) + continue + with tempfile.NamedTemporaryFile(dir=unzipdir, delete=False, prefix=filename) as tfile: + for piece in openfile: + tfile.write(piece) + tempfiles.append(tfile.name) return tempfiles - def print_plugins(plugins): - "Print list of plugins with additional info" - row = "{:<40} {:15} {:<20} {:<20} {:<10} {}" - print(row.format('module', 'name', 'title', 'type', 'author', 'description')) - print('-' * 121) - for name, module in plugins.items(): - print(row.format(module.__module__, - name, - module.name, - module.__class__.__bases__[0].__name__, - module.author, - module.description)) - -def main(plugin_args={}, **kwargs): + """ + Print list of plugins with additional info. + """ + headers = ['module', 'name', 'title', 'type', 'author', 'description'] + rows = [] + for name, module in sorted(plugins.items()): + rows.append([ + module.__module__, + name, + module.name, + module.__class__.__bases__[0].__name__, + module.author, + module.description, + ]) + + print(tabulate(rows, headers=headers)) + + +def main(plugin_args=None, **kwargs): global plugin_chain + if not plugin_args: + plugin_args = {} + # dictionary of all available plugins: {name: module path} - plugin_map = get_plugins(logger) + plugin_map = get_plugins() # Attempt to catch segfaults caused when certain linktypes (e.g. 204) are # given to pcapy @@ -225,36 +181,27 @@ def main(plugin_args={}, **kwargs): plugin_chain[0].defrag_ip = kwargs.get("defrag", False) + # Setup logging + log_format = "%(levelname)s (%(name)s) - %(message)s" if kwargs.get("verbose", False): - logger.setLevel(logging.INFO) - dshell.core.logger.setLevel(logging.INFO) - dshell.core.geoip.logger.setLevel(logging.INFO) - # Activate verbose mode in each of the plugins - for plugin in plugin_chain: - plugin.out.set_level(logging.INFO) + log_level = logging.INFO + elif kwargs.get("debug", False): + log_level = logging.DEBUG + elif kwargs.get("quiet", False): + log_level = logging.CRITICAL + else: + log_level = logging.WARNING + logging.basicConfig(format=log_format, level=log_level) + + # since pypacker handles its own exceptions (loudly), this attempts to keep + # it quiet + logging.getLogger("pypacker").setLevel(logging.CRITICAL) if kwargs.get("allcc", False): # Activate all country code (allcc) mode to display all 3 GeoIP2 country # codes dshell.core.geoip.acc = True - if kwargs.get("debug", False): - pypacker.logger.setLevel(logging.WARNING) - logger.setLevel(logging.DEBUG) - dshell.core.logger.setLevel(logging.DEBUG) - dshell.core.geoip.logger.setLevel(logging.DEBUG) - # Activate debug mode in each of the plugins - for plugin in plugin_chain: - plugin.out.set_level(logging.DEBUG) - - if kwargs.get("quiet", False): - logger.disabled = True - dshell.core.logger.disabled = True - dshell.core.geoip.logger.disabled = True - # Disable logging for each of the plugins - for plugin in plugin_chain: - plugin.out.logger.disabled = True - dshell.core.geoip.check_file_dates() # If alternate output module is selected, tell each plugin to use that @@ -270,17 +217,12 @@ def main(plugin_args={}, **kwargs): else: oargs[oarg] = True try: + # TODO: Create a factory classmethod in the base Output class (e.g. "from_name()") instead. omodule = import_module("dshell.output."+kwargs["omodule"]) omodule = omodule.obj for plugin in plugin_chain: - oargs['label'] = plugin.__module__ + # TODO: Should we have a single instance of the Output module used by all plugins? oomodule = omodule(**oargs) - if kwargs.get("verbose", False): - oomodule.set_level(logging.INFO) - if kwargs.get("debug", False): - oomodule.set_level(logging.DEBUG) - if kwargs.get("quiet", False): - oomodule.logger.disabled = True plugin.out = oomodule except ImportError as e: logger.error("Could not import module named '{}'. Use --list-output flag to see available modules".format(kwargs["omodule"])) @@ -289,15 +231,7 @@ def main(plugin_args={}, **kwargs): # If writing to a file, set for each output module here if kwargs.get("outfile", None): for plugin in plugin_chain: - try: - plugin.out.reset_fh(filename=kwargs["outfile"]) - # Try and catch common exceptions to avoid lengthy tracebacks - except OSError as e: - if not self.debug: - logger.error(str(e)) - sys.exit(1) - else: - raise e + plugin.out.reset_fh(filename=kwargs["outfile"]) # Set nobuffer mode if that's what the user wants if kwargs.get("nobuffer", False): @@ -383,7 +317,7 @@ def main(plugin_args={}, **kwargs): processes = [] for i in inputs: processes.append( - multiprocessing.Process(target=process_files, args=([i]), kwargs=kwargs) + multiprocessing.Process(target=process_files, args=(i,), kwargs=kwargs) ) # Spawn processes, and keep track of which ones are running @@ -421,17 +355,142 @@ def main(plugin_args={}, **kwargs): plugin._postmodule() +# Maps datalink type reported by pcapy to a pypacker packet class. +datalink_map = { + 1: ethernet.Ethernet, + 9: ppp.PPP, + 51: pppoe.PPPoE, + 105: ieee80211.IEEE80211, + 113: linuxcc.LinuxCC, + 127: radiotap.Radiotap, + 204: ppp.PPP, + 227: can.CAN, + 228: ip.IP, + 229: ip6.IP6, +} + + +def read_packets(input: str, interface=False, bpf=None, count=None) -> Iterable[dshell.Packet]: + """ + Yields packets from input pcap file or device. + + :param str input: device or pcap file path + :param bool interface: Whether input is a device. + :param str bpf: Optional bpf filter. + :param int count: Optional max count of packets to read before exiting. + + :yields: packets defined by pypacker. + NOTE: Timestamp and frame id are added to packet for convenience. + """ + + if interface: + # Listen on an interface if the option is set + try: + capture = pcapy.open_live(input, 65536, True, 0) + except pcapy.PcapError as e: + # User probably doesn't have permission to listen on interface + # In any case, print just the error without traceback + logger.error(str(e)) + return + else: + # Otherwise, read from pcap file(s) + try: + capture = pcapy.open_offline(input) + except pcapy.PcapError as e: + logger.error("Could not open '{}': {!s}".format(input, e)) + return + + # TODO: We may want to allow all packets to go through and then allow the plugin to filter + # them out in feed_plugin_chain(). + # That way our frame_id won't be out of sync from skipped packets. + # Try and use the first plugin's BPF as the initial filter + # The BPFs for other plugins will be applied along the chain as needed + try: + if bpf: + capture.setfilter(bpf) + except pcapy.PcapError as e: + if str(e).startswith("no VLAN support for data link type"): + logger.error("Cannot use VLAN filters for {!r}. Recommend running with --no-vlan argument.".format(input)) + return + elif "syntax error" in str(e) or "link layer applied in wrong context" == str(e): + logger.error("Could not compile BPF: {!s} ({!r})".format(e, bpf)) + return + elif "802.11 link-layer types supported only on 802.11" == str(e): + logger.error("BPF incompatible with pcap file: {!s}".format(e)) + return + else: + raise e + + # Set the datalink layer for each plugin, based on the pcapy capture. + # Also compile a pcapy BPF object for each. + datalink = capture.datalink() + for plugin in plugin_chain: + # TODO Find way around libpcap bug that segfaults when certain BPFs + # are used with certain datalink types + # (e.g. datalink=204, bpf="ip") + plugin.link_layer_type = datalink + plugin.recompile_bpf() + + # Get correct pypacker class based on datalink layer. + packet_class = datalink_map.get(datalink, ethernet.Ethernet) + + logger.info(f"Datalink: {datalink} - {packet_class.__name__}") + + # Iterate over the file/interface and yield Packet objects. + frame = 1 # Start with 1 because Wireshark starts with 1. + while True: + try: + header, packet_data = capture.next() + if header is None and not packet_data: + # probably the end of the capture + break + if count and frame - 1 >= count: + # we've reached the maximum number of packets to process + break + + # Add timestamp and frame id to packet object for convenience. + pktlen = header.getlen() + s, us = header.getts() + ts = s + us / 1000000.0 + + # Wrap packet in dshell's Packet class. + packet = dshell.Packet(pktlen, packet_class(packet_data), ts, frame=frame) + frame += 1 + + yield packet + + except pcapy.PcapError as e: + estr = str(e) + eformat = "Error processing '{i}' - {e}" + if estr.startswith("truncated dump file"): + logger.error(eformat.format(i=input, e=estr)) + logger.debug(e, exc_info=True) + elif estr.startswith("bogus savefile header"): + logger.error(eformat.format(i=input, e=estr)) + logger.debug(e, exc_info=True) + else: + raise + break + + +# TODO: The use of kwargs makes it difficult to understand what arguments the function accept +# and difficult to follow the code flow. def process_files(inputs, **kwargs): # Iterate over each of the input files # For live capture, the "input" would just be the name of the interface global plugin_chain + interface = kwargs.get("interface", False) + count = kwargs.get("count", None) + # Try and use the first plugin's BPF as the initial filter + # The BPFs for other plugins will be applied along the chain as needed + bpf = plugin_chain[0].bpf while len(inputs) > 0: input0 = inputs.pop(0) # Check if file needs to be decompressed by its file extension extension = os.path.splitext(input0)[-1] - if extension in (".gz", ".bz2", ".zip") and not "interface" in kwargs: + if extension in (".gz", ".bz2", ".zip") and "interface" not in kwargs: tempfiles = decompress_file(input0, extension, kwargs.get("unzipdir", tempfile.gettempdir())) inputs = tempfiles + inputs continue @@ -439,79 +498,8 @@ def process_files(inputs, **kwargs): for plugin in plugin_chain: plugin._prefile(input0) - if kwargs.get("interface", None): - # Listen on an interface if the option is set - try: - capture = pcapy.open_live(input0, 65536, True, 0) - except pcapy.PcapError as e: - # User probably doesn't have permission to listen on interface - # In any case, print just the error without traceback - logger.error(str(e)) - sys.exit(1) - else: - # Otherwise, read from pcap file(s) - try: - capture = pcapy.open_offline(input0) - except pcapy.PcapError as e: - logger.error("Could not open '{}': {!s}".format(input0, e)) - continue - - # Try and use the first plugin's BPF as the initial filter - # The BPFs for other plugins will be applied along the chain as needed - initial_bpf = plugin_chain[0].bpf - try: - if initial_bpf: - capture.setfilter(initial_bpf) - except pcapy.PcapError as e: - if str(e).startswith("no VLAN support for data link type"): - logger.error("Cannot use VLAN filters for {!r}. Recommend running with --no-vlan argument.".format(input0)) - continue - elif "syntax error" in str(e) or "link layer applied in wrong context" == str(e): - logger.error("Could not compile BPF: {!s} ({!r})".format(e, initial_bpf)) - sys.exit(1) - elif "802.11 link-layer types supported only on 802.11" == str(e): - logger.error("BPF incompatible with pcap file: {!s}".format(e)) - continue - else: - raise e - - # Set the datalink layer for each plugin, based on the pcapy capture. - # Also compile a pcapy BPF object for each. - for plugin in plugin_chain: - # TODO Find way around libpcap bug that segfaults when certain BPFs - # are used with certain datalink types - # (e.g. datalink=204, bpf="ip") - plugin.set_link_layer_type(capture.datalink()) - plugin.recompile_bpf() - - # Iterate over the file/interface and pass the packets down the chain - while True: - try: - header, packet = capture.next() - if header == None and not packet: - # probably the end of the capture - break - if kwargs.get("count", 0) and plugin_chain[0].seen_packet_count.value >= kwargs["count"]: - # we've reached the maximum number of packets to process - break - pktlen = header.getlen() - ts = header.getts() - ts = ts[0] + ts[1] / 1000000.0 - feed_plugin_chain(0, (pktlen, packet, ts)) - except pcapy.PcapError as e: - estr = str(e) - eformat = "Error processing '{i}' - {e}" - if estr.startswith("truncated dump file"): - logger.error( eformat.format(i=input0, e=estr) ) - if kwargs.get("debug", False): - logger.exception(e) - elif estr.startswith("bogus savefile header"): - logger.error( eformat.format(i=input0, e=estr) ) - if kwargs.get("debug", False): - logger.exception(e) - else: - raise e - break + for packet in read_packets(input0, interface=interface, bpf=bpf, count=count): + feed_plugin_chain(0, packet) clean_plugin_chain(0) for plugin in plugin_chain: @@ -523,10 +511,18 @@ def process_files(inputs, **kwargs): plugin._postfile() +# TODO: Separate some of this logic outside of this function so we can call +# dshell as a library. def main_command_line(): + # Since plugin_chain contains the actual plugin instances we have to make sure + # we reset the global plugin_chain so multiple runs don't affect each other. + # (This was necessary to call this function through a python script.) + # TODO: Should plugin_chain be a list of plugin classes instead of instances? global plugin_chain + plugin_chain = [] + # dictionary of all available plugins: {name: module path} - plugin_map = get_plugins(logger) + plugin_map = get_plugins() # dictionary of plugins that the user wants to use: {name: object} active_plugins = OrderedDict() @@ -544,7 +540,7 @@ def main_command_line(): parser.add_argument('-acc', '--allcc', action="store_true", help="Show all 3 GeoIP2 country code types (represented_country/registered_country/country)") parser.add_argument('-d', '-p', '--plugin', dest='plugin', type=str, - action='append', metavar="DECODER", + action='append', metavar="PLUGIN", help="Use a specific plugin module. Can be chained with '+'.") parser.add_argument('--defragment', dest='defrag', action='store_true', help='Reconnect fragmented IP packets') @@ -613,7 +609,7 @@ def main_command_line(): parser.add_argument('--version', action='version', version="Dshell " + str(dshell.core.__version__)) parser_short.add_argument('-d', '-p', '--plugin', dest='plugin', type=str, - action='append', metavar="DECODER", + action='append', metavar="PLUGIN", help="Use a specific plugin module") parser_short.add_argument('--ebpf', default='', type=str, metavar="BPF", help="Extend existing BPFs with provided input for additional filtering. It will transform input into \"() and ()\"") @@ -623,6 +619,7 @@ def main_command_line(): help='List all available plugins', dest='list') parser_short.add_argument("--lo", "--list-output", action="store_true", help="List available output modules") + # FIXME: Should this duplicate option be removed? parser_short.add_argument("-o", "--omodule", type=str, metavar="MODULE", help="Use specified output module for plugins instead of defaults. For example, --omodule=jsonout for JSON output.") parser_short.add_argument('files', nargs='*', @@ -662,6 +659,9 @@ def main_command_line(): i += 1 plugin = plugin[:-(len(str(i-1)))] + str(i) # Add copy of plugin object to chain and add to argument parsers + # TODO: Use class attributes for class related things like name, description, optionsdict + # This way we don't have to initialize the plugin at this point and fixes a lot of the + # issues that arise that come from dealing with a singleton. active_plugins[plugin] = plugin_module.DshellPlugin() plugin_chain.append(active_plugins[plugin]) parser.add_plugin_arguments(plugin, active_plugins[plugin]) @@ -685,25 +685,15 @@ def main_command_line(): sys.exit() if opts.list: - # Import ALL of the plugins and print info about them before exiting - listing_plugins = OrderedDict() - for name, module in sorted(plugin_map.items(), key=operator.itemgetter(1)): - try: - module = import_module(module) - if not module.DshellPlugin: - continue - module = module.DshellPlugin() - listing_plugins[name] = module - except Exception as e: - logger.error("Could not load {!r}. ({!s})".format(module, e)) - if opts.debug: - logger.exception(e) - print_plugins(listing_plugins) + try: + print_plugins(get_plugin_information()) + except ImportError as e: + logger.error(e, exc_info=opts.debug) sys.exit() if opts.listoutput: # List available output modules and a brief description - output_map = get_output_modules(get_output_path(), logger) + output_map = get_output_modules(get_output_path()) for modulename in sorted(output_map): try: module = import_module("dshell.output."+modulename) @@ -738,5 +728,6 @@ def main_command_line(): main(plugin_args=plugin_args, **vars(opts)) + if __name__ == "__main__": main_command_line() diff --git a/dshell/dshellargparse.py b/dshell/dshellargparse.py index 82feaa0..afcc43c 100644 --- a/dshell/dshellargparse.py +++ b/dshell/dshellargparse.py @@ -5,6 +5,23 @@ import argparse + +def custom_bytes(value): + """ + Converts value strings for command lines that are suppose to be bytes. + If value startswith "0x", value will be assumed to be a hex string. + Otherwise data will be encoded with utf8 + """ + if isinstance(value, bytes): + return value + if value.startswith("0x"): + try: + return bytes.fromhex(value[2:]) + except ValueError: + pass # Wasn't hex after all, just treat as a utf8 string. + return value.encode("utf8") + + class DshellArgumentParser(argparse.ArgumentParser): def add_plugin_arguments(self, plugin_name, plugin_obj): @@ -19,6 +36,12 @@ def add_plugin_arguments(self, plugin_name, plugin_obj): group = self.add_argument_group(group) for argname, optargs in plugin_obj.optiondict.items(): optname = "{}_{}".format(plugin_name, argname) + data_type = optargs.get("type", None) + if data_type and data_type == bytes: + optargs["type"] = custom_bytes + default = optargs.get("default", None) + if default is not None: + optargs["default"] = custom_bytes(default) group.add_argument("--" + optname, dest=optname, **optargs) def get_plugin_arguments(self, plugin_name, plugin_obj): diff --git a/dshell/dshellgeoip.py b/dshell/dshellgeoip.py index f8c0bbe..0a61414 100644 --- a/dshell/dshellgeoip.py +++ b/dshell/dshellgeoip.py @@ -14,12 +14,14 @@ from dshell.util import get_data_path -class DshellGeoIP(object): +logger = logging.getLogger(__name__) + + +class DshellGeoIP(object): MAX_CACHE_SIZE = 5000 - def __init__(self, acc=False, logger=logging.getLogger("dshellgeoip.py")): - self.logger = logger + def __init__(self, acc=False): self.geodir = os.path.join(get_data_path(), 'GeoIP') self.geoccfile = os.path.join(self.geodir, 'GeoLite2-City.mmdb') self.geoasnfile = os.path.join(self.geodir, 'GeoLite2-ASN.mmdb') @@ -30,16 +32,20 @@ def __init__(self, acc=False, logger=logging.getLogger("dshellgeoip.py")): self.acc = acc def check_file_dates(self): - "Check the data file age, and log a warning if it's over a year old" + """ + Check the data file age, and log a warning if it's over a year old. + """ cc_mtime = datetime.datetime.fromtimestamp(os.path.getmtime(self.geoccfile)) asn_mtime = datetime.datetime.fromtimestamp(os.path.getmtime(self.geoasnfile)) n = datetime.datetime.now() year = datetime.timedelta(days=365) if (n - cc_mtime) > year or (n - asn_mtime) > year: - self.logger.debug("GeoIP data file(s) over a year old, and possibly outdated.") + logger.debug("GeoIP data file(s) over a year old, and possibly outdated.") def geoip_country_lookup(self, ip): - "Looks up the IP and returns the two-character country code." + """ + Looks up the IP and returns the two-character country code. + """ location = self.geoip_location_lookup(ip) return location[0] @@ -81,17 +87,17 @@ def geoip_location_lookup(self, ip): if self.acc: try: cc = "{}/{}/{}".format(location.represented_country.iso_code, - location.registered_country.iso_code, - location.country.iso_code) + location.registered_country.iso_code, + location.country.iso_code) cc = cc.replace("None", "--") except KeyError: pass else: cc = (location.represented_country.iso_code or - location.registered_country.iso_code or - location.country.iso_code or - '--') + location.registered_country.iso_code or + location.country.iso_code or + '--') location = ( cc, @@ -109,11 +115,13 @@ def geoip_location_lookup(self, ip): self.geo_loc_cache[ip] = location return location + class DshellFailedGeoIP(object): - "Class used in place of DshellGeoIP if GeoIP database files are not found." + """ + Class used in place of DshellGeoIP if GeoIP database files are not found. + """ - def __init__(self, logger=logging.getLogger("dshellgeoip.py")): - self.logger = logger + def __init__(self): self.geodir = os.path.join(get_data_path(), 'GeoIP') self.geoccdb = None self.geoasndb = None @@ -130,8 +138,12 @@ def geoip_asn_lookup(self, ip): def geoip_location_lookup(self, ip): return ("??", None, None) + class DshellGeoIPCache(OrderedDict): - "A cache for storing recent IP lookups to improve performance." + """ + A cache for storing recent IP lookups to improve performance. + """ + def __init__(self, *args, **kwargs): self.max_cache_size = kwargs.pop("max_cache_size", 500) OrderedDict.__init__(self, *args, **kwargs) diff --git a/dshell/dshelllist.py b/dshell/dshelllist.py index 450f14e..4841311 100644 --- a/dshell/dshelllist.py +++ b/dshell/dshelllist.py @@ -3,14 +3,18 @@ These are mostly used in decode.py and in unit tests """ +import logging import os import pkg_resources from glob import iglob from dshell.util import get_plugin_path -#def get_plugins(plugin_path, logger=None): -def get_plugins(logger=None): + +logger = logging.getLogger(__name__) + + +def get_plugins(): """ Generate a list of all available plugin modules, either in the dshell.plugins directory or external packages @@ -36,13 +40,14 @@ def get_plugins(logger=None): # Next, try to discover additional plugins installed externally. # Uses entry points in setup.py files. for ep_plugin in pkg_resources.iter_entry_points("dshell_plugins"): - if ep_plugin.name in plugins and logger: - logger.warning("Duplicate plugin name found: {}".format(name)) + if ep_plugin.name in plugins: + logger.warning("Duplicate plugin name found: {}".format(ep_plugin.name)) plugins[ep_plugin.name] = ep_plugin.module_name return plugins -def get_output_modules(output_module_path, logger=None): + +def get_output_modules(output_module_path): """ Generate a list of all available output modules under an output_module_path """ diff --git a/dshell/output/jsonout.py b/dshell/output/jsonout.py index 49014d9..f570e3b 100644 --- a/dshell/output/jsonout.py +++ b/dshell/output/jsonout.py @@ -6,6 +6,7 @@ import json from dshell.output.output import Output + class JSONOutput(Output): """ Converts arguments for every write into JSON diff --git a/dshell/output/output.py b/dshell/output/output.py index b543ab2..1387b9b 100644 --- a/dshell/output/output.py +++ b/dshell/output/output.py @@ -10,13 +10,17 @@ import sys from collections import defaultdict from datetime import datetime +import warnings -class Output(): + +logger = logging.getLogger(__name__) + + +class Output: """ Base-level output class Arguments: - label : name to use for logging.getLogger(label) format : 'format string' to override default formatstring for output class timeformat : 'format string' for datetime representation delim : set a delimiter for CSV or similar output @@ -31,36 +35,36 @@ class Output(): _DEFAULT_DELIM = ',' _DESCRIPTION = "Base output class" - def __init__(self, *args, **kwargs): - self.logger = logging.getLogger(kwargs.get("label", "dshell")) - + def __init__( + self, file=None, fh=None, mode='w', format=None, timeformat=None, delim=None, nobuffer=False, + noclobber=False, extra=None, **unused_kwargs + ): self.format_fields = [] - self.timeformat = kwargs.get('timeformat', self._DEFAULT_TIME_FORMAT) - self.delim = kwargs.get('delim', self._DEFAULT_DELIM) - self.nobuffer = kwargs.get('nobuffer', False) - self.noclobber = kwargs.get('noclobber', False) - self.mode = kwargs.get('mode', 'w') - self.extra = kwargs.get('extra', False) - - self.set_format( kwargs.get('format', self._DEFAULT_FORMAT) ) + self.timeformat = timeformat or self._DEFAULT_TIME_FORMAT + self.delim = delim or self._DEFAULT_DELIM + self.nobuffer = nobuffer + self.noclobber = noclobber + self.extra = extra + self.mode = mode + + # Must define attributes even if they are setup in different function. + self.format_fields = None + self.format = None + self.set_format(format or self._DEFAULT_FORMAT) # Set the filehandle for any output - f = None - if 'fh' in kwargs: - self.fh = kwargs['fh'] + if fh: + self.fh = fh return - elif 'file' in kwargs: - f = kwargs['file'] - elif len(args) > 0: - f = args[0] + + f = file if f: if self.noclobber: - f = self.__incrementFilename(f) + f = self._increment_filename(f) self.fh = open(f, self.mode) else: self.fh = sys.stdout - def reset_fh(self, filename=None, fh=None, mode=None): """ Alter the module's open file handle without changing any of the other @@ -71,33 +75,29 @@ def reset_fh(self, filename=None, fh=None, mode=None): self.fh = fh elif filename: if self.noclobber: - filename = self.__incrementFilename(filename) + filename = self._increment_filename(filename) if mode: self.mode = mode self.fh = open(filename, mode) else: self.fh = open(filename, self.mode) - def set_level(self, lvl): - "Set the logging level. Just a wrapper around logging.setLevel(lvl)." - self.logger.setLevel(lvl) - def set_format(self, fmt): - "Set the output format to a new format string" + """Set the output format to a new format string""" # Use a regular expression to identify all fields that the format will # populate, based on limited printf-style formatting. # https://docs.python.org/3/library/stdtypes.html#old-string-formatting regexmatch = "%\((?P.*?)\)[diouxXeEfFgGcrs]" self.format_fields = re.findall(regexmatch, fmt) - self.format = fmt - def __incrementFilename(self, filename): + def _increment_filename(self, filename): """ Used with the noclobber argument. Creates a distinct filename by appending a sequence number. """ try: + # FIXME: Should n be incremented in the loop? while os.stat(filename): p = filename.rsplit('-', 1) try: @@ -117,16 +117,20 @@ def setup(self): pass def close(self): - "Close output file, assuming it's not stdout" + """Close output file, assuming it's not stdout""" if self.fh not in (sys.stdout, sys.stdout.buffer): self.fh.close() + # NOTE: Output modules no longer handles logging. Logging should be done by creating a logger + # at the top of each of the modules. + # If we want to change the destination of the log messages we can create a log handler. def log(self, msg, level=logging.INFO, *args, **kwargs): """ Write a message to the log Passes all args and kwargs thru to logging, except for 'level' """ - self.logger.log(level, msg, *args, **kwargs) + warnings.warn("Please create and use a logger using the logging module instead", DeprecationWarning) + logger.log(level, msg, *args, **kwargs) def convert(self, *args, **kwargs): """ @@ -190,7 +194,7 @@ def convert(self, *args, **kwargs): return output def write(self, *args, **kwargs): - "Primary output function. Should be overwritten by subclasses." + """Primary output function. Should be overwritten by subclasses.""" line = self.convert(*args, **kwargs) try: self.fh.write(line) @@ -204,6 +208,7 @@ def alert(self, *args, **kwargs): DEPRECATED Use the write function of the AlertOutput class """ + warnings.warn("Use the write function of the AlertOutput class", DeprecationWarning) self.write(*args, **kwargs) def dump(self, *args, **kwargs): @@ -211,10 +216,10 @@ def dump(self, *args, **kwargs): DEPRECATED Use the write function of the PCAPOutput class """ + warnings.warn("Use the write function of the PCAPOutput class", DeprecationWarning) self.write(*args, **kwargs) - class QueueOutputWrapper(object): """ Wraps an instance of any other Output-like object to make its diff --git a/dshell/plugins/dnsplugin.py b/dshell/plugins/dnsplugin.py index 48da51b..613ddf6 100644 --- a/dshell/plugins/dnsplugin.py +++ b/dshell/plugins/dnsplugin.py @@ -8,12 +8,15 @@ handler for a custom plugin, such as dns.py, to use. """ +import logging + import dshell.core as dshell from pypacker.pypacker import dns_name_decode from pypacker.layer567 import dns -import struct +logger = logging.getLogger(__name__) + def basic_cname_decode(request, answer): """ @@ -41,6 +44,7 @@ def basic_cname_decode(request, answer): rebuilt = answer[:answer.index(b"\xc0")] + snip return dns_name_decode(rebuilt) + class DNSPlugin(dshell.ConnectionPlugin): """ A base-level plugin that overwrites the connection_handler in @@ -57,7 +61,7 @@ def connection_handler(self, conn): id_to_packets_map = {} for blob in conn.blobs: - for pkt in blob.all_packets: + for pkt in blob.packets: packet = pkt.pkt if not isinstance(packet.highest_layer, dns.DNS): # First packet is not DNS, so we don't care @@ -87,17 +91,19 @@ def connection_handler(self, conn): # remove packets from connections that dns_handler did not like for blob in id_to_blob_map[id]: for pkt in id_to_packets_map[id]: - try: blob.all_packets.remove(pkt) - except ValueError: continue + try: + blob.packets.remove(pkt) + except ValueError: + continue else: for blob in id_to_blob_map[id]: blob.hidden = False try: if dns_handler_out and not isinstance(dns_handler_out[0], dshell.Connection): - self.warn("The output from {} dns_handler must be a list with a dshell.Connection as the first element! Chaining plugins from here may not be possible.".format(self.name)) + logger.warning("The output from {} dns_handler must be a list with a dshell.Connection as the first element! Chaining plugins from here may not be possible.".format(self.name)) continue except TypeError: - self.warn("The output from {} dns_handler must be a list with a dshell.Connection as the first element! Chaining plugins from here may not be possible.".format(self.name)) + logger.warning("The output from {} dns_handler must be a list with a dshell.Connection as the first element! Chaining plugins from here may not be possible.".format(self.name)) continue keep_connection = True if keep_connection: @@ -121,4 +127,5 @@ def dns_handler(self, conn, requests, responses): """ return (conn, requests, responses) + DshellPlugin = None diff --git a/dshell/plugins/filter/country.py b/dshell/plugins/filter/country.py index 47f90ec..1111ef1 100644 --- a/dshell/plugins/filter/country.py +++ b/dshell/plugins/filter/country.py @@ -2,11 +2,16 @@ A filter for connections by IP address country code. Will generally be chained with other plugins. """ +import logging import dshell.core from dshell.output.netflowout import NetflowOutput +logger = logging.getLogger(__name__) + + class DshellPlugin(dshell.core.ConnectionPlugin): + def __init__(self, *args, **kwargs): super().__init__( name="Country Filter", @@ -59,7 +64,7 @@ def premodule(self): # Several of the args are mutually exclusive # Check if more than one is set, and print a warning if so if (self.neither + self.both + self.notboth) > 1: - self.warn("Can only use one of these args at a time: 'neither', 'both', or 'notboth'") + logger.warning("Can only use one of these args at a time: 'neither', 'both', or 'notboth'") def connection_handler(self, conn): # If no country code specified, pass all traffic through @@ -99,4 +104,4 @@ def connection_handler(self, conn): if __name__ == "__main__": - print (DshellPlugin()) + print(DshellPlugin()) diff --git a/dshell/plugins/filter/track.py b/dshell/plugins/filter/track.py index eeab990..2bf8ee7 100644 --- a/dshell/plugins/filter/track.py +++ b/dshell/plugins/filter/track.py @@ -3,11 +3,15 @@ generally chained with other plugins. """ +import logging +import ipaddress +import sys + import dshell.core from dshell.output.alertout import AlertOutput -import ipaddress -import sys +logger = logging.getLogger(__name__) + class DshellPlugin(dshell.core.ConnectionPlugin): def __init__(self, **kwargs): @@ -114,8 +118,8 @@ def premodule(self): if self.source: for sstr in self.source: self.sources.extend(self.__split_ips(sstr)) - self.debug("targets: {!s}".format(self.targets)) - self.debug("sources: {!s}".format(self.sources)) + logger.debug("targets: {!s}".format(self.targets)) + logger.debug("sources: {!s}".format(self.sources)) def connection_handler(self, conn): if self.targets: diff --git a/dshell/plugins/flows/largeflows.py b/dshell/plugins/flows/largeflows.py index ee40046..d9161f3 100644 --- a/dshell/plugins/flows/largeflows.py +++ b/dshell/plugins/flows/largeflows.py @@ -3,9 +3,14 @@ Megabyte threshold can be updated by the user. """ +import logging + import dshell.core from dshell.output.netflowout import NetflowOutput +logger = logging.getLogger(__name__) + + class DshellPlugin(dshell.core.ConnectionPlugin): def __init__(self): @@ -25,10 +30,10 @@ def __init__(self): def premodule(self): if self.size <= 0: - self.warn("Cannot have a size that's less than or equal to zero (size: {}). Setting to 1.".format(self.size)) + logger.warning("Cannot have a size that's less than or equal to zero (size: {}). Setting to 1.".format(self.size)) self.size = 1 self.min = 1048576 * self.size - self.debug("Input: {}, Final size: {} bytes".format(self.size, self.min)) + logger.debug("Input: {}, Final size: {} bytes".format(self.size, self.min)) def connection_handler(self, conn): if conn.clientbytes + conn.serverbytes >= self.min: diff --git a/dshell/plugins/flows/longflows.py b/dshell/plugins/flows/longflows.py index 3bccfc9..da04f31 100644 --- a/dshell/plugins/flows/longflows.py +++ b/dshell/plugins/flows/longflows.py @@ -3,9 +3,14 @@ Minute threshold can be updated by the user. """ +import logging + import dshell.core from dshell.output.netflowout import NetflowOutput +logger = logging.getLogger(__name__) + + class DshellPlugin(dshell.core.ConnectionPlugin): def __init__(self): @@ -26,7 +31,7 @@ def __init__(self): def premodule(self): if self.len <= 0: - self.warn("Cannot have a time that's less than or equal to zero (size: {}). Setting to 5.".format(self.len)) + logger.warning("Cannot have a time that's less than or equal to zero (size: {}). Setting to 5.".format(self.len)) self.len = 5 self.secs = 60 * self.len diff --git a/dshell/plugins/flows/reverseflows.py b/dshell/plugins/flows/reverseflows.py index 921458a..3414720 100644 --- a/dshell/plugins/flows/reverseflows.py +++ b/dshell/plugins/flows/reverseflows.py @@ -21,10 +21,15 @@ Generates an alert for all client transmissions that are 61 times greater than the server transmission. """ +import logging import dshell.core from dshell.output.alertout import AlertOutput + +logger = logging.getLogger(__name__) + + class DshellPlugin(dshell.core.ConnectionPlugin): def __init__(self): @@ -69,10 +74,10 @@ def __init__(self): def premodule(self): if self.threshold < 0: - self.warn("Cannot have a negative threshold. Defaulting to 3.0. (threshold: {0})".format(self.threshold)) + logger.warning("Cannot have a negative threshold. Defaulting to 3.0. (threshold: {0})".format(self.threshold)) self.threshold = 3.0 elif not self.threshold: - self.warn("Threshold not set. Displaying all client-server transmissions (threshold: {0})".format(self.threshold)) + logger.warning("Threshold not set. Displaying all client-server transmissions (threshold: {0})".format(self.threshold)) def connection_handler(self, conn): if conn.clientbytes < self.minimum: diff --git a/dshell/plugins/http/httpdump.py b/dshell/plugins/http/httpdump.py index 1aeeb4a..fcf200a 100644 --- a/dshell/plugins/http/httpdump.py +++ b/dshell/plugins/http/httpdump.py @@ -128,7 +128,7 @@ def http_handler(self, conn, request, response): msg.append(dshell.util.printable_text(str(post_params))) elif request.body: msg.append("POST Body:") - request_body = dshell.util.printable_text(request_body) + request_body = dshell.util.printable_text(request.body) if self.maxpost > 0 and len(request.body) > self.maxpost: msg.append("{}[truncated]".format(request_body[:self.maxpost])) else: diff --git a/dshell/plugins/http/riphttp.py b/dshell/plugins/http/riphttp.py index d5b5ccf..582efda 100644 --- a/dshell/plugins/http/riphttp.py +++ b/dshell/plugins/http/riphttp.py @@ -3,12 +3,16 @@ files. """ +import logging +import os +import re +import sys + from dshell.plugins.httpplugin import HTTPPlugin from dshell.output.alertout import AlertOutput -import os -import sys -import re +logger = logging.getLogger(__name__) + class DshellPlugin(HTTPPlugin): def __init__(self): @@ -43,7 +47,7 @@ def __init__(self): def premodule(self): if self.direction not in ('cs', 'sc', None): - self.error("Invalid value for direction: {!r}. Argument must be either 'sc' for server-to-client or 'cs' for client-to-server.".format(self.direction)) + logger.warning("Invalid value for direction: {!r}. Argument must be either 'sc' for server-to-client or 'cs' for client-to-server.".format(self.direction)) sys.exit(1) if self.content_filter: @@ -81,7 +85,7 @@ def http_handler(self, conn, request, response): if url in self.openfiles: # File is already open, so just insert the new data s, e = self.openfiles[url].handleresponse(response) - self.debug("{0!r} --> Range: {1} - {2}".format(url, s, e)) + logger.debug("{0!r} --> Range: {1} - {2}".format(url, s, e)) else: # A new file! filename = request.uri.split('?', 1)[0].split('/')[-1] @@ -100,13 +104,14 @@ def http_handler(self, conn, request, response): self.write("New file {} ({})".format(filename, url), **conn.info(), dir_arrow="<-") self.openfiles[url] = HTTPFile(os.path.join(self.outdir, filename), self) s, e = self.openfiles[url].handleresponse(payload) - self.debug("{0!r} --> Range: {1} - {2}".format(url, s, e)) + logger.debug("{0!r} --> Range: {1} - {2}".format(url, s, e)) if self.openfiles[url].done(): self.write("File done {} ({})".format(filename, url), **conn.info(), dir_arrow="<-") del self.openfiles[url] return conn, request, response + class HTTPFile(object): """ An internal class used to hold metadata for open HTTP files. diff --git a/dshell/plugins/httpplugin.py b/dshell/plugins/httpplugin.py index 99fe472..f7b7d19 100644 --- a/dshell/plugins/httpplugin.py +++ b/dshell/plugins/httpplugin.py @@ -9,6 +9,8 @@ to the http_handler. """ +import logging + import dshell.core from pypacker.layer567 import http @@ -16,6 +18,10 @@ import gzip import io + +logger = logging.getLogger(__name__) + + def parse_headers(obj, f): """Return dict of HTTP headers parsed from a file object.""" # Logic lifted mostly from dpkt's http module @@ -28,7 +34,7 @@ def parse_headers(obj, f): break l = line.split(None, 1) if not l[0].endswith(':'): - obj.errors.append(dshell.core.DataError("Invalid header {!r}".format(line))) + raise dshell.core.DataError("Invalid header {!r}".format(line)) k = l[0][:-1].lower() v = len(l) != 1 and l[1] or '' if k in d: @@ -39,6 +45,7 @@ def parse_headers(obj, f): d[k] = v return d + def parse_body(obj, f, headers): """Return HTTP body parsed from a file object, given HTTP header dict.""" # Logic lifted mostly from dpkt's http module @@ -50,6 +57,9 @@ def parse_body(obj, f, headers): sz = f.readline().split(None, 1)[0] except IndexError: obj.errors.append(dshell.core.DataError('missing chunk size')) + # FIXME: If this error occurs sz is not available to continue parsing! + # The appropriate exception should be thrown. + raise n = int(sz, 16) if n == 0: found_end = True @@ -61,7 +71,7 @@ def parse_body(obj, f, headers): else: break if not found_end: - obj.errors.append(dshell.core.DataError('premature end of chunked body')) + raise dshell.core.DataError('premature end of chunked body') body = b''.join(l) elif 'content-length' in headers: n = int(headers['content-length']) @@ -75,6 +85,7 @@ def parse_body(obj, f, headers): body = b'' return body + class HTTPRequest(object): """ A class for HTTP requests @@ -127,6 +138,7 @@ def __init__(self, blob): self.headers = parse_headers(self, data) self.body = parse_body(self, data, self.headers) + class HTTPResponse(object): """ A class for HTTP responses @@ -174,6 +186,9 @@ def decompress_gzip_content(self): try: iobody = io.BytesIO(self.body) except TypeError as e: + # TODO: Why would body ever not be bytes? If it's not bytes, then that means + # we have a bug somewhere in the code and therefore should just allow the + # original exception to be raised. self.errors.append(dshell.core.DataError("Body was not a byte string ({!s}). Could not decompress.".format(type(self.body)))) return try: @@ -203,7 +218,7 @@ def connection_handler(self, conn): request = None response = None for blob in conn.blobs: - blob.reassemble(allow_overlap=True, allow_padding=True) + # blob.reassemble(allow_overlap=True, allow_padding=True) if not blob.data: continue if blob.direction == 'cs': diff --git a/dshell/plugins/malware/sweetorange.py b/dshell/plugins/malware/sweetorange.py index f45e328..7777b3e 100644 --- a/dshell/plugins/malware/sweetorange.py +++ b/dshell/plugins/malware/sweetorange.py @@ -14,10 +14,13 @@ http://malware-traffic-analysis.net/2014/09/25/index.html """ +import logging +import re + from dshell.output.alertout import AlertOutput from dshell.plugins.httpplugin import HTTPPlugin -import re +logger = logging.getLogger(__name__) class DshellPlugin(HTTPPlugin): @@ -51,7 +54,7 @@ def premodule(self): self.sig_regex = re.compile( r"var (" + '|'.join(map(re.escape, self.variable)) + ")='(.*?)';") self.hexregex = re.compile(r'[^a-fA-F0-9]') - self.debug('Variable regex: "%s"' % self.sig_regex.pattern) + logger.debug('Variable regex: "%s"' % self.sig_regex.pattern) def http_handler(self, conn, request, response): try: @@ -76,7 +79,8 @@ def http_handler(self, conn, request, response): # between encoded/decoded strings hidden = "\x1b[37;2m%s\x1b[0m" % hidden match = "\x1b[32m%s\x1b[0m" % match - self.log(hidden) + + logger.info(hidden) self.write(match, **conn.info()) return (conn, request, response) diff --git a/dshell/plugins/misc/pcapwriter.py b/dshell/plugins/misc/pcapwriter.py index 2407bc9..95bedc3 100644 --- a/dshell/plugins/misc/pcapwriter.py +++ b/dshell/plugins/misc/pcapwriter.py @@ -14,10 +14,13 @@ (decode -d web+pcapwriter ~/pcap/*) """ +import logging +import struct + import dshell.core -from dshell.output.pcapout import PCAPOutput -import sys +logger = logging.getLogger(__name__) + class DshellPlugin(dshell.core.PacketPlugin): @@ -32,12 +35,11 @@ def __init__(self, *args, **kwargs): Use --pcapwriter_outfile to separate its output from that of other plugins. Example uses include: - - merging multiple pcap files into one (decode -d pcapwriter ~/pcap/* >merged.pcap) + - merging multiple pcap files into one (decode -d pcapwriter ~/pcap/* --pcapwriter_outfile=merged.pcap) - saving relevant traffic by chaining with another plugin (decode -d track+pcapwriter --track_source=192.168.1.1 --pcapwriter_outfile=merged.pcap ~/pcap/*) - getting pcap output from plugins that can't use pcapout (decode -d web+pcapwriter ~/pcap/*) """, author="dev195", - output=PCAPOutput(label=__name__), optiondict={ "outfile": { "type": str, @@ -46,19 +48,41 @@ def __init__(self, *args, **kwargs): } } ) + self.outfile = None # Filled in with constructor + self.pcap_fh = None + + def prefile(self, infile=None): + # Default to setting pcap output filename based on first input file. + if not self.outfile: + self.outfile = (infile or self.current_pcap_file) + ".pcap" + + def packet_handler(self, packet: dshell.Packet): + # If we don't have a pcap file handle, this is our first packet. + # Create the output pcap file handle. + # NOTE: We want to create the file on the first packet instead of premodule so we + # have a chance to use the input file as part of our output filename. + if not self.pcap_fh: + self.pcap_fh = open(self.outfile, mode="wb") + link_layer_type = self.link_layer_type or 1 + # write the header: + # magic_number, version_major, version_minor, thiszone, sigfigs, + # snaplen, link-layer type + self.pcap_fh.write( + struct.pack('IHHIIII', 0xa1b2c3d4, 2, 4, 0, 0, 65535, link_layer_type)) + + ts = packet.ts + rawpkt = packet.rawpkt + pktlen = packet.pktlen + self.pcap_fh.write(struct.pack('II', int(ts), int((ts - int(ts)) * 1000000))) + self.pcap_fh.write(struct.pack('II', len(rawpkt), pktlen)) + self.pcap_fh.write(rawpkt) + + return packet + + def postmodule(self): + if self.pcap_fh: + self.pcap_fh.close() - def premodule(self): - if self.outfile: - try: - self.out.reset_fh(filename=self.outfile, mode='wb') - except OSError as e: - self.error(str(e)) - sys.exit(1) - - def raw_handler(self, pktlen, pkt, ts): - rawpkt = pkt.header_bytes + pkt.body_bytes - self.write(pktlen=pktlen, rawpkt=rawpkt, ts=ts, link_layer_type=self.link_layer_type) - return pktlen, pkt, ts if __name__ == "__main__": print(DshellPlugin()) diff --git a/dshell/plugins/misc/xor.py b/dshell/plugins/misc/xor.py index 8e98385..e4fa438 100644 --- a/dshell/plugins/misc/xor.py +++ b/dshell/plugins/misc/xor.py @@ -3,11 +3,15 @@ for different data directions. """ +import logging +import struct + import dshell.core import dshell.util from dshell.output.output import Output -import struct +logger = logging.getLogger(__name__) + class DshellPlugin(dshell.core.ConnectionPlugin): def __init__(self): @@ -53,7 +57,7 @@ def __make_key(self, key): try: newkey += struct.pack('B', int(oldkey[i:i + 2], 16)) except ValueError as e: - self.warn("Error converting hex. Will treat as raw string. - {!s}".format(e)) + logger.warning("Error converting hex. Will treat as raw string. - {!s}".format(e)) newkey = key.encode('ascii') break else: @@ -64,7 +68,7 @@ def __make_key(self, key): except ValueError: # otherwise, convert string key to bytes as it is newkey = key.encode('ascii') - self.debug("__make_key: {!r} -> {!r}".format(key, newkey)) + logger.debug("__make_key: {!r} -> {!r}".format(key, newkey)) return newkey def premodule(self): @@ -83,10 +87,11 @@ def connection_handler(self, conn): key = self.cskey else: key = self.key - for pkt in blob.all_packets: + for pkt in blob.packets: # grab the data from the TCP layer and down - data = pkt.pkt.upper_layer.upper_layer.body_bytes - self.debug("Original:\n{}".format(dshell.util.hex_plus_ascii(data))) + data = pkt.data + # data = pkt.pkt.upper_layer.upper_layer.body_bytes + logger.debug("Original:\n{}".format(dshell.util.hex_plus_ascii(data))) # XOR the data and store it in new_data new_data = b'' for i in range(len(data)): @@ -95,7 +100,8 @@ def connection_handler(self, conn): x = data[i] ^ key[key_index] new_data += struct.pack('B', x) key_index = (key_index + 1) % len(key) - # rebuild the packet by adding together each of the layers - pkt.rawpkt = pkt.pkt.header_bytes + pkt.pkt.upper_layer.header_bytes + pkt.pkt.upper_layer.upper_layer.header_bytes + new_data - self.debug("New:\n{}".format(dshell.util.hex_plus_ascii(new_data))) + pkt.data = new_data + # # rebuild the packet by adding together each of the layers + # pkt.rawpkt = pkt.pkt.header_bytes + pkt.pkt.upper_layer.header_bytes + pkt.pkt.upper_layer.upper_layer.header_bytes + new_data + logger.debug("New:\n{}".format(dshell.util.hex_plus_ascii(new_data))) return conn diff --git a/dshell/plugins/nbns/nbns.py b/dshell/plugins/nbns/nbns.py index 413c3ff..81c9d21 100644 --- a/dshell/plugins/nbns/nbns.py +++ b/dshell/plugins/nbns/nbns.py @@ -2,10 +2,13 @@ NBNS plugin """ +import logging +from struct import unpack + import dshell.core from dshell.output.alertout import AlertOutput -from struct import unpack +logger = logging.getLogger(__name__) # A few common NBNS Protocol Info Opcodes @@ -90,8 +93,8 @@ def packet_handler(self, pkt): nbns_packet = pkt.pkt.upper_layer try: nbns_packet = nbns_packet.upper_layer - except (IndexError) as e: - self.out.log('{}: could not parse session data \ + except IndexError as e: + logger.error('{}: could not parse session data \ (NBNS packet not found)'.format(str(e))) # pypacker may throw an Exception here; could use # further testing @@ -102,8 +105,8 @@ def packet_handler(self, pkt): # It is represented as 32-bytes half-ASCII try: nbns_name = unpack('32s', pkt.data[13:45])[0] - except error as e: - self.out.log('{}: (NBNS packet not found)'.format(str(e))) + except Exception as e: + logger.error('{}: (NBNS packet not found)'.format(str(e))) return @@ -122,7 +125,7 @@ def packet_handler(self, pkt): self.client_hostname = str(nbns_name) except ValueError as e: - self.out.log('{}: Hostname in improper format \ + logger.error('{}: Hostname in improper format \ (NBNS packet not found)'.format(str(e))) return @@ -156,5 +159,6 @@ def packet_handler(self, pkt): self.xid, self.prot_info, self.client_hostname, self.mac_address), **pkt.info(), dir_arrow='->') return pkt + if __name__ == "__main__": print(DshellPlugin()) diff --git a/dshell/plugins/protocol/bitcoin.py b/dshell/plugins/protocol/bitcoin.py index 015be19..0547eb9 100644 --- a/dshell/plugins/protocol/bitcoin.py +++ b/dshell/plugins/protocol/bitcoin.py @@ -7,6 +7,9 @@ import json from struct import unpack +import logging + +logger = logging.getLogger(__name__) # Magic values used to determine Bitcoin Network Type @@ -128,7 +131,7 @@ def blob_handler(self, conn, blob): data_str = ''.join(chr(x) for x in data) data_len = len(data) except: - self.out.log('could not parse session data') + logger.error('could not parse session data') return # Only continue if the packet contains data @@ -185,9 +188,9 @@ def blob_handler(self, conn, blob): clean_jobs] except KeyError as e: - self.out.log("{} - Error extracting auth ID".format(str(e))) + logger.error("{} - Error extracting auth ID".format(str(e))) except ValueError as e: - self.out.log('{} - json data not found'.format(str(e))) + logger.error('{} - json data not found'.format(str(e))) return @@ -198,7 +201,7 @@ def blob_handler(self, conn, blob): magic_val = data[0:4].hex().upper() magic_val = ' '.join([magic_val[i:i+2] for i in range(0, len(magic_val), 2)]) except: - self.out.log('could not parse session data') + logger.error('could not parse session data') return # Attempt to translate first 4 bytes of payload into a Bitcoin (bc) diff --git a/dshell/plugins/protocol/ether.py b/dshell/plugins/protocol/ether.py index b6e5826..2b83fed 100644 --- a/dshell/plugins/protocol/ether.py +++ b/dshell/plugins/protocol/ether.py @@ -3,11 +3,16 @@ recommended that oui.txt be included in the share/ directory (see README). """ +import logging import os + import dshell.core from dshell.output.output import Output from dshell.util import get_data_path +logger = logging.getLogger(__name__) + + class DshellPlugin(dshell.core.PacketPlugin): OUTPUT_FORMAT = "[%(plugin)s] %(dt)s %(sip)-15s %(smac)-18s %(smac_org)-35s -> %(dip)-15s %(dmac)-18s %(dmac_org)-35s %(byte_count)d\n" @@ -41,7 +46,7 @@ def premodule(self): except FileNotFoundError: # user probably did not download it # print warning and continue - self.warn("Could not find {} (see README). Will not be able to determine MAC organizations.".format(ouifilepath)) + logger.warning("Could not find {} (see README). Will not be able to determine MAC organizations.".format(ouifilepath)) def packet_handler(self, pkt): if not pkt.smac or not pkt.dmac: @@ -62,5 +67,6 @@ def packet_handler(self, pkt): self.write("", smac_org=smac_org, dmac_org=dmac_org, **pkt.info()) return pkt + if __name__ == "__main__": print(DshellPlugin()) diff --git a/dshell/plugins/protocol/ip.py b/dshell/plugins/protocol/ip.py index 607c2ed..749d5a4 100644 --- a/dshell/plugins/protocol/ip.py +++ b/dshell/plugins/protocol/ip.py @@ -2,10 +2,15 @@ Outputs all IPv4/IPv6 traffic, and hex plus ascii with verbose flag """ +import logging + import dshell.core import dshell.util from dshell.output.alertout import AlertOutput +logger = logging.getLogger(__name__) + + class DshellPlugin(dshell.core.PacketPlugin): def __init__(self): @@ -20,5 +25,5 @@ def __init__(self): def packet_handler(self, packet): self.write(**packet.info(), dir_arrow='->') # If verbose flag set, outputs packet contents in hex and ascii alongside packet info - self.out.log("\n" + dshell.util.hex_plus_ascii(packet.rawpkt)) + logger.info("\n" + dshell.util.hex_plus_ascii(packet.rawpkt)) return packet diff --git a/dshell/plugins/tftp/tftp.py b/dshell/plugins/tftp/tftp.py index de5e9dd..d29a1fc 100644 --- a/dshell/plugins/tftp/tftp.py +++ b/dshell/plugins/tftp/tftp.py @@ -38,14 +38,17 @@ filenames when saved """ +import logging +import os +import struct + +from pypacker.layer4 import udp + import dshell.core import dshell.util from dshell.output.alertout import AlertOutput -from pypacker.layer4 import udp - -import os -import struct +logger = logging.getLogger(__name__) class DshellPlugin(dshell.core.PacketPlugin): @@ -106,8 +109,8 @@ def premodule(self): def postmodule(self): "cleanup any unfinished streams" - self.debug("Unset Read Streams: {!s}".format(self.unset_read_streams)) - self.debug("Unset Write Streams: {!s}".format(self.unset_write_streams)) + logger.debug("Unset Read Streams: {!s}".format(self.unset_read_streams)) + logger.debug("Unset Write Streams: {!s}".format(self.unset_write_streams)) while(len(self.open_streams) > 0): k = list(self.open_streams)[0] self.__closeStream(k, "POSSIBLY INCOMPLETE") diff --git a/dshell/util.py b/dshell/util.py index 37669bc..5ed2ded 100644 --- a/dshell/util.py +++ b/dshell/util.py @@ -5,6 +5,7 @@ import os import string + def xor(xinput, key): """ Xor an input string with a given character key. @@ -19,15 +20,18 @@ def xor(xinput, key): def get_data_path(): dpath = os.path.dirname(__file__) - return os.path.sep.join( (dpath, 'data') ) + return os.path.sep.join((dpath, 'data')) + def get_plugin_path(): dpath = os.path.dirname(__file__) - return os.path.sep.join( (dpath, 'plugins') ) + return os.path.sep.join((dpath, 'plugins')) + def get_output_path(): dpath = os.path.dirname(__file__) - return os.path.sep.join( (dpath, 'output') ) + return os.path.sep.join((dpath, 'output')) + def decode_base64(intext, alphabet='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/', padchar='='): """ @@ -53,7 +57,12 @@ def decode_base64(intext, alphabet='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr i = 0 while i < len(intext) - 3: - if intext[i] not in alphabet or intext[i + 1] not in alphabet or intext[i + 2] not in alphabet or intext[i + 3] not in alphabet: + if ( + intext[i] not in alphabet + or intext[i + 1] not in alphabet + or intext[i + 2] not in alphabet + or intext[i + 3] not in alphabet + ): raise KeyError("Non-alphabet character in encoded text.") val = alphabet_index[intext[i]] * 262144 val += alphabet_index[intext[i + 1]] * 4096 @@ -111,6 +120,7 @@ def hex_plus_ascii(data, width=16, offset=0): output += outstr return output + def gen_local_filename(path, origname): """ Generates a local filename based on the original. Automatically adds a @@ -138,6 +148,7 @@ def gen_local_filename(path, origname): postfix = "_{:04d}".format(i) return localname + postfix + def human_readable_filesize(bytecount): """ Converts the raw byte counts into a human-readable format @@ -148,4 +159,3 @@ def human_readable_filesize(bytecount): return "{:3.2f} {}".format(bytecount, unit) bytecount /= 1024.0 return "{:3.2f} {}".format(bytecount, "YB") - diff --git a/setup.py b/setup.py index 9ce3a3a..4fd5fb5 100644 --- a/setup.py +++ b/setup.py @@ -23,6 +23,8 @@ "pcapy", "pypacker", "pyopenssl", + "elasticsearch", + "tabulate", ], entry_points={ "console_scripts": [ From bf13027912c2cfcc8bbd28a47c86ff6b8c7c8952 Mon Sep 17 00:00:00 2001 From: DC3-DCCI <12175126+DC3-DCCI@users.noreply.github.com> Date: Thu, 22 Oct 2020 15:33:52 -0400 Subject: [PATCH 113/166] Fix bug with handled connection count and added catch for miss-calculated TCP sequence numbers. --- dshell/core.py | 68 +++++++++++++++++++---------------------- dshell/output/output.py | 8 +++-- 2 files changed, 38 insertions(+), 38 deletions(-) diff --git a/dshell/core.py b/dshell/core.py index 635dca4..31bec00 100644 --- a/dshell/core.py +++ b/dshell/core.py @@ -625,7 +625,7 @@ def _close_connection(self, conn, full=False): connection_handler_out = None if connection_handler_out: self._connection_queue.append(connection_handler_out) - with self.handled_packet_count.get_lock(): + with self.handled_conn_count.get_lock(): self.handled_conn_count.value += 1 if full: try: @@ -1265,8 +1265,6 @@ def __init__(self, first_packet, direction) Attributes: addr: .addr attribute of the first packet - direction: direction of blob - - 'cs' for client-to-server, 'sc' for server-to-client ts: timestamp of the first packet starttime: datetime for first packet endtime: datetime of last packet @@ -1406,6 +1404,12 @@ def get_packets(self, start, end=None) -> List["Packet"]: return packets def get_frames(self, start, end=None) -> List[int]: + """ + Returns frame identifiers for the packets that contain data for the given start offset + up to the end offset. + If end offset is not provided, just the frame identifier for the packet containing the + start offset is provided. + """ return [packet.frame for packet in self.get_packets(start, end=end)] @property @@ -1456,6 +1460,7 @@ def segments(self) -> List[Tuple[int, "Packet"]]: expected_seq += missing_num_bytes + len(packet.data) prev_packet = packet + # TODO: Support rollover sequence numbers. # Otherwise, we have some overlap in data and need to remove the invalid segment/packet # and ignoring adding it to the segments list. else: @@ -1465,19 +1470,6 @@ def segments(self) -> List[Tuple[int, "Packet"]]: self._segments = segments # cache for next time. return segments - # # TODO: Should this account for pulling data before all packets have been added? - # @property - # def data(self): - # """ - # Returns the reassembled byte string. - # - # If it was not already reassembled, reassemble is called with default - # arguments. - # """ - # if not self.__data_bytes: - # self.reassemble() - # return self.__data_bytes - @property def data(self): """ @@ -1501,7 +1493,6 @@ def data(self): # Check if we have missing packets. if seq - initial_seq != len(data): - # logger.warning('Missing packets in TCP stream.') # buffer data with null bytes data += b'\x00' * (seq - initial_seq - len(data)) @@ -1542,10 +1533,15 @@ def data(self, data): if initial_seq is None: initial_seq = seq + relative_seq = seq - initial_seq + if relative_seq < written_bytes: + raise RuntimeError( + "Relative sequence is less then written byte count. " + "Sequence numbers have be miss-calculated." + ) # Skip holes in data. (User should have put padding in these areas) - if seq - initial_seq != written_bytes: - # logger.warning('Missing packets in TCP stream.') - written_bytes += seq - initial_seq - written_bytes + elif relative_seq != written_bytes: + written_bytes = relative_seq packet.data = data[written_bytes:written_bytes + len(packet.data)] written_bytes += len(packet.data) @@ -1763,22 +1759,22 @@ def add_packet(self, packet): return # Replace packet(s) with retransmitted packet - else: - # First add the retransmitted packet, replacing the original packet matching the - # sequence number. - logger.debug(f'Replacing packet {orig_packet.frame} with {packet.frame}') - self._seq_map[seq] = packet - self.packets = [packet if p.sequence_number == seq else p for p in self.packets] - - # Now remove any packets that contained data that is now part of the retransmitted packet. - packets_to_remove = [] - for seq_, packet_ in self._seq_map.items(): - if 0 < (seq_ - seq) < len(packet.data): - logger.debug(f'Removing packet: {packet_.frame}') - packets_to_remove.append(packet_) - # NOTE: need to remove packets outside the above loop because removing packets affect seq_map - for packet_ in packets_to_remove: - self._remove_packet(packet_) + + # First add the retransmitted packet, replacing the original packet matching the + # sequence number. + logger.debug(f'Replacing packet {orig_packet.frame} with {packet.frame}') + self._seq_map[seq] = packet + self.packets = [packet if p.sequence_number == seq else p for p in self.packets] + + # Now remove any packets that contained data that is now part of the retransmitted packet. + packets_to_remove = [] + for seq_, packet_ in self._seq_map.items(): + if 0 < (seq_ - seq) < len(packet.data): + logger.debug(f'Removing packet: {packet_.frame}') + packets_to_remove.append(packet_) + # NOTE: need to remove packets outside the above loop because removing packets affect seq_map + for packet_ in packets_to_remove: + self._remove_packet(packet_) def _remove_packet(self, packet): """ diff --git a/dshell/output/output.py b/dshell/output/output.py index 1387b9b..2da1627 100644 --- a/dshell/output/output.py +++ b/dshell/output/output.py @@ -117,7 +117,9 @@ def setup(self): pass def close(self): - """Close output file, assuming it's not stdout""" + """ + Close output file, assuming it's not stdout + """ if self.fh not in (sys.stdout, sys.stdout.buffer): self.fh.close() @@ -194,7 +196,9 @@ def convert(self, *args, **kwargs): return output def write(self, *args, **kwargs): - """Primary output function. Should be overwritten by subclasses.""" + """ + Primary output function. Should be overwritten by subclasses. + """ line = self.convert(*args, **kwargs) try: self.fh.write(line) From 5b8539b5202fc564b195e15f50d5238b1d05ab18 Mon Sep 17 00:00:00 2001 From: DC3-DCCI <12175126+DC3-DCCI@users.noreply.github.com> Date: Fri, 6 Nov 2020 17:46:32 -0500 Subject: [PATCH 114/166] Set BLOB_FILTERING to lowercase --- dshell/core.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dshell/core.py b/dshell/core.py index 31bec00..8b17748 100644 --- a/dshell/core.py +++ b/dshell/core.py @@ -454,7 +454,7 @@ class ConnectionPlugin(PacketPlugin): # Due to how we modified the blob creation code, the ACK and handshake methods are not # part of any of the blobs. Therefore, when the produce_packets() function is called, those # packets are missing if we are only producing the packets within a blob. - BLOB_FILTERING = True + blob_filtering = True def __init__(self, **kwargs): super().__init__(**kwargs) @@ -513,7 +513,7 @@ def produce_packets(self) -> Iterable["Packet"]: """ # Produce connections for connection in self.produce_connections(): - if self.BLOB_FILTERING: + if self.blob_filtering: for blob in connection.blobs: if not blob.hidden: yield from blob.packets From fab16281f79f7ae096772d34ec3f1ab33b776972 Mon Sep 17 00:00:00 2001 From: DC3-DCCI <12175126+DC3-DCCI@users.noreply.github.com> Date: Tue, 17 Nov 2020 12:02:10 -0500 Subject: [PATCH 115/166] Remove resolved fixme --- dshell/output/output.py | 1 - 1 file changed, 1 deletion(-) diff --git a/dshell/output/output.py b/dshell/output/output.py index 2da1627..688b2e9 100644 --- a/dshell/output/output.py +++ b/dshell/output/output.py @@ -97,7 +97,6 @@ def _increment_filename(self, filename): Creates a distinct filename by appending a sequence number. """ try: - # FIXME: Should n be incremented in the loop? while os.stat(filename): p = filename.rsplit('-', 1) try: From 1f0d59a515842b0d529b55c7cc3d316075aa09a4 Mon Sep 17 00:00:00 2001 From: DC3-DCCI Date: Mon, 11 Jan 2021 13:26:19 -0500 Subject: [PATCH 116/166] Fixed bug that caused first packet in connection to be added twice --- dshell/core.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/dshell/core.py b/dshell/core.py index 8b17748..f4b78e3 100644 --- a/dshell/core.py +++ b/dshell/core.py @@ -570,6 +570,7 @@ def _connection_handler(self, packet: "Packet"): self.seen_conn_count.value += 1 else: conn = self._connection_tracker[addr] + conn.add_packet(packet) if conn.stop: # This connection was flagged to not be tracked @@ -583,8 +584,6 @@ def _connection_handler(self, packet: "Packet"): # if pkt.data: # conn.handled = False - conn.add_packet(packet) - if conn.closed: # Both sides have closed the connection, process blobs (messages) and # close connection. From ec5d2d8afcbc4014dc5f7f35d6c6c88236d60f50 Mon Sep 17 00:00:00 2001 From: dev195 Date: Tue, 12 Jan 2021 09:35:34 -0500 Subject: [PATCH 117/166] Fixed multiprocessing AttributeError bug --- dshell/decode.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dshell/decode.py b/dshell/decode.py index 2e7da66..7a5470c 100755 --- a/dshell/decode.py +++ b/dshell/decode.py @@ -317,7 +317,7 @@ def main(plugin_args=None, **kwargs): processes = [] for i in inputs: processes.append( - multiprocessing.Process(target=process_files, args=(i,), kwargs=kwargs) + multiprocessing.Process(target=process_files, args=([i],), kwargs=kwargs) ) # Spawn processes, and keep track of which ones are running From 2f08f8b869f5e7f8d8d2988337e857614ed626be Mon Sep 17 00:00:00 2001 From: dev195 Date: Tue, 12 Jan 2021 09:50:35 -0500 Subject: [PATCH 118/166] Removed .decode import from __init__.py, since it raised warnings in some circumstances --- dshell/__init__.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/dshell/__init__.py b/dshell/__init__.py index 8031e98..c241f84 100644 --- a/dshell/__init__.py +++ b/dshell/__init__.py @@ -1,8 +1,7 @@ # Expose classes and functions that external users will need to access as the API from .core import ConnectionPlugin, PacketPlugin, Packet -# TODO: Make process_files()/main() function more API friendly through documentation and unwrapping the kwargs. -from .decode import process_files, main_command_line +# TODO: Make decode.process_files()/main() function more API friendly through documentation and unwrapping the kwargs from .api import get_plugins, get_plugin_information from .output.alertout import AlertOutput From a70670157fb48e9cc0c08c93db139bc6ccf37dd0 Mon Sep 17 00:00:00 2001 From: dev195 Date: Tue, 12 Jan 2021 11:07:06 -0500 Subject: [PATCH 119/166] updated plugin loggers to be created as an attribute in the superclass constructor --- dshell/core.py | 4 +++- dshell/plugins/filter/country.py | 6 +----- dshell/plugins/filter/track.py | 8 ++------ dshell/plugins/flows/largeflows.py | 9 ++------- dshell/plugins/flows/longflows.py | 7 +------ dshell/plugins/flows/reverseflows.py | 9 ++------- dshell/plugins/http/riphttp.py | 10 +++------- dshell/plugins/malware/sweetorange.py | 8 ++------ dshell/plugins/misc/pcapwriter.py | 4 ---- dshell/plugins/misc/xor.py | 12 ++++-------- dshell/plugins/nbns/nbns.py | 10 +++------- dshell/plugins/protocol/bitcoin.py | 12 ++++-------- dshell/plugins/protocol/ether.py | 6 +----- dshell/plugins/protocol/ip.py | 7 +------ dshell/plugins/tftp/tftp.py | 8 ++------ 15 files changed, 31 insertions(+), 89 deletions(-) diff --git a/dshell/core.py b/dshell/core.py index f4b78e3..be3e49f 100644 --- a/dshell/core.py +++ b/dshell/core.py @@ -16,6 +16,7 @@ # standard Python imports import datetime +import inspect import ipaddress import logging import warnings @@ -59,7 +60,7 @@ class DataError(Exception): try: geoip = DshellGeoIP() except FileNotFoundError: - logger.error( + logger.warning( "Could not find GeoIP data files! Country and ASN lookups will not be possible. Check README for instructions on where to find and install necessary data files.") geoip = DshellFailedGeoIP() @@ -119,6 +120,7 @@ def __init__(self, **kwargs): self.compiled_bpf = kwargs.get('compiled_bpf', None) self.vlan_bpf = kwargs.get("vlan_bpf", True) self.author = kwargs.get('author', '') + self.logger = logging.getLogger(inspect.getmodule(self).__name__) # define overall counts as multiprocessing Values for --parallel self.seen_packet_count = Value('i', 0) diff --git a/dshell/plugins/filter/country.py b/dshell/plugins/filter/country.py index 1111ef1..aa66280 100644 --- a/dshell/plugins/filter/country.py +++ b/dshell/plugins/filter/country.py @@ -2,14 +2,10 @@ A filter for connections by IP address country code. Will generally be chained with other plugins. """ -import logging import dshell.core from dshell.output.netflowout import NetflowOutput -logger = logging.getLogger(__name__) - - class DshellPlugin(dshell.core.ConnectionPlugin): def __init__(self, *args, **kwargs): @@ -64,7 +60,7 @@ def premodule(self): # Several of the args are mutually exclusive # Check if more than one is set, and print a warning if so if (self.neither + self.both + self.notboth) > 1: - logger.warning("Can only use one of these args at a time: 'neither', 'both', or 'notboth'") + self.logger.warning("Can only use one of these args at a time: 'neither', 'both', or 'notboth'") def connection_handler(self, conn): # If no country code specified, pass all traffic through diff --git a/dshell/plugins/filter/track.py b/dshell/plugins/filter/track.py index 2bf8ee7..59ebc3c 100644 --- a/dshell/plugins/filter/track.py +++ b/dshell/plugins/filter/track.py @@ -3,16 +3,12 @@ generally chained with other plugins. """ -import logging import ipaddress import sys import dshell.core from dshell.output.alertout import AlertOutput -logger = logging.getLogger(__name__) - - class DshellPlugin(dshell.core.ConnectionPlugin): def __init__(self, **kwargs): super().__init__( @@ -118,8 +114,8 @@ def premodule(self): if self.source: for sstr in self.source: self.sources.extend(self.__split_ips(sstr)) - logger.debug("targets: {!s}".format(self.targets)) - logger.debug("sources: {!s}".format(self.sources)) + self.logger.debug("targets: {!s}".format(self.targets)) + self.logger.debug("sources: {!s}".format(self.sources)) def connection_handler(self, conn): if self.targets: diff --git a/dshell/plugins/flows/largeflows.py b/dshell/plugins/flows/largeflows.py index d9161f3..6988a57 100644 --- a/dshell/plugins/flows/largeflows.py +++ b/dshell/plugins/flows/largeflows.py @@ -3,14 +3,9 @@ Megabyte threshold can be updated by the user. """ -import logging - import dshell.core from dshell.output.netflowout import NetflowOutput -logger = logging.getLogger(__name__) - - class DshellPlugin(dshell.core.ConnectionPlugin): def __init__(self): @@ -30,10 +25,10 @@ def __init__(self): def premodule(self): if self.size <= 0: - logger.warning("Cannot have a size that's less than or equal to zero (size: {}). Setting to 1.".format(self.size)) + self.logger.warning("Cannot have a size that's less than or equal to zero (size: {}). Setting to 1.".format(self.size)) self.size = 1 self.min = 1048576 * self.size - logger.debug("Input: {}, Final size: {} bytes".format(self.size, self.min)) + self.logger.debug("Input: {}, Final size: {} bytes".format(self.size, self.min)) def connection_handler(self, conn): if conn.clientbytes + conn.serverbytes >= self.min: diff --git a/dshell/plugins/flows/longflows.py b/dshell/plugins/flows/longflows.py index da04f31..729b978 100644 --- a/dshell/plugins/flows/longflows.py +++ b/dshell/plugins/flows/longflows.py @@ -3,14 +3,9 @@ Minute threshold can be updated by the user. """ -import logging - import dshell.core from dshell.output.netflowout import NetflowOutput -logger = logging.getLogger(__name__) - - class DshellPlugin(dshell.core.ConnectionPlugin): def __init__(self): @@ -31,7 +26,7 @@ def __init__(self): def premodule(self): if self.len <= 0: - logger.warning("Cannot have a time that's less than or equal to zero (size: {}). Setting to 5.".format(self.len)) + self.logger.warning("Cannot have a time that's less than or equal to zero (size: {}). Setting to 5.".format(self.len)) self.len = 5 self.secs = 60 * self.len diff --git a/dshell/plugins/flows/reverseflows.py b/dshell/plugins/flows/reverseflows.py index 3414720..a68f60d 100644 --- a/dshell/plugins/flows/reverseflows.py +++ b/dshell/plugins/flows/reverseflows.py @@ -21,15 +21,10 @@ Generates an alert for all client transmissions that are 61 times greater than the server transmission. """ -import logging import dshell.core from dshell.output.alertout import AlertOutput - -logger = logging.getLogger(__name__) - - class DshellPlugin(dshell.core.ConnectionPlugin): def __init__(self): @@ -74,10 +69,10 @@ def __init__(self): def premodule(self): if self.threshold < 0: - logger.warning("Cannot have a negative threshold. Defaulting to 3.0. (threshold: {0})".format(self.threshold)) + self.logger.warning("Cannot have a negative threshold. Defaulting to 3.0. (threshold: {0})".format(self.threshold)) self.threshold = 3.0 elif not self.threshold: - logger.warning("Threshold not set. Displaying all client-server transmissions (threshold: {0})".format(self.threshold)) + self.logger.warning("Threshold not set. Displaying all client-server transmissions (threshold: {0})".format(self.threshold)) def connection_handler(self, conn): if conn.clientbytes < self.minimum: diff --git a/dshell/plugins/http/riphttp.py b/dshell/plugins/http/riphttp.py index 582efda..1bd90cd 100644 --- a/dshell/plugins/http/riphttp.py +++ b/dshell/plugins/http/riphttp.py @@ -3,7 +3,6 @@ files. """ -import logging import os import re import sys @@ -11,9 +10,6 @@ from dshell.plugins.httpplugin import HTTPPlugin from dshell.output.alertout import AlertOutput -logger = logging.getLogger(__name__) - - class DshellPlugin(HTTPPlugin): def __init__(self): super().__init__( @@ -47,7 +43,7 @@ def __init__(self): def premodule(self): if self.direction not in ('cs', 'sc', None): - logger.warning("Invalid value for direction: {!r}. Argument must be either 'sc' for server-to-client or 'cs' for client-to-server.".format(self.direction)) + self.logger.warning("Invalid value for direction: {!r}. Argument must be either 'sc' for server-to-client or 'cs' for client-to-server.".format(self.direction)) sys.exit(1) if self.content_filter: @@ -85,7 +81,7 @@ def http_handler(self, conn, request, response): if url in self.openfiles: # File is already open, so just insert the new data s, e = self.openfiles[url].handleresponse(response) - logger.debug("{0!r} --> Range: {1} - {2}".format(url, s, e)) + self.logger.debug("{0!r} --> Range: {1} - {2}".format(url, s, e)) else: # A new file! filename = request.uri.split('?', 1)[0].split('/')[-1] @@ -104,7 +100,7 @@ def http_handler(self, conn, request, response): self.write("New file {} ({})".format(filename, url), **conn.info(), dir_arrow="<-") self.openfiles[url] = HTTPFile(os.path.join(self.outdir, filename), self) s, e = self.openfiles[url].handleresponse(payload) - logger.debug("{0!r} --> Range: {1} - {2}".format(url, s, e)) + self.logger.debug("{0!r} --> Range: {1} - {2}".format(url, s, e)) if self.openfiles[url].done(): self.write("File done {} ({})".format(filename, url), **conn.info(), dir_arrow="<-") del self.openfiles[url] diff --git a/dshell/plugins/malware/sweetorange.py b/dshell/plugins/malware/sweetorange.py index 7777b3e..f26a337 100644 --- a/dshell/plugins/malware/sweetorange.py +++ b/dshell/plugins/malware/sweetorange.py @@ -14,15 +14,11 @@ http://malware-traffic-analysis.net/2014/09/25/index.html """ -import logging import re from dshell.output.alertout import AlertOutput from dshell.plugins.httpplugin import HTTPPlugin -logger = logging.getLogger(__name__) - - class DshellPlugin(HTTPPlugin): def __init__(self): @@ -54,7 +50,7 @@ def premodule(self): self.sig_regex = re.compile( r"var (" + '|'.join(map(re.escape, self.variable)) + ")='(.*?)';") self.hexregex = re.compile(r'[^a-fA-F0-9]') - logger.debug('Variable regex: "%s"' % self.sig_regex.pattern) + self.logger.debug('Variable regex: "%s"' % self.sig_regex.pattern) def http_handler(self, conn, request, response): try: @@ -80,7 +76,7 @@ def http_handler(self, conn, request, response): hidden = "\x1b[37;2m%s\x1b[0m" % hidden match = "\x1b[32m%s\x1b[0m" % match - logger.info(hidden) + self.logger.info(hidden) self.write(match, **conn.info()) return (conn, request, response) diff --git a/dshell/plugins/misc/pcapwriter.py b/dshell/plugins/misc/pcapwriter.py index 95bedc3..a6df98d 100644 --- a/dshell/plugins/misc/pcapwriter.py +++ b/dshell/plugins/misc/pcapwriter.py @@ -14,14 +14,10 @@ (decode -d web+pcapwriter ~/pcap/*) """ -import logging import struct import dshell.core -logger = logging.getLogger(__name__) - - class DshellPlugin(dshell.core.PacketPlugin): def __init__(self, *args, **kwargs): diff --git a/dshell/plugins/misc/xor.py b/dshell/plugins/misc/xor.py index e4fa438..9b1cbfe 100644 --- a/dshell/plugins/misc/xor.py +++ b/dshell/plugins/misc/xor.py @@ -3,16 +3,12 @@ for different data directions. """ -import logging import struct import dshell.core import dshell.util from dshell.output.output import Output -logger = logging.getLogger(__name__) - - class DshellPlugin(dshell.core.ConnectionPlugin): def __init__(self): super().__init__( @@ -57,7 +53,7 @@ def __make_key(self, key): try: newkey += struct.pack('B', int(oldkey[i:i + 2], 16)) except ValueError as e: - logger.warning("Error converting hex. Will treat as raw string. - {!s}".format(e)) + self.logger.warning("Error converting hex. Will treat as raw string. - {!s}".format(e)) newkey = key.encode('ascii') break else: @@ -68,7 +64,7 @@ def __make_key(self, key): except ValueError: # otherwise, convert string key to bytes as it is newkey = key.encode('ascii') - logger.debug("__make_key: {!r} -> {!r}".format(key, newkey)) + self.logger.debug("__make_key: {!r} -> {!r}".format(key, newkey)) return newkey def premodule(self): @@ -91,7 +87,7 @@ def connection_handler(self, conn): # grab the data from the TCP layer and down data = pkt.data # data = pkt.pkt.upper_layer.upper_layer.body_bytes - logger.debug("Original:\n{}".format(dshell.util.hex_plus_ascii(data))) + self.logger.debug("Original:\n{}".format(dshell.util.hex_plus_ascii(data))) # XOR the data and store it in new_data new_data = b'' for i in range(len(data)): @@ -103,5 +99,5 @@ def connection_handler(self, conn): pkt.data = new_data # # rebuild the packet by adding together each of the layers # pkt.rawpkt = pkt.pkt.header_bytes + pkt.pkt.upper_layer.header_bytes + pkt.pkt.upper_layer.upper_layer.header_bytes + new_data - logger.debug("New:\n{}".format(dshell.util.hex_plus_ascii(new_data))) + self.logger.debug("New:\n{}".format(dshell.util.hex_plus_ascii(new_data))) return conn diff --git a/dshell/plugins/nbns/nbns.py b/dshell/plugins/nbns/nbns.py index 81c9d21..c2ed789 100644 --- a/dshell/plugins/nbns/nbns.py +++ b/dshell/plugins/nbns/nbns.py @@ -2,15 +2,11 @@ NBNS plugin """ -import logging from struct import unpack import dshell.core from dshell.output.alertout import AlertOutput -logger = logging.getLogger(__name__) - - # A few common NBNS Protocol Info Opcodes # Due to a typo in RFC 1002, 0x9 is also acceptable, but rarely used # for 'NetBios Refresh' @@ -94,7 +90,7 @@ def packet_handler(self, pkt): try: nbns_packet = nbns_packet.upper_layer except IndexError as e: - logger.error('{}: could not parse session data \ + self.logger.error('{}: could not parse session data \ (NBNS packet not found)'.format(str(e))) # pypacker may throw an Exception here; could use # further testing @@ -106,7 +102,7 @@ def packet_handler(self, pkt): try: nbns_name = unpack('32s', pkt.data[13:45])[0] except Exception as e: - logger.error('{}: (NBNS packet not found)'.format(str(e))) + self.logger.error('{}: (NBNS packet not found)'.format(str(e))) return @@ -125,7 +121,7 @@ def packet_handler(self, pkt): self.client_hostname = str(nbns_name) except ValueError as e: - logger.error('{}: Hostname in improper format \ + self.logger.error('{}: Hostname in improper format \ (NBNS packet not found)'.format(str(e))) return diff --git a/dshell/plugins/protocol/bitcoin.py b/dshell/plugins/protocol/bitcoin.py index 0547eb9..4e6a237 100644 --- a/dshell/plugins/protocol/bitcoin.py +++ b/dshell/plugins/protocol/bitcoin.py @@ -7,10 +7,6 @@ import json from struct import unpack -import logging - -logger = logging.getLogger(__name__) - # Magic values used to determine Bitcoin Network Type # Bitcoin Testnet is an alternative blockchain used for testing @@ -131,7 +127,7 @@ def blob_handler(self, conn, blob): data_str = ''.join(chr(x) for x in data) data_len = len(data) except: - logger.error('could not parse session data') + self.logger.error('could not parse session data') return # Only continue if the packet contains data @@ -188,9 +184,9 @@ def blob_handler(self, conn, blob): clean_jobs] except KeyError as e: - logger.error("{} - Error extracting auth ID".format(str(e))) + self.logger.error("{} - Error extracting auth ID".format(str(e))) except ValueError as e: - logger.error('{} - json data not found'.format(str(e))) + self.logger.error('{} - json data not found'.format(str(e))) return @@ -201,7 +197,7 @@ def blob_handler(self, conn, blob): magic_val = data[0:4].hex().upper() magic_val = ' '.join([magic_val[i:i+2] for i in range(0, len(magic_val), 2)]) except: - logger.error('could not parse session data') + self.logger.error('could not parse session data') return # Attempt to translate first 4 bytes of payload into a Bitcoin (bc) diff --git a/dshell/plugins/protocol/ether.py b/dshell/plugins/protocol/ether.py index 2b83fed..87bffa5 100644 --- a/dshell/plugins/protocol/ether.py +++ b/dshell/plugins/protocol/ether.py @@ -3,16 +3,12 @@ recommended that oui.txt be included in the share/ directory (see README). """ -import logging import os import dshell.core from dshell.output.output import Output from dshell.util import get_data_path -logger = logging.getLogger(__name__) - - class DshellPlugin(dshell.core.PacketPlugin): OUTPUT_FORMAT = "[%(plugin)s] %(dt)s %(sip)-15s %(smac)-18s %(smac_org)-35s -> %(dip)-15s %(dmac)-18s %(dmac_org)-35s %(byte_count)d\n" @@ -46,7 +42,7 @@ def premodule(self): except FileNotFoundError: # user probably did not download it # print warning and continue - logger.warning("Could not find {} (see README). Will not be able to determine MAC organizations.".format(ouifilepath)) + self.logger.warning("Could not find {} (see README). Will not be able to determine MAC organizations.".format(ouifilepath)) def packet_handler(self, pkt): if not pkt.smac or not pkt.dmac: diff --git a/dshell/plugins/protocol/ip.py b/dshell/plugins/protocol/ip.py index 749d5a4..db93919 100644 --- a/dshell/plugins/protocol/ip.py +++ b/dshell/plugins/protocol/ip.py @@ -2,15 +2,10 @@ Outputs all IPv4/IPv6 traffic, and hex plus ascii with verbose flag """ -import logging - import dshell.core import dshell.util from dshell.output.alertout import AlertOutput -logger = logging.getLogger(__name__) - - class DshellPlugin(dshell.core.PacketPlugin): def __init__(self): @@ -25,5 +20,5 @@ def __init__(self): def packet_handler(self, packet): self.write(**packet.info(), dir_arrow='->') # If verbose flag set, outputs packet contents in hex and ascii alongside packet info - logger.info("\n" + dshell.util.hex_plus_ascii(packet.rawpkt)) + self.logger.info("\n" + dshell.util.hex_plus_ascii(packet.rawpkt)) return packet diff --git a/dshell/plugins/tftp/tftp.py b/dshell/plugins/tftp/tftp.py index d29a1fc..760b0de 100644 --- a/dshell/plugins/tftp/tftp.py +++ b/dshell/plugins/tftp/tftp.py @@ -38,7 +38,6 @@ filenames when saved """ -import logging import os import struct @@ -48,9 +47,6 @@ import dshell.util from dshell.output.alertout import AlertOutput -logger = logging.getLogger(__name__) - - class DshellPlugin(dshell.core.PacketPlugin): "Primary plugin class" # packet opcodes (http://www.networksorcery.com/enp/default1101.htm) @@ -109,8 +105,8 @@ def premodule(self): def postmodule(self): "cleanup any unfinished streams" - logger.debug("Unset Read Streams: {!s}".format(self.unset_read_streams)) - logger.debug("Unset Write Streams: {!s}".format(self.unset_write_streams)) + self.logger.debug("Unset Read Streams: {!s}".format(self.unset_read_streams)) + self.logger.debug("Unset Write Streams: {!s}".format(self.unset_write_streams)) while(len(self.open_streams) > 0): k = list(self.open_streams)[0] self.__closeStream(k, "POSSIBLY INCOMPLETE") From 2a06f567ac10f707cc750488df936bb7fd1cf750 Mon Sep 17 00:00:00 2001 From: dev195 Date: Tue, 12 Jan 2021 11:08:23 -0500 Subject: [PATCH 120/166] fixed bug in 'info' function caused by deleting attributes that no longer exist --- dshell/core.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/dshell/core.py b/dshell/core.py index be3e49f..8825945 100644 --- a/dshell/core.py +++ b/dshell/core.py @@ -990,8 +990,6 @@ def info(self): """ d = dict(self.__dict__) del d['pkt'] - del d['rawpkt'] - del d['data'] return d From f274cc38bb6d60f05e2c2f08a9bcaa902efc349e Mon Sep 17 00:00:00 2001 From: dev195 Date: Tue, 12 Jan 2021 11:59:07 -0500 Subject: [PATCH 121/166] updated version numbers --- README | 2 +- README.md | 2 +- dshell/core.py | 2 +- setup.py | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/README b/README index 11d8e04..10a2f6a 100644 --- a/README +++ b/README @@ -10,7 +10,7 @@ Key features: ## Requirements * Linux (developed on Red Hat Enterprise Linux 6.7) -* Python 3 (developed with Python 3.5.1) +* Python 3 (developed with Python 3.6.2) * [pypacker](https://gitlab.com/mike01/pypacker) * [pcapy](https://github.com/helpsystems/pcapy) * [pyOpenSSL](https://github.com/pyca/pyopenssl) diff --git a/README.md b/README.md index 11d8e04..10a2f6a 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ Key features: ## Requirements * Linux (developed on Red Hat Enterprise Linux 6.7) -* Python 3 (developed with Python 3.5.1) +* Python 3 (developed with Python 3.6.2) * [pypacker](https://gitlab.com/mike01/pypacker) * [pcapy](https://github.com/helpsystems/pcapy) * [pyOpenSSL](https://github.com/pyca/pyopenssl) diff --git a/dshell/core.py b/dshell/core.py index 8825945..7b34b19 100644 --- a/dshell/core.py +++ b/dshell/core.py @@ -38,7 +38,7 @@ logger = logging.getLogger(__name__) -__version__ = "3.1.3" +__version__ = "3.2.1" class SequenceNumberError(Exception): """ diff --git a/setup.py b/setup.py index 4fd5fb5..2b896cb 100644 --- a/setup.py +++ b/setup.py @@ -2,11 +2,11 @@ setup( name="Dshell", - version="3.1.3", + version="3.2.1", author="USArmyResearchLab", description="An extensible network forensic analysis framework", url="https://github.com/USArmyResearchLab/Dshell", - python_requires='>=3.5', + python_requires='>=3.6', packages=find_packages(), package_data={ "dshell": ["data/dshellrc", "data/GeoIP/readme.txt"], From ed7aa78c869ccac7b0233a6974c80a9a73c7cf5d Mon Sep 17 00:00:00 2001 From: Adam M Date: Tue, 9 Feb 2021 13:46:21 +0000 Subject: [PATCH 122/166] Per comment from @dev195, updating to return None on non-HTTP traffic. --- dshell/plugins/http/web.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dshell/plugins/http/web.py b/dshell/plugins/http/web.py index b559908..b11d0bf 100644 --- a/dshell/plugins/http/web.py +++ b/dshell/plugins/http/web.py @@ -27,7 +27,7 @@ def http_handler(self, conn, request, response): if request.method=="": # It's impossible to have a properly formed HTTP request without a method # indicating, the httpplugin is calling http_handler without a full object - return conn, request, response + return None # Collect basics about the request, if available method = request.method host = request.headers.get("host", "") @@ -44,7 +44,7 @@ def http_handler(self, conn, request, response): if response: if response.status == "" and response.reason == "": # Another indication of improperly parsed HTTP object in httpplugin - return conn, request, response + return None # Collect basics about the response, if available status = response.status reason = response.reason From 461693c80d18649001271d99bd02c13a85f2cd90 Mon Sep 17 00:00:00 2001 From: J Date: Tue, 9 Feb 2021 10:30:26 -0500 Subject: [PATCH 123/166] Removed hard-coded delimiter from colorout.py Removed the hard-coded delimiter from the output module, and replaced it with a default. This will allow users to override the delimiter using --oarg. --- dshell/output/colorout.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dshell/output/colorout.py b/dshell/output/colorout.py index 154659a..be25c07 100644 --- a/dshell/output/colorout.py +++ b/dshell/output/colorout.py @@ -27,6 +27,7 @@ class ColorOutput(Output): """ _DEFAULT_FORMAT = _PACKET_FORMAT + _DEFAULT_DELIM = "\n\n" def __init__(self, *args, **kwargs): @@ -37,7 +38,6 @@ def __init__(self, *args, **kwargs): 'sc': '32', # server-to-client is green '--': '34', # everything else is blue } # TODO configurable for color-blind users? - self.delim = "\n\n" self.hexmode = kwargs.get('hex', False) self.format_is_set = False From 017ae5daa5145a7a444c159a8a785edf29b96fd1 Mon Sep 17 00:00:00 2001 From: J Date: Tue, 9 Feb 2021 10:32:02 -0500 Subject: [PATCH 124/166] Remove hard-coded delimiter from htmlout.py Removed the hard-coded delimiter from the output module, and replaced it with a default. This will allow users to override the delimiter using --oarg. --- dshell/output/htmlout.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dshell/output/htmlout.py b/dshell/output/htmlout.py index bff3ec7..3deea20 100644 --- a/dshell/output/htmlout.py +++ b/dshell/output/htmlout.py @@ -24,6 +24,7 @@ class HTMLOutput(Output): %(data)s """ _DEFAULT_FORMAT = _PACKET_FORMAT + _DEFAULT_DELIM = "
      " _HTML_HEADER = """ @@ -68,7 +69,6 @@ def __init__(self, *args, **kwargs): 'sc': 'green', # server-to-client is green '--': 'blue', # everything else is blue } - self.delim = "
      " self.hexmode = kwargs.get('hex', False) self.format_is_set = False From cbe458ebe58710965c4bf8efcb64028db5ce07fc Mon Sep 17 00:00:00 2001 From: J Date: Wed, 17 Feb 2021 14:46:58 -0500 Subject: [PATCH 125/166] Quick fix for IPv6 AttributeError Fixed an AttributeError when handling IPv6 packets. It is an incomplete fix that does not handle IPv6 extension headers, but should handle most IPv6. --- dshell/core.py | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/dshell/core.py b/dshell/core.py index 7b34b19..7334478 100644 --- a/dshell/core.py +++ b/dshell/core.py @@ -950,8 +950,13 @@ def data(self): ip_layer = self._ip_layer tcp_layer = self._tcp_layer if ip_layer and tcp_layer: - data_size = ip_layer.len - (ip_layer.header_len + tcp_layer.header_len) - self._data = best_layer.body_bytes[:data_size] + if isinstance(ip_layer, ip.IP): # IPv4 + data_size = ip_layer.len - (ip_layer.header_len + tcp_layer.header_len) + self._data = best_layer.body_bytes[:data_size] + else: # IPv6 + # TODO handle extension headers + data_size = ip_layer.dlen - tcp_layer.header_len + self._data = best_layer.body_bytes[:data_size] else: self._data = best_layer.body_bytes @@ -971,8 +976,13 @@ def data(self, data): ip_layer = self._ip_layer tcp_layer = self._tcp_layer if ip_layer and tcp_layer: - data_size = ip_layer.len - (ip_layer.header_len + tcp_layer.header_len) - best_layer.body_bytes = data + best_layer.body_bytes[data_size:] + if isinstance(ip_layer, ip.IP): # IPv4 + data_size = ip_layer.len - (ip_layer.header_len + tcp_layer.header_len) + best_layer.body_bytes = data + best_layer.body_bytes[data_size:] + else: # IPv6 + # TODO handle extension headers + data_size = ip_layer.dlen - tcp_layer.header_len + best_layer.body_bytes = data + best_layer.body_bytes[data_size:] else: best_layer.body_bytes = data From fbfd3ad29f99efe9d78baf3278c76d9e3f05d77a Mon Sep 17 00:00:00 2001 From: DC3-DCCI <12175126+DC3-DCCI@users.noreply.github.com> Date: Mon, 22 Mar 2021 19:36:45 -0400 Subject: [PATCH 126/166] Optimized processing time for ConnectionPlugin by adding a max connections limiter and decreasing the frequency of the timeout check. --- dshell/core.py | 54 ++++++++++++++++++++++++++++++++++-------------- dshell/decode.py | 7 +++++++ 2 files changed, 45 insertions(+), 16 deletions(-) diff --git a/dshell/core.py b/dshell/core.py index 7334478..289d25f 100644 --- a/dshell/core.py +++ b/dshell/core.py @@ -465,6 +465,7 @@ def __init__(self, **kwargs): self._connection_queue = [] # dictionary to store packets for connections according to addr() + # NOTE: Only currently unhandled (ie. open) connections are stored here. self._connection_tracker = {} # define overall counts as multiprocessing Values for --parallel @@ -475,11 +476,18 @@ def __init__(self, **kwargs): # connection_handler # it defaults to infinite, but this should be lowered for huge datasets self.maxblobs = float("inf") # infinite + # how long do we wait before deciding a connection is "finished" # time is checked by iterating over cached connections and checking if # the timestamp of the connection's last packet is older than the # timestamp of the current packet, minus this value - self.connection_timeout = datetime.timedelta(hours=1) + self.timeout = datetime.timedelta(hours=1) + # The frequency of packets to process between timeout checks. + self.timeout_frequency = 300 + # The maximum number of open connections allowed at one time. + # If the maximum number of connections is met, the oldest connections + # will be force closed. + self.max_open_connections = 1000 def _postmodule(self): """ @@ -599,15 +607,9 @@ def _connection_handler(self, packet: "Packet"): # # will clear the connection's blob cache # self._close_connection(conn) - # The current connection is done processing. Now, look over existing - # connections and look for any that have timed out. - # This is based on comparing the time of the current packet, minus - # self.connection_timeout, to each connection's current endtime value. - for addr, conn in self._connection_tracker.items(): - if conn.handled: - continue - if conn.endtime < (packet.dt - self.connection_timeout): - self._close_connection(conn) + # Check for and close old connections every so often. + if self.handled_packet_count.value % self.timeout_frequency == 0: + self._timeout_connections(packet.dt) def _close_connection(self, conn, full=False): """ @@ -619,6 +621,13 @@ def _close_connection(self, conn, full=False): print_handler_exception(e, self, 'connection_handler') return None conn.handled = True + + # Remove connection from tracker once successfully closed/handled. + try: + del self._connection_tracker[tuple(sorted(conn.addr))] + except KeyError: + pass + if connection_handler_out and not isinstance(connection_handler_out, Connection): logger.warning( "The output from {} connection_handler must be of type dshell.Connection! Chaining plugins from here may not be possible.".format( @@ -635,6 +644,24 @@ def _close_connection(self, conn, full=False): print_handler_exception(e, self, 'connection_close_handler') return connection_handler_out + def _timeout_connections(self, timestamp: datetime.datetime): + """ + Checks for and force closes connections that have been alive for too long. + It also closes the oldest connections if too many connections are open. + """ + # Force close any connections that have timed out. + # This is based on comparing the time of the current packet, minus + # self.timeout, to each connection's current endtime value. + for conn in list(self._connection_tracker.values()): + if conn.endtime < (timestamp - self.timeout): + self._close_connection(conn) + + # Force close oldest connections if we have too many. + if len(self._connection_tracker) > self.max_open_connections: + connections = sorted(self._connection_tracker.values(), key=lambda conn: conn.endtime, reverse=True) + for conn in connections[self.max_open_connections:]: + self._close_connection(conn) + def _cleanup_connections(self): """ decode.py will often reach the end of packet capture before all of the @@ -644,13 +671,8 @@ def _cleanup_connections(self): NOTE: Because the connections did not close cleanly, connection_close_handler will not be called. """ - for addr, conn in self._connection_tracker.items(): + for conn in list(self._connection_tracker.values()): if not conn.stop and not conn.handled: - # try to process the final blob in the connection - # TODO: Refactoring most likely made processing the last blob obsolete. - # self._blob_handler(conn, conn.blobs[-1]) - - # then, handle the connection itself self._close_connection(conn) def _purge_connections(self): diff --git a/dshell/decode.py b/dshell/decode.py index 7a5470c..b73bcde 100755 --- a/dshell/decode.py +++ b/dshell/decode.py @@ -79,6 +79,13 @@ def feed_plugin_chain(plugin_index: int, packet: Packet): if next_plugin_index: for _packet in current_plugin.produce_packets(): feed_plugin_chain(next_plugin_index, _packet) + else: + # For the last plugin in the chain we still need to call produce_packets() + # to release resources for already processed packets. + # This prevents us consuming too much memory or processing time for large pcaps + # or long running live captures. + for _ in current_plugin.produce_packets(): + pass def clean_plugin_chain(plugin_index): From adcad5a793dfdc71f6e0b31fbfe1c3a82acc3258 Mon Sep 17 00:00:00 2001 From: DC3-DCCI <12175126+DC3-DCCI@users.noreply.github.com> Date: Tue, 23 Mar 2021 15:31:43 -0400 Subject: [PATCH 127/166] Optimize processing time by lazy evaluating ConnectionPlugin attributes. --- dshell/core.py | 126 +++++++++++++++++++++++++++++++------------------ 1 file changed, 80 insertions(+), 46 deletions(-) diff --git a/dshell/core.py b/dshell/core.py index 289d25f..66448b8 100644 --- a/dshell/core.py +++ b/dshell/core.py @@ -22,7 +22,7 @@ import warnings from collections import defaultdict from multiprocessing import Value -from typing import Iterable, List, Tuple +from typing import Iterable, List, Tuple, Union # Dshell imports from dshell.output.output import Output @@ -814,7 +814,6 @@ def __init__(self, pktlen, packet: pypacker.Packet, timestamp: int, frame=0): self.pkt = packet self.pktlen = pktlen # TODO: Is this needed? - self.byte_count = None self.sip = None self.dip = None self.sport = None @@ -831,11 +830,14 @@ def __init__(self, pktlen, packet: pypacker.Packet, timestamp: int, frame=0): self.dipasn = None self.protocol = None self.protocol_num = None - self._data = None # data cache self.sequence_number = None self.ack_number = None self.tcp_flags = None + # attribute cache + self._byte_count = None + self._data = None + # these are the layers Dshell will help parse # try to find them in the packet and eventually pull out useful data ethernet_p = None @@ -843,24 +845,25 @@ def __init__(self, pktlen, packet: pypacker.Packet, timestamp: int, frame=0): ip_p = None tcp_p = None udp_p = None - current_layer = packet - self._highest_layer = current_layer - while current_layer: - self._highest_layer = current_layer - if isinstance(current_layer, ethernet.Ethernet) and not ethernet_p: - ethernet_p = current_layer - elif isinstance(current_layer, ieee80211.IEEE80211) and not ieee80211_p: - ieee80211_p = current_layer - elif isinstance(current_layer, (ip.IP, ip6.IP6)) and not ip_p: - ip_p = current_layer - elif isinstance(current_layer, tcp.TCP) and not tcp_p: - tcp_p = current_layer - elif isinstance(current_layer, udp.UDP) and not udp_p: - udp_p = current_layer - try: - current_layer = current_layer.upper_layer - except AttributeError: - break + highest_layer = packet + for layer in packet: + highest_layer = layer + if ethernet_p is None and isinstance(layer, ethernet.Ethernet): + ethernet_p = layer + elif ieee80211_p is None and isinstance(layer, ieee80211.IEEE80211): + ieee80211_p = layer + elif ip_p is None and isinstance(layer, (ip.IP, ip6.IP6)): + ip_p = layer + elif tcp_p is None and isinstance(layer, tcp.TCP): + tcp_p = layer + elif udp_p is None and isinstance(layer, udp.UDP): + udp_p = layer + self._highest_layer = highest_layer + self._ethernet_layer = ethernet_p # type: ethernet.Ethernet + self._ieee80211_layer = ieee80211_p # type: ieee80211.IEEE80211 + self._ip_layer = ip_p # type: Union[ip.IP, ip6.IP6] + self._tcp_layer = tcp_p # type: tcp.TCP + self._udp_layer = udp_p # type: udp.UDP # attempt to grab MAC addresses if ethernet_p: @@ -888,11 +891,6 @@ def __init__(self, pktlen, packet: pypacker.Packet, timestamp: int, frame=0): except AttributeError as e: pass - # Cache ip, tcp, and udp layer for future use. - self._ip_layer = ip_p - self._tcp_layer = tcp_p - self._udp_layer = udp_p - # process IP addresses and associated metadata (if applicable) if ip_p: # get IP addresses @@ -922,8 +920,6 @@ def __init__(self, pktlen, packet: pypacker.Packet, timestamp: int, frame=0): self.sport = udp_p.sport self.dport = udp_p.dport - self.byte_count = len(self.data) - @property def addr(self): """ @@ -942,6 +938,15 @@ def addr(self): else: return (None, None), (None, None) + @property + def byte_count(self) -> int: + """ + Total number of payload bytes in the packet. + """ + if self._byte_count is None: + self._byte_count = len(self.data) + return self._byte_count + @property def packet_tuple(self): """ @@ -1020,7 +1025,8 @@ def info(self): Provides a dictionary with information about a packet. Useful for calls to a plugin's write() function, e.g. self.write(\\*\\*pkt.info()) """ - d = dict(self.__dict__) + d = {k: v for k, v in self.__dict__ if not k.startswith('_')} + d['byte_count'] = self.byte_count del d['pkt'] return d @@ -1130,10 +1136,6 @@ def __init__(self, first_packet): self.serverlon = first_packet.diplon self.serverasn = first_packet.dipasn self.protocol = first_packet.protocol - self.clientpackets = 0 - self.clientbytes = 0 - self.serverpackets = 0 - self.serverbytes = 0 self.ts = first_packet.ts self.dt = first_packet.dt self.starttime = first_packet.dt @@ -1144,8 +1146,6 @@ def __init__(self, first_packet): self.packets = [] # keeps track of packets in connection. self.stop = False self.handled = False - # used to determine if direction changes - self._current_addr_pair = None self.add_packet(first_packet) @@ -1236,15 +1236,6 @@ def add_packet(self, packet: Packet): elif packet.dip == self.clientip and self.client_state == self.FINISHING: self.client_state = self.CLOSED - # Only count packets if they have data (i.e. ignore SYNs, ACKs, etc.) - if packet.data: - if packet.addr == self.addr: - self.clientpackets += 1 - self.clientbytes += packet.byte_count - else: - self.serverpackets += 1 - self.serverbytes += packet.byte_count - if packet.dt > self.endtime: self.endtime = packet.dt @@ -1256,13 +1247,56 @@ def info(self): Returns: Dictionary with information """ - d = dict(self.__dict__) + d = {k: v for k, v in self.__dict__ if not k.startswith('_')} d['duration'] = self.duration + d['clientbytes'] = self.clientbytes + d['clientpackets'] = self.clientpackets + d['serverbytes'] = self.serverbytes + d['serverpackets'] = self.serverpackets del d['stop'] - del d['_current_addr_pair'] del d['handled'] return d + def _client_packets(self) -> Iterable[Packet]: + for packet in self.packets: + if packet.addr == self.addr: + yield packet + + def _server_packets(self) -> Iterable[Packet]: + for packet in self.packets: + if packet.addr != self.addr: + yield packet + + @property + def clientbytes(self) -> int: + """ + The total number of bytes form the client. + """ + return sum(packet.byte_count for packet in self._client_packets()) + + @property + def clientpackets(self) -> int: + """ + The total number of packets from the client. + """ + # (Only counting packets with data.) + return sum(bool(packet.byte_count) for packet in self._client_packets()) + + @property + def serverbytes(self) -> int: + """ + The total number of bytes form the server. + """ + return sum(packet.byte_count for packet in self._server_packets()) + + @property + def serverpackets(self) -> int: + """ + The total number of packets from the server. + """ + # (Only counting packets with data.) + return sum(bool(packet.byte_count) for packet in self._server_packets()) + def __repr__(self): return '%s %16s -> %16s (%s -> %s) %6s %6s %5d %5d %7d %7d %-.4fs' % ( self.starttime, From cea5752b3d780bd3116287b2e8aff13aced76fa1 Mon Sep 17 00:00:00 2001 From: DC3-DCCI <12175126+DC3-DCCI@users.noreply.github.com> Date: Tue, 23 Mar 2021 16:27:58 -0400 Subject: [PATCH 128/166] Created standardized purge() function. Add purging for PacketPlugin. --- dshell/core.py | 27 +++++++++++++++++---------- dshell/decode.py | 6 +----- 2 files changed, 18 insertions(+), 15 deletions(-) diff --git a/dshell/core.py b/dshell/core.py index 66448b8..f257d1a 100644 --- a/dshell/core.py +++ b/dshell/core.py @@ -149,7 +149,7 @@ def __init__(self, **kwargs): self.current_pcap_file = None # a holder for IP packet fragments when attempting to reassemble them - self.packet_fragments = defaultdict(dict) + self._packet_fragments = defaultdict(dict) def produce_packets(self) -> Iterable["Packet"]: """ @@ -166,6 +166,14 @@ def flush(self): # right away. pass + def purge(self): + """ + When finished with handling a pcap file, calling this will clear all + caches in preparation for next file. + """ + self._packet_queue = [] + self._packet_fragments = defaultdict(dict) + def write(self, *args, **kwargs): """ Sends information to the output formatter, after adding some @@ -255,14 +263,14 @@ def ipdefrag(self, pkt): IP fragment reassembly """ if isinstance(pkt, ip.IP): # IPv4 - f = self.packet_fragments[(pkt.src, pkt.dst, pkt.id)] + f = self._packet_fragments[(pkt.src, pkt.dst, pkt.id)] f[pkt.offset] = pkt if not pkt.flags & 0x1: data = b'' for key in sorted(f.keys()): data += f[key].body_bytes - del self.packet_fragments[(pkt.src, pkt.dst, pkt.id)] + del self._packet_fragments[(pkt.src, pkt.dst, pkt.id)] newpkt = ip.IP(pkt.header_bytes + data) newpkt.bin(update_auto_fields=True) # refresh checksum return newpkt @@ -675,11 +683,12 @@ def _cleanup_connections(self): if not conn.stop and not conn.handled: self._close_connection(conn) - def _purge_connections(self): + def purge(self): """ When finished with handling a pcap file, calling this will clear all caches in preparation for next file. """ + super().purge() self._connection_queue = [] self._connection_tracker = {} @@ -894,12 +903,10 @@ def __init__(self, pktlen, packet: pypacker.Packet, timestamp: int, frame=0): # process IP addresses and associated metadata (if applicable) if ip_p: # get IP addresses - sip = ipaddress.ip_address(ip_p.src) - dip = ipaddress.ip_address(ip_p.dst) - self.sip = sip.compressed - self.dip = dip.compressed - self.sip_bytes = sip.packed - self.dip_bytes = dip.packed + self.sip = ip_p.src_s + self.dip = ip_p.dst_s + self.sip_bytes = ip_p.src + self.dip_bytes = ip_p.dst # get protocols, country codes, and ASNs self.protocol_num = ip_p.p if isinstance(ip_p, ip.IP) else ip_p.nxt diff --git a/dshell/decode.py b/dshell/decode.py index b73bcde..b54817c 100755 --- a/dshell/decode.py +++ b/dshell/decode.py @@ -510,11 +510,7 @@ def process_files(inputs, **kwargs): clean_plugin_chain(0) for plugin in plugin_chain: - try: - plugin._purge_connections() - except AttributeError: - # probably just a packet plugin - pass + plugin.purge() plugin._postfile() From c1ebfb1a69a9ee4ef6424e2e2ea2ba4dde3ebe7d Mon Sep 17 00:00:00 2001 From: DC3-DCCI <12175126+DC3-DCCI@users.noreply.github.com> Date: Wed, 24 Mar 2021 11:43:47 -0400 Subject: [PATCH 129/166] Fixes to ConnectionPlugin to ensure connections are produced and handled in the correct order. --- dshell/core.py | 76 ++++++++++++++++++++++++++++++------------------ dshell/decode.py | 7 +++++ 2 files changed, 54 insertions(+), 29 deletions(-) diff --git a/dshell/core.py b/dshell/core.py index f257d1a..3b5a85c 100644 --- a/dshell/core.py +++ b/dshell/core.py @@ -16,8 +16,8 @@ # standard Python imports import datetime +import heapq import inspect -import ipaddress import logging import warnings from collections import defaultdict @@ -471,6 +471,9 @@ def __init__(self, **kwargs): # similar to packet_queue and raw_packet_queue in superclass self._connection_queue = [] + # Flag used to determine if we are ready to produce closed connections + # for the next plugin in the chain. + self._production_ready = True # dictionary to store packets for connections according to addr() # NOTE: Only currently unhandled (ie. open) connections are stored here. @@ -511,19 +514,20 @@ def produce_connections(self) -> Iterable["Connection"]: """ Produces recently closed connections ready to be passed down to the next plugin in the chain. """ + # Avoid producing connections if we are still waiting for an older connection to close. + # This helps to ensure connections are produced in the right order.... for the most part. + if not self._production_ready: + return while self._connection_queue: - connection = self._connection_queue.pop(0) + # Pop off oldest closed connection. + _, full, connection = heapq.heappop(self._connection_queue) + # Handle connection + success = self._handle_connection(connection, full=full) + if not success or connection.stop: + continue + # Pass along connection to next plugin. yield connection - - # Attempt to clear out the connection, now that it has been handled. - conn_key = tuple(sorted(connection.addr)) - try: - del self._connection_tracker[conn_key] - except KeyError: - # If the plugin messed with the connection's address, it might - # fail to clear it. - # TODO find some way to better handle this scenario - pass + self._production_ready = False def produce_packets(self) -> Iterable["Packet"]: """ @@ -590,10 +594,6 @@ def _connection_handler(self, packet: "Packet"): conn = self._connection_tracker[addr] conn.add_packet(packet) - if conn.stop: - # This connection was flagged to not be tracked - return - # TODO: Do we need this? This flag is set to False when the connection is initialized and not # set to true until it is closed. # Is there any scenario where we would want to undo a True handled state? @@ -623,34 +623,47 @@ def _close_connection(self, conn, full=False): """ Runs through some standard actions to close a connection """ - try: - connection_handler_out = self.connection_handler(conn) - except Exception as e: - print_handler_exception(e, self, 'connection_handler') - return None - conn.handled = True + # Add connection to queue ready to be processed, based on order they were received on the wire. + heapq.heappush(self._connection_queue, (conn.packets[0].frame, full, conn)) - # Remove connection from tracker once successfully closed/handled. + # Remove connection from tracker once in the queue. try: del self._connection_tracker[tuple(sorted(conn.addr))] except KeyError: pass + def _handle_connection(self, conn: "Connection", full=False) -> bool: + """ + Handles produced connections. + + :returns: True if connection was handled successfully. + """ + try: + connection_handler_out = self.connection_handler(conn) + except Exception as e: + print_handler_exception(e, self, 'connection_handler') + return False + conn.handled = True + + # TODO: Perhaps connection_handler() just returns a True or False indicating success? if connection_handler_out and not isinstance(connection_handler_out, Connection): logger.warning( "The output from {} connection_handler must be of type dshell.Connection! Chaining plugins from here may not be possible.".format( self.name)) connection_handler_out = None - if connection_handler_out: - self._connection_queue.append(connection_handler_out) - with self.handled_conn_count.get_lock(): - self.handled_conn_count.value += 1 + + if not connection_handler_out: + return False + + with self.handled_conn_count.get_lock(): + self.handled_conn_count.value += 1 + if full: try: self.connection_close_handler(conn) except Exception as e: print_handler_exception(e, self, 'connection_close_handler') - return connection_handler_out + return True def _timeout_connections(self, timestamp: datetime.datetime): """ @@ -670,6 +683,9 @@ def _timeout_connections(self, timestamp: datetime.datetime): for conn in connections[self.max_open_connections:]: self._close_connection(conn) + # We can produce connections again, now that we have handled lingering old connections. + self._production_ready = True + def _cleanup_connections(self): """ decode.py will often reach the end of packet capture before all of the @@ -680,8 +696,9 @@ def _cleanup_connections(self): connection_close_handler will not be called. """ for conn in list(self._connection_tracker.values()): - if not conn.stop and not conn.handled: + if not conn.handled: self._close_connection(conn) + self._production_ready = True def purge(self): """ @@ -691,6 +708,7 @@ def purge(self): super().purge() self._connection_queue = [] self._connection_tracker = {} + self._production_ready = False # TODO: Have blobs handled with consumer/producer model just like Packets and Connections? def _blob_handler(self, conn: "Connection", blob: "Blob"): diff --git a/dshell/decode.py b/dshell/decode.py index b54817c..ec9e465 100755 --- a/dshell/decode.py +++ b/dshell/decode.py @@ -106,6 +106,13 @@ def clean_plugin_chain(plugin_index): for _packet in current_plugin.produce_packets(): feed_plugin_chain(next_plugin_index, _packet) clean_plugin_chain(next_plugin_index) + else: + # For the last plugin in the chain we still need to call produce_packets() + # to release resources for already processed packets. + # This prevents us consuming too much memory or processing time for large pcaps + # or long running live captures. + for _ in current_plugin.produce_packets(): + pass def decompress_file(filepath, extension, unzipdir): From f2e7ca2f93949af61ec04102002392dc97755ef5 Mon Sep 17 00:00:00 2001 From: DC3-DCCI <12175126+DC3-DCCI@users.noreply.github.com> Date: Wed, 24 Mar 2021 15:10:09 -0400 Subject: [PATCH 130/166] Small fixups --- dshell/core.py | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/dshell/core.py b/dshell/core.py index 3b5a85c..cfdaf52 100644 --- a/dshell/core.py +++ b/dshell/core.py @@ -493,7 +493,7 @@ def __init__(self, **kwargs): # the timestamp of the connection's last packet is older than the # timestamp of the current packet, minus this value self.timeout = datetime.timedelta(hours=1) - # The frequency of packets to process between timeout checks. + # The number of packets to process between timeout checks. self.timeout_frequency = 300 # The maximum number of open connections allowed at one time. # If the maximum number of connections is met, the oldest connections @@ -872,7 +872,7 @@ def __init__(self, pktlen, packet: pypacker.Packet, timestamp: int, frame=0): ip_p = None tcp_p = None udp_p = None - highest_layer = packet + highest_layer = None for layer in packet: highest_layer = layer if ethernet_p is None and isinstance(layer, ethernet.Ethernet): @@ -1050,7 +1050,7 @@ def info(self): Provides a dictionary with information about a packet. Useful for calls to a plugin's write() function, e.g. self.write(\\*\\*pkt.info()) """ - d = {k: v for k, v in self.__dict__ if not k.startswith('_')} + d = {k: v for k, v in self.__dict__.items() if not k.startswith('_')} d['byte_count'] = self.byte_count del d['pkt'] return d @@ -1272,7 +1272,7 @@ def info(self): Returns: Dictionary with information """ - d = {k: v for k, v in self.__dict__ if not k.startswith('_')} + d = {k: v for k, v in self.__dict__.items() if not k.startswith('_')} d['duration'] = self.duration d['clientbytes'] = self.clientbytes d['clientpackets'] = self.clientpackets @@ -1787,9 +1787,8 @@ def info(self): Returns: Dictionary with information """ - d = dict(self.__dict__) + d = {k: v for k, v in self.__dict__.items() if not k.startswith('_')} del d['hidden'] - del d['_Blob__data_bytes'] del d['packets'] return d From 93834c14dce79ea3e34dd1f651f98db5bc4e3aec Mon Sep 17 00:00:00 2001 From: DC3-DCCI <12175126+DC3-DCCI@users.noreply.github.com> Date: Thu, 25 Mar 2021 10:09:51 -0400 Subject: [PATCH 131/166] Simplify implementation of feed_plugin_chain() and clean_plugin_chain() --- dshell/decode.py | 42 ++++++++++++++---------------------------- 1 file changed, 14 insertions(+), 28 deletions(-) diff --git a/dshell/decode.py b/dshell/decode.py index ec9e465..94febb0 100755 --- a/dshell/decode.py +++ b/dshell/decode.py @@ -65,27 +65,18 @@ def feed_plugin_chain(plugin_index: int, packet: Packet): Each plugin decides whether the packet(s) will proceed to the next plugin, i.e. act as a filter. """ - global plugin_chain + if plugin_index >= len(plugin_chain): + # We are at the end of the chain. + return current_plugin = plugin_chain[plugin_index] - next_plugin_index = plugin_index + 1 - if next_plugin_index >= len(plugin_chain): - next_plugin_index = None # Pass packet into plugin for processing. current_plugin.consume_packet(packet) # Process produced packets. - if next_plugin_index: - for _packet in current_plugin.produce_packets(): - feed_plugin_chain(next_plugin_index, _packet) - else: - # For the last plugin in the chain we still need to call produce_packets() - # to release resources for already processed packets. - # This prevents us consuming too much memory or processing time for large pcaps - # or long running live captures. - for _ in current_plugin.produce_packets(): - pass + for _packet in current_plugin.produce_packets(): + feed_plugin_chain(plugin_index + 1, _packet) def clean_plugin_chain(plugin_index): @@ -94,25 +85,20 @@ def clean_plugin_chain(plugin_index): It will go through the plugins and attempt to cleanup any connections that were not yet closed. """ + if plugin_index >= len(plugin_chain): + # We are at the end of the chain + return + current_plugin = plugin_chain[plugin_index] - next_plugin_index = plugin_index + 1 - if next_plugin_index >= len(plugin_chain): - next_plugin_index = None # need to flush even if there are no more plugins in the chain to ensure all packets are processed. current_plugin.flush() - if next_plugin_index: - for _packet in current_plugin.produce_packets(): - feed_plugin_chain(next_plugin_index, _packet) - clean_plugin_chain(next_plugin_index) - else: - # For the last plugin in the chain we still need to call produce_packets() - # to release resources for already processed packets. - # This prevents us consuming too much memory or processing time for large pcaps - # or long running live captures. - for _ in current_plugin.produce_packets(): - pass + # Feed plugin chain with lingering packets released by flush. + for _packet in current_plugin.produce_packets(): + feed_plugin_chain(plugin_index + 1, _packet) + + clean_plugin_chain(plugin_index + 1) def decompress_file(filepath, extension, unzipdir): From 8c9989cd565412c1cc406b3eb4648910176fec45 Mon Sep 17 00:00:00 2001 From: dev195 Date: Mon, 12 Apr 2021 13:02:24 -0400 Subject: [PATCH 132/166] Fixes for JSON output. Prevented .info() calls from returning a full list of packets, and making some core Dshell classes serializable --- dshell/core.py | 1 + dshell/output/jsonout.py | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/dshell/core.py b/dshell/core.py index cfdaf52..8452036 100644 --- a/dshell/core.py +++ b/dshell/core.py @@ -1280,6 +1280,7 @@ def info(self): d['serverpackets'] = self.serverpackets del d['stop'] del d['handled'] + del d['packets'] return d def _client_packets(self) -> Iterable[Packet]: diff --git a/dshell/output/jsonout.py b/dshell/output/jsonout.py index f570e3b..8955031 100644 --- a/dshell/output/jsonout.py +++ b/dshell/output/jsonout.py @@ -5,7 +5,7 @@ from datetime import datetime import json from dshell.output.output import Output - +from dshell.core import Packet, Blob, Connection class JSONOutput(Output): """ @@ -40,6 +40,9 @@ def json_default(self, obj): if isinstance(obj, bytes): serial = repr(obj) return serial + if isinstance(obj, (Connection, Blob, Packet)): + serial = obj.info() + return serial raise TypeError ("Type not serializable ({})".format(str(type(obj)))) obj = JSONOutput From 2d8e3836dd03d643cfba02e96743e706b3a4c828 Mon Sep 17 00:00:00 2001 From: dev195 Date: Wed, 21 Apr 2021 14:13:48 -0400 Subject: [PATCH 133/166] Altered --oarg flag to work with all output modules, including plugin defaults, and changed instances of 'delim' to 'delimiter' in the code. --- dshell/decode.py | 26 +++++++++++++++----------- dshell/output/csvout.py | 8 ++++++-- dshell/output/elasticout.py | 2 +- dshell/output/output.py | 32 ++++++++++++++++++++++++-------- 4 files changed, 46 insertions(+), 22 deletions(-) diff --git a/dshell/decode.py b/dshell/decode.py index 94febb0..9d01922 100755 --- a/dshell/decode.py +++ b/dshell/decode.py @@ -207,27 +207,31 @@ def main(plugin_args=None, **kwargs): # If alternate output module is selected, tell each plugin to use that # instead if kwargs.get("omodule", None): - # Check if any user-defined output arguments are provided - oargs = {} - if kwargs.get("oargs", None): - for oarg in kwargs["oargs"]: - if '=' in oarg: - key, val = oarg.split('=', 1) - oargs[key] = val - else: - oargs[oarg] = True try: # TODO: Create a factory classmethod in the base Output class (e.g. "from_name()") instead. omodule = import_module("dshell.output."+kwargs["omodule"]) omodule = omodule.obj for plugin in plugin_chain: # TODO: Should we have a single instance of the Output module used by all plugins? - oomodule = omodule(**oargs) + oomodule = omodule() plugin.out = oomodule except ImportError as e: logger.error("Could not import module named '{}'. Use --list-output flag to see available modules".format(kwargs["omodule"])) sys.exit(1) + # Check if any user-defined output arguments are provided + if kwargs.get("oargs", None): + oargs = {} + for oarg in kwargs["oargs"]: + if '=' in oarg: + key, val = oarg.split('=', 1) + oargs[key] = val + else: + oargs[oarg] = True + logger.debug("oargs: %s" % oargs) + for plugin in plugin_chain: + plugin.out.set_oargs(**oargs) + # If writing to a file, set for each output module here if kwargs.get("outfile", None): for plugin in plugin_chain: @@ -584,7 +588,7 @@ def main_command_line(): help="Use specified output module for plugins instead of defaults. For example, --omodule=jsonout for JSON output.") output_group.add_argument("--oarg", type=str, metavar="ARG=VALUE", dest="oargs", action="append", - help="Supply a specific keyword argument to user-defined output module. Only used in conjunction with --omodule. Can be used multiple times for multiple arguments. Not using an equal sign will treat it as a flag and set the value to True. Example: --omodule=alertout --oarg \"timeformat=%%H %%M %%S\"") + help="Supply a specific keyword argument to plugins' output modules. Can be used multiple times for multiple arguments. Not using an equal sign will treat it as a flag and set the value to True. Example: --oarg \"delimiter=:\" --oarg \"timeformat=%%H %%M %%S\"") output_group.add_argument("-q", "--quiet", action="store_true", help="Disable logging") output_group.add_argument("-W", metavar="OUTFILE", dest="outfile", diff --git a/dshell/output/csvout.py b/dshell/output/csvout.py index e23e864..8ba9cbd 100644 --- a/dshell/output/csvout.py +++ b/dshell/output/csvout.py @@ -10,7 +10,7 @@ class CSVOutput(Output): Takes specified fields provided to the write function and print them in a CSV format. - Delimiter can be set with --oarg delim= + Delimiter can be set with --oarg delimiter= A header row can be printed with --oarg header @@ -26,7 +26,7 @@ class CSVOutput(Output): _DESCRIPTION = "CSV format output" def __init__(self, *args, **kwargs): - self.delimiter = kwargs.get('delim', self._DEFAULT_DELIM) + self.delimiter = kwargs.get('delimiter', self._DEFAULT_DELIM) if self.delimiter == 'tab': self.delimiter = '\t' @@ -53,6 +53,10 @@ def set_format(self, _=None): fmt += "\n" super().set_format(fmt) + def set_oargs(self, **kwargs): + super().set_oargs(**kwargs) + self.set_format() + def setup(self): if self.use_header: self.fh.write(self.delimiter.join([f for f in self.fields]) + "\n") diff --git a/dshell/output/elasticout.py b/dshell/output/elasticout.py index 9cec05d..0eae856 100644 --- a/dshell/output/elasticout.py +++ b/dshell/output/elasticout.py @@ -43,7 +43,7 @@ def __init__(self, *args, **kwargs): def write(self, *args, **kwargs): "Converts alert's keyword args to JSON and indexes it into Elasticsearch datastore." if args and 'data' not in kwargs: - kwargs['data'] = self.delim.join(map(str, args)) + kwargs['data'] = self.delimiter.join(map(str, args)) # Elasticsearch can't handle IPv6 (at time of writing) # Just delete the ints and expand the string notation. diff --git a/dshell/output/output.py b/dshell/output/output.py index 688b2e9..cf4556d 100644 --- a/dshell/output/output.py +++ b/dshell/output/output.py @@ -23,7 +23,7 @@ class Output: Arguments: format : 'format string' to override default formatstring for output class timeformat : 'format string' for datetime representation - delim : set a delimiter for CSV or similar output + delimiter : set a delimiter for CSV or similar output nobuffer : true/false to run flush() after every relevant write noclobber : set to true to avoid overwriting existing files fh : existing open file handle @@ -36,12 +36,12 @@ class Output: _DESCRIPTION = "Base output class" def __init__( - self, file=None, fh=None, mode='w', format=None, timeformat=None, delim=None, nobuffer=False, + self, file=None, fh=None, mode='w', format=None, timeformat=None, delimiter=None, nobuffer=False, noclobber=False, extra=None, **unused_kwargs ): self.format_fields = [] self.timeformat = timeformat or self._DEFAULT_TIME_FORMAT - self.delim = delim or self._DEFAULT_DELIM + self.delimiter = delimiter or self._DEFAULT_DELIM self.nobuffer = nobuffer self.noclobber = noclobber self.extra = extra @@ -82,6 +82,19 @@ def reset_fh(self, filename=None, fh=None, mode=None): else: self.fh = open(filename, self.mode) + def set_oargs(self, format=None, noclobber=None, delimiter=None, timeformat=None, **unused_kwargs): + """ + Process the standard oargs from the command line. + """ + if delimiter: + self.delimiter = delimiter + if timeformat: + self.timeformat = timeformat + if noclobber: + self.noclobber = noclobber + if format: + self.set_format(format) + def set_format(self, fmt): """Set the output format to a new format string""" # Use a regular expression to identify all fields that the format will @@ -149,10 +162,6 @@ def convert(self, *args, **kwargs): try: outdict['ts'] = datetime.fromtimestamp(float(outdict['ts'])) outdict['ts'] = outdict['ts'].strftime(self.timeformat) - outdict['starttime'] = datetime.fromtimestamp(float(outdict['starttime'])) - outdict['starttime'] = outdict['starttime'].strftime(self.timeformat) - outdict['endtime'] = datetime.fromtimestamp(float(outdict['endtime'])) - outdict['endtime'] = outdict['endtime'].strftime(self.timeformat) except TypeError: pass except KeyError: @@ -160,6 +169,13 @@ def convert(self, *args, **kwargs): except ValueError: pass + if "starttime" in outdict and isinstance(outdict["starttime"], datetime): + outdict['starttime'] = outdict['starttime'].strftime(self.timeformat) + if "endtime" in outdict and isinstance(outdict["endtime"], datetime): + outdict['endtime'] = outdict['endtime'].strftime(self.timeformat) + if 'dt' in outdict and isinstance(outdict["dt"], datetime): + outdict['dt'] = outdict['dt'].strftime(self.timeformat) + # Create directional arrows if 'dir_arrow' not in outdict: if outdict.get('direction') == 'cs': @@ -181,7 +197,7 @@ def convert(self, *args, **kwargs): extras.append("%s=%s" % (key, val)) # Dump the args into a 'data' field - outdict['data'] = self.delim.join(map(str, args)) + outdict['data'] = self.delimiter.join(map(str, args)) # Create an optional 'extra' field if self.extra: From f46fe40f2d6de28de1e598d4de5d0b169c75f6f4 Mon Sep 17 00:00:00 2001 From: adam Date: Tue, 1 Jun 2021 15:36:02 +0000 Subject: [PATCH 134/166] Updated delimiter member to conform with new output main class --- dshell/output/jsonout.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dshell/output/jsonout.py b/dshell/output/jsonout.py index 8955031..f1e6121 100644 --- a/dshell/output/jsonout.py +++ b/dshell/output/jsonout.py @@ -25,7 +25,7 @@ def write(self, *args, **kwargs): # before printing output self.extra = False if args and 'data' not in kwargs: - kwargs['data'] = self.delim.join(map(str, args)) + kwargs['data'] = self.delimiter.join(map(str, args)) jsondata = json.dumps(kwargs, ensure_ascii=self.ensure_ascii, default=self.json_default) super().write(jsondata=jsondata) From 502a546914d58d5336eda5ee91430256d06f24be Mon Sep 17 00:00:00 2001 From: J Date: Wed, 9 Jun 2021 12:55:14 -0400 Subject: [PATCH 135/166] Fix for open_live issue Fixed issue related to the timeout argument when calling pcapy.open_live, which caused Dshell to hang when listening live on an interface. --- dshell/decode.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dshell/decode.py b/dshell/decode.py index 9d01922..7b0c765 100755 --- a/dshell/decode.py +++ b/dshell/decode.py @@ -390,7 +390,7 @@ def read_packets(input: str, interface=False, bpf=None, count=None) -> Iterable[ if interface: # Listen on an interface if the option is set try: - capture = pcapy.open_live(input, 65536, True, 0) + capture = pcapy.open_live(input, 65536, True, 1) except pcapy.PcapError as e: # User probably doesn't have permission to listen on interface # In any case, print just the error without traceback From 58324732283100fb9b1720b3aee1ee8cb85f4dc2 Mon Sep 17 00:00:00 2001 From: ammaddock Date: Tue, 31 Aug 2021 14:17:31 +0000 Subject: [PATCH 136/166] Add handler for hexout in set_oargs --- dshell/output/output.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/dshell/output/output.py b/dshell/output/output.py index cf4556d..41b57af 100644 --- a/dshell/output/output.py +++ b/dshell/output/output.py @@ -82,7 +82,7 @@ def reset_fh(self, filename=None, fh=None, mode=None): else: self.fh = open(filename, self.mode) - def set_oargs(self, format=None, noclobber=None, delimiter=None, timeformat=None, **unused_kwargs): + def set_oargs(self, format=None, noclobber=None, delimiter=None, timeformat=None, hex=None, **unused_kwargs): """ Process the standard oargs from the command line. """ @@ -92,6 +92,8 @@ def set_oargs(self, format=None, noclobber=None, delimiter=None, timeformat=None self.timeformat = timeformat if noclobber: self.noclobber = noclobber + if hex: + self.hexmode = hex if format: self.set_format(format) From d918607161a7c27a798d7da73ef45a0e88fb12fb Mon Sep 17 00:00:00 2001 From: Davis Schirmer Date: Sat, 6 Nov 2021 01:34:46 -0400 Subject: [PATCH 137/166] Update Dockerfile to build cryptography > 3.4 * https://cryptography.io/en/3.4.5/installation.html#building-cryptography-on-linux * https://github.com/pyca/cryptography/blob/main/CHANGELOG.rst#34---2021-02-07 * https://github.com/pyca/cryptography/blob/main/CHANGELOG.rst#3500---2021-09-29 * https://github.com/pyca/cryptography/issues/5771 --- Dockerfile | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/Dockerfile b/Dockerfile index 4ecc200..df6549e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -4,29 +4,30 @@ COPY . /src WORKDIR /src -ARG BUILD_DEPS="curl gcc g++ libpcap-dev" -ARG OUI_SRC="http://standards-oui.ieee.org/oui.txt" +ARG OUI_SRC="http://standards-oui.ieee.org/oui/oui.txt" -RUN apk add --no-cache ${BUILD_DEPS} && python -m venv "/opt/venv" +ENV VIRTUAL_ENV="/opt/venv" -RUN curl --location --silent --output "/src/dshell/data/oui.txt" "${OUI_SRC}" +RUN apk add cargo curl g++ gcc rust libpcap-dev libffi-dev \ + && python3 -m venv "${VIRTUAL_ENV}" \ + && curl --location --silent --output "/src/dshell/data/oui.txt" "${OUI_SRC}" -ENV PATH="/opt/venv/bin:${PATH}" +ENV PATH="${VIRTUAL_ENV}/bin:${PATH}" -RUN pip install --upgrade pip wheel && pip install --use-feature=2020-resolver . +RUN pip install --upgrade pip wheel && pip install . FROM python:3-alpine -ARG RUN_DEPS="bash libstdc++ libpcap" +ENV VIRTUAL_ENV="/opt/venv" -COPY --from=builder /opt/venv /opt/venv +COPY --from=builder "${VIRTUAL_ENV}/" "${VIRTUAL_ENV}/" -RUN apk add --no-cache ${RUN_DEPS} +RUN apk add --no-cache bash libstdc++ libpcap VOLUME ["/data"] WORKDIR "/data" -ENV PATH="/opt/venv/bin:${PATH}" +ENV PATH="${VIRTUAL_ENV}/bin:${PATH}" ENTRYPOINT ["dshell"] From 1c1269165fd9fdb70f53c6aec66aa3771ed29016 Mon Sep 17 00:00:00 2001 From: J Date: Fri, 4 Mar 2022 11:42:42 -0500 Subject: [PATCH 138/166] Update README.md updated README.md to clarify install location for GeoIP files --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 10a2f6a..b597a8e 100644 --- a/README.md +++ b/README.md @@ -56,8 +56,8 @@ Key features: ## Installation 1. Install Dshell with pip - * `sudo python3 -m pip install Dshell/` OR `sudo python3 -m pip install ` -2. Configure geoip2 by moving the MaxMind data files (GeoLite2-ASN.mmdb, GeoLite2-City.mmdb, GeoLite2-Country.mmdb) to <install-location>/data/GeoIP/ + * `python3 -m pip install Dshell/` OR `python3 -m pip install ` +2. Configure geoip2 by moving the MaxMind data files (GeoLite2-ASN.mmdb, GeoLite2-City.mmdb, GeoLite2-Country.mmdb) to [...]/site-packages/dshell/data/GeoIP/ 3. Run `dshell`. This should drop you into a `Dshell> ` prompt. ## Basic Usage From 7bf660ad761bd14dea3ff95eab69330d979510f9 Mon Sep 17 00:00:00 2001 From: Adam Maddock Date: Mon, 14 Mar 2022 13:50:28 +0000 Subject: [PATCH 139/166] update to httpdump module --- dshell/plugins/http/httpdump.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/dshell/plugins/http/httpdump.py b/dshell/plugins/http/httpdump.py index fcf200a..71362a5 100644 --- a/dshell/plugins/http/httpdump.py +++ b/dshell/plugins/http/httpdump.py @@ -163,6 +163,15 @@ def http_handler(self, conn, request, response): kwargs['endtime'] = None kwargs['serverbytes'] = 0 + if post_params: + kwargs['post_params'] = post_params + if url_params: + kwargs['url_params'] = url_params + if client_cookie: + kwargs['client_cookie'] = client_cookie + if server_cookie: + kwargs['server_cookie'] = server_cookie + self.write('\n'.join(msg), **kwargs) return conn, request, response From a7c27c8a8099cabc9167d123bdfce4532cfc3c68 Mon Sep 17 00:00:00 2001 From: J Date: Mon, 6 Mar 2023 10:26:04 -0500 Subject: [PATCH 140/166] Update setup.py to require pcapy-ng Changed setup.py install_requires list to replace the now unsupported pcapy library with pcapy-ng. Also increased Dshell version number and required Python version. --- setup.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/setup.py b/setup.py index 2b896cb..4441e07 100644 --- a/setup.py +++ b/setup.py @@ -2,11 +2,11 @@ setup( name="Dshell", - version="3.2.1", + version="3.2.2", author="USArmyResearchLab", description="An extensible network forensic analysis framework", url="https://github.com/USArmyResearchLab/Dshell", - python_requires='>=3.6', + python_requires='>=3.8', packages=find_packages(), package_data={ "dshell": ["data/dshellrc", "data/GeoIP/readme.txt"], @@ -20,7 +20,7 @@ ], install_requires=[ "geoip2", - "pcapy", + "pcapy-ng", "pypacker", "pyopenssl", "elasticsearch", From b11ac38e370111318bd5ffa48636d80306df72d5 Mon Sep 17 00:00:00 2001 From: J Date: Mon, 6 Mar 2023 10:28:34 -0500 Subject: [PATCH 141/166] Netflowout bug fix Updated the default netflowout template string for packets and blobs to use the automatically created "data" field instead of the inconsistent custom "msg" field --- dshell/output/netflowout.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dshell/output/netflowout.py b/dshell/output/netflowout.py index 48469ca..27f8581 100644 --- a/dshell/output/netflowout.py +++ b/dshell/output/netflowout.py @@ -18,8 +18,8 @@ class NetflowOutput(Output): _DESCRIPTION = "Flow (connection overview) format output" # Define two types of formats: # Those for plugins handling individual packets (not really helpful) - _PACKET_FORMAT = "%(ts)s %(sip)16s -> %(dip)16s (%(sipcc)s -> %(dipcc)s) %(protocol)5s %(sport)6s %(dport)6s %(bytes)7s %(msg)s\n" - _PACKET6_FORMAT = "%(ts)s %(sip)40s -> %(dip)40s (%(sipcc)s -> %(dipcc)s) %(protocol)5s %(sport)6s %(dport)6s %(bytes)7s %(msg)s\n" + _PACKET_FORMAT = "%(ts)s %(sip)16s -> %(dip)16s (%(sipcc)s -> %(dipcc)s) %(protocol)5s %(sport)6s %(dport)6s %(bytes)7s %(data)s\n" + _PACKET6_FORMAT = "%(ts)s %(sip)40s -> %(dip)40s (%(sipcc)s -> %(dipcc)s) %(protocol)5s %(sport)6s %(dport)6s %(bytes)7s %(data)s\n" # And those plugins handling full connections (more useful and common) _CONNECTION_FORMAT = "%(starttime)s %(clientip)16s -> %(serverip)16s (%(clientcc)s -> %(servercc)s) %(protocol)5s %(clientport)6s %(serverport)6s %(clientpackets)5s %(serverpackets)5s %(clientbytes)7s %(serverbytes)7s %(duration)-.4fs %(data)s\n" _CONNECTION6_FORMAT = "%(starttime)s %(clientip)40s -> %(serverip)40s (%(clientcc)s -> %(servercc)s) %(protocol)5s %(clientport)6s %(serverport)6s %(clientpackets)5s %(serverpackets)5s %(clientbytes)7s %(serverbytes)7s %(duration)-.4fs %(data)s\n" From 8fed00cd84003a621b7bb15d68294712ffda26dc Mon Sep 17 00:00:00 2001 From: J Date: Mon, 6 Mar 2023 10:37:00 -0500 Subject: [PATCH 142/166] Raw packet bytes in Packet info and comment updates Added the raw packet bytes to the Packet.info() output in the new 'rawpkt' key. This allows pcapout to function as intended. Also minor updates to some doc strings. --- dshell/core.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/dshell/core.py b/dshell/core.py index 8452036..185c2c4 100644 --- a/dshell/core.py +++ b/dshell/core.py @@ -802,6 +802,7 @@ def __init__(self, plugin, pktlen, pkt, ts): Attributes: ts: timestamp of packet dt: datetime of packet + frame: sequential packet number as read from data stream pkt: pypacker object for the packet rawpkt: raw bytestring of the packet pktlen: length of packet @@ -1052,6 +1053,7 @@ def info(self): """ d = {k: v for k, v in self.__dict__.items() if not k.startswith('_')} d['byte_count'] = self.byte_count + d['rawpkt'] = self.pkt.bin() del d['pkt'] return d @@ -1783,7 +1785,7 @@ def reassemble(self, allow_padding=True, allow_overlap=True, padding=b'\x00'): def info(self): """ Provides a dictionary with information about a blob. Useful for - calls to a plugin's write() function, e.g. self.write(\\*\\*conn.info()) + calls to a plugin's write() function, e.g. self.write(\\*\\*blob.info()) Returns: Dictionary with information From 7aa565b87443457299d40c7738373ae5c3d4465d Mon Sep 17 00:00:00 2001 From: J Date: Mon, 6 Mar 2023 11:05:38 -0500 Subject: [PATCH 143/166] Update README.md Updated README.md file with new requirements, information, and example output --- README.md | 48 ++++++++++++------------------------------------ 1 file changed, 12 insertions(+), 36 deletions(-) diff --git a/README.md b/README.md index b597a8e..bed66e8 100644 --- a/README.md +++ b/README.md @@ -5,14 +5,16 @@ Key features: * Deep packet analysis using specialized plugins * Robust stream reassembly * IPv4 and IPv6 support -* Custom output handlers +* Multiple user-selectable output formats and the ability to create custom output handlers * Chainable plugins +* Parallel processing option to divide the handling of data source into separate Python processes +* Enables development of external plugin packs to share and install new externally developed plugins without overlapping the core Dshell plugin directories ## Requirements -* Linux (developed on Red Hat Enterprise Linux 6.7) -* Python 3 (developed with Python 3.6.2) +* Linux (developed on Ubuntu 20.04 LTS) +* Python 3 (developed with Python 3.8.10) * [pypacker](https://gitlab.com/mike01/pypacker) -* [pcapy](https://github.com/helpsystems/pcapy) +* [pcapy-ng](https://github.com/stamparm/pcapy-ng/) * [pyOpenSSL](https://github.com/pyca/pyopenssl) * [geoip2](https://github.com/maxmind/GeoIP2-python) * [MaxMind GeoIP2 datasets](https://dev.maxmind.com/geoip/geoip2/geolite2/) @@ -27,32 +29,6 @@ Key features: * [pyJA3](https://github.com/salesforce/ja3/tree/master/python) * used in the tls plugin -## Major Changes Since Previous Release -* This is a major framework update to Dshell. Plugins written for the previous version are not compatible with this version, and vice versa. -* Uses Python 3 - * Rewritten in Python 3 from the ground up. Python 2 language deprecated on [1 JAN 2020](https://www.python.org/doc/sunset-python-2/) - * By extension, dpkt and pypcap have been replaced with Python3-friendly pypacker and pcapy (respectively). -* Is a Python package - * Converted into a single package, removing the need for the shell to set several environment variables. - * Allows easier use of Dshell plugins in other Python scripts -* Changed "decoders" to "plugins" - * Primarily a word-swap, to clarify that "decoders" can do more than simply decode traffic, and to put Dshell more in line with the terminology of other frameworks. -* Significant reduction in camelCase functions, replaced with more Pythonic snake\_case functions. - * Notable examples include blobHandler->blob\_handler, rawHandler->raw\_handler, connectionInitHandler->connection\_init\_handler, etc. -* All plugins are now chainable - * To accommodate this, handler functions in plugins must now use return statements indicating whether a packet, connection, or similar will continue to the next plugin. The type of object(s) to return depends on the type of handler, but will generally match the types of the handler's input. Dshell will display a warning if it's not the right type. -* Plugins can now use all output modules\* available to the command line switch, -O - * That does not mean every output module will be _useful_ to every plugin (e.g. using netflow output for a plugin that looks at individual packets), but they are available. - * alert(), write(), and dump() are now the same function: write() - * Output modules can be listed with a new flag in decode.py, --list-output or --lo - * Arguments for output modules are now passed with the --oargs command-line argument - * \* pcapout is (currently) the exception to this rule. A method has yet to arise that allows it to work with connection-based plugins -* No more dObj declaration - * decode.py just looks for the class named DshellPlugin and creates an instance of that -* Improved error handling - * Dshell handles more of the most common exceptions during everyday use -* Enables development of external plugin packs, allowing the sharing and installation of new, externally-developed plugins without overlapping the core Dshell libraries. - ## Installation 1. Install Dshell with pip @@ -69,7 +45,7 @@ Key features: * `decode -p ` * Display information about a plugin, including available command line flags * `decode -p ` - * Run the selected plugin on a pcap file + * Run the selected plugin on a pcap or pcapng file * `decode -p + ` * Chain two (or more) plugins together and run them on a pcap file * `decode -p -i ` @@ -79,7 +55,7 @@ Key features: Showing DNS lookups in [sample traffic](http://wiki.wireshark.org/SampleCaptures#General_.2F_Unsorted) ``` -Dshell> decode -p dns ~/pcap/dns.cap |sort +Dshell> decode -p dns ~/pcap/dns.cap | sort [DNS] 2005-03-30 03:47:46 192.168.170.8:32795 -- 192.168.170.20:53 ** ID: 4146, TXT? google.com., TXT: b'\x0fv=spf1 ptr ?all' ** [DNS] 2005-03-30 03:47:50 192.168.170.8:32795 -- 192.168.170.20:53 ** ID: 63343, MX? google.com., MX: b'\x00(\x05smtp4\xc0\x0c', MX: b'\x00\n\x05smtp5\xc0\x0c', MX: b'\x00\n\x05smtp6\xc0\x0c', MX: b'\x00\n\x05smtp1\xc0\x0c', MX: b'\x00\n\x05smtp2\xc0\x0c', MX: b'\x00(\x05smtp3\xc0\x0c' ** [DNS] 2005-03-30 03:47:59 192.168.170.8:32795 -- 192.168.170.20:53 ** ID: 18849, LOC? google.com. ** @@ -165,8 +141,8 @@ Dshell> decode -p country+netflow --country_code=JP ~/pcap/SkypeIRC.cap Collecting DNS traffic from several files and storing it in a new pcap file. ``` -Dshell> decode -p dns+pcapwriter --pcapwriter_outfile=test.pcap ~/pcap/*.cap >/dev/null -Dshell> tcpdump -nnr test.pcap |head +Dshell> decode -p dns+pcapwriter --pcapwriter_outfile=test.pcap ~/pcap/*.cap > /dev/null +Dshell> tcpdump -nnr test.pcap | head reading from file test.pcap, link-type EN10MB (Ethernet) 15:36:08.670569 IP 192.168.1.2.2131 > 192.168.1.1.53: 40209+ A? ui.skype.com. (30) 15:36:08.670687 IP 192.168.1.2.2131 > 192.168.1.1.53: 40210+ AAAA? ui.skype.com. (30) @@ -184,8 +160,8 @@ Collecting TFTP data and converting alerts to JSON format using [sample traffic] ``` Dshell> decode -p tftp -O jsonout ~/pcap/tftp_*.pcap -{"dport": 3445, "dip": "192.168.0.10", "data": "read rfc1350.txt (24599 bytes) ", "sport": 50618, "readwrite": "read", "sip": "192.168.0.253", "plugin": "tftp", "ts": 1367411051.972852, "filename": "rfc1350.txt"} -{"dport": 2087, "dip": "192.168.0.13", "data": "write rfc1350.txt (24599 bytes) ", "sport": 57509, "readwrite": "write", "sip": "192.168.0.1", "plugin": "tftp", "ts": 1367053679.45274, "filename": "rfc1350.txt"} +{"ts": 1367411051.972852, "sip": "192.168.0.253", "sport": 50618, "dip": "192.168.0.10", "dport": 3445, "readwrite": "read", "filename": "rfc1350.txt", "plugin": "tftp", "pcapfile": "/home/pcap/tftp_rrq.pcap", "data": "read rfc1350.txt (24599 bytes) "} +{"ts": 1367053679.45274, "sip": "192.168.0.1", "sport": 57509, "dip": "192.168.0.13", "dport": 2087, "readwrite": "write", "filename": "rfc1350.txt", "plugin": "tftp", "pcapfile": "/home/pcap/tftp_wrq.pcap", "data": "write rfc1350.txt (24599 bytes) "} ``` Running a plugin within a separate Python script using [sample traffic](https://wiki.wireshark.org/SampleCaptures#TFTP) From cf7527116da0f89f3edc1336acf09ca73d1f2f9e Mon Sep 17 00:00:00 2001 From: J Date: Mon, 6 Mar 2023 11:07:18 -0500 Subject: [PATCH 144/166] Update README Updated README file with new requirements, information, and example output --- README | 52 ++++++++++++++-------------------------------------- 1 file changed, 14 insertions(+), 38 deletions(-) diff --git a/README b/README index 10a2f6a..bed66e8 100644 --- a/README +++ b/README @@ -5,14 +5,16 @@ Key features: * Deep packet analysis using specialized plugins * Robust stream reassembly * IPv4 and IPv6 support -* Custom output handlers +* Multiple user-selectable output formats and the ability to create custom output handlers * Chainable plugins +* Parallel processing option to divide the handling of data source into separate Python processes +* Enables development of external plugin packs to share and install new externally developed plugins without overlapping the core Dshell plugin directories ## Requirements -* Linux (developed on Red Hat Enterprise Linux 6.7) -* Python 3 (developed with Python 3.6.2) +* Linux (developed on Ubuntu 20.04 LTS) +* Python 3 (developed with Python 3.8.10) * [pypacker](https://gitlab.com/mike01/pypacker) -* [pcapy](https://github.com/helpsystems/pcapy) +* [pcapy-ng](https://github.com/stamparm/pcapy-ng/) * [pyOpenSSL](https://github.com/pyca/pyopenssl) * [geoip2](https://github.com/maxmind/GeoIP2-python) * [MaxMind GeoIP2 datasets](https://dev.maxmind.com/geoip/geoip2/geolite2/) @@ -27,37 +29,11 @@ Key features: * [pyJA3](https://github.com/salesforce/ja3/tree/master/python) * used in the tls plugin -## Major Changes Since Previous Release -* This is a major framework update to Dshell. Plugins written for the previous version are not compatible with this version, and vice versa. -* Uses Python 3 - * Rewritten in Python 3 from the ground up. Python 2 language deprecated on [1 JAN 2020](https://www.python.org/doc/sunset-python-2/) - * By extension, dpkt and pypcap have been replaced with Python3-friendly pypacker and pcapy (respectively). -* Is a Python package - * Converted into a single package, removing the need for the shell to set several environment variables. - * Allows easier use of Dshell plugins in other Python scripts -* Changed "decoders" to "plugins" - * Primarily a word-swap, to clarify that "decoders" can do more than simply decode traffic, and to put Dshell more in line with the terminology of other frameworks. -* Significant reduction in camelCase functions, replaced with more Pythonic snake\_case functions. - * Notable examples include blobHandler->blob\_handler, rawHandler->raw\_handler, connectionInitHandler->connection\_init\_handler, etc. -* All plugins are now chainable - * To accommodate this, handler functions in plugins must now use return statements indicating whether a packet, connection, or similar will continue to the next plugin. The type of object(s) to return depends on the type of handler, but will generally match the types of the handler's input. Dshell will display a warning if it's not the right type. -* Plugins can now use all output modules\* available to the command line switch, -O - * That does not mean every output module will be _useful_ to every plugin (e.g. using netflow output for a plugin that looks at individual packets), but they are available. - * alert(), write(), and dump() are now the same function: write() - * Output modules can be listed with a new flag in decode.py, --list-output or --lo - * Arguments for output modules are now passed with the --oargs command-line argument - * \* pcapout is (currently) the exception to this rule. A method has yet to arise that allows it to work with connection-based plugins -* No more dObj declaration - * decode.py just looks for the class named DshellPlugin and creates an instance of that -* Improved error handling - * Dshell handles more of the most common exceptions during everyday use -* Enables development of external plugin packs, allowing the sharing and installation of new, externally-developed plugins without overlapping the core Dshell libraries. - ## Installation 1. Install Dshell with pip - * `sudo python3 -m pip install Dshell/` OR `sudo python3 -m pip install ` -2. Configure geoip2 by moving the MaxMind data files (GeoLite2-ASN.mmdb, GeoLite2-City.mmdb, GeoLite2-Country.mmdb) to <install-location>/data/GeoIP/ + * `python3 -m pip install Dshell/` OR `python3 -m pip install ` +2. Configure geoip2 by moving the MaxMind data files (GeoLite2-ASN.mmdb, GeoLite2-City.mmdb, GeoLite2-Country.mmdb) to [...]/site-packages/dshell/data/GeoIP/ 3. Run `dshell`. This should drop you into a `Dshell> ` prompt. ## Basic Usage @@ -69,7 +45,7 @@ Key features: * `decode -p ` * Display information about a plugin, including available command line flags * `decode -p ` - * Run the selected plugin on a pcap file + * Run the selected plugin on a pcap or pcapng file * `decode -p + ` * Chain two (or more) plugins together and run them on a pcap file * `decode -p -i ` @@ -79,7 +55,7 @@ Key features: Showing DNS lookups in [sample traffic](http://wiki.wireshark.org/SampleCaptures#General_.2F_Unsorted) ``` -Dshell> decode -p dns ~/pcap/dns.cap |sort +Dshell> decode -p dns ~/pcap/dns.cap | sort [DNS] 2005-03-30 03:47:46 192.168.170.8:32795 -- 192.168.170.20:53 ** ID: 4146, TXT? google.com., TXT: b'\x0fv=spf1 ptr ?all' ** [DNS] 2005-03-30 03:47:50 192.168.170.8:32795 -- 192.168.170.20:53 ** ID: 63343, MX? google.com., MX: b'\x00(\x05smtp4\xc0\x0c', MX: b'\x00\n\x05smtp5\xc0\x0c', MX: b'\x00\n\x05smtp6\xc0\x0c', MX: b'\x00\n\x05smtp1\xc0\x0c', MX: b'\x00\n\x05smtp2\xc0\x0c', MX: b'\x00(\x05smtp3\xc0\x0c' ** [DNS] 2005-03-30 03:47:59 192.168.170.8:32795 -- 192.168.170.20:53 ** ID: 18849, LOC? google.com. ** @@ -165,8 +141,8 @@ Dshell> decode -p country+netflow --country_code=JP ~/pcap/SkypeIRC.cap Collecting DNS traffic from several files and storing it in a new pcap file. ``` -Dshell> decode -p dns+pcapwriter --pcapwriter_outfile=test.pcap ~/pcap/*.cap >/dev/null -Dshell> tcpdump -nnr test.pcap |head +Dshell> decode -p dns+pcapwriter --pcapwriter_outfile=test.pcap ~/pcap/*.cap > /dev/null +Dshell> tcpdump -nnr test.pcap | head reading from file test.pcap, link-type EN10MB (Ethernet) 15:36:08.670569 IP 192.168.1.2.2131 > 192.168.1.1.53: 40209+ A? ui.skype.com. (30) 15:36:08.670687 IP 192.168.1.2.2131 > 192.168.1.1.53: 40210+ AAAA? ui.skype.com. (30) @@ -184,8 +160,8 @@ Collecting TFTP data and converting alerts to JSON format using [sample traffic] ``` Dshell> decode -p tftp -O jsonout ~/pcap/tftp_*.pcap -{"dport": 3445, "dip": "192.168.0.10", "data": "read rfc1350.txt (24599 bytes) ", "sport": 50618, "readwrite": "read", "sip": "192.168.0.253", "plugin": "tftp", "ts": 1367411051.972852, "filename": "rfc1350.txt"} -{"dport": 2087, "dip": "192.168.0.13", "data": "write rfc1350.txt (24599 bytes) ", "sport": 57509, "readwrite": "write", "sip": "192.168.0.1", "plugin": "tftp", "ts": 1367053679.45274, "filename": "rfc1350.txt"} +{"ts": 1367411051.972852, "sip": "192.168.0.253", "sport": 50618, "dip": "192.168.0.10", "dport": 3445, "readwrite": "read", "filename": "rfc1350.txt", "plugin": "tftp", "pcapfile": "/home/pcap/tftp_rrq.pcap", "data": "read rfc1350.txt (24599 bytes) "} +{"ts": 1367053679.45274, "sip": "192.168.0.1", "sport": 57509, "dip": "192.168.0.13", "dport": 2087, "readwrite": "write", "filename": "rfc1350.txt", "plugin": "tftp", "pcapfile": "/home/pcap/tftp_wrq.pcap", "data": "write rfc1350.txt (24599 bytes) "} ``` Running a plugin within a separate Python script using [sample traffic](https://wiki.wireshark.org/SampleCaptures#TFTP) From df7b491fb4e2436855bc99a2f69ba9780f1e4314 Mon Sep 17 00:00:00 2001 From: dek <41297634+dek443@users.noreply.github.com> Date: Wed, 5 Apr 2023 13:00:40 -0400 Subject: [PATCH 145/166] Add files via upload Please check out the new guides for the decoder-shell (Dshell) framework: the Dshell User Guide and the Dshell Developer Guide. The Dshell User Guide is a general user guide which details installation and both basic and advanced analysis usage with examples. The Dshell Developer Guide is a guide to plugin development which provides basic examples, core function and class definitions, and an overview of data flow. This guide will help end users develop new, custom plugins as well as modify existing plugins. --- Dshell_Developer_Guide.pdf | Bin 0 -> 609633 bytes Dshell_User_Guide.pdf | Bin 0 -> 754263 bytes 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 Dshell_Developer_Guide.pdf create mode 100644 Dshell_User_Guide.pdf diff --git a/Dshell_Developer_Guide.pdf b/Dshell_Developer_Guide.pdf new file mode 100644 index 0000000000000000000000000000000000000000..dd5cb4ec915f35d468210308830fc9dc3b42e365 GIT binary patch literal 609633 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

        (VC?Jzu-4zEahQmDr& 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�UIux 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 z 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%0AMvS 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 VJ=6pP70_A?R4OWQ1qlq){|`l8WkLV| literal 0 HcmV?d00001 diff --git a/Dshell_User_Guide.pdf b/Dshell_User_Guide.pdf new file mode 100644 index 0000000000000000000000000000000000000000..21badf1c1f777ab3cdea3099e14067bf7fb92928 GIT binary patch literal 754263 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 z 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 z%0A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 <%{KEfWHC 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

          hi6BhM=kd9J3QLIM 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

          2gXIi!9#WO+GZ*7mc$q1hqm0hK6#p)M7L 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 literal 0 HcmV?d00001 From 35ef4781e1749b3d14a5552e84d8a6eb7d021c49 Mon Sep 17 00:00:00 2001 From: dek <41297634+dek443@users.noreply.github.com> Date: Wed, 5 Apr 2023 15:02:50 -0400 Subject: [PATCH 146/166] Update README.md Added references to the Dshell User Guide and the Dshell Developer Guide. --- README.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/README.md b/README.md index bed66e8..2200f2e 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,14 @@ Key features: * Parallel processing option to divide the handling of data source into separate Python processes * Enables development of external plugin packs to share and install new externally developed plugins without overlapping the core Dshell plugin directories +## Guides +* [Dshell User Guide](Dshell_User_Guide.pdf) + * A guide to installation as well as both basic and advanced analysis with examples + * Helps new and experienced end users with using and understanding the decoder-shell (Dshell) framework +* [Dshell Developer Guide](Dshell_Developer_Guide.pdf) + * A guide to plugin development with basic examples, as well as core function and class definitions, and an overview of data flow + * Helps end users develop new, custom Dshell plugins as well as modify existing plugins + ## Requirements * Linux (developed on Ubuntu 20.04 LTS) * Python 3 (developed with Python 3.8.10) From a59272ce15620f5f64e6f31261e207e2d54c1a56 Mon Sep 17 00:00:00 2001 From: dek <41297634+dek443@users.noreply.github.com> Date: Wed, 5 Apr 2023 15:03:59 -0400 Subject: [PATCH 147/166] Update README Added references to the Dshell User Guide and the Dshell Developer Guide. --- README | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/README b/README index bed66e8..e31bf5a 100644 --- a/README +++ b/README @@ -10,6 +10,14 @@ Key features: * Parallel processing option to divide the handling of data source into separate Python processes * Enables development of external plugin packs to share and install new externally developed plugins without overlapping the core Dshell plugin directories +## Guides +* [Dshell User Guide](Dshell_User_Guide.pdf) + * A guide to installation as well as both basic and advanced analysis with examples + * Helps new and experienced end users with using and understanding the decoder-shell (Dshell) framework +* [Dshell Developer Guide](Dshell_Developer_Guide.pdf) + * A guide to plugin development with basic examples, as well as core function and class definitions, and an overview of data flow + * Helps end users develop new, custom Dshell plugins as well as modify existing plugins + ## Requirements * Linux (developed on Ubuntu 20.04 LTS) * Python 3 (developed with Python 3.8.10) From bcb3c37d98fe16e0180f068c41260fa276ce432e Mon Sep 17 00:00:00 2001 From: dek <41297634+dek443@users.noreply.github.com> Date: Wed, 19 Apr 2023 16:48:28 -0400 Subject: [PATCH 148/166] Update decode.py Added color-blind-friendly command-line flag. Optimized looping through plugin_chain to set user-defined output arguments. --- dshell/decode.py | 32 +++++++++++++++++++------------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/dshell/decode.py b/dshell/decode.py index 7b0c765..4e5cbb6 100755 --- a/dshell/decode.py +++ b/dshell/decode.py @@ -232,26 +232,27 @@ def main(plugin_args=None, **kwargs): for plugin in plugin_chain: plugin.out.set_oargs(**oargs) - # If writing to a file, set for each output module here - if kwargs.get("outfile", None): - for plugin in plugin_chain: + for plugin in plugin_chain: + # If writing to a file, set for each output module here + if kwargs.get("outfile", None): plugin.out.reset_fh(filename=kwargs["outfile"]) - # Set nobuffer mode if that's what the user wants - if kwargs.get("nobuffer", False): - for plugin in plugin_chain: + # Set nobuffer mode if that's what the user wants + if kwargs.get("nobuffer", False): plugin.out.nobuffer = True + + # Set color blind friendly mode + if kwargs.get("cbf", False): + plugin.out.cbf = True - # Set the extra flag for all output modules - if kwargs.get("extra", False): - for plugin in plugin_chain: + # Set the extra flag for all output modules + if kwargs.get("extra", False): plugin.out.extra = True plugin.out.set_format(plugin.out.format) - # Set the BPF filters - # Each plugin has its own default BPF that will be extended or replaced - # based on --no-vlan, --ebpf, or --bpf arguments. - for plugin in plugin_chain: + # Set the BPF filters + # Each plugin has its own default BPF that will be extended or replaced + # based on --no-vlan, --ebpf, or --bpf arguments. if kwargs.get("bpf", None): plugin.bpf = kwargs.get("bpf", "") continue @@ -579,6 +580,9 @@ def main_command_line(): output_group.add_argument("--no-buffer", action="store_true", help="Do not buffer plugin output", dest="nobuffer") + output_group.add_argument("-cbf", "--color-blind-friendly", action="store_true", + help="Activate color blind friendly mode, colorout and htmlout output modules use yellow/gold in place of red and different shades of green/yellow/blue are used to help better differentiate between them", + dest="cbf") output_group.add_argument("-x", "--extra", action="store_true", help="Appends extra data to all plugin output.") # TODO Figure out how to make --extra flag play nicely with user-only @@ -619,6 +623,8 @@ def main_command_line(): help='List all available plugins', dest='list') parser_short.add_argument("--lo", "--list-output", action="store_true", help="List available output modules") + parser_short.add_argument("-cbf", "--color-blind-friendly", action="store_true", + help="Activate color blind friendly mode, colorout and htmlout output modules use yellow/gold in place of red and different shades of green/yellow/blue are used to help better differentiate between them") # FIXME: Should this duplicate option be removed? parser_short.add_argument("-o", "--omodule", type=str, metavar="MODULE", help="Use specified output module for plugins instead of defaults. For example, --omodule=jsonout for JSON output.") From 5d19c03a7770ef16a99f740e2881ca53620eeae2 Mon Sep 17 00:00:00 2001 From: dek <41297634+dek443@users.noreply.github.com> Date: Wed, 19 Apr 2023 16:57:17 -0400 Subject: [PATCH 149/166] Update output.py Added color-blind-friendly, "cbf" argument (user-defined command-line option) to base-level output class to be used by colorout and htmlout output modules. --- dshell/output/output.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/dshell/output/output.py b/dshell/output/output.py index 41b57af..316b508 100644 --- a/dshell/output/output.py +++ b/dshell/output/output.py @@ -29,6 +29,9 @@ class Output: fh : existing open file handle file : filename to write to, assuming fh is not defined mode : mode to open file, assuming fh is not defined (default 'w') + cbf : activate color blind friendly mode, colorout and htmlout output + modules use yellow/gold in place of red and different shades of + green/yellow/blue are used to help better differentiate between them """ _DEFAULT_FORMAT = "%(data)s\n" _DEFAULT_TIME_FORMAT = "%Y-%m-%d %H:%M:%S" @@ -37,7 +40,7 @@ class Output: def __init__( self, file=None, fh=None, mode='w', format=None, timeformat=None, delimiter=None, nobuffer=False, - noclobber=False, extra=None, **unused_kwargs + noclobber=False, extra=None, cbf=False, **unused_kwargs ): self.format_fields = [] self.timeformat = timeformat or self._DEFAULT_TIME_FORMAT @@ -46,6 +49,7 @@ def __init__( self.noclobber = noclobber self.extra = extra self.mode = mode + self.cbf = cbf # Must define attributes even if they are setup in different function. self.format_fields = None From 0ad266fd676c6c166ffcfe39fba2439e9c0c5335 Mon Sep 17 00:00:00 2001 From: dek <41297634+dek443@users.noreply.github.com> Date: Wed, 19 Apr 2023 17:06:54 -0400 Subject: [PATCH 150/166] Update colorout.py Activate color blind friendly mode in colorout output module. Use ANSI color yellow (darker yellow) in place of red. Different shades of green/yellow/blue are used which helps better differentiate between them. The base-level Output() class' setup() function is called within the _premodule() function of the plugin using this output module, before capture starts or files are read. --- dshell/output/colorout.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/dshell/output/colorout.py b/dshell/output/colorout.py index be25c07..5511fc6 100644 --- a/dshell/output/colorout.py +++ b/dshell/output/colorout.py @@ -41,6 +41,11 @@ def __init__(self, *args, **kwargs): self.hexmode = kwargs.get('hex', False) self.format_is_set = False + def setup(self): + # activate color blind friendly mode + if self.cbf: + self.colors['cs'] = '33' #client-to-server is yellow + def write(self, *args, **kwargs): if not self.format_is_set: if 'clientip' in kwargs: From 1c8b28c8b31b48ace78410eb3aa548987b790a4c Mon Sep 17 00:00:00 2001 From: dek <41297634+dek443@users.noreply.github.com> Date: Wed, 19 Apr 2023 17:13:27 -0400 Subject: [PATCH 151/166] Update htmlout.py Activate color blind friendly mode in htmlout output module. Use HTML colors gold (darker yellow) in place of red, and sea green (lighter green) in place of green. Keep the HTML color blue the same. These different shades of green/yellow/blue are used to help better differentiate between them. The base-level Output() class' setup() function is called within the _premodule() function of the plugin using this output module, before capture starts or files are read. --- dshell/output/htmlout.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/dshell/output/htmlout.py b/dshell/output/htmlout.py index 3deea20..0e0a1da 100644 --- a/dshell/output/htmlout.py +++ b/dshell/output/htmlout.py @@ -73,6 +73,10 @@ def __init__(self, *args, **kwargs): self.format_is_set = False def setup(self): + # activate color blind friendly mode + if self.cbf: + self.colors['cs'] = 'gold' # client-to-server is gold (darker yellow) + self.colors['sc'] = 'seagreen' # server-to-client is sea green (lighter green) self.fh.write(self._HTML_HEADER) def write(self, *args, **kwargs): From 638c87b30f1c736734bb7e6c5733557df53bd543 Mon Sep 17 00:00:00 2001 From: dek <41297634+dek443@users.noreply.github.com> Date: Wed, 19 Apr 2023 17:33:09 -0400 Subject: [PATCH 152/166] Update colorout.py Removed TODO comment regarding making the colors configurable to be color blind friendly. --- dshell/output/colorout.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dshell/output/colorout.py b/dshell/output/colorout.py index 5511fc6..76e1cea 100644 --- a/dshell/output/colorout.py +++ b/dshell/output/colorout.py @@ -37,7 +37,7 @@ def __init__(self, *args, **kwargs): 'cs': '31', # client-to-server is red 'sc': '32', # server-to-client is green '--': '34', # everything else is blue - } # TODO configurable for color-blind users? + } self.hexmode = kwargs.get('hex', False) self.format_is_set = False From 93c5e937c7902df5130d13009eb3df47ff5a43c0 Mon Sep 17 00:00:00 2001 From: dek <41297634+dek443@users.noreply.github.com> Date: Thu, 20 Apr 2023 10:59:34 -0400 Subject: [PATCH 153/166] Update decode.py Updated argument parsing syntax for 'cbf' and 'acc' command-line options to conform with standard form used, '-' for single char options, '--' for multiple char options. --- dshell/decode.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dshell/decode.py b/dshell/decode.py index 4e5cbb6..62bd364 100755 --- a/dshell/decode.py +++ b/dshell/decode.py @@ -538,7 +538,7 @@ def main_command_line(): help="Show debug messages") parser.add_argument('-v', '--verbose', action="store_true", help="Show informational messages") - parser.add_argument('-acc', '--allcc', action="store_true", + parser.add_argument('--acc', '--allcc', action="store_true", help="Show all 3 GeoIP2 country code types (represented_country/registered_country/country)") parser.add_argument('-d', '-p', '--plugin', dest='plugin', type=str, action='append', metavar="PLUGIN", @@ -580,7 +580,7 @@ def main_command_line(): output_group.add_argument("--no-buffer", action="store_true", help="Do not buffer plugin output", dest="nobuffer") - output_group.add_argument("-cbf", "--color-blind-friendly", action="store_true", + output_group.add_argument("--cbf", "--color-blind-friendly", action="store_true", help="Activate color blind friendly mode, colorout and htmlout output modules use yellow/gold in place of red and different shades of green/yellow/blue are used to help better differentiate between them", dest="cbf") output_group.add_argument("-x", "--extra", action="store_true", @@ -623,7 +623,7 @@ def main_command_line(): help='List all available plugins', dest='list') parser_short.add_argument("--lo", "--list-output", action="store_true", help="List available output modules") - parser_short.add_argument("-cbf", "--color-blind-friendly", action="store_true", + parser_short.add_argument("--cbf", "--color-blind-friendly", action="store_true", help="Activate color blind friendly mode, colorout and htmlout output modules use yellow/gold in place of red and different shades of green/yellow/blue are used to help better differentiate between them") # FIXME: Should this duplicate option be removed? parser_short.add_argument("-o", "--omodule", type=str, metavar="MODULE", From a856793b7cd56ebf86e96116c404fb2784d5f65c Mon Sep 17 00:00:00 2001 From: dek <41297634+dek443@users.noreply.github.com> Date: Thu, 1 Jun 2023 11:46:52 -0400 Subject: [PATCH 154/166] Update README.md Updated geoip2 links/verbiage, fixed bug in "Running a Plugin Within a Separate Python Script Using Sample Traffic" example. --- README.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 2200f2e..cf5d778 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,9 @@ Key features: * [pcapy-ng](https://github.com/stamparm/pcapy-ng/) * [pyOpenSSL](https://github.com/pyca/pyopenssl) * [geoip2](https://github.com/maxmind/GeoIP2-python) - * [MaxMind GeoIP2 datasets](https://dev.maxmind.com/geoip/geoip2/geolite2/) + * [MaxMind GeoIP2 data sets](https://dev.maxmind.com/geoip/geolite2-free-geolocation-data) + * Used to map IP addresses to country codes + * See Installation section for configuration ## Optional * [oui.txt](http://standards-oui.ieee.org/oui.txt) @@ -41,7 +43,7 @@ Key features: 1. Install Dshell with pip * `python3 -m pip install Dshell/` OR `python3 -m pip install ` -2. Configure geoip2 by moving the MaxMind data files (GeoLite2-ASN.mmdb, GeoLite2-City.mmdb, GeoLite2-Country.mmdb) to [...]/site-packages/dshell/data/GeoIP/ +2. Configure geoip2 by placing the MaxMind GeoLite2 data set files (GeoLite2-ASN.mmdb, GeoLite2-City.mmdb, GeoLite2-Country.mmdb) in [...]/site-packages/dshell/data/GeoIP/ 3. Run `dshell`. This should drop you into a `Dshell> ` prompt. ## Basic Usage @@ -182,7 +184,7 @@ import dshell.plugins.tftp.tftp as tftp # Instantiate plugin plugin = tftp.DshellPlugin() # Define plugin-specific arguments, if needed -dargs = {plugin: {"outdir": "/tmp/"}} +dargs = {plugin: {"rip": True, "outdir": "/tmp/"}} # Add plugin(s) to plugin chain decode.plugin_chain = [plugin] # Run decode main function with all other arguments From bfa3db06ad55d1a5670447c28d2b12ae0f593b9d Mon Sep 17 00:00:00 2001 From: dek <41297634+dek443@users.noreply.github.com> Date: Thu, 1 Jun 2023 11:47:02 -0400 Subject: [PATCH 155/166] Update README Updated geoip2 links/verbiage, fixed bug in "Running a Plugin Within a Separate Python Script Using Sample Traffic" example. --- README | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/README b/README index e31bf5a..beda1a7 100644 --- a/README +++ b/README @@ -25,7 +25,9 @@ Key features: * [pcapy-ng](https://github.com/stamparm/pcapy-ng/) * [pyOpenSSL](https://github.com/pyca/pyopenssl) * [geoip2](https://github.com/maxmind/GeoIP2-python) - * [MaxMind GeoIP2 datasets](https://dev.maxmind.com/geoip/geoip2/geolite2/) + * [MaxMind GeoIP2 data sets](https://dev.maxmind.com/geoip/geolite2-free-geolocation-data) + * Used to map IP addresses to country codes + * See Installation section for configuration ## Optional * [oui.txt](http://standards-oui.ieee.org/oui.txt) @@ -41,7 +43,7 @@ Key features: 1. Install Dshell with pip * `python3 -m pip install Dshell/` OR `python3 -m pip install ` -2. Configure geoip2 by moving the MaxMind data files (GeoLite2-ASN.mmdb, GeoLite2-City.mmdb, GeoLite2-Country.mmdb) to [...]/site-packages/dshell/data/GeoIP/ +2. Configure geoip2 by placing the MaxMind GeoLite2 data set files (GeoLite2-ASN.mmdb, GeoLite2-City.mmdb, GeoLite2-Country.mmdb) in [...]/site-packages/dshell/data/GeoIP/ 3. Run `dshell`. This should drop you into a `Dshell> ` prompt. ## Basic Usage @@ -182,7 +184,7 @@ import dshell.plugins.tftp.tftp as tftp # Instantiate plugin plugin = tftp.DshellPlugin() # Define plugin-specific arguments, if needed -dargs = {plugin: {"outdir": "/tmp/"}} +dargs = {plugin: {"rip": True, "outdir": "/tmp/"}} # Add plugin(s) to plugin chain decode.plugin_chain = [plugin] # Run decode main function with all other arguments From 8f33ca72b025a9da35e05cdd0d87d35b4eb5b517 Mon Sep 17 00:00:00 2001 From: dek <41297634+dek443@users.noreply.github.com> Date: Thu, 1 Jun 2023 11:53:23 -0400 Subject: [PATCH 156/166] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index cf5d778..e1e0f6f 100644 --- a/README.md +++ b/README.md @@ -51,7 +51,7 @@ Key features: * `decode -l` * This will list all available plugins, alongside basic information about them * `decode -h` - * Show generic command-line flags available to most plugins + * Show generic command-line flags available to most plugins, such as the color blind friendly mode for all color output * `decode -p ` * Display information about a plugin, including available command line flags * `decode -p ` From 1cd0601675dffdcf750c4e3cd5a54b50e08563ae Mon Sep 17 00:00:00 2001 From: dek <41297634+dek443@users.noreply.github.com> Date: Thu, 1 Jun 2023 11:53:44 -0400 Subject: [PATCH 157/166] Update README --- README | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README b/README index beda1a7..29ea177 100644 --- a/README +++ b/README @@ -51,7 +51,7 @@ Key features: * `decode -l` * This will list all available plugins, alongside basic information about them * `decode -h` - * Show generic command-line flags available to most plugins + * Show generic command-line flags available to most plugins, such as the color blind friendly mode for all color output * `decode -p ` * Display information about a plugin, including available command line flags * `decode -p ` From 9c45414bbd5a3e0803f5ed8b3288211dee1b9fbf Mon Sep 17 00:00:00 2001 From: J Date: Mon, 29 Apr 2024 10:39:36 -0400 Subject: [PATCH 158/166] Updated CSV output module to fix oarg bug and add 'flows' convenience feature --- dshell/output/csvout.py | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/dshell/output/csvout.py b/dshell/output/csvout.py index 8ba9cbd..0ad2b9c 100644 --- a/dshell/output/csvout.py +++ b/dshell/output/csvout.py @@ -15,32 +15,24 @@ class CSVOutput(Output): A header row can be printed with --oarg header Additional fields can be included with --oarg fields=field1,field2,field3 + For example, MAC address can be included with --oarg fields=smac,dmac + Note: Field names must match the variable names in the plugin - Note: Field names much match the variable names in the plugin + Additional flow fields for connection can be included with --oarg flows """ # TODO refine plugin to do things like wrap quotes around long strings _DEFAULT_FIELDS = ['plugin', 'ts', 'sip', 'sport', 'dip', 'dport', 'data'] + _DEFAULT_FLOW_FIELDS = ['plugin', 'starttime', 'clientip', 'serverip', 'clientcc', 'servercc', 'protocol', 'clientport', 'serverport', 'clientpackets', 'serverpackets', 'clientbytes', 'serverbytes', 'duration', 'data'] _DEFAULT_DELIM = ',' _DESCRIPTION = "CSV format output" def __init__(self, *args, **kwargs): - self.delimiter = kwargs.get('delimiter', self._DEFAULT_DELIM) - if self.delimiter == 'tab': - self.delimiter = '\t' - - self.use_header = kwargs.get("header", False) - + self.use_header = False self.fields = list(self._DEFAULT_FIELDS) - exfields = kwargs.get("fields", "") - for field in exfields.split(','): - self.fields.append(field) - super().__init__(**kwargs) - self.set_format() - def set_format(self, _=None): "Set the format to a CSV list of fields" columns = [] @@ -54,6 +46,12 @@ def set_format(self, _=None): super().set_format(fmt) def set_oargs(self, **kwargs): + self.use_header = kwargs.pop("header", False) + if kwargs.pop("flows", False): + self.fields = list(self._DEFAULT_FLOW_FIELDS) + if exfields := kwargs.pop("fields", None): + for field in exfields.split(','): + self.fields.append(field) super().set_oargs(**kwargs) self.set_format() @@ -62,4 +60,4 @@ def setup(self): self.fh.write(self.delimiter.join([f for f in self.fields]) + "\n") -obj = CSVOutput +obj = CSVOutput \ No newline at end of file From 5d0263adb458b93244b89d21ecdc53484f9decf9 Mon Sep 17 00:00:00 2001 From: J Date: Mon, 29 Apr 2024 10:46:35 -0400 Subject: [PATCH 159/166] Updated netflow output module to fix grouping error and add 'header' oarg. Added "tab" delimiter to output.py. --- dshell/output/netflowout.py | 35 ++++++++++++++++++++++++++--------- dshell/output/output.py | 5 ++++- 2 files changed, 30 insertions(+), 10 deletions(-) diff --git a/dshell/output/netflowout.py b/dshell/output/netflowout.py index 27f8581..f27cc3f 100644 --- a/dshell/output/netflowout.py +++ b/dshell/output/netflowout.py @@ -13,6 +13,9 @@ class NetflowOutput(Output): separated by a forward-slash For example: --output=netflowout --oarg="group=clientip/serverip" + Note: Output when grouping is only generated at the end of analysis + + A header row can be printed before output using --oarg header """ _DESCRIPTION = "Flow (connection overview) format output" @@ -20,33 +23,48 @@ class NetflowOutput(Output): # Those for plugins handling individual packets (not really helpful) _PACKET_FORMAT = "%(ts)s %(sip)16s -> %(dip)16s (%(sipcc)s -> %(dipcc)s) %(protocol)5s %(sport)6s %(dport)6s %(bytes)7s %(data)s\n" _PACKET6_FORMAT = "%(ts)s %(sip)40s -> %(dip)40s (%(sipcc)s -> %(dipcc)s) %(protocol)5s %(sport)6s %(dport)6s %(bytes)7s %(data)s\n" + _PACKET_PRETTY_HEADER = "[start timestamp] [source IP] -> [destination IP] ([source country] -> [destination country]) [protocol] [source port] [destination port] [bytes] [message data]\n" # And those plugins handling full connections (more useful and common) _CONNECTION_FORMAT = "%(starttime)s %(clientip)16s -> %(serverip)16s (%(clientcc)s -> %(servercc)s) %(protocol)5s %(clientport)6s %(serverport)6s %(clientpackets)5s %(serverpackets)5s %(clientbytes)7s %(serverbytes)7s %(duration)-.4fs %(data)s\n" _CONNECTION6_FORMAT = "%(starttime)s %(clientip)40s -> %(serverip)40s (%(clientcc)s -> %(servercc)s) %(protocol)5s %(clientport)6s %(serverport)6s %(clientpackets)5s %(serverpackets)5s %(clientbytes)7s %(serverbytes)7s %(duration)-.4fs %(data)s\n" + _CONNECTION_PRETTY_HEADER = "[start timestamp] [client IP] -> [server IP] ([client country] -> [server country]) [protocol] [client port] [server port] [client packets] [server packets] [client bytes] [server bytes] [duration] [message data]\n" # TODO decide if IPv6 formats are necessary, and how to switch between them # and IPv4 formats # Default to packets since those fields are in both types of object _DEFAULT_FORMAT = _PACKET_FORMAT def __init__(self, *args, **kwargs): + self.group = False + self.group_cache = {} # results will be stored here, if grouping + self.format_is_set = False + self.use_header = False + Output.__init__(self, *args, **kwargs) + + def set_format(self, fmt, pretty_header=_PACKET_PRETTY_HEADER): + if self.use_header: + self.fh.write(str(pretty_header)) + return super().set_format(fmt) + + def set_oargs(self, **kwargs): + # Are we printing the format string as a file header? + self.use_header = kwargs.pop("header", False) # Are we grouping the results, and by what fields? if 'group' in kwargs: self.group = True - self.group_fields = kwargs['group'].split('/') + groupfields = kwargs.pop('group', '') + self.group_fields = groupfields.split('/') else: self.group = False - self.group_cache = {} # results will be stored here, if grouping - self.format_is_set = False - Output.__init__(self, *args, **kwargs) + super().set_oargs(**kwargs) def write(self, *args, **kwargs): # Change output format depending on if we're handling a connection or # a single packet if not self.format_is_set: if "clientip" in kwargs: - self.set_format(self._CONNECTION_FORMAT) + self.set_format(self._CONNECTION_FORMAT, self._CONNECTION_PRETTY_HEADER) else: - self.set_format(self._PACKET_FORMAT) + self.set_format(self._PACKET_FORMAT, self._PACKET_PRETTY_HEADER) self.format_is_set = True if self.group: @@ -55,7 +73,6 @@ def write(self, *args, **kwargs): try: key = tuple([kwargs[g] for g in self.group_fields]) except KeyError as e: - self.logger.error("Could not group by key %s" % str(e)) Output.write(self, *args, **kwargs) return if key not in self.group_cache: @@ -72,7 +89,7 @@ def write(self, *args, **kwargs): def close(self): if self.group: self.group = False # we're done grouping, so turn it off - for key in sorted(self.group_cache.keys()): + for key in self.group_cache.keys(): # write header by mapping key index with user's group list self.fh.write(' '.join([ '%s=%s' % (self.group_fields[i], key[i]) for i in range(len(self.group_fields))]) @@ -83,4 +100,4 @@ def close(self): self.fh.write("\n") Output.close(self) -obj = NetflowOutput +obj = NetflowOutput \ No newline at end of file diff --git a/dshell/output/output.py b/dshell/output/output.py index 316b508..60b53e8 100644 --- a/dshell/output/output.py +++ b/dshell/output/output.py @@ -91,7 +91,10 @@ def set_oargs(self, format=None, noclobber=None, delimiter=None, timeformat=None Process the standard oargs from the command line. """ if delimiter: - self.delimiter = delimiter + if delimiter == "tab": + self.delimiter = '\t' + else: + self.delimiter = delimiter if timeformat: self.timeformat = timeformat if noclobber: From 4636882068f9f1316694ddad55bff75b7108d69b Mon Sep 17 00:00:00 2001 From: J Date: Mon, 29 Apr 2024 11:07:22 -0400 Subject: [PATCH 160/166] Updates to core.py's handling of IP defragmentation to ensure that correct port numbers are used for reassembled packet. If first packet is missing, a debug message is printed and entire packet is dropped. --- dshell/core.py | 66 +++++++++++++++++++++++++++++++++----------------- 1 file changed, 44 insertions(+), 22 deletions(-) diff --git a/dshell/core.py b/dshell/core.py index 185c2c4..e358ab6 100644 --- a/dshell/core.py +++ b/dshell/core.py @@ -258,22 +258,43 @@ def recompile_bpf(self): else: raise e - def ipdefrag(self, pkt): + def ipdefrag(self, packet: 'Packet') -> 'Packet': """ IP fragment reassembly - """ - if isinstance(pkt, ip.IP): # IPv4 - f = self._packet_fragments[(pkt.src, pkt.dst, pkt.id)] - f[pkt.offset] = pkt - if not pkt.flags & 0x1: + Store the first seen packet, collect data from followup packets, then + glue it all together and update that first packet with new data + """ + pkt = packet.pkt + ipp = pkt.upper_layer + if isinstance(ipp, ip.IP): # IPv4 + f = self._packet_fragments[(ipp.src, ipp.dst, ipp.id)] + f[ipp.offset] = packet + + if not ipp.flags & 0x1: # If no more fragments (MF) + if len(f) <= 1 and 0 in f: + # If only one unfragmented packet, return that packet + del self._packet_fragments[(ipp.src, ipp.dst, ipp.id)] + return f[0] + elif 0 not in f: + logger.debug(f"Missing first fragment of fragmented packet. Dropping ({packet.sip} -> {packet.dip}: {ipp.id}:{ipp.flags}:{ipp.offset})") + del self._packet_fragments[(ipp.src, ipp.dst, ipp.id)] + return None + fkeys = sorted(f.keys()) data = b'' - for key in sorted(f.keys()): - data += f[key].body_bytes - del self._packet_fragments[(pkt.src, pkt.dst, pkt.id)] - newpkt = ip.IP(pkt.header_bytes + data) - newpkt.bin(update_auto_fields=True) # refresh checksum - return newpkt + firstpacket = f[fkeys[0]] + for key in fkeys: + data += f[key].pkt.upper_layer.body_bytes + newip = ip.IP(firstpacket.pkt.upper_layer.header_bytes + data) + newip.bin(update_auto_fields=True) # refresh checksum + firstpacket.pkt.upper_layer = newip + del self._packet_fragments[(ipp.src, ipp.dst, ipp.id)] + return Packet( + firstpacket.pkt.__len__, + firstpacket.pkt, + firstpacket.ts, + firstpacket.frame + ) elif isinstance(pkt, ip6.IP6): # IPv6 # TODO handle IPv6 offsets https://en.wikipedia.org/wiki/IPv6_packet#Fragment @@ -398,16 +419,14 @@ def consume_packet(self, packet: "Packet"): self.seen_packet_count.value += 1 # Attempt to perform defragmentation - if isinstance(packet.pkt.upper_layer, (ip.IP, ip6.IP6)): - ipp = packet.pkt.upper_layer - if self.defrag_ip: - ipp = self.ipdefrag(ipp) - if not ipp: - # we do not yet have all of the packet fragments, so move - # on to next packet for now - return - else: - packet.pkt.upper_layer = ipp + if self.defrag_ip and isinstance(packet.pkt.upper_layer, (ip.IP, ip6.IP6)): + defragpkt = self.ipdefrag(packet) + if not defragpkt: + # we do not yet have all of the packet fragments, so move + # on to next packet for now + return + else: + packet = defragpkt # call packet_handler and return its output # decode.py will continue down the chain if it returns anything @@ -882,6 +901,9 @@ def __init__(self, pktlen, packet: pypacker.Packet, timestamp: int, frame=0): ieee80211_p = layer elif ip_p is None and isinstance(layer, (ip.IP, ip6.IP6)): ip_p = layer + if ip_p.flags & 0x1 and ip_p.offset > 0: + # IP fragmentation, break all further layer processing + break elif tcp_p is None and isinstance(layer, tcp.TCP): tcp_p = layer elif udp_p is None and isinstance(layer, udp.UDP): From 030e6e57a77d853d1ca2011c22122045563ecc85 Mon Sep 17 00:00:00 2001 From: J Date: Mon, 29 Apr 2024 11:14:53 -0400 Subject: [PATCH 161/166] Updated core.py to use 5-tuple (addresses, ports, and protocol) for a connection tracking key instead of a 4-tuple --- dshell/core.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/dshell/core.py b/dshell/core.py index e358ab6..851db60 100644 --- a/dshell/core.py +++ b/dshell/core.py @@ -596,12 +596,12 @@ def _connection_handler(self, packet: "Packet"): connection should close. """ # Sort the addr value for consistent dictionary key purposes - addr = tuple(sorted(packet.addr)) + connkey = tuple(sorted(packet.addr) + [packet.protocol_num]) # If this is a new connection, initialize it and call the init handler - if addr not in self._connection_tracker: + if connkey not in self._connection_tracker: conn = Connection(packet) - self._connection_tracker[addr] = conn + self._connection_tracker[connkey] = conn try: self.connection_init_handler(conn) except Exception as e: @@ -610,7 +610,7 @@ def _connection_handler(self, packet: "Packet"): with self.seen_conn_count.get_lock(): self.seen_conn_count.value += 1 else: - conn = self._connection_tracker[addr] + conn = self._connection_tracker[connkey] conn.add_packet(packet) # TODO: Do we need this? This flag is set to False when the connection is initialized and not @@ -647,7 +647,8 @@ def _close_connection(self, conn, full=False): # Remove connection from tracker once in the queue. try: - del self._connection_tracker[tuple(sorted(conn.addr))] + connkey = tuple(sorted(conn.addr) + [conn.protocol_num]) + del self._connection_tracker[connkey] except KeyError: pass @@ -1120,6 +1121,7 @@ def __init__(self, plugin, first_packet) serverlon: same as diplon serverasn: same as dipasn protocol: text version of protocol in layer-3 header + protocol_num: numeric version of protocol in layer-3 header clientpackets: counts of packets from client side clientbytes: total bytes transferred from client side serverpackets: counts of packets from server side @@ -1185,6 +1187,7 @@ def __init__(self, first_packet): self.serverlon = first_packet.diplon self.serverasn = first_packet.dipasn self.protocol = first_packet.protocol + self.protocol_num = first_packet.protocol_num self.ts = first_packet.ts self.dt = first_packet.dt self.starttime = first_packet.dt From df6e7916fbb2bc1008532dd4c86ea7ebdf355cbc Mon Sep 17 00:00:00 2001 From: J Date: Mon, 29 Apr 2024 11:29:03 -0400 Subject: [PATCH 162/166] Efficiency updates to core.py to reduce how often we loop over packet lists by adding more caching and convenience functions. Should significantly improve processing time for large capture files. --- dshell/core.py | 170 +++++++++++++++++++--------- dshell/plugins/misc/followstream.py | 2 +- 2 files changed, 120 insertions(+), 52 deletions(-) diff --git a/dshell/core.py b/dshell/core.py index 851db60..dd02579 100644 --- a/dshell/core.py +++ b/dshell/core.py @@ -513,7 +513,7 @@ def __init__(self, **kwargs): # timestamp of the current packet, minus this value self.timeout = datetime.timedelta(hours=1) # The number of packets to process between timeout checks. - self.timeout_frequency = 300 + self.timeout_frequency = 50 # The maximum number of open connections allowed at one time. # If the maximum number of connections is met, the oldest connections # will be force closed. @@ -1199,6 +1199,9 @@ def __init__(self, first_packet): self.stop = False self.handled = False + # Cache of created blobs + self._blob_cache = [] + self.add_packet(first_packet) @property @@ -1224,37 +1227,42 @@ def blobs(self) -> Iterable["Blob"]: This is dynamically generated on-demand based on the current set of packets in the connection. """ - blobs = [] + if self._blob_cache: + yield from self._blob_cache - for packet in self.packets: - # TODO: skipping packets without data greatly improves speed, but we may want to - # allow them if we support using ack numbers. - if not packet.data: - continue + else: + blobs = [] - # If we see a sequence for an old blob, this is a retransmission. - # Find the blob and add this packet. - # NOTE: There is probably more to it than this, but this seems to work for now. - seq = packet.sequence_number - if seq is not None: - found = False - for blob in blobs: - if blob.sip == packet.sip and seq in blob.sequence_range: - blob.add_packet(packet) - found = True - break - if found: + for packet in self.packets: + # TODO: skipping packets without data greatly improves speed, but we may want to + # allow them if we support using ack numbers. + if not packet.data: continue - # Create a new message if the first or the other direction has started sending data. - if not blobs or (packet.sip != blobs[-1].sip and packet.data): - blobs.append(Blob(self, packet)) - - # Otherwise add packet to last blob. - else: - blobs[-1].add_packet(packet) + # If we see a sequence for an old blob, this is a retransmission. + # Find the blob and add this packet. + # NOTE: There is probably more to it than this, but this seems to work for now. + seq = packet.sequence_number + if seq is not None: + found = False + for blob in blobs: + if blob.sip == packet.sip and seq in blob.sequence_range: + blob.add_packet(packet) + found = True + break + if found: + continue + + # Create a new message if the first or the other direction has started sending data. + if not blobs or (packet.sip != blobs[-1].sip and packet.data): + blobs.append(Blob(self, packet)) + + # Otherwise add packet to last blob. + else: + blobs[-1].add_packet(packet) - yield from blobs + self._blob_cache = blobs + yield from blobs def add_packet(self, packet: Packet): """ @@ -1266,6 +1274,8 @@ def add_packet(self, packet: Packet): raise ValueError(f"Address {repr(packet.sip)} is not part of connection.") self.packets.append(packet) + # A new packet means we might need to recalculate all of the blobs + self._blob_cache = [] # Adjust state if packet is part of a startup or shutdown. if packet.tcp_flags is not None: @@ -1300,11 +1310,18 @@ def info(self): Dictionary with information """ d = {k: v for k, v in self.__dict__.items() if not k.startswith('_')} + + cb, cp, sb, sp = self.bytes_and_counts() + d['duration'] = self.duration - d['clientbytes'] = self.clientbytes - d['clientpackets'] = self.clientpackets - d['serverbytes'] = self.serverbytes - d['serverpackets'] = self.serverpackets +# d['clientbytes'] = self.clientbytes +# d['clientpackets'] = self.clientpackets +# d['serverbytes'] = self.serverbytes +# d['serverpackets'] = self.serverpackets + d['clientbytes'] = cb + d['clientpackets'] = cp + d['serverbytes'] = sb + d['serverpackets'] = sp del d['stop'] del d['handled'] del d['packets'] @@ -1320,10 +1337,36 @@ def _server_packets(self) -> Iterable[Packet]: if packet.addr != self.addr: yield packet + def bytes_and_counts(self) -> Tuple[int, int, int, int]: + """ + Convenience function to get client and server packet and byte counts + while only iterating over the packet list once. + Returns a tuple of: + (client bytes, client packets, server bytes, server packets) + """ + cbytes, cpkts, sbytes, spkts = 0, 0, 0, 0 + for packet in self.packets: + if packet.addr == self.addr: + # client + cbytes += packet.byte_count + cpkts += bool(packet.byte_count) # only count packets with data + else: + # server + sbytes += packet.byte_count + spkts += bool(packet.byte_count) # only count packets with data + return (cbytes, cpkts, sbytes, spkts) + + @property + def totalbytes(self) -> int: + """ + The total number of bytes from both directions + """ + return sum(packet.byte_count for packet in self.packets) + @property def clientbytes(self) -> int: """ - The total number of bytes form the client. + The total number of bytes from the client. """ return sum(packet.byte_count for packet in self._client_packets()) @@ -1338,7 +1381,7 @@ def clientpackets(self) -> int: @property def serverbytes(self) -> int: """ - The total number of bytes form the server. + The total number of bytes from the server. """ return sum(packet.byte_count for packet in self._server_packets()) @@ -1351,6 +1394,7 @@ def serverpackets(self) -> int: return sum(bool(packet.byte_count) for packet in self._server_packets()) def __repr__(self): + cb, cp, sb, sp = self.bytes_and_counts() return '%s %16s -> %16s (%s -> %s) %6s %6s %5d %5d %7d %7d %-.4fs' % ( self.starttime, self.clientip, @@ -1359,10 +1403,14 @@ def __repr__(self): self.servercc, self.clientport, self.serverport, - self.clientpackets, - self.serverpackets, - self.clientbytes, - self.serverbytes, +# self.clientpackets, +# self.serverpackets, +# self.clientbytes, +# self.serverbytes, + cp, + sp, + cb, + sb, self.duration, ) @@ -1418,6 +1466,8 @@ def __init__(self, connection: Connection, first_packet): self.connection = connection self.addr = first_packet.addr self.ts = first_packet.ts + self.starttime = first_packet.ts + self.endtime = first_packet.ts self.sip = first_packet.sip self.smac = first_packet.smac self.sport = first_packet.sport @@ -1440,6 +1490,8 @@ def __init__(self, connection: Connection, first_packet): # Maps sequence number with packets self._seq_map = {} + self.seq_max = 0 + self.seq_min = 0 # Used to indicate that a Blob should not be passed to next plugin. # Can theoretically be overruled in, say, a connection_handler to @@ -1461,17 +1513,17 @@ def all_packets(self): warnings.warn("all_packets has been replaced with packets attribute", DeprecationWarning) return self.packets - @property - def starttime(self): - return min(packet.dt for packet in self.packets) +# @property +# def starttime(self): +# return min(packet.dt for packet in self.packets) @property def start_time(self): return self.starttime - @property - def endtime(self): - return max(packet.dt for packet in self.packets) +# @property +# def endtime(self): +# return max(packet.dt for packet in self.packets) @property def end_time(self): @@ -1542,13 +1594,17 @@ def sequence_range(self) -> range: """ The range of sequence numbers found within the packets. """ - sequence_numbers = self.sequence_numbers - if not sequence_numbers: +# sequence_numbers = self.sequence_numbers +# if not sequence_numbers: +# return range(0, 0) +# +# min_seq = min(sequence_numbers) +# max_seq = max(sequence_numbers) +# return range(min_seq, max_seq + len(self._seq_map[max_seq].data)) + if not self._seq_map: return range(0, 0) - min_seq = min(sequence_numbers) - max_seq = max(sequence_numbers) - return range(min_seq, max_seq + len(self._seq_map[max_seq].data)) + return range(self.seq_min, self.seq_max + len(self._seq_map[self.seq_max].data)) @property def segments(self) -> List[Tuple[int, "Packet"]]: @@ -1573,7 +1629,7 @@ def segments(self) -> List[Tuple[int, "Packet"]]: if missing_num_bytes: logger.debug( f"Missing {missing_num_bytes} bytes of data between packets " - f"{prev_packet and prev_packet.frame} and {packet.frame}" + f"{prev_packet.frame} and {packet.frame}" ) expected_seq += missing_num_bytes + len(packet.data) prev_packet = packet @@ -1842,11 +1898,17 @@ def add_packet(self, packet): # If packet is not TCP just add packet to list. if seq is None: self.packets.append(packet) + if packet.ts < self.starttime: self.starttime = packet.ts + if packet.ts > self.endtime: self.endtime = packet.ts return # If this a new sequence number we haven't seen before, add it to the map. if seq not in self._seq_map: self._seq_map[seq] = packet + if seq < self.seq_min: self.seq_min = seq + if seq > self.seq_max: self.seq_max = seq + if packet.ts < self.starttime: self.starttime = packet.ts + if packet.ts > self.endtime: self.endtime = packet.ts self.packets.append(packet) return @@ -1856,7 +1918,8 @@ def add_packet(self, packet): orig_packet = self._seq_map[seq] # ignore duplicate packet. - if len(packet.data) <= len(orig_packet.data): +# if len(packet.data) <= len(orig_packet.data): + if packet.data == orig_packet.data: # TODO: should we still handle duplicate packets. logger.debug(f'Ignoring duplicate packet: {packet.frame}') return @@ -1867,7 +1930,8 @@ def add_packet(self, packet): orig_next_seq = seq + len(orig_packet.data) next_seq = seq + len(packet.data) if ( - next_seq < max(self.sequence_numbers) +# next_seq < max(self.sequence_numbers) + next_seq < self.seq_max and orig_packet.data and next_seq not in self._seq_map and orig_next_seq in self._seq_map @@ -1882,6 +1946,8 @@ def add_packet(self, packet): logger.debug(f'Replacing packet {orig_packet.frame} with {packet.frame}') self._seq_map[seq] = packet self.packets = [packet if p.sequence_number == seq else p for p in self.packets] + if packet.ts < self.starttime: self.starttime = packet.ts + if packet.ts > self.endtime: self.endtime = packet.ts # Now remove any packets that contained data that is now part of the retransmitted packet. packets_to_remove = [] @@ -1904,5 +1970,7 @@ def _remove_packet(self, packet): for seq, packet_ in list(self._seq_map.items()): if packet_ == packet: del self._seq_map[seq] + if seq == self.seq_max: + self.seq_max = max(self._seq_map.keys()) self.packets.remove(packet) diff --git a/dshell/plugins/misc/followstream.py b/dshell/plugins/misc/followstream.py index 5e73d57..10aa770 100644 --- a/dshell/plugins/misc/followstream.py +++ b/dshell/plugins/misc/followstream.py @@ -17,7 +17,7 @@ def __init__(self): ) def connection_handler(self, conn): - if (conn.clientbytes + conn.serverbytes > 0): + if conn.totalbytes > 0: self.write(conn, **conn.info()) return conn From cafe3c5610a6114153139127b1219f74226b4499 Mon Sep 17 00:00:00 2001 From: J Date: Mon, 29 Apr 2024 11:31:16 -0400 Subject: [PATCH 163/166] Added long description to netflow plugin to describe default output fields --- dshell/plugins/flows/netflow.py | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/dshell/plugins/flows/netflow.py b/dshell/plugins/flows/netflow.py index 89a30e9..df9a7a8 100644 --- a/dshell/plugins/flows/netflow.py +++ b/dshell/plugins/flows/netflow.py @@ -9,10 +9,33 @@ class DshellPlugin(dshell.core.ConnectionPlugin): def __init__(self, *args, **kwargs): super().__init__( name="Netflow", - description="Collects and displays statistics about connections", + description="Collects and displays flow statistics about connections", author="dev195", bpf="ip or ip6", output=NetflowOutput(label=__name__), + longdescription=""" +Collect and display flow statistics about connections. + +It will reassemble connections and print one row for each flow keyed by +address four-tuple. Each row, by default, will have the following fields: + +- Start Time : the timestamp of the first packet for a connection +- Client IP : the IP address of the host that initiated the connection +- Server IP : the IP address of the host that receives the connection + (note: client/server designation is based on first packet seen for a connection) +- Client Country : the country code for the client IP address +- Server Country : the country code for the server IP address +- Protocol : the layer-3 protocol of the connection +- Client Port: port number used by client +- Server Port: port number used by server +- Client Packets : number of data-carrying packets from the client +- Server Packets : number of data-carrying packets from the server + (note: packet counts ignore packets without data, e.g. handshakes, ACKs, etc.) +- Client Bytes : total bytes sent by the client +- Server Bytes : total bytes sent by the server +- Duration : time between the first packet and final packet of a connection +- Message Data: extra field not used by this plugin +""" ) def connection_handler(self, conn): From 809f599649364670e3e069032668297083905ace Mon Sep 17 00:00:00 2001 From: J Date: Mon, 29 Apr 2024 11:39:55 -0400 Subject: [PATCH 164/166] Updated decode.py with new connection management arguments and a way of handling packet timeouts when listening live on an interface --- dshell/decode.py | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/dshell/decode.py b/dshell/decode.py index 62bd364..8b37be1 100755 --- a/dshell/decode.py +++ b/dshell/decode.py @@ -32,6 +32,7 @@ import tempfile import zipfile from collections import OrderedDict +from datetime import timedelta from getpass import getpass from glob import glob from importlib import import_module @@ -250,6 +251,17 @@ def main(plugin_args=None, **kwargs): plugin.out.extra = True plugin.out.set_format(plugin.out.format) + # Set some attributes for ConnectionPlugins + if hasattr(plugin, "timeout"): + # Set wait time since last packet arrived in a connection before + # considering connection closed + if t := kwargs.get("conntimeout"): + td = timedelta(seconds=int(t)) + plugin.timeout = td + # Set max number of allowed open connections + if t := kwargs.get("connmax"): + plugin.max_open_connections = int(t) + # Set the BPF filters # Each plugin has its own default BPF that will be extended or replaced # based on --no-vlan, --ebpf, or --bpf arguments. @@ -447,8 +459,12 @@ def read_packets(input: str, interface=False, bpf=None, count=None) -> Iterable[ try: header, packet_data = capture.next() if header is None and not packet_data: - # probably the end of the capture - break + if not interface: + # probably the end of the capture + break + else: + # interface timed out + continue if count and frame - 1 >= count: # we've reached the maximum number of packets to process break @@ -464,6 +480,11 @@ def read_packets(input: str, interface=False, bpf=None, count=None) -> Iterable[ yield packet + # handle SIGINT gracefully, break read loop and allow shutdown + except KeyboardInterrupt: + logger.debug("Caught KeyboardInterrupt or SIGINT. Closing capture.") + break + except pcapy.PcapError as e: estr = str(e) eformat = "Error processing '{i}' - {e}" @@ -557,6 +578,12 @@ def main_command_line(): parser.add_argument('--unzipdir', type=str, metavar="DIRECTORY", default=tempfile.gettempdir(), help='Directory to use when decompressing input files (.gz, .bz2, and .zip only)') + parser.add_argument('--conn-timeout', dest="conntimeout", type=int, + metavar="SECONDS", default=3600, + help="Number of seconds to wait after last packet in a connection before closing it (default: 3600)") + parser.add_argument('--conn-max-open', dest='connmax', type=int, + metavar="NUMBER", default=1000, + help="Number of connections to hold in an open state before Dshell begins closing the oldest (default: 1000)") multiprocess_group = parser.add_argument_group("multiprocessing arguments") multiprocess_group.add_argument('-P', '--parallel', dest='multiprocessing', action='store_true', From f7dd262f526789326c668e6ad9765724c63e38b8 Mon Sep 17 00:00:00 2001 From: J Date: Mon, 29 Apr 2024 11:41:32 -0400 Subject: [PATCH 165/166] Updated version numbers in core.py and setup.py --- dshell/core.py | 2 +- setup.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/dshell/core.py b/dshell/core.py index dd02579..b562a17 100644 --- a/dshell/core.py +++ b/dshell/core.py @@ -38,7 +38,7 @@ logger = logging.getLogger(__name__) -__version__ = "3.2.1" +__version__ = "3.2.3" class SequenceNumberError(Exception): """ diff --git a/setup.py b/setup.py index 4441e07..9465134 100644 --- a/setup.py +++ b/setup.py @@ -2,7 +2,7 @@ setup( name="Dshell", - version="3.2.2", + version="3.2.3", author="USArmyResearchLab", description="An extensible network forensic analysis framework", url="https://github.com/USArmyResearchLab/Dshell", From d7b9f0b5a9716b3780b4877fa5c4e7a3beec73d9 Mon Sep 17 00:00:00 2001 From: J Date: Wed, 1 May 2024 12:29:33 -0400 Subject: [PATCH 166/166] Added exception handler to core.py for when IPv6 packets are processed that do not have fragmentation flags set in their headers. --- dshell/core.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/dshell/core.py b/dshell/core.py index b562a17..9b57fd9 100644 --- a/dshell/core.py +++ b/dshell/core.py @@ -902,9 +902,13 @@ def __init__(self, pktlen, packet: pypacker.Packet, timestamp: int, frame=0): ieee80211_p = layer elif ip_p is None and isinstance(layer, (ip.IP, ip6.IP6)): ip_p = layer - if ip_p.flags & 0x1 and ip_p.offset > 0: - # IP fragmentation, break all further layer processing - break + try: + if ip_p.flags & 0x1 and ip_p.offset > 0: + # IP fragmentation, break all further layer processing + break + except AttributeError: + # IPv6 does not always have flags header field set + pass elif tcp_p is None and isinstance(layer, tcp.TCP): tcp_p = layer elif udp_p is None and isinstance(layer, udp.UDP):

          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 `s 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¥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 diff --git a/doc/image3.png b/doc/image3.png deleted file mode 100644 index 23a9f582cea1b6d4cda48c1d9088922b72c3fb5c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 109282 zcmZ^~WmH?;8ZAsqp+$lgDO$X^ySr0dOCh+sl;RewxVyW%YoJ(g4Ni-@6t^#Z-*e7) z?~ltE86zY+Yp-XmN9Hr<+F{B{(g0)vWH>lDfUJy!DjXbqH5}aQhIg-FpBQIkz&?O` z<*X_#23Ivsv=95|jk&0zC>&gEG|D3o0S@k^O;$ow{oB{0OoVUm2iFIazrQp#%gO7> zMSicP+;tpS?UbS&h~H4onH1B@z;&1L`}WT9^zjJ!0;IO3M8=vgm zhoDs`v=!RfzCr_DVNxrVom{HLXv>ogPU~qj{^$~{>;<_KMEqu2;NI2tX{C`uuiuO3 z;Tvm3a?!){b>?cwgo7yrMah>sY3IoC8*);%+e*5cib_&P8GZZqoQlvL4z&F^%S7vI z9nqC7aeUIfd9s$pkp|h(&ea}8V;X3 zJk*)H=KeY<0SR9B=j_AEJN)gt*oUO3=5L3XAWLosXCqoh-02RQkPg&ayZ1zQ_pUpQ ztX&8zx@)=q%q+x3!MGalL&k!%e(F8p+TEbOLtYfTWCz_Dc?h^vf3lcfhRBNxUM$`Z z(Cqm13oJN)&f5)LF!->MRnvVM!Te`2bA$D9TUsa!ueU4jPgA}t*PkrzwoWu}nm4zH z)!lB#ON9WR({- zPpK-88{LRybK?;l?ciqb_~>KWES>GTlqgG&#Olz8`Nrd&PP3hUmuM8JaF@%z>aFa; zAv{5W;-S%8nMOIMPP?0}g@uJj>-BEnS0iKN{c)=tDEwQr{=va&gKiR^=kr0*hBBWV z%r+B@V$Nr8?ziHG{L3DQ-+-mnagzStg3wqL9v=efz;%@P*80QX zHPapv>0!_BqS3qvXx?o?K;6YfU4XHCo8U;2-pSC&jwDxmM+e7#G}94Ub=1W;J#&;c zTozn5)Idov)abY9ew?$na{#F@83_7b4oA# z@bBq6Pw3FGQ*mC&2m0Im+B`f{a{Bvdaf;hIF|7qeJm&J{3v)A38&d&`*Z3gnyYX^xe>brvWMC zQ!s(lpD(+Y^q*#V$_p*q-*(Rzt)@JQcIya&8wj_vdYh~_<}A(%3mY3bEa8uC?-!o8 z9=E^$_#WxueKfxvH<)dlEncPUw}~C~aY+2#kcE|?%x$80QqPR9oKSo}Vv^zJ0>R1}o;}e*32@#71%b_o714|g^z@^b#5a6kfpepF z_jS+Tz9ysY&v!cQ$Gn7Yi}4zonyTjD)|#X`;|=R0y3yaCg?>I?cFFTBYi^#mW;+Z( z)TXzmB=a;%K5jr#*g^wmEg}@zV{NBe^-g>?y%XhRpzDeB!4o~*C;_pG2$s=a&=CnWVt$X7lJq5kJ(QPw# z|6pAf%oWY5wkaxJW)qFsZQXefKpjY$lbjuTE)BuG2&M?HgnRbCxu3-mlXUs`JnVW6 zvt%Siw&mIxF$d$dAg+H1i9fSVy~jmCH8$zn!lj zIyxHSkvt&K%-FTLf0AuN@*G1sT5sI6ARRN?No-*op!xa7zO(2p`F=bEMUabHq%|w+ z(96eFct4JxSe{cU&^N;DeUoCU<8(?EJ)4FPur)sH6@lUdA(+`c(25w&_+@hC} znUAY;-P^etiI=x6ch2olqRT(q0#gp9ZAmAP_Gty0-hs3G`pzH)TD>OrP>hqmWz9ZTJOP6Va5w>O>3mOT133K%{6)42(>Ta(@J@ivttK7lyPd@$%k(U>#w zR=y^pSz?0ONgh`Re|qRbESMCuT~8=i7np>8 zvT}{IqZ5+(LATtsM?9O))oLt_69ECCK}MwKU`h&f(xaB}-J-Y0?l^1b{%Wt@-ph#n zQichtj?ru_bu;nRGhq48QF@&08ni&b=LSNO-FeTW_jo(1Pkmn(qMgz*(fUx#Tx-5v z$~`7k^$xv7XCjcV`)4MAhjgOx$>gjl!Kg$np>CIdMvK&U&FAfn1TKwj z&9^v@uG6m<4MnF1S45Wu1NW3obP-){4daLrUByz7o7k^=JPFr?1C!fE%}?Bff5p3P z2*wz4k=RVH3d=Zq3ePFZSz|YN8mVVT80n~a&%5b+VOH!Pw2tp;O~j99&y9spca93I z8_Tot`XdbDxq2krIp}`8shYmAn&k^Js@c>c^%#ylBx+9d=sZk5UL5rPQ#kQ`j5lG# zElo9}VG41rw>s+2q`-P)-f%^J##Y1kf z>I_jIeOCy3Ozl&w?tqsD0v}=i=OUhe>-2d->A~}#qMHG@&*l8#7h0{f0eyuN6%i2_ zjS9c_pcimZLp|$07qe*yswy4yyJ}@7geNe;xHUfPQr6ILeY`#Q^Mh-v8jhXIk3?PF z?0x+?>K*uR>EKf5!NjRwKh^$o4qy7PHueVnI}+56GO`P zTYo;0eZLLY!(VO9`|)YN_s*p=>icJ&fRE^8G1Pay7r`6qi)C(Y}rS5k{QupO0GqX*>O-`O^BWhrM)vy34zV(5NMv-o? zUa0Em5YP=O>5Zr8OTm84MMOxLo{*4`mX?O;{>kHpKQ)B^r;S%+ zwZO0RTW)$Bd)JX+wIcs86i$GboZ!0{@+CXgO`2qtcO<1_vns1ZEW?|Y>s}ES$%j&_QvvcW?U7(8 zt7OAT`CP-A6<*#YqUhDk&o`4kbJ9Q*xVBfs*VotMV`GJqp#-p-p9QTLp9N98GxAGG z!9UTn9fRXQm~_+Q!oz>lqdnszfIId`_-oI#mfl$v0<3a$HYCKw8_D(9O)d=?+h>eYHfxxOBLl%5g#K2xd63`-4Hi5qpUS23H$^HoJKC9Qp5N4o^;RiXyKc}Uta*4>L4tQ}=r;8o6 zELwExY=kI)%XudCwB?l4G&gouN7dA`;QvjR1=W|#C{YY~oXNHVhch=Cyj$BhQpp<)CI^wv< zjjg{suFK&&pVvBLu7J-wDP>i?{$-oaGpu6Qq(s2?f<<1|9YIgcoQ#917GEHqF@v); zdPQ_T)&9+YH?;=AMjK6quE4D+3AS-WoK7qz{b!#)&oL z!rWX=EIwkD9`l%w2OhGSCM4>hYj7`G+1c5VtHl6~v9YmHJn-lff8ZE+RMXlhVi>3` znpiE3iJ2DbTbSn_P}et{3fmmjWHn7!&F}0KVX;@S;;N}(qv&W^#Qf=BS?N=M(mt~& zqFz{to#v{Z8ms?b&#C-03)*I@fA!>vX&dbKtgAcp7X4_9>7Uoh zsC{snQ)=lrvB%Av4*ANINP%1aZVfWOZABm|(Y$(DoqL^gjC(z6a;bV!5tegt?(d=r zCj|MdQvslt0X>SPd172M(6#8AoBP z`FhmScq{T>I~WCKL8hwlu@rlI%)>Fg-jxj7ou0ffkH@tm;5Euo7c10k$OjVQ{$29& zT&4=|HYH-{s;U(oE4#{&f(=xsyUfmP2hF(1$?kw{Au(PBV{r|cFg2)o^R8;fjQ6wi zb5nBRY)~^WQp_KaK543HwLA73cW2^pN%Vm7)QVi=3ST&rK9$q+rwN~}v8p@OZA0FT zN!5ke0xi2aB;}NEUL~CC$G-tSbKjRzfB9-lHEcL#N?bacfLvj{YjsQ`&d0kwVkDPZ zrgEIP*Za=&7;7^M(TJS$l+}!FO4(uN!#d#5o}N3|C5ir+vaCxD+9wOHfGD)3mfU+! zMC~i>k4D`hQ%k0#xWvn~m8iQd1>@4`>2slunyo5m1X6=9Dq4TrYM4=DT|Uo1z0JLr z#m$z+Am4A_8-bD4u*0q#wA^O;U(u;yyOjl{2Fj81A^(%dSnw4_(T%I(#7$JyVgcv` zv&$o@LOH&lZ+T$}qAR1EOP!i^sx|)=A?~roN4mtqFo~juL&1ykQ}fzsq|`fc-^6JJ zI@d=lAx6x8(}GM13$U3|xZPxwf@QV-r?-;xwqUH%)D^S$+-Hx0@k9v==Z6S20-hOx zsimp?0nI?FlG=VZhD@k{@e;TAy|(P}R_5Ka@qhMRSH1^iiqQ(OIos&!SU~%*vM?>i zYNAZ)mYOMEfzQ@L%G?MGzC?LN*At6HP%uA1sA_54h=QpTuS`j4zf(_8YK1#rbPekv zwc{g*bM{WHn^4eZR>l>?1C^mPyU3F83eih*)pFA)HTgJ;RVmiGRtvNcqs52gO5}0m z5-_g_?4O-gumJ0CA?va1KIeBkn%$T#lbSMO5+nR4zZPwWEY+woIl9!42;05kp*NWw zA`=h!L-C)4;7W8{iGxh%n+MzS#(ZaKc-F)vzALu|6*&c{?7Q$RlZ%rI)@xPlusgpG z72bTG2@I)%D_7f6hZ8iNu<3&fQ~Mps`I8s6J>87Nxz*IvtP>NX#GF5I`~Y#2h z^>Z1Ek>a$txlaS;LG5xl*K)M{(tYYioHl&3soQK2F_-uMO~Of}R^T1FQUxnMqy7y? z;}C3*xetr5_a9RsKi0dE_zxoczo&c;kkH@p+BT%!H!>867g&obNg8 zDwbST?OXRg{V$Y-I{>2z$YF)SMvu3#_Z_$+!1CZ$vC^0ePfk;5?^xYylB=;Bruq`U zarb9nUnogZoZYn?d+_v#y3zR8D@f{>D~RjKk5egLnWJs}0y@I5x`!0fA}qm7evg*? ziuBe#x$;RFLbGmrn%I;ZBEFpvQW~YqKUe*wM-)sMd!M*DW0z1V^><;r&`61o|rHm#=DL@#!m5L-noiC4(4Qh|!_%59p z`>8?!0$H@g__KpcjV!B0Soi^2rk>^=KcoQlKwi;|w`;m!dW{3H@_{^Ekr7eRtlHs-Z)8OEqA;~j%KH$oIIl>1 zY*m;LC-h(3p{vpZ68(LU7n43*SR~lC9EmSv@p!AU?#++p)8~Xv!`})~CwrSeSMs-@ zH%*p66csg|peR+Xf0v{vBGJ{63*y00K-vb_2oh^oEKt{U=E#gbL}gqI>m#IG@$~8mc~Rnf>dhCtoG9 zJ5t^l0#~;c0V8v8HerUKpxj{|CTP0zH9S^nm*B_4`tYM*{ zC1QVZo}$wHAT6WP;V;zb?;?bDn3%FGVX-6(aUGs97izmCei=NDd02nppoX$>XNWSw zd_Z^&L0M0l@|>8ifCczQm>h|^bRkd@RK`yJ0)7|B_2c8a0F075f*@U3?-k5j^4eO= z7R3^p16bb;rA+DfLyquDj+VJ%xk9wXhmFe$*J#LC@(xynAfhy(#k{d;dHoM6&3WzVo&y`)6+gJ;Dv-;|7j|(RqGwIg=mlmfsT98j7zWTo zG3Yv^L|jt>30Rd!>`VE9P3@2p9nhb z&K5G>$;-yIhjy_aeNz{;G?m@{V2njV@)h)V;5W)IoCF7bX|RQspzMd4NJL_%vDXAV z+o15zHSCGNV?O_Lp)@fRRD5;NX#GN_Sfm+2pmoz``PHx)6dasL4l^8`NZp?hVGgKRf>xeOULi%< zKN~!!jDjojgkmYXSF;%xKGR)wYr8+4U0>&1(n~h>=E^{^1i@Juv+8qj>9vz`8Nj=E5l%>(o|E=2bb`CYYUmFnIdM|>3<#zON zN^?&PU}E4eWi|v4zzi6If1CIVBwnZu2OHh0|9eJ@sF(r{swJz%qJzfOfNA&R_r038 zuG|H8ITz(fjfQA+efJvLl)dVnyd}fPIhu%#t4NPeArl6szHA@ z!$FzWjz>KlL78?ZN3~-97d0}gh$O1zD~rXN;^>#~MEc(Ud(u}WEa!$IpZ+_xoHnVi z@TA1x&(A4m-cC|VKC*>w0fB)im|2gr8&8B<3}0%P1d@~R#qCylHBgFtE|25#p?sRK zZb}zXJ^nCIt`?4NfJi-@myucwb>rQ6plBvQD?^Ce_TJ^&*U~P>9{J6)O)w#k;j6Cz z7kDEMbsx@LT!^UTVh%FOU|=I4rLB^HE->wj&nIYy>2mn`^ALU2q>{3-a&ITO@LkVB zw$PZs6SUcm_O77y1dZnSH-g_aN zC*P7+&|`9FLNN?k7&m#Y1utD?Yv4prXt!7~Hx=Oh!*jBE9+lHnu>`N2Oi2NQuht?a zrHw^8FbF?~5456nV8g>g=>;R%W;b~9^7FN*+X=L{P7+Q6u zoyZd_$IAmYe+5c4>2-eQ?anHth49= z(k#jGC~GHcB5h-^*XCkigQnk&vPJ#4=DzB(W1&*hsrL92@KI6+t#GuGQt^nz> zyu|@hsHfZ*mi1U674?mZdM5>r82d8I!iOh**m0=FW_jBI{ccI?c$jL0(i zt_`wFViNOi)>w?Jh*Mu9t%D}R$D7*9nbBR@AH6t^!rIeUj z%?}}@4x-CMC9Ld;N{NZ}u*@`u4I7TV0$<9n|8CEkY%D&KB0Jr~Qg}MrFoB z-i6~J^NB3L1TtsK%QL^%Ela4qsw$TLE*u$13?2P3EmKALWiBYZW(u1!6#4RZuNYF% zPWgVE*06Me|RSDQ~2-)p4aro))jg!DvT*p98EOA?5pXMPY64vpx!&DeRYa;- zev62GqTBlX81Vw*d;0VO)iD_LPugn!p{H#&1=Z)ywbI>L#m##<=UoZ&QN>dvt+Hf~ z5aWIGE`m?F%N#Q22K&D*BFyu4tdpqdsUY6JnJ@MAzkJzYc=m3$=h&A~a+4d%a_xTP zNM7Aw^SnD5QczVIQsQ+xt2V$J53sFrPPY3a4;kUmAp-YbOdk3 zU08o!Q4sTVm^@(|vBRWa&(9LJ%uQ?fa4O840#2$Ed^9!}5fFTLg6ZKSgrVo|03DV- zymrcLwmGh%aQxsBKOQpgj8$i}n$!k)iWjisbpt z%>x@3#;EV5 zpO;eUzi-`Xef2zUUT;y)4OAa}r>Qu|0gK=FAIUWWMiTsay>1iZg3SvaN zFKb6<*YuwS&!HU~F1?!q_wU_fdP3B^)PVNz#JD8M*Jad`VM@^~_K{G+Y*~2@iz)N; zLyYK>a#wH9UzScrA9mtDOj-&m&iM+xx&o4@B{z6n_#XUxseUN?z28PRxNqCKF9<~c zBJ7MV2{wO0)1M?rpj^ipA0I^Ohx;#$Q5zB9k%#B7M1dLQEP^H1pfE$D#v9U6uKZvkc`>g4j;nCoMV*B`JAC&cTHM zMS>fpgXQJI2Y--Q+M3!~8*dugNB#r)VMi9&p zMdYyQqy(0IaGEHs-~4qkQmR%Q5UG+o1BTX{dys)lb;BK$Uo^yVQUbrRd{hN`=l5+b zVZwIrED5_4o%NrlYGqJcuN1~N*VjWM(&90Vyw#{nP@LZd!ypW-kI)9Va%_E7F$Wh< z7_2qfrdL-pbMilB@ViI7JBKM&7MOjajM@O$%n$l90M_L!9|>@%7nIqxh9yr$93ePz z!3s?5@v@4ASZXjjS*~!l?+aNKtz5o)|KE;vXEQ3X5LqaPot-^cjDdg*k#L?C2Fa&D zdRVSpsI&~U*{sHh0s!@sKk#Blo12cme*)T~9F$QsDJ~5CNbz?xw0T${wmTi`@$wqMe&G49nW3BDNZGoex~!rT=x}q$IgpzwseM z=FN=wc<~+icg*c(Tige54Vy`RAb@yZH1W%Rakj`*$vPRpU$=%JlM8~58lj$oih6mo z@R56##SknPEKwM9b-G}ETl4BKKb?QG#36kosXhGYQgr zZA2*K{e1fLfX<-b_CDhW9f=XgY`~STGa3dOs}yDA<{Dh;dt8?t|~DJy0E) zmgjJi>?xR!9yI~|!wPzZ)~r~*`z&7K$jEyJO}~CfzuelKTzQfICv`5Y)Tg~trU)}{ z?*0*oER0z<wJo)?l47>-+C%(&~#2NJ{}E``5gmwa+Iham?Ml`8MS-13oCns6K%B;!?M0_=%Zp3R5 zcbRurZ?U74&FTo5JfVZ}%hr`6_v9*kG7N|lTe>ML(kCAe8OjVlIwf{W%saESpKbw@ z;!cojW$Wo|%s7pxms>6|oUNb4zSyhXFfbO={Pq2*4@O{1OG}gM8iy{4nQCTHVnD0b zUJWpA_D=-@3NDjg69Wgw`z(BAZY!@)pAr3_7?tG*=e>}(wd0{B|m z*_qO@8oTfM6)~9T=X%eJUU3vw3)3YA@8KVB!ck$hjccBm<*@OREirP-ezsWVryIPCunn{o=8ag&1HHi66k+9W38%gDGD z`1aZ?`JdO#cC(lwjG@|%>UcO{z=ZMjeL$@mF16OCxgy!$gZ_mU3*PSb*MeTZ)`5 zqVH2@eL4I7qStPi!A)~rlB)`x$J;rJ5h>H$dSOjvre;jy{LU4p$pvh)wwRy#yGk!^ z3I_DfvRc;qiBN2#qG>ywIU+&Fn6%RGs82vX_q-k6i7d7E!V6 zut{Ce-Y=}aO<)bs=Nqh%TypqJv=|?Z!8k3KqOyDPf(rIBNNVo zh64rJ?bKi4Gm_iI$fHWQ37XqDT3fhD+wT+1w(-ojaEo@|?==8ZXHB-=@!iX_nK&5G z%X^%DjXJ|l3Qm`b!vB=0T#9r2ABy}Z@Gs_IEcQY$zUr816@4mbQ=qoF@9X@WgcXqAh;7w93neA{k_Cmm zk!RdJlWWu??XtPEV)2!kH?$r5FssX>u@s`t?Xs}{xN~z2BpcHkfb-1w9 z2ZKKD6F%3P;6nAYmH_O$>g}SNe$_cowgvy-DmAn56xMauiv0Js_^_g$MsxNm6Q=UV z#feeNhcYn%ztz2|1qLV);)*5$TCHKghL#*@N39wVh#X!lS{V~<_Y(-rBZ+dW7qhOQ?Ig4;z!u3R=|W#n_zfO|vpN}AE)A)y7 z3p19481MFFN>XmJ?ev8 zxk5{@t8s(PV1b!ay2^^hA-WPWfUrn0b%^NCwKTbl@-_Z8T_i0j7jj~0-MUNDa{}f@ zbsjc(2zFlcHuX*ah=LLSeCli}>v1}ncSV8Q#rUJ;--4^41`9ga37q@CZX*Ce|2La8 z6HS8B-^aeWoU#VfOd#9ht81Hpc@YZxK{Iuiyo5<9QkedY`_P5(|`6f3YfamIiY%z*JKSE&<>91WRlwG$&eEe8&BB$n{?5MW-{`&sjn4TS*IDZIqyzRs;NovR8 zKJuv+;LbH!2l!KNDd-QM{AuI#P5M7-)hM(`O6Tw!FYvF6VEUt5)NB?MP#S^rP|#6q zQ%Fgq2<>YB#t$D=N;E4MLk5R}4G(>H%92Bo9iiq3RTSF%@4-ko^WYx@ye4}wJ|-Vt zk1C5L9Ph!FASlmrM1NbvXlYDtN-}ppc*9(^F!O`3S{`>Q?YZEg zn{)SmA!~$)k(rPoqTZOtG#ou`1GF+dRl$;qn^j9&o&hmVas5W47W;Ku>d1D{#t=3X zsg7y=CZ=|Mi=DGkYwoIpjB5o);md3SGKu1qjnDjGO`Fze06{flZisLoyylahY6N$Cbi zcdCVyzH_!%Wzr$)=i4?<#Xj&@(I16^6^NKci!iKW{RO`pY9Ywhee z+d8_d$8Awc<@F}u&O72OZO+K}2hMS@!VJg5OHN6V>5>`zOpLq4l5-m20tc%?uWVan zEi?W}q1q4hF0gb!`=Rx_O^P?RuI{Iw(WIpl*11GYx+(N6se@xR`Ca(-VC52Z-832X z)es-fz;=ZbOE-B_63GIZG_TTL&k(_)wG#ebxH}stTNSH)#+mK$T@wakl zGQqrl61216R{5R-1R!LOP| z(?PjtnsHTI8UG~7Ffy);m>7{NK87}0;yd!pA&?{(3~OrNHf&NCPH~~qF*E@yt0(;d z^jlboahAwo$9wS!{(mw)W1A<$8hNl8SklB*VdVS-KH-zbwPJ+xcanT-pu0`rK_AR$B$&~X*#K;GE*o%8A35Pp zw-`+g5aS~Y{;GeaQ>kV2iQ8YCE9^7tz8)2rU9$onR$^k`R?zK0k%cLP*PjxSip=II ziXbV203cHu=aPTsmLXl)ye_%cl7&Ku;eh&=w|`r5bdintgvFX`Q>q|?0t#4-V+6V(QmGL^6|pn+>!M)|0+mj52q_n3ixHdd;dYcMqrCFTJ%^b7gZx z);#l06~DEs2M`5qYj6VfA8-j?IJ4~WBW_Fovi36 zD~l}8p~F_h=m$Uzoy!8;7XiQ~R2m*aAWRyCzywrH__1cfo!?^<#m zx$$Izfrya0;kp(WyUN9(gu?cgIqJ0e(_K1FZNmV&xroW8#8e_R9E|`Soz>;en2WwJ zY+dBomumKmz=mL1ODOCd(0?V{nLJq4>;S}%%E2lFpEqvd_16?By)By*CeF7%8$f?o zrw7#9KKY>u_-q7=o_{EYhOIL$1-l-y2H++YY~3T#ZO>oTZ^lb@84Ftt8a2|LG<-V@ z#LTz3HQ5dui$CV?yhJ>Ub=os}NpKS6%D{ejFszSW_q@DXFtA7ISo0T>he=`Y0vcF) zK*q+#l3Wl2C+%!NL=e7h3c77A!qQpT&|Y2qT%Oo(Cm~=W@orzw?mB5DA8pmy$9{Z5 zrl>C_h$JiH4HGGwJEwiqArxr1IEM|JN5=Jvy+QuXYx`&8>9)($=170F*BD$-69C1& z$DeCuauQcB2jKbb+c!^78p`5;%`mRH_;6#jt~cmDT6R;I&z9?+TK6BWisEIvedpAs zT8%x&6V?w8IDA?S4odI2M3wL!Dj(-hi3!LrgjIaZHt)OEpxv^k^$+k3^0l=dz2nI^Z-ow}>(Vo|Dh!I6K1 z=Ox9QR(sr#^3A@{I!?ed!?kSbG!UHX`Mm~Nfa&9niAIbwo_3RNx{Adls2##XkR6+z zpvs+3^sjxvusqkCKVu1&2!)lp9KdBRW0L|QH4!gXOrqYWr7~eW=M||A^ti?0?VFqtQ}TCiG~? zsA-H{RE@8D?im~{{E*+=Ac?(s` zjbKk?im_G4U_%hsVmZnSBkv`P)1+w2|XW>1lr*K0bamNs zxhC+OM>Ca=r&HRk*iPzBA^IxOq}rrVZC=#f zCPvu@qStq5fw+N5N1Kt%s%V+X)`Jws>tZ`N)Adgn48+-UJgzC|ZNMMDFb z^2~u@YU$tSXG9UI@({=D!G6ifT1uj|C25~(`u2m{lu$2Co}i->evz8LH);;`61I`yby!P>PlC+9pn(5E#iipu5V6Eu5h$oXiE! z!(-o0wy;!PQ-x0Syxs7eGPR^X``XMGX3x}Y*0p34Lr*8XH)jWf=790l?v#=hwVpSb z%->&dll9zGn*qL)isbRKZC?NX&h>*}qBQDqjl(y5+eHzJi2J9xv9V*=iEtN3N7zGb ztFSB^1^~aV5F@j3a(6G*K;Y;GyhTLV#Yqf1u-I0Z{Gp_d#%Zx`?McQjt3_G5-TS*G zck#qi{`0|l!YO+IAC`M>knOL-14?prprq-`YYm;S~EhouiYZV>sy#>H4=6x-)9NCo_Ial?;PPm>q^v; zKWED6Qu^a$a@m+D0ti8ajfPrF{1u^0B_JuLgoKPTKk40vOEsAt+Uo$UZ7Qhaow;Z* z0+$!HTOlt$xy_5Y*f#VczIX<0VnZr){oC&dOCN+I4x}1b#|TT)a{u#66%`d&mHuX7 z%TxU8r?0Mri9V(VHmJ#B(qN%VUw*~?_G}ZI$Iw5ahgw%Qey0}rnYnuLwtr-1BlA~f zn-lH2GvsXrweDja0cy9BL!oCeRX*oS zTp`t{`#GAI*LpKO)Iq=dG_((ec)5jN;MBSOMjB42`$V^VfxOaC4%1IUfmZdOzFd%6uXbEd7Vq^We7)FYE4!-Zo#7yD>?ho&; z4qM3#HAB01KhmMvEY|pIP8Sp|oxvxxn}Smn>wv+Rti{20HIt`W)vxHi@2k&FYHxG; zc)w`x3Q1k*xr!<(W_acXFuM$AC#hVn?;nWPACz%&dZjx@Jo7!QH_o!rs~`+zOh1`h zGZ$#^wOQCsr%K(-P*uO&hg+6k9R6@ldj7h4xD^TL)NuZNsv{gW0$b~%xdN(12VGr) zB?mRJ|KuhnCZ>MxMn_lIPCYGc>sn09y(i@AZZRZW4~Gx*z2>83Wn>x13#-9s>M&}J zE%}Qwd3R7YM@C#M3LQ~)hUofRL|(U}lv!Rq{6uSuiEQ+nuP3}4?%lc8(P%o@llH;U zR+^zDy82(75RZ5Wzh0eIE-fvkEf@0ceo5+M#*5?&H!VgnET=Ax#!I)>q^N!BbaI|< z{6){Xp{=%SZRa|io$S1;G_dbqe}HU?G8(;JF?RDxxQgD!=wK;B4(@CJb`$wP66@X6(C~>c z38KK7PVgy{q#y&wjPoVsD!}+UqVM75gnI-1MX39`9t3%*&3vgSll_4S74K2Xj3V7& z$N5=P^-pT>@~FAz*P(8GJw3+ezWaiJ$WH@5J%&)cbsc{t1hkB_e`o?D_k#5xyNoy?_%7m|k_qq+(-QWp`XSqji16*kCdt zwbt;1zcHElN4EIQfyc&o#p5f}?z+JNHC*ii^3JxaQx7)=t;5YPmo&t!8574&zxx`+ z?Ibm~)CrGF)UqUQ=?hD)mG*YN0EuDFWk7)|^ur(jcQxIOKWxP@e%tc!@e$azw2J9* zj2mpKM{j)OvhmY21CvkL;8?0~Rlum``pL1A;y}vl2y{LM-mTmEkQuhm+Q+p$hhE={ zFF$0K#S7y-HqC|0XUXqmE}`s7P0TMz#6Qf1=@~XSn21U|i9?2JeJhc5lbkT19e&xqoeMo5*)s+6gzHs4}Ro96qB}FXL7r+)1)e&d#ha zwV9qTQ-n76axFX~cbm9gsp)&1?9`DqYuL)YE$qaujXo~^eNql{g_VZ5qZEFsC#7TP z!R96OH(#AZnfrn1%?yd(3N$KwH?l?ET-+R8Zj%z8)KU~i2d(X_C-|T(u z0K6{{poGs7LY`~;*)pQ{jxG&{J6@=5r@(o(vY$yuL;EKRoyAeLp3~ShHRm)EnhwKd zUD^rc_l(yyhHnRpg-S$QE)l#h=5%2FKJ0(t2|B~o*E8Sfk&tgM*QNx38)nZaWI}*d@uCmQ4I-7lS*N5xgxYnb6KQ*VhR77s=tAns(U#2qzmAYNseDqNY8QAsh zsGHdLrJWdVk4%rs4jl;Ff%>J|#!zf@NFScBng?nSV5KY+!kB)`RLs|FlNCS1Qn0xB z9Kl46jplJH#HtHw@a|#Q!qaa4h{&IL*hC zDZRXjctb0XCyP#YL}-PuuAzeQR$6sLqP`MylYUf`!NTz~s($$vV`^48TZ`pE)4U9V zRal^(Wa88^ZQ-Fj$=^=dFdlK=%6OxbO^Y<0Ym4viikPaEF_luao$oys3(MNtEn~N- zlTk&8yd@Yi+lw0zN_b3>+AA2wcn3{1HJg%u6SX0+a)53ivw0`Jd-^F&0(YR%2^wUE6dr6E2ayVmll^Xlsm1`Sw^AI z`3NQe^;|7F0_%fMzE8UFItPy?gN}>Ql|zk*{W>GzcM%-MgvY~krJ6RJR_c6!lM zps4xnaO0B#T~~!F!GZG*oz<}zG41yw{phjRJv zMwyVB^*uR@#SG2eN8DEj_Yn>41i7s2^uFm8mNS>wLz3qgg7(QYV^JnHk#YuGke71M~vV{*{&|MHno2H=~tD@Pv z?C~)M_)W>i#UnsXM#;uVlitpN3}n$WrYHY4mk4*#4xQWdOV{a5gz;4+dH(Wcx39(3 zx8=*jWIA8RN~`Vpeuw$X^-gQX#njbZ<0cbRQ4x=pfUVqL@Dw}rw#5K$BAi|^Pp1A~ zNYHfciu;!OaFlb0`Nf0P^Z?1K_mRu+QDf(Mg?iF+oLkNI$ki3yKCNibGw>yzo7mk+ z8uqm-k5z~3B3b!%nh_yy?ItH535j)iOdR(%+bklitdRY{%!!ho|Ts_-XTP7+JB(u$6JwpnjQ=tc1eC+Y`QqPO7RWg+^VD; zX)2#{1xDHIY&W+_oG@6wQ-aLDIFwdp^fEcQ$V;Nha#vBkg)#GWaxvP)M8Q8>o^wq) z@Ka*?pNb~p_Mig>*Z>TP!z>0`V;V0@lgKkCo=G%dD=^MOVbZKL{F@^VR4C{-JME2v zURu5G&JBF-wq^``^{R}2|4E?p-MQU}0rHl$>rzZm;0j5Mi2FRC2rnzE-hHfI2=4Xq z8OfqV;PZ~(VHjb1-qM5BM$Vj1SKdZK zedA*aGX5YM#9jD-8+YHQ{4Y6H&dEA|=98$3JRPw=C?{DnPKK#opRW1}i56fcZFT=i ztc;df?(rK8nwiBZPrvgVG?(Xnr}XU6oVD%JpQwuue;m$6$A? z6P^8z%hg^9T>a)B3v;b+vZIkNj-+A)ML-R$(0sY zTut-}?Bj9+cIVmwwelu6hJ&{YhevcX0bUVDQ_TpmOtc`Vg3I%}itRDXscOX0YF|6i zBfgjIv`hvm#PF57-{bN(mx0^kCMkZ<3^l zj3J*kI0_{`TMLVQwxalFjHzG<7JotNH`+zB?ygG}D`-Kr&6ahY7N!MJcR+m)W&%X= zW=&^aUzv)A?9FuH5XTWe?+k^7{hs5y0hpD?z?F{UqQk}5rEI;Ho8fx}t@_Q>W2%#C zYtq!1`wh!A_YrlvM?Fuchg;%u^$@1gUixc>PtX=+Qkp#NfKT|l#L5od5`i!PbiA!`zk6y3SmNtly1G+HCKjvaN7W*)3b{KYen}|f~20A z&6k!2UY}mMEX$b@o9VFbea8V`-by-B?+rbNs(sny1$1>+5YbVR#yTjH&A{?}siFVv zVCu4pNxJJV*D+1`4(>5nm}`62bhM@SV2R~7nN3eqQk zEO`Jam~lA95ZBi?5_Ke36fmr!^^X^l&tt){`S!TB;M4r0eQ>-LwxDMbxk&_cNxxnJ zF+)YEVCK=?l11h98h1rpgjo?`>6}3OBiW{^ne-S}X6N|>1T{fjG2Pp)(N$c0pbB4a z?sKLb;s8hwn|&})C)uGk5^Fl%Vz5Ns+`_y^{21>H!^X`wPa$YNcy5VKA(OwV*%i)( z^sXDsCNfvXMUF-V7z-F-3UP58Z1#Bxl2s@gmL)_=rSX7sv0M-CAt<|PA0Kijn7h|m z2FrOcKB|`fM{B1)1poIhXNFx;6D=9z&9D~Fq`?GiZJ z4sAtIFR;+Rk65)vX}WwGC_qSUZ_;qI{7n-_PjlGEh;h`Dn~VM7u9K!FU2iJ6gQaoT zYb)9D%fdrdjb{hA)+L|j@nP-LN!kQ1yK{ZFkbC686o$PTPA=jRHz+-y5ZI?d-P15tPgJCG! zi|*w9I=1|$WcLIdt}ye1ow9wblKjU;!CWnmpbzjlXvGatLH89nlfHFXakpcBoRRE7 z+YM`gj#q@Dz@zU)>$)?OKAYf@8MT~bpzmEp?;iE8Wq$d(;74TqVGzOR2-c1B;=NmI z;Pt{KSd{OW&@R)*F_3Wh9bx&zoI{LK>18|H5cSRFo!81Y(n>l*h=s9w;cR-IjDl)f zMPaBxr;oRSC4?B3l)i{tFa4Y4TRyH_y_w`b`EaipdodDO;DF)Iy}c|SbJCo3CAan! z<1}@3laM&0sh&cA$+#dqCAyenYT~jKX6tNl=du1KxqU}Qmb42CrD0s);#Gb0Ax5Ra zQdoe!IkSNgSK{`TQf=nR%wEs80`S&j>`C{709v4;6qtO*t^L2rn*%vwyn$oEMs?&q z$ZEZ5gaQ!@*A31(>zO&q%1Ab)s4hKkU;`cX zeakn|sMmrvWJ65Ez`cb%&ny#ywmZIXU1B1X!r}dYCsmYXHF`GGmesA)bj))1mBsym z+yV2PZqNMbQRist0Y87@x=O`NpZ z9J^}Xu;yF*HYrNg$t@a+#BSkBXWVK$ti+aG#(Cx~8H9fVbV|+uJk=FRMi;$9%6cw& zr}jJKO|4NL4SNAfd~z3%`0QCk@4aLA)uB6ex`U*mRnwVu#RLe@_4XduZaQiS+BloU z1XvmOxq?0);x?j55!(mnvVJI&aK1Ojtxz^ku8jX-nHdm@>7yIMBbi z$G^BRE&M5#2c3E2w)MOOs9wkraJlGpS2l>yDL~~FSjs<0=_ahr!bh)lXSe`_{H`wC zy?lv@Kp%auGWWi@LN?T%XBouE&vtHl)^UTN<0dqPuk%}Vh)JJBs( zXB|8G?myl0SNG&|93!%ng9HH03e@_zfTzsE<&^p>hOF=%1R@G z$9t>oT)uueXLCYxc(b!iSpV^Xp2h+|tkeo;b3Pt3S2&#I!-~rUkum%UMk5}bCHm3G z!R+p7zaKqTn{Kq%(#>{FG&=7|?s-!+)VMfKN6jTvp1~uvAJL>$H+nrFImC(cl4};V z(`rL%)~@?|Z>KC`fUpnT{>;sHeW$9!mNeUueVSSPu^g!TdV2h*ySFp)&4%oQP5gy? ze)?qX(}d#QUkyIAXUa$RpU@(dPX&*w4dG}Df)l~E;dcgbg9C8q6%KWux;bBHK#y(v zkouR6eZl*4YI(M6bG`O=2_yH{?!oRR#a4=?v~5A$7zsBNU1`Z>RfQPbc;!wL4aaxk=yv>!AoRp-voRa`#OnVM18 z8o{{FW^b2}T6MiG{Ey#a_rekU^V=Ad2xM?fe*hV;0C>14XDNW!<@U!@vu=xvoi<|> z9nOHID1^^Cdp=kIxXTif#NNjJR8PkUUbK&11SC>ne>pAe!1Rww>c5LBSFJF!x?i2` z3#OJ+ikOI%xtD{4tcaDW7pr#?9#EjNiPM*#8@3>#+z^r<>xX^#de)4}OjFH{R79&?qPy7o`gWpqUsAX5?mKqG0d zddbq!=Gk2`d#}OPNke+X>KJ0DSovbK^0Vf}{^3jQz?6}GeOmRlU&TvT9Y`wEh$Q|o z(Oa$!!RFTAgjRt+xxK{aeqYTK)st1)>m_R7Lld*v?%21)OW&B%_Rzs+!IF zvQ)JPTM`RF%^wmj{H}Q~HA8S0DkXCpR(u`?PMAN^^qjY-W<*j)scrdpaX?5Y^*AqzfD3>0fl|5w+HC*KEpWhu&{+_cCAWa+R zb95)oS2=y1?%7BrUyklp#;hHu?Mp&HxJ(4D6$mUoJw8P~Y2>e%)eUvE(Kl5e_@%O( zL^~tQm{>-3#nGhHEPgg?vb`|K6EkH8!G-j-4z=843sx+`eL|IYm9&42GQhgE`)fJTVyhf`lZO}7sH0J&_ zirh*?cgLeEWdzxzo|qGfE38-#p70Ly;<&V@W57zlR)6qiLnb)(u<&+gJL*qcy#i|{ z(`d8Dh1Ez!CL0qf5-+tNqtFXPFFa#XewLH}I=CF!r1_U@4aBc7p382zQ4vgpy?&Pz zA*!<-%e2$0pSKlwK)Gw+RyFyNN(T?&(eFB)6j{02`c@jaW*$|DS2$0`+gD!G9_k3;6}@ zvrs4{+as1<8>MFtRZ43i7ZrVl1;=VGy?hcJ!~DpE@99OC z1du|e6p1CsaQ+2$60g{gpf6xVt{y*e5099C7b`OeE~A0;P+91}Cmx-3N2;Be{l_T_ z2MxW#%MLfzTVu1%-^E!n)G-FU#NVE*IEoDV5+XA}W*K|Vx2ow;dh+_G2#{7AkmsNg z$ah6=LeRVrV_$AgH)_T11LDQc4PkqgSmL+ywhqoD2b|V1Cx73J9xZY$ z>+jZ;fH`c|j$y@A6jFy|)Z;ZyZqE1`uiIuMZT1ezkNczw9p>0*!2z3dXnX zJ8hHxh~Mi-uYk`_t!qrHKK;1en#_m)ewJ+1ji9VFLcpq+Q2ReSxpY#pK@9TC%d8@6%ThL78CzIL3G zKN1qNA$E~7!rAmkmQT8&VUAJY{&RuwAf&i_JgT$q{AnrE2wcBH#3w1kxO0fNas=?4 z>}~ZAA4SKKWjsiuw?1oiDm-;~1+{h0PaGwzJSJ$CEg1<_&eS2U;MZri-otqQ7|OkGHHtIo2&HY(33>pgbLBF1d82|{)Z!@iS;kG0WxIo z>13f*HDllarj3~CFIaNrsqLu$wX-{5=bJPWJ3bB7-Xi-V&7c~jan=iEHi!6$YOD#? z4V7_|_;F)Q<&P%u@;wxtdGTPNuG2tFP6gRl+6I2#z7$)(FSHRh$H*8UKI=- zqzUsH>=FRar%%}V7__Ad{^HStl6eKal6jR;|Bqud0RwI@pmH??uDOAQ%uU4v$sc1= zl2hZlP>>7Edns$UOrxU}!a}9_Nr=(xG63 z(DXCZi}gxBw%4&**y_t_z2W3%&PpjSY0^%2=I5s!_gw;`Ww?3gX>4I@zmC~8>wLk! z5Xt(rz?Q@KJ60|_(%-#`=j-#_=+DsK5o?R7URA7N69|f$Q96lD-a|M=-Cy9Q^8ZLl z+#w08)oK39@NUehkH!u=JjLB}cR*%-R`;9RdFR0G|pWK zGr5{=VyLXfd*DPky{G$W7z?+vnIzO1z=O@0Lz|YXzBZ)$wb$N71d$joI$XiLKw9iK zX+&gDgJK&D42i1OaVn}nAL}@SqOP?O5u^)k%b+42!2j)keg(khH zt8s^|#(>QWx`XhWQfSkFOqU^4Wa=7d2+Luoy|St7`dMM)X+Pd=YPJ4q`Zd?9@Z*}L zyy&I)arzyHF~?*mPa%diFAE||3`?&GzeIgvLPA1nDiUcAB_*YqnHlgmYK07b?|Ua_ z=PO`-KzXeF+4}FnB&K)`fGaVeGM7b-ku{o0b(w4};O5~GhwIX|_+U}vLx{6i!7Qg? zl#XeWcOGt2m;HLNU28|C{+F<`Ex;X-U|0vYgDnEUA7E(H`ikv6Pz#y)nA3ie436NL zGnL|C#M{%eGSZXhcfxlDuMNKs=@Qx)9F~F$ET+?+ka!1 z4E;oi@YmQj6bma93tAPOeG5T|49CI1hMR)}JCK{28cs0c4#QYKbYN0{y$8Sw;C^9w zaYD*8JAV&-$)hf+s|DkJt%HFEWV$N_4Y=7SzMy5cLvh;3LTs3_N0mW` z?B;iHe0==G_;|k;!Ywx=E$ui>&(zeEMaf_s^mPj<6K{!&@$*b6PlImQRBYtckCU8f`U#F+Re>ecPc*!AW~m#5 z6+rz$!HU}sp1;6AU50dvx(5{q^gDV2g}q41N!6yirf_rPQl{nQiqUn;h%WF;TU%RSU%vdkaC&2p-R9uXLOg_SO7ypBE!fw6*Yg_T5<3gQU7(g+`xgq< znE(lfnznQBjiHnPEfCTwu*%y6wc4`o!COOG5pfgKhc45lY}_2R&Gdy6ckI}xhcq{0 zl~Yn{=U`3oY-Z_J{0_r=CWXXC<{MA*>5z$^)I#=|xY)qR&@}@?0ePm|)kaMDRHug5 zBaVka_`1b&z3oV?i5-m+6AFcmiWuYPs?m0Pd)ujl1ngH$G3XsEuoB*cX|OTJ$$jw?_1Cf{+1})$V~1 z)_Jj|c&#Ae_Rc`vWSzW)KhGw-ZM`lS}H5(6H)R!jSKw}+K>Cidg3Fd0j9oh5ay7lJtAEfQ1|tr zs}wH&05L)hOo;t@K1Rxg8}3L|CdI+?VGt9M;N!WxUDmr=KRS|I)&S}>q+|l{V&p?% z&(KN96{*KB4E9a)Q1ZURv+#vXa+Brb(EGiryev9sfKQuze46&LzI#SmOutr#3UG?_Q}y~ zHSHZw2H%)jP(F&=G%kf?df(4k7-;i&n!dN#G9v;{CeXpInNcghIk_<)&CmkJwpM_w z`#W`rmxIUGTH=0Z%wPV;dA1-Z&@~^s(x9jdfFA>2=6>YW(n}dznTr&62Fx{e7ybP< zpp@197ojg#3ma7cgV=$d_S0q0-ybHYJLYYjnRJ%}|JKTz9=l87){v0>7=mKZ{R?3_ zJPSx_aSX%Qs>`bI(Mp)O=E~l{#%-dq0o=!jn$~8%P_M>Dylgn{#lOVFF}xFkI%JX= zrPI_0xmdmCutuZ8Nk~lG@<8?sb9Ww-09_kHvSaaoJ*IQYe@olWIkys+`J^!jfh`lX@{j92|MRc`Jivi&3j+I3@7@YCrEOFKBam*y3$R5U#WlLpg%)i=EhW}lnWVZQ86+Al4jUrwhe(QmD#P^_IR4M|U-RvcaeK^>g+R_6 z+0_tXVo7U1#k}7+!p4elX{=C-xP+YEt;5u8{3eZem^6Je+MwZ9zTaHtt{pEX&lNY@ zjjfN5K&U|O@Ui(2B5Gi~oZ?pNmnx_Y27*4mH-5+uC0O zIkZDS@t>=eQIS_8T~;$9FK45Ag8NASZ1$O%xS$%_Hl@KP}HpkSu{EMDt6JcM@vGG)3k zRD%M#6<~r%(BKho(2(Ug-nuF8roI+9H8r4z72)o4rzlRWWn~V${f&{rQt`X{+q&n6 zo=J8cXkb+uWMh%;-*&X~ZD8{2nvSv!)sW74*STr9Nst`$1SP|T_@O9p$Cb2$*c2Jx zyiaa0^=oehmSQZ`rP<``QdIv>QW-mNgP=twgB@~YXZ}=>)$;=}lV3+2N7Cl@LYjL~@WZ5;G`qf_ICG zXUA9I{5LIwiiBt)w$A7RJ68Hz%R@U##L_n@Q;M5 zk(S+xdrPJgSOnMSfUC06&gn`|o~SGKR`u3$w<@=*?=dF$o&-gn#XkTJEzT9=HGJ#H z!pViB(# zLwfS^^YaUSlPw<`a4vgW}p_+@HgKY+7~4h2&8* zsUarm>)T@!mnk1nFC!1kM#o|;!I?tlVJYuJP);>uxImx2}ffoaVn3$N5kdTx#6AT8YrKJHN|HQ<^*w{_J zC(+=$$AZ(Lv|7l&3P!2<)^!OighC~hYQ^s)B53<8JAJ+(`Bo7#* z1Xrx=T-?xMaBf9jFC^n{2yvvDNly*Y6h?Pv-I(>-3{tU*PY3qLm8~EttyAv)23Eqo z$t7b;UV#P>&1^3qYdYo|B|&4!I9u9i3T5Yj$2ES2>J--)pI z^|m*>cQ@%I9i-Czp)vFFwr>$Dg-MtIGeFx+D@Xq7@U8hco{;GoVJ?FpuOHfsF zKOj63XVQ$jkP2Q`>r3L7m?3@nE3w?>IQua7m^Cbq@5rMLF`BTI++r;4eQU!%Sb_8{oX)XCx=} zEel1&n=Hq;hkm*k)5xH@be{IG%t7&OU#c2>7NpQydPw#_4eoqv0FP~{CYNFb$?5>= z=YoD6&TL1jtrfEwLXhfg@X~G|-w0-g}$3P;UR~IXWJk zw}0?iz=|KQHW6)jT%8O`CxH61@MX0+m!@>Pmvmv1Rq9%aul{nW9ChXS8#ir&+El1* z+lt3g-OTcF4Nvd?cqbNi5(V;pkXA|UbNrv*QaEF!1} z1z-6SsysT(z}5%-bo0bI@(4+4iYQ`v@oc*Qm#wk%)kp80?_=o#-MLoOA`J+C zre$ORNyV7AgIS{nUV#igYZFQ>>otxJJpEC%q4*c*;@jCwOme%{C0ApuY?RGJ`*7KG zuq=Oq#bJj+@R&&?;No-(5PZIW{|@vmT3cHK8ks}@jI{7@|IsbYt5O7? zbulX|D*{Pgi{8z*MOs9g(@>W_+E%YVg_}%uxi$5A7(CllUT=PR z7ImX%BLX!?=d`6qU1I+3&^XN%{jMmxH26VNBfw=ke@8PfI#9CLDzHwU)37b=R-%dr z2LWNNn}C_Ai)`_|(eXUSv!tk342=5&oX1_2Xm=^1=WQeLwSR+p+u>qUd~4Fb5B{zW zkD+h`K8rE;j&#d!EGEcYwpMeq=k!i4P?O#4t<7vFJWG|4-~K5yyNH*8&Fsnw=);E( zpFVv87*K(D*Zyc`+33_16n^N`l$2-kvbA8{57@PuroH@^YQKWp!R*-;1+Sa;X&+zd zYfcs*-n1fKaOzediXwh4`EdV=HeHiq1}@>x=j(KFdfpxcBv7oh@_3;|XKU}(4GQP2 zg1H$Z!X+i^Mqc!154aj^NvaeGS2+e0Z|k;xHb-M)6JMBdYry@#W<=&|%w4 z){fu}`c?hx>8kFwtwAjYo*%QAvh94HEW8Mm|XWAgl_GgtL}mW-(m$ z4w^23e7$lj?pF+2v#rA*^QQ}+clr_?>~}K#t|v)O5pPpU@ly|o83q~rnVA^bd`H~v zo``42qq3qUpYYKWq> zoA~w?7+fV4F~D6V6)LVm)ql!tIP?=?znkbE=6Twmz*45$jZo0}elq-4Ew`Px?V(>^ zJ1;1gcBS1Lfd91sJsjISZ(gOQ&&)SKnNQ%UOAK*eq~KY)N-8jF>v z|Kqr2HXYIvn9C#^Cjjdrpr;kx+P5e=QwVwYy|FRG&xkDlyyP9nSYjX`$Iw1ncaZ{} z)E=idLX18JA0dn}^Z>%tkF>?R)C83u@ftrhG_@6V^;NaCl=aor-HX>ZlmDnp zQIDqasd+y;T?MgOFsWy@sCqx2&ms9{wz$1>cpg{l4;q~Lfcw&p+T^qaJFr#q0)KH+ zmpb3%@T6XXWLv=-=s_6_D5+}jRCc$_m$-E&n;LK>3{BW3NX!ioq_gRdDH*j@v zsBBmutAK_RxM?DWMO$uL@tzTENcTjwS*f!-7!i1us5F8En_oIiht25Nc+Y8Ie7PEcx!K_CFF9AF+2P5N?V!_LPs z_qw@ZXAtc?PF00{bOFFG!a3C3goYq0F?zBOg9TU;RQl!)ojE3(;`2tXp|>OG33D5YrM&U=g=-36pM8SQ8^%+552;RA3s#pqhC0NiYI~5 z5vuG1Z|ea3tL- z)eE=LWaxKD@MSMR7(s?L`H(A#nkHzw4ipBAPfT=$U7VjIA|et1$oE&uZ4|DtpLQjV zs<_UZ;3&xu#0n);e&)x`z4+Q-Km~WDIpwt><{a{@gu>pI3?hS7)$}Z9F0@y)yzL1y zh{Bt<7%GI?=tCs}xuE|eVBiJdbDNv`j;#;Gw}*vA{}~zC4$|Bq0=7M5PMb&IDAQ|9 zSg;pW!xJKGm-&usgj8p=93akV6N!kckp_##sUP$)XMAC0$ccewi<5_0)`7E+<2tXy4P4Ro*~1m=QI!l@rxgjAA^Nbgr{iPY(LRywS+ z@BteZs5VvB4nes9K7XYkHYdLZ09G~i7jyDDZ@xNMRaj8^c#lTBNcivnkPTq<*z_X{ z@UUI3B@+=+T{zDdJCkM=gFIa0QA|m48zzSbwk6L9! zhNJIN)|4-+h;0kC%a-BYp#V!5tO_HWcKDFXLW>OW1b@}a6Hcod`9uefAYjhjQHlit z=q(kti`%B|R>TnT9^~B}c1xjAVQ7!t!A>7})N6H|ZHJ&m05lqqnYisB2{#D!)Er?I zKE6x*ZyaC5@mULTy}-RaJ$~o~d3mO$rk1`%$D0H31qzwLqi*Qy7dxW|sjR{_nmWMu zYbZwO;f?AW9JHRTGx&R7n$b z$Cn1QRWs2J3xCM;Mv}A}J|BX79?X{JS5~R%WAHhU3D_$?Zhy_!xFNZAaY+GMI6e7BsnwrYW%79#`r6nB*;3-pZjR7RvPlQ*J zt{WJjn7%T8*-?S@fU7G;t2aAV%0~3II4&=D{d6eSA&7d4TQ)MgpoLt?qF`{jG?f6-)w&)|_+{{y{sH#$IF2`0 z=ky}f{_gzWk!g>;xS$e^GR>y-9Rpu25r7a@?KJR~Plqm@k5j<=!R6%d#8-P#Po=xI zQSXy5bvTdt8@w^!$p*F^ZiRyig7Jmmir3a?U@BNa*)?cET3TA5B$3P_C39s01h+S!FXd#BecXqACID)Spls;WI12Ija{)DLO5YqjPz8^18FmPmx|GLyXr!xp^X^WljS@De6 zq&5l#-FL-KI=P@;;BSf7$=e2fd6#|?g#V$@at z@F#}Id45@zNomT`*Cs6Bd>BDlNOw2TSFdX{3EexlytFhD8SMfq6a}Exk>Q}A0qo^q zVZyJL+RZ4|k%$Kbc(B;Peu(kkjdHrXzppj(V1_}lH7jBJJUL(Qln{}kXe|{ad3Oj# z=Unb>W&KF`#e>$uZLumoszHyKX}(;yOtz!b8M%UHC7uVlscqvNdtdlM}& zO~p4N9WdO`>~l)7%f1W`k!CV7t`x|060%x!-qx?}P6vozjn$Gi7dU!;COB{ks@}|1QzKcHeGtFPrIT+_) zXZGir!X#EHcNO%UZr36Ukg& zVko7jq&j?419Z0YGiyi>TdJ62?qy{xsnG@n5{4g75BJEDf2&p7E#a?C zDjP{m{Y5>-{nIhktMTsbrbyE`$J}=xX%LY_54lmzWg@(a*l)>3~ zb90yJT4--iKJ7W4Ka{$nR8*KnPEu&r<4~`g|0LlpGYT>?G71Vd3L26H+C{_Wss&p7 zfs7vtv;-=e3a$j;X^Vy z_}b49$C@kFBZ+#kl=($_$$y1AU`W@(DzdnLUUvbc5F-n zC3i!v$y}~fFpD=c1~^F2l%`md-%}m|bY!iOBwf+C!|A%fGK+K=W!ih3o`=IUzRHka zd6GBnR_|1)ZCn(RZG=WiJ_kW&2J1-`Ac~04OP~Rx9n5iZxoOC~vkJu4Z zttquclYrKmd?6Gi4O;j`RA*x}ik!y2UJHv$%Hhk%Y!*&I48>{!R$J51zjK=1Cy}29 z4!cjRMPIfW!sB!KE_j~W?ncf8074$E#K)*MF*U`I1%+pPWFdNQM0 z8ftFwsNSf^E*IGE{S3rNvU!O5b#s_lDiJItqMBwyi)VE~$*Q_qR5L3MDxNv2*C+Cs zNhC|2@FPNYMMXo+FE_ptl_hEHG6}41@J+wcMPtY=q#i(5KR(y-j@5YDt^IXob4I%HSh83x@%npS6BK|WaH(<(*4J>qYAu1U$Ny)yxzWCH{ z@OCpp3W=*BAp@>^ft;m|)j*UOJX^^*seFPBbmSsumQQFu9yo)&0X2q#ZUHj7D6jk>S4+Qg-hy!SSuKJu~` zF}TGai@~YJzcQQF4AV6StZTcEHc{}zY`ZT8-^ir33Q4ke_Ib7NFI_{(wg{p6r}sDk zGZ}_$V>dd4$z#D=0f*R?6-{zX02ysBtB6_JTCyEyZ9EV66(;90q*r2_`+!>q z^w{w1z&88`r(WQ)fj*X_jCv{E<`!~tJQ)CjP6-3CPpOyNr!|hSiRSVjHu$i9N0~t7 z=DqssyFc`E`{Q%?$Cf_gg$5gK-;0dt4`a@wZ(r9tGH_nEwYCZo-wt5roQ$6}R zoUZ%={si_|V3`A8vUKiJ9OLC+gjd}C)a#l*{cK%}Qla1G5ha}Uwyan>-bRyM?yV|# z);?pk+sY8Y?ddZZP-8Gblc{u1OAUYvv(*w%g?EfqJQy zc#X#Z7c@O~cRuW_6fuz}l8nck=D=aTV{X}635P8nEum#o$FJ%z0SuD%coWxH6x_Vv z5MtdL`_i^wvPM@=8D5`;E>@Z?=OgDjGC%nt0tXE-I&u2$JM%$t8Oa|SR^V-?Ej$yz4~W&wB@IF(L`i+^$7 z22Z{l=->-*TM9UcG&E+O9&VBn5`=+XXs$GJRcnCKQ^p1VTIT-6@0EZ&{^JW~_aJio z7tA!22YB0CDMhe>P-W7}-++wv=#QTx1L!z^m>{r9BHL7%N`1E3GFDFdno?$r}U z@n{OQubgNqHSRgy0Z+zI!z;$WuKK=?Dp>Jfsg&vZmes3CT%rk3tr+TDSNnoZ>SI)a zW}nw!=g_Me{s!qp%rJ8^x|R%B?L@9J>TZaulRahz6oTgfoJ#W0(113h#@vlQK@W+~ zsVp4Oj38X;fi0WB8e*9c-_v0b#f1O#FzzfhM zNCXIQaBzScPM|$4DJfH{QqAcf%z0cAPKRokS?27z*;A&D$7%q6d9=`Q@|C-C21p-4 zq{f+N84n&PntmQ32Z`(KZ1MHuNO9b+CbNATeQ2IGw_dOj|k;EF2WX zDNBVC|1kO;MIoEBb&2Z`X0~!PRtPQgBb&R^Rk23lpNr_6z!0_*I4zD%8To`#jdZpQFaQ5*{6XPmxEiF zUC|yNXDW@Nq~9SnDeeuKRv*_y+vDndk{y*(V2sw`kfn+JL+mq)4Z#+PLz+Dar)-MR zxT;k~NZq$)sH!_DV*H-BWu70`rpy&n9WNu6KumOK>L8iUa8sYiQ3ZU2h6dO7^OXUA zdZgQ=zx*HC-a9I)ZCMvbQ9z-IO0bC{q5_he3@Qjp6v;W~oN1aU(13s>$vK0Pb4F>& zIfn+CoO8~+g?pcK_SxsYcklZJ|IjfQveue4t7_I)Rr9NJxrq=Fmm zk#s(Ce(e_AKL&t*12PF@2Pw+&h&Uh6^VNSkrX%yWGC50^^z<`+k9XY;?N%iL>n>oyn zAbCSYI@Q2v)U1&T>HFFDz^);7gLZ>#-q)mhIwOc_#c$SUj;BX`KKeblgKX)z`DA9} zh$eN!>-;YB4cHDOfr6wN5>7&JGP>aY!o-OWQ`TT5Cci$tCkmz}&bSdbL^L~#9Op4k z^0NHmpk`qp?iUtV;X^NL!`%J(^N|`~dF@b7i{g-1Ke6E(FmV#ESwQTf|Dt>U?!uX6 zbNek!53*4SlcwWaHyIZ=I#t%z))sFzF1V^^Vs$Y4=YUA%?95w`Gn%>cM45@aIT*VP zZ4f zu~n#`(L0(H66f`ZEGyU}$8uri!Y^(QG#I-V)9R^<(#4;HA@+S^thCg6qImQ)-w|-! zI~pU^=?%b$(Aqc347I#tDq~|j@5ebK1QoN692E`kV=ITflT0ulk0XX0eat0;Vc$E7 zBFd`YeDJ~8%#1zg!XQc}s;p11{y0p{J-o9h?7uSLg@P8{eUaCuvEx4z^<9PfCXnc(lV+5v#S zrzR)chGtVzsAq?C`lVLO3QMyF;SM#Av@^cnlJC27qjo8v%KNIZzv*#F1$3PxvtvK!>0RjLcaHjP!j&!|qUVvJpD(*Df#- zeETF8qSavDyBFuPUt& zetfJ)qyiSaX?eN@*#P4&tb(ok21(4vCd5t5^em}&a4T7&86Ft2<>t!k-WGajd++O* za-i8wR%%-*&z#&BGKp*wk^ilOq={a5gKpbV*{qEYQZ!gGZa-`>zn97f+`~XAs3rp8H8)m{pf*teMv5w#ME=2r{nL%hUh~6aUcuNg z>y_PSMLHf^H@m&%SASeXQBtPe*bN8l3!qEs2UZ7^PIjUrvF_dT>V@sS^8CPe8X zE(EykCyJz%21hs(3tEH?@-rt`Sd6k!GXku_N1xGsivko0fsv<5Ci%cC)k8o=BjYR{ zuYnmez;<|owt1}kn$$5o`u~`|WMV&qcmS}r=K;sXN(te`Wo$qWAPeZ;6W29xkk#4gBX~5ldJK>( zGbK~my+{5Hd}BXu=M8{VfA3f29}Lp2zFz{4<5h zyQ5QMHd=s=iR%eEKR@@rVP3`u6Km)P`#-WmECkv=R$@;vd!sa;+A-o{PHKIzuiVSj zN>lVI(BA7taEE~40B3df5+eDsP!#xks~zxB^kXb;l7Dbo{^&{M`w17|=l=l*xJTM9 zV^1Y;jr8?Ns}_pdhH=*8`i7lzO3Gh=D^$R12TI&`00P~YKtlTk5bWn-f^`s0YF5C+ z)-7ECy?P^PmBCBD-&A3i4F1O((8hMIF3*3$FE1|I-j1}<`Tc|gd2?rA5w^-m_#v>A zQO-HjJG$m*3Kfb5h$xRc<5pO{KW;M(094Kzi?@n@Z%#xYXdgmO7T<>?dobX=fIE;Y3YY#oa1-~G)pZHxdm z`f!5fweg=H+oAPEx$u73C9U>W@>bb95+J6G#O#2dg8Ns?b$$k~oTym=_oQyxAWMq? z0|$zTgka)nPhr&NiU{yT{mt28ozq_T`s*EydJ8IzQFLI%nLx4e!9^mP6!UAB)~tuUum#p!TtD!bL?e&;q7hE6@osf zk!e3EfB&n6R$52^P@JWHM}!6*f!Z0Sf+B#&S;SPuu|gzYfgw0RV#!1ljJuq|fMHSx zSOF0*67631%V(_Ghy_u52MBq@%rPvaQklZNa{C+Y8j=lmxtiv3NSAI-${T$1WIU#W z`95m3N=rH}qa}-&$%I(IgqFJMKuU^=k4zAC_?5iiq(5VyF$g&`b0IJbO_)zq5Zf35 z%B(gg<#(p_V|`=ZRhl~r1e-MH$JKGAQXdF8Wm&NdrlKG6Saq>w zya@R-Q7(fT(K5jzVDww`bF2diLBHBYe!zcDI|GsgK7<=+?A1rin2JuYSefVd!$++- zr2PT20yYVw2Yr+Dl<~=vY`ScNETbjE#Rm%u4;LRs5kH6~iBydGsuZb^^o<*uwI_er z&b}>g)Zb7P_KOO5K+wx?@CO&4yP zS&jwjjl*jLj1Wor6J}gJpRpLD!B7w|miRV!y3&e@OX1pD{mo}V@E4i(8H*F;g)nQzbd;$ zM~gWE&kxYlvR7Myegt4gJ3FEYYkmEUHu(PjesCGUN=|A)%2L8vHVe;s4#|`Ay$AQb z*|BHfr!R2Gk9LA�R+`I1tyzyh-J=^I?7-t5?J;I}C}U)i^HK21T7 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 diff --git a/doc/image4.png b/doc/image4.png deleted file mode 100644 index c4dbc1850b4b6a62d597c20a06ce6909dd24737b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 32473 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 YPbDILcfM&Ttbc!7MgpOHMZfy~FX8VlegFUf diff --git a/doc/image5.png b/doc/image5.png deleted file mode 100644 index a9b02f9c3cafa7c3ec261a5af1a1222f8cae3057..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 50002 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%0A&+|^J-79U{BCKHH72!A)yn_ux%}AzD(TOB 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 z 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 diff --git a/doc/image7.png b/doc/image7.png deleted file mode 100644 index 25dfbf868c97916605eb7ea37dcab8b362ebedf3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 104139 zcmYhi1CTAj(lt8P8QZpP+qUhQGq!Epwr%^2ZQC~9-0$9q_h-cJ9o^B@QQeifGIM2C zxV)?w3=}350001tgt)LG002<=?~eik==TcjBdhrDAE2Y6m>@vSH1^r=35c11i~s;Y zee9o415f~fpAHFO0cAJc%WhC@<&Ev1neJY)>o2|;$BUv-c2uzWt*KcZAi{tMK*L$6 zfK`bwLUN$_tzY4RrXO^g#h>)ON=HDLbR0TpH|zcCv8!%Yo7ui-T$XJ)KR@4St;xtd z&%m_8WuB*J@JY3(VSx9o#tDL9UDXf#J+Q7Whuv`co33Iam}MNt4~ohGeXa!n0Y}03 z>-}3)|Hz9+wXW+2!}>iu|25;^Z40{q|e^*^Sr^72#idpI-S2!MfkScrh5S$+rQ=ND7gQqx7oB`T$;E%BoZ z`e#@b00R4aa8g=QI!r)dpaeyQWN?q&Rx|YC0#|Dx0sUtRzw__~0Zy1QHLNPEtOi>2 z7>;^ea&}TaL@}v$Qm)ZD{lI1FGP1B6k;lm=F3k6*XOw4KG#dtS1iw|oAgC;_@mk${ ze61%MjnPa?N3S3}Tv9&jS2YcC#b6q+)I!<|1S_6bT3S$8UeL+R?5~upVW^XkQ&UmV zkQGycjA*AFAX}5Pm-bZ4zkqopp!dc>(Xo+tR{<_Vp?vp<@>&-8RtDyve_->g0J#St znEcF-)63=i@3ec>7StA&m5sT~i>eEQXIE5AFjw=+i>nIAk=!N$+?PDAYhboMCii(Z z!m-GdE~R0V50w{D{N3n@fH@QtlX#6?ZYxqdUjnt@zOLWiwmV&4LN-LmbZ}r$f~ez~ zlCxIO$;GvF1Vkh-0n?*0Du9H5G&p>VFaS{0)D#5C&n(9*@Y6ITgd7oIhB_PO7gUv2 z7PxuEon(Sy*~IIb5iBPd<@5Coi)uiIoMp0HF~lotBIH4S;3L*8A#9vc zf)WCHLN-gE`?O$;YszcFwFtsOm7V zEUl~vAD#T-gi4Bw3yA5EjH+AhzQzJd*OER2CP<7jHu^c_7E)KJD`>G7MaC-1g&aZQ zH6#Q^K4<$oU2EL=+T3rhpSW6UfjWI}z|z3ApE{}vi)%`#!JEuT9+pa~%WEw3tqlxp zO`KQH!_wP(B0>s+QcxRBtBCp6(`~)=p<#f*QeG#k@r6ZXWnVU<=R?j{E5#n8WU8p) zfVm89jf-dtEAR)SM#9FkQ~;C|R27-HecExCa8EqOge8>K)Upx8f;DPr3#sLy8aI<~ zRS0Sy7Uf08D9W+YGBh+a)iu-7&dSj(D9K)HdAI_P{Xu7&b#xz(G0!IQe`x^%UpO5!k?`F+yOO3!L+7Y$Ir({f?=$1Y@BNsn8EAw9%7Yz>y2Nx9yvn(AZBQHhC zdARJp8)iopyS+q8MOai&oSsz>9h#5`i#V|)F{_{u4+Wzj_f>&P%fsJ0DE3j2Qc{zU zfMq}@B`9<>bW}tHlq_BCzCLf`G8!Z?&grE(ENE*essUFWnh*~M4fCrU38?gUNy6mg z(*Ozz2a^nmD8ndJ`TH8$?>1wE?m&^a+tZypk#|r~MFTfcLtRuyX*uv6Fd?|K5)vTTXI3G^ItR%<#v3uynJ4G|>4F1-C}J#h zkzET^Q)9#x>%_>!e8st>B$Q%`7_81+m)qKwhLX_Q`zr$e8`|^+z!e+oeE0bg*Z|C9 zQxXCrzf{^=ZCXr9LKX4=5$oTo&c&Oq`fG#EwsT%dxrXeXrjh)KsvTMMxkvQA8i@u~4CE6fib$Qh}r@rYhqBl4=M+S8{)N21DdTK1;4s)_?lwTT@K z^N1CtbX!squ-uiTv}U$=h*(&=6@Q4;Wi?io7q~chSlD=2-^Y`gN*pX9+{-vHB^e_) zuMOPYv|R;WtN)b7=D4Yi@A-H2eVjy+?qeD!1XhcLD^yZN( zmy|Tu^}gr+K2t%WAixpJZE7P+r9K)mVV=?HM$1f+*N(&VTGAXnJWOm`9OznXLics0 zVv!&qLCXz8kXG}ym(?BkD$G!%95I`(yvNO*Q;UaJVBxqz!_`a5#QyH<*On0!5S=@1 z8$7>WQbQCYrzqE21@8)*n30izYWLAb>L{o`7W=PPzj`sZoM^Cq@36$IxYz#zmzEKd zP?0S-NMrs^yB$&>NUGj16bd_-=T>tv>9kQHjfwE%zoZy1oIs4Ih;V4wFO|i0c6D^J z=dCTQK0b6?K4@rMNsc6wQwO?o?L35N!kYv}J|q^9_zy5>AysK6(~6zMxS(#e&M7SO zy?3=`&*vHz5*7dTMq*(?H!P(qa3HU7x28TxV9xDJ-6tQsHoabN3GHj=oDp0U@E|ksaE%q^p4Zm({ftf=%mgJTXILdV;jD zvZI@bl&Z8OjX~jUUQ0?wQC?VH6eX|7Y*&Gfek$#)pFc)KLqSPI7A>Eo9GAS**r~8K zx22b=q^J>oSsmMMNjh1*o2tOhu&k>Sx4gKrpoMu>MnYU}96z_ty{fGkhkNFD_DVtb zV{3e(BqcJnuwvQa(J`U4a347`+VKYn_TjcnL}eLnSp*OHn8S@PJE-EBgNO>>B4KVj z=DNC^S{kayw%pR|Uct>tQqap=%h6ROt|zE!@C%LTG$x~KadGS-RGGxNdb2Yu&^`tn zg?XxQLQDRtm}K~^+j}e7fHvZDz{OS9^#^U4dXOzqOj#cxefF z`7`Xl(cBlV3<|+uNo93O33X|H352wYjD(D8*FzorGdBujGJ0!mjQF~diC zItUE5lMxL_Y$Ze$d4;4zgjQbLy?w9g{%ut)si&yw=E6Y?v(m;CF=-f>CjWzi3s55> z9(Rq?Ax5Sjlm+EqvsQNSjA!Lu=i{9Z6oHF!O5tUi zJ*OU|bGz0(g>N`-pzM9Tvzh|#28EkC8V)8oY~Ccaf}l|#TM9mmzKQ^gf0CO%{r4dC zZ(;)H`2z1s;+dng#$<z2?KvXvvflHUgpR17pq7q;u7JYZ z*q5!cTug6aJ$ovqd3;7dM?_U#)me32K=>XvnGFLj#Y0iX@%21Dj{(QdWy1D7gc3na zplbpt*gvn!L(t+$2M;c)oOUb7%j13I`Yz1brJYmH&7li-To>{e>VVjtTSF5qF^M=( zx>`+h19vftuzLF1yQ`qNoC42M6OiJm`}aP6VsA z8_cs>r)C3GWhk2Jk>?bTF1!^4L{*e@`T4NxuOqP#{}*p>+{`5*%v*D6QdU4{IIDo_ zS5!nmXoL$A`D_xvMq!8r90Qucgr_iBzCfFNDYuWv!0k@5b4t6*9EqSLqx|~mDQW1L z+(r)9=cJ5^f+K`RC9-O3SsW(T`MCv^)?R(j?@bFFn!H5CJYv&ts*-$CGMbuG++?PC zjmOmmlCCy{jb!gN>4a3Vk;!Wpx}JwO3mIIDz!MbjFX$^iPc~zC4R0Ym>B-6NhU#wi zF-b*nW!ZnUy|tB$lR|p8e)j~Pd0+Zlwd75)a^maz9?+Nz2rf(5_P3%h`mS0g9*+-x zyZk?9v9;=D|1LCjEr%b6v}aFtsLo&M4Xm3c1#k>*a2OaBk0W+bcrO)Tntp0)wmH5W#>9wrRDjE`bU-fTB z)f%*#UiYK6&QY)|Lplp+dji-l)mT{7o<47{7^9CR{@+e&7`);ip`w6uBcDfv( z2xwi8eJ0U6Xx<~5mx4EiB;T$F3DgB=xEIUP_UsB(4LYw$nYbz-aBZ8S* z+v+9}YW-^bk3&<|&G3c{=xyTFY-YCH*4I{aZx12pN)M|K6{TIzfVq@LOEuEI_di$} zffP;g-JQo!9Ot~XCB=m9JHu#ZV$aTWeGr-0wU3Jkt-P6xLAFpFj~)$}ykR)pzl^SJ zkhbWiGtY6lH(7a=pC`A@SJ#3Xp6`y)MiBSSu6gygx`+M6hK5w6r>G~TrMm+XN9zN} zuix+Q6)P@$#QsYu__&r7;g6T(*Ax|z7e~c`f;nmGN~o%6va4C~_1mGXhk0+Bvnl@l zNb9FHZp) z?$0WyEGh`nBrl;LDyXO`vokbt9+q6(-d!$s1S&5)@Pe!$ie~2UtldvNOCGsawP~R!S-&k^sIT?|TBmg2I9V z5){Trv|Saogp?D)CMc+@DF|6`VR3(qL5j)9S;C!y!5vgZCsAk=?(A$la@;&!1BZcO zJ}yB?o{hudFfG5LC7`S;E32U;zPPwOxFaYkpdh2Arar#D(A8~6TyC93NP~gE!U7b9 z$LL?7{1z;hl{r=TKPn6Q#0&B;3JP(F391WhWi%gg(+e* zQIE;R2o)Wnv6|`@|H{Y0BK{FR{-Pz9r9n+C#5yfmY0;hOi{|NXELM4rp80#-eRKXY zucRp;>h*jF_J5gc?f7^^eR(-0<(L#uw6=|+!~A^$;d6sFf#l`c1XlrkC(jXFnFOT7 zZ{pR1p(LOysi`Qfperh+q#~y#r6#7NBcq`zs;H?ctsvmxJjntUk(!K*iiDJq7^)jV zMn**Wn^n^gecYJZ3%Jd}3o)Z0^rK-3$0YrUfeZ}?@Oi`V zX$c`buq}B{sq6`6r6F$z87f{xUn2aiNd%tKvcU%OWj&XS|A)~xq*O#BB?VRZbVT|1 zblryhjsAcVU{YQP6!xdy%nAGZ^9lTfer0|#7lcyd!CC2j^oiC*O08`~R8qzd)bb)*KvbprCJWZ|?t{Vn5hMZ#N1GN&^B! z(Ak;A`XTZEbN|D`gEcuaROp~g-+$#35Ir&@FmNn=^O2DRYzC zp#}jW>uOIF51rshQX%7os8z?vCKuJf}!J2rAq&A;Z2J2;c`2|0cXh+^>w8x4@1)3_nPy zU89PKVMBX2py!=;K`?Wof5X;vflL1MctJtAr|A3}BGB3rB1f+Bk{)D{p8A1TQtApb z#$G(*Jdo~OHf2WeGDD5e66k4kz(OCRyjLE4ra(d@@_vBeROZ0=2zJPXJ_&*qHRS)q zr6go!BVuD`#>P&suDpLVpt$2fl6;XlqWbl3g&E;RXE_N2WB-y87v=Ig1E3h8J~CiN z5yjmKQ|5>Rh7ctPuxMcM#?;p{%<`9D1q;H!!V<=dm!KUJ5$x4p0iQ19f64u`L!a2+ z+`lJVBh2oRF0F;sHj~dPK0+ASBjV6R2KmMcJNJAaNUlMoQCKqQc{xNrI z|5yQA2%E0|cu&djb}kZGMhHYjsv>i5E3R>m8q#oRNZyhxYM!wh$B)^fJNc zVqDkDN<;iK54HWyrDlKomdB$7LXdCMiemX#X5v?-b@2r8vED*~1cZwV@_^sRm!) z`V>FUW~#sRtwDeh)JaKxr54CdNl`H)GjoSim|tvzij>~STPNFF$SAkx^Uavwq;CwG zvZbd*Um95GYs2zi1(`ljV84H$oh_!*?&y>j&;WO*f~#H*5AT0n=}*seBx-yKNe zHK?I82o7reZoR>w6WFlT8({^P##wR;P06)P5t3km`P@(U!@KyHApH`_FH zbiP9J_3VV{g2jqs#*Cn!`SPUil62@8o+2%>vbL8zyLp(y!^1s2J(K4Q7vqQHiDY>w zyu7^nv${Mb{sIXK8lockm`ER%^R~KAR2Fzd2z-LCbs&reyZ!b!NUg@$>5nb#Ffqa- zswCh#zVKT-5u?83QuLoOuuo0S&$0Pz9_9D6b;Ov(Obco{XX4g0A);@q3`p}nbzWW< z(zn&Wm_&v*?%Fir3KSDP>jQug`yf?*D@$v2gI8mD;hCnnm#O*1-O0*8fFKR#9}%c= z*lcWQW1CxTf;T{8Qp!C9*uV@zOuNxU(ZyIM>n9(Rc3q)#VR4hBQgv zm#`iSXa{g3RzVS#l9qOQa|7qH_Wb+|XXz{R*{uEdfEzE7TQ5=jFA+UtS(sgUM2|Mg zkuJv7wkCW)@ZrzZ)}M2@37~a2pSJq?`nI+@%@L5rMh0%SA zCJJ)%1fb|L^?}1h;@~i?UTU|>XS%3Gw+zaPvT`d+b9AkB&?1&;YNpmIe=j8^h&|<@ zUu8%=MYNIampUVUH%^8v^^@9Xw*sET%ZZ--E-x=1jl~P}k5n1q>?8a*p32lu(x>tF zyFHjgseh4HIXXf)JYuE>n$IK!yKj27-{83cbX2ojM6ioGfQlqyf~B(4j>ix{Vqf+L z6U;MVW7aDb*e;hq+#8$%L;+Z8b2x%RPt-`(0$1PT_I$Q>a7ai7k;BjPJh;wQOO02N zk5giEoUp+=qlK7NZH_7zoijJ4G@=HOR#a0(Kyo8Y$KZyc6eU&&+oGNDVq{fdheDTI zUcnH{9x~x(FElt`@+0xF#1gan~3Ib*^cKTR{ zu0N!(bi6zQzMLRfYD=Xv6KI!b5eP|CLMF_KKcwMb|6w3&6;MS6a?fGplFKPxNQpV* z&^YP@0KX03uM1~5?SX*?lglKYoJ1@!TV9`}ex=#bWXk(`LHg&VG;v~Xe7O4hRdjz^ zAljLCiPp}NW-or;$9t!Gg@=Vf-d3rC;!|JS-Ar(0-wzW!ososrdJ}j6cxj;T4gFj+ zG9o%_t(u|YhlAh*s(#Jq^$I`93E0=4^b?DqERToZ&Hn+2SNOGLuNw>~W`$_GIHU&- z))jXy)~+JbdGeM4^aft(3!j+0FQeLoha4eHC{QRVCABa=Pe?@M8@mn{L-MKrRK8_x zZQZFoP*KLzn0Uym<}M4^sQ-x!v!;srvj6rFhqi`trB1lYLJFo?xo|KjAn&DWVWs8m zA+0_Zxq6=>0EF((UyHy1^A@geWhn54?jIrMd~9O6(gYXC!Cl#<)}``MdM-HpQ-8J^ zeVP>og7=ar=-G1aKB9{ zAxvqB8R9UMf&mrgX`FDX#3Bl0Xgh9hN{pWNtJ!B~XPz(DD$2@r6YAjTskAyBO$A>d zh$eNP@u$;QP^vlo{eZfuwLN3j{V*t*c8=yb&oR;A;*+&F{Rv?p+_u(rj8w;O4<~f{ z4O}4%#E5`QoXUDx2neY6+}!0Yo>{CC*R^y2p(bvMJ}=}>)Qpvnv}xhz4@_ z;G)N>uKa(SUM+#z$LIIY2q8UO@S7plp;P-y4?w4y35Ny+4IL@N7>Fw) zmgM_!ST05Hj|r!I8c87E%R5Rqk&n@pItKBR0Mh6s61ZE2tYiBI=Sp3O4BKf*xQH0x z;eK)>2`vR<6wC1NuWr9f{l{W%o&nEu)-rqqmsZsYig>Zq4|_>oS15VRPHTwXo_(Sec+NBaip%#L@F2>q!$Nj>=~UFP^d| ziAEcAupLefC`XOs$!qw#;Pd&4Ua_AplaXoMMMZd&;MCr0A!C31q~-c|s{;id9v&Op z>+Ah#d3pJ10NMj!61p#GzdsOMe{XuxXBR+M9(DCGht}|VNM8(yq2CD*;21-h@@Y!~ z{|cN@59dH2Z<1d2K2aAVoj<(>r1B?r!AG7p&6$On85tSb4;Yu7_f^R!n17v5-d;0E ziC;ZLPk60X|MloHtTZI-aSm-Ly*%Y`gS2B^Q*z*vJHnN*)68@PPh;Y{>Bujlg8QUK zM=(Kgf|7Eco6AK)i?ns`*y5D>FBS!Xg0l^ZF0DbR*|5-5zV^?i(@>|ELq)&Hvb*?8wJs(LKVP%P()zjIlA^}cs-rc;hRz3#{3#;49wc>+Y zY~U$4)5^eXl%e9s=;q*8V%pKxNqJ0Z5QD2w_di%gU;1M}RDh}&7XX3DnVB0@SEC7I zi_gd(H$JNu@qr+fpKoht5|}mxrL)#MaGB2$m6Q=T>(d4osT>SEVi+|~&dke;%ZQwH zV$1J7WEQw8r~#`_M4fq64cm8U$p?XNaLyz_M~h9vZ*9youP%lJfSz!Z21v?aZNL6P zOhaSs>*Gbwg3lm=6Ze4jWu=?*Ovv%^NJM_EJbk<+sB*It!2rfsddcxE*LRhwqKLS~ zmn`&iaMR`fk-CNHrYmNbmsde0Xh<&8MU%H8CmXk;3etkl-KB(SP|VCG+rCLd@m}Q1 zd;gb{TsVrIuJdixkXBH+>~padx!BYlK(09&Q6Rx3u+X7V`4h`NiA?cauos&NTV{Td zsq^?38+*pnxHP}Kka%*u+>N?AQCvtR8+E7KJvS{Q;dI(Y-psJX)ckas?1cIGh7X^H ztkUXcgE55eo{xxzxT2(bV3frCBsaK(UXCEH(-GG){Q3kb6>Wcw%z3pCN~DmGYG;x@ zvaM-0$1XTmjIE~ODrH#~LF#6XX5PEqh7DM<~L`05`k9!WXprk%9faCz(=`p96vEx3~GPi5K^6mlhzJ!E?CM70U zS65$O+0#I}9xnf_z!ZIbk*IokvGTfyt2Mt!Xr>T`-ke8DX$2dQk%glhtC@LPd0$K1 z=@6#Sl`)aau>h7Ed09z#-`#tHoG&G%F)E5$d+=`$HldV=X$oY zr`fx|*w)L_hSA(oG_i$78wh;}DK#T^ThwRDh&yh*D#8wdPMCB4$kD+;gbM?KOi!lU`m>hA9AExM^T+kz}scJV4 z>KnD*q81K{2TD!7?mU`WC&C2gaM=e(<&=~-wWO2JGjN0jvm%T|6&eMRjn(p0DIJQK z%>vADp~io0s^H;YC2EbHlC{4_HoK`$N}q z2KmZ6^-BPhSK$Lt9Vk9X$k{aXBWo7L>?Hn)=KN~9i>yfx#+;AwgSC)X-$fS2b(TBN z-N?9LLBuS!%?Q~xrib6ARS9wNe$v2_Z-5|>F)N6@u4h{MitRWdq>1k$0H2R0fxZPW*$y7`tI^re9i9QBpzH`eMfg z*H@l}L)CbU$ovJ`>6maaof|BDYgL(U_^RRrYy4lMGNO$`2i2hS1>4VluqX`)z2%)n z){OOttn3sb*T9jR%f^uF^vo2^th|pY_z?9qY?LzYp?CHkuWk2X&zXOdl~)#Ke0Abt ziF~lPmn)+dBVO9Q)%wbTDFz!)H>miBzmMOJAIhz*ojNuGCzVVVfvg3Y)t?KhWRsn^Zgc>;LTdkr5xbh*zUT#Iuuu1U-sHB_G%&ifg&rW zaBQlTnB5+%Oyp_)=KuzlF{?yZ<15+K^=tAfXHg=J-yg@**a@1)zjVHgcwp4(r^E3( z^R?@rhLV5&#OnbRmpjbg-INnt+$2@!F(CgxW!x}6<6I^Sf3kfpxj=1GcT$UP~)IAlT?5 z<@D}g-6urLH4r^<`xFV!4VrBDum?_mA#s)BrZh1B@mV@KI!!;bxYy6Xe3_}hEk8hK zMhpiT-CAWo-l8H6(<}O#wNfB0Ejj7y=iIodsQ2zHmve8ZMK9%)`pAFRKXV%R<4J>C zeIf4ETZ%xIdUP;H@jkD-qLK0pr=y6Z=rWd(Gp2N+p>_g!n)PFOb&}9hD<(6Qz(tD> zvZS2|*>twHcD8ryMfazE3fnSW$f$mL9bB2aeMHSj|5f;3S^w zh*|stRM(ZXR=@+UXV?E*P7oEe>}?oheeu!hZ_UcI&1Nbh7X(t_tOIP6ra5#9KM`Ds z)%_LgeRZ1Wn?ua(QAwNB-s6ITaxlZq1vH2IQ{qR-yHd9sJ2MfM#pBy|W+*W-4c+>g zWV)^d(aijIF*yG^@0Av>zPB8a{E<-n#Rfmy}(JmihB1vU`Fw04tk>%b$PE zaMCn1w9sy!uR7~+%cuI`c!-FIcz8Dl2aa#|CUr0J<;u&)u>gFPj(OF)1Y_C4GJT^eli%F!Wr2 z1p2NL5)yz)*igX(5igxU^WQy&O3%5`wTE)kGBPvrRJqt+SXfvmcTN-X1(-LiCY|7G zZx|;g&rq1Wgws)NRQBN--FcHU%|qE+!vqfno(}e1)2jNNEmoAti`RKguCY~bgLS7T zasl&FnxY-^G>gu)Vr+`$MJ(NKHO{?5J8U@JxXH-~H&-r-VcwB3V$|;8ygaH%IEm`I zN=IfSlLSVAMKgS}`>8E5z!Io&=?#}%xNpqw19hG6fUrkM{SxUCbM;5ng^%O1Ry8z| z&*R35D-_!{4lWEs!L59(01skD2iH$jbiOBrrTVK~Zg=|;&j*l0Jr!e-HMYF|`SJa5 zuo5p z7<}bIfUZE$Tf1o0SN=JwR;p+4tx?+?*o6InvXD3K8GHjEyK7Y@yB4ZxtJ7pB{9>jc z#{=qSv%;Om*Tr_j01MA9s2Gr2KaIW!$sxr1v)!Kt0)k#Iw5^_I)kDD3}Fbx}PiTH2W8MdsTaBT@RAF zhEnX*!Qvme1SzOL`-Vp88KaVQP_uF0-#&Gppj@bFc+iq93uO=V+t{&~&S>%BnUA8?;S+-6FMQn#n6=h`*{}`2JJ1;Hi zf@m%WE}tV=CNs;L&g<>%+@CezLkp+Q8;V9Lxd`$Hrot(W>(Qp7Bjm%QN4z1G0uM&G zN=v;D^D8~{@;ml2KY0ZuH8nPN>j(B~`wW8R#T;WTB^VeO=PMzXdX_YkckR#QMp`+` z{t^-E?#gBz;Xz`%nb@UG4x=b}6(tqcKa*!g3#pleI?k|qRw6Slq-|%|9g2MKh!e2K za5JLjKZ}dV=ok%+jT$CZg`J%r?@t$0>#>7Kb~^2BI58L)=$Pjhc#d6K!C6HyE1em5 z?WwCAd~#M(UQS~JEWNRUm^JNYX4F)*LGnpz487Xxfnq7Wb&TC{>wYB(ckJAdeDn8< zTaps8x&pWc7bvWLWC+__s0__J3k!~JZfPp*&PBz={?4!$7<}R%49yh0sGOAdP!SG{ zlB#HU%~6RVl7rMTbjB_T@+byT@A@YvcW1mYp*R5@3{4dG;vKz>H4zap`NuglTFrk^ zq^G5wO+GL!Gha)dr*^q=x;4x`L0l|j)-iwjt`&vxEE+D$JKrdFS{TlW>qkGTl7;k9 zEQ&rWqH6*Q5&{}xwDg}LazsU!KD6l*Qj(P#I~2B;GtV7mRb&D4i^vOYpQuYyxi!7- z>W(U=oyN}yr)3j08v|p`D93);Y0aG)3}T~B2Rgh3(-=)x!U)nbWO~Pey>Jj^syT$+R3LWXh%8adash|eyiJw>|o=NvU${*zBW ziH~%ECGe4ZFI#?-ap5i{yN>;0GsbDT;w=0`dmpea+I|dXsBm%oE|u4GKOHD?!qs8D zE;m3};N4fZFH;~7;6s4dMO%aGDZF$jajpa6p9!4r%IHb>?^a+*K#``_*4WtC!2OYt zkv{3NvNCc$zTT3OW2KAFOyCUQ=K(I)>zq!zy{zmh3b0a}>8#e)Ub|^lR#saVAAdoD zK=xTGo;)#a(lBGFL4Uw*;o`Xdx^cIbG$&Kz>D^ghpQxfi!VlH&hpGVV-Ut;0Tn{l(HFEaO6Yzr$0mjBqZwq3cWGGB5=txX|DYTue zaDftq$vBWd1x+#9Lm~tpD_tB9nU>%4eOv$!3|SsI2cw^4e00ysKi(_+(VtU?K=qB% z2dBBSrZx|e@}WZo)&-O8Jv;8KTICA#eCF@(Us6I!UkGBWdb$Gf`0Fot0oZX>Ge%Ys z^1IES1n#+jl(`59{NJ>XFeN1=`4{-5H0Y7KTm+__X-8a0sdPh(U@Dt`(7G1Tz>Zhw zrPJUj2XkS+vew}MF8otcQi_U-hK7W1T|sw2e|H2i!9uIr@6H1I%jE#vne?%r=B*^g z>E;r9dOy-DF{(rAbE?y~3e*8@!!hZan2H^_)BcOs)W@^~uUMY%4c|{X#qy)%Hn9`B&-Sdv1!r z#Wzc?raw#zOtZmfmmc6UZ$+=st)nF$0JL{h?Oqq?v2+H?4NfR-8oc$UKr5I$hCGSt z(ehn+sr3o~qgY``=XwSv7G}nV=ZO7mr@Q*bHlR7XId3DLs_WtnfV|eDxtf%ak<nv>kX&Ta5jB*y9*q2(BBJQ1(P z*tWqdRu2{^YN%OOJ~+VEkB-F~9iRu;J&_jFez)AmZ|O8&3|3#?hee;w=t@No24qth z5AlKh?+`7b1s0D7ukEK7wRN30B-iNcMKU9%9t$UP#M>+(4A?Q#gX|S}Wz%ov?zbrT zyIwBnX?ij?HZ%`|fmJ-0Q~=U3VxtVjHb(lNFtvTc%7#P+fi?#)mll19R%B3GBOBne zRa*#P$A5qEJB|kF(O3@PH{&r3@A=u6S)`Wd=F^?-j z=D&Y6_~|8da2@W!9dLbTW8(wm7bBpdC-Gp!KhkppjX=Bh8_j)BAZiMLmli{9&&3kS zH0UJ0sHvyq6v#@^_SlNPeE!=Oa!ds{@3XkEefDwD+-m{gNI?H`nW(K0DlaigpL>|` zrdPNW*{Hm{Xj>bIIg%qMw)_7MHvn$tD=v9iOzeuBO9taj$81%)%0YoAXMV>z z@0CA2@sp2BghxR}PU3VsHuWL9u5JW276~gTyB&_AEpc^W7W0d~`rDB@lJ1kX1N>Wr z(!aoivCFH+gaZZ!ekgt=ztYpxG>lQA@`J!9ag^2@oS%14c-YN;jo=Dj!eu}~Bl-u& zGojL+?D6c5(Qxs+`MOjL3Qa}n{T@G!%gWmF*X8#1;p*+gxBd$*)IgN0rMIN6tRa#c zoNyAlDHSD!`8as(Cp=na=vY?QM}aJXIg~2-=OXuq#0E1%PhERUHplE(w3JTng*6EU z6?M6(Fa;fOVW>Xke12dcAYfqr83Bq2`nYxPYaQ;H?GnTkn&lI`F&}c0{kc20Kj?Rz z-Y&h8o_oFC8mg+O85tR$Q4|yuaBy%Y8N6W3_&B@Hhay7ah1Yb$&1Z7zcR|S|G^-4nTcb z_k1uB1w~(Z+E$OD5;p3m(an4`*KK*o)aX!npv!bbw}jSrb>q zg#727ULC(dfCxA^IDV`73=9mkw6t_|e|>yR+P}aS&p4K->KSqCp>!okx64a`7Gyz+ zvb_>AHL(THl17%j**Ko#P*BW!zj<4JHuvHK2#Kt+ReBAKK0dO$p5NOVe}eqTI~+;Ctz8b=SXj z_j8n;_>%t{^A zme4kAnnUCx)C}fL>rmTyY@2z!zw`YpPzRWBQEH#!ICn-O#d6^3P~YLr)Zmz3uDV3A zF6;O6@*VRp)|t$;p}IDIPg{O^3LteHCnb7$_U&yDr= zVrnqRuT%~7Uk5I{%Jm7Ep?#J=%CfE0 zIwod-+7CTFy)>`DhXu2ys;a87v9Y`R+rR)2l@rddqFUlIc*+Ksl<4FyU5%>VjHuQd zRk|2au8mH(#2orcVfYM0KsD{8eaQKKhc?Y=ptV-Y8U7h9MenDx=M@88{r*HcN#XlZ zde`28_NIS0|Ea5|*rwCB23yx7f5^4YjN+Mf@@OGr!@^Q?qG>n|=D^zURp+fNT}U0U zE?!;z_9#XjpZ)%EDNipZ8g%o~-zfIVoSXzYj(qUB`fG6kJ%i&_`5cNCC5oC~7%`_H zVuS#ii(ii*a+)?Dero7sOaSGO8Wma_`4CA{V8>lyo|J6BOWEN>SaF+pglFz6uWT!! zzB>uto-R<*hu=?}Q_E}(?e926x96+&z4pTaY4(b7^58#AK~Oy%HQjPaGVpB>-tQB)tm7~jt) zxt&P8U*{6#C=cA8RSB{Xnup_S@S*#=YyYo&(3+c1`m-3SQ2|s)&d|z-=n{9--#^p1 znn-&%tcV)i&xh_oB?*MBVFfipi^Gw!j2>)WOrwN+CeOF9SmET@kYQsFZi={BkrC9G za57_y!r0snounm~3ngg3yGD>LR9(Gn`{uH`dvp@ykPrtm?u6(bpt@--{ zrkr$B(=CMa^aN^f#esUtixeEFfEAi>Ml$K=_hhs?#SS`1n(jF>tM*xW#M*u1ZR`XW zcw)GsP){w6Y%j*c@0}ny!_XAUK64TtLU;XtES*(U99`F~g9V4+4#C~s3GPlHxVr@R zCb+x1y9Iam;O-8MyVJ<&_y11c_2`QlU1RTEYpprwQ=;%LUUs7@ylv!o)iVk{7|1e5 z$VD$NFdQ*@j07S2ld8dRr!?5s{3-YyPg9^ZKGwXqUe~Say6twn6V)^F;W&9BuT*4 z*wzE$IA7|5-Pg&Eucf&{|L~(}aKlY0ODQ!IjU$we+Q2UIqUX7~zZ<*PkS>sL4B{b& z`32)L%30dhx?{(YkS;!)NfhN7-!yozb;1Q4YMP{8+@v3jB?T!3nvTPY=YM^c&?vh= ztjPKs|MX8I|2~Zav+t;(4EJ|1B0NkZm3YZU_-kOF8r2c71a2jK`Tn%(ZG^r+=yWQ?FY&h@tE_1F9&9L~% zIP7skf*l?tXSJ*$OI_g<$LJDri-xx6pSlF24eITGnaeEEQx-7G&>@f&gV-D{|x zBXcQRaI)NzsKb@Ag1Z?BCnb*b{jOv)AtfY5vDDZ49ghnFWr^+nj9^rldL8`D#yI z2X$XyTrI>Gwa+?-a(uibh6UtDUj`dqJyTg|_Q>^RvzlS3@K)DM+2>JxJ<9PajUG-Z z5KE{aJm2JqRw~2GZf?)O$`bB&x-{x~#277#$qMUmH)xDC)btCxTP&5{erDiCnSM5= z#*{T2_Qeu4eZlKp0~ZzzA;=4WV@GcvcDt$|uAlPY6xGz8R^OFH{j$uPfvv3{aM{(a zci`#*^t6l7M1rLzwCg*52^Dd*lb>#1@t!0^7s1XyI$!JwU}C5#pddVM-o8U5jtqpSd)9XVUc*O}*UvX- z!BtFa)IQggIrY@dg~<^sJVI^G@4qu2j~2fs$#GB(6t5AL(AVk-c2zTfuG)AjpHRE8 zN)(!O5_UXQcnUETKnr#@++7L(rpsNLQ{T83?6^!02%CckMu(m?lE`IeGTn2m)JxE} zz)F#_y&?qmp-GDqwzqT@w>4n|lO}}61?|h23gEBKu5E10Epc-M41d|B7A0j=P?)sy z9WaSPA~n1S_4oe;!rU>$L&-9?! z--}d<>b-fcuPM|f6OQ101)^b$gQ_(=TOxU(lOIVE(091tVrz4e5L)Y85o=!(cb^y3 zS=|73u_cXPWmPu^hYDYX5&6DiBIPV#fb@?$-BEapt9~fNNga!O`FKXA(DcmA2Bp!> z&By%_>=OV4E{_{P0>14<3S(^PRI}C1KCct=K}(NpAmukj|3kz6UUk3!9Rs~uPq8tba-i)8ND|yMB{NIQ z@{fK{{JoEPTsPH_}wvtmGTW{mo{Ywg)n) ztL@e8SM113P^;5MB#$)6wT1)sb?v=X^HCICs4XHRDV=uu24hckYCqI{#l0*G5pUdf zIE!6vo5}UWXi9ux#9BCqOJbti=H|}6ydxY7IhfhSvzazK`nzJRAP>cBLm6+GkH)Rt zB~d4Fy2)r2qOd)%Gi8=*V}5Rf7b(Wb{0Xe6gZKN_l1J42-!`x?Ea=fOF#$KmxL<*q zf#PJ~89WFC5`N7RW~)GYVmM|U5&j?ru+bIa;^-kA_;IxVos<>xNNjB|5TY$N-U-70 zoF;oT+;m_fpD_7`uOWdDj&!ujXzJ2KVA;bn^C7ngpNt`Y@%d}!MCM0rGT$eaOp8=- zqRbHIzW{-L>iKs?02)tZN>+ZUoHGLu%2$b|Ig)n5 z^}46)_fAI(#HLBeqj#qp$HSGsT1)N10&@-{N`zi5nX35Ifl!whAfwcDceR}Xoep=J zT;CX32SR?Eie|kv1z1>Y{xtf%5v>VxasAZO+k7py zw1Ij=__jc(y4a5Q{6roVGq^kdw!}^STRPrJH6_+Qt8}5Ps$nYFt12i zD*N{`wo;OxMD@e%N+uUl_RsVKluok~EzvS3+uKbhNswLrUL|~sUaZ|}qn_6KPd$lK zKR-;qS04@`%J|gu&WvvcD?SqJ?jCZ!c7B+JjeJ>44xX;3A9g8Iv9tW+~2bJw671>J3!zU-+^ zT5caQSIDLS`B;P8&BB0?Kzi@7?f-W57b{`ncg2g^^74~sG8b33M>ltfvn&6qQUWiu z6Xv|qmfG5uNU&2rThI6XJ&NqRl!LnkKiHHjIlH#Jp}_t{fXZVfMQ%9ssi7fRlp@%`{kW!~iVY=HKnVrjcC+9YbZ{y47E?r3Pq z3S29c8!nKQBoTlU*uy1?6C~CVx&-ko++XuT$(`xxG)Lx6$1n|mqZi&@y7L?YHRdjB z6TA!jz6@-IKqPkF`@!#g9Ci0mlf0aP`_{u2F&;(2lM*ACZtdP4#mgb+SD@=#414Azja6KG9l=@-|q3i2#Si zk39n5`FgU!!7?}Z;^G1)vdM6RedcGU4)BMpf|^wl#MRGWcIL3gAE*jUZoKOo!&3=x zPre<`f~sF>O&E(cqQ%Ie^0~+|c^eT%XfOpD??e9!#h4?|0s;`q`lUhNfJ;e{yZ$8n8v`Q3jEUNu*W_bST9z;(5nMMltj?>mNKcJ@^3Zy7E|=E@r5*Phi*$vXQJ*!Fb&K;c)~Q!C<|7=oT?@G_1N zM!#TtCRE76SC{`UcvR)@IOTWVqWk3T?n(yhm0Oaey`jWQl0<%$T=tvtBgs$OPR-r@ z>3b2rp56trMtQsviSYfy&5bvHj@Il36xEm7h3uO)bQY!K^OLJ;M|JGDMz~{Q!Y`}! z&Fr37l^rd$O%&=@%*$g^$zl&Gy^b5DmZq&wdd@Iu(~!rn1{LqQvyxwFiXG5j3Xtu2*>ZRKb)3o8q&vHfUc;^$iKI%;apu;>bg z0{gHMXJ;3uwhl56EoR${kALymgGo+o!LE5r+Y9{Oo$x45Vd(!IkcL}lp}N9kfvm@f zmcm-=%bd-o*vkU449$oWLU$ZbGljaL3UZ=Hh@>vX3b%MC)WJ5utJ>F@MxwaDcy;#jMPq5S5vOwsy zeTK?D_PWCVBj(@Rb3?`X_KkI@<^ySmb*`s2y^PHGs8yTL6bZ4to96zD5qoN9Ra8*I zZZ!_frf*l5udjjx>thL>>YOTEqH~=Ykzg{~Kf=yZyfsupYQu|d4UdxHj>t*B{qAxds$&)n2+SQZOF=cFHD!_Nt#7V@ zAUp^U4;KOX2Vy~kM~oweW-4`Ghuc57=RR_3rq+hBVOpf&TP$Usv{YI!t)}JMDp%(; zZ}kGyMs&Uccwt}lU(5mt87*DE)Z?&x2aP;hLK4^iLDN{17Vr3C>H1X`e; z?^nwJ7FN5fpCBBw{RoxiB)*&La2>we)zOQSK z{5DqvIIHdJNNsMbgF5(a2((Rg^?zqa`rra`muO^dHl%D0@;EO@mo9o2&imATwhg?? zVPCv9V~wjo{0MKJ-S4aCUQ5T%B94t$j(X+3x{yCL3%$M)=q14v#X#T3L^WayC2ukt zk}R#@T0G6i3frvf-nJh2jBVbzDT^AJm(k&Trsu8gzDh&GZl6e*(NI*q6O4~o`q>HB z*@yk)7JuKztG4&B4z%;qgZsa`ZTmppFdJ?a{ov}*HG9;u@KM7w`~cX-lo>fr;?WU> z0eQUWs|UkX$l5om;%m?aF`!+R`z-|yvei5}>!H-1UtN{`i)~R`eJ6@F*OGAe14r<@ zuM7hBygAuAv^O-MDe%^|RliX*#9sMmi5dL*bG>BOPVDGA5GY7gO{6Dyakz`H zzRE~~iOeNVe_<%>L+_2-cDwLpBIKI%Vk7{rY}RoC8YQ}~|9^x=dSs+hX$o|t9>YIo z$W4{cj7=mni>tr37cz8bR?@D5{#i(2T@ukH5YVVzFmu6FY%gX(?cJjwb5m{LfIxod z2g#~Qsptp5omB37nKE2a6iv#lg`Y_(i^>?ljatWBz@129;0A<|+NVBd1*Ncv3+%{A z>0(;^R2h9JkNee5VnQmqhSQ_W@kMo8QTq{feqs4gv1a3w-Cm0{%^BezlACR5@J1i$ z1B|Z7{C}cI^4Acx`)3|p?Hmo$w-K+e_G>8W-36tedoXs0i5B>x6$QqXtP?q$poJ{>E2 zbMrzWIefOREtyded=7OH!N@TC_;&jGK&l~Dw1d1d|IG#DjwCI*H>#IFNjWO4cWi%! zzQcRQy?_O+>pZF8f{ZNyN8Z3T$l%XO(UtR*1ydmP>yEeb)bvS%G znBQES-9+RS0et^vzW=A`^9cq#DB8aKu;KOng64?0o+Swx5B;I`2gxT0aLiI6UzkcU> zdk3UV4}p5NQQf$}Ck0*aF%&i#4Q2$&f5OifIX@Pt@894I(Z3AKBLqY0AwBbmRHUV) zEuK}P+I+Gg40y;q6Z}~rCnpDcVyk5Pdf)g$LPET}y}8vv;Oubx%PXh_f-STZn*<(L z_RnJ=CEVEv_#dx&fL$BuVE5Pi6`$NI)3wK2hPq)VDDSawyZsVe6av{HgAV4KNaVh& zm0El+p)Q9ebb}mN`%4_>g2}tGEG+Qx$fNaJy!xXbdBWSH<&pU@xztpnkprug5)1in zzYst3%^@x8;U-T?s-i)!+i+;9n-W9)8~udQopGTYA1%Wbf12bHv{1w;={(NJ86=5> zn_=oNf;=Eaaf(aL^Y%1h2_u(46Ku=iZBJnQzalB4AvKp*Err{{8PPdNdcwv^GQsYG zra~IZ@~X3FK4!*=xUq$o)T`>z5%=-ZKnLcCFna3AhEA3q_#R2nj{~J8z+X>aydG5$ z4i1p|D}QM@Man0)v6WE<3+s;@-?7_)H#hKz(1hwY1-emD105?F2L%NOQ}tixu%^NQ zOC;PIE&Kih4yLVnd99&x6d4MCt9}G!3PNK3EIjOMfkJqtKPBHLTxR@O9QL!c+pKo-MF&hW{P zJKe$DTb>$SGEe6V!{eF&(%Q}Ab*q1)&gD=nSVMGTOGL*|W4q0Sg|DhUOQQkM{4360 zdGIe6?Q>PLAJh=Y)(3#Tara~Jjv(Y($0%c~qsWi*l9FHCn`e*668{UsE57fHc;yo6 z)&W2?35~Q;W`X*GV1O5J}d_Gsg{>7Ak((ukGEQ0@pB&S+ zI4&F-eZ@mNL+;Rcc;Or=4Q~gI0zX=`x9dotpCrTGO1S1N=1Z>jFc0OZy!Ik#D%NYd z=P#G-Ftwq4_mo3e`9&eD^+NO}eNf#Z?2Cjh2DR3QJ4=eYLEQRxSg}%#X9TCS;`@ev zyh#U3ZHx=q(Y;y~zu2_rh1?#YS=0{GMySY9jH}RoCgC2k&D{H*yFW(ZI{LyV0jUS4l z>R`vOE*OT|-TAahe}A~d(m~|+iQ4@6mg{#J2WMMcAFw?#j$@&*y0S8b6FBhAdsDQBP)&aH;;1L_jjpulE;ugNAU3^Oy|BQ!IGNqhadg6d zG2+>Lv8OqwsyW;ASb>{k4rJ9Qa9>>k72$+19DEltQnk8PgLgqn*&HX zqr5^`#Wcqyu-wCP<`f#^W7NRgf*xlQt-l2>X?nb*#k7Zn#Eb3BFl7J4A^Uib4RFdh zr3>5F>{n5naI3YKU{t=^(*eF&bNA+{0ghOD)-+Nc#V+=E&vkk_7i=b5BE>{?l*BY9 z7lfLS`6flqM!P+B?V+@azG?r6rLC-Jh)4r)o_2TWB=F~{+_@&!O6B9~h1)1PvcQ^^ zY3oOeGS8-lGgbnK@G%3sqZm*dmef?2XEk@X8`Opo;VE@J#$)@x=w*6LiR)?TiAfCX z{EKA!8?KD+avSE%4xdr~-T9JG*xP1@eM0P`6}%u(J2^Qy4TFd7yF-KVv_JH+a|DEU zh8vF#Hr2s!#&*D&zK6$iKV+i;xbgb4f$LaGa&if=_BM%P4*=9C_<zAKncQ@5ez&qL}eKE4sh5;tZ6vmZC!>)2%iPWmHsP zLnQrp7w47L)i=4N{P2z{KB=2O-RPj8CgboxpLOpSz0pN){q;W)T>Nbz7FE>Za&ryT zS7QU6{;Vp4vkQ*ubT#*Fn~#%O)b_#4Zn0BL-C3F0_~qeqds|GdqmZ>ZF0|s@M&|*dG@#n zzbmp(!Xw?-vDWGR+O4duDyZVFM&8{}6ZfGAJw9GE;m7G^#^R~59vyLC15D7jd>H!4afDjsa|v8D1$&FFF;dbF>?&`k8DC$-oL&1$bUa-8 zBj}u+?)X{cT&(ZV?A?YE0ViXmDGB^RF#=!6$88NV!W&1ewhvAVjspuemijcv5B>Li z&Kh%9vn-DxMF!FEtmgBQivb0R|EK^s8|Q;i^g<|`axhp!Coh~qsV=IEYP*btrB@@= zp?axXO^0!Qcwqu*E@m3^6j0i~v7V~IYFzqkO&BSkZ^;AP2p1apQ|n-vTuA}{VC<5r z{@lMV-WGCI$>Rp(A3nn8EjNm?C^rdfbuV##w9dSP^4;A!A2*4L!{2@FDdt^@$H;Vl z`Y$fbI(QPa%V|{%=*r&fKh&{}f+(mG<;8cBEuF z+CQX>Q~}Gz>nK46^4iCn&OROPxt_BfJcP9E-lbBkF2#<|KigbC&yn+3o( zbUeKDl$52#MNaOg?nqS;5aOj(Ds0Ya^+ZMF(#I zWe3!Czxr*)Kp^yc+ZJRdSa%N}&CFviBw)gadxx1oTv_3|vF@?_9ze%4c4Yzm_x(vp zmUaklY2&l+-X5*FOeBGCZsU&*=ogW1{bB+v1wX5-fvh99Px1TcJbFjk&F40DVaiF{ zV-bOX@CP;dj)Mi+8SaDss)&#Ri1dLvjw+-cQZVXULcg(UC^O81QC<2I5;x*6%sgP9 zy=0++qKoPAZ}=?46X>(PRZpk-OtjP}XBy0Qv06C1fXGu!!S{8fsMWV%Dw54jY}s-k;I;wV~jeku1<4 z)EX|kyGzd27E#VB`9X+gFc% zy3^-1YA`*Pp$!=PM#{+idvFfFllM_h=px`Yv&NTdEI)mTTR0Bg((tp2n-gYN3D6UbQcyAv`(9xA{}`)56}3L*?4EU;Xb})g>gwChK}}|6DqIrlO`%m zUCR=L_d~1;N$GEPn+3_UJu7Iwd%3llot`bTUC@4Kn{(8e`i$!`$N+~AzK&Wm*ToTNhDidSlUSl5*4-dzi3+_~= zE?rx>o>Wf>q1PTbTb-UymwMMviyEINBJW+cpKWK_Om`_F z{ZMi!T+Kb(mLleQv*sosCGy&t6LNsh)Up}WV=x;ng2u9?y`rLezs7Xs{$A&;me`=FB^F8HlUnrbWJG@aos zwk@!)qh|?l12fcAc#vF3Y+m@RelcQ5bzL-;Ixd$OG@Ee%a?;gl?CKBP)Nr%n;ZRAj zD5F4dMPE-ZA7T7WRc2+LA(}~AZRuB1%G%OtLtyUZ=-B;MLmWEOw-!z;Wk$*vTQzn< zO9mk=Yz9tBgayj_|C(NJ^kaKYsyePKjZ*VdcQCQS8twuxk05fsP&%Z_PcL{~qKOoV z(8-rhbLL`hTI0+sTEfNeEXkb0{5Y;G3CQ4P^S2@E(@?+u4Qu}l+=bG?it!RgxxWKX zWAT42{3xDw&rRB`LkeJ;%tzeJL&AGHRjv%Acq|`j?kQqc;-nO8oJsl?$LXUVqn~5T zhJ)!Efd}IlQg43?pRT!gvKZ_7(XF{Pd9-RGeD%kI6b~8vo&uo)NLWP2nFoN8P@z0U zn9!sx3XJMfs?G9y44v?87C~Am^ZfAKTNa1uGi8*n_20;(iZ858*@N~piW#Btf8swU z*gl5y-z&Az^a3fcHu)IxJVPP%uDEe#T6s~R-Rtgxkf!7FuxTh={0h=+AWe|6?D&{k zA4Gj%>qwJ|-U?5)`!?mYV2cg0hCj@8cqEa4rg0E%Na*W0H+CT$7z*ZLq&rU~B* z@DDOtufetpzESk_udWT#*ufW<**`;{*6sGVB{TTcYWDb?*0go(H`|ecabW-V4d z)GGbOG&mFUk;6N)e|3e4rN_ECHT;+==+iIy1`Bw-)Dgleb>zD#SVbG=g2LedQ^oyLjAQS&{G0Jf0__miQcO9=}X}{2VGqkJ1#A;_3OM?=VL` zOIlFXJ23m01Q+5xpFT4~J$MR%)9Q8{xn=KKgxH(QDw>NkyfLMddzt44Tvse@saS4~ z%WnCZ<#s%T_?#hB$@CFqL`{$k677Hu^a-7z8TqN!~25 z36a#LzDtX|Pwe%JR8TK-`Tuo0HPy?bDdht5zq(KmEcHVhNieR+`W@D|kV`BxGJ~sZ ze$V{#c0|F)2peh%YC|g@m`NYPQ*WNj$u8L{UXbAH9*lJ;m36t>*n`~9&psih9&-?n zft@w?W(XE1#9I?ibIjJ9sfrRO8Nb`;R$$1>V69-OVOPWy+F8v{i_(QW18fmRIKG36 zmX``(Cz3D&rO|U-bEm*~=T^@H!Tg_!m&2hGUYZwqhp3H`&!*@z3a+3qXDjw#-o?#7 z+r1VE-ARC7@1@JtfA(xqv`^93gRo46A6T zwH6JQ`pDs98X_=Zi`ZK)=tB_fGCyqD-ejzxeIMVK&|KnZ6W%mAnl1noo8*m~o12$@ zWlw&p)2VrN?O%s0q-=4s!{{~$gM_EMOuNG9;;HLQ+s(f*cTTAbtX_X5$$W)A}gI;BAA5lE1%xJbCt{y1+$BqRoS z?A*$rz6g?0KOY|-S69w!wt;O4cLzWHA7GMw-=;UJuAUw^yua;M+k1~O%=_tm7`bz8 zBiB9r!bq@AH6SVfnLPmNZQnl7*3!_>@N@)N&0j+j?SF4SR9YXz$V(_Co2qN5dp}0g z)64ZDX~iTyKL1nZytI$xIF_m_0HKdcf>>70Rb zp^e1rdV9{24j2UM*!v=T79Qf*KwqDXN0S@%el4T0z^vAyh?3^|qAx8h{rt6=0T++_ z<-Ofcf3gx1hQs+KhE85#TNMTDv$FGN%w^!G);c7n+*M2N?6quP$GHRQBkDy7J0u#R zB4N$V%Zfir+nVjMl2e7j37)*OzT!p*yeYgGDuMMqgZ-Y3t zQuJkc&oZW82;gq{+O0)$`h9qyxU8J1cfkAE{;SqAdL+s3E7h35B-;svRIxF3tk#*? zqqZk&jksfGsmg4Z=O;vIYn#e5oh?FN-o)bqCd0kJP#0L1?dN`(s8BI&F#`?LC)5oo zdPyMYuEwhDl$fuKc7ocGv)j(GV)gjT(<+>$?|SZD-P4!*?5;|3wz~)-uf?pxL5w{=&x1fQvdaA|U9r*?_eZP6gzNCdGA>ISwE&C;c>{3`zM96pFwJd9BAs*k zPS>M!oUT?UzxWI9Z1Pj|jV2fcgQm!(i|-BY1gV|zHRw+e_Vn9?_{U{rGb(iDG_Uf> z+XNDpTiFFY@=hv;ewr=6iD<Ozf z2?C%Zq(Yr^B?6}87d-G1Y*7#=?+kcN_BrMKT!sP;TM4JxfWZ}D^ZTDsIk~7rp{uXz zo9pZAU?v(-)f2M;3L;`=md{yR-pNS2H+ZDcy*Wnz-D9WY^Tp5BZ_}Ns2!b#odltw2 zlX+dZ*?DYi^xr6H%@Jf@E|2eygYD-|On_qYq{XHxxS~Pi?!V5%*V=E80b#{|l|^!Y z3%~H=MuhwQv7Ni}(Kv!FV_=Wa_|8wTZUDo8FkG5AE&Zn+urkhE?V9guO!HPz-r87E zQ-5u+y3(8ujixn%H6eK;vxdsca(w%iByy#bLrk2b=@3eV)7;p+--i-O%%B*Jgn|+y z&3Hy|UOPHoZAC)51D?CqwB$2%rX>JL+0w%X_TX1`Z>w74 zc6JW>hqq$dC+;CVHb0q`tUu8?dquT&2anjW?iUpeHoY4VT45nSgBW=)G`KPM-VP=PEKlq2fvBqMA$(@gdr`4f8+VitaZ` zAj%SufRbzD==pPV_@Vif4`g^6n)4B6Szd$4&5O;^6RZc9uJr%3%V(t7Hs_VKXTK)7 zl$6#L)bNbSCY)`^cBJ4?c@a3zC+=aON8*R({p&iV=_fosVcqf269*l$)m@f7d$*gJ zW~2{QP{pdIW%IB8{3?n*FSkY$#bW~?`pT}S(H4GlLz@m`Hy{qAX+4#)%GK8IM{ZVM zdJ3dSeu{NM&W&H|aPnezyU(3arN+*px5~PmfU3 zlwKKpfzCxYG@b=O!eK< zy!80};n>y}SPb64#Nh8(`H!zMf+{}%@Oq)IH?#6R7@|Iqq6K?vOZvrurXIuXvpxxr zfn6kn!j{(dJ~M-u{ez<-PkD7{a1`<7jkLhb4;n+DTy|E`H%CMJh(7smqYJe7u3j;i z?mt{JciI&9Zs+z0qamx$^Cx*A?GU_VzDxh1PADz0yngs_uag8>)JcbL2Bfm%rIv9= zT^>8HuX5I_5cn~~6w6+$`0?IBIlw&YeorIcV0A=@g z$H>t13a7pANwfKE+;trG$4?5_Agp*z#xJnrdrZ7M8_{%B4UmQatRC+RivZDlV`Jll z#KdjKeiC5p5c3RRM-R$oz#Br&hs@R5J|twIzw*^!^!4mNuNT2&?JU5&VsTp*1`6m< z_zq^v8a{l+J3s}!v>f4B3Qst|%zSKYY|N@0e|Um5CuS&~<3AoySg_;f6zDRAv!f)i zVentU6rPpc-Q8_{uygq*6j*bDW6AjA>IY{1aDqchIQbP7bZl(sVcg1x0RaIA2L}_e zRP^+SaDHI>=qbeGz*?+mKG;9HY6%vZh#&wZ`T6;L|6NPM&d$!phW=}yk+qwzuVC7@ zFT9_)A`>w&C~?0ZzWtjx@?G1WUx)nw$DbevL;g?8`A_c>Aoj{b2jg$$`UPHldEhsS zl>9~hbld!spMv%f&U?2+%J_RZ3H;6l_HyK+{huGpup5_T2>|)EdkeK;w|DIm6wr42 z2dtJQu*3=he{nBGeC&U@S&pg!TU~sxz`yfDzR8127;reVN-qAtyQrk2L+~~57w@YU z&Yf_~e__L*8sh&XwPScBpD7aaLjR^ucj$Easp)AYIl0P!|CBiOpFi2I?qDOI!O=f( zf)E@RTJn7(`QhZ`WN*)eAFYok;lB^HhPr(Qdj|tn|Ju=|UFILOcSD+|(}$APPdK>wHiw~VLP-J9py!|ZMrmdY2i z|5D3o?w#MlgPwXaNdnV*F~%@&JG#drVetF~w7R#yF`zWUaR6-q+t*UopO_`J-ByOL zcRrt9={$3@tbarwnp*DbyQ@1OCcg6%fM#oZsJl6MXLXlDjC_2rkg=(~Gw@$$*#A?# zs8N!!7Y$2JAh3P=j`OyB4YdgESjY%+adT-7>_A?f7mgT~?^OG6#KdPh z%P*X*bti0WoT4neX4-ZWgYER00aG&N zdU!tX(YeJrZ>1?2|4uVP1Mk|0L)S84({epN;eb*OnKZemqbS{mrarWxSkG<02>)@V zs=?FvzQYL1+Lc8d_YFQa8PMoaapb6r>ne)Wy2Q|Ii`@92mY#k@7-Kn#3Cj}5&Z%Vjg%vS zckdrCU${Cd{lDc_3>NG5!;5Y%*`^2n!9M;*K=^$({!2Xd;oI2Ek$dS8HZ~57$y|ae`}$;X6&Zt7X2CJSwo@;gidac_bGaG7vSqQSn0k>eq=@griEW?ZH84= zIgm&^dEwC$KKkuf-d*`G5tB{PzEs%>%*e|w76)Oywpk(Ywkb^%WISv0re@|wo~uXL z>X*J_B!>uy+MjTwd=f<+ZXF&ijQ7oyA8x&6@zK@_{X)nfcN1Bt{eT)1PJdZ4Q6&UI zATwNjZ3v=WJi>BPBs6(3;!1k}BQ6KQh{mX>sMXb92*ILMi8irwEihyLCheWIEfKe{^y22`D;zHQ1GRBb@V1`c#AN?B zd50AkP`UOlumS)+Hca%vlZErl#$f>#U#cdp2vRd+)#i-t+p?PKT;b%)MH9oI$--II z@b)jhMzkJaEQY5Kx>C@-za{=HS$w&Bgy1D=q?MIYnK*Rj;<8|tz;uhVT*x2pA6d>8 zIh@{xvmqL8HWhUKdcnW{Do`0He;j+;wM(QQKxKQr82M!LIiWQ_Pr#&DlR9k~ewBEG z>*XqoYw)3dKBD(py0Otkta*>RIfu1E={N(vyZnX8lIf#}9apF4;0MJcLxX2Z@*Za~ z_dWCiGscPB^aRBd0)d{3lT#O#daM`L4P`mco{+Q;Ba2xO>!MasUcDGDUb~0H5$4e# zjJ}go``dS~KmF~H{&tgHumMb4qn5)gV#kpf?nuv^dWodjxe^x8n_uws`O14T^{DGG zs-{aTFo^m1c>~x^RS?G$8Kqtx!%kKL(Cq~jNPIbae)TqoZaO-;H~}&iU(u6Pj~ORy z(jxQc>E44pAJo7+LQ9mMHOdJ#-$thSqYV1dhuh7a;aT1#VCq2v4T5`hM&( zi~lkvMv*CYzcOuGfT-M8hmJ2h%}*gsiqjeT_2?noOXgh;k^tzK3@JSG(@RI1_y|eCy%C!8wLT|C`A5t7t0A;c$R4 zPWssgjF0^&QRB_;G4Ln_KaoxDdX;@AbLCbe6j#Q) zut4kxy7BZbjhmaI(5$wDbh{`@f6ENz_G?%^Sa>1l+v9(V)K|F7$Ub*e-&>`39^D)m zpzcP3dGtZ|EGX@D`2-5inWMN#QJ~mjG_=k}<>V0Bh2M6Z1BM0&`@BUCeXzVx(vQI8 z6x4)Q>Zx{pB^z7<8pONK^W77}zK+;+pw;C0`HG$32gxedH2(_C@3+R_?Dd0#RTDlk z;Y$r4UAAVCOH`ghrV2}^)o}^EwDFy}$jeLJNkRT1)SRc=c48fNHsxzAInjl|rOm@M zzLvP3E+ZbZn}s^vnDcWBWqna`)x0-{PY- zQBa$mc-&QFcmGM#7v(OpZ+O4C-6+^Q;DiV$kYmHX&fb`&UNd*y_IcGeYUyT%Wmp zFPvtZ@4|00Yba05IP;M#YcnhAuQE=NRLQMqtHb%J z=7`ov5fGZDA4hjRsqQ&2F^|q3e}pC)O01f4lJq*7{1qXBpcoY+@)G|F$WDJ{*=aS% z?EMN)T$E<%ap`{du{o~YPgubeo;N^1lD+auRN52?LNn{G&TO_KZg3a0sJDO()f?17 zU?kKlNv!mL>?qzj9#68=^tE~*=f3hhk-Nq798CDBm>s7bb8EX<`un_oT*fmeTb24P z&QMX@s-ud!m$usZv7fi4cOiWBaH})Vrsc{z3!KX+!`kFk%C!-Gl%(6vN8R{!6KdG? z2&GJe8TVN*cU%9jBFCSU#oy_-%lRcqm4huYE*_D1bZjB3A;jj-!cZ=NRZ~jTYUSF2fctFWF*Y>3p5zx%BAd=w%&~b#6XL zxxXQiGu3MQTV$;chMixEsNJM@pn8u>{IW?3&dS?#dSY5dCeD5@+!RR~@MoF{_xu2{ z3$F!+tInIEadKkzYsNoSu;9y-@!lyz*NVWM@msN1E?&4-4|^dTw)u zAmCH|HEs67jfGY0-|tCNt`b68cQ^484|4?ZDbto);1qv?!kov4 z9s&=~8^KxN+hF-`Jd3YU7O~d@OU0C?Q7rti-dv47xz;H0FP^#Xlqsq>6chQ`A<#y8 zT=l{P9%8BRd?Y06Bd)fV_H_UBjT)}|EW*pn!-dF%KlDz#uvXTtXQDK>>~ZBG+XtZC z?!2&eetfUH&!5q+p7>ZTv5?%pQj4)P*4r@{{+Wpo#xwLIcnOARlgf6HP3lUi^RHFr zPO(M!N%_ssJ)P!E0sAS`Bup0V!uQHd=V=kqRUrasCNzTBn|E8c4i|)My6(^sMnq%@ zvwD%sD#kJCXnxu{sR_Cq#oQ+@AM)hcMZ&TUcr0wPtVh=-{6 zS)=jh_k{MENeap4`{3EBwT-AG?-Vv+L|xqCd7Dd}-}D|LFsPxjPUl@ZVqd4?#K`(# zbD3swe6|=C4&27ZSFzQ8u*S;I-D-7SH`{$p9Z;QDyCO{esJ-BOsl9~wLgX5!Im%0X zN~1c7QO8IaTRH4Cm(}8YS`^#aJ%2+9qoJ0Si0`O$dDPWB9eRv7S>jN%=1%Ppgm)J^ zp>y>xU{sf=ep{Ut)B6Ur7;B@poyz)K=bMuCR8S-V4lV__>;D3M$DIeanJ=<0>KCDx z58#@#gf?(;NNHo@>1x$ohyoPMZ`_h%!fxi7AxfcUi9wX^wE^j-qysd!N^B^?x|qJ_ z0H!$Gd2A(*oV$Zc_$z&Iy;mVmygYpjojsn*8=TeX2UqWA6vfxH- z=zS|_nP@7lEb}OyH=mrQ>1V`N-Ju^VLw_1slu(Zyr+~P$-^l8}4u9=m=MGO3qEsxb zu@0wO6Q9S%=1a(K4PG>UEzvj5AS&XSs4;iN(c5}_M^*I-oluBUn4DnT3_!RmT!bFn zOnAjPI>Nqwc;xHoK1^ZfH3eMfg|`jC=SBe==}R{16%`8A>4Jks?uWLT)v%8+G=$G{ z*Zz*S<6Tbts^3v1+FTOa z)8$0(C6FBh*OQUBowf5)*G8@zh2yuz@#gvj=8?3d+scMY-EAOM5%6aK8X$%p?O{x- zYq<@&^z@qUPAO^LWY6UtpK+_3>Sh(Y=MZIh`%P168&*vPm_~;m1;Glxv9NeH{0Z94 z9Cy3{L5Geu^m6oPi571S{?|sE3(zjLKh&UI{LhFDn=Z7Z@84@&UYau@h2!XXW~V4H8QRPB&*i7>KC6J&Y1(4E$r5#~_>$Yvb2vQi zk%%0ljF-(pFU#98N@^Bp<*<1H)n7G7iY=MTM-VAZhVm;z?sALF z3JWpd4W&lbHA(9Acz}}6m*JfaHP?vPC3kNHE75nm+InX|zHBGHwGhn6cZvy*A~9?i zSoozat~$L})=UG!hLE~WT=depq4g9gB`))9Pk_{nAU&CMRZgDi5tcLXcs9>>D$P+Y z+@i29$AF#zu#>VbL(|Z|>fX`T5h=zW@&eku zk(p~ZsCh%nomi3*)t6d07S}+NISqZj_rX8!7R$w(vwVg#s6OI7D<1=ABf>`X<*j7t zY{2enu9;;hx7pS5qV5L?v#Z&e+p1xqHRgE$5HWkvQk45h z7n+FWy%Q6RhBjSoEgyyit4Kd%nHh?QqKWtL)@pzAMX+(NXB-SN7U3_7>EJs2O$Bm1 z{1fGZakN`^Aenz~a>SP3D(6`9unCwWu4yp3h(v5?X!KtXg=wK}Z#J?3ce7&@xAy{f z=fPqFaOvW`iaT&>4GquvuazO*e&_<~;Z#O(fq^saekQ;Cru@K^j6?Kq(Zwad*C#=Z z^C6^WHur+yp3>@2U%2Fv8j>iu*Si9dj=%151vXQhhhvYA)LkiU65w_iz>zYWUs30S+9N19;w z`mxfQ8lJa=e5?*ZwI!jxqs$*o==RgAW2X%pH)&(rwr#UfV@=f9wr$(CZQJG~@AUcJ z?>$%ko9x-=+GjS-TKD?hs$ZhpUK-=d(u~LojFTWZirS_^FX%f}`Eg|QnS+Que0Jn} zF4FLG;_t(mBxetEq95_9B!9FDZDBZqD!i4@6&K~OqbL+1dRjuFU>61}lGa-7nAI6t`UB}?FB>Z%W~V%fv0jru#;Jzg&|Y`t})6?iV* zT7BSS^No4T2V0u^5r{m({FCK17jbLEM^^kzt>`rcDEjTpbA~VlB((((>PXjK;^9=- z+B7lp7+idmwze{}{#-`2EKWPdJPW>8S>I)6#~_{q4`qZ)-|NY zj^|epiYDeCua>>ItFbrKoJH-gbQKzuoEy!mc&n&o7M44Xj{5>va46NEhE~d~54h$8 zGDkXWKIT4cW;hKUMloyRGM0X|1KbnSkIP$(@S_?NENv$P=5h5f`@SROHH9#z8JK5zgC~xKg9Hy#DAn zQN#3Me;_P4rQ#I%eO;2`oc5WF_34mDad(|O*8s57i=*}SW(_46TQ{iMIp-t}A0c>I z2Fqh>bq06{Z8-;^Wk~5Hf79YX9@%Y3S(77(V@or4R82N@;)Am+dJSMC!P!F_EX3!T300tsm|!isKmT z&K9oAAAG9|#I!<7_|@QlXUH1OU>P1a2mnBHsZr=iAlr|<4gcV5d8YkI)rugD@1(Hx zV=oa=dk@X*(MGKz-$%sbFZq=$9MA|9XPqRNqQ6i2(InHXvM!q3G(i(%sKdO{(jV2P z&0$OSIA!h5;pI?Vntg{%u<5d)?6ypEbucN@bbPUCh4CdL_)@C1-mA&WAGezxd{%dVP-F!UGLgjZ{MlgL^|--+%d)8P zwX`m;ZBHXs&XfkCVDbps5q(i%E6@0nF)Ut_iOTx-oX8%Y0WVMY` z?^d>)3Q$Qqo@0Mn`-BAZLFlslz_I3LS$&L{UJH6MQj-UW>dt8(FM$8{RU){;6?kw87Uo z|H_qgPPfs+@UxC#RWgEwc!$r$xLaDpkl;Ry5HFPywsdR$g5MW(L8idu6iD*s)!p$ zpIR1tjy%nDgHv-LSp3L^rLe%$dYOR7pXSGtykpvRs?U47cTzern4qAL2%#T6ifu2* z84q@LcI{ZY!tP$guB?l?vi@~UYxE509D$jUw(h6EZ2S)XEMf9zJ^Sh=7snRN=w)^kQwfz3a03xzdbYIh z!GOnnbJ)>JIyP?hM#~u9H&>k;pPRsDD;HfyA)qw1Yfo`q-$VJ}%s|P9*^_7Onm8zY zs0snIFP%Zh!KvL!xFV$ga0AiE^xlaVd~x&hJCh7ySxDC|V(PK$jkDdx^gZLnMajo@ zyV@HbC1+5qr8{F94CoJ|)PrP{tF$eU5UU>e2ZSWU8Qi=1zq!GDVWxXUp^zfi3c{|B zOAAuzAl~2dF7933F)>3BaQ=`b-N`;WX2AZJ`ZKk3PsF?`u8|tA!NP6Qo0N_fhzUPB zml(%_9G8vpwNor+_RtCgF{t#M!%hgeY)tHjmG#udhKJ2zLsC<`;Uu9HuuO9hpwuBu zoNZG721&w*63rbR_8dYVjzRJd#-FU<;M(ci37?*yGoytG$nm4>3Te%ZAHCtwA*!e6 z#lR6k$r*MM>jOds^?A0YT)n#2$H~}{;pC~z*$>;k@Xy?36Uon02L$&?Z}Y3_P2B+r zr-VN?Ah{M8)yo!_sI$YII38CzeEI=<-TPa+>%TBIZU*b1@p>IAK72dMQiWPddgxp_ zeGcB#hpm)o463YdhSMWA#RIg}j)!W(e=V&HUBr(kJ9{#BQ7?4yT(xgT^>Gd?>^I!2 zIV1Zn@Hs+&)#f}3#H(2f{jr|fr{g(_(gjs{FaOKKi1MnudH+&pjF7+IkA1P|dQ>2} zYwT?Dqlng|oI6KO)j=M$wz4iS3n;Ft(gPBg^HFE%yh%)qu!?PrMVBLVQ$=f%MrGL1 zZZx|*3sST6yQ}NEb2i>kBrLI*arT^*-|bl@UKwd5g{~gkIGjsN1Uk>rl~H=7tUCeo zW%SV!4?fue8l~PIn*~5J?nSny0fx#$NlAY*Ng$QgwRj01mXgjKi!`}Ub5R&7t zZ!&2Xa2yVvDPE|!`C$0Dgc?Fd86jE_?K@x5z4|!x<-YG|0RT#~qTH%pmt#6!7mz6D|Bx z7Au%Tzeq|LC{3O>bG*E)PCpLtdn8pL75?`XNQYyVeB)IRh(AF1KoCcITkT&RA|w3( zUhyAycXtB=15lQCVn{(xFDo@wQ(hhn8H9huWarHW0{#8-jp@WgE_{Pnk&gVd- zM!H~-f*{9AXHW?t5M+4j3ErLCm7j0y>4_gT7MpNT}x1eVXMYi3Z9Lhjnv<^{~T5cFIBI>o5Tzu3+j3e}fXq|MIo} zJX8*Sgsr*o5B^^S>|0q(Ao*f7@|+>;BE1rSz7A za*Ix3rYl6u*jfFiOTSnA(FxecK14uZKo0t}F2n~l@z&=p2Lgqz-`)*a)2E7o?A(C* zE*?H&a_)P#YX^RH1EVRZOdrS-oa)^UXBkxS{g^=P?>Gr-DL^Gx!?t6s39^|;u;F>PHZJ0v!|~UC{?k zRfgmc@Ok#?oS7SedDqY3Wp>=YmIVGJ7+9 z#o@r2kdkAZsXvJs98d7%&cu?ImLqDM#kHG?r1773LZXXBO{wmg_mRGhef7*ba@Zmeo9c`Lw@P`T7khQJp)S~ z{eWJ8N0x7g%QTHvCy!_5uL+ruCFFC%gF653XbMp_a`*eoKaTNHozC)SKY?4kXI64q zx*X%3Lc8`O!{!G}G!hm?6c)b#&JgdG1`S3R5}Ei_rQoq*tl=#E$Enibq~FtnrVf zna~%HI;Z}88_e8a-{DS4X4yh(9632Qh5UsMJV|ksQQw~brVlG*l~M#4EiqB8)s~%dPy&v3uKhAUv0K@gbe(e9%J5d$jJEqK z3`j_y`%zoVy&j@A(u#fe$KdvX!+Tm0@yp!O63pvA7u7>7kkATJbm;*CMG&;Q=|6*i z)Agz>JXYodhn)EIcn~UCrV9 z)otqHZR6b^Jj6m(@%nUdZg*-g*DFB@tmL{F2|V$U+NtFz3#id|BREA$rLrY(>^w3N z?S-u&VlTTD9&D9cp4)iJ3tZY5C$zV%xSo*)A_a8muJPqz(_s$EyQgF(+~?v0|+L8 z%zUs5tXNimVJxlR75&zC&93%1Py6+!x|1F4!F3DG8rlx&t-)kUZ@zt0X2vf+TG+eY zQ7B0238e678WLBkF445UdC5pS{~*+T!!qH26EPn5d7L{HoQE_*R%4cc{-YN5ZTnUJ0?svNm#w{dDvS^U|iX6N#2C=FKP&Tc4$P;92yhsh% z=S2oU3F?kL0_OT1=Mcmymqwn_;i-Qhe)}G`3}lM>J9rb;;^j)YLu36Pp19q|9s{(b zY-Q?|1J4Y2x3cgEzkWl1KVPW>k;I>O3qK|c-+Mzl?MW;Qt4rzITCKsPh|mVx!fqKY z-v(h_x!v=N*y*|~Q2p@&@FRfc+{hrvT@7gljskHHaSaQP5hgD5ibhhJ-Unq?`f6oP zOlD!b-z_gQTGTo9B#rsSP_$j&f(VC71tb(D64_KF0<=@`M2Vm*s{F=73(>74%PNcn zrl6jZf$Q-d)(G^55&NPH!oS@Y5AMIMGfUxZscXqLREt;?VUs6wGlRybypV#dy z3O0G!mUtHO{9aVFpNQ=~eK9-w^jUN$DV$;z82r%V2V;3)J&Kni@!rHCHzn12ceG)t zVcWI+@IE}(QXtvb-AYbF)?wMUk|iI=q5^5+O3;dLLJhnE$PBvl5H;T{I^oSPia;v3 z7sKgQxjPkptIsCrVgz}Of1k(lIXraCc>4)~{_o>vdiB$KW@%|ipPs+Mw+r-n7M@)N zL&|uJn%+jcSpNkI&W^;tZ8%Wm9FR1J0MYI)wGn1te&K< zt{~D+&q}H)El>6DTE@TVo5LKCI-nRDF==XQt!d$vTBd6JCXj?LFhrk69TqWC;(BA# z3MDaM#8f49n^3*9Bn!p3Rf5mMU$KCOr-H6p8^#Y8wxQtrbrjLZ7IV~5kkDgp_3r=r z>dMdY(jPA%#sgyBEn)v@&k_Kdo|q~QK?e3RTxPOqc1Ji6WY zv+3eyazF}sqvR{>ewrNwLm%GU$hT16c4PUA#PvYbw@he2~!weux@p?<&YTOcrWP!t826jlWOSr9X-+!Ij+Z zVUsczfcW{8{i_>R7QL^@vzsiL$Zq?SO_VOQz3QPQ+K$F<=MczleTu}xUx*dl_A1pK5j)@L{8!#mseu5&8ZaB)7K@KlFPArY%pSX(-xE6184wiN zd1NM=&`^>Om9@Ih4Pd{xXpd74I)w$%9jR+oJVeMu1NfbqmDOZl(BSx=_#c*j=BOL0 zlM!_*qmxdTdQh0P*-RPTqacNr1pF<@K@8Rm?!AQ$M0J^z&trlp4KU63|fCQW3)iY=DvSX?p z-EOvtIhPS}eRl+@DDrh|@i#dfrifdL8MpN~jlf-Qa z%pgI&4$@Ts=|P)&Ru;+vK=|jWG#}eV7eKf3O;b?tx3aOZrzlPs%#-u{K|%ipGD639 zud4hOEDCy2Ck0bY07V*t0BTtSGY?f&L6S~PT1;_B(?zv=L-()!w> zAO6SH)z{-i6Z|9k$y2{QX!uWG$gzKLM)r*mUEqw!Cx9(;t3d@XaDW1?k!a9RJ%B z2i}V7AjCzHv$*+`wgt1(T}4rOuKZrtM?LknrKj{V+SWpAoEXPt`zA65d#K~m*TD^B zB)Bj)^%)WL@VrXV)<|A7g_xPAy0m1}VtD#Lxu+y*x>zP&$=H_CnRz_cV#amVRDB{I ztB=#TMA-Dimm?eo<)-M08yW6)A&Cv%PJ}ZWF-h@{@f5j#a!T9oC0(VJm9+(&umX)x zo8ByRMK9w_rMo-0^*quCceNO5h_NCo8<+5ltX=Nxxss>u1Slr0I2trRy}h2i!xyux zgZ{GjR!n-JI#E2vM%@*EzPgRwSjEIBq?pK5n`e_=1P^X~UVOgG94RA127jkT`--o} z@p#n=Q@I&})OCKC&!ym^t4$+EhE9w$B83Qe-P!_LFT8MTi(jvV`@PM?%*1>+6n?M| z9xq=UH-ieHxQ37b@_dQ&l;~*e#Km1#OrjcB+P~xwMWw4COVMMGbT;-?S(x6APhA$U zn*DB#Z2S`wR+b?#=J^v;K9x5!`{oFemg2Gc0|G?*^B0{S6|i9ZIu`3uEfFKopZn^h z7GzZSpJLI`Eodh~Lc&8kokm4P%*F<4Kfnd1C@LlQ@L1Yw>#PKDF1ygbe*I%{M7b7% zQRE)9ePa6;m6!HeAA!?75ADM(P^we$sJ2=6@C)wz0*6-3!fj7?0 zpRES`Th9dzS$+S`Hg$JBt8}Q0j8k%iwvNA|c$k@q(EVbVC4;Ne_1O*x#nM*Uam(bU z8#msgf1Qe7D}66=da#I6CK=^8%r&kqPwwMB<(}|#KqNlcST^ReyvMZST4NErtaD$p zah+0~n{H%W$||*LWNVbB{|RutYyhj%d^Q9>o7D_cFq;34U%^Z+$C}JAx7pJp?XhcI z*YI@q3^dkruYQw;+*_eV=1l#m{@Vse`C2uYic-EkYF#M^l27e z0&EY!^W2s6=$R(047FE&HQ87Y>%Sv56^))Wp12$6kbmI0T9|Y=S}vBE(Zoszf0BZy zwa$7SGZ%8e!-|@F2{;L>cWTltb0fc$;^>+fajUGz2@ISFj32Rp{Pb z`fL7vk)&cqfFS(5_PuXy^$JrR?5;G*wt9h;-XUYJ*)o zW?|-@-#e_0BZix`upe8>-gU+-t;I0O9Xa)&qLIL1?j7aZw3P*5@-DZ@&v9nMVHI6y zu`f7^@sLk)bRI5wzr8U#SlwADC4_6+aGOf*%qFyUS<-YuJmsljr6rH^%~8aL_A4?J zd8Q34OE^TaIFx8zS7;QC%N%{t<1j8Ua_8-e<2S*RL~1{l<QFe(CbZQeo=|x4&PQ69jo$0$EWYdi6^rg2jNd5bWTH#D6UO!% zB|!ZN#xmp&Whk-E$tJa1K z#EH*mZ>0{KMYQmGIh_PR#C~0o*`lR6wfDM+IN2_M`0epA#al%yenFPmEWH-6GH=Ug z7|Ro-CJlU9`c)XoS{O%B?4~Wg2m8a=_99q&yi;X;CfQT_3h4rCJD*ywkv9Zt(e?ZZ z&znh%e|O~XN4y?jv$Z%S~)@LE9oCTWzUR~2nX zFv%vbfv-JJcd~NDJ+aD@ipu1l9#Ou&CvHCl5bMCP5^^_y9o&u;?~>R1JQIg0f1b7Q7#$2CF%8MAsRqF-JyOdv{Gqcs5}=>g%3_t1 zngVJTC`Z(T^#3ir6{uzw*3 z$px4|esUG&wz?Tz=XNN3@l}lWs_|36N>`CIYjr0Y=D~^0v?!m)?aHldZnH?z-WFV(Y8t(){MqyyQ6JXtwQ6XSS@G>Oi{S}yP0>1xJ1H9>yed*vnnOO*;ISP z!y8lxYm`3>sWpe9gpmmwD;)NIfNLdK+u#Pp6neg6+Tt)Nt?{lU%|zw+y76wie0}j( z0WaQFeO9NN8|Izpd);k_md7GO?OX;2Gf47LSWQ+DGbd9X7{kP?T9rj7o>Bg0la>>X z0U7L(mfGch^UDxg%plijJN{%h*MVny2PQ2dder8cg-QFj3^SqSm4mqp?!Fc%@WT!I zUp6x9M#bDT<@E?cXz^riggOmu8Q>rn*X;i1JR! zwKavIMbKKqagX~DTcEDb+*S#!vTO7h@aqo8z2|7M%cH*X%kiBD+Ad(t)c48CSdD~` zBhPAJ+OWBum(IDt-pz2UOvofry@nhLIZ((tUsn!@Jk)?w=7rl}*5IMLbXjW74asDB zw`bt{W$LDuRC;g+%|tCUr%|0%aj*3Xv`OV!Cp0wbRGp1(zKqdjHBu^tzgC@A-WE=Z+1V%!ddgfN9c76Nm)jAhDFj-PS(Zn!&dnlm))n-Fk;TZRx`dspUsL4CeNu-Z}Gh_rGqTQRxF z_}i7sqFK)n^J65VvQ1s(5;_dn?vhqtq=|k zG|Z6Kr;Co1m>3tHRoKbv9mMRPIaO?2YZMERFIagq2EB@hz@IkM`vlxp1dKC!hKIjN zqiB@q3A$^gm37V8HO5Q$9d1Ffs3paeFT08!OiWf>7z+$tmLAGNP}5|TJil|qe{Qpa zT`X-m*Qxr=>#et}{~naalZvbHPN}~+#{i!Oe21)xe#H_Jg5+r_a~%5J`BF^0SKnDE zWyr#{H=h3aY(Fdgw({uQcsLhv-V_wSzqPTi&pzR~I9X@^urZ%NhdScImWcIi)m{Ot zgCr0T7rXae7<6xqECXKdvmtyL-tP!&pnflXd(8^dY(Kv@yBH&GyId*t<^!Y#Kqk*= zXkklddH?Fzf6hH|Caos~cW64if8oSUt4c&fL~=CI!OsD*_qsCM?&c4?G0_7Sauyoh zzs#vULm#nKiwK)VhlNCVP;)$oZ$+CISTs|Vq&?VOEnj_B3M~ZCs9;rojI4}EAt8C` z!ijF&5nJp5`&yM~Y`8D+a7oaeK{#7Q875Fhq&wT>L~jfY3HcE#LnFKJ=rveIa=>uq z%)KKCRC}9Ew09k9zo%Wt70~{7RA-P`ivF9F=Cwz29SBPN5nu+|I34H zG;bXhNby5^i^*$Oj#f-@Bqt}eaIxTrEZ&$t8(64+qd3Q!Lp^aF~bj$pp&ku9O+(0GmZa(Yj z>wfU$(#(A9xfEk>VZ=TDO{ZbU!A-LYf4bI|=@O8m#}URrr}nJV<6pYDOcPA`_U5n= zeA~r5eAzYL;_?I>QX)^kB~?ya+&-^V<{0Z&-Sfo22IUYIOq&yGVW4Pc5;-LaLS+0Q zA+brlTOv0Tr4mSVHKt4Dv=YwEgl7Gg8oFpm)%U#XWzFhqEYTNNaEH^}G4O&?nGPYZ zi2299P#Qs~G+^bk+|9~yMYZ$ey9Dxub9}Tu3QYwK??WQ+cS3l>oSO9&u%R-X4Qo>t)qVsyJYAQg#rWm6EzZB4BAHIJeMCM&?!aUi zYiQu4O#t4X8Q7seAR-7ZnS7BzlU$FK&|_-rd6e{WdfK5xn3@PS2fL%oET-^f5}urX z(PKr{VHM~TEuJ=qoR-SjY^`B)c&xB46gme=~#sxdE zh}1^$JyerxptnKog5bF08)8+$_#xthv3)ruNH(w2^w#jSmD(<6dD z39b^270Ym`U~+D8%Q?@~TwEFbq$;OvTc9nQ7|>MOY9+|?A}!g`FJ=NqKGV4W!!&Sg zef_u0_e#)gbOrs6u{#!uaG%9DYrf*TpN+Z3KPsJ^^uR(Kfu?h2zSuZQ(7Q>_?23V2C_Fn2xvHMOFhd4tBUjP`J$ zF_sC>(G)?r#p*tr)$Q6@p_R!M16ON~%V`#v3B8`+Yo zZXE)FJ5t$cRb(cS+gc`SATdc0KT&ulsoPmNg|@;>I!HCWd{Rbjj#4 z@ASX<`6Db1dPDGZp=GH)OCTa~{|EWEkhe9)$I{bOoif4g!Fm5S=XS%ZiquAs9e|bF z=G$9Men;3=Y1KJLt7Oe>Gw20KZ&Nl5CgxHwfd?vS^6u*xny5Y)qlT}VUKdJnw z*Mh8O%7R#cK~D&a?dF}D&U1F==&7BO%L?AqC2e-CLkGNeW`RN*i_^FK`tFva!>DF{ zb#DBM(2c4BR*D*l;s+W}%I)W4wvy;~OVvTqJGhu1ixd8+9$ zX9vzY>XwGJ$0T~f7JS1c<)1se?3bLkrN*_(q*c8CO=y2Aki#Q06BEXLoXgcFv`zO` zjE&C@WJ8wjRMuhGb{1Xv*q=~heu~DC>R1}y=I+fQOm1IWN=xtz^s8cNnsaGlp;r(!A!pVn;rAJ zy-nu~+1^4AkD-0+=Nb4bdDsu0_$ntf*RFbUz?(74U9f2nQQNqXx1UruBt*rQ1qeQ6 zcrb9CJZ;4mi*U+bfm25=x8d62ZZ7^#HgA>7D9-}d^;|fR%y8E(w*lW3r!>fq%9}Ja zB*AXq^x(1u{ESe|wET+5<4^g1B$IJ^Opv5y=TtW#9MN##$!OAqkdR3bPG&FbRht)E z3aSn;-P|mRQ{kE1nviJTWw+QJjT7nZ^n)JV8(+$7CG<85%Nxu;u_AO1Q*Xg41hQ{l ztj<-|Ca+i;nN}hqMzuHqM=y3)3r~k`)C6~Hl}OcO-xmIi6)Z-!KTK8zUCQgBwr?=B z=Kv2LHXc7-(lck1tMM3qwYVVDsNj}itt_WC+J59)5EMwqV3s+g{=7k{xGk7V#ZZ53o^P=W7%x18E zv)$D(qT^7VW-U$59mW+D$ce1G4Ks{0#2n~Xe@bxDG@@RYdi_fhQvYL84XCz|CfDYp ziK(Z@raM4cO7LxuUQqH4eo6+9&s6NsT-;n4xlH;~H6(`OR@ya@^zz$&?M%J|*RCah zM_;r2{GEBmjvV<~UvjcMQ8&S}2IUzwV3ah#&`u|P0jT>h4E&aZiYPbS>cKTwe5_Y4 zT%9e;RrJK~Ws5>iS%a#?G9PrHMvk)R$Rbi{pkBUYMLd zb%F`s?Hcm^;EdTO)S|oP`gp93#anUZPYL|xc*loDnWA*8;;Gk&z4zRTHwPo*KFLGn z*56-iLh$t9iU}@9w{}Wf?geFS-6C$Mfl^<$Z#{7vjr?kjwDVvqgPrjw2NJ3&tUJDQ zU?BnUuK;!VG*6*Bav1A2@y^`s#*7Q`qeY!NgDe5Z&9n-x$;mxwQQ1@E zuwSotbiIa)01wI{?&;5HVKs&4U~!?lvbAiqtZ={1o2RQ6NRJmUfFDse@iW&fIQ<+b zY0q*i0OFhW!3xCEM4`~Sq%`U8kl>6ho|g#*MA=^IoH*xnCK2r<)~zjFw7<`~O`oJeu)92R7`f5-Pv(Z_z`q9-@6$^#JzP#i4@zrg< z$?5TKNl&h70M0acOEe0@g8tXB)%a$oWnV!#a!9iAqVf6KHc3@joC`cXalDIDTVJn^ zTLVu(4p(~86+&0_TzB_}GmGBe+ZWhPwY1YZ!^_Aqw-*B#wH6)o!?=i)96X)!@^WkH z-==TrU0Wkq!8NZHb1LDD>%{rOk2ok)Os9LCRvtwlKLaL84=6)>+mj8N$}vHL##lj! zKz+sFrTi~kZNH^TjS+tAPOe+weXEkHG=YO^?}x-&Ja1lwmc$7p!VU-GM%rjxI@1<$ zKlYb?^~iF*MmRh z=s5dLT|RC`!-1v+C5rXlI0SzCNPS?U`=oK=(TR2?RvPC*t>Z;iq(U}O5+=S0vRj^| z!o7lSDduub_%i_YKn@50#QK+T)zB7Nv#?;pu&Qlfd^2=dPB&rRCH85Gt~S530QAK4 znr+0?O<4#bm-zJz&IQaglw3BN+42%29C>nTNma+`!6FFO@2W)O>owE5jb0e+edu;Ky)DR^E;Jfk0lQ0EsG z8jOmnnxdwVZRw!bc;vD;0}zDynT)e0Z{;m{P+pqu=3VL`VzUV{6~wqpvGO}rcPSC! zUHQFyDKPUmB}&&0?1-R9i>d6``A=D&rLN|mn)Qce1K@l6;ZVP`BM{fh7whvUA^+)z z5y+lT8en{yN2i?^8~lk(-q;QIBP;Y-0G=qGY(#CO&=4l?YrN);$RgVH*OQpG!~n!x znD0TQftxzUG=w~_2|!#;m; za9me@wcG~unfKY%RwzfB}V)T}=q)(*iCqp!r+lfyMBy83w=}(O4FHl$B zGkT7I3+0M{l-i;Ccs1UJOQZwc7>t)y-t70{uigiV*~tQofm9-iu9gi;E(_2NtjNU_ z(~0`h({ww!x+dj(SK<_+KKR3uu*#$hvVjQ>pccFp9x!BU>4w&X(N@r&$=w=BqWeG-!%YpnT8MZPxkueoJC8&+@Bj%B zNfw&YaTBbVb_+BJ;z8H;Mg7s;Y-Mf1(YZzys=gwkF)JwZ09eCq__{Z_#HM# z+0;KVgBZiq$OG*E`n#kU9~~ePjw1RjMPP>JCAAy;a3C>T7PQHBHR0*q(fa1Sz4Jgi zaH3Y&sfTjx?jz7`_1y5s*FWq_uWS`-iCQaB(eWh<7v3SbUiA%+ zVXYdkdV`Sv7C)gy0az;uUz&_$hTLR_l6SirSN|~G)Z_4EV#f*XTbk?~%fANSN3k8@ zVCi#Qd?><4W8Ixi%t*Wo40xA!ejhESkGN;+^?QBdQh7lS_!`jr<@!|JCN|}3A=;%V zzS1Xur>28!R}5W>5YFu$8gWFm=hzBW9K;F-{J@PAe~}nSddEjh_}rdViy2~!U>Lzq zggR_G#+;S3HT%Jb1d={o{I)e1Uc6RY_TuHoJkM-wWF=2d{Z+mRW0{CV9)HWm+@-?H zctr>sHDv1C=#uj;9&KqF?4^8P~gQ*4_3 zDwc(JDghIWq=^3^bt7_%te}N0-*n8!rPoN=rQN9uLB_|yp-~C6x3~Y}zq?KdJ_6Rs zEB&THy;yx_@Na#o2kGjNz{&WisLHCVqeqPWc!U25^5zy6oIqT3eX!W9cf&wOH#9QpQU34(qg7H;5+Fn{{S38w_5v9%%n41sS@5#eKYDBVq(T5; zi_!G|wS_>WYTA7k0t58uwYYF>?*bt&V2ZY`A;BswKsWvuq-*@AgdF%Muq*Rf1mNQ0 zrapn+`xD-H`136SzQuJO$^Fwwey%~x2fWjgfMk+bUjp3NZw>emcgDUAxI;Jp{p5e+ zTIK5I3mA~{u>z?fd5J+cA>?CeNRJ&wz#|EgG)hV;wucLY`gxI%>GZyKju=u2TzYtX zdcSC&sXbD40zg9+Cgv$#53S01?}^<(XE%J}L5R$NAcY|E7YH**4-4ib25JrshJ}|l zvh3KYu~cT!y5#|s2BuQKTUom#*l;M#^qu1AQa(pD5T^f21v@~df(NEJ6)OMe2N!e-12h_Hw8jo8z^`Bt_=}CA(Iw+ za&<1bMtymTsZrv(9dY)0FHh6AW1s(UJRX~%u=s$=McJ0h_8PqVsbRG&2j<5htF zR}=i>I}J8FIE9IstEaA>wStX}J?WE9O*XfR=vW+Eh?1rjknNR zVN+|AfCr$d24p@mz!^RXW|nUoR9K_^WF^FWDO48MQ|@uOME4075CmNJ*)cxsA=4aZSnK4}aXV9jHkY=Xn)1 zwgxBrgMrDtIH>pQTU92rr*-Faejhx*dZpXqSY(4>?e_;h#LV$Gh@uHIBiWXe3FPwg zFP4%A@vBqcEjzY5EXQ^{yoPNfUiLS)D4a_}8dbmLA0_yb!{=c)ad zjrv~Sab!$9fKEmgh~M5VHK+FM)oC6Ylw(v?7w1`=?(bCw3F{j)U5nb2o;L&#CkP?n zQx*ZK-juw`Zw9f(-!?R|AIC7Q`%VhKyapa>p#-qp41e?hAa)#HUz_O}nD290$>pbv zRaDu6cUt1j5$czk9;MyCAb%lKX6xUPXCr&5=BNISkAI#7s}MW{&I+n8x`)K`5f*Q6 zuR?G)%rBs~Y1*nuU)80@@t8m&L=SG>;X1;l;TelXM0!9lptm|8g8@|mw*dF zt%v1vy3IBeJER}vlk$~|^7pD-9bt4S;%T(QemwRm ziE~2LIcv+@Lr*=ww61cQ)4({iCzPw{X2MDPnOUePy?)6^D=M0s7$3h=^nTWR3BIFH zB-%>Mfps%mgDgDC9#i&5|&0X@6Cnk|V0 z$CV@viGWf-8EPoG5FSL*7rg?-Mfno0gW*#}WpPL}aPn)<%p2>9))#f})1E?e*v{Ak$yDu+sA=2tv}RQjw}rp5H1vsyVgrh6kR#oK zZ5RVjE#H6eO+XD|1;`qN*QH0h2*WO9YbRqTIYOb2$d{PDb~A)`ePhC&=oyDK>G<*0 z>CRD6>FZIpMCmVC^EE74I;u89z$#}^Q4zCoy3CToi}&pKcKzR9w|7=eqPDiLgk0ut zhtK#IO)Jd1k1y0$`JjhC?Ey$R41o)bjJzG>mx70*Hnl31>ZnmLsJKbboz^IxG*ooV z4fI`0^w=8>!aaJO_f9`=U+uG)8p#|?W=4ogbkb^X^l-o6Oiz# zVe9A7QW%9rqxF{EsWWQ?8K+cDj|a%h7jkN&)F6+e3#d0fpruW4Y0cMEdy1pvmg4Wp zE6~sV@cUq15Ieei{q%g96nxE3YkHzWTXNWXyz8G!Mh394&V@iw-_GcqF9~3@0?(7K z-WP}B6?2(+YwvQq?!Z=@EV3)>B%QeqoLS>ciUHt%X^q{QmXLDbr?xTWhY+O0=k;r1 zTFP!|x^N$S$XL;+Hksf}F!%X!udDdI$(nEWbn?ss2I*OVkn77*X;e-JZ+lDKv)Sqb z=lA@mrOak8J`R#X3^X`f&{lP?&_u$(St7}3t9^8Ff%{(1x_A7&&@T9Forl*2D%fP{ zMlWzGgfUPd(RO8M!)xs_;RI8Q!|!?pe8BL;-TB4XoD#OrwNegiD$sZ- zA8J!B-oAIM@2lb;Q+kBK)^b8^-d)(!jWb(Q5pF`zP_u)L2W@VKqh)h)atUMres*@J z3R;e>EMAb>O5BprWl9fr7Zd4e?1%I8c4NSz#==*122dl0b<%(}zQ)>6nVYNJ%-;v$ z!+CuYIgsL~AX=^L1L0B=37+$W)#n__U|QHK007Fz)bsOMChR(5nu^=|Wm91d zINDmC%wyT%4*M_0>17c))|HdV5mqKPEL?=0>9D`#wl6LtP%;GbQ@N#ISQY-|nJXty zPQ;B_TSFSHZ_Mi`JfDs?Q#kJ!bBkX!MgH2?B7On)EH{N^y6;=-QT(6*%{H;T!12nA z?CM}B@Y($`3L3V1_>z>5^lD zoWR3hT8F{hikn%-C$ToEZK+Z11-${EH)0tAe%-EbPFv05Mg5VkaZWK(g`n!!3pcaB zQ`g6Ue%R3i>qEj&$x|Sf{|IKzP@jnZYAWw&{YjlSG!AaN0 z@C1-f3!l9sGtw&g65%Gts)W@@F|GLe4MA#`0i05+4^3adC4)p z>^cwl6%F-l9wI;|alFZT>zgA`PUWo+-$Bv}%L59!f_au@IYU+58;}Y@6^OWDWpwCF z_jo#6C+3%(*Rli7vZ4^RJV!asBP1fdvn?B)+Ky_5&(CFZ!uG~(4qX!FrGjKea90_+ zw=-*hYgNn6ZOl-#8ALj7Wz>B5E$pz=1*n+-DD=O&t6p$e%fO^CB$|Ef-LIOTP4Oft zaeI3A-PKTJ@EA+Ys5<^L0F_UWo6<`5ozKsCv{>uNwFN_>DU_Xz3AC6WLZ~I0T&uGx z`Nbz*7U!(vQmL97wM@!Z*Bh)Q&hLxIRo$Duk+j{Wlt(H5)VOT(Dtr%=t8-q@Ex=)+ zdalIJ3vF$ITyn#Sa#_U@H|yeIt_@ivDJ44Ew|DA0;6&8){>X6W^;K#ZGw+Q_C}z-P z@i{rOqsVhDCpnE8mhGgSJC_RgSF{=w8iBgP%Tqla zR8-R+VG{wktH?!90w)Ybw&rcZN?Afz<$9s^7NG-_tD@0he5ydXyEbjM3{V6$H33>_ ziz zR%AuvAY3-@**JG4pBmtalwQ$W$t1p2#t`s<_^cUeBu?1WmQBFe#D1@ogAE*Il6!wF4$1+V*f zW)>D9*}%D)@g3mL?Jl7)!_wSsyV9ejELpsM82IhNglEsW)*nV``sqdcCWndTxw8_lC2ZYp9|m zHu#Zny!hzaI<1)HbNeY$+s?(*^Q#teW4myltxT%(lG-r&|wd>j^#@ZNu{6pkdkuRXCy4nt8s_B!$FAH){~k>$1NmN z@ui{~2(@#%#l6qdEq#FvhC=1eY{-0AvLn+kvAmbufbNkA+8BvG@_Gk)pTJ5G8Wnk6k9QUT3~TH%eoK-)U;42YZ!>vR9IPt zq4M}FK3_$?kZlB{ZM>n4hyjoxuu7)Z)ub9qs^%gbS@0j2w$<4k?$tbI`~NBvdi0S~ z#ski^bGaX7X_=-OP_NTxkIYWo)+-W{mTPCYByLsz#%th;%GgDg`R8<@9OY;g78s^1 zLKhNhLI_pu_|dp>=(yC5UE?7Rxq1pykttGX|JN{6?udI#FZh#J zGThcGk-c@`+THi%`6nr1^k*{~k=ra?~n&Gnfr&73ZN*x{Yo(1nR=@2-< zs_8;~d$K`9*AWzU-z*%OV7dlwVu0JEs<}E<+F_Be*Ze5xVp8^KsC72{ZHL*+ho9Nx zzJ3O`DuCMUpWo{Fn#^_{@ej`-JgFl{C(GTh7l1$fNQk8Cc=~W*!}!u%4#@1+f%el@1FO7$w_TGd=pa^4@fo{9`9~$PIT~B zm#7#;DQ6QYzsqI9v`+ipW@@Qp@&zm2j6dJ7?NY`-vAB(1wb^r`2sG4jLzREVbxKK; zl;~7%TyQC^JbH=6XmXZqHEVg1fgWaE4aLu^7z5gMe}yd zFUr~!b+W(P{HbOnwgC3MTB;yq|bb-GIXW}2%#`RRe1q758ZWNo%KPg?R6~G)8kj4q@%~*a%c(dV z)Csfr9&?zrYExJ2c33r-5az|8-45nuCSKlc$BzP3LFxt=)OS^O!u*y6DRuvmEj{OX zKM61f+(Mm)6pHP0^@oun<4clFtx1B`i6|Nrwfl5i|q+`UTsoi>ifPO50 z^~G(JGNX!SHet11!^gPLSv~hMa*%n?M!0R5ob6@p6*Lah%*yI|!=HcsvQ14%c*qRs z%6lW-z&pkGvg?^ulnPw557f`geVb8huq)%Mk(z=bhk)pVk6%hJBKI;g6iybG$#?y!2F*HBnd>HFj_5%`=g?o^9#9t z1*J{iyD-9*u;Mxc8VXf7{8cm&mH{K-!APgjxq(wtlZ&^X8^2$#2y5lHw!d^P8&wlp z0}Sci^y#ZA6&sJjFsmxp9GeFHFalurLYyGRYPKx_LtE8EP$;Sh2AGjRfwx@u#-kzNq3~ z;BQob0?4{bt{H(B|gVV%Niy*4G)`znJbEM-ZFsJhRdyR4U-e4(1t=mg_EFl4<_1 zp5U`6H95vooB4RfG0jD(t}d_3uZw^VR)+vjL~XaPohchf@&kkZ#ZXcG-t*(aY!mff zpLoI8lrP%Fyi0O5qZ=+a7v%lGzhxf;9t=S`HHzoi{Lr*G1EK>~o^>y7py*!l&NwuyyV zj9B=RHJftwNfyyD)}fB`lDu3_mmV-&4Q7-AVXut%FWrK-|7|YK(qS>_V_Mdim!QY2S=V)>^f9CKwjTP$mbm#sfb;@4VIUb-7i1^6lwbZ}-gP>qz1QaT+^_SSp+#MqiI8yXVyEsgbc)GA$?Av&hQX+5Of@!( zK9USx`t6^Kf1>V5h)VRk_vs(xE-8cw%F^%nk`)Qztu7j+(i)i5vHu>x`bK4iNsLr} z<3?rd;x7>!7jRLxE6~xfnjU~sqCG_Qd3&Jv=qh)ggdmPc-XJocca)QsXo!VPC29I0VV?@Y^M<&fkM)5V~OHi)J+qL zGD9Bu_*gYW`L={X+mtUER5ZBCIN7Q{v0w7z?$AYHys_?j{S@O>Mq$nQv4rHT_x8$% z7!H>n;h{LbD8l*v4V3k-r_hK>Ykv0xr$*ft({XbTjR{#>#2;cFORuxhX~qL$^j>v7 z#E(%1B>ZWGM+@=D*qsEdv^tdou48YIIt4;ql8dr9y(|BPQDWR6pjYLz#;vZvzIZZv z3383iPT_%iLm`coOgc}3BhX)?=VJ{nt*x~MiIudddd#A`nzyXZl-Zknxj7fsH-o1Y zOm-1ge z#VYLNHuo*bZ|JVLeG}BDT31VQ?qBjcTg=MCSxCZ(E2gJttd+w%m29>@RF{Vi^d&LG z>d$_JP}_3)QCN>oX-A(=vp=8K{OX*CVnHpagxJNVr|l_LQ!g2y=PFLzS+9_#^2 z@n&gzB9|f{klP+T&sY}bPS~lXtbmE?>1-IrYjuL~&p2QvZ-BwRj?x=W{T#k}MAy7u_z1T5-Sxpria5zS&^t2KnzKhl;B`Um20p zl?!I;TS3ZVD6T-@@=0Pc3ZL{b9Sq{)30<$WR&;c{d?AEY8VoQZ zMwHbV+=CNCl!Pm##P`Gw`0lb+o>tL8|A_S0`B{zRDEyG!kmlgj``F&FMIF%OWd#p31cTW88P2@U5lyt!Gev z+BC2D8D_LR6J5Xtg9b?7+}zBnBq}W_A8mE~8=09j&Rfgcb$%_sG;+m;=WqYkJbNL; zi-5DKcBZidYK|2!Du`Lw9J0JPGdnk68@2RiaM5jCTT-((ZOCt!SU0c}(Y#wz1qQkM zZrril#DDmcTTB|U>g$e|aNKrY5#e19Z`L?Jm(~Z%Y-hn19p#E#sI}aC;wx);*H(6j5rXyEz2>WYhtbRB@bh}T1uS)Rm5ay`t}2A}$1bI`z4u;~c*V%7 zKYsA!!gXan)U9}dy0<<*Se;J@xCL)}%QxAH)R~poISDZT7`l>LSQUG>to{z79fdSiIqnh}98hNHc``YmId2rJz; z|GozN#0Oe;x&N*GgT;Rw&*b0TIqC)z!OegFq#nRDEy-Z4+E%TP=irKN0Jn9^8Gq$tn7INyMT}oAI5b3#e6Vs40VmSNxP5%p9V3eTBTCjk8rqVArCkdoY9zEW; z4EdF92oXC#Z62T00dy|!9LRMFoF)Qv{4vO1JVg71H+vm#PUQdjFX)m@PfvUP{7m#{ zK7k5?e_L;WNPyY0`VuwO`4-O6#-h3GoFe-$y+P3$FUT~oPBYb>(QtstXJftq+5SbH#d;sC^_J(ZBAlhzkW@yhn(&cVcU>s3K1OUPM;8}`Gx09=ZWT+*^WoADLJJ=&DblObf3EPL z^UXdZ?x4X4Kn#nu@Ry(iT8)99&`vB&*Vxf@XM{f(vpbm!5;1aX zZ@(C7Q)3Kae8KhY-7TD;oh$xideRxD)>e_L`cF?!aoMfc+guokiFYnH+D@2!iOI+c z+JH&UkbSTg{Q2du{@T`Ww`kkxpxY`l3<~a$QA4p$Op4!1++GFCWhK#|#J90!|M++J zG!SDr*tD#bO>!+GibL0GNj)=$?{z~5qu)rWxKY_kJoj{OgJt5Qg25E6;~`-^f$c!R z+CToY>{C_)3sm*zhu_F6IEJSvg!|-t2f_88aUR1%#*K|M}SONR@}8|E<_e2Lzos%Qxf;#e2qQ#8+bgAAEw4#Tm6V)^o6h)E zlH}NP7uPAif6{S}nBFNgZAAY4>Jez3${ee!tF4y2S~F4e#o3t$|K6>s(T7U%x^qD5 z`Sa%j7zfV9CtOl)($TuLPW1I{Y;@G`o2d@d5oAyo6v6Q@9)Dn80C4QKbg@B~oR5yM z_>FlGSKGZ`-!N+8@*>#=b9b`X(yaYXHPS%%#RPE2|0+8D&)clB!i ziyFd4S#AwEJI@$&d27-F%j}Qhbe$_Ql zrd4&}*l`ngRo&a|^BBB2h2-DJS4}P`Xm}A zbgr|?t=q{e^UuaLwOSri$K@$t{ZTQDm7zGy%G9enzI%_2De0IUwu(y1nXHP(J~;{I z%`71;n@4AN?l5UYZh_t}<|*gop)_hqzA&+Lmc8TDb>L+st9pmYpMTv&&l5+D(RiUz zQpGbyOU%l7Y7MG@XeM~B_jrFks9CmHy6)S%$|J7-Ra6yJ6(&Fe)(^VoTvS8}HRncM z6_?^P=4M6=e|esIb%UN8?pB294Ba_1?~`}v?q$+)nErXhPdCOO+l-+!eWuYNwV``4 z1QPt%@HP7w+P9~=ftw59!@2rN?wif%twAl5%6Dw{Al6P-`nWrTM+hua^{1uV7abnb zOV`x$30sSP)sQ3X71wogAZ)hycH*4G`%T>{+M}o97-10Q#7 zB;I$SD$9mcE`TBOtjCJgi)+V9u>nFVqj)X~vXEg6>)}F?Ve#Sn&<#PgAt=eb9Oz6!%(C(;M*2^=axj zGUX=Jhr0$T^{WmsjRN|m!s}PvCU+%a5neG_T<*umVRI=44(1Z_SSL7^ZF1z_b_)K} zJesT|fG^6zv8>~2o}J$FS3cCqv#REP(Ugxm7Nz4S(CS^oEckJUc?g-1%kAMcYrX7M z)<^1X;1PGY=UuR!b5!WUBp=h8GKP@XasTNVw?+o{G-i^yupK@1T_zvrJc0zq6 zNqW!}5cb8RR^=pW)0MP~nt55kK-v-K#?v$uc$GS1II+fhApk7xza1cni~UqfJ-&m? zi6gTB4^^kw>cfz3F?V(|=^fS4l!6|oB+=G&%rlIsdvTgGzu-Vc2{6Bs6l^~D&&a^j zZL{<(*TwI-y+b@H#zKQ0CMTQUhTtiS+pDaxVb2VKnX%?a!`~>-K2V(!GxvV7hq%95 z&AuR4^k$p7WJ!0FixkH}-ECC6`SO~~hm^APzW;D1j-H%7`Wu>T+{nR=v6^#3NnvWQ z@PYC|i$}>uN|_YPSm|Yj`fP%KhPL4FO<4mpzxqTtqOW~0nvElEh5}`GeN$UeV1AHL z7T3U&xD9{zmScllV?wDu1-1#iG^C~D2Ypx*p>4cJiUmk?urn4ZXqhEbWBM1r#$6OW z)2TW=2TpN`UX&wkMGk#_oaKx@kM+%d8rILjD9i-1;j&a5`qmrpkD{G*a@Pu=yUx5I z2s)W3Buc5`H>VC;!Zs`l;f{eNlh?Zs)bFz#pXIeU zcVR34g$YoLm`&?S$?}DnaL!Lc?W{sB^@-(i>w})5uNCbP8IDC%IO?3L6OLStK;mNN zAvF=J+oV5X*jQr!5(8*`-W~zPYRjtFCDb@A>%)NLFF1bAt8+`DSMYd3jEQOv))5Ui z7++~&VG-6a``QzVFSYU$;D%UF3oB~7~0Zl0$DyIA? zuzHN#x9i`$Se2MHETo+7MPUD`{q1S2cX0oB%lR|+!;-F8D!mMVFAo+0+iK4+h7M?c z5ObakaQmLFQMK5P?YnhHPhcs{k;~R|^BcVIjhLX3<^guqeN70d>Yr`unYl@Y)iIjZ z>^n>Eo6oxjz+OAWw}8*>>GqR8zC8f3Tl}$#aXMRR3S+~r@@dcYT;;*2$vQf!TW-|F z4?Q5IiQ|)uJ~|AjC&cF9(N^;YO-|J?lG4hYTphm)iP92CaE&65VIojs;$#fAKMkMj z>k}eHv)52#46`dIpa=>I3=ACnrrcx)#D>O6BfsZmgi^SD_mWV&PuA|l$45oY(3$9F zw5_~T<{O>#SnW?D4~x;Y)fvi%brAs5bBQlsQ>BV_WW^W?4ha%or?ogGhjR5e=;Lnc zdA^z#P4Yr1ruj&6;pE|qBwim~_sAnAt~nWyB%qJ~a*7@!rI3Azg@=icc}>(69HP6; zB!VKcOA6q%G_#={A1#Ux|6A=bWQ(ZZs3`AdGJK=`LPgpYK5 zP;VoOoO*=wt{wCY%s6~(==$5hU0z049UZ5#lq9#3thuPZ)zhB+NO}17nJa;VLF(3mu8eR#Id&O7sR0By-QV>uf zz@x7?@j3X8HWp@Am>CX^3r=S4m>1eXyToJyZNptcny)cJYe7?8j>i3a4R)n zL2h{T$UUHgU-4W z?GOt`)~kyO^WOP@Zt(9MhL}|WqH}d^jb9kJV)+>`v4aeXSU#wHA3%X)jp`4PgBeh& z=G`p<+mBn~3K~`C;=(Q-Ki|3m0JnwbT5fJ`uBxg+p7vH|511-mx-EWg|4+k#J31pk zMq1kY4=A}2alP3WcXVVyvB@0;rD%_UEg27+*||BttCYmV$aCEfRUq!!F|Vf?ANT*# z`9`1lW%%su?CPre>AiNEaY{-`062K;?IU=zrKu?xfv9udjjgu~(8A)oY~p98hXBg- zzM(+*ZTfxYv?N_G0{rmf0x4UB*uh)J{5?B_p!o!%xKKS`B2vKqs}_9TJrF^!4{|R4 zKT>&+eQ{c32U?LPg?=NM*!$H+~41Sef-;f1-m*`)CDMhe*Nzy zCVT;YM#SU80HEJ{=f~q4M|8m0!(56WoFt_&)Y()>k-_a$X!Y&y*e&t+8ge-?y**7&X8z#8h^YNoL_oQ z!Irq|GW_@E@t?95a6Pu?GM0{Gd$;a5GWHJH^Na$g-L4v)XH&2}dwo>lo-0w%e34s= z?^t4>_6^vC6=j{dQBY@$d;dmM(uG&xuBqv9i?4>3@(^)0b#w?0M!lj^{e2i_NS7dg zFO{omFX~s`p*G*V6xTcs!C$wm*CzFZ|LYB$(|2NRW8hfVZB`{&Cw_B)m_4^PvpF-d z+g>h?+(+4e9PlPl|HC=i#XvV5$r_XFy4V0)mNcwGxS4-V(70;`YCziqMb%-z|3ekv17@E<~eW)tpMnvs|W*HnfrWp$Q zHQ3yau7Aq25Y=6#!0D{{hQOiA{)`GLi##FDkEX6)Z&@W&=O`Fs2uPgODdnLWAo+IolHg z5!J--eu=Ai$IRA}cN(iQiy>*|UV`97V!4+;vHjYef7r^UmxLEdus<}4#@ ztuJ&JN8cFc*_IQ8Xrg@rHY*g|zuz)({u0*vmp!;%;2gyJbwULi^tk#6^jvPwK}NXV zJl-(oA78!-rS{?*j<|8aVO_lxL>K*m_Dx%pLwsmQka9)FHUf?Qxw*{-fd{nVM4@AM z#auHU&eAg=yEJ9V#bm@I)6dmkSqKzdJj(%*GZ`)p7mbFr+tU^YM7hW67+{_uTrRc! zP*)l}PtR20esRcLYTa)fUS96tIQ}fFh$8Lc?cVF5noq#DTV0!*GXcV6fnHQ8N5mZ- zOQ;a=ob>Kwr^H=0XUj{#T?dEM0Nd9$nqYq)Ec}8CM>Un$>FDzY(b?MUOtj$!{zcyW zD{c)TD%&&j=F!4eYb{rZ&ELPfye*gB-5@1m*n;3PsGMl=NDljBdGB8g{_QPahl+Qb z>btg&dEQolv3W;L$y2HN&8AH`I^EZ}2a;jCcg%Nk^EmwcU42Ul?tzH|M3dui-01(t zrl$C*C~oD9U+)F@ySz*cxUK}#LWs4k7R_`UGH761CZ>rV_aS(Xe1VCR5-;*Lc+lW5 z)@juRJnS{s&(pD2X1xPi-kn6z_J`dFf)nmqm^UjPV9oE;#zhP>v6)`J$U8*;cKe#Ix(@T^DL2EtJvizo%(K)}^!%E*u z^|Wp2?0ct-0Wh$pGL41o@}iO=~{cVYS&~RWQ^XQ9}S{xrK)1*15G6MW?|*2i~cW zzyrPC{86=ADE}NbEDs2MShAYviFAR83)jhf*8)Y?;Uyx;%u6o>-20q5TZY;~%)`5} z1#eYJ$#%A-uE)@5H52M;bK_PiA6&2#K7mw zf16j{8hupRY7#&q$DizJJD{k9kbyH80ojL>YN(6S^&gX@DhkQORvW+8G#k2)v;u}D zC6n5-6B2mMRuIUdFN#Qlv%lD%UWyB~X^~$~*!$CX^RHRL#Ut6yEO-GYzVME7gL40P zT6G}+69xucjo!RgEJwUhXmG`eqU&^$+k^WjAB))I5Fjh2U&pyg(H^eE5J3!&Ttrno zFeiBPZ-Md5ZI3s2n{G?otj*zWnlQ~}N9%x)le277YUH)kVwyv4QOMH7v0;tRhf@gu z0C$7V)m>(3vXQ69$8;=}Yfai)G>a~EMMq(!zH80H^X;YTFQbbNocTK~ReWPUZ*$w9 z$P8_IC5Q2nyc?$WP1s#TsqT`~u10-|6JHTaucBk_P5a23&6dD5&LIMP4{g23vvM`zR7s$*z7~y(Tcjv%sNc;g0!wHHAm6dti^uMwUUy5y#;hv{ zO`5BIbIoTr?=9KQLD-NN@iezhI*tbxs+2iYO-<_vf0oZD|KnH({(v3qCml}&XAAcp z?Fcshd9R~9OCD}@g~sXan=;PZ0f*2wDJyH%3(4z@?2fJ8fJIHx317wFf2^yTqAR!F zb&4b>lb%G5*xd|0?%+fBbm5_k@lzECcVOshr!zcNRIGu zGGX!NoYu?Ues@ip6VX$f4{Lf`Nh&j`_55P99M$wLi>jX8eDPRU0Wu=p&eyL&Q@w5V zK161ZcpGj*E%R*;WYgZFIgYySJ#NPZ>~F4}s&|e#;eKzB!iSArgA>zkjh1bRJrI>(8q@#2lZ(PV6-RkFOAPM%RVzoY$IUGJYZ8k^A%Hicu*`8i>z!h_p3Cr}u?bil0HNIjhD6+-{2?hdX5)u-1 zwY38LZlF%!ZJ1a56Buj|2c9OmxW>!$pTY&mjhyioE4*c=lOA2sIQ=+{@Q+b@_jhLo z7Uubdxr|PhN*qjwFUj9&R$$2f#)JFI{gbw-7`ud`XZFbhA%(a~`l!<3GX-7}P7`d| z>kWU5X79Gg8;^eN7R0UEbk_M(W8^!nSrv0$jD5Sh!8(?5T+Wb0;yWu3&CJsyTk>9M z|Jaca7)jgz;&H5RDryIPr)bc*H z#=7PVj0h6e*wozXrI#r!--WnqmCxQM>_sDGXWJLMml=}P14@|hL#ukiNgPX9H}_Jg z=}!{*p}kg$9gA8GZ-a;b>TZ-e#D6wO(}2W@5F$9ocu)b$k_~vhH?)oMw6?LqyKVxJ z0a9zXzrQM|wnP2jWuBeYsb7J!ldwRa=gYP(Y|CoFen_+mM#Hr(pT~`Y29;LbI00Xt z_TwT}5rdw=i!l=^g|yBm>#vbbMa$6&>OM6>Bot6+ESn~auD`aF`6&B0&O@l_kyo3M zU$cfz+}XBwVcU#j7My6$P{pUyqkfMb@;wI1lUxjkQ=>0@YkRiT;<@$teL^64smKEu z$_q(ZXH8Nvu3SB=8*!T7Dsoq7dSN~vq_%3+X1J90!J!UDF?4uw(}=SBElmr;#SV8I z%HpG(40URi2u)Z#2ApM@I+h$(vo|&V{`@m!z48qZ5H=9Go3ZB2jYSnR)+e@mQaJ%S zRiDyU7&Zi0TGFN%LW}pHoX0u`nPYQKa;MR)`k@#u^EAs=Sjm9#`ZRP_XA@mr0hF_& zf-;i}ob4m7UlWcOX_rU8mh%-9erpV}fQS6}SV@?8T!*D_o^PZ^$BVFIG>frcOk?qS z59alFb-Cyoz;RFZ(JxKz%O*Iz@XO0PGR^F&t1UYD{SmMkA^FZ`t!#OTg{tAj=337OfnfsmQIpE-%+?x*-NA+N&haKBNvv<9@*YZ91G-sN~G zejfTVeaKRL&Cd-G$LeU12m3m~pSjg_#IUsuoB9(m;RAm~&pYzrmh+C+Cw*!%1f)g| zK#>)nuBQD;0W8JqPX0jY#W!Mq0E+TiL!r@n(B){Mcx+mnDK}{iDU4x5g*kASTW9g0 z>r6-MG5QN0jO0-=Y@TgLTu%;}_(SA}Ygo*ZN^7@oLF*}%>TN6H;tu3awy8{l$QAHB z?C5{?`BTq;yNw#B_vWxUB$InFxD{nA-G?aKaP;aIci&+iXZ*J7=Ip3{<^r1VL5LMi z%Ba*|{47ug;(|r(U|m|li`!yC79Os|(5zgsUAjYRInmOG1fP=9^7sg>H9BGnk{?3F zE^Q7Wf?PdAQN(8&G0tkxm$JuFkiMknk2@C?}xFp}0Ed<2iMx#4%LE0YJpDdE&wJBY+MZ z{zR(Xo4GAp9U9JxuGyV8FUwuW*3@?i#m$+)w&`qp!QA{H=RJI1V#so)76m~X4v`;FB;p&_L|T*QK-odW z5$8maZ8o>hO4))0Rx?CP>{k!s*MpR6vM&lcgSUElP^r(lsfYq_d5V(qGK0jDBo~yZ ze31y``u;;Z-3&5z9G>z&P*LFsca;m);iLWxPfT!J@JUzMuUz4JJsiENLBr@PqZ;PW9z#Q<;J7MY zKTuq$qW#t0DPT3uf;93Y*6dyQxJ6zZ z0jW*Tfrds#BMtm)Y>jPgxI=d4BsT=Q*o#X`SXfxFtt*f7-Y8ElKfWQjmy5#u7d`MK z1qspMt??l2VJL<$Ks_IH5T@Y)T*(2DQ3r_G`2*U-H)B9AV37&-4-fq#T$-_oyW3od4Sw9@}3X> zlbLQ$netyLZ1s$lh|He;yF=x-O;wM;WbKN!t?IE5lMuh9;YbT9+6UobzTl z;RZMW4gxkr(k7fkR@|0|xOU8A+z=L)k3?VNcToIl$n?35uY1-%4w1P1OIXyvciqnze>APlL_NW*U#7CBe5;&B6*#Se&HU{ zP@Nn_JS13qABIkO)`|8+NDi9{l{o$mnRk!CWszN-pqKP&X9gnnTb>vqSU8yqsk|8e z7q~y(`}X9qE1?4= zZ>&%6A||>Phb^3g_)Bs+jJEU@Ua5l!2QIpSuf4-K%*CG0pT#&va&VxZgl!lqCI;P9 zYt>EE;D~l53R_&?)JA{$n+Gl~F0F(EGqaiy-ott*N4=ewtk}=r`nqJ0O(sA~ReP2O zB*ZV9GpnYi?`r>DO?wT5JHFBCkBq0TxqZYXV|*nDuURc>+q}y9V zT!i?uHas{ilCQ|glE4#C7emtm7Qrsr;GQhgh)IJnrLf3W6o2EQG-&pP8kVfJ|AMA7 z0}Tlmy=OvN^z#c`(1Sy>Ztw6#g;W#*GD3tHL)B3(*`U!re<%_H!j$JKVo@vOxJl!} z|7%JTq=RI$bH<9I6xP-nD(bacl4YPUaP=0ARH%=nc5F=-@u-IDk3FGqa7gfG^eDZ> z4r!q9=+~7)#@`n2X&G^G$T#Y#x_Et%A_JyW5)z?b5WY$cSLyaa4PMZQ73oj8t|I1P zW0Qcn9Xiez^sggDGy@CbL_k)JOIGYE{})|v85UQxb!%b)f(C+XaCi3rL4rF3ch}%n zxVyW%ySoQ>cXxLR>EfKPpL@IecKxkqORd^_uDQmV^Bu}rkow3`UTWh3*@L-rS5whb zJj3X89gH9%y=Zet@Mswr71XmEona}dYp~p0g5&fRg8&_TbD|5!O>|n_jKA4XEPRzU z^P7l`m0;8sw)n%su>=bTIVKukaKu-E(>!34SKYGh4`O!qj^e8&JWs2jzID!!+-Zhp>4uo$WL_DI%?@rnsdHDlB9+sRs>}DN>6g0m=x<`p^RCFb7ya5d zb_Dl20ybO#I&OA;j>`?^gs<=qh4A?hP~Y{&ooVL)S_JA4qHv%&;Pv}wAEaszXuf2X z0O|$3SvkRQ(>~Ns!kTJ$l$K#$*!V%8$vFHuv#x9Z*5Fz-A1&Dst!V7uN?MKG4Mw5-c7hJq;=S;!%y&)8`2|;< z>{V!JiBexJ*}Rl9m~7rXCd-yRJI0fmTClLw+BmT+u({W%FAUKF|3rMameyocgq)B% zo{lcly)jgqc0CJxlwKS$d!>8?#L7U4=|+PXi&ml$nfgX1Z3ni*WliUUNED9L4`zyv z#uqKOXs8m;h)QttcT#i+Y^-!iBJp<;U+CJ->Wh~!Y42KMw3E>+Ii&3m&RQbjn*t4+ z6rHDh9!MhE&Wx-NCO4hP!uqVcw)xzD{Uh^0+r4!O{`v1;JELd&^nfP2azO3~nOmGx z`wXb$ux#*YfWn>!o*t{@=nJ1I8r*LMW=eDEKe=3XVrn%{&-NwB?nX5sF{i)DiNIK1 z0Oi(?5RL|yj2m@6YjHH9QK~;c13)hEz@3GZFGC?ELGy=z#Gp$7@?OL9~uilZVczln_0|x?3X7Bj5(; zeZ?o8K0SiDWiEaXbNfNH0dGQRn7dZaCfJl!QIsT~DPU3Hf9Lk1x8@0=f85!2$0ZYK zf2ImY*MG}0eLJX~;vderQ}3#T```*JfAZt4o=^1mi(N)hn?DLh97Rn* zh_@2CPSQ9wwyXsxLx1!#RlYYQ@on#vxMRvNZK%vh-zkf!QATJ18kDF_A8OMM>M6cp z!VT!RllF?4?bN?9k)0zhr%4T!RCOpNyNK#69}F5q!cyPXXO?$dP}|619q*R&Q546} zlRNN(o3OZ>&FO;|T7XpzP!XDCC zWxP1|zN&}SYPe!S$ggC1E?btX=pN+-w#F9cosvfpbdl97F;h~tAD2{cE32wnL_SKB z)8}6(=tAVv+vN;GP2xt$#RQXb5z$0+ewc*@R8&MnRCJ7o{}%X2TJGf3oN=}cc!xUt zuA55leuNYP9lQrAIVh#6(2t%3Rkg@rH#r)XTE=1Y*6@082LCd`e9qANZp_>}lCSVC z&A~Ht?wpCJXObk_bc=9^3e~^cli$o{7nO5UUp+&w@WUIsK-*2=z0^|I0$D-d#Gnw^ zhuqaVp!!)s{aNJ;N;SPyfPPOH0LRfuhw2!B5GO1|yLzzf^1M0zl4(QR@D4A(0uUv= zT=q_tps4ZQa_{YEl%^<3QOhBmjC>c8j-30ve9*_{_e4xW>Z~){j1twq`Va5AnhG&I>cj_lV6L-upx znFa%C6>lcM#tm-m|0BRAfY;UhDvupc*!#hGf4%l?yNlcmD>Wr;GF`9jTuGA$GZ01d zp9S~MYu|^>Nc$eSl7HWi4jXfUX=l%rYo)yToNH$TgUgMmj^=K|@Z(C;@EJhIS9_Vr zx%YTT$ss8Z_+X}L6?QR47_qC~;l{ZF8) z6F3`r8_q&do!#&)^n`a$j?AnU;)4%j;`=?uVGTP*`4oUaYKsq36+3FWUbEh|^Ym5Z z_B=wYWT{_;(SCvsr=W|v$wb%G^vB^9oMT+ZxaWCL(urv~=O&5Eb$i$49&cQVMK9%f z5aU-BLQWk;gL|?>T{+5c2;$lKdH*$LfY=C1HE=eUVGOl6hFqyK`>)h_uidEInnjOV z@3wrz^-=^21D*LhC*OeHOI0UYZhX7O-7T4xAaI@xZ$UK!U1f|A$JfT)@0foIz`SD8 z*t*+;p+-$?WV6~a2LN??d&HuBbwQ3C$F-{FPFhCRw~4r&O*c%HQ*^a#={y*L=kqn0 zg#PmQW~n62KHqcRc6NvFLXCzKhc2{N-pLaV`V-lzHgr1e}^gN9q&OxrvUp zr9ShARF*jLH*sxPoJV>Ejt8WDzSBwmPLH|b6qJ3>8~1kw>z1Mc&iyYYtp$@=>DpyE z9VhZU>_4`DUD&V|qI0SGDCag{HDL%(#oP*r9oteY`e9m@y)Qz<1 zYPHFtY9q>DY`*^kHk72I&5BieA<(Y|Ry2C7Xj&%qd&L5bh*-LgDeti9ehQL;I{JPU z+ixq+sfN|V*Kj5B3eFS}iJUZxBH4vhTn`#jYNkg!r?ZCYr?a_#2`^o#704H;p(y2WAMaBW$Wwk_V z!5)Fvp6=`=MY^s5pxo51Jw=6&Ye1I}Eq~?O=w0=;nIqB}J2&$Q6deuu+DMuDFln~LHcD0b%SUaB? zsW=t&ue99pV-R`y9R%|HG+3WB^)ja`Y^<7GX_{MTnwx3zs8u~zy2QcVRM3S4u)LNY zY7X(Z6D@N9c;owNa*^q@b`+O}Vd7L_q3h(Vcg&EJ5D(R#e~tF7YG5w^`Ln8~zTAc{ zX=rPUYH%2cuX$u@2EvqcSqxtvDPV~dJ6!!hI2mrnI5Ib}wz6v2meXgDU^QG{+tN2P zGV5GAb&%)Lp&cO9hS&Um!Qatg-KbHU7#bU@Yt`#G3SkCum~G0P8yf2y8&m4YNq9XCJN0w7`fzM&bf-K{sD|Kdi@hY1&9 zY^J|G7zEjhHDyto@9I+q_LZ08x@%d{RnX$`$__Nxl}w(s(OkHW>Tf#yAm)1sF6)S> zsAxDH>^M$Xzfp!4Ou1`!sB@dlAn-RGYq?kd7tiu(@;qRtaZnL9cG+)~wM?@m2sM-D zwCovTV@ns+Z%Fv%<{O^%Frp^Y$5@9#GAUCz17NZcv8`7Ju)FBOrTaX%MM^HE%Q<1j z&~nr@L4X!gFtEnfc`agv6{#nb%e!+GsthBE?Ew{Ni&`bi$1*uj(?GDVN^0qufFQ@j zS$B7Vv1mkutnr%&To~j}IQM_xou7l-32LE>snV@`l^yMK0RHeSFz^d~vRx;U{u4k5 zD?q+Z6{g!OU+k41Ya1T!%`Z>qmxpFzu)A{x2@;3D@*gdgaNMHv7gx>OK@h&LdAaCe z|G;IOlEi~KC+I8rqEn1~>>53W3C^Cx^Y%7HL@`7-UH-P+n(T2|(B1^EmU z2XNc?kEr_W!f-Bj^!RGV&!P(g1**c364noZh?AY2{342Z|5Z^HZ--VUk4}6)^~5o6 zS1-_xAjp8qROzOqE4KvH<@w1`E^$RZH(}IOtGPR1{2UqepDbmSmCzBTd3kva4GH7M zG^s1@rUKPu-zuRF#cTM7PX(wpD1HfeSP?#>wmy~Z8|;T`1}1)rwyOc3t1^hGu~I`N zB_*(DuMby&YDjAq>gS@r!QWkd<46EQ_QQG0d*>8tAlWM8W->^3PfMfmiikh&;xBi%OiRgR8}MirCnIpIzIyMmchT6*p$G)IC(pCWhl7`ulabPsKow|YvaQa{g+gNt z<-~3pIc@s9j*6C=lFHW7(!$1?mV%s0XeA3zNq1Guyttlt%_C@s2$F% z^>sB>MJ>hEl>t#Eb5(+G_-V`Y)60nYsij~9QM03Grk95IcCP7*aXwqc9$4TjFhT3n zE6YRRDY;0k>Nr1zN-a*)Qqu&levpmhYiVUYw67bytabog?`=L*vW%qZD?ws6Ew{C+RG0 zd`-X$brTM0*H#-54tiAL`9Cr4jW)M8w)e9wE7t)i3}3htm$v$e z!NNKzPAB+nbc48}<@EgYKU@R8a>#5-7}zp}FQPhLOR32~h6=KA)rdhfLYfG2)VawM zHQf(4^zm=mUhel}AcfSW>H9r4x3s`ywkfVcLdHNFfeC_0wTqq&2tx_W1AX6M|8cHp zCcD7;?;R5+%757w0-vd#RX1qg)`fYdp+9RkQ4@+1A9ufew@pp*Xz>J(njrWCubdg(0cMxxHhUWCo0WlcWI|3tY{%U zf#bMu6!f=XvcO;W=TwYt6_4Kixx%tjA1G!DfvVzJxL1ghL4k7;9;83Kg0>~c-UaPn zyjNq#~|@eTBBg&AJrpRHvC7#^$_>2>-99zDCbSV zXwZ<|>VHX@xkcPY*D<6X-?|zG^g$RSI#p_) z&_grnznrlY33nOlx>sSb&kN_PNP&E3W>hQ3`E2w3cDsqvJThWzPAt~0T-d9$>zI22 zt8xaFm*YrE-a?F#%rc!f_r*mmQ$uE)^a&zCs4u@D*Q2b*78FzYoyQXkoTyI*f!|Na zdQ}8?@X_ng-I4LyGZm7Z#)Y-Ub^SiTH`m2>2%UG5g@B$$)(>Z!UfY7$Z3z-lw0i|N z(J72b*G4N@u6i#}ab;h=DeL*x25|32@G6p;Mid2v1^^?{r|?rx8n+8NbQ2@PprOW* zF)U>6kmyj6kR*Psl}Uy>S~{aEEh?!juqx+U+sUynVamDe*iNpk+c*n&8Y z&IcYrL`-A2t3yp@X0GN}T~zDkv?TheQn5}Y0EEPb>C5qg2y`;8MVZ%jhTq>$uyp!T zEC>w6I8RM4J5|N>DWQ7u@BS?My@^so$0%EZP=g!F?Y}k5B30F_6s<&*wTvD_?9YdB ziAO(E4%OYLhOVScP-+C&vjBRR2r!1D0lI;vT_DZ&uWDbaeRvRCe+`t3YudL2-lng{ zCzs}pNS3a`z#gcS+34D_u`@L!-n-oSRi~BGxE4R*-ZOg|v6AtSs=lB=|6!2a%C@{b zW&mBqrU2?6%w#ymWb{o(G_LFzC$WX?9k7+|UK`%E;sc>xz7YTJf*NjVw!WKNo}T}A zi@76Kq)JJ}W$0LU`P5=M$)z@#5S$aM%;JEVP8A*8`Z&&9y@uoWn^b`**4=eIxuhC*XC%vPrF zL}QdzVqFKNp1t0=RXlH75Y&EnyJ+&0|2#p(G?%(+zlKE*5s&@eI&x&=m8ENHZmzG- z-S^98?D0ddQGfum4vB6)vz@W|dv2z+Etdx)`Xq1d-`6MCXV2W&t$Xf3YcfZX4X4tF z&Zf~>daU9l#T6Zo(VKfiyiwBxIBc<`WIC=?m=%Tarnm6@B5W-1TbKXMWI7BDR#&v7 zX#-gxaxt0Tpf%*!Vb-kF3kYPezMlWw0V?~PcJ!TYpYLuzLrU@^2P^A84a~S?Tf$SL=zj8p|5P( z+eX$zXduv{{T|-%(#(ZAbg@> z=tRXU9%#Ra1=7HE2R!80>)sBr^4k{?&x$rY1duYj0|6draJE2U!iSlHb;Mo1k)bdV zy?Hy7qt38u7LWU_)*FA{hW~$vj2N{wH}NdU8g>ZaE1L=Kvj;<6=E*CQI`xL*$45FuS$;3nw2{&mgvei|zOw$dwUNcKdI-7IyS;q&(hV3kbJ|*Ci4S}o``I?tmgnk_h()&9Z?e4` z;?SgSgYItQ4riN1<65V?yLG)X_f_A=tyOPCus~M9my|2{6}*cSwJmuql{pRD)9CQ{ zpe4<1)jvWDfwczj|S zkiE=%d3J#!qBE=AA58XSsp@s*VGMz|2ZAgMR!`;PS1o~P@#Js6{Y^z)wIi|sSCMY% zgeUAyrHYnx5BlN?w$=%?u~u%F@c`ZJUl|Pnd^?AR^C!nEl|?uED>fZ$sj|^R;PH;u z`wWU1`lUo6-zaQz|DVW6MUUG-zx|bu8O(Hhz5AmiJM>JQymG^&7VbogP$1$r>7&|SFcQk~rT5|2O2RXg#V#SOBA`|fDTJ(_rJ6R}g| z%ce9hiHjdYs7%%Tl=giwV$4I_m!`&ux2}&vfx)qmivFBl3l<$oXex}`UC0CK)5)7v zOf)Pk7u!jh(~|EPgc71;5K32p517_dDq60js;^Svac_oVJC?%x_b5jH4G8=zvX}cH z;LG#T8wlQ5wD4UW=Ed@Dqyo}>&J#Bt$w7K~(`-l80#^>va?FFqBvT})fskCp3i+Wp zT!HI7dYS|D}N>N4o#FXYbrJz!ub#!)fQp9-;Yu4Kh;Pu#Nfwb}+!KCVL zy+zq;j=?z1fGGRzTd4gBiLYnV)0x0g!!P$*6*&dE4aN3#8Le5%%%q`Evr=k!(u}xly`Wf#HMw$fTyx$%9$J`~ zc9Hm98Bx{k%yzT-Tz^cM-sk$65k!Hlb=ikEpICojrvDEKZ)dp|Tyz6n%!;h;8JACm zTSlH`>ANafZ1&@;7J1~Xdds|(j;-ZMhN3k=XV8PYMv1g~Gf%GS5C3NmghR5I$(WX9 z99#a1IwG&2yu$wy_Wt~{W2{TttSMb>b4xEu&OeM-gM00m8;@gWSmg*{atU(=G!Iq_C8d+mo`utw1!vm zW+xj@x!G;sJ$~wD@%i~A1vl_A{uK6-8}1}DBQS+}%CaxEe=3Uwk@L-ZQippRGs#;C zH6IOySX!P%384A+lq%$Nd#~!VA57;9VbvQYMF)ob`XYzDNkD*XN{ejEK_t#O{(QIP zfueO|-dKN^o)Of>c%b3t)3q)_iDZ}O-BE=bxej|-pslY?ysg#db+S{Zw^+yDF8kAk z3WAMy)e8(JE=Cz$x`0O{V2jQA$w32fX<41 zgSm*nN;Kr52(7(6QG2eTD$bdO^RK0jdPkr-p1tAfAYz)+hIE;tF2$VLUVCesiBnER zMrWLS%$w~aM)?3t75~6(d?Ulv=(JBjZrMZ)Zi-OEZwZ$3mQuXcC1m=SZ=;4G0whZ2jvU)x z?&5}Q;#ub5%&$S7oH;**X-W6AxINf0hZc`(YI^y9l*n-Xy)sAnQ_g|&rJ*EAMvK-U zm{q+(K|F%j>qQ<~&`-T|j@osegCQfd+!TcFrv=|4#5EK+!UQ-!Sj_*W)@Z!x^ceec z?=QKMJ(?PlG=Jn~ZH644D7=(x|vv zV}Gilk@ZK)ls?$=HG2U&O~cY;LBN9jSgDcuE=$3tHka6;CiRYzu!cBd!*0Set_LvK zg#dK(S*~#kQ;y0|u3}{UGd*av+VfuAx?ozOD)V~Dez}gf5yUrd=Awi56A$Mtv-3GHr}X% zVR*%Iq0EY{2Hc{SJ#9+#JPl$iYjCxW(1_Pi;Asgo$Rx!|lrbEkN)g0txBKwa+rc%i z7LyhbVBG=*8+AHGvwF)_zFtGf9)_23Z^05&i@KQ0ra9^F(1&8o6bkzK$9y919!> z>`~X*twoO(pt2?wm%(N97|vPX61KYf5i#U7jHa>uC~@v^QQ4H|VsDDZ0PAdCL6wEm{Gw;Y5mE-zyGKtz*h z5EY~ycX`@+kLwp|#3HNtMeRuYx}<%aoreZ?#r`=$PwUH7i>L5#aP->k#k0qFt8Um4 zqCAc#Xldhs_ellHd3CO~m-m*pG*^csV7IE5TuGdJ+5|Ry~ zW%K5&<{H>eiWLgE9*UI84??UyPH6m#4T%diiJBz}tJeIRe^tMfhpNvjuhuB#$XT38 zP8(-2I9QG(HZ=NHqRz!);<`^GSYkpe#ziJ{>H3d`O3q`1VOXhE%F| z3RsUE1fgcgQ~)}CGG8LuSCj*F@tYQv4Q|~VWF*CT`G)Q9o=WPvHeLA`&Zir*CeT>! zG2$jVRa7^v8qUjBS8Yxo(_n6&zja_?h=qt6&>ZFXRUu-4Wt;rZXxOmg?C$PfZgiY3 z$;n3IaS4&4%J=5Hz!j)aSa8-Gu64)kc51b~r-{IG5Jn_oKT{Y3qdqRULu3jVIhhlz zUaI7Bf5g~gL-A&gV3^l)CusH>F+U4YEy#of5A90ISyJr_@uv-=XRr0*7-~q4Sp2d; zp+xXetDHWLM;Kt)LkANo!uMK$ufUWpw2FYfOp zA!;4pN|q^Q>bNSUvIL0$sj;HCYfik(LDXWo5Fw(t&=x5i@FO&mU1iD3v}*C5Nzod~F7#?wHGP|RQlBCE+BpEYjT(};BfpapjFb8M zfLNaxR@C%Set-QdA~L4Kei*80dZRM)y-Y@|j?FkD`{JtCu20PE#l7uWHo4W~**Bz< zp9H$i)16tx&>TZ$(1XQzPFz-iVR1T#1(RNb*FL;zD0=#P)ZjvCntK1d{OLhB_UCh_771BCfyVSKK0C_}@qT-NT2f50kxvQ^fT; zuNh>!K=R@F1QyKm-!mF$)4-$_MBMGuOBVh7$pgt@wat5Tp_PV#p3Y8i{>b=se*7#HG_0-j9X=yR&5nQO7}+_%SxkZ)y`0g=Ux#8Dj=&~?wijvG%(ff5 z3L(kySF@g9Hk;nlnFe0Xi8-ugsFCGYSWIg}n>NdlVQt3H^eeY&tJ9)VoZBpJ+J+T{ zed3(e{a)`SXaUI{X18)PO_8JNtWu}-v{^edz?Z{9P5LJX$54c3DQOJoxMLY zaEN|O9bfx?%Nqz)C0Ws*G?;n)G6t%;YgMh?G)2MBxZu+}SIkp(uuLsFT${aD652zV zd%S)O;b!4EwD>@&L;h9M(qC3KgpAYGsAkHX&8S>Ts!5$GWw2GJ`UMGT1t*Rk~NYZ1h`C;*8#z1HQ8`N-X1mA%yYY!*jx9E<6}o(gfaYh<1^SB2GFZBVHqoPjq6!xP&Z!ZC9f+h0jL2cqm(Tont#8 zu-rgW4Ca!2M1!Z|Zd@-@F$xXq`F9*|U}XepLsJv(Q^BU2TgOdi7ave|4CG|=&8iEv zk!o;lBPVxI#`c;knmj%}{pm*5>jo*S&9rCj$}aDN)y+(^0~LR@m<>+z;H_eFB8$%? z@iHmvg}$YtCRAqPE5bTf0f+!JKA1Y>uE~elABR9UP6w^hij1b)gBgONUcrz4 zlYONpzcHr>Sy@|K*;p{)Dt%e(`WVgj))^^I!iYdzzf!WO3B9g~TYE(=xO!><%7t!{ z<(}Cz{bj~%12i6}1c<2AGXJw5j^au3?6?>!$vPO=Z1Qc0Z_wxj9G5f_hbp^VnN zpBV}7q*2|{@}Z}wjJsOFDeHHqamTFokCNPuI0uuurlB2F^|x!IOnOCj(S3}KC0?WE z#T7S=hc@Y_5*gFR6RK4Tpo~DW#TJF^U&7iGl$?${tx2kvl@8$H+nwj^8^uSwz8Qw| zn3R>Q$0Ze*t0n7;t`Go@$57=m($3mjk zCy};~-UD5wsnus^*kB*>b6WPX6-pFcY)?ahb$@2u+n%)oAl55K z$6?jh!k~yq;el$bc=J(Q*vDPU4^{aVrs|BJ` z@9vv@7aq<{wZh7Bj$5tgO4s}8$HVhQrc!#-*xRhv+hk80@i0am2AfR5^l&lu?RqCx z+lhynmawv;7D>`yr;^L9t$S>?{N5oLzD~TCS(5h5Bo6nvqll*94E&K`&utPDOR?pu zie?_O>eXdhcAnF6VDuF*ff8u9Y7!2&iW^d!WozGO+9XoYA6v1VAu4y?Ys8HS||LEV@;}*RdJ=|4`wv;1O*HE zZR;20=e;(XKd4+EE5rhu&#DR1xdtpA(T zWpUKOhMHE6bRq^@co`Q4W#x+0^U@f9`Xi4&Kxx71>1vyT-8%6tCr3d$Iim$oH7d5& zW=rK(H7n#{$UK^UX@rd3mCIW|-;V?&RF;Rh*S>OD@`o|%@!`=^*Kw7vXI;Pf% z?(1KWRnFEf`;x)nzG3TdaBA_?(cFGhQ)?7bN4kQi)qMP))g46X+*?UulXt8Nvs&@s z5c@%YJQ+(%tA#x6G5kyRkH zL+vZvhvyM@M7l}VN0mt2gEmrCT~lWBWo0HBa$xgw1mWc=_t?j(l5cF9JK2)+dmLQJ z?j(IaYx_X)yZ|!+FdGQa0ySVW;|(VQI%-I#!;OuH zr!7A}|IP@+I72}}X|mZAE$dopmZIKbjlF6PgvLwhQ7(4GDF~m`t8*o;XK7IyGp>0i zKJ#aZP@y@PvPI;CQ_L1EiOe`El%poqM3M}yq>5)IO6o(;CLT&eIU^N18~a)BiWf8T zeVCQILt%_)8|MnGP%5C&HzQ$4uf~O#N?o@9u$t4OM2IRWR4(TyaolexS`0DL1R8XO zRiQcR0;PW80R0q&JQcX)_`nx#yqK|_FnN-G2zv9XxdjIePbPDJ^)l7p)!#R8Y@u+% zDD2X`gBxTE;u*0WFjPtR^t43FzP8@uH~290PP7SgT^xOh^bf5rfPE0=S0E3N)6tR5 zW|YH3gZs01(zs8JPMwW<&B+@;6Tk8@L1Hl8J^P1uIm}Zpp{B=;KY8TBFXTr91qd8!mk)2N}_juk>i`0Wy**XH5u3z;zs712R~sgp@(G`4-h3m zLK)O1J<8CPF5vaPGb%Ui2ZO9eyKqbRP~-aE#?+XVTtmh|UGtWYpdNgK$n$#x!0(RS zg^?$h3yB0&U$U7o)do^^A6l55cL~kj1KAlq+>l%82+^ZKz+$D@G$bmJ;u$9xnu(40YC3 zLYE%z^&Qi!GtL2uWsMCF2_uaY+>IYMy8N3w3xKoCOPs_*?eiZhJ%HN+Xh<;aMfZo( z`xkJ^T^%oxz%v-a1)!mTuTY;QJI8&$A#(@b>!(Nrl7z&9rqmv~-e9Hz?3S zsGmaB5ycOnPu!c3R`VX*0`YBXR$^IWtsrHZ;u3DlL=}RB|w$L6P5AC+@e`9&+&&gkvvY6Dk*2RD@KYMMKZt3vm+B^7Vx;XAUQ-V z(J*Z|SBhqHzQ{w+ldaxGH)5o4%@ZCeRXK+(4P61(Cg4UUjHe0?HUSO#WqXgtT~d{D z*mQIi?31Zb;aa_FF#<6S|8%cN^vI%n%Y6jBjxxmC)c)cGaN9V+uUXwT)%)gOaLImF- z0Sc5lYfck7H%?%xHLHZ87gzP|qC?GwJ~Ix~y?otZK&FHdNC7r)@IlxF6|p#;X8Pi^=l>8!=givIm?jr|}O_>?@2MZ;*JW-=AELLjt)XtR=Wt@!k zL_V8;I%|cMJk{>E<#v^QehVhw_C@1l@?zOzuU&|>%H`6^$@R~eE@O5lNEhVHlzb$L zV&F@lcw+`tOzX|-6-$y=#fi4;(8y&=W{005TzE4l(DV9WX_YOPy-Y^KnaUWLl#Cnv zWl45yU5F(q7mMc=P_o9ie_MXHBM74V_FKO2X4!$5Ks`Nfqsy}8IuE5{vZ3TUjxbZkx+%WrFTiP1`(SxgjqvH@%T&tK-%&=!#)CIND zpOqF?F`BP{*MDDNB!eR&q#~6<*h_W{`hL}N^kLkp`?VXVYzCVR?G!7)#nJRTl_%C& z?ve?Ku^riVFJx4rMieZo*?A>B_S-00Ek`}j{mj_b8;|}yz)MefFF}-a0|M$s>u98F zgqlz(OR!o;pb;a<>e`B!+BYJZlk$=$h%&gm#%(US4%1c)6vus40|}FZ7-n}z+(`om zdF<3^3j9eFiTb!0If93wdmypJgYz?*xeWtYok2Dbu24=WA&TOAd*7E3GXL>|i!3vc z6-?Y>+jD9KuoH_5aGgwAA2PdENcSGaoesLXxwg1?b$p;~T9Wl=*gj9nb_@oMYr9u_ zD|tEgIUr-oE>73L`-W`hkHs~mPYP2&?jr4;zDes0`uZ)8#6X6+ zh;!dw;AkJ@YlrCb;aA*gYlWiK_L#){i*n;S+QGH6F zrPpZca$U3-VTZqc%w~Ogu1Q4WH8Ir%VD4RYzALtae~h=i@4YGG@AHfzXJ^N*;ha}=$|ycQ z`|zl$$D zLqn|w49ji_IZX2+XXhh;1evPvRX!fWV>6$Yl+<<`&81wW%-@pITBz*j9xCGrj`oY| zlq_ij&P@!q_}eFky9XG}TPlFOX-jv-6-h_hjPrn36@;NO`imC<||Ue|Lq) zbGQhB!DsDt^<>mSn^(eQ4EVRS`zPF(+==F}xX9t~7Y=mUqi{-Xg~}jPE`5`S9nc z-X6`}vAmObPMUDUqDDSPrhHWU7Aaj5KThHvuw2Ru3SVSc(F;RXsWRm{P1vQhv*m>j z<|bXFU}AOdbEgQlUwL{DmFG!CXjjN}B|nzYnS+N(4JMs3nt2C+wa><)rJE41{q+i=Q@(8K`j`~w zdy=E;8OU^u?1@KU?CR}-R9%uX2L9`Bcu3v_t;xf!*)CiT^NUWXh=F1i^ZT0>&C$0}V#;2*SY{S3>`Ves(^)!RSga+ zT#8iTT>OpDE1-4uOt5 zPjKlQ2aE3OHE&2t0{`TYvlnsM&0!U!F}~^CDXv0Q-rz(E_RT(K--8jzYLMGttWf7U z&_tU2JC)HQrq`RpS@<*j;RGz!{qh{5stb9TiqRw>>+(VcG-a1VPv>dr5!@m%(;jIv z|2ogaueP0h#;<$D!2cV6mU`T_XSlOY;-fcuz8rOdrYC&&f3f$LQE^0Vw_p-N5(pAJ zc!E2@9fG@CXe_~L8VK%?1PdOtacc;!jcagscXzi&nuh7*d%wHx%$l|CUH9+I&#taI zRdwX4bN1e6Kin&5mQG)5b)REioi4g_@Ex>|XXX;oyqI1l{vO7L&r6)tXz`q_-r%wr z3SDbcSosyf6OgCbB%=OONN}DM8Wr{WmaRnC@psftw33CFS7T5*_ngS8nnYj4?M6#$ zdWt77_Hmc}2d`)wEoJ(fOIu#;pva^{Y_!X9WYQ)Ee00nwr!RKV+BeQT1)lw#MUNv< zvsu33&GXlKH@)b|Sny{l&9ks{F#+2a`_&eA(Her+w|Ukb?bjzvnSO#Kfvbls7RqOU=7Vy?Fy4KyH$D z|8^b2H`Sl#%6ck|vuYFjOG`-a`oIqx{y%>BHwXI(dXM{(F#hY@sVpu&iscp>?<@9rPm4p0m1srmGT?tC?EoIa&vy2ZbL!0_r+(Tp%MFbDCzdCH@Q;I%7d0nvbQaqu?qo}l<@9v0nX0yyFUnQbV_d5 zZXPJXKCO2LbDGmD4A6P1M-LdgFxaLNU_()Il~I+I{7rDzmp^uDZcJu?pVO79|KTUG zXu2%)ldY{SFb)A}#?EmJ9r42xwV7+EF1n@=ZQ5Tr(J4#hv)PE3$?ba({goy~C0+)2 z^36ytSEC2-H~qhv$%wC1u9}?L?3|b33U|+JrI=4?%0a*4Er_n*-MRap%g|0x`@eo(l-Cvo^uGK*86Aj&t9*RkJ-s@dIeH?u&964^qgivI1_ zvbg8=5v1I}g(VG{+h%JDYBku#I<{AYeoT0!v3ea-=T#59>t+(q4rR%0WuU06q)k&V z^{%d9`Fk)_9d=P>PlnfU$Em31v^5!61!ys{2Wm{(WgH7QT^r)2EcBZ3m>It&+w-HU zxastELw<0a3Q2%WHqQY9=u2NrTcX$t+tf*uuFfXBpJAJy3eFEzJ^bKTVTgCa1X)sDq}=(&S{AK*YI35 zt4or*&S8$3H| zNxQfZ48dxNEY763dcIn$`;5mSOSmLZZ(O7G5#i^2 zqZ&+i$#{?Fq0tld;KsnMmRRU~zaVL5rtWTdX#IoA(8Z~ddp<@~W3AWrn-l4zCOYe( zw6n*D716XN-l7Co^Eq9VhuWTKdIA763%>E<>gkhFp&sZK=HKOZ6Av6G?ygMOgn%hR zPljKZZn)|HO zDwtJE6W5Qok9Y;YUgT;ihlyG|&csd|XAMMnHb)wg)H}vRh2@ov%ofOIAMgM$=S#Xj zXXY4ST%3vh3NLc^q?sMy`FcOAE{V+D+&i%=75y@y4%6xE!h!Udhbuc&UP+K#&{p{c zT(2?P`Czd^=meZRG@fY6d~YD*4!7)K`|X|= zO~sjBk+znnTae#wHCas;aC|SqLf~o_v=Rt6O}yExUK51~d!x|%5h=zD?3=WteQ?~g z8ljb?SbZh15~M1S)&T`1hc}H!i2J!2y2R#HBu_?MV|yQMZ43COuKXNpBMQ9@4Z1n` zfy7uT>L&7ec%;ZP);HGI4t9i0uVT@&)bk|#3&(&5*^$rdvCdCPpc@VaGVBpz)q;Pf zrko~s^+?%PrCt;z5IJQRnQfr{7|hAtDbCpC-T2C4Z2s}(8=${DfQZZKM%Ts;T>D9& zC!wyMMR-IDkj!0$^17qtvAz@ZncM&$sRj5xW>OHbNW$r3n>No>60yQB^0_Ln6+Cd7 zN$Ul~CzMydOzwLqT{cSp&c#MIWur{j98kw+wj1E0YhIEt$OUb=1SE)0Bs({YfSx>Q zCHM<`xb;2E6in@R2Ha$@rwKV6o+70;Q5h{?FP8m(_C$4RB&igcsiR?H@^kuAM>CsI ziG~dk43wL`jF%~jLGN`Z``#V{0qM?-;NkU_<8|Saq!9|0Va$A^{x$bZe&%VVL~h(! zBKHg9pna#k&bvELs=#3)#j&$sh4){6om!!i#L~wPR6rjc%C00^$b9_#{_R%78sh34}L;~|`LJp-I+$3TsegfL*q^+q3W>9mUCi} zih^TKbUn*?*Pmk$p#;KdHCWjh|j#REqBz~tvk!MO$JZ5--YoM z6_v3coq5!osxFbNRNu$PfL%i?Fo}R9`#3fE3+z~PwYT>QGf1QO`I`N@nRKu->6-<@ z(a1wvxBE%#C##Z308ix{zKx_l2Tdx3z4R0nUweADpR}Po`E!EuA501fFJfc;AA*XT zZf31YbQ49+IwjI;mwru#B{~Pr4Q}?Vo-LW$qsB;U9{-vs*pJMeEXb=TPeeukQ|B&B zhP?Hw5@#-1Qu!M9K?Ey!3J%Y{s~H%Cr$1wg?^nOG$k)UTc`l+iy5e^7t}vuKCo}UM zGEYHG4U8`WA#`S!wAk6s(@VSZwd#Ab$V*uoh9= z*j{MeVBlsiflS7iSf>8@aeY|U=U|269+^~y;l_TYC8Cn7ODsf6A~2Gqtm36u=)JKY z;tFi+EAF=<@-T)peLuLnI}?w#Ft zExKx}!F;v6al!qo=eA@bnd(1Vo)NT|zFn}qhpo0c?`aqq7(|U=32Cv#_MKl`lo>V# zX*^Ds=4?vjO##*4doBwAkwCKSzg8xPuH^ILkM(y@ z`f&*Xx0({Gzo4z$cCn}8)mo@b7M{`@pY#hC=vsT-?^E^S|kca<})7bF{si!r8Z%YJ0uv^wozHH7r5qk5&yWKpABZpJ9& z@{G4@a{J;IRL;kCZ4Egr=ys7F+k#X#O`U zW6JODvc*`p7s?2)K41K0oHFsi`1p9_svl5d!I^|jDJr!VL3Mw=HK4Ap&Tyk%59ua- z6)2&F>2ie3{K?QhX3Pc-Q&2-5wi$huX=xxM(|vU?GuC1^o5|ezaK{X!kCyX3c!Lyw zdi@(1Da#jp{L2^iV!A#HJivxebQM-Z`I{w3Ds_3|MEnFU9ScWh5#lzNokMmdY3>bK zRrIO^)3cPUJhZ|fCdlOD?M}v+afs9pg=OxITFD4;&HK*IPG;TG%wE~KsA=gl>=oF{ zC;Tt}z4oB55Zny`s7lz#)eRO&>?L%l?vJ`M6q}^E#Qzx{F4Y(D`+*^5#k~8G3_w0~ zKIVYZZ+}Tt0%!A)k|oWzP*6Yz9PCdOSxJ*&1*bFLCRW@ICH|hK@$0Ov1g^=!fiW~;c?%$ap zk`el~c2iSR%~wl*2Z7qZK@fR3Q{-&DnTkiN`y4mx9D=C925Lx4qx!dfRDI!$sD1IF z5UH_MP*50s`ur}ev=vS`DvspsAZiR&@ovVipFCN{`}^K2(FiMaJGH&B!`2@5YoCw1 z)~6}kcV!d6YQeP9YfUuIfESxfV#a@i&|hYw@8mCc@q`iudF}s1V_c>q@(pq|vRaY< ziN1n|6>dnw%>M%zUVh%VxJ3qqCzSY}*3#_dk>Gi|zi)uN#>K_Oim?y{$<6qGWG~#! zB|yq_Y2hdpJ%_TV?%v4NB7_NfUmfGkwlirF6D#$|A7-9zXDQ961H`EBK+jYZ7m=b1@%h~ z(6Z{9PbI9jk))LRvMF6=l{Ma@Ew!}()@dEft0zs!Inb`xFN7brZR&gsXZEDS0ronv zYt#Ag+C*__Z-3!VG8x}WF+$HNHaEAq!{K7X%6uk10na>A-+p?`Wb@a-z(5g$!PZIS zaioQ|xeA;3>}DO}eO10dmq$ERM-MsO>G6Lx#K{Q8Gl04U(9^=g(-R;gV<7{OK@BvD zPf0Ljb)CF1Esq&^%|tBNQ&L;md$EC6_{o067cG~wHWU#}U&R`bnsZrLi|OvgRm8;1 zQBs~RXMx7kDr6zVGQL>X2`rs+fJ>Ik$)SzS{lKo5KQ;RAdjgaI72ifIC+S6+Qnba_ zUk9L#}M3Or7hUtMkhE8!#SN^)w>}*Rz$;|Y4PC`f>8J6z5 zX*d1T!D1Z8IpK=-bB%X=Q)ZoAJCl`jEYb6eW6Onp=6MVmRgM%XT{!(pL*!{g{q3DO zKrBKX&p@ftF1j{bWdKgp&^G#1H{k-wTRU4jGXu8xu1y6km|YSN=Ok0K#7aqpT=3NH zTg>=^+_@ZWpi<3?nmsLrl3U^iSg|}iUe;4jbFFC0%^#DS-c7$ow$ROM8eG}2-NPFA zkF7l!lLm+woNMxs6Jn*G$24OXXV%qkH%&zM>pofQ=R%}e*PsHzxo2IP#T`@ws!F9> zS!{0Hdz->o0Jd?SIni}%8y#jfL(r5Zp}$0djky2J!(e92xw=T{Mx?8|MZ#+jEAzm% zc^XKb6#a}^U8?T>H_^We0t&N7%8$@uhWCZ(MYT&-5CR$zPh4vUxu6+pI4~6HiyNDmp#6z)v|1lO;?~-VTEJTVtbPhZt4(F;6Zr){6)m+8 z&x5suMPPeELcXJsf`JCm)6v8Lz^D$Vf|OwDq2Y`%dfeXT+a8rz5Dr&Ngrhg)HcznR zS_iQ{OBBG)#i8LQ&aj-@%tM_1I44Dd;_YI4)pe9=q5Q9qO03=_1 zw6dRzifV%s%C!zjca11CWF|Qcj>;ZerR|cYC!8!O$v@qCYFRWte`$V(qb@%e*hNe8 zy#OMwmy$si)lEe!Dhf?3lMTioPwg-6?VY_G9OMkm!NioX^#uZD*htzp$$pQY(fR4Z z^hdQlOqD6-pVkDTd*BHYzRByNnS5Qb14-7q<<3$Y3tBQxQqAc6ZD#SiTe`>m18AWQ zmJTKZ|4L1d)*H}H!7q-J#oo|>R!*!#HaJNeVW@ZL|A{6~lw;a&@&Ps7u8_dEj2N9^ z>x117p(NRmn70h*tnGudd8kqqZTXfuxniO0341)WA!q~r@MpM?MMZv?y@aiI&}!AX;+gzV?9Wdz_fx@CWo+#4qXNu1 z=6}n_5tAB9X(P)#@VKgo4&g>sP$Mm(5@TByC1IGTsCEpgdBUBLOHVL9`llw^F?OQA zo;;0Q=8Fi4c5+P-M;hy9Q(T;hjFY}s*wZWK%78+kO@c);@2WXt9}k&VvFqu96IHCj zrm_`F_>~?O15|w^8lt8A;iY9K>hhC2&cgOtwjy|He^T0Ksh0?RyMKoORliu0d z%)Ch#^?aL=o|YCLpOl zK;XId4wr+4iBk0}MW^jxOkEtVqi*--xr~{3#E4R5gPqWp)%<*TcIe^e=H(%vAs?;e zLPcnUoFo`bYntD&Y3}vqN2HhOsyVu8%ur(Ct#ZT_?Vk0X)k{?hDcx+zCd*1t9Kr-7*I+J&+Sm%R4?I0kZ)GS+n-01s@{(oI zD8^cG&Bzu!+pXK_Y9z_T{<{O><=o@TQvl3T2W_<475Y~BIokNND>=`d^)n-rBP)B! z`LV;PAGwA+3lA;=%vlWY1vAX-4$4_&4$BZnO%0PjH*s@wuabU56UO#W&O*grl0W}E zkkRLeo9+0Mv+9SBG-w*+Z|>)rHU?7>A1sX`WU1DZ z7r=xao~%ygIj=Ap+KpW6phhK~7lGU$Ik|0#70N8#;cJ%hrU0|l8@-|?I!-1W^1UjaqJdbveyfIIUULMNWZTO?Tj|EnY!lCPyMCW2;{)`xesz)jGT8qh&_Qa z@a;PgOo-~)w?XENiLniB_|PV@Hx8sm1Q#MO=PD}pXq~Y#I@Wu+w}%PMjg&yB6IS}D z($YTOT1se~Y{B%0o;|Hl%^w3{DuukC&&IXlDZqN{(nC1Bo63Hxr~h`&#b4;oHnQ?6i&%nzIAN^hYXD)t;XWIr7g71oHZmQ zlni(z-w|;*WkVG5^P`70@9TCavt=kUJ|#Tx7f3CQ-6|0lLPKl@D-xd8vqoP@*}(EDrFDK|c>s5tA(iAAlxcC|SH3oRk( zk+On`xwwp{r>Dhx!yHLjlz>Xd}RSHR0^+|igdr7k|c=9cT%JS5!_tYxTP_15Za#mg_5^F$wPHgQ-zY_4ST3M^G zF2Q(xYK4YN<@*X)qatYGAEv5gvnyHw zt8ZLfl}wD@mxG|GQ_wY0&F`j)tm1T2Apw-7r2vV;W0VSZgxt`CpAbSfc+8uI3 z=HHbFa!IK4cW>oiMcX$n@qb|sDW4mD{;#!=vNnF?>h=FW@&B)$|Cdf-KlA{Dxyt_2 zbz(N>OThd^rxjt4m->c=9V%lYD`?$XrTg2Wp5`OEgX*VG z8MFZ64=6xr1#$#k>mvu3U^3xiR2%nM5<-GYs(?TC8 zQ8JbvKkJIG5Qx;v{r=FUaeHx;z425scFJVDU(D{umpmYilJF* znL&uUm2g&Z?b?&oe^_;&{g5yIy;VFi&9!l>F9HdLx;50>IwA4goE#c0=zePy5y2?!;XR(57;oR%}2KUs-MzV=|iW&AMdzS1%9wu1?8)v;l zF4xG+B(S$XL7;RBh!NWH}F_eGmd1YMb` zb!0~Lxm@nr9O7V|t|v{JDLkGcjk^!y#6^&PX_@AEb@V@CWdD$E9ysO;NhF*( zRisOP(E38eHHt!{|MQ1QAl!x<-IoW#4Ln#c5XY1J(P44al1jyQiluypv5dd6I5!qf z=d)kh%&g@JnKP;2PQu8?P)2v5gNo-R^qHYoPn+=;#?NY}wSgwHA_lZbN`5B7mcj#d z(R0$$kbL=Fogp+hYC(C%rAiD+QpKP$DM+x4;VK6#>neW}=xg3HodK^9m1?eiO7>hc!$n>3B@Zb_qaZgsBK$=V}% zo(2d>rl+M26v@3%IBA~B4;j)t2D@}i9E z(jXsBRfod!g>n1;1?}6LcVCoF1IBxXuNH)?n!JY9ES=Dqpt+6fu z=z+a-Sbm7*J#)1uYVa=##Om>qmpm#zM=}#6FIIyQud?VOhElA~?b=t$$QB}#C&>yf zMZW)ZtSNC2CH7xk-|)eka)d4 zX%P2Eruh5{L2BkGHgz<)T#hKU8A|hn=r{mGUGm|*RnEX5`8B0T_;6XQRXBi=S?pnL z$qU;FND@zS`1Tb!Q^+d^yw*F%J8UpjhH!teIWU4wfHVWw<8c|1h#o3eCK;@@yDQt% zMvzq*T%o7+z2A&euD1ZXOoy9>R#NW_mOME1})@S!xBN+}zJ;N0^*o|XH(S0aB29xa z7?+A4sqjv)lPvgUl(9pIY1Qu7*-HUJXl~v#&77hHtqJ^tTDN0qv8J2fZr(~r2JEA6wwZTk*beJL~%o)5;Mpn336@vbx|k#)JnTIFr8Twbm`d83 z+op@rGNBQZn3I>qyXj!(5mClPq06vv8NpYhLb|n2L2@Y6ZhD{fyfPty(`I%>=K(N2 zU(gEW*cA&ZEsU<(KjZ7cpseIeG86jvbTta;qQc+TGwjQKHdBa-W;tDt?TTq!4pVS` zs#{w7c2?HnCc@Z3*J5-=6k)xpD~hyo@l5Z|xl2oS(h#jc3ov5!g6V#@2km~S{pNEvXsP3*31!>+lO6p%rN91# zzi&5ee!&SbkWFYLxrpm%#&)U-*fbX4MaJN4LCpx8-EGUN4eL@Cgq0n1 z`w4hjKUFlH?w`XzPtx$Sy}Dudu8Gm!&tIAlbudm1h$Y6aF6ypV7K>TP$-95c+wRnN zhE7F$(7mntD7-F5H)2xdH-3ie1@k&2Qe9MBa8&$CtyzCZlEGFLdTDDqg8uB9v-{Yx zH5Gv#G1kl8z~OOtX_c(4>0?{Gvk8wskHnhVAlDSTz7r&-|0N%w5m9;9C#pMgTOnoW z6g!r0N}0ArS;?{dj$QAN&wDL!oUmxMmn9>Fl!8Gmy#E#{9aT#~ddR$KJ)zheiV#zV zrL~An!EV22-JM0Yp)_NQl$gX^Oh+K#nYVewOwPZ46RnxjN5EF_W^Rh>`+(6R^Bh}F zW#-m21%OYr)S^)M51TiF|i>)f4PN6gywv(5K@kH_BM0l)ZaZI;Wlh@G3l>svZn zTV;VJ!e{UWzeo0{YN=QbV24!e?M|-6S>N1Kyctt+{h$Y`urM&xFk2U5pf` ztZ(tGrAWHP*n_UIjG{Yuh! z>T?E-!2wZ}lq3}V=NGENwVEDvhE73I3*;rhW6)SMZ}9D)h@Qzht%~FAgl3Ne1mIHJBFxlj2Ad45-hp1P*(m44lA+;NB@ zI_t#{>&Jr;|8CWEQCe?}QU1r#2tI3*5~HX}F*;DyXYaeDBVU9$S6WvIVFT*XMgwRSG>-st!}Jp01l zHeJ|ti{N*E@!pwN%zt`XYBU15x7Z$3`ANO5a^m{o3Jz=Ol$smR|R{9~+cTY}&Y}fJ5qgb); zL7SVOe#qrbIh#KY{sfTEvr~Ka?6!&b@t`jJ_TEAuP?HsO-M2~kGOpZ3uX@|Z?3nF- zrU))5PqKaybyC4kq7j%_YEAXzmu3QIS>~#-B*=M+DzBs?AlK*gC$x7*khESTup?so zA!2cX-+^7gTWrpcZ=+Fe;^I&jSjD8%mt0{Sfu7!Iw$^kT21csL1+CUy3&TB33W5h} zXP$Q>b>@)jE-j)8x6OP32O3i^#aO+O8gsvZ>G|D56(L`G$S#-ho)6>_f4 z341n61^jy(#h&MEchc4-2<|?w^J6Wi0qC@aOMgHq6DRVyDOHHeI~BI;RTk8nU36-Yz|q zjhOjVjO%T1W7UcxZ(u!_^u^z2__Oim;i`o(jGW{lN5SCcB74NUWq_#W^R@1vN^O}p z#rmY@_(syx^a(JFLBrl)2eZDVN)i{B`(Pw|OAz|h0Vhi>YkTp;GlH)R*mx-Nn9zG3!((E1t>8*PFZ9@BOZu zG`l7iDl=jn+b+aJQ)-XaV_y>O-1+QX4QXeEdt0sL<7o0qZ4n|Gc%3s3LP-iL_NNop zGNKIp&Q&^xBt=ogGF&SEm}rYE^KOOVY`}~>PB$Npf>og&{plkCwLUW=!k&Ee-l`pS zBAxHyi4%4TKB^8VuDJ9^v_VJjZ;mrr!raplv$Z?@_NDhGpX6xtOvh}hx-G14wKLeo z;2h}zUJWZ(1MiJbT24>fj_CESs_wnM7<-HE1Vh~@y5iQ*Wb-_pdq1j~*SyW$q=t%7 zepp@6F&@&;6LOx+w@x=!ns*lEqPNu_{d#gMR+P-+rW;8r>{DIWV^h?h_eQ|Mu6LNEmq+zv z5N(9>&fs^ptR6ezmO9gi)vTvPj_%6YmG-hef)-tvzm@!dFYUgSXk)pz+x_;`4=bz$ zZ>H<;w(KcN5Nm6@7J%i&^mlo?r_5AJI%Dshx8T7fHqe~4y;*U#1=CNqB<;(@rT#r^ z_2)D&F!{yfUF~SFHVL_a>+gj>zv5-7D2$9&#TZr_Upv>&0XL0Pg}(mzCT3gjugjJF z>>=an2BLOUR?i>RnZfgm--9^nY?XK%6-_~0a zJXN>7m1j{8m0T*1B%U8&Gp&saTb znnjT&L17wh7U%PA)2KP7!zu~=0V9*C0hJwMnd9| zR3M2#{U>MXBR3-hzghQPUSL3PM@milfYz?FjDO+z-oq#(>BOl9grYgUm)V4kC5@NE z+tGbDXU?l^2NF%hOJi#+=wTw)d;K!we99Aeyu@=s9~cm*oLnthnp!&c#eT+yN5Nn} zzH80O-IBaX_sa*S^JDU4N>L8y^+`&$PL3^r^Gyz6^f5U=#M;E_^fGtHlzG#$%1M2B zh%%3DF)1+Cq*Xani+D0SAXd@RPC#|M2G~oiZ=ocVq!u=xsp)ibBoh@tmZt7a*%%Xo zo?Ep@2`;OTq`*~{LCZbe{2hp=4wd*p1gbaaQv)PB=cIbs>;we_J!hYDt@yz>W33HH zqo8#Ay1hOn&us{earNjLi+bj80udcT&;ze0u^1X$H6o!{v)6La@Aw{ zh!daPBER2*w}Am!VF*PLOj|9{+F7vqD9`8e1xm6l1eJumAv<)nvx_MMG1}r^SyuU8V)h}knw#lx)3M6%P{|Pl1C6?s z1RlNiVkWmi0R|War*#BPSNqJI?Cxf1W=vWw00uuDfW%n7*}k;Z4C6#))-2HWMlY?b z4C-H>q{~2iyI;vg7-cJ!E3RDarfg&LHA)HK;T=DCoin(V*@-BBYbXpNg1dlG)~#oF z1Zb46*>kfnAqZE3S-;Jf5h1ujiS5Y&M;b*sU(Uj>D3&G*)z|Nj1EZ zx?wi2tlX?jVd6C%z9@gp{tP#PP4f;RDCEvjpKTT>(Poz>CnTTojE}KQ+AY|VWp&jA zqt!@W>YBo7pUC<}%$B{&j4wCF`QzLEbol6{--l1IFe$2Dq=f)t`cPKw9{Q>H^70Z1 zLF9mGX=sp|Tm_ohvO@vjLe@(=FcEE}%~DxQ{$8E+#rn2Q*deG3h8p?!CEfU_;m1@3 zbV&*o5c@sGTXfd`i&^|4=p&b5&$CYT2^mxFU$LdE$*aU4TvMaKkLM`YRvIodaCoHP z(u@x(fF_~0KR*>ZlNuj(b5o{+=Iv)yZKyUn9dqjp> z2HKHE?KxsAi)(S5*uJXNwWDH3Hv(MV%hZnRGV}AJzmXNM#r2vy(0zJ?(pH%iozeG%7^@8E60$YF+bm#<{qH_s#>oHEenO&b2Kx{Y0usLDbk9Ay4hT8J+boX>HCkTNIwq0(*$H$NPvf{I%k^{Yr>RU|H8@AVl)GK+J8|#_8XPhl{UGr- zsk|mTY94YGrck9(-;MCBm-<;Mq_Cp$PCL}ep5or_Al{QM`SvwgSM%LBTf(2YB+WW> zgqa65Dd=fB)Y7ul?AMvs9Nt9DwR1?U8W{jhM;=yfZ(}1*+p)P;&Ny#haoxXjS{I)# zY-~T68>dGd&)9grl4gN=Vi`pCnXQ?zE{R#hBN(r#)?u2UEy8=QS!%5^c5qa(%x*^+ z{7bS)0FLg}_kiq-+1XUla-ByZYAggFfRx69Rlcm1XT2k;HU(sd2$S$vDQ+g^A(py0 zyr!-nyK1fz)J61(RllA0yK2%Tl-pz@*IuQ~Mg1AJn|GqZ(?`s>nON9J1AZfK9 zXhZHZm1C(QavT)y zV5+?x=%1&_Y(>S9ocfw^i=#)yu$SiRSlgeA-z|bcOckqFzRk)fwl)94(K3JKV^5R3 zY~5NgDY9zz-ca9sfV-Fe$Q#oi3ZjFynT%iTo;T|zeHY`X$r)fJ|J{$F(#vRst2kpl zMN5BXL1u>`a=Gui?2IPRnFcM(ygp=SVUc>@;foo?zP`>`qvU!E47g4;XKpnX_BoG9 zlQ(z9BG)z20T`((nmelBL6R|;DryRws*0N;<#x_c4S2(bwjiB(+*)98y!H$p>6~zu z+(-K9g!uR=+&zf`vaM-u-I0h^9fr+kkv@KgYNnxKVO}F+eATxCSYUR%aeENf+YiW` zQZ+&t(HLHSsY7<&V_Gi+u~xITp^4lYlG@UGdL9JP!#HTtoV1T;s!+opwcuZ~+*IG& z%$(lvA~(~izg0Tiw-J>~!O2om2^HHrXZObzwf)6denPG#4Z1%7+vTAPC~z3RJM_Sa zcWf&{>}N%k?IXMEKUXADS=i$*zP%58Wabw_hHu-v-ZDdIe$YXJn8iF}MIOm^ytBqf zO*SV(whzsV731VF?)pu}@P7QB%83ZuP?_&}C2-R(}D*2xuszQpUmX{DliL)%>+pT#GtSyE-E_@cCRM z(lDkwlhN@+;4X;Q?Mvk-Ml#^5ljG;n!mE`#&%hOC)1T5*yai?}i{Hd0)in(bygRT& z2R8-?Hk*RO5JA`uSLcqz$6U9KUbkksIsuh_&NnSFi@nmzrD990Z)`3nH%-NtH++ZR zXGVWL%uT@_wIFSgQcw~mI(5sq*i&+fHM0Mpp>ZAgR%Ba(Lza32ESurwgTc2{sP4#Y zv_}-izFD5A)T84y{XgOp101RSMYSDzE!3Ir{0r%#fl^fgPZHBDoG)(ZeL2X{XocrG z)}8UWhi_lMy5E-mZP5meu>V-jj9$e2EWgSw#e65q<*DT5scy~1_CP1f;oK*fB`gNv z;o)J$HsDSi+l8k#u~Ual(zsUfkx3%f6raYbve$(3mDRSMp)S79{K-JpL8-2Socu&E zMtZXlu5Ma|SHb`h-ZcK{RA*-_g)s)ebJtf~+)l-spp?otYoy#-=y?6rmSxLpGHzdG zg)isc*kxBU{WMf65Yr5-d=6Ap)aD(lC|lpG=su!y%A>?%v6HvTYEZ^b+wB&H7OnYD z1VTg8lXuBYPBxOFz#)4e;Hm)_S#!xS-x^at zE7N&JgL!t*lE4uPwYjbQtFY4iCsf-F?+kFWV>lV|VUQ5qY(;QLDw z`~k3j2??>W{ubY>z+v)|d`6Uh{D4+pfI*g;76J6);_*iHI%L9f zB$e>+6ei=O3_g7^9lq#-Ez zAcYR=+%UQC*Vn>q%gop=TVC$i@%8_V zZrqMcK9xk(P4)zxsYRIwP6lllzeGA};`HE_zm05mzJ9Q+F+D@A3sBs6ya#7`*wom< z*Mcd14LD{_T4i257`%T+d%Wj>!MB``yS`!BGFhhDB9!t6_uLD(_xgW)-;nB8CC|}> z!*c&Y`Iq@8&U327jbW}ds$YC8@_W~m79?RyDn?&pjUgYBq$>%6^KI5?XT2VB+w-0) zH%e#34ky)s$(k}q9{OFEy_4!P1iV!3PA(n}4?%RX@;=1qsAD0NUK%hQ&ba zffr6J-!o6a5&nVRx{{rsxH9hUkjYy zTvg;D#IA*LCf>!P1xh%$T*AKCeFrPl)y>+9M6M+)R8x5`4j}Fp`0`9iZ-pC7i$o6o zN5t2Ml!NwgKPxN)J#v%x*Km4FCpjq$x+$5enNoS!b5Zbx<@2X5s(U-rb{0Dhj-v6RwW|d)Q9= zTGKp^cRDb^YV^L_%0|>eouK1Rp-dOlmW|%qjhA0#)aC7DJjM0M>zOR(|FHkI_fs#`cm@_uQQ!O@KCv7n^L&=l8e1qL6ff z{VR@p_~6o5+c-$@gSE9e_abG1w(U%hBdoS=mJ}6(kR&5 z;JZ-Q9poNBVq#)$l874;+>rLnDcRIz&NiQ$ue#XSGdL}pe8TcS#V!#!(GcNh_rk3t zxa9{k?cEJGfe+tF*|x%H4~tWTyzh5b7(c&Cs{0vRgfIwh@Th~2%%y7}P18jMmi#8a z@{NqKnfeJ+DqF7k>4`a%kIY0lp((xSs!$~5rXA|<-xrZxnY5S$GWiE8!aYI{cGKL> z=Y+A+WOf`$|E~ZE1@`(=uB;yFG4Ez<>^E+o{N*b*Ur)EeF8&)Y#?b_Vvd72V|NY;- za`pBYJ#0kataEXtja*($!iC8mBj)XlU3Q8;Mad-m0p{k;yx(-Jq5^!}j6%|#ekVv9XDWvMs0&KOS@_Iap zN~1PZm*%3|xdj!~_2|fgh_5LwF0HP^qZPZOP$(#nde6}}wb>3=S6x{HDg~`YA`xmT zON+~DsdQRt?3wW{0f(Zh*bK65Ydv`XHa~}NsH-TisI7PG2v=WIUQt1*5R@e;HLWq(#L*`J!4nv#-2B9R*20EdE{NV306 zOhOroZle@(+$It5I8+0L5OxJsMn?-MkFcxgIywSy)WV^X7we(QcvJzqja9bQ?gmXs z)6>&?$(9WrJ1}^_W=%8WWoX+O)7-(9I(viZT<=xmm^zUOYBoTNlnyrJ5 z6=)1bdCHyD(`zWkMln#|Z=fmZTXXbxv>8QbeRWCf<0r|v zl_)pug*ZH}swnfxqv*WydX$*PIOrViTLu;SA3*4zl$FG^)7mE zvmKWG^hPFRKL7yq2xb4{=(O=0(<+WbMhwas=|_QQAm005vD=p|mQ zR%tc;=%P`pdYRQBsLklrzrTStJ4f$rMj-nE004l0E|C2I006*07cBc(EH-360002+ zPXfz+xm5Vp&jtVh008ih!8Y$_vo&g%_X7X`0RI%!YW4pQZw;?#C+@RAZDNBfx+kGx)({&k_@sINq9LgvcB$_hA3?cjxxt1UjCYS2_vMX|Z>Hb{f`B&&SQWWcTEWgas4d z9@s?31-Ydb3i0>w8UVxpokr+;Pks#g-n`xI+ORVTuxDmr`TUd*QpV2uu%lP=w`lL^ zmbWJK(ZhGkv0K8oW6!x_$FEkyw`)#Bb+0vmRoby}h)U^zU9n=x=IjEJa;v*@X?b*M z31jK?j)X;}i(vNXZCde)7eZb;$TPyuj7IuseW*N&<#sK|5RaH!AVH0R-}o72?7tV$Z1z&;M2%fLR`xt7Jbkt0`}0#X2$@ipkwfXV)xHwq?{s@h;n?Wa5O$H2_g#umi) zWOep$wNwjl?S42so5=vRwbhJY6EnlbVG!hR0hEmiq2Nnf2wM+wW{OcM;1JR5B3S3Z zMl$fU6Eb)rfD7C0(T}qxHOJ&&V*G zDHd}}J>fbv)1bwUXL4#BURnLf$qqo;#gLSCUf@`7_5z^D1Po8k;D!W}L&!I;DF-z> z1-0A+x7-A^)H2vy@}HxeSlJmF0X;Z!vn(x${4B>qp_x@0B8+N1U^obW27T@x=Mi+} zCB*G-Ff=SG39mdBO? zcmz|M03j@H4Z|bSJzKijVXrf=cR1Nxj?^uzq{7Y1xN2;N$=F$`30=!c?3)nWs-!D z-9Tn;o>fSFP8=Vi9iN@kUgr{^zWz|c??2J9BIdxedoD{G;*T(C{XIXiEN<~})sWP{W3$*44k6v76;c|E%L2fN$*HoDMzpDzGdu}iVmA7HRG$Lsbt$~xAZJqWD22U1u>}?7MAQAN= z&IB1e#7>hV@-9J1AQN&PGifZyv5*whJT4FkJ=@tVswuA#^{)Wy456bs62zTa>ott@ zqgTl@3jZv`I?Nd3mtz|^m5@;L`>%Q;thVLH||)KF$%e@04S5Uu5Y+;ED3jE;QpDI}FZA!Av^ zVRAEkqWIh`o`y-_BI6*TjLe`9ax)DS?Vvg)7}C6%;$hC@IIgY1vBZEd=`8vg6^tdk z85iYQJqr{C=F%xt_~tW|8G%g4r6bJRQOwZ(JlP!~2eCXPTm%}+lrp9*m37!q-nx;H&iTB#k&}oFyBvU9V{mg%lixJE@R(fiEMF;# z8bp|daZFiYaM$ChvN-5RJP)^q?bdxMLpw44zD9-WsnF8iLOFr>j##W zW_r;5`nimTw7qj@4a-&b9lNUfJzSh!*;s2M zY*k(uw+BN@!_Jl+!?ZaWnWmxmBs}96VvhQfD*PkI5ihSzfo zGXX^d+dE|$8o{^GpmBloW2;P~IvxTEI!mmOUEAO9|2GAXOfZCEs*X)!;%Eq$!UW&$pvIB6e z0Dx(JnE%2M7l`V|@cKBKdAYru0C13JMqIvLdGynPS(70H+8F!g9v&Em@ZzS%WgK7Y z?Bv-%&RAm=b{buit4xf-a6A2!TggXU7N?&AY1|csJTAAN&G(n@dKK-hxX*Lo;^jI! z_L+6C(a_=aO#j57i2C&X!{qQ*b0Wqv$n>i|47cmxxQgy3EiIpYUf0R#;ypujIpq1A z{EGESN0v2?l^oP+evRd?%^5WU=e}RZe>T>1?sgiBB5j?VmBk(RHfc%_Usk*cI%a>u z2deMm+UK#YE?t}Zv&A^hro?nEl|vr==C-8t{0d27QC%0|k={!7SasaiU2-@_^%1M< zqsjJ$1+o2s&x@zDvWv835Fgm1QXZ!38(YWVxBuY_nEbz4r>?8rveGr*Tn3ciwQh4mJ>& zAj^k=@8qlo%8{9o(fy7O56NfONlVbu-Z?A0duu9> zM>jb3^f^e_j^F;;iq6AHLVOEpWl;&&cSc2Wec@5k(DWW~j3Jlpm7~j|an}o5b=XQ_ z<517{K1=4$zx|10JE{0~bd3l86VbkK>o7mIgU-2!FcR zYC;o<`>|oLQ$i^Hai^}se3rq_dU%xRe&0nr8Bt1=p zbCQlts~N`wx}k=UvWJV4*Qu;6XP(=g&|`z;xzHVXBAS^8^w$h!r$9%PrgkWQWQUSD>wz>-s&S5M8k{x)Z^;2(|Tm?5&7fVZAlob9;fBKVoX6?NHiK{^ie z&~Kcd(ZSa%X_i>Lvi5W~okRu~&!#kXF6|xj#HPeU;EX^j5wEr1e4aRmCn$GK!fcq7(l(=Cnwr#qZ(y0W8}B@!kxeAW~nFPiwPsl4@p> zDV!)9(@$C#fP3B@d*M{NWh1v#k`DVr>)54m1x{X!jI01-&}M@-&5WQmO;8c|()_^a z=H%>bA9gs~R)_g|cNb4@ePjXxrJBwc+~m!0m{xnD<)a}imL--bxF;Q(s4Lz0%|mDN zo&|xg=>7h$;7jn`Zca_nfvRI;$o2a9Xz9#o6giCw>&#YjnP_7rXXDX*AbUPbPtcY> z=HP=*FIB{jKFRuXdf2B0wk~9k|4pVy#R+HdW;8)o|2a0qF`HY7t~2A}rt2|$(eA03 zHRyBUw3wvq>U4GP-KP7?O<*Bp=L|N4x1h$dHo8ek)uB^;Y4z?TAA>0PMd3z&YJbV^ zHEUJ21;-W3c?WVa2#6QDG(bCbgYw=u4Yjmh&M+mFq5Fo-wdFrw^jhoZ(f;b;3vF>| zF@e?HVSCo(<(a{&o{!pwik-%i^-yzBE2>2t0m=mz^(TaW@Zbz=;J`=9(RXFZ%k*{Krv3 zE{zsSY{sSkfB9y5Ehh*UD2fU0FckUH%HYDkRfVouKhRM_*|cb%@c66R`87fHRd#}G zy^+U#Ii(D>dJ9ln)?v(OCT8Y^TL<^GF6(hIdv$SfYYK53f!dwjt5)ZcqbluA1@bTp zWno@5l^5JS$FR4|HNCIhD&fsTrse5eK0I8Xuf%P79$^`aVL9FOTf^w(tGth+Re6|4Zskn*QuNmEVL&1y=8 z`|hdvS8$gWOqgK}j2Y|&6*Nx-M1rxJx%KKk3nyRUpP;3$2?faHtDN_t#?(?NB_Of>F=fg(+z%lik*8LSe zrpYJZioR>FDAm~CT%X8j{0RY(cDR? zg3U3ejuh7=YYuGcb8H*~rdlLSoYV9IxV}N3V}x8j@8-+3CfDU^I&U}o^(N=&X){C? zkl`5t^X3DtK_j>aHrI_fU3#nXYn!U;b1Q7ji!&OpI>dPHcj6}Q_gQjZ(f)*Ry2XrT zgdG<)6;*f}xh**x`w4_wX7-s`_Fmhl8rpFL9xF>D6kWv}@8iFK?yS1HoaV^IK-lMP zb~Z$J6%*c@=V9xzGJtNRG=Q#_oW&%*EUH@B$JA5qMUgNr(DD$zuFs8f(>A~6ZS3m0 zab9JS(UAu;Sy5+edwp(M@t5nws(_&H@$0&4Y}>I-V`EmFX-ca3#=`=L*U=G9w(89C z@>aULJBk>NaX~b?b~yXY9FyaUcTss&H}6wra2@uTgg(Y4ro*$TuCJ`Nu&A@^R9Dj0 z4@hO$?vHg}PE%Ip*aR=P_{U{zZPa$E;UuUju52o;YbkklDO>Cn=M7R%GuF-x@B&CD z_RD+hvAVdrOtQZhrK+R<=C!RMi+5Z9W~FPX=CwX)YgeI!%8>PJB#s z8#g_DVcUX`;)ZBU5jotTd9MdRJhuH``rlAkX3U3-C21rlGG>C1SHJCmfE|d{8PcKjmLnmK*gMfGw zb6{7l-ITxxpJM_0<_Mz^!on$dSd@uz>Fb+kVO(HghUfs~yF5NTx(NC@q+uJyHq}vr zg05&78+4V`A&dzOpt7yA|ChWF!^5*0Ixftsif3R>AZ1DHTrAElH_a&XnNZ@`bbfW- zhHZx3QR>3m3iF}DOfe>*Accg#d1(n;IB1~ahY#n)!UrInSm(<;m^*dLdnDD-r>9Tn zS4T#6NB-&rS|(nzGJ?Y}ikjp2RTD+SHp>F>8Y^J@P=YZSI}7mVRIhJ8b-Knb5RF_by%CZ{cVpzD7jCKB?NM4ZIIp3`5Ejl!1 z+i6nqH|lh4H*xnj>MBoH;a>sA0uOh|o=BF638suPX`|#;!~e2yHn7Ymc&KNWrk@dd zJo+U8=uYSk3(Sei$%*RDDF%+v?}bJbu?o!E31OXChG=_mVGE?i9x$pCkoy@T;tyd3 zdG&o9c|;66I#oh*esQFF;3;XHKRv%G{zr#REi5X24-c&hs*37;JVE~ViU?F`b@9vO zk?a=v@S8^#)qnknQRh)jUu1Q4b=}?FDL}xWkO2Q(jts#bp{hJ#H{{Oz_GmMFe z2_(hF$q9x21s&i^=Jibfn>0>9p`xPVha$y6B7Bjsu(7eRwN0rc6u4nhP*qLI&DB>_ z1b%>_{T2rD4(ur`EJR)efHG%%g}4OuX2k&O&v>|cXn`u&H>U?LzC){ejb0$Q;at)K337(jXdz zL@ydtX!2A4%}fbfFm3(~&1JPdXrKTiD{FFcGT7iPL026dDS}Le;K7T0)c)WgSkkD8 zkE=obiVb#I3G1~iV#esPW4a8wvD4r3+R}W$gjs_??u0=7z_dW8>y?@0*fJy|EbtW| zEe#T#R8k)!-5`dnNwsH+jzlqo7X1c{Jbe7bmUf!ns(2<)d-4TM8b~m^OfZW1Xx0@j zFUujb73!Br^mS_%=OGQ)%*fZ**TKO7Vgw2Fhc*-ex;RYe9qb+yd*DvO+hX7_vJeS4 zV$=7fKaG7G&p%YC7hWs%=FsGa)LL#v9up9L$bFu)k$opj)-%+UsiV6WgHX^!k39_> zy}jDrVJhm_Q3%VuDjo8b-3qX5IY_@0007oUEAhcKaClEx7kcC`dR6O8nmZCTwY_~Y%s9@L)DOXfc0;IEJDtSqqCZf2Rew$A(@@e_itVsc7UNmYIL;^N|7I7%KKoR>z@({m70 zqo^Swbq~v`rA;ipQNxDTjXn;;GwG#V*=ux}rft5fpuW7=Tf2NoRhj%+w%g9AEK?g4 z-@KFjXY!s81nzk8xGo=u`L>fUD*CkFneV;Zz>q#udk3Gid#Juv$SOCBz#(=&R>)5g z*XU?)j6d!$97*_-Ww!6FGr(z#}3CSLH3$!0ji=sOh_<-+Be_e^JD!s>Xv- z;8EA6DX-z{O&Z5@pca$=H6PmICG1gSBW#N2OSh+JnlRWuT#1N&Vf$`UnI~surtX!# zhQxY5P$Mtm9ut!ude<@WTf?(Xc|-`j6`>BkdvvAFkbz*ytE{BmaZCJLgRrjx!S>ns zDkZvJDTqFZ9eqDgy|Aeya!@bE1KWT+SFgXhV&1GZMAa3&nC+z}xkTI?x%6=NPl`%M zg$_PQB8|^wX$9=L?v?GAINPGaagNE~4W5E#!A1VI1gY#~l{+@z6Ju}h_vuKI=!sSp zC+XkF>%V6t@w023zRNj-viq2CD?lx?q|T?{7PYIqpJnZDt74hQ&=WF7tF6w~?K%$~ zC;+f~46g({o$J!K?~6FXQkKD7%`nv71WiInTzh|V3cB8$CU1iNh? z4Y07ZmLpkEi-khs8+!XZmBrgU4c~F#-PI8~fM+Qv#eBqYMipB}VVYv2zaS$NlyCi; zQnY1ex2zlXYRo^4ebw{j;8qy$x97cKD_`Vp0qpdgM>&wNxv_BqMSREdK#^HNcnj>< z><}dzY$Rv*_t^`n1TH}~+Kj&{uD6$0uZqP@#Q>6}Q31(k<`qmV&1n~i*|Mp;uP0sQ z5%*)4yLEWQRep-eOwRjfyq&Ucr`h}=h?IS5RnT3WwyF>U(;2DWl#l-q7^~g~QjgxN zl96b?Xaj%M((1lH)6Dn8t2B}OK1@4ASmcdzg+4|v?cc&e&*Q~^>!*MUE&**&|lPdis z8Nr#GM>+xA8pIe@+$O#I!s_|cUczq{V2qj#j|^Q78B)JcbLyL-AH!?glfWi|hevFB zc6EDjO$>{~kg}^7T3K>geujH!es*<1e3;Pj|4<+L<>9QauYau`-ko1}o0?3sHonL} z&MG@oIsgxi;Pm}E$szsBUs@6C^zN3iHjv3Qb+fLEJx70BKf=vYb%@%sMSIK)k%K=n zhV+yg=NM^!Wwb<{C0|MB?PswnPaPQfxNo9lZ*DGcZ}0!DzEafH`zx@))XXgCCsHg& zbSKo!o~4Z3htK?X9YjBQX=9*U|rs1*YjW2IBhEu%L=|AnRr_lleV+s?%epzM&HJNZ|Dey@`M;^Y-&oj0%LXg z_BJDrYZ=p%_Yu6&mfoI_5SX8kFel#8{XU(`u1AMs=W$xeKvHFBWo*}Z(80D|gMp-- zc&l{YRfFD8%J+e*h@^#U1{ts45GXL zH+UQv#OuR@%g+3dmq6a^5-#K`f|SMZy`PMVuE7?EfP{ebhAo`77?&u^ucCuP?bf#P z;VJQMZZo>~{OL#l=&em-Kgps#P>)SD`sxKE?6(IF z-*4_O>%m)$9A~h-m5mL!ppmB?Q2rZ zdLh8M?O0!=^cCfGT`e6|tUO1z_Y)9|{5Itg{ysDhUMJb%imOFzwwHLDzMoa9_Bs4e zu<%{CJDO6e4Xt@K2)$_m?UQKYv->>8HZVz|h5{}pR;$5}2^N3o(+>hfkko_Vh(q7g zhJL|4=7HPl6KQF$^K?K8L@cjvtx-#zo?v5QUtC@RRp@qo4iudC4d(adR6i{>Px&#v zxesu4c)dZsd-G^%3;6wkvPZ*UgSuwog~M1Or@x^Ab@)3xJiJ_^A6zGx_|OFMBI$nJ z`;-6OfJ3kGc)jn^SkxxLJ-NC85m-W2v$D>>ZWI+(m^(;x+LqSfJm6m>W^Z;8=YsrR z;n1E^hhQX)7^*8NF+U2MfD6EeKo6_#uAynymQDRDx1WnKGCMmP6&3X}vb+HsIw4T} zAoq87_xH}nWIyYSTM;ZT@Y{{<{|_&^a0_kVdg9P~q7QqeukO zZra4O5U!=n6`Z;9QKOSx7}tTqkiWT8&|-$^?HQ{%3f8^aZvQb|1ZTEw;3nBPp>G%q z*3RPT&qJFxIDgrwzp2m4TXnDsSucJt{m=1iLLoglJuRGbTq>ynu!6k6gS)~yM1zOI zF6i-eAs#-!e`2U0!lwdz4|0dl>R*w>fo_Q+7(!SYxIoYeE+|p8nTK}j!I9!AkZPDY z9W3)S=q12jJqzYeaJez)0|yQVI%c?7oBu!x%H;9T&Vs1$*(Gaj|Wq95;UbQRAnd!xL1# zP~`~MExUvRp26!EdPSg*UV11|b)*)YGG?1i1nU~mgomC<*_^J#4nl$D29?OoHP zK=d2q110%4-*wx$9-{WlH@6cBLg;WH`L0c8+;B2nEf~m}#DL{BUD|%T0Fg^|z* z^?N*%u=2_%#yJ-)ih9*nX;L9zgGLQ#)_m0qfmwtHf7QaNt275$ZCAG!KnN(v z$jQ4Rr0K5BRdk*;znrNgB^iv8?yV#U={t{0J7xMvh}r1wo;-s-n7c0By~H})ZC~`} zPkofcyliB2WVBv^P_P+%|GplJ;+N!-lXbVc7*#|qAUEtM1mkjAWV?6vK+JIottq(v zBf?nC?SAL4u-O9$iXh0N{-{;LU$7#KXN5n}xZR~QYM%tM?aHlP5HK7hho0_ebcATa zXb3E-lzaZLfi(jYgooX2qN)=_+M${rZMo0SHzVR;$np~TZCg@sU6L?ZBB`LZTaFqH zl#;i~Xv|wwy~m_gxp%QZ2)epIQCF$3%qfUnddYws9_py;S)*^l#bRtLX$ATz@PgNa zI#zm~b?L3=|Dldq4NFa8nNwC>ck6&bO+h)KFLbVqgSR+}-2lo*0Spu|?@ViU!Q5#yk2OR=FK(`t6?^CXW$lxb^;%DA=@NZjT%L>| zF;l}O8QlBle`IUa{-`Odl~*70^|@BpUjZ1}TXC@eUgM{mAJ9nORaDykhIc)|f@ZZZ z9rPn|wDI%sxcsJFV(tS?U&W^dpt5i9-`rDybv{ltB9tTT@i{CjlVw$0;#rhU@z_u? z7`sk^2XJv1jIqoeA|Gsf+1LvE5hzTU1{ zt3XPUwh_ zgHLy4-GG@YGXvqhV=TI45q!Bbjh4x87Q`u%eE;Doxb*Nm%RW}<#zjMLv?Lj7Tzx`w zB=_rM9dp*??< zVD9yibn&8VZK@Db$GZ7tyqce;kKHu=5Sm&EvuDA<*8d)?o}V#z`eJl7 zPyo4Vh#epeM7{#e*Q(3`1_-g6Z?f~cy28$_JDU~h(7Z=#>UUWZs3M@5dh|735H&@aP|dOK-}b%To~SAv|>OIi=eKrUY1yijwtLTR-f} zkMT(d$w_4Tqm{kANwj{^XeemNG-golWBRei-fFTDH;SjPZ3=mRt zZ{4~RR$<%@ZZsv$-R+;F0iManTUghZEyV}+gJ>w9S`EHKDiK7ztB z5zocakA=MGX^2y~Qy=RHPvR_q41+7aS$$v2p72QMHB8YJZ??K{m_VVVsms;fT$x?y z6WTz9f1@z>P3vww@pLEC{%4WwOhY>}7FligaoVSkD7X=QVHyj&X++^S!^M;+#>c_S zQjooNLBr`t3^n&nBs!zPQ6Jz+S}6A1SpCy?2DO~55a(_DmGKP!pf*U@k+Qb`X12zv z;mbRf<6ku~F#~Jv*jU8O&(8&xeT|_Yh~1#bVOAF1H~&d1BAKXpQ^a>nb3+%g+3?`5 z!TD;v^v3#$q~KF1;)FV%pPx-lO|I9#q#$j8gnq>6{U0{723frIR{>;t#>J~Svxcd| z?&@Ks5eV}uF415ZIJlna9TC3&6OqG9#*I4x$Z=Foau|k(Q09rD0XL;GR3D;Tbi=L4 zG<1W=Vq^|`xI3`2)~xdap`yyr!$I<>F)U%EZ#e$ z*7O^cue^~z;l01Ul(Q(}2=_pVJ-$9(qpyh=8E;0DC|I1H4IM*zi0-Y2esSJTe+^p) z=KA;b`~hf&`qOcASmvujo1+}3y-uCUe7XBqaCFgXrX1uZy>5!p|M}9($(78I=KQ6X zKFLCHyJ?#bo^ z`Ek?^D>o=>|CIu6Rtq{hI+`9iFvQt^oa_&y-x(M|@*nw63nYU3>%Uq7FyUUr4lKBT zB_&yLX)_bW?{AAMxoH)$bWvL3qk zx1$$;6f0mOEAx-iwhG!eah2~yHoJ3rVLU6N+{DhR~Yt!T%w>Y;5gHTR%!Us;KQ>x=+4N#L1eXxD>tA~IMUo~;?^?sVGMvaFT2x8@5FwNJ# zwr@~XES8q6;35U17p5N{7AA-!k(|=DPs5!W-N%tu1lNN@Pf}4z(b5_J_qzX=fr*`M zi{tkIg?emiX&72>4G0Kf_wOz#wRguf5BR<`U_ZTx;Go0NrQKoKvrO@QG15^23?ZXG zNl~Y>>21g=cxNOPm+SO?*_*gX_th2SS`_Y5YW@hTf%H);y^c`SP;SbD5D$`as0mz0 z6zyfk=1o1{epS_7!E9>^+Pd2xLO!u3fBZ4*={+b5KEnNpSIeK1DzpNydZl|I+`ilX7>qWAMp>4dOF>lnaok|J;%T z*K~j3GvO6e-isvLrqQJjDUl-)HMHO}mKKJen0nu9A%OvBgqhYZKY4Gw-C_Fk^b|QO zl}*8B#1@LVn0B}jL*g}P4b=@*+wP+XgTK5D6MDIhnp&mC-b83n)dGh4$T+wzxd;up z3FU!nHh&6vNi2>faM_u1N> zsMNn^4&r*;w6~^gFfK$Oe250MIwda1qk!+dJ05RpBc_&v716^@^rSguyPACnU|6^G zB_BoVxTQlg7O|t!YEfeC#*2{!mUi&~HNs5R7NF~t*-~K{vnG)}H12xq2FAN~+S}Cb z*g8okX&62|EF&;;vhFcs%sFFRK;7M0w#@5Dnly@nf+BGDvpwSHYHVbr*XaSA`u_H2 zb_e9c>sT2h#E`V*dh6*Uv=>|GHr9?n#ka!=L(&EJkY(r?^VDagGo`<3U2a4G71r0H z&M|hDiyB>+IEHX*Vp;I9c6ZJGavZQfq=YKb6S>ze5QGRVbk%EnB87S%HQzD z??RCkm;x#V4Wa5s4Xw*!hCB-mu)rp#h*#t>)pQLv~YX2}M zRs_F9;S_bJTt7biid1xv^M-tiN5ljz5Avwa;Mk!FBy|$?ygWawFHiX|8et}NzDt!y z3$^~%*AW$f0!++lw{EApO1E6Gqk<{?{cSUInZ%L(xQ!y7|F4?w5+p+LOJM(6I$M4t78I|j zOKS5ST@?x~+g+#76^`QR#lU`0WnC_|T@DI)BO9*vwh>+m8T6l;H1OhA4=mI5~tT1O$&Rc>fgfu0JB6P~AXK`mY&f znqa-lvcqFKDot@C1AV&MS=Uyo@i5#f?=#LBOQ}|hrNUFZg^gMa(GwM|?UK+aK=M5! zD79x%L}(7Y8Lg8NFh}$6R5VI4Fb)3fGKHL z_l3yey-a{MD%^({CyHYCa0Q#qb+Kw>VRJ&Kf~@B{YTh!^!v&$(@F6?W;!PFy_V_+R z?%h34lk``3kG38IUFT7uR60pqL39+c^M@d@i2Z6Ib;qj}covNC%|BJ~#SiSH*?L5} zq9YI1CaF92caFZCu@j(|?B|(YIb(3Z`6E)zlBVluC7OQ<^w?GFxv9x-dEB<(uik2w zn>&y0(#eAPutc;xIPR$aiq>w;(FFo1L(Pb^#J^E~3Zbr05#~LV6A}9-CzLZC9q!k9 zC`7ER54!{50yF>sfQ6Y^;3hpQ3vN%m4*RE2DtPf)K{C=JFQaz;yBxKuUQ)2tb<8cl z*D}|8I;t@6UAWetx9}4EM&_s0ouO|E025QalMD0t+uwg zwsB$g=Ch@p$4VsE0Q_fZJ&cu*)3DlO$mu)#IID?Gk|JlQ`7;@C*s&?xv}?mM#HY5E zTfK=52^Yyq|Y4k3fyUko@_j$4&f*>(P|W?Yr&oa{xb@E zHS;%@d3Tz)oQWpQqBx%~+Z}rB2{Z(jRJ>?|pPl&N-hb`HD&_Iqhb#?B{$%@*2Re5>s<_MHKcZuu25|$jHuHsJx zpO#N@$Du|6=>r33xJ*kqXD8xMAjZZI(s!Pg^bLZrWQMXkzVm*QV0mxB2M%{r(BB(;0UwZ>;V>l`{UDC!xJ;ZQX>QR`d}hT1UKNLUimIT5&dN1E1BOK*z}z|#zP3-$1)NcPNSZq zQVR`MQjfCFrq(yp(KMfxi?}71nU#K#x{rmGfkp6I#=%jyL+UrsVD8CRk-v}}bR2TD z!M|j3EJ_$4ucJv61gKMB=K6%(+@4}_IP`k_;6tvavUxl`Jqa{%Ln|YX<}MCGTGP{4 zk}C`J>NVCv28+kWAXa$9Gb^ZZcH2TR7y6dwTCxqyj})vuHBnSqwW63-*Aw$Pn{zfx)CQ)!qAl`8{e*V5va3aIVrI4I~goE>3o@WR1q$*~82q^HHp*FKt zRTTC65Yuh*WjTW4`g9FFrHb6~k@QoY;o|<~PX=C2&0MD9jwByC>Ma2+sd%!@ zE`kHE-tM%-HW2PisPCV!R;MS5Own-^i3D(_1bNaAZ~Y@0R1f)a z4Ew{e8yh+h!9;%8xDr_DY9k{fB}GNLZBB>#+kXTDfPjOhQSJwsXlZGgn0`@e|Hz?) zg@s*R*&=ZF_x9%I=X3e}^%NC})H;6%j0BEAk{<~o%gFmOF2iKs;dmN@PV1kfB;mr@ zfTciQBj5Mqp|(-}SM?iK&B@Ta53PDJE@={-SO zc8o!gYtt7@lm0`N^!W-Ggjl+Rn~=r~I2M!JRiB7HF9u)wQ(SJyy}R8_bM)etyPv}8 zR1J@{0G9&`7%b~Po|9k(Ec-~-R{0{cbIT%y}d||L1b>c*wGwJzn2y{#PWaq zOH$G(AT#Ua6c0bcpeN~z-qPl3<5f4^_Xvf0t3Vkv2!7z@9nQf{*SeL4vwtr*M}dQ6Wi9r9b;nK znq*=p6Wg{Y)?{Maw$ZU|8^7H5^PE%XocFNm{j;lfbyZjQuHNgrKG(IH^-p$$L>rMd zS1aoji7`XyI1c`#Yin@4iot+hdQLxq$>DPxyv?|7&QZG^nl>JZ(P<9-nvHZBLbq$) z;dB8sWse>R)m>&Hotruyf`#%ktpG>#(Fdo^$I!ZwBgm4vUsbnZRs(0$e)dd51a*I} zcKv%(b~7c$9>9y4uA1a9+KX=#-knqCd2U+IdIYZS)ix<$xp@isGuoF+$@xdf!QQJ7 zzkaNvIo2{nRQFajfH!#4k;x@-@Dx660zph2SG)`Rq>Y!#SWlezwPt8XNZ~9ZeVty95geYU6B@LkYGt)E0+FsqSCsytbf0>4h)FKp#*Gl0!svjSFe;(@t=BxE2c)F zLP1=T?|Ip8P&>1NV63kM9N5`rdA`RGhK>uP+EjCB`h+f@lVdP-s>LQE_$XVPog0za z@7!263?S6_b>wG>z3u_Ce0e=?p4~qu$F#b)gn1dS64QPS`~3uEvk%TOsbNZEv{?MP zU-?UbDZ1b)thn0VL0(?I2e?ki@QWmc&fv`&csbb1uj6?^zfcrTLhuxuP{3g7K#>IY*_+%I8MJ$U21 ziSTfWkwWLnD=QZh5#fWHt-CV09|?3T*WE`^0Ll0g8Q5i;+NU+iMRUUqwv{4+D^2|) zCdkba_uN&4oYReFRP($uJvKH~Yn6Kd;(4gho&+;fDJuaVgCIp;0KtUNz=B2YlxbMj z=l!)mB9Sv{t=-t|Xfkidf!5;>K4@mY5qwVfemHg&du^GEQkTiiA#bRF(snsn?UOU) z<&OpQ;;($n95iPmYOLmK`FB4gy0S{#GoR^?MXj92sqv0Sn~STpZl>l_1N(M4qsY3b zj${~77Q?opBb!nbt1FK~HX9`h9$Tpmzc`w@B+Fx|&XUmj2?l;I>9$dPjV1IUaTTQL zst(=rZ$TKT>&AudXA`)bVMl{41zOT*RviU=KTp(2uDbN# zWJG|0)h!v;aYSt+o^I5RgWp95p6aips8va1zSw>4u}iE?*a#V4?D5_HaZkj<7*-Eg z(8ELS<%fxcY8_CtABvlUJ7&E9QgwJa$L#tgi08R!NkLa>Xpu)#ZipVc2!>yFJCW-o zKtDUET{2pst}x%1s=Xznl5F#}Efuo!E|=~hE7K2iq(@I)wflJUjgj&+fkE;BeRs@g znG2=U*Y2Q{uRf)m2@^ogy_G~q)X%Kny z_GQA(M;rBf#pJ#*QK`W854D7x^#a7LM1DV}wHIxW`rlBu&H=&IACHtC)!YRna51^!aGX$#0f%S_x!v!*k z$Zuxj6OPubxUbmc#K!sJhw*OvN2psvR2p46y&YVKA8N3|&AMU;PgxXPI=SJ5WUB|& z7=a!4zlIEF^$4ruXRa=aZV4K7DEH7w-A@>Z`T}*+fGWV;izMd7xryFIr*Q3T1rqNu z`&x`&gw?h@%OhlW$!~|xRkWYs?Jv&JfN(ur(I8XO70r^K}HD9d)7o<`jkqVTN=EqA1y^{x1*3eShy=`+C})x|J0# z1H;~V&i0IV8#ZV%ejTn?wk$86C`p-!2|JitoB$%@@L^QwUs zixRtahR8tkBz`srOyQu-lWSxqF=HFo(cV*;_`3M32`k?ik6UJ(9^4z|q16drp#%^tzKc}k?!(-Ye;?!_E8EFD@%FAr)Y1oRBM?&27 zbyXAU-KRkg-0WA?Cib7H1F$z~-%{$2HT-dqV&>;rcu_Pn?YmF-?8zg>LET@Yjimb& zb>r-!#)|r(t*2F$*&nzt9+F|`J)9nqS)(%I`*UXMG9hFthHi&`QmUiQ%DE2;f)G6FRQeXx-V@qQhnav6^(4Ag5y9>iF3MzkCeKw~rNr~y7qU;W`|$@F%t7$%Sbbu2!JU8k)eG~oGf*;- z#d0snOY7Qs;+TuEObS!F?VvQG35b@>2fkYs7k2 zhL{1F&n1lB?6wX~ww49gVE7dcQUtr_vM`iboFh1fv55@46 zw(--eN^)O7)YFdLtQ*u!R=^*%pX;Zo)XM8+4g*rpXw=|Jr&pLdBRfvY$O`L^FvF0I zGpqFr?f>|}!3KYk-7UPQ>UMuNOlMS}{?Zr5W!ND+u=rskBXfI$HH@JWin^bhzvJbj z1LLRps`0HR>D56O`Qva-MS$my;+Sehj7q9Tk6+gPje9@-ye1oIko|slBT?7ST?aD4 zsE>aYcWj9ebndoC-npOK_QS&-);@-e1&T}I$|-wKI+FB++L*JkLc{R2%)9ONUQLr> z5#M!=YTkC~vOUD_`Zya{;wY>p zrl#-^{`>p;(8z?VFo;o-BUW_oPy4j{cNkXI`|Vfy_T%=3$3VUVYVX8@)PT4!8q9!h zEpA(QH%;yyh`3C$^#d%x$?lz4cR!$1?9{#Vn-_>+_Ur=toZ> z=S#UnRJf@ATxJb6D3@owbBJ^YpVG8ASlp=oJfY);(!FwUd1vjhf}BPj+M_)Ow@@Na zO^7(;(vyOE(q~s*oKR5puk0!=7B}}NIN!SDmv4wXtnYo+s8Ha72!bXXSHKU1n+cIh zNv{Q^juHeby&ibX!6wXx>Kb4Q8#^p{es_^PB~*7*rbi0mSaCeNBe$mK|A`D2FlczWG9l_T?bg>=&7U=> zUvK~9>3whA8AX+KHxmR#c;+OM!`J<}7y#IG>d2!`y@W@*ubg$Nva)M9uMVF5)EJ|o zVn2ml#K%AGzRlBlv^KVKHqsuE0+7oh^ zDs>&i_jolDxoHeTP$;3T0RGIDrWk~9ux_u~ESMLw(DYQ!r8%PJnrN+-eo02sO>a1Eb!6w~a#a?ts4*{w^6 zq1&xdvZ;Z%c<2@-3w4K3Fp1k09?Dk(j&$%B*eJx8FR!bl0i)ZpAGaXua6A|R@I|4{ zX-*7Z#kXKLiw4cDNF*TMVVyy#JL^@&hVRBv~*cCYgb9L1C<3ui60^B10WSpo42QV_GNfD@S3U*J>z&GkoLb{ zUVM;;ZJ(SPI{H>$&JyG~Pt=2DpnoY9%C2g%^H$^$-6wvH1%RP~`(*RFU9-{tCVBZj z;r5nsn=c`mz5&)xs)pkg(qjs@V}HMO$~$L;`**V#}M67 zDENA0kIuh3>$Xq$U@jk92DX;A#N9f&im?4E=-b>!r>(e1#w6ZcwJ6yzfeC0IZJTed zpOi!g()|XA*1&&--rfzKeH+F;o?U#C zAJzxW5ruIqyLEraq}Gq01v|1xKAS%}(uPiwzNNAG@O*y&$TUFt$1v;@m24eIaBFvM zUkcbmK>QvPp1ycHDD?4sr`#vj@x6%1f3$J3u{keQuk@7)4i4sbzYUd1!>8yaj{<9c z*~>ARy0+Kp^ycIB2pTOgQIwe@Oq;w>UD8Yd?m+lBn;gPhH6xO@glgtnE;x zHgm>zReKTs@$kQfO!zl_SL$G>;(uMYCD?}w`pH)?yNXZ-k=J5DKVNs-g1&1gO35f% z8_9W|o=^^_%kuLNjY~4^tkCET(?UeC?}~QN7j!XIctKkkzD0xpCylZ^lzUf(D9zJIJUckY_^4rX?K^NX%_lx6)q!$Gx8LK-F!7FKq=Dv-*3Efb=rqopzF z?y^+_q$$y_XZP{(F|ba3sggxW=sgj*m$^nTpTwXNHV8xWc2{^u@bl4B3#Nl@%9511 zB$a14O&jsnEB}SOm=BMYeRCzJd@Uy z@uo|b+AJ-h#Yc|oP1K>WJZY%%xte|M`p;U?4~Bfpb2HoDg~Uduc4ht$t-`NrX96GA z?al3cgoUMfhWO~}6!stve*N(uZ$4_=iSpf+bldt=?*BsGiK52SEU8jVvnyo7I8}H#WIz#IzU$66PVv{#&y# z9oQ12ySVv#>k$2dN2E|U;Jk5p!WIzR3+8XUBDk3g*=-ZP=-Y8b4aPC}D#Gb>T6X`i zQ91uva4CjoQF@ZDA6lt7<+Gu4sUY%%{2?63>D?`sZbvUp9?kujj}!mHAf>j%%|J`N zn}9(yJ&`b!b0H%>m9@)vU?Z?c?WZJ*_tIl#f1KXaoNLg2Ch2tPod`-1Z^@p}xMDD! zQ}#l4SVFxEy3gy)zN_nN%L_R;JZO@Ve~MH%GDk4XvmK&ornIW6e+yKIjsFQ$0GR&;P-*{nKqao@ z-vE^uWFd^)6*ceHWpvx%eytY)n)tESeJw>X2$DWg9^KlVWD}6(i=+LKj_6 z!t7Yroj;j172l+g0ew9%^5905rrTqXK!Oj;AX!2fc#V3Vsg`$1*`$~Ty1WPWaiqOO zJS2yGXtKVnMF-oMQ-|K17bZg^Bg36Mxu(+cYW|tX&>gIhuo62&$owH2SMFmPrl4ia zU-6ei+Af8^fEZun9o$(6R2OnwbUdG4lOv)NyQ4z{Sw<^e8MTAjlVZPkPn`}5c%7g= zQj;A2nto1d5b8(iljYjUF>m0h&S9hN($pJNy*+mSbDNw}HvCyL+GizSm#7!L=0?NF zY=JDcPu0FDxqg@wC52Zezl*+C^dlwehD2(Z?~Y=IN7(R77Q}I--nMfsNa7U6MP*S` zXO==N7C{a}kw>X>9rcf$mu+eeDzHAw)rPf_8tsaR5Fg*%x95}k#=^_Apau&%hF4PQ z^&bTo_29Nl?JaJ1xVQBO!}5%-<=VM+h3M$Rl37MU{uQRE#@D}V-#xae(Uv4*EZ`JG*VP{tZoXJtWU)9Fv z)<QbcJfw-s$s}os9kY_rJKp!?k!g^jbBu1$cF$fY3(|tb84tqX*lJ zU^g;mEYTX=+1jjNm~g2t5r-rw@j7glv6QYigP<_YQq(F>5#3kSSt|&H^)1@ifz@#8 zkA(wd$*h_b?Ae737P}~G(?;D~-Q4gr%-&!4=y`C%%cM(!nuIsJYZ7Z;$sQE8@EnWC zsX01E`1@_Zn39eFUF(C-*6L{O=Q!fAN@#4;!8(Pp+?`R#b{z0REgsdPF81t0bMi|2R!wS0F00e^?SALBhGVfeNcn+diXGGcpgnqaER*Xiu8T8Bs+j+0?6EmX2=ni-2b3OHD*myhNlw|0 zU0q~fI(;+b#)z5U4SBY+f_>94dUU4CO4Zzt+4)PJT%hm;pSRwE^lk)LHOs zzI<;?ZVs$cVlhIwt3ez(LQ&HOH0W;`2=uS(Aod6i^Q;1}DqjrQ1m+=~!zy->O@jW= zaqUM6mucF!6;jwH%pn08%HV-X@g6heEdw7E+pJCdO*(J;CyIWtlY0)`%)!ciKz!}2 zzexvJi=G4pJJEuE@%B$>*KJ28FRv62Mtq_9?Qs%OkpOAe*W%K4`#Cd+Mm$tfPVY!q@;$KVjT_qS>*3dXO-1~-v+

    Icon  Name                    Last modified      Size  Description
    [DIR] 202-vorbereitung/ 06-Jul-2007 14:31 - +[   ] Efficient_Video_on_d..> 19-Dec-2006 03:17 291K +[   ] Welcome Stranger!!! 28-Dec-2006 03:46 0 +[TXT] barschel.htm 31-Jul-2007 02:21 44K +[DIR] bnd/ 30-Dec-2006 08:59 - +[DIR] cia/ 28-Jun-2007 00:04 - +[   ] cisco_ccna_640-801_c..> 28-Dec-2006 03:48 236K +[DIR] doc/ 19-Sep-2006 01:43 - +[DIR] freenetproto/ 06-Dec-2006 09:00 - +[DIR] korrupt/ 03-Jul-2007 11:57 - +[DIR] mp3_technosets/ 04-Jul-2007 08:56 - +[TXT] neues_von_rainald_go..> 21-Mar-2007 23:27 31K +[TXT] neues_von_rainald_go..> 21-Mar-2007 23:29 36K +[   ] pruef.pdf 28-Dec-2006 07:48 88K +