mirror of
https://github.com/BishopFox/sliver.git
synced 2026-11-09 01:49:40 -10:00
Compare commits
3
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
afe6c88f83 | ||
|
|
361a4e5112 | ||
|
|
4e7093671c |
No files matched your search
+1
-1
@@ -1,4 +1,4 @@
|
||||
FROM golang:1.18.3
|
||||
FROM golang:1.18.4
|
||||
|
||||
#
|
||||
# IMPORTANT: This Dockerfile is used for testing, I do not recommend deploying
|
||||
|
||||
@@ -35,6 +35,7 @@ type ClientSettings struct {
|
||||
BeaconAutoResults bool `json:"beacon_autoresults"`
|
||||
SmallTermWidth int `json:"small_term_width"`
|
||||
AlwaysOverflow bool `json:"always_overflow"`
|
||||
VimMode bool `json:"vim_mode"`
|
||||
}
|
||||
|
||||
// LoadSettings - Load the client settings from disk
|
||||
@@ -59,6 +60,7 @@ func defaultSettings() *ClientSettings {
|
||||
BeaconAutoResults: true,
|
||||
SmallTermWidth: 170,
|
||||
AlwaysOverflow: false,
|
||||
VimMode: false,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -47,6 +47,7 @@ func SettingsCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
|
||||
tw.AppendRow(table.Row{"Beacon Auto Results", con.Settings.BeaconAutoResults, "Automatically display beacon results when tasks complete"})
|
||||
tw.AppendRow(table.Row{"Small Term Width", con.Settings.SmallTermWidth, "Omit some table columns when terminal width is less than this value"})
|
||||
tw.AppendRow(table.Row{"Always Overflow", con.Settings.AlwaysOverflow, "Disable table pagination"})
|
||||
tw.AppendRow(table.Row{"Vim mode", con.Settings.VimMode, "Navigation mode, vim style"})
|
||||
con.Printf("%s\n", tw.Render())
|
||||
}
|
||||
|
||||
|
||||
@@ -113,6 +113,7 @@ func Start(rpc rpcpb.SliverRPCClient, bindCmds BindCmds, extraCmds BindCmds, isS
|
||||
HelpHeadlineColor: color.New(),
|
||||
HelpHeadlineUnderline: true,
|
||||
HelpSubCommands: true,
|
||||
VimMode: settings.VimMode,
|
||||
}),
|
||||
Rpc: rpc,
|
||||
ActiveTarget: &ActiveTarget{
|
||||
|
||||
+1
-1
@@ -20,7 +20,7 @@ set -e
|
||||
|
||||
# Creates the static go asset archives
|
||||
|
||||
GO_VER="1.18.3"
|
||||
GO_VER="1.18.4"
|
||||
GARBLE_VER="1.18.0"
|
||||
|
||||
GO_ARCH_1="amd64"
|
||||
|
||||
@@ -2,7 +2,7 @@ module github.com/bishopfox/sliver
|
||||
|
||||
go 1.17
|
||||
|
||||
replace github.com/desertbit/grumble v1.1.1 => github.com/moloch--/grumble v1.1.4
|
||||
replace github.com/desertbit/grumble v1.1.1 => github.com/moloch--/grumble v1.1.6
|
||||
|
||||
require (
|
||||
github.com/AlecAivazis/survey/v2 v2.2.2
|
||||
|
||||
@@ -648,8 +648,8 @@ github.com/modern-go/reflect2 v0.0.0-20180320133207-05fbef0ca5da/go.mod h1:bx2lN
|
||||
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/mohae/deepcopy v0.0.0-20170308212314-bb9b5e7adda9/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8=
|
||||
github.com/moloch--/grumble v1.1.4 h1:/utJ405bbS2/Kx73XE03zqP1a3ZE9p3vqD3ePvsrG8o=
|
||||
github.com/moloch--/grumble v1.1.4/go.mod h1:r7j3ShNy5EmOsegRD2DzTutIaGiLiA3M5yBTXXeLwcs=
|
||||
github.com/moloch--/grumble v1.1.6 h1:FjPkuGOIwGL8nGkEH0EegnQgsl6Rn0R0fhBW/kcA0s8=
|
||||
github.com/moloch--/grumble v1.1.6/go.mod h1:r7j3ShNy5EmOsegRD2DzTutIaGiLiA3M5yBTXXeLwcs=
|
||||
github.com/moloch--/memmod v0.0.0-20211120144554-8b37cc654945 h1:m3yCfV8Vqp4MF1B+gPPjbjINdufl0UXqyYplE0aGhx8=
|
||||
github.com/moloch--/memmod v0.0.0-20211120144554-8b37cc654945/go.mod h1:1grVt4HaTofvhFUZYtofeRbGXfczNwCie9MYoM4lP/o=
|
||||
github.com/mrunalp/fileutils v0.5.0/go.mod h1:M1WthSahJixYnrXQl/DFQuteStB1weuxD2QJNHXfbSQ=
|
||||
|
||||
@@ -109,7 +109,7 @@ func (e *ECCKeyPair) PrivateBase64() string {
|
||||
return base64.RawStdEncoding.EncodeToString(e.Private[:])
|
||||
}
|
||||
|
||||
// RandomeECCKeyPair - Generate a random Curve 25519 key pair
|
||||
// RandomECCKeyPair - Generate a random Curve 25519 key pair
|
||||
func RandomECCKeyPair() (*ECCKeyPair, error) {
|
||||
public, private, err := box.GenerateKey(rand.Reader)
|
||||
if err != nil {
|
||||
|
||||
@@ -894,7 +894,6 @@ const (
|
||||
// GoPrivate - The default Go private arg to garble when obfuscation is enabled.
|
||||
// Wireguard dependencies prevent the use of wildcard github.com/* and golang.org/*.
|
||||
// The current packages below aren't definitive and need to be tidied up.
|
||||
// GoPrivate = "github.com/bishopfox/*,github.com/Microsoft/*,github.com/burntsushi/*,github.com/kbinani/*,github.com/lxn/*,github.com/golang/*,github.com/shm/*,github.com/lesnuages/*"
|
||||
wgGoPrivate = "github.com/*,golang.org/*,golang.zx2c4.com/*,google.golang.org/*"
|
||||
allGoPrivate = "*"
|
||||
)
|
||||
|
||||
+45
-1
@@ -81,11 +81,55 @@ Builtin support for multiple lines.
|
||||
... command
|
||||
```
|
||||
|
||||
## Separate flags and args specifically
|
||||
If you need to pass a flag-like value as positional argument, you can do so by using a double dash:
|
||||
`>>> command --flag1=something -- --myPositionalArg`
|
||||
|
||||
## Remote shell access with readline
|
||||
By calling RunWithReadline() rather than Run() you can pass instance of readline.Instance.
|
||||
One of interesting usages is having a possibility of remote access to your shell:
|
||||
|
||||
```go
|
||||
handleFunc := func(rl *readline.Instance) {
|
||||
|
||||
var app = grumble.New(&grumble.Config{
|
||||
// override default interrupt handler to avoid remote shutdown
|
||||
InterruptHandler: func(a *grumble.App, count int) {
|
||||
// do nothing
|
||||
},
|
||||
|
||||
// your usual grumble configuration
|
||||
})
|
||||
|
||||
// add commands
|
||||
|
||||
app.RunWithReadline(rl)
|
||||
|
||||
}
|
||||
|
||||
cfg := &readline.Config{}
|
||||
readline.ListenRemote("tcp", ":5555", cfg, handleFunc)
|
||||
```
|
||||
|
||||
In the client code just use readline built in DialRemote function:
|
||||
|
||||
```go
|
||||
if err := readline.DialRemote("tcp", ":5555"); err != nil {
|
||||
fmt.Errorf("An error occurred: %s \n", err.Error())
|
||||
}
|
||||
```
|
||||
|
||||
## Samples
|
||||
|
||||
Check out the [sample directory](/sample) for some detailed examples.
|
||||
|
||||
The [grml project](https://github.com/desertbit/grml) uses grumble.
|
||||
## Projects using Grumble
|
||||
|
||||
- grml - A simple build automation tool written in Go: https://github.com/desertbit/grml
|
||||
- orbit - A RPC-like networking backend written in Go: https://github.com/desertbit/orbit
|
||||
|
||||
## Known issues
|
||||
- Windows unicode not fully supported ([issue](https://github.com/desertbit/grumble/issues/48))
|
||||
|
||||
## Additional Useful Packages
|
||||
|
||||
|
||||
+61
-31
@@ -80,6 +80,9 @@ func New(c *Config) (a *App) {
|
||||
printCommandHelp: defaultPrintCommandHelp,
|
||||
interruptHandler: defaultInterruptHandler,
|
||||
}
|
||||
if c.InterruptHandler != nil {
|
||||
a.interruptHandler = c.InterruptHandler
|
||||
}
|
||||
|
||||
// Register the builtin flags.
|
||||
a.flags.Bool("h", "help", false, "display help")
|
||||
@@ -118,6 +121,7 @@ func (a *App) Config() *Config {
|
||||
}
|
||||
|
||||
// Commands returns the app's commands.
|
||||
// Access is not thread-safe. Only access during command execution.
|
||||
func (a *App) Commands() *Commands {
|
||||
return &a.commands
|
||||
}
|
||||
@@ -277,8 +281,21 @@ func (a *App) RunCommand(args []string) error {
|
||||
// Run the application and parse the command line arguments.
|
||||
// This method blocks.
|
||||
func (a *App) Run() (err error) {
|
||||
// Create the readline instance.
|
||||
config := &readline.Config{}
|
||||
a.setReadlineDefaults(config)
|
||||
rl, err := readline.NewEx(config)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return a.RunWithReadline(rl)
|
||||
}
|
||||
|
||||
func (a *App) RunWithReadline(rl *readline.Instance) (err error) {
|
||||
defer a.Close()
|
||||
|
||||
a.setReadlineDefaults(rl.Config)
|
||||
|
||||
// Sort all commands by their name.
|
||||
a.commands.SortRecursive()
|
||||
|
||||
@@ -323,6 +340,7 @@ func (a *App) Run() (err error) {
|
||||
a.printCommandHelp(a, cmd, a.isShell)
|
||||
return nil
|
||||
},
|
||||
isBuiltin: true,
|
||||
}, false)
|
||||
|
||||
// Check if help should be displayed.
|
||||
@@ -331,6 +349,30 @@ func (a *App) Run() (err error) {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Add shell builtin commands.
|
||||
// Ensure to add all commands before running the init hook.
|
||||
// If the init hook does something with the app commands, then these should also be included.
|
||||
if a.isShell {
|
||||
a.AddCommand(&Command{
|
||||
Name: "exit",
|
||||
Help: "exit the shell",
|
||||
Run: func(c *Context) error {
|
||||
c.Stop()
|
||||
return nil
|
||||
},
|
||||
isBuiltin: true,
|
||||
})
|
||||
a.AddCommand(&Command{
|
||||
Name: "clear",
|
||||
Help: "clear the screen",
|
||||
Run: func(c *Context) error {
|
||||
readline.ClearScreen(a.rl)
|
||||
return nil
|
||||
},
|
||||
isBuiltin: true,
|
||||
})
|
||||
}
|
||||
|
||||
// Run the init hook.
|
||||
if a.initHook != nil {
|
||||
err = a.initHook(a, a.flagMap)
|
||||
@@ -344,36 +386,8 @@ func (a *App) Run() (err error) {
|
||||
return a.RunCommand(args)
|
||||
}
|
||||
|
||||
// Add shell builtin commands.
|
||||
a.AddCommand(&Command{
|
||||
Name: "exit",
|
||||
Help: "exit the shell",
|
||||
Run: func(c *Context) error {
|
||||
c.Stop()
|
||||
return nil
|
||||
},
|
||||
})
|
||||
a.AddCommand(&Command{
|
||||
Name: "clear",
|
||||
Help: "clear the screen",
|
||||
Run: func(c *Context) error {
|
||||
readline.ClearScreen(a.rl)
|
||||
return nil
|
||||
},
|
||||
})
|
||||
|
||||
// Create the readline instance.
|
||||
a.rl, err = readline.NewEx(&readline.Config{
|
||||
Prompt: a.currentPrompt,
|
||||
HistorySearchFold: true, // enable case-insensitive history searching
|
||||
DisableAutoSaveHistory: true,
|
||||
HistoryFile: a.config.HistoryFile,
|
||||
HistoryLimit: a.config.HistoryLimit,
|
||||
AutoComplete: newCompleter(&a.commands),
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Assign readline instance
|
||||
a.rl = rl
|
||||
a.OnClose(a.rl.Close)
|
||||
|
||||
// Run the shell hook.
|
||||
@@ -393,6 +407,16 @@ func (a *App) Run() (err error) {
|
||||
return a.runShell()
|
||||
}
|
||||
|
||||
func (a *App) setReadlineDefaults(config *readline.Config) {
|
||||
config.Prompt = a.currentPrompt
|
||||
config.HistorySearchFold = true
|
||||
config.DisableAutoSaveHistory = true
|
||||
config.HistoryFile = a.config.HistoryFile
|
||||
config.HistoryLimit = a.config.HistoryLimit
|
||||
config.AutoComplete = newCompleter(&a.commands)
|
||||
config.VimMode = a.config.VimMode
|
||||
}
|
||||
|
||||
func (a *App) runShell() error {
|
||||
var interruptCount int
|
||||
var lines []string
|
||||
@@ -461,7 +485,13 @@ Loop:
|
||||
err = a.RunCommand(args)
|
||||
if err != nil {
|
||||
a.PrintError(err)
|
||||
continue Loop
|
||||
// Do not continue the Loop here. We want to handle command changes below.
|
||||
}
|
||||
|
||||
// Sort the commands again if they have changed (Add or remove action).
|
||||
if a.commands.hasChanged() {
|
||||
a.commands.SortRecursive()
|
||||
a.commands.unsetChanged()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+5
-4
@@ -67,10 +67,11 @@ type Command struct {
|
||||
// A non-nil Completer overrides the default behaviour.
|
||||
Completer func(prefix string, args []string) []string
|
||||
|
||||
parent *Command
|
||||
flags Flags
|
||||
args Args
|
||||
commands Commands
|
||||
parent *Command
|
||||
flags Flags
|
||||
args Args
|
||||
commands Commands
|
||||
isBuiltin bool // Whenever this is a build-in command not added by the user.
|
||||
}
|
||||
|
||||
func (c *Command) validate() error {
|
||||
|
||||
+42
-9
@@ -30,29 +30,43 @@ import (
|
||||
|
||||
// Commands collection.
|
||||
type Commands struct {
|
||||
list []*Command
|
||||
list []*Command
|
||||
changed bool // Used to resort if something changes.
|
||||
}
|
||||
|
||||
// Add the command to the slice.
|
||||
// Duplicates are ignored.
|
||||
func (c *Commands) Add(cmd *Command) {
|
||||
c.list = append(c.list, cmd)
|
||||
c.changed = true
|
||||
}
|
||||
|
||||
// Remove a command from the slice.
|
||||
func (c *Commands) Remove(name string) {
|
||||
var index int
|
||||
var cmd *Command
|
||||
found := false
|
||||
for index, cmd = range c.list {
|
||||
func (c *Commands) Remove(name string) (found bool) {
|
||||
for index, cmd := range c.list {
|
||||
if cmd.Name == name {
|
||||
found = true
|
||||
break
|
||||
c.changed = true
|
||||
c.list = append(c.list[:index], c.list[index+1:]...)
|
||||
return
|
||||
}
|
||||
}
|
||||
if found {
|
||||
c.list = append(c.list[:index], c.list[index+1:]...)
|
||||
return
|
||||
}
|
||||
|
||||
func (c *Commands) RemoveAll() {
|
||||
var builtins []*Command
|
||||
|
||||
// Hint: There are no built-in sub commands. Ignore them.
|
||||
for _, cmd := range c.list {
|
||||
if cmd.isBuiltin {
|
||||
builtins = append(builtins, cmd)
|
||||
}
|
||||
}
|
||||
|
||||
// Only keep the builtins.
|
||||
c.list = builtins
|
||||
c.changed = true
|
||||
}
|
||||
|
||||
// All returns a slice of all commands.
|
||||
@@ -108,6 +122,25 @@ func (c *Commands) SortRecursive() {
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Commands) hasChanged() bool {
|
||||
if c.changed {
|
||||
return true
|
||||
}
|
||||
for _, sc := range c.list {
|
||||
if sc.commands.hasChanged() {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (c *Commands) unsetChanged() {
|
||||
c.changed = false
|
||||
for _, sc := range c.list {
|
||||
sc.commands.unsetChanged()
|
||||
}
|
||||
}
|
||||
|
||||
// parse the args and return a command path to the root.
|
||||
// cmds slice is empty, if no command was found.
|
||||
func (c *Commands) parse(
|
||||
|
||||
+6
@@ -54,6 +54,9 @@ type Config struct {
|
||||
// NoColor defines if color output should be disabled.
|
||||
NoColor bool
|
||||
|
||||
// VimMode defines if Readline is to use VimMode for line navigation.
|
||||
VimMode bool
|
||||
|
||||
// Prompt defines the shell prompt.
|
||||
Prompt string
|
||||
PromptColor *color.Color
|
||||
@@ -70,6 +73,9 @@ type Config struct {
|
||||
HelpHeadlineUnderline bool
|
||||
HelpSubCommands bool
|
||||
HelpHeadlineColor *color.Color
|
||||
|
||||
// Override default iterrupt handler
|
||||
InterruptHandler func(a *App, count int)
|
||||
}
|
||||
|
||||
// SetDefaults sets the default values if not set.
|
||||
|
||||
+2
-3
@@ -26,7 +26,6 @@ package grumble
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"runtime"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
@@ -130,9 +129,9 @@ Loop:
|
||||
}
|
||||
args = args[1:]
|
||||
|
||||
// A double dash (--) is used in most Bash commands to signify the end of command options,
|
||||
// A double dash (--) is used to signify the end of command options,
|
||||
// after which only positional arguments are accepted.
|
||||
if a == "--" && runtime.GOOS == "linux" {
|
||||
if a == "--" {
|
||||
break Loop
|
||||
}
|
||||
|
||||
|
||||
Vendored
+1
-1
@@ -107,7 +107,7 @@ github.com/desertbit/columnize
|
||||
# github.com/desertbit/go-shlex v0.1.1
|
||||
## explicit; go 1.14
|
||||
github.com/desertbit/go-shlex
|
||||
# github.com/desertbit/grumble v1.1.1 => github.com/moloch--/grumble v1.1.4
|
||||
# github.com/desertbit/grumble v1.1.1 => github.com/moloch--/grumble v1.1.6
|
||||
## explicit; go 1.12
|
||||
github.com/desertbit/grumble
|
||||
# github.com/desertbit/readline v1.5.1
|
||||
|
||||
Reference in new issue
Block a user