Skip to content

Commit

Permalink
Merge pull request #663 from BishopFox/ux/cdc
Browse files Browse the repository at this point in the history
Ux/cdc
  • Loading branch information
moloch-- authored Apr 14, 2022
2 parents b116ac9 + d9fe00d commit 6dab042
Show file tree
Hide file tree
Showing 20 changed files with 207 additions and 103 deletions.
55 changes: 46 additions & 9 deletions client/command/beacons/beacons.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ package beacons
import (
"context"
"fmt"
"regexp"
"strings"
"time"

Expand Down Expand Up @@ -71,27 +72,36 @@ func BeaconsCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
con.PrintInfof("Killed %s (%s)\n", beacon.Name, beacon.ID)
}
}
filter := ctx.Flags.String("filter")
var filterRegex *regexp.Regexp
if ctx.Flags.String("filter-re") != "" {
var err error
filterRegex, err = regexp.Compile(ctx.Flags.String("filter-re"))
if err != nil {
con.PrintErrorf("%s\n", err)
return
}
}

beacons, err := con.Rpc.GetBeacons(context.Background(), &commonpb.Empty{})
if err != nil {
con.PrintErrorf("%s\n", err)
return
}

PrintBeacons(beacons.Beacons, con)
PrintBeacons(beacons.Beacons, filter, filterRegex, con)
}

// PrintBeacons - Display a list of beacons
func PrintBeacons(beacons []*clientpb.Beacon, con *console.SliverConsoleClient) {
func PrintBeacons(beacons []*clientpb.Beacon, filter string, filterRegex *regexp.Regexp, con *console.SliverConsoleClient) {
if len(beacons) == 0 {
con.PrintInfof("No beacons 🙁\n")
return
}
tw := renderBeacons(beacons, con)
tw := renderBeacons(beacons, filter, filterRegex, con)
con.Printf("%s\n", tw.Render())
}

func renderBeacons(beacons []*clientpb.Beacon, con *console.SliverConsoleClient) table.Writer {
func renderBeacons(beacons []*clientpb.Beacon, filter string, filterRegex *regexp.Regexp, con *console.SliverConsoleClient) table.Writer {
width, _, err := term.GetSize(0)
if err != nil {
width = 999
Expand Down Expand Up @@ -140,8 +150,11 @@ func renderBeacons(beacons []*clientpb.Beacon, con *console.SliverConsoleClient)
eta := time.Until(nextCheckin)
next = fmt.Sprintf("%s%s%s", console.Bold+console.Green, eta, console.Normal)
}

// We need a slice of strings so we can apply filters
var rowEntries []string
if con.Settings.SmallTermWidth < width {
tw.AppendRow(table.Row{
rowEntries = []string{
fmt.Sprintf(color+"%s"+console.Normal, strings.Split(beacon.ID, "-")[0]),
fmt.Sprintf(color+"%s"+console.Normal, beacon.Name),
fmt.Sprintf(color+"%d/%d"+console.Normal, beacon.TasksCountCompleted, beacon.TasksCount),
Expand All @@ -152,17 +165,41 @@ func renderBeacons(beacons []*clientpb.Beacon, con *console.SliverConsoleClient)
fmt.Sprintf(color+"%s/%s"+console.Normal, beacon.OS, beacon.Arch),
fmt.Sprintf(color+"%s ago"+console.Normal, time.Since(time.Unix(beacon.LastCheckin, 0))),
next,
})
}
} else {
tw.AppendRow(table.Row{
rowEntries = []string{
fmt.Sprintf(color+"%s"+console.Normal, strings.Split(beacon.ID, "-")[0]),
fmt.Sprintf(color+"%s"+console.Normal, beacon.Name),
fmt.Sprintf(color+"%s"+console.Normal, beacon.Transport),
fmt.Sprintf(color+"%s"+console.Normal, strings.TrimPrefix(beacon.Username, beacon.Hostname+"\\")),
fmt.Sprintf(color+"%s/%s"+console.Normal, beacon.OS, beacon.Arch),
fmt.Sprintf(color+"%s ago"+console.Normal, time.Since(time.Unix(beacon.LastCheckin, 0))),
next,
})
}
}
// Build the row struct
row := table.Row{}
for _, entry := range rowEntries {
row = append(row, entry)
}
// Apply filters if any
if filter == "" && filterRegex == nil {
tw.AppendRow(row)
} else {
for _, rowEntry := range rowEntries {
if filter != "" {
if strings.Contains(rowEntry, filter) {
tw.AppendRow(row)
break
}
}
if filterRegex != nil {
if filterRegex.MatchString(rowEntry) {
tw.AppendRow(row)
break
}
}
}
}
}
return tw
Expand Down
2 changes: 1 addition & 1 deletion client/command/beacons/watch.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ func BeaconsWatchCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
if err != nil {
panic(err) // If we return we may leak the waiting goroutine, so we panic instead
}
tw := renderBeacons(beacons.Beacons, con)
tw := renderBeacons(beacons.Beacons, "", nil, con)
lines := strings.Split(tw.Render(), "\n")
for _, line := range lines {
con.Printf(console.Clearln+"\r%s\n", line)
Expand Down
20 changes: 14 additions & 6 deletions client/command/commands.go
Original file line number Diff line number Diff line change
Expand Up @@ -399,6 +399,7 @@ func BindCommands(con *console.SliverConsoleClient) {
f.Bool("c", "no-canaries", false, "disable dns canary detection")
f.String("L", "lhost", "", "interface to bind server to")
f.Int("l", "lport", generate.DefaultDNSLPort, "udp listen port")
f.Bool("D", "disable-otp", false, "disable otp authentication")

f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
f.Bool("p", "persistent", false, "make persistent across restarts")
Expand Down Expand Up @@ -558,7 +559,10 @@ func BindCommands(con *console.SliverConsoleClient) {
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.Bool("f", "force", false, "force session action without waiting for results")
f.Bool("F", "force", false, "force session action without waiting for results")

f.String("f", "filter", "", "filter sessions by substring")
f.String("e", "filter-re", "", "filter sessions by regular expression")

f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
},
Expand All @@ -575,7 +579,8 @@ func BindCommands(con *console.SliverConsoleClient) {
Help: "Kill all stale/dead sessions",
LongHelp: help.GetHelpFor([]string{consts.SessionsStr, consts.PruneStr}),
Flags: func(f *grumble.Flags) {
f.Bool("f", "force", false, "Force the killing of stale/dead sessions")
f.Bool("F", "force", false, "Force the killing of stale/dead sessions")

f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
},
Run: func(ctx *grumble.Context) error {
Expand Down Expand Up @@ -615,7 +620,7 @@ func BindCommands(con *console.SliverConsoleClient) {
return nil
},
Flags: func(f *grumble.Flags) {
f.Bool("f", "force", false, "Force kill, does not clean up")
f.Bool("F", "force", false, "Force kill, does not clean up")

f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
},
Expand Down Expand Up @@ -1677,7 +1682,7 @@ func BindCommands(con *console.SliverConsoleClient) {
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.Bool("F", "force", false, "ignore safety and forcefully remove files")

f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
},
Expand Down Expand Up @@ -1913,7 +1918,7 @@ func BindCommands(con *console.SliverConsoleClient) {
a.Uint("pid", "pid")
},
Flags: func(f *grumble.Flags) {
f.Bool("f", "force", false, "disregard safety and kill the PID")
f.Bool("F", "force", false, "disregard safety and kill the PID")

f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
},
Expand Down Expand Up @@ -2163,8 +2168,11 @@ func BindCommands(con *console.SliverConsoleClient) {
Flags: func(f *grumble.Flags) {
f.String("k", "kill", "", "kill a beacon")
f.Bool("K", "kill-all", false, "kill all beacons")
f.Bool("F", "force", false, "force killing of the beacon")
f.String("f", "filter", "", "filter beacons by substring")
f.String("e", "filter-re", "", "filter beacons by regular expression")

f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
f.Bool("f", "force", false, "force killing of the beacon")
},
HelpGroup: consts.GenericHelpGroup,
Run: func(ctx *grumble.Context) error {
Expand Down
1 change: 1 addition & 0 deletions client/command/jobs/dns.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ func DNSListenerCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
Port: uint32(lport),
Canaries: !ctx.Flags.Bool("no-canaries"),
Persistent: ctx.Flags.Bool("persistent"),
EnforceOTP: !ctx.Flags.Bool("disable-otp"),
})
con.Println()
if err != nil {
Expand Down
51 changes: 44 additions & 7 deletions client/command/sessions/sessions.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ package sessions
import (
"context"
"fmt"
"regexp"
"strings"
"time"

Expand Down Expand Up @@ -97,20 +98,31 @@ func SessionsCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
con.PrintErrorf("Invalid session name or session number: %s\n", interact)
}
} else {
filter := ctx.Flags.String("filter")
var filterRegex *regexp.Regexp
if ctx.Flags.String("filter-re") != "" {
var err error
filterRegex, err = regexp.Compile(ctx.Flags.String("filter-re"))
if err != nil {
con.PrintErrorf("%s\n", err)
return
}
}

sessionsMap := map[string]*clientpb.Session{}
for _, session := range sessions.GetSessions() {
sessionsMap[session.ID] = session
}
if 0 < len(sessionsMap) {
PrintSessions(sessionsMap, con)
PrintSessions(sessionsMap, filter, filterRegex, con)
} else {
con.PrintInfof("No sessions 🙁\n")
}
}
}

// PrintSessions - Print the current sessions
func PrintSessions(sessions map[string]*clientpb.Session, con *console.SliverConsoleClient) {
func PrintSessions(sessions map[string]*clientpb.Session, filter string, filterRegex *regexp.Regexp, con *console.SliverConsoleClient) {
width, _, err := term.GetSize(0)
if err != nil {
width = 999
Expand All @@ -128,7 +140,7 @@ func PrintSessions(sessions map[string]*clientpb.Session, con *console.SliverCon
"Hostname",
"Username",
"Operating System",
"Last Check-in",
"Last Message",
"Health",
})
} else {
Expand Down Expand Up @@ -164,8 +176,9 @@ func PrintSessions(sessions map[string]*clientpb.Session, con *console.SliverCon
}
username := strings.TrimPrefix(session.Username, session.Hostname+"\\") // For non-AD Windows users

var rowEntries []string
if con.Settings.SmallTermWidth < width {
tw.AppendRow(table.Row{
rowEntries = []string{
fmt.Sprintf(color+"%s"+console.Normal, ShortSessionID(session.ID)),
fmt.Sprintf(color+"%s"+console.Normal, session.Name),
fmt.Sprintf(color+"%s"+console.Normal, session.Transport),
Expand All @@ -175,17 +188,41 @@ func PrintSessions(sessions map[string]*clientpb.Session, con *console.SliverCon
fmt.Sprintf(color+"%s/%s"+console.Normal, session.OS, session.Arch),
fmt.Sprintf(color+"%s"+console.Normal, time.Unix(session.LastCheckin, 0).Format(time.RFC1123)),
burned + SessionHealth,
})
}
} else {
tw.AppendRow(table.Row{
rowEntries = []string{
fmt.Sprintf(color+"%s"+console.Normal, ShortSessionID(session.ID)),
fmt.Sprintf(color+"%s"+console.Normal, session.Transport),
fmt.Sprintf(color+"%s"+console.Normal, session.RemoteAddress),
fmt.Sprintf(color+"%s"+console.Normal, session.Hostname),
fmt.Sprintf(color+"%s"+console.Normal, username),
fmt.Sprintf(color+"%s/%s"+console.Normal, session.OS, session.Arch),
burned + SessionHealth,
})
}
}
// Build the row struct
row := table.Row{}
for _, entry := range rowEntries {
row = append(row, entry)
}
// Apply filters if any
if filter == "" && filterRegex == nil {
tw.AppendRow(row)
} else {
for _, rowEntry := range rowEntries {
if filter != "" {
if strings.Contains(rowEntry, filter) {
tw.AppendRow(row)
break
}
}
if filterRegex != nil {
if filterRegex.MatchString(rowEntry) {
tw.AppendRow(row)
break
}
}
}
}
}

Expand Down
16 changes: 13 additions & 3 deletions protobuf/clientpb/client.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions protobuf/clientpb/client.proto
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,7 @@ message DNSListenerReq {
string Host = 3;
uint32 Port = 4;
bool Persistent = 5;
bool EnforceOTP = 6;
}

message DNSListener {
Expand Down
2 changes: 1 addition & 1 deletion protobuf/commonpb/common.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion protobuf/dnspb/dns.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion protobuf/rpcpb/services.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion protobuf/sliverpb/sliver.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 6dab042

Please sign in to comment.