Compare commits

...
Author SHA1 Message Date
Raf f67e96e1de Sliver Protobuf updates 2023-12-29 09:01:20 -05:00
Andrew Klaus 1301cf6027 Referencing final array elements for mountinfo 2023-12-27 10:33:08 -07:00
Andrew Klaus ce72711bc3 Adding linux mount command 2023-12-22 12:31:52 -07:00
Raf b732ce1daa Merge branch 'master' into mount-command 2023-12-22 08:32:25 -05:00
Ronan Kervella a84f13e8a0 Merge pull request #1424 from C-Sto/extensionargs
Extensionargs
2023-12-20 16:05:03 -08:00
Raf 218e3c53b1 Adding the mount command and the implementation for Windows implants 2023-12-20 11:43:09 -05: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
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
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
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
Joe 79b2b9da1f Merge branch 'master' into vendor/sqlite 2023-11-16 15:36:31 -08:00
moloch-- e0a3114692 Update sqlite deps 2023-11-16 16:35:34 -07:00
Joe 4bbe8f0976 Merge pull request #1460 from BishopFox/vendor/wg
Update Wireguard Deps
2023-11-16 15:31:02 -08:00
Joe 699b9bbe9b Merge pull request #1378 from BishopFox/fix/kill
Fix kill for sessions
2023-11-16 15:14:31 -08:00
moloch-- a6b583f538 Re-add forwarding to custom netstack 2023-11-16 15:57:49 -07:00
moloch-- 2ac22d137a Re-add custom netstack 2023-11-16 15:43:28 -07:00
moloch-- 579252f531 Downgrade x/crypo/ssh to v0.13.0 2023-11-16 15:24:01 -07:00
moloch-- 6558d53cc0 Update implant crypto/ssh 2023-11-16 14:40:44 -07:00
moloch-- d364f30ce6 Update crypto/ssh 2023-11-16 14:20:42 -07:00
moloch-- 499df6f923 Use upstream netstack 2023-11-16 14:09:39 -07:00
moloch-- 5a3053fe7a Use go branch of gvisor 2023-11-16 13:44:30 -07:00
moloch-- 9d08e4ca9f Update implant wireguard, tailscale, and gvisor 2023-11-16 13:31:46 -07:00
moloch-- ed9d8274f8 Update wireguard, tailscale, and gvisor 2023-11-16 13:20:38 -07:00
moloch-- 5efd05fcdf Switch to slim image for prod 2023-11-16 11:41:49 -07:00
moloch-- 9e95f3dbdc Specify container platform 2023-11-16 11:24:01 -07:00
Joe 3bbd4a230e Merge pull request #1458 from bman46/docker-optimization
Optimize Dockerfile
2023-11-16 09:25:35 -08:00
Joe ee2a72ff5f Merge branch 'master' into fix/kill 2023-11-16 07:30:29 -08:00
Joe 86507dc5c5 Merge pull request #1459 from BishopFox/fix_external_build
adapt external builds to support http c2 configuration and new build …
2023-11-16 07:29:36 -08:00
Tim Makram Ghatas d2b43ebb9f adapt external builds to support http c2 configuration and new build system 2023-11-15 23:46:28 +01:00
Joe 29dde09bdc Merge branch 'master' into docker-optimization 2023-11-14 11:51:36 -08:00
Joe 3a0ce8b890 Merge pull request #1402 from BishopFox/cc07dependabot/github_actions/actions/checkout-4
Bump actions/checkout from 3 to 4
2023-11-14 11:51:21 -08:00
Joe 623579affb Merge branch 'master' into cc07dependabot/github_actions/actions/checkout-4 2023-11-14 11:50:18 -08:00
Joe 632eacf3fd Merge pull request #1457 from BishopFox/allow_selective_staging
Allow selective staging
2023-11-14 11:49:55 -08:00
Brendan McShane ce6402a5d8 Fix comment 2023-11-14 10:57:33 -05:00
Brendan McShane 6da2209509 Update docker file 2023-11-14 10:57:33 -05:00
Joe 6918743f03 Merge branch 'master' into allow_selective_staging 2023-11-14 07:55:35 -08:00
Joe 5d333af798 Merge pull request #1456 from BishopFox/fix_profile_update
allow profile updates
2023-11-14 07:55:22 -08:00
Tim Makram Ghatas 68cddc1de2 Merge branch 'master' into allow_selective_staging 2023-11-13 23:54:47 +01:00
Tim Makram Ghatas c681fa68f3 Merge branch 'master' into fix_profile_update 2023-11-13 23:54:19 +01:00
Tim Makram Ghatas 8a04d8d882 removed unused http staging code and http stage flag. Added a new subcommand to implants, stage that allows to select which builds to exposed externally. ImplantBuilds now have a stage field marking whether they are available externally or not. 2023-11-13 23:53:05 +01:00
Joe b973e286cb Merge pull request #1455 from BishopFox/go/v1.21.4
Go/v1.21.4
2023-11-13 13:59:40 -08:00
Tim Makram Ghatas 49f9cf0963 Merge branch 'master' into fix_profile_update 2023-11-13 22:37:33 +01:00
Tim Makram Ghatas 5ffdcf8a7a allow profile updates 2023-11-13 22:36:07 +01:00
Joe 01656894ee Merge branch 'master' into go/v1.21.4 2023-11-13 11:16:10 -08:00
Joe d994f76920 Merge pull request #1454 from BishopFox/v1.6.0/http-c2
V1.6.0/http c2
2023-11-13 11:15:37 -08:00
Tim Makram Ghatas 6e40fcdf91 fix binary generation tests 2023-11-13 19:31:59 +01:00
Tim Makram Ghatas b6df1e2981 update go.mod and update WGImplantPrivKey reference to build object 2023-11-13 18:23:06 +01:00
moloch-- 56b84e44f3 Update makefile to require go 1.21.x 2023-11-10 18:36:40 -07:00
moloch-- 96896a7442 Go 1.21.4 2023-11-10 18:33:10 -07:00
moloch-- ac9b293942 Fix website pkg tests and MapContent, refactor naming 2023-11-10 16:53:11 -07:00
moloch-- ebf68f6b61 Fix println, dropped err 2023-11-10 16:27:21 -07:00
Tim Makram Ghatas e25e228f5c remove server side imports from utils package 2023-11-10 23:47:53 +01:00
Tim Makram Ghatas b84092b24b renamed resourceIDs 2023-11-10 23:34:12 +01:00
moloch-- eddfa20684 Move minisign to util/ 2023-11-10 15:31:35 -07:00
moloch-- 21468a6310 Duplicate minisign dep to client/ 2023-11-10 15:22:04 -07:00
Ronan Kervella 8c1194283b Merge branch 'master' into upload-dir 2023-11-10 14:05:05 -08:00
Tim Makram Ghatas 48d7e7217c add option to save stage to disk 2023-11-10 22:39:26 +01:00
Tim Makram Ghatas a19fddfdba merge master 2023-11-10 22:36:04 +01:00
Ronan Kervella 28397eb7a9 Merge branch 'master' into extensionargs 2023-11-10 13:02:13 -08:00
Ronan Kervella f944d24dc3 Merge pull request #1453 from D00Movenok/fix/implant_macos_proxy_log
Fix: removed implant macos and generic proxy logs when debug is disabled
2023-11-10 13:01:56 -08:00
D00Movenok 917586f2cc fix: removed implant macos and generic proxy logs when debug is disabled 2023-11-10 23:19:31 +03:00
Tim Makram Ghatas 4e56c69cfe implants now also display whether compression/encryption was used in display 2023-11-09 18:13:30 +01:00
Tim Makram Ghatas e6487fb01d implants command now displays resource id's 2023-11-09 17:16:00 +01:00
Tim Makram Ghatas d88011e140 remove http/s stage listeners 2023-11-09 16:44:15 +01:00
Tim Makram Ghatas 2c5c3ac997 Move stage generation server side and add a new subcommand for profiles to generate them 2023-11-09 01:41:14 +01:00
Tim Makram Ghatas 9178f6ea5b move keys to implant build (WG, MTLS and ECC) 2023-11-08 17:29:22 +01:00
Raf 8ebd7da9a8 Merge branch 'master' into upload-dir 2023-11-08 08:15:02 -05:00
Tim Makram Ghatas a691484f47 fix config reuse bug and duplicate c2 object creation 2023-11-07 01:08:37 +01:00
Tim Makram Ghatas 3442599ee8 add missing field in implantconfig protobuf 2023-11-06 14:26:16 +01:00
Tim Makram Ghatas d3f40963e3 fixed missing implant config id bug 2023-11-05 00:17:44 +01:00
Tim Makram Ghatas c83a0447b3 allow disabling http payload staging 2023-11-04 23:41:01 +01:00
Joe daaf6e27a2 Merge pull request #1447 from alrs/info-cmd-err
client/command/info: fix dropped errors
2023-11-03 08:59:21 -07:00
Joe 9d1fa0d016 Merge pull request #1445 from BishopFox/fix-1444
Fixing issue with User Agent in Implant Generation
2023-11-03 08:53:29 -07:00
Lars Lehtonen a13d63ee47 client/command/info: fix dropped errors
Signed-off-by: Lars Lehtonen <[email protected]>
2023-11-03 06:04:22 -07:00
Raf 4da9233563 Merge branch 'master' into fix-1444 2023-11-03 06:51:28 -04:00
Joe 16db6033a5 Merge pull request #1446 from luca994/fix-minpath-httpconf
Fixed min_path and max_path settings on http profile customization
2023-11-02 15:48:06 -07:00
Raf c1d1bf7873 Blocking backticks from user agent strings in the config so that we can support other characters that would normally need to be escaped. 2023-11-02 13:29:39 -04:00
Luca 3217ab53fe Fixed min_path and max_path settings on http profile customization 2023-11-02 16:55:41 +01:00
Raf d46e43dbd6 Changing the user agent declaration to use a different template that allows for other characters that would have to be escaped 2023-11-02 10:48:20 -04:00
Raf 070bac1bf3 Fixing issue #1444: making User Agent a string literal in generation code 2023-11-01 12:52:42 -04: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
Tim Makram Ghatas 9a63b64a39 remove implant builds when implant profiles are removed 2023-10-31 18:24:54 +01:00
Joe 9894d79dbf Merge pull request #1443 from BishopFox/1684dependabot/go_modules/google.golang.org/grpc-1.59.0
Bump google.golang.org/grpc from 1.56.1 to 1.59.0
2023-10-31 09:58:21 -07:00
Tim Makram Ghatas 4b0190b08c check implant exists before freeing up resources 2023-10-31 17:36:38 +01:00
dependabot[bot] 80dea74d97 Bump google.golang.org/grpc from 1.56.1 to 1.59.0
Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.56.1 to 1.59.0.
- [Release notes](https://github.com/grpc/grpc-go/releases)
- [Commits](https://github.com/grpc/grpc-go/compare/v1.56.1...v1.59.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]>
2023-10-31 15:29:09 +00:00
Joe db5d12d4b6 Merge pull request #1425 from BishopFox/ac46dependabot/go_modules/tailscale.com-1.50.1
Bump tailscale.com from 1.44.0 to 1.50.1
2023-10-31 08:26:27 -07:00
Joe 1c4503c1cc Merge branch 'master' into ac46dependabot/go_modules/tailscale.com-1.50.1
Signed-off-by: Joe <[email protected]>
2023-10-31 07:47:00 -07:00
Joe 13fb854b4e Merge pull request #1407 from BishopFox/heads-and-tails
Head and Tail commands
2023-10-31 07:46:30 -07:00
Raf d0574ffe48 Merge branch 'heads-and-tails' of ssh://github.com/BishopFox/sliver into heads-and-tails 2023-10-31 09:42:24 -04:00
Raf ba6b53d569 Merge branch 'master' into heads-and-tails 2023-10-31 09:40:55 -04:00
Tim Makram Ghatas 749c3b9247 fixed profile removal crash and automatically delete profile implantconfig 2023-10-31 12:46:12 +01:00
Tim Makram Ghatas 79ca1c9f72 update protobuf definitions for generate stage rpc call 2023-10-31 12:21:01 +01:00
Tim Makram Ghatas 7a6f2c3b53 resource id's no longer need to be prime 2023-10-31 11:59:17 +01:00
Joe e4ade4e8c9 Merge pull request #1440 from alrs/filesystem-cmd-err
client/command/filesystem: fix dropped error
2023-10-26 16:10:17 -07:00
Joe f4beecdc8a Merge branch 'master' into filesystem-cmd-err
Signed-off-by: Joe <[email protected]>
2023-10-26 08:38:32 -07:00
Joe 78627a6eff Merge pull request #1437 from testwill/ioutil
chore: remove refs to deprecated io/ioutil
2023-10-25 18:35:16 -07:00
Joe 77f2b7fd48 Merge branch 'master' into ioutil
Signed-off-by: Joe <[email protected]>
2023-10-25 16:37:55 -07:00
Lars Lehtonen 6f043f8406 client/command/filesystem: fix dropped error
Signed-off-by: Lars Lehtonen <[email protected]>
2023-10-24 15:14:47 -07:00
Tim Makram Ghatas 9870c254f6 remove save stager rpc call 2023-10-24 23:48:32 +02:00
Tim Makram Ghatas 99281bad0f removed name from implantconfig, implant names are only tied to builds 2023-10-24 23:41:37 +02:00
Tim Makram Ghatas 02d1eb5ba4 refactored generate rpc 2023-10-24 20:44:43 +02:00
Tim Makram Ghatas fce86738cc fix incorrect object reference error 2023-10-24 20:40:14 +02:00
Tim Makram Ghatas b723194931 fix implant config generation for stagers 2023-10-23 00:57:10 +02:00
Tim Makram Ghatas 7dc631077a renamed db functions for consistency 2023-10-22 21:30:16 +02:00
Tim Makram Ghatas e204247009 move implantbuild models to protobuf struct 2023-10-22 21:02:00 +02:00
Tim Makram Ghatas 504e5c7b32 check port is not in use before spawning listener 2023-10-22 17:47:39 +02:00
Tim Makram Ghatas fdec3cb317 Started moving all use of models.* structs to the models and helpers file. The goal of this commit is to eventually only use protobuf accross the entire project, in order to avoid mixing different structs for the same datatype accross the codebase. This also will allow switching backend if the project eventually moves away from an sql backend. 2023-10-22 15:37:21 +02:00
Ronan Kervella 342ed489f3 Merge branch 'master' into multiextensions 2023-10-20 10:30:30 -07:00
Ronan Kervella b7d0dcc5dd Merge pull request #1422 from BishopFox/grep
Adding the grep command
2023-10-20 10:23:46 -07:00
guoguangwu 0b7596373a fix: typo
Signed-off-by: guoguangwu <[email protected]>
2023-10-20 09:04:54 +08:00
Ronan Kervella 6b88a01fad Merge branch 'master' into upload-dir 2023-10-19 15:31:56 -07:00
Ronan Kervella d58c7b3bca Merge branch 'master' into heads-and-tails 2023-10-19 15:15:03 -07:00
Ronan Kervella c23a542233 Merge branch 'master' into grep 2023-10-19 15:12:56 -07:00
guoguangwu 5b415c5aa1 chore: remove refs to deprecated io/ioutil
Signed-off-by: guoguangwu <[email protected]>
2023-10-19 20:06:45 +08:00
Tim Makram Ghatas 6c77151b80 started moving c2profile to only use protobuf, fixed bug in http mainhandler and c2profile command now also displays poll extension 2023-10-17 00:52:13 +02:00
dependabot[bot] 5e7507ba4d Bump tailscale.com from 1.44.0 to 1.50.1
Bumps [tailscale.com](https://github.com/tailscale/tailscale) from 1.44.0 to 1.50.1.
- [Release notes](https://github.com/tailscale/tailscale/releases)
- [Commits](https://github.com/tailscale/tailscale/compare/v1.44.0...v1.50.1)

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

Signed-off-by: dependabot[bot] <[email protected]>
2023-10-16 16:04:58 +00:00
Joe 06d5a934be Merge pull request #1431 from BishopFox/35abdependabot/go_modules/golang.org/x/net-0.17.0
Bump golang.org/x/net from 0.11.0 to 0.17.0
2023-10-16 09:03:18 -07:00
Ronan Kervella 5e5e0df4ec Merge branch 'master' into multiextensions 2023-10-16 09:03:17 -07:00
Joe e804605d05 Merge pull request #1432 from BishopFox/go/v1.21.3
Go 1.21.3
2023-10-16 08:55:20 -07:00
Joe 35eac6f582 Merge branch 'master' into grep 2023-10-16 07:02:11 -07:00
Tim Makram Ghatas ff382e4029 Refactor websites to only use protobuf objects 2023-10-15 22:13:16 +02:00
Joe 5a5e8d2a04 Merge pull request #1420 from ssepi0l-pv/patch-1
Update install
2023-10-15 06:39:07 -07:00
Tim Makram Ghatas 05a69474e5 modify backend to server arbitrary stages for a given implant configuration 2023-10-15 08:22:49 +02:00
moloch-- 4516e4994d Garble v1.21.3 2023-10-13 16:24:34 +02:00
ssepi0l-pv 843e287f0c Merge branch 'master' into patch-1 2023-10-13 09:36:50 -03:00
Tim Makram Ghatas 47f19d477d switch to referencing builds by resource ID instead of profiles in staging requests and prepare rpc call to save stager builds 2023-10-13 12:01:07 +02:00
moloch-- aee2f78718 Go 1.21.3 2023-10-12 15:21:04 +02:00
dependabot[bot] 2edb14baa1 Bump golang.org/x/net from 0.11.0 to 0.17.0
Bumps [golang.org/x/net](https://github.com/golang/net) from 0.11.0 to 0.17.0.
- [Commits](https://github.com/golang/net/compare/v0.11.0...v0.17.0)

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

Signed-off-by: dependabot[bot] <[email protected]>
2023-10-11 22:50:09 +00:00
Ronan Kervella a2208280a0 Merge pull request #1430 from alrs/console-err
client/console: fix dropped error
2023-10-11 12:06:27 -07:00
Lars Lehtonen 0834b725fd client/console: fix dropped error 2023-10-11 09:44:18 -07:00
Tim Makram Ghatas a0fa261e32 display profile nonce 2023-10-08 21:03:08 +02:00
Tim Makram Ghatas c578c426dc fix stager listener url generationerror 2023-10-08 21:02:47 +02:00
Tim Makram Ghatas da9b72c72c modify stagerhandler to serve valid profile (without stage-listener mods) when the correct stager id is used as a nonce 2023-10-08 20:13:16 +02: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
Tim Makram Ghatas cb8170c27b change naming and type of encoder id's 2023-10-06 16:42:38 +02:00
Tim Makram Ghatas 03cfab5276 Merge branch 'master' into v1.6.0/http-c2 2023-10-06 16:16:38 +02:00
Tim Makram Ghatas 114ad3e6a1 remove resource id on profile deletion 2023-10-06 16:10:41 +02:00
Tim Makram Ghatas 3d6a8dda52 switch to uin64[] instead of int[] 2023-10-06 15:47:41 +02:00
Tim Makram Ghatas ea1fbf1d74 save implant id to profile during profile creation 2023-10-06 12:06:25 +02:00
Tim Makram Ghatas 49b8cd299a embed encoder id's during code rendering 2023-10-06 11:48:13 +02:00
Tim Makram Ghatas b8dcf756f7 generate encoder id's on server setup for backend 2023-10-06 11:04:08 +02:00
Tim Makram Ghatas 0b9d7cc603 added resource id queries and save 2023-10-04 23:02:05 +02:00
Tim Makram Ghatas 3ba3cf1177 create resourceID table 2023-10-04 22:56:28 +02: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 9c87c59ec6 grep: Print error messages from files that could not be read 2023-10-04 10:37:56 -04:00
Raf dd249088c3 Adding the client implementation for grep 2023-10-04 10:28:54 -04:00
Raf 914354222d Adding the grep command 2023-10-04 10:28:39 -04:00
Raf efe747b8aa Adding the ability to upload directories 2023-10-04 10:13:04 -04:00
ssepi0l-pv 369406928c Update install
Hello!
I wanted to commit these changes because I'd love to see official support for Arch Linux. I modified this script and installed Sliver on my system using it, so I know it works. Nevertheless, please do check it and try it yourselves! :)

Signed-off-by: ssepi0l-pv <[email protected]>
2023-10-04 09:40:47 -03:00
Tim Makram Ghatas f6ac166314 display c2 profile in profile details 2023-10-03 14:22:06 +02:00
Tim Makram Ghatas 3da9ffb7d3 added c2 profile flag to profile creation 2023-10-03 14:19:38 +02: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
Tim Makram Ghatas 01c813148b added watchtower configuration import/deletion/view 2023-09-29 13:32:30 +02:00
Tim Makram Ghatas 7fce95e707 allow overwriting c2 profiles on the fly 2023-09-28 18:19:11 +02:00
Ronan Kervella 84aed0720f Merge branch 'master' into multiextensions 2023-09-27 10:53:29 -07:00
Joe 71ba959e12 Merge branch 'master' into heads-and-tails 2023-09-27 10:50:00 -07:00
Joe 5d40d41105 Merge pull request #1416 from BishopFox/e20adependabot/go_modules/github.com/klauspost/compress-1.17.0
Bump github.com/klauspost/compress from 1.16.6 to 1.17.0
2023-09-27 10:49:15 -07:00
Tim Makram Ghatas 237663be19 move job restart on profile import client side 2023-09-26 00:13:08 +02:00
Ronan Kervella b212e0fb99 Merge branch 'master' into multiextensions 2023-09-25 11:14:16 -07:00
Tim Makram Ghatas 96a6efae07 restart http/s listeners on c2 profile import 2023-09-25 12:35:02 +02:00
dependabot[bot] 3561461547 Bump github.com/klauspost/compress from 1.16.6 to 1.17.0
Bumps [github.com/klauspost/compress](https://github.com/klauspost/compress) from 1.16.6 to 1.17.0.
- [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.16.6...v1.17.0)

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

Signed-off-by: dependabot[bot] <[email protected]>
2023-09-25 03:49:33 +00:00
Joe 1d9d5cf85a Merge branch 'master' into cc07dependabot/github_actions/actions/checkout-4 2023-09-20 20:34:14 -07:00
Tim Makram Ghatas e70a022981 add check for duplicate stager extension and duplicate c2 profile name 2023-09-18 22:07:44 +02:00
Ronan Kervella b0c3549b08 Merge branch 'master' into fix/kill 2023-09-18 12:51:41 -07:00
Tim Makram Ghatas d924d80ddb added dropdown to choose c2 profile 2023-09-18 21:08:59 +02:00
Joe b3acf2db1f Merge branch 'master' into heads-and-tails 2023-09-17 07:59:40 -07:00
Joe a670538a77 Merge pull request #1409 from BishopFox/download-filter-fix
Fix filters in the download command
2023-09-17 07:59:28 -07:00
Raf d6ea4794b7 Removed a check from the implant download code that broke filters 2023-09-15 09:10:42 -04:00
Tim Makram Ghatas 7b67ec872e save profile to database on import 2023-09-14 23:51:59 +02:00
Raf a2bbaa095e Fixing typo in tail command help 2023-09-14 12:05:20 -04:00
Tim Makram Ghatas e5a01ae244 moved c2profile struct to client assets 2023-09-14 17:31:55 +02:00
Tim Makram Ghatas 4bcefdddb5 fix circular dependency 2023-09-14 17:24:54 +02:00
Raf 8e64ab288d Adding the head and tail commands, fixing a small issue with download 2023-09-14 10:32:54 -04:00
Tim Makram Ghatas 1bba3532af fix profile parsing errors 2023-09-13 20:09:37 +02:00
Tim Makram Ghatas 002e38e0ac Merge branch 'master' into v1.6.0/http-c2 2023-09-13 19:18:23 +02:00
Tim Makram Ghatas 99817a5f35 implemented c2 profile import and display 2023-09-13 19:11:24 +02:00
Tim Makram Ghatas 4921fa4fcf display implant c2 profile in implants command 2023-09-13 14:35:57 +02:00
dependabot[bot] b044a4584b 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-09-11 03:13:23 +00:00
Tim Makram Ghatas eccc31f945 fix regression, http listener now uses correct port, and http headers are set when an associated profile can be found 2023-09-07 23:53:33 +02:00
Tim Makram Ghatas f2b42211d2 remove error handling statement 2023-09-06 14:54:10 +02:00
Tim Makram Ghatas b1ba761fff update handler to select session cookie based on profile 2023-09-04 23:36:18 +02:00
Tim Makram Ghatas 580d5128ba added main request handler for http profiles 2023-09-04 23:22:56 +02:00
Tim Makram Ghatas 67c519e8d6 add autocomplete for c2profile parameter during generation 2023-09-04 21:51:33 +02:00
Tim Makram Ghatas 4f9851215e merged master into branch 2023-09-04 20:41:33 +02:00
Joe f32d9a91ee Merge pull request #1399 from SpadesA99/SpadesA99-patch-1
Fix the process handle leak when using ps command on Windows
2023-09-01 09:28:50 -05:00
SpadesA99 f9c5daec39 Fix the process handle leak when using ps command on Windows
Signed-off-by: SpadesA99 <[email protected]>
2023-09-01 10:18:45 +08:00
Ronan Kervella b3ab5ea62e Merge branch 'master' into multiextensions 2023-08-31 10:15:36 -07:00
Ronan Kervella f623b0cdce Merge pull request #1398 from realalexandergeorgiev/realalexandergeorgiev-patch-2
Update ps.go
2023-08-31 08:44:35 -07:00
Alexander Georgiev 9b5d4c3bab Update ps.go
Added more MDE processes

Signed-off-by: Alexander Georgiev <[email protected]>
2023-08-31 15:13:53 +02:00
C-Sto 9d4486f906 multimanifest extension support 2023-08-31 10:57:27 +08:00
Tim Makram Ghatas 29c2c9df76 merge master into branch 2023-08-30 19:19:50 +02:00
Tim Makram Ghatas 58b4596598 merged 1.6 master into branch 2023-08-30 14:34:47 +02:00
Joe a9f885a919 Merge pull request #1382 from BishopFox/go/v1.21.0
Go v1.21.0
2023-08-09 19:02:52 -05:00
moloch-- 5a532f77dc Go v1.21.0 2023-08-09 15:58:36 -07:00
Joe 375f6fd235 Merge pull request #1381 from BishopFox/cybereason
Added Cybereason ActiveProbe to known processes
2023-08-09 15:45:24 -05:00
c2biz 0a32ca109d Added Cybereason ActiveProbe to known processes 2023-08-09 16:01:03 -04:00
Joe d048427ebf Merge pull request #1284 from rwincey/notxt_dns
Notxt dns
2023-08-08 18:37:58 -05:00
Joe d22579c204 Merge pull request #1374 from BishopFox/mtls/lencheck
Add basic len check to mtls conn
2023-08-08 18:37:29 -05:00
Ronan Kervella fb5bd84811 Merge branch 'master' into fix/kill 2023-08-08 11:14:23 -07:00
Joe 1e79af3d89 Merge pull request #1375 from BishopFox/87c0dependabot/go_modules/github.com/tetratelabs/wazero-1.3.1
Bump github.com/tetratelabs/wazero from 1.2.1 to 1.3.1
2023-08-08 12:09:15 -05:00
Joe f018f86522 Merge branch 'master' into 87c0dependabot/go_modules/github.com/tetratelabs/wazero-1.3.1 2023-08-08 12:08:58 -05:00
Joe 584cacb7da Merge pull request #1377 from TheDuchy/master
Add the ability to generate .exe MSF stagers from Sliver
2023-08-08 12:08:13 -05:00
Ronan Kervella 714ab96270 Merge branch 'master' into mtls/lencheck 2023-08-08 09:59:30 -07:00
rkervella ae8444fc75 fix kill for sessions 2023-08-08 09:28:52 -07:00
duchy c7a2bbc46b Added ability to generate .exe stagers from MSF 2023-08-08 13:26:27 +02:00
dependabot[bot] 4458911e5c Bump github.com/tetratelabs/wazero from 1.2.1 to 1.3.1
Bumps [github.com/tetratelabs/wazero](https://github.com/tetratelabs/wazero) from 1.2.1 to 1.3.1.
- [Release notes](https://github.com/tetratelabs/wazero/releases)
- [Commits](https://github.com/tetratelabs/wazero/compare/v1.2.1...v1.3.1)

---
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]>
2023-08-07 03:50:35 +00:00
Joe 477df0eac9 Merge pull request #1335 from BishopFox/b6e0dependabot/go_modules/golang.org/x/crypto-0.11.0
Bump golang.org/x/crypto from 0.10.0 to 0.11.0
2023-08-04 15:50:22 -05:00
Joe 22286fdcdd Merge branch 'master' into b6e0dependabot/go_modules/golang.org/x/crypto-0.11.0
Signed-off-by: Joe <[email protected]>
2023-08-04 15:50:13 -05:00
Joe 150b62a0aa Merge pull request #1373 from BishopFox/fix/windows-assets-filepath
Use path.Join for embedded fs instead of filepath.Join
2023-08-04 15:47:44 -05:00
rkervella 270e9f2c5f Use path.Join for embedded fs instead of filepath.Join 2023-08-04 12:59:55 -07:00
Joe ce81ce5de0 Merge pull request #1372 from BishopFox/go/v1.20.7
Go 1.20.7
2023-08-04 09:13:05 -05:00
moloch-- 388b371573 Add basic len check to mtls conn 2023-08-03 17:32:57 -07:00
moloch-- a4425c169e Update go 2023-08-03 17:03:07 -07:00
Joe fd0e54c02c Merge branch 'master' into notxt_dns 2023-08-03 18:57:50 -05:00
Joe 59212f06fd Merge pull request #1339 from BishopFox/e3bddependabot/go_modules/golang.org/x/sys-0.10.0
Bump golang.org/x/sys from 0.9.0 to 0.10.0
2023-08-03 18:57:09 -05:00
Joe 0140bc2b8f Merge branch 'master' into e3bddependabot/go_modules/golang.org/x/sys-0.10.0 2023-08-03 18:56:54 -05:00
Ronan Kervella 4faaa4c075 Merge pull request #1368 from SpadesA99/master
Fix CP command file occupation
2023-08-01 18:51:13 -07:00
SpadesA99 ef1e12e6d4 Fix CP command file occupation
Signed-off-by: SpadesA99 <[email protected]>
2023-08-01 18:04:31 +08:00
Ronan Kervella 7741b0373f Merge branch 'master' into notxt_dns 2023-07-28 11:09:44 -07:00
Joe 4f2767ab59 Merge pull request #1356 from rarFood/master
fix 'gpg: invalid armor header'
2023-07-23 17:18:53 -05:00
rarFood 68f78e791f fix 'gpg: invalid armor header' 2023-07-21 11:21:05 -04:00
Ronan Kervella d28bac4259 Merge branch 'master' into e3bddependabot/go_modules/golang.org/x/sys-0.10.0 2023-07-19 08:35:23 -07:00
Ronan Kervella 00197deefb Merge branch 'master' into b6e0dependabot/go_modules/golang.org/x/crypto-0.11.0 2023-07-19 08:33:47 -07:00
Ronan Kervella 0bfbe9ecd4 Merge pull request #1350 from n3rada/install_script
Enhance the `install` script
2023-07-19 08:27:30 -07:00
Joe 88ac55a2f7 Merge branch 'master' into install_script 2023-07-16 08:19:40 -05:00
Ronan Kervella a1c19bc745 Merge pull request #1352 from xinhuang/pr/no-http-fallback-master
Add option to disable connect to tcp/80 when tcp/443 not reachable
2023-07-13 11:24:20 -07:00
Xin Huang 5a39e253bb Add no-fallback=true parameter for https beacons so they won't connect to TCP 80 if TCP 443 isn't reachable 2023-07-14 01:08:47 +09:00
n3rada 3b8912df4f Enhance the install script 2023-07-13 00:04:29 +02:00
Ronan Kervella 452ce12e9f Merge pull request #1346 from Paradoxis/feature/added-copy-command
Added a copy file command
2023-07-12 10:34:03 -07:00
Ronan Kervella aed28b0ff1 Merge branch 'master' into feature/added-copy-command 2023-07-12 09:21:18 -07:00
Ronan Kervella a2c3263619 Merge pull request #1345 from BishopFox/fix/pstree-1.6
Fix pstree (v1.6)
2023-07-12 08:49:33 -07:00
Paradoxis 300c2f7851 Titlecased copy message 2023-07-12 00:06:31 +02:00
Paradoxis b1d41f1032 Added a check to ensure two arguments are passed to CpCmd 2023-07-12 00:01:39 +02:00
Paradoxis 9054d11749 Moved constants to the end 2023-07-12 00:01:30 +02:00
Paradoxis c1f0b32c93 Added a copy file command 2023-07-11 23:55:00 +02:00
Ronan Kervella a3ecf3d593 Merge branch 'master' into fix/pstree-1.6 2023-07-11 14:23:49 -07:00
rkervella 1a43e70fd1 Fix pstree 2023-07-11 12:25:23 -07:00
Ronan Kervella 1fc7d881b2 Merge pull request #1341 from BishopFox/upload-fixes
Upload command: Changes to remote path specification
2023-07-11 08:43:26 -07:00
Raf 27254a2d89 upload: Fixing panic when remote path not specified, allowing for specification of a directory for remote path 2023-07-10 16:49:03 -04:00
dependabot[bot] 19573c9f20 Bump golang.org/x/sys from 0.9.0 to 0.10.0
Bumps [golang.org/x/sys](https://github.com/golang/sys) from 0.9.0 to 0.10.0.
- [Commits](https://github.com/golang/sys/compare/v0.9.0...v0.10.0)

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

Signed-off-by: dependabot[bot] <[email protected]>
2023-07-10 03:36:14 +00:00
dependabot[bot] 0f11532e37 Bump golang.org/x/crypto from 0.10.0 to 0.11.0
Bumps [golang.org/x/crypto](https://github.com/golang/crypto) from 0.10.0 to 0.11.0.
- [Commits](https://github.com/golang/crypto/compare/v0.10.0...v0.11.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]>
2023-07-10 03:35:37 +00:00
Joe c75cf89def Merge branch 'master' into notxt_dns 2023-07-08 11:27:04 -05:00
Joe 2c6cf1e96b Merge pull request #1332 from stephenbradshaw/stager-rc4-support
Add RC4 support to shellcode stager
2023-07-08 11:26:13 -05:00
Stephen Bradshaw bd4d5eca77 Add RC4 support to shellcode stager 2023-07-08 14:53:37 +10:00
Joe 514da3a682 Merge pull request #1324 from BishopFox/a8c6dependabot/go_modules/gorm.io/gorm-1.25.2
Bump gorm.io/gorm from 1.25.2-0.20230530020048-26663ab9bf55 to 1.25.2
2023-07-03 00:38:33 -05:00
Joe 5e691bdf25 Merge branch 'master' into a8c6dependabot/go_modules/gorm.io/gorm-1.25.2 2023-07-03 00:38:26 -05:00
Joe 0eb997388a Merge pull request #1325 from BishopFox/6595dependabot/go_modules/google.golang.org/protobuf-1.31.0
Bump google.golang.org/protobuf from 1.30.0 to 1.31.0
2023-07-03 00:38:10 -05:00
dependabot[bot] 33e6273c62 Bump google.golang.org/protobuf from 1.30.0 to 1.31.0
Bumps google.golang.org/protobuf from 1.30.0 to 1.31.0.

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

Signed-off-by: dependabot[bot] <[email protected]>
2023-07-03 03:26:44 +00:00
dependabot[bot] 704d65059f Bump gorm.io/gorm from 1.25.2-0.20230530020048-26663ab9bf55 to 1.25.2
Bumps [gorm.io/gorm](https://github.com/go-gorm/gorm) from 1.25.2-0.20230530020048-26663ab9bf55 to 1.25.2.
- [Release notes](https://github.com/go-gorm/gorm/releases)
- [Commits](https://github.com/go-gorm/gorm/commits/v1.25.2)

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

Signed-off-by: dependabot[bot] <[email protected]>
2023-07-03 03:26:39 +00:00
Joe dee7434bd8 Merge pull request #1323 from BishopFox/go/v1.20.5
Go v1.20.5
2023-07-01 17:33:57 -05:00
moloch-- 8b6b0d7a14 Go v1.20.5 2023-07-01 14:31:55 -07:00
Joe ccf53647b8 Merge pull request #1322 from BishopFox/multiplayer/tailscale
Multiplayer/Tailscale
2023-07-01 11:35:33 -05:00
moloch-- 9e0f9d2fbb Update implant gvisor 2023-07-01 08:46:40 -07:00
Joe dc228a5d2d Merge branch 'master' into multiplayer/tailscale 2023-07-01 10:20:02 -05:00
moloch-- 6bc6f15fd1 Bug fixes to tsnet 2023-07-01 08:19:09 -07:00
moloch-- cb6c8ce4e7 Integrate tsnet option into job mgmt 2023-07-01 07:59:33 -07:00
moloch-- ddf2344e61 Add multiplayer tailscale option, update gvisor 2023-07-01 07:49:24 -07:00
Joe bfacc71048 Merge branch 'master' into notxt_dns 2023-06-29 09:18:11 -05:00
Joe ced8bdda0c Merge pull request #1319 from BishopFox/fix/make-token
Fix make token test
2023-06-29 09:17:50 -05:00
rkervella 78222cb1bc Fix make token test 2023-06-28 15:26:59 -07:00
Joe f99b3cae9c Merge branch 'master' into notxt_dns 2023-06-26 14:26:42 -05:00
Joe 01b370ba44 Merge pull request #1314 from BishopFox/b141dependabot/go_modules/github.com/klauspost/compress-1.16.6
Bump github.com/klauspost/compress from 1.16.5 to 1.16.6
2023-06-26 14:26:15 -05:00
Joe 5b90358328 Merge pull request #1316 from BishopFox/e64fdependabot/go_modules/github.com/AlecAivazis/survey/v2-2.3.7
Bump github.com/AlecAivazis/survey/v2 from 2.3.6 to 2.3.7
2023-06-26 14:26:02 -05:00
Joe f13b11ff52 Merge branch 'master' into b141dependabot/go_modules/github.com/klauspost/compress-1.16.6 2023-06-26 13:57:25 -05:00
Joe af19c97372 Merge pull request #1311 from ActualTrash/taskmany
Add command to task many implants at once
2023-06-26 13:55:49 -05:00
Joe 4f86172543 Merge branch 'master' into taskmany 2023-06-26 13:55:38 -05:00
dependabot[bot] a5c9f53b8a Bump github.com/AlecAivazis/survey/v2 from 2.3.6 to 2.3.7
Bumps [github.com/AlecAivazis/survey/v2](https://github.com/AlecAivazis/survey) from 2.3.6 to 2.3.7.
- [Release notes](https://github.com/AlecAivazis/survey/releases)
- [Commits](https://github.com/AlecAivazis/survey/compare/v2.3.6...v2.3.7)

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

Signed-off-by: dependabot[bot] <[email protected]>
2023-06-26 18:12:14 +00:00
dependabot[bot] 8673552694 Bump github.com/klauspost/compress from 1.16.5 to 1.16.6
Bumps [github.com/klauspost/compress](https://github.com/klauspost/compress) from 1.16.5 to 1.16.6.
- [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.16.5...v1.16.6)

---
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]>
2023-06-26 18:10:56 +00:00
Joe 3a5f4b13a1 Merge pull request #1313 from BishopFox/0530dependabot/go_modules/google.golang.org/grpc-1.56.1
Bump google.golang.org/grpc from 1.56.0 to 1.56.1
2023-06-26 13:05:21 -05:00
Joe f12ba957d4 Merge branch 'master' into taskmany 2023-06-26 12:39:57 -05:00
dependabot[bot] fa4a9cc845 Bump google.golang.org/grpc from 1.56.0 to 1.56.1
Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.56.0 to 1.56.1.
- [Release notes](https://github.com/grpc/grpc-go/releases)
- [Commits](https://github.com/grpc/grpc-go/compare/v1.56.0...v1.56.1)

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

Signed-off-by: dependabot[bot] <[email protected]>
2023-06-26 17:23:45 +00:00
Joe ac66b0726c Merge pull request #1312 from BishopFox/949bdependabot/go_modules/golang.org/x/net-0.11.0
Bump golang.org/x/net from 0.10.0 to 0.11.0
2023-06-26 12:22:00 -05:00
dependabot[bot] c4a35d6850 Bump golang.org/x/net from 0.10.0 to 0.11.0
Bumps [golang.org/x/net](https://github.com/golang/net) from 0.10.0 to 0.11.0.
- [Commits](https://github.com/golang/net/compare/v0.10.0...v0.11.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]>
2023-06-26 04:00:01 +00:00
chase 395e9717b1 Reorganize taskmany code to work with v1.6 cli 2023-06-25 20:06:33 -04:00
chase f89e435e59 Add additional commands to taskmany 2023-06-25 04:06:46 -04:00
chase 1220611e28 Reorganize and gofmt code 2023-06-24 16:35:43 -04:00
chase e452809056 Add filtering capabilities to taskmany 2023-06-24 15:56:34 -04:00
moloch-- b2989e0ea3 Prevent keyex replays 2023-06-20 22:35:27 -07:00
Joe 6bd1108152 Merge branch 'master' into notxt_dns 2023-06-20 16:29:33 -05:00
Joe 37e35dc1bd Merge pull request #1304 from BishopFox/48c8dependabot/go_modules/golang.org/x/crypto-0.10.0
Bump golang.org/x/crypto from 0.9.0 to 0.10.0
2023-06-20 16:29:19 -05:00
Joe 77a9113025 Merge branch 'master' into 48c8dependabot/go_modules/golang.org/x/crypto-0.10.0 2023-06-20 16:29:02 -05:00
moloch-- 47705435f9 Reorg actions 2023-06-20 12:01:45 -07:00
moloch-- 233542e059 Re-add ref guards 2023-06-20 12:00:15 -07:00
Joe 42795b077e Merge branch 'master' into 48c8dependabot/go_modules/golang.org/x/crypto-0.10.0 2023-06-20 13:57:57 -05:00
moloch-- e687d12241 Only check release ref on release 2023-06-20 11:57:42 -07:00
moloch-- f414bfb01e Fix peer key encoding 2023-06-20 11:56:47 -07:00
Joe 6db7861a70 Merge branch 'master' into notxt_dns 2023-06-20 13:56:16 -05:00
Joe 711c56c0b0 Merge branch 'master' into 48c8dependabot/go_modules/golang.org/x/crypto-0.10.0 2023-06-20 13:42:26 -05:00
Joe 2d1ea6192c Merge pull request from GHSA-8jxm-xp43-qh3q
Fix Sliver KEM
2023-06-20 13:30:11 -05:00
moloch-- 24aa3508b3 Regenerate pb 2023-06-20 11:27:49 -07:00
Joe 02de46647d Merge branch 'master' into advisory-fix-1
Signed-off-by: Joe <[email protected]>
2023-06-20 13:26:54 -05:00
dependabot[bot] 829e83008b Bump golang.org/x/crypto from 0.9.0 to 0.10.0
Bumps [golang.org/x/crypto](https://github.com/golang/crypto) from 0.9.0 to 0.10.0.
- [Commits](https://github.com/golang/crypto/compare/v0.9.0...v0.10.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]>
2023-06-20 14:55:50 +00:00
Joe e11f4323a2 Merge pull request #1305 from BishopFox/6f30dependabot/go_modules/github.com/tetratelabs/wazero-1.2.1
Bump github.com/tetratelabs/wazero from 1.2.0 to 1.2.1
2023-06-20 09:54:05 -05:00
Joe 6f7e4401bd Merge pull request #1306 from BishopFox/1efddependabot/go_modules/google.golang.org/grpc-1.56.0
Bump google.golang.org/grpc from 1.55.0 to 1.56.0
2023-06-20 09:53:39 -05:00
Joe 6d32be6d98 Merge pull request #1308 from BishopFox/6e51dependabot/go_modules/golang.org/x/sys-0.9.0
Bump golang.org/x/sys from 0.8.0 to 0.9.0
2023-06-20 09:53:10 -05:00
moloch-- dd98134729 Refactor 2023-06-19 18:23:43 -07:00
moloch-- 4da5deae47 Update vendor/ 2023-06-19 17:54:03 -07:00
moloch-- 1d50db6982 Unit tests pass 2023-06-19 12:28:04 -07:00
moloch-- c718085695 Implemented basic keyex unit tests 2023-06-19 11:19:34 -07:00
dependabot[bot] 466abd1bea Bump golang.org/x/sys from 0.8.0 to 0.9.0
Bumps [golang.org/x/sys](https://github.com/golang/sys) from 0.8.0 to 0.9.0.
- [Commits](https://github.com/golang/sys/compare/v0.8.0...v0.9.0)

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

Signed-off-by: dependabot[bot] <[email protected]>
2023-06-19 04:05:25 +00:00
dependabot[bot] 408a13cf43 Bump google.golang.org/grpc from 1.55.0 to 1.56.0
Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.55.0 to 1.56.0.
- [Release notes](https://github.com/grpc/grpc-go/releases)
- [Commits](https://github.com/grpc/grpc-go/compare/v1.55.0...v1.56.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]>
2023-06-19 04:04:30 +00:00
dependabot[bot] 548a4c54c4 Bump github.com/tetratelabs/wazero from 1.2.0 to 1.2.1
Bumps [github.com/tetratelabs/wazero](https://github.com/tetratelabs/wazero) from 1.2.0 to 1.2.1.
- [Release notes](https://github.com/tetratelabs/wazero/releases)
- [Commits](https://github.com/tetratelabs/wazero/compare/v1.2.0...v1.2.1)

---
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]>
2023-06-19 04:04:12 +00:00
moloch-- 959c3f1909 Peer verification keyex 2023-06-18 17:58:41 -07:00
moloch-- 8f561abfc8 Implemented implant-side encrypt/decrypt 2023-06-18 16:40:28 -07:00
moloch-- 9ab27d1746 initial refactor, broken tests 2023-06-18 16:17:05 -07:00
chase a32d077e16 Add cd and remove duplicate rm from taskmany 2023-06-17 21:11:50 -04:00
Joe 6647abe3d5 Merge pull request #1303 from BishopFox/audit/log
Add additional details to audit log
2023-06-16 18:06:01 -05:00
moloch-- 73f155f6c0 Add additional details to audit log 2023-06-16 13:55:19 -07:00
Joe 57e2111299 Merge pull request #1295 from BishopFox/http-c2-fallback
Fallback to Direct Connection when HTTP Proxy Connection Fails
2023-06-16 15:24:41 -05:00
Joe ea4d517a90 Merge pull request #1302 from BishopFox/fix/implant-exit-1.6
Fix implant exit code.
2023-06-16 13:59:05 -05:00
rkervella b7c8cba630 Fix implant exit code. 2023-06-16 09:14:04 -07:00
Joe f882f52d44 Merge pull request #1301 from BishopFox/windows-hidden-exec
Hidden windows for Executed Processes on Windows
2023-06-16 11:02:03 -05:00
Raf 4b67745c56 Adding the option to spawn processes in Windows with a hidden window 2023-06-16 10:05:38 -04:00
Joe 853537d1f4 Merge pull request #1299 from BishopFox/profile-info
"profiles info" subcommand and saving poll timeout in profile
2023-06-15 09:38:40 -05:00
Raf f6a2021213 Adding profiles info command for detailed info on a profile, saving poll timeout in profile 2023-06-15 09:57:06 -04:00
Joe 4841e46c34 Merge pull request #1298 from BishopFox/save-sgn-pref-in-profile
Storing Shikata Ga Nai (SGN) preference with implant profile
2023-06-14 14:25:16 -05:00
Raf 888d4479a3 Storing Shikata Ga Nai (SGN) preference with implant profile 2023-06-14 12:18:23 -04:00
Joe fd7585e628 Merge pull request #1293 from BishopFox/88cedependabot/go_modules/github.com/ncruces/go-sqlite3-0.7.2
Bump github.com/ncruces/go-sqlite3 from 0.7.0 to 0.7.2
2023-06-13 11:13:31 -05:00
Joe 43969f7c11 Merge pull request #1292 from BishopFox/b526dependabot/go_modules/gorm.io/driver/sqlite-1.5.2
Bump gorm.io/driver/sqlite from 1.5.1 to 1.5.2
2023-06-13 09:48:36 -05:00
Joe d79fe0c4d1 Merge pull request #1291 from BishopFox/370ddependabot/go_modules/modernc.org/sqlite-1.23.1
Bump modernc.org/sqlite from 1.22.1 to 1.23.1
2023-06-13 09:48:16 -05:00
dependabot[bot] 934e45ce38 Bump github.com/ncruces/go-sqlite3 from 0.7.0 to 0.7.2
Bumps [github.com/ncruces/go-sqlite3](https://github.com/ncruces/go-sqlite3) from 0.7.0 to 0.7.2.
- [Release notes](https://github.com/ncruces/go-sqlite3/releases)
- [Commits](https://github.com/ncruces/go-sqlite3/compare/v0.7.0...v0.7.2)

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

Signed-off-by: dependabot[bot] <[email protected]>
2023-06-12 04:03:46 +00:00
dependabot[bot] ab8da44be4 Bump gorm.io/driver/sqlite from 1.5.1 to 1.5.2
Bumps [gorm.io/driver/sqlite](https://github.com/go-gorm/sqlite) from 1.5.1 to 1.5.2.
- [Commits](https://github.com/go-gorm/sqlite/compare/v1.5.1...v1.5.2)

---
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-06-12 04:02:47 +00:00
dependabot[bot] eb3db89e9f Bump modernc.org/sqlite from 1.22.1 to 1.23.1
Bumps [modernc.org/sqlite](https://gitlab.com/cznic/sqlite) from 1.22.1 to 1.23.1.
- [Commits](https://gitlab.com/cznic/sqlite/compare/v1.22.1...v1.23.1)

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

Signed-off-by: dependabot[bot] <[email protected]>
2023-06-12 04:01:58 +00:00
Tim Makram Ghatas aa2652e4e7 add default http c2 profile parameter for beacons 2023-06-11 19:28:55 -04:00
Tim Makram Ghatas c7531bdacf fixed http c2 randomizer and path segments length bug 2023-06-11 19:24:24 -04:00
Tim Makram Ghatas b7d8c535f0 retrieve monitor config from sqlite db on start command 2023-06-11 18:53:22 -04:00
Tim Makram Ghatas a1194c0c41 allow inserting, deleting and retrieving watchtower configurations from database 2023-06-11 18:44:12 -04:00
Tim Makram Ghatas aac5b227ca added rpc functions for watchtower configuration 2023-06-09 15:33:58 -04:00
Tim Makram Ghatas 20221a8a50 updated watchtower pb object, and added commands for listing adding and removing watchtower configuration 2023-06-09 15:28:50 -04:00
Tim Makram Ghatas fca1202cee added watchtower objects to sql db 2023-06-08 12:24:33 -04:00
Tim Makram Ghatas 6e49197b2c add protobuf definition for watchtower config 2023-06-07 18:01:50 -04:00
b0yd bbe5f4c7cf Removed unnecessary change 2023-06-07 10:15:09 -04:00
b0yd 66c521d719 Merge updates 2023-06-07 09:58:47 -04:00
Tim Makram Ghatas 25f7c6e63e switch to constants variable 2023-06-07 08:08:59 -04:00
Tim Makram Ghatas 678c70d108 add default port check for mtls 2023-06-07 07:53:16 -04:00
Tim Makram Ghatas ee95829770 refactor job creation and move hardcoded values to constants 2023-06-06 23:37:53 -04:00
Tim Makram Ghatas a73bdf91e2 automatically update job id's on server restart 2023-06-06 23:00:37 -04:00
Tim Makram Ghatas 2cac1eb38b set default value for c2 profile and move to constant strings 2023-06-06 21:01:13 -04:00
b0yd 9148720eb2 Added logic to send clear message after a job is completed 2023-06-06 11:09:52 -04:00
Tim Makram Ghatas dcb0128c3c added multiplayer mode job listener to db 2023-06-06 02:40:44 +02:00
Tim Makram Ghatas 195354792e remove unused code 2023-06-06 02:24:35 +02:00
Tim Makram Ghatas 1419e7173c store and retrieve persistent listeners from database 2023-06-06 02:21:16 +02:00
Tim Makram Ghatas 1241d87b9b remove listener from db when killed 2023-06-06 01:13:32 +02:00
Tim Makram Ghatas 3dc7002fdd fixed jobid display error and added sql tables for dns domains and mtls 2023-06-06 00:45:07 +02:00
b0yd 80947425ec Don't bail on replay attack 2023-06-05 17:23:26 -04:00
b0yd 185ded66c2 Error msg 2023-06-05 17:04:35 -04:00
b0yd 884f2d0bd7 Typo 2023-06-05 16:57:51 -04:00
b0yd 4d0f6585d8 More dbg msgs 2023-06-05 16:48:24 -04:00
b0yd 998bd5ab80 Fixed empty message bug 2023-06-05 16:19:15 -04:00
b0yd 76a8de643f Fixed empty message bug 2023-06-05 16:12:23 -04:00
Tim Makram Ghatas a463aa1218 added listener jobs to database, fixed jobid output issue and implemented save query for listener jobs 2023-06-05 20:05:02 +02:00
Tim Makram Ghatas 5281465c7f typo 2023-06-05 19:42:36 +02:00
Tim Makram Ghatas dd433136bc move away from server object to protobuf 2023-06-05 19:17:31 +02:00
Tim Makram Ghatas 906b8eeec7 rebuild protobuf 2023-06-05 19:16:14 +02:00
Tim Makram Ghatas 126dcf7d86 remove persistent flag from client job commands and update variable name 2023-06-05 19:15:44 +02:00
Tim Makram Ghatas 43eb9e3ded update protobuf definition for c2 listeners 2023-06-05 19:14:23 +02:00
Tim Makram Ghatas c8a661dccc fix for binary test cases 2023-06-04 20:32:16 +02:00
b0yd 66b7b98ed3 Hopefully fixed race condition 2023-06-02 16:49:19 -04:00
b0yd d341b1cb3a Hopefully fixed race condition 2023-06-02 16:13:01 -04:00
b0yd f5d2cd2e94 Initialized new map 2023-06-02 15:59:45 -04:00
b0yd 2b2feb306b Hopefully fixed race condition 2023-06-02 15:46:34 -04:00
b0yd d390ac95c7 Attempting to fix race condition in poll 2023-06-02 15:03:18 -04:00
b0yd 52ff6b4c52 Do not respond if there are no messages available 2023-06-02 14:31:23 -04:00
b0yd 4c8486349b Do not respond if there are no messages available 2023-06-02 14:29:08 -04:00
b0yd 58bcac52eb Refuse requests for duplicate requests 2023-06-02 14:11:24 -04:00
b0yd 8469c9a1ce Debug on message send queue 2023-06-02 13:15:27 -04:00
b0yd ca7b62fb7e Removed some error handled that was designed that way 2023-06-02 10:53:22 -04:00
b0yd 1902f131e7 Added error handling, debug msgs, and indexes to AAAA records to be reassembled 2023-06-02 09:40:55 -04:00
b0yd 80e04c71ff Merge branch 'notxt_dns' of https://github.com/rwincey/sliver into notxt_dns 2023-06-01 14:58:04 -04:00
b0yd b8697f6271 Switched from cname to just aaaa IPs 2023-06-01 14:56:01 -04:00
rwincey 91b2836968 Merge branch 'BishopFox:master' into notxt_dns 2023-05-30 13:46:55 -04:00
Tim Makram Ghatas 3e67c6e2b8 replaced hardcoded http profile value with commandline arg, fixed pb issue with certificate digest and switched from profile id to profile name in implantconfig pb 2023-05-30 17:11:32 +02:00
rwincey 244639a79c Merge branch 'BishopFox:master' into notxt_dns 2023-05-30 10:12:52 -04:00
Tim Makram Ghatas c03975d6c4 added profile randomization during implant generation 2023-05-30 13:59:57 +02:00
Tim Makram Ghatas 429c520c78 add ECCPublicKeyDigest to protobuf and database 2023-05-30 11:46:18 +02:00
Tim Makram Ghatas a6ba86379a Merge branch 'v1.6.0/master' into v1.6.0/http-c2 2023-05-30 10:39:22 +02:00
Tim Makram Ghatas 4b7b8c4b3e autoload default profile during implant generation 2023-05-30 10:08:09 +02:00
Tim Makram Ghatas 75c3d0c0fb load http configurations from database on listener creation 2023-05-30 06:41:08 +02:00
Tim Makram Ghatas 8f7da07a35 protobuf build update 2023-05-30 06:21:34 +02:00
Tim Makram Ghatas 95a4604a8b fix path segments generation issues 2023-05-30 06:20:53 +02:00
b0yd 992ee14e82 Fixed cname recursive lookup 2023-05-29 16:00:50 -04:00
b0yd 2066d200c4 More size massaging 2023-05-29 13:10:20 -04:00
b0yd 683a779159 More size massaging 2023-05-29 12:49:35 -04:00
b0yd d14003bf14 More size massaging 2023-05-29 11:15:29 -04:00
b0yd e4b6da3471 More size massaging 2023-05-29 11:06:58 -04:00
b0yd 4c0f36dba2 More size massaging 2023-05-29 10:50:56 -04:00
Tim Makram Ghatas 3b295b3bae fixed renamed protobuf issues and default configuration save 2023-05-28 23:20:59 +02:00
b0yd 302711e817 Trimmed DNS size to fit within 512 2023-05-26 17:39:35 -04:00
b0yd a8b69b352d Added AAAA record to response along with CNAME 2023-05-26 11:32:43 -04:00
b0yd f180dd9aff Added support for nonTXT based DNS comms 2023-05-26 09:13:45 -04:00
Tim Makram Ghatas 09f2521bc3 added check for included c2 channels during config generation 2023-05-26 02:15:25 +02:00
Tim Makram Ghatas d674b8d40f fix sliver rendering code variable name changes 2023-05-26 01:45:04 +02:00
Tim Makram Ghatas d98b24fbc6 add boolean checks for named pipe and tcp pivot 2023-05-26 01:37:44 +02:00
Tim Makram Ghatas 0f38081c0c check for presence of default http c2 profile on startup, and if not present generate and insert into database 2023-05-25 22:58:48 +02:00
Tim Makram Ghatas bedc225344 added default http profile generator 2023-05-25 20:25:42 +02:00
Tim Makram Ghatas 82c68bda54 ImplantConfigSave uses model object instead of protobuf 2023-05-25 16:46:09 +02:00
Tim Makram Ghatas 89b0263634 switch use of models.ImplantConfig to clientpb.ImplantConfig 2023-05-25 00:10:07 +02:00
moloch-- 865f295c65 wip refactor of generate code 2023-05-19 08:25:28 -07:00
moloch-- bad1897e78 Implemented ToProtobuf() conversions 2023-05-17 18:24:05 -07:00
moloch-- ae101d3243 Implemented ToProtobuf() conversions 2023-05-17 18:23:25 -07:00
moloch-- a947d9efeb Implemented basic http c2 pb 2023-05-17 18:13:14 -07:00
moloch-- afa2b5c715 Implemented basic http c2 pb 2023-05-17 18:11:55 -07:00
moloch-- 086eb7fe42 Added more cookie names 2023-05-17 17:27:29 -07:00
moloch-- 55c8cddf88 Expanded default http c2 config 2023-05-17 17:04:44 -07:00
moloch-- 7661d0c1b9 Implement gorm hooks, cleanup 2023-05-17 16:43:40 -07:00
moloch-- f1f736d7c1 Outline http c2 in db 2023-05-17 16:32:04 -07:00
moloch-- 8ad0dfb4c8 Outline http c2 in db 2023-05-17 16:31:56 -07:00
chase 1fd410ee71 Add basic functionality to taskmany command 2023-05-06 04:29:58 -04:00
4798 changed files with 807792 additions and 101805 deletions

No files matched your search

+10 -10
View File
@@ -6,15 +6,15 @@ on:
jobs:
servers-build:
name: Build Server Binaries
name: Release Build Server
if: startsWith( github.ref, 'refs/tags/v')
runs-on: ubuntu-latest
timeout-minutes: 45
steps:
- name: Go 1.20
uses: actions/setup-go@v4
- name: Go 1.21
uses: actions/setup-go@v5
with:
go-version: "^1.20"
go-version: "^1.21"
- name: OS Packages
run: |
@@ -22,7 +22,7 @@ jobs:
git build-essential zlib1g zlib1g-dev wget zip unzip
- name: Check Out Code
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Git Fetch Tags
run: git fetch --prune --unshallow --tags -f
@@ -37,18 +37,18 @@ jobs:
path: ./sliver-server_*
clients-build:
name: Build Client Binaries
name: Release Build Client
if: startsWith( github.ref, 'refs/tags/v')
runs-on: ubuntu-latest
timeout-minutes: 45
steps:
- name: Go 1.20
uses: actions/setup-go@v4
- name: Go 1.21
uses: actions/setup-go@v5
with:
go-version: "^1.20"
go-version: "^1.21"
- name: Check Out Code
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Git Fetch Tags
run: git fetch --prune --unshallow --tags -f
+5 -5
View File
@@ -16,13 +16,13 @@ jobs:
steps:
# Setup go environment
- name: Go 1.20
uses: actions/setup-go@v4
- name: Go 1.21
uses: actions/setup-go@v5
with:
go-version: "^1.20"
go-version: "^1.21"
- name: Checkout repository
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
# Must fetch at least the immediate parents so that if this is
# a pull request then we can checkout the head of the pull request.
@@ -36,7 +36,7 @@ jobs:
git build-essential zlib1g zlib1g-dev wget zip unzip
- name: Check Out Code
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Initialize CodeQL
uses: github/codeql-action/init@v2
+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@v3
- 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@v3
- name: Restore cache
uses: actions/cache@v3
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@v1
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@v2
@@ -3,6 +3,14 @@ on:
pull_request:
branches:
- master
paths:
- "go.mod"
- "go.sum"
- "Makefile"
- "**/*.go"
- "**/*.c"
- "**/*.h"
- "**/*.sh"
types:
- opened
- reopened
@@ -10,15 +18,15 @@ on:
- ready_for_review
jobs:
linux-windows-build:
name: Linux & Windows Build
linux-windows-build-test:
name: Linux & Windows Test
runs-on: ubuntu-latest
timeout-minutes: 90
steps:
- name: Go 1.20
uses: actions/setup-go@v4
- name: Go 1.21
uses: actions/setup-go@v5
with:
go-version: "^1.20"
go-version: "^1.21"
- name: OS Packages
run: |
@@ -27,7 +35,7 @@ jobs:
mingw-w64 binutils-mingw-w64 g++-mingw-w64 gcc-multilib
- name: Check Out Code
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Git Fetch Tags
run: git fetch --prune --unshallow --tags -f
@@ -44,21 +52,21 @@ jobs:
- name: Make Linux (arm64)
run: make linux-arm64
macos-build:
name: MacOS Build
macos-build-test:
name: MacOS Test
runs-on: macos-latest
timeout-minutes: 90
steps:
- name: Go 1.20
uses: actions/setup-go@v4
- name: Go 1.21
uses: actions/setup-go@v5
with:
go-version: "^1.20"
go-version: "^1.21"
- name: Mingw
run: brew install mingw-w64
- name: Check Out Code
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Git Fetch Tags
run: git fetch --prune --unshallow --tags -f
@@ -80,13 +88,13 @@ jobs:
runs-on: ubuntu-latest
timeout-minutes: 90
steps:
- name: Go 1.20
uses: actions/setup-go@v4
- name: Go 1.21
uses: actions/setup-go@v5
with:
go-version: "^1.20"
go-version: "^1.21"
- name: Check Out Code
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Git Fetch Tags
run: git fetch --prune --unshallow --tags -f
+107 -53
View File
@@ -1,71 +1,125 @@
FROM golang:1.20.4
#
# IMPORTANT: This Dockerfile is used for testing, I do not recommend deploying
# Sliver using this container configuration! However, if you do want
# a Docker deployment this is probably a good place to start.
# 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 .
#
ENV PROTOC_VER 21.12
ENV PROTOC_GEN_GO_VER v1.27.1
ENV GRPC_GO v1.2.0
# STAGE: base
## Compiles Sliver for use
FROM --platform=linux/amd64 golang:1.21.4 as base
# Base packages
### Base packages
RUN apt-get update --fix-missing && apt-get -y install \
git build-essential zlib1g zlib1g-dev \
libxml2 libxml2-dev libxslt-dev locate curl \
libreadline6-dev libcurl4-openssl-dev git-core \
libssl-dev libyaml-dev openssl autoconf libtool \
ncurses-dev bison curl wget xsel postgresql \
postgresql-contrib postgresql-client libpq-dev \
libapr1 libaprutil1 libsvn1 \
libpcap-dev libsqlite3-dev libgmp3-dev \
zip unzip mingw-w64 binutils-mingw-w64 g++-mingw-w64 \
nasm gcc-multilib
git build-essential zlib1g zlib1g-dev wget zip unzip
#
# > User
#
### 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
#
# > Metasploit
#
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'
#
# > Sliver
#
# Protoc
# WORKDIR /tmp
# RUN wget -O protoc-${PROTOC_VER}-linux-x86_64.zip https://github.com/protocolbuffers/protobuf/releases/download/v${PROTOC_VER}/protoc-${PROTOC_VER}-linux-x86_64.zip \
# && unzip protoc-${PROTOC_VER}-linux-x86_64.zip \
# && cp -vv ./bin/protoc /usr/local/bin
# RUN go install google.golang.org/protobuf/cmd/protoc-gen-go@${PROTOC_GEN_GO_VER} \
# && go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@${GRPC_GO}
# Go assets
### Build sliver:
WORKDIR /go/src/github.com/bishopfox/sliver
ADD . /go/src/github.com/bishopfox/sliver/
RUN make clean-all \
&& make \
&& cp -vv sliver-server /opt/sliver-server \
&& /opt/sliver-server unpack --force
RUN make clean-all
RUN make
RUN cp -vv sliver-server /opt/sliver-server
# Run unit tests
# 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
RUN apt-get update --fix-missing \
&& apt-get -y upgrade \
&& apt-get -y install \
curl gcc-multilib build-essential mingw-w64 binutils-mingw-w64 g++-mingw-w64
RUN /opt/sliver-server unpack --force
### Run unit tests
RUN /go/src/github.com/bishopfox/sliver/go-tests.sh
# Clean up
RUN make clean \
&& rm -rf /go/src/* \
&& rm -rf /home/sliver/.sliver
# STAGE: production
## Final dockerized form of Sliver
FROM --platform=linux/amd64 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 \
mingw-w64 binutils-mingw-w64 g++-mingw-w64 \
nasm gcc-multilib
### 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
### 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)
### Slim production image, i.e. without MSF and assoicated libraries
### Still include GCC and MinGW for cross-platform generation
FROM --platform=linux/amd64 debian:bookworm-slim as production-slim
### Install production packages
RUN apt-get update --fix-missing \
&& apt-get -y upgrade \
&& apt-get -y install \
build-essential mingw-w64 binutils-mingw-w64 g++-mingw-w64 gcc-multilib
### 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
WORKDIR /home/sliver/
VOLUME [ "/home/sliver/.sliver" ]
ENTRYPOINT [ "/opt/sliver-server" ]
+2 -2
View File
@@ -5,7 +5,7 @@
GO ?= go
ARTIFACT_SUFFIX ?=
ENV =
TAGS ?= -tags osusergo,netgo,go_sqlite
TAGS ?= -tags go_sqlite
CGO_ENABLED = 0
ifneq (,$(findstring cgo_sqlite,$(TAGS)))
@@ -27,7 +27,7 @@ GO_VERSION = $(shell $(GO) version)
GO_MAJOR_VERSION = $(shell $(GO) version | cut -c 14- | cut -d' ' -f1 | cut -d'.' -f1)
GO_MINOR_VERSION = $(shell $(GO) version | cut -c 14- | cut -d' ' -f1 | cut -d'.' -f2)
MIN_SUPPORTED_GO_MAJOR_VERSION = 1
MIN_SUPPORTED_GO_MINOR_VERSION = 20
MIN_SUPPORTED_GO_MINOR_VERSION = 21
GO_VERSION_VALIDATION_ERR_MSG = Golang version is not supported, please update to at least $(MIN_SUPPORTED_GO_MAJOR_VERSION).$(MIN_SUPPORTED_GO_MINOR_VERSION)
VERSION ?= $(shell git describe --abbrev=0)
+7 -7
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 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,11 +39,11 @@ 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
+2 -7
View File
@@ -61,14 +61,9 @@ def docker_rm_all():
def build():
status = exec_cmd("docker build -t sliver .")
status = exec_cmd("docker build --target test .")
if status == 0:
print(
INFO
+ "Build successful, start with %sdocker run -it sliver:latest%s"
% (BOLD, NORM)
)
print(INFO + "Remember you'll need to manually forward network ports")
print("\n\n" + INFO + "Build successful")
def main(args):
+86
View File
@@ -0,0 +1,86 @@
package assets
/*
Sliver Implant Framework
Copyright (C) 2019 Bishop Fox
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
// HTTPC2Config - Parent config file struct for implant/server
type HTTPC2Config struct {
ImplantConfig HTTPC2ImplantConfig `json:"implant_config"`
ServerConfig HTTPC2ServerConfig `json:"server_config"`
}
// HTTPC2ServerConfig - Server configuration options
type HTTPC2ServerConfig struct {
RandomVersionHeaders bool `json:"random_version_headers"`
Headers []NameValueProbability `json:"headers"`
Cookies []string `json:"cookies"`
}
type NameValueProbability struct {
Name string `json:"name"`
Value string `json:"value"`
Probability int `json:"probability"`
Methods []string
}
// HTTPC2ImplantConfig - Implant configuration options
// Procedural C2
// ===============
// .txt = rsakey
// .css = start
// .php = session
//
// .js = poll
//
// .png = stop
// .woff = sliver shellcode
type HTTPC2ImplantConfig struct {
UserAgent string `json:"user_agent"`
ChromeBaseVersion int `json:"chrome_base_version"`
MacOSVersion string `json:"macos_version"`
NonceQueryArgChars string `json:"nonce_query_args"`
URLParameters []NameValueProbability `json:"url_parameters"`
Headers []NameValueProbability `json:"headers"`
MaxFiles int `json:"max_files"`
MinFiles int `json:"min_files"`
MaxPaths int `json:"max_paths"`
MinPaths int `json:"min_paths"`
// Stager files and paths
StagerFileExt string `json:"stager_file_ext"`
StagerFiles []string `json:"stager_files"`
StagerPaths []string `json:"stager_paths"`
// Poll files and paths
PollFileExt string `json:"poll_file_ext"`
PollFiles []string `json:"poll_files"`
PollPaths []string `json:"poll_paths"`
// Session files and paths
StartSessionFileExt string `json:"start_session_file_ext"`
SessionFileExt string `json:"session_file_ext"`
SessionFiles []string `json:"session_files"`
SessionPaths []string `json:"session_paths"`
// Close session files and paths
CloseFileExt string `json:"close_file_ext"`
CloseFiles []string `json:"close_files"`
ClosePaths []string `json:"close_paths"`
}
+2 -2
View File
@@ -21,7 +21,7 @@ package alias
import (
"encoding/json"
"fmt"
"io/ioutil"
"os"
"strings"
"github.com/bishopfox/sliver/client/assets"
@@ -115,7 +115,7 @@ func getInstalledManifests() map[string]*AliasManifest {
manifestPaths := assets.GetInstalledAliasManifests()
installedManifests := map[string]*AliasManifest{}
for _, manifestPath := range manifestPaths {
data, err := ioutil.ReadFile(manifestPath)
data, err := os.ReadFile(manifestPath)
if err != nil {
continue
}
+4 -5
View File
@@ -20,7 +20,6 @@ package alias
import (
"fmt"
"io/ioutil"
"os"
"path/filepath"
"strings"
@@ -50,7 +49,7 @@ func AliasesInstallCmd(cmd *cobra.Command, con *console.SliverConsoleClient, arg
// Install an extension from a directory
func installFromDir(aliasLocalPath string, con *console.SliverConsoleClient) {
manifestData, err := ioutil.ReadFile(filepath.Join(aliasLocalPath, ManifestFileName))
manifestData, err := os.ReadFile(filepath.Join(aliasLocalPath, ManifestFileName))
if err != nil {
con.PrintErrorf("Error reading %s: %s", ManifestFileName, err)
return
@@ -78,7 +77,7 @@ func installFromDir(aliasLocalPath string, con *console.SliverConsoleClient) {
con.PrintErrorf("Error creating alias directory: %s\n", err)
return
}
err = ioutil.WriteFile(filepath.Join(installPath, ManifestFileName), manifestData, 0o600)
err = os.WriteFile(filepath.Join(installPath, ManifestFileName), manifestData, 0o600)
if err != nil {
con.PrintErrorf("Failed to write %s: %s\n", ManifestFileName, err)
forceRemoveAll(installPath)
@@ -133,7 +132,7 @@ func InstallFromFile(aliasGzFilePath string, autoOverwrite bool, con *console.Sl
con.PrintErrorf("Failed to create alias directory: %s\n", err)
return nil
}
err = ioutil.WriteFile(filepath.Join(installPath, ManifestFileName), manifestData, 0o600)
err = os.WriteFile(filepath.Join(installPath, ManifestFileName), manifestData, 0o600)
if err != nil {
con.PrintErrorf("Failed to write %s: %s\n", ManifestFileName, err)
forceRemoveAll(installPath)
@@ -166,7 +165,7 @@ func installArtifact(aliasGzFilePath string, installPath, artifactPath string, c
if _, err := os.Stat(artifactDir); os.IsNotExist(err) {
os.MkdirAll(artifactDir, 0o700)
}
err = ioutil.WriteFile(localArtifactPath, data, 0o600)
err = os.WriteFile(localArtifactPath, data, 0o600)
if err != nil {
return err
}
+18 -14
View File
@@ -36,7 +36,7 @@ import (
"github.com/bishopfox/sliver/client/command/extensions"
"github.com/bishopfox/sliver/client/command/settings"
"github.com/bishopfox/sliver/client/console"
"github.com/bishopfox/sliver/server/cryptography/minisign"
"github.com/bishopfox/sliver/util/minisign"
)
// ArmoryIndex - Index JSON containing alias/extension/bundle information
@@ -141,7 +141,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
@@ -183,7 +183,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
@@ -217,9 +217,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)
@@ -291,14 +293,16 @@ 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{
CommandName: extension.CommandName,
Version: extension.Manifest.Version,
Type: "Extension",
Help: extension.Help,
URL: extension.Manifest.RepoURL,
})
}
}
sliverMenu := con.App.Menu("implant")
+41 -49
View File
@@ -32,7 +32,7 @@ import (
"github.com/bishopfox/sliver/client/command/extensions"
"github.com/bishopfox/sliver/client/console"
"github.com/bishopfox/sliver/client/constants"
"github.com/bishopfox/sliver/server/cryptography/minisign"
"github.com/bishopfox/sliver/util/minisign"
)
// ErrPackageNotFound - The package was not found
@@ -96,11 +96,13 @@ func installPackageByName(name string, clientConfig ArmoryHTTPConfig, con *conso
}
}
}
for _, ext := range extensions {
if ext.CommandName == name || name == "all" {
installExtension(ext, clientConfig, con)
if name != "all" {
return nil
for _, extm := range extensions {
for _, ext := range extm.ExtCommand {
if ext.CommandName == name || name == "all" {
installExtension(ext.Manifest, clientConfig, con)
if name != "all" {
return nil
}
}
}
}
@@ -186,25 +188,27 @@ func installAliasPackageByName(name string, clientConfig ArmoryHTTPConfig, con *
return nil
}
func installExtension(ext *extensions.ExtensionManifest, clientConfig ArmoryHTTPConfig, con *console.SliverConsoleClient) {
func installExtension(extm *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
for _, ext := range extm.ExtCommand {
resolveExtensionPackageDependencies(ext.CommandName, deps, clientConfig, con)
sliverMenu := con.App.Menu(constants.ImplantMenu).Root()
for dep := range deps {
if extensions.CmdExists(dep, sliverMenu) {
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(dep, clientConfig, con)
err := installExtensionPackageByName(ext.CommandName, clientConfig, con)
if err != nil {
con.PrintErrorf("Failed to install extension dependency '%s': %s", dep, err)
con.PrintErrorf("Failed to install extension '%s': %s", ext.CommandName, 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
@@ -222,24 +226,25 @@ func resolveExtensionPackageDependencies(name string, deps map[string]struct{},
if entry == nil {
return
}
for _, multiExt := range entry.Extension.ExtCommand {
if multiExt.DependsOn == "" {
continue // Avoid adding empty dependency
}
if entry.Extension.DependsOn == "" {
return // Avoid adding empty dependency
if multiExt.DependsOn == 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
}
if maxDepDepth < len(deps) {
continue
}
deps[multiExt.DependsOn] = struct{}{}
resolveExtensionPackageDependencies(multiExt.DependsOn, deps, clientConfig, con)
}
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)
}
func installExtensionPackageByName(name string, clientConfig ArmoryHTTPConfig, con *console.SliverConsoleClient) error {
@@ -297,20 +302,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(), 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
}
+1 -1
View File
@@ -33,7 +33,7 @@ import (
"time"
"github.com/bishopfox/sliver/client/assets"
"github.com/bishopfox/sliver/server/cryptography/minisign"
"github.com/bishopfox/sliver/util/minisign"
)
// ArmoryIndexParser - Generic interface to fetch armory indexes
+5 -3
View File
@@ -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 {
+3 -2
View File
@@ -104,10 +104,11 @@ func checkForExtensionUpdates(clientConfig ArmoryHTTPConfig, con *console.Sliver
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)
if latestExt.Name == localManifest.Name && latestExt.Version != localManifest.Version {
results = append(results, localManifest.Name)
}
}
}
return results
}
+437
View File
@@ -0,0 +1,437 @@
package c2profiles
/*
Sliver Implant Framework
Copyright (C) 2019 Bishop Fox
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import (
"context"
"encoding/json"
"io"
"os"
"strings"
"github.com/AlecAivazis/survey/v2"
"github.com/jedib0t/go-pretty/v6/table"
"github.com/spf13/cobra"
"golang.org/x/exp/slices"
"github.com/bishopfox/sliver/client/assets"
"github.com/bishopfox/sliver/client/command/settings"
"github.com/bishopfox/sliver/client/console"
"github.com/bishopfox/sliver/client/constants"
"github.com/bishopfox/sliver/protobuf/clientpb"
"github.com/bishopfox/sliver/protobuf/commonpb"
)
// C2ProfileCmd list available http profiles
func C2ProfileCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []string) {
profileName, _ := cmd.Flags().GetString("name")
if profileName == constants.DefaultC2Profile {
httpC2Profiles, err := con.Rpc.GetHTTPC2Profiles(context.Background(), &commonpb.Empty{})
if err != nil {
con.PrintErrorf("failed to fetch HTTP C2 profiles: %s", err.Error())
return
}
if len(httpC2Profiles.Configs) != 1 {
profileName = selectC2Profile(httpC2Profiles.Configs)
}
}
profile, err := con.Rpc.GetHTTPC2ProfileByName(context.Background(), &clientpb.C2ProfileReq{Name: profileName})
if err != nil {
con.PrintErrorf("%s\n", err)
return
}
PrintC2Profiles(profile, con)
}
func ImportC2ProfileCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []string) {
protocols := []string{constants.HttpStr, constants.HttpsStr}
profileName, _ := cmd.Flags().GetString("name")
if profileName == "" {
con.PrintErrorf("Invalid c2 profile name\n")
return
}
filepath, _ := cmd.Flags().GetString("file")
if filepath == "" {
con.PrintErrorf("Missing file path\n")
return
}
overwrite, _ := cmd.Flags().GetBool("overwrite")
// retrieve and unmarshal profile config
jsonFile, err := os.Open(filepath)
if err != nil {
con.PrintErrorf("%s\n", err)
return
}
byteFile, _ := io.ReadAll(jsonFile)
var config *assets.HTTPC2Config = &assets.HTTPC2Config{}
err = json.Unmarshal(byteFile, config)
if err != nil {
con.PrintErrorf("%s\n", err)
return
}
httpC2ConfigReq := clientpb.HTTPC2ConfigReq{Overwrite: overwrite, C2Config: C2ConfigToProtobuf(profileName, config)}
_, err = con.Rpc.SaveHTTPC2Profile(context.Background(), &httpC2ConfigReq)
if err != nil {
con.PrintErrorf("%s\n", err)
return
}
confirm := false
prompt := &survey.Confirm{Message: "Restart HTTP/S jobs?"}
survey.AskOne(prompt, &confirm)
if confirm {
var restartJobReq clientpb.RestartJobReq
jobs, err := con.Rpc.GetJobs(context.Background(), &commonpb.Empty{})
if err != nil {
con.PrintErrorf("%s\n", err)
return
}
// reload jobs to include new profile
for _, job := range jobs.Active {
if job != nil && slices.Contains(protocols, job.Name) {
restartJobReq.JobIDs = append(restartJobReq.JobIDs, job.ID)
}
}
_, err = con.Rpc.RestartJobs(context.Background(), &restartJobReq)
if err != nil {
con.PrintErrorf("%s\n", err)
return
}
}
}
// convert json to protobuf
func C2ConfigToProtobuf(profileName string, config *assets.HTTPC2Config) *clientpb.HTTPC2Config {
httpC2UrlParameters := []*clientpb.HTTPC2URLParameter{}
httpC2Headers := []*clientpb.HTTPC2Header{}
pathSegments := []*clientpb.HTTPC2PathSegment{}
// files
for _, poll := range config.ImplantConfig.PollFiles {
pathSegments = append(pathSegments, &clientpb.HTTPC2PathSegment{
IsFile: true,
SegmentType: 0,
Value: poll,
})
}
for _, session := range config.ImplantConfig.SessionFiles {
pathSegments = append(pathSegments, &clientpb.HTTPC2PathSegment{
IsFile: true,
SegmentType: 1,
Value: session,
})
}
for _, close := range config.ImplantConfig.CloseFiles {
pathSegments = append(pathSegments, &clientpb.HTTPC2PathSegment{
IsFile: true,
SegmentType: 2,
Value: close,
})
}
for _, stager := range config.ImplantConfig.StagerFiles {
pathSegments = append(pathSegments, &clientpb.HTTPC2PathSegment{
IsFile: true,
SegmentType: 3,
Value: stager,
})
}
// paths
for _, poll := range config.ImplantConfig.PollPaths {
pathSegments = append(pathSegments, &clientpb.HTTPC2PathSegment{
IsFile: false,
SegmentType: 0,
Value: poll,
})
}
for _, session := range config.ImplantConfig.SessionPaths {
pathSegments = append(pathSegments, &clientpb.HTTPC2PathSegment{
IsFile: false,
SegmentType: 1,
Value: session,
})
}
for _, close := range config.ImplantConfig.ClosePaths {
pathSegments = append(pathSegments, &clientpb.HTTPC2PathSegment{
IsFile: false,
SegmentType: 2,
Value: close,
})
}
for _, stager := range config.ImplantConfig.StagerPaths {
pathSegments = append(pathSegments, &clientpb.HTTPC2PathSegment{
IsFile: false,
SegmentType: 3,
Value: stager,
})
}
implantConfig := &clientpb.HTTPC2ImplantConfig{
UserAgent: config.ImplantConfig.UserAgent,
ChromeBaseVersion: int32(config.ImplantConfig.ChromeBaseVersion),
MacOSVersion: config.ImplantConfig.MacOSVersion,
NonceQueryArgChars: config.ImplantConfig.NonceQueryArgChars,
ExtraURLParameters: httpC2UrlParameters,
Headers: httpC2Headers,
MaxFiles: int32(config.ImplantConfig.MaxFiles),
MinFiles: int32(config.ImplantConfig.MinFiles),
MaxPaths: int32(config.ImplantConfig.MaxPaths),
MinPaths: int32(config.ImplantConfig.MinFiles),
StagerFileExtension: config.ImplantConfig.StagerFileExt,
PollFileExtension: config.ImplantConfig.PollFileExt,
StartSessionFileExtension: config.ImplantConfig.StartSessionFileExt,
SessionFileExtension: config.ImplantConfig.SessionFileExt,
CloseFileExtension: config.ImplantConfig.CloseFileExt,
PathSegments: pathSegments,
}
// Server Config
serverHeaders := []*clientpb.HTTPC2Header{}
for _, serverHeader := range config.ServerConfig.Headers {
for _, method := range serverHeader.Methods {
serverHeaders = append(serverHeaders, &clientpb.HTTPC2Header{
Method: method,
Name: serverHeader.Name,
Value: serverHeader.Value,
Probability: int32(serverHeader.Probability),
})
}
}
serverCookies := []*clientpb.HTTPC2Cookie{}
for _, cookie := range config.ServerConfig.Cookies {
serverCookies = append(serverCookies, &clientpb.HTTPC2Cookie{
Name: cookie,
})
}
serverConfig := &clientpb.HTTPC2ServerConfig{
RandomVersionHeaders: config.ServerConfig.RandomVersionHeaders,
Headers: serverHeaders,
Cookies: serverCookies,
}
return &clientpb.HTTPC2Config{
Name: profileName,
ImplantConfig: implantConfig,
ServerConfig: serverConfig,
}
}
// PrintImplantBuilds - Print the implant builds on the server
func PrintC2Profiles(profile *clientpb.HTTPC2Config, con *console.SliverConsoleClient) {
tw := table.NewWriter()
tw.SetStyle(settings.GetTableStyle(con))
tw.AppendHeader(table.Row{
"Parameter",
"Value",
})
// Profile metadata
tw.AppendRow(table.Row{
"Profile Name",
profile.Name,
})
// Server side configuration
var serverHeaders []string
for _, header := range profile.ServerConfig.Headers {
serverHeaders = append(serverHeaders, header.Value)
}
tw.AppendRow(table.Row{
"Server Headers",
strings.Join(serverHeaders[:], ","),
})
var serverCookies []string
for _, cookie := range profile.ServerConfig.Cookies {
serverCookies = append(serverCookies, cookie.Name)
}
tw.AppendRow(table.Row{
"Server Cookies",
strings.Join(serverCookies[:], ","),
})
tw.AppendRow(table.Row{
"Randomize Server Headers",
profile.ServerConfig.RandomVersionHeaders,
})
// Client side configuration
var clientHeaders []string
for _, header := range profile.ImplantConfig.Headers {
clientHeaders = append(clientHeaders, header.Value)
}
tw.AppendRow(table.Row{
"Client Headers",
strings.Join(clientHeaders[:], ","),
})
var clientUrlParams []string
for _, clientUrlParam := range profile.ImplantConfig.ExtraURLParameters {
clientUrlParams = append(clientUrlParams, clientUrlParam.Name)
}
tw.AppendRow(table.Row{
"Extra URL Parameters",
strings.Join(clientUrlParams[:], ","),
})
tw.AppendRow(table.Row{
"User agent",
profile.ImplantConfig.UserAgent,
})
tw.AppendRow(table.Row{
"Chrome base version",
profile.ImplantConfig.ChromeBaseVersion,
})
tw.AppendRow(table.Row{
"MacOS version",
profile.ImplantConfig.MacOSVersion,
})
tw.AppendRow(table.Row{
"Nonce query arg chars",
profile.ImplantConfig.NonceQueryArgChars,
})
tw.AppendRow(table.Row{
"Max files",
profile.ImplantConfig.MaxFiles,
})
tw.AppendRow(table.Row{
"Min files",
profile.ImplantConfig.MinFiles,
})
tw.AppendRow(table.Row{
"Max paths",
profile.ImplantConfig.MaxPaths,
})
tw.AppendRow(table.Row{
"Min paths",
profile.ImplantConfig.MinPaths,
})
tw.AppendRow(table.Row{
"Stager file extension",
profile.ImplantConfig.StagerFileExtension,
})
tw.AppendRow(table.Row{
"Start session file extension",
profile.ImplantConfig.StartSessionFileExtension,
})
tw.AppendRow(table.Row{
"Session file extension",
profile.ImplantConfig.SessionFileExtension,
})
tw.AppendRow(table.Row{
"Poll file extension",
profile.ImplantConfig.PollFileExtension,
})
tw.AppendRow(table.Row{
"Close file extension",
profile.ImplantConfig.CloseFileExtension,
})
var (
pollPaths []string
pollFiles []string
sessionPaths []string
sessionFiles []string
closePaths []string
closeFiles []string
)
for _, segment := range profile.ImplantConfig.PathSegments {
if segment.IsFile {
switch segment.SegmentType {
case 0:
pollFiles = append(pollFiles, segment.Value)
case 1:
sessionFiles = append(sessionFiles, segment.Value)
case 2:
closeFiles = append(closeFiles, segment.Value)
}
} else {
switch segment.SegmentType {
case 0:
pollPaths = append(pollPaths, segment.Value)
case 1:
sessionPaths = append(sessionPaths, segment.Value)
case 2:
closePaths = append(closePaths, segment.Value)
}
}
}
tw.AppendRow(table.Row{
"Poll paths",
strings.Join(pollPaths[:], ","),
})
tw.AppendRow(table.Row{
"Poll files",
strings.Join(pollFiles[:], ","),
})
tw.AppendRow(table.Row{
"Session paths",
strings.Join(sessionPaths[:], ","),
})
tw.AppendRow(table.Row{
"Session files",
strings.Join(sessionFiles[:], ","),
})
tw.AppendRow(table.Row{
"Close paths",
strings.Join(closePaths[:], ","),
})
tw.AppendRow(table.Row{
"Close files",
strings.Join(closeFiles[:], ","),
})
con.Println(tw.Render())
con.Println("\n")
}
func selectC2Profile(c2profiles []*clientpb.HTTPC2Config) string {
c2profile := ""
var choices []string
for _, c2profile := range c2profiles {
choices = append(choices, c2profile.Name)
}
prompt := &survey.Select{
Message: "Select a c2 profile",
Options: choices,
}
survey.AskOne(prompt, &c2profile, nil)
return c2profile
}
+3 -3
View File
@@ -21,7 +21,7 @@ package dllhijack
import (
"context"
"fmt"
"io/ioutil"
"os"
"github.com/spf13/cobra"
@@ -58,7 +58,7 @@ func DllHijackCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []s
}
if localReferenceFilePath != "" {
localRefData, err = ioutil.ReadFile(localReferenceFilePath)
localRefData, err = os.ReadFile(localReferenceFilePath)
if err != nil {
con.PrintErrorf("Could not load the reference file from the client: %s\n", err)
return
@@ -70,7 +70,7 @@ func DllHijackCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []s
con.PrintErrorf("please use either --profile or --File")
return
}
targetDLLData, err = ioutil.ReadFile(localFile)
targetDLLData, err = os.ReadFile(localFile)
if err != nil {
con.PrintErrorf("Error: %s\n", err)
return
+16 -10
View File
@@ -44,6 +44,7 @@ func ExecuteCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []str
args = args[1:]
token, _ := cmd.Flags().GetBool("token")
hidden, _ := cmd.Flags().GetBool("hidden")
output, _ := cmd.Flags().GetBool("output")
stdout, _ := cmd.Flags().GetString("stdout")
stderr, _ := cmd.Flags().GetString("stderr")
@@ -64,16 +65,21 @@ 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 || ppid != 0 {
if token || hidden || ppid != 0 {
if session.OS != "windows" {
con.PrintErrorf("The token, hide window, and ppid options are not valid on %s\n", session.OS)
return
}
exec, err = con.Rpc.ExecuteWindows(context.Background(), &sliverpb.ExecuteWindowsReq{
Request: con.ActiveTarget.Request(cmd),
Path: cmdPath,
Args: args,
Output: captureOutput,
Stderr: stderr,
Stdout: stdout,
UseToken: token,
PPid: ppid,
Request: con.ActiveTarget.Request(cmd),
Path: cmdPath,
Args: args,
Output: captureOutput,
Stderr: stderr,
Stdout: stdout,
UseToken: token,
HideWindow: hidden,
PPid: ppid,
})
} else {
exec, err = con.Rpc.Execute(context.Background(), &sliverpb.ExecuteReq{
@@ -219,7 +225,7 @@ 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)
}
+22 -10
View File
@@ -66,25 +66,27 @@ func PrintExtensions(con *console.SliverConsoleClient) {
installedManifests := getInstalledManifests()
for _, extension := range loadedExtensions {
//for _, extension := range extensionm.ExtCommand {
installed := ""
if _, ok := installedManifests[extension.CommandName]; ok {
if _, ok := installedManifests[extension.Manifest.Name]; ok {
installed = "✅"
}
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)] = ""
@@ -109,7 +111,7 @@ func getInstalledManifests() map[string]*ExtensionManifest {
if err != nil {
continue
}
installedManifests[manifest.CommandName] = manifest
installedManifests[manifest.Name] = manifest
}
return installedManifests
}
@@ -117,9 +119,9 @@ func getInstalledManifests() map[string]*ExtensionManifest {
// ExtensionsCommandNameCompleter - Completer for installed extensions command names
func ExtensionsCommandNameCompleter(con *console.SliverConsoleClient) 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 +129,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",
+49 -79
View File
@@ -22,6 +22,7 @@ import (
"fmt"
"os"
"path/filepath"
"strings"
"github.com/AlecAivazis/survey/v2"
"github.com/spf13/cobra"
@@ -35,121 +36,90 @@ import (
func ExtensionsInstallCmd(cmd *cobra.Command, con *console.SliverConsoleClient, 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, 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))
func InstallFromDir(extLocalPath string, con *console.SliverConsoleClient, 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)
//create repo path
minstallPath := filepath.Join(assets.GetExtensionsDir(), filepath.Base(manifestF.Name))
if _, err := os.Stat(minstallPath); !os.IsNotExist(err) {
con.PrintInfof("Extension '%s' already exists", manifestF.Name)
confirm := false
prompt := &survey.Confirm{Message: "Overwrite current install?"}
survey.AskOne(prompt, &confirm)
if !confirm {
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("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)
forceRemoveAll(minstallPath)
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
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, con)
} 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\n", src, dst, err)
}
}
if err != nil {
con.PrintErrorf("Error installing command: %s\n", 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)
confirm := false
prompt := &survey.Confirm{Message: "Overwrite current install?"}
survey.AskOne(prompt, &confirm)
if !confirm {
return nil
}
}
forceRemoveAll(installPath)
}
con.PrintInfof("Installing extension '%s' (%s) ... ", manifest.CommandName, manifest.Version)
err = os.MkdirAll(installPath, 0o700)
if err != nil {
con.PrintErrorf("Failed to create extension directory: %s\n", err)
return nil
}
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 nil
}
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
}
}
}
con.Printf("done!\n")
return &installPath
}
func installArtifact(extGzFilePath string, installPath string, artifactPath string, con *console.SliverConsoleClient) error {
data, err := util.ReadFileFromTarGz(extGzFilePath, "."+filepath.ToSlash(artifactPath))
if err != nil {
+228 -71
View File
@@ -24,12 +24,14 @@ import (
"encoding/json"
"errors"
"fmt"
"log"
"os"
"path"
"path/filepath"
"strconv"
"strings"
"github.com/AlecAivazis/survey/v2"
appConsole "github.com/reeflective/console"
"github.com/rsteube/carapace"
"github.com/spf13/cobra"
@@ -53,9 +55,10 @@ const (
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 +76,32 @@ type ExtensionManifest struct {
RootPath string `json:"-"`
}
type ExtensionManifest struct {
Name string `json:"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:"-"`
}
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"`
Manifest *ExtensionManifest
}
//type MultiManifest []*ExtensionManifest
type extensionFile struct {
OS string `json:"os"`
Arch string `json:"arch"`
@@ -86,11 +115,11 @@ type extensionArgument struct {
Optional bool `json:"optional"`
}
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)
filePath = path.Join(assets.GetExtensionsDir(), e.Manifest.Name, extFile.Path)
break
}
}
@@ -109,18 +138,25 @@ func (e *ExtensionManifest) getFileForTarget(cmdName string, targetOS string, ta
func ExtensionLoadCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []string) {
dirPath := args[0]
// dirPath := ctx.Args.String("dir-path")
extCmd, err := LoadExtensionManifest(filepath.Join(dirPath, ManifestFileName))
manyfest, 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 manyfest.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
@@ -129,66 +165,165 @@ func LoadExtensionManifest(manifestPath string) (*ExtensionManifest, error) {
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 commandname 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,
},
},
}
//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
log.Println(err)
oldmanifest := &ExtensionManifest_{}
err := json.Unmarshal(data, &oldmanifest)
if err != nil {
//nope, just broken
return nil, err
}
if extFiles.Arch == "" {
return nil, errors.New("missing `files.arch` field in extension manifest")
}
extFiles.Path = util.ResolvePath(extFiles.Path)
if extFiles.Path == "" || extFiles.Path == "/" {
return nil, errors.New("missing `files.path` field in extension manifest")
}
extFiles.OS = strings.ToLower(extFiles.OS)
extFiles.Arch = strings.ToLower(extFiles.Arch)
//yes, ok, lets jigger it to a new manifest
extManifest = convertOldManifest(oldmanifest)
}
if extManifest.Help == "" {
return nil, errors.New("missing `help` field in extension manifest")
//pass ref to manifest to each command
for i := range extManifest.ExtCommand {
extManifest.ExtCommand[i].Manifest = extManifest
}
return extManifest, nil
return extManifest, validManifest(extManifest)
}
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")
}
}
return nil
}
// ExtensionRegisterCommand - Register a new extension command
func ExtensionRegisterCommand(extCmd *ExtensionManifest, cmd *cobra.Command, con *console.SliverConsoleClient) {
func ExtensionRegisterCommand(extCmd *ExtCommand, cmd *cobra.Command, con *console.SliverConsoleClient) {
if errInvalidArgs := checkExtensionArgs(extCmd); errInvalidArgs != nil {
con.PrintErrorf(errInvalidArgs.Error())
return
}
loadedExtensions[extCmd.CommandName] = extCmd
helpMsg := extCmd.Help
//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(), //extCmd.CommandName,
//Short: helpMsg.String(), doesn't appear to be used?
Long: help.FormatHelpTmpl(longHelp.String()),
Run: func(cmd *cobra.Command, args []string) {
runExtensionCmd(cmd, con, args)
},
@@ -197,7 +332,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 +345,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.SliverConsoleClient) error {
var extensionList []string
binPath, err := ext.getFileForTarget(cmd.Name(), goos, goarch)
binPath, err := ext.getFileForTarget(goos, goarch)
if err != nil {
return err
}
@@ -233,10 +368,12 @@ func loadExtension(goos string, goarch string, checkCache bool, ext *ExtensionMa
}
depLoaded := false
for _, extName := range extensionList {
if !depLoaded && extName == ext.DependsOn {
depLoaded = true
if !depLoaded {
if extN, ok := loadedExtensions[cmd.Name()]; ok && extName == extN.DependsOn {
depLoaded = true
}
}
if ext.CommandName == extName {
if extN, ok := loadedExtensions[cmd.Name()]; ok && extN.CommandName == extName {
return nil
}
}
@@ -261,12 +398,12 @@ 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.SliverConsoleClient) error {
registerResp, err := con.Rpc.RegisterExtension(context.Background(), &sliverpb.RegisterExtensionReq{
Name: ext.CommandName,
Data: binData,
OS: goos,
Init: ext.Init,
Name: ext.CommandName,
Data: binData,
OS: goos,
//Init: ext.Init, ?
Request: con.ActiveTarget.Request(cmd),
})
if err != nil {
@@ -281,7 +418,7 @@ func registerExtension(goos string, ext *ExtensionManifest, binData []byte, cmd
func loadDep(goos string, goarch string, depName string, cmd *cobra.Command, con *console.SliverConsoleClient) 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
}
@@ -327,7 +464,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
@@ -351,8 +488,17 @@ func runExtensionCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args
entryPoint = loadedExtensions[extName].Entrypoint // should exist at this point
} else {
// Regular DLL
extArgs := strings.Join(args, " ")
extensionArgs = []byte(extArgs)
// extArgs := strings.Join(args, " ")
//legacy case - single string arg
if len(ext.Arguments) == 1 && ext.Arguments[0].Type == "string" {
extensionArgs = []byte(strings.Join(args, " "))
} else {
extensionArgs, err = getExtArgs(cmd, args, binPath, ext)
if err != nil {
con.PrintErrorf("ext args error: %s\n", err)
return
}
}
extName = ext.CommandName
entryPoint = ext.Entrypoint
}
@@ -404,12 +550,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(cmd *cobra.Command, args []string, binPath string, ext *ExtCommand) ([]byte, error) {
var err error
argsBuffer := core.BOFArgsBuffer{
Buffer: new(bytes.Buffer),
}
@@ -486,6 +628,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 +651,10 @@ func getBOFArgs(cmd *cobra.Command, args []string, binPath string, ext *Extensio
if err != nil {
return nil, err
}
parsedArgs, err := getExtArgs(cmd, args, binPath, ext)
if err != nil {
return nil, err
}
err = extensionArgsBuffer.AddData(parsedArgs)
if err != nil {
return nil, err
@@ -520,7 +677,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 +693,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 +715,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)
+35 -3
View File
@@ -45,12 +45,22 @@ 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)
}
}
@@ -71,6 +81,28 @@ 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.SliverConsoleClient) (bool, error) {
if manifestName == "" {
return false, errors.New("command name is required")
}
if man, ok := loadedManifests[manifestName]; ok {
//foudn the manifest
//delet it
extPath := filepath.Join(assets.GetExtensionsDir(), filepath.Base(manifestName))
if _, err := os.Stat(extPath); os.IsNotExist(err) {
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)
+3 -2
View File
@@ -56,8 +56,9 @@ func CatCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []string)
ctrl := make(chan bool)
con.SpinUntil(fmt.Sprintf("Downloading %s ...", filePath), ctrl)
download, err := con.Rpc.Download(context.Background(), &sliverpb.DownloadReq{
Request: con.ActiveTarget.Request(cmd),
Path: filePath,
Request: con.ActiveTarget.Request(cmd),
RestrictedToFile: true,
Path: filePath,
})
ctrl <- true
<-ctrl
+82
View File
@@ -0,0 +1,82 @@
package filesystem
/*
Sliver Implant Framework
Copyright (C) 2019 Bishop Fox
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import (
"context"
"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"
)
func CpCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []string) (err error) {
session, beacon := con.ActiveTarget.GetInteractive()
if session == nil && beacon == nil {
return
}
if len(args) != 2 {
con.PrintErrorf("Please specify a source and destination filename.\n")
return
}
src := args[0]
dst := args[1]
cp, err := con.Rpc.Cp(context.Background(), &sliverpb.CpReq{
Request: con.ActiveTarget.Request(cmd),
Src: src,
Dst: dst,
})
if err != nil {
con.PrintErrorf("%s\n", err)
return
}
cp.Src, cp.Dst = src, dst
if cp.Response != nil && cp.Response.Async {
con.AddBeaconCallback(cp.Response.TaskID, func(task *clientpb.BeaconTask) {
err = proto.Unmarshal(task.Response, cp)
if err != nil {
con.PrintErrorf("Failed to decode response %s\n", err)
return
}
})
con.PrintAsyncResponse(cp.Response)
} else {
PrintCp(cp, con)
}
return
}
func PrintCp(cp *sliverpb.Cp, con *console.SliverConsoleClient) {
if cp.Response != nil && cp.Response.Err != "" {
con.PrintErrorf("%s\n", cp.Response.Err)
return
}
con.PrintInfof("Copied '%s' to '%s' (%d bytes written)\n", cp.Src, cp.Dst, cp.BytesWritten)
}
+10 -4
View File
@@ -51,9 +51,10 @@ func DownloadCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []st
ctrl := make(chan bool)
con.SpinUntil(fmt.Sprintf("Downloading %s ...", remotePath), ctrl)
download, err := con.Rpc.Download(context.Background(), &sliverpb.DownloadReq{
Request: con.ActiveTarget.Request(cmd),
Path: remotePath,
Recurse: recurse,
Request: con.ActiveTarget.Request(cmd),
Path: remotePath,
Recurse: recurse,
RestrictedToFile: false,
})
ctrl <- true
<-ctrl
@@ -119,7 +120,12 @@ func HandleDownloadResponse(download *sliverpb.Download, cmd *cobra.Command, arg
}
remotePath := args[0]
localPath := args[1]
var localPath string
if len(args) == 1 {
localPath = "."
} else {
localPath = args[1]
}
saveLoot, _ := cmd.Flags().GetBool("loot")
if download.ReadFiles == 0 {
+304
View File
@@ -0,0 +1,304 @@
package filesystem
/*
Sliver Implant Framework
Copyright (C) 2023 Bishop Fox
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import (
"context"
"fmt"
"regexp"
"strings"
"time"
"github.com/bishopfox/sliver/client/command/loot"
"github.com/bishopfox/sliver/client/console"
"github.com/bishopfox/sliver/protobuf/clientpb"
"github.com/bishopfox/sliver/protobuf/sliverpb"
"github.com/fatih/color"
"github.com/spf13/cobra"
"google.golang.org/protobuf/proto"
)
const maxLinesDisplayed = 50
func processFlags(searchPattern string, insensitive bool, exact bool) string {
if !insensitive && !exact {
return searchPattern
}
var processedSearchPattern = searchPattern
flagsAtBeginning, _ := regexp.Compile(`^\(\?.*\)`)
flagsSpecifiedIndex := flagsAtBeginning.FindStringIndex(searchPattern)
if insensitive {
if flagsSpecifiedIndex != nil {
// If we matched, flagsSpecifiedIndex[0] will always be 0 (the start of the string)
flags := searchPattern[:flagsSpecifiedIndex[1]]
if !strings.Contains(flags, "i") {
processedSearchPattern = "(?i" + searchPattern[2:]
}
} else {
processedSearchPattern = "(?i)" + processedSearchPattern
}
}
// For exact matches, we will replace any start and end of line anchors with (^|\s) and (\s|$) respectively
flagsSpecifiedIndex = flagsAtBeginning.FindStringIndex(processedSearchPattern)
if exact {
var endIndexOfFlags = 0
if flagsSpecifiedIndex != nil {
endIndexOfFlags = flagsSpecifiedIndex[1]
}
if strings.HasPrefix(processedSearchPattern[endIndexOfFlags:], "^") {
processedSearchPattern = processedSearchPattern[:endIndexOfFlags] + strings.Replace(processedSearchPattern[endIndexOfFlags:], "^", `(^|\s)`, 1)
} else {
processedSearchPattern = `(^|\s)` + processedSearchPattern
}
if strings.HasSuffix(processedSearchPattern, "$") {
processedSearchPattern = processedSearchPattern[:len(processedSearchPattern)-1] + `(\s|$)`
} else {
processedSearchPattern = processedSearchPattern + `(\s|$)`
}
}
return processedSearchPattern
}
func GrepCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []string) {
session, beacon := con.ActiveTarget.GetInteractive()
if session == nil && beacon == nil {
return
}
searchPattern := args[0]
searchPath := args[1]
recursive, _ := cmd.Flags().GetBool("recursive")
insensitive, _ := cmd.Flags().GetBool("insensitive")
exact, _ := cmd.Flags().GetBool("exact")
searchPatternProcessed := processFlags(searchPattern, insensitive, exact)
// Sanity check the search pattern to validate that it is a valid regex
_, err := regexp.Compile(searchPattern)
if err != nil {
con.PrintErrorf("%s is not a valid regex: %s\n", searchPattern, err)
return
}
// Context overrides individual values for before and after
var linesBefore int32 = 0
var linesAfter int32 = 0
if cmd.Flags().Changed("context") {
linesBefore, _ = cmd.Flags().GetInt32("context")
linesAfter = linesBefore
} else {
linesBefore, _ = cmd.Flags().GetInt32("before")
linesAfter, _ = cmd.Flags().GetInt32("after")
}
ctrl := make(chan bool)
con.SpinUntil(fmt.Sprintf("Searching for %s in %s ...", searchPattern, searchPath), ctrl)
grep, err := con.Rpc.Grep(context.Background(), &sliverpb.GrepReq{
Request: con.ActiveTarget.Request(cmd),
SearchPattern: searchPatternProcessed,
Path: searchPath,
Recursive: recursive,
LinesBefore: linesBefore,
LinesAfter: linesAfter,
})
ctrl <- true
<-ctrl
if err != nil {
con.PrintErrorf("%s\n", err)
return
}
if grep.Response != nil && grep.Response.Async {
con.AddBeaconCallback(grep.Response.TaskID, func(task *clientpb.BeaconTask) {
err = proto.Unmarshal(task.Response, grep)
if err != nil {
con.PrintErrorf("Failed to decode response %s\n", err)
return
}
// Using args[0] so that the operator's original input is preserved
printGrep(grep, args[0], searchPath, cmd, con)
})
con.PrintAsyncResponse(grep.Response)
} else {
printGrep(grep, args[0], searchPath, cmd, con)
}
}
// printGrep - Print the results from the grep operation to stdout
func printGrep(grep *sliverpb.Grep, searchPattern string, searchPath string, cmd *cobra.Command, con *console.SliverConsoleClient) {
saveLoot, _ := cmd.Flags().GetBool("loot")
lootName, _ := cmd.Flags().GetString("name")
colorize, _ := cmd.Flags().GetBool("colorize-output")
userLootFileType, _ := cmd.Flags().GetString("file-type")
currentDateTime := time.Now().Format("2006-01-02_150405")
if !cmd.Flags().Changed("lootName") {
// If the loot name has not been specified by the operator, generate one
con.GetActiveSessionConfig()
lootName = fmt.Sprintf("grep from %s on %s (%s)", searchPath, con.GetActiveSessionConfig().ID, currentDateTime)
}
if grep.Response != nil && grep.Response.Err != "" {
con.PrintErrorf("%s\n", grep.Response.Err)
return
}
grepResults, numberOfResults, binaryFilesMatched := printGrepResults(grep.Results, colorize, true)
if len(grepResults) > maxLinesDisplayed {
// If there are more than maxResultsDisplayed results, then loot the rest so that we do not overfill the console
saveLoot = true
}
var resultQualifier string
var displayLimit string
if numberOfResults == 1 {
resultQualifier = "line"
} else {
resultQualifier = "lines"
}
if len(grepResults) > maxLinesDisplayed {
displayLimit = fmt.Sprintf(" (%d displayed, including context if available)", maxLinesDisplayed)
}
con.Printf("Found %d matching %s for %s in %s%s\n\n", numberOfResults, resultQualifier, searchPattern, searchPath, displayLimit)
if len(grepResults) > maxLinesDisplayed {
con.Println(strings.Join(grepResults[:maxLinesDisplayed+1], "\n"))
} else {
con.Println(strings.Join(grepResults, "\n"))
}
if len(grepResults) > maxLinesDisplayed {
con.PrintWarnf("Number of output lines exceed %d. The full output is available in the loot file \"%s\"\n", maxLinesDisplayed, lootName)
}
if len(binaryFilesMatched) > 0 {
con.PrintInfof("The following binary files contained one or more matches that may not be reflected above:\n")
for _, fileName := range binaryFilesMatched {
con.Printf("\t%s\n", fileName)
}
}
if saveLoot {
// Do not allow escape sequences in the output when looting
grepResultsForLoot, numberOfResults, binaryFilesMatched := printGrepResults(grep.Results, false, false)
lootFileName := fmt.Sprintf("grep_%s_%s.txt", con.GetActiveSessionConfig().ID, currentDateTime)
flags := []string{}
if recursive, _ := cmd.Flags().GetBool("recursive"); recursive {
flags = append(flags, "recursive")
}
if exact, _ := cmd.Flags().GetBool("exact"); exact {
flags = append(flags, "exact match")
}
if insensitive, _ := cmd.Flags().GetBool("insensitive"); insensitive {
flags = append(flags, "case insensitive search")
}
// Add a header to the looted grep results to indicate what the pattern was and what was searched
grepResultsString := fmt.Sprintf("Search pattern: %s\nSearch location: %s\n", searchPattern, grep.SearchPathAbsolute)
if len(flags) > 0 {
grepResultsString += fmt.Sprintf("Search flags: %s\n", strings.Join(flags, ", "))
}
grepResultsString += fmt.Sprintf("Number of Results: %d\n\n%s", numberOfResults, strings.Join(grepResultsForLoot, "\n"))
if len(binaryFilesMatched) > 0 {
grepResultsString += "\nThe following binary files contained one or more matches:\n"
grepResultsString += strings.Join(binaryFilesMatched, "\n")
}
fileType := loot.ValidateLootFileType(userLootFileType, []byte(grepResultsString))
loot.LootText(grepResultsString, lootName, lootFileName, fileType, con)
}
}
// grepLineResult - Add color or formatting for results for console output
func grepLineResult(positions []*sliverpb.GrepLinePosition, line string, colorize bool, allowFormatting bool) string {
var result string = ""
var matchOutput func(a ...interface{}) string
var previousPositionEnd int32 = 0
if colorize {
matchOutput = color.New(color.FgRed, color.Bold).SprintFunc()
} else if allowFormatting {
matchOutput = color.New(color.Bold).SprintFunc()
}
for idx, position := range positions {
if colorize || allowFormatting {
result += line[previousPositionEnd:position.Start]
result += matchOutput(line[position.Start:position.End])
if idx == len(positions)-1 {
result += line[position.End:]
} else {
previousPositionEnd = position.End
}
} else {
result = line
}
}
return result
}
// printGrepResults - Take the results from the implant and put them together for output to the console or loot
func printGrepResults(results map[string]*sliverpb.GrepResultsForFile, colorize bool, allowFormatting bool) ([]string, int, []string) {
var resultOutput []string
var numberOfResults = 0
binaryFilesMatched := []string{}
for fileName, result := range results {
if result.IsBinary {
if len(result.FileResults) > 0 {
binaryFilesMatched = append(binaryFilesMatched, fileName)
}
}
for _, lineResult := range result.FileResults {
line := lineResult.Line
if len(lineResult.LinesBefore) > 0 || len(lineResult.LinesAfter) > 0 {
resultOutput = append(resultOutput, fmt.Sprintf("%s (match on line %d)\n", fileName, lineResult.LineNumber))
if len(lineResult.LinesBefore) > 0 {
resultOutput = append(resultOutput, strings.Join(lineResult.LinesBefore, "\n"))
}
resultOutput = append(resultOutput, grepLineResult(lineResult.Positions, line, colorize, allowFormatting))
if len(lineResult.LinesAfter) > 0 {
resultOutput = append(resultOutput, strings.Join(lineResult.LinesAfter, "\n"))
}
resultOutput = append(resultOutput, "\n")
} else {
if lineResult.LineNumber == -1 {
resultOutput = append(resultOutput, fmt.Sprintf("Error when reading file %s: %s", fileName, line))
} else {
resultOutput = append(resultOutput, fmt.Sprintf("%s: Line %d: %s", fileName, lineResult.LineNumber, grepLineResult(lineResult.Positions, line, colorize, allowFormatting)))
}
}
numberOfResults += 1
}
}
return resultOutput, numberOfResults, binaryFilesMatched
}
+127
View File
@@ -0,0 +1,127 @@
package filesystem
/*
Sliver Implant Framework
Copyright (C) 2023 Bishop Fox
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import (
"context"
"fmt"
"github.com/bishopfox/sliver/client/console"
"github.com/bishopfox/sliver/protobuf/clientpb"
"github.com/bishopfox/sliver/protobuf/sliverpb"
"github.com/spf13/cobra"
"google.golang.org/protobuf/proto"
)
func HeadCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []string, head bool) {
session, beacon := con.ActiveTarget.GetInteractive()
if session == nil && beacon == nil {
return
}
var filePath string
var fetchBytes bool
var fetchSize int64
var operationName string
var download *sliverpb.Download
var err error
if len(args) > 0 {
filePath = args[0]
}
if filePath == "" {
con.PrintErrorf("Missing parameter: file name\n")
return
}
if cmd.Flags().Changed("bytes") {
fetchBytes = true
fetchSize, _ = cmd.Flags().GetInt64("bytes")
if fetchSize < 0 {
// Cannot fetch a negative number of bytes
con.PrintErrorf("The number of bytes specified must be positive.")
return
}
if fetchSize == 1 {
operationName = "byte"
} else {
operationName = "bytes"
}
} else if cmd.Flags().Changed("lines") {
fetchBytes = false
fetchSize, _ = cmd.Flags().GetInt64("lines")
if fetchSize < 0 {
// Cannot fetch a negative number of lines
con.PrintErrorf("The number of lines specified must be positive.")
return
}
if fetchSize == 1 {
operationName = "line"
} else {
operationName = "lines"
}
} else {
con.PrintErrorf("A number of bytes or a number of lines must be specified.")
return
}
ctrl := make(chan bool)
con.SpinUntil(fmt.Sprintf("Retrieving %d %s from %s ...", fetchSize, operationName, filePath), ctrl)
// A tail is a negative head
if !head {
fetchSize *= -1
}
if fetchBytes {
download, err = con.Rpc.Download(context.Background(), &sliverpb.DownloadReq{
Request: con.ActiveTarget.Request(cmd),
Path: filePath,
MaxBytes: fetchSize,
RestrictedToFile: true,
})
} else {
download, err = con.Rpc.Download(context.Background(), &sliverpb.DownloadReq{
Request: con.ActiveTarget.Request(cmd),
Path: filePath,
MaxLines: fetchSize,
RestrictedToFile: true,
})
}
ctrl <- true
<-ctrl
if err != nil {
con.PrintErrorf("%s\n", err)
return
}
if download.Response != nil && download.Response.Async {
con.AddBeaconCallback(download.Response.TaskID, func(task *clientpb.BeaconTask) {
err = proto.Unmarshal(task.Response, download)
if err != nil {
con.PrintErrorf("Failed to decode response %s\n", err)
return
}
PrintCat(download, cmd, con)
})
con.PrintAsyncResponse(download.Response)
} else {
PrintCat(download, cmd, con)
}
}
+4 -1
View File
@@ -43,7 +43,10 @@ func MemfilesRmCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []
}
fdInt, err := strconv.ParseInt(fdArg, 0, 64)
if err != nil {
con.PrintErrorf("Failed to parse fdArg: %s\n", err)
return
}
memfilesList, err := con.Rpc.MemfilesRm(context.Background(), &sliverpb.MemfilesRmReq{
Request: con.ActiveTarget.Request(cmd),
Fd: fdInt,
+149
View File
@@ -0,0 +1,149 @@
/*
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/>.
*/
package filesystem
import (
"context"
"fmt"
"math"
"google.golang.org/protobuf/proto"
"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/sliverpb"
)
// MountCmd - Print information about mounted filesystems
func MountCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []string) {
session, beacon := con.ActiveTarget.GetInteractive()
if session == nil && beacon == nil {
return
}
mount, err := con.Rpc.Mount(context.Background(), &sliverpb.MountReq{
Request: con.ActiveTarget.Request(cmd),
})
if err != nil {
con.PrintErrorf("%s\n", err)
return
}
os := getOS(session, beacon)
if mount.Response != nil && mount.Response.Async {
con.AddBeaconCallback(mount.Response.TaskID, func(task *clientpb.BeaconTask) {
err = proto.Unmarshal(task.Response, mount)
if err != nil {
con.PrintErrorf("Failed to decode response %s\n", err)
return
}
PrintMount(os, mount, con)
})
con.PrintAsyncResponse(mount.Response)
} else {
PrintMount(os, mount, con)
}
}
func getOS(session *clientpb.Session, beacon *clientpb.Beacon) string {
if session != nil {
return session.OS
} else if beacon != nil {
return beacon.OS
}
return ""
}
func reduceSpaceMetric(numberOfBytes float64) string {
units := []string{"B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"}
if numberOfBytes < 1 {
return fmt.Sprintf("0 %s", units[0])
}
base := 1024.0
exp := math.Floor(math.Log(numberOfBytes) / math.Log(base))
index := int(math.Min(exp, float64(len(units)-1)))
divisor := math.Pow(base, float64(index))
value := numberOfBytes / divisor
return fmt.Sprintf("%.2f %s", value, units[index])
}
// PrintMount - Print a table containing information on mounted filesystems
func PrintMount(os string, mount *sliverpb.Mount, con *console.SliverConsoleClient) {
if mount.Response != nil && mount.Response.Err != "" {
con.PrintErrorf("%s\n", mount.Response.Err)
return
}
tw := table.NewWriter()
tw.SetStyle(settings.GetTableStyle(con))
switch os {
case "windows":
tw.AppendHeader(table.Row{"Volume", "Volume Type", "Mount Point", "Label", "Filesystem", "Used Space", "Free Space", "Total Space"})
case "darwin":
fallthrough
case "linux":
fallthrough
default:
tw.AppendHeader(table.Row{"Source", "Mount Point", "Mount Root", "Filesystem Type", "Options", "Total Space"})
}
for _, mountPoint := range mount.Info {
row := mountRow(os, mountPoint)
tw.AppendRow(row)
}
settings.PaginateTable(tw, 0, false, false, con)
}
func mountRow(os string, mountInfo *sliverpb.MountInfo) table.Row {
var row table.Row
switch os {
case "windows":
row = table.Row{mountInfo.VolumeName,
mountInfo.VolumeType,
mountInfo.MountPoint,
mountInfo.Label,
mountInfo.FileSystem,
reduceSpaceMetric(float64(mountInfo.UsedSpace)),
reduceSpaceMetric(float64(mountInfo.FreeSpace)),
reduceSpaceMetric(float64(mountInfo.TotalSpace)),
}
case "darwin":
fallthrough
case "linux":
fallthrough
default:
row = table.Row{mountInfo.VolumeName,
mountInfo.MountPoint,
mountInfo.Label,
mountInfo.VolumeType,
mountInfo.MountOptions,
reduceSpaceMetric(float64(mountInfo.TotalSpace)),
}
}
return row
}
+356 -20
View File
@@ -19,34 +19,277 @@ package filesystem
*/
import (
"archive/tar"
"bytes"
"context"
"errors"
"fmt"
"io/ioutil"
"io"
"io/fs"
"os"
"path/filepath"
"strings"
"google.golang.org/protobuf/proto"
"github.com/spf13/cobra"
"github.com/bishopfox/sliver/client/console"
"github.com/bishopfox/sliver/implant/sliver/handlers/matcher"
"github.com/bishopfox/sliver/protobuf/clientpb"
"github.com/bishopfox/sliver/protobuf/sliverpb"
"github.com/bishopfox/sliver/util/encoders"
)
func determineDirPathFilter(targetPath string) (string, string) {
// The filter
filter := ""
// The path the filter applies to
path := ""
/*
Check to see if the remote path is a filter or contains a filter.
If the path passes the test to be a filter, then it is a filter
because paths are not valid filters.
*/
if targetPath != "." {
// Check if the path contains a filter
// Test on a standardized version of the path (change any \ to /)
testPath := strings.Replace(targetPath, "\\", "/", -1)
/*
Cannot use the path or filepath libraries because the OS
of the client does not necessarily match the OS of the
implant
*/
lastSeparatorOccurrence := strings.LastIndex(testPath, "/")
if lastSeparatorOccurrence == -1 {
// Then this is only a filter
filter = targetPath
path = "."
} else {
// Then we need to test for a filter on the end of the string
// The indices should be the same because we did not change the length of the string
path = targetPath[:lastSeparatorOccurrence+1]
filter = targetPath[lastSeparatorOccurrence+1:]
}
} else {
path = targetPath
// filter remains blank
}
return path, filter
}
func standarizeArchiveFileName(path string, uploadPathSpecified string) string {
// Change all backslashes to forward slashes
var standardFilePath string = strings.ReplaceAll(path, "\\", "/")
var standardUploadPath string = strings.ReplaceAll(uploadPathSpecified, "\\", "/")
/*
Remove the volume / root from the directory
path. This makes it so that files on the
system where the archive is extracted to
will not be clobbered.
Tried with filepath.VolumeName, but that function
does not work reliably with Windows paths
*/
if strings.HasPrefix(standardFilePath, "//") {
// If this a UNC path, filepath.Rel is not going to work
return standardFilePath[2:]
} else {
beginningOfUploadPath, _, _ := strings.Cut(standardUploadPath, "/")
if index := strings.Index(standardFilePath, beginningOfUploadPath); index != -1 {
// Add a / in front to make the specified upload path the root
standardFilePath = "/" + standardFilePath[index:]
}
// Calculate a path relative to the root
pathParts := strings.SplitN(standardFilePath, "/", 2)
if len(pathParts) < 2 {
// Then something is wrong with this path
return standardFilePath
}
basePath := pathParts[0]
fileRelPath := pathParts[1]
if basePath == "" {
// If base path is blank, that means it started with / and / is the root
return fileRelPath
} else {
/*
Then this is almost certainly Windows, and we will set the archive up
so that it preserves the path but without the colon.
Something like:
c/windows/system32/file.whatever
Colons are not legal in Windows filenames, so let's get rid of them.
*/
basePath = strings.ReplaceAll(basePath, ":", "")
basePath = strings.ToLower(basePath)
return basePath + "/" + fileRelPath
}
}
}
func tarDirectory(sourcePath string, pathAsSpecified string, sourceFilter string, recurse bool, preserveDirStructure bool) ([]byte, int, int, error) {
readFiles := 0
unreadableFiles := 0
var matchingFiles []string
var buffer bytes.Buffer
tarWriter := tar.NewWriter(&buffer)
/*
Build the list of files to include in the archive.
Walking the directory can take a long time and do a lot of unnecessary work
if we do not need to recurse through subdirectories.
If we are not recursing, then read the directory without worrying about
subdirectories.
*/
if !recurse {
testPath := strings.ReplaceAll(sourcePath, "\\", "/")
directory, err := os.Open(sourcePath)
if err != nil {
return nil, readFiles, unreadableFiles, err
}
directoryFiles, err := directory.Readdirnames(0)
directory.Close()
if err != nil {
return nil, readFiles, unreadableFiles, err
}
for _, fileName := range directoryFiles {
standardFileName := strings.ReplaceAll(testPath+fileName, "\\", "/")
if sourceFilter != "" {
match, err := matcher.Match(sourcePath+sourceFilter, standardFileName)
if err == nil && match {
matchingFiles = append(matchingFiles, standardFileName)
}
} else {
matchingFiles = append(matchingFiles, standardFileName)
}
}
} else {
filepath.WalkDir(sourcePath, func(file string, d os.DirEntry, err error) error {
filePath := strings.ReplaceAll(file, "\\", "/")
if sourceFilter != "" {
// Normalize paths
testPath := strings.ReplaceAll(filepath.Dir(file), "\\", "/") + "/"
match, matchErr := matcher.Match(testPath+sourceFilter, filePath)
if !match || matchErr != nil {
// If there is an error, it is because the filter is bad, so it is not a match
return nil
}
matchingFiles = append(matchingFiles, file)
} else {
matchingFiles = append(matchingFiles, file)
}
return nil
})
}
var fileName string
for _, file := range matchingFiles {
fi, err := os.Stat(file)
if err != nil {
// Cannot get info on the file, so skip it
unreadableFiles += 1
continue
}
if preserveDirStructure {
fileName = standarizeArchiveFileName(file, pathAsSpecified)
} else {
fileName = fi.Name()
}
// If the file is a SymLink replace fileInfo and path with the symlink destination.
if fi.Mode()&os.ModeSymlink == os.ModeSymlink {
file, err = filepath.EvalSymlinks(file)
if err != nil {
unreadableFiles += 1
continue
}
fi, err = os.Lstat(file)
if err != nil {
unreadableFiles += 1
continue
}
}
header, err := tar.FileInfoHeader(fi, file)
if err != nil {
unreadableFiles += 1
continue
}
// Keep the symlink file path for the header name.
header.Name = filepath.ToSlash(fileName)
// Check that we can open the file before we try to write it to the archive
if !fi.IsDir() {
data, err := os.Open(file)
if err != nil {
// Skip this file and do not write it to the archive.
unreadableFiles += 1
continue
}
if err := tarWriter.WriteHeader(header); err != nil {
unreadableFiles += 1
data.Close()
continue
}
if _, err := io.Copy(tarWriter, data); err != nil {
unreadableFiles += 1
data.Close()
continue
}
data.Close()
readFiles += 1
} else {
if err := tarWriter.WriteHeader(header); err != nil {
unreadableFiles += 1
continue
}
}
}
if err := tarWriter.Close(); err != nil {
return buffer.Bytes(), readFiles, unreadableFiles, err
}
return buffer.Bytes(), readFiles, unreadableFiles, nil
}
// UploadCmd - Upload a file to the remote system
func UploadCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []string) {
readFiles := 0
unreadableFiles := 0
var isDirectory bool
var fileName string
var sourceInfomation fs.FileInfo
var uploadData []byte
session, beacon := con.ActiveTarget.GetInteractive()
if session == nil && beacon == nil {
return
}
remotePath := ""
localPath := args[0]
remotePath := args[1]
// localPath := ctx.Args.String("local-path")
// remotePath := ctx.Args.String("remote-path")
if len(args) > 1 {
remotePath = args[1]
}
recurse, _ := cmd.Flags().GetBool("recurse")
preserve, _ := cmd.Flags().GetBool("preserve")
isIOC, _ := cmd.Flags().GetBool("ioc")
overwrite, _ := cmd.Flags().GetBool("overwrite")
if localPath == "" {
con.PrintErrorf("Missing parameter, see `help upload`\n")
@@ -54,33 +297,110 @@ func UploadCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []stri
}
src, _ := filepath.Abs(localPath)
_, err := os.Stat(src)
if err != nil {
con.PrintErrorf("%s\n", err)
return
}
if remotePath == "" {
fileName := filepath.Base(src)
remotePath = fileName
}
dst := remotePath
fileBuf, err := ioutil.ReadFile(src)
// Get information on the source - is it a directory?
srcPath, srcFilter := determineDirPathFilter(src)
sourceInfomation, err := os.Stat(src)
if err == nil && sourceInfomation.IsDir() {
if !strings.HasSuffix(src, string(os.PathSeparator)) {
src += string(os.PathSeparator)
}
srcPath = src
srcFilter = ""
}
if err != nil {
con.PrintErrorf("%s\n", err)
if errors.Is(err, fs.ErrNotExist) {
// Check to see if src ends with a filter
sourceInfomation, err = os.Stat(srcPath)
if errors.Is(err, fs.ErrNotExist) {
con.PrintErrorf("The source %s does not exist.\n", src)
return
} else if errors.Is(err, fs.ErrPermission) {
con.PrintErrorf("Permissions error when trying to read %s.\n", src)
return
}
}
if errors.Is(err, fs.ErrPermission) {
con.PrintErrorf("Permissions error when trying to read %s.\n", src)
return
}
}
// If we still do not have information about the source at this point, bail.
if sourceInfomation == nil {
con.PrintErrorf("Could not get information about the upload source %s\n", src)
return
}
uploadGzip, _ := new(encoders.Gzip).Encode(fileBuf)
if sourceInfomation.IsDir() {
// tar the directory and send it over
uploadData, readFiles, unreadableFiles, err = tarDirectory(srcPath, localPath, srcFilter, recurse, preserve)
if err != nil {
con.PrintErrorf("%s\n", err)
return
}
if readFiles == 0 {
con.PrintErrorf("Could not find any files matching %s\n", src)
return
}
isDirectory = true
fileName = ""
} else {
uploadData, err = os.ReadFile(src)
if err != nil {
con.PrintErrorf("%s\n", err)
return
}
readFiles = 1
unreadableFiles = 0
isDirectory = false
fileName = filepath.Base(src)
}
uploadGzip, _ := new(encoders.Gzip).Encode(uploadData)
var readFilesQualifier string
var unsuccessfulFiles string
if readFiles == 1 {
readFilesQualifier = ""
} else {
readFilesQualifier = "s"
}
if unreadableFiles > 0 {
if unreadableFiles == 1 {
unsuccessfulFiles = fmt.Sprintf(" (could not read %d file)", unreadableFiles)
} else {
unsuccessfulFiles = fmt.Sprintf(" (could not read %d files)", unreadableFiles)
}
} else {
unsuccessfulFiles = ""
}
ctrl := make(chan bool)
con.SpinUntil(fmt.Sprintf("%s -> %s", src, dst), ctrl)
con.SpinUntil(fmt.Sprintf("Uploading %d file%s %sfrom %s to %s", readFiles,
readFilesQualifier,
unsuccessfulFiles,
src,
dst), ctrl)
upload, err := con.Rpc.Upload(context.Background(), &sliverpb.UploadReq{
Request: con.ActiveTarget.Request(cmd),
Path: dst,
Data: uploadGzip,
Encoder: "gzip",
IsIOC: isIOC,
Request: con.ActiveTarget.Request(cmd),
Path: dst,
Data: uploadGzip,
Encoder: "gzip",
IsIOC: isIOC,
FileName: fileName,
IsDirectory: isDirectory,
Overwrite: overwrite,
})
ctrl <- true
<-ctrl
@@ -109,5 +429,21 @@ func PrintUpload(upload *sliverpb.Upload, con *console.SliverConsoleClient) {
con.PrintErrorf("%s\n", upload.Response.Err)
return
}
con.PrintInfof("Wrote file to %s\n", upload.Path)
writtenFileQualifier := "s"
if upload.WrittenFiles == 1 {
writtenFileQualifier = ""
}
unwrittenFileQualifier := "s"
if upload.UnwriteableFiles == 1 {
unwrittenFileQualifier = ""
}
if upload.WrittenFiles > 0 {
if upload.UnwriteableFiles > 0 {
con.PrintInfof("Wrote %d file%s successfully (%d file%s not written) to %s\n", upload.WrittenFiles, writtenFileQualifier, upload.UnwriteableFiles, unwrittenFileQualifier, upload.Path)
} else {
con.PrintInfof("Wrote %d file%s successfully to %s\n", upload.WrittenFiles, writtenFileQualifier, upload.Path)
}
} else {
con.PrintInfof("Could not write %d file%s to %s: the files already exist on the target\n", upload.UnwriteableFiles, unwrittenFileQualifier, upload.Path)
}
}
+3 -4
View File
@@ -18,7 +18,7 @@ var (
// GenerateBeaconCmd - The main command used to generate implant binaries
func GenerateBeaconCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []string) {
config := parseCompileFlags(cmd, con)
name, config := parseCompileFlags(cmd, con)
if config == nil {
return
}
@@ -33,10 +33,9 @@ func GenerateBeaconCmd(cmd *cobra.Command, con *console.SliverConsoleClient, arg
save, _ = os.Getwd()
}
if external, _ := cmd.Flags().GetBool("external-builder"); !external {
disableSGN, _ := cmd.Flags().GetBool("disable-sgn")
compile(config, disableSGN, save, con)
compile(config, save, con)
} else {
externalBuild(config, save, con)
externalBuild(name, config, save, con)
}
}
+37 -29
View File
@@ -90,7 +90,7 @@ var (
// GenerateCmd - The main command used to generate implant binaries
func GenerateCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []string) {
config := parseCompileFlags(cmd, con)
name, config := parseCompileFlags(cmd, con)
if config == nil {
return
}
@@ -99,10 +99,9 @@ func GenerateCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []st
save, _ = os.Getwd()
}
if external, _ := cmd.Flags().GetBool("external-builder"); !external {
disableSGN, _ := cmd.Flags().GetBool("disable-sgn")
compile(config, disableSGN, save, con)
compile(config, save, con)
} else {
_, err := externalBuild(config, save, con)
_, err := externalBuild(name, config, save, con)
if err != nil {
if err == ErrNoExternalBuilder {
con.PrintErrorf("There are no external builders currently connected to the server\n")
@@ -183,14 +182,14 @@ func nameOfOutputFormat(value clientpb.OutputFormat) string {
}
// Shared function that extracts the compile flags from the grumble context
func parseCompileFlags(cmd *cobra.Command, con *console.SliverConsoleClient) *clientpb.ImplantConfig {
func parseCompileFlags(cmd *cobra.Command, con *console.SliverConsoleClient) (string, *clientpb.ImplantConfig) {
var name string
if nameF, _ := cmd.Flags().GetString("name"); nameF != "" {
name = strings.ToLower(nameF)
if err := util.AllowedName(name); err != nil {
con.PrintErrorf("%s\n", err)
return nil
return "", nil
}
}
@@ -200,7 +199,7 @@ func parseCompileFlags(cmd *cobra.Command, con *console.SliverConsoleClient) *cl
mtlsC2, err := ParseMTLSc2(mtlsC2F)
if err != nil {
con.PrintErrorf("%s\n", err.Error())
return nil
return "", nil
}
c2s = append(c2s, mtlsC2...)
@@ -208,7 +207,7 @@ func parseCompileFlags(cmd *cobra.Command, con *console.SliverConsoleClient) *cl
wgC2, err := ParseWGc2(wgC2F)
if err != nil {
con.PrintErrorf("%s\n", err.Error())
return nil
return "", nil
}
wgKeyExchangePort, _ := cmd.Flags().GetUint32("key-exchange")
wgTcpCommsPort, _ := cmd.Flags().GetUint32("tcp-comms")
@@ -219,7 +218,7 @@ func parseCompileFlags(cmd *cobra.Command, con *console.SliverConsoleClient) *cl
httpC2, err := ParseHTTPc2(httpC2F)
if err != nil {
con.PrintErrorf("%s\n", err.Error())
return nil
return "", nil
}
c2s = append(c2s, httpC2...)
@@ -227,7 +226,7 @@ func parseCompileFlags(cmd *cobra.Command, con *console.SliverConsoleClient) *cl
dnsC2, err := ParseDNSc2(dnsC2F)
if err != nil {
con.PrintErrorf("%s\n", err.Error())
return nil
return "", nil
}
c2s = append(c2s, dnsC2...)
@@ -235,7 +234,7 @@ func parseCompileFlags(cmd *cobra.Command, con *console.SliverConsoleClient) *cl
namedPipeC2, err := ParseNamedPipec2(namedPipeC2F)
if err != nil {
con.PrintErrorf("%s\n", err.Error())
return nil
return "", nil
}
c2s = append(c2s, namedPipeC2...)
@@ -243,7 +242,7 @@ func parseCompileFlags(cmd *cobra.Command, con *console.SliverConsoleClient) *cl
tcpPivotC2, err := ParseTCPPivotc2(tcpPivotC2F)
if err != nil {
con.PrintErrorf("%s\n", err.Error())
return nil
return "", nil
}
c2s = append(c2s, tcpPivotC2...)
@@ -257,7 +256,7 @@ func parseCompileFlags(cmd *cobra.Command, con *console.SliverConsoleClient) *cl
if len(mtlsC2) == 0 && len(wgC2) == 0 && len(httpC2) == 0 && len(dnsC2) == 0 && len(namedPipeC2) == 0 && len(tcpPivotC2) == 0 {
con.PrintErrorf("Must specify at least one of --mtls, --wg, --http, --dns, --named-pipe, or --tcp-pivot\n")
return nil
return "", nil
}
rawCanaries, _ := cmd.Flags().GetString("canary")
@@ -290,6 +289,7 @@ func parseCompileFlags(cmd *cobra.Command, con *console.SliverConsoleClient) *cl
isSharedLib := false
isService := false
isShellcode := false
sgnEnabled := false
format, _ := cmd.Flags().GetString("format")
runAtLoad := false
@@ -304,6 +304,8 @@ func parseCompileFlags(cmd *cobra.Command, con *console.SliverConsoleClient) *cl
case "shellcode":
configFormat = clientpb.OutputFormat_SHELLCODE
isShellcode = true
sgnEnabled, _ = cmd.Flags().GetBool("disable-sgn")
sgnEnabled = !sgnEnabled
case "service":
configFormat = clientpb.OutputFormat_SERVICE
isService = true
@@ -318,20 +320,20 @@ func parseCompileFlags(cmd *cobra.Command, con *console.SliverConsoleClient) *cl
targetArch := strings.ToLower(targetArchF)
targetOS, targetArch = getTargets(targetOS, targetArch, con)
if targetOS == "" || targetArch == "" {
return nil
return "", nil
}
if configFormat == clientpb.OutputFormat_SHELLCODE && targetOS != "windows" {
con.PrintErrorf("Shellcode format is currently only supported on Windows\n")
return nil
return "", nil
}
if len(namedPipeC2) > 0 && targetOS != "windows" {
con.PrintErrorf("Named pipe pivoting can only be used in Windows.")
return nil
return "", nil
}
// Check to see if we can *probably* build the target binary
if !checkBuildTargetCompatibility(configFormat, targetOS, targetArch, con) {
return nil
return "", nil
}
var tunIP net.IP
@@ -340,7 +342,7 @@ func parseCompileFlags(cmd *cobra.Command, con *console.SliverConsoleClient) *cl
tunIP = net.ParseIP(uniqueWGIP.IP)
if err != nil {
con.PrintErrorf("Failed to generate unique ip for wg peer tun interface")
return nil
return "", nil
}
con.PrintInfof("Generated unique ip for wg peer tun interface: %s\n", tunIP.String())
}
@@ -351,19 +353,24 @@ func parseCompileFlags(cmd *cobra.Command, con *console.SliverConsoleClient) *cl
connectionStrategy, _ := cmd.Flags().GetString("strategy")
if connectionStrategy != "" && connectionStrategy != "s" && connectionStrategy != "r" && connectionStrategy != "rd" {
con.PrintErrorf("Invalid connection strategy: %s\n", connectionStrategy)
return nil
return "", nil
}
// Parse Traffic Encoder Args
httpC2Enabled := 0 < len(httpC2)
trafficEncodersEnabled, trafficEncoderAssets := parseTrafficEncoderArgs(cmd, httpC2Enabled, con)
c2Profile, _ := cmd.Flags().GetString("c2profile")
if c2Profile == "" {
c2Profile = consts.DefaultC2Profile
}
config := &clientpb.ImplantConfig{
GOOS: targetOS,
GOARCH: targetArch,
Name: name,
Debug: debug,
Evasion: evasion,
SGNEnabled: sgnEnabled,
ObfuscateSymbols: symbolObfuscation,
C2: c2s,
CanaryDomains: canaryDomains,
@@ -395,10 +402,11 @@ func parseCompileFlags(cmd *cobra.Command, con *console.SliverConsoleClient) *cl
TrafficEncodersEnabled: trafficEncodersEnabled,
Assets: trafficEncoderAssets,
DebugFile: debugFile,
DebugFile: debugFile,
HTTPC2ConfigName: c2Profile,
}
return config
return name, config
}
// parseTrafficEncoderArgs - parses the traffic encoder args and returns a bool indicating if traffic encoders are enabled
@@ -775,7 +783,7 @@ func ParseTCPPivotc2(args string) ([]*clientpb.ImplantC2, error) {
return c2s, nil
}
func externalBuild(config *clientpb.ImplantConfig, save string, con *console.SliverConsoleClient) (*commonpb.File, error) {
func externalBuild(name string, config *clientpb.ImplantConfig, save string, con *console.SliverConsoleClient) (*commonpb.File, error) {
potentialBuilders, err := findExternalBuilders(config, con)
if err != nil {
return nil, err
@@ -815,6 +823,7 @@ func externalBuild(config *clientpb.ImplantConfig, save string, con *console.Sli
con.PrintInfof("Creating external build ... ")
externalImplantConfig, err := con.Rpc.GenerateExternal(context.Background(), &clientpb.ExternalGenerateReq{
Name: name,
Config: config,
BuilderName: externalBuilder.Name,
})
@@ -824,7 +833,6 @@ func externalBuild(config *clientpb.ImplantConfig, save string, con *console.Sli
}
con.Printf("done\n")
var name string
msgF := "Waiting for external builder to acknowledge build (template: %s) ... %s"
for waiting {
select {
@@ -842,13 +850,13 @@ func externalBuild(config *clientpb.ImplantConfig, save string, con *console.Sli
if len(parts) != 2 {
continue
}
if parts[0] == externalImplantConfig.Config.ID {
if parts[0] == externalImplantConfig.Build.ID {
con.RemoveEventListener(listenerID)
return nil, fmt.Errorf("external build failed: %s", parts[1])
}
case consts.AcknowledgeBuildEvent:
if string(event.Data) == externalImplantConfig.Config.ID {
if string(event.Data) == externalImplantConfig.Build.ID {
msgF = "External build acknowledged by builder (template: %s) ... %s"
}
@@ -857,7 +865,7 @@ func externalBuild(config *clientpb.ImplantConfig, save string, con *console.Sli
if len(parts) != 2 {
continue
}
if parts[0] == externalImplantConfig.Config.ID {
if parts[0] == externalImplantConfig.Build.ID {
con.RemoveEventListener(listenerID)
name = parts[1]
waiting = false
@@ -898,7 +906,7 @@ func externalBuild(config *clientpb.ImplantConfig, save string, con *console.Sli
return nil, nil
}
func compile(config *clientpb.ImplantConfig, disableSGN bool, save string, con *console.SliverConsoleClient) (*commonpb.File, error) {
func compile(config *clientpb.ImplantConfig, save string, con *console.SliverConsoleClient) (*commonpb.File, error) {
if config.IsBeacon {
interval := time.Duration(config.BeaconInterval)
con.PrintInfof("Generating new %s/%s beacon implant binary (%v)\n", config.GOOS, config.GOARCH, interval)
@@ -934,7 +942,7 @@ func compile(config *clientpb.ImplantConfig, disableSGN bool, save string, con *
fileData := generated.File.Data
if config.IsShellcode {
if disableSGN {
if !config.SGNEnabled {
con.PrintErrorf("Shikata ga nai encoder is %sdisabled%s\n", console.Bold, console.Normal)
} else {
con.PrintInfof("Encoding shellcode with shikata ga nai ... ")
+33 -37
View File
@@ -14,46 +14,24 @@ import (
// GetSliverBinary - Get the binary of an implant based on it's profile
func GetSliverBinary(profile *clientpb.ImplantProfile, con *console.SliverConsoleClient) ([]byte, error) {
var data []byte
// get implant builds
builds, err := con.Rpc.ImplantBuilds(context.Background(), &commonpb.Empty{})
ctrl := make(chan bool)
con.SpinUntil("Compiling, please wait ...", ctrl)
generated, err := con.Rpc.Generate(context.Background(), &clientpb.GenerateReq{
Config: profile.Config,
})
ctrl <- true
<-ctrl
if err != nil {
con.PrintErrorf("Error generating implant\n")
return data, err
}
implantName := buildImplantName(profile.GetConfig().GetFileName())
_, ok := builds.GetConfigs()[implantName]
if implantName == "" || !ok {
// no built implant found for profile, generate a new one
con.PrintInfof("No builds found for profile %s, generating a new one\n", profile.GetName())
ctrl := make(chan bool)
con.SpinUntil("Compiling, please wait ...", ctrl)
generated, err := con.Rpc.Generate(context.Background(), &clientpb.GenerateReq{
Config: profile.Config,
})
ctrl <- true
<-ctrl
if err != nil {
con.PrintErrorf("Error generating implant\n")
return data, err
}
data = generated.GetFile().GetData()
profile.Config.FileName = generated.File.Name
_, err = con.Rpc.SaveImplantProfile(context.Background(), profile)
if err != nil {
con.PrintErrorf("Error updating implant profile\n")
return data, err
}
} else {
// Found a build, reuse that one
con.PrintInfof("Sliver name for profile: %s\n", implantName)
regenerate, err := con.Rpc.Regenerate(context.Background(), &clientpb.RegenerateReq{
ImplantName: implantName,
})
if err != nil {
return data, err
}
data = regenerate.GetFile().GetData()
data = generated.GetFile().GetData()
_, err = con.Rpc.SaveImplantProfile(context.Background(), profile)
if err != nil {
con.PrintErrorf("Error updating implant profile\n")
return data, err
}
return data, err
}
@@ -135,6 +113,24 @@ func FormatCompleter() carapace.Action {
})
}
// HTTPC2Completer - Completes the HTTP C2 PROFILES
func HTTPC2Completer(con *console.SliverConsoleClient) carapace.Action {
return carapace.ActionCallback(func(c carapace.Context) carapace.Action {
grpcCtx, cancel := con.GrpcContext(nil)
defer cancel()
httpC2Profiles, err := con.Rpc.GetHTTPC2Profiles(grpcCtx, &commonpb.Empty{})
if err != nil {
return carapace.ActionMessage("failed to fetch HTTP C2 profiles: %s", err.Error())
}
var results []string
for _, profile := range httpC2Profiles.Configs {
results = append(results, profile.Name)
}
return carapace.ActionValues(results...).Tag("HTTP C2 Profiles")
})
}
// TrafficEncoderCompleter - Completes the names of traffic encoders
func TrafficEncodersCompleter(con *console.SliverConsoleClient) carapace.Action {
return carapace.ActionCallback(func(c carapace.Context) carapace.Action {
+39
View File
@@ -0,0 +1,39 @@
package generate
import (
"context"
"github.com/AlecAivazis/survey/v2"
"github.com/spf13/cobra"
"github.com/bishopfox/sliver/client/console"
"github.com/bishopfox/sliver/protobuf/clientpb"
"github.com/bishopfox/sliver/protobuf/commonpb"
)
// ImplantsStageCmd - Serve a previously generated build
func ImplantsStageCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []string) {
builds, err := con.Rpc.ImplantBuilds(context.Background(), &commonpb.Empty{})
if err != nil {
con.PrintErrorf("Unable to load implant builds '%s'\n", err)
return
}
options := []string{}
for name, _ := range builds.Configs {
options = append(options, name)
}
prompt := &survey.MultiSelect{
Message: "Select sessions and beacons to expose:",
Options: options,
}
selected := []string{}
survey.AskOne(prompt, &selected)
_, err = con.Rpc.StageImplantBuild(context.Background(), &clientpb.ImplantStageReq{Build: selected})
if err != nil {
con.PrintErrorf("Failed to serve implant %s\n", err)
return
}
}
+17 -5
View File
@@ -53,14 +53,14 @@ func ImplantsCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []st
implantBuildFilters := ImplantBuildFilter{}
if 0 < len(builds.Configs) {
PrintImplantBuilds(builds.Configs, implantBuildFilters, con)
PrintImplantBuilds(builds, implantBuildFilters, con)
} else {
con.PrintInfof("No implant builds\n")
}
}
// PrintImplantBuilds - Print the implant builds on the server
func PrintImplantBuilds(configs map[string]*clientpb.ImplantConfig, filters ImplantBuildFilter, con *console.SliverConsoleClient) {
func PrintImplantBuilds(builds *clientpb.ImplantBuilds, filters ImplantBuildFilter, con *console.SliverConsoleClient) {
tw := table.NewWriter()
tw.SetStyle(settings.GetTableStyle(con))
tw.AppendHeader(table.Row{
@@ -71,12 +71,15 @@ func PrintImplantBuilds(configs map[string]*clientpb.ImplantConfig, filters Impl
"Format",
"Command & Control",
"Debug",
"C2 Config",
"ID",
"Stage",
})
tw.SortBy([]table.SortBy{
{Name: "Name", Mode: table.Asc},
})
for sliverName, config := range configs {
for sliverName, config := range builds.Configs {
if filters.GOOS != "" && config.GOOS != filters.GOOS {
continue
}
@@ -97,9 +100,15 @@ func PrintImplantBuilds(configs map[string]*clientpb.ImplantConfig, filters Impl
continue
}
implantType := "session"
implantType := ""
if builds.ResourceIDs[sliverName].Type != "" {
implantType = builds.ResourceIDs[sliverName].Type
}
if config.IsBeacon {
implantType = "beacon"
implantType += "beacon"
} else {
implantType += "session"
}
c2URLs := []string{}
for index, c2 := range config.C2 {
@@ -116,6 +125,9 @@ func PrintImplantBuilds(configs map[string]*clientpb.ImplantConfig, filters Impl
config.Format,
strings.Join(c2URLs, "\n"),
fmt.Sprintf("%v", config.Debug),
fmt.Sprintf(config.HTTPC2ConfigName),
fmt.Sprintf("%v", builds.ResourceIDs[sliverName].Value),
fmt.Sprintf("%v", builds.Staged[sliverName]),
})
}
+4 -8
View File
@@ -19,7 +19,6 @@ package generate
*/
import (
"context"
"os"
"path/filepath"
"strings"
@@ -46,15 +45,12 @@ func ProfilesGenerateCmd(cmd *cobra.Command, con *console.SliverConsoleClient, a
}
profile := GetImplantProfileByName(name, con)
if profile != nil {
disableSGN, _ := cmd.Flags().GetBool("disable-sgn")
implantFile, err := compile(profile.Config, disableSGN, save, con)
if err != nil {
return
// If SGN is explicitly disabled, make sure this compilation reflects that despite whatever is set in the profile
if SGNDisabled, _ := cmd.Flags().GetBool("disable-sgn"); SGNDisabled {
profile.Config.SGNEnabled = !SGNDisabled
}
profile.Config.Name = buildImplantName(implantFile.Name)
_, err = con.Rpc.SaveImplantProfile(context.Background(), profile)
_, err := compile(profile.Config, save, con)
if err != nil {
con.PrintErrorf("could not update implant profile: %v\n", err)
return
}
} else {
+2 -2
View File
@@ -33,7 +33,7 @@ func ProfilesNewCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args [
name = args[0]
}
// name := ctx.Args.String("name")
config := parseCompileFlags(cmd, con)
_, config := parseCompileFlags(cmd, con)
if config == nil {
return
}
@@ -60,7 +60,7 @@ func ProfilesNewBeaconCmd(cmd *cobra.Command, con *console.SliverConsoleClient,
con.PrintErrorf("No profile name specified\n")
return
}
config := parseCompileFlags(cmd, con)
_, config := parseCompileFlags(cmd, con)
if config == nil {
return
}
+80
View File
@@ -0,0 +1,80 @@
package generate
/*
Sliver Implant Framework
Copyright (C) 2019 Bishop Fox
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import (
"context"
"os"
"strings"
"github.com/spf13/cobra"
"github.com/bishopfox/sliver/client/console"
"github.com/bishopfox/sliver/protobuf/clientpb"
)
// ProfilesStageCmd - Generate an encrypted/compressed implant binary based on a profile
func ProfilesStageCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []string) {
name, _ := cmd.Flags().GetString("name")
profileName := args[0]
aesEncryptKey, _ := cmd.Flags().GetString("aes-encrypt-key")
aesEncryptIv, _ := cmd.Flags().GetString("aes-encrypt-iv")
rc4EncryptKey, _ := cmd.Flags().GetString("rc4-encrypt-key")
prependSize, _ := cmd.Flags().GetBool("prepend-size")
compressF, _ := cmd.Flags().GetString("compress")
compress := strings.ToLower(compressF)
save, _ := cmd.Flags().GetString("save")
profile := GetImplantProfileByName(profileName, con)
if profile == nil {
con.PrintErrorf("Profile not found\n")
return
}
ctrl := make(chan bool)
con.SpinUntil("Compiling, please wait ...", ctrl)
stage2, err := con.Rpc.GenerateStage(context.Background(), &clientpb.GenerateStageReq{
Profile: profileName,
Name: name,
AESEncryptKey: aesEncryptKey,
AESEncryptIv: aesEncryptIv,
RC4EncryptKey: rc4EncryptKey,
PrependSize: prependSize,
Compress: compress,
})
ctrl <- true
<-ctrl
if err != nil {
con.PrintErrorf("%s\n", err)
return
}
saveTo, err := saveLocation(save, stage2.File.Name, con)
if err != nil {
con.PrintErrorf("%s\n", err)
return
}
err = os.WriteFile(saveTo, stage2.File.Data, 0o700)
if err != nil {
con.PrintErrorf("Failed to write to: %s\n", saveTo)
return
}
con.PrintInfof("Implant saved to %s\n", saveTo)
}
+304
View File
@@ -21,6 +21,7 @@ package generate
import (
"context"
"fmt"
"math"
"strings"
"github.com/jedib0t/go-pretty/v6/table"
@@ -61,6 +62,8 @@ func PrintProfiles(profiles []*clientpb.ImplantProfile, con *console.SliverConso
"Format",
"Obfuscation",
"Limitations",
"C2 Profile",
// "Nonce",
})
tw.SortBy([]table.SortBy{
{Name: "Profile Name", Mode: table.Asc},
@@ -90,6 +93,8 @@ func PrintProfiles(profiles []*clientpb.ImplantProfile, con *console.SliverConso
fmt.Sprintf("%v", config.Format),
obfuscation,
getLimitsString(config),
config.HTTPC2ConfigName,
// profile.ImplantID,
})
}
@@ -120,6 +125,305 @@ func GetImplantProfileByName(name string, con *console.SliverConsoleClient) *cli
return nil
}
func populateProfileProperties(config *clientpb.ImplantConfig) map[string]string {
properties := make(map[string]string)
var plural string
properties["osarch"] = fmt.Sprintf("%s %s", strings.Title(config.GOOS), strings.ToUpper(config.GOARCH))
if config.IsBeacon {
properties["implanttype"] = "Beacon"
jitter := int(config.BeaconJitter / int64(math.Pow10(9)))
plural = "s"
if jitter == 1 {
plural = ""
}
properties["beaconjitter"] = fmt.Sprintf("%d second%s", jitter, plural)
interval := int(config.BeaconInterval / int64(math.Pow10(9)))
plural = "s"
if interval == 1 {
plural = ""
}
properties["beaconinterval"] = fmt.Sprintf("%d second%s", interval, plural)
} else {
properties["implanttype"] = "Session"
}
if config.Debug {
properties["debugging"] = "enabled"
} else {
properties["debugging"] = "disabled"
}
if config.Evasion {
properties["evasion"] = "enabled"
} else {
properties["evasion"] = "disabled"
}
if config.ObfuscateSymbols {
properties["obsymbols"] = "enabled"
} else {
properties["obsymbols"] = "disabled"
}
if config.SGNEnabled {
properties["sgn"] = "enabled"
} else {
properties["sgn"] = "disabled"
}
reconnect := int(config.ReconnectInterval / int64(math.Pow10(9)))
if reconnect == 1 {
plural = ""
} else {
plural = "s"
}
properties["reconnect"] = fmt.Sprintf("%d second%s", reconnect, plural)
properties["maxerrors"] = fmt.Sprintf("%d", config.MaxConnectionErrors)
poll := int(config.PollTimeout / int64(math.Pow10(9)))
if poll == 1 {
plural = ""
} else {
plural = "s"
}
properties["polltimeout"] = fmt.Sprintf("%d second%s", poll, plural)
c2URLs := []string{}
for index, c2 := range config.C2 {
c2URLs = append(c2URLs, fmt.Sprintf("[%d] %s", index+1, c2.URL))
}
properties["implantC2"] = strings.Join(c2URLs, "\n")
properties["canary"] = strings.Join(config.CanaryDomains, "\n")
if config.ConnectionStrategy == "" {
properties["connectstrat"] = "Sequential"
} else if config.ConnectionStrategy == "r" {
properties["connectstrat"] = "Random"
} else if config.ConnectionStrategy == "rd" {
properties["connectstrat"] = "Random Domain"
} else {
properties["connectstrat"] = config.ConnectionStrategy
}
properties["outputlimits"] = "n"
if config.LimitDomainJoined {
properties["limit-domjoin"] = "Yes"
properties["outputlimits"] = "y"
} else {
properties["limit-domjoin"] = "No"
}
if config.LimitDatetime != "" {
properties["limit-dt"] = config.LimitDatetime
properties["outputlimits"] = "y"
} else {
properties["limit-dt"] = "No restriction"
}
if config.LimitFileExists != "" {
properties["limit-file"] = config.LimitFileExists
properties["outputlimits"] = "y"
} else {
properties["limit-file"] = "No restriction"
}
if config.LimitHostname != "" {
properties["limit-host"] = config.LimitHostname
properties["outputlimits"] = "y"
} else {
properties["limit-host"] = "No restriction"
}
if config.LimitLocale != "" {
properties["limit-locale"] = config.LimitLocale
properties["outputlimits"] = "y"
} else {
properties["limit-locale"] = "No restriction"
}
if config.LimitUsername != "" {
properties["limit-user"] = config.LimitUsername
properties["outputlimits"] = "y"
} else {
properties["limit-user"] = "No restriction"
}
switch config.Format {
case clientpb.OutputFormat_EXECUTABLE:
properties["format"] = "Executable"
case clientpb.OutputFormat_SHARED_LIB:
properties["format"] = "Shared Library"
case clientpb.OutputFormat_SERVICE:
properties["format"] = "Service"
case clientpb.OutputFormat_SHELLCODE:
properties["format"] = "Shellcode"
case clientpb.OutputFormat_THIRD_PARTY:
properties["format"] = "Third Party"
}
if config.TrafficEncodersEnabled {
properties["trafficencoders"] = strings.Join(config.TrafficEncoders, "\n")
}
return properties
}
// PrintProfileInfo - Print detailed information about a given profile
func PrintProfileInfo(name string, con *console.SliverConsoleClient) {
profile := GetImplantProfileByName(name, con)
if profile == nil {
con.PrintErrorf("Could not find a profile with the name \"%s\"", name)
return
}
config := profile.Config
properties := populateProfileProperties(config)
//con.Printf("--- Details for profile %s ---\n", profile.Name)
tw := table.NewWriter()
// Implant Basics
tw.AppendRow(table.Row{
"OS / Architecture",
properties["osarch"],
})
tw.AppendRow(table.Row{
"Implant Type",
properties["implanttype"],
})
tw.AppendRow(table.Row{
"Implant Format",
properties["format"],
})
con.PrintInfof("Implant Basics\n")
con.Printf("%s\n\n", tw.Render())
tw.ResetRows()
// Obfuscation Options
tw.AppendRow(table.Row{
"Evasion is",
properties["evasion"],
})
tw.AppendRow(table.Row{
"Debugging is",
properties["debugging"],
})
tw.AppendRow(table.Row{
"Obfuscation of symbols is",
properties["obsymbols"],
})
tw.AppendRow(table.Row{
"Shikata Ga Nai (SGN) is",
properties["sgn"],
})
con.PrintInfof("Obfuscation\n")
con.Printf("%s\n\n", tw.Render())
// Timeouts and Intervals
tw.ResetRows()
if config.IsBeacon {
tw.AppendRow(table.Row{
"Beacon Interval",
properties["beaconinterval"],
})
tw.AppendRow(table.Row{
"Beacon Jitter",
properties["beaconjitter"],
})
}
tw.AppendRow(table.Row{
"Reconnect Interval",
properties["reconnect"],
})
tw.AppendRow(table.Row{
"Maximum Connection Errors",
properties["maxerrors"],
})
tw.AppendRow(table.Row{
"Poll Timeout",
properties["polltimeout"],
})
con.PrintInfof("Timeouts and Intervals\n")
con.Printf("%s\n\n", tw.Render())
// C2
tw.ResetRows()
tw.AppendRow(table.Row{
"Endpoints",
properties["implantC2"],
})
if len(config.CanaryDomains) > 0 {
plural := "s"
if len(config.CanaryDomains) == 1 {
plural = ""
}
tw.AppendRow(table.Row{
fmt.Sprintf("Canary Domain%s", plural),
properties["canary"],
})
}
tw.AppendRow(table.Row{
"Connection Strategy",
properties["connectstrat"],
})
con.PrintInfof("Command and Control\n")
con.Printf("%s\n\n", tw.Render())
// Connection Restrictions
if properties["outputlimits"] == "y" {
tw.ResetRows()
tw.AppendRow(table.Row{
"Device must be domain joined",
properties["limit-domjoin"],
})
tw.AppendRow(table.Row{
"Execution will only occur before the following date/time",
properties["limit-dt"],
})
tw.AppendRow(table.Row{
"Files that must be present",
properties["limit-file"],
})
tw.AppendRow(table.Row{
"Device has the hostname",
properties["limit-host"],
})
tw.AppendRow(table.Row{
"Device uses the locale",
properties["limit-locale"],
})
tw.AppendRow(table.Row{
"The implant must be running under the context of specified user",
properties["limit-user"],
})
con.PrintInfof("Execution is subject to the following restrictions\n")
con.Printf("%s\n\n", tw.Render())
}
// Traffic encoders
if config.TrafficEncodersEnabled {
tw.ResetRows()
tw.AppendRow(table.Row{
"Traffic encoders",
properties["trafficencoders"],
})
con.PrintInfof("Traffic Encoders\n")
con.Printf("%s\n\n", tw.Render())
}
// Output messages that would otherwise get lost in between the tables
if properties["outputlimits"] == "n" {
con.PrintInfof("Execution is not subject to any restrictions\n")
}
if !config.TrafficEncodersEnabled {
con.PrintInfof("Traffic encoders are not enabled\n")
}
}
// ProfileNameCompleter - Completer for implant build names
func ProfileNameCompleter(con *console.SliverConsoleClient) carapace.Action {
comps := func(ctx carapace.Context) carapace.Action {
+76 -1
View File
@@ -59,6 +59,9 @@ var (
consts.PwdStr: pwdHelp,
consts.CatStr: catHelp,
consts.DownloadStr: downloadHelp,
consts.GrepStr: grepHelp,
consts.HeadStr: headHelp,
consts.TailStr: tailHelp,
consts.UploadStr: uploadHelp,
consts.MkdirStr: mkdirHelp,
consts.RmStr: rmHelp,
@@ -76,6 +79,7 @@ var (
consts.PsExecStr: psExecHelp,
consts.BackdoorStr: backdoorHelp,
consts.SpawnDllStr: spawnDllHelp,
consts.MountStr: mountHelp,
consts.WebsitesStr: websitesHelp,
consts.ScreenshotStr: screenshotHelp,
@@ -113,6 +117,9 @@ var (
// Builders
consts.BuildersStr: buildersHelp,
// HTTP C2
consts.C2ProfileStr: c2ProfilesHelp,
}
jobsHelp = `[[.Bold]]Command:[[.Normal]] jobs <options>
@@ -321,8 +328,38 @@ Downloads can be filtered using the following patterns:
If you need to match a special character (*, ?, '-', '[', ']', '\\'), place '\\' in front of it (example: \\?).
On Windows, escaping is disabled. Instead, '\\' is treated as path separator.`
headHelp = `[[.Bold]]Command:[[.Normal]] head [--bytes/-b <number of bytes>] [--lines/-l <number of lines>] <remote path>
[[.Bold]]About:[[.Normal]] Fetch the first number of bytes or lines from a remote file and display it to stdout.`
tailHelp = `[[.Bold]]Command:[[.Normal]] tail [--bytes/-b <number of bytes>] [--lines/-l <number of lines>] <remote path>
[[.Bold]]About:[[.Normal]] Fetch the last number of bytes or lines from a remote file and display it to stdout.`
uploadHelp = `[[.Bold]]Command:[[.Normal]] upload [local src] <remote dst>
[[.Bold]]About:[[.Normal]] Upload a file to the remote system.`
[[.Bold]]About:[[.Normal]] Upload a file or directory to the remote system.
[[.Bold]][[.Underline]]Paths[[.Normal]]
You can preserve directory structures using the -p switch. Directories will be preserved as they are specified in the source path.
For example, the command upload -p /home/me/docs /tmp will upload the files in /home/me/docs to /tmp/home/me/docs on the target.
However, if you are in the local directory /home/me, and issue the command upload -p docs /tmp, the files in /home/me/docs will
be uploaded to /tmp/docs on the target. This is equivalent to upload /home/me/docs /tmp/docs (notice the lack of the -p switch).
[[.Bold]][[.Underline]]Filters[[.Normal]]
Filters are a way to limit uploads to file names matching given criteria. Filters DO NOT apply to directory names.
Filters are specified after the path. A blank path will filter on names in the current directory. For example:
upload /etc/*.conf will upload all files from /etc whose names end in .conf. /etc/ is the path, *.conf is the filter.
Uploads can be filtered using the following patterns:
'*': Wildcard, matches any sequence of non-path separators (slashes)
Example: n*.txt will match all file names starting with n and ending with .txt
'?': Single character wildcard, matches a single non-path separator (slashes)
Example: s?iver will match all file names starting with s followed by any non-separator character and ending with iver.
'[{range}]': Match a range of characters. Ranges are specified with '-'. This is usually combined with other patterns. Ranges can be negated with '^'.
Example: [a-c] will match the characters a, b, and c. [a-c]* will match all file names that start with a, b, or c.
^[r-u] will match all characters except r, s, t, and u.
If you need to match a special character (*, ?, '-', '[', ']', '\\'), place '\\' in front of it (example: \\?).
On Windows, escaping is disabled. Instead, '\\' is treated as path separator.`
procdumpHelp = `[[.Bold]]Command:[[.Normal]] procdump [pid]
[[.Bold]]About:[[.Normal]] Dumps the process memory given a process identifier (pid)`
@@ -343,6 +380,9 @@ On Windows, escaping is disabled. Instead, '\\' is treated as path separator.`
[[.Bold]]About:[[.Normal]] (Windows Only) Executes the .NET assembly in a child process.
`
mountHelp = `[[.Bold]]Command:[[.Normal]] mount
[[.Bold]]About:[[.Normal]] Displays information about mounted drives on the system, including mount point, space metrics, and filesystem.`
executeShellcodeHelp = `[[.Bold]]Command:[[.Normal]] execute-shellcode [local path to raw shellcode]
[[.Bold]]About:[[.Normal]] Executes the given shellcode in the implant's process.
@@ -1220,6 +1260,41 @@ Sliver uses the same hash identifiers as Hashcat (use the #):
% 10s - A file containing lines of 'username:hash' pairs.
% 10s - A CSV file containing 'username,hash' pairs (additional columns ignored).
`, creds.HashNewlineFormat, creds.UserColonHashNewlineFormat, creds.CSVFormat)
c2ProfilesHelp = `[[.Bold]]Command:[[.Normal]] c2profile
[[.Bold]]About:[[.Normal]] Display details of HTTP C2 profiles loaded into Sliver.
`
C2ProfileImportStr = `[[.Bold]]Command:[[.Normal]] Import
[[.Bold]]About:[[.Normal]] Load custom HTTP C2 profiles.
`
grepHelp = `[[.Bold]]Command:[[.Normal]] grep [flags / options] <search pattern> <path>
[[.Bold]]About:[[.Normal]] Search a file or path for a search pattern
[[.Bold]][[.Underline]]Search Patterns[[.Normal]]
Search patterns use RE2 regular expression syntax.
[[.Bold]][[.Underline]]Binary Files[[.Normal]]
When searching a binary file, grep will only return the line that matches if it exclusively contains UTF-8 printable characters.
Before, after, and context options are disabled for binary files.
[[.Bold]][[.Underline]]Path Filters[[.Normal]]
Filters are a way to limit searches to file names matching given criteria. Filters DO NOT apply to directory names.
Filters are specified after the path. A blank path will filter on names in the current directory. For example:
grep something /etc/*.conf will search all files in /etc whose names end in .conf. /etc/ is the path, *.conf is the filter.
Searches can be filtered using the following patterns:
'*': Wildcard, matches any sequence of non-path separators (slashes)
Example: n*.txt will search all file names starting with n and ending with .txt
'?': Single character wildcard, matches a single non-path separator (slashes)
Example: s?iver will search all file names starting with s followed by any non-separator character and ending with iver.
'[{range}]': Match a range of characters. Ranges are specified with '-'. This is usually combined with other patterns. Ranges can be negated with '^'.
Example: [a-c] will match the characters a, b, and c. [a-c]* will match all file names that start with a, b, or c.
^[r-u] will match all characters except r, s, t, and u.
If you need to match a special character (*, ?, '-', '[', ']', '\\'), place '\\' in front of it (example: \\?).
On Windows, escaping is disabled. Instead, '\\' is treated as path separator.`
)
const (
+2 -2
View File
@@ -26,7 +26,7 @@ import (
"github.com/bishopfox/sliver/client/console"
)
// HostsIOCRmCmd - Remove a host from the database
// HostsIOCRmCmd - Remove an IOC from the database
func HostsIOCRmCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []string) {
host, err := SelectHost(con)
if err != nil {
@@ -43,5 +43,5 @@ func HostsIOCRmCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []
con.PrintErrorf("%s\n", err)
return
}
con.PrintInfof("Removed host from database\n")
con.PrintInfof("Removed IOC from database\n")
}
+4
View File
@@ -62,6 +62,10 @@ func hostIOCsTable(host *clientpb.Host, con *console.SliverConsoleClient) string
}
func SelectHostIOC(host *clientpb.Host, con *console.SliverConsoleClient) (*clientpb.IOC, error) {
if len(host.IOCs) == 0 {
return nil, ErrNoIOCs
}
// Sort the keys because maps have a randomized order, these keys must be ordered for the selection
// to work properly since we rely on the index of the user's selection to find the session in the map
var keys []string
+2
View File
@@ -42,6 +42,8 @@ import (
var (
// ErrNoHosts - No hosts in database
ErrNoHosts = errors.New("no hosts")
// ErrNoIOCs - No IOCs in database
ErrNoIOCs = errors.New("no IOCs in database for selected host")
// ErrNoSelection - No selection made
ErrNoSelection = errors.New("no selection")
)
+8
View File
@@ -43,6 +43,10 @@ func InfoCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []string
// ID passed via argument takes priority
idArg := args[0]
session, beacon, err = use.SessionOrBeaconByID(idArg, con)
if err != nil {
con.PrintErrorf("%s\n", err)
return
}
} else if session != nil || beacon != nil {
currID := ""
if session != nil {
@@ -51,6 +55,10 @@ func InfoCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []string
currID = beacon.ID
}
session, beacon, err = use.SessionOrBeaconByID(currID, con)
if err != nil {
con.PrintErrorf("%s\n", err)
return
}
} else {
if session == nil && beacon == nil {
session, beacon, err = use.SelectSessionOrBeacon(con)
-2
View File
@@ -41,7 +41,6 @@ func DNSListenerCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args [
lhost, _ := cmd.Flags().GetString("lhost")
lport, _ := cmd.Flags().GetUint32("lport")
canaries, _ := cmd.Flags().GetBool("no-canaries")
persistent, _ := cmd.Flags().GetBool("persistent")
enforceOTP, _ := cmd.Flags().GetBool("disable-otp")
con.PrintInfof("Starting DNS listener with parent domain(s) %v ...\n", domains)
@@ -50,7 +49,6 @@ func DNSListenerCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args [
Host: lhost,
Port: lport,
Canaries: !canaries,
Persistent: persistent,
EnforceOTP: !enforceOTP,
})
con.Println()
-2
View File
@@ -37,7 +37,6 @@ func HTTPListenerCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args
pollTimeout, _ := cmd.Flags().GetString("long-poll-timeout")
pollJitter, _ := cmd.Flags().GetString("long-poll-jitter")
website, _ := cmd.Flags().GetString("website")
persistent, _ := cmd.Flags().GetBool("persistent")
longPollTimeout, err := time.ParseDuration(pollTimeout)
if err != nil {
@@ -57,7 +56,6 @@ func HTTPListenerCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args
Host: lhost,
Port: lport,
Secure: false,
Persistent: persistent,
EnforceOTP: !disableOTP,
LongPollTimeout: int64(longPollTimeout),
LongPollJitter: int64(longPollJitter),
+3 -5
View File
@@ -22,7 +22,7 @@ import (
"context"
"crypto/tls"
"fmt"
"io/ioutil"
"os"
"time"
"github.com/spf13/cobra"
@@ -40,7 +40,6 @@ func HTTPSListenerCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args
pollTimeout, _ := cmd.Flags().GetString("long-poll-timeout")
pollJitter, _ := cmd.Flags().GetString("long-poll-jitter")
website, _ := cmd.Flags().GetString("website")
persistent, _ := cmd.Flags().GetBool("persistent")
letsEncrypt, _ := cmd.Flags().GetBool("lets-encrypt")
disableRandomize, _ := cmd.Flags().GetBool("disable-randomized-jarm")
@@ -72,7 +71,6 @@ func HTTPSListenerCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args
Cert: cert,
Key: key,
ACME: letsEncrypt,
Persistent: persistent,
EnforceOTP: !disableOTP,
LongPollTimeout: int64(longPollTimeout),
LongPollJitter: int64(longPollJitter),
@@ -92,11 +90,11 @@ func getLocalCertificatePair(cmd *cobra.Command) ([]byte, []byte, error) {
if certPath == "" && keyPath == "" {
return nil, nil, nil
}
cert, err := ioutil.ReadFile(certPath)
cert, err := os.ReadFile(certPath)
if err != nil {
return nil, nil, err
}
key, err := ioutil.ReadFile(keyPath)
key, err := os.ReadFile(keyPath)
if err != nil {
return nil, nil, err
}
+2
View File
@@ -70,6 +70,7 @@ func PrintJobs(jobs map[uint32]*clientpb.Job, con *console.SliverConsoleClient)
"Name",
"Protocol",
"Port",
"Domains",
})
var keys []int
@@ -85,6 +86,7 @@ func PrintJobs(jobs map[uint32]*clientpb.Job, con *console.SliverConsoleClient)
job.Name,
job.Protocol,
fmt.Sprintf("%d", job.Port),
strings.Join(job.Domains, ","),
})
}
con.Printf("%s\n", tw.Render())
+2 -4
View File
@@ -31,13 +31,11 @@ import (
func MTLSListenerCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []string) {
lhost, _ := cmd.Flags().GetString("lhost")
lport, _ := cmd.Flags().GetUint32("lport")
persistent, _ := cmd.Flags().GetBool("persistent")
con.PrintInfof("Starting mTLS listener ...\n")
mtls, err := con.Rpc.StartMTLSListener(context.Background(), &clientpb.MTLSListenerReq{
Host: lhost,
Port: lport,
Persistent: persistent,
Host: lhost,
Port: lport,
})
con.Println()
if err != nil {
+24 -49
View File
@@ -43,7 +43,7 @@ func StageListenerCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args
listenerURL, _ := cmd.Flags().GetString("url")
aesEncryptKey, _ := cmd.Flags().GetString("aes-encrypt-key")
aesEncryptIv, _ := cmd.Flags().GetString("aes-encrypt-iv")
prependSize, _ := cmd.Flags().GetBool("prepend-size")
rc4EncryptKey, _ := cmd.Flags().GetString("rc4-encrypt-key")
compressF, _ := cmd.Flags().GetString("compress")
compress := strings.ToLower(compressF)
@@ -70,6 +70,21 @@ func StageListenerCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args
return
}
if rc4EncryptKey != "" && aesEncryptKey != "" {
con.PrintErrorf("Cannot use both RC4 and AES encryption\n")
return
}
rc4Encrypt := false
if rc4EncryptKey != "" {
// RC4 keysize can be between 1 to 256 bytes
if len(rc4EncryptKey) < 1 || len(rc4EncryptKey) > 256 {
con.PrintErrorf("Incorrect length of RC4 Key\n")
return
}
rc4Encrypt = true
}
aesEncrypt := false
if aesEncryptKey != "" {
// check if aes encryption key is correct length
@@ -121,55 +136,11 @@ func StageListenerCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args
stage2 = util.PreludeEncrypt(stage2, []byte(aesEncryptKey), []byte(aesEncryptIv))
}
if rc4Encrypt {
stage2 = util.RC4EncryptUnsafe(stage2, []byte(rc4EncryptKey))
}
switch stagingURL.Scheme {
case "http":
if prependSize {
stage2 = prependPayloadSize(stage2)
}
ctrl := make(chan bool)
con.SpinUntil("Starting HTTP staging listener...", ctrl)
stageListener, err := con.Rpc.StartHTTPStagerListener(context.Background(), &clientpb.StagerListenerReq{
Protocol: clientpb.StageProtocol_HTTP,
Data: stage2,
Host: stagingURL.Hostname(),
Port: uint32(stagingPort),
})
ctrl <- true
<-ctrl
if err != nil {
con.PrintErrorf("Error starting HTTP staging listener: %s\n", err)
return
}
con.PrintInfof("Job %d (http) started\n", stageListener.GetJobID())
case "https":
letsEncrypt, _ := cmd.Flags().GetBool("lets-encrypt")
if prependSize {
stage2 = prependPayloadSize(stage2)
}
cert, key, err := getLocalCertificatePair(cmd)
if err != nil {
con.Println()
con.PrintErrorf("Failed to load local certificate %s\n", err)
return
}
ctrl := make(chan bool)
con.SpinUntil("Starting HTTPS staging listener...", ctrl)
stageListener, err := con.Rpc.StartHTTPStagerListener(context.Background(), &clientpb.StagerListenerReq{
Protocol: clientpb.StageProtocol_HTTPS,
Data: stage2,
Host: stagingURL.Hostname(),
Port: uint32(stagingPort),
Cert: cert,
Key: key,
ACME: letsEncrypt,
})
ctrl <- true
<-ctrl
if err != nil {
con.PrintErrorf("Error starting HTTPS staging listener: %v\n", err)
return
}
con.PrintInfof("Job %d (https) started\n", stageListener.GetJobID())
case "tcp":
// Always prepend payload size for TCP stagers
stage2 = prependPayloadSize(stage2)
@@ -198,6 +169,10 @@ func StageListenerCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args
con.PrintInfof("AES KEY: %v\n", aesEncryptKey)
con.PrintInfof("AES IV: %v\n", aesEncryptIv)
}
if rc4Encrypt {
con.PrintInfof("RC4 KEY: %v\n", rc4EncryptKey)
}
}
func prependPayloadSize(payload []byte) []byte {
+3 -5
View File
@@ -32,14 +32,12 @@ func WGListenerCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []
lport, _ := cmd.Flags().GetUint32("lport")
nport, _ := cmd.Flags().GetUint32("nport")
keyExchangePort, _ := cmd.Flags().GetUint32("key-port")
persistent, _ := cmd.Flags().GetBool("persistent")
con.PrintInfof("Starting Wireguard listener ...\n")
wg, err := con.Rpc.StartWGListener(context.Background(), &clientpb.WGListenerReq{
Port: lport,
NPort: nport,
KeyPort: keyExchangePort,
Persistent: persistent,
Port: lport,
NPort: nport,
KeyPort: keyExchangePort,
})
if err != nil {
con.PrintErrorf("%s\n", err)
+11 -5
View File
@@ -92,13 +92,14 @@ func PerformDownload(remotePath string, fileName string, cmd *cobra.Command, con
return download, nil
}
func CreateLootMessage(fileName string, lootName string, lootFileType clientpb.FileType, data []byte) *clientpb.Loot {
func CreateLootMessage(hostUUID string, fileName string, lootName string, lootFileType clientpb.FileType, data []byte) *clientpb.Loot {
if lootName == "" {
lootName = fileName
}
lootMessage := &clientpb.Loot{
Name: lootName,
FileType: lootFileType,
Name: lootName,
OriginHostUUID: hostUUID,
FileType: lootFileType,
File: &commonpb.File{
Name: fileName,
Data: data,
@@ -141,7 +142,7 @@ func LootDownload(download *sliverpb.Download, lootName string, fileType clientp
if !download.IsDir {
// filepath.Base does not deal with backslashes correctly in Windows paths, so we have to standardize the path to forward slashes
downloadPath := strings.ReplaceAll(download.Path, "\\", "/")
lootMessage := CreateLootMessage(filepath.Base(downloadPath), lootName, fileType, download.Data)
lootMessage := CreateLootMessage(con.ActiveTarget.GetHostUUID(), filepath.Base(downloadPath), lootName, fileType, download.Data)
SendLootMessage(lootMessage, con)
} else {
// We have to decompress the gzip file first
@@ -190,13 +191,18 @@ func LootDownload(download *sliverpb.Download, lootName string, fileType clientp
*/
fileData, err := io.ReadAll(tarReader)
if err == nil {
lootMessage := CreateLootMessage(filepath.Base(entryHeader.Name), lootName, fileType, fileData)
lootMessage := CreateLootMessage(con.ActiveTarget.GetHostUUID(), filepath.Base(entryHeader.Name), lootName, fileType, fileData)
SendLootMessage(lootMessage, con)
}
}
}
}
func LootText(text string, lootName string, lootFileName string, fileType clientpb.FileType, con *console.SliverConsoleClient) {
lootMessage := CreateLootMessage(con.ActiveTarget.GetHostUUID(), lootFileName, lootName, fileType, []byte(text))
SendLootMessage(lootMessage, con)
}
// LootAddRemoteCmd - Add a file from the remote system to the server as loot
func LootAddRemoteCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []string) {
session := con.ActiveTarget.GetSessionInteractive()
+139
View File
@@ -0,0 +1,139 @@
package monitor
/*
Sliver Implant Framework
Copyright (C) 2021 Bishop Fox
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import (
"context"
"fmt"
"github.com/AlecAivazis/survey/v2"
"github.com/bishopfox/sliver/client/command/settings"
"github.com/bishopfox/sliver/client/console"
"github.com/bishopfox/sliver/protobuf/clientpb"
"github.com/bishopfox/sliver/protobuf/commonpb"
"github.com/jedib0t/go-pretty/v6/table"
"github.com/spf13/cobra"
)
func MonitorConfigCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []string) {
resp, err := con.Rpc.MonitorListConfig(context.Background(), &commonpb.Empty{})
if err != nil {
con.PrintErrorf("%s\n", err)
return
}
PrintWTConfig(resp, con)
}
func MonitorAddConfigCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []string) {
apiKey, _ := cmd.Flags().GetString("apiKey")
apiPassword, _ := cmd.Flags().GetString("apiPassword")
apiType, _ := cmd.Flags().GetString("type")
MonitoringProvider := &clientpb.MonitoringProvider{Type: apiType, APIKey: apiKey}
if apiType == "xforce" {
MonitoringProvider.APIPassword = apiPassword
}
resp, err := con.Rpc.MonitorAddConfig(context.Background(), MonitoringProvider)
if err != nil {
con.PrintErrorf("%s\n", err)
return
}
if resp != nil && resp.Err != "" {
con.PrintErrorf("%s\n", resp.Err)
return
}
con.PrintInfof("Added monitoring configuration\n")
}
func MonitorDelConfigCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []string) {
resp, err := con.Rpc.MonitorListConfig(context.Background(), &commonpb.Empty{})
if err != nil {
con.PrintErrorf("%s\n", err)
return
}
config, err := selectWatchtowerConfig(resp)
if err != nil {
con.PrintErrorf("%s\n", err)
return
}
_, err = con.Rpc.MonitorDelConfig(context.Background(), config)
if err != nil {
con.PrintErrorf("%s\n", err)
return
}
con.PrintInfof("Removed monitoring configuration\n")
}
// PrintWTConfig - Print the current watchtower configuration
func PrintWTConfig(configs *clientpb.MonitoringProviders, con *console.SliverConsoleClient) {
tw := table.NewWriter()
tw.SetStyle(settings.GetTableStyle(con))
tw.AppendHeader(table.Row{
"ID",
"Type",
"APIKey",
"APIPassword",
})
color := console.Normal
for _, config := range configs.Providers {
row := table.Row{}
row = append(row, fmt.Sprintf(color+"%s"+console.Normal, config.ID))
row = append(row, fmt.Sprintf(color+"%s"+console.Normal, config.Type))
row = append(row, fmt.Sprintf(color+"%s"+console.Normal, config.APIKey))
row = append(row, fmt.Sprintf(color+"%s"+console.Normal, config.APIPassword))
tw.AppendRow(row)
}
con.Printf("%s\n", tw.Render())
}
func selectWatchtowerConfig(configs *clientpb.MonitoringProviders) (*clientpb.MonitoringProvider, error) {
var options []string
for _, config := range configs.Providers {
options = append(options, config.Type)
}
selected := ""
prompt := &survey.Select{
Message: "Select a configuration:",
Options: options,
}
err := survey.AskOne(prompt, &selected)
if err != nil {
return nil, err
}
for _, provider := range configs.Providers {
if provider.Type == selected {
return provider, nil
}
}
return nil, nil
}
+2 -3
View File
@@ -21,7 +21,6 @@ package processes
import (
"context"
"fmt"
"io/ioutil"
"os"
"path/filepath"
"time"
@@ -112,7 +111,7 @@ func PrintProcessDump(dump *sliverpb.ProcessDump, saveTo string, hostname string
var saveToFile *os.File
if saveTo == "" {
tmpFileName := filepath.Base(fmt.Sprintf("procdump_%s_%d_*", hostname, pid))
saveToFile, err = ioutil.TempFile("", tmpFileName)
saveToFile, err = os.CreateTemp("", tmpFileName)
if err != nil {
con.PrintErrorf("Error creating temporary file: %s\n", err)
return
@@ -147,6 +146,6 @@ func LootProcessDump(dump *sliverpb.ProcessDump, lootName string, hostName strin
lootName = dumpFileName
}
lootMessage := loot.CreateLootMessage(dumpFileName, lootName, clientpb.FileType_BINARY, dump.GetData())
lootMessage := loot.CreateLootMessage(con.ActiveTarget.GetHostUUID(), dumpFileName, lootName, clientpb.FileType_BINARY, dump.GetData())
loot.SendLootMessage(lootMessage, con)
}
+22 -8
View File
@@ -46,14 +46,20 @@ var knownSecurityTools = map[string][]string{
"RepUx.exe": {console.Red, "Carbon Black Cloud Sensor"}, // Carbon Black Cloud Sensor
"RepWSC.exe": {console.Red, "Carbon Black Cloud Sensor"}, // Carbon Black Cloud Sensor
"scanhost.exe": {console.Red, "Carbon Black Cloud Sensor"}, // Carbon Black Cloud Sensor
"MsMpEng.exe": {console.Red, "Windows Defender"}, // Windows Defender
"SenseIR.exe": {console.Red, "Windows Defender MDE"}, // Windows Defender Endpoint (Live Response Session)
"SenseCncProxy.exe": {console.Red, "Windows Defender MDE"}, // Windows Defender Endpoint
"MsSense.exe": {console.Red, "Windows Defender MDE"}, // Windows Defender Endpoint
"MpCmdRun.exe": {console.Red, "Windows Defender"}, // Windows Defender
"smartscreen.exe": {console.Red, "Windows Smart Screen"}, // Windows Defender Smart Screen
"MpCmdRun.exe": {console.Red, "Windows Defender"}, // Windows Defender Command-line
"MonitoringHost.exe": {console.Red, "Windows Defender"}, // Microsoft Monitoring Agent
"HealthService.exe": {console.Red, "Windows Defender"}, // Microsoft Monitoring Agent
"smartscreen.exe": {console.Red, "Windows Smart Screen"}, // Windows Defender Smart Screen
"MsMpEng.exe": {console.Red, "Windows Defender"}, // Windows Defender (Service Executable)
"NisSrv.exe": {console.Red, "Windows Defender"}, // Windows Defender (Network Realtime Inspection)
"SenseIR.exe": {console.Red, "Windows Defender MDE"}, // Windows Defender Endpoint (Live Response Session)
"SenseNdr.exe": {console.Red, "Windows Defender MDE"}, // Windows Defender Endpoint (Network Detection and Response)
"SenseSC.exe": {console.Red, "Windows Defender MDE"}, // Windows Defender Endpoint (Screenshot Capture Module)
"SenseCE.exe": {console.Red, "Windows Defender MDE"}, // Windows Defender Endpoint (Classification Engine Module)
"SenseCM.exe": {console.Red, "Windows Defender MDE"}, // Windows Defender Endpoint (Configuration Management Module)
"SenseSampleUploader.exe": {console.Red, "Windows Defender MDE"}, // Windows Defender Endpoint (Sample Uploader Module)
"SenseCncProxy.exe": {console.Red, "Windows Defender MDE"}, // Windows Defender Endpoint (Communication Module)
"MsSense.exe": {console.Red, "Windows Defender MDE"}, // Windows Defender Endpoint (Service Executable)
"CSFalconService.exe": {console.Red, "CrowdStrike"}, // Crowdstrike Falcon Service
"CSFalconContainer.exe": {console.Red, "CrowdStrike"}, // CrowdStrike Falcon Container Security
"bdservicehost.exe": {console.Red, "Bitdefender"}, // Bitdefender (Total Security)
@@ -86,6 +92,10 @@ var knownSecurityTools = map[string][]string{
"eguiproxy.exe": {console.Red, "ESET Security"}, // ESET Internet Security
"ekrn.exe": {console.Red, "ESET Security"}, // ESET Internet Security
"efwd.exe": {console.Red, "ESET Security"}, // ESET Internet Security
"AmSvc.exe": {console.Red, "Cybereason ActiveProbe"}, // Cybereason ActiveProbe
"CrAmTray.exe": {console.Red, "Cybereason ActiveProbe"}, // Cybereason ActiveProbe
"CrsSvc.exe": {console.Red, "Cybereason ActiveProbe"}, // Cybereason ActiveProbe
"CybereasonAV.exe": {console.Red, "Cybereason ActiveProbe"}, // Cybereason ActiveProbe
}
// PsCmd - List processes on the remote system
@@ -202,12 +212,16 @@ func PrintPS(os string, ps *sliverpb.Ps, interactive bool, flags *pflag.FlagSet,
}
func findKnownSecurityProducts(ps *sliverpb.Ps) []string {
products := []string{}
uniqProducts := map[string]string{}
for _, proc := range ps.Processes {
if secTool, ok := knownSecurityTools[proc.Executable]; ok {
products = append(products, secTool[1])
uniqProducts[secTool[1]] = secTool[0]
}
}
products := make([]string, 0, len(uniqProducts))
for name := range uniqProducts {
products = append(products, name)
}
return products
}
+7
View File
@@ -51,9 +51,16 @@ func (n *node) insert(proc *commonpb.Process) {
}
func (n *node) findParent(proc *commonpb.Process) *node {
// Empty node
if n.Value == nil {
return nil
}
// Skip self when called from reorder
// otherwise things might explode, see #1340
if n.Value.Pid == proc.Pid {
return nil
}
// Found parent
if n.Value.Pid == proc.Ppid {
return n
}
+3 -3
View File
@@ -21,7 +21,7 @@ package reaction
import (
"encoding/json"
"fmt"
"io/ioutil"
"os"
"path"
"strconv"
"strings"
@@ -49,13 +49,13 @@ func SaveReactions(reactions []core.Reaction) error {
if err != nil {
return err
}
return ioutil.WriteFile(reactionFilePath, data, 0o600)
return os.WriteFile(reactionFilePath, data, 0o600)
}
// LoadReactions - Save the reactions to the reaction file
func LoadReactions() (int, error) {
reactionFilePath := GetReactionFilePath()
data, err := ioutil.ReadFile(reactionFilePath)
data, err := os.ReadFile(reactionFilePath)
if err != nil {
return 0, err
}
+2 -2
View File
@@ -21,7 +21,7 @@ package registry
import (
"context"
"encoding/hex"
"io/ioutil"
"os"
"strconv"
"strings"
@@ -100,7 +100,7 @@ func RegWriteCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []st
return
}
} else {
v, err = ioutil.ReadFile(binPath)
v, err = os.ReadFile(binPath)
if err != nil {
con.PrintErrorf("%s\n", err)
return
+2 -3
View File
@@ -21,7 +21,6 @@ package screenshot
import (
"context"
"fmt"
"io/ioutil"
"os"
"path/filepath"
"time"
@@ -107,7 +106,7 @@ func PrintScreenshot(screenshot *sliverpb.Screenshot, hostname string, cmd *cobr
var err error
if saveTo == "" {
tmpFileName := filepath.Base(fmt.Sprintf("screenshot_%s_%s_*.png", filepath.Base(hostname), timestamp))
saveToFile, err = ioutil.TempFile("", tmpFileName)
saveToFile, err = os.CreateTemp("", tmpFileName)
if err != nil {
con.PrintErrorf("%s\n", err)
return
@@ -138,7 +137,7 @@ func LootScreenshot(screenshot *sliverpb.Screenshot, lootName string, hostName s
lootName = screenshotFileName
}
lootMessage := loot.CreateLootMessage(screenshotFileName, lootName, clientpb.FileType_BINARY, screenshot.GetData())
lootMessage := loot.CreateLootMessage(con.ActiveTarget.GetHostUUID(), screenshotFileName, lootName, clientpb.FileType_BINARY, screenshot.GetData())
loot.SendLootMessage(lootMessage, con)
}
+212 -5
View File
@@ -31,9 +31,11 @@ import (
"github.com/bishopfox/sliver/client/command/armory"
"github.com/bishopfox/sliver/client/command/beacons"
"github.com/bishopfox/sliver/client/command/builders"
"github.com/bishopfox/sliver/client/command/c2profiles"
"github.com/bishopfox/sliver/client/command/crack"
"github.com/bishopfox/sliver/client/command/creds"
"github.com/bishopfox/sliver/client/command/exit"
"github.com/bishopfox/sliver/client/command/extensions"
"github.com/bishopfox/sliver/client/command/generate"
"github.com/bishopfox/sliver/client/command/help"
"github.com/bishopfox/sliver/client/command/hosts"
@@ -47,11 +49,13 @@ import (
"github.com/bishopfox/sliver/client/command/sessions"
"github.com/bishopfox/sliver/client/command/settings"
sgn "github.com/bishopfox/sliver/client/command/shikata-ga-nai"
"github.com/bishopfox/sliver/client/command/taskmany"
"github.com/bishopfox/sliver/client/command/update"
"github.com/bishopfox/sliver/client/command/use"
"github.com/bishopfox/sliver/client/command/websites"
"github.com/bishopfox/sliver/client/command/wireguard"
client "github.com/bishopfox/sliver/client/console"
"github.com/bishopfox/sliver/client/constants"
consts "github.com/bishopfox/sliver/client/constants"
"github.com/bishopfox/sliver/client/licenses"
)
@@ -145,6 +149,61 @@ func ServerCommands(con *client.SliverConsoleClient, serverCmds func() []*cobra.
carapace.Gen(aliasRemove).PositionalCompletion(alias.AliasCompleter())
aliasCmd.AddCommand(aliasRemove)
// [ Extensions ] ---------------------------------------------
extCmd := &cobra.Command{
Use: consts.ExtensionsStr,
Short: "List current exts",
Long: help.GetHelpFor([]string{consts.ExtensionsStr}),
Run: func(cmd *cobra.Command, args []string) {
extensions.ExtensionsCmd(cmd, con)
},
GroupID: consts.GenericHelpGroup,
}
server.AddCommand(extCmd)
/*
parking 'load' for now - the difference between 'load' and 'install' is that 'load' should not move binaries and manifests to the client install dir.
Maybe we can revisit this if it's required - but the usecase I can think of is when developing extensions, and that will also occasionally require a manifest update
// extLoadCmd := &cobra.Command{
// Use: consts.LoadStr + " [EXT]",
// Short: "Load a command EXT",
// Long: help.GetHelpFor([]string{consts.ExtensionsStr, consts.LoadStr}),
// Args: cobra.ExactArgs(1),
// Run: func(cmd *cobra.Command, args []string) {
// extensions.ExtensionLoadCmd(cmd, con, args)
// },
// }
// carapace.Gen(extLoadCmd).PositionalCompletion(
// carapace.ActionDirectories().Tag("ext directory").Usage("path to the ext directory"))
// extCmd.AddCommand(extLoadCmd)
*/
extInstallCmd := &cobra.Command{
Use: consts.InstallStr + " [filepath]",
Short: "Install an extension from a local directory/file.",
Long: help.GetHelpFor([]string{consts.ExtensionsStr, consts.InstallStr}),
Args: cobra.ExactArgs(1),
Run: func(cmd *cobra.Command, args []string) {
extensions.ExtensionsInstallCmd(cmd, con, args)
},
}
carapace.Gen(extInstallCmd).PositionalCompletion(carapace.ActionFiles().Tag("ext file"))
extCmd.AddCommand(extInstallCmd)
extendo := &cobra.Command{
Use: consts.RmStr + " [Name]",
Short: "Remove extension. Will remove all commands associated with the installed extension. Does not unload the extension from implants that have already loaded it, but removes the command from the client.",
Long: help.GetHelpFor([]string{consts.RmStr}),
Args: cobra.ExactArgs(1),
Run: func(cmd *cobra.Command, args []string) {
extensions.ExtensionsRemoveCmd(cmd, con, args)
},
}
carapace.Gen(extendo).PositionalCompletion(extensions.ManifestCompleter())
extCmd.AddCommand(extendo)
// [ Armory ] ---------------------------------------------
armoryCmd := &cobra.Command{
@@ -269,7 +328,6 @@ func ServerCommands(con *client.SliverConsoleClient, serverCmds func() []*cobra.
Flags("mTLS listener", false, mtlsCmd, func(f *pflag.FlagSet) {
f.StringP("lhost", "L", "", "interface to bind server to")
f.Uint32P("lport", "l", generate.DefaultMTLSLPort, "tcp listen port")
f.BoolP("persistent", "p", false, "make persistent across restarts")
})
server.AddCommand(mtlsCmd)
@@ -287,7 +345,6 @@ func ServerCommands(con *client.SliverConsoleClient, serverCmds func() []*cobra.
f.Uint32P("lport", "l", generate.DefaultWGLPort, "udp listen port")
f.Uint32P("nport", "n", generate.DefaultWGNPort, "virtual tun interface listen port")
f.Uint32P("key-port", "x", generate.DefaultWGKeyExPort, "virtual tun interface key exchange port")
f.BoolP("persistent", "p", false, "make persistent across restarts")
})
server.AddCommand(wgCmd)
@@ -306,7 +363,6 @@ func ServerCommands(con *client.SliverConsoleClient, serverCmds func() []*cobra.
f.StringP("lhost", "L", "", "interface to bind server to")
f.Uint32P("lport", "l", generate.DefaultDNSLPort, "udp listen port")
f.BoolP("disable-otp", "D", false, "disable otp authentication")
f.BoolP("persistent", "p", false, "make persistent across restarts")
})
server.AddCommand(dnsCmd)
@@ -327,7 +383,7 @@ func ServerCommands(con *client.SliverConsoleClient, serverCmds func() []*cobra.
f.BoolP("disable-otp", "D", false, "disable otp authentication")
f.StringP("long-poll-timeout", "T", "1s", "server-side long poll timeout")
f.StringP("long-poll-jitter", "J", "2s", "server-side long poll jitter")
f.BoolP("persistent", "p", false, "make persistent across restarts")
f.BoolP("staging", "s", false, "enable staging")
})
server.AddCommand(httpCmd)
@@ -348,13 +404,13 @@ func ServerCommands(con *client.SliverConsoleClient, serverCmds func() []*cobra.
f.BoolP("disable-otp", "D", false, "disable otp authentication")
f.StringP("long-poll-timeout", "T", "1s", "server-side long poll timeout")
f.StringP("long-poll-jitter", "J", "2s", "server-side long poll jitter")
f.BoolP("enable-staging", "s", false, "enable staging")
f.StringP("cert", "c", "", "PEM encoded certificate file")
f.StringP("key", "k", "", "PEM encoded private key file")
f.BoolP("lets-encrypt", "e", false, "attempt to provision a let's encrypt certificate")
f.BoolP("disable-randomized-jarm", "E", false, "disable randomized jarm fingerprints")
f.BoolP("persistent", "p", false, "make persistent across restarts")
})
server.AddCommand(httpsCmd)
@@ -375,6 +431,7 @@ func ServerCommands(con *client.SliverConsoleClient, serverCmds func() []*cobra.
f.BoolP("lets-encrypt", "e", false, "attempt to provision a let's encrypt certificate (HTTPS only)")
f.String("aes-encrypt-key", "", "encrypt stage with AES encryption key")
f.String("aes-encrypt-iv", "", "encrypt stage with AES encryption iv")
f.String("rc4-encrypt-key", "", "encrypt stage with RC4 encryption key")
f.StringP("compress", "C", "none", "compress the stage before encrypting (zlib, gzip, deflate9, none)")
f.BoolP("prepend-size", "P", false, "prepend the size of the stage to the payload (to use with MSF stagers)")
})
@@ -665,6 +722,7 @@ func ServerCommands(con *client.SliverConsoleClient, serverCmds func() []*cobra.
f.StringP("format", "f", "exe", "Specifies the output formats, valid values are: 'exe', 'shared' (for dynamic libraries), 'service' (see: `psexec` for more info) and 'shellcode' (windows only)")
f.StringP("save", "s", "", "directory/file to the binary to")
f.StringP("c2profile", "C", constants.DefaultC2Profile, "HTTP C2 profile to use")
})
FlagComps(generateCmd, func(comp *carapace.ActionMap) {
(*comp)["debug-file"] = carapace.ActionFiles()
@@ -673,6 +731,7 @@ func ServerCommands(con *client.SliverConsoleClient, serverCmds func() []*cobra.
(*comp)["strategy"] = carapace.ActionValuesDescribed([]string{"r", "random", "rd", "random domain", "s", "sequential"}...).Tag("C2 strategy")
(*comp)["format"] = generate.FormatCompleter()
(*comp)["save"] = carapace.ActionFiles().Tag("directory/file to save implant")
(*comp)["c2profile"] = generate.HTTPC2Completer(con)
})
server.AddCommand(generateCmd)
@@ -733,6 +792,7 @@ func ServerCommands(con *client.SliverConsoleClient, serverCmds func() []*cobra.
f.StringP("format", "f", "exe", "Specifies the output formats, valid values are: 'exe', 'shared' (for dynamic libraries), 'service' (see: `psexec` for more info) and 'shellcode' (windows only)")
f.StringP("save", "s", "", "directory/file to the binary to")
f.StringP("c2profile", "C", constants.DefaultC2Profile, "HTTP C2 profile to use")
})
FlagComps(generateBeaconCmd, func(comp *carapace.ActionMap) {
(*comp)["debug-file"] = carapace.ActionFiles()
@@ -741,6 +801,7 @@ func ServerCommands(con *client.SliverConsoleClient, serverCmds func() []*cobra.
(*comp)["strategy"] = carapace.ActionValuesDescribed([]string{"r", "random", "rd", "random domain", "s", "sequential"}...).Tag("C2 strategy")
(*comp)["format"] = generate.FormatCompleter()
(*comp)["save"] = carapace.ActionFiles().Tag("directory/file to save implant")
(*comp)["c2profile"] = generate.HTTPC2Completer(con)
})
generateCmd.AddCommand(generateBeaconCmd)
@@ -920,6 +981,7 @@ func ServerCommands(con *client.SliverConsoleClient, serverCmds func() []*cobra.
f.StringP("limit-locale", "L", "", "limit execution to hosts that match this locale")
f.StringP("format", "f", "exe", "Specifies the output formats, valid values are: 'exe', 'shared' (for dynamic libraries), 'service' (see: `psexec` for more info) and 'shellcode' (windows only)")
f.StringP("c2profile", "C", constants.DefaultC2Profile, "HTTP C2 profile to use")
})
FlagComps(profilesNewCmd, func(comp *carapace.ActionMap) {
(*comp)["debug-file"] = carapace.ActionFiles()
@@ -928,6 +990,7 @@ func ServerCommands(con *client.SliverConsoleClient, serverCmds func() []*cobra.
(*comp)["strategy"] = carapace.ActionValuesDescribed([]string{"r", "random", "rd", "random domain", "s", "sequential"}...).Tag("C2 strategy")
(*comp)["format"] = generate.FormatCompleter()
(*comp)["save"] = carapace.ActionFiles().Tag("directory/file to save implant")
(*comp)["c2profile"] = generate.HTTPC2Completer(con)
})
carapace.Gen(profilesNewCmd).PositionalCompletion(carapace.ActionValues().Usage("name of the session profile (optional)"))
profilesCmd.AddCommand(profilesNewCmd)
@@ -990,6 +1053,7 @@ func ServerCommands(con *client.SliverConsoleClient, serverCmds func() []*cobra.
f.StringP("limit-locale", "L", "", "limit execution to hosts that match this locale")
f.StringP("format", "f", "exe", "Specifies the output formats, valid values are: 'exe', 'shared' (for dynamic libraries), 'service' (see: `psexec` for more info) and 'shellcode' (windows only)")
f.StringP("c2profile", "C", constants.DefaultC2Profile, "HTTP C2 profile to use")
})
FlagComps(profilesNewBeaconCmd, func(comp *carapace.ActionMap) {
(*comp)["debug-file"] = carapace.ActionFiles()
@@ -998,6 +1062,7 @@ func ServerCommands(con *client.SliverConsoleClient, serverCmds func() []*cobra.
(*comp)["strategy"] = carapace.ActionValuesDescribed([]string{"r", "random", "rd", "random domain", "s", "sequential"}...).Tag("C2 strategy")
(*comp)["format"] = generate.FormatCompleter()
(*comp)["save"] = carapace.ActionFiles().Tag("directory/file to save implant")
(*comp)["c2profile"] = generate.HTTPC2Completer(con)
})
carapace.Gen(profilesNewBeaconCmd).PositionalCompletion(carapace.ActionValues().Usage("name of the beacon profile (optional)"))
profilesNewCmd.AddCommand(profilesNewBeaconCmd)
@@ -1014,6 +1079,38 @@ func ServerCommands(con *client.SliverConsoleClient, serverCmds func() []*cobra.
carapace.Gen(profilesRmCmd).PositionalCompletion(generate.ProfileNameCompleter(con))
profilesCmd.AddCommand(profilesRmCmd)
profilesStageCmd := &cobra.Command{
Use: consts.StageStr,
Short: "Generate an encrypted and/or compressed implant",
Long: help.GetHelpFor([]string{consts.ProfilesStr, consts.StageStr}),
Args: cobra.ExactArgs(1),
Run: func(cmd *cobra.Command, args []string) {
generate.ProfilesStageCmd(cmd, con, args)
},
}
Flags("stage", false, profilesStageCmd, func(f *pflag.FlagSet) {
f.StringP("name", "n", "", "implant name")
f.String("aes-encrypt-key", "", "encrypt stage with AES encryption key")
f.String("aes-encrypt-iv", "", "encrypt stage with AES encryption iv")
f.String("rc4-encrypt-key", "", "encrypt stage with RC4 encryption key")
f.StringP("compress", "C", "", "compress the stage before encrypting (zlib, gzip, deflate9, none)")
f.BoolP("prepend-size", "P", false, "prepend the size of the stage to the payload (to use with MSF stagers)")
})
carapace.Gen(profilesStageCmd).PositionalCompletion(generate.ProfileNameCompleter(con))
profilesCmd.AddCommand(profilesStageCmd)
profilesInfoCmd := &cobra.Command{
Use: consts.InfoStr,
Short: "Details about a profile",
Long: help.GetHelpFor([]string{consts.ProfilesStr, consts.RmStr}),
Args: cobra.ExactArgs(1),
Run: func(cmd *cobra.Command, args []string) {
generate.PrintProfileInfo(args[0], con)
},
}
carapace.Gen(profilesInfoCmd).PositionalCompletion(generate.ProfileNameCompleter(con))
profilesCmd.AddCommand(profilesInfoCmd)
implantBuildsCmd := &cobra.Command{
Use: consts.ImplantBuildsStr,
Short: "List implant builds",
@@ -1053,6 +1150,16 @@ func ServerCommands(con *client.SliverConsoleClient, serverCmds func() []*cobra.
carapace.Gen(implantsRmCmd).PositionalCompletion(generate.ImplantBuildNameCompleter(con))
implantBuildsCmd.AddCommand(implantsRmCmd)
implantStageCmd := &cobra.Command{
Use: consts.StageStr,
Short: "Serve a previously generated implant",
Long: help.GetHelpFor([]string{consts.ImplantBuildsStr, consts.StageStr}),
Run: func(cmd *cobra.Command, args []string) {
generate.ImplantsStageCmd(cmd, con, args)
},
}
implantBuildsCmd.AddCommand(implantStageCmd)
canariesCmd := &cobra.Command{
Use: consts.CanariesStr,
Short: "List previously generated canaries",
@@ -1254,6 +1361,14 @@ func ServerCommands(con *client.SliverConsoleClient, serverCmds func() []*cobra.
Short: "Monitor threat intel platforms for Sliver implants",
GroupID: consts.SliverHelpGroup,
}
configCmd := &cobra.Command{
Use: consts.MonitorConfigStr,
Short: "Configure monitor API keys",
Run: func(cmd *cobra.Command, args []string) {
monitor.MonitorConfigCmd(cmd, con, args)
},
}
monitorCmd.AddCommand(&cobra.Command{
Use: "start",
Short: "Start the monitoring loops",
@@ -1268,6 +1383,23 @@ func ServerCommands(con *client.SliverConsoleClient, serverCmds func() []*cobra.
monitor.MonitorStopCmd(cmd, con, args)
},
})
configCmd.AddCommand(&cobra.Command{
Use: "add",
Short: "Add API key configuration",
Run: func(cmd *cobra.Command, args []string) {
monitor.MonitorAddConfigCmd(cmd, con, args)
},
})
configCmd.AddCommand(&cobra.Command{
Use: "del",
Short: "Remove API key configuration",
Run: func(cmd *cobra.Command, args []string) {
monitor.MonitorDelConfigCmd(cmd, con, args)
},
})
monitorCmd.AddCommand(configCmd)
server.AddCommand(monitorCmd)
// [ Loot ] --------------------------------------------------------------
@@ -1734,6 +1866,81 @@ func ServerCommands(con *client.SliverConsoleClient, serverCmds func() []*cobra.
carapace.Gen(hcstat2RmCmd).PositionalCompletion(crack.CrackHcstat2Completer(con).Usage("hcstat2 to remove"))
hcstat2Cmd.AddCommand(hcstat2RmCmd)
// [ Task many ]-----------------------------------------
taskmanyCmd := &cobra.Command{
Use: consts.TaskmanyStr,
Short: "Task many beacons or sessions",
Long: help.GetHelpFor([]string{consts.TaskmanyStr}),
GroupID: consts.GenericHelpGroup,
Run: func(cmd *cobra.Command, args []string) {
taskmany.TaskmanyCmd(cmd, con, args)
},
}
server.AddCommand(taskmanyCmd)
// Add the relevant beacon commands as a subcommand to taskmany
taskmanyCmds := map[string]bool{
consts.ExecuteStr: true,
consts.LsStr: true,
consts.CdStr: true,
consts.MkdirStr: true,
consts.RmStr: true,
consts.UploadStr: true,
consts.DownloadStr: true,
consts.InteractiveStr: true,
consts.ChmodStr: true,
consts.ChownStr: true,
consts.ChtimesStr: true,
consts.PwdStr: true,
consts.CatStr: true,
consts.MvStr: true,
consts.PingStr: true,
consts.NetstatStr: true,
consts.PsStr: true,
consts.IfconfigStr: true,
}
for _, c := range SliverCommands(con)().Commands() {
_, ok := taskmanyCmds[c.Use]
if ok {
taskmanyCmd.AddCommand(taskmany.WrapCommand(c, con))
}
}
// [ HTTP C2 Profiles ] --------------------------------------------------------------
ImportC2ProfileCmd := &cobra.Command{
Use: consts.ImportC2ProfileStr,
Short: "Import HTTP C2 profile",
Long: help.GetHelpFor([]string{consts.ImportC2ProfileStr}),
Run: func(cmd *cobra.Command, args []string) {
c2profiles.ImportC2ProfileCmd(cmd, con, args)
},
}
Flags(consts.ImportC2ProfileStr, true, ImportC2ProfileCmd, func(f *pflag.FlagSet) {
f.StringP("name", "n", constants.DefaultC2Profile, "HTTP C2 Profile name")
f.StringP("file", "f", "", "Path to C2 configuration file to import")
f.BoolP("overwrite", "o", false, "Overwrite profile if it exists")
})
C2ProfileCmd := &cobra.Command{
Use: consts.C2ProfileStr,
Short: "Display C2 profile details",
Long: help.GetHelpFor([]string{consts.C2ProfileStr}),
Run: func(cmd *cobra.Command, args []string) {
c2profiles.C2ProfileCmd(cmd, con, args)
},
}
Flags(consts.C2ProfileStr, true, C2ProfileCmd, func(f *pflag.FlagSet) {
f.StringP("name", "n", constants.DefaultC2Profile, "HTTP C2 Profile to display")
})
FlagComps(C2ProfileCmd, func(comp *carapace.ActionMap) {
(*comp)["name"] = generate.HTTPC2Completer(con)
})
C2ProfileCmd.AddCommand(ImportC2ProfileCmd)
server.AddCommand(C2ProfileCmd)
// [ Post-command declaration setup]-----------------------------------------
// Everything below this line should preferably not be any command binding
+3 -3
View File
@@ -21,7 +21,7 @@ package sgn
import (
"context"
"encoding/hex"
"io/ioutil"
"os"
"path/filepath"
"github.com/spf13/cobra"
@@ -33,7 +33,7 @@ import (
// ShikataGaNaiCmd - Command wrapper for the Shikata Ga Nai shellcode encoder
func ShikataGaNaiCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []string) {
shellcodeFile := args[0]
rawShellcode, err := ioutil.ReadFile(shellcodeFile)
rawShellcode, err := os.ReadFile(shellcodeFile)
if err != nil {
con.PrintErrorf("Failed to read shellcode file: %s", err)
return
@@ -73,7 +73,7 @@ func ShikataGaNaiCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args
outputFile += ".sgn"
}
err = ioutil.WriteFile(outputFile, shellcodeResp.Data, 0o644)
err = os.WriteFile(outputFile, shellcodeResp.Data, 0o644)
if err != nil {
con.PrintErrorf("Failed to write shellcode file: %s", err)
return
+133 -5
View File
@@ -19,6 +19,8 @@ package command
*/
import (
"fmt"
"github.com/reeflective/console"
"github.com/rsteube/carapace"
"github.com/spf13/cobra"
@@ -94,13 +96,17 @@ func SliverCommands(con *client.SliverConsoleClient) console.Commands {
// Load Extensions
extensionManifests := assets.GetInstalledExtensionManifests()
for _, manifest := range extensionManifests {
ext, err := extensions.LoadExtensionManifest(manifest)
mext, err := extensions.LoadExtensionManifest(manifest)
// Absorb error in case there's no extensions manifest
if err != nil {
con.PrintErrorf("Failed to load extension: %s", err)
//con doesn't appear to be initialised here?
//con.PrintErrorf("Failed to load extension: %s", err)
fmt.Printf("Failed to load extension: %s\n", err)
continue
}
extensions.ExtensionRegisterCommand(ext, sliver, con)
for _, ext := range mext.ExtCommand {
extensions.ExtensionRegisterCommand(ext, sliver, con)
}
}
// [ Reconfig ] ---------------------------------------------------------------
@@ -456,7 +462,7 @@ func SliverCommands(con *client.SliverConsoleClient) console.Commands {
}
sliver.AddCommand(executeCmd)
Flags("", false, executeCmd, func(f *pflag.FlagSet) {
f.BoolP("token", "T", false, "execute command with current token (windows only)")
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")
@@ -465,6 +471,7 @@ func SliverCommands(con *client.SliverConsoleClient) console.Commands {
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", defaultTimeout, "grpc timeout in seconds")
})
@@ -790,6 +797,25 @@ func SliverCommands(con *client.SliverConsoleClient) console.Commands {
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) {
filesystem.CpCmd(cmd, con, args)
},
GroupID: consts.FilesystemHelpGroup,
}
sliver.AddCommand(cpCmd)
Flags("", false, cpCmd, func(f *pflag.FlagSet) {
f.Int64P("timeout", "t", 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",
@@ -919,9 +945,94 @@ func SliverCommands(con *client.SliverConsoleClient) console.Commands {
carapace.ActionFiles().Usage("local path where the downloaded file will be saved (optional)"),
)
grepCmd := &cobra.Command{
Use: consts.GrepStr,
Short: "Search for strings that match a regex within a file or directory",
Long: help.GetHelpFor([]string{consts.GrepStr}),
Args: cobra.ExactArgs(2),
Run: func(cmd *cobra.Command, args []string) {
filesystem.GrepCmd(cmd, con, args)
},
GroupID: consts.FilesystemHelpGroup,
}
sliver.AddCommand(grepCmd)
Flags("", false, grepCmd, func(f *pflag.FlagSet) {
f.BoolP("colorize-output", "c", false, "colorize output")
f.BoolP("loot", "X", false, "save output as loot (loot is saved without formatting)")
f.StringP("name", "n", "", "name to assign loot (optional)")
f.StringP("type", "T", "", "force a specific loot type (file/cred) if looting (optional)")
f.Int64P("timeout", "t", defaultTimeout, "grpc timeout in seconds")
f.BoolP("recursive", "r", false, "search recursively")
f.BoolP("insensitive", "i", false, "case-insensitive search")
f.Int32P("after", "A", 0, "number of lines to print after a match (ignored if the file is binary)")
f.Int32P("before", "B", 0, "number of lines to print before a match (ignored if the file is binary)")
f.Int32P("context", "C", 0, "number of lines to print before and after a match (ignored if the file is binary), equivalent to -A x -B x")
f.BoolP("exact", "e", false, "match the search term exactly")
})
carapace.Gen(grepCmd).PositionalCompletion(
carapace.ActionValues().Usage("regex to search the file for"),
carapace.ActionValues().Usage("remote path / file to search in"),
)
headCmd := &cobra.Command{
Use: consts.HeadStr,
Short: "Grab the first number of bytes or lines from a file",
Long: help.GetHelpFor([]string{consts.HeadStr}),
Args: cobra.ExactArgs(1),
Run: func(cmd *cobra.Command, args []string) {
/*
The last argument tells head if the user requested the head or tail of the file
True means head, false means tail
*/
filesystem.HeadCmd(cmd, con, args, true)
},
GroupID: consts.FilesystemHelpGroup,
}
sliver.AddCommand(headCmd)
Flags("", false, headCmd, func(f *pflag.FlagSet) {
f.BoolP("colorize-output", "c", false, "colorize output")
f.BoolP("hex", "x", false, "display as a hex dump")
f.BoolP("loot", "X", false, "save output as loot")
f.StringP("name", "n", "", "name to assign loot (optional)")
f.StringP("type", "T", "", "force a specific loot type (file/cred) if looting (optional)")
f.StringP("file-type", "F", "", "force a specific file type (binary/text) if looting (optional)")
f.Int64P("timeout", "t", defaultTimeout, "grpc timeout in seconds")
f.Int64P("bytes", "b", 0, "Grab the first number of bytes from the file")
f.Int64P("lines", "l", 0, "Grab the first number of lines from the file")
})
carapace.Gen(headCmd).PositionalCompletion(carapace.ActionValues().Usage("path to the file to print"))
tailCmd := &cobra.Command{
Use: consts.TailStr,
Short: "Grab the last number of bytes or lines from a file",
Long: help.GetHelpFor([]string{consts.TailStr}),
Args: cobra.ExactArgs(1),
Run: func(cmd *cobra.Command, args []string) {
/*
The last argument tells head if the user requested the head or tail of the file
True means head, false means tail
*/
filesystem.HeadCmd(cmd, con, args, false)
},
GroupID: consts.FilesystemHelpGroup,
}
sliver.AddCommand(tailCmd)
Flags("", false, tailCmd, func(f *pflag.FlagSet) {
f.BoolP("colorize-output", "c", false, "colorize output")
f.BoolP("hex", "x", false, "display as a hex dump")
f.BoolP("loot", "X", false, "save output as loot")
f.StringP("name", "n", "", "name to assign loot (optional)")
f.StringP("type", "T", "", "force a specific loot type (file/cred) if looting (optional)")
f.StringP("file-type", "F", "", "force a specific file type (binary/text) if looting (optional)")
f.Int64P("timeout", "t", defaultTimeout, "grpc timeout in seconds")
f.Int64P("bytes", "b", 0, "Grab the last number of bytes from the file")
f.Int64P("lines", "l", 0, "Grab the last number of lines from the file")
})
carapace.Gen(tailCmd).PositionalCompletion(carapace.ActionValues().Usage("path to the file to print"))
uploadCmd := &cobra.Command{
Use: consts.UploadStr,
Short: "Upload a file",
Short: "Upload a file or directory",
Long: help.GetHelpFor([]string{consts.UploadStr}),
Args: cobra.RangeArgs(1, 2),
Run: func(cmd *cobra.Command, args []string) {
@@ -932,6 +1043,9 @@ func SliverCommands(con *client.SliverConsoleClient) console.Commands {
sliver.AddCommand(uploadCmd)
Flags("", false, uploadCmd, func(f *pflag.FlagSet) {
f.BoolP("ioc", "i", false, "track uploaded file as an ioc")
f.BoolP("recurse", "r", false, "recursively upload a directory")
f.BoolP("overwrite", "o", false, "overwrite files that exist in the destination")
f.BoolP("preserve", "p", false, "preserve directory structure when uploading a directory")
f.Int64P("timeout", "t", defaultTimeout, "grpc timeout in seconds")
})
carapace.Gen(uploadCmd).PositionalCompletion(
@@ -976,6 +1090,20 @@ func SliverCommands(con *client.SliverConsoleClient) console.Commands {
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) {
filesystem.MountCmd(cmd, con, args)
},
GroupID: consts.FilesystemHelpGroup,
}
Flags("", false, mountCmd, func(f *pflag.FlagSet) {
f.Int64P("timeout", "t", defaultTimeout, "grpc timeout in seconds")
})
sliver.AddCommand(mountCmd)
// [ Network ] ---------------------------------------------
ifconfigCmd := &cobra.Command{
+3
View File
@@ -0,0 +1,3 @@
Taskmany
========
This package implements the `taskmany` command, which is used to task multiple beacons or sessions at once
+199
View File
@@ -0,0 +1,199 @@
package taskmany
/*
Sliver Implant Framework
Copyright (C) 2021 Bishop Fox
Copyright (C) 2023 ActualTrash
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import (
"bytes"
"context"
"fmt"
"sort"
"strings"
"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"
"github.com/spf13/cobra"
)
// TaskmanyCmd - Task many beacons / sessions
func TaskmanyCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []string) {
con.PrintErrorf("Must specify subcommand. See taskmany --help for supported subcommands.\n")
}
// Helper function to wrap grumble commands with taskmany logic
func WrapCommand(c *cobra.Command, con *console.SliverConsoleClient) *cobra.Command {
wc := &cobra.Command{
Use: c.Use,
Short: c.Short,
Long: c.Long,
Args: c.Args,
Run: wrapFunctionWithTaskmany(con, c.Run),
}
wc.Flags().AddFlagSet(c.Flags())
wc.PersistentFlags().AddFlagSet(c.PersistentFlags())
return wc
}
// Wrap a function to run it for each beacon / session
func wrapFunctionWithTaskmany(con *console.SliverConsoleClient, f func(cmd *cobra.Command, args []string)) func(cmd *cobra.Command, args []string) {
return func(cmd *cobra.Command, args []string) {
defer con.Println()
sessions, beacons, err := SelectMultipleBeaconsAndSessions(con)
if err != nil {
con.Println()
con.PrintErrorf("%s\n", err)
return
}
con.Println()
// Save current active beacon or session
origSession, origBeacon := con.ActiveTarget.Get()
nB := 0
nBSkipped := 0
for _, b := range beacons {
if !b.IsDead {
con.ActiveTarget.Set(nil, b)
f(cmd, args)
nB += 1
} else {
nBSkipped += 1
}
}
nS := 0
nSSkipped := 0
for _, s := range sessions {
if !s.IsDead {
con.ActiveTarget.Set(s, nil)
f(cmd, args)
nS += 1
} else {
nSSkipped += 1
}
}
// Restore active session / beacon
con.ActiveTarget.Set(origSession, origBeacon)
con.PrintInfof("Tasked %d sessions and %d beacons >:D\n", nS, nB)
if nBSkipped > 0 || nSSkipped > 0 {
con.PrintWarnf("Skipped %d dead sessions and %d dead beacons\n", nSSkipped, nBSkipped)
}
}
}
func SelectMultipleBeaconsAndSessions(con *console.SliverConsoleClient) ([]*clientpb.Session, []*clientpb.Beacon, error) {
// Get and sort sessions
sessionsObj, err := con.Rpc.GetSessions(context.Background(), &commonpb.Empty{})
if err != nil {
return nil, nil, err
}
sessions := sessionsObj.Sessions
sort.Slice(sessions, func(i, j int) bool {
return sessions[i].ID < sessions[j].ID
})
// Get and sort beacons
beaconsObj, err := con.Rpc.GetBeacons(context.Background(), &commonpb.Empty{})
if err != nil {
return nil, nil, err
}
beacons := beaconsObj.Beacons
sort.Slice(beacons, func(i, j int) bool {
return beacons[i].ID < beacons[j].ID
})
if len(beacons) == 0 && len(sessions) == 0 {
return nil, nil, fmt.Errorf("no sessions or beacons 🙁")
}
// Render selection table
outputBuf := bytes.NewBufferString("")
table := tabwriter.NewWriter(outputBuf, 0, 2, 2, ' ', 0)
sessionOptionMap := map[string]*clientpb.Session{}
for _, session := range sessions {
option := fmt.Sprintf("%s\t%s\t%s\t%s\t%s\t%s\t%s",
"SESSION",
strings.Split(session.ID, "-")[0],
session.Name,
session.RemoteAddress,
session.Hostname,
session.Username,
fmt.Sprintf("%s/%s", session.OS, session.Arch),
)
fmt.Fprintf(table, option+"\n")
o := strings.ReplaceAll(option, "\t", "")
sessionOptionMap[o] = session
}
beaconOptionMap := map[string]*clientpb.Beacon{}
for _, beacon := range beacons {
option := fmt.Sprintf("%s\t%s\t%s\t%s\t%s\t%s\t%s",
"BEACON",
strings.Split(beacon.ID, "-")[0],
beacon.Name,
beacon.RemoteAddress,
beacon.Hostname,
beacon.Username,
fmt.Sprintf("%s/%s", beacon.OS, beacon.Arch),
)
fmt.Fprintf(table, option+"\n")
o := strings.ReplaceAll(option, "\t", "")
beaconOptionMap[o] = beacon
}
table.Flush()
options := strings.Split(outputBuf.String(), "\n")
options = options[:len(options)-1] // Remove the last empty option
prompt := &survey.MultiSelect{
Message: "Select sessions and beacons:",
Options: options,
}
selected := []string{}
survey.AskOne(prompt, &selected)
if len(selected) == 0 {
return nil, nil, fmt.Errorf("no sessions or beacons selected 🤔")
}
selectedSessions := []*clientpb.Session{}
selectedBeacons := []*clientpb.Beacon{}
for _, s := range selected {
s = strings.ReplaceAll(s, " ", "")
s = strings.ReplaceAll(s, "\t", "")
session, ok := sessionOptionMap[s]
if ok {
selectedSessions = append(selectedSessions, session)
}
beacon, ok := beaconOptionMap[s]
if ok {
selectedBeacons = append(selectedBeacons, beacon)
}
}
return selectedSessions, selectedBeacons, nil
}
+1 -2
View File
@@ -20,7 +20,6 @@ package tasks
import (
"context"
"io/ioutil"
"os"
"strings"
"time"
@@ -782,7 +781,7 @@ func promptSaveToFile(data []byte, con *console.SliverConsoleClient) {
return
}
}
err = ioutil.WriteFile(saveTo, data, 0o600)
err = os.WriteFile(saveTo, data, 0o600)
if err != nil {
con.PrintErrorf("Failed to save file: %s\n", err)
return
+1 -2
View File
@@ -23,7 +23,6 @@ import (
"crypto/tls"
"fmt"
"io"
"io/ioutil"
"net"
"net/http"
"net/url"
@@ -120,7 +119,7 @@ func UpdateCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []stri
lastCheck := []byte(fmt.Sprintf("%d", now.Unix()))
appDir := assets.GetRootAppDir()
lastUpdateCheckPath := path.Join(appDir, consts.LastUpdateCheckFileName)
err = ioutil.WriteFile(lastUpdateCheckPath, lastCheck, 0o600)
err = os.WriteFile(lastUpdateCheckPath, lastCheck, 0o600)
if err != nil {
con.Printf("Failed to save update check time %s", err)
}
+2 -2
View File
@@ -23,8 +23,8 @@ import (
"context"
"encoding/base64"
"encoding/hex"
"io/ioutil"
"net"
"os"
"strings"
"text/template"
@@ -95,7 +95,7 @@ func WGConfigCmd(cmd *cobra.Command, con *console.SliverConsoleClient, args []st
if !strings.HasSuffix(save, ".conf") {
save += ".conf"
}
err = ioutil.WriteFile(save, output.Bytes(), 0o600)
err = os.WriteFile(save, output.Bytes(), 0o600)
if err != nil {
con.PrintErrorf("Error: %s\n", err)
return
+21 -2
View File
@@ -192,7 +192,7 @@ func StartClient(con *SliverConsoleClient, rpc rpcpb.SliverRPCClient, serverCmds
consoleLog := getConsoleLogFile()
consoleLogStream, err := con.ClientLogStream("json")
if err != nil {
log.Printf("Could not get client log stream: %s", err)
log.Printf("Could not get client json log stream: %s", err)
}
con.setupLogger(consoleLog, consoleLogStream)
defer consoleLog.Close()
@@ -202,6 +202,9 @@ func StartClient(con *SliverConsoleClient, rpc rpcpb.SliverRPCClient, serverCmds
defer asciicastLog.Close()
asciicastStream, err := con.ClientLogStream("asciicast")
if err != nil {
log.Printf("Could not get client asciicast log stream: %s", err)
}
con.setupAsciicastRecord(asciicastLog, asciicastStream)
}
@@ -547,7 +550,7 @@ func (con *SliverConsoleClient) GetActiveSessionConfig() *clientpb.ImplantConfig
Priority: uint32(0),
})
config := &clientpb.ImplantConfig{
Name: session.GetName(),
ID: session.ID,
GOOS: session.GetOS(),
GOARCH: session.GetArch(),
Debug: true,
@@ -686,6 +689,11 @@ func (s *ActiveTarget) IsSession() bool {
return s.session != nil
}
// IsBeacon - Is the current target a beacon?
func (s *ActiveTarget) IsBeacon() bool {
return s.beacon != nil
}
// AddObserver - Observers to notify when the active session changes
func (s *ActiveTarget) AddObserver(observer Observer) int {
s.observerID++
@@ -793,6 +801,17 @@ func (s *ActiveTarget) Background() {
}
}
// GetHostUUID - Get the Host's UUID (ID in the database)
func (s *ActiveTarget) GetHostUUID() string {
if s.IsSession() {
return s.session.UUID
} else if s.IsBeacon() {
return s.beacon.UUID
}
return ""
}
// Expose or hide commands if the active target does support them (or not).
// Ex; hide Windows commands on Linux implants, Wireguard tools on HTTP C2, etc.
func (con *SliverConsoleClient) ExposeCommands() {
+1 -1
View File
@@ -163,7 +163,7 @@ func (con *SliverConsoleClient) Println(args ...any) {
logger := slog.New(con.jsonHandler)
format := strings.Repeat("%s", len(args))
logger.Info(fmt.Sprintf(format, args))
con.printf(format, args...)
con.printf(format+"\n", args...)
}
// PrintInfof prints an info message immediately below the last line of output.
+17 -5
View File
@@ -127,6 +127,7 @@ const (
BackgroundStr = "background"
InfoStr = "info"
UseStr = "use"
TaskmanyStr = "taskmany"
ReconfigStr = "reconfig"
PruneStr = "prune"
TasksStr = "tasks"
@@ -142,6 +143,8 @@ const (
SettingsStr = "settings"
SearchStr = "search"
TrafficEncodersStr = "traffic-encoders"
C2ProfileStr = "c2profiles"
ImportC2ProfileStr = "import"
// Generic
@@ -179,6 +182,7 @@ const (
HttpsStr = "https"
NamedPipeStr = "named-pipe"
TCPListenerStr = "tcp"
UDPListenerStr = "udp"
MsfStr = "msf"
MsfInjectStr = "msf-inject"
@@ -198,18 +202,24 @@ const (
LsStr = "ls"
MvStr = "mv"
CpStr = "cp"
RmStr = "rm"
StageStr = "stage"
MkdirStr = "mkdir"
CdStr = "cd"
PwdStr = "pwd"
CatStr = "cat"
DownloadStr = "download"
HeadStr = "head"
TailStr = "tail"
GrepStr = "grep"
UploadStr = "upload"
IfconfigStr = "ifconfig"
NetstatStr = "netstat"
ChmodStr = "chmod"
ChownStr = "chown"
ChtimesStr = "chtimes"
MountStr = "mount"
MemfilesStr = "memfiles"
@@ -253,6 +263,7 @@ const (
WgSocksStr = "wg-socks"
WgPortFwdStr = "wg-portfwd"
MonitorStr = "monitor"
MonitorConfigStr = "config"
SSHStr = "ssh"
DLLHijackStr = "dllhijack"
InteractiveStr = "interactive"
@@ -285,11 +296,12 @@ const (
BuildersStr = "builders"
CrackStr = "crack"
StationsStr = "stations"
WordlistsStr = "wordlists"
RulesStr = "rules"
Hcstat2Str = "hcstat2"
CrackStr = "crack"
StationsStr = "stations"
WordlistsStr = "wordlists"
RulesStr = "rules"
Hcstat2Str = "hcstat2"
DefaultC2Profile = "default"
)
// Groups
+2 -2
View File
@@ -22,7 +22,7 @@ import (
"bytes"
"context"
"errors"
"io/ioutil"
"os"
"path"
"github.com/bishopfox/sliver/client/assets"
@@ -139,7 +139,7 @@ func registerLoader(implant ActiveImplant, rpc rpcpb.SliverRPCClient) error {
coffLoaderPath = "COFFLoader.x86.dll"
}
loaderPath := path.Join(assets.GetExtensionsDir(), coffLoaderName, coffLoaderPath)
loaderData, err := ioutil.ReadFile(loaderPath)
loaderData, err := os.ReadFile(loaderPath)
if err != nil {
return err
}
+2 -2
View File
@@ -24,7 +24,7 @@ import (
"encoding/hex"
"encoding/json"
"fmt"
"io/ioutil"
"io"
"net"
"net/http"
"strings"
@@ -161,7 +161,7 @@ func requestPayload(target string) ([]byte, error) {
if resp.StatusCode != 200 {
return nil, fmt.Errorf("invalid status code: %d", resp.StatusCode)
}
return ioutil.ReadAll(resp.Body)
return io.ReadAll(resp.Body)
}
func (a *OperatorImplantBridge) refreshBeacon() {
+2 -2
View File
@@ -3,7 +3,7 @@ package version
import (
"encoding/json"
"errors"
"io/ioutil"
"io"
"net/http"
"os"
"strconv"
@@ -77,7 +77,7 @@ func CheckForUpdates(client *http.Client, prereleases bool) (*Release, error) {
return nil, err
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
body, err := io.ReadAll(resp.Body)
if err != nil {
return nil, err
}
-24
View File
@@ -1,24 +0,0 @@
---
layout: default
---
<style type="text/css" media="screen">
.container {
margin: 10px auto;
max-width: 600px;
text-align: center;
}
h1 {
margin: 30px 0;
font-size: 4em;
line-height: 1;
letter-spacing: -1px;
}
</style>
<div class="container">
<h1>404</h1>
<p><strong>Page not found :(</strong></p>
<p>The requested page could not be found.</p>
</div>
-41
View File
@@ -1,41 +0,0 @@
source "https://rubygems.org"
# Hello! This is where you manage which Jekyll version is used to run.
# When you want to use a different version, change it below, save the
# file and run `bundle install`. Run Jekyll with `bundle exec`, like so:
#
# bundle exec jekyll serve
#
# This will help ensure the proper Jekyll version is running.
# Happy Jekylling!
gem "jekyll", "~> 3.9.0"
# This is the default theme for new Jekyll sites. You may change this to anything you like.
# gem "minima", "~> 2.0"
gem "github-pages", group: :jekyll_plugins
# If you want to use GitHub Pages, remove the "gem "jekyll"" above and
# uncomment the line below. To upgrade, run `bundle update github-pages`.
# gem "github-pages", group: :jekyll_plugins
# If you have any plugins, put them here!
group :jekyll_plugins do
gem "jekyll-feed", "~> 0.6"
end
# Windows does not include zoneinfo files, so bundle the tzinfo-data gem
# and associated library.
install_if -> { RUBY_PLATFORM =~ %r!mingw|mswin|java! } do
gem "tzinfo", "~> 1.2"
gem "tzinfo-data"
end
# Performance-booster for watching directories on Windows
gem "wdm", "~> 0.1.0", :install_if => Gem.win_platform?
# kramdown v2 ships without the gfm parser by default. If you're using
# kramdown v1, comment out this line.
gem "kramdown-parser-gfm"
gem "webrick", "~> 1.8"
-274
View File
@@ -1,274 +0,0 @@
GEM
remote: https://rubygems.org/
specs:
activesupport (6.0.6.1)
concurrent-ruby (~> 1.0, >= 1.0.2)
i18n (>= 0.7, < 2)
minitest (~> 5.1)
tzinfo (~> 1.1)
zeitwerk (~> 2.2, >= 2.2.2)
addressable (2.8.1)
public_suffix (>= 2.0.2, < 6.0)
coffee-script (2.4.1)
coffee-script-source
execjs
coffee-script-source (1.11.1)
colorator (1.1.0)
commonmarker (0.23.9)
concurrent-ruby (1.2.0)
dnsruby (1.61.9)
simpleidn (~> 0.1)
em-websocket (0.5.3)
eventmachine (>= 0.12.9)
http_parser.rb (~> 0)
ethon (0.16.0)
ffi (>= 1.15.0)
eventmachine (1.2.7)
execjs (2.8.1)
faraday (2.7.4)
faraday-net_http (>= 2.0, < 3.1)
ruby2_keywords (>= 0.0.4)
faraday-net_http (3.0.2)
ffi (1.15.5)
forwardable-extended (2.6.0)
gemoji (3.0.1)
github-pages (228)
github-pages-health-check (= 1.17.9)
jekyll (= 3.9.3)
jekyll-avatar (= 0.7.0)
jekyll-coffeescript (= 1.1.1)
jekyll-commonmark-ghpages (= 0.4.0)
jekyll-default-layout (= 0.1.4)
jekyll-feed (= 0.15.1)
jekyll-gist (= 1.5.0)
jekyll-github-metadata (= 2.13.0)
jekyll-include-cache (= 0.2.1)
jekyll-mentions (= 1.6.0)
jekyll-optional-front-matter (= 0.3.2)
jekyll-paginate (= 1.1.0)
jekyll-readme-index (= 0.3.0)
jekyll-redirect-from (= 0.16.0)
jekyll-relative-links (= 0.6.1)
jekyll-remote-theme (= 0.4.3)
jekyll-sass-converter (= 1.5.2)
jekyll-seo-tag (= 2.8.0)
jekyll-sitemap (= 1.4.0)
jekyll-swiss (= 1.0.0)
jekyll-theme-architect (= 0.2.0)
jekyll-theme-cayman (= 0.2.0)
jekyll-theme-dinky (= 0.2.0)
jekyll-theme-hacker (= 0.2.0)
jekyll-theme-leap-day (= 0.2.0)
jekyll-theme-merlot (= 0.2.0)
jekyll-theme-midnight (= 0.2.0)
jekyll-theme-minimal (= 0.2.0)
jekyll-theme-modernist (= 0.2.0)
jekyll-theme-primer (= 0.6.0)
jekyll-theme-slate (= 0.2.0)
jekyll-theme-tactile (= 0.2.0)
jekyll-theme-time-machine (= 0.2.0)
jekyll-titles-from-headings (= 0.5.3)
jemoji (= 0.12.0)
kramdown (= 2.3.2)
kramdown-parser-gfm (= 1.1.0)
liquid (= 4.0.4)
mercenary (~> 0.3)
minima (= 2.5.1)
nokogiri (>= 1.13.6, < 2.0)
rouge (= 3.26.0)
terminal-table (~> 1.4)
github-pages-health-check (1.17.9)
addressable (~> 2.3)
dnsruby (~> 1.60)
octokit (~> 4.0)
public_suffix (>= 3.0, < 5.0)
typhoeus (~> 1.3)
html-pipeline (2.14.3)
activesupport (>= 2)
nokogiri (>= 1.4)
http_parser.rb (0.8.0)
i18n (1.12.0)
concurrent-ruby (~> 1.0)
jekyll (3.9.3)
addressable (~> 2.4)
colorator (~> 1.0)
em-websocket (~> 0.5)
i18n (>= 0.7, < 2)
jekyll-sass-converter (~> 1.0)
jekyll-watch (~> 2.0)
kramdown (>= 1.17, < 3)
liquid (~> 4.0)
mercenary (~> 0.3.3)
pathutil (~> 0.9)
rouge (>= 1.7, < 4)
safe_yaml (~> 1.0)
jekyll-avatar (0.7.0)
jekyll (>= 3.0, < 5.0)
jekyll-coffeescript (1.1.1)
coffee-script (~> 2.2)
coffee-script-source (~> 1.11.1)
jekyll-commonmark (1.4.0)
commonmarker (~> 0.22)
jekyll-commonmark-ghpages (0.4.0)
commonmarker (~> 0.23.7)
jekyll (~> 3.9.0)
jekyll-commonmark (~> 1.4.0)
rouge (>= 2.0, < 5.0)
jekyll-default-layout (0.1.4)
jekyll (~> 3.0)
jekyll-feed (0.15.1)
jekyll (>= 3.7, < 5.0)
jekyll-gist (1.5.0)
octokit (~> 4.2)
jekyll-github-metadata (2.13.0)
jekyll (>= 3.4, < 5.0)
octokit (~> 4.0, != 4.4.0)
jekyll-include-cache (0.2.1)
jekyll (>= 3.7, < 5.0)
jekyll-mentions (1.6.0)
html-pipeline (~> 2.3)
jekyll (>= 3.7, < 5.0)
jekyll-optional-front-matter (0.3.2)
jekyll (>= 3.0, < 5.0)
jekyll-paginate (1.1.0)
jekyll-readme-index (0.3.0)
jekyll (>= 3.0, < 5.0)
jekyll-redirect-from (0.16.0)
jekyll (>= 3.3, < 5.0)
jekyll-relative-links (0.6.1)
jekyll (>= 3.3, < 5.0)
jekyll-remote-theme (0.4.3)
addressable (~> 2.0)
jekyll (>= 3.5, < 5.0)
jekyll-sass-converter (>= 1.0, <= 3.0.0, != 2.0.0)
rubyzip (>= 1.3.0, < 3.0)
jekyll-sass-converter (1.5.2)
sass (~> 3.4)
jekyll-seo-tag (2.8.0)
jekyll (>= 3.8, < 5.0)
jekyll-sitemap (1.4.0)
jekyll (>= 3.7, < 5.0)
jekyll-swiss (1.0.0)
jekyll-theme-architect (0.2.0)
jekyll (> 3.5, < 5.0)
jekyll-seo-tag (~> 2.0)
jekyll-theme-cayman (0.2.0)
jekyll (> 3.5, < 5.0)
jekyll-seo-tag (~> 2.0)
jekyll-theme-dinky (0.2.0)
jekyll (> 3.5, < 5.0)
jekyll-seo-tag (~> 2.0)
jekyll-theme-hacker (0.2.0)
jekyll (> 3.5, < 5.0)
jekyll-seo-tag (~> 2.0)
jekyll-theme-leap-day (0.2.0)
jekyll (> 3.5, < 5.0)
jekyll-seo-tag (~> 2.0)
jekyll-theme-merlot (0.2.0)
jekyll (> 3.5, < 5.0)
jekyll-seo-tag (~> 2.0)
jekyll-theme-midnight (0.2.0)
jekyll (> 3.5, < 5.0)
jekyll-seo-tag (~> 2.0)
jekyll-theme-minimal (0.2.0)
jekyll (> 3.5, < 5.0)
jekyll-seo-tag (~> 2.0)
jekyll-theme-modernist (0.2.0)
jekyll (> 3.5, < 5.0)
jekyll-seo-tag (~> 2.0)
jekyll-theme-primer (0.6.0)
jekyll (> 3.5, < 5.0)
jekyll-github-metadata (~> 2.9)
jekyll-seo-tag (~> 2.0)
jekyll-theme-slate (0.2.0)
jekyll (> 3.5, < 5.0)
jekyll-seo-tag (~> 2.0)
jekyll-theme-tactile (0.2.0)
jekyll (> 3.5, < 5.0)
jekyll-seo-tag (~> 2.0)
jekyll-theme-time-machine (0.2.0)
jekyll (> 3.5, < 5.0)
jekyll-seo-tag (~> 2.0)
jekyll-titles-from-headings (0.5.3)
jekyll (>= 3.3, < 5.0)
jekyll-watch (2.2.1)
listen (~> 3.0)
jemoji (0.12.0)
gemoji (~> 3.0)
html-pipeline (~> 2.2)
jekyll (>= 3.0, < 5.0)
kramdown (2.3.2)
rexml
kramdown-parser-gfm (1.1.0)
kramdown (~> 2.0)
liquid (4.0.4)
listen (3.8.0)
rb-fsevent (~> 0.10, >= 0.10.3)
rb-inotify (~> 0.9, >= 0.9.10)
mercenary (0.3.6)
mini_portile2 (2.8.1)
minima (2.5.1)
jekyll (>= 3.5, < 5.0)
jekyll-feed (~> 0.9)
jekyll-seo-tag (~> 2.1)
minitest (5.17.0)
nokogiri (1.14.3)
mini_portile2 (~> 2.8.0)
racc (~> 1.4)
octokit (4.25.1)
faraday (>= 1, < 3)
sawyer (~> 0.9)
pathutil (0.16.2)
forwardable-extended (~> 2.6)
public_suffix (4.0.7)
racc (1.6.2)
rb-fsevent (0.11.2)
rb-inotify (0.10.1)
ffi (~> 1.0)
rexml (3.2.5)
rouge (3.26.0)
ruby2_keywords (0.0.5)
rubyzip (2.3.2)
safe_yaml (1.0.5)
sass (3.7.4)
sass-listen (~> 4.0.0)
sass-listen (4.0.0)
rb-fsevent (~> 0.9, >= 0.9.4)
rb-inotify (~> 0.9, >= 0.9.7)
sawyer (0.9.2)
addressable (>= 2.3.5)
faraday (>= 0.17.3, < 3)
simpleidn (0.2.1)
unf (~> 0.1.4)
terminal-table (1.8.0)
unicode-display_width (~> 1.1, >= 1.1.1)
thread_safe (0.3.6)
typhoeus (1.4.0)
ethon (>= 0.9.0)
tzinfo (1.2.11)
thread_safe (~> 0.1)
tzinfo-data (1.2022.7)
tzinfo (>= 1.0.0)
unf (0.1.4)
unf_ext
unf_ext (0.0.8.2)
unicode-display_width (1.8.0)
wdm (0.1.1)
webrick (1.8.1)
zeitwerk (2.6.7)
PLATFORMS
ruby
DEPENDENCIES
github-pages
jekyll (~> 3.9.0)
jekyll-feed (~> 0.6)
kramdown-parser-gfm
tzinfo (~> 1.2)
tzinfo-data
wdm (~> 0.1.0)
webrick (~> 1.8)
BUNDLED WITH
2.4.6
-51
View File
@@ -1,51 +0,0 @@
# Welcome to Jekyll!
#
# This config file is meant for settings that affect your whole blog, values
# which you are expected to set up once and rarely edit after that. If you find
# yourself editing this file very often, consider using Jekyll's data files
# feature for the data you need to update frequently.
#
# For technical reasons, this file is *NOT* reloaded automatically when you use
# 'bundle exec jekyll serve'. If you change this file, please restart the server process.
# Site settings
# These are used to personalize your new site. If you look in the HTML files,
# you will see them accessed via {{ site.title }}, {{ site.email }}, and so on.
# You can create any custom variable you would like, and they will be accessible
# in the templates via {{ site.myvariable }}.
title: Sliver
description: >- # this means to ignore newlines until "baseurl:"
Sliver is an open source cross-platform adversary emulation/red team framework.
baseurl: "" # the subpath of your site, e.g. /blog
url: "https://sliver.sh/"
github:
latest_url: https://github.com/BishopFox/sliver/releases/latest
repository_url: https://github.com/BishopFox/sliver
# Build settings
markdown: kramdown
theme: jekyll-theme-hacker
show_downloads: true
plugins:
- jekyll-feed
plugins:
- jekyll-notion
# https://www.notion.so/sliver-sh/Sliver-4bbf1c77cabc46e09428c871283683d3?pvs=4
notion:
fetch_on_watch: true
databases:
- id: 4bbf1c77cabc46e09428c871283683d3
# Exclude from processing.
# The following items will not be processed, by default. Create a custom list
# to override the default setting.
exclude:
- Gemfile
- Gemfile.lock
- CNAME
- .gitignore
- _site
-39
View File
@@ -1,39 +0,0 @@
<!DOCTYPE html>
<html lang="{{ site.lang | default: "en-US" }}">
<head>
<meta charset='utf-8'>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="{{ '/assets/css/style.css?v=' | append: site.github.build_revision | relative_url }}">
{% seo %}
</head>
<body>
<header>
<div class="container">
<a id="a-title" href="{{ '/' | relative_url }}">
<h1>{{ site.title | default: site.github.repository_name }}</h1>
</a>
<h2>{{ site.description | default: site.github.project_tagline }}</h2>
<section id="downloads">
{% if site.show_downloads %}
<a href="{{ site.github.latest_url }}" target="_blank" class="btn">Latest Release</a>
{% endif %}
<a href="{{ site.github.repository_url }}" target="_blank" class="btn btn-github"><span class="icon"></span>View on GitHub</a>
</section>
</div>
</header>
<div class="container">
<section id="main_content">
{{ content }}
</section>
</div>
</body>
</html>
-14
View File
@@ -1,14 +0,0 @@
---
layout: default
---
<small>{{ page.date | date: "%-d %B %Y" }}</small>
<h1>{{ page.title }}</h1>
<p class="view">by {{ page.author | default: site.author }}</p>
{{ content }}
{% if page.tags %}
<small>tags: <em>{{ page.tags | join: "</em> - <em>" }}</em></small>
{% endif %}
-18
View File
@@ -1,18 +0,0 @@
---
layout: default
title: About
permalink: /about/
---
This is the base Jekyll theme. You can find out more info about customizing your Jekyll theme, as well as basic Jekyll usage documentation at [jekyllrb.com](https://jekyllrb.com/)
You can find the source code for Minima at GitHub:
[jekyll][jekyll-organization] /
[minima](https://github.com/jekyll/minima)
You can find the source code for Jekyll at GitHub:
[jekyll][jekyll-organization] /
[jekyll](https://github.com/jekyll/jekyll)
[jekyll-organization]: https://github.com/jekyll
-11
View File
@@ -1,11 +0,0 @@
---
layout: default
---
<ul>
{% for post in site.posts %}
<li>
<a href="{{ post.url }}">{{ post.title }}</a>
</li>
{% endfor %}
</ul>
+3
View File
@@ -0,0 +1,3 @@
{
"extends": "next/core-web-vitals"
}
+44
View File
@@ -0,0 +1,44 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# generated files
public/sitemap.json
public/docs.json
/www.zip
# code editor files
.vscode/
# dependencies
/node_modules
/.pnp
.pnp.js
.yarn/install-state.gz
# testing
/coverage
# next.js
/.next/
/out/
# production
/build
# misc
.DS_Store
*.pem
# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# local env files
.env*.local
# vercel
.vercel
# typescript
*.tsbuildinfo
next-env.d.ts
+33
View File
@@ -0,0 +1,33 @@
# Sliver Docs
The source code for the Sliver documentation site.
### Developers
To run the documentation site locally first install the dependencies and then run the `dev` npm script:
```bash
npm install
npm run dev
```
**NOTE:** The markdown is compiled into a static JSON object at build time. This means if you edit a `.md` file you will need to restart the dev server to see your changes.
### Offline Docs
To run your own copy of the documentation first install the dependencies and then run the `offline` npm script:
```bash
npm install
npm run offline
```
This will produce a `www.zip` file that contains the static html and JavaScript for the documentation site. You can extract this archive and host it anywhere:
```bash
unzip -o www.zip
cd out/
python -m http.server 8000
```
Then open your browser to `http://localhost:8000/` to view the documentation.
+21
View File
@@ -0,0 +1,21 @@
declare module "asciinema-player" {
export function create(
src: string,
element: HTMLElement | null,
// START asciinemaOptions
opts: {
cols?: string,
rows?: string,
autoPlay?: boolean,
preload?: boolean,
loop?: boolean | number,
startAt?: number | string,
speed?: number,
idleTimeLimit?: number,
theme?: string,
poster?: string,
fit?: string,
fontSize?: string
}
)
}
@@ -0,0 +1,3 @@
.hide-control-bar :global(.ap-control-bar){
display: none !important;
}
+41
View File
@@ -0,0 +1,41 @@
import "asciinema-player/dist/bundle/asciinema-player.css";
import React from "react";
type AsciinemaPlayerProps = {
src: string;
cols?: string;
rows?: string;
autoPlay?: boolean;
preload?: boolean;
loop?: boolean | number;
startAt?: number | string;
speed?: number;
idleTimeLimit?: number;
theme?: string;
poster?: string;
fit?: string;
fontSize?: string;
};
function AsciinemaPlayer({ src, ...asciinemaOptions }: AsciinemaPlayerProps) {
const ref = React.useRef<HTMLDivElement>(null);
const [player, setPlayer] =
React.useState<typeof import("asciinema-player")>();
React.useEffect(() => {
import("asciinema-player").then((p) => {
setPlayer(p);
});
}, []);
React.useEffect(() => {
const currentRef = ref.current;
const instance = player?.create(src, currentRef, asciinemaOptions);
return () => {
instance?.dispose();
};
}, [src, player, asciinemaOptions]);
return <div ref={ref} />;
}
export default AsciinemaPlayer;
+91
View File
@@ -0,0 +1,91 @@
import { Themes } from "@/util/themes";
import { faLinux, faPython } from "@fortawesome/free-brands-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import Editor, { loader } from "@monaco-editor/react";
import { useTheme } from "next-themes";
import React, { useRef } from "react";
export type CodeSchema = {
name: string;
script_type: string;
source_code: string;
};
export type CodeViewerProps = {
script: CodeSchema;
fontSize?: number;
className?: string;
};
export function renderScriptTypeIcon(key: string, className?: string) {
switch (key) {
case "bash":
return (
<FontAwesomeIcon icon={faLinux} className={className || undefined} />
);
case "python":
return (
<FontAwesomeIcon icon={faPython} className={className || undefined} />
);
default:
return <></>;
}
}
const CodeViewer = (props: CodeViewerProps) => {
const { theme } = useTheme();
// Editor
loader.config({ paths: { vs: "/js/monaco" } });
const editorRef = useRef(null as any);
function handleEditorDidMount(editor: any, monaco: any) {
editorRef.current = editor;
}
const vsTheme = React.useMemo(() => {
return theme === Themes.DARK ? "vs-dark" : undefined;
}, [theme]);
const language = React.useMemo(() => {
switch (props.script?.script_type) {
case "bash":
return "shell";
default:
return props.script?.script_type || "shell";
}
}, [props]);
const [scriptSourceCode, setScriptSourceCode] = React.useState(
props.script.source_code
);
const [fontSize, setFontSize] = React.useState(props.fontSize || 14);
const editorContainerClassName = React.useMemo(() => {
return theme === Themes.DARK
? "col-span-12 mt-4 rounded-2xl overflow-hidden"
: "col-span-12 mt-4 rounded-2xl overflow-hidden border border-gray-300";
}, [theme]);
return (
<div className={editorContainerClassName}>
<Editor
className={props.className || "min-h-[200px]"}
theme={vsTheme}
defaultLanguage={language}
defaultValue={scriptSourceCode}
onChange={(value, event) => {
setScriptSourceCode(value || "");
}}
onMount={handleEditorDidMount}
options={{
readOnly: true,
fontFamily: "Fira Code",
fontLigatures: true,
fontSize: fontSize,
}}
/>
</div>
);
};
export default CodeViewer;
@@ -0,0 +1,26 @@
export type SliversIconProps = {
className?: string;
fill?: string;
height?: number;
width?: number;
};
export const SliversIcon = (props: SliversIconProps) => {
return (
<svg
aria-hidden="true"
focusable="false"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 912 1024"
className={props.className}
height={props.height || 24}
width={props.width}
>
<path
fill={props.fill ? props.fill : "currentColor"}
d="M3.767 709.26s-38.415-249.17 142.452-440.946C326.97 76.538 584.482 63.816 759.689 133.127c0 0-32.847 29.271-32.847 65.806 0 36.444 21.936 58.378 45.658 82.101 23.723 23.815 135.095 158.909 135.095 312.294 0 153.453-125.972 336.015-324.992 336.015-199.042 0-312.293-144.239-328.682-310.414 0 0 96.771 164.294 255.611 164.294s213.62-125.971 213.62-219.167c0-93.034-51.113-272.02-275.666-272.02-224.645 0-379.795 199.042-443.72 417.224z"
></path>
</svg>
);
};
+188
View File
@@ -0,0 +1,188 @@
import CodeViewer, { CodeSchema } from "@/components/code";
import { Themes } from "@/util/themes";
import { useTheme } from "next-themes";
import Image from "next/image";
import Link from "next/link";
import { useRouter } from "next/router";
import Markdown from "react-markdown";
import remarkGfm from "remark-gfm";
import AsciinemaPlayer from "./asciinema";
export type MarkdownProps = {
key?: string;
markdown: string;
};
type MarkdownAsciiCast = {
src?: string;
rows?: string;
cols?: string;
idleTimeLimit?: number;
};
const MarkdownViewer = (props: MarkdownProps) => {
const { theme } = useTheme();
const router = useRouter();
return (
<div
className={
theme === Themes.DARK ? "prose dark:prose-invert" : "prose prose-slate"
}
>
<Markdown
key={props.key || `${Math.random()}`}
remarkPlugins={[remarkGfm]}
components={{
a(props) {
const { href, children, ...rest } = props;
if (href?.startsWith("/")) {
return (
// @ts-ignore
<a
{...rest}
href={href}
className="text-primary hover:text-primary-dark"
onClick={(e) => {
e.preventDefault();
router.push(href);
}}
>
{children}
</a>
);
}
const url = new URL(href || "");
if (url.protocol !== "http:" && url.protocol !== "https:") {
return <></>;
}
if (url.host === "sliver.sh") {
return (
// @ts-ignore
<Link
{...rest}
href={url.toString()}
className="text-primary hover:text-primary-dark"
>
{children}
</Link>
);
}
return (
<a
{...rest}
href={url.toString()}
rel="noopener noreferrer"
target="_blank"
className="text-primary hover:text-primary-dark"
>
{children}
</a>
);
},
pre(props) {
// We need to look at the child nodes to avoid wrapping
// a monaco code block in a <pre> tag
const { children, className, node, ...rest } = props;
const childClass = (children as any)?.props?.className;
if (
childClass &&
childClass.startsWith("language-") &&
childClass !== "language-plaintext"
) {
// @ts-ignore
return <div {...rest}>{children}</div>;
}
return (
<pre {...rest} className={className}>
{children}
</pre>
);
},
img(props) {
const { src, alt, ...rest } = props;
return (
// @ts-ignore
<Image
{...rest}
src={src || ""}
alt={alt || ""}
width={500}
height={500}
className="w-full rounded-medium"
/>
);
},
code(props) {
const { children, className, node, ...rest } = props;
const langTag = /language-(\w+)/.exec(className || "");
const lang = langTag ? langTag[1] : "plaintext";
if (lang === "plaintext") {
return (
<span className="prose-sm">
<code {...rest} className={className}>
{children}
</code>
</span>
);
}
if (lang === "asciinema") {
const asciiCast: MarkdownAsciiCast = JSON.parse(
children as string
);
const src = asciiCast.src?.startsWith("/")
? `${window.location.origin}${asciiCast.src}`
: asciiCast.src || "";
const srcUrl = new URL(src);
if (srcUrl.protocol !== "http:" && srcUrl.protocol !== "https:") {
return <></>;
}
return (
<AsciinemaPlayer
src={srcUrl.toString()}
rows={asciiCast.rows || "18"}
cols={asciiCast.cols || "75"}
idleTimeLimit={asciiCast.idleTimeLimit || 2}
preload={true}
autoPlay={true}
loop={true}
/>
);
}
const sourceCode = (children as string) || "";
const lines = sourceCode.split("\n").length;
return (
<CodeViewer
className={
lines < 7
? "min-h-[100px]"
: lines < 17
? "min-h-[250px]"
: "min-h-[450px]"
}
key={`${Math.random()}`}
fontSize={11}
script={
{
script_type: lang,
source_code: sourceCode,
} as CodeSchema
}
/>
);
},
}}
>
{props.markdown}
</Markdown>
</div>
);
};
export default MarkdownViewer;
+142
View File
@@ -0,0 +1,142 @@
"use client";
import { SliversIcon } from "@/components/icons/slivers";
import { useSearchContext } from "@/util/search-context";
import { Themes } from "@/util/themes";
import { faGithub } from "@fortawesome/free-brands-svg-icons";
import {
faHome,
faMoon,
faSearch,
faSun,
} from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import {
Button,
Input,
Link,
Navbar,
NavbarBrand,
NavbarContent,
NavbarItem,
Tooltip,
} from "@nextui-org/react";
import { useTheme } from "next-themes";
import { useRouter } from "next/router";
import React from "react";
export type TopNavbarProps = {};
export default function TopNavbar(props: TopNavbarProps) {
const router = useRouter();
const search = useSearchContext();
const { theme, setTheme } = useTheme();
const lightDarkModeIcon = React.useMemo(
() => (theme === Themes.DARK ? faSun : faMoon),
[theme]
);
const [query, setQuery] = React.useState("");
return (
<Navbar
isBordered
maxWidth="full"
classNames={{
item: [
"flex",
"relative",
"h-full",
"items-center",
"data-[active=true]:after:content-['']",
"data-[active=true]:after:absolute",
"data-[active=true]:after:bottom-0",
"data-[active=true]:after:left-0",
"data-[active=true]:after:right-0",
"data-[active=true]:after:h-[2px]",
"data-[active=true]:after:rounded-[2px]",
"data-[active=true]:after:bg-primary",
],
}}
>
<NavbarBrand>
<SliversIcon />
<span className="hidden sm:block font-bold text-inherit">
&nbsp; Sliver C2
</span>
</NavbarBrand>
<NavbarContent>
<NavbarItem isActive={router.pathname === "/"}>
<Button
variant="light"
color={router.pathname === "/" ? "primary" : "default"}
as={Link}
onPress={() => router.push("/")}
>
<FontAwesomeIcon fixedWidth icon={faHome} />
</Button>
</NavbarItem>
<NavbarItem isActive={router.pathname.startsWith("/tutorials")}>
<Button
variant="light"
color={router.pathname === "/tutorials" ? "primary" : "default"}
as={Link}
onPress={() => router.push("/tutorials")}
>
Tutorials
</Button>
</NavbarItem>
<NavbarItem isActive={router.pathname.startsWith("/docs")}>
<Button
variant="light"
color={router.pathname === "/docs" ? "primary" : "default"}
as={Link}
onPress={() => router.push("/docs")}
>
Docs
</Button>
</NavbarItem>
</NavbarContent>
<NavbarContent as="div" justify="end">
<Tooltip content="Press enter to search" isOpen={query.length > 0}>
<Input
size="sm"
placeholder="Search..."
value={query}
onChange={(e) => setQuery(e.target.value)}
onClear={() => setQuery("")}
startContent={<FontAwesomeIcon icon={faSearch} />}
onKeyDown={(e) => {
if (e.key === "Enter") {
router.push({ pathname: `/search/`, query: { search: query } });
setQuery("");
}
}}
/>
</Tooltip>
<Button
variant="ghost"
onPress={() => {
setTheme(theme === Themes.DARK ? Themes.LIGHT : Themes.DARK);
}}
>
<FontAwesomeIcon icon={lightDarkModeIcon} />
</Button>
<Button
variant="ghost"
onPress={() => {
window.open("https://github.com/BishopFox/sliver", "_blank");
}}
>
<FontAwesomeIcon icon={faGithub} />
</Button>
</NavbarContent>
</Navbar>
);
}
@@ -0,0 +1,75 @@
import { Button, Card, CardFooter, CardHeader } from "@nextui-org/react";
import AsciinemaPlayer from "./asciinema";
import { faChevronRight } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import styles from "./TutorialCard.module.css";
export type TutorialCardCardProps = {
name: string;
description: string;
asciiCast: string;
rows?: string;
cols?: string;
idleTimeLimit?: number;
italicDescription?: boolean;
onPress?: () => void;
showButton?: boolean;
buttonText?: string;
};
export default function TutorialCard(props: TutorialCardCardProps) {
return (
<Card isFooterBlurred>
<CardHeader className="absolute z-10 top-1 flex-col items-end">
<p className="text-md text-white/70 uppercase font-bold">
{props.name}
</p>
</CardHeader>
<div className={styles["hide-control-bar"]}>
<AsciinemaPlayer
src={props.asciiCast}
rows={props.rows ? props.rows : "18"}
cols={props.cols ? props.cols : "75"}
idleTimeLimit={props.idleTimeLimit ? props.idleTimeLimit : 2}
preload={true}
autoPlay={true}
loop={true}
/>
</div>
<CardFooter className="absolute bg-black/40 bottom-0 z-100 border-t-1 border-default-600 dark:border-default-100">
<div className="flex w-full items-center">
<p
className={
props.italicDescription
? "text-xs text-white/80 italic"
: "text-xs text-white/80"
}
>
{props.description}
</p>
{props.showButton ? (
<div className="justify-items-end">
<Button
variant="ghost"
color="warning"
size="sm"
onPress={props.onPress}
>
{props.buttonText ? props.buttonText : "Read Tutorial"}{" "}
<FontAwesomeIcon icon={faChevronRight} />
</Button>
</div>
) : (
<></>
)}
</div>
</CardFooter>
</Card>
);
}
+19
View File
@@ -0,0 +1,19 @@
/** @type {import('next').NextConfig} */
const nextConfig = {
output: 'export',
reactStrictMode: true,
images: {
unoptimized: true,
},
experimental: {
scrollRestoration: true,
},
webpack: (config, { isServer }) => {
if (isServer) {
require('./prebuild/generate-docs');
}
return config;
}
}
module.exports = nextConfig;
+8578
View File
File diff suppressed because it is too large. Load diff
+44
View File
@@ -0,0 +1,44 @@
{
"name": "sliver-docs",
"version": "0.1.0",
"private": true,
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
"lint": "next lint",
"offline": "next build && zip -r www.zip ./out"
},
"dependencies": {
"@fontsource/fira-code": "^5.0.16",
"@fortawesome/free-brands-svg-icons": "^6.5.1",
"@fortawesome/free-solid-svg-icons": "^6.5.1",
"@fortawesome/react-fontawesome": "^0.2.0",
"@monaco-editor/react": "^4.6.0",
"@nextui-org/react": "^2.2.9",
"@tanstack/react-query": "^5.13.4",
"asciinema-player": "^3.6.3",
"framer-motion": "^10.16.16",
"fuse.js": "^7.0.0",
"lunr": "^2.3.9",
"next": "14.0.4",
"next-themes": "^0.2.1",
"react": "18.2.0",
"react-dom": "18.2.0",
"react-markdown": "^9.0.1",
"remark-gfm": "^4.0.0"
},
"devDependencies": {
"@tailwindcss/typography": "^0.5.10",
"@types/lunr": "^2.3.7",
"@types/node": "^20",
"@types/react": "^18",
"@types/react-dom": "^18",
"autoprefixer": "^10.0.1",
"eslint": "^8",
"eslint-config-next": "14.0.4",
"postcss": "^8",
"tailwindcss": "^3.3.0",
"typescript": "^5"
}
}
+95
View File
@@ -0,0 +1,95 @@
import Navbar from "@/components/navbar";
import "@/styles/globals.css";
import { Docs } from "@/util/docs";
import { SearchContext, SearchCtx } from "@/util/search-context";
import { Themes } from "@/util/themes";
import { faExternalLink } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { NextUIProvider } from "@nextui-org/react";
import {
HydrationBoundary,
QueryClient,
QueryClientProvider,
} from "@tanstack/react-query";
import { ThemeProvider as NextThemesProvider, useTheme } from "next-themes";
import type { AppProps } from "next/app";
import React from "react";
export default function App({ Component, pageProps }: AppProps) {
// Initialize theme
const { theme, setTheme } = useTheme();
function getThemeState(): Themes {
if (typeof window !== "undefined") {
const loadedTheme = localStorage.getItem("theme");
const currentTheme = loadedTheme ? (loadedTheme as Themes) : Themes.DARK;
setTheme(currentTheme);
}
return Themes.DARK;
}
// Initialize search
const [search, setSearch] = React.useState(new SearchCtx());
// Initialize query client
const [queryClient] = React.useState(() => new QueryClient());
queryClient.prefetchQuery({
queryKey: ["docs"],
queryFn: async (): Promise<Docs> => {
const res = await fetch("/docs.json");
const docs: Docs = await res.json();
search.addDocs(docs);
return docs;
},
});
return (
<NextUIProvider>
<NextThemesProvider attribute="class" defaultTheme={getThemeState()}>
<QueryClientProvider client={queryClient}>
<HydrationBoundary state={pageProps.dehydratedState}>
<SearchContext.Provider value={search}>
<Navbar />
<Component {...pageProps} />
<div className="mb-12"></div>
<footer className="fixed bottom-0 left-0 z-20 w-full p-2 bg-white border-t border-gray-200 shadow md:flex md:items-center md:justify-between md:p-6 dark:bg-black dark:border-gray-600">
<span className="text-sm text-gray-500 sm:text-center dark:text-gray-400">
© {new Date().getFullYear()}{" "}
<a
href="https://bishopfox.com/"
className="hover:underline"
rel="noreferrer"
target="_blank"
>
Bishop Fox
</a>
{" - "}
<a
href="https://github.com/BishopFox/sliver/pulls"
rel="noreferrer"
className="hover:underline"
target="_blank"
>
You can help improve this documentation by opening a pull
request on Github <FontAwesomeIcon icon={faExternalLink} />
</a>
</span>
<ul className="flex flex-wrap items-center mt-3 text-sm font-medium text-gray-500 dark:text-gray-400 sm:mt-0">
<li>
<a
href="https://github.com/BishopFox/sliver/blob/master/LICENSE"
target="_blank"
rel="noreferrer"
className="hover:underline me-4 md:me-6"
>
GPLv3 License
</a>
</li>
</ul>
</footer>
</SearchContext.Provider>
</HydrationBoundary>
</QueryClientProvider>
</NextThemesProvider>
</NextUIProvider>
);
}
+32
View File
@@ -0,0 +1,32 @@
import Document, { Head, Html, Main, NextScript } from "next/document";
import React from "react";
// This generates the https: and wss: "connect-src" directives based on the above backends list so its a little easier to edit.
const CSP = `default-src 'none'; script-src 'self' 'unsafe-eval'; img-src 'self'; style-src 'self' 'unsafe-inline'; font-src 'self'; connect-src 'self'`;
class MyDocument extends Document {
static async getInitialProps(ctx: any) {
const initialProps = await Document.getInitialProps(ctx);
return {
...initialProps,
styles: React.Children.toArray([initialProps.styles]),
};
}
render() {
return (
<Html lang="en">
<Head>
<title>Sliver Docs</title>
<meta httpEquiv="Content-Security-Policy" content={CSP} />
</Head>
<body>
<Main />
<NextScript />
</body>
</Html>
);
}
}
export default MyDocument;
+152
View File
@@ -0,0 +1,152 @@
import MarkdownViewer from "@/components/markdown";
import { Docs } from "@/util/docs";
import { Themes } from "@/util/themes";
import { faSearch } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import {
Card,
CardBody,
CardHeader,
Divider,
Input,
Listbox,
ListboxItem,
ScrollShadow,
} from "@nextui-org/react";
import { useQuery } from "@tanstack/react-query";
import Fuse from "fuse.js";
import { NextPage } from "next";
import { useTheme } from "next-themes";
import Head from "next/head";
import { useSearchParams } from "next/navigation";
import { useRouter } from "next/router";
import React from "react";
const DocsIndexPage: NextPage = () => {
const { theme } = useTheme();
const router = useRouter();
const { data: docs, isLoading } = useQuery({
queryKey: ["docs"],
queryFn: async (): Promise<Docs> => {
const res = await fetch("/docs.json");
return res.json();
},
});
const params = useSearchParams();
const [name, setName] = React.useState("");
const [markdown, setMarkdown] = React.useState("");
React.useEffect(() => {
const _name = params.get("name");
setName(_name || "");
setMarkdown(docs?.docs.find((doc) => doc.name === _name)?.content || "");
}, [params, docs]);
const [filterValue, setFilterValue] = React.useState("");
const fuse = React.useMemo(() => {
return new Fuse(docs?.docs || [], {
keys: ["name"],
threshold: 0.3,
});
}, [docs]);
const visibleDocs = React.useMemo(() => {
if (filterValue) {
// Fuzzy match display names
const fuzzy = fuse.search(filterValue).map((r) => r.item);
return fuzzy;
}
return docs?.docs || [];
}, [docs, fuse, filterValue]);
const listboxClasses = React.useMemo(() => {
if (theme === Themes.DARK) {
return "p-0 gap-0 divide-y divide-default-300/50 dark:divide-default-100/80 bg-content1 overflow-visible shadow-small rounded-medium";
} else {
return "border p-0 gap-0 divide-y divide-default-300/50 dark:divide-default-100/80 bg-content1 overflow-visible shadow-small rounded-medium";
}
}, [theme]);
if (isLoading || !docs) {
return <div>Loading...</div>;
}
return (
<div className="grid grid-cols-12">
<Head>
<title>Sliver Docs: {name}</title>
</Head>
<div className="col-span-3 mt-4 ml-4 h-screen sticky top-20">
<div className="flex flex-row justify-center text-lg gap-2">
<Input
placeholder="Filter..."
startContent={<FontAwesomeIcon icon={faSearch} />}
value={filterValue}
onChange={(e) => setFilterValue(e.target.value)}
isClearable={true}
onClear={() => setFilterValue("")}
/>
</div>
<div className="mt-2">
<ScrollShadow>
<div className="max-h-[70vh]">
<Listbox
aria-label="Toolbox Menu"
className={listboxClasses}
itemClasses={{
base: "px-3 first:rounded-t-medium last:rounded-b-medium rounded-none gap-3 h-12 data-[hover=true]:bg-default-100/80",
}}
>
{visibleDocs.map((doc) => (
<ListboxItem
key={doc.name}
value={doc.name}
onClick={() => {
router.push({
pathname: "/docs",
query: { name: doc.name },
});
}}
>
{doc.name}
</ListboxItem>
))}
</Listbox>
</div>
</ScrollShadow>
</div>
</div>
<div className="col-span-9">
{name !== "" ? (
<Card className="mt-8 ml-8 mr-8 mb-8">
<CardHeader>
<span className="text-3xl">{name}</span>
</CardHeader>
<Divider />
<CardBody>
<MarkdownViewer
key={name || `${Math.random()}`}
markdown={markdown || ""}
/>
</CardBody>
</Card>
) : (
<div className="grid grid-cols-3">
<div className="col-span-1"></div>
<div className="col-span-1 mt-8 text-2xl text-center">
Welcome to the Sliver Wiki!
<div className="text-xl text-gray-500">
Please select a document
</div>
</div>
<div className="col-span-1"></div>
</div>
)}
</div>
</div>
);
};
export default DocsIndexPage;
Loaded 100 of 4798 files, more files were not shown because too many files have changed in this diff. Show more