Python: module smbdecoder

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