Compare commits

..
229 Commits
Author SHA1 Message Date
moloch-- a8d59daded tidy 2025-12-31 10:12:28 -06:00
moloch-- 9195376993 Refactor survey to huh 2025-12-31 10:04:27 -06:00
moloch-- a6de8e0304 Add profile forms 2025-12-31 09:13:21 -06:00
moloch-- 310619526d Tweak settings 2025-12-31 08:40:02 -06:00
moloch-- 1990777c4b Tweak settings 2025-12-31 08:39:55 -06:00
moloch-- 9570556a87 Refactor to use debug.BuildInfo for version info 2025-12-31 08:27:09 -06:00
moloch-- b563919c19 Update x/crypto 2025-12-31 08:03:33 -06:00
moloch-- f1858ee8f3 Add 'generate beacon' form 2025-12-31 07:58:27 -06:00
moloch-- 46a8313a33 Tweak generate form 2025-12-31 07:51:57 -06:00
moloch-- 868b2c294c Merge branch 'master' into fix/dnsc2 2025-12-30 23:04:32 -06:00
moloch-- 9827b4df4b Add forms pkg 2025-12-30 23:04:03 -06:00
moloch-- a48309a813 Add forms pkg 2025-12-30 23:03:55 -06:00
moloch-- 5df5dec5d4 Add forms pkg 2025-12-30 23:03:46 -06:00
Joe 3ff3ef2ed4 Merge pull request #2076 from BishopFox/fix/dnsc2
Add cleanup to unit tests to avoid excessive disk usage
2025-12-30 21:59:21 -07:00
moloch-- 73cc8c38ff Add cleanup to unit tests to avoid excessive disk usage 2025-12-30 17:47:49 -06:00
Joe ec7e2facbc Merge pull request #2075 from BishopFox/fix/dnsc2
Improvements to DNS C2, Port go-assest.sh to Golang
2025-12-30 15:37:37 -07:00
Joe 4969c2dc51 Merge branch 'master' into fix/dnsc2 2025-12-30 15:36:27 -07:00
moloch-- 94cb60b1f7 Updates to tests and implementation of dns c2 2025-12-30 16:35:37 -06:00
moloch-- 33fcfd54ef Update makefile to make goos/goarch override easier 2025-12-30 13:04:52 -06:00
moloch-- 10bb248e50 Code cleanup 2025-12-30 12:18:05 -06:00
moloch-- e023fd507e Port go-assets.sh to golang with go run 2025-12-30 11:55:56 -06:00
moloch-- 1a9f0f38dd Port go-assets.sh to golang with go run 2025-12-30 10:56:02 -06:00
moloch-- 02831a80bf Cleanup outputs of go-assets.sh 2025-12-30 10:26:24 -06:00
moloch-- 9ccff1798e Expand and update dns c2 unit tests 2025-12-30 09:46:49 -06:00
Joe cd5ef8b5c6 Merge pull request #2063 from BishopFox/3e11dependabot/npm_and_yarn/docs/sliver-docs/next-15.5.9
Bump next from 15.5.7 to 15.5.9 in /docs/sliver-docs
2025-12-30 08:12:38 -07:00
moloch-- dda1fdbbc2 Update dns unit tests 2025-12-30 08:52:26 -06:00
Joe 3b49df5662 Merge pull request #2067 from BishopFox/350cdependabot/github_actions/actions/upload-artifact-6
Bump actions/upload-artifact from 5 to 6
2025-12-29 21:44:47 -07:00
Joe 32be71ff8e Merge pull request #2069 from BishopFox/0d1adependabot/github_actions/actions/download-artifact-7
Bump actions/download-artifact from 6 to 7
2025-12-29 21:44:33 -07:00
Joe 3f77da1524 Merge pull request #2068 from BishopFox/f7cedependabot/github_actions/actions/cache-5
Bump actions/cache from 4 to 5
2025-12-29 21:44:19 -07:00
Joe bae3e9e45d Merge pull request #2074 from BishopFox/polite-zig
Update zig download to be more polite and secure issue #2065
2025-12-29 14:52:04 -07:00
moloch-- 205f5b4196 Update zig download to be more polite and secure issue #2065 2025-12-29 12:04:27 -06:00
dependabot[bot] fae7e211a7 Bump actions/download-artifact from 6 to 7
Bumps [actions/download-artifact](https://github.com/actions/download-artifact) from 6 to 7.
- [Release notes](https://github.com/actions/download-artifact/releases)
- [Commits](https://github.com/actions/download-artifact/compare/v6...v7)

---
updated-dependencies:
- dependency-name: actions/download-artifact
  dependency-version: '7'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <[email protected]>
2025-12-15 03:02:52 +00:00
dependabot[bot] 346da14431 Bump actions/cache from 4 to 5
Bumps [actions/cache](https://github.com/actions/cache) from 4 to 5.
- [Release notes](https://github.com/actions/cache/releases)
- [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md)
- [Commits](https://github.com/actions/cache/compare/v4...v5)

---
updated-dependencies:
- dependency-name: actions/cache
  dependency-version: '5'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <[email protected]>
2025-12-15 03:02:47 +00:00
dependabot[bot] 15174f6c31 Bump actions/upload-artifact from 5 to 6
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 5 to 6.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/v5...v6)

---
updated-dependencies:
- dependency-name: actions/upload-artifact
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <[email protected]>
2025-12-15 03:02:44 +00:00
dependabot[bot] f29df040bb Bump next from 15.5.7 to 15.5.9 in /docs/sliver-docs
Bumps [next](https://github.com/vercel/next.js) from 15.5.7 to 15.5.9.
- [Release notes](https://github.com/vercel/next.js/releases)
- [Changelog](https://github.com/vercel/next.js/blob/canary/release.js)
- [Commits](https://github.com/vercel/next.js/compare/v15.5.7...v15.5.9)

---
updated-dependencies:
- dependency-name: next
  dependency-version: 15.5.9
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <[email protected]>
2025-12-12 01:53:24 +00:00
Joe 0bbecc16ec Merge pull request #2060 from BishopFox/go/v1.25.5
Go v1.25.5
2025-12-05 13:29:26 -07:00
moloch-- 0c216161c2 npm update 2025-12-05 12:28:39 -08:00
moloch-- 8ad9c62eb5 Go v1.25.5 2025-12-04 20:12:24 -08:00
Joe 4c99fbfd82 Merge pull request #2059 from BishopFox/e722dependabot/npm_and_yarn/docs/sliver-docs/next-15.5.7
Bump next from 15.5.4 to 15.5.7 in /docs/sliver-docs
2025-12-04 15:48:34 -07:00
dependabot[bot] ed713e199c Bump next from 15.5.4 to 15.5.7 in /docs/sliver-docs
Bumps [next](https://github.com/vercel/next.js) from 15.5.4 to 15.5.7.
- [Release notes](https://github.com/vercel/next.js/releases)
- [Changelog](https://github.com/vercel/next.js/blob/canary/release.js)
- [Commits](https://github.com/vercel/next.js/compare/v15.5.4...v15.5.7)

---
updated-dependencies:
- dependency-name: next
  dependency-version: 15.5.7
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <[email protected]>
2025-12-04 20:55:48 +00:00
Joe aacdb71c4a Merge pull request #2058 from BishopFox/e72edependabot/npm_and_yarn/docs/sliver-docs/mdast-util-to-hast-13.2.1
Bump mdast-util-to-hast from 13.2.0 to 13.2.1 in /docs/sliver-docs
2025-12-04 13:54:17 -07:00
dependabot[bot] 6968c3aae5 Bump mdast-util-to-hast from 13.2.0 to 13.2.1 in /docs/sliver-docs
Bumps [mdast-util-to-hast](https://github.com/syntax-tree/mdast-util-to-hast) from 13.2.0 to 13.2.1.
- [Release notes](https://github.com/syntax-tree/mdast-util-to-hast/releases)
- [Commits](https://github.com/syntax-tree/mdast-util-to-hast/compare/13.2.0...13.2.1)

---
updated-dependencies:
- dependency-name: mdast-util-to-hast
  dependency-version: 13.2.1
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <[email protected]>
2025-12-02 04:02:29 +00:00
Joe 410fd93025 Merge pull request #2052 from BishopFox/d161dependabot/github_actions/actions/checkout-6
Bump actions/checkout from 5 to 6
2025-11-23 22:11:44 -07:00
dependabot[bot] f2a0435dd2 Bump actions/checkout from 5 to 6
Bumps [actions/checkout](https://github.com/actions/checkout) from 5 to 6.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v5...v6)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <[email protected]>
2025-11-24 03:04:10 +00:00
Joe d66ec956a4 Merge pull request #2037 from BishopFox/2979dependabot/go_modules/tailscale.com-1.90.6
Bump tailscale.com from 1.90.2 to 1.90.6
2025-11-03 12:57:04 -07:00
dependabot[bot] 8229722735 Bump tailscale.com from 1.90.2 to 1.90.6
Bumps [tailscale.com](https://github.com/tailscale/tailscale) from 1.90.2 to 1.90.6.
- [Release notes](https://github.com/tailscale/tailscale/releases)
- [Commits](https://github.com/tailscale/tailscale/compare/v1.90.2...v1.90.6)

---
updated-dependencies:
- dependency-name: tailscale.com
  dependency-version: 1.90.6
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <[email protected]>
2025-11-03 03:04:28 +00:00
Joe dcd81a4db7 Merge pull request #2035 from BishopFox/util/rand
Secure Rand Utils
2025-11-02 10:01:16 -07:00
Joe 2617387417 Merge pull request #2028 from BishopFox/586cdependabot/go_modules/tailscale.com-1.90.2
Bump tailscale.com from 1.88.4 to 1.90.2
2025-11-02 09:39:38 -07:00
moloch-- 56aee7d6e4 Add missing pkg 2025-11-02 09:21:34 -07:00
moloch-- b4f07e8629 Fix various uses of util in implant/ 2025-11-02 08:39:31 -07:00
moloch-- 280cb34049 Replace most instances of insecureRand with util funcs wrapping secure rand 2025-11-02 08:25:14 -07:00
Joe 8e5c5f1450 Merge commit from fork
Fix GHSA-q8j9-34qf-7vq7
2025-10-27 15:58:48 -07:00
Joe b8f4f0c1ea Merge pull request #2027 from BishopFox/dbf6dependabot/github_actions/actions/upload-artifact-5
Bump actions/upload-artifact from 4 to 5
2025-10-26 22:16:59 -07:00
Joe 17cb7fbd50 Merge pull request #2030 from BishopFox/cd33dependabot/github_actions/actions/download-artifact-6
Bump actions/download-artifact from 5 to 6
2025-10-26 22:16:47 -07:00
Joe 9963bc6a3f Merge pull request #2031 from BishopFox/implant/dep-updates
Update implant's x/crypto version
2025-10-26 22:16:30 -07:00
moloch-- 274943f383 Update implant's x/crypto version 2025-10-26 20:13:26 -07:00
dependabot[bot] be81755056 Bump actions/download-artifact from 5 to 6
Bumps [actions/download-artifact](https://github.com/actions/download-artifact) from 5 to 6.
- [Release notes](https://github.com/actions/download-artifact/releases)
- [Commits](https://github.com/actions/download-artifact/compare/v5...v6)

---
updated-dependencies:
- dependency-name: actions/download-artifact
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <[email protected]>
2025-10-27 03:05:46 +00:00
dependabot[bot] a5861c43f2 Bump tailscale.com from 1.88.4 to 1.90.2
Bumps [tailscale.com](https://github.com/tailscale/tailscale) from 1.88.4 to 1.90.2.
- [Release notes](https://github.com/tailscale/tailscale/releases)
- [Commits](https://github.com/tailscale/tailscale/compare/v1.88.4...v1.90.2)

---
updated-dependencies:
- dependency-name: tailscale.com
  dependency-version: 1.90.2
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <[email protected]>
2025-10-27 03:04:45 +00:00
dependabot[bot] e3025a2da2 Bump actions/upload-artifact from 4 to 5
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 4 to 5.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/v4...v5)

---
updated-dependencies:
- dependency-name: actions/upload-artifact
  dependency-version: '5'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <[email protected]>
2025-10-27 03:03:53 +00:00
Joe 40cc1f4eeb Merge pull request #2024 from BishopFox/blincoln-2025-10-21-01
Fix Windows network adapter retrieval for DNS C2, add additional logging
2025-10-24 11:41:04 -07:00
Ben Lincoln b117a1325d Fix Windows network adapter retrieval for DNS C2, add additional logging 2025-10-21 12:08:44 -07:00
Joe a809989536 Merge pull request #2022 from BishopFox/go/v1.25.3
Update to Go v1.25.3
2025-10-19 22:11:07 -07:00
moloch-- a9ee3ca9ed Update some deps 2025-10-19 21:31:03 -07:00
moloch-- 56d972dd32 Update some deps 2025-10-19 21:17:40 -07:00
moloch-- b4091264d7 Update to Go v1.25.3 2025-10-19 21:09:39 -07:00
Joe 23bf325a66 Merge pull request #2015 from BishopFox/sgn-wasm
Sgn wasm
2025-10-19 20:42:54 -07:00
moloch-- d9344a4c79 Run native bin for unit tests 2025-10-19 19:41:04 -07:00
moloch-- 67d9a772e3 Add shellcode+sgn build to unit tests 2025-10-19 18:56:08 -07:00
moloch-- dae284e62e Add sgn unit tests to go-tests.sh 2025-10-19 18:35:11 -07:00
moloch-- 60f48bdc51 Add sgn unit tests 2025-10-19 18:26:15 -07:00
moloch-- 0d7885de29 Replace subprocess with library call 2025-10-19 17:18:34 -07:00
moloch-- d41d29fc1e Replace CGO build of sgn with wasm/pure-go 2025-10-19 17:09:36 -07:00
Joe 3f400bd3f0 Merge pull request #2004 from BishopFox/5069dependabot/github_actions/actions/upload-pages-artifact-4
Bump actions/upload-pages-artifact from 3 to 4
2025-10-12 15:39:17 -07:00
Joe d43f664821 Merge pull request #2003 from BishopFox/7682dependabot/github_actions/actions/setup-go-6
Bump actions/setup-go from 5 to 6
2025-10-12 15:39:06 -07:00
Joe 85c57c07da Merge pull request #2006 from BishopFox/3c4bdependabot/github_actions/actions/download-artifact-5
Bump actions/download-artifact from 4 to 5
2025-10-12 15:38:56 -07:00
Joe 60d15447e0 Merge pull request #2005 from BishopFox/dd46dependabot/github_actions/actions/setup-node-5
Bump actions/setup-node from 4 to 5
2025-10-12 15:38:44 -07:00
Joe 6351b2d671 Merge pull request #2007 from BishopFox/52f6dependabot/github_actions/actions/checkout-5
Bump actions/checkout from 4 to 5
2025-10-12 15:38:32 -07:00
dependabot[bot] c7535ec509 Bump actions/checkout from 4 to 5
Bumps [actions/checkout](https://github.com/actions/checkout) from 4 to 5.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v4...v5)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: '5'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <[email protected]>
2025-10-06 03:03:10 +00:00
dependabot[bot] 67e17d073b Bump actions/download-artifact from 4 to 5
Bumps [actions/download-artifact](https://github.com/actions/download-artifact) from 4 to 5.
- [Release notes](https://github.com/actions/download-artifact/releases)
- [Commits](https://github.com/actions/download-artifact/compare/v4...v5)

---
updated-dependencies:
- dependency-name: actions/download-artifact
  dependency-version: '5'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <[email protected]>
2025-10-06 03:03:05 +00:00
dependabot[bot] c5cb4dcb6c Bump actions/setup-node from 4 to 5
Bumps [actions/setup-node](https://github.com/actions/setup-node) from 4 to 5.
- [Release notes](https://github.com/actions/setup-node/releases)
- [Commits](https://github.com/actions/setup-node/compare/v4...v5)

---
updated-dependencies:
- dependency-name: actions/setup-node
  dependency-version: '5'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <[email protected]>
2025-10-06 03:03:02 +00:00
dependabot[bot] 0b9fe603a8 Bump actions/upload-pages-artifact from 3 to 4
Bumps [actions/upload-pages-artifact](https://github.com/actions/upload-pages-artifact) from 3 to 4.
- [Release notes](https://github.com/actions/upload-pages-artifact/releases)
- [Commits](https://github.com/actions/upload-pages-artifact/compare/v3...v4)

---
updated-dependencies:
- dependency-name: actions/upload-pages-artifact
  dependency-version: '4'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <[email protected]>
2025-10-06 03:02:59 +00:00
dependabot[bot] c7141892d1 Bump actions/setup-go from 5 to 6
Bumps [actions/setup-go](https://github.com/actions/setup-go) from 5 to 6.
- [Release notes](https://github.com/actions/setup-go/releases)
- [Commits](https://github.com/actions/setup-go/compare/v5...v6)

---
updated-dependencies:
- dependency-name: actions/setup-go
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <[email protected]>
2025-10-06 03:02:56 +00:00
Joe c5556f9e2b Merge pull request #2001 from BishopFox/codex/ioutil
Codex refactors ioutil usage
2025-10-05 18:06:31 -07:00
Joe 1bc45c2ab2 Merge pull request #1985 from hypnoticpattern/fix-daemon-multiplayer-conflict
Add info about potential causes for sliver daemon port binding error
2025-10-05 17:03:19 -07:00
moloch-- 739ad98b81 Codex refactors ioutil usage 2025-10-05 17:02:37 -07:00
Joe 95c1697d1b Merge pull request #1979 from z3xddd/add-ntcreatethreadex-syscall
feat: Add NtCreateThreadEx syscall for advanced evasion techniques
2025-10-05 12:09:34 -07:00
moloch-- f7b9571cfc Increase workflow time limits 2025-10-05 11:52:21 -07:00
Joe 0d08f8c62f Merge pull request #2000 from BishopFox/codex/deps
Dependency Updates
2025-10-05 11:51:52 -07:00
Joe aa9c8d89e9 Merge branch 'master' into add-ntcreatethreadex-syscall 2025-10-05 10:38:30 -07:00
moloch-- 152e60ba29 Fix fmt string syntax 2025-10-05 10:05:52 -07:00
moloch-- d13a71b808 Update most go deps, compiles okay 2025-10-05 10:04:24 -07:00
moloch-- b17e2f056f Update most go deps, compiles okay 2025-10-05 10:04:11 -07:00
moloch-- 42fb1e835e Snap to anchor on load 2025-10-04 21:09:02 -07:00
moloch-- 521356ff6e Make sidebar sticky 2025-10-04 21:03:39 -07:00
moloch-- 74b5d720b2 Fix docs build errors 2025-10-04 20:02:48 -07:00
moloch-- cd75545323 Add mobile version of docs site 2025-10-04 19:07:13 -07:00
Joe 396dc9724f Merge branch 'master' into add-ntcreatethreadex-syscall 2025-10-04 18:05:59 -07:00
moloch-- 33398146d3 Fix broken AV links 2025-10-04 18:02:52 -07:00
moloch-- 21039554e5 Add NoStarch 'Red Team Engineering' book to Community Guides 2025-10-04 18:02:07 -07:00
moloch-- cca73be1c8 Add missing types pkg 2025-10-04 17:57:09 -07:00
moloch-- 596bc455d8 Apply a pixel offset to anchor links 2025-10-04 17:55:28 -07:00
moloch-- 400c36c5df Small tweaks to how code blocks are rendered 2025-10-04 17:52:42 -07:00
moloch-- c94dde3efb Add docs watcher in dev mode, fix markdown syntax, update cross-compiler instructions 2025-10-04 17:32:26 -07:00
moloch-- 827a9ca156 Fix docs errors and warnings 2025-10-04 16:53:56 -07:00
Joe d066dbc49a Merge pull request #1999 from moloch--/codex/docs
Update Docs and Fix Various Quirks
2025-10-04 16:47:31 -07:00
Joe f1fbc345a2 Merge branch 'master' into codex/docs 2025-10-04 16:47:20 -07:00
moloch-- 2889c1ee29 Fix font for <code> 2025-10-04 16:46:31 -07:00
moloch-- 28ee216b36 Fix styling of <pre> blocks 2025-10-04 16:44:17 -07:00
moloch-- 2dd3e84f60 Re-implement markdown rendering 2025-10-04 15:39:20 -07:00
moloch-- 067cdf712d Sticky sidebar 2025-10-04 15:21:37 -07:00
moloch-- 22ae941e17 Tweak sidebar radius 2025-10-04 15:15:10 -07:00
moloch-- 7c0c2c2dda Tweak scroll styling 2025-10-04 15:12:55 -07:00
moloch-- 39de742223 Tweak styling 2025-10-04 15:10:03 -07:00
moloch-- b07e750cf5 Add missing tailwind.config.js 2025-10-04 15:06:19 -07:00
Joe 8786979001 Merge pull request #1998 from moloch--/codex/basics
Codex/basics
2025-10-04 14:53:40 -07:00
moloch-- aa223e4488 Update docs to latest tailwind, react, and heroui, some formatting broken 2025-10-04 14:26:03 -07:00
moloch-- 8785c55cf3 Update zig download to use mirrors 2025-10-04 13:27:52 -07:00
Joe 38fa64d266 Merge branch 'master' into codex/basics 2025-10-04 11:51:50 -07:00
moloch-- b04fff21fd Fix format str errors 2025-10-04 11:49:32 -07:00
moloch-- 3f656da786 Add readmes and AGENT.md 2025-10-04 10:25:58 -07:00
Joe 55311868a7 Merge pull request #1983 from hypnoticpattern/enrich-session-logs
Enrich client logging in implant sessions
2025-10-03 07:21:04 -07:00
Ronan Kervella 422a1d39c3 Merge pull request #1996 from moloch--/go/v1.25
Go v1.25.1
2025-09-18 07:57:18 -07:00
moloch-- 6938759e9d Update workflows to use go v1.25.x 2025-09-17 12:09:56 -07:00
moloch-- 5febe5e539 Go v1.25.1 2025-09-17 10:11:12 -07:00
hypnoticpattern 38479e34aa Add comment about the conflict 2025-08-10 15:02:59 -07:00
hypnoticpattern abe8f8e77b Enrich client logging in implant sessions 2025-08-10 10:39:33 -07:00
Israel Comazzetto dos Reis c0f3161525 feat: Add NtCreateThreadEx syscall for advanced evasion techniques 2025-07-29 01:57:48 -03:00
moloch-- c6bbba16e1 Go v1.24.5 2025-07-21 15:33:25 -07:00
Joe af4f99de51 Merge pull request #1970 from atomicchonk/master
Suggested adjective and noun changes
2025-07-18 07:59:28 -07:00
Max Andreacchi 8e6e8e18ad Update nouns.txt
Suggested updates to nouns list to remove some nouns that result in NSFW names upon beacon generation.

Signed-off-by: Max Andreacchi <[email protected]>
2025-07-17 20:05:13 -04:00
Max Andreacchi 544e577eb2 Update adjectives.txt
Updated list to remove adjectives that could result in NSFW names for beacons

Signed-off-by: Max Andreacchi <[email protected]>
2025-07-17 20:01:30 -04:00
Joe 9939d2c320 Merge pull request #1956 from tandem97/master
closes #1955
2025-06-30 13:28:41 -07:00
Joe f47af1e94e Merge pull request #1958 from Hunter-0x07/fix-c2generator-closure
Fix: correct closure capture in C2Generator to prevent loop variable bug
2025-06-16 17:52:10 -07:00
Hunter-0x07 d3302583f5 Fix: correct closure capture in C2Generator to prevent loop variable bug 2025-06-03 14:37:14 +08:00
tandem97 d9403c7f05 fixes #1955 2025-05-31 00:23:40 +03:00
Joe 65eb72506b Merge pull request #1947 from BishopFox/bugfix_shellcodeDefaultExport
add exports when creating profile for windows shellcode
2025-05-15 06:57:19 -07:00
Tim Makram Ghatas d86cdcad8e add exports when creating profile for windows shellcode 2025-05-15 11:53:39 +02:00
Joe 7d7f858c15 Merge pull request #1943 from Signum21/ps_faronics_anti_executable
Added ps detection for Faronics Anti-Executable processes
2025-05-13 09:08:06 -07:00
Joe ee1ad9edd1 Merge pull request #1944 from BishopFox/bugfix_addDefaultExport
Bugfix add default export
2025-05-13 09:07:52 -07:00
Tim Makram Ghatas d985564198 add exports to db for implantconfig object 2025-05-12 14:03:08 +02:00
Tim Makram Ghatas c1b5a3f7b4 ensure server generate call always has a default value for the exports variable 2025-05-12 13:52:40 +02:00
Signum21 927ff9c4ab Added ps detection for Faronics Anti-Executable processes
Signed-off-by: Signum21 <[email protected]>
2025-05-09 00:07:37 +02:00
Joe 3411b438b6 Merge pull request #1942 from BishopFox/doc_1.6_update
Doc 1.6 update
2025-05-08 11:20:02 -07:00
Joe 40bc0d6464 Merge pull request #1941 from BishopFox/fix_pivots
Fix pivots
2025-05-08 11:13:03 -07:00
Tim Makram Ghatas b0639275f4 Merge branch 'master' into doc_1.6_update 2025-05-08 20:11:15 +02:00
Tim Makram Ghatas 6216cd1dc6 update c2profile docs 2025-05-08 20:10:44 +02:00
Joe 78e6b3a9b3 Merge branch 'master' into fix_pivots 2025-05-07 07:48:33 -07:00
Joe 509d1b46ff Merge pull request #1940 from BishopFox/add_implant_configurations
Bugfixes and additional compilation options
2025-05-07 07:48:23 -07:00
Tim Makram Ghatas f06b2c2192 Merge branch 'master' into fix_pivots 2025-05-07 14:58:54 +02:00
Tim Makram Ghatas 4138ddd84a fix multiLibrary test 2025-05-05 23:46:37 +02:00
Tim Makram Ghatas e9a300bab2 add duplicate implant running check for all exports 2025-05-05 16:20:18 +02:00
Tim Makram Ghatas 6edd10a010 allow specifying exports in generate command 2025-05-05 16:17:13 +02:00
Tim Makram Ghatas b438df4db9 add donut bypass field to server.json 2025-04-26 11:25:58 +01:00
Tim Makram Ghatas 49eab476bb update base58 id write in implant 2025-04-26 09:34:56 +01:00
Joe 8976654010 Merge pull request #1928 from BishopFox/v1.6.0/fix-beacon-tasks
Fixes for Issues with Beacon Tasks
2025-04-22 18:51:26 -07:00
Ronan Kervella a78b8c2097 Merge branch 'master' into v1.6.0/fix-beacon-tasks 2025-04-21 10:52:42 -07:00
Ronan Kervella 5709bb9a24 Merge pull request #1935 from BishopFox/v1.6.0/ps-toggle-info
Simplified Default ps Output
2025-04-21 10:52:24 -07:00
Raf 25668a6d82 Correcting condition in client ps command 2025-04-21 12:57:50 -04:00
rkervella 87dfe96ee9 Remove insertion to db, already performed elsewhere 2025-04-18 12:32:48 -07:00
rkervella 5bb4338d76 Add an IPTable to the tun device and set the default INPUT
chain to deny everything. Add an `AllowTCPPort` method to add
exceptions at runtime.
2025-04-18 12:31:45 -07:00
rkervella bb35fa56d6 Use AllowTCPPort to whitelist the required ports for the wg listner 2025-04-18 12:30:59 -07:00
rkervella fbab18b2fe Remove job insertion to db, already done elsewhere 2025-04-18 12:30:22 -07:00
Raf 3ae8353030 Changes to reduce the amount of information pulled by ps by default, changing deprecated x/sys/windows calls 2025-04-15 08:27:32 -04:00
Raf a3d053bde5 Merge branch 'master' into v1.6.0/fix-beacon-tasks 2025-04-14 08:17:01 -04:00
Tim Makram Ghatas 7e27a18245 Merge branch 'master' into fix_pivots 2025-04-12 18:07:33 +02:00
Tim Makram Ghatas 6d09b27c85 updated documentation for 1.6 2025-04-11 17:26:47 +02:00
Tim Makram Ghatas c389bac46e bugfix - switch pivot decryption to alternative function without signature verification 2025-04-11 17:23:35 +02:00
Raf fae8e77665 Fix SQL issues when accessing or cancelling beacon tasks, fix panic when cancelling a task by ID 2025-04-11 10:59:55 -04:00
Joe 38cf0aeb8b Merge pull request #1924 from mosesrenegade/master
Cursed Chrome Cookie Fix
2025-04-11 07:36:02 -07:00
Joe a755750a89 Merge pull request #1926 from BishopFox/bugfix_listeners
Bugfix listeners
2025-04-11 07:35:37 -07:00
Tim Makram Ghatas 555ee5c63d remove unused persistent flags 2025-04-11 15:45:18 +02:00
Tim Makram Ghatas 0fc51677c1 fix bug for payload staging 2025-04-11 13:54:00 +02:00
Tim Makram Ghatas cc1c7a5364 crop c2profile output to 50 char max for paths and files 2025-04-11 13:53:18 +02:00
Timothy Makram Ghatas d1fa99d6eb Merge branch 'master' into bugfix_listeners 2025-04-11 01:25:43 +02:00
Timothy Makram Ghatas 6697801f59 Merge pull request #1925 from BishopFox/bof_flag_args
Bof flag args
2025-04-11 01:25:09 +02:00
Tim Makram Ghatas 32fa69356c fix to address integer conversion in bof default value routine written by ccardio 2025-04-10 21:52:28 +02:00
Timothy Makram Ghatas c42d754e72 Update list.go
remove outer loop and switch to contains for extension lists

Signed-off-by: Timothy Makram Ghatas <[email protected]>
2025-04-10 21:50:35 +02:00
c2biz e4babaf471 add flag-style arg parsing for BOF extensions 2025-04-10 15:42:04 -04:00
c2biz da196a789d fix DLL based extension argument parsing 2025-04-10 15:39:35 -04:00
c2biz 6a656d63ab Merge branch 'extensions_cmd_improvements' into bof_flag_args 2025-04-10 15:27:47 -04:00
c2biz b0e226199a Merge remote-tracking branch 'origin/master' into extensions_cmd_improvements 2025-04-10 15:27:43 -04:00
Tim Makram Ghatas 7cce6b17b2 fix console test 2025-04-10 19:16:07 +02:00
Tim Makram Ghatas d07aae4d0b restrict operator certificates to SHA256 to fix grpcio bugs (#1877) 2025-04-10 18:45:40 +02:00
Tim Makram Ghatas f4a2ba536c store tcp listener in database 2025-04-10 18:29:35 +02:00
Moses Frost 2bbd69719d This commit is a fix for the Cursed module cookie subcommand. The library upstream changed it's cookie values from a string value to a struct and the download command needed to be modified to work with the struct 2025-04-09 16:05:17 -04:00
Joe cf4ff14342 Merge pull request #1914 from m1tm4n404/from-as-casting
build Dockerfile: use uppercase FROM / AS combination
2025-03-31 08:14:11 -07:00
Timothy Makram Ghatas ae3a2fd51e Merge pull request #1919 from BishopFox/extend_nonce_configurations
Extend nonce configurations
2025-03-31 17:13:52 +02:00
Tim Makram Ghatas d14ba3d35f Merge branch 'master' into extend_nonce_configurations 2025-03-27 22:40:00 +01:00
Tim Makram Ghatas 10ef8b3e88 remove need for http job restart on c2profile import and allow hiding nonce in url segment instead of a parameter 2025-03-27 02:01:26 +01:00
Tim Makram Ghatas 4bc65e2193 allow specifying implant name for profile generate and fix duplicate name bug 2025-03-27 00:35:12 +01:00
Tim Makram Ghatas a45a5795d3 fix autocompletion for c2profile in generate 2025-03-27 00:06:03 +01:00
Tim Makram Ghatas e1c5b77db4 add default server header to server json config for anonymous requests 2025-03-26 23:58:43 +01:00
Tim Makram Ghatas 280d08d074 refactored nonce parsing in url parameters 2025-03-25 14:25:47 +01:00
svd 1d55b34b62 fixing from as casting 2025-03-23 15:18:36 +03:00
Joe d32302a1ab Merge pull request #1911 from kmathisbf/ps_cortex
Add Palo Alto Cortex XDR binaries to `knownSecurityTools`
2025-03-18 18:36:40 -07:00
kmathisbf 2eabfc255b Fix typo 2025-03-18 18:10:23 -04:00
kmathisbf d0375da6e4 Add Palo Alto Cortex processes to knownSecurityTools 2025-03-18 18:02:15 -04:00
Tim Makram Ghatas 4523c83b89 fix implant bug for url generation 2025-03-11 16:25:36 +01:00
Tim Makram Ghatas 1decc7f462 update client side c2 profile to match new format 2025-03-10 15:42:57 +01:00
Tim Makram Ghatas f97a1e3fdf remove legacy c2profile import validation 2025-03-10 15:19:24 +01:00
Tim Makram Ghatas 1e12ea3242 remove support for default server header when unauthenticated, to be reimplemented later on 2025-03-10 15:17:09 +01:00
Tim Makram Ghatas 8919bc3b07 update http c2 config and remove segmenttype from model and protobuf 2025-03-10 15:12:57 +01:00
Tim Makram Ghatas 1a2b392d20 remove unused queries from helpers 2025-03-10 14:58:54 +01:00
Tim Makram Ghatas 11a6584973 update http c2 model 2025-03-10 14:55:49 +01:00
Tim Makram Ghatas 1e06fe6612 update protobuf to merge all http extensions into an array and split max/min generation and implant configuration variables 2025-03-10 14:55:13 +01:00
Tim Makram Ghatas 65ee18026e update server side code to remove the need for url extensions in http handler 2025-03-07 19:07:56 +01:00
Tim Makram Ghatas 9c1617c213 add noncequerylength to implant 2025-03-07 16:21:04 +01:00
Tim Makram Ghatas d74067ddff allow arbitrary nonce length in c2profile server side 2025-02-25 19:51:33 +01:00
Tim Makram Ghatas 60772c7659 add default length for url nonce length 2025-02-25 17:36:49 +01:00
Tim Makram Ghatas 25a70e6e4f add nonce length to protobuf definition and db model 2025-02-25 17:23:30 +01:00
Joe a89675d961 Merge pull request #1879 from BishopFox/fix_missing_extension
Keep track of file extension
2025-02-21 08:05:41 -07:00
Joe 0f340a25cf Merge pull request #1889 from BishopFox/fix/GHSA-fh4v-v779-4g2w
Track tunnel creation for `rportfwd`
2025-02-14 09:27:58 -06:00
Joe 9cdc326b57 Merge pull request #1882 from BishopFox/fix_1842
missing default value
2025-02-14 09:27:43 -06:00
Ronan Kervella 3faabd36c1 Merge branch 'master' into fix_missing_extension 2025-02-13 15:18:07 -08:00
Tim Makram Ghatas 2d9a46543d Keep track of file extension in implant config and automatically append correct extension when saving builds 2025-02-09 17:46:33 +01:00
rkervella e5e589e1b0 Simplify expression 2025-02-08 11:13:01 -08:00
rkervella 2e0fab3a71 Track reverse portfwd state 2025-02-08 11:09:54 -08:00
c2biz 99571dc73e fix bug in extensions rm command 2025-01-21 10:54:32 -05:00
c2biz 5c2848c84c improve extensions list output 2025-01-21 07:26:06 -05:00
c2biz ffcfa8d1b5 add extension short help to SliverCommand help menu 2025-01-20 14:20:09 -05:00
c2biz debc03203c restrict 'extensions list' sub-command to session mode 2025-01-20 14:07:45 -05:00
c2biz b84037af11 fix bug in PrintExtensions 2025-01-17 18:11:11 -05:00
c2biz 61ed176683 fix dupe issue in GetAllExtensionManifests() 2025-01-17 17:51:08 -05:00
c2biz 12e44644ed introduce package_name field 2025-01-17 15:16:03 -05:00
c2biz 0b185cc885 fix bin path bug for temp-installed extensions and display bug in PrintExtensions() 2025-01-17 00:20:28 -05:00
c2biz ae0c106595 add GetAllExtensionManifests() to obtain installed and temp-installed extensions 2025-01-16 23:53:18 -05:00
c2biz 6d2b0f8319 fix bug for temporarily installed (extensions load) extensions 2025-01-16 18:34:46 -05:00
c2biz 60443f4fc7 split extensions' subcommands: 'install', 'load', 'rm' in server context and 'list' in sliver context 2025-01-16 12:27:57 -05:00
c2biz 418fe757d1 moved extensions command from sliver to server menu 2025-01-16 08:57:57 -05:00
5027 changed files with 1821464 additions and 909099 deletions

No files matched your search

+7
View File
@@ -1,4 +1,9 @@
# go-assets.sh downloads
/server/assets/fs/**.zip
/server/assets/fs/**/garble*
/server/assets/fs/**/zig.tar.xz
/server/assets/fs/**/zig.zip
/server/assets/fs/src.zip
/*.sdk.tar.xz
@@ -19,3 +24,5 @@
/SECURITY.md
/README.md
/CONTRIBUTING.md
.downloaded_assets
+11 -11
View File
@@ -11,10 +11,10 @@ jobs:
runs-on: ubuntu-latest
timeout-minutes: 45
steps:
- name: Go 1.21
uses: actions/setup-go@v5
- name: Go 1.25
uses: actions/setup-go@v6
with:
go-version: "^1.21"
go-version: "^1.25"
- 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@v4
uses: actions/checkout@v6
- name: Git Fetch Tags
run: git fetch --prune --unshallow --tags -f
@@ -31,7 +31,7 @@ jobs:
run: make servers
- name: Server Artifacts
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v6
with:
name: servers
path: ./sliver-server_*
@@ -42,13 +42,13 @@ jobs:
runs-on: ubuntu-latest
timeout-minutes: 45
steps:
- name: Go 1.22
uses: actions/setup-go@v5
- name: Go 1.25
uses: actions/setup-go@v6
with:
go-version: "^1.22"
go-version: "^1.25"
- name: Check Out Code
uses: actions/checkout@v4
uses: actions/checkout@v6
- name: Git Fetch Tags
run: git fetch --prune --unshallow --tags -f
@@ -57,7 +57,7 @@ jobs:
run: make clients
- name: Client Artifacts
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v6
with:
name: clients
path: ./sliver-client_*
@@ -72,7 +72,7 @@ jobs:
steps:
- run: mkdir -p ./builds
- uses: actions/download-artifact@v4
- uses: actions/download-artifact@v7
with:
path: ./builds
+7 -7
View File
@@ -16,13 +16,13 @@ jobs:
steps:
# Setup go environment
- name: Go 1.22
uses: actions/setup-go@v5
- name: Go 1.25
uses: actions/setup-go@v6
with:
go-version: "^1.22"
go-version: "^1.25"
- name: Checkout repository
uses: actions/checkout@v4
uses: actions/checkout@v6
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,10 +36,10 @@ jobs:
git build-essential zlib1g zlib1g-dev wget zip unzip
- name: Check Out Code
uses: actions/checkout@v4
uses: actions/checkout@v6
- name: Initialize CodeQL
uses: github/codeql-action/init@v3
uses: github/codeql-action/init@v4
with:
config-file: ./.github/codeql/codeql-config.yml
languages: go
@@ -48,6 +48,6 @@ jobs:
run: make
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v3
uses: github/codeql-action/analyze@v4
env:
VERSION: ${{github.sha}}
+4 -4
View File
@@ -35,7 +35,7 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v6
- name: Detect package manager
id: detect-package-manager
@@ -56,7 +56,7 @@ jobs:
fi
- name: Setup Node
uses: actions/setup-node@v4
uses: actions/setup-node@v6
with:
cache: "npm"
cache-dependency-path: "**/package-lock.json"
@@ -66,7 +66,7 @@ jobs:
uses: actions/configure-pages@v5
- name: Restore cache
uses: actions/cache@v4
uses: actions/cache@v5
with:
path: |
.next/cache
@@ -85,7 +85,7 @@ jobs:
run: ${{ steps.detect-package-manager.outputs.runner }} next build
- name: Upload artifact
uses: actions/upload-pages-artifact@v3
uses: actions/upload-pages-artifact@v4
with:
path: ${{ github.workspace }}/docs/sliver-docs/out
+24 -26
View File
@@ -21,12 +21,12 @@ jobs:
linux-windows-build-test:
name: Linux & Windows Test
runs-on: ubuntu-latest
timeout-minutes: 90
timeout-minutes: 180
steps:
- name: Go 1.22
uses: actions/setup-go@v5
- name: Go 1.25
uses: actions/setup-go@v6
with:
go-version: "^1.22"
go-version: "^1.25"
- name: OS Packages
run: |
@@ -34,38 +34,36 @@ jobs:
git build-essential zlib1g zlib1g-dev wget zip unzip
- name: Check Out Code
uses: actions/checkout@v4
uses: actions/checkout@v6
- name: Git Fetch Tags
run: git fetch --prune --unshallow --tags -f
- name: Make Linux (amd64)
run: make linux-amd64
- name: Test Linux
run: ./sliver-server unpack --force && ./go-tests.sh
- name: Make Windows (amd64)
run: make windows-amd64
- name: Make Linux (arm64)
run: make linux-arm64
- name: Make Linux (amd64)
run: make linux-amd64
- name: Test Linux
run: make clean && make && ./sliver-server unpack --force && ./go-tests.sh
macos-build-test:
name: MacOS Test
runs-on: macos-latest
timeout-minutes: 90
timeout-minutes: 180
steps:
- name: Go 1.22
uses: actions/setup-go@v5
- name: Go 1.25
uses: actions/setup-go@v6
with:
go-version: "^1.22"
- name: Mingw
run: brew install mingw-w64
go-version: "^1.25"
- name: Check Out Code
uses: actions/checkout@v4
uses: actions/checkout@v6
- name: Git Fetch Tags
run: git fetch --prune --unshallow --tags -f
@@ -73,24 +71,24 @@ jobs:
- name: Make MacOS (amd64)
run: make macos-amd64
- name: Test MacOS (amd64)
run: ./sliver-server unpack --force && ./go-tests.sh
- name: Make MacOS (arm64)
run: make macos-arm64
- name: Test MacOS
run: make clean && make && ./sliver-server unpack --force && ./go-tests.sh
clients-build:
name: Clients Build
runs-on: ubuntu-latest
timeout-minutes: 90
steps:
- name: Go 1.22
uses: actions/setup-go@v5
- name: Go 1.25
uses: actions/setup-go@v6
with:
go-version: "^1.22"
go-version: "^1.25"
- name: Check Out Code
uses: actions/checkout@v4
uses: actions/checkout@v6
- name: Git Fetch Tags
run: git fetch --prune --unshallow --tags -f
+2
View File
@@ -45,6 +45,8 @@ sliver-server-windows.zip
.DS_Store
dist/
.gocache/
.gomodcache/
# Flag to show that go-assets.sh has been run
.downloaded_assets
+41
View File
@@ -0,0 +1,41 @@
# Repository Guidelines
## Project Structure & Module Organization
- `client/` holds the CLI client and interactive commands.
- `server/` contains the server runtime, C2 logic, configs, and web assets.
- `implant/` is the implant runtime and transport implementations.
- `protobuf/` stores protobuf definitions and generated Go types.
- `util/` is shared helpers (crypto, encoders, minisign, etc.).
- `docs/sliver-docs/` is the Next.js documentation site and prebuild scripts.
- `vendor/` is the vendored Go dependency tree used by builds.
- Build outputs land in the repo root as `sliver-client*` and `sliver-server*`.
## Build, Test, and Development Commands
- `make` builds server + client using vendored modules and runs `go-assets.sh`.
- `make client` builds a CGO-free client; `make debug` keeps symbols.
- `make pb` regenerates protobuf stubs from `protobuf/`.
- `./go-tests.sh` runs the curated Go test suite with build tags.
- Docs site: `cd docs/sliver-docs && npm install && npm run dev` for local dev; `npm run build` for a static build.
- Go toolchain: the Makefile enforces Go >= 1.24.
## Coding Style & Naming Conventions
- Run `gofmt` on all Go code; keep package names lowercase and idiomatic.
- Avoid `CGO` and empty interfaces; prefer explicit types and interfaces.
- Do not import `server` packages from `client`.
- If `math/rand` is required, import it as `insecureRand` and avoid security use.
## Testing Guidelines
- Go tests follow standard `_test.go` naming within each package.
- Prefer `docker build --target test --build-arg GO_TESTS_FLAGS=--skip-generate .`
- Add or update tests when behavior changes; some server packages run longer tests.
## Commit & Pull Request Guidelines
- Commits must be signed for PRs to `master`; work in a feature branch.
- Commit subjects are short and imperative (e.g., "Fix ...", "Add ...", "Update ...", "Bump ...").
- Changes to `vendor/` should be in a distinct commit.
- PRs should link the tracking issue, note tests run, and confirm `gofmt` plus unit tests as applicable.
## Security Notes
- Default to secure configuration; fail closed rather than open.
- Avoid insecure algorithms (MD5/SHA1/AES-ECB); prefer AES-GCM and modern curves.
- Treat user input as untrusted: canonicalize paths and use restrictive file permissions.
+9 -5
View File
@@ -5,11 +5,12 @@
#
# For unit testing:
# docker build --target test .
# docker build --target test --build-arg GO_TESTS_FLAGS=--skip-generate .
#
# STAGE: base
## Compiles Sliver for use
FROM golang:1.23.5 AS base
FROM golang:latest AS base
### Base packages
RUN apt-get update --fix-missing && apt-get -y install \
@@ -20,10 +21,10 @@ RUN groupadd -g 999 sliver && useradd -r -u 999 -g sliver sliver
RUN mkdir -p /home/sliver/ && chown -R sliver:sliver /home/sliver
### Build sliver:
RUN mkdir -p /go/src/github.com/bishopfox/sliver
WORKDIR /go/src/github.com/bishopfox/sliver
ADD . /go/src/github.com/bishopfox/sliver/
RUN make clean-all
RUN make
RUN make
RUN cp -vv sliver-server /opt/sliver-server
# STAGE: test
@@ -31,6 +32,9 @@ RUN cp -vv sliver-server /opt/sliver-server
## Use `--target test` in the docker build command to run this stage
FROM base AS test
ARG GO_TESTS_FLAGS=""
ENV GO_TESTS_FLAGS="${GO_TESTS_FLAGS}"
RUN apt-get update --fix-missing \
&& apt-get -y upgrade \
&& apt-get -y install \
@@ -39,7 +43,7 @@ RUN apt-get update --fix-missing \
RUN /opt/sliver-server unpack --force
### Run unit tests
RUN /go/src/github.com/bishopfox/sliver/go-tests.sh
RUN /go/src/github.com/bishopfox/sliver/go-tests.sh ${GO_TESTS_FLAGS}
# STAGE: production
## Final dockerized form of Sliver
@@ -91,7 +95,7 @@ ENTRYPOINT [ "/opt/sliver-server" ]
# STAGE: production-slim (about 1Gb smaller)
FROM debian:bookworm-slim as production-slim
FROM debian:bookworm-slim AS production-slim
### Install production packages
RUN apt-get update --fix-missing \
+12 -35
View File
@@ -16,49 +16,29 @@ endif
# Prerequisites
#
# https://stackoverflow.com/questions/5618615/check-if-a-program-exists-from-a-makefile
EXECUTABLES = uname sed git zip date cut $(GO)
EXECUTABLES = uname sed git date cut $(GO)
K := $(foreach exec,$(EXECUTABLES),\
$(if $(shell which $(exec)),some string,$(error "No $(exec) in PATH")))
#
# Version Information
# Build Information
#
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 = 21
MIN_SUPPORTED_GO_MINOR_VERSION = 24
GO_VERSION_VALIDATION_ERR_MSG = Golang version is not supported, please update to at least $(MIN_SUPPORTED_GO_MAJOR_VERSION).$(MIN_SUPPORTED_GO_MINOR_VERSION)
VERSION ?= $(shell git describe --abbrev=0)
COMPILED_AT = $(shell date +%s)
RELEASES_URL ?= https://api.github.com/repos/BishopFox/sliver/releases
ARMORY_PUBLIC_KEY ?= RWSBpxpRWDrD7Fe+VvRE3c2VEDC2NK80rlNCj+BX0gz44Xw07r6KQD9L
ARMORY_REPO_URL ?= https://api.github.com/repos/sliverarmory/armory/releases
VERSION_PKG = github.com/bishopfox/sliver/client/version
CLIENT_ASSETS_PKG = github.com/bishopfox/sliver/client/assets
GIT_DIRTY = $(shell git diff --quiet|| echo 'Dirty')
GIT_COMMIT = $(shell git rev-parse HEAD)
LDFLAGS = -ldflags "-s -w \
-X $(VERSION_PKG).Version=$(VERSION) \
-X \"$(VERSION_PKG).GoVersion=$(GO_VERSION)\" \
-X $(VERSION_PKG).CompiledAt=$(COMPILED_AT) \
-X $(VERSION_PKG).GithubReleasesURL=$(RELEASES_URL) \
-X $(VERSION_PKG).GitCommit=$(GIT_COMMIT) \
-X $(VERSION_PKG).GitDirty=$(GIT_DIRTY) \
-X $(CLIENT_ASSETS_PKG).DefaultArmoryPublicKey=$(ARMORY_PUBLIC_KEY) \
-X $(CLIENT_ASSETS_PKG).DefaultArmoryRepoURL=$(ARMORY_REPO_URL)"
# Debug builds shouldn't be stripped (-s -w flags)
LDFLAGS_DEBUG = -ldflags "-X $(VERSION_PKG).Version=$(VERSION) \
-X \"$(VERSION_PKG).GoVersion=$(GO_VERSION)\" \
-X $(VERSION_PKG).CompiledAt=$(COMPILED_AT) \
-X $(VERSION_PKG).GithubReleasesURL=$(RELEASES_URL) \
-X $(VERSION_PKG).GitCommit=$(GIT_COMMIT) \
-X $(VERSION_PKG).GitDirty=$(GIT_DIRTY) \
-X $(CLIENT_ASSETS_PKG).DefaultArmoryPublicKey=$(ARMORY_PUBLIC_KEY) \
LDFLAGS_DEBUG = -ldflags "-X $(CLIENT_ASSETS_PKG).DefaultArmoryPublicKey=$(ARMORY_PUBLIC_KEY) \
-X $(CLIENT_ASSETS_PKG).DefaultArmoryRepoURL=$(ARMORY_REPO_URL)"
SED_INPLACE := sed -i
@@ -83,7 +63,9 @@ endif
# If no target is specified, determine GOARCH
ifeq ($(UNAME_P),arm)
ifeq ($(MAKECMDGOALS), )
ENV += GOARCH=arm64
ifeq ($(origin GOARCH), undefined)
ENV += GOARCH=arm64
endif
endif
endif
@@ -91,12 +73,6 @@ ifeq ($(MAKECMDGOALS), linux)
# Redefine LDFLAGS to add the static part
LDFLAGS = -ldflags "-s -w \
-extldflags '-static' \
-X $(VERSION_PKG).Version=$(VERSION) \
-X \"$(VERSION_PKG).GoVersion=$(GO_VERSION)\" \
-X $(VERSION_PKG).CompiledAt=$(COMPILED_AT) \
-X $(VERSION_PKG).GithubReleasesURL=$(RELEASES_URL) \
-X $(VERSION_PKG).GitCommit=$(GIT_COMMIT) \
-X $(VERSION_PKG).GitDirty=$(GIT_DIRTY) \
-X $(CLIENT_ASSETS_PKG).DefaultArmoryPublicKey=$(ARMORY_PUBLIC_KEY) \
-X $(CLIENT_ASSETS_PKG).DefaultArmoryRepoURL=$(ARMORY_REPO_URL)"
endif
@@ -105,9 +81,10 @@ endif
# Targets
#
.PHONY: default
default: clean .downloaded_assets validate-go-version
$(ENV) CGO_ENABLED=$(CGO_ENABLED) $(GO) build -mod=vendor -trimpath $(TAGS),server $(LDFLAGS) -o sliver-server$(ARTIFACT_SUFFIX) ./server
$(ENV) CGO_ENABLED=0 $(GO) build -mod=vendor -trimpath $(TAGS),client $(LDFLAGS) -o sliver-client$(ARTIFACT_SUFFIX) ./client
default: clean validate-go-version
env -u GOOS -u GOARCH $(MAKE) GOOS= GOARCH= .downloaded_assets
$(ENV) $(if $(GOOS),GOOS=$(GOOS)) $(if $(GOARCH),GOARCH=$(GOARCH)) CGO_ENABLED=$(CGO_ENABLED) $(GO) build -mod=vendor -trimpath $(TAGS),server $(LDFLAGS) -o sliver-server$(ARTIFACT_SUFFIX) ./server
$(ENV) $(if $(GOOS),GOOS=$(GOOS)) $(if $(GOARCH),GOARCH=$(GOARCH)) CGO_ENABLED=0 $(GO) build -mod=vendor -trimpath $(TAGS),client $(LDFLAGS) -o sliver-client$(ARTIFACT_SUFFIX) ./client
# Allows you to build a CGO-free client for any target e.g. `GOOS=windows GOARCH=arm64 make client`
# NOTE: WireGuard is not supported on all platforms, but most 64-bit GOOS/GOARCH combinations should work.
@@ -199,5 +176,5 @@ clean:
rm -f sliver-client sliver-client_* sliver-server sliver-server_* sliver-*.exe
.downloaded_assets:
./go-assets.sh
$(ENV) $(GO) run -mod=vendor ./util/cmd/assets
touch ./.downloaded_assets
-135
View File
@@ -1,135 +0,0 @@
#!/usr/bin/env python3
"""
Sliver Implant Framework
Copyright (C) 2019 Bishop Fox
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
"""
import os
import sys
import argparse
INFO = "\033[1m\033[36m[*]\033[0m "
WARN = "\033[1m\033[31m[!]\033[0m "
BOLD = "\033[1m"
NORM = "\033[0m"
def exec_cmd(cmd, ignore_status=False):
"""Executes a command with some sugar"""
print("\n" + INFO + " %s\n" % cmd)
status = os.system(cmd)
if status != 0 and not ignore_status:
print("\n" + WARN + "Command did not exit cleanly (%s) " % status)
if input("continue? [Y/n]: ").upper() != "Y":
sys.exit(status)
return status
def docker_rm_volumes():
exec_cmd("docker volume rm $(docker volume ls -q)", ignore_status=True)
def docker_rm_containers():
exec_cmd("docker rm $(docker ps -a -q)", ignore_status=True)
def docker_rm_images():
exec_cmd("docker rmi -f $(docker images -q)", ignore_status=True)
def docker_prune():
exec_cmd("docker image prune -f", ignore_status=True)
def docker_rm_all():
docker_rm_containers()
docker_rm_images()
docker_rm_volumes()
def build():
status = exec_cmd("docker build --target test .")
if status == 0:
print("\n\n" + INFO + "Build successful")
def main(args):
"""Execute the respective task(s) based on cli args"""
if args.rm_images:
docker_rm_images()
if args.rm_containers:
docker_rm_containers()
if args.rm_volumes:
docker_rm_volumes()
if args.rm_all:
docker_rm_all()
if not args.no_prune:
docker_prune()
if not args.no_build:
build()
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="automates interactions with docker")
parser.add_argument(
"--no-build",
"-b",
help="do not run build",
dest="no_build",
action="store_true",
)
parser.add_argument(
"--no-prune",
"-np",
help="do not prune images",
dest="no_prune",
action="store_true",
)
parser.add_argument(
"--rm-all",
"-rma",
help="rm all containers, images, and volumes",
dest="rm_all",
action="store_true",
)
parser.add_argument(
"--rm-containers",
"-rmc",
help="rm all containers",
dest="rm_containers",
action="store_true",
)
parser.add_argument(
"--rm-images",
"-rmi",
help="rm all images",
dest="rm_images",
action="store_true",
)
parser.add_argument(
"--rm-volumes",
"-rmv",
help="rm dangling volumes only",
dest="rm_volumes",
action="store_true",
)
try:
main(parser.parse_args())
except KeyboardInterrupt:
print("\n\n" + WARN + "User stopped process")
+23 -15
View File
@@ -1,18 +1,26 @@
Client
=======
# client
This directory contains the client implementation, pretty much all of this code is also used by the server console.
## Overview
__Important:__ No code in this directory can import any code from `server/`.
Main command-line client for interacting with and administering Sliver servers. Provides the Cobra entrypoint and aggregates console, command, and transport subsystems.
* `assets/` - Static asset files and management code (e.g. client configs)
* `cli/` - Command line interface implementation
* `command/` - Console command implementations
* `constants/` - Various shared constant values
* `core/` - Client state management
* `licenses/` - Open source licenses
* `spin/` - Console spinner library
* `tcpproxy/` - Local TCP proxy listener code
* `transport/` - Wires the client to the server
* `version/` - Version information
* `main.go` - Entrypoint
## Go Files
- `main.go` – Entry point that initializes the CLI, processes flags, and launches the interactive console.
## Sub-packages
- `assets/` – Manages embedded client asset manifests such as operator profiles, settings, and armory catalogs. Handles serialization, bundling, and lookup of static client metadata.
- `cli/` – Defines the Cobra root command and CLI initialization for the Sliver client binary. Sets up persistent flags, environment bootstrapping, and command wiring.
- `command/` – Shared registration glue, scaffolding, and helpers for Sliver client console command groups. Hosts common utilities for binding Cobra commands to RPC-backed actions.
- `console/` – Renders the interactive console UI, logging, and terminal helpers for the client. Coordinates readline behavior, prompt styling, and message formatting.
- `constants/` – Centralizes constants shared across the client runtime and command packages. Captures strings, flag names, and feature toggles used throughout the CLI.
- `core/` – Maintains client application state, background workers, and RPC coordination. Orchestrates session tracking, event streams, and health checks.
- `credentials/` – Credential management utilities including sniffers and import helpers for operators. Provides parsers, storage helpers, and output formatting for recovered secrets.
- `licenses/` – Holds embedded license metadata bundled with the client distribution. Supplies license retrieval utilities used for attribution commands.
- `overlord/` – Supervises long-running client jobs, scheduling, and task orchestration. Tracks job lifecycle events and exposes status updates to the console.
- `packages/` – Deals with packaged extensions and module discovery for the client. Scans, validates, and caches extension manifests and assets.
- `spin/` – Lightweight terminal spinner utilities used for progress feedback. Wraps spinner styles and timing helpers shared across commands.
- `tcpproxy/` – Implements the local TCP proxy used for port forwarding from the client side. Manages listener lifecycles, connection pumps, and cleanup hooks.
- `transport/` – Client-side transports and RPC wiring to communicate with Sliver servers. Builds authenticated gRPC clients, TLS dialers, and reconnect logic.
- `version/` – Build-time version and semantic metadata for the client binary. Exposes git information, release channels, and helper formatters.
+14 -2
View File
@@ -1,3 +1,15 @@
Assets
======
# client/assets
## Overview
Manages embedded client asset manifests such as operator profiles, settings, and armory catalogs. Handles serialization, bundling, and lookup of static client metadata. Core logic addresses aliases, armories, C2 profiles, and extensions within the assets package.
## Go Files
- `aliases.go` – Provides helpers for discovering, installing, and reading alias manifests shipped with the client.
- `armories.go` – Loads configured armory definitions and persists operator customizations.
- `assets.go` – Central entry point that exposes asset directories, lazy initialization, and filesystem utilities.
- `c2profiles.go` – Embeds default HTTP C2 profile templates and exposes lookup utilities.
- `config.go` – Tracks client configuration paths and manages persistence of runtime options.
- `extensions.go` – Handles embedded extension manifests and supports lookup by command name.
- `settings.go` – Stores default console settings and manages serialization to disk.
+1 -1
View File
@@ -96,7 +96,7 @@ func Setup(force bool, echo bool) {
if force || localVer == "" || localVer != ver.GitCommit {
if echo {
fmt.Printf(`
Sliver Copyright (C) 2022 Bishop Fox
Sliver Copyright (C) 2025 Bishop Fox
This program comes with ABSOLUTELY NO WARRANTY; for details type 'licenses'.
This is free software, and you are welcome to redistribute it
under certain conditions; type 'licenses' for details.`)
+11 -24
View File
@@ -57,30 +57,17 @@ type HTTPC2ImplantConfig struct {
NonceQueryArgChars string `json:"nonce_query_args"`
URLParameters []NameValueProbability `json:"url_parameters"`
Headers []NameValueProbability `json:"headers"`
NonceQueryLength int `json:"nonce_query_length"`
NonceMode string `json:"nonce_mode"`
MaxFiles int `json:"max_files"`
MinFiles int `json:"min_files"`
MaxPaths int `json:"max_paths"`
MinPaths int `json:"min_paths"`
MaxFileGen int `json:"max_files"`
MinFileGen int `json:"min_files"`
MaxPathGen int `json:"max_paths"`
MinPathGen int `json:"min_paths"`
MaxPathLength int `json:"max_path_length"`
MinPathLength int `json:"min_path_length"`
// 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"`
Extensions []string `json:"extensions"`
Files []string `json:"files"`
Paths []string `json:"paths"`
}
+13 -3
View File
@@ -1,4 +1,14 @@
CLI
===
# client/cli
This package implements the Sliver client cli.
## Overview
Defines the Cobra root command and CLI initialization for the Sliver client binary. Sets up persistent flags, environment bootstrapping, and command wiring. Core logic addresses console, implant, import, and version within the cli package.
## Go Files
- `cli.go` – Builds the root Cobra command, wires global flags, and starts the console UI.
- `config.go` – Parses CLI configuration files and environment variables used during startup.
- `console.go` – Launches the interactive console mode and handles profile selection.
- `implant.go` – Implements CLI entry points for implant-specific operations without launching the console.
- `import.go` – Provides import routines for bringing external state into the client (e.g., implants or loot).
- `version.go` – Prints version/build information for the CLI binary.
+10 -24
View File
@@ -23,7 +23,7 @@ import (
"sort"
"github.com/bishopfox/sliver/client/assets"
"gopkg.in/AlecAivazis/survey.v1"
"github.com/bishopfox/sliver/client/forms"
)
func selectConfig() *assets.ClientConfig {
@@ -39,32 +39,18 @@ func selectConfig() *assets.ClientConfig {
}
}
answer := struct{ Config string }{}
qs := getPromptForConfigs(configs)
err := survey.Ask(qs, &answer)
keys := make([]string, 0, len(configs))
for key := range configs {
keys = append(keys, key)
}
sort.Strings(keys)
selection := keys[0]
err := forms.Select("Select a server:", keys, &selection)
if err != nil {
fmt.Println(err.Error())
return nil
}
return configs[answer.Config]
}
func getPromptForConfigs(configs map[string]*assets.ClientConfig) []*survey.Question {
keys := []string{}
for k := range configs {
keys = append(keys, k)
}
sort.Strings(keys)
return []*survey.Question{
{
Name: "config",
Prompt: &survey.Select{
Message: "Select a server:",
Options: keys,
Default: keys[0],
},
},
}
return configs[selection]
}
+62 -11
View File
@@ -1,14 +1,65 @@
Command
=======
# client/command
This package contains all of the client command implementations that are shared between the client and the server console.
## Overview
### Developers
Shared registration glue, scaffolding, and helpers for Sliver client console command groups. Hosts common utilities for binding Cobra commands to RPC-backed actions. Core logic addresses sliver within the command package.
General guidance on the structure of this package:
* One command per file and the name of the file should reflect the command it implements (or there about, trivial commands can go into the same file). This makes it easy to find where a command implementation lives within a package or to search by file name if it is not clear which package implements a given command.
* The root command, and reused code should go into the file named after the command
* For example, code shared between the `generate` and the `regenerate` command should go in `generate.go`, and any `regenerate` specific code should go in `regenerate.go`
* Command entrypoint functions should have the suffix `Cmd` e.g., `GenerateCmd` is the entrypoint for `generate`
* Command entrypoints should always a function signature of `func (ctx *grumble.Context, con *console.SliverConsoleClient)`
* Functions that are only ever exported for other commands to use should go in a `helpers.go`, if the function is used internally and exported follow the guidance above on shared code.
## Go Files
- `command.go` – Provides helpers for binding Cobra commands, flag sets, and visibility filters into the client command tree.
- `server.go` – Defines the server menu composition, wiring each server-side command group onto the root console structure at runtime.
- `sliver.go` – Builds the implant/Sliver menu, attaching per-target command groups and loading alias/extension manifests before exposure.
## Sub-packages
- `alias/` – Implements the 'alias' command group for the Sliver client console.
- `armory/` – Implements the 'armory' command group for the Sliver client console.
- `backdoor/` – Implements the 'backdoor' command group for the Sliver client console.
- `beacons/` – Implements the 'beacons' command group for the Sliver client console.
- `builders/` – Implements the 'builders' command group for the Sliver client console.
- `c2profiles/` – Implements the 'c2profiles' command group for the Sliver client console.
- `certificates/` – Implements the 'certificates' command group for the Sliver client console.
- `clean/` – Implements the 'clean' command group for the Sliver client console.
- `completers/` – Implements the 'completers' command group for the Sliver client console.
- `crack/` – Implements the 'crack' command group for the Sliver client console.
- `creds/` – Implements the 'creds' command group for the Sliver client console.
- `cursed/` – Implements the 'cursed' command group for the Sliver client console.
- `dllhijack/` – Implements the 'dllhijack' command group for the Sliver client console.
- `environment/` – Implements the 'environment' command group for the Sliver client console.
- `exec/` – Implements the 'exec' command group for the Sliver client console.
- `exit/` – Implements the 'exit' command group for the Sliver client console.
- `extensions/` – Implements the 'extensions' command group for the Sliver client console.
- `filesystem/` – Implements the 'filesystem' command group for the Sliver client console.
- `flags/` – Implements the 'flags' command group for the Sliver client console.
- `generate/` – Implements the 'generate' command group for the Sliver client console.
- `help/` – Implements the 'help' command group for the Sliver client console.
- `hosts/` – Implements the 'hosts' command group for the Sliver client console.
- `info/` – Implements the 'info' command group for the Sliver client console.
- `jobs/` – Implements the 'jobs' command group for the Sliver client console.
- `kill/` – Implements the 'kill' command group for the Sliver client console.
- `licenses/` – Implements the 'licenses' command group for the Sliver client console.
- `loot/` – Implements the 'loot' command group for the Sliver client console.
- `monitor/` – Implements the 'monitor' command group for the Sliver client console.
- `network/` – Implements the 'network' command group for the Sliver client console.
- `operators/` – Implements the 'operators' command group for the Sliver client console.
- `pivots/` – Implements the 'pivots' command group for the Sliver client console.
- `portfwd/` – Implements the 'portfwd' command group for the Sliver client console.
- `privilege/` – Implements the 'privilege' command group for the Sliver client console.
- `processes/` – Implements the 'processes' command group for the Sliver client console.
- `reaction/` – Implements the 'reaction' command group for the Sliver client console.
- `reconfig/` – Implements the 'reconfig' command group for the Sliver client console.
- `registry/` – Implements the 'registry' command group for the Sliver client console.
- `rportfwd/` – Implements the 'rportfwd' command group for the Sliver client console.
- `screenshot/` – Implements the 'screenshot' command group for the Sliver client console.
- `sessions/` – Implements the 'sessions' command group for the Sliver client console.
- `settings/` – Implements the 'settings' command group for the Sliver client console.
- `shell/` – Implements the 'shell' command group for the Sliver client console.
- `shikata-ga-nai/` – Implements the 'shikata-ga-nai' command group for the Sliver client console.
- `socks/` – Implements the 'socks' command group for the Sliver client console.
- `taskmany/` – Implements the 'taskmany' command group for the Sliver client console.
- `tasks/` – Implements the 'tasks' command group for the Sliver client console.
- `update/` – Implements the 'update' command group for the Sliver client console.
- `use/` – Implements the 'use' command group for the Sliver client console.
- `wasm/` – Implements the 'wasm' command group for the Sliver client console.
- `websites/` – Implements the 'websites' command group for the Sliver client console.
- `wireguard/` – Implements the 'wireguard' command group for the Sliver client console.
+10 -7
View File
@@ -1,11 +1,14 @@
Alias
===========
# client/command/alias
Wraps external DLLs/tool in Sliver console commands.
## Overview
Implements the 'alias' command group for the Sliver client console. Handlers map Cobra invocations to alias workflows such as install, load, and remove.
## Go Files
### Format
* `alias-dir/`
* * `manifest.json` -
- `alias.go` – Implements runtime alias management, printing installed aliases and exposing tab-completion helpers.
- `alias_test.go` *(tests)* – Exercises manifest parsing logic to ensure alias metadata is interpreted correctly.
- `commands.go` – Wires Cobra commands for listing, installing, loading, and removing aliases into the client console.
- `install.go` – Handles installing alias bundles from directories or archives, writing manifests and payload artifacts to disk.
- `load.go` – Loads alias manifests, validates target compatibility, and registers commands against the active console.
- `remove.go` – Removes installed aliases, prompting for confirmation and deleting associated on-disk assets.
+4 -6
View File
@@ -24,9 +24,9 @@ import (
"path/filepath"
"strings"
"github.com/AlecAivazis/survey/v2"
"github.com/bishopfox/sliver/client/assets"
"github.com/bishopfox/sliver/client/console"
"github.com/bishopfox/sliver/client/forms"
"github.com/bishopfox/sliver/util"
"github.com/spf13/cobra"
)
@@ -62,8 +62,7 @@ func installFromDir(aliasLocalPath string, con *console.SliverClient) {
if _, err := os.Stat(installPath); !os.IsNotExist(err) {
con.PrintInfof("Alias '%s' already exists", manifest.CommandName)
confirm := false
prompt := &survey.Confirm{Message: "Overwrite current install?"}
survey.AskOne(prompt, &confirm)
_ = forms.Confirm("Overwrite current install?", &confirm)
if !confirm {
return
}
@@ -114,7 +113,7 @@ func InstallFromFile(aliasGzFilePath string, aliasName string, promptToOverwrite
} else {
errorMsg = fmt.Sprintf("Failed to parse %s: %s\n", ManifestFileName, err)
}
con.PrintErrorf(errorMsg)
con.PrintErrorf("%s", errorMsg)
return nil
}
installPath := filepath.Join(assets.GetAliasesDir(), filepath.Base(manifest.CommandName))
@@ -122,8 +121,7 @@ func InstallFromFile(aliasGzFilePath string, aliasName string, promptToOverwrite
if promptToOverwrite {
con.PrintInfof("Alias '%s' already exists\n", manifest.CommandName)
confirm := false
prompt := &survey.Confirm{Message: "Overwrite current install?"}
survey.AskOne(prompt, &confirm)
_ = forms.Confirm("Overwrite current install?", &confirm)
if !confirm {
return nil
}
+3 -4
View File
@@ -27,11 +27,11 @@ import (
"path/filepath"
"strings"
"github.com/AlecAivazis/survey/v2"
"github.com/bishopfox/sliver/client/assets"
"github.com/bishopfox/sliver/client/command/help"
"github.com/bishopfox/sliver/client/console"
consts "github.com/bishopfox/sliver/client/constants"
"github.com/bishopfox/sliver/client/forms"
"github.com/bishopfox/sliver/client/packages"
"github.com/bishopfox/sliver/protobuf/clientpb"
"github.com/bishopfox/sliver/protobuf/sliverpb"
@@ -311,10 +311,9 @@ func runAliasCommand(cmd *cobra.Command, con *console.SliverClient, args []strin
} else if !aliasManifest.IsReflective {
msgStr = " Arguments are limited to 256 characters when using the default fork/exec model for non-reflective PE payloads.\n"
}
con.PrintWarnf(msgStr)
con.PrintWarnf("%s", msgStr)
confirm := false
prompt := &survey.Confirm{Message: "Do you want to continue?"}
survey.AskOne(prompt, &confirm, nil)
_ = forms.Confirm("Do you want to continue?", &confirm)
if !confirm {
return
}
+2 -3
View File
@@ -24,9 +24,9 @@ import (
"os"
"path/filepath"
"github.com/AlecAivazis/survey/v2"
"github.com/bishopfox/sliver/client/assets"
"github.com/bishopfox/sliver/client/console"
"github.com/bishopfox/sliver/client/forms"
"github.com/spf13/cobra"
)
@@ -39,8 +39,7 @@ func AliasesRemoveCmd(cmd *cobra.Command, con *console.SliverClient, args []stri
return
}
confirm := false
prompt := &survey.Confirm{Message: fmt.Sprintf("Remove '%s' alias?", name)}
survey.AskOne(prompt, &confirm)
_ = forms.Confirm(fmt.Sprintf("Remove '%s' alias?", name), &confirm)
if !confirm {
return
}
+16
View File
@@ -0,0 +1,16 @@
# client/command/armory
## Overview
Implements the 'armory' command group for the Sliver client console. Handlers map Cobra invocations to armory workflows such as install, manage, parsers, and search.
## Go Files
- `armory.go` – Maintains the armory cache lifecycle, fetching package metadata, verifying signatures, and presenting bundle listings.
- `armory_test.go` *(tests)* – Placeholder for armory command tests; currently used to keep the package's test harness wired up.
- `commands.go` – Declares the Cobra command hierarchy for armory actions and binds shared flag/completion plumbing.
- `install.go` – Resolves dependencies and installs aliases or extensions from cached metadata, prompting when overwriting existing packages.
- `manage.go` – Implements management helpers for viewing, adding, verifying, and persisting armory configurations.
- `parsers.go` – Provides parsers and HTTP helpers for retrieving armory indexes and packages, including Minisign verification.
- `search.go` – Implements the regex-driven search command that filters cached armory packages.
- `update.go` – Calculates available package updates, presents options to the user, and orchestrates update installation.
+5 -12
View File
@@ -27,7 +27,6 @@ import (
"path/filepath"
"slices"
"github.com/AlecAivazis/survey/v2"
"github.com/spf13/cobra"
"github.com/bishopfox/sliver/client/assets"
@@ -35,6 +34,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/client/forms"
"github.com/bishopfox/sliver/util"
"github.com/bishopfox/sliver/util/minisign"
)
@@ -95,12 +95,9 @@ func ArmoryInstallCmd(cmd *cobra.Command, con *console.SliverClient, args []stri
if extCount == 1 {
pluralExtensions = ""
}
prompt := &survey.Confirm{
Message: fmt.Sprintf("Install %d alias%s and %d extension%s?",
aliasCount, pluralAliases, extCount, pluralExtensions,
),
}
survey.AskOne(prompt, &confirm)
forms.Confirm(fmt.Sprintf("Install %d alias%s and %d extension%s?",
aliasCount, pluralAliases, extCount, pluralExtensions,
), &confirm)
if !confirm {
return
}
@@ -296,11 +293,7 @@ func getPackageIDFromUser(name string, options map[string]string) string {
// Add a cancel option
optionKeys = append(optionKeys, doNotInstallOption)
options[doNotInstallOption] = doNotInstallPackageName
prompt := &survey.Select{
Message: fmt.Sprintf("More than one package contains the command %s. Please choose an option from the list below:", name),
Options: optionKeys,
}
survey.AskOne(prompt, &selectedPackageKey)
forms.Select(fmt.Sprintf("More than one package contains the command %s. Please choose an option from the list below:", name), optionKeys, &selectedPackageKey)
selectedPackageID := options[selectedPackageKey]
return selectedPackageID
+2 -3
View File
@@ -8,10 +8,10 @@ import (
"strings"
"sync"
"github.com/AlecAivazis/survey/v2"
"github.com/bishopfox/sliver/client/assets"
"github.com/bishopfox/sliver/client/command/settings"
"github.com/bishopfox/sliver/client/console"
"github.com/bishopfox/sliver/client/forms"
"github.com/jedib0t/go-pretty/v6/table"
"github.com/spf13/cobra"
)
@@ -602,8 +602,7 @@ func ModifyArmoryCmd(cmd *cobra.Command, con *console.SliverClient, args []strin
if err != nil {
con.PrintErrorf("could not modify armory: %s\n", err)
confirm := false
prompt := &survey.Confirm{Message: "Would you like to revert the properties of the armory back to their previous values?"}
survey.AskOne(prompt, &confirm, nil)
_ = forms.Confirm("Would you like to revert the properties of the armory back to their previous values?", &confirm)
if !confirm {
return
} else {
+3 -5
View File
@@ -25,7 +25,6 @@ import (
"strconv"
"strings"
"github.com/AlecAivazis/survey/v2"
"github.com/jedib0t/go-pretty/v6/table"
"github.com/spf13/cobra"
@@ -34,6 +33,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/client/forms"
"github.com/bishopfox/sliver/util"
)
@@ -89,7 +89,7 @@ func ArmoryUpdateCmd(cmd *cobra.Command, con *console.SliverClient, args []strin
displayAvailableUpdates(con, updateKeys, aliasUpdates, extUpdates)
selectedUpdates, err = getUpdatesFromUser(con, updateKeys)
if err != nil {
con.PrintErrorf(err.Error() + "\n")
con.PrintErrorf("%s\n", err.Error())
return
}
if len(selectedUpdates) == 0 {
@@ -305,9 +305,7 @@ func getUpdatesFromUser(con *console.SliverClient, updateKeys []UpdateIdentifier
var updateResponse string
con.Println("You can apply all, none, or some updates.\nTo apply some updates, specify the number of a single update, a range (1-3), or a combination of the two (1, 3-5, 7)\n")
err := survey.AskOne(&survey.Input{
Message: "Which updates would you like to apply? [A]ll, [N]one, or some:",
}, &updateResponse)
err := forms.Input("Which updates would you like to apply? [A]ll, [N]one, or some:", &updateResponse)
if err != nil {
// We do not need to set selectionError because an error here means the same thing as responding with "none"
return
+9 -3
View File
@@ -1,4 +1,10 @@
Backdoor
========
# client/command/backdoor
Implements command related to `backdoor`
## Overview
Implements the 'backdoor' command group for the Sliver client console.
## Go Files
- `backdoor.go` – Implements the RPC workflow that backdoors a remote binary with Sliver shellcode for the active session.
- `commands.go` – Registers the Cobra command, binds flags/completions, and restricts usage to applicable targets.
+13 -3
View File
@@ -1,4 +1,14 @@
Beacons
========
# client/command/beacons
This package implements the beacons command, which can be used to list and interact with beacons.
## Overview
Implements the 'beacons' command group for the Sliver client console. Handlers map Cobra invocations to beacons workflows such as prune, RM, and watch.
## Go Files
- `beacons.go` – Retrieves beacon inventories and renders them in tabular form with optional filtering.
- `commands.go` – Declares the beacons command set, binds flags/completions, and wires subcommands like prune, rm, and watch.
- `helpers.go` – Provides helper RPC wrappers for selecting, fetching, and listing beacons.
- `prune.go` – Implements the prune routine that removes stale beacon entries via the backend API.
- `rm.go` – Removes a specific beacon by ID, coordinating confirmation and RPC teardown.
- `watch.go` – Streams beacon events in a watch loop, handling cancellation and console interaction.
+2 -7
View File
@@ -26,9 +26,8 @@ import (
"strings"
"text/tabwriter"
"github.com/AlecAivazis/survey/v2"
"github.com/bishopfox/sliver/client/console"
"github.com/bishopfox/sliver/client/forms"
"github.com/bishopfox/sliver/protobuf/clientpb"
"github.com/bishopfox/sliver/protobuf/commonpb"
)
@@ -83,12 +82,8 @@ func SelectBeacon(con *console.SliverClient) (*clientpb.Beacon, error) {
options := strings.Split(outputBuf.String(), "\n")
options = options[:len(options)-1] // Remove the last empty option
prompt := &survey.Select{
Message: "Select a beacon:",
Options: options,
}
selected := ""
survey.AskOne(prompt, &selected)
_ = forms.Select("Select a beacon:", options, &selected)
if selected == "" {
return nil, ErrNoSelection
}
+2 -3
View File
@@ -21,10 +21,10 @@ package beacons
import (
"time"
"github.com/AlecAivazis/survey/v2"
"github.com/spf13/cobra"
"github.com/bishopfox/sliver/client/console"
"github.com/bishopfox/sliver/client/forms"
"github.com/bishopfox/sliver/protobuf/clientpb"
"github.com/bishopfox/sliver/protobuf/commonpb"
)
@@ -71,8 +71,7 @@ func BeaconsPruneCmd(cmd *cobra.Command, con *console.SliverClient, args []strin
}
con.Println()
confirm := false
prompt := &survey.Confirm{Message: "Prune these beacons?"}
survey.AskOne(prompt, &confirm)
_ = forms.Confirm("Prune these beacons?", &confirm)
if !confirm {
return
}
+10
View File
@@ -0,0 +1,10 @@
# client/command/builders
## Overview
Implements the 'builders' command group for the Sliver client console.
## Go Files
- `builders.go` – Fetches external builder metadata and formats it for console display.
- `commands.go` – Registers the builders CLI command with its flags and completion helpers.
+10
View File
@@ -0,0 +1,10 @@
# client/command/c2profiles
## Overview
Implements the 'c2profiles' command group for the Sliver client console. Handlers map Cobra invocations to c2profiles workflows such as C2 profiles.
## Go Files
- `c2profiles.go` – Implements listing, import/export, and generation routines for HTTP C2 profiles, including protobuf/JSON conversion helpers.
- `commands.go` – Binds the c2profiles command suite with flag handling and completions for profile management operations.
+82 -297
View File
@@ -23,14 +23,12 @@ import (
"encoding/json"
"fmt"
"io"
"math/rand"
"net/url"
"os"
"path"
"path/filepath"
"strings"
"github.com/AlecAivazis/survey/v2"
"github.com/jedib0t/go-pretty/v6/table"
"github.com/spf13/cobra"
"golang.org/x/exp/slices"
@@ -39,6 +37,7 @@ import (
"github.com/bishopfox/sliver/client/command/settings"
"github.com/bishopfox/sliver/client/console"
"github.com/bishopfox/sliver/client/constants"
"github.com/bishopfox/sliver/client/forms"
"github.com/bishopfox/sliver/protobuf/clientpb"
"github.com/bishopfox/sliver/protobuf/commonpb"
)
@@ -67,7 +66,6 @@ func C2ProfileCmd(cmd *cobra.Command, con *console.SliverClient, args []string)
}
func ImportC2ProfileCmd(cmd *cobra.Command, con *console.SliverClient, args []string) {
protocols := []string{constants.HttpStr, constants.HttpsStr}
profileName, _ := cmd.Flags().GetString("name")
if profileName == "" {
con.PrintErrorf("Invalid c2 profile name\n")
@@ -103,29 +101,6 @@ func ImportC2ProfileCmd(cmd *cobra.Command, con *console.SliverClient, args []st
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
}
}
}
func ExportC2ProfileCmd(cmd *cobra.Command, con *console.SliverClient, args []string) {
@@ -201,23 +176,6 @@ func GenerateC2ProfileCmd(cmd *cobra.Command, con *console.SliverClient, args []
return
}
c2Profiles, err := con.Rpc.GetHTTPC2Profiles(context.Background(), &commonpb.Empty{})
if err != nil {
con.PrintErrorf("%s\n", err)
return
}
var extensions []string
for _, c2profile := range c2Profiles.Configs {
confProfile, err := con.Rpc.GetHTTPC2ProfileByName(context.Background(), &clientpb.C2ProfileReq{Name: c2profile.Name})
if err != nil {
con.PrintErrorf("%s\n", err)
return
}
extensions = append(extensions, confProfile.ImplantConfig.StagerFileExtension)
extensions = append(extensions, confProfile.ImplantConfig.StartSessionFileExtension)
}
config, err := C2ConfigToJSON(profileName, profile)
if err != nil {
con.PrintErrorf("%s\n", err)
@@ -243,7 +201,7 @@ func GenerateC2ProfileCmd(cmd *cobra.Command, con *console.SliverClient, args []
}
urls := strings.Split(string(fileContent), "\n")
jsonProfile, err := updateC2Profile(extensions, config, urls)
jsonProfile, err := updateC2Profile(config, urls)
if err != nil {
con.PrintErrorf("%s\n", err)
return
@@ -264,26 +222,26 @@ func GenerateC2ProfileCmd(cmd *cobra.Command, con *console.SliverClient, args []
}
con.Println("C2 profile generated and saved as ", profileName)
} else {
PrintC2Profiles(profile, con)
PrintC2Profiles(C2ConfigToProtobuf(profileName, jsonProfile), con)
}
}
// convert protobuf to json
func C2ConfigToJSON(profileName string, profile *clientpb.HTTPC2Config) (*assets.HTTPC2Config, error) {
implantConfig := assets.HTTPC2ImplantConfig{
UserAgent: profile.ImplantConfig.UserAgent,
ChromeBaseVersion: int(profile.ImplantConfig.ChromeBaseVersion),
MacOSVersion: profile.ImplantConfig.MacOSVersion,
NonceQueryArgChars: profile.ImplantConfig.NonceQueryArgChars,
MaxFiles: int(profile.ImplantConfig.MaxFiles),
MinFiles: int(profile.ImplantConfig.MinFiles),
MaxPaths: int(profile.ImplantConfig.MaxPaths),
MinPaths: int(profile.ImplantConfig.MinFiles),
StagerFileExt: profile.ImplantConfig.StagerFileExtension,
PollFileExt: profile.ImplantConfig.PollFileExtension,
StartSessionFileExt: profile.ImplantConfig.StartSessionFileExtension,
SessionFileExt: profile.ImplantConfig.SessionFileExtension,
CloseFileExt: profile.ImplantConfig.CloseFileExtension,
UserAgent: profile.ImplantConfig.UserAgent,
ChromeBaseVersion: int(profile.ImplantConfig.ChromeBaseVersion),
MacOSVersion: profile.ImplantConfig.MacOSVersion,
NonceQueryArgChars: profile.ImplantConfig.NonceQueryArgChars,
NonceQueryLength: int(profile.ImplantConfig.NonceQueryLength),
NonceMode: profile.ImplantConfig.NonceMode,
MaxFileGen: int(profile.ImplantConfig.MaxFileGen),
MinFileGen: int(profile.ImplantConfig.MinFileGen),
MaxPathGen: int(profile.ImplantConfig.MaxPathGen),
MinPathGen: int(profile.ImplantConfig.MinFileGen),
MaxPathLength: int(profile.ImplantConfig.MaxPathLength),
MinPathLength: int(profile.ImplantConfig.MinPathLength),
Extensions: profile.ImplantConfig.Extensions,
}
var headers []assets.NameValueProbability
@@ -308,50 +266,19 @@ func C2ConfigToJSON(profileName string, profile *clientpb.HTTPC2Config) (*assets
implantConfig.URLParameters = urlParameters
var (
stagerFiles []string
pollFiles []string
sessionFiles []string
closeFiles []string
stagerPaths []string
pollPaths []string
sessionPaths []string
closePaths []string
files []string
paths []string
)
for _, pathSegment := range profile.ImplantConfig.PathSegments {
if pathSegment.IsFile {
switch pathSegment.SegmentType {
case 0:
pollFiles = append(pollFiles, pathSegment.Value)
case 1:
sessionFiles = append(sessionFiles, pathSegment.Value)
case 2:
closeFiles = append(closeFiles, pathSegment.Value)
case 3:
stagerFiles = append(stagerFiles, pathSegment.Value)
}
files = append(files, pathSegment.Value)
} else {
switch pathSegment.SegmentType {
case 0:
pollPaths = append(pollPaths, pathSegment.Value)
case 1:
sessionPaths = append(sessionPaths, pathSegment.Value)
case 2:
closePaths = append(closePaths, pathSegment.Value)
case 3:
stagerPaths = append(stagerPaths, pathSegment.Value)
}
paths = append(paths, pathSegment.Value)
}
}
implantConfig.PollFiles = pollFiles
implantConfig.SessionFiles = sessionFiles
implantConfig.CloseFiles = closeFiles
implantConfig.StagerFiles = stagerFiles
implantConfig.PollPaths = pollPaths
implantConfig.SessionPaths = sessionPaths
implantConfig.ClosePaths = closePaths
implantConfig.StagerPaths = stagerPaths
implantConfig.Files = files
implantConfig.Paths = paths
var serverHeaders []assets.NameValueProbability
for _, header := range profile.ServerConfig.Headers {
@@ -390,68 +317,17 @@ func C2ConfigToProtobuf(profileName string, config *assets.HTTPC2Config) *client
pathSegments := []*clientpb.HTTPC2PathSegment{}
// files
for _, poll := range config.ImplantConfig.PollFiles {
for _, file := range config.ImplantConfig.Files {
pathSegments = append(pathSegments, &clientpb.HTTPC2PathSegment{
IsFile: true,
SegmentType: 0,
Value: poll,
IsFile: true,
Value: file,
})
}
for _, session := range config.ImplantConfig.SessionFiles {
for _, path := range config.ImplantConfig.Paths {
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,
IsFile: false,
Value: path,
})
}
@@ -474,22 +350,22 @@ func C2ConfigToProtobuf(profileName string, config *assets.HTTPC2Config) *client
}
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,
UserAgent: config.ImplantConfig.UserAgent,
ChromeBaseVersion: int32(config.ImplantConfig.ChromeBaseVersion),
MacOSVersion: config.ImplantConfig.MacOSVersion,
NonceQueryArgChars: config.ImplantConfig.NonceQueryArgChars,
NonceQueryLength: int32(config.ImplantConfig.NonceQueryLength),
NonceMode: config.ImplantConfig.NonceMode,
ExtraURLParameters: httpC2UrlParameters,
Headers: httpC2Headers,
MaxFileGen: int32(config.ImplantConfig.MaxFileGen),
MinFileGen: int32(config.ImplantConfig.MinFileGen),
MaxPathGen: int32(config.ImplantConfig.MaxPathGen),
MinPathGen: int32(config.ImplantConfig.MinPathGen),
MaxPathLength: int32(config.ImplantConfig.MaxPathLength),
MinPathLength: int32(config.ImplantConfig.MinPathLength),
Extensions: config.ImplantConfig.Extensions,
PathSegments: pathSegments,
}
// Server Config
@@ -599,96 +475,65 @@ func PrintC2Profiles(profile *clientpb.HTTPC2Config, con *console.SliverClient)
"Nonce query arg chars",
profile.ImplantConfig.NonceQueryArgChars,
})
tw.AppendRow(table.Row{
"Nonce query length",
profile.ImplantConfig.NonceQueryLength,
})
tw.AppendRow(table.Row{
"Nonce mode",
profile.ImplantConfig.NonceMode,
})
tw.AppendRow(table.Row{
"Max files",
profile.ImplantConfig.MaxFiles,
profile.ImplantConfig.MaxFileGen,
})
tw.AppendRow(table.Row{
"Min files",
profile.ImplantConfig.MinFiles,
profile.ImplantConfig.MinFileGen,
})
tw.AppendRow(table.Row{
"Max paths",
profile.ImplantConfig.MaxPaths,
profile.ImplantConfig.MaxPathGen,
})
tw.AppendRow(table.Row{
"Min paths",
profile.ImplantConfig.MinPaths,
profile.ImplantConfig.MinPathGen,
})
tw.AppendRow(table.Row{
"Stager file extension",
profile.ImplantConfig.StagerFileExtension,
"Max path length",
profile.ImplantConfig.MaxPathLength,
})
tw.AppendRow(table.Row{
"Start session file extension",
profile.ImplantConfig.StartSessionFileExtension,
"Min path length",
profile.ImplantConfig.MinPathLength,
})
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,
"File extensions",
strings.Join(profile.ImplantConfig.Extensions, ","),
})
var (
pollPaths []string
pollFiles []string
sessionPaths []string
sessionFiles []string
closePaths []string
closeFiles []string
paths []string
files []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)
}
files = append(files, 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)
}
paths = append(paths, segment.Value)
}
}
tw.AppendRow(table.Row{
"Poll paths",
strings.Join(pollPaths[:], ","),
"Paths",
strings.Join(paths[:], ",")[:50] + "...",
})
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[:], ","),
"Files",
strings.Join(files[:], ",")[:50] + "...",
})
con.Println(tw.Render())
@@ -702,23 +547,18 @@ func selectC2Profile(c2profiles []*clientpb.HTTPC2Config) string {
choices = append(choices, c2profile.Name)
}
prompt := &survey.Select{
Message: "Select a c2 profile",
Options: choices,
}
survey.AskOne(prompt, &c2profile, nil)
_ = forms.Select("Select a c2 profile", choices, &c2profile)
return c2profile
}
func updateC2Profile(usedExtensions []string, template *assets.HTTPC2Config, urls []string) (*assets.HTTPC2Config, error) {
func updateC2Profile(template *assets.HTTPC2Config, urls []string) (*assets.HTTPC2Config, error) {
// update the template with the urls
var (
paths []string
filenames []string
extensions []string
filteredExtensions []string
paths []string
filenames []string
extensions []string
)
for _, urlPath := range urls {
@@ -747,23 +587,13 @@ func updateC2Profile(usedExtensions []string, template *assets.HTTPC2Config, url
slices.Sort(extensions)
extensions = slices.Compact(extensions)
for _, extension := range extensions {
if !slices.Contains(usedExtensions, extension) {
filteredExtensions = append(filteredExtensions, extension)
}
}
slices.Sort(paths)
paths = slices.Compact(paths)
slices.Sort(filenames)
filenames = slices.Compact(filenames)
// 5 is arbitrarily used as a minimum value, it only has to be 5 for the extensions, the others can be lower
if len(filteredExtensions) < 5 {
return nil, fmt.Errorf("got %d unused extensions, need at least 5", len(filteredExtensions))
}
// 5 is arbitrarily used as a minimum value
if len(paths) < 5 {
return nil, fmt.Errorf("got %d paths need at least 5", len(paths))
}
@@ -772,53 +602,8 @@ func updateC2Profile(usedExtensions []string, template *assets.HTTPC2Config, url
return nil, fmt.Errorf("got %d paths need at least 5", len(filenames))
}
// shuffle extensions
for i := len(extensions) - 1; i > 0; i-- {
j := rand.Intn(i + 1)
extensions[i], extensions[j] = extensions[j], extensions[i]
}
template.ImplantConfig.PollFileExt = extensions[0]
template.ImplantConfig.StagerFileExt = extensions[1]
template.ImplantConfig.StartSessionFileExt = extensions[2]
template.ImplantConfig.SessionFileExt = extensions[3]
template.ImplantConfig.CloseFileExt = extensions[4]
// randomly distribute the paths and filenames into the different segment types
template.ImplantConfig.CloseFiles = []string{}
template.ImplantConfig.SessionFiles = []string{}
template.ImplantConfig.PollFiles = []string{}
template.ImplantConfig.StagerFiles = []string{}
template.ImplantConfig.ClosePaths = []string{}
template.ImplantConfig.SessionPaths = []string{}
template.ImplantConfig.PollPaths = []string{}
template.ImplantConfig.StagerPaths = []string{}
for _, path := range paths {
switch rand.Intn(4) {
case 0:
template.ImplantConfig.PollPaths = append(template.ImplantConfig.PollPaths, path)
case 1:
template.ImplantConfig.SessionPaths = append(template.ImplantConfig.SessionPaths, path)
case 2:
template.ImplantConfig.ClosePaths = append(template.ImplantConfig.ClosePaths, path)
case 3:
template.ImplantConfig.StagerPaths = append(template.ImplantConfig.StagerPaths, path)
}
}
for _, filename := range filenames {
switch rand.Intn(4) {
case 0:
template.ImplantConfig.PollFiles = append(template.ImplantConfig.PollFiles, filename)
case 1:
template.ImplantConfig.SessionFiles = append(template.ImplantConfig.SessionFiles, filename)
case 2:
template.ImplantConfig.CloseFiles = append(template.ImplantConfig.CloseFiles, filename)
case 3:
template.ImplantConfig.StagerFiles = append(template.ImplantConfig.StagerFiles, filename)
}
}
template.ImplantConfig.Extensions = extensions
template.ImplantConfig.Paths = paths
template.ImplantConfig.Files = filenames
return template, nil
}
+10
View File
@@ -0,0 +1,10 @@
# client/command/certificates
## Overview
Implements the 'certificates' command group for the Sliver client console.
## Go Files
- `certificates.go` – Retrieves certificate metadata from the server, formats expiration status, and prints results to the console.
- `commands.go` – Registers the certificates command and binds the flags needed to query certificate inventories.
+9
View File
@@ -0,0 +1,9 @@
# client/command/clean
## Overview
Implements the 'clean' command group for the Sliver client console.
## Go Files
- `clean.go` – Defines the clean command and its helpers that purge local build artifacts, cached profiles, and stale sessions.
+2 -3
View File
@@ -21,10 +21,10 @@ package clean
import (
"context"
"github.com/AlecAivazis/survey/v2"
"github.com/bishopfox/sliver/client/command/flags"
"github.com/bishopfox/sliver/client/console"
"github.com/bishopfox/sliver/client/constants"
"github.com/bishopfox/sliver/client/forms"
"github.com/bishopfox/sliver/protobuf/clientpb"
"github.com/bishopfox/sliver/protobuf/commonpb"
"github.com/bishopfox/sliver/protobuf/sliverpb"
@@ -35,8 +35,7 @@ import (
func CleanCmd(cmd *cobra.Command, con *console.SliverClient, args []string) {
con.Printf("This command will kill and remove all sessions, beacons and profiles \n")
confirm := false
prompt := &survey.Confirm{Message: "Are you sure you want to destroy everything?"}
survey.AskOne(prompt, &confirm)
_ = forms.Confirm("Are you sure you want to destroy everything?", &confirm)
if !confirm {
return
}
+8 -3
View File
@@ -1,4 +1,9 @@
Completers
===========
# client/command/completers
This package contains general purpose completers for the console, note that some package also contain their own package-specific completers.
## Overview
Implements the 'completers' command group for the Sliver client console.
## Go Files
- `completers.go` – Provides reusable carapace completion helpers for selecting client interfaces and proxy endpoints.
+12
View File
@@ -0,0 +1,12 @@
# client/command/crack
## Overview
Implements the 'crack' command group for the Sliver client console. Handlers map Cobra invocations to crack workflows such as crack files.
## Go Files
- `commands.go` – Defines the crack command hierarchy, attaching operations for stations and file management.
- `crack-files.go` – Manages cracking asset uploads, listings, and removals, handling streaming transfers and chunking.
- `crack.go` – Implements station status reporting, health checks, and list rendering for distributed cracking nodes.
- `helpers.go` – Supplies completion helpers and byte formatting utilities for crack subcommands.
+14
View File
@@ -0,0 +1,14 @@
# client/command/creds
## Overview
Implements the 'creds' command group for the Sliver client console. Handlers map Cobra invocations to creds workflows such as ADD, hash types, RM, and select.
## Go Files
- `add.go` – Adds credentials to the client store via interactive or flag-based input.
- `commands.go` – Registers credential management commands and subcommands.
- `creds.go` – Lists stored credentials and formats them for display.
- `hash-types.go` – Enumerates supported hash types and their identifiers.
- `rm.go` – Removes credentials by ID or filter from the store.
- `select.go` – Selects credentials for use in other workflows, updating defaults.
+2 -6
View File
@@ -8,8 +8,8 @@ import (
"strings"
"text/tabwriter"
"github.com/AlecAivazis/survey/v2"
"github.com/bishopfox/sliver/client/console"
"github.com/bishopfox/sliver/client/forms"
"github.com/bishopfox/sliver/protobuf/clientpb"
"github.com/bishopfox/sliver/protobuf/commonpb"
)
@@ -55,11 +55,7 @@ func SelectCredential(plaintext bool, hashType clientpb.HashType, con *console.S
}
selected := ""
prompt := &survey.Select{
Message: "Select a credential:",
Options: options,
}
err = survey.AskOne(prompt, &selected)
err = forms.Select("Select a credential:", options, &selected)
if err != nil {
return nil, err
}
+16 -2
View File
@@ -1,3 +1,17 @@
# Cursed
# client/command/cursed
Cursed is a Sliver Chrome/Electron post-exploitation tool kit based on/integrated with [CursedChrome](https://github.com/mandatoryprogrammer/CursedChrome). Code injection is performed via the [DevTools protocol](https://chromedevtools.github.io/devtools-protocol/).
## Overview
Implements the 'cursed' command group for the Sliver client console. Handlers map Cobra invocations to cursed workflows such as cursed chrome, cursed console, cursed cookies, and cursed edge.
## Go Files
- `commands.go` – Exposes the cursed command suite and binds individual subcommands for supported targets.
- `cursed-chrome.go` – Launches or hijacks Chrome debugging sessions, locating executables and wiring remote control.
- `cursed-console.go` – Provides the interactive cursed console experience atop Chrome DevTools sessions.
- `cursed-cookies.go` – Fetches and displays browser cookies from an active cursed session.
- `cursed-edge.go` – Mirrors the Chrome workflow for Microsoft Edge, including process discovery logic.
- `cursed-electron.go` – Drives cursed interactions with arbitrary Electron apps, validating binaries and starting injected sessions.
- `cursed-rm.go` – Removes cursed sessions from the client cache and tears down associated resources.
- `cursed-screenshot.go` – Captures screenshots from a cursed browser context via DevTools APIs.
- `cursed.go` – Manages the cursed process registry, selection helpers, and remote debugger configuration defaults.
+4 -4
View File
@@ -23,19 +23,19 @@ import (
"errors"
"fmt"
"log"
insecureRand "math/rand"
"os"
"strings"
"time"
"github.com/AlecAivazis/survey/v2"
"github.com/bishopfox/sliver/client/console"
"github.com/bishopfox/sliver/client/core"
"github.com/bishopfox/sliver/client/forms"
"github.com/bishopfox/sliver/client/overlord"
"github.com/bishopfox/sliver/client/tcpproxy"
"github.com/bishopfox/sliver/protobuf/clientpb"
"github.com/bishopfox/sliver/protobuf/commonpb"
"github.com/bishopfox/sliver/protobuf/sliverpb"
"github.com/bishopfox/sliver/util"
"github.com/spf13/cobra"
)
@@ -123,7 +123,7 @@ func avadaKedavraChrome(session *clientpb.Session, cmd *cobra.Command, con *cons
con.PrintWarnf("Sliver will attempt to restore the user's session, however %sDATA LOSS MAY OCCUR!%s\n", console.Bold, console.Normal)
con.Printf("\n")
confirm := false
err = survey.AskOne(&survey.Confirm{Message: "Kill and restore existing Chrome process?"}, &confirm)
err = forms.Confirm("Kill and restore existing Chrome process?", &confirm)
if err != nil {
con.PrintErrorf("%s\n", err)
return nil
@@ -213,7 +213,7 @@ func startCursedChromeProcess(isEdge bool, session *clientpb.Session, cmd *cobra
con.PrintInfof("Waiting for %s process to initialize ... ", name)
time.Sleep(2 * time.Second)
bindPort := insecureRand.Intn(10000) + 40000
bindPort := util.Intn(10000) + 40000
bindAddr := fmt.Sprintf("127.0.0.1:%d", bindPort)
remoteAddr := fmt.Sprintf("127.0.0.1:%d", debugPort)
+2 -6
View File
@@ -26,9 +26,9 @@ import (
"strings"
"text/tabwriter"
"github.com/AlecAivazis/survey/v2"
"github.com/bishopfox/sliver/client/console"
"github.com/bishopfox/sliver/client/core"
"github.com/bishopfox/sliver/client/forms"
"github.com/bishopfox/sliver/client/overlord"
"github.com/reeflective/readline"
"github.com/spf13/cobra"
@@ -71,12 +71,8 @@ func selectDebugTarget(targets []overlord.ChromeDebugTarget, con *console.Sliver
table.Flush()
options := strings.Split(outputBuf.String(), "\n")
options = options[:len(options)-1] // Remove the last empty option
prompt := &survey.Select{
Message: "Select a debug target:",
Options: options,
}
selected := ""
err := survey.AskOne(prompt, &selected)
err := forms.Select("Select a debug target:", options, &selected)
if err != nil {
con.PrintErrorf("%s\n", err)
return nil
+11 -10
View File
@@ -21,9 +21,10 @@ package cursed
import (
"fmt"
"os"
"strings"
"time"
"encoding/json"
"github.com/bishopfox/sliver/client/console"
"github.com/bishopfox/sliver/client/overlord"
"github.com/spf13/cobra"
@@ -46,24 +47,24 @@ func CursedCookiesCmd(cmd *cobra.Command, con *console.SliverClient, args []stri
if len(cookies) == 0 {
return
}
saveFile, _ := cmd.Flags().GetString("save")
if saveFile == "" {
saveFile = fmt.Sprintf("cookies-%s.json", time.Now().Format("20060102150405"))
}
jsonCookies := []string{}
for _, cookie := range cookies {
jsonCookie, err := cookie.MarshalJSON()
if err != nil {
con.PrintErrorf("Failed to marshal cookie: %s\n", err)
continue
}
jsonCookies = append(jsonCookies, string(jsonCookie))
jsonBytes, err := json.MarshalIndent(cookies, "", " ")
if err != nil {
con.PrintErrorf("Failed to marshal cookies: %s\n", err)
return
}
err = os.WriteFile(saveFile, []byte(strings.Join(jsonCookies, "\n")), 0o600)
err = os.WriteFile(saveFile, jsonBytes, 0o600)
if err != nil {
con.PrintErrorf("Failed to save cookies: %s\n", err)
return
}
con.PrintInfof("Saved to %s", saveFile)
con.Println()
}
+2 -2
View File
@@ -23,9 +23,9 @@ import (
"os"
"strings"
"github.com/AlecAivazis/survey/v2"
"github.com/bishopfox/sliver/client/console"
"github.com/bishopfox/sliver/client/core"
"github.com/bishopfox/sliver/client/forms"
"github.com/bishopfox/sliver/client/overlord"
"github.com/bishopfox/sliver/protobuf/clientpb"
"github.com/bishopfox/sliver/protobuf/commonpb"
@@ -106,7 +106,7 @@ func avadaKedavraEdge(session *clientpb.Session, cmd *cobra.Command, con *consol
con.PrintWarnf("Sliver will attempt to restore the user's session, however %sDATA LOSS MAY OCCUR!%s\n", console.Bold, console.Normal)
con.Printf("\n")
confirm := false
err = survey.AskOne(&survey.Confirm{Message: "Kill and restore existing Edge process?"}, &confirm)
err = forms.Confirm("Kill and restore existing Edge process?", &confirm)
if err != nil {
con.PrintErrorf("%s\n", err)
return nil
+5 -5
View File
@@ -22,18 +22,18 @@ import (
"context"
"fmt"
"log"
insecureRand "math/rand"
"path"
"time"
"github.com/AlecAivazis/survey/v2"
"github.com/bishopfox/sliver/client/console"
"github.com/bishopfox/sliver/client/core"
"github.com/bishopfox/sliver/client/forms"
"github.com/bishopfox/sliver/client/overlord"
"github.com/bishopfox/sliver/client/tcpproxy"
"github.com/bishopfox/sliver/protobuf/clientpb"
"github.com/bishopfox/sliver/protobuf/commonpb"
"github.com/bishopfox/sliver/protobuf/sliverpb"
"github.com/bishopfox/sliver/util"
"github.com/spf13/cobra"
)
@@ -88,7 +88,7 @@ func avadaKedavraElectron(electronExe string, session *clientpb.Session, cmd *co
con.PrintWarnf("%sDATA LOSS MAY OCCUR!%s\n", console.Bold, console.Normal)
con.Printf("\n")
confirm := false
err = survey.AskOne(&survey.Confirm{Message: "Kill and restart the process?"}, &confirm)
err = forms.Confirm("Kill and restart the process?", &confirm)
if err != nil {
con.PrintErrorf("%s\n", err)
return nil
@@ -118,7 +118,7 @@ func avadaKedavraElectron(electronExe string, session *clientpb.Session, cmd *co
return curse
}
func checkElectronPath(electronExe string, session *clientpb.Session, cmd *cobra.Command, con *console.SliverClient) (bool, error) {
func checkElectronPath(electronExe string, _ *clientpb.Session, cmd *cobra.Command, con *console.SliverClient) (bool, error) {
ls, err := con.Rpc.Ls(context.Background(), &sliverpb.LsReq{
Request: con.ActiveTarget.Request(cmd),
Path: electronExe,
@@ -175,7 +175,7 @@ func startCursedElectronProcess(electronExe string, session *clientpb.Session, c
con.PrintInfof("Waiting for process to initialize ... ")
time.Sleep(2 * time.Second)
bindPort := insecureRand.Intn(10000) + 40000
bindPort := util.Intn(10000) + 40000
bindAddr := fmt.Sprintf("127.0.0.1:%d", bindPort)
remoteAddr := fmt.Sprintf("127.0.0.1:%d", debugPort)
+2 -2
View File
@@ -22,9 +22,9 @@ import (
"context"
"strconv"
"github.com/AlecAivazis/survey/v2"
"github.com/bishopfox/sliver/client/console"
"github.com/bishopfox/sliver/client/core"
"github.com/bishopfox/sliver/client/forms"
"github.com/bishopfox/sliver/protobuf/sliverpb"
"github.com/spf13/cobra"
)
@@ -44,7 +44,7 @@ func CursedRmCmd(cmd *cobra.Command, con *console.SliverClient, args []string) {
core.CloseCursedProcessesByBindPort(session.ID, bindPort)
if kill {
confirm := false
err := survey.AskOne(&survey.Confirm{Message: "Kill the cursed process?"}, &confirm)
err := forms.Confirm("Kill the cursed process?", &confirm)
if err != nil {
con.PrintErrorf("%s", err)
return
+4 -8
View File
@@ -21,15 +21,15 @@ package cursed
import (
"bytes"
"fmt"
insecureRand "math/rand"
"strconv"
"strings"
"text/tabwriter"
"github.com/AlecAivazis/survey/v2"
"github.com/bishopfox/sliver/client/command/settings"
"github.com/bishopfox/sliver/client/console"
"github.com/bishopfox/sliver/client/core"
"github.com/bishopfox/sliver/client/forms"
"github.com/bishopfox/sliver/util"
"github.com/jedib0t/go-pretty/v6/table"
"github.com/spf13/cobra"
)
@@ -95,12 +95,8 @@ func selectCursedProcess(con *console.SliverClient) *core.CursedProcess {
table.Flush()
options := strings.Split(outputBuf.String(), "\n")
options = options[:len(options)-1] // Remove the last empty option
prompt := &survey.Select{
Message: "Select a curse:",
Options: options,
}
selected := ""
err := survey.AskOne(prompt, &selected)
err := forms.Select("Select a curse:", options, &selected)
if err != nil {
con.PrintErrorf("%s\n", err)
return nil
@@ -115,7 +111,7 @@ func selectCursedProcess(con *console.SliverClient) *core.CursedProcess {
func getRemoteDebuggerPort(cmd *cobra.Command) int {
port, _ := cmd.Flags().GetInt("remote-debugging-port")
if port == 0 {
port = insecureRand.Intn(30000) + 10000
port = util.Intn(30000) + 10000
}
return port
}
+9 -3
View File
@@ -1,4 +1,10 @@
DLL Hijack
===========
# client/command/dllhijack
Implements command related to `dllhijack`.
## Overview
Implements the 'dllhijack' command group for the Sliver client console.
## Go Files
- `commands.go` – Registers the dllhijack command, its flags, and completions for selecting remote DLL targets.
- `dllhijack.go` – Performs the RPC call that plants a Sliver DLL alongside a target executable for hijacking.
+11 -3
View File
@@ -1,4 +1,12 @@
Environment
===========
# client/command/environment
Contains command implementations for manipulating remote environment variables.
## Overview
Implements the 'environment' command group for the Sliver client console. Handlers map Cobra invocations to environment workflows such as GET, SET, and unset.
## Go Files
- `commands.go` – Declares environment command variations and wires subcommands for get/set/unset operations with shared flags.
- `get.go` – Invokes the RPC to retrieve environment variables and prints the results for sessions or beacons.
- `set.go` – Handles setting environment variables remotely, including beacon callback handling and result formatting.
- `unset.go` – Removes environment variables on the remote target and reports task outcomes back to the user.
+18 -3
View File
@@ -1,4 +1,19 @@
Exec
====
# client/command/exec
Implements execution related commands like `execute`, `execute-shellcode`, `execute-assembly`, etc.
## Overview
Implements the 'exec' command group for the Sliver client console. Handlers map Cobra invocations to exec workflows such as execute assembly, execute shellcode, execute, and migrate.
## Go Files
- `commands.go` – Registers the exec command family and binds shared flags across execution techniques.
- `execute-assembly.go` – Uploads .NET assemblies and triggers in-memory execution, handling results and loot capture.
- `execute-shellcode.go` – Executes raw shellcode via RPC, supporting interactive injection and task result printing.
- `execute.go` – Runs arbitrary commands, streams combined stdout/stderr, and persists output as loot when requested.
- `migrate.go` – Implements process migration, moving implants into new host processes and reporting completion.
- `msf-inject.go` – Coordinates Metasploit payload injection tasks and prints remote execution responses.
- `msf.go` – Launches Metasploit jobs on targets and tracks their beacon callbacks.
- `psexec.go` – Provides PsExec-style remote service deployment using generated binaries and random filenames.
- `sideload.go` – Executes unmanaged DLL exports in a remote process and summarizes task output.
- `spawndll.go` – Spawns new processes with DLL injection, capturing returned handles and statuses.
- `ssh.go` – Runs remote commands over SSH, sourcing credentials from loot and presenting command output.
+2 -3
View File
@@ -24,8 +24,8 @@ import (
"path/filepath"
"strings"
"github.com/AlecAivazis/survey/v2"
"github.com/bishopfox/sliver/client/console"
"github.com/bishopfox/sliver/client/forms"
"github.com/bishopfox/sliver/protobuf/clientpb"
"github.com/bishopfox/sliver/protobuf/sliverpb"
"github.com/spf13/cobra"
@@ -82,8 +82,7 @@ func ExecuteAssemblyCmd(cmd *cobra.Command, con *console.SliverClient, args []st
if len(assemblyArgsStr) > 256 && !inProcess {
con.PrintWarnf(" Injected .NET assembly arguments are limited to 256 characters when using the default fork/exec model.\nConsider using the --in-process flag to execute the .NET assembly in-process and work around this limitation.\n")
confirm := false
prompt := &survey.Confirm{Message: "Do you want to continue?"}
survey.AskOne(prompt, &confirm, nil)
_ = forms.Confirm("Do you want to continue?", &confirm)
if !confirm {
return
}
+9 -9
View File
@@ -21,7 +21,6 @@ package exec
import (
"context"
"fmt"
insecureRand "math/rand"
"os"
"strings"
"time"
@@ -32,6 +31,7 @@ import (
"github.com/bishopfox/sliver/protobuf/clientpb"
"github.com/bishopfox/sliver/protobuf/commonpb"
"github.com/bishopfox/sliver/protobuf/sliverpb"
"github.com/bishopfox/sliver/util"
"github.com/bishopfox/sliver/util/encoders"
"github.com/spf13/cobra"
)
@@ -175,8 +175,8 @@ func PsExecCmd(cmd *cobra.Command, con *console.SliverClient, args []string) {
func randomString() string {
alphanumeric := "abcdefghijklmnopqrstuvwxyz0123456789"
str := ""
for index := 0; index < insecureRand.Intn(8)+1; index++ {
str += string(alphanumeric[insecureRand.Intn(len(alphanumeric))])
for index := 0; index < util.Intn(8)+1; index++ {
str += string(alphanumeric[util.Intn(len(alphanumeric))])
}
return str
}
@@ -184,7 +184,7 @@ func randomString() string {
func randomFileName() string {
noun := randomString()
noun = strings.ToLower(noun)
switch insecureRand.Intn(3) {
switch util.Intn(3) {
case 0:
noun = strings.ToUpper(noun)
case 1:
@@ -192,16 +192,16 @@ func randomFileName() string {
}
separators := []string{"", "", "", "", "", ".", "-", "_", "--", "__"}
sep := separators[insecureRand.Intn(len(separators))]
sep := separators[util.Intn(len(separators))]
alphanumeric := "abcdefghijklmnopqrstuvwxyz0123456789"
prefix := ""
for index := 0; index < insecureRand.Intn(3); index++ {
prefix += string(alphanumeric[insecureRand.Intn(len(alphanumeric))])
for index := 0; index < util.Intn(3); index++ {
prefix += string(alphanumeric[util.Intn(len(alphanumeric))])
}
suffix := ""
for index := 0; index < insecureRand.Intn(6)+1; index++ {
suffix += string(alphanumeric[insecureRand.Intn(len(alphanumeric))])
for index := 0; index < util.Intn(6)+1; index++ {
suffix += string(alphanumeric[util.Intn(len(alphanumeric))])
}
return fmt.Sprintf("%s%s%s%s%s", prefix, sep, noun, sep, suffix)
+2 -3
View File
@@ -23,8 +23,8 @@ import (
"os"
"strings"
"github.com/AlecAivazis/survey/v2"
"github.com/bishopfox/sliver/client/console"
"github.com/bishopfox/sliver/client/forms"
"github.com/bishopfox/sliver/protobuf/clientpb"
"github.com/bishopfox/sliver/protobuf/sliverpb"
"github.com/spf13/cobra"
@@ -145,8 +145,7 @@ func tryCredsFromLoot(con *console.SliverClient) (string, string, []byte) {
privKey []byte
)
confirm := false
prompt := &survey.Confirm{Message: "No credentials provided, use from loot?"}
survey.AskOne(prompt, &confirm, nil)
_ = forms.Confirm("No credentials provided, use from loot?", &confirm)
if confirm {
// cred, err := loot.SelectCredentials(con)
// if err != nil {
+9
View File
@@ -0,0 +1,9 @@
# client/command/exit
## Overview
Implements the 'exit' command group for the Sliver client console.
## Go Files
- `exit.go` – Implements the client exit command, ensuring cleanup before terminating the console.
+2 -3
View File
@@ -23,9 +23,9 @@ import (
"fmt"
"os"
"github.com/AlecAivazis/survey/v2"
"github.com/bishopfox/sliver/client/console"
"github.com/bishopfox/sliver/client/constants"
"github.com/bishopfox/sliver/client/forms"
"github.com/bishopfox/sliver/protobuf/commonpb"
"github.com/spf13/cobra"
)
@@ -45,8 +45,7 @@ func ExitCmd(cmd *cobra.Command, con *console.SliverClient, args []string) {
if 0 < len(sessions.Sessions) || 0 < len(beacons.Beacons) {
con.Printf("There are %d active sessions and %d active beacons.\n", len(sessions.Sessions), len(beacons.Beacons))
confirm := false
prompt := &survey.Confirm{Message: "Are you sure you want to exit?"}
survey.AskOne(prompt, &confirm)
_ = forms.Confirm("Are you sure you want to exit?", &confirm)
if !confirm {
return
}
+12 -63
View File
@@ -1,67 +1,16 @@
Extensions
===========
# client/command/extensions
Allows to load and execute 3rd party extensions.
## Overview
Extensions directory structures can be arbitrary, however in the root of the directory or .tar.gz there
must be a `extension.json` or a `alias.json` file. All paths are relative to the manifest/root directory,
parent directories are not allowed. Only files listed in the manifest are copied, any other files will
be ignored.
Implements the 'extensions' command group for the Sliver client console. Handlers map Cobra invocations to extensions workflows such as argparser, install, list, and load.
```shell
/path/to/extension/folder/
├── extension.json
└── windows
│ └── extension.x86.dll
│ └── extension.x64.dll
└── linux
│ └── extension.x86.so
│ └── extension.x64.so
└── darwin
└── extension.x86.dylib
└── extension.x64.dylib
```
## Go Files
Here's an example manifest (i.e., the `extension.json` or a `alias.json`):
```json
{
"name": "foo",
"version": "1.0.0",
"extension_author": "ac1d-burn",
"original_author": "zer0-cool",
"repo_url": "https://github.com/foo/bar",
"help": "Help for foo command",
"entrypoint": "RunFoo",
"init" :"NimMain",
"depends_on": "bar",
"files": [
{
"os": "windows",
"arch": "amd64",
"path": "extension.x64.o",
}
],
"arguments": [
{"name": "pid", "type": "int", "desc": "pid", "optional": false},
]
}
```
The structure is the following one:
- `name`: name of the extension, which will also be the name of the command in the sliver client
- `help`: the documentation for the new command
- `entrypoint`: the name of the exported function to call
- `files`: a list of object pointing to the extensions files to load for each architectures and operating systems
- `init`: the initialization function name (if relevant, can be omitted)
- `arguments`: an optional list of objects (for DLLs), but mandatory for BOFs
- `depends_on`: the name of an extension required by the current extension (won't load if the dependency is not loaded)
The `type` of an argument can be one of the following:
- `string`: regular ASCII string
- `wstring`: string that will be UTF16 encoded
- `int`: will be parsed as a 32 bit unsigned integer
- `short`: will be parsed as a 16 bit unsigned integer
- `file`: a string to a file path on the client side which content will be passed to the BOF
- `argparser.go` – Builds argument buffers for extensions, including BOF-specific marshaling and validation.
- `commands.go` – Declares the extensions command tree and binds subcommands for list, install, load, and remove actions.
- `extensions.go` – Manages installed/temporary extension manifests, printing metadata and supplying completers.
- `extensions_test.go` *(tests)* – Verifies manifest parsing and conversion routines to guard against format regressions.
- `install.go` – Installs extension bundles from directories or archives, handling overwrite prompts and asset extraction.
- `list.go` – Queries the server for matching extensions and renders results categorized by hash or type.
- `load.go` – Loads extension binaries for the active target, registers generated commands, and dispatches execution RPCs.
- `remove.go` – Removes installed extensions, coordinating manifest lookups and filesystem cleanup.
+413
View File
@@ -0,0 +1,413 @@
package extensions
import (
"bytes"
"flag"
"fmt"
"os"
"strconv"
"strings"
"github.com/bishopfox/sliver/client/core"
"github.com/spf13/cobra"
)
// ParseFlagArgumentsToBuffer parses flag-style arguments based on extension manifest
// and converts them to a BOF-compatible binary buffer
func ParseFlagArgumentsToBuffer(_ *cobra.Command, args []string, _ string, ext *ExtCommand) ([]byte, error) {
// Create a flag set and parse the arguments
fs, stringValues, wstringValues, intValues, shortValues, fileValues, err := bofSetupAndParseFlags(args, ext)
if err != nil {
return nil, err
}
// Print debug information about parsed flags
//bofDebugPrintParsedFlags(fs, ext, stringValues, wstringValues, intValues, shortValues, fileValues)
// Initialize the BOF arguments buffer
argsBuffer := core.BOFArgsBuffer{
Buffer: new(bytes.Buffer),
}
// Process arguments and build the buffer
missingRequiredArgs, err := bofProcessArgumentsToBuffer(fs, ext, argsBuffer,
stringValues, wstringValues, intValues, shortValues, fileValues)
if err != nil {
return nil, err
}
// Return error if we have missing required arguments
if len(missingRequiredArgs) > 0 {
return nil, fmt.Errorf("required arguments %s were not provided", strings.Join(missingRequiredArgs, ", "))
}
// Get the final binary buffer
parsedArgs, err := argsBuffer.GetBuffer()
if err != nil {
return nil, fmt.Errorf("failed to get buffer: %v", err)
}
return parsedArgs, nil
}
// bofSetupAndParseFlags creates a flag set, defines expected flags based on the extension manifest,
// and parses the provided arguments
func bofSetupAndParseFlags(args []string, ext *ExtCommand) (*flag.FlagSet,
map[string]*string, map[string]*string, map[string]*int, map[string]*int, map[string]*string, error) {
// Create a new FlagSet
fs := flag.NewFlagSet("sliver-bof", flag.ContinueOnError)
// Maps to store flag value pointers
stringValues := make(map[string]*string)
intValues := make(map[string]*int)
shortValues := make(map[string]*int)
fileValues := make(map[string]*string) // Path to file data
wstringValues := make(map[string]*string)
// Define expected flags based on manifest arguments
for _, arg := range ext.Arguments {
flagName := arg.Name
flagDesc := arg.Desc
switch arg.Type {
case "string":
stringValues[flagName] = fs.String(flagName, "", flagDesc)
case "wstring":
wstringValues[flagName] = fs.String(flagName, "", flagDesc)
case "int", "integer":
intValues[flagName] = fs.Int(flagName, 0, flagDesc)
case "short":
shortValues[flagName] = fs.Int(flagName, 0, flagDesc)
case "file":
fileValues[flagName] = fs.String(flagName, "", flagDesc)
default:
return nil, nil, nil, nil, nil, nil, fmt.Errorf("unsupported argument type: %s", arg.Type)
}
}
// Parse the arguments
if err := fs.Parse(args); err != nil {
return nil, nil, nil, nil, nil, nil, err
}
return fs, stringValues, wstringValues, intValues, shortValues, fileValues, nil
}
// bofProcessArgumentsToBuffer processes each argument and adds its value to the buffer
// Returns a list of missing required arguments and any error encountered
func bofProcessArgumentsToBuffer(fs *flag.FlagSet, ext *ExtCommand, argsBuffer core.BOFArgsBuffer,
stringValues, wstringValues map[string]*string,
intValues, shortValues map[string]*int,
fileValues map[string]*string) ([]string, error) {
missingRequiredArgs := make([]string, 0)
for _, argDef := range ext.Arguments {
var provided bool
var err error
// Process based on argument type
switch argDef.Type {
case "string":
provided, err = bofProcessStringArg(fs, argDef, stringValues, argsBuffer)
case "wstring":
provided, err = bofProcessWStringArg(fs, argDef, wstringValues, argsBuffer)
case "int", "integer":
provided, err = bofProcessIntArg(fs, argDef, intValues, argsBuffer)
case "short":
provided, err = bofProcessShortArg(fs, argDef, shortValues, argsBuffer)
case "file":
provided, err = bofProcessFileArg(fs, argDef, fileValues, argsBuffer)
}
if err != nil {
return nil, err
}
// If argument not provided, handle according to rules
if !provided {
if argDef.Optional {
// Try to apply default or type-appropriate zero value
err = bofApplyDefaultValue(argDef, argsBuffer)
if err != nil {
return nil, err
}
} else {
// Required argument was not provided
missingRequiredArgs = append(missingRequiredArgs, "`"+argDef.Name+"`")
}
}
}
return missingRequiredArgs, nil
}
// bofProcessStringArg processes a string argument
func bofProcessStringArg(fs *flag.FlagSet, argDef *extensionArgument, stringValues map[string]*string,
argsBuffer core.BOFArgsBuffer) (bool, error) {
ptr := stringValues[argDef.Name]
flagWasSet := *ptr != "" && bofFlagWasProvided(fs, argDef.Name)
if flagWasSet {
err := argsBuffer.AddString(*ptr)
if err != nil {
return false, fmt.Errorf("failed to add string argument %s: %v", argDef.Name, err)
}
return true, nil
}
return false, nil
}
// bofProcessWStringArg processes a wide string argument
func bofProcessWStringArg(fs *flag.FlagSet, argDef *extensionArgument, wstringValues map[string]*string,
argsBuffer core.BOFArgsBuffer) (bool, error) {
ptr := wstringValues[argDef.Name]
flagWasSet := *ptr != "" && bofFlagWasProvided(fs, argDef.Name)
if flagWasSet {
err := argsBuffer.AddWString(*ptr)
if err != nil {
return false, fmt.Errorf("failed to add wstring argument %s: %v", argDef.Name, err)
}
return true, nil
}
return false, nil
}
// bofProcessIntArg processes an integer argument
func bofProcessIntArg(fs *flag.FlagSet, argDef *extensionArgument, intValues map[string]*int,
argsBuffer core.BOFArgsBuffer) (bool, error) {
ptr := intValues[argDef.Name]
flagWasSet := bofFlagWasProvided(fs, argDef.Name)
if flagWasSet {
err := argsBuffer.AddInt(uint32(*ptr))
if err != nil {
return false, fmt.Errorf("failed to add int argument %s: %v", argDef.Name, err)
}
return true, nil
}
return false, nil
}
// bofProcessShortArg processes a short integer argument
func bofProcessShortArg(fs *flag.FlagSet, argDef *extensionArgument, shortValues map[string]*int,
argsBuffer core.BOFArgsBuffer) (bool, error) {
ptr := shortValues[argDef.Name]
flagWasSet := bofFlagWasProvided(fs, argDef.Name)
if flagWasSet {
err := argsBuffer.AddShort(uint16(*ptr))
if err != nil {
return false, fmt.Errorf("failed to add short argument %s: %v", argDef.Name, err)
}
return true, nil
}
return false, nil
}
// bofProcessFileArg processes a file argument
func bofProcessFileArg(fs *flag.FlagSet, argDef *extensionArgument, fileValues map[string]*string,
argsBuffer core.BOFArgsBuffer) (bool, error) {
ptr := fileValues[argDef.Name]
flagWasSet := *ptr != "" && bofFlagWasProvided(fs, argDef.Name)
if flagWasSet {
// Validate file exists and read it
data, err := os.ReadFile(*ptr)
if err != nil {
return false, fmt.Errorf("error reading file for argument %s: %v", argDef.Name, err)
}
err = argsBuffer.AddData(data)
if err != nil {
return false, fmt.Errorf("failed to add file data for argument %s: %v", argDef.Name, err)
}
return true, nil
}
return false, nil
}
// bofApplyDefaultValue applies a default value based on the argument definition
func bofApplyDefaultValue(argDef *extensionArgument, argsBuffer core.BOFArgsBuffer) error {
// Try to use default value from manifest if available
if argDef.Default != nil {
switch argDef.Type {
case "string":
// Handle string default - could be string literal or numeric in JSON
defaultVal, ok := argDef.Default.(string)
if !ok {
// Try to convert from other types
defaultVal = fmt.Sprintf("%v", argDef.Default)
}
err := argsBuffer.AddString(defaultVal)
if err != nil {
return fmt.Errorf("failed to add default string: %v", err)
}
fmt.Printf(" -%s:%s (default)\n", argDef.Name, defaultVal)
case "wstring":
// Handle wstring default
defaultVal, ok := argDef.Default.(string)
if !ok {
defaultVal = fmt.Sprintf("%v", argDef.Default)
}
err := argsBuffer.AddWString(defaultVal)
if err != nil {
return fmt.Errorf("failed to add default wstring: %v", err)
}
fmt.Printf(" -%s:%s (default)\n", argDef.Name, defaultVal)
case "int", "integer":
// Handle int default - could be number or string in JSON
var defaultInt uint32
// Try as number first
numVal, ok := argDef.Default.(float64) // JSON unmarshals numbers as float64
if ok {
defaultInt = uint32(numVal)
} else {
// Try as string
strVal, ok := argDef.Default.(string)
if ok {
val, err := strconv.ParseUint(strVal, 10, 32)
if err == nil {
defaultInt = uint32(val)
}
}
}
err := argsBuffer.AddInt(defaultInt)
if err != nil {
return fmt.Errorf("failed to add default int: %v", err)
}
fmt.Printf(" -%s:%d (default)\n", argDef.Name, defaultInt)
case "short":
// Handle short default - could be number or string in JSON
var defaultShort uint16
// Try as number first
numVal, ok := argDef.Default.(float64) // JSON unmarshals numbers as float64
if ok {
defaultShort = uint16(numVal)
} else {
// Try as string
strVal, ok := argDef.Default.(string)
if ok {
val, err := strconv.ParseUint(strVal, 10, 16)
if err == nil {
defaultShort = uint16(val)
}
}
}
err := argsBuffer.AddShort(defaultShort)
if err != nil {
return fmt.Errorf("failed to add default short: %v", err)
}
fmt.Printf(" -%s:%d (default)\n", argDef.Name, defaultShort)
case "file":
// Default for file doesn't really make sense, but handle for completeness
err := argsBuffer.AddData([]byte{})
if err != nil {
return fmt.Errorf("failed to add default file data: %v", err)
}
fmt.Printf(" -%s:<empty> (default)\n", argDef.Name)
}
} else {
// No default specified in manifest, use type-appropriate zero values
switch argDef.Type {
case "string":
err := argsBuffer.AddString("")
if err != nil {
return fmt.Errorf("failed to add default string: %v", err)
}
fmt.Printf(" -%s:<empty> (default)\n", argDef.Name)
case "wstring":
err := argsBuffer.AddWString("")
if err != nil {
return fmt.Errorf("failed to add default wstring: %v", err)
}
fmt.Printf(" -%s:<empty> (default)\n", argDef.Name)
case "int", "integer":
err := argsBuffer.AddInt(0)
if err != nil {
return fmt.Errorf("failed to add default int: %v", err)
}
fmt.Printf(" -%s:0 (default)\n", argDef.Name)
case "short":
err := argsBuffer.AddShort(0)
if err != nil {
return fmt.Errorf("failed to add default short: %v", err)
}
fmt.Printf(" -%s:0 (default)\n", argDef.Name)
case "file":
// Empty data for optional file
err := argsBuffer.AddData([]byte{})
if err != nil {
return fmt.Errorf("failed to add default file data: %v", err)
}
fmt.Printf(" -%s:<empty> (default)\n", argDef.Name)
}
}
return nil
}
// bofDebugPrintParsedFlags prints information about the parsed flags
func bofDebugPrintParsedFlags(fs *flag.FlagSet, ext *ExtCommand,
stringValues map[string]*string,
wstringValues map[string]*string,
intValues map[string]*int,
shortValues map[string]*int,
fileValues map[string]*string) {
fmt.Println("parsed flags:")
for _, arg := range ext.Arguments {
flagName := arg.Name
wasProvided := bofFlagWasProvided(fs, flagName)
if wasProvided {
switch arg.Type {
case "string":
fmt.Printf(" -%s:%s\n", flagName, *stringValues[flagName])
case "wstring":
fmt.Printf(" -%s:%s\n", flagName, *wstringValues[flagName])
case "int", "integer":
fmt.Printf(" -%s:%d\n", flagName, *intValues[flagName])
case "short":
fmt.Printf(" -%s:%d\n", flagName, *shortValues[flagName])
case "file":
fmt.Printf(" -%s:%s\n", flagName, *fileValues[flagName])
}
}
}
}
// bofFlagWasProvided checks if a flag was explicitly set
func bofFlagWasProvided(fs *flag.FlagSet, name string) bool {
provided := false
fs.Visit(func(f *flag.Flag) {
if f.Name == name {
provided = true
}
})
return provided
}
+32 -11
View File
@@ -1,34 +1,28 @@
package extensions
import (
"github.com/bishopfox/sliver/client/command/flags"
"github.com/bishopfox/sliver/client/command/help"
"github.com/bishopfox/sliver/client/command/use"
"github.com/bishopfox/sliver/client/console"
consts "github.com/bishopfox/sliver/client/constants"
"github.com/rsteube/carapace"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
)
// Commands returns the “ command and its subcommands.
// Commands returns the 'extensions' command and its subcommands.
func Commands(con *console.SliverClient) []*cobra.Command {
extensionCmd := &cobra.Command{
Use: consts.ExtensionsStr,
Short: "Manage extensions",
Long: help.GetHelpFor([]string{consts.ExtensionsStr}),
GroupID: consts.ExecutionHelpGroup,
GroupID: consts.GenericHelpGroup,
Run: func(cmd *cobra.Command, _ []string) {
ExtensionsCmd(cmd, con)
},
}
extensionCmd.AddCommand(&cobra.Command{
Use: consts.ListStr,
Short: "List extensions loaded in the current session or beacon",
Long: help.GetHelpFor([]string{consts.ExtensionsStr, consts.ListStr}),
Run: func(cmd *cobra.Command, args []string) {
ExtensionsListCmd(cmd, con, args)
},
})
extensionLoadCmd := &cobra.Command{
Use: consts.LoadStr,
Short: "Temporarily load an extension from a local directory",
@@ -66,3 +60,30 @@ func Commands(con *console.SliverClient) []*cobra.Command {
return []*cobra.Command{extensionCmd}
}
func SliverCommands(con *console.SliverClient) []*cobra.Command {
extensionCmd := &cobra.Command{
Use: consts.ExtensionsStr,
Short: "Manage extensions",
Long: help.GetHelpFor([]string{consts.ExtensionsStr}),
GroupID: consts.InfoHelpGroup,
Annotations: flags.RestrictTargets(consts.SessionCmdsFilter), // restrict to session targets since we cannot `list` "loaded" extensions from beacon mode
}
listCmd := &cobra.Command{
Use: consts.ListStr,
Short: "List extensions loaded in the current session",
Long: help.GetHelpFor([]string{consts.ExtensionsStr, consts.ListStr}),
Run: func(cmd *cobra.Command, args []string) {
ExtensionsListCmd(cmd, con, args)
},
}
flags.Bind("use", false, listCmd, func(f *pflag.FlagSet) {
f.Int64P("timeout", "t", flags.DefaultTimeout, "grpc timeout in seconds")
})
extensionCmd.AddCommand(listCmd)
carapace.Gen(listCmd).PositionalCompletion(use.BeaconAndSessionIDCompleter(con))
return []*cobra.Command{extensionCmd}
}
+48 -3
View File
@@ -22,6 +22,7 @@ import (
"encoding/json"
"fmt"
"os"
"path/filepath"
"strings"
"github.com/bishopfox/sliver/client/assets"
@@ -35,7 +36,7 @@ import (
// ExtensionsCmd - List information about installed extensions.
func ExtensionsCmd(cmd *cobra.Command, con *console.SliverClient) {
if 0 < len(getInstalledManifests()) {
if len(GetAllExtensionManifests()) > 0 {
PrintExtensions(con)
} else {
con.PrintInfof("No extensions installed, use the 'armory' command to automatically install some\n")
@@ -67,8 +68,12 @@ func PrintExtensions(con *console.SliverClient) {
for _, extension := range loadedExtensions {
//for _, extension := range extensionm.ExtCommand {
installed := ""
if _, ok := installedManifests[extension.Manifest.Name]; ok {
installed = "✅"
//if _, ok := installedManifests[extension.Manifest.Name]; ok {
for _, installedManifest := range installedManifests {
if extension.Manifest.RootPath == installedManifest.RootPath {
installed = "✅"
break
}
}
tw.AppendRow(table.Row{
extension.Manifest.Name,
@@ -97,6 +102,9 @@ func extensionPlatforms(extension *ExtCommand) []string {
return keys
}
// getInstalledManifests - Returns a mapping of extension names to their parsed manifest objects.
// Reads all installed extension manifests from disk, ignoring any that cannot be read or parsed.
// The returned manifests have their RootPath set to the directory containing their manifest file.
func getInstalledManifests() map[string]*ExtensionManifest {
manifestPaths := assets.GetInstalledExtensionManifests()
installedManifests := map[string]*ExtensionManifest{}
@@ -110,11 +118,48 @@ func getInstalledManifests() map[string]*ExtensionManifest {
if err != nil {
continue
}
manifest.RootPath = filepath.Dir(manifestPath)
installedManifests[manifest.Name] = manifest
}
return installedManifests
}
// getTemporarilyLoadedManifests returns a map of extension manifests that are currently
// loaded into memory but not permanently installed. The map is keyed by the manifest's
// Name field.
func getTemporarilyLoadedManifests() map[string]*ExtensionManifest {
tempManifests := map[string]*ExtensionManifest{}
for name, manifest := range loadedManifests {
tempManifests[name] = manifest
}
return tempManifests
}
// GetAllExtensionManifests returns a combined list of manifest file paths from
// both installed and temporarily loaded extensions
func GetAllExtensionManifests() []string {
manifestPaths := make(map[string]struct{}) // use map for deduplication
// Add installed manifests
for _, manifest := range getInstalledManifests() {
manifestPath := filepath.Join(manifest.RootPath, ManifestFileName)
manifestPaths[manifestPath] = struct{}{}
}
// Add temporarily loaded manifests
for _, manifest := range getTemporarilyLoadedManifests() {
manifestPath := filepath.Join(manifest.RootPath, ManifestFileName)
manifestPaths[manifestPath] = struct{}{}
}
// Convert to slice
paths := make([]string, 0, len(manifestPaths))
for path := range manifestPaths {
paths = append(paths, path)
}
return paths
}
// ExtensionsCommandNameCompleter - Completer for installed extensions command names.
func ExtensionsCommandNameCompleter(con *console.SliverClient) carapace.Action {
return carapace.ActionCallback(func(c carapace.Context) carapace.Action {
+26 -5
View File
@@ -24,9 +24,9 @@ import (
"path/filepath"
"strings"
"github.com/AlecAivazis/survey/v2"
"github.com/bishopfox/sliver/client/assets"
"github.com/bishopfox/sliver/client/console"
"github.com/bishopfox/sliver/client/forms"
"github.com/bishopfox/sliver/util"
"github.com/spf13/cobra"
)
@@ -43,7 +43,22 @@ func ExtensionsInstallCmd(cmd *cobra.Command, con *console.SliverClient, args []
InstallFromDir(extLocalPath, true, con, strings.HasSuffix(extLocalPath, ".tar.gz"))
}
// Install an extension from a directory
// InstallFromDir installs a Sliver extension from either a local directory or gzipped archive.
// It reads the extension manifest, validates it, and copies all required files to the extensions
// directory. If an extension with the same name already exists, it can optionally prompt for
// overwrite confirmation.
//
// Parameters:
// - extLocalPath: Path to the source directory or gzipped archive containing the extension
// - promptToOverwrite: If true, prompts for confirmation before overwriting existing extension
// - con: Sliver console client for displaying status and error messages
// - isGz: Whether the source is a gzipped archive (true) or directory (false)
//
// The function will return early with error messages printed to console if:
// - The manifest cannot be read or parsed
// - Required directories cannot be created
// - File copy operations fail
// - User declines overwrite when prompted
func InstallFromDir(extLocalPath string, promptToOverwrite bool, con *console.SliverClient, isGz bool) {
var manifestData []byte
var err error
@@ -64,14 +79,20 @@ func InstallFromDir(extLocalPath string, promptToOverwrite bool, con *console.Sl
return
}
// Use package name if available, otherwise use extension name
// (Note, for v1 manifests this will actually be command_name)
packageID := manifestF.Name
if manifestF.PackageName != "" {
packageID = manifestF.PackageName
}
//create repo path
minstallPath := filepath.Join(assets.GetExtensionsDir(), filepath.Base(manifestF.Name))
minstallPath := filepath.Join(assets.GetExtensionsDir(), filepath.Base(packageID))
if _, err := os.Stat(minstallPath); !os.IsNotExist(err) {
if promptToOverwrite {
con.PrintInfof("Extension '%s' already exists", manifestF.Name)
confirm := false
prompt := &survey.Confirm{Message: "Overwrite current install?"}
survey.AskOne(prompt, &confirm)
_ = forms.Confirm("Overwrite current install?", &confirm)
if !confirm {
return
}
+106 -5
View File
@@ -20,12 +20,111 @@ package extensions
import (
"context"
"crypto/sha256"
"encoding/hex"
"os"
"path/filepath"
"slices"
"github.com/bishopfox/sliver/client/command/settings"
"github.com/bishopfox/sliver/client/console"
"github.com/bishopfox/sliver/protobuf/sliverpb"
"github.com/jedib0t/go-pretty/v6/table"
"github.com/spf13/cobra"
)
// ExtensionMatch holds the details of a matched extension
type ExtensionMatch struct {
CommandName string
Hash string
BinPath string
}
// FindExtensionMatches searches through loaded extensions for matching hashes
// Returns a map of hash to ExtensionMatch (match will be nil if hash wasn't found)
func FindExtensionMatches(targetHashes []string) map[string]*ExtensionMatch {
results := make(map[string]*ExtensionMatch)
pathCache := make(map[string]*ExtensionMatch)
// Initialize results map with all target hashes
for _, hash := range targetHashes {
results[hash] = nil
}
// Search for matches
for _, extCmd := range loadedExtensions {
if extCmd == nil || len(extCmd.Files) == 0 {
continue
}
for _, file := range extCmd.Files {
fullPath := filepath.Join(extCmd.Manifest.RootPath, file.Path)
// Check cache first
var match *ExtensionMatch
if cached, exists := pathCache[fullPath]; exists {
match = cached
} else {
// Calculate hash if not cached
fileData, err := os.ReadFile(fullPath)
if err != nil {
continue
}
hashBytes := sha256.Sum256(fileData)
fileHash := hex.EncodeToString(hashBytes[:])
match = &ExtensionMatch{
CommandName: extCmd.CommandName,
Hash: fileHash,
BinPath: fullPath,
}
pathCache[fullPath] = match
}
if slices.Contains(targetHashes, match.Hash) {
results[match.Hash] = match
}
}
}
return results
}
// PrintExtensionMatches prints the extension matches in a formatted table
func PrintExtensionMatches(matches map[string]*ExtensionMatch, con *console.SliverClient) {
tw := table.NewWriter()
tw.SetStyle(settings.GetTableStyle(con))
tw.AppendHeader(table.Row{
"Command Name",
"Sha256 Hash",
"Bin Path",
})
tw.SortBy([]table.SortBy{
{Name: "Command Name", Mode: table.Asc},
})
for hash, match := range matches {
if match != nil {
tw.AppendRow(table.Row{
match.CommandName,
hash,
match.BinPath,
})
} else {
tw.AppendRow(table.Row{
"",
hash,
"",
})
}
}
con.Println(tw.Render())
}
// ExtensionsListCmd - List all extension loaded on the active session/beacon.
func ExtensionsListCmd(cmd *cobra.Command, con *console.SliverClient, args []string) {
session := con.ActiveTarget.GetSessionInteractive()
@@ -45,10 +144,12 @@ func ExtensionsListCmd(cmd *cobra.Command, con *console.SliverClient, args []str
con.PrintErrorf("%s\n", extList.Response.Err)
return
}
if len(extList.Names) > 0 {
con.PrintInfof("Loaded extensions:\n")
for _, ext := range extList.Names {
con.Printf("- %s\n", ext)
}
if len(extList.Names) == 0 {
return
}
con.PrintInfof("Loaded extensions:\n\n")
matches := FindExtensionMatches(extList.Names)
PrintExtensionMatches(matches, con)
}
+50 -25
View File
@@ -33,12 +33,12 @@ import (
"strconv"
"strings"
"github.com/AlecAivazis/survey/v2"
"github.com/bishopfox/sliver/client/assets"
"github.com/bishopfox/sliver/client/command/help"
"github.com/bishopfox/sliver/client/console"
consts "github.com/bishopfox/sliver/client/constants"
"github.com/bishopfox/sliver/client/core"
"github.com/bishopfox/sliver/client/forms"
"github.com/bishopfox/sliver/client/packages"
"github.com/bishopfox/sliver/protobuf/clientpb"
"github.com/bishopfox/sliver/protobuf/sliverpb"
@@ -80,6 +80,7 @@ type ExtensionManifest_ struct {
type ExtensionManifest struct {
Name string `json:"name"`
PackageName string `json:"package_name"`
Version string `json:"version"`
ExtensionAuthor string `json:"extension_author"`
OriginalAuthor string `json:"original_author"`
@@ -115,17 +116,24 @@ type extensionFile struct {
}
type extensionArgument struct {
Name string `json:"name"`
Type string `json:"type"`
Desc string `json:"desc"`
Optional bool `json:"optional"`
Name string `json:"name"`
Type string `json:"type"`
Desc string `json:"desc"`
Optional bool `json:"optional"`
Default interface{} `json:"default,omitempty"`
}
func (e *ExtCommand) getFileForTarget(targetOS string, targetArch string) (string, error) {
filePath := ""
for _, extFile := range e.Files {
if targetOS == extFile.OS && targetArch == extFile.Arch {
filePath = path.Join(assets.GetExtensionsDir(), e.Manifest.Name, extFile.Path)
if e.Manifest.RootPath != "" {
// Use RootPath for temporarily loaded extensions
filePath = path.Join(e.Manifest.RootPath, extFile.Path)
} else {
// Fall back to extensions dir for installed extensions
filePath = path.Join(assets.GetExtensionsDir(), e.Manifest.Name, extFile.Path)
}
break
}
}
@@ -140,10 +148,19 @@ func (e *ExtCommand) getFileForTarget(targetOS string, targetArch string) (strin
return filePath, nil
}
// ExtensionLoadCmd - Load extension command.
// ExtensionLoadCmd - Temporarily installs an extension from a local directory into the client.
// The extension must contain a valid manifest file. If commands from the extension
// already exist, the user will be prompted to overwrite them.
func ExtensionLoadCmd(cmd *cobra.Command, con *console.SliverClient, args []string) {
dirPath := args[0]
// dirPath := ctx.Args.String("dir-path")
// Add directory check
fileInfo, err := os.Stat(dirPath)
if err != nil || !fileInfo.IsDir() {
con.PrintErrorf("Path is not a directory: %s\n", dirPath)
return
}
manifest, err := LoadExtensionManifest(filepath.Join(dirPath, ManifestFileName))
if err != nil {
return
@@ -154,8 +171,7 @@ func ExtensionLoadCmd(cmd *cobra.Command, con *console.SliverClient, args []stri
if CmdExists(extCmd.CommandName, sliverMenu.Command) {
con.PrintErrorf("%s command already exists\n", extCmd.CommandName)
confirm := false
prompt := &survey.Confirm{Message: "Overwrite current command?"}
survey.AskOne(prompt, &confirm)
_ = forms.Confirm("Overwrite current command?", &confirm)
if !confirm {
return
}
@@ -165,7 +181,11 @@ func ExtensionLoadCmd(cmd *cobra.Command, con *console.SliverClient, args []stri
}
}
// LoadExtensionManifest - Parse extension files.
// LoadExtensionManifest loads and parses an extension manifest file from the given path.
// It registers each command defined in the manifest into the loadedExtensions map
// and registers the complete manifest into loadedManifests. A single manifest may
// contain multiple extension commands. The manifest's RootPath is set to its containing
// directory. Returns the parsed manifest and any errors encountered.
func LoadExtensionManifest(manifestPath string) (*ExtensionManifest, error) {
data, err := os.ReadFile(manifestPath)
if err != nil {
@@ -279,15 +299,20 @@ func validManifest(manifest *ExtensionManifest) error {
return nil
}
// ExtensionRegisterCommand - Register a new extension command
// ExtensionRegisterCommand adds an extension command to the cobra command system.
// It validates the extension's arguments, updates the loadedExtensions map, and
// creates a cobra.Command with proper usage text, help documentation, and argument
// handling. The command is added as a subcommand to the provided parent cobra.Command.
// Arguments are displayed in the help text as uppercase, with optional args in square
// brackets. The help text includes sections for command usage, description, and detailed
// argument specifications.
func ExtensionRegisterCommand(extCmd *ExtCommand, cmd *cobra.Command, con *console.SliverClient) {
if errInvalidArgs := checkExtensionArgs(extCmd); errInvalidArgs != nil {
con.PrintErrorf(errInvalidArgs.Error())
con.PrintErrorf("%s", errInvalidArgs.Error())
return
}
loadedExtensions[extCmd.CommandName] = extCmd
//helpMsg := extCmd.Help
usage := strings.Builder{}
usage.WriteString(extCmd.CommandName)
@@ -339,9 +364,9 @@ func ExtensionRegisterCommand(extCmd *ExtCommand, cmd *cobra.Command, con *conso
// Command
extensionCmd := &cobra.Command{
Use: usage.String(), //extCmd.CommandName,
//Short: helpMsg.String(), doesn't appear to be used?
Long: help.FormatHelpTmpl(longHelp.String()),
Use: usage.String(),
Short: extCmd.Help,
Long: help.FormatHelpTmpl(longHelp.String()),
Run: func(cmd *cobra.Command, args []string) {
runExtensionCmd(cmd, con, args)
},
@@ -559,11 +584,11 @@ func runExtensionCmd(cmd *cobra.Command, con *console.SliverClient, args []strin
extName = ext.DependsOn
entryPoint = loadedExtensions[extName].Entrypoint // should exist at this point
} else {
// Regular DLL
extensionArgs, err = getExtArgs(cmd, args, binPath, ext)
if err != nil {
con.PrintErrorf("ext args error: %s\n", err)
return
// Regular DLL - Just join the arguments with spaces
if len(args) > 0 {
extensionArgs = []byte(strings.Join(args, " "))
} else {
extensionArgs = []byte{}
}
extName = ext.CommandName
entryPoint = ext.Entrypoint
@@ -659,7 +684,7 @@ func PrintExtOutput(extName string, commandName string, outputSchema *packages.O
}
}
if callExtension.Response != nil && callExtension.Response.Err != "" {
con.PrintErrorf(callExtension.Response.Err)
con.PrintErrorf("%s", callExtension.Response.Err)
return
}
}
@@ -771,7 +796,7 @@ func getBOFArgs(cmd *cobra.Command, args []string, binPath string, ext *ExtComma
if err != nil {
return nil, err
}
parsedArgs, err := getExtArgs(cmd, args, binPath, ext)
parsedArgs, err := ParseFlagArgumentsToBuffer(cmd, args, binPath, ext)
if err != nil {
return nil, err
}
@@ -829,7 +854,7 @@ func makeExtensionArgCompleter(extCmd *ExtCommand, _ *cobra.Command, comps *cara
usage += " (optional)"
}
actions = append(actions, action.Usage(usage))
actions = append(actions, action.Usage("%s", usage))
}
comps.PositionalCompletion(actions...)
+28 -6
View File
@@ -23,10 +23,11 @@ import (
"fmt"
"os"
"path/filepath"
"strings"
"github.com/AlecAivazis/survey/v2"
"github.com/bishopfox/sliver/client/assets"
"github.com/bishopfox/sliver/client/console"
"github.com/bishopfox/sliver/client/forms"
"github.com/bishopfox/sliver/util"
"github.com/spf13/cobra"
)
@@ -39,8 +40,7 @@ func ExtensionsRemoveCmd(cmd *cobra.Command, con *console.SliverClient, args []s
return
}
confirm := false
prompt := &survey.Confirm{Message: fmt.Sprintf("Remove '%s' extension?", name)}
survey.AskOne(prompt, &confirm)
_ = forms.Confirm(fmt.Sprintf("Remove '%s' extension?", name), &confirm)
if !confirm {
return
}
@@ -86,12 +86,34 @@ func RemoveExtensionByManifestName(manifestName string, con *console.SliverClien
return false, errors.New("command name is required")
}
if man, ok := loadedManifests[manifestName]; ok {
//foudn the manifest
//delet it
extPath := filepath.Join(assets.GetExtensionsDir(), filepath.Base(manifestName))
// Found the manifest
var extPath string
if man.RootPath != "" {
// Use RootPath for temporarily loaded extensions
extPath = man.RootPath
} else {
// Fall back to extensions dir for installed extensions
extPath = filepath.Join(assets.GetExtensionsDir(), filepath.Base(manifestName))
}
if _, err := os.Stat(extPath); os.IsNotExist(err) {
return true, nil
}
// If path is outside extensions directory, prompt for confirmation
if !strings.HasPrefix(extPath, assets.GetExtensionsDir()) {
confirm := false
_ = forms.Confirm(fmt.Sprintf("Remove '%s' extension directory from filesystem?", manifestName), &confirm)
if !confirm {
// Skip the forceRemoveAll but continue with the rest
delete(loadedManifests, manifestName)
for _, cmd := range man.ExtCommand {
delete(loadedExtensions, cmd.CommandName)
}
return true, nil
}
}
forceRemoveAll(extPath)
delete(loadedManifests, manifestName)
for _, cmd := range man.ExtCommand {
+27 -3
View File
@@ -1,4 +1,28 @@
Filesystem
==========
# client/command/filesystem
This package implements file system commands such as `ls`, `cd`, `rm`, `download`, `upload`, etc.
## Overview
Implements the 'filesystem' command group for the Sliver client console. Handlers map Cobra invocations to filesystem workflows such as CAT, CD, chmod, and chown.
## Go Files
- `cat.go` – Downloads remote files and prints contents locally with optional ANSI colorization.
- `cd.go` – Changes the working directory of the active session or beacon.
- `chmod.go` – Adjusts remote file permissions via RPC for Unix-like targets.
- `chown.go` – Alters remote file ownership metadata where supported.
- `chtimes.go` – Updates remote file access and modification timestamps.
- `commands.go` – Assembles the filesystem command group and wires each file operation subcommand.
- `cp.go` – Copies files on the remote target, handling overwrite prompts and path validation.
- `download.go` – Retrieves files from the target and writes them to the local loot directory.
- `grep.go` – Runs server-side grep equivalents with pattern, highlight, and streaming options.
- `head.go` – Streams the first bytes or lines of a remote file.
- `ls.go` – Lists directory contents with filtering, sorting, and long-format support.
- `memfiles-add.go` – Uploads file data into in-memory implants for later retrieval.
- `memfiles-list.go` – Enumerates in-memory file entries stored on the implant.
- `memfiles-rm.go` – Removes staged in-memory files from the implant cache.
- `mkdir.go` – Creates directories on the remote system, with recursive creation if requested.
- `mount.go` – Mounts remote filesystem paths for live browsing through the client.
- `mv.go` – Moves or renames remote files and directories.
- `pwd.go` – Prints the current working directory of the active target.
- `rm.go` – Deletes remote files or directories with optional recursive behavior.
- `upload.go` – Transfers local files to the target and sets desired permissions.
+2 -3
View File
@@ -30,12 +30,12 @@ import (
"github.com/bishopfox/sliver/client/command/loot"
"github.com/bishopfox/sliver/client/console"
"github.com/bishopfox/sliver/client/forms"
"github.com/bishopfox/sliver/protobuf/clientpb"
"github.com/bishopfox/sliver/protobuf/sliverpb"
"github.com/bishopfox/sliver/util/encoders"
"github.com/spf13/cobra"
"google.golang.org/protobuf/proto"
"gopkg.in/AlecAivazis/survey.v1"
)
func DownloadCmd(cmd *cobra.Command, con *console.SliverClient, args []string) {
@@ -189,8 +189,7 @@ func HandleDownloadResponse(download *sliverpb.Download, cmd *cobra.Command, arg
if _, err := os.Stat(dst); err == nil {
overwrite := false
prompt := &survey.Confirm{Message: "Overwrite local file?"}
survey.AskOne(prompt, &overwrite, nil)
_ = forms.Confirm("Overwrite local file?", &overwrite)
if !overwrite {
return
}
+9
View File
@@ -0,0 +1,9 @@
# client/command/flags
## Overview
Implements the 'flags' command group for the Sliver client console.
## Go Files
- `flags.go` – Provides shared helpers for binding Cobra flag sets, target filters, and carapace completions to commands.
+22 -3
View File
@@ -1,5 +1,24 @@
Generate
========
# client/command/generate
Implements command related to implant generation such as `generate`, `regenerate`, `profiles`, etc.
## Overview
Implements the 'generate' command group for the Sliver client console. Handlers map Cobra invocations to generate workflows such as canaries, generate beacon, generate info, and implants RM.
## Go Files
- `canaries.go` – Lists DNS canaries, filters burned entries, and prints status tables.
- `commands.go` – Defines the generate command hierarchy spanning implant, profile, and canary tooling.
- `generate-beacon.go` – Builds staged beacons from profile/flag inputs and triggers compilation via RPC.
- `generate-info.go` – Displays build configuration details for a generated implant artifact.
- `generate.go` – Orchestrates implant compilation pipelines, parsing C2 flags and selecting targets/builders.
- `helpers.go` – Supplies completions, helper lookups, and binary retrieval utilities used across generate commands.
- `implants-rm.go` – Deletes stored implant builds from the server catalog.
- `implants-stage.go` – Uploads generated implants into staging slots for later deployment.
- `implants.go` – Lists implant builds, filters them, and resolves selected build metadata.
- `profiles-generate.go` – Generates new implant profiles from templates and selected options.
- `profiles-new.go` – Creates empty implant profiles populated with default settings.
- `profiles-rm.go` – Removes saved implant profiles and confirms deletion state.
- `profiles-stage.go` – Stages implant profiles to facilitate rapid build operations.
- `profiles.go` – Lists profiles, prints detailed info, and resolves profile selections for other commands.
- `regenerate.go` – Rebuilds implants from existing configuration IDs without re-specifying flags.
- `traffic-encoders.go` – Manages generation of HTTP/DNS traffic encoder assets for implants.
+4 -1
View File
@@ -143,6 +143,8 @@ func Commands(con *console.SliverClient) []*cobra.Command {
flags.Bind("profiles", false, profilesGenerateCmd, func(f *pflag.FlagSet) {
f.StringP("save", "s", "", "directory/file to the binary to")
f.BoolP("disable-sgn", "G", false, "disable shikata ga nai shellcode encoder")
f.StringP("name", "n", "", "Implant name")
})
flags.BindFlagCompletions(profilesGenerateCmd, func(comp *carapace.ActionMap) {
(*comp)["save"] = carapace.ActionFiles().Tag("directory/file to save implant")
@@ -307,7 +309,7 @@ func coreImplantFlags(name string, cmd *cobra.Command) {
f.BoolP("evasion", "e", false, "enable evasion features (e.g. overwrite user space hooks)")
f.BoolP("skip-symbols", "l", false, "skip symbol obfuscation")
f.BoolP("disable-sgn", "G", false, "disable shikata ga nai shellcode encoder")
f.StringP("exports", "v", "StartW,VoidFunc,DllInstall,DllRegisterServer,DllUnregisterServer", "comma separated list of exports to include in the binary")
f.StringP("canary", "c", "", "canary domain(s)")
// C2 channels
@@ -353,6 +355,7 @@ func coreImplantFlagCompletions(cmd *cobra.Command, con *console.SliverClient) {
(*comp)["format"] = FormatCompleter()
(*comp)["save"] = carapace.ActionFiles().Tag("directory/file to save implant")
(*comp)["traffic-encoders"] = TrafficEncodersCompleter(con).UniqueList(",")
(*comp)["c2profile"] = HTTPC2Completer(con)
})
}
+115
View File
@@ -1,11 +1,15 @@
package generate
import (
"errors"
"fmt"
"os"
"strconv"
"strings"
"time"
"github.com/bishopfox/sliver/client/console"
"github.com/bishopfox/sliver/client/forms"
"github.com/bishopfox/sliver/protobuf/clientpb"
"github.com/spf13/cobra"
)
@@ -17,6 +21,21 @@ var (
// GenerateBeaconCmd - The main command used to generate implant binaries
func GenerateBeaconCmd(cmd *cobra.Command, con *console.SliverClient, args []string) {
if shouldRunGenerateBeaconForm(cmd, con, args) {
result, err := forms.GenerateBeaconForm()
if err != nil {
if errors.Is(err, forms.ErrUserAborted) {
return
}
con.PrintErrorf("Generate beacon form failed: %s\n", err)
return
}
if err := applyGenerateBeaconForm(cmd, result); err != nil {
con.PrintErrorf("Failed to apply generate beacon form values: %s\n", err)
return
}
}
name, config := parseCompileFlags(cmd, con)
if config == nil {
return
@@ -67,3 +86,99 @@ func parseBeaconFlags(cmd *cobra.Command, config *clientpb.ImplantConfig) error
config.BeaconJitter = int64(time.Duration(beaconJitter) * time.Second)
return nil
}
func shouldRunGenerateBeaconForm(cmd *cobra.Command, con *console.SliverClient, args []string) bool {
if con == nil || con.IsCLI {
return false
}
if len(args) != 0 {
return false
}
return cmd.Flags().NFlag() == 0
}
func applyGenerateBeaconForm(cmd *cobra.Command, result *forms.GenerateBeaconFormResult) error {
if err := cmd.Flags().Set("os", result.OS); err != nil {
return err
}
if err := cmd.Flags().Set("arch", result.Arch); err != nil {
return err
}
if err := cmd.Flags().Set("format", result.Format); err != nil {
return err
}
name := strings.TrimSpace(result.Name)
if name != "" {
if err := cmd.Flags().Set("name", name); err != nil {
return err
}
}
save := strings.TrimSpace(result.Save)
if save != "" {
if err := cmd.Flags().Set("save", save); err != nil {
return err
}
}
c2Value := strings.TrimSpace(result.C2Value)
switch result.C2Type {
case "mtls":
if err := cmd.Flags().Set("mtls", c2Value); err != nil {
return err
}
case "wg":
if err := cmd.Flags().Set("wg", c2Value); err != nil {
return err
}
case "http":
if err := cmd.Flags().Set("http", c2Value); err != nil {
return err
}
case "dns":
if err := cmd.Flags().Set("dns", c2Value); err != nil {
return err
}
case "named-pipe":
if err := cmd.Flags().Set("named-pipe", c2Value); err != nil {
return err
}
case "tcp-pivot":
if err := cmd.Flags().Set("tcp-pivot", c2Value); err != nil {
return err
}
default:
return errors.New("unsupported C2 transport selection")
}
if err := setOptionalInt64Flag(cmd, "days", result.Days); err != nil {
return err
}
if err := setOptionalInt64Flag(cmd, "hours", result.Hours); err != nil {
return err
}
if err := setOptionalInt64Flag(cmd, "minutes", result.Minutes); err != nil {
return err
}
if err := setOptionalInt64Flag(cmd, "seconds", result.Seconds); err != nil {
return err
}
if err := setOptionalInt64Flag(cmd, "jitter", result.Jitter); err != nil {
return err
}
return nil
}
func setOptionalInt64Flag(cmd *cobra.Command, name, value string) error {
trimmed := strings.TrimSpace(value)
if trimmed == "" {
return nil
}
parsed, err := strconv.ParseInt(trimmed, 10, 64)
if err != nil {
return err
}
if parsed < 0 {
return fmt.Errorf("%s must be 0 or greater", name)
}
return cmd.Flags().Set(name, strconv.FormatInt(parsed, 10))
}
+86 -21
View File
@@ -32,9 +32,9 @@ import (
"strings"
"time"
"github.com/AlecAivazis/survey/v2"
"github.com/bishopfox/sliver/client/console"
consts "github.com/bishopfox/sliver/client/constants"
"github.com/bishopfox/sliver/client/forms"
"github.com/bishopfox/sliver/client/spin"
"github.com/bishopfox/sliver/protobuf/clientpb"
"github.com/bishopfox/sliver/protobuf/commonpb"
@@ -89,6 +89,21 @@ var (
// GenerateCmd - The main command used to generate implant binaries
func GenerateCmd(cmd *cobra.Command, con *console.SliverClient, args []string) {
if shouldRunGenerateForm(cmd, con, args) {
result, err := forms.GenerateForm()
if err != nil {
if errors.Is(err, forms.ErrUserAborted) {
return
}
con.PrintErrorf("Generate form failed: %s\n", err)
return
}
if err := applyGenerateForm(cmd, result); err != nil {
con.PrintErrorf("Failed to apply generate form values: %s\n", err)
return
}
}
name, config := parseCompileFlags(cmd, con)
if config == nil {
return
@@ -117,6 +132,58 @@ func GenerateCmd(cmd *cobra.Command, con *console.SliverClient, args []string) {
}
}
func shouldRunGenerateForm(cmd *cobra.Command, con *console.SliverClient, args []string) bool {
if con == nil || con.IsCLI {
return false
}
if len(args) != 0 {
return false
}
return cmd.Flags().NFlag() == 0
}
func applyGenerateForm(cmd *cobra.Command, result *forms.GenerateFormResult) error {
if err := cmd.Flags().Set("os", result.OS); err != nil {
return err
}
if err := cmd.Flags().Set("arch", result.Arch); err != nil {
return err
}
if err := cmd.Flags().Set("format", result.Format); err != nil {
return err
}
name := strings.TrimSpace(result.Name)
if name != "" {
if err := cmd.Flags().Set("name", name); err != nil {
return err
}
}
save := strings.TrimSpace(result.Save)
if save != "" {
if err := cmd.Flags().Set("save", save); err != nil {
return err
}
}
c2Value := strings.TrimSpace(result.C2Value)
switch result.C2Type {
case "mtls":
return cmd.Flags().Set("mtls", c2Value)
case "wg":
return cmd.Flags().Set("wg", c2Value)
case "http":
return cmd.Flags().Set("http", c2Value)
case "dns":
return cmd.Flags().Set("dns", c2Value)
case "named-pipe":
return cmd.Flags().Set("named-pipe", c2Value)
case "tcp-pivot":
return cmd.Flags().Set("tcp-pivot", c2Value)
default:
return errors.New("unsupported C2 transport selection")
}
}
func expandPath(path string) string {
// unless path starts with ~
if len(path) == 0 || path[0] != 126 {
@@ -134,13 +201,10 @@ func saveLocation(save, DefaultName string, con *console.SliverClient) (string,
save = expandPath(save)
fi, err := os.Stat(save)
if os.IsNotExist(err) {
con.Printf("%s does not exist\n", save)
if strings.HasSuffix(save, "/") {
con.Printf("%s is dir\n", save)
os.MkdirAll(save, 0o700)
saveTo, _ = filepath.Abs(filepath.Join(saveTo, DefaultName))
} else {
con.Printf("%s is not dir\n", save)
saveDir := filepath.Dir(save)
_, err := os.Stat(saveTo)
if os.IsNotExist(err) {
@@ -152,10 +216,8 @@ func saveLocation(save, DefaultName string, con *console.SliverClient) (string,
if fi.IsDir() {
saveTo, _ = filepath.Abs(filepath.Join(save, DefaultName))
} else {
con.PrintInfof("%s is not dir\n", save)
prompt := &survey.Confirm{Message: "Overwrite existing file?"}
var confirm bool
survey.AskOne(prompt, &confirm)
_ = forms.Confirm("Overwrite existing file?", &confirm)
if !confirm {
return "", errors.New("file already exists")
}
@@ -290,6 +352,15 @@ func parseCompileFlags(cmd *cobra.Command, con *console.SliverClient) (string, *
isShellcode := false
sgnEnabled := false
var exports []string
exportsArg, _ := cmd.Flags().GetString("exports")
if exportsArg == "" {
con.PrintErrorf("Shared libraries need at least one export\n")
return "", nil
} else {
exports = strings.Split(exportsArg, ",")
}
format, _ := cmd.Flags().GetString("format")
runAtLoad := false
var configFormat clientpb.OutputFormat
@@ -364,6 +435,8 @@ func parseCompileFlags(cmd *cobra.Command, con *console.SliverClient) (string, *
c2Profile = consts.DefaultC2Profile
}
// exports if its a shared library
config := &clientpb.ImplantConfig{
GOOS: targetOS,
GOARCH: targetArch,
@@ -395,6 +468,7 @@ func parseCompileFlags(cmd *cobra.Command, con *console.SliverClient) (string, *
IsSharedLib: isSharedLib,
IsService: isService,
IsShellcode: isShellcode,
Exports: exports,
RunAtLoad: runAtLoad,
NetGoEnabled: netGo,
@@ -454,9 +528,8 @@ func getTargets(targetOS string, targetArch string, con *console.SliverClient) (
console.Bold, target, console.Normal,
)
con.Printf("⚠️ Generic implants do not support all commands/features.\n")
prompt := &survey.Confirm{Message: "Attempt to build generic implant?"}
var confirm bool
survey.AskOne(prompt, &confirm)
_ = forms.Confirm("Attempt to build generic implant?", &confirm)
if !confirm {
return "", ""
}
@@ -564,7 +637,7 @@ func hasValidC2AdvancedOptions(options url.Values) (bool, error) {
if testValue != "wininet" {
return false, fmt.Errorf("C2 option \"driver\" must be empty for the default driver or \"wininet\" for the wininet driver (Windows only)")
}
case "force-http", "disable-accept-header", "disable-upgrade-header", "ask-proxy-creds", "force-base32":
case "force-http", "disable-accept-header", "disable-upgrade-header", "ask-proxy-creds":
if testValue != "true" && testValue != "false" {
return false, fmt.Errorf("C2 option \"%s\" must be a boolean value: true or false", key)
}
@@ -726,11 +799,8 @@ func ParseNamedPipec2(args string) ([]*clientpb.ImplantC2, error) {
}
if !strings.HasPrefix(uri.Path, "/pipe/") {
prompt := &survey.Confirm{
Message: fmt.Sprintf("Named pipe '%s' is missing the 'pipe' path prefix\nContinue anyways?", uri),
}
var confirm bool
survey.AskOne(prompt, &confirm)
_ = forms.Confirm(fmt.Sprintf("Named pipe '%s' is missing the 'pipe' path prefix\nContinue anyways?", uri), &confirm)
if !confirm {
return nil, fmt.Errorf("invalid namedpipe path: %s", uri.Path)
}
@@ -1037,8 +1107,7 @@ func warnMissingCrossCompiler(format clientpb.OutputFormat, targetOS string, tar
con.PrintWarnf("For more information please read %s\n", crossCompilerInfoURL)
confirm := false
prompt := &survey.Confirm{Message: "Try to compile anyways (will likely fail)?"}
survey.AskOne(prompt, &confirm, nil)
_ = forms.Confirm("Try to compile anyways (will likely fail)?", &confirm)
return confirm
}
@@ -1074,11 +1143,7 @@ func selectExternalBuilder(builders []*clientpb.Builder, _ *console.SliverClient
choices = append(choices, builder.Name)
}
choice := ""
prompt := &survey.Select{
Message: "Select an external builder:",
Options: choices,
}
survey.AskOne(prompt, &choice, nil)
_ = forms.Select("Select an external builder:", choices, &choice)
for _, builder := range builders {
if builder.Name == choice {
return builder, nil
+2 -3
View File
@@ -4,8 +4,8 @@ import (
"context"
"fmt"
"github.com/AlecAivazis/survey/v2"
"github.com/bishopfox/sliver/client/console"
"github.com/bishopfox/sliver/client/forms"
"github.com/bishopfox/sliver/protobuf/clientpb"
"github.com/spf13/cobra"
)
@@ -24,8 +24,7 @@ func ImplantsRmCmd(cmd *cobra.Command, con *console.SliverClient, args []string)
return
}
confirm := false
prompt := &survey.Confirm{Message: fmt.Sprintf("Remove '%s' build?", name)}
survey.AskOne(prompt, &confirm)
_ = forms.Confirm(fmt.Sprintf("Remove '%s' build?", name), &confirm)
if !confirm {
return
}
+2 -6
View File
@@ -21,10 +21,10 @@ package generate
import (
"context"
"github.com/AlecAivazis/survey/v2"
"github.com/spf13/cobra"
"github.com/bishopfox/sliver/client/console"
"github.com/bishopfox/sliver/client/forms"
"github.com/bishopfox/sliver/protobuf/clientpb"
"github.com/bishopfox/sliver/protobuf/commonpb"
)
@@ -42,12 +42,8 @@ func ImplantsStageCmd(cmd *cobra.Command, con *console.SliverClient, args []stri
options = append(options, name)
}
prompt := &survey.MultiSelect{
Message: "Select sessions and beacons to expose:",
Options: options,
}
selected := []string{}
survey.AskOne(prompt, &selected)
_ = forms.MultiSelect("Select sessions and beacons to expose:", options, &selected)
_, err = con.Rpc.StageImplantBuild(context.Background(), &clientpb.ImplantStageReq{Build: selected})
if err != nil {
+3 -1
View File
@@ -36,6 +36,8 @@ func ProfilesGenerateCmd(cmd *cobra.Command, con *console.SliverClient, args []s
con.PrintErrorf("No profile name specified\n")
return
}
implantName, _ := cmd.Flags().GetString("name")
save, _ := cmd.Flags().GetString("save")
if save == "" {
save, _ = os.Getwd()
@@ -46,7 +48,7 @@ func ProfilesGenerateCmd(cmd *cobra.Command, con *console.SliverClient, args []s
if SGNDisabled, _ := cmd.Flags().GetBool("disable-sgn"); SGNDisabled {
profile.Config.SGNEnabled = !SGNDisabled
}
_, err := compile(name, profile.Config, save, con)
_, err := compile(implantName, profile.Config, save, con)
if err != nil {
return
}
+183 -2
View File
@@ -19,8 +19,11 @@ package generate
*/
import (
"context"
"errors"
"strings"
"github.com/bishopfox/sliver/client/console"
"github.com/bishopfox/sliver/client/forms"
"github.com/bishopfox/sliver/protobuf/clientpb"
"github.com/spf13/cobra"
)
@@ -28,7 +31,22 @@ import (
// ProfilesNewCmd - Create a new implant profile.
func ProfilesNewCmd(cmd *cobra.Command, con *console.SliverClient, args []string) {
var name string
if len(args) > 0 {
if shouldRunGenerateProfilesNewForm(cmd, con, args) {
result, err := forms.GenerateProfilesNewForm()
if err != nil {
if errors.Is(err, forms.ErrUserAborted) {
return
}
con.PrintErrorf("Profiles new form failed: %s\n", err)
return
}
profileName, err := applyGenerateProfilesNewForm(cmd, result)
if err != nil {
con.PrintErrorf("Failed to apply profiles new form values: %s\n", err)
return
}
name = profileName
} else if len(args) > 0 {
name = args[0]
}
// name := ctx.Args.String("name")
@@ -51,7 +69,22 @@ func ProfilesNewCmd(cmd *cobra.Command, con *console.SliverClient, args []string
// ProfilesNewBeaconCmd - Create a new beacon profile.
func ProfilesNewBeaconCmd(cmd *cobra.Command, con *console.SliverClient, args []string) {
var name string
if len(args) > 0 {
if shouldRunGenerateProfilesNewBeaconForm(cmd, con, args) {
result, err := forms.GenerateProfilesNewBeaconForm()
if err != nil {
if errors.Is(err, forms.ErrUserAborted) {
return
}
con.PrintErrorf("Profiles new beacon form failed: %s\n", err)
return
}
profileName, err := applyGenerateProfilesNewBeaconForm(cmd, result)
if err != nil {
con.PrintErrorf("Failed to apply profiles new beacon form values: %s\n", err)
return
}
name = profileName
} else if len(args) > 0 {
name = args[0]
}
// name := ctx.Args.String("name")
@@ -80,3 +113,151 @@ func ProfilesNewBeaconCmd(cmd *cobra.Command, con *console.SliverClient, args []
con.PrintInfof("Saved new implant profile (beacon) %s\n", resp.Name)
}
}
func shouldRunGenerateProfilesNewForm(cmd *cobra.Command, con *console.SliverClient, args []string) bool {
if con == nil || con.IsCLI {
return false
}
if len(args) != 0 {
return false
}
return cmd.Flags().NFlag() == 0
}
func applyGenerateProfilesNewForm(cmd *cobra.Command, result *forms.GenerateProfilesNewFormResult) (string, error) {
if err := cmd.Flags().Set("os", result.OS); err != nil {
return "", err
}
if err := cmd.Flags().Set("arch", result.Arch); err != nil {
return "", err
}
if err := cmd.Flags().Set("format", result.Format); err != nil {
return "", err
}
profileName := strings.TrimSpace(result.ProfileName)
if profileName == "" {
return "", errors.New("profile name required")
}
implantName := strings.TrimSpace(result.Name)
if implantName != "" {
if err := cmd.Flags().Set("name", implantName); err != nil {
return "", err
}
}
c2Value := strings.TrimSpace(result.C2Value)
switch result.C2Type {
case "mtls":
if err := cmd.Flags().Set("mtls", c2Value); err != nil {
return "", err
}
case "wg":
if err := cmd.Flags().Set("wg", c2Value); err != nil {
return "", err
}
case "http":
if err := cmd.Flags().Set("http", c2Value); err != nil {
return "", err
}
case "dns":
if err := cmd.Flags().Set("dns", c2Value); err != nil {
return "", err
}
case "named-pipe":
if err := cmd.Flags().Set("named-pipe", c2Value); err != nil {
return "", err
}
case "tcp-pivot":
if err := cmd.Flags().Set("tcp-pivot", c2Value); err != nil {
return "", err
}
default:
return "", errors.New("unsupported C2 transport selection")
}
return profileName, nil
}
func shouldRunGenerateProfilesNewBeaconForm(cmd *cobra.Command, con *console.SliverClient, args []string) bool {
if con == nil || con.IsCLI {
return false
}
if len(args) != 0 {
return false
}
return cmd.Flags().NFlag() == 0
}
func applyGenerateProfilesNewBeaconForm(cmd *cobra.Command, result *forms.GenerateProfilesNewBeaconFormResult) (string, error) {
if err := cmd.Flags().Set("os", result.OS); err != nil {
return "", err
}
if err := cmd.Flags().Set("arch", result.Arch); err != nil {
return "", err
}
if err := cmd.Flags().Set("format", result.Format); err != nil {
return "", err
}
profileName := strings.TrimSpace(result.ProfileName)
if profileName == "" {
return "", errors.New("profile name required")
}
implantName := strings.TrimSpace(result.Name)
if implantName != "" {
if err := cmd.Flags().Set("name", implantName); err != nil {
return "", err
}
}
c2Value := strings.TrimSpace(result.C2Value)
switch result.C2Type {
case "mtls":
if err := cmd.Flags().Set("mtls", c2Value); err != nil {
return "", err
}
case "wg":
if err := cmd.Flags().Set("wg", c2Value); err != nil {
return "", err
}
case "http":
if err := cmd.Flags().Set("http", c2Value); err != nil {
return "", err
}
case "dns":
if err := cmd.Flags().Set("dns", c2Value); err != nil {
return "", err
}
case "named-pipe":
if err := cmd.Flags().Set("named-pipe", c2Value); err != nil {
return "", err
}
case "tcp-pivot":
if err := cmd.Flags().Set("tcp-pivot", c2Value); err != nil {
return "", err
}
default:
return "", errors.New("unsupported C2 transport selection")
}
if err := setOptionalInt64Flag(cmd, "days", result.Days); err != nil {
return "", err
}
if err := setOptionalInt64Flag(cmd, "hours", result.Hours); err != nil {
return "", err
}
if err := setOptionalInt64Flag(cmd, "minutes", result.Minutes); err != nil {
return "", err
}
if err := setOptionalInt64Flag(cmd, "seconds", result.Seconds); err != nil {
return "", err
}
if err := setOptionalInt64Flag(cmd, "jitter", result.Jitter); err != nil {
return "", err
}
return profileName, nil
}
+2 -3
View File
@@ -22,8 +22,8 @@ import (
"context"
"fmt"
"github.com/AlecAivazis/survey/v2"
"github.com/bishopfox/sliver/client/console"
"github.com/bishopfox/sliver/client/forms"
"github.com/bishopfox/sliver/protobuf/clientpb"
"github.com/spf13/cobra"
)
@@ -45,8 +45,7 @@ func ProfilesRmCmd(cmd *cobra.Command, con *console.SliverClient, args []string)
return
}
confirm := false
prompt := &survey.Confirm{Message: fmt.Sprintf("Remove '%s' profile?", name)}
survey.AskOne(prompt, &confirm)
_ = forms.Confirm(fmt.Sprintf("Remove '%s' profile?", name), &confirm)
if !confirm {
return
}
+3 -10
View File
@@ -26,10 +26,10 @@ import (
"strings"
"time"
"github.com/AlecAivazis/survey/v2"
"github.com/bishopfox/sliver/client/command/settings"
"github.com/bishopfox/sliver/client/console"
consts "github.com/bishopfox/sliver/client/constants"
"github.com/bishopfox/sliver/client/forms"
"github.com/bishopfox/sliver/protobuf/clientpb"
"github.com/bishopfox/sliver/protobuf/commonpb"
"github.com/bishopfox/sliver/util"
@@ -140,10 +140,7 @@ func TrafficEncodersAddCmd(cmd *cobra.Command, con *console.SliverClient, args [
// saveFailedSample - Save the sample the encoder failed to properly encode/decode.
func saveFailedSample(encoderName string, test *clientpb.TrafficEncoderTest) {
confirm := false
prompt := &survey.Confirm{
Message: fmt.Sprintf("Failed to add traffic encoder %s, save failed sample to disk?", encoderName),
}
survey.AskOne(prompt, &confirm)
_ = forms.Confirm(fmt.Sprintf("Failed to add traffic encoder %s, save failed sample to disk?", encoderName), &confirm)
if !confirm {
return
}
@@ -286,10 +283,6 @@ func SelectTrafficEncoder(con *console.SliverClient) string {
}
sort.Strings(encoderNames)
var selectedEncoder string
prompt := &survey.Select{
Message: "Select a traffic encoder:",
Options: encoderNames,
}
survey.AskOne(prompt, &selectedEncoder)
_ = forms.Select("Select a traffic encoder:", encoderNames, &selectedEncoder)
return selectedEncoder
}
+9 -3
View File
@@ -1,4 +1,10 @@
Help
====
# client/command/help
This package contains all of the long-form command help templates that are displayed when a user types `help <cmd>`
## Overview
Implements the 'help' command group for the Sliver client console. Handlers map Cobra invocations to help workflows such as long help.
## Go Files
- `help.go` – Houses the legacy grouped help implementation for the console, kept for reference and future reuse.
- `long-help.go` – Stores long-form help templates and utilities for formatting command documentation.
+12 -3
View File
@@ -1,4 +1,13 @@
Hosts
======
# client/command/hosts
Command to access and manage host information.
## Overview
Implements the 'hosts' command group for the Sliver client console. Handlers map Cobra invocations to hosts workflows such as hosts IOC RM, hosts IOC, and hosts RM.
## Go Files
- `commands.go` – Sets up the hosts command suite and its IOC management subcommands.
- `hosts-ioc-rm.go` – Removes stored indicators of compromise for a host via RPC.
- `hosts-ioc.go` – Lists and prints host IOC data retrieved from the server.
- `hosts-rm.go` – Deletes hosts from inventory and confirms removal operations.
- `hosts.go` – Displays host summaries, filters by query, and renders tabular output.
+2 -6
View File
@@ -25,8 +25,8 @@ import (
"strings"
"text/tabwriter"
"github.com/AlecAivazis/survey/v2"
"github.com/bishopfox/sliver/client/console"
"github.com/bishopfox/sliver/client/forms"
"github.com/bishopfox/sliver/protobuf/clientpb"
"github.com/jedib0t/go-pretty/v6/table"
"github.com/spf13/cobra"
@@ -86,12 +86,8 @@ func SelectHostIOC(host *clientpb.Host, con *console.SliverClient) (*clientpb.IO
options := strings.Split(outputBuf.String(), "\n")
options = options[:len(options)-1] // Remove the last empty option
prompt := &survey.Select{
Message: "Select an IOC:",
Options: options,
}
selected := ""
survey.AskOne(prompt, &selected)
_ = forms.Select("Select an IOC:", options, &selected)
if selected == "" {
return nil, ErrNoSelection
}
+2 -6
View File
@@ -28,9 +28,9 @@ import (
"text/tabwriter"
"time"
"github.com/AlecAivazis/survey/v2"
"github.com/bishopfox/sliver/client/command/settings"
"github.com/bishopfox/sliver/client/console"
"github.com/bishopfox/sliver/client/forms"
"github.com/bishopfox/sliver/protobuf/clientpb"
"github.com/bishopfox/sliver/protobuf/commonpb"
"github.com/jedib0t/go-pretty/v6/table"
@@ -172,12 +172,8 @@ func SelectHost(con *console.SliverClient) (*clientpb.Host, error) {
options := strings.Split(outputBuf.String(), "\n")
options = options[:len(options)-1] // Remove the last empty option
prompt := &survey.Select{
Message: "Select a host:",
Options: options,
}
selected := ""
survey.AskOne(prompt, &selected)
_ = forms.Select("Select a host:", options, &selected)
if selected == "" {
return nil, ErrNoSelection
}
+10 -3
View File
@@ -1,4 +1,11 @@
Info
====
# client/command/info
Implements session information commands like `info`, `print`, `whoami`, etc.
## Overview
Implements the 'info' command group for the Sliver client console. Handlers map Cobra invocations to info workflows such as ping.
## Go Files
- `commands.go` – Registers information-oriented commands and binds them into the console.
- `info.go` – Queries detailed session or beacon metadata and prints rich status tables.
- `ping.go` – Sends ping requests to implants to test connectivity and round-trip latency.
+2 -2
View File
@@ -2,10 +2,10 @@ package info
import (
"context"
insecureRand "math/rand"
"github.com/bishopfox/sliver/client/console"
"github.com/bishopfox/sliver/protobuf/sliverpb"
"github.com/bishopfox/sliver/util"
"github.com/spf13/cobra"
)
@@ -16,7 +16,7 @@ func PingCmd(cmd *cobra.Command, con *console.SliverClient, args []string) {
return
}
nonce := insecureRand.Intn(999999)
nonce := util.Intn(999999)
con.PrintInfof("Ping %d\n", nonce)
pong, err := con.Rpc.Ping(context.Background(), &sliverpb.Ping{
Nonce: int32(nonce),
+15 -3
View File
@@ -1,4 +1,16 @@
Jobs
=====
# client/command/jobs
Implements commands related to starting/killing jobs like `jobs` and starting C2 listeners (`mtls`, `http`, etc.)
## Overview
Implements the 'jobs' command group for the Sliver client console. Handlers map Cobra invocations to jobs workflows such as DNS, HTTP, HTTPS, and mTLS.
## Go Files
- `commands.go` – Declares the jobs command tree and wires transport-specific subcommands.
- `dns.go` – Lists, starts, and stops DNS listener jobs via RPC.
- `http.go` – Manages HTTP listener jobs, including creation and teardown.
- `https.go` – Handles HTTPS listener lifecycle operations with certificate options.
- `jobs.go` – Provides common utilities for rendering job tables and selecting listener IDs.
- `mtls.go` – Controls mTLS listener jobs and prints connection details.
- `stage.go` – Manages staging servers for delivering payloads to new implants.
- `wg.go` – Configures and monitors WireGuard listener jobs for C2 traffic.
+1 -7
View File
@@ -48,7 +48,6 @@ func Commands(con *console.SliverClient) []*cobra.Command {
flags.Bind("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")
})
// Wireguard
@@ -66,7 +65,6 @@ func Commands(con *console.SliverClient) []*cobra.Command {
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")
})
// DNS
@@ -85,7 +83,6 @@ func Commands(con *console.SliverClient) []*cobra.Command {
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")
})
// HTTP
@@ -106,7 +103,6 @@ func Commands(con *console.SliverClient) []*cobra.Command {
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")
})
// HTTPS
@@ -132,8 +128,6 @@ func Commands(con *console.SliverClient) []*cobra.Command {
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")
})
flags.BindFlagCompletions(httpsCmd, func(comp *carapace.ActionMap) {
(*comp)["cert"] = carapace.ActionFiles().Tag("certificate file")
@@ -169,5 +163,5 @@ func Commands(con *console.SliverClient) []*cobra.Command {
(*comp)["compress"] = carapace.ActionValues([]string{"zlib", "gzip", "deflate9", "none"}...).Tag("compression formats")
})
return []*cobra.Command{jobsCmd, mtlsCmd, wgCmd, httpCmd, httpsCmd, stageCmd}
return []*cobra.Command{jobsCmd, mtlsCmd, wgCmd, dnsCmd, httpCmd, httpsCmd, stageCmd}
}
+10
View File
@@ -0,0 +1,10 @@
# client/command/kill
## Overview
Implements the 'kill' command group for the Sliver client console.
## Go Files
- `commands.go` – Registers the kill command and binds timeout/target flags.
- `kill.go` – Terminates sessions or beacons on the server, handling confirmations and output messaging.
+3 -3
View File
@@ -22,11 +22,11 @@ import (
"context"
"errors"
"github.com/AlecAivazis/survey/v2"
"github.com/spf13/cobra"
"github.com/bishopfox/sliver/client/console"
"github.com/bishopfox/sliver/client/core"
"github.com/bishopfox/sliver/client/forms"
"github.com/bishopfox/sliver/protobuf/clientpb"
"github.com/bishopfox/sliver/protobuf/commonpb"
"github.com/bishopfox/sliver/protobuf/sliverpb"
@@ -39,7 +39,7 @@ func KillCmd(cmd *cobra.Command, con *console.SliverClient, args []string) {
confirm := false
con.PrintWarnf("WARNING: This will kill the remote implant process\n\n")
if session != nil {
survey.AskOne(&survey.Confirm{Message: "Kill the active session?"}, &confirm, nil)
_ = forms.Confirm("Kill the active session?", &confirm)
if !confirm {
return
}
@@ -52,7 +52,7 @@ func KillCmd(cmd *cobra.Command, con *console.SliverClient, args []string) {
con.ActiveTarget.Background()
return
} else if beacon != nil {
survey.AskOne(&survey.Confirm{Message: "Kill the active beacon?"}, &confirm, nil)
_ = forms.Confirm("Kill the active beacon?", &confirm)
if !confirm {
return
}
+9
View File
@@ -0,0 +1,9 @@
# client/command/licenses
## Overview
Implements the 'licenses' command group for the Sliver client console.
## Go Files
- `commands.go` – Displays third-party license information through a dedicated console command.
+14 -3
View File
@@ -1,5 +1,16 @@
Loot
=====
# client/command/loot
Client loot command implementations
## Overview
Implements the 'loot' command group for the Sliver client console. Handlers map Cobra invocations to loot workflows such as fetch, local, remote, and rename.
## Go Files
- `commands.go` – Declares the loot command tree and binds fetch/local/removal subcommands.
- `fetch.go` – Downloads remote loot artifacts and writes them to local storage.
- `helpers.go` – Provides helper functions for lookup, filtering, and formatting loot entries.
- `local.go` – Lists, inspects, and opens loot stored on the client filesystem.
- `loot.go` – Shows remote loot inventory and renders summaries.
- `remote.go` – Interacts with server-side loot, supporting filtering and detail views.
- `rename.go` – Renames loot items while synchronizing local and remote metadata.
- `rm.go` – Deletes loot entries from the server or local cache with confirmation prompts.
+2 -6
View File
@@ -31,9 +31,9 @@ import (
"strings"
"text/tabwriter"
"github.com/AlecAivazis/survey/v2"
"github.com/spf13/cobra"
"github.com/bishopfox/sliver/client/forms"
"github.com/bishopfox/sliver/protobuf/clientpb"
"github.com/bishopfox/sliver/protobuf/commonpb"
"github.com/bishopfox/sliver/protobuf/rpcpb"
@@ -106,11 +106,7 @@ func SelectLoot(cmd *cobra.Command, rpc rpcpb.SliverRPCClient) (*clientpb.Loot,
}
selected := ""
prompt := &survey.Select{
Message: "Select a piece of loot:",
Options: options,
}
err = survey.AskOne(prompt, &selected)
err = forms.Select("Select a piece of loot:", options, &selected)
if err != nil {
return nil, err
}
+2 -3
View File
@@ -26,12 +26,12 @@ import (
"strings"
"unicode/utf8"
"github.com/AlecAivazis/survey/v2"
"github.com/jedib0t/go-pretty/v6/table"
"github.com/spf13/cobra"
"github.com/bishopfox/sliver/client/command/settings"
"github.com/bishopfox/sliver/client/console"
"github.com/bishopfox/sliver/client/forms"
"github.com/bishopfox/sliver/protobuf/clientpb"
"github.com/bishopfox/sliver/protobuf/commonpb"
"github.com/bishopfox/sliver/util"
@@ -111,8 +111,7 @@ func saveLootToDisk(cmd *cobra.Command, loot *clientpb.Loot) (string, error) {
}
if _, err := os.Stat(saveTo); err == nil {
overwrite := false
prompt := &survey.Confirm{Message: "Overwrite local file?"}
survey.AskOne(prompt, &overwrite, nil)
_ = forms.Confirm("Overwrite local file?", &overwrite)
if !overwrite {
return "", nil
}
+2 -3
View File
@@ -21,10 +21,10 @@ package loot
import (
"context"
"github.com/AlecAivazis/survey/v2"
"github.com/spf13/cobra"
"github.com/bishopfox/sliver/client/console"
"github.com/bishopfox/sliver/client/forms"
"github.com/bishopfox/sliver/protobuf/clientpb"
)
@@ -37,8 +37,7 @@ func LootRenameCmd(cmd *cobra.Command, con *console.SliverClient, args []string)
}
oldName := loot.Name
newName := ""
prompt := &survey.Input{Message: "Enter new name: "}
survey.AskOne(prompt, &newName)
_ = forms.Input("Enter new name:", &newName)
loot, err = con.Rpc.LootUpdate(context.Background(), &clientpb.Loot{
ID: loot.ID,
+10 -3
View File
@@ -1,5 +1,12 @@
Monitor
========
# client/command/monitor
Contains `monitor` related command implementations.
## Overview
Implements the 'monitor' command group for the Sliver client console. Handlers map Cobra invocations to monitor workflows such as start and stop.
## Go Files
- `commands.go` – Registers the monitor command suite for live session monitoring.
- `config.go` – Parses monitor configuration flags and resolves target selections.
- `start.go` – Starts monitoring jobs and streams event output to the console.
- `stop.go` – Stops active monitor jobs and reports termination status.
+2 -6
View File
@@ -22,9 +22,9 @@ 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/client/forms"
"github.com/bishopfox/sliver/protobuf/clientpb"
"github.com/bishopfox/sliver/protobuf/commonpb"
"github.com/jedib0t/go-pretty/v6/table"
@@ -121,11 +121,7 @@ func selectWatchtowerConfig(configs *clientpb.MonitoringProviders) (*clientpb.Mo
}
selected := ""
prompt := &survey.Select{
Message: "Select a configuration:",
Options: options,
}
err := survey.AskOne(prompt, &selected)
err := forms.Select("Select a configuration:", options, &selected)
if err != nil {
return nil, err
}
+10 -3
View File
@@ -1,4 +1,11 @@
Network
========
# client/command/network
Network related command implementations such as `netstat` and `ifconfig`
## Overview
Implements the 'network' command group for the Sliver client console. Handlers map Cobra invocations to network workflows such as ifconfig and netstat.
## Go Files
- `commands.go` – Registers network inspection commands for implants.
- `ifconfig.go` – Retrieves and prints interface configuration details from the target.
- `netstat.go` – Displays remote socket listings similar to netstat output.
+8 -4
View File
@@ -1,6 +1,10 @@
Operators
==========
# client/command/operators
Operator related command implementations.
## Overview
__NOTE:__ Some operator-related commands are server-side only and are located instead in `server/console`
Implements the 'operators' command group for the Sliver client console.
## Go Files
- `commands.go` – Declares the operators command and binds associated flags.
- `operators.go` – Lists operators connected to the server and prints session details.
+13 -3
View File
@@ -1,5 +1,15 @@
Pivots
=======
# client/command/pivots
Pivot related command implementations, pivots are specifically for pivoting C2 traffic (not to be confused with port forwarding)
## Overview
Implements the 'pivots' command group for the Sliver client console. Handlers map Cobra invocations to pivots workflows such as details, graph, start, and stop.
## Go Files
- `commands.go` – Declares the pivots command family and ties start/stop operations together.
- `details.go` – Prints detailed information about a specific pivot chain.
- `graph.go` – Renders pivot relationships as ASCII graphs for situational awareness.
- `helpers.go` – Supplies shared RPC helpers and completions used across pivot commands.
- `pivots.go` – Lists pivot sessions and summarizes their status.
- `start.go` – Initiates new pivot listeners or routes for the active target.
- `stop.go` – Stops running pivots and cleans up resources on the implant.
+2 -6
View File
@@ -27,8 +27,8 @@ import (
"strings"
"text/tabwriter"
"github.com/AlecAivazis/survey/v2"
"github.com/bishopfox/sliver/client/console"
"github.com/bishopfox/sliver/client/forms"
"github.com/bishopfox/sliver/protobuf/sliverpb"
"github.com/rsteube/carapace"
)
@@ -49,11 +49,7 @@ func SelectPivotListener(listeners []*sliverpb.PivotListener, con *console.Slive
}
selected := ""
prompt := &survey.Select{
Message: "Select a beacon task:",
Options: options,
}
err := survey.AskOne(prompt, &selected)
err := forms.Select("Select a beacon task:", options, &selected)
if err != nil {
return nil, err
}
+9 -4
View File
@@ -1,7 +1,12 @@
Portfwd
========
# client/command/portfwd
In-band port forwarding related command implementations.
## Overview
__NOTE:__ WireGuard port forwarding commands are located in `client/command/wireguard`
Implements the 'portfwd' command group for the Sliver client console. Handlers map Cobra invocations to portfwd workflows such as portfwd ADD and portfwd RM.
## Go Files
- `commands.go` – Sets up the port forwarding command suite.
- `portfwd-add.go` – Adds new local-to-remote port forwarders on the active session.
- `portfwd-rm.go` – Removes configured port forwarders by ID.
- `portfwd.go` – Lists existing port forwards and renders their configuration.
+13 -3
View File
@@ -1,5 +1,15 @@
Privilege
==========
# client/command/privilege
Commands related to manipulation of operating system privileges, such as Windows Tokens.
## Overview
Implements the 'privilege' command group for the Sliver client console. Handlers map Cobra invocations to privilege workflows such as getprivs, getsystem, impersonate, and make token.
## Go Files
- `commands.go` – Registers privilege escalation commands and binds platform restrictions.
- `getprivs.go` – Queries and prints token privileges for the current user context.
- `getsystem.go` – Attempts to obtain SYSTEM privileges via built-in escalation techniques.
- `impersonate.go` – Handles impersonation of other logon sessions using available tokens.
- `make-token.go` – Creates new logon tokens with supplied credentials for the implant.
- `rev2self.go` – Reverts impersonation back to the implant's original security context.
- `runas.go` – Runs commands under alternate credentials or integrity levels through runas-like workflows.
+13 -3
View File
@@ -1,4 +1,14 @@
Processes
==========
# client/command/processes
Commands for manipulating remote processes, e.g. `ps`, `terminate`, etc.
## Overview
Implements the 'processes' command group for the Sliver client console. Handlers map Cobra invocations to processes workflows such as procdump, PS, pstree, and terminate.
## Go Files
- `commands.go` – Creates the processes command suite and binds subcommands for inspection and control.
- `procdump.go` – Dumps process memory to loot for forensic analysis via RPC tasks.
- `ps.go` – Lists active processes on the target with filtering options.
- `pstree.go` – Renders process hierarchies as a tree view.
- `services.go` – Enumerates Windows services and their states.
- `terminate.go` – Terminates processes by PID with confirmation messaging.
Loaded 100 of 5027 files, more files were not shown because too many files have changed in this diff. Show more