From 5a352de05605caa4d5090e19738be2a9ba47322e Mon Sep 17 00:00:00 2001 From: moloch-- <875022+moloch--@users.noreply.github.com> Date: Wed, 31 Aug 2022 17:43:56 -0700 Subject: [PATCH] Improved state mgmt --- client/command/commands.go | 2 +- client/command/cursed/cursed-chrome.go | 7 ++-- client/command/cursed/cursed-stop.go | 34 +++++++++++++++ client/command/cursed/cursed.go | 58 ++++++++++++++++++++++++++ client/console/console.go | 1 + client/core/curses.go | 11 +++++ 6 files changed, 109 insertions(+), 4 deletions(-) create mode 100644 client/command/cursed/cursed-stop.go diff --git a/client/command/commands.go b/client/command/commands.go index d922d40c00..d02494fc14 100644 --- a/client/command/commands.go +++ b/client/command/commands.go @@ -3313,7 +3313,7 @@ func BindCommands(con *console.SliverConsoleClient) { }, Run: func(ctx *grumble.Context) error { con.Println() - con.Println("You must specify a subcommand, see --help for options") + cursed.CursedCmd(ctx, con) con.Println() return nil }, diff --git a/client/command/cursed/cursed-chrome.go b/client/command/cursed/cursed-chrome.go index 4d00aa1d5f..236ecfc054 100644 --- a/client/command/cursed/cursed-chrome.go +++ b/client/command/cursed/cursed-chrome.go @@ -108,7 +108,7 @@ func CursedChromeCmd(ctx *grumble.Context, con *console.SliverConsoleClient) { } if chromeExt != nil { con.Printf("success!\n") - con.PrintInfof("Found viable Chrome extension: %s%s%s (%s)\n", console.Bold, chromeExt.Title, console.Normal, chromeExt.ID) + con.PrintInfof("Found viable Chrome extension %s%s%s (%s)\n", console.Bold, chromeExt.Title, console.Normal, chromeExt.ID) con.PrintInfof("Injecting payload ... ") ctx, _, _ := overlord.GetChromeContext(chromeExt.WebSocketDebuggerURL, curse) @@ -185,18 +185,19 @@ func startCursedChromeProcess(restore bool, session *clientpb.Session, ctx *grum core.Portfwds.Add(tcpProxy, channelProxy) curse := &core.CursedProcess{ + SessionID: session.ID, BindTCPPort: bindPort, Platform: session.GetOS(), ChromeExePath: chromeExePath, ChromeUserDataDir: chromeUserDataDir, } - core.CursedProcesses.Store(session.ID, curse) + core.CursedProcesses.Store(bindPort, curse) go func() { err := tcpProxy.Run() if err != nil { log.Printf("Proxy error %s", err) } - core.CursedProcesses.Delete(session.ID) + core.CursedProcesses.Delete(bindPort) }() con.PrintInfof("Port forwarding %s -> %s\n", bindAddr, remoteAddr) diff --git a/client/command/cursed/cursed-stop.go b/client/command/cursed/cursed-stop.go new file mode 100644 index 0000000000..be3001e118 --- /dev/null +++ b/client/command/cursed/cursed-stop.go @@ -0,0 +1,34 @@ +package cursed + +/* + Sliver Implant Framework + Copyright (C) 2022 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 ( + "github.com/bishopfox/sliver/client/console" + "github.com/bishopfox/sliver/client/core" + "github.com/desertbit/grumble" +) + +func CursedStopCmd(ctx *grumble.Context, con *console.SliverConsoleClient) { + session := con.ActiveTarget.GetSessionInteractive() + if session == nil { + return + } + bindPort := ctx.Args.Int("bind-port") + core.CursedProcesses.Delete(bindPort) +} diff --git a/client/command/cursed/cursed.go b/client/command/cursed/cursed.go index 5a21783249..36a188142d 100644 --- a/client/command/cursed/cursed.go +++ b/client/command/cursed/cursed.go @@ -1 +1,59 @@ package cursed + +/* + Sliver Implant Framework + Copyright (C) 2022 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" + "strings" + + "github.com/bishopfox/sliver/client/command/settings" + "github.com/bishopfox/sliver/client/console" + "github.com/bishopfox/sliver/client/core" + "github.com/desertbit/grumble" + "github.com/jedib0t/go-pretty/v6/table" +) + +// CursedChromeCmd - Execute a .NET assembly in-memory +func CursedCmd(ctx *grumble.Context, con *console.SliverConsoleClient) { + cursedProcesses := [][]string{} + core.CursedProcesses.Range(func(key, value interface{}) bool { + curse := value.(*core.CursedProcess) + cursedProcesses = append(cursedProcesses, []string{ + fmt.Sprintf("%d", curse.BindTCPPort), strings.Split(curse.SessionID, "-")[0], curse.Platform, curse.ChromeExePath, curse.DebugURL().String(), + }) + return true + }) + if 0 < len(cursedProcesses) { + tw := table.NewWriter() + tw.SetStyle(settings.GetTableStyle(con)) + tw.AppendHeader(table.Row{ + "Bind Port", "Session ID", "Platform", "Executable", "Debug URL", + }) + for _, rowEntries := range cursedProcesses { + row := table.Row{} + for _, entry := range rowEntries { + row = append(row, entry) + } + tw.AppendRow(table.Row(row)) + } + con.Printf("%s\n", tw.Render()) + } else { + con.PrintInfof("No cursed processes\n") + } +} diff --git a/client/console/console.go b/client/console/console.go index c4c746e4c6..e00d71355b 100644 --- a/client/console/console.go +++ b/client/console/console.go @@ -216,6 +216,7 @@ func (con *SliverConsoleClient) EventLoop() { shortID, session.Name, session.RemoteAddress, session.Hostname, session.OS, session.Arch, currentTime) activeSession := con.ActiveTarget.GetSession() core.GetTunnels().CloseForSession(session.ID) + core.CloseCursedProcesses(session.ID) if activeSession != nil && activeSession.ID == session.ID { con.ActiveTarget.Set(nil, nil) con.PrintEventErrorf("Active session disconnected") diff --git a/client/core/curses.go b/client/core/curses.go index bf32fe62c0..2721d85f4d 100644 --- a/client/core/curses.go +++ b/client/core/curses.go @@ -30,6 +30,7 @@ var ( ) type CursedProcess struct { + SessionID string BindTCPPort int Platform string ChromeExePath string @@ -43,3 +44,13 @@ func (c *CursedProcess) DebugURL() *url.URL { Path: "/json", } } + +func CloseCursedProcesses(sessionID string) { + CursedProcesses.Range(func(key, value interface{}) bool { + cursedProcess := value.(*CursedProcess) + if cursedProcess.SessionID == sessionID { + defer CursedProcesses.Delete(key) + } + return true + }) +}