Skip to content

Commit

Permalink
Updated version of go-smb library to add support for NTLM relaying an…
Browse files Browse the repository at this point in the history
…d to establish connection via an upstream SOCKS5 proxy. Also added a verbose flag to print some more logging
  • Loading branch information
jfjallid committed Dec 10, 2023
1 parent b9b0f53 commit c2dddb2
Show file tree
Hide file tree
Showing 4 changed files with 109 additions and 39 deletions.
13 changes: 11 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

## Description
Package go-shareenum is a tool build to enumerate SMB shares in a Windows
domain. It is built on top of the library https://github.com/jfjallid/go-smb
domain. It is built on top of the library [go-smb](https://github.com/jfjallid/go-smb)
and provides functionality to list SMB shares and enumerate the files.

## Usage
Expand All @@ -15,9 +15,10 @@ options:
-d, --domain Domain name to use for login
-u, --user Username
-p, --pass Password
-n, --no-pass Disable password prompt and send no credentials
--hash Hex encoded NT Hash for user password
--local Authenticate as a local user instead of domain user
-n, --null Attempt null session authentication
--null Attempt null session authentication
-t, --timeout Dial timeout in seconds (default 5)
--enum List available SMB shares
--exclude Comma-separated list of shares to exclude
Expand All @@ -32,9 +33,17 @@ options:
--min-size Minimum file size to include in results in bytes
--download <outdir> Attempt to download all the files in the filtered result set.
-r, --recurse Recursively list directories on server
--relay Start an SMB listener that will relay incoming
NTLM authentications to the remote server and
use that connection. NOTE that this forces SMB 2.1
without encryption.
--relay-port <port> Listening port for relay (default 445)
--socks-host <target> Establish connection via a SOCKS5 proxy server
--socks-port <port> SOCKS5 proxy port (default 1080)
--noenc Disable smb encryption
--smb2 Force smb 2.1
--debug Enable debug logging
--verbose Enable verbose logging
-v, --version Show version
```

Expand Down
4 changes: 3 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,14 @@ module github.com/jfjallid/go-shareenum
go 1.19

require (
github.com/jfjallid/go-smb v0.2.8
github.com/jfjallid/go-smb v0.3.0
github.com/jfjallid/golog v0.3.3
golang.org/x/net v0.6.0
golang.org/x/term v0.5.0
)

require (
github.com/jfjallid/ber v1.1.0 // indirect
golang.org/x/crypto v0.6.0 // indirect
golang.org/x/sys v0.5.0 // indirect
)
8 changes: 6 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
github.com/jfjallid/go-smb v0.2.8 h1:ZvQWVAtfLJuNQW94Pa5tKybowb3s+hVfKvt6m38aTQE=
github.com/jfjallid/go-smb v0.2.8/go.mod h1:Kew0ysf3f+GtnBzpU7jiZmZ4ohp4ZHE7z2PMnXXG7IM=
github.com/jfjallid/ber v1.1.0 h1:hVaxa1K4vBwh5Arvc70uhatZephEgJpRTHKQCf4u7OA=
github.com/jfjallid/ber v1.1.0/go.mod h1:EJC7yARA25HsUp0G498XpiJahwGx+T+HKh2LHZ/QslA=
github.com/jfjallid/go-smb v0.3.0 h1:PBm0FMtZ4tkDe41DdXrgOt8QXgKUvfcWUcQkKQku2K4=
github.com/jfjallid/go-smb v0.3.0/go.mod h1:ImsLHX4xjKkSbKottJO9+qyhDo/b72QiaXh2n6E6ZTY=
github.com/jfjallid/golog v0.3.3 h1:dY6qf8wTxJ9OwBPVTadVRDmt/6MVXSWwXrxaGMMyXsU=
github.com/jfjallid/golog v0.3.3/go.mod h1:19Q/zg5OgPPd0xhFllokPnMzthzhFPZmiAGAokE7k58=
golang.org/x/crypto v0.6.0 h1:qfktjS5LUO+fFKeJXZ+ikTRijMmljikvG68fpMMruSc=
golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58=
golang.org/x/net v0.6.0 h1:L4ZwwTvKW9gr0ZMS1yrHD9GZhIuVjOBBnaKH+SPQK0Q=
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.5.0 h1:n2a8QNdAb0sZNpU9R1ALUXBbY+w51fCQDN+7EdxNBsY=
Expand Down
123 changes: 89 additions & 34 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import (

rundebug "runtime/debug"

"golang.org/x/net/proxy"
"golang.org/x/term"

"github.com/jfjallid/go-smb/smb"
Expand All @@ -41,7 +42,7 @@ import (
)

var log = golog.Get("")
var release string = "0.1.6"
var release string = "0.1.7"
var includedExts map[string]interface{}
var excludedExts map[string]interface{}
var excludedFolders map[string]interface{}
Expand Down Expand Up @@ -291,9 +292,10 @@ var helpMsg = `
-d, --domain Domain name to use for login
-u, --user Username
-p, --pass Password
-n, --no-pass Disable password prompt and send no credentials
--hash Hex encoded NT Hash for user password
--local Authenticate as a local user instead of domain user
-n, --null Attempt null session authentication
--null Attempt null session authentication
-t, --timeout Dial timeout in seconds (default 5)
--enum List available SMB shares
--exclude Comma-separated list of shares to exclude
Expand All @@ -308,16 +310,24 @@ var helpMsg = `
--min-size Minimum file size to include in results in bytes
--download <outdir> Attempt to download all the files in the filtered result set.
-r, --recurse Recursively list directories on server
--relay Start an SMB listener that will relay incoming
NTLM authentications to the remote server and
use that connection. NOTE that this forces SMB 2.1
without encryption.
--relay-port <port> Listening port for relay (default 445)
--socks-host <target> Establish connection via a SOCKS5 proxy server
--socks-port <port> SOCKS5 proxy port (default 1080)
--noenc Disable smb encryption
--smb2 Force smb 2.1
--debug Enable debug logging
--verbose Enable verbose logging
-v, --version Show version
`

func main() {
var host, username, password, hash, domain, shareFlag, excludeShareFlag, includeName, includeExt, excludeExt, excludeFolder string
var port, dialTimeout int
var debug, dirList, recurse, shareEnumFlag, noEnc, forceSMB2, localUser, nullSession, version bool
var host, username, password, hash, domain, shareFlag, excludeShareFlag, includeName, includeExt, excludeExt, excludeFolder, socksIP string
var port, dialTimeout, socksPort, relayPort int
var debug, dirList, recurse, shareEnumFlag, noEnc, forceSMB2, localUser, nullSession, version, verbose, relay, noPass bool
var err error

flag.Usage = func() {
Expand All @@ -336,6 +346,7 @@ func main() {
flag.IntVar(&port, "P", 445, "")
flag.IntVar(&port, "port", 445, "")
flag.BoolVar(&debug, "debug", false, "")
flag.BoolVar(&verbose, "verbose", false, "")
flag.StringVar(&shareFlag, "shares", "", "")
flag.BoolVar(&dirList, "list", false, "")
flag.BoolVar(&recurse, "r", false, "")
Expand All @@ -353,21 +364,33 @@ func main() {
flag.BoolVar(&localUser, "local", false, "")
flag.IntVar(&dialTimeout, "t", 5, "")
flag.IntVar(&dialTimeout, "timeout", 5, "")
flag.BoolVar(&nullSession, "n", false, "")
flag.BoolVar(&nullSession, "null", false, "")
flag.BoolVar(&version, "v", false, "")
flag.BoolVar(&version, "version", false, "")
flag.BoolVar(&relay, "relay", false, "")
flag.IntVar(&relayPort, "relay-port", 445, "")
flag.StringVar(&socksIP, "socks-host", "", "")
flag.IntVar(&socksPort, "socks-port", 1080, "")
flag.BoolVar(&noPass, "no-pass", false, "")
flag.BoolVar(&noPass, "n", false, "")

flag.Parse()

if debug {
golog.Set("github.com/jfjallid/go-smb/smb", "smb", golog.LevelDebug, golog.LstdFlags|golog.Lshortfile, golog.DefaultOutput, golog.DefaultErrOutput)
golog.Set("github.com/jfjallid/go-smb/gss", "gss", golog.LevelDebug, golog.LstdFlags|golog.Lshortfile, golog.DefaultOutput, golog.DefaultErrOutput)
golog.Set("github.com/jfjallid/go-smb/smb/dcerpc", "dcerpc", golog.LevelDebug, golog.LstdFlags|golog.Lshortfile, golog.DefaultOutput, golog.DefaultErrOutput)
log.SetFlags(golog.LstdFlags | golog.Lshortfile)
log.SetLogLevel(golog.LevelDebug)
} else if verbose {
golog.Set("github.com/jfjallid/go-smb/smb", "smb", golog.LevelInfo, golog.LstdFlags|golog.Lshortfile, golog.DefaultOutput, golog.DefaultErrOutput)
golog.Set("github.com/jfjallid/go-smb/gss", "gss", golog.LevelInfo, golog.LstdFlags|golog.Lshortfile, golog.DefaultOutput, golog.DefaultErrOutput)
golog.Set("github.com/jfjallid/go-smb/smb/dcerpc", "dcerpc", golog.LevelInfo, golog.LstdFlags|golog.Lshortfile, golog.DefaultOutput, golog.DefaultErrOutput)
log.SetLogLevel(golog.LevelInfo)
} else {
golog.Set("github.com/jfjallid/go-smb/smb", "smb", golog.LevelError, golog.LstdFlags|golog.Lshortfile, golog.DefaultOutput, golog.DefaultErrOutput)
golog.Set("github.com/jfjallid/go-smb/gss", "gss", golog.LevelError, golog.LstdFlags|golog.Lshortfile, golog.DefaultOutput, golog.DefaultErrOutput)
golog.Set("github.com/jfjallid/go-smb/smb", "smb", golog.LevelNotice, golog.LstdFlags|golog.Lshortfile, golog.DefaultOutput, golog.DefaultErrOutput)
golog.Set("github.com/jfjallid/go-smb/gss", "gss", golog.LevelNotice, golog.LstdFlags|golog.Lshortfile, golog.DefaultOutput, golog.DefaultErrOutput)
golog.Set("github.com/jfjallid/go-smb/smb/dcerpc", "dcerpc", golog.LevelNotice, golog.LstdFlags|golog.Lshortfile, golog.DefaultOutput, golog.DefaultErrOutput)
}

if version {
Expand Down Expand Up @@ -452,6 +475,12 @@ func main() {
}
}

if socksIP != "" && isFlagSet("timeout") {
log.Errorln("When a socks proxy is specified, --timeout is not supported")
flag.Usage()
return
}

if dialTimeout < 1 {
log.Errorln("Valid value for the timeout is > 0 seconds")
return
Expand All @@ -466,18 +495,23 @@ func main() {
}
}

if (password == "") && (hashBytes == nil) {
if (username != "") && (!nullSession) {
// Check if password is already specified to be empty
if !isFlagSet("P") && !isFlagSet("pass") {
fmt.Printf("Enter password: ")
passBytes, err := term.ReadPassword(int(os.Stdin.Fd()))
fmt.Println()
if err != nil {
log.Errorln(err)
return
if noPass {
password = ""
hashBytes = nil
} else {
if (password == "") && (hashBytes == nil) {
if (username != "") && (!nullSession) {
// Check if password is already specified to be empty
if !isFlagSet("P") && !isFlagSet("pass") {
fmt.Printf("Enter password: ")
passBytes, err := term.ReadPassword(int(os.Stdin.Fd()))
fmt.Println()
if err != nil {
log.Errorln(err)
return
}
password = string(passBytes)
}
password = string(passBytes)
}
}
}
Expand All @@ -489,32 +523,52 @@ func main() {
excludedShares[part] = true
}

timeout, err := time.ParseDuration(fmt.Sprintf("%ds", dialTimeout))
if err != nil {
log.Errorln(err)
return
}
options := smb.Options{
Host: host,
Port: port,
Initiator: &smb.NTLMInitiator{
User: username,
Password: password,
Hash: hashBytes,
Domain: domain,
LocalUser: localUser,
NullSession: nullSession,
EncryptionDisabled: noEnc,
User: username,
Password: password,
Hash: hashBytes,
Domain: domain,
LocalUser: localUser,
NullSession: nullSession,
},
DisableEncryption: noEnc,
ForceSMB2: forceSMB2,
DialTimeout: timeout,
}
session, err := smb.NewConnection(options)

// Only if not using SOCKS
if socksIP == "" {
options.DialTimeout, err = time.ParseDuration(fmt.Sprintf("%ds", dialTimeout))
if err != nil {
log.Errorln(err)
return
}
}

var session *smb.Connection

if socksIP != "" {
dialSocksProxy, err := proxy.SOCKS5("tcp", fmt.Sprintf("%s:%d", socksIP, socksPort), nil, proxy.Direct)
if err != nil {
log.Errorln(err)
return
}
options.ProxyDialer = dialSocksProxy
}

if relay {
options.RelayPort = relayPort
session, err = smb.NewRelayConnection(options)
} else {
session, err = smb.NewConnection(options)
}
if err != nil {
log.Criticalln(err)
return
}

defer session.Close()

if session.IsSigningRequired.Load() {
Expand All @@ -524,9 +578,10 @@ func main() {
}

if session.IsAuthenticated {
log.Noticeln("[+] Login successful")
log.Noticef("[+] Login successful as %s\n", session.GetAuthUsername())
} else {
log.Noticeln("[-] Login failed")
return
}

if shareEnumFlag {
Expand Down

0 comments on commit c2dddb2

Please sign in to comment.