Compare commits

...
731 Commits
Author SHA1 Message Date
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
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 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
Ronan Kervella 113ef5d7d0 Merge branch 'master' into fix_1842 2025-02-13 15:16:52 -08:00
Tim Makram Ghatas 9fa1e15425 set stage2 before encryption/compression 2025-02-10 13:48:20 +01: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
Joe 2f486be19c Merge pull request #1872 from BishopFox/go/v1.23.5
Update to Go v1.23.5 and Garble v1.23.5
2025-02-05 10:56:03 -06:00
moloch-- 85868e5b8f Update to Go v1.23.5 and Garble v1.23.5 2025-01-29 11:28:42 -07:00
Joe 31c70938bd Merge pull request #1858 from BishopFox/48b9dependabot/go_modules/golang.org/x/net-0.33.0
Bump golang.org/x/net from 0.26.0 to 0.33.0
2025-01-21 11:07:27 -06: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
dependabot[bot] 63668f57b5 Bump golang.org/x/net from 0.26.0 to 0.33.0
Bumps [golang.org/x/net](https://github.com/golang/net) from 0.26.0 to 0.33.0.
- [Commits](https://github.com/golang/net/compare/v0.26.0...v0.33.0)

---
updated-dependencies:
- dependency-name: golang.org/x/net
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <[email protected]>
2025-01-20 18:01:38 +00:00
Joe aefe6b31e9 Merge pull request #1854 from BishopFox/74eedependabot/go_modules/golang.org/x/crypto-0.32.0
Bump golang.org/x/crypto from 0.29.0 to 0.32.0
2025-01-20 12:00:00 -06:00
Joe f854af1134 Merge pull request #1855 from BishopFox/abide_generate_name
Abide generate name
2025-01-20 11:59:44 -06:00
Joe a9ef42a416 Merge branch 'master' into abide_generate_name 2025-01-20 11:03:14 -06:00
Joe 67c6140e6a Merge pull request #1857 from BishopFox/v1.6.0/download-refactor
Simplifying Implant Download Code
2025-01-20 11:02:33 -06: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
Raf 59352177eb Simplifying file downloads to address issue #1812 2025-01-17 12:30:49 -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
c2biz c9a624831a fix input bug to AllowedName in GenerateExternal() 2025-01-15 09:23:02 -05:00
c2biz ed64f2e0d2 fix bug ignoring supplied name for generate functions 2025-01-15 08:40:45 -05:00
dependabot[bot] 5f18609ed7 Bump golang.org/x/crypto from 0.29.0 to 0.32.0
Bumps [golang.org/x/crypto](https://github.com/golang/crypto) from 0.29.0 to 0.32.0.
- [Commits](https://github.com/golang/crypto/compare/v0.29.0...v0.32.0)

---
updated-dependencies:
- dependency-name: golang.org/x/crypto
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <[email protected]>
2025-01-13 03:30:28 +00:00
Timothy Makram Ghatas 53c61cb024 Merge pull request #1844 from w4lle-code/fix_c2profile_import_overwrite_url_parameters
fix to import overwrite c2Profile to url_parameters
2025-01-07 16:25:50 +01:00
Timothy Makram Ghatas 3d70247f8b Update httpclient.go - use updated uri for debug logs
Signed-off-by: Timothy Makram Ghatas <[email protected]>
2025-01-07 15:33:29 +01:00
Timothy Makram Ghatas 52b1c7b93b Merge branch 'master' into fix_c2profile_import_overwrite_url_parameters 2025-01-07 14:57:24 +01:00
Timothy Makram Ghatas daeb463f77 Update httpclient.go
add check for method in implant httpclient

Signed-off-by: Timothy Makram Ghatas <[email protected]>
2025-01-07 14:46:32 +01:00
Joe 0c75f70a1d Merge pull request #1847 from BishopFox/404ddependabot/npm_and_yarn/docs/sliver-docs/next-14.2.22
Bump next from 14.2.20 to 14.2.22 in /docs/sliver-docs
2025-01-06 13:41:51 -06:00
AndresFelipeGualdron 674df112a4 adding method of url parameter in template 2025-01-04 20:12:10 -05:00
AndresFelipeGualdron 26efc776c7 fix to import no overwrite c2Profile 2025-01-03 22:32:53 -05:00
dependabot[bot] f221dc95cf Bump next from 14.2.20 to 14.2.22 in /docs/sliver-docs
Bumps [next](https://github.com/vercel/next.js) from 14.2.20 to 14.2.22.
- [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/v14.2.20...v14.2.22)

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

Signed-off-by: dependabot[bot] <[email protected]>
2025-01-04 02:59:04 +00:00
AndresFelipeGualdron 187fc6acd2 fix to import overwrite c2Profile to url_parameters 2025-01-03 12:01:42 -05:00
Joe 9ecb68f6a3 Merge pull request #1841 from BishopFox/fix_c2profile_display
fix broken pr for http headers and add additional constraints for c2p…
2025-01-02 20:42:29 -06:00
Tim Makram Ghatas f0113655ce fix broken pr for http headers and add additional constraints for c2profile import 2025-01-02 14:53:31 +01:00
Joe 31265c626b Merge pull request #1836 from BishopFox/b3f8dependabot/npm_and_yarn/docs/sliver-docs/next-14.2.20
Bump next from 14.2.12 to 14.2.20 in /docs/sliver-docs
2024-12-18 15:26:49 -06:00
dependabot[bot] e2603ac3ae Bump next from 14.2.12 to 14.2.20 in /docs/sliver-docs
Bumps [next](https://github.com/vercel/next.js) from 14.2.12 to 14.2.20.
- [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/v14.2.12...v14.2.20)

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

Signed-off-by: dependabot[bot] <[email protected]>
2024-12-18 19:02:18 +00:00
Ronan Kervella 7acbed9637 Merge pull request #1724 from BishopFox/4ddedependabot/go_modules/gorm.io/driver/postgres-1.5.9
Bump gorm.io/driver/postgres from 1.5.7 to 1.5.9
2024-12-03 10:33:02 -10:00
Ronan Kervella 20786fa6fb Merge branch 'master' into 4ddedependabot/go_modules/gorm.io/driver/postgres-1.5.9
Signed-off-by: Ronan Kervella <[email protected]>
2024-12-03 10:34:33 -08:00
Ronan Kervella 03c750a8b5 Merge pull request #1741 from BishopFox/378ddependabot/go_modules/gorm.io/driver/mysql-1.5.7
Bump gorm.io/driver/mysql from 1.5.6 to 1.5.7
2024-12-03 10:30:21 -08:00
Ronan Kervella 4da8c6053f Merge branch 'master' into 4ddedependabot/go_modules/gorm.io/driver/postgres-1.5.9 2024-12-02 16:12:23 -08:00
Ronan Kervella a43061c61b Merge branch 'master' into 378ddependabot/go_modules/gorm.io/driver/mysql-1.5.7 2024-12-02 15:40:49 -08:00
Ronan Kervella 11dc6bac4d Merge pull request #1824 from BishopFox/b42adependabot/go_modules/github.com/ncruces/go-sqlite3-0.20.3
Bump github.com/ncruces/go-sqlite3 from 0.15.0 to 0.20.3
2024-12-02 15:39:58 -08:00
dependabot[bot] 7d5a886397 Bump github.com/ncruces/go-sqlite3 from 0.15.0 to 0.20.3
Bumps [github.com/ncruces/go-sqlite3](https://github.com/ncruces/go-sqlite3) from 0.15.0 to 0.20.3.
- [Release notes](https://github.com/ncruces/go-sqlite3/releases)
- [Commits](https://github.com/ncruces/go-sqlite3/compare/v0.15.0...v0.20.3)

---
updated-dependencies:
- dependency-name: github.com/ncruces/go-sqlite3
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <[email protected]>
2024-12-02 03:42:38 +00:00
Joe 77aef8179d Merge branch 'master' into 4ddedependabot/go_modules/gorm.io/driver/postgres-1.5.9 2024-11-25 10:28:39 -06:00
Joe 69e7c8ce71 Merge pull request #1811 from rwincey/c2_profile_headers_fix
Fixed implant custom HTTP header code
2024-11-11 14:40:00 -06:00
b0yd 82e294e3ef Gofmt 2024-11-06 15:40:48 +00:00
b0yd ccf3701011 Fixed implant custom HTTP header code 2024-11-06 15:26:40 +00:00
Joe e4b64e1050 Merge pull request #1800 from toasted-time-traveller/fix-wording
Added a missing word and a missing period.
2024-10-30 12:19:52 -05:00
Joe 0b8f702aa0 Merge pull request #1787 from An00bRektn/master
Update link in Community Guides section of docs
2024-10-30 12:19:14 -05:00
Ronan Kervella 8caf90536b Merge branch 'master' into master 2024-10-30 08:27:08 -07:00
toasted-time-traveller 50e7d89576 Added the missing word 'at' to the note section and a period to the 'Feedback' section in README 2024-10-23 03:38:28 +02:00
Joe fe5e9382d7 Merge pull request #1796 from AD2011/patch-1
Correct Windows compile command
2024-10-17 10:40:53 -05:00
Abir Dey 934c01f08d Correct Windows compile command
Signed-off-by: Abir Dey <[email protected]>
2024-10-17 14:17:28 +05:30
An00bRektn 4ced15e528 Changed link to point to updated location 2024-10-04 17:14:39 -05:00
Joe 3c151ed172 Merge pull request #1784 from BishopFox/docs/community-guides
Add detecting sliver c2 with zeek to community guides
2024-09-29 17:04:22 -05:00
moloch-- dd09895d7e Add detecting sliver c2 with zeek to community guides 2024-09-26 13:02:06 -04:00
Joe 3dd2b2ddce Merge pull request #1779 from AFrenchBanana/fix/DuplicateWord
Removed duplicate word from help menu
2024-09-22 13:28:01 -05:00
Joe e4027d6373 Merge pull request #1780 from BishopFox/7953dependabot/npm_and_yarn/docs/sliver-docs/next-14.2.12
Bump next from 14.2.3 to 14.2.12 in /docs/sliver-docs
2024-09-19 09:40:59 -05:00
dependabot[bot] 7e880d33c7 Bump next from 14.2.3 to 14.2.12 in /docs/sliver-docs
Bumps [next](https://github.com/vercel/next.js) from 14.2.3 to 14.2.12.
- [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/v14.2.3...v14.2.12)

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

Signed-off-by: dependabot[bot] <[email protected]>
2024-09-18 02:47:07 +00:00
ryan dodd 356b17160e Removed duplicate word from comment 2024-09-17 21:34:09 +01:00
Joe 9a9b0c74ba Merge pull request #1763 from BishopFox/1cbddependabot/go_modules/github.com/tetratelabs/wazero-1.8.0
Bump github.com/tetratelabs/wazero from 1.7.2 to 1.8.0
2024-09-07 15:39:38 -05:00
Joe dbde661d90 Merge pull request #1772 from BishopFox/2e71dependabot/npm_and_yarn/docs/sliver-docs/micromatch-4.0.8
Bump micromatch from 4.0.5 to 4.0.8 in /docs/sliver-docs
2024-09-07 15:15:50 -05:00
dependabot[bot] 8904267cad Bump micromatch from 4.0.5 to 4.0.8 in /docs/sliver-docs
Bumps [micromatch](https://github.com/micromatch/micromatch) from 4.0.5 to 4.0.8.
- [Release notes](https://github.com/micromatch/micromatch/releases)
- [Changelog](https://github.com/micromatch/micromatch/blob/master/CHANGELOG.md)
- [Commits](https://github.com/micromatch/micromatch/compare/4.0.5...4.0.8)

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

Signed-off-by: dependabot[bot] <[email protected]>
2024-09-07 10:28:02 +00:00
Joe c58cb2d4e7 Merge pull request #1765 from BishopFox/go/v1.22.5
Go 1.22.5, Zig 0.13.0
2024-08-23 13:47:48 -05:00
moloch-- cf971ea599 Go 1.22.5, Zig 0.13.0 2024-08-23 10:26:52 -07:00
Ronan Kervella 71c922c914 Merge pull request #1762 from martinboca/docs/fix-typos
fixed typos in docs
2024-08-20 11:04:40 -07:00
dependabot[bot] 3607b526f0 Bump github.com/tetratelabs/wazero from 1.7.2 to 1.8.0
Bumps [github.com/tetratelabs/wazero](https://github.com/tetratelabs/wazero) from 1.7.2 to 1.8.0.
- [Release notes](https://github.com/tetratelabs/wazero/releases)
- [Commits](https://github.com/tetratelabs/wazero/compare/v1.7.2...v1.8.0)

---
updated-dependencies:
- dependency-name: github.com/tetratelabs/wazero
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <[email protected]>
2024-08-19 03:25:13 +00:00
Martín Bocanegra 1c87e8134c fixed typos 2024-08-18 21:40:11 -03:00
Ronan Kervella 2a849312cc Merge branch 'master' into 378ddependabot/go_modules/gorm.io/driver/mysql-1.5.7 2024-07-31 13:21:26 -07:00
Ronan Kervella 127caf54ae Merge pull request #1740 from BishopFox/e942dependabot/go_modules/golang.org/x/crypto-0.25.0
Bump golang.org/x/crypto from 0.24.0 to 0.25.0
2024-07-31 13:21:13 -07:00
Ronan Kervella 5902f4b02d Merge branch 'master' into e942dependabot/go_modules/golang.org/x/crypto-0.25.0 2024-07-31 12:08:33 -07:00
Joe 40dfa95291 Merge pull request #1752 from BishopFox/wiki_1.6_update
Wiki 1.6 update
2024-07-22 16:31:31 -05:00
Tim Makram Ghatas b8cef5fbd6 removed broken links from chapter 7 and added disclaimer to all pages 2024-07-22 21:26:49 +02:00
Tim Makram Ghatas eed6890700 update tutorial text and add 1.6 disclaimer 2024-07-22 20:14:34 +02:00
Tim Makram Ghatas 36e0c71b10 Merge branch 'master' into wiki_1.6_update 2024-07-22 19:50:58 +02:00
dependabot[bot] 1bf020c594 Bump gorm.io/driver/mysql from 1.5.6 to 1.5.7
Bumps [gorm.io/driver/mysql](https://github.com/go-gorm/mysql) from 1.5.6 to 1.5.7.
- [Commits](https://github.com/go-gorm/mysql/compare/v1.5.6...v1.5.7)

---
updated-dependencies:
- dependency-name: gorm.io/driver/mysql
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <[email protected]>
2024-07-18 18:08:17 +00:00
dependabot[bot] 072111a692 Bump golang.org/x/crypto from 0.24.0 to 0.25.0
Bumps [golang.org/x/crypto](https://github.com/golang/crypto) from 0.24.0 to 0.25.0.
- [Commits](https://github.com/golang/crypto/compare/v0.24.0...v0.25.0)

---
updated-dependencies:
- dependency-name: golang.org/x/crypto
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <[email protected]>
2024-07-18 18:08:15 +00:00
Joe 2cd7a96324 Merge pull request #1743 from BishopFox/49f9dependabot/go_modules/google.golang.org/grpc-1.64.1
Bump google.golang.org/grpc from 1.64.0 to 1.64.1
2024-07-18 13:05:58 -05:00
Joe d8ff64222d Merge pull request #1751 from BishopFox/v1.6.0/remove-msf-stager
Removing generate msf-stager command
2024-07-18 13:03:49 -05:00
Raf 0deaee625d Removing generate msf-stager command
Removing the generate msf-stager command and adding documentation on how to use msfvenom / msfconsole to generate stager binaries.
2024-07-18 13:14:16 -04:00
Ronan Kervella bdfd89167d Merge pull request #1737 from lip234/master
Fixes #1736
2024-07-11 10:53:34 -07:00
dependabot[bot] 6b35032c0e Bump google.golang.org/grpc from 1.64.0 to 1.64.1
Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.64.0 to 1.64.1.
- [Release notes](https://github.com/grpc/grpc-go/releases)
- [Commits](https://github.com/grpc/grpc-go/compare/v1.64.0...v1.64.1)

---
updated-dependencies:
- dependency-name: google.golang.org/grpc
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <[email protected]>
2024-07-09 21:45:35 +00:00
lip234 8bf4f8ef02 Fixes #1736
Fixes issue in the implant where `ps` command leads to infinite loop on Darwin under certain conditions.
2024-07-08 13:35:30 -06:00
Ronan Kervella 7676fc6c37 Merge pull request #1720 from BishopFox/9d54dependabot/npm_and_yarn/docs/sliver-docs/braces-3.0.3
Bump braces from 3.0.2 to 3.0.3 in /docs/sliver-docs
2024-07-03 10:05:45 -07:00
Ronan Kervella d2ff8dca46 Merge branch 'master' into 9d54dependabot/npm_and_yarn/docs/sliver-docs/braces-3.0.3 2024-07-02 15:09:08 -07:00
Ronan Kervella 9c3d7abff5 Merge pull request #1723 from BishopFox/b71edependabot/go_modules/modernc.org/sqlite-1.30.1
Bump modernc.org/sqlite from 1.30.0 to 1.30.1
2024-07-02 15:08:41 -07:00
Ronan Kervella 4df4e21255 Merge branch 'master' into b71edependabot/go_modules/modernc.org/sqlite-1.30.1 2024-07-02 12:59:33 -07:00
Ronan Kervella 3fdde93255 Merge pull request #1733 from BishopFox/2d74dependabot/go_modules/github.com/spf13/cobra-1.8.1
Bump github.com/spf13/cobra from 1.8.0 to 1.8.1
2024-07-02 12:59:14 -07:00
dependabot[bot] 65a7faebd5 Bump github.com/spf13/cobra from 1.8.0 to 1.8.1
Bumps [github.com/spf13/cobra](https://github.com/spf13/cobra) from 1.8.0 to 1.8.1.
- [Release notes](https://github.com/spf13/cobra/releases)
- [Commits](https://github.com/spf13/cobra/compare/v1.8.0...v1.8.1)

---
updated-dependencies:
- dependency-name: github.com/spf13/cobra
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <[email protected]>
2024-07-01 03:57:53 +00:00
Ronan Kervella c3b0909be0 Merge branch 'master' into 4ddedependabot/go_modules/gorm.io/driver/postgres-1.5.9 2024-06-28 11:10:57 -07:00
Ronan Kervella 641361d7c3 Merge pull request #1722 from BishopFox/cacfdependabot/go_modules/github.com/klauspost/compress-1.17.9
Bump github.com/klauspost/compress from 1.17.8 to 1.17.9
2024-06-28 10:44:17 -07:00
dependabot[bot] 4a149f073a Bump gorm.io/driver/postgres from 1.5.7 to 1.5.9
Bumps [gorm.io/driver/postgres](https://github.com/go-gorm/postgres) from 1.5.7 to 1.5.9.
- [Commits](https://github.com/go-gorm/postgres/compare/v1.5.7...v1.5.9)

---
updated-dependencies:
- dependency-name: gorm.io/driver/postgres
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <[email protected]>
2024-06-17 03:11:56 +00:00
dependabot[bot] ba43b3fd4b Bump modernc.org/sqlite from 1.30.0 to 1.30.1
Bumps [modernc.org/sqlite](https://gitlab.com/cznic/sqlite) from 1.30.0 to 1.30.1.
- [Commits](https://gitlab.com/cznic/sqlite/compare/v1.30.0...v1.30.1)

---
updated-dependencies:
- dependency-name: modernc.org/sqlite
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <[email protected]>
2024-06-17 03:11:48 +00:00
dependabot[bot] 5c2314702b Bump github.com/klauspost/compress from 1.17.8 to 1.17.9
Bumps [github.com/klauspost/compress](https://github.com/klauspost/compress) from 1.17.8 to 1.17.9.
- [Release notes](https://github.com/klauspost/compress/releases)
- [Changelog](https://github.com/klauspost/compress/blob/master/.goreleaser.yml)
- [Commits](https://github.com/klauspost/compress/compare/v1.17.8...v1.17.9)

---
updated-dependencies:
- dependency-name: github.com/klauspost/compress
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <[email protected]>
2024-06-17 03:11:31 +00:00
Joe 3051de7a61 Merge pull request #1711 from BishopFox/8a2bdependabot/go_modules/golang.org/x/crypto-0.24.0
Bump golang.org/x/crypto from 0.23.0 to 0.24.0
2024-06-15 12:11:12 -05:00
dependabot[bot] 1abf8e54c3 Bump braces from 3.0.2 to 3.0.3 in /docs/sliver-docs
Bumps [braces](https://github.com/micromatch/braces) from 3.0.2 to 3.0.3.
- [Changelog](https://github.com/micromatch/braces/blob/master/CHANGELOG.md)
- [Commits](https://github.com/micromatch/braces/compare/3.0.2...3.0.3)

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

Signed-off-by: dependabot[bot] <[email protected]>
2024-06-15 17:10:59 +00:00
Joe 93624cdb2d Merge pull request #1712 from BishopFox/e733dependabot/go_modules/modernc.org/sqlite-1.30.0
Bump modernc.org/sqlite from 1.29.10 to 1.30.0
2024-06-15 12:10:24 -05:00
dependabot[bot] a7c6ea1f43 Bump modernc.org/sqlite from 1.29.10 to 1.30.0
Bumps [modernc.org/sqlite](https://gitlab.com/cznic/sqlite) from 1.29.10 to 1.30.0.
- [Commits](https://gitlab.com/cznic/sqlite/compare/v1.29.10...v1.30.0)

---
updated-dependencies:
- dependency-name: modernc.org/sqlite
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <[email protected]>
2024-06-10 03:32:41 +00:00
dependabot[bot] f23093c3a9 Bump golang.org/x/crypto from 0.23.0 to 0.24.0
Bumps [golang.org/x/crypto](https://github.com/golang/crypto) from 0.23.0 to 0.24.0.
- [Commits](https://github.com/golang/crypto/compare/v0.23.0...v0.24.0)

---
updated-dependencies:
- dependency-name: golang.org/x/crypto
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <[email protected]>
2024-06-10 03:31:01 +00:00
Ronan Kervella 6f4a150d82 Merge pull request #1705 from BishopFox/autoremove_socks_proxies
autoremove socks proxies
2024-06-03 09:31:59 -07:00
Tim Makram Ghatas 6790cd1647 automatically remove socks proxies during a kill/close command for a session 2024-06-02 15:06:38 +02:00
Joe 05408ef4ea Merge pull request #1700 from BishopFox/0850dependabot/go_modules/tailscale.com-1.66.4
Bump tailscale.com from 1.66.3 to 1.66.4
2024-05-31 10:41:32 -05:00
Joe 2bc3fe8a57 Merge pull request #1704 from BishopFox/improve_socks_menu
Improve socks menu
2024-05-31 10:40:48 -05:00
Joe 015942a1e4 Merge pull request #1703 from BishopFox/implement_clean_command
Implement clean command
2024-05-31 10:40:00 -05:00
Tim Makram Ghatas 321da76fd9 add server command to list/stop socks proxies and modify implant socks command to only display proxies for the currently selected session 2024-05-31 12:41:29 +02:00
Tim Makram Ghatas 2407b4dd2e remove profiles and implants. Beacons are just removed instead of killing them. 2024-05-31 12:10:49 +02:00
Tim Makram Ghatas ea06daa5ac add clean command and function definitions 2024-05-31 11:46:54 +02:00
dependabot[bot] f67b08768d Bump tailscale.com from 1.66.3 to 1.66.4
Bumps [tailscale.com](https://github.com/tailscale/tailscale) from 1.66.3 to 1.66.4.
- [Release notes](https://github.com/tailscale/tailscale/releases)
- [Commits](https://github.com/tailscale/tailscale/compare/v1.66.3...v1.66.4)

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

Signed-off-by: dependabot[bot] <[email protected]>
2024-05-27 03:35:03 +00:00
Joe d0e5fbb680 Merge pull request #1693 from BishopFox/981ddependabot/go_modules/google.golang.org/grpc-1.64.0
Bump google.golang.org/grpc from 1.63.2 to 1.64.0
2024-05-22 13:48:45 -05:00
dependabot[bot] 6dd56bbfd5 Bump google.golang.org/grpc from 1.63.2 to 1.64.0
Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.63.2 to 1.64.0.
- [Release notes](https://github.com/grpc/grpc-go/releases)
- [Commits](https://github.com/grpc/grpc-go/compare/v1.63.2...v1.64.0)

---
updated-dependencies:
- dependency-name: google.golang.org/grpc
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <[email protected]>
2024-05-22 15:47:44 +00:00
Joe 8f15f896ac Merge pull request #1697 from BishopFox/1071dependabot/go_modules/modernc.org/sqlite-1.29.10
Bump modernc.org/sqlite from 1.29.9 to 1.29.10
2024-05-22 10:46:17 -05:00
Joe a0706ffc1f Merge pull request #1699 from BishopFox/fix_externalbuild_encoderids
send encoder id's to external server during external implant generation
2024-05-22 09:40:30 -05:00
Ronan Kervella 550700de98 Merge branch 'master' into fix_externalbuild_encoderids 2024-05-22 06:49:01 -07:00
dependabot[bot] 652d960d59 Bump modernc.org/sqlite from 1.29.9 to 1.29.10
Bumps [modernc.org/sqlite](https://gitlab.com/cznic/sqlite) from 1.29.9 to 1.29.10.
- [Commits](https://gitlab.com/cznic/sqlite/compare/v1.29.9...v1.29.10)

---
updated-dependencies:
- dependency-name: modernc.org/sqlite
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <[email protected]>
2024-05-21 21:39:28 +00:00
Ronan Kervella 292f41c665 Merge pull request #1696 from BishopFox/b516dependabot/go_modules/github.com/tetratelabs/wazero-1.7.2
Bump github.com/tetratelabs/wazero from 1.7.1 to 1.7.2
2024-05-21 14:32:56 -07:00
dependabot[bot] ef324e8b9d Bump github.com/tetratelabs/wazero from 1.7.1 to 1.7.2
Bumps [github.com/tetratelabs/wazero](https://github.com/tetratelabs/wazero) from 1.7.1 to 1.7.2.
- [Release notes](https://github.com/tetratelabs/wazero/releases)
- [Commits](https://github.com/tetratelabs/wazero/compare/v1.7.1...v1.7.2)

---
updated-dependencies:
- dependency-name: github.com/tetratelabs/wazero
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <[email protected]>
2024-05-21 17:09:18 +00:00
Joe a405ae8f20 Merge pull request #1694 from BishopFox/e220dependabot/go_modules/tailscale.com-1.66.3
Bump tailscale.com from 1.64.2 to 1.66.3
2024-05-21 12:08:00 -05:00
Ronan Kervella 222cc3437b Merge branch 'master' into e220dependabot/go_modules/tailscale.com-1.66.3 2024-05-21 08:35:08 -07:00
Ronan Kervella fdeca972bd Merge pull request #1692 from BishopFox/generate_c2profiles
improve c2profiles command
2024-05-20 15:30:59 -07:00
Tim Makram Ghatas 69bcf72e80 send encoder id's to external server during external implant generation 2024-05-21 00:04:33 +02:00
Timothy Makram Ghatas d60dd6a5a0 Merge branch 'master' into generate_c2profiles 2024-05-20 23:26:37 +02:00
Tim Makram Ghatas 8737bba4c3 enforce unique startsession extensions 2024-05-20 23:25:10 +02:00
Tim Makram Ghatas 97716d2b9e only stager extensions need to be unique 2024-05-20 23:01:38 +02:00
Tim Makram Ghatas 844a6f8d25 check there are sufficient unused extensions in the provided file 2024-05-20 22:58:09 +02:00
Tim Makram Ghatas b6f2c1b4bb fix documentation for generate command 2024-05-20 22:23:56 +02:00
Ronan Kervella c6397918c6 Merge branch 'master' into e220dependabot/go_modules/tailscale.com-1.66.3 2024-05-20 11:02:00 -07:00
Ronan Kervella 848704eb3c Merge pull request #1695 from BishopFox/0bafdependabot/go_modules/github.com/fatih/color-1.17.0
Bump github.com/fatih/color from 1.16.0 to 1.17.0
2024-05-20 11:01:48 -07:00
dependabot[bot] c3571b001a Bump github.com/fatih/color from 1.16.0 to 1.17.0
Bumps [github.com/fatih/color](https://github.com/fatih/color) from 1.16.0 to 1.17.0.
- [Release notes](https://github.com/fatih/color/releases)
- [Commits](https://github.com/fatih/color/compare/v1.16.0...v1.17.0)

---
updated-dependencies:
- dependency-name: github.com/fatih/color
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <[email protected]>
2024-05-20 03:37:24 +00:00
dependabot[bot] 53449c1a83 Bump tailscale.com from 1.64.2 to 1.66.3
Bumps [tailscale.com](https://github.com/tailscale/tailscale) from 1.64.2 to 1.66.3.
- [Release notes](https://github.com/tailscale/tailscale/releases)
- [Commits](https://github.com/tailscale/tailscale/compare/v1.64.2...v1.66.3)

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

Signed-off-by: dependabot[bot] <[email protected]>
2024-05-20 03:37:15 +00:00
Tim Makram Ghatas cf6682dff7 allow generating c2profiles using a file containing one url per line. Fix autocomplete for export c2profile name 2024-05-19 13:18:26 +02:00
Joe 2a1453ee37 Merge pull request #1691 from BishopFox/v1.6.0/certificate-management
View Certificate Information
2024-05-17 12:46:13 -05:00
Raf a9f06fc299 Merge branch 'master' into v1.6.0/certificate-management 2024-05-17 09:39:30 -04:00
Raf 5839c59682 Changing help text for certificates command 2024-05-17 09:35:54 -04:00
Raf 860810c148 Adding filters to certificate command 2024-05-17 09:33:24 -04:00
Ronan Kervella d92f079f97 Merge pull request #1690 from w33ts/patch-1
Fixed command typo in Getting Started.md
2024-05-17 13:19:58 +02:00
w33ts 4315a3fce3 Fixed command typo in Getting Started.md
There is a command that says "systemctrl" instead of "systemctl". Yup, I'm *that* guy now.

Signed-off-by: w33ts <[email protected]>
2024-05-16 21:50:34 -05:00
Joe 5d142acb86 Merge pull request #1681 from BishopFox/1c54dependabot/go_modules/golang.org/x/net-0.25.0
Bump golang.org/x/net from 0.24.0 to 0.25.0
2024-05-16 14:43:36 -05:00
Raf 0ee50c3150 Adding ID to certificates output, adjusting for narrow terms 2024-05-16 13:37:30 -04:00
Joe c0840eb9d6 Merge branch 'master' into 1c54dependabot/go_modules/golang.org/x/net-0.25.0 2024-05-16 10:54:09 -05:00
Joe 8b3e3cd6ab Merge pull request #1682 from BishopFox/5a34dependabot/go_modules/github.com/cheggaaa/pb/v3-3.1.5
Bump github.com/cheggaaa/pb/v3 from 3.1.2 to 3.1.5
2024-05-16 10:53:39 -05:00
Joe ffd2fa6e8b Merge pull request #1686 from BishopFox/fix-install-script
Fixing install script for Arch
2024-05-16 10:53:23 -05:00
Joe 130b5f9706 Merge pull request #1687 from BishopFox/v1.6.0/database-implant-table-fixes
Improving PostgreSQL Support
2024-05-16 10:53:06 -05:00
Raf 549a54cf4b Initial components of the certificates command
This commit adds a command (certificates) to the client that retrieves selected certificate information from the database.
2024-05-16 11:32:34 -04:00
Raf e2d11c40dd Fixed poor declaration of DB models for migration 2024-05-14 11:49:44 -04:00
Raf 9749cd8e58 Merge branch 'master' into v1.6.0/database-implant-table-fixes 2024-05-14 10:42:22 -04:00
Raf 4082378313 Adding nil check to listener deletion to prevent panic 2024-05-14 10:23:42 -04:00
Raf df65d7fe11 More thorough deletion of jobs from the DB when they are killed 2024-05-14 10:22:00 -04:00
Raf 99ce1cfb7a Fixing FK constraint while deleting profiles 2024-05-14 09:07:06 -04:00
Raf 5f2abac8d0 Database model fixes for non-SQLite databases, part 2
Changing implant generation without an associated profile to insert NULL into the database instead of the zero GUID
2024-05-13 15:43:04 -04:00
dependabot[bot] f265214006 Bump github.com/cheggaaa/pb/v3 from 3.1.2 to 3.1.5
Bumps [github.com/cheggaaa/pb/v3](https://github.com/cheggaaa/pb) from 3.1.2 to 3.1.5.
- [Commits](https://github.com/cheggaaa/pb/compare/v3.1.2...v3.1.5)

---
updated-dependencies:
- dependency-name: github.com/cheggaaa/pb/v3
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <[email protected]>
2024-05-13 17:14:40 +00:00
dependabot[bot] 23bdc7053d Bump golang.org/x/net from 0.24.0 to 0.25.0
Bumps [golang.org/x/net](https://github.com/golang/net) from 0.24.0 to 0.25.0.
- [Commits](https://github.com/golang/net/compare/v0.24.0...v0.25.0)

---
updated-dependencies:
- dependency-name: golang.org/x/net
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <[email protected]>
2024-05-13 17:14:34 +00:00
Joe 9510a5f0c1 Merge pull request #1685 from BishopFox/47b6dependabot/go_modules/google.golang.org/protobuf-1.34.1
Bump google.golang.org/protobuf from 1.34.0 to 1.34.1
2024-05-13 12:13:32 -05:00
Joe 72ea11790f Merge pull request #1683 from BishopFox/e97ddependabot/go_modules/golang.org/x/crypto-0.23.0
Bump golang.org/x/crypto from 0.22.0 to 0.23.0
2024-05-13 12:13:19 -05:00
Raf d651e0888f Database model fixes for non-SQLite databases, part 1
Changing database migrations to occur in sequence instead of all at once for more accurate error reporting in the log
Changing HostUUID in the models.Host struct to be unique to fix a constraint issue
Changing models.HttpC2Header to contain pointers to ServerConfigIDs and ImplantConfigIDs so that NULL values can be inserted into the database when a type of config does not apply.
2024-05-13 12:55:53 -04:00
Raf f2bb628883 Fixing install script for Arch 2024-05-13 09:15:20 -04:00
dependabot[bot] 8e5ff45306 Bump google.golang.org/protobuf from 1.34.0 to 1.34.1
Bumps google.golang.org/protobuf from 1.34.0 to 1.34.1.

---
updated-dependencies:
- dependency-name: google.golang.org/protobuf
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <[email protected]>
2024-05-13 08:03:08 +00:00
Ronan Kervella 9dbd5a1c92 Merge branch 'master' into e97ddependabot/go_modules/golang.org/x/crypto-0.23.0 2024-05-13 10:02:18 +02:00
Ronan Kervella 6115702268 Merge pull request #1684 from BishopFox/527ddependabot/go_modules/modernc.org/sqlite-1.29.9
Bump modernc.org/sqlite from 1.29.8 to 1.29.9
2024-05-13 10:01:48 +02:00
dependabot[bot] ed1739c8d2 Bump modernc.org/sqlite from 1.29.8 to 1.29.9
Bumps [modernc.org/sqlite](https://gitlab.com/cznic/sqlite) from 1.29.8 to 1.29.9.
- [Commits](https://gitlab.com/cznic/sqlite/compare/v1.29.8...v1.29.9)

---
updated-dependencies:
- dependency-name: modernc.org/sqlite
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <[email protected]>
2024-05-13 03:08:40 +00:00
dependabot[bot] 88da1fe868 Bump golang.org/x/crypto from 0.22.0 to 0.23.0
Bumps [golang.org/x/crypto](https://github.com/golang/crypto) from 0.22.0 to 0.23.0.
- [Commits](https://github.com/golang/crypto/compare/v0.22.0...v0.23.0)

---
updated-dependencies:
- dependency-name: golang.org/x/crypto
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <[email protected]>
2024-05-13 03:08:17 +00:00
Joe b520eaf6e6 Merge pull request #1679 from BishopFox/v1.6.0/fix-console-hang
Fix #1668
2024-05-10 09:31:13 -05:00
rkervella 635086364e Fix #1668 2024-05-10 11:46:31 +02:00
Ronan Kervella 4bfdb7bcee Merge pull request #1676 from BishopFox/v1.6.0/package-output
New Output Handler for Extensions and Aliases
2024-05-08 09:46:49 +02:00
Ronan Kervella 7e4ba5d3e7 Merge branch 'master' into v1.6.0/package-output 2024-05-07 17:20:47 +02:00
Ronan Kervella c642bfcacb Merge pull request #1675 from BishopFox/xforwardedfor_fix
extract original host ip if forwarded by one or more hosts
2024-05-07 17:20:17 +02:00
Timothy Makram Ghatas a424412edd Merge branch 'master' into xforwardedfor_fix 2024-05-07 15:34:08 +02:00
Raf 4d15774c9b Merge branch 'master' into v1.6.0/package-output 2024-05-07 09:05:14 -04:00
Raf 51c45a48e8 Adding error handling for bad ingestion 2024-05-07 09:04:55 -04:00
Tim Makram Ghatas 94f01c8230 added default case if only one forwarding ip exists 2024-05-07 14:41:51 +02:00
Raf 0307bf16eb Adding a new output handler for extensions and aliases that deserializes JSON output into tables 2024-05-07 08:30:17 -04:00
Tim Makram Ghatas 1a73128163 extract original host ip if forwarded by one or more hosts 2024-05-07 12:31:01 +02:00
Joe eff371f6b7 Merge pull request #1671 from BishopFox/d2cbdependabot/go_modules/github.com/stretchr/testify-1.9.0
Bump github.com/stretchr/testify from 1.8.4 to 1.9.0
2024-05-06 10:37:28 -05:00
Joe 3a48d8480e Merge pull request #1674 from BishopFox/f9f5dependabot/go_modules/golang.org/x/text-0.15.0
Bump golang.org/x/text from 0.14.0 to 0.15.0
2024-05-06 10:37:16 -05:00
Joe 5cd83392e0 Merge pull request #1672 from BishopFox/7227dependabot/go_modules/github.com/glebarez/sqlite-1.11.0
Bump github.com/glebarez/sqlite from 1.10.0 to 1.11.0
2024-05-06 10:37:06 -05:00
Joe fffaca3945 Merge pull request #1670 from BishopFox/7890dependabot/go_modules/github.com/ncruces/go-sqlite3-0.15.0
Bump github.com/ncruces/go-sqlite3 from 0.7.2 to 0.15.0
2024-05-06 10:36:54 -05:00
dependabot[bot] fae797eff0 Bump github.com/ncruces/go-sqlite3 from 0.7.2 to 0.15.0
Bumps [github.com/ncruces/go-sqlite3](https://github.com/ncruces/go-sqlite3) from 0.7.2 to 0.15.0.
- [Release notes](https://github.com/ncruces/go-sqlite3/releases)
- [Commits](https://github.com/ncruces/go-sqlite3/compare/v0.7.2...v0.15.0)

---
updated-dependencies:
- dependency-name: github.com/ncruces/go-sqlite3
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <[email protected]>
2024-05-06 08:14:52 +00:00
dependabot[bot] 64a7095f5f Bump github.com/stretchr/testify from 1.8.4 to 1.9.0
Bumps [github.com/stretchr/testify](https://github.com/stretchr/testify) from 1.8.4 to 1.9.0.
- [Release notes](https://github.com/stretchr/testify/releases)
- [Commits](https://github.com/stretchr/testify/compare/v1.8.4...v1.9.0)

---
updated-dependencies:
- dependency-name: github.com/stretchr/testify
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <[email protected]>
2024-05-06 08:13:52 +00:00
dependabot[bot] 82909ad1d9 Bump github.com/glebarez/sqlite from 1.10.0 to 1.11.0
Bumps [github.com/glebarez/sqlite](https://github.com/glebarez/sqlite) from 1.10.0 to 1.11.0.
- [Release notes](https://github.com/glebarez/sqlite/releases)
- [Commits](https://github.com/glebarez/sqlite/compare/v1.10.0...v1.11.0)

---
updated-dependencies:
- dependency-name: github.com/glebarez/sqlite
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <[email protected]>
2024-05-06 08:13:37 +00:00
Ronan Kervella e2e9bc18dc Merge branch 'master' into f9f5dependabot/go_modules/golang.org/x/text-0.15.0 2024-05-06 01:12:43 -07:00
Ronan Kervella 5bed9d4e90 Merge pull request #1673 from BishopFox/c6e8dependabot/go_modules/github.com/jedib0t/go-pretty/v6-6.5.9
Bump github.com/jedib0t/go-pretty/v6 from 6.5.8 to 6.5.9
2024-05-06 01:12:20 -07:00
dependabot[bot] 60e87f9e08 Bump golang.org/x/text from 0.14.0 to 0.15.0
Bumps [golang.org/x/text](https://github.com/golang/text) from 0.14.0 to 0.15.0.
- [Release notes](https://github.com/golang/text/releases)
- [Commits](https://github.com/golang/text/compare/v0.14.0...v0.15.0)

---
updated-dependencies:
- dependency-name: golang.org/x/text
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <[email protected]>
2024-05-06 03:45:35 +00:00
dependabot[bot] d4c37f45d2 Bump github.com/jedib0t/go-pretty/v6 from 6.5.8 to 6.5.9
Bumps [github.com/jedib0t/go-pretty/v6](https://github.com/jedib0t/go-pretty) from 6.5.8 to 6.5.9.
- [Release notes](https://github.com/jedib0t/go-pretty/releases)
- [Commits](https://github.com/jedib0t/go-pretty/compare/v6.5.8...v6.5.9)

---
updated-dependencies:
- dependency-name: github.com/jedib0t/go-pretty/v6
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <[email protected]>
2024-05-06 03:45:25 +00:00
Joe 79d22bafbf Merge pull request #1669 from ngn13/wg-config-fix
fix: add missing newline
2024-05-05 10:56:55 -05:00
ngn 6396a64878 add missing newline
Signed-off-by: ngn <[email protected]>
2024-05-04 23:41:34 +00:00
Tim Makram Ghatas fb1e59ef5a update http payload staging tutorial 2024-05-04 09:48:46 +02:00
Joe 335797e661 Merge pull request #1667 from BishopFox/docs/community-guides
Docs/community guides
2024-05-03 21:13:39 -05:00
moloch-- d767bd019c Add youtube embed component 2024-05-03 19:13:02 -07:00
moloch-- 590f9c3f96 Add youtube embed component 2024-05-03 18:59:42 -07:00
Joe cff899aa49 Merge pull request #1646 from testwill/close_resource
fix: close resource
2024-05-03 12:17:46 -05:00
Joe ca2dc9d267 Merge pull request #1665 from BishopFox/c2profile_update_bugfix
C2profile update bugfix
2024-05-03 12:17:19 -05:00
Ronan Kervella afdd77c642 Merge branch 'master' into close_resource 2024-05-03 09:21:54 -07:00
Ronan Kervella 8a5970c3da Merge branch 'master' into c2profile_update_bugfix 2024-05-03 09:21:40 -07:00
Ronan Kervella 2eb2ac8121 Merge pull request #1659 from C-Sto/bugfix-extensions
fix extension registration, run, and load flows
2024-05-03 09:21:29 -07:00
Ronan Kervella daf7d404b1 Merge branch 'master' into c2profile_update_bugfix 2024-05-03 09:21:23 -07:00
Ronan Kervella 3b308920f4 Merge branch 'master' into close_resource 2024-05-03 08:34:23 -07:00
Ronan Kervella c73b183f74 Merge branch 'master' into bugfix-extensions 2024-05-03 08:32:44 -07:00
Ronan Kervella 7564312f5e Merge pull request #1666 from BishopFox/v1.6.0/fix-alias-hostproc
Fix Default Linux Host Process for Aliases
2024-05-03 08:32:22 -07:00
Raf 6134b78afb Fix default linux host process for aliases 2024-05-03 08:24:32 -04:00
Tim Makram Ghatas a1318f1061 Merge branch 'master' into wiki_1.6_update 2024-05-03 10:39:03 +02:00
Ronan Kervella 3db9946608 Merge branch 'master' into bugfix-extensions 2024-05-02 14:11:02 -07:00
Joe ef09058498 Merge pull request #1664 from BishopFox/v1.6.0/ls-rootdir
Adding root directory entry to `ls` command
2024-05-02 16:06:46 -05:00
Tim Makram Ghatas 9543951747 update http payload staging wiki 2024-05-02 23:02:28 +02:00
Tim Makram Ghatas 331faeb8ef fix commandline paramameters for profile staging 2024-05-02 20:30:33 +02:00
Tim Makram Ghatas 0926339482 update http staging wiki page 2024-05-02 20:10:59 +02:00
Tim Makram Ghatas 4ae195e3eb fix c2 profile update issue with headers, cookies and segments 2024-05-02 19:09:46 +02:00
Ronan Kervella f8f8ba5864 Merge branch 'master' into bugfix-extensions 2024-05-02 09:59:25 -07:00
Tim Makram Ghatas 7f60e133dc update tutorial first three chapters with asciinema and fix markdown loading issue 2024-05-02 18:58:09 +02:00
Raf 216e3b9759 Adds an entry in the directory listing returned by ls for the root directory ('.'). 2024-05-02 12:12:32 -04:00
Tim Makram Ghatas ba3893980d Merge branch 'master' into wiki_1.6_update 2024-05-02 09:25:13 +02:00
Tim Makram Ghatas 363f59d276 Add first draft tutorial draft for 1.6 2024-05-02 09:21:29 +02:00
Joe f1bc5074f9 Merge pull request #1663 from BishopFox/docs/compile-from-source
Add to index
2024-05-01 21:40:10 -05:00
moloch-- 5083faa1e1 Add to index 2024-05-01 19:39:34 -07:00
Joe 1b5d3436eb Merge pull request #1662 from BishopFox/docs/compile-from-source
Improve compile from source docs
2024-05-01 21:23:20 -05:00
moloch-- 56303eb89a Improve compile from source docs 2024-05-01 19:22:57 -07:00
Joe 9397fcb4ae Merge pull request #1661 from BishopFox/fix_stage_encoder
fix merge error for stage encoders
2024-05-01 20:11:35 -05:00
Joe 04c6c3f800 Merge pull request #1658 from C-Sto/bugfix-extensionnoargs
fix: handle noargs case
2024-05-01 20:08:17 -05:00
C-Sto 7842a6c4c6 add init back in, handle nils/zero values more elegantly 2024-05-02 08:49:21 +08:00
Tim Makram Ghatas 6c815a4432 fix merge error for stage encoders 2024-05-02 02:06:54 +02:00
C-Sto 81358e31bb fix extension registration, run, and load flows 2024-05-01 12:31:19 +08:00
C-Sto 7bea772dbd fix: handle noargs case 2024-05-01 12:15:33 +08:00
Joe 0b235b4d42 Merge pull request #1656 from BishopFox/fix/deps
Update Various Server and Implant Dependencies
2024-04-30 16:33:11 -07:00
moloch-- 1402a75b18 Update implant deps 2024-04-30 15:26:16 -07:00
moloch-- ff5e4a4a24 Update implant deps 2024-04-30 15:26:02 -07:00
moloch-- e59c90c89a Update wireguard 2024-04-30 15:21:03 -07:00
moloch-- 49771f0159 Update binject deps 2024-04-30 15:05:46 -07:00
moloch-- a2808b19f6 Update binject deps 2024-04-30 15:05:40 -07:00
Joe eddfb7073c Merge pull request #1655 from BishopFox/fix/init-logging
Fix/init logging
2024-04-30 14:58:00 -07:00
moloch-- 930799495c Update various deps 2024-04-30 14:49:40 -07:00
moloch-- 5016fb8d7c Update wazero 2024-04-30 14:34:59 -07:00
moloch-- 65382f7b77 Update wazero 2024-04-30 14:34:52 -07:00
moloch-- c1d00f0e48 Update gorm, etc 2024-04-30 14:34:17 -07:00
moloch-- e89280d64a Update modernc.org/sqlite 2024-04-30 14:20:24 -07:00
moloch-- aa4c9d7b8a Update tailscale 2024-04-30 14:09:05 -07:00
moloch-- 2be820daf1 Update tailscale 2024-04-30 14:08:55 -07:00
moloch-- 0a44fde9fa Linter fixes 2024-04-30 13:39:06 -07:00
moloch-- 151dfe2643 Fix nil err logging on client start 2024-04-30 13:25:37 -07:00
Joe fa7033f0c4 Merge pull request #1654 from BishopFox/tests/zig-docker
Remove docker platform specification
2024-04-30 08:07:16 -07:00
moloch-- 4eab1b582a Correct comment 2024-04-29 21:03:24 -07:00
moloch-- f78db1a825 Remove docker platform specification 2024-04-29 20:58:28 -07:00
Joe eb61740f5d Merge pull request #1653 from BishopFox/tests/zig-updates
Expand unit tests for better arm64 coverage
2024-04-29 20:32:16 -07:00
moloch-- 39d0f3b838 Expand unit tests for better arm64 coverage 2024-04-29 19:13:48 -07:00
Joe 8f084c99a4 Merge pull request #1651 from BishopFox/3139dependabot/go_modules/golang.org/x/net-0.24.0
Bump golang.org/x/net from 0.23.0 to 0.24.0
2024-04-29 17:36:46 -07:00
dependabot[bot] 87720d8a41 Bump golang.org/x/net from 0.23.0 to 0.24.0
Bumps [golang.org/x/net](https://github.com/golang/net) from 0.23.0 to 0.24.0.
- [Commits](https://github.com/golang/net/compare/v0.23.0...v0.24.0)

---
updated-dependencies:
- dependency-name: golang.org/x/net
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <[email protected]>
2024-04-29 23:51:46 +00:00
Joe f8dd5230c1 Merge pull request #1652 from BishopFox/zig
Embedded Zig Cross-Compiler
2024-04-29 16:50:21 -07:00
moloch-- 9296a8abce Remove mingw env vars from unit test workflow 2024-04-29 16:10:01 -07:00
moloch-- abc8747a51 Remove mingw from docker, cleanup util 2024-04-29 15:41:40 -07:00
moloch-- dcbfe10bc4 Cleanup commands 2024-04-29 14:51:08 -07:00
moloch-- 4336f933e0 Unit tests passing 2024-04-29 14:42:37 -07:00
moloch-- 6a4521a4b0 Add zig as default cc/cxx except for macos, add cc/cxx to server config 2024-04-29 13:46:19 -07:00
moloch-- bf80f8f7e6 Fix unobfuscated builds 2024-04-29 09:16:01 -07:00
Joe 174455cbcc Merge pull request #1648 from BishopFox/go/v1.22.2
Go 1.22.2
2024-04-29 09:07:32 -07:00
moloch-- 09564cf241 Added more tar validation 2024-04-28 22:41:53 -07:00
moloch-- 03fa4029d3 Add zig to go-assets script 2024-04-28 22:34:49 -07:00
moloch-- b33e012f2a Basic zig cc implementation 2024-04-28 21:19:41 -07:00
moloch-- 98f13030f9 Go 1.22.2 2024-04-28 20:00:32 -07:00
Joe 040863b757 Merge pull request #1645 from BishopFox/fix/dnspb
Tweak builder
2024-04-26 09:29:49 -07:00
guangwu 7fe0b295f5 fix: close resource
Signed-off-by: guangwu <[email protected]>
2024-04-25 20:54:30 +08:00
Joe 1624c84eb6 Merge branch 'master' into fix/dnspb
Signed-off-by: Joe <[email protected]>
2024-04-24 15:23:23 -07:00
Joe 44368b26ad Merge pull request #1644 from BishopFox/fix/sideload-spaces
Fix bug in `sideload`, `execute-assembly` and `spawndll`` where spaces were removed in command line arguments
2024-04-24 15:22:37 -07:00
moloch-- 0eb93d51c0 Tweak builder pb 2024-04-24 16:52:58 -05:00
Ronan Kervella c7cd14eae2 Merge pull request #1627 from BishopFox/54b2dependabot/go_modules/github.com/jedib0t/go-pretty/v6-6.5.8
Bump github.com/jedib0t/go-pretty/v6 from 6.4.6 to 6.5.8
2024-04-23 15:19:25 -07:00
Ronan Kervella 9c9caba8d8 Merge branch 'master' into fix/sideload-spaces 2024-04-23 11:53:50 -07:00
rkervella 4b6219d860 Fix #1598 2024-04-23 11:49:54 -07:00
Ronan Kervella a47aeb7e73 Merge pull request #1643 from BishopFox/remove-prelude
Remove prelude operator support
2024-04-23 11:49:29 -07:00
Ronan Kervella d3255ec7bb Merge branch 'master' into remove-prelude 2024-04-23 11:02:49 -07:00
Ronan Kervella 4c0e6cb585 Merge branch 'master' into 54b2dependabot/go_modules/github.com/jedib0t/go-pretty/v6-6.5.8 2024-04-23 10:49:03 -07:00
Ronan Kervella 88e35469b8 Merge pull request #1630 from BishopFox/8c63dependabot/go_modules/github.com/klauspost/compress-1.17.8
Bump github.com/klauspost/compress from 1.17.0 to 1.17.8
2024-04-23 10:48:49 -07:00
Ronan Kervella cd711c1e2f Merge branch 'master' into 54b2dependabot/go_modules/github.com/jedib0t/go-pretty/v6-6.5.8 2024-04-23 10:15:22 -07:00
rkervella 723eca2ddd Remove prelude operator support 2024-04-23 10:14:37 -07:00
Ronan Kervella 0b2e0fa9bc Merge branch 'master' into 8c63dependabot/go_modules/github.com/klauspost/compress-1.17.8 2024-04-23 09:49:42 -07:00
Joe 9135afd201 Merge pull request #1639 from BishopFox/4cd6dependabot/go_modules/golang.org/x/net-0.23.0
Bump golang.org/x/net from 0.21.0 to 0.23.0
2024-04-23 09:31:14 -07:00
Joe b3a9ba86e1 Merge pull request #1566 from BishopFox/ff34dependabot/github_actions/actions/cache-4
Bump actions/cache from 3 to 4
2024-04-23 09:23:12 -07:00
Ronan Kervella 2211b13c31 Merge branch 'master' into 4cd6dependabot/go_modules/golang.org/x/net-0.23.0 2024-04-23 08:33:04 -07:00
Ronan Kervella 187394439e Merge branch 'master' into 54b2dependabot/go_modules/github.com/jedib0t/go-pretty/v6-6.5.8 2024-04-23 08:32:47 -07:00
Ronan Kervella 3b767baca3 Merge branch 'master' into 8c63dependabot/go_modules/github.com/klauspost/compress-1.17.8 2024-04-23 08:32:11 -07:00
Ronan Kervella c1070f917f Merge pull request #1637 from C-Sto/bugfix-windowsuseragent
fix useragent variable in implant generation
2024-04-23 08:31:48 -07:00
Ronan Kervella 5487df2000 Merge branch 'master' into bugfix-windowsuseragent 2024-04-22 15:08:50 -07:00
Ronan Kervella 97497c9f78 Merge pull request #1562 from BishopFox/v1.6.0/fix-procdump
Fix procdump (bis)
2024-04-22 15:08:35 -07:00
Ronan Kervella ee36676ba2 Merge branch 'master' into 4cd6dependabot/go_modules/golang.org/x/net-0.23.0 2024-04-22 13:06:01 -07:00
rkervella 6809d81b66 Merge branch 'v1.6.0/fix-procdump' of bishopfox.github.com:BishopFox/sliver into v1.6.0/fix-procdump 2024-04-22 13:01:57 -07:00
rkervella 6b876b0a0e Fix procdump, use a sync.Map instead of a shared
byte slice.
2024-04-22 13:01:39 -07:00
Ronan Kervella 33ab6096f1 Merge branch 'master' into bugfix-windowsuseragent 2024-04-22 11:10:06 -07:00
Ronan Kervella 0a6636fb71 Merge branch 'master' into v1.6.0/fix-procdump 2024-04-22 11:09:48 -07:00
Ronan Kervella 6a30b8a99a Merge pull request #1634 from C-Sto/bugfix-execwindows
check session mode correctly in windows exec
2024-04-22 11:09:38 -07:00
Ronan Kervella a3c353baf7 Merge branch 'master' into bugfix-execwindows 2024-04-19 11:40:30 -07:00
Ronan Kervella 5e992e073e Merge pull request #1635 from C-Sto/bugfix-overwrite
add overwrite flag back into upload cmd
2024-04-19 10:47:42 -07:00
rkervella 12d2569c2f Merge branch 'master' into v1.6.0/fix-procdump 2024-04-19 10:16:27 -07:00
Ronan Kervella 1abda712c4 Merge branch 'master' into 4cd6dependabot/go_modules/golang.org/x/net-0.23.0 2024-04-19 10:10:43 -07:00
Ronan Kervella 6dc49f5074 Merge branch 'master' into bugfix-windowsuseragent 2024-04-19 10:09:27 -07:00
Ronan Kervella 2eff697a50 Merge branch 'master' into bugfix-execwindows 2024-04-19 10:07:06 -07:00
Ronan Kervella 143246a9fc Merge branch 'master' into 54b2dependabot/go_modules/github.com/jedib0t/go-pretty/v6-6.5.8 2024-04-19 10:06:52 -07:00
Ronan Kervella ab80379e5e Merge branch 'master' into bugfix-overwrite 2024-04-19 09:47:31 -07:00
Ronan Kervella d8e400f005 Merge pull request #1636 from C-Sto/bugfix-infosession
add session command back to implant context
2024-04-19 09:47:21 -07:00
dependabot[bot] a4cc570845 Bump golang.org/x/net from 0.21.0 to 0.23.0
Bumps [golang.org/x/net](https://github.com/golang/net) from 0.21.0 to 0.23.0.
- [Commits](https://github.com/golang/net/compare/v0.21.0...v0.23.0)

---
updated-dependencies:
- dependency-name: golang.org/x/net
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <[email protected]>
2024-04-19 13:16:44 +00:00
Ronan Kervella 0072335cc0 Merge branch 'master' into bugfix-infosession 2024-04-18 10:55:14 -07:00
Ronan Kervella 6bccd35318 Merge pull request #1633 from BishopFox/v1.6.0/private-armories
Support for Self-Hosted Armories and Armory Fixes
2024-04-18 10:54:59 -07:00
Ronan Kervella f37bed31c0 Merge branch 'master' into v1.6.0/private-armories 2024-04-18 10:26:33 -07:00
Ronan Kervella dac592d231 Merge branch 'master' into bugfix-infosession 2024-04-18 08:36:00 -07:00
Ronan Kervella f98ae8e7fe Merge pull request #1638 from C-Sto/feature-extensionsident
use filehash for extension ref instead of command name
2024-04-18 08:35:45 -07:00
Raf 026c1d6ef6 Merge branch 'v1.6.0/private-armories' of ssh://github.com/BishopFox/sliver into v1.6.0/private-armories 2024-04-18 09:44:30 -04:00
Raf 4b982f422f Adding armory choice to install and update commands 2024-04-18 09:44:13 -04:00
dependabot[bot] c2f5460c63 Bump github.com/fatih/color from 1.15.0 to 1.16.0
Bumps [github.com/fatih/color](https://github.com/fatih/color) from 1.15.0 to 1.16.0.
- [Release notes](https://github.com/fatih/color/releases)
- [Commits](https://github.com/fatih/color/compare/v1.15.0...v1.16.0)

---
updated-dependencies:
- dependency-name: github.com/fatih/color
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <[email protected]>
2024-04-18 09:44:13 -04:00
Tim Makram Ghatas 214143e9d9 add export command for c2 profiles 2024-04-18 09:44:13 -04:00
Tim Makram Ghatas 2607a021d8 re-add deleted commands from bad merge 2024-04-18 09:44:13 -04:00
dependabot[bot] e474dc452f Bump actions/configure-pages from 4 to 5
Bumps [actions/configure-pages](https://github.com/actions/configure-pages) from 4 to 5.
- [Release notes](https://github.com/actions/configure-pages/releases)
- [Commits](https://github.com/actions/configure-pages/compare/v4...v5)

---
updated-dependencies:
- dependency-name: actions/configure-pages
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <[email protected]>
2024-04-18 09:44:13 -04:00
Raf c28e8e1e0f Add nosave option to armory add, armory modify 2024-04-18 09:44:13 -04:00
Raf 7b2822795c Add nosave option to armory add, armory modify 2024-04-18 09:44:13 -04:00
Raf cc5f162848 Added armory reset command 2024-04-18 09:44:13 -04:00
Raf 83b6bf9147 armory update range processing fixes 2024-04-18 09:44:13 -04:00
Raf 79202297df Limit concurrent requests to armories
Addresses #1401

Placing a limit of 10 concurrent requests for fetching resources
(indexes, package signatures) from armories. Also checking for a nil
response when downloading from GitHub to prevent a panic.
2024-04-18 09:44:13 -04:00
Raf cd4e967cd9 Changes to the package update process
armory update now prints a table of updates and allows the user to choose the updates they want to perform.
Refined dependency resolution so that it considers packages that are
pending install
Re-did the fix for the client continuously asking to overwrite packages
when installing bundles
Added a force option to the install command
2024-04-18 09:44:13 -04:00
Raf ea901f5442 Fixing a potential nil pointer dereference 2024-04-18 09:44:13 -04:00
Raf a5cd0d0cae Ensured cache consistency on index changes
If a package is deleted from the index, the cache was not subsequently
updated.
2024-04-18 09:44:13 -04:00
Raf e9930d01fd Initial support for self-hosted armories
Changes that allow for multiple armories, including commands for
managing armories, dependency resolution, and deconfliction.

There is still more work to be done, including refactoring,
simplification, and getting rid of bugs.
2024-04-18 09:44:13 -04:00
rkervella f83131ef43 Fix hang when calling generate stager 2024-04-18 09:44:13 -04:00
dependabot[bot] 73d5c3192d Bump golang.org/x/crypto from 0.17.0 to 0.21.0
Bumps [golang.org/x/crypto](https://github.com/golang/crypto) from 0.17.0 to 0.21.0.
- [Commits](https://github.com/golang/crypto/compare/v0.17.0...v0.21.0)

---
updated-dependencies:
- dependency-name: golang.org/x/crypto
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <[email protected]>
2024-04-18 09:44:13 -04:00
dependabot[bot] 076db57bba Bump google.golang.org/protobuf from 1.31.0 to 1.33.0
Bumps google.golang.org/protobuf from 1.31.0 to 1.33.0.

---
updated-dependencies:
- dependency-name: google.golang.org/protobuf
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <[email protected]>
2024-04-18 09:44:13 -04:00
dependabot[bot] db85a76c85 Bump github.com/jackc/pgx/v5 from 5.3.1 to 5.5.4
Bumps [github.com/jackc/pgx/v5](https://github.com/jackc/pgx) from 5.3.1 to 5.5.4.
- [Changelog](https://github.com/jackc/pgx/blob/master/CHANGELOG.md)
- [Commits](https://github.com/jackc/pgx/compare/v5.3.1...v5.5.4)

---
updated-dependencies:
- dependency-name: github.com/jackc/pgx/v5
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <[email protected]>
2024-04-18 09:44:13 -04:00
Andrew Klaus 662c1c1e18 Adding namespace support to Linux ifconfig 2024-04-18 09:44:13 -04:00
Andrew Klaus 5634b09921 Testing fix for Windows implant 2024-04-18 09:44:13 -04:00
Andrew Klaus f8c8cdfe31 Updating protobufs 2024-04-18 09:44:13 -04:00
Andrew Klaus cabe48e997 Adding linux mount command 2024-04-18 09:44:13 -04:00
Raf cabb1b09cc Adding the mount command and the implementation for Windows implants 2024-04-18 09:44:13 -04:00
moloch-- 3bb667f814 Remove prelude operator support, since product is discontinued 2024-04-18 09:44:13 -04:00
moloch-- 6cb1ffbe4e Go 1.22.1 2024-04-18 09:44:13 -04:00
moloch-- dba5ba5767 Fix link in docs 2024-04-18 09:44:13 -04:00
moloch-- 65a7730bf4 Fix link in docs 2024-04-18 09:44:13 -04:00
xl4sh e17c363381 Fix using duplicated envelope id bug 2024-04-18 09:44:13 -04:00
gatari 454ffd7bcd Update make-token.go
Signed-off-by: gatari <[email protected]>
2024-04-18 09:44:13 -04:00
kmathisbf be75b1557c Add elastic binaries to knownSecurityTools 2024-04-18 09:44:12 -04:00
Raf d12d2fb792 Adding armory choice to install and update commands 2024-04-18 09:43:03 -04:00
Ronan Kervella 4debb053bd Merge branch 'master' into v1.6.0/private-armories 2024-04-17 19:07:41 -07:00
C-Sto d45a62867f use filehash for extension ref instead of command name 2024-04-18 09:05:17 +08:00
C-Sto 32c7e02f09 fix useragent variable 2024-04-18 08:56:49 +08:00
C-Sto e0ba712631 add session command back to implant context 2024-04-18 08:52:54 +08:00
C-Sto fd17c4ed20 add overwrite flag back into upload cmd 2024-04-18 08:50:13 +08:00
C-Sto 76eb06e6b9 check session mode correctly in windows exec 2024-04-18 08:46:02 +08:00
dependabot[bot] 7a7f169e0a Bump github.com/jedib0t/go-pretty/v6 from 6.4.6 to 6.5.8
Bumps [github.com/jedib0t/go-pretty/v6](https://github.com/jedib0t/go-pretty) from 6.4.6 to 6.5.8.
- [Release notes](https://github.com/jedib0t/go-pretty/releases)
- [Commits](https://github.com/jedib0t/go-pretty/compare/v6.4.6...v6.5.8)

---
updated-dependencies:
- dependency-name: github.com/jedib0t/go-pretty/v6
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <[email protected]>
2024-04-17 16:16:28 +00:00
Ronan Kervella 61090be973 Merge branch 'master' into ff34dependabot/github_actions/actions/cache-4 2024-04-17 09:16:18 -07:00
dependabot[bot] a0360fac17 Bump github.com/klauspost/compress from 1.17.0 to 1.17.8
Bumps [github.com/klauspost/compress](https://github.com/klauspost/compress) from 1.17.0 to 1.17.8.
- [Release notes](https://github.com/klauspost/compress/releases)
- [Changelog](https://github.com/klauspost/compress/blob/master/.goreleaser.yml)
- [Commits](https://github.com/klauspost/compress/compare/v1.17.0...v1.17.8)

---
updated-dependencies:
- dependency-name: github.com/klauspost/compress
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <[email protected]>
2024-04-17 16:15:43 +00:00
Ronan Kervella 61210acff0 Merge pull request #1621 from BishopFox/9192dependabot/go_modules/github.com/fatih/color-1.16.0
Bump github.com/fatih/color from 1.15.0 to 1.16.0
2024-04-17 09:14:17 -07:00
Ronan Kervella eca785a99a Merge branch 'master' into v1.6.0/private-armories 2024-04-17 08:46:48 -07:00
Raf 0b9442d2b8 Add nosave option to armory add, armory modify 2024-04-17 11:42:05 -04:00
Raf b6a24b0ab2 Add nosave option to armory add, armory modify 2024-04-17 11:39:21 -04:00
Raf 9f43f73350 Added armory reset command 2024-04-17 11:29:23 -04:00
Ronan Kervella d6ccb0044c Merge branch 'master' into 9192dependabot/go_modules/github.com/fatih/color-1.16.0 2024-04-17 08:25:31 -07:00
Raf 5d13415770 armory update range processing fixes 2024-04-17 10:56:22 -04:00
Raf f4c72d5216 Limit concurrent requests to armories
Addresses #1401

Placing a limit of 10 concurrent requests for fetching resources
(indexes, package signatures) from armories. Also checking for a nil
response when downloading from GitHub to prevent a panic.
2024-04-04 08:36:21 -04:00
Joe bb28d796a4 Merge pull request #1623 from BishopFox/export_c2profiles
add export command for c2 profiles
2024-04-02 15:04:01 -07:00
Tim Makram Ghatas f0b078bcd1 add export command for c2 profiles 2024-04-02 22:28:47 +02:00
Raf e926f1b954 Changes to the package update process
armory update now prints a table of updates and allows the user to choose the updates they want to perform.
Refined dependency resolution so that it considers packages that are
pending install
Re-did the fix for the client continuously asking to overwrite packages
when installing bundles
Added a force option to the install command
2024-04-02 13:20:07 -04:00
Ronan Kervella 9f4988e12a Merge pull request #1622 from BishopFox/bugfix_merge_issue
re-add deleted commands from bad merge for c2profiles and implant staging
2024-04-02 10:11:07 -07:00
Tim Makram Ghatas 124c12bebd re-add deleted commands from bad merge 2024-04-02 18:06:18 +02:00
Raf 84acde7db0 Fixing a potential nil pointer dereference 2024-04-01 11:24:20 -04:00
Joe 142bf83ffd Merge pull request #1620 from BishopFox/77cedependabot/github_actions/actions/configure-pages-5
Bump actions/configure-pages from 4 to 5
2024-04-01 06:49:08 -07:00
dependabot[bot] 30587f6e8f Bump github.com/fatih/color from 1.15.0 to 1.16.0
Bumps [github.com/fatih/color](https://github.com/fatih/color) from 1.15.0 to 1.16.0.
- [Release notes](https://github.com/fatih/color/releases)
- [Commits](https://github.com/fatih/color/compare/v1.15.0...v1.16.0)

---
updated-dependencies:
- dependency-name: github.com/fatih/color
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <[email protected]>
2024-04-01 04:58:31 +00:00
dependabot[bot] b290474e5d Bump actions/configure-pages from 4 to 5
Bumps [actions/configure-pages](https://github.com/actions/configure-pages) from 4 to 5.
- [Release notes](https://github.com/actions/configure-pages/releases)
- [Commits](https://github.com/actions/configure-pages/compare/v4...v5)

---
updated-dependencies:
- dependency-name: actions/configure-pages
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <[email protected]>
2024-04-01 03:28:25 +00:00
Raf de02d2fa6e Ensured cache consistency on index changes
If a package is deleted from the index, the cache was not subsequently
updated.
2024-03-29 10:24:56 -04:00
Raf b286aa979f Initial support for self-hosted armories
Changes that allow for multiple armories, including commands for
managing armories, dependency resolution, and deconfliction.

There is still more work to be done, including refactoring,
simplification, and getting rid of bugs.
2024-03-28 13:35:00 -04:00
Joe c18fc567a3 Merge pull request #1617 from BishopFox/fix-msf-stager
Fix hang when calling generate stager
2024-03-27 07:36:32 -07:00
rkervella 5bd1f4727c Fix hang when calling generate stager 2024-03-26 15:55:35 -07:00
Joe 619d4994da Merge pull request #1612 from BishopFox/c64bdependabot/go_modules/golang.org/x/crypto-0.21.0
Bump golang.org/x/crypto from 0.17.0 to 0.21.0
2024-03-26 06:55:33 -07:00
dependabot[bot] 1666d6f5ad Bump golang.org/x/crypto from 0.17.0 to 0.21.0
Bumps [golang.org/x/crypto](https://github.com/golang/crypto) from 0.17.0 to 0.21.0.
- [Commits](https://github.com/golang/crypto/compare/v0.17.0...v0.21.0)

---
updated-dependencies:
- dependency-name: golang.org/x/crypto
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <[email protected]>
2024-03-25 03:44:43 +00:00
Joe 6443aaba3d Merge pull request #1597 from BishopFox/48d6dependabot/go_modules/google.golang.org/protobuf-1.33.0
Bump google.golang.org/protobuf from 1.31.0 to 1.33.0
2024-03-19 10:21:19 -07:00
dependabot[bot] e14619fffc Bump google.golang.org/protobuf from 1.31.0 to 1.33.0
Bumps google.golang.org/protobuf from 1.31.0 to 1.33.0.

---
updated-dependencies:
- dependency-name: google.golang.org/protobuf
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <[email protected]>
2024-03-19 15:46:19 +00:00
Joe 07ec53e148 Merge pull request #1599 from BishopFox/88cbdependabot/go_modules/github.com/jackc/pgx/v5-5.5.4
Bump github.com/jackc/pgx/v5 from 5.3.1 to 5.5.4
2024-03-19 08:44:52 -07:00
dependabot[bot] 1c9d11f967 Bump github.com/jackc/pgx/v5 from 5.3.1 to 5.5.4
Bumps [github.com/jackc/pgx/v5](https://github.com/jackc/pgx) from 5.3.1 to 5.5.4.
- [Changelog](https://github.com/jackc/pgx/blob/master/CHANGELOG.md)
- [Commits](https://github.com/jackc/pgx/compare/v5.3.1...v5.5.4)

---
updated-dependencies:
- dependency-name: github.com/jackc/pgx/v5
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <[email protected]>
2024-03-14 22:01:41 +00:00
Ronan Kervella 2da1da7c40 Merge branch 'master' into v1.6.0/fix-procdump 2024-03-14 14:59:31 -07:00
Ronan Kervella 85b949a7df Merge pull request #1545 from precurse-bf/ifns
Adding Linux namespace support to ifconfig
2024-03-14 14:57:23 -07:00
Andrew Klaus 2c0d46278a Adding namespace support to Linux ifconfig 2024-03-14 12:01:25 -06:00
Ronan Kervella 74653968df Merge pull request #1596 from precurse-bf/mount_linux_rebase
Adding mount command for Windows and Linux
2024-03-14 09:44:16 -07:00
Andrew Klaus 49b55c7763 Testing fix for Windows implant 2024-03-14 10:07:24 -06:00
Ronan Kervella d02b38681c Merge branch 'master' into v1.6.0/fix-procdump 2024-03-13 15:23:54 -07:00
Andrew Klaus d625c8c2b7 Updating protobufs 2024-03-13 14:55:04 -06:00
Andrew Klaus 9f33e8103a Adding linux mount command 2024-03-13 14:55:04 -06:00
Raf abd375f501 Adding the mount command and the implementation for Windows implants 2024-03-13 14:24:19 -06:00
moloch-- 715c37addf Remove prelude operator support, since product is discontinued 2024-03-07 16:07:47 -08:00
Joe 754ce39076 Merge pull request #1592 from BishopFox/go/v1.22.1
Go 1.22.1
2024-03-07 16:47:15 -07:00
moloch-- 580f98419d Go 1.22.1 2024-03-07 15:10:30 -08:00
moloch-- c8a7948671 Fix link in docs 2024-02-29 10:14:02 -08:00
moloch-- 9da3112c04 Fix link in docs 2024-02-29 10:12:23 -08:00
Ronan Kervella 12ca498386 Merge pull request #1586 from xl4sh/fix/loopvar
Fix using duplicated envelope id bug
2024-02-29 08:33:38 -08:00
xl4sh 2f9c1857bb Fix using duplicated envelope id bug 2024-02-29 13:43:40 +09:00
Joe ac2ee6dfff Merge pull request #1585 from gatariee/master
Fix typo in `make-token` when no credentials are provided.
2024-02-27 07:54:34 -07:00
gatari bfde6a4dc8 Update make-token.go
Signed-off-by: gatari <[email protected]>
2024-02-27 21:06:50 +08:00
Ronan Kervella dc93d054a9 Merge pull request #1572 from BishopFox/v1.6.0/remove-legacy-DLL-extension-support
Removing support for legacy DLL extensions
2024-02-15 15:41:19 -08:00
Ronan Kervella 173366ba7d Merge branch 'master' into v1.6.0/remove-legacy-DLL-extension-support 2024-02-15 14:17:09 -08:00
Joe 4bfca79860 Merge pull request #1579 from BishopFox/ps_elastic
Add elastic binaries to knownSecurityTools
2024-02-06 17:06:50 -06:00
kmathisbf baa3659f20 Add elastic binaries to knownSecurityTools 2024-02-06 15:36:59 -05:00
Raf 59b2996862 Removing support for legacy DLL extensions 2024-01-30 08:42:34 -05:00
Ronan Kervella d0dc42ea2f Merge pull request #1568 from BishopFox/fix/download
Fix download RPC
2024-01-24 13:51:42 -08:00
Ronan Kervella 235c666b61 Merge branch 'master' into v1.6.0/fix-procdump 2024-01-24 10:35:01 -08:00
rkervella 12d6c13f4e Return error if file doesn't exist 2024-01-23 14:53:08 -08:00
dependabot[bot] a7befbe8a6 Bump actions/cache from 3 to 4
Bumps [actions/cache](https://github.com/actions/cache) from 3 to 4.
- [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/v3...v4)

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

Signed-off-by: dependabot[bot] <[email protected]>
2024-01-22 17:38:41 +00:00
Joe 0a31daf6ef Merge pull request #1515 from BishopFox/eea1dependabot/github_actions/github/codeql-action-3
Bump github/codeql-action from 2 to 3
2024-01-22 11:38:00 -06:00
Joe 34b97418b1 Merge pull request #1517 from BishopFox/deabdependabot/github_actions/actions/configure-pages-4
Bump actions/configure-pages from 3 to 4
2024-01-22 11:37:41 -06:00
rkervella 9baa1c0095 Merge branch 'v1.6.0/fix-procdump' of bishopfox.github.com:BishopFox/sliver into v1.6.0/fix-procdump 2024-01-18 14:07:35 -08:00
rkervella af27a2f0ec Update dump method. No more RtlCopyMemory and HeapAlloc. 2024-01-18 14:05:53 -08:00
Ronan Kervella 0c7cb4c566 Merge branch 'master' into v1.6.0/fix-procdump 2024-01-17 15:00:00 -08:00
rkervella bf3846ac30 Rework minidump callback. Ditch dynamic realloc and add a safety net buffer instead at initial allocation. 2024-01-17 14:56:47 -08:00
Ronan Kervella d9db5752c1 Merge pull request #1559 from BishopFox/windows-dumpkey
Adding the `registry read hive` command
2024-01-17 14:11:12 -08:00
rkervella 33b21778d0 Update vendor 2024-01-17 11:29:53 -08:00
Ronan Kervella 58916d47b9 Merge branch 'master' into windows-dumpkey 2024-01-17 09:57:48 -08:00
Ronan Kervella 49a095de44 Merge pull request #1560 from BishopFox/v1.6.0/fix-procdump
Fix procdump on Windows
2024-01-17 09:56:07 -08:00
Raf c9f5f0b122 registry read hive: removing support for running the command against a remote host due to limitations in the RegSaveKeyW API call 2024-01-17 12:31:03 -05:00
rkervella 942823bb1f Don't use global variable for buffer size 2024-01-17 09:23:58 -08:00
Raf 9cbca40e90 registry read hive: Making sure that the generated file name does not exist prior to the call to RegSaveKeyW 2024-01-17 12:18:01 -05:00
Raf fcbcef0472 Adding the registry read hive command for dumping the contents of a registry hive 2024-01-17 11:04:31 -05:00
Joe 3274631b04 Merge branch 'master' into eea1dependabot/github_actions/github/codeql-action-3 2024-01-16 14:53:18 -06:00
Ronan Kervella 310b844c64 Merge pull request #1557 from BishopFox/windows-services
Adding the `services` command
2024-01-15 11:50:08 -08:00
Raf f50a1ed243 services: Moving strings from implant to client, renaming StartExistingService to StartServiceByName, removing unnecessary test 2024-01-15 13:30:57 -05:00
Raf 8ff7d4ec04 Merge branch 'master' into windows-services 2024-01-15 11:32:40 -05:00
Raf 0bfa34357e Adding help for services command 2024-01-15 11:08:46 -05:00
Raf ad1ee0a52d Adding the services command for getting information about and controlling services on Windows 2024-01-15 10:48:59 -05:00
Joe d9705a3cbe Merge pull request #1551 from BishopFox/v1.6.0/daemon-tailscale-flag
Add support for tailscale to daemon mode
2024-01-11 12:28:08 -06:00
rkervella 3c91f8eb52 Setup default C2 profiles in daemon mode. 2024-01-11 09:11:10 -08:00
rkervella 9d36920115 Add tailscale option to config file and fix missing argument to daemon.Start() 2024-01-10 14:51:40 -08:00
rkervella 8731006619 Remove empty line 2024-01-10 14:47:31 -08:00
rkervella 19cac4a08a Add support for tailscale to daemon mode 2024-01-10 14:45:12 -08:00
Ronan Kervella a9679e56d3 Merge pull request #1550 from BishopFox/v1.6.0/external-builders-multiservers
Don't exit on connection error.
2024-01-10 12:41:59 -08:00
rkervella 8e833d3510 Don't exit on connection error. 2024-01-10 10:50:30 -08:00
Ronan Kervella f227fedd46 Merge pull request #1549 from BishopFox/v1.6.0/external-builders-multiservers
Support multi-builders (1:n)
2024-01-09 16:43:50 -08:00
Ronan Kervella 804cf1b3fa Merge branch 'master' into v1.6.0/external-builders-multiservers 2024-01-09 16:04:41 -08:00
Ronan Kervella 7e23f93ba7 Merge pull request #1475 from BishopFox/8a21dependabot/go_modules/github.com/chromedp/chromedp-0.9.3
Bump github.com/chromedp/chromedp from 0.9.1 to 0.9.3
2024-01-09 16:04:28 -08:00
Ronan Kervella 1a79fb0176 Merge branch 'master' into v1.6.0/external-builders-multiservers 2024-01-09 15:05:18 -08:00
Ronan Kervella 7d9ced0d58 Merge branch 'master' into 8a21dependabot/go_modules/github.com/chromedp/chromedp-0.9.3 2024-01-09 14:17:26 -08:00
rkervella a0ea8eca27 Add support for multiple builders with reload from SIGHUP. 2024-01-09 14:11:44 -08:00
Ronan Kervella 61193c51c5 Merge pull request #1548 from BishopFox/client-command-fixes
Small Client Command Fixes
2024-01-09 10:19:55 -08:00
Raf 849f6fb683 Rewiring the grep, head, and tail commands; fixing timeout for procdump command 2024-01-09 12:24:59 -05:00
Ronan Kervella 24bb07e981 Merge branch 'master' into eea1dependabot/github_actions/github/codeql-action-3 2024-01-08 16:11:48 -08:00
Joe ad3b55fc0d Merge pull request #1544 from audibleblink/fix/migrate-cli
address regression; previously fixed in dd2af38
2024-01-08 12:58:49 -06:00
Ronan Kervella e5bc13e9ed Merge branch 'master' into 8a21dependabot/go_modules/github.com/chromedp/chromedp-0.9.3 2024-01-05 13:50:42 -08:00
Ronan Kervella 2fbd8e059a Merge branch 'master' into fix/migrate-cli 2024-01-05 13:08:47 -08:00
Ronan Kervella b20c5374b7 Merge pull request #1543 from BishopFox/windows-service-migrate
Fix migration issues with Windows service builds
2024-01-05 13:08:32 -08:00
rkervella 05ea6ce233 Initial support for multi-server builders 2024-01-05 13:01:00 -08:00
Alex Flores 72a37aa07a address regression; previously fixed in dd2af38 2024-01-05 14:30:58 -05:00
Ronan Kervella ae6028b7f6 Merge branch 'master' into eea1dependabot/github_actions/github/codeql-action-3 2024-01-05 11:09:46 -08:00
Ronan Kervella 13b2b5bc96 Merge branch 'master' into windows-service-migrate 2024-01-05 11:04:32 -08:00
Ronan Kervella 49bd90bc96 Merge pull request #1538 from BishopFox/more-session-data
Display More Process Information (`sessions` and `beacons` commands)
2024-01-05 11:04:06 -08:00
Raf 2d463f7b39 Merge branch 'master' into more-session-data 2024-01-05 12:43:43 -05:00
Raf 24b0301000 Fixing reference to SliverConsoleClient 2024-01-05 12:43:23 -05:00
Raf 70c65ca13b Merge branch 'master' into more-session-data 2024-01-05 12:41:25 -05:00
Raf 80b4a29ce5 Merge branch 'master' into windows-service-migrate 2024-01-05 11:10:42 -05:00
Joe 239c32e9c0 Merge pull request #1518 from BishopFox/c0b0dependabot/github_actions/actions/checkout-4
Bump actions/checkout from 3 to 4
2024-01-05 10:00:32 -06:00
Joe 78b0a46654 Merge pull request #1534 from BishopFox/c027dependabot/github_actions/actions/upload-artifact-4
Bump actions/upload-artifact from 3 to 4
2024-01-05 09:54:23 -06:00
Joe 6597361075 Merge pull request #1533 from BishopFox/f9e9dependabot/github_actions/actions/download-artifact-4
Bump actions/download-artifact from 3 to 4
2024-01-05 09:54:08 -06:00
Raf ad544ef4fa Fix migration issues with Windows service builds 2024-01-05 10:30:27 -05:00
Ronan Kervella ceb8b2f513 Merge pull request #1540 from BishopFox/v1.6.0/operator-creds-stdout
Add option to output credentials to stdout
2024-01-04 19:54:31 -08:00
Ronan Kervella b4bb80caab Merge branch 'master' into v1.6.0/operator-creds-stdout 2024-01-04 16:19:56 -08:00
Ronan Kervella c6cfb2dee9 Merge pull request #1541 from audibleblink/msf/exe-service
enables generation of exe-service stagers
2024-01-04 16:19:44 -08:00
Alex Flores 2792dd026e enables generation of exe-service stagers 2024-01-04 16:48:58 -05:00
Raf 43567441cc In the unfiltered view of sessions and beacons, do not show the integrity column if there are no Windows beacons or sessions 2024-01-04 13:56:16 -05:00
rkervella 3d2751bb2b Add option to output credentials to stdout 2024-01-04 10:55:10 -08:00
Ronan Kervella bdd8390913 Merge pull request #1537 from BishopFox/v1.6.0/cli-changes
Fix CLI changes
2024-01-04 10:46:30 -08:00
rkervella 77fea4f81c Update readline lib 2024-01-03 13:14:19 -08:00
Raf b9403085c6 Adding process information (PID, name, integrity) to long form session and beacon displays 2024-01-03 11:57:28 -05:00
rkervella 2ad8aa4829 Fix last merge issues 2024-01-02 16:13:26 -08:00
rkervella eecaeabf45 Merge branch 'beacon-commands' of https://github.com/maxlandon/sliver into maxlandon-beacon-commands 2024-01-02 16:11:42 -08:00
Ronan Kervella 67f92d6b4d Merge pull request #1536 from BishopFox/migrate-beacon
Add `migrate` support to beacons
2024-01-02 14:10:30 -08:00
Raf 8fd2cd98c7 Merging master into migrate-beacon 2024-01-02 15:33:04 -05:00
Raf 3d79a60464 Finishing support for migrating when using a beacon 2024-01-02 15:30:54 -05:00
Ronan Kervella 5c8f0f46d1 Merge pull request #1535 from BishopFox/migrate-with-name
Addressing Migrate "record not found"
2024-01-02 08:26:02 -08:00
Raf a58889ce14 Merge branch 'master' into migrate-beacon 2024-01-02 07:58:24 -05:00
Raf 37d7395f91 Populating the name of the implant in the migrate request from the client 2024-01-02 07:37:23 -05:00
dependabot[bot] 5039be3db8 Bump actions/upload-artifact from 3 to 4
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 3 to 4.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/v3...v4)

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

Signed-off-by: dependabot[bot] <[email protected]>
2024-01-01 03:06:53 +00:00
dependabot[bot] b64dd14f2f Bump actions/download-artifact from 3 to 4
Bumps [actions/download-artifact](https://github.com/actions/download-artifact) from 3 to 4.
- [Release notes](https://github.com/actions/download-artifact/releases)
- [Commits](https://github.com/actions/download-artifact/compare/v3...v4)

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

Signed-off-by: dependabot[bot] <[email protected]>
2024-01-01 03:06:51 +00:00
Joe dd2af38196 Merge pull request #1531 from audibleblink/fix/migrate-cli
no positional arg needed
2023-12-30 12:13:58 -06:00
Joe 77c3d851a2 Merge pull request #1526 from BishopFox/7983dependabot/github_actions/actions/upload-pages-artifact-3
Bump actions/upload-pages-artifact from 1 to 3
2023-12-29 20:12:35 -06:00
Joe 99b15a0d71 Merge pull request #1527 from BishopFox/090adependabot/github_actions/actions/deploy-pages-4
Bump actions/deploy-pages from 2 to 4
2023-12-29 20:12:22 -06:00
Joe 04e869ce48 Merge pull request #1530 from BishopFox/sgn-stage-listener
Encode Shellcode with SGN when generating via stage-listener
2023-12-29 20:04:21 -06:00
Alex Flores dc467bcfee adds help menu to account for new usage 2023-12-29 16:44:18 -05:00
Alex Flores 21aa7d0ce9 no positional arg needed 2023-12-29 16:10:51 -05:00
Raf 32a60456e5 Encoding shellcode with SGN for shellcode generated by stage-listener, if enabled in the profile 2023-12-29 10:09:24 -05:00
Raf 01719c15c7 Initial changes to support migrating beacons 2023-12-27 04:44:11 -05:00
dependabot[bot] 8a29924a12 Bump actions/deploy-pages from 2 to 4
Bumps [actions/deploy-pages](https://github.com/actions/deploy-pages) from 2 to 4.
- [Release notes](https://github.com/actions/deploy-pages/releases)
- [Commits](https://github.com/actions/deploy-pages/compare/v2...v4)

---
updated-dependencies:
- dependency-name: actions/deploy-pages
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <[email protected]>
2023-12-25 03:56:38 +00:00
dependabot[bot] 59eb25a5ad Bump actions/upload-pages-artifact from 1 to 3
Bumps [actions/upload-pages-artifact](https://github.com/actions/upload-pages-artifact) from 1 to 3.
- [Release notes](https://github.com/actions/upload-pages-artifact/releases)
- [Commits](https://github.com/actions/upload-pages-artifact/compare/v1...v3)

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

Signed-off-by: dependabot[bot] <[email protected]>
2023-12-25 03:56:32 +00:00
Joe 538912c89d Merge branch 'master' into deabdependabot/github_actions/actions/configure-pages-4 2023-12-24 09:40:09 -06:00
Joe b4cf8482c1 Merge pull request #1525 from BishopFox/fix-c2-db-duplication
Fix C2 URL Duplication in Database
2023-12-22 13:55:22 -06:00
Raf de7d466acb Fixing an issue where C2 URLs are duplicated every time a profile is used to generate an implant. 2023-12-22 12:23:19 -05:00
Ronan Kervella a84f13e8a0 Merge pull request #1424 from C-Sto/extensionargs
Extensionargs
2023-12-20 16:05:03 -08:00
C_Sto dfaadfb5c0 Merge branch 'master' into extensionargs
Signed-off-by: C_Sto <[email protected]>
2023-12-20 09:19:21 +08:00
Ronan Kervella 478dabf5e1 Merge pull request #1397 from C-Sto/multiextensions
multimanifest extension support
2023-12-19 09:51:01 -08:00
Ronan Kervella 5767abe616 Merge branch 'master' into multiextensions 2023-12-19 08:29:57 -08:00
Joe 2fabbee6bf Merge pull request #1523 from BishopFox/8b62dependabot/go_modules/golang.org/x/crypto-0.17.0
Bump golang.org/x/crypto from 0.15.0 to 0.17.0
2023-12-19 10:08:20 -06:00
C-Sto 1e6d91fb6a menu better 2023-12-19 13:12:36 +08:00
moloch-- 31022c12db Add offline docs script 2023-12-18 20:47:17 -06:00
Ronan Kervella 456ca26817 Merge branch 'master' into 8a21dependabot/go_modules/github.com/chromedp/chromedp-0.9.3 2023-12-18 16:03:40 -08:00
Ronan Kervella 0bf4dd4313 Merge branch 'master' into eea1dependabot/github_actions/github/codeql-action-3 2023-12-18 16:02:28 -08:00
Ronan Kervella f18e383e33 Merge branch 'master' into deabdependabot/github_actions/actions/configure-pages-4 2023-12-18 16:02:23 -08:00
Ronan Kervella 5f34e9672b Merge branch 'master' into c0b0dependabot/github_actions/actions/checkout-4 2023-12-18 16:02:16 -08:00
dependabot[bot] e82975d1bd Bump golang.org/x/crypto from 0.15.0 to 0.17.0
Bumps [golang.org/x/crypto](https://github.com/golang/crypto) from 0.15.0 to 0.17.0.
- [Commits](https://github.com/golang/crypto/compare/v0.15.0...v0.17.0)

---
updated-dependencies:
- dependency-name: golang.org/x/crypto
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <[email protected]>
2023-12-18 23:59:26 +00:00
Ronan Kervella 1205defc3e Merge branch 'master' into extensionargs 2023-12-18 09:25:56 -08:00
Ronan Kervella 33613d25da Merge branch 'master' into multiextensions 2023-12-18 08:52:47 -08:00
moloch-- 5c9b4a6af7 fix typos 2023-12-18 08:08:11 -06:00
dependabot[bot] 9f2ab9ba1b Bump actions/checkout from 3 to 4
Bumps [actions/checkout](https://github.com/actions/checkout) from 3 to 4.
- [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/v3...v4)

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

Signed-off-by: dependabot[bot] <[email protected]>
2023-12-18 03:05:22 +00:00
dependabot[bot] d984d3a5f9 Bump actions/configure-pages from 3 to 4
Bumps [actions/configure-pages](https://github.com/actions/configure-pages) from 3 to 4.
- [Release notes](https://github.com/actions/configure-pages/releases)
- [Commits](https://github.com/actions/configure-pages/compare/v3...v4)

---
updated-dependencies:
- dependency-name: actions/configure-pages
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <[email protected]>
2023-12-18 03:05:18 +00:00
dependabot[bot] 35b7b034ce Bump github/codeql-action from 2 to 3
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 2 to 3.
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/github/codeql-action/compare/v2...v3)

---
updated-dependencies:
- dependency-name: github/codeql-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <[email protected]>
2023-12-18 03:05:10 +00:00
moloch-- cfdbe6d467 Fix more links 2023-12-17 17:53:48 -06:00
moloch-- 8ad5d44114 Adjust page title 2023-12-17 16:34:55 -06:00
moloch-- ada14762cd Self host images 2023-12-17 16:26:17 -06:00
moloch-- 5f0b778c18 Add page title 2023-12-17 12:20:47 -06:00
moloch-- 78038a8dcc Fix typo 2023-12-17 12:16:55 -06:00
moloch-- 9f0f9b1206 Update generate beacon example 2023-12-17 11:48:30 -06:00
moloch-- a02f1ac529 Update generate session example 2023-12-17 11:32:46 -06:00
moloch-- dd51a66b63 Add service status 2023-12-17 10:35:58 -06:00
moloch-- d98810a65e Update install cast 2023-12-17 10:04:50 -06:00
moloch-- 803adef634 Fix code block 2023-12-17 09:43:50 -06:00
moloch-- 03c3d45500 Fix more links 2023-12-16 23:36:59 -06:00
moloch-- ec31b5dfa6 Fix more links 2023-12-16 23:33:35 -06:00
moloch-- f1ce927e1d Simplify name/md state mgmt 2023-12-16 23:24:11 -06:00
moloch-- a4ee4dc5e9 Fix more links 2023-12-16 23:01:04 -06:00
moloch-- d4e0c562ee Fix links, enable scroll restoration 2023-12-16 22:55:38 -06:00
moloch-- 7047ec1c52 Add asciinema markdown renderer 2023-12-16 22:51:09 -06:00
moloch-- cdfc2cd241 Tweak footer 2023-12-16 21:11:18 -06:00
moloch-- c4597cca76 fix links to c2 2023-12-16 20:50:53 -06:00
moloch-- 727693f3f2 Update intro paragraph 2023-12-16 19:38:15 -06:00
moloch-- 2d51293792 Tweak timers 2023-12-16 19:29:14 -06:00
moloch-- aa1850b8e6 Update readme 2023-12-16 19:27:34 -06:00
moloch-- a84b01ed40 Tweak timers 2023-12-16 19:10:35 -06:00
moloch-- 84808f626e Implement cards 2023-12-16 18:52:50 -06:00
moloch-- a10770ae2c Override ap-control-bar class 2023-12-16 18:33:47 -06:00
moloch-- 5d8d3a5d78 Fix bottom marge in search results 2023-12-16 17:32:21 -06:00
moloch-- a0a59ee540 Add footer 2023-12-16 17:00:08 -06:00
moloch-- 58be6c5a10 Add gh button 2023-12-16 16:44:18 -06:00
moloch-- 9cd27ed805 Various small tweaks 2023-12-16 16:40:09 -06:00
moloch-- 147e06d058 Remove old install script file 2023-12-16 16:27:04 -06:00
moloch-- 26aad81968 Fix various rel links 2023-12-16 16:24:56 -06:00
moloch-- 0f26ad1396 Fix relative navigation 2023-12-16 16:20:40 -06:00
moloch-- aac3c142e5 Implement search 2023-12-16 15:41:06 -06:00
moloch-- 4e012113cf Adjust border in dark mode 2023-12-16 13:38:39 -06:00
moloch-- 6916dbe684 Fixed docs sidebar 2023-12-16 13:23:23 -06:00
moloch-- 97e5142b7a Open 3rd party links in new tab 2023-12-16 10:25:54 -06:00
moloch-- 06fc398033 Implement onClear 2023-12-15 18:24:03 -06:00
moloch-- c2f4856255 Implement fuzzy filter 2023-12-15 18:22:52 -06:00
moloch-- ad7e1dcafa Fix theme on dark landing page 2023-12-15 18:01:21 -06:00
moloch-- 8c5d3dd637 Fix theme on dark landing page 2023-12-15 17:50:32 -06:00
Joe 2e7498c94c Merge pull request #1512 from BishopFox/docs/next
Docs/next
2023-12-15 17:44:46 -06:00
moloch-- dee26bcb3d Add paths to unit tests 2023-12-15 17:44:18 -06:00
moloch-- 67c6710ff9 Add asciinema intro 2023-12-15 17:40:05 -06:00
Joe e4a98e9a34 Merge pull request #1511 from BishopFox/docs/next
Docs/next
2023-12-15 16:21:36 -06:00
moloch-- 15781566ab Add more pages 2023-12-15 16:18:23 -06:00
moloch-- 2bcaf9a78f Store doc state in frag 2023-12-15 15:59:26 -06:00
Joe d8fe33d20a Merge pull request #1510 from BishopFox/docs/next
Fix image rendering
2023-12-15 15:48:38 -06:00
moloch-- 3a846e41a7 Fix image rendering 2023-12-15 15:44:56 -06:00
Joe d3ad2dc84f Merge pull request #1508 from BishopFox/fix-hosts-rm
Fix for hosts command and host IDs for loot
2023-12-15 15:40:04 -06:00
Joe 8aa4dd4a28 Merge pull request #1507 from BishopFox/fix-ioc-rm
Fixes for removing IOCs
2023-12-15 15:39:31 -06:00
Joe b360eae3fb Merge pull request #1509 from BishopFox/docs/next
Docs/next
2023-12-15 15:39:10 -06:00
moloch-- 8260c90288 Add more pages 2023-12-15 15:36:01 -06:00
Raf b080e06039 Fixing issue with removal of hosts and an issue where the host ID for loot did not populate in the database 2023-12-15 13:49:17 -05:00
Raf d394a5936d Associating IOC Protobuf objects with database objects to fix IOC deletion, changing some error messages 2023-12-15 11:52:22 -05:00
moloch-- 7ab9ddb68f Implement monaco code viewer 2023-12-15 09:15:27 -06:00
Joe 7d496d9036 Merge pull request #1506 from BishopFox/docs/next
Fix dark mode docs
2023-12-14 18:30:28 -06:00
moloch-- 99c3bde7df Fix dark mode docs 2023-12-14 18:29:52 -06:00
Joe bc5c1e0d8a Merge pull request #1505 from BishopFox/docs/next
Docs/next
2023-12-14 18:24:09 -06:00
moloch-- 84c4832ff4 Basic renderer working 2023-12-14 18:18:01 -06:00
moloch-- 1a280c3677 Fix root document 2023-12-14 17:57:31 -06:00
moloch-- c16737bfe9 Implement docs.json scheme 2023-12-14 16:40:29 -06:00
dependabot[bot] b5262b0c3a Bump github.com/chromedp/chromedp from 0.9.1 to 0.9.3
Bumps [github.com/chromedp/chromedp](https://github.com/chromedp/chromedp) from 0.9.1 to 0.9.3.
- [Release notes](https://github.com/chromedp/chromedp/releases)
- [Commits](https://github.com/chromedp/chromedp/compare/v0.9.1...v0.9.3)

---
updated-dependencies:
- dependency-name: github.com/chromedp/chromedp
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <[email protected]>
2023-12-14 20:03:18 +00:00
Joe b84796f723 Merge pull request #1478 from BishopFox/2ee9dependabot/go_modules/gorm.io/driver/sqlite-1.5.4
Bump gorm.io/driver/sqlite from 1.5.2 to 1.5.4
2023-12-14 14:01:33 -06:00
Joe 5c206cdd01 Merge pull request #1504 from BishopFox/fix-iocs
IOC Fixes
2023-12-14 12:43:07 -06:00
Raf f2be8a41e7 Fixing associations between database models and IOC data objects so that IOCs are properly recorded; changed recorded IOC hash to the hash of the non-gzipped data 2023-12-14 11:46:36 -05:00
moloch-- 2e6904d838 Update docs readme 2023-12-13 18:43:09 -06:00
Joe e197ba9438 Merge pull request #1503 from BishopFox/docs/next
Docs/next
2023-12-13 18:25:40 -06:00
moloch-- f92067ef7d Place holders 2023-12-13 18:25:15 -06:00
moloch-- 33e678684f Add asciinema and monaco 2023-12-13 18:23:57 -06:00
moloch-- 0c2e8e1164 Add page dirs 2023-12-13 18:12:06 -06:00
moloch-- f7e3fd99e4 Initial commit 2023-12-13 17:57:31 -06:00
moloch-- 5539016c9b Fix out path 2023-12-13 17:23:54 -06:00
moloch-- 96fd678b3e Try to fix npm and node being stupid 2023-12-13 17:22:32 -06:00
moloch-- d2ccfb288d Node being dumb as usual 2023-12-13 17:20:28 -06:00
moloch-- cd834fcab4 Fix docs paths 2023-12-13 17:15:42 -06:00
moloch-- 8e9899e6c4 Change working directory 2023-12-13 17:14:24 -06:00
moloch-- 84d82aedcf Change working directory 2023-12-13 17:13:00 -06:00
moloch-- a3d1015449 Fix paths to subdir 2023-12-13 17:09:25 -06:00
Joe 60da181cc6 Merge pull request #1502 from BishopFox/docs/next
Add nextjs docs app
2023-12-13 17:06:15 -06:00
moloch-- a1abcaa6c8 Add nextjs docs app 2023-12-13 17:04:22 -06:00
Ronan Kervella 3974b53301 Merge pull request #1495 from vitorfhc/master
Adds the "permissions" flag to operator cmd in cli
2023-12-13 08:52:38 -08:00
Ronan Kervella dabc301108 Merge branch 'master' into master 2023-12-13 08:24:07 -08:00
Joe e32d0dd283 Merge pull request #1498 from BishopFox/4997dependabot/github_actions/actions/setup-go-5
Bump actions/setup-go from 4 to 5
2023-12-13 09:27:54 -06:00
dependabot[bot] 823d10c43c Bump actions/setup-go from 4 to 5
Bumps [actions/setup-go](https://github.com/actions/setup-go) from 4 to 5.
- [Release notes](https://github.com/actions/setup-go/releases)
- [Commits](https://github.com/actions/setup-go/compare/v4...v5)

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

Signed-off-by: dependabot[bot] <[email protected]>
2023-12-11 03:26:17 +00:00
Vitor Falcao fc7e0a8d19 Adds the "permissions" flag to operator cmd in cli 2023-12-06 15:39:33 -03:00
Ronan Kervella 48562a4221 Merge branch 'master' into extensionargs 2023-12-06 09:07:26 -08:00
Joe c1242a82a6 Merge pull request #1489 from Z3ratu1/fix/correct-section-length-in-evasion_windows.go
correct section length in evasion_windows.go
2023-12-04 12:27:39 -08:00
z3ratu1 d2bd8ddd42 correct section length in evasion_windows.go(fix for issue #1189) 2023-12-04 12:13:11 +08:00
dependabot[bot] e9cc6804bf Bump gorm.io/driver/sqlite from 1.5.2 to 1.5.4
Bumps [gorm.io/driver/sqlite](https://github.com/go-gorm/sqlite) from 1.5.2 to 1.5.4.
- [Commits](https://github.com/go-gorm/sqlite/compare/v1.5.2...v1.5.4)

---
updated-dependencies:
- dependency-name: gorm.io/driver/sqlite
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <[email protected]>
2023-11-27 16:52:42 +00:00
Joe 061166755d Merge pull request #1477 from BishopFox/347bdependabot/go_modules/github.com/spf13/cobra-1.8.0
Bump github.com/spf13/cobra from 1.7.0 to 1.8.0
2023-11-27 08:49:58 -08:00
dependabot[bot] 489678e635 Bump github.com/spf13/cobra from 1.7.0 to 1.8.0
Bumps [github.com/spf13/cobra](https://github.com/spf13/cobra) from 1.7.0 to 1.8.0.
- [Release notes](https://github.com/spf13/cobra/releases)
- [Commits](https://github.com/spf13/cobra/compare/v1.7.0...v1.8.0)

---
updated-dependencies:
- dependency-name: github.com/spf13/cobra
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <[email protected]>
2023-11-27 16:17:54 +00:00
Joe 93f86ac79b Merge pull request #1476 from BishopFox/61f3dependabot/go_modules/github.com/reeflective/readline-1.0.11
Bump github.com/reeflective/readline from 1.0.10 to 1.0.11
2023-11-27 08:15:10 -08:00
dependabot[bot] 6ea60eeffc Bump github.com/reeflective/readline from 1.0.10 to 1.0.11
Bumps [github.com/reeflective/readline](https://github.com/reeflective/readline) from 1.0.10 to 1.0.11.
- [Release notes](https://github.com/reeflective/readline/releases)
- [Changelog](https://github.com/reeflective/readline/blob/master/history.go)
- [Commits](https://github.com/reeflective/readline/compare/v1.0.10...v1.0.11)

---
updated-dependencies:
- dependency-name: github.com/reeflective/readline
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <[email protected]>
2023-11-27 03:47:58 +00:00
Joe 2bc427f551 Merge pull request #1467 from BishopFox/5fa4dependabot/go_modules/github.com/yiya1989/sshkrb5-0.0.1
Bump github.com/yiya1989/sshkrb5 from 0.0.0-20201110125252-a1455b75a35e to 0.0.1
2023-11-21 12:28:42 -08:00
dependabot[bot] 59f54706a0 Bump github.com/yiya1989/sshkrb5
Bumps [github.com/yiya1989/sshkrb5](https://github.com/yiya1989/sshkrb5) from 0.0.0-20201110125252-a1455b75a35e to 0.0.1.
- [Release notes](https://github.com/yiya1989/sshkrb5/releases)
- [Commits](https://github.com/yiya1989/sshkrb5/commits/v0.0.1)

---
updated-dependencies:
- dependency-name: github.com/yiya1989/sshkrb5
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <[email protected]>
2023-11-21 17:43:58 +00:00
Joe cb61b81459 Merge pull request #1469 from BishopFox/fecbdependabot/go_modules/github.com/google/uuid-1.4.0
Bump github.com/google/uuid from 1.3.1 to 1.4.0
2023-11-21 09:42:17 -08:00
Joe 880eb6091b Merge pull request #1468 from BishopFox/34ffdependabot/go_modules/github.com/miekg/dns-1.1.57
Bump github.com/miekg/dns from 1.1.56 to 1.1.57
2023-11-21 09:41:45 -08:00
dependabot[bot] 36ed8ad5b9 Bump github.com/miekg/dns from 1.1.56 to 1.1.57
Bumps [github.com/miekg/dns](https://github.com/miekg/dns) from 1.1.56 to 1.1.57.
- [Changelog](https://github.com/miekg/dns/blob/master/Makefile.release)
- [Commits](https://github.com/miekg/dns/compare/v1.1.56...v1.1.57)

---
updated-dependencies:
- dependency-name: github.com/miekg/dns
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <[email protected]>
2023-11-20 22:25:37 +00:00
dependabot[bot] 1b6af55b14 Bump github.com/google/uuid from 1.3.1 to 1.4.0
Bumps [github.com/google/uuid](https://github.com/google/uuid) from 1.3.1 to 1.4.0.
- [Release notes](https://github.com/google/uuid/releases)
- [Changelog](https://github.com/google/uuid/blob/master/CHANGELOG.md)
- [Commits](https://github.com/google/uuid/compare/v1.3.1...v1.4.0)

---
updated-dependencies:
- dependency-name: github.com/google/uuid
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <[email protected]>
2023-11-20 22:25:11 +00:00
Joe 95a2eead7d Merge pull request #1470 from BishopFox/eda5dependabot/go_modules/github.com/mattn/go-sqlite3-1.14.18
Bump github.com/mattn/go-sqlite3 from 1.14.17 to 1.14.18
2023-11-20 14:24:08 -08:00
Joe c02b87030e Merge pull request #1471 from BishopFox/c9f2dependabot/go_modules/github.com/reeflective/readline-1.0.10
Bump github.com/reeflective/readline from 1.0.8 to 1.0.10
2023-11-20 14:23:55 -08:00
dependabot[bot] 9f252327ca Bump github.com/reeflective/readline from 1.0.8 to 1.0.10
Bumps [github.com/reeflective/readline](https://github.com/reeflective/readline) from 1.0.8 to 1.0.10.
- [Release notes](https://github.com/reeflective/readline/releases)
- [Changelog](https://github.com/reeflective/readline/blob/master/history.go)
- [Commits](https://github.com/reeflective/readline/compare/v1.0.8...v1.0.10)

---
updated-dependencies:
- dependency-name: github.com/reeflective/readline
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <[email protected]>
2023-11-20 03:57:56 +00:00
dependabot[bot] c3889e160c Bump github.com/mattn/go-sqlite3 from 1.14.17 to 1.14.18
Bumps [github.com/mattn/go-sqlite3](https://github.com/mattn/go-sqlite3) from 1.14.17 to 1.14.18.
- [Release notes](https://github.com/mattn/go-sqlite3/releases)
- [Commits](https://github.com/mattn/go-sqlite3/compare/v1.14.17...v1.14.18)

---
updated-dependencies:
- dependency-name: github.com/mattn/go-sqlite3
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <[email protected]>
2023-11-20 03:57:49 +00:00
moloch-- 853fb02e9f Fix duplicate sectool names 2023-11-19 11:01:05 -07:00
moloch-- 4f9943ec41 Fix duplicate sectool names 2023-11-19 10:59:42 -07:00
moloch-- 3e72fff43b Minor cleanups 2023-11-19 10:27:21 -07:00
moloch-- 13178f5849 Tweak token err msg 2023-11-18 13:36:31 -07:00
moloch-- 88c67e88d9 Merge branch 'operator/permissions' 2023-11-18 13:34:24 -07:00
moloch-- 14e78df896 Add more nil checks 2023-11-18 13:34:09 -07:00
moloch-- b3429f5f88 Fix err nil deref 2023-11-18 13:31:47 -07:00
Joe 0402d622e1 Merge pull request #1466 from BishopFox/operator/permissions
Operator/permissions
2023-11-18 12:11:59 -08:00
moloch-- 04d8d2aac7 Add missing builder permissions 2023-11-18 12:39:34 -07:00
moloch-- b71759f3b2 Add basic methods 2023-11-18 12:33:06 -07:00
moloch-- 13c68a7f50 Implement method checks 2023-11-18 12:27:39 -07:00
moloch-- 1f894f50ff Add permissions to operator config 2023-11-18 12:14:33 -07:00
moloch-- 33ea66de58 Add production 'slim' Docker stage 2023-11-18 10:19:14 -07:00
moloch-- 9a432f583d Add missing libs to docker test 2023-11-18 10:09:32 -07:00
moloch-- cbcd948c83 Add comments to Dockerfile 2023-11-18 09:24:21 -07:00
Joe 2ada8bf8ed Merge pull request #1465 from BishopFox/vendor/ssh
Update ssh and garble
2023-11-18 08:16:16 -08:00
moloch-- 02a4657d14 Additional tweaks to dockerfile 2023-11-18 08:53:46 -07:00
Joe b7cef9a07c Merge branch 'master' into vendor/ssh 2023-11-18 07:06:53 -08:00
moloch-- 49606ba753 Update ssh and garble 2023-11-18 07:49:03 -07:00
Joe 116431a049 Merge pull request #1421 from BishopFox/upload-dir
Adding the ability to upload directories
2023-11-17 10:03:09 -08:00
Joe ae5ac2af0f Merge branch 'master' into upload-dir 2023-11-17 09:34:45 -08:00
Joe b03c2ca6cd Merge pull request #1464 from BishopFox/vendor/gorilla
Update deps
2023-11-16 17:55:34 -08:00
Joe 6a4276e1e2 Merge pull request #1463 from BishopFox/http/default-config
Update default http c2 config
2023-11-16 17:55:17 -08:00
moloch-- c7358f8e63 Remove uneeded rand seeding 2023-11-16 18:32:54 -07:00
moloch-- de2fb65ee0 Improve cert randomization 2023-11-16 18:28:48 -07:00
moloch-- c52ca054a0 Update default http c2 config 2023-11-16 18:22:50 -07:00
moloch-- ffdbaba982 Update default http c2 config 2023-11-16 18:17:04 -07:00
moloch-- d23d814368 Update deps 2023-11-16 17:20:33 -07:00
Joe a57a67b6e0 Merge pull request #1461 from BishopFox/vendor/sqlite
Update sqlite deps
2023-11-16 15:59:35 -08:00
Ronan Kervella 8c1194283b Merge branch 'master' into upload-dir 2023-11-10 14:05:05 -08:00
Ronan Kervella 28397eb7a9 Merge branch 'master' into extensionargs 2023-11-10 13:02:13 -08:00
Raf 8ebd7da9a8 Merge branch 'master' into upload-dir 2023-11-08 08:15:02 -05:00
Raf a511af6fd2 Merge branch 'master' into upload-dir 2023-11-01 10:52:23 -04:00
Raf 97a22bb8eb Merging master into this branch and making some tweaks to upload. 2023-11-01 10:38:34 -04:00
Ronan Kervella 342ed489f3 Merge branch 'master' into multiextensions 2023-10-20 10:30:30 -07:00
Ronan Kervella 6b88a01fad Merge branch 'master' into upload-dir 2023-10-19 15:31:56 -07:00
Ronan Kervella 5e5e0df4ec Merge branch 'master' into multiextensions 2023-10-16 09:03:17 -07:00
C-Sto c02c40cb65 improve extensions UX 2023-10-08 10:48:29 +08:00
C-Sto be222e3ffa use bof arg packer for extensions 2023-10-08 07:16:34 +08:00
Raf 7747df7b96 Addressing potential zip slip issue, fixing bug when uploading directories without a filter 2023-10-04 11:11:49 -04:00
Raf efe747b8aa Adding the ability to upload directories 2023-10-04 10:13:04 -04:00
C-Sto 4421ec1698 make client work with updated manifest schema 2023-09-30 14:07:29 +08:00
C-Sto 7815b67a8a revise manifest schema 2023-09-30 14:07:02 +08:00
Ronan Kervella 84aed0720f Merge branch 'master' into multiextensions 2023-09-27 10:53:29 -07:00
Ronan Kervella b212e0fb99 Merge branch 'master' into multiextensions 2023-09-25 11:14:16 -07:00
Ronan Kervella b3ab5ea62e Merge branch 'master' into multiextensions 2023-08-31 10:15:36 -07:00
C-Sto 9d4486f906 multimanifest extension support 2023-08-31 10:57:27 +08:00
Joe a79b397d17 Merge branch 'master' into beacon-commands 2023-08-09 19:05:56 -05:00
Ronan Kervella 46a33851fd Merge branch 'master' into beacon-commands 2023-08-08 11:14:44 -07:00
Ronan Kervella 1da52a3fec Merge branch 'master' into beacon-commands 2023-08-08 09:33:37 -07:00
maxlandon 12065fdb99 Rename SliverConsoleClient to SliverClient 2023-07-23 19:48:38 +02:00
maxlandon d5c1daaa48 Simplify binding commands with groups 2023-07-23 19:36:57 +02:00
maxlandon be65f1ce58 Filter portfwd/socks commands out of beacons 2023-07-23 19:23:13 +02:00
maxlandon 163c11b60c Fmt 2023-07-23 19:04:44 +02:00
maxlandon 47a280cc16 Fix beacon compile flags + debug level for client asciicast 2023-07-23 19:04:20 +02:00
maxlandon ba34df3b4b Merge remote-tracking branch 'BishopFox/master' into beacon-commands 2023-07-19 02:37:44 +02:00
maxlandon 51473ec137 Add many missing completers 2023-06-22 20:26:04 +02:00
maxlandon 2da61c1e54 Finish splits. Compiles 2023-06-22 19:29:04 +02:00
maxlandon e23f040962 Split sliver commands in their files 2023-06-22 17:55:32 +02:00
maxlandon f370e96058 Finish splitting server commands in their files 2023-06-20 13:28:03 +02:00
maxlandon ec88f9bd02 Start splitting commands declarations 2023-06-07 23:00:29 +02:00
maxlandon bce0c8de06 Add a flags package, in which we store some command utility functions to
bind flags, completions, apply command filters, etc.
2023-06-07 22:24:19 +02:00
maxlandon 44ceccff12 Fix some newlines printed or not 2023-06-07 21:44:01 +02:00
4186 changed files with 3841990 additions and 2061482 deletions

No files matched your search

+7 -7
View File
@@ -12,7 +12,7 @@ jobs:
timeout-minutes: 45
steps:
- name: Go 1.21
uses: actions/setup-go@v4
uses: actions/setup-go@v5
with:
go-version: "^1.21"
@@ -31,7 +31,7 @@ jobs:
run: make servers
- name: Server Artifacts
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: servers
path: ./sliver-server_*
@@ -42,10 +42,10 @@ jobs:
runs-on: ubuntu-latest
timeout-minutes: 45
steps:
- name: Go 1.21
uses: actions/setup-go@v4
- name: Go 1.22
uses: actions/setup-go@v5
with:
go-version: "^1.21"
go-version: "^1.22"
- name: Check Out Code
uses: actions/checkout@v4
@@ -57,7 +57,7 @@ jobs:
run: make clients
- name: Client Artifacts
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: clients
path: ./sliver-client_*
@@ -72,7 +72,7 @@ jobs:
steps:
- run: mkdir -p ./builds
- uses: actions/download-artifact@v3
- uses: actions/download-artifact@v4
with:
path: ./builds
+5 -5
View File
@@ -16,10 +16,10 @@ jobs:
steps:
# Setup go environment
- name: Go 1.21
uses: actions/setup-go@v4
- name: Go 1.22
uses: actions/setup-go@v5
with:
go-version: "^1.21"
go-version: "^1.22"
- name: Checkout repository
uses: actions/checkout@v4
@@ -39,7 +39,7 @@ jobs:
uses: actions/checkout@v4
- name: Initialize CodeQL
uses: github/codeql-action/init@v2
uses: github/codeql-action/init@v3
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@v2
uses: github/codeql-action/analyze@v3
env:
VERSION: ${{github.sha}}
+102
View File
@@ -0,0 +1,102 @@
# Sample workflow for building and deploying a Next.js site to GitHub Pages
#
# To get started with Next.js see: https://nextjs.org/docs/getting-started
#
name: Sliver Docs
on:
# Runs on pushes targeting the default branch
push:
branches: ["master"]
# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:
# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages
permissions:
contents: read
pages: write
id-token: write
# Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued.
# However, do NOT cancel in-progress runs as we want to allow these production deployments to complete.
concurrency:
group: "pages"
cancel-in-progress: false
jobs:
build:
runs-on: ubuntu-latest
defaults:
run:
working-directory: ${{ github.workspace }}/docs/sliver-docs
env:
working-directory: ${{ github.workspace }}/docs/sliver-docs
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Detect package manager
id: detect-package-manager
run: |
if [ -f "${{ github.workspace }}/docs/sliver-docs/yarn.lock" ]; then
echo "manager=yarn" >> $GITHUB_OUTPUT
echo "command=install" >> $GITHUB_OUTPUT
echo "runner=yarn" >> $GITHUB_OUTPUT
exit 0
elif [ -f "${{ github.workspace }}/docs/sliver-docs/package.json" ]; then
echo "manager=npm" >> $GITHUB_OUTPUT
echo "command=ci" >> $GITHUB_OUTPUT
echo "runner=npx --no-install" >> $GITHUB_OUTPUT
exit 0
else
echo "Unable to determine package manager"
exit 1
fi
- name: Setup Node
uses: actions/setup-node@v4
with:
cache: "npm"
cache-dependency-path: "**/package-lock.json"
node-version: "lts/*"
- name: Setup Pages
uses: actions/configure-pages@v5
- name: Restore cache
uses: actions/cache@v4
with:
path: |
.next/cache
# Generate a new cache whenever packages or source files change.
key: ${{ runner.os }}-nextjs-${{ hashFiles('**/package-lock.json', '**/yarn.lock') }}-${{ hashFiles('**.[jt]s', '**.[jt]sx') }}
# If source files changed but packages didn't, rebuild from a prior cache.
restore-keys: |
${{ runner.os }}-nextjs-${{ hashFiles('**/package-lock.json', '**/yarn.lock') }}-
- name: Install dependencies
working-directory: ${{ env.working-directory}}
run: ${{ steps.detect-package-manager.outputs.manager }} ${{ steps.detect-package-manager.outputs.command }}
- name: Build with Next.js
working-directory: ${{ env.working-directory}}
run: ${{ steps.detect-package-manager.outputs.runner }} next build
- name: Upload artifact
uses: actions/upload-pages-artifact@v3
with:
path: ${{ github.workspace }}/docs/sliver-docs/out
# Deployment job
deploy:
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
runs-on: ubuntu-latest
needs: build
steps:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4
+18 -14
View File
@@ -3,6 +3,14 @@ on:
pull_request:
branches:
- master
paths:
- "go.mod"
- "go.sum"
- "Makefile"
- "**/*.go"
- "**/*.c"
- "**/*.h"
- "**/*.sh"
types:
- opened
- reopened
@@ -15,16 +23,15 @@ jobs:
runs-on: ubuntu-latest
timeout-minutes: 90
steps:
- name: Go 1.21
uses: actions/setup-go@v4
- name: Go 1.22
uses: actions/setup-go@v5
with:
go-version: "^1.21"
go-version: "^1.22"
- name: OS Packages
run: |
sudo apt-get update --fix-missing && sudo apt-get -y install \
git build-essential zlib1g zlib1g-dev wget zip unzip \
mingw-w64 binutils-mingw-w64 g++-mingw-w64 gcc-multilib
git build-essential zlib1g zlib1g-dev wget zip unzip
- name: Check Out Code
uses: actions/checkout@v4
@@ -49,10 +56,10 @@ jobs:
runs-on: macos-latest
timeout-minutes: 90
steps:
- name: Go 1.21
uses: actions/setup-go@v4
- name: Go 1.22
uses: actions/setup-go@v5
with:
go-version: "^1.21"
go-version: "^1.22"
- name: Mingw
run: brew install mingw-w64
@@ -67,9 +74,6 @@ jobs:
run: make macos-amd64
- name: Test MacOS (amd64)
env:
SLIVER_CC_32: /usr/local/bin/i686-w64-mingw32-gcc
SLIVER_CC_64: /usr/local/bin/x86_64-w64-mingw32-gcc
run: ./sliver-server unpack --force && ./go-tests.sh
- name: Make MacOS (arm64)
@@ -80,10 +84,10 @@ jobs:
runs-on: ubuntu-latest
timeout-minutes: 90
steps:
- name: Go 1.21
uses: actions/setup-go@v4
- name: Go 1.22
uses: actions/setup-go@v5
with:
go-version: "^1.21"
go-version: "^1.22"
- name: Check Out Code
uses: actions/checkout@v4
+80 -27
View File
@@ -1,6 +1,15 @@
#
# For production:
# docker build --target production -t sliver .
# docker run -it --rm -v $HOME/.sliver:/home/sliver/.sliver sliver
#
# For unit testing:
# docker build --target test .
#
# STAGE: base
## Compiles Sliver for use
FROM --platform=linux/amd64 golang:1.21.4 as base
FROM golang:1.23.5 AS base
### Base packages
RUN apt-get update --fix-missing && apt-get -y install \
@@ -20,27 +29,12 @@ RUN cp -vv sliver-server /opt/sliver-server
# STAGE: test
## Run unit tests against the compiled instance
## Use `--target test` in the docker build command to run this stage
FROM --platform=linux/amd64 base as test
FROM base AS test
### Install testing packages
RUN apt-get update --fix-missing && apt-get -y install \
libxml2 libxml2-dev libxslt-dev locate curl \
libreadline6-dev libcurl4-openssl-dev git-core \
libssl-dev libyaml-dev openssl autoconf libtool \
ncurses-dev bison curl xsel postgresql \
postgresql-contrib postgresql-client libpq-dev \
libapr1 libaprutil1 libsvn1 \
libpcap-dev libsqlite3-dev libgmp3-dev \
mingw-w64 binutils-mingw-w64 g++-mingw-w64 \
nasm gcc-multilib
### Install MSF for testing
RUN curl https://raw.githubusercontent.com/rapid7/metasploit-omnibus/master/config/templates/metasploit-framework-wrappers/msfupdate.erb > msfinstall \
&& chmod 755 msfinstall \
&& ./msfinstall
RUN mkdir -p ~/.msf4/ \
&& touch ~/.msf4/initial_setup_complete \
&& su -l sliver -c 'mkdir -p ~/.msf4/ && touch ~/.msf4/initial_setup_complete'
RUN apt-get update --fix-missing \
&& apt-get -y upgrade \
&& apt-get -y install \
curl
RUN /opt/sliver-server unpack --force
@@ -49,19 +43,78 @@ RUN /go/src/github.com/bishopfox/sliver/go-tests.sh
# STAGE: production
## Final dockerized form of Sliver
FROM --platform=linux/amd64 debian:bookworm-slim as production
FROM debian:bookworm-slim AS production
### Install production packages
RUN apt-get update --fix-missing \
&& apt-get -y upgrade \
&& apt-get -y install \
libxml2 libxml2-dev libxslt-dev locate gnupg \
libreadline6-dev libcurl4-openssl-dev git-core \
libssl-dev libyaml-dev openssl autoconf libtool \
ncurses-dev bison curl xsel postgresql \
postgresql-contrib postgresql-client libpq-dev \
curl libapr1 libaprutil1 libsvn1 \
libpcap-dev libsqlite3-dev libgmp3-dev \
nasm
### Install MSF for stager generation
RUN curl https://raw.githubusercontent.com/rapid7/metasploit-omnibus/master/config/templates/metasploit-framework-wrappers/msfupdate.erb > msfinstall \
&& chmod 755 msfinstall \
&& ./msfinstall \
&& mkdir -p ~/.msf4/ \
&& touch ~/.msf4/initial_setup_complete
### Cleanup unneeded packages
RUN apt-get remove -y curl gnupg \
&& apt-get autoremove -y \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
### Add sliver user
RUN groupadd -g 999 sliver \
&& useradd -r -u 999 -g sliver sliver \
&& mkdir -p /home/sliver/ \
&& chown -R sliver:sliver /home/sliver \
&& su -l sliver -c 'mkdir -p ~/.msf4/ && touch ~/.msf4/initial_setup_complete'
### Copy compiled binary
COPY --from=base /opt/sliver-server /opt/sliver-server
### Add sliver user
RUN groupadd -g 999 sliver && useradd -r -u 999 -g sliver sliver
RUN mkdir -p /home/sliver/ && chown -R sliver:sliver /home/sliver
### Unpack Sliver:
USER sliver
RUN /opt/sliver-server unpack --force
WORKDIR /home/sliver/
VOLUME [ "/home/sliver/.sliver" ]
ENTRYPOINT [ "/opt/sliver-server" ]
# STAGE: production-slim (about 1Gb smaller)
FROM debian:bookworm-slim AS production-slim
### Install production packages
RUN apt-get update --fix-missing \
&& apt-get -y upgrade
### Cleanup unneeded packages
RUN apt-get autoremove -y \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
### Add sliver user
RUN groupadd -g 999 sliver \
&& useradd -r -u 999 -g sliver sliver \
&& mkdir -p /home/sliver/ \
&& chown -R sliver:sliver /home/sliver
### Copy compiled binary
COPY --from=base /opt/sliver-server /opt/sliver-server
### Unpack Sliver:
USER sliver
RUN /opt/sliver-server unpack --force
USER sliver
WORKDIR /home/sliver/
VOLUME [ "/home/sliver/.sliver" ]
ENTRYPOINT [ "/opt/sliver-server" ]
+8 -8
View File
@@ -8,7 +8,7 @@ The server and client support MacOS, Windows, and Linux. Implants are supported
# v1.6.0 / `master`
**NOTE:** You are looking the latest master branch of Sliver v1.6.0; PRs should target this branch starting on 6/1/2023 ('MURICA format). However, this branch is NOT RECOMMENDED for production use yet. Please use release tagged versions for the best experience.
**NOTE:** You are looking at the latest master branch of Sliver v1.6.0; new PRs should target this branch. However, this branch is NOT RECOMMENDED for production use yet. Please use release tagged versions for the best experience.
For PRs containing bug fixes specific to Sliver v1.5, please target the [`v1.5.x/master` branch](https://github.com/BishopFox/sliver/tree/v1.5.x/master).
@@ -18,9 +18,9 @@ For PRs containing bug fixes specific to Sliver v1.5, please target the [`v1.5.x
- Compile-time obfuscation
- Multiplayer-mode
- Staged and Stageless payloads
- [Procedurally generated C2](<https://github.com/BishopFox/sliver/wiki/HTTP(S)-C2#under-the-hood>) over HTTP(S)
- [DNS canary](https://github.com/BishopFox/sliver/wiki/DNS-C2#dns-canaries) blue team detection
- [Secure C2](https://github.com/BishopFox/sliver/wiki/Transport-Encryption) over mTLS, WireGuard, HTTP(S), and DNS
- [Procedurally generated C2](https://sliver.sh/docs?name=HTTPS+C2) over HTTP(S)
- [DNS canary](https://sliver.sh/docs?name=DNS+C2) blue team detection
- [Secure C2](https://sliver.sh/docs?name=Transport+Encryption) over mTLS, WireGuard, HTTP(S), and DNS
- Fully scriptable using [JavaScript/TypeScript](https://github.com/moloch--/sliver-script) or [Python](https://github.com/moloch--/sliver-py)
- Windows process migration, process injection, user token manipulation, etc.
- Let's Encrypt integration
@@ -31,7 +31,7 @@ For PRs containing bug fixes specific to Sliver v1.5, please target the [`v1.5.x
### Getting Started
Download the latest [release](https://github.com/BishopFox/sliver/releases) and see the Sliver [wiki](https://github.com/BishopFox/sliver/wiki/Getting-Started) for a quick tutorial on basic setup and usage. To get the very latest and greatest compile from source.
Download the latest [release](https://github.com/BishopFox/sliver/releases) and see the Sliver [wiki](https://sliver.sh/docs?name=Getting+Started) for a quick tutorial on basic setup and usage. To get the very latest and greatest compile from source.
#### Linux One Liner
@@ -39,15 +39,15 @@ Download the latest [release](https://github.com/BishopFox/sliver/releases) and
### Help!
Please checkout the [wiki](https://github.com/BishopFox/sliver/wiki), or start a [GitHub discussion](https://github.com/BishopFox/sliver/discussions). We also tend to hang out in the #golang Slack channel on the [Bloodhound Gang](https://bloodhoundgang.herokuapp.com/) server.
Please checkout the [wiki](https://sliver.sh/), or start a [GitHub discussion](https://github.com/BishopFox/sliver/discussions). We also tend to hang out in the #golang Slack channel on the [Bloodhound Gang](https://bloodhoundgang.herokuapp.com/) server.
### Compile From Source
See the [wiki](https://github.com/BishopFox/sliver/wiki/Compile-From-Source).
See the [wiki](https://sliver.sh/docs?name=Compile+from+Source).
### Feedback
Please take a moment and fill out [our survey](https://forms.gle/SwVsHFNh24ChG58C6)
Please take a moment and fill out [our survey](https://forms.gle/SwVsHFNh24ChG58C6).
### License - GPLv3
+58 -19
View File
@@ -27,7 +27,8 @@ import (
)
const (
armoryConfigFileName = "armories.json"
ArmoryConfigFileName = "armories.json"
DefaultArmoryName = "Default"
)
var (
@@ -36,9 +37,11 @@ var (
// DefaultArmoryRepoURL - The default repo url for the armory
DefaultArmoryRepoURL string
defaultArmoryConfig = &ArmoryConfig{
DefaultArmoryConfig = &ArmoryConfig{
PublicKey: DefaultArmoryPublicKey,
RepoURL: DefaultArmoryRepoURL,
Name: DefaultArmoryName,
Enabled: true,
}
)
@@ -48,29 +51,65 @@ type ArmoryConfig struct {
RepoURL string `json:"repo_url"`
Authorization string `json:"authorization"`
AuthorizationCmd string `json:"authorization_cmd"`
Name string `json:"name"`
Enabled bool `json:"enabled"`
}
// GetArmoriesConfig - The parsed armory config file
func GetArmoriesConfig() []*ArmoryConfig {
armoryConfigPath := filepath.Join(GetRootAppDir(), armoryConfigFileName)
if _, err := os.Stat(armoryConfigPath); os.IsNotExist(err) {
return []*ArmoryConfig{defaultArmoryConfig}
}
data, err := os.ReadFile(armoryConfigPath)
if err != nil {
return []*ArmoryConfig{defaultArmoryConfig}
}
var armoryConfigs []*ArmoryConfig
err = json.Unmarshal(data, &armoryConfigs)
if err != nil {
return []*ArmoryConfig{defaultArmoryConfig}
}
for _, armoryConfig := range armoryConfigs {
func RefreshArmoryAuthorization(armories []*ArmoryConfig) {
for _, armoryConfig := range armories {
if armoryConfig.AuthorizationCmd != "" {
armoryConfig.Authorization = executeAuthorizationCmd(armoryConfig)
}
}
return append(armoryConfigs, defaultArmoryConfig)
}
// GetArmoriesConfig - The parsed armory config file
func GetArmoriesConfig() []*ArmoryConfig {
armoryConfigPath := filepath.Join(GetRootAppDir(), ArmoryConfigFileName)
if _, err := os.Stat(armoryConfigPath); os.IsNotExist(err) {
return []*ArmoryConfig{DefaultArmoryConfig}
}
data, err := os.ReadFile(armoryConfigPath)
if err != nil {
return []*ArmoryConfig{DefaultArmoryConfig}
}
var armoryConfigsFromFile []*ArmoryConfig
var armoryConfigs []*ArmoryConfig
err = json.Unmarshal(data, &armoryConfigsFromFile)
if err != nil {
return []*ArmoryConfig{DefaultArmoryConfig}
}
// Force the default armory to be the last
defaultArmorySpecified := false
for _, config := range armoryConfigsFromFile {
if config.Name == DefaultArmoryName {
defaultArmorySpecified = true
continue
} else {
armoryConfigs = append(armoryConfigs, config)
}
}
if defaultArmorySpecified {
armoryConfigs = append(armoryConfigs, DefaultArmoryConfig)
}
RefreshArmoryAuthorization(armoryConfigs)
return armoryConfigs
}
func SaveArmoriesConfig(armories []*ArmoryConfig) error {
configData, err := json.Marshal(armories)
if err != nil {
return err
}
armoryConfigPath := filepath.Join(GetRootAppDir(), ArmoryConfigFileName)
err = os.WriteFile(armoryConfigPath, configData, 0640)
if err != nil {
return err
}
return nil
}
func executeAuthorizationCmd(armoryConfig *ArmoryConfig) string {
+12 -25
View File
@@ -35,7 +35,7 @@ type NameValueProbability struct {
Name string `json:"name"`
Value string `json:"value"`
Probability int `json:"probability"`
Methods []string
Method string `json:"method"`
}
// HTTPC2ImplantConfig - Implant configuration options
@@ -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"`
}
+9 -8
View File
@@ -24,20 +24,17 @@ import (
"os"
"path"
"github.com/bishopfox/sliver/client/assets"
"github.com/bishopfox/sliver/client/console"
"github.com/rsteube/carapace"
"github.com/spf13/cobra"
"github.com/bishopfox/sliver/client/console"
"github.com/bishopfox/sliver/client/version"
)
const (
logFileName = "sliver-client.log"
)
var sliverServerVersion = fmt.Sprintf("v%s", version.FullVersion())
// Initialize logging
// Initialize logging.
func initLogging(appDir string) *os.File {
log.SetFlags(log.LstdFlags | log.Lshortfile)
logFile, err := os.OpenFile(path.Join(appDir, logFileName), os.O_RDWR|os.O_CREATE|os.O_APPEND, 0o600)
@@ -49,6 +46,10 @@ func initLogging(appDir string) *os.File {
}
func init() {
appDir := assets.GetRootAppDir()
logFile := initLogging(appDir)
defer logFile.Close()
rootCmd.TraverseChildren = true
// Create the console client, without any RPC or commands bound to it yet.
@@ -88,10 +89,10 @@ var rootCmd = &cobra.Command{
Long: ``,
}
// Execute - Execute root command
// Execute - Execute root command.
func Execute() {
if err := rootCmd.Execute(); err != nil {
fmt.Println(err)
fmt.Printf("root command: %s\n", err)
os.Exit(1)
}
}
-1
View File
@@ -23,7 +23,6 @@ import (
"sort"
"github.com/bishopfox/sliver/client/assets"
"gopkg.in/AlecAivazis/survey.v1"
)
+43 -11
View File
@@ -1,37 +1,53 @@
package cli
import (
"fmt"
/*
Sliver Implant Framework
Copyright (C) 2019 Bishop Fox
"github.com/spf13/cobra"
"google.golang.org/grpc"
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import (
"context"
"fmt"
"os"
"github.com/bishopfox/sliver/client/assets"
"github.com/bishopfox/sliver/client/command"
"github.com/bishopfox/sliver/client/console"
"github.com/bishopfox/sliver/client/transport"
"github.com/bishopfox/sliver/protobuf/rpcpb"
"github.com/spf13/cobra"
"google.golang.org/grpc"
"google.golang.org/grpc/connectivity"
)
// consoleCmd generates the console with required pre/post runners
func consoleCmd(con *console.SliverConsoleClient) *cobra.Command {
// consoleCmd generates the console with required pre/post runners.
func consoleCmd(con *console.SliverClient) *cobra.Command {
consoleCmd := &cobra.Command{
Use: "console",
Short: "Start the sliver client console",
}
consoleCmd.RunE, consoleCmd.PersistentPostRunE = consoleRunnerCmd(con, true)
return consoleCmd
}
func consoleRunnerCmd(con *console.SliverConsoleClient, run bool) (pre, post func(cmd *cobra.Command, args []string) error) {
func consoleRunnerCmd(con *console.SliverClient, run bool) (pre, post func(cmd *cobra.Command, args []string) error) {
var ln *grpc.ClientConn
pre = func(_ *cobra.Command, _ []string) error {
appDir := assets.GetRootAppDir()
logFile := initLogging(appDir)
defer logFile.Close()
configs := assets.GetConfigs()
if len(configs) == 0 {
@@ -57,6 +73,9 @@ func consoleRunnerCmd(con *console.SliverConsoleClient, run bool) (pre, post fun
return nil
}
// Wait for any connection state changes and exit if the connection is lost.
go handleConnectionLost(ln)
return console.StartClient(con, rpc, command.ServerCommands(con, nil), command.SliverCommands(con), run)
}
@@ -71,3 +90,16 @@ func consoleRunnerCmd(con *console.SliverConsoleClient, run bool) (pre, post fun
return pre, post
}
func handleConnectionLost(ln *grpc.ClientConn) {
currentState := ln.GetState()
// currentState should be "Ready" when the connection is established.
if ln.WaitForStateChange(context.Background(), currentState) {
newState := ln.GetState()
// newState will be "Idle" if the connection is lost.
if newState == connectivity.Idle {
fmt.Println("\nLost connection to server. Exiting now.")
os.Exit(1)
}
}
}
+26 -9
View File
@@ -1,19 +1,36 @@
package cli
/*
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 (
"errors"
"github.com/rsteube/carapace"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
"github.com/bishopfox/sliver/client/command"
"github.com/bishopfox/sliver/client/command/use"
"github.com/bishopfox/sliver/client/console"
"github.com/bishopfox/sliver/client/constants"
"github.com/rsteube/carapace"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
)
func implantCmd(con *console.SliverConsoleClient) *cobra.Command {
func implantCmd(con *console.SliverClient) *cobra.Command {
con.IsCLI = true
makeCommands := command.SliverCommands(con)
@@ -25,7 +42,7 @@ func implantCmd(con *console.SliverConsoleClient) *cobra.Command {
implantFlags.StringP("use", "s", "", "interact with a session")
cmd.Flags().AddFlagSet(implantFlags)
// Prerunners (console setup, connection, etc)
// Pre-runners (console setup, connection, etc)
cmd.PersistentPreRunE, cmd.PersistentPostRunE = makeRunners(cmd, con)
// Completions
@@ -34,7 +51,7 @@ func implantCmd(con *console.SliverConsoleClient) *cobra.Command {
return cmd
}
func makeRunners(implantCmd *cobra.Command, con *console.SliverConsoleClient) (pre, post func(cmd *cobra.Command, args []string) error) {
func makeRunners(implantCmd *cobra.Command, con *console.SliverClient) (pre, post func(cmd *cobra.Command, args []string) error) {
startConsole, closeConsole := consoleRunnerCmd(con, false)
// The pre-run function connects to the server and sets up a "fake" console,
@@ -59,7 +76,7 @@ func makeRunners(implantCmd *cobra.Command, con *console.SliverConsoleClient) (p
return pre, closeConsole
}
func makeCompleters(cmd *cobra.Command, con *console.SliverConsoleClient) {
func makeCompleters(cmd *cobra.Command, con *console.SliverClient) {
comps := carapace.Gen(cmd)
comps.PreRun(func(cmd *cobra.Command, args []string) {
@@ -67,7 +84,7 @@ func makeCompleters(cmd *cobra.Command, con *console.SliverConsoleClient) {
})
// Bind completers to flags (wrap them to use the same pre-runners)
command.FlagComps(cmd, func(comp *carapace.ActionMap) {
command.BindFlagCompletions(cmd, func(comp *carapace.ActionMap) {
(*comp)["use"] = carapace.ActionCallback(func(c carapace.Context) carapace.Action {
cmd.PersistentPreRunE(cmd, c.Args)
return use.SessionIDCompleter(con)
+1 -2
View File
@@ -22,10 +22,9 @@ import (
"fmt"
"os"
"github.com/bishopfox/sliver/client/assets"
"github.com/rsteube/carapace"
"github.com/spf13/cobra"
"github.com/bishopfox/sliver/client/assets"
)
func importCmd() *cobra.Command {
+1 -2
View File
@@ -21,9 +21,8 @@ package cli
import (
"fmt"
"github.com/spf13/cobra"
"github.com/bishopfox/sliver/client/version"
"github.com/spf13/cobra"
)
var cmdVersion = &cobra.Command{
+7 -8
View File
@@ -27,15 +27,14 @@ import (
"github.com/bishopfox/sliver/client/assets"
"github.com/bishopfox/sliver/client/command/settings"
"github.com/bishopfox/sliver/client/console"
"github.com/jedib0t/go-pretty/v6/table"
"github.com/jedib0t/go-pretty/v6/text"
"github.com/rsteube/carapace"
"github.com/spf13/cobra"
)
// AliasesCmd - The alias command
func AliasesCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []string) error {
// AliasesCmd - The alias command.
func AliasesCmd(cmd *cobra.Command, con *console.SliverClient, args []string) error {
if 0 < len(loadedAliases) {
PrintAliases(con)
} else {
@@ -45,8 +44,8 @@ func AliasesCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []str
return nil
}
// PrintAliases - Print a list of loaded aliases
func PrintAliases(con *console.SliverConsoleClient) {
// PrintAliases - Print a list of loaded aliases.
func PrintAliases(con *console.SliverClient) {
tw := table.NewWriter()
tw.SetStyle(settings.GetTableStyle(con))
tw.AppendHeader(table.Row{
@@ -88,8 +87,8 @@ func PrintAliases(con *console.SliverConsoleClient) {
con.Println(tw.Render())
}
// AliasCommandNameCompleter - Completer for installed extensions command names
func AliasCommandNameCompleter(prefix string, args []string, con *console.SliverConsoleClient) []string {
// AliasCommandNameCompleter - Completer for installed extensions command names.
func AliasCommandNameCompleter(prefix string, args []string, con *console.SliverClient) []string {
results := []string{}
for name := range loadedAliases {
if strings.HasPrefix(name, prefix) {
@@ -129,7 +128,7 @@ func getInstalledManifests() map[string]*AliasManifest {
return installedManifests
}
// AliasCommandNameCompleter - Completer for installed extensions command names
// AliasCommandNameCompleter - Completer for installed extensions command names.
func AliasCompleter() carapace.Action {
return carapace.ActionCallback(func(c carapace.Context) carapace.Action {
results := []string{}
+61
View File
@@ -0,0 +1,61 @@
package alias
import (
"github.com/bishopfox/sliver/client/command/flags"
"github.com/bishopfox/sliver/client/command/help"
"github.com/bishopfox/sliver/client/console"
consts "github.com/bishopfox/sliver/client/constants"
"github.com/rsteube/carapace"
"github.com/spf13/cobra"
)
// Commands returns the `alias` command and its child commands.
func Commands(con *console.SliverClient) []*cobra.Command {
aliasCmd := &cobra.Command{
Use: consts.AliasesStr,
Short: "List current aliases",
Long: help.GetHelpFor([]string{consts.AliasesStr}),
Run: func(cmd *cobra.Command, args []string) {
AliasesCmd(cmd, con, args)
},
GroupID: consts.GenericHelpGroup,
}
aliasLoadCmd := &cobra.Command{
Use: consts.LoadStr + " [ALIAS]",
Short: "Load a command alias",
Long: help.GetHelpFor([]string{consts.AliasesStr, consts.LoadStr}),
Args: cobra.ExactArgs(1),
Run: func(cmd *cobra.Command, args []string) {
AliasesLoadCmd(cmd, con, args)
},
}
aliasCmd.AddCommand(aliasLoadCmd)
flags.NewCompletions(aliasLoadCmd).PositionalCompletion(carapace.ActionDirectories().Tag("alias directory").Usage("path to the alias directory"))
aliasInstallCmd := &cobra.Command{
Use: consts.InstallStr + " [ALIAS]",
Short: "Install a command alias",
Long: help.GetHelpFor([]string{consts.AliasesStr, consts.InstallStr}),
Args: cobra.ExactArgs(1),
Run: func(cmd *cobra.Command, args []string) {
AliasesInstallCmd(cmd, con, args)
},
}
aliasCmd.AddCommand(aliasInstallCmd)
flags.NewCompletions(aliasInstallCmd).PositionalCompletion(carapace.ActionFiles().Tag("alias file"))
aliasRemove := &cobra.Command{
Use: consts.RmStr + " [ALIAS]",
Short: "Remove an alias",
Long: help.GetHelpFor([]string{consts.RmStr}),
Args: cobra.ExactArgs(1),
Run: func(cmd *cobra.Command, args []string) {
AliasesRemoveCmd(cmd, con, args)
},
}
flags.NewCompletions(aliasRemove).PositionalCompletion(AliasCompleter())
aliasCmd.AddCommand(aliasRemove)
return []*cobra.Command{aliasCmd}
}
+19 -14
View File
@@ -25,30 +25,29 @@ import (
"strings"
"github.com/AlecAivazis/survey/v2"
"github.com/spf13/cobra"
"github.com/bishopfox/sliver/client/assets"
"github.com/bishopfox/sliver/client/console"
"github.com/bishopfox/sliver/util"
"github.com/spf13/cobra"
)
// AliasesInstallCmd - Install an alias
func AliasesInstallCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []string) {
// AliasesInstallCmd - Install an alias.
func AliasesInstallCmd(cmd *cobra.Command, con *console.SliverClient, args []string) {
aliasLocalPath := args[0]
fi, err := os.Stat(aliasLocalPath)
if os.IsNotExist(err) {
con.PrintErrorf("Extension path '%s' does not exist", aliasLocalPath)
con.PrintErrorf("Alias path '%s' does not exist", aliasLocalPath)
return
}
if !fi.IsDir() {
InstallFromFile(aliasLocalPath, false, con)
InstallFromFile(aliasLocalPath, "", false, con)
} else {
installFromDir(aliasLocalPath, con)
}
}
// Install an extension from a directory
func installFromDir(aliasLocalPath string, con *console.SliverConsoleClient) {
// Install an extension from a directory.
func installFromDir(aliasLocalPath string, con *console.SliverClient) {
manifestData, err := os.ReadFile(filepath.Join(aliasLocalPath, ManifestFileName))
if err != nil {
con.PrintErrorf("Error reading %s: %s", ManifestFileName, err)
@@ -100,8 +99,8 @@ func installFromDir(aliasLocalPath string, con *console.SliverConsoleClient) {
con.Printf("done!\n")
}
// Install an extension from a .tar.gz file
func InstallFromFile(aliasGzFilePath string, autoOverwrite bool, con *console.SliverConsoleClient) *string {
// Install an extension from a .tar.gz file.
func InstallFromFile(aliasGzFilePath string, aliasName string, promptToOverwrite bool, con *console.SliverClient) *string {
manifestData, err := util.ReadFileFromTarGz(aliasGzFilePath, fmt.Sprintf("./%s", ManifestFileName))
if err != nil {
con.PrintErrorf("Failed to read %s from '%s': %s\n", ManifestFileName, aliasGzFilePath, err)
@@ -109,12 +108,18 @@ func InstallFromFile(aliasGzFilePath string, autoOverwrite bool, con *console.Sl
}
manifest, err := ParseAliasManifest(manifestData)
if err != nil {
con.PrintErrorf("Failed to parse %s: %s\n", ManifestFileName, err)
errorMsg := ""
if aliasName != "" {
errorMsg = fmt.Sprintf("Error processing manifest for alias %s - failed to parse %s: %s\n", aliasName, ManifestFileName, err)
} else {
errorMsg = fmt.Sprintf("Failed to parse %s: %s\n", ManifestFileName, err)
}
con.PrintErrorf(errorMsg)
return nil
}
installPath := filepath.Join(assets.GetAliasesDir(), filepath.Base(manifest.CommandName))
if _, err := os.Stat(installPath); !os.IsNotExist(err) {
if !autoOverwrite {
if promptToOverwrite {
con.PrintInfof("Alias '%s' already exists\n", manifest.CommandName)
confirm := false
prompt := &survey.Confirm{Message: "Overwrite current install?"}
@@ -140,7 +145,7 @@ func InstallFromFile(aliasGzFilePath string, autoOverwrite bool, con *console.Sl
}
for _, aliasFile := range manifest.Files {
if aliasFile.Path != "" {
err := installArtifact(aliasGzFilePath, installPath, aliasFile.Path, con)
err := installArtifact(aliasGzFilePath, installPath, aliasFile.Path)
if err != nil {
con.PrintErrorf("Failed to install file: %s\n", err)
forceRemoveAll(installPath)
@@ -152,7 +157,7 @@ func InstallFromFile(aliasGzFilePath string, autoOverwrite bool, con *console.Sl
return &installPath
}
func installArtifact(aliasGzFilePath string, installPath, artifactPath string, con *console.SliverConsoleClient) error {
func installArtifact(aliasGzFilePath string, installPath, artifactPath string) error {
data, err := util.ReadFileFromTarGz(aliasGzFilePath, fmt.Sprintf("./%s", strings.TrimPrefix(artifactPath, string(os.PathSeparator))))
if err != nil {
return err
+105 -51
View File
@@ -28,18 +28,18 @@ import (
"strings"
"github.com/AlecAivazis/survey/v2"
app "github.com/reeflective/console"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
"google.golang.org/protobuf/proto"
"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/packages"
"github.com/bishopfox/sliver/protobuf/clientpb"
"github.com/bishopfox/sliver/protobuf/sliverpb"
"github.com/bishopfox/sliver/util"
app "github.com/reeflective/console"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
"google.golang.org/protobuf/proto"
)
const (
@@ -53,30 +53,30 @@ const (
)
var (
// alias name -> manifest/command
// alias name -> manifest/command.
loadedAliases = map[string]*loadedAlias{}
defaultHostProc = map[string]string{
"windows": windowsDefaultHostProc,
"linux": windowsDefaultHostProc,
"linux": linuxDefaultHostProc,
"darwin": macosDefaultHostProc,
}
)
// Ties the manifest struct to the command struct
// Ties the manifest struct to the command struct.
type loadedAlias struct {
Manifest *AliasManifest
Command *cobra.Command
}
// AliasFile - An OS/Arch specific file
// AliasFile - An OS/Arch specific file.
type AliasFile struct {
OS string `json:"os"`
Arch string `json:"arch"`
Path string `json:"path"`
}
// AliasManifest - The manifest for an alias, contains metadata
// AliasManifest - The manifest for an alias, contains metadata.
type AliasManifest struct {
Name string `json:"name"`
Version string `json:"version"`
@@ -86,14 +86,17 @@ type AliasManifest struct {
Help string `json:"help"`
LongHelp string `json:"long_help"`
Entrypoint string `json:"entrypoint"`
AllowArgs bool `json:"allow_args"`
DefaultArgs string `json:"default_args"`
Files []*AliasFile `json:"files"`
IsReflective bool `json:"is_reflective"`
IsAssembly bool `json:"is_assembly"`
Entrypoint string `json:"entrypoint"`
AllowArgs bool `json:"allow_args"`
DefaultArgs string `json:"default_args"`
Files []*AliasFile `json:"files"`
IsReflective bool `json:"is_reflective"`
IsAssembly bool `json:"is_assembly"`
Schema *packages.OutputSchema `json:"schema"`
RootPath string `json:"-"`
RootPath string `json:"-"`
ArmoryName string `json:"-"`
ArmoryPK string `json:"-"`
}
func (ec *AliasManifest) getDefaultProcess(targetOS string) (proc string, err error) {
@@ -104,7 +107,7 @@ func (ec *AliasManifest) getDefaultProcess(targetOS string) (proc string, err er
return
}
func (a *AliasManifest) getFileForTarget(cmdName string, targetOS string, targetArch string) (string, error) {
func (a *AliasManifest) getFileForTarget(_ string, targetOS string, targetArch string) (string, error) {
filePath := ""
for _, extFile := range a.Files {
if targetOS == extFile.OS && targetArch == extFile.Arch {
@@ -124,7 +127,7 @@ func (a *AliasManifest) getFileForTarget(cmdName string, targetOS string, target
}
// AliasesLoadCmd - Locally load a alias into the Sliver shell.
func AliasesLoadCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []string) {
func AliasesLoadCmd(cmd *cobra.Command, con *console.SliverClient, args []string) {
dirPath := args[0]
// dirPath := ctx.Args.String("dir-path")
alias, err := LoadAlias(dirPath, cmd.Root(), con)
@@ -135,8 +138,8 @@ func AliasesLoadCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args [
}
}
// LoadAlias - Load an alias into the Sliver shell from a given directory
func LoadAlias(manifestPath string, cmd *cobra.Command, con *console.SliverConsoleClient) (*AliasManifest, error) {
// LoadAlias - Load an alias into the Sliver shell from a given directory.
func LoadAlias(manifestPath string, cmd *cobra.Command, con *console.SliverClient) (*AliasManifest, error) {
// retrieve alias manifest
var err error
manifestPath, err = filepath.Abs(manifestPath)
@@ -205,7 +208,7 @@ func LoadAlias(manifestPath string, cmd *cobra.Command, con *console.SliverConso
return aliasManifest, nil
}
// ParseAliasManifest - Parse an alias manifest
// ParseAliasManifest - Parse an alias manifest.
func ParseAliasManifest(data []byte) (*AliasManifest, error) {
// parse it
alias := &AliasManifest{}
@@ -238,10 +241,17 @@ func ParseAliasManifest(data []byte) (*AliasManifest, error) {
}
}
if alias.Schema != nil {
if !packages.IsValidSchemaType(alias.Schema.Name) {
return nil, fmt.Errorf("%s is not a valid schema type", alias.Schema.Name)
}
alias.Schema.IngestColumns()
}
return alias, nil
}
func runAliasCommand(cmd *cobra.Command, con *console.SliverConsoleClient, args []string) {
func runAliasCommand(cmd *cobra.Command, con *console.SliverClient, args []string) {
session, beacon := con.ActiveTarget.GetInteractive()
if session == nil && beacon == nil {
return
@@ -268,20 +278,20 @@ func runAliasCommand(cmd *cobra.Command, con *console.SliverConsoleClient, args
return
}
// args := ctx.Args.StringList("arguments")
var extArgs string
var extArgsStr string
if len(aliasManifest.DefaultArgs) != 0 && len(args) == 0 {
extArgs = aliasManifest.DefaultArgs
extArgsStr = aliasManifest.DefaultArgs
} else {
extArgs = strings.Join(args, " ")
extArgsStr = strings.Join(args, " ")
}
extArgs = strings.TrimSpace(extArgs)
extArgsStr = strings.TrimSpace(extArgsStr)
entryPoint := aliasManifest.Entrypoint
processArgsStr, _ := cmd.Flags().GetString("process-arguments")
// Special case for payloads with pass to Donut (.NET assemblies and sideloaded payloads):
// The Donut loader has a hard limit of 256 characters for the command line arguments, so
// we're alerting the user that the arguments will be truncated.
if len(extArgs) > 256 && (aliasManifest.IsAssembly || !aliasManifest.IsReflective) {
if len(extArgsStr) > 256 && (aliasManifest.IsAssembly || !aliasManifest.IsReflective) {
msgStr := ""
// The --in-process flag only exists for .NET assemblies (aliasManifest.IsAssembly == true).
// Groupping the two conditions together could crash the client since ctx.Flags.Type panics
@@ -353,13 +363,13 @@ func runAliasCommand(cmd *cobra.Command, con *console.SliverConsoleClient, args
// Execute Assembly
ctrl := make(chan bool)
msg := fmt.Sprintf("Executing %s %s ...", cmd.Name(), extArgs)
msg := fmt.Sprintf("Executing %s %s ...", cmd.Name(), extArgsStr)
con.SpinUntil(msg, ctrl)
executeAssemblyResp, err := con.Rpc.ExecuteAssembly(context.Background(), &sliverpb.ExecuteAssemblyReq{
Request: con.ActiveTarget.Request(cmd),
IsDLL: isDLL,
Process: processName,
Arguments: extArgs,
Arguments: args,
Assembly: binData,
Arch: arch,
Method: method,
@@ -386,11 +396,11 @@ func runAliasCommand(cmd *cobra.Command, con *console.SliverConsoleClient, args
con.PrintErrorf("Failed to decode call ext response %s\n", err)
return
}
PrintAssemblyOutput(cmd.Name(), executeAssemblyResp, outFilePath, con)
PrintAssemblyOutput(cmd.Name(), aliasManifest.Schema, executeAssemblyResp, outFilePath, con)
})
con.PrintAsyncResponse(executeAssemblyResp.Response)
} else {
PrintAssemblyOutput(cmd.Name(), executeAssemblyResp, outFilePath, con)
PrintAssemblyOutput(cmd.Name(), aliasManifest.Schema, executeAssemblyResp, outFilePath, con)
}
} else if aliasManifest.IsReflective {
@@ -399,11 +409,11 @@ func runAliasCommand(cmd *cobra.Command, con *console.SliverConsoleClient, args
// Spawn DLL
ctrl := make(chan bool)
msg := fmt.Sprintf("Executing %s %s ...", cmd.Name(), extArgs)
msg := fmt.Sprintf("Executing %s %s ...", cmd.Name(), extArgsStr)
con.SpinUntil(msg, ctrl)
spawnDllResp, err := con.Rpc.SpawnDll(context.Background(), &sliverpb.InvokeSpawnDllReq{
Request: con.ActiveTarget.Request(cmd),
Args: strings.Trim(extArgs, " "),
Args: args,
Data: binData,
ProcessName: processName,
EntryPoint: aliasManifest.Entrypoint,
@@ -425,11 +435,11 @@ func runAliasCommand(cmd *cobra.Command, con *console.SliverConsoleClient, args
con.PrintErrorf("Failed to decode call ext response %s\n", err)
return
}
PrintSpawnDLLOutput(cmd.Name(), spawnDllResp, outFilePath, con)
PrintSpawnDLLOutput(cmd.Name(), aliasManifest.Schema, spawnDllResp, outFilePath, con)
})
con.PrintAsyncResponse(spawnDllResp.Response)
} else {
PrintSpawnDLLOutput(cmd.Name(), spawnDllResp, outFilePath, con)
PrintSpawnDLLOutput(cmd.Name(), aliasManifest.Schema, spawnDllResp, outFilePath, con)
}
} else {
@@ -438,11 +448,11 @@ func runAliasCommand(cmd *cobra.Command, con *console.SliverConsoleClient, args
// Sideload
ctrl := make(chan bool)
msg := fmt.Sprintf("Executing %s %s ...", cmd.Name(), extArgs)
msg := fmt.Sprintf("Executing %s %s ...", cmd.Name(), extArgsStr)
con.SpinUntil(msg, ctrl)
sideloadResp, err := con.Rpc.Sideload(context.Background(), &sliverpb.SideloadReq{
Request: con.ActiveTarget.Request(cmd),
Args: extArgs,
Args: args,
Data: binData,
EntryPoint: entryPoint,
ProcessName: processName,
@@ -465,36 +475,80 @@ func runAliasCommand(cmd *cobra.Command, con *console.SliverConsoleClient, args
con.PrintErrorf("Failed to decode call ext response %s\n", err)
return
}
PrintSideloadOutput(cmd.Name(), sideloadResp, outFilePath, con)
PrintSideloadOutput(cmd.Name(), aliasManifest.Schema, sideloadResp, outFilePath, con)
})
con.PrintAsyncResponse(sideloadResp.Response)
} else {
PrintSideloadOutput(cmd.Name(), sideloadResp, outFilePath, con)
PrintSideloadOutput(cmd.Name(), aliasManifest.Schema, sideloadResp, outFilePath, con)
}
}
}
// PrintSpawnDLLOutput - Prints the output of a spawn dll command
func PrintSpawnDLLOutput(cmdName string, spawnDllResp *sliverpb.SpawnDll, outFilePath *os.File, con *console.SliverConsoleClient) {
con.PrintInfof("%s output:\n%s", cmdName, spawnDllResp.GetResult())
func getOutputWithSchema(schema *packages.OutputSchema, result string) string {
if schema == nil {
return result
}
outputSchema := packages.GetNewPackageOutput(schema.Name)
if outputSchema == nil {
return result
}
err := outputSchema.IngestData([]byte(result), schema.Columns(), schema.GroupBy)
if err != nil {
return result
}
return outputSchema.CreateTable()
}
// PrintSpawnDLLOutput - Prints the output of a spawn dll command.
func PrintSpawnDLLOutput(cmdName string, schema *packages.OutputSchema, spawnDllResp *sliverpb.SpawnDll, outFilePath *os.File, con *console.SliverClient) {
var result string
if schema != nil {
result = getOutputWithSchema(schema, spawnDllResp.GetResult())
} else {
result = spawnDllResp.GetResult()
}
con.PrintInfof("%s output:\n%s", cmdName, result)
// Output the raw result to the file
if outFilePath != nil {
outFilePath.Write([]byte(spawnDllResp.GetResult()))
outFilePath.WriteString(spawnDllResp.GetResult())
con.PrintInfof("Output saved to %s\n", outFilePath.Name())
}
}
// PrintSideloadOutput - Prints the output of a sideload command
func PrintSideloadOutput(cmdName string, sideloadResp *sliverpb.Sideload, outFilePath *os.File, con *console.SliverConsoleClient) {
con.PrintInfof("%s output:\n%s", cmdName, sideloadResp.GetResult())
// PrintSideloadOutput - Prints the output of a sideload command.
func PrintSideloadOutput(cmdName string, schema *packages.OutputSchema, sideloadResp *sliverpb.Sideload, outFilePath *os.File, con *console.SliverClient) {
var result string
if schema != nil {
result = getOutputWithSchema(schema, sideloadResp.GetResult())
} else {
result = sideloadResp.GetResult()
}
con.PrintInfof("%s output:\n%s", cmdName, result)
// Output the raw result to the file
if outFilePath != nil {
outFilePath.Write([]byte(sideloadResp.GetResult()))
outFilePath.WriteString(sideloadResp.GetResult())
con.PrintInfof("Output saved to %s\n", outFilePath.Name())
}
}
// PrintAssemblyOutput - Prints the output of an execute-assembly command
func PrintAssemblyOutput(cmdName string, execAsmResp *sliverpb.ExecuteAssembly, outFilePath *os.File, con *console.SliverConsoleClient) {
con.PrintInfof("%s output:\n%s", cmdName, string(execAsmResp.GetOutput()))
// PrintAssemblyOutput - Prints the output of an execute-assembly command.
func PrintAssemblyOutput(cmdName string, schema *packages.OutputSchema, execAsmResp *sliverpb.ExecuteAssembly, outFilePath *os.File, con *console.SliverClient) {
var result string
if schema != nil {
result = getOutputWithSchema(schema, string(execAsmResp.GetOutput()))
} else {
result = string(execAsmResp.GetOutput())
}
con.PrintInfof("%s output:\n%s", cmdName, result)
// Output the raw result to the file
if outFilePath != nil {
outFilePath.Write(execAsmResp.GetOutput())
con.PrintInfof("Output saved to %s\n", outFilePath.Name())
+4 -5
View File
@@ -25,14 +25,13 @@ import (
"path/filepath"
"github.com/AlecAivazis/survey/v2"
"github.com/spf13/cobra"
"github.com/bishopfox/sliver/client/assets"
"github.com/bishopfox/sliver/client/console"
"github.com/spf13/cobra"
)
// AliasesRemoveCmd - Locally load a alias into the Sliver shell.
func AliasesRemoveCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []string) {
func AliasesRemoveCmd(cmd *cobra.Command, con *console.SliverClient, args []string) {
name := args[0]
// name := ctx.Args.String("name")
if name == "" {
@@ -54,8 +53,8 @@ func AliasesRemoveCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args
}
}
// RemoveAliasByCommandName - Remove an alias by command name
func RemoveAliasByCommandName(commandName string, con *console.SliverConsoleClient) error {
// RemoveAliasByCommandName - Remove an alias by command name.
func RemoveAliasByCommandName(commandName string, con *console.SliverClient) error {
if commandName == "" {
return errors.New("command name is required")
}
+383 -89
View File
@@ -23,6 +23,7 @@ import (
"errors"
"fmt"
"net/url"
"slices"
"sync"
"time"
@@ -54,13 +55,24 @@ type ArmoryPackage struct {
RepoURL string `json:"repo_url"`
PublicKey string `json:"public_key"`
IsAlias bool `json:"-"`
IsAlias bool `json:"-"`
ArmoryName string `json:"-"`
/*
With support for multiple armories, the command name of a package
is not unique anymore, so we need something that is unique
to be able to keep track of packages.
This ID will be a hash calculated from properties of the package.
*/
ID string `json:"-"`
ArmoryPK string `json:"-"`
}
// ArmoryBundle - A list of packages
type ArmoryBundle struct {
Name string `json:"name"`
Packages []string `json:"packages"`
Name string `json:"name"`
Packages []string `json:"packages"`
ArmoryName string `json:"-"`
}
// ArmoryHTTPConfig - Configuration for armory HTTP client
@@ -89,48 +101,75 @@ type pkgCacheEntry struct {
Alias *alias.AliasManifest
Extension *extensions.ExtensionManifest
LastErr error
// This corresponds to Pkg.ID
ID string
}
var (
// public key -> armoryCacheEntry
indexCache = sync.Map{}
// public key -> armoryPkgCacheEntry
// package ID -> armoryPkgCacheEntry
pkgCache = sync.Map{}
// public key -> assets.ArmoryConfig
currentArmories = sync.Map{}
// cacheTime - How long to cache the index/pkg manifests
cacheTime = time.Hour
//cacheTime = time.Hour
cacheTime = 2 * time.Minute
// This will kill a download if exceeded so needs to be large
defaultTimeout = 15 * time.Minute
// Track whether armories have been initialized so that we know if we need to pull from the config
armoriesInitialized = false
// Track whether the default armory has been removed by the user (this is needed to prevent it from being readded in if they have removed it)
defaultArmoryRemoved = false
)
// ArmoryCmd - The main armory command
func ArmoryCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []string) {
armoriesConfig := assets.GetArmoriesConfig()
con.PrintInfof("Fetching %d armory index(es) ... ", len(armoriesConfig))
func ArmoryCmd(cmd *cobra.Command, con *console.SliverClient, args []string) {
armoriesConfig := getCurrentArmoryConfiguration()
if len(armoriesConfig) == 1 {
con.Printf("Reading armory index ... ")
} else {
con.PrintInfof("Reading %d armory indexes ... ", len(armoriesConfig))
}
clientConfig := parseArmoryHTTPConfig(cmd)
indexes := fetchIndexes(armoriesConfig, clientConfig)
indexes := fetchIndexes(clientConfig)
if len(indexes) != len(armoriesConfig) {
con.Printf("errors!\n")
indexCache.Range(func(key, value interface{}) bool {
cacheEntry := value.(indexCacheEntry)
if cacheEntry.LastErr != nil {
con.PrintErrorf("%s - %s\n", cacheEntry.RepoURL, cacheEntry.LastErr)
con.PrintErrorf("%s (%s) - %s\n", cacheEntry.ArmoryConfig.Name, cacheEntry.RepoURL, cacheEntry.LastErr)
}
return true
})
} else {
con.Printf("done!\n")
}
armoriesInitialized = true
if len(indexes) == 0 {
con.PrintInfof("No indexes found\n")
return
}
aliases := []*alias.AliasManifest{}
exts := []*extensions.ExtensionManifest{}
if 0 < len(indexes) {
con.PrintInfof("Fetching package information ... ")
fetchPackageSignatures(indexes, clientConfig)
for _, index := range indexes {
errorCount := 0
aliases := []*alias.AliasManifest{}
exts := []*extensions.ExtensionManifest{}
con.PrintInfof("Reading package information for armory %s ... ", index.ArmoryConfig.Name)
fetchPackageSignatures(index, clientConfig)
pkgCache.Range(func(key, value interface{}) bool {
cacheEntry := value.(pkgCacheEntry)
cacheEntry, ok := value.(pkgCacheEntry)
if !ok {
// Something is wrong with this entry
pkgCache.Delete(value)
return true
}
if cacheEntry.ArmoryConfig.PublicKey != index.ArmoryConfig.PublicKey {
return true
}
if cacheEntry.LastErr != nil {
errorCount++
if errorCount == 0 {
@@ -141,7 +180,7 @@ func ArmoryCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []stri
if cacheEntry.Pkg.IsAlias {
aliases = append(aliases, cacheEntry.Alias)
} else {
exts = append(exts, cacheEntry.Extension)
exts = append(exts, cacheEntry.Extension) //todo: check this isn't a bug
}
}
return true
@@ -149,32 +188,52 @@ func ArmoryCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []stri
if errorCount == 0 {
con.Printf("done!\n")
}
if 0 < len(aliases) || 0 < len(exts) {
con.Println()
PrintArmoryPackages(aliases, exts, con)
} else {
con.PrintInfof("No packages found\n")
}
}
if 0 < len(aliases) || 0 < len(exts) {
con.Println()
bundles := bundlesInCache()
if 0 < len(bundles) {
PrintArmoryBundles(bundles, con)
} else {
con.PrintInfof("No bundles found\n")
}
PrintArmoryPackages(aliases, exts, con)
} else {
con.PrintInfof("No indexes found\n")
con.PrintInfof("No packages found\n")
}
con.Println()
bundles := bundlesInCache()
if 0 < len(bundles) {
PrintArmoryBundles(bundles, con)
} else {
con.PrintInfof("No bundles found\n")
}
}
func refresh(clientConfig ArmoryHTTPConfig) {
armoriesConfig := assets.GetArmoriesConfig()
indexes := fetchIndexes(armoriesConfig, clientConfig)
fetchPackageSignatures(indexes, clientConfig)
getCurrentArmoryConfiguration()
indexes := fetchIndexes(clientConfig)
for _, index := range indexes {
fetchPackageSignatures(index, clientConfig)
}
}
func packagesInCache() ([]*alias.AliasManifest, []*extensions.ExtensionManifest) {
func countUniqueCommandsFromManifests(aliases []*alias.AliasManifest, exts []*extensions.ExtensionManifest) (int, int) {
uniqueAliasNames := []string{}
uniqueExtensionNames := []string{}
for _, alias := range aliases {
if !slices.Contains(uniqueAliasNames, alias.CommandName) {
uniqueAliasNames = append(uniqueAliasNames, alias.CommandName)
}
}
for _, ext := range exts {
for _, cmd := range ext.ExtCommand {
if !slices.Contains(uniqueExtensionNames, cmd.CommandName) {
uniqueExtensionNames = append(uniqueExtensionNames, cmd.CommandName)
}
}
}
return len(uniqueAliasNames), len(uniqueExtensionNames)
}
func packageManifestsInCache() ([]*alias.AliasManifest, []*extensions.ExtensionManifest) {
aliases := []*alias.AliasManifest{}
exts := []*extensions.ExtensionManifest{}
pkgCache.Range(func(key, value interface{}) bool {
@@ -183,7 +242,7 @@ func packagesInCache() ([]*alias.AliasManifest, []*extensions.ExtensionManifest)
if cacheEntry.Pkg.IsAlias {
aliases = append(aliases, cacheEntry.Alias)
} else {
exts = append(exts, cacheEntry.Extension)
exts = append(exts, cacheEntry.Extension) //todo: check this isn't a bug
}
}
return true
@@ -191,6 +250,125 @@ func packagesInCache() ([]*alias.AliasManifest, []*extensions.ExtensionManifest)
return aliases, exts
}
func armoryLookupByName(name string) *assets.ArmoryConfig {
var result *assets.ArmoryConfig
indexCache.Range(func(key, value interface{}) bool {
indexEntry, ok := value.(indexCacheEntry)
if !ok {
// Keep going
return true
}
if indexEntry.ArmoryConfig.Name == name {
result = indexEntry.ArmoryConfig
return false
}
return true
})
return result
}
// Returns the packages in the cache with a given name
func packageCacheLookupByName(name string) []*pkgCacheEntry {
var result []*pkgCacheEntry = make([]*pkgCacheEntry, 0)
pkgCache.Range(func(key, value interface{}) bool {
cacheEntry, ok := value.(pkgCacheEntry)
if !ok {
// Keep going
return true
}
if cacheEntry.Pkg.Name == name {
result = append(result, &cacheEntry)
}
return true
})
return result
}
// Returns the packages in the cache for a given command name
func packageCacheLookupByCmd(commandName string) []*pkgCacheEntry {
var result []*pkgCacheEntry = make([]*pkgCacheEntry, 0)
pkgCache.Range(func(key, value interface{}) bool {
cacheEntry, ok := value.(pkgCacheEntry)
if !ok {
// Keep going
return true
}
if cacheEntry.Pkg.CommandName == commandName {
result = append(result, &cacheEntry)
}
return true
})
return result
}
// Returns the package in the cache for a given command name and armory
func packageCacheLookupByCmdAndArmory(commandName string, armoryPublicKey string) *pkgCacheEntry {
var result *pkgCacheEntry
pkgCache.Range(func(key, value interface{}) bool {
cacheEntry, ok := value.(pkgCacheEntry)
if !ok {
// Keep going
return true
}
if cacheEntry.ArmoryConfig.PublicKey == armoryPublicKey && cacheEntry.Pkg.CommandName == commandName {
result = &cacheEntry
// Stop iterating
return false
}
return true
})
return result
}
// Returns the package hashes in the cache for a given armory
func packageHashLookupByArmory(armoryPublicKey string) []string {
result := []string{}
pkgCache.Range(func(key, value interface{}) bool {
cacheEntry, ok := value.(pkgCacheEntry)
if !ok {
// Keep going
return true
}
if cacheEntry.ArmoryConfig.PublicKey == armoryPublicKey {
result = append(result, cacheEntry.ID)
}
return true
})
return result
}
func packageCacheLookupByID(packageID string) *pkgCacheEntry {
var packageEntry *pkgCacheEntry
pkgCache.Range(func(key, value interface{}) bool {
cacheEntry, ok := value.(pkgCacheEntry)
if !ok {
// Keep going
return true
}
if cacheEntry.LastErr == nil {
if cacheEntry.ID == packageID {
packageEntry = &cacheEntry
// Stop iterating
return false
}
}
return true
})
return packageEntry
}
func bundlesInCache() []*ArmoryBundle {
bundles := []*ArmoryBundle{}
indexCache.Range(func(key, value interface{}) bool {
@@ -207,7 +385,7 @@ func AliasExtensionOrBundleCompleter() carapace.Action {
var action carapace.Action
results := []string{}
aliases, exts := packagesInCache()
aliases, exts := packageManifestsInCache()
bundles := bundlesInCache()
for _, aliasPkg := range aliases {
@@ -217,9 +395,11 @@ func AliasExtensionOrBundleCompleter() carapace.Action {
aliasesComps := carapace.ActionValuesDescribed(results...).Tag("aliases").Invoke(ctx)
results = make([]string, 0)
for _, extensionPkg := range exts {
results = append(results, extensionPkg.CommandName)
results = append(results, extensionPkg.Help)
for _, extension := range exts {
for _, extensionPkg := range extension.ExtCommand {
results = append(results, extensionPkg.CommandName)
results = append(results, extensionPkg.Help)
}
}
extentionComps := carapace.ActionValuesDescribed(results...).Tag("extensions").Invoke(ctx)
results = make([]string, 0)
@@ -240,7 +420,7 @@ func AliasExtensionOrBundleCompleter() carapace.Action {
}
// PrintArmoryPackages - Prints the armory packages
func PrintArmoryPackages(aliases []*alias.AliasManifest, exts []*extensions.ExtensionManifest, con *console.SliverConsoleClient) {
func PrintArmoryPackages(aliases []*alias.AliasManifest, exts []*extensions.ExtensionManifest, con *console.SliverClient) {
width, _, err := term.GetSize(0)
if err != nil {
width = 1
@@ -254,6 +434,7 @@ func PrintArmoryPackages(aliases []*alias.AliasManifest, exts []*extensions.Exte
if con.Settings.SmallTermWidth+urlMargin < width {
tw.AppendHeader(table.Row{
"Armory",
"Command Name",
"Version",
"Type",
@@ -262,6 +443,7 @@ func PrintArmoryPackages(aliases []*alias.AliasManifest, exts []*extensions.Exte
})
} else {
tw.AppendHeader(table.Row{
"Armory",
"Command Name",
"Version",
"Type",
@@ -271,10 +453,11 @@ func PrintArmoryPackages(aliases []*alias.AliasManifest, exts []*extensions.Exte
// Columns start at 1 for some dumb reason
tw.SortBy([]table.SortBy{
{Number: 1, Mode: table.Asc},
{Number: 2, Mode: table.Asc},
})
type pkgInfo struct {
ArmoryName string
CommandName string
Version string
Type string
@@ -282,8 +465,10 @@ func PrintArmoryPackages(aliases []*alias.AliasManifest, exts []*extensions.Exte
URL string
}
entries := []pkgInfo{}
for _, aliasPkg := range aliases {
entries = append(entries, pkgInfo{
ArmoryName: aliasPkg.ArmoryName,
CommandName: aliasPkg.CommandName,
Version: aliasPkg.Version,
Type: "Alias",
@@ -291,14 +476,17 @@ func PrintArmoryPackages(aliases []*alias.AliasManifest, exts []*extensions.Exte
URL: aliasPkg.RepoURL,
})
}
for _, extension := range exts {
entries = append(entries, pkgInfo{
CommandName: extension.CommandName,
Version: extension.Version,
Type: "Extension",
Help: extension.Help,
URL: extension.RepoURL,
})
for _, extm := range exts {
for _, extension := range extm.ExtCommand {
entries = append(entries, pkgInfo{
ArmoryName: extm.ArmoryName,
CommandName: extension.CommandName,
Version: extension.Manifest.Version,
Type: "Extension",
Help: extension.Help,
URL: extension.Manifest.RepoURL,
})
}
}
sliverMenu := con.App.Menu("implant")
@@ -311,6 +499,7 @@ func PrintArmoryPackages(aliases []*alias.AliasManifest, exts []*extensions.Exte
}
if con.Settings.SmallTermWidth+urlMargin < width {
rows = append(rows, table.Row{
fmt.Sprintf(color+"%s"+console.Normal, pkg.ArmoryName),
fmt.Sprintf(color+"%s"+console.Normal, pkg.CommandName),
fmt.Sprintf(color+"%s"+console.Normal, pkg.Version),
fmt.Sprintf(color+"%s"+console.Normal, pkg.Type),
@@ -319,6 +508,7 @@ func PrintArmoryPackages(aliases []*alias.AliasManifest, exts []*extensions.Exte
})
} else {
rows = append(rows, table.Row{
fmt.Sprintf(color+"%s"+console.Normal, pkg.ArmoryName),
fmt.Sprintf(color+"%s"+console.Normal, pkg.CommandName),
fmt.Sprintf(color+"%s"+console.Normal, pkg.Version),
fmt.Sprintf(color+"%s"+console.Normal, pkg.Type),
@@ -331,11 +521,12 @@ func PrintArmoryPackages(aliases []*alias.AliasManifest, exts []*extensions.Exte
}
// PrintArmoryBundles - Prints the armory bundles
func PrintArmoryBundles(bundles []*ArmoryBundle, con *console.SliverConsoleClient) {
func PrintArmoryBundles(bundles []*ArmoryBundle, con *console.SliverClient) {
tw := table.NewWriter()
tw.SetStyle(settings.GetTableStyle(con))
tw.SetTitle(console.Bold + "Bundles" + console.Normal)
tw.AppendHeader(table.Row{
"Armory Name",
"Name",
"Contains",
})
@@ -361,6 +552,7 @@ func PrintArmoryBundles(bundles []*ArmoryBundle, con *console.SliverConsoleClien
}
}
tw.AppendRow(table.Row{
bundle.ArmoryName,
bundle.Name,
packages,
})
@@ -398,12 +590,19 @@ func parseArmoryHTTPConfig(cmd *cobra.Command) ArmoryHTTPConfig {
// fetch armory indexes, only returns indexes that were fetched successfully
// errors are still in the cache objects however and can be checked
func fetchIndexes(armoryConfigs []*assets.ArmoryConfig, clientConfig ArmoryHTTPConfig) []ArmoryIndex {
func fetchIndexes(clientConfig ArmoryHTTPConfig) []ArmoryIndex {
wg := &sync.WaitGroup{}
for _, armoryConfig := range armoryConfigs {
wg.Add(1)
go fetchIndex(armoryConfig, clientConfig, wg)
}
// Try to get a max of 10 indexes at a time
currentRequests := make(chan struct{}, 10)
currentArmories.Range(func(key, value interface{}) bool {
armoryEntry := value.(assets.ArmoryConfig)
if armoryEntry.Enabled {
wg.Add(1)
currentRequests <- struct{}{}
go fetchIndex(&armoryEntry, currentRequests, clientConfig, wg)
}
return true
})
wg.Wait()
indexes := []ArmoryIndex{}
indexCache.Range(func(key, value interface{}) bool {
@@ -416,13 +615,19 @@ func fetchIndexes(armoryConfigs []*assets.ArmoryConfig, clientConfig ArmoryHTTPC
return indexes
}
func fetchIndex(armoryConfig *assets.ArmoryConfig, clientConfig ArmoryHTTPConfig, wg *sync.WaitGroup) {
func fetchIndex(armoryConfig *assets.ArmoryConfig, requestChannel chan struct{}, clientConfig ArmoryHTTPConfig, wg *sync.WaitGroup) {
defer wg.Done()
defer func() {
<-requestChannel
}()
cacheEntry, ok := indexCache.Load(armoryConfig.PublicKey)
if ok {
cached := cacheEntry.(indexCacheEntry)
if time.Since(cached.Fetched) < cacheTime && cached.LastErr == nil && !clientConfig.IgnoreCache {
return
} else if time.Since(cached.Fetched) >= cacheTime {
// If an index has gone stale, remove it from the index cache
indexCache.Delete(armoryConfig.PublicKey)
}
}
@@ -459,40 +664,95 @@ func fetchIndex(armoryConfig *assets.ArmoryConfig, clientConfig ArmoryHTTPConfig
}
}
func fetchPackageSignatures(indexes []ArmoryIndex, clientConfig ArmoryHTTPConfig) {
wg := &sync.WaitGroup{}
for _, index := range indexes {
for _, armoryPkg := range index.Extensions {
wg.Add(1)
armoryPkg.IsAlias = false
go fetchPackageSignature(wg, index.ArmoryConfig, armoryPkg, clientConfig)
}
for _, armoryPkg := range index.Aliases {
wg.Add(1)
armoryPkg.IsAlias = true
go fetchPackageSignature(wg, index.ArmoryConfig, armoryPkg, clientConfig)
}
func calculateHashesForIndex(index ArmoryIndex) []string {
result := []string{}
for _, pkg := range index.Aliases {
result = append(result, calculatePackageHash(pkg))
}
wg.Wait()
for _, pkg := range index.Extensions {
result = append(result, calculatePackageHash(pkg))
}
return result
}
func fetchPackageSignature(wg *sync.WaitGroup, armoryConfig *assets.ArmoryConfig, armoryPkg *ArmoryPackage, clientConfig ArmoryHTTPConfig) {
func makePackageCacheConsistent(index ArmoryIndex) {
packagesToRemove := []string{}
// Get the packages for the armory out of the cache
cacheHashesForArmory := packageHashLookupByArmory(index.ArmoryConfig.PublicKey)
indexHashesForArmory := calculateHashesForIndex(index)
if len(cacheHashesForArmory) > len(indexHashesForArmory) {
// Then there are packages in the cache that do not exist in the armory
if len(indexHashesForArmory) == 0 {
packagesToRemove = cacheHashesForArmory
} else {
for _, packageHash := range indexHashesForArmory {
if !slices.Contains(cacheHashesForArmory, packageHash) {
packagesToRemove = append(packagesToRemove, packageHash)
}
}
}
}
// The remaining case of there being packages in the armory that do not exist in the cache
// will have to be solved with fetchPackageSignatures, and that function calls this one
// after fetching signatures and storing them in the cache, so that case should not apply
for _, packageHash := range packagesToRemove {
pkgCache.Delete(packageHash)
}
}
func fetchPackageSignatures(index ArmoryIndex, clientConfig ArmoryHTTPConfig) {
wg := &sync.WaitGroup{}
// Be kind to armories and limit concurrent requests to 10
// This is an arbritrary number and we may have to tweak it if it causes problems
currentRequests := make(chan struct{}, 10)
for _, armoryPkg := range index.Extensions {
wg.Add(1)
currentRequests <- struct{}{}
armoryPkg.IsAlias = false
go fetchPackageSignature(wg, currentRequests, index.ArmoryConfig, armoryPkg, clientConfig)
}
for _, armoryPkg := range index.Aliases {
wg.Add(1)
currentRequests <- struct{}{}
armoryPkg.IsAlias = true
go fetchPackageSignature(wg, currentRequests, index.ArmoryConfig, armoryPkg, clientConfig)
}
wg.Wait()
// If packages were deleted from the index, make sure the cache is consistent
makePackageCacheConsistent(index)
}
func fetchPackageSignature(wg *sync.WaitGroup, requestChannel chan struct{}, armoryConfig *assets.ArmoryConfig, armoryPkg *ArmoryPackage, clientConfig ArmoryHTTPConfig) {
defer wg.Done()
cacheEntry, ok := pkgCache.Load(armoryPkg.CommandName)
defer func() {
<-requestChannel
}()
cacheEntry, ok := pkgCache.Load(armoryPkg.ID)
if ok {
cached := cacheEntry.(pkgCacheEntry)
if time.Since(cached.Fetched) < cacheTime && cached.LastErr == nil && !clientConfig.IgnoreCache {
return
} else if time.Since(cached.Fetched) >= cacheTime {
// If a package has gone stale, remove it from the package cache
pkgCache.Delete(armoryPkg.ID)
}
}
pkgCacheEntry := &pkgCacheEntry{
ArmoryConfig: armoryConfig,
RepoURL: armoryPkg.RepoURL,
ID: armoryPkg.ID,
}
defer func() {
pkgCacheEntry.Fetched = time.Now()
pkgCache.Store(armoryPkg.CommandName, *pkgCacheEntry)
pkgCache.Store(armoryPkg.ID, *pkgCacheEntry)
}()
repoURL, err := url.Parse(armoryPkg.RepoURL)
@@ -524,19 +784,53 @@ func fetchPackageSignature(wg *sync.WaitGroup, armoryConfig *assets.ArmoryConfig
if armoryPkg != nil {
pkgCacheEntry.Pkg = *armoryPkg
}
if err == nil {
manifestData, err := base64.StdEncoding.DecodeString(sig.TrustedComment)
if err != nil {
pkgCacheEntry.LastErr = fmt.Errorf("failed to b64 decode trusted comment: %s", err)
return
}
if armoryPkg.IsAlias {
pkgCacheEntry.Alias, err = alias.ParseAliasManifest(manifestData)
} else {
pkgCacheEntry.Extension, err = extensions.ParseExtensionManifest(manifestData)
}
if err != nil {
pkgCacheEntry.LastErr = fmt.Errorf("failed to parse trusted manifest in pkg signature: %s", err)
}
manifestData, err := base64.StdEncoding.DecodeString(sig.TrustedComment)
if err != nil {
pkgCacheEntry.LastErr = fmt.Errorf("failed to b64 decode trusted comment: %s", err)
return
}
if armoryPkg.IsAlias {
pkgCacheEntry.Alias, err = alias.ParseAliasManifest(manifestData)
pkgCacheEntry.Alias.ArmoryName = armoryConfig.Name
pkgCacheEntry.Alias.ArmoryPK = armoryConfig.PublicKey
} else {
pkgCacheEntry.Extension, err = extensions.ParseExtensionManifest(manifestData)
pkgCacheEntry.Extension.ArmoryName = armoryConfig.Name
pkgCacheEntry.Extension.ArmoryPK = armoryConfig.PublicKey
}
if err != nil {
pkgCacheEntry.LastErr = fmt.Errorf("failed to parse trusted manifest in pkg signature: %s", err)
}
}
func clearAllCaches() {
currentArmories.Range(func(key, value any) bool {
currentArmories.Delete(key)
return true
})
indexCache.Range(func(key, value any) bool {
indexCache.Delete(key)
return true
})
pkgCache.Range(func(key, value any) bool {
pkgCache.Delete(key)
return true
})
}
func getArmoryPublicKey(armoryName string) string {
// Find PK for the armory name
armoryPK := ""
currentArmories.Range(func(key, value any) bool {
armoryEntry := value.(assets.ArmoryConfig)
if armoryEntry.Name == armoryName {
armoryPK = armoryEntry.PublicKey
return false
}
return true
})
return armoryPK
}
+211
View File
@@ -0,0 +1,211 @@
package armory
import (
"github.com/rsteube/carapace"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
"github.com/bishopfox/sliver/client/command/completers"
"github.com/bishopfox/sliver/client/command/flags"
"github.com/bishopfox/sliver/client/command/help"
"github.com/bishopfox/sliver/client/console"
consts "github.com/bishopfox/sliver/client/constants"
)
// Commands returns the `armory` command and its subcommands.
func Commands(con *console.SliverClient) []*cobra.Command {
armoryCmd := &cobra.Command{
Use: consts.ArmoryStr,
Short: "Automatically download and install extensions/aliases",
Long: help.GetHelpFor([]string{consts.ArmoryStr}),
Run: func(cmd *cobra.Command, args []string) {
ArmoryCmd(cmd, con, args)
},
GroupID: consts.GenericHelpGroup,
}
flags.Bind("connection", true, armoryCmd, func(f *pflag.FlagSet) {
f.BoolP("insecure", "I", false, "skip tls certificate validation")
f.StringP("proxy", "p", "", "specify a proxy url (e.g. http://localhost:8080)")
f.BoolP("ignore-cache", "c", false, "ignore metadata cache, force refresh")
f.StringP("timeout", "t", "15m", "download timeout")
})
flags.BindFlagCompletions(armoryCmd, func(comp *carapace.ActionMap) {
(*comp)["proxy"] = completers.LocalProxyCompleter()
})
armoryInstallCmd := &cobra.Command{
Use: consts.InstallStr,
Short: "Install an alias or extension",
Long: help.GetHelpFor([]string{consts.ArmoryStr, consts.InstallStr}),
Args: cobra.ExactArgs(1),
Run: func(cmd *cobra.Command, args []string) {
ArmoryInstallCmd(cmd, con, args)
},
}
flags.Bind("", false, armoryInstallCmd, func(f *pflag.FlagSet) {
f.BoolP("force", "f", false, "force installation of package, overwriting the package if it exists")
f.StringP("armory", "a", "", "name of armory to install package from")
})
armoryCmd.AddCommand(armoryInstallCmd)
flags.NewCompletions(armoryInstallCmd).PositionalCompletion(
AliasExtensionOrBundleCompleter().Usage("name of the extension or alias to install"),
)
armoryUpdateCmd := &cobra.Command{
Use: consts.UpdateStr,
Short: "Update installed aliases and extensions",
Long: help.GetHelpFor([]string{consts.ArmoryStr, consts.UpdateStr}),
Run: func(cmd *cobra.Command, args []string) {
ArmoryUpdateCmd(cmd, con, args)
},
}
flags.Bind("", false, armoryUpdateCmd, func(f *pflag.FlagSet) {
f.StringP("armory", "a", "", "name of armory to get updates from")
})
armoryCmd.AddCommand(armoryUpdateCmd)
armorySearchCmd := &cobra.Command{
Use: consts.SearchStr,
Short: "Search for aliases and extensions by name (regex)",
Long: help.GetHelpFor([]string{consts.ArmoryStr, consts.SearchStr}),
Args: cobra.ExactArgs(1),
Run: func(cmd *cobra.Command, args []string) {
ArmorySearchCmd(cmd, con, args)
},
}
armoryCmd.AddCommand(armorySearchCmd)
flags.NewCompletions(armorySearchCmd).PositionalCompletion(carapace.ActionValues().Usage("a name regular expression"))
armoryInfoCmd := &cobra.Command{
Use: consts.InfoStr,
Short: "View configured armories or details about a specific armory or package",
Args: cobra.RangeArgs(0, 1),
Long: help.GetHelpFor([]string{consts.ArmoryStr, consts.InfoStr}),
Run: func(cmd *cobra.Command, args []string) {
ArmoryInfoCommand(cmd, con, args)
},
}
armoryCmd.AddCommand(armoryInfoCmd)
carapace.Gen(armoryInfoCmd).PositionalCompletion(
carapace.ActionValues().Usage("armory or package name"),
)
armoryAddCmd := &cobra.Command{
Use: consts.AddStr,
Short: "Add a new armory",
Long: help.GetHelpFor([]string{consts.ArmoryStr, consts.AddStr}),
Args: cobra.ExactArgs(1), // the name of the armory
Run: func(cmd *cobra.Command, args []string) {
AddArmoryCmd(cmd, con, args)
},
}
flags.Bind("", false, armoryAddCmd, func(f *pflag.FlagSet) {
f.StringP("url", "u", "", "The URL of the armory index (required)")
f.StringP("pubkey", "k", "", "The public key for the armory (required)")
f.StringP("auth", "a", "", "Authorization details / credentials for the armory")
f.StringP("authcmd", "x", "", "Local command to run for authorization to the armory")
f.BoolP("no-save", "e", false, "Do not save this armory configuration to disk")
})
armoryAddCmd.MarkFlagRequired("url")
armoryAddCmd.MarkFlagRequired("pubkey")
carapace.Gen(armoryAddCmd).PositionalCompletion(
carapace.ActionValues().Usage("name of the armory"),
)
armoryCmd.AddCommand(armoryAddCmd)
armoryRemoveCmd := &cobra.Command{
Use: consts.RmStr,
Short: "Remove an armory",
Long: help.GetHelpFor([]string{consts.ArmoryStr, consts.RmStr}),
Args: cobra.ExactArgs(1), // the name of the armory
Run: func(cmd *cobra.Command, args []string) {
RemoveArmoryCmd(cmd, con, args)
},
}
carapace.Gen(armoryAddCmd).PositionalCompletion(
carapace.ActionValues().Usage("name of the armory"),
)
armoryCmd.AddCommand(armoryRemoveCmd)
armorySaveCmd := &cobra.Command{
Use: consts.SaveStr,
Short: "Save the armory configuration to disk",
Long: help.GetHelpFor([]string{consts.ArmoryStr, consts.SaveStr}),
Run: func(cmd *cobra.Command, args []string) {
SaveArmories(con)
},
}
armoryCmd.AddCommand(armorySaveCmd)
armoryEnableCmd := &cobra.Command{
Use: consts.EnableStr,
Short: "Enable an armory",
Long: help.GetHelpFor([]string{consts.ArmoryStr, consts.EnableStr}),
Args: cobra.ExactArgs(1), // The name of the armory
Run: func(cmd *cobra.Command, args []string) {
ChangeArmoryEnabledState(cmd, con, args, true)
},
}
carapace.Gen(armoryEnableCmd).PositionalCompletion(
carapace.ActionValues().Usage("name of the armory"),
)
armoryCmd.AddCommand(armoryEnableCmd)
armoryDisableCmd := &cobra.Command{
Use: consts.DisableStr,
Short: "Disable an armory",
Long: help.GetHelpFor([]string{consts.ArmoryStr, consts.DisableStr}),
Args: cobra.ExactArgs(1), // The name of the armory
Run: func(cmd *cobra.Command, args []string) {
ChangeArmoryEnabledState(cmd, con, args, false)
},
}
carapace.Gen(armoryDisableCmd).PositionalCompletion(
carapace.ActionValues().Usage("name of the armory"),
)
armoryCmd.AddCommand(armoryDisableCmd)
armoryModifyCmd := &cobra.Command{
Use: consts.ModifyStr,
Short: "Modify an armory configuration",
Long: help.GetHelpFor([]string{consts.ArmoryStr, consts.ModifyStr}),
Args: cobra.ExactArgs(1), // The name of the armory
Run: func(cmd *cobra.Command, args []string) {
ModifyArmoryCmd(cmd, con, args)
},
}
flags.Bind("", false, armoryModifyCmd, func(f *pflag.FlagSet) {
f.StringP("name", "n", "", "new name for the armory")
f.StringP("pubkey", "k", "", "new public key for the armory")
f.StringP("url", "u", "", "new URL for the armory")
f.StringP("auth", "a", "", "new authorization details / credentials for the armory")
f.StringP("authcmd", "x", "", "new local command to run for authorization to the armory")
f.BoolP("no-save", "e", false, "do not save armory configuration to armory configuration file")
})
carapace.Gen(armoryModifyCmd).PositionalCompletion(
carapace.ActionValues().Usage("name of the armory"),
)
armoryCmd.AddCommand(armoryModifyCmd)
armoryRefreshCmd := &cobra.Command{
Use: consts.RefreshStr,
Short: "Refresh armory indexes",
Long: help.GetHelpFor([]string{consts.ArmoryStr, consts.RefreshStr}),
Run: func(cmd *cobra.Command, args []string) {
RefreshArmories(cmd, con)
},
}
armoryCmd.AddCommand(armoryRefreshCmd)
armoryResetCmd := &cobra.Command{
Use: consts.ResetStr,
Short: "Reset armory configuration",
Long: help.GetHelpFor([]string{consts.ArmoryStr, consts.ResetStr}),
Run: func(cmd *cobra.Command, args []string) {
ResetArmoryConfig(cmd, con)
},
}
armoryCmd.AddCommand(armoryResetCmd)
return []*cobra.Command{armoryCmd}
}
+404 -121
View File
@@ -19,120 +19,444 @@ package armory
*/
import (
"encoding/json"
"errors"
"fmt"
"net/url"
"os"
"path/filepath"
"slices"
"github.com/AlecAivazis/survey/v2"
"github.com/spf13/cobra"
"github.com/bishopfox/sliver/client/assets"
"github.com/bishopfox/sliver/client/command/alias"
"github.com/bishopfox/sliver/client/command/extensions"
"github.com/bishopfox/sliver/client/console"
"github.com/bishopfox/sliver/client/constants"
"github.com/bishopfox/sliver/util"
"github.com/bishopfox/sliver/util/minisign"
)
// ErrPackageNotFound - The package was not found
var ErrPackageNotFound = errors.New("package not found")
var ErrPackageAlreadyInstalled = errors.New("package is already installed")
const (
doNotInstallOption = "Do not install this package"
doNotInstallPackageName = "do not install"
)
// ArmoryInstallCmd - The armory install command
func ArmoryInstallCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []string) {
func ArmoryInstallCmd(cmd *cobra.Command, con *console.SliverClient, args []string) {
var promptToOverwrite bool
name := args[0]
// name := ctx.Args.String("name")
if name == "" {
con.PrintErrorf("A package or bundle name is required")
return
}
forceInstallation, err := cmd.Flags().GetBool("force")
if err != nil {
con.PrintErrorf("Could not parse %q flag: %s\n", "force", err)
return
}
if forceInstallation {
promptToOverwrite = false
} else {
promptToOverwrite = true
}
armoryName, err := cmd.Flags().GetString("armory")
if err != nil {
con.PrintErrorf("Could not parse %q flag: %s\n", "armory", err)
return
}
// Find PK for the armory name
armoryPK := getArmoryPublicKey(armoryName)
// If the armory with the name is not found, print a warning
if cmd.Flags().Changed("armory") && armoryPK == "" {
con.PrintWarnf("Could not find a configured armory named %q - searching all configured armories\n\n", armoryName)
}
clientConfig := parseArmoryHTTPConfig(cmd)
refresh(clientConfig)
if name == "all" {
aliases, extensions := packagesInCache()
aliases, extensions := packageManifestsInCache()
aliasCount, extCount := countUniqueCommandsFromManifests(aliases, extensions)
confirm := false
pluralAliases := "es"
if aliasCount == 1 {
pluralAliases = ""
}
pluralExtensions := "s"
if extCount == 1 {
pluralExtensions = ""
}
prompt := &survey.Confirm{
Message: fmt.Sprintf("Install %d aliases and %d extensions?",
len(aliases), len(extensions),
Message: fmt.Sprintf("Install %d alias%s and %d extension%s?",
aliasCount, pluralAliases, extCount, pluralExtensions,
),
}
survey.AskOne(prompt, &confirm)
if !confirm {
return
}
promptToOverwrite = false
}
err := installPackageByName(name, clientConfig, con)
err = installPackageByName(name, armoryPK, forceInstallation, promptToOverwrite, clientConfig, con)
if err == nil {
return
}
if err == ErrPackageNotFound {
if errors.Is(err, ErrPackageNotFound) {
bundles := bundlesInCache()
for _, bundle := range bundles {
if bundle.Name == name {
installBundle(bundle, clientConfig, con)
installBundle(bundle, armoryPK, forceInstallation, clientConfig, con)
return
}
}
// If we have made it here, then there was not a bundle or package that matched the provided name
if armoryPK == "" {
con.PrintErrorf("No package or bundle named %q was found\n", name)
} else {
con.PrintErrorf("No package or bundle named %q was found in armory %s\n", name, armoryName)
}
} else if errors.Is(err, ErrPackageAlreadyInstalled) {
con.PrintErrorf("Package %q is already installed - use the force option to overwrite it\n", name)
} else {
con.PrintErrorf("Could not install package: %s\n", err)
}
}
func installBundle(bundle *ArmoryBundle, armoryPK string, forceInstallation bool, clientConfig ArmoryHTTPConfig, con *console.SliverClient) {
installList := []string{}
pendingPackages := make(map[string]string)
for _, bundlePkgName := range bundle.Packages {
packageInstallList, err := buildInstallList(bundlePkgName, armoryPK, forceInstallation, pendingPackages)
if err != nil {
if errors.Is(err, ErrPackageAlreadyInstalled) {
con.PrintInfof("Package %s is already installed. Skipping...\n", bundlePkgName)
continue
} else {
con.PrintErrorf("Error for package %s: %s\n", bundlePkgName, err)
return
}
}
for _, pkgID := range packageInstallList {
if !slices.Contains(installList, pkgID) {
installList = append(installList, pkgID)
}
}
}
for _, packageID := range installList {
packageEntry := packageCacheLookupByID(packageID)
if packageEntry == nil {
con.PrintErrorf("The package cache is out of date. Please run armory refresh and try again.\n")
return
}
if packageEntry.Pkg.IsAlias {
err := installAliasPackage(packageEntry, false, clientConfig, con)
if err != nil {
con.PrintErrorf("Failed to install alias '%s': %s", packageEntry.Alias.CommandName, err)
return
}
} else {
err := installExtensionPackage(packageEntry, false, clientConfig, con)
if err != nil {
con.PrintErrorf("Failed to install extension '%s': %s", packageEntry.Extension.Name, err)
return
}
}
}
con.PrintErrorf("No package or bundle named '%s' was found", name)
}
func installBundle(bundle *ArmoryBundle, clientConfig ArmoryHTTPConfig, con *console.SliverConsoleClient) {
for _, pkgName := range bundle.Packages {
err := installPackageByName(pkgName, clientConfig, con)
func getInstalledPackageNames() []string {
packageNames := []string{}
installedAliases := assets.GetInstalledAliasManifests()
installedExtensions := assets.GetInstalledExtensionManifests()
for _, aliasFileName := range installedAliases {
alias := &alias.AliasManifest{}
manifestData, err := os.ReadFile(aliasFileName)
if err != nil {
con.PrintErrorf("Failed to install '%s': %s", pkgName, err)
continue
}
err = json.Unmarshal(manifestData, alias)
if err != nil {
continue
}
if !slices.Contains(packageNames, alias.CommandName) {
packageNames = append(packageNames, alias.CommandName)
}
}
}
func installPackageByName(name string, clientConfig ArmoryHTTPConfig, con *console.SliverConsoleClient) error {
aliases, extensions := packagesInCache()
for _, alias := range aliases {
if alias.CommandName == name || name == "all" {
installAlias(alias, clientConfig, con)
if name != "all" {
return nil
for _, extensionFileName := range installedExtensions {
extension := &extensions.ExtensionManifest{}
manifestData, err := os.ReadFile(extensionFileName)
if err != nil {
continue
}
err = json.Unmarshal(manifestData, extension)
if err != nil {
continue
}
if len(extension.ExtCommand) == 0 {
extensionOld := &extensions.ExtensionManifest_{}
// Some extension manifests are using an older version
// To maintain compatibility with those extensions, we will
// re-unmarshal the data as the older version
err = json.Unmarshal(manifestData, extensionOld)
if err != nil {
continue
}
if !slices.Contains(packageNames, extensionOld.CommandName) {
packageNames = append(packageNames, extensionOld.CommandName)
}
} else {
for _, command := range extension.ExtCommand {
if !slices.Contains(packageNames, command.CommandName) {
packageNames = append(packageNames, command.CommandName)
}
}
}
}
for _, ext := range extensions {
if ext.CommandName == name || name == "all" {
installExtension(ext, clientConfig, con)
if name != "all" {
return nil
}
}
}
if name == "all" {
con.Printf("\n")
con.PrintInfof("All packages installed\n")
return nil
}
return ErrPackageNotFound
return packageNames
}
func installAlias(alias *alias.AliasManifest, clientConfig ArmoryHTTPConfig, con *console.SliverConsoleClient) {
err := installAliasPackageByName(alias.CommandName, clientConfig, con)
if err != nil {
con.PrintErrorf("Failed to install alias '%s': %s", alias.CommandName, err)
return
}
}
// This is a convenience function to get the names of the commands in the cache
func getCommandsInCache() []string {
commandNames := []string{}
func installAliasPackageByName(name string, clientConfig ArmoryHTTPConfig, con *console.SliverConsoleClient) error {
var entry *pkgCacheEntry
pkgCache.Range(func(key, value interface{}) bool {
cacheEntry := value.(pkgCacheEntry)
if cacheEntry.Pkg.CommandName == name {
entry = &cacheEntry
return false
if cacheEntry.LastErr == nil {
if cacheEntry.Pkg.IsAlias {
if !slices.Contains(commandNames, cacheEntry.Alias.CommandName) {
commandNames = append(commandNames, cacheEntry.Alias.CommandName)
}
} else {
for _, command := range cacheEntry.Extension.ExtCommand {
if !slices.Contains(commandNames, command.CommandName) {
commandNames = append(commandNames, command.CommandName)
}
}
}
}
return true
})
return commandNames
}
func getPackagesWithCommandName(name, armoryPK, minimumVersion string) []*pkgCacheEntry {
packages := []*pkgCacheEntry{}
pkgCache.Range(func(key, value interface{}) bool {
cacheEntry := value.(pkgCacheEntry)
if cacheEntry.LastErr == nil {
if cacheEntry.Pkg.IsAlias {
if cacheEntry.Alias.CommandName == name {
if minimumVersion == "" || (minimumVersion != "" && cacheEntry.Alias.Version >= minimumVersion) {
if armoryPK == "" || (armoryPK != "" && cacheEntry.ArmoryConfig.PublicKey == armoryPK) {
packages = append(packages, &cacheEntry)
}
}
}
} else {
for _, command := range cacheEntry.Extension.ExtCommand {
if command.CommandName == name {
if minimumVersion == "" || (minimumVersion != "" && cacheEntry.Extension.Version >= minimumVersion) {
if armoryPK == "" || (armoryPK != "" && cacheEntry.ArmoryConfig.PublicKey == armoryPK) {
packages = append(packages, &cacheEntry)
}
break
}
}
}
}
}
return true
})
return packages
}
func getPackageIDFromUser(name string, options map[string]string) string {
selectedPackageKey := ""
optionKeys := util.Keys(options)
slices.Sort(optionKeys)
// 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)
selectedPackageID := options[selectedPackageKey]
return selectedPackageID
}
func getPackageForCommand(name, armoryPK, minimumVersion string) (*pkgCacheEntry, error) {
packagesWithCommand := getPackagesWithCommandName(name, armoryPK, minimumVersion)
if len(packagesWithCommand) > 1 {
// Build an option map for the user to choose from (option -> pkgID)
optionMap := make(map[string]string)
for _, packageEntry := range packagesWithCommand {
var optionName string
if packageEntry.Pkg.IsAlias {
optionName = fmt.Sprintf("Alias %s %s from armory %s (%s)",
name,
packageEntry.Alias.Version,
packageEntry.ArmoryConfig.Name,
packageEntry.Pkg.RepoURL,
)
} else {
optionName = fmt.Sprintf("Extension %s %s from armory %s with command %s (%s)",
packageEntry.Pkg.Name,
packageEntry.Extension.Version,
packageEntry.ArmoryConfig.Name,
name,
packageEntry.Pkg.RepoURL,
)
}
optionMap[optionName] = packageEntry.ID
}
selectedPackageID := getPackageIDFromUser(name, optionMap)
if selectedPackageID == doNotInstallPackageName {
return nil, fmt.Errorf("user cancelled installation")
}
for _, packageEntry := range packagesWithCommand {
if packageEntry.ID == selectedPackageID {
return packageEntry, nil
}
}
} else if len(packagesWithCommand) == 1 {
return packagesWithCommand[0], nil
}
return nil, ErrPackageNotFound
}
func buildInstallList(name, armoryPK string, forceInstallation bool, pendingPackages map[string]string) ([]string, error) {
packageInstallList := []string{}
installedPackages := getInstalledPackageNames()
/*
Gather information about what we are working with
Find all conflicts within aliases for a given name (or all names), same thing with extensions
Then if there are aliases and extensions with a given name, make sure to note that for when we ask the user what to do
*/
var requestedPackageList []string
if name == "all" {
requestedPackageList = []string{}
allCommands := getCommandsInCache()
for _, cmdName := range allCommands {
if !slices.Contains(installedPackages, cmdName) || forceInstallation {
// Check to see if there is a package pending with that name
if _, ok := pendingPackages[cmdName]; !ok {
requestedPackageList = append(requestedPackageList, cmdName)
}
}
}
} else {
if !slices.Contains(installedPackages, name) || forceInstallation {
// Check to see if there is a package pending with that name
if _, ok := pendingPackages[name]; !ok {
requestedPackageList = []string{name}
}
} else {
return nil, ErrPackageAlreadyInstalled
}
}
for _, packageName := range requestedPackageList {
if _, ok := pendingPackages[packageName]; ok {
// We are already going to install a package with this name, so do not try to resolve it
continue
}
packageEntry, err := getPackageForCommand(packageName, armoryPK, "")
if err != nil {
return nil, err
}
if !slices.Contains(packageInstallList, packageEntry.ID) {
packageInstallList = append(packageInstallList, packageEntry.ID)
pendingPackages[packageName] = packageEntry.ID
}
if !packageEntry.Pkg.IsAlias {
dependencies := make(map[string]*pkgCacheEntry)
err = resolveExtensionPackageDependencies(packageEntry, dependencies, pendingPackages)
if err != nil {
return nil, err
}
for pkgName, packageEntry := range dependencies {
if !slices.Contains(packageInstallList, packageEntry.ID) {
packageInstallList = append(packageInstallList, packageEntry.ID)
}
if _, ok := pendingPackages[pkgName]; !ok {
pendingPackages[pkgName] = packageEntry.ID
}
}
}
}
return packageInstallList, nil
}
func installPackageByName(name, armoryPK string, forceInstallation, promptToOverwrite bool, clientConfig ArmoryHTTPConfig, con *console.SliverClient) error {
pendingPackages := make(map[string]string)
packageInstallList, err := buildInstallList(name, armoryPK, forceInstallation, pendingPackages)
if err != nil {
return err
}
if len(packageInstallList) > 0 {
for _, packageID := range packageInstallList {
entry := packageCacheLookupByID(packageID)
if entry == nil {
return errors.New("cache consistency error - please refresh the cache and try again")
}
if entry.Pkg.IsAlias {
err := installAliasPackage(entry, promptToOverwrite, clientConfig, con)
if err != nil {
return fmt.Errorf("failed to install alias '%s': %s", entry.Alias.CommandName, err)
}
} else {
err := installExtensionPackage(entry, promptToOverwrite, clientConfig, con)
if err != nil {
return fmt.Errorf("failed to install extension '%s': %s", entry.Extension.Name, err)
}
}
}
} else {
return ErrPackageNotFound
}
if name == "all" {
con.Printf("\n")
con.PrintInfof("Operation complete\n")
}
return nil
}
func installAliasPackage(entry *pkgCacheEntry, promptToOverwrite bool, clientConfig ArmoryHTTPConfig, con *console.SliverClient) error {
if entry == nil {
return errors.New("package not found")
}
if !entry.Pkg.IsAlias {
return errors.New("package is not an alias")
}
repoURL, err := url.Parse(entry.RepoURL)
if err != nil {
return err
@@ -172,7 +496,7 @@ func installAliasPackageByName(name string, clientConfig ArmoryHTTPConfig, con *
con.Printf(console.Clearln + "\r") // Clear the line
installPath := alias.InstallFromFile(tmpFile.Name(), true, con)
installPath := alias.InstallFromFile(tmpFile.Name(), entry.Alias.CommandName, promptToOverwrite, con)
if installPath == nil {
return errors.New("failed to install alias")
}
@@ -186,72 +510,44 @@ func installAliasPackageByName(name string, clientConfig ArmoryHTTPConfig, con *
return nil
}
func installExtension(ext *extensions.ExtensionManifest, clientConfig ArmoryHTTPConfig, con *console.SliverConsoleClient) {
deps := make(map[string]struct{})
resolveExtensionPackageDependencies(ext.CommandName, deps, clientConfig, con)
sliverMenu := con.App.Menu(constants.ImplantMenu)
for dep := range deps {
if extensions.CmdExists(dep, sliverMenu.Command) {
continue // Dependency is already installed
}
err := installExtensionPackageByName(dep, clientConfig, con)
if err != nil {
con.PrintErrorf("Failed to install extension dependency '%s': %s", dep, err)
return
}
}
err := installExtensionPackageByName(ext.CommandName, clientConfig, con)
if err != nil {
con.PrintErrorf("Failed to install extension '%s': %s", ext.CommandName, err)
return
}
}
const maxDepDepth = 10 // Arbitrary recursive limit for dependencies
func resolveExtensionPackageDependencies(name string, deps map[string]struct{}, clientConfig ArmoryHTTPConfig, con *console.SliverConsoleClient) {
var entry *pkgCacheEntry
pkgCache.Range(func(key, value interface{}) bool {
cacheEntry := value.(pkgCacheEntry)
if cacheEntry.Pkg.CommandName == name {
entry = &cacheEntry
return false
func resolveExtensionPackageDependencies(pkg *pkgCacheEntry, deps map[string]*pkgCacheEntry, pendingPackages map[string]string) error {
for _, multiExt := range pkg.Extension.ExtCommand {
if multiExt.DependsOn == "" {
continue // Avoid adding empty dependency
}
return true
})
if entry == nil {
return
}
if entry.Extension.DependsOn == "" {
return // Avoid adding empty dependency
if multiExt.DependsOn == pkg.Extension.Name {
continue // Avoid infinite loop of something that depends on itself
}
// We also need to look out for circular dependencies, so if we've already
// seen this dependency, we stop resolving
if _, ok := deps[multiExt.DependsOn]; ok {
continue // Already resolved
}
// Check to make sure we are not already going to install a package with this name
if _, ok := pendingPackages[multiExt.DependsOn]; ok {
continue
}
if maxDepDepth < len(deps) {
continue
}
// Figure out what package we need for the dependency
dependencyEntry, err := getPackageForCommand(multiExt.DependsOn, "", "")
if err != nil {
return fmt.Errorf("could not resolve dependency %s for %s: %s", multiExt.DependsOn, pkg.Extension.Name, err)
}
deps[multiExt.DependsOn] = dependencyEntry
err = resolveExtensionPackageDependencies(dependencyEntry, deps, pendingPackages)
if err != nil {
return err
}
}
if entry.Extension.DependsOn == name {
return // Avoid infinite loop of something that depends on itself
}
// We also need to look out for circular dependencies, so if we've already
// seen this dependency, we stop resolving
if _, ok := deps[entry.Extension.DependsOn]; ok {
return // Already resolved
}
if maxDepDepth < len(deps) {
return
}
deps[entry.Extension.DependsOn] = struct{}{}
resolveExtensionPackageDependencies(entry.Extension.DependsOn, deps, clientConfig, con)
return nil
}
func installExtensionPackageByName(name string, clientConfig ArmoryHTTPConfig, con *console.SliverConsoleClient) error {
var entry *pkgCacheEntry
pkgCache.Range(func(key, value interface{}) bool {
cacheEntry := value.(pkgCacheEntry)
if cacheEntry.Pkg.CommandName == name {
entry = &cacheEntry
return false
}
return true
})
func installExtensionPackage(entry *pkgCacheEntry, promptToOverwrite bool, clientConfig ArmoryHTTPConfig, con *console.SliverClient) error {
if entry == nil {
return errors.New("package not found")
}
@@ -297,20 +593,7 @@ func installExtensionPackageByName(name string, clientConfig ArmoryHTTPConfig, c
con.Printf(console.Clearln + "\r") // Clear download message
installPath := extensions.InstallFromFilePath(tmpFile.Name(), true, con)
if installPath == nil {
return errors.New("failed to install extension")
}
extCmd, err := extensions.LoadExtensionManifest(filepath.Join(*installPath, extensions.ManifestFileName))
if err != nil {
return err
}
extensions.InstallFromDir(tmpFile.Name(), promptToOverwrite, con, true)
sliverMenu := con.App.Menu(constants.ImplantMenu)
//
// if extensions.CmdExists(extCmd.Name, sliverMenu.Command) {
// con.App.Commands().Remove(extCmd.Name)
// }
extensions.ExtensionRegisterCommand(extCmd, sliverMenu.Command, con)
return nil
}
+653
View File
@@ -0,0 +1,653 @@
package armory
import (
"fmt"
"os"
"path/filepath"
"slices"
"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/jedib0t/go-pretty/v6/table"
"github.com/spf13/cobra"
)
func printArmories(con *console.SliverClient) {
tw := table.NewWriter()
tw.SetStyle(settings.GetTableStyle(con))
tw.AppendHeader(table.Row{
"Armory Name",
"Authorization Required",
"Enabled",
"URL",
})
configuredArmories := getCurrentArmoryConfiguration()
for _, armory := range configuredArmories {
var authRequired string
var enabled string
if armory.Authorization != "" {
authRequired = "yes"
} else {
authRequired = "no"
}
if armory.Enabled {
enabled = "yes"
} else {
enabled = "no"
}
tw.AppendRow(table.Row{
armory.Name,
authRequired,
enabled,
armory.RepoURL,
})
}
con.Printf("%s\n", tw.Render())
}
func generateRowsForArmory(armoryInfo *assets.ArmoryConfig) []table.Row {
rows := make([]table.Row, 0)
rows = append(rows, table.Row{
"Name",
armoryInfo.Name,
})
rows = append(rows, table.Row{
"Public Key",
armoryInfo.PublicKey,
})
enabled := "yes"
if !armoryInfo.Enabled {
enabled = "no"
}
rows = append(rows, table.Row{
"Enabled",
enabled,
})
authorizationRequired := "no"
if armoryInfo.Authorization != "" {
authorizationRequired = fmt.Sprintf("yes; current authorization: %s", armoryInfo.Authorization)
}
rows = append(rows, table.Row{
"Authorization required?",
authorizationRequired,
})
if authorizationRequired != "no" {
authCmd := armoryInfo.AuthorizationCmd
if authCmd == "" {
authCmd = "not configured"
}
rows = append(rows, table.Row{
"Authorization Command",
authCmd,
})
}
rows = append(rows, table.Row{
"URL",
armoryInfo.RepoURL,
})
return rows
}
func generateRowsForPackage(packageInfo *pkgCacheEntry) []table.Row {
rows := make([]table.Row, 0)
rows = append(rows, table.Row{
"Name",
packageInfo.Pkg.Name,
})
rows = append(rows, table.Row{
"Command Name",
packageInfo.Pkg.CommandName,
})
rows = append(rows, table.Row{
"Armory Name",
packageInfo.Pkg.ArmoryName,
})
packageType := "alias"
if !packageInfo.Pkg.IsAlias {
packageType = "extension"
}
rows = append(rows, table.Row{
"Package Type",
packageType,
})
if packageType == "alias" {
rows = append(rows, table.Row{
"Version",
packageInfo.Alias.Version,
})
rows = append(rows, table.Row{
"Author",
packageInfo.Alias.OriginalAuthor,
})
rows = append(rows, table.Row{
"Repo URL",
packageInfo.Alias.RepoURL,
})
rows = append(rows, table.Row{
"Help",
packageInfo.Alias.Help,
})
} else {
rows = append(rows, table.Row{
"Version",
packageInfo.Extension.Version,
})
rows = append(rows, table.Row{
"Original Author",
packageInfo.Extension.OriginalAuthor,
})
rows = append(rows, table.Row{
"Extension Author",
packageInfo.Extension.ExtensionAuthor,
})
rows = append(rows, table.Row{
"URL",
packageInfo.Extension.RepoURL,
})
extCommands := []string{}
for _, cmd := range packageInfo.Extension.ExtCommand {
extCommands = append(extCommands, cmd.CommandName)
}
rows = append(rows, table.Row{
"Contains commands",
strings.Join(extCommands, ", "),
})
rows = append(rows, table.Row{"", ""})
rows = append(rows, table.Row{"Command Info", ""})
for _, extCmd := range packageInfo.Extension.ExtCommand {
rows = append(rows, table.Row{
"Command Name",
extCmd.CommandName,
})
rows = append(rows, table.Row{
"Dependencies",
extCmd.DependsOn,
})
rows = append(rows, table.Row{
"Help",
extCmd.Help,
})
rows = append(rows, table.Row{"", ""})
}
}
rows = append(rows, table.Row{"", ""})
return rows
}
func viewDetailedInformation(con *console.SliverClient, entity string) {
tw := table.NewWriter()
tw.SetStyle(settings.GetTableStyle(con))
tw.AppendHeader(table.Row{
"Property",
"Value",
})
// See where this name exists in the armory and package indexes
armoryResult := armoryLookupByName(entity)
if armoryResult != nil {
tw.AppendRows(generateRowsForArmory(armoryResult))
con.Printf("Armory information for %s\n\n", entity)
con.Printf("%s\n", tw.Render())
tw.ResetRows()
con.Printf("\n")
}
// Get packages with this name
packageResult := packageCacheLookupByName(entity)
if len(packageResult) > 0 {
con.Printf("Packages named %s\n\n", entity)
for _, pkg := range packageResult {
tw.AppendRows(generateRowsForPackage(pkg))
con.Printf("%s\n", tw.Render())
tw.ResetRows()
con.Printf("\n")
}
}
// Get extensions containing commands with this name
commandResult := packageCacheLookupByCmd(entity)
commandResultFiltered := make([]*pkgCacheEntry, 0)
for _, cmd := range commandResult {
if !cmd.Pkg.IsAlias {
commandResultFiltered = append(commandResultFiltered, cmd)
}
}
if len(commandResultFiltered) > 0 {
con.Printf("Packages containing commands named %s\n\n", entity)
for _, cmd := range commandResultFiltered {
tw.AppendRows(generateRowsForPackage(cmd))
con.Printf("%s\n", tw.Render())
tw.ResetRows()
}
}
}
func ArmoryInfoCommand(cmd *cobra.Command, con *console.SliverClient, args []string) {
if len(args) == 0 {
printArmories(con)
return
}
// If the user wants info on something specific, make sure the caches are up to date
refresh(parseArmoryHTTPConfig(cmd))
viewDetailedInformation(con, args[0])
}
func verifyArmory(armoryInfo *assets.ArmoryConfig, clientConfig ArmoryHTTPConfig) error {
wg := &sync.WaitGroup{}
// Only making one request, so we can limit ourselves to one concurrent request
requestChannel := make(chan struct{}, 1)
wg.Add(1)
requestChannel <- struct{}{}
go fetchIndex(armoryInfo, requestChannel, clientConfig, wg)
wg.Wait()
result, ok := indexCache.Load(armoryInfo.PublicKey)
if !ok {
return fmt.Errorf("failed to retrieve armory index")
}
cacheResult := result.(indexCacheEntry)
return cacheResult.LastErr
}
func getCurrentArmoryConfiguration() []*assets.ArmoryConfig {
configs := []*assets.ArmoryConfig{}
armoryNames := []string{}
// If the default armory is in the configuration, force it to be last
var defaultConfig *assets.ArmoryConfig
currentArmories.Range(func(key, value interface{}) bool {
armoryEntry := value.(assets.ArmoryConfig)
// Skip over the default armory for now
if armoryEntry.Name != assets.DefaultArmoryName {
configs = append(configs, &armoryEntry)
armoryNames = append(armoryNames, armoryEntry.Name)
} else {
defaultConfig = &armoryEntry
}
return true
})
if !armoriesInitialized {
/*
Armories are initialized on the first call to the armory command
If armories are added or removed before the first call, we want
to make sure we still load in the ones from the configuration
file.
*/
persistentConfigs := assets.GetArmoriesConfig()
for _, config := range persistentConfigs {
if !slices.Contains(armoryNames, config.Name) {
if config.Name == assets.DefaultArmoryName {
if defaultArmoryRemoved {
continue
} else if defaultConfig != nil {
// The user potentially changed something about the default config
configs = append(configs, defaultConfig)
currentArmories.Store(config.PublicKey, *defaultConfig)
continue
}
}
configs = append(configs, config)
currentArmories.Store(config.PublicKey, *config)
}
}
return configs
}
if !defaultArmoryRemoved {
if defaultConfig != nil {
configs = append(configs, defaultConfig)
} else {
configs = append(configs, assets.DefaultArmoryConfig)
}
}
assets.RefreshArmoryAuthorization(configs)
return configs
}
func armoryNameExists(name string) bool {
currentArmoriesConfigured := getCurrentArmoryConfiguration()
for _, armory := range currentArmoriesConfigured {
if armory.Name == name {
return true
}
}
return false
}
func armoryKeyExists(pubKey string) bool {
currentArmoriesConfigured := getCurrentArmoryConfiguration()
for _, armory := range currentArmoriesConfigured {
if armory.PublicKey == pubKey {
return true
}
}
return false
}
func AddArmoryCmd(cmd *cobra.Command, con *console.SliverClient, args []string) {
// Get necessary information
url, _ := cmd.Flags().GetString("url")
pubKey, _ := cmd.Flags().GetString("pubkey")
auth, _ := cmd.Flags().GetString("auth")
authCmd, _ := cmd.Flags().GetString("authcmd")
noSave, _ := cmd.Flags().GetBool("no-save")
name := args[0]
if name == "" {
con.PrintErrorf("an armory name is required\n")
return
}
// Make sure we do not already have an armory config with the supplied name
if armoryNameExists(name) {
con.PrintErrorf("armory %s already exists\n", name)
return
}
clientConfig := parseArmoryHTTPConfig(cmd)
armoryConfig := assets.ArmoryConfig{
PublicKey: pubKey,
RepoURL: url,
Authorization: auth,
AuthorizationCmd: authCmd,
Name: name,
Enabled: true,
}
// verifyArmory will add the armory index to the cache on success, so we do not have to force a refresh
err := verifyArmory(&armoryConfig, clientConfig)
if err != nil {
con.PrintErrorf("could not add armory: %s\n", err)
return
}
currentArmories.Store(armoryConfig.PublicKey, armoryConfig)
if !noSave {
configs := getCurrentArmoryConfiguration()
err = assets.SaveArmoriesConfig(configs)
if err != nil {
con.PrintErrorf("Could not save armory configuration: %s\n", err)
} else {
con.PrintSuccessf("Armory configuration saved\n")
}
}
con.PrintSuccessf("Added armory %s\n", name)
}
// Get a list of package IDs for an armory by its public key
func getPackageIDsForArmory(armoryPublicKey string) []string {
packageIDs := []string{}
pkgCache.Range(func(key, value interface{}) bool {
pkgEntry := value.(pkgCacheEntry)
if pkgEntry.ArmoryConfig.PublicKey == armoryPublicKey {
packageIDs = append(packageIDs, pkgEntry.ID)
}
return true
})
return packageIDs
}
func RemoveArmoryCmd(cmd *cobra.Command, con *console.SliverClient, args []string) {
name := args[0]
if name == "" {
con.PrintErrorf("an armory name is required\n")
return
}
armories := getCurrentArmoryConfiguration()
deleted := false
newConfiguration := []*assets.ArmoryConfig{}
for _, armory := range armories {
if armory.Name != name {
newConfiguration = append(newConfiguration, armory)
} else {
currentArmories.Delete(armory.PublicKey)
indexCache.Delete(armory.PublicKey)
/*
To delete from the package cache, we will have
to gather a list of package IDs for the
armory then delete them from the cache.
*/
armoryPackageIDs := getPackageIDsForArmory(armory.PublicKey)
for _, id := range armoryPackageIDs {
pkgCache.Delete(id)
}
deleted = true
}
}
if deleted {
con.PrintSuccessf("Armory %s successfully deleted, saving configuration...\n", name)
if name == assets.DefaultArmoryName {
defaultArmoryRemoved = true
}
} else {
con.PrintErrorf("Armory %s is not a configured armory\n", name)
return
}
err := assets.SaveArmoriesConfig(newConfiguration)
if err != nil {
con.PrintErrorf("Could not save new armory configuration: %s\n", err)
} else {
con.PrintSuccessf("Saved armory configuration\n")
}
}
func SaveArmories(con *console.SliverClient) {
configs := getCurrentArmoryConfiguration()
err := assets.SaveArmoriesConfig(configs)
if err != nil {
con.PrintErrorf("Could not save armory configuration: %s\n", err)
} else {
con.PrintSuccessf("Successfully saved armory configuration\n")
}
}
func getArmoryConfig(name string) (assets.ArmoryConfig, error) {
armories := getCurrentArmoryConfiguration()
var armoryPublicKey string
armoryConfig := assets.ArmoryConfig{}
for _, armory := range armories {
if armory.Name == name {
armoryPublicKey = armory.PublicKey
break
}
}
if armoryPublicKey == "" {
return armoryConfig, fmt.Errorf("could not retrieve armory configuration for armory %s. Try running the armory command to refresh indexes", name)
}
value, ok := currentArmories.Load(armoryPublicKey)
if !ok {
return armoryConfig, fmt.Errorf("could not retrieve armory configuration for armory %s. Try running the armory command to refresh indexes", name)
}
armoryConfig = value.(assets.ArmoryConfig)
return armoryConfig, nil
}
func ChangeArmoryEnabledState(cmd *cobra.Command, con *console.SliverClient, args []string, enabled bool) {
// Get the armory's public key, change its state, then update the cache to remove packages from the armory
var name string
if len(args) > 0 && args[0] != "" {
name = args[0]
} else {
con.PrintErrorf("an armory name is required")
return
}
armoryConfig, err := getArmoryConfig(name)
if err != nil {
con.PrintErrorf("%s\n", err)
return
}
armoryPublicKey := armoryConfig.PublicKey
armoryConfig.Enabled = enabled
currentArmories.Store(armoryPublicKey, armoryConfig)
if !enabled {
// Remove cached info for the armory if it is disabled
armoryPackageIDs := getPackageIDsForArmory(armoryPublicKey)
for _, id := range armoryPackageIDs {
pkgCache.Delete(id)
}
indexCache.Delete(armoryPublicKey)
}
// Force a refresh
clientConfig := parseArmoryHTTPConfig(cmd)
con.PrintInfof("Refreshing armory information...\n")
refresh(clientConfig)
SaveArmories(con)
con.PrintSuccessf("Done\n")
}
func ModifyArmoryCmd(cmd *cobra.Command, con *console.SliverClient, args []string) {
// Quick check to make sure we were provided with a name
var name string
if len(args) > 0 && args[0] != "" {
name = args[0]
}
if name == "" {
con.PrintErrorf("an armory name is required\n")
return
}
// Get the record for the armory
armoryConfig, err := getArmoryConfig(name)
if err != nil {
con.PrintErrorf("%s\n", err)
return
}
// Save the old config so we can delete the existing config
// and revert if needed
previousConfig := assets.ArmoryConfig{
PublicKey: armoryConfig.PublicKey,
RepoURL: armoryConfig.RepoURL,
Authorization: armoryConfig.Authorization,
AuthorizationCmd: armoryConfig.AuthorizationCmd,
Name: armoryConfig.Name,
Enabled: armoryConfig.Enabled,
}
if cmd.Flags().Changed("name") {
newName, _ := cmd.Flags().GetString("name")
// Make sure the name does not already exist
if armoryNameExists(newName) {
con.PrintErrorf("armory with name %s already exists\n", name)
return
}
armoryConfig.Name = newName
}
if cmd.Flags().Changed("pubkey") {
newPubKey, _ := cmd.Flags().GetString("pubkey")
/*
Since public keys are used as the key for the index cache,
make sure we have not been given a key that already exists
*/
if armoryKeyExists(newPubKey) {
con.PrintErrorf("armory provided public key already exists\n")
return
}
armoryConfig.PublicKey = newPubKey
}
if cmd.Flags().Changed("url") {
newUrl, _ := cmd.Flags().GetString("url")
armoryConfig.RepoURL = newUrl
}
if cmd.Flags().Changed("auth") {
newAuth, _ := cmd.Flags().GetString("auth")
armoryConfig.Authorization = newAuth
}
if cmd.Flags().Changed("authcmd") {
newAuthCmd, _ := cmd.Flags().GetString("authcmd")
armoryConfig.AuthorizationCmd = newAuthCmd
}
// We will remove the old armory and add a new one with the changed properties to force a refresh
currentArmories.Delete(previousConfig.PublicKey)
indexCache.Delete(previousConfig.PublicKey)
armoryPackageIDs := getPackageIDsForArmory(previousConfig.PublicKey)
for _, id := range armoryPackageIDs {
pkgCache.Delete(id)
}
clientConfig := parseArmoryHTTPConfig(cmd)
err = verifyArmory(&armoryConfig, clientConfig)
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)
if !confirm {
return
} else {
err = verifyArmory(&previousConfig, clientConfig)
if err != nil {
con.PrintErrorf("could not re-add armory %s: %s\n", name, err)
return
}
armoryConfig = previousConfig
con.PrintSuccessf("Re-added armory with previous values")
}
}
currentArmories.Store(armoryConfig.PublicKey, armoryConfig)
if !cmd.Flags().Changed("no-save") {
SaveArmories(con)
}
// Force a refresh
con.PrintInfof("Refreshing armory information...\n")
refresh(clientConfig)
con.PrintSuccessf("Done\n")
}
func RefreshArmories(cmd *cobra.Command, con *console.SliverClient) {
clientConfig := parseArmoryHTTPConfig(cmd)
// Since this being called from the refresh command, force the refresh
clientConfig.IgnoreCache = true
clearAllCaches()
armoriesInitialized = false
con.PrintInfof("Refreshing armory information...")
refresh(clientConfig)
con.PrintSuccessf("Refreshed armory information\n")
}
func ResetArmoryConfig(cmd *cobra.Command, con *console.SliverClient) {
armoryConfigPath := filepath.Join(assets.GetRootAppDir(), assets.ArmoryConfigFileName)
con.PrintInfof("Removing armory configuration file %s...", armoryConfigPath)
err := os.Remove(armoryConfigPath)
if err != nil {
con.PrintErrorf("Could not delete armory configuration file %s: %s", armoryConfigPath, err)
return
}
con.PrintSuccessf("Removed armory configuration file %s\n", armoryConfigPath)
// Force a refresh
RefreshArmories(cmd, con)
con.PrintSuccessf("Successfully reset armory configuration\n")
}
+82 -5
View File
@@ -19,6 +19,8 @@ package armory
*/
import (
"bytes"
"crypto/sha256"
"crypto/tls"
"encoding/base64"
"encoding/json"
@@ -67,6 +69,18 @@ type armoryPkgResponse struct {
TarGzURL string `json:"tar_gz_url"` // Raw tar.gz url
}
func calculatePackageHash(pkg *ArmoryPackage) string {
if pkg == nil {
return ""
}
hasher := sha256.New()
// Hash some of the things that make the package unique
packageIdentifier := []byte(pkg.RepoURL + pkg.PublicKey + pkg.ArmoryName + pkg.CommandName)
hasher.Write(packageIdentifier)
return fmt.Sprintf("%x", hasher.Sum(nil))
}
//
// Default Parsers for Self-Hosted Armories
//
@@ -79,7 +93,10 @@ func DefaultArmoryIndexParser(armoryConfig *assets.ArmoryConfig, clientConfig Ar
return nil, err
}
resp, body, _ := httpRequest(clientConfig, armoryConfig.RepoURL, armoryConfig, http.Header{})
resp, body, err := httpRequest(clientConfig, armoryConfig.RepoURL, armoryConfig, http.Header{})
if err != nil {
return nil, err
}
if resp.StatusCode != http.StatusOK {
return nil, errors.New("api returned non-200 status code")
}
@@ -111,9 +128,45 @@ func DefaultArmoryIndexParser(armoryConfig *assets.ArmoryConfig, clientConfig Ar
if err != nil {
return nil, err
}
// Populate armory name and ID information for assets
for _, bundle := range armoryIndex.Bundles {
bundle.ArmoryName = armoryIndex.ArmoryConfig.Name
}
for _, alias := range armoryIndex.Aliases {
alias.ArmoryName = armoryIndex.ArmoryConfig.Name
alias.ArmoryPK = armoryIndex.ArmoryConfig.PublicKey
if cached := packageCacheLookupByCmdAndArmory(alias.CommandName, armoryIndex.ArmoryConfig.PublicKey); cached != nil {
// A package with this name is in the cache, so we will remove it here so that the latest version is added
// when the index is parsed
pkgCache.Delete(cached.ID)
}
alias.ID = calculatePackageHash(alias)
}
for _, extension := range armoryIndex.Extensions {
extension.ArmoryName = armoryIndex.ArmoryConfig.Name
extension.ArmoryPK = armoryIndex.ArmoryConfig.PublicKey
if cached := packageCacheLookupByCmdAndArmory(extension.CommandName, armoryIndex.ArmoryConfig.PublicKey); cached != nil {
// A package with this name is in the cache, so we will remove it here so that the latest version is added
// when the index is parsed
pkgCache.Delete(cached.ID)
}
extension.ID = calculatePackageHash(extension)
}
return armoryIndex, nil
}
func decodePackageSignature(sigString string) ([]byte, error) {
// Base64 decode the signature
decodedData := make([]byte, base64.StdEncoding.DecodedLen(len(sigString)))
_, err := base64.StdEncoding.Decode(decodedData, []byte(sigString))
if err != nil {
return nil, err
}
// If decodedData does not end up being base64.StdEncoding.DecodedLen(len(data)) bytes long, trim the null bytes
decodedData = bytes.Trim(decodedData, "\x00")
return decodedData, nil
}
// DefaultArmoryPkgParser - Parse the armory package manifest directly from the url
func DefaultArmoryPkgParser(armoryConfig *assets.ArmoryConfig, armoryPkg *ArmoryPackage, sigOnly bool, clientConfig ArmoryHTTPConfig) (*minisign.Signature, []byte, error) {
var publicKey minisign.PublicKey
@@ -122,25 +175,29 @@ func DefaultArmoryPkgParser(armoryConfig *assets.ArmoryConfig, armoryPkg *Armory
return nil, nil, err
}
resp, body, err := httpRequest(clientConfig, armoryConfig.RepoURL, armoryConfig, http.Header{})
resp, body, err := httpRequest(clientConfig, armoryPkg.RepoURL, armoryConfig, http.Header{})
if err != nil {
return nil, nil, err
}
if resp.StatusCode != http.StatusOK {
return nil, nil, errors.New("api returned non-200 status code")
return nil, nil, fmt.Errorf("api returned non-200 status code (%d)", resp.StatusCode)
}
pkgResp := &armoryPkgResponse{}
err = json.Unmarshal(body, pkgResp)
if err != nil {
return nil, nil, err
}
sig, err := parsePkgMinsig([]byte(pkgResp.Minisig))
decodedSig, err := decodePackageSignature(pkgResp.Minisig)
if err != nil {
return nil, nil, err
}
sig, err := parsePkgMinsig(decodedSig)
if err != nil {
return nil, nil, err
}
var tarGz []byte
if !sigOnly {
tarGzURL, err := url.Parse(armoryPkg.RepoURL)
tarGzURL, err := url.Parse(pkgResp.TarGzURL)
if err != nil {
return nil, nil, err
}
@@ -242,6 +299,20 @@ func GithubAPIArmoryIndexParser(armoryConfig *assets.ArmoryConfig, clientConfig
if err != nil {
return nil, err
}
// Populate armory name and ID information for assets
for _, bundle := range armoryIndex.Bundles {
bundle.ArmoryName = armoryIndex.ArmoryConfig.Name
}
for _, alias := range armoryIndex.Aliases {
alias.ArmoryName = armoryIndex.ArmoryConfig.Name
alias.ArmoryPK = armoryIndex.ArmoryConfig.PublicKey
alias.ID = calculatePackageHash(alias)
}
for _, extension := range armoryIndex.Extensions {
extension.ArmoryName = armoryIndex.ArmoryConfig.Name
extension.ArmoryPK = armoryIndex.ArmoryConfig.PublicKey
extension.ID = calculatePackageHash(extension)
}
return armoryIndex, nil
}
@@ -436,6 +507,12 @@ func downloadRequest(clientConfig ArmoryHTTPConfig, reqURL string, armoryConfig
"Accept": {"application/octet-stream"},
}
resp, body, err := httpRequest(clientConfig, reqURL, armoryConfig, downloadHdr)
if err != nil {
return nil, err
}
if resp == nil {
return nil, fmt.Errorf("invalid response when downloading %s, try again later", reqURL)
}
if resp.StatusCode != http.StatusOK && resp.StatusCode != http.StatusFound {
return nil, fmt.Errorf("error downloading asset: http %d", resp.StatusCode)
}
+7 -5
View File
@@ -29,7 +29,7 @@ import (
)
// ArmorySearchCmd - Search for packages by name
func ArmorySearchCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []string) {
func ArmorySearchCmd(cmd *cobra.Command, con *console.SliverClient, args []string) {
con.PrintInfof("Refreshing package cache ... ")
clientConfig := parseArmoryHTTPConfig(cmd)
refresh(clientConfig)
@@ -47,7 +47,7 @@ func ArmorySearchCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args
return
}
aliases, exts := packagesInCache()
aliases, exts := packageManifestsInCache()
matchedAliases := []*alias.AliasManifest{}
for _, a := range aliases {
if nameExpr.MatchString(a.CommandName) {
@@ -55,9 +55,11 @@ func ArmorySearchCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args
}
}
matchedExts := []*extensions.ExtensionManifest{}
for _, ext := range exts {
if nameExpr.MatchString(ext.CommandName) {
matchedExts = append(matchedExts, ext)
for _, extm := range exts {
for _, ext := range extm.ExtCommand {
if nameExpr.MatchString(ext.CommandName) {
matchedExts = append(matchedExts, extm)
}
}
}
if len(matchedAliases) == 0 && len(matchedExts) == 0 {
+298 -37
View File
@@ -19,56 +19,127 @@ package armory
*/
import (
"fmt"
"os"
"sort"
"strconv"
"strings"
"github.com/AlecAivazis/survey/v2"
"github.com/jedib0t/go-pretty/v6/table"
"github.com/spf13/cobra"
"github.com/bishopfox/sliver/client/assets"
"github.com/bishopfox/sliver/client/command/alias"
"github.com/bishopfox/sliver/client/command/extensions"
"github.com/bishopfox/sliver/client/command/settings"
"github.com/bishopfox/sliver/client/console"
"github.com/bishopfox/sliver/util"
)
type VersionInformation struct {
OldVersion string
NewVersion string
ArmoryName string
}
type PackageType uint
const (
AliasPackage PackageType = iota
ExtensionPackage
)
type UpdateIdentifier struct {
Type PackageType
Name string
}
// ArmoryUpdateCmd - Update all installed extensions/aliases
func ArmoryUpdateCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []string) {
func ArmoryUpdateCmd(cmd *cobra.Command, con *console.SliverClient, args []string) {
var selectedUpdates []UpdateIdentifier
var err error
con.PrintInfof("Refreshing package cache ... ")
clientConfig := parseArmoryHTTPConfig(cmd)
refresh(clientConfig)
con.Printf(console.Clearln + "\r")
// Aliases
aliasUpdates := checkForAliasUpdates(clientConfig, con)
if 0 < len(aliasUpdates) {
con.PrintInfof("%d alias(es) out of date: %s\n", len(aliasUpdates), strings.Join(aliasUpdates, ", "))
for _, aliasName := range aliasUpdates {
err := installAliasPackageByName(aliasName, clientConfig, con)
if err != nil {
con.PrintErrorf("Failed to update %s: %s\n", aliasName, err)
}
}
} else {
con.PrintInfof("All aliases up to date!\n")
armoryName, err := cmd.Flags().GetString("armory")
if err != nil {
con.PrintErrorf("Could not parse %q flag: %s\n", "armory", err)
return
}
// Extensions
extUpdates := checkForExtensionUpdates(clientConfig, con)
if 0 < len(extUpdates) {
con.PrintInfof("%d extension(s) out of date: %s\n", len(extUpdates), strings.Join(extUpdates, ", "))
for _, extName := range extUpdates {
err := installExtensionPackageByName(extName, clientConfig, con)
if err != nil {
con.PrintErrorf("Failed to update %s: %s\n", extName, err)
}
// Find PK for the armory name
armoryPK := getArmoryPublicKey(armoryName)
// If the armory with the name is not found, print a warning
if cmd.Flags().Changed("armory") && armoryPK == "" {
con.PrintWarnf("Could not find a configured armory named %q - searching all configured armories\n\n", armoryName)
}
// Check packages for updates
aliasUpdates := checkForAliasUpdates(armoryPK)
extUpdates := checkForExtensionUpdates(armoryPK)
// Display a table of results
if len(aliasUpdates) > 0 || len(extUpdates) > 0 {
updateKeys := sortUpdateIdentifiers(aliasUpdates, extUpdates)
displayAvailableUpdates(con, updateKeys, aliasUpdates, extUpdates)
selectedUpdates, err = getUpdatesFromUser(con, updateKeys)
if err != nil {
con.PrintErrorf(err.Error() + "\n")
return
}
if len(selectedUpdates) == 0 {
return
}
} else {
con.PrintInfof("All extensions up to date!\n")
con.PrintSuccessf("All packages are up to date")
return
}
for _, update := range selectedUpdates {
switch update.Type {
case AliasPackage:
aliasVersionInfo, ok := aliasUpdates[update.Name]
if !ok {
continue
}
updatedPackage, err := getPackageForCommand(update.Name, armoryPK, aliasVersionInfo.NewVersion)
if err != nil {
con.PrintErrorf("Could not get update package for alias %s: %s\n", update.Name, err)
// Keep going because other packages might not encounter errors
continue
}
err = installAliasPackage(updatedPackage, false, clientConfig, con)
if err != nil {
con.PrintErrorf("Failed to update %s: %s\n", update.Name, err)
}
case ExtensionPackage:
extVersionInfo, ok := extUpdates[update.Name]
if !ok {
continue
}
updatedPackage, err := getPackageForCommand(update.Name, armoryPK, extVersionInfo.NewVersion)
if err != nil {
con.PrintErrorf("Could not get update package for extension %s: %s\n", update.Name, err)
continue
}
err = installExtensionPackage(updatedPackage, false, clientConfig, con)
if err != nil {
con.PrintErrorf("Failed to update %s: %s\n", update.Name, err)
}
default:
continue
}
}
}
func checkForAliasUpdates(clientConfig ArmoryHTTPConfig, con *console.SliverConsoleClient) []string {
cachedAliases, _ := packagesInCache()
results := []string{}
func checkForAliasUpdates(armoryPK string) map[string]VersionInformation {
cachedAliases, _ := packageManifestsInCache()
results := make(map[string]VersionInformation)
for _, aliasManifestPath := range assets.GetInstalledAliasManifests() {
data, err := os.ReadFile(aliasManifestPath)
if err != nil {
@@ -79,19 +150,31 @@ func checkForAliasUpdates(clientConfig ArmoryHTTPConfig, con *console.SliverCons
continue
}
for _, latestAlias := range cachedAliases {
// Right now we don't try to enforce any kind of versioning, it is assumed if the version from
// the armory differs at all from the local version, the extension is out of date.
if latestAlias.CommandName == localManifest.CommandName && latestAlias.Version != localManifest.Version {
results = append(results, localManifest.CommandName)
/*
We used to check if the version identifiers were different between the installed version and the
version in the armory. This worked when we had one armory, but with multiple potential armories,
we have to have some type of versioning. We do not have an official versioning scheme for packages,
so we will rely on the author of the package incrementing the version identifier somehow to determine
if a package is newer.
*/
if latestAlias.CommandName == localManifest.CommandName && latestAlias.Version > localManifest.Version {
if latestAlias.ArmoryPK == armoryPK || armoryPK == "" {
results[localManifest.CommandName] = VersionInformation{
OldVersion: localManifest.Version,
NewVersion: latestAlias.Version,
ArmoryName: latestAlias.ArmoryName,
}
}
}
}
}
return results
}
func checkForExtensionUpdates(clientConfig ArmoryHTTPConfig, con *console.SliverConsoleClient) []string {
_, cachedExtensions := packagesInCache()
results := []string{}
func checkForExtensionUpdates(armoryPK string) map[string]VersionInformation {
_, cachedExtensions := packageManifestsInCache()
// Return a map of extension name to minimum version to install
results := make(map[string]VersionInformation)
for _, extManifestPath := range assets.GetInstalledExtensionManifests() {
data, err := os.ReadFile(extManifestPath)
if err != nil {
@@ -102,12 +185,190 @@ func checkForExtensionUpdates(clientConfig ArmoryHTTPConfig, con *console.Sliver
continue
}
for _, latestExt := range cachedExtensions {
// Right now we don't try to enforce any kind of versioning, it is assumed if the version from
// the armory differs at all from the local version, the extension is out of date.
if latestExt.CommandName == localManifest.CommandName && latestExt.Version != localManifest.Version {
results = append(results, localManifest.CommandName)
/*
We used to check if the version identifiers were different between the installed version and the
version in the armory. This worked when we had one armory, but with multiple potential armories,
we have to have some type of versioning. We do not have an official versioning scheme for packages,
so we will rely on the author of the package incrementing the version identifier somehow to determine
if a package is newer.
*/
if latestExt.Name == localManifest.Name && latestExt.Version > localManifest.Version {
if latestExt.ArmoryPK == armoryPK || armoryPK == "" {
results[localManifest.Name] = VersionInformation{
OldVersion: localManifest.Version,
NewVersion: latestExt.Version,
ArmoryName: latestExt.ArmoryName,
}
}
}
}
}
return results
}
func sortUpdateIdentifiers(aliasUpdates, extensionUpdates map[string]VersionInformation) []UpdateIdentifier {
/*
This function helps us keep updates straight when the user chooses from them. Just in case
an alias and an extension exist with the same name, we cannot simply combine the two maps.
We will assume that no two aliases and no two extensions have the same name.
*/
result := []UpdateIdentifier{}
aliasNames := util.Keys(aliasUpdates)
extensionNames := util.Keys(extensionUpdates)
for _, name := range aliasNames {
result = append(result, UpdateIdentifier{
Type: AliasPackage,
Name: name,
})
}
for _, name := range extensionNames {
result = append(result, UpdateIdentifier{
Type: ExtensionPackage,
Name: name,
})
}
sort.Slice(result, func(i, j int) bool {
return result[i].Name < result[j].Name
})
return result
}
func displayAvailableUpdates(con *console.SliverClient, updateKeys []UpdateIdentifier, aliasUpdates, extensionUpdates map[string]VersionInformation) {
var (
aliasSuffix string
extensionSuffix string
title string = "Available Updates (%d alias%s, %d extension%s)"
)
tw := table.NewWriter()
tw.SetAutoIndex(true)
tw.SetStyle(settings.GetTableStyle(con))
if len(aliasUpdates) != 1 {
aliasSuffix = "es"
}
if len(extensionUpdates) != 1 {
extensionSuffix = "s"
}
tw.SetTitle(console.Bold + fmt.Sprintf(title, len(aliasUpdates), aliasSuffix, len(extensionUpdates), extensionSuffix) + console.Normal)
tw.AppendHeader(table.Row{
"Package Name",
"Package Type",
"Installed Version",
"Available Version",
})
for _, key := range updateKeys {
var (
packageName string
packageType string
packageVersion VersionInformation
ok bool
)
switch key.Type {
case AliasPackage:
packageVersion, ok = aliasUpdates[key.Name]
if !ok {
continue
}
packageName = key.Name
packageType = "Alias"
case ExtensionPackage:
packageVersion, ok = extensionUpdates[key.Name]
if !ok {
continue
}
packageName = key.Name
packageType = "Extension"
default:
continue
}
tw.AppendRow(table.Row{
packageName,
packageType,
packageVersion.OldVersion,
fmt.Sprintf("%s (Armory: %s)", packageVersion.NewVersion, packageVersion.ArmoryName),
})
}
con.Printf("%s\n\n", tw.Render())
}
func getUpdatesFromUser(con *console.SliverClient, updateKeys []UpdateIdentifier) (chosenUpdates []UpdateIdentifier, selectionError error) {
chosenUpdates = []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)
if err != nil {
// We do not need to set selectionError because an error here means the same thing as responding with "none"
return
}
updateResponse = strings.ToLower(updateResponse)
updateResponse = strings.Replace(updateResponse, " ", "", -1)
if updateResponse == "n" || updateResponse == "none" {
return
}
if updateResponse == "a" || updateResponse == "all" {
chosenUpdates = updateKeys
return
}
selections := strings.Split(updateResponse, ",")
for _, selection := range selections {
// Handle a range
if strings.Contains(selection, "-") {
rangeParts := strings.Split(selection, "-")
start, err := strconv.Atoi(rangeParts[0])
if err != nil {
selectionError = fmt.Errorf("%s is not a valid range", rangeParts[0])
return
}
end, err := strconv.Atoi(rangeParts[1])
if err != nil {
selectionError = fmt.Errorf("%s is not a valid range", rangeParts[1])
return
}
// Adjust for the 0 indexed slice we are working with
start -= 1
end -= 1
if start < 0 {
start = 0
}
if start > end {
selectionError = fmt.Errorf("%s is not a valid range", selection)
return
}
if end >= len(updateKeys) {
end = len(updateKeys) - 1
}
for i := start; i <= end; i++ {
chosenUpdates = append(chosenUpdates, updateKeys[i])
}
} else {
// Single entry
index, err := strconv.Atoi(selection)
if err != nil {
selectionError = fmt.Errorf("%s is not a valid range", selection)
return
}
index -= 1
if index >= 0 && index < len(updateKeys) {
chosenUpdates = append(chosenUpdates, updateKeys[index])
}
}
}
return
}
+3 -4
View File
@@ -21,14 +21,13 @@ package backdoor
import (
"fmt"
"github.com/spf13/cobra"
"github.com/bishopfox/sliver/client/console"
"github.com/bishopfox/sliver/protobuf/clientpb"
"github.com/spf13/cobra"
)
// BackdoorCmd - Command to inject implant code into an existing binary
func BackdoorCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []string) {
// BackdoorCmd - Command to inject implant code into an existing binary.
func BackdoorCmd(cmd *cobra.Command, con *console.SliverClient, args []string) {
session := con.ActiveTarget.GetSessionInteractive()
if session == nil {
return
+38
View File
@@ -0,0 +1,38 @@
package backdoor
import (
"github.com/rsteube/carapace"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
"github.com/bishopfox/sliver/client/command/flags"
"github.com/bishopfox/sliver/client/command/generate"
"github.com/bishopfox/sliver/client/command/help"
"github.com/bishopfox/sliver/client/console"
consts "github.com/bishopfox/sliver/client/constants"
)
// Commands returns the “ command and its subcommands.
func Commands(con *console.SliverClient) []*cobra.Command {
backdoorCmd := &cobra.Command{
Use: consts.BackdoorStr,
Short: "Infect a remote file with a sliver shellcode",
Long: help.GetHelpFor([]string{consts.BackdoorStr}),
Args: cobra.ExactArgs(1),
GroupID: consts.ExecutionHelpGroup,
Annotations: flags.RestrictTargets(consts.WindowsCmdsFilter),
Run: func(cmd *cobra.Command, args []string) {
BackdoorCmd(cmd, con, args)
},
}
flags.Bind("", false, backdoorCmd, func(f *pflag.FlagSet) {
f.StringP("profile", "p", "", "profile to use for service binary")
f.Int64P("timeout", "t", flags.DefaultTimeout, "grpc timeout in seconds")
})
flags.BindFlagCompletions(backdoorCmd, func(comp *carapace.ActionMap) {
(*comp)["profile"] = generate.ProfileNameCompleter(con)
})
carapace.Gen(backdoorCmd).PositionalCompletion(carapace.ActionValues().Usage("path to the remote file to backdoor"))
return []*cobra.Command{backdoorCmd}
}
+53 -17
View File
@@ -36,7 +36,7 @@ import (
)
// BeaconsCmd - Display/interact with beacons
func BeaconsCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []string) {
func BeaconsCmd(cmd *cobra.Command, con *console.SliverClient, args []string) {
killFlag, _ := cmd.Flags().GetString("kill")
killAll, _ := cmd.Flags().GetBool("kill-all")
@@ -94,7 +94,7 @@ func BeaconsCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []str
}
// PrintBeacons - Display a list of beacons
func PrintBeacons(beacons []*clientpb.Beacon, filter string, filterRegex *regexp.Regexp, con *console.SliverConsoleClient) {
func PrintBeacons(beacons []*clientpb.Beacon, filter string, filterRegex *regexp.Regexp, con *console.SliverClient) {
if len(beacons) == 0 {
con.PrintInfof("No beacons 🙁\n")
return
@@ -103,7 +103,7 @@ func PrintBeacons(beacons []*clientpb.Beacon, filter string, filterRegex *regexp
con.Printf("%s\n", tw.Render())
}
func renderBeacons(beacons []*clientpb.Beacon, filter string, filterRegex *regexp.Regexp, con *console.SliverConsoleClient) table.Writer {
func renderBeacons(beacons []*clientpb.Beacon, filter string, filterRegex *regexp.Regexp, con *console.SliverClient) table.Writer {
width, _, err := term.GetSize(0)
if err != nil {
width = 999
@@ -112,20 +112,45 @@ func renderBeacons(beacons []*clientpb.Beacon, filter string, filterRegex *regex
tw := table.NewWriter()
tw.SetStyle(settings.GetTableStyle(con))
wideTermWidth := con.Settings.SmallTermWidth < width
windowsBeaconInList := false
for _, beacon := range beacons {
if beacon.OS == "windows" {
windowsBeaconInList = true
}
}
if wideTermWidth {
tw.AppendHeader(table.Row{
"ID",
"Name",
"Tasks",
"Transport",
"Remote Address",
"Hostname",
"Username",
"Operating System",
"Locale",
"Last Check-in",
"Next Check-in",
})
if windowsBeaconInList {
tw.AppendHeader(table.Row{
"ID",
"Name",
"Tasks",
"Transport",
"Remote Address",
"Hostname",
"Username",
"Process (PID)",
"Integrity",
"Operating System",
"Locale",
"Last Check-in",
"Next Check-in",
})
} else {
tw.AppendHeader(table.Row{
"ID",
"Name",
"Tasks",
"Transport",
"Remote Address",
"Hostname",
"Username",
"Process (PID)",
"Operating System",
"Locale",
"Last Check-in",
"Next Check-in",
})
}
} else {
tw.AppendHeader(table.Row{
"ID",
@@ -145,6 +170,9 @@ func renderBeacons(beacons []*clientpb.Beacon, filter string, filterRegex *regex
if activeBeacon != nil && activeBeacon.ID == beacon.ID {
color = console.Green
}
if beacon.Integrity == "" {
beacon.Integrity = "-"
}
// We need a slice of strings so we can apply filters
var rowEntries []string
@@ -158,11 +186,19 @@ func renderBeacons(beacons []*clientpb.Beacon, filter string, filterRegex *regex
fmt.Sprintf(color+"%s"+console.Normal, beacon.RemoteAddress),
fmt.Sprintf(color+"%s"+console.Normal, beacon.Hostname),
fmt.Sprintf(color+"%s"+console.Normal, strings.TrimPrefix(beacon.Username, beacon.Hostname+"\\")),
fmt.Sprintf(color+"%s (%d)"+console.Normal, beacon.Filename, beacon.PID),
}
if windowsBeaconInList {
rowEntries = append(rowEntries, fmt.Sprintf(color+"%s"+console.Normal, beacon.Integrity))
}
rowEntries = append(rowEntries, []string{
fmt.Sprintf(color+"%s/%s"+console.Normal, beacon.OS, beacon.Arch),
fmt.Sprintf(color+"%s"+console.Normal, beacon.Locale),
con.FormatDateDelta(time.Unix(beacon.LastCheckin, 0), wideTermWidth, false),
con.FormatDateDelta(time.Unix(beacon.NextCheckin, 0), wideTermWidth, true),
}
}...)
} else {
rowEntries = []string{
fmt.Sprintf(color+"%s"+console.Normal, strings.Split(beacon.ID, "-")[0]),
+102
View File
@@ -0,0 +1,102 @@
package beacons
import (
"context"
"fmt"
"strings"
"github.com/rsteube/carapace"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
"github.com/bishopfox/sliver/client/command/flags"
"github.com/bishopfox/sliver/client/command/help"
"github.com/bishopfox/sliver/client/console"
consts "github.com/bishopfox/sliver/client/constants"
"github.com/bishopfox/sliver/protobuf/commonpb"
)
// Commands returns the “ command and its subcommands.
func Commands(con *console.SliverClient) []*cobra.Command {
beaconsCmd := &cobra.Command{
Use: consts.BeaconsStr,
Short: "Manage beacons",
Long: help.GetHelpFor([]string{consts.BeaconsStr}),
GroupID: consts.SliverHelpGroup,
Run: func(cmd *cobra.Command, args []string) {
BeaconsCmd(cmd, con, args)
},
}
flags.Bind("beacons", true, beaconsCmd, func(f *pflag.FlagSet) {
f.IntP("timeout", "t", flags.DefaultTimeout, "grpc timeout in seconds")
})
flags.Bind("beacons", false, beaconsCmd, func(f *pflag.FlagSet) {
f.StringP("kill", "k", "", "kill the designated beacon")
f.BoolP("kill-all", "K", false, "kill all beacons")
f.BoolP("force", "F", false, "force killing the beacon")
f.StringP("filter", "f", "", "filter beacons by substring")
f.StringP("filter-re", "e", "", "filter beacons by regular expression")
})
flags.BindFlagCompletions(beaconsCmd, func(comp *carapace.ActionMap) {
(*comp)["kill"] = BeaconIDCompleter(con)
})
beaconsRmCmd := &cobra.Command{
Use: consts.RmStr,
Short: "Remove a beacon",
Long: help.GetHelpFor([]string{consts.BeaconsStr, consts.RmStr}),
Run: func(cmd *cobra.Command, args []string) {
BeaconsRmCmd(cmd, con, args)
},
}
carapace.Gen(beaconsRmCmd).PositionalCompletion(BeaconIDCompleter(con))
beaconsCmd.AddCommand(beaconsRmCmd)
beaconsWatchCmd := &cobra.Command{
Use: consts.WatchStr,
Short: "Watch your beacons",
Long: help.GetHelpFor([]string{consts.BeaconsStr, consts.WatchStr}),
Run: func(cmd *cobra.Command, args []string) {
BeaconsWatchCmd(cmd, con, args)
},
}
beaconsCmd.AddCommand(beaconsWatchCmd)
beaconsPruneCmd := &cobra.Command{
Use: consts.PruneStr,
Short: "Prune stale beacons automatically",
Long: help.GetHelpFor([]string{consts.BeaconsStr, consts.PruneStr}),
Run: func(cmd *cobra.Command, args []string) {
BeaconsPruneCmd(cmd, con, args)
},
}
flags.Bind("beacons", false, beaconsPruneCmd, func(f *pflag.FlagSet) {
f.StringP("duration", "d", "1h", "duration to prune beacons that have missed their last checkin")
})
beaconsCmd.AddCommand(beaconsPruneCmd)
return []*cobra.Command{beaconsCmd}
}
// BeaconIDCompleter completes beacon IDs
func BeaconIDCompleter(con *console.SliverClient) carapace.Action {
callback := func(_ carapace.Context) carapace.Action {
results := make([]string, 0)
beacons, err := con.Rpc.GetBeacons(context.Background(), &commonpb.Empty{})
if err == nil {
for _, b := range beacons.Beacons {
link := fmt.Sprintf("[%s <- %s]", b.ActiveC2, b.RemoteAddress)
id := fmt.Sprintf("%s (%d)", b.Name, b.PID)
userHost := fmt.Sprintf("%s@%s", b.Username, b.Hostname)
desc := strings.Join([]string{id, userHost, link}, " ")
results = append(results, b.ID[:8])
results = append(results, desc)
}
}
return carapace.ActionValuesDescribed(results...).Tag("beacons")
}
return carapace.ActionCallback(callback)
}
+3 -3
View File
@@ -43,7 +43,7 @@ var (
)
// SelectBeacon - Interactive menu for the user to select an session, optionally only display live sessions
func SelectBeacon(con *console.SliverConsoleClient) (*clientpb.Beacon, error) {
func SelectBeacon(con *console.SliverClient) (*clientpb.Beacon, error) {
grpcCtx, cancel := con.GrpcContext(nil)
defer cancel()
beacons, err := con.Rpc.GetBeacons(grpcCtx, &commonpb.Empty{})
@@ -102,7 +102,7 @@ func SelectBeacon(con *console.SliverConsoleClient) (*clientpb.Beacon, error) {
return nil, ErrNoSelection
}
func GetBeacon(con *console.SliverConsoleClient, beaconID string) (*clientpb.Beacon, error) {
func GetBeacon(con *console.SliverClient, beaconID string) (*clientpb.Beacon, error) {
grpcCtx, cancel := con.GrpcContext(nil)
defer cancel()
beacons, err := con.Rpc.GetBeacons(grpcCtx, &commonpb.Empty{})
@@ -120,7 +120,7 @@ func GetBeacon(con *console.SliverConsoleClient, beaconID string) (*clientpb.Bea
return nil, ErrBeaconNotFound
}
func GetBeacons(con *console.SliverConsoleClient) (*clientpb.Beacons, error) {
func GetBeacons(con *console.SliverClient) (*clientpb.Beacons, error) {
grpcCtx, cancel := con.GrpcContext(nil)
defer cancel()
beacons, err := con.Rpc.GetBeacons(grpcCtx, &commonpb.Empty{})
+1 -1
View File
@@ -30,7 +30,7 @@ import (
)
// BeaconsPruneCmd - Prune stale beacons automatically
func BeaconsPruneCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []string) {
func BeaconsPruneCmd(cmd *cobra.Command, con *console.SliverClient, args []string) {
duration, _ := cmd.Flags().GetString("duration")
pruneDuration, err := time.ParseDuration(duration)
if err != nil {
+1 -1
View File
@@ -25,7 +25,7 @@ import (
)
// BeaconsRmCmd - Display/interact with beacons
func BeaconsRmCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []string) {
func BeaconsRmCmd(cmd *cobra.Command, con *console.SliverClient, args []string) {
beacon, err := SelectBeacon(con)
if err != nil {
con.PrintErrorf("%s\n", err)
+1 -1
View File
@@ -31,7 +31,7 @@ import (
)
// BeaconsWatchCmd - Watch your beacons in real-ish time
func BeaconsWatchCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []string) {
func BeaconsWatchCmd(cmd *cobra.Command, con *console.SliverClient, args []string) {
done := waitForInput()
defer func() {
con.Printf(console.UpN+console.Clearln+"\r", 1)
+5 -6
View File
@@ -23,17 +23,16 @@ import (
"fmt"
"strings"
"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/protobuf/clientpb"
"github.com/bishopfox/sliver/protobuf/commonpb"
"github.com/jedib0t/go-pretty/v6/table"
"github.com/spf13/cobra"
)
// BuildersCmd - List external builders
func BuildersCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []string) {
// BuildersCmd - List external builders.
func BuildersCmd(cmd *cobra.Command, con *console.SliverClient, args []string) {
builders, err := con.Rpc.Builders(context.Background(), &commonpb.Empty{})
if err != nil {
con.PrintErrorf("%s", err)
@@ -46,7 +45,7 @@ func BuildersCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []st
}
}
func PrintBuilders(externalBuilders []*clientpb.Builder, con *console.SliverConsoleClient) {
func PrintBuilders(externalBuilders []*clientpb.Builder, con *console.SliverClient) {
tw := table.NewWriter()
tw.SetStyle(settings.GetTableStyle(con))
tw.AppendHeader(table.Row{
+28
View File
@@ -0,0 +1,28 @@
package builders
import (
"github.com/bishopfox/sliver/client/command/flags"
"github.com/bishopfox/sliver/client/command/help"
"github.com/bishopfox/sliver/client/console"
consts "github.com/bishopfox/sliver/client/constants"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
)
// Commands returns the “ command and its subcommands.
func Commands(con *console.SliverClient) []*cobra.Command {
buildersCmd := &cobra.Command{
Use: consts.BuildersStr,
Short: "List external builders",
Long: help.GetHelpFor([]string{consts.BuildersStr}),
Run: func(cmd *cobra.Command, args []string) {
BuildersCmd(cmd, con, args)
},
GroupID: consts.PayloadsHelpGroup,
}
flags.Bind("builders", false, buildersCmd, func(f *pflag.FlagSet) {
f.Int64P("timeout", "t", flags.DefaultTimeout, "grpc timeout in seconds")
})
return []*cobra.Command{buildersCmd}
}
+335 -159
View File
@@ -21,8 +21,12 @@ package c2profiles
import (
"context"
"encoding/json"
"fmt"
"io"
"net/url"
"os"
"path"
"path/filepath"
"strings"
"github.com/AlecAivazis/survey/v2"
@@ -39,7 +43,7 @@ import (
)
// C2ProfileCmd list available http profiles
func C2ProfileCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []string) {
func C2ProfileCmd(cmd *cobra.Command, con *console.SliverClient, args []string) {
profileName, _ := cmd.Flags().GetString("name")
if profileName == constants.DefaultC2Profile {
@@ -61,8 +65,7 @@ func C2ProfileCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []s
PrintC2Profiles(profile, con)
}
func ImportC2ProfileCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []string) {
protocols := []string{constants.HttpStr, constants.HttpsStr}
func ImportC2ProfileCmd(cmd *cobra.Command, con *console.SliverClient, args []string) {
profileName, _ := cmd.Flags().GetString("name")
if profileName == "" {
con.PrintErrorf("Invalid c2 profile name\n")
@@ -98,29 +101,212 @@ func ImportC2ProfileCmd(cmd *cobra.Command, con *console.SliverConsoleClient, ar
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)
func ExportC2ProfileCmd(cmd *cobra.Command, con *console.SliverClient, args []string) {
filepath, _ := cmd.Flags().GetString("file")
if filepath == "" {
con.PrintErrorf("Missing file path\n")
return
}
profileName, _ := cmd.Flags().GetString("name")
if profileName == "" {
con.PrintErrorf("Invalid c2 profile name\n")
return
}
if profileName == constants.DefaultC2Profile {
httpC2Profiles, err := con.Rpc.GetHTTPC2Profiles(context.Background(), &commonpb.Empty{})
if err != nil {
con.PrintErrorf("%s\n", err)
con.PrintErrorf("failed to fetch HTTP C2 profiles: %s", err.Error())
return
}
if len(httpC2Profiles.Configs) != 1 {
profileName = selectC2Profile(httpC2Profiles.Configs)
}
}
profile, err := con.Rpc.GetHTTPC2ProfileByName(context.Background(), &clientpb.C2ProfileReq{Name: profileName})
if err != nil {
con.PrintErrorf("%s\n", err)
return
}
config, err := C2ConfigToJSON(profileName, profile)
if err != nil {
con.PrintErrorf("%s\n", err)
return
}
jsonProfile, err := json.Marshal(config)
if err != nil {
con.PrintErrorf("%s\n", err)
return
}
err = os.WriteFile(filepath, jsonProfile, 0644)
if err != nil {
con.PrintErrorf("%s\n", err)
return
}
con.Println(profileName, "C2 profile exported to ", filepath)
}
func GenerateC2ProfileCmd(cmd *cobra.Command, con *console.SliverClient, args []string) {
// load template to use as starting point
template, err := cmd.Flags().GetString("template")
if err != nil {
con.PrintErrorf("%s\n", err)
return
}
profileName, _ := cmd.Flags().GetString("name")
if profileName == "" {
con.PrintErrorf("Invalid c2 profile name\n")
return
}
profile, err := con.Rpc.GetHTTPC2ProfileByName(context.Background(), &clientpb.C2ProfileReq{Name: template})
if err != nil {
con.PrintErrorf("%s\n", err)
return
}
config, err := C2ConfigToJSON(profileName, profile)
if err != nil {
con.PrintErrorf("%s\n", err)
return
}
// read urls files and replace segments
filepath, err := cmd.Flags().GetString("file")
if err != nil {
con.PrintErrorf("%s\n", err)
return
}
urlsFile, err := os.Open(filepath)
if err != nil {
con.PrintErrorf("%s\n", err)
return
}
fileContent, err := io.ReadAll(urlsFile)
if err != nil {
con.PrintErrorf("%s\n", err)
return
}
urls := strings.Split(string(fileContent), "\n")
jsonProfile, err := updateC2Profile(config, urls)
if err != nil {
con.PrintErrorf("%s\n", err)
return
}
// save or display config
importC2Profile, err := cmd.Flags().GetBool("import")
if err != nil {
con.PrintErrorf("%s\n", err)
return
}
if importC2Profile {
httpC2ConfigReq := clientpb.HTTPC2ConfigReq{C2Config: C2ConfigToProtobuf(profileName, jsonProfile)}
_, err = con.Rpc.SaveHTTPC2Profile(context.Background(), &httpC2ConfigReq)
if err != nil {
con.PrintErrorf("%s\n", err)
return
}
con.Println("C2 profile generated and saved as ", profileName)
} else {
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,
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
for _, header := range profile.ImplantConfig.Headers {
headers = append(headers, assets.NameValueProbability{
Name: header.Name,
Value: header.Value,
Probability: int(header.Probability),
Method: header.Method,
})
}
implantConfig.Headers = headers
var urlParameters []assets.NameValueProbability
for _, urlParameter := range profile.ImplantConfig.ExtraURLParameters {
urlParameters = append(urlParameters, assets.NameValueProbability{
Name: urlParameter.Name,
Value: urlParameter.Value,
Probability: int(urlParameter.Probability),
})
}
implantConfig.URLParameters = urlParameters
var (
files []string
paths []string
)
for _, pathSegment := range profile.ImplantConfig.PathSegments {
if pathSegment.IsFile {
files = append(files, pathSegment.Value)
} else {
paths = append(paths, pathSegment.Value)
}
}
implantConfig.Files = files
implantConfig.Paths = paths
var serverHeaders []assets.NameValueProbability
for _, header := range profile.ServerConfig.Headers {
serverHeaders = append(serverHeaders, assets.NameValueProbability{
Name: header.Name,
Value: header.Value,
Probability: int(header.Probability),
Method: header.Method,
})
}
var serverCookies []string
for _, cookie := range profile.ServerConfig.Cookies {
serverCookies = append(serverCookies, cookie.Name)
}
serverConfig := assets.HTTPC2ServerConfig{
RandomVersionHeaders: profile.ServerConfig.RandomVersionHeaders,
Headers: serverHeaders,
Cookies: serverCookies,
}
config := assets.HTTPC2Config{
ImplantConfig: implantConfig,
ServerConfig: serverConfig,
}
return &config, nil
}
// convert json to protobuf
@@ -131,101 +317,66 @@ 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,
IsFile: false,
Value: path,
})
}
for _, close := range config.ImplantConfig.CloseFiles {
pathSegments = append(pathSegments, &clientpb.HTTPC2PathSegment{
IsFile: true,
SegmentType: 2,
Value: close,
for _, clientHeader := range config.ImplantConfig.Headers {
httpC2Headers = append(httpC2Headers, &clientpb.HTTPC2Header{
Method: clientHeader.Method,
Name: clientHeader.Name,
Value: clientHeader.Value,
Probability: int32(clientHeader.Probability),
})
}
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,
for _, urlParameter := range config.ImplantConfig.URLParameters {
httpC2UrlParameters = append(httpC2UrlParameters, &clientpb.HTTPC2URLParameter{
Method: urlParameter.Method,
Name: urlParameter.Name,
Value: urlParameter.Value,
Probability: int32(urlParameter.Probability),
})
}
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
serverHeaders := []*clientpb.HTTPC2Header{}
for _, serverHeader := range config.ServerConfig.Headers {
for _, method := range serverHeader.Methods {
serverHeaders = append(serverHeaders, &clientpb.HTTPC2Header{
Method: method,
Name: serverHeader.Name,
Value: serverHeader.Value,
Probability: int32(serverHeader.Probability),
})
}
serverHeaders = append(serverHeaders, &clientpb.HTTPC2Header{
Method: serverHeader.Method,
Name: serverHeader.Name,
Value: serverHeader.Value,
Probability: int32(serverHeader.Probability),
})
}
serverCookies := []*clientpb.HTTPC2Cookie{}
@@ -248,7 +399,7 @@ func C2ConfigToProtobuf(profileName string, config *assets.HTTPC2Config) *client
}
// PrintImplantBuilds - Print the implant builds on the server
func PrintC2Profiles(profile *clientpb.HTTPC2Config, con *console.SliverConsoleClient) {
func PrintC2Profiles(profile *clientpb.HTTPC2Config, con *console.SliverClient) {
tw := table.NewWriter()
tw.SetStyle(settings.GetTableStyle(con))
@@ -268,7 +419,7 @@ func PrintC2Profiles(profile *clientpb.HTTPC2Config, con *console.SliverConsoleC
var serverHeaders []string
for _, header := range profile.ServerConfig.Headers {
serverHeaders = append(serverHeaders, header.Value)
serverHeaders = append(serverHeaders, header.Name)
}
tw.AppendRow(table.Row{
"Server Headers",
@@ -293,7 +444,7 @@ func PrintC2Profiles(profile *clientpb.HTTPC2Config, con *console.SliverConsoleC
var clientHeaders []string
for _, header := range profile.ImplantConfig.Headers {
clientHeaders = append(clientHeaders, header.Value)
clientHeaders = append(clientHeaders, header.Name)
}
tw.AppendRow(table.Row{
"Client Headers",
@@ -324,96 +475,65 @@ func PrintC2Profiles(profile *clientpb.HTTPC2Config, con *console.SliverConsoleC
"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())
@@ -435,3 +555,59 @@ func selectC2Profile(c2profiles []*clientpb.HTTPC2Config) string {
return c2profile
}
func updateC2Profile(template *assets.HTTPC2Config, urls []string) (*assets.HTTPC2Config, error) {
// update the template with the urls
var (
paths []string
filenames []string
extensions []string
)
for _, urlPath := range urls {
parsedURL, err := url.Parse(urlPath)
if err != nil {
fmt.Println("Error parsing URL:", err)
continue
}
dir, file := path.Split(parsedURL.Path)
dir = strings.Trim(dir, "/")
if dir != "" {
paths = append(paths, strings.Split(dir, "/")...)
}
if file != "" {
fileName := strings.TrimSuffix(file, filepath.Ext(file))
filenames = append(filenames, fileName)
ext := strings.TrimPrefix(filepath.Ext(file), ".")
if ext != "" {
extensions = append(extensions, ext)
}
}
}
slices.Sort(extensions)
extensions = slices.Compact(extensions)
slices.Sort(paths)
paths = slices.Compact(paths)
slices.Sort(filenames)
filenames = slices.Compact(filenames)
// 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))
}
if len(filenames) < 5 {
return nil, fmt.Errorf("got %d paths need at least 5", len(filenames))
}
template.ImplantConfig.Extensions = extensions
template.ImplantConfig.Paths = paths
template.ImplantConfig.Files = filenames
return template, nil
}
+91
View File
@@ -0,0 +1,91 @@
package c2profiles
import (
"github.com/bishopfox/sliver/client/command/flags"
"github.com/bishopfox/sliver/client/command/generate"
"github.com/bishopfox/sliver/client/command/help"
"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.
func Commands(con *console.SliverClient) []*cobra.Command {
importC2ProfileCmd := &cobra.Command{
Use: consts.ImportC2ProfileStr,
Short: "Import HTTP C2 profile",
Long: help.GetHelpFor([]string{consts.ImportC2ProfileStr}),
Run: func(cmd *cobra.Command, args []string) {
ImportC2ProfileCmd(cmd, con, args)
},
}
flags.Bind(consts.ImportC2ProfileStr, false, importC2ProfileCmd, func(f *pflag.FlagSet) {
f.StringP("name", "n", consts.DefaultC2Profile, "HTTP C2 Profile name")
f.StringP("file", "f", "", "Path to C2 configuration file to import")
f.BoolP("overwrite", "o", false, "Overwrite profile if it exists")
})
exportC2ProfileCmd := &cobra.Command{
Use: consts.ExportC2ProfileStr,
Short: "Export HTTP C2 profile",
Long: help.GetHelpFor([]string{consts.ExportC2ProfileStr}),
Run: func(cmd *cobra.Command, args []string) {
ExportC2ProfileCmd(cmd, con, args)
},
}
flags.Bind(consts.ExportC2ProfileStr, false, exportC2ProfileCmd, func(f *pflag.FlagSet) {
f.StringP("file", "f", "", "Path to file to export C2 configuration to")
f.StringP("name", "n", consts.DefaultC2Profile, "HTTP C2 Profile name")
})
flags.BindFlagCompletions(exportC2ProfileCmd, func(comp *carapace.ActionMap) {
(*comp)["name"] = generate.HTTPC2Completer(con)
})
C2ProfileCmd := &cobra.Command{
Use: consts.C2ProfileStr,
Short: "Display C2 profile details",
Long: help.GetHelpFor([]string{consts.C2ProfileStr}),
Run: func(cmd *cobra.Command, args []string) {
C2ProfileCmd(cmd, con, args)
},
GroupID: consts.NetworkHelpGroup,
}
flags.Bind(consts.C2ProfileStr, true, C2ProfileCmd, func(f *pflag.FlagSet) {
f.StringP("name", "n", consts.DefaultC2Profile, "HTTP C2 Profile to display")
})
flags.BindFlagCompletions(C2ProfileCmd, func(comp *carapace.ActionMap) {
(*comp)["name"] = generate.HTTPC2Completer(con)
})
generateC2ProfileCmd := &cobra.Command{
Use: consts.C2GenerateStr,
Short: "Generate a C2 Profile from a list of urls",
Long: help.GetHelpFor([]string{consts.C2ProfileStr + "." + consts.C2GenerateStr}),
Run: func(cmd *cobra.Command, args []string) {
GenerateC2ProfileCmd(cmd, con, args)
},
}
flags.Bind(consts.GenerateStr, false, generateC2ProfileCmd, func(f *pflag.FlagSet) {
f.StringP("file", "f", "", "Path to file containing URL list, /hello/there.txt one per line")
f.BoolP("import", "i", false, "Import the generated profile after creation")
f.StringP("name", "n", "", "HTTP C2 Profile name to save C2Profile as")
f.StringP("template", "t", consts.DefaultC2Profile, "HTTP C2 Profile to use as a template for the new profile")
})
flags.BindFlagCompletions(generateC2ProfileCmd, func(comp *carapace.ActionMap) {
(*comp)["template"] = generate.HTTPC2Completer(con)
})
C2ProfileCmd.AddCommand(generateC2ProfileCmd)
C2ProfileCmd.AddCommand(importC2ProfileCmd)
C2ProfileCmd.AddCommand(exportC2ProfileCmd)
return []*cobra.Command{
C2ProfileCmd,
}
}
+181
View File
@@ -0,0 +1,181 @@
package certificates
import (
"context"
"fmt"
"time"
"github.com/bishopfox/sliver/client/command/settings"
"github.com/bishopfox/sliver/client/console"
"github.com/bishopfox/sliver/protobuf/clientpb"
"github.com/jedib0t/go-pretty/v6/table"
"github.com/spf13/cobra"
"golang.org/x/term"
)
/*
Sliver Implant Framework
Copyright (C) 2024 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/>.
*/
const (
timeFormat = "2006-01-02 15:04:05 UTC-0700"
)
// Defining the transport filters
const (
MTLSTransport uint32 = 1 << iota
HTTPSTransport
AllTransports
)
// Defining the role filters
const (
// Provide some separation between the options so that we do not have duplicate combinations
ServerRole uint32 = 8 << iota
ImplantRole
AllRoles
)
func CertificateInfoCmd(cmd *cobra.Command, con *console.SliverClient, args []string) {
// Since we are sending this value in a protobuf, we will give it a fixed bit size
// 32 is the smallest we can go
var chosenOptions uint32
if cmd.Flags().Changed("mtls") {
if cmd.Flags().Changed("https") {
chosenOptions = AllTransports
} else {
chosenOptions = MTLSTransport
}
} else if cmd.Flags().Changed("https") {
chosenOptions = HTTPSTransport
} else {
chosenOptions = AllTransports
}
if cmd.Flags().Changed("server") {
if cmd.Flags().Changed("implant") {
chosenOptions |= AllRoles
} else {
chosenOptions |= ServerRole
}
} else if cmd.Flags().Changed("implant") {
chosenOptions |= ImplantRole
} else {
chosenOptions |= AllRoles
}
request := &clientpb.CertificatesReq{
CategoryFilters: chosenOptions,
}
request.CN, _ = cmd.Flags().GetString("cn")
// Ask the server for information about certificates
certificateInfo, err := con.Rpc.GetCertificateInfo(context.Background(), request)
if err != nil {
con.PrintErrorf("could not get certificate information from database: %s", err.Error())
return
}
printCertificateInfo(con, certificateInfo.Info)
}
func checkCertExpiry(expiryTime time.Time) string {
if expiryTime.Before(time.Now()) || expiryTime.Equal(time.Now()) {
return console.Bold + console.Red
}
// One week is 168 hours - this is bad
if expiryTime.Before(time.Now().Add(168 * time.Hour)) {
return console.Bold + console.Red
}
// One month is approximately 730 hours - this is a warning
if expiryTime.Before(time.Now().Add(730 * time.Hour)) {
return console.Bold + console.Orange
}
return console.Normal
}
func printCertificateInfo(con *console.SliverClient, certData []*clientpb.CertificateData) {
// Get the terminal width
width, _, err := term.GetSize(0)
if err != nil {
width = 999
}
if len(certData) == 0 {
con.PrintWarnf("There are no certificates in the database matching the given parameters.\n")
return
}
tw := table.NewWriter()
tw.SetStyle(settings.GetTableStyle(con))
wideTermWidth := con.Settings.SmallTermWidth < width
if wideTermWidth {
tw.AppendHeader(table.Row{
"ID",
"Common Name",
"Creation Time",
"Certificate Type",
"Key Algorithm",
"Validity Start",
"Expires",
})
} else {
tw.AppendHeader(table.Row{
"ID",
"Common Name",
"Expires",
})
}
for _, cert := range certData {
rowColor := console.Normal
expiry, err := time.Parse(timeFormat, cert.ValidityExpiry)
// This should not error out, but if it does, the row will not be colored
if err == nil {
rowColor = checkCertExpiry(expiry)
}
if wideTermWidth {
tw.AppendRow(table.Row{
fmt.Sprintf(rowColor+"%s"+console.Normal, cert.ID),
fmt.Sprintf(rowColor+"%s"+console.Normal, cert.CN),
fmt.Sprintf(rowColor+"%s"+console.Normal, cert.CreationTime),
fmt.Sprintf(rowColor+"%s"+console.Normal, cert.Type),
fmt.Sprintf(rowColor+"%s"+console.Normal, cert.KeyAlgorithm),
fmt.Sprintf(rowColor+"%s"+console.Normal, cert.ValidityStart),
fmt.Sprintf(rowColor+"%s"+console.Normal, cert.ValidityExpiry),
})
} else {
tw.AppendRow(table.Row{
fmt.Sprintf(rowColor+"%s"+console.Normal, cert.ID),
fmt.Sprintf(rowColor+"%s"+console.Normal, cert.CN),
fmt.Sprintf(rowColor+"%s"+console.Normal, cert.ValidityExpiry),
})
}
}
tw.SortBy([]table.SortBy{{Name: "Expires", Mode: table.Dsc}})
con.Printf("%s\n", tw.Render())
}
+51
View File
@@ -0,0 +1,51 @@
package certificates
/*
Sliver Implant Framework
Copyright (C) 2024 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 (
"github.com/bishopfox/sliver/client/command/flags"
"github.com/bishopfox/sliver/client/command/help"
"github.com/bishopfox/sliver/client/console"
consts "github.com/bishopfox/sliver/client/constants"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
)
func Commands(con *console.SliverClient) []*cobra.Command {
certificatesCmd := &cobra.Command{
Use: consts.CertificatesStr,
Short: "Certificate management",
Long: help.GetHelpFor([]string{consts.CertificatesStr}),
Run: func(cmd *cobra.Command, args []string) {
CertificateInfoCmd(cmd, con, args)
},
GroupID: consts.GenericHelpGroup,
}
flags.Bind(consts.CertificatesStr, false, certificatesCmd, func(f *pflag.FlagSet) {
f.BoolP("mtls", "m", false, "Show MTLS certificates")
f.BoolP("https", "p", false, "Show HTTPS certificates")
f.BoolP("implant", "i", false, "Show implant certificates")
f.BoolP("server", "s", false, "Show server certificates")
f.StringP("cn", "c", "", "Show certificate information for a provided common name")
})
return []*cobra.Command{
certificatesCmd,
}
}
+141
View File
@@ -0,0 +1,141 @@
package clean
/*
Sliver Implant Framework
Copyright (C) 2023 Bishop Fox
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import (
"context"
"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/protobuf/clientpb"
"github.com/bishopfox/sliver/protobuf/commonpb"
"github.com/bishopfox/sliver/protobuf/sliverpb"
"github.com/spf13/cobra"
)
// CleanCmd - Remove all profiles, beacons, sessions and implant builds (Builds and logs will still exist on disk in .sliver)
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)
if !confirm {
return
}
err := removeSessionsAndBeacons(con)
if err != nil {
con.PrintErrorf("%s\n", err)
return
}
err = removeImplantBuilds(con)
if err != nil {
con.PrintErrorf("%s\n", err)
return
}
err = removeProfiles(con)
if err != nil {
con.PrintErrorf("%s\n", err)
return
}
con.Printf("All done !\n")
}
func removeImplantBuilds(con *console.SliverClient) error {
builds, err := con.Rpc.ImplantBuilds(context.Background(), &commonpb.Empty{})
if err != nil {
return err
}
for name, _ := range builds.Configs {
_, err := con.Rpc.DeleteImplantBuild(context.Background(), &clientpb.DeleteReq{
Name: name,
})
if err != nil {
return err
}
}
return nil
}
func removeProfiles(con *console.SliverClient) error {
profiles, err := con.Rpc.ImplantProfiles(context.Background(), &commonpb.Empty{})
if err != nil {
return err
}
for _, profile := range profiles.Profiles {
_, err := con.Rpc.DeleteImplantProfile(context.Background(), &clientpb.DeleteReq{
Name: profile.Name,
})
if err != nil {
return err
}
}
return nil
}
func removeSessionsAndBeacons(con *console.SliverClient) error {
sessions, err := con.Rpc.GetSessions(context.Background(), &commonpb.Empty{})
if err != nil {
return err
}
for _, session := range sessions.Sessions {
_, err := con.Rpc.Kill(context.Background(), &sliverpb.KillReq{
Request: &commonpb.Request{
SessionID: session.ID,
Timeout: flags.DefaultTimeout,
},
Force: false,
})
if err != nil {
return err
}
}
beacons, err := con.Rpc.GetBeacons(context.Background(), &commonpb.Empty{})
if err != nil {
return err
}
for _, beacon := range beacons.Beacons {
_, err = con.Rpc.RmBeacon(context.Background(), &clientpb.Beacon{ID: beacon.ID})
if err != nil {
return err
}
}
return nil
}
// Commands returns the `exit` command.
func Command(con *console.SliverClient) []*cobra.Command {
return []*cobra.Command{{
Use: "clean",
Short: "Remove all profiles, beacons, sessions, implant builds and HTTP profiles (Builds and logs will still exist on disk in .sliver)",
Run: func(cmd *cobra.Command, args []string) {
CleanCmd(cmd, con, args)
},
GroupID: constants.GenericHelpGroup,
}}
}
+69 -12
View File
@@ -21,19 +21,18 @@ package command
import (
"strings"
client "github.com/bishopfox/sliver/client/console"
"github.com/reeflective/console"
"github.com/rsteube/carapace"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
)
const defaultTimeout = 60
// Flags is a convenience function to bind flags to a given command.
// Bind is a convenience function to bind flags to a given command.
// name - The name of the flag set (can be empty).
// cmd - The command to which the flags should be bound.
// flags - A function exposing the flag set through which flags are declared.
func Flags(name string, persistent bool, cmd *cobra.Command, flags func(f *pflag.FlagSet)) {
func Bind(name string, persistent bool, cmd *cobra.Command, flags func(f *pflag.FlagSet)) {
flagSet := pflag.NewFlagSet(name, pflag.ContinueOnError) // Create the flag set.
flags(flagSet) // Let the user bind any number of flags to it.
@@ -44,22 +43,21 @@ func Flags(name string, persistent bool, cmd *cobra.Command, flags func(f *pflag
}
}
// FlagComps is a convenience function for adding completions to a command's flags.
// BindFlagCompletions is a convenience function for adding completions to a command's flags.
// cmd - The command owning the flags to complete.
// bind - A function exposing a map["flag-name"]carapace.Action.
func FlagComps(cmd *cobra.Command, bind func(comp *carapace.ActionMap)) {
func BindFlagCompletions(cmd *cobra.Command, bind func(comp *carapace.ActionMap)) {
comps := make(carapace.ActionMap)
bind(&comps)
carapace.Gen(cmd).FlagCompletion(comps)
}
// hideCommand generates a cobra annotation map with a single
// console.CommandHiddenFilter key, which value is a comma-separated list
// of filters to use in order to expose/hide commands based on requirements.
// Ex: cmd.Annotations = hideCommand("windows") will hide the cmd
// if the target session/beacon is not a Windows host.
func hideCommand(filters ...string) map[string]string {
// RestrictTargets generates a cobra annotation map with a single console.CommandHiddenFilter key
// to a comma-separated list of filters to use in order to expose/hide commands based on requirements.
// Ex: cmd.Annotations = RestrictTargets("windows") will only show the command if the target is Windows.
// Ex: cmd.Annotations = RestrictTargets("windows", "beacon") show the command if target is a beacon on Windows.
func RestrictTargets(filters ...string) map[string]string {
if len(filters) == 0 {
return nil
}
@@ -76,3 +74,62 @@ func hideCommand(filters ...string) map[string]string {
console.CommandFilterKey: filts,
}
}
// makeBind returns a commandBinder helper function
// @menu - The command menu to which the commands should be bound (either server or implant menu).
func makeBind(cmd *cobra.Command, con *client.SliverClient) func(group string, cmds ...func(con *client.SliverClient) []*cobra.Command) {
return func(group string, cmds ...func(con *client.SliverClient) []*cobra.Command) {
found := false
// Ensure the given command group is available in the menu.
if group != "" {
for _, grp := range cmd.Groups() {
if grp.Title == group {
found = true
break
}
}
if !found {
cmd.AddGroup(&cobra.Group{
ID: group,
Title: group,
})
}
}
// Bind the command to the root
for _, command := range cmds {
cmd.AddCommand(command(con)...)
}
}
}
// commandBinder is a helper used to bind commands to a given menu, for a given "command help group".
//
// @group - Name of the group under which the command should be shown. Preferably use a string in the constants package.
// @ cmds - A list of functions returning a list of root commands to bind. See any package's `commands.go` file and function.
// type commandBinder func(group string, cmds ...func(con *client.SliverClient) []*cobra.Command)
// [ Core ]
// [ Sessions ]
// [ Execution ]
// [ Filesystem ]
// [ Info ]
// [ Network (C2)]
// [ Network tools ]
// [ Payloads ]
// [ Privileges ]
// [ Processes ]
// [ Aliases ]
// [ Extensions ]
// Commands not to bind in CLI:
// - portforwarders
// - Socks (and wg-socks ?)
// - shell ?
// Take care of:
// - double bind help command
// - double bind session commands
// - don't bind readline command in CLI.
+29
View File
@@ -55,3 +55,32 @@ func ClientInterfacesCompleter() carapace.Action {
return carapace.ActionValues(results...).Tag("client interfaces").NoSpace(':')
})
}
// LocalProxyCompleter gives URL completion to all flags/arguments that accept a client proxy address.
func LocalProxyCompleter() carapace.Action {
return carapace.ActionCallback(func(c carapace.Context) carapace.Action {
prefix := ""
hostPort := carapace.ActionMultiParts(":", func(c carapace.Context) carapace.Action {
switch len(c.Parts) {
case 0:
return ClientInterfacesCompleter()
case 1:
return carapace.ActionMessage("server port")
default:
return carapace.ActionValues()
}
})
return carapace.ActionMultiParts("://", func(c carapace.Context) carapace.Action {
switch len(c.Parts) {
case 0:
return carapace.ActionValues("http", "https").Tag("proxy protocols").Suffix("://")
case 1:
return hostPort
default:
return carapace.ActionValues()
}
}).Invoke(c).Prefix(prefix).ToA()
})
}
+143
View File
@@ -0,0 +1,143 @@
package crack
import (
"github.com/rsteube/carapace"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
"github.com/bishopfox/sliver/client/command/flags"
"github.com/bishopfox/sliver/client/command/help"
"github.com/bishopfox/sliver/client/console"
consts "github.com/bishopfox/sliver/client/constants"
)
// Commands returns the “ command and its subcommands.
func Commands(con *console.SliverClient) []*cobra.Command {
crackCmd := &cobra.Command{
Use: consts.CrackStr,
Short: "Crack: GPU password cracking",
Long: help.GetHelpFor([]string{consts.CrackStr}),
GroupID: consts.GenericHelpGroup,
Run: func(cmd *cobra.Command, args []string) {
CrackCmd(cmd, con, args)
},
}
flags.Bind("", true, crackCmd, func(f *pflag.FlagSet) {
f.Int64P("timeout", "t", flags.DefaultTimeout, "grpc timeout in seconds")
})
crackStationsCmd := &cobra.Command{
Use: consts.StationsStr,
Short: "Manage crackstations",
Long: help.GetHelpFor([]string{consts.CrackStr, consts.StationsStr}),
Run: func(cmd *cobra.Command, args []string) {
CrackStationsCmd(cmd, con, args)
},
}
crackCmd.AddCommand(crackStationsCmd)
wordlistsCmd := &cobra.Command{
Use: consts.WordlistsStr,
Short: "Manage wordlists",
Long: help.GetHelpFor([]string{consts.CrackStr, consts.WordlistsStr}),
Run: func(cmd *cobra.Command, args []string) {
CrackWordlistsCmd(cmd, con, args)
},
}
crackCmd.AddCommand(wordlistsCmd)
wordlistsAddCmd := &cobra.Command{
Use: consts.AddStr,
Short: "Add a wordlist",
Run: func(cmd *cobra.Command, args []string) {
CrackWordlistsAddCmd(cmd, con, args)
},
}
flags.Bind("", false, wordlistsAddCmd, func(f *pflag.FlagSet) {
f.StringP("name", "n", "", "wordlist name (blank = filename)")
})
carapace.Gen(wordlistsAddCmd).PositionalCompletion(carapace.ActionFiles().Usage("path to local wordlist file"))
wordlistsCmd.AddCommand(wordlistsAddCmd)
wordlistsRmCmd := &cobra.Command{
Use: consts.RmStr,
Short: "Remove a wordlist",
Run: func(cmd *cobra.Command, args []string) {
CrackWordlistsRmCmd(cmd, con, args)
},
}
wordlistsCmd.AddCommand(wordlistsRmCmd)
carapace.Gen(wordlistsRmCmd).PositionalCompletion(CrackWordlistCompleter(con).Usage("wordlist to remove"))
rulesCmd := &cobra.Command{
Use: consts.RulesStr,
Short: "Manage rule files",
Long: help.GetHelpFor([]string{consts.CrackStr, consts.RulesStr}),
Run: func(cmd *cobra.Command, args []string) {
CrackRulesCmd(cmd, con, args)
},
}
crackCmd.AddCommand(rulesCmd)
rulesAddCmd := &cobra.Command{
Use: consts.AddStr,
Short: "Add a rules file",
Long: help.GetHelpFor([]string{consts.CrackStr, consts.RulesStr, consts.AddStr}),
Run: func(cmd *cobra.Command, args []string) {
CrackRulesAddCmd(cmd, con, args)
},
}
flags.Bind("", false, rulesAddCmd, func(f *pflag.FlagSet) {
f.StringP("name", "n", "", "rules name (blank = filename)")
})
carapace.Gen(rulesAddCmd).PositionalCompletion(carapace.ActionFiles().Usage("path to local rules file"))
rulesCmd.AddCommand(rulesAddCmd)
rulesRmCmd := &cobra.Command{
Use: consts.RmStr,
Short: "Remove rules",
Long: help.GetHelpFor([]string{consts.CrackStr, consts.RulesStr, consts.RmStr}),
Run: func(cmd *cobra.Command, args []string) {
CrackRulesRmCmd(cmd, con, args)
},
}
carapace.Gen(rulesRmCmd).PositionalCompletion(CrackRulesCompleter(con).Usage("rules to remove"))
rulesCmd.AddCommand(rulesRmCmd)
hcstat2Cmd := &cobra.Command{
Use: consts.Hcstat2Str,
Short: "Manage markov hcstat2 files",
Long: help.GetHelpFor([]string{consts.CrackStr, consts.Hcstat2Str}),
Run: func(cmd *cobra.Command, args []string) {
CrackHcstat2Cmd(cmd, con, args)
},
}
crackCmd.AddCommand(hcstat2Cmd)
hcstat2AddCmd := &cobra.Command{
Use: consts.AddStr,
Short: "Add a hcstat2 file",
Long: help.GetHelpFor([]string{consts.CrackStr, consts.Hcstat2Str, consts.AddStr}),
Run: func(cmd *cobra.Command, args []string) {
CrackHcstat2AddCmd(cmd, con, args)
},
}
flags.Bind("", false, hcstat2AddCmd, func(f *pflag.FlagSet) {
f.StringP("name", "n", "", "hcstat2 name (blank = filename)")
})
carapace.Gen(hcstat2AddCmd).PositionalCompletion(carapace.ActionFiles().Usage("path to local hcstat2 file"))
hcstat2Cmd.AddCommand(hcstat2AddCmd)
hcstat2RmCmd := &cobra.Command{
Use: consts.RmStr,
Short: "Remove hcstat2 file",
Long: help.GetHelpFor([]string{consts.CrackStr, consts.Hcstat2Str, consts.RmStr}),
Run: func(cmd *cobra.Command, args []string) {
CrackHcstat2RmCmd(cmd, con, args)
},
}
carapace.Gen(hcstat2RmCmd).PositionalCompletion(CrackHcstat2Completer(con).Usage("hcstat2 to remove"))
hcstat2Cmd.AddCommand(hcstat2RmCmd)
return []*cobra.Command{crackCmd}
}
+24 -25
View File
@@ -25,18 +25,17 @@ import (
"io"
"os"
"github.com/jedib0t/go-pretty/v6/table"
"github.com/klauspost/compress/zstd"
"github.com/spf13/cobra"
"github.com/bishopfox/sliver/client/command/settings"
"github.com/bishopfox/sliver/client/console"
"github.com/bishopfox/sliver/protobuf/clientpb"
"github.com/bishopfox/sliver/util"
"github.com/jedib0t/go-pretty/v6/table"
"github.com/klauspost/compress/zstd"
"github.com/spf13/cobra"
)
// CrackWordlistsCmd - Manage GPU cracking stations
func CrackWordlistsCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []string) {
// CrackWordlistsCmd - Manage GPU cracking stations.
func CrackWordlistsCmd(cmd *cobra.Command, con *console.SliverClient, args []string) {
wordlists, err := con.Rpc.CrackFilesList(context.Background(), &clientpb.CrackFile{Type: clientpb.CrackFileType_WORDLIST})
if err != nil {
con.PrintErrorf("%s\n", err)
@@ -55,8 +54,8 @@ func CrackWordlistsCmd(cmd *cobra.Command, con *console.SliverConsoleClient, arg
}
}
// CrackRulesCmd - Manage GPU cracking stations
func CrackRulesCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []string) {
// CrackRulesCmd - Manage GPU cracking stations.
func CrackRulesCmd(cmd *cobra.Command, con *console.SliverClient, args []string) {
rules, err := con.Rpc.CrackFilesList(context.Background(), &clientpb.CrackFile{Type: clientpb.CrackFileType_RULES})
if err != nil {
con.PrintErrorf("%s\n", err)
@@ -75,8 +74,8 @@ func CrackRulesCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []
}
}
// CrackHcstat2Cmd - Manage GPU cracking stations
func CrackHcstat2Cmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []string) {
// CrackHcstat2Cmd - Manage GPU cracking stations.
func CrackHcstat2Cmd(cmd *cobra.Command, con *console.SliverClient, args []string) {
hcstat2, err := con.Rpc.CrackFilesList(context.Background(), &clientpb.CrackFile{Type: clientpb.CrackFileType_MARKOV_HCSTAT2})
if err != nil {
con.PrintErrorf("%s\n", err)
@@ -95,7 +94,7 @@ func CrackHcstat2Cmd(cmd *cobra.Command, con *console.SliverConsoleClient, args
}
}
func PrintCrackFiles(crackFiles *clientpb.CrackFiles, con *console.SliverConsoleClient) {
func PrintCrackFiles(crackFiles *clientpb.CrackFiles, con *console.SliverClient) {
tw := table.NewWriter()
tw.SetStyle(settings.GetTableStyle(con))
tw.AppendHeader(table.Row{"Name", "Size"})
@@ -105,7 +104,7 @@ func PrintCrackFiles(crackFiles *clientpb.CrackFiles, con *console.SliverConsole
con.Printf("%s\n", tw.Render())
}
func PrintCrackFilesByType(crackFiles *clientpb.CrackFiles, con *console.SliverConsoleClient) {
func PrintCrackFilesByType(crackFiles *clientpb.CrackFiles, con *console.SliverClient) {
wordlistTable := table.NewWriter()
wordlistTable.SetTitle(console.Bold + "Wordlists" + console.Normal)
wordlistTable.SetStyle(settings.GetTableStyle(con))
@@ -162,8 +161,8 @@ func PrintCrackFilesByType(crackFiles *clientpb.CrackFiles, con *console.SliverC
)
}
// CrackWordlistsAddCmd - Manage GPU cracking stations
func CrackWordlistsAddCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []string) {
// CrackWordlistsAddCmd - Manage GPU cracking stations.
func CrackWordlistsAddCmd(cmd *cobra.Command, con *console.SliverClient, args []string) {
name, _ := cmd.Flags().GetString("name")
var localPath string
@@ -206,8 +205,8 @@ func CrackWordlistsAddCmd(cmd *cobra.Command, con *console.SliverConsoleClient,
addCrackFile(wordlist, crackFile, con)
}
// CrackRulesAddCmd - add a rules file
func CrackRulesAddCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []string) {
// CrackRulesAddCmd - add a rules file.
func CrackRulesAddCmd(cmd *cobra.Command, con *console.SliverClient, args []string) {
name, _ := cmd.Flags().GetString("name")
var localPath string
@@ -250,8 +249,8 @@ func CrackRulesAddCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args
addCrackFile(rules, crackFile, con)
}
// CrackHcstat2AddCmd - add a hcstat2 file
func CrackHcstat2AddCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []string) {
// CrackHcstat2AddCmd - add a hcstat2 file.
func CrackHcstat2AddCmd(cmd *cobra.Command, con *console.SliverClient, args []string) {
name, _ := cmd.Flags().GetString("name")
var localPath string
@@ -294,7 +293,7 @@ func CrackHcstat2AddCmd(cmd *cobra.Command, con *console.SliverConsoleClient, ar
addCrackFile(hcstat2, crackFile, con)
}
func addCrackFile(localFile *os.File, crackFile *clientpb.CrackFile, con *console.SliverConsoleClient) {
func addCrackFile(localFile *os.File, crackFile *clientpb.CrackFile, con *console.SliverClient) {
digest := sha256.New()
wordlistReader := io.TeeReader(localFile, digest)
@@ -402,8 +401,8 @@ func readChunkAt(tmpFile *os.File, offset int64, chunkSize int64) ([]byte, error
return chunkBuf[:n], nil
}
// CrackWordlistsRmCmd - Manage GPU cracking stations
func CrackWordlistsRmCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []string) {
// CrackWordlistsRmCmd - Manage GPU cracking stations.
func CrackWordlistsRmCmd(cmd *cobra.Command, con *console.SliverClient, args []string) {
var wordlistName string
if len(args) > 0 {
wordlistName = args[0]
@@ -436,8 +435,8 @@ func CrackWordlistsRmCmd(cmd *cobra.Command, con *console.SliverConsoleClient, a
}
}
// CrackRulesRmCmd - Manage GPU cracking stations
func CrackRulesRmCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []string) {
// CrackRulesRmCmd - Manage GPU cracking stations.
func CrackRulesRmCmd(cmd *cobra.Command, con *console.SliverClient, args []string) {
var rulesName string
if len(args) > 0 {
rulesName = args[0]
@@ -470,8 +469,8 @@ func CrackRulesRmCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args
}
}
// CrackHcstat2RmCmd - remove a hcstat2 file
func CrackHcstat2RmCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []string) {
// CrackHcstat2RmCmd - remove a hcstat2 file.
func CrackHcstat2RmCmd(cmd *cobra.Command, con *console.SliverClient, args []string) {
var hcstat2Name string
if len(args) > 0 {
hcstat2Name = args[0]
+7 -7
View File
@@ -33,7 +33,7 @@ import (
)
// CrackCmd - GPU password cracking interface
func CrackCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []string) {
func CrackCmd(cmd *cobra.Command, con *console.SliverClient, args []string) {
if !AreCrackersOnline(con) {
PrintNoCrackstations(con)
} else {
@@ -58,7 +58,7 @@ func CrackCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []strin
}
// CrackStationsCmd - Manage GPU cracking stations
func CrackStationsCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []string) {
func CrackStationsCmd(cmd *cobra.Command, con *console.SliverClient, args []string) {
crackers, err := con.Rpc.Crackstations(context.Background(), &commonpb.Empty{})
if err != nil {
con.PrintErrorf("%s\n", err)
@@ -71,11 +71,11 @@ func CrackStationsCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args
}
}
func PrintNoCrackstations(con *console.SliverConsoleClient) {
func PrintNoCrackstations(con *console.SliverClient) {
con.PrintInfof("No crackstations connected to server\n")
}
func AreCrackersOnline(con *console.SliverConsoleClient) bool {
func AreCrackersOnline(con *console.SliverClient) bool {
crackers, err := con.Rpc.Crackstations(context.Background(), &commonpb.Empty{})
if err != nil {
return false
@@ -83,7 +83,7 @@ func AreCrackersOnline(con *console.SliverConsoleClient) bool {
return len(crackers.Crackstations) > 0
}
func PrintCrackers(crackers []*clientpb.Crackstation, con *console.SliverConsoleClient) {
func PrintCrackers(crackers []*clientpb.Crackstation, con *console.SliverClient) {
sort.Slice(crackers, func(i, j int) bool {
return crackers[i].Name < crackers[j].Name
})
@@ -96,7 +96,7 @@ func PrintCrackers(crackers []*clientpb.Crackstation, con *console.SliverConsole
}
}
func printCracker(cracker *clientpb.Crackstation, index int, con *console.SliverConsoleClient) {
func printCracker(cracker *clientpb.Crackstation, index int, con *console.SliverClient) {
tw := table.NewWriter()
tw.SetStyle(settings.GetTableStyle(con))
tw.SetTitle(console.Bold + console.Orange + fmt.Sprintf(">>> Crackstation %02d - %s (%s)", index+1, cracker.Name, cracker.OperatorName) + console.Normal + "\n")
@@ -135,7 +135,7 @@ func printCracker(cracker *clientpb.Crackstation, index int, con *console.Sliver
printBenchmarks(cracker, con)
}
func printBenchmarks(cracker *clientpb.Crackstation, con *console.SliverConsoleClient) {
func printBenchmarks(cracker *clientpb.Crackstation, con *console.SliverClient) {
tw := table.NewWriter()
tw.SetStyle(settings.GetTableStyle(con))
tw.SetTitle(console.Bold + "Benchmarks" + console.Normal)
+3 -3
View File
@@ -10,7 +10,7 @@ import (
"github.com/rsteube/carapace"
)
func CrackHcstat2Completer(con *console.SliverConsoleClient) carapace.Action {
func CrackHcstat2Completer(con *console.SliverClient) carapace.Action {
return carapace.ActionCallback(func(c carapace.Context) carapace.Action {
hcstat2, err := con.Rpc.CrackFilesList(context.Background(), &clientpb.CrackFile{Type: clientpb.CrackFileType_MARKOV_HCSTAT2})
if err != nil {
@@ -33,7 +33,7 @@ func CrackHcstat2Completer(con *console.SliverConsoleClient) carapace.Action {
})
}
func CrackWordlistCompleter(con *console.SliverConsoleClient) carapace.Action {
func CrackWordlistCompleter(con *console.SliverClient) carapace.Action {
return carapace.ActionCallback(func(c carapace.Context) carapace.Action {
hcstat2, err := con.Rpc.CrackFilesList(context.Background(), &clientpb.CrackFile{Type: clientpb.CrackFileType_MARKOV_HCSTAT2})
if err != nil {
@@ -57,7 +57,7 @@ func CrackWordlistCompleter(con *console.SliverConsoleClient) carapace.Action {
})
}
func CrackRulesCompleter(con *console.SliverConsoleClient) carapace.Action {
func CrackRulesCompleter(con *console.SliverClient) carapace.Action {
return carapace.ActionCallback(func(c carapace.Context) carapace.Action {
hcstat2, err := con.Rpc.CrackFilesList(context.Background(), &clientpb.CrackFile{Type: clientpb.CrackFileType_MARKOV_HCSTAT2})
if err != nil {
+4 -4
View File
@@ -37,8 +37,8 @@ const (
CSVFormat = "csv" // username,hash\n
)
// CredsCmd - Add new credentials
func CredsAddCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []string) {
// CredsCmd - Add new credentials.
func CredsAddCmd(cmd *cobra.Command, con *console.SliverClient, args []string) {
collection, _ := cmd.Flags().GetString("collection")
username, _ := cmd.Flags().GetString("username")
plaintext, _ := cmd.Flags().GetString("plaintext")
@@ -76,8 +76,8 @@ func CredsAddCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []st
PrintCreds(creds.Credentials, con)
}
// CredsCmd - Add new credentials
func CredsAddHashFileCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []string) {
// CredsCmd - Add new credentials.
func CredsAddHashFileCmd(cmd *cobra.Command, con *console.SliverClient, args []string) {
collection, _ := cmd.Flags().GetString("collection")
filePath := args[0]
fileFormat, _ := cmd.Flags().GetString("file-format")
+82
View File
@@ -0,0 +1,82 @@
package creds
import (
"github.com/bishopfox/sliver/client/command/flags"
"github.com/bishopfox/sliver/client/command/help"
"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.
func Commands(con *console.SliverClient) []*cobra.Command {
credsCmd := &cobra.Command{
Use: consts.CredsStr,
Short: "Manage the database of credentials",
Long: help.GetHelpFor([]string{consts.CredsStr}),
GroupID: consts.GenericHelpGroup,
Run: func(cmd *cobra.Command, args []string) {
CredsCmd(cmd, con, args)
},
}
flags.Bind("creds", true, credsCmd, func(f *pflag.FlagSet) {
f.IntP("timeout", "t", flags.DefaultTimeout, "grpc timeout in seconds")
})
credsAddCmd := &cobra.Command{
Use: consts.AddStr,
Short: "Add a credential to the database",
Long: help.GetHelpFor([]string{consts.CredsStr, consts.AddStr}),
Run: func(cmd *cobra.Command, args []string) {
CredsAddCmd(cmd, con, args)
},
}
flags.Bind("", false, credsAddCmd, func(f *pflag.FlagSet) {
f.StringP("collection", "c", "", "name of collection")
f.StringP("username", "u", "", "username for the credential")
f.StringP("plaintext", "p", "", "plaintext for the credential")
f.StringP("hash", "P", "", "hash of the credential")
f.StringP("hash-type", "H", "", "hash type of the credential")
})
flags.BindFlagCompletions(credsAddCmd, func(comp *carapace.ActionMap) {
(*comp)["hash-type"] = CredsHashTypeCompleter(con)
})
credsCmd.AddCommand(credsAddCmd)
credsAddFileCmd := &cobra.Command{
Use: consts.FileStr,
Short: "Add a credential to the database",
Long: help.GetHelpFor([]string{consts.CredsStr, consts.AddStr, consts.FileStr}),
Args: cobra.ExactArgs(1),
Run: func(cmd *cobra.Command, args []string) {
CredsAddHashFileCmd(cmd, con, args)
},
}
flags.Bind("", false, credsAddFileCmd, func(f *pflag.FlagSet) {
f.StringP("collection", "c", "", "name of collection")
f.StringP("file-format", "F", HashNewlineFormat, "file format of the credential file")
f.StringP("hash-type", "H", "", "hash type of the credential")
})
flags.BindFlagCompletions(credsAddFileCmd, func(comp *carapace.ActionMap) {
(*comp)["collection"] = CredsCollectionCompleter(con)
(*comp)["file-format"] = CredsHashFileFormatCompleter(con)
(*comp)["hash-type"] = CredsHashTypeCompleter(con)
})
carapace.Gen(credsAddFileCmd).PositionalCompletion(carapace.ActionFiles().Tag("credential file"))
credsAddCmd.AddCommand(credsAddFileCmd)
credsRmCmd := &cobra.Command{
Use: consts.RmStr,
Short: "Remove a credential to the database",
Long: help.GetHelpFor([]string{consts.CredsStr, consts.RmStr}),
Run: func(cmd *cobra.Command, args []string) {
CredsRmCmd(cmd, con, args)
},
}
carapace.Gen(credsRmCmd).PositionalCompletion(CredsCredentialIDCompleter(con).Usage("id of credential to remove (leave empty to select)"))
credsCmd.AddCommand(credsRmCmd)
return []*cobra.Command{credsCmd}
}
+13 -14
View File
@@ -23,18 +23,17 @@ import (
"fmt"
"strings"
"github.com/jedib0t/go-pretty/v6/table"
"github.com/rsteube/carapace"
"github.com/spf13/cobra"
"github.com/bishopfox/sliver/client/command/settings"
"github.com/bishopfox/sliver/client/console"
"github.com/bishopfox/sliver/protobuf/clientpb"
"github.com/bishopfox/sliver/protobuf/commonpb"
"github.com/jedib0t/go-pretty/v6/table"
"github.com/rsteube/carapace"
"github.com/spf13/cobra"
)
// CredsCmd - Manage credentials
func CredsCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []string) {
// CredsCmd - Manage credentials.
func CredsCmd(cmd *cobra.Command, con *console.SliverClient, args []string) {
creds, err := con.Rpc.Creds(context.Background(), &commonpb.Empty{})
if err != nil {
con.PrintErrorf("%s\n", err)
@@ -47,7 +46,7 @@ func CredsCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []strin
PrintCreds(creds.Credentials, con)
}
func PrintCreds(creds []*clientpb.Credential, con *console.SliverConsoleClient) {
func PrintCreds(creds []*clientpb.Credential, con *console.SliverClient) {
collections := make(map[string][]*clientpb.Credential)
for _, cred := range creds {
collections[cred.Collection] = append(collections[cred.Collection], cred)
@@ -58,7 +57,7 @@ func PrintCreds(creds []*clientpb.Credential, con *console.SliverConsoleClient)
}
}
func printCollection(collection string, creds []*clientpb.Credential, con *console.SliverConsoleClient) {
func printCollection(collection string, creds []*clientpb.Credential, con *console.SliverClient) {
tw := table.NewWriter()
tw.SetStyle(settings.GetTableStyle(con))
if collection != "" {
@@ -88,7 +87,7 @@ func printCollection(collection string, creds []*clientpb.Credential, con *conso
}
// CredsHashTypeCompleter completes hash types.
func CredsHashTypeCompleter(con *console.SliverConsoleClient) carapace.Action {
func CredsHashTypeCompleter(con *console.SliverClient) carapace.Action {
return carapace.ActionCallback(func(c carapace.Context) carapace.Action {
results := make([]string, 0)
@@ -101,8 +100,8 @@ func CredsHashTypeCompleter(con *console.SliverConsoleClient) carapace.Action {
})
}
// CredsHashFileFormatCompleter completes file formats for hash-files
func CredsHashFileFormatCompleter(con *console.SliverConsoleClient) carapace.Action {
// CredsHashFileFormatCompleter completes file formats for hash-files.
func CredsHashFileFormatCompleter(con *console.SliverClient) carapace.Action {
return carapace.ActionValuesDescribed(
UserColonHashNewlineFormat, "One hash per line.",
HashNewlineFormat, "A file containing lines of 'username:hash' pairs.",
@@ -110,8 +109,8 @@ func CredsHashFileFormatCompleter(con *console.SliverConsoleClient) carapace.Act
).Tag("hash file formats")
}
// CredsCollectionCompleter completes existing creds collection names
func CredsCollectionCompleter(con *console.SliverConsoleClient) carapace.Action {
// CredsCollectionCompleter completes existing creds collection names.
func CredsCollectionCompleter(con *console.SliverClient) carapace.Action {
return carapace.ActionCallback(func(c carapace.Context) carapace.Action {
results := make([]string, 0)
@@ -134,7 +133,7 @@ func CredsCollectionCompleter(con *console.SliverConsoleClient) carapace.Action
}
// CredsCredentialIDCompleter completes credential IDs.
func CredsCredentialIDCompleter(con *console.SliverConsoleClient) carapace.Action {
func CredsCredentialIDCompleter(con *console.SliverClient) carapace.Action {
return carapace.ActionCallback(func(c carapace.Context) carapace.Action {
results := make([]string, 0)
+2 -2
View File
@@ -27,8 +27,8 @@ import (
"github.com/spf13/cobra"
)
// CredsCmd - Add new credentials
func CredsRmCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []string) {
// CredsCmd - Add new credentials.
func CredsRmCmd(cmd *cobra.Command, con *console.SliverClient, args []string) {
var id string
if len(args) > 0 {
id = args[0]
+2 -3
View File
@@ -9,14 +9,13 @@ import (
"text/tabwriter"
"github.com/AlecAivazis/survey/v2"
"github.com/bishopfox/sliver/client/console"
"github.com/bishopfox/sliver/protobuf/clientpb"
"github.com/bishopfox/sliver/protobuf/commonpb"
)
// SelectCredential - Interactive menu for the user to select a credentials from the database
func SelectCredential(plaintext bool, hashType clientpb.HashType, con *console.SliverConsoleClient) (*clientpb.Credential, error) {
// SelectCredential - Interactive menu for the user to select a credentials from the database.
func SelectCredential(plaintext bool, hashType clientpb.HashType, con *console.SliverClient) (*clientpb.Credential, error) {
var creds *clientpb.Credentials
var err error
if hashType == clientpb.HashType_INVALID {
+149
View File
@@ -0,0 +1,149 @@
package cursed
import (
"github.com/bishopfox/sliver/client/command/flags"
"github.com/bishopfox/sliver/client/command/help"
"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.
func Commands(con *console.SliverClient) []*cobra.Command {
cursedCmd := &cobra.Command{
Use: consts.Cursed,
Short: "Chrome/electron post-exploitation tool kit (∩`-´)⊃━☆゚.*・。゚",
Long: help.GetHelpFor([]string{consts.Cursed}),
GroupID: consts.ExecutionHelpGroup,
Annotations: flags.RestrictTargets(consts.SessionCmdsFilter),
Run: func(cmd *cobra.Command, args []string) {
CursedCmd(cmd, con, args)
},
}
flags.Bind("", true, cursedCmd, func(f *pflag.FlagSet) {
f.Int64P("timeout", "t", flags.DefaultTimeout, "grpc timeout in seconds")
})
cursedRmCmd := &cobra.Command{
Use: consts.RmStr,
Short: "Remove a Curse from a process",
Long: help.GetHelpFor([]string{consts.Cursed, consts.CursedConsole}),
Args: cobra.ExactArgs(1),
Run: func(cmd *cobra.Command, args []string) {
CursedRmCmd(cmd, con, args)
},
}
cursedCmd.AddCommand(cursedRmCmd)
flags.Bind("", false, cursedRmCmd, func(f *pflag.FlagSet) {
f.BoolP("kill", "k", false, "kill the process after removing the curse")
})
carapace.Gen(cursedRmCmd).PositionalCompletion(carapace.ActionValues().Usage("bind port of the Cursed process to stop"))
cursedConsoleCmd := &cobra.Command{
Use: consts.CursedConsole,
Short: "Start a JavaScript console connected to a debug target",
Long: help.GetHelpFor([]string{consts.Cursed, consts.CursedConsole}),
Run: func(cmd *cobra.Command, args []string) {
CursedConsoleCmd(cmd, con, args)
},
}
cursedCmd.AddCommand(cursedConsoleCmd)
flags.Bind("", false, cursedConsoleCmd, func(f *pflag.FlagSet) {
f.IntP("remote-debugging-port", "r", 0, "remote debugging tcp port (0 = random)`")
})
cursedChromeCmd := &cobra.Command{
Use: consts.CursedChrome,
Short: "Automatically inject a Cursed Chrome payload into a remote Chrome extension",
Long: help.GetHelpFor([]string{consts.Cursed, consts.CursedChrome}),
Run: func(cmd *cobra.Command, args []string) {
CursedChromeCmd(cmd, con, args)
},
}
cursedCmd.AddCommand(cursedChromeCmd)
flags.Bind("", false, cursedChromeCmd, func(f *pflag.FlagSet) {
f.IntP("remote-debugging-port", "r", 0, "remote debugging tcp port (0 = random)")
f.BoolP("restore", "R", true, "restore the user's session after process termination")
f.StringP("exe", "e", "", "chrome/chromium browser executable path (blank string = auto)")
f.StringP("user-data", "u", "", "user data directory (blank string = auto)")
f.StringP("payload", "p", "", "cursed chrome payload file path (.js)")
f.BoolP("keep-alive", "k", false, "keeps browser alive after last browser window closes")
f.BoolP("headless", "H", false, "start browser process in headless mode")
})
flags.BindFlagCompletions(cursedChromeCmd, func(comp *carapace.ActionMap) {
(*comp)["payload"] = carapace.ActionFiles("js").Tag("javascript files")
})
cursedChromeCmd.Flags().ParseErrorsWhitelist.UnknownFlags = true
carapace.Gen(cursedChromeCmd).PositionalAnyCompletion(carapace.ActionValues().Usage("additional Chrome CLI arguments"))
cursedEdgeCmd := &cobra.Command{
Use: consts.CursedEdge,
Short: "Automatically inject a Cursed Chrome payload into a remote Edge extension",
Long: help.GetHelpFor([]string{consts.Cursed, consts.CursedEdge}),
Run: func(cmd *cobra.Command, args []string) {
CursedEdgeCmd(cmd, con, args)
},
}
cursedCmd.AddCommand(cursedEdgeCmd)
flags.Bind("", false, cursedEdgeCmd, func(f *pflag.FlagSet) {
f.IntP("remote-debugging-port", "r", 0, "remote debugging tcp port (0 = random)")
f.BoolP("restore", "R", true, "restore the user's session after process termination")
f.StringP("exe", "e", "", "edge browser executable path (blank string = auto)")
f.StringP("user-data", "u", "", "user data directory (blank string = auto)")
f.StringP("payload", "p", "", "cursed chrome payload file path (.js)")
f.BoolP("keep-alive", "k", false, "keeps browser alive after last browser window closes")
f.BoolP("headless", "H", false, "start browser process in headless mode")
})
flags.BindFlagCompletions(cursedEdgeCmd, func(comp *carapace.ActionMap) {
(*comp)["payload"] = carapace.ActionFiles("js").Tag("javascript files")
})
cursedEdgeCmd.Flags().ParseErrorsWhitelist.UnknownFlags = true
carapace.Gen(cursedEdgeCmd).PositionalAnyCompletion(carapace.ActionValues().Usage("additional Edge CLI arguments"))
cursedElectronCmd := &cobra.Command{
Use: consts.CursedElectron,
Short: "Curse a remote Electron application",
Long: help.GetHelpFor([]string{consts.Cursed, consts.CursedElectron}),
Run: func(cmd *cobra.Command, args []string) {
CursedElectronCmd(cmd, con, args)
},
}
cursedCmd.AddCommand(cursedElectronCmd)
flags.Bind("", false, cursedElectronCmd, func(f *pflag.FlagSet) {
f.StringP("exe", "e", "", "remote electron executable absolute path")
f.IntP("remote-debugging-port", "r", 0, "remote debugging tcp port (0 = random)")
})
cursedElectronCmd.Flags().ParseErrorsWhitelist.UnknownFlags = true
carapace.Gen(cursedElectronCmd).PositionalAnyCompletion(carapace.ActionValues().Usage("additional Electron CLI arguments"))
CursedCookiesCmd := &cobra.Command{
Use: consts.CursedCookies,
Short: "Dump all cookies from cursed process",
Long: help.GetHelpFor([]string{consts.Cursed, consts.CursedCookies}),
Run: func(cmd *cobra.Command, args []string) {
CursedCookiesCmd(cmd, con, args)
},
}
cursedCmd.AddCommand(CursedCookiesCmd)
flags.Bind("", false, CursedCookiesCmd, func(f *pflag.FlagSet) {
f.StringP("save", "s", "", "save to file")
})
cursedScreenshotCmd := &cobra.Command{
Use: consts.ScreenshotStr,
Short: "Take a screenshot of a cursed process debug target",
Long: help.GetHelpFor([]string{consts.Cursed, consts.ScreenshotStr}),
Run: func(cmd *cobra.Command, args []string) {
CursedScreenshotCmd(cmd, con, args)
},
}
cursedCmd.AddCommand(cursedScreenshotCmd)
flags.Bind("", false, cursedScreenshotCmd, func(f *pflag.FlagSet) {
f.Int64P("quality", "q", 100, "screenshot quality (1 - 100)")
f.StringP("save", "s", "", "save to file")
})
return []*cobra.Command{cursedCmd}
}
+8 -9
View File
@@ -29,8 +29,6 @@ import (
"time"
"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/overlord"
@@ -38,6 +36,7 @@ import (
"github.com/bishopfox/sliver/protobuf/clientpb"
"github.com/bishopfox/sliver/protobuf/commonpb"
"github.com/bishopfox/sliver/protobuf/sliverpb"
"github.com/spf13/cobra"
)
var (
@@ -51,8 +50,8 @@ var (
cursedChromePermissionsAlt = []string{overlord.AllHTTP, overlord.AllHTTPS, overlord.WebRequest, overlord.WebRequestBlocking}
)
// CursedChromeCmd - Execute a .NET assembly in-memory
func CursedChromeCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []string) {
// CursedChromeCmd - Execute a .NET assembly in-memory.
func CursedChromeCmd(cmd *cobra.Command, con *console.SliverClient, args []string) {
session := con.ActiveTarget.GetSessionInteractive()
if session == nil {
return
@@ -112,7 +111,7 @@ func CursedChromeCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args
}
}
func avadaKedavraChrome(session *clientpb.Session, cmd *cobra.Command, con *console.SliverConsoleClient, cargs []string) *core.CursedProcess {
func avadaKedavraChrome(session *clientpb.Session, cmd *cobra.Command, con *console.SliverClient, cargs []string) *core.CursedProcess {
chromeProcess, err := getChromeProcess(session, cmd, con)
if err != nil {
con.PrintErrorf("%s\n", err)
@@ -154,7 +153,7 @@ func avadaKedavraChrome(session *clientpb.Session, cmd *cobra.Command, con *cons
return curse
}
func startCursedChromeProcess(isEdge bool, session *clientpb.Session, cmd *cobra.Command, con *console.SliverConsoleClient, cargs []string) (*core.CursedProcess, error) {
func startCursedChromeProcess(isEdge bool, session *clientpb.Session, cmd *cobra.Command, con *console.SliverClient, cargs []string) (*core.CursedProcess, error) {
name := "Chrome"
if isEdge {
name = "Edge"
@@ -254,7 +253,7 @@ func startCursedChromeProcess(isEdge bool, session *clientpb.Session, cmd *cobra
return curse, nil
}
func findChromeUserDataDir(isEdge bool, session *clientpb.Session, cmd *cobra.Command, con *console.SliverConsoleClient) (string, error) {
func findChromeUserDataDir(isEdge bool, session *clientpb.Session, cmd *cobra.Command, con *console.SliverClient) (string, error) {
userDataFlag, _ := cmd.Flags().GetString("user-data")
if userDataFlag != "" {
return userDataFlag, nil
@@ -307,7 +306,7 @@ func findChromeUserDataDir(isEdge bool, session *clientpb.Session, cmd *cobra.Co
}
}
func findChromeExecutablePath(isEdge bool, session *clientpb.Session, cmd *cobra.Command, con *console.SliverConsoleClient) (string, error) {
func findChromeExecutablePath(isEdge bool, session *clientpb.Session, cmd *cobra.Command, con *console.SliverClient) (string, error) {
exeFlag, _ := cmd.Flags().GetString("exe")
if exeFlag != "" {
return exeFlag, nil
@@ -417,7 +416,7 @@ func isChromeProcess(executable string) bool {
return false
}
func getChromeProcess(session *clientpb.Session, cmd *cobra.Command, con *console.SliverConsoleClient) (*commonpb.Process, error) {
func getChromeProcess(session *clientpb.Session, cmd *cobra.Command, con *console.SliverClient) (*commonpb.Process, error) {
ps, err := con.Rpc.Ps(context.Background(), &sliverpb.PsReq{
Request: con.ActiveTarget.Request(cmd),
})
+5 -6
View File
@@ -27,15 +27,14 @@ import (
"text/tabwriter"
"github.com/AlecAivazis/survey/v2"
"github.com/reeflective/readline"
"github.com/spf13/cobra"
"github.com/bishopfox/sliver/client/console"
"github.com/bishopfox/sliver/client/core"
"github.com/bishopfox/sliver/client/overlord"
"github.com/reeflective/readline"
"github.com/spf13/cobra"
)
func CursedConsoleCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []string) {
func CursedConsoleCmd(cmd *cobra.Command, con *console.SliverClient, args []string) {
curse := selectCursedProcess(con)
if curse == nil {
return
@@ -56,7 +55,7 @@ func CursedConsoleCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args
startCursedConsole(curse, true, target, con)
}
func selectDebugTarget(targets []overlord.ChromeDebugTarget, con *console.SliverConsoleClient) *overlord.ChromeDebugTarget {
func selectDebugTarget(targets []overlord.ChromeDebugTarget, con *console.SliverClient) *overlord.ChromeDebugTarget {
if len(targets) < 1 {
con.PrintErrorf("No debug targets\n")
return nil
@@ -94,7 +93,7 @@ var helperHooks = []string{
"console.log = (...a) => {return a;}", // console.log
}
func startCursedConsole(curse *core.CursedProcess, helpers bool, target *overlord.ChromeDebugTarget, con *console.SliverConsoleClient) {
func startCursedConsole(curse *core.CursedProcess, helpers bool, target *overlord.ChromeDebugTarget, con *console.SliverClient) {
tmpFile, _ := os.CreateTemp("", "cursed")
shell := readline.NewShell()
shell.History.AddFromFile("cursed history", tmpFile.Name())
+12 -12
View File
@@ -21,16 +21,16 @@ package cursed
import (
"fmt"
"os"
"strings"
"time"
"github.com/spf13/cobra"
"encoding/json"
"github.com/bishopfox/sliver/client/console"
"github.com/bishopfox/sliver/client/overlord"
"github.com/spf13/cobra"
)
func CursedCookiesCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []string) {
func CursedCookiesCmd(cmd *cobra.Command, con *console.SliverClient, args []string) {
curse := selectCursedProcess(con)
if curse == nil {
return
@@ -47,24 +47,24 @@ func CursedCookiesCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args
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()
}
+5 -7
View File
@@ -21,22 +21,20 @@ package cursed
import (
"context"
"os"
"strings"
"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/overlord"
"github.com/bishopfox/sliver/protobuf/clientpb"
"github.com/bishopfox/sliver/protobuf/commonpb"
"github.com/bishopfox/sliver/protobuf/sliverpb"
"github.com/spf13/cobra"
)
// CursedChromeCmd - Execute a .NET assembly in-memory
func CursedEdgeCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []string) {
// CursedChromeCmd - Execute a .NET assembly in-memory.
func CursedEdgeCmd(cmd *cobra.Command, con *console.SliverClient, args []string) {
session := con.ActiveTarget.GetSessionInteractive()
if session == nil {
return
@@ -96,7 +94,7 @@ func CursedEdgeCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []
}
}
func avadaKedavraEdge(session *clientpb.Session, cmd *cobra.Command, con *console.SliverConsoleClient, cargs []string) *core.CursedProcess {
func avadaKedavraEdge(session *clientpb.Session, cmd *cobra.Command, con *console.SliverClient, cargs []string) *core.CursedProcess {
edgeProcess, err := getEdgeProcess(session, cmd, con)
if err != nil {
con.PrintErrorf("%s\n", err)
@@ -153,7 +151,7 @@ func isEdgeProcess(executable string) bool {
return false
}
func getEdgeProcess(session *clientpb.Session, cmd *cobra.Command, con *console.SliverConsoleClient) (*commonpb.Process, error) {
func getEdgeProcess(session *clientpb.Session, cmd *cobra.Command, con *console.SliverClient) (*commonpb.Process, error) {
ps, err := con.Rpc.Ps(context.Background(), &sliverpb.PsReq{
Request: con.ActiveTarget.Request(cmd),
})
+6 -7
View File
@@ -27,8 +27,6 @@ import (
"time"
"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/overlord"
@@ -36,9 +34,10 @@ import (
"github.com/bishopfox/sliver/protobuf/clientpb"
"github.com/bishopfox/sliver/protobuf/commonpb"
"github.com/bishopfox/sliver/protobuf/sliverpb"
"github.com/spf13/cobra"
)
func CursedElectronCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []string) {
func CursedElectronCmd(cmd *cobra.Command, con *console.SliverClient, args []string) {
session := con.ActiveTarget.GetSessionInteractive()
if session == nil {
return
@@ -68,7 +67,7 @@ func CursedElectronCmd(cmd *cobra.Command, con *console.SliverConsoleClient, arg
con.PrintInfof("Found %d debug targets, good hunting!\n", len(targets))
}
func avadaKedavraElectron(electronExe string, session *clientpb.Session, cmd *cobra.Command, con *console.SliverConsoleClient, cargs []string) *core.CursedProcess {
func avadaKedavraElectron(electronExe string, session *clientpb.Session, cmd *cobra.Command, con *console.SliverClient, cargs []string) *core.CursedProcess {
exists, err := checkElectronPath(electronExe, session, cmd, con)
if err != nil {
con.PrintErrorf("%s", err)
@@ -119,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.SliverConsoleClient) (bool, error) {
func checkElectronPath(electronExe string, session *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,
@@ -130,7 +129,7 @@ func checkElectronPath(electronExe string, session *clientpb.Session, cmd *cobra
return ls.GetExists(), nil
}
func checkElectronProcess(electronExe string, session *clientpb.Session, cmd *cobra.Command, con *console.SliverConsoleClient) (*commonpb.Process, error) {
func checkElectronProcess(electronExe string, session *clientpb.Session, cmd *cobra.Command, con *console.SliverClient) (*commonpb.Process, error) {
ps, err := con.Rpc.Ps(context.Background(), &sliverpb.PsReq{
Request: con.ActiveTarget.Request(cmd),
})
@@ -148,7 +147,7 @@ func checkElectronProcess(electronExe string, session *clientpb.Session, cmd *co
return nil, nil
}
func startCursedElectronProcess(electronExe string, session *clientpb.Session, cmd *cobra.Command, con *console.SliverConsoleClient, cargs []string) (*core.CursedProcess, error) {
func startCursedElectronProcess(electronExe string, session *clientpb.Session, cmd *cobra.Command, con *console.SliverClient, cargs []string) (*core.CursedProcess, error) {
con.PrintInfof("Starting '%s' ... ", path.Base(electronExe))
debugPort := getRemoteDebuggerPort(cmd)
args := []string{
+2 -3
View File
@@ -23,14 +23,13 @@ import (
"strconv"
"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/protobuf/sliverpb"
"github.com/spf13/cobra"
)
func CursedRmCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []string) {
func CursedRmCmd(cmd *cobra.Command, con *console.SliverClient, args []string) {
session := con.ActiveTarget.GetSessionInteractive()
if session == nil {
return
+2 -3
View File
@@ -23,13 +23,12 @@ import (
"os"
"time"
"github.com/spf13/cobra"
"github.com/bishopfox/sliver/client/console"
"github.com/bishopfox/sliver/client/overlord"
"github.com/spf13/cobra"
)
func CursedScreenshotCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []string) {
func CursedScreenshotCmd(cmd *cobra.Command, con *console.SliverClient, args []string) {
curse := selectCursedProcess(con)
if curse == nil {
return
+6 -7
View File
@@ -27,16 +27,15 @@ import (
"text/tabwriter"
"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/core"
"github.com/jedib0t/go-pretty/v6/table"
"github.com/spf13/cobra"
)
// CursedChromeCmd - Execute a .NET assembly in-memory
func CursedCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []string) {
// CursedChromeCmd - Execute a .NET assembly in-memory.
func CursedCmd(cmd *cobra.Command, con *console.SliverClient, args []string) {
// Collect existing curses from core
cursedProcesses := [][]string{}
core.CursedProcesses.Range(func(key, value interface{}) bool {
@@ -71,8 +70,8 @@ func CursedCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []stri
}
}
// selectCursedProcess - Interactively select a cursed process from a list
func selectCursedProcess(con *console.SliverConsoleClient) *core.CursedProcess {
// selectCursedProcess - Interactively select a cursed process from a list.
func selectCursedProcess(con *console.SliverClient) *core.CursedProcess {
cursedProcesses := []*core.CursedProcess{}
core.CursedProcesses.Range(func(key, value interface{}) bool {
cursedProcesses = append(cursedProcesses, value.(*core.CursedProcess))
+43
View File
@@ -0,0 +1,43 @@
package dllhijack
import (
"github.com/rsteube/carapace"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
"github.com/bishopfox/sliver/client/command/flags"
"github.com/bishopfox/sliver/client/command/generate"
"github.com/bishopfox/sliver/client/command/help"
"github.com/bishopfox/sliver/client/console"
consts "github.com/bishopfox/sliver/client/constants"
)
// Commands returns the “ command and its subcommands.
func Commands(con *console.SliverClient) []*cobra.Command {
dllhijackCmd := &cobra.Command{
Use: consts.DLLHijackStr,
Short: "Plant a DLL for a hijack scenario",
Long: help.GetHelpFor([]string{consts.DLLHijackStr}),
GroupID: consts.ExecutionHelpGroup,
Annotations: flags.RestrictTargets(consts.WindowsCmdsFilter),
Args: cobra.ExactArgs(1),
Run: func(cmd *cobra.Command, args []string) {
DllHijackCmd(cmd, con, args)
},
}
flags.Bind("", false, dllhijackCmd, func(f *pflag.FlagSet) {
f.StringP("reference-path", "r", "", "Path to the reference DLL on the remote system")
f.StringP("reference-file", "R", "", "Path to the reference DLL on the local system")
f.StringP("file", "f", "", "Local path to the DLL to plant for the hijack")
f.StringP("profile", "p", "", "Profile name to use as a base DLL")
f.Int64P("timeout", "t", flags.DefaultTimeout, "grpc timeout in seconds")
})
flags.BindFlagCompletions(dllhijackCmd, func(comp *carapace.ActionMap) {
(*comp)["reference-file"] = carapace.ActionFiles()
(*comp)["file"] = carapace.ActionFiles()
(*comp)["profile"] = generate.ProfileNameCompleter(con)
})
carapace.Gen(dllhijackCmd).PositionalCompletion(carapace.ActionValues().Usage("Path to upload the DLL to on the remote system"))
return []*cobra.Command{dllhijackCmd}
}
+1 -1
View File
@@ -34,7 +34,7 @@ import (
// dllhijack --ref-path c:\windows\system32\msasn1.dll --ref-file /tmp/ref.dll --profile dll TARGET_PATH
// DllHijackCmd -- implements the dllhijack command
func DllHijackCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []string) {
func DllHijackCmd(cmd *cobra.Command, con *console.SliverClient, args []string) {
var (
localRefData []byte
targetDLLData []byte
+59
View File
@@ -0,0 +1,59 @@
package environment
import (
"github.com/rsteube/carapace"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
"github.com/bishopfox/sliver/client/command/flags"
"github.com/bishopfox/sliver/client/command/help"
"github.com/bishopfox/sliver/client/console"
consts "github.com/bishopfox/sliver/client/constants"
)
// Commands returns the “ command and its subcommands.
func Commands(con *console.SliverClient) []*cobra.Command {
envCmd := &cobra.Command{
Use: consts.EnvStr,
Short: "List environment variables",
Long: help.GetHelpFor([]string{consts.EnvStr}),
Args: cobra.RangeArgs(0, 1),
Run: func(cmd *cobra.Command, args []string) {
EnvGetCmd(cmd, con, args)
},
GroupID: consts.InfoHelpGroup,
}
flags.Bind("", true, envCmd, func(f *pflag.FlagSet) {
f.Int64P("timeout", "t", flags.DefaultTimeout, "grpc timeout in seconds")
})
carapace.Gen(envCmd).PositionalCompletion(carapace.ActionValues().Usage("environment variable to fetch (optional)"))
envSetCmd := &cobra.Command{
Use: consts.SetStr,
Short: "Set environment variables",
Long: help.GetHelpFor([]string{consts.EnvStr, consts.SetStr}),
Args: cobra.ExactArgs(2),
Run: func(cmd *cobra.Command, args []string) {
EnvSetCmd(cmd, con, args)
},
}
envCmd.AddCommand(envSetCmd)
carapace.Gen(envSetCmd).PositionalCompletion(
carapace.ActionValues().Usage("environment variable name"),
carapace.ActionValues().Usage("value to assign"),
)
envUnsetCmd := &cobra.Command{
Use: consts.UnsetStr,
Short: "Clear environment variables",
Long: help.GetHelpFor([]string{consts.EnvStr, consts.UnsetStr}),
Args: cobra.ExactArgs(1),
Run: func(cmd *cobra.Command, args []string) {
EnvUnsetCmd(cmd, con, args)
},
}
envCmd.AddCommand(envUnsetCmd)
carapace.Gen(envUnsetCmd).PositionalCompletion(carapace.ActionValues().Usage("environment variable name"))
return []*cobra.Command{envCmd}
}
+2 -2
View File
@@ -31,7 +31,7 @@ import (
)
// EnvGetCmd - Get a remote environment variable
func EnvGetCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []string) {
func EnvGetCmd(cmd *cobra.Command, con *console.SliverClient, args []string) {
session, beacon := con.ActiveTarget.GetInteractive()
if session == nil && beacon == nil {
return
@@ -66,7 +66,7 @@ func EnvGetCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []stri
}
// PrintGetEnvInfo - Print the results of the env get command
func PrintGetEnvInfo(envInfo *sliverpb.EnvInfo, con *console.SliverConsoleClient) {
func PrintGetEnvInfo(envInfo *sliverpb.EnvInfo, con *console.SliverClient) {
if envInfo.Response != nil && envInfo.Response.Err != "" {
con.PrintErrorf("%s\n", envInfo.Response.Err)
return
+2 -2
View File
@@ -32,7 +32,7 @@ import (
)
// EnvSetCmd - Set a remote environment variable
func EnvSetCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []string) {
func EnvSetCmd(cmd *cobra.Command, con *console.SliverClient, args []string) {
session, beacon := con.ActiveTarget.GetInteractive()
if session == nil && beacon == nil {
return
@@ -72,7 +72,7 @@ func EnvSetCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []stri
}
// PrintSetEnvInfo - Print the set environment info
func PrintSetEnvInfo(name string, value string, envInfo *sliverpb.SetEnv, con *console.SliverConsoleClient) {
func PrintSetEnvInfo(name string, value string, envInfo *sliverpb.SetEnv, con *console.SliverClient) {
if envInfo.Response != nil && envInfo.Response.Err != "" {
con.PrintErrorf("%s\n", envInfo.Response.Err)
return
+2 -2
View File
@@ -31,7 +31,7 @@ import (
)
// EnvUnsetCmd - Unset a remote environment variable
func EnvUnsetCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []string) {
func EnvUnsetCmd(cmd *cobra.Command, con *console.SliverClient, args []string) {
session, beacon := con.ActiveTarget.GetInteractive()
if session == nil && beacon == nil {
return
@@ -67,7 +67,7 @@ func EnvUnsetCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []st
}
// PrintUnsetEnvInfo - Print the set environment info
func PrintUnsetEnvInfo(name string, envInfo *sliverpb.UnsetEnv, con *console.SliverConsoleClient) {
func PrintUnsetEnvInfo(name string, envInfo *sliverpb.UnsetEnv, con *console.SliverClient) {
if envInfo.Response != nil && envInfo.Response.Err != "" {
con.PrintErrorf("%s\n", envInfo.Response.Err)
return
+277
View File
@@ -0,0 +1,277 @@
package exec
import (
"github.com/bishopfox/sliver/client/command/flags"
"github.com/bishopfox/sliver/client/command/generate"
"github.com/bishopfox/sliver/client/command/help"
"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.
func Commands(con *console.SliverClient) []*cobra.Command {
executeCmd := &cobra.Command{
Use: consts.ExecuteStr,
Short: "Execute a program on the remote system",
Long: help.GetHelpFor([]string{consts.ExecuteStr}),
Args: cobra.MinimumNArgs(1),
Run: func(cmd *cobra.Command, args []string) {
ExecuteCmd(cmd, con, args)
},
GroupID: consts.ExecutionHelpGroup,
}
flags.Bind("", false, executeCmd, func(f *pflag.FlagSet) {
f.BoolP("token", "T", false, "execute command with current token (Windows only)")
f.BoolP("output", "o", false, "capture command output")
f.BoolP("save", "s", false, "save output to a file")
f.BoolP("loot", "X", false, "save output as loot")
f.BoolP("ignore-stderr", "S", false, "don't print STDERR output")
f.StringP("stdout", "O", "", "remote path to redirect STDOUT to")
f.StringP("stderr", "E", "", "remote path to redirect STDERR to")
f.StringP("name", "n", "", "name to assign loot (optional)")
f.Uint32P("ppid", "P", 0, "parent process id (optional, Windows only)")
f.BoolP("hidden", "H", false, "hide the window of the spawned process (Windows only)")
f.Int64P("timeout", "t", flags.DefaultTimeout, "grpc timeout in seconds")
})
executeCmd.Flags().ParseErrorsWhitelist.UnknownFlags = true
carapace.Gen(executeCmd).PositionalCompletion(carapace.ActionValues().Usage("command to execute (required)"))
carapace.Gen(executeCmd).PositionalAnyCompletion(carapace.ActionValues().Usage("arguments to the command (optional)"))
executeAssemblyCmd := &cobra.Command{
Use: consts.ExecuteAssemblyStr,
Short: "Loads and executes a .NET assembly in a child process (Windows Only)",
Long: help.GetHelpFor([]string{consts.ExecuteAssemblyStr}),
Args: cobra.MinimumNArgs(1),
Run: func(cmd *cobra.Command, args []string) {
ExecuteAssemblyCmd(cmd, con, args)
},
GroupID: consts.ExecutionHelpGroup,
Annotations: flags.RestrictTargets(consts.WindowsCmdsFilter),
}
flags.Bind("", false, executeAssemblyCmd, func(f *pflag.FlagSet) {
f.StringP("process", "p", "notepad.exe", "hosting process to inject into")
f.StringP("method", "m", "", "Optional method (a method is required for a .NET DLL)")
f.StringP("class", "c", "", "Optional class name (required for .NET DLL)")
f.StringP("app-domain", "d", "", "AppDomain name to create for .NET assembly. Generated randomly if not set.")
f.StringP("arch", "a", "x84", "Assembly target architecture: x86, x64, x84 (x86+x64)")
f.BoolP("in-process", "i", false, "Run in the current sliver process")
f.StringP("runtime", "r", "", "Runtime to use for running the assembly (only supported when used with --in-process)")
f.BoolP("save", "s", false, "save output to file")
f.BoolP("loot", "X", false, "save output as loot")
f.StringP("name", "n", "", "name to assign loot (optional)")
f.Uint32P("ppid", "P", 0, "parent process id (optional)")
f.StringP("process-arguments", "A", "", "arguments to pass to the hosting process")
f.BoolP("amsi-bypass", "M", false, "Bypass AMSI on Windows (only supported when used with --in-process)")
f.BoolP("etw-bypass", "E", false, "Bypass ETW on Windows (only supported when used with --in-process)")
f.Int64P("timeout", "t", flags.DefaultTimeout, "grpc timeout in seconds")
})
executeAssemblyCmd.Flags().ParseErrorsWhitelist.UnknownFlags = true
carapace.Gen(executeAssemblyCmd).PositionalCompletion(carapace.ActionFiles().Usage("path to assembly file (required)"))
carapace.Gen(executeAssemblyCmd).PositionalAnyCompletion(carapace.ActionValues().Usage("arguments to pass to the assembly entrypoint (optional)"))
executeShellcodeCmd := &cobra.Command{
Use: consts.ExecuteShellcodeStr,
Short: "Executes the given shellcode in the sliver process",
Long: help.GetHelpFor([]string{consts.ExecuteShellcodeStr}),
Args: cobra.ExactArgs(1),
Run: func(cmd *cobra.Command, args []string) {
ExecuteShellcodeCmd(cmd, con, args)
},
GroupID: consts.ExecutionHelpGroup,
}
flags.Bind("", false, executeShellcodeCmd, func(f *pflag.FlagSet) {
f.BoolP("rwx-pages", "r", false, "Use RWX permissions for memory pages")
f.Uint32P("pid", "p", 0, "Pid of process to inject into (0 means injection into ourselves)")
f.StringP("process", "n", `c:\windows\system32\notepad.exe`, "Process to inject into when running in interactive mode")
f.BoolP("interactive", "i", false, "Inject into a new process and interact with it")
f.BoolP("shikata-ga-nai", "S", false, "encode shellcode using shikata ga nai prior to execution")
f.StringP("architecture", "A", "amd64", "architecture of the shellcode: 386, amd64 (used with --shikata-ga-nai flag)")
f.Uint32P("iterations", "I", 1, "number of encoding iterations (used with --shikata-ga-nai flag)")
f.Int64P("timeout", "t", flags.DefaultTimeout, "grpc timeout in seconds")
})
flags.BindFlagCompletions(executeShellcodeCmd, func(comp *carapace.ActionMap) {
(*comp)["shikata-ga-nai"] = carapace.ActionValues("386", "amd64").Tag("shikata-ga-nai architectures")
})
carapace.Gen(executeShellcodeCmd).PositionalCompletion(carapace.ActionFiles().Usage("path to shellcode file (required)"))
sideloadCmd := &cobra.Command{
Use: consts.SideloadStr,
Short: "Load and execute a shared object (shared library/DLL) in a remote process",
Long: help.GetHelpFor([]string{consts.SideloadStr}),
Args: cobra.MinimumNArgs(1),
Run: func(cmd *cobra.Command, args []string) {
SideloadCmd(cmd, con, args)
},
GroupID: consts.ExecutionHelpGroup,
}
flags.Bind("", false, sideloadCmd, func(f *pflag.FlagSet) {
f.StringP("entry-point", "e", "", "Entrypoint for the DLL (Windows only)")
f.StringP("process", "p", `c:\windows\system32\notepad.exe`, "Path to process to host the shellcode")
f.BoolP("unicode", "w", false, "Command line is passed to unmanaged DLL function in UNICODE format. (default is ANSI)")
f.BoolP("save", "s", false, "save output to file")
f.BoolP("loot", "X", false, "save output as loot")
f.StringP("name", "n", "", "name to assign loot (optional)")
f.BoolP("keep-alive", "k", false, "don't terminate host process once the execution completes")
f.Uint32P("ppid", "P", 0, "parent process id (optional)")
f.StringP("process-arguments", "A", "", "arguments to pass to the hosting process")
f.Int64P("timeout", "t", flags.DefaultTimeout, "grpc timeout in seconds")
})
sideloadCmd.Flags().ParseErrorsWhitelist.UnknownFlags = true
carapace.Gen(sideloadCmd).PositionalCompletion(carapace.ActionFiles().Usage("path to shared library file (required)"))
carapace.Gen(sideloadCmd).PositionalAnyCompletion(carapace.ActionValues().Usage("arguments to pass to the binary (optional)"))
spawnDllCmd := &cobra.Command{
Use: consts.SpawnDllStr,
Short: "Load and execute a Reflective DLL in a remote process",
Long: help.GetHelpFor([]string{consts.SpawnDllStr}),
Args: cobra.MinimumNArgs(1),
Run: func(cmd *cobra.Command, args []string) {
SpawnDllCmd(cmd, con, args)
},
GroupID: consts.ExecutionHelpGroup,
Annotations: flags.RestrictTargets(consts.WindowsCmdsFilter),
}
flags.Bind("", false, spawnDllCmd, func(f *pflag.FlagSet) {
f.StringP("process", "p", `c:\windows\system32\notepad.exe`, "Path to process to host the shellcode")
f.StringP("export", "e", "ReflectiveLoader", "Entrypoint of the Reflective DLL")
f.BoolP("save", "s", false, "save output to file")
f.BoolP("loot", "X", false, "save output as loot")
f.StringP("name", "n", "", "name to assign loot (optional)")
f.BoolP("keep-alive", "k", false, "don't terminate host process once the execution completes")
f.UintP("ppid", "P", 0, "parent process id (optional)")
f.StringP("process-arguments", "A", "", "arguments to pass to the hosting process")
f.Int64P("timeout", "t", flags.DefaultTimeout, "grpc timeout in seconds")
})
spawnDllCmd.Flags().ParseErrorsWhitelist.UnknownFlags = true
carapace.Gen(spawnDllCmd).PositionalCompletion(carapace.ActionFiles().Usage("path to DLL file (required)"))
carapace.Gen(spawnDllCmd).PositionalAnyCompletion(carapace.ActionValues().Usage("arguments to pass to the DLL entrypoint (optional)"))
migrateCmd := &cobra.Command{
Use: consts.MigrateStr,
Short: "Migrate into a remote process",
Long: help.GetHelpFor([]string{consts.MigrateStr}),
Run: func(cmd *cobra.Command, args []string) {
MigrateCmd(cmd, con, args)
},
GroupID: consts.ExecutionHelpGroup,
Annotations: flags.RestrictTargets(consts.WindowsCmdsFilter),
}
flags.Bind("", false, migrateCmd, func(f *pflag.FlagSet) {
f.BoolP("disable-sgn", "S", true, "disable shikata ga nai shellcode encoder")
f.Uint32P("pid", "p", 0, "process id to migrate into")
f.StringP("process-name", "n", "", "name of the process to migrate into")
f.Int64P("timeout", "t", flags.DefaultTimeout, "grpc timeout in seconds")
})
carapace.Gen(migrateCmd).PositionalCompletion(carapace.ActionValues().Usage("PID of process to migrate into"))
msfCmd := &cobra.Command{
Use: consts.MsfStr,
Short: "Execute an MSF payload in the current process",
Long: help.GetHelpFor([]string{consts.MsfStr}),
Run: func(cmd *cobra.Command, args []string) {
MsfCmd(cmd, con, args)
},
GroupID: consts.ExecutionHelpGroup,
}
flags.Bind("", false, msfCmd, func(f *pflag.FlagSet) {
f.StringP("payload", "m", "meterpreter_reverse_https", "msf payload")
f.StringP("lhost", "L", "", "listen host")
f.IntP("lport", "l", 4444, "listen port")
f.StringP("encoder", "e", "", "msf encoder")
f.IntP("iterations", "i", 1, "iterations of the encoder")
f.Int64P("timeout", "t", flags.DefaultTimeout, "grpc timeout in seconds")
})
msfInjectCmd := &cobra.Command{
Use: consts.MsfInjectStr,
Short: "Inject an MSF payload into a process",
Long: help.GetHelpFor([]string{consts.MsfInjectStr}),
Run: func(cmd *cobra.Command, args []string) {
MsfInjectCmd(cmd, con, args)
},
GroupID: consts.ExecutionHelpGroup,
}
flags.Bind("", false, msfInjectCmd, func(f *pflag.FlagSet) {
f.IntP("pid", "p", -1, "pid to inject into")
f.StringP("payload", "m", "meterpreter_reverse_https", "msf payload")
f.StringP("lhost", "L", "", "listen host")
f.IntP("lport", "l", 4444, "listen port")
f.StringP("encoder", "e", "", "msf encoder")
f.IntP("iterations", "i", 1, "iterations of the encoder")
f.Int64P("timeout", "t", flags.DefaultTimeout, "grpc timeout in seconds")
})
psExecCmd := &cobra.Command{
Use: consts.PsExecStr,
Short: "Start a sliver service on a remote target",
Long: help.GetHelpFor([]string{consts.PsExecStr}),
Args: cobra.ExactArgs(1),
Run: func(cmd *cobra.Command, args []string) {
PsExecCmd(cmd, con, args)
},
GroupID: consts.ExecutionHelpGroup,
Annotations: flags.RestrictTargets(consts.WindowsCmdsFilter),
}
flags.Bind("", false, psExecCmd, func(f *pflag.FlagSet) {
f.StringP("service-name", "s", "Sliver", "name that will be used to register the service")
f.StringP("service-description", "d", "Sliver implant", "description of the service")
f.StringP("profile", "p", "", "profile to use for service binary")
f.StringP("binpath", "b", "c:\\windows\\temp", "directory to which the executable will be uploaded")
f.StringP("custom-exe", "c", "", "custom service executable to use instead of generating a new Sliver")
f.Int64P("timeout", "t", flags.DefaultTimeout, "grpc timeout in seconds")
})
flags.BindFlagCompletions(psExecCmd, func(comp *carapace.ActionMap) {
(*comp)["custom-exe"] = carapace.ActionFiles()
(*comp)["profile"] = generate.ProfileNameCompleter(con)
})
carapace.Gen(psExecCmd).PositionalCompletion(carapace.ActionValues().Usage("hostname (required)"))
sshCmd := &cobra.Command{
Use: consts.SSHStr,
Short: "Run a SSH command on a remote host",
Long: help.GetHelpFor([]string{consts.SSHStr}),
Args: cobra.MinimumNArgs(1),
Run: func(cmd *cobra.Command, args []string) {
SSHCmd(cmd, con, args)
},
GroupID: consts.ExecutionHelpGroup,
}
flags.Bind("", false, sshCmd, func(f *pflag.FlagSet) {
f.UintP("port", "p", 22, "SSH port")
f.StringP("private-key", "i", "", "path to private key file")
f.StringP("password", "P", "", "SSH user password")
f.StringP("login", "l", "", "username to use to connect")
f.BoolP("skip-loot", "s", false, "skip the prompt to use loot credentials")
f.StringP("kerberos-config", "c", "/etc/krb5.conf", "path to remote Kerberos config file")
f.StringP("kerberos-keytab", "k", "", "path to Kerberos keytab file")
f.StringP("kerberos-realm", "r", "", "Kerberos realm")
f.Int64P("timeout", "t", flags.DefaultTimeout, "grpc timeout in seconds")
})
sshCmd.Flags().ParseErrorsWhitelist.UnknownFlags = true
flags.BindFlagCompletions(sshCmd, func(comp *carapace.ActionMap) {
(*comp)["private-key"] = carapace.ActionFiles()
(*comp)["kerberos-keytab"] = carapace.ActionFiles()
})
carapace.Gen(sshCmd).PositionalCompletion(carapace.ActionValues().Usage("remote host to SSH to (required)"))
carapace.Gen(sshCmd).PositionalAnyCompletion(carapace.ActionValues().Usage("command line with arguments"))
return []*cobra.Command{executeCmd, executeAssemblyCmd, executeShellcodeCmd, sideloadCmd, spawnDllCmd, migrateCmd, msfCmd, msfInjectCmd, psExecCmd, sshCmd}
}
+6 -7
View File
@@ -25,16 +25,15 @@ import (
"strings"
"github.com/AlecAivazis/survey/v2"
"github.com/spf13/cobra"
"google.golang.org/protobuf/proto"
"github.com/bishopfox/sliver/client/console"
"github.com/bishopfox/sliver/protobuf/clientpb"
"github.com/bishopfox/sliver/protobuf/sliverpb"
"github.com/spf13/cobra"
"google.golang.org/protobuf/proto"
)
// ExecuteAssemblyCmd - Execute a .NET assembly in-memory
func ExecuteAssemblyCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []string) {
// ExecuteAssemblyCmd - Execute a .NET assembly in-memory.
func ExecuteAssemblyCmd(cmd *cobra.Command, con *console.SliverClient, args []string) {
session, beacon := con.ActiveTarget.GetInteractive()
if session == nil && beacon == nil {
return
@@ -96,7 +95,7 @@ func ExecuteAssemblyCmd(cmd *cobra.Command, con *console.SliverConsoleClient, ar
Request: con.ActiveTarget.Request(cmd),
IsDLL: isDLL,
Process: process,
Arguments: assemblyArgsStr,
Arguments: assemblyArgs,
Assembly: assemblyBytes,
Arch: arch,
Method: method,
@@ -132,7 +131,7 @@ func ExecuteAssemblyCmd(cmd *cobra.Command, con *console.SliverConsoleClient, ar
}
}
func HandleExecuteAssemblyResponse(execAssembly *sliverpb.ExecuteAssembly, assemblyPath string, hostName string, cmd *cobra.Command, con *console.SliverConsoleClient) {
func HandleExecuteAssemblyResponse(execAssembly *sliverpb.ExecuteAssembly, assemblyPath string, hostName string, cmd *cobra.Command, con *console.SliverClient) {
saveLoot, _ := cmd.Flags().GetBool("loot")
lootName, _ := cmd.Flags().GetString("name")
+8 -10
View File
@@ -26,19 +26,17 @@ import (
"log"
"os"
"golang.org/x/term"
"google.golang.org/protobuf/proto"
"github.com/spf13/cobra"
"github.com/bishopfox/sliver/client/console"
"github.com/bishopfox/sliver/client/core"
"github.com/bishopfox/sliver/protobuf/clientpb"
"github.com/bishopfox/sliver/protobuf/sliverpb"
"github.com/spf13/cobra"
"golang.org/x/term"
"google.golang.org/protobuf/proto"
)
// ExecuteShellcodeCmd - Execute shellcode in-memory
func ExecuteShellcodeCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []string) {
// ExecuteShellcodeCmd - Execute shellcode in-memory.
func ExecuteShellcodeCmd(cmd *cobra.Command, con *console.SliverClient, args []string) {
session, beacon := con.ActiveTarget.GetInteractive()
if session == nil && beacon == nil {
return
@@ -128,8 +126,8 @@ func ExecuteShellcodeCmd(cmd *cobra.Command, con *console.SliverConsoleClient, a
}
}
// PrintExecuteShellcode - Display result of shellcode execution
func PrintExecuteShellcode(task *sliverpb.Task, con *console.SliverConsoleClient) {
// PrintExecuteShellcode - Display result of shellcode execution.
func PrintExecuteShellcode(task *sliverpb.Task, con *console.SliverClient) {
if task.Response.GetErr() != "" {
con.PrintErrorf("%s\n", task.Response.GetErr())
} else {
@@ -137,7 +135,7 @@ func PrintExecuteShellcode(task *sliverpb.Task, con *console.SliverConsoleClient
}
}
func executeInteractive(cmd *cobra.Command, hostProc string, shellcode []byte, rwxPages bool, con *console.SliverConsoleClient) {
func executeInteractive(cmd *cobra.Command, hostProc string, shellcode []byte, rwxPages bool, con *console.SliverClient) {
// Check active session
session := con.ActiveTarget.GetSessionInteractive()
if session == nil {
+13 -15
View File
@@ -23,18 +23,16 @@ import (
"strings"
"time"
"google.golang.org/protobuf/proto"
"github.com/spf13/cobra"
"github.com/bishopfox/sliver/client/command/loot"
"github.com/bishopfox/sliver/client/console"
"github.com/bishopfox/sliver/protobuf/clientpb"
"github.com/bishopfox/sliver/protobuf/sliverpb"
"github.com/spf13/cobra"
"google.golang.org/protobuf/proto"
)
// ExecuteCmd - Run a command on the remote system
func ExecuteCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []string) {
// ExecuteCmd - Run a command on the remote system.
func ExecuteCmd(cmd *cobra.Command, con *console.SliverClient, args []string) {
session, beacon := con.ActiveTarget.GetInteractive()
if session == nil && beacon == nil {
return
@@ -66,7 +64,7 @@ func ExecuteCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []str
ctrl := make(chan bool)
con.SpinUntil(fmt.Sprintf("Executing %s %s ...", cmdPath, strings.Join(args, " ")), ctrl)
if token || hidden || ppid != 0 {
if session.OS != "windows" {
if (session != nil && session.OS != "windows") || (beacon != nil && beacon.OS != "windows") {
con.PrintErrorf("The token, hide window, and ppid options are not valid on %s\n", session.OS)
return
}
@@ -113,7 +111,7 @@ func ExecuteCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []str
}
}
func HandleExecuteResponse(exec *sliverpb.Execute, cmdPath string, hostName string, cmd *cobra.Command, con *console.SliverConsoleClient) {
func HandleExecuteResponse(exec *sliverpb.Execute, cmdPath string, hostName string, cmd *cobra.Command, con *console.SliverClient) {
var lootedOutput []byte
stdout, _ := cmd.Flags().GetString("stdout")
saveLoot, _ := cmd.Flags().GetBool("loot")
@@ -136,8 +134,8 @@ func HandleExecuteResponse(exec *sliverpb.Execute, cmdPath string, hostName stri
PrintExecute(exec, cmd, con)
}
// PrintExecute - Print the output of an executed command
func PrintExecute(exec *sliverpb.Execute, cmd *cobra.Command, con *console.SliverConsoleClient) {
// PrintExecute - Print the output of an executed command.
func PrintExecute(exec *sliverpb.Execute, cmd *cobra.Command, con *console.SliverClient) {
ignoreStderr, _ := cmd.Flags().GetBool("ignore-stderr")
stdout, _ := cmd.Flags().GetString("stdout")
stderr, _ := cmd.Flags().GetString("stderr")
@@ -210,7 +208,7 @@ func combineCommandOutput(exec *sliverpb.Execute, combineStdOut bool, combineStd
return []byte(outputString)
}
func LootExecute(commandOutput []byte, lootName string, sliverCmdName string, cmdName string, hostName string, con *console.SliverConsoleClient) {
func LootExecute(commandOutput []byte, lootName string, sliverCmdName string, cmdName string, hostName string, con *console.SliverClient) {
if len(commandOutput) == 0 {
con.PrintInfof("There was no output from execution, so there is nothing to loot.\n")
return
@@ -225,11 +223,11 @@ func LootExecute(commandOutput []byte, lootName string, sliverCmdName string, cm
lootName = fmt.Sprintf("[%s] %s on %s (%s)", sliverCmdName, shortCommandName, hostName, timeNow)
}
lootMessage := loot.CreateLootMessage(fileName, lootName, clientpb.FileType_TEXT, commandOutput)
lootMessage := loot.CreateLootMessage(con.ActiveTarget.GetHostUUID(), fileName, lootName, clientpb.FileType_TEXT, commandOutput)
loot.SendLootMessage(lootMessage, con)
}
func PrintExecutionOutput(executionOutput string, saveOutput bool, commandName string, hostName string, con *console.SliverConsoleClient) {
func PrintExecutionOutput(executionOutput string, saveOutput bool, commandName string, hostName string, con *console.SliverClient) {
con.PrintInfof("Output:\n%s", executionOutput)
if saveOutput {
@@ -237,7 +235,7 @@ func PrintExecutionOutput(executionOutput string, saveOutput bool, commandName s
}
}
func SaveExecutionOutput(executionOutput string, commandName string, hostName string, con *console.SliverConsoleClient) {
func SaveExecutionOutput(executionOutput string, commandName string, hostName string, con *console.SliverClient) {
var outFilePath *os.File
var err error
@@ -258,7 +256,7 @@ func SaveExecutionOutput(executionOutput string, commandName string, hostName st
}
if outFilePath != nil {
outFilePath.Write([]byte(executionOutput))
outFilePath.WriteString(executionOutput)
con.PrintInfof("Output saved to %s\n", outFilePath.Name())
}
}
+64 -38
View File
@@ -21,19 +21,19 @@ package exec
import (
"context"
"fmt"
"strings"
"github.com/spf13/cobra"
"google.golang.org/protobuf/proto"
"github.com/bishopfox/sliver/client/console"
consts "github.com/bishopfox/sliver/client/constants"
"github.com/bishopfox/sliver/protobuf/clientpb"
"github.com/bishopfox/sliver/protobuf/sliverpb"
)
// MigrateCmd - Windows only, inject an implant into another process
func MigrateCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []string) {
session := con.ActiveTarget.GetSession()
if session == nil {
func MigrateCmd(cmd *cobra.Command, con *console.SliverClient, args []string) {
session, beacon := con.ActiveTarget.GetInteractive()
if session == nil && beacon == nil {
return
}
@@ -43,44 +43,47 @@ func MigrateCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []str
con.PrintErrorf("Error: Must specify either a PID or process name\n")
return
}
if procName != "" {
procCtrl := make(chan bool)
con.SpinUntil(fmt.Sprintf("Searching for %s ...", procName), procCtrl)
proc, err := con.Rpc.Ps(context.Background(), &sliverpb.PsReq{
Request: con.ActiveTarget.Request(cmd),
})
if err != nil {
con.PrintErrorf("Error: %v\n", err)
return
}
procCtrl <- true
<-procCtrl
for _, p := range proc.GetProcesses() {
if strings.EqualFold(p.Executable, procName) {
pid = uint32(p.Pid)
break
}
}
if pid == 0 {
con.PrintErrorf("Error: Could not find process %s\n", procName)
return
}
con.PrintInfof("Process name specified, overriding PID with %d\n", pid)
var config *clientpb.ImplantConfig
var implantName string
if session != nil {
config = con.GetActiveSessionConfig()
implantName = session.Name
} else {
config = con.GetActiveBeaconConfig()
implantName = beacon.Name
}
config := con.GetActiveSessionConfig()
encoder := clientpb.ShellcodeEncoder_SHIKATA_GA_NAI
if disableSgn, _ := cmd.Flags().GetBool("disable-sgn"); disableSgn {
encoder = clientpb.ShellcodeEncoder_NONE
}
ctrl := make(chan bool)
con.SpinUntil(fmt.Sprintf("Migrating into %d ...", pid), ctrl)
if pid != 0 {
con.SpinUntil(fmt.Sprintf("Migrating into %d ...", pid), ctrl)
} else {
con.SpinUntil(fmt.Sprintf("Migrating into %s...", procName), ctrl)
}
/* If the HTTP C2 Config name is not defined, then put in the default value
This will have no effect on implants that do not use HTTP C2
Also this should be overridden when the build info is pulled from the
database, but if there is no build info and we have to create the build
from scratch, we need to have something in here.
*/
if config.HTTPC2ConfigName == "" {
config.HTTPC2ConfigName = consts.DefaultC2Profile
}
migrate, err := con.Rpc.Migrate(context.Background(), &clientpb.MigrateReq{
Pid: pid,
Config: config,
Request: con.ActiveTarget.Request(cmd),
Encoder: encoder,
Pid: pid,
Config: config,
Request: con.ActiveTarget.Request(cmd),
Encoder: encoder,
Name: implantName,
ProcName: procName,
})
ctrl <- true
<-ctrl
@@ -88,9 +91,32 @@ func MigrateCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []str
con.PrintErrorf("Error: %v", err)
return
}
if !migrate.Success {
con.PrintErrorf("%s\n", migrate.GetResponse().GetErr())
return
if migrate.Response != nil && migrate.Response.Async {
con.AddBeaconCallback(migrate.Response.TaskID, func(task *clientpb.BeaconTask) {
err = proto.Unmarshal(task.Response, migrate)
if err != nil {
con.PrintErrorf("Failed to decode response %s\n", err)
}
if !migrate.Success {
if migrate.GetResponse().GetErr() != "" {
con.PrintErrorf("%s\n", migrate.GetResponse().GetErr())
} else {
con.PrintErrorf("Could not migrate into a new process. Check the PID or name.")
}
return
}
con.PrintInfof("Successfully migrated to %d\n", migrate.Pid)
})
con.PrintAsyncResponse(migrate.Response)
} else {
if !migrate.Success {
if migrate.GetResponse().GetErr() != "" {
con.PrintErrorf("%s\n", migrate.GetResponse().GetErr())
} else {
con.PrintErrorf("Could not migrate into a new process. Check the PID or name.")
}
return
}
con.PrintInfof("Successfully migrated to %d\n", migrate.Pid)
}
con.PrintInfof("Successfully migrated to %d\n", pid)
}
+7 -9
View File
@@ -22,18 +22,16 @@ import (
"context"
"fmt"
"google.golang.org/protobuf/proto"
"github.com/spf13/cobra"
"github.com/bishopfox/sliver/client/console"
consts "github.com/bishopfox/sliver/client/constants"
"github.com/bishopfox/sliver/protobuf/clientpb"
"github.com/bishopfox/sliver/protobuf/sliverpb"
"github.com/spf13/cobra"
"google.golang.org/protobuf/proto"
)
// MsfInjectCmd - Inject a metasploit payload into a remote process
func MsfInjectCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []string) {
// MsfInjectCmd - Inject a metasploit payload into a remote process.
func MsfInjectCmd(cmd *cobra.Command, con *console.SliverClient, args []string) {
session, beacon := con.ActiveTarget.GetInteractive()
if session == nil && beacon == nil {
return
@@ -51,7 +49,7 @@ func MsfInjectCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []s
return
}
if pid == -1 {
con.PrintErrorf("Invalid pid '%s', see `help %s`\n", lhost, consts.MsfInjectStr)
con.PrintErrorf("Invalid pid '%d', see `help %s`\n", pid, consts.MsfInjectStr)
return
}
var goos string
@@ -99,8 +97,8 @@ func MsfInjectCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []s
}
}
// PrintMsfRemote - Print the results of the remote injection attempt
func PrintMsfRemote(msfRemote *sliverpb.Task, con *console.SliverConsoleClient) {
// PrintMsfRemote - Print the results of the remote injection attempt.
func PrintMsfRemote(msfRemote *sliverpb.Task, con *console.SliverClient) {
if msfRemote.Response == nil {
con.PrintErrorf("Empty response from msf payload injection task")
return
+4 -6
View File
@@ -22,17 +22,15 @@ import (
"context"
"fmt"
"google.golang.org/protobuf/proto"
"github.com/spf13/cobra"
"github.com/bishopfox/sliver/client/console"
consts "github.com/bishopfox/sliver/client/constants"
"github.com/bishopfox/sliver/protobuf/clientpb"
"github.com/spf13/cobra"
"google.golang.org/protobuf/proto"
)
// MsfCmd - Inject a metasploit payload into the current remote process
func MsfCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []string) {
// MsfCmd - Inject a metasploit payload into the current remote process.
func MsfCmd(cmd *cobra.Command, con *console.SliverClient, args []string) {
session, beacon := con.ActiveTarget.GetInteractive()
if session == nil && beacon == nil {
return
+3 -5
View File
@@ -21,14 +21,11 @@ package exec
import (
"context"
"fmt"
insecureRand "math/rand"
"os"
"strings"
"time"
insecureRand "math/rand"
"github.com/spf13/cobra"
"github.com/bishopfox/sliver/client/command/generate"
"github.com/bishopfox/sliver/client/command/settings"
"github.com/bishopfox/sliver/client/console"
@@ -36,10 +33,11 @@ import (
"github.com/bishopfox/sliver/protobuf/commonpb"
"github.com/bishopfox/sliver/protobuf/sliverpb"
"github.com/bishopfox/sliver/util/encoders"
"github.com/spf13/cobra"
)
// PsExecCmd - psexec command implementation.
func PsExecCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []string) {
func PsExecCmd(cmd *cobra.Command, con *console.SliverClient, args []string) {
session := con.ActiveTarget.GetSessionInteractive()
if session == nil {
return
+15 -9
View File
@@ -25,24 +25,30 @@ import (
"path/filepath"
"strings"
"google.golang.org/protobuf/proto"
"github.com/spf13/cobra"
"github.com/bishopfox/sliver/client/console"
"github.com/bishopfox/sliver/protobuf/clientpb"
"github.com/bishopfox/sliver/protobuf/sliverpb"
"github.com/spf13/cobra"
"google.golang.org/protobuf/proto"
)
// SideloadCmd - Sideload a shared library on the remote system
func SideloadCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []string) {
// SideloadCmd - Sideload a shared library on the remote system.
func SideloadCmd(cmd *cobra.Command, con *console.SliverClient, args []string) {
session, beacon := con.ActiveTarget.GetInteractive()
if session == nil && beacon == nil {
return
}
if len(args) < 1 {
cmd.Usage()
return
}
binPath := args[0]
binArgs := strings.Join(args[1:], " ")
var binArgs []string
if len(args) > 1 {
binArgs = args[1:]
}
entryPoint, _ := cmd.Flags().GetString("entry-point")
processName, _ := cmd.Flags().GetString("process")
@@ -59,7 +65,7 @@ func SideloadCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []st
processArgs := strings.Split(processArgsStr, " ")
isDLL := (filepath.Ext(binPath) == ".dll")
ctrl := make(chan bool)
con.SpinUntil(fmt.Sprintf("Sideloading %s ...", binPath), ctrl)
con.SpinUntil(fmt.Sprintf("Sideloading %s %v...", binPath, binArgs), ctrl)
sideload, err := con.Rpc.Sideload(context.Background(), &sliverpb.SideloadReq{
Request: con.ActiveTarget.Request(cmd),
Args: binArgs,
@@ -96,7 +102,7 @@ func SideloadCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []st
}
}
func HandleSideloadResponse(sideload *sliverpb.Sideload, binPath string, hostName string, cmd *cobra.Command, con *console.SliverConsoleClient) {
func HandleSideloadResponse(sideload *sliverpb.Sideload, binPath string, hostName string, cmd *cobra.Command, con *console.SliverClient) {
saveLoot, _ := cmd.Flags().GetBool("loot")
lootName, _ := cmd.Flags().GetString("name")
+9 -9
View File
@@ -22,25 +22,25 @@ import (
"context"
"fmt"
"os"
"strings"
"google.golang.org/protobuf/proto"
"github.com/spf13/cobra"
"github.com/bishopfox/sliver/client/console"
"github.com/bishopfox/sliver/protobuf/clientpb"
"github.com/bishopfox/sliver/protobuf/sliverpb"
"github.com/spf13/cobra"
"google.golang.org/protobuf/proto"
)
// SpawnDllCmd - Spawn execution of a DLL on the remote system
func SpawnDllCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []string) {
// SpawnDllCmd - Spawn execution of a DLL on the remote system.
func SpawnDllCmd(cmd *cobra.Command, con *console.SliverClient, args []string) {
session, beacon := con.ActiveTarget.GetInteractive()
if session == nil && beacon == nil {
return
}
binPath := args[0]
dllArgs := strings.Join(args[1:], " ")
var dllArgs []string
if len(args) > 1 {
dllArgs = args[1:]
}
processName, _ := cmd.Flags().GetString("process")
exportName, _ := cmd.Flags().GetString("export")
@@ -85,7 +85,7 @@ func SpawnDllCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []st
}
}
func HandleSpawnDLLResponse(spawndll *sliverpb.SpawnDll, binPath string, hostName string, cmd *cobra.Command, con *console.SliverConsoleClient) {
func HandleSpawnDLLResponse(spawndll *sliverpb.SpawnDll, binPath string, hostName string, cmd *cobra.Command, con *console.SliverClient) {
saveLoot, _ := cmd.Flags().GetBool("loot")
lootName, _ := cmd.Flags().GetString("name")
+7 -8
View File
@@ -24,16 +24,15 @@ import (
"strings"
"github.com/AlecAivazis/survey/v2"
"github.com/spf13/cobra"
"google.golang.org/protobuf/proto"
"github.com/bishopfox/sliver/client/console"
"github.com/bishopfox/sliver/protobuf/clientpb"
"github.com/bishopfox/sliver/protobuf/sliverpb"
"github.com/spf13/cobra"
"google.golang.org/protobuf/proto"
)
// SSHCmd - A built-in SSH client command for the remote system (doesn't shell out)
func SSHCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []string) {
// SSHCmd - A built-in SSH client command for the remote system (doesn't shell out).
func SSHCmd(cmd *cobra.Command, con *console.SliverClient, args []string) {
var (
privKey []byte
err error
@@ -120,8 +119,8 @@ func SSHCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []string)
}
}
// PrintSSHCmd - Print the ssh command response
func PrintSSHCmd(sshCmd *sliverpb.SSHCommand, con *console.SliverConsoleClient) {
// PrintSSHCmd - Print the ssh command response.
func PrintSSHCmd(sshCmd *sliverpb.SSHCommand, con *console.SliverClient) {
if sshCmd.Response != nil && sshCmd.Response.Err != "" {
con.PrintErrorf("Error: %s\n", sshCmd.Response.Err)
if sshCmd.StdErr != "" {
@@ -139,7 +138,7 @@ func PrintSSHCmd(sshCmd *sliverpb.SSHCommand, con *console.SliverConsoleClient)
}
}
func tryCredsFromLoot(con *console.SliverConsoleClient) (string, string, []byte) {
func tryCredsFromLoot(con *console.SliverClient) (string, string, []byte) {
var (
username string
password string
+15 -2
View File
@@ -25,12 +25,13 @@ import (
"github.com/AlecAivazis/survey/v2"
"github.com/bishopfox/sliver/client/console"
"github.com/bishopfox/sliver/client/constants"
"github.com/bishopfox/sliver/protobuf/commonpb"
"github.com/spf13/cobra"
)
// ExitCmd - Exit the console
func ExitCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []string) {
// ExitCmd - Exit the console.
func ExitCmd(cmd *cobra.Command, con *console.SliverClient, args []string) {
fmt.Println("Exiting...")
if con.IsServer {
sessions, err := con.Rpc.GetSessions(context.Background(), &commonpb.Empty{})
@@ -53,3 +54,15 @@ func ExitCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []string
}
os.Exit(0)
}
// Commands returns the `exit` command.
func Command(con *console.SliverClient) []*cobra.Command {
return []*cobra.Command{{
Use: "exit",
Short: "Exit the program",
Run: func(cmd *cobra.Command, args []string) {
ExitCmd(cmd, con, args)
},
GroupID: constants.GenericHelpGroup,
}}
}
+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
}
+89
View File
@@ -0,0 +1,89 @@
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 '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.GenericHelpGroup,
Run: func(cmd *cobra.Command, _ []string) {
ExtensionsCmd(cmd, con)
},
}
extensionLoadCmd := &cobra.Command{
Use: consts.LoadStr,
Short: "Temporarily load an extension from a local directory",
Long: help.GetHelpFor([]string{consts.ExtensionsStr, consts.LoadStr}),
Run: func(cmd *cobra.Command, args []string) {
ExtensionLoadCmd(cmd, con, args)
},
}
extensionCmd.AddCommand(extensionLoadCmd)
carapace.Gen(extensionLoadCmd).PositionalCompletion(carapace.ActionDirectories().Usage("path to the extension directory"))
extensionInstallCmd := &cobra.Command{
Use: consts.InstallStr,
Short: "Install an extension from a local directory or .tar.gz file",
Long: help.GetHelpFor([]string{consts.ExtensionsStr, consts.InstallStr}),
Args: cobra.ExactArgs(1),
Run: func(cmd *cobra.Command, args []string) {
ExtensionsInstallCmd(cmd, con, args)
},
}
extensionCmd.AddCommand(extensionInstallCmd)
carapace.Gen(extensionInstallCmd).PositionalCompletion(carapace.ActionFiles().Usage("path to the extension .tar.gz or directory"))
extensionRmCmd := &cobra.Command{
Use: consts.RmStr,
Short: "Remove an installed extension",
Args: cobra.ExactArgs(1),
Long: help.GetHelpFor([]string{consts.ExtensionsStr, consts.RmStr}),
Run: func(cmd *cobra.Command, args []string) {
ExtensionsRemoveCmd(cmd, con, args)
},
}
extensionCmd.AddCommand(extensionRmCmd)
carapace.Gen(extensionRmCmd).PositionalCompletion(ExtensionsCommandNameCompleter(con).Usage("the command name of the extension to remove"))
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}
}
+79 -23
View File
@@ -22,29 +22,29 @@ import (
"encoding/json"
"fmt"
"os"
"path/filepath"
"strings"
"github.com/jedib0t/go-pretty/v6/table"
"github.com/jedib0t/go-pretty/v6/text"
"github.com/rsteube/carapace"
"github.com/spf13/cobra"
"github.com/bishopfox/sliver/client/assets"
"github.com/bishopfox/sliver/client/command/settings"
"github.com/bishopfox/sliver/client/console"
"github.com/jedib0t/go-pretty/v6/table"
"github.com/jedib0t/go-pretty/v6/text"
"github.com/rsteube/carapace"
"github.com/spf13/cobra"
)
// ExtensionsCmd - List information about installed extensions
func ExtensionsCmd(cmd *cobra.Command, con *console.SliverConsoleClient) {
if 0 < len(getInstalledManifests()) {
// ExtensionsCmd - List information about installed extensions.
func ExtensionsCmd(cmd *cobra.Command, con *console.SliverClient) {
if len(GetAllExtensionManifests()) > 0 {
PrintExtensions(con)
} else {
con.PrintInfof("No extensions installed, use the 'armory' command to automatically install some\n")
}
}
// PrintExtensions - Print a list of loaded extensions
func PrintExtensions(con *console.SliverConsoleClient) {
// PrintExtensions - Print a list of loaded extensions.
func PrintExtensions(con *console.SliverClient) {
tw := table.NewWriter()
tw.SetStyle(settings.GetTableStyle(con))
tw.AppendHeader(table.Row{
@@ -66,25 +66,31 @@ func PrintExtensions(con *console.SliverConsoleClient) {
installedManifests := getInstalledManifests()
for _, extension := range loadedExtensions {
//for _, extension := range extensionm.ExtCommand {
installed := ""
if _, ok := installedManifests[extension.CommandName]; 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.Name,
extension.Manifest.Name,
extension.CommandName,
strings.Join(extensionPlatforms(extension), ",\n"),
extension.Version,
extension.Manifest.Version,
installed,
extension.ExtensionAuthor,
extension.OriginalAuthor,
extension.RepoURL,
extension.Manifest.ExtensionAuthor,
extension.Manifest.OriginalAuthor,
extension.Manifest.RepoURL,
})
//}
}
con.Println(tw.Render())
}
func extensionPlatforms(extension *ExtensionManifest) []string {
func extensionPlatforms(extension *ExtCommand) []string {
platforms := map[string]string{}
for _, entry := range extension.Files {
platforms[fmt.Sprintf("%s/%s", entry.OS, entry.Arch)] = ""
@@ -96,6 +102,9 @@ func extensionPlatforms(extension *ExtensionManifest) []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{}
@@ -109,17 +118,54 @@ func getInstalledManifests() map[string]*ExtensionManifest {
if err != nil {
continue
}
installedManifests[manifest.CommandName] = manifest
manifest.RootPath = filepath.Dir(manifestPath)
installedManifests[manifest.Name] = manifest
}
return installedManifests
}
// ExtensionsCommandNameCompleter - Completer for installed extensions command names
func ExtensionsCommandNameCompleter(con *console.SliverConsoleClient) carapace.Action {
// 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 {
installedManifests := getInstalledManifests()
//installedManifests := getInstalledManifests()
results := []string{}
for _, manifest := range installedManifests {
for _, manifest := range loadedExtensions {
results = append(results, manifest.CommandName)
results = append(results, manifest.Help)
}
@@ -127,3 +173,13 @@ func ExtensionsCommandNameCompleter(con *console.SliverConsoleClient) carapace.A
return carapace.ActionValuesDescribed(results...).Tag("extension commands")
})
}
func ManifestCompleter() carapace.Action {
return carapace.ActionCallback(func(c carapace.Context) carapace.Action {
results := []string{}
for k := range loadedManifests {
results = append(results, k)
}
return carapace.ActionValues(results...).Tag("extensions")
})
}
+150 -75
View File
@@ -1,5 +1,10 @@
package extensions
import (
"encoding/json"
"testing"
)
/*
Sliver Implant Framework
Copyright (C) 2021 Bishop Fox
@@ -18,26 +23,25 @@ package extensions
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import (
"encoding/json"
"testing"
)
const (
sample1 = `{
"name": "test1",
"command_name": "test1",
"version": "1.0.0",
"extension_author": "test",
"original_author": "test",
"repo_url": "https://example.com/",
"help": "some help",
"files": [
{
"os": "windows",
"arch": "amd64",
"path": "foo/test1.dll"
}
"commands":[
{
"command_name": "test1",
"help": "some help",
"files": [
{
"os": "windows",
"arch": "amd64",
"path": "foo/test1.dll"
}
]
}
]
}`
@@ -53,6 +57,60 @@ const (
}
]
}`
sample3 = `{
"name": "test3",
"version": "1.0.0",
"extension_author": "test",
"original_author": "test",
"repo_url": "https://example.com/",
"commands": [
{
"command_name": "test3",
"help": "some help",
"files": [
{
"os": "windows",
"arch": "amd64",
"path": "foo/test1.dll"
}
]
}
]
}`
multicmd = `{
"name": "example-multientry",
"version": "0.0.0",
"extension_author": "cs",
"original_author": "cs",
"repo_url": "no",
"commands": [
{
"command_name": "startw",
"help": "startw",
"entrypoint": "StartW",
"files": [
{
"os": "windows",
"arch": "amd64",
"path": "ex.dll"
}
]
},
{
"command_name": "Test2",
"help": "startw",
"entrypoint": "Test2",
"files": [
{
"os": "windows",
"arch": "amd64",
"path": "ex.dll"
}
]
}
]
}`
)
func TestParseExtensionManifest(t *testing.T) {
@@ -63,9 +121,7 @@ func TestParseExtensionManifest(t *testing.T) {
if extManifest.Name != "test1" {
t.Errorf("Expected extension name 'test1', got '%s'", extManifest.Name)
}
if extManifest.CommandName != "test1" {
t.Errorf("Expected extension command name 'test1', got '%s'", extManifest.CommandName)
}
if extManifest.Version != "1.0.0" {
t.Errorf("Expected extension version '1.0.0', got '%s'", extManifest.Version)
}
@@ -78,67 +134,86 @@ func TestParseExtensionManifest(t *testing.T) {
if extManifest.RepoURL != "https://example.com/" {
t.Errorf("Expected repo URL 'https://example.com/', got '%s'", extManifest.RepoURL)
}
if extManifest.Help != "some help" {
t.Errorf("Expected help 'some help', got '%s'", extManifest.Help)
}
if len(extManifest.Files) != 1 {
t.Errorf("Expected 1 file, got %d", len(extManifest.Files))
}
if extManifest.Files[0].OS != "windows" {
t.Errorf("Expected OS 'windows', got '%s'", extManifest.Files[0].OS)
}
if extManifest.Files[0].Arch != "amd64" {
t.Errorf("Expected Arch 'amd64', got '%s'", extManifest.Files[0].Arch)
}
if extManifest.Files[0].Path != "/foo/test1.dll" {
t.Errorf("Expected path '/foo/test1.dll', got '%s'", extManifest.Files[0].Path)
for _, extCmd := range extManifest.ExtCommand { //should only be a single manfiest here, so should pass
if extCmd.CommandName != "test1" {
t.Errorf("Expected extension command name 'test1', got '%s'", extCmd.CommandName)
}
if extCmd.Help != "some help" {
t.Errorf("Expected help 'some help', got '%s'", extCmd.Help)
}
if len(extCmd.Files) != 1 {
t.Errorf("Expected 1 file, got %d", len(extCmd.Files))
}
if extCmd.Files[0].OS != "windows" {
t.Errorf("Expected OS 'windows', got '%s'", extCmd.Files[0].OS)
}
if extCmd.Files[0].Arch != "amd64" {
t.Errorf("Expected Arch 'amd64', got '%s'", extCmd.Files[0].Arch)
}
if extCmd.Files[0].Path != "/foo/test1.dll" {
t.Errorf("Expected path '/foo/test1.dll', got '%s'", extCmd.Files[0].Path)
}
}
extManifest2, err := ParseExtensionManifest([]byte(sample2))
mextManifest2, err := ParseExtensionManifest([]byte(sample2)) //checking old manifests work good too
if err != nil {
t.Fatalf("Error parsing extension manifest (2): %s", err)
}
if extManifest2.Name != "test2" {
t.Errorf("Expected extension name 'test2', got '%s'", extManifest2.Name)
if mextManifest2.Name != "test2" {
t.Errorf("Expected extension name 'test2', got '%s'", mextManifest2.Name)
}
if extManifest2.CommandName != "test2" {
t.Errorf("Expected extension command name 'test2', got '%s'", extManifest2.CommandName)
}
if extManifest2.Help != "some help" {
t.Errorf("Expected help 'some help', got '%s'", extManifest2.Help)
}
if len(extManifest2.Files) != 1 {
t.Errorf("Expected 1 file, got %d", len(extManifest2.Files))
}
if extManifest2.Files[0].OS != "windows" {
t.Errorf("Expected OS 'windows', got '%s'", extManifest2.Files[0].OS)
}
if extManifest2.Files[0].Arch != "amd64" {
t.Errorf("Expected Arch 'amd64', got '%s'", extManifest2.Files[0].Arch)
}
if extManifest2.Files[0].Path != "/foo/test1.dll" {
t.Errorf("Expected path '/foo/test1.dll', got '%s'", extManifest2.Files[0].Path)
for _, extManifest2 := range mextManifest2.ExtCommand {
if extManifest2.CommandName != "test2" {
t.Errorf("Expected extension command name 'test2', got '%s'", extManifest2.CommandName)
}
if extManifest2.Help != "some help" {
t.Errorf("Expected help 'some help', got '%s'", extManifest2.Help)
}
if len(extManifest2.Files) != 1 {
t.Errorf("Expected 1 file, got %d", len(extManifest2.Files))
}
if extManifest2.Files[0].OS != "windows" {
t.Errorf("Expected OS 'windows', got '%s'", extManifest2.Files[0].OS)
}
if extManifest2.Files[0].Arch != "amd64" {
t.Errorf("Expected Arch 'amd64', got '%s'", extManifest2.Files[0].Arch)
}
if extManifest2.Files[0].Path != "/foo/test1.dll" {
t.Errorf("Expected path '/foo/test1.dll', got '%s'", extManifest2.Files[0].Path)
}
}
}
const (
sample3 = `{
"name": "test3",
"command_name": "test3",
"version": "1.0.0",
"extension_author": "test",
"original_author": "test",
"repo_url": "https://example.com/",
"help": "some help",
"files": [
{
"os": "windows",
"arch": "amd64",
"path": "foo/test1.dll"
}
]
}`
)
func TestParseMultipleCmdManifest(t *testing.T) {
mextManifest, err := ParseExtensionManifest([]byte(multicmd))
if err != nil {
t.Errorf("error parsing manifest: %s", err)
}
if mextManifest.Name != "example-multientry" {
t.Errorf("expected name example-multientry, got %s", mextManifest.Name)
}
if mextManifest.ExtCommand[0].CommandName != "startw" {
t.Errorf("expected commandname startw, got %s", mextManifest.ExtCommand[0].CommandName)
}
if mextManifest.ExtCommand[1].CommandName != "Test2" {
t.Errorf("expected commandname Test2, got %s", mextManifest.ExtCommand[1].CommandName)
}
if mextManifest.ExtCommand[0].Entrypoint != "StartW" {
t.Errorf("expected entrypoint StartW, got %s", mextManifest.ExtCommand[0].Entrypoint)
}
if mextManifest.ExtCommand[1].Entrypoint != "Test2" {
t.Errorf("expected entrypoint Test2, got %s", mextManifest.ExtCommand[1].Entrypoint)
}
if mextManifest.ExtCommand[0].Files[0].Path != "/ex.dll" { //path cleaning adds a root path here? I am not sure if this should be a bug or not... works fine in prod
t.Errorf("expected path ex.dll, got %s", mextManifest.ExtCommand[0].Files[0].Path)
}
if mextManifest.ExtCommand[1].Files[0].Path != "/ex.dll" { //path cleaning adds a root path here? I am not sure if this should be a bug or not... works fine in prod
t.Errorf("expected path ex.dll, got %s", mextManifest.ExtCommand[0].Files[0].Path)
}
//maybe some more? args?
}
func TestParseExtensionManifestErrors(t *testing.T) {
sample3, err := ParseExtensionManifest([]byte(sample3))
@@ -155,7 +230,7 @@ func TestParseExtensionManifestErrors(t *testing.T) {
}
missingCmdName := (*sample3)
missingCmdName.CommandName = ""
missingCmdName.ExtCommand[0].CommandName = ""
data, _ = json.Marshal(missingCmdName)
_, err = ParseExtensionManifest(data)
if err == nil {
@@ -163,7 +238,7 @@ func TestParseExtensionManifestErrors(t *testing.T) {
}
missingHelp := (*sample3)
missingHelp.Help = ""
missingHelp.ExtCommand[0].Help = ""
data, _ = json.Marshal(missingHelp)
_, err = ParseExtensionManifest(data)
if err == nil {
@@ -171,7 +246,7 @@ func TestParseExtensionManifestErrors(t *testing.T) {
}
missingFiles := (*sample3)
missingFiles.Files = []*extensionFile{}
missingFiles.ExtCommand[0].Files = []*extensionFile{}
data, _ = json.Marshal(missingFiles)
_, err = ParseExtensionManifest(data)
if err == nil {
@@ -179,7 +254,7 @@ func TestParseExtensionManifestErrors(t *testing.T) {
}
missingFileOS := (*sample3)
missingFileOS.Files = []*extensionFile{
missingFileOS.ExtCommand[0].Files = []*extensionFile{
{
OS: "",
Arch: "amd64",
@@ -193,7 +268,7 @@ func TestParseExtensionManifestErrors(t *testing.T) {
}
missingFileArch := (*sample3)
missingFileArch.Files = []*extensionFile{
missingFileArch.ExtCommand[0].Files = []*extensionFile{
{
OS: "windows",
Arch: "",
@@ -207,7 +282,7 @@ func TestParseExtensionManifestErrors(t *testing.T) {
}
missingFilePath := (*sample3)
missingFilePath.Files = []*extensionFile{
missingFilePath.ExtCommand[0].Files = []*extensionFile{
{
OS: "windows",
Arch: "amd64",
@@ -228,7 +303,7 @@ func TestParseExtensionManifestErrors(t *testing.T) {
}
for _, invalidPath := range invalidPaths {
missingFilePath2 := (*sample3)
missingFilePath2.Files = []*extensionFile{
missingFilePath2.ExtCommand[0].Files = []*extensionFile{
{
OS: "windows",
Arch: "amd64",
+80 -87
View File
@@ -22,135 +22,128 @@ import (
"fmt"
"os"
"path/filepath"
"strings"
"github.com/AlecAivazis/survey/v2"
"github.com/spf13/cobra"
"github.com/bishopfox/sliver/client/assets"
"github.com/bishopfox/sliver/client/console"
"github.com/bishopfox/sliver/util"
"github.com/spf13/cobra"
)
// ExtensionsInstallCmd - Install an extension
func ExtensionsInstallCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []string) {
// ExtensionsInstallCmd - Install an extension.
func ExtensionsInstallCmd(cmd *cobra.Command, con *console.SliverClient, args []string) {
extLocalPath := args[0]
fi, err := os.Stat(extLocalPath)
_, err := os.Stat(extLocalPath)
if os.IsNotExist(err) {
con.PrintErrorf("Extension path '%s' does not exist", extLocalPath)
return
}
if !fi.IsDir() {
InstallFromFilePath(extLocalPath, false, con)
} else {
installFromDir(extLocalPath, con)
}
InstallFromDir(extLocalPath, true, con, strings.HasSuffix(extLocalPath, ".tar.gz"))
}
// Install an extension from a directory
func installFromDir(extLocalPath string, con *console.SliverConsoleClient) {
manifestData, err := os.ReadFile(filepath.Join(extLocalPath, ManifestFileName))
// 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
if isGz {
manifestData, err = util.ReadFileFromTarGz(extLocalPath, fmt.Sprintf("./%s", ManifestFileName))
} else {
manifestData, err = os.ReadFile(filepath.Join(extLocalPath, ManifestFileName))
}
if err != nil {
con.PrintErrorf("Error reading %s: %s", ManifestFileName, err)
return
}
manifest, err := ParseExtensionManifest(manifestData)
manifestF, err := ParseExtensionManifest(manifestData)
if err != nil {
con.PrintErrorf("Error parsing %s: %s", ManifestFileName, err)
return
}
installPath := filepath.Join(assets.GetExtensionsDir(), filepath.Base(manifest.CommandName))
if _, err := os.Stat(installPath); !os.IsNotExist(err) {
con.PrintInfof("Extension '%s' already exists", manifest.CommandName)
confirm := false
prompt := &survey.Confirm{Message: "Overwrite current install?"}
survey.AskOne(prompt, &confirm)
if !confirm {
return
}
forceRemoveAll(installPath)
// 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
}
con.PrintInfof("Installing extension '%s' (%s) ... ", manifest.CommandName, manifest.Version)
err = os.MkdirAll(installPath, 0o700)
if err != nil {
con.PrintErrorf("Error creating extension directory: %s\n", err)
return
}
err = os.WriteFile(filepath.Join(installPath, ManifestFileName), manifestData, 0o600)
if err != nil {
con.PrintErrorf("Failed to write %s: %s\n", ManifestFileName, err)
forceRemoveAll(installPath)
return
}
for _, manifestFile := range manifest.Files {
if manifestFile.Path != "" {
src := filepath.Join(extLocalPath, util.ResolvePath(manifestFile.Path))
dst := filepath.Join(installPath, util.ResolvePath(manifestFile.Path))
err := util.CopyFile(src, dst)
if err != nil {
con.PrintErrorf("Error copying file '%s' -> '%s': %s\n", src, dst, err)
forceRemoveAll(installPath)
return
}
}
}
}
// InstallFromFilePath - Install an extension from a .tar.gz file
func InstallFromFilePath(extLocalPath string, autoOverwrite bool, con *console.SliverConsoleClient) *string {
manifestData, err := util.ReadFileFromTarGz(extLocalPath, fmt.Sprintf("./%s", ManifestFileName))
if err != nil {
con.PrintErrorf("Failed to read %s from '%s': %s\n", ManifestFileName, extLocalPath, err)
return nil
}
manifest, err := ParseExtensionManifest(manifestData)
if err != nil {
con.PrintErrorf("Failed to parse %s: %s\n", ManifestFileName, err)
return nil
}
installPath := filepath.Join(assets.GetExtensionsDir(), filepath.Base(manifest.CommandName))
if _, err := os.Stat(installPath); !os.IsNotExist(err) {
if !autoOverwrite {
con.PrintInfof("Extension '%s' already exists\n", manifest.CommandName)
//create repo path
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)
if !confirm {
return nil
return
}
}
forceRemoveAll(installPath)
forceRemoveAll(minstallPath)
}
con.PrintInfof("Installing extension '%s' (%s) ... ", manifest.CommandName, manifest.Version)
err = os.MkdirAll(installPath, 0o700)
con.PrintInfof("Installing extension '%s' (%s) ... \n", manifestF.Name, manifestF.Version)
err = os.MkdirAll(minstallPath, 0o700)
if err != nil {
con.PrintErrorf("Failed to create extension directory: %s\n", err)
return nil
con.PrintErrorf("Error creating extension directory: %s\n", err)
return
}
err = os.WriteFile(filepath.Join(installPath, ManifestFileName), manifestData, 0o600)
err = os.WriteFile(filepath.Join(minstallPath, ManifestFileName), manifestData, 0o600)
if err != nil {
con.PrintErrorf("Failed to write %s: %s\n", ManifestFileName, err)
forceRemoveAll(installPath)
return nil
forceRemoveAll(minstallPath)
return
}
for _, manifestFile := range manifest.Files {
if manifestFile.Path != "" {
err = installArtifact(extLocalPath, installPath, manifestFile.Path, con)
if err != nil {
con.PrintErrorf("Failed to install file: %s\n", err)
forceRemoveAll(installPath)
return nil
for _, manifest := range manifestF.ExtCommand {
installPath := filepath.Join(minstallPath)
for _, manifestFile := range manifest.Files {
if manifestFile.Path != "" {
if isGz {
err = installArtifact(extLocalPath, installPath, manifestFile.Path)
} else {
src := filepath.Join(extLocalPath, util.ResolvePath(manifestFile.Path))
dst := filepath.Join(installPath, util.ResolvePath(manifestFile.Path))
err = os.MkdirAll(filepath.Dir(dst), 0o700) //required for extensions with multiple dirs between the .o file and the manifest
if err != nil {
con.PrintErrorf("\nError creating extension directory: %s\n", err)
forceRemoveAll(installPath)
return
}
err = util.CopyFile(src, dst)
if err != nil {
err = fmt.Errorf("error copying file '%s' -> '%s': %s", src, dst, err)
}
}
if err != nil {
con.PrintErrorf("Error installing command: %s\n", err)
forceRemoveAll(installPath)
return
}
}
}
}
con.Printf("done!\n")
return &installPath
}
func installArtifact(extGzFilePath string, installPath string, artifactPath string, con *console.SliverConsoleClient) error {
func installArtifact(extGzFilePath string, installPath string, artifactPath string) error {
data, err := util.ReadFileFromTarGz(extGzFilePath, "."+filepath.ToSlash(artifactPath))
if err != nil {
return err
+109 -9
View File
@@ -20,15 +20,113 @@ package extensions
import (
"context"
"crypto/sha256"
"encoding/hex"
"os"
"path/filepath"
"slices"
"github.com/spf13/cobra"
"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"
)
// ExtensionsListCmd - List all extension loaded on the active session/beacon
func ExtensionsListCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []string) {
// 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()
if session == nil {
return
@@ -46,10 +144,12 @@ func ExtensionsListCmd(cmd *cobra.Command, con *console.SliverConsoleClient, arg
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)
}
+410 -107
View File
@@ -21,41 +21,46 @@ package extensions
import (
"bytes"
"context"
"crypto/sha256"
"encoding/hex"
"encoding/json"
"errors"
"fmt"
"log"
"os"
"path"
"path/filepath"
"strconv"
"strings"
appConsole "github.com/reeflective/console"
"github.com/rsteube/carapace"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
"google.golang.org/protobuf/proto"
"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/packages"
"github.com/bishopfox/sliver/protobuf/clientpb"
"github.com/bishopfox/sliver/protobuf/sliverpb"
"github.com/bishopfox/sliver/util"
appConsole "github.com/reeflective/console"
"github.com/rsteube/carapace"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
"google.golang.org/protobuf/proto"
)
const (
defaultTimeout = 60
// ManifestFileName - Extension manifest file name
// ManifestFileName - Extension manifest file name.
ManifestFileName = "extension.json"
)
var loadedExtensions = map[string]*ExtensionManifest{}
var loadedExtensions = map[string]*ExtCommand{}
var loadedManifests = map[string]*ExtensionManifest{}
type ExtensionManifest struct {
type ExtensionManifest_ struct {
Name string `json:"name"`
CommandName string `json:"command_name"`
Version string `json:"version"`
@@ -73,6 +78,37 @@ type ExtensionManifest struct {
RootPath string `json:"-"`
}
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"`
RepoURL string `json:"repo_url"`
ExtCommand []*ExtCommand `json:"commands"`
RootPath string `json:"-"`
ArmoryName string `json:"-"`
ArmoryPK string `json:"-"`
}
type ExtCommand struct {
CommandName string `json:"command_name"`
Help string `json:"help"`
LongHelp string `json:"long_help"`
Files []*extensionFile `json:"files"`
Arguments []*extensionArgument `json:"arguments"`
Entrypoint string `json:"entrypoint"`
DependsOn string `json:"depends_on"`
Init string `json:"init"`
Schema *packages.OutputSchema `json:"schema"`
Manifest *ExtensionManifest
}
//type MultiManifest []*ExtensionManifest
type extensionFile struct {
OS string `json:"os"`
Arch string `json:"arch"`
@@ -80,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 *ExtensionManifest) getFileForTarget(cmdName string, targetOS string, targetArch string) (string, error) {
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.CommandName, 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
}
}
@@ -105,90 +148,226 @@ func (e *ExtensionManifest) getFileForTarget(cmdName string, targetOS string, ta
return filePath, nil
}
// ExtensionLoadCmd - Load extension command
func ExtensionLoadCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []string) {
// 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")
extCmd, err := LoadExtensionManifest(filepath.Join(dirPath, ManifestFileName))
// 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
}
// do not add if the command already exists
sliverMenu := con.App.Menu("implant")
if CmdExists(extCmd.CommandName, sliverMenu.Command) {
con.PrintErrorf("%s command already exists\n", extCmd.CommandName)
return
for _, extCmd := range manifest.ExtCommand {
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)
if !confirm {
return
}
}
ExtensionRegisterCommand(extCmd, cmd.Root(), con)
con.PrintInfof("Added %s command: %s\n", extCmd.CommandName, extCmd.Help)
}
ExtensionRegisterCommand(extCmd, cmd.Root(), con)
con.PrintInfof("Added %s command: %s\n", extCmd.CommandName, extCmd.Help)
}
// 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 {
return nil, err
}
extManifest, err := ParseExtensionManifest(data)
manifest, err := ParseExtensionManifest(data)
if err != nil {
return nil, err
}
extManifest.RootPath = filepath.Dir(manifestPath)
loadedExtensions[extManifest.CommandName] = extManifest
return extManifest, nil
manifest.RootPath = filepath.Dir(manifestPath)
for _, extManifest := range manifest.ExtCommand {
loadedExtensions[extManifest.CommandName] = extManifest
}
loadedManifests[manifest.Name] = manifest
return manifest, nil
}
// ParseExtensionManifest - Parse extension manifest from buffer
func convertOldManifest(old *ExtensionManifest_) *ExtensionManifest {
ret := &ExtensionManifest{
Name: old.CommandName, //treating old command name as the manifest name to avoid weird chars mostly
Version: old.Version,
ExtensionAuthor: old.ExtensionAuthor,
OriginalAuthor: old.OriginalAuthor,
RepoURL: old.RepoURL,
RootPath: old.RootPath,
//only one command exists in the old manifest, so we can 'confidently' create it here
ExtCommand: []*ExtCommand{
{
CommandName: old.CommandName,
DependsOn: old.DependsOn,
Help: old.Help,
LongHelp: old.LongHelp,
Entrypoint: old.Entrypoint,
Files: old.Files,
Arguments: old.Arguments,
Schema: nil,
},
},
}
//Manifest ref is done in the parser that calls this
return ret
}
// parseExtensionManifest - Parse extension manifest from buffer (legacy, only parses one)
func ParseExtensionManifest(data []byte) (*ExtensionManifest, error) {
extManifest := &ExtensionManifest{}
err := json.Unmarshal(data, &extManifest)
if err != nil {
return nil, err
}
if extManifest.Name == "" {
return nil, errors.New("missing `name` field in extension manifest")
}
if extManifest.CommandName == "" {
return nil, errors.New("missing `command_name` field in extension manifest")
}
if len(extManifest.Files) == 0 {
return nil, errors.New("missing `files` field in extension manifest")
}
for _, extFiles := range extManifest.Files {
if extFiles.OS == "" {
return nil, errors.New("missing `files.os` field in extension manifest")
if err != nil || len(extManifest.ExtCommand) == 0 { //extensions must have at least one command to be sensible
//maybe it's an old manifest
if err != nil {
log.Printf("extension load error: %s", err)
}
if extFiles.Arch == "" {
return nil, errors.New("missing `files.arch` field in extension manifest")
oldmanifest := &ExtensionManifest_{}
err := json.Unmarshal(data, &oldmanifest)
if err != nil {
//nope, just broken
return nil, err
}
extFiles.Path = util.ResolvePath(extFiles.Path)
if extFiles.Path == "" || extFiles.Path == "/" {
return nil, errors.New("missing `files.path` field in extension manifest")
//yes, ok, lets jigger it to a new manifest
extManifest = convertOldManifest(oldmanifest)
}
//pass ref to manifest to each command and initialize output schema if applicable
for i := range extManifest.ExtCommand {
command := extManifest.ExtCommand[i]
command.Manifest = extManifest
if command.Schema != nil {
command.Schema.IngestColumns()
}
extFiles.OS = strings.ToLower(extFiles.OS)
extFiles.Arch = strings.ToLower(extFiles.Arch)
}
if extManifest.Help == "" {
return nil, errors.New("missing `help` field in extension manifest")
}
return extManifest, nil
return extManifest, validManifest(extManifest)
}
// ExtensionRegisterCommand - Register a new extension command
func ExtensionRegisterCommand(extCmd *ExtensionManifest, cmd *cobra.Command, con *console.SliverConsoleClient) {
func validManifest(manifest *ExtensionManifest) error {
if manifest.Name == "" {
return errors.New("missing `name` field in extension manifest")
}
for _, extManifest := range manifest.ExtCommand {
if extManifest.CommandName == "" {
return errors.New("missing `command_name` field in extension manifest")
}
if len(extManifest.Files) == 0 {
return errors.New("missing `files` field in extension manifest")
}
for _, extFiles := range extManifest.Files {
if extFiles.OS == "" {
return errors.New("missing `files.os` field in extension manifest")
}
if extFiles.Arch == "" {
return errors.New("missing `files.arch` field in extension manifest")
}
extFiles.Path = util.ResolvePath(extFiles.Path)
if extFiles.Path == "" || extFiles.Path == "/" {
return errors.New("missing `files.path` field in extension manifest")
}
extFiles.OS = strings.ToLower(extFiles.OS)
extFiles.Arch = strings.ToLower(extFiles.Arch)
}
if extManifest.Help == "" {
return errors.New("missing `help` field in extension manifest")
}
if extManifest.Schema != nil {
if !packages.IsValidSchemaType(extManifest.Schema.Name) {
return fmt.Errorf("%s is not a valid schema type", extManifest.Schema.Name)
}
}
}
return nil
}
// 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())
return
}
loadedExtensions[extCmd.CommandName] = extCmd
helpMsg := extCmd.Help
usage := strings.Builder{}
usage.WriteString(extCmd.CommandName)
//build usage including args
for _, arg := range extCmd.Arguments {
usage.WriteString(" ")
if arg.Optional {
usage.WriteString("[")
}
usage.WriteString(strings.ToUpper(arg.Name))
if arg.Optional {
usage.WriteString("]")
}
}
longHelp := strings.Builder{}
//prepend the help value, because otherwise I don't see where it is meant to be shown
//build the command ref
longHelp.WriteString("[[.Bold]]Command:[[.Normal]]")
longHelp.WriteString(usage.String())
longHelp.WriteString("\n")
if len(extCmd.Help) > 0 || len(extCmd.LongHelp) > 0 {
longHelp.WriteString("[[.Bold]]About:[[.Normal]]")
if len(extCmd.Help) > 0 {
longHelp.WriteString(extCmd.Help)
longHelp.WriteString("\n")
}
if len(extCmd.LongHelp) > 0 {
longHelp.WriteString(extCmd.LongHelp)
longHelp.WriteString("\n")
}
}
if len(extCmd.Arguments) > 0 {
longHelp.WriteString("[[.Bold]]Arguments:[[.Normal]]")
}
//if more than 0 args specified, describe each arg at the bottom of the long help text (incase the manifest doesn't include it)
for _, arg := range extCmd.Arguments {
longHelp.WriteString("\n\t")
optStr := ""
if arg.Optional {
optStr = "[OPTIONAL]"
}
aType := arg.Type
if aType == "wstring" {
aType = "string" //avoid confusion, as this is mostly for telling operator what to shove into the args
}
//idk how to make this look nice, tabs don't work especially good - maybe should use the table stuff other things do? Pls help.
longHelp.WriteString(fmt.Sprintf("%s (%s):\t%s%s", strings.ToUpper(arg.Name), aType, optStr, arg.Desc))
}
// Command
extensionCmd := &cobra.Command{
Use: extCmd.CommandName,
Short: helpMsg,
Long: help.FormatHelpTmpl(extCmd.LongHelp),
Use: usage.String(),
Short: extCmd.Help,
Long: help.FormatHelpTmpl(longHelp.String()),
Run: func(cmd *cobra.Command, args []string) {
runExtensionCmd(cmd, con, args)
},
@@ -197,7 +376,7 @@ func ExtensionRegisterCommand(extCmd *ExtensionManifest, cmd *cobra.Command, con
}
// Flags
f := pflag.NewFlagSet(extCmd.Name, pflag.ContinueOnError)
f := pflag.NewFlagSet(extCmd.CommandName, pflag.ContinueOnError)
f.BoolP("save", "s", false, "Save output to disk")
f.IntP("timeout", "t", defaultTimeout, "command timeout in seconds")
extensionCmd.Flags().AddFlagSet(f)
@@ -210,9 +389,9 @@ func ExtensionRegisterCommand(extCmd *ExtensionManifest, cmd *cobra.Command, con
cmd.AddCommand(extensionCmd)
}
func loadExtension(goos string, goarch string, checkCache bool, ext *ExtensionManifest, cmd *cobra.Command, con *console.SliverConsoleClient) error {
func loadExtension(goos string, goarch string, checkCache bool, ext *ExtCommand, cmd *cobra.Command, con *console.SliverClient) error {
var extensionList []string
binPath, err := ext.getFileForTarget(cmd.Name(), goos, goarch)
binPath, err := ext.getFileForTarget(goos, goarch)
if err != nil {
return err
}
@@ -231,25 +410,50 @@ func loadExtension(goos string, goarch string, checkCache bool, ext *ExtensionMa
}
extensionList = extList.Names
}
depLoaded := false
for _, extName := range extensionList {
if !depLoaded && extName == ext.DependsOn {
depLoaded = true
//extensionList contains all *implant* loaded extensions. Is a sha256 sum of the relevant file.
//get the file hash to compare against implant extensions later
toberunfilepath, err := ext.getFileForTarget(goos, goarch)
if err != nil {
return err
}
//we need to check the dependent if it's a bof
if ext.DependsOn != "" {
//verify extension is in loaded list
if extension, found := loadedExtensions[ext.DependsOn]; found {
toberunfilepath, err = extension.getFileForTarget(goos, goarch)
if err != nil {
return err
}
} else {
// handle error
return fmt.Errorf("attempted to load non-existing extension: %s", ext.DependsOn)
}
if ext.CommandName == extName {
}
//todo, maybe cache these values somewhere
toberunfiledata, err := os.ReadFile(toberunfilepath)
if err != nil {
return err
}
if len(toberunfiledata) == 0 {
//read an empty file, bail out
return errors.New("read empty extension file content")
}
bd := sha256.Sum256(toberunfiledata)
toberunhash := hex.EncodeToString(bd[:])
for _, extName := range extensionList {
//check if extension we are trying to run (ext.CommandName or ext.DependsOn, for bofs) is already loaded
if extName == toberunhash {
//exists on the other side, exit early
return nil
}
}
// Extension not found, let's load it
if filepath.Ext(binPath) == ".o" {
// BOFs are not loaded by the DLL loader, but we make sure the loader itself is loaded
// Auto load the coff loader if we have it
if !depLoaded {
if errLoad := loadDep(goos, goarch, ext.DependsOn, cmd, con); errLoad != nil {
return errLoad
}
}
return nil
// BOFs are not loaded by the DLL loader, but we need to load the loader (more load more good)
if ext.DependsOn != "" {
return loadDep(goos, goarch, ext.DependsOn, cmd, con)
}
binData, err := os.ReadFile(binPath)
if err != nil {
@@ -261,14 +465,45 @@ func loadExtension(goos string, goarch string, checkCache bool, ext *ExtensionMa
return nil
}
func registerExtension(goos string, ext *ExtensionManifest, binData []byte, cmd *cobra.Command, con *console.SliverConsoleClient) error {
func registerExtension(goos string, ext *ExtCommand, binData []byte, cmd *cobra.Command, con *console.SliverClient) error {
//set extension name to a hash of the data to avoid loading more than one instance
bd := sha256.Sum256(binData)
name := hex.EncodeToString(bd[:])
sess, beac := con.ActiveTarget.GetInteractive()
ctrl := make(chan bool)
//first time run of an extension will require some waiting depending on the size
if sess != nil {
msg := fmt.Sprintf("Sending %s to implant ...", ext.CommandName)
con.SpinUntil(msg, ctrl)
}
//don't block if we are in beacon mode
if beac != nil && sess == nil {
go func() {
registerResp, err := con.Rpc.RegisterExtension(context.Background(), &sliverpb.RegisterExtensionReq{
Name: name,
Data: binData,
OS: goos,
Init: ext.Init,
Request: con.ActiveTarget.Request(cmd),
})
if err != nil {
con.PrintErrorf("Error registering extension: %s\n", err)
}
if registerResp.Response != nil && registerResp.Response.Err != "" {
con.PrintErrorf("Error registering extension: %s\n", errors.New(registerResp.Response.Err))
}
}()
return nil
}
//session mode (hopefully)
registerResp, err := con.Rpc.RegisterExtension(context.Background(), &sliverpb.RegisterExtensionReq{
Name: ext.CommandName,
Name: name,
Data: binData,
OS: goos,
Init: ext.Init,
Request: con.ActiveTarget.Request(cmd),
})
ctrl <- true
<-ctrl
if err != nil {
return err
}
@@ -278,10 +513,10 @@ func registerExtension(goos string, ext *ExtensionManifest, binData []byte, cmd
return nil
}
func loadDep(goos string, goarch string, depName string, cmd *cobra.Command, con *console.SliverConsoleClient) error {
func loadDep(goos string, goarch string, depName string, cmd *cobra.Command, con *console.SliverClient) error {
depExt, ok := loadedExtensions[depName]
if ok {
depBinPath, err := depExt.getFileForTarget(depExt.CommandName, goos, goarch)
depBinPath, err := depExt.getFileForTarget(goos, goarch)
if err != nil {
return err
}
@@ -294,7 +529,7 @@ func loadDep(goos string, goarch string, depName string, cmd *cobra.Command, con
return fmt.Errorf("missing dependency %s", depName)
}
func runExtensionCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []string) {
func runExtensionCmd(cmd *cobra.Command, con *console.SliverClient, args []string) {
var (
err error
extensionArgs []byte
@@ -327,7 +562,7 @@ func runExtensionCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args
return
}
binPath, err := ext.getFileForTarget(cmd.Name(), goos, goarch)
binPath, err := ext.getFileForTarget(goos, goarch)
if err != nil {
con.PrintErrorf("Failed to read extension file: %s\n", err)
return
@@ -350,9 +585,12 @@ func runExtensionCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args
extName = ext.DependsOn
entryPoint = loadedExtensions[extName].Entrypoint // should exist at this point
} else {
// Regular DLL
extArgs := strings.Join(args, " ")
extensionArgs = []byte(extArgs)
// 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
}
@@ -360,8 +598,41 @@ func runExtensionCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args
ctrl := make(chan bool)
msg := fmt.Sprintf("Executing %s ...", cmd.Name())
con.SpinUntil(msg, ctrl)
extdata, err := os.ReadFile(binPath)
if err != nil {
con.PrintErrorf("ext read file error: %s\n", err)
}
bd := sha256.Sum256(extdata)
name := hex.EncodeToString(bd[:])
if isBOF {
//if we are using a bof, we are actually calling the coffloader extension - so get the file from dep ref and use that shasum
if extension, found := loadedExtensions[ext.DependsOn]; found {
dep, err := extension.getFileForTarget(goos, goarch)
if err != nil {
con.PrintErrorf("could not get file for extension %s", ext.DependsOn)
return
}
depdata, err := os.ReadFile(dep)
if err != nil {
con.PrintErrorf("dep read file error: %s\n", err)
return
}
if len(depdata) == 0 {
con.PrintErrorf("read empty file: %s\n", dep)
return
}
bd = sha256.Sum256(depdata)
name = hex.EncodeToString(bd[:])
} else {
// handle error
con.PrintErrorf("attempted to load non-existing extension: %s", ext.DependsOn)
return
}
}
callExtResp, err := con.Rpc.CallExtension(context.Background(), &sliverpb.CallExtensionReq{
Name: extName,
Name: name,
Export: entryPoint,
Args: extensionArgs,
Request: con.ActiveTarget.Request(cmd),
@@ -380,23 +651,38 @@ func runExtensionCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args
con.PrintErrorf("Failed to decode call ext response %s\n", err)
return
}
PrintExtOutput(extName, ext.CommandName, callExtResp, con)
PrintExtOutput(extName, ext.CommandName, ext.Schema, callExtResp, con)
})
con.PrintAsyncResponse(callExtResp.Response)
} else {
PrintExtOutput(extName, ext.CommandName, callExtResp, con)
PrintExtOutput(extName, ext.CommandName, ext.Schema, callExtResp, con)
}
}
// PrintExtOutput - Print the ext execution output
func PrintExtOutput(extName string, commandName string, callExtension *sliverpb.CallExtension, con *console.SliverConsoleClient) {
// PrintExtOutput - Print the ext execution output.
func PrintExtOutput(extName string, commandName string, outputSchema *packages.OutputSchema, callExtension *sliverpb.CallExtension, con *console.SliverClient) {
if extName == commandName {
con.PrintInfof("Successfully executed %s", extName)
con.PrintInfof("Successfully executed %s\n", extName)
} else {
con.PrintInfof("Successfully executed %s (%s)", commandName, extName)
con.PrintInfof("Successfully executed %s (%s)\n", commandName, extName)
}
if 0 < len(string(callExtension.Output)) {
con.PrintInfof("Got output:\n%s", callExtension.Output)
if outputSchema == nil {
con.PrintInfof("Got output:\n%s", callExtension.Output)
} else {
// Get output schema
schema := packages.GetNewPackageOutput(outputSchema.Name)
if schema != nil {
ingestErr := schema.IngestData(callExtension.Output, outputSchema.Columns(), outputSchema.GroupBy)
if ingestErr != nil {
con.PrintInfof("Got output:\n%s", callExtension.Output)
} else {
con.Printf("%s\n", schema.CreateTable())
}
} else {
con.PrintInfof("Got output:\n%s", callExtension.Output)
}
}
}
if callExtension.Response != nil && callExtension.Response.Err != "" {
con.PrintErrorf(callExtension.Response.Err)
@@ -404,12 +690,8 @@ func PrintExtOutput(extName string, commandName string, callExtension *sliverpb.
}
}
func getBOFArgs(cmd *cobra.Command, args []string, binPath string, ext *ExtensionManifest) ([]byte, error) {
var extensionArgs []byte
binData, err := os.ReadFile(binPath)
if err != nil {
return nil, err
}
func getExtArgs(_ *cobra.Command, args []string, _ string, ext *ExtCommand) ([]byte, error) {
var err error
argsBuffer := core.BOFArgsBuffer{
Buffer: new(bytes.Buffer),
}
@@ -417,6 +699,12 @@ func getBOFArgs(cmd *cobra.Command, args []string, binPath string, ext *Extensio
// Parse BOF arguments from grumble
missingRequiredArgs := make([]string, 0)
// If we have an extension that expects a single string, but more than one has been parsed, combine them
if len(ext.Arguments) == 1 && strings.Contains(ext.Arguments[0].Type, "string") && len(args) > 0 {
// The loop below will only read the first element of args because ext.Arguments is 1
args[0] = strings.Join(args, " ")
}
for _, arg := range ext.Arguments {
// If we don't have any positional words left to consume,
// add the remaining required extension arguments in the
@@ -486,6 +774,17 @@ func getBOFArgs(cmd *cobra.Command, args []string, binPath string, ext *Extensio
if err != nil {
return nil, err
}
return parsedArgs, nil
}
func getBOFArgs(cmd *cobra.Command, args []string, binPath string, ext *ExtCommand) ([]byte, error) {
var extensionArgs []byte
binData, err := os.ReadFile(binPath)
if err != nil {
return nil, err
}
// Now build the extension's argument buffer
extensionArgsBuffer := core.BOFArgsBuffer{
Buffer: new(bytes.Buffer),
@@ -498,6 +797,10 @@ func getBOFArgs(cmd *cobra.Command, args []string, binPath string, ext *Extensio
if err != nil {
return nil, err
}
parsedArgs, err := ParseFlagArgumentsToBuffer(cmd, args, binPath, ext)
if err != nil {
return nil, err
}
err = extensionArgsBuffer.AddData(parsedArgs)
if err != nil {
return nil, err
@@ -509,7 +812,7 @@ func getBOFArgs(cmd *cobra.Command, args []string, binPath string, ext *Extensio
return extensionArgs, nil
}
// CmdExists - checks if a command exists
// CmdExists - checks if a command exists.
func CmdExists(name string, cmd *cobra.Command) bool {
for _, c := range cmd.Commands() {
if name == c.Name() {
@@ -520,7 +823,7 @@ func CmdExists(name string, cmd *cobra.Command) bool {
}
// makeExtensionArgParser builds the valid positional arguments cobra handler for the extension.
func checkExtensionArgs(extCmd *ExtensionManifest) error {
func checkExtensionArgs(extCmd *ExtCommand) error {
if 0 < len(extCmd.Arguments) {
for _, arg := range extCmd.Arguments {
switch arg.Type {
@@ -536,7 +839,7 @@ func checkExtensionArgs(extCmd *ExtensionManifest) error {
}
// makeExtensionArgCompleter builds the positional arguments completer for the extension.
func makeExtensionArgCompleter(extCmd *ExtensionManifest, _ *cobra.Command, comps *carapace.Carapace) {
func makeExtensionArgCompleter(extCmd *ExtCommand, _ *cobra.Command, comps *carapace.Carapace) {
var actions []carapace.Action
for _, arg := range extCmd.Arguments {
@@ -558,7 +861,7 @@ func makeExtensionArgCompleter(extCmd *ExtensionManifest, _ *cobra.Command, comp
comps.PositionalCompletion(actions...)
}
func makeCommandPlatformFilters(extCmd *ExtensionManifest) map[string]string {
func makeCommandPlatformFilters(extCmd *ExtCommand) map[string]string {
filtersOS := make(map[string]bool)
filtersArch := make(map[string]bool)
+64 -9
View File
@@ -23,17 +23,17 @@ import (
"fmt"
"os"
"path/filepath"
"strings"
"github.com/AlecAivazis/survey/v2"
"github.com/spf13/cobra"
"github.com/bishopfox/sliver/client/assets"
"github.com/bishopfox/sliver/client/console"
"github.com/bishopfox/sliver/util"
"github.com/spf13/cobra"
)
// ExtensionsRemoveCmd - Remove an extension
func ExtensionsRemoveCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []string) {
// ExtensionsRemoveCmd - Remove an extension.
func ExtensionsRemoveCmd(cmd *cobra.Command, con *console.SliverClient, args []string) {
name := args[0]
if name == "" {
con.PrintErrorf("Extension name is required\n")
@@ -45,17 +45,27 @@ func ExtensionsRemoveCmd(cmd *cobra.Command, con *console.SliverConsoleClient, a
if !confirm {
return
}
err := RemoveExtensionByCommandName(name, con)
found, err := RemoveExtensionByManifestName(name, con)
if err != nil {
con.PrintErrorf("Error removing extension: %s\n", err)
con.PrintErrorf("Error removing extensions: %s\n", err)
return
}
if !found {
err = RemoveExtensionByCommandName(name, con)
if err != nil {
con.PrintErrorf("Error removing extension: %s\n", err)
return
} else {
con.PrintInfof("Extension '%s' removed\n", name)
}
} else {
con.PrintInfof("Extension '%s' removed\n", name)
//found, and no error, manifest must have removed good
con.PrintInfof("Extensions from %s removed\n", name)
}
}
// RemoveExtensionByCommandName - Remove an extension by command name
func RemoveExtensionByCommandName(commandName string, con *console.SliverConsoleClient) error {
// RemoveExtensionByCommandName - Remove an extension by command name.
func RemoveExtensionByCommandName(commandName string, con *console.SliverClient) error {
if commandName == "" {
return errors.New("command name is required")
}
@@ -71,6 +81,51 @@ func RemoveExtensionByCommandName(commandName string, con *console.SliverConsole
return nil
}
// RemoveExtensionByManifestName - remove by the named manifest, returns true if manifest was removed, false if no manifest with that name was found
func RemoveExtensionByManifestName(manifestName string, con *console.SliverClient) (bool, error) {
if manifestName == "" {
return false, errors.New("command name is required")
}
if man, ok := loadedManifests[manifestName]; ok {
// 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
prompt := &survey.Confirm{Message: fmt.Sprintf("Remove '%s' extension directory from filesystem?", manifestName)}
survey.AskOne(prompt, &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 {
delete(loadedExtensions, cmd.CommandName)
}
return true, nil
}
return false, nil
}
func forceRemoveAll(rootPath string) {
util.ChmodR(rootPath, 0o600, 0o700)
os.RemoveAll(rootPath)
+12 -9
View File
@@ -23,22 +23,22 @@ import (
"encoding/hex"
"fmt"
"os"
"strings"
"github.com/alecthomas/chroma/formatters"
"github.com/alecthomas/chroma/lexers"
"github.com/alecthomas/chroma/styles"
"github.com/spf13/cobra"
"google.golang.org/protobuf/proto"
"github.com/bishopfox/sliver/client/command/loot"
"github.com/bishopfox/sliver/client/console"
"github.com/bishopfox/sliver/protobuf/clientpb"
"github.com/bishopfox/sliver/protobuf/sliverpb"
"github.com/bishopfox/sliver/util/encoders"
"github.com/spf13/cobra"
"google.golang.org/protobuf/proto"
)
// CatCmd - Display the contents of a remote file
func CatCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []string) {
// CatCmd - Display the contents of a remote file.
func CatCmd(cmd *cobra.Command, con *console.SliverClient, args []string) {
session, beacon := con.ActiveTarget.GetInteractive()
if session == nil && beacon == nil {
return
@@ -73,16 +73,16 @@ func CatCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []string)
con.PrintErrorf("Failed to decode response %s\n", err)
return
}
PrintCat(download, cmd, con)
PrintCat(filePath, download, cmd, con)
})
con.PrintAsyncResponse(download.Response)
} else {
PrintCat(download, cmd, con)
PrintCat(filePath, download, cmd, con)
}
}
// PrintCat - Print the download to stdout
func PrintCat(download *sliverpb.Download, cmd *cobra.Command, con *console.SliverConsoleClient) {
// PrintCat - Print the download to stdout.
func PrintCat(originalFileName string, download *sliverpb.Download, cmd *cobra.Command, con *console.SliverClient) {
var (
lootDownload bool = true
err error
@@ -109,6 +109,9 @@ func PrintCat(download *sliverpb.Download, cmd *cobra.Command, con *console.Sliv
con.Printf("\n")
}
}
if !strings.Contains(download.Path, originalFileName) {
con.PrintInfof("Supplied pattern %s matched file %s\n\n", originalFileName, download.Path)
}
if color, _ := cmd.Flags().GetBool("colorize-output"); color {
if err = colorize(download); err != nil {
con.Println(string(download.Data))
+4 -6
View File
@@ -21,17 +21,15 @@ package filesystem
import (
"context"
"google.golang.org/protobuf/proto"
"github.com/spf13/cobra"
"github.com/bishopfox/sliver/client/console"
"github.com/bishopfox/sliver/protobuf/clientpb"
"github.com/bishopfox/sliver/protobuf/sliverpb"
"github.com/spf13/cobra"
"google.golang.org/protobuf/proto"
)
// CdCmd - Change directory on the remote system
func CdCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []string) {
// CdCmd - Change directory on the remote system.
func CdCmd(cmd *cobra.Command, con *console.SliverClient, args []string) {
session, beacon := con.ActiveTarget.GetInteractive()
if session == nil && beacon == nil {
return
+6 -8
View File
@@ -20,17 +20,15 @@ package filesystem
import (
"context"
"google.golang.org/protobuf/proto"
"github.com/spf13/cobra"
"github.com/bishopfox/sliver/client/console"
"github.com/bishopfox/sliver/protobuf/clientpb"
"github.com/bishopfox/sliver/protobuf/sliverpb"
"github.com/spf13/cobra"
"google.golang.org/protobuf/proto"
)
// ChmodCmd - Change the permissions of a file on the remote file system
func ChmodCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []string) {
// ChmodCmd - Change the permissions of a file on the remote file system.
func ChmodCmd(cmd *cobra.Command, con *console.SliverClient, args []string) {
session, beacon := con.ActiveTarget.GetInteractive()
if session == nil && beacon == nil {
return
@@ -77,8 +75,8 @@ func ChmodCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []strin
}
}
// PrintChmod - Print the chmod response
func PrintChmod(chmod *sliverpb.Chmod, con *console.SliverConsoleClient) {
// PrintChmod - Print the chmod response.
func PrintChmod(chmod *sliverpb.Chmod, con *console.SliverClient) {
if chmod.Response != nil && chmod.Response.Err != "" {
con.PrintErrorf("%s\n", chmod.Response.Err)
return
+6 -8
View File
@@ -20,17 +20,15 @@ package filesystem
import (
"context"
"google.golang.org/protobuf/proto"
"github.com/spf13/cobra"
"github.com/bishopfox/sliver/client/console"
"github.com/bishopfox/sliver/protobuf/clientpb"
"github.com/bishopfox/sliver/protobuf/sliverpb"
"github.com/spf13/cobra"
"google.golang.org/protobuf/proto"
)
// ChownCmd - Change the owner of a file on the remote file system
func ChownCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []string) {
// ChownCmd - Change the owner of a file on the remote file system.
func ChownCmd(cmd *cobra.Command, con *console.SliverClient, args []string) {
session, beacon := con.ActiveTarget.GetInteractive()
if session == nil && beacon == nil {
return
@@ -85,8 +83,8 @@ func ChownCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []strin
}
}
// PrintChown - Print the chown response
func PrintChown(chown *sliverpb.Chown, con *console.SliverConsoleClient) {
// PrintChown - Print the chown response.
func PrintChown(chown *sliverpb.Chown, con *console.SliverClient) {
if chown.Response != nil && chown.Response.Err != "" {
con.PrintErrorf("%s\n", chown.Response.Err)
return
+6 -8
View File
@@ -21,17 +21,15 @@ import (
"context"
"time"
"google.golang.org/protobuf/proto"
"github.com/spf13/cobra"
"github.com/bishopfox/sliver/client/console"
"github.com/bishopfox/sliver/protobuf/clientpb"
"github.com/bishopfox/sliver/protobuf/sliverpb"
"github.com/spf13/cobra"
"google.golang.org/protobuf/proto"
)
// ChtimesCmd - Change the access and modified time of a file on the remote file system
func ChtimesCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []string) {
// ChtimesCmd - Change the access and modified time of a file on the remote file system.
func ChtimesCmd(cmd *cobra.Command, con *console.SliverClient, args []string) {
session, beacon := con.ActiveTarget.GetInteractive()
if session == nil && beacon == nil {
return
@@ -98,8 +96,8 @@ func ChtimesCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []str
}
}
// PrintChtimes - Print the Chtimes response
func PrintChtimes(chtimes *sliverpb.Chtimes, con *console.SliverConsoleClient) {
// PrintChtimes - Print the Chtimes response.
func PrintChtimes(chtimes *sliverpb.Chtimes, con *console.SliverClient) {
if chtimes.Response != nil && chtimes.Response.Err != "" {
con.PrintErrorf("%s\n", chtimes.Response.Err)
return
+346
View File
@@ -0,0 +1,346 @@
package filesystem
import (
"github.com/bishopfox/sliver/client/command/flags"
"github.com/bishopfox/sliver/client/command/help"
"github.com/bishopfox/sliver/client/command/loot"
"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.
func Commands(con *console.SliverClient) []*cobra.Command {
mvCmd := &cobra.Command{
Use: consts.MvStr,
Short: "Move or rename a file",
Long: help.GetHelpFor([]string{consts.MvStr}),
Args: cobra.ExactArgs(2),
Run: func(cmd *cobra.Command, args []string) {
MvCmd(cmd, con, args)
},
GroupID: consts.FilesystemHelpGroup,
}
flags.Bind("", false, mvCmd, func(f *pflag.FlagSet) {
f.Int64P("timeout", "t", flags.DefaultTimeout, "grpc timeout in seconds")
})
carapace.Gen(mvCmd).PositionalCompletion(
carapace.ActionValues().Usage("path to source file (required)"),
carapace.ActionValues().Usage("path to dest file (required)"),
)
cpCmd := &cobra.Command{
Use: consts.CpStr,
Short: "Copy a file",
Long: help.GetHelpFor([]string{consts.CpStr}),
Args: cobra.ExactArgs(2),
Run: func(cmd *cobra.Command, args []string) {
CpCmd(cmd, con, args)
},
GroupID: consts.FilesystemHelpGroup,
}
flags.Bind("", false, cpCmd, func(f *pflag.FlagSet) {
f.Int64P("timeout", "t", flags.DefaultTimeout, "grpc timeout in seconds")
})
carapace.Gen(cpCmd).PositionalCompletion(
carapace.ActionValues().Usage("path to source file (required)"),
carapace.ActionValues().Usage("path to dest file (required)"),
)
lsCmd := &cobra.Command{
Use: consts.LsStr,
Short: "List current directory",
Long: help.GetHelpFor([]string{consts.LsStr}),
Args: cobra.RangeArgs(0, 1),
Run: func(cmd *cobra.Command, args []string) {
LsCmd(cmd, con, args)
},
GroupID: consts.FilesystemHelpGroup,
}
flags.Bind("", false, lsCmd, func(f *pflag.FlagSet) {
f.BoolP("reverse", "r", false, "reverse sort order")
f.BoolP("modified", "m", false, "sort by modified time")
f.BoolP("size", "s", false, "sort by size")
f.Int64P("timeout", "t", flags.DefaultTimeout, "grpc timeout in seconds")
})
carapace.Gen(lsCmd).PositionalCompletion(carapace.ActionValues().Usage("path to enumerate (optional)"))
rmCmd := &cobra.Command{
Use: consts.RmStr,
Short: "Remove a file or directory",
Long: help.GetHelpFor([]string{consts.RmStr}),
Args: cobra.ExactArgs(1),
Run: func(cmd *cobra.Command, args []string) {
RmCmd(cmd, con, args)
},
GroupID: consts.FilesystemHelpGroup,
}
flags.Bind("", false, rmCmd, func(f *pflag.FlagSet) {
f.BoolP("recursive", "r", false, "recursively remove files")
f.BoolP("force", "F", false, "ignore safety and forcefully remove files")
f.Int64P("timeout", "t", flags.DefaultTimeout, "grpc timeout in seconds")
})
carapace.Gen(rmCmd).PositionalCompletion(carapace.ActionValues().Usage("path to the file to remove"))
mkdirCmd := &cobra.Command{
Use: consts.MkdirStr,
Short: "Make a directory",
Long: help.GetHelpFor([]string{consts.MkdirStr}),
Args: cobra.ExactArgs(1),
Run: func(cmd *cobra.Command, args []string) {
MkdirCmd(cmd, con, args)
},
GroupID: consts.FilesystemHelpGroup,
}
flags.Bind("", false, mkdirCmd, func(f *pflag.FlagSet) {
f.Int64P("timeout", "t", flags.DefaultTimeout, "grpc timeout in seconds")
})
carapace.Gen(mkdirCmd).PositionalCompletion(carapace.ActionValues().Usage("path to the directory to create"))
cdCmd := &cobra.Command{
Use: consts.CdStr,
Short: "Change directory",
Long: help.GetHelpFor([]string{consts.CdStr}),
Args: cobra.RangeArgs(0, 1),
Run: func(cmd *cobra.Command, args []string) {
CdCmd(cmd, con, args)
},
GroupID: consts.FilesystemHelpGroup,
}
flags.Bind("", false, cdCmd, func(f *pflag.FlagSet) {
f.Int64P("timeout", "t", flags.DefaultTimeout, "grpc timeout in seconds")
})
carapace.Gen(cdCmd).PositionalCompletion(carapace.ActionValues().Usage("path to the directory"))
pwdCmd := &cobra.Command{
Use: consts.PwdStr,
Short: "Print working directory",
Long: help.GetHelpFor([]string{consts.PwdStr}),
Run: func(cmd *cobra.Command, args []string) {
PwdCmd(cmd, con, args)
},
GroupID: consts.FilesystemHelpGroup,
}
flags.Bind("", false, pwdCmd, func(f *pflag.FlagSet) {
f.Int64P("timeout", "t", flags.DefaultTimeout, "grpc timeout in seconds")
})
catCmd := &cobra.Command{
Use: consts.CatStr,
Short: "Dump file to stdout",
Long: help.GetHelpFor([]string{consts.CatStr}),
Args: cobra.ExactArgs(1),
Run: func(cmd *cobra.Command, args []string) {
CatCmd(cmd, con, args)
},
GroupID: consts.FilesystemHelpGroup,
}
flags.Bind("", false, catCmd, func(f *pflag.FlagSet) {
f.BoolP("colorize-output", "c", false, "colorize output")
f.BoolP("hex", "x", false, "display as a hex dump")
f.BoolP("loot", "X", false, "save output as loot")
f.StringP("name", "n", "", "name to assign loot (optional)")
f.StringP("type", "T", "", "force a specific loot type (file/cred) if looting (optional)")
f.StringP("file-type", "F", "", "force a specific file type (binary/text) if looting (optional)")
f.Int64P("timeout", "t", flags.DefaultTimeout, "grpc timeout in seconds")
})
carapace.Gen(catCmd).PositionalCompletion(carapace.ActionValues().Usage("path to the file to print"))
downloadCmd := &cobra.Command{
Use: consts.DownloadStr,
Short: "Download a file",
Long: help.GetHelpFor([]string{consts.DownloadStr}),
Args: cobra.RangeArgs(1, 2),
Run: func(cmd *cobra.Command, args []string) {
DownloadCmd(cmd, con, args)
},
GroupID: consts.FilesystemHelpGroup,
}
flags.Bind("", false, downloadCmd, func(f *pflag.FlagSet) {
f.BoolP("loot", "X", false, "save output as loot")
f.StringP("type", "T", "", "force a specific loot type (file/cred) if looting")
f.StringP("file-type", "F", "", "force a specific file type (binary/text) if looting")
f.StringP("name", "n", "", "name to assign the download if looting")
f.BoolP("recurse", "r", false, "recursively download all files in a directory")
f.Int64P("timeout", "t", flags.DefaultTimeout, "grpc timeout in seconds")
})
flags.BindFlagCompletions(downloadCmd, func(comp *carapace.ActionMap) {
(*comp)["type"] = loot.LootTypeCompleter(con)
(*comp)["file-type"] = loot.FileTypeCompleter(con)
})
carapace.Gen(downloadCmd).PositionalCompletion(
carapace.ActionValues().Usage("path to the file or directory to download"),
carapace.ActionFiles().Usage("local path where the downloaded file will be saved (optional)"),
)
uploadCmd := &cobra.Command{
Use: consts.UploadStr,
Short: "Upload a file",
Long: help.GetHelpFor([]string{consts.UploadStr}),
Args: cobra.RangeArgs(1, 2),
Run: func(cmd *cobra.Command, args []string) {
UploadCmd(cmd, con, args)
},
GroupID: consts.FilesystemHelpGroup,
}
flags.Bind("", false, uploadCmd, func(f *pflag.FlagSet) {
f.BoolP("ioc", "i", false, "track uploaded file as an ioc")
f.Int64P("timeout", "t", flags.DefaultTimeout, "grpc timeout in seconds")
f.BoolP("overwrite", "o", false, "overwrite file if it exists")
})
carapace.Gen(uploadCmd).PositionalCompletion(
carapace.ActionFiles().Usage("local path to the file to upload"),
carapace.ActionValues().Usage("path to the file or directory to upload to (optional)"),
)
memfilesCmd := &cobra.Command{
Use: consts.MemfilesStr,
Short: "List current memfiles",
Long: help.GetHelpFor([]string{consts.MemfilesStr}),
GroupID: consts.FilesystemHelpGroup,
Run: func(cmd *cobra.Command, args []string) {
MemfilesListCmd(cmd, con, args)
},
}
flags.Bind("", true, memfilesCmd, func(f *pflag.FlagSet) {
f.Int64P("timeout", "t", flags.DefaultTimeout, "grpc timeout in seconds")
})
memfilesAddCmd := &cobra.Command{
Use: consts.AddStr,
Short: "Add a memfile",
Long: help.GetHelpFor([]string{consts.MemfilesStr, consts.AddStr}),
Run: func(cmd *cobra.Command, args []string) {
MemfilesAddCmd(cmd, con, args)
},
}
memfilesCmd.AddCommand(memfilesAddCmd)
memfilesRmCmd := &cobra.Command{
Use: consts.RmStr,
Short: "Remove a memfile",
Long: help.GetHelpFor([]string{consts.MemfilesStr, consts.RmStr}),
Args: cobra.ExactArgs(1),
Run: func(cmd *cobra.Command, args []string) {
MemfilesRmCmd(cmd, con, args)
},
}
memfilesCmd.AddCommand(memfilesRmCmd)
carapace.Gen(memfilesRmCmd).PositionalCompletion(carapace.ActionValues().Usage("memfile file descriptor"))
mountCmd := &cobra.Command{
Use: consts.MountStr,
Short: "Get information on mounted filesystems",
Long: help.GetHelpFor([]string{consts.MountStr}),
Run: func(cmd *cobra.Command, args []string) {
MountCmd(cmd, con, args)
},
GroupID: consts.FilesystemHelpGroup,
}
flags.Bind("", false, mountCmd, func(f *pflag.FlagSet) {
f.Int64P("timeout", "t", flags.DefaultTimeout, "grpc timeout in seconds")
})
grepCmd := &cobra.Command{
Use: consts.GrepStr,
Short: "Search for strings that match a regex within a file or directory",
Long: help.GetHelpFor([]string{consts.GrepStr}),
Args: cobra.ExactArgs(2),
Run: func(cmd *cobra.Command, args []string) {
GrepCmd(cmd, con, args)
},
GroupID: consts.FilesystemHelpGroup,
}
flags.Bind("", false, grepCmd, func(f *pflag.FlagSet) {
f.BoolP("colorize-output", "c", false, "colorize output")
f.BoolP("loot", "X", false, "save output as loot (loot is saved without formatting)")
f.StringP("name", "n", "", "name to assign loot (optional)")
f.StringP("type", "T", "", "force a specific loot type (file/cred) if looting (optional)")
f.Int64P("timeout", "t", flags.DefaultTimeout, "grpc timeout in seconds")
f.BoolP("recursive", "r", false, "search recursively")
f.BoolP("insensitive", "i", false, "case-insensitive search")
f.Int32P("after", "A", 0, "number of lines to print after a match (ignored if the file is binary)")
f.Int32P("before", "B", 0, "number of lines to print before a match (ignored if the file is binary)")
f.Int32P("context", "C", 0, "number of lines to print before and after a match (ignored if the file is binary), equivalent to -A x -B x")
f.BoolP("exact", "e", false, "match the search term exactly")
})
carapace.Gen(grepCmd).PositionalCompletion(
carapace.ActionValues().Usage("regex to search the file for"),
carapace.ActionValues().Usage("remote path / file to search in"),
)
headCmd := &cobra.Command{
Use: consts.HeadStr,
Short: "Grab the first number of bytes or lines from a file",
Long: help.GetHelpFor([]string{consts.HeadStr}),
Args: cobra.ExactArgs(1),
Run: func(cmd *cobra.Command, args []string) {
/*
The last argument tells head if the user requested the head or tail of the file
True means head, false means tail
*/
HeadCmd(cmd, con, args, true)
},
GroupID: consts.FilesystemHelpGroup,
}
flags.Bind("", false, headCmd, func(f *pflag.FlagSet) {
f.BoolP("colorize-output", "c", false, "colorize output")
f.BoolP("hex", "x", false, "display as a hex dump")
f.BoolP("loot", "X", false, "save output as loot")
f.StringP("name", "n", "", "name to assign loot (optional)")
f.StringP("type", "T", "", "force a specific loot type (file/cred) if looting (optional)")
f.StringP("file-type", "F", "", "force a specific file type (binary/text) if looting (optional)")
f.Int64P("timeout", "t", flags.DefaultTimeout, "grpc timeout in seconds")
f.Int64P("bytes", "b", 0, "Grab the first number of bytes from the file")
f.Int64P("lines", "l", 10, "Grab the first number of lines from the file")
})
carapace.Gen(headCmd).PositionalCompletion(carapace.ActionValues().Usage("path to the file to print"))
tailCmd := &cobra.Command{
Use: consts.TailStr,
Short: "Grab the last number of bytes or lines from a file",
Long: help.GetHelpFor([]string{consts.TailStr}),
Args: cobra.ExactArgs(1),
Run: func(cmd *cobra.Command, args []string) {
/*
The last argument tells head if the user requested the head or tail of the file
True means head, false means tail
*/
HeadCmd(cmd, con, args, false)
},
GroupID: consts.FilesystemHelpGroup,
}
flags.Bind("", false, tailCmd, func(f *pflag.FlagSet) {
f.BoolP("colorize-output", "c", false, "colorize output")
f.BoolP("hex", "x", false, "display as a hex dump")
f.BoolP("loot", "X", false, "save output as loot")
f.StringP("name", "n", "", "name to assign loot (optional)")
f.StringP("type", "T", "", "force a specific loot type (file/cred) if looting (optional)")
f.StringP("file-type", "F", "", "force a specific file type (binary/text) if looting (optional)")
f.Int64P("timeout", "t", flags.DefaultTimeout, "grpc timeout in seconds")
f.Int64P("bytes", "b", 0, "Grab the last number of bytes from the file")
f.Int64P("lines", "l", 10, "Grab the last number of lines from the file")
})
carapace.Gen(tailCmd).PositionalCompletion(carapace.ActionValues().Usage("path to the file to print"))
return []*cobra.Command{
mvCmd,
cpCmd,
lsCmd,
rmCmd,
mkdirCmd,
pwdCmd,
catCmd,
cdCmd,
downloadCmd,
uploadCmd,
memfilesCmd,
mountCmd,
grepCmd,
headCmd,
tailCmd,
}
}
+4 -6
View File
@@ -21,16 +21,14 @@ package filesystem
import (
"context"
"google.golang.org/protobuf/proto"
"github.com/spf13/cobra"
"github.com/bishopfox/sliver/client/console"
"github.com/bishopfox/sliver/protobuf/clientpb"
"github.com/bishopfox/sliver/protobuf/sliverpb"
"github.com/spf13/cobra"
"google.golang.org/protobuf/proto"
)
func CpCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []string) (err error) {
func CpCmd(cmd *cobra.Command, con *console.SliverClient, args []string) (err error) {
session, beacon := con.ActiveTarget.GetInteractive()
if session == nil && beacon == nil {
return
@@ -72,7 +70,7 @@ func CpCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []string)
return
}
func PrintCp(cp *sliverpb.Cp, con *console.SliverConsoleClient) {
func PrintCp(cp *sliverpb.Cp, con *console.SliverClient) {
if cp.Response != nil && cp.Response.Err != "" {
con.PrintErrorf("%s\n", cp.Response.Err)
return
+15 -10
View File
@@ -28,18 +28,17 @@ import (
"strings"
"time"
"github.com/spf13/cobra"
"google.golang.org/protobuf/proto"
"gopkg.in/AlecAivazis/survey.v1"
"github.com/bishopfox/sliver/client/command/loot"
"github.com/bishopfox/sliver/client/console"
"github.com/bishopfox/sliver/protobuf/clientpb"
"github.com/bishopfox/sliver/protobuf/sliverpb"
"github.com/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.SliverConsoleClient, args []string) {
func DownloadCmd(cmd *cobra.Command, con *console.SliverClient, args []string) {
session, beacon := con.ActiveTarget.GetInteractive()
if session == nil && beacon == nil {
return
@@ -98,14 +97,12 @@ func prettifyDownloadName(path string) string {
filteredString = multipleUnderscoreRegex.ReplaceAllString(filteredString, "_")
// If there is an underscore at the front of the filename, strip that off
if strings.HasPrefix(filteredString, "_") {
filteredString = filteredString[1:]
}
filteredString, _ = strings.CutPrefix(filteredString, "_")
return filteredString
}
func HandleDownloadResponse(download *sliverpb.Download, cmd *cobra.Command, args []string, con *console.SliverConsoleClient) {
func HandleDownloadResponse(download *sliverpb.Download, cmd *cobra.Command, args []string, con *console.SliverClient) {
var err error
if download.Response != nil && download.Response.Err != "" {
con.PrintErrorf("%s\n", download.Response.Err)
@@ -119,7 +116,15 @@ func HandleDownloadResponse(download *sliverpb.Download, cmd *cobra.Command, arg
}
}
remotePath := args[0]
// Use download.Path because a glob matching a single file on the remote will not have the
// correct file name - the filename will contain the globs if we use the path from the user
// On non-Windows systems, filepath.Base will not see backslashes, so we will replace them
// on systems that do not use backslashes as path separators
remotePath := download.Path
if strings.Contains(download.Path, "\\") && string(os.PathSeparator) != "\\" {
remotePath = strings.ReplaceAll(download.Path, "\\", "/")
}
var localPath string
if len(args) == 1 {
localPath = "."
+2 -2
View File
@@ -83,7 +83,7 @@ func processFlags(searchPattern string, insensitive bool, exact bool) string {
return processedSearchPattern
}
func GrepCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []string) {
func GrepCmd(cmd *cobra.Command, con *console.SliverClient, args []string) {
session, beacon := con.ActiveTarget.GetInteractive()
if session == nil && beacon == nil {
return
@@ -152,7 +152,7 @@ func GrepCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []string
}
// printGrep - Print the results from the grep operation to stdout
func printGrep(grep *sliverpb.Grep, searchPattern string, searchPath string, cmd *cobra.Command, con *console.SliverConsoleClient) {
func printGrep(grep *sliverpb.Grep, searchPattern string, searchPath string, cmd *cobra.Command, con *console.SliverClient) {
saveLoot, _ := cmd.Flags().GetBool("loot")
lootName, _ := cmd.Flags().GetString("name")
colorize, _ := cmd.Flags().GetBool("colorize-output")
+4 -7
View File
@@ -29,7 +29,7 @@ import (
"google.golang.org/protobuf/proto"
)
func HeadCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []string, head bool) {
func HeadCmd(cmd *cobra.Command, con *console.SliverClient, args []string, head bool) {
session, beacon := con.ActiveTarget.GetInteractive()
if session == nil && beacon == nil {
return
@@ -63,7 +63,7 @@ func HeadCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []string
} else {
operationName = "bytes"
}
} else if cmd.Flags().Changed("lines") {
} else {
fetchBytes = false
fetchSize, _ = cmd.Flags().GetInt64("lines")
if fetchSize < 0 {
@@ -76,9 +76,6 @@ func HeadCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []string
} else {
operationName = "lines"
}
} else {
con.PrintErrorf("A number of bytes or a number of lines must be specified.")
return
}
ctrl := make(chan bool)
@@ -118,10 +115,10 @@ func HeadCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []string
con.PrintErrorf("Failed to decode response %s\n", err)
return
}
PrintCat(download, cmd, con)
PrintCat(filePath, download, cmd, con)
})
con.PrintAsyncResponse(download.Response)
} else {
PrintCat(download, cmd, con)
PrintCat(filePath, download, cmd, con)
}
}
+7 -9
View File
@@ -27,19 +27,17 @@ import (
"text/tabwriter"
"time"
"google.golang.org/protobuf/proto"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
"github.com/bishopfox/sliver/client/console"
"github.com/bishopfox/sliver/protobuf/clientpb"
"github.com/bishopfox/sliver/protobuf/sliverpb"
"github.com/bishopfox/sliver/util"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
"google.golang.org/protobuf/proto"
)
// LsCmd - List the contents of a remote directory
func LsCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []string) {
// LsCmd - List the contents of a remote directory.
func LsCmd(cmd *cobra.Command, con *console.SliverClient, args []string) {
session, beacon := con.ActiveTarget.GetInteractive()
if session == nil && beacon == nil {
return
@@ -75,8 +73,8 @@ func LsCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []string)
}
}
// PrintLs - Display an sliverpb.Ls object
func PrintLs(ls *sliverpb.Ls, flags *pflag.FlagSet, con *console.SliverConsoleClient) {
// PrintLs - Display an sliverpb.Ls object.
func PrintLs(ls *sliverpb.Ls, flags *pflag.FlagSet, con *console.SliverClient) {
if ls.Response != nil && ls.Response.Err != "" {
con.PrintErrorf("%s\n", ls.Response.Err)
return
+6 -7
View File
@@ -20,16 +20,15 @@ package filesystem
import (
"context"
"github.com/spf13/cobra"
"google.golang.org/protobuf/proto"
"github.com/bishopfox/sliver/client/console"
"github.com/bishopfox/sliver/protobuf/clientpb"
"github.com/bishopfox/sliver/protobuf/sliverpb"
"github.com/spf13/cobra"
"google.golang.org/protobuf/proto"
)
// MemfilesAddCmd - Add memfile
func MemfilesAddCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []string) {
// MemfilesAddCmd - Add memfile.
func MemfilesAddCmd(cmd *cobra.Command, con *console.SliverClient, args []string) {
session, beacon := con.ActiveTarget.GetInteractive()
if session == nil && beacon == nil {
return
@@ -57,8 +56,8 @@ func MemfilesAddCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args [
}
}
// PrintAddMemfile - Print the memfiles response
func PrintAddMemfile(memfilesAdd *sliverpb.MemfilesAdd, con *console.SliverConsoleClient) {
// PrintAddMemfile - Print the memfiles response.
func PrintAddMemfile(memfilesAdd *sliverpb.MemfilesAdd, con *console.SliverClient) {
if memfilesAdd.Response != nil && memfilesAdd.Response.Err != "" {
con.PrintErrorf("%s\n", memfilesAdd.Response.Err)
return
+6 -7
View File
@@ -25,17 +25,16 @@ import (
"text/tabwriter"
"time"
"github.com/spf13/cobra"
"google.golang.org/protobuf/proto"
"github.com/bishopfox/sliver/client/console"
"github.com/bishopfox/sliver/protobuf/clientpb"
"github.com/bishopfox/sliver/protobuf/sliverpb"
"github.com/bishopfox/sliver/util"
"github.com/spf13/cobra"
"google.golang.org/protobuf/proto"
)
// MemfilesListCmd - List memfiles
func MemfilesListCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []string) {
// MemfilesListCmd - List memfiles.
func MemfilesListCmd(cmd *cobra.Command, con *console.SliverClient, args []string) {
session, beacon := con.ActiveTarget.GetInteractive()
if session == nil && beacon == nil {
return
@@ -63,8 +62,8 @@ func MemfilesListCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args
}
}
// PrintMemfiles - Display an sliverpb.Ls object
func PrintMemfiles(ls *sliverpb.Ls, con *console.SliverConsoleClient) {
// PrintMemfiles - Display an sliverpb.Ls object.
func PrintMemfiles(ls *sliverpb.Ls, con *console.SliverClient) {
if ls.Response != nil && ls.Response.Err != "" {
con.PrintErrorf("%s\n", ls.Response.Err)
return
Loaded 100 of 4186 files, more files were not shown because too many files have changed in this diff. Show more