smbdecoder
index
/build/dshell/src/dshell/lib/smbdecoder.py

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= <type 'int'>  [3]
            status= <type 'int'>  [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

 
Modules
       
dshell
struct

 
Classes
       
dshell.Decoder(__builtin__.object)
displaystub
dshell.TCPDecoder(dshell.UDPDecoder)
SMBDecoder
exceptions.Exception(exceptions.BaseException)
InsufficientData
NTLMSSP_AUTH_RECORD
NTLMSSP_CHALLENGE_RECORD
SMB

 
class InsufficientData(exceptions.Exception)
    
Method resolution order:
InsufficientData
exceptions.Exception
exceptions.BaseException
__builtin__.object

Data descriptors defined here:
__weakref__
list of weak references to the object (if defined)

Methods inherited from exceptions.Exception:
__init__(...)
x.__init__(...) initializes x; see help(type(x)) for signature

Data and other attributes inherited from exceptions.Exception:
__new__ = <built-in method __new__ of type object>
T.__new__(S, ...) -> a new object with type S, a subtype of T

Methods inherited from exceptions.BaseException:
__delattr__(...)
x.__delattr__('name') <==> del x.name
__getattribute__(...)
x.__getattribute__('name') <==> x.name
__getitem__(...)
x.__getitem__(y) <==> x[y]
__getslice__(...)
x.__getslice__(i, j) <==> x[i:j]
 
Use of negative indices is not supported.
__reduce__(...)
__repr__(...)
x.__repr__() <==> repr(x)
__setattr__(...)
x.__setattr__('name', value) <==> x.name = value
__setstate__(...)
__str__(...)
x.__str__() <==> str(x)
__unicode__(...)

Data descriptors inherited from exceptions.BaseException:
__dict__
args
message

 
class NTLMSSP_AUTH_RECORD
    self.messagetype
self.lanman_response        #
self.ntlm_response  #
self.domain_name    # Domain the client is attempting to autheticate too
self.user_name              # Username of the account your attempting to authenticate too
self.host_name              # Hostname of the machine your attempting to connect too
self.sessionkey     # Will be 0x0000000000 by default for the client
self.nativeos               # String representation of the client's Native Operating System (unicode)
self.nativelanman   # String representation of the client's LAN manager type (unicode)
self.primary_domain         # representation of the client's DOMAIN (int)
self.valid          # Is it a valid NTLMSSP_AUTH request
 
  Methods defined here:
__init__(self, secblob)

 
class NTLMSSP_CHALLENGE_RECORD
    self.target_name      # Domain name of server
self.server_challenge # NTLM Server Challenge, a 64-bit nonce.
...
Other values not implemented yet
...
self.valid                  # Is it a valid NTLMSSP_CHALLENGE request
 
  Methods defined here:
__init__(self, secblob)

 
class SMB
     Methods defined here:
PARSE_COM_CLOSE(self, data)
return the FID associated with the CLOSE request
PARSE_NT_CREATE_ANDX_REQUEST(self, data)
return the filename associated with the request (return None if err)
PARSE_NT_CREATE_ANDX_RESPONSE(self, data)
return the FID associated with the requested filename
PARSE_READ_ANDX_Request(self, data)
parse READ_ANDX request message to extract the FID
return fid (file handle to be written)
-1 if err
PARSE_READ_ANDX_Response(self, data)
parse READ_ANDX response message to extract the raw bytes
return the raw bytes: return rawbytes
'' if err
PARSE_SESSION_SETUP_ANDX_REQUEST(self, data)
only currently supports NTLMSSP Authentication Requests/Responses
PARSE_WRITE_ANDX(self, data)
parse WRITE_ANDX message to extract the FID and raw bytes
return fid (file handle to be written) and the raw bytes: return fid,rawbytes)
-1 and '' if err
SMB_COM_TREE_CONNECT_ANDX_Request(self, data)
parse TREE_CONNECT request message to extract the Request_Path
__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 'ÿ', '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

 
class SMBDecoder(dshell.TCPDecoder)
    
Method resolution order:
SMBDecoder
dshell.TCPDecoder
dshell.UDPDecoder
dshell.IPDecoder
dshell.Decoder
__builtin__.object

Methods defined here:
SMBHandler(self, conn, request=None, response=None, requesttime=None, responsetime=None, cmd=None, status=None)
Placeholder. Overwrite in separate decoders.
__init__(self, **kwargs)
blobHandler(self, conn, blob)
connectionHandler(self, conn)
clean up all requests associated with this connection
connectionInitHandler(self, conn)
parseNetBIOSSessionService(self, data)
parse the NetBIOS Session Service header [2]
postModule(self)
clean up self.requests to process all SMB messages that only have a single request and no response
smbFactory(self, conn, blob, data)
# Returns number of bytes used by NetBIOS+SMB
# e.g. mlength+4

Methods inherited from dshell.TCPDecoder:
IPHandler(self, addr, pkt, ts, **kwargs)
IPv4 dispatch
TCP(self, addr, tcp, ts, **kwargs)
TCP dispatch

Methods inherited from dshell.UDPDecoder:
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)

Methods inherited from dshell.IPDecoder:
ipdefrag(self, pkt)
ip fragment reassembly
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()

Data and other attributes inherited from dshell.IPDecoder:
IP_PROTO_MAP = {0: 'IP', 1: 'ICMP', 6: 'TCP', 17: 'UDP', 41: 'IP6', 58: 'ICMP6'}

Methods inherited from dshell.Decoder:
__repr__(self)
__super__(self)
convenience function to get bound instance of superclass
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
cleanConnectionStore(self)
cleans connection store of all information, flushing out data
cleanup(self, ts)
if cleanup interval expired, close connections not updated in last interval
close(self, conn, ts=None)
for connection based decoders
close and discard the connection object
debug(self, msg)
logs msg at debug level
decode(self, *args, **kw)
# we get the raw output from pcapy as header, data
dump(self, *args, **kw)
write packet data (probably to the PCAP writer if present)
error(self, msg)
logs msg at error level
find(self, addr, state=None)
getASN(self, ip, db=None, notfound='--')
Get ASN associated with an IP.
Requires GeoIP library (geoip2) and data files.
getGeoIP(self, ip, db=None, notfound='--')
Get country code associated with an IP.
Requires GeoIP library (geoip2) and data files.
log(self, msg, level=20)
logs msg at specified level (default of INFO is for -v/--verbose output)
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
parseOptions(self, options={})
option keys:values will set class members (self.key=value)
if key is in optiondict
postFile(self)
preFile(self)
preModule(self)
preModule is called before capture starts
default preModule, dumps object data to debug
stop(self, conn)
stop following connection
handlers will not be called, except for connectionCloseHandler
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
warn(self, msg)
logs msg at warning level
write(self, obj, **kw)
write session data

Data descriptors inherited from dshell.Decoder:
__dict__
dictionary for instance variables (if defined)
__weakref__
list of weak references to the object (if defined)

 
class displaystub(dshell.Decoder)
    
Method resolution order:
displaystub
dshell.Decoder
__builtin__.object

Methods defined here:
__init__(self)

Methods inherited from dshell.Decoder:
__repr__(self)
__super__(self)
convenience function to get bound instance of superclass
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
cleanConnectionStore(self)
cleans connection store of all information, flushing out data
cleanup(self, ts)
if cleanup interval expired, close connections not updated in last interval
close(self, conn, ts=None)
for connection based decoders
close and discard the connection object
debug(self, msg)
logs msg at debug level
decode(self, *args, **kw)
# we get the raw output from pcapy as header, data
dump(self, *args, **kw)
write packet data (probably to the PCAP writer if present)
error(self, msg)
logs msg at error level
find(self, addr, state=None)
getASN(self, ip, db=None, notfound='--')
Get ASN associated with an IP.
Requires GeoIP library (geoip2) and data files.
getGeoIP(self, ip, db=None, notfound='--')
Get country code associated with an IP.
Requires GeoIP library (geoip2) and data files.
log(self, msg, level=20)
logs msg at specified level (default of INFO is for -v/--verbose output)
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
parseOptions(self, options={})
option keys:values will set class members (self.key=value)
if key is in optiondict
postFile(self)
postModule(self)
postModule is called after capture stops
default postModule, prints basic decoding stats
preFile(self)
preModule(self)
preModule is called before capture starts
default preModule, dumps object data to debug
stop(self, conn)
stop following connection
handlers will not be called, except for connectionCloseHandler
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
warn(self, msg)
logs msg at warning level
write(self, obj, **kw)
write session data

Data descriptors inherited from dshell.Decoder:
__dict__
dictionary for instance variables (if defined)
__weakref__
list of weak references to the object (if defined)

 
Functions
       
UTF16LEtoUTF8(inbytes)

 
Data
        NTLMSSP_AUTH = 3
NTLMSSP_CHALLENGE = 2
NTLMSSP_IDENT = 'NTLMSSP\x00'
SMB_PROTOCOL = '\xffSMB'
SMB_STATUS_SUCCESS = 0
dObj = smbdecoder