ENUM^:Enumeration

smbclient & smbclient.py

List and browse SMB shares with Samba or Impacket; use modern Kerberos flags, distinguish permissions, and collect selected files with their original paths.

beginnerupdated 2026-10-12smbclient · Impacket

smbclient & smbclient.py

Two different tools, same goal — reading files off SMB (445) shares. Reach for Samba smbclient by default; switch to Impacket smbclient.py when the domain is Kerberos-only (NTLM disabled) or you’re authenticating with a ticket/hash.

smbclient (Samba) — the default

# list shares — anonymous / null session
smbclient -L //10.10.10.5 -N
smbclient -L //10.10.10.5 -U '' -N

# list shares — authenticated
smbclient -L //10.10.10.5 -U 'DOMAIN/user'

# connect to one share
smbclient //10.10.10.5/Development -N
smbclient '//10.10.10.5/IT' -U 'DOMAIN/user'

# pass-the-hash
smbclient //10.10.10.5/C$ --pw-nt-hash -U 'DOMAIN/administrator%<NThash>'
FlagMeaning
-L //hostlist shares
-Nno password (null/anonymous)
-U 'DOM/user%pass'credentials inline (% separates pass)
--pw-nt-hashtreat the -U password as an NT hash (PtH)
-c "cmds"run ;-separated commands then exit (scripting)
--use-kerberos=requiredrequire Kerberos; use the server FQDN and an available ticket
-m SMB3set the maximum protocol level; not an exact-version pin
-W DOMAINset workgroup/domain separately

Inside the smbclient session

smb: \> ls                      # list current dir
smb: \> cd "Internal Dir"       # quote names with spaces
smb: \> get Upgrade_Notice.pdf  # download one file
smb: \> put payload.exe         # upload
smb: \> mget *                  # download many (prompt per file)
smb: \> prompt off              # turn OFF per-file confirmation before mget/mput
smb: \> recurse on              # descend subdirs for mget
smb: \> mask ""                 # clear filename mask so recurse grabs everything
smb: \> tar c loot.tar          # tar the whole share to a local file

Non-interactive mass-loot (recurse everything a share exposes):

smbclient //10.10.10.5/Share -N -c 'prompt off; recurse on; mget *'
# whole share to a tarball:
smbclient //10.10.10.5/Share -N -c 'tar c share.tar'

[!tip] prompt off; recurse on; mask "" is the loot combo Without prompt off every file asks y/n; without recurse on + an empty mask you only get the top directory. Chain all three (via -c or at the prompt) to pull an entire tree in one shot.

smbclient.py (Impacket) — Kerberos-only domains

Samba also supports Kerberos. Require it explicitly rather than relying on deprecated -k or NTLM fallback:

# Kerberos with a prompted password (Impacket builds the TGT)
smbclient.py 'domain.htb/user@dc01.domain.htb' -k -dc-ip 10.10.10.5

# Kerberos from an existing ccache (NTLM off)
export KRB5CCNAME=user.ccache
smbclient.py -k -no-pass domain.htb/user@dc01.domain.htb

# pass-the-hash
smbclient.py -hashes ':<NThash>' 'DOMAIN/administrator@10.10.10.5'

Session commands differ slightly from Samba’s:

# shares                     # list shares
# use CertEnroll             # select a share
# ls
# get file.txt
# put payload.exe
# cat file.txt               # read without downloading
# mkdir / rm / mget          # as expected
FlagMeaning
-kKerberos auth (uses KRB5CCNAME if present)
-no-passdon’t prompt (ticket/-k already covers it)
-hashes [LM]:NTpass-the-hash
-dc-ipDC for Kerberos/name resolution

[!warning] Watch out

  • NT_STATUS_ACCESS_DENIED on -L — null listing is blocked; you need creds. netexec smb $IP -u '' -p '' --shares sometimes still enumerates where smbclient -L -N won’t.
  • Kerberos needs the FQDN and correct clock — use dc.domain.htb, not the IP, and sudo ntpdate <dc> if you get KRB_AP_ERR_SKEW.
  • Spaces in share/dir names must be quoted inside the session (cd "Third-Line Support").
  • smbmap / netexec --shares are faster for which shares are readable/writable at a glance; smbclient is for actually moving files. See below.

Samba Kerberos and targeted collection

export KRB5CCNAME="$PWD/user.ccache"
smbclient //files01.domain.htb/Share --use-kerberos=required -U 'DOMAIN/user'

# Put selected downloads in a local directory; prompt for the password
mkdir -p evidence/smb
smbclient //10.10.10.5/IT -U 'DOMAIN/user'   -c 'lcd evidence/smb; cd Reports; get review.pdf'

List first, select files, then collect. Preserve the share and remote path in your notes. Recursive download can be large and does not preserve the server’s ACLs as evidence. Samba’s recurse, mask and prompt commands are not a portable script for Impacket’s shell.

Success: the account can open the specific share and read the chosen file. Share listing, authentication, read access and write access are separate claims; don’t label a share writable from an ls result. Validate a suspected write permission with an agreed disposable file and remove it afterward.

Work one share without collecting the whole tree

mkdir -p evidence/smb
smbclient //files01.example.test/Department -U 'EXAMPLE/labuser'

At Samba’s prompt:

pwd
ls
cd "Monthly Reports"
ls
allinfo review.pdf
lcd evidence/smb
get review.pdf
quit

allinfo is a Samba command; do not paste it into Impacket’s shell. Keep the server, share, directory and filename in the collection notes. A download to the current local directory does not preserve every server-side metadata field.

Preserve the server name when connecting to an IP

# Samba: logical server name remains the FQDN, TCP connects to the stated IP
smbclient //files01.example.test/Department -I 192.0.2.20 \
  --use-kerberos=required -U 'EXAMPLE/labuser'

# Impacket: service name and connection address are separate options
smbclient.py -k -no-pass -target-ip 192.0.2.20 \
  'example.test/labuser@files01.example.test'

The FQDN is used for the service identity; the address selects the TCP destination. A DNS alias is not necessarily registered as a CIFS SPN. Check the service’s real name before assuming a cache or password is invalid.

Test a suspected write separately

Where a write check is part of the exercise, use a unique disposable text file. In Samba’s shell, put lab-write-proof.txt tests create/write, and del lab-write-proof.txt tests cleanup. Verify deletion. A share can permit creation while denying deletion; record those operations separately and avoid repeatedly leaving new files behind.

Diagnose status codes in context

Error/resultFirst check
NT_STATUS_LOGON_FAILUREUser/domain identity, auth method and material
NT_STATUS_BAD_NETWORK_NAMEExact share name; C$ may not exist or be exposed
NT_STATUS_ACCESS_DENIED on connectShare-level access for the authenticated identity
Access denied on one fileFile/directory ACL, not automatically the entire share
NT_STATUS_OBJECT_NAME_NOT_FOUNDCurrent remote directory and exact filename
Kerberos service-principal errorFQDN/SPN registration, realm and clock
SMB1 workgroup-listing warningWhether the preceding SMB2/3 share list already succeeded

Share discovery may return entries you cannot open. A readable folder can contain unreadable files. Validate the operation needed for the proposed attack chain rather than translating every successful connection into administrator access.

See Also

  • smbmap — read/write permission matrix across all shares at once.
  • NetExec — --shares, --spider_plus, and SMB auth checks.
  • Anonymous / Null Testing — the unauthenticated SMB/RPC/LDAP sweep.
  • Impacket — the rest of the .py toolset for Kerberos domains.

Sources

On this page

☧ CPTS · ordered posts

Locked

Unlock with your Main_Key through local GPG.

Start the local GPG helper

In your cheatsheet checkout, run:

npm run unlock:helper

Open the link it prints, or paste its pairing code below. Keep the terminal open until GPG finishes.

Import an index you already decrypted

Download the encrypted index, then decrypt with GPG:

gpg --output report-index.json --decrypt report-index.gpg

Your private key stays in GPG. The decrypted index is saved in this browser so you can reopen it after navigation, refreshes and restarts. Lock this browser or clear this site's browser data to remove the saved index. Nothing is uploaded.