From 990c8bbca032d11ca641de0ab90ab85fb765803b Mon Sep 17 00:00:00 2001 From: psycep Date: Wed, 22 Apr 2026 09:54:09 -0500 Subject: [PATCH] tools: migrate flags.Parse tools to transport Four tools that already used flags.Parse (and therefore already had -proxy registered transparently) still reached out via net.Dial* or ran DNS resolution past the proxy. Migrate the network calls: - tools/GetADComputers: custom net.Resolver now dials via transport.DialContext, so UDP DNS through the DC surfaces ErrUDPUnderProxy cleanly rather than bypassing -proxy. - tools/changepasswd: kpasswd TCP dial now uses transport.DialTimeout. - tools/smbexec: getLocalIP() short-circuits when transport.IsProxyConfigured(). The "dial UDP to find the local source address" trick has no meaning when traffic flows through a SOCKS5 proxy. - tools/raiseChild: the DNS forest-FQDN fallback (net.LookupHost) is skipped under -proxy with a message pointing the user to -parent-dc, since net.LookupHost goes to the OS resolver and would leak DNS. --- tools/GetADComputers/main.go | 7 ++++--- tools/changepasswd/main.go | 4 ++-- tools/raiseChild/main.go | 10 +++++++++- tools/smbexec/main.go | 10 +++++++++- 4 files changed, 24 insertions(+), 7 deletions(-) diff --git a/tools/GetADComputers/main.go b/tools/GetADComputers/main.go index 3a00ec2..15ed989 100644 --- a/tools/GetADComputers/main.go +++ b/tools/GetADComputers/main.go @@ -28,6 +28,7 @@ import ( "gopacket/pkg/flags" "gopacket/pkg/ldap" "gopacket/pkg/session" + "gopacket/pkg/transport" ) var ( @@ -161,12 +162,12 @@ func resolveHostname(hostname, dnsServer string) string { return "" } - // Use custom resolver to query the DC's DNS + // Custom resolver using the DC's DNS. Under -proxy, UDP DNS cannot be + // tunneled via SOCKS5; callers should pass an IP directly in that case. resolver := &net.Resolver{ PreferGo: true, Dial: func(ctx context.Context, network, address string) (net.Conn, error) { - d := net.Dialer{Timeout: 2 * time.Second} - return d.DialContext(ctx, "udp", dnsServer+":53") + return transport.DialContext(ctx, network, dnsServer+":53") }, } diff --git a/tools/changepasswd/main.go b/tools/changepasswd/main.go index d54120e..2875170 100644 --- a/tools/changepasswd/main.go +++ b/tools/changepasswd/main.go @@ -20,7 +20,6 @@ import ( "fmt" "io" "log" - "net" "os" "strings" "time" @@ -33,6 +32,7 @@ import ( "gopacket/pkg/ldap" "gopacket/pkg/session" "gopacket/pkg/smb" + "gopacket/pkg/transport" goldap "github.com/go-ldap/ldap/v3" krbclient "github.com/jcmturner/gokrb5/v8/client" @@ -616,7 +616,7 @@ func doKpasswd(opts *flags.Options, target session.Target, targetUsername, targe // sendKpasswd sends a kpasswd request to the KDC on TCP port 464 and returns the response. func sendKpasswd(kdc string, data []byte) ([]byte, error) { addr := fmt.Sprintf("%s:464", kdc) - conn, err := net.DialTimeout("tcp", addr, 10*time.Second) + conn, err := transport.DialTimeout("tcp", addr, 10) if err != nil { return nil, fmt.Errorf("failed to connect to kpasswd %s: %v", addr, err) } diff --git a/tools/raiseChild/main.go b/tools/raiseChild/main.go index 641ee82..cf48b33 100644 --- a/tools/raiseChild/main.go +++ b/tools/raiseChild/main.go @@ -35,6 +35,7 @@ import ( "gopacket/pkg/kerberos" "gopacket/pkg/session" "gopacket/pkg/smb" + "gopacket/pkg/transport" ) var ( @@ -356,7 +357,14 @@ func discoverParentDC(forestFQDN string, target session.Target, creds *session.C } } - // Fallback: DNS resolution of forest FQDN + // Fallback: DNS resolution of forest FQDN. Disabled under -proxy because + // net.LookupHost uses the OS resolver, which would silently bypass the + // configured SOCKS5 proxy and leak DNS. Callers should pass the parent DC + // explicitly via -parent-dc in that case. + if transport.IsProxyConfigured() { + fmt.Println("[!] DNS fallback disabled under -proxy, pass parent DC explicitly via -parent-dc") + return "" + } addrs, err := net.LookupHost(forestFQDN) if err == nil && len(addrs) > 0 { fmt.Printf("[*] DNS resolved %s to %s\n", forestFQDN, addrs[0]) diff --git a/tools/smbexec/main.go b/tools/smbexec/main.go index 39686fa..f7ea088 100644 --- a/tools/smbexec/main.go +++ b/tools/smbexec/main.go @@ -36,6 +36,7 @@ import ( "gopacket/pkg/flags" "gopacket/pkg/session" "gopacket/pkg/smb" + "gopacket/pkg/transport" ) var ( @@ -446,8 +447,15 @@ func (e *SMBExec) finish() { } } -// getLocalIP determines the local IP address used to reach the target host +// getLocalIP determines the local IP address used to reach the target host. +// Under -proxy the concept doesn't apply (traffic flows via the proxy, not +// directly from this host), so we return "" and let the caller fall back. +// The UDP socket here doesn't actually send packets — it just asks the kernel +// which source address would be picked for a hypothetical connection. func getLocalIP(targetHost string) string { + if transport.IsProxyConfigured() { + return "" + } conn, err := net.Dial("udp", targetHost+":445") if err != nil { return ""