--- Server Message Block (SMB, also known as CIFS) traffic.
--
-- SMB traffic is normally sent to/from ports 139 or 445 of Windows systems, some of them
-- properly and many of them not. Samba implements it, as do many printers and other embedded
-- devices. Although the protocol has been documented decently well by Samba and others,
-- many 3rd party implementations are broken or make assumptions.
--
-- Naturally, I do the same; however, that being said, this has been tested against every
-- broken implementation we could find, and will accept (or fail gracefully) against any
-- bad implementations we could find.
--
-- The intention of this library is to eventually handle all aspects of the SMB protocol.
-- That being said, I'm only implementing the pieces that I find myself needing. If you
-- require something more, let me know and I'll put it on my todo list.
--
-- A programmer using this library must already have some knowledge of the SMB protocol,
-- although a lot isn't necessary. You can pick up a lot by looking at the code that uses
-- this. The basic login/logoff is this:
--
--
-- [connect]
-- C->S SMB_COM_NEGOTIATE
-- S->C SMB_COM_NEGOTIATE
-- C->S SMB_COM_SESSION_SETUP_ANDX
-- S->C SMB_COM_SESSION_SETUP_ANDX
-- C->S SMB_COM_TREE_CONNECT_ANDX
-- S->C SMB_COM_TREE_CONNECT_ANDX
-- ...
-- C->S SMB_COM_TREE_DISCONNECT
-- S->C SMB_COM_TREE_DISCONNECT
-- C->S SMB_COM_LOGOFF_ANDX
-- S->C SMB_COM_LOGOFF_ANDX
--
--
-- In terms of functions here, the protocol is:
--
--
-- status, smbstate = smb.start(host)
-- status, err = smb.negotiate_protocol(smbstate)
-- status, err = smb.start_session(smbstate)
-- status, err = smb.tree_connect(smbstate, path)
-- ...
-- status, err = smb.tree_disconnect(smbstate)
-- status, err = smb.logoff(smbstate)
-- status, err = smb.stop(smbstate)
--
--
-- The stop
function will automatically call tree_disconnect and logoff,
-- cleaning up the session, if it hasn't been done already.
--
-- To initially begin the connection, there are two options:
--
-- 1) Attempt to start a raw session over 445, if it's open.
--
-- 2) Attempt to start a NetBIOS session over 139. Although the
-- protocol's the same, it requires a session request
packet.
-- That packet requires the computer's name, which is requested
-- using a NBSTAT probe over UDP port 137.
--
-- Once it's connected, a SMB_COM_NEGOTIATE
packet is sent, requesting the protocol
-- "NT LM 0.12", which is the most commonly supported one. Among other things, the server's
-- response contains the host's security level, the system time, and the computer/domain name.
-- Some systems will refuse to use that protocol and return "-1" or "1" instead of 0. If that's
-- detected, we kill the connection (because the protocol following will be unexpected).
--
-- If that's successful, SMB_COM_SESSION_SETUP_ANDX
is sent. It is essentially the logon
-- packet, where the username, domain, and password are sent to the server for verification.
-- The username and password are generally picked up from the program parameters, which are
-- set when running a script, or from the registry [TODO: Where?], which are set by other
-- scripts. However, they can also be passed as parameters to the function, which will
-- override any other username/password set.
--
-- If a username is set without a password, then a NULL session is started. If a login fails,
-- we attempt to log in as the 'GUEST' account with a blank password. If that fails, we try
-- setting up a NULL session. Starting a NULL session will always work, but we may not get
-- any further (tree_connect
might fail).
--
-- In terms of the login protocol, by default, we sent only NTLMv1 authentication, Lanman
-- isn't sent at all. The reason for this is, NTLMv2 isn't supported by every system (and I
-- don't know how to do message signing on the v2 protocols), and doesn't have a significant security
-- advantage over NTLMv1 for performing single scans (the major change in NTLMv2 is incorporating
-- a client challenge). Lanman is somewhat insecure, though, so I don't send it at all. These options
-- can, however, be overridden either through script parameters or registry settings.
--
-- Lanman v1 is a fairly weak protocol, although it's still fairly difficult to break. NTLMv1 is a slightly more secure
-- protocol (although not much) -- it's also fairly difficult to reverse, though. Windows clients, by default send LMv1 and
-- NTLMv1 together, but every modern Windows server will accept NTLM alone, so I opted to use that. LMv2 and NTLMv2 are
-- slightly more secure, and they let the client specify random data (to help fight malicious servers with pre-
-- generated tables). LMv2 and NTLMv2 are identical, except that NTLMv2 has a longer client challenge. LMv2 can be sent
-- alone, but NTLMv2 can't.
--
-- Another interesting aspect of the password hashing is that the original password isn't even necessary, the
-- password's hash can be used instead. This hash can be dumped from memory of a live system by tools such as
-- pwdump and fgdump, or read straight from the SAM file (maybe some day, I'll do an Nmap script to dump it).
-- This means that if a password file is recovered, it doesn't even need to be cracked before it can be used here.
--
-- Thanks go to Christopher R. Hertel and his book Implementing CIFS, which
-- taught me everything I know about Microsoft's protocols. Additionally, I used Samba's
-- list of error codes for my constants, although I don't believe they would be covered
-- by GPL, since they're public now anyways, but I'm not a lawyer and, if somebody feels
-- differently, let me know and we can sort this out.
--
-- Scripts that use this module can use the script arguments
-- smbusername
, smbpassword
, smbhash
,
-- example of using these script arguments:
--
-- nmap --script=smb-