Skip to content

SMB / NetBIOS

Back to the Technology Index

Impacket’s SMB implementation is both a packet construction library and a session implementation. Most CLIs use only SMBConnection, which hides differences between dialects.

ModuleRole
nmb.pyNetBIOS name resolution and session framing
smb.pySMB1 (NT LM 0.12), \xffSMB
smb3.py + smb3structs.pySMB2 and SMB3, \xfeSMB / \xfdSMB when encrypted
smbconnection.pyClient facade that hides dialect differences
smbserver.pyTest server (SMBSERVER / SimpleSMBServer)

Related commands: smbclient, smbserver, DumpNTLMInfo, psexec, ntlmrelayx

Even on port 445, messages are wrapped in a NetBIOS session message (type 0x00). Only port 139 starts with a SESSION REQUEST (0x81); *SMBSERVER obtains the real name through NBSTAT.

Port constants: SMB_SESSION_PORT=445, NETBIOS_SESSION_PORT=139, NETBIOS_NS_PORT=137.

When no preferred dialect is set, SMBConnection.negotiateSession() places the following in an SMB1 SMB_COM_NEGOTIATE request:

NT LM 0.12 / SMB 2.002 / SMB 2.???

On port 139, it omits SMB 2.???. If the first response byte is \xfe, it selects SMB2/3; otherwise, it stays with SMB1.

smb3.SMB3.negotiateSession() maintains the [MS-SMB2] Connection state.

  • Offered dialects, unless specified: 0x0202 / 0x0210 / 0x0300 / 0x0302 / 0x0311
  • If 3.1.1 is offered: negotiation contexts for Preauth Integrity (SHA-512) and Encryption (AES-128-GCM, AES-128-CCM)
  • RequireSigning if the server sets SIGNING_REQUIRED or the dialect is 3.1.1
  • Switch to SMB3Packet when the dialect is at least 3.0 (Status becomes ChannelSequence in requests)

For 3.1.1, it prefers AES-128-GCM and also offers AES-128-CCM. Versions 3.0 / 3.0.2 do not negotiate the cipher and use AES-128-CCM. Compression is not supported.

Both carry NTLM or a Kerberos AP-REQ inside SPNEGO.

PathEntry PointKey Detail
NTLMlogin()Type1 → Type2 → Type3; exportedSessionKey is the basis for signing and encryption
KerberoskerberosLogin()TGS for cifs/<ServerName>; on KDC_ERR_ETYPE_NOSUPP, retry with an NT hash
Legacy SMB1login_standard()DES(challenge, LM/NT hash) when extended security is absent

The extended SMB1 login temporarily disables Unicode. ntlmFallback applies only to SMB1. When NativeLanMan is Windows 2000 / Samba, it falls back to NTLMv1.

signSMB():

SecurityFeatures = LE64(seq)
MD5(SigningSessionKey || SigningChallengeResponse || packet)[:8]
seq += 2

With an NTLMv2 exported key, the challenge-response portion is empty.

DialectSigning
2.0.2 / 2.1HMAC-SHA256(SessionKey, packet)[:16]
3.xAES_CMAC(SigningKey, packet) (crypto.AES_CMAC)

Key derivation for 3.x uses crypto.KDF_CounterMode (HMAC-SHA256, 128 bits).

Key3.0 / 3.0.23.1.1
SigningKeyLabel SMB2AESCMAC\0, Context SmbSign\0Label SMBSigningKey\0, Context = PreauthHash
ApplicationKeySMB2APP\0 / SmbRpc\0SMBAppKey\0 / PreauthHash
EncryptionKey (C2S)SMB2AESCCM\0 / ServerIn \0SMBC2SCipherKey\0
DecryptionKey (S2C)SMB2AESCCM\0 / ServerOut\0SMBS2CCipherKey\0

When the dialect is at least 3.0 and the server advertises GLOBAL_CAP_ENCRYPTION, the client forces SMB2_SESSION_FLAG_ENCRYPT_DATA unless it is a guest or anonymous session. Encrypted PDUs use the SMB2_TRANSFORM_HEADER marked by \xfdSMB and AES-128-GCM or AES-128-CCM, as selected during negotiation.

RPC over SMB3 uses the ApplicationKey returned by getSessionKey(). It does not use the raw NTLM session key.

connectTree() builds \\host\SHARE and retains the TreeID. The typical DCERPC path is:

  1. connectTree('IPC$')
  2. If needed, call waitNamedPipe (SMB1 TRANS_WAIT_NMPIPE or FSCTL_PIPE_WAIT)
  3. Open \pipe\<name> using create / nt_create_andx
  4. Use transactNamedPipe (TRANS_TRANSACT_NMPIPE=0x26) or FSCTL_PIPE_TRANSCEIVE=0x0011C017

listShares() enumerates shares through srvsvc RPC (NetrShareEnum info level 1) on the same session, not through SMB1 LANMAN. listSharesWithPrivs() uses info level 502 and returns share privilege fields; it requires administrator privileges. The SMB3 client’s list_shared is unimplemented.

SimpleSMBServer / SMBSERVER:

  • SMB1 uses NT LM 0.12 and offers NTLMSSP with extended security
  • SMB2/3 response dialects are 2.0.2, 2.1, and 3.1.1; 3.1.1 supports preauth hashes and AES-128-GCM / AES-128-CCM encryption
  • If the credential store is empty, a path through SMB1 standard security may treat authentication as successful
  • registerNamedPipe can attach in-process DCERPC (srvsvc / wkssvc)
  • Hooks (hookSmbCommand / hookSmb2Command) are used by tools such as karmaSMB

Check individually for unsupported features such as SMB 3.0 / 3.0.2 and multichannel.

  • Oplock breaks and multichannel binding are not implemented. Some compound requests are handled, but do not assume every pattern works
  • Transform decryption verifies GCM / CCM authentication tags
  • The client’s encryption nonce is an 11-character ASCII string for AES-CCM or a 12-character string for AES-GCM, generated with random.choice rather than a CSPRNG
  • negoex is not connected to SMB login
  • Keep dialect branching inside SMBConnection
  • Preserve signing sequences, preauth hashes, and EncryptData per tree
  • For new create options or information classes, check constants for both SMB1 and SMB2
  • Related tests: tests/SMB_RPC/