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.
This commit is contained in:
psycep
2026-04-22 09:54:09 -05:00
parent efccf92228
commit 990c8bbca0
4 changed files with 24 additions and 7 deletions
+4 -3
View File
@@ -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")
},
}
+2 -2
View File
@@ -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)
}
+9 -1
View File
@@ -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])
+9 -1
View File
@@ -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 ""