Skip to content

Commit

Permalink
Add process name to getprivs and cleaning up getprivs code
Browse files Browse the repository at this point in the history
  • Loading branch information
RafBishopFox committed Aug 21, 2021
1 parent 59bdaa7 commit c4101f5
Show file tree
Hide file tree
Showing 5 changed files with 80 additions and 32 deletions.
10 changes: 8 additions & 2 deletions client/command/privilege/getprivs.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ import (
*/

func GetPrivsCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
var processName string = "Current Process"

session := con.ActiveSession.GetInteractive()
if session == nil {
return
Expand Down Expand Up @@ -58,11 +60,15 @@ func GetPrivsCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
return
}

if privs.ProcessName != "" {
processName = privs.ProcessName
}

// To make things look pretty, figure out the longest name and description
// for column width
var nameColumnWidth int = 0
var descriptionColumnWidth int = 0
var introWidth int = 49 + len(strconv.Itoa(int(session.PID)))
var introWidth int = 34 + len(processName) + len(strconv.Itoa(int(session.PID)))

for _, entry := range privs.PrivInfo {
if len(entry.Name) > nameColumnWidth {
Expand All @@ -77,7 +83,7 @@ func GetPrivsCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
nameColumnWidth += 1
descriptionColumnWidth += 1

con.Printf("Privilege Information for Current Process (PID: %d)\n", session.PID)
con.Printf("Privilege Information for %s (PID: %d)\n", processName, session.PID)
con.Println(strings.Repeat("-", introWidth))
con.Printf("\nProcess Integrity Level: %s\n\n", privs.ProcessIntegrity)
con.Printf("%-*s\t%-*s\t%s\n", nameColumnWidth, "Name", descriptionColumnWidth, "Description", "Attributes")
Expand Down
3 changes: 2 additions & 1 deletion implant/sliver/handlers/handlers_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -543,7 +543,7 @@ func getPrivsHandler(data []byte, resp RPCResponse) {
return
}

privsInfo, integrity, err := priv.GetPrivs()
privsInfo, integrity, processName, err := priv.GetPrivs()

response_data := make([]*sliverpb.WindowsPrivilegeEntry, len(privsInfo))

Expand All @@ -569,6 +569,7 @@ func getPrivsHandler(data []byte, resp RPCResponse) {
getPrivsResp := &sliverpb.GetPrivs{
PrivInfo: response_data,
ProcessIntegrity: integrity,
ProcessName: processName,
Response: &commonpb.Response{},
}

Expand Down
71 changes: 50 additions & 21 deletions implant/sliver/priv/priv_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -344,12 +344,12 @@ func GetSystem(data []byte, hostingProcess string) (err error) {
return
}

func getProcessIntegrityLevel(processToken syscall.Token) (string, error) {
func getProcessIntegrityLevel(processToken windows.Token) (string, error) {
// A place to put the size of the token integrity information
var tokenIntegrityBufferSize uint32

// Determine the integrity of the process
syscall.GetTokenInformation(processToken, windows.TokenIntegrityLevel, nil, 0, &tokenIntegrityBufferSize)
windows.GetTokenInformation(processToken, windows.TokenIntegrityLevel, nil, 0, &tokenIntegrityBufferSize)

if tokenIntegrityBufferSize < 4 {
// {{if .Config.Debug}}
Expand All @@ -360,8 +360,8 @@ func getProcessIntegrityLevel(processToken syscall.Token) (string, error) {

tokenIntegrityBuffer := make([]byte, tokenIntegrityBufferSize)

err := syscall.GetTokenInformation(processToken,
syscall.TokenIntegrityLevel,
err := windows.GetTokenInformation(processToken,
windows.TokenIntegrityLevel,
&tokenIntegrityBuffer[0],
tokenIntegrityBufferSize,
&tokenIntegrityBufferSize,
Expand Down Expand Up @@ -441,44 +441,73 @@ func lookupPrivilegeNameByLUID(luid uint64) (string, string, error) {
return syscall.UTF16ToString(nameBuffer), syscall.UTF16ToString(displayNameBuffer), nil
}

func GetPrivs() ([]PrivilegeInfo, string, error) {
func GetPrivs() ([]PrivilegeInfo, string, string, error) {
// A place to store the process token
var tokenHandle syscall.Token
var tokenHandle windows.Token

// Process integrity
var integrity string

// The current process name
var processName string

// A place to put the size of the token information
var tokenInfoBufferSize uint32

// Get a handle for the current process
currentProcHandle, err := syscall.GetCurrentProcess()
currentProcHandle, err := windows.GetCurrentProcess()

if err != nil {
// {{if .Config.Debug}}
log.Println("Could not get a handle for the current process: ", err)
// {{end}}
return nil, "", err
return nil, integrity, processName, err
}

// Get the PID for the current process
sessionPID, err := windows.GetProcessId(currentProcHandle)

// This error is not fatal. Worst case, we can display the PID from the registered session
if err != nil {
// {{if .Config.Debug}}
log.Println("Could not get PID for current process: ", err)
// {{end}}
} else {
// Get process info for the current PID
processInformation, err := ps.FindProcess(int(sessionPID))

if err != nil {
// {{if .Config.Debug}}
log.Printf("Could not get process information for PID %d: %v\n", sessionPID, err)
// {{end}}
}

if processInformation != nil {
processName = processInformation.Executable()
}
}

// Get the process token from the current process
err = syscall.OpenProcessToken(currentProcHandle, syscall.TOKEN_QUERY, &tokenHandle)
err = windows.OpenProcessToken(currentProcHandle, windows.TOKEN_QUERY, &tokenHandle)

if err != nil {
// {{if .Config.Debug}}
log.Println("Could not open process token: ", err)
// {{end}}
return nil, "", err
return nil, integrity, processName, err
}

// Get the size of the token information buffer so we know how large of a buffer to allocate
// This produces an error about a data area passed to the syscall being too small, but
// we do not care about that because we just want to know how big of a buffer to make
syscall.GetTokenInformation(tokenHandle, syscall.TokenPrivileges, nil, 0, &tokenInfoBufferSize)
windows.GetTokenInformation(tokenHandle, windows.TokenPrivileges, nil, 0, &tokenInfoBufferSize)

// Make the buffer and get token information
// Using a bytes Buffer so that we can Read from it later
tokenInfoBuffer := bytes.NewBuffer(make([]byte, tokenInfoBufferSize))

err = syscall.GetTokenInformation(tokenHandle,
syscall.TokenPrivileges,
err = windows.GetTokenInformation(tokenHandle,
windows.TokenPrivileges,
&tokenInfoBuffer.Bytes()[0],
uint32(tokenInfoBuffer.Len()),
&tokenInfoBufferSize,
Expand All @@ -488,7 +517,7 @@ func GetPrivs() ([]PrivilegeInfo, string, error) {
// {{if .Config.Debug}}
log.Println("Error in call to GetTokenInformation (privileges): ", err)
// {{end}}
return nil, "", err
return nil, integrity, processName, err
}

// The first 32 bits is the number of privileges in the structure
Expand All @@ -499,7 +528,7 @@ func GetPrivs() ([]PrivilegeInfo, string, error) {
// {{if .Config.Debug}}
log.Println("Could not read the number of privileges from the token information.")
// {{end}}
return nil, "", err
return nil, integrity, processName, err
}

/*
Expand Down Expand Up @@ -528,7 +557,7 @@ func GetPrivs() ([]PrivilegeInfo, string, error) {
// {{if .Config.Debug}}
log.Println("Could not read the LUID from the binary stream: ", err)
// {{end}}
return privInfo, "", err
return privInfo, integrity, processName, err
}

// Read the attributes
Expand All @@ -537,15 +566,15 @@ func GetPrivs() ([]PrivilegeInfo, string, error) {
// {{if .Config.Debug}}
log.Println("Could not read the attributes from the binary stream: ", err)
// {{end}}
return privInfo, "", err
return privInfo, integrity, processName, err
}

currentPrivInfo.Name, currentPrivInfo.Description, err = lookupPrivilegeNameByLUID(luid)
if err != nil {
// {{if .Config.Debug}}
log.Println("Could not get privilege info based on the LUID: ", err)
// {{end}}
return privInfo, "", err
return privInfo, integrity, processName, err
}

// Figure out the attributes
Expand All @@ -558,11 +587,11 @@ func GetPrivs() ([]PrivilegeInfo, string, error) {
}

// Get the process integrity before we leave
integrity, err := getProcessIntegrityLevel(tokenHandle)
integrity, err = getProcessIntegrityLevel(tokenHandle)

if err != nil {
return privInfo, "Could not determine integrity level", err
return privInfo, "Could not determine integrity level", processName, err
}

return privInfo, integrity, nil
return privInfo, integrity, processName, nil
}
27 changes: 19 additions & 8 deletions protobuf/sliverpb/sliver.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions protobuf/sliverpb/sliver.proto
Original file line number Diff line number Diff line change
Expand Up @@ -831,6 +831,7 @@ message WindowsPrivilegeEntry {
message GetPrivs {
repeated WindowsPrivilegeEntry PrivInfo = 1;
string ProcessIntegrity = 2;
string ProcessName = 3;

commonpb.Response Response = 9;
}

0 comments on commit c4101f5

Please sign in to comment.