Skip to content

Refactor SMB client to Manticore network/smb/client v1.1.5#1

Open
p0dalirius wants to merge 3 commits into
mainfrom
refactor-manticore-smb-client
Open

Refactor SMB client to Manticore network/smb/client v1.1.5#1
p0dalirius wants to merge 3 commits into
mainfrom
refactor-manticore-smb-client

Conversation

@p0dalirius

@p0dalirius p0dalirius commented Jun 18, 2026

Copy link
Copy Markdown
Collaborator

Summary

Replaces the jfjallid/go-smb SMB stack with the generic Manticore SMB client from github.com/TheManticoreProject/Manticore v1.1.5. SMB usage in this project was confined to two files (the SYSVOL recursive walk and GPP XML retrieval); both now go through the Manticore client.

Motivation

Standardize on the in-house Manticore SMB client, consistent with other tools in TheManticoreProject (e.g. smbclient-ng). The Manticore generic client negotiates the highest dialect the server supports (SMB1/SMB2/SMB3) transparently, where the previous stack was a separate third-party dependency.

Changes

  • core/workers.go
    • FindCPasswords now builds credentials.Credentials and connects with smbclient.Dial, then Login / TreeConnect("SYSVOL"), with Disconnect / Logoff / TreeDisconnect deferred for clean teardown.
    • SMBListFilesRecursivelyAndCallback takes a *smbclient.Client instead of an *smb.Connection. The tree connect now happens once in FindCPasswords rather than per recursion level, and the walk uses client.ListDirectory(dir, "*"). Full paths are built by joining the parent dir with each entry's Name (backslash separated), and the . / .. pseudo-entries returned by the server are skipped.
  • core/crypto/grouppolicypreferencepasswords.go
    • CallbackFunctionCPassword takes a *smbclient.Client; the UNC path now uses client.ServerIdentity().DNSComputerName.
    • File retrieval (session.RetrieveFile) is replaced by a readRemoteFile helper using OpenFile / ReadFile / CloseFile with the appropriate fileflags, streaming the file into the buffer.
  • go.mod / go.sum: drop github.com/jfjallid/go-smb (and its transitive gofork/gokrb5/golog); add github.com/TheManticoreProject/Manticore v1.1.5. go mod tidy brought the toolchain to go 1.24.0 and upgraded a few transitive dependencies pulled in by Manticore.

Verification

  • go build ./... — succeeds.
  • go vet ./... — clean.
  • go test ./... — no test files in the repo; nothing to run.
  • grep -rn "jfjallid\|go-smb\|spnego" over *.go — no remaining references.

Scope of change

  • Files changed: core/workers.go, core/crypto/grouppolicypreferencepasswords.go, go.mod, go.sum.
  • No behavioral changes outside the SMB client swap.## Follow-up: SMB pass-the-hash wiring

The Manticore v1.1.5 SMB stack supports pass-the-hash (the SMB1/SMB2 session setup authenticates from creds.GetNTHash() when set). The -H/--hashes flag, however, was parsed but never propagated to the connection (this predated the refactor). A second commit wires it through:

  • core/config/config.go: add Hashes to config.Credentials.
  • main.go: store authHashes into config.Credentials.Hashes.
  • core/workers.go: pass config.Credentials.Hashes to credentials.NewCredentials instead of "".

Verified against a live host (SMB 2.0.2): authenticating as Administrator with only the NT hash and an empty password succeeds — Login, TreeConnect("SYSVOL"), and ListDirectory all work, and CanPassTheHash() returns true for the parsed hash.

Note: the LDAP DC-enumeration step uses go-ldap/ldap/v3 (not the Manticore LDAP client), so -H still does not apply to that initial LDAP bind — that would be a separate change.## Follow-up: LDAP pass-the-hash wiring

Pass-the-hash is now also honored by the initial LDAP DC-enumeration bind (previously password-only simple bind). go-ldap/ldap/v3 provides NTLMBindWithHash, so no LDAP-client swap is needed:

  • network/ldap/ldap.go: add a hashes field + InitSession parameter; factor binding into a shared authenticate(conn) helper (used by both Connect and CanLogin) that binds over NTLMSSP with the NT hash when -H is supplied, falling back to simple/unauthenticated bind otherwise. The NT hash is parsed with credentials.ParseLMNTHashes.
  • main.go: pass config.Credentials.Hashes to the primary InitSession, and "" for the credential-testing session (which tests recovered cleartext passwords).

Verified end-to-end against a live DC with only the NT hash and an empty password:

$ findgpp --dc-ip 192.168.1.31 --domain TMP-W-2016.local --username Administrator --hashes <nthash>
INFO: Connected as 'TMP-W-2016.LOCAL\Administrator'
INFO: (1/1) Searching for GPPPasswords in '\\TMP-W-2016.TMP-W-2016.local\SYSVOL\' ...

The LDAP bind, DC enumeration, and the SMB SYSVOL connection all authenticated via pass-the-hash.

Replace the jfjallid/go-smb SMB stack with the generic Manticore SMB
client (github.com/TheManticoreProject/Manticore v1.1.5). The recursive
SYSVOL walk and the GPP XML file retrieval now go through the Manticore
client's Dial/Login/TreeConnect/ListDirectory/OpenFile/ReadFile surface,
which negotiates the highest dialect the server supports.
The -H/--hashes flag was parsed but never propagated to the SMB
connection. Carry it through config.Credentials into FindCPasswords so
credentials.NewCredentials receives the NT/LM hashes; the Manticore SMB
client then authenticates with the NT hash (pass-the-hash) instead of
the password.
The LDAP bind only supported simple bind with a password. Carry the
NT/LM hashes into the LDAP session and bind over NTLMSSP with the NT
hash (NTLMBindWithHash) when they are supplied, so the DC enumeration
step honors -H/--hashes like the SMB connection now does. The bind
logic is factored into a shared authenticate helper used by both
Connect and CanLogin.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant