Skip to content

Commit

Permalink
Reworked runas to act as the windows utility
Browse files Browse the repository at this point in the history
  • Loading branch information
rkervella committed Nov 3, 2022
1 parent e083fa6 commit f8ae372
Show file tree
Hide file tree
Showing 6 changed files with 908 additions and 869 deletions.
4 changes: 3 additions & 1 deletion client/command/commands.go
Original file line number Diff line number Diff line change
Expand Up @@ -2051,7 +2051,9 @@ func BindCommands(con *console.SliverConsoleClient) {
f.String("a", "args", "", "arguments for the process")
f.String("d", "domain", "", "domain of the user")
f.String("P", "password", "", "password of the user")
f.Bool("s", "show-window", false, "show the window of the process")
f.Bool("s", "show-window", false, `
Log on, but use the specified credentials on the network only. The new process uses the same token as the caller, but the system creates a new logon session within LSA, and the process uses the specified credentials as the default credentials.`)
f.Bool("n", "net-only", false, "use ")
f.Int("t", "timeout", 30, "command timeout in seconds")
},
Run: func(ctx *grumble.Context) error {
Expand Down
2 changes: 2 additions & 0 deletions client/command/privilege/runas.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ func RunAsCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
showWindow := ctx.Flags.Bool("show-window")
process := ctx.Flags.String("process")
arguments := ctx.Flags.String("args")
netonly := ctx.Flags.Bool("net-only")

if username == "" {
con.PrintErrorf("Please specify a username\n")
Expand All @@ -60,6 +61,7 @@ func RunAsCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
Domain: domain,
Password: password,
HideWindow: !showWindow,
NetOnly: netonly,
})
if err != nil {
con.PrintErrorf("%s", err)
Expand Down
4 changes: 2 additions & 2 deletions implant/sliver/handlers/handlers_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -153,10 +153,10 @@ func runAsHandler(data []byte, resp RPCResponse) {
return
}
show := 10
if runAsReq.HideWindow == "" {
if runAsReq.HideWindow {
show = 0
}
err = priv.RunAs(runAsReq.Username, runAsReq.Domain, runAsReq.Password, runAsReq.ProcessName, runAsReq.Args, show)
err = priv.RunAs(runAsReq.Username, runAsReq.Domain, runAsReq.Password, runAsReq.ProcessName, runAsReq.Args, show, runAsReq.NetOnly)
runAs := &sliverpb.RunAs{}
if err != nil {
runAs.Response = &commonpb.Response{Err: err.Error()}
Expand Down
48 changes: 36 additions & 12 deletions implant/sliver/priv/priv_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -279,45 +279,61 @@ func deleteRegistryKey(keyPath, keyName string) (err error) {
return
}

func RunAs(username string, domain string, password string, program string, args []string, show int) (err error) {
func RunAs(username string, domain string, password string, program string, args string, show int, netonly bool) (err error) {
// call CreateProcessWithLogonW to create a new process with the specified credentials
// https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-createprocesswithlogonw
// convert username, domain, password, program, args, env, dir to *uint16
u, err := windows.UTF16PtrFromString(username)
if err != nil {
// {{if .Config.Debug}}
log.Printf("Invalid username\n")
// {{end}}
return
}
d, err := windows.UTF16PtrFromString(domain)
if err != nil {
// {{if .Config.Debug}}
log.Printf("Invalid domain\n")
// {{end}}
return
}
p, err := windows.UTF16PtrFromString(password)
if err != nil {
// {{if .Config.Debug}}
log.Printf("Invalid password\n")
// {{end}}
return
}
prog, err := windows.UTF16PtrFromString(program)
if err != nil {
// {{if .Config.Debug}}
log.Printf("Invalid program\n")
// {{end}}
return
}
var cmd *uint16
if len(args) > 0 {
cmd, err = windows.UTF16PtrFromString(strings.Join(args, " "))
cmd, err = windows.UTF16PtrFromString(fmt.Sprintf("%s %s", program, args))
if err != nil {
// {{if .Config.Debug}}
log.Printf("Invalid prog args\n")
// {{end}}
return
}
}
var e *uint16
if len(env) > 0 {
env := os.Environ()
e, err = windows.UTF16PtrFromString(strings.Join(env, "\x00"))
if err != nil {
return
}
}
// env := os.Environ()
// e, err = windows.UTF16PtrFromString(strings.Join(env, "\x00"))
// if err != nil {
// // {{if .Config.Debug}}
// log.Printf("Invalid env\n")
// // {{end}}
// return
// }
var di *uint16

// create a new startup info struct
si := &StartupInfoEx{
si := &syscalls.StartupInfoEx{
StartupInfo: windows.StartupInfo{
Flags: windows.STARTF_USESHOWWINDOW,
ShowWindow: uint16(show),
Expand All @@ -326,8 +342,16 @@ func RunAs(username string, domain string, password string, program string, args
// create a new process info struct
pi := &windows.ProcessInformation{}
// call CreateProcessWithLogonW
err = CreateProcessWithLogonW(u, d, p, 0, prog, cmd, 0, e, di, si, pi)

var logonFlags uint32 = 0
if netonly {
logonFlags = 2 // LOGON_NETCREDENTIALS_ONLY
}
err = syscalls.CreateProcessWithLogonW(u, d, p, logonFlags, prog, cmd, 0, e, di, si, pi)
if err != nil {
// {{if .Config.Debug}}
log.Printf("CreateProcessWithLogonW failed: %v\n", err)
// {{end}}
}
return
}

Expand Down
Loading

0 comments on commit f8ae372

Please sign in to comment.