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
+ })
+}